[
  {
    "path": ".clang-format",
    "content": "Language: Cpp\nBasedOnStyle: LLVM\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlines: Left\nAlignOperands: true\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: true\nAllowShortFunctionsOnASingleLine: InlineOnly\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakTemplateDeclarations: Yes\nBinPackArguments: false\nBinPackParameters: false\nBreakBeforeBinaryOperators: NonAssignment\nBreakBeforeBraces: Custom\nBraceWrapping:\n  AfterClass: true\n  AfterControlStatement: true\n  AfterEnum: true\n  AfterFunction: true\n  AfterNamespace: true\n  AfterStruct: true\n  AfterUnion: true\n  BeforeCatch: true\n  BeforeElse: true\n  IndentBraces: true\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: false\nBreakInheritanceList: AfterColon\nColumnLimit: 0\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nConstructorInitializerIndentWidth: 2\nContinuationIndentWidth: 2\nCpp11BracedListStyle: true\nEmptyLineBeforeAccessModifier: Never\nIndentCaseLabels: false\nIndentPPDirectives: None\nIndentWidth: 2\nKeepEmptyLinesAtTheStartOfBlocks: false\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nPointerAlignment: Left\nReflowComments: true\nSortIncludes: false\nSpaceAfterCStyleCast: false\nSpaceAfterLogicalNot: false\nSpaceBeforeParens: Custom\nSpaceBeforeParensOptions:\n  AfterControlStatements: true\n  AfterFunctionDefinitionName: true\n  AfterFunctionDeclarationName: true\nSpacesInAngles: false\nSpacesInContainerLiterals: false\nSpacesInCStyleCastParentheses: false\nSpacesInSquareBrackets: false\nStandard: Latest\nTabWidth: 2\nUseTab: Never\n\n"
  },
  {
    "path": ".gitignore",
    "content": "*.whl\ndist\nbuild\n*.vol.gz\n*.vol\n*.ini\n__pycache__\n*.json\n*.zip\n.cache\n*.patch\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "stages:\n  - build\n  - test\n  - test_ngsolve\n  - deploy\n  - cleanup\n\npush_github:\n  stage: build\n  tags:\n    - linux\n    - docker\n    - bash\n  script:\n    - git remote add github git@github.com:NGSolve/netgen.git || true\n    - git remote update\n    - git checkout --track origin/master\n    - git pull origin master\n    - git push github master --tags\n  only:\n    - master\n\n############################################\n# Windows\n############################################\n.template_windows: &win\n  tags:\n    - windows\n    - pip\n  before_script:\n    - |\n        $ErrorActionPreference = \"Stop\"\n\n        # Import MSVC environment from vcvars64.bat into the current PowerShell process\n        $vcvars = '\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat\"'\n        cmd /c \"$vcvars && set\" |\n          ForEach-Object {\n            if ($_ -match '^(.*?)=(.*)$') {\n              [System.Environment]::SetEnvironmentVariable($matches[1], $matches[2])\n              Set-Item -Path \"env:$($matches[1])\" -Value $matches[2] -ErrorAction SilentlyContinue\n            }\n          }\n\n        $env:CI_DIR           = \"C:\\ci\\$env:CI_PIPELINE_ID\"\n        $env:CCACHE_BASEDIR   = $env:CI_DIR\n        $env:NETGEN_BUILD_DIR = Join-Path $env:CI_DIR \"build\"\n        $env:INSTALL_DIR      = Join-Path $env:CI_DIR \"install\"\n        $env:SRC_DIR          = Join-Path $env:CI_DIR \"src\"\n        $env:NETGENDIR        = Join-Path $env:INSTALL_DIR \"bin\"\n        $env:PYTHONPATH       = Join-Path $env:INSTALL_DIR \"lib\\site-packages\"\n\n        Write-Output $env:PATH\n        $env:PATH = @(\n          (Join-Path $env:INSTALL_DIR \"bin\")\n          \"C:\\python314\"\n          \"C:\\python314\\bin\"\n          \"C:\\python314\\Scripts\"\n          \"C:\\tools\"\n          $env:PATH\n        ) -join \";\"\n        Write-Output $env:PATH\n\n        $env:CCACHE_HARDLINK  = \"1\"\n        $env:CCACHE_NOHASHDIR = \"1\"\n\n        & \"C:\\tools\\ccache.exe\" -s\n        & \"C:\\tools\\ccache.exe\" -M \"20G\"\n\n        python.exe --version\n        cmake --version\n\nbuild_win:\n  <<: *win\n  stage: build\n  script:\n    - |\n        New-Item -ItemType Directory -Force -Path $env:SRC_DIR | Out-Null\n        Get-ChildItem -Force | Copy-Item -Destination $env:SRC_DIR -Recurse -Force\n\n        python.exe -m pip install -U netgen-occt netgen-occt-devel ninja cmake\n        Set-Location $env:SRC_DIR\n        git submodule update --init --recursive\n\n        if (Test-Path $env:NETGEN_BUILD_DIR) {\n          Remove-Item $env:NETGEN_BUILD_DIR -Recurse -Force\n        }\n\n        New-Item -ItemType Directory -Force -Path $env:NETGEN_BUILD_DIR | Out-Null\n        Set-Location $env:NETGEN_BUILD_DIR\n\n        cmake $env:SRC_DIR `\n          -G Ninja `\n          -DCMAKE_PREFIX=C:/python314 `\n          -DPython3_ROOT_DIR=C:/python314 `\n          -DCMAKE_INSTALL_PREFIX=\"$($env:INSTALL_DIR)\" `\n          -DCHECK_RANGE=ON `\n          -DUSE_CGNS=OFF `\n          -DUSE_OCC=ON `\n          -DUSE_CCACHE=ON `\n          -DENABLE_UNIT_TESTS=OFF `\n          -DCMAKE_BUILD_TYPE=Release\n\n        cmake --build . --target install --config Release\n\ntest_win:\n  <<: *win\n  stage: test\n  script:\n    - |\n        pip install pytest-check\n        Set-Location (Join-Path $env:NETGEN_BUILD_DIR \"netgen\")\n        ctest -C Release -V --output-on-failure\n        Set-Location ..\n  needs: [\"build_win\"]\n\ngenerate_results:\n  <<: *win\n  stage: test\n  script:\n    - |\n        pip install pytest-check\n        Set-Location \"tests\\pytest\"\n        python test_tutorials.py \"new_results.json\"\n  needs: [\"build_win\"]\n  when: manual\n  artifacts:\n    paths:\n      - tests/pytest/new_results.json\n    when: always\n    expire_in: 1 week\n\n\ncleanup_win:\n  <<: *win\n  stage: cleanup\n  script:\n    - |\n        Set-Location $env:CI_PROJECT_DIR\n        if (Test-Path $env:CI_DIR) {\n          Remove-Item $env:CI_DIR -Recurse -Force\n        }\n  when: always\n  allow_failure: true\n  needs: [\"test_win\"]\n\n############################################\n# Ubuntu/Linux\n############################################\n\n.template_ubuntu: &ubuntu\n  tags:\n    - linux\n    - bash\n  before_script:\n    - pwd\n    - ls\n    - docker info\n    - export PYTHONPATH=/opt/netgen/`python3 -c \"import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))\"`\n  variables:\n    UBUNTU_VERSION: \"22.04\"\n\nbuild_ubuntu_debug:\n  <<: *ubuntu\n  stage: build\n  script:\n    - docker build -t netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} -f tests/dockerfile .\n    - rm -f netgen_${CI_PIPELINE_ID}_$UBUNTU_VERSION.id\n    - >-\n      docker run\n      --cidfile netgen_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id\n      -e CCACHE_DIR=/ccache\n      -e PYTHONPATH=$PYTHONPATH\n      -v /mnt/ccache:/ccache\n      netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION}\n      bash /root/src/netgen/tests/build_debug.sh\n    - docker commit `cat netgen_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id` netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}\n    - rm netgen_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id\n\nbuild_ubuntu_mpi:\n  <<: *ubuntu\n  stage: build\n  script:\n    - docker build -t netgen_mpi_${CI_PIPELINE_ID}:${UBUNTU_VERSION} -f tests/dockerfile_mpi .\n    - rm -f netgen_mpi_${CI_PIPELINE_ID}_$UBUNTU_VERSION.id_mpi\n    - >-\n      docker run>-\n      --cidfile netgen_mpi_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id>-\n      -e CCACHE_DIR=/ccache\n      -e PYTHONPATH=$PYTHONPATH\n      -e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}\n      -v /mnt/ccache:/ccache\n      netgen_mpi_${CI_PIPELINE_ID}:${UBUNTU_VERSION}\n      bash /root/src/netgen/tests/build_mpi.sh\n    - docker commit `cat netgen_mpi_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id` netgen_mpi_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}\n    - rm netgen_mpi_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id\n\ntest_ubuntu_debug:\n  <<: *ubuntu\n  stage: test\n  script:\n    - >-\n      docker run\n      -e PYTHONPATH=$PYTHONPATH\n      netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}\n      bash -c 'cd /root/build/netgen && make test_netgen ARGS=\"-V --output-on-failure\"'\n  needs: [\"build_ubuntu_debug\"]\n\ntest_ubuntu_mpi:\n  <<: *ubuntu\n  stage: test\n  script:\n    - >-\n      docker run\n      -e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}\n      -e PYTHONPATH=$PYTHONPATH\n      netgen_mpi_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}\n      bash -c 'cd /root/build/netgen && make test_netgen ARGS=\"-V --output-on-failure\"'\n  needs: [\"build_ubuntu_mpi\"]\n\ntest_build_ngsolve:\n  <<: *ubuntu\n  allow_failure: true\n  stage: test_ngsolve\n  script:\n    - >-\n      docker run\n      -e NETGENDIR=/opt/netgen/bin\n      -e PYTHONPATH=$PYTHONPATH\n      -e MKLROOT=/opt/intel/mkl\n      -v /opt/intel:/opt/intel\n      -e CCACHE_DIR=/ccache\n      -v /mnt/ccache:/ccache\n      netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}\n      bash -c 'cd /root/src/netgen/tests/ && ./build_ngsolve.sh'\n\ncleanup_ubuntu:\n  stage: cleanup\n  tags:\n    - linux\n    - bash\n  script:\n    # remove intermediate and old docker images and containers\n    - docker rm -f `docker ps --no-trunc -aq`\n    - docker images --no-trunc -aqf \"dangling=true\" | xargs docker rmi -f || true\n    - docker rmi -f netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} || true\n    - docker rmi -f netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION} || true\n    - docker rmi -f netgen_mpi_${CI_PIPELINE_ID}:${UBUNTU_VERSION} || true\n    - docker rmi -f netgen_mpi_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION} || true\n  when: always\n  allow_failure: true\n\n\n############################################\n# MacOSX\n############################################\n\n.template_mac: &mac\n  tags:\n    - macosx\n    - m1\n  before_script:\n    - export PATH=/Library/Frameworks/Python.framework/Versions/3.14/bin:$PATH\n    - export ROOT_DIR=/tmp/$CI_PIPELINE_ID\n    - export SRC_DIR=$ROOT_DIR/src\n    - export BUILD_DIR=$ROOT_DIR/build\n    - export CMAKE_INSTALL_PREFIX=/tmp/$CI_PIPELINE_ID/install/Netgen.app\n    - export PYTHONPATH=$CMAKE_INSTALL_PREFIX/Contents/Resources/`python3 -c \"import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))\"`:.\n    - export PATH=$CMAKE_INSTALL_PREFIX/Contents/MacOS:$PATH\n\nbuild_mac:\n  <<: *mac\n  stage: build\n  script:\n    - python3 -m pip install -U netgen-occt netgen-occt-devel cmake pytest-check\n    - git submodule update --init --recursive\n    - rm -rf $BUILD_DIR\n    - mkdir -p $BUILD_DIR\n    - rm -rf $SRC_DIR\n    - mkdir -p $SRC_DIR\n    - cp -a . $SRC_DIR/\n    - cd $BUILD_DIR\n    - >-\n        cmake $SRC_DIR\n        -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX\n        -DCMAKE_BUILD_TYPE=Release\n        -DCHECK_RANGE=ON\n        -DUSE_NATIVE_ARCH=ON\n        -DUSE_CCACHE=ON\n        -DENABLE_UNIT_TESTS=ON\n        -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15\n        -DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk\n        -DUSE_CGNS=OFF\n        -DPython3_ROOT_DIR=/Library/Frameworks/Python.framework/Versions/3.14\n        -DUSE_OCC=ON\n    - make -j5 install\n\ntest_mac:\n  <<: *mac\n  stage: test\n  script:\n    - cd $BUILD_DIR/netgen\n    - ctest . -V --output-on-failure\n  needs: [\"build_mac\"]\n\ncleanup_mac:\n  <<: *mac\n  stage: cleanup\n  script:\n    - rm -rf $ROOT_DIR\n  when: always\n  allow_failure: true\n  needs: [\"test_mac\"]\n\npip_linux:\n  image: quay.io/pypa/manylinux_2_28_x86_64\n  stage: build\n  tags:\n    - pip\n    - linux\n    - docker\n  script:\n    - ./tests/build_pip.sh\n  when: manual\n\npip_windows:\n  stage: build\n  tags:\n    - pip\n    - windows\n  script:\n    - .\\tests\\build_pip.ps1 C:\\Python314\n    - .\\tests\\build_pip.ps1 C:\\Python313\n    - .\\tests\\build_pip.ps1 C:\\Python312\n    - .\\tests\\build_pip.ps1 C:\\Python311\n    - .\\tests\\build_pip.ps1 C:\\Python310\n  when: manual\n\npip_macos:\n  stage: build\n  tags:\n    - pip\n    - macosx\n    - m1\n  script:\n    - ./tests/build_pip_mac.sh 3.14\n    - ./tests/build_pip_mac.sh 3.13\n    - ./tests/build_pip_mac.sh 3.12\n    - ./tests/build_pip_mac.sh 3.11\n    - ./tests/build_pip_mac.sh 3.10\n  when: manual\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"external_dependencies/pybind11\"]\n\tpath = external_dependencies/pybind11\n\turl = https://github.com/ngsolve/pybind11.git\n"
  },
  {
    "path": "AUTHORS",
    "content": "Joachim Schoeberl <joachim.schoeberl@tuwien.ac.at>\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "if(NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE \"RelWithDebInfo\" CACHE STRING INTERNAL)\nendif(NOT CMAKE_BUILD_TYPE)\n\nset(CMAKE_MSVC_RUNTIME_LIBRARY \"MultiThreadedDLL\")\n\ncmake_minimum_required(VERSION 3.16)\ncmake_policy(VERSION 3.16)\n\nif(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.24.0\")\n  cmake_policy(SET CMP0135 NEW)\nendif()\n\ninclude (CMakeDependentOption)\noption( USE_NATIVE_ARCH  \"build for native cpu architecture\" ON)\n\noption( USE_GUI     \"build with GUI\" ON )\noption( USE_PYTHON  \"build with python interface\" ON )\ncmake_dependent_option( PREFER_SYSTEM_PYBIND11  \"Use system wide PyBind11\" OFF \"USE_PYTHON\" OFF)\noption( USE_MPI     \"enable mpi parallelization\" OFF )\noption( USE_MPI_WRAPPER \"enable mpi wrapper (run-time dispatch of MPI library calls)\" OFF )\noption( USE_OCC     \"build with OpenCascade geometry kernel interface\" ON)\noption( USE_STLGEOM     \"build with STL geometry support\" ON)\noption( USE_CSG     \"build with CSG kernel\" ON)\noption( USE_INTERFACE     \"build nginterface\" ON)\noption( USE_GEOM2D     \"build 2d geometry kernels\" ON)\noption( USE_JPEG    \"enable snapshots using library libjpeg\" OFF )\noption( USE_MPEG    \"enable video recording with FFmpeg, uses libavcodec\" OFF )\noption( USE_CGNS    \"enable CGNS file read/write support\" OFF )\noption( USE_NUMA         \"compile with NUMA-aware code\")\noption( INTEL_MIC        \"cross compile for intel xeon phi\")\noption( INSTALL_PROFILES \"install environment variable settings to /etc/profile.d\" OFF )\noption( USE_CCACHE       \"use ccache\")\noption( USE_INTERNAL_TCL \"Compile tcl files into the code and don't install them\" ON)\noption( ENABLE_UNIT_TESTS \"Enable Catch unit tests\")\noption( ENABLE_CPP_CORE_GUIDELINES_CHECK \"Enable cpp core guideline checks on ngcore\" OFF)\noption( DEBUG_LOG \"Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON\" OFF)\noption( CHECK_RANGE \"Check array range access, automatically enabled if built in debug mode\" OFF)\noption( BUILD_STUB_FILES \"Build stub files for better autocompletion\" ON)\noption( BUILD_FOR_CONDA \"Link python libraries only to executables\" OFF)\n\noption( USE_SUPERBUILD       \"build dependencies automatically\" ON)\noption( TRACE_MEMORY     \"Enable memory tracing\" OFF)\n\nset(NG_COMPILE_FLAGS \"\" CACHE STRING \"Additional compile flags\")\n\nset(NGLIB_LIBRARY_TYPE SHARED CACHE STRING \"nglib library type\")\nset(NGCORE_LIBRARY_TYPE SHARED CACHE STRING \"ngcore library type\")\nset(NGGUI_LIBRARY_TYPE SHARED CACHE STRING \"nggui library type\")\n\nset(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\" \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_modules\")\n\nif(APPLE)\n  set(INSTALL_DIR_DEFAULT /Applications/Netgen.app)\nelse(APPLE)\n  if(WIN32)\n    set(INSTALL_DIR_DEFAULT \"C:/netgen\")\n  else(WIN32)\n    set(INSTALL_DIR_DEFAULT /opt/netgen)\n  endif(WIN32)\nendif(APPLE)\n\nif(INSTALL_DIR)\n  message(WARNING \"INSTALL_DIR is deprecated, use CMAKE_INSTALL_PREFIX instead\")\n  set(INSTALL_DIR_DEFAULT ${INSTALL_DIR})\nendif(INSTALL_DIR)\n\nif(UNIX AND USE_SUPERBUILD)\n  message(\"Checking for write permissions in install directory...\")\n  execute_process(COMMAND mkdir -p ${CMAKE_INSTALL_PREFIX})\n  execute_process(COMMAND test -w ${CMAKE_INSTALL_PREFIX} RESULT_VARIABLE res)\n  if(res)\n    message(WARNING \"No write access at install directory, please set correct permissions\")\n  endif()\nendif(UNIX AND USE_SUPERBUILD)\n\nif (USE_SUPERBUILD)\n  project (SUPERBUILD)\nelse()\n  project(Netgen)\nendif()\n\nif (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)\n  set(CMAKE_INSTALL_PREFIX \"${INSTALL_DIR_DEFAULT}\" CACHE PATH \"Install directory\" FORCE)\nendif()\n\nset(NG_INSTALL_SUFFIX netgen CACHE STRING \"Suffix appended to install directories (project name)\")\n\nif(USE_PYTHON)\n  if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)\n      find_package(Python3 REQUIRED COMPONENTS Development.Module)\n      if(NOT EMSCRIPTEN)\n          find_package(Python3 COMPONENTS Interpreter Development.Embed)\n      endif()\n  else()\n    find_package(Python3 REQUIRED COMPONENTS Interpreter Development)\n  endif()\n\n  if(NOT CMAKE_CROSSCOMPILING)\n      find_package(Python3 REQUIRED COMPONENTS Interpreter)\n      execute_process(COMMAND ${Python3_EXECUTABLE} -c \"import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))\" OUTPUT_VARIABLE PYTHON_PACKAGES_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)\n      file(TO_CMAKE_PATH ${PYTHON_PACKAGES_INSTALL_DIR} PYTHON_PACKAGES_INSTALL_DIR)\n  endif(NOT CMAKE_CROSSCOMPILING)\nendif(USE_PYTHON)\n\nif(APPLE AND NOT EMSCRIPTEN)\n  set(NG_INSTALL_DIR_BIN_DEFAULT Contents/MacOS)\n  set(NG_INSTALL_DIR_LIB_DEFAULT Contents/MacOS)\n  set(NG_INSTALL_DIR_CMAKE_DEFAULT Contents/Resources/CMake)\n  set(NG_INSTALL_DIR_PYTHON_DEFAULT Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR})\n  set(NG_INSTALL_DIR_RES_DEFAULT Contents/Resources/share)\n  set(NG_INSTALL_DIR_INCLUDE_DEFAULT Contents/Resources/include)\n\n  set(NG_RPATH_TOKEN \"@loader_path\")\nelse(APPLE AND NOT EMSCRIPTEN)\n  set(NG_INSTALL_DIR_BIN_DEFAULT bin)\n  set(NG_INSTALL_DIR_LIB_DEFAULT lib)\n  if(WIN32)\n    set(NG_INSTALL_DIR_CMAKE_DEFAULT cmake)\n  else(WIN32)\n    set(NG_INSTALL_DIR_CMAKE_DEFAULT lib/cmake/${NG_INSTALL_SUFFIX})\n  endif(WIN32)\n  set(NG_INSTALL_DIR_PYTHON_DEFAULT ${PYTHON_PACKAGES_INSTALL_DIR})\n  set(NG_INSTALL_DIR_RES_DEFAULT share)\n  set(NG_INSTALL_DIR_INCLUDE_DEFAULT include)\n\n  set(NG_RPATH_TOKEN \"\\$ORIGIN\")\nendif(APPLE AND NOT EMSCRIPTEN)\n\nset(NG_INSTALL_DIR_PYTHON ${NG_INSTALL_DIR_PYTHON_DEFAULT} CACHE STRING \"Install directory for Python files\")\nset(NG_INSTALL_DIR_BIN ${NG_INSTALL_DIR_BIN_DEFAULT} CACHE STRING \"Install directory for executables\")\nset(NG_INSTALL_DIR_LIB ${NG_INSTALL_DIR_LIB_DEFAULT} CACHE STRING \"Install directory for libraries\")\nset(NG_INSTALL_DIR_INCLUDE ${NG_INSTALL_DIR_INCLUDE_DEFAULT} CACHE STRING \"Install directory for header files\")\nset(NG_INSTALL_DIR_CMAKE ${NG_INSTALL_DIR_CMAKE_DEFAULT} CACHE STRING \"Install directory for CMake files\")\nset(NG_INSTALL_DIR_RES ${NG_INSTALL_DIR_RES_DEFAULT} CACHE STRING \"Install directory for resources\")\n\nget_filename_component(NETGEN_CMAKE_DIR_ABSOLUTE ${NG_INSTALL_DIR_CMAKE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\nget_filename_component(NETGEN_BINARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_BIN} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\nget_filename_component(NETGEN_LIBRARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_LIB} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\nget_filename_component(NETGEN_INCLUDE_DIR_ABSOLUTE ${NG_INSTALL_DIR_INCLUDE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\nget_filename_component(NETGEN_RESOURCE_DIR_ABSOLUTE ${NG_INSTALL_DIR_RES} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\n\nfile(RELATIVE_PATH NETGEN_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${CMAKE_INSTALL_PREFIX})\nfile(RELATIVE_PATH NETGEN_BINARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})\nfile(RELATIVE_PATH NETGEN_LIBRARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})\nfile(RELATIVE_PATH NETGEN_INCLUDE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_INCLUDE_DIR_ABSOLUTE})\nfile(RELATIVE_PATH NETGEN_RESOURCE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_RESOURCE_DIR_ABSOLUTE})\n\nfile(RELATIVE_PATH NETGEN_RPATH ${NETGEN_BINARY_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})\n\nif (USE_SUPERBUILD)\n  # execute the superbuild (this script will be invoked again without the\n  # USE_SUPERBUILD option this time)\n  include (cmake/SuperBuild.cmake)\n  return()                      # stop processing this file further\nendif()\n\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\ninclude (${CMAKE_CURRENT_LIST_DIR}/cmake/generate_version_file.cmake)\nset(CPACK_PACKAGE_VERSION \"${NETGEN_VERSION}\")\n\n\n#######################################################################\nif(USE_CCACHE)\n  find_program(CCACHE_FOUND NAMES ccache ccache.bat)\n  if(CCACHE_FOUND)\n    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})\n    message(STATUS \"Using ccache ${CCACHE_FOUND}\")\n  endif(CCACHE_FOUND)\nendif(USE_CCACHE)\n\n#######################################################################\nif(INTEL_MIC)\n    set(MKL_ARCH \"mic\")\n    include(cmake/mic.cmake)\nelse(INTEL_MIC)\n    set(MKL_ARCH \"intel64\")\nendif(INTEL_MIC)\n\n#######################################################################\n# Append install paths of software in non-standard paths (e.g. openmpi, metis, intel mkl, ...)\n# cmake -DUSE_MPI=ON -DCMAKE_PREFIX_PATH=\"/opt/openmpi165;/opt/metis51\" ../\nset(ADDITIONAL_PATHS \"\" CACHE PATH \"List of paths to additional libraries in non-standard locations, separated by ';'\")\nif (ADDITIONAL_PATHS)\n  set(CMAKE_PREFIX_PATH ${ADDITIONAL_PATHS})\nendif (ADDITIONAL_PATHS)\n\n#######################################################################\n# build options\ninclude_directories (\"${PROJECT_SOURCE_DIR}/include\")\ninclude_directories (\"${PROJECT_SOURCE_DIR}/libsrc\")\ninclude_directories (\"${PROJECT_SOURCE_DIR}/libsrc/include\")\ninclude_directories (\"${PROJECT_BINARY_DIR}\")\n\nset(CMAKE_INCLUDE_CURRENT_DIR ON)\n\nif(USE_PYTHON)\n    get_filename_component(NETGEN_PYTHON_DIR_ABSOLUTE ${NG_INSTALL_DIR_PYTHON} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})\n    file(RELATIVE_PATH NETGEN_PYTHON_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_PYTHON_DIR_ABSOLUTE})\n    file(RELATIVE_PATH NETGEN_PYTHON_RPATH_BIN ${NETGEN_PYTHON_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})\n    file(RELATIVE_PATH NETGEN_PYTHON_RPATH ${NETGEN_PYTHON_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})\n    if(WIN32)\n        set(NETGEN_PYTHON_RPATH ${NETGEN_PYTHON_RPATH_BIN})\n    endif(WIN32)\nendif(USE_PYTHON)\n\nset(NG_INSTALL_DIR EXPORT netgen-targets RUNTIME DESTINATION ${NG_INSTALL_DIR_BIN} COMPONENT netgen LIBRARY DESTINATION ${NG_INSTALL_DIR_LIB} COMPONENT netgen_devel ARCHIVE DESTINATION ${NG_INSTALL_DIR_LIB} COMPONENT netgen_devel)\ninstall(EXPORT netgen-targets DESTINATION ${NG_INSTALL_DIR_CMAKE} COMPONENT netgen_devel)\n\nset(CMAKE_MACOSX_RPATH TRUE)\nset(CMAKE_INSTALL_RPATH \"${NG_RPATH_TOKEN};${NG_RPATH_TOKEN}/${NETGEN_RPATH}\")\nif(BUILD_FOR_CONDA)\n    file(RELATIVE_PATH py_rpath \"/bin\" \"/${NG_INSTALL_DIR_LIB}\")\n    set(CMAKE_INSTALL_RPATH \"${CMAKE_INSTALL_RPATH};${py_rpath}\")\nendif(BUILD_FOR_CONDA)\n\ninclude (CheckIncludeFiles)\ncheck_include_files (dlfcn.h HAVE_DLFCN_H)\nif(HAVE_DLFCN_H)\n  add_definitions(-DHAVE_DLFCN_H)\nendif()\n\ninclude_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})\n\n#######################################################################\n# platform specific definitions and flags\nmacro(get_WIN32_WINNT version)\n    if (WIN32 AND CMAKE_SYSTEM_VERSION)\n        if(\"${CMAKE_SYSTEM_VERSION}\" MATCHES \"^([0-9]+)\\\\.([0-9]+)\")\n            math(EXPR ver \"${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}\")\n        endif()\n        set(${version} \"0x${ver}\")\n    endif()\nendmacro()\n\nmacro(get_dll_from_lib dll_path lib_path)\n        get_filename_component(parent_lib_path ${lib} DIRECTORY)\n        get_filename_component(lib_name ${lib} name)\nendmacro()\n\nset(CMAKE_CXX_VISIBILITY_PRESET hidden)\nset(CMAKE_CXX_STANDARD 17)\nif(WIN32)\n    set(CMAKE_MFC_FLAG 0)\nendif(WIN32)\nif(APPLE)\n    set(CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup\")\nendif(APPLE)\n\n#######################################################################\nadd_library(nglib ${NGLIB_LIBRARY_TYPE})\nif(USE_GUI)\n    add_library(nggui ${NGGUI_LIBRARY_TYPE})\n    if(WIN32)\n        set_target_properties( nggui PROPERTIES OUTPUT_NAME \"libnggui\")\n    endif(WIN32)\nendif(USE_GUI)\n\n#######################################################################\nif(NOT ZLIB_INCLUDE_DIRS)\n  find_package(ZLIB REQUIRED)\nendif(NOT ZLIB_INCLUDE_DIRS)\ntarget_include_directories(nglib PRIVATE ${ZLIB_INCLUDE_DIRS})\nif(USE_GUI)\n    target_include_directories(nggui PRIVATE ${ZLIB_INCLUDE_DIRS})\nendif(USE_GUI)\n\n#######################################################################\nif(WIN32)\n    add_library(netgen_gui INTERFACE IMPORTED)\nelse()\n    add_library(netgen_gui INTERFACE)\nendif()\n\nif (USE_GUI)\n    find_package(TCL 8.5 REQUIRED)\n    find_package(TclStub 8.5 REQUIRED)\n    find_package(Threads REQUIRED)\n    if(APPLE)\n          set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} -framework AppKit\")\n          target_link_libraries(netgen_gui INTERFACE \"-framework AppKit\")\n    else(APPLE)\n          find_package(X11 REQUIRED) \n          target_link_libraries( netgen_gui INTERFACE ${X11_Xmu_LIB} ${X11_X11_LIB})\n    endif(APPLE)\n    find_package(OpenGL REQUIRED)\n\n    target_compile_definitions(netgen_gui INTERFACE -DTCL -DOPENGL -DUSE_TOGL_2 -DUSE_TCL_STUBS -DUSE_TK_STUBS)\n    target_include_directories(netgen_gui INTERFACE ${TCL_INCLUDE_PATH} ${TK_INCLUDE_PATH})\n    target_link_libraries(netgen_gui INTERFACE ${TCL_STUB_LIBRARY} ${TK_STUB_LIBRARY})\n    if(NOT EXISTS ${TK_INCLUDE_PATH}/tkWin.h AND EXISTS ${TK_INCLUDE_PATH}/../win/tkWin.h)\n       target_include_directories(netgen_gui INTERFACE ${TK_INCLUDE_PATH}/../win)\n    endif()\n    if(NOT EXISTS ${TK_INCLUDE_PATH}/x11/Xlib.h AND EXISTS ${TK_INCLUDE_PATH}/../xlib/X11/Xlib.h)\n       target_include_directories(netgen_gui INTERFACE ${TK_INCLUDE_PATH}/../xlib)\n    endif()\n\n    target_link_libraries(nggui PUBLIC nglib togl PRIVATE \"$<BUILD_INTERFACE:netgen_python>\" )\n\n    if(WIN32)\n      target_compile_definitions(netgen_gui INTERFACE -DTOGL_WGL)\n    endif()\n    if(APPLE)\n      target_compile_definitions(netgen_gui INTERFACE -DTOGL_NSOPENGL)\n    endif()\n    if(UNIX AND NOT APPLE)\n      target_compile_definitions(netgen_gui INTERFACE -DTOGL_X11)\n    endif()\n\nendif (USE_GUI)\n\n#######################################################################\nif(WIN32)\n    add_library(netgen_python INTERFACE IMPORTED)\nelse()\n    add_library(netgen_python INTERFACE)\nendif()\n\nif (USE_PYTHON)\n    if (PREFER_SYSTEM_PYBIND11)\n      set(NG_INSTALL_PYBIND OFF)\n      find_package(pybind11 CONFIG REQUIRED)\n    else()\n      add_subdirectory(external_dependencies/pybind11)\n    endif()\n\n    target_compile_definitions(netgen_python INTERFACE NG_PYTHON NETGEN_PYTHON)\n    target_include_directories(netgen_python INTERFACE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})\n    target_include_directories(nglib PRIVATE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})\n    if(Python3_LIBRARIES AND (WIN32 OR NOT BUILD_FOR_CONDA))\n        target_link_libraries(netgen_python INTERFACE ${Python3_LIBRARIES})\n    endif()\n\n    if(NG_INSTALL_PYBIND)\n      install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)\n      install(FILES ${pybind11_INCLUDE_DIR}/../LICENSE DESTINATION ${NG_INSTALL_DIR_INCLUDE}/pybind11 COMPONENT netgen_devel)\n    endif(NG_INSTALL_PYBIND)\nendif (USE_PYTHON)\n\n#######################################################################\nadd_library(netgen_metis INTERFACE)\nif (USE_MPI)\n    set(MPI_DETERMINE_LIBRARY_VERSION TRUE)\n    find_package(MPI)\n\n    find_package(METIS REQUIRED)\n    target_include_directories(netgen_metis INTERFACE ${METIS_INCLUDE_DIR})\n    target_link_libraries(netgen_metis INTERFACE ${METIS_LIBRARY} )\n    target_compile_definitions(netgen_metis INTERFACE METIS )\nendif (USE_MPI)\n\n#######################################################################\nadd_library(occ_libs INTERFACE IMPORTED)\nif (USE_OCC)\n    find_package(OpenCascade NAMES OpenCASCADE opencascade REQUIRED CMAKE_FIND_ROOT_PATH_BOTH)\n    add_definitions(-DOCCGEOMETRY)\n    set(OCC_LIBRARIES\n      TKBO\n      TKBRep\n      TKBool\n      TKCAF\n      TKCDF\n      TKFillet\n      TKG2d\n      TKG3d\n      TKGeomAlgo\n      TKGeomBase\n      TKHLR\n      TKLCAF\n      TKMath\n      TKMesh\n      TKOffset\n      TKPrim\n      TKService\n      TKShHealing\n      TKTopAlgo\n      TKV3d\n      TKVCAF\n      TKXCAF\n      TKXSBase\n      TKernel\n    )\n    if(${OpenCASCADE_MAJOR_VERSION}.${OpenCASCADE_MINOR_VERSION} VERSION_GREATER_EQUAL 7.8)\n      list(APPEND OCC_LIBRARIES TKDEIGES TKDESTEP TKDESTL)\n    else()\n      list(APPEND OCC_LIBRARIES\n        TKIGES\n        TKSTEP\n        TKSTL\n        TKXDEIGES\n        TKXDESTEP\n        TKSTEP209\n        TKSTEPAttr\n        TKSTEPBase\n        )\n    endif()\n    if(UNIX AND NOT APPLE)\n      list(PREPEND OCC_LIBRARIES -Wl,--start-group)\n      list(APPEND OCC_LIBRARIES -Wl,--end-group)\n    endif()\n\n    target_link_libraries(occ_libs INTERFACE ${OCC_LIBRARIES})\n    get_target_property(occ_include_dir TKernel INTERFACE_INCLUDE_DIRECTORIES)\n    if(NOT occ_include_dir)\n      set(occ_include_dir ${OpenCASCADE_INCLUDE_DIR})\n    endif()\n    target_include_directories(occ_libs INTERFACE ${occ_include_dir})\n    message(STATUS \"OpenCasCade include dirs: ${occ_include_dir}\")\n    if(NOT OpenCASCADE_BUILD_SHARED_LIBS)\n      if(OpenCASCADE_WITH_FREETYPE)\n        find_library( FREETYPE NAMES freetype HINTS ${OpenCASCADE_LIBRARY_DIR})\n        list(APPEND OCC_LIBRARIES ${FREETYPE})\n        target_link_libraries(occ_libs INTERFACE ${FREETYPE})\n        if(UNIX AND NOT APPLE)\n          find_package(Fontconfig REQUIRED)\n          target_link_libraries(occ_libs INTERFACE ${Fontconfig_LIBRARIES})\n        endif()\n      endif(OpenCASCADE_WITH_FREETYPE)\n      set(THREADS_PREFER_PTHREAD_FLAG ON)\n      find_package(Threads REQUIRED)\n      target_link_libraries(occ_libs INTERFACE Threads::Threads)\n    endif()\n    if(WIN32 AND USE_GUI)\n      target_link_libraries(nggui PRIVATE Ws2_32.lib)\n    endif(WIN32 AND USE_GUI)\n    if(USE_GUI)\n      target_link_libraries(nggui PRIVATE occ_libs)\n    endif(USE_GUI)\nendif (USE_OCC)\n\n#######################################################################\nif (USE_JPEG)\n    find_package(JPEG REQUIRED)\n    add_definitions(-DJPEGLIB)\n    include_directories(${JPEG_INCLUDE_DIR})\nendif (USE_JPEG)\n\n#######################################################################\nif (USE_MPEG)\n    find_package(FFMPEG REQUIRED)\n    add_definitions(-DFFMPEG -D__STDC_CONSTANT_MACROS)\n    include_directories(${FFMPEG_INCLUDE_DIR})\nendif (USE_MPEG)\n\n#######################################################################\nadd_custom_target(ng_generate_version_file\n  ${CMAKE_COMMAND}\n    -DBDIR=${CMAKE_CURRENT_BINARY_DIR}\n    -P ${CMAKE_CURRENT_LIST_DIR}/cmake/generate_version_file.cmake\n    )\n#######################################################################\nif(INSTALL_PROFILES)\n    file(WRITE  ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh \"#!/bin/sh\\n\")\n    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh \"export PATH=${CMAKE_INSTALL_PREFIX}/bin:$PATH\\n\")\n    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh \"export NETGENDIR=${CMAKE_INSTALL_PREFIX}/bin\\n\")\n    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh \"export PYTHONPATH=${CMAKE_INSTALL_PREFIX}/${PYTHON_PACKAGES_INSTALL_DIR}:.\\n\")\n    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh \"export LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib:.\\n\")\n    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/netgen.sh DESTINATION /etc/profile.d COMPONENT netgen)\n\n    string(ASCII 27 Esc)\n    file(WRITE  ${CMAKE_CURRENT_BINARY_DIR}/postinst \"#!/bin/sh\\n\")\n    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/postinst \"echo \\\"${Esc}[0;31mPlease log out and in again or do 'source /etc/profile.d/netgen.sh' to load the correct environment variables!${Esc}[m\\\"\")\n    set( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA \"${CMAKE_CURRENT_BINARY_DIR}/postinst\")\nendif(INSTALL_PROFILES)\n\n#######################################################################\nfile(WRITE ${CMAKE_CURRENT_BINARY_DIR}/fixup.cmake \"\\\ninclude(${CMAKE_CURRENT_SOURCE_DIR}/cmake/netgen_fixup.cmake)\nset(APP ${CMAKE_INSTALL_PREFIX})\nmessage(\\${APP})\nset(BU_CHMOD_BUNDLE_ITEMS ON)\n\nfile(GLOB libs ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}/*.dylib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}/*.so)\nmessage(\\\"\\${libs}\\\")\nnetgen_fixup_bundle( \\${APP}/Contents/MacOS/netgen \\\"\\${libs}\\\" ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB} )\nexecute_process(COMMAND ln -s /Applications ${CMAKE_INSTALL_PREFIX}/../Applications)\nset (bundle_filename \\$ENV{NETGEN_BUNDLE_NAME})\nif(NOT bundle_filename)\n  set(bundle_filename netgen)\nendif(NOT bundle_filename)\nexecute_process(COMMAND hdiutil create -volname Netgen -srcfolder ${CMAKE_INSTALL_PREFIX} -ov -format UDZO \\${bundle_filename}-${PACKAGE_VERSION}.dmg)\n\")\n  add_custom_target(bundle COMMAND ${CMAKE_COMMAND} \"-P\" \"${CMAKE_CURRENT_BINARY_DIR}/fixup.cmake\")\n#######################################################################\n# CTest\nenable_testing()\ninclude(CTest)\n\nif(ENABLE_UNIT_TESTS)\n  include(${CMAKE_CURRENT_LIST_DIR}/cmake/external_projects/catch.cmake)\nendif(ENABLE_UNIT_TESTS)\n\n\n#######################################################################\n\nif(USE_SPDLOG)\n  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/external_projects/spdlog.cmake)\n  include_directories(${SPDLOG_INCLUDE_DIR})\nendif(USE_SPDLOG)\n\nif(ENABLE_CPP_CORE_GUIDELINES_CHECK)\n  find_program(\n    CLANG_TIDY_EXE\n    NAMES \"clang-tidy\"\n    DOC \"Path to clang-tidy executable\"\n    )\n  if(NOT CLANG_TIDY_EXE)\n    message(WARNING \"clang-tidy not found.\")\n  else()\n    message(STATUS \"clang-tidy found: ${CLANG_TIDY_EXE}\")\n    set(DO_CLANG_TIDY \"${CLANG_TIDY_EXE}\" \"-header-filter=libsrc/core/\")\n  endif()\nendif(ENABLE_CPP_CORE_GUIDELINES_CHECK)\n\nadd_library(netgen_cgns INTERFACE)\nif(USE_CGNS)\n    find_library( CGNS_LIBRARY NAMES cgns cgnsdll )\n    find_path( CGNS_INCLUDE_DIR cgnslib.h )\n    target_compile_definitions(netgen_cgns INTERFACE NG_CGNS)\n    target_include_directories(netgen_cgns INTERFACE ${CGNS_INCLUDE_DIR})\n    target_link_libraries(netgen_cgns INTERFACE ${CGNS_LIBRARY})\n    if(NOT WIN32 AND NOT APPLE) # hdf5 is statically linked into cgns in Windows amd MacOS binaries\n        find_library(HDF5_LIBRARY NAMES hdf5 hdf5_serial)\n        target_link_libraries(netgen_cgns INTERFACE ${HDF5_LIBRARY})\n    endif(NOT WIN32 AND NOT APPLE)\nendif(USE_CGNS)\n\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/netgen_version.hpp ${CMAKE_CURRENT_BINARY_DIR}/netgen_config.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/include COMPONENT netgen_devel)\n\n# include instead of add_subdirectory to recognize the generated source files properly\ninclude(rules/CMakeLists.txt)\n\nadd_subdirectory(windows)\nadd_subdirectory(libsrc)\nadd_subdirectory(ng)\nadd_subdirectory(tutorials)\nadd_subdirectory(py_tutorials)\nadd_subdirectory(doc)\nadd_subdirectory(nglib)\nadd_subdirectory(tests)\n\n#######################################################################\nif(USE_NATIVE_ARCH)\n    if(WIN32)\n        include(CheckCXXSourceRuns)\n        check_cxx_source_runs(\"\n                #include <immintrin.h>\n                int main()\n                {\n                    __m256d a{1.,2.,3.,4.};\n                    __m256d b{2.,0.,3.,5.};\n                    __m256d c = _mm256_mul_pd(a,b);\n                    return 0;\n                } \" NG_HAVE_AVX)\n        check_cxx_source_runs(\"\n                #include <immintrin.h>\n                int main()\n                {\n                    __m256i a{1,2,3,4};\n                    __m256i b{2,0,3,5};\n                    __m256i c = _mm256_cmpgt_epi64 (a,b);\n                    return 0;\n                } \" NG_HAVE_AVX2)\n        check_cxx_source_runs(\"\n                #include <immintrin.h>\n                int main()\n                {\n                    __m512d a{1.,2.,3.,4.};\n                    __m512d b{5.,6.,7.,8.};\n                    __m512d c = _mm512_mul_pd(a,b);\n                    return 0;\n                } \" NG_HAVE_AVX512)\n\n        if(NG_HAVE_AVX512)\n            target_compile_options(ngcore PUBLIC \"/arch:AVX512\")\n            message(STATUS \"Build for AVX512 CPU\")\n        elseif(NG_HAVE_AVX2)\n            target_compile_options(ngcore PUBLIC \"/arch:AVX2\")\n            message(STATUS \"Build for AVX2 CPU\")\n        elseif(NG_HAVE_AVX)\n            target_compile_options(ngcore PUBLIC \"/arch:AVX\")\n            message(STATUS \"Build for AVX CPU\")\n        else()\n            message(STATUS \"Build for generic CPU\")\n        endif()\n    elseif(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL \"arm64\")\n\t# no flag necessary/available on Apple M1\n    else()\n        target_compile_options(ngcore PUBLIC \"-march=native\")\n    endif(WIN32)\n    if(APPLE)\n        # work-around for bug in Xcode 11.3: https://forums.developer.apple.com/thread/121887\n        target_compile_options(ngcore PUBLIC \"-fno-stack-check\")\n    endif(APPLE)\nendif(USE_NATIVE_ARCH)\n\nif (USE_PYTHON)\n  add_subdirectory(python)\nendif (USE_PYTHON)\n\n#######################################################################\n# Debian packager\n\nif(UNIX)\n    set(CPACK_SOURCE_GENERATOR \"TGZ\")\n    set(CPACK_SOURCE_IGNORE_FILES \"/cmake/;/build/;/.gz/;~$;${CPACK_SOURCE_IGNORE_FILES}\")\n    set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION} )\n\n    set(CPACK_PACKAGE_NAME netgen)\n    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"automatic 3d tetrahedral mesh generator\")\n    set(CPACK_PACKAGE_DESCRIPTION \"NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STL file format. The connection to a geometry kernel allows the handling of IGES and STEP files. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Netgen is open source based on the LGPL license. It is available for Unix/Linux and Windows.\")\n\n    set(CPACK_PACKAGING_INSTALL_PREFIX \"/opt/netgen\")\n    execute_process(COMMAND grep CODENAME /etc/lsb-release OUTPUT_VARIABLE temp OUTPUT_STRIP_TRAILING_WHITESPACE)\n    execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)\n    if(temp)\n        set(CPACK_GENERATOR \"DEB\")\n        string(SUBSTRING ${temp} 17 -1 UBUNTU_VERSION)\n        message(\"ubuntu version: ${UBUNTU_VERSION}\")\n\n        set(CPACK_DEBIAN_PACKAGE_DEPENDS \"python3, libtk8.5, libtcl8.5, tix, libxmu6\")\n        execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)\n        set(CPACK_DEBIAN_PACKAGE_MAINTAINER \"Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>\")\n        if(USE_MPI)\n            set(CPACK_DEBIAN_PACKAGE_DEPENDS \"${CPACK_DEBIAN_PACKAGE_DEPENDS}, libmetis5, openmpi-bin\")\n            set(CPACK_PACKAGE_NAME \"${CPACK_PACKAGE_NAME}_mpi\")\n        endif(USE_MPI)\n        if(USE_OCC)\n            set(CPACK_DEBIAN_PACKAGE_DEPENDS \"${CPACK_DEBIAN_PACKAGE_DEPENDS}, liboce-ocaf-dev\")\n        endif(USE_OCC)\n        set(CPACK_DEBIAN_PACKAGE_SECTION Science)\n        set(CPACK_DEBIAN_PACKAGE_NAME ${CPACK_PACKAGE_NAME})\n        set(CPACK_PACKAGE_FILE_NAME \"netgen-${PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}\")   \n    endif(temp)\nendif(UNIX)\n\nif(USE_PYTHON AND NOT SKBUILD)\n  # install egg file to let python/pip know that Netgen ist installed\n  file( WRITE \"netgen_mesher-py3.egg-info\"\n\"Metadata-Version: 2.1\nName: netgen-mesher\nVersion: ${NETGEN_VERSION_MAJOR}.${NETGEN_VERSION_MINOR}.${NETGEN_VERSION_PATCH}.post${NETGEN_VERSION_TWEAK}\n\")\n  install(FILES netgen_mesher-py3.egg-info DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)\nendif()\n\nif(APPLE AND NOT SKBUILD)\n    # create some auxiliary files\n    set(mac_startup ${CMAKE_CURRENT_BINARY_DIR}/startup.sh)\n    file(WRITE ${mac_startup} \"\\\n#!/bin/sh\nNetgen_BUNDLE=\\\"`echo \\\"$0\\\" | sed -e 's/\\\\/Contents\\\\/MacOS\\\\/startup.sh//'`\\\"\nNetgen_MACOS=\\\"$Netgen_BUNDLE/Contents/MacOS\\\"\nexport NETGENDIR=$Netgen_MACOS  \nexport DYLD_LIBRARY_PATH=$Netgen_MACOS:$DYLD_LIBRARY_PATH\n# export TIX_LIBRARY=$Netgen_MACOS/library\n# export TCLLIBPATH=$Netgen_MACOS:$TCLLIBPATH\nexport PYTHONPATH=$Netgen_BUNDLE/Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR}:$PYTHONPATH\ncd $Netgen_MACOS\n$Netgen_MACOS/netgen\n\")\n    install(PROGRAMS ${mac_startup} DESTINATION ${NG_INSTALL_DIR_BIN})\n\n    set(mac_ngsuite ${CMAKE_CURRENT_BINARY_DIR}/ngsuite.sh)\n    file(WRITE ${mac_ngsuite} \"\\\n#!/bin/sh\nNetgen_BUNDLE=\\\"`echo \\\"$0\\\" | sed -e 's/\\\\/Contents\\\\/MacOS\\\\/Netgen1//'`\\\"\nNetgen_MACOS=\\\"$Netgen_BUNDLE/Contents/MacOS\\\"\nopen -a /Applications/Utilities/Terminal.app $Netgen_MACOS/startup.sh || open -a /System/Applications/Utilities/Terminal.app $Netgen_MACOS/startup.sh\n\")\n    install(PROGRAMS ${mac_ngsuite} DESTINATION ${NG_INSTALL_DIR_BIN} RENAME Netgen1)\n\n    set(mac_plist ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)\n    file(WRITE ${mac_plist} \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\n<!DOCTYPE plist PUBLIC \\\"-//Apple Computer//DTD PLIST 1.0//EN\\\" \\\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\\">\n<plist version=\\\"1.0\\\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>Netgen1</string>\n\t<key>CFBundleIconFile</key>\n\t<string>Netgen.icns</string>\n        <key>NSHighResolutionCapable</key>\n        <string>True</string>\n</dict>\n</plist>\n\")\n    install(FILES ${mac_plist} DESTINATION ${NG_INSTALL_DIR_BIN}/../)\n    install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/netgen.icns DESTINATION ${NG_INSTALL_DIR_RES}/../ RENAME Netgen.icns)\n\nendif(APPLE AND NOT SKBUILD)\n\nif(NOT APPLE)\n  include(CPack) \nendif()\n\n#######################################################################\n# uninstall target\nconfigure_file(\n    \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in\"\n    \"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake\"\n    IMMEDIATE @ONLY)\nadd_custom_target(uninstall\n    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)\n\n#######################################################################\n# Generate package config file\nset(NETGEN_MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})\n\nconfigure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/NetgenConfig.cmake.in\n    ${CMAKE_CURRENT_BINARY_DIR}/NetgenConfig.cmake @ONLY ESCAPE_QUOTES)\n\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/NetgenConfig.cmake DESTINATION ${NG_INSTALL_DIR_CMAKE} COMPONENT netgen_devel)\n\n#######################################################################\n# Configure message\n# TODO: other message in case of failure\nstring(TOUPPER \"CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}\" name)\nset(flags \"${${name}} ${CMAKE_CXX_FLAGS}\")\nmessage(\"\n------------------------------------------------------------------------\n  ${PROJECT_NAME} ${PACKAGE_VERSION}:  Automatic configuration OK.\n\n  Build type: ${CMAKE_BUILD_TYPE}\n  Flags: ${flags}\n\n  Enabled functionality:\n\n    OCC: ............... ${USE_OCC}\n    JPEGlib: ........... ${USE_JPEG}\n    FFMPEG: ............ ${USE_MPEG}\n    GUI: ............... ${USE_GUI}\n    MPI: ............... ${USE_MPI}\n    PYTHON: ............ ${USE_PYTHON}\n\n\n  Building: \")\nif(WIN32)\nmessage(\"\n    Open ${CMAKE_BINARY_DIR}/Netgen.sln and build solution to compile ${PROJECT_NAME}.\n\n    Build \\\"INSTALL\\\" to install ${PROJECT_NAME}.\n\")\nelse(WIN32)\nmessage(\"\n    Type 'make' to compile ${PROJECT_NAME}.\n\n    Type 'make install' to install ${PROJECT_NAME}.\n\")\nendif(WIN32)\nmessage(\"\n  Install directory:\n\n    ${CMAKE_INSTALL_PREFIX}\n\n  Please set the following environment variables:\n\n    NETGENDIR=${CMAKE_INSTALL_PREFIX}/bin\")\nif(USE_PYTHON)\nmessage(\"    PYTHONPATH=.:${CMAKE_INSTALL_PREFIX}/${PYTHON_PACKAGES_INSTALL_DIR}\")\nendif(USE_PYTHON)\nmessage(\"\n------------------------------------------------------------------------\n\")\nif (ADDITIONAL_PATHS)\n  message(WARNING \"The use of ADDITIONAL_PATHS is deprecated, use CMAKE_PREFIX_PATH instead\")\nendif (ADDITIONAL_PATHS)\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "\n# How to Contribute\n\n## Reporting issues\n\nIf you have a problem using Netgen/NGSolve consider asking a question in our [forum](https://ngsolve.org/forum).\n\nIf you found a bug create an issue in the [Github Issue Tracker](https://github.com/NGSolve/netgen/issues). Please be as specific as possible, issues with a reproducible minimal failing example will get more attention than unspecific one liners :)\n\n## Contributing patches\n\nWe love and want to encourage community engagement and will review and accept patches and contributions to this project. There are just a few steps to follow:\n\nOn your first contribution, to clear any legal questions, we ask you to sign our [Contributor License Agreement](CLA.pdf). Generally you have to sign this only once for Netgen or NGSolve. Please send the signed agreement to <joachim.schoeberl@tuwien.ac.at>.\n\nPlace a pull request on GitHub. From there we will pull it into our internal testing environment and, if approved, merge it into the main codebase.\n\nIf you have any questions feel free to ask on the [forum](https://ngsolve.org/forum).\n"
  },
  {
    "path": "ChangeLog",
    "content": ""
  },
  {
    "path": "INSTALL",
    "content": "Basic Installation\n==================\n\n   These are generic installation instructions.\n\n   The `configure' shell script attempts to guess correct values for\nvarious system-dependent variables used during compilation.  It uses\nthose values to create a `Makefile' in each directory of the package.\nIt may also create one or more `.h' files containing system-dependent\ndefinitions.  Finally, it creates a shell script `config.status' that\nyou can run in the future to recreate the current configuration, a file\n`config.cache' that saves the results of its tests to speed up\nreconfiguring, and a file `config.log' containing compiler output\n(useful mainly for debugging `configure').\n\n   If you need to do unusual things to compile the package, please try\nto figure out how `configure' could check whether to do them, and mail\ndiffs or instructions to the address given in the `README' so they can\nbe considered for the next release.  If at some point `config.cache'\ncontains results you don't want to keep, you may remove or edit it.\n\n   The file `configure.in' is used to create `configure' by a program\ncalled `autoconf'.  You only need `configure.in' if you want to change\nit or regenerate `configure' using a newer version of `autoconf'.\n\nThe simplest way to compile this package is:\n\n  1. `cd' to the directory containing the package's source code and type\n     `./configure' to configure the package for your system.  If you're\n     using `csh' on an old version of System V, you might need to type\n     `sh ./configure' instead to prevent `csh' from trying to execute\n     `configure' itself.\n\n     Running `configure' takes a while.  While running, it prints some\n     messages telling which features it is checking for.\n\n  2. Type `make' to compile the package.\n\n  3. Type `make install' to install the programs and any data files and\n     documentation.\n\n  4. You can remove the program binaries and object files from the\n     source code directory by typing `make clean'.  \n\nCompilers and Options\n=====================\n\n   Some systems require unusual options for compilation or linking that\nthe `configure' script does not know about.  You can give `configure'\ninitial values for variables by setting them in the environment.  Using\na Bourne-compatible shell, you can do that on the command line like\nthis:\n     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure\n\nOr on systems that have the `env' program, you can do it like this:\n     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure\n\nCompiling For Multiple Architectures\n====================================\n\n   You can compile the package for more than one kind of computer at the\nsame time, by placing the object files for each architecture in their\nown directory.  To do this, you must use a version of `make' that\nsupports the `VPATH' variable, such as GNU `make'.  `cd' to the\ndirectory where you want the object files and executables to go and run\nthe `configure' script.  `configure' automatically checks for the\nsource code in the directory that `configure' is in and in `..'.\n\n   If you have to use a `make' that does not supports the `VPATH'\nvariable, you have to compile the package for one architecture at a time\nin the source code directory.  After you have installed the package for\none architecture, use `make distclean' before reconfiguring for another\narchitecture.\n\nInstallation Names\n==================\n\n   By default, `make install' will install the package's files in\n`/usr/local/bin', `/usr/local/man', etc.  You can specify an\ninstallation prefix other than `/usr/local' by giving `configure' the\noption `--prefix=PATH'.\n\n   You can specify separate installation prefixes for\narchitecture-specific files and architecture-independent files.  If you\ngive `configure' the option `--exec-prefix=PATH', the package will use\nPATH as the prefix for installing programs and libraries.\nDocumentation and other data files will still use the regular prefix.\n\n   If the package supports it, you can cause programs to be installed\nwith an extra prefix or suffix on their names by giving `configure' the\noption `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.\n\nOptional Features\n=================\n\n   Some packages pay attention to `--enable-FEATURE' options to\n`configure', where FEATURE indicates an optional part of the package.\nThey may also pay attention to `--with-PACKAGE' options, where PACKAGE\nis something like `gnu-as' or `x' (for the X Window System).  The\n`README' should mention any `--enable-' and `--with-' options that the\npackage recognizes.\n\n   For packages that use the X Window System, `configure' can usually\nfind the X include and library files automatically, but if it doesn't,\nyou can use the `configure' options `--x-includes=DIR' and\n`--x-libraries=DIR' to specify their locations.\n\nSpecifying the System Type\n==========================\n\n   There may be some features `configure' can not figure out\nautomatically, but needs to determine by the type of host the package\nwill run on.  Usually `configure' can figure that out, but if it prints\na message saying it can not guess the host type, give it the\n`--host=TYPE' option.  TYPE can either be a short name for the system\ntype, such as `sun4', or a canonical name with three fields:\n     CPU-COMPANY-SYSTEM\n\nSee the file `config.sub' for the possible values of each field.  If\n`config.sub' isn't included in this package, then this package doesn't\nneed to know the host type.\n\n   If you are building compiler tools for cross-compiling, you can also\nuse the `--target=TYPE' option to select the type of system they will\nproduce code for and the `--build=TYPE' option to select the type of\nsystem on which you are compiling the package.\n\nSharing Defaults\n================\n\n   If you want to set default values for `configure' scripts to share,\nyou can create a site shell script called `config.site' that gives\ndefault values for variables like `CC', `cache_file', and `prefix'.\n`configure' looks for `PREFIX/share/config.site' if it exists, then\n`PREFIX/etc/config.site' if it exists.  Or, you can set the\n`CONFIG_SITE' environment variable to the location of the site script.\nA warning: not all `configure' scripts look for a site script.\n\nOperation Controls\n==================\n\n   `configure' recognizes the following options to control how it\noperates.\n\n`--cache-file=FILE'\n     Use and save the results of the tests in FILE instead of\n     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for\n     debugging `configure'.\n\n`--help'\n     Print a summary of the options to `configure', and exit.\n\n`--quiet'\n`--silent'\n`-q'\n     Do not print messages saying which checks are being made.\n\n`--srcdir=DIR'\n     Look for the package's source code in directory DIR.  Usually\n     `configure' can determine that directory automatically.\n\n`--version'\n     Print the version of Autoconf used to generate the `configure'\n     script, and exit.\n\n`configure' also accepts some other, not widely useful, options.\n\n"
  },
  {
    "path": "LICENSE",
    "content": "\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n\t\t       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the Lesser GPL.  It also counts\n as the successor of the GNU Library Public License, version 2, hence\n the version number 2.1.]\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Lesser General Public License, applies to some\nspecially designated software packages--typically libraries--of the\nFree Software Foundation and other authors who decide to use it.  You\ncan use it too, but we suggest you first think carefully about whether\nthis license or the ordinary General Public License is the better\nstrategy to use in any particular case, based on the explanations below.\n\n  When we speak of free software, we are referring to freedom of use,\nnot price.  Our General Public Licenses are designed to make sure that\nyou have the freedom to distribute copies of free software (and charge\nfor this service if you wish); that you receive source code or can get\nit if you want it; that you can change the software and use pieces of\nit in new free programs; and that you are informed that you can do\nthese things.\n\n  To protect your rights, we need to make restrictions that forbid\ndistributors to deny you these rights or to ask you to surrender these\nrights.  These restrictions translate to certain responsibilities for\nyou if you distribute copies of the library or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link other code with the library, you must provide\ncomplete object files to the recipients, so that they can relink them\nwith the library after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  We protect your rights with a two-step method: (1) we copyright the\nlibrary, and (2) we offer you this license, which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  To protect each distributor, we want to make it very clear that\nthere is no warranty for the free library.  Also, if the library is\nmodified by someone else and passed on, the recipients should know\nthat what they have is not the original version, so that the original\nauthor's reputation will not be affected by problems that might be\nintroduced by others.\n\f\n  Finally, software patents pose a constant threat to the existence of\nany free program.  We wish to make sure that a company cannot\neffectively restrict the users of a free program by obtaining a\nrestrictive license from a patent holder.  Therefore, we insist that\nany patent license obtained for a version of the library must be\nconsistent with the full freedom of use specified in this license.\n\n  Most GNU software, including some libraries, is covered by the\nordinary GNU General Public License.  This license, the GNU Lesser\nGeneral Public License, applies to certain designated libraries, and\nis quite different from the ordinary General Public License.  We use\nthis license for certain libraries in order to permit linking those\nlibraries into non-free programs.\n\n  When a program is linked with a library, whether statically or using\na shared library, the combination of the two is legally speaking a\ncombined work, a derivative of the original library.  The ordinary\nGeneral Public License therefore permits such linking only if the\nentire combination fits its criteria of freedom.  The Lesser General\nPublic License permits more lax criteria for linking other code with\nthe library.\n\n  We call this license the \"Lesser\" General Public License because it\ndoes Less to protect the user's freedom than the ordinary General\nPublic License.  It also provides other free software developers Less\nof an advantage over competing non-free programs.  These disadvantages\nare the reason we use the ordinary General Public License for many\nlibraries.  However, the Lesser license provides advantages in certain\nspecial circumstances.\n\n  For example, on rare occasions, there may be a special need to\nencourage the widest possible use of a certain library, so that it becomes\na de-facto standard.  To achieve this, non-free programs must be\nallowed to use the library.  A more frequent case is that a free\nlibrary does the same job as widely used non-free libraries.  In this\ncase, there is little to gain by limiting the free library to free\nsoftware only, so we use the Lesser General Public License.\n\n  In other cases, permission to use a particular library in non-free\nprograms enables a greater number of people to use a large body of\nfree software.  For example, permission to use the GNU C Library in\nnon-free programs enables many more people to use the whole GNU\noperating system, as well as its variant, the GNU/Linux operating\nsystem.\n\n  Although the Lesser General Public License is Less protective of the\nusers' freedom, it does ensure that the user of a program that is\nlinked with the Library has the freedom and the wherewithal to run\nthat program using a modified version of the Library.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, whereas the latter must\nbe combined with the library in order to run.\n\f\n\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library or other\nprogram which contains a notice placed by the copyright holder or\nother authorized party saying it may be distributed under the terms of\nthis Lesser General Public License (also called \"this License\").\nEach licensee is addressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n  \n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\f\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Library, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote\nit.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\f\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\f\n  6. As an exception to the Sections above, you may also combine or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Use a suitable shared library mechanism for linking with the\n    Library.  A suitable mechanism is one that (1) uses at run time a\n    copy of the library already present on the user's computer system,\n    rather than copying library functions into the executable, and (2)\n    will operate properly with a modified version of the library, if\n    the user installs one, as long as the modified version is\n    interface-compatible with the version that the work was made with.\n\n    c) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    d) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    e) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe materials to be distributed need not include anything that is\nnormally distributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\f\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties with\nthis License.\n\f\n  11. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Lesser General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\f\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n           How to Apply These Terms to Your New Libraries\n\n  If you develop a new library, and you want it to be of the greatest\npossible use to the public, we recommend making it free software that\neveryone can redistribute and change.  You can do so by permitting\nredistribution under these terms (or, alternatively, under the terms of the\nordinary General Public License).\n\n  To apply these terms, attach the following notices to the library.  It is\nsafest to attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the library's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nAlso add information on how to contact you by electronic and paper mail.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the library, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the\n  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\n\n  <signature of Ty Coon>, 1 April 1990\n  Ty Coon, President of Vice\n\nThat's all there is to it!\n\n\n"
  },
  {
    "path": "NEWS",
    "content": ""
  },
  {
    "path": "README.md",
    "content": "Netgen mesh generator\n\nNETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STL file format. The connection to a geometry kernel allows the handling of IGES and STEP files. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Netgen 6.x supports scripting via a Python interface. Netgen is open source based on the LGPL license. It is available for Unix/Linux, Windows, and OSX.\n\nFind the Open Source Community on https://ngsolve.org\nSupport & Services: https://cerbsim.com\n\n"
  },
  {
    "path": "TODO",
    "content": ""
  },
  {
    "path": "cmake/NetgenConfig.cmake.in",
    "content": "set(CMAKE_MSVC_RUNTIME_LIBRARY \"@CMAKE_MSVC_RUNTIME_LIBRARY@\")\nset(NETGEN_VERSION \"@NETGEN_VERSION@\")\nset(NETGEN_VERSION_MAJOR \"@NETGEN_VERSION_MAJOR@\")\nset(NETGEN_VERSION_MINOR \"@NETGEN_VERSION_MINOR@\")\nset(NETGEN_VERSION_PATCH \"@NETGEN_VERSION_PATCH@\")\nset(NETGEN_VERSION_TWEAK \"@NETGEN_VERSION_TWEAK@\")\n\nget_filename_component(NETGEN_CMAKE_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n\nget_filename_component(NETGEN_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_DIR@\" ABSOLUTE)\n\nset(NETGEN_COMPILE_DEFINITIONS \"@NETGEN_COMPILE_DEFINITIONS@\")\n\nget_filename_component(NETGEN_INCLUDE_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_INCLUDE_DIR@\" ABSOLUTE)\nget_filename_component(NETGEN_BINARY_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_BINARY_DIR@\" ABSOLUTE)\nget_filename_component(NETGEN_LIBRARY_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_LIBRARY_DIR@\" ABSOLUTE)\nget_filename_component(NETGEN_PYTHON_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_PYTHON_DIR@\" ABSOLUTE)\nget_filename_component(NETGEN_RESOURCE_DIR \"${NETGEN_CMAKE_DIR}/@NETGEN_RESOURCE_DIR@\" ABSOLUTE)\n\nset(NETGEN_SOURCE_DIR \"@PROJECT_SOURCE_DIR@\")\n\nset(NETGEN_BUILD_FOR_CONDA \"@BUILD_FOR_CONDA@\")\nset(NETGEN_CHECK_RANGE \"@CHECK_RANGE@\")\nset(NETGEN_INCLUDE_DIRS \"${NETGEN_INCLUDE_DIR}/include;${NETGEN_INCLUDE_DIR}\")\nset(NETGEN_CMAKE_THREAD_LIBS_INIT \"@CMAKE_THREAD_LIBS_INIT@\")\nset(NETGEN_FFMPEG_LIBRARIES \"@FFMPEG_LIBRARIES@\")\nset(NETGEN_JPEG_INCLUDE_DIR \"@JPEG_INCLUDE_DIR@\")\nset(NETGEN_JPEG_LIBRARIES \"@JPEG_LIBRARIES@\")\nset(NETGEN_LIBTOGL \"@LIBTOGL@\")\nset(NETGEN_METIS_INCLUDE_DIR \"@METIS_INCLUDE_DIR@\")\nset(NETGEN_METIS_LIBRARY \"@METIS_LIBRARY@\")\nset(NETGEN_MKL_LIBRARIES \"@MKL_LIBRARIES@\")\nset(NETGEN_MPI_CXX_INCLUDE_PATH \"@MPI_CXX_INCLUDE_PATH@\")\nset(NETGEN_MPI_CXX_LIBRARIES \"@MPI_CXX_LIBRARIES@\")\nset(NETGEN_NUMA_LIBRARY \"@NUMA_LIBRARY@\")\nset(NETGEN_OCC_DIR \"@OpenCasCade_DIR@\")\nset(NETGEN_OCC_INCLUDE_DIR \"@OpenCASCADE_INCLUDE_DIR@\")\nset(NETGEN_OCC_LIBRARIES_BIN \"@OpenCASCADE_BINARY_DIR@\")\nset(NETGEN_OCC_LIBRARIES \"@OCC_LIBRARIES@\")\nset(NETGEN_OCC_LIBRARY_DIR \"@OpenCASCADE_LIBRARY_DIR@\")\nset(NETGEN_OPENGL_LIBRARIES \"@OPENGL_LIBRARIES@\")\nset(NETGEN_PYTHON_EXECUTABLE \"@Python3_EXECUTABLE@\")\nset(NETGEN_PYTHON_INCLUDE_DIRS \"@Python3_INCLUDE_DIRS@\")\nset(NETGEN_PYTHON_LIBRARIES \"@Python3_LIBRARIES@\")\nset(NETGEN_TCL_INCLUDE_PATH \"@TCL_INCLUDE_PATH@\")\nset(NETGEN_TCL_LIBRARY \"@TCL_STUB_LIBRARY@\")\nset(NETGEN_TK_DND_LIBRARY \"@TK_DND_LIBRARY@\")\nset(NETGEN_TK_INCLUDE_PATH \"@TK_INCLUDE_PATH@\")\nset(NETGEN_TK_LIBRARY \"@TK_STUB_LIBRARY@\")\nset(NETGEN_X11_X11_LIB \"@X11_X11_LIB@\")\nset(NETGEN_X11_Xmu_LIB \"@X11_Xmu_LIB@\")\nset(NETGEN_ZLIB_INCLUDE_DIRS \"@ZLIB_INCLUDE_DIRS@\")\nset(NETGEN_ZLIB_LIBRARIES \"@ZLIB_LIBRARIES@\")\n\nset(NETGEN_USE_GUI @USE_GUI@)\nset(NETGEN_USE_PYTHON @USE_PYTHON@)\nset(NETGEN_USE_MPI @USE_MPI@)\nset(NETGEN_USE_OCC @USE_OCC@)\nset(NETGEN_USE_JPEG @USE_JPEG@)\nset(NETGEN_USE_MPEG @USE_MPEG@)\nset(NETGEN_USE_CGNS @USE_CGNS@)\nset(NETGEN_INTEL_MIC @INTEL_MIC@)\nset(NETGEN_INSTALL_PROFILES @INSTALL_PROFILES@)\nset(NETGEN_USE_CCACHE @USE_CCACHE@)\nset(NETGEN_USE_NATIVE_ARCH @USE_NATIVE_ARCH@)\nset(NETGEN_USE_NUMA @USE_NUMA@)\n\nset(NETGEN_PYTHON_RPATH \"@NETGEN_PYTHON_RPATH@\")\nset(NETGEN_RPATH_TOKEN \"@NG_RPATH_TOKEN@\")\n\nset(NETGEN_INSTALL_DIR_PYTHON @NG_INSTALL_DIR_PYTHON@)\nset(NETGEN_INSTALL_DIR_BIN @NG_INSTALL_DIR_BIN@)\nset(NETGEN_INSTALL_DIR_LIB @NG_INSTALL_DIR_LIB@)\nset(NETGEN_INSTALL_DIR_INCLUDE @NG_INSTALL_DIR_INCLUDE@)\nset(NETGEN_INSTALL_DIR_CMAKE @NG_INSTALL_DIR_CMAKE@)\nset(NETGEN_INSTALL_DIR_RES @NG_INSTALL_DIR_RES@)\n\nif (NETGEN_USE_PYTHON)\n  # Make sure we are finding the same Python version Netgen was built with\n  set(Python3_FIND_VERSION_MAJOR @Python3_VERSION_MAJOR@)\n  set(Python3_FIND_VERSION_MINOR @Python3_VERSION_MINOR@)\nendif()\n\ninclude(${CMAKE_CURRENT_LIST_DIR}/netgen-targets.cmake)\nmessage(STATUS \"Found Netgen: ${CMAKE_CURRENT_LIST_DIR}\")\n"
  },
  {
    "path": "cmake/SuperBuild.cmake",
    "content": "include (ExternalProject)\n\noption( BUILD_ZLIB \"Build and link static version of zlib (useful for pip binaries)\" OFF )\noption( BUILD_OCC \"Build and link static version of occ (useful for pip binaries)\" OFF )\nset_property (DIRECTORY PROPERTY EP_PREFIX dependencies)\n\nset (NETGEN_DEPENDENCIES)\nset (LAPACK_DEPENDENCIES)\nset (NETGEN_CMAKE_ARGS \"\" CACHE INTERNAL \"\")\nset (SUBPROJECT_CMAKE_ARGS \"\" CACHE INTERNAL \"\")\n\nset (SUBPROJECT_ARGS\n    LIST_SEPARATOR |\n    PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies\n)\n\nif (EMSCRIPTEN)\n    set (SUBPROJECT_ARGS\n        ${SUBPROJECT_ARGS}\n        CMAKE_COMMAND emcmake ${CMAKE_COMMAND})\nendif()\n\n# only show output on failure in ci-builds\nif(DEFINED ENV{CI})\n    set (SUBPROJECT_ARGS\n        ${SUBPROJECT_ARGS}\n        LOG_DOWNLOAD ON\n        LOG_BUILD ON\n        LOG_INSTALL ON\n        LOG_CONFIGURE ON\n    )\n    if(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.14.0\")\n        set (SUBPROJECT_ARGS\n            ${SUBPROJECT_ARGS}\n            LOG_OUTPUT_ON_FAILURE ON\n            LOG_MERGED_STDOUTERR ON\n        )\n    endif()\nendif()\n\n\nset (NETGEN_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} )\n\nmacro(set_vars VAR_OUT)\n  foreach(varname ${ARGN})\n    if(NOT \"${${varname}}\" STREQUAL \"\")\n      string(REPLACE \";\" \"|\" varvalue \"${${varname}}\" )\n      set(${VAR_OUT} \"${${VAR_OUT}};-D${varname}=${varvalue}\" CACHE INTERNAL \"\")\n    endif()\n  endforeach()\nendmacro()\n#######################################################################\n\nset_vars(SUBPROJECT_CMAKE_ARGS CMAKE_OSX_DEPLOYMENT_TARGET)\nset_vars(SUBPROJECT_CMAKE_ARGS CMAKE_OSX_SYSROOT)\nset_vars(SUBPROJECT_CMAKE_ARGS CMAKE_C_COMPILER)\nset_vars(SUBPROJECT_CMAKE_ARGS CMAKE_CXX_COMPILER)\nset_vars(SUBPROJECT_CMAKE_ARGS CMAKE_BUILD_TYPE)\n\nset(SUBPROJECT_CMAKE_ARGS \"${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5\" CACHE INTERNAL \"\")\n\nif(USE_CCACHE)\n  find_program(CCACHE_FOUND NAMES ccache ccache.bat)\n  if(CCACHE_FOUND)\n      set(SUBPROJECT_CMAKE_ARGS \"${SUBPROJECT_CMAKE_ARGS};-DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE_FOUND}\" CACHE INTERNAL \"\")\n  endif()\nendif()\n\n#######################################################################\nset (DEPS_DOWNLOAD_URL \"https://github.com/NGSolve/ngsolve_dependencies/releases/download/v1.0.0\" CACHE STRING INTERNAL)\nset (OCC_DOWNLOAD_URL_WIN \"${DEPS_DOWNLOAD_URL}/occ75_win64.zip\" CACHE STRING INTERNAL)\nset (TCLTK_DOWNLOAD_URL_WIN \"${DEPS_DOWNLOAD_URL}/tcltk_win64.zip\" CACHE STRING INTERNAL)\nset (ZLIB_DOWNLOAD_URL_WIN \"${DEPS_DOWNLOAD_URL}/zlib_win64.zip\" CACHE STRING INTERNAL)\nset (CGNS_DOWNLOAD_URL_WIN \"${DEPS_DOWNLOAD_URL}/cgns_win64.zip\" CACHE STRING INTERNAL)\nset (CGNS_DOWNLOAD_URL_MAC \"${DEPS_DOWNLOAD_URL}/cgns_mac.zip\" CACHE STRING INTERNAL)\n\n\nif(UNIX)\n  message(\"Checking for write permissions in install directory...\")\n  execute_process(COMMAND mkdir -p ${CMAKE_INSTALL_PREFIX})\n  execute_process(COMMAND test -w ${CMAKE_INSTALL_PREFIX} RESULT_VARIABLE res)\n  if(res)\n    message(WARNING \"No write access at install directory, please set correct permissions\")\n  endif()\nendif(UNIX)\n\nif(USE_OCC)\nif(BUILD_OCC)\n  set(OCC_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/occ)\n\n  ExternalProject_Add(project_occ\n    # URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_3.zip\n    # URL_MD5 2426e373903faabbd4f96a01a934b66d\n    # URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_7_2.zip\n    # URL_MD5 533eb4f18af0f77ae321b158caeaee79\n    URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_8_1.zip\n    URL_MD5 bf62952a03696dab9e4272aa8efacb1a\n    DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n    ${SUBPROJECT_ARGS}\n    CMAKE_ARGS\n         -DCMAKE_INSTALL_PREFIX=${OCC_DIR}\n         -DCMAKE_PREFIX_PATH=${OCC_DIR}\n         -DBUILD_LIBRARY_TYPE:STRING=Static\n         -DBUILD_MODULE_FoundationClasses:BOOL=ON\n         -DBUILD_MODULE_ModelingData:BOOL=ON\n         -DBUILD_MODULE_ModelingAlgorithms:BOOL=ON\n         -DBUILD_MODULE_DataExchange:BOOL=ON\n         -DBUILD_MODULE_Visualization:BOOL=OFF\n         -DBUILD_MODULE_ApplicationFramework:BOOL=OFF\n         -DBUILD_MODULE_Draw:BOOL=OFF\n         -DBUILD_MODULE_DETools:BOOL=OFF\n         -DUSE_FREETYPE:BOOL=OFF\n         -DUSE_OPENGL:BOOL=OFF\n         -DUSE_XLIB:BOOL=OFF\n         -DBUILD_DOC_Overview:BOOL=OFF\n         ${SUBPROJECT_CMAKE_ARGS}\n    UPDATE_COMMAND \"\"\n    )\n\n  list(APPEND NETGEN_DEPENDENCIES project_occ)\n  set(OpenCascade_ROOT ${OCC_DIR})\nelse(BUILD_OCC)\n    find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)\n    if(NOT OpenCascade_FOUND)\n      message(FATAL_ERROR \"Opencascade not found, either\\n\\\n      - install pip packages netgen-occt-devel netgen-occt\\n\\\n      - set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\\n\\\n      - build OpenCascade automatically by passing -DBUILD_OCC=ON\\n\\\n      - disable OpenCascade by passing -DUSE_OCC=OFF\\n\\\n      \")\n    endif()\nendif(BUILD_OCC)\nendif(USE_OCC)\n\nif(BUILD_ZLIB)\n  set(ZLIB_ROOT ${CMAKE_CURRENT_BINARY_DIR}/dependencies/zlib)\n  ExternalProject_Add(project_zlib\n    ${SUBPROJECT_ARGS}\n    URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip\n    URL_MD5 9d6a627693163bbbf3f26403a3a0b0b1\n    DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n    CMAKE_ARGS\n         -DCMAKE_INSTALL_PREFIX=${ZLIB_ROOT}\n         ${SUBPROJECT_CMAKE_ARGS}\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    )\n\n  list(APPEND NETGEN_DEPENDENCIES project_zlib)\n  if(WIN32)\n    # force linking the static library\n    set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)\n    set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/zlibstatic.lib)\n    set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/zlibstatic.lib)\n  else(WIN32)\n    set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)\n    set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/libz.a)\n    set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/libz.a)\n  endif(WIN32)\nelse()\n    include(cmake/external_projects/zlib.cmake)\nendif()\n\n#######################################################################\nif (USE_PYTHON)\n  find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies/pybind11/include NO_DEFAULT_PATH)\n    set(NG_INSTALL_PYBIND ON)\n    if( NOT PYBIND_INCLUDE_DIR )\n      # if the pybind submodule is missing, try to initialize and update all submodules\n      execute_process(COMMAND git submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\n      find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies/pybind11/include NO_DEFAULT_PATH)\n    endif( NOT PYBIND_INCLUDE_DIR )\n    if( PYBIND_INCLUDE_DIR )\n        message(\"-- Found Pybind11: ${PYBIND_INCLUDE_DIR}\")\n    else( PYBIND_INCLUDE_DIR )\n        message(FATAL_ERROR \"Could NOT find pybind11!\")\n    endif( PYBIND_INCLUDE_DIR )\n    if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)\n      find_package(Python3 COMPONENTS Interpreter Development.Module)\n      if(NOT EMSCRIPTEN)\n          find_package(Python3 COMPONENTS Interpreter Development.Embed)\n      endif()\n    else()\n      find_package(Python3 REQUIRED COMPONENTS Interpreter Development)\n    endif()\n\n    set_vars(NETGEN_CMAKE_ARGS\n      Python3_INCLUDE_DIRS\n      Python3_LIBRARIES\n      Python3_EXECUTABLE\n      Python3_VERSION\n      PYBIND_INCLUDE_DIR\n      NG_INSTALL_PYBIND\n      )\nendif (USE_PYTHON)\n\n#######################################################################\n\nif(USE_GUI)\n  include(cmake/external_projects/tcltk.cmake)\nendif(USE_GUI)\n\nif(USE_CGNS)\n  include(cmake/external_projects/cgns.cmake)\nendif(USE_CGNS)\n\n#######################################################################\nif(USE_MPI)\n    if (METIS_DIR)\n      message(STATUS \"Using external METIS at: ${METIS_DIR}\")\n    else (METIS_DIR)\n      message(STATUS \"Looking for system METIS\")\n      find_package(METIS QUIET)\n      if(NOT METIS_FOUND)\n\tmessage(WARNING \"Could not find METIS, it will be built from source (this might conflict with NGSolve MUMPS)!\")\n\tinclude(cmake/external_projects/metis.cmake)\n      endif(NOT METIS_FOUND)\n    endif(METIS_DIR)\nendif(USE_MPI)\n\n\n#######################################################################\n# propagate cmake variables to Netgen subproject\nset_vars( NETGEN_CMAKE_ARGS\n  CMAKE_MODULE_LINKER_FLAGS\n  CMAKE_MODULE_LINKER_FLAGS_RELEASE\n  CMAKE_SHARED_LINKER_FLAGS\n  CMAKE_SHARED_LINKER_FLAGS_RELEASE\n  CMAKE_CXX_FLAGS\n  CMAKE_CXX_FLAGS_RELEASE\n  CMAKE_STRIP\n\n  USE_GUI\n  USE_PYTHON\n  USE_MPI\n  USE_MPI_WRAPPER\n  USE_VT\n  USE_VTUNE\n  USE_NUMA\n  USE_CCACHE\n  USE_NATIVE_ARCH\n  USE_OCC\n  USE_MPEG\n  USE_JPEG\n  USE_CGNS\n  USE_INTERNAL_TCL\n  INSTALL_PROFILES\n  INTEL_MIC\n  CMAKE_INSTALL_PREFIX\n  ENABLE_UNIT_TESTS\n  ENABLE_CPP_CORE_GUIDELINES_CHECK\n  USE_SPDLOG\n  DEBUG_LOG\n  CHECK_RANGE\n  TRACE_MEMORY\n  BUILD_STUB_FILES\n  BUILD_FOR_CONDA\n  NG_COMPILE_FLAGS\n  OpenCascade_ROOT\n  ZLIB_INCLUDE_DIRS\n  ZLIB_LIBRARIES\n  ZLIB_LIBRARY_RELEASE\n  ZLIB_ROOT\n\n  NGLIB_LIBRARY_TYPE\n  NGCORE_LIBRARY_TYPE\n  NGGUI_LIBRARY_TYPE\n\n  NG_INSTALL_DIR_PYTHON\n  NG_INSTALL_DIR_BIN\n  NG_INSTALL_DIR_LIB\n  NG_INSTALL_DIR_INCLUDE\n  NG_INSTALL_DIR_CMAKE\n  NG_INSTALL_DIR_RES\n  NG_INSTALL_SUFFIX\n  )\n\n# propagate all variables set on the command line using cmake -DFOO=BAR\n# to Netgen subproject\nget_cmake_property(CACHE_VARS CACHE_VARIABLES)\nforeach(CACHE_VAR ${CACHE_VARS})\n  get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)\n  if(CACHE_VAR_HELPSTRING STREQUAL \"No help, variable specified on the command line.\" AND NOT CACHE_VAR STREQUAL \"CMAKE_OSX_ARCHITECTURES\")\n    get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE)\n    string(REPLACE \";\" \"|\" varvalue \"${${CACHE_VAR}}\" )\n    set(NETGEN_CMAKE_ARGS ${NETGEN_CMAKE_ARGS};-D${CACHE_VAR}:${CACHE_VAR_TYPE}=${varvalue} CACHE INTERNAL \"\")\n  endif()\nendforeach()\n\nif(${CMAKE_GENERATOR} STREQUAL \"Unix Makefiles\")\n  set(NETGEN_BUILD_COMMAND $(MAKE) --silent )\nelse()\n  set(NETGEN_BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/netgen --config ${CMAKE_BUILD_TYPE})\nendif()\n\n\nstring(REPLACE \";\" \"|\" NETGEN_CMAKE_PREFIX_PATH_ALT_SEP \"${NETGEN_CMAKE_PREFIX_PATH}\")\nExternalProject_Add (netgen\n  ${SUBPROJECT_ARGS}\n  DEPENDS ${NETGEN_DEPENDENCIES}\n  SOURCE_DIR ${PROJECT_SOURCE_DIR}\n  CMAKE_ARGS\n      -DUSE_SUPERBUILD=OFF\n      ${NETGEN_CMAKE_ARGS}\n      ${SUBPROJECT_CMAKE_ARGS}\n      -DCMAKE_PREFIX_PATH=${NETGEN_CMAKE_PREFIX_PATH_ALT_SEP}\n  INSTALL_COMMAND \"\"\n  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/netgen\n  BUILD_COMMAND ${NETGEN_BUILD_COMMAND}\n  STEP_TARGETS build\n)\n\n# Check if the git submodules (i.e. pybind11) are up to date\n# in case, something is wrong, emit a warning but continue\n ExternalProject_Add_Step(netgen check_submodules\n   COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_submodules.cmake\n   DEPENDERS install # Steps on which this step depends\n   )\n\n# Due to 'ALWAYS 1', this step is always run which also forces a build of\n# the Netgen subproject\n ExternalProject_Add_Step(netgen check_submodules1\n   COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_submodules.cmake\n   DEPENDEES configure # Steps on which this step depends\n   DEPENDERS build     # Steps that depend on this step\n   ALWAYS 1            # No stamp file, step always runs\n   )\n\n\ninstall(CODE \"execute_process(COMMAND \\\"${CMAKE_COMMAND}\\\" --build . --target install --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY \\\"${CMAKE_CURRENT_BINARY_DIR}/netgen\\\")\")\n\nadd_custom_target(test_netgen\n  ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/netgen\n                   --target test\n                   --config ${CMAKE_BUILD_TYPE}\n                   )\n"
  },
  {
    "path": "cmake/check_submodules.cmake",
    "content": "execute_process(COMMAND git submodule status --recursive WORKING_DIRECTORY \"${CMAKE_CURRENT_LIST_DIR}/../\" OUTPUT_VARIABLE git_status_output)\nstring(REPLACE \"\\n\" \";\" git_status_output \"${git_status_output}\")\nforeach( a ${git_status_output})\n  if(NOT ${a} MATCHES \" [a-f,0-9]* external_dependencies[.]*\")\n    message(WARNING\n\"*****************************************************************\n      WARNING: The git submodules are out of sync! Please run\n      git submodule update --init --recursive\n      in your source directory\n*****************************************************************\")\n  endif()\nendforeach()\n\n"
  },
  {
    "path": "cmake/cmake_modules/FindFFMPEG.cmake",
    "content": "# - Try to find ffmpeg libraries (libavcodec, libavformat, libavutil and swscale)\n# Once done this will define\n#\n#  FFMPEG_FOUND - system has ffmpeg or libav\n#  FFMPEG_INCLUDE_DIR - the ffmpeg include directory\n#  FFMPEG_LIBRARIES - Link these to use ffmpeg\n#  FFMPEG_LIBAVCODEC\n#  FFMPEG_LIBAVFORMAT\n#  FFMPEG_LIBAVUTIL\n#  FFMPEG_SWSCALE\n#\n#  Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>\n#  Modified for other libraries by Lasse Kärkkäinen <tronic>\n#  Modified for Hedgewars by Stepik777\n#  Modified for Netgen by Christoph Lehrenfeld (2015) (current version)\n#\n#  Redistribution and use is allowed according to the terms of the New\n#  BSD license.\n#\n\nif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)\n  # in cache already\n  set(FFMPEG_FOUND TRUE)\nelse (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)\n  # use pkg-config to get the directories and then use these values\n  # in the FIND_PATH() and FIND_LIBRARY() calls\n  find_package(PkgConfig)\n  if (PKG_CONFIG_FOUND)\n    pkg_check_modules(_FFMPEG_AVCODEC libavcodec)\n    pkg_check_modules(_FFMPEG_AVFORMAT libavformat)\n    pkg_check_modules(_FFMPEG_AVUTIL libavutil)\n    pkg_check_modules(SWSCALE libswscale)\n  endif (PKG_CONFIG_FOUND)\n\n  find_path(FFMPEG_AVCODEC_INCLUDE_DIR\n    NAMES libavcodec/avcodec.h\n    PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} /usr/include /usr/local/include /opt/local/include /sw/include\n    PATH_SUFFIXES ffmpeg libav\n  )\n\n  find_library(FFMPEG_LIBAVCODEC\n    NAMES avcodec\n    PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib\n  )\n\n  find_library(FFMPEG_LIBAVFORMAT\n    NAMES avformat\n    PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib\n  )\n\n  find_library(FFMPEG_LIBAVUTIL\n    NAMES avutil\n    PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib\n  )\n\n  find_library(FFMPEG_SWSCALE\n    NAMES swscale\n    PATHS ${SWSCALE_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib\n  )\n\n  if (FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT)\n    set(FFMPEG_FOUND TRUE)\n  endif()\n\n  if (FFMPEG_FOUND)\n    set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR})\n\n    set(FFMPEG_LIBRARIES\n      ${FFMPEG_LIBAVCODEC}\n      ${FFMPEG_LIBAVFORMAT}\n      ${FFMPEG_LIBAVUTIL}\n      ${FFMPEG_SWSCALE}\n    )\n\n  endif (FFMPEG_FOUND)\n\n  if (FFMPEG_FOUND)\n    if (NOT FFMPEG_FIND_QUIETLY)\n      message(STATUS \"Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}\")\n    endif (NOT FFMPEG_FIND_QUIETLY)\n  else (FFMPEG_FOUND)\n    if (FFMPEG_FIND_REQUIRED)\n      message(FATAL_ERROR \"Could not find libavcodec or libavformat or libavutil\")\n    endif (FFMPEG_FIND_REQUIRED)\n  endif (FFMPEG_FOUND)\n\nendif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)\n"
  },
  {
    "path": "cmake/cmake_modules/FindMETIS.cmake",
    "content": "# -*- mode: cmake -*-\n#\n# METIS Find Module for MSTK\n# Shamelessly stolen from Amanzi open source code https://software.lanl.gov/ascem/trac\n#\n# Usage:\n#    Control the search through METIS_DIR or setting environment variable\n#    METIS_ROOT to the METIS installation prefix.\n#\n#    This module does not search default paths!\n#\n#    Following variables are set:\n#    METIS_FOUND            (BOOL)       Flag indicating if METIS was found\n#    METIS_INCLUDE_DIR      (PATH)       Path to the METIS include file\n#    METIS_INCLUDE_DIRS     (LIST)       List of all required include files\n#    METIS_LIBRARY_DIR      (PATH)       Path to the METIS library\n#    METIS_LIBRARY          (FILE)       METIS library\n#    METIS_LIBRARIES        (LIST)       List of all required METIS libraries\n#\n# #############################################################################\n# Standard CMake modules see CMAKE_ROOT/Modules\ninclude(FindPackageHandleStandardArgs)\n# Amanzi CMake functions see <root>/tools/cmake for source\n#     include(PrintVariable)\nif ( METIS_LIBRARIES AND METIS_INCLUDE_DIRS )\n# Do nothing. Variables are set. No need to search again\nelse(METIS_LIBRARIES AND METIS_INCLUDE_DIRS)\n# Cache variables\nif(METIS_DIR)\n    set(METIS_DIR \"${METIS_DIR}\" CACHE PATH \"Path to search for METIS include and library files\")\n    endif()\nif(METIS_INCLUDE_DIR)\n    set(METIS_INCLUDE_DIR \"${METIS_INCLUDE_DIR}\" CACHE PATH \"Path to search for METIS include files\")\n    endif()\nif(METIS_LIBRARY_DIR)\n    set(METIS_LIBRARY_DIR \"${METIS_LIBRARY_DIR}\" CACHE PATH \"Path to search for METIS library files\")\nendif()\n\n# Search for include files\n# Search order preference:\n#  (1) METIS_INCLUDE_DIR - check existence of path AND if the include files exist\n#  (2) METIS_DIR/<include>\n#  (3) Default CMake paths See cmake --html-help=out.html file for more information.\n#\n    set(metis_inc_names \"metis.h\")\nif (METIS_INCLUDE_DIR)\n    if (EXISTS \"${METIS_INCLUDE_DIR}\")\n    find_path(metis_test_include_path\n            NAMES ${metis_inc_names}\n            HINTS ${METIS_INCLUDE_DIR}\n            NO_DEFAULT_PATH)\n    set(METIS_INCLUDE_DIR \"${metis_test_include_path}\")\nendif()\nelse() \n# Metis sometimes puts the include files in a subdir called Lib\n    set(metis_inc_suffixes \"include\" \"Lib\")\nif(METIS_DIR)\n    if (EXISTS \"${METIS_DIR}\" )\n    find_path(METIS_INCLUDE_DIR\n            NAMES ${metis_inc_names}\n            HINTS ${METIS_DIR}\n            PATH_SUFFIXES ${metis_inc_suffixes}\n            NO_DEFAULT_PATH)\n    endif()\nelse()\n    find_path(METIS_INCLUDE_DIR\n            NAMES ${metis_inc_names}\n            PATH_SUFFIXES ${metis_inc_suffixes})\n    endif()\n    endif()\n# Search for libraries\n# Search order preference:\n#  (1) METIS_LIBRARY_DIR - check existence of path AND if the library file exists\n#  (2) METIS_DIR/<lib,Lib>\n#  (3) Default CMake paths See cmake --html-help=out.html file for more information.\n#\n    set(metis_lib_names \"metis5\" \"metis\")\nif (METIS_LIBRARY_DIR)\n    if (EXISTS \"${METIS_LIBRARY_DIR}\")\n    find_library(METIS_LIBRARY\n            NAMES ${metis_lib_names}\n            HINTS ${METIS_LIBRARY_DIR}\n            NO_DEFAULT_PATH)\n    endif()\nelse() \n    list(APPEND metis_lib_suffixes \"lib\" \"Lib\")\nif(METIS_DIR)\n    if (EXISTS \"${METIS_DIR}\" )\n    find_library(METIS_LIBRARY\n            NAMES ${metis_lib_names}\n            HINTS ${METIS_DIR}\n            PATH_SUFFIXES ${metis_lib_suffixes}\n            NO_DEFAULT_PATH)\n    endif()   \nelse()\n    find_library(METIS_LIBRARY\n            NAMES ${metis_lib_names}\n            PATH_SUFFIXES ${metis_lib_suffixes})\n    endif()\n    endif()\n\n# Define prerequisite packages\nset(METIS_INCLUDE_DIRS ${METIS_INCLUDE_DIR})\nset(METIS_LIBRARIES    ${METIS_LIBRARY})\n\nendif(METIS_LIBRARIES AND METIS_INCLUDE_DIRS )   \n# Send useful message if everything is found\n    find_package_handle_standard_args(METIS DEFAULT_MSG\n            METIS_LIBRARIES\n            METIS_INCLUDE_DIRS)\n# find_package_handle_standard_args should set METIS_FOUND but it does not!\n    if ( METIS_LIBRARIES AND METIS_INCLUDE_DIRS)\n    set(METIS_FOUND TRUE)\n    else()\n    set(METIS_FOUND FALSE)\nendif()\n# Define the version\nmark_as_advanced(\n        METIS_INCLUDE_DIR\n        METIS_INCLUDE_DIRS\n        METIS_LIBRARY\n        METIS_LIBRARIES\n        METIS_LIBRARY_DIR\n        )\n"
  },
  {
    "path": "cmake/cmake_uninstall.cmake.in",
    "content": "if(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n  message(FATAL_ERROR \"Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\nendif(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n\nfile(READ \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\" files)\nstring(REGEX REPLACE \"\\n\" \";\" files \"${files}\")\nforeach(file ${files})\n  message(STATUS \"Uninstalling $ENV{DESTDIR}${file}\")\n  if(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\n    exec_program(\n      \"@CMAKE_COMMAND@\" ARGS \"-E remove \\\"$ENV{DESTDIR}${file}\\\"\"\n      OUTPUT_VARIABLE rm_out\n      RETURN_VALUE rm_retval\n      )\n    if(NOT \"${rm_retval}\" STREQUAL 0)\n      message(FATAL_ERROR \"Problem when removing $ENV{DESTDIR}${file}\")\n    endif(NOT \"${rm_retval}\" STREQUAL 0)\n  else(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\n    message(STATUS \"File $ENV{DESTDIR}${file} does not exist.\")\n  endif(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\nendforeach(file)\n"
  },
  {
    "path": "cmake/external_projects/catch.cmake",
    "content": "include (ExternalProject)\nfind_program(GIT_EXECUTABLE git)\nExternalProject_Add(\n    project_catch\n    PREFIX ${CMAKE_BINARY_DIR}/catch\n    GIT_REPOSITORY https://github.com/catchorg/Catch2.git\n    GIT_TAG v2.13.7\n    TIMEOUT 10\n    UPDATE_COMMAND \"\" # ${GIT_EXECUTABLE} pull\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND \"\"\n    INSTALL_COMMAND \"\"\n    LOG_DOWNLOAD ON\n   )\n\n# Expose required variable (CATCH_INCLUDE_DIR) to parent scope\nExternalProject_Get_Property(project_catch source_dir)\nset(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL \"Path to include folder for Catch\")\n"
  },
  {
    "path": "cmake/external_projects/cgns.cmake",
    "content": "if(WIN32)\n\n  ExternalProject_Add(project_win_cgns\n    URL ${CGNS_DOWNLOAD_URL_WIN}\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND \"\"\n    INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}\n    LOG_DOWNLOAD 1\n    )\n\n  list(APPEND NETGEN_DEPENDENCIES project_win_cgns)\nendif(WIN32)\n\nif(APPLE)\n  ExternalProject_Add(project_mac_cgns\n    URL ${CGNS_DOWNLOAD_URL_MAC}\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND \"\"\n    INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}\n    LOG_DOWNLOAD 1\n    )\n\n  list(APPEND NETGEN_DEPENDENCIES project_mac_cgns)\n  list(APPEND NETGEN_CMAKE_ARGS \"-DCGNS_INCLUDE_DIR=${CMAKE_INSTALL_PREFIX}/Contents/Resources/include\")\n  list(APPEND NETGEN_CMAKE_ARGS \"-DCGNS_LIBRARY=${CMAKE_INSTALL_PREFIX}/Contents/MacOS/libcgns.dylib\")\nendif(APPLE)\n"
  },
  {
    "path": "cmake/external_projects/metis.cmake",
    "content": "set(METIS_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_metis)\nset(METIS_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/metis)\n\nExternalProject_Add(project_metis\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies\n  URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p12.tar.gz\n  URL_MD5 6cd66f75f88dfa2cf043de011f85d8bc\n  DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n  CMAKE_ARGS\n         -DCMAKE_POLICY_VERSION_MINIMUM=3.5\n         -DGKLIB_PATH=${METIS_SRC_DIR}/GKlib\n         -DCMAKE_INSTALL_PREFIX=${METIS_DIR}\n\t -DCMAKE_POSITION_INDEPENDENT_CODE=ON\n\t -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\n\t -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\n  UPDATE_COMMAND \"\" # Disable update\n  BUILD_IN_SOURCE 1\n  )\n\nset_vars( NETGEN_CMAKE_ARGS METIS_DIR )\n\nlist(APPEND NETGEN_DEPENDENCIES project_metis)\n"
  },
  {
    "path": "cmake/external_projects/spdlog.cmake",
    "content": "include(ExternalProject)\nfind_program(GIT_EXECUTABLE git)\n\nExternalProject_Add(\n  project_spdlog\n  PREFIX ${CMAKE_BINARY_DIR}/spdlog\n  GIT_REPOSITORY https://github.com/gabime/spdlog.git\n  GIT_TAG v1.2.1\n  TIMEOUT 01\n  UPDATE_COMMAND \"\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND \"\"\n  INSTALL_COMMAND \"\"\n  LOG_DOWNLOAD ON\n  )\n\nExternalProject_Get_Property(project_spdlog source_dir)\nset(SPDLOG_INCLUDE_DIR ${source_dir}/include)\n"
  },
  {
    "path": "cmake/external_projects/tcltk.cmake",
    "content": "if(UNIX AND NOT APPLE)\n  set (LINUX TRUE)\nendif()\nif(LINUX)\n    find_package(TclStub 8.5 REQUIRED)\nelse(LINUX)\nif(SKBUILD)\n# we are building a pip package - download the tcl/tk sources matching the tkinter version (for private headers not shipped with python)\n\nexecute_process(COMMAND ${Python3_EXECUTABLE} -c\n\"import tkinter;print(tkinter.Tcl().eval('info patchlevel').replace('.','-'))\"\nOUTPUT_VARIABLE PYTHON_TCL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)\n\nset(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl)\nset(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk)\n\nExternalProject_Add(project_tcl\n  URL \"https://github.com/tcltk/tcl/archive/refs/tags/core-${PYTHON_TCL_VERSION}.zip\"\n  UPDATE_COMMAND \"\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND \"\"\n  INSTALL_COMMAND \"\"\n  ${SUBPROJECT_ARGS}\n  DOWNLOAD_DIR download_tcl\n)\nExternalProject_Add(project_tk\n  URL \"https://github.com/tcltk/tk/archive/refs/tags/core-${PYTHON_TCL_VERSION}.zip\"\n  UPDATE_COMMAND \"\"\n  CONFIGURE_COMMAND \"\"\n  INSTALL_COMMAND \"\"\n  BUILD_COMMAND ${CMAKE_COMMAND} -E copy_directory macosx generic\n  ${SUBPROJECT_ARGS}\n  DOWNLOAD_DIR download_tk\n  BUILD_IN_SOURCE 1\n)\n\nset(TCL_INCLUDE_PATH ${TCL_DIR}/generic)\nset(TK_INCLUDE_PATH ${TK_DIR}/generic)\nlist(APPEND NETGEN_DEPENDENCIES project_tcl project_tk)\n\nif(APPLE OR WIN32)\n    execute_process(COMMAND ${Python3_EXECUTABLE} -c \"import sys; print(sys.prefix)\" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)\n    file(TO_CMAKE_PATH ${PYTHON_PREFIX} PYTHON_PREFIX)\n\n    set(tcl_find_args\n        REQUIRED\n        NO_DEFAULT_PATH\n        NO_PACKAGE_ROOT_PATH\n        NO_CMAKE_PATH\n        NO_CMAKE_ENVIRONMENT_PATH\n        NO_SYSTEM_ENVIRONMENT_PATH\n        NO_CMAKE_SYSTEM_PATH\n        NO_CMAKE_FIND_ROOT_PATH\n        HINTS\n        ${PYTHON_PREFIX}/lib\n        ${PYTHON_PREFIX}/tcl\n        ${PYTHON_PREFIX}/Frameworks\n        ${PYTHON_PREFIX}/Frameworks/Tcl.framework\n        ${PYTHON_PREFIX}/Frameworks/Tk.framework\n        )\n    find_library(TCL_STUB_LIBRARY NAMES tclstub85 tclstub8.5 tclstub86 tclstub8.6 ${tcl_find_args})\n    find_library(TK_STUB_LIBRARY NAMES tkstub85 tkstub8.5 tkstub86 tkstub8.6 ${tcl_find_args})\n    find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t Tcl ${tcl_find_args})\n    find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t Tk ${tcl_find_args})\nelse()\n    # use system tcl/tk on linux\n    find_package(TclStub REQUIRED)\nendif()\n\nelse(SKBUILD)\nif(APPLE)\n  set(tcl_prefix ${CMAKE_INSTALL_PREFIX})\n  # URL \"http://sourceforge.net/projects/tcl/files/Tcl/8.6.9/tcl8.6.9-src.tar.gz\"\n  # URL_MD5 aa0a121d95a0e7b73a036f26028538d4\n  ExternalProject_Add(project_tcl\n    URL \"https://github.com/NGSolve/tcl/archive/7769161.zip\"\n    URL_MD5 1131f188dd26944df557913c475d43b4\n    DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n    UPDATE_COMMAND \"\"\n    CONFIGURE_COMMAND ../project_tcl/macosx/configure --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin\n    BUILD_COMMAND make -j4 binaries libraries\n    INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers\n    ${SUBPROJECT_ARGS}\n    )\n\n  # URL \"http://sourceforge.net/projects/tcl/files/Tcl/8.6.9/tk8.6.9.1-src.tar.gz\"\n  # URL_MD5 9efe3976468352dc894dae0c4e785a8e\n  ExternalProject_Add(project_tk\n    DEPENDS project_tcl\n    URL \"https://github.com/NGSolve/tk/archive/e7c2bc7.zip\"\n    URL_MD5 94044140d4826069c22f1c60cedb6e59\n    DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n    UPDATE_COMMAND \"\"\n    CONFIGURE_COMMAND ../project_tk/macosx/configure --enable-aqua=yes --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin --with-tcl=${tcl_prefix}/Contents/Frameworks/Tcl.framework\n    BUILD_COMMAND make -j4 binaries libraries\n    INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers\n    ${SUBPROJECT_ARGS}\n    )\n\n  ExternalProject_Add(project_tkdnd\n    URL \"https://src.fedoraproject.org/repo/pkgs/tkdnd/tkdnd2.8-src.tar.gz/a6d47a996ea957416469b12965d4db91/tkdnd2.8-src.tar.gz\"\n    URL_MD5 a6d47a996ea957416469b12965d4db91\n    DEPENDS project_tcl project_tk\n    DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n    PATCH_COMMAND  patch < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    CMAKE_ARGS\n           -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS\n\t   -DTCL_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers\n\t   -DTK_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers\n     -DCMAKE_POLICY_VERSION_MINIMUM=3.5\n    ${SUBPROJECT_ARGS}\n  )\n\n  list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk project_tkdnd)\n  list(APPEND CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks)\n  set(TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers)\n  set(TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework)\n  set(TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework)\n  set(TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers)\n\n  set(TCL_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/libtclstub8.6.a)\n  set(TK_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/libtkstub8.6.a)\n\n#   # use system tcl/tk\n#   if((${PYTHON_VERSION_STRING} VERSION_EQUAL \"3.7\") OR (${PYTHON_VERSION_STRING} VERSION_GREATER \"3.7\"))\n#     # fetch tcl/tk sources to match the one used in Python 3.7\n#     ExternalProject_Add(project_tcl\n#       URL \"https://prdownloads.sourceforge.net/tcl/tcl8.6.8-src.tar.gz\"\n#       URL_MD5 81656d3367af032e0ae6157eff134f89\n#       DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n#       UPDATE_COMMAND \"\" # Disable update\n#       CONFIGURE_COMMAND \"\"\n#       BUILD_COMMAND \"\"\n#       INSTALL_COMMAND \"\"\n#       )\n#     ExternalProject_Add(project_tk\n#       URL \"https://prdownloads.sourceforge.net/tcl/tk8.6.8-src.tar.gz\"\n#       URL_MD5 5e0faecba458ee1386078fb228d008ba\n#       DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n#       UPDATE_COMMAND \"\" # Disable update\n#       CONFIGURE_COMMAND \"\"\n#       BUILD_COMMAND \"\"\n#       INSTALL_COMMAND \"\"\n#       )\n# \n#     get_filename_component(PYTHON_LIB_DIR ${PYTHON_LIBRARY} DIRECTORY)\n#     find_library(TCL_LIBRARY libtcl8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH)\n#     find_library(TK_LIBRARY libtk8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH)\n# \n#     set(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl)\n#     set(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk)\n#     set(TCL_INCLUDE_PATH \"${TCL_DIR}/generic;${TCL_DIR}/macosx\")\n#     set(TK_INCLUDE_PATH \"${TK_DIR}/generic;${TK_DIR}/macosx;${TK_DIR}/xlib\")\n#     string(REPLACE \";\" \"$<SEMICOLON>\" TCL_INC \"${TCL_INCLUDE_PATH}\")\n#     string(REPLACE \";\" \"$<SEMICOLON>\" TK_INC \"${TK_INCLUDE_PATH}\")\n# \n#     ExternalProject_Add(project_tkdnd\n#       URL \"http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz\"\n#       URL_MD5 a6d47a996ea957416469b12965d4db91\n#       DEPENDS project_tcl project_tk\n#       DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies\n#       PATCH_COMMAND  patch < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch\n#       UPDATE_COMMAND \"\" # Disable update\n#       BUILD_IN_SOURCE 1\n#       CMAKE_ARGS\n# \t      -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS\n# \t      -DTCL_INCLUDE_PATH=${TCL_INC}\n# \t      -DTK_INCLUDE_PATH=${TK_INC}\n# \t      -DTK_LIBRARY=${TK_LIBRARY}\n# \t      -DTCL_LIBRARY=${TCL_LIBRARY}\n#       LOG_DOWNLOAD 1\n#       LOG_CONFIGURE 1\n#       LOG_BUILD 1\n#       LOG_INSTALL 1\n#     )\n#       \n# list(APPEND NETGEN_DEPENDENCIES project_tkdnd)\n#   else()\n#     find_package(TCL 8.5 REQUIRED)\n#   endif()\n\nelseif(WIN32)\n\n  ExternalProject_Add(project_win_tcltk\n    URL ${TCLTK_DOWNLOAD_URL_WIN}\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND \"\"\n    INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}\n\t    COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}\n\t    COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}\n\n    ${SUBPROJECT_ARGS}\n    )\n\n  set (TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include)\n  set (TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include)\n  set (TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tcl86t.lib)\n  set (TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tk86t.lib)\n  set (TCL_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tclstub86.lib)\n  set (TK_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tkstub86.lib)\n\n  list(APPEND NETGEN_DEPENDENCIES project_win_tcltk)\nelse(WIN32)\n    find_package(TCL 8.5 REQUIRED)\n#     ExternalProject_Add(project_tkdnd\n#       GIT_REPOSITORY https://github.com/petasis/tkdnd.git\n#       GIT_TAG d7cfd96087b248255da5349086ef70cc4bbfb619\n#       PREFIX ${CMAKE_CURRENT_BINARY_DIR}/tkdnd\n#       CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/lib\n#       UPDATE_COMMAND \"\"\n#       LOG_DOWNLOAD 1\n#       LOG_BUILD 1\n#       LOG_INSTALL 1\n# )\n# list(APPEND NETGEN_DEPENDENCIES project_tkdnd)\nendif(APPLE)\nendif(SKBUILD)\nendif(LINUX)\n\n# Propagate settings to Netgen subproject\nset_vars(NETGEN_CMAKE_ARGS TCL_INCLUDE_PATH TCL_STUB_LIBRARY TCL_LIBRARY TK_STUB_LIBRARY TK_LIBRARY TK_INCLUDE_PATH TCL_TCLSH TK_WISH)\n"
  },
  {
    "path": "cmake/external_projects/zlib.cmake",
    "content": "if(WIN32)\n\n  ExternalProject_Add(project_win_zlib\n    URL ${ZLIB_DOWNLOAD_URL_WIN}\n    UPDATE_COMMAND \"\" # Disable update\n    BUILD_IN_SOURCE 1\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND \"\"\n    INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}\n\t    COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}\n\t    COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}\n    LOG_DOWNLOAD 1\n    )\n\n\n  list(APPEND NETGEN_DEPENDENCIES project_win_zlib)\nendif(WIN32)\n\n"
  },
  {
    "path": "cmake/generate_version_file.cmake",
    "content": "if(NOT BDIR)\n  set(BDIR ${CMAKE_CURRENT_BINARY_DIR})\nendif()\n\nif(NETGEN_VERSION_GIT)\n    set(git_version_string ${NETGEN_VERSION_GIT})\nelse()\n    find_package(Git REQUIRED)\n    execute_process(COMMAND git describe --tags --match \"v[0-9]*\" --long --dirty\n        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}\n        OUTPUT_VARIABLE git_version_string\n        RESULT_VARIABLE status\n        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE\n    )\nendif()\n\nif(status AND NOT status EQUAL 0)\n  if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../version.txt)\n    # for source package files (generated for ubuntu builds on launchpad) read the version from version.txt\n    if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../version.txt)\n      file(READ ${CMAKE_CURRENT_LIST_DIR}/../version.txt git_version_string )\n    else()\n      get_filename_component(git_version_string ${CMAKE_CURRENT_LIST_DIR}/.. NAME)\n      string(REGEX REPLACE \"^netgen(.*)\" \"\\\\1\" git_version_string \"${git_version_string}\")\n    endif()\n  else()\n    MESSAGE(WARNING \"Could not determine git-version from source code - assuming 6.2.0-0\")\n    set(git_version_string \"v6.2.0-0\")\n  endif()\nendif()\nstring(STRIP ${git_version_string} git_version_string)\n\nstring(REGEX REPLACE \"^v([0-9]+)\\\\..*\" \"\\\\1\" NETGEN_VERSION_MAJOR \"${git_version_string}\")\nstring(REGEX REPLACE \"^v[0-9]+\\\\.([0-9]+).*\" \"\\\\1\" NETGEN_VERSION_MINOR \"${git_version_string}\")\nstring(REGEX REPLACE \"^v[0-9]+\\\\.[0-9]+\\\\.([0-9]+).*\" \"\\\\1\" NETGEN_VERSION_PATCH \"${git_version_string}\")\nstring(REGEX REPLACE \"^v[0-9]+\\\\.[0-9]+\\\\.[0-9]+\\\\-([0-9]+).*\" \"\\\\1\" NETGEN_VERSION_TWEAK \"${git_version_string}\")\nstring(REGEX REPLACE \"^v[0-9]+\\\\.[0-9]+\\\\.[0-9]+\\\\-[0-9]+\\\\-([0-9a-z]+).*\" \"\\\\1\" NETGEN_VERSION_HASH \"${git_version_string}\")\n\nset(NETGEN_VERSION_SHORT ${NETGEN_VERSION_MAJOR}.${NETGEN_VERSION_MINOR}.${NETGEN_VERSION_PATCH})\nset(NETGEN_VERSION_LONG ${NETGEN_VERSION_SHORT}-${NETGEN_VERSION_TWEAK}-${NETGEN_VERSION_HASH})\n\nif(NETGEN_VERSION_TWEAK)\n  # no release version - nightly build\n  set(NETGEN_VERSION ${NETGEN_VERSION_LONG})\nelse()\n  # TWEAK is 0 -> current version has a tag assigned\n  set(NETGEN_VERSION ${NETGEN_VERSION_SHORT})\nendif()\n\nset(NETGEN_VERSION_LONG ${NETGEN_VERSION_SHORT}-${NETGEN_VERSION_TWEAK}-${NETGEN_VERSION_HASH})\n\nif(NOT NETGEN_VERSION_GIT)\n    set(NETGEN_VERSION_GIT ${NETGEN_VERSION_LONG})\nendif()\n\nif(NOT NETGEN_VERSION_PYTHON)\n    set(NETGEN_VERSION_PYTHON ${NETGEN_VERSION_TWEAK})\nendif()\n\n\nset(version_file ${BDIR}/netgen_version.hpp)\nset(new_version_file_string \"\\\n#ifndef NETGEN_VERSION_HPP_INCLUDED\n#define NETGEN_VERSION_HPP_INCLUDED\n#define NETGEN_VERSION \\\"${NETGEN_VERSION}\\\"\n#define NETGEN_VERSION_MAJOR ${NETGEN_VERSION_MAJOR}\n#define NETGEN_VERSION_MINOR ${NETGEN_VERSION_MINOR}\n#define NETGEN_VERSION_PATCH ${NETGEN_VERSION_PATCH}\n#define NETGEN_VERSION_TWEAK ${NETGEN_VERSION_TWEAK}\n#define NETGEN_VERSION_HASH \\\"${NETGEN_VERSION_HASH}\\\"\n#endif // NETGEN_VERSION_HPP_INCLUDED\n\")\nif(EXISTS ${version_file})\n  file(READ ${version_file} old_version_file_string )\n  if(${old_version_file_string} STREQUAL ${new_version_file_string})\n  else()\n    file(WRITE ${BDIR}/netgen_version.hpp ${new_version_file_string})\n  endif()\nelse()\n    file(WRITE ${BDIR}/netgen_version.hpp ${new_version_file_string})\nendif()\n\nfile(GENERATE OUTPUT netgen_config.hpp CONTENT\n\"\\\n#ifndef NETGEN_CONFIG_HPP_INCLUDED___\n#define NETGEN_CONFIG_HPP_INCLUDED___\n\n#define NETGEN_USE_NATIVE_ARCH          $<BOOL:${USE_NATIVE_ARCH}>\n#define NETGEN_USE_GUI                  $<BOOL:${USE_GUI}>\n#define NETGEN_USE_PYTHON               $<BOOL:${USE_PYTHON}>\n#define NETGEN_USE_MPI                  $<BOOL:${USE_MPI}}>\n#define NETGEN_USE_MPI4PY               $<BOOL:${USE_MPI4PY}>\n#define NETGEN_USE_OCC                  $<BOOL:${USE_OCC}}>\n#define NETGEN_USE_JPEG                 $<BOOL:${USE_JPEG}}>\n#define NETGEN_USE_MPEG                 $<BOOL:${USE_MPEG}}>\n#define NETGEN_USE_CGNS                 $<BOOL:${USE_CGNS}}>\n#define NETGEN_USE_NUMA                 $<BOOL:${USE_NUMA}}>\n#define NETGEN_INTEL_MIC                $<BOOL:${USE_INTEL_MIC}}>\n#define NETGEN_INSTALL_PROFILES         $<BOOL:${INSTALL_PROFILES}>\n#define NETGEN_USE_CCACHE               $<BOOL:${USE_CCACHE}}>\n#define NETGEN_USE_INTERNAL_TCL         $<BOOL:${USE_INTERNAL_TCL}>\n#define NETGEN_ENABLE_UNIT_TESTS        $<BOOL:${ENABLE_UNIT_TESTS}>\n#define NETGEN_ENABLE_CPP_CORE_GUIDELINES_CHECK $<BOOL:${ENABLE_CPP_CORE_GUIDELINES_CHECK}>\n#define NETGEN_USE_SPDLOG               $<BOOL:${USE_SPDLOG}>\n#define NETGEN_DEBUG_LOG                $<BOOL:${DEBUG_LOG}>\n#define NETGEN_USE_CHECK_RANGE          $<BOOL:${CHECK_RANGE}>\n#define NETGEN_BUILD_STUB_FILES         $<BOOL:${BUILD_STUB_FILES}>\n#define NETGEN_BUILD_FOR_CONDA          $<BOOL:${BUILD_FOR_CONDA}>\n#define NETGEN_SHARED_LIBRARY_SUFFIX    \\\"${CMAKE_SHARED_LIBRARY_SUFFIX}\\\"\n\n#endif // NETGEN_CONFIG_HPP_INCLUDED___\n\")\n"
  },
  {
    "path": "cmake/mic.cmake",
    "content": "set(CMAKE_SYSTEM_NAME Linux)\nset(CMAKE_SYSTEM_PROCESSOR k1om)\nset(CMAKE_SYSTEM_VERSION 1)\n\n# specify the cross compiler\nset(CMAKE_C_COMPILER   icc)\nset(CMAKE_CXX_COMPILER icpc)\nset(MPI_C_COMPILER mpiicc)\nset(_CMAKE_TOOLCHAIN_PREFIX  x86_64-k1om-linux-)\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -mmic\")\nset(CMAKE_CXX_LINK_FLAGS \"${CMAKE_CXX_LINK_FLAGS} -limf -lsvml -lirng -lintlc\")\n\n# where is the target environment \nset(CMAKE_FIND_ROOT_PATH /usr/linux-k1om-4.7)\n\n"
  },
  {
    "path": "cmake/netgen_fixup.cmake",
    "content": "include(BundleUtilities)\nfunction(netgen_fixup_bundle app libs dirs)\n  message(STATUS \"fixup_bundle\")\n  message(STATUS \"  app='${app}'\")\n  message(STATUS \"  libs='${libs}'\")\n  message(STATUS \"  dirs='${dirs}'\")\n\n  get_bundle_and_executable(\"${app}\" bundle executable valid)\n  if(valid)\n    get_filename_component(exepath \"${executable}\" PATH)\n\n    message(STATUS \"fixup_bundle: preparing...\")\n    get_bundle_keys(\"${app}\" \"${libs}\" \"${dirs}\" keys)\n\n    message(STATUS \"fixup_bundle: copying...\")\n    list(LENGTH keys n)\n    math(EXPR n ${n}*2)\n\n    set(i 0)\n    foreach(key ${keys})\n      math(EXPR i ${i}+1)\n      if(${${key}_COPYFLAG})\n        set(item \"${${key}_ITEM}\")\n        if(item MATCHES \"[^/]+\\\\.framework/\")\n          copy_resolved_framework_into_bundle(\"${${key}_RESOLVED_ITEM}\"\n            \"${${key}_RESOLVED_EMBEDDED_ITEM}\")\n        else()\n          copy_resolved_item_into_bundle(\"${${key}_RESOLVED_ITEM}\"\n            \"${${key}_RESOLVED_EMBEDDED_ITEM}\")\n        endif()\n      endif()\n    endforeach()\n\n    message(STATUS \"fixup_bundle: fixing...\")\n    foreach(key ${keys})\n      math(EXPR i ${i}+1)\n      message(STATUS \"${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'\")\n      fixup_bundle_item(\"${${key}_RESOLVED_EMBEDDED_ITEM}\" \"${exepath}\" \"${dirs}\")\n    endforeach()\n\n    message(STATUS \"fixup_bundle: cleaning up...\")\n    clear_bundle_keys(keys)\n\n  else()\n    message(SEND_ERROR \"error: fixup_bundle: not a valid bundle\")\n  endif()\n\n  message(STATUS \"fixup_bundle: done\")\nendfunction()\n"
  },
  {
    "path": "depcomp",
    "content": "#! /bin/sh\n\n# depcomp - compile a program generating dependencies as side-effects\n# Copyright 1999, 2000 Free Software Foundation, Inc.\n\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\n# 02111-1307, USA.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.\n\nif test -z \"$depmode\" || test -z \"$source\" || test -z \"$object\"; then\n  echo \"depcomp: Variables source, object and depmode must be set\" 1>&2\n  exit 1\nfi\n# `libtool' can also be set to `yes' or `no'.\n\ndepfile=${depfile-`echo \"$object\" | sed 's,\\([^/]*\\)$,.deps/\\1,;s/\\.\\([^.]*\\)$/.P\\1/'`}\ntmpdepfile=${tmpdepfile-`echo \"$depfile\" | sed 's/\\.\\([^.]*\\)$/.T\\1/'`}\n\nrm -f \"$tmpdepfile\"\n\n# Some modes work just like other modes, but use different flags.  We\n# parameterize here, but still list the modes in the big case below,\n# to make depend.m4 easier to write.  Note that we *cannot* use a case\n# here, because this file can only contain one case statement.\nif test \"$depmode\" = hp; then\n  # HP compiler uses -M and no extra arg.\n  gccflag=-M\n  depmode=gcc\nfi\n\nif test \"$depmode\" = dashXmstdout; then\n   # This is just like dashmstdout with a different argument.\n   dashmflag=-xM\n   depmode=dashmstdout\nfi\n\ncase \"$depmode\" in\ngcc3)\n## gcc 3 implements dependency tracking that does exactly what\n## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like\n## it if -MD -MP comes after the -MF stuff.  Hmm.\n  \"$@\" -MT \"$object\" -MD -MP -MF \"$tmpdepfile\"\n  stat=$?\n  if test $stat -eq 0; then :\n  else\n    rm -f \"$tmpdepfile\"\n    exit $stat\n  fi\n  mv \"$tmpdepfile\" \"$depfile\"\n  ;;\n\ngcc)\n## There are various ways to get dependency output from gcc.  Here's\n## why we pick this rather obscure method:\n## - Don't want to use -MD because we'd like the dependencies to end\n##   up in a subdir.  Having to rename by hand is ugly.\n##   (We might end up doing this anyway to support other compilers.)\n## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like\n##   -MM, not -M (despite what the docs say).\n## - Using -M directly means running the compiler twice (even worse\n##   than renaming).\n  if test -z \"$gccflag\"; then\n    gccflag=-MD,\n  fi\n  \"$@\" -Wp,\"$gccflag$tmpdepfile\"\n  stat=$?\n  if test $stat -eq 0; then :\n  else\n    rm -f \"$tmpdepfile\"\n    exit $stat\n  fi\n  rm -f \"$depfile\"\n  echo \"$object : \\\\\" > \"$depfile\"\n  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n## The second -e expression handles DOS-style file names with drive letters.\n  sed -e 's/^[^:]*: / /' \\\n      -e 's/^['$alpha']:\\/[^:]*: / /' < \"$tmpdepfile\" >> \"$depfile\"\n## This next piece of magic avoids the `deleted header file' problem.\n## The problem is that when a header file which appears in a .P file\n## is deleted, the dependency causes make to die (because there is\n## typically no way to rebuild the header).  We avoid this by adding\n## dummy dependencies for each header file.  Too bad gcc doesn't do\n## this for us directly.\n  tr ' ' '\n' < \"$tmpdepfile\" |\n## Some versions of gcc put a space before the `:'.  On the theory\n## that the space means something, we add a space to the output as\n## well.\n## Some versions of the HPUX 10.20 sed can't process this invocation\n## correctly.  Breaking it into two sed invocations is a workaround.\n    sed -e 's/^\\\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> \"$depfile\"\n  rm -f \"$tmpdepfile\"\n  ;;\n\nhp)\n  # This case exists only to let depend.m4 do its work.  It works by\n  # looking at the text of this script.  This case will never be run,\n  # since it is checked for above.\n  exit 1\n  ;;\n\nsgi)\n  if test \"$libtool\" = yes; then\n    \"$@\" \"-Wp,-MDupdate,$tmpdepfile\"\n  else\n    \"$@\" -MDupdate \"$tmpdepfile\"\n  fi\n  stat=$?\n  if test $stat -eq 0; then :\n  else\n    rm -f \"$tmpdepfile\"\n    exit $stat\n  fi\n  rm -f \"$depfile\"\n\n  if test -f \"$tmpdepfile\"; then  # yes, the sourcefile depend on other files\n    echo \"$object : \\\\\" > \"$depfile\"\n\n    # Clip off the initial element (the dependent).  Don't try to be\n    # clever and replace this with sed code, as IRIX sed won't handle\n    # lines with more than a fixed number of characters (4096 in\n    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;\n    # the IRIX cc adds comments like `#:fec' to the end of the\n    # dependency line.\n    tr ' ' '\n' < \"$tmpdepfile\" \\\n    | sed -e 's/^.*\\.o://' -e 's/#.*$//' -e '/^$/ d' | \\\n    tr '\n' ' ' >> $depfile\n    echo >> $depfile\n\n    # The second pass generates a dummy entry for each header file.\n    tr ' ' '\n' < \"$tmpdepfile\" \\\n   | sed -e 's/^.*\\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \\\n   >> $depfile\n  else\n    # The sourcefile does not contain any dependencies, so just\n    # store a dummy comment line, to avoid errors with the Makefile\n    # \"include basename.Plo\" scheme.\n    echo \"#dummy\" > \"$depfile\"\n  fi\n  rm -f \"$tmpdepfile\"\n  ;;\n\naix)\n  # The C for AIX Compiler uses -M and outputs the dependencies\n  # in a .u file.  This file always lives in the current directory.\n  # Also, the AIX compiler puts `$object:' at the start of each line;\n  # $object doesn't have directory information.\n  stripped=`echo \"$object\" | sed -e 's,^.*/,,' -e 's/\\(.*\\)\\..*$/\\1/'`\n  tmpdepfile=\"$stripped.u\"\n  outname=\"$stripped.o\"\n  if test \"$libtool\" = yes; then\n    \"$@\" -Wc,-M\n  else\n    \"$@\" -M\n  fi\n\n  stat=$?\n  if test $stat -eq 0; then :\n  else\n    rm -f \"$tmpdepfile\"\n    exit $stat\n  fi\n\n  if test -f \"$tmpdepfile\"; then\n    # Each line is of the form `foo.o: dependent.h'.\n    # Do two passes, one to just change these to\n    # `$object: dependent.h' and one to simply `dependent.h:'.\n    sed -e \"s,^$outname:,$object :,\" < \"$tmpdepfile\" > \"$depfile\"\n    sed -e \"s,^$outname: \\(.*\\)$,\\1:,\" < \"$tmpdepfile\" >> \"$depfile\"\n  else\n    # The sourcefile does not contain any dependencies, so just\n    # store a dummy comment line, to avoid errors with the Makefile\n    # \"include basename.Plo\" scheme.\n    echo \"#dummy\" > \"$depfile\"\n  fi\n  rm -f \"$tmpdepfile\"\n  ;;\n\nicc)\n  # Must come before tru64.\n\n  # Intel's C compiler understands `-MD -MF file'.  However\n  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c\n  # will fill foo.d with something like\n  #    foo.o: sub/foo.c\n  #    foo.o: sub/foo.h\n  # which is wrong.  We want:\n  #    sub/foo.o: sub/foo.c\n  #    sub/foo.o: sub/foo.h\n  #    sub/foo.c:\n  #    sub/foo.h:\n\n  \"$@\" -MD -MF \"$tmpdepfile\"\n  stat=$?\n  if test $stat -eq 0; then :\n  else\n    rm -f \"$tmpdepfile\"\n    exit $stat\n  fi\n  rm -f \"$depfile\"\n  # Each line is of the form `foo.o: dependent.h'.\n  # Do two passes, one to just change these to\n  # `$object: dependent.h' and one to simply `dependent.h:'.\n  sed -e \"s,^[^:]*:,$object :,\" < \"$tmpdepfile\" > \"$depfile\"\n  sed -e \"s,^[^:]*: \\(.*\\)$,\\1:,\" < \"$tmpdepfile\" >> \"$depfile\"\n  rm -f \"$tmpdepfile\"\n  ;;\n\ntru64)\n   # The Tru64 AIX compiler uses -MD to generate dependencies as a side\n   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.\n   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put \n   # dependencies in `foo.d' instead, so we check for that too.\n   # Subdirectories are respected.\n\n   tmpdepfile1=\"$object.d\"\n   tmpdepfile2=`echo \"$object\" | sed -e 's/.o$/.d/'` \n   if test \"$libtool\" = yes; then\n      \"$@\" -Wc,-MD\n   else\n      \"$@\" -MD\n   fi\n\n   stat=$?\n   if test $stat -eq 0; then :\n   else\n      rm -f \"$tmpdepfile1\" \"$tmpdepfile2\"\n      exit $stat\n   fi\n\n   if test -f \"$tmpdepfile1\"; then\n      tmpdepfile=\"$tmpdepfile1\"\n   else\n      tmpdepfile=\"$tmpdepfile2\"\n   fi\n   if test -f \"$tmpdepfile\"; then\n      sed -e \"s,^.*\\.[a-z]*:,$object:,\" < \"$tmpdepfile\" > \"$depfile\"\n      # That's a space and a tab in the [].\n      sed -e 's,^.*\\.[a-z]*:[ \t]*,,' -e 's,$,:,' < \"$tmpdepfile\" >> \"$depfile\"\n   else\n      echo \"#dummy\" > \"$depfile\"\n   fi\n   rm -f \"$tmpdepfile\"\n   ;;\n\n#nosideeffect)\n  # This comment above is used by automake to tell side-effect\n  # dependency tracking mechanisms from slower ones.\n\ndashmstdout)\n  # Important note: in order to support this mode, a compiler *must*\n  # always write the proprocessed file to stdout, regardless of -o,\n  # because we must use -o when running libtool.\n  test -z \"$dashmflag\" && dashmflag=-M\n  ( IFS=\" \"\n    case \" $* \" in\n    *\" --mode=compile \"*) # this is libtool, let us make it quiet\n      for arg\n      do # cycle over the arguments\n        case \"$arg\" in\n\t\"--mode=compile\")\n\t  # insert --quiet before \"--mode=compile\"\n\t  set fnord \"$@\" --quiet\n\t  shift # fnord\n\t  ;;\n\tesac\n\tset fnord \"$@\" \"$arg\"\n\tshift # fnord\n\tshift # \"$arg\"\n      done\n      ;;\n    esac\n    \"$@\" $dashmflag | sed 's:^[^:]*\\:[ \t]*:'\"$object\"'\\: :' > \"$tmpdepfile\"\n  ) &\n  proc=$!\n  \"$@\"\n  stat=$?\n  wait \"$proc\"\n  if test \"$stat\" != 0; then exit $stat; fi\n  rm -f \"$depfile\"\n  cat < \"$tmpdepfile\" > \"$depfile\"\n  tr ' ' '\n' < \"$tmpdepfile\" | \\\n## Some versions of the HPUX 10.20 sed can't process this invocation\n## correctly.  Breaking it into two sed invocations is a workaround.\n    sed -e 's/^\\\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> \"$depfile\"\n  rm -f \"$tmpdepfile\"\n  ;;\n\ndashXmstdout)\n  # This case only exists to satisfy depend.m4.  It is never actually\n  # run, as this mode is specially recognized in the preamble.\n  exit 1\n  ;;\n\nmakedepend)\n  # X makedepend\n  (\n    shift\n    cleared=no\n    for arg in \"$@\"; do\n      case $cleared in no)\n        set \"\"; shift\n\tcleared=yes\n      esac\n      case \"$arg\" in\n        -D*|-I*)\n\t  set fnord \"$@\" \"$arg\"; shift;;\n\t-*)\n\t  ;;\n\t*)\n\t  set fnord \"$@\" \"$arg\"; shift;;\n      esac\n    done\n    obj_suffix=\"`echo $object | sed 's/^.*\\././'`\"\n    touch \"$tmpdepfile\"\n    ${MAKEDEPEND-makedepend} 2>/dev/null -o\"$obj_suffix\" -f\"$tmpdepfile\" \"$@\"\n  ) &\n  proc=$!\n  \"$@\"\n  stat=$?\n  wait \"$proc\"\n  if test \"$stat\" != 0; then exit $stat; fi\n  rm -f \"$depfile\"\n  cat < \"$tmpdepfile\" > \"$depfile\"\n  tail +3 \"$tmpdepfile\" | tr ' ' '\n' | \\\n## Some versions of the HPUX 10.20 sed can't process this invocation\n## correctly.  Breaking it into two sed invocations is a workaround.\n    sed -e 's/^\\\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> \"$depfile\"\n  rm -f \"$tmpdepfile\" \"$tmpdepfile\".bak\n  ;;\n\ncpp)\n  # Important note: in order to support this mode, a compiler *must*\n  # always write the proprocessed file to stdout, regardless of -o,\n  # because we must use -o when running libtool.\n  ( IFS=\" \"\n    case \" $* \" in\n    *\" --mode=compile \"*)\n      for arg\n      do # cycle over the arguments\n        case $arg in\n\t\"--mode=compile\")\n\t  # insert --quiet before \"--mode=compile\"\n\t  set fnord \"$@\" --quiet\n\t  shift # fnord\n\t  ;;\n\tesac\n\tset fnord \"$@\" \"$arg\"\n\tshift # fnord\n\tshift # \"$arg\"\n      done\n      ;;\n    esac\n    \"$@\" -E |\n    sed -n '/^# [0-9][0-9]* \"\\([^\"]*\\)\".*/ s:: \\1 \\\\:p' |\n    sed '$ s: \\\\$::' > \"$tmpdepfile\"\n  ) &\n  proc=$!\n  \"$@\"\n  stat=$?\n  wait \"$proc\"\n  if test \"$stat\" != 0; then exit $stat; fi\n  rm -f \"$depfile\"\n  echo \"$object : \\\\\" > \"$depfile\"\n  cat < \"$tmpdepfile\" >> \"$depfile\"\n  sed < \"$tmpdepfile\" '/^$/d;s/^ //;s/ \\\\$//;s/$/ :/' >> \"$depfile\"\n  rm -f \"$tmpdepfile\"\n  ;;\n\nmsvisualcpp)\n  # Important note: in order to support this mode, a compiler *must*\n  # always write the proprocessed file to stdout, regardless of -o,\n  # because we must use -o when running libtool.\n  ( IFS=\" \"\n    case \" $* \" in\n    *\" --mode=compile \"*)\n      for arg\n      do # cycle over the arguments\n        case $arg in\n\t\"--mode=compile\")\n\t  # insert --quiet before \"--mode=compile\"\n\t  set fnord \"$@\" --quiet\n\t  shift # fnord\n\t  ;;\n\tesac\n\tset fnord \"$@\" \"$arg\"\n\tshift # fnord\n\tshift # \"$arg\"\n      done\n      ;;\n    esac\n    \"$@\" -E |\n    sed -n '/^#line [0-9][0-9]* \"\\([^\"]*\\)\"/ s::echo \"`cygpath -u \\\\\"\\1\\\\\"`\":p' | sort | uniq > \"$tmpdepfile\"\n  ) &\n  proc=$!\n  \"$@\"\n  stat=$?\n  wait \"$proc\"\n  if test \"$stat\" != 0; then exit $stat; fi\n  rm -f \"$depfile\"\n  echo \"$object : \\\\\" > \"$depfile\"\n  . \"$tmpdepfile\" | sed 's% %\\\\ %g' | sed -n '/^\\(.*\\)$/ s::\t\\1 \\\\:p' >> \"$depfile\"\n  echo \"\t\" >> \"$depfile\"\n  . \"$tmpdepfile\" | sed 's% %\\\\ %g' | sed -n '/^\\(.*\\)$/ s::\\1\\::p' >> \"$depfile\"\n  rm -f \"$tmpdepfile\"\n  ;;\n\nnone)\n  exec \"$@\"\n  ;;\n\n*)\n  echo \"Unknown depmode $depmode\" 1>&2\n  exit 1\n  ;;\nesac\n\nexit 0\n"
  },
  {
    "path": "doc/CMakeLists.txt",
    "content": "INSTALL(FILES ng4.pdf DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX}/doc COMPONENT netgen_doc)\n"
  },
  {
    "path": "doc/element_types.tex",
    "content": "\\documentclass[convert=pdf2svg]{standalone}\n% \\documentclass{article}\n\n\\usepackage[T1]{fontenc}\n\\usepackage{lmodern}\n\\renewcommand{\\familydefault}{\\sfdefault}\n\\usepackage{tikz}\n\\usepackage{tikz-3dplot}\n\\usetikzlibrary{external}\n\\tikzset{external/force remake}\n\\tikzset{external/disable dependency files}\n\\tikzset{external/aux in dpth={false}}\n% uncomment this to generate a figure for each cell type (and change documentclass to article)\n% \\tikzexternalize\n\n\\tikzstyle{vertex} = [circle,draw=black,fill=black,scale = 0.5]\n\\tdplotsetmaincoords{70}{110}\n\n% cnode(tag,x,y,z,label,label_pos)\n\\def\\cnode(#1,#2,#3,#4,#5,#6){\n\\node (#1) at (#2,#3,#4) [vertex,label=#6:$\\mathsf{#5}$] {};\n}\n\n\\pagestyle{empty}\n\n\\begin{document}\n\n\\begin{tabular}{cc}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\nSEGMENT &\nSEGMENT3\n\\\\\n\\tikzsetnextfilename{line}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\draw (n0) -- (n1);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{line3}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\cnode(n2,1,0,0,3,below right);\n\\draw (n0) -- (n2) -- (n1);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nTRIG &\nTRIG6\n\\\\\n\\tikzsetnextfilename{triangle}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\cnode(n2,0,2,0,3,right);\n\\draw (n0) -- (n1) -- (n2) -- (n0);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{triangle6}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\cnode(n2,0,2,0,3,right);\n\\cnode(n3,1,0,0,6,below right);\n\\cnode(n4,1,1,0,4,right);\n\\cnode(n5,0,1,0,5,below right);\n\\draw (n0) -- (n3) -- (n1) -- (n4) -- (n2) -- (n5) -- (n0);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nQUAD &\nQUAD8\n\\\\\n\\tikzsetnextfilename{quad}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,4,below right);\n\\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{quad8}\n\\begin{tikzpicture}[scale = 2]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,2,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,4,below right);\n\\cnode(n4,1,0,0,5,below right);\n\\cnode(n5,2,1,0,8,below right);\n\\cnode(n6,1,2,0,6,below right);\n\\cnode(n7,0,1,0,7,below right);\n\\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n3) -- (n7) -- (n0);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nTET &\nTET10\n\\\\\n\\tikzsetnextfilename{tetra}\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,3,below right);\n\\cnode(n2,0,2,0,2,below right);\n\\cnode(n3,0,0,2,4,right);\n\\draw (n0) -- (n1) -- (n2) -- (n0);\n\\draw (n0) -- (n3);\n\\draw (n1) -- (n3);\n\\draw (n2) -- (n3);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{tetra10} % VTK\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,3,below right);\n\\cnode(n2,0,2,0,2,below right);\n\\cnode(n3,0,0,2,4,right);\n\\cnode(n4,1,0,0,6,below right);\n\\cnode(n5,1,1,0,8,below right);\n\\cnode(n6,0,1,0,5,below right);\n\\cnode(n7,0,0,1,7,below right);\n\\cnode(n8,1,0,1,10,below right);\n\\cnode(n9,0,1,1,9,right);\n\\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n0);\n\\draw (n0) -- (n7) -- (n3);\n\\draw (n1) -- (n8) -- (n3);\n\\draw (n2) -- (n9) -- (n3);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nPYRAMID &\nPYRAMID13\n\\\\\n\\tikzsetnextfilename{pyramid}\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,4,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,2,below right);\n\\cnode(n4,1,1,2,5,right);\n\\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);\n\\draw (n0) -- (n4);\n\\draw (n1) -- (n4);\n\\draw (n2) -- (n4);\n\\draw (n3) -- (n4);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{pyramid13} % VTK != gmsh\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,4,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,2,below right);\n\\cnode(n4,1,1,2,5,right);\n\\cnode(n5,1,0,0,8,below right);\n\\cnode(n6,2,1,0,7,below right);\n\\cnode(n7,1,2,0,9,below right);\n\\cnode(n8,0,1,0,6,below right);\n\\cnode(n9,0.5,0.5,1,10,below right);\n\\cnode(n10,1.5,0.5,1,13,below right);\n\\cnode(n11,1.5,1.5,1,12,below right);\n\\cnode(n12,0.5,1.5,1,11,right);\n\\draw (n0) -- (n5) -- (n1) -- (n6) -- (n2) -- (n7) -- (n3) -- (n8) -- (n0);\n\\draw (n0) -- (n9) -- (n4);\n\\draw (n1) -- (n10) -- (n4);\n\\draw (n2) -- (n11) -- (n4);\n\\draw (n3) -- (n12) -- (n4);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nPRISM &\nPRISM15\n\\\\\n\\tikzsetnextfilename{wedge} % gmsh != VTK\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,3,below right);\n\\cnode(n2,0,2,0,2,below right);\n\\cnode(n3,0,0,2,4,below right);\n\\cnode(n4,2,0,2,6,below right);\n\\cnode(n5,0,2,2,5,below right);\n\\draw (n0) -- (n1) -- (n2) -- (n0);\n\\draw (n3) -- (n4) -- (n5) -- (n3);\n\\draw (n0) -- (n3);\n\\draw (n1) -- (n4);\n\\draw (n2) -- (n5);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{wedge15} % VTK != gmsh\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,3,below right);\n\\cnode(n2,0,2,0,2,below right);\n\\cnode(n3,0,0,2,4,below right);\n\\cnode(n4,2,0,2,6,below right);\n\\cnode(n5,0,2,2,5,below right);\n\\cnode(n6,1,0,0,8,below right);\n\\cnode(n7,1,1,0,9,below right);\n\\cnode(n8,0,1,0,7,below right);\n\\cnode(n9,1,0,2,14,below right);\n\\cnode(n10,1,1,2,15,below right);\n\\cnode(n11,0,1,2,13,below right);\n\\cnode(n12,0,0,1,10,below right);\n\\cnode(n13,2,0,1,12,below right);\n\\cnode(n14,0,2,1,11,below right);\n\\draw (n0) -- (n6) -- (n1) -- (n7) -- (n2) -- (n8) -- (n0);\n\\draw (n3) -- (n9) -- (n4) -- (n10) -- (n5) -- (n11) -- (n3);\n\\draw (n0) -- (n12) -- (n3);\n\\draw (n1) -- (n13) -- (n4);\n\\draw (n2) -- (n14) -- (n5);\n\\end{tikzpicture}\n\\\\[1 em]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\nHEX &\nHEX20\n\\\\\n\\tikzsetnextfilename{hexahedron}\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,4,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,2,below right);\n\\cnode(n4,0,0,2,5,below right);\n\\cnode(n5,2,0,2,8,below right);\n\\cnode(n6,2,2,2,7,below right);\n\\cnode(n7,0,2,2,6,below right);\n\\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);\n\\draw (n4) -- (n5) -- (n6) -- (n7) -- (n4);\n\\draw (n0) -- (n4);\n\\draw (n1) -- (n5);\n\\draw (n2) -- (n6);\n\\draw (n3) -- (n7);\n\\end{tikzpicture}\n&\n\\tikzsetnextfilename{hexahedron20} % VTK != gmsh\n\\begin{tikzpicture}[scale = 2, tdplot_main_coords]\n\\cnode(n0,0,0,0,1,below right);\n\\cnode(n1,2,0,0,4,below right);\n\\cnode(n2,2,2,0,3,below right);\n\\cnode(n3,0,2,0,2,below right);\n\\cnode(n4,0,0,2,5,below right);\n\\cnode(n5,2,0,2,8,below right);\n\\cnode(n6,2,2,2,7,below right);\n\\cnode(n7,0,2,2,6,below right);\n\\cnode(n8,1,0,0,11,below right);\n\\cnode(n9,2,1,0,10,below right);\n\\cnode(n10,1,2,0,12,below right);\n\\cnode(n11,0,1,0,9,below right);\n\\cnode(n12,1,0,2,15,below right);\n\\cnode(n13,2,1,2,14,below right);\n\\cnode(n14,1,2,2,16,below right);\n\\cnode(n15,0,1,2,13,below right);\n\\cnode(n16,0,0,1,17,below right);\n\\cnode(n17,2,0,1,20,below right);\n\\cnode(n18,2,2,1,19,below right);\n\\cnode(n19,0,2,1,18,below right);\n\\draw (n0) -- (n8) -- (n1) -- (n9) -- (n2) -- (n10) -- (n3) -- (n11) -- (n0);\n\\draw (n4) -- (n12) -- (n5) -- (n13) -- (n6) -- (n14) -- (n7) -- (n15) -- (n4);\n\\draw (n0) -- (n16) -- (n4);\n\\draw (n1) -- (n17) -- (n5);\n\\draw (n2) -- (n18) -- (n6);\n\\draw (n3) -- (n19) -- (n7);\n\\end{tikzpicture}\n\n\n\n\\end{tabular}\n\n\\end{document}\n"
  },
  {
    "path": "doc/ng4.tex",
    "content": "%\n% Requires latex and latex2html packages \n%\n% Generate pdf-file with\n% pdflatex ng4.tex\n% \n% Generate html docu with\n% latex2html ng4.tex\n%\n\n\n\\documentclass[12pt]{book}\n\\usepackage{a4, epsf, graphicx}\n\\usepackage{html}\n\n\\title{NETGEN - 4.X}\n\\author{Joachim Sch\\\"oberl}\n\n\n\n\\unitlength=1cm\n\n\\begin{document}\n\\maketitle\n\\tableofcontents\n\n\\chapter{Getting Started}\n\n\nWARNING: DOCUMENTATION IS NOT UP TO DATE\n\n\n\\section{What is NETGEN}\nNETGEN is an automatic mesh generation tool for two and three\ndimensions. Netgen is open source under the conditions of the LGPL.\nIt comes as stand alone programme with graphical user\ninterface, or as C++ library to be linked into an other application.\nNetgen is available for Unix/Linux and Windows 98/NT.  Netgen\ngenerates triangular or quadrilateral meshes in 2D, and tetrahedral\nmeshes in 3D. The input for 2D is described by spline curves, and the\ninput for 3D problems is either defined by constructive solid\ngeometries (CSG), see Chapter \\ref{chap_csg}, or by the standard STL\nfile format.  NETGEN contains modules for mesh optimization and\nhierarchical mesh refinement. Curved elements are supported of arbitrary\norder.\n\n\n\\section{The history of NETGEN}\n%\nThe NETGEN project was started 1994 in the master's programme of\nJoachim Sch\\\"oberl, under supervision of Prof. Ulrich Langer, at the\nDepartment of Computational Mathematics and Optimization, University\nLinz, Austria.  Its further development was supported by the Austrian\nscience Fund ``Fonds zur F\\\"orderung der wissenschaftlichen\nForschung'' (http://www.fwf.ac.at) under projects P 10643-TEC and SFB\n1306.  Starting from 2002, the development continued within the Start\nproject ``hp-FEM'' (http://www.hpfem.jku.at) granted by the FWF.  In\n2006, the Netgen development moved together with J.~Sch\\\"oberl to RWTH\nAachen University, Germany (http://www.mathcces.rwth-aachen.de/netgen).\n\n\n\\section{How to receive NETGEN}\n%\nThe latest NETGEN source code release is available from sourceforge\n\\begin{center}\nhttp://sourceforge.net/projects/netgen-mesher\n\\end{center}\n\nThere are file releases, as well as a public SVN repository containing\nthe latest sources.\n\nThe latest NETGEN Windows executable is available from \n\\begin{center}\nhttp://www.mathcces.rwth-aachen.de/netgen\n\\end{center}\n\n\\section{Installing NETGEN}\n\nTHIS SECTION NEEDS UPDATE \n\nINFORMATION AVAILABLE AT http://netgen-mesher.wiki.sourceforge.net/\n\n\\subsection{Installing NETGEN for Unix/Linux}\n\nTo install NETGEN on Unix/Linux you will download the source code and\ncompile it yourself. You need the following libraries:\n\n\\begin{itemize}\n\\item\nThe 3D visualization library {\\bf OpenGL}.\nIt comes with most systems with hardware graphics. The free\nsoftware version mesagl is available from\n\\htmladdnormallink{http://www.mesa3d.org}{http://www.mesa3d.org/}.\n\\item\nThe graphical toolkit {\\bf TclTk} developed by John Ousterhout \n(available from \\htmladdnormallink{http://www.scriptics.com/}{http://www.scriptics.com/}) and its extension {\\bf Tix} available from  \\htmladdnormallink{http://www.sourceforge.com}{http://www.sourceforge.com/}) by Iam Lan. \nNetgen has been tested with version TclTk 8.0 - TclTk 8.4 and Tix 4.6. - Tix 8.2\n\\end{itemize}\nYou can also download these packages from the Netgen site.\n\n\nTo install NETGEN please move into the directory ng4.\nYou set the Unix-variable MACHINE according to\nyour machine/operating system, e.g.\n\\begin{quote}\n\\tt\nsetenv MACHINE LINUX\n\\end{quote}\n%\n(in bash shell you type {\\tt export MACHINE=LINUX}).\nThe Makefile includes the makefile-include\n\\begin{quote}\n\\tt \n        libsrc/makefile.mach.\\$(MACHINE)   \n%$              \n\\end{quote}     \nPlease create/modify the according file,        \n(e.g. copy makefile.mach.LINUX to makefile.mach.SUN). Then you enter \n{\\bf \\tt make} to build the executable. \n\n\\medskip\n\nTo make NETGEN globally available you just copy the binary ``ng'' \nto the global bin - directory. In difference to earlier versions,\nit needs no additional files.\n\n\\subsection{Installing NETGEN for Windows}\n\nNETGEN is available now for Windows in binary form. You download\nthe zip - archive {\\tt ng4win.zip}. After unpacking it with winzip,\nyou can start the executable ``ng4.exe''.\n\n\\subsection{Adding IGES/STEP file support via OpenCascade}\n\\label{subsec_occ}\n\nNETGEN is capable of importing IGES and STEP geometry files. If you want to use this functionality you have the add the OpenCascade library to your NETGEN distribution.\n\nOpenCascade is an open source 3D solid modeller library by OpenCASCADE S.A. You can obtain it from \\htmladdnormallink{http://www.opencascade.org}{http://www.opencascade.org/} (Linux and Windows).\n\nTo compile NETGEN with OpenCascade for Windows just choose the project settings ``Release (OCC)'' and adjust the proper search paths.\n\nFor Linux adjust the directory search paths OCC\\_DIR, OCCINC\\_DIR and OCCLIB\\_DIR in the Makefile and in libsrc/makefile.inc. Then add -DOCCGEOMETRY to the CPLUSPLUSFLAGS2 in libsrc/makefile.mach.\\$(MACHINE). If you use OpenCascade version 5.2 also add -DOCC52 and -DHAVE\\_IOSTREAM to the CPLUSPLUSFLAGS2.\n\n\\subsection{Testing Netgen}\nPlease start Netgen by entering ``ng'' or clicking the ``ng.exe'' icon.\n\nA white window with menu items should appear.  Please load a geometry\nfile by selecting \"File {\\tt ->} Load Geometry\", choose e.g.\ntutorials/cube.geo.  Then press the button \"Generate Mesh\". By keeping\npressed the left, middle or right button of your mouse you can rotate,\nmove or zoom the object.  With ``File {\\tt->} Export Mesh'' you can\nsave the mesh file.\n\n\n\\chapter{Constructive Solid Geometry (CSG)}\n\\label{chap_csg}\n%\nThe CSG input format is a useful geometry format for small and\nmedium size geometries. One defines the geometry by writing an\nASCII file in a text editor.\n\nThe geometry is defined by the Eulerian operations (union,\nintersection and complement) from primitives. A complete list of\navailable primitives is given in Section~\\ref{sec_primitives}.\n\nThe following input describes a cube:\n\\begin{quote}\n\\begin{verbatim}\n# A cube\nalgebraic3d\nsolid cube = orthobrick (0, 0, 0; 1, 1, 1);\ntlo cube;\n\\end{verbatim}\n\\end{quote}\nLines starting with $\\#$ are comment lines. Every CSG file must contain the\nkeyword {\\tt algebraic3d} before any non-comment line.\nThe keyword {\\tt solid} defines a named solid, here the solid {\\it cube}\nis defined. A solid is defined by the Eulerian operations applied to \nprimitives. Here, the solid is just the primitive defined by {\\tt orthobrick}.\nThis is a brick parallel to the axis, specified by the minimal $x$, $y$, and\n$z$ coordinates, and the maximal $x$, $y$, and $z$ coordinates. The present\ndefinition gives the cube $[0,1]^3$. Finally, the definition {\\tt tlo cube}\ndeclares the solid {\\it cube} as a top-level-object, what is necessary for\nmeshing.\n\nPlease start netgen with the geometry file above by entering\n\\begin{quote}\nng cube.geo\n\\end{quote}\nInstead, you can also load the geometry from the file menu. You will\nsee a blue cube, which you can rotate by keeping the left mouse button\npressed. Pressing the big {\\bf generate mesh} button will result in a\n(very coarse) mesh of that cube. \n\nInstead of using the primitive {\\tt orthobrick}, one can also specify\na cube by intersecting six halfspaces (called planes). Each primitive\n{\\tt plane} is given by an arbitrary point in the plane, and a outward\nvector, not necessarily a unit vector. The six halfspaces are intersected\nby the keyword {\\tt and}. The following input gives an equivalent result:\n\n\\begin{quote}\n\\begin{verbatim}\n# A cube\nalgebraic3d\nsolid cube = plane (0, 0, 0; 0, 0, -1) \n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\ntlo cube;\n\\end{verbatim}\n\\end{quote}\n\nTo drill a hole though the cube, we will intersect the cube\nand the complement of a cylinder. A cylinder is defined by two points\non the central axis, and the radius.  Please note, a cylinder is\nunderstood as an infinitely long cylinder (although the visualization\nmay suggest a finite cylinder):\n\\begin{quote}\n\\begin{verbatim}\n# cube with hole\nalgebraic3d\nsolid cubehole = orthobrick (0, 0, 0; 1, 1, 1)\n         and not cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.1);\ntlo cubehole;\n\\end{verbatim}\n\\end{quote}\n\nLike {\\tt and} denotes the intersection, {\\tt or} denotes the union:\n\\begin{quote}\n\\begin{verbatim}\nsolid cubeball = orthobrick (0, 0, 0; 1, 1, 1)\n        or sphere (0, 0, 0; 0.5) -maxh=0.2;\n\\end{verbatim}\n\\end{quote}\nThe flag {\\tt -maxh=0.2} assigns the maximal mesh size of $0.2$ to\nthe solid. The current version, NG4.1, uses the mesh size assigned to\nthe main solid of the top-level-object for the domain. Future version\nwill contain more possibilities to define mesh-sizes for parts of a\ndomain.\n\nIt is possible to define geometries with several sub-domains, simply\nby declaring several tlos: \n\\begin{quote}\n\\begin{verbatim}\nalgebraic3d\nsolid cube = orthobrick (0, 0, 0; 1, 1, 1);\nsolid cyl = cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.1);\nsolid dom1 = cube and not cyl;\nsolid dom2 = cube and cyl;\n\ntlo dom1 -col=[0,0,1] -transparent;\ntlo dom2 -col=[1,0,0];\n\\end{verbatim}\n\\end{quote}\nThis example show also solid trees involving previously defined named\nsolids. Top-level-objects can be assigned a color specified by the\namount of red, green and blue (RGB) values. The flag {\\tt\n  -transparent} makes the solid appear transparent.\n\n\nIt is possible to specify boundary condition numbers for individual\nsurfaces of a solid. The flag {\\tt -bc} assigns the bc to all \nsurfaces of that solid-tree. If several flags are given the one closest\nto the leaves of the tree dominates. The following file defines a \ncube, with $bc=1$ at the bottom, $bc=2$ at the top, and $bc=3$ for \nall other surfaces:\n\n\\begin{quote}\n\\begin{verbatim}\nalgebraic3d\n\nsolid bottom = plane (0, 0, 0; 0, 0, -1) -bc=1;\nsolid top    = plane (1, 1, 1; 0, 0,  1) -bc=2;\nsolid cube = bottm and top \n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0) -bc=3;\n\ntlo cube;\n\\end{verbatim}\n\\end{quote}\n\n\n\n\\section{Curves}\nFor the construction of some of the primitives in the following section it is necessary to define 2D or\n3D curves, which are given in terms of straight lines and of quadratic rational spline patches. A line is given\nby the two endpoints, a spline patch by three d'Boor points. The patch is an elliptic arc from point 1 to point 3,\nsuch that the lines 1--2 and 2--3 are tangents.\n\nA 2D curve is defined as\n\\begin{quote}\n\\samepage\n\\tt\n\\begin{tabbing}\naaa\\=aaa\\=aaa\\=aaa\\=aaa\\=aaa\\= \\kill\ncurve2d $name$ = ($np$;\\\\\n\\>\\> $x_1$, $y_1$;\\\\\n\\>\\> \\ldots\\\\\n\\>\\> $x_{np}$, $y_{np}$;\\\\\n\\>\\> $ns$;\\\\\n\\>\\> [ 2 | 3 ], $p_{1,1}$, $p_{1,2}$ [, $p_{1,3}$];\\\\ \n\\>\\> \\ldots\\\\\n\\>\\> [ 2 | 3 ], $p_{ns,1}$, $p_{ns,2}$ [, $p_{ns,3}$]); \n\\end{tabbing}\n\\end{quote}\nThe number of points is given by $np$, the number of segments by $ns$. Each point is\ngiven by its coordinates, each segment by the number of points \n(2 for line segments, 3 for spline patches) and the pointnumbers.\n\nThe 3D curves are given analogously by\n\\begin{quote}\n\\samepage\n\\tt\n\\begin{tabbing}\naaa\\=aaa\\=aaa\\=aaa\\=aaa\\=aaa\\= \\kill\ncurve3d $name$ = ($np$;\\\\\n\\>\\> $x_1$, $y_1$, $z_1$;\\\\\n\\>\\> \\ldots\\\\\n\\>\\> $x_{np}$, $y_{np}$, $z_{np}$;\\\\\n\\>\\> $ns$;\\\\\n\\>\\> [ 2 | 3 ], $p_{1,1}$, $p_{1,2}$ [, $p_{1,3}$];\\\\ \n\\>\\> \\ldots\\\\\n\\>\\> [ 2 | 3 ], $p_{ns,1}$, $p_{ns,2}$ [, $p_{ns,3}$]); \n\\end{tabbing}\n\\end{quote}\n\n\n\n\\section{Available Primitives}\n\\label{sec_primitives}\nNetgen %4.1 \nsupports the following primitives:\n\\begin{enumerate}\n\\item A halfspace, i.e., a plane and everything on one side of it,\n  given by an arbitrary point~$p = (p_x, p_y, p_z)$ in the plane and\n  an outside normal vector~$n = (n_x, n_y, n_z)$, not necessarily a\n  unit vector:\n  \\begin{quote}\n    \\tt\n    plane ( $p_x$, $p_y$, $p_z$ ; $n_x$, $n_y$, $n_z$ )\n  \\end{quote}\n  \n\\item \n  A cylinder of infinite length, given by two points~$a=(a_x, a_y,a_z)$\n  and $b=(b_x, b_y, b_z)$ on the central axis and the radius $r$:\n  \\begin{quote}\n    \\tt cylinder ( $a_x$, $a_y$, $a_z$ ; $b_x$, $b_y$, $b_z$ ; $r$ )\n  \\end{quote}\n  \n\\item \n  A sphere, given by the center~ $c=(c_x,c_y,c_z)$ and the radius~$r$:\n  \\begin{quote}\n    \\tt\n    sphere ( $c_x$, $c_y$, $c_z$ ; $r$ )\n  \\end{quote}\n \n\\item\n  An elliptic cylinder, given by the point $c=(c_x, c_y, c_z)$ on the main axis, \n  and the vectors $v$ and $w$ of the long and short axis of the ellipse, respectively:\n  \\begin{quote}\n    \\tt\n    ellipticcylinder ($c_x$, $c_y$, $c_z$ ; $v_x$, $v_y$, $v_z$ ; $w_x$, $w_y$, $w_z$)\n  \\end{quote}\n\n\\item\n  An ellipsoid, given by the center $c=(c_x, c_y, c_z)$,\n  and the vectors $u$, $v$ and $w$ of the main axis of the ellipsoid:\n  \\begin{quote}\n    \\tt\n    ellipsoid ($c_x$, $c_y$, $c_z$ ; $u_x$, $u_y$, $u_z$; $v_x$, $v_y$, $v_z$ ; $w_x$, $w_y$, $w_z$)\n  \\end{quote}\n\n \n\\item A cone is given by two points on the central axis and the two\n  corresponding radii.  It is not possible to mesh the top of the cone\n  yet, it must be cut off.\n  \\begin{quote}\n    \\tt\n    cone ( $a_x$, $a_y$, $a_z$ ; $r_a$; $b_x$, $b_y$, $b_z$ ; $r_b$  )\n  \\end{quote}\n  \n\\item A orthobrick is a brick parallel to the coordinate axis. It is\n  specified by two opposite corner points $a = (a_x, a_y, a_z)$ and\n  $b = (b_x, b_y, b_z)$:\n  \\begin{quote}\n    \\tt\n    orthobrick ( $a_x$, $a_y$, $a_z$ ; $b_x$, $b_y$, $b_z$  )\n  \\end{quote}\n  \n\\item A polyhedron is defined by a set of triangles forming\n  a closed polyhedron. First, a set of points is defined, then\n  the triangles are given by point indices. The triangles must be\n  oriented counter-clockwise when looking onto the object. The\n  following polyhedron describes a tetrahedron:\n  \\begin{quote}\n\\begin{verbatim}\nalgebraic3d\nsolid poly = polyhedron (0,0,0; 1,0,0; 0,1,0; 0,0,1 ;;\n                         1,3,2 ; 1,4,3; 1,2,4 ; 2,3,4 );\ntlo poly;\n\\end{verbatim}\n  \\end{quote}\n\n\\item A body of extrusion is defined by its profile \n(which has to be a closed, \\textit{clockwise} oriented 2D curve), by a path (a 3D curve) and a\nvector $d$. It is constructed as follows. Take a point $p$ on the path and denote the (unit-) tangent of the path in this point by $t$.\nIf we cut the body by the plane given by $p$ and $t$ as normal vector, the cut is the profile. \nThe profile is oriented by the (local) y-direction $\\bar{y} := d - (d \\cdot t) t$ and the (local) x-direction $\\bar{x} := t \\times \\bar{y}$. The\nsyntax is:\n\\begin{quote}\n  \\tt\n  extrusion ( <name of pathcurve>; <name of profilecurve>; $d_x$, $d_y$, $d_z$ )\n\\end{quote}\nThe following points have to be noticed:\n\\begin{itemize}\n\\item If the path is not closed, then also the body is NOT closed. In this case e.g.\\ planes or orthobricks have to be used to construct\na closed body.\n\\item The path has to be smooth, i.e.\\ the tangents at the end- resp.\\ startpoint of two consecutive spline or line patches have\nto have the same directions.\n\\end{itemize}\n\n\\item A body of revolution is given by two points, defining the axis of revolution, and the 2D curve which is rotated:\n\\begin{quote}\n  \\tt\n  revolution ( $p_{1,x}$, $p_{1,y}$, $p_{1,z}$; $p_{2,x}$, $p_{2,y}$, $p_{2,z}$; <name of curve>)\n\\end{quote}\nThe first point defines the origin of the local 2D coordinate system of the curve. It is assumed, that the curve lies above the\n(local) x-axis, and that it is described \\textit{clockwise}.\n\nIf the curve is not closed, then the start point and the end point have to lie on the x-axis, and the tangents at those points\nhave to be orthogonal to the x-axis.\n\\end{enumerate}\n\n\n\\section{Surface Identification}\nIn Netgen it is possible to construct prismatic meshes between two surfaces, where these surfaces\nhave to be specified explicitly in the .geo file with the command\n\\begin{quote}\n  \\tt\n  identify closesurfaces <surface1> <surface2>;\n\\end{quote}\n(this feature originally was intended for close surface, which is the reason for the command name).\n\\paragraph{Optional parameters:} (selection)\n\\begin{itemize}\n\\item \\texttt{-tlo=<name of top level object>}\\\\\nthe prisms are only constructed between two faces of a tlo.\n\\item \\texttt{-direction=[<x>,<y>,<z>]}\\\\\nThis parameter has to be used if \\textbf{skew prisms} should be built. In this case netgen ``needs help'' by the user,\nit needs to know the direction of identification.\n\n\\textit{Example:} We start with a cylinder with the axis given by the points $(-1,0,4)$ and $(4,10,1)$. This cylinder\nis cut by the planes \\texttt{p1} and \\texttt{p2} (which are not necessarily normal to the axis and not necessarily parallel)\nand we want to build prisms between\nthese planes. Then the command would, e.g., look like\n\\begin{quote}\n\\tt identify closesurfaces p1 p2 -direction=[5,10,-3]\n\\end{quote}\n\\end{itemize}\n\n\n\n\n\n\n\n\\section{Known problems and work-arounds}\n\\subsection{Interfaces}\nA airdomain with two connected interior parts may be described by\n\\begin{quote}\n\\begin{verbatim}\nalgebraic3d\n\nsolid cube = orthobrick (0, 0, 0; 1, 1, 1);\nsolid part1 = orthobrick (0.2, 0.2, 0.2; 0.5, 0.8, 0.8);\nsolid part2 = orthobrick (0.5, 0.2, 0.2; 0.8, 0.8, 0.8);\nsolid air = cube and not part1 and not part2;\n\ntlo air;\ntlo part1;\ntlo part2;\n\\end{verbatim}\n\\end{quote}\nThe problem is, that a domain is an open domain. Thus, the domain\n{\\it air} is not only the outer part, but also the interface between\n{\\it part1} and {\\it part2}. The result is unspecified. To fix this\nproblem, one can define the {\\it air}-domain by cutting out one big\nbrick:\n\\begin{quote}\n\\begin{verbatim}\nsolid air = cube and not othrobrick  (0.2, 0.2, 0.2; 0.8, 0.8, 0.8);\n\\end{verbatim}\n\\end{quote}\n\n\\subsection{Degenerated edges}\nDegenerated edges are found sometimes, but some still cause troubles.\nA sphere on top of a cylinder my be described by:\n\\begin{quote}\n\\begin{verbatim}\nsolid cyl = cylinder (0, 0, 0; 1, 0, 0; 0.5)\n        and plane (0, 0, 0; -1, 0, 0)\n        and plane (1, 0, 0;  1, 0, 0);\nsolid main = cyl or sphere (1, 0, 0; 0.5);\ntlo main;\n\\end{verbatim}\n\\end{quote}\nThe edge is a degenerated one. A work-around is to split the \ndomain (artificially) into two non-degenerated parts:\n\\begin{quote}\n\\begin{verbatim}\nsolid cyl = cylinder (0, 0, 0; 1, 0, 0; 0.5)\n        and plane (0, 0, 0; -1, 0, 0)\n        and plane (1, 0, 0;  1, 0, 0);\nsolid hemisphere = sphere (1, 0, 0; 0.5) and not plane (1, 0, 0; -1, 0, 0);\ntlo cyl;\ntlo hemisphere;\n\\end{verbatim}\n\\end{quote}\n\n\n\n\n\n\\chapter{Other Geometry Formats}\n\n\\section{Using IGES/STEP Geometries}\n%\nIGES and STEP are standard exchange formats for CAD files. Contrary to the STL format, IGES and STEP deliver an exact representation of the geometry and do not approximate it. In order to use IGES/STEP geometries you have to install NETGEN with the OpenCascade Geometry Kernel as described in \\ref{subsec_occ}. Most solid modellers can export IGES or STEP files. However, often these files are not as exact as a mesher needs them to be. So is meshing fails, try repairing the model via {\\bf IGES/STEP Topology Explorer/Doctor}.\n\n\\section{Using STL Geometries}\n%\nSTL is a standardized file format to describe (approximate) geometies\nby triangulated surfaces. It is useful to describe complicated parts\nwhich are modeled with some CAD programmes. Also, some users have written\ntheir own (C) programmes to define STL geometries, where was not so easy\nto use the CSG format. The syntax of STL files is as follows\n\\begin{quote}\n(not available yet. please figure out the syntax from the examples)\n\\end{quote}\n\nWe found that many STL geometries have some difficulties. Some of them\ncan be corrected (removed) by the {\\bf STL - Doctor}. Please see the\ncorresponding manual pages (not available yet).\n\n\n\\section{2D Spline Geometry}\n%\nThe extension for 2D spline geometry is ``.in2d''.\n\nThe boundary is given in terms of straight lines and of quadratic rational\nspline patches. \nA line is given by the two endpoints, a spline patch by 3 d'Boor\npoints. The patch is an elliptic arc from point 1 to point 3, such that\nthe lines 1-2 and 2-3 are tangents.\n\nIt is possible to use different subdomains with this format.\n\nThis file format also supports a priori mesh grading. To the spline \npoint i one adds a local refinement factor {\\tt rp}$_i$ . Close to \nthis point the mesh-size $h(x)$ is {\\tt h}$_{Glob}$ / {\\tt rp}$_i$ .\nThe global parameter {\\tt grading} describes how fast the mesh-size decreases.\nThe gradient of the local mesh-size function $h(x)$ is bounded by\n$| \\nabla_x h(x)| \\leq \\mbox{grading}^{-1}$ \nAlso a refinement by a factor {\\tt rs}$_i$ > 1 along the whole \nsegment i is possible.\nThe file looks like:\n%\n\\begin{quote}\n\\samepage\n\\tt \nsplinecurves2d   \\\\\ngrading   \\\\\nnp   \\\\\nx$_1$ y$_1$ rp$_1$ \\\\\n...   \\\\\nx$_{np}$ y$_{np}$ rp$_{np}$ \\\\\nns   \\\\\ndil$_1$ dir$_1$ [ 2 | 3 ] pi$_{1,1}$ pi$_{1,2}$ [ pi$_{1,3}$ ] rs$_1$ \\\\\n... \\\\\ndil$_{nl}$ dir$_{nl}$ [ 2 | 3 ] pi$_{nl,1}$ pi$_{nl,2}$ [ pi$_{nl,3}$ ] rs$_{nl}$ \\\\\n\\end{quote}\n%\n{\\tt np} is the number of points, {\\tt ns} the number of spline segments.\nEvery segment starts with the domain numbers at the left and at the\nright sides of the segment. Domain number 0 is reserved for the exterior.  \nThen the number of points and two or three point indices follow.\nFinally, the refinement factor along the line follows.\n\n\n\\chapter{Mesh and Solution Formats}\n\nYou can export meshes to a couple of file formats. Some are self-defined,\nsome other are standard formats. The self-defined are the following:\n\n\\section{Mesh Size File}\nBy means of a mesh size file you can provide a local mesh size density. The file extension must be {\\it .msz}. If you want to use the mesh size file, you specify it in the ``Meshing Options'', dialog box, page ``Mesh Size''.\n\nThe syntay is:\n\\begin{verbatim}\nnp\nx1   y1   z1   h1\nx2   y2   z2   h2\n....\nxnp  ynp  znp  hnp\nnl\nxs1   ys1   zs1   xe1   ye1   ze1   h1\nxs2   ys2   zs2   xe2   ye2   ze2   h2\n....\nxsnl  ysnl  zsnl  xenl  yenl  zenl  hnl\n\\end{verbatim}\nYou specify {\\tt np} points, given by the $(x_i,y_i,z_i)$-coordinates,\nwhere the mesh size will be reduced at least to $h_i$. You specify\nalso {\\tt nl} line-segments by the start-point and end-point\ncoordinates. The mesh-size along the whole line will be reduced to the given $h_i$.\n\n\\section{Neutral Format}\nThe neutral volume mesh format contains the following sections:\n\n\\begin{enumerate}\n\\item\nnodes \\\\\nAfter the number of nodes there follows a list of $x$, $y$, \nand $z$-coordinates of the mesh-nodes.\n\\item\nvolume elements \\\\\nAfter the number of volume elements there follows the list of tetrahedra.\nEach element is specified by the sub-domain number, and 4 node indices. The\nnode indices start with 1.\n\\item\nsurface elements \\\\ \nAfter the number of surface elements there follows\nthe list of triangles.  Each element is specified by the boundary\ncondition number, and 3 node indices. The node indices start with 1.\n\\end{enumerate}\n\n\n\n\\section{Fepp Format 2D}\nThe Fepp 2D format contains the following sections:\n\n\\begin{enumerate}\n\\item\nboundary segments \\\\\nAfter the number of boundary segments there follows a list of \nsegments. Each segment is specified by the spline - patch number,\nand the two node indices. Counting starts with 1\n\\item\ndomain elements \\\\\nAfter the number of domain elements there follows the list of elements.\nEach element is specified by the sub-domain number, the number of nodes (3 or 4) and the node indices. Counting starts with 1\n\\item\nnodes \\\\\nAfter the number of nodes there follows a list of $x$ and $y$ \n-coordinates of the mesh-nodes.\n\\item\ngeometric information \\\\\nAfter the number of spline patches there follows a list of spline specifications. Each spline patch is given by the 6 coefficients of the describing \nquadratic polynomial equation\n$$\nc_1 x^2 + c_2 y^2 + c_3 xy + c_4 x + c_5 y + c_6 = 0\n$$\n\\end{enumerate}\n\n\\section{Surface triangulaton file}\nOne can export to and import from a surface mesh file. It´s structure\nis as follows:\n\\begin{enumerate}\n\\item\n  {\\tt surfacemesh} \\\\\n  starts with that keyword\n\\item\n  number of points \\\\\n  point coordinates $(x,y,z)$.\n\\item\n  number of surface triangles, \\\\\n  surface triangles oriented counter-clock wise when looking at the \n  object, index starts from 1.\n\\end{enumerate}\n\n\n\n\\section{Solution File Format}\nThe Netgen software includes also a simple visualizer for finite\nelement gridfunctions. It supports scalar fields (e.g. temperature),\nand vector valued fields (flow velocities, mechanical deformations).\nThe solution field is imported by the menu item File $->$ Import Solution.\nIt is important to load the corresponding mesh in advance.\n\nThe format of the solution file is as follows. It consists of an\narbitrary number of blocks of this structure:\n\n\\begin{enumerate}\n\\item\n  {\\tt solution} {\\it function-name} flags\n  \n  {\\tt solution} is the keyword, {\\it function-name} is a string to\n  refer to that functions. The supported flags are\n  \\begin{enumerate}\n  \\item -size=s \\\\\n    number of entries (default: number of mesh-points)\n  \\item -components=c \\\\\n    number of components (default: 1). Mechanical deformations have 3 components.\n  \\item -type=[nodal,element,surfaceelement] \\\\\n    the grid-funciton has nodal values, or one value per volume element,\n    or one value per surface element (default: nodal)\n  \\end{enumerate}\n\\item\n  block of $size \\times components$ values\n\\end{enumerate}\n\nPlease try out to import the solution file 'tutorials/cube.sol' fitting\nto the mesh 'tutorials/cube.vol'.\n\n\n\\chapter{Netgen operations}\nYou can use netgen in interactive mode using its menus, or, you\ncan run netgen in batch-mode using command line arguments.\n\n\\section{Command line arguments}\nCommand line arguments are specified as {\\it -flag=value}.\n\\begin{itemize}\n\\item -help \\newline\nPrints the available command line arguments\n\\item -geofile=filename \\newline\nSpecifies geometry file. Is equivalent to {\\it filename}, i.e., you can\nscip {\\it -geofile=}.\n\\item -meshfile=filename \\newline\nMesh file will be stored in file {\\it filename}.\n\\item -batchmode \\newline\nExit after mesh generation. Otherwise, the GUI will be started\n\\item -V \\newline\nVerbose mode. Prints some additional information \n\\item -verycoarse, -coarse, -moderate, -fine, -veryfine \\newline\nMesh size control\n\\end{itemize}\n\n\\chapter{Using the Graphical User Interface}\nThe Netgen main window looks like:\n\\begin{center}\n\\includegraphics[width=12cm]{pictures/screenshot}\n\\end{center}\nIt consists of the menuline and the button line at the top, the status line at\nthe bottom, and the large drawing window. The menu items will be explained in \n\\ref{sec_menuitems}. The button line provides shot-cuts for common opteration:\n\\begin{itemize}\n\\item Quit \\newline\nTerminate Netgen\n\\item Generate mesh \\newline\nPerform mesh generation \n\\item Stop Meshing \\newline\nStop mesh generation \n\\item Geometry/Edges/Mesh/Solution \\newline\nSwitch between operation modes of visualization.\n\\item Zoom all \\newline\nZooms such that the whole visualization scene fits into the window.\n\\item Center \\newline\nCenter rotation and scaling at marked point, available only in mesh - visuailzation mode.\n\\item Rotate/Move/Zoom\nLeft mouse drag rotates/moves/zooms object.\n\\end{itemize}\n\nThe status line shows information, namely\n\\begin{itemize}\n\\item Points \\newline\nNumber of points in the mesh\n\\item Elements \\newline\nNumber of volume elements (3D) in the mesh\n\\item Surf Elements \\newline\nNumber of surface elements (3D) or inner elements (2d) in the mesh.\n\\item Mem \\newline\nUsed memory in the large memory arena\n\\item Meshing Job, percentage\nDouriing mesh generation, the current job as well as the progress is displayed on the \nright side of the statu line.\n\\end{itemize}\n\nThe drawing window displays the geometry or the mesh. The view\ncan be changed with the mouse:\n\\begin{itemize}\n\\item drag with left button pressed rotates the object,\n\\item drag with middle button pressed moves the object,\n\\item drag with right button pressed zooms the object.\n\\end{itemize}\nThe view can also be changed with the keyboard:\n\\begin{itemize}\n\\item cursor keys rotate the object\n\\item shift + cursor keys move the object\n\\item control + cursor keys zoom the object\n\\end{itemize}\n\nWhen in Mesh - visualization scene, double clicking on triangles mark the\nsurface. The point cursor is set.\n\n\\section{The Netgen menu items}\n\\label{sec_menuitems}\n\\subsection{The menu item {\\em File}}\n\\includegraphics[height=7.8cm]{pictures/menufile} \n\n\\subsection{The menu item {\\em Geometry}}\n\\includegraphics[height=2.7cm]{pictures/menugeometry} \n\n\\subsection{The menu item {\\em Mesh}}\n\\includegraphics[height=9.8cm]{pictures/menumesh} \n\n\\subsection{The menu item {\\em View}}\n\\includegraphics[height=6.0cm]{pictures/menuview} \n\n\\subsection{The menu item {\\em Refinement}}\n\\includegraphics[width=3.2cm]{pictures/menurefinement} \n\n\n\\section{Meshing Options}\n\n\\includegraphics[width=10cm]{pictures/meshingoptions_1} \n\n\\includegraphics[width=10cm]{pictures/meshingoptions_2} \n\n\\includegraphics[width=10cm]{pictures/meshingoptions_3} \n\n\\includegraphics[width=10cm]{pictures/meshingoptions_4} \n\n\\includegraphics[width=10cm]{pictures/meshingoptions_5} \n\n\\includegraphics[width=10cm]{pictures/meshingoptions_6} \n\n\n\\section{Visualization Options}\n\n\n\n% \\chapter{The Algorithms of Netgen}\n%\n% Netgen follows a top down strategy. It starts from computing the\n% corner points (CSG only). Then, the edges are defined and meshed into\n% segments (CSG and STL). Next, the faces are meshed by an advancing front\n% surface mesh generator. After meshing, the faces meshes are optimized.\n% Finally, the individual sub-domains are filled with tets. Therefore, \n% a fast Delaunay algorithm generates most of the elements (about 98 percent).\n% But often it fails for mesh the whole domain, then the slower back-tracking\n% rule-base algorithm takes over. Finally, the volume is optimized by the\n% usual node - movement, element swapping and splitting algorithms.\n\n\n\\chapter{Programming Interfaces}\n%\n\\section{The nginterface}\nBy means of the nginterface one's own simulation code can be \nincluded into the netgen environment. This is particular useful\nfor FEM (FVM,BEM) code developers, since they may profit from the\nnetgen preprocessing and postprocessing possibilities. \n\nPlease download the example Netgen-add-on module {\\it demoapp} and\nfollow the instructions therein\n\n\\section{The nglib}\n\n\n\\subsection{Introduction}\nThe NETGEN mesh generation library {\\it nglib} is available in C++\nsource code and can be compiled for Unix/Linux as well as Win95/98/NT\nand linked to one library file. The interface to the application\nprogramme is by the C language header file {\\it nglib.h}.\n\nThe functionality of nglib is volume mesh generation by a domain given \nby a surface triangulation, and surface mesh generation from a domain \ndescribed by an STL file (standard file format for geometries defined by\ntriangle approximation). It can do mesh optimization as well as mesh \nrefinement. It can generate 4 node tetrahedra and 10 node tetrahedrons\n(with quadratic shape functions). The local mesh size can be defined \nautomatically by geometric features and/or by user specification.\n\n\n\\subsection{The Header File}\n\nThe interface file contains the following type definitions and function\ncalls. All Netgen types and functions start with {\\tt Ng}. Types and\nfunctions have capital initial letters, constants are in capital letters.\n\n\\subsection{Types and Constants}\n\\begin{verbatim}\n\n/// Data type for NETGEN mesh\ntypedef void * Ng_Mesh;\n\n/// Data type for NETGEN STL geomty\ntypedef void * Ng_STL_Geometry;\n\n\n// max number of nodes per element\n#define NG_VOLUME_ELEMENT_MAXPOINTS 10\n\n// implemented element types:\nenum Ng_Volume_Element_Type { NG_TET = 1, NG_PYRAMID = 2, NG_PRISM = 3,\n                              NG_TET10 = 4 };\n\n// max number of nodes per surface element\n#define NG_SURFACE_ELEMENT_MAXPOINTS 6\n\n// implemented element types:\nenum Ng_Surface_Element_Type { NG_TRIG = 1, NG_QUAD = 2, \n                                NG_TRIG6 = 3 };\n\n\nstruct Ng_Meshing_Parameters \n{\n  double maxh;\n  double fineness;   // 0 .. coarse, 1 .. fine\n  int secondorder;\n};\n\nenum Ng_Result { NG_OK = 0, \n                 NG_SURFACE_INPUT_ERROR = 1,\n                 NG_VOLUME_FAILURE = 2, \n                 NG_STL_INPUT_ERROR = 3,\n                 NG_SURFACE_FAILURE = 4 };\n\\end{verbatim}\n\n\n{\\tt Ng\\_Mesh} is a data type representing a Netgen mesh. {\\tt Ng\\_STL\\_Geometry}\nrepresents an STL geometry. One can operate on these data structures by\nthe functions defined below. Netgen can (now and/or in future) work with\nvarious element types defined by generic constants. Several parameters\ncan be specified in the {\\tt Ng\\_Meshing\\_Parameters} structure for \nvolume and/or surface mesh generation. The result of Netgen functions\nis of type {\\tt Ng\\_Result}.\n\n\n\n\\subsection{Initialization}\nPlease call these functions before using netgen functions and after\nusing netgen functions, respectively:\n\\begin{verbatim}\n  // initialize, deconstruct Netgen library:\n  void Ng_Init ();\n  void Ng_Exit ();\n\\end{verbatim}\n\n\n\\subsection{Mesh access}\nNetgen meshes can be processed by the means of the following functions.\nA mesh contains nodes, surface elements and volume elements. Counting\nstarts from 1.\n\n\\begin{verbatim}\n  // Generates new mesh structure\n  Ng_Mesh * Ng_NewMesh ();\n  void Ng_DeleteMesh (Ng_Mesh * mesh);\n  \n  // feeds points, surface elements and volume elements to the mesh\n  void Ng_AddPoint (Ng_Mesh * mesh, double * x);\n  void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et,\n                             int * pi);\n  void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et,\n                            int * pi);\n  \n  // ask for number of points, surface and volume elements\n  int Ng_GetNP (Ng_Mesh * mesh);\n  int Ng_GetNSE (Ng_Mesh * mesh);\n  int Ng_GetNE (Ng_Mesh * mesh);\n\n  \n  //  return point coordinates\n  void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x);\n\n  // return surface and volume element in pi\n  Ng_Surface_Element_Type \n  Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi);\n\n  Ng_Volume_Element_Type\n  Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi);\n\\end{verbatim}\n\n\n\\subsubsection{Mesh Generation}\nThe user can specify the mesh size function by the global parameter\nmaximal mesh size, and can additionally restrict the mesh size in\npoints or cubes. The function {\\tt Ng\\_GenerateVolumeMesh} generates\nthe volume mesh starting from the surface.\n\n\\begin{verbatim}\n  // Defines MeshSize Functions\n  void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h);\n  void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h);\n  void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h);\n  \n  // generates volume mesh from surface mesh\n  Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp);\n\\end{verbatim}\n\n\n\\subsection{STL Geometry}\nA STL geometry can be read from a STL file (ASCII or binary), or can\nbe assembled by providing triangle by triangle. Either, the user\ncan specify the edges of the geometry, or netgen can define edges \nby {\\tt Ng\\_STL\\_MakeEdges} by using an angle criterium.\n\n\\begin{verbatim}\n  // loads geometry from STL file\n  Ng_STL_Geometry * Ng_STL_LoadGeometry (char * filename, int binary = 0);\n\n  // generate new STL Geometry\n  Ng_STL_Geometry * Ng_STL_NewGeometry ();\n  \n  // fills STL Geometry\n  // positive orientation\n  // normal vector may be null-pointer\n  void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, \n                           double * p1, double * p2, double * p3, double * nv);\n\n  // add (optional) edges:\n  void Ng_STL_AddEdge (Ng_STL_Geometry * geom, \n                       double * p1, double * p2);\n\n\n  // after adding triangles (and edges) initialize\n  Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom);\n\n  // automatically generates edges:\n  void Ng_STL_MakeEdges (Ng_STL_Geometry * geom);\n\n    // generates mesh, empty mesh be already created.\n  Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom,\n                                        Ng_Mesh * mesh,\n                                        Ng_Meshing_Parameters * mp);\n\\end{verbatim}\n\n\\subsection{Programming Example}\n\nThe File {\\it ngcore.cc}, see Appendix A, is a simple application\nusing the netgen volume mesh generator. First, the surface mesh\nis read from a file containing point coordinates and surface triangles\n(see e.g. file {\\it cube.surf}). The volume mesh generate is called, \nand the volume mesh is written to the standard output, see file {\\it cube.vol}.\n\n\n\n\\end{document}\n"
  },
  {
    "path": "external_dependencies/.gitignore",
    "content": "*.tar.gz\n"
  },
  {
    "path": "libsrc/CMakeLists.txt",
    "content": "add_subdirectory(core)\nadd_subdirectory(general)\nadd_subdirectory(gprim)\nadd_subdirectory(linalg)\nadd_subdirectory(include)\nadd_subdirectory(meshing)\nif(USE_OCC)\n    add_subdirectory(occ)\nendif(USE_OCC)\nif(USE_STLGEOM)\n    add_subdirectory(stlgeom)\nendif(USE_STLGEOM)\nif(USE_GUI)\n    add_subdirectory(visualization)\nendif(USE_GUI)\nif(USE_INTERFACE)\n    add_subdirectory(interface)\nendif(USE_INTERFACE)\nif(USE_CSG)\n    add_subdirectory(csg)\nendif(USE_CSG)\nif(USE_GEOM2D)\n    add_subdirectory(geom2d)\nendif(USE_GEOM2D)\n"
  },
  {
    "path": "libsrc/core/.clang-tidy",
    "content": "Checks: '*,-cppcoreguidelines-avoid-non-const-global-variables,-llvmlibc-restrict-system-libc-headers,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'\nCheckOptions:\n        - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor\n          value: 1\n        - key: cppcoreguidelines-macro-usage.AllowedRegexp\n          value: NGCORE_*|NETGEN_*|NG_EXCEPTION*\n\nWarningsAsErrors: '*'\n"
  },
  {
    "path": "libsrc/core/CMakeLists.txt",
    "content": "\nadd_library(ngcore ${NGCORE_LIBRARY_TYPE}\n  archive.cpp\n  bitarray.cpp\n  exception.cpp\n  localheap.cpp\n  logging.cpp\n  flags.cpp\n  paje_trace.cpp\n  profiler.cpp\n  table.cpp\n  taskmanager.cpp\n  utils.cpp\n  version.cpp\n  ng_mpi_wrapper.cpp\n  statushandler.cpp\n  )\n\nstring(REPLACE \"|\" \";\" ng_compile_flags_replace_sep \"${NG_COMPILE_FLAGS}\")\ntarget_compile_options(ngcore PUBLIC ${ng_compile_flags_replace_sep})\n\nif(EMSCRIPTEN)\n  set(PYTHON_MODULE_EXTENSION \".so\")\n  target_link_options(ngcore PUBLIC -sALLOW_MEMORY_GROWTH -sENVIRONMENT=web -sWASM_BIGINT -fwasm-exceptions)\n  target_compile_options(ngcore PUBLIC -fwasm-exceptions)\nendif()\n\nif (CMAKE_CXX_COMPILER_ID MATCHES \"GNU\" AND USE_PYTHON)\n  # Python packages on Linux are compiled with the old ABI,\n  # make sure that the same ABI is used in plugins aswell\n  try_run(\n    ret_val can_compile\n    ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_glibcxx_use_cxx11_abi.cpp\n    RUN_OUTPUT_VARIABLE use_glibcxx_cxx11_abi\n    )\n  target_compile_definitions(ngcore PUBLIC -D_GLIBCXX_USE_CXX11_ABI=${use_glibcxx_cxx11_abi})\n  try_run(\n    ret_val can_compile\n    ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_gxx_abi.cpp\n    RUN_OUTPUT_VARIABLE default_cxx_abi_version\n    )\n  if(${can_compile} AND (${ret_val} EQUAL 0))\n    # Different python modules using pybind11 need to use the same C++ ABI version\n    # for compatibility\n    set(cxx_abi_version 17)\n    message(STATUS \"GNU C++ ABI version: ${cxx_abi_version}\")\n    target_compile_options(ngcore PUBLIC \"-fabi-version=${cxx_abi_version}\")\n  endif()\nendif()\n\nif(USE_PYTHON)\n  target_sources(ngcore PRIVATE python_ngcore.cpp)\n  target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON NG_PYTHON PYBIND11_SIMPLE_GIL_MANAGEMENT)\nendif(USE_PYTHON)\n\nif(WIN32)\n  target_compile_options(ngcore PUBLIC /bigobj $<BUILD_INTERFACE:/MP;/W1;/wd4068>)\n  get_WIN32_WINNT(ver)\n  target_compile_definitions(ngcore PUBLIC _WIN32_WINNT=${ver} WNT WNT_WINDOW NOMINMAX MSVC_EXPRESS _CRT_SECURE_NO_WARNINGS HAVE_STRUCT_TIMESPEC WIN32)\n  target_link_options(ngcore PUBLIC /ignore:4273 /ignore:4217 /ignore:4049)\nelse(WIN32)\n  target_link_libraries(ngcore PUBLIC dl)\nendif(WIN32)\n\ntarget_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)\ntarget_include_directories(ngcore INTERFACE $<INSTALL_INTERFACE:${NG_INSTALL_DIR_INCLUDE}> $<INSTALL_INTERFACE:${NG_INSTALL_DIR_INCLUDE}/include>)\n\nif(CHECK_RANGE)\n  target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE)\nendif(CHECK_RANGE)\n\nif(CMAKE_BUILD_TYPE STREQUAL \"Debug\" OR CMAKE_BUILD_TYPE STREQUAL \"DEBUG\")\n  target_compile_definitions(ngcore PUBLIC _DEBUG NETGEN_ENABLE_CHECK_RANGE)\nendif(CMAKE_BUILD_TYPE STREQUAL \"Debug\" OR CMAKE_BUILD_TYPE STREQUAL \"DEBUG\")\n\nif(TRACE_MEMORY)\n  target_compile_definitions(ngcore PUBLIC NETGEN_TRACE_MEMORY)\nendif(TRACE_MEMORY)\n\nif(USE_NUMA)\n    find_library(NUMA_LIBRARY libnuma.so)\n    target_compile_definitions(ngcore PUBLIC USE_NUMA)\n    target_link_libraries(ngcore PRIVATE ${NUMA_LIBRARY})\nendif(USE_NUMA)\n\ninstall(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)\n\ntarget_link_libraries(ngcore PRIVATE \"$<BUILD_INTERFACE:netgen_python>\" ${CMAKE_THREAD_LIBS_INIT})\n\ninstall(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp memtracer.hpp\n  exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.hpp\n  array.hpp taskmanager.hpp concurrentqueue.h localheap.hpp python_ngcore.hpp flags.hpp\n  xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp ngstream.hpp\n  simd.hpp simd_avx.hpp simd_avx512.hpp simd_generic.hpp simd_math.hpp simd_sse.hpp simd_arm64.hpp\n  register_archive.hpp autodiff.hpp autodiffdiff.hpp\n  ng_mpi.hpp ng_mpi_generated_declarations.hpp mpi4py_pycapi.h ng_mpi_native.hpp statushandler.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)\n\nif(ENABLE_CPP_CORE_GUIDELINES_CHECK)\n  set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY \"${DO_CLANG_TIDY}\")\nendif(ENABLE_CPP_CORE_GUIDELINES_CHECK)\n\nadd_dependencies(ngcore ng_generate_version_file)\n\nif(USE_PYTHON)\n  pybind11_add_module(pyngcore MODULE python_ngcore_export.cpp)\n  target_link_libraries(pyngcore PUBLIC ngcore PRIVATE \"$<BUILD_INTERFACE:netgen_python>\")\n  set_target_properties(pyngcore PROPERTIES INSTALL_RPATH \"${NG_RPATH_TOKEN}/../${NETGEN_PYTHON_RPATH}\")\n  if(EMSCRIPTEN)\n    target_link_options(pyngcore PUBLIC -sALLOW_MEMORY_GROWTH -sENVIRONMENT=web -sWASM_BIGINT -fwasm-exceptions)\n  endif(EMSCRIPTEN)\n  install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON}/pyngcore COMPONENT netgen)\nendif(USE_PYTHON)\n\nfunction (build_mpi_variant)\n  set(target ng_${ARGV0})\n  set(include_dir ${ARGV1})\n  message(\"1Building MPI variant: ${ARGV0} ${ARGV1}\")\n  add_library(${target} SHARED ng_mpi.cpp)\n  target_link_libraries(${target} PUBLIC ngcore PRIVATE \"$<BUILD_INTERFACE:netgen_python>\")\n  target_compile_definitions(${target} PUBLIC PARALLEL NG_MPI_WRAPPER)\n  target_include_directories(${target} PRIVATE ${include_dir})\n  set_target_properties(${target} PROPERTIES PREFIX \"\")\n  install(TARGETS ${target} RUNTIME DESTINATION ${NG_INSTALL_DIR_BIN} LIBRARY DESTINATION ${NG_INSTALL_DIR_LIB} COMPONENT netgen)\nendfunction()\n\nif(USE_MPI)\n  target_compile_definitions(ngcore PUBLIC PARALLEL)\n\n  message(STATUS \"Found MPI version\\n${MPI_C_LIBRARY_VERSION_STRING}\")\n\n  if(USE_MPI_WRAPPER)\n    target_compile_definitions(ngcore PUBLIC NG_MPI_WRAPPER)\n    if(MPI_C_LIBRARY_VERSION_STRING MATCHES \"Microsoft MPI.*\")\n      set(MICROSOFT_MPI_INCLUDE_DIR ${MPI_C_HEADER_DIR})\n      set(MICROSOFT_MPI_LIBRARY ${MPI_msmpi_LIBRARY})\n    endif()\n\n    if(MPI_C_LIBRARY_VERSION_STRING MATCHES \"Open MPI.*\")\n      set(OPENMPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})\n    endif()\n\n    if(MPI_C_LIBRARY_VERSION_STRING MATCHES \"MPICH.*\")\n      set(MPICH_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})\n    endif()\n\n    if(MPI_C_LIBRARY_VERSION_STRING MATCHES \"Intel.*\")\n      set(INTEL_MPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})\n    endif()\n\n    if(OPENMPI_INCLUDE_DIR)\n      build_mpi_variant(openmpi ${OPENMPI_INCLUDE_DIR})\n    endif()\n    if(MPICH_INCLUDE_DIR)\n      build_mpi_variant(mpich ${MPICH_INCLUDE_DIR})\n    endif()\n    if(INTEL_MPI_INCLUDE_DIR)\n      build_mpi_variant(intel_mpi ${INTEL_MPI_INCLUDE_DIR})\n      if(WIN32)\n        target_link_libraries(ng_intel_mpi PUBLIC ${INTEL_MPI_LIBRARY})\n      endif()\n    endif()\n    if(MICROSOFT_MPI_INCLUDE_DIR)\n      build_mpi_variant(microsoft_mpi ${MICROSOFT_MPI_INCLUDE_DIR})\n      target_link_libraries(ng_microsoft_mpi PUBLIC ${MICROSOFT_MPI_LIBRARY})\n    endif()\n  else()\n    target_link_libraries(ngcore PUBLIC ${MPI_C_LIBRARIES})\n    target_include_directories(ngcore PUBLIC ${MPI_C_INCLUDE_PATH})\n  endif(USE_MPI_WRAPPER)\n\nendif(USE_MPI)\n\n"
  },
  {
    "path": "libsrc/core/_get_glibcxx_use_cxx11_abi.cpp",
    "content": "#include <iostream>\n\nint main() {\n  #ifdef _GLIBCXX_USE_CXX11_ABI\n  if(_GLIBCXX_USE_CXX11_ABI)\n    std::cout << 1;\n  else\n    std::cout << 0;\n  #else // _GLIBCXX_USE_CXX11_ABI\n    std::cout << 0;\n  #endif // _GLIBCXX_USE_CXX11_ABI\n  return 0;\n}\n"
  },
  {
    "path": "libsrc/core/_get_gxx_abi.cpp",
    "content": "#include <iostream>\n\nint main() {\n  if (__GXX_ABI_VERSION >= 2000 || __GXX_ABI_VERSION < 1000) return 1;\n  std::cout << (__GXX_ABI_VERSION % 100);\n  return 0;\n}\n"
  },
  {
    "path": "libsrc/core/archive.cpp",
    "content": "\n#include \"archive.hpp\"\n#include \"register_archive.hpp\"\n#include \"version.hpp\"\n\n#ifndef WIN32\n#include <cxxabi.h>\n#endif\n\nnamespace ngcore\n{\n  std::map<std::string, detail::ClassArchiveInfo> & GetTypeRegister()\n  {\n    static std::map<std::string, detail::ClassArchiveInfo> type_register;\n    return type_register;\n  }\n  \n  const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)\n  {\n    // if(type_register == nullptr) type_register =\n    // std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();\n    return GetTypeRegister()[classname];\n  }\n  void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info)\n  {\n    // if(type_register == nullptr) type_register =\n    // std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();\n    GetTypeRegister()[classname] = info;\n  }\n  bool Archive :: IsRegistered(const std::string& classname)\n  {\n    // if(type_register == nullptr) type_register =\n    // std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();\n    return GetTypeRegister().count(classname) != 0;\n  }\n\n#ifdef NETGEN_PYTHON\n  pybind11::object CastAnyToPy(const std::any& a)\n  {\n    auto info = Archive::GetArchiveRegister(Demangle(a.type().name()));\n    return info.anyToPyCaster(a);\n  }\n\n  std::any CastPyToAny(pybind11::object& obj)\n  {\n    auto name = Demangle(pybind11::detail::get_type_info((PyTypeObject*) pybind11::type::of(obj).ptr())->cpptype->name());\n    auto info = Archive::GetArchiveRegister(name);\n    if(!info.pyToAnyCaster)\n      throw Exception(\"Need to register class \" + name + \" for Archive using std::any\");\n    return info.pyToAnyCaster(obj);\n  }\n#endif // NETGEN_PYTHON\n\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/archive.hpp",
    "content": "#ifndef NETGEN_CORE_ARCHIVE_HPP\n#define NETGEN_CORE_ARCHIVE_HPP\n\n#include <algorithm>\n#include <any>\n#include <array>                // for array\n#include <complex>              // for complex\n#include <cstring>              // for size_t, strlen\n#include <filesystem>           // for path\n#include <fstream>              // for ifstream, ofstream\n#include <functional>           // for function\n#include <map>                  // for map\n#include <memory>               // for shared_ptr\n#include <optional>             // for optional\n#include <string>               // for string\n#include <type_traits>          // for declval, enable_if_t, false_type, is_co...\n#include <cstddef>              // for std::byte\n#include <set>                  // for set\n#include <typeinfo>             // for type_info\n#include <utility>              // for move, swap, pair\n#include <vector>               // for vector\n\n#include \"exception.hpp\"        // for UnreachableCodeException, Exception\n#include \"ngcore_api.hpp\"       // for NGCORE_API\n#include \"type_traits.hpp\"      // for all_of_tmpl\n#include \"utils.hpp\"            // for Demangle, unlikely\n#include \"version.hpp\"          // for VersionInfo\n\n#ifdef NETGEN_PYTHON\nnamespace pybind11\n{\n  class object;\n}\n#endif // NETGEN_PYTHON\n\nnamespace ngcore\n{\n  template <typename T>\n  struct Shallow {\n    T val;\n    Shallow() = default;\n    Shallow(T aval) : val(aval) { ; }\n    operator T&() { return val; }\n  };\n\n  // Helper to detect shared_from_this\n  template <typename T>\n  class has_shared_from_this2\n    {\n    private:\n      // typedef T* T_ptr;\n      template <typename C> static std::true_type test(decltype(((C*)nullptr)->shared_from_this()));\n      template <typename C> static std::false_type test(...);\n      \n    public:\n      // If the test returns true_type, then T has shared_from_this\n      static constexpr bool value = decltype(test<T>(0))::value;\n  };\n  \n  \n\n  \n  template <typename T, typename = void>\n  class has_shallow_archive : public std::false_type {};\n  \n  template <typename T>\n  class has_shallow_archive<T, std::void_t<decltype(T::shallow_archive)>>\n    : public std::is_same<decltype(T::shallow_archive), std::true_type> {};\n  \n\n  \n#ifdef NETGEN_PYTHON\n  NGCORE_API pybind11::object CastAnyToPy(const std::any& a);\n  NGCORE_API std::any CastPyToAny(pybind11::object& h);\n#endif // NETGEN_PYTHON\n\n  class NGCORE_API Archive;\n  namespace detail\n  {\n    template <class T, class Tuple, size_t... Is>\n    T* construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {\n      // return new T{std::get<Is>(std::forward<Tuple>(tuple))...};\n      return new T{std::get<Is>(std::move(tuple))...};\n    }\n\n    template <class T, class Tuple>\n    T* construct_from_tuple(Tuple&& tuple) {\n      return construct_from_tuple<T>(std::forward<Tuple>(tuple),\n                                     std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}\n                                     );\n    }\n\n    // create new pointer of type T if it is default constructible, else throw\n    template<typename T, typename... TArgs>\n    T* constructIfPossible(std::tuple<TArgs...> args)\n    {\n      if constexpr(std::is_constructible_v<T, TArgs...>)\n        return construct_from_tuple<T>(args);\n          throw Exception(std::string(Demangle(typeid(T).name())) +\n                          \" is not constructible!\");\n    }\n\n    template <typename T> T *constructIfPossible()\n    {\n      if constexpr(std::is_constructible_v<T>)\n        return new T();\n      throw Exception(std::string(Demangle(typeid(T).name())) +\n                      \" is not default constructible!\");\n    }\n\n    //Type trait to check if a class implements a 'void DoArchive(Archive&)' function\n    template<typename T>\n    struct has_DoArchive\n    {\n    private:\n      template<typename T2>\n      static constexpr auto check(T2*) ->\n        typename std::is_same<decltype(std::declval<T2>().DoArchive(std::declval<Archive&>())),void>::type;\n      template<typename>\n      static constexpr std::false_type check(...);\n      using type = decltype(check<T>(nullptr)); // NOLINT\n    public:\n      NGCORE_API static constexpr bool value = type::value;\n    };\n\n    // Check if class is archivable\n    template<typename T>\n    struct is_Archivable_struct\n    {\n    private:\n      template<typename T2>\n      static constexpr auto check(T2*) ->\n        typename std::is_same<decltype(std::declval<Archive>() & std::declval<T2&>()),Archive&>::type;\n      template<typename>\n      static constexpr std::false_type check(...);\n      using type = decltype(check<T>(nullptr)); // NOLINT\n    public:\n      NGCORE_API static constexpr bool value = type::value;\n    };\n\n    template <typename T>\n    struct has_GetCArgs\n    {\n      template <typename C> static std::true_type check( decltype( sizeof(&C::GetCArgs )) ) { return std::true_type(); }\n      template <typename> static std::false_type check(...) { return std::false_type(); }\n      typedef decltype( check<T>(sizeof(char)) ) type;\n      static constexpr type value = type();\n    };\n    template<typename T>\n    constexpr bool has_GetCArgs_v = has_GetCArgs<T>::value;\n\n    template<typename T,\n    typename std::enable_if<!has_GetCArgs_v<T>>::type* = nullptr>\n    std::tuple<> GetCArgs(T&val) { return {}; }\n\n    template<typename T,\n    typename std::enable_if<has_GetCArgs_v<T>>::type* = nullptr>\n    auto GetCArgs(T&val) {\n      return val.GetCArgs();\n    }\n\n    template<typename T>\n    using TCargs = decltype(GetCArgs<T>(*static_cast<T*>(nullptr)));\n\n\n    struct ClassArchiveInfo\n    {\n      // create new object of this type and return a void* pointer that is points to the location\n      // of the (base)class given by type_info\n      // std::function<void*(const std::type_info&)> creator;\n      void* (*creator)(const std::type_info&, Archive&);\n      // This caster takes a void* pointer to the type stored in this info and casts it to a\n      // void* pointer pointing to the (base)class type_info\n      // std::function<void*(const std::type_info&, void*)> upcaster;\n      void* (*upcaster) (const std::type_info&, void*);\n      // This caster takes a void* pointer to the (base)class type_info and returns void* pointing\n      // to the type stored in this info\n      // std::function<void*(const std::type_info&, void*)> downcaster;\n      void* (*downcaster)(const std::type_info&, void*);\n\n      // Archive constructor arguments\n      // std::function<void(Archive&, void*)> cargs_archiver;\n      void (*cargs_archiver)(Archive&, void*);\n\n#ifdef NETGEN_PYTHON\n      // std::function<pybind11::object(const std::any&)> anyToPyCaster;\n      pybind11::object (*anyToPyCaster)(const std::any&);\n      std::any (*pyToAnyCaster)(pybind11::object&);\n#endif // NETGEN_PYTHON\n    };\n  } // namespace detail\n\n  template<typename T>\n  constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;\n\n  \n  template <typename T, typename ... Trest>\n  constexpr size_t TotSize () \n  {\n    if constexpr (sizeof...(Trest) == 0)\n                   return sizeof(T);\n    else\n      return sizeof(T) + TotSize<Trest...> ();\n  }\n  \n  \n  // Base Archive class\n  class NGCORE_API Archive\n  {\n    const bool is_output;\n    // how many different shared_ptr/pointer have been (un)archived\n    int shared_ptr_count{0}, ptr_count{0};\n    // maps for archived shared pointers and pointers\n    std::map<void*, int> shared_ptr2nr{}, ptr2nr{};\n    // vectors for storing the unarchived (shared) pointers\n    std::vector<std::shared_ptr<void>> nr2shared_ptr{};\n    std::vector<void*> nr2ptr{};\n  protected:\n    bool shallow_to_python = false;\n    std::map<std::string, VersionInfo> version_map = GetLibraryVersions();\n  public:\n    template<typename T>\n      static constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;\n\n    Archive() = delete;\n    Archive(const Archive&) = delete;\n    Archive(Archive&&) = delete;\n    Archive (bool ais_output) : is_output(ais_output) { ; }\n\n    virtual ~Archive() { ; }\n\n    // If the object is pickled, all shallow archived objects will be pickled as a list,\n    // instead of written as a binary archive. This allows pickle to serialize every object only\n    // once and put them together correctly afterwards. Therefore all objects that may live in\n    // Python should be archived using this Shallow function. If Shallow is called from C++ code\n    // it archives the object normally.\n#ifdef NETGEN_PYTHON\n    template<typename T>\n    Archive& Shallow(T& val); // implemented in register_archive.hpp\n#ifndef __CUDACC__\n    Archive& Shallow(std::any& val); // implemented in python_ngcore.cpp\n#endif // __CUDACC__\n#else // NETGEN_PYTHON\n    template<typename T>\n    Archive& Shallow(T& val)\n    {\n      static_assert(detail::is_any_pointer<T>, \"ShallowArchive must be given pointer type!\");\n        *this & val;\n      return *this;\n    }\n#endif // NETGEN_PYTHON\n\n#ifdef NETGEN_PYTHON\n    virtual void ShallowOutPython(const pybind11::object& /*unused*/)\n    { throw UnreachableCodeException{}; }\n    virtual void ShallowInPython(pybind11::object &)\n    { throw UnreachableCodeException{}; }\n#endif // NETGEN_PYTHON\n\n    Archive& operator=(const Archive&) = delete;\n    Archive& operator=(Archive&&) = delete;\n\n    bool Output () const { return is_output; }\n    bool Input () const { return !is_output; }\n    const VersionInfo& GetVersion(const std::string& library)\n    { return version_map[library]; }\n\n    // only used for PyArchive\n    virtual void NeedsVersion(const std::string& /*unused*/, const std::string& /*unused*/) {}\n\n    // Pure virtual functions that have to be implemented by In-/OutArchive\n    virtual Archive & operator & (std::byte & d) = 0;    \n    virtual Archive & operator & (float & d) = 0;\n    virtual Archive & operator & (double & d) = 0;\n    virtual Archive & operator & (int & i) = 0;\n    virtual Archive & operator & (long & i) = 0;\n    virtual Archive & operator & (size_t & i) = 0;\n    virtual Archive & operator & (short & i) = 0;\n    virtual Archive & operator & (unsigned char & i) = 0;\n    virtual Archive & operator & (bool & b) = 0;\n    virtual Archive & operator & (std::string & str) = 0;\n    virtual Archive & operator & (char *& str) = 0;\n\n#ifdef NETGEN_PYTHON    \n    Archive & operator &(std::any& a)\n    {\n      Shallow(a);\n      return *this;\n    }\n#endif\n    \n    Archive & operator & (VersionInfo & version)\n    {\n        if(Output())\n            (*this) << version.to_string();\n        else\n        {\n            std::string s;\n            (*this) & s;\n            version = VersionInfo(s);\n        }\n        return *this;\n    }\n\n    // Archive std classes ================================================\n    template<typename T>\n    Archive& operator & (std::complex<T>& c)\n    {\n      if(Output())\n          (*this) << c.real() << c.imag();\n      else\n        {\n          T tmp;\n          (*this) & tmp;\n          c.real(tmp);\n          (*this) & tmp;\n          c.imag(tmp);\n        }\n      return (*this);\n    }\n    template<typename T>\n    Archive& operator & (std::vector<T>& v)\n    {\n      size_t size;\n      if(Output())\n          size = v.size();\n      (*this) & size;\n      if(Input())\n        v.resize(size);\n      Do(&v[0], size);\n      return (*this);\n    }\n \n    // archive implementation for enums\n    template<typename T>\n    auto operator & (T& val) -> std::enable_if_t<std::is_enum<T>::value, Archive&>\n    {\n      int enumval;\n      if(Output())\n        enumval = int(val);\n      *this & enumval;\n      if(Input())\n        val = T(enumval);\n      return *this;\n    }\n\n    // vector<bool> has special implementation (like a bitarray) therefore\n    // it needs a special overload (this could probably be more efficient, but we\n    // don't use it that often anyway)\n    Archive& operator& (std::vector<bool>& v)\n    {\n      size_t size;\n      if(Output())\n        size = v.size();\n      (*this) & size;\n      if(Input())\n        {\n          v.resize(size);\n          bool b;\n          for(size_t i=0; i<size; i++)\n            {\n              (*this) & b;\n              v[i] = b;\n            }\n        }\n      else\n        {\n          for(bool b : v)\n            (*this) & b;\n        }\n      return *this;\n    }\n    template<typename T1, typename T2>\n    Archive& operator& (std::map<T1, T2>& map)\n    {\n      if(Output())\n        {\n          (*this) << size_t(map.size());\n          for(auto& pair : map)\n              (*this) << pair.first << pair.second;\n        }\n      else\n        {\n          size_t size = 0;\n          (*this) & size;\n          T1 key; T2 val;\n          for(size_t i = 0; i < size; i++)\n            {\n              T1 key; T2 val;\n              (*this) & key & val;\n              map[key] = val;\n            }\n        }\n      return (*this);\n    }\n    template<typename T>\n    Archive& operator& (std::optional<T>& opt)\n    {\n        bool has_value = opt.has_value();\n        (*this) & has_value;\n        if(has_value)\n          {\n            if(Output())\n                (*this) << *opt;\n            else\n            {\n                T value;\n                (*this) & value;\n                opt = value;\n            }\n          }\n      return (*this);\n    }\n    template <typename T>\n    Archive& operator&(std::set<T> &s)\n    {\n      auto size = s.size();\n      (*this) & size;\n      if(Output())\n        for(const auto & val : s)\n          (*this) << val;\n      else\n      {\n          for(size_t i=0; i<size; i++)\n          {\n              T val;\n              (*this) & val;\n              s.insert(val);\n          }\n      }\n      return *this;\n    }\n\n    // Archive arrays =====================================================\n    // this functions can be overloaded in Archive implementations for more efficiency\n    template <typename T, typename = std::enable_if_t<is_archivable<T>>>\n    Archive & Do (T * data, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (std::byte * d, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (double * d, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (int * i, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (long * i, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (size_t * i, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (short * i, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (unsigned char * i, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT\n\n    virtual Archive & Do (bool * b, size_t n)\n    { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT\n\n    // Archive a class implementing a (void DoArchive(Archive&)) method =======\n    template<typename T, typename=std::enable_if_t<detail::has_DoArchive<T>::value>>\n    Archive& operator & (T& val)\n    {\n      val.DoArchive(*this); return *this;\n    }\n\n\n\n    \n    // pack elements to binary\n    template <typename ... Types>\n      Archive & DoPacked (Types & ... args)\n    {\n      if (true) // (isbinary)\n        {\n          constexpr size_t totsize = TotSize<Types...>(); // (args...);\n          std::byte mem[totsize];\n          if (is_output)\n            {\n              CopyToBin (&mem[0], args...);\n              Do(&mem[0], totsize);\n            }\n          else\n            {\n              Do(&mem[0], totsize);\n              CopyFromBin (&mem[0], args...);\n            }\n        }\n      // else\n      // cout << \"DoPacked of non-binary called --> individual pickling\" << endl;\n      return *this;\n    }\n    \n    \n    template <typename T, typename ... Trest>\n      constexpr void CopyToBin (std::byte * ptr, T & first, Trest & ...rest) const\n    {\n      memcpy (ptr, &first, sizeof(first));\n      CopyToBin(ptr+sizeof(first), rest...);\n    }\n    constexpr void CopyToBin (std::byte * ptr) const { }\n    \n    template <typename T, typename ... Trest>\n      constexpr void CopyFromBin (std::byte * ptr, T & first, Trest & ...rest) const\n    {\n      memcpy (&first, ptr, sizeof(first));\n      CopyFromBin(ptr+sizeof(first), rest...);\n    }\n    constexpr void CopyFromBin (std::byte * ptr) const { }\n\n\n      \n\n    template <typename T>\n    Archive& operator & (ngcore::Shallow<T>& shallow)\n    {\n      if(shallow_to_python)\n        Shallow(shallow.val);\n      return *this;\n    }\n      \n\n    // Archive shared_ptrs =================================================\n    template <typename T>\n    Archive& operator & (std::shared_ptr<T>& ptr)\n    {\n      if constexpr(has_shallow_archive<T>::value)\n        if (shallow_to_python)\n          {\n            Shallow (ptr);\n            return *this;\n          }\n          \n      if(Output())\n        {\n          // save -2 for nullptr\n          if(!ptr)\n            return (*this) << -2;\n\n          void* reg_ptr = ptr.get();\n          bool neededDowncast = false;\n          // Downcasting is only possible for our registered classes\n          if(typeid(T) != typeid(*ptr))\n            {\n              if(!IsRegistered(Demangle(typeid(*ptr).name())))\n                  throw Exception(std::string(\"Archive error: Polymorphic type \")\n                                  + Demangle(typeid(*ptr).name())\n                                  + \" not registered for archive\");\n              reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());\n              // if there was a true downcast we have to store more information\n              if(reg_ptr != static_cast<void*>(ptr.get()))\n                neededDowncast = true;\n            }\n          auto pos = shared_ptr2nr.find(reg_ptr);\n          // if not found store -1 and the pointer\n          if(pos == shared_ptr2nr.end())\n            {\n              auto p = ptr.get();\n              (*this) << -1;\n              (*this) & neededDowncast & p;\n              // if we did downcast we store the true type as well\n              if(neededDowncast)\n                (*this) << Demangle(typeid(*ptr).name());\n              shared_ptr2nr[reg_ptr] = shared_ptr_count++;\n              return *this;\n            }\n          // if found store the position and if it has to be downcasted and how\n          (*this) << pos->second << neededDowncast;\n          if(neededDowncast)\n            (*this) << Demangle(typeid(*ptr).name());\n        }\n      else // Input\n        {\n          int nr;\n          (*this) & nr;\n          // -2 restores a nullptr\n          if(nr == -2)\n            {\n              ptr = nullptr;\n              return *this;\n            }\n          // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it\n          if (nr == -1)\n            {\n              T* p = nullptr;\n              bool neededDowncast;\n              (*this) & neededDowncast & p;\n              ptr = std::shared_ptr<T>(p);\n              // if we did downcast we need to store a shared_ptr<void> to the true object\n              if(neededDowncast)\n                {\n                  std::string name;\n                  (*this) & name;\n                  auto info = GetArchiveRegister(name);\n                  // for this we use an aliasing constructor to create a shared pointer sharing lifetime\n                  // with our shared ptr, but pointing to the true object\n                  nr2shared_ptr.push_back(std::shared_ptr<void>(std::static_pointer_cast<void>(ptr),\n                                                                info.downcaster(typeid(T),\n                                                                                ptr.get())));\n                }\n              else\n                  nr2shared_ptr.push_back(ptr);\n            }\n          else\n            {\n              auto other = nr2shared_ptr[nr];\n              bool neededDowncast;\n              (*this) & neededDowncast;\n              if(neededDowncast)\n                {\n                  // if there was a downcast we can expect the class to be registered (since archiving\n                  // wouldn't have worked else)\n                  std::string name;\n                  (*this) & name;\n                  auto info = GetArchiveRegister(name);\n                  // same trick as above, create a shared ptr sharing lifetime with\n                  // the shared_ptr<void> in the register, but pointing to our object\n                  ptr = std::static_pointer_cast<T>(std::shared_ptr<void>(other,\n                                                                          info.upcaster(typeid(T),\n                                                                               other.get())));\n                }\n              else\n                {\n                  ptr = std::static_pointer_cast<T>(other);\n                }\n            }\n        }\n      return *this;\n    }\n\n    // Archive pointers =======================================================\n    template <typename T>\n    Archive & operator& (T *& p)\n    {\n      if (Output())\n        {\n          // if the pointer is null store -2\n          if (!p)\n              return (*this) << -2;\n          auto reg_ptr = static_cast<void*>(p);\n          if(typeid(T) != typeid(*p))\n            {\n              if(!IsRegistered(Demangle(typeid(*p).name())))\n                throw Exception(std::string(\"Archive error: Polymorphic type \")\n                                + Demangle(typeid(*p).name())\n                                + \" not registered for archive\");\n              reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));\n            }\n          auto pos = ptr2nr.find(reg_ptr);\n          // if the pointer is not found in the map create a new entry\n          if (pos == ptr2nr.end())\n            {\n              ptr2nr[reg_ptr] = ptr_count++;\n              if(typeid(*p) == typeid(T))\n                if (std::is_constructible<T>::value)\n                  return (*this) << -1 & (*p);\n                else\n                  {\n                    if (IsRegistered(Demangle(typeid(*p).name())))\n                    {\n                      (*this) << -3 << Demangle(typeid(*p).name());\n                      GetArchiveRegister(Demangle(typeid(*p).name())).\n                        cargs_archiver(*this, p);\n                      return (*this) & (*p);\n                    }\n                    else\n                      throw Exception(std::string(\"Archive error: Class \") +\n                                      Demangle(typeid(*p).name()) + \" does not provide a default constructor!\");\n                  }\n              else\n                {\n                  // if a pointer to a base class is archived, the class hierarchy must be registered\n                  // to avoid compile time issues we allow this behaviour only for \"our\" classes that\n                  // implement a void DoArchive(Archive&) member function\n                  // To recreate the object we need to store the true type of it\n                  if(!IsRegistered(Demangle(typeid(*p).name())))\n                    throw Exception(std::string(\"Archive error: Polymorphic type \")\n                                    + Demangle(typeid(*p).name())\n                                    + \" not registered for archive\");\n                  (*this) << -3 << Demangle(typeid(*p).name());\n                  GetArchiveRegister(Demangle(typeid(*p).name())).\n                    cargs_archiver(*this, p);\n                  return (*this) & (*p);\n                }\n            }\n          else\n            {\n              (*this) & pos->second;\n              bool downcasted = !(reg_ptr == static_cast<void*>(p) );\n              // store if the class has been downcasted and the name\n              (*this) << downcasted << Demangle(typeid(*p).name());\n            }\n        }\n      else\n        {\n          int nr;\n          (*this) & nr;\n          if (nr == -2) // restore a nullptr\n              p = nullptr;\n          else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)\n            {\n              p = detail::constructIfPossible<T>();\n              nr2ptr.push_back(p);\n              (*this) & *p;\n            }\n          else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...\n            {\n              // As stated above, we want this special behaviour only for our classes that implement DoArchive\n              std::string name;\n              (*this) & name;\n              auto info = GetArchiveRegister(name);\n              // the creator creates a new object of type name, and returns a void* pointing\n              // to T (which may have an offset)\n              p = static_cast<T*>(info.creator(typeid(T), *this));\n              // we store the downcasted pointer (to be able to find it again from\n              // another class in a multiple inheritance tree)\n              nr2ptr.push_back(info.downcaster(typeid(T),p));\n              (*this) & *p;\n            }\n          else\n            {\n              bool downcasted;\n              std::string name;\n              (*this) & downcasted & name;\n              if(downcasted)\n                {\n                  // if the class has been downcasted we can assume it is in the register\n                  auto info = GetArchiveRegister(name);\n                  p = static_cast<T*>(info.upcaster(typeid(T), nr2ptr[nr]));\n                }\n              else\n                p = static_cast<T*>(nr2ptr[nr]);\n            }\n        }\n      return *this;\n    }\n\n    Archive& operator&(std::tuple<>&) { return *this; }\n\n    template <typename... T>\n    Archive& operator&(std::tuple<T...> &t)\n    {\n      // call operator& for each element of the tuple\n      std::apply([this](auto&... arg) { std::make_tuple(((*this) & arg).IsParallel()...);}, t);\n      return *this;\n    }\n\n    // const ptr\n    template<typename T>\n    Archive& operator &(const T*& t)\n    {\n      return (*this) & const_cast<T*&>(t); // NOLINT\n    }\n\n    // Write a read only variable\n    template <typename T>\n    Archive & operator << (const T & t)\n    {\n      T ht(t);\n      (*this) & ht;\n      return *this;\n    }\n\n    virtual void FlushBuffer() {}\n\n    bool parallel = false;\n    bool IsParallel() const { return parallel; }\n    void SetParallel (bool _parallel) { parallel = _parallel; }\n    \n  private:\n  template<typename T, typename Bases>\n    friend class RegisterClassForArchive;\n\n#ifdef NETGEN_PYTHON\n    friend pybind11::object CastAnyToPy(const std::any&);\n    friend std::any CastPyToAny(pybind11::object&);\n#endif // NETGEN_PYTHON\n\n    // Returns ClassArchiveInfo of Demangled typeid\n    static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname);\n    // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of\n    // RegisterClassForArchive<type, bases...>\n    static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info);\n    static bool IsRegistered(const std::string& classname);\n\n    // Helper class for up-/downcasting\n    template<typename T, typename ... Bases>\n    struct Caster{};\n\n    template<typename T>\n    struct Caster<T, std::tuple<>>\n    {\n      static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)\n      {\n        throw Exception(\"Upcast not successful, some classes are not registered properly for archiving!\");\n      }\n      static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/)\n      {\n        throw Exception(\"Downcast not successful, some classes are not registered properly for archiving!\");\n      }\n    };\n\n    template<typename T, typename B1>\n    struct Caster<T,B1>\n    {\n      static void* tryUpcast(const std::type_info& ti, T* p)\n      {\n        try {\n          return GetArchiveRegister(Demangle(typeid(B1).name()))\n            .upcaster(ti, static_cast<void *>(dynamic_cast<B1 *>(p)));\n        } catch (const Exception &) {\n        throw Exception(\"Upcast not successful, some classes are not \"\n                                \"registered properly for archiving!\");\n        }\n      }\n\n      static void* tryDowncast(const std::type_info& ti, void* p)\n      {\n        if(typeid(B1) == ti)\n          return dynamic_cast<T*>(static_cast<B1*>(p));\n        try\n          {\n            return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).\n                                                     downcaster(ti, p)));\n        } catch (const Exception &) {\n            throw Exception(\"Downcast not successful, some classes are not \"\n                            \"registered properly for archiving!\");\n        }\n      }\n    };\n\n    template<typename T, typename B1, typename ... Brest>\n    struct Caster<T,std::tuple<B1, Brest...>>\n    {\n      static void* tryUpcast(const std::type_info& ti, T* p)\n      {\n        try\n          { return GetArchiveRegister(Demangle(typeid(B1).name())).\n              upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }\n        catch(const Exception&)\n          { return Caster<T, std::tuple<Brest...>>::tryUpcast(ti, p); }\n      }\n\n      static void* tryDowncast(const std::type_info& ti, void* p)\n      {\n        if(typeid(B1) == ti)\n          return dynamic_cast<T*>(static_cast<B1*>(p));\n        try\n          {\n            return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).\n                                                     downcaster(ti, p)));\n          }\n        catch(const Exception&)\n          {\n            return Caster<T, std::tuple<Brest...>>::tryDowncast(ti, p);\n          }\n      }\n    };\n  };\n\n  // BinaryOutArchive ======================================================================\n  class NGCORE_API BinaryOutArchive : public Archive\n  {\n    static constexpr size_t BUFFERSIZE = 1024;\n    std::array<char,BUFFERSIZE> buffer{};\n    size_t ptr = 0;\n  protected:\n    std::shared_ptr<std::ostream> stream;\n  public:\n    BinaryOutArchive() = delete;\n    BinaryOutArchive(const BinaryOutArchive&) = delete;\n    BinaryOutArchive(BinaryOutArchive&&) = delete;\n    BinaryOutArchive(std::shared_ptr<std::ostream>&& astream)\n      : Archive(true), stream(std::move(astream))\n    { }\n    BinaryOutArchive(const std::filesystem::path& filename)\n      : BinaryOutArchive(std::make_shared<std::ofstream>(filename)) {}\n    ~BinaryOutArchive () override { FlushBuffer(); }\n\n    BinaryOutArchive& operator=(const BinaryOutArchive&) = delete;\n    BinaryOutArchive& operator=(BinaryOutArchive&&) = delete;\n\n    using Archive::operator&;\n    Archive & operator & (std::byte & d) override\n    { return Write(d); }\n    Archive & operator & (float & f) override\n    { return Write(f); }\n    Archive & operator & (double & d) override\n    { return Write(d); }\n    Archive & operator & (int & i) override\n    { return Write(i); }\n    Archive & operator & (short & i) override\n    { return Write(i); }\n    Archive & operator & (long & i) override\n    {\n      // for platform independence\n      if constexpr (sizeof(long) == 8)\n        return Write(i);\n      else\n        return Write(static_cast<int64_t>(i));\n    }\n    Archive & operator & (size_t & i) override\n    {\n      // for platform independence\n      if constexpr (sizeof(size_t) == 8)\n        return Write(i);\n      else\n        return Write(static_cast<uint64_t>(i));\n    }\n    Archive & operator & (unsigned char & i) override\n    { return Write(i); }\n    Archive & operator & (bool & b) override\n    { return Write(b); }\n\n    Archive & operator & (std::string & str) override\n    {\n      int len = str.length();\n      (*this) & len;\n      FlushBuffer();\n      if(len)\n        stream->write (&str[0], len);\n      return *this;\n    }\n    Archive & operator & (char *& str) override\n    {\n      long len = str ? static_cast<long>(strlen (str)) : -1;\n      (*this) & len;\n      FlushBuffer();\n      if(len > 0)\n        stream->write (&str[0], len); // NOLINT\n      return *this;\n    }\n    void FlushBuffer() override\n    {\n      if (ptr > 0)\n        {\n          stream->write(&buffer[0], ptr);\n          ptr = 0;\n        }\n    }\n    Archive & Do (std::byte * d, size_t n) override\n    {\n      FlushBuffer();\n      stream->write(reinterpret_cast<char*>(d), n*sizeof(std::byte)); return *this;\n    } \n\n  private:\n    template <typename T>\n    Archive & Write (T x)\n    {\n      static_assert(sizeof(T) < BUFFERSIZE, \"Cannot write large types with this function!\");\n      if (unlikely(ptr > BUFFERSIZE-sizeof(T)))\n        {\n          stream->write(&buffer[0], ptr);\n          ptr = 0;\n        }\n      memcpy(&buffer[ptr], &x, sizeof(T));\n      ptr += sizeof(T);\n      return *this;\n    }\n  };\n\n  // BinaryInArchive ======================================================================\n  class NGCORE_API BinaryInArchive : public Archive\n  {\n  protected:\n    std::shared_ptr<std::istream> stream;\n  public:\n    BinaryInArchive (std::shared_ptr<std::istream>&& astream)\n      : Archive(false), stream(std::move(astream))\n    { }\n    BinaryInArchive (const std::filesystem::path& filename)\n      : BinaryInArchive(std::make_shared<std::ifstream>(filename)) { ; }\n\n    using Archive::operator&;\n    Archive & operator & (std::byte & d) override\n    { Read(d); return *this; }\n    Archive & operator & (float & f) override\n    { Read(f); return *this; }\n    Archive & operator & (double & d) override\n    { Read(d); return *this; }\n    Archive & operator & (int & i) override\n    { Read(i); return *this; }\n    Archive & operator & (short & i) override\n    { Read(i); return *this; }\n    Archive & operator & (long & i) override\n    {\n      // for platform independence\n      if constexpr (sizeof(long) == 8)\n        Read(i);\n      else\n      {\n        int64_t tmp = 0;\n        Read(tmp);\n        i = tmp;\n      }\n      return *this;\n    }\n    Archive & operator & (size_t & i) override\n    {\n      // for platform independence\n      if constexpr (sizeof(long) == 8)\n        Read(i);\n      else\n      {\n        uint64_t tmp = 0;\n        Read(tmp);\n        i = tmp;\n      }\n      return *this;\n    }\n    Archive & operator & (unsigned char & i) override\n    { Read(i); return *this; }\n    Archive & operator & (bool & b) override\n    { Read(b); return *this; }\n    Archive & operator & (std::string & str) override\n    {\n      int len;\n      (*this) & len;\n      str.resize(len);\n      if(len)\n        stream->read(&str[0], len); // NOLINT\n      return *this;\n    }\n    Archive & operator & (char *& str) override\n    {\n      long len;\n      (*this) & len;\n      if(len == -1)\n        str = nullptr;\n      else\n        {\n          str = new char[len+1]; // NOLINT\n          stream->read(&str[0], len); // NOLINT\n          str[len] = '\\0'; // NOLINT\n        }\n      return *this;\n    }\n\n    Archive & Do (std::byte * d, size_t n) override\n    { stream->read(reinterpret_cast<char*>(d), n*sizeof(std::byte)); return *this; } // NOLINT\n    Archive & Do (double * d, size_t n) override\n    { stream->read(reinterpret_cast<char*>(d), n*sizeof(double)); return *this; } // NOLINT\n    Archive & Do (int * i, size_t n) override\n    { stream->read(reinterpret_cast<char*>(i), n*sizeof(int)); return *this; } // NOLINT\n    Archive & Do (size_t * i, size_t n) override\n    {\n      // for platform independence\n      if constexpr (sizeof(long) == 8)\n        stream->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); // NOLINT\n      else\n        for(size_t j = 0; j < n; j++)\n          (*this) & i[j];\n      return *this;\n    }\n\n  private:\n    template<typename T>\n    inline void Read(T& val)\n    { stream->read(reinterpret_cast<char*>(&val), sizeof(T)); } // NOLINT\n  };\n\n  // TextOutArchive ======================================================================\n  class NGCORE_API TextOutArchive : public Archive\n  {\n  protected:\n    std::shared_ptr<std::ostream> stream;\n  public:\n    TextOutArchive (std::shared_ptr<std::ostream>&& astream)\n      : Archive(true), stream(std::move(astream))\n    { }\n    TextOutArchive (const std::filesystem::path& filename) :\n      TextOutArchive(std::make_shared<std::ofstream>(filename)) { }\n\n    using Archive::operator&;\n    Archive & operator & (std::byte & d) override\n    { *stream << int(d) << ' '; return *this; }\n    Archive & operator & (float & f) override\n    { *stream << f << '\\n'; return *this; }\n    Archive & operator & (double & d) override\n    { *stream << d << '\\n'; return *this; }\n    Archive & operator & (int & i) override\n    { *stream << i << '\\n'; return *this; }\n    Archive & operator & (short & i) override\n    { *stream << i << '\\n'; return *this; }\n    Archive & operator & (long & i) override\n    { *stream << i << '\\n'; return *this; }\n    Archive & operator & (size_t & i) override\n    { *stream << i << '\\n'; return *this; }\n    Archive & operator & (unsigned char & i) override\n    { *stream << int(i) << '\\n'; return *this; }\n    Archive & operator & (bool & b) override\n    { *stream << (b ? 't' : 'f') << '\\n'; return *this; }\n    Archive & operator & (std::string & str) override\n    {\n      int len = str.length();\n      *stream << len << '\\n';\n      if(len)\n        {\n          stream->write(&str[0], len); // NOLINT\n          *stream << '\\n';\n        }\n      return *this;\n    }\n    Archive & operator & (char *& str) override\n    {\n      long len = str ? static_cast<long>(strlen (str)) : -1;\n      *this & len;\n      if(len > 0)\n        {\n          stream->write (&str[0], len); // NOLINT\n          *stream << '\\n';\n        }\n      return *this;\n    }\n  };\n\n  // TextInArchive ======================================================================\n  class NGCORE_API TextInArchive : public Archive\n  {\n  protected:\n    std::shared_ptr<std::istream> stream;\n  public:\n    TextInArchive (std::shared_ptr<std::istream>&& astream) :\n      Archive(false), stream(std::move(astream))\n    { }\n    TextInArchive (const std::filesystem::path& filename)\n      : TextInArchive(std::make_shared<std::ifstream>(filename)) {}\n\n    using Archive::operator&;\n    Archive & operator & (std::byte & d) override\n    { int tmp; *stream >> tmp; d = std::byte(tmp); return *this; }\n    Archive & operator & (float & f) override\n    { *stream >> f; return *this; }\n    Archive & operator & (double & d) override\n    { *stream >> d; return *this; }\n    Archive & operator & (int & i) override\n    { *stream >> i; return *this; }\n    Archive & operator & (short & i) override\n    { *stream >> i; return *this; }\n    Archive & operator & (long & i) override\n    { *stream >> i; return *this; }\n    Archive & operator & (size_t & i) override\n    { *stream >> i; return *this; }\n    Archive & operator & (unsigned char & i) override\n    { int _i; *stream >> _i; i = _i; return *this; }\n    Archive & operator & (bool & b) override\n    { char c; *stream >> c; b = (c=='t'); return *this; }\n    Archive & operator & (std::string & str) override\n    {\n      // Ignore \\r (carriage return) characters when reading strings\n      // this is necessary for instance when a file was written on Windows and is read on Unix\n\n      int len;\n      *stream >> len;\n      char ch;\n      stream->get(ch); // read newline character\n      if(ch == '\\r') // windows line endings -> read \\n as well\n        stream->get(ch);\n      str.resize(len);\n      if(len)\n        stream->get(&str[0], len+1, '\\0');\n\n      // remove all \\r characters from the string, check if size changed\n      // if so, read the remaining characters\n      str.erase(std::remove(str.begin(), str.end(), '\\r'), str.cend());\n      size_t chars_to_read = len-str.size();\n      while (chars_to_read>0)\n      {\n        auto old_size = str.size();\n        str.resize(len);\n\n        stream->get(&str[old_size], chars_to_read+1, '\\0');\n        str.erase(std::remove(str.begin()+old_size, str.end(), '\\r'), str.cend());\n        chars_to_read = len - str.size();\n      }\n      return *this;\n    }\n    Archive & operator & (char *& str) override\n    {\n      long len;\n      (*this) & len;\n      char ch;\n      if(len == -1)\n        {\n          str = nullptr;\n          return (*this);\n        }\n      str = new char[len+1]; // NOLINT\n      if(len)\n        {\n          stream->get(ch); // \\n\n          if(ch == '\\r') // windows line endings, read \\n as well\n            stream->get(ch);\n          stream->get(&str[0], len+1, '\\0'); // NOLINT\n        }\n      str[len] = '\\0'; // NOLINT\n      return *this;\n    }\n  };\n\n  // HashArchive =================================================================\n  // This class enables to easily create hashes for archivable objects by xoring\n  // threw its data\n\n  class NGCORE_API HashArchive : public Archive\n  {\n    size_t hash_value = 0;\n    char* h;\n    int offset = 0;\n  public:\n    HashArchive() : Archive(true)\n      { h = (char*)&hash_value; }\n\n    using Archive::operator&;\n    Archive & operator & (std::byte & d) override { return ApplyHash(d); }    \n    Archive & operator & (float & f) override { return ApplyHash(f); }\n    Archive & operator & (double & d) override { return ApplyHash(d); }\n    Archive & operator & (int & i) override { return ApplyHash(i); }\n    Archive & operator & (short & i) override { return ApplyHash(i); }\n    Archive & operator & (long & i) override { return ApplyHash(i); }\n    Archive & operator & (size_t & i) override { return ApplyHash(i); }\n    Archive & operator & (unsigned char & i) override { return ApplyHash(i); }\n    Archive & operator & (bool & b) override { return ApplyHash(b); }\n    Archive & operator & (std::string & str) override\n    { for(auto c : str) ApplyHash(c);  return *this; }\n    Archive & operator & (char *& str) override\n    { char* s = str; while(*s != '\\0') ApplyHash(*(s++)); return *this; }\n\n    // HashArchive can be used in const context\n    template<typename T>\n      Archive & operator& (const T& val) const\n    { return (*this) & const_cast<T&>(val); }\n\n    size_t GetHash() const { return hash_value; }\n\n  private:\n    template<typename T>\n      Archive& ApplyHash(T val)\n    {\n      size_t n = sizeof(T);\n      char* pval = (char*)&val;\n      for(size_t i = 0; i < n; i++)\n        {\n          h[offset++] ^= pval[i];\n          offset %= 8;\n        }\n      return *this;\n    }\n  };\n\n  NGCORE_API std::map<std::string, detail::ClassArchiveInfo> & GetTypeRegister();\n} // namespace ngcore\n\n#endif // NETGEN_CORE_ARCHIVE_HPP\n"
  },
  {
    "path": "libsrc/core/array.hpp",
    "content": "#ifndef NETGEN_CORE_ARRAY_HPP\n#define NETGEN_CORE_ARRAY_HPP\n\n/**************************************************************************/\n/* File:   array.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <cstring>\n#include <array>\n#include <type_traits>\n\n#include \"exception.hpp\"\n#include \"logging.hpp\"          // for logger\n#include \"ngcore_api.hpp\"       // for NGCORE_API\n#include \"type_traits.hpp\"      // for all_of_tmpl\n#include \"localheap.hpp\"\n#include \"memtracer.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n  using std::ostream;\n\n  template <typename ... ARGS> class Tuple \n  { \n  public:\n    int Size() const { return 0; }\n  };\n\n  template <typename HEAD, typename ... TAIL>\n  class Tuple<HEAD, TAIL...> : Tuple<TAIL...>\n  {\n    typedef Tuple<TAIL...> BASE;\n    HEAD head;\n  public:\n    Tuple () { ; }\n    Tuple (HEAD h, TAIL ... t) : Tuple<TAIL...> (t...), head(h) { ; }\n\n    HEAD Head() const { return head; }\n    Tuple<TAIL...> Tail() const { return *this; }\n\n    int Size() const { return BASE::Size()+1; }\n  };\n\n  template <typename ... ARGS>\n  ostream & operator<< (ostream & ost, Tuple<ARGS...> /* tup */)\n  {\n    return ost;\n  }\n\n  template <typename FIRST, typename ... ARGS>\n  ostream & operator<< (ostream & ost, Tuple<FIRST, ARGS...> tup)\n  {\n    ost << tup.Head() << \", \" << tup.Tail();\n    return ost;\n  }\n\n\n  template <typename ... ARGS>\n  Tuple<ARGS...> MakeTuple (ARGS ... args)\n  {\n    return Tuple<ARGS...> (args...);\n  }\n\n\n  template <typename AO>\n  class AOWrapperIterator\n  {\n    const AO & ao;\n    size_t ind;\n  public:\n    NETGEN_INLINE AOWrapperIterator (const AO &  aao, size_t ai) \n      : ao(aao), ind(ai) { ; }\n    NETGEN_INLINE AOWrapperIterator operator++ (int) \n    { return AOWrapperIterator(ao, ind++); }\n    NETGEN_INLINE AOWrapperIterator& operator++ ()\n    { ++ind; return *this; }\n    NETGEN_INLINE auto operator*() const -> decltype(ao[ind]) { return ao[ind]; }\n    NETGEN_INLINE auto operator*() -> decltype(ao[ind]) { return ao[ind]; }\n    NETGEN_INLINE bool operator != (AOWrapperIterator d2) { return ind != d2.ind; }\n    NETGEN_INLINE bool operator == (AOWrapperIterator d2) { return ind == d2.ind; }\n  };\n\n\n\n  \n  /*\n    Some class which can be treated as array\n   */\n  template <typename T> // , typename TA = T>\n  class BaseArrayObject\n  {\n  public:\n    NETGEN_INLINE BaseArrayObject() { ; }\n\n    NETGEN_INLINE const T & Spec() const { return static_cast<const T&> (*this); }\n    NETGEN_INLINE size_t Size() const { return Spec().Size(); }\n    template <typename T2>\n    NETGEN_INLINE bool Contains(const T2 & el) const\n    {\n      for (size_t i = 0; i < Size(); i++)\n        if (Spec()[i] == el)\n          return true;\n      return false;\n    }\n\n    static constexpr size_t ILLEGAL_POSITION = size_t(-1);\n    template <typename T2>\n    NETGEN_INLINE size_t Pos(const T2 & el) const\n    {\n      for (size_t i = 0; i < Size(); i++)\n        if (Spec()[i] == el)\n          return i;\n      return ILLEGAL_POSITION;\n    }\n\n    template <typename T2>\n    NETGEN_INLINE size_t PosSure(const T2 & el) const\n    {\n      for (size_t i = 0; ; i++)\n        if (Spec()[i] == el)\n          return i;\n    }\n\n    // NETGEN_INLINE auto & operator[] (size_t i) { return Spec()[i]; }\n    NETGEN_INLINE auto operator[] (size_t i) const { return Spec()[i]; }\n    // NETGEN_INLINE auto begin() const { return Spec().begin(); }\n    // NETGEN_INLINE auto end() const { return Spec().end(); }\n    NETGEN_INLINE auto begin () const { return AOWrapperIterator<BaseArrayObject> (*this, 0); }\n    NETGEN_INLINE auto end () const { return AOWrapperIterator<BaseArrayObject> (*this, Size()); }\n  };\n  \n\n  \n  template <typename T>\n  class AOWrapper : public BaseArrayObject<AOWrapper<T>>\n  {\n    T ar;\n  public:\n    NETGEN_INLINE AOWrapper (T aar) : ar(aar) { ; }\n    NETGEN_INLINE operator T () const { return ar; }\n    NETGEN_INLINE size_t Size() const { return ar.Size(); }\n    NETGEN_INLINE auto operator[] (size_t i) { return ar[i]; }\n    NETGEN_INLINE auto operator[] (size_t i) const { return ar[i]; }\n    NETGEN_INLINE AOWrapperIterator<AOWrapper> begin () const { return AOWrapperIterator<AOWrapper> (*this, 0); }\n    NETGEN_INLINE AOWrapperIterator<AOWrapper> end () const { return AOWrapperIterator<AOWrapper> (*this, Size()); }\n  };\n\n  template <typename T>\n  NETGEN_INLINE AOWrapper<const T&> ArrayObject (const T & ar)\n  {\n    return AOWrapper<const T&> (ar);\n  }\n\n  template <typename T>\n  NETGEN_INLINE AOWrapper<T> ArrayObject (T && ar)\n  {\n    return AOWrapper<T> (ar);\n  }\n\n  template <typename FUNC>\n  auto ArrayObject (size_t s, FUNC f)\n  {\n    class Dummy\n    {\n      size_t s;\n      FUNC f;\n    public:\n      Dummy (size_t _s, FUNC _f) : s(_s), f(_f) { ; }\n      size_t Size() const { return s; }\n      auto operator[] (size_t i) const { return f(i); }\n    };\n    return ArrayObject(Dummy(s,f));\n  }\n\n  template <typename T, typename FUNC>\n  auto Substitute (const BaseArrayObject<T> & ao, FUNC f)\n  {\n    return ArrayObject(ao.Size(),\n                       [&ao,f] (size_t i) { return f(ao[i]); });\n  }\n  \n\n\n\n  /**\n     nothing more but a new type for a C array.\n     return value for Addr - operator of array \n  */\n  template <class T>\n  class CArray\n  {\n  protected:\n    /// the data\n    T * data;\n  public:\n\n    /// initialize array \n    NETGEN_INLINE CArray () { data = 0; }\n\n    /// provide size and memory\n    NETGEN_INLINE CArray (T * adata) \n      : data(adata) { ; }\n\n    /// Access array\n    NETGEN_INLINE T & operator[] (size_t i) const\n    {\n      return data[i]; \n    }\n\n    NETGEN_INLINE operator T* () const { return data; }\n  };\n\n\n  template <typename  T>\n  constexpr T IndexBASE () { return T(0); }\n\n  template <typename  T>\n  constexpr T IndexBASE (T ind) { return IndexBASE<T>(); }\n\n  \n\n  class IndexFromEnd\n  {\n    ptrdiff_t i;\n  public:\n    constexpr IndexFromEnd (ptrdiff_t ai) : i(ai) { }\n    IndexFromEnd operator+ (ptrdiff_t inc) const { return i+inc; }\n    IndexFromEnd operator- (ptrdiff_t dec) const { return i-dec; }\n    // operator ptrdiff_t () const { return i; }\n    ptrdiff_t Value() const { return i; }\n  };\n\n  constexpr IndexFromEnd END(0);\n  \n  \n  template <class T, class IndexType = size_t> class FlatArray;\n\n\n  template <typename TELEM, typename IndexType>\n  class ArrayIterator\n  {\n    FlatArray<TELEM, IndexType> ar;\n    IndexType ind;\n  public:\n    NETGEN_INLINE ArrayIterator (FlatArray<TELEM, IndexType> aar, IndexType ai) \n      : ar(aar), ind(ai) { ; }\n    NETGEN_INLINE ArrayIterator operator++ (int) \n    { return ArrayIterator(ar, ind++); }\n    NETGEN_INLINE ArrayIterator operator++ ()\n    { return ArrayIterator(ar, ++ind); }\n    // NETGEN_INLINE const TELEM & operator*() const { return ar[ind]; }\n    // NETGEN_INLINE TELEM & operator*() { return ar[ind]; }\n    NETGEN_INLINE auto operator*() const -> decltype(ar[ind]) { return ar[ind]; }\n    NETGEN_INLINE auto operator*() -> decltype(ar[ind]) { return ar[ind]; }\n    NETGEN_INLINE bool operator != (ArrayIterator d2) { return ind != d2.ind; }\n    NETGEN_INLINE bool operator == (ArrayIterator d2) { return ind == d2.ind; }\n  };\n  \n\n\n  template <typename TSIZE>\n  class ArrayRangeIterator\n  {\n    TSIZE ind;\n  public:\n    NETGEN_INLINE ArrayRangeIterator (TSIZE ai) : ind(ai) { ; }\n    NETGEN_INLINE ArrayRangeIterator operator++ (int) { return ind++; }\n    NETGEN_INLINE ArrayRangeIterator operator++ () { return ++ind; }\n    NETGEN_INLINE TSIZE operator*() const { return ind; }\n    NETGEN_INLINE TSIZE Index() { return ind; }\n    NETGEN_INLINE operator TSIZE () const { return ind; }\n    NETGEN_INLINE bool operator != (ArrayRangeIterator d2) { return ind != d2.ind; }\n    NETGEN_INLINE bool operator == (ArrayRangeIterator d2) { return ind == d2.ind; }\n  };\n\n  /// a range of integers\n  template <typename T>\n  class T_Range : public BaseArrayObject <T_Range<T>>\n  {\n    T first, next;\n  public: \n    NETGEN_INLINE T_Range () { ; }\n    // NETGEN_INLINE T_Range (T n) : first(0), next(n) {;}\n    NETGEN_INLINE explicit T_Range (size_t n) : first(IndexBASE<T>()), next(IndexBASE<T>()+n) {;}    \n    NETGEN_INLINE T_Range (T f, T n) : first(f), next(n) {;}\n    template <typename T2>\n      NETGEN_INLINE T_Range(T_Range<T2> r2) : first(r2.First()), next(r2.Next()) { ; }\n    NETGEN_INLINE T First() const { return first; }\n    NETGEN_INLINE T Next() const { return next; }\n    NETGEN_INLINE T & First() { return first; }\n    NETGEN_INLINE T & Next() { return next; }\n    NETGEN_INLINE auto Size() const { return next-first; }\n    NETGEN_INLINE T operator[] (size_t i) const { return first+i; }\n    NETGEN_INLINE bool Contains (T i) const { return ((i >= first) && (i < next)); }\n    NETGEN_INLINE T_Range Modify(int inc_beg, int inc_end) const\n    { return T_Range(first+inc_beg, next+inc_end); }\n    NETGEN_INLINE ArrayRangeIterator<T> begin() const { return first; }\n    NETGEN_INLINE ArrayRangeIterator<T> end() const { return next; }\n\n    NETGEN_INLINE T_Range Split (size_t nr, int tot) const\n    {\n      auto diff = next-first;\n      return T_Range (first + nr * diff / tot,\n                      first + (nr+1) * diff / tot);\n    }\n    // NETGEN_INLINE operator IntRange () const { return IntRange(first,next); }\n  };\n\n  using IntRange = T_Range<size_t>;\n\n  template <typename T>\n  NETGEN_INLINE T_Range<T> Range (T a, T b)\n  {\n    return T_Range<T>(a,b);\n  }\n\n  template<typename T>\n  NETGEN_INLINE auto Range (const T& ao)\n    -> typename std::enable_if<has_range<T>, decltype(std::declval<T>().Range())>::type\n  { return ao.Range(); }\n\n  template <typename T>\n  NETGEN_INLINE auto Range (FlatArray<T> fa)\n  {\n    return fa.Range();\n  }\n  \n  template <typename T>\n  NETGEN_INLINE T_Range<T> Range_impl (T n, std::true_type)\n  {\n    return T_Range<T> (0, n);\n  }\n\n  template <typename TA>\n  NETGEN_INLINE auto Range_impl (const TA & ao, std::false_type)\n    -> T_Range<index_type<TA>>\n  {\n    return T_Range<index_type<TA>> (IndexBASE<index_type<TA>>(),\n                                   IndexBASE<index_type<TA>>() + index_type<TA>(ao.Size()));\n  }\n\n  /*\n    Range(obj) will create a range in using the following steps:\n    \n    * if obj is an integral type it will create T_Range<type(obj)>(0, obj)\n    * if obj has a function Range() it will return obj.Range()\n    * if obj has a typedef index_type it will return\n      T_Range<index_type>(IndexBASE<index_type>(), IndexBASE<index_type>() + index_type(obj.Size()))\n    * else it will return T_Range<size_t> (0, obj.Size())\n\n   */\n  template <typename T>\n  NETGEN_INLINE auto Range(const T & x)\n    -> typename std::enable_if<std::is_integral_v<T> || !has_range<T>,\n                               decltype(Range_impl(x, std::is_integral<T>()))>::type {\n    return Range_impl(x, std::is_integral<T>());\n  }\n\n\n  NETGEN_INLINE IntRange operator+ (const IntRange & range, int shift)\n  {\n    return IntRange (range.First()+shift, range.Next()+shift);\n  }\n\n  NETGEN_INLINE IntRange operator+ (int shift, const IntRange & range)\n  {\n    return IntRange (range.First()+shift, range.Next()+shift);\n  }\n\n  NETGEN_INLINE IntRange operator* (int scale, const IntRange & range)\n  {\n    return IntRange (scale*range.First(), scale*range.Next());\n  }\n\n  NETGEN_INLINE IntRange operator* (const IntRange & range, int scale)\n  {\n    return IntRange (scale*range.First(), scale*range.Next());\n  }\n\n  template <typename TI>\n  inline ostream & operator<< (ostream & s, T_Range<TI> ir)\n  {\n    s << \"[\" << ir.First() << \",\" << ir.Next() << \")\";\n    return s;\n  }\n\n  template <typename ... ARGS>\n  ostream & operator<< (ostream & ost, Tuple<IntRange, ARGS...> tup)\n  {\n    ost << tup.Head() << \", \" << tup.Tail();\n    return ost;\n  }\n\n\n  template <typename T>\n  inline ostream & operator<< (ostream & ost, const BaseArrayObject<T> & array)\n  {\n    for (auto i : Range(array.Size()))\n      ost << i << \":\" << array[i] << std::endl;\n    return ost;\n  }\n\n\n  template <typename T, typename TI, typename INDEX_ARRAY>\n  class IndirectArray : public BaseArrayObject<IndirectArray<T, TI, INDEX_ARRAY> >\n  {\n    FlatArray<T,TI> ba;\n    const INDEX_ARRAY & ia;\n\n  public:\n    NETGEN_INLINE IndirectArray (FlatArray<T,TI> aba,\n                          const INDEX_ARRAY & aia)\n      : ba(aba), ia(aia) { ; }\n    \n    NETGEN_INLINE size_t Size() const { return ia.Size(); }\n    NETGEN_INLINE T & operator[] (size_t i) const { return ba[ia[i]]; }\n    // NETGEN_INLINE T & operator[] (size_t i) { return ba[ia[i]]; }\n\n    NETGEN_INLINE IndirectArray operator= (const T & val) \n    {\n      for (auto i : Range(Size()))\n        (*this)[i] = val;\n      return IndirectArray (ba, ia);\n    }\n\n    template <typename T2>\n    NETGEN_INLINE IndirectArray operator= (const BaseArrayObject<T2> & a2) \n    {\n      for (auto i : Range(Size()))\n\t(*this)[i] = a2[i];\n      return IndirectArray (ba, ia);\n    }\n\n    NETGEN_INLINE AOWrapperIterator<IndirectArray> begin() const { return { *this, 0 }; }\n    NETGEN_INLINE AOWrapperIterator<IndirectArray> end() const { return { *this, Size() }; }\n  };\n\n\n  /**\n     A simple array container.\n     Array represented by size and data-pointer.\n     No memory allocation and deallocation, must be provided by user.\n     Helper functions for printing. \n     Optional range check by macro NETGEN_CHECK_RANGE\n  */\n  template <class T, class IndexType>\n  class FlatArray : public BaseArrayObject<FlatArray<T,IndexType> >\n  {\n  protected:\n    static constexpr IndexType BASE = IndexBASE<IndexType>();\n    /// the size\n    size_t size = 0;\n    /// the data\n    T * __restrict data = nullptr;\n  public:\n    typedef T value_type;\n    typedef IndexType index_type;\n    using BaseArrayObject<FlatArray>::ILLEGAL_POSITION;\n\n    /// initialize array \n    FlatArray () = default;\n    // { ; } // size = 0; data = 0; }\n\n    /// copy constructor allows size-type conversion \n    FlatArray (const FlatArray & a2) = default;\n    // : size(a2.Size()), data(a2.data) { ; } \n\n    /// provide size and memory\n    NETGEN_INLINE FlatArray (size_t asize, T * adata) \n      : size(asize), data(adata) { ; }\n    \n    /// memory from local heap\n    NETGEN_INLINE FlatArray(size_t asize, Allocator & lh)\n      : size(asize), data(new (lh) T[asize])\n    { ; }\n\n    NETGEN_INLINE FlatArray(size_t asize, LocalHeap & lh)\n      : size(asize), data (lh.Alloc<T> (asize))\n    { ; }\n\n    template <size_t N>\n    NETGEN_INLINE FlatArray(std::array<T,N> & a)\n      : size(N), data(&a[0]) { }\n    \n    /// the size\n    NETGEN_INLINE size_t Size() const { return size; }\n\n    /// the data\n    NETGEN_INLINE T* Data() const { return data; }\n\n    /// Fill array with value val\n    NETGEN_INLINE const FlatArray & operator= (const T & val) const\n    {\n      size_t hsize = size;\n      T * hdata = data;\n      for (size_t i = 0; i < hsize; i++)\n        hdata[i] = val;\n      return *this;\n    }\n\n    /// copies array\n    NETGEN_INLINE const FlatArray & operator= (const FlatArray & a2) const\n    {\n      size_t hsize = size;\n      T * hdata = data;\n      for (size_t i = 0; i < hsize; i++) hdata[i] = a2.data[i];\n      return *this;\n    }\n\n    template <typename T2>\n    NETGEN_INLINE const FlatArray & operator= (const BaseArrayObject<T2> & a2) const\n    {\n      size_t hsize = size;\n      T * hdata = data;\n      auto p2 = a2.begin();\n      for (size_t i = 0; i < hsize; i++, p2++) hdata[i] = *p2;\n      return *this;\n    }\n\n    template <typename T2, std::enable_if_t<std::is_function<T2>::value>>\n    NETGEN_INLINE const FlatArray & operator= (const T2 & func) const\n    {\n      for (size_t i = 0; i < size; i++)\n        data[i] = func(i+BASE);\n      return *this;\n    }\n\n//     template <typename T2>\n//     const FlatArray operator= (ParallelValue<T2> val);\n//     template <typename T2>\n//     const FlatArray operator= (ParallelFunction<T2> val);\n\n    /// copies pointers\n    NETGEN_INLINE const FlatArray & Assign (const FlatArray & a2)\n    {\n      size = a2.size;\n      data = a2.data;\n      return *this;\n    }\n\n    /// assigns memory from local heap\n    NETGEN_INLINE const FlatArray & Assign (size_t asize, LocalHeap & lh)\n    {\n      size = asize;\n      data = lh.Alloc<T> (asize);\n      return *this;\n    }\n\n    /// Access array. range check by macro NETGEN_CHECK_RANGE\n    NETGEN_INLINE T & operator[] (IndexType i) const\n    {\n      NETGEN_CHECK_RANGE(i,BASE,size+BASE);\n      return data[i-BASE]; \n    }\n  \n    NETGEN_INLINE T_Range<index_type> Range () const\n    {\n      return T_Range<index_type> (BASE, size+BASE);\n    }\n    \n    NETGEN_INLINE const CArray<T> Addr (size_t pos) const\n    {\n      return CArray<T> (data+pos-BASE);\n    }\n\n    // const CArray<T> operator+ (int pos)\n    // { return CArray<T> (data+pos); }\n    NETGEN_INLINE T * operator+ (size_t pos) const { return data+pos; }\n\n    /// access first element. check by macro NETGEN_CHECK_RANGE\n    T & First () const\n    {\n      NETGEN_CHECK_RANGE(0,0,size);\n      return data[0];\n    }\n\n    /// access last element. check by macro NETGEN_CHECK_RANGE\n    T & Last () const\n    {\n      NETGEN_CHECK_RANGE(size-1,0,size);\n      return data[size-1];\n    }\n\n    /// takes sub-array starting from position pos\n    NETGEN_INLINE const FlatArray<T> Part (size_t pos)\n    {\n      return FlatArray<T> (size-pos, data+pos);\n    }\n\n    /// takes subsize elements starting from position pos\n    NETGEN_INLINE const FlatArray<T> Part (size_t pos, size_t subsize)\n    {\n      return FlatArray<T> (subsize, data+pos);\n    }\n\n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE FlatArray<T> Range (size_t start, size_t end) const\n    {\n      return FlatArray<T> (end-start, data+start);\n    }\n\n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE FlatArray<T> Range (size_t start, IndexFromEnd indend) const\n    {\n      return this->Range(start, size_t(Size()+indend.Value()));\n    }\n    \n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE FlatArray<T> Range (T_Range<size_t> range) const\n    {\n      return FlatArray<T> (range.Size(), data+range.First());\n    }\n\n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE const FlatArray<T> operator[] (T_Range<IndexType> range) const\n    {\n      return FlatArray<T> (range.Size(), data+range.First());\n    }\n    \n    template <typename TI1>\n    auto operator[] (const BaseArrayObject<TI1> & ind_array) const\n    {\n      return IndirectArray<T, IndexType, BaseArrayObject<TI1> > (*this, ind_array);\n    }\n\n    /// first position of element elem, returns -1 if element not contained in array \n    NETGEN_INLINE size_t Pos(const T & el) const\n    {\n      for (size_t i = 0; i < Size(); i++)\n        if (data[i] == el)\n          return i;\n      return ILLEGAL_POSITION;\n    }\n\n    /// does the array contain element elem ?\n    NETGEN_INLINE bool Contains(const T & elem) const\n    {\n      return Pos(elem) != ILLEGAL_POSITION;\n    }\n    \n    //auto begin() const { return ArrayIterator<T,IndexType> (*this, BASE); }\n    // auto end() const { return ArrayIterator<T,IndexType> (*this, size+BASE); }\n    NETGEN_INLINE auto begin() const { return data; }\n    NETGEN_INLINE auto end() const { return data+Size(); }\n  };\n\n  template <typename T>\n  FlatArray<T> View (FlatArray<T> fa) { return fa; }\n\n  template <typename T, typename TI>\n  auto Max (FlatArray<T,TI> array, typename std::remove_const<T>::type max = std::numeric_limits<T>::min()) -> T\n  {\n    for (auto & v : array)\n      if (v > max) max = v;\n    return max;\n  }\n\n  template <typename T, typename TI>\n  auto Min (FlatArray<T,TI> array, typename std::remove_const<T>::type min = std::numeric_limits<T>::max()) -> T\n  {\n    for (auto & v : array)\n      if (v < min) min = v;\n    return min;\n  }\n  \n  /// print array\n  template <class T, class TIND>\n  inline ostream & operator<< (ostream & s, const FlatArray<T, TIND> & a)\n  {\n    for (auto i : a.Range())\n      s << i << \": \" << a[i] << \"\\n\";\n    return s;\n  }\n\n  /// have arrays the same contents ?\n  template <class T1, class T2>\n  inline bool operator== (const FlatArray<T1> & a1,\n                          const FlatArray<T2> & a2)\n  {\n    if (a1.Size () != a2.Size()) return 0;\n    for (size_t i = 0; i < a1.Size(); i++)\n      if (a1[i] != a2[i]) return false;\n    return true;\n  }\n\t\t \n  template <class T1, class T2>\n  inline bool operator!= (const FlatArray<T1> & a1,\n                          const FlatArray<T2> & a2)\n  {\n    return !(a1==a2);\n  }\n  \n\n  /** \n      Dynamic array container.\n   \n      Array<T> is an automatically increasing array container.\n      The allocated memory doubles on overflow. \n      Either the container takes care of memory allocation and deallocation,\n      or the user provides one block of data.\n  */\n  template <class T, class IndexType = size_t>\n  class Array : public FlatArray<T, IndexType>\n  {\n  protected:\n    /// physical size of array\n    size_t allocsize;\n    /// that's the data we have to delete, nullptr for not owning the memory\n    T * mem_to_delete;\n    MemoryTracer mt;\n\n\n    using FlatArray<T,IndexType>::size;\n    using FlatArray<T,IndexType>::data;\n    using FlatArray<T,IndexType>::BASE;\n\n  public:\n    using index_type = typename FlatArray<T, IndexType>::index_type;\n    /// Generate array of logical and physical size asize\n    NETGEN_INLINE explicit Array()\n      : FlatArray<T,IndexType> (0, nullptr)\n    {\n      allocsize = 0; \n      mem_to_delete = nullptr;\n    }\n\n    NETGEN_INLINE explicit Array(size_t asize)\n      : FlatArray<T,IndexType> (asize, new T[asize])\n    {\n      allocsize = asize; \n      mem_to_delete = data;\n      mt.Alloc(sizeof(T)*asize);\n    }\n\n\n    /// Generate array in user data\n    NETGEN_INLINE Array(size_t asize, T* adata, bool ownMemory = false)\n      : FlatArray<T> (asize, adata)\n    {\n      allocsize = asize;\n      if(ownMemory)\n      {\n        mem_to_delete = adata;\n        mt.Alloc(sizeof(T)*asize);\n      }\n      else\n        mem_to_delete = nullptr;\n    }\n\n    /// Generate array in user data\n    template <typename ALLOCATOR>\n    NETGEN_INLINE Array(size_t asize, ALLOCATOR & lh)\n      : FlatArray<T> (asize, lh)\n    {\n      allocsize = asize; \n      mem_to_delete = nullptr;\n    }\n\n    NETGEN_INLINE Array (Array && a2) \n    {\n      mt = std::move(a2.mt);\n      size = a2.size; \n      data = a2.data;\n      allocsize = a2.allocsize;\n      mem_to_delete = a2.mem_to_delete;\n      a2.size = 0;\n      a2.allocsize = 0;\n      a2.data = nullptr;\n      a2.mem_to_delete = nullptr;\n    }\n\n    /// array copy \n    NETGEN_INLINE explicit Array (const Array & a2)\n      : FlatArray<T,IndexType> (a2.Size(), a2.Size() ? new T[a2.Size()] : nullptr)\n    {\n      if constexpr (std::is_copy_assignable<T>::value)\n        {\n          allocsize = size;\n          mem_to_delete = data;\n          mt.Alloc(sizeof(T)*size);\n          for (size_t i = 0; i < size; i++)\n            data[i] = a2.data[i];\n        }\n      \n// #ifdef __cpp_exceptions\n#ifndef __CUDA_ARCH__\n      else\n        throw Exception(std::string(\"cannot copy-construct Array of type \") + typeid(T).name());\n#endif      \n    }\n\n    \n    template <typename TA>\n    explicit Array (const BaseArrayObject<TA> & a2)\n      : FlatArray<T,IndexType> (a2.Size(), \n                                a2.Size() ? new T[a2.Size()] : nullptr)\n    {\n      allocsize = size;\n      mem_to_delete = data;\n      mt.Alloc(sizeof(T)*size);\n      /*\n      for (size_t i = 0; i < size; i++)\n        data[i] = a2[i];\n      */\n      auto p2 = a2.begin();\n      for (size_t i = 0; i < size; i++, p2++)\n        data[i] = *p2;\n      \n    }\n\n    Array (std::initializer_list<T> list) \n      : FlatArray<T> (list.size(), \n                      list.size() ? new T[list.size()] : NULL)\n    {\n      allocsize = size;\n      mem_to_delete = data;\n      mt.Alloc(sizeof(T)*size);\n      size_t cnt = 0;\n      for (auto val : list)\n        data[cnt++] = val;\n    }\n\n    /// array merge-copy\n    explicit Array (const Array<T> & a2, const Array<T> & a3)\n      : FlatArray<T> (a2.Size()+a3.Size(), \n                      a2.Size()+a3.Size() ? new T[a2.Size()+a3.Size()] : 0)\n    {\n      allocsize = size;\n      mem_to_delete = data;\n      mt.Alloc(sizeof(T)*size);\n      for(size_t i = 0; i <  a2.Size(); i++)\n        data[i] = a2[i];\n      for (size_t i = a2.Size(), j=0; i < size; i++,j++)\n        data[i] = a3[j];\n    }\n\n    /// if responsible, deletes memory\n    NETGEN_INLINE ~Array()\n    {\n      if(mem_to_delete)\n        mt.Free(sizeof(T)*allocsize);\n      delete [] mem_to_delete;\n    }\n\n    // Only provide this function if T is archivable\n    template<typename ARCHIVE>\n    auto DoArchive(ARCHIVE& archive)\n      -> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>\n    {\n      if(archive.Output())\n        archive << size;\n      else\n        {\n          size_t s;\n          archive & s;\n          SetSize(s);\n        }\n      archive.Do(data, size);\n    }\n\n    /// we tell the compiler that there is no need for deleting the array ..\n    NETGEN_INLINE void NothingToDelete () \n    { \n      mem_to_delete = nullptr;\n\n      // this memory is not managed by the Array anymore, so set the memory usage to 0\n      mt.Free(sizeof(T)*allocsize);\n    }\n\n    /// Change logical size. If necessary, do reallocation. Keeps contents.\n    NETGEN_INLINE void SetSize(size_t nsize)\n    {\n      if (nsize > allocsize) ReSize (nsize);\n      size = nsize; \n    }\n\n    ///\n    NETGEN_INLINE void SetSize0()\n    {\n      size = 0; \n    }\n\n    /// Change physical size. Keeps logical size. Keeps contents.\n    NETGEN_INLINE void SetAllocSize (size_t nallocsize)\n    {\n      if (nallocsize > allocsize)\n        ReSize (nallocsize);\n    }\n\n    /// Change physical size. Keeps logical size. Keeps contents.\n    NETGEN_INLINE size_t AllocSize () const\n    {\n      return allocsize;\n    }\n\n\n    /// assigns memory from local heap\n    NETGEN_INLINE const Array & Assign (size_t asize, LocalHeap & lh)\n    {\n      if(mem_to_delete)\n        mt.Free(sizeof(T)*allocsize);\n      delete [] mem_to_delete;\n      size = allocsize = asize;\n      data = lh.Alloc<T> (asize);\n      mem_to_delete = nullptr;\n      return *this;\n    }\n\n    /// Add element at end of array. reallocation if necessary.\n    /// Returns index of new element.\n    NETGEN_INLINE index_type Append (const T & el)\n    {\n      if (size == allocsize) \n        ReSize (size+1);\n      data[size] = el;\n      return BASE + size++;\n    }\n\n    /// Add element at end of array. reallocation not necessary.\n    /// Returns index of new element.\n    NETGEN_INLINE index_type AppendHaveMem (const T & el)\n    {\n      NETGEN_CHECK_RANGE(size, 0, allocsize);\n      data[size] = el;\n      return BASE + size++;\n    }\n\n    \n    /// Add element at end of array. reallocation if necessary.\n    /// Returns index of new element.\n    NETGEN_INLINE index_type Append (T && el)\n    {\n      if (size == allocsize) \n        ReSize (size+1);\n      data[size] = std::move(el);\n      return BASE + size++;\n    }\n\n    // Add elements of initializer list to end of array. Reallocation if necessary.\n    NETGEN_INLINE void Append(std::initializer_list<T> lst)\n    {\n      if(allocsize < size + lst.size())\n        ReSize(size+lst.size());\n      for(auto val : lst)\n        data[size++] = val;\n    }\n\n    /// Add element at end of array. reallocation if necessary.\n    NETGEN_INLINE void Insert (size_t pos, const T & el)\n    {\n      if (size == allocsize) \n        ReSize (size+1);\n      for (size_t i = size; i > pos; i--)\n        data[i] = data[i-1];\n      data[pos] = el;\n      size++;\n    }\n    \n    NETGEN_INLINE Array & operator += (const T & el)\n    {\n      Append (el);\n      return *this;\n    }\n\n\n    /// Append array at end of array. reallocation if necessary.\n    NETGEN_INLINE void Append (FlatArray<T> source)\n    {\n      if(size + source.Size() >= allocsize)\n        ReSize (size + source.Size() + 1);\n\n      for(size_t i = size, j=0; j<source.Size(); i++, j++)\n        data[i] = source[j];\n\n      size += source.Size();\n    }\n\n\n\n    /// Delete element i. Move last element to position i.\n    NETGEN_INLINE void DeleteElement (IndexType i)\n    {\n      NETGEN_CHECK_RANGE(i,BASE,BASE+size);\n      data[i-BASE] = std::move(data[size-1]);\n      size--;\n    }\n\n\n    /// Delete element i. Move all remaining elements forward\n    NETGEN_INLINE void RemoveElement (IndexType i)\n    {\n      NETGEN_CHECK_RANGE(i, BASE, BASE+size);\n      for(size_t j = i-BASE; j+1 < this->size; j++)\n\tthis->data[j] = this->data[j+1];\n      this->size--;\n    }\n\n    template <typename FUNC>\n    NETGEN_INLINE void RemoveElementIf (FUNC func)\n    {\n      ptrdiff_t move_forward = 0;\n      for (size_t j = 0; j < this->size; j++)\n        {\n          if (func(this->data[j]))\n            move_forward++;\n          else\n            {\n              if (move_forward > 0)\n                this->data[j-move_forward] = this->data[j];\n            }\n        }\n      this->size -= move_forward;\n    }\n\n    /// Delete last element. \n    NETGEN_INLINE void DeleteLast ()\n    {\n      NETGEN_CHECK_RANGE(size-1,0,size);\n      size--;\n    }\n\n    /// Deallocate memory\n    NETGEN_INLINE void DeleteAll ()\n    {\n      if(mem_to_delete)\n        mt.Free(sizeof(T)*allocsize);\n      delete [] mem_to_delete;\n      mem_to_delete = NULL;\n      data = 0;\n      size = allocsize = 0;\n    }\n\n    /// Fill array with val\n    NETGEN_INLINE Array & operator= (const T & val)\n    {\n      FlatArray<T,IndexType>::operator= (val);\n      return *this;\n    }\n\n    /// array copy\n    NETGEN_INLINE Array & operator= (const Array & a2)\n    {\n      if constexpr (std::is_copy_assignable<T>::value)\n        {\n          SetSize0 ();\n          SetSize (a2.Size());\n          for (size_t i = 0; i < size; i++)\n            data[i] = a2.data[i];\n          return *this;\n        }\n#ifndef __CUDA_ARCH__      \n      else\n        throw Exception(std::string(\"cannot copy Array of type \") + typeid(T).name());\n#endif\n    }\n\n    \n    /// steal array \n    NETGEN_INLINE Array & operator= (Array && a2)\n    {\n      mt = std::move(a2.mt);\n      ngcore::Swap (size, a2.size);\n      ngcore::Swap (data, a2.data);\n      ngcore::Swap (allocsize, a2.allocsize);\n      ngcore::Swap (mem_to_delete, a2.mem_to_delete);\n      return *this;\n    }\n\n\n    /// array copy\n    NETGEN_INLINE Array & operator= (const FlatArray<T> & a2)\n    {\n      SetSize (a2.Size());\n      for (size_t i = 0; i < size; i++)\n        data[i] = a2[i];\n      return *this;\n    }\n\n    /*\n    /// fill array with first, first+1, ... \n    Array & operator= (const IntRange & range)\n    {\n      SetSize (range.Size());\n      for (int i = 0; i < size; i++)\n        (*this)[i] = range.First()+i;\n      return *this;\n    }\n    */\n    template <typename T2>\n    Array & operator= (const BaseArrayObject<T2> & a2)\n    {\n      size_t newsize = a2.Spec().Size();\n      SetSize0 ();      \n      SetSize (newsize);\n      // for (size_t i = 0; i < newsize; i++)\n      // (*this)[i] = a2.Spec()[i];\n      size_t i = 0;\n      for (auto val : a2.Spec())\n        (*this)[i++] = val;\n      \n      return *this;\n    }\n\n    template <typename ...ARGS>\n    Array & operator= (Tuple<ARGS...> tup)\n    {\n      SetSize (ArraySize (tup));\n      StoreToArray (*this, tup);\n      return *this;\n    }\n\n    Array & operator= (std::initializer_list<T> list)\n    {\n      *this = Array<T> (list); \n      return *this;\n    }\n      \n\n//     template <typename T2>\n//     Array & operator= (ParallelValue<T2> val)\n//     {\n//       FlatArray<T>::operator= (val);\n//       return *this;\n//     }\n//     template <typename T2>\n//     Array & operator= (ParallelFunction<T2> val)\n//     {\n//       FlatArray<T>::operator= (val);\n//       return *this;\n//     }\n\n    \n    NETGEN_INLINE void Swap (Array & b)\n    {\n      mt = std::move(b.mt);\n      ngcore::Swap (size, b.size);\n      ngcore::Swap (data, b.data);\n      ngcore::Swap (allocsize, b.allocsize);\n      ngcore::Swap (mem_to_delete, b.mem_to_delete);\n    }\n\n    NETGEN_INLINE void StartMemoryTracing () const\n    {\n      if(mem_to_delete)\n        mt.Alloc(sizeof(T) * allocsize);\n    }\n\n    const MemoryTracer& GetMemoryTracer() const { return mt; }\n\n  private:\n\n    /// resize array, at least to size minsize. copy contents\n    NETGEN_INLINE void ReSize (size_t minsize);\n  };\n\n  \n  /// resize array, at least to size minsize. copy contents\n  template <class T, class IndexType> \n  NETGEN_INLINE void Array<T, IndexType> :: ReSize (size_t minsize)\n  {\n    size_t nsize = 2 * allocsize;\n    if (nsize < minsize) nsize = minsize;\n    \n    T * hdata = data;\n    data = new T[nsize];\n    mt.Alloc(sizeof(T) * nsize);\n\n    if (hdata)\n      {\n        size_t mins = (nsize < size) ? nsize : size;\n#if defined(__GNUG__) && __GNUC__ < 5 && !defined(__clang__)\n        for (size_t i = 0; i < mins; i++) data[i] = std::move(hdata[i]);\n#else\n        if (std::is_trivially_copyable<T>::value)\n          memcpy ((void*)data, hdata, sizeof(T)*mins);\n        else\n          for (size_t i = 0; i < mins; i++) data[i] = std::move(hdata[i]);\n#endif\n        if(mem_to_delete)\n          mt.Free(sizeof(T) * allocsize);\n        delete [] mem_to_delete;\n      }\n\n    mem_to_delete = data;\n    allocsize = nsize;\n  }\n\n  //extern template class Array<int,int>;\n  \n\n  /**\n     Array with static and dynamic memory management.\n     Declares a static array which size is given by the template parameter.\n     If the dynamic size fits into the static size, use static memory, \n     otherwise perform dynamic allocation\n  */\n  template <class T, int S> \n  class ArrayMem : public Array<T>\n  {\n    T mem[S];    \n\n    using Array<T>::size;\n    using Array<T>::allocsize;\n    using Array<T>::data;\n    using Array<T>::mem_to_delete;\n    using Array<T>::mt;\n    // using Array<T>::ownmem;\n\n  public:\n    /// Generate array of logical and physical size asize\n    explicit ArrayMem(size_t asize = 0)    \n      : Array<T> (S, mem)\n    {\n      size = asize;\n      if (asize > S)\n        {\n          data = new T[asize];\n          allocsize = size;\n          mem_to_delete = data;\n          mt.Alloc(sizeof(T)*asize);\n        }\n    }\n\n    /// copies from Array a2\n    explicit ArrayMem(const Array<T> & a2)\n      : Array<T> (S, (T*)mem)\n    {\n      Array<T>::operator= (a2);\n    }\n\n    /// copies from ArrayMem a2\n    explicit ArrayMem(const ArrayMem & a2)\n      : Array<T> (S, (T*)mem)\n    {\n      Array<T>::operator= (a2);\n    }\n  \n    ArrayMem(ArrayMem && a2)\n      : Array<T> (a2.Size(), (T*)mem)\n    {\n      mt = std::move(a2.mt);\n      if (a2.mem_to_delete)\n        {\n          mem_to_delete = a2.mem_to_delete;\n          data = a2.data;\n          allocsize = a2.allocsize;\n          a2.mem_to_delete = nullptr;\n          a2.data = nullptr;\n          a2.size = 0;\n        }\n      else\n        {\n          allocsize = S;\n          for (auto i : ngcore::Range(size))\n            mem[i] = a2.mem[i];\n        }\n    }\n    \n    ArrayMem (std::initializer_list<T> list)\n      : ArrayMem (list.size())\n    {\n      size_t cnt = 0;\n      for (auto val : list)\n        data[cnt++] = val;\n    }\n  \n    template <typename T2>\n    ArrayMem (const BaseArrayObject<T2> & a2)\n      : ArrayMem (a2.Size())\n    {\n      for (size_t i : ngcore::Range(size))\n        data[i] = a2[i];\n    }\n\n    \n    ArrayMem & operator= (const T & val)\n    {\n      FlatArray<T>::operator= (val);\n      return *this;\n    }\n\n    ArrayMem & operator= (ArrayMem && a2)\n    {\n      mt = std::move(a2.mt);\n      ngcore::Swap (mem_to_delete, a2.mem_to_delete);\n      ngcore::Swap (allocsize, a2.allocsize);\n      ngcore::Swap (size, a2.size);\n\n      if (mem_to_delete==nullptr)\n      {\n        for (auto i : ngcore::Range(size))\n          mem[i] = std::move(a2.mem[i]);\n        data = mem;\n      }\n      else\n        ngcore::Swap (data, a2.data);\n\n      return *this;\n    }\n\n\n    /// array copy\n    ArrayMem & operator= (const FlatArray<T> & a2)\n    {\n      this->SetSize (a2.Size());\n      for (size_t i = 0; i < size; i++)\n        (*this)[i] = a2[i];\n      return *this;\n    }\n\n\n    template <typename T2>\n    ArrayMem & operator= (const BaseArrayObject<T2> & a2)\n    {\n      this->SetSize (a2.Spec().Size());\n\n      size_t i = 0;\n      for (auto val : a2.Spec())\n        (*this)[i++] = val;\n      \n      return *this;\n    }\n\n  };\n\n\n\n\n\n  template <typename ... ARGS>\n  size_t ArraySize (Tuple<ARGS...> /* tup */)  \n  { return 0;}\n  \n  template <typename ... ARGS>\n  size_t ArraySize (Tuple<int,ARGS...> tup) \n  { return 1+ArraySize(tup.Tail()); }\n  \n  template <typename ... ARGS>\n  size_t ArraySize (Tuple<IntRange,ARGS...> tup) \n  { return tup.Head().Size()+ArraySize(tup.Tail()); }\n\n  \n  template <typename T, typename ... ARGS>\n  void StoreToArray (FlatArray<T> /* a */, Tuple<ARGS...> /* tup */) { ; }\n  \n  template <typename T, typename ... ARGS>\n  void StoreToArray (FlatArray<T> a, Tuple<int,ARGS...> tup)\n  {\n    a[0] = tup.Head();\n    StoreToArray (a.Range(1, a.Size()), tup.Tail());\n  }\n  \n  template <typename T, typename ... ARGS>\n  void StoreToArray (FlatArray<T> a, Tuple<IntRange,ARGS...> tup)\n  {\n    IntRange r = tup.Head();\n    a.Range(0,r.Size()) = r;\n    StoreToArray (a.Range(r.Size(), a.Size()), tup.Tail());\n  }\n\n  /*\n  template <typename T> template <typename ...ARGS>\n  NETGEN_INLINE Array<T> & Array<T> :: operator= (Tuple<ARGS...> tup)\n  {\n    SetSize (ArraySize (tup));\n    StoreToArray (*this, tup);\n  }\n  */\n\n  /*\n  /// append integers to array\n  inline Array<int> & operator+= (Array<int> & array, const IntRange & range)\n  {\n    int oldsize = array.Size();\n    int s = range.Next() - range.First();\n    \n    array.SetSize (oldsize+s);\n\n    for (int i = 0; i < s; i++)\n      array[oldsize+i] = range.First()+i;\n\n    return array;\n  }\n  */\n  \n\n  /*\n  template <typename T, typename T2>\n  inline Array<T> & operator+= (Array<T> & array, const BaseArrayObject<T2> & a2)\n  {\n    size_t oldsize = array.Size();\n    size_t s = a2.Spec().Size();\n    \n    array.SetSize (oldsize+s);\n\n    for (size_t i = 0; i < s; i++)\n      array[oldsize+i] = a2.Spec()[i];\n\n    return array;\n  }\n  */\n  \n  template <typename T, typename T2>\n  inline Array<T> & operator+= (Array<T> & array, const BaseArrayObject<T2> & a2)\n  {\n    auto oldsize = array.Size();\n    auto s = a2.Spec().Size();\n\n    array.SetSize (oldsize+s);\n\n    for (auto val : a2.Spec())\n      array[oldsize++] = val;\n    \n    return array;\n  }\n\n  template <typename T, typename T2>\n  inline Array<T> operator+= (Array<T> && array, const BaseArrayObject<T2> & a2)\n  {\n    array += a2;\n    return std::move(array);\n  }\n\n\n  /// bubble sort array\n  template <class T>\n  inline void BubbleSort (FlatArray<T> data)\n  {\n    T hv;\n    for (size_t i = 0; i < data.Size(); i++)\n      for (size_t j = i+1; j < data.Size(); j++)\n        if (data[i] > data[j])\n          {\n            hv = data[i];\n            data[i] = data[j];\n            data[j] = hv;\n          }\n  }\n\n  /// bubble sort array\n  template <class T, class S>\n  inline void BubbleSort (FlatArray<T> data, FlatArray<S> index)\n  {\n    for (size_t i = 0; i < data.Size(); i++)\n      for (size_t j = i+1; j < data.Size(); j++)\n\tif (data[i] > data[j])\n\t  {\n\t    T hv = data[i];\n\t    data[i] = data[j];\n\t    data[j] = hv;\n\n\t    S hvs = index[i];\n\t    index[i] = index[j];\n\t    index[j] = hvs;\n\t  }\n  }\n\n\n\n\n  template <class T, typename TLESS>\n  void QuickSort (FlatArray<T> data, TLESS less)\n  {\n    constexpr size_t INSERTION_SORT_THRESHOLD = 16;\n    \n    if (data.Size() <= INSERTION_SORT_THRESHOLD) {\n      // insertion sort\n      for (ptrdiff_t k = 1; k < data.Size(); ++k)\n        {\n          auto newval = data[k];\n          ptrdiff_t l = k;\n          for ( ; l > 0 && less(newval, data[l-1]); --l)\n            data[l] = data[l-1];\n          data[l] = newval;\n        }\n      \n      return;\n    }\n\n    // if (data.Size() <= 1) return;\n    \n    ptrdiff_t i = 0;\n    ptrdiff_t j = data.Size()-1;\n\n    T midval = data[ (i+j)/2 ];\n  \n    do\n      {\n        while (less (data[i], midval)) i++;\n        while (less (midval, data[j])) j--;\n\n        if (i <= j)\n          {\n\t    Swap (data[i], data[j]);\n            i++; j--;\n          }\n      }\n    while (i <= j);\n\n    QuickSort (data.Range (0, j+1), less);\n    QuickSort (data.Range (i, data.Size()), less);\n  }\n\n  template <typename T>\n  NETGEN_INLINE bool DefaultLess (const T & a, const T & b)\n  {\n    return a < b;\n  }\n\n  template <typename T>\n  class DefaultLessCl\n  {\n  public:\n    bool operator() (const T & a, const T & b) const\n    {\n      return a < b;\n    }\n  };\n\n\n\n  template <class T>\n  NETGEN_INLINE void QuickSort (FlatArray<T> data)\n  {\n    QuickSort (data, DefaultLessCl<T>());\n  }\n\n\n\n  template <class T, typename TLESS>\n  void QuickSortI (FlatArray<T> data, FlatArray<int> index, TLESS less)\n  {\n    if (index.Size() <= 1) return;\n\n    ptrdiff_t i = 0;\n    ptrdiff_t j = index.Size()-1;\n\n    int midval = index[ (i+j)/2 ];\n  \n    do\n      {\n        while (less (data[index[i]],data[midval])  ) i++;\n        while (less (data[midval],  data[index[j]])) j--;\n\n        if (i <= j)\n          {\n\t    Swap (index[i], index[j]);\n            i++; j--;\n          }\n      }\n    while (i <= j);\n\n    QuickSortI (data, index.Range (0, j+1), less);\n    QuickSortI (data, index.Range (i, index.Size()), less);\n  }\n\n\n  template <class T>\n  NETGEN_INLINE void QuickSortI (FlatArray<T> data, FlatArray<int> index)\n  {\n    QuickSortI (data, index, DefaultLessCl<T>());\n  }\n\n\n\n\n\n  template <typename T>\n  NETGEN_INLINE T xxxRemoveRef (const T & x)\n  {\n    return x;\n  }\n\n  template <class TA1, class TA2> \n  class SumArray : public BaseArrayObject<SumArray<TA1,TA2>>\n  {\n    const TA1 & a1;\n    const TA2 & a2;\n  public:\n    SumArray (const TA1 & aa1, const TA2 & aa2) : a1(aa1), a2(aa2) { ; }\n    size_t Size() const { return a1.Size()+a2.Size(); }\n    auto operator[] (size_t i) const -> decltype (xxxRemoveRef (a1[0])) \n    {\n      return (i < a1.Size()) ? a1[i] : a2[i-a1.Size()];\n    }\n  };\n\n  template <class TA1, class TA2> \n  SumArray<TA1,TA2> operator+ (const BaseArrayObject<TA1> & a1,\n                               const BaseArrayObject<TA2> & a2)\n  {\n    return SumArray<TA1,TA2> (a1.Spec(), a2.Spec());\n  }\n                               \n\n  struct HTAHelp { };\n  \n  // head-tail array\n  template <size_t S, typename T>\n  class HTArray\n  {\n    HTArray<S-1,T> tail;\n    T head;\n  public:\n    constexpr HTArray () = default;\n    constexpr HTArray (const HTArray &) = default;\n    template <typename T2>\n    constexpr HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }\n\n    constexpr HTArray (T v) : tail(v), head(v) { } // all the same\n    \n    template <class... T2,\n              std::enable_if_t<S==1+sizeof...(T2),bool> = true>\n    constexpr HTArray (const T &v, T2... rest)\n      : tail{HTAHelp(), v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }\n\n    template <class... T2>\n    constexpr HTArray (HTAHelp h, const T &v, T2... rest)\n      : tail{h, v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }\n\n    \n    HTArray & operator= (const HTArray &) = default;\n\n    T * Ptr () { return tail.Ptr(); }\n    T & operator[] (size_t i) { return Ptr()[i]; }\n\n    const T * Ptr () const { return tail.Ptr(); }\n    const T & operator[] (size_t i) const { return Ptr()[i]; }\n    template <int NR>\n    T & Elem() { return (NR==S-1) ? head : tail.template Elem<NR>(); }\n\n    auto Tail() const { return tail; }\n    auto Head() const { return head; }\n  };\n\n  template <typename T>\n  class HTArray<1,T>\n  {\n    T head;\n  public:\n    constexpr HTArray () = default;\n    constexpr HTArray (const HTArray &) = default;\n    template <typename T2>\n    constexpr HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }\n    constexpr HTArray (T v) : head(v) { } // all the same\n    template <class... T2>    \n    constexpr HTArray (HTAHelp h, const T &v, T2... rest)\n      : head(v) { } \n\n    \n    HTArray & operator= (const HTArray &) = default;\n\n    T * Ptr () { return &head; }\n    T & operator[] (size_t i) { return Ptr()[i]; }\n\n    const T * Ptr () const { return &head; }\n    const T & operator[] (size_t i) const { return Ptr()[i]; }\n    template <int NR>    \n    T & Elem()\n    {\n      // assert(NR==0, \"HTArray index error\");\n      return head;\n    }\n\n    auto Head() const { return head; }\n  };\n\n  template <typename T>\n  class HTArray<0,T>\n  {\n    // T head; // dummy variable\n  public:\n    HTArray () = default;\n    HTArray (const HTArray &) = default;\n    template <typename T2>\n    HTArray (const HTArray<0,T2> & a2) { ; }\n    constexpr HTArray (T v) { } // all the same    \n    HTArray & operator= (const HTArray &) = default;\n\n    /*\n    T * Ptr () { return &head; }\n    T & operator[] (size_t i) { return Ptr()[i]; }\n\n    const T * Ptr () const { return &head; }\n    const T & operator[] (size_t i) const { return Ptr()[i]; }\n    template <int NR>        \n    T & Elem()\n    {\n      // assert(false, \"HTArray index error\");\n      return head;\n    }\n    */\n    // T * Ptr () { return (T*)(void*)&head; }\n    T * Ptr () { return (T*)(void*)this; }\n    T & operator[] (size_t i) { return Ptr()[i]; }\n    // const T * Ptr () const { return (const T*)(const void*)&head; }\n    const T * Ptr () const { return (const T*)(const void*)this; }\n    const T & operator[] (size_t i) const { return Ptr()[i]; }\n    template <int NR>        \n    T & Elem()\n    {\n      throw Exception(\"illegal HTArray<0>::Elem<0>\");\n    }\n\n  };\n\n  template<size_t S, typename T>\n  const T * operator+ (const HTArray<S,T> & ar, size_t i)\n  {\n    return ar.Ptr()+i;\n  }\n  template<size_t S, typename T>\n  T * operator+ (HTArray<S,T> & ar, size_t i)\n  {\n    return ar.Ptr()+i;\n  }\n\n\n\n\n\n\n\n\n\n\n  template <typename TIA, typename TIB>\n  class IteratorPair\n  {\n    TIA a;\n    TIB b;\n  public:\n    IteratorPair (TIA _a, TIB _b) : a(_a), b(_b) { ; }\n    \n    IteratorPair & operator++() { ++a; ++b; return *this; }\n    bool operator!= (const IteratorPair & it2)  { return a != it2.a; }\n    \n    auto operator*()\n    {\n      // return pair(*a,*b);\n      return std::pair<decltype(*a), decltype(*b)> (*a, *b); // keep reference\n    }\n  };\n  \n  \n  template <typename TA, typename TB>\n  class Zip\n  {\n    const TA & a;\n    const TB & b;\n  public:\n    Zip(const TA & _a, const TB & _b) : a(_a), b(_b) { ; }\n    auto begin() const { return IteratorPair(a.begin(), b.begin()); }\n    auto end() const { return IteratorPair(a.end(), b.end()); }\n  };\n\n  template <typename T>\n  inline size_t size (const BaseArrayObject<T> & ao) { return ao.Size(); }\n  \n  template <typename TA>\n  class Enumerate\n  {\n    IntRange r;\n    const TA & a;\n  public:\n    Enumerate(const TA & _a) : r(size(_a)), a(_a) { ; }\n    auto begin() const { return IteratorPair(r.begin(), a.begin()); }\n    auto end() const { return IteratorPair(r.end(), a.end()); }\n  };\n  \n  \n\n\n  \n}\n\n\n#endif // NETGEN_CORE_ARRAY_HPP\n\n"
  },
  {
    "path": "libsrc/core/autodiff.hpp",
    "content": "#ifndef FILE_AUTODIFF\n#define FILE_AUTODIFF\n\n/**************************************************************************/\n/* File:   autodiff.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   24. Oct. 02                                                    */\n/**************************************************************************/\n\nnamespace ngcore\n{\n\n// Automatic differentiation datatype\n\n  template <int D, typename SCAL = double> class AutoDiffRec;\n\n\n/**\n   Datatype for automatic differentiation.\n   Contains function value and D derivatives. Algebraic\n   operations are overloaded by using product-rule etc. etc. \n**/\ntemplate <int D, typename SCAL = double>\nclass AutoDiffVec\n{\n  SCAL val;\n  SCAL dval[D?D:1];\npublic:\n\n  typedef AutoDiffVec<D,SCAL> TELEM;\n  typedef SCAL TSCAL;\n\n\n  /// elements are undefined\n  // NETGEN_INLINE AutoDiffVec  () throw() { };\n  AutoDiffVec() = default;\n  // { val = 0; for (int i = 0; i < D; i++) dval[i] = 0; }  // !\n\n  /// copy constructor\n  AutoDiffVec  (const AutoDiffVec & ad2) = default;\n  /*\n  NETGEN_INLINE AutoDiffVec  (const AutoDiffVec & ad2) throw()\n  {\n    val = ad2.val;\n    for (int i = 0; i < D; i++)\n      dval[i] = ad2.dval[i];\n  }\n  */\n  /// initial object with constant value\n  NETGEN_INLINE AutoDiffVec  (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n  }\n\n  /// init object with (val, e_diffindex)\n  NETGEN_INLINE AutoDiffVec  (SCAL aval, int diffindex)  throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    dval[diffindex] = 1;\n  }\n\n  NETGEN_INLINE AutoDiffVec (SCAL aval, const SCAL * grad)\n  {\n    val = aval;\n    LoadGradient (grad);\n  }\n\n  /// assign constant value\n  NETGEN_INLINE AutoDiffVec & operator= (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    return *this;\n  }\n\n  AutoDiffVec & operator= (const AutoDiffVec & ad2) = default;\n  \n  /// returns value\n  NETGEN_INLINE SCAL Value() const throw() { return val; }\n  \n  /// returns partial derivative\n  NETGEN_INLINE SCAL DValue (int i) const throw() { return dval[i]; }\n\n  ///\n  NETGEN_INLINE void StoreGradient (SCAL * p) const \n  {\n    for (int i = 0; i < D; i++)\n      p[i] = dval[i];\n  }\n\n  NETGEN_INLINE void LoadGradient (const SCAL * p) \n  {\n    for (int i = 0; i < D; i++)\n      dval[i] = p[i];\n  }\n\n  /// access value\n  NETGEN_INLINE SCAL & Value() throw() { return val; }\n\n  /// accesses partial derivative \n  NETGEN_INLINE SCAL & DValue (int i) throw() { return dval[i]; }\n};\n\n\n//@{  AutoDiffVec helper functions.\n\n/// prints AutoDiffVec\ntemplate<int D, typename SCAL>\ninline ostream & operator<< (ostream & ost, const AutoDiffVec<D,SCAL> & x)\n{\n  ost << x.Value() << \", D = \";\n  for (int i = 0; i < D; i++)\n    ost << x.DValue(i) << \" \";\n  return ost;\n}\n\n/// AutoDiffVec plus AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator+ (const AutoDiffVec<D,SCAL> & x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value () = x.Value()+y.Value();\n  // AutoDiffVec<D,SCAL> res(x.Value()+y.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) + y.DValue(i);\n  return res;\n}\n\n\n/// AutoDiffVec minus AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator- (const AutoDiffVec<D,SCAL> & x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x.Value()-y.Value();\n  // AutoDiffVec<D,SCAL> res (x.Value()-y.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) - y.DValue(i);\n  return res;\n}\n\n/// double plus AutoDiffVec\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator+ (SCAL2 x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  return res;\n}\n\n/// AutoDiffVec plus double\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator+ (const AutoDiffVec<D,SCAL> & y, SCAL2 x) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  return res;\n}\n\n\n/// minus AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator- (const AutoDiffVec<D,SCAL> & x) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = -x.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i);\n  return res;\n}\n\n/// AutoDiffVec minus double\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator- (const AutoDiffVec<D,SCAL> & x, SCAL2 y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x.Value()-y;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i);\n  return res;\n}\n\n///\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator- (SCAL2 x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x-y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -y.DValue(i);\n  return res;\n}\n\n\n/// double times AutoDiffVec\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator* (SCAL2 x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  return res;\n}\n\n/// AutoDiffVec times double\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n\n  NETGEN_INLINE AutoDiffVec<D,SCAL> operator* (const AutoDiffVec<D,SCAL> & y, SCAL2 x) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  return res;\n}\n\n/// AutoDiffVec times AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator* (const AutoDiffVec<D,SCAL> & x, const AutoDiffVec<D,SCAL> & y) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL hx = x.Value();\n  SCAL hy = y.Value();\n\n  res.Value() = hx*hy;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);\n\n  return res;\n}\n\n/// AutoDiffVec times AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> sqr (const AutoDiffVec<D,SCAL> & x) throw()\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL hx = x.Value();\n  res.Value() = hx*hx;\n  hx *= 2;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = hx*x.DValue(i);\n  return res;\n}\n\n/// Inverse of AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> Inv (const AutoDiffVec<D,SCAL> & x)\n{\n  AutoDiffVec<D,SCAL> res(1.0 / x.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());\n  return res;\n}\n\n\n/// AutoDiffVec div AutoDiffVec\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator/ (const AutoDiffVec<D,SCAL> & x, const AutoDiffVec<D,SCAL> & y)\n{\n  return x * Inv (y);\n}\n\n/// AutoDiffVec div double\ntemplate<int D, typename SCAL, typename SCAL2,\n         typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\nNETGEN_INLINE AutoDiffVec<D,SCAL> operator/ (const AutoDiffVec<D,SCAL> & x, SCAL2 y)\n{\n  return (1.0/y) * x;\n}\n\n  /// double div AutoDiffVec\ntemplate<int D, typename SCAL, typename SCAL2,\n         typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> operator/ (SCAL2 x, const AutoDiffVec<D,SCAL> & y)\n  {\n    return x * Inv(y);\n  }\n  \n\n\n  \n  template <int D, typename SCAL, typename SCAL2>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator+= (AutoDiffVec<D,SCAL> & x, SCAL2 y) throw()\n  {\n    x.Value() += y;\n    return x;\n  }\n\n\n  /// \n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator+= (AutoDiffVec<D,SCAL> & x, AutoDiffVec<D,SCAL> y)\n  {\n    x.Value() += y.Value();\n    for (int i = 0; i < D; i++)\n      x.DValue(i) += y.DValue(i);\n    return x;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator-= (AutoDiffVec<D,SCAL> & x, AutoDiffVec<D,SCAL> y)\n  {\n    x.Value() -= y.Value();\n    for (int i = 0; i < D; i++)\n      x.DValue(i) -= y.DValue(i);\n    return x;\n\n  }\n\n  template <int D, typename SCAL, typename SCAL2>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator-= (AutoDiffVec<D,SCAL> & x, SCAL2 y)\n  {\n    x.Value() -= y;\n    return x;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator*= (AutoDiffVec<D,SCAL> & x, AutoDiffVec<D,SCAL> y) \n  {\n    for (int i = 0; i < D; i++)\n      x.DValue(i) = x.DValue(i)*y.Value() + x.Value() * y.DValue(i);\n    x.Value() *= y.Value();\n    return x;\n  }\n\n  ///\n  template <int D, typename SCAL, typename SCAL2>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator*= (AutoDiffVec<D,SCAL> & x, SCAL2 y) \n  {\n    x.Value() *= y;\n    for (int i = 0; i < D; i++)\n      x.DValue(i) *= y;\n    return x;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> & operator/= (AutoDiffVec<D,SCAL> & x, SCAL y) \n  {\n    SCAL iy = 1.0 / y;\n    x.Value() *= iy;\n    for (int i = 0; i < D; i++)\n      x.DValue(i) *= iy;\n    return x;\n  }\n\n\n\n\n  /// \n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator== (AutoDiffVec<D,SCAL> x, SCAL val2) \n  {\n    return x.Value() == val2;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator!= (AutoDiffVec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() != val2;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator< (AutoDiffVec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() < val2;\n  }\n  \n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator> (AutoDiffVec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() > val2;\n  }\n\n\n\n\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> fabs (const AutoDiffVec<D,SCAL> & x)\n{\n  double abs = fabs (x.Value());\n  AutoDiffVec<D,SCAL> res( abs );\n  if (abs != 0.0)\n    for (int i = 0; i < D; i++)\n      res.DValue(i) = x.Value()*x.DValue(i) / abs;\n  else\n    for (int i = 0; i < D; i++)\n      res.DValue(i) = 0.0;\n  return res;\n}\n\nusing std::sqrt;\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> sqrt (const AutoDiffVec<D,SCAL> & x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = sqrt(x.Value());\n  for (int j = 0; j < D; j++)\n    res.DValue(j) = 0.5 / res.Value() * x.DValue(j);\n  return res;\n}\n\nusing std::log;\ntemplate <int D, typename SCAL>\nAutoDiffVec<D,SCAL> log (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = log(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) / x.Value();\n  return res;\n}\n\nusing std::exp;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> exp (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = exp(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * res.Value();\n  return res;\n}\n\nusing std::pow;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> pow (AutoDiffVec<D,SCAL> x, AutoDiffVec<D,SCAL> y )\n{\n  return exp(log(x)*y);\n}\n\nusing std::sin;\n/*\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> sin (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = sin(x.Value());\n  SCAL c = cos(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * c;\n  return res;\n}\n*/\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> sin (AutoDiffVec<D,SCAL> x)\n{\n  return sin(AutoDiffRec<D,SCAL>(x));\n}\n  \nusing std::cos;\n/*\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> cos (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = cos(x.Value());\n  SCAL ms = -sin(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * ms;\n  return res;\n}\n*/\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> cos (AutoDiffVec<D,SCAL> x)\n{\n  return cos(AutoDiffRec<D,SCAL>(x));\n}\n\nusing std::tan;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> tan (AutoDiffVec<D,SCAL> x)\n{ return sin(x) / cos(x); }\n\nusing std::sinh;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> sinh (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = sinh(x.Value());\n  SCAL ch = cosh(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * ch;\n  return res;\n}\n\nusing std::cosh;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> cosh (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = cosh(x.Value());\n  SCAL sh = sinh(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * sh;\n  return res;\n}\n\nusing std::erf;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> erf (AutoDiffVec<D,SCAL> x)\n{\n  return erf(AutoDiffRec<D,SCAL>(x));\n}\n\nusing std::floor;\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> floor (const AutoDiffVec<D,SCAL> & x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = floor(x.Value());\n  for (int j = 0; j < D; j++)\n    res.DValue(j) = 0.0;\n  return res;\n}\n\nusing std::ceil;\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> ceil (const AutoDiffVec<D,SCAL> & x)\n{\n  AutoDiffVec<D,SCAL> res;\n  res.Value() = ceil(x.Value());\n  for (int j = 0; j < D; j++)\n    res.DValue(j) = 0.0;\n  return res;\n}\n\n\nusing std::atan;\n/*\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> atan (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL a = atan(x.Value());\n  res.Value() = a;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)/(1+x.Value()*x.Value()) ;\n  return res;\n}\n*/\ntemplate <int D, typename SCAL>\nAutoDiffVec<D,SCAL> atan (AutoDiffVec<D,SCAL> x)\n{\n  return atan (AutoDiffRec<D,SCAL> (x));\n}\n\nusing std::atan2;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> atan2 (AutoDiffVec<D,SCAL> x, AutoDiffVec<D,SCAL> y)\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL a = atan2(x.Value(), y.Value());\n  res.Value() = a;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = (x.Value()*y.DValue(k)-y.Value()*x.DValue(k))/(y.Value()*y.Value()+x.Value()*x.Value());\n  return res;\n}\n\n\nusing std::acos;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> acos (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL a = acos(x.Value());\n  res.Value() = a;\n  SCAL da = -1 / sqrt(1-x.Value()*x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)*da;\n  return res;\n}\n\n\nusing std::asin;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffVec<D,SCAL> asin (AutoDiffVec<D,SCAL> x)\n{\n  AutoDiffVec<D,SCAL> res;\n  SCAL a = asin(x.Value());\n  res.Value() = a;\n  SCAL da = 1 / sqrt(1-x.Value()*x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)*da;\n  return res;\n}\n\n\n\n\n  template <int D, typename SCAL, typename TB, typename TC>\n  auto IfPos (AutoDiffVec<D,SCAL> a, TB b, TC c) // -> decltype(IfPos (a.Value(), b, c))\n  {\n    return IfPos (a.Value(), b, c);\n  }\n\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffVec<D,SCAL> b, AutoDiffVec<D,SCAL> c)\n  {\n    AutoDiffVec<D,SCAL> res;\n    res.Value() = IfPos (a, b.Value(), c.Value());\n    for (int j = 0; j < D; j++)\n      res.DValue(j) = IfPos (a, b.DValue(j), c.DValue(j));\n    return res;\n  }\n\n  template <int D, typename SCAL, typename TC>\n  NETGEN_INLINE AutoDiffVec<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffVec<D,SCAL> b, TC c)\n  {\n    return IfPos (a, b, AutoDiffVec<D,SCAL> (c));\n  }\n\n//@}\n\n\n  \n  template <int D, typename SCAL>\n  class AutoDiffRec\n  {\n    AutoDiffRec<D-1, SCAL> rec;\n    SCAL last;\n\n  public:\n    AutoDiffRec () = default;\n    AutoDiffRec (const AutoDiffRec &) = default;\n    NETGEN_INLINE AutoDiffRec (AutoDiffRec<D-1,SCAL> _rec, SCAL _last) : rec(_rec), last(_last) { ; }\n    AutoDiffRec & operator= (const AutoDiffRec &) = default;\n\n    NETGEN_INLINE AutoDiffRec (SCAL aval) : rec(aval), last(0.0) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL aval, int diffindex) : rec(aval, diffindex), last((diffindex==D-1) ? 1.0 : 0.0) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL aval, const SCAL * grad)\n      : rec(aval, grad), last(grad[D-1]) { } \n\n    NETGEN_INLINE AutoDiffRec (const AutoDiffVec<D,SCAL> & ad)\n    {\n      Value() = ad.Value();\n      for (int i = 0; i < D; i++)\n        DValue(i) = ad.DValue(i);\n    }\n    \n    NETGEN_INLINE AutoDiffRec & operator= (SCAL aval) { rec = aval; last = 0.0; return *this; }\n    NETGEN_INLINE SCAL Value() const { return rec.Value(); }\n    NETGEN_INLINE SCAL DValue(int i) const { return (i == D-1) ? last : rec.DValue(i); }\n    NETGEN_INLINE SCAL & Value() { return rec.Value(); }\n    NETGEN_INLINE SCAL & DValue(int i) { return (i == D-1) ? last : rec.DValue(i); }\n    NETGEN_INLINE auto Rec() const { return rec; }\n    NETGEN_INLINE auto Last() const { return last; }\n    NETGEN_INLINE auto & Rec() { return rec; }\n    NETGEN_INLINE auto & Last() { return last; }\n    NETGEN_INLINE operator AutoDiffVec<D,SCAL> () const\n    {\n      AutoDiffVec<D,SCAL> res(Value());\n      for (int i = 0; i < D; i++)\n        res.DValue(i) = DValue(i);\n      return res;\n    }\n  };\n\n  template<int D, typename SCAL>\n  ostream & operator<< (ostream & ost, AutoDiffRec<D,SCAL> ad)\n  {\n    return ost << AutoDiffVec<D,SCAL> (ad);\n  }\n\n  template <typename SCAL>\n  class AutoDiffRec<0,SCAL>\n  {\n    SCAL val;\n  public:\n    AutoDiffRec () = default;\n    AutoDiffRec (const AutoDiffRec &) = default;\n    NETGEN_INLINE AutoDiffRec (SCAL _val) : val(_val) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL _val, SCAL /* _dummylast */) : val(_val) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL aval, const SCAL * /* grad */)\n      : val(aval) { } \n\n    AutoDiffRec & operator= (const AutoDiffRec &) = default;\n    NETGEN_INLINE AutoDiffRec & operator= (SCAL aval) { val = aval; return *this; }\n\n    NETGEN_INLINE SCAL Value() const { return val; }\n    NETGEN_INLINE SCAL DValue(int /* i */) const { return SCAL(0); }\n    NETGEN_INLINE SCAL & Value() { return val; }\n    // SCAL & DValue(int i) { return val; }\n    NETGEN_INLINE auto Rec() const { return val; }\n    NETGEN_INLINE auto Last() const { return SCAL(0); }\n    NETGEN_INLINE auto & Rec() { return val; }\n    NETGEN_INLINE auto & Last() { return val; }\n    NETGEN_INLINE operator AutoDiffVec<0,SCAL> () const { return AutoDiffVec<0,SCAL>(); }\n  };\n\n\n  template <typename SCAL>\n  class AutoDiffRec<1,SCAL>\n  {\n    SCAL val;\n    SCAL last;\n  public:\n    AutoDiffRec () = default;\n    AutoDiffRec (const AutoDiffRec &) = default;\n    NETGEN_INLINE AutoDiffRec (SCAL _val) : val(_val), last(0.0) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL _val, SCAL _last) : val(_val), last(_last) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL aval, int diffindex) : val(aval), last((diffindex==0) ? 1.0 : 0.0) { ; }\n    NETGEN_INLINE AutoDiffRec (SCAL aval, const SCAL * grad)\n      : val(aval), last(grad[0]) { } \n    \n    NETGEN_INLINE AutoDiffRec (const AutoDiffVec<1,SCAL> & ad)\n    {\n      Value() = ad.Value();\n      DValue(0) = ad.DValue(0);\n    }\n\n    AutoDiffRec & operator= (const AutoDiffRec &) = default;\n    NETGEN_INLINE AutoDiffRec & operator= (SCAL aval) { val = aval; last = 0.0; return *this; }\n\n    NETGEN_INLINE SCAL Value() const { return val; }\n    NETGEN_INLINE SCAL DValue(int /* i */) const { return last; }\n    NETGEN_INLINE SCAL & Value() { return val; }\n    NETGEN_INLINE SCAL & DValue(int /* i */) { return last; }\n    NETGEN_INLINE auto Rec() const { return val; }\n    NETGEN_INLINE auto Last() const { return last; }\n    NETGEN_INLINE auto & Rec() { return val; }\n    NETGEN_INLINE auto & Last() { return last; }\n\n    NETGEN_INLINE operator AutoDiffVec<1,SCAL> () const\n    {\n      AutoDiffVec<1,SCAL> res(Value());\n      res.DValue(0) = DValue(0);\n      return res;\n    }\n  };\n\n  template <int D, typename SCAL, typename SCAL2,\n            typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator+ (SCAL2 a, AutoDiffRec<D,SCAL> b)\n  {\n    return AutoDiffRec<D,SCAL> (a+b.Rec(), b.Last());\n  }\n  \n  template <int D, typename SCAL, typename SCAL2,\n            typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator+ (AutoDiffRec<D,SCAL> a, SCAL2 b)\n  {\n    return AutoDiffRec<D,SCAL> (a.Rec()+b, a.Last());\n  }\n  \n  template <int D, typename SCAL>  \n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator+ (AutoDiffRec<D,SCAL> a, AutoDiffRec<D,SCAL> b)\n  {\n    return AutoDiffRec<D,SCAL> (a.Rec()+b.Rec(), a.Last()+b.Last());\n  }\n\n  template <int D, typename SCAL, typename SCAL2,\n            typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator- (SCAL2 b, AutoDiffRec<D,SCAL> a)\n  {\n    return AutoDiffRec<D,SCAL> (b-a.Rec(), -a.Last());\n  }\n  \n  template <int D, typename SCAL, typename SCAL2, \n            typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator- (AutoDiffRec<D,SCAL> a, SCAL2 b)\n  {\n    return AutoDiffRec<D,SCAL> (a.Rec()-b, a.Last());\n  }\n  \n  template <int D, typename SCAL>  \n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator- (AutoDiffRec<D,SCAL> a, AutoDiffRec<D,SCAL> b)\n  {\n    return AutoDiffRec<D,SCAL> (a.Rec()-b.Rec(), a.Last()-b.Last());\n  }\n\n  /// minus AutoDiff\n  template<int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator- (AutoDiffRec<D,SCAL> a)\n  {\n    return AutoDiffRec<D,SCAL> (-a.Rec(), -a.Last());\n  }\n\n  template <int D, typename SCAL>  \n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator* (AutoDiffRec<D,SCAL> a, AutoDiffRec<D,SCAL> b)\n  {\n    return AutoDiffRec<D,SCAL> (a.Rec()*b.Rec(), a.Value()*b.Last()+b.Value()*a.Last());\n  }\n\n  template <int D, typename SCAL, typename SCAL1,\n            typename std::enable_if<std::is_convertible<SCAL1,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator* (AutoDiffRec<D,SCAL> b, SCAL1 a)\n  {\n    return AutoDiffRec<D,SCAL> (a*b.Rec(), a*b.Last());\n  }\n\n  template <int D, typename SCAL, typename SCAL1,\n            typename std::enable_if<std::is_convertible<SCAL1,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator* (SCAL1 a, AutoDiffRec<D,SCAL> b)\n  {\n    return AutoDiffRec<D,SCAL> (a*b.Rec(), a*b.Last());\n  }\n\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> & operator+= (AutoDiffRec<D,SCAL> & a, AutoDiffRec<D,SCAL> b)\n  {\n    a.Rec() += b.Rec();\n    a.Last() += b.Last();\n    return a;\n  }\n\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> & operator-= (AutoDiffRec<D,SCAL> & a, double b)\n  {\n    a.Rec() -= b;\n    return a;\n  }\n\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> & operator-= (AutoDiffRec<D,SCAL> & a, AutoDiffRec<D,SCAL> b)\n  {\n    a.Rec() -= b.Rec();\n    a.Last() -= b.Last();\n    return a;\n  }\n\n\n  template <int D, typename SCAL>  \n  NETGEN_INLINE AutoDiffRec<D,SCAL> & operator*= (AutoDiffRec<D,SCAL> & a, AutoDiffRec<D,SCAL> b)\n  {\n    a = a*b;\n    return a;\n  }\n\n  \n  template <int D, typename SCAL, typename SCAL2>  \n  NETGEN_INLINE AutoDiffRec<D,SCAL> & operator*= (AutoDiffRec<D,SCAL> & b, SCAL2 a)\n  {\n    b.Rec() *= a;\n    b.Last() *= a;\n    return b;\n  }\n\n  /// Inverse of AutoDiffRec\n\n  template <typename SCAL>\n  auto Inv1 (SCAL x)  { return 1.0/x; }\n\n  template<int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> Inv1 (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (Inv1(x.Rec()), (-sqr(1.0/x.Value())) * x.Last());\n  }\n\n  /// AutoDiffRec div AutoDiffRec\n  template<int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator/ (const AutoDiffRec<D,SCAL> & x, const AutoDiffRec<D,SCAL> & y)\n  {\n    return x * Inv1 (y);\n  }\n\n\n  /// AutoDiffVec div double\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator/ (const AutoDiffRec<D,SCAL> & x, SCAL2 y)\n  {\n    return (1.0/y) * x;\n  }\n\n\n  /// double div AutoDiffVec\n  template<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> operator/ (SCAL2 x, const AutoDiffRec<D,SCAL> & y)\n  {\n    return x * Inv1(y);\n  }\n\n\n\n\n\n\n\n  /// \n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator== (AutoDiffRec<D,SCAL> x, SCAL val2) \n  {\n    return x.Value() == val2;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator!= (AutoDiffRec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() != val2;\n  }\n\n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator< (AutoDiffRec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() < val2;\n  }\n  \n  ///\n  template <int D, typename SCAL>\n  NETGEN_INLINE bool operator> (AutoDiffRec<D,SCAL> x, SCAL val2) throw()\n  {\n    return x.Value() > val2;\n  }\n\n  using std::fabs;\n  template<int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> fabs (const AutoDiffRec<D,SCAL> & x)\n  {\n    auto sign = IfPos(x.Value(), SCAL(1.0), IfPos(-x.Value(), SCAL(-1.0), SCAL(0.0)));\n    return AutoDiffRec<D,SCAL> (fabs(x.Rec()), sign*x.Last());\n    // return fabs (AutoDiffVec<D,SCAL>(x));\n    /*\n      double abs = fabs (x.Value());\n      AutoDiffVec<D,SCAL> res( abs );\n      if (abs != 0.0)\n      for (int i = 0; i < D; i++)\n      res.DValue(i) = x.Value()*x.DValue(i) / abs;\n      else\n      for (int i = 0; i < D; i++)\n      res.DValue(i) = 0.0;\n      return res;\n    */\n  }\n\n\n  template<int D, typename SCAL>\n  NETGEN_INLINE auto sqrt (const AutoDiffRec<D,SCAL> & x)\n  {\n    return AutoDiffRec<D,SCAL> (sqrt(x.Rec()), (0.5/sqrt(x.Value()))*x.Last());\n  }\n\n\n\n  template <int D, typename SCAL>\n  auto log (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (log(x.Rec()), (1.0/x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto exp (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (exp(x.Rec()), exp(x.Value())*x.Last());\n  }\n  \n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> pow (AutoDiffRec<D,SCAL> x, AutoDiffRec<D,SCAL> y )\n  {\n    return exp(log(x)*y);\n  }\n\n\n  template <int D, typename SCAL>\n  auto sin (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (sin(x.Rec()), cos(x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto cos (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (cos(x.Rec()), -sin(x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto tan (AutoDiffRec<D,SCAL> x)\n  {\n    return sin(x) / cos(x);\n  }\n\n  template <int D, typename SCAL>\n  auto sinh (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (sinh(x.Rec()), cosh(x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto cosh (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (cosh(x.Rec()), sinh(x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto asinh (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (asinh(x.Rec()), 1/sqrt(sqr(x.Value()+1))*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto acosh (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (acosh(x.Rec()), 1/sqrt(sqr(x.Value()-1))*x.Last());\n  }\n\n\n  template <int D, typename SCAL>\n  auto erf (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (erf(x.Rec()), 2. / sqrt(M_PI) * exp(- x.Value() * x.Value())*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto floor (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (floor(x.Rec()), 0.0);\n  }\n\n  template <int D, typename SCAL>\n  auto ceil (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (ceil(x.Rec()), 0.0);\n  }\n\n\n\n  template <int D, typename SCAL>\n  auto atan (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (atan(x.Rec()), (1./(1.+x.Value()*x.Value()))*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto atan2 (AutoDiffRec<D,SCAL> x, AutoDiffRec<D,SCAL> y)\n  {\n    return AutoDiffRec<D,SCAL> (atan2(x.Rec(), y.Rec()),\n                                (1./(x.Value()*x.Value()+y.Value()*y.Value()))*(x.Value()*y.Last()-y.Value()*x.Last()));\n  }\n\n  template <int D, typename SCAL>\n  auto acos (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (acos(x.Rec()), (-1./sqrt(1.-x.Value()*x.Value()))*x.Last());\n  }\n\n  template <int D, typename SCAL>\n  auto asin (AutoDiffRec<D,SCAL> x)\n  {\n    return AutoDiffRec<D,SCAL> (asin(x.Rec()), (1./sqrt(1.-x.Value()*x.Value()))*x.Last());\n  }\n\n\n  template <int D, typename SCAL, typename TB, typename TC>\n  auto IfPos (AutoDiffRec<D,SCAL> a, TB b, TC c) // -> decltype(IfPos (a.Value(), b, c))\n  {\n    return IfPos (a.Value(), b, c);\n  }\n\n  template <int D, typename SCAL>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffRec<D,SCAL> b, AutoDiffRec<D,SCAL> c)\n  {\n    /*\n    AutoDiffRec<D,SCAL> res;\n    res.Value() = IfPos (a, b.Value(), c.Value());\n    for (int j = 0; j < D; j++)\n      res.DValue(j) = IfPos (a, b.DValue(j), c.DValue(j));\n    return res;\n    */\n    return AutoDiffRec<D,SCAL> (IfPos(a, b.Rec(), c.Rec()), IfPos(a, b.Last(), c.Last()));\n  }\n\n  template <int D, typename SCAL, typename TC>\n  NETGEN_INLINE AutoDiffRec<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffRec<D,SCAL> b, TC c)\n  {\n    return IfPos (a, b, AutoDiffRec<D,SCAL> (c));\n  }\n\n\n\ntemplate <int D, typename SCAL = double>\nusing AutoDiff = AutoDiffRec<D,SCAL>;\n\n}\n\n\n\nnamespace ngbla\n{\n  template <typename T> struct is_scalar_type;\n  template <int D, typename T>\n  struct is_scalar_type<ngcore::AutoDiff<D,T>> { static constexpr bool value = true; };\n\n  // not meaningful for AutoDiff<D,Complex>, since this is\n  // not (complex) differentiable anyway\n  template<int D, typename SCAL>\n  inline auto L2Norm2 (const ngcore::AutoDiff<D,SCAL> & x) \n  {\n    return x*x;\n  }\n\n  template<int D, typename SCAL>\n  inline auto L2Norm (const ngcore::AutoDiff<D,SCAL> & x) throw()\n  {\n    return IfPos(x.Value(), x, -x);\n  }\n  \n\n  \n  template<int D, typename TAD>\n  NETGEN_INLINE auto Conj (const ngcore::AutoDiff<D,TAD> & a) \n  { \n    ngcore::AutoDiff<D,TAD> b; \n    b.Value() = conj(a.Value()); \n    \n    for(int i=0;i<D;i++) \n      b.DValue(i) = conj(a.DValue(i)); \n    \n    return b;\n  }\n\n  \n}\n\n\n#endif\n\n\n"
  },
  {
    "path": "libsrc/core/autodiffdiff.hpp",
    "content": "#ifndef FILE_AUTODIFFDIFF\n#define FILE_AUTODIFFDIFF\n\n/**************************************************************************/\n/* File:   autodiffdiff.hpp                                               */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   13. June. 05                                                   */\n/**************************************************************************/\n\nnamespace ngcore\n{\n// Automatic second differentiation datatype\n\n\n/**\n   Datatype for automatic differentiation.  Contains function value,\n   D first derivatives, and D*D second derivatives. Algebraic operations are\n   overloaded by using product-rule etc. etc.\n**/\ntemplate <int D, typename SCAL = double>\nclass AutoDiffDiff\n{\n  SCAL val;\n  SCAL dval[D?D:1];\n  SCAL ddval[D?D*D:1];\npublic:\n\n  typedef AutoDiffDiff<D, SCAL> TELEM;\n\n\n  /// elements are undefined\n  AutoDiffDiff  () throw() { ; }\n\n  /// copy constructor\n  AutoDiffDiff  (const AutoDiffDiff & ad2) throw()\n  {\n    val = ad2.val;\n    for (int i = 0; i < D; i++)\n      dval[i] = ad2.dval[i];\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = ad2.ddval[i];\n  }\n\n  /// initial object with constant value\n  AutoDiffDiff  (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = 0;\n  }\n\n  /// initial object with value and derivative\n  AutoDiffDiff  (const AutoDiff<D, SCAL> & ad2) throw()\n  {\n    val = ad2.Value();\n    for (int i = 0; i < D; i++)\n      dval[i] = ad2.DValue(i);\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = 0;\n  }\n\n  /// init object with (val, e_diffindex)\n  AutoDiffDiff  (SCAL aval, int diffindex)  throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = 0;\n    dval[diffindex] = 1;\n  }\n\n  NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad)\n  {\n    val = aval;\n    LoadGradient (grad);\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = 0;\n  }\n\n  NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad, const SCAL * hesse)\n  {\n    val = aval;\n    LoadGradient (grad);\n    LoadHessian (hesse);\n  }\n\n  /// assign constant value\n  AutoDiffDiff & operator= (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = 0;\n    return *this;\n  }\n\n  NETGEN_INLINE void StoreGradient (SCAL * p) const \n  {\n    for (int i = 0; i < D; i++)\n      p[i] = dval[i];\n  }\n\n  NETGEN_INLINE void LoadGradient (const SCAL * p) \n  {\n    for (int i = 0; i < D; i++)\n      dval[i] = p[i];\n  }\n\n  NETGEN_INLINE void StoreHessian (SCAL * p) const \n  {\n    for (int i = 0; i < D*D; i++)\n      p[i] = ddval[i];\n  }\n\n  NETGEN_INLINE void LoadHessian (const SCAL * p) \n  {\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = p[i];\n  }\n\n  /// returns value\n  SCAL Value() const throw() { return val; }\n\n  /// returns partial derivative\n  SCAL DValue (int i) const throw() { return dval[i]; }\n\n  AutoDiff<D,SCAL> DValueAD (int i) const\n  {\n    AutoDiff<D,SCAL> r(dval[i]);\n    for (int j = 0; j < D; j++)\n      r.DValue(j) = ddval[i*D+j];\n    return r;\n  }\n  \n  /// returns partial derivative\n  SCAL DDValue (int i) const throw() { return ddval[i]; }\n\n  /// returns partial derivative\n  SCAL DDValue (int i, int j) const throw() { return ddval[i*D+j]; }\n\n  /// access value\n  SCAL & Value() throw() { return val; }\n\n  /// accesses partial derivative \n  SCAL & DValue (int i) throw() { return dval[i]; }\n\n  /// accesses partial derivative \n  SCAL & DDValue (int i) throw() { return ddval[i]; }\n\n  /// accesses partial derivative \n  SCAL & DDValue (int i, int j) throw() { return ddval[i*D+j]; }\n\n  explicit operator AutoDiff<D,SCAL> () const\n  { return AutoDiff<D,SCAL> (val, &dval[0]); }\n  \n  /// add autodiffdiff object\n  AutoDiffDiff<D, SCAL> & operator+= (const AutoDiffDiff<D, SCAL> & y) throw()\n  {\n    val += y.val;\n    for (int i = 0; i < D; i++)\n      dval[i] += y.dval[i];\n    for (int i = 0; i < D*D; i++)\n      ddval[i] += y.ddval[i];\n    return *this;\n  }\n\n  /// subtract autodiffdiff object\n  AutoDiffDiff<D, SCAL> & operator-= (const AutoDiffDiff<D, SCAL> & y) throw()\n  {\n    val -= y.val;\n    for (int i = 0; i < D; i++)\n      dval[i] -= y.dval[i];\n    for (int i = 0; i < D*D; i++)\n      ddval[i] -= y.ddval[i];\n    return *this;\n  }\n\n  /// multiply with autodiffdiff object\n  AutoDiffDiff<D, SCAL> & operator*= (const AutoDiffDiff<D, SCAL> & y) throw()\n  {\n    for (int i = 0; i < D*D; i++)\n      ddval[i] = val * y.ddval[i] + y.val * ddval[i];\n\n    for (int i = 0; i < D; i++)\n      for (int j = 0; j < D; j++)\n\tddval[i*D+j] += dval[i] * y.dval[j] + dval[j] * y.dval[i];\n\n    for (int i = 0; i < D; i++)\n      {\n\tdval[i] *= y.val;\n\tdval[i] += val * y.dval[i];\n      }\n    val *= y.val;\n    return *this;\n  }\n\n  /// multiply with scalar\n  AutoDiffDiff<D, SCAL> & operator*= (const SCAL & y) throw()\n  {\n    for ( int i = 0; i < D*D; i++ )\n      ddval[i] *= y;\n    for (int i = 0; i < D; i++)\n      dval[i] *= y;\n    val *= y;\n    return *this;\n  }\n\n  /// divide by scalar\n  AutoDiffDiff<D, SCAL> & operator/= (const SCAL & y) throw()\n  {\n    SCAL iy = 1.0 / y;\n    for ( int i = 0; i < D*D; i++ )\n      ddval[i] *= iy;\n    for (int i = 0; i < D; i++)\n      dval[i] *= iy;\n    val *= iy;\n    return *this;\n  }\n\n  /// same value\n  bool operator== (SCAL val2) throw()\n  {\n    return val == val2;\n  }\n\n  /// different values \n  bool operator!= (SCAL val2) throw()\n  {\n    return val != val2;\n  }\n\n  /// less \n  bool operator< (SCAL val2) throw()\n  {\n    return val < val2;\n  }\n  \n  /// greater\n  bool operator> (SCAL val2) throw()\n  {\n    return val > val2;\n  }\n};\n\n\n//@{  AutoDiff helper functions.\n\n/// Prints AudoDiffDiff\ntemplate<int D, typename SCAL>\ninline ostream & operator<< (ostream & ost, const AutoDiffDiff<D, SCAL> & x)\n{\n  ost << x.Value() << \", D = \";\n  for (int i = 0; i < D; i++)\n    ost << x.DValue(i) << \" \";\n  ost << \", DD = \";\n  for (int i = 0; i < D*D; i++)\n    ost << x.DDValue(i) << \" \";\n  return ost;\n}\n\n///\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value () = x.Value()+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) + y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = x.DDValue(i) + y.DDValue(i);\n  return res;\n}\n\n\n/// \ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x.Value()-y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) - y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = x.DDValue(i) - y.DDValue(i);\n  return res;\n}\n\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator+ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = y.DDValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = y.DDValue(i);\n  return res;\n}\n\n\n///\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = -x.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = -x.DDValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, SCAL2 y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x.Value()-y;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = x.DDValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator- (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x-y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = -y.DDValue(i);\n  return res;\n}\n\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator* (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = x*y.DDValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  for (int i = 0; i < D*D; i++)\n    res.DDValue(i) = x*y.DDValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL hx = x.Value();\n  SCAL hy = y.Value();\n\n  res.Value() = hx*hy;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);\n\n  for (int i = 0; i < D; i++)\n    for (int j = 0; j < D; j++)\n      res.DDValue(i,j) = hx * y.DDValue(i,j) + hy * x.DDValue(i,j)\n\t+ x.DValue(i) * y.DValue(j) + x.DValue(j) * y.DValue(i);\n\n  return res;\n}\n\n\n\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> Inv (const AutoDiffDiff<D, SCAL> & x)\n{\n  AutoDiffDiff<D, SCAL> res(1.0 / x.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());\n\n  SCAL fac1 = 2/(x.Value()*x.Value()*x.Value());\n  SCAL fac2 = 1/sqr(x.Value());\n  for (int i = 0; i < D; i++)\n    for (int j = 0; j < D; j++)\n      res.DDValue(i,j) = fac1*x.DValue(i)*x.DValue(j) - fac2*x.DDValue(i,j);\n  return res;\n}\n\n\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y)\n{\n  return x * Inv (y);\n}\n\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, SCAL2 y)\n{\n  return (1/y) * x;\n}\n\ntemplate<int D, typename SCAL, typename SCAL2,\n           typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>\ninline AutoDiffDiff<D, SCAL> operator/ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y)\n{\n  return x * Inv(y);\n}\n\n\ntemplate<int D, typename SCAL>\ninline AutoDiffDiff<D, SCAL> sqrt (const AutoDiffDiff<D, SCAL> & x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = sqrt(x.Value());\n  for (int j = 0; j < D; j++)\n    res.DValue(j) = IfZero(x.DValue(j),SCAL{0.},0.5 / res.Value() * x.DValue(j));\n\n  \n  for (int i = 0; i < D; i++)\n    for (int j = 0; j < D; j++)\n      res.DDValue(i,j) = IfZero(x.DDValue(i,j)+x.DValue(i) * x.DValue(j),SCAL{0.},0.5/res.Value() * x.DDValue(i,j) - 0.25 / (x.Value()*res.Value()) * x.DValue(i) * x.DValue(j));\n\n  return res;\n}\n\n// df(u)/dx  = exp(x) * du/dx\n// d^2 f(u) / dx^2 = exp(x) * (du/dx)^2 + exp(x) * d^2u /dx^2\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> exp (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = exp(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * res.Value();\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = (x.DValue(k) * x.DValue(l)+x.DDValue(k,l)) * res.Value();\n  return res;\n}\n\nusing std::pow;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> pow (AutoDiffDiff<D,SCAL> x, AutoDiffDiff<D,SCAL> y )\n{\n  return exp(log(x)*y);\n}\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> log (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  res.Value() = log(x.Value());\n  SCAL xinv = 1.0/x.Value();\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * xinv;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = -xinv*xinv*x.DValue(k) * x.DValue(l) + xinv * x.DDValue(k,l);\n  return res;\n}\n\n\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> sin (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL s = sin(x.Value());\n  SCAL c = cos(x.Value());\n  \n  res.Value() = s;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * c;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = -s * x.DValue(k) * x.DValue(l) + c * x.DDValue(k,l);\n  return res;\n}\n\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> cos (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL s = sin(x.Value());\n  SCAL c = cos(x.Value());\n  \n  res.Value() = c;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = -s * x.DValue(k);\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = -c * x.DValue(k) * x.DValue(l) - s * x.DDValue(k,l);\n  return res;\n}\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> tan (AutoDiffDiff<D, SCAL> x)\n{ return sin(x) / cos(x); }\n\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> atan (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL a = atan(x.Value());\n  res.Value() = a;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)/(1+x.Value()*x.Value()) ;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = -2*x.Value()/((1+x.Value()*x.Value())*(1+x.Value()*x.Value())) * x.DValue(k) * x.DValue(l) + x.DDValue(k,l)/(1+x.Value()*x.Value());\n  return res;\n}\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> atan2 (AutoDiffDiff<D, SCAL> x,AutoDiffDiff<D, SCAL> y)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL a = atan2(x.Value(), y.Value());\n  res.Value() = a;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = (x.Value()*y.DValue(k)-y.Value()*x.DValue(k))/(y.Value()*y.Value()+x.Value()*x.Value());\n\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = (x.DValue(k)*y.DValue(l)+x.Value()*y.DDValue(l,k) - y.DValue(k)*x.DValue(l) - y.Value()*x.DDValue(l,k))/(y.Value()*y.Value()+x.Value()*x.Value()) - 2 * (x.Value()*y.DValue(k)-y.Value()*x.DValue(k)) * (x.Value()*x.DValue(k) + y.Value()*y.DValue(k))/( (y.Value()*y.Value()+x.Value()*x.Value()) * (y.Value()*y.Value()+x.Value()*x.Value()) );\n  return res;\n}\n\n\n\nusing std::acos;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> acos (AutoDiffDiff<D,SCAL> x)\n{\n  AutoDiffDiff<D,SCAL> res;\n  SCAL a = acos(x.Value());\n  res.Value() = a;\n  auto omaa = 1-x.Value()*x.Value();\n  auto s = sqrt(omaa);\n  SCAL da = -1 / s;\n  SCAL dda = -x.Value() / (s*omaa);\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)*da;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);\n  \n  return res;\n}\n\n\nusing std::acos;\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> asin (AutoDiffDiff<D,SCAL> x)\n{\n  AutoDiffDiff<D,SCAL> res;\n  SCAL a = asin(x.Value());\n  res.Value() = a;\n  auto omaa = 1-x.Value()*x.Value();\n  auto s = sqrt(omaa);\n  SCAL da = 1 / s;\n  SCAL dda = x.Value() / (s*omaa);\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k)*da;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);\n  \n  return res;\n}\n\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> sinh (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL sh = sinh(x.Value());\n  SCAL ch = cosh(x.Value());\n  \n  res.Value() = sh;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = x.DValue(k) * ch;\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = sh * x.DValue(k) * x.DValue(l) + ch * x.DDValue(k,l);\n  return res;\n}\n\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> cosh (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL sh = sinh(x.Value());\n  SCAL ch = cosh(x.Value());\n  \n  res.Value() = ch;\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = sh * x.DValue(k);\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = ch * x.DValue(k) * x.DValue(l) + sh * x.DDValue(k,l);\n  return res;\n}\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D, SCAL> erf (AutoDiffDiff<D, SCAL> x)\n{\n  AutoDiffDiff<D, SCAL> res;\n  SCAL derf = 2. / sqrt(M_PI) * exp(- x.Value() * x.Value());\n  \n  res.Value() = erf(x.Value());\n  for (int k = 0; k < D; k++)\n    res.DValue(k) = - derf * x.DValue(k);\n  for (int k = 0; k < D; k++)\n    for (int l = 0; l < D; l++)\n      res.DDValue(k,l) = derf * (x.DDValue(k, l) - 2 * x.Value() * x.DValue(k) * x.DValue(l));\n  return res;\n}\n\nusing std::floor;\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> floor (const AutoDiffDiff<D,SCAL> & x)\n{\n  return floor(x.Value());\n}\n\nusing std::ceil;\ntemplate<int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> ceil (const AutoDiffDiff<D,SCAL> & x)\n{\n  return ceil(x.Value());  \n}\n\n\ntemplate <int D, typename SCAL, typename TB, typename TC>\nauto IfPos (AutoDiffDiff<D,SCAL> a, TB b, TC c) -> decltype(IfPos (a.Value(), b, c))\n{\n  return IfPos (a.Value(), b, c);\n}\n\ntemplate <int D, typename SCAL>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, AutoDiffDiff<D,SCAL> c)\n{\n  AutoDiffDiff<D,SCAL> res;\n  res.Value() = IfPos (a, b.Value(), c.Value());\n  for (int j = 0; j < D; j++)\n  {\n    res.DValue(j) = IfPos (a, b.DValue(j), c.DValue(j));\n    res.DDValue(j) = IfPos (a, b.DDValue(j), c.DDValue(j));\n  }\n  return res;\n}\n\ntemplate <int D, typename SCAL, typename TC>\nNETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, TC c)\n{\n  return IfPos (a, b, AutoDiffDiff<D,SCAL> (c));\n}\n\n\n\n\n//@}\n\n}\n\n\nnamespace ngbla\n{\n  template <typename T> struct is_scalar_type;\n  template <int D, typename T>\n  struct is_scalar_type<ngcore::AutoDiffDiff<D,T>> { static constexpr bool value = true; };\n\n\n  // not meaningful for AutoDiff<D,Complex>, since this is\n  // not (complex) differentiable anyway\n  template<int D, typename SCAL>\n  inline auto L2Norm2 (const ngcore::AutoDiffDiff<D,SCAL> & x) \n  {\n    return x*x;\n  }\n  \n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/core/bitarray.cpp",
    "content": "/**************************************************************************/\n/* File:   bitarray.cpp                                                   */\n/* Autho: Joachim Schoeberl                                               */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/*\n   data type BitArray\n*/\n\n#include \"bitarray.hpp\"\n#include \"archive.hpp\"\n\nnamespace ngcore\n{\n  BitArray :: BitArray (size_t asize)\n  {\n    size = 0;\n    data = NULL;\n    SetSize (asize);\n  }\n\n  BitArray :: BitArray (size_t asize, LocalHeap & lh)\n  {\n    size = asize;\n    data = new (lh) unsigned char [Addr (size)+1];\n    owns_data = false;\n  }\n\n  BitArray :: BitArray (const BitArray & ba2)\n  {\n    size = 0;\n    data = NULL;\n    (*this) = ba2;\n  }\n\n  void BitArray :: SetSize (size_t asize)\n  {\n    if (size == asize) return;\n    if (owns_data)\n      {\n        delete [] data;\n        mt.Free(GetMemoryUsage());\n      }\n\n    size = asize;\n    data = new unsigned char [Addr (size)+1];\n    owns_data = true;\n    mt.Alloc(GetMemoryUsage());\n  }\n\n  BitArray & BitArray :: Set () throw()\n  {\n    if (!size) return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] = UCHAR_MAX;\n    return *this;\n  }\n\n  BitArray & BitArray :: Clear () throw()\n  {\n    if (!size) return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] = 0;\n    return *this;\n  }\n\n  BitArray & BitArray :: Invert ()\n  {\n    if (!size) return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] ^= 255;\n    return *this;\n  }\n\n  BitArray & BitArray :: And (const BitArray & ba2)\n  {\n    if (!size) return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] &= ba2.data[i];\n        return *this;\n  }\n\n\n  BitArray & BitArray :: Or (const BitArray & ba2)\n  {\n    if (!size) return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] |= ba2.data[i];\n    return *this;\n  }\n\n  bool BitArray :: operator==(const BitArray& other) const\n  {\n    if(size != other.Size())\n      return false;\n    for(auto i : Range(size/CHAR_BIT))\n      if(data[i] != other.data[i])\n        return false;\n    for(auto i : Range(size%CHAR_BIT))\n      if(Test(i + CHAR_BIT * (size/CHAR_BIT)) != other.Test(i + CHAR_BIT * (size/CHAR_BIT)))\n        return false;\n    return true;\n  }\n\n  BitArray & BitArray :: operator= (const BitArray & ba2)\n  {\n    SetSize (ba2.Size());\n    if (!size)\n      return *this;\n    for (size_t i = 0; i <= Addr (size); i++)\n      data[i] = ba2.data[i];\n    return *this;\n  }\n\n  std::ostream & operator<<(std::ostream & s, const BitArray & ba)\n  {\n    size_t n = ba.Size();\n    for (size_t i = 0; i < n; i++)\n      {\n\tif (i % 50 == 0) s << i << \": \";\n\ts << int(ba[i]);\n\tif (i % 50 == 49) s << \"\\n\";\n      }\n    s << std::flush;\n    return s;\n  }\n\n  size_t BitArray :: NumSet () const\n  {\n    size_t cnt = 0;\n    for (size_t i = 0; i < Size(); i++)\n      if (Test(i)) cnt++;\n    return cnt;\n  }\n\n  void BitArray :: DoArchive(Archive& archive)\n  {\n    if(archive.GetVersion(\"netgen\") >= \"v6.2.2007-62\")\n      {\n        archive.NeedsVersion(\"netgen\", \"v6.2.2007-62\");\n        auto size = Size();\n        archive & size;\n        if(archive.Input())\n          SetSize(size);\n        if(archive.GetVersion(\"netgen\") < \"v6.2.2009-20\")\n          archive.Do(data, size/CHAR_BIT+1);\n        else\n          {\n            archive.NeedsVersion(\"netgen\", \"v6.2.2009-20\");\n            archive.Do(data, size/CHAR_BIT);\n            for(size_t i = 0; i < size%CHAR_BIT; i++)\n              {\n                size_t index =  CHAR_BIT * (size/CHAR_BIT) + i;\n                bool b = Test(index);\n                archive & b;\n                b ? SetBit(index) : Clear(index);\n              }\n          }\n      }\n    else\n      {\n        if (archive.Output())\n          {\n            throw Exception(\"should not get here\");\n            archive << Size();\n            for (size_t i = 0; i < Size(); i++)\n              archive << (*this)[i];\n          }\n        else\n          {\n            size_t size;\n            archive & size;\n            SetSize (size);\n            Clear();\n            for (size_t i = 0; i < size; i++)\n              {\n                bool b;\n                archive & b;\n                if (b) SetBit(i);\n              }\n          }\n      }\n  }\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/bitarray.hpp",
    "content": "#ifndef NETGEN_CORE_BITARRAY\n#define NETGEN_CORE_BITARRAY\n\n/**************************************************************************/\n/* File:   bitarray.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <climits>\n#include <cstring>\n#include <ostream>\n\n#include \"array.hpp\"\n#include \"localheap.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n\n/**\n   A compressed array of bools.\n\n   Provides bit-operations and whole array operations.\n*/\nclass BitArray\n{\nprotected:\n  /// number of bits\n  size_t size;\n\n  /// the data\n  unsigned char * data;\n  ///\n  bool owns_data = true;\npublic:\n  /// empty array\n  BitArray ()\n    : size(0), data(nullptr) { ; }\n  /// array of asize bits\n  NGCORE_API BitArray (size_t asize);\n  /// array of asize bits\n  NGCORE_API BitArray (size_t asize, LocalHeap & lh);\n  ///\n  NGCORE_API BitArray (const BitArray & ba2);\n  BitArray (BitArray && ba2)\n    : size(ba2.size), data(ba2.data), owns_data(ba2.owns_data)\n  {\n    ba2.owns_data = false;\n    ba2.data = nullptr;\n    mt = std::move(ba2.mt);\n  }\n\n  template <typename T>\n  NETGEN_INLINE BitArray (std::initializer_list<T> list)\n    : BitArray (list.size())\n  {\n    Clear();\n    int cnt = 0;\n    for (auto i = list.begin(); i < list.end(); i++, cnt++)\n      if (*i) SetBit(cnt);\n    StartMemoryTracing();\n  }\n\n  /// delete data\n  ~BitArray ()\n  {\n    if (owns_data)\n    {\n      delete [] data;\n      mt.Free(GetMemoryUsage());\n    }\n  }\n\n  /// Set size, loose values\n  NGCORE_API void SetSize (size_t asize);\n\n  /// the size\n  size_t Size () const { return size; }\n\n  /// set all bits\n  NGCORE_API BitArray & Set () throw();\n\n  /// clear all bits\n  NGCORE_API BitArray & Clear () throw();\n\n  /// set bit i\n  [[deprecated(\"Use either SetBit() or SetBitAtomic()\")]]\n  void Set (size_t i) { SetBitAtomic(i); }\n\n  /// set bit i ( not thread safe )\n  void SetBit (size_t i)\n  {\n    NETGEN_CHECK_RANGE(i, 0, size);\n    data[Addr(i)] |= Mask(i);\n  }\n\n  /// set bit i ( thread safe )\n  void SetBitAtomic (size_t i)\n  {\n    NETGEN_CHECK_RANGE(i, 0, size);\n    unsigned char * p = data+Addr(i);\n    unsigned char mask = Mask(i);\n\n    AsAtomic(*p) |= mask;\n  }\n\n  /// clear bit i\n  void Clear (size_t i)\n  {\n    NETGEN_CHECK_RANGE(i, 0, size);\n    data[Addr(i)] &= ~Mask(i);\n  }\n\n  /// check bit i\n  bool Test (size_t i) const\n  {\n    NETGEN_CHECK_RANGE(i, 0, size);\n    return (data[Addr(i)] & Mask(i)) ? true : false;\n  }\n\n  /// set all bits to b\n  BitArray & operator= (bool b)\n  {\n    if (b) Set();\n    else   Clear();\n    return *this;\n  }\n\n  /// check bit i\n  bool operator[] (size_t i) const\n  {\n    NETGEN_CHECK_RANGE(i, 0, size);\n    return Test(i);\n  }\n\n  NGCORE_API bool operator==(const BitArray& other) const;\n\n  /// invert all bits\n  NGCORE_API BitArray & Invert ();\n\n  /// logical AND with ba2\n  NGCORE_API BitArray & And (const BitArray & ba2);\n\n  /// logical OR with ba2\n  NGCORE_API BitArray & Or (const BitArray & ba2);\n\n  /// copy from ba2\n  NGCORE_API BitArray & operator= (const BitArray & ba2);\n\n  NGCORE_API size_t NumSet () const;\n\n  NGCORE_API void DoArchive(class Archive& archive);\n  \n  NGCORE_API auto * Data() const { return data; }\n\n  size_t GetMemoryUsage() const { return owns_data ? (size+CHAR_BIT-1)/CHAR_BIT : 0; }\n  const MemoryTracer& GetMemoryTracer() const { return mt; }\n  void StartMemoryTracing() const\n  {\n    mt.Alloc(GetMemoryUsage());\n  }\n\nprivate:\n  ///\n  unsigned char Mask (size_t i) const\n  { return char(1) << (i % CHAR_BIT); }\n\n  ///\n  size_t Addr (size_t i) const\n  { return (i / CHAR_BIT); }\n\n  MemoryTracer mt;\n};\n\n\n  inline BitArray & operator|= (BitArray & me, const BitArray & you)\n  {\n    me.Or(you);\n    return me;\n  }\n\n  inline BitArray & operator&= (BitArray & me, const BitArray & you)\n  {\n    me.And(you);\n    return me;\n  }\n\n  inline BitArray operator| (const BitArray & a, const BitArray & b)\n  {\n    BitArray res = a;\n    res |= b;\n    return res;\n  }\n\n  inline BitArray operator& (const BitArray & a, const BitArray & b)\n  {\n    BitArray res = a;\n    res &= b;\n    return res;\n  }\n\n  inline BitArray operator~ (const BitArray & a)\n  {\n    BitArray res = a;\n    res.Invert();\n    return res;\n  }\n\n  NGCORE_API std::ostream & operator<<(std::ostream & s, const BitArray & ba);\n\n\n\n  template <typename IndexType>\n  class TBitArray : public BitArray\n  {\n  public:\n    using BitArray::BitArray;\n\n    void SetBit (IndexType i) { BitArray::SetBit(i-IndexBASE<IndexType>()); }\n    void Clear () { BitArray::Clear(); }\n    void Clear (IndexType i) { BitArray::Clear(i-IndexBASE<IndexType>()); }\n    void SetBitAtomic (IndexType i) { BitArray::SetBitAtomic(i-IndexBASE<IndexType>()); }\n    bool Test (IndexType i) const { return BitArray::Test(i-IndexBASE<IndexType>()); }\n    \n    bool operator[] (IndexType i) const { return Test(i); } \n    T_Range<IndexType> Range() const { return { IndexBASE<IndexType>(), IndexBASE<IndexType>()+Size() }; }\n    NGCORE_API TBitArray & Or (const TBitArray & ba2)\n    {\n      BitArray::Or(ba2);\n      return *this;\n    }\n\n  };\n\n} // namespace ngcore\n\n  \n#endif // NETGEN_CORE_BITARRAY\n"
  },
  {
    "path": "libsrc/core/concurrentqueue.h",
    "content": "// Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue.\n// An overview, including benchmark results, is provided here:\n//     http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++\n// The full design is also described in excruciating detail at:\n//    http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue\n\n// Boost Software License - Version 1.0 - August 17th, 2003\n// \n// Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the \"Software\") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following:\n// \n// The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor.\n// \n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE\n\n#pragma once\n\n#if defined(__GNUC__)\n// Disable -Wconversion warnings (spuriously triggered when Traits::size_t and\n// Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings\n// upon assigning any computed values)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wconversion\"\n\n#ifdef MCDBGQ_USE_RELACY\n#pragma GCC diagnostic ignored \"-Wint-to-pointer-cast\"\n#endif\n#endif\n\n#if defined(__APPLE__)\n#include \"TargetConditionals.h\"\n#endif\n\n#ifdef MCDBGQ_USE_RELACY\n#include \"relacy/relacy_std.hpp\"\n#include \"relacy_shims.h\"\n// We only use malloc/free anyway, and the delete macro messes up `= delete` method declarations.\n// We'll override the default trait malloc ourselves without a macro.\n#undef new\n#undef delete\n#undef malloc\n#undef free\n#else\n#include <atomic>  // Requires C++11. Sorry VS2010.\n#include <cassert>\n#endif\n#include <cstddef>              // for max_align_t\n#include <cstdint>\n#include <cstdlib>\n#include <type_traits>\n#include <algorithm>\n#include <utility>\n#include <limits>\n#include <climits>  // for CHAR_BIT\n#include <array>\n#include <thread>  // partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading\n\n// Platform-specific definitions of a numeric thread ID type and an invalid value\nnamespace moodycamel { namespace details {\n template<typename thread_id_t> struct thread_id_converter {\n  typedef thread_id_t thread_id_numeric_size_t;\n  typedef thread_id_t thread_id_hash_t;\n  static thread_id_hash_t prehash(thread_id_t const& x) { return x; }\n };\n} }\n#if defined(MCDBGQ_USE_RELACY)\nnamespace moodycamel { namespace details {\n typedef std::uint32_t thread_id_t;\n static const thread_id_t invalid_thread_id  = 0xFFFFFFFFU;\n static const thread_id_t invalid_thread_id2 = 0xFFFFFFFEU;\n static inline thread_id_t thread_id() { return rl::thread_index(); }\n} }\n#elif defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)\n// No sense pulling in windows.h in a header, we'll manually declare the function\n// we use and rely on backwards-compatibility for this not to break\nextern \"C\" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(void);\nnamespace moodycamel { namespace details {\n static_assert(sizeof(unsigned long) == sizeof(std::uint32_t), \"Expected size of unsigned long to be 32 bits on Windows\");\n typedef std::uint32_t thread_id_t;\n static const thread_id_t invalid_thread_id  = 0;   // See http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx\n static const thread_id_t invalid_thread_id2 = 0xFFFFFFFFU; // Not technically guaranteed to be invalid, but is never used in practice. Note that all Win32 thread IDs are presently multiples of 4.\n static inline thread_id_t thread_id() { return static_cast<thread_id_t>(::GetCurrentThreadId()); }\n} }\n#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE)\nnamespace moodycamel { namespace details {\n static_assert(sizeof(std::thread::id) == 4 || sizeof(std::thread::id) == 8, \"std::thread::id is expected to be either 4 or 8 bytes\");\n \n typedef std::thread::id thread_id_t;\n static const thread_id_t invalid_thread_id;         // Default ctor creates invalid ID\n\n // Note we don't define a invalid_thread_id2 since std::thread::id doesn't have one; it's\n // only used if MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is defined anyway, which it won't\n // be.\n static inline thread_id_t thread_id() { return std::this_thread::get_id(); }\n\n template<std::size_t> struct thread_id_size { };\n template<> struct thread_id_size<4> { typedef std::uint32_t numeric_t; };\n template<> struct thread_id_size<8> { typedef std::uint64_t numeric_t; };\n\n template<> struct thread_id_converter<thread_id_t> {\n  typedef thread_id_size<sizeof(thread_id_t)>::numeric_t thread_id_numeric_size_t;\n#ifndef __APPLE__\n  typedef std::size_t thread_id_hash_t;\n#else\n  typedef thread_id_numeric_size_t thread_id_hash_t;\n#endif\n\n  static thread_id_hash_t prehash(thread_id_t const& x)\n  {\n#ifndef __APPLE__\n   return std::hash<std::thread::id>()(x);\n#else\n   return *reinterpret_cast<thread_id_hash_t const*>(&x);\n#endif\n  }\n };\n} }\n#else\n// Use a nice trick from this answer: http://stackoverflow.com/a/8438730/21475\n// In order to get a numeric thread ID in a platform-independent way, we use a thread-local\n// static variable's address as a thread identifier :-)\n#if defined(__GNUC__) || defined(__INTEL_COMPILER)\n#define MOODYCAMEL_THREADLOCAL __thread\n#elif defined(_MSC_VER)\n#define MOODYCAMEL_THREADLOCAL __declspec(thread)\n#else\n// Assume C++11 compliant compiler\n#define MOODYCAMEL_THREADLOCAL thread_local\n#endif\nnamespace moodycamel { namespace details {\n typedef std::uintptr_t thread_id_t;\n static const thread_id_t invalid_thread_id  = 0;  // Address can't be nullptr\n static const thread_id_t invalid_thread_id2 = 1;  // Member accesses off a null pointer are also generally invalid. Plus it's not aligned.\n static inline thread_id_t thread_id() { static MOODYCAMEL_THREADLOCAL int x; return reinterpret_cast<thread_id_t>(&x); }\n} }\n#endif\n\n// Exceptions\n#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED\n#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__))\n#define MOODYCAMEL_EXCEPTIONS_ENABLED\n#endif\n#endif\n#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED\n#define MOODYCAMEL_TRY try\n#define MOODYCAMEL_CATCH(...) catch(__VA_ARGS__)\n#define MOODYCAMEL_RETHROW throw\n#define MOODYCAMEL_THROW(expr) throw (expr)\n#else\n#define MOODYCAMEL_TRY if (true)\n#define MOODYCAMEL_CATCH(...) else if (false)\n#define MOODYCAMEL_RETHROW\n#define MOODYCAMEL_THROW(expr)\n#endif\n\n#ifndef MOODYCAMEL_NOEXCEPT\n#if !defined(MOODYCAMEL_EXCEPTIONS_ENABLED)\n#define MOODYCAMEL_NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) true\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) true\n#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1800\n// VS2012's std::is_nothrow_[move_]constructible is broken and returns true when it shouldn't :-(\n// We have to assume *all* non-trivial constructors may throw on VS2012!\n#define MOODYCAMEL_NOEXCEPT _NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))\n#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1900\n#define MOODYCAMEL_NOEXCEPT _NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value || std::is_nothrow_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value || std::is_nothrow_copy_constructible<type>::value)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))\n#else\n#define MOODYCAMEL_NOEXCEPT noexcept\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) noexcept(expr)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) noexcept(expr)\n#endif\n#endif\n\n#ifndef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#ifdef MCDBGQ_USE_RELACY\n#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#else\n// VS2013 doesn't support `thread_local`, and MinGW-w64 w/ POSIX threading has a crippling bug: http://sourceforge.net/p/mingw-w64/bugs/445\n// g++ <=4.7 doesn't support thread_local either.\n// Finally, iOS/ARM doesn't have support for it either, and g++/ARM allows it to compile but it's unconfirmed to actually work\n#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && (!defined(__MINGW32__) && !defined(__MINGW64__) || !defined(__WINPTHREADS_VERSION)) && (!defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && (!defined(__APPLE__) || !TARGET_OS_IPHONE) && !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)\n// Assume `thread_local` is fully supported in all other C++11 compilers/platforms\n//#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED    // always disabled for now since several users report having problems with it on\n#endif\n#endif\n#endif\n\n// VS2012 doesn't support deleted functions. \n// In this case, we declare the function normally but don't define it. A link error will be generated if the function is called.\n#ifndef MOODYCAMEL_DELETE_FUNCTION\n#if defined(_MSC_VER) && _MSC_VER < 1800\n#define MOODYCAMEL_DELETE_FUNCTION\n#else\n#define MOODYCAMEL_DELETE_FUNCTION = delete\n#endif\n#endif\n\n// Compiler-specific likely/unlikely hints\nnamespace moodycamel { namespace details {\n#if defined(__GNUC__)\n static inline bool (likely)(bool x) { return __builtin_expect((x), true); }\n static inline bool (unlikely)(bool x) { return __builtin_expect((x), false); }\n#else\n static inline bool (likely)(bool x) { return x; }\n static inline bool (unlikely)(bool x) { return x; }\n#endif\n} }\n\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n#include \"internal/concurrentqueue_internal_debug.h\"\n#endif\n\nnamespace moodycamel {\nnamespace details {\n template<typename T>\n struct const_numeric_max {\n  static_assert(std::is_integral<T>::value, \"const_numeric_max can only be used with integers\");\n  static const T value = std::numeric_limits<T>::is_signed\n   ? (static_cast<T>(1) << (sizeof(T) * CHAR_BIT - 1)) - static_cast<T>(1)\n   : static_cast<T>(-1);\n };\n\n#if defined(__GLIBCXX__)\n typedef ::max_align_t std_max_align_t;      // libstdc++ forgot to add it to std:: for a while\n#else\n typedef std::max_align_t std_max_align_t;   // Others (e.g. MSVC) insist it can *only* be accessed via std::\n#endif\n\n // Some platforms have incorrectly set max_align_t to a type with <8 bytes alignment even while supporting\n // 8-byte aligned scalar values (*cough* 32-bit iOS). Work around this with our own union. See issue #64.\n typedef union {\n  std_max_align_t x;\n  long long y;\n  void* z;\n } max_align_t;\n}\n\n// Default traits for the ConcurrentQueue. To change some of the\n// traits without re-implementing all of them, inherit from this\n// struct and shadow the declarations you wish to be different;\n// since the traits are used as a template type parameter, the\n// shadowed declarations will be used where defined, and the defaults\n// otherwise.\nstruct ConcurrentQueueDefaultTraits\n{\n // General-purpose size type. std::size_t is strongly recommended.\n typedef std::size_t size_t;\n \n // The type used for the enqueue and dequeue indices. Must be at least as\n // large as size_t. Should be significantly larger than the number of elements\n // you expect to hold at once, especially if you have a high turnover rate;\n // for example, on 32-bit x86, if you expect to have over a hundred million\n // elements or pump several million elements through your queue in a very\n // short space of time, using a 32-bit type *may* trigger a race condition.\n // A 64-bit int type is recommended in that case, and in practice will\n // prevent a race condition no matter the usage of the queue. Note that\n // whether the queue is lock-free with a 64-int type depends on the whether\n // std::atomic<std::uint64_t> is lock-free, which is platform-specific.\n typedef std::size_t index_t;\n \n // Internally, all elements are enqueued and dequeued from multi-element\n // blocks; this is the smallest controllable unit. If you expect few elements\n // but many producers, a smaller block size should be favoured. For few producers\n // and/or many elements, a larger block size is preferred. A sane default\n // is provided. Must be a power of 2.\n static const size_t BLOCK_SIZE = 32;\n \n // For explicit producers (i.e. when using a producer token), the block is\n // checked for being empty by iterating through a list of flags, one per element.\n // For large block sizes, this is too inefficient, and switching to an atomic\n // counter-based approach is faster. The switch is made for block sizes strictly\n // larger than this threshold.\n static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = 32;\n \n // How many full blocks can be expected for a single explicit producer? This should\n // reflect that number's maximum for optimal performance. Must be a power of 2.\n static const size_t EXPLICIT_INITIAL_INDEX_SIZE = 32;\n \n // How many full blocks can be expected for a single implicit producer? This should\n // reflect that number's maximum for optimal performance. Must be a power of 2.\n static const size_t IMPLICIT_INITIAL_INDEX_SIZE = 32;\n \n // The initial size of the hash table mapping thread IDs to implicit producers.\n // Note that the hash is resized every time it becomes half full.\n // Must be a power of two, and either 0 or at least 1. If 0, implicit production\n // (using the enqueue methods without an explicit producer token) is disabled.\n static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = 32;\n \n // Controls the number of items that an explicit consumer (i.e. one with a token)\n // must consume before it causes all consumers to rotate and move on to the next\n // internal queue.\n static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = 256;\n \n // The maximum number of elements (inclusive) that can be enqueued to a sub-queue.\n // Enqueue operations that would cause this limit to be surpassed will fail. Note\n // that this limit is enforced at the block level (for performance reasons), i.e.\n // it's rounded up to the nearest block size.\n static const size_t MAX_SUBQUEUE_SIZE = details::const_numeric_max<size_t>::value;\n \n \n#ifndef MCDBGQ_USE_RELACY\n // Memory allocation can be customized if needed.\n // malloc should return nullptr on failure, and handle alignment like std::malloc.\n#if defined(malloc) || defined(free)\n // Gah, this is 2015, stop defining macros that break standard code already!\n // Work around malloc/free being special macros:\n static inline void* WORKAROUND_malloc(size_t size) { return malloc(size); }\n static inline void WORKAROUND_free(void* ptr) { return free(ptr); }\n static inline void* (malloc)(size_t size) { return WORKAROUND_malloc(size); }\n static inline void (free)(void* ptr) { return WORKAROUND_free(ptr); }\n#else\n static inline void* malloc(size_t size) { return std::malloc(size); }\n static inline void free(void* ptr) { return std::free(ptr); }\n#endif\n#else\n // Debug versions when running under the Relacy race detector (ignore\n // these in user code)\n static inline void* malloc(size_t size) { return rl::rl_malloc(size, $); }\n static inline void free(void* ptr) { return rl::rl_free(ptr, $); }\n#endif\n};\n\n\n// When producing or consuming many elements, the most efficient way is to:\n//    1) Use one of the bulk-operation methods of the queue with a token\n//    2) Failing that, use the bulk-operation methods without a token\n//    3) Failing that, create a token and use that with the single-item methods\n//    4) Failing that, use the single-parameter methods of the queue\n// Having said that, don't create tokens willy-nilly -- ideally there should be\n// a maximum of one token per thread (of each kind).\nstruct ProducerToken;\nstruct ConsumerToken;\n\ntemplate<typename T, typename Traits> class ConcurrentQueue;\ntemplate<typename T, typename Traits> class BlockingConcurrentQueue;\nclass ConcurrentQueueTests;\n\n\nnamespace details\n{\n struct ConcurrentQueueProducerTypelessBase\n {\n  ConcurrentQueueProducerTypelessBase* next;\n  std::atomic<bool> inactive;\n  ProducerToken* token;\n  \n  ConcurrentQueueProducerTypelessBase()\n   : next(nullptr), inactive(false), token(nullptr)\n  {\n  }\n };\n \n template<bool use32> struct _hash_32_or_64 {\n  static inline std::uint32_t hash(std::uint32_t h)\n  {\n   // MurmurHash3 finalizer -- see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp\n   // Since the thread ID is already unique, all we really want to do is propagate that\n   // uniqueness evenly across all the bits, so that we can use a subset of the bits while\n   // reducing collisions significantly\n   h ^= h >> 16;\n   h *= 0x85ebca6b;\n   h ^= h >> 13;\n   h *= 0xc2b2ae35;\n   return h ^ (h >> 16);\n  }\n };\n template<> struct _hash_32_or_64<1> {\n  static inline std::uint64_t hash(std::uint64_t h)\n  {\n   h ^= h >> 33;\n   h *= 0xff51afd7ed558ccd;\n   h ^= h >> 33;\n   h *= 0xc4ceb9fe1a85ec53;\n   return h ^ (h >> 33);\n  }\n };\n template<std::size_t size> struct hash_32_or_64 : public _hash_32_or_64<(size > 4)> {  };\n \n static inline size_t hash_thread_id(thread_id_t id)\n {\n  static_assert(sizeof(thread_id_t) <= 8, \"Expected a platform where thread IDs are at most 64-bit values\");\n  return static_cast<size_t>(hash_32_or_64<sizeof(thread_id_converter<thread_id_t>::thread_id_hash_t)>::hash(\n   thread_id_converter<thread_id_t>::prehash(id)));\n }\n \n template<typename T>\n static inline bool circular_less_than(T a, T b)\n {\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable: 4554)\n#endif\n  static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, \"circular_less_than is intended to be used only with unsigned integer types\");\n  return static_cast<T>(a - b) > static_cast<T>(static_cast<T>(1) << static_cast<T>(sizeof(T) * CHAR_BIT - 1));\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n }\n \n template<typename U>\n static inline char* align_for(char* ptr)\n {\n  const std::size_t alignment = std::alignment_of<U>::value;\n  return ptr + (alignment - (reinterpret_cast<std::uintptr_t>(ptr) % alignment)) % alignment;\n }\n\n template<typename T>\n static inline T ceil_to_pow_2(T x)\n {\n  static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, \"ceil_to_pow_2 is intended to be used only with unsigned integer types\");\n\n  // Adapted from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2\n  --x;\n  x |= x >> 1;\n  x |= x >> 2;\n  x |= x >> 4;\n  for (std::size_t i = 1; i < sizeof(T); i <<= 1) {\n   x |= x >> (i << 3);\n  }\n  ++x;\n  return x;\n }\n \n template<typename T>\n static inline void swap_relaxed(std::atomic<T>& left, std::atomic<T>& right)\n {\n  T temp = std::move(left.load(std::memory_order_relaxed));\n  left.store(std::move(right.load(std::memory_order_relaxed)), std::memory_order_relaxed);\n  right.store(std::move(temp), std::memory_order_relaxed);\n }\n \n template<typename T>\n static inline T const& nomove(T const& x)\n {\n  return x;\n }\n \n template<bool Enable>\n struct nomove_if\n {\n  template<typename T>\n  static inline T const& eval(T const& x)\n  {\n   return x;\n  }\n };\n \n template<>\n struct nomove_if<false>\n {\n  template<typename U>\n  static inline auto eval(U&& x)\n   -> decltype(std::forward<U>(x))\n  {\n   return std::forward<U>(x);\n  }\n };\n \n template<typename It>\n static inline auto deref_noexcept(It& it) MOODYCAMEL_NOEXCEPT -> decltype(*it)\n {\n  return *it;\n }\n \n#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)\n template<typename T> struct is_trivially_destructible : std::is_trivially_destructible<T> { };\n#else\n template<typename T> struct is_trivially_destructible : std::has_trivial_destructor<T> { };\n#endif\n \n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#ifdef MCDBGQ_USE_RELACY\n typedef RelacyThreadExitListener ThreadExitListener;\n typedef RelacyThreadExitNotifier ThreadExitNotifier;\n#else\n struct ThreadExitListener\n {\n  typedef void (*callback_t)(void*);\n  callback_t callback;\n  void* userData;\n  \n  ThreadExitListener* next;  // reserved for use by the ThreadExitNotifier\n };\n \n \n class ThreadExitNotifier\n {\n public:\n  static void subscribe(ThreadExitListener* listener)\n  {\n   auto& tlsInst = instance();\n   listener->next = tlsInst.tail;\n   tlsInst.tail = listener;\n  }\n  \n  static void unsubscribe(ThreadExitListener* listener)\n  {\n   auto& tlsInst = instance();\n   ThreadExitListener** prev = &tlsInst.tail;\n   for (auto ptr = tlsInst.tail; ptr != nullptr; ptr = ptr->next) {\n    if (ptr == listener) {\n     *prev = ptr->next;\n     break;\n    }\n    prev = &ptr->next;\n   }\n  }\n  \n private:\n  ThreadExitNotifier() : tail(nullptr) { }\n  ThreadExitNotifier(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION;\n  ThreadExitNotifier& operator=(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION;\n  \n  ~ThreadExitNotifier()\n  {\n   // This thread is about to exit, let everyone know!\n   assert(this == &instance() && \"If this assert fails, you likely have a buggy compiler! Change the preprocessor conditions such that MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is no longer defined.\");\n   for (auto ptr = tail; ptr != nullptr; ptr = ptr->next) {\n    ptr->callback(ptr->userData);\n   }\n  }\n  \n  // Thread-local\n  static inline ThreadExitNotifier& instance()\n  {\n   static thread_local ThreadExitNotifier notifier;\n   return notifier;\n  }\n  \n private:\n  ThreadExitListener* tail;\n };\n#endif\n#endif\n \n template<typename T> struct static_is_lock_free_num { enum { value = 0 }; };\n template<> struct static_is_lock_free_num<signed char> { enum { value = ATOMIC_CHAR_LOCK_FREE }; };\n template<> struct static_is_lock_free_num<short> { enum { value = ATOMIC_SHORT_LOCK_FREE }; };\n template<> struct static_is_lock_free_num<int> { enum { value = ATOMIC_INT_LOCK_FREE }; };\n template<> struct static_is_lock_free_num<long> { enum { value = ATOMIC_LONG_LOCK_FREE }; };\n template<> struct static_is_lock_free_num<long long> { enum { value = ATOMIC_LLONG_LOCK_FREE }; };\n template<typename T> struct static_is_lock_free : static_is_lock_free_num<typename std::make_signed<T>::type> {  };\n template<> struct static_is_lock_free<bool> { enum { value = ATOMIC_BOOL_LOCK_FREE }; };\n template<typename U> struct static_is_lock_free<U*> { enum { value = ATOMIC_POINTER_LOCK_FREE }; };\n}\n\n\nstruct ProducerToken\n{\n template<typename T, typename Traits>\n explicit ProducerToken(ConcurrentQueue<T, Traits>& queue);\n \n template<typename T, typename Traits>\n explicit ProducerToken(BlockingConcurrentQueue<T, Traits>& queue);\n \n ProducerToken(ProducerToken&& other) MOODYCAMEL_NOEXCEPT\n  : producer(other.producer)\n {\n  other.producer = nullptr;\n  if (producer != nullptr) {\n   producer->token = this;\n  }\n }\n \n inline ProducerToken& operator=(ProducerToken&& other) MOODYCAMEL_NOEXCEPT\n {\n  swap(other);\n  return *this;\n }\n \n void swap(ProducerToken& other) MOODYCAMEL_NOEXCEPT\n {\n  std::swap(producer, other.producer);\n  if (producer != nullptr) {\n   producer->token = this;\n  }\n  if (other.producer != nullptr) {\n   other.producer->token = &other;\n  }\n }\n \n // A token is always valid unless:\n //     1) Memory allocation failed during construction\n //     2) It was moved via the move constructor\n //        (Note: assignment does a swap, leaving both potentially valid)\n //     3) The associated queue was destroyed\n // Note that if valid() returns true, that only indicates\n // that the token is valid for use with a specific queue,\n // but not which one; that's up to the user to track.\n inline bool valid() const { return producer != nullptr; }\n \n ~ProducerToken()\n {\n  if (producer != nullptr) {\n   producer->token = nullptr;\n   producer->inactive.store(true, std::memory_order_release);\n  }\n }\n \n // Disable copying and assignment\n ProducerToken(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n ProducerToken& operator=(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n \nprivate:\n template<typename T, typename Traits> friend class ConcurrentQueue;\n friend class ConcurrentQueueTests;\n \nprotected:\n details::ConcurrentQueueProducerTypelessBase* producer;\n};\n\n\nstruct ConsumerToken\n{\n template<typename T, typename Traits>\n explicit ConsumerToken(ConcurrentQueue<T, Traits>& q);\n \n template<typename T, typename Traits>\n explicit ConsumerToken(BlockingConcurrentQueue<T, Traits>& q);\n \n ConsumerToken(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT\n  : initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer)\n {\n }\n \n inline ConsumerToken& operator=(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT\n {\n  swap(other);\n  return *this;\n }\n \n void swap(ConsumerToken& other) MOODYCAMEL_NOEXCEPT\n {\n  std::swap(initialOffset, other.initialOffset);\n  std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset);\n  std::swap(itemsConsumedFromCurrent, other.itemsConsumedFromCurrent);\n  std::swap(currentProducer, other.currentProducer);\n  std::swap(desiredProducer, other.desiredProducer);\n }\n \n // Disable copying and assignment\n ConsumerToken(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n ConsumerToken& operator=(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n\nprivate:\n template<typename T, typename Traits> friend class ConcurrentQueue;\n friend class ConcurrentQueueTests;\n \nprivate: // but shared with ConcurrentQueue\n std::uint32_t initialOffset;\n std::uint32_t lastKnownGlobalOffset;\n std::uint32_t itemsConsumedFromCurrent;\n details::ConcurrentQueueProducerTypelessBase* currentProducer;\n details::ConcurrentQueueProducerTypelessBase* desiredProducer;\n};\n\n// Need to forward-declare this swap because it's in a namespace.\n// See http://stackoverflow.com/questions/4492062/why-does-a-c-friend-class-need-a-forward-declaration-only-in-other-namespaces\ntemplate<typename T, typename Traits>\ninline void swap(typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& a, typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT;\n\n\ntemplate<typename T, typename Traits = ConcurrentQueueDefaultTraits>\nclass ConcurrentQueue\n{\npublic:\n typedef ::moodycamel::ProducerToken producer_token_t;\n typedef ::moodycamel::ConsumerToken consumer_token_t;\n \n typedef typename Traits::index_t index_t;\n typedef typename Traits::size_t size_t;\n \n static const size_t BLOCK_SIZE = static_cast<size_t>(Traits::BLOCK_SIZE);\n static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = static_cast<size_t>(Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD);\n static const size_t EXPLICIT_INITIAL_INDEX_SIZE = static_cast<size_t>(Traits::EXPLICIT_INITIAL_INDEX_SIZE);\n static const size_t IMPLICIT_INITIAL_INDEX_SIZE = static_cast<size_t>(Traits::IMPLICIT_INITIAL_INDEX_SIZE);\n static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = static_cast<size_t>(Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE);\n static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = static_cast<std::uint32_t>(Traits::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE);\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable: 4307)  // + integral constant overflow (that's what the ternary expression is for!)\n#pragma warning(disable: 4309)  // static_cast: Truncation of constant value\n#endif\n static const size_t MAX_SUBQUEUE_SIZE = (details::const_numeric_max<size_t>::value - static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) < BLOCK_SIZE) ? details::const_numeric_max<size_t>::value : ((static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE);\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n static_assert(!std::numeric_limits<size_t>::is_signed && std::is_integral<size_t>::value, \"Traits::size_t must be an unsigned integral type\");\n static_assert(!std::numeric_limits<index_t>::is_signed && std::is_integral<index_t>::value, \"Traits::index_t must be an unsigned integral type\");\n static_assert(sizeof(index_t) >= sizeof(size_t), \"Traits::index_t must be at least as wide as Traits::size_t\");\n static_assert((BLOCK_SIZE > 1) && !(BLOCK_SIZE & (BLOCK_SIZE - 1)), \"Traits::BLOCK_SIZE must be a power of 2 (and at least 2)\");\n static_assert((EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD > 1) && !(EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD & (EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD - 1)), \"Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD must be a power of 2 (and greater than 1)\");\n static_assert((EXPLICIT_INITIAL_INDEX_SIZE > 1) && !(EXPLICIT_INITIAL_INDEX_SIZE & (EXPLICIT_INITIAL_INDEX_SIZE - 1)), \"Traits::EXPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)\");\n static_assert((IMPLICIT_INITIAL_INDEX_SIZE > 1) && !(IMPLICIT_INITIAL_INDEX_SIZE & (IMPLICIT_INITIAL_INDEX_SIZE - 1)), \"Traits::IMPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)\");\n static_assert((INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) || !(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE & (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - 1)), \"Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be a power of 2\");\n static_assert(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0 || INITIAL_IMPLICIT_PRODUCER_HASH_SIZE >= 1, \"Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be at least 1 (or 0 to disable implicit enqueueing)\");\n\npublic:\n // Creates a queue with at least `capacity` element slots; note that the\n // actual number of elements that can be inserted without additional memory\n // allocation depends on the number of producers and the block size (e.g. if\n // the block size is equal to `capacity`, only a single block will be allocated\n // up-front, which means only a single producer will be able to enqueue elements\n // without an extra allocation -- blocks aren't shared between producers).\n // This method is not thread safe -- it is up to the user to ensure that the\n // queue is fully constructed before it starts being used by other threads (this\n // includes making the memory effects of construction visible, possibly with a\n // memory barrier).\n explicit ConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)\n  : producerListTail(nullptr),\n  producerCount(0),\n  initialBlockPoolIndex(0),\n  nextExplicitConsumerId(0),\n  globalExplicitConsumerOffset(0)\n {\n  implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n  populate_initial_implicit_producer_hash();\n  populate_initial_block_list(capacity / BLOCK_SIZE + ((capacity & (BLOCK_SIZE - 1)) == 0 ? 0 : 1));\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n  // Track all the producers using a fully-resolved typed list for\n  // each kind; this makes it possible to debug them starting from\n  // the root queue object (otherwise wacky casts are needed that\n  // don't compile in the debugger's expression evaluator).\n  explicitProducers.store(nullptr, std::memory_order_relaxed);\n  implicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n }\n \n // Computes the correct amount of pre-allocated blocks for you based\n // on the minimum number of elements you want available at any given\n // time, and the maximum concurrent number of each type of producer.\n ConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)\n  : producerListTail(nullptr),\n  producerCount(0),\n  initialBlockPoolIndex(0),\n  nextExplicitConsumerId(0),\n  globalExplicitConsumerOffset(0)\n {\n  implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n  populate_initial_implicit_producer_hash();\n  size_t blocks = (((minCapacity + BLOCK_SIZE - 1) / BLOCK_SIZE) - 1) * (maxExplicitProducers + 1) + 2 * (maxExplicitProducers + maxImplicitProducers);\n  populate_initial_block_list(blocks);\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n  explicitProducers.store(nullptr, std::memory_order_relaxed);\n  implicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n }\n \n // Note: The queue should not be accessed concurrently while it's\n // being deleted. It's up to the user to synchronize this.\n // This method is not thread safe.\n ~ConcurrentQueue()\n {\n  // Destroy producers\n  auto ptr = producerListTail.load(std::memory_order_relaxed);\n  while (ptr != nullptr) {\n   auto next = ptr->next_prod();\n   if (ptr->token != nullptr) {\n    ptr->token->producer = nullptr;\n   }\n   destroy(ptr);\n   ptr = next;\n  }\n  \n  // Destroy implicit producer hash tables\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE != 0) {\n   auto hash = implicitProducerHash.load(std::memory_order_relaxed);\n   while (hash != nullptr) {\n    auto prev = hash->prev;\n    if (prev != nullptr) {  // The last hash is part of this object and was not allocated dynamically\n     for (size_t i = 0; i != hash->capacity; ++i) {\n      hash->entries[i].~ImplicitProducerKVP();\n     }\n     hash->~ImplicitProducerHash();\n     (Traits::free)(hash);\n    }\n    hash = prev;\n   }\n  }\n  \n  // Destroy global free list\n  auto block = freeList.head_unsafe();\n  while (block != nullptr) {\n   auto next = block->freeListNext.load(std::memory_order_relaxed);\n   if (block->dynamicallyAllocated) {\n    destroy(block);\n   }\n   block = next;\n  }\n  \n  // Destroy initial free list\n  destroy_array(initialBlockPool, initialBlockPoolSize);\n }\n\n // Disable copying and copy assignment\n ConcurrentQueue(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n ConcurrentQueue& operator=(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n \n // Moving is supported, but note that it is *not* a thread-safe operation.\n // Nobody can use the queue while it's being moved, and the memory effects\n // of that move must be propagated to other threads before they can use it.\n // Note: When a queue is moved, its tokens are still valid but can only be\n // used with the destination queue (i.e. semantically they are moved along\n // with the queue itself).\n ConcurrentQueue(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n  : producerListTail(other.producerListTail.load(std::memory_order_relaxed)),\n  producerCount(other.producerCount.load(std::memory_order_relaxed)),\n  initialBlockPoolIndex(other.initialBlockPoolIndex.load(std::memory_order_relaxed)),\n  initialBlockPool(other.initialBlockPool),\n  initialBlockPoolSize(other.initialBlockPoolSize),\n  freeList(std::move(other.freeList)),\n  nextExplicitConsumerId(other.nextExplicitConsumerId.load(std::memory_order_relaxed)),\n  globalExplicitConsumerOffset(other.globalExplicitConsumerOffset.load(std::memory_order_relaxed))\n {\n  // Move the other one into this, and leave the other one as an empty queue\n  implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n  populate_initial_implicit_producer_hash();\n  swap_implicit_producer_hashes(other);\n  \n  other.producerListTail.store(nullptr, std::memory_order_relaxed);\n  other.producerCount.store(0, std::memory_order_relaxed);\n  other.nextExplicitConsumerId.store(0, std::memory_order_relaxed);\n  other.globalExplicitConsumerOffset.store(0, std::memory_order_relaxed);\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n  explicitProducers.store(other.explicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed);\n  other.explicitProducers.store(nullptr, std::memory_order_relaxed);\n  implicitProducers.store(other.implicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed);\n  other.implicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n  \n  other.initialBlockPoolIndex.store(0, std::memory_order_relaxed);\n  other.initialBlockPoolSize = 0;\n  other.initialBlockPool = nullptr;\n  \n  reown_producers();\n }\n \n inline ConcurrentQueue& operator=(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n {\n  return swap_internal(other);\n }\n \n // Swaps this queue's state with the other's. Not thread-safe.\n // Swapping two queues does not invalidate their tokens, however\n // the tokens that were created for one queue must be used with\n // only the swapped queue (i.e. the tokens are tied to the\n // queue's movable state, not the object itself).\n inline void swap(ConcurrentQueue& other) MOODYCAMEL_NOEXCEPT\n {\n  swap_internal(other);\n }\n \nprivate:\n ConcurrentQueue& swap_internal(ConcurrentQueue& other)\n {\n  if (this == &other) {\n   return *this;\n  }\n  \n  details::swap_relaxed(producerListTail, other.producerListTail);\n  details::swap_relaxed(producerCount, other.producerCount);\n  details::swap_relaxed(initialBlockPoolIndex, other.initialBlockPoolIndex);\n  std::swap(initialBlockPool, other.initialBlockPool);\n  std::swap(initialBlockPoolSize, other.initialBlockPoolSize);\n  freeList.swap(other.freeList);\n  details::swap_relaxed(nextExplicitConsumerId, other.nextExplicitConsumerId);\n  details::swap_relaxed(globalExplicitConsumerOffset, other.globalExplicitConsumerOffset);\n  \n  swap_implicit_producer_hashes(other);\n  \n  reown_producers();\n  other.reown_producers();\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n  details::swap_relaxed(explicitProducers, other.explicitProducers);\n  details::swap_relaxed(implicitProducers, other.implicitProducers);\n#endif\n  \n  return *this;\n }\n \npublic:\n // Enqueues a single item (by copying it).\n // Allocates memory if required. Only fails if memory allocation fails (or implicit\n // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Thread-safe.\n inline bool enqueue(T const& item)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue<CanAlloc>(item);\n }\n \n // Enqueues a single item (by moving it, if possible).\n // Allocates memory if required. Only fails if memory allocation fails (or implicit\n // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Thread-safe.\n inline bool enqueue(T&& item)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue<CanAlloc>(std::move(item));\n }\n \n // Enqueues a single item (by copying it) using an explicit producer token.\n // Allocates memory if required. Only fails if memory allocation fails (or\n // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Thread-safe.\n inline bool enqueue(producer_token_t const& token, T const& item)\n {\n  return inner_enqueue<CanAlloc>(token, item);\n }\n \n // Enqueues a single item (by moving it, if possible) using an explicit producer token.\n // Allocates memory if required. Only fails if memory allocation fails (or\n // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Thread-safe.\n inline bool enqueue(producer_token_t const& token, T&& item)\n {\n  return inner_enqueue<CanAlloc>(token, std::move(item));\n }\n \n // Enqueues several items.\n // Allocates memory if required. Only fails if memory allocation fails (or\n // implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n // is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Note: Use std::make_move_iterator if the elements should be moved instead of copied.\n // Thread-safe.\n template<typename It>\n bool enqueue_bulk(It itemFirst, size_t count)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue_bulk<CanAlloc>(itemFirst, count);\n }\n \n // Enqueues several items using an explicit producer token.\n // Allocates memory if required. Only fails if memory allocation fails\n // (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n // Note: Use std::make_move_iterator if the elements should be moved\n // instead of copied.\n // Thread-safe.\n template<typename It>\n bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n {\n  return inner_enqueue_bulk<CanAlloc>(token, itemFirst, count);\n }\n \n // Enqueues a single item (by copying it).\n // Does not allocate memory. Fails if not enough room to enqueue (or implicit\n // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n // is 0).\n // Thread-safe.\n inline bool try_enqueue(T const& item)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue<CannotAlloc>(item);\n }\n \n // Enqueues a single item (by moving it, if possible).\n // Does not allocate memory (except for one-time implicit producer).\n // Fails if not enough room to enqueue (or implicit production is\n // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n // Thread-safe.\n inline bool try_enqueue(T&& item)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue<CannotAlloc>(std::move(item));\n }\n \n // Enqueues a single item (by copying it) using an explicit producer token.\n // Does not allocate memory. Fails if not enough room to enqueue.\n // Thread-safe.\n inline bool try_enqueue(producer_token_t const& token, T const& item)\n {\n  return inner_enqueue<CannotAlloc>(token, item);\n }\n \n // Enqueues a single item (by moving it, if possible) using an explicit producer token.\n // Does not allocate memory. Fails if not enough room to enqueue.\n // Thread-safe.\n inline bool try_enqueue(producer_token_t const& token, T&& item)\n {\n  return inner_enqueue<CannotAlloc>(token, std::move(item));\n }\n \n // Enqueues several items.\n // Does not allocate memory (except for one-time implicit producer).\n // Fails if not enough room to enqueue (or implicit production is\n // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n // Note: Use std::make_move_iterator if the elements should be moved\n // instead of copied.\n // Thread-safe.\n template<typename It>\n bool try_enqueue_bulk(It itemFirst, size_t count)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n  return inner_enqueue_bulk<CannotAlloc>(itemFirst, count);\n }\n \n // Enqueues several items using an explicit producer token.\n // Does not allocate memory. Fails if not enough room to enqueue.\n // Note: Use std::make_move_iterator if the elements should be moved\n // instead of copied.\n // Thread-safe.\n template<typename It>\n bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n {\n  return inner_enqueue_bulk<CannotAlloc>(token, itemFirst, count);\n }\n \n \n \n // Attempts to dequeue from the queue.\n // Returns false if all producer streams appeared empty at the time they\n // were checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename U>\n bool try_dequeue(U& item)\n {\n  // Instead of simply trying each producer in turn (which could cause needless contention on the first\n  // producer), we score them heuristically.\n  size_t nonEmptyCount = 0;\n  ProducerBase* best = nullptr;\n  size_t bestSize = 0;\n  for (auto ptr = producerListTail.load(std::memory_order_acquire); nonEmptyCount < 3 && ptr != nullptr; ptr = ptr->next_prod()) {\n   auto size = ptr->size_approx();\n   if (size > 0) {\n    if (size > bestSize) {\n     bestSize = size;\n     best = ptr;\n    }\n    ++nonEmptyCount;\n   }\n  }\n  \n  // If there was at least one non-empty queue but it appears empty at the time\n  // we try to dequeue from it, we need to make sure every queue's been tried\n  if (nonEmptyCount > 0) {\n   if ((details::likely)(best->dequeue(item))) {\n    return true;\n   }\n   for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n    if (ptr != best && ptr->dequeue(item)) {\n     return true;\n    }\n   }\n  }\n  return false;\n }\n \n // Attempts to dequeue from the queue.\n // Returns false if all producer streams appeared empty at the time they\n // were checked (so, the queue is likely but not guaranteed to be empty).\n // This differs from the try_dequeue(item) method in that this one does\n // not attempt to reduce contention by interleaving the order that producer\n // streams are dequeued from. So, using this method can reduce overall throughput\n // under contention, but will give more predictable results in single-threaded\n // consumer scenarios. This is mostly only useful for internal unit tests.\n // Never allocates. Thread-safe.\n template<typename U>\n bool try_dequeue_non_interleaved(U& item)\n {\n  for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n   if (ptr->dequeue(item)) {\n    return true;\n   }\n  }\n  return false;\n }\n \n // Attempts to dequeue from the queue using an explicit consumer token.\n // Returns false if all producer streams appeared empty at the time they\n // were checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename U>\n bool try_dequeue(consumer_token_t& token, U& item)\n {\n  // The idea is roughly as follows:\n  // Every 256 items from one producer, make everyone rotate (increase the global offset) -> this means the highest efficiency consumer dictates the rotation speed of everyone else, more or less\n  // If you see that the global offset has changed, you must reset your consumption counter and move to your designated place\n  // If there's no items where you're supposed to be, keep moving until you find a producer with some items\n  // If the global offset has not changed but you've run out of items to consume, move over from your current position until you find an producer with something in it\n  \n  if (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) {\n   if (!update_current_producer_after_rotation(token)) {\n    return false;\n   }\n  }\n  \n  // If there was at least one non-empty queue but it appears empty at the time\n  // we try to dequeue from it, we need to make sure every queue's been tried\n  if (static_cast<ProducerBase*>(token.currentProducer)->dequeue(item)) {\n   if (++token.itemsConsumedFromCurrent == EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) {\n    globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed);\n   }\n   return true;\n  }\n  \n  auto tail = producerListTail.load(std::memory_order_acquire);\n  auto ptr = static_cast<ProducerBase*>(token.currentProducer)->next_prod();\n  if (ptr == nullptr) {\n   ptr = tail;\n  }\n  while (ptr != static_cast<ProducerBase*>(token.currentProducer)) {\n   if (ptr->dequeue(item)) {\n    token.currentProducer = ptr;\n    token.itemsConsumedFromCurrent = 1;\n    return true;\n   }\n   ptr = ptr->next_prod();\n   if (ptr == nullptr) {\n    ptr = tail;\n   }\n  }\n  return false;\n }\n \n // Attempts to dequeue several elements from the queue.\n // Returns the number of items actually dequeued.\n // Returns 0 if all producer streams appeared empty at the time they\n // were checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename It>\n size_t try_dequeue_bulk(It itemFirst, size_t max)\n {\n  size_t count = 0;\n  for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n   count += ptr->dequeue_bulk(itemFirst, max - count);\n   if (count == max) {\n    break;\n   }\n  }\n  return count;\n }\n \n // Attempts to dequeue several elements from the queue using an explicit consumer token.\n // Returns the number of items actually dequeued.\n // Returns 0 if all producer streams appeared empty at the time they\n // were checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename It>\n size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)\n {\n  if (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) {\n   if (!update_current_producer_after_rotation(token)) {\n    return 0;\n   }\n  }\n  \n  size_t count = static_cast<ProducerBase*>(token.currentProducer)->dequeue_bulk(itemFirst, max);\n  if (count == max) {\n   if ((token.itemsConsumedFromCurrent += static_cast<std::uint32_t>(max)) >= EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) {\n    globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed);\n   }\n   return max;\n  }\n  token.itemsConsumedFromCurrent += static_cast<std::uint32_t>(count);\n  max -= count;\n  \n  auto tail = producerListTail.load(std::memory_order_acquire);\n  auto ptr = static_cast<ProducerBase*>(token.currentProducer)->next_prod();\n  if (ptr == nullptr) {\n   ptr = tail;\n  }\n  while (ptr != static_cast<ProducerBase*>(token.currentProducer)) {\n   auto dequeued = ptr->dequeue_bulk(itemFirst, max);\n   count += dequeued;\n   if (dequeued != 0) {\n    token.currentProducer = ptr;\n    token.itemsConsumedFromCurrent = static_cast<std::uint32_t>(dequeued);\n   }\n   if (dequeued == max) {\n    break;\n   }\n   max -= dequeued;\n   ptr = ptr->next_prod();\n   if (ptr == nullptr) {\n    ptr = tail;\n   }\n  }\n  return count;\n }\n \n \n \n // Attempts to dequeue from a specific producer's inner queue.\n // If you happen to know which producer you want to dequeue from, this\n // is significantly faster than using the general-case try_dequeue methods.\n // Returns false if the producer's queue appeared empty at the time it\n // was checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename U>\n inline bool try_dequeue_from_producer(producer_token_t const& producer, U& item)\n {\n  return static_cast<ExplicitProducer*>(producer.producer)->dequeue(item);\n }\n \n // Attempts to dequeue several elements from a specific producer's inner queue.\n // Returns the number of items actually dequeued.\n // If you happen to know which producer you want to dequeue from, this\n // is significantly faster than using the general-case try_dequeue methods.\n // Returns 0 if the producer's queue appeared empty at the time it\n // was checked (so, the queue is likely but not guaranteed to be empty).\n // Never allocates. Thread-safe.\n template<typename It>\n inline size_t try_dequeue_bulk_from_producer(producer_token_t const& producer, It itemFirst, size_t max)\n {\n  return static_cast<ExplicitProducer*>(producer.producer)->dequeue_bulk(itemFirst, max);\n }\n \n \n // Returns an estimate of the total number of elements currently in the queue. This\n // estimate is only accurate if the queue has completely stabilized before it is called\n // (i.e. all enqueue and dequeue operations have completed and their memory effects are\n // visible on the calling thread, and no further operations start while this method is\n // being called).\n // Thread-safe.\n size_t size_approx() const\n {\n  size_t size = 0;\n  for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n   size += ptr->size_approx();\n  }\n  return size;\n }\n \n \n // Returns true if the underlying atomic variables used by\n // the queue are lock-free (they should be on most platforms).\n // Thread-safe.\n static bool is_lock_free()\n {\n  return\n   details::static_is_lock_free<bool>::value == 2 &&\n   details::static_is_lock_free<size_t>::value == 2 &&\n   details::static_is_lock_free<std::uint32_t>::value == 2 &&\n   details::static_is_lock_free<index_t>::value == 2 &&\n   details::static_is_lock_free<void*>::value == 2 &&\n   details::static_is_lock_free<typename details::thread_id_converter<details::thread_id_t>::thread_id_numeric_size_t>::value == 2;\n }\n\n\nprivate:\n friend struct ProducerToken;\n friend struct ConsumerToken;\n struct ExplicitProducer;\n friend struct ExplicitProducer;\n struct ImplicitProducer;\n friend struct ImplicitProducer;\n friend class ConcurrentQueueTests;\n  \n enum AllocationMode { CanAlloc, CannotAlloc };\n \n \n ///////////////////////////////\n // Queue methods\n ///////////////////////////////\n \n template<AllocationMode canAlloc, typename U>\n inline bool inner_enqueue(producer_token_t const& token, U&& element)\n {\n  return static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));\n }\n \n template<AllocationMode canAlloc, typename U>\n inline bool inner_enqueue(U&& element)\n {\n  auto producer = get_or_add_implicit_producer();\n  return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));\n }\n \n template<AllocationMode canAlloc, typename It>\n inline bool inner_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n {\n  return static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue_bulk<canAlloc>(itemFirst, count);\n }\n \n template<AllocationMode canAlloc, typename It>\n inline bool inner_enqueue_bulk(It itemFirst, size_t count)\n {\n  auto producer = get_or_add_implicit_producer();\n  return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue_bulk<canAlloc>(itemFirst, count);\n }\n \n inline bool update_current_producer_after_rotation(consumer_token_t& token)\n {\n  // Ah, there's been a rotation, figure out where we should be!\n  auto tail = producerListTail.load(std::memory_order_acquire);\n  if (token.desiredProducer == nullptr && tail == nullptr) {\n   return false;\n  }\n  auto prodCount = producerCount.load(std::memory_order_relaxed);\n  auto globalOffset = globalExplicitConsumerOffset.load(std::memory_order_relaxed);\n  if ((details::unlikely)(token.desiredProducer == nullptr)) {\n   // Aha, first time we're dequeueing anything.\n   // Figure out our local position\n   // Note: offset is from start, not end, but we're traversing from end -- subtract from count first\n   std::uint32_t offset = prodCount - 1 - (token.initialOffset % prodCount);\n   token.desiredProducer = tail;\n   for (std::uint32_t i = 0; i != offset; ++i) {\n    token.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();\n    if (token.desiredProducer == nullptr) {\n     token.desiredProducer = tail;\n    }\n   }\n  }\n  \n  std::uint32_t delta = globalOffset - token.lastKnownGlobalOffset;\n  if (delta >= prodCount) {\n   delta = delta % prodCount;\n  }\n  for (std::uint32_t i = 0; i != delta; ++i) {\n   token.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();\n   if (token.desiredProducer == nullptr) {\n    token.desiredProducer = tail;\n   }\n  }\n  \n  token.lastKnownGlobalOffset = globalOffset;\n  token.currentProducer = token.desiredProducer;\n  token.itemsConsumedFromCurrent = 0;\n  return true;\n }\n \n \n ///////////////////////////\n // Free list\n ///////////////////////////\n \n template <typename N>\n struct FreeListNode\n {\n  FreeListNode() : freeListRefs(0), freeListNext(nullptr) { }\n  \n  std::atomic<std::uint32_t> freeListRefs;\n  std::atomic<N*> freeListNext;\n };\n \n // A simple CAS-based lock-free free list. Not the fastest thing in the world under heavy contention, but\n // simple and correct (assuming nodes are never freed until after the free list is destroyed), and fairly\n // speedy under low contention.\n template<typename N>  // N must inherit FreeListNode or have the same fields (and initialization of them)\n struct FreeList\n {\n  FreeList() : freeListHead(nullptr) { }\n  FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); }\n  void swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); }\n  \n  FreeList(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;\n  FreeList& operator=(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;\n  \n  inline void add(N* node)\n  {\n#if MCDBGQ_NOLOCKFREE_FREELIST\n   debug::DebugLock lock(mutex);\n#endif  \n   // We know that the should-be-on-freelist bit is 0 at this point, so it's safe to\n   // set it using a fetch_add\n   if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST, std::memory_order_acq_rel) == 0) {\n    // Oh look! We were the last ones referencing this node, and we know\n    // we want to add it to the free list, so let's do it!\n     add_knowing_refcount_is_zero(node);\n   }\n  }\n  \n  inline N* try_get()\n  {\n#if MCDBGQ_NOLOCKFREE_FREELIST\n   debug::DebugLock lock(mutex);\n#endif  \n   auto head = freeListHead.load(std::memory_order_acquire);\n   while (head != nullptr) {\n    auto prevHead = head;\n    auto refs = head->freeListRefs.load(std::memory_order_relaxed);\n    if ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong(refs, refs + 1, std::memory_order_acquire, std::memory_order_relaxed)) {\n     head = freeListHead.load(std::memory_order_acquire);\n     continue;\n    }\n    \n    // Good, reference count has been incremented (it wasn't at zero), which means we can read the\n    // next and not worry about it changing between now and the time we do the CAS\n    auto next = head->freeListNext.load(std::memory_order_relaxed);\n    if (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) {\n     // Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no\n     // matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on).\n     assert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0);\n     \n     // Decrease refcount twice, once for our ref, and once for the list's ref\n     head->freeListRefs.fetch_sub(2, std::memory_order_release);\n     return head;\n    }\n    \n    // OK, the head must have changed on us, but we still need to decrease the refcount we increased.\n    // Note that we don't need to release any memory effects, but we do need to ensure that the reference\n    // count decrement happens-after the CAS on the head.\n    refs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel);\n    if (refs == SHOULD_BE_ON_FREELIST + 1) {\n     add_knowing_refcount_is_zero(prevHead);\n    }\n   }\n   \n   return nullptr;\n  }\n  \n  // Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes)\n  N* head_unsafe() const { return freeListHead.load(std::memory_order_relaxed); }\n  \n private:\n  inline void add_knowing_refcount_is_zero(N* node)\n  {\n   // Since the refcount is zero, and nobody can increase it once it's zero (except us, and we run\n   // only one copy of this method per node at a time, i.e. the single thread case), then we know\n   // we can safely change the next pointer of the node; however, once the refcount is back above\n   // zero, then other threads could increase it (happens under heavy contention, when the refcount\n   // goes to zero in between a load and a refcount increment of a node in try_get, then back up to\n   // something non-zero, then the refcount increment is done by the other thread) -- so, if the CAS\n   // to add the node to the actual list fails, decrease the refcount and leave the add operation to\n   // the next thread who puts the refcount back at zero (which could be us, hence the loop).\n   auto head = freeListHead.load(std::memory_order_relaxed);\n   while (true) {\n    node->freeListNext.store(head, std::memory_order_relaxed);\n    node->freeListRefs.store(1, std::memory_order_release);\n    if (!freeListHead.compare_exchange_strong(head, node, std::memory_order_release, std::memory_order_relaxed)) {\n     // Hmm, the add failed, but we can only try again when the refcount goes back to zero\n     if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST - 1, std::memory_order_release) == 1) {\n      continue;\n     }\n    }\n    return;\n   }\n  }\n  \n private:\n  // Implemented like a stack, but where node order doesn't matter (nodes are inserted out of order under contention)\n  std::atomic<N*> freeListHead;\n \n static const std::uint32_t REFS_MASK = 0x7FFFFFFF;\n static const std::uint32_t SHOULD_BE_ON_FREELIST = 0x80000000;\n  \n#if MCDBGQ_NOLOCKFREE_FREELIST\n  debug::DebugMutex mutex;\n#endif\n };\n \n \n ///////////////////////////\n // Block\n ///////////////////////////\n \n enum InnerQueueContext { implicit_context = 0, explicit_context = 1 };\n \n struct Block\n {\n  Block()\n   : next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), shouldBeOnFreeList(false), dynamicallyAllocated(true)\n  {\n#if MCDBGQ_TRACKMEM\n   owner = nullptr;\n#endif\n  }\n  \n  template<InnerQueueContext context>\n  inline bool is_empty() const\n  {\n   if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n    // Check flags\n    for (size_t i = 0; i < BLOCK_SIZE; ++i) {\n     if (!emptyFlags[i].load(std::memory_order_relaxed)) {\n      return false;\n     }\n    }\n    \n    // Aha, empty; make sure we have all other memory effects that happened before the empty flags were set\n    std::atomic_thread_fence(std::memory_order_acquire);\n    return true;\n   }\n   else {\n    // Check counter\n    if (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) {\n     std::atomic_thread_fence(std::memory_order_acquire);\n     return true;\n    }\n    assert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE);\n    return false;\n   }\n  }\n  \n  // Returns true if the block is now empty (does not apply in explicit context)\n  template<InnerQueueContext context>\n  inline bool set_empty(index_t i)\n  {\n   if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n    // Set flag\n    assert(!emptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].load(std::memory_order_relaxed));\n    emptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].store(true, std::memory_order_release);\n    return false;\n   }\n   else {\n    // Increment counter\n    auto prevVal = elementsCompletelyDequeued.fetch_add(1, std::memory_order_release);\n    assert(prevVal < BLOCK_SIZE);\n    return prevVal == BLOCK_SIZE - 1;\n   }\n  }\n  \n  // Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0).\n  // Returns true if the block is now empty (does not apply in explicit context).\n  template<InnerQueueContext context>\n  inline bool set_many_empty(index_t i, size_t count)\n  {\n   if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n    // Set flags\n    std::atomic_thread_fence(std::memory_order_release);\n    i = BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1)) - count + 1;\n    for (size_t j = 0; j != count; ++j) {\n     assert(!emptyFlags[i + j].load(std::memory_order_relaxed));\n     emptyFlags[i + j].store(true, std::memory_order_relaxed);\n    }\n    return false;\n   }\n   else {\n    // Increment counter\n    auto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release);\n    assert(prevVal + count <= BLOCK_SIZE);\n    return prevVal + count == BLOCK_SIZE;\n   }\n  }\n  \n  template<InnerQueueContext context>\n  inline void set_all_empty()\n  {\n   if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n    // Set all flags\n    for (size_t i = 0; i != BLOCK_SIZE; ++i) {\n     emptyFlags[i].store(true, std::memory_order_relaxed);\n    }\n   }\n   else {\n    // Reset counter\n    elementsCompletelyDequeued.store(BLOCK_SIZE, std::memory_order_relaxed);\n   }\n  }\n  \n  template<InnerQueueContext context>\n  inline void reset_empty()\n  {\n   if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n    // Reset flags\n    for (size_t i = 0; i != BLOCK_SIZE; ++i) {\n     emptyFlags[i].store(false, std::memory_order_relaxed);\n    }\n   }\n   else {\n    // Reset counter\n    elementsCompletelyDequeued.store(0, std::memory_order_relaxed);\n   }\n  }\n  \n  inline T* operator[](index_t idx) MOODYCAMEL_NOEXCEPT { return static_cast<T*>(static_cast<void*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }\n  inline T const* operator[](index_t idx) const MOODYCAMEL_NOEXCEPT { return static_cast<T const*>(static_cast<void const*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }\n  \n private:\n  // IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of\n  // addresses returned by malloc, that alignment will be preserved. Apparently clang actually\n  // generates code that uses this assumption for AVX instructions in some cases. Ideally, we\n  // should also align Block to the alignment of T in case it's higher than malloc's 16-byte\n  // alignment, but this is hard to do in a cross-platform way. Assert for this case:\n  static_assert(std::alignment_of<T>::value <= std::alignment_of<details::max_align_t>::value, \"The queue does not support super-aligned types at this time\");\n  // Additionally, we need the alignment of Block itself to be a multiple of max_align_t since\n  // otherwise the appropriate padding will not be added at the end of Block in order to make\n  // arrays of Blocks all be properly aligned (not just the first one). We use a union to force\n  // this.\n  union {\n   char elements[sizeof(T) * BLOCK_SIZE];\n   details::max_align_t dummy;\n  };\n public:\n  Block* next;\n  std::atomic<size_t> elementsCompletelyDequeued;\n  std::atomic<bool> emptyFlags[BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD ? BLOCK_SIZE : 1];\n public:\n  std::atomic<std::uint32_t> freeListRefs;\n  std::atomic<Block*> freeListNext;\n  std::atomic<bool> shouldBeOnFreeList;\n  bool dynamicallyAllocated;  // Perhaps a better name for this would be 'isNotPartOfInitialBlockPool'\n  \n#if MCDBGQ_TRACKMEM\n  void* owner;\n#endif\n };\n static_assert(std::alignment_of<Block>::value >= std::alignment_of<details::max_align_t>::value, \"Internal error: Blocks must be at least as aligned as the type they are wrapping\");\n\n\n#if MCDBGQ_TRACKMEM\npublic:\n struct MemStats;\nprivate:\n#endif\n \n ///////////////////////////\n // Producer base\n ///////////////////////////\n \n struct ProducerBase : public details::ConcurrentQueueProducerTypelessBase\n {\n  ProducerBase(ConcurrentQueue* parent_, bool isExplicit_) :\n   tailIndex(0),\n   headIndex(0),\n   dequeueOptimisticCount(0),\n   dequeueOvercommit(0),\n   tailBlock(nullptr),\n   isExplicit(isExplicit_),\n   parent(parent_)\n  {\n  }\n  \n  virtual ~ProducerBase() { };\n  \n  template<typename U>\n  inline bool dequeue(U& element)\n  {\n   if (isExplicit) {\n    return static_cast<ExplicitProducer*>(this)->dequeue(element);\n   }\n   else {\n    return static_cast<ImplicitProducer*>(this)->dequeue(element);\n   }\n  }\n  \n  template<typename It>\n  inline size_t dequeue_bulk(It& itemFirst, size_t max)\n  {\n   if (isExplicit) {\n    return static_cast<ExplicitProducer*>(this)->dequeue_bulk(itemFirst, max);\n   }\n   else {\n    return static_cast<ImplicitProducer*>(this)->dequeue_bulk(itemFirst, max);\n   }\n  }\n  \n  inline ProducerBase* next_prod() const { return static_cast<ProducerBase*>(next); }\n  \n  inline size_t size_approx() const\n  {\n   auto tail = tailIndex.load(std::memory_order_relaxed);\n   auto head = headIndex.load(std::memory_order_relaxed);\n   return details::circular_less_than(head, tail) ? static_cast<size_t>(tail - head) : 0;\n  }\n  \n  inline index_t getTail() const { return tailIndex.load(std::memory_order_relaxed); }\n protected:\n  std::atomic<index_t> tailIndex;  // Where to enqueue to next\n  std::atomic<index_t> headIndex;  // Where to dequeue from next\n  \n  std::atomic<index_t> dequeueOptimisticCount;\n  std::atomic<index_t> dequeueOvercommit;\n  \n  Block* tailBlock;\n  \n public:\n  bool isExplicit;\n  ConcurrentQueue* parent;\n  \n protected:\n#if MCDBGQ_TRACKMEM\n  friend struct MemStats;\n#endif\n };\n \n \n ///////////////////////////\n // Explicit queue\n ///////////////////////////\n  \n struct ExplicitProducer : public ProducerBase\n {\n  explicit ExplicitProducer(ConcurrentQueue* parent) :\n   ProducerBase(parent, true),\n   blockIndex(nullptr),\n   pr_blockIndexSlotsUsed(0),\n   pr_blockIndexSize(EXPLICIT_INITIAL_INDEX_SIZE >> 1),\n   pr_blockIndexFront(0),\n   pr_blockIndexEntries(nullptr),\n   pr_blockIndexRaw(nullptr)\n  {\n   size_t poolBasedIndexSize = details::ceil_to_pow_2(parent->initialBlockPoolSize) >> 1;\n   if (poolBasedIndexSize > pr_blockIndexSize) {\n    pr_blockIndexSize = poolBasedIndexSize;\n   }\n   \n   new_block_index(0);  // This creates an index with double the number of current entries, i.e. EXPLICIT_INITIAL_INDEX_SIZE\n  }\n  \n  ~ExplicitProducer()\n  {\n   // Destruct any elements not yet dequeued.\n   // Since we're in the destructor, we can assume all elements\n   // are either completely dequeued or completely not (no halfways).\n   if (this->tailBlock != nullptr) {  // Note this means there must be a block index too\n    // First find the block that's partially dequeued, if any\n    Block* halfDequeuedBlock = nullptr;\n    if ((this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) != 0) {\n     // The head's not on a block boundary, meaning a block somewhere is partially dequeued\n     // (or the head block is the tail block and was fully dequeued, but the head/tail are still not on a boundary)\n     size_t i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & (pr_blockIndexSize - 1);\n     while (details::circular_less_than<index_t>(pr_blockIndexEntries[i].base + BLOCK_SIZE, this->headIndex.load(std::memory_order_relaxed))) {\n      i = (i + 1) & (pr_blockIndexSize - 1);\n     }\n     assert(details::circular_less_than<index_t>(pr_blockIndexEntries[i].base, this->headIndex.load(std::memory_order_relaxed)));\n     halfDequeuedBlock = pr_blockIndexEntries[i].block;\n    }\n    \n    // Start at the head block (note the first line in the loop gives us the head from the tail on the first iteration)\n    auto block = this->tailBlock;\n    do {\n     block = block->next;\n     if (block->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n      continue;\n     }\n     \n     size_t i = 0; // Offset into block\n     if (block == halfDequeuedBlock) {\n      i = static_cast<size_t>(this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));\n     }\n     \n     // Walk through all the items in the block; if this is the tail block, we need to stop when we reach the tail index\n     auto lastValidIndex = (this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 ? BLOCK_SIZE : static_cast<size_t>(this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));\n     while (i != BLOCK_SIZE && (block != this->tailBlock || i != lastValidIndex)) {\n      (*block)[i++]->~T();\n     }\n    } while (block != this->tailBlock);\n   }\n   \n   // Destroy all blocks that we own\n   if (this->tailBlock != nullptr) {\n    auto block = this->tailBlock;\n    do {\n     auto nextBlock = block->next;\n     if (block->dynamicallyAllocated) {\n      destroy(block);\n     }\n     else {\n      this->parent->add_block_to_free_list(block);\n     }\n     block = nextBlock;\n    } while (block != this->tailBlock);\n   }\n   \n   // Destroy the block indices\n   auto header = static_cast<BlockIndexHeader*>(pr_blockIndexRaw);\n   while (header != nullptr) {\n    auto prev = static_cast<BlockIndexHeader*>(header->prev);\n    header->~BlockIndexHeader();\n    (Traits::free)(header);\n    header = prev;\n   }\n  }\n  \n  template<AllocationMode allocMode, typename U>\n  inline bool enqueue(U&& element)\n  {\n   index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n   index_t newTailIndex = 1 + currentTailIndex;\n   if ((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n    // We reached the end of a block, start a new one\n    auto startBlock = this->tailBlock;\n    auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;\n    if (this->tailBlock != nullptr && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n     // We can re-use the block ahead of us, it's empty!     \n     this->tailBlock = this->tailBlock->next;\n     this->tailBlock->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n     \n     // We'll put the block on the block index (guaranteed to be room since we're conceptually removing the\n     // last block from it first -- except instead of removing then adding, we can just overwrite).\n     // Note that there must be a valid block index here, since even if allocation failed in the ctor,\n     // it would have been re-attempted when adding the first block to the queue; since there is such\n     // a block, a block index must have been successfully allocated.\n    }\n    else {\n     // Whatever head value we see here is >= the last value we saw here (relatively),\n     // and <= its current value. Since we have the most recent tail, the head must be\n     // <= to it.\n     auto head = this->headIndex.load(std::memory_order_relaxed);\n     assert(!details::circular_less_than<index_t>(currentTailIndex, head));\n     if (!details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE)\n      || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) {\n      // We can't enqueue in another block because there's not enough leeway -- the\n      // tail could surpass the head by the time the block fills up! (Or we'll exceed\n      // the size limit, if the second part of the condition was true.)\n      return false;\n     }\n     // We're going to need a new block; check that the block index has room\n     if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize) {\n      // Hmm, the circular block index is already full -- we'll need\n      // to allocate a new index. Note pr_blockIndexRaw can only be nullptr if\n      // the initial allocation failed in the constructor.\n      \n      if (allocMode == CannotAlloc || !new_block_index(pr_blockIndexSlotsUsed)) {\n       return false;\n      }\n     }\n     \n     // Insert a new block in the circular linked list\n     auto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n     if (newBlock == nullptr) {\n      return false;\n     }\n#if MCDBGQ_TRACKMEM\n     newBlock->owner = this;\n#endif\n     newBlock->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n     if (this->tailBlock == nullptr) {\n      newBlock->next = newBlock;\n     }\n     else {\n      newBlock->next = this->tailBlock->next;\n      this->tailBlock->next = newBlock;\n     }\n     this->tailBlock = newBlock;\n     ++pr_blockIndexSlotsUsed;\n    }\n    \n    if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward<U>(element)))) {\n     // The constructor may throw. We want the element not to appear in the queue in\n     // that case (without corrupting the queue):\n     MOODYCAMEL_TRY {\n      new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n     }\n     MOODYCAMEL_CATCH (...) {\n      // Revert change to the current block, but leave the new block available\n      // for next time\n      pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n      this->tailBlock = startBlock == nullptr ? this->tailBlock : startBlock;\n      MOODYCAMEL_RETHROW;\n     }\n    }\n    else {\n     (void)startBlock;\n     (void)originalBlockIndexSlotsUsed;\n    }\n    \n    // Add block to block index\n    auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n    entry.base = currentTailIndex;\n    entry.block = this->tailBlock;\n    blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release);\n    pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n    \n    if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward<U>(element)))) {\n     this->tailIndex.store(newTailIndex, std::memory_order_release);\n     return true;\n    }\n   }\n   \n   // Enqueue\n   new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n   \n   this->tailIndex.store(newTailIndex, std::memory_order_release);\n   return true;\n  }\n  \n  template<typename U>\n  bool dequeue(U& element)\n  {\n   auto tail = this->tailIndex.load(std::memory_order_relaxed);\n   auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n   if (details::circular_less_than<index_t>(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) {\n    // Might be something to dequeue, let's give it a try\n    \n    // Note that this if is purely for performance purposes in the common case when the queue is\n    // empty and the values are eventually consistent -- we may enter here spuriously.\n    \n    // Note that whatever the values of overcommit and tail are, they are not going to change (unless we\n    // change them) and must be the same value at this point (inside the if) as when the if condition was\n    // evaluated.\n\n    // We insert an acquire fence here to synchronize-with the release upon incrementing dequeueOvercommit below.\n    // This ensures that whatever the value we got loaded into overcommit, the load of dequeueOptisticCount in\n    // the fetch_add below will result in a value at least as recent as that (and therefore at least as large).\n    // Note that I believe a compiler (signal) fence here would be sufficient due to the nature of fetch_add (all\n    // read-modify-write operations are guaranteed to work on the latest value in the modification order), but\n    // unfortunately that can't be shown to be correct using only the C++11 standard.\n    // See http://stackoverflow.com/questions/18223161/what-are-the-c11-memory-ordering-guarantees-in-this-corner-case\n    std::atomic_thread_fence(std::memory_order_acquire);\n    \n    // Increment optimistic counter, then check if it went over the boundary\n    auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed);\n    \n    // Note that since dequeueOvercommit must be <= dequeueOptimisticCount (because dequeueOvercommit is only ever\n    // incremented after dequeueOptimisticCount -- this is enforced in the `else` block below), and since we now\n    // have a version of dequeueOptimisticCount that is at least as recent as overcommit (due to the release upon\n    // incrementing dequeueOvercommit and the acquire above that synchronizes with it), overcommit <= myDequeueCount.\n    // However, we can't assert this since both dequeueOptimisticCount and dequeueOvercommit may (independently)\n    // overflow; in such a case, though, the logic still holds since the difference between the two is maintained.\n    \n    // Note that we reload tail here in case it changed; it will be the same value as before or greater, since\n    // this load is sequenced after (happens after) the earlier load above. This is supported by read-read\n    // coherency (as defined in the standard), explained here: http://en.cppreference.com/w/cpp/atomic/memory_order\n    tail = this->tailIndex.load(std::memory_order_acquire);\n    if ((details::likely)(details::circular_less_than<index_t>(myDequeueCount - overcommit, tail))) {\n     // Guaranteed to be at least one element to dequeue!\n     \n     // Get the index. Note that since there's guaranteed to be at least one element, this\n     // will never exceed tail. We need to do an acquire-release fence here since it's possible\n     // that whatever condition got us to this point was for an earlier enqueued element (that\n     // we already see the memory effects for), but that by the time we increment somebody else\n     // has incremented it, and we need to see the memory effects for *that* element, which is\n     // in such a case is necessarily visible on the thread that incremented it in the first\n     // place with the more current condition (they must have acquired a tail that is at least\n     // as recent).\n     auto index = this->headIndex.fetch_add(1, std::memory_order_acq_rel);\n     \n     \n     // Determine which block the element is in\n     \n     auto localBlockIndex = blockIndex.load(std::memory_order_acquire);\n     auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);\n     \n     // We need to be careful here about subtracting and dividing because of index wrap-around.\n     // When an index wraps, we need to preserve the sign of the offset when dividing it by the\n     // block size (in order to get a correct signed block count offset in all cases):\n     auto headBase = localBlockIndex->entries[localBlockIndexHead].base;\n     auto blockBaseIndex = index & ~static_cast<index_t>(BLOCK_SIZE - 1);\n     auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(blockBaseIndex - headBase) / BLOCK_SIZE);\n     auto block = localBlockIndex->entries[(localBlockIndexHead + offset) & (localBlockIndex->size - 1)].block;\n     \n     // Dequeue\n     auto& el = *((*block)[index]);\n     if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) {\n      // Make sure the element is still fully dequeued and destroyed even if the assignment\n      // throws\n      struct Guard {\n       Block* block;\n       index_t index;\n       \n       ~Guard()\n       {\n        (*block)[index]->~T();\n        block->ConcurrentQueue::Block::template set_empty<explicit_context>(index);\n       }\n      } guard = { block, index };\n      \n      element = std::move(el);\n     }\n     else {\n      element = std::move(el);\n      el.~T();\n      block->ConcurrentQueue::Block::template set_empty<explicit_context>(index);\n     }\n     \n     return true;\n    }\n    else {\n     // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent\n     this->dequeueOvercommit.fetch_add(1, std::memory_order_release);  // Release so that the fetch_add on dequeueOptimisticCount is guaranteed to happen before this write\n    }\n   }\n  \n   return false;\n  }\n  \n  template<AllocationMode allocMode, typename It>\n  bool enqueue_bulk(It itemFirst, size_t count)\n  {\n   // First, we need to make sure we have enough room to enqueue all of the elements;\n   // this means pre-allocating blocks and putting them in the block index (but only if\n   // all the allocations succeeded).\n   index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n   auto startBlock = this->tailBlock;\n   auto originalBlockIndexFront = pr_blockIndexFront;\n   auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;\n   \n   Block* firstAllocatedBlock = nullptr;\n   \n   // Figure out how many blocks we'll need to allocate, and do so\n   size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));\n   index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n   if (blockBaseDiff > 0) {\n    // Allocate as many blocks as possible from ahead\n    while (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n     blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n     currentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n     \n     this->tailBlock = this->tailBlock->next;\n     firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;\n     \n     auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n     entry.base = currentTailIndex;\n     entry.block = this->tailBlock;\n     pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n    }\n    \n    // Now allocate as many blocks as necessary from the block pool\n    while (blockBaseDiff > 0) {\n     blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n     currentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n     \n     auto head = this->headIndex.load(std::memory_order_relaxed);\n     assert(!details::circular_less_than<index_t>(currentTailIndex, head));\n     bool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));\n     if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) {\n      if (allocMode == CannotAlloc || full || !new_block_index(originalBlockIndexSlotsUsed)) {\n       // Failed to allocate, undo changes (but keep injected blocks)\n       pr_blockIndexFront = originalBlockIndexFront;\n       pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n       this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n       return false;\n      }\n      \n      // pr_blockIndexFront is updated inside new_block_index, so we need to\n      // update our fallback value too (since we keep the new index even if we\n      // later fail)\n      originalBlockIndexFront = originalBlockIndexSlotsUsed;\n     }\n     \n     // Insert a new block in the circular linked list\n     auto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n     if (newBlock == nullptr) {\n      pr_blockIndexFront = originalBlockIndexFront;\n      pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n      this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n      return false;\n     }\n     \n#if MCDBGQ_TRACKMEM\n     newBlock->owner = this;\n#endif\n     newBlock->ConcurrentQueue::Block::template set_all_empty<explicit_context>();\n     if (this->tailBlock == nullptr) {\n      newBlock->next = newBlock;\n     }\n     else {\n      newBlock->next = this->tailBlock->next;\n      this->tailBlock->next = newBlock;\n     }\n     this->tailBlock = newBlock;\n     firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;\n     \n     ++pr_blockIndexSlotsUsed;\n     \n     auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n     entry.base = currentTailIndex;\n     entry.block = this->tailBlock;\n     pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n    }\n    \n    // Excellent, all allocations succeeded. Reset each block's emptiness before we fill them up, and\n    // publish the new block index front\n    auto block = firstAllocatedBlock;\n    while (true) {\n     block->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n     if (block == this->tailBlock) {\n      break;\n     }\n     block = block->next;\n    }\n    \n    if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) {\n     blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release);\n    }\n   }\n   \n   // Enqueue, one block at a time\n   index_t newTailIndex = startTailIndex + static_cast<index_t>(count);\n   currentTailIndex = startTailIndex;\n   auto endBlock = this->tailBlock;\n   this->tailBlock = startBlock;\n   assert((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0);\n   if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) {\n    this->tailBlock = firstAllocatedBlock;\n   }\n   while (true) {\n    auto stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n    if (details::circular_less_than<index_t>(newTailIndex, stopIndex)) {\n     stopIndex = newTailIndex;\n    }\n    if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) {\n     while (currentTailIndex != stopIndex) {\n      new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++);\n     }\n    }\n    else {\n     MOODYCAMEL_TRY {\n      while (currentTailIndex != stopIndex) {\n       // Must use copy constructor even if move constructor is available\n       // because we may have to revert if there's an exception.\n       // Sorry about the horrible templated next line, but it was the only way\n       // to disable moving *at compile time*, which is important because a type\n       // may only define a (noexcept) move constructor, and so calls to the\n       // cctor will not compile, even if they are in an if branch that will never\n       // be executed\n       new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst));\n       ++currentTailIndex;\n       ++itemFirst;\n      }\n     }\n     MOODYCAMEL_CATCH (...) {\n      // Oh dear, an exception's been thrown -- destroy the elements that\n      // were enqueued so far and revert the entire bulk operation (we'll keep\n      // any allocated blocks in our linked list for later, though).\n      auto constructedStopIndex = currentTailIndex;\n      auto lastBlockEnqueued = this->tailBlock;\n      \n      pr_blockIndexFront = originalBlockIndexFront;\n      pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n      this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n      \n      if (!details::is_trivially_destructible<T>::value) {\n       auto block = startBlock;\n       if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n        block = firstAllocatedBlock;\n       }\n       currentTailIndex = startTailIndex;\n       while (true) {\n        stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n        if (details::circular_less_than<index_t>(constructedStopIndex, stopIndex)) {\n         stopIndex = constructedStopIndex;\n        }\n        while (currentTailIndex != stopIndex) {\n         (*block)[currentTailIndex++]->~T();\n        }\n        if (block == lastBlockEnqueued) {\n         break;\n        }\n        block = block->next;\n       }\n      }\n      MOODYCAMEL_RETHROW;\n     }\n    }\n    \n    if (this->tailBlock == endBlock) {\n     assert(currentTailIndex == newTailIndex);\n     break;\n    }\n    this->tailBlock = this->tailBlock->next;\n   }\n   \n   if (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst))) && firstAllocatedBlock != nullptr) {\n    blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release);\n   }\n   \n   this->tailIndex.store(newTailIndex, std::memory_order_release);\n   return true;\n  }\n  \n  template<typename It>\n  size_t dequeue_bulk(It& itemFirst, size_t max)\n  {\n   auto tail = this->tailIndex.load(std::memory_order_relaxed);\n   auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n   auto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));\n   if (details::circular_less_than<size_t>(0, desiredCount)) {\n    desiredCount = desiredCount < max ? desiredCount : max;\n    std::atomic_thread_fence(std::memory_order_acquire);\n    \n    auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);;\n    \n    tail = this->tailIndex.load(std::memory_order_acquire);\n    auto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));\n    if (details::circular_less_than<size_t>(0, actualCount)) {\n     actualCount = desiredCount < actualCount ? desiredCount : actualCount;\n     if (actualCount < desiredCount) {\n      this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);\n     }\n     \n     // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this\n     // will never exceed tail.\n     auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);\n     \n     // Determine which block the first element is in\n     auto localBlockIndex = blockIndex.load(std::memory_order_acquire);\n     auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);\n     \n     auto headBase = localBlockIndex->entries[localBlockIndexHead].base;\n     auto firstBlockBaseIndex = firstIndex & ~static_cast<index_t>(BLOCK_SIZE - 1);\n     auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(firstBlockBaseIndex - headBase) / BLOCK_SIZE);\n     auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1);\n     \n     // Iterate the blocks and dequeue\n     auto index = firstIndex;\n     do {\n      auto firstIndexInBlock = index;\n      auto endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n      endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n      auto block = localBlockIndex->entries[indexIndex].block;\n      if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {\n       while (index != endIndex) {\n        auto& el = *((*block)[index]);\n        *itemFirst++ = std::move(el);\n        el.~T();\n        ++index;\n       }\n      }\n      else {\n       MOODYCAMEL_TRY {\n        while (index != endIndex) {\n         auto& el = *((*block)[index]);\n         *itemFirst = std::move(el);\n         ++itemFirst;\n         el.~T();\n         ++index;\n        }\n       }\n       MOODYCAMEL_CATCH (...) {\n        // It's too late to revert the dequeue, but we can make sure that all\n        // the dequeued objects are properly destroyed and the block index\n        // (and empty count) are properly updated before we propagate the exception\n        do {\n         block = localBlockIndex->entries[indexIndex].block;\n         while (index != endIndex) {\n          (*block)[index++]->~T();\n         }\n         block->ConcurrentQueue::Block::template set_many_empty<explicit_context>(firstIndexInBlock, static_cast<size_t>(endIndex - firstIndexInBlock));\n         indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1);\n         \n         firstIndexInBlock = index;\n         endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n         endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n        } while (index != firstIndex + actualCount);\n        \n        MOODYCAMEL_RETHROW;\n       }\n      }\n      block->ConcurrentQueue::Block::template set_many_empty<explicit_context>(firstIndexInBlock, static_cast<size_t>(endIndex - firstIndexInBlock));\n      indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1);\n     } while (index != firstIndex + actualCount);\n     \n     return actualCount;\n    }\n    else {\n     // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent\n     this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release);\n    }\n   }\n   \n   return 0;\n  }\n  \n private:\n  struct BlockIndexEntry\n  {\n   index_t base;\n   Block* block;\n  };\n  \n  struct BlockIndexHeader\n  {\n   size_t size;\n   std::atomic<size_t> front;  // Current slot (not next, like pr_blockIndexFront)\n   BlockIndexEntry* entries;\n   void* prev;\n  };\n  \n  \n  bool new_block_index(size_t numberOfFilledSlotsToExpose)\n  {\n   auto prevBlockSizeMask = pr_blockIndexSize - 1;\n   \n   // Create the new block\n   pr_blockIndexSize <<= 1;\n   auto newRawPtr = static_cast<char*>((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * pr_blockIndexSize));\n   if (newRawPtr == nullptr) {\n    pr_blockIndexSize >>= 1;  // Reset to allow graceful retry\n    return false;\n   }\n   \n   auto newBlockIndexEntries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(newRawPtr + sizeof(BlockIndexHeader)));\n   \n   // Copy in all the old indices, if any\n   size_t j = 0;\n   if (pr_blockIndexSlotsUsed != 0) {\n    auto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask;\n    do {\n     newBlockIndexEntries[j++] = pr_blockIndexEntries[i];\n     i = (i + 1) & prevBlockSizeMask;\n    } while (i != pr_blockIndexFront);\n   }\n   \n   // Update everything\n   auto header = new (newRawPtr) BlockIndexHeader;\n   header->size = pr_blockIndexSize;\n   header->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed);\n   header->entries = newBlockIndexEntries;\n   header->prev = pr_blockIndexRaw;  // we link the new block to the old one so we can free it later\n   \n   pr_blockIndexFront = j;\n   pr_blockIndexEntries = newBlockIndexEntries;\n   pr_blockIndexRaw = newRawPtr;\n   blockIndex.store(header, std::memory_order_release);\n   \n   return true;\n  }\n  \n private:\n  std::atomic<BlockIndexHeader*> blockIndex;\n  \n  // To be used by producer only -- consumer must use the ones in referenced by blockIndex\n  size_t pr_blockIndexSlotsUsed;\n  size_t pr_blockIndexSize;\n  size_t pr_blockIndexFront;  // Next slot (not current)\n  BlockIndexEntry* pr_blockIndexEntries;\n  void* pr_blockIndexRaw;\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n public:\n  ExplicitProducer* nextExplicitProducer;\n private:\n#endif\n  \n#if MCDBGQ_TRACKMEM\n  friend struct MemStats;\n#endif\n };\n \n \n //////////////////////////////////\n // Implicit queue\n //////////////////////////////////\n \n struct ImplicitProducer : public ProducerBase\n {   \n  ImplicitProducer(ConcurrentQueue* parent) :\n   ProducerBase(parent, false),\n   nextBlockIndexCapacity(IMPLICIT_INITIAL_INDEX_SIZE),\n   blockIndex(nullptr)\n  {\n   new_block_index();\n  }\n  \n  ~ImplicitProducer()\n  {\n   // Note that since we're in the destructor we can assume that all enqueue/dequeue operations\n   // completed already; this means that all undequeued elements are placed contiguously across\n   // contiguous blocks, and that only the first and last remaining blocks can be only partially\n   // empty (all other remaining blocks must be completely full).\n   \n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n   // Unregister ourselves for thread termination notification\n   if (!this->inactive.load(std::memory_order_relaxed)) {\n    details::ThreadExitNotifier::unsubscribe(&threadExitListener);\n   }\n#endif\n   \n   // Destroy all remaining elements!\n   auto tail = this->tailIndex.load(std::memory_order_relaxed);\n   auto index = this->headIndex.load(std::memory_order_relaxed);\n   Block* block = nullptr;\n   assert(index == tail || details::circular_less_than(index, tail));\n   bool forceFreeLastBlock = index != tail;  // If we enter the loop, then the last (tail) block will not be freed\n   while (index != tail) {\n    if ((index & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 || block == nullptr) {\n     if (block != nullptr) {\n      // Free the old block\n      this->parent->add_block_to_free_list(block);\n     }\n     \n     block = get_block_index_entry_for_index(index)->value.load(std::memory_order_relaxed);\n    }\n    \n    ((*block)[index])->~T();\n    ++index;\n   }\n   // Even if the queue is empty, there's still one block that's not on the free list\n   // (unless the head index reached the end of it, in which case the tail will be poised\n   // to create a new block).\n   if (this->tailBlock != nullptr && (forceFreeLastBlock || (tail & static_cast<index_t>(BLOCK_SIZE - 1)) != 0)) {\n    this->parent->add_block_to_free_list(this->tailBlock);\n   }\n   \n   // Destroy block index\n   auto localBlockIndex = blockIndex.load(std::memory_order_relaxed);\n   if (localBlockIndex != nullptr) {\n    for (size_t i = 0; i != localBlockIndex->capacity; ++i) {\n     localBlockIndex->index[i]->~BlockIndexEntry();\n    }\n    do {\n     auto prev = localBlockIndex->prev;\n     localBlockIndex->~BlockIndexHeader();\n     (Traits::free)(localBlockIndex);\n     localBlockIndex = prev;\n    } while (localBlockIndex != nullptr);\n   }\n  }\n  \n  template<AllocationMode allocMode, typename U>\n  inline bool enqueue(U&& element)\n  {\n   index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n   index_t newTailIndex = 1 + currentTailIndex;\n   if ((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n    // We reached the end of a block, start a new one\n    auto head = this->headIndex.load(std::memory_order_relaxed);\n    assert(!details::circular_less_than<index_t>(currentTailIndex, head));\n    if (!details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) {\n     return false;\n    }\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n    debug::DebugLock lock(mutex);\n#endif\n    // Find out where we'll be inserting this block in the block index\n    BlockIndexEntry* idxEntry;\n    if (!insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) {\n     return false;\n    }\n    \n    // Get ahold of a new block\n    auto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n    if (newBlock == nullptr) {\n     rewind_block_index_tail();\n     idxEntry->value.store(nullptr, std::memory_order_relaxed);\n     return false;\n    }\n#if MCDBGQ_TRACKMEM\n    newBlock->owner = this;\n#endif\n    newBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>();\n    \n    if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward<U>(element)))) {\n     // May throw, try to insert now before we publish the fact that we have this new block\n     MOODYCAMEL_TRY {\n      new ((*newBlock)[currentTailIndex]) T(std::forward<U>(element));\n     }\n     MOODYCAMEL_CATCH (...) {\n      rewind_block_index_tail();\n      idxEntry->value.store(nullptr, std::memory_order_relaxed);\n      this->parent->add_block_to_free_list(newBlock);\n      MOODYCAMEL_RETHROW;\n     }\n    }\n    \n    // Insert the new block into the index\n    idxEntry->value.store(newBlock, std::memory_order_relaxed);\n    \n    this->tailBlock = newBlock;\n    \n    if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward<U>(element)))) {\n     this->tailIndex.store(newTailIndex, std::memory_order_release);\n     return true;\n    }\n   }\n   \n   // Enqueue\n   new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n   \n   this->tailIndex.store(newTailIndex, std::memory_order_release);\n   return true;\n  }\n  \n  template<typename U>\n  bool dequeue(U& element)\n  {\n   // See ExplicitProducer::dequeue for rationale and explanation\n   index_t tail = this->tailIndex.load(std::memory_order_relaxed);\n   index_t overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n   if (details::circular_less_than<index_t>(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) {\n    std::atomic_thread_fence(std::memory_order_acquire);\n    \n    index_t myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed);\n    tail = this->tailIndex.load(std::memory_order_acquire);\n    if ((details::likely)(details::circular_less_than<index_t>(myDequeueCount - overcommit, tail))) {\n     index_t index = this->headIndex.fetch_add(1, std::memory_order_acq_rel);\n     \n     // Determine which block the element is in\n     auto entry = get_block_index_entry_for_index(index);\n     \n     // Dequeue\n     auto block = entry->value.load(std::memory_order_relaxed);\n     auto& el = *((*block)[index]);\n     \n     if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n      // Note: Acquiring the mutex with every dequeue instead of only when a block\n      // is released is very sub-optimal, but it is, after all, purely debug code.\n      debug::DebugLock lock(producer->mutex);\n#endif\n      struct Guard {\n       Block* block;\n       index_t index;\n       BlockIndexEntry* entry;\n       ConcurrentQueue* parent;\n       \n       ~Guard()\n       {\n        (*block)[index]->~T();\n        if (block->ConcurrentQueue::Block::template set_empty<implicit_context>(index)) {\n         entry->value.store(nullptr, std::memory_order_relaxed);\n         parent->add_block_to_free_list(block);\n        }\n       }\n      } guard = { block, index, entry, this->parent };\n      \n      element = std::move(el);\n     }\n     else {\n      element = std::move(el);\n      el.~T();\n     \n      if (block->ConcurrentQueue::Block::template set_empty<implicit_context>(index)) {\n       {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n        debug::DebugLock lock(mutex);\n#endif\n        // Add the block back into the global free pool (and remove from block index)\n        entry->value.store(nullptr, std::memory_order_relaxed);\n       }\n       this->parent->add_block_to_free_list(block);  // releases the above store\n      }\n     }\n     \n     return true;\n    }\n    else {\n     this->dequeueOvercommit.fetch_add(1, std::memory_order_release);\n    }\n   }\n  \n   return false;\n  }\n  \n  template<AllocationMode allocMode, typename It>\n  bool enqueue_bulk(It itemFirst, size_t count)\n  {\n   // First, we need to make sure we have enough room to enqueue all of the elements;\n   // this means pre-allocating blocks and putting them in the block index (but only if\n   // all the allocations succeeded).\n   \n   // Note that the tailBlock we start off with may not be owned by us any more;\n   // this happens if it was filled up exactly to the top (setting tailIndex to\n   // the first index of the next block which is not yet allocated), then dequeued\n   // completely (putting it on the free list) before we enqueue again.\n   \n   index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n   auto startBlock = this->tailBlock;\n   Block* firstAllocatedBlock = nullptr;\n   auto endBlock = this->tailBlock;\n   \n   // Figure out how many blocks we'll need to allocate, and do so\n   size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));\n   index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n   if (blockBaseDiff > 0) {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n    debug::DebugLock lock(mutex);\n#endif\n    do {\n     blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n     currentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n     \n     // Find out where we'll be inserting this block in the block index\n     BlockIndexEntry* idxEntry = nullptr;  // initialization here unnecessary but compiler can't always tell\n     Block* newBlock;\n     bool indexInserted = false;\n     auto head = this->headIndex.load(std::memory_order_relaxed);\n     assert(!details::circular_less_than<index_t>(currentTailIndex, head));\n     bool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));\n     if (full || !(indexInserted = insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) || (newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>()) == nullptr) {\n      // Index allocation or block allocation failed; revert any other allocations\n      // and index insertions done so far for this operation\n      if (indexInserted) {\n       rewind_block_index_tail();\n       idxEntry->value.store(nullptr, std::memory_order_relaxed);\n      }\n      currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n      for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {\n       currentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n       idxEntry = get_block_index_entry_for_index(currentTailIndex);\n       idxEntry->value.store(nullptr, std::memory_order_relaxed);\n       rewind_block_index_tail();\n      }\n      this->parent->add_blocks_to_free_list(firstAllocatedBlock);\n      this->tailBlock = startBlock;\n      \n      return false;\n     }\n     \n#if MCDBGQ_TRACKMEM\n     newBlock->owner = this;\n#endif\n     newBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>();\n     newBlock->next = nullptr;\n     \n     // Insert the new block into the index\n     idxEntry->value.store(newBlock, std::memory_order_relaxed);\n     \n     // Store the chain of blocks so that we can undo if later allocations fail,\n     // and so that we can find the blocks when we do the actual enqueueing\n     if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr) {\n      assert(this->tailBlock != nullptr);\n      this->tailBlock->next = newBlock;\n     }\n     this->tailBlock = newBlock;\n     endBlock = newBlock;\n     firstAllocatedBlock = firstAllocatedBlock == nullptr ? newBlock : firstAllocatedBlock;\n    } while (blockBaseDiff > 0);\n   }\n   \n   // Enqueue, one block at a time\n   index_t newTailIndex = startTailIndex + static_cast<index_t>(count);\n   currentTailIndex = startTailIndex;\n   this->tailBlock = startBlock;\n   assert((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0);\n   if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) {\n    this->tailBlock = firstAllocatedBlock;\n   }\n   while (true) {\n    auto stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n    if (details::circular_less_than<index_t>(newTailIndex, stopIndex)) {\n     stopIndex = newTailIndex;\n    }\n    if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) {\n     while (currentTailIndex != stopIndex) {\n      new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++);\n     }\n    }\n    else {\n     MOODYCAMEL_TRY {\n      while (currentTailIndex != stopIndex) {\n       new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst));\n       ++currentTailIndex;\n       ++itemFirst;\n      }\n     }\n     MOODYCAMEL_CATCH (...) {\n      auto constructedStopIndex = currentTailIndex;\n      auto lastBlockEnqueued = this->tailBlock;\n      \n      if (!details::is_trivially_destructible<T>::value) {\n       auto block = startBlock;\n       if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n        block = firstAllocatedBlock;\n       }\n       currentTailIndex = startTailIndex;\n       while (true) {\n        stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n        if (details::circular_less_than<index_t>(constructedStopIndex, stopIndex)) {\n         stopIndex = constructedStopIndex;\n        }\n        while (currentTailIndex != stopIndex) {\n         (*block)[currentTailIndex++]->~T();\n        }\n        if (block == lastBlockEnqueued) {\n         break;\n        }\n        block = block->next;\n       }\n      }\n      \n      currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n      for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {\n       currentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n       auto idxEntry = get_block_index_entry_for_index(currentTailIndex);\n       idxEntry->value.store(nullptr, std::memory_order_relaxed);\n       rewind_block_index_tail();\n      }\n      this->parent->add_blocks_to_free_list(firstAllocatedBlock);\n      this->tailBlock = startBlock;\n      MOODYCAMEL_RETHROW;\n     }\n    }\n    \n    if (this->tailBlock == endBlock) {\n     assert(currentTailIndex == newTailIndex);\n     break;\n    }\n    this->tailBlock = this->tailBlock->next;\n   }\n   this->tailIndex.store(newTailIndex, std::memory_order_release);\n   return true;\n  }\n  \n  template<typename It>\n  size_t dequeue_bulk(It& itemFirst, size_t max)\n  {\n   auto tail = this->tailIndex.load(std::memory_order_relaxed);\n   auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n   auto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));\n   if (details::circular_less_than<size_t>(0, desiredCount)) {\n    desiredCount = desiredCount < max ? desiredCount : max;\n    std::atomic_thread_fence(std::memory_order_acquire);\n    \n    auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);\n    \n    tail = this->tailIndex.load(std::memory_order_acquire);\n    auto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));\n    if (details::circular_less_than<size_t>(0, actualCount)) {\n     actualCount = desiredCount < actualCount ? desiredCount : actualCount;\n     if (actualCount < desiredCount) {\n      this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);\n     }\n     \n     // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this\n     // will never exceed tail.\n     auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);\n     \n     // Iterate the blocks and dequeue\n     auto index = firstIndex;\n     BlockIndexHeader* localBlockIndex;\n     auto indexIndex = get_block_index_index_for_index(index, localBlockIndex);\n     do {\n      auto blockStartIndex = index;\n      auto endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n      endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n      \n      auto entry = localBlockIndex->index[indexIndex];\n      auto block = entry->value.load(std::memory_order_relaxed);\n      if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {\n       while (index != endIndex) {\n        auto& el = *((*block)[index]);\n        *itemFirst++ = std::move(el);\n        el.~T();\n        ++index;\n       }\n      }\n      else {\n       MOODYCAMEL_TRY {\n        while (index != endIndex) {\n         auto& el = *((*block)[index]);\n         *itemFirst = std::move(el);\n         ++itemFirst;\n         el.~T();\n         ++index;\n        }\n       }\n       MOODYCAMEL_CATCH (...) {\n        do {\n         entry = localBlockIndex->index[indexIndex];\n         block = entry->value.load(std::memory_order_relaxed);\n         while (index != endIndex) {\n          (*block)[index++]->~T();\n         }\n         \n         if (block->ConcurrentQueue::Block::template set_many_empty<implicit_context>(blockStartIndex, static_cast<size_t>(endIndex - blockStartIndex))) {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n          debug::DebugLock lock(mutex);\n#endif\n          entry->value.store(nullptr, std::memory_order_relaxed);\n          this->parent->add_block_to_free_list(block);\n         }\n         indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1);\n         \n         blockStartIndex = index;\n         endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n         endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n        } while (index != firstIndex + actualCount);\n        \n        MOODYCAMEL_RETHROW;\n       }\n      }\n      if (block->ConcurrentQueue::Block::template set_many_empty<implicit_context>(blockStartIndex, static_cast<size_t>(endIndex - blockStartIndex))) {\n       {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n        debug::DebugLock lock(mutex);\n#endif\n        // Note that the set_many_empty above did a release, meaning that anybody who acquires the block\n        // we're about to free can use it safely since our writes (and reads!) will have happened-before then.\n        entry->value.store(nullptr, std::memory_order_relaxed);\n       }\n       this->parent->add_block_to_free_list(block);  // releases the above store\n      }\n      indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1);\n     } while (index != firstIndex + actualCount);\n     \n     return actualCount;\n    }\n    else {\n     this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release);\n    }\n   }\n   \n   return 0;\n  }\n  \n private:\n  // The block size must be > 1, so any number with the low bit set is an invalid block base index\n  static const index_t INVALID_BLOCK_BASE = 1;\n  \n  struct BlockIndexEntry\n  {\n   std::atomic<index_t> key;\n   std::atomic<Block*> value;\n  };\n  \n  struct BlockIndexHeader\n  {\n   size_t capacity;\n   std::atomic<size_t> tail;\n   BlockIndexEntry* entries;\n   BlockIndexEntry** index;\n   BlockIndexHeader* prev;\n  };\n  \n  template<AllocationMode allocMode>\n  inline bool insert_block_index_entry(BlockIndexEntry*& idxEntry, index_t blockStartIndex)\n  {\n   auto localBlockIndex = blockIndex.load(std::memory_order_relaxed);  // We're the only writer thread, relaxed is OK\n   if (localBlockIndex == nullptr) {\n    return false;  // this can happen if new_block_index failed in the constructor\n   }\n   auto newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1);\n   idxEntry = localBlockIndex->index[newTail];\n   if (idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE ||\n    idxEntry->value.load(std::memory_order_relaxed) == nullptr) {\n    \n    idxEntry->key.store(blockStartIndex, std::memory_order_relaxed);\n    localBlockIndex->tail.store(newTail, std::memory_order_release);\n    return true;\n   }\n   \n   // No room in the old block index, try to allocate another one!\n   if (allocMode == CannotAlloc || !new_block_index()) {\n    return false;\n   }\n   localBlockIndex = blockIndex.load(std::memory_order_relaxed);\n   newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1);\n   idxEntry = localBlockIndex->index[newTail];\n   assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE);\n   idxEntry->key.store(blockStartIndex, std::memory_order_relaxed);\n   localBlockIndex->tail.store(newTail, std::memory_order_release);\n   return true;\n  }\n  \n  inline void rewind_block_index_tail()\n  {\n   auto localBlockIndex = blockIndex.load(std::memory_order_relaxed);\n   localBlockIndex->tail.store((localBlockIndex->tail.load(std::memory_order_relaxed) - 1) & (localBlockIndex->capacity - 1), std::memory_order_relaxed);\n  }\n  \n  inline BlockIndexEntry* get_block_index_entry_for_index(index_t index) const\n  {\n   BlockIndexHeader* localBlockIndex;\n   auto idx = get_block_index_index_for_index(index, localBlockIndex);\n   return localBlockIndex->index[idx];\n  }\n  \n  inline size_t get_block_index_index_for_index(index_t index, BlockIndexHeader*& localBlockIndex) const\n  {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n   debug::DebugLock lock(mutex);\n#endif\n   index &= ~static_cast<index_t>(BLOCK_SIZE - 1);\n   localBlockIndex = blockIndex.load(std::memory_order_acquire);\n   auto tail = localBlockIndex->tail.load(std::memory_order_acquire);\n   auto tailBase = localBlockIndex->index[tail]->key.load(std::memory_order_relaxed);\n   assert(tailBase != INVALID_BLOCK_BASE);\n   // Note: Must use division instead of shift because the index may wrap around, causing a negative\n   // offset, whose negativity we want to preserve\n   auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(index - tailBase) / BLOCK_SIZE);\n   size_t idx = (tail + offset) & (localBlockIndex->capacity - 1);\n   assert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr);\n   return idx;\n  }\n  \n  bool new_block_index()\n  {\n   auto prev = blockIndex.load(std::memory_order_relaxed);\n   size_t prevCapacity = prev == nullptr ? 0 : prev->capacity;\n   auto entryCount = prev == nullptr ? nextBlockIndexCapacity : prevCapacity;\n   auto raw = static_cast<char*>((Traits::malloc)(\n    sizeof(BlockIndexHeader) +\n    std::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * entryCount +\n    std::alignment_of<BlockIndexEntry*>::value - 1 + sizeof(BlockIndexEntry*) * nextBlockIndexCapacity));\n   if (raw == nullptr) {\n    return false;\n   }\n   \n   auto header = new (raw) BlockIndexHeader;\n   auto entries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(raw + sizeof(BlockIndexHeader)));\n   auto index = reinterpret_cast<BlockIndexEntry**>(details::align_for<BlockIndexEntry*>(reinterpret_cast<char*>(entries) + sizeof(BlockIndexEntry) * entryCount));\n   if (prev != nullptr) {\n    auto prevTail = prev->tail.load(std::memory_order_relaxed);\n    auto prevPos = prevTail;\n    size_t i = 0;\n    do {\n     prevPos = (prevPos + 1) & (prev->capacity - 1);\n     index[i++] = prev->index[prevPos];\n    } while (prevPos != prevTail);\n    assert(i == prevCapacity);\n   }\n   for (size_t i = 0; i != entryCount; ++i) {\n    new (entries + i) BlockIndexEntry;\n    entries[i].key.store(INVALID_BLOCK_BASE, std::memory_order_relaxed);\n    index[prevCapacity + i] = entries + i;\n   }\n   header->prev = prev;\n   header->entries = entries;\n   header->index = index;\n   header->capacity = nextBlockIndexCapacity;\n   header->tail.store((prevCapacity - 1) & (nextBlockIndexCapacity - 1), std::memory_order_relaxed);\n   \n   blockIndex.store(header, std::memory_order_release);\n   \n   nextBlockIndexCapacity <<= 1;\n   \n   return true;\n  }\n  \n private:\n  size_t nextBlockIndexCapacity;\n  std::atomic<BlockIndexHeader*> blockIndex;\n\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n public:\n  details::ThreadExitListener threadExitListener;\n private:\n#endif\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n public:\n  ImplicitProducer* nextImplicitProducer;\n private:\n#endif\n\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n  mutable debug::DebugMutex mutex;\n#endif\n#if MCDBGQ_TRACKMEM\n  friend struct MemStats;\n#endif\n };\n \n \n //////////////////////////////////\n // Block pool manipulation\n //////////////////////////////////\n \n void populate_initial_block_list(size_t blockCount)\n {\n  initialBlockPoolSize = blockCount;\n  if (initialBlockPoolSize == 0) {\n   initialBlockPool = nullptr;\n   return;\n  }\n  \n  initialBlockPool = create_array<Block>(blockCount);\n  if (initialBlockPool == nullptr) {\n   initialBlockPoolSize = 0;\n  }\n  for (size_t i = 0; i < initialBlockPoolSize; ++i) {\n   initialBlockPool[i].dynamicallyAllocated = false;\n  }\n }\n \n inline Block* try_get_block_from_initial_pool()\n {\n  if (initialBlockPoolIndex.load(std::memory_order_relaxed) >= initialBlockPoolSize) {\n   return nullptr;\n  }\n  \n  auto index = initialBlockPoolIndex.fetch_add(1, std::memory_order_relaxed);\n  \n  return index < initialBlockPoolSize ? (initialBlockPool + index) : nullptr;\n }\n \n inline void add_block_to_free_list(Block* block)\n {\n#if MCDBGQ_TRACKMEM\n  block->owner = nullptr;\n#endif\n  freeList.add(block);\n }\n \n inline void add_blocks_to_free_list(Block* block)\n {\n  while (block != nullptr) {\n   auto next = block->next;\n   add_block_to_free_list(block);\n   block = next;\n  }\n }\n \n inline Block* try_get_block_from_free_list()\n {\n  return freeList.try_get();\n }\n \n // Gets a free block from one of the memory pools, or allocates a new one (if applicable)\n template<AllocationMode canAlloc>\n Block* requisition_block()\n {\n  auto block = try_get_block_from_initial_pool();\n  if (block != nullptr) {\n   return block;\n  }\n  \n  block = try_get_block_from_free_list();\n  if (block != nullptr) {\n   return block;\n  }\n  \n  if (canAlloc == CanAlloc) {\n   return create<Block>();\n  }\n  \n  return nullptr;\n }\n \n\n#if MCDBGQ_TRACKMEM\n public:\n  struct MemStats {\n   size_t allocatedBlocks;\n   size_t usedBlocks;\n   size_t freeBlocks;\n   size_t ownedBlocksExplicit;\n   size_t ownedBlocksImplicit;\n   size_t implicitProducers;\n   size_t explicitProducers;\n   size_t elementsEnqueued;\n   size_t blockClassBytes;\n   size_t queueClassBytes;\n   size_t implicitBlockIndexBytes;\n   size_t explicitBlockIndexBytes;\n   \n   friend class ConcurrentQueue;\n   \n  private:\n   static MemStats getFor(ConcurrentQueue* q)\n   {\n    MemStats stats = { 0 };\n    \n    stats.elementsEnqueued = q->size_approx();\n   \n    auto block = q->freeList.head_unsafe();\n    while (block != nullptr) {\n     ++stats.allocatedBlocks;\n     ++stats.freeBlocks;\n     block = block->freeListNext.load(std::memory_order_relaxed);\n    }\n    \n    for (auto ptr = q->producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n     bool implicit = dynamic_cast<ImplicitProducer*>(ptr) != nullptr;\n     stats.implicitProducers += implicit ? 1 : 0;\n     stats.explicitProducers += implicit ? 0 : 1;\n     \n     if (implicit) {\n      auto prod = static_cast<ImplicitProducer*>(ptr);\n      stats.queueClassBytes += sizeof(ImplicitProducer);\n      auto head = prod->headIndex.load(std::memory_order_relaxed);\n      auto tail = prod->tailIndex.load(std::memory_order_relaxed);\n      auto hash = prod->blockIndex.load(std::memory_order_relaxed);\n      if (hash != nullptr) {\n       for (size_t i = 0; i != hash->capacity; ++i) {\n        if (hash->index[i]->key.load(std::memory_order_relaxed) != ImplicitProducer::INVALID_BLOCK_BASE && hash->index[i]->value.load(std::memory_order_relaxed) != nullptr) {\n         ++stats.allocatedBlocks;\n         ++stats.ownedBlocksImplicit;\n        }\n       }\n       stats.implicitBlockIndexBytes += hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry);\n       for (; hash != nullptr; hash = hash->prev) {\n        stats.implicitBlockIndexBytes += sizeof(typename ImplicitProducer::BlockIndexHeader) + hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry*);\n       }\n      }\n      for (; details::circular_less_than<index_t>(head, tail); head += BLOCK_SIZE) {\n       //auto block = prod->get_block_index_entry_for_index(head);\n       ++stats.usedBlocks;\n      }\n     }\n     else {\n      auto prod = static_cast<ExplicitProducer*>(ptr);\n      stats.queueClassBytes += sizeof(ExplicitProducer);\n      auto tailBlock = prod->tailBlock;\n      bool wasNonEmpty = false;\n      if (tailBlock != nullptr) {\n       auto block = tailBlock;\n       do {\n        ++stats.allocatedBlocks;\n        if (!block->ConcurrentQueue::Block::template is_empty<explicit_context>() || wasNonEmpty) {\n         ++stats.usedBlocks;\n         wasNonEmpty = wasNonEmpty || block != tailBlock;\n        }\n        ++stats.ownedBlocksExplicit;\n        block = block->next;\n       } while (block != tailBlock);\n      }\n      auto index = prod->blockIndex.load(std::memory_order_relaxed);\n      while (index != nullptr) {\n       stats.explicitBlockIndexBytes += sizeof(typename ExplicitProducer::BlockIndexHeader) + index->size * sizeof(typename ExplicitProducer::BlockIndexEntry);\n       index = static_cast<typename ExplicitProducer::BlockIndexHeader*>(index->prev);\n      }\n     }\n    }\n    \n    auto freeOnInitialPool = q->initialBlockPoolIndex.load(std::memory_order_relaxed) >= q->initialBlockPoolSize ? 0 : q->initialBlockPoolSize - q->initialBlockPoolIndex.load(std::memory_order_relaxed);\n    stats.allocatedBlocks += freeOnInitialPool;\n    stats.freeBlocks += freeOnInitialPool;\n    \n    stats.blockClassBytes = sizeof(Block) * stats.allocatedBlocks;\n    stats.queueClassBytes += sizeof(ConcurrentQueue);\n    \n    return stats;\n   }\n  };\n  \n  // For debugging only. Not thread-safe.\n  MemStats getMemStats()\n  {\n   return MemStats::getFor(this);\n  }\n private:\n  friend struct MemStats;\n#endif\n \n \n //////////////////////////////////\n // Producer list manipulation\n ////////////////////////////////// \n \n ProducerBase* recycle_or_create_producer(bool isExplicit)\n {\n  bool recycled;\n  return recycle_or_create_producer(isExplicit, recycled);\n }\n \n ProducerBase* recycle_or_create_producer(bool isExplicit, bool& recycled)\n {\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n  debug::DebugLock lock(implicitProdMutex);\n#endif\n  // Try to re-use one first\n  for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n   if (ptr->inactive.load(std::memory_order_relaxed) && ptr->isExplicit == isExplicit) {\n    bool expected = true;\n    if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) {\n     // We caught one! It's been marked as activated, the caller can have it\n     recycled = true;\n     return ptr;\n    }\n   }\n  }\n  \n  recycled = false;\n  return add_producer(isExplicit ? static_cast<ProducerBase*>(create<ExplicitProducer>(this)) : create<ImplicitProducer>(this));\n }\n \n ProducerBase* add_producer(ProducerBase* producer)\n {\n  // Handle failed memory allocation\n  if (producer == nullptr) {\n   return nullptr;\n  }\n  \n  producerCount.fetch_add(1, std::memory_order_relaxed);\n  \n  // Add it to the lock-free list\n  auto prevTail = producerListTail.load(std::memory_order_relaxed);\n  do {\n   producer->next = prevTail;\n  } while (!producerListTail.compare_exchange_weak(prevTail, producer, std::memory_order_release, std::memory_order_relaxed));\n  \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n  if (producer->isExplicit) {\n   auto prevTailExplicit = explicitProducers.load(std::memory_order_relaxed);\n   do {\n    static_cast<ExplicitProducer*>(producer)->nextExplicitProducer = prevTailExplicit;\n   } while (!explicitProducers.compare_exchange_weak(prevTailExplicit, static_cast<ExplicitProducer*>(producer), std::memory_order_release, std::memory_order_relaxed));\n  }\n  else {\n   auto prevTailImplicit = implicitProducers.load(std::memory_order_relaxed);\n   do {\n    static_cast<ImplicitProducer*>(producer)->nextImplicitProducer = prevTailImplicit;\n   } while (!implicitProducers.compare_exchange_weak(prevTailImplicit, static_cast<ImplicitProducer*>(producer), std::memory_order_release, std::memory_order_relaxed));\n  }\n#endif\n  \n  return producer;\n }\n \n void reown_producers()\n {\n  // After another instance is moved-into/swapped-with this one, all the\n  // producers we stole still think their parents are the other queue.\n  // So fix them up!\n  for (auto ptr = producerListTail.load(std::memory_order_relaxed); ptr != nullptr; ptr = ptr->next_prod()) {\n   ptr->parent = this;\n  }\n }\n \n \n //////////////////////////////////\n // Implicit producer hash\n //////////////////////////////////\n \n struct ImplicitProducerKVP\n {\n  std::atomic<details::thread_id_t> key;\n  ImplicitProducer* value;  // No need for atomicity since it's only read by the thread that sets it in the first place\n  \n  ImplicitProducerKVP() : value(nullptr) { }\n  \n  ImplicitProducerKVP(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT\n  {\n   key.store(other.key.load(std::memory_order_relaxed), std::memory_order_relaxed);\n   value = other.value;\n  }\n  \n  inline ImplicitProducerKVP& operator=(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT\n  {\n   swap(other);\n   return *this;\n  }\n  \n  inline void swap(ImplicitProducerKVP& other) MOODYCAMEL_NOEXCEPT\n  {\n   if (this != &other) {\n    details::swap_relaxed(key, other.key);\n    std::swap(value, other.value);\n   }\n  }\n };\n \n template<typename XT, typename XTraits>\n friend void moodycamel::swap(typename ConcurrentQueue<XT, XTraits>::ImplicitProducerKVP&, typename ConcurrentQueue<XT, XTraits>::ImplicitProducerKVP&) MOODYCAMEL_NOEXCEPT;\n \n struct ImplicitProducerHash\n {\n  size_t capacity;\n  ImplicitProducerKVP* entries;\n  ImplicitProducerHash* prev;\n };\n \n inline void populate_initial_implicit_producer_hash()\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return;\n  \n  implicitProducerHashCount.store(0, std::memory_order_relaxed);\n  auto hash = &initialImplicitProducerHash;\n  hash->capacity = INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;\n  hash->entries = &initialImplicitProducerHashEntries[0];\n  for (size_t i = 0; i != INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; ++i) {\n   initialImplicitProducerHashEntries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed);\n  }\n  hash->prev = nullptr;\n  implicitProducerHash.store(hash, std::memory_order_relaxed);\n }\n \n void swap_implicit_producer_hashes(ConcurrentQueue& other)\n {\n  if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return;\n  \n  // Swap (assumes our implicit producer hash is initialized)\n  initialImplicitProducerHashEntries.swap(other.initialImplicitProducerHashEntries);\n  initialImplicitProducerHash.entries = &initialImplicitProducerHashEntries[0];\n  other.initialImplicitProducerHash.entries = &other.initialImplicitProducerHashEntries[0];\n  \n  details::swap_relaxed(implicitProducerHashCount, other.implicitProducerHashCount);\n  \n  details::swap_relaxed(implicitProducerHash, other.implicitProducerHash);\n  if (implicitProducerHash.load(std::memory_order_relaxed) == &other.initialImplicitProducerHash) {\n   implicitProducerHash.store(&initialImplicitProducerHash, std::memory_order_relaxed);\n  }\n  else {\n   ImplicitProducerHash* hash;\n   for (hash = implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &other.initialImplicitProducerHash; hash = hash->prev) {\n    continue;\n   }\n   hash->prev = &initialImplicitProducerHash;\n  }\n  if (other.implicitProducerHash.load(std::memory_order_relaxed) == &initialImplicitProducerHash) {\n   other.implicitProducerHash.store(&other.initialImplicitProducerHash, std::memory_order_relaxed);\n  }\n  else {\n   ImplicitProducerHash* hash;\n   for (hash = other.implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &initialImplicitProducerHash; hash = hash->prev) {\n    continue;\n   }\n   hash->prev = &other.initialImplicitProducerHash;\n  }\n }\n \n // Only fails (returns nullptr) if memory allocation fails\n ImplicitProducer* get_or_add_implicit_producer()\n {\n  // Note that since the data is essentially thread-local (key is thread ID),\n  // there's a reduced need for fences (memory ordering is already consistent\n  // for any individual thread), except for the current table itself.\n  \n  // Start by looking for the thread ID in the current and all previous hash tables.\n  // If it's not found, it must not be in there yet, since this same thread would\n  // have added it previously to one of the tables that we traversed.\n  \n  // Code and algorithm adapted from http://preshing.com/20130605/the-worlds-simplest-lock-free-hash-table\n  \n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n  debug::DebugLock lock(implicitProdMutex);\n#endif\n  \n  auto id = details::thread_id();\n  auto hashedId = details::hash_thread_id(id);\n  \n  auto mainHash = implicitProducerHash.load(std::memory_order_acquire);\n  for (auto hash = mainHash; hash != nullptr; hash = hash->prev) {\n   // Look for the id in this hash\n   auto index = hashedId;\n   while (true) {  // Not an infinite loop because at least one slot is free in the hash table\n    index &= hash->capacity - 1;\n    \n    auto probedKey = hash->entries[index].key.load(std::memory_order_relaxed);\n    if (probedKey == id) {\n     // Found it! If we had to search several hashes deep, though, we should lazily add it\n     // to the current main hash table to avoid the extended search next time.\n     // Note there's guaranteed to be room in the current hash table since every subsequent\n     // table implicitly reserves space for all previous tables (there's only one\n     // implicitProducerHashCount).\n     auto value = hash->entries[index].value;\n     if (hash != mainHash) {\n      index = hashedId;\n      while (true) {\n       index &= mainHash->capacity - 1;\n       probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed);\n       auto empty = details::invalid_thread_id;\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n       auto reusable = details::invalid_thread_id2;\n       if ((probedKey == empty    && mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_relaxed, std::memory_order_relaxed)) ||\n        (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) {\n#else\n       if ((probedKey == empty    && mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_relaxed, std::memory_order_relaxed))) {\n#endif\n        mainHash->entries[index].value = value;\n        break;\n       }\n       ++index;\n      }\n     }\n     \n     return value;\n    }\n    if (probedKey == details::invalid_thread_id) {\n     break;  // Not in this hash table\n    }\n    ++index;\n   }\n  }\n  \n  // Insert!\n  auto newCount = 1 + implicitProducerHashCount.fetch_add(1, std::memory_order_relaxed);\n  while (true) {\n   if (newCount >= (mainHash->capacity >> 1) && !implicitProducerHashResizeInProgress.test_and_set(std::memory_order_acquire)) {\n    // We've acquired the resize lock, try to allocate a bigger hash table.\n    // Note the acquire fence synchronizes with the release fence at the end of this block, and hence when\n    // we reload implicitProducerHash it must be the most recent version (it only gets changed within this\n    // locked block).\n    mainHash = implicitProducerHash.load(std::memory_order_acquire);\n    if (newCount >= (mainHash->capacity >> 1)) {\n     auto newCapacity = mainHash->capacity << 1;\n     while (newCount >= (newCapacity >> 1)) {\n      newCapacity <<= 1;\n     }\n     auto raw = static_cast<char*>((Traits::malloc)(sizeof(ImplicitProducerHash) + std::alignment_of<ImplicitProducerKVP>::value - 1 + sizeof(ImplicitProducerKVP) * newCapacity));\n     if (raw == nullptr) {\n      // Allocation failed\n      implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);\n      implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n      return nullptr;\n     }\n     \n     auto newHash = new (raw) ImplicitProducerHash;\n     newHash->capacity = newCapacity;\n     newHash->entries = reinterpret_cast<ImplicitProducerKVP*>(details::align_for<ImplicitProducerKVP>(raw + sizeof(ImplicitProducerHash)));\n     for (size_t i = 0; i != newCapacity; ++i) {\n      new (newHash->entries + i) ImplicitProducerKVP;\n      newHash->entries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed);\n     }\n     newHash->prev = mainHash;\n     implicitProducerHash.store(newHash, std::memory_order_release);\n     implicitProducerHashResizeInProgress.clear(std::memory_order_release);\n     mainHash = newHash;\n    }\n    else {\n     implicitProducerHashResizeInProgress.clear(std::memory_order_release);\n    }\n   }\n   \n   // If it's < three-quarters full, add to the old one anyway so that we don't have to wait for the next table\n   // to finish being allocated by another thread (and if we just finished allocating above, the condition will\n   // always be true)\n   if (newCount < (mainHash->capacity >> 1) + (mainHash->capacity >> 2)) {\n    bool recycled;\n    auto producer = static_cast<ImplicitProducer*>(recycle_or_create_producer(false, recycled));\n    if (producer == nullptr) {\n     implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);\n     return nullptr;\n    }\n    if (recycled) {\n     implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);\n    }\n    \n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n    producer->threadExitListener.callback = &ConcurrentQueue::implicit_producer_thread_exited_callback;\n    producer->threadExitListener.userData = producer;\n    details::ThreadExitNotifier::subscribe(&producer->threadExitListener);\n#endif\n    \n    auto index = hashedId;\n    while (true) {\n     index &= mainHash->capacity - 1;\n     auto probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed);\n     \n     auto empty = details::invalid_thread_id;\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n     auto reusable = details::invalid_thread_id2;\n     if ((probedKey == empty    && mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_relaxed, std::memory_order_relaxed)) ||\n      (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) {\n#else\n     if ((probedKey == empty    && mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_relaxed, std::memory_order_relaxed))) {\n#endif\n      mainHash->entries[index].value = producer;\n      break;\n     }\n     ++index;\n    }\n    return producer;\n   }\n   \n   // Hmm, the old hash is quite full and somebody else is busy allocating a new one.\n   // We need to wait for the allocating thread to finish (if it succeeds, we add, if not,\n   // we try to allocate ourselves).\n   mainHash = implicitProducerHash.load(std::memory_order_acquire);\n  }\n }\n \n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n void implicit_producer_thread_exited(ImplicitProducer* producer)\n {\n  // Remove from thread exit listeners\n  details::ThreadExitNotifier::unsubscribe(&producer->threadExitListener);\n  \n  // Remove from hash\n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n  debug::DebugLock lock(implicitProdMutex);\n#endif\n  auto hash = implicitProducerHash.load(std::memory_order_acquire);\n  assert(hash != nullptr);  // The thread exit listener is only registered if we were added to a hash in the first place\n  auto id = details::thread_id();\n  auto hashedId = details::hash_thread_id(id);\n  details::thread_id_t probedKey;\n  \n  // We need to traverse all the hashes just in case other threads aren't on the current one yet and are\n  // trying to add an entry thinking there's a free slot (because they reused a producer)\n  for (; hash != nullptr; hash = hash->prev) {\n   auto index = hashedId;\n   do {\n    index &= hash->capacity - 1;\n    probedKey = hash->entries[index].key.load(std::memory_order_relaxed);\n    if (probedKey == id) {\n     hash->entries[index].key.store(details::invalid_thread_id2, std::memory_order_release);\n     break;\n    }\n    ++index;\n   } while (probedKey != details::invalid_thread_id);  // Can happen if the hash has changed but we weren't put back in it yet, or if we weren't added to this hash in the first place\n  }\n  \n  // Mark the queue as being recyclable\n  producer->inactive.store(true, std::memory_order_release);\n }\n \n static void implicit_producer_thread_exited_callback(void* userData)\n {\n  auto producer = static_cast<ImplicitProducer*>(userData);\n  auto queue = producer->parent;\n  queue->implicit_producer_thread_exited(producer);\n }\n#endif\n \n //////////////////////////////////\n // Utility functions\n //////////////////////////////////\n \n template<typename U>\n static inline U* create_array(size_t count)\n {\n  assert(count > 0);\n  auto p = static_cast<U*>((Traits::malloc)(sizeof(U) * count));\n  if (p == nullptr) {\n   return nullptr;\n  }\n  \n  for (size_t i = 0; i != count; ++i) {\n   new (p + i) U();\n  }\n  return p;\n }\n \n template<typename U>\n static inline void destroy_array(U* p, size_t count)\n {\n  if (p != nullptr) {\n   assert(count > 0);\n   for (size_t i = count; i != 0; ) {\n    (p + --i)->~U();\n   }\n   (Traits::free)(p);\n  }\n }\n \n template<typename U>\n static inline U* create()\n {\n  auto p = (Traits::malloc)(sizeof(U));\n  return p != nullptr ? new (p) U : nullptr;\n }\n \n template<typename U, typename A1>\n static inline U* create(A1&& a1)\n {\n  auto p = (Traits::malloc)(sizeof(U));\n  return p != nullptr ? new (p) U(std::forward<A1>(a1)) : nullptr;\n }\n \n template<typename U>\n static inline void destroy(U* p)\n {\n  if (p != nullptr) {\n   p->~U();\n  }\n  (Traits::free)(p);\n }\n\nprivate:\n std::atomic<ProducerBase*> producerListTail;\n std::atomic<std::uint32_t> producerCount;\n \n std::atomic<size_t> initialBlockPoolIndex;\n Block* initialBlockPool;\n size_t initialBlockPoolSize;\n \n#if !MCDBGQ_USEDEBUGFREELIST\n FreeList<Block> freeList;\n#else\n debug::DebugFreeList<Block> freeList;\n#endif\n \n std::atomic<ImplicitProducerHash*> implicitProducerHash;\n std::atomic<size_t> implicitProducerHashCount;  // Number of slots logically used\n ImplicitProducerHash initialImplicitProducerHash;\n std::array<ImplicitProducerKVP, INITIAL_IMPLICIT_PRODUCER_HASH_SIZE> initialImplicitProducerHashEntries;\n std::atomic_flag implicitProducerHashResizeInProgress;\n \n std::atomic<std::uint32_t> nextExplicitConsumerId;\n std::atomic<std::uint32_t> globalExplicitConsumerOffset;\n \n#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n debug::DebugMutex implicitProdMutex;\n#endif\n \n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n std::atomic<ExplicitProducer*> explicitProducers;\n std::atomic<ImplicitProducer*> implicitProducers;\n#endif\n};\n\n\ntemplate<typename T, typename Traits>\nProducerToken::ProducerToken(ConcurrentQueue<T, Traits>& queue)\n : producer(queue.recycle_or_create_producer(true))\n{\n if (producer != nullptr) {\n  producer->token = this;\n }\n}\n\ntemplate<typename T, typename Traits>\nProducerToken::ProducerToken(BlockingConcurrentQueue<T, Traits>& queue)\n : producer(reinterpret_cast<ConcurrentQueue<T, Traits>*>(&queue)->recycle_or_create_producer(true))\n{\n if (producer != nullptr) {\n  producer->token = this;\n }\n}\n\ntemplate<typename T, typename Traits>\nConsumerToken::ConsumerToken(ConcurrentQueue<T, Traits>& queue)\n : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr)\n{\n initialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release);\n lastKnownGlobalOffset = -1;\n}\n\ntemplate<typename T, typename Traits>\nConsumerToken::ConsumerToken(BlockingConcurrentQueue<T, Traits>& queue)\n : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr)\n{\n initialOffset = reinterpret_cast<ConcurrentQueue<T, Traits>*>(&queue)->nextExplicitConsumerId.fetch_add(1, std::memory_order_release);\n lastKnownGlobalOffset = -1;\n}\n\ntemplate<typename T, typename Traits>\ninline void swap(ConcurrentQueue<T, Traits>& a, ConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT\n{\n a.swap(b);\n}\n\ninline void swap(ProducerToken& a, ProducerToken& b) MOODYCAMEL_NOEXCEPT\n{\n a.swap(b);\n}\n\ninline void swap(ConsumerToken& a, ConsumerToken& b) MOODYCAMEL_NOEXCEPT\n{\n a.swap(b);\n}\n\ntemplate<typename T, typename Traits>\ninline void swap(typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& a, typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT\n{\n a.swap(b);\n}\n\n}\n\n#if defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "libsrc/core/exception.cpp",
    "content": "#include \"exception.hpp\"\n#include \"utils.hpp\"\n\n#ifdef EMSCRIPTEN\n#include <iostream>\n#endif // EMSCRIPTEN\n\n// no backtrace on Emscripten\n// backtrace on Apple platforms with GNUC (does not define __GLIBC__)\n// backtrace on GNU/Linux with glibc\n// no backtrace with musl libc\n#if !defined(__EMSCRIPTEN__) && ( \\\n     (defined(__APPLE__) && defined(__GNUC__)) || \\\n     (defined(__GNUC__) && defined(__GLIBC__)) )\n#define NG_HAVE_BACKTRACE\n#endif\n\nnamespace ngcore\n{\n  Exception :: Exception(const std::string& s)\n    : m_what(s) {\n  #ifdef EMSCRIPTEN\n  std::cout << \"THROW Exception \" << s << std::endl;\n  #endif\n}\n  \n  Exception :: Exception(const char* s)\n    : m_what(s) {\n  #ifdef EMSCRIPTEN\n  std::cout << \"THROW Exception \" << s << std::endl;\n  #endif\n\n}\n\n\n  Exception :: Exception(std::string_view s1, std::string_view s2)\n    : Exception(std::string(s1)+std::string(s2))\n  { }\n\n  Exception :: Exception(std::string_view s1, std::string_view s2, std::string_view s3)\n    : Exception(std::string(s1)+std::string(s2)+std::string(s3))\n  { }\n\n\n  void Exception :: Throw (std::string_view s1)\n  {\n    throw Exception(std::string(s1));\n  }\n\n  void Exception :: Throw (std::string_view s1, std::string_view s2)\n  {\n    throw Exception(std::string(s1)+std::string(s2));\n  }\n    \n  void Exception :: Throw (std::string_view s1, std::string_view s2, std::string_view s3)\n  {\n    throw Exception(std::string(s1)+std::string(s2)+std::string(s3));\n  }\n  \n  \n  RangeException :: RangeException (// const std::string & where,\n                                    const char * where,\n                                    ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax) : Exception(\"\")\n  {\n    std::stringstream str;\n    str << where << \": index \" << ind << \" out of range [\" << imin << \",\" << imax << \")\\n\";\n    Append (str.str());\n    Append (GetBackTrace());\n  }\n  \n\n  void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax)\n  {\n    throw RangeException(s, ind, imin, imax);\n  }\n  \n  void ThrowException(const std::string & s)\n  {\n    throw Exception (s);\n  }\n  \n  void ThrowException(const char * s)\n  {\n    throw Exception (s);\n  }\n\n\n  void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b)\n  {\n    throw ngcore::Exception(std::string(s) + \", a=\"+ToString(a) + \", b=\"+ToString(b) + GetBackTrace());     \n  }\n  \n} // namespace ngcore\n\n\n// ********* STUFF FOR GETBACKTRACE ***************************\n#ifdef NG_HAVE_BACKTRACE\n\n#include <execinfo.h>\n#include <string.h>\n#include <errno.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <iostream>\n#include <dlfcn.h>\n#include <array>\n#include <memory>\n#include <cxxabi.h>\n#include <signal.h>\n#include <vector>\n\nnamespace ngcore\n{\n  namespace detail\n  {\n    static int exec(std::string cmd, std::string & out) {\n      std::array<char, 128> buffer;\n      FILE *pipe = popen(cmd.c_str(), \"r\");\n\n      if (!pipe)\n        throw std::runtime_error(\"popen() failed!\");\n\n      out = \"\";\n      while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)\n        out += buffer.data();\n\n      int error_code = pclose(pipe);\n      return error_code;\n    }\n\n#ifdef __APPLE__\n    // Split output line from backtrace_symbols to recover function name and offset\n    // then use `nm` command line tool to get the address of the function\n    // then use `add42line` command line tool to map function address + offset to line in source code\n    static std::string TranslateBacktrace( std::string s, std::string libname )\n    {\n      // example line\n      // 1   libngcore.dylib                     0x000000010ddb298c _ZL21ngcore_signal_handleri + 316\n      constexpr char reset_shell[] = \"\\033[0m\";\n      constexpr char green[] = \"\\033[32m\";\n      [[maybe_unused]] constexpr char yellow[] = \"\\033[33m\";\n\n      std::istringstream in(s);\n\n      std::string libname1, funcname, addr, plus_sign;\n      size_t i,offset;\n\n      in >> i >> libname1 >> addr >> funcname >> plus_sign >> std::hex >> offset;\n\n      std::stringstream out;\n\n      if(!funcname.empty() && !libname.empty())\n      {\n        std::string nm_command = \"nm \" + libname + \" | grep \\\"\" + funcname + \"$\\\" | cut -f 1 -d ' '\";\n        std::string output;\n        auto exit_code = exec(nm_command, output);\n        auto fptr = std::strtoul(output.c_str(), 0, 16);\n        if(fptr == 0)\n            return out.str()+'\\n';\n        std::stringstream offset_s;\n        offset_s << \"0x\" << std::hex << fptr+offset - 5;\n        std::string addr2line_command = std::string(\"atos -o \") + libname + \" --fullPath \" + offset_s.str();\n        exit_code = exec(addr2line_command, output);\n        if(exit_code==0)\n          out << \" at \" << green << output << reset_shell;\n        else\n          out << '\\n';\n      }\n      else\n        out << s << '\\n';\n\n      return out.str();\n    }\n#else // __APPLE__\n\n    // Split output line from backtrace_symbols to recover function name and offset\n    // then use `nm` command line tool to get the address of the function\n    // then use `addr2line` command line tool to map function address + offset to line in source code\n    static std::string TranslateBacktrace( std::string s, std::string /*dummy*/ )\n    {\n      // example line:\n      // /home/mhochsteger/install/ngs_clang/bin/../lib/libngcore.so(_ZN6ngcore11TaskManager4LoopEi+0x1e0) [0x7f2991fe1030]\n      constexpr char reset_shell[] = \"\\033[0m\";\n      constexpr char green[] = \"\\033[32m\";\n      constexpr char yellow[] = \"\\033[33m\";\n\n      auto brace_open_pos = s.find('(');\n      auto brace_close_pos = s.find(')', brace_open_pos);\n      auto plus_pos = s.find('+', brace_open_pos);\n      auto bracket_open_pos = s.find('[');\n      auto bracket_close_pos = s.find(']');\n\n      auto libname = s.substr(0, brace_open_pos);\n      auto funcname = s.substr(brace_open_pos+1, plus_pos - brace_open_pos - 1);\n      auto offset = std::strtoul(s.substr(plus_pos+1, brace_close_pos - plus_pos - 1).c_str(), 0, 16);\n      // auto position = std::strtoul(s.substr(bracket_open_pos+1, bracket_close_pos - bracket_open_pos - 1).c_str(), 0, 16);\n      std::stringstream out;\n\n      if(!funcname.empty())\n      {\n        std::vector<char> buffer(10240);\n        int status;\n        size_t size = buffer.size();\n        abi::__cxa_demangle(funcname.c_str(), &buffer[0], &size, &status);\n        out << \"in \" << yellow << &buffer[0] << reset_shell << '\\n';\n\n        std::string nm_command = \"nm \" + libname + \" | grep \" + funcname + \" | cut -f 1 -d ' '\";\n        std::string output;\n        auto exit_code = exec(nm_command, output);\n        auto fptr = std::strtoul(output.c_str(), 0, 16);\n\n        std::stringstream offset_s;\n        offset_s << \"0x\" << std::hex << fptr+offset - 5;\n        std::string addr2line_command = std::string(\"addr2line -i -p -e \") + libname + \" \" + offset_s.str();\n        exit_code = exec(addr2line_command, output);\n        if(exit_code==0)\n          {\n            std::stringstream soutput(output);\n            std::string s;\n            while(soutput)\n              {\n                if(getline(soutput, s))\n                    out << \"\\t   at \" << green << s << reset_shell << '\\n';\n              }\n          }\n        else\n          out << '\\n';\n      }\n      else\n        out << s << '\\n';\n\n      return out.str();\n    }\n#endif // __APPLE__\n\n  } // namespace detail\n\n  std::string GetBackTrace()\n  {\n    if(!getenv(\"NG_BACKTRACE\"))\n        return \"\";\n    std::cerr << \"Collecting backtrace...\" << std::endl;\n    std::stringstream result;\n    void *bt[100];\n    int bt_size;\n    char **bt_syms;\n    int i;\n\n    bt_size = backtrace(bt, 100);\n    bt_syms = backtrace_symbols(bt, bt_size);\n    Dl_info info;\n    for (i = 1; i < bt_size-1; i++)\n      {\n        dladdr(bt[i], &info);\n        // size_t len = strlen(bt_syms[i]);\n        result << '#'<< i << '\\t' << detail::TranslateBacktrace( bt_syms[i], info.dli_fname );\n      }\n    free(bt_syms);\n    return result.str();\n  }\n\n} // namespace ngcore\n\nstatic void ngcore_signal_handler(int sig)\n{\n  static bool first_call = true;\n  if(!first_call)\n      exit(1); // avoid endless recursions if signals are caused by this handler\n  first_call = false;\n\n  switch(sig)\n    {\n      case SIGABRT:\n          std::cerr << \"Caught SIGABRT: usually caused by abort() or assert()\" << std::endl;\n          break;\n      case SIGILL:\n          std::cerr << \"Caught SIGILL: illegal instruction\" << std::endl;\n          break;\n      case SIGSEGV:\n          std::cerr << \"Caught SIGSEGV: segmentation fault\" << std::endl;\n          break;\n    }\n\n  std::cerr << ngcore::GetBackTrace() << std::endl;\n  exit(1);\n}\n\n// register signal handler when library is loaded\nstatic bool dummy = []()\n{\n    if(getenv(\"NG_BACKTRACE\"))\n    {\n      signal(SIGABRT, ngcore_signal_handler);\n      signal(SIGILL, ngcore_signal_handler);\n      signal(SIGSEGV, ngcore_signal_handler);\n    }\n    return true;\n}();\n\n#else // NG_HAVE_BACKTRACE\n\nnamespace ngcore\n{\n  std::string GetBackTrace()\n  {\n    return std::string();\n  }\n} // namespace ngcore\n\n#endif // NG_HAVE_BACKTRACE\n"
  },
  {
    "path": "libsrc/core/exception.hpp",
    "content": "#ifndef NETGEN_CORE_EXCEPTION_HPP\n#define NETGEN_CORE_EXCEPTION_HPP\n\n#include <cstddef>\n#include <sstream>         // for stringstream\n#include <stdexcept>       // for exception\n#include <string>          // for string\n\n#include \"ngcore_api.hpp\"  // for NGCORE_API\n#include \"utils.hpp\"       // for ToString\n\n\nnamespace ngcore\n{\n  NGCORE_API std::string GetBackTrace();\n\n  // Exception for code that shouldn't be executed\n  class NGCORE_API UnreachableCodeException : public std::exception\n  {\n    const char* what() const noexcept override\n    {\n      return \"Shouldn't get here, something went wrong!\";\n    }\n  };\n\n  // Default exception class\n  class NGCORE_API Exception : public std::exception\n  {\n    /// a verbal description of the exception\n    std::string m_what;\n  public:\n    Exception() = default;\n    Exception(const Exception&) = default;\n    Exception(Exception&&) = default;\n    Exception(const std::string& s); //  : m_what(s) {}\n    Exception(const char* s); //  : m_what(s) {}\n    Exception(std::string_view s1, std::string_view s2);\n    Exception(std::string_view s1, std::string_view s2, std::string_view s3);\n    ~Exception() override = default;\n\n    [[noreturn]] static void Throw (std::string_view s1);\n    [[noreturn]] static void Throw (std::string_view s1, std::string_view s2);\n    [[noreturn]] static void Throw (std::string_view s1, std::string_view s2, std::string_view s3);\n    \n    Exception& operator =(const Exception&) = default;\n    Exception& operator =(Exception&&) noexcept = default;\n\n    /// append string to description\n    Exception & Append (const std::string & s) { m_what += s; return *this; }\n  /// append string to description\n    Exception & Append (const char * s) { m_what += s; return *this; }\n\n    /// verbal description of exception\n    const std::string & What() const { return m_what; }\n\n    /// implement virtual function of std::exception\n    const char* what() const noexcept override { return m_what.c_str(); }\n  };\n  \n  [[noreturn]] NGCORE_API void ThrowException(const std::string & s);\n  [[noreturn]] NGCORE_API void ThrowException(const char * s);\n  \n  // Out of Range exception\n  class NGCORE_API RangeException : public Exception\n  {\n  public:\n    /// where it occurs, index, minimal and maximal indices\n    RangeException (// const std::string & where,\n                    const char * where,\n                    ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);\n    /*\n    : Exception(\"\")\n      {\n        std::stringstream str;\n        str << where << \": index \" << ind << \" out of range [\" << imin << \",\" << imax << \")\\n\";\n        Append (str.str());\n        Append (GetBackTrace());\n      }\n    */\n    template<typename T>\n    RangeException(const std::string& where, const T& value)\n    {\n      std::stringstream str;\n      str << where << \" called with wrong value \" << value << \"\\n\";\n      Append(str.str());\n    }\n  };\n\n  [[noreturn]] NGCORE_API void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);\n  [[noreturn]] NGCORE_API void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b);\n  \n  \n  // Exception used if no simd implementation is available to fall back to standard evaluation\n  class NGCORE_API ExceptionNOSIMD : public Exception\n  { public: using Exception::Exception; };\n\n  template <typename T>\n  struct IsSafe {\n    constexpr operator bool() const { return false; } };\n\n  namespace detail {\n    template <typename T, typename Tmin, typename Tmax>\n    inline static constexpr void CheckRange(const char * s, const T& n, Tmin first, Tmax next)\n    {\n      if constexpr (!IsSafe<decltype(n)>())\n        if (n<first || n>=next)\n          ThrowRangeException(s, ptrdiff_t(n), ptrdiff_t(first), ptrdiff_t(next));\n    }\n\n    template <typename Ta, typename Tb>\n    inline static constexpr void CheckSame(const char * s, const Ta& a, const Tb& b)\n    {\n     if constexpr (!IsSafe<decltype(a)>() || !IsSafe<decltype(b)>())\n      if(a != b)\n      {\n        if constexpr(std::is_integral_v<decltype(a)> && std::is_same_v<decltype(a),decltype(b)>)\n          ThrowNotTheSameException(s, long(a), long(b)); \\\n        else\n          throw Exception(std::string(s) + \"\\t: not the same, a=\"+ToString(a) + \", b=\"+ngcore::ToString(b) + GetBackTrace());\n      }\n    }\n  } // namespace detail\n} // namespace ngcore\n\n#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x\n#define NETGEN_CORE_NGEXEPTION_STR(x) NETGEN_CORE_NGEXEPTION_STR_HELPER(x)\n\n// Convenience macro to append file name and line of exception origin to the string\n#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ \":\" NETGEN_CORE_NGEXEPTION_STR(__LINE__) \"\\t\"+std::string(s))\n\n#if defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)\n#define NETGEN_CHECK_RANGE(value, min, max_plus_one) ngcore::detail::CheckRange(__FILE__ \":\" NETGEN_CORE_NGEXEPTION_STR(__LINE__) \"\\t\", value, min, max_plus_one);\n#define NETGEN_CHECK_SAME(a,b) ngcore::detail::CheckSame(__FILE__ \":\" NETGEN_CORE_NGEXEPTION_STR(__LINE__) \"\\t\", a, b);\n\n#define NETGEN_NOEXCEPT \n#else // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)\n#define NETGEN_CHECK_RANGE(value, min, max)\n#define NETGEN_CHECK_SAME(a,b)\n// #define NETGEN_CHECK_SHAPE(a,b)\n#define NETGEN_NOEXCEPT noexcept\n#endif // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)\n\n\n  \n#endif // NETGEN_CORE_EXCEPTION_HPP\n"
  },
  {
    "path": "libsrc/core/flags.cpp",
    "content": "/**************************************************************************/\n/* File:   flags.cpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   10. Oct. 96                                                    */\n/**************************************************************************/\n\n#include \"archive.hpp\"\n#include \"flags.hpp\"\n\n#ifdef WIN32\n#include <float.h>\n#endif\n\n#include <algorithm>\n\nnamespace ngcore\n{\n  using std::string;\n  using std::string_view;\n  using std::endl;\n  Flags :: Flags () { ; }\n\n  Flags :: Flags (const Flags & flags)\n  {\n    string name;\n    for (int i = 0; i < flags.GetNStringFlags(); i++)\n      {\n\tstring str = flags.GetStringFlag (i, name);\n\tSetFlag (name, str);\n      }\n    for (int i = 0; i < flags.GetNNumFlags(); i++)\n      {\n\tdouble val = flags.GetNumFlag (i, name);\n\tSetFlag (name, val);\n      }\n    for (int i = 0; i < flags.GetNDefineFlags(); i++)\n      {\n\tbool val = flags.GetDefineFlag (i, name);\n\tSetFlag (name, val);\n      }\n    for (int i = 0; i < flags.GetNNumListFlags(); i++)\n      {\n\tauto numa = flags.GetNumListFlag (i, name);\n\tSetFlag (name, *numa);\n      }\n    for (int i = 0; i < flags.GetNStringListFlags(); i++)\n      {\n\tauto stra = flags.GetStringListFlag (i, name);\n\tSetFlag (name, *stra);\n      }\n    for (int i = 0; i < flags.GetNFlagsFlags(); i++)\n      {\n\tauto lflags = flags.GetFlagsFlag (i, name);\n\tSetFlag (name, lflags);\n      }\n    for(auto i : Range(flags.anyflags.Size()))\n      {\n        SetFlag(flags.anyflags.GetName(i), flags.anyflags[i]);\n      }\n  }\n  \n  Flags :: Flags (std::initializer_list<string> list)\n  {\n    for (auto i = list.begin(); i < list.end(); i++)\n      SetCommandLineFlag ((string(\"-\")+*i).c_str());      \n  }\n\n\n  Flags :: Flags (string f1, string f2, string f3, string f4, string f5)\n  {\n    SetCommandLineFlag ((string(\"-\")+f1).c_str());\n    if (f2.length()) SetCommandLineFlag ( (string(\"-\")+f2).c_str() );\n    if (f3.length()) SetCommandLineFlag ( (string(\"-\")+f3).c_str() );\n    if (f4.length()) SetCommandLineFlag ( (string(\"-\")+f4).c_str() );\n    if (f5.length()) SetCommandLineFlag ( (string(\"-\")+f5).c_str() );\n  }\n  \n  Flags :: ~Flags ()\n  {\n    DeleteFlags ();\n  }\n  \n  void Flags :: DeleteFlags ()\n  {\n    strflags.DeleteAll();\n    numflags.DeleteAll();\n    defflags.DeleteAll();\n    strlistflags.DeleteAll();\n    numlistflags.DeleteAll();\n  }\n\n\n  Flags Flags :: SetFlag (const char * name, bool b) &&\n  {\n    this -> SetFlag (name, b);\n    return std::move(*this);\n  }\n\n  Flags Flags :: SetFlag (const char * name, double val) &&\n  {\n    this -> SetFlag (name, val);\n    return std::move(*this);\n  }\n\n\n\n  Flags & Flags :: SetFlag (const char * name, const string & val)\n  {\n    strflags.Set (name, val);\n    return *this;\n  }\n  \n  Flags & Flags :: SetFlag (const char * name, double val) &\n  {\n    numflags.Set (name, val);\n    return *this;\n  }\n  \n  Flags & Flags :: SetFlag (const char * name, bool b) &\n  {\n    defflags.Set (name, b);\n    return *this;\n  }\n\n  Flags & Flags :: SetFlag (const char * name, Flags & val) &\n  {\n    flaglistflags.Set (name, val);\n    return *this;\n  }\n\n\n  \n  Flags & Flags :: SetFlag (const string & name, const string & val)\n  {\n    // char * hval = new char[strlen (val) + 1];\n    // strcpy (hval, val);\n    strflags.Set (name, val);\n    return *this;\n  }\n  \n  Flags & Flags :: SetFlag (const string & name, double val) \n  {\n    numflags.Set (name, val);\n    return *this;\n  }\n  \n  Flags & Flags :: SetFlag (const string & name, bool b)\n  {\n    defflags.Set (name, b);\n    return *this;\n  }\n\n  Flags & Flags :: SetFlag (const string & name, Flags & val)\n  {\n    flaglistflags.Set (name, val);\n    return *this;\n  }\n\n  Flags & Flags :: SetFlag (const string & name, const Array<string> & val)\n  {\n    auto strarray = std::make_shared<Array<string>>(val);\n      /*\n    for (int i = 0; i < val.Size(); i++)\n      {\n\tstrarray->Append (new char[strlen(val[i])+1]);\n\tstrcpy (strarray->Last(), val[i]);\n      }\n      */\n    strlistflags.Set (name, strarray);    \n    return *this;\n  }\n\n  Flags & Flags :: SetFlag (const string & name, const Array<double> & val)\n  {\n    // Array<double> * numarray = new Array<double>(val);\n    auto numarray = std::make_shared<Array<double>> (val);\n\n    numlistflags.Set (name, numarray);\n    return *this;\n  }\n\n  Flags & Flags :: SetFlag (const string & name, const std::any & val)\n  {\n    anyflags.Set(name, val);\n    return *this;\n  }\n\n  string Flags :: GetStringFlag (const string & name, const char * def) const\n  {\n    if (strflags.Used (name))\n      return strflags[name];\n    else\n      {\n        if (!def) return string(\"\");\n        return def;\n      }\n  }\n\n  string Flags :: GetStringFlag (const string & name, string def) const\n  {\n    if (strflags.Used (name))\n      return strflags[name];\n    else\n      return def;\n  }\n\n\n  double Flags :: GetNumFlag (string_view name, double def) const\n  {\n    if (numflags.Used (name))\n      return numflags[string(name)];\n    else\n      return def;\n  }\n  \n  const double * Flags :: GetNumFlagPtr (string_view name) const\n  {\n    if (numflags.Used (name))\n      return & ((SymbolTable<double>&)numflags)[string(name)];\n    else\n      return NULL;\n  }\n  \n  double * Flags :: GetNumFlagPtr (const string & name) \n  {\n    if (numflags.Used (name))\n      return & ((SymbolTable<double>&)numflags)[name];\n    else\n      return NULL;\n  }\n\n  /*\n  int Flags :: GetDefineFlag (const char * name) const\n  {\n    return defflags.Used (name);\n  }\n  */\n  bool Flags :: GetDefineFlag (string_view name) const throw()\n  {\n    if (!defflags.Used (string(name))) return false;\n    return defflags[string(name)];\n  }\n\n  xbool Flags :: GetDefineFlagX (string_view name) const throw()\n  {\n    if (!defflags.Used (string(name))) return maybe;\n    return bool(defflags[string(name)]);\n  }\n\n\n  const Array<string> & \n  Flags :: GetStringListFlag (const string & name) const\n  {\n    if (strlistflags.Used (name))\n      return *strlistflags[name];\n    else\n      {\n\tstatic Array<string> hstra(0);\n\treturn hstra;\n      }\n  }\n\n  const Array<double> & \n  Flags ::GetNumListFlag (const string & name) const\n  {\n    if (numlistflags.Used (name))\n      return *numlistflags[name];\n    else\n      {\n\tstatic Array<double> hnuma(0);\n\treturn hnuma;\n      }\n  }\n\n  const Flags & \n  Flags ::GetFlagsFlag (const string & name) const\n  {\n    if (flaglistflags.Used (name))\n      return flaglistflags[name];\n    else\n      {\n\tstatic Flags empty;\n\treturn empty;\n      }\n  }\n\n  const std::any& Flags:: GetAnyFlag(const std::string& name) const\n  {\n    if(anyflags.Used(name))\n      return anyflags[name];\n    static std::any empty;\n    return empty;\n  }\n\n  bool Flags :: StringFlagDefined (string_view name) const noexcept\n  {\n    return strflags.Used (name);\n  }\n\n  bool Flags :: NumFlagDefined (string_view name) const noexcept\n  {\n    return numflags.Used (name);\n  }\n\n  bool Flags :: FlagsFlagDefined (string_view name) const noexcept\n  {\n    return flaglistflags.Used (name);\n  }\n  \n  bool Flags :: StringListFlagDefined (string_view name) const noexcept\n  {\n    return strlistflags.Used (name);\n  }\n\n  bool Flags :: NumListFlagDefined (string_view name) const noexcept\n  {\n    return numlistflags.Used (name);\n  }\n\n  bool Flags :: AnyFlagDefined (string_view name) const noexcept\n  {\n    return anyflags.Used(name);\n  }\n\n  void Flags :: SaveFlags (ostream & str) const\n  {\n    for (int i = 0; i < strflags.Size(); i++)\n      str << strflags.GetName(i) << \" = \" << strflags[i] << endl;\n    for (int i = 0; i < numflags.Size(); i++)\n      str << numflags.GetName(i) << \" = \" << numflags[i] << endl;\n    for (int i = 0; i < defflags.Size(); i++)\n      str << defflags.GetName(i) << \" = \" << (defflags[i] ? \"_TRUE\" : \"_FALSE\") << endl;\n    for (int i = 0; i < flaglistflags.Size(); i++)\n      str << flaglistflags.GetName(i) << \" =*\" << flaglistflags[i] << endl;\n    for (int i = 0; i < numlistflags.Size(); i++)\n      {\n        str << numlistflags.GetName(i) << \" = [\";\n        int j = 0;\n        for (j = 0; j + 1 < numlistflags[i]->Size(); ++j)\n          str << (*numlistflags[i])[j] << \", \";\n\tif (numlistflags[i]->Size())\n\t  str << (*numlistflags[i])[j];\n\tstr << \"]\" << endl;\n      }\n  }\n\n  void Flags :: SaveFlags (const char * filename) const \n  {\n    std::ofstream outfile (filename);\n    SaveFlags(outfile);\n  }\n \n\n\n  void Flags :: PrintFlags (ostream & ost) const \n  {\n    for (int i = 0; i < strflags.Size(); i++)\n      ost << strflags.GetName(i) << \" = \" << strflags[i] << endl;\n    for (int i = 0; i < numflags.Size(); i++)\n      ost << numflags.GetName(i) << \" = \" << numflags[i] << endl;\n    for (int i = 0; i < defflags.Size(); i++)\n      ost << defflags.GetName(i) << endl;\n    for (int i = 0; i < strlistflags.Size(); i++)\n      ost << strlistflags.GetName(i) << \" = \" << *strlistflags[i] << endl;\n    for (int i = 0; i < numlistflags.Size(); i++)\n      ost << numlistflags.GetName(i) << \" = \" << *numlistflags[i] << endl;\n    for (int i = 0; i < flaglistflags.Size(); i++)\n      ost << flaglistflags.GetName(i) << \" = \" << flaglistflags[i] << endl;\n    for (int i = 0; i < anyflags.Size(); i++)\n      ost << anyflags.GetName(i) << \" = \" << \"[any]\" << endl;\n  }\n\n  void Flags :: LoadFlags (const char * filename, SymbolTable<Flags> * sf)\n  {\n    std::ifstream str(filename);\n    LoadFlags(str,sf);\n  }\n\n  void Flags :: LoadFlags (std::istream & istr, SymbolTable<Flags> * sf ) \n  {\n    char str[100];\n    char ch;\n    // double val;\n\n    while (istr.good())\n      {\n        string name;\n        string content;\n        string line;\n        getline(istr, line);\n        std::istringstream line_stream(line);\n\n        getline(line_stream, name, '=');\n        name.erase(std::remove(name.begin(), name.end(), ' '), name.end());\n\n        getline(line_stream, content);\n        content.erase(std::remove(content.begin(), content.end(), ' '), content.end());\n        \n\t// if (name[0] == '/' && name[1] == '/')\n\t//   {\n\t//     ch = 0;\n\t//     while (ch != '\\n' && istr.good())\n\t//       {\n\t// \tch = istr.get();\n\t//       }\n\t//     continue;\n\t//   }\n\n        if (strlen(content.c_str())==0)\n        {\n          SetFlag (name);\n          continue;\n        }\n\telse\n\t  {\n            std::istringstream content_stream(content);\n            \n            content_stream >> ch;\n            if (ch != '*')\n              {\n                if (ch == '[')\n                  {\n                    // content_stream.putback (ch);\n                    // content_stream >> ch;\n                    string inner_string;\n                    getline(content_stream, inner_string, ']');\n                    std::istringstream inner_string_stream(inner_string);\n                    \n                    Array<double> values;\n                    Array<string> strings;\n\n                    string cur;\n                    while (getline(inner_string_stream, cur, ','))\n                    {\n                      char* endptr;\n                      double vald = strtod (cur.c_str(), &endptr);\n                      \n                      if (endptr != cur.c_str() && strings.Size() == 0)\n                        values.Append(vald);\n                      else\n                        strings.Append(cur);\n                    }\n                    if (strings.Size() > 0)\n                      SetFlag(name, strings);\n                    else\n                      SetFlag(name, values);\n                  }\n                else\n                  {\n                    if(content == \"_TRUE\" || content == \"_FALSE\")\n                      {\n                        SetFlag(name, (content ==\"_TRUE\") ? true : false);\n                        continue;\n                      }\n                    char* endptr;\n                    double vald = strtod (content.c_str(), &endptr);\n                    if (endptr != content.c_str())\n                      SetFlag (name, vald);\n                    else\n                      SetFlag (name, content);\n                  }\n              }\n            else\n              {\n                content_stream.clear();\n                content_stream >> str;\n                if (sf)\n                  SetFlag (name, (*sf)[str]);\n                else\n                  throw Exception (\" no symboltable of flags \");\n              }\n\t  }\n      }\n  }\n\n  void Flags :: DoArchive(Archive & archive)\n  {\n    archive & strflags & numflags & defflags & numlistflags & strlistflags & flaglistflags & anyflags;\n  }\n\n  void Flags :: Update(const Flags& other)\n  {\n    strflags.Update(other.strflags);\n    numflags.Update(other.numflags);\n    defflags.Update(other.defflags);\n    numlistflags.Update(other.numlistflags);\n    strlistflags.Update(other.strlistflags);\n    flaglistflags.Update(other.flaglistflags);\n  }\n\n  void Flags :: SetCommandLineFlag (const char * st, SymbolTable<Flags> * sf )\n  {\n    //cout << \"SetCommandLineFlag: flag = \" << st << endl;\n    std::istringstream inst( (char *)st);\n\n    char name[100];\n    double val;\n\n\n    if (st[0] != '-')\n      {\n        std::cerr << \"flag must start with '-'\" << endl;\n\treturn;\n      }\n\n    // flag with double --\n    if (st[1] == '-') st++;\n  \n    const char * pos = strchr (st, '=');\n    const char * posstar = strchr (st, '*');\n    const char * posbrack = strchr (st, '[');\n\n    if (!pos)\n      {\n\t//      (cout) << \"Add def flag: \" << st+1 << endl;\n\tSetFlag (st+1);\n      }\n    else\n      {\n\t//cout << \"pos = \" << pos << endl;\n\n\tstrncpy (name, st+1, (pos-st)-1);\n\tname[pos-st-1] = 0;\n\n\t//cout << \"name = \" << name << endl;\n\n\tpos++;\n\tchar * endptr = NULL;\n\tval = strtod (pos, &endptr);\n\n        /*\n        cout << \"val = \" << val << endl;\n        cout << \"isfinite = \" << std::isfinite (val) << endl;\n        cout << \"isinf = \" << std::isinf (val) << endl;\n        cout << \"pos = \" << pos << \", endpos = \" << endptr << endl;\n        */\n        if (endptr != pos && !std::isfinite (val))\n          endptr = const_cast<char *>(pos);          \n\n        /*\n#ifdef WIN32\n\tif(endptr != pos && !_finite(val))\n\t  endptr = const_cast<char *>(pos);\n#else\n#ifdef MACOS\n\tif(endptr != pos && (__isnand(val) || __isinfd(val)))\n\t  endptr = const_cast<char *>(pos);\n#else\n#ifdef SUN\n#else\n\tif(endptr != pos && (std::isnan(val) || std::isinf(val)))\n\t  endptr = const_cast<char *>(pos);\n#endif\n#endif\n#endif\n        */\n\t\n\t//cout << \"val = \" << val << endl;\n\n\tif (!posbrack)\n\t  {\n            if (posstar)\n              {\n                pos++;\n                if (sf)\n                  SetFlag (name, (*sf)[pos]);\n                else\n                  throw Exception (\" no symboltable of flags \");\n              }\n\t    else if (endptr == pos)\n\t      {\n\t\t// string-flag\n\t\t//(cout) << \"Add String Flag: \" << name << \" = \" << pos << endl;\n\t\tSetFlag (name, pos);\n\t      }\n\t    else\n\t      {\n\t\t// num-flag\n\t\t//(cout) << \"Add Num Flag: \" << name << \" = \" << val << endl;\n\t\tSetFlag (name, val);\n\t      }\n\t  }\n\telse\n\t  {\n\t    // list-flag\n\t    char hc;\n\t    double val;\n\n\t    val = strtod (posbrack+1, &endptr);\n\t    if (endptr != posbrack+1)\n\t      {\n\t\tArray<double> values;\n\t\t\n                std::istringstream ist(posbrack);\n\t\tist >> hc;   // '['\n\t\tist >> val;\n\t\twhile (ist.good())\n\t\t  {\n\t\t    values.Append (val);\n\t\t    ist >> hc;  // ','\n\t\t    ist >> val;\n\t\t  }\n\t\tSetFlag (name, values);\n\t      }\n\t    else\n\t      {\n                // to be cleaned up ...\n\t\tArray<char *> strs;\n\n\t\tposbrack++;\n\t\tchar * hstr = new char[strlen(posbrack)+1];\n\t\tstrcpy (hstr, posbrack);\n\t\t\n\t\tchar * chp = hstr;\n\n\t\tbool start = 1;\n\t\twhile (*chp && *chp != ']')\n\t\t  {\n\t\t    if (start)\n\t\t      strs.Append (chp);\n\t\t    start = 0;\n\t\t    if (*chp == ',')\n\t\t      {\n\t\t\t*chp = 0;\n\t\t\tstart = 1;\n\t\t      }\n\t\t    chp++;\n\t\t  }\n\t\t*chp = 0;\n\n                Array<string> strings;\n                for (int i = 0; i < strs.Size(); i++)\n                  strings.Append (string (strs[i]));\n\t\tSetFlag (name, strings);\n                delete [] hstr;\n\t      }\n\t  }\n      }\n  }\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/flags.hpp",
    "content": "#ifndef NETGEN_CORE_FLAGS_HPP\n#define NETGEN_CORE_FLAGS_HPP\n\n\n/**************************************************************************/\n/* File:   flags.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   10. Oct. 96                                                    */\n/**************************************************************************/\n\n#include <iostream>\n#include <memory>\n#include <string>\n#include <any>\n\n#include \"array.hpp\"\n#include \"symboltable.hpp\"\n#include \"xbool.hpp\"\n\nnamespace ngcore\n{\n\n  /** \n      A storage for command-line flags.\n      The flag structure maintains string flags, numerical flags,\n      define flags, string list flags, num list flags.\n  */\n  class NGCORE_API Flags \n  {\n    /// string flags\n    SymbolTable<std::string> strflags;\n    /// numerical flags\n    SymbolTable<double> numflags;\n    /// define flags\n    SymbolTable<bool> defflags;\n    /// string list flags\n    SymbolTable<std::shared_ptr<Array<std::string>>> strlistflags;\n    /// numerical list flags\n    SymbolTable<std::shared_ptr<Array<double>>> numlistflags;\n    /// flags list flags\n    SymbolTable<Flags> flaglistflags;\n    /// any object can be stored as a flag\n    SymbolTable<std::any> anyflags;\n  public:\n    /// no flags\n    Flags ();\n    /// copy flags \n    Flags (const Flags & flags);\n    /// steal flags\n    Flags (Flags && flags) = default;\n    ///\n    Flags (std::initializer_list<std::string> list);\n    /// \n    Flags (std::string f1, std::string f2 = \"\", std::string f3 = \"\", std::string f4 = \"\", std::string f5 = \"\");\n    /// delete mem\n    ~Flags ();\n\n    Flags & operator= (const Flags & f2) = default;\n    Flags & operator= (Flags && f2) = default;\n\n    void DoArchive(class Archive& ar);\n\n    void Update(const Flags& other);\n  \n    /// Deletes all flags\n    void DeleteFlags ();\n\n    /// Sets string flag, overwrite if exists\n    Flags & SetFlag (const char * name, const std::string & val);\n    /// Sets string flag, overwrite if exists\n    Flags & SetFlag (const char * name, const char * str)\n    { return SetFlag (name, std::string(str)); }\n    /// Sets numerical flag, overwrite if exists\n    Flags & SetFlag (const char * name, double val) &;\n    /// Sets numerical flag, overwrite if exists    \n    Flags & SetFlag (const char * name, int val)\n    { return SetFlag (name, double(val)); }\n    /// Sets boolean flag\n    Flags & SetFlag (const char * name, bool b = true) &;\n    /// Sets numerical flag, overwrite if exists\n    Flags & SetFlag (const char * name, Flags & val) &;\n\n    /// Sets string flag, overwrite if exists\n    Flags & SetFlag (const std::string & name, const std::string & val);\n    Flags & SetFlag (const std::string & name, const char * str)\n    { return SetFlag (name, std::string(str)); }\n    /// Sets numerical flag, overwrite if exists\n    Flags &  SetFlag (const std::string & name, double val);\n    /// Sets numerical flag, overwrite if exists    \n    Flags &  SetFlag (const std::string & name, int val)\n    { return SetFlag (name, double(val)); }\n    /// Sets boolean flag\n    Flags &  SetFlag (const std::string & name, bool b = true);\n    /// Sets numerical flag, overwrite if exists\n    Flags &  SetFlag (const std::string & name, Flags & val);\n    /// Sets string array flag\n    Flags &  SetFlag (const std::string & name, const Array<std::string> & val);\n    /// Sets double array flag\n    Flags &  SetFlag (const std::string & name, const Array<double> & val);\n    /// Sets any flag\n    Flags &  SetFlag(const std::string& name, const std::any& val);\n\n\n    Flags SetFlag (const char * name, bool b = true) &&;\n    Flags SetFlag (const char * name, double val) &&;\n\n\n\n    /// Save flags to file\n    void SaveFlags (const char * filename) const;\n    void SaveFlags (ostream & str) const;\n    /// write flags to stream\n    void PrintFlags (ostream & ost) const;\n    /// Load flags from file\n    void LoadFlags (const char * filename, SymbolTable<Flags> * sf = nullptr);\n    void LoadFlags (std::istream & str, SymbolTable<Flags> * sf = nullptr);\n    /**\n       Set command line flag.\n       Flag must be in form: -name=hello -val=0.5 -defflag \n       -names=[Joe,Jim] -values=[1,3,4] -solverflags=*abc\n    */\n    void SetCommandLineFlag (const char * st, SymbolTable<Flags> * sf = nullptr);\n    /// Returns string flag, default value if not exists\n    std::string GetStringFlag (const std::string & name, const char * def) const;\n    /// Returns std::string flag, default value if not exists\n    std::string GetStringFlag (const std::string & name, std::string def = \"\") const;\n    /// Returns numerical flag, default value if not exists\n    double GetNumFlag (std::string_view name, double def) const;\n    /// Returns address of numerical flag, null if not exists\n    const double * GetNumFlagPtr (std::string_view name) const;\n    /// Returns address of numerical flag, null if not exists\n    double * GetNumFlagPtr (const std::string & name);\n    /// Returns boolean flag\n    // int GetDefineFlag (const char * name) const;\n    bool GetDefineFlag (std::string_view name) const  noexcept;\n    xbool GetDefineFlagX (std::string_view name) const  noexcept;\n    /// Returns string list flag, empty array if not exist\n    const Array<std::string> & GetStringListFlag (const std::string & name) const;\n    /// Returns num list flag, empty array if not exist\n    const Array<double> & GetNumListFlag (const std::string & name) const;\n    /// Returns flag list flag, empty flag if not exist\n    const Flags & GetFlagsFlag (const std::string & name) const;\n    const std::any& GetAnyFlag (const std::string& name) const;\n\n\n    /// Test, if string flag is defined\n    bool StringFlagDefined (std::string_view name) const noexcept;\n    /// Test, if num flag is defined\n    bool NumFlagDefined (std::string_view name) const noexcept;\n    /// Test, if num flag is defined\n    bool FlagsFlagDefined (std::string_view name) const noexcept;\n    /// Test, if string list flag is defined\n    bool StringListFlagDefined (std::string_view name) const noexcept;\n    /// Test, if num list flag is defined\n    bool NumListFlagDefined (std::string_view name) const noexcept;\n    bool AnyFlagDefined (std::string_view name) const noexcept;\n\n    /// number of string flags\n    int GetNStringFlags () const { return strflags.Size(); }\n    /// number of num flags\n    int GetNNumFlags () const { return numflags.Size(); }\n    /// number of num flags\n    int GetNFlagsFlags () const { return flaglistflags.Size(); }\n    /// number of define flags\n    int GetNDefineFlags () const { return defflags.Size(); }\n    /// number of string-list flags\n    int GetNStringListFlags () const { return strlistflags.Size(); }\n    /// number of num-list flags\n    int GetNNumListFlags () const { return numlistflags.Size(); }\n    int GetNAnyFlags() const { return anyflags.Size(); }\n\n    ///\n    const std::string & GetStringFlag (int i, std::string & name) const\n    { name = strflags.GetName(i); return strflags[i]; }\n    double GetNumFlag (int i, std::string & name) const\n    { name = numflags.GetName(i); return numflags[i]; }\n    bool GetDefineFlag (int i, std::string & name) const\n    { name = defflags.GetName(i); return defflags[i]; }\n    const std::shared_ptr<Array<double>> GetNumListFlag (int i, std::string & name) const\n    { name = numlistflags.GetName(i).c_str(); return numlistflags[i]; }\n    const std::shared_ptr<Array<std::string>> GetStringListFlag (int i, std::string & name) const\n    { name = strlistflags.GetName(i); return strlistflags[i]; }\n    const Flags & GetFlagsFlag (int i, std::string & name) const\n    { name = flaglistflags.GetName(i); return flaglistflags[i]; }\n    const std::any& GetAnyFlag(int i, std::string& name) const\n    { name = anyflags.GetName(i); return anyflags[i]; }\n  };\n\n  /// Print flags\n  inline std::ostream & operator<< (std::ostream & s, const Flags & flags)\n  {\n    flags.PrintFlags (s);\n    return s;\n  }\n} // namespace ngcore\n\n  \n#endif // NETGEN_CORE_FLAGS_HPP\n\n"
  },
  {
    "path": "libsrc/core/generate_mpi_sources.py",
    "content": "functions = [\n        (\"double\", \"MPI_Wtime\"),\n        (\"int\", \"MPI_Allgather\", \"void*\", \"int\", \"MPI_Datatype\", \"void*\", \"int\", \"MPI_Datatype\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Allreduce\", \"void*\", \"void*\", \"int\", \"MPI_Datatype\", \"MPI_Op\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Alltoall\", \"void*\", \"int\", \"MPI_Datatype\", \"void*\", \"int\", \"MPI_Datatype\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Barrier\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Bcast\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Ibcast\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"MPI_Comm\", \"MPI_Request*\"),    \n        (\"int\", \"MPI_Comm_c2f\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Comm_create\", \"MPI_Comm\", \"MPI_Group\", \"MPI_Comm*\"),\n        (\"int\", \"MPI_Comm_create_group\", \"MPI_Comm\", \"MPI_Group\", \"int\", \"MPI_Comm*\"),\n        (\"int\", \"MPI_Comm_free\", \"MPI_Comm*\"),\n        (\"int\", \"MPI_Comm_group\", \"MPI_Comm\", \"MPI_Group*\"),\n        (\"int\", \"MPI_Comm_rank\", \"MPI_Comm\", \"int*\"),\n        (\"int\", \"MPI_Comm_size\", \"MPI_Comm\", \"int*\"),\n        (\"int\", \"MPI_Finalize\"),\n        (\"int\", \"MPI_Gather\", \"void*\", \"int\", \"MPI_Datatype\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Gatherv\", \"void*\", \"int\", \"MPI_Datatype\", \"void*\", \"int*\", \"int*\", \"MPI_Datatype\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Get_count\", \"MPI_Status*\", \"MPI_Datatype\", \"int*\"),\n        (\"int\", \"MPI_Get_processor_name\", \"char*\", \"int*\"),\n        (\"int\", \"MPI_Group_incl\", \"MPI_Group\", \"int\", \"int*\", \"MPI_Group*\"),\n        (\"int\", \"MPI_Init\", \"int*\", \"char***\"),\n        (\"int\", \"MPI_Init_thread\", \"int*\", \"char***\", \"int\", \"int*\"),\n        (\"int\", \"MPI_Initialized\", \"int*\"),\n        (\"int\", \"MPI_Iprobe\", \"int\", \"int\", \"MPI_Comm\", \"int*\", \"MPI_Status*\"),\n        (\"int\", \"MPI_Irecv\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Request*\"),\n        (\"int\", \"MPI_Isend\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Request*\"),\n        (\"int\", \"MPI_Probe\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Status*\"),\n        (\"int\", \"MPI_Query_thread\", \"int*\"),\n        (\"int\", \"MPI_Recv\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Status*\"),\n        (\"int\", \"MPI_Recv_init\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Request*\"),\n        (\"int\", \"MPI_Reduce\", \"void*\", \"void*\", \"int\", \"MPI_Datatype\", \"MPI_Op\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Reduce_local\", \"void*\", \"void*\", \"int\", \"MPI_Datatype\", \"MPI_Op\"),\n        (\"int\", \"MPI_Request_free\", \"MPI_Request*\"),\n        (\"int\", \"MPI_Scatter\", \"void*\", \"int\", \"MPI_Datatype\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Send\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\"),\n        (\"int\", \"MPI_Send_init\", \"void*\", \"int\", \"MPI_Datatype\", \"int\", \"int\", \"MPI_Comm\", \"MPI_Request*\"),\n        (\"int\", \"MPI_Startall\", \"int\", \"MPI_Request*:0\"),\n        (\"int\", \"MPI_Type_commit\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_contiguous\", \"int\", \"MPI_Datatype\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_create_resized\", \"MPI_Datatype\", \"MPI_Aint\", \"MPI_Aint\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_create_struct\", \"int\", \"int*:0\", \"MPI_Aint*:0\", \"MPI_Datatype*:0\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_free\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_get_extent\", \"MPI_Datatype\", \"MPI_Aint*\", \"MPI_Aint*\"),\n        (\"int\", \"MPI_Type_indexed\", \"int\", \"int*:0\", \"int*:0\", \"MPI_Datatype\", \"MPI_Datatype*\"),\n        (\"int\", \"MPI_Type_size\", \"MPI_Datatype\", \"int*\"),\n        (\"int\", \"MPI_Wait\", \"MPI_Request*\", \"MPI_Status*\"),\n        (\"int\", \"MPI_Waitall\", \"int\", \"MPI_Request*:0\", \"MPI_Status*\"),\n        (\"int\", \"MPI_Waitany\", \"int\", \"MPI_Request*:0\", \"int*\", \"MPI_Status*\"),\n        ]\n\nconstants = [\n        (\"MPI_Comm\", \"MPI_COMM_NULL\"),\n        (\"MPI_Comm\", \"MPI_COMM_WORLD\"),\n        (\"MPI_Datatype\", \"MPI_CHAR\"),\n        (\"MPI_Datatype\", \"MPI_CXX_DOUBLE_COMPLEX\"),\n        (\"MPI_Datatype\", \"MPI_C_BOOL\"),\n        (\"MPI_Datatype\", \"MPI_DATATYPE_NULL\"),\n        (\"MPI_Datatype\", \"MPI_DOUBLE\"),\n        (\"MPI_Datatype\", \"MPI_FLOAT\"),\n        (\"MPI_Datatype\", \"MPI_INT\"),\n        (\"MPI_Datatype\", \"MPI_SHORT\"),\n        (\"MPI_Datatype\", \"MPI_UINT64_T\"),\n        (\"MPI_Op\", \"MPI_LOR\"),\n        (\"MPI_Op\", \"MPI_MAX\"),\n        (\"MPI_Op\", \"MPI_MIN\"),\n        (\"MPI_Op\", \"MPI_SUM\"),\n        (\"MPI_Request\", \"MPI_REQUEST_NULL\"),\n        (\"MPI_Status*\", \"MPI_STATUSES_IGNORE\"),\n        (\"MPI_Status*\", \"MPI_STATUS_IGNORE\"),\n        (\"int\", \"MPI_ANY_SOURCE\"),\n        (\"int\", \"MPI_ANY_TAG\"),\n        (\"int\", \"MPI_MAX_PROCESSOR_NAME\"),\n        (\"int\", \"MPI_PROC_NULL\"),\n        (\"int\", \"MPI_ROOT\"),\n        (\"int\", \"MPI_SUBVERSION\"),\n        (\"int\", \"MPI_THREAD_MULTIPLE\"),\n        (\"int\", \"MPI_THREAD_SINGLE\"),\n        (\"int\", \"MPI_VERSION\"),\n        (\"void*\", \"MPI_IN_PLACE\"),\n]\n\ndef get_args(f, counts=False):\n    args = []\n    for arg in f[2:]:\n        has_count = ':' in arg\n        if has_count:\n            s, count = arg.split(':')\n            count = int(count)\n        else:\n            s = arg\n            count = None\n        if s.startswith(\"MPI_\"):\n            s = \"NG_\" + s\n        if counts:\n            args.append((s, count))\n        else:\n            args.append(s)\n    return args\n\ndef generate_declarations():\n    code = \"\"\n    nowrapper_code = \"\"\n    for f in functions:\n        ret = f[0]\n        name = f[1]\n        args = \", \".join(get_args(f))\n        code += f\"NGCORE_API extern {ret} (*NG_{name})({args});\\n\"\n        nowrapper_code += f\"#define NG_{name} {name}\\n\"\n\n    for typ, name in constants:\n        if typ.startswith(\"MPI_\"):\n            typ = \"NG_\" + typ\n        code += f\"NGCORE_API extern {typ} NG_{name};\\n\"\n        nowrapper_code += f\"#define NG_{name} {name}\\n\"\n\n    with open(\"ng_mpi_generated_declarations.hpp\", \"w\") as f:\n        f.write(\"#ifdef NG_MPI_WRAPPER\\n\")\n        f.write(code)\n        f.write(\"#else  // NG_MPI_WRAPPER\\n\")\n        f.write(nowrapper_code)\n        f.write(\"#endif // NG_MPI_WRAPPER\\n\")\n\ndef generate_dummy_init():\n    code = \"\"\n    for f in functions:\n        ret = f[0]\n        name = f[1]\n        args = \", \".join(get_args(f))\n        code += f\"decltype(NG_{name}) NG_{name} = []({args})->{ret} {{ throw no_mpi(); }};\\n\"\n\n    for typ, name in constants:\n        if typ.startswith(\"MPI_\"):\n            typ = \"NG_\" + typ\n        code += f\"{typ} NG_{name} = 0;\\n\"\n\n    with open(\"ng_mpi_generated_dummy_init.hpp\", \"w\") as f:\n        f.write(code)\n\ndef generate_init():\n    code = \"\"\n    for f in functions:\n        ret = f[0]\n        name = f[1]\n        args = get_args(f, counts=True)\n        in_args  =''\n        call_args = ''\n        for i in range(len(args)):\n            arg, count = args[i]\n            if i > 0:\n                in_args += ', '\n                call_args += ', '\n            in_args += arg + f\" arg{i}\"\n            if not arg.startswith(\"NG_\"):\n                # plain type (like int, int *, etc.), just pass the argument along\n                call_args += f\" arg{i}\"\n            elif count is None:\n                # MPI type (by value or pointer), but just one object, no arrays\n                call_args += f\" ng2mpi(arg{i})\"\n            else:\n                # arrays of MPI types, we need to copy them due to incompatible size\n                call_args += f\" ng2mpi(arg{i}, arg{count})\"\n        code += f\"NG_{name} = []({in_args})->{ret} {{ return {name}({call_args}); }};\\n\"\n\n    for _, name in constants:\n        code += f\"NG_{name} = mpi2ng({name});\\n\"\n\n    with open(\"ng_mpi_generated_init.hpp\", \"w\") as f:\n        f.write(code)\n\nif __name__ == \"__main__\":\n    generate_declarations()\n    generate_dummy_init()\n    generate_init()\n"
  },
  {
    "path": "libsrc/core/hashtable.hpp",
    "content": "#ifndef FILE_NGSTD_HASHTABLE\n#define FILE_NGSTD_HASHTABLE\n\n/**************************************************************************/\n/* File:   hashtable.hpp                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <string>\n#include <tuple>\n#include <optional>\n\n// #include \"mpi_wrapper.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"table.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n\n\n  template <int K> \n  class MakeTupleFromInt\n  {\n  public:\n    template <typename I>\n    auto operator()(I & i)\n    { return tuple_cat(MakeTupleFromInt<K-1> ()(i), std::tie(i[K-1])); }\n  };\n  \n  template <> \n  class MakeTupleFromInt<1>\n  {\n  public:\n    template <typename I>\n    auto operator()(I & i) { return std::tie(i[0]); }\n  };\n  \n  \n\n  // feature check macro for transition from INT to IVec\n#define NGCORE_HAS_IVEC\n  \n  /// N integers\n  template <int N, typename T = int>\n  class IVec\n  {\n    /// data\n    // T i[(N>0)?N:1];\n\n    HTArray<N,T> i;\n    \n  public:\n    ///\n    constexpr IVec () = default;\n    constexpr NETGEN_INLINE IVec (const IVec & i1) : i(i1.i) { }\n\n    constexpr NETGEN_INLINE IVec (T ai1) : i(ai1) { }\n    \n    template <class... T2,\n              std::enable_if_t<N==1+sizeof...(T2),bool> = true>\n    constexpr IVec (const T &v, T2... rest)\n      : i{v,rest...} { } \n\n    /*\n    /// init all\n    NETGEN_INLINE IVec (T ai1)\n    { \n     for (int j = 0; j < N; j++) { i[j] = ai1; }\n    }\n\n    /// init i[0], i[1]\n    constexpr NETGEN_INLINE IVec (T ai1, T ai2)\n      : i{ai1, ai2} { ; } \n\n    /// init i[0], i[1], i[2]\n    constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3)\n      : i{ai1, ai2, ai3} { ; } \n\n    /// init i[0], i[1], i[2]\n    constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4)\n      : i{ai1, ai2, ai3, ai4} { ; }\n    \n    /// init i[0], i[1], i[2]\n    constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5)\n      : i{ai1, ai2, ai3, ai4, ai5} { ; }      \n      \n    /// init i[0], i[1], i[2]\n    NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)\n      : i{ai1, ai2, ai3, ai4, ai5, ai6, ai7, ai8, ai9 } { ; }            \n    */\n    \n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE& ar)\n    {\n      // ar.Do(i.begin(), N);\n      ar.Do(i.Ptr(), N);\n    }\n\n    template <int N2, typename T2>\n    NETGEN_INLINE IVec (const IVec<N2,T2> & in2)\n    {\n      if (N2 <= N)\n        {\n          for (int j = 0; j < N2; j++)\n            i[j] = in2[j];\n          for (int j = N2; j < N; j++)\n            i[j] = 0;\n        }\n      else\n        {\n          for (int j = 0; j < N; j++)\n            i[j] = in2[j];\n        }\n    }\n\n    template <typename T2>\n    NETGEN_INLINE IVec (const BaseArrayObject<T2> & ao)\n    {\n      for (int j = 0; j < N; j++)\n        i[j] = ao.Spec()[j];\n    }\n    \n    NETGEN_INLINE size_t Size() const { return N; }\n    /// all ints equal ?\n    NETGEN_INLINE bool operator== (const IVec & in2) const\n    { \n      for (int j = 0; j < N; j++) \n\tif (i[j] != in2.i[j]) return 0;\n      return 1; \n    }\n\n    /// any ints unequal ?\n    NETGEN_INLINE bool operator!= (const IVec & in2) const\n    {\n      for (int j = 0; j < N; j++)\n        if (i[j] != in2.i[j]) return 1;\n      return 0;\n    }\n\n    /// sort integers\n    NETGEN_INLINE IVec & Sort () & \n    {\n      for (int k = 0; k < N; k++)\n\tfor (int l = k+1; l < N; l++)\n\t  if (i[k] > i[l]) \n\t    Swap (i[k], i[l]);\n      return *this;\n    }\n\n    NETGEN_INLINE IVec Sort () &&\n    {\n      for (int k = 0; k < N; k++)\n\tfor (int l = k+1; l < N; l++)\n\t  if (i[k] > i[l]) \n\t    Swap (i[k], i[l]);\n      return *this;\n    }\n\n    /// access\n    NETGEN_INLINE T & operator[] (int j)\n    { return i[j]; }\n\n    /// access\n    NETGEN_INLINE constexpr const T & operator[] (int j) const\n    { return i[j]; }\n\n    template <size_t J>\n    constexpr T get() const { return i[J]; }\n    \n    operator FlatArray<T> () { return FlatArray<T> (N, i.Ptr()); }\n\n    NETGEN_INLINE IVec<N,T> & operator= (T value)\n    {\n      for (int j = 0; j < N; j++)\n\ti[j] = value;\n      return *this;\n    }\n\n    template <typename T2>\n    NETGEN_INLINE IVec<N,T> & operator= (IVec<N,T2> v2)\n    {\n      for (int j = 0; j < N; j++)\n\ti[j] = v2[j];\n      return *this;\n    }\n\n    template <typename... Ts>\n    operator std::tuple<Ts...> ()\n    {\n      return MakeTupleFromInt<N>()(*this);\n    }\n\n    bool Contains (T val)\n    {\n      for (int j = 0; j < N; j++)\n        if (i[j] == val) return true;\n      return false;\n    }\n  };\n\n  /// sort 2 integers\n  template <>\n  NETGEN_INLINE IVec<2> & IVec<2>::Sort () & \n  {\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    return *this;\n  }\n\n  template <>\n  NETGEN_INLINE IVec<2> IVec<2>::Sort () &&\n  {\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    return *this;\n  }\n\n  /// sort 3 integers\n  template <>\n  NETGEN_INLINE IVec<3> IVec<3>::Sort () &&\n  {\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    if (i[1] > i[2]) Swap (i[1], i[2]);\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    return *this;\n  }\n\n  /// Print integers\n  template <int N, typename T>\n  inline ostream & operator<<(ostream  & s, const IVec<N,T> & i2)\n  {\n    for (int j = 0; j < N; j++)\n      s << (int) i2[j] << \" \";\n    return s;\n  }\n  \n  template <int N, typename T>\n  auto begin(const IVec<N,T> & ind)\n  {\n    return AOWrapperIterator<IVec<N,T>> (ind, 0);\n  }\n\n  template <int N, typename T>\n  auto end(const IVec<N,T> & ind)\n  {\n    return AOWrapperIterator<IVec<N,T>> (ind, N);    \n  }\n\n\n\n\n\n  \n  template <int N, typename TI>\n  NETGEN_INLINE size_t HashValue (const IVec<N,TI> & ind, size_t size)\n  {\n    IVec<N,size_t> lind = ind;    \n    size_t sum = 0;\n    for (int i = 0; i < N; i++)\n      sum += lind[i];\n    return sum % size;\n  }\n\n  /// hash value of 1 int\n  template <typename TI>\n  NETGEN_INLINE size_t HashValue (const IVec<1,TI> & ind, size_t size) \n  {\n    return ind[0] % size;\n  }\n\n  /// hash value of 2 int\n  template <typename TI>  \n  NETGEN_INLINE size_t HashValue (const IVec<2,TI> & ind, size_t size) \n  {\n    IVec<2,size_t> lind = ind;\n    return (113*lind[0]+lind[1]) % size;\n  }\n\n  /// hash value of 3 int\n  template <typename TI>    \n  NETGEN_INLINE size_t HashValue (const IVec<3,TI> & ind, size_t size) \n  {\n    IVec<3,size_t> lind = ind;\n    return (113*lind[0]+59*lind[1]+lind[2]) % size;\n  }\n\n  NETGEN_INLINE size_t HashValue (size_t ind, size_t size)\n  {\n    return ind%size;\n  }\n  NETGEN_INLINE size_t HashValue (int ind, size_t size)\n  {\n    return size_t(ind)%size;\n  }\n  \n\n\n\n\n\n  \n  template <int N, typename TI>\n  NETGEN_INLINE constexpr size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)\n  {\n    IVec<N,size_t> lind = ind;    \n    size_t sum = 0;\n    for (int i = 0; i < N; i++)\n      sum += lind[i];\n    return sum & mask;\n  }\n\n  /// hash value of 1 int\n  template <typename TI>\n  NETGEN_INLINE constexpr size_t HashValue2 (const IVec<1,TI> & ind, size_t mask) \n  {\n    return ind[0] & mask;\n  }\n\n  /// hash value of 2 int\n  template <typename TI>  \n  NETGEN_INLINE constexpr size_t HashValue2 (const IVec<2,TI> & ind, size_t mask) \n  {\n    IVec<2,size_t> lind = ind;\n    return (113*lind[0]+lind[1]) & mask;\n  }\n\n  /// hash value of 3 int\n  template <typename TI>    \n  NETGEN_INLINE constexpr size_t HashValue2 (const IVec<3,TI> & ind, size_t mask) \n  {\n    IVec<3,size_t> lind = ind;\n    return (113*lind[0]+59*lind[1]+lind[2]) & mask;\n  }\n\n  NETGEN_INLINE constexpr size_t HashValue2 (size_t ind, size_t mask)\n  {\n    return ind & mask;\n  }\n  NETGEN_INLINE constexpr size_t HashValue2 (int ind, size_t mask)\n  {\n    return size_t(ind) & mask;\n  }\n  \n\n\n\n  \n  // using ngstd::max;\n\n  template <int D, typename T>\n  NETGEN_INLINE T Max (const IVec<D,T> & i)\n  {\n    if (D == 0) return 0;\n    T m = i[0];\n    for (int j = 1; j < D; j++)\n      if (i[j] > m) m = i[j];\n    return m;\n  }\n\n  template <int D, typename T>\n  NETGEN_INLINE T Min (const IVec<D,T> & i)\n  {\n    if (D == 0) return 0;\n    T m = i[0];\n    for (int j = 1; j < D; j++)\n      if (i[j] < m) m = i[j];\n    return m;\n  }\n\n  template <int D, typename T>\n  NETGEN_INLINE IVec<D,T> Max (IVec<D,T> i1, IVec<D,T> i2)\n  {\n    IVec<D,T> tmp;\n    for (int i = 0; i < D; i++)\n      tmp[i] = std::max(i1[i], i2[i]);\n    return tmp;\n  }\n\n  template <int D, typename T>\n  NETGEN_INLINE IVec<D,T> operator+ (IVec<D,T> i1, IVec<D,T> i2)\n  {\n    IVec<D,T> tmp;\n    for (int i = 0; i < D; i++)\n      tmp[i] = i1[i]+i2[i];\n    return tmp;\n  }\n  \n\n\n\n\n\n\n\n\n\n\n  /**\n     A hash-table.\n     Generic identifiers are mapped to the generic type T.\n     An open hashtable. The table is implemented by a DynamicTable.\n     Identifiers must provide a HashValue method.\n  */\n  template <class T_HASH, class T>\n  class HashTable\n  {\n    /*\n    DynamicTable<T_HASH> hash;\n    DynamicTable<T> cont;\n    */\n    DynamicTable<std::pair<T_HASH,T>> table;\n  public:\n    /// Constructs a hashtable of size bags.\n    NETGEN_INLINE HashTable (int size)\n    // : hash(size), cont(size)\n      : table(size)\n    { ; }\n    NETGEN_INLINE ~HashTable () { ; }\n\n    /// Sets identifier ahash to value acont\n    void Set (const T_HASH & ahash, const T & acont)\n    {\n      int bnr = HashValue (ahash, Size());\n      int pos = CheckPosition (bnr, ahash);\n      if (pos != -1)\n\t// cont.Set (bnr, pos, acont);\n        table[bnr][pos].second = acont;\n      else\n\t{\n\t  // hash.Add (bnr, ahash);\n\t  // cont.Add (bnr, acont);\n          table.Add (bnr, std::make_pair(ahash, acont));\n\t}        \n    }\n\n    /// get value of identifier ahash, exception if unused\n    const T & Get (const T_HASH & ahash) const\n    {\n      int bnr = HashValue (ahash, Size());\n      int pos = Position (bnr, ahash);\n      // return cont.Get (bnr, pos);\n      return table.Get (bnr, pos).second;\n    }\n\n    /// get value of identifier ahash, exception if unused\n    const T & Get (int bnr, int pos) const\n    {\n      // return cont.Get (bnr, pos);\n      return table.Get (bnr, pos).second;\n    }\n\n    /// is identifier used ?\n    bool Used (const T_HASH & ahash) const\n    {\n      // return (CheckPosition (HashValue (ahash, hash.Size()), ahash) != -1);\n      return (CheckPosition (HashValue (ahash, table.Size()), ahash) != -1);\n    }\n\n    /// is identifier used ?\n    bool Used (const T_HASH & ahash, int & bnr, int & pos) const\n    {\n      // bnr = HashValue (ahash, hash.Size());\n      bnr = HashValue (ahash, Size());\n      pos = CheckPosition (bnr, ahash);\n      return (pos != -1);\n    }\n\n\n    /// number of hash entries\n    size_t Size () const\n    {\n      // return hash.Size();\n      return table.Size();\n    }\n\n    /// size of hash entry\n    size_t EntrySize (int bnr) const\n    {\n      // return hash[bnr].Size();\n      return table[bnr].Size();\n    }\n\n    /// get identifier and value of entry bnr, position colnr\n    void GetData (int bnr, int colnr, T_HASH & ahash, T & acont) const\n    {\n      // ahash = hash[bnr][colnr];\n      // acont = cont[bnr][colnr];\n      ahash = table[bnr][colnr].first;\n      acont = table[bnr][colnr].second;\n    }\n\n    /// set identifier and value of entry bnr, position colnr\n    void SetData (int bnr, int colnr, const T_HASH & ahash, const T & acont)\n    {\n      // hash[bnr][colnr] = ahash;\n      // cont[bnr][colnr] = acont;\n      table[bnr][colnr] = std::make_pair(ahash, acont);\n    }    \n\n    /// returns position of index. returns -1 on unused\n    int CheckPosition (int bnr, const T_HASH & ind) const\n    {\n      /*\n      for (int i = 0; i < hash[bnr].Size(); i++)\n\tif (hash[bnr][i] == ind)\n\t  return i;\n      */\n      for (int i = 0; i < table[bnr].Size(); i++)\n\tif (table[bnr][i].first == ind)\n\t  return i;\n      return -1;\n    }\n\n    /// returns position of index. exception on unused\n    int Position (int bnr, const T_HASH & ind) const\n    {\n      for (int i = 0; i < table[bnr].Size(); i++)\n\tif (table[bnr][i].first == ind)\n\t  return i;\n      throw Exception (\"Ask for unused hash-value\");\n    }\n\n    T & operator[] (T_HASH ahash)\n    {\n      int bnr, pos;\n      if (Used (ahash, bnr, pos))\n        return table[bnr][pos].second;\n      else\n        {\n\t  // hash.Add (bnr, ahash);\n\t  // cont.Add (bnr, T(0));\n          table.Add (bnr, std::make_pair(ahash, T(0)));\n          // return cont[bnr][cont[bnr].Size()-1];\n          return table[bnr][table[bnr].Size()-1].second;\n        }\n    }\n\n    const T & operator[] (T_HASH ahash) const\n    {\n      return Get(ahash);\n    }\n\n    class Iterator\n    {\n      const HashTable & ht;\n      int bnr;\n      int pos;\n    public:\n      Iterator (const HashTable & aht, int abnr, int apos)\n        : ht(aht), bnr(abnr), pos(apos) { ; }\n      std::pair<T_HASH,T> operator* () const\n      {\n        T_HASH hash; \n        T data;\n        ht.GetData (bnr, pos, hash, data);\n        return std::pair<T_HASH,T> (hash, data);\n      }\n\n      Iterator & operator++() \n      {\n        pos++;\n        if (pos == ht.EntrySize(bnr))\n          {\n            pos = 0;\n            bnr++;\n            for ( ; bnr < ht.Size(); bnr++)\n              if (ht.EntrySize(bnr) != 0) break;\n          }\n        return *this;\n      }\n      \n      bool operator!= (const Iterator & it2) { return bnr != it2.bnr || pos != it2.pos; }\n    };\n\n    Iterator begin () const \n    {\n      int i = 0;\n      for ( ; i < Size(); i++)\n        if (EntrySize(i) != 0) break;\n      return Iterator(*this, i,0); \n    }\n    Iterator end () const { return Iterator(*this, Size(),0); }\n  };\n\n\n\n  inline size_t RoundUp2 (size_t i)\n  {\n    size_t res = 1;\n    while (res < i) res *= 2; // hope it will never be too large \n    return res; \n  }\n\n  template <typename T>\n  constexpr inline T InvalidHash() { return T(-1); }\n\n  template <typename T_HASH>\n  struct CHT_trait\n  {\n    constexpr static inline T_HASH Invalid() { return InvalidHash<T_HASH>(); }\n    constexpr static inline size_t HashValue (const T_HASH & hash, size_t mask) { return HashValue2(hash, mask); }\n  };\n\n  template <typename T1, typename T2>\n  struct CHT_trait<std::tuple<T1,T2>>\n  {\n    constexpr static inline std::tuple<T1,T2> Invalid() { return { CHT_trait<T1>::Invalid(), CHT_trait<T2>::Invalid() } ; }\n    constexpr static inline size_t HashValue (const std::tuple<T1,T2> & hash, size_t mask)\n    {\n      return (CHT_trait<T1>::HashValue(std::get<0>(hash), mask) + CHT_trait<T2>::HashValue(std::get<1>(hash),mask)) & mask;\n    }\n  };\n\n  \n\n  /**\n     A closed hash-table.\n     All information is stored in one fixed array.\n     The array should be allocated with the double size of the expected number of entries.\n  */\n  template <class T_HASH, class T>\n  class ClosedHashTable\n  {\n  protected:\n    ///\n    size_t size;\n    size_t mask;\n    ///\n    size_t used = 0;\n    ///\n    Array<T_HASH> hash;\n    ///\n    Array<T> cont;\n    ///\n    // T_HASH invalid = -1;\n    // static constexpr T_HASH invalid = InvalidHash<T_HASH>();\n    static constexpr T_HASH invalid = CHT_trait<T_HASH>::Invalid();\n  public:\n    ///\n    ClosedHashTable (size_t asize = 128)\n      : size(RoundUp2(asize)), hash(size), cont(size)\n    {\n      mask = size-1;\n      // hash = T_HASH(invalid);\n      // hash = InvalidHash<T_HASH>();\n      hash = CHT_trait<T_HASH>::Invalid();\n    }\n\n    ClosedHashTable (ClosedHashTable && ht2) = default;\n\n    /// allocate on local heap\n    ClosedHashTable (size_t asize, LocalHeap & lh)\n      : size(RoundUp2(asize)), mask(size-1), hash(size, lh), cont(size, lh)\n    {\n      // hash = T_HASH(invalid);\n      hash = InvalidHash<T_HASH>();\n    }\n\n    ClosedHashTable & operator= (ClosedHashTable && ht2) = default;\n\n    /// \n    size_t Size() const\n    {\n      return size;\n    }\n\n    /// is position used\n    bool UsedPos (size_t pos) const\n    {\n      return ! (hash[pos] == invalid); \n    }\n\n    /// number of used elements\n    size_t UsedElements () const\n    {\n      return used;\n    }\n\n    size_t Position (const T_HASH ind) const\n    {\n      // size_t i = HashValue2(ind, mask);\n      size_t i = CHT_trait<T_HASH>::HashValue(ind, mask);\n      while (true)\n\t{\n\t  if (hash[i] == ind) return i;\n\t  if (hash[i] == invalid) return size_t(-1);\n          i = (i+1) & mask;          \n\t}\n    }\n\n    void DoubleSize()\n    {\n      ClosedHashTable tmp(2*Size());\n      for (auto both : *this)\n        tmp[both.first] = both.second;\n      *this = std::move(tmp);\n    }\n    \n    // returns true if new position is created\n    bool PositionCreate (const T_HASH ind, size_t & apos)\n    {\n      if (UsedElements()*2 > Size()) DoubleSize();\n      \n      // size_t i = HashValue2 (ind, mask);\n      size_t i = CHT_trait<T_HASH>::HashValue (ind, mask);\n\n      while (true)\n\t{\n\t  if (hash[i] == invalid)\n\t    { \n\t      hash[i] = ind; \n\t      apos = i;\n              used++;\n\t      return true;\n\t    }\n\t  if (hash[i] == ind) \n\t    { \n\t      apos = i; \n\t      return false; \n\t    }\n          i = (i+1) & mask;\n\t}\n    }\n\n\n    ///\n    void Set (const T_HASH & ahash, const T & acont)\n    {\n      size_t pos;\n      PositionCreate (ahash, pos);\n      hash[pos] = ahash;\n      cont[pos] = acont;\n    }\n\n    ///\n    const T & Get (const T_HASH & ahash) const\n    {\n      size_t pos = Position (ahash);\n      if (pos == size_t(-1))\n        throw Exception (std::string(\"illegal key: \") + ToString(ahash) );\n      return cont[pos];\n    }\n\n    ///\n    bool Used (const T_HASH & ahash) const\n    {\n      return (Position (ahash) != size_t(-1));\n    }\n\n    inline std::optional<T> GetIfUsed (const T_HASH & ahash) const\n    {\n      size_t pos = Position (ahash);\n      if (pos != size_t(-1))\n        return cont[pos];\n      else\n        return std::nullopt;\n    }\n    \n\n    void SetData (size_t pos, const T_HASH & ahash, const T & acont)\n    {\n      hash[pos] = ahash;\n      cont[pos] = acont;\n    }\n\n    void GetData (size_t pos, T_HASH & ahash, T & acont) const\n    {\n      ahash = hash[pos];\n      acont = cont[pos];\n    }\n  \n    void SetData (size_t pos, const T & acont)\n    {\n      cont[pos] = acont;\n    }\n\n    void GetData (size_t pos, T & acont) const\n    {\n      acont = cont[pos];\n    }\n\n    T GetData (size_t pos) const\n    {\n      return cont[pos];\n    }\n\n    std::pair<T_HASH,T> GetBoth (size_t pos) const\n    {\n      return std::pair<T_HASH,T> (hash[pos], cont[pos]);\n    }\n\n    const T & operator[] (T_HASH key) const { return Get(key); }\n    T & operator[] (T_HASH key)\n    {\n      size_t pos;\n      PositionCreate(key, pos);\n      return cont[pos];\n    }\n    \n    void SetSize (size_t asize)\n    {\n      size = asize;\n      hash.Alloc(size);\n      cont.Alloc(size);\n\n      // for (size_t i = 0; i < size; i++)\n      // hash[i] = invalid;\n      hash = T_HASH(invalid);\n    }\n\n    void Delete (T_HASH key)\n    {\n      size_t pos = Position(key);\n      if (pos == size_t(-1)) return;\n      hash[pos] = invalid; used--;\n      \n      while (1)\n        {\n          size_t nextpos = pos+1;\n          if (nextpos == size) nextpos = 0;\n          if (hash[nextpos] == invalid) break;\n          \n          auto key = hash[nextpos];\n          auto val = cont[nextpos];\n          hash[pos] = invalid; used--;\n          \n          Set (key, val);\n          pos = nextpos;\n        }\n    }\n\n    void DeleteData()\n    {\n      hash = T_HASH(invalid);\n      used = 0;\n    }\n\n    template <typename ARCHIVE>\n    void DoArchive (ARCHIVE& ar)\n    {\n      ar & hash & cont;\n      ar & size & mask & used;\n    }    \n\n    struct EndIterator { };\n    \n    class Iterator\n    {\n      const ClosedHashTable & tab;\n      size_t nr;\n    public:\n      Iterator (const ClosedHashTable & _tab, size_t _nr)\n        : tab(_tab), nr(_nr)\n      {\n        while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;\n      }\n      Iterator & operator++()\n      {\n        nr++;\n        while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;\n        return *this;\n      }\n\n      bool operator!= (EndIterator it2) { return nr != tab.Size(); }\n      \n      auto operator* () const { return tab.GetBoth(nr); }\n    };\n\n    Iterator begin() const { return Iterator(*this, 0); }\n    EndIterator end() const { return EndIterator(); }\n  };\n\n  template <class T_HASH, class T>  \n  ostream & operator<< (ostream & ost,\n                        const ClosedHashTable<T_HASH,T> & tab)\n  {\n    /*\n    for (size_t i = 0; i < tab.Size(); i++)\n      if (tab.UsedPos(i))\n        {\n          T_HASH key;\n          T val;\n          tab.GetData (i, key, val);\n          ost << key << \": \" << val << \", \";\n        }\n    */\n    for (auto [key,val] : tab)\n      ost << key << \": \" << val << \", \";      \n    return ost;\n  }\n\n  template <typename TI>\n  NETGEN_INLINE size_t HashValue (const IVec<3,TI> ind)\n  {\n    IVec<3,size_t> lind = ind;\n    return 113*lind[0]+59*lind[1]+lind[2];\n  }\n\n  template <typename TI>  \n  NETGEN_INLINE size_t HashValue (const IVec<2,TI> ind)\n  {\n    IVec<2,size_t> lind = ind;\n    return 113*lind[0]+lind[1];\n  }\n\n  template <typename TI>  \n  NETGEN_INLINE size_t HashValue (const IVec<1,TI> ind)\n  {\n    return ind[0];\n  }\n\n\n  template <typename TKEY, typename T>\n  class ParallelHashTable\n  {\n    class ClosedHT\n    {\n      Array<TKEY> keys;\n      Array<T> values;\n      size_t used;\n      \n    public:\n      ClosedHT(size_t asize = 256) : keys(asize), values(asize), used(0)\n      {\n        keys = TKEY(-1);\n      }\n\n      size_t Size () const { return keys.Size(); }\n      size_t Used () const { return used; }\n\n      ClosedHT & operator= (ClosedHT&&) = default;\n\n      void Resize()\n      {\n        ClosedHT tmp(keys.Size()*2);\n        for (size_t i = 0; i < keys.Size(); i++)\n          if (keys[i] != TKEY(-1))\n            {\n              TKEY hkey = keys[i];\n              T hval = values[i];\n              size_t hhash = HashValue(hkey);\n              size_t hhash2 = hhash / 256;\n              tmp.DoSave(hkey, [hval] (T & v) { v = hval; }, hhash2);\n            }\n        (*this) = std::move(tmp);\n      }\n      \n      template <typename TFUNC>\n      auto Do (TKEY key, TFUNC func, size_t hash)\n      {\n        if (used > keys.Size()/2)\n          Resize();\n        return DoSave (key, func, hash);\n      }\n      \n      template <typename TFUNC>\n      auto DoSave (TKEY key, TFUNC func, size_t hash)\n      {\n        size_t pos = hash & (keys.Size()-1);\n        while (1)\n          {\n            if (keys[pos] == key)\n              break;\n            if (keys[pos] == TKEY(-1))\n              {\n                keys[pos] = key;\n                values[pos] = T(0);\n                used++;\n                break;\n              }\n            pos++;\n            if (pos == keys.Size()) pos = 0;\n          }\n        return func(values[pos]);\n      }\n      \n      T Get (TKEY key, size_t hash)\n      {\n        size_t pos = hash & (keys.Size()-1);\n        while (1)\n          {\n            if (keys[pos] == key)\n              return values[pos];\n            if (keys[pos] == TKEY(-1))\n              throw Exception (\"ParallelHashTable::Get of unused key\");\n            pos++;\n            if (pos == keys.Size()) pos = 0;\n          }\n      }\n\n      size_t GetCosts (TKEY key, size_t hash)\n      {\n        size_t pos = hash & (keys.Size()-1);\n        size_t costs = 1;\n        while (1)\n          {\n            if (keys[pos] == key)\n              return costs;\n            if (keys[pos] == TKEY(-1))\n              throw Exception (\"ParallelHashTable::Get of unused key\");\n            costs++;\n            pos++;\n            if (pos == keys.Size()) pos = 0;\n          }\n      }\n\n\n      template <typename TFUNC>\n      void Iterate (TFUNC func) const\n      {\n        for (size_t i = 0; i < keys.Size(); i++)\n          if (keys[i] != TKEY(-1))\n            func(keys[i], values[i]);\n      }\n        \n      void Print (ostream & ost) const\n      {\n        for (size_t i = 0; i < keys.Size(); i++)\n          if (keys[i] != TKEY(-1))\n            ost << keys[i] << \": \" << values[i] << \", \";\n      }\n    };\n\n    Array<ClosedHT> hts;\n    class alignas(64) MyMutex64 : public MyMutex { };\n    \n    Array<MyMutex64> locks;\n\n  public:\n    ParallelHashTable() : hts(256), locks(256) { ; }\n    size_t NumBuckets() const { return hts.Size(); }\n    auto & Bucket(size_t nr) { return hts[nr]; }\n    size_t BucketSize(size_t nr) const { return hts[nr].Size(); }\n    size_t Used (size_t nr) const { return hts[nr].Used(); } \n    size_t Used() const\n    {\n      size_t used = 0;\n      for (auto & ht : hts)\n        used += ht.Used();\n      return used;\n    }  \n    template <typename TFUNC>\n    auto Do (TKEY key, TFUNC func)\n    {\n      size_t hash = HashValue(key);\n      size_t hash1 = hash % 256;\n      size_t hash2 = hash / 256;\n      \n      // locks[hash1].lock();\n      // hts[hash1].Do (key, func, hash2);\n      // locks[hash1].unlock();\n      MyLock lock(locks[hash1]);\n      return hts[hash1].Do (key, func, hash2);\n    }\n    \n    T Get (TKEY key)\n    {\n      size_t hash = HashValue(key);\n      size_t hash1 = hash % 256;\n      size_t hash2 = hash / 256;\n      \n      return hts[hash1].Get (key, hash2);\n    }\n\n    auto GetCosts (TKEY key)\n    {\n      size_t hash = HashValue(key);\n      size_t hash1 = hash % 256;\n      size_t hash2 = hash / 256;\n      \n      return hts[hash1].GetCosts (key, hash2);\n    }\n\n    \n    template <typename TFUNC>\n    void Iterate(TFUNC func) const\n    {\n      for (auto & bucket : hts)\n        bucket.Iterate(func);\n    }\n\n    template <typename TFUNC>\n    void Iterate(size_t nr, TFUNC func) const\n    {\n      hts[nr].Iterate(func);\n    }\n\n\n    template <typename FUNC>\n    void IterateParallel (FUNC func)\n    {\n      Array<size_t> base(NumBuckets());\n      size_t sum = 0;\n      for (size_t i = 0; i < NumBuckets(); i++)\n        {\n          base[i] = sum;\n          sum += Used(i); \n        }\n      ParallelFor(NumBuckets(),\n                  [&] (size_t nr)\n                  {\n                    size_t cnt = base[nr];\n                    Iterate(nr,\n                            [&cnt, func] (TKEY key, T val)\n                            {\n                              func(cnt, key, val);\n                              cnt++;\n                            });\n                  });\n    }\n    \n\n    \n\n    void Print (ostream & ost) const\n    {\n      for (size_t i : Range(hts))\n        if (hts[i].Used() > 0)\n          {\n            ost << i << \": \";\n            hts[i].Print(ost);\n          }\n    }\n  };\n\n  template <typename TKEY, typename T>\n  inline ostream & operator<< (ostream & ost, const ParallelHashTable<TKEY,T> & ht)\n  {\n    ht.Print(ost);\n    return ost;\n  }\n\n\n\n\n\n\n\n\n\n  template <class T, class IndexType>\n  class CompressedTable\n  {\n    Table<T, size_t> table;\n    ClosedHashTable<IndexType, size_t> idmap;\n    \n  public:\n    CompressedTable (Table<T, size_t> && atable, ClosedHashTable<IndexType, size_t> && aidmap)\n      : table(std::move(atable)), idmap(std::move(aidmap)) { }\n\n    FlatArray<T> operator[](IndexType id) const\n    {\n      if (auto nr = idmap.GetIfUsed(id))\n        return table[*nr];\n      else\n        return { 0, nullptr };\n    }\n    auto & GetTable() { return table; }\n  };\n\n\n  template <class T, typename IndexType>\n  class CompressedTableCreator\n  {\n  protected:\n    int mode;    // 1 .. cnt, 2 .. cnt entries, 3 .. fill table\n    size_t nd;   // number of entries;\n    ClosedHashTable<IndexType, size_t> idmap;\n    Array<int,size_t> cnt;\n    Table<T,size_t> table;\n  public:\n    CompressedTableCreator()\n    { nd = 0; mode = 1; }\n\n    CompressedTable<T,IndexType> MoveTable()\n    {\n      return { std::move(table), std::move(idmap) };\n    }\n\n    bool Done () { return mode > 3; }\n    void operator++(int) { SetMode (mode+1); }\n\n    int GetMode () const { return mode; }\n    void SetMode (int amode)\n    {\n      mode = amode;\n      if (mode == 2)\n\t{\n          cnt.SetSize(nd);  \n          cnt = 0;\n\t}\n      if (mode == 3)\n\t{\n          table = Table<T,size_t> (cnt);\n          cnt = 0;\n\t}\n    }\n\n    void Add (IndexType blocknr, const T & data)\n    {\n      switch (mode)\n\t{\n\tcase 1:\n          {\n            if (!idmap.Used (blocknr))\n              idmap[blocknr] = nd++;\n            break;\n          }\n\tcase 2:\n\t  cnt[idmap.Get(blocknr)]++;\n\t  break;\n\tcase 3:\n          size_t cblock = idmap.Get(blocknr);\n          int ci = cnt[cblock]++;\n          table[cblock][ci] = data;\n\t  break;\n\t}\n    }\n  };\n\n\n  \n\n\n\n\n\n\n\n\n\n  \n} // namespace ngcore\n\n\n/*\n#ifdef PARALLEL\nnamespace ngcore {\n  template<int S, typename T>\n  class MPI_typetrait<ngcore::IVec<S, T> >\n  {\n  public:\n    /// gets the MPI datatype\n    static MPI_Datatype MPIType () \n    { \n      static MPI_Datatype MPI_T = 0;\n      if (!MPI_T)\n\t{\n\t  MPI_Type_contiguous ( S, MPI_typetrait<T>::MPIType(), &MPI_T);\n\t  MPI_Type_commit ( &MPI_T );\n\t}\n      return MPI_T;\n    }\n  };\n}\n#endif\n*/\n\nnamespace ngcore\n{\n  template<typename T> struct MPI_typetrait;\n  \n  template<int S, typename T>\n  struct MPI_typetrait<IVec<S, T> > {\n    static auto MPIType () {\n      return MPI_typetrait<std::array<T,S>>::MPIType();\n    }\n  };\n}\n\n\n\nnamespace std\n{\n  // structured binding support\n  template <auto N, typename T>\n  struct tuple_size<ngcore::IVec<N,T>> : std::integral_constant<std::size_t, N> {};\n  template<size_t N, auto M, typename T> struct tuple_element<N,ngcore::IVec<M,T>> { using type = T; };\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/core/localheap.cpp",
    "content": "/**************************************************************************/\n/* File:   localheap.cpp                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   19. Apr. 2002                                                  */\n/**************************************************************************/\n\n#include <exception>\n#include <string>\n\n#include \"localheap.hpp\"\n#include \"taskmanager.hpp\"\n\nnamespace ngcore\n{\n\n  LocalHeap :: LocalHeap (size_t asize, const char * aname, bool mult_by_threads)\n  {\n    if (mult_by_threads)\n      asize *= TaskManager::GetMaxThreads();\n    totsize = asize;\n    try\n      {\n        data = new char[asize];\n      }\n    catch (std::exception & e)\n      {\n        throw Exception (ToString (\"Could not allocate localheap, heapsize = \") + ToString(asize));\n      }\n\n    next = data + totsize;\n    p = data;\n    owner = true;\n    name = aname;\n    CleanUp();   // align pointer\n  }\n\n  LocalHeap LocalHeap :: Split() const\n  {\n    int pieces = TaskManager::GetNumThreads();\n    int i = TaskManager::GetThreadId();\n    size_t freemem = totsize - (p - data);\n    size_t size_of_piece = freemem / pieces;\n    return LocalHeap (p + i * size_of_piece, size_of_piece, name);\n  }\n\n  void LocalHeap :: ThrowException() // throw (LocalHeapOverflow)\n  {\n    /*\n    cout << \"allocated: \" << (p-data) << endl;\n    cout << \"throw LocalHeapOverflow, totsize = \"<< totsize << endl;\n    cout << \"heap name = \" << name << endl;\n    */\n    throw LocalHeapOverflow(totsize);\n  }\n\n\n  LocalHeapOverflow :: LocalHeapOverflow (size_t size) \n    : Exception(\"Local Heap overflow\\n\")\n  {\n    std::stringstream str;\n    str << \"Current heapsize is \" << size << '\\n';\n    Append (str.str());\n    // Append (\"please use 'define constant heapsize = xxx' with larger value\\n\");\n  }\n  \n  LocalHeapOverflow :: ~LocalHeapOverflow ()\n  {\n    ; \n  }\n\n}\n\n"
  },
  {
    "path": "libsrc/core/localheap.hpp",
    "content": "#ifndef NETGEN_CORE_LOCALHEAP_HPP\n#define NETGEN_CORE_LOCALHEAP_HPP\n\n/**************************************************************************/\n/* File:   localheap.hpp                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   19. Apr. 2000                                                  */\n/**************************************************************************/\n\n#include <cstdlib>\n\n#include \"exception.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n\nclass Allocator\n{\npublic:\n  virtual ~Allocator() {}\n  virtual void * Alloc (size_t size)\n  {\n    return new char[size];\n  }\n  virtual void Delete(void* p)\n  {\n    delete (char*) p;\n  }\n  virtual void ArrayDelete(void* p)\n  {\n      delete [] (char*) p;\n  }\n};\nstatic Allocator global_alloc;\n\n/**\n   Exception on heap overflow.\n   Thrown by allocation on LocalHeap.\n*/\nclass NGCORE_API LocalHeapOverflow : public Exception\n{\npublic:\n  LocalHeapOverflow (size_t size);\n  virtual ~LocalHeapOverflow ();\n};\n\n\n\n/**\n   Optimized memory handler.\n   One block of data is organized as stack memory. \n   One can allocate memory out of it. This increases the stack pointer.\n   With \\Ref{CleanUp}, the pointer is reset to the beginning or to a\n   specific position. \n*/\nclass LocalHeap : public Allocator\n{\n  char * data;\n  char * next;\n  char * p;\n  size_t totsize;\npublic:\n  bool owner;\n  const char * name;\n\n#if defined(__MIC__) || defined (__AVX512F__)\n  enum { ALIGN = 64 };\n#else\n  enum { ALIGN = 32 };\n#endif  \n\npublic:\n  /// Allocate one block of size asize.\n  NGCORE_API LocalHeap (size_t asize, \n                            const char * aname = \"noname\",\n                            bool mult_by_threads = false);\n\n  /// Use provided memory for the LocalHeap\n  NETGEN_INLINE LocalHeap (char * adata, size_t asize, \n                    const char  * aname = \"noname\") throw ()\n  {\n    totsize = asize;\n    data = adata;\n    next = data + totsize;\n    owner = 0;\n    // p = data;\n    name = aname;\n    CleanUp();\n  }\n\n  /*\n  /// Use provided memory for the LocalHeap\n  NETGEN_INLINE LocalHeap (const LocalHeap & lh2)\n    : data(lh2.data), p(lh2.p), totsize(lh2.totsize), owner(false),\n      name(lh2.name)\n  {\n    next = data + totsize;\n  }\n  */\n  NETGEN_INLINE LocalHeap (const LocalHeap & lh2) = delete;\n\n  NETGEN_INLINE LocalHeap (LocalHeap && lh2)\n    : data(lh2.data), p(lh2.p), totsize(lh2.totsize), owner(lh2.owner),\n      name(lh2.name)\n  {\n    next = data + totsize;\n    lh2.owner = false;\n  }\n  \n  NETGEN_INLINE LocalHeap Borrow() \n  {\n    return LocalHeap (p, Available());\n  }\n\n\n  NETGEN_INLINE LocalHeap & operator= (LocalHeap && lh2)\n  {\n    if (owner)\n      delete [] data;\n    \n    data = lh2.data;\n    p = lh2.p;\n    totsize = lh2.totsize;\n    owner = lh2.owner;\n    name = lh2.name;\n\n    next = data + totsize;\n    lh2.owner = false;\n    return *this;\n  }\n\n  NETGEN_INLINE LocalHeap ()\n    : data(nullptr), next(nullptr), p(nullptr), totsize(0), owner(false) { ; }\n\n\n  /// free memory\n  virtual ~LocalHeap ()\n  {\n    if (owner)\n      delete [] data;\n  }\n\n  /// delete all memory on local heap\n  NETGEN_INLINE void CleanUp() throw ()\n  {\n    p = data;\n    // p += (16 - (long(p) & 15) );\n    p += (ALIGN - (size_t(p) & (ALIGN-1) ) );\n  }\n\n  /// returns heap-pointer\n  NETGEN_INLINE void * GetPointer () throw ()\n  {\n    return p;\n  }\n\n  /// deletes memory back to heap-pointer\n  NETGEN_INLINE void CleanUp (void * addr) throw ()\n  {\n    p = (char*)addr;\n  }\n\n  /// allocates size bytes of memory from local heap\n  void * Alloc (size_t size) final // throw (LocalHeapOverflow)\n  {\n    char * oldp = p;\n  \n    // 16 byte alignment\n    size += (ALIGN - size % ALIGN);\n    p += size;\n\n    // if ( size_t(p - data) >= totsize )\n#ifndef FULLSPEED\n    if (likely(p >= next))\n        ThrowException();\n#endif\n      return oldp;\n    }\n\n    /// allocates size objects of type T on local heap\n    template <typename T>\n    T * Alloc (size_t size) // throw (LocalHeapOverflow)\n    {\n      char * oldp = p;\n      size *= sizeof (T);\n\n      // 16 byte alignment\n      size += (ALIGN - size % ALIGN);\n      p += size;\n\n#ifndef FULLSPEED\n      if (likely(p >= next))\n\tThrowException();\n#endif\n\n      return reinterpret_cast<T*> (oldp);\n    }\n\n  virtual void Delete(void* /* p */) {}\n\n  virtual void ArrayDelete(void* /* p */) {}\n  private: \n    ///\n#ifndef __CUDA_ARCH__\n    [[noreturn]] NGCORE_API void ThrowException(); \n#else\n    NETGEN_INLINE void ThrowException() { ; }\n#endif\n\n  public:\n    /// free memory (dummy function)\n  NETGEN_INLINE void Free (void * /* data */) throw () \n    {\n      ;\n    }\n\n    /// available memory on LocalHeap\n    NETGEN_INLINE size_t Available () const throw () { return (totsize - (p-data)); }\n\n    /// Split free memory on heap into pieces for each thread\n    NGCORE_API LocalHeap Split () const;\n\n    /// Split free memory on heap into pieces\n    NETGEN_INLINE LocalHeap Split (int partnr, int nparts) const\n    {\n      int pieces = nparts;\n      int i = partnr;\n\n      size_t freemem = totsize - (p - data);\n      size_t size_of_piece = freemem / pieces;\n      return LocalHeap (p + i * size_of_piece, size_of_piece, name);\n    }\n\n\n    NETGEN_INLINE void ClearValues ()\n    {\n      for (size_t i = 0; i < totsize; i++) data[i] = 47;\n    }\n\n    NETGEN_INLINE size_t UsedSize ()\n    {\n      for (size_t i = totsize-1; i != 0; i--)\n        if (data[i] != 47) return i;\n      return 0;\n    }\n  };\n\n\n\n  /**\n     Optimized memory handler.\n     Provides static memory for the local heap. The template argument specifies the size in number of chars.\n  */\n  template <int S>\n  class LocalHeapMem : public LocalHeap\n  {\n    char mem[S];\n  public:\n    NETGEN_INLINE LocalHeapMem (const char * aname) throw () : LocalHeap (mem, S, aname) { ; }\n  };\n\n\n\n\n\n\n\n\n  /**\n     A reset for the heap-pointer of a LocalHeap..\n     The constructor stores the heap-pointer, the constructor at the end of the regions resets the heap-pointer.\n  */\n  class HeapReset\n  {\n    LocalHeap & lh;\n    void * pointer;\n  public:\n    ///\n    NETGEN_INLINE HeapReset (LocalHeap & alh) \n      : lh(alh), pointer (alh.GetPointer()) { ; }\n    \n    ///\n    NETGEN_INLINE ~HeapReset () \n    {\n      lh.CleanUp (pointer);\n    }\n  };\n\n}\n\n\n\nNETGEN_INLINE void * operator new (size_t size, ngcore::Allocator & alloc)  \n{\n  return alloc.Alloc(size);\n}\n\nNETGEN_INLINE void * operator new [] (size_t size, ngcore::Allocator & alloc)  \n{\n  return alloc.Alloc(size);\n}\n\n\nNETGEN_INLINE void operator delete (void * p, ngcore::Allocator & lh)  \n{\n  lh.Delete(p);\n}\n\nNETGEN_INLINE void operator delete [] (void * p, ngcore::Allocator & lh)  \n{\n  lh.ArrayDelete(p);\n}\n\n\n\n#endif // NETGEN_CORE_LOCALHEAP_HPP\n"
  },
  {
    "path": "libsrc/core/logging.cpp",
    "content": "#include \"logging.hpp\"\n\n#include <iostream>\n\nnamespace ngcore\n{\n  std::ostream* testout = new std::ostream(nullptr); // NOLINT\n\n  level::level_enum Logger::global_level = level::warn;\n\n  void Logger::log(level::level_enum level, std::string && s)\n  {\n    if(level>=global_level)\n      std::clog << s << '\\n';\n  }\n\n} //namespace ngcore\n\nnamespace spdlog\n{\n  class logger\n  {\n    public:\n    logger() = default;\n  };\n} // namespace spdlog\n\nnamespace ngcore\n{\n\n  // Dummy functions if no spdlog is available\n\n  std::shared_ptr<Logger> GetLogger(const std::string& /*unused*/)\n  {\n    return std::make_shared<Logger>(std::make_shared<spdlog::logger>());\n  }\n\n  void SetLoggingLevel(level::level_enum level, const std::string& /*unused*/)\n  {\n    Logger::SetGlobalLoggingLevel(level);\n  }\n\n  void AddFileSink(const std::string& /*unused*/, level::level_enum /*unused*/,\n      const std::string& /*unused*/)\n  {}\n  void AddConsoleSink(level::level_enum /*unused*/, const std::string& /*unused*/) {}\n  void ClearLoggingSinks(const std::string& /*unused*/) {}\n  void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {}\n} //namespace ngcore\n"
  },
  {
    "path": "libsrc/core/logging.hpp",
    "content": "#ifndef NETGEN_CORE_LOGGING_HPP\n#define NETGEN_CORE_LOGGING_HPP\n\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"exception.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"utils.hpp\"\n\n#ifndef NETGEN_DEBUG_LOG\n#define NETGEN_DEBUG_LOG(logger, ...)\n#endif  // NETGEN_DEBUG_LOG\n\nnamespace spdlog\n{\n  class logger;\n} // namespace spdlog\n\nnamespace ngcore\n{\n  NGCORE_API extern std::ostream* testout; // NOLINT\n  \n  namespace level\n  {\n    enum level_enum\n    {\n      trace = 0,\n      debug = 1,\n      info = 2,\n      warn = 3,\n      err = 4,\n      critical = 5,\n      off = 6\n    };\n  } // namespace level\n\n  class Logger\n  {\n    static NGCORE_API level::level_enum global_level;\n\n  public:\n    static auto SetGlobalLoggingLevel( level::level_enum level )\n    {\n      auto oldval = global_level;\n      global_level = level;\n      return oldval;\n    }\n\n    std::shared_ptr<spdlog::logger> logger;\n\n    Logger(std::shared_ptr<spdlog::logger> l) : logger(std::move(l)) {}\n\n    void NGCORE_API log( level::level_enum level, std::string && s);\n\n    template<typename T>\n    std::string replace(std::string s, const T & t)\n    {\n      auto p0 = s.find_first_of('{');\n      auto p1 = s.find_first_of('}', p0);\n      if(p0==std::string::npos || p1==std::string::npos)\n        throw Exception(\"invalid format string\");\n      s.replace(p0, p1-p0+1, ToString(t));\n      return s;\n    }\n\n    std::string log_helper(std::string s)\n    {\n      return s;\n    }\n\n    template<typename T>\n    std::string log_helper(std::string s,  const T &t)\n    {\n      return replace(s,t);\n    }\n\n    template<typename T, typename ... Args>\n    std::string log_helper( std::string s, const T &t, Args ... args)\n    {\n      return log_helper(replace(s,t), args...);\n    }\n\n    template<typename ... Args>\n    void log( level::level_enum level, const char* str, Args ... args)\n    {\n      log(level, log_helper(std::string(str), args...));\n    }\n\n    template<typename ... Args>\n    void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); }\n    template<typename ... Args>\n    void debug( const char* str, Args ... args) { log(level::level_enum::debug, str, args...); }\n    template<typename ... Args>\n    void info( const char* str, Args ... args) { log(level::level_enum::info, str, args...); }\n    template<typename ... Args>\n    void warn( const char* str, Args ... args) { log(level::level_enum::warn, str, args...); }\n    template<typename ... Args>\n    void error( const char* str, Args ... args) { log(level::level_enum::err, str, args...); }\n    template<typename ... Args>\n    void critical( const char* str, Args ... args) { log(level::level_enum::critical, str, args...); }\n  };\n\n\n\n\n  NGCORE_API std::shared_ptr<Logger> GetLogger(const std::string& name);\n  NGCORE_API void SetLoggingLevel(level::level_enum level, const std::string& name);\n  NGCORE_API void AddFileSink(const std::string& filename, level::level_enum level, const std::string& logger);\n  NGCORE_API void AddConsoleSink(level::level_enum level, const std::string& logger);\n  NGCORE_API void ClearLoggingSinks(const std::string& logger);\n  NGCORE_API void FlushOnLoggingLevel(level::level_enum level, const std::string& logger);\n} // namespace ngcore\n\n#endif // NETGEN_CORE_LOGGING_HPP\n"
  },
  {
    "path": "libsrc/core/memtracer.hpp",
    "content": "#ifndef NETGEN_CORE_MEMTRACER_HPP\n#define NETGEN_CORE_MEMTRACER_HPP\n\n#include <array>\n#include <chrono>\n#include <string>\n\n#include \"array.hpp\"\n#include \"logging.hpp\"\n#include \"paje_trace.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n\n  class MemoryTracer;\n\n  namespace detail\n  {\n    //Type trait to check if a class implements a 'void SetMemoryTacing(int)' function\n    template<typename T>\n    struct has_StartMemoryTracing\n    {\n    private:\n      template<typename T2>\n      static constexpr auto check(T2*) ->\n        typename std::is_same<decltype(std::declval<T2>().StartMemoryTracing()),void>::type;\n      template<typename>\n      static constexpr std::false_type check(...);\n      using type = decltype(check<T>(nullptr)); // NOLINT\n    public:\n      static constexpr bool value = type::value;\n    };\n  } // namespace detail\n\n  class MemoryTracer\n  {\n#if defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)\n    NGCORE_API static std::vector<std::string> names;\n    NGCORE_API static std::vector<int> parents;\n\n    #if defined(NETGEN_CHECK_RANGE)\n    NGCORE_API static std::atomic<size_t> total_memory;\n    mutable size_t allocated_memory = 0;\n    #endif // NETGEN_CHECK_RANGE\n\n    static int CreateId(const std::string& name = \"\")\n    {\n      int id = names.size();\n      names.push_back(name);\n      parents.push_back(0);\n      if(id==10*8*1024)\n        std::cerr << \"Allocated \" << id << \" MemoryTracer objects\" << std::endl;\n      return id;\n    }\n    mutable int id = 0;\n\n    public:\n\n    MemoryTracer( std::string name )\n    {\n      id = CreateId(name);\n    }\n\n    MemoryTracer() { }\n\n    MemoryTracer(const MemoryTracer & tracer)\n    {\n      (*this) = tracer;\n    }\n\n    MemoryTracer(MemoryTracer && tracer)\n    {\n      (*this) = std::move(tracer);\n    }\n\n    MemoryTracer & operator=(const MemoryTracer & tracer) {\n      if(tracer.id)\n        id = CreateId(names[tracer.id]);\n      return *this;\n    }\n\n    MemoryTracer & operator=(MemoryTracer && tracer) {\n      ngcore::Swap(id, tracer.id);\n\n      #if defined(NETGEN_CHECK_RANGE)\n      ngcore::Swap(allocated_memory, tracer.allocated_memory);\n      #endif // NETGEN_CHECK_RANGE\n\n      return *this;\n    }\n\n    template <typename... TRest>\n    MemoryTracer( std::string name, TRest & ... rest )\n    {\n      id = CreateId(name);\n      Track(rest...);\n    }\n\n    #if defined(NETGEN_CHECK_RANGE)\n    // check if all memory was freed when object is destroyed\n    ~MemoryTracer()\n    {\n      NETGEN_CHECK_SAME(allocated_memory, 0);\n    }\n    #endif // NETGEN_CHECK_RANGE\n\n    NETGEN_INLINE void Alloc(size_t size) const\n    {\n      #if defined(NETGEN_CHECK_RANGE)\n      // Trace also nameless Memtracer objects if range checks are active\n      if(!id && size)\n        id = CreateId();\n      #endif // NETGEN_CHECK_RANGE\n\n      if(id && trace)\n        trace->AllocMemory(id, size);\n\n      #if defined(NETGEN_CHECK_RANGE)\n      if(id)\n      {\n        allocated_memory += size;\n        total_memory += size;\n      }\n      #endif // NETGEN_CHECK_RANGE\n    }\n\n    void Free(size_t size) const\n    {\n      if(id && trace)\n        trace->FreeMemory(id, size);\n\n      #if defined(NETGEN_CHECK_RANGE)\n      if(id)\n      {\n        // check if we have at least size bytes of memory currently allocated (such that allocated_memory doesn't get negative)\n        NETGEN_CHECK_RANGE(allocated_memory, static_cast<ptrdiff_t>(size), std::numeric_limits<ptrdiff_t>::max());\n        allocated_memory -= size;\n        total_memory -= size;\n        #endif // NETGEN_CHECK_RANGE\n      }\n    }\n\n    int GetId() const { return id; }\n\n    template <typename T1, typename... TRest>\n    void Track( T1 & obj, const std::string& name, TRest & ... rest ) const\n    {\n      Track(obj, name);\n      Track(rest...);\n    }\n\n    template<typename T>\n    void Track( T & obj, const std::string& name ) const\n    {\n      obj.GetMemoryTracer().Activate(obj, name);\n      parents[obj.GetMemoryTracer().GetId()] = id;\n    }\n\n    static std::string GetName(int id)\n    {\n      return names[id];\n    }\n\n    std::string GetName() const\n    {\n      return names[id];\n    }\n\n    template<typename T>\n    void Activate(T& me, const std::string& name) const\n    {\n      if(!id)\n        {\n          const_cast<MemoryTracer*>(this)->id = CreateId(name);\n          if constexpr(detail::has_StartMemoryTracing<T>::value)\n            me.StartMemoryTracing();\n        }\n      else\n        SetName(name);\n    }\n\n    void SetName(const std::string& name) const\n    {\n      names[id] = name;\n    }\n\n\n    static const std::vector<std::string> & GetNames() { return names; }\n    static const std::vector<int> & GetParents() { return parents; }\n    static size_t GetTotalMemory()\n    {\n      #if defined(NETGEN_CHECK_RANGE)\n      return total_memory;\n      #else\n      return 0;\n      #endif // NETGEN_CHECK_RANGE\n    }\n#else // defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)\n  public:\n    NETGEN_INLINE MemoryTracer() {}\n    NETGEN_INLINE MemoryTracer( std::string /* name */ ) {}\n    template <typename... TRest>\n    NETGEN_INLINE MemoryTracer( std::string /* name */, TRest & ... ) {}\n\n    NETGEN_INLINE void Alloc(size_t /* size */) const {}\n    NETGEN_INLINE void Free(size_t /* size */) const {}\n    NETGEN_INLINE int GetId() const { return 0; }\n\n    template <typename... TRest>\n    NETGEN_INLINE void Track(TRest&...) const {}\n\n    static std::string GetName(int /* id */) { return \"\"; }\n    std::string GetName() const { return \"\"; }\n    void SetName(std::string /* name */) const {}\n    static size_t GetTotalMemory() { return 0; }\n#endif // NETGEN_TRACE_MEMORY\n  };\n} // namespace ngcore\n\n#endif // NETGEN_CORE_MEMTRACER_HPP\n"
  },
  {
    "path": "libsrc/core/mpi4py_pycapi.h",
    "content": "/* Author:  Lisandro Dalcin   */\n/* Contact: dalcinl@gmail.com */\n\n#ifndef MPI4PY_PYCAPI_H\n#define MPI4PY_PYCAPI_H\n\n#include <mpi.h>\n#include <Python.h>\n\n#define _mpi4py_declare_pycapi(Type, star) \\\nstatic PyTypeObject *_mpi4py_PyMPI##Type = NULL; \\\nstatic PyObject *(*_mpi4py_PyMPI##Type##_New)(MPI_##Type star) = NULL; \\\nstatic MPI_##Type *(*_mpi4py_PyMPI##Type##_Get)(PyObject *) = NULL;\n\n#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE\n_mpi4py_declare_pycapi(Datatype,)\n#define PyMPIDatatype_Type (*_mpi4py_PyMPIDatatype)\n#define PyMPIDatatype_New _mpi4py_PyMPIDatatype_New\n#define PyMPIDatatype_Get _mpi4py_PyMPIDatatype_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_STATUS\n_mpi4py_declare_pycapi(Status,*)\n#define PyMPIStatus_Type (*_mpi4py_PyMPIStatus)\n#define PyMPIStatus_New _mpi4py_PyMPIStatus_New\n#define PyMPIStatus_Get _mpi4py_PyMPIStatus_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST\n_mpi4py_declare_pycapi(Request,)\n#define PyMPIRequest_Type (*_mpi4py_PyMPIRequest)\n#define PyMPIRequest_New _mpi4py_PyMPIRequest_New\n#define PyMPIRequest_Get _mpi4py_PyMPIRequest_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE\n_mpi4py_declare_pycapi(Message,)\n#define PyMPIMessage_Type (*_mpi4py_PyMPIMessage)\n#define PyMPIMessage_New _mpi4py_PyMPIMessage_New\n#define PyMPIMessage_Get _mpi4py_PyMPIMessage_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_OP\n_mpi4py_declare_pycapi(Op,)\n#define PyMPIOp_Type (*_mpi4py_PyMPIOp)\n#define PyMPIOp_New _mpi4py_PyMPIOp_New\n#define PyMPIOp_Get _mpi4py_PyMPIOp_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_GROUP\n_mpi4py_declare_pycapi(Group,)\n#define PyMPIGroup_Type (*_mpi4py_PyMPIGroup)\n#define PyMPIGroup_New _mpi4py_PyMPIGroup_New\n#define PyMPIGroup_Get _mpi4py_PyMPIGroup_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_INFO\n_mpi4py_declare_pycapi(Info,)\n#define PyMPIInfo_Type (*_mpi4py_PyMPIInfo)\n#define PyMPIInfo_New _mpi4py_PyMPIInfo_New\n#define PyMPIInfo_Get _mpi4py_PyMPIInfo_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER\n_mpi4py_declare_pycapi(Errhandler,)\n#define PyMPIErrhandler_Type (*_mpi4py_PyMPIErrhandler)\n#define PyMPIErrhandler_New _mpi4py_PyMPIErrhandler_New\n#define PyMPIErrhandler_Get _mpi4py_PyMPIErrhandler_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_SESSION\n_mpi4py_declare_pycapi(Session,)\n#define PyMPISession_Type (*_mpi4py_PyMPISession)\n#define PyMPISession_New _mpi4py_PyMPISession_New\n#define PyMPISession_Get _mpi4py_PyMPISession_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_COMM\n_mpi4py_declare_pycapi(Comm,)\n#define PyMPIComm_Type (*_mpi4py_PyMPIComm)\n#define PyMPIComm_New _mpi4py_PyMPIComm_New\n#define PyMPIComm_Get _mpi4py_PyMPIComm_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_WIN\n_mpi4py_declare_pycapi(Win,)\n#define PyMPIWin_Type (*_mpi4py_PyMPIWin)\n#define PyMPIWin_New _mpi4py_PyMPIWin_New\n#define PyMPIWin_Get _mpi4py_PyMPIWin_Get\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_FILE\n_mpi4py_declare_pycapi(File,)\n#define PyMPIFile_Type (*_mpi4py_PyMPIFile)\n#define PyMPIFile_New _mpi4py_PyMPIFile_New\n#define PyMPIFile_Get _mpi4py_PyMPIFile_Get\n#endif\n\n#undef _mpi4py_define_pycapi\n\nstatic int _mpi4py_ImportType(PyObject *module,\n                              const char *type_name,\n                              PyTypeObject **type)\n{\n  PyObject *attr = NULL;\n  attr = PyObject_GetAttrString(module, type_name);\n  if (!attr)\n    goto fn_fail;\n  if (!PyType_Check(attr)) {\n    PyErr_Format(PyExc_TypeError,\n                 \"%.200s.%.200s is not a type object\",\n                 PyModule_GetName(module), type_name);\n    goto fn_fail;\n  }\n  *type = (PyTypeObject *)attr;\n  return 0;\n fn_fail:\n  Py_DecRef(attr);\n  return -1;\n}\n\nstatic int _mpi4py_ImportFunc(PyObject *module,\n                              const char *func_name,\n                              const char *signature,\n                              void (**func)(void))\n{\n    PyObject *pyxcapi = NULL;\n    PyObject *capsule = NULL;\n    union { void *obj; void (*fcn)(void); } ptr;\n    pyxcapi = PyObject_GetAttrString(module, (char *)\"__pyx_capi__\");\n    if (!pyxcapi)\n      goto fn_fail;\n\n    capsule = PyDict_GetItemString(pyxcapi, func_name);\n    if (!capsule) {\n      PyErr_Format(PyExc_ImportError,\n                   \"%.200s does not export expected C function %.200s\",\n                   PyModule_GetName(module), func_name);\n      goto fn_fail;\n    }\n    if (!PyCapsule_CheckExact(capsule)) {\n      PyErr_Format(PyExc_TypeError,\n                   \"%.200s.%.200s is not a capsule\",\n                   PyModule_GetName(module), func_name);\n    }\n    if (!signature) {\n      signature = PyCapsule_GetName(capsule);\n    }\n    if (!PyCapsule_IsValid(capsule, signature)) {\n      PyErr_Format(PyExc_TypeError,\n                   \"C function %.200s.%.200s has wrong signature \"\n                   \"(expected %.500s, got %.500s)\",\n                   PyModule_GetName(module), func_name,\n                   signature, PyCapsule_GetName(capsule));\n      goto fn_fail;\n    }\n    ptr.obj = PyCapsule_GetPointer(capsule, signature);\n    if (!ptr.obj)\n      goto fn_fail;\n    *func = ptr.fcn;\n    Py_DecRef(pyxcapi);\n    return 0;\n fn_fail:\n    Py_DecRef(pyxcapi);\n    return -1;\n}\n\nstatic int import_mpi4py_MPI(void)\n{\n  PyObject *module = PyImport_ImportModule(\"mpi4py.MPI\");\n  if (!module)\n    goto fn_fail;\n\n#define _mpi4py_import_pycapi(Type) do {                                     \\\n    if (_mpi4py_ImportType(module, #Type, &_mpi4py_PyMPI##Type) < 0)         \\\n      goto fn_fail;                                                          \\\n    if (_mpi4py_ImportFunc(module, \"PyMPI\" #Type \"_New\", NULL,               \\\n                           (void (**)(void))&_mpi4py_PyMPI##Type##_New) < 0) \\\n      goto fn_fail;                                                          \\\n    if (_mpi4py_ImportFunc(module, \"PyMPI\" #Type \"_Get\", NULL,               \\\n                           (void (**)(void))&_mpi4py_PyMPI##Type##_Get) < 0) \\\n      goto fn_fail;                                                          \\\n  } while (0)\n\n#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE\n  _mpi4py_import_pycapi(Datatype);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_STATUS\n  _mpi4py_import_pycapi(Status);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST\n  _mpi4py_import_pycapi(Request);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE\n  _mpi4py_import_pycapi(Message);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_OP\n  _mpi4py_import_pycapi(Op);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_GROUP\n  _mpi4py_import_pycapi(Group);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_INFO\n  _mpi4py_import_pycapi(Info);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER\n  _mpi4py_import_pycapi(Errhandler);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_SESSION\n  _mpi4py_import_pycapi(Session);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_COMM\n  _mpi4py_import_pycapi(Comm);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_WIN\n  _mpi4py_import_pycapi(Win);\n#endif\n\n#ifndef MPI4PY_LIMITED_API_SKIP_FILE\n  _mpi4py_import_pycapi(File);\n#endif\n\n#undef _mpi4py_import_pycapi\n\n  Py_DecRef(module);\n  return 0;\n fn_fail:\n  Py_DecRef(module);\n  return -1;\n}\n\n#define __PYX_HAVE_API__mpi4py__MPI\n#define import_mpi4py__MPI import_mpi4py_MPI\n\n#endif /* MPI4PY_PYCAPI_H */\n"
  },
  {
    "path": "libsrc/core/mpi_wrapper.hpp",
    "content": "#ifndef NGCORE_MPIWRAPPER_HPP\n#define NGCORE_MPIWRAPPER_HPP\n\n#include <array>\n\n#include <complex>\n\n#include \"array.hpp\"\n#include \"table.hpp\"\n#include \"exception.hpp\"\n#include \"profiler.hpp\"\n#include \"ngstream.hpp\"\n#include \"ng_mpi.hpp\"\n\nnamespace ngcore\n{\n\n#ifdef PARALLEL\n\n  template <class T> struct MPI_typetrait  { };\n  \n  template <> struct MPI_typetrait<int> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_INT; } };\n\n  template <> struct MPI_typetrait<short> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_SHORT; } };\n\n  template <> struct MPI_typetrait<char> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };\n\n  template <> struct MPI_typetrait<signed char> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };\n  \n  template <> struct MPI_typetrait<unsigned char> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };\n\n  template <> struct MPI_typetrait<size_t> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_UINT64_T; } };\n\n  template <> struct MPI_typetrait<double> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_DOUBLE; } };\n\n  template <> struct MPI_typetrait<std::complex<double>> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_CXX_DOUBLE_COMPLEX; } };\n\n  template <> struct MPI_typetrait<bool> {\n    static NG_MPI_Datatype MPIType () { return NG_MPI_C_BOOL; } };\n\n\n  template<typename T, size_t S>\n  struct MPI_typetrait<std::array<T,S>>\n  {\n    static NG_MPI_Datatype MPIType ()\n    { \n      static NG_MPI_Datatype NG_MPI_T = 0;\n      if (!NG_MPI_T)\n\t{\n\t  NG_MPI_Type_contiguous ( S, MPI_typetrait<T>::MPIType(), &NG_MPI_T);\n\t  NG_MPI_Type_commit ( &NG_MPI_T );\n\t}\n      return NG_MPI_T;\n    }\n  };\n  \n  template <class T, class T2 = decltype(MPI_typetrait<T>::MPIType())>\n  inline NG_MPI_Datatype GetMPIType () {\n    return MPI_typetrait<T>::MPIType();\n  }\n\n  template <class T>\n  inline NG_MPI_Datatype GetMPIType (T &) {\n    return GetMPIType<T>();\n  }\n\n  class NgMPI_Request\n  {\n    NG_MPI_Request request;\n  public:\n    NgMPI_Request (NG_MPI_Request requ) : request{requ} { }\n    NgMPI_Request (const NgMPI_Request&) = delete;    \n    NgMPI_Request (NgMPI_Request&&) = default;\n    ~NgMPI_Request () { NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }\n    void Wait() {  NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }\n    operator NG_MPI_Request() &&\n    {\n      auto tmp = request;\n      request = NG_MPI_REQUEST_NULL;\n      return tmp;\n    }\n  };\n\n  class NgMPI_Requests\n  {\n    Array<NG_MPI_Request> requests;\n  public:\n    NgMPI_Requests() = default;\n    ~NgMPI_Requests() { WaitAll(); }\n\n    void Reset() { requests.SetSize0(); }\n    \n    NgMPI_Requests & operator+= (NgMPI_Request && r)\n    {\n      requests += NG_MPI_Request(std::move(r));\n      return *this;\n    }\n\n    NgMPI_Requests & operator+= (NG_MPI_Request r)\n    {\n      requests += r;\n      return *this;\n    }\n    \n    void WaitAll()\n    {\n      static Timer t(\"NgMPI - WaitAll\"); RegionTimer reg(t);    \n      if (!requests.Size()) return;\n      NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);\n    }\n\n    int WaitAny ()\n    {\n      int nr;\n      NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);\n      return nr;\n    }\n  };\n  \n  [[deprecated(\"use requests.WaitAll instread\")]]\n  inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests)\n  {\n    static Timer t(\"MPI - WaitAll\"); RegionTimer reg(t);    \n    if (!requests.Size()) return;\n    NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);\n  }\n\n  [[deprecated(\"use requests.WaitAny instread\")]]  \n  inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests)\n  {\n    int nr;\n    NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);\n    return nr;\n  }\n\n  \n\n  class NgMPI_Comm\n  {\n  protected:\n    NG_MPI_Comm comm;\n    bool valid_comm;\n    int * refcount;\n    int rank, size;\n  public:\n    NgMPI_Comm ()\n      : valid_comm(false), refcount(nullptr), rank(0), size(1)\n    { ; }\n\n    NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false)\n      : comm(_comm), valid_comm(true)\n    {\n      int flag;\n      NG_MPI_Initialized (&flag);\n      if (!flag)\n        {\n          valid_comm = false;\n          refcount = nullptr;\n          rank = 0;\n          size = 1;\n          return;\n        }\n\n      if (!owns)\n        refcount = nullptr;\n      else\n        refcount = new int{1};\n      \n      NG_MPI_Comm_rank(comm, &rank);\n      NG_MPI_Comm_size(comm, &size);\n    }\n    \n    NgMPI_Comm (const NgMPI_Comm & c)\n      : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount),\n        rank(c.rank), size(c.size)\n    {\n      if (refcount) (*refcount)++;\n    }\n\n    NgMPI_Comm (NgMPI_Comm && c)\n      : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount),\n        rank(c.rank), size(c.size)\n    {\n      c.refcount = nullptr;\n    }\n    \n    ~NgMPI_Comm()\n    {\n      if (refcount)\n        if (--(*refcount) == 0)\n          NG_MPI_Comm_free(&comm);\n    }\n\n    bool ValidCommunicator() const\n    {\n      return valid_comm;\n    }\n    \n    NgMPI_Comm & operator= (const NgMPI_Comm & c)\n    {\n      if (refcount)\n        if (--(*refcount) == 0)\n          NG_MPI_Comm_free(&comm);\n\n      refcount = c.refcount;\n      if (refcount) (*refcount)++;      \n      comm = c.comm;\n      valid_comm = c.valid_comm;\n      size = c.size;\n      rank = c.rank;\n      return *this;\n    }\n    \n    class InvalidCommException : public Exception {\n    public:\n      InvalidCommException() : Exception(\"Do not have a valid communicator\") { ; }\n    };\n    \n    operator NG_MPI_Comm() const {\n      if (!valid_comm) throw InvalidCommException();\n      return comm;\n    }\n\n    int Rank() const { return rank; }\n    int Size() const { return size; }\n    void Barrier() const {\n      static Timer t(\"MPI - Barrier\"); RegionTimer reg(t);\n      if (size > 1) NG_MPI_Barrier (comm);\n    }\n    \n\n    /** --- blocking P2P --- **/\n\n    template<typename T, typename T2 = decltype(GetMPIType<T>())>\n    void Send (T & val, int dest, int tag) const {\n      NG_MPI_Send (&val, 1, GetMPIType<T>(), dest, tag, comm);\n    }\n\n    void Send (const std::string & s, int dest, int tag) const {\n      NG_MPI_Send( const_cast<char*> (&s[0]), s.length(), NG_MPI_CHAR, dest, tag, comm);\n    }\n    \n    template<typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>\n    void Send(FlatArray<T,TI> s, int dest, int tag) const {\n      NG_MPI_Send (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm);\n    }\n    \n    template<typename T, typename T2 = decltype(GetMPIType<T>())> \n    void Recv (T & val, int src, int tag) const {\n      NG_MPI_Recv (&val, 1, GetMPIType<T>(), src, tag, comm, NG_MPI_STATUS_IGNORE);\n    }\n\n    void Recv (std::string & s, int src, int tag) const {    \n      NG_MPI_Status status;\n      int len;\n      NG_MPI_Probe (src, tag, comm, &status);\n      NG_MPI_Get_count (&status, NG_MPI_CHAR, &len);\n      // s.assign (len, ' ');\n      s.resize (len);\n      NG_MPI_Recv( &s[0], len, NG_MPI_CHAR, src, tag, comm, NG_MPI_STATUS_IGNORE);\n    }\n    \n\n    template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>\n    void Recv (FlatArray <T,TI> s, int src, int tag) const {\n      NG_MPI_Recv (s.Data(), s.Size(), GetMPIType<T> (), src, tag, comm, NG_MPI_STATUS_IGNORE);\n    }\n    \n    template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>\n    void Recv (Array <T,TI> & s, int src, int tag) const\n    {\n      NG_MPI_Status status;\n      int len;\n      const NG_MPI_Datatype NG_MPI_T  = GetMPIType<T> ();\n      NG_MPI_Probe (src, tag, comm, &status);\n      NG_MPI_Get_count (&status, NG_MPI_T, &len);\n      s.SetSize (len);\n      NG_MPI_Recv (s.Data(), len, NG_MPI_T, src, tag, comm, NG_MPI_STATUS_IGNORE);\n    }\n\n    /** --- non-blocking P2P --- **/\n\n    template<typename T, typename T2 = decltype(GetMPIType<T>())> \n    [[nodiscard]] NG_MPI_Request ISend (T & val, int dest, int tag) const\n    {\n      NG_MPI_Request request;\n      NG_MPI_Isend (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);\n      return request;\n    }\n    \n    template<typename T, typename T2 = decltype(GetMPIType<T>())>\n    [[nodiscard]] NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const\n    {\n      NG_MPI_Request request;\n      NG_MPI_Isend (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);\n      return request;\n    }\n    \n    template<typename T, typename T2 = decltype(GetMPIType<T>())> \n    [[nodiscard]] NG_MPI_Request IRecv (T & val, int dest, int tag) const\n    {\n      NG_MPI_Request request;\n      NG_MPI_Irecv (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);\n      return request;\n    }\n    \n    template<typename T, typename T2 = decltype(GetMPIType<T>())>\n    [[nodiscard]] NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const\n    { \n      NG_MPI_Request request;\n      NG_MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);\n      return request;\n    }\n\n    \n    /** --- collectives --- **/\n\n    template <typename T, typename T2 = decltype(GetMPIType<T>())> \n    T Reduce (T d, const NG_MPI_Op & op, int root = 0) const\n    {\n      static Timer t(\"MPI - Reduce\"); RegionTimer reg(t);          \n      if (size == 1) return d;\n      \n      T global_d;\n      NG_MPI_Reduce (&d, &global_d, 1, GetMPIType<T>(), op, root, comm);\n      return global_d;\n    }\n    \n    template <typename T, typename T2 = decltype(GetMPIType<T>())> \n    T AllReduce (T d, const NG_MPI_Op & op) const\n    {\n      static Timer t(\"MPI - AllReduce\"); RegionTimer reg(t);\n      if (size == 1) return d;\n      \n      T global_d;\n      NG_MPI_Allreduce ( &d, &global_d, 1, GetMPIType<T>(), op, comm);\n      return global_d;\n    }\n\n    template <typename T, typename T2 = decltype(GetMPIType<T>())> \n    void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const\n    {\n      static Timer t(\"MPI - AllReduce Array\"); RegionTimer reg(t);\n      if (size == 1) return;\n      \n      NG_MPI_Allreduce (NG_MPI_IN_PLACE, d.Data(), d.Size(), GetMPIType<T>(), op, comm);\n    }\n    \n    template <typename T, typename T2 = decltype(GetMPIType<T>())> \n    void Bcast (T & s, int root = 0) const {\n      if (size == 1) return;\n      static Timer t(\"MPI - Bcast\"); RegionTimer reg(t);\n      NG_MPI_Bcast (&s, 1, GetMPIType<T>(), root, comm);\n    }\n\n\n    template <class T, size_t S>\n    void Bcast (std::array<T,S> & d, int root = 0) const\n    {\n      if (size == 1) return;\n      if (S != 0)\n        NG_MPI_Bcast (&d[0], S, GetMPIType<T>(), root, comm);\n    }\n    \n    \n    template <class T>\n    void Bcast (Array<T> & d, int root = 0) const\n    {\n      if (size == 1) return;\n      \n      int ds = d.Size();\n      Bcast (ds, root);\n      if (Rank() != root) d.SetSize (ds);\n      if (ds != 0)\n        NG_MPI_Bcast (d.Data(), ds, GetMPIType<T>(), root, comm);\n    }\n\n    \n    void Bcast (std::string & s, int root = 0) const \n    {\n      if (size == 1) return;\n      int len = s.length();\n      Bcast (len, root);\n      if (rank != 0) s.resize (len);\n      NG_MPI_Bcast (&s[0], len, NG_MPI_CHAR, root, comm);\n    }\n\n\n    \n    template <class T, size_t S>\n    [[nodiscard]] NgMPI_Request IBcast (std::array<T,S> & d, int root = 0) const\n    {\n      NG_MPI_Request request;      \n      NG_MPI_Ibcast (&d[0], S, GetMPIType<T>(), root, comm, &request);\n      return request;\n    }\n\n    template <class T>\n     [[nodiscard]] NgMPI_Request IBcast (FlatArray<T> d, int root = 0) const\n    {\n      NG_MPI_Request request;      \n      int ds = d.Size();\n      NG_MPI_Ibcast (d.Data(), ds, GetMPIType<T>(), root, comm, &request);\n      return request;\n    }\n\n    \n    template <typename T>\n    void AllToAll (FlatArray<T> send, FlatArray<T> recv) const\n    {\n      NG_MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),\n                       recv.Data(), 1, GetMPIType<T>(), comm);\n    }\n\n\n    template <typename T>\n    void ScatterRoot (FlatArray<T> send) const\n    {\n      if (size == 1) return;\n      NG_MPI_Scatter (send.Data(), 1, GetMPIType<T>(),\n                      NG_MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);\n    }\n    \n    template <typename T>\n    void Scatter (T & recv) const\n    {\n      if (size == 1) return;      \n      NG_MPI_Scatter (NULL, 0, GetMPIType<T>(),\n                      &recv, 1, GetMPIType<T>(), 0, comm);\n    }\n\n    template <typename T>\n    void GatherRoot (FlatArray<T> recv) const\n    {\n      recv[0] = T(0);\n      if (size == 1) return;      \n      NG_MPI_Gather (NG_MPI_IN_PLACE, 1, GetMPIType<T>(),\n                     recv.Data(), 1, GetMPIType<T>(), 0, comm);\n    }\n\n    template <typename T>\n    void Gather (T send) const\n    {\n      if (size == 1) return;            \n      NG_MPI_Gather (&send, 1, GetMPIType<T>(),\n                  NULL, 1, GetMPIType<T>(), 0, comm);\n    }\n\n    \n    template <typename T>\n    void AllGather (T val, FlatArray<T> recv) const\n    {\n      if (size == 1)\n        {\n          recv[0] = val;\n          return;\n        }\n      NG_MPI_Allgather (&val, 1, GetMPIType<T>(),\n                     recv.Data(), 1, GetMPIType<T>(), \n                     comm);\n    }\n    \n\n\n    template <typename T>\n    void ExchangeTable (DynamicTable<T> & send_data, \n                        DynamicTable<T> & recv_data, int tag)\n    {\n      Array<int> send_sizes(size);\n      Array<int> recv_sizes(size);\n      \n      for (int i = 0; i < size; i++)\n        send_sizes[i] = send_data[i].Size();\n      \n      AllToAll (send_sizes, recv_sizes);\n    \n      recv_data = DynamicTable<T> (recv_sizes, true);\n      \n      NgMPI_Requests requests;\n      for (int dest = 0; dest < size; dest++)\n        if (dest != rank && send_data[dest].Size())\n          requests += ISend (FlatArray<T>(send_data[dest]), dest, tag);\n      \n      for (int dest = 0; dest < size; dest++)\n        if (dest != rank && recv_data[dest].Size())\n          requests += IRecv (FlatArray<T>(recv_data[dest]), dest, tag);\n\n      requests.WaitAll();\n    }\n    \n\n\n\n    \n    NgMPI_Comm SubCommunicator (FlatArray<int> procs) const\n    {\n      NG_MPI_Comm subcomm;\n      NG_MPI_Group gcomm, gsubcomm;\n      NG_MPI_Comm_group(comm, &gcomm);\n      NG_MPI_Group_incl(gcomm, procs.Size(), procs.Data(), &gsubcomm);\n      NG_MPI_Comm_create_group(comm, gsubcomm, 4242, &subcomm);\n      return NgMPI_Comm(subcomm, true);\n    }\n\n  }; // class NgMPI_Comm\n\n#else // PARALLEL\n  class NG_MPI_Comm {\n    int nr;\n  public:\n    NG_MPI_Comm (int _nr = 0) : nr(_nr) { ; }\n    operator int() const { return nr; }\n    bool operator== (NG_MPI_Comm c2) const { return nr == c2.nr; }\n  };\n  static NG_MPI_Comm NG_MPI_COMM_WORLD = 12345, NG_MPI_COMM_NULL = 10000;\n\n  typedef int NG_MPI_Op;\n  typedef int NG_MPI_Datatype;  \n  typedef int NG_MPI_Request;\n  \n  enum { NG_MPI_SUM = 0, NG_MPI_MIN = 1, NG_MPI_MAX = 2, NG_MPI_LOR = 4711 };\n\n  inline void NG_MPI_Type_contiguous ( int, NG_MPI_Datatype, NG_MPI_Datatype*) { ; } \n  inline void NG_MPI_Type_commit ( NG_MPI_Datatype * ) { ; }\n\n  template <class T> struct MPI_typetrait  {\n    static NG_MPI_Datatype MPIType () { return -1; }    \n  };\n  template <class T, class T2=void>\n  inline NG_MPI_Datatype GetMPIType () { return -1; }\n\n  class NgMPI_Request {\n  public:\n    NgMPI_Request() = default;\n    NgMPI_Request(NgMPI_Request &&) { ; }    \n    NgMPI_Request(NG_MPI_Request &&) { ; }\n  };\n  class NgMPI_Requests\n  {\n  public:\n    NgMPI_Requests & operator+= (NgMPI_Request &&) { return *this; }\n    NgMPI_Requests & operator+= (NG_MPI_Request r) { return *this; }\n    void Reset() { ; }\n    void WaitAll() { ; }\n    int WaitAny() { return 0; }\n  };\n  \n  class NgMPI_Comm\n  {\n    \n  public:\n    NgMPI_Comm () { ; } \n    NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false) { ; }\n\n    size_t Rank() const { return 0; }\n    size_t Size() const { return 1; }\n    bool ValidCommunicator() const { return false; }\n    void Barrier() const { ; } \n    operator NG_MPI_Comm() const { return NG_MPI_Comm(); }\n\n    template<typename T>\n    void Send( T & val, int dest, int tag) const { ; }\n    \n    template<typename T>\n    void Send(FlatArray<T> s, int dest, int tag) const { ; }\n\n    template<typename T>\n    void Recv (T & val, int src, int tag) const { ; }\n\n    template <typename T>\n    void Recv (FlatArray <T> s, int src, int tag) const { ; }\n\n    template <typename T>\n    void Recv (Array <T> & s, int src, int tag) const { ; }\n\n    template<typename T>\n    NG_MPI_Request ISend (T & val, int dest, int tag) const { return 0; } \n    \n    template<typename T>\n    NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const { return 0; }\n\n    template<typename T>\n    NG_MPI_Request IRecv (T & val, int dest, int tag) const { return 0; } \n    \n    template<typename T>\n    NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const { return 0; }\n\n    template <typename T>\n    T Reduce (T d, const NG_MPI_Op & op, int root = 0) const { return d; }\n    \n    template <typename T>\n    T AllReduce (T d, const NG_MPI_Op & op) const { return d; }\n\n    template <typename T>\n    void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const { ; }\n    \n    template <typename T>\n    void Bcast (T & s, int root = 0) const { ; } \n\n    template <class T, size_t S>\n    void Bcast (std::array<T,S> & d, int root = 0) const {}\n    \n    template <class T>\n    void Bcast (Array<T> & d, int root = 0) const { ; } \n\n    template <class T, size_t S>\n    NG_MPI_Request IBcast (std::array<T,S> & d, int root = 0) const { return 0; }\n\n    template <class T>\n    NG_MPI_Request IBcast (FlatArray<T> d, int root = 0) const { return 0; } \n    \n    template <typename T>\n    void AllGather (T val, FlatArray<T> recv) const\n    {\n      recv[0] = val;\n    }\n\n    template <typename T>\n    void ExchangeTable (DynamicTable<T> & send_data, \n                        DynamicTable<T> & recv_data, int tag) { ; }\n\n    \n    NgMPI_Comm SubCommunicator (FlatArray<int> procs) const\n    { return *this; }\n  };  \n\n  inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests) { ; }\n  inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests) { return 0; }\n\n#endif // PARALLEL\n\n} // namespace ngcore\n\n#endif // NGCORE_MPIWRAPPER_HPP\n\n"
  },
  {
    "path": "libsrc/core/ng_mpi.cpp",
    "content": "#define OMPI_SKIP_MPICXX\n#include <mpi.h>\n\n#include \"ng_mpi.hpp\"\n\n#include <type_traits>\n\n#include \"array.hpp\"\n#include \"ngcore_api.hpp\"\n\n#ifdef NG_PYTHON\n#include \"pybind11/pytypes.h\"\n#include \"python_ngcore.hpp\"\n\n#define MPI4PY_LIMITED_API 1\n#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1\n#define MPI4PY_LIMITED_API_SKIP_SESSION 1\n#include \"mpi4py_pycapi.h\"  // mpi4py < 4.0.0\n#endif\n\n#ifdef MSMPI_VER\nint MPI_Comm_create_group(MPI_Comm arg0, MPI_Group arg1, int arg2,\n                          MPI_Comm* arg3) {\n  throw std::runtime_error(\n      \"MPI_Comm_create_group not supported on Microsoft MPI\");\n}\nstatic MPI_Datatype MPI_CXX_DOUBLE_COMPLEX;\n#endif  // MSMPI_VER\n\nnamespace ngcore {\n\nstatic_assert(sizeof(MPI_Status) <= sizeof(NG_MPI_Status), \"Size mismatch\");\nstatic_assert(alignof(MPI_Status) <= alignof(NG_MPI_Status), \"Size mismatch\");\n\nint mpi2ng(int value) { return value; }\nvoid* mpi2ng(void* ptr) { return ptr; }\n\nNG_MPI_Status* mpi2ng(MPI_Status* status) {\n  return reinterpret_cast<NG_MPI_Status*>(status);\n}\n\n#if !defined(MPICH) && !defined(MSMPI_VER)\nNG_MPI_Comm mpi2ng(MPI_Comm comm) { return reinterpret_cast<uintptr_t>(comm); }\n#endif\n\ntemplate <size_t size, size_t stride>\nvoid gather_strided_array(size_t count, char* data) {\n  static_assert(size <= stride, \"Size must be less than or equal to stride\");\n  if constexpr (size < stride) {\n    char* dst = data;\n    char* src = data;\n    for ( [[maybe_unused]] auto i : Range(count)) {\n      memcpy(dst, src, size);\n      dst += size;\n      src += stride;\n    }\n  }\n}\n\ntemplate <typename T>\nT cast_ng2mpi(uintptr_t obj) {\n  if constexpr (std::is_pointer_v<T>)\n    return reinterpret_cast<T>(obj);\n  else\n    return static_cast<T>(obj);\n}\n\ntemplate <typename T>\nT cast_ng2mpi(uintptr_t* ptr) {\n  if constexpr (std::is_pointer_v<T>)\n    return reinterpret_cast<T>(ptr);\n  else\n    return static_cast<T>(ptr);\n}\n\ntemplate <typename T, typename TSrc>\nT* cast_ng2mpi(TSrc* ptr, int count) {\n  gather_strided_array<sizeof(T), sizeof(TSrc)>(count,\n                                                reinterpret_cast<char*>(ptr));\n  return reinterpret_cast<T*>(ptr);\n}\n\nMPI_Comm ng2mpi(NG_MPI_Comm comm) {\n  static_assert(sizeof(MPI_Comm) <= sizeof(comm.value), \"Size mismatch\");\n  static_assert(alignof(MPI_Comm) <= alignof(NG_MPI_Comm), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Comm>(comm.value);\n}\n\nMPI_Group ng2mpi(NG_MPI_Group group) {\n  static_assert(sizeof(MPI_Group) <= sizeof(group.value), \"Size mismatch\");\n  static_assert(alignof(MPI_Group) <= alignof(NG_MPI_Group), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Group>(group.value);\n}\n\nMPI_Comm* ng2mpi(NG_MPI_Comm* comm) {\n  return cast_ng2mpi<MPI_Comm*>(&comm->value);\n}\nMPI_Group* ng2mpi(NG_MPI_Group* group) {\n  return cast_ng2mpi<MPI_Group*>(&group->value);\n}\nMPI_Datatype* ng2mpi(NG_MPI_Datatype* type) {\n  return cast_ng2mpi<MPI_Datatype*>(&type->value);\n}\nMPI_Datatype* ng2mpi(NG_MPI_Datatype* type, int count) {\n  return cast_ng2mpi<MPI_Datatype>(&type->value, count);\n}\nMPI_Request* ng2mpi(NG_MPI_Request* request) {\n  return cast_ng2mpi<MPI_Request*>(&request->value);\n}\nMPI_Request* ng2mpi(NG_MPI_Request* request, int count) {\n  return cast_ng2mpi<MPI_Request>(&request->value, count);\n}\nMPI_Status* ng2mpi(NG_MPI_Status* status) {\n  return reinterpret_cast<MPI_Status*>(status);\n}\nMPI_Aint* ng2mpi(NG_MPI_Aint* aint) {\n  return reinterpret_cast<MPI_Aint*>(aint);\n}\nMPI_Aint* ng2mpi(NG_MPI_Aint* aint, int count) {\n  return cast_ng2mpi<MPI_Aint>(aint, count);\n}\n\nMPI_Datatype ng2mpi(NG_MPI_Datatype type) {\n  static_assert(sizeof(MPI_Datatype) <= sizeof(type.value), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Datatype>(type.value);\n}\n\nMPI_Request ng2mpi(NG_MPI_Request request) {\n  static_assert(sizeof(MPI_Request) <= sizeof(request.value), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Request>(request.value);\n}\n\nMPI_Op ng2mpi(NG_MPI_Op op) {\n  static_assert(sizeof(MPI_Op) <= sizeof(op.value), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Op>(op.value);\n}\n\nMPI_Aint ng2mpi(NG_MPI_Aint aint) {\n  static_assert(sizeof(MPI_Aint) <= sizeof(aint.value), \"Size mismatch\");\n  return cast_ng2mpi<MPI_Aint>(aint.value);\n}\n\nvoid* ng2mpi(void* ptr) { return ptr; }\nchar* ng2mpi(char* ptr) { return ptr; }\nchar*** ng2mpi(char*** ptr) { return ptr; }\nint* ng2mpi(int* ptr) { return ptr; }\nint ng2mpi(int value) { return value; }\n\n}  // namespace ngcore\n\nusing namespace ngcore;\n\nextern \"C\" {\nNGCORE_API_EXPORT void ng_init_mpi();\n}\n\nstatic bool imported_mpi4py = false;\n\nvoid ng_init_mpi() {\n#ifdef NG_PYTHON\n  NG_MPI_CommFromMPI4Py = [](py::handle src, NG_MPI_Comm& dst) -> bool {\n    if (!imported_mpi4py) {\n      import_mpi4py__MPI();\n      imported_mpi4py = true;\n    }\n    PyObject* py_src = src.ptr();\n    [[maybe_unused]] auto type = Py_TYPE(py_src);\n    if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {\n      dst = mpi2ng(*PyMPIComm_Get(py_src));\n      return !PyErr_Occurred();\n    }\n    return false;\n  };\n  NG_MPI_CommToMPI4Py = [](NG_MPI_Comm src) -> py::handle {\n    if (!imported_mpi4py) {\n      import_mpi4py__MPI();\n      imported_mpi4py = true;\n    }\n    return py::handle(PyMPIComm_New(ng2mpi(src)));\n  };\n#endif  // NG_PYTHON\n\n#include \"ng_mpi_generated_init.hpp\"\n}\n"
  },
  {
    "path": "libsrc/core/ng_mpi.hpp",
    "content": "#ifndef NG_MPI_HPP_INCLUDED\n#define NG_MPI_HPP_INCLUDED\n\n#ifdef PARALLEL\n\n#include <cstdint>\n#include <filesystem>\n#include <optional>\n\n#include \"ngcore_api.hpp\"\n\n#ifndef NG_MPI_WRAPPER\n#define OMPI_SKIP_MPICXX\n#include <mpi.h>\n#endif  // NG_MPI_WRAPPER\n\nnamespace ngcore {\n\nNGCORE_API bool MPI_Loaded();\nNGCORE_API void InitMPI(\n    std::optional<std::filesystem::path> mpi_lib_path = std::nullopt);\n\n#ifdef NG_MPI_WRAPPER\ninline void not_implemented() { throw std::runtime_error(\"Not implemented\"); }\n\nstruct NG_MPI_Status {\n  uintptr_t data[4];\n};\n\nstruct NG_MPI_Comm {\n  uintptr_t value;\n  NG_MPI_Comm() { value = 0; }\n  NG_MPI_Comm(uintptr_t value_) : value(value_) {}\n  NG_MPI_Comm(const NG_MPI_Comm &comm) : value(comm.value) {}\n\n  void operator=(int value_) { value = value_; }\n  void operator=(uintptr_t value_) { value = value_; }\n  bool operator==(const NG_MPI_Comm &comm) const { return value == comm.value; }\n  bool operator!=(const NG_MPI_Comm &comm) const { return value != comm.value; }\n};\n\nstruct NG_MPI_Datatype {\n  uintptr_t value = 0;\n  NG_MPI_Datatype() = default;\n  NG_MPI_Datatype(uintptr_t value_) : value(value_) {}\n  operator bool() const { return value != 0; }\n  void operator=(NG_MPI_Datatype type) { value = type.value; }\n  void operator=(uintptr_t value_) { value = value_; }\n  void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }\n};\n\nstruct NG_MPI_Request {\n  uintptr_t value = 0;\n  NG_MPI_Request() = default;\n  NG_MPI_Request(uintptr_t value_) : value(value_) {}\n  void operator=(uintptr_t value_) { value = value_; }\n  void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }\n};\n\nstruct NG_MPI_Op {\n  uintptr_t value;\n  NG_MPI_Op(uintptr_t value_) : value(value_) {}\n  void operator=(uintptr_t value_) { value = value_; }\n  void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }\n};\n\nstruct NG_MPI_Group {\n  uintptr_t value = 0;\n  NG_MPI_Group(uintptr_t value_) : value(value_) {}\n  NG_MPI_Group() = default;\n};\n\nstruct NG_MPI_Aint {\n  intptr_t value = 0;\n  NG_MPI_Aint(intptr_t value_) : value(value_) {}\n  NG_MPI_Aint() = default;\n};\n\n#else   // NG_MPI_WRAPPER\nusing NG_MPI_Comm = MPI_Comm;\nusing NG_MPI_Status = MPI_Status;\nusing NG_MPI_Datatype = MPI_Datatype;\nusing NG_MPI_Request = MPI_Request;\nusing NG_MPI_Op = MPI_Op;\nusing NG_MPI_Group = MPI_Group;\nusing NG_MPI_Aint = MPI_Aint;\n#endif  // NG_MPI_WRAPPER\n\n#include \"ng_mpi_generated_declarations.hpp\"\n\n}  // namespace ngcore\n\n#endif  // PARALLEL\n#endif  // NG_MPI_HPP_INCLUDED\n"
  },
  {
    "path": "libsrc/core/ng_mpi_generated_declarations.hpp",
    "content": "#ifdef NG_MPI_WRAPPER\nNGCORE_API extern double (*NG_MPI_Wtime)();\nNGCORE_API extern int (*NG_MPI_Allgather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Allreduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Alltoall)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Barrier)(NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Bcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Ibcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Comm_c2f)(NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Comm_create)(NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*);\nNGCORE_API extern int (*NG_MPI_Comm_create_group)(NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*);\nNGCORE_API extern int (*NG_MPI_Comm_free)(NG_MPI_Comm*);\nNGCORE_API extern int (*NG_MPI_Comm_group)(NG_MPI_Comm, NG_MPI_Group*);\nNGCORE_API extern int (*NG_MPI_Comm_rank)(NG_MPI_Comm, int*);\nNGCORE_API extern int (*NG_MPI_Comm_size)(NG_MPI_Comm, int*);\nNGCORE_API extern int (*NG_MPI_Finalize)();\nNGCORE_API extern int (*NG_MPI_Gather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Gatherv)(void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Get_count)(NG_MPI_Status*, NG_MPI_Datatype, int*);\nNGCORE_API extern int (*NG_MPI_Get_processor_name)(char*, int*);\nNGCORE_API extern int (*NG_MPI_Group_incl)(NG_MPI_Group, int, int*, NG_MPI_Group*);\nNGCORE_API extern int (*NG_MPI_Init)(int*, char***);\nNGCORE_API extern int (*NG_MPI_Init_thread)(int*, char***, int, int*);\nNGCORE_API extern int (*NG_MPI_Initialized)(int*);\nNGCORE_API extern int (*NG_MPI_Iprobe)(int, int, NG_MPI_Comm, int*, NG_MPI_Status*);\nNGCORE_API extern int (*NG_MPI_Irecv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Isend)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Probe)(int, int, NG_MPI_Comm, NG_MPI_Status*);\nNGCORE_API extern int (*NG_MPI_Query_thread)(int*);\nNGCORE_API extern int (*NG_MPI_Recv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*);\nNGCORE_API extern int (*NG_MPI_Recv_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Reduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Reduce_local)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op);\nNGCORE_API extern int (*NG_MPI_Request_free)(NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Scatter)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Send)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm);\nNGCORE_API extern int (*NG_MPI_Send_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Startall)(int, NG_MPI_Request*);\nNGCORE_API extern int (*NG_MPI_Type_commit)(NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_contiguous)(int, NG_MPI_Datatype, NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_create_resized)(NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_create_struct)(int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_free)(NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_get_extent)(NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*);\nNGCORE_API extern int (*NG_MPI_Type_indexed)(int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*);\nNGCORE_API extern int (*NG_MPI_Type_size)(NG_MPI_Datatype, int*);\nNGCORE_API extern int (*NG_MPI_Wait)(NG_MPI_Request*, NG_MPI_Status*);\nNGCORE_API extern int (*NG_MPI_Waitall)(int, NG_MPI_Request*, NG_MPI_Status*);\nNGCORE_API extern int (*NG_MPI_Waitany)(int, NG_MPI_Request*, int*, NG_MPI_Status*);\nNGCORE_API extern NG_MPI_Comm NG_MPI_COMM_NULL;\nNGCORE_API extern NG_MPI_Comm NG_MPI_COMM_WORLD;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_CHAR;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_C_BOOL;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_DATATYPE_NULL;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_DOUBLE;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_FLOAT;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_INT;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_SHORT;\nNGCORE_API extern NG_MPI_Datatype NG_MPI_UINT64_T;\nNGCORE_API extern NG_MPI_Op NG_MPI_LOR;\nNGCORE_API extern NG_MPI_Op NG_MPI_MAX;\nNGCORE_API extern NG_MPI_Op NG_MPI_MIN;\nNGCORE_API extern NG_MPI_Op NG_MPI_SUM;\nNGCORE_API extern NG_MPI_Request NG_MPI_REQUEST_NULL;\nNGCORE_API extern NG_MPI_Status* NG_MPI_STATUSES_IGNORE;\nNGCORE_API extern NG_MPI_Status* NG_MPI_STATUS_IGNORE;\nNGCORE_API extern int NG_MPI_ANY_SOURCE;\nNGCORE_API extern int NG_MPI_ANY_TAG;\nNGCORE_API extern int NG_MPI_MAX_PROCESSOR_NAME;\nNGCORE_API extern int NG_MPI_PROC_NULL;\nNGCORE_API extern int NG_MPI_ROOT;\nNGCORE_API extern int NG_MPI_SUBVERSION;\nNGCORE_API extern int NG_MPI_THREAD_MULTIPLE;\nNGCORE_API extern int NG_MPI_THREAD_SINGLE;\nNGCORE_API extern int NG_MPI_VERSION;\nNGCORE_API extern void* NG_MPI_IN_PLACE;\n#else  // NG_MPI_WRAPPER\n#define NG_MPI_Wtime MPI_Wtime\n#define NG_MPI_Allgather MPI_Allgather\n#define NG_MPI_Allreduce MPI_Allreduce\n#define NG_MPI_Alltoall MPI_Alltoall\n#define NG_MPI_Barrier MPI_Barrier\n#define NG_MPI_Bcast MPI_Bcast\n#define NG_MPI_Ibcast MPI_Ibcast\n#define NG_MPI_Comm_c2f MPI_Comm_c2f\n#define NG_MPI_Comm_create MPI_Comm_create\n#define NG_MPI_Comm_create_group MPI_Comm_create_group\n#define NG_MPI_Comm_free MPI_Comm_free\n#define NG_MPI_Comm_group MPI_Comm_group\n#define NG_MPI_Comm_rank MPI_Comm_rank\n#define NG_MPI_Comm_size MPI_Comm_size\n#define NG_MPI_Finalize MPI_Finalize\n#define NG_MPI_Gather MPI_Gather\n#define NG_MPI_Gatherv MPI_Gatherv\n#define NG_MPI_Get_count MPI_Get_count\n#define NG_MPI_Get_processor_name MPI_Get_processor_name\n#define NG_MPI_Group_incl MPI_Group_incl\n#define NG_MPI_Init MPI_Init\n#define NG_MPI_Init_thread MPI_Init_thread\n#define NG_MPI_Initialized MPI_Initialized\n#define NG_MPI_Iprobe MPI_Iprobe\n#define NG_MPI_Irecv MPI_Irecv\n#define NG_MPI_Isend MPI_Isend\n#define NG_MPI_Probe MPI_Probe\n#define NG_MPI_Query_thread MPI_Query_thread\n#define NG_MPI_Recv MPI_Recv\n#define NG_MPI_Recv_init MPI_Recv_init\n#define NG_MPI_Reduce MPI_Reduce\n#define NG_MPI_Reduce_local MPI_Reduce_local\n#define NG_MPI_Request_free MPI_Request_free\n#define NG_MPI_Scatter MPI_Scatter\n#define NG_MPI_Send MPI_Send\n#define NG_MPI_Send_init MPI_Send_init\n#define NG_MPI_Startall MPI_Startall\n#define NG_MPI_Type_commit MPI_Type_commit\n#define NG_MPI_Type_contiguous MPI_Type_contiguous\n#define NG_MPI_Type_create_resized MPI_Type_create_resized\n#define NG_MPI_Type_create_struct MPI_Type_create_struct\n#define NG_MPI_Type_free MPI_Type_free\n#define NG_MPI_Type_get_extent MPI_Type_get_extent\n#define NG_MPI_Type_indexed MPI_Type_indexed\n#define NG_MPI_Type_size MPI_Type_size\n#define NG_MPI_Wait MPI_Wait\n#define NG_MPI_Waitall MPI_Waitall\n#define NG_MPI_Waitany MPI_Waitany\n#define NG_MPI_COMM_NULL MPI_COMM_NULL\n#define NG_MPI_COMM_WORLD MPI_COMM_WORLD\n#define NG_MPI_CHAR MPI_CHAR\n#define NG_MPI_CXX_DOUBLE_COMPLEX MPI_CXX_DOUBLE_COMPLEX\n#define NG_MPI_C_BOOL MPI_C_BOOL\n#define NG_MPI_DATATYPE_NULL MPI_DATATYPE_NULL\n#define NG_MPI_DOUBLE MPI_DOUBLE\n#define NG_MPI_FLOAT MPI_FLOAT\n#define NG_MPI_INT MPI_INT\n#define NG_MPI_SHORT MPI_SHORT\n#define NG_MPI_UINT64_T MPI_UINT64_T\n#define NG_MPI_LOR MPI_LOR\n#define NG_MPI_MAX MPI_MAX\n#define NG_MPI_MIN MPI_MIN\n#define NG_MPI_SUM MPI_SUM\n#define NG_MPI_REQUEST_NULL MPI_REQUEST_NULL\n#define NG_MPI_STATUSES_IGNORE MPI_STATUSES_IGNORE\n#define NG_MPI_STATUS_IGNORE MPI_STATUS_IGNORE\n#define NG_MPI_ANY_SOURCE MPI_ANY_SOURCE\n#define NG_MPI_ANY_TAG MPI_ANY_TAG\n#define NG_MPI_MAX_PROCESSOR_NAME MPI_MAX_PROCESSOR_NAME\n#define NG_MPI_PROC_NULL MPI_PROC_NULL\n#define NG_MPI_ROOT MPI_ROOT\n#define NG_MPI_SUBVERSION MPI_SUBVERSION\n#define NG_MPI_THREAD_MULTIPLE MPI_THREAD_MULTIPLE\n#define NG_MPI_THREAD_SINGLE MPI_THREAD_SINGLE\n#define NG_MPI_VERSION MPI_VERSION\n#define NG_MPI_IN_PLACE MPI_IN_PLACE\n#endif // NG_MPI_WRAPPER\n"
  },
  {
    "path": "libsrc/core/ng_mpi_generated_dummy_init.hpp",
    "content": "decltype(NG_MPI_Wtime) NG_MPI_Wtime = []()->double { throw no_mpi(); };\ndecltype(NG_MPI_Allgather) NG_MPI_Allgather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Allreduce) NG_MPI_Allreduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Alltoall) NG_MPI_Alltoall = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Barrier) NG_MPI_Barrier = [](NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Bcast) NG_MPI_Bcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Ibcast) NG_MPI_Ibcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_c2f) NG_MPI_Comm_c2f = [](NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_create) NG_MPI_Comm_create = [](NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_create_group) NG_MPI_Comm_create_group = [](NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_free) NG_MPI_Comm_free = [](NG_MPI_Comm*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_group) NG_MPI_Comm_group = [](NG_MPI_Comm, NG_MPI_Group*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_rank) NG_MPI_Comm_rank = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Comm_size) NG_MPI_Comm_size = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Finalize) NG_MPI_Finalize = []()->int { throw no_mpi(); };\ndecltype(NG_MPI_Gather) NG_MPI_Gather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Gatherv) NG_MPI_Gatherv = [](void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Get_count) NG_MPI_Get_count = [](NG_MPI_Status*, NG_MPI_Datatype, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Get_processor_name) NG_MPI_Get_processor_name = [](char*, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Group_incl) NG_MPI_Group_incl = [](NG_MPI_Group, int, int*, NG_MPI_Group*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Init) NG_MPI_Init = [](int*, char***)->int { throw no_mpi(); };\ndecltype(NG_MPI_Init_thread) NG_MPI_Init_thread = [](int*, char***, int, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Initialized) NG_MPI_Initialized = [](int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Iprobe) NG_MPI_Iprobe = [](int, int, NG_MPI_Comm, int*, NG_MPI_Status*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Irecv) NG_MPI_Irecv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Isend) NG_MPI_Isend = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Probe) NG_MPI_Probe = [](int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Query_thread) NG_MPI_Query_thread = [](int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Recv) NG_MPI_Recv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Recv_init) NG_MPI_Recv_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Reduce) NG_MPI_Reduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Reduce_local) NG_MPI_Reduce_local = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op)->int { throw no_mpi(); };\ndecltype(NG_MPI_Request_free) NG_MPI_Request_free = [](NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Scatter) NG_MPI_Scatter = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Send) NG_MPI_Send = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm)->int { throw no_mpi(); };\ndecltype(NG_MPI_Send_init) NG_MPI_Send_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Startall) NG_MPI_Startall = [](int, NG_MPI_Request*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_commit) NG_MPI_Type_commit = [](NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_contiguous) NG_MPI_Type_contiguous = [](int, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_create_resized) NG_MPI_Type_create_resized = [](NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_create_struct) NG_MPI_Type_create_struct = [](int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_free) NG_MPI_Type_free = [](NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_get_extent) NG_MPI_Type_get_extent = [](NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_indexed) NG_MPI_Type_indexed = [](int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Type_size) NG_MPI_Type_size = [](NG_MPI_Datatype, int*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Wait) NG_MPI_Wait = [](NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Waitall) NG_MPI_Waitall = [](int, NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };\ndecltype(NG_MPI_Waitany) NG_MPI_Waitany = [](int, NG_MPI_Request*, int*, NG_MPI_Status*)->int { throw no_mpi(); };\nNG_MPI_Comm NG_MPI_COMM_NULL = 0;\nNG_MPI_Comm NG_MPI_COMM_WORLD = 0;\nNG_MPI_Datatype NG_MPI_CHAR = 0;\nNG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX = 0;\nNG_MPI_Datatype NG_MPI_C_BOOL = 0;\nNG_MPI_Datatype NG_MPI_DATATYPE_NULL = 0;\nNG_MPI_Datatype NG_MPI_DOUBLE = 0;\nNG_MPI_Datatype NG_MPI_FLOAT = 0;\nNG_MPI_Datatype NG_MPI_INT = 0;\nNG_MPI_Datatype NG_MPI_SHORT = 0;\nNG_MPI_Datatype NG_MPI_UINT64_T = 0;\nNG_MPI_Op NG_MPI_LOR = 0;\nNG_MPI_Op NG_MPI_MAX = 0;\nNG_MPI_Op NG_MPI_MIN = 0;\nNG_MPI_Op NG_MPI_SUM = 0;\nNG_MPI_Request NG_MPI_REQUEST_NULL = 0;\nNG_MPI_Status* NG_MPI_STATUSES_IGNORE = 0;\nNG_MPI_Status* NG_MPI_STATUS_IGNORE = 0;\nint NG_MPI_ANY_SOURCE = 0;\nint NG_MPI_ANY_TAG = 0;\nint NG_MPI_MAX_PROCESSOR_NAME = 0;\nint NG_MPI_PROC_NULL = 0;\nint NG_MPI_ROOT = 0;\nint NG_MPI_SUBVERSION = 0;\nint NG_MPI_THREAD_MULTIPLE = 0;\nint NG_MPI_THREAD_SINGLE = 0;\nint NG_MPI_VERSION = 0;\nvoid* NG_MPI_IN_PLACE = 0;\n"
  },
  {
    "path": "libsrc/core/ng_mpi_generated_init.hpp",
    "content": "NG_MPI_Wtime = []()->double { return MPI_Wtime(); };\nNG_MPI_Allgather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Allgather( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Allreduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, NG_MPI_Comm arg5)->int { return MPI_Allreduce( arg0,  arg1,  arg2,  ng2mpi(arg3),  ng2mpi(arg4),  ng2mpi(arg5)); };\nNG_MPI_Alltoall = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Alltoall( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Barrier = [](NG_MPI_Comm arg0)->int { return MPI_Barrier( ng2mpi(arg0)); };\nNG_MPI_Bcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4)->int { return MPI_Bcast( arg0,  arg1,  ng2mpi(arg2),  arg3,  ng2mpi(arg4)); };\nNG_MPI_Ibcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4, NG_MPI_Request* arg5)->int { return MPI_Ibcast( arg0,  arg1,  ng2mpi(arg2),  arg3,  ng2mpi(arg4),  ng2mpi(arg5)); };\nNG_MPI_Comm_c2f = [](NG_MPI_Comm arg0)->int { return MPI_Comm_c2f( ng2mpi(arg0)); };\nNG_MPI_Comm_create = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, NG_MPI_Comm* arg2)->int { return MPI_Comm_create( ng2mpi(arg0),  ng2mpi(arg1),  ng2mpi(arg2)); };\nNG_MPI_Comm_create_group = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, int arg2, NG_MPI_Comm* arg3)->int { return MPI_Comm_create_group( ng2mpi(arg0),  ng2mpi(arg1),  arg2,  ng2mpi(arg3)); };\nNG_MPI_Comm_free = [](NG_MPI_Comm* arg0)->int { return MPI_Comm_free( ng2mpi(arg0)); };\nNG_MPI_Comm_group = [](NG_MPI_Comm arg0, NG_MPI_Group* arg1)->int { return MPI_Comm_group( ng2mpi(arg0),  ng2mpi(arg1)); };\nNG_MPI_Comm_rank = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_rank( ng2mpi(arg0),  arg1); };\nNG_MPI_Comm_size = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_size( ng2mpi(arg0),  arg1); };\nNG_MPI_Finalize = []()->int { return MPI_Finalize(); };\nNG_MPI_Gather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Gather( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  arg6,  ng2mpi(arg7)); };\nNG_MPI_Gatherv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int* arg4, int* arg5, NG_MPI_Datatype arg6, int arg7, NG_MPI_Comm arg8)->int { return MPI_Gatherv( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  arg5,  ng2mpi(arg6),  arg7,  ng2mpi(arg8)); };\nNG_MPI_Get_count = [](NG_MPI_Status* arg0, NG_MPI_Datatype arg1, int* arg2)->int { return MPI_Get_count( ng2mpi(arg0),  ng2mpi(arg1),  arg2); };\nNG_MPI_Get_processor_name = [](char* arg0, int* arg1)->int { return MPI_Get_processor_name( arg0,  arg1); };\nNG_MPI_Group_incl = [](NG_MPI_Group arg0, int arg1, int* arg2, NG_MPI_Group* arg3)->int { return MPI_Group_incl( ng2mpi(arg0),  arg1,  arg2,  ng2mpi(arg3)); };\nNG_MPI_Init = [](int* arg0, char*** arg1)->int { return MPI_Init( arg0,  arg1); };\nNG_MPI_Init_thread = [](int* arg0, char*** arg1, int arg2, int* arg3)->int { return MPI_Init_thread( arg0,  arg1,  arg2,  arg3); };\nNG_MPI_Initialized = [](int* arg0)->int { return MPI_Initialized( arg0); };\nNG_MPI_Iprobe = [](int arg0, int arg1, NG_MPI_Comm arg2, int* arg3, NG_MPI_Status* arg4)->int { return MPI_Iprobe( arg0,  arg1,  ng2mpi(arg2),  arg3,  ng2mpi(arg4)); };\nNG_MPI_Irecv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Irecv( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Isend = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Isend( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Probe = [](int arg0, int arg1, NG_MPI_Comm arg2, NG_MPI_Status* arg3)->int { return MPI_Probe( arg0,  arg1,  ng2mpi(arg2),  ng2mpi(arg3)); };\nNG_MPI_Query_thread = [](int* arg0)->int { return MPI_Query_thread( arg0); };\nNG_MPI_Recv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Status* arg6)->int { return MPI_Recv( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Recv_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Recv_init( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Reduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, int arg5, NG_MPI_Comm arg6)->int { return MPI_Reduce( arg0,  arg1,  arg2,  ng2mpi(arg3),  ng2mpi(arg4),  arg5,  ng2mpi(arg6)); };\nNG_MPI_Reduce_local = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4)->int { return MPI_Reduce_local( arg0,  arg1,  arg2,  ng2mpi(arg3),  ng2mpi(arg4)); };\nNG_MPI_Request_free = [](NG_MPI_Request* arg0)->int { return MPI_Request_free( ng2mpi(arg0)); };\nNG_MPI_Scatter = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Scatter( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  arg6,  ng2mpi(arg7)); };\nNG_MPI_Send = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5)->int { return MPI_Send( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5)); };\nNG_MPI_Send_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Send_init( arg0,  arg1,  ng2mpi(arg2),  arg3,  arg4,  ng2mpi(arg5),  ng2mpi(arg6)); };\nNG_MPI_Startall = [](int arg0, NG_MPI_Request* arg1)->int { return MPI_Startall( arg0,  ng2mpi(arg1, arg0)); };\nNG_MPI_Type_commit = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_commit( ng2mpi(arg0)); };\nNG_MPI_Type_contiguous = [](int arg0, NG_MPI_Datatype arg1, NG_MPI_Datatype* arg2)->int { return MPI_Type_contiguous( arg0,  ng2mpi(arg1),  ng2mpi(arg2)); };\nNG_MPI_Type_create_resized = [](NG_MPI_Datatype arg0, NG_MPI_Aint arg1, NG_MPI_Aint arg2, NG_MPI_Datatype* arg3)->int { return MPI_Type_create_resized( ng2mpi(arg0),  ng2mpi(arg1),  ng2mpi(arg2),  ng2mpi(arg3)); };\nNG_MPI_Type_create_struct = [](int arg0, int* arg1, NG_MPI_Aint* arg2, NG_MPI_Datatype* arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_create_struct( arg0,  arg1,  ng2mpi(arg2, arg0),  ng2mpi(arg3, arg0),  ng2mpi(arg4)); };\nNG_MPI_Type_free = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_free( ng2mpi(arg0)); };\nNG_MPI_Type_get_extent = [](NG_MPI_Datatype arg0, NG_MPI_Aint* arg1, NG_MPI_Aint* arg2)->int { return MPI_Type_get_extent( ng2mpi(arg0),  ng2mpi(arg1),  ng2mpi(arg2)); };\nNG_MPI_Type_indexed = [](int arg0, int* arg1, int* arg2, NG_MPI_Datatype arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_indexed( arg0,  arg1,  arg2,  ng2mpi(arg3),  ng2mpi(arg4)); };\nNG_MPI_Type_size = [](NG_MPI_Datatype arg0, int* arg1)->int { return MPI_Type_size( ng2mpi(arg0),  arg1); };\nNG_MPI_Wait = [](NG_MPI_Request* arg0, NG_MPI_Status* arg1)->int { return MPI_Wait( ng2mpi(arg0),  ng2mpi(arg1)); };\nNG_MPI_Waitall = [](int arg0, NG_MPI_Request* arg1, NG_MPI_Status* arg2)->int { return MPI_Waitall( arg0,  ng2mpi(arg1, arg0),  ng2mpi(arg2)); };\nNG_MPI_Waitany = [](int arg0, NG_MPI_Request* arg1, int* arg2, NG_MPI_Status* arg3)->int { return MPI_Waitany( arg0,  ng2mpi(arg1, arg0),  arg2,  ng2mpi(arg3)); };\nNG_MPI_COMM_NULL = mpi2ng(MPI_COMM_NULL);\nNG_MPI_COMM_WORLD = mpi2ng(MPI_COMM_WORLD);\nNG_MPI_CHAR = mpi2ng(MPI_CHAR);\nNG_MPI_CXX_DOUBLE_COMPLEX = mpi2ng(MPI_CXX_DOUBLE_COMPLEX);\nNG_MPI_C_BOOL = mpi2ng(MPI_C_BOOL);\nNG_MPI_DATATYPE_NULL = mpi2ng(MPI_DATATYPE_NULL);\nNG_MPI_DOUBLE = mpi2ng(MPI_DOUBLE);\nNG_MPI_FLOAT = mpi2ng(MPI_FLOAT);\nNG_MPI_INT = mpi2ng(MPI_INT);\nNG_MPI_SHORT = mpi2ng(MPI_SHORT);\nNG_MPI_UINT64_T = mpi2ng(MPI_UINT64_T);\nNG_MPI_LOR = mpi2ng(MPI_LOR);\nNG_MPI_MAX = mpi2ng(MPI_MAX);\nNG_MPI_MIN = mpi2ng(MPI_MIN);\nNG_MPI_SUM = mpi2ng(MPI_SUM);\nNG_MPI_REQUEST_NULL = mpi2ng(MPI_REQUEST_NULL);\nNG_MPI_STATUSES_IGNORE = mpi2ng(MPI_STATUSES_IGNORE);\nNG_MPI_STATUS_IGNORE = mpi2ng(MPI_STATUS_IGNORE);\nNG_MPI_ANY_SOURCE = mpi2ng(MPI_ANY_SOURCE);\nNG_MPI_ANY_TAG = mpi2ng(MPI_ANY_TAG);\nNG_MPI_MAX_PROCESSOR_NAME = mpi2ng(MPI_MAX_PROCESSOR_NAME);\nNG_MPI_PROC_NULL = mpi2ng(MPI_PROC_NULL);\nNG_MPI_ROOT = mpi2ng(MPI_ROOT);\nNG_MPI_SUBVERSION = mpi2ng(MPI_SUBVERSION);\nNG_MPI_THREAD_MULTIPLE = mpi2ng(MPI_THREAD_MULTIPLE);\nNG_MPI_THREAD_SINGLE = mpi2ng(MPI_THREAD_SINGLE);\nNG_MPI_VERSION = mpi2ng(MPI_VERSION);\nNG_MPI_IN_PLACE = mpi2ng(MPI_IN_PLACE);\n"
  },
  {
    "path": "libsrc/core/ng_mpi_native.hpp",
    "content": "#ifndef NG_MPI_NATIVE_HPP\n#define NG_MPI_NATIVE_HPP\n\n#include <mpi.h>\n\n#include \"mpi_wrapper.hpp\"\n#include \"ng_mpi.hpp\"\n\nnamespace ngcore {\n\nMPI_Comm NG_MPI_Native(NG_MPI_Comm comm) {\n  return reinterpret_cast<MPI_Comm>(comm.value);\n}\n\nMPI_Comm NG_MPI_Native(NgMPI_Comm comm) {\n  return reinterpret_cast<MPI_Comm>(static_cast<NG_MPI_Comm>(comm).value);\n}\n\nNG_MPI_Comm NG_MPI_From_Native (MPI_Comm comm) {\n  return {reinterpret_cast<uintptr_t>(comm)};\n}\n\n}  // namespace ngcore\n\n#endif  // NG_MPI_NATIVE_HPP\n"
  },
  {
    "path": "libsrc/core/ng_mpi_wrapper.cpp",
    "content": "#ifdef PARALLEL\n\n#include <filesystem>\n#include <iostream>\n#include <stdexcept>\n\n#include \"ng_mpi.hpp\"\n#include \"ngstream.hpp\"\n#ifdef NG_PYTHON\n#include \"python_ngcore.hpp\"\n#endif // NG_PYTHON\n#include \"utils.hpp\"\n\nusing std::cerr;\nusing std::cout;\nusing std::endl;\n\n#ifndef NG_MPI_WRAPPER\n#ifdef NG_PYTHON\n#define MPI4PY_LIMITED_API 1\n#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1\n#define MPI4PY_LIMITED_API_SKIP_SESSION 1\n#include \"mpi4py_pycapi.h\"  // mpi4py < 4.0.0\n#endif // NG_PYTHON\n#endif // NG_MPI_WRAPPER\n\nnamespace ngcore {\n\n#ifdef NG_MPI_WRAPPER\nstatic std::unique_ptr<SharedLibrary> mpi_lib, ng_mpi_lib;\nstatic bool need_mpi_finalize = false;\n\nstruct MPIFinalizer {\n  ~MPIFinalizer() {\n    if (need_mpi_finalize) {\n      cout << IM(5) << \"Calling MPI_Finalize\" << endl;\n      NG_MPI_Finalize();\n    }\n  }\n} mpi_finalizer;\n\nbool MPI_Loaded() { return ng_mpi_lib != nullptr; }\n\nvoid InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {\n  if (ng_mpi_lib) return;\n\n  cout << IM(3) << \"InitMPI\" << endl;\n\n  std::string vendor = \"\";\n  std::string mpi4py_lib_file = \"\";\n\n  if (mpi_lib_path) {\n    // Dynamic load of given shared MPI library\n    // Then call MPI_Init, read the library version and set the vender name\n    try {\n      typedef int (*init_handle)(int *, char ***);\n      typedef int (*mpi_initialized_handle)(int *);\n      mpi_lib =\n          std::make_unique<SharedLibrary>(*mpi_lib_path, std::nullopt, true);\n      auto mpi_init = mpi_lib->GetSymbol<init_handle>(\"MPI_Init\");\n      auto mpi_initialized =\n          mpi_lib->GetSymbol<mpi_initialized_handle>(\"MPI_Initialized\");\n\n      int flag = 0;\n      mpi_initialized(&flag);\n      if (!flag) {\n        typedef const char *pchar;\n        int argc = 1;\n        pchar args[] = {\"netgen\", nullptr};\n        pchar *argv = &args[0];\n        cout << IM(5) << \"Calling MPI_Init\" << endl;\n        mpi_init(&argc, (char ***)argv);\n        need_mpi_finalize = true;\n      }\n\n      char c_version_string[65536];\n      c_version_string[0] = '\\0';\n      int result_len = 0;\n      typedef void (*get_version_handle)(char *, int *);\n      auto get_version =\n          mpi_lib->GetSymbol<get_version_handle>(\"MPI_Get_library_version\");\n      get_version(c_version_string, &result_len);\n      std::string version = c_version_string;\n\n      if (version.substr(0, 8) == \"Open MPI\")\n        vendor = \"Open MPI\";\n      else if (version.substr(0, 5) == \"MPICH\")\n        vendor = \"MPICH\";\n      else if (version.substr(0, 13) == \"Microsoft MPI\")\n        vendor = \"Microsoft MPI\";\n      else if (version.substr(0, 12) == \"Intel(R) MPI\")\n        vendor = \"Intel MPI\";\n      else\n        throw std::runtime_error(\n            std::string(\"Unknown MPI version: \" + version));\n    } catch (std::runtime_error &e) {\n      cerr << \"Could not load MPI: \" << e.what() << endl;\n      throw e;\n    }\n  } else {\n#ifdef NG_PYTHON\n    // Use mpi4py to init MPI library and get the vendor name\n    auto mpi4py = py::module::import(\"mpi4py.MPI\");\n    vendor = mpi4py.attr(\"get_vendor\")()[py::int_(0)].cast<std::string>();\n\n#ifndef WIN32\n    // Load mpi4py library (it exports all MPI symbols) to have all MPI symbols\n    // available before the ng_mpi wrapper is loaded This is not necessary on\n    // windows as the matching mpi dll is linked to the ng_mpi wrapper directly\n    mpi4py_lib_file = mpi4py.attr(\"__file__\").cast<std::string>();\n    mpi_lib =\n        std::make_unique<SharedLibrary>(mpi4py_lib_file, std::nullopt, true);\n#endif  // WIN32\n#endif // NG_PYTHON\n  }\n\n  std::string ng_lib_name = \"\";\n  if (vendor == \"Open MPI\")\n    ng_lib_name = \"ng_openmpi\";\n  else if (vendor == \"MPICH\")\n    ng_lib_name = \"ng_mpich\";\n  else if (vendor == \"Microsoft MPI\")\n    ng_lib_name = \"ng_microsoft_mpi\";\n  else if (vendor == \"Intel MPI\")\n    ng_lib_name = \"ng_intel_mpi\";\n  else\n    throw std::runtime_error(\"Unknown MPI vendor: \" + vendor);\n\n  ng_lib_name += NETGEN_SHARED_LIBRARY_SUFFIX;\n\n  // Load the ng_mpi wrapper and call ng_init_mpi to set all function pointers\n  typedef void (*ng_init_handle)();\n  ng_mpi_lib = std::make_unique<SharedLibrary>(ng_lib_name);\n  ng_mpi_lib->GetSymbol<ng_init_handle>(\"ng_init_mpi\")();\n  std::cout << IM(3) << \"MPI wrapper loaded, vendor: \" << vendor << endl;\n}\n\nstatic std::runtime_error no_mpi() {\n  return std::runtime_error(\"MPI not enabled\");\n}\n\n#ifdef NG_PYTHON\ndecltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =\n    [](py::handle py_obj, NG_MPI_Comm &ng_comm) -> bool {\n  // If this gets called, it means that we want to convert an mpi4py\n  // communicator to a Netgen MPI communicator, but the Netgen MPI wrapper\n  // runtime was not yet initialized.\n\n  // store the current address of this function\n  auto old_converter_address = NG_MPI_CommFromMPI4Py;\n\n  // initialize the MPI wrapper runtime, this sets all the function pointers\n  InitMPI();\n\n  // if the initialization was successful, the function pointer should have\n  // changed\n  // -> call the actual conversion function\n  if (NG_MPI_CommFromMPI4Py != old_converter_address)\n    return NG_MPI_CommFromMPI4Py(py_obj, ng_comm);\n\n  // otherwise, something strange happened\n  throw no_mpi();\n};\ndecltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =\n    [](NG_MPI_Comm) -> py::handle { throw no_mpi(); };\n#endif  // NG_PYTHON\n\n#include \"ng_mpi_generated_dummy_init.hpp\"\n#else  // NG_MPI_WRAPPER\n\nstatic bool imported_mpi4py = false;\n#ifdef NG_PYTHON\ndecltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =\n    [](py::handle src, NG_MPI_Comm &dst) -> bool {\n  if (!imported_mpi4py) {\n    import_mpi4py__MPI();\n    imported_mpi4py = true;\n  }\n  PyObject *py_src = src.ptr();\n  // auto type = Py_TYPE(py_src);\n  if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {\n    dst = *PyMPIComm_Get(py_src);\n    return !PyErr_Occurred();\n  }\n  return false;\n};\n\ndecltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =\n    [](NG_MPI_Comm src) -> py::handle {\n  if (!imported_mpi4py) {\n    import_mpi4py__MPI();\n    imported_mpi4py = true;\n  }\n  return py::handle(PyMPIComm_New(src));\n};\n\n#endif  // NG_PYTHON\n\nbool MPI_Loaded() { return true; }\nvoid InitMPI(std::optional<std::filesystem::path>) {}\n\n#endif  // NG_MPI_WRAPPER\n\n}  // namespace ngcore\n\n#endif  // PARALLEL\n"
  },
  {
    "path": "libsrc/core/ngcore.hpp",
    "content": "#ifndef NETGEN_CORE_NGCORE_HPP\n#define NETGEN_CORE_NGCORE_HPP\n\n#include \"archive.hpp\"\n#include \"array.hpp\"\n#include \"bitarray.hpp\"\n#include \"exception.hpp\"\n#include \"flags.hpp\"\n#include \"table.hpp\"\n#include \"hashtable.hpp\"\n#include \"localheap.hpp\"\n#include \"logging.hpp\"\n// #include \"mpi_wrapper.hpp\"\n#include \"profiler.hpp\"\n#include \"signal.hpp\"\n#include \"simd.hpp\"\n#include \"autodiff.hpp\"\n#include \"autodiffdiff.hpp\"\n#include \"symboltable.hpp\"\n#include \"taskmanager.hpp\"\n#include \"version.hpp\"\n#include \"xbool.hpp\"\n#include \"ngstream.hpp\"\n#include \"utils.hpp\"\n#include \"ranges.hpp\"\n#include \"statushandler.hpp\"\n\n#endif // NETGEN_CORE_NGCORE_HPP\n\n\n\n\n"
  },
  {
    "path": "libsrc/core/ngcore_api.hpp",
    "content": "#ifndef NETGEN_CORE_NGCORE_API_HPP\n#define NETGEN_CORE_NGCORE_API_HPP\n\n#include \"netgen_config.hpp\"\n\n#ifdef WIN32\n\n// This function or variable may be unsafe. Consider using _ftime64_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.\n#pragma warning(disable:4244)\n#pragma warning(disable:4996)\n\n// multiple inheritance via dominance\n#pragma warning(disable:4250)\n\n// needs to have dll-interface to be used by clients of class\n#pragma warning(disable:4251)\n\n// size_t to int conversion:\n#pragma warning(disable:4267)\n\n// non dll-interface class 'std::exception' used as base for dll-interface class\n#pragma warning(disable:4275)\n\n// C++ exception specification ignored except to indicate a function is not __declspec(nothrow)\n#pragma warning(disable:4290)\n\n// no suitable definition provided for explicit template instantiation request\n#pragma warning(disable:4661)\n\n// bool-int conversion\n#pragma warning(disable:4800)\n\n// '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation\n#pragma warning(disable:4910)\n\n#endif // WIN32\n\n\n#ifdef WIN32\n        #define NGCORE_API_EXPORT __declspec(dllexport)\n        #define NGCORE_API_IMPORT __declspec(dllimport)\n#else\n        #define NGCORE_API_EXPORT __attribute__((visibility(\"default\")))\n        #define NGCORE_API_IMPORT __attribute__((visibility(\"default\")))\n#endif\n\n#ifdef NGCORE_EXPORTS\n        #define NGCORE_API NGCORE_API_EXPORT\n#else\n        #define NGCORE_API NGCORE_API_IMPORT\n#endif\n\n// Set __host__ __device__ for all inline functions\n#ifdef __CUDACC__\n  #define NETGEN_HD __host__ __device__\n#else // __CUDACC__\n  #define NETGEN_HD\n#endif // __CUDACC__\n\n\n#ifdef __CUDACC__\n// partial override of overloaded function (Archive, MultAdd)\n#pragma nv_diag_suppress 611\n#endif\n\n\n\n#ifdef __INTEL_COMPILER\n  #define NETGEN_ALWAYS_INLINE __forceinline\n  #define NETGEN_INLINE __forceinline inline\n  #ifdef WIN32\n    #define NETGEN_LAMBDA_INLINE\n  #else\n    #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__))\n  #endif\n#else\n  #ifdef __GNUC__\n    #define NETGEN_ALWAYS_INLINE __attribute__ ((__always_inline__))\n    #define NETGEN_INLINE __attribute__ ((__always_inline__)) inline NETGEN_HD\n    #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) NETGEN_HD\n    #define NETGEN_VLA\n  #else\n    #define NETGEN_ALWAYS_INLINE\n    #define NETGEN_INLINE inline\n    #define NETGEN_LAMBDA_INLINE\n  #endif\n#endif\n\n#if defined(__amd64__) || defined(_M_AMD64)\n#define NETGEN_ARCH_AMD64\n#endif\n\n#if defined(__aarch64__) || defined(_M_ARM64)\n#define NETGEN_ARCH_ARM64\n#endif\n\n#if defined(__arm__) || defined(_M_ARM)\n#define NETGEN_ARCH_ARM\n#endif\n\n#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED\n#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101400\n// The c++ standard library on MacOS 10.13 and earlier has no aligned new operator,\n// thus implement it here globally\n#include <mm_malloc.h>\n#ifdef __clang__\n#pragma clang diagnostic ignored \"-Winline-new-delete\"\n#endif\ninline void * operator new (size_t s, std::align_val_t al)\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n    return _mm_malloc(s, int(al));\n  else\n    return new char[s];\n}\n\ninline void * operator new[] (size_t s, std::align_val_t al)\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n    return _mm_malloc(s, int(al));\n  else\n    return new char[s];\n}\n\ninline void operator delete  ( void* ptr, std::align_val_t al ) noexcept\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n     _mm_free(ptr);\n  else\n    delete (char*)ptr;\n}\n\ninline void operator delete[]( void* ptr, std::align_val_t al ) noexcept\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n     _mm_free(ptr);\n  else\n    delete[] (char*)ptr;\n}\n\ninline void operator delete  ( void* ptr, std::size_t sz, std::align_val_t al ) noexcept\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n     _mm_free(ptr);\n  else\n    delete (char*)ptr;\n}\n\ninline void operator delete[]( void* ptr, std::size_t sz, std::align_val_t al ) noexcept\n{\n  if (int(al) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)\n     _mm_free(ptr);\n  else\n    delete[] (char*)ptr;\n}\n\n#endif // __MAC_OS_X_VERSION_MIN_REQUIRED\n#endif // __MAC_OS_X_VERSION_MIN_REQUIRED < 101300\n\n#endif // NETGEN_CORE_NGCORE_API_HPP\n"
  },
  {
    "path": "libsrc/core/ngstream.hpp",
    "content": "#ifndef FILE_NGSTREAM\n#define FILE_NGSTREAM\n\n/**************************************************************************/\n/* File:   ng(s)stream.hpp                                                */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   20. Jul. 2011                                                  */\n/**************************************************************************/\n\n// #include <ios>\n// #include <iostream>\nnamespace ngcore\n{\n\n  NGCORE_API extern int printmessage_importance;\n \n  // important message\n  class IM\n  {\n    int value;\n  public:\n    IM (int val) : value(val) { ; }\n    int Value () const { return value; }\n  };\n\n  class trunc\n  {\n    double eps;\n  public:\n    trunc (double aeps) : eps(aeps) { ; }\n    double Eps() const { return eps; }\n  };\n  \n  class NGSOStream\n  {\n    std::ostream & ost;\n    bool active;\n    NGCORE_API static bool glob_active;\n    double trunc;\n  public:\n    NGSOStream (std::ostream & aost, bool aactive)\n      : ost(aost), active(aactive), trunc(-1) { ; }\n    NGSOStream & SetTrunc (double atrunc) { trunc = atrunc; return *this; }\n    double GetTrunc () const { return trunc; }\n    bool Active () const { return active && glob_active; }\n    std::ostream & GetStream () { return ost; }\n    static void SetGlobalActive (bool b) { glob_active = b; }\n  };\n  \n  inline NGSOStream operator<< (std::ostream & ost, const IM & im)\n  {\n    return NGSOStream (ost, \n\t\t       (im.Value() <= printmessage_importance));\n  }\n\n  /*\n    // doesn't work for matrices\n  inline NGSOStream operator<< (ostream & ost, trunc tr)\n  {\n    cout << \"set trunc modifier\" << endl;\n    return NGSOStream (ost, true).SetTrunc (tr.Eps());\n  }\n  */\n\n  \n  template <typename T>\n  inline NGSOStream operator<< (NGSOStream ngsost, const T & data)\n  {\n    if (ngsost.Active())\n      ngsost.GetStream() << data;\n    return ngsost;\n  }\n\n  /*\n  inline NGSOStream operator<< (NGSOStream ngsost, const double & data)\n  {\n    cout << \"double out\" << endl;\n    if (ngsost.Active())\n      {\n        double hdata = data;\n        if (fabs (hdata) < ngsost.GetTrunc()) hdata = 0.0;\n        ngsost.GetStream() << hdata;\n      }\n    return ngsost;\n  }\n  */\n  \n  inline NGSOStream operator<< (NGSOStream ngsost, std::ostream& ( *pf )(std::ostream&))\n  {\n    if ( ngsost.Active() )\n      ngsost.GetStream() << (*pf);\n\n    return ngsost;\n  }\n  \n  inline NGSOStream operator<< (NGSOStream ngsost, std::ios& ( *pf )(std::ios&))\n  {\n    if ( ngsost.Active() )\n      ngsost.GetStream() << (*pf);\n    \n    return ngsost;\n  }\n\n  inline NGSOStream operator<< (NGSOStream ngsost, std::ios_base& ( *pf )(std::ios_base&))\n  {\n    if ( ngsost.Active() )\n      ngsost.GetStream() << (*pf);\n    \n    return ngsost;\n  }\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/core/paje_trace.cpp",
    "content": "#include <algorithm>\n#include <atomic>\n#include <iostream>\n#include <map>\n#include <set>\n#include <thread>\n\n#include \"archive.hpp\"           // for Demangle\n#include \"paje_trace.hpp\"\n#include \"ng_mpi.hpp\"\n#include \"profiler.hpp\"\n#include \"mpi_wrapper.hpp\"\n\nextern const char *header;\n\nconstexpr int MPI_PAJE_WRITER = 1;\nconstexpr int ASSUMED_MPI_MAX_PROCESSOR_NAME = 256;\n\nnamespace ngcore\n{\n  static std::string GetTimerName( int id )\n  {\n#ifndef PARALLEL\n    return NgProfiler::GetName(id);\n#else // PARALLEL\n    if(id<NgProfiler::SIZE)\n      return NgProfiler::GetName(id);\n\n    NgMPI_Comm comm(NG_MPI_COMM_WORLD);\n    return NgProfiler::GetName(id-NgProfiler::SIZE*comm.Rank());\n#endif // PARALLEL\n  }\n\n  std::vector<PajeTrace::MemoryEvent> PajeTrace::memory_events;\n\n  // Produce no traces by default\n  size_t PajeTrace::max_tracefile_size = 0;\n\n  // If true, produce variable counting active threads\n  // increases trace by a factor of two\n  bool PajeTrace::trace_thread_counter = false;\n  bool PajeTrace::trace_threads = true;\n  bool PajeTrace::mem_tracing_enabled = true;\n  bool PajeTrace::write_paje_file = true;\n\n  PajeTrace :: PajeTrace(int anthreads, std::string aname)\n  {\n\n    nthreads = anthreads;\n    tracefile_name = std::move(aname);\n\n    int bytes_per_event=33;\n    max_num_events_per_thread = std::min( static_cast<size_t>(std::numeric_limits<int>::max()), max_tracefile_size/bytes_per_event/(nthreads+1+trace_thread_counter*nthreads)*10/7);\n    if(max_num_events_per_thread>0)\n    {\n      logger->info( \"Tracefile size = {}MB\", max_tracefile_size/1024/1024);\n      logger->info( \"Tracing {} events per thread\", max_num_events_per_thread);\n    }\n\n    tasks.resize(nthreads);\n    int reserve_size = std::min(1000000U, max_num_events_per_thread);\n    for(auto & t : tasks)\n        t.reserve(reserve_size);\n\n    links.resize(nthreads);\n    for(auto & l : links)\n      l.reserve(reserve_size);\n\n    jobs.reserve(reserve_size);\n    timer_events.reserve(reserve_size);\n    gpu_events.reserve(reserve_size);\n    memory_events.reserve(1024*1024);\n\n    // sync start time when running in parallel\n#ifdef PARALLEL\n    if(MPI_Loaded())\n    {\n      NgMPI_Comm comm(NG_MPI_COMM_WORLD);\n      for([[maybe_unused]] auto i : Range(5))\n          comm.Barrier();\n    }\n#endif // PARALLEL\n\n    start_time = GetTimeCounter();\n    tracing_enabled = true;\n    mem_tracing_enabled = true;\n    n_memory_events_at_start = memory_events.size();\n  }\n\n  PajeTrace :: ~PajeTrace()\n  {\n    for(auto & ltask : tasks)\n        for(auto & task : ltask)\n          {\n            task.time -= start_time;\n          }\n    for(auto & job : jobs)\n      {\n        job.start_time -= start_time;\n        job.stop_time -= start_time;\n      }\n    for(auto & event : timer_events)\n        event.time -= start_time;\n\n    for(auto & event : user_events)\n      {\n        event.t_start -= start_time;\n        event.t_end -= start_time;\n      }\n\n    for(auto & event : gpu_events)\n        event.time -= start_time;\n\n    for(auto & llink : links)\n        for(auto & link : llink)\n            link.time -= start_time;\n\n    for(auto i : IntRange(n_memory_events_at_start, memory_events.size()))\n      memory_events[i].time -= start_time;\n\n    NgMPI_Comm comm;\n  #ifdef PARALLEL\n    if(MPI_Loaded())\n      comm = NgMPI_Comm(NG_MPI_COMM_WORLD);\n  #endif\n    if(comm.Size()==1)\n    {\n      Write();\n    }\n    else\n    {\n      // make sure the timer id is unique across all ranks\n      for(auto & event : timer_events)\n        event.timer_id += NgProfiler::SIZE*comm.Rank();\n\n      for(auto & event : gpu_events)\n        event.timer_id += NgProfiler::SIZE*comm.Rank();\n\n      if(comm.Rank() == MPI_PAJE_WRITER)\n        Write();\n      else\n        SendData();\n    }\n  }\n\n\n  void PajeTrace::StopTracing()\n    {\n      if(tracing_enabled && max_num_events_per_thread>0)\n        {\n          logger->warn(\"Maximum number of traces reached, tracing is stopped now.\");\n        }\n      tracing_enabled = false;\n    }\n\n  class PajeFile\n    {\n    public:\n      static void Hue2RGB ( double x, double &r, double &g, double &b )\n        {\n          double d = 1.0/6.0;\n          if(x<d)\n            r=1, g=6*x,b=0;\n          else if (x<2*d)\n            r=1.0-6*(x-d),g=1,b=0;\n          else if (x<3*d)\n            r=0, g=1,b=6*(x-2*d);\n          else if (x<4*d)\n            r=0, g=1-6*(x-3*d),b=1;\n          else if (x<5*d)\n            r=6*(x-4*d), g=0,b=1;\n          else\n            r=1, g=0,b=1-6*(x-5*d);\n        };\n\n      int alias_counter;\n\n      FILE * ctrace_stream;\n      std::shared_ptr<Logger> logger = GetLogger(\"PajeTrace\");\n\n\n      double ConvertTime(TTimePoint t) {\n          // return time in milliseconds as double\n        // return std::chrono::duration<double>(t-start_time).count()*1000.0;\n        // return std::chrono::duration<double>(t-start_time).count() / 2.7e3;\n        return 1000.0*static_cast<double>(t) * seconds_per_tick;\n      }\n\n      enum PType\n        {\n          SET_VARIABLE=1,\n          ADD_VARIABLE,\n          SUB_VARIABLE,\n          PUSH_STATE,\n          POP_STATE,\n          START_LINK,\n          STOP_LINK\n        };\n\n      struct PajeEvent\n        {\n          PajeEvent( int aevent_type, double atime, int atype, int acontainer, double avar_value )\n            : time(atime), var_value(avar_value), event_type(aevent_type), type(atype), container(acontainer)\n            { }\n\n          PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue = 0, int aid = 0, bool avalue_is_alias = true )\n            : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias)\n            { }\n\n          PajeEvent( int aevent_type, double atime, int atype, int acontainer, std::string as_value, int aid = 0 )\n            : time(atime), event_type(aevent_type), type(atype), container(acontainer), s_value(as_value), id(aid), value_is_alias(false), value_is_int(false)\n            { }\n\n          PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey )\n            : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey)\n            { }\n\n          double time;\n          double var_value = 0.0;\n          int event_type;\n          int type;\n          int container;\n          std::string s_value = \"\";\n          int value = 0;\n          int start_container = 0;\n          int id = 0;\n          bool value_is_alias = true;\n          bool value_is_int = true;\n\n          bool operator < (const PajeEvent & other) const {\n            /*\n              // Same start and stop times can occur for very small tasks -> take \"starting\" events first (eg. PajePushState before PajePopState)\n              if(time == other.time) {\n                if(value == other.value)  // same timer - first start, then stop\n                  return event_type < other.event_type;\n                else                              // different timers - first stop, then start\n                  return event_type > other.event_type;\n              }\n            */\n              return (time < other.time);\n          }\n\n          int write(FILE *stream)\n            {\n              const int &key = id;\n              const int &end_container = start_container;\n              switch(event_type)\n                {\n                case PajeSetVariable:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%.15g\\n\", PajeSetVariable, time, type, container, var_value ); // NOLINT\n                case PajeAddVariable:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%.15g\\n\", PajeAddVariable, time, type, container, var_value ); // NOLINT\n                case PajeSubVariable:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%.15g\\n\", PajeSubVariable, time, type, container, var_value ); // NOLINT\n                case PajePushState:\n                  if(value_is_alias)\n                    return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\ta%d\\t%d\\n\", PajePushState, time, type, container, value, id); // NOLINT\n                  else if(value_is_int)\n                    return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%d\\t%d\\n\", PajePushState, time, type, container, value, id); // NOLINT\n                  else\n                    return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t\\\"%s\\\"\\t%d\\n\", PajePushState, time, type, container, s_value.c_str(), id); // NOLINT\n                case PajePopState:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\n\", PajePopState, time, type, container ); // NOLINT\n                case PajeStartLink:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%d\\ta%d\\t%d\\n\", PajeStartLink, time, type, container, value, start_container, key ); // NOLINT\n                case PajeEndLink:\n                  return fprintf( stream, \"%d\\t%.15g\\ta%d\\ta%d\\t%d\\ta%d\\t%d\\n\", PajeEndLink, time, type, container, value, end_container, key ); // NOLINT\n                }\n              return 0;\n            }\n        };\n\n      std::vector<PajeEvent> events;\n\n    public:\n      PajeFile() = delete;\n      PajeFile(const PajeFile &) = delete;\n      PajeFile(PajeFile &&) = delete;\n      void operator=(const PajeFile &) = delete;\n      void operator=(PajeFile &&) = delete;\n\n      PajeFile( const std::string & filename)\n        {\n          std::string fname = filename + \".trace\";\n          ctrace_stream = fopen (fname.c_str(),\"w\"); // NOLINT\n          fprintf(ctrace_stream, \"%s\", header ); // NOLINT\n          alias_counter = 0;\n        }\n\n      ~PajeFile()\n        {\n          fclose (ctrace_stream); // NOLINT\n        }\n\n      int DefineContainerType ( int parent_type, const std::string & name )\n        {\n          int alias = ++alias_counter;\n          if(parent_type!=0)\n            fprintf( ctrace_stream, \"%d\\ta%d\\ta%d\\t\\\"%s\\\"\\n\", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT\n          else\n            fprintf( ctrace_stream, \"%d\\ta%d\\t%d\\t\\\"%s\\\"\\n\", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT\n          return alias;\n        }\n\n      int DefineVariableType ( int container_type, const std::string & name )\n        {\n          int alias = ++alias_counter;\n          fprintf( ctrace_stream, \"%d\\ta%d\\ta%d\\t\\\"%s\\\"\\t\\\"1.0 1.0 1.0\\\"\\n\", PajeDefineVariableType, alias, container_type, name.c_str() ); // NOLINT\n          return alias;\n        }\n\n      int DefineStateType ( int type, const std::string & name )\n        {\n          int alias = ++alias_counter;\n          fprintf( ctrace_stream, \"%d\\ta%d\\ta%d\\t\\\"%s\\\"\\n\", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT\n          return alias;\n        }\n\n      //       int DefineEventType ()\n      //         {\n      //           Write(\"event not implemented\");\n      //         }\n\n      int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, const std::string & name)\n        {\n          int alias = ++alias_counter;\n          fprintf( ctrace_stream, \"%d\\ta%d\\ta%d\\ta%d\\ta%d\\t\\\"%s\\\"\\n\", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); // NOLINT\n          return alias;\n        }\n\n      int DefineEntityValue (int type, const std::string & name, double hue = -1)\n        {\n          if(hue==-1)\n            {\n              std::hash<std::string> shash;\n              size_t h = shash(name);\n              h ^= h>>32U;\n              h = static_cast<uint32_t>(h);\n              hue = h*1.0/std::numeric_limits<uint32_t>::max();\n            }\n\n          int alias = ++alias_counter;\n          double r;\n          double g;\n          double b;\n          Hue2RGB( hue, r, g, b );\n          fprintf( ctrace_stream, \"%d\\ta%d\\ta%d\\t\\\"%s\\\"\\t\\\"%.15g %.15g %.15g\\\"\\n\", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); // NOLINT\n          return alias;\n        }\n\n      int CreateContainer ( int type, int parent, const std::string & name )\n        {\n          int alias = ++alias_counter;\n          if(parent!=0)\n            fprintf( ctrace_stream, \"%d\\t0\\ta%d\\ta%d\\ta%d\\t\\\"%s\\\"\\n\", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT\n          else\n            fprintf( ctrace_stream, \"%d\\t0\\ta%d\\ta%d\\t%d\\t\\\"%s\\\"\\n\", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT\n          return alias;\n        }\n      void DestroyContainer ()\n        {}\n\n      void SetVariable (TTimePoint time, int type, int container, double value )\n        {\n          events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) );\n        }\n\n      void AddVariable (TTimePoint time, int type, int container, double value )\n        {\n          events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) );\n        }\n\n      void SubVariable (TTimePoint time, int type, int container, double value )\n        {\n          events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) );\n        }\n\n      void SetState ()\n        {}\n\n      void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true )\n        {\n          events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) );\n        }\n\n      void PushState ( TTimePoint time, int type, int container, std::string value, int id = 0)\n        {\n          events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) );\n        }\n\n      void PopState ( TTimePoint time, int type, int container )\n        {\n          events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) );\n        }\n\n      void ResetState ()\n        {}\n\n      void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key )\n        {\n          events.emplace_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) );\n        }\n\n      void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key )\n        {\n          events.emplace_back( PajeEvent(  PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) );\n        }\n\n      void NewEvent ()\n        {}\n\n      void WriteEvents()\n        {\n          logger->info(\"Sorting traces...\");\n          // std::stable_sort (events.begin(), events.end());\n\n          logger->info(\"Writing traces... \");\n          for (auto & event : events)\n          {\n              event.write( ctrace_stream );\n//               fprintf( ctrace_stream, \"%s\", buf ); // NOLINT\n          }\n          logger->info(\"Done\");\n        }\n\n    private:\n      enum\n        {\n          PajeDefineContainerType = 0,\n          PajeDefineVariableType = 1,\n          PajeDefineStateType = 2,\n          PajeDefineEventType = 3,\n          PajeDefineLinkType = 4,\n          PajeDefineEntityValue = 5,\n          PajeCreateContainer = 6,\n          PajeDestroyContainer = 7,\n          PajeSetVariable = 8,\n          PajeAddVariable = 9,\n          PajeSubVariable = 10,\n          PajeSetState = 11,\n          PajePushState = 12,\n          PajePopState = 13,\n          PajeResetState = 14,\n          PajeStartLink = 15,\n          PajeEndLink = 16,\n          PajeNewEvent = 17\n        };\n\n    };\n\n  NGCORE_API PajeTrace *trace;\n\n  void PajeTrace::Write( )\n    {\n      if(write_paje_file) WritePajeFile( tracefile_name );\n      WriteTimingChart();\n#ifdef NETGEN_TRACE_MEMORY\n      WriteMemoryChart(\"\");\n#endif // NETGEN_TRACE_MEMORY\n    }\n\n  void PajeTrace::WritePajeFile( const std::string & filename )\n    {\n      auto n_events = jobs.size() + timer_events.size();\n      for(auto & vtasks : tasks)\n        n_events += vtasks.size();\n\n      logger->info(\"{} events traced\",  n_events);\n\n      if(n_events==0)\n        {\n          logger->info(\"No data traced, skip writing trace file\");\n          return;\n        }\n\n      if(!tracing_enabled)\n        {\n            logger->warn(\"Tracing stopped during computation due to tracefile size limit of {} megabytes.\", max_tracefile_size/1024/1024);\n        }\n\n      PajeFile paje(filename);\n\n      const int container_type_task_manager = paje.DefineContainerType( 0, \"Task Manager\" );\n      const int container_type_node = paje.DefineContainerType( container_type_task_manager, \"Node\");\n      const int container_type_thread = paje.DefineContainerType( container_type_task_manager, \"Thread\");\n      const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, \"Timers\");\n      const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, \"Jobs\");\n      const int container_type_memory = paje.DefineContainerType( container_type_task_manager, \"Memory usage\");\n\n      const int state_type_job = paje.DefineStateType( container_type_jobs, \"Job\" );\n      const int state_type_task = paje.DefineStateType( container_type_thread, \"Task\" );\n      const int state_type_timer = paje.DefineStateType( container_type_timer, \"Timer state\" );\n\n      int variable_type_active_threads = 0;\n      if(trace_thread_counter)\n          variable_type_active_threads = paje.DefineVariableType( container_type_jobs, \"Active threads\" );\n\n      const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, \"The task manager\" );\n      const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, \"Jobs\" );\n\n      int variable_type_memory = 0;\n      const int container_memory = paje.CreateContainer( container_type_memory, container_task_manager, \"Memory\" );\n      if(mem_tracing_enabled)\n      {\n        variable_type_memory = paje.DefineVariableType( container_type_task_manager, \"Memory [MB]\" );\n      }\n\n\n      int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1;\n      std::vector <int> thread_aliases;\n      std::vector<int> container_nodes;\n\n      NgMPI_Comm comm;\n  #ifdef PARALLEL\n      if(MPI_Loaded())\n        comm = NgMPI_Comm(NG_MPI_COMM_WORLD);\n      if(comm.Size()>1)\n      {\n        auto comm = NgMPI_Comm(NG_MPI_COMM_WORLD);\n        nthreads = comm.Size();\n        thread_aliases.reserve(nthreads);\n\n        std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;\n        int len;\n        NG_MPI_Get_processor_name(ahostname.data(), &len);\n        std::string hostname = ahostname.data();\n\n        std::map<std::string, int> host_map;\n\n        std::string name;\n        for(auto i : IntRange(0, comm.Size()))\n        {\n          if(i!=MPI_PAJE_WRITER)\n            comm.Recv(name, i, 0);\n          else\n            name = hostname;\n          if(host_map.count(name)==0)\n          {\n            host_map[name] = container_nodes.size();\n            container_nodes.emplace_back( paje.CreateContainer( container_type_node, container_task_manager, name) );\n          }\n          thread_aliases.emplace_back( paje.CreateContainer( container_type_thread, container_nodes[host_map[name]], \"Rank \" + ToString(i) ) );\n        }\n      }\n      else\n  #endif\n      {\n        container_nodes.reserve(num_nodes);\n        for(int i=0; i<num_nodes; i++)\n          container_nodes.emplace_back( paje.CreateContainer( container_type_node, container_task_manager, \"Node \" + ToString(i)) );\n\n        thread_aliases.reserve(nthreads);\n        if(trace_threads)\n          for (int i=0; i<nthreads; i++)\n          {\n            auto name = \"Thread \" + ToString(i);\n            if(tasks[i].size())\n              thread_aliases.emplace_back( paje.CreateContainer( container_type_thread, container_nodes[i*num_nodes/nthreads], name ) );\n          }\n      }\n\n      std::map<const std::type_info *, int> job_map;\n      std::map<const std::type_info *, int> job_task_map;\n\n      for(Job & j : jobs)\n        if(job_map.find(j.type) == job_map.end())\n          {\n            std::string name = Demangle(j.type->name());\n            job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 );\n            job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 );\n          }\n\n      for(Job & j : jobs)\n        {\n          paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] );\n          paje.PopState( j.stop_time, state_type_job, container_jobs );\n        }\n\n      size_t memory_at_start = 0;\n\n      for(const auto & i : IntRange(0, n_memory_events_at_start))\n      {\n        if(memory_events[i].is_alloc)\n            memory_at_start += memory_events[i].size;\n        else\n            memory_at_start -= memory_events[i].size;\n      }\n\n      paje.SetVariable( 0, variable_type_memory, container_memory, 1.0*memory_at_start/(1024*1024));\n\n      for(const auto & i : IntRange(n_memory_events_at_start, memory_events.size()))\n      {\n        auto & m = memory_events[i];\n        if(m.size==0)\n            continue;\n        double size = 1.0*m.size/(1024*1024);\n        if(m.is_alloc)\n          paje.AddVariable( m.time, variable_type_memory, container_memory, size);\n        else\n          paje.SubVariable( m.time, variable_type_memory, container_memory, size);\n      }\n\n      std::set<int> timer_ids;\n      std::map<int,int> timer_aliases;\n      std::map<int,std::string> timer_names;\n\n      for(auto & event : timer_events)\n          timer_ids.insert(event.timer_id);\n\n      for(auto & event : gpu_events)\n          timer_ids.insert(event.timer_id);\n\n      // Timer names\n      for(auto & vtasks : tasks)\n          for (Task & t : vtasks)\n              if(t.id_type==Task::ID_TIMER)\n                  timer_ids.insert(t.id);\n\n      for(auto id : timer_ids)\n          timer_names[id] = GetTimerName(id);\n\n      if(comm.Size()>1)\n      {\n        for(auto src : IntRange(0, comm.Size()))\n        {\n          if(src==MPI_PAJE_WRITER)\n            continue;\n\n          size_t n_timers;\n          comm.Recv (n_timers, src, 0);\n\n          int id;\n          std::string name;\n          for([[maybe_unused]]auto i : IntRange(n_timers))\n          {\n            comm.Recv (id, src, 0);\n            comm.Recv (name, src, 0);\n            timer_ids.insert(id);\n            timer_names[id] = name;\n          }\n        }\n      }\n\n      for(auto id : timer_ids)\n          timer_aliases[id] = paje.DefineEntityValue( state_type_timer, timer_names[id], -1 );\n\n      int timerdepth = 0;\n      int maxdepth = 0;\n      for(auto & event : timer_events)\n        {\n          if(event.is_start)\n            {\n              timerdepth++;\n              maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth;\n            }\n          else\n            timerdepth--;\n        }\n\n      std::vector<int> timer_container_aliases;\n      timer_container_aliases.resize(maxdepth);\n      for(int i=0; i<maxdepth; i++)\n        {\n          auto name = \"Timer level \" + ToString(i);\n          timer_container_aliases[i] =  paje.CreateContainer( container_type_timer, container_task_manager, name );\n        }\n\n      timerdepth = 0;\n      for(auto & event : timer_events)\n        {\n          if(event.is_start)\n            paje.PushState( event.time, state_type_timer, timer_container_aliases[timerdepth++], timer_aliases[event.timer_id], event.custom_value );\n          else\n            paje.PopState( event.time, state_type_timer, timer_container_aliases[--timerdepth] );\n        }\n\n      if(gpu_events.size())\n      {\n        auto gpu_container =  paje.CreateContainer( container_type_timer, container_task_manager, \"GPU\" );\n        for(auto & event : gpu_events)\n        {\n          if(event.is_start)\n            paje.PushState( event.time, state_type_timer, gpu_container, timer_aliases[event.timer_id] );\n          else\n            paje.PopState( event.time, state_type_timer, gpu_container);\n        }\n      }\n\n      if(user_events.size())\n        {\n          // std::stable_sort (user_events.begin(), user_events.end());\n\n          std::map<int, int> containers;\n\n          for(auto i : Range(user_containers.size()))\n          {\n              auto & [name, parent] = user_containers[i];\n              int a_parent = parent == -1 ? container_task_manager : containers[parent];\n              containers[i] = paje.CreateContainer( container_type_timer, a_parent, name );\n          }\n\n          for(auto ev : user_events)\n          {\n            if(containers[ev.container]==0)\n            {\n              std::string name = \"User \" + ToString(ev.container);\n              containers[ev.container] = paje.CreateContainer( container_type_timer, container_task_manager, name );\n            }\n          }\n\n          int i_start = 0;\n          for(auto i : Range(user_events.size()))\n          {\n            auto & event = user_events[i];\n            while(i_start < user_events.size() && user_events[i_start].t_start < event.t_end)\n            {\n              auto & ev = user_events[i_start];\n              paje.PushState( ev.t_start, state_type_timer, containers[ev.container], ev.data, ev.id );\n              i_start++;\n            }\n            paje.PopState( event.t_end, state_type_timer, containers[event.container]);\n          }\n        }\n\n      for(auto & vtasks : tasks)\n        {\n          for (Task & t : vtasks) {\n              int value_id = t.id;\n\n              switch(t.id_type)\n                {\n                case Task::ID_JOB:\n                  value_id = job_task_map[jobs[t.id-1].type];\n                  if(trace_thread_counter)\n                    {\n                      if(t.is_start)\n                        paje.AddVariable( t.time, variable_type_active_threads, container_jobs, 1.0 );\n                      else\n                        paje.SubVariable( t.time, variable_type_active_threads, container_jobs, 1.0 );\n                    }\n                  if(trace_threads)\n                    {\n                      if(t.is_start)\n                        paje.PushState( t.time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, true );\n                      else\n                        paje.PopState( t.time, state_type_task, thread_aliases[t.thread_id] );\n                    }\n                  break;\n                case Task::ID_TIMER:\n                  value_id = timer_aliases[t.id];\n                  if(t.is_start)\n                    paje.PushState( t.time, state_type_timer, thread_aliases[t.thread_id], value_id, t.additional_value, true );\n                  else\n                    paje.PopState( t.time, state_type_timer, thread_aliases[t.thread_id] );\n                  break;\n                default:\n                  if(t.is_start)\n                    paje.PushState( t.time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, false );\n                  else\n                    paje.PopState( t.time, state_type_task, thread_aliases[t.thread_id] );\n                  break;\n                }\n          }\n        }\n\n#ifdef PARALLEL\n      if(comm.Size()>1)\n      {\n        for(auto & event : timer_events)\n        {\n          if(event.is_start)\n            paje.PushState( event.time, state_type_timer, thread_aliases[MPI_PAJE_WRITER], timer_aliases[event.timer_id] );\n          else\n            paje.PopState( event.time, state_type_timer, thread_aliases[MPI_PAJE_WRITER] );\n        }\n\n        // Timer events\n        Array<int> timer_id;\n        Array<TTimePoint> time;\n        Array<bool> is_start;\n        Array<int> thread_id;\n\n        for(auto src : IntRange(0, comm.Size()))\n        {\n          if(src==MPI_PAJE_WRITER)\n            continue;\n\n          comm.Recv (timer_id, src, 0);\n          comm.Recv (time, src, 0);\n          comm.Recv (is_start, src, 0);\n          comm.Recv (thread_id, src, 0);\n\n          for(auto i : Range(timer_id.Size()))\n          {\n            TimerEvent event;\n            event.timer_id = timer_id[i];\n            event.time = time[i];\n            event.is_start = is_start[i];\n            event.thread_id = thread_id[i];\n\n            if(event.is_start)\n              paje.PushState( event.time, state_type_timer, thread_aliases[src], timer_aliases[event.timer_id] );\n            else\n              paje.PopState( event.time, state_type_timer, thread_aliases[src] );\n          }\n        }\n      }\n#endif // PARALLEL\n\n      // Merge link event\n      int nlinks = 0;\n      for( auto & l : links)\n        nlinks += l.size();\n\n      std::vector<ThreadLink> links_merged;\n      links_merged.reserve(nlinks);\n      std::vector<unsigned int> pos(nthreads);\n\n      int nlinks_merged = 0;\n      while(nlinks_merged < nlinks)\n        {\n          int minpos = -1;\n          TTimePoint mintime = -1;\n          for (int t = 0; t<nthreads; t++)\n            {\n              if(pos[t] < links[t].size() && (minpos==-1 || links[t][pos[t]].time < mintime))\n                {\n                  minpos = t;\n                  mintime = links[t][pos[t]].time;\n                }\n            }\n          links_merged.push_back( links[minpos][pos[minpos]] );\n          pos[minpos]++;\n          nlinks_merged++;\n        }\n\n      std::vector<ThreadLink> started_links;\n\n      int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, \"links\");\n\n      // match links\n      for ( auto & l : links_merged )\n        {\n          if(l.is_start)\n            {\n              started_links.push_back(l);\n            }\n          else\n            {\n              unsigned int i = 0;\n              while(i<started_links.size())\n                {\n                  while(i<started_links.size() && started_links[i].key == l.key)\n                    {\n                      ThreadLink & sl = started_links[i];\n                      // Avoid links on same thread\n                      if(sl.thread_id != l.thread_id)\n                        {\n                          paje.StartLink( sl.time, link_type, container_nodes[sl.thread_id*num_nodes/nthreads], l.key, thread_aliases[sl.thread_id], l.key);\n                          paje.EndLink(    l.time, link_type, container_nodes[l.thread_id*num_nodes/nthreads], l.key, thread_aliases[l.thread_id], l.key);\n                        }\n                      started_links.erase(started_links.begin()+i);\n                    }\n                  i++;\n                }\n            }\n        }\n      paje.WriteEvents();\n    }\n\n  void PajeTrace::SendData( )\n    {\n#ifdef PARALLEL\n      // Hostname\n      NgMPI_Comm comm(NG_MPI_COMM_WORLD);\n      // auto rank = comm.Rank();\n      // auto nranks = comm.Size();\n\n      std::string hostname;\n        {\n          std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;\n          int len;\n          NG_MPI_Get_processor_name(ahostname.data(), &len);\n          hostname = ahostname.data();\n        }\n\n      comm.Send(hostname, MPI_PAJE_WRITER, 0);\n\n      // Timer names\n      std::set<int> timer_ids;\n      std::map<int,std::string> timer_names;\n\n      for(auto & event : timer_events)\n          timer_ids.insert(event.timer_id);\n\n      for(auto id : timer_ids)\n          timer_names[id] = GetTimerName(id);\n      size_t size = timer_ids.size();\n      comm.Send(size, MPI_PAJE_WRITER, 0);\n      for(auto id : timer_ids)\n        {\n          comm.Send(id, MPI_PAJE_WRITER, 0);\n          comm.Send(timer_names[id], MPI_PAJE_WRITER, 0);\n        }\n\n\n      // Timer events\n      Array<int> timer_id;\n      Array<TTimePoint> time;\n      Array<bool> is_start;\n      Array<int> thread_id;\n\n      for(auto & event : timer_events)\n        {\n          timer_id.Append(event.timer_id);\n          time.Append(event.time);\n          is_start.Append(event.is_start);\n          thread_id.Append(event.thread_id);\n        }\n\n      comm.Send (timer_id, MPI_PAJE_WRITER, 0);\n      comm.Send (time, MPI_PAJE_WRITER, 0);\n      comm.Send (is_start, MPI_PAJE_WRITER, 0);\n      comm.Send (thread_id, MPI_PAJE_WRITER, 0);\n#endif // PARALLEL\n    }\n\n  ///////////////////////////////////////////////////////////////////\n  // Write HTML file drawing a sunburst chart with cumulated timings\n  struct TreeNode\n  {\n      int id = 0;\n      std::map<int, TreeNode> children;\n      double chart_size = 0.0; // time without children (the chart lib accumulates children sizes again)\n      double size = 0.0;\n      double min_size = 1e99;\n      double max_size = 0.0;\n      std::string name;\n\n      size_t calls = 0;\n      TTimePoint start_time = 0;\n  };\n\n  void PrintNode (const TreeNode &n, std::ofstream & f)\n  {\n      f << \"{ name: \\\"\" + n.name + \"\\\"\";\n      f << \", calls: \" << n.calls;\n      f << \", size: \" << n.chart_size;\n      f << \", value: \" << n.size;\n      f << \", min: \" << n.min_size;\n      f << \", max: \" << n.max_size;\n      if(n.calls)\n        f << \", avg: \" << n.size/n.calls;\n      int size = n.children.size();\n      if(size>0)\n      {\n          int i = 0;\n          f << \", children: [\";\n          for(auto & c : n.children)\n          {\n              PrintNode(c.second, f);\n              if(++i<size)\n                  f << \" , \";\n          }\n          f << ']';\n      }\n      f << '}';\n  }\n\n  void WriteSunburstHTML( TreeNode & root, std::string filename, bool time_or_memory )\n  {\n    std::ofstream f(filename+\".html\");\n    f.precision(4);\n    f << R\"CODE_(\n<head>\n  <script src=\"https://cdn.jsdelivr.net/npm/d3@7\"></script>\n  <script src=\"https://unpkg.com/sunburst-chart\"></script>\n\n  <style>\n    body { margin: 0 }\n    .tooltip {\n      white-space: pre-line !important;\n      max-width: 800px !important;\n      word-wrap: break-word !important;\n      padding: 10px !important;\n    }\n  </style>\n)CODE_\";\n    if(!time_or_memory)\n      f << \"<title>Maximum Memory Consumption</title>\\n\";\n    f << R\"CODE_(\n</head>\n<body>\n  <div id=\"chart\"></div>\n\n  <script>\n    const data = \n)CODE_\";\n      PrintNode(root, f);\n      f << \";\\n\\n\";\n      if(time_or_memory)\n        f << \"const chart_type = 'time';\\n\";\n      else\n        f << \"const chart_type = 'memory';\\n\";\n      f << R\"CODE_(\n    const color = d3.scaleOrdinal(d3.schemePaired);\n\n    let getTime = (t) =>\n    {\n       if(t>=1000)  return (t/1000).toPrecision(4) + '  s';\n       if(t>=0.1)   return t.toPrecision(4) + ' ms';\n       if(t>=1e-4)  return (t*1e3).toPrecision(4) + ' us';\n\n       return (t/1e6).toPrecision(4) + ' ns';\n    };\n\n    const KB_ = 1024;\n    const MB_ = KB_*1024;\n    const GB_ = MB_*1024;\n    let getMemory = (m) =>\n    {\n       if(m>=GB_)  return (m/GB_).toPrecision(4) + ' GB';\n       if(m>=MB_)  return (m/MB_).toPrecision(4) + ' MB';\n       if(m>=KB_)  return (m/KB_).toPrecision(4) + ' KB';\n       return m.toPrecision(4) + ' B';\n    };\n\n    Sunburst()\n      .data(data)\n      .size('size')\n      .color(d => color(d.name))\n      .tooltipTitle((d, node) => { return node.parent ? node.parent.data.name + \" &rarr; \" + d.name : d.name; })\n      .tooltipContent((d, node) => {\n        if(chart_type==\"memory\")\n        {\n          return `Total Memory: <i>${getMemory(d.value)}</i> <br>`\n               + `Memory: <i>${getMemory(d.size)}</i>`\n        }\n        else\n        {\n          return `Time: <i>${getTime(d.value)}</i> <br>`\n               + `calls: <i>${d.calls}</i> <br>`\n               + `min: <i>${getTime(d.min)}</i> <br>`\n               + `max: <i>${getTime(d.max)}</i> <br>`\n               + `avg: <i>${getTime(d.avg)}</i>`\n        }\n      })\n      (document.getElementById('chart'));\n\n      // Line breaks in tooltip\n      var all = document.getElementsByClassName('sunbirst-tooltip');\n      for (var i = 0; i < all.length; i++) {\n          all[i].white_space = \"\";\n      }\n  </script>\n</body>\n)CODE_\" << std::endl;\n\n\n  }\n\n#ifdef NETGEN_TRACE_MEMORY\n  void PajeTrace::WriteMemoryChart( std::string fname )\n  {\n    if(fname==\"\")\n      fname = tracefile_name + \"_memory\";\n    size_t mem_allocated = 0;\n    size_t max_mem_allocated = 0;\n    size_t imax_mem_allocated = 0;\n\n    const auto & names = MemoryTracer::GetNames();\n    const auto & parents = MemoryTracer::GetParents();\n    size_t N = names.size();\n\n    Array<size_t> mem_allocated_id;\n    mem_allocated_id.SetSize(N);\n    mem_allocated_id = 0;\n\n    // Find point with maximum memory allocation, check for missing allocs/frees\n    for(auto i : IntRange(memory_events.size()))\n    {\n      const auto & ev = memory_events[i];\n\n      if(ev.is_alloc)\n      {\n        mem_allocated += ev.size;\n        mem_allocated_id[ev.id] += ev.size;\n        if(mem_allocated > max_mem_allocated && i>=n_memory_events_at_start)\n        {\n          imax_mem_allocated = i;\n          max_mem_allocated = mem_allocated;\n        }\n      }\n      else\n      {\n        if(ev.size > mem_allocated)\n          {\n            std::cerr << \"Error in memory tracer: have total allocated memory < 0\" << std::endl;\n            mem_allocated = 0;\n          }\n        else\n          mem_allocated -= ev.size;\n        if(ev.size > mem_allocated_id[ev.id])\n          {\n            std::cerr << \"Error in memory tracer: have allocated memory < 0 in tracer \" << names[ev.id] << std::endl;\n            mem_allocated_id[ev.id] = 0;\n          }\n        else\n          mem_allocated_id[ev.id] -= ev.size;\n      }\n    }\n\n    // reconstruct again the memory consumption after event imax_mem_allocated\n    mem_allocated_id = 0;\n    for(auto i : IntRange(imax_mem_allocated+1))\n    {\n      const auto & ev = memory_events[i];\n\n      if(ev.is_alloc)\n        mem_allocated_id[ev.id] += ev.size;\n      else\n        {\n          if(ev.size > mem_allocated_id[ev.id])\n            mem_allocated_id[ev.id] = 0;\n          else\n            mem_allocated_id[ev.id] -= ev.size;\n        }\n    }\n\n    TreeNode root;\n    root.name=\"all\";\n\n    Array<TreeNode*> nodes;\n    nodes.SetSize(N);\n    nodes = nullptr;\n    nodes[0] = &root;\n    Array<Array<int>> children(N);\n\n    Array<size_t> sorting; // topological sorting (parents before children)\n    sorting.SetAllocSize(N);\n\n    for(auto i : IntRange(1, N))\n        children[parents[i]].Append(i);\n\n    ArrayMem<size_t, 100> stack;\n    sorting.Append(0);\n    stack.Append(0);\n\n    while(stack.Size())\n    {\n      auto current = stack.Last();\n      stack.DeleteLast();\n\n      for(const auto child : children[current])\n      {\n        sorting.Append(child);\n        if(children[child].Size())\n          stack.Append(child);\n      }\n    }\n\n    for(auto i : sorting)\n    {\n      if(i==0)\n          continue;\n\n      TreeNode * parent = nodes[parents[i]];\n\n      auto & node = parent->children[i];\n      nodes[i] = &node;\n      node.id = i;\n      node.chart_size = mem_allocated_id[i];\n      node.size = mem_allocated_id[i];\n      node.name = names[i];\n    }\n\n    for(auto i_ : Range(sorting))\n    {\n      // reverse topological order to accumulate total memory usage of all children\n      auto i = sorting[sorting.Size()-1-i_];\n      if(i==0)\n          continue;\n      nodes[parents[i]]->size += nodes[i]->size;\n    }\n\n    WriteSunburstHTML( root, fname, false );\n\n  }\n#endif // NETGEN_TRACE_MEMORY\n\n  void PajeTrace::WriteTimingChart( )\n  {\n      std::vector<TimerEvent> events;\n\n      TreeNode root;\n      root.name=\"all\";\n      TreeNode *current = &root;\n\n      std::vector<TreeNode*> node_stack;\n\n      node_stack.push_back(&root);\n\n      TTimePoint stop_time = 0;\n\n      for(auto & event : timer_events)\n      {\n          events.push_back(event);\n          stop_time = std::max(event.time, stop_time);\n      }\n\n      std::map<std::string, int> jobs_map;\n      std::vector<std::string> job_names;\n      for(auto & job : jobs)\n      {\n          auto name = Demangle(job.type->name());\n          int id = job_names.size();\n          if(jobs_map.count(name)==0)\n          {\n              jobs_map[name] = id;\n              job_names.push_back(name);\n          }\n          else\n              id = jobs_map[name];\n\n          events.push_back(TimerEvent{job.start_time, -1, id, -1, true});\n          events.push_back(TimerEvent{job.stop_time, -1, id, -1, false});\n          stop_time = std::max(job.stop_time, stop_time);\n      }\n\n      std::stable_sort (events.begin(), events.end());\n\n      root.size = 1000.0*static_cast<double>(stop_time) * seconds_per_tick;\n      root.calls = 1;\n      root.min_size = root.size;\n      root.max_size = root.size;\n\n      for(auto & event : events)\n      {\n          bool is_timer_event = event.timer_id != -1;\n          int id = is_timer_event ? event.timer_id : event.thread_id;\n\n          if(event.is_start)\n          {\n              bool need_init = !current->children.count(id);\n\n              node_stack.push_back(current);\n              current = &current->children[id];\n\n              if(need_init)\n              {\n                  current->name = is_timer_event ? GetTimerName(id) : job_names[id];\n                  current->size = 0.0;\n                  current->id = id;\n              }\n\n              current->start_time = event.time;\n          }\n          else\n          {\n              if(node_stack.size()==0) {\n                std::cout << \"node stack empty!\" << std::endl;\n                break;\n              }\n              double size = 1000.0*static_cast<double>(event.time-current->start_time) * seconds_per_tick;\n              current->size += size;\n              current->chart_size += size;\n              current->min_size = std::min(current->min_size, size);\n              current->max_size = std::max(current->max_size, size);\n              current->calls++;\n\n              current = node_stack.back();\n              current->chart_size -= size;\n              node_stack.pop_back();\n          }\n      }\n\n      root.chart_size = 0.0;\n\n      ngcore::WriteSunburstHTML( root, tracefile_name, true );\n  }\n\n} // namespace ngcore\n\nconst char *header =\n        \"%EventDef PajeDefineContainerType 0 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDefineVariableType 1 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%       Color color \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDefineStateType 2 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDefineEventType 3 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%       Color color \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDefineLinkType 4 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       StartContainerType string \\n\"\n        \"%       EndContainerType string \\n\"\n        \"%       Name string \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDefineEntityValue 5 \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%       Color color \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeCreateContainer 6 \\n\"\n        \"%       Time date \\n\"\n        \"%       Alias string \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Name string \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeDestroyContainer 7 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Name string \\n\"\n        \"%EndEventDef \\n\"\n        \"%EventDef PajeSetVariable 8 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value double \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeAddVariable 9 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value double \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeSubVariable 10 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value double \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeSetState 11 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajePushState 12 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value string \\n\"\n        \"%       Id string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajePopState 13 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeResetState 14 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeStartLink 15 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value string \\n\"\n        \"%       StartContainer string \\n\"\n        \"%       Key string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeEndLink 16 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value string \\n\"\n        \"%       EndContainer string \\n\"\n        \"%       Key string \\n\"\n        \"%EndEventDef\\n\"\n        \"%EventDef PajeNewEvent 17 \\n\"\n        \"%       Time date \\n\"\n        \"%       Type string \\n\"\n        \"%       Container string \\n\"\n        \"%       Value string \\n\"\n        \"%EndEventDef\\n\";\n"
  },
  {
    "path": "libsrc/core/paje_trace.hpp",
    "content": "#ifndef NETGEN_CORE_PAJE_TRACE_HPP\n#define NETGEN_CORE_PAJE_TRACE_HPP\n\n#include <algorithm>\n#include <limits>\n#include <vector>\n\n#include \"logging.hpp\"       // for logger\n#include \"ngcore_api.hpp\"    // for NGCORE_API\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n\n  extern NGCORE_API class PajeTrace *trace;\n  class PajeTrace\n    {\n    public:\n      using TClock = std::chrono::system_clock;\n\n    protected:\n      std::shared_ptr<Logger> logger = GetLogger(\"PajeTrace\");\n    private:\n      NGCORE_API static size_t max_tracefile_size;\n      NGCORE_API static bool trace_thread_counter;\n      NGCORE_API static bool trace_threads;\n      NGCORE_API static bool mem_tracing_enabled;\n      NGCORE_API static bool write_paje_file;\n\n      bool tracing_enabled;\n      TTimePoint start_time;\n      int nthreads;\n      size_t n_memory_events_at_start;\n\n    public:\n      NGCORE_API void Write();\n      NGCORE_API void WritePajeFile( const std::string & filename );\n      NGCORE_API void WriteTimingChart();\n#ifdef NETGEN_TRACE_MEMORY\n      NGCORE_API void WriteMemoryChart( std::string fname );\n#endif // NETGEN_TRACE_MEMORY\n\n      // Approximate number of events to trace. Tracing will\n      // be stopped if any thread reaches this number of events\n      unsigned int max_num_events_per_thread;\n\n      static void SetTraceMemory( bool trace_memory )\n        {\n          mem_tracing_enabled = trace_memory;\n        }\n\n      static void SetTraceThreads( bool atrace_threads )\n        {\n          trace_threads = atrace_threads;\n        }\n\n      static void SetTraceThreadCounter( bool trace_threads )\n        {\n          trace_thread_counter = trace_threads;\n        }\n\n      static void SetMaxTracefileSize( size_t max_size )\n        {\n          max_tracefile_size = max_size;\n        }\n\n      static void SetWritePajeFile( bool write )\n        {\n          write_paje_file = write;\n        }\n\n      std::string tracefile_name;\n\n      struct Job\n        {\n          int job_id;\n          const std::type_info *type;\n          TTimePoint start_time;\n          TTimePoint stop_time;\n        };\n\n      struct Task\n        {\n          int thread_id;\n\n          int id;\n          int id_type;\n\n          int additional_value;\n\n          TTimePoint time;\n          bool is_start;\n\n          static constexpr int ID_NONE = -1;\n          static constexpr int ID_JOB = 1;\n          static constexpr int ID_TIMER = 2;\n        };\n\n      struct TimerEvent\n        {\n          TTimePoint time;\n          int timer_id;\n          int thread_id;\n          int custom_value = -1;\n          bool is_start;\n\n          bool operator < (const TimerEvent & other) const { return time < other.time; }\n        };\n\n      struct UserEvent\n        {\n          TTimePoint t_start = 0, t_end = 0;\n          std::string data = \"\";\n          int container = 0;\n          int id = 0;\n\n          bool operator < (const UserEvent & other) const { return t_start < other.t_start; }\n        };\n\n      struct ThreadLink\n        {\n          int thread_id;\n          int key;\n          TTimePoint time;\n          bool is_start;\n          bool operator < (const ThreadLink & other) const { return time < other.time; }\n        };\n\n      struct MemoryEvent\n        {\n          TTimePoint time;\n          size_t size;\n          int id;\n          bool is_alloc;\n\n          bool operator < (const MemoryEvent & other) const { return time < other.time; }\n        };\n\n      std::vector<std::vector<Task> > tasks;\n      std::vector<Job> jobs;\n      std::vector<TimerEvent> timer_events;\n      std::vector<UserEvent> user_events;\n      std::vector<std::tuple<std::string, int>> user_containers;\n      std::vector<TimerEvent> gpu_events;\n      std::vector<std::vector<ThreadLink> > links;\n      NGCORE_API static std::vector<MemoryEvent> memory_events;\n\n    public:\n      NGCORE_API void StopTracing();\n\n      PajeTrace() = delete;\n      PajeTrace(const PajeTrace &) = delete;\n      PajeTrace(PajeTrace &&) = delete;\n      NGCORE_API PajeTrace(int anthreads, std::string aname = \"\");\n      NGCORE_API ~PajeTrace();\n\n      void operator=(const PajeTrace &) = delete;\n      void operator=(PajeTrace &&) = delete;\n\n      int AddUserContainer(std::string name, int parent=-1)\n      {\n        if(auto pos = std::find(user_containers.begin(), user_containers.end(), std::tuple{name,parent}); pos != user_containers.end())\n          return pos - user_containers.begin();\n        int id = user_containers.size();\n        user_containers.push_back({name, parent});\n        return id;\n      }\n\n      void AddUserEvent(UserEvent ue)\n      {\n          if(!tracing_enabled) return;\n          user_events.push_back(ue);\n      }\n      void StartGPU(int timer_id = 0, int user_value = -1)\n        {\n          if(!tracing_enabled) return;\n          if(unlikely(gpu_events.size() == max_num_events_per_thread))\n            StopTracing();\n          gpu_events.push_back(TimerEvent{GetTimeCounter(), timer_id, 0, user_value, true});\n        }\n\n      void StopGPU(int timer_id)\n        {\n          if(!tracing_enabled) return;\n          if(unlikely(gpu_events.size() == max_num_events_per_thread))\n            StopTracing();\n          gpu_events.push_back(TimerEvent{GetTimeCounter(), timer_id, 0, -1, false});\n        }\n\n      void StartTimer(int timer_id, int user_value = -1)\n        {\n          if(!tracing_enabled) return;\n          if(unlikely(timer_events.size() == max_num_events_per_thread))\n            StopTracing();\n          timer_events.push_back(TimerEvent{GetTimeCounter(), timer_id, 0, user_value, true});\n        }\n\n      void StopTimer(int timer_id)\n        {\n          if(!tracing_enabled) return;\n          if(unlikely(timer_events.size() == max_num_events_per_thread))\n            StopTracing();\n          timer_events.push_back(TimerEvent{GetTimeCounter(), timer_id, 0, -1, false});\n        }\n\n      void AllocMemory(int id, size_t size)\n        {\n          if(!mem_tracing_enabled) return;\n          memory_events.push_back(MemoryEvent{GetTimeCounter(), size, id, true});\n        }\n\n      void FreeMemory(int id, size_t size)\n        {\n          if(!mem_tracing_enabled) return;\n          memory_events.push_back(MemoryEvent{GetTimeCounter(), size, id, false});\n        }\n\n      void ChangeMemory(int id, long long size)\n        {\n          if(size>0)\n            AllocMemory(id, size);\n          if(size<0)\n            FreeMemory(id, -size);\n        }\n\n\n      int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1)\n        {\n          if(!tracing_enabled) return -1;\n          if(!trace_threads && !trace_thread_counter) return -1;\n\t  if(unlikely(tasks[thread_id].size() == max_num_events_per_thread))\n            StopTracing();\n          int task_num = tasks[thread_id].size();\n          tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter(), true} );\n          return task_num;\n        }\n\n      void StopTask(int thread_id, int id, int id_type = Task::ID_NONE)\n        {\n          if(!trace_threads && !trace_thread_counter) return;\n          tasks[thread_id].push_back( Task{thread_id, id, id_type, 0, GetTimeCounter(), false} );\n        }\n\n      void StartJob(int job_id, const std::type_info & type)\n        {\n          if(!tracing_enabled) return;\n          if(jobs.size() == max_num_events_per_thread)\n            StopTracing();\n          jobs.push_back( Job{job_id, &type, GetTimeCounter()} );\n        }\n\n      void StopJob()\n        {\n          if(tracing_enabled)\n            jobs.back().stop_time = GetTimeCounter();\n        }\n\n      void StartLink(int thread_id, int key)\n        {\n          if(!tracing_enabled) return;\n          if(links[thread_id].size() == max_num_events_per_thread)\n            StopTracing();\n          links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} );\n        }\n\n      void StopLink(int thread_id, int key)\n        {\n          if(!tracing_enabled) return;\n          if(links[thread_id].size() == max_num_events_per_thread)\n            StopTracing();\n          links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} );\n        }\n\n      void SendData(); // MPI parallel data reduction\n\n    };\n} // namespace ngcore\n\n#endif // NETGEN_CORE_PAJE_TRACE_HPP\n"
  },
  {
    "path": "libsrc/core/profiler.cpp",
    "content": "#include <mutex>\n\n#include \"profiler.hpp\"\n\nnamespace ngcore\n{\n  std::vector<NgProfiler::TimerVal> NgProfiler::timers(NgProfiler::SIZE); // NOLINT\n\n  std::string NgProfiler::filename;\n\n  std::array<size_t,NgProfiler::SIZE> NgProfiler::dummy_thread_times;\n  size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times.data(); // NOLINT\n  std::array<size_t,NgProfiler::SIZE> NgProfiler::dummy_thread_flops;\n  size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops.data(); // NOLINT\n\n  std::shared_ptr<Logger> NgProfiler::logger = GetLogger(\"Profiler\"); // NOLINT\n\n  NgProfiler :: NgProfiler()\n  {\n    for (auto & t : timers)\n    {\n        t.tottime = 0.0;\n        t.usedcounter = 0;\n        t.flops = 0.0;\n    }\n  }\n\n  NgProfiler :: ~NgProfiler()\n  {\n    if (filename.length())\n      {\n        logger->debug( \"write profile to file {}\", filename );\n        FILE *prof = fopen(filename.c_str(),\"w\"); // NOLINT\n        Print (prof);\n        fclose(prof); // NOLINT\n      }\n\n    if (getenv (\"NGPROFILE\"))\n      {\n       std::string filename = \"netgen.prof\";\n#ifdef PARALLEL\n       filename += \".\"+ToString(id);\n#endif\n       if (id == 0) logger->info( \"write profile to file {}\", filename );\n       FILE *prof = fopen(filename.c_str(),\"w\"); // NOLINT\n       Print (prof);\n       fclose(prof); // NOLINT\n      }\n  }\n\n  void NgProfiler :: Print (FILE * prof)\n  {\n    int i = 0;\n    for (auto & t : timers)\n    {\n      if (t.count != 0 || t.usedcounter != 0)\n        {\n          fprintf(prof,\"job %3i calls %8li, time %6.4f sec\",i,t.count,t.tottime); // NOLINT\n          if(t.flops != 0.0)\n            fprintf(prof,\", MFlops = %6.2f\",t.flops / (t.tottime) * 1e-6); // NOLINT\n          if(t.loads != 0.0)\n            fprintf(prof,\", MLoads = %6.2f\",t.loads / (t.tottime) * 1e-6); // NOLINT\n          if(t.stores != 0.0)\n            fprintf(prof,\", MStores = %6.2f\",t.stores / (t.tottime) * 1e-6); // NOLINT\n          if(t.usedcounter)\n            fprintf(prof,\" %s\",t.name.c_str()); // NOLINT\n          fprintf(prof,\"\\n\"); // NOLINT\n        }\n      i++;\n    }\n  }\n\n\n  int NgProfiler :: CreateTimer (const std::string & name)\n  {\n    static std::mutex createtimer_mutex;\n    int nr = -1;\n    {\n      std::lock_guard<std::mutex> guard(createtimer_mutex);\n      for (int i = SIZE-1; i > 0; i--)\n      {\n        auto & t = timers[i];\n        if (!t.usedcounter)\n          {\n            t.usedcounter = 1;\n            t.name = name;\n            nr = i;\n            break;\n          }\n      }\n    }\n    if (nr > -1) return nr;\n    static bool first_overflow = true;\n    if (first_overflow)\n      {\n        first_overflow = false;\n        NgProfiler::logger->warn( (\"no more timer available (\"+name+\"), reusing last one\").c_str());\n      }\n    return 0;\n  }\n\n  void NgProfiler :: Reset ()\n  {\n      for(auto & t : timers)\n      {\n          t.tottime = 0.0;\n          t.count = 0;\n          t.flops = 0.0;\n          t.loads = 0;\n          t.stores = 0;\n      }\n  }\n\n  NgProfiler prof; // NOLINT\n\n#ifdef NETGEN_TRACE_MEMORY\n  std::vector<std::string> MemoryTracer::names{\"all\"};\n  std::vector<int> MemoryTracer::parents{-1};\n  std::atomic<size_t> MemoryTracer::total_memory{0};\n#endif // NETGEN_TRACE_MEMORY\n\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/profiler.hpp",
    "content": "#ifndef NETGEN_CORE_PROFILER_HPP\n#define NETGEN_CORE_PROFILER_HPP\n\n#include <array>\n#include <chrono>\n#include <functional>\n#include <string>\n\n#include \"array.hpp\"\n#include \"logging.hpp\"\n#include \"paje_trace.hpp\"\n#include \"taskmanager.hpp\"\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n  class NgProfiler\n  {\n  public:\n    /// maximal number of timers\n    enum { SIZE = 8*1024 };\n\n    struct TimerVal\n    {\n        TimerVal() = default;\n\n        double tottime = 0.0;\n        TTimePoint starttime=0;\n        double flops = 0.0;\n        double loads = 0.0;\n        double stores = 0.0;\n        long count = 0;\n        std::string name = \"\";\n        int usedcounter = 0;\n    };\n\n    NGCORE_API static std::vector<TimerVal> timers;\n\n    NGCORE_API static TTimePoint * thread_times;\n    NGCORE_API static TTimePoint * thread_flops;\n    NGCORE_API static std::shared_ptr<Logger> logger;\n    NGCORE_API static std::array<size_t, NgProfiler::SIZE> dummy_thread_times;\n    NGCORE_API static std::array<size_t, NgProfiler::SIZE> dummy_thread_flops;\n  private:\n\n    NGCORE_API static std::string filename;\n  public:\n    NgProfiler();\n    ~NgProfiler();\n\n    NgProfiler(const NgProfiler &) = delete;\n    NgProfiler(NgProfiler &&) = delete;\n    void operator=(const NgProfiler &) = delete;\n    void operator=(NgProfiler &&) = delete;\n\n    static void SetFileName (const std::string & afilename) { filename = afilename; }\n\n    /// create new timer, use integer index\n    NGCORE_API static int CreateTimer (const std::string & name);\n\n    NGCORE_API static void Reset ();\n\n\n    /// start timer of index nr\n    static void StartTimer (int nr)\n    {\n      timers[nr].starttime = GetTimeCounter(); timers[nr].count++;\n    }\n\n    /// stop timer of index nr\n    static void StopTimer (int nr)\n    {\n      timers[nr].tottime += (GetTimeCounter()-timers[nr].starttime)*seconds_per_tick;\n    }\n\n    static void StartThreadTimer (size_t nr, size_t tid)\n    {\n      thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT\n    }\n\n    static void StopThreadTimer (size_t nr, size_t tid)\n    {\n      thread_times[tid*SIZE+nr] += GetTimeCounter(); // NOLINT\n    }\n\n    static void AddThreadFlops (size_t nr, size_t tid, size_t flops)\n    {\n      thread_flops[tid*SIZE+nr] += flops; // NOLINT\n    }\n\n    /// if you know number of flops, provide them to obtain the MFlop - rate\n    static void AddFlops (int nr, double aflops) { timers[nr].flops += aflops; }\n    static void AddLoads (int nr, double aloads) { timers[nr].loads += aloads; }\n    static void AddStores (int nr, double astores) { timers[nr].stores += astores; }\n\n    static int GetNr (const std::string & name)\n    {\n      for (int i = SIZE-1; i >= 0; i--)\n        if (timers[i].name == name)\n          return i;\n      return -1;\n    }\n\n    static double GetTime (int nr)\n    {\n      return timers[nr].tottime;\n    }\n\n    static double GetTime (const std::string & name)\n    {\n      for (int i = SIZE-1; i >= 0; i--)\n        if (timers[i].name == name)\n          return GetTime (i);\n      return 0;\n    }\n\n    static long int GetCounts (int nr)\n    {\n      return timers[nr].count;\n    }\n\n    static double GetFlops (int nr)\n    {\n      return timers[nr].flops;\n    }\n\n    /// change name\n    static void SetName (int nr, const std::string & name) { timers[nr].name = name; }\n    static std::string GetName (int nr) { return timers[nr].name; }\n    /// print profile\n    NGCORE_API static void Print (FILE * prof);\n\n    class RegionTimer\n    {\n      int nr;\n    public:\n      /// start timer\n      RegionTimer (int anr) : nr(anr) { NgProfiler::StartTimer(nr); }\n      /// stop timer\n      ~RegionTimer () { NgProfiler::StopTimer(nr); }\n\n      RegionTimer() = delete;\n      RegionTimer(const RegionTimer &) = delete;\n      RegionTimer(RegionTimer &&) = delete;\n      void operator=(const RegionTimer &) = delete;\n      void operator=(RegionTimer &&) = delete;\n    };\n  };\n\n  \n  struct TNoTracing{ static constexpr bool do_tracing=false; };\n  struct TTracing{ static constexpr bool do_tracing=true; };\n\n  struct TNoTiming{ static constexpr bool do_timing=false; };\n  struct TTiming{ static constexpr bool do_timing=true; };\n\n  namespace detail {\n\n      template<typename T>\n      constexpr bool is_tracing_type_v = std::is_same_v<T, TNoTracing> || std::is_same_v<T, TTracing>;\n\n      template<typename T>\n      constexpr bool is_timing_type_v = std::is_same_v<T, TNoTiming> || std::is_same_v<T, TTiming>;\n  }\n\n  [[maybe_unused]] static TNoTracing NoTracing;\n  [[maybe_unused]] static TNoTiming NoTiming;\n\n  template<typename TTracing=TTracing, typename TTiming=TTiming>\n  class Timer\n  {\n    int timernr;\n    int Init( const std::string & name )\n    {\n      return NgProfiler::CreateTimer (name);\n    }\n  public:\n    static constexpr bool do_tracing = TTracing::do_tracing;\n    static constexpr bool do_timing = TTiming::do_timing;\n\n    Timer (const std::string & name) : timernr(Init(name)) { }\n\n    template<std::enable_if_t< detail::is_tracing_type_v<TTracing>, bool> = false>\n    Timer( const std::string & name, TTracing ) : timernr(Init(name)) { }\n\n    template<std::enable_if_t< detail::is_timing_type_v<TTiming>, bool> = false>\n    Timer( const std::string & name, TTiming ) : timernr(Init(name)) { }\n\n    Timer( const std::string & name, TTracing, TTiming ) : timernr(Init(name)) { }\n\n    [[deprecated (\"Use Timer(name, NoTracing/NoTiming) instead\")]] Timer( const std::string & name, int ) : timernr(Init(name)) {}\n\n    void SetName (const std::string & name)\n    {\n      NgProfiler::SetName (timernr, name);\n    }\n    void Start () const\n    {\n      Start(TaskManager::GetThreadId());\n    }\n    void Stop () const\n    {\n      Stop(TaskManager::GetThreadId());\n    }\n    void Start (int tid, int trace_value = -1) const\n    {\n        if(tid==0)\n        {\n          if constexpr(do_timing)\n            NgProfiler::StartTimer (timernr);\n          if constexpr(do_tracing)\n            if(trace) trace->StartTimer(timernr, trace_value);\n        }\n        else\n        {\n          if constexpr(do_timing)\n            NgProfiler::StartThreadTimer(timernr, tid);\n          if constexpr(do_tracing)\n            if(trace) trace->StartTask (tid, timernr, PajeTrace::Task::ID_TIMER, trace_value);\n        }\n    }\n    void Stop (int tid) const\n    {\n        if(tid==0)\n        {\n            if constexpr(do_timing)\n                NgProfiler::StopTimer (timernr);\n            if constexpr(do_tracing)\n                if(trace) trace->StopTimer(timernr);\n        }\n        else\n        {\n          if constexpr(do_timing)\n            NgProfiler::StopThreadTimer(timernr, tid);\n          if constexpr(do_tracing)\n            if(trace) trace->StopTask (tid, timernr, PajeTrace::Task::ID_TIMER);\n        }\n    }\n    void AddFlops (double aflops)\n    {\n      if constexpr(do_timing)\n\tNgProfiler::AddFlops (timernr, aflops);\n    }\n\n    double GetTime () { return NgProfiler::GetTime(timernr); }\n    long int GetCounts () { return NgProfiler::GetCounts(timernr); }\n    double GetMFlops ()\n    { return NgProfiler::GetFlops(timernr)\n        / NgProfiler::GetTime(timernr) * 1e-6; }\n    operator int () const { return timernr; }\n  };\n\n\n  /**\n     Timer object.\n       Start / stop timer at constructor / destructor.\n  */\n  template<typename TTimer>\n  class RegionTimer\n  {\n    const TTimer & timer;\n    int tid;\n  public:\n    /// start timer\n    RegionTimer (const TTimer & atimer, int trace_value = -1) : timer(atimer)\n    {\n      tid = TaskManager::GetThreadId();\n      timer.Start(tid, trace_value);\n    }\n\n    /// stop timer\n    ~RegionTimer () { timer.Stop(tid); }\n\n    RegionTimer() = delete;\n    RegionTimer(const RegionTimer &) = delete;\n    RegionTimer(RegionTimer &&) = delete;\n    void operator=(const RegionTimer &) = delete;\n    void operator=(RegionTimer &&) = delete;\n  };\n\n  class [[deprecated(\"Use RegionTimer instead (now thread safe)\")]] ThreadRegionTimer\n  {\n    size_t nr;\n    size_t tid;\n  public:\n    /// start timer\n    ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid)\n    { NgProfiler::StartThreadTimer(nr, tid); }\n    /// stop timer\n    ~ThreadRegionTimer ()\n    { NgProfiler::StopThreadTimer(nr, tid); }\n\n    ThreadRegionTimer() = delete;\n    ThreadRegionTimer(ThreadRegionTimer &&) = delete;\n    ThreadRegionTimer(const ThreadRegionTimer &) = delete;\n    void operator=(const ThreadRegionTimer &) = delete;\n    void operator=(ThreadRegionTimer &&) = delete;\n  };\n\n  class RegionTracer\n    {\n      int nr;\n      int thread_id;\n      int type;\n    public:\n      static constexpr int ID_JOB = PajeTrace::Task::ID_JOB;\n      static constexpr int ID_NONE = PajeTrace::Task::ID_NONE;\n      static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER;\n\n      RegionTracer() = delete;\n      RegionTracer(RegionTracer &&) = delete;\n      RegionTracer(const RegionTracer &) = delete;\n      void operator=(const RegionTracer &) = delete;\n      void operator=(RegionTracer &&) = delete;\n\n      /// start trace\n      RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 )\n        : thread_id(athread_id)\n        {\n\t  if (trace)\n          trace->StartTask (athread_id, region_id, id_type, additional_value);\n          type = id_type;\n          nr = region_id;\n        }\n      /// start trace with timer\n      template<typename TTimer>\n      RegionTracer (int athread_id, TTimer & timer, int additional_value = -1 )\n        : thread_id(athread_id)\n        {\n          nr = timer;\n          type = ID_TIMER;\n\t  if (trace)\n            trace->StartTask (athread_id, nr, type, additional_value);\n        }\n\n      /// stop trace\n      ~RegionTracer ()\n        {\n\t  if (trace)\n            trace->StopTask (thread_id, nr, type);\n        }\n    };\n\n\n  // Helper function for timings\n  // Run f() at least min_iterations times until max_time seconds elapsed\n  // returns minimum runtime for a call of f()\n  template<typename TFunc>\n  double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 )\n  {\n      // Make sure the whole test run does not exceed maxtime\n      double tend = WallTime()+max_time;\n\n      // warmup\n      f();\n\n      double tres = std::numeric_limits<double>::max();\n      int iteration = 0;\n      while(WallTime()<tend || iteration++ < min_iterations)\n      {\n          double t = -WallTime();\n          f();\n          t += WallTime();\n          tres = std::min(tres, t);\n      }\n\n      return tres;\n  }\n\n} // namespace ngcore\n\n// Helper macro to easily add multiple timers in a function for profiling\n// Usage: NETGEN_TIMER_FROM_HERE(\"my_timer_name\")\n// Effect: define static Timer and RegionTimer with given name and line number\n#define NETGEN_TOKEN_CONCAT(x, y) x ## y\n#define NETGEN_TOKEN_CONCAT2(x, y) NETGEN_TOKEN_CONCAT(x, y)\n#define NETGEN_TIMER_FROM_HERE(name) \\\n  static Timer NETGEN_TOKEN_CONCAT2(timer_, __LINE__)( string(name)+\"_\"+ToString(__LINE__)); \\\n  RegionTimer NETGEN_TOKEN_CONCAT2(rt_,__LINE__)(NETGEN_TOKEN_CONCAT2(timer_,__LINE__));\n\n\n#endif // NETGEN_CORE_PROFILER_HPP\n"
  },
  {
    "path": "libsrc/core/python_ngcore.cpp",
    "content": "\n#include \"logging.hpp\"\n#include \"python_ngcore.hpp\"\n\nnamespace py = pybind11;\nusing std::string;\n\nnamespace ngcore\n{\n  bool ngcore_have_numpy = false;\n  bool parallel_pickling = true;\n\n  Archive& Archive::Shallow(std::any& val)\n  {\n    if(shallow_to_python)\n      {\n        if(is_output)\n          ShallowOutPython(CastAnyToPy(val));\n        else\n          {\n            pybind11::object obj;\n            ShallowInPython(obj);\n            val = CastPyToAny(obj);\n          }\n      }\n    return *this;\n  }\n  \n  void SetFlag(Flags &flags, string s, py::object value) \n  {\n    if (py::isinstance<py::dict>(value))\n      {             \n        Flags nested_flags;\n        for(auto item : value.cast<py::dict>())\n          SetFlag(nested_flags, item.first.cast<string>(),\n                  item.second.cast<py::object>());\n        flags.SetFlag(s, nested_flags);\n        return;\n      }\n    else if (py::isinstance<py::bool_>(value))\n      flags.SetFlag(s, value.cast<bool>());\n    else if (py::isinstance<py::float_>(value))\n      flags.SetFlag(s, value.cast<double>());\n    else if (py::isinstance<py::int_>(value))\n      flags.SetFlag(s, double(value.cast<int>()));\n    else if (py::isinstance<py::str>(value))\n      flags.SetFlag(s, value.cast<string>());\n    else if (py::isinstance<py::list>(value))\n      {             \n        auto vdl = py::cast<py::list>(value);\n        if (py::len(vdl) > 0)\n          {\n            if(py::isinstance<py::float_>(vdl[0]) || py::isinstance<py::int_>(vdl[0]))\n              flags.SetFlag(s, makeCArray<double>(vdl));\n            if(py::isinstance<py::str>(vdl[0]))\n              flags.SetFlag(s, makeCArray<string>(vdl));\n          }\n        else\n          {\n            Array<string> dummystr;\n            Array<double> dummydbl;\n            flags.SetFlag(s,dummystr);\n            flags.SetFlag(s,dummydbl);\n          }\n      }\n    else if (py::isinstance<py::tuple>(value))\n      {\n        auto vdt = py::cast<py::tuple>(value);\n        if (py::isinstance<py::float_>(value))\n          flags.SetFlag(s, makeCArray<double>(vdt));\n        if (py::isinstance<py::int_>(value))\n          flags.SetFlag(s, makeCArray<double>(vdt));\n        if (py::isinstance<py::str>(value))\n          flags.SetFlag(s, makeCArray<string>(vdt));\n      }\n    else\n      {\n        flags.SetFlag(s, CastPyToAny(value));\n      }\n  }\n\n  Flags CreateFlagsFromKwArgs(const py::kwargs& kwargs, py::object pyclass, py::list info)\n  {\n    static std::shared_ptr<Logger> logger = GetLogger(\"Flags\");\n    py::dict flags_dict;\n\n    if (kwargs.contains(\"flags\"))\n      {\n        logger->warn(\"WARNING: using flags as kwarg is deprecated{}, use the flag arguments as kwargs instead!\",\n                     pyclass.is_none() ? \"\" : std::string(\" in \") + std::string(py::str(pyclass)));\n        auto addflags = py::cast<py::dict>(kwargs[\"flags\"]);\n        for (auto item : addflags)\n          flags_dict[item.first.cast<string>().c_str()] = item.second;\n      }\n    py::dict special;\n    if(!pyclass.is_none())\n      {\n        auto flags_doc = pyclass.attr(\"__flags_doc__\")();\n        for (auto item : kwargs)\n          if (!flags_doc.contains(item.first.cast<string>().c_str()) &&\n              !(item.first.cast<string>() == \"flags\"))\n            logger->warn(\"WARNING: kwarg '{}' is an undocumented flags option for class {}, maybe there is a typo?\",\n                         item.first.cast<string>(), std::string(py::str(pyclass)));\n      \n        if(py::hasattr(pyclass,\"__special_treated_flags__\"))\n          special = pyclass.attr(\"__special_treated_flags__\")();\n      }\n    for (auto item : kwargs)\n      {\n        auto name = item.first.cast<string>();\n        if (name != \"flags\")\n          {\n            if(!special.contains(name.c_str()))\n              flags_dict[name.c_str()] = item.second;\n          }\n      }\n\n    Flags flags;\n    for(auto item : flags_dict)\n      SetFlag(flags, item.first.cast<string>(), item.second.cast<py::object>());\n\n    for (auto item : kwargs)\n      {\n        auto name = item.first.cast<string>();\n        if (name != \"flags\")\n          {\n            if(special.contains(name.c_str()))\n              special[name.c_str()](item.second, &flags, info);\n          }\n      }\n    return flags;\n  }\n\n  py::dict CreateDictFromFlags(const Flags& flags)\n  {\n    py::dict d;\n    std::string key;\n    for(auto i : Range(flags.GetNFlagsFlags()))\n      {\n        auto& f = flags.GetFlagsFlag(i, key);\n        d[key.c_str()] = CreateDictFromFlags(f);\n      }\n    for(auto i : Range(flags.GetNStringListFlags()))\n      {\n        auto strlistflag = flags.GetStringListFlag(i, key);\n        py::list lst;\n        for(auto& val : *strlistflag)\n          lst.append(val);\n        d[key.c_str()] = lst;\n      }\n    for(auto i : Range(flags.GetNNumListFlags()))\n      {\n        auto numlistflag = flags.GetNumListFlag(i, key);\n        py::list lst;\n        for(auto& val : *numlistflag)\n          lst.append(val);\n        d[key.c_str()] = lst;\n      }\n    for(auto i : Range(flags.GetNStringFlags()))\n      {\n        auto val = flags.GetStringFlag(i, key);\n        d[key.c_str()] = val;\n      }\n    for(auto i : Range(flags.GetNNumFlags()))\n      {\n        auto val = flags.GetNumFlag(i, key);\n        d[key.c_str()] = val;\n      }\n    for(auto i : Range(flags.GetNDefineFlags()))\n      {\n        auto val = flags.GetDefineFlag(i, key);\n        d[key.c_str()] = val;\n      }\n    for(auto i : Range(flags.GetNAnyFlags()))\n      {\n        auto& a = flags.GetAnyFlag(i, key);\n        d[key.c_str()] = CastAnyToPy(a);\n      }\n    return d;\n  }\n\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/python_ngcore.hpp",
    "content": "#ifndef NETGEN_CORE_PYTHON_NGCORE_HPP\n#define NETGEN_CORE_PYTHON_NGCORE_HPP\n\n#include \"ngcore_api.hpp\" // for operator new\n#include <pybind11/pybind11.h>\n#include <pybind11/operators.h>\n#include <pybind11/numpy.h>\n#include <pybind11/stl.h>\n#include <pybind11/stl/filesystem.h>\n\n#include \"array.hpp\"\n#include \"table.hpp\"\n#include \"archive.hpp\"\n#include \"flags.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"ng_mpi.hpp\"\n\nnamespace py = pybind11;\n\nnamespace ngcore\n{\n#ifdef PARALLEL\n  NGCORE_API extern bool (*NG_MPI_CommFromMPI4Py)(py::handle, NG_MPI_Comm &);\n  NGCORE_API extern py::handle (*NG_MPI_CommToMPI4Py)(NG_MPI_Comm);\n#endif // PARALLEL\n\n  namespace detail\n  {\n    template<typename T>\n    struct HasPyFormat\n    {\n    private:\n      template<typename T2>\n      static auto check(T2*) -> std::enable_if_t<std::is_same_v<decltype(std::declval<py::format_descriptor<T2>>().format()), std::string>, std::true_type>;\n      static auto check(...) -> std::false_type;\n    public:\n      static constexpr bool value = decltype(check((T*) nullptr))::value;\n    };\n  } // namespace detail\n\n#ifdef PARALLEL\n  struct mpi4py_comm {\n    mpi4py_comm() = default;\n    mpi4py_comm(NG_MPI_Comm value) : value(value) {}\n    operator NG_MPI_Comm () { return value; }\n\n    NG_MPI_Comm value;\n  };\n#endif  // PARALLEL\n} // namespace ngcore\n\n\n////////////////////////////////////////////////////////////////////////////////\n// automatic conversion of python list to Array<>\nnamespace pybind11 {\nnamespace detail {\n\n#ifdef PARALLEL\ntemplate <> struct type_caster<ngcore::mpi4py_comm> {\n  public:\n  PYBIND11_TYPE_CASTER(ngcore::mpi4py_comm, _(\"mpi4py_comm\"));\n\n    // Python -> C++\n    bool load(handle src, bool) {\n      return ngcore::NG_MPI_CommFromMPI4Py(src, value.value);\n    }\n\n    // C++ -> Python\n    static handle cast(ngcore::mpi4py_comm src,\n                       return_value_policy /* policy */,\n                       handle /* parent */)\n    {\n      // Create an mpi4py handle\n      return ngcore::NG_MPI_CommToMPI4Py(src.value);\n    }\n};\n#endif //  PARALLEL\n\ntemplate <typename Type, typename Value> struct ngcore_list_caster {\n    using value_conv = make_caster<Value>;\n\n    bool load(handle src, bool convert) {\n        if (!isinstance<sequence>(src) || isinstance<str>(src))\n            return false;\n        auto s = reinterpret_borrow<sequence>(src);\n        value.SetSize(s.size());\n        value.SetSize0();\n        for (auto it : s) {\n            value_conv conv;\n            if (!conv.load(it, convert))\n                return false;\n            value.Append(cast_op<Value &&>(std::move(conv)));\n        }\n        return true;\n    }\n\npublic:\n    template <typename T>\n    static handle cast(T &&src, return_value_policy policy, handle parent) {\n        if (!std::is_lvalue_reference<T>::value)\n            policy = return_value_policy_override<Value>::policy(policy);\n        list l(src.Size());\n        size_t index = 0;\n        for (auto &&value : src) {\n            auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));\n            if (!value_)\n                return handle();\n            PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference\n        }\n        return l.release();\n    }\n\n    PYBIND11_TYPE_CASTER(Type, _(\"Array[\") + value_conv::name + _(\"]\"));\n};\n\n\ntemplate <typename Type> struct type_caster<ngcore::Array<Type>, enable_if_t<!ngcore::detail::HasPyFormat<Type>::value>>\n : ngcore_list_caster<ngcore::Array<Type>, Type> { };\n\n\n  /*\n  template <typename Type> struct type_caster<std::shared_ptr<ngcore::Table<Type>>>\n  {\n    template <typename T>\n    static handle cast(T &&src, return_value_policy policy, handle parent)\n    {\n      std::cout << \"handle called with type src = \" << typeid(src).name() << std::endl;\n\n      return handle(); // what so ever\n    }\n    \n    PYBIND11_TYPE_CASTER(Type, _(\"Table[\") + make_caster<Type>::name + _(\"]\"));\n  };\n  */\n  \n  \n\n} // namespace detail\n} // namespace pybind11\n////////////////////////////////////////////////////////////////////////////////\n\nnamespace ngcore\n{\n  NGCORE_API extern bool ngcore_have_numpy;\n  NGCORE_API extern bool parallel_pickling;\n  \n  // Python class name type traits\n  template <typename T>\n  struct PyNameTraits {\n    static const std::string & GetName()\n    {\n      static const std::string name = typeid(T).name();\n      return name;\n    }\n  };\n\n  template <typename T>\n  std::string GetPyName(const char *prefix = 0) {\n    std::string s;\n    if(prefix) s = std::string(prefix);\n    s+= PyNameTraits<T>::GetName();\n    return s;\n  }\n\n  template<>\n  struct PyNameTraits<int> {\n    static std::string GetName() { return \"I\"; }\n  };\n\n  template<>\n  struct PyNameTraits<unsigned> {\n    static std::string GetName() { return \"U\"; }\n  };\n\n  template<>\n  struct PyNameTraits<float> {\n    static std::string GetName() { return \"F\"; }\n  };\n\n  template<>\n  struct PyNameTraits<double> {\n    static std::string GetName() { return \"D\"; }\n  };\n\n  template<>\n  struct PyNameTraits<size_t> {\n    static std::string GetName() { return \"S\"; }\n  };\n\n  template<typename T>\n  struct PyNameTraits<std::shared_ptr<T>> {\n    static std::string GetName()\n    { return std::string(\"sp_\")+GetPyName<T>(); }\n  };\n\n  template<typename ARCHIVE>\n  class NGCORE_API_EXPORT PyArchive : public ARCHIVE\n  {\n  private:\n    pybind11::list lst;\n    size_t index = 0;\n    std::map<std::string, VersionInfo> version_needed;\n  protected:\n    using ARCHIVE::stream;\n    using ARCHIVE::version_map;\n  public:\n    PyArchive(const pybind11::object& alst = pybind11::none()) :\n      ARCHIVE(std::make_shared<std::stringstream>()),\n      lst(alst.is_none() ? pybind11::list() : pybind11::cast<pybind11::list>(alst))\n    {\n      ARCHIVE::shallow_to_python = true;\n      if(Input())\n        {\n          stream = std::make_shared<std::stringstream>\n            (pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));\n          *this & version_needed;\n          for(auto& libversion : version_needed)\n            if(libversion.second > GetLibraryVersion(libversion.first))\n              throw Exception(\"Error in unpickling data:\\nLibrary \" + libversion.first +\n                              \" must be at least \" + libversion.second.to_string());\n          stream = std::make_shared<std::stringstream>\n            (pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-2]));\n          *this & version_map;\n          stream = std::make_shared<std::stringstream>\n            (pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-3]));\n        }\n    }\n\n    void NeedsVersion(const std::string& library, const std::string& version) override\n    {\n      if(Output())\n        {\n          version_needed[library] = version_needed[library] > version ? version_needed[library] : version;\n        }\n    }\n\n    using ARCHIVE::Output;\n    using ARCHIVE::Input;\n    using ARCHIVE::FlushBuffer;\n    using ARCHIVE::operator&;\n    using ARCHIVE::operator<<;\n    using ARCHIVE::GetVersion;\n    void ShallowOutPython(const pybind11::object& val) override { lst.append(val); }\n    void ShallowInPython(pybind11::object& val) override { val = lst[index++]; }\n\n    pybind11::list WriteOut()\n    {\n      auto version_runtime = GetLibraryVersions();\n      FlushBuffer();\n      lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));\n      stream = std::make_shared<std::stringstream>();\n      *this & version_runtime;\n      FlushBuffer();\n      lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));\n      stream = std::make_shared<std::stringstream>();\n      *this & version_needed;\n      FlushBuffer();\n      lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));\n      return lst;\n    }\n  };\n\n  template<typename T, typename T_ARCHIVE_OUT=BinaryOutArchive, typename T_ARCHIVE_IN=BinaryInArchive>\n  auto NGSPickle()\n  {\n    return pybind11::pickle([](T* self)\n                      {\n                        PyArchive<T_ARCHIVE_OUT> ar;\n                        ar.SetParallel(parallel_pickling);\n                        ar & self;\n                        auto output = pybind11::make_tuple(ar.WriteOut());\n                        return output;\n                      },\n                      [](const pybind11::tuple & state)\n                      {\n                        T* val = nullptr;\n                        PyArchive<T_ARCHIVE_IN> ar(state[0]);\n                        ar & val;\n                        return val;\n                      });\n  }\n\n  template<typename T>\n  Array<T> makeCArray(const py::object& obj)\n  {\n    Array<T> arr;\n    if(py::isinstance<py::list>(obj))\n        for(auto& val : py::cast<py::list>(obj))\n          arr.Append(py::cast<T>(val));\n    else if(py::isinstance<py::tuple>(obj))\n      for(auto& val : py::cast<py::tuple>(obj))\n        arr.Append(py::cast<T>(val));\n    else\n      throw py::type_error(\"Cannot convert Python object to C Array\");\n    return arr;\n  }\n\n  template <typename T>\n  // py::object makePyTuple (FlatArray<T> ar)\n  py::object makePyTuple (const BaseArrayObject<T> & ar)\n  {\n    py::tuple res(ar.Size());\n    for (auto i : Range(ar))\n      res[i] = py::cast(ar[i]);\n    return res;\n  }\n\n  template <typename T, typename TIND=typename FlatArray<T>::index_type>\n  void ExportArray (py::module &m)\n  {\n      using TFlat = FlatArray<T, TIND>;\n      using TArray = Array<T, TIND>;\n      std::string suffix = GetPyName<T>() + \"_\" +\n        GetPyName<TIND>();\n      std::string fname = std::string(\"FlatArray_\") + suffix;\n      auto flatarray_class = py::class_<TFlat>(m, fname.c_str(),\n                                               py::buffer_protocol())\n        .def (\"__len__\", [] ( TFlat &self ) { return self.Size(); } )\n        .def (\"__getitem__\",\n              [](TFlat & self, TIND i) -> T&\n                             {\n                               // static constexpr int base = IndexBASE<TIND>();\n                               auto reli = i - IndexBASE<TIND>();\n                               if (reli < 0 || reli >= self.Size())\n                                 throw py::index_error();\n                               return self[i]; \n                             },\n              py::return_value_policy::reference)\n        .def (\"__setitem__\",\n              [](TFlat & self, TIND i, T val) -> T&\n                             {\n                               // static constexpr int base = IndexBASE<TIND>();\n                               auto reli = i - IndexBASE<TIND>();                               \n                               if (reli < 0 || reli >= self.Size())\n                                 throw py::index_error();\n                               self[i] = val;\n                               return self[i];\n                             },\n              py::return_value_policy::reference)\n\n        .def (\"__setitem__\",\n              [](TFlat & self, py::slice slice, T val)\n              {\n                size_t start, stop, step, slicelength;\n                if (!slice.compute(self.Size(), &start, &stop, &step, &slicelength))\n                  throw py::error_already_set();\n                static constexpr int base = IndexBASE<TIND>();\n                if (start < base || start+(slicelength-1)*step >= self.Size()+base)\n                  throw py::index_error();\n                for (size_t i = 0; i < slicelength; i++, start+=step)\n                  self[start] = val;\n              })\n\n        .def(\"__iter__\", [] ( TFlat & self) {\n             return py::make_iterator (self.begin(),self.end());\n             }, py::keep_alive<0,1>()) // keep array alive while iterator is used\n\n        .def(\"__str__\", [](TFlat& self)\n                        {\n                          return ToString(self);\n                        })\n      ;\n\n      if constexpr (detail::HasPyFormat<T>::value)\n        {\n          if(ngcore_have_numpy && !py::detail::npy_format_descriptor<T>::dtype().is_none())\n            {\n              flatarray_class\n                .def_buffer([](TFlat& self)\n                            {\n                              return py::buffer_info(\n                                self.Addr(0),\n                                sizeof(T),\n                                py::format_descriptor<T>::format(),\n                                1,\n                                { self.Size() },\n                                { sizeof(T) * (self.Addr(1) - self.Addr(0)) });\n                            })\n                .def(\"NumPy\", [](py::object self)\n                              {\n                                return py::module::import(\"numpy\")\n                                  .attr(\"frombuffer\")(self, py::detail::npy_format_descriptor<T>::dtype());\n                              })\n                ;\n              }\n          }\n\n      std::string aname = std::string(\"Array_\") + suffix;\n      auto arr = py::class_<TArray, TFlat> (m, aname.c_str())\n        .def(py::init([] (size_t n) { return new TArray(n); }),py::arg(\"n\"), \"Makes array of given length\")\n        .def(py::init([] (std::vector<T> const & x)\n                  {\n                    size_t s = x.size();\n                    TArray tmp(s);\n                    for (size_t i : Range(tmp))\n                      tmp[TIND(i)] = x[i];\n                    return tmp;\n                  }), py::arg(\"vec\"), \"Makes array with given list of elements\")\n        ;\n      if constexpr(is_archivable<TArray>)\n        arr.def(NGSPickle<TArray>());\n      py::implicitly_convertible<std::vector<T>, TArray>();\n    }\n\n  template <typename T>\n  void ExportTable (py::module &m)\n  {\n    py::class_<ngcore::Table<T>, std::shared_ptr<ngcore::Table<T>>> (m, (\"Table_\"+GetPyName<T>()).c_str())\n      .def(py::init([] (py::list blocks)\n                    {\n                       size_t size = py::len(blocks);\n                       Array<int> cnt(size);\n                       size_t i = 0;\n                       for (auto block : blocks)\n                         cnt[i++] = py::len(block);\n                       \n                       i = 0;\n                       Table<T> blocktable(cnt);\n                       for (auto block : blocks)\n                         {\n                           auto row = blocktable[i++];\n                           size_t j = 0;\n                           for (auto val : block)\n                             row[j++] = val.cast<T>();\n                         }\n                       // cout << \"blocktable = \" << *blocktable << endl;\n                       return blocktable;\n                      \n                    }), py::arg(\"blocks\"), \"a list of lists\")\n\n      .def (\"__len__\", [] (Table<T> &self ) { return self.Size(); } )\n      .def (\"__getitem__\",\n            [](Table<T> & self, size_t i) -> FlatArray<T>\n            {\n              if (i >= self.Size())\n                throw py::index_error();\n              return self[i]; \n            })\n      .def(\"__str__\", [](Table<T> & self)\n           {\n             return ToString(self);\n           })\n      ;\n  }\n\n  \n  void NGCORE_API SetFlag(Flags &flags, std::string s, py::object value);\n  // Parse python kwargs to flags\n  Flags NGCORE_API CreateFlagsFromKwArgs(const py::kwargs& kwargs, py::object pyclass = py::none(),\n                                         py::list info = py::list());\n  // Create python dict from kwargs\n  py::dict NGCORE_API CreateDictFromFlags(const Flags& flags);\n\n\n} // namespace ngcore\n\n#endif // NETGEN_CORE_PYTHON_NGCORE_HPP\n"
  },
  {
    "path": "libsrc/core/python_ngcore_export.cpp",
    "content": "#include \"archive.hpp\"\n#include \"python_ngcore.hpp\"\n#include \"bitarray.hpp\"\n#include \"taskmanager.hpp\"\n#include \"mpi_wrapper.hpp\"\n\nusing namespace ngcore;\nusing namespace std;\nusing namespace pybind11::literals;\n\nnamespace pybind11 { namespace detail {\n}} // namespace pybind11::detail\n\n\n\n\nPYBIND11_MODULE(pyngcore, m) // NOLINT\n{\n  try\n    {\n      auto numpy = py::module::import(\"numpy\");\n      ngcore_have_numpy = !numpy.is_none();\n    }\n  catch(...) {}\n  ExportArray<int>(m);\n  ExportArray<unsigned>(m);\n  ExportArray<size_t>(m);\n  ExportArray<double>(m);\n  ExportArray<float>(m);\n  ExportArray<signed short>(m);\n  ExportArray<signed char>(m);\n  ExportArray<unsigned short>(m);\n  ExportArray<unsigned char>(m);\n\n  // Compiler dependent implementation of size_t\n  if constexpr(!is_same_v<size_t, uint64_t>)\n    ExportArray<uint64_t>(m);\n\n  ExportTable<int>(m);\n\n  #ifdef PARALLEL\n  py::class_<NG_MPI_Comm> (m, \"_NG_MPI_Comm\")\n          ;\n  m.def(\"InitMPI\", &InitMPI, py::arg(\"mpi_library_path\")=nullopt);\n  #endif // PARALLEL\n\n  py::class_<BitArray, shared_ptr<BitArray>> (m, \"BitArray\")\n    .def(py::init([] (size_t n) { return make_shared<BitArray>(n); }),py::arg(\"n\"))\n    .def(py::init([] (const BitArray& a) { return make_shared<BitArray>(a); } ), py::arg(\"ba\"))\n    .def(py::init([] (const vector<bool> & a)\n                  {\n                    auto ba = make_shared<BitArray>(a.size());\n                    ba->Clear();\n                    for (size_t i = 0; i < a.size(); i++)\n                      if (a[i]) ba->SetBit(i);\n                    return ba;\n                  } ), py::arg(\"vec\"))\n    .def(NGSPickle<BitArray>())\n    .def(\"__str__\", &ToString<BitArray>)\n    .def(\"__len__\", &BitArray::Size)\n    .def(\"__getitem__\", [] (BitArray & self, int i)\n                                         {\n                                           if (i < 0) i+=self.Size();\n                                           if (i < 0 || i >= self.Size())\n                                             throw py::index_error();\n                                           return self.Test(i);\n                                         }, py::arg(\"pos\"), \"Returns bit from given position\")\n    .def(\"__setitem__\", [] (BitArray & self, int i, bool b)\n                                         {\n                                           if (i < 0) i+=self.Size();\n                                           if (i < 0 || i >= self.Size())\n                                             throw py::index_error();\n                                           if (b) self.SetBit(i); else self.Clear(i);\n                                         }, py::arg(\"pos\"), py::arg(\"value\"), \"Clear/Set bit at given position\")\n\n    .def(\"__setitem__\", [] (BitArray & self, py::slice inds, bool b)\n                                         {\n                                           size_t start, step, stop, n;\n                                           if (!inds.compute(self.Size(), &start, &stop, &step, &n))\n                                             throw py::error_already_set();\n\n                                           if (start == 0 && n == self.Size() && step == 1)\n                                             { // base branch\n                                               if (b)\n                                                 self.Set();\n                                               else\n                                                 self.Clear();\n                                             }\n                                           else\n                                             {\n                                               if (b)\n                                                 for (size_t i=0; i<n; i++, start+=step)\n                                                   self.SetBit(start);\n                                               else\n                                                 for (size_t i=0; i<n; i++, start+=step)\n                                                   self.Clear(start);\n                                             }\n                                         }, py::arg(\"inds\"), py::arg(\"value\"), \"Clear/Set bit at given positions\")\n\n    .def(\"__setitem__\", [] (BitArray & self, py::slice inds, BitArray & ba)\n                                         {\n                                           size_t start, step, stop, n;\n                                           if (!inds.compute(self.Size(), &start, &stop, &step, &n))\n                                             throw py::error_already_set();\n\n                                           if (start == 0 && n == self.Size() && step == 1)\n                                             {\n                                               self = ba;\n                                             }\n                                           else\n                                             {\n                                               for (size_t i = 0; i < n; i++, start += step)\n                                                 {\n                                                   bool b = ba.Test(i);\n                                                   if (b)\n                                                     self.SetBit(start);\n                                                   else\n                                                     self.Clear(start);\n                                                 }\n                                             }\n                                         }, py::arg(\"inds\"), py::arg(\"ba\"), \"copy BitArray\")\n\n    .def(\"__setitem__\", [](BitArray & self,  IntRange range, bool b)\n      {\n        if (b)\n          for (size_t i : range)\n            self.SetBit(i);\n        else\n          for (size_t i : range)\n            self.Clear(i);\n      }, py::arg(\"range\"), py::arg(\"value\"), \"Set value for range of indices\" )\n\n    .def(\"NumSet\", &BitArray::NumSet)\n    .def(\"Set\", [] (BitArray & self) { self.Set(); }, \"Set all bits\")\n    .def(\"Set\", &BitArray::SetBit, py::arg(\"i\"), \"Set bit at given position\")\n    .def(\"Clear\", [] (BitArray & self) { self.Clear(); }, \"Clear all bits\")\n    .def(\"Clear\", [] (BitArray & self, int i)\n                                   {\n                                       self.Clear(i);\n                                   }, py::arg(\"i\"), \"Clear bit at given position\")\n\n\n    .def(py::self | py::self)\n    .def(py::self & py::self)\n    #ifdef __clang__ \n    // see https://github.com/pybind/pybind11/issues/1893\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wself-assign-overloaded\"\n    #endif\n    .def(py::self |= py::self)\n    .def(py::self &= py::self)\n    #ifdef __clang__\n    #pragma GCC diagnostic pop\n    #endif\n    .def(~py::self)\n    ;\n\n  py::class_<Flags>(m, \"Flags\")\n    .def(py::init<>())\n    .def(\"__str__\", &ToString<Flags>)\n    .def(py::init([](py::dict kwargs) {\n          Flags flags;\n          for (auto d : kwargs)\n            SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());\n          return flags;\n    }), \"Create flags from dict\")\n    .def(py::init([](py::kwargs kwargs) {\n          Flags flags;\n          for (auto d : kwargs)\n            SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());\n          return flags;\n        }), \"Create flags from kwargs\")\n    // .def(NGSPickle<Flags>()) // in future versions we can kick out backward compatibility\n    .def(py::pickle([](Flags &f)\n        {\n          PyArchive<BinaryOutArchive> ar;\n          ar.SetParallel(parallel_pickling);\n          ar & f;\n          auto output = py::make_tuple(ar.WriteOut());\n          return output;\n        },\n        [](py::tuple& state)\n        {\n          if(py::isinstance<py::list>(state[0]))\n            {\n              Flags flags;\n              PyArchive<BinaryInArchive> ar(state[0]);\n              ar & flags;\n              return flags;\n            }\n          else\n            {\n              // flags have been pickled with old Netgen version\n              string s = state[0].cast<string>();\n              std::stringstream str(s);\n              Flags flags;\n              flags.LoadFlags(str);\n              return flags;\n            }\n        }\n    ))\n    .def(\"Set\",[](Flags & self,const py::dict & aflags)->Flags&\n    {      \n      SetFlag(self, \"\", aflags);\n      return self;\n    }, py::arg(\"aflag\"), \"Set the flags by given dict\")\n\n    .def(\"Set\",[](Flags & self, const char * akey, const py::object & value)->Flags&\n    {             \n        SetFlag(self, akey, value);\n        return self;\n    }, py::arg(\"akey\"), py::arg(\"value\"), \"Set flag by given value.\")\n\n    .def(\"keys\", [](Flags & self) -> py::list {\n        return CreateDictFromFlags(self).attr(\"keys\")();\n    })\n    .def(\"__getitem__\", [](Flags & self, const string& name) -> py::object {\n\n\t  if(self.NumListFlagDefined(name))\n\t    return py::cast(self.GetNumListFlag(name));\n\n\t  if(self.StringListFlagDefined(name))\n\t    return py::cast(self.GetStringListFlag(name));\n\t \n\t  if(self.NumFlagDefined(name))\n\t    return py::cast(*self.GetNumFlagPtr(name));\n\t  \n\t  if(self.StringFlagDefined(name))\n\t    return py::cast(self.GetStringFlag(name));\n\n\t  if(self.FlagsFlagDefined(name))\n\t    return py::cast(self.GetFlagsFlag(name));\n\n          if(self.AnyFlagDefined(name))\n            return CastAnyToPy(self.GetAnyFlag(name));\n\n\t  return py::cast(self.GetDefineFlag(name));\n      }, py::arg(\"name\"), \"Return flag by given name\")\n    .def(\"ToDict\", [](const Flags& flags)\n    {\n      return CreateDictFromFlags(flags);\n    })\n    .def(\"items\", [](const Flags& flags)\n    {\n      return CreateDictFromFlags(flags).attr(\"items\")();\n    })\n  ;\n  py::implicitly_convertible<py::dict, Flags>();\n\n  py::class_<xbool>(m, \"xbool\")\n    .def(py::init<>())\n    .def(py::init<bool>(), py::arg(\"b\"))\n    .def(\"__str__\", &ToString<xbool>)\n    .def_property_readonly(\"is_true\", &xbool::IsTrue)\n    .def_property_readonly(\"is_false\", &xbool::IsFalse)\n    .def_property_readonly(\"is_maybe\", &xbool::IsMaybe)\n    ;\n\n  \n  py::enum_<level::level_enum>(m, \"LOG_LEVEL\", \"Logging level\")\n    .value(\"Trace\", level::trace)\n    .value(\"Debug\", level::debug)\n    .value(\"Info\", level::info)\n    .value(\"Warn\", level::warn)\n    .value(\"Error\", level::err)\n    .value(\"Critical\", level::critical)\n    .value(\"Off\", level::off);\n\n  m.def(\"SetLoggingLevel\", &SetLoggingLevel, py::arg(\"level\"), py::arg(\"logger\")=\"\",\n        \"Set logging level, if name is given only to the specific logger, else set the global logging level\");\n  m.def(\"AddFileSink\", &AddFileSink, py::arg(\"filename\"), py::arg(\"level\"), py::arg(\"logger\")=\"\",\n        \"Add File sink, either only to logger specified or globally to all loggers\");\n  m.def(\"AddConsoleSink\", &AddConsoleSink, py::arg(\"level\"), py::arg(\"logger\")=\"\",\n        \"Add console output for specific logger or all if none given\");\n  m.def(\"ClearLoggingSinks\", &ClearLoggingSinks, py::arg(\"logger\")=\"\",\n        \"Clear sinks of specific logger, or all if none given\");\n  m.def(\"FlushOnLoggingLevel\", &FlushOnLoggingLevel, py::arg(\"level\"), py::arg(\"logger\")=\"\",\n        \"Flush every message with level at least `level` for specific logger or all loggers if none given.\");\n\n  m.def(\"RunWithTaskManager\",\n          [](py::object lam)\n                           {\n                             GetLogger(\"TaskManager\")->info(\"running Python function with task-manager\");\n                             RunWithTaskManager ([&] () { lam(); });\n                           }, py::arg(\"lam\"), R\"raw_string(\nParameters:\n\nlam : object\n  input function\n\n)raw_string\")\n          ;\n\n  m.def(\"SetNumThreads\", &TaskManager::SetNumThreads, py::arg(\"threads\"), R\"raw_string(\nSet number of threads\n\nParameters:\n\nthreads : int\n  input number of threads\n\n)raw_string\");\n\n  // local TaskManager class to be used as context manager in Python\n  class ParallelContextManager {\n      int num_threads;\n    public:\n      ParallelContextManager() : num_threads(0) {\n        TaskManager::SetPajeTrace(0);\n        PajeTrace::SetMaxTracefileSize(0);\n      };\n      ParallelContextManager(size_t pajesize) : num_threads(0) {\n        TaskManager::SetPajeTrace(pajesize > 0);\n        PajeTrace::SetMaxTracefileSize(pajesize);\n      }\n      void Enter() {num_threads = EnterTaskManager(); }\n      void Exit(py::object exc_type, py::object exc_value, py::object traceback) {\n          ExitTaskManager(num_threads);\n      }\n    };\n\n  py::class_<ParallelContextManager>(m, \"TaskManager\")\n    .def(py::init<>())\n    .def(py::init<size_t>(), \"pajetrace\"_a, \"Run paje-tracer, specify buffersize in bytes\")\n    .def(\"__enter__\", &ParallelContextManager::Enter)\n    .def(\"__exit__\", &ParallelContextManager::Exit)\n    .def(\"__timing__\", &TaskManager::Timing)\n    ;\n\n\n  py::class_<SuspendTaskManager>(m, \"SuspendTaskManager\")\n        .def(py::init<int>(),py::arg(\"sleep_usecs\")=1000,\n             \"sleep_usecs : int\\n    number of microseconds the worker threads sleep\")\n        .def(\"__enter__\", [](SuspendTaskManager &self) -> SuspendTaskManager& {\n            return self;\n        })\n        .def(\"__exit__\", [](SuspendTaskManager &self, py::object exc_type, py::object exc_value, py::object traceback) {\n            return false;\n        });\n\n  py::class_<PajeTrace>(m, \"PajeTrace\")\n    .def(py::init( [] (string filename, size_t size_mb, bool threads, bool thread_counter, bool memory)\n          {\n              PajeTrace::SetMaxTracefileSize(size_mb*1014*1024);\n              PajeTrace::SetTraceThreads(threads);\n              PajeTrace::SetTraceMemory(memory);\n              PajeTrace::SetTraceThreadCounter(thread_counter);\n              trace = new PajeTrace(TaskManager::GetMaxThreads(), filename);\n              return trace;\n          }), py::arg(\"filename\")=\"ng.trace\", py::arg(\"size\")=1000,\n              py::arg(\"threads\")=true, py::arg(\"thread_counter\")=false,\n              py::arg(\"memory\")=true,\n              \"size in Megabytes\"\n        )\n    .def(\"__enter__\", [](PajeTrace & self) { })\n    .def(\"__exit__\", [](PajeTrace & self, py::args) { trace = nullptr; })\n    .def_static(\"SetTraceThreads\", &PajeTrace::SetTraceThreads)\n    .def_static(\"SetTraceThreadCounter\", &PajeTrace::SetTraceThreadCounter)\n    .def_static(\"SetMaxTracefileSize\", &PajeTrace::SetMaxTracefileSize)\n#ifdef NETGEN_TRACE_MEMORY\n    .def_static(\"WriteMemoryChart\", [](string filename){ if(trace) trace->WriteMemoryChart(filename); }, py::arg(\"filename\")=\"memory\" )\n#endif // NETGEN_TRACE_MEMORY\n    ;\n\n    m.def(\"GetTotalMemory\", MemoryTracer::GetTotalMemory);\n\n    py::class_<Timer<>> (m, \"Timer\")\n    .def(py::init<const string&>())\n    .def(\"Start\", static_cast<void (Timer<>::*)()const>(&Timer<>::Start), \"start timer\")\n    .def(\"Stop\", static_cast<void (Timer<>::*)()const>(&Timer<>::Stop), \"stop timer\")\n    .def_property_readonly(\"time\", &Timer<>::GetTime, \"returns time\")\n    .def(\"__enter__\", static_cast<void (Timer<>::*)()const>(&Timer<>::Start))\n    .def(\"__exit__\", [](Timer<>& t, py::object, py::object, py::object)\n                     {\n                       t.Stop();\n                     })\n    ;\n  \n  m.def(\"Timers\",\n\t  []() \n\t   {\n\t     py::list timers;\n\t     for (int i = 0; i < NgProfiler::SIZE; i++)\n\t       if (!NgProfiler::timers[i].name.empty())\n               {\n                 py::dict timer;\n                 timer[\"name\"] = py::str(NgProfiler::timers[i].name);\n                 timer[\"time\"] = py::float_(NgProfiler::GetTime(i));\n                 timer[\"counts\"] = py::int_(NgProfiler::GetCounts(i));\n                 timer[\"flops\"] = py::float_(NgProfiler::GetFlops(i));\n                 timer[\"Gflop/s\"] = py::float_(NgProfiler::GetFlops(i)/NgProfiler::GetTime(i)*1e-9);\n                 timers.append(timer);\n               }\n\t     return timers;\n\t   }, \"Returns list of timers\"\n\t   );\n  m.def(\"ResetTimers\", &NgProfiler::Reset);\n\n  py::class_<NgMPI_Comm> (m, \"MPI_Comm\")\n#ifdef PARALLEL\n    .def(py::init([] (mpi4py_comm comm) { return NgMPI_Comm(comm); }))\n    .def(\"WTime\", [](NgMPI_Comm  & c) { return NG_MPI_Wtime(); })\n    .def_property_readonly (\"mpi4py\", [](NgMPI_Comm & self) { return NG_MPI_CommToMPI4Py(self); })\n#endif  // PARALLEL\n    .def_property_readonly (\"rank\", &NgMPI_Comm::Rank)\n    .def_property_readonly (\"size\", &NgMPI_Comm::Size)\n    .def(\"Barrier\", &NgMPI_Comm::Barrier)\n    .def(\"Sum\", [](NgMPI_Comm  & c, double x) { return c.AllReduce(x, NG_MPI_SUM); })\n    .def(\"Min\", [](NgMPI_Comm  & c, double x) { return c.AllReduce(x, NG_MPI_MIN); })\n    .def(\"Max\", [](NgMPI_Comm  & c, double x) { return c.AllReduce(x, NG_MPI_MAX); })\n    .def(\"Sum\", [](NgMPI_Comm  & c, int x) { return c.AllReduce(x, NG_MPI_SUM); })\n    .def(\"Min\", [](NgMPI_Comm  & c, int x) { return c.AllReduce(x, NG_MPI_MIN); })\n    .def(\"Max\", [](NgMPI_Comm  & c, int x) { return c.AllReduce(x, NG_MPI_MAX); })\n    .def(\"Sum\", [](NgMPI_Comm  & c, size_t x) { return c.AllReduce(x, NG_MPI_SUM); })\n    .def(\"Min\", [](NgMPI_Comm  & c, size_t x) { return c.AllReduce(x, NG_MPI_MIN); })\n    .def(\"Max\", [](NgMPI_Comm  & c, size_t x) { return c.AllReduce(x, NG_MPI_MAX); })\n    .def(\"SubComm\", [](NgMPI_Comm & c, std::vector<int> proc_list) {\n        Array<int> procs(proc_list.size());\n        for (int i = 0; i < procs.Size(); i++)\n          { procs[i] = proc_list[i]; }\n        if (!procs.Contains(c.Rank()))\n          { throw Exception(\"rank \"+ToString(c.Rank())+\" not in subcomm\"); }\n\treturn c.SubCommunicator(procs);\n      }, py::arg(\"procs\"));\n  ;\n\n  m.def(\"_GetArchiveRegisteredClasses\", []() {\n      const auto & reg = GetTypeRegister();\n      py::dict class_dict;\n      for (const auto & [name, info] : reg)\n      {\n        class_dict[py::str(name)] = py::make_tuple(\n            (uintptr_t)info.creator,\n            (uintptr_t)info.upcaster,\n            (uintptr_t)info.downcaster,\n            (uintptr_t)info.cargs_archiver,\n            (uintptr_t)info.anyToPyCaster,\n            (uintptr_t)info.pyToAnyCaster\n        );\n      }\n      return class_dict;\n  });\n\n    \n#ifdef PARALLEL\n  py::implicitly_convertible<mpi4py_comm, NgMPI_Comm>();\n#endif // PARALLEL\n}\n"
  },
  {
    "path": "libsrc/core/ranges.hpp",
    "content": "#ifndef NETGEN_CORE_RANGES_HPP\n#define NETGEN_CORE_RANGES_HPP\n\n#include <iterator>\n\nnamespace ngcore\n{\n  template<typename Iterator>\n  class AdapterRange\n  {\n    Iterator _begin,_end;\n  public:\n    AdapterRange(Iterator abegin, Iterator aend) : _begin(abegin), _end(aend) { ; }\n    Iterator begin() const { return _begin; }\n    Iterator end() const { return _end; }\n  };\n\n  template<typename FUNC>\n  class FilterAdapter\n  {\n    FUNC f;\n  public:\n    FilterAdapter(FUNC af) : f(af) { ; }\n    FUNC GetFunction() const { return f; }\n  };\n\n  template<typename FUNC, typename Iterator>\n  class FilterIterator\n  {\n    Iterator iter;\n    Iterator end;\n    FUNC f;\n  public:\n    FilterIterator(FUNC af, Iterator aiter, Iterator aend)\n      :  iter(aiter), end(aend), f(af)\n    {\n      while(iter!=end && !f(*iter))\n        ++iter;\n    }\n    inline FilterIterator& operator ++()\n    {\n      ++iter;\n      while(iter!=end && !f(*iter))\n        ++iter;\n      return *this;\n    }\n\n    inline bool operator !=(FilterIterator other)\n    {\n      return iter != other.iter;\n    }\n\n    inline bool operator ==(FilterIterator other)\n    {\n      return iter == other.iter;\n    }\n\n    inline decltype(auto) operator *() const\n    {\n      return *iter;\n    }\n  };\n\n  template<typename FUNC>\n  FilterAdapter<FUNC> filter(FUNC f) { return {f}; }\n\n  template<typename Range, typename FUNC>\n  auto operator |(Range&& range, FilterAdapter<FUNC> adapter)\n    -> AdapterRange<FilterIterator<FUNC,decltype(std::begin(range))>>\n  {\n    return {{adapter.GetFunction(),std::begin(range),std::end(range)},\n        {adapter.GetFunction(), std::end(range), std::end(range)}};\n  }\n\n  template<typename FUNC, typename Iterator>\n  class TransformIterator\n  {\n    FUNC f;\n    Iterator iter;\n  public:\n    TransformIterator(FUNC af, Iterator aiter) : f(af), iter(aiter) { ; }\n\n    TransformIterator& operator++() { ++iter; }\n    bool operator !=(TransformIterator other) { return iter != other.iter; }\n    decltype(auto) operator *() const { return f(*iter); }\n  };\n\n  template<typename FUNC>\n  class TransformAdapter\n  {\n    FUNC f;\n  public:\n    TransformAdapter(FUNC af) : f(af) { ; }\n    FUNC GetFunction() const { return f; }\n  };\n\n  template<typename FUNC>\n  TransformAdapter<FUNC> transform(FUNC f) { return {f}; }\n\n  template<typename Range, typename FUNC>\n  auto operator |(Range&& range, TransformAdapter<FUNC> adapter)\n    -> AdapterRange<TransformIterator<FUNC,decltype(std::begin(range))>>\n  {\n    return {{adapter.GetFunction(), std::begin(range)},\n        {adapter.GetFunction(),std::end(range)}};\n  }\n} // namespace ngcore\n\n#endif // NETGEN_CORE_RANGES_HPP\n"
  },
  {
    "path": "libsrc/core/register_archive.hpp",
    "content": "#ifndef NETGEN_REGISTER_ARCHIVE_HPP\n#define NETGEN_REGISTER_ARCHIVE_HPP\n\n#ifdef NETGEN_PYTHON\n#include <memory>\n#include <pybind11/pybind11.h>\n#include <pybind11/cast.h>\n#endif // NETGEN_PYTHON\n#include <tuple>\n\n#include \"archive.hpp\"\n\nnamespace ngcore {\n  // ***************  Archiving functionality  **************\n\n#ifdef NETGEN_PYTHON\n  template<typename T>\n  Archive& Archive :: Shallow(T& val)\n  {\n    static_assert(detail::is_any_pointer<T>, \"ShallowArchive must be given pointer type!\");\n    if(shallow_to_python)\n      {\n        if(is_output)\n          ShallowOutPython(pybind11::cast(val));\n        else\n        {\n          pybind11::object obj;\n          ShallowInPython(obj);\n          val = pybind11::cast<T>(obj);\n        }\n      }\n    else\n      *this & val;\n    return *this;\n  }\n\n  /*\n    // now using has_shared_from_this2 in archive.hpp\n  template <typename T>\n  struct has_shared_from_this\n  {\n    template <typename C> static std::true_type check( decltype( sizeof(&C::shared_from_this )) ) { return std::true_type(); }\n    template <typename> static std::false_type check(...) { return std::false_type(); }\n    typedef decltype( check<T>(sizeof(char)) ) type;\n    static constexpr type value = type();\n  };\n  */\n#endif // NETGEN_PYTHON\n\n\n  template<typename T, typename Bases=std::tuple<>>\n  class RegisterClassForArchive\n  {\n  public:\n    RegisterClassForArchive()\n    {\n      static_assert(std::is_base_of<Bases, T>::value ||\n                    detail::is_base_of_tuple<T, Bases>,\n                    \"Second argument must be base class or tuple of base classes of T\");\n      detail::ClassArchiveInfo info {};\n      info.creator = [](const std::type_info& ti, Archive& ar) -> void*\n      {\n        detail::TCargs<T> args;\n        ar &args;\n        auto nT = detail::constructIfPossible<T>(std::move(args));\n        return typeid(T) == ti ? nT\n          : Archive::Caster<T, Bases>::tryUpcast(ti, nT);\n      };\n      info.upcaster = [](const std::type_info& ti, void* p) -> void*\n      { return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryUpcast(ti, static_cast<T*>(p)); };\n      info.downcaster = [](const std::type_info& ti, void* p) -> void*\n      { return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryDowncast(ti, p); };\n      info.cargs_archiver = [](Archive &ar, void* p) {\n        if constexpr(detail::has_GetCArgs_v<T>)\n          ar << static_cast<T*>(p)->GetCArgs();\n      };\n#ifdef NETGEN_PYTHON\n    info.anyToPyCaster = [](const std::any &a) {\n      if constexpr(has_shared_from_this2<T>::value) {\n        std::shared_ptr<T> val = std::any_cast<std::shared_ptr<T>>(a);\n        return pybind11::cast(val);\n      } else {\n        const T* val = std::any_cast<T>(&a);\n        return pybind11::cast(val);\n      }\n    };\n    info.pyToAnyCaster = [](pybind11::object &obj)\n    {\n      if constexpr(has_shared_from_this2<T>::value || !std::is_copy_constructible<T>::value)\n        return std::any { obj.cast<std::shared_ptr<T>>() };\n      else\n        return std::any { obj.cast<T>() };\n    };\n\n#endif // NETGEN_PYTHON\n    Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);\n  }\n};\n} // namespace ngcore\n#endif // NETGEN_REGISTER_ARCHIVE_HPP\n"
  },
  {
    "path": "libsrc/core/signal.hpp",
    "content": "#ifndef NGCORE_SIGNALS_HPP\n#define NGCORE_SIGNALS_HPP\n\n#include <list>\n#include <map>\n#include <functional>\n\nnamespace ngcore\n{\n  template<typename ... ParameterTypes>\n  class Signal\n  {\n  private:\n    std::list<std::function<bool(ParameterTypes...)>> funcs;\n    bool is_emitting;\n  public:\n    Signal() : is_emitting(true) {}\n\n    template<typename Cls, typename FUNC>\n    void Connect(Cls* self, FUNC f)\n    {\n      auto ptr = self->weak_from_this();\n      auto func = [ptr, f](ParameterTypes... args)\n        {\n          if (ptr.expired())\n            return false;\n          f(args...);\n          return true;\n        };\n      funcs.push_back(func);\n    }\n\n    inline void Emit(ParameterTypes ...args)\n    {\n      if(is_emitting)\n        funcs.remove_if([&](auto& f){ return !f(args...); });\n    }\n\n    inline bool SetEmitting(bool emitting)\n    {\n      bool was_emitting = is_emitting;\n      is_emitting = emitting;\n      return was_emitting;\n    }\n    inline bool GetEmitting() const { return is_emitting; }\n  };\n\n\n\n\n  class SimpleSignal\n  {\n  private:\n    // std::map<void*,std::function<void()>> funcs;\n    std::list<std::pair<void*,std::function<void()>>> funcs;\n  public:\n    SimpleSignal() = default;\n\n    template<typename FUNC>\n    void Connect(void* var, FUNC f)\n    {\n      // funcs[var] = f;\n      funcs.push_back ( { var, f } );\n    }\n\n    void Remove(void* var)\n    {\n      // funcs.erase(var);\n      funcs.remove_if([&] (auto var_f) { return var_f.first==var; });\n    }\n\n    inline void Emit()\n    {\n      for (auto [key,f] : funcs)\n        f();\n    }\n  };\n\n  \n} // namespace ngcore\n\n#endif // NGCORE_SIGNALS_HPP\n"
  },
  {
    "path": "libsrc/core/simd.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_HPP\n#define NETGEN_CORE_SIMD_HPP\n\n/**************************************************************************/\n/* File:   simd.hpp                                                       */\n/* Author: Joachim Schoeberl, Matthias Hochsteger                         */\n/* Date:   25. Mar. 16                                                    */\n/**************************************************************************/\n\n#include <array>\n#include <tuple>\n#include \"ngcore_api.hpp\"\n#include \"simd_generic.hpp\"\n\n\n#ifndef __CUDA_ARCH__\n\n#ifdef NETGEN_ARCH_AMD64\n#ifndef __SSE__\n#define __SSE__\n#endif\n#include \"simd_sse.hpp\"\n#endif\n\n#ifdef __AVX__\n#include \"simd_avx.hpp\"\n#endif\n\n#ifdef __AVX512F__\n#include \"simd_avx512.hpp\"\n#endif\n\n#ifdef __aarch64__\n#include \"simd_arm64.hpp\"\n#endif\n\n#endif // __CUDA_ARCH__\n\nnamespace ngcore\n{\n#ifndef __CUDA_ARCH__\n#ifdef NETGEN_ARCH_AMD64\n  /*\n  NETGEN_INLINE auto HSum (SIMD<double,2> v1, SIMD<double,2> v2, SIMD<double,2> v3, SIMD<double,2> v4)\n  {\n    SIMD<double,2> hsum1 = my_mm_hadd_pd (v1.Data(), v2.Data());\n    SIMD<double,2> hsum2 = my_mm_hadd_pd (v3.Data(), v4.Data());\n    return SIMD<double,4> (hsum1, hsum2);\n  }\n  */\n  \n  NETGEN_INLINE auto GetMaskFromBits( unsigned int i )\n  {\n    return SIMD<mask64>::GetMaskFromBits(i);\n  }\n#endif\n#endif // __CUDA_ARCH__\n  \n  NETGEN_INLINE void SIMDTranspose (SIMD<double,4> a1, SIMD<double,4> a2, SIMD <double,4> a3, SIMD<double,4> a4,\n                                    SIMD<double,4> & b1, SIMD<double,4> & b2, SIMD<double,4> & b3, SIMD<double,4> & b4)\n  {\n    if constexpr (sizeof(a1.Lo()) == 16)\n      {\n        auto [h1,h2] = Unpack(a1,a2);\n        auto [h3,h4] = Unpack(a3,a4);\n        b1 = SIMD<double,4> (h1.Lo(), h3.Lo());\n        b2 = SIMD<double,4> (h2.Lo(), h4.Lo());\n        b3 = SIMD<double,4> (h1.Hi(), h3.Hi());\n        b4 = SIMD<double,4> (h2.Hi(), h4.Hi());\n      }\n    else\n      {\n        b1 = SIMD<double,4> (a1[0], a2[0], a3[0], a4[0]);\n        b2 = SIMD<double,4> (a1[1], a2[1], a3[1], a4[1]);\n        b3 = SIMD<double,4> (a1[2], a2[2], a3[2], a4[2]);\n        b4 = SIMD<double,4> (a1[3], a2[3], a3[3], a4[3]);\n      }\n  }\n  \n  template<int N>\n  NETGEN_INLINE auto HSum (SIMD<double,N> s1, SIMD<double,N> s2)\n  {\n    return SIMD<double,2>(HSum(s1), HSum(s2));\n  }\n\n  template<int N>\n  NETGEN_INLINE auto HSum (SIMD<double,N> s1, SIMD<double,N> s2, SIMD<double,N> s3, SIMD<double,N> s4 )\n  {\n    // return SIMD<double,4>(HSum(s1), HSum(s2), HSum(s3), HSum(s4));\n    return SIMD<double,4>(HSum(s1, s2), HSum(s3,s4));\n  }\n\n\n\n  template <typename T, size_t S> class MakeSimdCl;\n  \n  template <typename T, size_t S>\n  auto MakeSimd (std::array<T,S> aa)  { return MakeSimdCl(aa).Get(); }\n\n  \n  template <typename T, size_t S>\n  class MakeSimdCl\n  {\n    std::array<T,S> a;\n  public:\n    MakeSimdCl (std::array<T,S> aa) : a(aa)  { ; }\n    auto Get() const\n    {\n      SIMD<T,S> sa( [this] (auto i) { return (this->a)[i]; });\n      return sa;\n    }\n  };\n  \n\n  \n  \n  template <typename Tfirst, size_t S, typename ...Trest>\n  class MakeSimdCl<std::tuple<Tfirst,Trest...>,S>\n  {\n    std::array<std::tuple<Tfirst,Trest...>,S> a;\n  public:\n    MakeSimdCl (std::array<std::tuple<Tfirst,Trest...>,S> aa) : a(aa)  { ; }\n    auto Get() const\n    {\n      std::array<Tfirst,S> a0;\n      for (int i = 0; i < S; i++)\n        a0[i] = std::get<0> (a[i]);\n      \n      if constexpr (std::tuple_size<std::tuple<Tfirst,Trest...>>::value == 1)\n        {\n          return std::tuple(MakeSimd(a0));\n        }\n      else\n        {\n          std::array<std::tuple<Trest...>,S> arest;\n          for (int i = 0; i < S; i++)\n            arest[i] = skip_first(a[i]);\n          \n          return std::tuple_cat ( std::tuple (MakeSimd(a0)), MakeSimd(arest) );\n        }\n    }\n\n    template <typename... Ts>\n    static auto skip_first(const std::tuple<Ts...>& t) {\n      return std::apply([](auto first, auto... rest) {\n        return std::make_tuple(rest...);\n      }, t);\n    }\n  };\n  \n\n  \n\n  \n}\n\n\n#include \"simd_math.hpp\"\n\n#endif // NETGEN_CORE_SIMD_HPP\n"
  },
  {
    "path": "libsrc/core/simd_arm64.hpp",
    "content": "#include \"arm_neon.h\"\n\nnamespace ngcore\n{\n\n  template <>\n  class SIMD<mask64,2>\n  {\n    int64x2_t mask;\n  public:\n    SIMD (int i)\n    {\n      mask[0] = i > 0 ? -1 : 0;\n      mask[1] = i > 1 ? -1 : 0;\n    }\n\n    SIMD (bool i0, bool i1) { mask[0] = i0 ? -1 : 0; mask[1] = i1 ? -1 : 0; }\n    SIMD (SIMD<mask64,1> i0, SIMD<mask64,1> i1) { mask[0] = i0[0]; mask[1] = i1[0]; }\n    // SIMD (float64x2_t _data) : mask{_data} { }\n    SIMD (int64x2_t _data) : mask{_data} { }\n    auto Data() const { return mask; }\n    static constexpr int Size() { return 2; }\n    // static NETGEN_INLINE SIMD<mask64, 2> GetMaskFromBits (unsigned int i);\n    int64_t operator[] (int i) const { return mask[i]; }\n\n    template <int I>\n    int64_t Get() const { return mask[I]; }\n    \n    auto Lo() const { return mask[0]; }\n    auto Hi() const { return mask[1]; }\n  };\n\n\n  // *************************** int32 ***************************\n\n\n  \n  template<>\n  class SIMD<int32_t,2>\n  {\n    int32x2_t data;\n  public:\n    static constexpr int Size() { return 2; }\n    SIMD() {}\n    SIMD (int32_t val) : data{val,val} {}\n    SIMD (int32_t v0, int32_t v1) : data{v0,v1} { }\n    SIMD (SIMD<int32_t,1> lo, SIMD<int32_t,1> hi) : data{lo[0], hi[0] } { }     \n    SIMD (std::array<int32_t, 2> arr) : data{arr[0], arr[1]} { } \n    \n    SIMD (int32x2_t _data) { data = _data; }\n\n    NETGEN_INLINE auto Data() const { return data; }\n    NETGEN_INLINE auto & Data() { return data; }\n\n    SIMD<int32_t,1> Lo() const { return Get<0>(); }\n    SIMD<int32_t,1> Hi() const { return Get<1>(); } \n    \n    int32_t operator[] (int i) const { return data[i]; }\n    int32_t & operator[] (int i)  { return ((int32_t*)&data)[i]; }\n\n    template <int I>\n    int32_t Get() const { return data[I]; }\n    static SIMD FirstInt(int n0=0) { return { n0+0, n0+1 }; }\n  };\n\n\n  template<>\n  class SIMD<int32_t,4>\n  {\n    int32x4_t data;\n  public:\n    static constexpr int Size() { return 4; }\n    SIMD() {}\n    SIMD (int32_t val) : data{val,val,val,val} {}\n    SIMD (int32_t v0, int32_t v1, int32_t v2, int32_t v3) : data{v0,v1,v2,v3} { }\n    SIMD (std::array<int32_t, 4> arr) : data{arr[0], arr[1], arr[2], arr[3]} { } \n    \n    SIMD (int32x4_t _data) { data = _data; }\n    SIMD (SIMD<int32_t,2> lo, SIMD<int32_t,2> hi) : data{vcombine_s32(lo.Data(), hi.Data())} {}\n    SIMD (int32_t * p) : data{vld1q_s32(p)} { }\n\n    NETGEN_INLINE auto Data() const { return data; }\n    NETGEN_INLINE auto & Data() { return data; }\n\n    SIMD<int32_t,2> Lo() const { return vget_low_s32(data); }\n    SIMD<int32_t,2> Hi() const { return vget_high_s32(data); }\n    \n    int32_t operator[] (int i) const { return data[i]; }\n    int32_t & operator[] (int i)  { return ((int32_t*)&data)[i]; }\n\n    void Store (int32_t * p) { vst1q_s32(p, data); }\n          \n    template <int I>\n    int32_t Get() const { return data[I]; }\n    static SIMD FirstInt(int n0=0) { return { n0+0, n0+1, n0+2, n0+3 }; }\n  };\n  \n\n  \n  NETGEN_INLINE auto Min (SIMD<int32_t,2> a, SIMD<int32_t,2> b) {\n    return SIMD<int32_t,2>(vmin_s32(a.Data(), b.Data()));\n  }\n  \n  NETGEN_INLINE auto Max (SIMD<int32_t,2> a, SIMD<int32_t,2> b) {\n    return SIMD<int32_t,2>(vmax_s32(a.Data(), b.Data()));\n  }\n\n  \n  NETGEN_INLINE auto Min (SIMD<int32_t,4> a, SIMD<int32_t,4> b) {\n    return SIMD<int32_t,4>(vminq_s32(a.Data(), b.Data()));\n  }\n  \n  NETGEN_INLINE auto Max (SIMD<int32_t,4> a, SIMD<int32_t,4> b) {\n    return SIMD<int32_t,4>(vmaxq_s32(a.Data(), b.Data()));\n  }\n\n\n  \n\n  // *************************** int64 ***************************  \n \n  template<>\n  class SIMD<int64_t,2>\n  {\n    int64x2_t data;\n  public:\n    static constexpr int Size() { return 2; }\n    SIMD() {}\n    SIMD (int64_t val) : data{val,val} {}\n    SIMD (int64_t v0, int64_t v1) : data{vcombine_s64(int64x1_t{v0}, int64x1_t{v1})} { }\n    SIMD (std::array<int64_t, 2> arr) : data{arr[0], arr[1]} { } \n    \n    SIMD (int64x2_t _data) { data = _data; }\n\n    NETGEN_INLINE auto Data() const { return data; }\n    NETGEN_INLINE auto & Data() { return data; }\n\n    int64_t Lo() const { return Get<0>(); } \n    int64_t Hi() const { return Get<1>(); } \n    \n    int64_t operator[] (int i) const { return data[i]; }\n    int64_t & operator[] (int i)  { return ((int64_t*)&data)[i]; }\n\n    template <int I>\n    int64_t Get() const { return data[I]; }\n    static SIMD FirstInt(int n0=0) { return { n0+0, n0+1 }; }\n  };\n\n  NETGEN_INLINE SIMD<int64_t,2> operator& (SIMD<int64_t,2> a, SIMD<int64_t,2> b)\n  {\n    return vandq_s64(a.Data(), b.Data());\n  }\n\n  NETGEN_INLINE SIMD<int64_t,2> operator+ (SIMD<int64_t,2> a, SIMD<int64_t,2> b)\n  {\n    return vaddq_s64(a.Data(), b.Data());\n  }\n\n  NETGEN_INLINE SIMD<mask64,2> operator== (SIMD<int64_t> a, SIMD<int64_t> b)\n  {\n    return vceqq_u64(a.Data(), b.Data());\n  }\n  \n  NETGEN_INLINE SIMD<mask64,2> operator> (SIMD<int64_t> a, SIMD<int64_t> b)\n  {\n    return vcgtq_s64(a.Data(), b.Data());\n  }\n\n  \n  template <int N>\n  SIMD<int64_t,2> operator<< (SIMD<int64_t,2> a, IC<N> n)\n  {\n    return vshlq_n_s64(a.Data(), N);\n  }\n  \n  \n  \n  // *************************** double ***************************\n  \n  template<>\n  class SIMD<double,2>\n  {\n    float64x2_t data;\n\n  public:\n    static constexpr int Size() { return 2; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    // SIMD (double v0, double v1) : data{v0,v1} { }\n    SIMD (double v0, double v1) : data{vcombine_f64(float64x1_t{v0}, float64x1_t{v1})} { }\n    SIMD (SIMD<double,1> v0, SIMD<double,1> v1) : data{vcombine_f64(float64x1_t{v0.Data()}, float64x1_t{v1.Data()})} { }\n    SIMD (std::array<double, 2> arr) : data{arr[0], arr[1]} { } \n\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (double val) : data{val,val} { }\n    SIMD (int val)    : data{double(val),double(val)} { }\n    SIMD (size_t val) : data{double(val),double(val)} { }\n\n    SIMD (double const * p)\n    {\n      data = vld1q_f64(p);      \n      // data[0] = p[0];\n      // data[1] = p[1];\n    }\n    \n    SIMD (double const * p, SIMD<mask64,2> mask)\n      {\n\tdata[0] = mask[0] ? p[0] : 0;\n\tdata[1] = mask[1] ? p[1] : 0;\n      }\n    SIMD (float64x2_t _data) { data = _data; }\n    \n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<double(int)>>::value, int>::type = 0>\n    SIMD (const T & func)\n    {\n      data[0] = func(0);\n      data[1] = func(1);\n    }\n\n    void Store (double * p)\n    {\n      vst1q_f64(p, data);\n      /*\n      p[0] = data[0];\n      p[1] = data[1];\n      */\n    }\n    \n    void Store (double * p, SIMD<mask64,2> mask)\n    {\n      if (mask[0]) p[0] = data[0];\n      if (mask[1]) p[1] = data[1];\n    }\n    \n    // NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }\n    NETGEN_INLINE double operator[] (int i) const { return data[i]; }\n    NETGEN_INLINE double & operator[] (int i)  { return ((double*)&data)[i]; }\n\n    template <int I>\n    double Get() const { return data[I]; }\n    \n    NETGEN_INLINE auto Data() const { return data; }\n    NETGEN_INLINE auto & Data() { return data; }\n\n    operator std::tuple<double&,double&> ()\n    {\n      auto pdata = (double*)&data;\n      return std::tuple<double&,double&>(pdata[0], pdata[1]);\n    }\n    \n    double Lo() const { return Get<0>(); } // data[0]; }\n    double Hi() const { return Get<1>(); } // data[1]; }\n    // double Hi() const { return vget_high_f64(data)[0]; }\n  };\n\n\n\n  NETGEN_INLINE double HSum (SIMD<double,2> sd)\n  {\n    return sd.Lo()+sd.Hi();  // sd[0]+sd[1];\n  }\n\n  NETGEN_INLINE SIMD<double,2> HSum (SIMD<double,2> a, SIMD<double,2> b)\n  {\n    // return SIMD<double,2> (a[0]+a[1], b[0]+b[1]);\n    return vpaddq_f64(a.Data(), b.Data());\n  }\n\n  NETGEN_INLINE SIMD<double,4> HSum(SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c, SIMD<double,2> d)\n  {\n    return SIMD<double,4> (HSum(a,b), HSum(c,d));\n  }\n\n\n  NETGEN_INLINE SIMD<double,2>  SwapPairs (SIMD<double,2> a)\n  {\n    return __builtin_shufflevector(a.Data(), a.Data(), 1, 0);\n  }\n  \n\n\n  // a*b+c\n  NETGEN_INLINE SIMD<double,2> FMA (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    return vmlaq_f64(c.Data(), a.Data(), b.Data());\n  }\n  NETGEN_INLINE SIMD<double,2> FMA (const double & a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    return FMA(SIMD<double,2> (a), b, c);\n  }\n  // -a*b+c\n  NETGEN_INLINE SIMD<double,2> FNMA (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    return vmlsq_f64(c.Data(), a.Data(), b.Data());    \n    // return c-a*b;\n  }\n  NETGEN_INLINE SIMD<double,2> FNMA (const double & a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    return FNMA(SIMD<double,2> (a), b, c);\n  }\n\n  // ARM complex mult:\n  // https://arxiv.org/pdf/1901.07294.pdf\n  // c += a*b    (a0re, a0im, a1re, a1im, ...), \n  NETGEN_INLINE void FMAComplex (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> & c)\n  {\n    auto tmp = vcmlaq_f64(c.Data(), a.Data(), b.Data());   // are * b\n    c = vcmlaq_rot90_f64(tmp, a.Data(), b.Data());    // += i*aim * b\n  }\n\n  NETGEN_INLINE void FMAComplex (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> & c)\n  {\n    SIMD<double,2> clo = c.Lo();\n    SIMD<double,2> chi = c.Hi();\n    FMAComplex (a.Lo(), b.Lo(), clo);\n    FMAComplex (a.Hi(), b.Hi(), chi);\n    c = SIMD<double,4> (clo, chi);\n  }\n\n  \n\n  NETGEN_INLINE SIMD<double,2> operator+ (SIMD<double,2> a, SIMD<double,2> b)\n  { return a.Data()+b.Data(); }\n  \n  NETGEN_INLINE SIMD<double,2> operator- (SIMD<double,2> a, SIMD<double,2> b)\n  { return a.Data()-b.Data(); }\n  NETGEN_INLINE SIMD<double,2> operator- (SIMD<double,2> a)\n  { return -a.Data(); }\n  \n  NETGEN_INLINE SIMD<double,2> operator* (SIMD<double,2> a, SIMD<double,2> b)\n  { return a.Data()*b.Data(); }\n  \n  NETGEN_INLINE SIMD<double,2> operator/ (SIMD<double,2> a, SIMD<double,2> b)\n  { return a.Data()/b.Data(); }\n\n  NETGEN_INLINE SIMD<double,2> sqrt (SIMD<double,2> x)\n  { return vsqrtq_f64(x.Data()); }\n\n  \n  NETGEN_INLINE SIMD<double,2> round (SIMD<double,2> x)\n  {\n    return vrndnq_f64(x.Data());\n  }\n  \n  NETGEN_INLINE SIMD<int64_t,2> lround (SIMD<double,2> x)\n  {\n    return vcvtq_s64_f64(x.Data());\n  }\n\n\n\n  NETGEN_INLINE SIMD<double,2> rsqrt (SIMD<double,2> x)\n  {\n    return 1.0 / sqrt(x);\n  \n    // SIMD<double,2> y = vrsqrteq_f64(x.Data());\n\n    /*\n    y = y * vrsqrtsq_f64( (x*y).Data(), y.Data());\n    y = y * vrsqrtsq_f64( (x*y).Data(), y.Data());\n    y = y * vrsqrtsq_f64( (x*y).Data(), y.Data());\n    */\n\n    /*\n    auto x_half = 0.5*x;\n    y = y * (1.5 - (x_half * y * y));\n    y = y * (1.5 - (x_half * y * y));\n    y = y * (1.5 - (x_half * y * y));\n    \n    return y;\n    */\n  }\n  \n  \n  \n\n  template <>\n  NETGEN_INLINE SIMD<double,2> Reinterpret (SIMD<int64_t,2> a)\n  {\n    return vreinterpretq_f64_s64(a.Data());\n  }\n\n  \n  NETGEN_INLINE SIMD<double,2> If (SIMD<mask64,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    // return { a[0] ? b[0] : c[0], a[1] ? b[1] : c[1] };\n    uint64x2_t mask = vreinterpretq_u64_s64(a.Data());\n    return vbslq_f64(mask, b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<int64_t,2> If (SIMD<mask64,2> a, SIMD<int64_t,2> b, SIMD<int64_t,2> c)\n  {\n    // return SIMD<int64_t,2> (a[0] ? b[0] : c[0], a[1] ? b[1] : c[1]);\n    uint64x2_t mask = vreinterpretq_u64_s64(a.Data());\n    return vbslq_s64(mask, b.Data(), c.Data());\n  }\n\n  NETGEN_INLINE SIMD<mask64,2> operator&& (SIMD<mask64,2> a, SIMD<mask64,2> b)\n  {\n    uint64x2_t m1 = vreinterpretq_u64_s64(a.Data());\n    uint64x2_t m2 = vreinterpretq_u64_s64(b.Data());\n    uint64x2_t res = vandq_u64 (m1, m2);\n    return vreinterpretq_s64_u64(res);\n  }\n  \n}\n\n"
  },
  {
    "path": "libsrc/core/simd_avx.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_AVX_HPP\n#define NETGEN_CORE_SIMD_AVX_HPP\n\n/**************************************************************************/\n/* File:   simd_avx.hpp                                                   */\n/* Author: Joachim Schoeberl, Matthias Hochsteger                         */\n/* Date:   25. Mar. 16                                                    */\n/**************************************************************************/\n\n#include <immintrin.h>\n\nnamespace ngcore\n{\n\n#if defined(__GNUC__) && (__GNUC__ == 7)\n  // GCC7 does not have intrinsic _mm256_set_m128i, see\n  // https://stackoverflow.com/questions/32630458/setting-m256i-to-the-value-of-two-m128i-values\n  NETGEN_INLINE auto _mm256_set_m128i(__m128i v0, __m128i v1) {\n      return _mm256_insertf128_si256(_mm256_castsi128_si256(v1), (v0), 1);\n  }\n#endif // defined(__GNUC__) && (__GNUC__ == 7)\n\n#if defined(__AVX2__)\n  NETGEN_INLINE __m256i my_mm256_cmpeq_epi64 (__m256i a, __m256i b)\n  {\n    return _mm256_cmpeq_epi64 (a,b);\n  }\n\n  NETGEN_INLINE __m256i my_mm256_cmpgt_epi64 (__m256i a, __m256i b)\n  {\n    return _mm256_cmpgt_epi64 (a,b);\n  }\n\n  NETGEN_INLINE __m256i my_mm256_cvtepi32_epi64 (__m128i a)\n  {\n    return _mm256_cvtepi32_epi64 (a);\n  }\n  \n#else\n  NETGEN_INLINE __m256i my_mm256_cmpeq_epi64 (__m256i a, __m256i b)\n  {\n    __m128i rlo = _mm_cmpeq_epi64(_mm256_extractf128_si256(a, 0),\n                                  _mm256_extractf128_si256(b, 0));\n    __m128i rhi = _mm_cmpeq_epi64(_mm256_extractf128_si256(a, 1),\n                                  _mm256_extractf128_si256(b, 1));\n    return _mm256_insertf128_si256 (_mm256_castsi128_si256(rlo), rhi, 1);\n  }\n\n  NETGEN_INLINE __m256i my_mm256_cmpgt_epi64 (__m256i a, __m256i b)\n  {\n    __m128i rlo = _mm_cmpgt_epi64(_mm256_extractf128_si256(a, 0),\n                                  _mm256_extractf128_si256(b, 0));\n    __m128i rhi = _mm_cmpgt_epi64(_mm256_extractf128_si256(a, 1),\n                                  _mm256_extractf128_si256(b, 1));\n    return _mm256_insertf128_si256 (_mm256_castsi128_si256(rlo), rhi, 1);\n  }\n\n  NETGEN_INLINE __m256i my_mm256_cvtepi32_epi64 (__m128i a)\n  {\n    __m128i rlo = _mm_cvtepi32_epi64(a);   // First two 32-bit integers\n    __m128i rhi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(a, _MM_SHUFFLE(3, 2, 3, 2))); // Next two 32-bit integers\n    return _mm256_insertf128_si256 (_mm256_castsi128_si256(rlo), rhi, 1);\n  }\n#endif\n\n\n  template <>\n  class SIMD<mask64,4>\n  {\n    __m256i mask;\n  public:\n    SIMD (int64_t i)\n      : mask(my_mm256_cmpgt_epi64(_mm256_set1_epi64x(i),\n                                  _mm256_set_epi64x(3, 2, 1, 0)))\n    { ; }\n    SIMD (__m256i _mask) : mask(_mask) { ; }\n    SIMD (__m256d _mask) : mask(_mm256_castpd_si256(_mask)) { ; }\n    __m256i Data() const { return mask; }\n    static constexpr int Size() { return 4; }\n    static SIMD<mask64, 4> GetMaskFromBits (unsigned int i);\n  };\n\n  static SIMD<mask64, 4> masks_from_4bits[16] = {\n    _mm256_set_epi64x (0,0,0,0), _mm256_set_epi64x (0,0,0,-1),\n    _mm256_set_epi64x (0,0,-1,0), _mm256_set_epi64x (0,0,-1,-1),\n    _mm256_set_epi64x (0,-1,0,0), _mm256_set_epi64x (0,-1,0,-1),\n    _mm256_set_epi64x (0,-1,-1,0), _mm256_set_epi64x (0,-1,-1,-1),\n    _mm256_set_epi64x (-1,0,0,0), _mm256_set_epi64x (-1,0,0,-1),\n    _mm256_set_epi64x (-1,0,-1,0), _mm256_set_epi64x (-1,0,-1,-1),\n    _mm256_set_epi64x (-1,-1,0,0), _mm256_set_epi64x (-1,-1,0,-1),\n    _mm256_set_epi64x (-1,-1,-1,0), _mm256_set_epi64x (-1,-1,-1,-1)\n  };\n\n  NETGEN_INLINE SIMD<mask64, 4> SIMD<mask64, 4> :: GetMaskFromBits (unsigned int i)\n  {\n    return masks_from_4bits[i & 15];\n  }\n\n  template<>\n  class alignas(32) SIMD<int64_t,4>\n  {\n    __m256i data;\n\n  public:\n    static constexpr int Size() { return 4; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (int64_t val) { data = _mm256_set1_epi64x(val); }\n    SIMD (int64_t v0, int64_t v1, int64_t v2, int64_t v3) { data = _mm256_set_epi64x(v3,v2,v1,v0); }\n    SIMD (std::array<int64_t,4> a)\n      : data{_mm256_set_epi64x(a[3],a[2],a[1],a[0])}\n    {}\n    SIMD (SIMD<int64_t,2> v0, SIMD<int64_t,2> v1)\n        : data(_mm256_set_m128i(v1.Data(),v0.Data()))\n      {}\n    SIMD (__m256i _data) { data = _data; }\n\n    NETGEN_INLINE auto operator[] (int i) const { return ((int64_t*)(&data))[i]; }\n    NETGEN_INLINE __m256i Data() const { return data; }\n    NETGEN_INLINE __m256i & Data() { return data; }\n\n    SIMD<int64_t,2> Lo() const { return _mm256_extractf128_si256(data, 0); }\n    SIMD<int64_t,2> Hi() const { return _mm256_extractf128_si256(data, 1); }\n    static SIMD FirstInt(int n0=0) { return { n0+0, n0+1, n0+2, n0+3 }; }\n\n    template <int I>\n    double Get() const\n    {\n      static_assert(I>=0 && I<4, \"Index out of range\");\n      return (*this)[I];\n    }\n  };\n\n\n  NETGEN_INLINE SIMD<int64_t,4> operator-(SIMD<int64_t,4> a) { return _mm256_sub_epi64(_mm256_setzero_si256(), a.Data()); }\n\n#ifdef __AVX2__\n  NETGEN_INLINE SIMD<int64_t,4> operator+ (SIMD<int64_t,4> a, SIMD<int64_t,4> b) { return _mm256_add_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<int64_t,4> operator- (SIMD<int64_t,4> a, SIMD<int64_t,4> b) { return _mm256_sub_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<int64_t,4> operator& (SIMD<int64_t,4> a, SIMD<int64_t,4> b)\n  { return _mm256_castpd_si256(_mm256_and_pd (_mm256_castsi256_pd(a.Data()),_mm256_castsi256_pd( b.Data()))); }\n\n  template <int N>\n  SIMD<int64_t,4> operator<< (SIMD<int64_t,4> a, IC<N> n) { return _mm256_sll_epi64(a.Data(),_mm_set_epi32(0,0,0,N)); }\n#endif // __AVX2__\n\n  template<>\n  class alignas(32) SIMD<double,4>\n  {\n    __m256d data;\n\n  public:\n    static constexpr int Size() { return 4; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (double val) { data = _mm256_set1_pd(val); }\n    SIMD (int val)    { data = _mm256_set1_pd(val); }\n    SIMD (size_t val) { data = _mm256_set1_pd(val); }\n    SIMD (double v0, double v1, double v2, double v3) { data = _mm256_set_pd(v3,v2,v1,v0); }\n    SIMD (SIMD<double,2> v0, SIMD<double,2> v1) : SIMD(v0[0], v0[1], v1[0], v1[1]) { ; }\n    SIMD (double const * p) { data = _mm256_loadu_pd(p); }\n    SIMD (double const * p, SIMD<mask64,4> mask) { data = _mm256_maskload_pd(p, mask.Data()); }\n    SIMD (__m256d _data) { data = _data; }\n    SIMD (std::array<double,4> a)\n      : data{_mm256_set_pd(a[3],a[2],a[1],a[0])}\n    {}\n\n    void Store (double * p) { _mm256_storeu_pd(p, data); }\n    void Store (double * p, SIMD<mask64,4> mask) { _mm256_maskstore_pd(p, mask.Data(), data); }\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<double(int)>>::value, int>::type = 0>\n    SIMD (const T & func)\n    {\n      data = _mm256_set_pd(func(3), func(2), func(1), func(0));\n    }\n\n    NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }\n    NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }\n    // [[deprecated(\"don't write to individual elements of SIMD\")]]\n    // NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }\n    NETGEN_INLINE __m256d Data() const { return data; }\n    NETGEN_INLINE __m256d & Data() { return data; }\n\n    SIMD<double,2> Lo() const { return _mm256_extractf128_pd(data, 0); }\n    SIMD<double,2> Hi() const { return _mm256_extractf128_pd(data, 1); }\n\n    operator std::tuple<double&,double&,double&,double&> ()\n    { return std::tuple<double&,double&,double&,double&>((*this)[0], (*this)[1], (*this)[2], (*this)[3]); }\n\n    template <int I>\n    double Get() const\n    {\n      static_assert(I>=0 && I<4, \"Index out of range\");\n      return (*this)[I];\n    }\n  };\n\n  NETGEN_INLINE auto Unpack (SIMD<double,4> a, SIMD<double,4> b)\n  {\n    return std::make_tuple(SIMD<double,4>(_mm256_unpacklo_pd(a.Data(),b.Data())),\n                      SIMD<double,4>(_mm256_unpackhi_pd(a.Data(),b.Data())));\n  }\n\n  NETGEN_INLINE SIMD<double,4> operator- (SIMD<double,4> a) { return _mm256_xor_pd(a.Data(), _mm256_set1_pd(-0.0)); }\n  NETGEN_INLINE SIMD<double,4> operator+ (SIMD<double,4> a, SIMD<double,4> b) { return _mm256_add_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,4> operator- (SIMD<double,4> a, SIMD<double,4> b) { return _mm256_sub_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,4> operator* (SIMD<double,4> a, SIMD<double,4> b) { return _mm256_mul_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,4> operator/ (SIMD<double,4> a, SIMD<double,4> b) { return _mm256_div_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,4> operator* (double a, SIMD<double,4> b) { return _mm256_set1_pd(a)*b.Data(); }\n  NETGEN_INLINE SIMD<double,4> operator* (SIMD<double,4> b, double a) { return _mm256_set1_pd(a)*b.Data(); }\n\n  NETGEN_INLINE SIMD<double,4> sqrt (SIMD<double,4> a) { return _mm256_sqrt_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,4> floor (SIMD<double,4> a) { return _mm256_floor_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,4> ceil (SIMD<double,4> a) { return _mm256_ceil_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,4> fabs (SIMD<double,4> a) { return _mm256_max_pd(a.Data(), (-a).Data()); }\n  NETGEN_INLINE SIMD<double,4> round(SIMD<double,4> a) { return _mm256_round_pd(a.Data(), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); }\n  NETGEN_INLINE SIMD<int64_t,4> lround (SIMD<double,4> a)\n  {\n    return my_mm256_cvtepi32_epi64(_mm256_cvtpd_epi32(_mm256_round_pd(a.Data(), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)));\n  }\n\n#ifdef __FMA__\n  NETGEN_INLINE SIMD<double,4> FMA (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    return _mm256_fmadd_pd (a.Data(), b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<double,4> FMA (const double & a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    return _mm256_fmadd_pd (_mm256_set1_pd(a), b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<double,4> FNMA (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    return _mm256_fnmadd_pd (a.Data(), b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<double,4> FNMA (const double & a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    return _mm256_fnmadd_pd (_mm256_set1_pd(a), b.Data(), c.Data());\n  }\n#endif\n\n#if defined(__FMA__) && !defined(__AVX512F__)\n  // make sure to use the update-version of fma\n  // important in matrix kernels using 12 sum-registers, 3 a-values and updated b-value\n  // avx512 has enough registers, and gcc seems to use only the first 16 z-regs\n  NETGEN_INLINE void FMAasm (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> & sum)\n  {\n    asm (\"vfmadd231pd %[a], %[b], %[sum]\"\n         : [sum] \"+x\" (sum.Data())\n         : [a] \"x\" (a.Data()), [b] \"x\" (b.Data())\n         );\n  }\n\n  NETGEN_INLINE void FNMAasm (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> & sum)\n  {\n    asm (\"vfnmadd231pd %[a], %[b], %[sum]\"\n         : [sum] \"+x\" (sum.Data())\n         : [a] \"x\" (a.Data()), [b] \"x\" (b.Data())\n         );\n  }\n#endif\n\n#if defined(__FMA__) \n  NETGEN_INLINE SIMD<double,4> FMAddSub (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    return _mm256_fmaddsub_pd(a.Data(), b.Data(), c.Data());\n  }\n#endif  \n  \n  NETGEN_INLINE SIMD<double,4> SwapPairs (SIMD<double,4> a)\n  {\n    return _mm256_shuffle_pd (a.Data(), a.Data(), 0b0101);\n  }\n\n  \n  NETGEN_INLINE SIMD<mask64,4> operator<= (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_LE_OQ); }\n  NETGEN_INLINE SIMD<mask64,4> operator< (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_LT_OQ); }\n  NETGEN_INLINE SIMD<mask64,4> operator>= (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_GE_OQ); }\n  NETGEN_INLINE SIMD<mask64,4> operator> (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_GT_OQ); }\n  NETGEN_INLINE SIMD<mask64,4> operator== (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_EQ_OQ); }\n  NETGEN_INLINE SIMD<mask64,4> operator!= (SIMD<double,4> a , SIMD<double,4> b)\n  { return _mm256_cmp_pd (a.Data(), b.Data(), _CMP_NEQ_OQ); }\n\n  NETGEN_INLINE SIMD<mask64,4> operator<= (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  _mm256_xor_si256(_mm256_cmpgt_epi64(a.Data(),b.Data()),_mm256_set1_epi32(-1)); }\n  NETGEN_INLINE SIMD<mask64,4> operator< (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  my_mm256_cmpgt_epi64(b.Data(),a.Data()); }\n  NETGEN_INLINE SIMD<mask64,4> operator>= (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  _mm256_xor_si256(_mm256_cmpgt_epi64(b.Data(),a.Data()),_mm256_set1_epi32(-1)); }\n  NETGEN_INLINE SIMD<mask64,4> operator> (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  my_mm256_cmpgt_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<mask64,4> operator== (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  my_mm256_cmpeq_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<mask64,4> operator!= (SIMD<int64_t,4> a , SIMD<int64_t,4> b)\n  { return  _mm256_xor_si256(my_mm256_cmpeq_epi64(a.Data(),b.Data()),_mm256_set1_epi32(-1)); }\n\n#ifdef __AVX2__\n  NETGEN_INLINE SIMD<mask64,4> operator&& (SIMD<mask64,4> a, SIMD<mask64,4> b)\n  { return _mm256_and_si256 (a.Data(), b.Data()); }\n  NETGEN_INLINE SIMD<mask64,4> operator|| (SIMD<mask64,4> a, SIMD<mask64,4> b)\n  { return _mm256_or_si256 (a.Data(), b.Data()); }\n  NETGEN_INLINE SIMD<mask64,4> operator! (SIMD<mask64,4> a)\n  { return _mm256_xor_si256 (a.Data(), _mm256_cmpeq_epi64(a.Data(),a.Data())); }\n#else //AVX2 is a superset of AVX. Without it, it is necessary to reinterpret the types\n  NETGEN_INLINE SIMD<mask64,4> operator&& (SIMD<mask64,4> a, SIMD<mask64,4> b)\n  { return _mm256_castpd_si256(_mm256_and_pd (_mm256_castsi256_pd(a.Data()),_mm256_castsi256_pd( b.Data()))); }\n  NETGEN_INLINE SIMD<mask64,4> operator|| (SIMD<mask64,4> a, SIMD<mask64,4> b)\n  { return _mm256_castpd_si256(_mm256_or_pd (_mm256_castsi256_pd(a.Data()), _mm256_castsi256_pd(b.Data()))); }\n  NETGEN_INLINE SIMD<mask64,4> operator! (SIMD<mask64,4> a)\n  { return _mm256_castpd_si256(_mm256_xor_pd (_mm256_castsi256_pd(a.Data()),_mm256_castsi256_pd( _mm256_cmpeq_epi64(a.Data(),a.Data())))); }\n#endif\n\n  template <>\n  NETGEN_INLINE SIMD<double,4> Reinterpret (SIMD<int64_t,4> a)\n  {\n    return _mm256_castsi256_pd (a.Data());\n  }\n\n\n  \n  NETGEN_INLINE SIMD<double,4> If (SIMD<mask64,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  { return _mm256_blendv_pd(c.Data(), b.Data(), _mm256_castsi256_pd(a.Data())); }\n\n  NETGEN_INLINE SIMD<double,4> IfPos (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    auto cp = _mm256_cmp_pd (a.Data(), _mm256_setzero_pd(), _CMP_GT_OS);\n    return _mm256_blendv_pd(c.Data(), b.Data(), cp);\n  }\n\n  NETGEN_INLINE SIMD<double,4> IfZero (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)\n  {\n    auto cp = _mm256_cmp_pd (a.Data(), _mm256_setzero_pd(), _CMP_EQ_OS);\n    return _mm256_blendv_pd(c.Data(), b.Data(), cp);\n  }\n\n  NETGEN_INLINE double HSum (SIMD<double,4> sd)\n  {\n    // __m128d hv = _mm_add_pd (_mm256_extractf128_pd(sd.Data(),0), _mm256_extractf128_pd(sd.Data(),1));\n    __m128d hv = (sd.Lo()+sd.Hi()).Data();\n    return _mm_cvtsd_f64 (_mm_hadd_pd (hv, hv));\n  }\n\n  NETGEN_INLINE auto HSum (SIMD<double,4> sd1, SIMD<double,4> sd2)\n  {\n    __m256d hv = _mm256_hadd_pd(sd1.Data(), sd2.Data());\n    __m128d hv2 = _mm_add_pd (_mm256_extractf128_pd(hv,0), _mm256_extractf128_pd(hv,1));\n    return SIMD<double,2>(_mm_cvtsd_f64 (hv2),  _mm_cvtsd_f64(_mm_shuffle_pd (hv2, hv2, 3)));\n  }\n\n  NETGEN_INLINE auto HSum (SIMD<double,4> v1, SIMD<double,4> v2, SIMD<double,4> v3, SIMD<double,4> v4)\n  {\n    __m256d hsum1 = _mm256_hadd_pd (v1.Data(), v2.Data());\n    __m256d hsum2 = _mm256_hadd_pd (v3.Data(), v4.Data());\n    SIMD<double,4> hsum = _mm256_add_pd (_mm256_permute2f128_pd (hsum1, hsum2, 1+2*16),\n                                         _mm256_blend_pd (hsum1, hsum2, 12));\n    return hsum;\n    // return make_tuple(hsum[0], hsum[1], hsum[2], hsum[3]);\n  }\n\n\n  /*\n    // untested ...\n    NETGEN_INLINE SIMD<double,4> rsqrt (SIMD<double,4> x)\n  {\n    // return 1.0 / sqrt(x);\n    // SIMD<double,4> y = _mm256_rsqrt14_pd(x.Data());  // only avx512\n    SIMD<double,4> y = _mm256_cvtps_pd ( _mm_rsqrt_ps ( _mm256_cvtpd_ps (x.Data())));\n    auto x_half = 0.5*x;\n    y = y * (1.5 - (x_half * y * y));\n    y = y * (1.5 - (x_half * y * y));\n    return y;\n  }\n  */\n  \n    \n\n  NETGEN_INLINE SIMD<int64_t,4> If (SIMD<mask64,4> a, SIMD<int64_t,4> b, SIMD<int64_t,4> c)\n  { return _mm256_castpd_si256(_mm256_blendv_pd(_mm256_castsi256_pd(c.Data()), _mm256_castsi256_pd(b.Data()),\n                                                _mm256_castsi256_pd(a.Data()))); }\n\n\n\n}\n\n#endif // NETGEN_CORE_SIMD_AVX_HPP\n\n"
  },
  {
    "path": "libsrc/core/simd_avx512.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_AVX512_HPP\n#define NETGEN_CORE_SIMD_AVX512_HPP\n\n/**************************************************************************/\n/* File:   simd_avx512.hpp                                                */\n/* Author: Joachim Schoeberl, Matthias Hochsteger                         */\n/* Date:   25. Mar. 16                                                    */\n/**************************************************************************/\n\n#include <immintrin.h>\n\nnamespace ngcore\n{\n\n  template <>\n  class SIMD<mask64,8>\n  {\n    __mmask8 mask;\n  public:\n    SIMD (size_t i)\n      : mask(_mm512_cmpgt_epi64_mask(_mm512_set1_epi64(i),\n                                     _mm512_set_epi64(7, 6, 5, 4, 3, 2, 1, 0)))\n    { ; }\n    SIMD (int i)\n      : mask(_mm512_cmpgt_epi64_mask(_mm512_set1_epi64(i),\n                                     _mm512_set_epi64(7, 6, 5, 4, 3, 2, 1, 0)))\n    { ; }\n    SIMD (int64_t i)\n      : mask(_mm512_cmpgt_epi64_mask(_mm512_set1_epi64(i),\n                                     _mm512_set_epi64(7, 6, 5, 4, 3, 2, 1, 0)))\n    { ; }\n    SIMD (__mmask8 _mask) : mask(_mask) { ; }\n    __mmask8 Data() const { return mask; }\n    static constexpr int Size() { return 8; }\n    static NETGEN_INLINE SIMD<mask64, 8> GetMaskFromBits (unsigned int i)\n    {\n      return SIMD<mask64, 8>(__mmask8(i));\n    }\n  };\n\n  template<>\n  class alignas(64) SIMD<int64_t,8>\n  {\n    __m512i data;\n\n  public:\n    static constexpr int Size() { return 8; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (int64_t val) { data = _mm512_set1_epi64(val); }\n    SIMD (int64_t v0, int64_t v1, int64_t v2, int64_t v3, int64_t v4, int64_t v5, int64_t v6, int64_t v7) { data = _mm512_set_epi64(v7,v6,v5,v4,v3,v2,v1,v0); }\n    SIMD (__m512i _data) { data = _data; }\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<int64_t(int)>>::value, int>::type = 0>\n      SIMD (const T & func)\n    {\n      data = _mm512_set_epi64(func(7), func(6), func(5), func(4), func(3), func(2), func(1), func(0));\n    }\n\n    SIMD (SIMD<int64_t,4> v0, SIMD<int64_t,4> v1)\n        : data(_mm512_castsi256_si512(v0.Data()))\n      {\n        data = _mm512_inserti64x4(data, v1.Data(), 1);\n      }\n\n    SIMD<int64_t,4> Lo() const { return _mm512_castsi512_si256(data); }\n    SIMD<int64_t,4> Hi() const { return _mm512_extracti64x4_epi64(data, 1); }\n\n\n    NETGEN_INLINE auto operator[] (int i) const { return ((int64_t*)(&data))[i]; }\n    NETGEN_INLINE auto & operator[] (int i) { return ((int64_t*)(&data))[i]; }\n    NETGEN_INLINE __m512i Data() const { return data; }\n    NETGEN_INLINE __m512i & Data() { return data; }\n    static SIMD FirstInt() { return { 0, 1, 2, 3, 4, 5, 6, 7 }; }\n  };\n\n  NETGEN_INLINE SIMD<int64_t,8> operator-(SIMD<int64_t,8> a) { return _mm512_sub_epi64(_mm512_setzero_si512(), a.Data()); }\n\n  NETGEN_INLINE SIMD<int64_t,8> operator+ (SIMD<int64_t,8> a, SIMD<int64_t,8> b) { return _mm512_add_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<int64_t,8> operator- (SIMD<int64_t,8> a, SIMD<int64_t,8> b) { return _mm512_sub_epi64(a.Data(),b.Data()); }\n\n   NETGEN_INLINE SIMD<int64_t,8> If (SIMD<mask64,8> a, SIMD<int64_t,8> b, SIMD<int64_t,8> c)\n  { return _mm512_mask_blend_epi64(a.Data(), c.Data(), b.Data()); }\n\n\n  template<>\n  class alignas(64) SIMD<double,8>\n  {\n    __m512d data;\n  public:\n    static constexpr int Size() { return 8; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (double val) { data = _mm512_set1_pd(val); }\n    SIMD (int val)    { data = _mm512_set1_pd(val); }\n    SIMD (size_t val) { data = _mm512_set1_pd(val); }\n    SIMD (double const * p) { data = _mm512_loadu_pd(p); }\n    SIMD (double const * p, SIMD<mask64,8> mask)\n      { data = _mm512_mask_loadu_pd(_mm512_setzero_pd(), mask.Data(), p); }\n    SIMD (__m512d _data) { data = _data; }\n    SIMD (SIMD<double,4> v0, SIMD<double,4> v1)\n        : data(_mm512_set_pd(v1[3], v1[2], v1[1], v1[0], v0[3], v0[2], v0[1], v0[0]))\n    {}\n    SIMD (SIMD<double,6> v0, SIMD<double,2> v1)\n        : data(_mm512_set_pd(v1[1], v1[0], v0[5], v0[4], v0[3], v0[2], v0[1], v0[0]))\n    {}\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<double(int)>>::value, int>::type = 0>\n    SIMD (const T & func)\n    {\n      data = _mm512_set_pd(func(7), func(6), func(5), func(4), func(3), func(2), func(1), func(0));\n    }\n\n    void Store (double * p) { _mm512_storeu_pd(p, data); }\n    void Store (double * p, SIMD<mask64,8> mask) { _mm512_mask_storeu_pd(p, mask.Data(), data); }\n\n    template <typename Function>\n    void SIMD_function (const Function & func, std::true_type)\n    {\n      data = (__m512d){ func(7), func(6), func(5), func(4),\n                       func(3), func(2), func(1), func(0) };\n    }\n\n    // not a function\n    void SIMD_function (double const * p, std::false_type)\n    {\n      data = _mm512_loadu_pd(p);\n    }\n\n    void SIMD_function (double val, std::false_type)\n    {\n      data = _mm512_set1_pd(val);\n    }\n\n    void SIMD_function (__m512d _data, std::false_type)\n    {\n      data = _data;\n    }\n\n    NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }\n    NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }\n    NETGEN_INLINE __m512d Data() const { return data; }\n    NETGEN_INLINE __m512d & Data() { return data; }\n\n    SIMD<double,4> Lo() const { return _mm512_extractf64x4_pd(data, 0); }\n    SIMD<double,4> Hi() const { return _mm512_extractf64x4_pd(data, 1); }\n\n    template <int I>\n    double Get() const\n    {\n      static_assert(I>=0 && I<8, \"Index out of range\");\n      return (*this)[I];\n    }\n  };\n\n  NETGEN_INLINE SIMD<double,8> operator- (SIMD<double,8> a) { return _mm512_xor_pd(a.Data(), _mm512_set1_pd(-0.0)); } //{ return -a.Data(); }\n  NETGEN_INLINE SIMD<double,8> operator+ (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_add_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,8> operator- (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_sub_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,8> operator* (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_mul_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,8> operator/ (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_div_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,8> operator* (double a, SIMD<double,8> b) { return _mm512_set1_pd(a)*b.Data(); }\n  NETGEN_INLINE SIMD<double,8> operator* (SIMD<double,8> b, double a) { return _mm512_set1_pd(a)*b.Data(); }\n\n  NETGEN_INLINE SIMD<double,8> sqrt (SIMD<double,8> a) { return _mm512_sqrt_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,8> floor (SIMD<double,8> a) { return _mm512_floor_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,8> ceil (SIMD<double,8> a) { return _mm512_ceil_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,8> fabs (SIMD<double,8> a) { return _mm512_max_pd(a.Data(), ( - a).Data()); }\n\n  NETGEN_INLINE SIMD<mask64,8> operator<= (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_LE_OQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator< (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_LT_OQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator>= (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_GE_OQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator> (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_GT_OQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator== (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_EQ_OQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator!= (SIMD<double,8> a , SIMD<double,8> b)\n  { return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_NEQ_OQ); }\n\n  NETGEN_INLINE SIMD<mask64,8> operator<= (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(), _MM_CMPINT_LE); }\n  NETGEN_INLINE SIMD<mask64,8> operator< (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(), _MM_CMPINT_LT); }\n  NETGEN_INLINE SIMD<mask64,8> operator>= (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(),  _MM_CMPINT_NLT); }\n  NETGEN_INLINE SIMD<mask64,8> operator> (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(), _MM_CMPINT_NLE); }\n  NETGEN_INLINE SIMD<mask64,8> operator== (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(), _MM_CMPINT_EQ); }\n  NETGEN_INLINE SIMD<mask64,8> operator!= (SIMD<int64_t,8> a , SIMD<int64_t,8> b)\n  { return _mm512_cmp_epi64_mask (a.Data(), b.Data(), _MM_CMPINT_NE); }\n\n  NETGEN_INLINE SIMD<mask64,8> operator&& (SIMD<mask64,8> a, SIMD<mask64,8> b)\n  { return (__mmask8)(a.Data() & b.Data()); }\n  NETGEN_INLINE SIMD<mask64,8> operator|| (SIMD<mask64,8> a, SIMD<mask64,8> b)\n  { return (__mmask8)(a.Data() | b.Data()); }\n  NETGEN_INLINE SIMD<mask64,8> operator! (SIMD<mask64,8> a)\n  { return (__mmask8)(~a.Data()); }\n\n  NETGEN_INLINE SIMD<double,8> If (SIMD<mask64,8> a, SIMD<double,8> b, SIMD<double,8> c)\n  { return _mm512_mask_blend_pd(a.Data(), c.Data(), b.Data()); }\n\n  NETGEN_INLINE SIMD<double,8> IfPos (SIMD<double,8> a, SIMD<double> b, SIMD<double> c)\n  {\n    auto k = _mm512_cmp_pd_mask(a.Data(),_mm512_setzero_pd(), _CMP_GT_OS);\n    return _mm512_mask_blend_pd(k,c.Data(),b.Data());\n  }\n  NETGEN_INLINE SIMD<double,8> IfZero (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    auto k = _mm512_cmp_pd_mask(a.Data(),_mm512_setzero_pd(), _CMP_EQ_OS);\n    return _mm512_mask_blend_pd(k,c.Data(),b.Data());\n  }\n\n\n  NETGEN_INLINE auto Unpack (SIMD<double,8> a, SIMD<double,8> b)\n  {\n    return std::make_tuple(SIMD<double,8>(_mm512_unpacklo_pd(a.Data(),b.Data())),\n                      SIMD<double,8>(_mm512_unpackhi_pd(a.Data(),b.Data())));\n  }\n\n\n  NETGEN_INLINE double HSum (SIMD<double,8> sd)\n  {\n    SIMD<double,4> low = _mm512_extractf64x4_pd(sd.Data(),0);\n    SIMD<double,4> high = _mm512_extractf64x4_pd(sd.Data(),1);\n    return HSum(low)+HSum(high);\n  }\n\n  NETGEN_INLINE auto HSum (SIMD<double,8> sd1, SIMD<double,8> sd2)\n  {\n    return SIMD<double,2>(HSum(sd1), HSum(sd2));\n  }\n\n  NETGEN_INLINE SIMD<double,4> HSum (SIMD<double,8> v1, SIMD<double,8> v2, SIMD<double,8> v3, SIMD<double,8> v4)\n  {\n    SIMD<double> lo,hi;\n    std::tie(lo,hi) = Unpack(v1, v2);\n    SIMD<double> sum01 = lo+hi;\n    std::tie(lo,hi) = Unpack(v3, v4);\n    SIMD<double> sum23 = lo+hi;\n    // sum01  b a b a b a b a\n    // sum23  d c d c d c d c\n    // __m512 perm = _mm512_permutex2var_pd (sum01.Data(), _mm512_set_epi64(1,2,3,4,5,6,7,8), sum23.Data());\n    SIMD<double,4> ab =  _mm512_extractf64x4_pd(sum01.Data(),0) + _mm512_extractf64x4_pd(sum01.Data(),1);\n    SIMD<double,4> cd =  _mm512_extractf64x4_pd(sum23.Data(),0) + _mm512_extractf64x4_pd(sum23.Data(),1);\n    return _mm256_add_pd (_mm256_permute2f128_pd (ab.Data(), cd.Data(), 1 + 2 * 16), _mm256_blend_pd(ab.Data(), cd.Data(), 12));\n  }\n\n  NETGEN_INLINE SIMD<double,8> FMA (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    return _mm512_fmadd_pd (a.Data(), b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<double,8> FMA (const double & a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    return _mm512_fmadd_pd (_mm512_set1_pd(a), b.Data(), c.Data());\n  }\n\n  NETGEN_INLINE SIMD<double,8> FNMA (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    return _mm512_fnmadd_pd (a.Data(), b.Data(), c.Data());\n  }\n  NETGEN_INLINE SIMD<double,8> FNMA (const double & a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    return _mm512_fnmadd_pd (_mm512_set1_pd(a), b.Data(), c.Data());\n  }\n\n  NETGEN_INLINE SIMD<double,8> FMAddSub (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)\n  {\n    return _mm512_fmaddsub_pd(a.Data(), b.Data(), c.Data());\n  }\n\n  NETGEN_INLINE SIMD<double,8> SwapPairs (SIMD<double,8> a)\n  {\n    return _mm512_shuffle_pd (a.Data(), a.Data(), 0b01010101);\n  }\n  \n}\n\n#endif // NETGEN_CORE_SIMD_AVX512_HPP\n"
  },
  {
    "path": "libsrc/core/simd_generic.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_GENERIC_HPP\n#define NETGEN_CORE_SIMD_GENERIC_HPP\n\n/**************************************************************************/\n/* File:   simd_base.hpp                                                  */\n/* Author: Joachim Schoeberl, Matthias Hochsteger                         */\n/* Date:   25. Mar. 16                                                    */\n/**************************************************************************/\n\n#include <type_traits>\n#include <functional>\n#include <tuple>\n#include <cmath>\n\n#include \"array.hpp\"\n\nnamespace ngcore\n{\n#if defined __AVX512F__\n    #define NETGEN_DEFAULT_SIMD_SIZE 8\n#elif defined __AVX__\n    #define NETGEN_DEFAULT_SIMD_SIZE 4\n#else\n    #define NETGEN_DEFAULT_SIMD_SIZE 2\n#endif\n\n  constexpr int GetDefaultSIMDSize() {\n      return NETGEN_DEFAULT_SIMD_SIZE;\n  }\n\n  constexpr bool IsNativeSIMDSize(int n) {\n    if(n==1) return true;\n    if(n==2) return true;\n#if defined __AVX__\n    if(n==4) return true;\n#endif\n#if defined __AVX512F__\n    if(n==8) return true;\n#endif\n    return false;\n  }\n\n  // split n = k+l such that k is the largest natively supported simd size < n\n  constexpr int GetLargestNativeSIMDPart(int n) {\n      int k = n-1;\n      while(!IsNativeSIMDSize(k))\n          k--;\n      return k;\n  }\n\n  constexpr size_t LargestPowerOfTwo (size_t x)\n  {\n    size_t y = 1;\n    while (2*y <= x) y *= 2;\n    return y;\n  }\n  \n\n  template <typename T, int N=GetDefaultSIMDSize()> class SIMD;\n\n  class mask64;\n\n  ////////////////////////////////////////////////////////////////////////////\n  namespace detail {\n    template <typename T, size_t N, size_t... I>\n    auto array_range_impl(std::array<T, N> const& arr,\n                   size_t first,\n                   std::index_sequence<I...>)\n    -> std::array<T, sizeof...(I)> {\n        return {arr[first + I]...};\n    }\n\n    template <size_t S, typename T, size_t N>\n    auto array_range(std::array<T, N> const& arr, size_t first) {\n      return array_range_impl(arr, first, std::make_index_sequence<S>{});\n    }\n  \n  } // namespace detail\n\n  ////////////////////////////////////////////////////////////////////////////\n  // mask\n\n  template <>\n  class SIMD<mask64,1>\n  {\n    int64_t mask;\n  public:\n    SIMD (int64_t i)\n      : mask(i > 0 ? -1 : 0) { ; }\n    bool Data() const { return mask; }\n    static constexpr int Size() { return 1; }\n    auto operator[] (int /* i */) const { return mask; }\n  };\n\n\n  template <int N>\n  class alignas(GetLargestNativeSIMDPart(N)*sizeof(int64_t)) SIMD<mask64,N>\n  {\n    // static constexpr int N1 = GetLargestNativeSIMDPart(N);\n    static constexpr size_t N1 = LargestPowerOfTwo(N-1);\n    static constexpr int N2 = N-N1;\n\n    SIMD<mask64,N1> lo;\n    SIMD<mask64,N2> hi;\n  public:\n\n    SIMD (int64_t i) : lo(i), hi(i-N1 ) { ; }\n    SIMD (SIMD<mask64,N1> lo_, SIMD<mask64,N2> hi_) : lo(lo_), hi(hi_) { ; }\n    SIMD<mask64,N1> Lo() const { return lo; }\n    SIMD<mask64,N2> Hi() const { return hi; }\n    static constexpr int Size() { return N; }\n  };\n\n  template<int N>\n  NETGEN_INLINE SIMD<mask64,N> operator&& (SIMD<mask64,N> a, SIMD<mask64,N> b)\n    {\n      if constexpr(N==1) return a.Data() && b.Data();\n      else               return { a.Lo() && b.Lo(), a.Hi() && b.Hi() };\n    }\n\n\n  ////////////////////////////////////////////////////////////////////////////\n  // int32\n\n  template<>\n  class SIMD<int32_t,1>\n  {\n    int32_t data;\n\n  public:\n    static constexpr int Size() { return 1; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n    // SIMD (int val) : data{val} {}\n    SIMD (int32_t val) : data{val} {}\n    SIMD (size_t val) : data(val) {}\n    explicit SIMD (std::array<int32_t, 1> arr) : data{arr[0]} {}\n    \n\n    \n    int32_t operator[] (int i) const { return ((int32_t*)(&data))[i]; }\n    auto Data() const { return data; }\n    static SIMD FirstInt(int32_t n0=0) { return {n0}; }\n    template <int I>\n    int32_t Get()\n    {\n      static_assert(I==0);\n      return data;\n    }\n  };\n\n  template<int N>\n  class alignas(GetLargestNativeSIMDPart(N)*sizeof(int64_t)) SIMD<int32_t,N>\n  {\n    // static constexpr int N1 = GetLargestNativeSIMDPart(N);\n    static constexpr size_t N1 = LargestPowerOfTwo(N-1);        \n    static constexpr int N2 = N-N1;\n\n    SIMD<int32_t,N1> lo;\n    SIMD<int32_t,N2> high;\n\n  public:\n    static constexpr int Size() { return N; }\n\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    // SIMD (int val) : lo{val}, high{val} { ; }\n    SIMD (int32_t val) : lo{val}, high{val} { ; }\n    SIMD (size_t val) : lo{val}, high{val} { ; }\n    SIMD (int32_t * p) : lo{p}, high{p+N1} { ; }\n    \n    SIMD (SIMD<int32_t,N1> lo_, SIMD<int32_t,N2> high_) : lo(lo_), high(high_) { ; }\n\n    explicit SIMD( std::array<int32_t, N> arr )\n        : lo(detail::array_range<N1>(arr, 0)),\n          high(detail::array_range<N2>(arr, N1))\n      {}\n\n\n    template<typename ...T>\n    explicit SIMD(const T... vals)\n      : lo(detail::array_range<N1>(std::array<int32_t, N>{vals...}, 0)),\n        high(detail::array_range<N2>(std::array<int32_t, N>{vals...}, N1))\n      {\n        static_assert(sizeof...(vals)==N, \"wrong number of arguments\");\n      }\n\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<int32_t(int)>>::value, int>::type = 0>\n      SIMD (const T & func)\n    {\n      for(auto i : IntRange(N1))\n          lo[i] = func(i);\n      for(auto i : IntRange(N2))\n          high[i] = func(N1+i);\n    }\n    \n    auto Lo() const { return lo; }\n    auto Hi() const { return high; }\n\n    int32_t operator[] (int i) const { return ((int32_t*)(&lo))[i]; }\n\n    void Store (int32_t * p) { lo.Store(p); high.Store(p+N1); }\n\n    \n    /*\n    operator tuple<int32_t&,int32_t&,int32_t&,int32_t&> ()\n    { return tuple<int32_t&,int32_t&,int32_t&,int32_t&>((*this)[0], (*this)[1], (*this)[2], (*this)[3]); }\n    */\n\n    /*\n    static SIMD FirstInt() { return { 0, 1, 2, 3 }; }\n    */\n    static SIMD FirstInt(int32_t n0=0) { return {SIMD<int32_t,N1>::FirstInt(n0), SIMD<int32_t,N2>::FirstInt(n0+N1)}; }\n    template <int I>\n    int32_t Get()\n    {\n      static_assert(I>=0 && I<N, \"Index out of range\");\n      if constexpr(I<N1) return lo.template Get<I>();\n      else               return high.template Get<I-N1>();\n    }\n  };\n\n\n\n  ////////////////////////////////////////////////////////////////////////////\n  // int64\n\n  template<>\n  class SIMD<int64_t,1>\n  {\n    int64_t data;\n\n  public:\n    static constexpr int Size() { return 1; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n    SIMD (int val) : data{val} {}\n    SIMD (int64_t val) : data{val} {}\n    SIMD (size_t val) : data(val) {}\n    explicit SIMD (std::array<int64_t, 1> arr)\n        : data{arr[0]}\n    {}\n\n    int64_t operator[] (int i) const { return ((int64_t*)(&data))[i]; }\n    auto Data() const { return data; }\n    static SIMD FirstInt(int64_t n0=0) { return {n0}; }\n    template <int I>\n    int64_t Get()\n    {\n      static_assert(I==0);\n      return data;\n    }\n  };\n\n  template<int N>\n  class alignas(GetLargestNativeSIMDPart(N)*sizeof(int64_t)) SIMD<int64_t,N>\n  {\n    // static constexpr int N1 = GetLargestNativeSIMDPart(N);\n    static constexpr size_t N1 = LargestPowerOfTwo(N-1);        \n    static constexpr int N2 = N-N1;\n\n    SIMD<int64_t,N1> lo;\n    SIMD<int64_t,N2> high;\n\n  public:\n    static constexpr int Size() { return N; }\n\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (int val) : lo{val}, high{val} { ; }\n    SIMD (int64_t val) : lo{val}, high{val} { ; }\n    SIMD (size_t val) : lo{val}, high{val} { ; }\n    SIMD (SIMD<int64_t,N1> lo_, SIMD<int64_t,N2> high_) : lo(lo_), high(high_) { ; }\n\n    explicit SIMD( std::array<int64_t, N> arr )\n        : lo(detail::array_range<N1>(arr, 0)),\n          high(detail::array_range<N2>(arr, N1))\n      {}\n\n    template<typename ...T>\n    explicit SIMD(const T... vals)\n    : lo(detail::array_range<N1>(std::array<int64_t, N>{vals...}, 0)),\n      high(detail::array_range<N2>(std::array<int64_t, N>{vals...}, N1))\n      {\n        static_assert(sizeof...(vals)==N, \"wrong number of arguments\");\n      }\n\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<int64_t(int)>>::value, int>::type = 0>\n      SIMD (const T & func)\n    {\n      for(auto i : IntRange(N1))\n          lo[i] = func(i);\n      for(auto i : IntRange(N2))\n          high[i] = func(N1+i);\n    }\n\n    auto Lo() const { return lo; }\n    auto Hi() const { return high; }\n\n    int64_t operator[] (int i) const { return ((int64_t*)(&lo))[i]; }\n\n    /*\n    operator tuple<int64_t&,int64_t&,int64_t&,int64_t&> ()\n    { return tuple<int64_t&,int64_t&,int64_t&,int64_t&>((*this)[0], (*this)[1], (*this)[2], (*this)[3]); }\n    */\n\n    /*\n    static SIMD FirstInt() { return { 0, 1, 2, 3 }; }\n    */\n    static SIMD FirstInt(int64_t n0=0) { return {SIMD<int64_t,N1>::FirstInt(n0), SIMD<int64_t,N2>::FirstInt(n0+N1)}; }\n    template <int I>\n    int64_t Get()\n    {\n      static_assert(I>=0 && I<N, \"Index out of range\");\n      if constexpr(I<N1) return lo.template Get<I>();\n      else               return high.template Get<I-N1>();\n    }\n  };\n\n  \n\n  ////////////////////////////////////////////////////////////////////////////\n  // double\n\n  template<>\n  class SIMD<double,1>\n  {\n    double data;\n\n  public:\n    static constexpr int Size() { return 1; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD & operator= (const SIMD &) = default;\n    SIMD (double val) { data = val; }\n    SIMD (int val)    { data = val; }\n    SIMD (size_t val) { data = val; }\n    SIMD (double const * p) { data = *p; }\n    SIMD (double const * p, SIMD<mask64,1> mask) { data = mask.Data() ? *p : 0.0; }\n    explicit SIMD (std::array<double, 1> arr)\n        : data{arr[0]}\n    {}\n\n    template <typename T, typename std::enable_if<std::is_convertible<T,std::function<double(int)>>::value,int>::type = 0>\n    SIMD (const T & func)\n    {\n      data = func(0);\n    }\n\n    template <typename T, typename std::enable_if<std::is_convertible<T,std::function<double(int)>>::value,int>::type = 0>\n    SIMD & operator= (const T & func)\n    {\n      data = func(0);\n      return *this;\n    }\n\n    void Store (double * p) { *p = data; }\n    void Store (double * p, SIMD<mask64,1> mask) { if (mask.Data()) *p = data; }\n\n    double operator[] (int i) const { return ((double*)(&data))[i]; }\n    double Data() const { return data; }\n    template <int I>\n    double Get()\n    {\n      static_assert(I==0);\n      return data;\n    }\n  };\n\n\n  template<int N>\n  class alignas(GetLargestNativeSIMDPart(N)*sizeof(double)) SIMD<double, N>\n  {\n    // static constexpr int N1 = GetLargestNativeSIMDPart(N);\n    static constexpr size_t N1 = LargestPowerOfTwo(N-1);    \n    static constexpr int N2 = N-N1;\n\n    SIMD<double, N1> lo;\n    SIMD<double, N2> high;\n\n  public:\n    static constexpr int Size() { return N; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD (SIMD<double,N1> lo_, SIMD<double,N2> hi_) : lo(lo_), high(hi_) { ; }\n\n    template <typename T, typename std::enable_if<std::is_convertible<T,std::function<double(int)>>::value,int>::type = 0>\n    SIMD (const T & func)\n    {\n      double  *p = (double*)this;\n      for(auto i : IntRange(N))\n          p[i] = func(i);\n    }\n\n    template <typename T, typename std::enable_if<std::is_convertible<T,std::function<double(int)>>::value,int>::type = 0>\n    SIMD & operator= (const T & func)\n    {\n      double  *p = (double*)this;\n      for(auto i : IntRange(N))\n          p[i] = func(i);\n      return *this;\n    }\n\n\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (double val) : lo{val}, high{val} { ; }\n    SIMD (int val)    : lo{val}, high{val} { ; }\n    SIMD (size_t val) : lo{val}, high{val} { ; }\n\n    SIMD (double const * p) : lo{p}, high{p+N1} { ; }\n    SIMD (double const * p, SIMD<mask64,N> mask)\n        : lo{p, mask.Lo()}, high{p+N1, mask.Hi()}\n      { }\n    SIMD (double * p) : lo{p}, high{p+N1} { ; }\n    SIMD (double * p, SIMD<mask64,N> mask)\n        : lo{p, mask.Lo()}, high{p+N1, mask.Hi()}\n      { }\n\n    explicit SIMD( std::array<double, N> arr )\n        : lo(detail::array_range<N1>(arr, 0)),\n          high(detail::array_range<N2>(arr, N1))\n      {}\n\n    template<typename ...T>\n    explicit SIMD(const T... vals)\n      : lo(detail::array_range<N1>(std::array<double, N>{vals...}, 0)),\n      high(detail::array_range<N2>(std::array<double, N>{vals...}, N1))\n      {\n        static_assert(sizeof...(vals)==N, \"wrong number of arguments\");\n      }\n\n    void Store (double * p) { lo.Store(p); high.Store(p+N1); }\n    void Store (double * p, SIMD<mask64,N> mask)\n    {\n      lo.Store(p, mask.Lo());\n      high.Store(p+N1, mask.Hi());\n    }\n\n    NETGEN_INLINE auto Lo() const { return lo; }\n    NETGEN_INLINE auto Hi() const { return high; }\n\n    double operator[] (int i) const { return ((double*)(&lo))[i]; }\n\n    template<typename=std::enable_if<N==2>>\n    operator std::tuple<double&,double&> ()\n    { \n\tdouble *p = (double*)this;\n\treturn std::tuple<double&,double&>(p[0], p[1]); \n    }\n\n    template<typename=std::enable_if<N==4>>\n    operator std::tuple<double&,double&,double&,double&> ()\n    { return std::tuple<double&,double&,double&,double&>((*this)[0], (*this)[1], (*this)[2], (*this)[3]); }\n\n    template <int I>\n    double Get()\n    {\n      static_assert(I>=0 && I<N, \"Index out of range\");\n      if constexpr(I<N1) return lo.template Get<I>();\n      else               return high.template Get<I-N1>();\n    }\n    auto Data() const { return *this; }\n  };\n\n\n  // Generic operators for any arithmetic type/simd width\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<T,N> operator+ (SIMD<T,N> a, SIMD<T,N> b) {\n      if constexpr(N==1) return a.Data()+b.Data();\n      else               return { a.Lo()+b.Lo(), a.Hi()+b.Hi() };\n  }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<T,N> operator- (SIMD<T,N> a, SIMD<T,N> b) {\n      if constexpr(N==1) return a.Data()-b.Data();\n      else               return { a.Lo()-b.Lo(), a.Hi()-b.Hi() };\n  }\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<T,N> operator- (SIMD<T,N> a) {\n      if constexpr(N==1) return -a.Data();\n      else               return { -a.Lo(), -a.Hi() };\n  }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<T,N> operator* (SIMD<T,N> a, SIMD<T,N> b) {\n      if constexpr(N==1) return a.Data()*b.Data();\n      else               return { a.Lo()*b.Lo(), a.Hi()*b.Hi() };\n  }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<T,N> operator/ (SIMD<T,N> a, SIMD<T,N> b) {\n      if constexpr(N==1) return a.Data()/b.Data();\n      else               return { a.Lo()/b.Lo(), a.Hi()/b.Hi() };\n  }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator< (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() < b.Data();\n      else               return { a.Lo()<b.Lo(), a.Hi()<b.Hi() };\n    }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator<= (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() <= b.Data();\n      else               return { a.Lo()<=b.Lo(), a.Hi()<=b.Hi() };\n    }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator> (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() > b.Data();\n      else               return { a.Lo()>b.Lo(), a.Hi()>b.Hi() };\n    }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator>= (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() >= b.Data();\n      else               return { a.Lo()>=b.Lo(), a.Hi()>=b.Hi() };\n    }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator== (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() == b.Data();\n      else               return { a.Lo()==b.Lo(), a.Hi()==b.Hi() };\n    }\n\n  template <typename T, int N>\n  NETGEN_INLINE SIMD<mask64,N> operator!= (SIMD<T,N> a, SIMD<T,N> b)\n    {\n      if constexpr(N==1) return a.Data() != b.Data();\n      else               return { a.Lo()!=b.Lo(), a.Hi()!=b.Hi() };\n    }\n\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator& (SIMD<int64_t,N> a, SIMD<int64_t,N> b)\n    {\n      if constexpr(N==1) return a.Data() & b.Data();\n      else               return { (a.Lo()&b.Lo()), (a.Hi()&b.Hi()) };\n    }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator| (SIMD<int64_t,N> a, SIMD<int64_t,N> b)\n    {\n      if constexpr(N==1) return a.Data() & b.Data();\n      else               return { (a.Lo()|b.Lo()), (a.Hi()|b.Hi()) };\n    }\n\n  \n  // int64_t operators with scalar operand (implement overloads to allow implicit casts for second operand)\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator+ (SIMD<int64_t,N> a, int64_t b) { return a+SIMD<int64_t,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator+ (int64_t a, SIMD<int64_t,N> b) { return SIMD<int64_t,N>(a)+b; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator- (int64_t a, SIMD<int64_t,N> b) { return SIMD<int64_t,N>(a)-b; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator- (SIMD<int64_t,N> a, int64_t b) { return a-SIMD<int64_t,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator* (int64_t a, SIMD<int64_t,N> b) { return SIMD<int64_t,N>(a)*b; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator* (SIMD<int64_t,N> b, int64_t a) { return SIMD<int64_t,N>(a)*b; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator/ (SIMD<int64_t,N> a, int64_t b) { return a/SIMD<int64_t,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> operator/ (int64_t a, SIMD<int64_t,N> b) { return SIMD<int64_t,N>(a)/b; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator+= (SIMD<int64_t,N> & a, SIMD<int64_t,N> b) { a=a+b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator+= (SIMD<int64_t,N> & a, int64_t b) { a+=SIMD<int64_t,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator-= (SIMD<int64_t,N> & a, SIMD<int64_t,N> b) { a = a-b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator-= (SIMD<int64_t,N> & a, int64_t b) { a-=SIMD<int64_t,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator*= (SIMD<int64_t,N> & a, SIMD<int64_t,N> b) { a=a*b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator*= (SIMD<int64_t,N> & a, int64_t b) { a*=SIMD<int64_t,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<int64_t,N> & operator/= (SIMD<int64_t,N> & a, SIMD<int64_t,N> b) { a = a/b; return a; }\n\n\n  // double operators with scalar operand (implement overloads to allow implicit casts for second operand)\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator+ (SIMD<double,N> a, double b) { return a+SIMD<double,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator+ (double a, SIMD<double,N> b) { return SIMD<double,N>(a)+b; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator- (double a, SIMD<double,N> b) { return SIMD<double,N>(a)-b; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator- (SIMD<double,N> a, double b) { return a-SIMD<double,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator* (double a, SIMD<double,N> b) { return SIMD<double,N>(a)*b; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator* (SIMD<double,N> b, double a) { return SIMD<double,N>(a)*b; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator/ (SIMD<double,N> a, double b) { return a/SIMD<double,N>(b); }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> operator/ (double a, SIMD<double,N> b) { return SIMD<double,N>(a)/b; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator+= (SIMD<double,N> & a, SIMD<double,N> b) { a=a+b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator+= (SIMD<double,N> & a, double b) { a+=SIMD<double,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator-= (SIMD<double,N> & a, SIMD<double,N> b) { a = a-b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator-= (SIMD<double,N> & a, double b) { a-=SIMD<double,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator*= (SIMD<double,N> & a, SIMD<double,N> b) { a=a*b; return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator*= (SIMD<double,N> & a, double b) { a*=SIMD<double,N>(b); return a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> & operator/= (SIMD<double,N> & a, SIMD<double,N> b) { a = a/b; return a; }\n\n  template <int N>\n  NETGEN_INLINE auto operator> (SIMD<double,N> & a, double b) { return a > SIMD<double,N>(b); }\n\n  \n  // double functions\n\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> L2Norm2 (SIMD<double,N> a) { return a*a; }\n  template <int N>\n  NETGEN_INLINE SIMD<double,N> Trans (SIMD<double,N> a) { return a; }\n\n  template <int N>\n  NETGEN_INLINE double HSum (SIMD<double,N> a)\n    {\n      if constexpr(N==1)\n          return a.Data();\n      else\n          return HSum(a.Lo()) + HSum(a.Hi());\n    }\n\n\n  template<typename T, int N>\n  NETGEN_INLINE SIMD<T,N> IfPos (SIMD<T,N> a, SIMD<T,N> b, SIMD<T,N> c)\n    {\n      if constexpr(N==1) return a.Data()>0.0 ? b : c;\n      else               return { IfPos(a.Lo(), b.Lo(), c.Lo()), IfPos(a.Hi(), b.Hi(), c.Hi())};\n\n    }\n\n  template<typename T, int N>\n  NETGEN_INLINE SIMD<T,N> IfZero (SIMD<T,N> a, SIMD<T,N> b, SIMD<T,N> c)\n    {\n      if constexpr(N==1) return a.Data()==0.0 ? b : c;\n      else               return { IfZero(a.Lo(), b.Lo(), c.Lo()), IfZero(a.Hi(), b.Hi(), c.Hi())};\n\n    }\n\n  template<typename T, int N>\n  NETGEN_INLINE SIMD<T,N> If (SIMD<mask64,N> a, SIMD<T,N> b, SIMD<T,N> c)\n    {\n      if constexpr(N==1) return a.Data() ? b : c;\n      else               return { If(a.Lo(), b.Lo(), c.Lo()), If(a.Hi(), b.Hi(), c.Hi())};\n\n    }\n\n  // a*b+c\n  template <typename T1, typename T2, typename T3>\n  NETGEN_INLINE auto FMA(T1 a, T2 b, T3 c)\n  {\n    return c+a*b;\n  }\n\n  template <typename T1, typename T2, typename T3>\n  NETGEN_INLINE auto FNMA(T1 a, T2 b, T3 c)\n  {\n    return c-a*b;\n  }\n\n  // update form of fma\n  template <int N>\n  void FMAasm (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> & sum)\n  {\n    sum = FMA(a,b,sum);\n  }\n\n  // update form of fms\n  template <int N>\n  void FNMAasm (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> & sum)\n  {\n    // sum -= a*b;\n    sum = FNMA(a,b,sum);\n  }\n\n  // c += a*b    (a0re, a0im, a1re, a1im, ...), \n  template <int N>\n  void FMAComplex (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> & c)\n  {\n    auto [are, aim] = Unpack(a, a);\n    SIMD<double,N> bswap = SwapPairs(b);\n    SIMD<double,N> aim_bswap = aim*bswap;\n    c += FMAddSub (are, b, aim_bswap);\n  }\n  \n  template <int i, typename T, int N>\n  T get(SIMD<T,N> a) { return a.template Get<i>(); }\n\n  template <int NUM, typename FUNC>\n  NETGEN_INLINE void Iterate2 (FUNC f)\n  {\n    if constexpr (NUM > 1) Iterate2<NUM-1> (f);\n    if constexpr (NUM >= 1) f(std::integral_constant<int,NUM-1>());\n  }\n\n\n  template<typename T2, typename T1>\n  T2 BitCast(T1 a)\n  {\n    T2 result;\n    static_assert(sizeof(T1) == sizeof(T2), \"BitCast requires same size\");\n    memcpy(&result, &a, sizeof(T1));\n    return result;\n  }\n\n  template <typename T, typename T1, int N>\n  SIMD<T, N> Reinterpret (SIMD<T1,N> a)\n  {\n    if constexpr (N == 1)\n      return SIMD<T,N> ( * (T*)(void*) & a.Data());\n    else if constexpr (N == 2)\n      return SIMD<T,N> { BitCast<T> (a.Lo()),\n                         BitCast<T> (a.Hi()) };\n    else\n      return SIMD<T,N> (Reinterpret<T> (a.Lo()), Reinterpret<T> (a.Hi()));\n  }\n\n  \n  using std::round;  \n  template <int N>\n  SIMD<double,N> round (SIMD<double,N> x)\n  {\n    if constexpr (N == 1) return round(x);\n    else                  return { round(x.Lo()), round(x.Hi()) };\n  }\n\n  // NETGEN_INLINE int64_t RoundI (double x) { return lround(x); }\n  using std::lround;\n  template <int N>  \n  SIMD<int64_t,N> lround (SIMD<double,N> x)\n  {\n    if constexpr (N == 1) return SIMD<int64_t,1> (lround(x));\n    else                  return { lround(x.Lo()), lround(x.Hi()) };\n  }\n\n  /*\n    reciprocal square root \n    Quake III algorithm, or intrinsics \n   */\n  //\n#ifndef __CUDACC__\n  NETGEN_INLINE double rsqrt (double x) { return 1.0/sqrt(x); }\n#endif\n  \n  template <int N>  \n  SIMD<double,N> rsqrt (SIMD<double,N> x)\n  {\n    if constexpr (N == 1) return 1.0/sqrt(x.Data()); \n    else                  return { rsqrt(x.Lo()), rsqrt(x.Hi()) };\n  }\n\n  template <int N>  \n  int64_t operator<< (int64_t a, IC<N> n) { return a << n.value; }\n  \n  template <int S, int N>\n  SIMD<int64_t,S> operator<< (SIMD<int64_t,S> a, IC<N> n)\n  {\n    if constexpr (S == 1) return SIMD<int64_t,1> (a.Data() << n);\n    else                  return SIMD<int64_t,S> (a.Lo() << n, a.Hi() << n);\n  }\n\n\n\n  \n  template <typename T, int N>\n  auto Min (SIMD<T,N> a, SIMD<T,N> b)\n  {\n    if constexpr (N==1)\n      return SIMD<T,1> (std::min(a[0], b[0]));\n    else\n      return SIMD<T,N> (Min(a.Lo(), b.Lo()), Min(a.Hi(), b.Hi()));\n  }\n  \n  template <typename T, int N>\n  auto Max (SIMD<T,N> a, SIMD<T,N> b)\n  {\n    if constexpr (N==1)\n      return SIMD<T,1> (std::max(a[0], b[0]));\n    else\n      return SIMD<T,N> (Max(a.Lo(), b.Lo()), Max(a.Hi(), b.Hi()));\n  }\n  \n\n\n  \n  \n  template <typename T, int N>\n  ostream & operator<< (ostream & ost, SIMD<T,N> simd)\n  {\n    /*\n    ost << simd[0];\n    for (int i = 1; i < simd.Size(); i++)\n      ost << \" \" << simd[i];\n    */\n    Iterate2<simd.Size()> ([&] (auto I) {\n        if (I.value != 0) ost << \" \";\n        ost << get<I.value>(simd);\n      });\n    return ost;\n  }\n\n  using std::sqrt;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> sqrt (ngcore::SIMD<double,N> a)\n  {\n    if constexpr (N == 1) return sqrt(a.Data());\n    else return { sqrt(a.Lo()), sqrt(a.Hi()) }; \n    // return ngcore::SIMD<double,N>([a](int i)->double { return sqrt(a[i]); } );\n  }\n\n  using std::fabs;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> fabs (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return fabs(a[i]); } );\n  }\n\n  using std::floor;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> floor (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return floor(a[i]); } );\n  }\n\n  using std::ceil;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> ceil (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return ceil(a[i]); } );\n  }\n\n  using std::exp;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> exp (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return exp(a[i]); } );\n  }\n\n  using std::log;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> log (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return log(a[i]); } );\n  }\n\n  using std::erf;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> erf (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return erf(a[i]); } );\n  }\n\n  using std::pow;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> pow (ngcore::SIMD<double,N> a, double x) {\n    return ngcore::SIMD<double,N>([a,x](int i)->double { return pow(a[i],x); } );\n  }\n\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> pow (ngcore::SIMD<double,N> a, ngcore::SIMD<double,N> b) {\n    return ngcore::SIMD<double,N>([a,b](int i)->double { return pow(a[i],b[i]); } );\n  }\n\n  using std::sin;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> sin (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return sin(a[i]); } );\n  }\n\n  using std::cos;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> cos (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return cos(a[i]); } );\n  }\n\n  using std::tan;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> tan (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return tan(a[i]); } );\n  }\n\n  using std::atan;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> atan (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return atan(a[i]); } );\n  }\n\n  using std::atan2;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> atan2 (ngcore::SIMD<double,N> y, ngcore::SIMD<double,N> x) {\n    return ngcore::SIMD<double,N>([y,x](int i)->double { return atan2(y[i], x[i]); } );\n  }\n\n  using std::acos;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> acos (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return acos(a[i]); } );\n  }\n\n  using std::asin;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> asin (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return asin(a[i]); } );\n  }\n\n  using std::sinh;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> sinh (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return sinh(a[i]); } );\n  }\n\n  using std::cosh;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> cosh (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return cosh(a[i]); } );\n  }\n\n  using std::asinh;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> asinh (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return asinh(a[i]); } );\n  }\n\n  using std::acosh;\n  template <int N>\n  NETGEN_INLINE ngcore::SIMD<double,N> acosh (ngcore::SIMD<double,N> a) {\n    return ngcore::SIMD<double,N>([a](int i)->double { return acosh(a[i]); } );\n  }\n\n\n  \n  template<int N, typename T>\n  using MultiSIMD = SIMD<T, N*GetDefaultSIMDSize()>;\n\n  template<int N>\n  NETGEN_INLINE auto Unpack (SIMD<double,N> a, SIMD<double,N> b)\n  {\n    if constexpr(N==1)\n      {\n        return std::make_tuple(SIMD<double,N>{a.Data()}, SIMD<double,N>{b.Data()} );\n      }\n    else if constexpr(N==2)\n      {\n        return std::make_tuple(SIMD<double,N>{ a.Lo(), b.Lo() },\n            SIMD<double,N>{ a.Hi(), b.Hi() });\n      }\n    else\n      {\n        auto [a1,b1] = Unpack(a.Lo(), b.Lo());\n        auto [a2,b2] = Unpack(a.Hi(), b.Hi());\n        return std::make_tuple(SIMD<double,N>{ a1, a2 },\n            SIMD<double,N>{ b1, b2 });\n      }\n  }\n\n  // TODO: specialize for AVX, ... \n  template<int N>\n  NETGEN_INLINE auto SwapPairs (SIMD<double,N> a)\n  {\n    if constexpr(N==1) {\n        // static_assert(false);\n        return a;\n      }\n    else if constexpr(N==2) {\n        return SIMD<double,N> (a.Hi(), a.Lo());\n      }\n    else {\n      return SIMD<double,N> (SwapPairs(a.Lo()), SwapPairs(a.Hi()));\n    }\n  }\n\n\n  template<int N>\n  NETGEN_INLINE auto HSum128 (SIMD<double,N> a)\n  {\n    if constexpr(N==1) {\n        // static_assert(false);\n        return a;\n      }\n    else if constexpr(N==2) {\n        return a;\n      }\n    else {\n      return HSum128(a.Lo()) + HSum128(a.Hi());\n    }\n  }\n\n  \n  // TODO: specialize for AVX, ... \n  // a*b+-c   (even: -, odd: +)\n  template<int N>\n  NETGEN_INLINE auto FMAddSub (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> c)\n  {\n    if constexpr(N==1) {\n        // static_assert(false);\n        return a*b-c;\n      }\n    else if constexpr(N==2) {\n        return SIMD<double,N> (a.Lo()*b.Lo()-c.Lo(),\n                               a.Hi()*b.Hi()+c.Hi());\n      }\n    else {\n      return SIMD<double,N> (FMAddSub(a.Lo(), b.Lo(), c.Lo()),\n                             FMAddSub(a.Hi(), b.Hi(), c.Hi()));\n    }\n  }\n\n\n\n\n  template <int BASE, typename Tuple, std::size_t ... Is>\n  auto subtuple (const Tuple& tup, std::index_sequence<Is...>)\n  {\n    return std::make_tuple(std::get<BASE+Is>(tup)...);\n  }\n  \n  template <typename ...Args, typename T, int M>\n  auto Concat (std::tuple<SIMD<T,M>, Args...> tup)\n  {\n    constexpr size_t N = std::tuple_size<std::tuple<SIMD<T,M>, Args...>>();\n    \n    if constexpr (N == 1)\n      return get<0>(tup);\n    else\n      {\n        static constexpr size_t N1 = LargestPowerOfTwo(N-1);\n        static constexpr int N2 = N-N1;\n        \n        auto SEQ1 = std::make_index_sequence<N1>();\n        auto sub1 = subtuple<0>(tup, SEQ1);\n        \n        auto SEQ2 = std::make_index_sequence<N2>();\n        auto sub2 = subtuple<N1>(tup, SEQ2);\n      \n        auto S1 = Concat(sub1);\n        auto S2 = Concat(sub2);\n        return SIMD<T,S1.Size()+S2.Size()>(S1, S2);\n      }\n  }\n  \n\n  \n}\n\n\nnamespace std\n{\n  // structured binding support\n  template <typename T, int N >\n  struct tuple_size<ngcore::SIMD<T,N>> : std::integral_constant<std::size_t, N> {};\n  template<size_t N, typename T, int M> struct tuple_element<N,ngcore::SIMD<T,M>> { using type = T; };\n}\n\n#endif // NETGEN_CORE_SIMD_GENERIC_HPP\n"
  },
  {
    "path": "libsrc/core/simd_math.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_MATH_HPP\n#define NETGEN_CORE_SIMD_MATH_HPP\n\n#include <tuple>\n\n#ifndef M_PI\n#define M_PI 3.14159265358979323846\n#endif\n\n\nnamespace ngcore\n{\n\n  /*\n    based on:\n    Stephen L. Moshier: Methods and Programs For Mathematical Functions\n    https://www.moshier.net/methprog.pdf\n    \n    CEPHES MATHEMATICAL FUNCTION LIBRARY\n    https://www.netlib.org/cephes/\n  */\n\n  static constexpr double sincof[] = {\n    1.58962301576546568060E-10,\n    -2.50507477628578072866E-8,\n    2.75573136213857245213E-6,\n    -1.98412698295895385996E-4,\n    8.33333333332211858878E-3,\n    -1.66666666666666307295E-1,\n  };\n\n  static constexpr double coscof[6] = {\n    -1.13585365213876817300E-11,\n    2.08757008419747316778E-9,\n    -2.75573141792967388112E-7,\n    2.48015872888517045348E-5,\n    -1.38888888888730564116E-3,\n    4.16666666666665929218E-2,\n  };\n\n\n  // highly accurate on [-pi/4, pi/4]\n  template <int N>\n  auto sincos_reduced (SIMD<double,N> x)\n  {\n    auto x2 = x*x;\n  \n    auto s = ((((( sincof[0]*x2 + sincof[1]) * x2 + sincof[2]) * x2 + sincof[3]) * x2 + sincof[4]) * x2 + sincof[5]);\n    s = x + x*x*x * s;\n\n    auto c = ((((( coscof[0]*x2 + coscof[1]) * x2 + coscof[2]) * x2 + coscof[3]) * x2 + coscof[4]) * x2 + coscof[5]);\n    c = 1.0 - 0.5*x2 + x2*x2*c;\n\n    return std::tuple{ s, c };\n  }\n\n  template <int N>\n  auto sincos (SIMD<double,N> x)\n  {\n    auto y = round((2/M_PI) * x);\n    auto q = lround(y);\n  \n    auto [s1,c1] = sincos_reduced(x - y * (M_PI/2));\n\n    auto s2 = If((q & SIMD<int64_t,N>(1)) == SIMD<int64_t,N>(0), s1,  c1);\n    auto s  = If((q & SIMD<int64_t,N>(2)) == SIMD<int64_t,N>(0), s2, -s2);\n  \n    auto c2 = If((q & SIMD<int64_t,N>(1)) == SIMD<int64_t,N>(0), c1, -s1);\n    auto c  = If((q & SIMD<int64_t,N>(2)) == SIMD<int64_t,N>(0), c2, -c2);\n  \n    return std::tuple{ s, c };\n  }\n\n\n\n\n\n\n  \n  template <int N>\n  SIMD<double,N> exp_reduced (SIMD<double,N> x)\n  {\n    static constexpr double P[] = {\n      1.26177193074810590878E-4,\n      3.02994407707441961300E-2,\n      9.99999999999999999910E-1,\n    };\n  \n    static constexpr double Q[] = {\n      3.00198505138664455042E-6,\n      2.52448340349684104192E-3,\n      2.27265548208155028766E-1,\n      2.00000000000000000009E0,\n    };\n  \n    /*\n    // from:  https://www.netlib.org/cephes/\n    rational approximation for exponential\n    * of the fractional part:\n    * e**x = 1 + 2x P(x**2)/( Q(x**2) - x P(x**2) )\n\n    xx = x * x;\n    px = x * polevl( xx, P, 2 );\n    x =  px/( polevl( xx, Q, 3 ) - px );\n    x = 1.0 + 2.0 * x;\n    */\n\n    auto xx = x*x;\n    auto px = (P[0]*xx + P[1]) * xx + P[2];\n    auto qx = ((Q[0]*xx+Q[1])*xx+Q[2])*xx+Q[3];\n    return 1.0 + 2.0*x * px / (qx- x * px);\n  }  \n\n\n  template <int N>\n  SIMD<double,N> pow2_int64_to_float64(SIMD<int64_t,N> n)\n  {\n    // thx to deepseek\n    \n    // Step 1: Clamp the input to valid exponent range [-1022, 1023]\n    // (We use saturated operations to handle out-of-range values)\n    SIMD<int64_t,N> max_exp(1023);\n    SIMD<int64_t,N> min_exp(-1022);\n    n = If(n > max_exp, max_exp, n);\n    n = If(min_exp > n, min_exp, n);\n\n    // Step 2: Add exponent bias (1023)\n    n = n + SIMD<int64_t,N>(1023);\n\n    // Step 3: Shift to exponent bit position (bit 52)\n    auto shifted_exp = (n << IC<52>());\n  \n    // Step 4: Reinterpret as double\n    return Reinterpret<double> (shifted_exp);\n  }\n\n\n  template <int N>\n  SIMD<double,N> myexp (SIMD<double,N> x)\n  {\n    constexpr double log2 = 0.693147180559945286;  //  log(2.0);\n                     \n    auto r = round(1/log2 * x);\n    auto rI = lround(r);\n    r *= log2;\n  \n    SIMD<double,N> pow2 = pow2_int64_to_float64 (rI);\n    return exp_reduced(x-r) * pow2;\n\n    // maybe better:\n    // x = ldexp( x, n );\n  }\n\n  /*\n  inline auto Test1 (SIMD<double> x)\n  {\n    return myexp(x);\n  }\n\n  inline auto Test2 (SIMD<double> x)\n  {\n    return sincos(x);\n  }\n\n  inline auto Test3 (SIMD<double,4> x)\n  {\n    return myexp(x);\n  }\n\n  inline auto Test4 (SIMD<double,4> x)\n  {\n    return sincos(x);\n  }\n  */\n  \n}\n\n#endif\n"
  },
  {
    "path": "libsrc/core/simd_sse.hpp",
    "content": "#ifndef NETGEN_CORE_SIMD_SSE_HPP\n#define NETGEN_CORE_SIMD_SSE_HPP\n\n/**************************************************************************/\n/* File:   simd_sse.hpp                                                   */\n/* Author: Joachim Schoeberl, Matthias Hochsteger                         */\n/* Date:   25. Mar. 16                                                    */\n/**************************************************************************/\n\n#include <immintrin.h>\n\nnamespace ngcore\n{\n\n  template <>\n  class SIMD<mask64,2>\n  {\n    __m128i mask;\n  public:\n    SIMD (int i)\n      : mask(_mm_cmpgt_epi32(_mm_set1_epi32(i),\n                             _mm_set_epi32(1, 1, 0, 0)))\n    { ; }\n\n    SIMD (bool i0, bool i1) { mask = _mm_set_epi64x(i1?-1:0, i0?-1:0); }\n    \n    SIMD (__m128i _mask) : mask(_mask) { ; }\n    __m128i Data() const { return mask; }\n    static constexpr int Size() { return 2; }\n    static NETGEN_INLINE SIMD<mask64, 2> GetMaskFromBits (unsigned int i);\n  };\n\n  static SIMD<mask64, 2> masks_from_2bits[4] = {\n    _mm_set_epi32 (0,0,0,0), _mm_set_epi32 (0,0,-1,0),\n    _mm_set_epi32 (-1,0,0,0), _mm_set_epi32 (-1,0,-1,0),\n  };\n\n  NETGEN_INLINE SIMD<mask64, 2> SIMD<mask64, 2> :: GetMaskFromBits (unsigned int i)\n  {\n    return masks_from_2bits[i & 3];\n  }\n\n\n  template<>\n  class alignas(16) SIMD<int64_t,2>\n  {\n    __m128i data;\n\n  public:\n    static constexpr int Size() { return 2; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD (int64_t v0, int64_t v1) { data = _mm_set_epi64x(v1,v0); }\n    SIMD (std::array<int64_t, 2> arr)\n        : data{_mm_set_epi64x(arr[1],arr[0])}\n    {}\n\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (int64_t val) { data = _mm_set1_epi64x(val); }\n    SIMD (__m128i _data) { data = _data; }\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<int64_t(int)>>::value, int>::type = 0>\n    SIMD (const T & func)\n    {\n      data = _mm_set_epi64(func(1), func(0));\n    }\n\n    NETGEN_INLINE auto operator[] (int i) const { return ((int64_t*)(&data))[i]; }\n    NETGEN_INLINE __m128i Data() const { return data; }\n    NETGEN_INLINE __m128i & Data() { return data; }\n    // NETGEN_INLINE int64_t Lo() const { return _mm_extract_epi64(data, 0); }\n    // NETGEN_INLINE int64_t Hi() const { return _mm_extract_epi64(data, 1); }\n    NETGEN_INLINE int64_t Lo() const { return ((int64_t*)(&data))[0]; }\n    NETGEN_INLINE int64_t Hi() const { return ((int64_t*)(&data))[1]; }\n    static SIMD FirstInt(int n0=0) { return { n0, n0+1 }; }\n  };\n\n\n\nNETGEN_INLINE SIMD<int64_t,2> operator-(SIMD<int64_t,2> a) { return _mm_sub_epi64(_mm_setzero_si128(), a.Data()); }\nNETGEN_INLINE SIMD<int64_t,2> operator+ (SIMD<int64_t,2> a, SIMD<int64_t,2> b) { return _mm_add_epi64(a.Data(),b.Data()); }\nNETGEN_INLINE SIMD<int64_t,2> operator- (SIMD<int64_t,2> a, SIMD<int64_t,2> b) { return _mm_sub_epi64(a.Data(),b.Data()); }\n\n\n  template<>\n  class alignas(16) SIMD<double,2>\n  {\n    __m128d data;\n\n  public:\n    static constexpr int Size() { return 2; }\n    SIMD () {}\n    SIMD (const SIMD &) = default;\n    SIMD (double v0, double v1) { data = _mm_set_pd(v1,v0); }\n    SIMD (SIMD<double,1> v0, SIMD<double,1> v1)\n        : data{_mm_set_pd(v0.Data(), v1.Data())}\n    { }\n    SIMD (std::array<double, 2> arr)\n        : data{_mm_set_pd(arr[1], arr[0])}\n    {}\n\n    SIMD & operator= (const SIMD &) = default;\n\n    SIMD (double val) { data = _mm_set1_pd(val); }\n    SIMD (int val)    { data = _mm_set1_pd(val); }\n    SIMD (size_t val) { data = _mm_set1_pd(val); }\n\n    SIMD (double const * p) { data = _mm_loadu_pd(p); }\n    SIMD (double const * p, SIMD<mask64,2> mask)\n      {\n#ifdef __AVX__\n        data = _mm_maskload_pd(p, mask.Data());\n#else\n        // this versions segfaults if p points to the last allowed element\n        // happened on Mac with the new SparseCholesky-factorization\n        // data = _mm_and_pd(_mm_castsi128_pd(mask.Data()), _mm_loadu_pd(p));\n        auto pmask = (int64_t*)&mask;\n        data = _mm_set_pd (pmask[1] ? p[1] : 0.0, pmask[0] ? p[0] : 0.0);\n#endif\n      }\n    SIMD (__m128d _data) { data = _data; }\n\n    void Store (double * p) { _mm_storeu_pd(p, data); }\n    void Store (double * p, SIMD<mask64,2> mask)\n    {\n#ifdef __AVX__\n      _mm_maskstore_pd(p, mask.Data(), data);\n#else\n      /*\n      _mm_storeu_pd (p, _mm_or_pd (_mm_and_pd(_mm_castsi128_pd(mask.Data()), data),\n                                   _mm_andnot_pd(_mm_castsi128_pd(mask.Data()), _mm_loadu_pd(p))));\n      */\n      auto pmask = (int64_t*)&mask;\n      if (pmask[0]) p[0] = (*this)[0];\n      if (pmask[1]) p[1] = (*this)[1];\n#endif\n    }\n\n    template<typename T, typename std::enable_if<std::is_convertible<T, std::function<double(int)>>::value, int>::type = 0>\n    SIMD (const T & func)\n    {\n      data = _mm_set_pd(func(1), func(0));\n    }\n\n    NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }\n    NETGEN_INLINE __m128d Data() const { return data; }\n    NETGEN_INLINE __m128d & Data() { return data; }\n\n    template <int I>\n    double Get() const\n    {\n      static_assert(I>=0 && I<2, \"Index out of range\");\n      return (*this)[I];\n    }\n\n    double Lo() const { return Get<0>(); } \n    double Hi() const { return Get<1>(); } \n    \n    operator std::tuple<double&,double&> ()\n    {\n      auto pdata = (double*)&data;\n      return std::tuple<double&,double&>(pdata[0], pdata[1]);\n    }\n  };\n\n  NETGEN_INLINE SIMD<double,2> operator- (SIMD<double,2> a) { return _mm_xor_pd(a.Data(), _mm_set1_pd(-0.0)); }\n  NETGEN_INLINE SIMD<double,2> operator+ (SIMD<double,2> a, SIMD<double,2> b) { return _mm_add_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,2> operator- (SIMD<double,2> a, SIMD<double,2> b) { return _mm_sub_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,2> operator* (SIMD<double,2> a, SIMD<double,2> b) { return _mm_mul_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,2> operator/ (SIMD<double,2> a, SIMD<double,2> b) { return _mm_div_pd(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<double,2> operator* (double a, SIMD<double,2> b) { return _mm_set1_pd(a)*b; }\n  NETGEN_INLINE SIMD<double,2> operator* (SIMD<double,2> b, double a) { return _mm_set1_pd(a)*b; }\n\n  template<>\n  NETGEN_INLINE auto Unpack (SIMD<double,2> a, SIMD<double,2> b)\n  {\n    return std::make_tuple(SIMD<double,2>(_mm_unpacklo_pd(a.Data(),b.Data())),\n                      SIMD<double,2>(_mm_unpackhi_pd(a.Data(),b.Data())));\n  }\n\n  NETGEN_INLINE __m128d my_mm_hadd_pd(__m128d a, __m128d b) {\n#if defined(__SSE3__) || defined(__AVX__)\n    return _mm_hadd_pd(a,b);\n#else\n    return _mm_add_pd( _mm_unpacklo_pd(a,b), _mm_unpackhi_pd(a,b) );\n#endif\n  }\n\n#ifndef __AVX__\n  NETGEN_INLINE __m128i my_mm_cmpgt_epi64(__m128i a, __m128i b) {\n    auto  res_lo = _mm_cvtsi128_si64(a)  > _mm_cvtsi128_si64(b) ? -1:0;\n    auto  res_hi = _mm_cvtsi128_si64(_mm_srli_si128(a,8)) > _mm_cvtsi128_si64(_mm_srli_si128(b,8)) ? -1 : 0;\n    return _mm_set_epi64x(res_hi,res_lo);\n  }\n#else\n  NETGEN_INLINE __m128i my_mm_cmpgt_epi64(__m128i a, __m128i b) {\n    return _mm_cmpgt_epi64(a,b);\n  }\n#endif\n\n\n  NETGEN_INLINE SIMD<double,2> sqrt (SIMD<double,2> a) { return _mm_sqrt_pd(a.Data()); }\n  NETGEN_INLINE SIMD<double,2> fabs (SIMD<double,2> a) { return _mm_max_pd(a.Data(), (-a).Data()); }\n  using std::floor;\n  NETGEN_INLINE SIMD<double,2> floor (SIMD<double,2> a)\n  { return ngcore::SIMD<double,2>([&](int i)->double { return floor(a[i]); } ); }\n  using std::ceil;\n  NETGEN_INLINE SIMD<double,2> ceil (SIMD<double,2> a)\n  { return ngcore::SIMD<double,2>([&](int i)->double { return ceil(a[i]); } ); }\n\n  NETGEN_INLINE SIMD<mask64,2> operator<= (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmple_pd(a.Data(),b.Data())); }\n  NETGEN_INLINE SIMD<mask64,2> operator< (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmplt_pd(a.Data(),b.Data())); }\n  NETGEN_INLINE SIMD<mask64,2> operator>= (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmpge_pd(a.Data(),b.Data())); }\n  NETGEN_INLINE SIMD<mask64,2> operator> (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmpgt_pd(a.Data(),b.Data())); }\n  NETGEN_INLINE SIMD<mask64,2> operator== (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmpeq_pd(a.Data(),b.Data())); }\n  NETGEN_INLINE SIMD<mask64,2> operator!= (SIMD<double,2> a , SIMD<double,2> b)\n  { return _mm_castpd_si128( _mm_cmpneq_pd(a.Data(),b.Data())); }\n\n#ifdef __SSE4_2__  \n  NETGEN_INLINE SIMD<mask64,2> operator<= (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  _mm_xor_si128(_mm_cmpgt_epi64(a.Data(),b.Data()),_mm_set1_epi32(-1)); }\n  NETGEN_INLINE SIMD<mask64,2> operator< (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  my_mm_cmpgt_epi64(b.Data(),a.Data()); }\n  NETGEN_INLINE SIMD<mask64,2> operator>= (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  _mm_xor_si128(_mm_cmpgt_epi64(b.Data(),a.Data()),_mm_set1_epi32(-1)); }\n  NETGEN_INLINE SIMD<mask64,2> operator> (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  my_mm_cmpgt_epi64(a.Data(),b.Data()); }\n#endif\n#ifdef __SSE4_1__  \n  NETGEN_INLINE SIMD<mask64,2> operator== (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  _mm_cmpeq_epi64(a.Data(),b.Data()); }\n  NETGEN_INLINE SIMD<mask64,2> operator!= (SIMD<int64_t,2> a , SIMD<int64_t,2> b)\n  { return  _mm_xor_si128(_mm_cmpeq_epi64(a.Data(),b.Data()),_mm_set1_epi32(-1)); }\n#endif\n\n\n NETGEN_INLINE SIMD<mask64,2> operator&& (SIMD<mask64,2> a, SIMD<mask64,2> b)\n  { return _mm_castpd_si128(_mm_and_pd (_mm_castsi128_pd(a.Data()),_mm_castsi128_pd( b.Data()))); }\n  NETGEN_INLINE SIMD<mask64,2> operator|| (SIMD<mask64,2> a, SIMD<mask64,2> b)\n  { return _mm_castpd_si128(_mm_or_pd (_mm_castsi128_pd(a.Data()), _mm_castsi128_pd(b.Data()))); }\n  NETGEN_INLINE SIMD<mask64,2> operator! (SIMD<mask64,2> a)\n  { return _mm_castpd_si128(_mm_xor_pd (_mm_castsi128_pd(a.Data()),_mm_castsi128_pd( _mm_cmpeq_epi64(a.Data(),a.Data())))); }\n#ifdef __SSE4_1__\n  NETGEN_INLINE SIMD<double,2> If (SIMD<mask64,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  { return _mm_blendv_pd(c.Data(), b.Data(), _mm_castsi128_pd(a.Data())); }\n#else\n  NETGEN_INLINE SIMD<double,2> If (SIMD<mask64,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  {\n    return _mm_or_pd(\n                      _mm_andnot_pd(_mm_castsi128_pd(a.Data()),c.Data()),\n                      _mm_and_pd(b.Data(),_mm_castsi128_pd(a.Data()))\n                      );}\n#endif // __SSE4_1__\n\n  NETGEN_INLINE SIMD<double,2> IfPos (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  { return ngcore::SIMD<double,2>([&](int i)->double { return a[i]>0 ? b[i] : c[i]; }); }\n  NETGEN_INLINE SIMD<double,2> IfZero (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)\n  { return ngcore::SIMD<double,2>([&](int i)->double { return a[i]==0. ? b[i] : c[i]; }); }\n\n\n  NETGEN_INLINE double HSum (SIMD<double,2> sd)\n  {\n    return _mm_cvtsd_f64 (my_mm_hadd_pd (sd.Data(), sd.Data()));\n  }\n\n  NETGEN_INLINE auto HSum (SIMD<double,2> sd1, SIMD<double,2> sd2)\n  {\n    __m128d hv2 = my_mm_hadd_pd(sd1.Data(), sd2.Data());\n    return SIMD<double,2> (hv2);\n    // return SIMD<double,2>(_mm_cvtsd_f64 (hv2),  _mm_cvtsd_f64(_mm_shuffle_pd (hv2, hv2, 3)));\n  }\n\n  NETGEN_INLINE SIMD<int64_t, 2> If(SIMD<mask64, 2> a, SIMD<int64_t, 2> b,\n                             SIMD<int64_t, 2> c) {\n    return _mm_or_si128(\n                        _mm_andnot_si128(a.Data(),c.Data()),\n                        _mm_and_si128(b.Data(),a.Data())\n                        );\n  }\n\n}\n\n#endif // NETGEN_CORE_SIMD_SSE_HPP\n"
  },
  {
    "path": "libsrc/core/statushandler.cpp",
    "content": "#include \"array.hpp\"\n#include \"statushandler.hpp\"\n\n\nnamespace ngcore\n{\n  volatile multithreadt multithread;\n  \n  multithreadt :: multithreadt()\n  {\n    pause =0;\n    testmode = 0;\n    redraw = 0;\n    drawing = 0;\n    terminate = 0;\n    running = 0;\n    percent = 0;\n    task = \"\";\n  }\n\n\n\n  \n  static Array<std::string> msgstatus_stack(0);\n  static Array<double> threadpercent_stack(0);\n  static std::string msgstatus = \"\";\n\n\n  void ResetStatus()\n  {\n    SetStatMsg(\"idle\");\n\n    // for (int i = 0; i < msgstatus_stack.Size(); i++)\n    // delete msgstatus_stack[i];\n    msgstatus_stack.SetSize(0);\n    threadpercent_stack.SetSize(0);\n\n    // multithread.task = \"\";\n    multithread.percent = 100.;\n  }\n\n  void PushStatus(const std::string& s)\n  {\n    msgstatus_stack.Append(s);  \n    SetStatMsg(s);\n    threadpercent_stack.Append(0);\n  }\n  \n  \n  void PopStatus()\n  {\n    if (msgstatus_stack.Size())\n      {\n        if (msgstatus_stack.Size() > 1)\n          // SetStatMsg (*msgstatus_stack.Last());\n          SetStatMsg (msgstatus_stack[msgstatus_stack.Size()-2]);\n        else\n          SetStatMsg (\"\");\n        // delete msgstatus_stack.Last();\n        msgstatus_stack.DeleteLast();\n        threadpercent_stack.DeleteLast();\n        if(threadpercent_stack.Size() > 0)\n          multithread.percent = threadpercent_stack.Last();\n        else\n          multithread.percent = 100.;\n      }\n    else\n      {\n        // PrintSysError(\"PopStatus failed\");\n        ;\n      }\n  }\n  \n\n\n  /*\n    void SetStatMsgF(const MyStr& s)\n    {\n    PrintFnStart(s);\n    SetStatMsg(s);\n    }\n  */\n\n  void SetStatMsg(const std::string& s)\n  {\n    msgstatus = s;\n    multithread.task = msgstatus.c_str();  \n  }\n  \n  void SetThreadPercent(double percent)\n  {\n    multithread.percent = percent;\n    if(threadpercent_stack.Size() > 0)\n      threadpercent_stack.Last() = percent;\n  }\n\n\n  void GetStatus(std::string & s, double & percentage)\n  {\n    if(threadpercent_stack.Size() > 0)\n      percentage = threadpercent_stack.Last();\n    else\n      percentage = multithread.percent;\n    \n    if ( msgstatus_stack.Size() )\n      s = msgstatus_stack.Last();\n    else\n      s = \"idle\";     \n  }\n}\n\n"
  },
  {
    "path": "libsrc/core/statushandler.hpp",
    "content": "#ifndef NETGEN_CORE_STATUSHANDLER\n#define NETGEN_CORE_STATUSHANDLER\n\n#include <string>\n#include \"utils.hpp\"\n\nnamespace ngcore\n{\n  \n  class NGCORE_API multithreadt\n  {\n  public:\n    int pause;\n    int testmode;\n    int redraw;\n    int drawing;\n    int terminate;\n    int running;\n    double percent;\n    const char * task;\n    bool demorunning;\n    std::string * tcl_todo = new std::string(\"\");  // tcl commands set from parallel thread\n    multithreadt();\n  };\n\n  NGCORE_API extern volatile multithreadt multithread;\n\n  \n  extern NGCORE_API void SetStatMsg(const std::string& s);\n\n  extern NGCORE_API void PushStatus(const std::string& s);\n  extern NGCORE_API void PushStatusF(const std::string& s);\n  extern NGCORE_API void PopStatus();\n  extern NGCORE_API void SetThreadPercent(double percent);\n  extern NGCORE_API void GetStatus(std::string & s, double & percentage);\n}\n#endif\n"
  },
  {
    "path": "libsrc/core/symboltable.hpp",
    "content": "#ifndef NETGEN_CORE_SYMBOLTABLE_HPP\n#define NETGEN_CORE_SYMBOLTABLE_HPP\n\n#include <ostream>\n#include <string>\n#include <vector>\n\n#include \"exception.hpp\"\n#include \"ngcore_api.hpp\"\n\nnamespace ngcore\n{\n  /**\n      A symbol table.\n\n      The symboltable provides a mapping from string identifiers\n      to the generic type T. The strings are copied.\n      Complexity by name access is linear, by index is constant.\n  */\n  template <class T>\n  class SymbolTable\n  {\n    std::vector<std::string> names;\n    std::vector<T> data;\n  public:\n    using value_type = T;\n    using reference = typename std::vector<T>::reference;\n    using const_reference = typename std::vector<T>::const_reference;\n\n    /// Creates a symboltable\n    SymbolTable () = default;\n    SymbolTable (const SymbolTable<T> &) = default;\n    SymbolTable (SymbolTable<T> &&) noexcept = default;\n\n    ~SymbolTable() = default;\n\n    SymbolTable& operator=(const SymbolTable<T>&) = default;\n    SymbolTable& operator=(SymbolTable<T>&&) = default;\n\n    template<typename ARCHIVE>\n    auto DoArchive(ARCHIVE& ar)\n      -> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>\n    {\n      ar & names & data;\n    }\n\n    /// INDEX of symbol name, throws exception if unused\n    size_t Index (std::string_view name) const\n    {\n      for (size_t i = 0; i < names.size(); i++)\n        if (names[i] == name) return i;\n      throw RangeException(\"SymbolTable\", name);\n    }\n\n    /// Index of symbol name, returns -1 if unused\n    int CheckIndex (std::string_view name) const\n    {\n      for (int i = 0; i < names.size(); i++)\n        if (names[i] == name) return i;\n      return -1;\n    }\n\n    /// number of identifiers\n    size_t Size() const\n    {\n      return data.size();\n    }\n\n    /// Returns reference to element. exception for unused identifier\n    reference operator[] (std::string_view name)\n    {\n      return data[Index (name)];\n    }\n\n    const_reference operator[] (std::string_view name) const\n    {\n      return data[Index (name)];\n    }\n\n    /// Returns reference to i-th element, range check only in debug build\n    reference operator[] (size_t i)\n    {\n      NETGEN_CHECK_RANGE(i, 0, data.size());\n      return data[i];\n    }\n\n    /// Returns const reference to i-th element, range check only in debug build\n    const_reference operator[] (size_t i) const\n    {\n      NETGEN_CHECK_RANGE(i, 0, data.size());\n      return data[i];\n    }\n\n    /// Returns name of i-th element, range check only in debug build\n    const std::string & GetName (size_t i) const\n    {\n      NETGEN_CHECK_RANGE(i, 0, names.size());\n      return names[i];\n    }\n\n    /// Associates el to the string name, overrides if name is used\n    void Set (std::string_view name, const T & el)\n    {\n      int i = CheckIndex (name);\n      if (i >= 0)\n        data[i] = el;\n      else\n        {\n          data.push_back(el);\n          names.push_back(std::string(name));\n        }\n    }\n\n\n    \n    /*\n    bool Used (const std::string & name) const\n    {\n      return CheckIndex(name) >= 0;\n    }\n    */\n    \n    bool Used (std::string_view name) const\n    {\n      return CheckIndex(name) >= 0;\n    }\n    \n    /// Deletes symboltable\n    inline void DeleteAll ()\n    {\n      names.clear();\n      data.clear();\n    }\n\n    // Adds all elements from other symboltable\n    SymbolTable<T>& Update(const SymbolTable<T>& tbl2)\n    {\n      for (size_t i = 0; i < tbl2.Size(); i++)\n        Set (tbl2.GetName(i), tbl2[i]);\n      return *this;\n    }\n  };\n\n  template <typename T>\n  std::ostream & operator<< (std::ostream & ost, const SymbolTable<T> & st)\n  {\n    for (int i = 0; i < st.Size(); i++)\n      ost << st.GetName(i) << \" : \" << st[i] << std::endl;\n    return ost;\n  }\n} // namespace ngcore\n\n#endif // NETGEN_CORE_SYMBOLTABLE_HPP\n"
  },
  {
    "path": "libsrc/core/table.cpp",
    "content": "/**************************************************************************/\n/* File:   table.cpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   25. Mar. 2000                                                  */\n/**************************************************************************/\n\n/*\n   Abstract data type Table\n*/\n\n#include \"table.hpp\"\n\nnamespace ngcore\n{\n  template <typename TI>\n  size_t * TablePrefixSum2 (FlatArray<TI> entrysize)\n  {\n    size_t size  = entrysize.Size();\n    size_t * index = new size_t[size+1];\n\n    if (entrysize.Size() < 100)\n      {\n        size_t mysum = 0;\n        for (size_t i = 0; i < entrysize.Size(); i++)\n          {\n            index[i] = mysum;\n            mysum += entrysize[i];\n          }\n        index[entrysize.Size()] = mysum;\n        return index;\n      }\n\n    \n    Array<size_t> partial_sums(TaskManager::GetNumThreads()+1);\n    partial_sums[0] = 0;\n    ParallelJob\n      ([&] (TaskInfo ti)\n       {\n         IntRange r = IntRange(size).Split(ti.task_nr, ti.ntasks);\n         size_t mysum = 0;\n         for (size_t i : r)\n           mysum += entrysize[i];\n         partial_sums[ti.task_nr+1] = mysum;\n       });\n\n    for (size_t i = 1; i < partial_sums.Size(); i++)\n      partial_sums[i] += partial_sums[i-1];\n\n    ParallelJob\n      ([&] (TaskInfo ti)\n       {\n         IntRange r = IntRange(size).Split(ti.task_nr, ti.ntasks);\n         size_t mysum = partial_sums[ti.task_nr];\n         for (size_t i : r)\n           {\n             index[i] = mysum;\n             mysum += entrysize[i];\n           }\n       });\n    index[size] = partial_sums.Last();\n\n    return index;\n  }\n\n  NGCORE_API size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize)\n  { return TablePrefixSum2 (entrysize); }\n  NGCORE_API size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize)\n  { return TablePrefixSum2 (entrysize); }\n\n  /*\n  BaseDynamicTable :: BaseDynamicTable (int size)\n    : data(size)\n  {\n    for (int i = 0; i < size; i++)\n      {\n\tdata[i].maxsize = 0;\n\tdata[i].size = 0;\n\tdata[i].col = NULL;\n      }\n    oneblock = NULL;\n  }\n\n  BaseDynamicTable :: BaseDynamicTable (const Array<int> & entrysizes, int elemsize)\n    : data(entrysizes.Size())\n  {\n    int cnt = 0;\n    int n = entrysizes.Size();\n\n    for (int i = 0; i < n; i++)\n      cnt += entrysizes[i];\n    oneblock = new char[elemsize * cnt];\n\n    cnt = 0;\n    for (int i = 0; i < n; i++)\n      {\n\tdata[i].maxsize = entrysizes[i];\n\tdata[i].size = 0;\n\n\tdata[i].col = &oneblock[elemsize * cnt];\n\tcnt += entrysizes[i];\n      }\n  }\n\n  BaseDynamicTable :: ~BaseDynamicTable ()\n  {\n    if (oneblock)\n      delete [] oneblock;\n    else\n      for (int i = 0; i < data.Size(); i++)\n\tdelete [] static_cast<char*> (data[i].col);\n  }\n\n  void BaseDynamicTable :: SetSize (int size)\n  {\n    for (int i = 0; i < data.Size(); i++)\n      delete [] static_cast<char*> (data[i].col);\n\n    data.SetSize(size);\n    for (int i = 0; i < size; i++)\n      {\n\tdata[i].maxsize = 0;\n\tdata[i].size = 0;\n\tdata[i].col = NULL;\n      }\n  }\n\n  void BaseDynamicTable :: IncSize (IndexType i, int elsize)\n  {\n    if (i < 0 || i >= data.Size())\n      {\n        std::cerr << \"BaseDynamicTable::Inc: Out of range, i = \" << i << \", size = \" << data.Size() << std::endl;\n\treturn;\n      }\n\n    linestruct & line = data[i];\n\n    if (line.size == line.maxsize)\n      {\n\tvoid * p = new char [(2*line.maxsize+5) * elsize];\n\n\tmemcpy (p, line.col, line.maxsize * elsize);\n\tdelete [] static_cast<char*> (line.col);\n\tline.col = p;\n\tline.maxsize = 2*line.maxsize+5;\n      }\n\n    line.size++;\n  }\n\n  void BaseDynamicTable :: DecSize (IndexType i)\n  {\n    if (i < 0 || i >= data.Size())\n      {\n        std::cerr << \"BaseDynamicTable::Dec: Out of range\" << std::endl;\n\treturn;\n      }\n\n    linestruct & line = data[i];\n\n    if (line.size == 0)\n      {\n        std::cerr << \"BaseDynamicTable::Dec: EntrySize < 0\" << std::endl;\n\treturn;\n      }\n\n    line.size--;\n  }\n  */\n\n  void FilteredTableCreator::Add (size_t blocknr, int data)\n  {\n    if (!takedofs||takedofs->Test(data))\n      TableCreator<int>::Add(blocknr,data);\n  }\n\n  void FilteredTableCreator::Add (size_t blocknr, IntRange range)\n  {\n    for (size_t i=range.First(); i<range.Next();i++)\n      if (!takedofs||takedofs->Test(i))\n\tTableCreator<int>::Add(blocknr,i);\n  }  \n  \n  void FilteredTableCreator::Add (size_t blocknr, FlatArray<int> dofs)\n  {\n    for (size_t i = 0; i < dofs.Size(); i++)\n      if (!takedofs||takedofs->Test(dofs[i]))\n\tTableCreator<int>::Add(blocknr,dofs[i]);\n  }  \n\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/table.hpp",
    "content": "#ifndef NETGEN_CORE_TABLE_HPP\n#define NETGEN_CORE_TABLE_HPP\n\n/**************************************************************************/\n/* File:   table.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   25. Mar. 2000                                                  */\n/**************************************************************************/\n\n#include <atomic>\n#include <iostream>\n#include <optional>\n\n#include \"array.hpp\"\n#include \"bitarray.hpp\"\n#include \"memtracer.hpp\"\n#include \"ngcore_api.hpp\"\n#include \"profiler.hpp\"\n\n\nnamespace ngcore\n{\n\n\n  template <class T, class IndexType = size_t>\n  class FlatTable\n  {\n  protected:\n    static constexpr IndexType BASE = IndexBASE<IndexType>();  \n    /// number of rows\n    size_t size;\n    /// pointer to first in row\n    size_t * index;\n    /// array of data\n    T * data;\n\n  public:\n    FlatTable() = delete;\n    FlatTable (const FlatTable &) = default;\n    \n    NETGEN_INLINE FlatTable(size_t as, size_t * aindex, T * adata)\n      : size(as), index(aindex), data(adata) { ; }\n\n    /// Size of table\n    NETGEN_INLINE size_t Size() const { return size; }\n\n    /// Access entry\n    NETGEN_INLINE const FlatArray<T> operator[] (IndexType i) const\n    {\n      return FlatArray<T> (index[i-BASE+1]-index[i-BASE], data+index[i-BASE]);\n    }\n\n    NETGEN_INLINE T * Data() const { return data; }\n\n    NETGEN_INLINE FlatArray<T> AsArray() const\n    {\n      return FlatArray<T> (index[size]-index[0], data+index[0]);\n    }\n\n    NETGEN_INLINE FlatArray<size_t> IndexArray() const\n    {\n      return FlatArray<size_t, IndexType> (size+1, index);\n    }\n\n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE FlatTable<T> Range (size_t start, size_t end) const\n    {\n      return FlatTable<T> (end-start, index+start-BASE, data);\n    }\n\n    /// takes range starting from position start of end-start elements\n    NETGEN_INLINE FlatTable<T> Range (T_Range<size_t> range) const\n    {\n      return FlatTable<T> (range.Size(), index+range.First()-BASE, data);\n    }\n\n    NETGEN_INLINE T_Range<IndexType> Range () const\n    {\n      return T_Range<IndexType> (BASE, size+BASE);\n    }\n  \n    class Iterator\n    {\n      const FlatTable & tab;\n      size_t row;\n    public:\n      Iterator (const FlatTable & _tab, size_t _row) : tab(_tab), row(_row) { ; }\n      Iterator & operator++ () { ++row; return *this; }\n      FlatArray<T> operator* () const { return tab[row]; }\n      bool operator!= (const Iterator & it2) { return row != it2.row; }\n    };\n\n    Iterator begin() const { return Iterator(*this, BASE); }\n    Iterator end() const { return Iterator(*this, BASE+size); }\n  };\n\n  /*\n  NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize);\n  NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<size_t> entrysize);\n\n\n  NETGEN_INLINE size_t * TablePrefixSum (FlatArray<unsigned int> entrysize)\n  { return TablePrefixSum32 (entrysize); }\n  NETGEN_INLINE size_t * TablePrefixSum (FlatArray<int> entrysize)\n  { return TablePrefixSum32 (FlatArray<unsigned> (entrysize.Size(), (unsigned int*)(int*)(entrysize.Addr(0)))); }\n  NETGEN_INLINE size_t * TablePrefixSum (FlatArray<std::atomic<int>> entrysize)\n  { return TablePrefixSum32 (FlatArray<unsigned> (entrysize.Size(), (unsigned int*)(std::atomic<int>*)entrysize.Addr(0))); }\n  NETGEN_INLINE size_t * TablePrefixSum (FlatArray<size_t> entrysize)\n  { return TablePrefixSum64 (entrysize); }\n  */\n\n  NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize);\n  NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize);\n\n  template <typename T> // TODO: enable_if T is integral\n  NETGEN_INLINE size_t * TablePrefixSum (FlatArray<T> entrysize)\n  {\n    if constexpr (sizeof(T) == 4)\n      return TablePrefixSum32 ( { entrysize.Size(), (uint32_t*)(void*)entrysize.Addr(0) });\n    else\n      return TablePrefixSum64 ( { entrysize.Size(), (uint64_t*)(void*)entrysize.Addr(0) });\n  }\n  \n\n  /**\n     A compact Table container.\n     A table contains size entries of variable size.\n     The entry sizes must be known at construction.\n  */\n  template <class T, class IndexType = size_t>\n  class Table : public FlatTable<T, IndexType>\n  {\n  protected:\n\n    using FlatTable<T,IndexType>::size;\n    using FlatTable<T,IndexType>::index;\n    using FlatTable<T,IndexType>::data;\n\n  public:\n    ///\n    NETGEN_INLINE Table () : FlatTable<T,IndexType> (0,nullptr,nullptr) { ; }\n    /// Construct table of uniform entrysize\n    NETGEN_INLINE Table (size_t asize, size_t entrysize)\n      : FlatTable<T,IndexType>( asize, new size_t[asize+1], new T[asize*entrysize] )\n    {\n      for (size_t i : IntRange(size+1))\n        index[i] = i*entrysize;\n      mt.Alloc(GetMemUsage());\n    }\n\n    /// Construct table of variable entrysize\n    template <typename TI>\n    NETGEN_INLINE Table (FlatArray<TI,IndexType> entrysize)\n      : FlatTable<T,IndexType> (0, nullptr, nullptr)\n    {\n      size  = entrysize.Size();\n      index = TablePrefixSum (FlatArray<TI> (entrysize.Size(), entrysize.Data()));\n      size_t cnt = index[size];\n      data = new T[cnt];\n      mt.Alloc(GetMemUsage());\n    }\n\n    explicit NETGEN_INLINE Table (const FlatTable<T,IndexType> & tab2)\n      : FlatTable<T,IndexType>(0, nullptr, nullptr)\n    {\n      size = tab2.Size();\n      if (size == 0) return;\n      \n      index = new size_t[size+1];\n      this->IndexArray() = tab2.IndexArray();\n      // for (size_t i = 0; i <= size; i++)\n      // index[i] = tab2.index[i];\n\n      size_t cnt = index[size];\n      data = new T[cnt];\n      this->AsArray() = tab2.AsArray();\n      mt.Alloc(GetMemUsage());\n      /*\n      for (size_t i = 0; i < cnt; i++)\n        data[i] = tab2.data[i];\n      */\n    }\n    \n    explicit NETGEN_INLINE Table (const Table & tab2)\n      : FlatTable<T,IndexType>(0, nullptr, nullptr)\n    {\n      size = tab2.Size();\n      if (size == 0) return;\n      \n      index = new size_t[size+1];\n      for (size_t i = 0; i <= size; i++)\n        index[i] = tab2.index[i];\n\n      size_t cnt = index[size];\n      data = new T[cnt];\n      for (size_t i = 0; i < cnt; i++)\n        data[i] = tab2.data[i];\n\n      mt.Alloc(GetMemUsage());\n    }\n\n    NETGEN_INLINE Table (Table && tab2)\n      : FlatTable<T,IndexType>(0, nullptr, nullptr)\n    {\n      mt = std::move(tab2.mt);\n      Swap (size, tab2.size);\n      Swap (index, tab2.index);\n      Swap (data, tab2.data);\n    }\n\n    template<typename ARCHIVE>\n    auto DoArchive(ARCHIVE& ar)\n    {\n      ar & size;\n      if(size == 0)\n        return;\n      if(ar.Input())\n        {\n          index = new IndexType[size+1];\n          mt.Alloc(sizeof(IndexType) * (size+1));\n        }\n      ar.Do(index, size+1);\n      if(ar.Input())\n        {\n          data = new T[index[size]];\n          mt.Alloc(sizeof(T) * index[size]);\n        }\n      ar.Do(data, index[size]);\n    }\n\n    NETGEN_INLINE Table & operator= (Table && tab2)\n    {\n      mt = std::move(tab2.mt);\n      Swap (size, tab2.size);\n      Swap (index, tab2.index);\n      Swap (data, tab2.data);\n      return *this;\n    }\n\n\n\n    /// Delete data\n    NETGEN_INLINE ~Table ()\n    {\n      mt.Free(GetMemUsage());\n      delete [] data;\n      delete [] index;\n    }\n\n    /// Size of table\n    using FlatTable<T,IndexType>::Size;\n\n    /// number of elements in all rows\n    NETGEN_INLINE size_t NElements() const { return index[size]; }\n\n    using FlatTable<T,IndexType>::operator[];\n\n    NETGEN_INLINE void StartMemoryTracing (int /* mem_id */)\n    {\n      mt.Alloc(GetMemUsage());\n    }\n    const MemoryTracer& GetMemoryTracer() const { return mt; }\n\n  private:\n    NETGEN_INLINE size_t GetMemUsage() const { return size == 0 ? 0 : sizeof(T)*index[size] + sizeof(IndexType) * size+1; }\n    MemoryTracer mt;\n  };\n\n\n  /// Print table\n  template <class T, typename IndexType>\n  inline ostream & operator<< (ostream & s, FlatTable<T,IndexType> table)\n  {\n    for (auto i : table.Range())\n      {\n        s << i << \":\";\n        for (auto el : table[i])\n          s << \" \" << el;\n        s << \"\\n\";\n      }\n    s << std::flush;\n    return s;\n  }\n\n\n\n\n  template <class T, typename IndexType=size_t>\n  class TableCreator\n  {\n  protected:\n    int mode;    // 1 .. cnt, 2 .. cnt entries, 3 .. fill table\n    std::atomic<size_t> nd;\n    Array<std::atomic<int>,IndexType> cnt;\n    Table<T,IndexType> table;\n  public:\n    TableCreator()\n    { nd = 0; mode = 1; }\n    TableCreator (size_t acnt)\n    { nd = acnt; SetMode(2); }\n\n    Table<T,IndexType> MoveTable()\n    {\n      return std::move(table);\n    }\n\n    bool Done () { return mode > 3; }\n    void operator++(int) { SetMode (mode+1); }\n\n    int GetMode () const { return mode; }\n    void SetMode (int amode)\n    {\n      mode = amode;\n      if (mode == 2)\n\t{\n\t  // cnt.SetSize(nd);  // atomic has no copy\n          cnt = Array<std::atomic<int>,IndexType> (nd);\n          for (auto & ci : cnt) ci.store (0, std::memory_order_relaxed);\n\t}\n      if (mode == 3)\n\t{\n          table = Table<T,IndexType> (cnt);\n          // for (auto & ci : cnt) ci = 0;\n          for (auto & ci : cnt) ci.store (0, std::memory_order_relaxed);\n          // cnt = 0;\n\t}\n    }\n\n    void SetSize (size_t _nd)\n    {\n      if (mode == 1)\n        nd = _nd;\n      else\n        {\n          if (nd != _nd)\n            throw Exception (\"cannot change size of table-creator\");\n        }\n    }\n\n    void Add (IndexType blocknr, const T & data)\n    {\n      switch (mode)\n\t{\n\tcase 1:\n          {\n            size_t oldval = nd;\n            while (blocknr-IndexBASE<IndexType>()+1>nd) {\n              nd.compare_exchange_weak (oldval, blocknr-IndexBASE<IndexType>()+1);\n              oldval = nd;\n            }\n            break;\n          }\n\tcase 2:\n\t  cnt[blocknr]++;\n\t  break;\n\tcase 3:\n          int ci = cnt[blocknr]++;\n          table[blocknr][ci] = data;\n\t  break;\n\t}\n    }\n\n\n    void Add (IndexType blocknr, IntRange range)\n    {\n      switch (mode)\n\t{\n\tcase 1:\n          {\n            size_t oldval = nd;\n            while (blocknr+1>nd) {\n              nd.compare_exchange_weak (oldval, blocknr+1);\n              oldval = nd;\n            }\n            break;\n          }\n\tcase 2:\n\t  cnt[blocknr] += range.Size();\n\t  break;\n\tcase 3:\n          size_t ci = ( cnt[blocknr] += range.Size() ) - range.Size();\n\t  for (size_t j = 0; j < range.Size(); j++)\n            table[blocknr][ci+j] = range.First()+j;\n\t  break;\n\t}\n    }\n\n    void Add (IndexType blocknr, const FlatArray<int> & dofs)\n    {\n      switch (mode)\n\t{\n\tcase 1:\n          {\n            size_t oldval = nd;\n            while (blocknr+1>nd) {\n              nd.compare_exchange_weak (oldval, blocknr+1);\n              oldval = nd;\n            }\n            break;\n          }\n\tcase 2:\n\t  cnt[blocknr] += dofs.Size();\n\t  break;\n\tcase 3:\n          size_t ci = ( cnt[blocknr] += dofs.Size() ) - dofs.Size();\n\t  for (size_t j = 0; j < dofs.Size(); j++)\n            table[blocknr][ci+j] = dofs[j];\n\t  break;\n\t}\n    }\n  };\n\n  template <typename TEntry, typename TIndex, typename TRange, typename TFunc>\n  Table<TEntry, TIndex> CreateTable( const TRange & range, const TFunc & func, std::optional< size_t > cnt )\n  {\n      static Timer timer(\"CreateTable\");\n      RegionTimer rt(timer);\n      std::unique_ptr<TableCreator<TEntry, TIndex>> pcreator;\n\n      if(cnt)\n          pcreator = std::make_unique<TableCreator<TEntry, TIndex>>(*cnt);\n      else\n          pcreator = std::make_unique<TableCreator<TEntry, TIndex>>();\n      \n      auto & creator = *pcreator;\n\n      for ( ; !creator.Done(); creator++)\n        ParallelForRange\n          (range, [&] (auto myrange)\n           {\n             for (auto i : myrange)\n               func(creator, i);\n           }, TasksPerThread(4)\n          );\n\n    return creator.MoveTable();\n  }\n\n  template <typename TEntry, typename TIndex, typename TRange, typename TFunc>\n  Table<TEntry, TIndex> CreateSortedTable( const TRange & range, const TFunc & func, std::optional< size_t > cnt )\n  {\n    static Timer timer(\"CreateSortedTable\");\n    RegionTimer rt(timer);\n    Table<TEntry, TIndex> table = CreateTable<TEntry, TIndex>(range, func, cnt);\n    ParallelForRange\n      (table.Range(), [&] (auto myrange)\n       {\n         for (auto i : myrange)\n           QuickSort(table[i]);\n       }, TasksPerThread(4)\n      );\n\n    return table;\n  }\n\n  class NGCORE_API FilteredTableCreator : public TableCreator<int>\n  {\n  protected:\n    const BitArray* takedofs;\n  public:\n    FilteredTableCreator(const BitArray* atakedofs)\n      : TableCreator<int>(), takedofs(atakedofs) { };\n    FilteredTableCreator(int acnt, const BitArray* atakedofs)\n      : TableCreator<int>(acnt),takedofs(atakedofs) { };\n    void SetFilter (const BitArray * atakedofs) { takedofs = atakedofs; } \n    void Add (size_t blocknr, int data);\n    void Add (size_t blocknr, IntRange range);\n    void Add (size_t blocknr, FlatArray<int> dofs);\n  };\n\n  \n\n  \n\n  /**\n     A dynamic table class.\n\n     A DynamicTable contains entries of variable size. Entry sizes can\n     be increased dynamically.\n  */\n  template <class T, class IndexType = size_t>\n  class DynamicTable \n  {\n  protected:\n    static constexpr IndexType BASE = IndexBASE<IndexType>();\n\n    struct linestruct\n    {\n      int size;\n      int maxsize;\n      T * col;\n    };\n\n    Array<linestruct, IndexType> data;\n    T * oneblock = nullptr;\n  \n  public:\n    /// Creates table of size size\n    DynamicTable (int size = 0)\n      : data(size)\n    {\n      for (auto & d : data)\n        {\n          d.maxsize = 0;\n          d.size = 0;\n          d.col = nullptr;\n        }\n      oneblock = nullptr;\n    }\n\n    /// Creates table with a priori fixed entry sizes.\n    DynamicTable (const Array<int, IndexType> & entrysizes, bool setentrysize=false)\n      : data(entrysizes.Size())\n    {\n      size_t cnt = 0;\n      // size_t n = entrysizes.Size();\n      \n      for (auto es : entrysizes)\n        cnt += es;\n      oneblock = new T[cnt];\n      \n      cnt = 0;\n      for (auto i : data.Range())\n        {\n          data[i].maxsize = entrysizes[i];\n          if (setentrysize)\n            data[i].size = entrysizes[i];\n          else\n            data[i].size = 0;\n          data[i].col = &oneblock[cnt];\n          cnt += entrysizes[i];\n        }\n    }\n\n    DynamicTable (DynamicTable && tab2)\n    {\n      Swap (data, tab2.data);\n      Swap (oneblock, tab2.oneblock);\n    }\n\n    ~DynamicTable ()\n    {\n      if (oneblock)\n        delete [] oneblock;\n      else\n        for (auto & d : data)\n          delete [] d.col;\n    }\n    \n    DynamicTable & operator= (DynamicTable && tab2)\n    {\n      Swap (data, tab2.data);\n      Swap (oneblock, tab2.oneblock);\n      return *this;\n    }\n\n    /// Changes Size of table to size, deletes data\n    void SetSize (int size)\n    {\n      for (auto & d : data)\n        delete [] d.col;\n    \n      data.SetSize(size);\n      for (auto & d : data)\n        {\n          d.maxsize = 0;\n          d.size = 0;\n          d.col = nullptr;\n        }\n    }      \n\n    void ChangeSize (size_t size)\n    {\n      if (oneblock)\n        throw Exception (\"cannot change size of oneblock dynamic table\");\n      \n      size_t oldsize = data.Size();\n      if (size == oldsize) \n        return;\n      \n      if (size < oldsize)\n        for (int i = size; i < oldsize; i++)\n          delete [] data[i+BASE].col;\n      \n      data.SetSize(size);\n\n      for (int i = oldsize; i < size; i++)\n        {\n          data[i+BASE].maxsize = 0;\n          data[i+BASE].size = 0;\n          data[i+BASE].col = nullptr;\n        }    \n    }\n    \n\n    \n    ///\n    void IncSize (IndexType i)\n    {\n      NETGEN_CHECK_RANGE(i,BASE,data.Size()+BASE);\n    \n      linestruct & line = data[i];\n    \n      if (line.size == line.maxsize)\n        {\n          T * p;\n          if constexpr (std::is_default_constructible<T>::value)\n            p = new T[(2*line.maxsize+5)];\n          else\n            p = reinterpret_cast<T*>(new char[(2*line.maxsize+5)*sizeof(T)]);\n          for (size_t i = 0; i < line.maxsize; i++)\n            p[i] = std::move(line.col[i]);\n          // memcpy (p, line.col, line.maxsize * sizeof(T));\n          delete [] line.col;\n          line.col = p;\n          line.maxsize = 2*line.maxsize+5;\n        }\n    \n      line.size++;\n    }\n  \n    void DecSize (IndexType i)\n    {\n      NETGEN_CHECK_RANGE(i,BASE,data.Size()+BASE);\n      linestruct & line = data[i];\n    \n#ifdef NETGEN_ENABLE_CHECK_RANGE\n      if (line.size == 0)\n        throw Exception (\"BaseDynamicTable::Dec: EntrySize < 0\");\n#endif\n    \n      line.size--;\n    }\n  \n  \n    /// Inserts element acont into row i. Does not test if already used.\n    void Add (IndexType i, const T & acont)\n    {\n      if (data[i].size == data[i].maxsize)\n        this->IncSize (i);\n      else\n        data[i].size++;\n      data[i].col[data[i].size-1] = acont;\n    }\n  \n    /// Inserts element acont into row i, iff not yet exists.\n    void AddUnique (IndexType i, const T & cont)\n    {\n      int es = EntrySize (i);\n      T * line = data[i].col;\n      for (int j = 0; j < es; j++)\n        if (line[j] == cont)\n          return;\n      Add (i, cont);\n    }\n  \n\n    /// Inserts element acont into row i. Does not test if already used.\n    void AddEmpty (IndexType i)\n    {\n      IncSize (i);\n    }\n  \n    /** Set the nr-th element in the i-th row to acont.\n        Does not check for overflow. */\n    void Set (IndexType i, int nr, const T & acont)\n    {\n      data[i].col[nr] = acont;\n    }\n\n\n    /** Returns the nr-th element in the i-th row.\n        Does not check for overflow. */\n    const T & Get (IndexType i, int nr) const\n    {\n      return data[i].col[nr];\n    }\n  \n  \n    /** Returns pointer to the first element in row i. */\n    const T * GetLine (IndexType i) const\n    {\n      return data[i].col;\n    }\n  \n    /// Returns size of the table.\n    size_t Size () const\n    {\n      return data.Size();\n    }\n\n    auto Range () const\n    {\n      return data.Range();\n    }\n\n    /// Returns size of the i-th row.\n    int EntrySize (IndexType i) const\n    {\n      return data[i].size;\n    }\n\n    ///\n    void DecEntrySize (IndexType i)\n    {\n      DecSize(i);\n    }\n  \n    /// Access entry i\n    FlatArray<T> operator[] (IndexType i)\n    {\n      return FlatArray<T> (data[i].size, data[i].col);\n    }\n  \n    /*\n      typedef const FlatArray<T> ConstFlatArray;\n      /// Access entry i\n      ConstFlatArray operator[] (int i) const\n      { return FlatArray<T> (data[i].size, static_cast<T*> (data[i].col)); }\n    */\n    FlatArray<T> operator[] (IndexType i) const\n    {\n      return FlatArray<T> (data[i].size, data[i].col);\n    }\n  };\n\n\n  /// Print table\n  template <class T>\n  inline ostream & operator<< (ostream & s, const DynamicTable<T> & table)\n  {\n    for (auto i : Range(table))\n      {\n        s << i << \":\";\n        for (int j = 0; j < table[i].Size(); j++)\n          s << \" \" << table[i][j];\n        s << \"\\n\";\n      }\n    s << std::flush;\n    return s;\n  }\n\n\n  //   Helper function to calculate coloring of a set of indices for parallel processing of independent elements/points/etc.\n  //   Assigns a color to each of colors.Size() elements, such that two elements with the same color don't share a common 'dof',\n  //   the mapping from element to dofs is provided by the function getDofs(int) -> iterable<int>\n  //\n  //   Returns the number of used colors\n  template <typename Tmask>\n  int ComputeColoring( FlatArray<int> colors, size_t ndofs, Tmask const & getDofs)\n  {\n    static Timer timer(\"ComputeColoring - \"+Demangle(typeid(Tmask).name())); RegionTimer rt(timer);\n    static_assert(sizeof(unsigned int)==4, \"Adapt type of mask array\");\n    size_t n = colors.Size();\n\n    Array<unsigned int> mask(ndofs);\n\n    size_t colored_blocks = 0;\n\n    // We are coloring with 32 colors at once and use each bit to mask conflicts\n    unsigned int check = 0;\n    unsigned int checkbit = 0;\n\n    int current_color = 0;\n    colors = -1;\n    int maxcolor = 0;\n\n    while(colored_blocks<n)\n    {\n        mask = 0;\n        for (auto i : Range(n) )\n        {\n            if(colors[i]>-1) continue;\n            check = 0;\n            const auto & dofs = getDofs(i);\n\n            // Check if adjacent dofs are already marked by current color\n            for (auto dof : dofs)\n                check|=mask[dof];\n\n            // Did we find a free color?\n            if(check != 0xFFFFFFFF)\n            {\n                checkbit = 1;\n                int color = current_color;\n                // find the actual color, which is free (out of 32)\n                while (check & checkbit)\n                {\n                    color++;\n                    checkbit *= 2;\n                }\n                colors[i] = color;\n                maxcolor = color > maxcolor ? color : maxcolor;\n                colored_blocks++;\n                // mask all adjacent dofs with the found color\n                for (auto dof : dofs)\n                    mask[dof] |= checkbit;\n            }\n        }\n        current_color+=32;\n    }\n    return maxcolor+1;\n  }\n\n\n  typedef DynamicTable<int> IntTable;\n\n} // namespace ngcore\n\n#endif // NETGEN_CORE_TABLE_HPP\n"
  },
  {
    "path": "libsrc/core/taskmanager.cpp",
    "content": "/********************************************************************/\n/* File:   taskmanager.cpp                                          */\n/* Author: M. Hochsterger, J. Schoeberl                             */\n/* Date:   10. Mar. 2015                                            */\n/********************************************************************/\n\n#include <thread>\n#include <atomic>\n#include <mutex>\n#include <chrono>\n\n#include \"concurrentqueue.h\"\n#include \"mpi_wrapper.hpp\"\n#include \"paje_trace.hpp\"\n#include \"profiler.hpp\"\n#include \"taskmanager.hpp\"\n\n#ifdef USE_MKL\n#include <mkl.h>\n#endif\n\n\n\nnamespace ngcore\n{\n  using std::mutex;\n  using std::lock_guard;\n  using std::memory_order_release;\n  using std::memory_order_relaxed;\n  using std::make_tuple;\n\n  TaskManager * task_manager = nullptr;\n  bool TaskManager :: use_paje_trace = false;\n  int TaskManager :: max_threads = getenv(\"NGS_NUM_THREADS\") ? atoi(getenv(\"NGS_NUM_THREADS\")) : std::thread::hardware_concurrency();\n  int TaskManager :: num_threads = 1;\n\n  \n  thread_local int TaskManager :: thread_id = 0;\n  \n  const function<void(TaskInfo&)> * TaskManager::func;\n  const function<void()> * TaskManager::startup_function = nullptr;\n  const function<void()> * TaskManager::cleanup_function = nullptr;\n\n  atomic<int> TaskManager::ntasks;\n  Exception * TaskManager::ex;\n  \n  atomic<int> TaskManager::jobnr;\n  \n  atomic<int> TaskManager::complete[8];   // max nodes\n  atomic<int> TaskManager::done;\n  atomic<int> TaskManager::active_workers;\n  atomic<int> TaskManager::workers_on_node[8];   // max nodes\n\n  \n  int TaskManager::sleep_usecs = 1000;\n  bool TaskManager::sleep = false;\n\n  TaskManager::NodeData *TaskManager::nodedata[8];\n  int TaskManager::num_nodes;\n  \n  static mutex copyex_mutex;\n\n  int EnterTaskManager ()\n  {\n    if (task_manager)\n      {\n        // no task manager started\n        return 0;\n      }\n\n    task_manager = new TaskManager();\n\n    GetLogger(\"TaskManager\")->info(\"task-based parallelization (C++11 threads) using {} threads\", task_manager->GetNumThreads());\n\n#ifdef USE_NUMA\n    numa_run_on_node (0);\n#endif\n\n#if !defined(WIN32) && !defined(EMSCRIPTEN)\n    // master has maximal priority !\n    int policy;\n    struct sched_param param;\n    pthread_getschedparam(pthread_self(), &policy, &param);\n    param.sched_priority = sched_get_priority_max(policy);\n    pthread_setschedparam(pthread_self(), policy, &param);\n#endif // !defined(WIN32) && !defined(EMSCRIPTEN)\n\n    \n    task_manager->StartWorkers();\n\n    ParallelFor (Range(100), [&] (int i) { ; });    // startup\n    return task_manager->GetNumThreads();\n  }\n\n\n  void ExitTaskManager (int num_threads)\n  {\n    if(num_threads > 0)\n      {\n        task_manager->StopWorkers();\n        delete task_manager;\n        task_manager = nullptr;\n      }\n  }\n\n  void RunWithTaskManager (function<void()> alg)\n  {\n    int num_threads = EnterTaskManager();\n    alg();\n    ExitTaskManager(num_threads);\n  }\n\n\n\n\n  void TaskManager :: SetNumThreads(int amax_threads)\n    { \n      if(task_manager && task_manager->active_workers>0)\n        {\n          std::cerr << \"Warning: can't change number of threads while TaskManager active!\" << std::endl;\n          return;\n        }\n      max_threads = amax_threads;\n    }\n\n\n  TaskManager :: TaskManager()\n    {\n      num_threads = GetMaxThreads();\n      // if (MyMPI_GetNTasks() > 1) num_threads = 1;\n\n#ifdef USE_NUMA\n      numa_available();\n      num_nodes = numa_max_node() + 1;\n      if (num_nodes > num_threads) num_nodes = num_threads;\n\n      for (int j = 0; j < num_nodes; j++)\n        {\n          void * mem = numa_alloc_onnode (sizeof(NodeData), j);\n          nodedata[j] = new (mem) NodeData;\n\t  complete[j] = -1;\n          workers_on_node[j] = 0;          \n        }\n#else\n      num_nodes = 1;\n      nodedata[0] = new NodeData;\n      complete[0] = -1;\n      workers_on_node[0] = 0;\n#endif\n\n      jobnr = 0;\n      done = 0;\n      sleep = false;\n      sleep_usecs = 1000;\n      active_workers = 0;\n\n      static int cnt = 0;\n      if (use_paje_trace)\n          trace = new PajeTrace(num_threads, \"ng\" + ToString(cnt++));\n    }\n\n\n  TaskManager :: ~TaskManager ()\n  {\n    if (use_paje_trace)\n      {\n        delete trace;\n        trace = nullptr;\n      }\n    num_threads = 1;\n#ifdef USE_NUMA\n      for (int j = 0; j < num_nodes; j++)\n          numa_free (nodedata[j], sizeof(NodeData));\n#else\n      delete nodedata[0];\n#endif\n  }\n\n#ifdef WIN32\n  int TaskManager :: GetThreadId()\n  {\n    return thread_id;\n  }\n#endif\n  \n  void TaskManager :: StartWorkers()\n  {\n    done = false;\n\n    for (int i = 1; i < num_threads; i++)\n      {\n        std::thread([this,i]() { this->Loop(i); }).detach();\n      }\n    thread_id = 0;\n    \n    size_t alloc_size = num_threads*NgProfiler::SIZE;\n    NgProfiler::thread_times = new size_t[alloc_size];\n    for (size_t i = 0; i < alloc_size; i++)\n      NgProfiler::thread_times[i] = 0;\n    NgProfiler::thread_flops = new size_t[alloc_size];\n    for (size_t i = 0; i < alloc_size; i++)\n      NgProfiler::thread_flops[i] = 0;\n\n    while (active_workers < num_threads-1)\n      ;\n  }\n\n  static size_t calibrate_init_tsc = GetTimeCounter();\n  typedef std::chrono::system_clock TClock;\n  static TClock::time_point calibrate_init_clock = TClock::now();\n  \n  void TaskManager :: StopWorkers()\n  {\n    done = true;\n    double delta_tsc = GetTimeCounter()-calibrate_init_tsc;\n    double delta_sec = std::chrono::duration<double>(TClock::now()-calibrate_init_clock).count();\n    double frequ = (delta_sec != 0) ? delta_tsc/delta_sec : 2.7e9;\n    \n    // cout << \"cpu frequ = \" << frequ << endl;\n    // collect timings\n    for (size_t i = 0; i < num_threads; i++)\n      for (size_t j = NgProfiler::SIZE; j-- > 0; )\n        {\n          if (!NgProfiler::timers[j].usedcounter) break;\n          NgProfiler::timers[j].tottime += 1.0/frequ * NgProfiler::thread_times[i*NgProfiler::SIZE+j];\n          NgProfiler::timers[j].flops += NgProfiler::thread_flops[i*NgProfiler::SIZE+j];\n        }\n    delete [] NgProfiler::thread_times;\n    NgProfiler::thread_times = NgProfiler::dummy_thread_times.data();\n    delete [] NgProfiler::thread_flops;\n    NgProfiler::thread_flops = NgProfiler::dummy_thread_flops.data();\n    \n    while (active_workers)\n      ;\n  }\n\n  /////////////////////// NEW: nested tasks using concurrent queue\n\n  struct TNestedTask\n  {\n    const function<void(TaskInfo&)> * func;\n    int mynr;\n    int total;\n    int producing_thread;\n    atomic<int> * endcnt;\n\n    TNestedTask () { ; }\n    TNestedTask (const function<void(TaskInfo&)> & _func,\n                 int _mynr, int _total,\n                 atomic<int> & _endcnt, int prod_tid)\n      : func(&_func), mynr(_mynr), total(_total), producing_thread(prod_tid), endcnt(&_endcnt)\n    {\n      ;\n    }\n  };\n\n  typedef moodycamel::ConcurrentQueue<TNestedTask> TQueue; \n  typedef moodycamel::ProducerToken TPToken; \n  typedef moodycamel::ConsumerToken TCToken; \n  \n  static TQueue taskqueue;\n\n  void AddTask (const function<void(TaskInfo&)> & afunc,\n                atomic<int> & endcnt)\n                \n  {\n    TPToken ptoken(taskqueue); \n\n    int num = endcnt;\n    auto tid = TaskManager::GetThreadId();\n    for (int i = 0; i < num; i++)\n      taskqueue.enqueue (ptoken, { afunc, i, num, endcnt, tid });\n  }\n\n  bool TaskManager :: ProcessTask()\n  {\n    // static Timer t(\"process task\");\n    TNestedTask task;\n    TCToken ctoken(taskqueue); \n    \n    if (taskqueue.try_dequeue(ctoken, task))\n      {\n        TaskInfo ti;\n        ti.task_nr = task.mynr;\n        ti.ntasks = task.total;\n        ti.thread_nr = TaskManager::GetThreadId();\n        ti.nthreads = TaskManager::GetNumThreads();\n        /*\n        {\n          lock_guard<mutex> guard(m);\n          cout << \"process nested, nr = \" << ti.task_nr << \"/\" << ti.ntasks << endl;\n        }\n        */\n        // if(trace && task.producing_thread != ti.thread_nr)\n        // trace->StartTask (ti.thread_nr, t, PajeTrace::Task::ID_TIMER, task.producing_thread);\n\n        (*task.func)(ti);\n        --*task.endcnt;\n\n        // if(trace && task.producing_thread != ti.thread_nr)\n        // trace->StopTask (ti.thread_nr, t);\n        return true;\n      }\n    return false;\n  }\n\n\n  void TaskManager :: CreateJob (const function<void(TaskInfo&)> & afunc,\n                                 int antasks)\n  {\n    if (num_threads == 1 || !task_manager) //  || func)\n      {\n        if (startup_function) (*startup_function)();\n        \n        TaskInfo ti;\n        ti.ntasks = antasks;\n        ti.thread_nr = 0; ti.nthreads = 1;\n        // ti.node_nr = 0; ti.nnodes = 1;\n        for (ti.task_nr = 0; ti.task_nr < antasks; ti.task_nr++)\n          afunc(ti);\n\n        if (cleanup_function) (*cleanup_function)();        \n        return;\n      }\n\n\n    if (func)\n      { // we are already parallel, use nested tasks\n        // startup for inner function not supported ...\n        // if (startup_function) (*startup_function)();\n\n        if (antasks == 1)\n          {\n            TaskInfo ti;\n            ti.task_nr = 0;\n            ti.ntasks = 1;\n            ti.thread_nr = 0; ti.nthreads = 1;\n            afunc(ti);\n            return;\n          }\n        \n        atomic<int> endcnt(antasks);\n        AddTask (afunc, endcnt);\n        while (endcnt > 0)\n          {\n            ProcessTask();\n          }\n        \n        // if (cleanup_function) (*cleanup_function)();\n        return;\n      }\n\n\n    class StartStop\n    {\n    public:\n      StartStop(const function<void(TaskInfo&)> & afunc)\n      {\n        if (trace)\n          trace->StartJob(jobnr, afunc.target_type());\n      }\n      ~StartStop()\n      {\n        if (trace)\n          trace->StopJob();\n      }\n    };\n    \n    if (antasks == 1)\n      {\n        StartStop startstop(afunc);\n        //if (trace)\n        // trace->StartJob(jobnr, afunc.target_type());\n        jobnr++;\n        if (startup_function) (*startup_function)();\n        TaskInfo ti;\n        ti.task_nr = 0;\n        ti.ntasks = 1;\n        ti.thread_nr = 0; ti.nthreads = 1;\n        {\n          RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr);\n          afunc(ti);\n        }\n        if (cleanup_function) (*cleanup_function)();\n        // if (trace)\n        // trace->StopJob();\n        return;\n      }\n\n    StartStop startstop(afunc);    \n    // if (trace)\n    // trace->StartJob(jobnr, afunc.target_type());\n\n    func = &afunc;\n\n    ntasks.store (antasks); // , memory_order_relaxed);\n    ex = nullptr;\n\n\n    nodedata[0]->start_cnt.store (0, memory_order_relaxed);\n\n    jobnr++;\n    \n    for (int j = 0; j < num_nodes; j++)\n      nodedata[j]->participate |= 1;\n\n    if (startup_function) (*startup_function)();\n    \n    int thd = 0;\n    int thds = GetNumThreads();\n    int mynode = num_nodes * thd/thds;\n\n    IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes);\n    NodeData & mynode_data = *(nodedata[mynode]);\n\n    TaskInfo ti;\n    ti.nthreads = thds;\n    ti.thread_nr = thd;\n    // ti.nnodes = num_nodes;\n    // ti.node_nr = mynode;\n\n    try\n      {\n        while (1)\n          {\n            int mytask = mynode_data.start_cnt++;\n            if (mytask >= mytasks.Size()) break;\n            \n            ti.task_nr = mytasks.First()+mytask;\n            ti.ntasks = ntasks;\n\n            {\n              RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr);\n              (*func)(ti); \n            }\n          }\n\n      }\n    catch (Exception & e)\n      {\n        {\n          lock_guard<mutex> guard(copyex_mutex);\n          delete ex;\n          ex = new Exception (e);\n          mynode_data.start_cnt = mytasks.Size();\n        }\n      }\n\n    if (cleanup_function) (*cleanup_function)();\n    \n    for (int j = 0; j < num_nodes; j++)\n      if (workers_on_node[j])\n        {\n          while (complete[j] != jobnr)\n          {\n#ifdef NETGEN_ARCH_AMD64\n            _mm_pause();\n#endif // NETGEN_ARCH_AMD64\n          }\n        }\n\n    func = nullptr;\n    if (ex)\n      throw Exception (*ex);\n\n    // if (trace)\n    //    trace->StopJob();\n  }\n    \n  void TaskManager :: Loop(int thd)\n  {\n    /*\n    static Timer tADD(\"add entry counter\");\n    static Timer tCASready1(\"spin-CAS ready tick1\");\n    static Timer tCASready2(\"spin-CAS ready tick2\");\n    static Timer tCASyield(\"spin-CAS yield\");\n    static Timer tCAS1(\"spin-CAS wait\");\n    static Timer texit(\"exit zone\");\n    static Timer tdec(\"decrement\");\n    */\n    thread_id = thd;\n\n    int thds = GetNumThreads();\n\n    int mynode = num_nodes * thd/thds;\n\n    NodeData & mynode_data = *(nodedata[mynode]);\n\n\n\n    TaskInfo ti;\n    ti.nthreads = thds;\n    ti.thread_nr = thd;\n    // ti.nnodes = num_nodes;\n    // ti.node_nr = mynode;\n\n      \n#ifdef USE_NUMA\n    numa_run_on_node (mynode);\n#endif\n    active_workers++;\n    workers_on_node[mynode]++;\n    int jobdone = 0;\n\n\n#ifdef USE_MKL\n    auto mkl_max = mkl_get_max_threads();\n    mkl_set_num_threads_local(1);\n#endif\n\n    \n    size_t no_job_counter = 0;\n    while (!done)\n      {\n        if (complete[mynode] > jobdone)\n          jobdone = complete[mynode];\n\n        if (jobnr == jobdone)\n          {\n            no_job_counter++;\n            // RegionTracer t(ti.thread_nr, tCASyield, ti.task_nr);\n            while (ProcessTask()) no_job_counter = 0; // do the nested tasks\n                   \n            if(sleep)\n              std::this_thread::sleep_for(std::chrono::microseconds(sleep_usecs));\n            else if(no_job_counter > 30000)\n              std::this_thread::sleep_for(std::chrono::microseconds(1000));\n            else if(no_job_counter > 20000)\n              std::this_thread::sleep_for(std::chrono::microseconds(100));\n            else if(no_job_counter > 10000)\n              std::this_thread::sleep_for(std::chrono::microseconds(10));\n            else\n              {\n#ifdef WIN32\n                std::this_thread::yield();\n#else  // WIN32\n                sched_yield();\n#endif // WIN32\n              }\n            continue;\n          }\n\n        {\n          // RegionTracer t(ti.thread_nr, tADD, ti.task_nr);\n\n          // non-atomic fast check ...\n          if ( (mynode_data.participate & 1) == 0) continue;\n\n          int oldval = mynode_data.participate += 2;\n          if ( (oldval & 1) == 0)\n            { // job not active, going out again\n              mynode_data.participate -= 2;\n              continue;\n            }\n        }\n\n        if (startup_function) (*startup_function)();\n        \n        IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes);\n          \n        try\n          {\n            \n            while (1)\n              {\n                if (mynode_data.start_cnt >= mytasks.Size()) break;\n\t\tint mytask = mynode_data.start_cnt.fetch_add(1, memory_order_relaxed);\n                if (mytask >= mytasks.Size()) break;\n                \n                ti.task_nr = mytasks.First()+mytask;\n                ti.ntasks = ntasks;\n                no_job_counter = 0;\n                \n                {\n                  RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr);\n                  (*func)(ti);\n                }\n              }\n\n          }\n        catch (Exception & e)\n          {\n            {\n              // cout << \"got exception in TM\" << endl; \n              lock_guard<mutex> guard(copyex_mutex);\n              delete ex;\n              ex = new Exception (e);\n              mynode_data.start_cnt = mytasks.Size();\n            }\n          }\n\n#ifndef __MIC__\n        atomic_thread_fence (memory_order_release);     \n#endif // __MIC__\n\n        if (cleanup_function) (*cleanup_function)();\n\n        jobdone = jobnr;\n\n        mynode_data.participate-=2;\n\n\t{\n\t  int oldpart = 1;\n\t  if (mynode_data.participate.compare_exchange_strong (oldpart, 0))\n\t    {\n              if (jobdone < jobnr.load())\n                { // reopen gate\n                  mynode_data.participate |= 1;                  \n                }\n              else\n                {\n                  if (mynode != 0)\n                    mynode_data.start_cnt = 0;\n                  complete[mynode] = jobnr.load(); \n                }\n\t    }\t      \n\t}\n      }\n    \n\n#ifdef USE_MKL\n    mkl_set_num_threads_local(mkl_max);\n#endif\n\n    workers_on_node[mynode]--;\n    active_workers--;\n  }\n\n\n  std::list<std::tuple<std::string,double>> TaskManager :: Timing ()\n  {\n    /*\n    list<tuple<string,double>>timings;\n    double time =\n      RunTiming\n      ( [&] ()\n        {\n          ParallelJob ( [] (TaskInfo ti) { ; } ,\n                        TasksPerThread(1) );\n        });\n    timings.push_back (make_tuple(\"parallel job with 1 task per thread\", time*1e9));\n    \n    time =\n      RunTiming\n      ( [&] ()\n        {\n          ParallelJob ( [] (TaskInfo ti) { ; } ,\n                        TasksPerThread(10) );\n        });\n    timings.push_back (make_tuple(\"parallel job with 10 tasks per thread\", time*1e9));\n\n    time =\n      RunTiming\n      ( [&] ()\n        {\n          ParallelJob ( [] (TaskInfo ti) { ; } ,\n                        TasksPerThread(100) );\n        });\n    timings.push_back (make_tuple(\"parallel job with 100 tasks per thread\", time*1e9));\n\n    return timings;\n    */\n\n\n    \n    // this is the old function moved from the py-interface:\n    std::list<std::tuple<std::string,double>>timings;           \n    double starttime, time;\n    double maxtime = 0.5;\n    size_t steps;\n    \n    starttime = WallTime();\n    steps = 0;\n    do\n      {\n        for (size_t i = 0; i < 1000; i++)\n          ParallelJob ( [] (TaskInfo ti) { ; },\n                        TasksPerThread(1));\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"ParallelJob 1 task/thread\", time/steps*1e9));\n\n\n    starttime = WallTime();\n    steps = 0;\n    do\n      {\n        for (size_t i = 0; i < 1000; i++)\n          ParallelJob ( [] (TaskInfo ti) { ; },\n                        TasksPerThread(100));\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"ParallelJob 100 task/thread\", time/steps*1e9));\n\n    \n    starttime = WallTime();\n    steps = 0;\n    do\n      {\n        for (int k = 0; k < 10000; k++)\n          {\n            SharedLoop2 sl(1000);\n            steps += 1;\n          }\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"SharedLoop init\", time/steps*1e9));\n    \n    starttime = WallTime();\n    steps = 0;\n    do\n      {\n        for (int k = 0; k < 1000; k++)\n          {\n            SharedLoop sl(5);\n            ParallelJob ( [&sl] (TaskInfo ti)\n                          {\n                            for (auto i : sl)\n                              (void)i;  // silence warning\n                          } );\n          }\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"short SharedLoop\", time/steps*1e9));\n    \n\n    starttime = WallTime();\n    steps = 0;\n    do\n      {\n        for (int k = 0; k < 1000; k++)\n          {\n            SharedLoop sl1(5), sl2(5), sl3(5), sl4(5), sl5(5);\n            ParallelJob ( [&sl1, &sl2, &sl3, &sl4, &sl5] (TaskInfo ti)\n                          {\n                            for (auto i : sl1)\n                              (void)i;  // silence warning\n                            for (auto i : sl2)\n                              (void)i;  // silence warning\n                            for (auto i : sl3)\n                              (void)i;  // silence warning\n                            for (auto i : sl4)\n                              (void)i;  // silence warning\n                            for (auto i : sl5)\n                              (void)i;  // silence warning\n                          } );\n          }\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"5 short SharedLoops\", time/steps*1e9));\n    \n\n    starttime = WallTime();\n    steps = 0;\n    SharedLoop2 sl2(5);\n    do\n      {\n        for (int k = 0; k < 1000; k++)\n          {\n            sl2.Reset(5);\n            ParallelJob ( [&sl2] (TaskInfo ti)\n                          {\n                            for (auto i : sl2)\n                              (void)i;  // silence warning                              \n                          } );\n          }\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"short SharedLoop2\", time/steps*1e9));\n\n    {\n    starttime = WallTime();\n    steps = 0;\n    SharedLoop2 sl1(5), sl2(5), sl3(5), sl4(5), sl5(5);\n    do\n      {\n        for (int k = 0; k < 1000; k++)\n          {\n            sl1.Reset(5);\n            sl2.Reset(5);\n            sl3.Reset(5);\n            sl4.Reset(5);\n            sl5.Reset(5);\n            ParallelJob ( [&sl1,&sl2,&sl3,&sl4,&sl5] (TaskInfo ti)\n                          {\n                            for (auto i : sl1)\n                              (void)i;  // silence warning                              \n                            for (auto i : sl2)\n                              (void)i;  // silence warning                              \n                            for (auto i : sl3)\n                              (void)i;  // silence warning                              \n                            for (auto i : sl4)\n                              (void)i;  // silence warning                              \n                            for (auto i : sl5)\n                              (void)i;  // silence warning                              \n                          } );\n          }\n        steps += 1000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"5 short SharedLoop2\", time/steps*1e9));\n    }\n\n    \n    starttime = WallTime();\n    steps = 0;\n    {\n    SharedLoop2 sl(1000);\n    do\n      {\n        for (int k = 0; k < 1000; k++)\n          {\n            sl.Reset(1000);\n            ParallelJob ( [&sl] (TaskInfo ti)\n                          {\n                            for (auto i : sl)\n                              (void)i;  // silence warning                               \n                          } );\n            steps += 1000;\n          }\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"SharedLoop2 1000, time per iteration\", time/steps*1e9));\n    }\n\n    {\n    starttime = WallTime();\n    steps = 0;\n    SharedLoop2 sl(1000000);\n    do\n      {\n        sl.Reset(1000000);\n        ParallelJob ( [&sl] (TaskInfo ti)\n                      {\n                        for (auto i : sl)\n                          (void)i;  // silence warning\n                      } );\n        steps += 1000000;\n        time = WallTime()-starttime;\n      }\n    while (time < maxtime);\n    timings.push_back(make_tuple(\"SharedLoop2 1000000, time per iteration\", time/steps*1e9));\n    }\n    \n    return timings;\n  }\n  \n}\n"
  },
  {
    "path": "libsrc/core/taskmanager.hpp",
    "content": "#ifndef NETGEN_CORE_TASKMANAGER_HPP\n#define NETGEN_CORE_TASKMANAGER_HPP\n\n/*********************************************************************/\n/* File:   taskmanager.hpp                                           */\n/* Author: M. Hochsterger, J. Schoeberl                              */\n/* Date:   10. Mar. 2015                                             */\n/*********************************************************************/\n\n#include <atomic>\n#include <functional>\n#include <list>\n#include <cmath>\n#include <ostream>\n#include <thread>\n\n#include \"array.hpp\"\n#include \"paje_trace.hpp\"\n#include \"taskmanager.hpp\"\n\n#ifdef USE_NUMA\n#include <numa.h>\n#include <sched.h>\n#endif\n\n\nnamespace ngcore\n{\n  using std::atomic;\n  using std::function;\n\n  class TaskInfo\n  {\n  public:\n    int task_nr;\n    int ntasks;\n\n    int thread_nr;\n    int nthreads;\n\n    // int node_nr;\n    // int nnodes;\n  };\n\n  NGCORE_API extern class TaskManager * task_manager;\n  \n  class TaskManager\n  {\n//     PajeTrace *trace;\n\n    class alignas(64) NodeData\n    {\n    public:\n      atomic<int> start_cnt{0};\n      atomic<int> participate{0};\n    };\n    \n    NGCORE_API static const function<void(TaskInfo&)> * func;\n    NGCORE_API static const function<void()> * startup_function;\n    NGCORE_API static const function<void()> * cleanup_function;\n    NGCORE_API static atomic<int> ntasks;\n    NGCORE_API static Exception * ex;\n\n    NGCORE_API static atomic<int> jobnr;\n\n    static atomic<int> complete[8];   // max nodes\n    static atomic<int> done;\n    static atomic<int> active_workers;\n    static atomic<int> workers_on_node[8];   // max nodes\n    // Array<atomic<int>*> sync;\n    NGCORE_API static int sleep_usecs;\n    NGCORE_API static bool sleep;\n\n    static NodeData *nodedata[8];\n\n    static int num_nodes;\n    NGCORE_API static int num_threads;\n    NGCORE_API static int max_threads;\n\n\n\n#ifdef WIN32 // no exported thread_local in dlls on Windows\n    static thread_local int thread_id;\n#else\n    NGCORE_API static thread_local int thread_id;\n#endif\n    NGCORE_API static bool use_paje_trace;\n  public:\n    \n    NGCORE_API TaskManager();\n    NGCORE_API ~TaskManager();\n\n\n    NGCORE_API void StartWorkers();\n    NGCORE_API void StopWorkers();\n\n    bool IsSleeping() const { return sleep; }\n\n    int SuspendWorkers(int asleep_usecs = 1000 )\n      {\n        int old_sleep_usecs = sleep_usecs;\n        sleep_usecs = asleep_usecs;\n        sleep = true;\n        return old_sleep_usecs;\n      }\n    void ResumeWorkers() { sleep = false; }\n\n    NGCORE_API static void SetNumThreads(int amax_threads);\n    static int GetMaxThreads() { return max_threads; }\n    // static int GetNumThreads() { return task_manager ? task_manager->num_threads : 1; }\n    static int GetNumThreads() { return num_threads; }\n#ifdef WIN32\n    NGCORE_API static int GetThreadId();\n#else\n    static int GetThreadId() { return thread_id; }\n#endif\n    int GetNumNodes() const { return num_nodes; }\n\n    static void SetPajeTrace (bool use)  { use_paje_trace = use; }\n    \n    NGCORE_API static bool ProcessTask();\n\n    NGCORE_API static void CreateJob (const function<void(TaskInfo&)> & afunc, \n                    int antasks = task_manager->GetNumThreads());\n\n    static void SetStartupFunction (const function<void()> & func) { startup_function = &func; }\n    static void SetStartupFunction () { startup_function = nullptr; }\n    static void SetCleanupFunction (const function<void()> & func) { cleanup_function = &func; }\n    static void SetCleanupFunction () { cleanup_function = nullptr; }    \n\n    void Done() { done = true; }\n    NGCORE_API void Loop(int thread_num);\n\n    NGCORE_API static std::list<std::tuple<std::string,double>> Timing ();\n  };\n\n\n\n\n\n\n\n\n  \n  NGCORE_API void RunWithTaskManager (function<void()> alg);\n\n  // For Python context manager\n  NGCORE_API int  EnterTaskManager ();\n  NGCORE_API void ExitTaskManager (int num_threads);\n\n  class RegionTaskManager\n  {\n    int nthreads_before;\n    int nthreads;\n    bool started_taskmanager;\n\n  public:\n    RegionTaskManager(int anthreads=TaskManager::GetMaxThreads())\n        : nthreads(anthreads)\n    {\n      if(task_manager || nthreads==0)\n        {\n          // already running, no need to do anything\n          started_taskmanager = false;\n          return;\n        }\n      else\n        {\n          nthreads_before = TaskManager::GetMaxThreads();\n          TaskManager::SetNumThreads(nthreads);\n          nthreads = EnterTaskManager();\n          started_taskmanager = true;\n        }\n    }\n\n    ~RegionTaskManager()\n    {\n      if(started_taskmanager)\n        {\n          ExitTaskManager(nthreads);\n          TaskManager::SetNumThreads(nthreads_before);\n        }\n    }\n  };\n\n  class SuspendTaskManager\n  {\n    int old_sleep_usecs = 0;\n    bool old_sleep = false;\n    TaskManager * tm = nullptr;\n\n  public:\n    SuspendTaskManager(int asleep_usecs=1000)\n      : tm(task_manager)\n    {\n      if(!tm)\n          return;\n\n      old_sleep = tm->IsSleeping();\n      old_sleep_usecs = tm->SuspendWorkers(asleep_usecs);\n    }\n\n    ~SuspendTaskManager()\n    {\n      if(!tm)\n          return;\n\n      if(old_sleep) // restore old sleep time\n          tm->SuspendWorkers(old_sleep_usecs);\n      else\n          tm->ResumeWorkers();\n    }\n  };\n\n  NETGEN_INLINE int TasksPerThread (int tpt)\n  {\n    // return task_manager ? tpt*task_manager->GetNumThreads() : 1;\n    return tpt*TaskManager::GetNumThreads();\n  }\n  \n\n  class TotalCosts\n  {\n    size_t cost;\n  public:\n    TotalCosts (size_t _cost) : cost(_cost) { ; }\n    size_t operator ()() { return cost; }\n  };\n\n  template <typename TR, typename TFUNC>\n  NETGEN_INLINE void ParallelFor (T_Range<TR> r, TFUNC f, \n                           int antasks = TaskManager::GetNumThreads(),\n                           TotalCosts costs = 1000)\n  {\n    // if (task_manager && costs() >= 1000)\n\n    TaskManager::CreateJob \n        ([r, f] (TaskInfo & ti) \n         {\n           auto myrange = r.Split (ti.task_nr, ti.ntasks);\n           for (auto i : myrange) f(i);\n         }, \n         antasks);\n\n      /*\n    else\n      for (auto i : r) f(i);\n      */\n  }\n\n  /*\n  template <typename TFUNC>\n  NETGEN_INLINE void ParallelFor (size_t n, TFUNC f, \n                           int antasks = task_manager ? task_manager->GetNumThreads() : 0)\n  {\n    ParallelFor (IntRange (n), f, antasks);\n  }\n  */\n  template <typename ...Args>\n  NETGEN_INLINE void ParallelFor (size_t n, Args...args)\n  {\n    ParallelFor (IntRange (n), args...);\n  }\n  \n  template <typename TR, typename TFUNC>\n  NETGEN_INLINE void ParallelForRange (T_Range<TR> r, TFUNC f, \n                                int antasks = TaskManager::GetNumThreads(),\n                                TotalCosts costs = 1000)\n  {\n    // if (task_manager && costs() >= 1000)\n\n    TaskManager::CreateJob \n        ([r, f] (TaskInfo & ti) \n         {\n           auto myrange = r.Split (ti.task_nr, ti.ntasks);\n           f(myrange);\n         }, \n         antasks);\n    /*\n    else\n      f(r);\n    */\n  }\n\n  /*\n  template <typename TFUNC>\n  NETGEN_INLINE void ParallelForRange (size_t n, TFUNC f, \n                                int antasks = task_manager ? task_manager->GetNumThreads() : 0)\n  {\n    ParallelForRange (IntRange(n), f, antasks);\n  }\n  */\n  template <typename ...Args>\n  NETGEN_INLINE void ParallelForRange (size_t n, Args...args)\n  {\n    ParallelForRange (IntRange(n), args...);\n  }\n  \n  template <typename TFUNC>\n  NETGEN_INLINE void ParallelJob (TFUNC f,\n                           int antasks = TaskManager::GetNumThreads())\n  {\n    TaskManager::CreateJob (f, antasks);\n  }\n\n  \n  /*\n    Usage example:\n\n    ShareLoop myloop(100);\n    task_manager->CreateJob ([]()\n    {\n      for (int i : myloop)\n        cout << \"i = \" << i << endl;\n    });\n\n  */\n  \n  class SharedLoop\n  {\n    atomic<int> cnt;\n    IntRange r;\n\n    \n    class SharedIterator\n    {\n      atomic<int> & cnt;\n      int myval;\n      int endval;\n    public:\n      SharedIterator (atomic<int> & acnt, int aendval, bool begin_iterator) \n        : cnt (acnt)\n      {\n        endval = aendval;\n        myval = begin_iterator ? cnt++ : endval;\n        if (myval > endval) myval = endval;\n      }\n      \n      SharedIterator & operator++ () \n      {\n        myval = cnt++; \n        if (myval > endval) myval = endval;\n        return *this; \n      }\n      \n      int operator* () const { return myval; }\n      bool operator!= (const SharedIterator & it2) const { return myval != it2.myval; }\n    };\n    \n    \n  public:\n    SharedLoop (IntRange ar) : r(ar) { cnt = r.begin(); }\n    SharedLoop (size_t s) : SharedLoop (IntRange{s}) { ; }\n    SharedIterator begin() { return SharedIterator (cnt, r.end(), true); }\n    SharedIterator end()   { return SharedIterator (cnt, r.end(), false); }\n  };\n\n\n  /*\nclass alignas(4096) AtomicRange\n{\n  mutex lock;\n  int begin;\n  int end;\npublic:\n  \n  void Set (IntRange r)\n  {\n    lock_guard<mutex> guard(lock);\n    begin = r.begin();\n    end = r.end();\n  }\n\n  IntRange Get()\n  {\n    lock_guard<mutex> guard(lock);\n    return IntRange(begin, end);\n  }\n\n  bool PopFirst (int & first)\n  {\n    lock_guard<mutex> guard(lock);\n    bool non_empty = end > begin;\n    first = begin;\n    if (non_empty) begin++;\n    return non_empty;\n  }\n\n  bool PopHalf (IntRange & r)\n  {\n    lock_guard<mutex> guard(lock);\n    bool non_empty = end > begin;\n    if (non_empty)\n      {\n        int mid = (begin+end+1)/2;\n        r = IntRange(begin, mid);\n        begin = mid;\n      }\n    return non_empty;\n  }\n};\n*/\n\n\n\n  // lock free popfirst\n  // faster for large loops, bug slower for small loops (~1000) ????\n   /*\n  class alignas(4096) AtomicRange\n{\n  mutex lock;\n  atomic<int> begin;\n  int end;\npublic:\n  \n  void Set (IntRange r)\n  {\n    lock_guard<mutex> guard(lock);\n    // begin = r.begin();\n    begin.store(r.begin(), std::memory_order_relaxed);\n    end = r.end();\n  }\n  \n  void SetNoLock (IntRange r)\n  {\n    begin.store(r.begin(), std::memory_order_relaxed);\n    end = r.end();\n  }\n\n  // IntRange Get()\n  // {\n  //   lock_guard<mutex> guard(lock);\n  //   return IntRange(begin, end);\n  // }\n\n  bool PopFirst (int & first)\n  {\n    // int oldbegin = begin;\n    int oldbegin = begin.load(std::memory_order_relaxed);\n    if (oldbegin >= end) return false;\n    while (!begin.compare_exchange_weak (oldbegin, oldbegin+1,\n                                         std::memory_order_relaxed, std::memory_order_relaxed))\n      if (oldbegin >= end) return false;        \n\n    first = oldbegin;\n    return true;\n  }\n\n  bool PopHalf (IntRange & r)\n  {\n    // int oldbegin = begin;\n    int oldbegin = begin.load(std::memory_order_relaxed);    \n    if (oldbegin >= end) return false;\n    \n    lock_guard<mutex> guard(lock);    \n    while (!begin.compare_exchange_weak (oldbegin, (oldbegin+end+1)/2,\n                                         std::memory_order_relaxed, std::memory_order_relaxed))\n      if (oldbegin >= end) return false;        \n\n    r = IntRange(oldbegin, (oldbegin+end+1)/2);\n    return true;\n  }\n};\n\n\n  // inline ostream & operator<< (ostream & ost, AtomicRange & r)\n  // {\n  //   ost << r.Get();\n  //   return ost;\n  // }\n  */\n\n\n   \n   class alignas(4096) AtomicRange\n  {\n    atomic<size_t> begin;\n    atomic<size_t> end;\n  public:\n    \n    void Set (IntRange r)\n    {\n      begin.store(std::numeric_limits<size_t>::max(), std::memory_order_release);\n      end.store(r.end(), std::memory_order_release);\n      begin.store(r.begin(), std::memory_order_release);\n    }\n  \n    void SetNoLock (IntRange r)\n    {\n      end.store(r.end(), std::memory_order_release);\n      begin.store(r.begin(), std::memory_order_release);\n    }\n\n    // IntRange Get()\n    // {\n    //   lock_guard<mutex> guard(lock);\n    //   return IntRange(begin, end);\n    // }\n    \n    bool PopFirst (size_t & hfirst)\n    {\n      // first = begin++;\n      // return first < end;\n      \n      size_t first = begin.load(std::memory_order_relaxed);\n      \n      size_t nextfirst = first+1;\n      if (first >= end) nextfirst = std::numeric_limits<size_t>::max()-1;\n\n      // while (!begin.compare_exchange_weak (first, nextfirst))\n      while (!begin.compare_exchange_weak (first, nextfirst,\n                                           std::memory_order_relaxed,\n                                           std::memory_order_relaxed))\n        {\n          first = begin;\n          nextfirst = first+1;\n          if (nextfirst >= end) nextfirst = std::numeric_limits<size_t>::max()-1;\n        }\n      hfirst = first;\n      return first < end;\n    }\n    \n    bool PopHalf (IntRange & r)\n    {\n      /*\n      // int oldbegin = begin;\n      size_t oldbegin = begin.load(std::memory_order_acquire);\n      size_t oldend = end.load(std::memory_order_acquire);\n      if (oldbegin >= oldend) return false;\n      \n      // lock_guard<mutex> guard(lock);    \n      while (!begin.compare_exchange_weak (oldbegin, (oldbegin+oldend+1)/2,\n                                           std::memory_order_relaxed, std::memory_order_relaxed))\n        {\n          oldend = end.load(std::memory_order_acquire);\n          if (oldbegin >= oldend) return false;\n        }\n      \n      r = IntRange(oldbegin, (oldbegin+oldend+1)/2);\n      return true;\n      */\n\n\n      size_t oldbegin = begin; // .load(std::memory_order_acquire);\n      size_t oldend = end; // .load(std::memory_order_acquire);\n      if (oldbegin >= oldend) return false;\n      \n      size_t nextbegin = (oldbegin+oldend+1)/2;\n      if (nextbegin >= oldend) nextbegin = std::numeric_limits<size_t>::max()-1;\n      \n      while (!begin.compare_exchange_weak (oldbegin, nextbegin))\n        // std::memory_order_relaxed, std::memory_order_relaxed))\n        {\n          oldend = end; // .load(std::memory_order_acquire);\n          if (oldbegin >= oldend) return false;\n          \n          nextbegin = (oldbegin+oldend+1)/2;\n          if (nextbegin >= oldend) nextbegin = std::numeric_limits<size_t>::max()-1;\n        }\n      \n      r = IntRange(oldbegin, (oldbegin+oldend+1)/2);\n      return true;\n    }\n  };\n  \n\n\n\n  class SharedLoop2\n  {\n    Array<AtomicRange> ranges;\n    atomic<size_t> processed;\n    atomic<size_t> total;\n    atomic<int> participants;\n    \n    class SharedIterator\n    {\n      FlatArray<AtomicRange> ranges;\n      atomic<size_t> & processed;\n      size_t total;\n      size_t myval;\n      size_t processed_by_me = 0;\n      int me;\n      int steal_from;\n    public:\n      SharedIterator (FlatArray<AtomicRange> _ranges, atomic<size_t> & _processed, size_t _total,\n                      int _me, bool begin_it)\n        : ranges(_ranges), processed(_processed), total(_total)\n      {\n        if (begin_it)\n          {\n            // me = TaskManager::GetThreadId();\n            me = _me;\n            steal_from = me;\n            GetNext();\n          }\n      }\n      ~SharedIterator()\n      {\n        if (processed_by_me)\n          processed += processed_by_me;\n      }\n      \n      SharedIterator & operator++ () { GetNext(); return *this;}\n\n      void GetNext()\n      {\n        size_t nr;\n        if (ranges[me].PopFirst(nr))\n          {\n            processed_by_me++;\n            myval = nr;\n            return;\n          }\n        GetNext2();\n      }\n\n      void GetNext2()\n      {\n        processed += processed_by_me;\n        processed_by_me = 0;\n        \n        // done with my work, going to steal ...\n        while (1)\n          {\n            if (processed >= total) return;\n\n            steal_from++;\n            if (steal_from == ranges.Size()) steal_from = 0;\n            \n            // steal half of the work reserved for 'from':\n            IntRange steal;\n            if (ranges[steal_from].PopHalf(steal))\n              {\n                myval = steal.First();\n                processed_by_me++;                    \n                if (myval+1 < steal.Next())\n                  ranges[me].Set (IntRange(myval+1, steal.Next()));\n                return;\n              }\n          }\n      }\n      \n      size_t operator* () const { return myval; }\n      bool operator!= (const SharedIterator & it2) const { return processed < total; }\n    };\n    \n    \n  public:\n    SharedLoop2 ()\n      : ranges(TaskManager::GetNumThreads())\n    { ; }\n    \n    SharedLoop2 (IntRange r)\n      : ranges(TaskManager::GetNumThreads())\n    {\n      Reset (r);\n    }\n\n    SharedLoop2 (size_t s) : SharedLoop2 (IntRange{s}) { } \n    \n    void Reset (IntRange r)\n    {\n      for (size_t i = 0; i < ranges.Size(); i++)\n        ranges[i].SetNoLock (r.Split(i,ranges.Size()));\n      \n      total.store(r.Size(), std::memory_order_relaxed);\n      participants.store(0, std::memory_order_relaxed);\n      processed.store(0, std::memory_order_release);\n    }\n\n    void Reset (size_t s) { Reset(IntRange{s}); }\n      \n    \n    SharedIterator begin()\n    {\n      /*\n      int me = participants++;\n      if (me < ranges.Size())\n        return SharedIterator (ranges, processed, total, me, true);\n      else\n        // more participants than buckets. set processed to total, and the loop is terminated immediately\n        return SharedIterator (ranges, total, total, me, true);\n      */\n      return SharedIterator (ranges, processed, total, TaskManager::GetThreadId(), true);      \n    }\n    \n    SharedIterator end()   { return SharedIterator (ranges, processed, total, -1, false); }\n  };\n\n\n\n\n\n  class Partitioning\n  {\n    Array<size_t> part;\n    size_t total_costs;\n  public:\n    Partitioning () { ; }\n\n    template <typename T>\n    Partitioning (const Array<T> & apart) { part = apart; }\n\n    template <typename T>\n    Partitioning & operator= (const Array<T> & apart) { part = apart; return *this; }\n\n    size_t GetTotalCosts() const { return total_costs; }\n\n    template <typename TFUNC>\n    void Calc (size_t n, TFUNC costs, int size = task_manager ? task_manager->GetNumThreads() : 1)\n    {\n      Array<size_t> prefix (n);\n\n      /*\n      size_t sum = 0;\n      for (auto i : ngstd::Range(n))\n        {\n          sum += costs(i);\n          prefix[i] = sum;\n        }\n      total_costs = sum;\n      */\n      \n      Array<size_t> partial_sums(TaskManager::GetNumThreads()+1);\n      partial_sums[0] = 0;\n      ParallelJob\n        ([&] (TaskInfo ti)\n         {\n           IntRange r = IntRange(n).Split(ti.task_nr, ti.ntasks);\n           size_t mysum = 0;\n           for (size_t i : r)\n             {\n               size_t c = costs(i);\n               mysum += c;\n               prefix[i] = c;\n             }\n           partial_sums[ti.task_nr+1] = mysum;\n         });\n      \n      for (size_t i = 1; i < partial_sums.Size(); i++)\n        partial_sums[i] += partial_sums[i-1];\n      total_costs = partial_sums.Last();\n      \n      ParallelJob\n        ([&] (TaskInfo ti)\n         {\n           IntRange r = IntRange(n).Split(ti.task_nr, ti.ntasks);\n           size_t mysum = partial_sums[ti.task_nr];\n           for (size_t i : r)\n             {\n               mysum += prefix[i];\n               prefix[i] = mysum;\n             }\n         });\n      \n\n      part.SetSize (size+1);\n      part[0] = 0;\n\n      for (int i = 1; i <= size; i++)\n        part[i] = BinSearch (prefix, total_costs*i/size);      \n    }\n    \n    size_t Size() const { return part.Size()-1; }\n    IntRange operator[] (size_t i) const { return ngcore::Range(part[i], part[i+1]); }\n    IntRange Range() const { return ngcore::Range(part[0], part[Size()]); }\n\n\n\n\n  private:\n    template <typename Tarray>\n    int BinSearch(const Tarray & v, size_t i) {\n      int n = v.Size();\n      if (n == 0) return 0;\n      \n      int first = 0;\n      int last = n-1;\n      if(v[0]>i) return 0;\n      if(v[n-1] <= i) return n;\n      while(last-first>1) {\n        int m = (first+last)/2;\n        if(v[m]<i)\n          first = m;\n        else\n          last = m;\n      }\n      return first;\n    }\n  };\n\n  \n  inline std::ostream & operator<< (std::ostream & ost, const Partitioning & part)\n  {\n    for (int i : Range(part.Size()))\n      ost << part[i] << \" \";\n    return ost;\n  }\n  \n\n  // tasks must be a multiple of part.size\n  template <typename TFUNC>\n  NETGEN_INLINE void ParallelFor (const Partitioning & part, TFUNC f, int tasks_per_thread = 1)\n  {\n    if (task_manager)\n      {\n        int ntasks = tasks_per_thread * task_manager->GetNumThreads();\n        if (ntasks % part.Size() != 0)\n          throw Exception (\"tasks must be a multiple of part.size\");\n\n        task_manager -> CreateJob \n          ([&] (TaskInfo & ti) \n           {\n             int tasks_per_part = ti.ntasks / part.Size();\n             int mypart = ti.task_nr / tasks_per_part;\n             int num_in_part = ti.task_nr % tasks_per_part;\n             \n             auto myrange = part[mypart].Split (num_in_part, tasks_per_part);\n             for (auto i : myrange) f(i);\n           }, ntasks);\n      }\n    else\n      {\n        for (auto i : part.Range())\n          f(i);\n      }\n  }\n\n\n\n\n\n  template <typename TFUNC>\n  NETGEN_INLINE void ParallelForRange (const Partitioning & part, TFUNC f,\n                                int tasks_per_thread = 1, TotalCosts costs = 1000)\n  {\n    if (task_manager && costs() >= 1000)\n      {\n        int ntasks = tasks_per_thread * task_manager->GetNumThreads();\n        if (ntasks % part.Size() != 0)\n          throw Exception (\"tasks must be a multiple of part.size\");\n\n        task_manager -> CreateJob \n          ([&] (TaskInfo & ti) \n           {\n             int tasks_per_part = ti.ntasks / part.Size();\n             int mypart = ti.task_nr / tasks_per_part;\n             int num_in_part = ti.task_nr % tasks_per_part;\n             \n             auto myrange = part[mypart].Split (num_in_part, tasks_per_part);\n             f(myrange);\n           }, ntasks);\n      }\n    else\n      {\n        f(part.Range());\n      }\n  }\n\n\n\n\n\n  template <typename FUNC, typename OP, typename T>\n  auto ParallelReduce (size_t n, FUNC f, OP op, T initial1)\n  {\n    typedef decltype (op(initial1,initial1)) TRES;\n    TRES initial(initial1);\n    /*\n    for (size_t i = 0; i < n; i++)\n      initial = op(initial, f(i));\n    */\n    Array<TRES> part_reduce(TaskManager::GetNumThreads());\n    ParallelJob ([&] (TaskInfo ti)\n                 {\n                   auto r = Range(n).Split(ti.task_nr, ti.ntasks);\n                   auto var = initial;\n                   for (auto i : r)\n                     var = op(var, f(i));\n                   part_reduce[ti.task_nr] = var;\n                 });\n    for (auto v : part_reduce)\n      initial = op(initial, v);\n    return initial;\n  }\n\n\n\n\n\n  \n\n//   //  some suggar for working with arrays \n// \n//   template <typename T> template <typename T2>\n//   const FlatArray<T> FlatArray<T>::operator= (ParallelValue<T2> val)\n//   {\n//     ParallelForRange (Size(),\n//                       [this, val] (IntRange r)\n//                       {\n//                         for (auto i : r)\n//                           (*this)[i] = val;\n//                       });\n//     return *this;\n//   }\n// \n//   template <typename T> template <typename T2>\n//   const FlatArray<T> FlatArray<T>::operator= (ParallelFunction<T2> func)\n//   {\n//     ParallelForRange (Size(),\n//                       [this, func] (IntRange r)\n//                       {\n//                         for (auto i : r)\n//                           (*this)[i] = func(i);\n//                       });\n//     return *this;\n//   }\n\nclass Tasks\n{\n  size_t num;\npublic:\n  explicit Tasks (size_t _num = TaskManager::GetNumThreads()) : num(_num) { ; }\n  auto GetNum() const { return num; } \n};\n\n\n/*\n  // some idea, not yet supported\n\n using namespace std;\n  template <typename T>\n  class ParallelValue\n  {\n    T val;\n  public:\n    ParallelValue (const T & _val) : val(_val) { ; }\n    operator T () const { return val; }\n  };\n  \n  template <typename FUNC> class ParallelFunction\n  {\n    FUNC f;\n  public:\n    ParallelFunction (const FUNC & _f) : f(_f) { ; }\n    operator FUNC () const { return f; }\n    auto operator() (size_t i) const { return f(i); }\n  };\n*/\n\n/* currently not used, plus causing problems on MSVC 2017\ntemplate <typename T, typename std::enable_if<ngstd::has_call_operator<T>::value, int>::type = 0>                                  \ninline ParallelFunction<T> operator| (const T & func, Tasks tasks)\n{\n  return func;\n}\n\ntemplate <typename T, typename std::enable_if<!ngstd::has_call_operator<T>::value, int>::type = 0>                                  \ninline ParallelValue<T> operator| (const T & obj, Tasks tasks)\n{\n  return obj;\n}\n\ninline Tasks operator \"\" _tasks_per_thread (unsigned long long n)\n{\n  return Tasks(n * TaskManager::GetNumThreads());\n}\n*/\n\n/*\n  thought to be used as:   array = 1 | tasks\nclass DefaultTasks\n{\npublic:\n  operator Tasks () const { return TaskManager::GetNumThreads(); }\n};\nstatic DefaultTasks tasks;\n*/\n\n\n\n\n\n\n\n#ifdef USE_NUMA\n\ntemplate <typename T>\nclass NumaInterleavedArray : public Array<T>\n{\n  T * numa_ptr;\n  size_t numa_size;\npublic:\n  NumaInterleavedArray () { numa_size = 0; numa_ptr = nullptr; }\n  NumaInterleavedArray (size_t s)\n    : Array<T> (s, (T*)numa_alloc_interleaved(s*sizeof(T)))\n  {\n    numa_ptr = this->data;\n    numa_size = s;\n  }\n\n  ~NumaInterleavedArray ()\n  {\n    numa_free (numa_ptr, numa_size*sizeof(T));\n  }\n\n  NumaInterleavedArray & operator= (T val)\n  {\n    Array<T>::operator= (val);      \n    return *this;\n  }\n\n  NumaInterleavedArray & operator= (NumaInterleavedArray && a2)\n  {\n    Array<T>::operator= ((Array<T>&&)a2);  \n    ngcore::Swap (numa_ptr, a2.numa_ptr);\n    ngcore::Swap (numa_size, a2.numa_size);\n    return *this;\n  }\n\n  void Swap (NumaInterleavedArray & b)\n  {\n    Array<T>::Swap(b);    \n    ngcore::Swap (numa_ptr, b.numa_ptr);\n    ngcore::Swap (numa_size, b.numa_size);\n  }\n\n  void SetSize (size_t size)\n  {\n    std::cerr << \"************************* NumaDistArray::SetSize not overloaded\" << std::endl;\n    Array<T>::SetSize(size);\n  }\n};\n\ntemplate <typename T>\nclass NumaDistributedArray : public Array<T>\n{\n  T * numa_ptr;\n  size_t numa_size;\npublic:\n  NumaDistributedArray () { numa_size = 0; numa_ptr = nullptr; }\n  NumaDistributedArray (size_t s)\n    : Array<T> (s, (T*)numa_alloc_local(s*sizeof(T)))\n  {\n    numa_ptr = this->data;\n    numa_size = s;\n\n    /* int avail = */ numa_available();   // initialize libnuma\n    int num_nodes = numa_num_configured_nodes();\n    size_t pagesize = numa_pagesize();\n    \n    int npages = std::ceil ( double(s)*sizeof(T) / pagesize );\n\n    // cout << \"size = \" << numa_size << endl;\n    // cout << \"npages = \" << npages << endl;\n\n    for (int i = 0; i < num_nodes; i++)\n      {\n        int beg = (i * npages) / num_nodes;\n        int end = ( (i+1) * npages) / num_nodes;\n        // cout << \"node \" << i << \" : [\" << beg << \"-\" << end << \")\" << endl;\n        numa_tonode_memory(numa_ptr+beg*pagesize/sizeof(T), (end-beg)*pagesize, i);\n      }\n  }\n\n  ~NumaDistributedArray ()\n  {\n    numa_free (numa_ptr, numa_size*sizeof(T));\n  }\n\n  NumaDistributedArray & operator= (NumaDistributedArray && a2)\n  {\n    Array<T>::operator= ((Array<T>&&)a2);  \n    ngcore::Swap (numa_ptr, a2.numa_ptr);\n    ngcore::Swap (numa_size, a2.numa_size);\n    return *this;\n  }\n\n  void Swap (NumaDistributedArray & b)\n  {\n    Array<T>::Swap(b);    \n    ngcore::Swap (numa_ptr, b.numa_ptr);\n    ngcore::Swap (numa_size, b.numa_size);\n  }\n\n  void SetSize (size_t size)\n  {\n    std::cerr << \"************************* NumaDistArray::SetSize not overloaded\" << std::endl;\n    Array<T>::SetSize(size);\n  }\n};\n\n\n\ntemplate <typename T>\nclass NumaLocalArray : public Array<T>\n{\n  T * numa_ptr;\n  size_t numa_size;\npublic:\n  NumaLocalArray () { numa_size = 0; numa_ptr = nullptr; }\n  NumaLocalArray (size_t s)\n    : Array<T> (s, (T*)numa_alloc_local(s*sizeof(T)))\n  {\n    numa_ptr = this->data;\n    numa_size = s;\n  }\n\n  ~NumaLocalArray ()\n  {\n    numa_free (numa_ptr, numa_size*sizeof(T));\n  }\n\n  NumaLocalArray & operator= (T val)\n  {\n    Array<T>::operator= (val);      \n    return *this;\n  }\n  \n  NumaLocalArray & operator= (NumaLocalArray && a2)\n  {\n    Array<T>::operator= ((Array<T>&&)a2);  \n    ngcore::Swap (numa_ptr, a2.numa_ptr);\n    ngcore::Swap (numa_size, a2.numa_size);\n    return *this;\n  }\n\n  void Swap (NumaLocalArray & b)\n  {\n    Array<T>::Swap(b);    \n    ngcore::Swap (numa_ptr, b.numa_ptr);\n    ngcore::Swap (numa_size, b.numa_size);\n  }\n\n  void SetSize (size_t size)\n  {\n    std::cerr << \"************************* NumaDistArray::SetSize not overloaded\" << std::endl;\n    Array<T>::SetSize(size);\n  }\n};\n\n\n#else // USE_NUMA\n\n  template <typename T>\n  using NumaDistributedArray = Array<T>;\n\n  template <typename T> \n  using NumaInterleavedArray = Array<T>;\n  \n  template <typename T>\n  using NumaLocalArray = Array<T>;\n  \n#endif // USE_NUMA\n\n}\n\n\n\n#endif // NETGEN_CORE_TASKMANAGER_HPP\n"
  },
  {
    "path": "libsrc/core/type_traits.hpp",
    "content": "#ifndef NETGEN_CORE_TYPE_TRAITS_HPP\n#define NETGEN_CORE_TYPE_TRAITS_HPP\n\n#include <memory>\n#include <type_traits>\n\nnamespace ngcore\n{\n  namespace detail\n  {\n    template<bool... b> struct _BoolArray{};\n\n    template<bool ... vals>\n    constexpr bool all_of_tmpl = std::is_same<_BoolArray<vals...>, _BoolArray<(vals || true)...>>::value; // NOLINT\n\n    template<typename T>\n    struct is_any_pointer_impl : std::false_type {};\n\n    // check if second template argument is tuple of base classes to first\n    // template argument, return constexpr bool\n    template<typename T, typename Tuple>\n    constexpr bool is_base_of_tuple = false;\n\n    template<typename T, typename... Ts>\n    constexpr bool is_base_of_tuple<T, std::tuple<Ts...>> =\n      all_of_tmpl<std::is_base_of<Ts, T>::value...>;\n\n    template<typename T>\n    struct is_any_pointer_impl<T*> : std::true_type {};\n\n    template<typename T>\n    struct is_any_pointer_impl<std::shared_ptr<T>> : std::true_type {};\n\n    template<typename T>\n    struct is_any_pointer_impl<std::unique_ptr<T>> : std::true_type {};\n\n    template<typename T>\n    constexpr bool is_any_pointer = is_any_pointer_impl<T>::value;\n  } // namespace detail\n\n  \n  // Type trait to check if a class implements a 'range_type Range()' function\n  namespace detail\n  {\n    template<typename T>\n    struct has_Range\n    {\n    private:\n      template<typename T2>\n      static constexpr auto check(T2*) ->\n        std::enable_if_t<!std::is_same_v<decltype(std::declval<T2>().Range()), void>, std::true_type>\n      { return std::true_type(); }\n      template<typename>\n      static constexpr std::false_type check(...);\n      using type = decltype(check<T>(nullptr)); // NOLINT\n    public:\n      NGCORE_API static constexpr bool value = type::value;\n    };\n  }\n  template<typename T>\n  constexpr bool has_range = detail::has_Range<T>::value;\n\n} // namespace ngcore\n\n#endif // NETGEN_CORE_TYPE_TRAITS_HPP\n"
  },
  {
    "path": "libsrc/core/utils.cpp",
    "content": "#include \"ngcore_api.hpp\"\n#include \"utils.hpp\"\n#include \"logging.hpp\"\n#include \"simd_generic.hpp\"\n\n#ifdef WIN32\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#undef WIN32_LEAN_AND_MEAN\n#else // WIN32\n#include <cxxabi.h>\n#include <dlfcn.h>\n#endif //WIN32\n//\n#include <array>\n#include <filesystem>\n#include <iostream>\n#include <regex>\n#include <string>\n#include <thread>\n\n#include \"ngstream.hpp\"\n\n\nnamespace ngcore\n{\n    namespace detail\n    {\n        // see https://github.com/RobotLocomotion/drake/blob/master/common/nice_type_name.cc\n        static const auto demangle_regexes =\n            std::array<std::pair<std::regex, std::string>, 8>{\n                // Remove unwanted keywords and following space. (\\b is word boundary.)\n                std::make_pair(std::regex(\"\\\\b(class|struct|enum|union) \"), \"\"),\n                // Tidy up anonymous namespace.\n                {std::regex(\"[`(]anonymous namespace[')]\"), \"(anonymous)\"},\n                // Replace Microsoft __int64 with long long.\n                {std::regex(\"\\\\b__int64\\\\b\"), \"long long\"},\n                // Temporarily replace spaces we want to keep with \"!\". (\\w is\n                // alphanumeric or underscore.)\n                {std::regex(\"(\\\\w) (\\\\w)\"), \"$1!$2\"},\n                {std::regex(\" \"), \"\"},  // Delete unwanted spaces.\n                // Some compilers throw in extra namespaces like \"__1\" or \"__cxx11\".\n                // Delete them.\n                {std::regex(\"\\\\b__[[:alnum:]_]+::\"), \"\"},\n                {std::regex(\"!\"), \" \"},  // Restore wanted spaces.\n\n                // Recognize std::string's full name and abbreviate.\n                {std::regex(\"\\\\bstd::basic_string<char,std::char_traits<char>,\"\n                        \"std::allocator<char>>\"), \"std::string\"}\n            };\n        std::string CleanupDemangledName( std::string s )\n        {\n            for(const auto & [r, sub] : demangle_regexes)\n                s = std::regex_replace (s,r,sub);\n#ifdef EMSCRIPTEN\n            // for some reason regex_replace is not working at all\n            std::string temp = s;\n            s = \"\";\n            for(auto c : temp)\n              if(c!=' ')\n                s+=c;\n#endif // EMSCRIPTEN\n\n            return s;\n        }\n    } // namespace detail\n\n  // parallel netgen\n  int id = 0, ntasks = 1;\n\n#ifdef WIN32\n  // windows does demangling in typeid(T).name()\n  NGCORE_API std::string Demangle(const char* typeinfo) {\n      std::string name = typeinfo;\n      return detail::CleanupDemangledName(name);\n  }\n#else\n  NGCORE_API std::string Demangle(const char* typeinfo)\n  {\n    int status=0;\n    try\n      {\n        char *s = abi::__cxa_demangle(typeinfo, nullptr, nullptr, &status);\n        std::string result;\n        if (s == nullptr)\n          result = typeinfo;\n        else\n          {\n            result = s;\n            free(s);\n          }\n        result = detail::CleanupDemangledName(result);\n        return result;\n      }\n    catch( const std::exception & e )\n      {\n        GetLogger(\"utils\")->warn(\"{}:{} cannot demangle {}, status: {}, error:{}\", __FILE__, __LINE__, typeinfo, status, e.what());\n      }\n    std::string name = typeinfo;\n    return detail::CleanupDemangledName(name);\n  }\n#endif\n\n  double seconds_per_tick = [] () noexcept\n  {\n      auto tick_start = GetTimeCounter();\n      double tstart = WallTime();\n      double tend = WallTime()+0.001;\n\n      // wait for 1ms and compare wall time with time counter\n      while(WallTime()<tend);\n\n      auto tick_end = GetTimeCounter();\n      tend = WallTime();\n\n      return (tend-tstart)/static_cast<double>(tick_end-tick_start);\n  }();\n\n  const std::chrono::time_point<TClock> wall_time_start = TClock::now();\n\n  int printmessage_importance = getenv(\"NG_MESSAGE_LEVEL\") ? atoi(getenv(\"NG_MESSAGE_LEVEL\")) : 0;\n  bool NGSOStream :: glob_active = true;\n\n  NGCORE_API int GetCompiledSIMDSize()\n  {\n      return GetDefaultSIMDSize();\n  }\n\n  NGCORE_API bool IsRangeCheckEnabled()\n  {\n#ifdef NETGEN_ENABLE_CHECK_RANGE\n      return true;\n#else\n      return false;\n#endif\n  }\n\n  NGCORE_API std::filesystem::path GetTempFilename()\n  {\n      static int counter = 0;\n      auto path = std::filesystem::temp_directory_path();\n      path += \".temp_netgen_file_\"+ToString(counter++)+\"_\"+ToString(GetTimeCounter());\n      return path;\n  }\n\n\n  SharedLibrary :: SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_, bool global )\n      : lib_name(lib_name_),directory_to_delete(directory_to_delete_)\n  {\n    Load(lib_name, global);\n  }\n\n  SharedLibrary :: ~SharedLibrary()\n  {\n    Unload();\n    if(directory_to_delete)\n      for([[maybe_unused]] auto i : Range(5))\n      {\n        // on Windows, a (detached?) child process of the compiler/linker might still block the directory\n        // wait for it to finish (up to a second)\n        try\n        {\n          std::filesystem::remove_all(*directory_to_delete);\n          directory_to_delete = std::nullopt;\n          break;\n        }\n        catch(const std::exception &e)\n        {\n          std::this_thread::sleep_for(std::chrono::milliseconds(200));\n        }\n      }\n    if(directory_to_delete)\n      std::cerr << \"Could not delete \" << directory_to_delete->string() << std::endl;\n  }\n\n  void SharedLibrary :: Load( const std::filesystem::path & lib_name_, bool global )\n  {\n    Unload();\n    lib_name = lib_name_;\n#ifdef WIN32\n    lib = LoadLibraryW(lib_name.wstring().c_str());\n    if (!lib) throw std::runtime_error(std::string(\"Could not load library \") + lib_name.string());\n#else // WIN32\n    auto flags = RTLD_NOW;\n    if (global) flags |= RTLD_GLOBAL;\n    lib = dlopen(lib_name.c_str(), flags);\n    if(lib == nullptr) throw std::runtime_error(dlerror());\n#endif // WIN32\n  }\n\n  void SharedLibrary :: Unload() {\n    if(lib)\n    {\n#ifdef WIN32\n      FreeLibrary((HMODULE)lib);\n#else // WIN32\n      int rc = dlclose(lib);\n      if(rc != 0) std::cerr << \"Failed to close library \" << lib_name << std::endl;\n#endif // WIN32\n    }\n  }\n\n  void* SharedLibrary :: GetRawSymbol( std::string func_name )\n  {\n#ifdef WIN32\n    void* func = GetProcAddress((HMODULE)lib, func_name.c_str());\n    if(func == nullptr)\n      throw std::runtime_error(std::string(\"Could not find function \") + func_name + \" in library \" + lib_name.string());\n#else // WIN32\n    void* func = dlsym(lib, func_name.c_str());\n    if(func == nullptr)\n        throw std::runtime_error(dlerror());\n#endif // WIN32\n\n    return func;\n  }\n\n  void* GetRawSymbol( std::string func_name )\n  {\n    void * func = nullptr;\n#ifdef WIN32\n    throw std::runtime_error(\"GetRawSymbol not implemented on WIN32\");\n#else // WIN32\n    func = dlsym(RTLD_DEFAULT, func_name.c_str());\n    if(func == nullptr)\n        throw std::runtime_error(dlerror());\n#endif // WIN32\n    return func;\n  }\n\n\n} // namespace ngcore\n\n"
  },
  {
    "path": "libsrc/core/utils.hpp",
    "content": "#ifndef NETGEN_CORE_UTILS_HPP\n#define NETGEN_CORE_UTILS_HPP\n\n#include <atomic>\n#include <chrono>\n#include <filesystem>\n#include <map>\n#include <ostream>\n#include <optional>\n#include <sstream>\n#include <string>\n\n#include \"ngcore_api.hpp\"       // for NGCORE_API and CPU arch macros\n\n#if defined(__APPLE__) && defined(NETGEN_ARCH_ARM64)\n#include <mach/mach_time.h>\n#endif\n\n#ifdef NETGEN_ARCH_AMD64\n#ifdef WIN32\n#include <intrin.h>   // for __rdtsc()  CPU time step counter\n#else\n#include <x86intrin.h>   // for __rdtsc()  CPU time step counter\n#endif // WIN32\n#endif // NETGEN_ARCH_AMD64\n\nnamespace ngcore\n{\n  // MPI rank, nranks TODO: Rename\n  // [[deprecated(\"don't use global id/ntasks\")]]       \n  extern NGCORE_API int id;\n  // [[deprecated(\"don't use global id/ntasks\")]]         \n  extern NGCORE_API int ntasks;\n  \n  NGCORE_API std::string Demangle(const char* typeinfo);\n\n  template<typename T>\n  std::string GetName(const T& obj)\n  { return Demangle(typeid(obj).name()); }\n\n#if defined(__GNUC__)\n  inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); }\n  inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); }\n#else\n  inline bool likely (bool x) { return x; }\n  inline bool unlikely (bool x) { return x; }\n#endif\n\n  using TClock = std::chrono::system_clock;\n  extern NGCORE_API const std::chrono::time_point<TClock> wall_time_start;\n\n  // Time in seconds since program start\n  inline double WallTime () noexcept\n  {\n      std::chrono::time_point<TClock> now = TClock::now();\n      std::chrono::duration<double> elapsed_seconds = now-wall_time_start;\n      return elapsed_seconds.count();\n  }\n\n  // High precision clock counter register\n  using TTimePoint = size_t;\n  extern NGCORE_API double seconds_per_tick;\n\n  inline TTimePoint GetTimeCounter() noexcept\n  {\n#if defined(NETGEN_ARCH_AMD64)\n    return __rdtsc();\n#elif defined(NETGEN_ARCH_ARM64)\n    unsigned long long tics;\n    __asm __volatile(\"mrs %0, CNTVCT_EL0\" : \"=&r\" (tics));\n    return tics;\n#elif defined(__EMSCRIPTEN__) || (defined(_MSC_VER) && defined(_M_ARM64))\n    return std::chrono::high_resolution_clock::now().time_since_epoch().count();\n#else\n#warning \"Unsupported CPU architecture\"\n    return 0;\n#endif\n  }\n\n  template <class T>\n  inline std::string ToString (const T& t)\n  {\n      std::stringstream ss;\n      ss << t;\n      return ss.str();\n  }\n\n  inline std::string ToLower( const std::string & s )\n  {\n    std::string res;\n    res.reserve(s.size());\n\n    for(auto & c : s)\n        res.push_back(tolower(c));\n\n    return res;\n  }\n\n  inline std::string ToLower( const std::filesystem::path & p )\n  {\n    return ToLower(p.string());\n  }\n\n\n\n  template <class T>\n  void SaveBin (std::ostream & ost, const T & val)\n  {\n    const char * cp = reinterpret_cast<const char*> (&val);\n    for (unsigned j = 0; j < sizeof(T); j++)\n      ost.put(cp[j]);\n  }\n  \n  \n  template <class T>\n  void LoadBin (std::istream & ist, T & val)\n  {\n    char * cp = reinterpret_cast<char*> (&val);\n    for (unsigned j = 0; j < sizeof(T); j++)\n      ist.get(cp[j]);\n  }\n  \n  \n  template<typename T1, typename T2>\n  std::ostream& operator << (std::ostream& ost, const std::map<T1,T2>& map)\n  {\n    for(auto& val : map)\n      ost << \"\\n\" << val.first << \": \" << val.second;\n    return ost;\n  }\n\n  template <class T>\n  NETGEN_INLINE void Swap (T & a, T & b)\n  {\n      T temp = std::move(a);\n      a = std::move(b);\n      b = std::move(temp);\n  }\n\n  \n  /// min of 2 values\n  template <class T>\n  NETGEN_INLINE T min2 (T a, T b)\n  {\n    return (a < b) ? a : b;\n  }\n  \n  /// max of 2 values\n  template <class T>\n  NETGEN_INLINE T max2 (T a, T b)\n  {\n    return (a > b) ? a : b;\n}\n  \n  /// min of 3 values\n  template <class T>\n  NETGEN_INLINE T min3 (T a, T b, T c)\n  {\n  return (a < b) ? (a < c) ? a : c\n    : (b < c) ? b : c;\n  }\n  \n  /// max of 3 values\n  template <class T>\n  NETGEN_INLINE T max3 (T a, T b, T c)\n  {\n    ///\n    return (a > b) ? ((a > c) ? a : c)\n      : ((b > c) ? b : c);\n  }\n  \n  \n  /// sign of value (+1, 0, -1)\n  template <class T>\n  NETGEN_INLINE int sgn (T a)\n  {\n    return (a > 0) ? 1 : ( ( a < 0) ? -1 : 0 );\n  }\n  \n  /// square element \n  template <class T>\n  NETGEN_INLINE constexpr T sqr (const T a)\n  {\n    return a * a; \n  }\n  \n  /// element to the third power\n  template <class T>\n  NETGEN_INLINE T pow3 (const T a)\n  {\n    return a * a * a; \n  }\n  \n  \n\n  NETGEN_INLINE double IfPos (double a, double b, double c) { return a>0 ? b : c; }\n  NETGEN_INLINE double IfZero (double a, double b, double c) { return a==0. ? b : c; }\n\n  // checks if string starts with sequence\n  inline bool StartsWith(const std::string& str, const std::string& start)\n  {\n    if(start.size() > str.size())\n      return false;\n    return std::equal(start.begin(), start.end(), str.begin());\n  }\n\n  // checks if string ends with sequence\n  inline bool EndsWith(const std::string& str, const std::string& end)\n  {\n    if(end.size() > str.size())\n      return false;\n    return std::equal(end.rbegin(), end.rend(), str.rbegin());\n  }\n\n  template<typename T>\n  NETGEN_INLINE std::atomic<T> & AsAtomic (T & d)\n  {\n    return reinterpret_cast<std::atomic<T>&> (d);\n  }\n\n  NETGEN_INLINE double AtomicAdd( double & sum, double val )\n  {\n      std::atomic<double> & asum = AsAtomic(sum);\n      double current = asum.load();\n      while (!asum.compare_exchange_weak(current, current + val))\n          ;\n      return current;\n  }\n\n  template<typename T>\n  NETGEN_INLINE T AtomicMin( T & minval, T val )\n  {\n      std::atomic<T> & aminval = AsAtomic(minval);\n      T current = aminval.load();\n      while (!aminval.compare_exchange_weak(current, std::min(current, val)))\n          ;\n      return current;\n  }\n\n  template<typename T>\n  NETGEN_INLINE T AtomicMax( T & maxval, T val )\n  {\n      std::atomic<T> & amaxval = AsAtomic(maxval);\n      T current = amaxval.load();\n      while (!amaxval.compare_exchange_weak(current, std::max(current, val)))\n          ;\n      return current;\n  }\n\n  \n\n  \n  template <int N> using IC = std::integral_constant<int,N>;  // needed for Iterate\n\n  \n  namespace detail {\n    template <typename T, typename Enable = int>\n    struct IsIC_trait {\n      static constexpr auto check() { return false; }\n    };\n    \n    template <typename T>\n    struct IsIC_trait<T, std::enable_if_t<std::is_same_v<T, IC<T::value>> == true, int> > {\n      static constexpr auto check() { return true; }  \n    };\n  }\n  \n  template <typename T>\n  constexpr bool is_IC() {\n    return detail::IsIC_trait<T>::check();\n  }\n  \n  \n\n  \n  template <int NUM, typename FUNC>\n  NETGEN_INLINE void Iterate (FUNC f)\n  {\n    if constexpr (NUM > 1) Iterate<NUM-1> (f);\n  if constexpr (NUM >= 1) f(IC<NUM-1>());\n  }\n  \n  \n  template <int NUM, typename FUNC>\n  NETGEN_INLINE void Switch (size_t nr, FUNC f)\n  {\n    if (NUM-1 == nr) f(IC<NUM-1>());\n    if constexpr (NUM > 1) Switch<NUM-1> (nr, f);\n  }\n  \n  \n  \n  namespace detail\n  {\n    template<typename T>\n    struct IndexTypeHelper\n    {\n    private:\n      template<typename T2>\n      static constexpr auto check(T2* t) -> typename T2::index_type { return *t; }\n      static constexpr size_t check(...);\n\n    public:\n      using type = decltype(check((T*) nullptr)); // NOLINT\n    };\n  \n  } // namespace detail\n\n  // Get index type of object. If object has a typedef index_type it is this type, else size_t\n  template<typename T>\n  using index_type = typename detail::IndexTypeHelper<T>::type;\n\n  class MyMutex\n  {\n    std::atomic<bool> m;\n  public:\n    MyMutex() { m.store(false, std::memory_order_relaxed); }\n    void lock()\n    {\n      bool should = false;\n      while (!m.compare_exchange_weak(should, true))\n        {\n          should = false;\n#ifdef NETGEN_ARCH_AMD64\n          _mm_pause();\n#endif // NETGEN_ARCH_AMD64\n        }\n    }\n    void unlock()\n    {\n      m = false;\n    }\n  };\n\n  class MyLock\n  {\n    MyMutex & mutex;\n  public:\n    MyLock (MyMutex & amutex) : mutex(amutex) { mutex.lock(); }\n    ~MyLock () { mutex.unlock(); }\n  };\n\n  NGCORE_API int GetCompiledSIMDSize();\n  NGCORE_API bool IsRangeCheckEnabled();\n\n  NGCORE_API std::filesystem::path GetTempFilename();\n\n  NGCORE_API void* GetRawSymbol( std::string func_name );\n\n  template <typename TFunc>\n  TFunc GetSymbol( std::string func_name )\n  {\n    return reinterpret_cast<TFunc>(GetRawSymbol(func_name));\n  }\n\n  // Class to handle/load shared libraries\n  class NGCORE_API SharedLibrary\n  {\n    std::filesystem::path lib_name;\n    std::optional<std::filesystem::path> directory_to_delete = std::nullopt;\n    void *lib = nullptr;\n\n  public:\n    SharedLibrary() = default;\n    SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_ = std::nullopt, bool global = false );\n\n    SharedLibrary(const SharedLibrary &) = delete;\n    SharedLibrary & operator =(const SharedLibrary &) = delete;\n\n    ~SharedLibrary();\n\n    template <typename TFunc>\n    TFunc GetSymbol( std::string func_name )\n    {\n      return reinterpret_cast<TFunc>(GetRawSymbol(func_name));\n    }\n\n    void Load( const std::filesystem::path & lib_name_, bool global = true);\n    void Unload();\n    void* GetRawSymbol( std::string func_name );\n  };\n\n} // namespace ngcore\n\n#endif // NETGEN_CORE_UTILS_HPP\n"
  },
  {
    "path": "libsrc/core/version.cpp",
    "content": "#include <map>\n\n#include <netgen_version.hpp>\n#include \"exception.hpp\"\n#include \"version.hpp\"\n\nnamespace ngcore\n{\n  // clang-tidy should ignore this static object\n  static std::map<std::string, VersionInfo> library_versions;  // NOLINT\n\n  const VersionInfo& GetLibraryVersion(const std::string& library)\n  { return library_versions[library]; }\n\n  const std::map<std::string, VersionInfo>& GetLibraryVersions()\n  { return library_versions; }\n\n  void SetLibraryVersion(const std::string& library, const VersionInfo& version)\n  {\n    if(library_versions.count(library) && (library_versions[library] != version))\n      throw Exception(\"Failed to set library version for \" + library + \" to \" + version.to_string() + \": version already set to \" + library_versions[library].to_string());\n    library_versions[library] = version;\n  }\n\n  static bool dummy = [](){\n    SetLibraryVersion(\"netgen\", NETGEN_VERSION);\n    return true;\n  }();\n} // namespace ngcore\n"
  },
  {
    "path": "libsrc/core/version.hpp",
    "content": "#ifndef NETGEN_CORE_VERSION_HPP\n#define NETGEN_CORE_VERSION_HPP\n\n#include <ostream>\n#include <string>\n#include <tuple>\n\n#include \"ngcore_api.hpp\"\n\nnamespace ngcore\n{\n  class VersionInfo\n  {\n  private:\n    size_t mayor_{}, minor_{}, release{}, patch{};\n    std::string git_hash{};\n  public:\n    VersionInfo() = default;\n    VersionInfo(std::string vstring)\n    {\n      minor_ = release = patch = 0;\n      git_hash = \"\";\n      if(vstring.substr(0,1) == \"v\")\n        vstring = vstring.substr(1,vstring.size()-1);\n      auto dot = vstring.find('.');\n      mayor_ = std::stoi(vstring.substr(0,dot));\n      if(dot == size_t(-1)) vstring = \"\";\n      else vstring = vstring.substr(dot+1, vstring.size()-dot-1);\n      if(!vstring.empty())\n        {\n          dot = vstring.find('.');\n          minor_ = std::stoi(vstring.substr(0,dot));\n          if (dot == size_t(-1)) vstring = \"\";\n          else vstring = vstring.substr(dot+1, vstring.size()-dot-1);\n          if(!vstring.empty())\n            {\n              dot = vstring.find('-');\n              release = std::stoi(vstring.substr(0,dot));\n              if(dot == size_t(-1)) vstring = \"\";\n              else vstring = vstring.substr(dot+1,vstring.size()-dot-1);\n              if(!vstring.empty())\n                {\n                  dot = vstring.find('-');\n                  patch = std::stoi(vstring.substr(0,dot));\n                  if(dot == size_t(-1)) vstring = \"\";\n                  else vstring = vstring.substr(dot+1, vstring.size()-dot-1);\n                  if(!vstring.empty())\n                    git_hash = vstring;\n                }\n            }\n        }\n    }\n    VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { }\n\n    std::string to_string() const\n    { std::string vstring = \"v\" + std::to_string(mayor_);\n      if(minor_ || release || patch || !git_hash.empty())\n        {\n          vstring += \".\" + std::to_string(minor_);\n          if(release || patch || !git_hash.empty())\n            {\n              vstring += \".\" + std::to_string(release);\n              if(patch || !git_hash.empty())\n                {\n                  vstring += \"-\" + std::to_string(patch);\n                  if(!git_hash.empty())\n                    vstring += \"-\" + git_hash;\n                }\n            }\n        }\n      return vstring;\n    }\n    bool operator <(const VersionInfo& other) const\n    {\n      return std::tie(mayor_, minor_, release, patch) <\n        std::tie(other.mayor_, other.minor_, other.release, other.patch);\n    }\n    bool operator ==(const VersionInfo& other) const\n    {\n      return mayor_ == other.mayor_ && minor_ == other.minor_ && release == other.release\n        && patch == other.patch;\n    }\n    bool operator !=(const VersionInfo& other) const\n    {\n      return !(*this==other);\n    }\n    bool operator >(const VersionInfo& other) const { return other < (*this); }\n    bool operator <=(const VersionInfo& other) const { return !((*this) > other); }\n    bool operator >=(const VersionInfo& other) const { return !((*this) < other); }\n  };\n\n  inline std::ostream& operator << (std::ostream& ost, const VersionInfo& version)\n  {\n    return ost << version.to_string();\n  }\n\n  NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library);\n  NGCORE_API const std::map<std::string, VersionInfo>& GetLibraryVersions();\n  NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version);\n} // namespace ngcore\n\n#endif // NETGEN_CORE_VERSION_HPP\n"
  },
  {
    "path": "libsrc/core/xbool.hpp",
    "content": "#ifndef NETGEN_CORE_XBOOL_HPP\n#define NETGEN_CORE_XBOOL_HPP\n\n/**************************************************************************/\n/* File:   xbool.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   14. Nov. 07                                                    */\n/**************************************************************************/\n\n\nnamespace ngcore\n{\n  // an extended bool with values false/maybe/true\n\n  struct TMAYBE { }; constexpr TMAYBE maybe;\n  \n  class xbool\n  {\n    uint8_t state;\n\n  public:\n    xbool (bool b) : state(b ? 2 : 0) { ; }\n    xbool (TMAYBE /* x */) : state(1) { ; }\n    xbool () = default;\n    xbool (const xbool &) = default;\n    \n    xbool & operator= (bool b) { state = b ? 2 : 0; return *this; }\n    xbool & operator= (TMAYBE /* x */) { state = 1; return *this; }\n    \n    bool IsTrue () const { return state == 2; }\n    bool IsMaybe () const { return state == 1; }\n    bool IsFalse () const { return state == 0; }\n    bool IsMaybeTrue() const { return state >= 1; } \n    bool IsMaybeFalse() const { return state <= 1; } \n    friend ostream & operator<< (ostream & ost, xbool xb);\n  };\n\n\n  static char output[] = \"0?1\";\n  inline ostream & operator<< (ostream & ost, xbool xb)\n  {\n    return ost << output[xb.state];\n  }\n  \n} // namespace ngcore\n\n#endif // NETGEN_CORE_XBOOL_HPP\n"
  },
  {
    "path": "libsrc/csg/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n        algprim.cpp brick.cpp   \n        bspline2d.cpp csgeom.cpp csgparser.cpp curve2d.cpp edgeflw.cpp\t       \n        explicitcurve2d.cpp extrusion.cpp gencyl.cpp genmesh.cpp identify.cpp  \n        manifold.cpp meshsurf.cpp polyhedra.cpp revolution.cpp singularref.cpp \n        solid.cpp specpoin.cpp spline3d.cpp surface.cpp triapprox.cpp zrefine.cpp \n        python_csg.cpp splinesurface.cpp\n)\n\nif(USE_GUI)\n    target_sources(nggui PRIVATE vscsg.cpp csgpkg.cpp)\nendif(USE_GUI)\n\ninstall(FILES\n  algprim.hpp brick.hpp csgeom.hpp csg.hpp csgparser.hpp\n  curve2d.hpp edgeflw.hpp explicitcurve2d.hpp extrusion.hpp\n  gencyl.hpp geoml.hpp identify.hpp manifold.hpp meshsurf.hpp\n  polyhedra.hpp revolution.hpp singularref.hpp solid.hpp\n  specpoin.hpp spline3d.hpp splinesurface.hpp surface.hpp\n  triapprox.hpp vscsg.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/csg COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/csg/algprim.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n  double \n  QuadraticSurface :: CalcFunctionValue (const Point<3> & p) const\n  {\n    return p(0) * (cxx * p(0) + cxy * p(1) + cxz * p(2) + cx) +\n      p(1) * (cyy * p(1) + cyz * p(2) + cy) +\n      p(2) * (czz * p(2) + cz) + c1;\n  }\n\n  void \n  QuadraticSurface :: CalcGradient (const Point<3> & p, Vec<3> & grad) const\n  {\n    grad(0) = 2 * cxx * p(0) + cxy * p(1) + cxz * p(2) + cx;\n    grad(1) = 2 * cyy * p(1) + cxy * p(0) + cyz * p(2) + cy;\n    grad(2) = 2 * czz * p(2) + cxz * p(0) + cyz * p(1) + cz;\n  }\n\n  void \n  QuadraticSurface :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const\n  {\n    hesse(0,0) = 2 * cxx;\n    hesse(1,1) = 2 * cyy;\n    hesse(2,2) = 2 * czz;\n    hesse(0,1) = hesse(1,0) = cxy;\n    hesse(0,2) = hesse(2,0) = cxz;\n    hesse(1,2) = hesse(2,1) = cyz;\n  }\n\n\n  void QuadraticSurface :: Read (istream & ist)\n  {\n    ist >> cxx >> cyy >> czz >> cxy >> cxz >> cyz >> cx >> cy >> cz >> c1;\n  }\n\n  void QuadraticSurface :: Print (ostream & ost) const\n  {\n    ost << cxx << \"  \" << cyy << \"  \" << czz << \"  \"\n        << cxy << \"  \" << cxz << \"  \" << cyz << \"  \"\n        << cx << \"  \" << cy << \"  \" << cz << \"  \"\n        << c1;\n  }\n\n\n  void QuadraticSurface :: PrintCoeff (ostream & ost) const\n  {\n    ost << \" cxx = \" << cxx\n        << \" cyy = \" << cyy\n        << \" czz = \" << czz\n        << \" cxy = \" << cxy\n        << \" cxz = \" << cxz\n        << \" cyz = \" << cyz\n        << \" cx = \" << cx\n        << \" cy = \" << cy\n        << \" cz = \" << cz\n        << \" c1 = \" << c1 << endl;\n  }\n\n\n\n  Point<3> QuadraticSurface :: GetSurfacePoint () const\n  {\n    MyError (\"GetSurfacePoint called for QuadraticSurface\");\n    return Point<3> (0, 0, 0);\n  }\n\n\n  Plane :: Plane (const Point<3> & ap, Vec<3> an)\n  {\n    eps_base = 1e-8;\n\n    p = ap;\n    n = an;\n    CalcData();\n  }\n\n  void Plane :: CalcData()\n  {\n    n.Normalize();\n    cxx = cyy = czz = cxy = cxz = cyz = 0;\n    cx = n(0); cy = n(1); cz = n(2);\n    c1 = - (cx * p(0) + cy * p(1) + cz * p(2));\n  }\n\n  Primitive * Plane :: Copy () const\n  {\n    return new Plane (p, n);\n  }\n\n  void Plane :: Print (ostream & ost) const\n  {\n    ost << \"plane(\" << p << \"; \" << n << \")\";\n  }\n  \n\n  void Plane :: Transform (Transformation<3> & trans)\n  {\n    Point<3> hp;\n    Vec<3> hn;\n    trans.Transform (p, hp);\n    trans.Transform (n, hn);\n    p = hp;\n    n = hn;\n\n    CalcData();\n  }\n\n\n\n  void Plane :: GetPrimitiveData (const char *& classname, \n                                  NgArray<double> & coeffs) const\n  {\n    classname = \"plane\";\n    coeffs.SetSize (6);\n    coeffs.Elem(1) = p(0);\n    coeffs.Elem(2) = p(1);\n    coeffs.Elem(3) = p(2);\n    coeffs.Elem(4) = n(0);\n    coeffs.Elem(5) = n(1);\n    coeffs.Elem(6) = n(2);\n  }\n\n  void Plane :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    p(0) = coeffs.Elem(1);\n    p(1) = coeffs.Elem(2);\n    p(2) = coeffs.Elem(3);\n    n(0) = coeffs.Elem(4);\n    n(1) = coeffs.Elem(5);\n    n(2) = coeffs.Elem(6);\n\n    CalcData();\n  }\n\n  Primitive * Plane :: CreateDefault ()\n  {\n    return new Plane (Point<3> (0,0,0), Vec<3> (0,0,1));\n  }\n\n\n  int Plane :: IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const Plane * ps2 = dynamic_cast<const Plane*>(&s2);\n\n    if(ps2)\n      {\n        Point<3> pp2 = ps2->GetSurfacePoint();\n        Vec<3> n2 = s2.GetNormalVector(pp2);\n\n        if(fabs(n*n2) < 1.-eps_base)\n          return 0;\n\n        if (fabs (s2.CalcFunctionValue(p)) > eps) return 0;\n      }\n    else\n      {\n        if (fabs (s2.CalcFunctionValue(p)) > eps) return 0;\n        Vec<3> hv1, hv2;\n        hv1 = n.GetNormal ();\n        hv2 = Cross (n, hv1);\n      \n        Point<3> hp = p + hv1;\n        if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0;\n        hp = p + hv2;\n        if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0;\n      }\n\n    Vec<3> n1, n2;\n    n1 = GetNormalVector (p);\n    n2 = s2.GetNormalVector (p);\n    inv = (n1 * n2 < 0);\n    return 1;\n  }\n\n\n\n  void Plane :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)\n  {\n    Surface::DefineTangentialPlane (ap1, ap2);\n  }\n\n\n  void Plane :: ToPlane (const Point<3> & p3d, \n                         Point<2> & pplane, \n                         double h, int & zone) const\n  {\n    Vec<3> p1p;\n\n    p1p = p3d - p1;\n    p1p /= h;\n    pplane(0) = p1p * ex;\n    pplane(1) = p1p * ey;\n    zone = 0;\n  }\n\n  void Plane :: FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const\n  {\n    p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey;\n  }\n\n\n  void Plane :: Project (Point<3> & p3d) const\n  {\n    double val = Plane::CalcFunctionValue (p3d);\n    p3d -= val * n;\n  }\n\n  INSOLID_TYPE Plane :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    int i;\n    double val;\n    Point<3> pp;\n\n    val = Plane::CalcFunctionValue (box.Center());\n    if (val > box.Diam() / 2) return IS_OUTSIDE;\n    if (val < -box.Diam() / 2) return IS_INSIDE;\n\n    if (val > 0)\n      {\n        /*\n          double modify = \n          ((box.MaxX()-box.MinX()) * fabs (cx) + \n          (box.MaxY()-box.MinY()) * fabs (cy) + \n          (box.MaxZ()-box.MinZ()) * fabs (cz)) / 2;\n        */\n        Vec<3> vdiag = box.PMax() - box.PMin();\n        double modify = (vdiag(0) * fabs (cx) + \n                         vdiag(1) * fabs (cy) + \n                         vdiag(2) * fabs (cz) ) / 2;\n\n        if (val - modify < 0)\n          return DOES_INTERSECT;\n        return IS_OUTSIDE;\n\n        // only outside or intersect possible\n        for (i = 0; i < 8; i++)\n          {\n            pp = box.GetPointNr (i);\n            val = Plane::CalcFunctionValue (pp);\n            if (val < 0) \n              return DOES_INTERSECT;\n          }\n        return IS_OUTSIDE;\n      }\n    else\n      {\n        /*\n          double modify = \n          ((box.MaxX()-box.MinX()) * fabs (cx) + \n          (box.MaxY()-box.MinY()) * fabs (cy) + \n          (box.MaxZ()-box.MinZ()) * fabs (cz)) / 2;\n        */\n        Vec<3> vdiag = box.PMax() - box.PMin();\n        double modify =  (vdiag(0) * fabs (cx) + \n                          vdiag(1) * fabs (cy) + \n                          vdiag(2) * fabs (cz) ) / 2;\n        if (val + modify > 0)\n          return DOES_INTERSECT;\n        return IS_INSIDE;\n\n\n        // only inside or intersect possible\n        for (i = 0; i < 8; i++)\n          {\n            pp = box.GetPointNr (i);\n            val = Plane::CalcFunctionValue (pp);\n            if (val > 0) \n              return DOES_INTERSECT;\n          }\n        return IS_INSIDE;\n      }\n\n\n\n    /*\n      for (i = 1; i <= 8; i++)\n      {\n      box.GetPointNr (i, p);\n      val = CalcFunctionValue (p);\n      if (val > 0) inside = 0;\n      if (val < 0) outside = 0;\n      }\n\n      if (inside) return IS_INSIDE;\n      if (outside) return IS_OUTSIDE;\n      return DOES_INTERSECT;\n    */\n  }\n\n\n\n  // double Plane :: CalcFunctionValue (const Point<3> & p3d) const\n  // {\n  //   return cx * p3d(0) + cy * p3d(1) + cz * p3d(2) + c1;\n  // }\n\n  void Plane :: CalcGradient (const Point<3> & /* p */, Vec<3> & grad) const\n  {\n    grad(0) = cx;\n    grad(1) = cy;\n    grad(2) = cz;\n  }\n\n  void Plane :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const\n  {\n    hesse = 0;\n  }\n\n  double Plane :: HesseNorm () const\n  {\n    return 0;\n  }\n\n\n  Point<3> Plane :: GetSurfacePoint () const\n  {\n    return p;\n  }\n\n\n  void Plane :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & boundingbox, double /* facets */) const\n  {\n    // find triangle, such that\n    // boundingbox \\cap plane is contained in it\n\n    Point<3> c = boundingbox.Center();\n    double r = boundingbox.Diam();\n\n    Project (c);\n    Vec<3> t1 = n.GetNormal();\n    Vec<3> t2 = Cross (n, t1);\n\n    t1.Normalize();\n    t2.Normalize();\n\n    tas.AddPoint (c + (-0.5 * r) * t2 + (sqrt(0.75) * r) * t1);\n    tas.AddPoint (c + (-0.5 * r) * t2 + (-sqrt(0.75) * r) * t1);\n    tas.AddPoint (c +  r * t2);\n\n    tas.AddTriangle (TATriangle (0, 0, 1, 2));\n  }\n\n\n\n\n  Sphere :: Sphere (const Point<3> & ac, double ar)\n  {\n    c = ac;\n    r = ar;\n    invr = 1.0/r;\n\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - c(0) / r;\n    cy = - c(1) / r;\n    cz = - c(2) / r;\n    c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;\n  }\n\n  void Sphere :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"sphere\";\n    coeffs.SetSize (4);\n    coeffs.Elem(1) = c(0);\n    coeffs.Elem(2) = c(1);\n    coeffs.Elem(3) = c(2);\n    coeffs.Elem(4) = r;\n  }\n\n  void Sphere :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    c(0) = coeffs.Elem(1);\n    c(1) = coeffs.Elem(2);\n    c(2) = coeffs.Elem(3);\n    r = coeffs.Elem(4);\n\n    invr = 1.0/r;\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - c(0) / r;\n    cy = - c(1) / r;\n    cz = - c(2) / r;\n    c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;\n  }\n\n  Primitive * Sphere :: CreateDefault ()\n  {\n    return new Sphere (Point<3> (0,0,0), 1);\n  }\n\n\n\n  Primitive * Sphere :: Copy () const\n  {\n    return new Sphere (c, r);\n  }\n\n  void Sphere :: Transform (Transformation<3> & trans)\n  {\n    Point<3> hp;\n    trans.Transform (c, hp);\n    c = hp;\n\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - c(0) / r;\n    cy = - c(1) / r;\n    cz = - c(2) / r;\n    c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;\n  }\n\n\n  double Sphere :: CalcFunctionValue (const Point<3> & point) const\n  {\n    return 0.5* (invr * Abs2 (point-c) - r);\n  }\n\n\n  int Sphere :: IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const Sphere * sp2 = dynamic_cast<const Sphere*>  (&s2);\n\n    if (!sp2) return 0;\n\n    if (Dist (sp2->c, c) > eps) return 0;\n    if (fabs (sp2->r - r) > eps) return 0;\n\n    inv = 0;\n\n    return 1;\n  }\n\n\n  void Sphere :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)\n  {\n    Surface::DefineTangentialPlane (ap1, ap2);\n\n    ez = p1 - c;\n    ez /= ez.Length();\n\n    ex = p2 - p1;\n    ex -= (ex * ez) * ez;\n    ex /= ex.Length();\n\n    ey = Cross (ez, ex);\n  }\n\n\n  void Sphere :: ToPlane (const Point<3> & p, Point<2> & pplane, double h, int & zone) const\n  {\n    Vec<3> p1p;\n  \n    p1p = p - p1;\n  \n    /*\n      if (p1p * ez < -r)\n      {\n      zone = -1;\n      pplane = Point<2> (1E8, 1E8);\n      }\n      else\n      { \n      zone = 0;\n      p1p /= h;\n      pplane(0) = p1p * ex;\n      pplane(1) = p1p * ey;\n      }\n    */\n\n    Point<3> p1top = c + (c - p1);\n\n    Vec<3> p1topp = p - p1top;\n    Vec<3> p1topp1 = p1 - p1top;\n    Vec<3> lam;\n    //  SolveLinearSystem (ex, ey, p1topp, p1topp1, lam);\n\n    Mat<3> m;\n    for (int i = 0; i < 3; i++)\n      {\n        m(i, 0) = ex(i);\n        m(i, 1) = ey(i);\n        m(i, 2) = p1topp(i);\n      }\n    m.Solve (p1topp1, lam);\n\n    pplane(0) = -lam(0) / h;\n    pplane(1) = -lam(1) / h;\n  \n    if (lam(2) > 2)\n      zone = -1;\n    else \n      zone = 0;\n  }\n\n  void Sphere :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const\n  {\n    /*\n    //  Vec<3> p1p;\n    double z;\n    Point<2> pplane2 (pplane);\n\n    pplane2(0) *= h;\n    pplane2(1) *= h;\n    z = -r + sqrt (sqr (r) - sqr (pplane2(0)) - sqr (pplane2(1)));\n    //  p = p1;\n    p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0) + z * ez(0);\n    p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1) + z * ez(1);\n    p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2) + z * ez(2);\n    */\n\n    Point<2> pplane2 (pplane);\n\n    pplane2(0) *= h;\n    pplane2(1) *= h;\n\n    p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0);\n    p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1);\n    p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2);\n    Project (p);\n  }\n\n\n  void Sphere :: Project (Point<3> & p) const\n  {\n    Vec<3> v;\n    v = p - c;\n    v *= (r / v.Length());\n    p = c + v;\n  }\n\n\n  INSOLID_TYPE Sphere :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    double dist;\n    dist = Dist (box.Center(), c);\n\n    if (dist - box.Diam()/2 > r) return IS_OUTSIDE;\n    if (dist + box.Diam()/2 < r) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n  double Sphere :: HesseNorm () const\n  {\n    return 2 / r;\n  }\n\n\n  Point<3> Sphere :: GetSurfacePoint () const\n  {\n    // if two spheres touch at exactly that point meshing fails.\n    return c + r * Vec<3> (0.12345, 0.54321, 0.8304715488203073);\n  }\n\n\n  void Sphere :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & /* boundingbox */, double facets) const\n  {\n    int n = int(facets) + 1;  \n\n    for (int j = 0; j <= n; j++)\n      for (int i = 0; i <= n; i++)\n        {\n          double lg = 2 * M_PI * double (i) / n;\n          double bg = M_PI * (double(j) / n - 0.5);\n\n          Point<3> p(c(0) + r * cos(bg) * sin (lg),\n                     c(1) + r * cos(bg) * cos (lg),\n                     c(2) + r * sin(bg));\n          tas.AddPoint (p);\n        }\n\n    for (int j = 0; j < n; j++)\n      for (int i = 0; i < n; i++)\n        {\n          int pi = i + (n+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n        }\n  }\n\n\n\n\n\n  Ellipsoid :: \n  Ellipsoid (const Point<3> & aa,\n             const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3)\n  {\n    a = aa;\n    v1 = av1;\n    v2 = av2;\n    v3 = av3;\n\n    CalcData();\n  }\n\n\n  void Ellipsoid :: CalcData ()\n  {\n    // f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1\n    // f = sum_{i=1}^3  (x-a,v_i)^2 / |vi|^4 - 1   =  sum (x-a,hv_i)^2\n  \n    Vec<3> hv1, hv2, hv3;\n    double lv1 = v1.Length2 ();\n    if (lv1 < 1e-32) lv1 = 1;\n    double lv2 = v2.Length2 ();\n    if (lv2 < 1e-32) lv2 = 1;\n    double lv3 = v3.Length2 ();\n    if (lv3 < 1e-32) lv3 = 1;\n\n    rmin = sqrt (min3 (lv1, lv2, lv3));\n\n    hv1 = (1.0 / lv1) * v1;\n    hv2 = (1.0 / lv2) * v2;\n    hv3 = (1.0 / lv3) * v3;\n\n    cxx = hv1(0) * hv1(0) + hv2(0) * hv2(0) + hv3(0) * hv3(0);\n    cyy = hv1(1) * hv1(1) + hv2(1) * hv2(1) + hv3(1) * hv3(1);\n    czz = hv1(2) * hv1(2) + hv2(2) * hv2(2) + hv3(2) * hv3(2);\n\n    cxy = 2 * (hv1(0) * hv1(1) + hv2(0) * hv2(1) + hv3(0) * hv3(1));\n    cxz = 2 * (hv1(0) * hv1(2) + hv2(0) * hv2(2) + hv3(0) * hv3(2));\n    cyz = 2 * (hv1(1) * hv1(2) + hv2(1) * hv2(2) + hv3(1) * hv3(2));\n\n    Vec<3> va (a);\n    c1 = sqr(va * hv1) + sqr(va * hv2) + sqr(va * hv3) - 1;\n  \n    Vec<3> v = -2 * (va * hv1) * hv1 - 2 * (va * hv2) * hv2  - 2 * (va * hv3) * hv3;\n    cx = v(0);\n    cy = v(1);\n    cz = v(2);\n  }\n\n  void Ellipsoid :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"ellipsoid\";\n    coeffs.SetSize (12);\n    for(auto i : Range(3))\n      {\n        coeffs[i] = a(i);\n        coeffs[3+i] = v1(i);\n        coeffs[6+i] = v2(i);\n        coeffs[9+i] = v3(i);\n      }\n  }\n\n  void Ellipsoid :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    for(auto i : Range(3))\n      {\n        a(i) = coeffs[i];\n        v1(i) = coeffs[3+i];\n        v2(i) = coeffs[6+i];\n        v3(i) = coeffs[9+i];\n      }\n\n    CalcData();\n  }\n\n\n  INSOLID_TYPE Ellipsoid :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    // double grad = 2.0 / rmin;\n    // double grad = 3*(box.Center()-a).Length() / (rmin*rmin*rmin);\n\n    double ggrad = 1.0 / (rmin*rmin);\n    Vec<3> g;\n    double val = CalcFunctionValue (box.Center());\n    CalcGradient (box.Center(), g);\n    double grad = g.Length();\n\n    double r = box.Diam() / 2;\n    double maxval = grad * r + ggrad * r * r;\n\n    //  (*testout) << \"box = \" << box << \", val = \" << val << \", maxval = \" << maxval << endl;\n\n    if (val > maxval) return IS_OUTSIDE;\n    if (val < -maxval) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n\n  double Ellipsoid :: HesseNorm () const\n  {\n    return 1.0/ (rmin * rmin);\n  }\n\n  double Ellipsoid :: MaxCurvature () const\n  {\n    const double a2 = v1.Length2();\n    const double b2 = v2.Length2();\n    const double c2 = v3.Length2();\n\n    return max3 ( sqrt(a2)/min2(b2,c2), sqrt(b2)/min2(a2,c2), sqrt(c2)/min2(a2,b2) );\n  }\n\n  Point<3> Ellipsoid :: GetSurfacePoint () const\n  {\n    return a + v1;\n  }\n\n\n\n  void Ellipsoid :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & /* boundingbox */, double facets) const\n  {\n    int n = int(facets) + 1;  \n\n    for (int j = 0; j <= n; j++)\n      for (int i = 0; i <= n; i++)\n        {\n          double lg = 2 * M_PI * double (i) / n;\n          double bg = M_PI * (double(j) / n - 0.5);\n\n          Point<3> p(a + \n                     sin (bg) * v1 + \n                     cos (bg) * sin (lg) * v2 +\n                     cos (bg) * cos (lg) * v3);\n\n          tas.AddPoint (p);\n        }\n\n    for (int j = 0; j < n; j++)\n      for (int i = 0; i < n; i++)\n        {\n          int pi = i + (n+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n        }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  Cylinder :: Cylinder (NgArray<double> & coeffs)\n  {\n    SetPrimitiveData(coeffs);\n  }\n\n  Cylinder :: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar)\n  {\n    a = aa;\n    b = ab;\n    vab = (b - a);\n    vab /= vab.Length();\n    r = ar;\n\n    // ( <x,x> - 2 <x,a> + <a,a>\n    //   - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^2\n    //   - r^2) / (2r) = 0\n\n    double hv;\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - a(0) / r;\n    cy = - a(1) / r;\n    cz = - a(2) / r;\n    c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);\n    hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);\n    cxx -= vab(0) * vab(0) / (2 * r);\n    cyy -= vab(1) * vab(1) / (2 * r);\n    czz -= vab(2) * vab(2) / (2 * r);\n    cxy -= vab(0) * vab(1) / r;\n    cxz -= vab(0) * vab(2) / r;\n    cyz -= vab(1) * vab(2) / r;\n    cx += vab(0) * hv / r;\n    cy += vab(1) * hv / r;\n    cz += vab(2) * hv / r;\n    c1 -= hv * hv / (2 * r);\n    c1 -= r / 2;\n    //  PrintCoeff ();\n  }\n\n\n\n\n  void Cylinder :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"cylinder\";\n    coeffs.SetSize (7);\n    coeffs.Elem(1) = a(0);\n    coeffs.Elem(2) = a(1);\n    coeffs.Elem(3) = a(2);\n    coeffs.Elem(4) = b(0);\n    coeffs.Elem(5) = b(1);\n    coeffs.Elem(6) = b(2);\n    coeffs.Elem(7) = r;\n  }\n\n  void Cylinder :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    a(0) = coeffs.Elem(1);\n    a(1) = coeffs.Elem(2);\n    a(2) = coeffs.Elem(3);\n    b(0) = coeffs.Elem(4);\n    b(1) = coeffs.Elem(5);\n    b(2) = coeffs.Elem(6);\n    r = coeffs.Elem(7);\n\n\n    vab = (b - a);\n    vab /= vab.Length();\n\n\n    double hv;\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - a(0) / r;\n    cy = - a(1) / r;\n    cz = - a(2) / r;\n    c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);\n    hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);\n    cxx -= vab(0) * vab(0) / (2 * r);\n    cyy -= vab(1) * vab(1) / (2 * r);\n    czz -= vab(2) * vab(2) / (2 * r);\n    cxy -= vab(0) * vab(1) / r;\n    cxz -= vab(0) * vab(2) / r;\n    cyz -= vab(1) * vab(2) / r;\n    cx += vab(0) * hv / r;\n    cy += vab(1) * hv / r;\n    cz += vab(2) * hv / r;\n    c1 -= hv * hv / (2 * r);\n    c1 -= r / 2;\n  }\n\n  Primitive * Cylinder :: CreateDefault ()\n  {\n    return new Cylinder (Point<3> (0,0,0), Point<3> (1,0,0), 1);\n  }\n\n\n\n\n  Primitive * Cylinder :: Copy () const\n  {\n    return new Cylinder (a, b, r);\n  }\n\n  void Cylinder :: Print (ostream & ost) const\n  {\n    ost << \"cylinder(\" << a << \"; \" << b << \"; \" << r << \")\";\n  }\n\n  int Cylinder :: IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const Cylinder * cyl2 = dynamic_cast<const Cylinder*>  (&s2);\n\n    if (!cyl2) return 0;\n\n    if (fabs (cyl2->r - r) > eps) return 0;\n\n    Vec<3> v1 = b - a;\n    Vec<3> v2 = cyl2->a - a;\n\n    // if ( fabs (v1 * v2) < (1-1e-12) * v1.Length() * v2.Length()) return 0;\n    if ( Cross(v1,v2).Length2() > 1e-20 * v1.Length2() * v2.Length2()) return 0;\n    v2 = cyl2->b - a;\n    // if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;\n    if ( Cross(v1,v2).Length2() > 1e-20 * v1.Length2() * v2.Length2()) return 0;\n\n    inv = 0;\n    return 1;\n  }\n\n\n\n  void Cylinder :: Transform (Transformation<3> & trans)\n  {\n    Point<3> hp;\n    trans.Transform (a, hp);\n    a = hp;\n    trans.Transform (b, hp);\n    b = hp;\n\n    vab = (b - a);\n    vab /= vab.Length();\n\n    // ( <x,x> - 2 <x,a> + <a,a>\n    //   - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^2\n    //   - r^2) / (2r) = 0\n\n    double hv;\n    cxx = cyy = czz = 0.5 / r;\n    cxy = cxz = cyz = 0;\n    cx = - a(0) / r;\n    cy = - a(1) / r;\n    cz = - a(2) / r;\n    c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);\n    hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);\n    cxx -= vab(0) * vab(0) / (2 * r);\n    cyy -= vab(1) * vab(1) / (2 * r);\n    czz -= vab(2) * vab(2) / (2 * r);\n    cxy -= vab(0) * vab(1) / r;\n    cxz -= vab(0) * vab(2) / r;\n    cyz -= vab(1) * vab(2) / r;\n    cx += vab(0) * hv / r;\n    cy += vab(1) * hv / r;\n    cz += vab(2) * hv / r;\n    c1 -= hv * hv / (2 * r);\n    c1 -= r / 2;\n    //  PrintCoeff ();\n  }\n\n\n\n\n\n\n\n\n\n  void Cylinder :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)\n  {\n    Surface::DefineTangentialPlane (ap1, ap2);\n\n    ez = Center (p1, p2) - a;\n    ez -= (ez * vab) * vab;\n    ez /= ez.Length();\n\n    ex = p2 - p1;\n    ex -= (ex * ez) * ez;\n    ex /= ex.Length();\n\n    ey = Cross (ez, ex);\n  }\n\n\n  void Cylinder :: ToPlane (const Point<3> & p, \n                            Point<2> & pplane, \n                            double h, int & zone) const\n  {\n    Point<3> cp1p2 = Center (p1, p2);\n    Project (cp1p2);\n  \n    Point<3> ccp1p2 = a + ( (cp1p2 - a) * vab ) * vab;\n\n    Vec<3> er = cp1p2 - ccp1p2;\n    er.Normalize();\n    Vec<3> ephi = Cross (vab, er);\n\n    double co, si;\n    Point<2> p1p, p2p, pp;\n\n    co = er * (p1 - ccp1p2);\n    si = ephi * (p1 - ccp1p2);\n    p1p(0) = r * atan2 (si, co);\n    p1p(1) = vab * (p1 - ccp1p2);\n\n    co = er * (p2 - ccp1p2);\n    si = ephi * (p2 - ccp1p2);\n    p2p(0) = r * atan2 (si, co);\n    p2p(1) = vab * (p2 - ccp1p2);\n  \n    co = er * (p - ccp1p2);\n    si = ephi * (p - ccp1p2);\n\n    double phi = atan2 (si, co);\n    pp(0) = r * phi;\n    pp(1) = vab * (p - ccp1p2);\n  \n    zone = 0;\n    if (phi > 1.57) zone = 1;\n    if (phi < -1.57) zone = 2;\n\n\n\n    Vec<2> e2x = p2p - p1p;\n    e2x /= e2x.Length();\n\n    Vec<2> e2y (-e2x(1), e2x(0));\n\n    Vec<2> p1pp = pp - p1p;\n\n\n    pplane(0) = (p1pp * e2x) / h;\n    pplane(1) = (p1pp * e2y) / h;\n\n    /*\n      (*testout) << \"p1 = \" << p1 << \",  p2 = \" << p2 << endl;\n      (*testout) << \"p = \" << p << \",  pp = \" << pp << \",  pplane = \" << pplane << endl;\n    */\n\n    /*\n      Vec<3> p1p;\n\n      p1p = p - p1;\n\n      if (p1p * ez < -1 * r)\n      {\n      zone = -1;\n      pplane(0) = 1e8;\n      pplane(1) = 1e8;\n      }\n      else\n      {\n      zone = 0;\n      p1p /= h;\n      pplane(0) = p1p * ex;\n      pplane(1) = p1p * ey;\n      }\n    */\n  }\n\n  void Cylinder :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const\n  {\n    Point<2> pplane2 (pplane);\n\n    pplane2(0) *= h;\n    pplane2(1) *= h;\n\n    p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0);\n    p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1);\n    p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2);\n    Project (p);\n  }\n\n\n  void Cylinder :: Project (Point<3> & p) const\n  {\n    Vec<3> v;\n    Point<3> c;\n\n    c = a + ((p - a) * vab) * vab;\n    v = p - c;\n    v *= (r / v.Length());\n    p = c + v;\n  }\n  /*\n    int Cylinder :: RootInBox (const BoxSphere<3> & box) const\n    {\n    double dist;\n    dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r);\n    if (fabs (dist - r) > box.Diam()/2) return 0;\n    return 2;\n    }\n  */\n\n  INSOLID_TYPE Cylinder :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    double dist;\n    //  dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r);\n\n    dist =  (2 * CalcFunctionValue(box.Center()) * r + r * r);\n    if (dist <= 0) dist = 0;\n    else dist = sqrt (dist + 1e-16);\n\n    if (dist - box.Diam()/2 > r) return IS_OUTSIDE;\n    if (dist + box.Diam()/2 < r) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n\n  double Cylinder :: HesseNorm () const\n  {\n    return 2 / r;\n  }\n\n  Point<3> Cylinder :: GetSurfacePoint () const\n  {\n    Vec<3> vr;\n    if (fabs (vab(0)) > fabs(vab(2)))\n      vr = Vec<3> (vab(1), -vab(0), 0);\n    else\n      vr = Vec<3> (0, -vab(2), vab(1));\n    \n    vr *= (r / vr.Length());\n    return a + vr;\n  }\n\n  void Cylinder :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & /* boundingbox */, double facets) const\n  {\n    int n = int(facets) + 1;  \n\n    Vec<3> lvab = b - a;\n    Vec<3> n1 = lvab.GetNormal();\n    Vec<3> n2 = Cross (lvab, n1);\n  \n    n1.Normalize();\n    n2.Normalize();\n\n\n    for (int j = 0; j <= n; j++)\n      for (int i = 0; i <= n; i++)\n        {\n          double lg = 2 * M_PI * double (i) / n;\n          double bg = double(j) / n;\n\n          Point<3> p = a + (bg * lvab) \n            + ((r * cos(lg)) * n1) \n            + ((r * sin(lg)) * n2);\n\n          tas.AddPoint (p);\n        }\n\n    for (int j = 0; j < n; j++)\n      for (int i = 0; i < n; i++)\n        {\n          int pi = i + (n+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n        }\n  }\n\n\n\n\n\n\n\n\n\n  EllipticCylinder :: \n  EllipticCylinder (const Point<3> & aa,\n                    const Vec<3> & avl, const Vec<3> & avs)\n  {\n    a = aa;\n    if(avl.Length2() > avs.Length2())\n      {\n        vl = avl;\n        vs = avs;\n      }\n    else\n      {\n        vl = avs;\n        vs = avl;\n      }\n\n    CalcData();\n  }\n\n  EllipticCylinder :: EllipticCylinder (NgArray<double> & coeffs)\n  {\n    SetPrimitiveData(coeffs);\n  }\n\n\n\n  void EllipticCylinder :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"ellipticcylinder\";\n    coeffs.SetSize (9);\n    coeffs[0] = a(0);\n    coeffs[1] = a(1);\n    coeffs[2] = a(2);\n    coeffs[3] = vl(0);\n    coeffs[4] = vl(1);\n    coeffs[5] = vl(2);\n    coeffs[6] = vs(0);\n    coeffs[7] = vs(1);\n    coeffs[8] = vs(2);\n  }\n\n  void EllipticCylinder :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    a(0) = coeffs[0];\n    a(1) = coeffs[1];\n    a(2) = coeffs[2];\n    vl(0) = coeffs[3];\n    vl(1) = coeffs[4];\n    vl(2) = coeffs[5];\n    vs(0) = coeffs[6];\n    vs(1) = coeffs[7];\n    vs(2) = coeffs[8];\n\n    CalcData();\n  }\n\n\n\n  void EllipticCylinder :: CalcData ()\n  {\n    // f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1\n\n    Vec<3> hvl, hvs;\n    double lvl = vl.Length2 ();\n    if (lvl < 1e-32) lvl = 1;\n    double lvs = vs.Length2 ();\n    if (lvs < 1e-32) lvs = 1;\n\n    hvl = (1.0 / lvl) * vl;\n    hvs = (1.0 / lvs) * vs;\n\n    cxx = hvl(0) * hvl(0) + hvs(0) * hvs(0);\n    cyy = hvl(1) * hvl(1) + hvs(1) * hvs(1);\n    czz = hvl(2) * hvl(2) + hvs(2) * hvs(2);\n\n    cxy = 2 * (hvl(0) * hvl(1) + hvs(0) * hvs(1));\n    cxz = 2 * (hvl(0) * hvl(2) + hvs(0) * hvs(2));\n    cyz = 2 * (hvl(1) * hvl(2) + hvs(1) * hvs(2));\n\n    Vec<3> va (a);\n    c1 = pow(va * hvl,2) + pow(va * hvs,2) - 1;\n  \n    Vec<3> v = -2 * (va * hvl) * hvl - 2 * (va * hvs) * hvs;\n    cx = v(0);\n    cy = v(1);\n    cz = v(2);\n  }\n\n\n  INSOLID_TYPE EllipticCylinder :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    double grad = 2.0 / vs.Length ();\n    double ggrad = 1.0 / vs.Length2 ();\n\n    double val = CalcFunctionValue (box.Center());\n    double r = box.Diam() / 2;\n    double maxval = grad * r + ggrad * r * r;\n\n    // (*testout) << \"box = \" << box << \", val = \" << val << \", maxval = \" << maxval << endl;\n\n    if (val > maxval) return IS_OUTSIDE;\n    if (val < -maxval) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n\n  double EllipticCylinder :: HesseNorm () const\n  {\n    return 1.0/min(vs.Length2 (),vl.Length2());\n  }\n\n  double EllipticCylinder :: MaxCurvature () const\n  {\n    double aa = vs.Length();\n    double bb = vl.Length();\n\n    return max2(bb/(aa*aa),aa/(bb*bb));\n  }\n\n  double EllipticCylinder :: MaxCurvatureLoc (const Point<3> & /* c */, \n                                              double /* rad */) const\n  {\n    // saubere Loesung wird noch notwendig !!!\n    double aa = vs.Length();\n    double bb = vl.Length();\n    return max2(bb/(aa*aa),aa/(bb*bb));\n  }\n\n  int EllipticCylinder :: IsIdentic(const Surface& s2, int& inv, double eps) const\n  {\n    const EllipticCylinder* ps2 = dynamic_cast<const EllipticCylinder*>(&s2);\n    if (!ps2) return 0;\n\n    if((vl - ps2->vl).Length() > eps || (vs - ps2->vs).Length() > eps || (a-ps2->a).Length() > eps)\n      return 0;\n    return 1;\n  }\n\n  Point<3> EllipticCylinder :: GetSurfacePoint () const\n  {\n    return a + vl;\n  }\n\n\n\n  void EllipticCylinder :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & /* boundingbox */, double facets) const\n  {\n    int n = int(facets) + 1;  \n\n    Vec<3> axis = Cross (vl, vs);\n\n    for (int j = 0; j <= n; j++)\n      for (int i = 0; i <= n; i++)\n        {\n          double lg = 2 * M_PI * double (i) / n;\n          double bg = double(j) / n;\n\n          Point<3> p = a + (bg * axis)\n            + cos(lg) * vl + sin(lg) * vs;\n\n          tas.AddPoint (p);\n        }\n\n    for (int j = 0; j < n; j++)\n      for (int i = 0; i < n; i++)\n        {\n          int pi = i + (n+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n        }\n  }\n\n\n\n\n\n\n\n\n\n\n  Cone :: Cone (const Point<3> & aa, const Point<3> & ab, \n                double ara, double arb)\n  {\n    a = aa;\n    b = ab;\n    ra = ara;\n    rb = arb;\n\n    CalcData();\n    // Print (cout);\n  }\n\n\n  Primitive * Cone :: CreateDefault ()\n  {\n    return new Cone (Point<3> (0,0,0), Point<3> (1,0,0), 0.5, 0.2);\n  }\n\n\n\n\n  void Cone :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"cone\";\n    coeffs.SetSize (8);\n    coeffs.Elem(1) = a(0);\n    coeffs.Elem(2) = a(1);\n    coeffs.Elem(3) = a(2);\n    coeffs.Elem(4) = b(0);\n    coeffs.Elem(5) = b(1);\n    coeffs.Elem(6) = b(2);\n    coeffs.Elem(7) = ra;\n    coeffs.Elem(8) = rb;\n  }\n\n  void Cone :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    a(0) = coeffs.Elem(1);\n    a(1) = coeffs.Elem(2);\n    a(2) = coeffs.Elem(3);\n    b(0) = coeffs.Elem(4);\n    b(1) = coeffs.Elem(5);\n    b(2) = coeffs.Elem(6);\n    ra = coeffs.Elem(7);\n    rb = coeffs.Elem(8);\n\n    CalcData();\n  }\n\n  void Cone :: CalcData ()\n  {\n\n    minr = (ra < rb) ? ra : rb;\n\n    vab = b - a;\n    vabl = vab.Length();\n\n    Vec<3> va (a);\n\n    //\n    //   f = r(P)^2 - R(z(P))^2\n    //\n    //   z(P) = t0vec * P + t0 = (P-a, b-a)/(b-a,b-a)\n    //   R(z(P)) = t1vec * P + t1 = rb * z + ra * (1-z)\n    //   r(P)^2 =||P-a||^2 - ||a-b||^2 z^2k\n\n    cosphi = vabl / sqrt (vabl*vabl+sqr(ra-rb));\n\n    t0vec = vab;\n    t0vec /= (vabl * vabl);\n    t0 = -(va * vab) / (vabl * vabl);\n\n    t1vec = t0vec;\n    t1vec *= (rb - ra);\n    t1 = ra + (rb - ra) * t0; \n\n    cxx = cyy = czz = 1;\n    cxy = cxz = cyz = 0;\n\n    cxx = 1 - (vab*vab) * t0vec(0) * t0vec(0) - t1vec(0) * t1vec(0);\n    cyy = 1 - (vab*vab) * t0vec(1) * t0vec(1) - t1vec(1) * t1vec(1);\n    czz = 1 - (vab*vab) * t0vec(2) * t0vec(2) - t1vec(2) * t1vec(2);\n  \n    cxy = -2 * (vab * vab) * t0vec(0) * t0vec(1) - 2 * t1vec(0) * t1vec(1);\n    cxz = -2 * (vab * vab) * t0vec(0) * t0vec(2) - 2 * t1vec(0) * t1vec(2);\n    cyz = -2 * (vab * vab) * t0vec(1) * t0vec(2) - 2 * t1vec(1) * t1vec(2);\n\n    cx = -2 * a(0) - 2 * (vab * vab) * t0 * t0vec(0) - 2 * t1 * t1vec(0);\n    cy = -2 * a(1) - 2 * (vab * vab) * t0 * t0vec(1) - 2 * t1 * t1vec(1);\n    cz = -2 * a(2) - 2 * (vab * vab) * t0 * t0vec(2) - 2 * t1 * t1vec(2);\n\n    c1 = va.Length2() - (vab * vab) * t0 * t0 - t1 * t1;\n\n\n    double maxr = max2(ra,rb);\n    cxx /= maxr; cyy /= maxr; czz /= maxr;\n    cxy /= maxr; cxz /= maxr; cyz /= maxr;\n    cx /= maxr; cy /= maxr; cz /= maxr;\n    c1 /= maxr;\n\n\n    // (*testout) << \"t0vec = \" << t0vec << \" t0 = \" << t0 << endl;\n    // (*testout) << \"t1vec = \" << t1vec << \" t1 = \" << t1 << endl;\n    // PrintCoeff (*testout);\n  }\n\n\n  INSOLID_TYPE Cone :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    Vec<3> cv(box.Center());\n\n    double rzp = cv * t1vec + t1;\n    double dist = sqrt (CalcFunctionValue(box.Center()) *max2(ra,rb) + rzp * rzp) - rzp;\n\n    dist *= cosphi;\n    INSOLID_TYPE res = DOES_INTERSECT;\n\n    if (dist - box.Diam() > 0) res = IS_OUTSIDE;\n    if (dist + box.Diam() < 0) res = IS_INSIDE;\n\n    return res;\n  }\n\n\n  double Cone :: HesseNorm () const\n  {\n    // cout << \"2/minr = \" << 2/minr << \",  cxx .. = \" << cxx << \", \" << cyy << \", \" << czz << endl;\n    return 2 / minr;\n  }\n\n\n  double Cone ::  LocH (const Point<3> & p, double /* x */, \n                        double /* c */, \n                        const MeshingParameters & mparam, double hmax) const\n  {\n    //double bloch = Surface::LocH (p, x, c, hmax);\n    Vec<3> g;\n    CalcGradient (p, g);\n\n    double lam = Abs(g);\n    double meancurv = \n      -( 2  * g(0)*g(1)*cxy - 2 * czz * (g(0)*g(0)+g(1)*g(1))\n         +2 * g(1)*g(2)*cyz - 2 * cxx * (g(1)*g(1)+g(2)*g(2))\n         +2 * g(0)*g(2)*cxz - 2 * cyy * (g(0)*g(0)+g(2)*g(2))) / (3*lam*lam*lam);\n\n    // cout << \"type = \" << typeid(*this).name() << \", baseh = \" << bloch << \", meancurv = \" << meancurv << endl;\n    // return bloch;\n  \n    meancurv = fabs (meancurv);\n    if (meancurv < 1e-20) meancurv = 1e-20;\n\n    // cout << \"c = \" << c << \", safety = \" << mparam.curvaturesafety << endl;\n    double hcurv = 1.0/(4*meancurv*mparam.curvaturesafety);\n\n    return min2 (hmax, hcurv);\n  }\n\n\n  Point<3> Cone :: GetSurfacePoint () const\n  {\n    Vec<3> vr = vab.GetNormal ();\n  \n    vr *= (ra / vr.Length());\n    return a + vr;\n  }\n\n\n\n\n\n  void Cone :: GetTriangleApproximation \n  (TriangleApproximation & tas, \n   const Box<3> & /* boundingbox */, double facets) const\n  {\n    int i, j;\n    double lg, bg;\n    int n = int(facets) + 1;  \n\n    Vec<3> lvab = b - a;\n    Vec<3> n1 = lvab.GetNormal();\n    Vec<3> n2 = Cross (lvab, n1);\n  \n    n1.Normalize();\n    n2.Normalize();\n\n\n    for (j = 0; j <= n; j++)\n      for (i = 0; i <= n; i++)\n        {\n          lg = 2 * M_PI * double (i) / n;\n          bg = double(j) / n;\n\n          Point<3> p = a + (bg * lvab) \n            + (( (ra+(rb-ra)*bg)  * cos(lg)) * n1) \n            + (( (ra+(rb-ra)*bg)  * sin(lg)) * n2);\n\n          tas.AddPoint (p);\n        }\n\n    for (j = 0; j < n; j++)\n      for (i = 0; i < n; i++)\n        {\n          int pi = i + (n+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n        }\n  }\n\n\n\n\n/// Elliptic Cone\n/// Josephat Kalezhi (kalezhi@cbu.ac.zm)\n/// February 21st, 2018\n///\n\nEllipticCone :: EllipticCone (const Point<3> & aa, const Vec<3> & avl,\n\t      const Vec<3> & avs, double ah, double avlr)\n{\n  a = aa;\n  h = ah;\n  vlr = avlr;\n\n  if (avl.Length2() >= avs.Length2())\n     {\n \tvl = avl;\n \tvs = avs;\n      }\n  else\n     {\n\tvl = avs;\n\tvs = avl;\n     }\n\n\n  CalcData();\n  // Print (cout);\n}\n\n\nPrimitive * EllipticCone :: CreateDefault ()\n  {\n    return new EllipticCone (Point<3> (0,0,0), Vec<3> (1,0,0), Vec<3> (0,1,0), 1, 0.5);\n  }\n\n\n void EllipticCone :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"ellipticcone\";\n    coeffs.SetSize (11);\n    coeffs.Elem(1) = a(0);\n    coeffs.Elem(2) = a(1);\n    coeffs.Elem(3) = a(2);\n    coeffs.Elem(4) = vl(0);\n    coeffs.Elem(5) = vl(1);\n    coeffs.Elem(6) = vl(2);\n    coeffs.Elem(7) = vs(0);\n    coeffs.Elem(8) = vs(1);\n    coeffs.Elem(9) = vs(2);\n    coeffs.Elem(10) = h;\n    coeffs.Elem(11) = vlr;\n\n  }\n\n\n  void EllipticCone :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n\n    a(0) = coeffs.Elem(1);\n    a(1) = coeffs.Elem(2);\n    a(2) = coeffs.Elem(3);\n    vl(0) = coeffs.Elem(4);\n    vl(1) = coeffs.Elem(5);\n    vl(2) = coeffs.Elem(6);\n    vs(0) = coeffs.Elem(7);\n    vs(1) = coeffs.Elem(8);\n    vs(2) = coeffs.Elem(9);\n    h = coeffs.Elem(10);\n    vlr = coeffs.Elem(11);\n    CalcData();\n  }\n\n\n\nvoid EllipticCone :: CalcData ()\n{\n  Vec<3> nh = Cross(vl, vs);\n  nh.Normalize();\n\n  double lvl = vl.Length();\n  double lvs = vs.Length();\n\n  Vec<3> t1vec = lvl*(vlr -1)*(1/h)*nh;\n\n  Vec<3> va (a);\n  double t1 = lvl*(1 - (vlr -1)*(1/h)*(va*nh));\n\n  Vec<3> nvl = (1.0/lvl)*vl;\n  Vec<3> nvs = (1.0/lvs)*vs;\n  double ellipt2 = sqr(lvl/lvs);\n\n  cxx = nvl(0)*nvl(0) + ellipt2*nvs(0)*nvs(0) - t1vec(0)*t1vec(0);\n  cyy = nvl(1)*nvl(1) + ellipt2*nvs(1)*nvs(1) - t1vec(1)*t1vec(1);\n  czz = nvl(2)*nvl(2) + ellipt2*nvs(2)*nvs(2) - t1vec(2)*t1vec(2);\n\n  cxy = 2*(nvl(0)*nvl(1) + ellipt2*nvs(0)*nvs(1) - t1vec(0)*t1vec(1));\n  cxz = 2*(nvl(0)*nvl(2) + ellipt2*nvs(0)*nvs(2) - t1vec(0)*t1vec(2));\n  cyz = 2*(nvl(1)*nvl(2) + ellipt2*nvs(1)*nvs(2) - t1vec(1)*t1vec(2));\n\n  Vec<3> v = -2*((va*nvl)*nvl + ellipt2*(va*nvs)*nvs + t1*t1vec);\n  cx = v(0);\n  cy = v(1);\n  cz = v(2);\n\n  c1 = pow(va*nvl,2) + ellipt2*pow(va*nvs,2) - t1*t1;\n\n  double lvltop = vlr*lvl;\n  // double minlvl = (lvl < lvltop) ? lvl : lvltop;\n  double maxlvl = max2( lvl,lvltop);\n  cxx /= maxlvl; cyy /= maxlvl; czz /= maxlvl;\n  cxy /= maxlvl; cxz /= maxlvl; cyz /= maxlvl;\n  cx /= maxlvl;  cy /= maxlvl;\tcz /= maxlvl;\n  c1 /= maxlvl;\n}\n\n\nINSOLID_TYPE EllipticCone :: BoxInSolid (const BoxSphere<3> & box) const\n{\n  double rp, dist;\n\n  Vec<3> cv( box.Center());\n  Vec<3> nh = Cross(vl, vs);\n  nh.Normalize();\n\n  double lvl = vl.Length();\n  Vec<3> t1vec = lvl*(vlr -1)*(1/h)*nh;\n  Vec<3> va (a);\n  double t1 = lvl*(1 - (vlr -1)*(1/h)*(va*nh));\n  rp = cv*t1vec + t1;\n  double lvltop = vlr*lvl;\n  double maxlvl = max2( lvl,lvltop);\n\n  dist = sqrt( CalcFunctionValue(box.Center())*maxlvl + rp*rp) - rp;\n\n  if (dist -  box.Diam() > 0) return IS_OUTSIDE;\n  if (dist + box.Diam() < 0) return IS_INSIDE;\n  return DOES_INTERSECT;\n}\n\ndouble EllipticCone :: HesseNorm () const\n{\n  return 1.0/min(vs.Length2 (),vl.Length2());\n}\n\ndouble EllipticCone :: MaxCurvature () const\n{\n  double a = vs.Length();\n  double b = vl.Length();\n\n  return max2(b/(a*a),a/(b*b));\n}\n\ndouble EllipticCone :: MaxCurvatureLoc (const Point<3> & c,\n                                            double rad) const\n{\n#ifdef JOACHIMxxx\n  cout << \"max curv local\" << endl;\n  return 0.02;\n#endif\n\n  // saubere Loesung wird noch notwendig !!!\n  double a = vs.Length();\n  double b = vl.Length();\n  return max2(b/(a*a),a/(b*b));\n}\n\nPoint<3> EllipticCone :: GetSurfacePoint () const\n{\n  return a + vl;\n}\n\n\nvoid EllipticCone :: GetTriangleApproximation\n(TriangleApproximation & tas,\n const Box<3> & boundingbox, double facets) const\n{\n  int i, j;\n  double lg, bg;\n  int n = int(facets) + 1;\n\n  Vec<3> nh = Cross(vl, vs);\n  nh.Normalize();\n  Vec<3> vh = h*nh;\n\n  double lvl = vl.Length();\n  double lvs = vs.Length();\n  Vec<3> nvl = (1.0/lvl)*vl;\n  Vec<3> nvs = (1.0/lvs)*vs;\n\n  for ( j = 0; j <= n; j++ )\n    for (i = 0; i <= n; i++)\n      {\n\tlg = 2 *M_PI * double (i) /n;\n\tbg = double(j) /n;\n\n\tPoint<3> p = a + (bg *vh)\n\t  + (( lvl*(1 + (vlr -1)*bg) * cos(lg)) * nvl)\n          + (( lvs*(1 + (vlr -1)*bg)* sin(lg) ) * nvs);\n\n\ttas.AddPoint (p);\n     }\n\n  for ( j = 0; j < n; j++)\n    for ( i = 0; i < n; i++)\n      {\n\tint pi = i + (n+1) * j;\n\ttas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));\n\ttas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));\n      }\n}\n\n\n\n  /// Torus \n  /// Lorenzo Codecasa (codecasa@elet.polimi.it)\n  /// April 27th, 2005 \n  ///\n  Torus :: Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar)\n  {\n    c = ac;\n    n = an;\n    n.Normalize();\n    R = aR;\n    r = ar;\n  }\n\n  void Torus :: GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n  {\n    classname = \"torus\";\n    coeffs.SetSize (8);\n    coeffs.Elem(1) = c(0);\n    coeffs.Elem(2) = c(1);\n    coeffs.Elem(3) = c(2);\n    coeffs.Elem(4) = n(0);\n    coeffs.Elem(5) = n(1);\n    coeffs.Elem(6) = n(2);\n    coeffs.Elem(7) = R;\n    coeffs.Elem(8) = r;\n  }\n\n  void Torus :: SetPrimitiveData (NgArray<double> & coeffs)\n  {\n    c(0) = coeffs.Elem(1);\n    c(1) = coeffs.Elem(2);\n    c(2) = coeffs.Elem(3);\n    n(0) = coeffs.Elem(4);\n    n(1) = coeffs.Elem(5);\n    n(2) = coeffs.Elem(6);\n    R = coeffs.Elem(7);\n    r = coeffs.Elem(8);\n  }\n\n  Primitive * Torus :: CreateDefault ()\n  {\n    return new Torus (Point<3> (0,0,0), Vec<3> (0,0,1), 2, 1);\n  }\n\n  Primitive * Torus :: Copy () const\n  {\n    return new Torus (c, n, R, r);\n  }\n\n  void Torus :: Transform (Transformation<3> & trans)\n  {\n    Point<3> hc;\n    trans.Transform (c, hc);\n    c = hc;\n  \n    Vec<3> hn;\n    trans.Transform (n, hn);\n    n = hn;\n  }\n\n  int Torus :: IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const Torus * torus2 = dynamic_cast<const Torus*>  (&s2);\n\n    if (!torus2) return 0;\n\n    if (fabs (torus2->R - R) > eps) return 0;\n  \n    if (fabs (torus2->r - r) > eps) return 0;\n\n    Vec<3> v2 = torus2->n - n;\n    if ( v2 * v2 > eps ) return 0;\n  \n    v2 = torus2->c - c;\n    if ( v2 * v2 > eps ) return 0;\n\n    inv = 0;\n    return 1;\n  }\n\n  double Torus :: CalcFunctionValue (const Point<3> & point) const\n  {\n    /*\n    // original version\n    Vec<3> v1 = point - c;\n    double a1 = Abs2 (v1);         // v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);\n    double a2 = n * v1;            // n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);\n    double a3 = a1 + R * R - r * r;\n    double a4 = Abs2 (n);          // n(0) * n(0) + n(1) * n(1) + n(2) * n(2);\n\n    return ( a3 * a3 -4 * R * R * ( a1 - a2 * a2 / a4 ) ) / ( R * R * R );\n    */\n\n    \n    // JS, April 2011\n    Vec<3> v1 = point-c;\n    double abs2 = Abs2(v1);\n    double tau = v1 * n;\n    double rho = sqrt (abs2 - tau*tau);\n    return sqr (R - rho) + tau*tau - r*r;\n\n    // double val2 = sqr (tau*tau + sqr (R - rho) -r*r) / (R*R*R);\n  }\n\n  void Torus :: CalcGradient (const Point<3> & point, Vec<3> & grad) const\n  {\n    /*\n    Vec<3> v1 = point - c;\n    double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);\n    double a2 = n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);\n    double a3 = a1 - R * R - r * r;\n    double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);\n    grad(0) = ( 4 * a3 * v1(0) + 8 * R * R * a2 / a4 * n(0) ) / ( R * R * R );\n    grad(1) = ( 4 * a3 * v1(1) + 8 * R * R * a2 / a4 * n(1) ) / ( R * R * R );\n    grad(2) = ( 4 * a3 * v1(2) + 8 * R * R * a2 / a4 * n(2) ) / ( R * R * R );\n    */\n\n    Vec<3> v1 = point-c;\n    double abs2 = Abs2(v1);\n    double tau = v1 * n;\n    double rho = sqrt (abs2 - tau*tau);\n    // double func = sqr (R - rho) + tau*tau - r*r;\n\n    Vec<3> gradabs2 = 2 * v1;\n    Vec<3> gradtau = n;\n    Vec<3> gradrho = 0.5 / rho * (gradabs2 - 2 * tau * gradtau);\n    grad = -2 * (R - rho) * gradrho  + 2 * tau * gradtau;\n  }\n\n  void Torus :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const\n  {\n    Surface::CalcHesse (point, hesse);\n    return;\n\n    Vec<3> v1 = point - c;\n    double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);\n    double a3 = a1 - R * R - r * r;\n    double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);\n    hesse(0,0) = ( 4 * a3 + 8 * (v1(0) * v1(0) + (R * n(0)) * (R * n(0)) / a4 ) ) / ( R * R * R );\n    hesse(1,1) = ( 4 * a3 + 8 * (v1(1) * v1(1) + (R * n(1)) * (R * n(1)) / a4 ) ) / ( R * R * R );\n    hesse(2,2) = ( 4 * a3 + 8 * (v1(2) * v1(2) + (R * n(2)) * (R * n(2)) / a4 ) ) / ( R * R * R );\n    hesse(0,1) = hesse(1,0) = 8 * (v1(0) * v1(1) + (R * n(0)) * (R * n(1)) / a4 ) / ( R * R * R );\n    hesse(1,2) = hesse(2,1) = 8 * (v1(1) * v1(2) + (R * n(1)) * (R * n(2)) / a4) / ( R * R * R );\n    hesse(0,2) = hesse(2,0) = 8 * (v1(0) * v1(2) + (R * n(0)) * (R * n(2)) / a4) / ( R * R * R );\n  }\n\n  double Torus :: HesseNorm () const\n  {\t\n    return 4/(r*r);\n    // return  ( 2 / r + 2 / ( R - r ) );\n  }\n\n  Point<3> Torus :: GetSurfacePoint () const\n  {\n    Vec<3> vn = n.GetNormal();\n    return c + ( R + r ) * vn.Normalize();\n  }\n\n  /// void Torus :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)\n  /// {\n  /// }\n\n  /// void Torus :: ToPlane (const Point<3> & p, \n  ///\t\t\t  Point<2> & pplane, \n  ///\t\t\t  double h, int & zone) const\n  /// {\n  /// }\n\n  /// void Torus :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const\n  /// {\n  /// }\n\n  /// void Torus :: Project (Point<3> & p) const\n  /// {\n  /// }\n\n  INSOLID_TYPE Torus :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    Vec<3> v1 = box.Center() - c;\n    double a1 = Abs2(v1);        // v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);\n    double a2 = n * v1;          // n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);\n    double a4 = Abs2(n);         // n(0) * n(0) + n(1) * n(1) + n(2) * n(2);\n \n    double dist = sqrt( a1 + R * R - 2 * R * sqrt( a1 - a2 * a2 / a4) );\n\n    if (dist - box.Diam()/2 > r) return IS_OUTSIDE;\n    if (dist + box.Diam()/2 < r) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n  void Torus :: GetTriangleApproximation (TriangleApproximation & tas, \n                                          const Box<3> & /* boundingbox */, double facets) const\n  {\n    int N = int(facets) + 1;  \n\n    Vec<3> lvab = n ;\n    lvab.Normalize();\n  \n    Vec<3> n1 = lvab.GetNormal();\n    n1.Normalize();\n  \n    Vec<3> n2 = Cross(lvab, n1);\n    n2.Normalize();\n  \n    for (int j = 0; j <= N; j++)\n      for (int i = 0; i <= N; i++)\n\t{\n          double lg = 2 * M_PI * double (i) / N;\n          double bg = 2 * M_PI * double(j) / N;\n\t\n          Point<3> p = c + ( R + r * cos(lg) ) * ( cos(bg) * n1 + sin(bg) * n2 ) + r * sin(lg) * n;\n          tas.AddPoint (p);\n\t}\n\t\n    for (int j = 0; j < N; j++)\n      for (int i = 0; i < N; i++)\n\t{\n          int pi = i + (N+1) * j;\n          tas.AddTriangle (TATriangle (0, pi, pi+1, pi+N+2));\n          tas.AddTriangle (TATriangle (0, pi, pi+N+2, pi+N+1));\n\t}\n  } \n  \n  void Torus :: Read (istream & ist)\n  {\n    ist >> c(0) >> c(1) >> c(2) >> n(0) >> n(1) >> n(2) >> R >> r;\n  }\n\n  void Torus :: Print (ostream & ost) const\n  {\n    ost << c(0) << \"  \" << c(1) << \"  \" << c(2) << \"  \"\n        << n(0) << \"  \" << n(1) << \"  \" << n(2) << \"  \"\n        << R    << \"  \" << r    << endl;\n  }\n\nRegisterClassForArchive<QuadraticSurface, OneSurfacePrimitive> regqs;\nRegisterClassForArchive<Plane, QuadraticSurface> regpl;\nRegisterClassForArchive<Sphere, QuadraticSurface> regsph;\nRegisterClassForArchive<Cylinder, QuadraticSurface> regcyl;\nRegisterClassForArchive<EllipticCylinder, QuadraticSurface> regelcyl;\nRegisterClassForArchive<Ellipsoid, QuadraticSurface> regell;\nRegisterClassForArchive<Cone, QuadraticSurface> regcone;\nRegisterClassForArchive<EllipticCone, QuadraticSurface> regellcone;\nRegisterClassForArchive<Torus, OneSurfacePrimitive> regtorus;\n}\n"
  },
  {
    "path": "libsrc/csg/algprim.hpp",
    "content": "#ifndef FILE_ALGPRIM\n#define FILE_ALGPRIM\n\n\n/**************************************************************************/\n/* File:   algprim.hpp                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   1. Dez. 95                                                     */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  /*\n\n  Quadric Surfaces (Plane, Sphere, Cylinder)\n  \n  */\n\n\n  /**\n     A quadric surface.\n     surface defined by\n     cxx x^2 + cyy y^2 + czz z^2 + cxy x y + cxz x z + cyz y z +\n     cx x + cy y + cz z + c1 = 0.\n  **/\n  class QuadraticSurface : public  OneSurfacePrimitive\n  {\n  protected:\n    double cxx, cyy, czz, cxy, cxz, cyz, cx, cy, cz, c1;\n\n  public:\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n    /*\n      virtual int RootInBox (const Box<3> & box) \n      const { return 0; }\n      virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) \n      const { return DOES_INTERSECT; }\n    */\n    virtual double HesseNorm () const { return cxx + cyy + czz; }\n\n    virtual Point<3> GetSurfacePoint () const;\n\n\n    virtual void Print (ostream & str) const;\n    virtual void Read (istream & ist);\n    void PrintCoeff (ostream & ost) const;\n    virtual void DoArchive(Archive& ar)\n    {\n      OneSurfacePrimitive::DoArchive(ar);\n      ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1;\n    }\n  };\n\n\n  /// A Plane (i.e., the plane and everything behind it).\n  class Plane : public QuadraticSurface\n  {\n  protected:\n    /// a point in the plane\n    Point<3> p;\n    /// outward normal vector \n    Vec<3> n;\n\n    double eps_base;\n\n  public:\n    ///\n    Plane (const Point<3> & ap, Vec<3> an);\n    // default constructor for archive\n    Plane() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & p & n & eps_base;\n    }\n    Point<3> P() const { return p; }\n    Vec<3> N() const { return n; }\n    virtual void GetPrimitiveData (const char *& classname, \n\t\t\t\t   NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n    static Primitive * CreateDefault ();\n\n    virtual Primitive * Copy () const;\n    virtual void Print (ostream & str) const;\n\n    virtual void Transform (Transformation<3> & trans);\n\n\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;\n\n    ///\n    virtual void DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t\tconst Point<3> & ap2);\n    ///\n    virtual void ToPlane (const Point<3> & p3d, \n\t\t\t  Point<2> & pplane, double h,\n\t\t\t  int & zone) const;\n    ///\n    virtual void FromPlane (const Point<2> & pplane, \n\t\t\t    Point<3> & p3d, \n\t\t\t    double h) const;\n    ///\n    virtual void Project (Point<3> & p) const;\n\n    ///\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n\n    ///\n    inline virtual double CalcFunctionValue (const Point<3> & p3d) const\n    {return cx * p3d(0) + cy * p3d(1) + cz * p3d(2) + c1;}\n    ///\n    virtual void CalcGradient (const Point<3> & point, \n\t\t\t       Vec<3> & grad) const;\n    ///\n    virtual void CalcHesse (const Point<3> & point, \n\t\t\t    Mat<3> & hesse) const;\n    ///\n    virtual double HesseNorm () const;\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n    ///\n    virtual void GetTriangleApproximation \n    (TriangleApproximation & tas, \n     const Box<3> & boundingbox, double facets) const;\n  protected:\n    void CalcData();\n  };\n\n  // typedef Plane Plane;\n\n\n  ///\n  class Sphere : public QuadraticSurface\n  {\n    ///\n    Point<3> c;\n    ///\n    double r, invr;\n  public:\n    ///\n    Sphere (const Point<3> & ac, double ar);\n    // default constructor for archive\n    Sphere() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & c & r & invr;\n    }\n\n    virtual void GetPrimitiveData (const char *& classname, \n\t\t\t\t   NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n    static Primitive * CreateDefault ();\n\n    virtual Primitive * Copy () const;\n    virtual void Transform (Transformation<3> & trans);\n\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n\n\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;\n\n    ///\n    virtual void DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t\tconst Point<3> & ap2);\n    ///\n    virtual void ToPlane (const Point<3> & p3d, \n\t\t\t  Point<2> & pplane, double h,\n\t\t\t  int & zone) const;\n    ///\n    virtual void FromPlane (const Point<2> & pplane, \n\t\t\t    Point<3> & p, double h) const;\n    ///\n    virtual void Project (Point<3> & p) const;\n\n    ///\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    ///\n    virtual double HesseNorm () const;\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n    ///\n    const Point<3> & Center () const { return c; }\n    ///\n    double Radius () const { return r; }\n\n    ///\n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const;\n  };\n\n\n  ///\n  class Cylinder : public QuadraticSurface\n  {\n    ///\n    Point<3> a, b;\n    ///\n    double r;\n    ///\n    Vec<3> vab;\n\n  public:\n    Cylinder (const Point<3> & aa, const Point<3> & ab, double ar);\n    Cylinder (NgArray<double> & coeffs);\n    // default constructor for archive\n    Cylinder() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & a & b & r & vab;\n    }\n    Point<3> A() const { return a; }\n    Point<3> B() const { return b; }\n    double R() const { return r; }\n    virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n    static Primitive * CreateDefault ();\n\n    virtual Primitive * Copy () const;\n    virtual void Print (ostream & str) const;\n\n    virtual void Transform (Transformation<3> & trans);\n\n    ///\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;\n    ///\n    virtual void DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t\tconst Point<3> & ap2);\n    ///\n    virtual void ToPlane (const Point<3> & p, \n\t\t\t  Point<2> & pplane, \n\t\t\t  double h,\n\t\t\t  int & zone) const;\n    ///\n    virtual void FromPlane (const Point<2> & pplane, \n\t\t\t    Point<3> & p, \n\t\t\t    double h) const;\n    ///\n    virtual void Project (Point<3> & p) const;\n\n    ///\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    ///\n    virtual double HesseNorm () const;\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n    ///\n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const;\n  };\n\n\n\n\n\n  ///\n  class EllipticCylinder : public QuadraticSurface\n  {\n  private:\n    ///\n    Point<3> a;\n    ///\n    Vec<3> vl, vs;\n    ///\n    Vec<3> vab, t0vec, t1vec;\n    ///\n    double vabl, t0, t1;\n  public:\n    ///\n    EllipticCylinder (const Point<3> & aa,\n\t\t      const Vec<3> & avl, const Vec<3> & avs);\n    EllipticCylinder (NgArray<double> & coeffs);\n    // default constructor for archive\n    EllipticCylinder() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & a & vl & vs & vab & t0vec & t1vec & vabl & t0 & t1;\n    }\n\n    // static Primitive * CreateDefault ();\n    virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n\n    ///\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    ///\n    virtual double HesseNorm () const;\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n\n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const;\n\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;\n\n    virtual double MaxCurvature () const;\n\n    virtual double MaxCurvatureLoc (const Point<3> & /* c */ , \n\t\t\t\t    double /* rad */) const;\n\n\n  private:\n    void CalcData();\n  };\n\n\n\n\n\n\n  ///\n  class Ellipsoid : public QuadraticSurface\n  {\n  private:\n    ///\n    Point<3> a;\n    ///\n    Vec<3> v1, v2, v3;\n    ///\n    double rmin;\n  public:\n    ///\n    Ellipsoid (const Point<3> & aa,\n\t       const Vec<3> & av1, \n\t       const Vec<3> & av2,\n\t       const Vec<3> & av3);\n    // default constructor for archive\n    Ellipsoid() {}\n\n    void DoArchive(Archive& ar) override\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & a & v1 & v2 & v3 & rmin;\n    }\n    ///\n    INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const override;\n    ///\n    double HesseNorm () const override;\n    ///\n    double MaxCurvature () const override;\n    ///\n    Point<3> GetSurfacePoint () const override;\n\n    void GetTriangleApproximation (TriangleApproximation & tas,\n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const override;\n\n    void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const override;\n    void SetPrimitiveData (NgArray<double> & coeffs) override;\n\n  private:\n    void CalcData();\n  };\n\n\n\n\n\n\n\n\n  ///\n  class Cone : public QuadraticSurface\n  {\n    ///\n    Point<3> a, b;\n    ///\n    double ra, rb, minr;\n    ///\n    Vec<3> vab, t0vec, t1vec;\n    ///\n    double vabl, t0, t1;\n    double cosphi;\n  public:\n    ///\n    Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb);\n    ///\n    // default constructor for archive\n    Cone() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi;\n    }\n    static Primitive * CreateDefault ();\n    virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n\n    ///\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    ///\n    virtual double HesseNorm () const;\n\n    virtual double LocH (const Point<3> & p, double x, \n\t\t\t double c,                          \n                         const MeshingParameters & mparam,\n                         double hmax) const;\n\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n\n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const;\n\n  private:\n    void CalcData();\n  };\n\n\n///\n\n/// Elliptic Cone\n/// Josephat Kalezhi (kalezhi@cbu.ac.zm)\n/// February 21st, 2018\n///\n\n  ///\n  class EllipticCone : public QuadraticSurface\n  {\n\tPoint<3> a;\n\tVec<3> vl, vs;\n\tdouble h, vlr;\n\n  public:\n  ///\n  EllipticCone (const Point<3> & aa, const Vec<3> & avl,\n\t      const Vec<3> & avs, double ah, double avlr);\n    // default constructor for archive\n    EllipticCone() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      QuadraticSurface::DoArchive(ar);\n      ar & a & vl & vs & h & vlr;\n    }\n  static Primitive * CreateDefault ();\n  virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const;\n  virtual void SetPrimitiveData (NgArray<double> & coeffs);\n\n  ///\n  virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n  ///\n  virtual double HesseNorm () const;\n  virtual double MaxCurvature () const;\n  virtual double MaxCurvatureLoc (const Point<3> & /* c */ ,\n\t\t\t\t  double /* rad */) const;\n  ///\n  virtual Point<3> GetSurfacePoint () const;\n\n  virtual void GetTriangleApproximation (TriangleApproximation & tas,\n\t\t\t\t\t const Box<3> & bbox,\n\t\t\t\t\t double facets) const;\n\n  private:\n  void CalcData();\n  };\n\n\n  /** Torus \n  /// Lorenzo Codecasa (codecasa@elet.polimi.it)\n  /// April 27th, 2005 \n  */\n  class Torus : public OneSurfacePrimitive\n  { \n    /// center of the torus\n    Point<3> c;\n    /// vector normal to the symmetry plane of the torus\n    Vec<3> n;\n    /// Large radius of the torus\n    double R;\n    /// Small radius of the torus\n    double r;\n  \n  public:\n    /// OK\n    Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar);\n    // default constructor for archive\n    Torus() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      OneSurfacePrimitive::DoArchive(ar);\n      ar & c & n & R & r;\n    }\n    /// OK\n    const Point<3> & Center () const { return c; }\n    /// OK\n    const Vec<3> & NormalToPlane () const { return n; }\n    /// OK\n    double LargeRadius () const { return R; }\n    /// OK\n    double SmallRadius () const { return r; }\n    /// OK\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    /// OK\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    /// OK\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n    /// OK\n    virtual double HesseNorm () const;\n    /// OK\n    virtual Point<3> GetSurfacePoint () const;\n    /// OK\n    virtual void GetPrimitiveData (const char *& classname, \n\t\t\t\t   NgArray<double> & coeffs) const;\n    /// OK\t\t\t \n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n    /// OK\n    static Primitive * CreateDefault ();\n    /// OK\n    virtual Primitive * Copy () const;\n    /// OK\n    virtual void Transform (Transformation<3> & trans);\n    /// OK\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;\n    /// OK\n    /// virtual void DefineTangentialPlane (const Point<3> & ap1, \n    //\t\t\t\t      const Point<3> & ap2);\n    /// OK\n    /// virtual void ToPlane (const Point<3> & p3d, \n    ///\t\t\tPoint<2> & pplane, \n    ///\t\t\tdouble h, int & zone) const;\n    /// OK\n    /// virtual void FromPlane (const Point<2> & pplane, \n    //\t\t\t  Point<3> & p, double h) const;\n    /// OK\n    /// virtual void Project (Point<3> & p) const;\n    /// OK\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    /// OK\n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & bbox, \n\t\t\t\t\t   double facets) const;\n    /// OK\t\t \n    virtual void Print (ostream & ist) const;\n    /// OK\n    virtual void Read (istream & ist);\n  };\n\n  /// ...end\n\n\n}\n\n\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/brick.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\nnamespace netgen\n{\n\nParallelogram3d :: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3)\n{\n  p1 = ap1;\n  p2 = ap2;\n  p3 = ap3;\n\n  CalcData();\n}\n\nParallelogram3d ::~Parallelogram3d ()\n{\n  ;\n}\n\nvoid Parallelogram3d :: SetPoints (Point<3> ap1, \n\t\t\t\t   Point<3> ap2, \n\t\t\t\t   Point<3> ap3)\n{\n  p1 = ap1;\n  p2 = ap2;\n  p3 = ap3;\n\n  CalcData();\n}\n\nvoid Parallelogram3d :: CalcData()\n{\n  v12 = p2 - p1;\n  v13 = p3 - p1;\n  p4 = p2 + v13;\n\n  n = Cross (v12, v13);\n  n.Normalize();\n}\n\nint Parallelogram3d :: \nIsIdentic (const Surface & s2, int & inv, double eps) const\n{\n  int id = \n    (fabs (s2.CalcFunctionValue (p1)) <= eps) &&\n    (fabs (s2.CalcFunctionValue (p2)) <= eps) &&\n    (fabs (s2.CalcFunctionValue (p3)) <= eps);\n\n  if (id)\n    {\n      Vec<3> n2;\n      n2 = s2.GetNormalVector(p1);\n      inv = (n * n2) < 0;\n    }\n  return id;\n}\n\n\ndouble Parallelogram3d :: CalcFunctionValue (const Point<3> & point) const\n{\n  return n * (point - p1);\n}\n\nvoid Parallelogram3d :: CalcGradient (const Point<3> & /* point */, \n\t\t\t\t      Vec<3> & grad) const\n{\n  grad = n;\n}\n\nvoid Parallelogram3d :: CalcHesse (const Point<3> & /* point */, Mat<3> & hesse) const\n{\n  hesse = 0;\n}\n\ndouble Parallelogram3d :: HesseNorm () const\n{\n  return 0;\n}\n\nPoint<3> Parallelogram3d :: GetSurfacePoint () const\n{\n  return p1;\n}\n\nvoid Parallelogram3d :: Print (ostream & str) const\n{\n  str << \"Parallelogram3d \" << p1 << \" - \" << p2 << \" - \" << p3 << endl;\n}\n\n  \nvoid Parallelogram3d :: \nGetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t  const Box<3> & /* bbox */, \n\t\t\t  double /* facets */) const\n{\n  tas.AddPoint (p1);\n  tas.AddPoint (p2);\n  tas.AddPoint (p3);\n  tas.AddPoint (p4);\n  tas.AddTriangle (TATriangle (0, 0, 1, 2));\n  tas.AddTriangle (TATriangle (0, 2, 1, 3));\n}\n\n\n\n\n\n\n\n\n\n\nBrick :: Brick (Point<3> ap1, Point<3> ap2, \n\t\tPoint<3> ap3, Point<3> ap4)\n{\n  faces.SetSize (6);\n  surfaceids.SetSize (6);\n  surfaceactive.SetSize(6);\n\n  p1 = ap1; p2 = ap2;\n  p3 = ap3; p4 = ap4;\n\n  for (int i = 0; i < 6; i++)\n    {\n      faces[i] = new Plane (Point<3>(0,0,0), Vec<3> (0,0,1));\n      surfaceactive[i] = 1;\n    }\n\n  CalcData();\n}\n\nBrick :: ~Brick ()\n{\n  for (int i = 0; i < 6; i++)\n    delete faces[i];\n}\n\nPrimitive * Brick :: CreateDefault ()\n{\n  return new Brick (Point<3> (0,0,0),\n\t\t    Point<3> (1,0,0),\n\t\t    Point<3> (0,1,0),\n\t\t    Point<3> (0,0,1));\n}\n\n\n\nPrimitive * Brick :: Copy () const\n{\n  return new Brick (p1, p2, p3, p4);\n}\n\nvoid  Brick :: Transform (Transformation<3> & trans)\n{\n  trans.Transform (p1);\n  trans.Transform (p2);\n  trans.Transform (p3);\n  trans.Transform (p4);\n\n  CalcData();\n}\n\n\n\n\n\n\n\n\n\nINSOLID_TYPE Brick :: BoxInSolid (const BoxSphere<3> & box) const\n{\n  /*\n  int i;\n  double maxval;\n  for (i = 1; i <= 6; i++)\n    {\n      double val = faces.Get(i)->CalcFunctionValue (box.Center());\n      if (i == 1 || val > maxval)\n\tmaxval = val;\n    }\n  \n  if (maxval > box.Diam()) return IS_OUTSIDE;\n  if (maxval < -box.Diam()) return IS_INSIDE;\n  return DOES_INTERSECT;\n  */\n\n  bool inside = 1;\n  bool outside = 0;\n\n  Point<3> p[8];\n  for (int j = 0; j < 8; j++)\n    p[j] = box.GetPointNr(j);\n\n  for (int i = 0; i < 6; i++)\n    {\n      bool outsidei = 1;\n      for (int j = 0; j < 8; j++)\n\t{\n\t  // Point<3> p = box.GetPointNr (j);\n\t  double val = faces[i]->Plane::CalcFunctionValue (p[j]);\n\n\t  if (val > 0)  inside = 0;\n\t  if (val < 0)  outsidei = 0;\n\t}\n      if (outsidei) outside = 1;\n    }\n\n  if (outside) return IS_OUTSIDE;\n  if (inside) return IS_INSIDE;\n  return DOES_INTERSECT;\n}\n\nINSOLID_TYPE Brick :: PointInSolid (const Point<3> & p,\n\t\t\t   double eps) const\n{\n  double maxval = faces[0] -> Plane::CalcFunctionValue (p);\n  for (int i = 1; i < 6; i++)\n    {\n      double val = faces[i] -> Plane::CalcFunctionValue (p);\n      if (val > maxval) maxval = val;\n    }\n\n  if (maxval > eps) return IS_OUTSIDE;\n  if (maxval < -eps) return IS_INSIDE;\n  return DOES_INTERSECT;\n}\n\n\nINSOLID_TYPE Brick :: VecInSolid (const Point<3> & p,\n\t\t\t\t  const Vec<3> & v,\n\t\t\t\t  double eps) const\n{\n  INSOLID_TYPE result = IS_INSIDE;\n  for (int i = 0; i < faces.Size(); i++)\n    {\n      INSOLID_TYPE hres = faces[i]->VecInSolid(p, v, eps);\n      if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE;\n      else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT;\n      else result = IS_INSIDE;\n    }\n  return result;\n\n  /*\n  INSOLID_TYPE is = IS_INSIDE;\n  Vec<3> grad;\n  double scal;\n\n  for (int i = 0; i < faces.Size(); i++)\n    {\n      if (faces[i] -> PointOnSurface (p, eps))\n\t{\n\t  GetSurface(i).CalcGradient (p, grad);\n\t  scal = v * grad;\n\t  \n\t  if (scal >= eps) \n\t    is = IS_OUTSIDE;\n\t  if (scal >= -eps && is == IS_INSIDE)\n\t    is = DOES_INTERSECT;\n\t}\n    }\n  return is;\n  */\n\n  /*\n  Point<3> p2 = p + 1e-2 * v;\n  return PointInSolid (p2, eps);\n  */\n}\n\n\n\n\n\nINSOLID_TYPE Brick :: VecInSolid2 (const Point<3> & p,\n\t\t\t\t    const Vec<3> & v1,\n\t\t\t\t    const Vec<3> & v2,\n\t\t\t\t    double eps) const\n{\n  INSOLID_TYPE result = IS_INSIDE;\n  for (int i = 0; i < faces.Size(); i++)\n    {\n      INSOLID_TYPE hres = faces[i]->VecInSolid2(p, v1, v2, eps);\n      if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE;\n      else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT;\n      else result = IS_INSIDE;\n    }\n  return result;\n}\n\nINSOLID_TYPE Brick :: VecInSolid3 (const Point<3> & p,\n\t\t\t\t    const Vec<3> & v1,\n\t\t\t\t    const Vec<3> & v2,\n\t\t\t\t    double eps) const\n{\n  INSOLID_TYPE result = IS_INSIDE;\n  for (int i = 0; i < faces.Size(); i++)\n    {\n      INSOLID_TYPE hres = faces[i]->VecInSolid3(p, v1, v2, eps);\n      if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE;\n      else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT;\n      else result = IS_INSIDE;\n    }\n  return result;\n}\n\nINSOLID_TYPE Brick :: VecInSolid4 (const Point<3> & p,\n\t\t\t\t    const Vec<3> & v,\n\t\t\t\t    const Vec<3> & v2,\n\t\t\t\t    const Vec<3> & m,\n\t\t\t\t    double eps) const\n{\n  INSOLID_TYPE result = IS_INSIDE;\n  for (int i = 0; i < faces.Size(); i++)\n    {\n      INSOLID_TYPE hres = faces[i]->VecInSolid4(p, v, v2, m, eps);\n      if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE;\n      else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT;\n      else result = IS_INSIDE;\n    }\n  return result;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid Brick :: \nGetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const\n{\n  classname = \"brick\";\n  coeffs.SetSize(12);\n  coeffs.Elem(1) = p1(0);\n  coeffs.Elem(2) = p1(1);\n  coeffs.Elem(3) = p1(2);\n\n  coeffs.Elem(4) = p2(0);\n  coeffs.Elem(5) = p2(1);\n  coeffs.Elem(6) = p2(2);\n\n  coeffs.Elem(7) = p3(0);\n  coeffs.Elem(8) = p3(1);\n  coeffs.Elem(9) = p3(2);\n\n  coeffs.Elem(10) = p4(0);\n  coeffs.Elem(11) = p4(1);\n  coeffs.Elem(12) = p4(2);\n}\n\nvoid Brick :: SetPrimitiveData (NgArray<double> & coeffs)\n{\n  p1(0) = coeffs.Elem(1);\n  p1(1) = coeffs.Elem(2);\n  p1(2) = coeffs.Elem(3);\n\n  p2(0) = coeffs.Elem(4);\n  p2(1) = coeffs.Elem(5);\n  p2(2) = coeffs.Elem(6);\n\n  p3(0) = coeffs.Elem(7);\n  p3(1) = coeffs.Elem(8);\n  p3(2) = coeffs.Elem(9);\n\n  p4(0) = coeffs.Elem(10);\n  p4(1) = coeffs.Elem(11);\n  p4(2) = coeffs.Elem(12);\n\n  CalcData();\n}\n\n\n\nvoid Brick :: CalcData()\n{\n  v12 = p2 - p1;\n  v13 = p3 - p1;\n  v14 = p4 - p1;\n\n  Point<3> pi[8];\n  int i1, i2, i3;\n  int i, j;\n  \n  i = 0;\n  for (i3 = 0; i3 <= 1; i3++)\n    for (i2 = 0; i2 <= 1; i2++)\n      for (i1 = 0; i1 <= 1; i1++)\n\t{\n\t  pi[i] = p1 + i1 * v12 + i2 * v13 + i3 * v14;\n\t  i++;\n\t}\n\n  static int lface[6][4] =\n  { { 1, 3, 2, 4 },\n    { 5, 6, 7, 8 },\n    { 1, 2, 5, 6 },\n    { 3, 7, 4, 8 },\n    { 1, 5, 3, 7 },\n    { 2, 4, 6, 8 } };\n  \n  NgArray<double> data(6);\n  for (i = 0; i < 6; i++)\n    {\n      const Point<3> lp1 = pi[lface[i][0]-1];\n      const Point<3> lp2 = pi[lface[i][1]-1];\n      const Point<3> lp3 = pi[lface[i][2]-1];\n\n      Vec<3> n = Cross ((lp2-lp1), (lp3-lp1));\n      n.Normalize();\n      \n      for (j = 0; j < 3; j++)\n\t{\n\t  data[j] = lp1(j);\n\t  data[j+3] = n(j);\n\t}\n      faces[i] -> SetPrimitiveData (data);\n      /* \n\t {\n\t faces.Elem(i+1) -> SetPoints\n\t (pi[lface[i][0]-1],\n\t pi[lface[i][1]-1],\n\t pi[lface[i][2]-1]);\n\t }\n      */\n    }\n}\n\n\nvoid Brick :: Reduce (const BoxSphere<3> & box)\n{\n  double val;\n  // Point<3> p;\n  Point<3> p[8];\n  for(int j=0;j<8;j++)\n    p[j]=box.GetPointNr(j);\n\n  for (int i = 0; i < 6; i++)\n    {\n      bool hasout = 0;\n      bool hasin = 0;\n      for (int j = 0; j < 8; j++)\n\t{\n\t  // p = box.GetPointNr (j);\n\t  val = faces[i]->Plane::CalcFunctionValue (p[j]);\n\t  if (val > 0)  hasout = 1;\n\t  else if (val < 0)  hasin = 1;\n\t  if (hasout && hasin) break;\n\t}\n      surfaceactive[i] =  hasout && hasin;\n    }\n}\n\nvoid Brick :: UnReduce ()\n{ \n  for (int i = 0; i < 6; i++)\n    surfaceactive[i] = 1;\n}\n\n\n\nOrthoBrick :: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2)\n  : Brick (ap1, \n\t   Point<3> (ap2(0), ap1(1), ap1(2)),\n\t   Point<3> (ap1(0), ap2(1), ap1(2)),\n\t   Point<3> (ap1(0), ap1(1), ap2(2)))\n{\n  pmin = ap1;\n  pmax = ap2;\n}\n\t \nINSOLID_TYPE OrthoBrick :: BoxInSolid (const BoxSphere<3> & box) const\n{\n  if (pmin(0) > box.PMax()(0) ||\n      pmin(1) > box.PMax()(1) ||\n      pmin(2) > box.PMax()(2) ||\n      pmax(0) < box.PMin()(0) ||\n      pmax(1) < box.PMin()(1) ||\n      pmax(2) < box.PMin()(2))\n    return IS_OUTSIDE;\n\n  if (pmin(0) < box.PMin()(0) &&\n      pmin(1) < box.PMin()(1) &&\n      pmin(2) < box.PMin()(2) &&\n      pmax(0) > box.PMax()(0) &&\n      pmax(1) > box.PMax()(1) &&\n      pmax(2) > box.PMax()(2))\n    return IS_INSIDE;\n\n  return DOES_INTERSECT;\n}\n\n\nvoid OrthoBrick :: Reduce (const BoxSphere<3> & box)\n{\n  surfaceactive.Elem(1) =\n    (box.PMin()(2) < pmin(2)) && (pmin(2) < box.PMax()(2));\n  surfaceactive.Elem(2) =\n    (box.PMin()(2) < pmax(2)) && (pmax(2) < box.PMax()(2));\n\n  surfaceactive.Elem(3) =\n    (box.PMin()(1) < pmin(1)) && (pmin(1) < box.PMax()(1));\n  surfaceactive.Elem(4) =\n    (box.PMin()(1) < pmax(1)) && (pmax(1) < box.PMax()(1));\n\n  surfaceactive.Elem(5) =\n    (box.PMin()(0) < pmin(0)) && (pmin(0) < box.PMax()(0));\n  surfaceactive.Elem(6) =\n    (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0));\n}\n\nRegisterClassForArchive<Parallelogram3d, Surface> regpar;\nRegisterClassForArchive<Brick, Primitive> regbrick;\nRegisterClassForArchive<OrthoBrick, Brick> regob;\n}\n"
  },
  {
    "path": "libsrc/csg/brick.hpp",
    "content": "#ifndef FILE_BRICK\n#define FILE_BRICK\n\n\n/**************************************************************************/\n/* File:   brick.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   11. Mar. 98                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n  /*\n\n  brick geometry, has several surfaces\n  \n  */\n\n\n\n  class Parallelogram3d : public Surface\n  {\n    Point<3> p1, p2, p3, p4;\n    Vec<3> v12, v13;\n    Vec<3> n;\n\n  public:\n    Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3);\n    // default constructor for archive\n    Parallelogram3d() {}\n    virtual ~Parallelogram3d ();\n\n    virtual void DoArchive(Archive& ar)\n    {\n      Surface::DoArchive(ar);\n      ar & p1 & p2 & p3 & p4 & v12 & v13 & n;\n    }\n\n    void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3);\n\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; \n\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n    virtual double HesseNorm () const;\n\n    virtual Point<3> GetSurfacePoint () const;\n    virtual void Print (ostream & str) const;\n  \n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & boundingbox, \n\t\t\t\t\t   double facets) const;\n\n  protected:\n    void CalcData();\n  };\n\n\n  class Brick : public Primitive\n  {\n    Point<3> p1, p2, p3, p4;\n    Vec<3> v12, v13, v14;\n    // NgArray<OneSurfacePrimitive*> faces;\n    NgArray<Plane*> faces;\n\n  public:\n    Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4);\n    // default constructor for archive\n    Brick() {}\n    virtual ~Brick ();\n\n    virtual void DoArchive(Archive& ar)\n    {\n      Primitive::DoArchive(ar);\n      ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces;\n    }\n    static Primitive * CreateDefault ();\n\n    virtual Primitive * Copy () const;\n    virtual void Transform (Transformation<3> & trans);\n\n\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n\n    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t\t       double eps) const;\n    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const;\n    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      const Vec<3> & m,\n\t\t\t\t      double eps) const;\n\n\n    virtual int GetNSurfaces() const \n    { return 6; }\n    virtual Surface & GetSurface (int i) \n    { return *faces[i]; }\n    virtual const Surface & GetSurface (int i) const\n    { return *faces[i]; }\n\n\n    virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n\n    virtual void Reduce (const BoxSphere<3> & box);\n    virtual void UnReduce ();\n\n  protected:\n    void CalcData();\n  };\n\n\n  class OrthoBrick : public Brick \n  {\n  protected:\n    Point<3> pmin, pmax;\n  public:\n    OrthoBrick (const Point<3> & ap1, const Point<3> & ap2);\n    // default constructor for archive\n    OrthoBrick() {}\n\n    virtual void DoArchive(Archive& ar)\n    {\n      Brick::DoArchive(ar);\n      ar & pmin & pmax;\n    }\n\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    virtual void Reduce (const BoxSphere<3> & box);\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/bspline2d.cpp",
    "content": "#include <mystdlib.h>\n\n#include <csg.hpp>\n\nnamespace netgen\n{\n\nBSplineCurve2d :: BSplineCurve2d ()\n{\n  redlevel = 0;\n}\n\n\nvoid BSplineCurve2d :: AddPoint (const Point<2> & apoint)\n{\n  points.Append (apoint);\n  intervallused.Append (0);\n}\n\nbool BSplineCurve2d :: Inside (const Point<2> & p, double & dist) const\n{\n  Point<2> hp = p;\n  double t = ProjectParam (p);\n  hp = Eval(t);\n  Vec<2> v = EvalPrime (t);\n\n  Vec<2> n (v(0), -v(1));\n  \n  cout << \"p = \" << p << \", hp = \" << hp << endl;\n  dist = Dist (p, hp);\n  double scal = (hp-p) * n;\n  cout << \"scal = \" << scal << endl;\n\n  return scal >= 0;\n}\n  \ndouble BSplineCurve2d :: ProjectParam (const Point<2> & p) const\n{\n  double t, dt, mindist, mint = 0.0;\n  int n1;\n  \n  mindist = 1e10;\n  dt = 0.2;\n  for (n1 = 1; n1 <= points.Size(); n1++)\n    if (intervallused.Get(n1) == 0)\n      for (t = n1; t <= n1+1; t += dt)\n        if (Dist (Eval(t), p) < mindist)\n          {\n\t    mint = t;\n\t    mindist = Dist (Eval(t), p);\n          }\n    \n  if (mindist > 1e9) \n    {\n      for (t = 0; t <= points.Size(); t += dt)\n\tif (Dist (Eval(t), p) < mindist)\n\t  {\n\t    mint = t;\n\t    mindist = Dist (Eval(t), p);\n\t  }   \n    }\n\n  while (Dist (Eval (mint-dt), p) < mindist)\n    {\n      mindist = Dist (Eval (mint-dt), p);\n      mint -= dt;\n    }\n  while (Dist (Eval (mint+dt), p) < mindist)\n    {\n      mindist = Dist (Eval (mint+dt), p);\n      mint += dt;\n    }\n\n\n  return NumericalProjectParam (p, mint-dt, mint+dt);  \n}\n  \n  \n// t \\in (n1, n2)  \n  \nPoint<2> BSplineCurve2d :: Eval (double t) const\n{\n  int n, n1, n2, n3, n4;\n  double loct, b1, b2, b3, b4;\n  Point<2> hp;\n\n  static int cnt = 0;\n  cnt++;\n  if (cnt % 100000 == 0) (*mycout) << \"cnt = \" << cnt << endl;\n  \n  n = int(t);   \n  loct = t - n;\n  \n  b1 = 0.25 * (1 - loct) * (1 - loct);\n  b4 = 0.25 * loct * loct;\n  b2 = 0.5 - b4;\n  b3 = 0.5 - b1;\n  \n  n1 = (n + 10 * points.Size() -1) % points.Size() + 1;\n  n2 = n1+1;\n  if (n2 > points.Size()) n2 = 1;\n  n3 = n2+1;\n  if (n3 > points.Size()) n3 = 1;\n  n4 = n3+1;\n  if (n4 > points.Size()) n4 = 1;\n\n  //  (*mycout) << \"t = \" << t << \" n = \" << n << \" loct = \" << loct \n  //      << \" n1 = \" << n1 << endl;\n\n  \n  hp(0) = b1 * points.Get(n1)(0) + b2 * points.Get(n2)(0) +\n    b3 * points.Get(n3)(0) + b4 * points.Get(n4)(0);\n  hp(1) = b1 * points.Get(n1)(1) + b2 * points.Get(n2)(1) +\n    b3 * points.Get(n3)(1) + b4 * points.Get(n4)(1);\n  return hp;\n}\n  \nVec<2> BSplineCurve2d :: EvalPrime (double t) const\n{\n  int n, n1, n2, n3, n4;\n  double loct, db1, db2, db3, db4;\n  Vec<2> hv;\n  \n  n = int(t);   \n  loct = t - n;\n  \n  db1 = 0.5 * (loct - 1);\n  db4 = 0.5 * loct;\n  db2 = -db4;\n  db3 = -db1;\n  \n  n1 = (n + 10 * points.Size() -1) % points.Size() + 1;\n  n2 = n1+1;\n  if (n2 > points.Size()) n2 = 1;\n  n3 = n2+1;\n  if (n3 > points.Size()) n3 = 1;\n  n4 = n3+1;\n  if (n4 > points.Size()) n4 = 1;\n  \n  hv(0) = db1 * points.Get(n1)(0) + db2 * points.Get(n2)(0) +\n    db3 * points.Get(n3)(0) + db4 * points.Get(n4)(0);\n  hv(1) = db1 * points.Get(n1)(1) + db2 * points.Get(n2)(1) +\n    db3 * points.Get(n3)(1) + db4 * points.Get(n4)(1);\n  return hv;\n}\n\nVec<2> BSplineCurve2d :: EvalPrimePrime (double t) const\n{\n  int n, n1, n2, n3, n4;\n  double ddb1, ddb2, ddb3, ddb4;\n  Vec<2> hv;\n  \n  n = int(t);   \n  //  double loct = t - n;\n  \n  ddb1 = 0.5;\n  ddb4 = 0.5;\n  ddb2 = -0.5;\n  ddb3 = -0.5;\n  \n  n1 = (n + 10 * points.Size() -1) % points.Size() + 1;\n  n2 = n1+1;\n  if (n2 > points.Size()) n2 = 1;\n  n3 = n2+1;\n  if (n3 > points.Size()) n3 = 1;\n  n4 = n3+1;\n  if (n4 > points.Size()) n4 = 1;\n  \n  hv(0) = ddb1 * points.Get(n1)(0) + ddb2 * points.Get(n2)(0) +\n    ddb3 * points.Get(n3)(0) + ddb4 * points.Get(n4)(0);\n  hv(1) = ddb1 * points.Get(n1)(1) + ddb2 * points.Get(n2)(1) +\n    ddb3 * points.Get(n3)(1) + ddb4 * points.Get(n4)(1);\n  return hv;\n}\n  \n\nint BSplineCurve2d :: SectionUsed (double t) const\n{\n  int n1 = int(t);   \n  n1 = (n1 + 10 * points.Size() - 1) % points.Size() + 1;\n  return (intervallused.Get(n1) == 0);\n}\n\nvoid BSplineCurve2d :: Reduce (const Point<2> & p, double rad)\n{\n  int n1, n;\n  int j; \n  double minx, miny, maxx, maxy;\n  \n  //  (*testout) << \"Reduce: \" << p << \",\" << rad << endl;\n  \n  redlevel++;\n  \n  for (n1 = 1; n1 <= points.Size(); n1++)\n    {\n      if (intervallused.Get(n1) != 0) continue;\n    \n      minx = maxx = points.Get(n1)(0);\n      miny = maxy = points.Get(n1)(1);\n    \n      n = n1;\n      for (j = 1; j <= 3; j++)\n\t{\n\t  n++;\n\t  if (n > points.Size()) n = 1;\n\t  if (points.Get(n)(0) < minx) minx = points.Get(n)(0);\n\t  if (points.Get(n)(1) < miny) miny = points.Get(n)(1);\n\t  if (points.Get(n)(0) > maxx) maxx = points.Get(n)(0);\n\t  if (points.Get(n)(1) > maxy) maxy = points.Get(n)(1);\n\t}\n      \n      if (minx > p(0) + rad || maxx < p(0) - rad ||\n\t  miny > p(1) + rad || maxy < p(1) - rad)\n\t{\n\t  intervallused.Elem(n1) = redlevel;\n\t  //      (*testout) << 0;\n\t}\n      else\n\t{\n\t  //      (*testout) << 1;\n\t  intervallused.Elem(n1) = 0;\n\t}\n    }\n  //  (*testout) << endl;\n}\n\nvoid BSplineCurve2d :: UnReduce () \n{\n  int i;\n  for (i = 1; i <= intervallused.Size(); i++)\n    if (intervallused.Get(i) == redlevel)\n      intervallused.Set (i, 0);\n  redlevel--;\n}\n  \nvoid BSplineCurve2d :: Print (ostream & ost) const\n{\n  ost << \"SplineCurve: \" << points.Size() << \" points.\" << endl;\n  for (int i = 1; i <= points.Size(); i++)\n    ost << \"P\" << i << \" = \" << points.Get(i) << endl;\n}\n}\n"
  },
  {
    "path": "libsrc/csg/csg.hpp",
    "content": "#ifndef FILE_CSG\n#define FILE_CSG\n\n/* *************************************************************************/\n/* File:   geoml.hpp                                                        */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   21. Jun. 98                                                     */\n/* *************************************************************************/\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n#include <meshing.hpp>\n// #include <geometry2d.hpp>\n#include \"../gprim/spline.hpp\"\n#include \"../gprim/splinegeometry.hpp\"\n\n\n\n#include \"surface.hpp\"\n#include \"solid.hpp\"\n#include \"identify.hpp\"\n#include \"singularref.hpp\"\n#include \"splinesurface.hpp\"\n#include \"csgeom.hpp\"\n#include \"csgparser.hpp\"\n\n#include \"triapprox.hpp\"\n#include \"algprim.hpp\"\n#include \"brick.hpp\"\n#include \"spline3d.hpp\"\n#include \"manifold.hpp\"\n#include \"curve2d.hpp\"\n#include \"explicitcurve2d.hpp\"\n#include \"gencyl.hpp\"\n#include \"polyhedra.hpp\"\n#include \"extrusion.hpp\"\n#include \"revolution.hpp\"\n#include \"specpoin.hpp\"\n#include \"edgeflw.hpp\"\n#include \"meshsurf.hpp\"\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/csgeom.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n#include <core/register_archive.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n\n\n  int CSGeometry :: changeval = 0;\n\n\n\n  TopLevelObject ::  \n  TopLevelObject (Solid * asolid,\n\t\t  Surface * asurface)\n  {\n    solid = asolid;\n    surface = asurface;\n\n    SetRGB (0, 0, 1);\n    SetTransparent (0);\n    SetVisible (1); \n    SetLayer (1);\n\n    if (!surface)\n      maxh = solid->GetMaxH();\n    else\n      maxh = surface->GetMaxH();\n\n    SetBCProp (-1);\n\n    bcname = \"default\";\n  }\n\n  void TopLevelObject :: GetData (ostream & ost)\n  {\n    ost << red << \" \" << green << \" \" << blue << \" \" \n\t<< transp << \" \" << visible << \" \";\n  }\n\n  void TopLevelObject :: SetData (istream & ist)\n  {\n    ist >> red >> green >> blue >> transp >> visible;\n  }\n\n\n \n  Box<3> CSGeometry::default_boundingbox (Point<3> (-1000, -1000, -1000),\n\t\t\t\t\t  Point<3> ( 1000,  1000,  1000));\n\n\n  CSGeometry :: CSGeometry ()\n    : boundingbox (default_boundingbox),\n      identicsurfaces (100), ideps(1e-9), filename(\"\")\n  {\n    ;\n  }\n\n  CSGeometry :: CSGeometry (const string & afilename)\n    : boundingbox (default_boundingbox),\n      identicsurfaces (100), ideps(1e-9), filename(afilename)\n  {\n    changeval++;\n  }\n\n  CSGeometry :: ~CSGeometry ()\n  {\n    Clean();\n  }\n\n  PointGeomInfo CSGeometry :: ProjectPoint(int surfind, Point<3> & p) const\n  {\n    Point<3> hp = p;\n    GetSurface(surfind)->Project (hp);\n    p = hp;\n    return PointGeomInfo();\n  }\n\n  bool CSGeometry :: ProjectPointGI(int surfind, Point<3> & p, PointGeomInfo & gi) const\n  {\n    GetSurface(surfind)->Project (p);\n    return true;\n  }\n\n  void CSGeometry :: ProjectPointEdge(int surfind, INDEX surfind2,\n                                      Point<3> & p, EdgePointGeomInfo* /*unused*/) const\n  {\n    Point<3> hp = p;\n    ProjectToEdge (GetSurface(surfind),\n                   GetSurface(surfind2), hp);\n    p = hp;\n  }\n\n\n  Vec<3> CSGeometry :: GetNormal(int surfind, const Point<3> & p,\n                                 const PointGeomInfo* /*unused*/) const\n  {\n    Vec<3> hn;\n    GetSurface(surfind)->CalcGradient(p, hn);\n    hn.Normalize();\n    return hn;\n  }\n\n  void CSGeometry ::\n  PointBetween(const Point<3> & p1, const Point<3> & p2, double secpoint,\n               int surfi,\n               const PointGeomInfo & gi1,\n               const PointGeomInfo & gi2,\n               Point<3> & newp, PointGeomInfo & newgi) const\n  {\n    Point<3> hnewp;\n    hnewp = p1+secpoint*(p2-p1);\n    if (surfi != -1)\n      {\n        GetSurface (surfi) -> Project (hnewp);\n        newgi.trignum = 1;\n      }\n\n    newp = hnewp;\n  }\n\n  void CSGeometry :: PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\n               int surfi1, int surfi2,\n               const EdgePointGeomInfo & ap1,\n               const EdgePointGeomInfo & ap2,\n               Point<3> & newp, EdgePointGeomInfo & newgi) const\n  {\n    Point<3> hnewp = p1+secpoint*(p2-p1);\n\n    //(*testout) << \"hnewp \" << hnewp << \" s1 \" << surfi1 << \" s2 \" << surfi2 << endl;\n    if (surfi1 != -1 && surfi2 != -1 && surfi1 != surfi2)\n      {\n        netgen::ProjectToEdge (GetSurface(surfi1),\n                               GetSurface(surfi2),\n                               hnewp);\n        // (*testout) << \"Pointbetween, newp = \" << hnewp << endl\n        // << \", err = \" << sqrt (sqr (hnewp(0))+ sqr(hnewp(1)) + sqr (hnewp(2))) - 1 << endl;\n        newgi.edgenr = 1;\n        //(*testout) << \"hnewp (a1) \" << hnewp << endl;\n      }\n    else if (surfi1 != -1)\n      {\n        GetSurface (surfi1) -> Project (hnewp);\n        //(*testout) << \"hnewp (a2) \" << hnewp << endl;\n      }\n\n    newp = hnewp;\n  };\n\n  Vec<3> CSGeometry :: GetTangent(const Point<3> & p, int surfi1, int surfi2,\n                                  const EdgePointGeomInfo & ap1) const\n  {\n    Vec<3> n1 = GetSurface (surfi1)->GetNormalVector (p);\n    Vec<3> n2 = GetSurface (surfi2)->GetNormalVector (p);\n    Vec<3> tau = Cross (n1, n2).Normalize();\n    return tau;\n  }\n\n  void CSGeometry :: Clean ()\n  {\n    NgArray< Solid* > to_delete;\n    \n    for (int i = 0; i < solids.Size(); i++)\n      if(!to_delete.Contains(solids[i]->S1()))\n\tto_delete.Append(solids[i]->S1());\n    for (int i = 0; i < solids.Size(); i++)\n      if(!to_delete.Contains(solids[i]))\n\tto_delete.Append(solids[i]);\n\n    for(int i = 0; i < to_delete.Size(); i++)\n      delete to_delete[i];    \n    \n    solids.DeleteAll ();\n\n    splinecurves2d.DeleteAll();\n    splinecurves3d.DeleteAll();\n    \n    /*\n    for (int i = 0; i < surfaces.Size(); i++)\n      delete surfaces[i];\n    surfaces.DeleteAll ();\n    */\n    for(int i = 0; i<delete_them.Size(); i++)\n      delete delete_them[i];\n    delete_them.DeleteAll();\n    surfaces.DeleteAll();\n\n    for (int i = 0; i < toplevelobjects.Size(); i++)\n      delete toplevelobjects[i];\n    toplevelobjects.DeleteAll ();\n    for (int i = 0; i < triapprox.Size(); i++)\n      delete triapprox[i];\n    triapprox.DeleteAll();\n\n    for(int i = 0; i < identifications.Size(); i++)\n      delete identifications[i];\n    identifications.DeleteAll();\n\n    for (int i = 0; i < singfaces.Size(); i++)\n      delete singfaces[i];\n    singfaces.DeleteAll();\n    for (int i = 0; i < singedges.Size(); i++)\n      delete singedges[i];\n    singedges.DeleteAll();\n    for (int i = 0; i < singpoints.Size(); i++)\n      delete singpoints[i];\n    singpoints.DeleteAll();\n\n    changeval++;\n  }\n\n\n  extern int CSGGenerateMesh (CSGeometry & geom, \n\t\t\t      shared_ptr<Mesh> & mesh, MeshingParameters & mparam);\n\n\n  int CSGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)\n  {\n    if(restricted_h.Size())\n      {\n        // copy so that we don't change mparam outside\n        MeshingParameters mp = mparam;\n        for(const auto& [pnt, maxh] : restricted_h)\n          mp.meshsize_points.Append({pnt, maxh});\n        return CSGGenerateMesh (*this, mesh, mp);\n      }\n    else\n      return CSGGenerateMesh (*this, mesh, mparam);\n  }\n  \n  class WritePrimitivesIt : public SolidIterator\n  {\n    ostream & ost;\n  public:\n    WritePrimitivesIt (ostream & aost) : ost(aost) { ; }\n    virtual ~WritePrimitivesIt () { ; }\n\n    virtual void Do (Solid * sol);\n  };\n\n  void WritePrimitivesIt :: Do (Solid * sol) \n  {\n    Primitive * prim = sol->GetPrimitive();\n    if (prim)\n      {\n\tconst char * classname;\n\tNgArray<double> coeffs;\n\n\tprim -> GetPrimitiveData (classname, coeffs);\n\n\tif (sol->Name())\n\t  ost << \"primitive \" \n\t      << sol->Name() << \" \"\n\t      << classname << \"  \" << coeffs.Size();\n\tfor (int i = 0; i < coeffs.Size(); i++)\n\t  ost << \" \" << coeffs[i];\n\tost << endl;\n      }\n  }\n\n\n  void CSGeometry :: Save (const filesystem::path & filename) const\n  {\n    ofstream ost (filename.c_str());\n    Save (ost);\n  }\n  \n  void CSGeometry :: Save (ostream & ost) const\n  {\n    ost << \"boundingbox \"\n\t<< boundingbox.PMin()(0) << \" \"\n\t<< boundingbox.PMin()(1) << \" \"\n\t<< boundingbox.PMin()(2) << \" \"\n\t<< boundingbox.PMax()(0) << \" \"\n\t<< boundingbox.PMax()(1) << \" \"\n\t<< boundingbox.PMax()(2) << endl;\n\n\n    WritePrimitivesIt wpi(ost);\n    IterateAllSolids (wpi, 1);\n\n    for (int i = 0; i < solids.Size(); i++)\n      {\n\tif (!solids[i]->GetPrimitive())\n\t  {\n\t    ost << \"solid \" << solids.GetName(i) << \" \";\n\t    solids[i] -> GetSolidData (ost);\n\t    ost << endl;\n\t  }\n      }\n\n    for (int i = 0; i < GetNTopLevelObjects(); i++)\n      {\n\tTopLevelObject * tlo = GetTopLevelObject (i);\n\tost << \"toplevel \";\n\tif (tlo -> GetSurface())\n\t  ost << \"surface \" << tlo->GetSolid()->Name() << \" \"\n\t      << tlo->GetSurface()->Name() << \" \";\n\telse\n\t  ost << \"solid \" << tlo->GetSolid()->Name() << \" \";\n\ttlo->GetData(ost);\n\tost << endl;\n      }\n\n    for (int i = 0; i < identifications.Size(); i++)\n      {\n\tost << \"identify \";\n\tidentifications[i] -> GetData (ost);\n\tost << endl;\n      }\n\n    ost << \"end\" << endl;\n  }\n\n \n  void CSGeometry :: Load (istream & ist)\n  {\n    //  CSGeometry * geo = new CSGeometry;\n  \n    char key[100], name[100], classname[100], sname[150];\n    int ncoeff, i, j;\n    NgArray<double> coeff;\n\n    while (ist.good())\n      {\n\tist >> key;\n\tif (strcmp (key, \"boundingbox\") == 0)\n\t  {\n\t    Point<3> pmin, pmax;\n\t    ist >> pmin(0) >> pmin(1) >> pmin(2);\n\t    ist >> pmax(0) >> pmax(1) >> pmax(2);\n\t    SetBoundingBox (Box<3> (pmin, pmax));\n\t  }\n\tif (strcmp (key, \"primitive\") == 0)\n\t  {\n\t    ist >> name >> classname >> ncoeff;\n\t    coeff.SetSize (ncoeff);\n\t    for (i = 0; i < ncoeff; i++)\n\t      ist >> coeff[i];\n\n\t    Primitive * nprim = Primitive::CreatePrimitive (classname);\n\t    nprim -> SetPrimitiveData (coeff);\n\t    Solid * nsol = new Solid (nprim);\n\n\t    for (j = 0; j < nprim->GetNSurfaces(); j++)\n\t      {\n\t\tsnprintf (sname, size(sname), \"%s,%d\", name, j);\n\t\tAddSurface (sname, &nprim->GetSurface(j));\n\t\tnprim -> SetSurfaceId (j, GetNSurf());\n\t      }\n\t    SetSolid (name, nsol);\n\t  }\n\telse if (strcmp (key, \"solid\") == 0)\n\t  {\n\t    ist >> name;\n\t    Solid * nsol = Solid::CreateSolid (ist, solids);\n\n\t    cout << \" I have found solid \" << name << \" = \";\n\t    nsol -> GetSolidData (cout);\n\t    cout << endl;\n\n\t    SetSolid (name, nsol);\n\t  }\n\telse if (strcmp (key, \"toplevel\") == 0)\n\t  {\n\t    char type[20], solname[50], surfname[50];\n\t    const Solid * sol = NULL;\n\t    const Surface * surf = NULL;\n\t    int nr;\n\n\t    ist >> type;\n\t    if (strcmp (type, \"solid\") == 0)\n\t      {\n\t\tist >> solname;\n\t\tsol = GetSolid (solname);\n\t      }\n\t    if (strcmp (type, \"surface\") == 0)\n\t      {\n\t\tist >> solname >> surfname;\n\t\tsol = GetSolid (solname);\n\t\tsurf = GetSurface (surfname);\n\t      }\n\t    nr = SetTopLevelObject ((Solid*)sol, (Surface*)surf);\n\t    GetTopLevelObject (nr) -> SetData (ist);\n\t  }\n\telse if (strcmp (key, \"identify\") == 0)\n\t  {\n\t    char type[10], surfname1[50], surfname2[50];\n\t    const Surface * surf1;\n\t    const Surface * surf2;\n\n\n\t    ist >> type >> surfname1 >> surfname2;\n\t    surf1 = GetSurface(surfname1);\n\t    surf2 = GetSurface(surfname2);\n\t  \n\t    AddIdentification (new PeriodicIdentification \n\t\t\t       (GetNIdentifications(),\n\t\t\t\t*this, surf1, surf2));\n\t  }\n\telse if (strcmp (key, \"end\") == 0)\n\t  break;\n      }\n\n    changeval++;\n  }\n\n\n  void CSGeometry :: DoArchive(Archive& archive)\n  {\n    archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor\n      & identpoints & boundingbox & isidenticto & ideps\n      & filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim;\n    if(archive.Input())\n      FindIdenticSurfaces(1e-8 * MaxSize());\n  }\n\n  void CSGeometry :: SaveSurfaces (ostream & out) const\n  {\n    if(singfaces.Size() > 0 || singedges.Size() > 0 || singpoints.Size() > 0)\n      {\n\tPrintMessage(3,\"Singular faces/edges/points => no csg-information in .vol file\");\n\treturn;\n      }\n\n\n    \n    NgArray<double> coeffs;\n    const char * classname;\n\n    out << \"csgsurfaces \" << GetNSurf() << \"\\n\";\n    for(int i=0; i<GetNSurf(); i++)\n      {\n\tconst OneSurfacePrimitive * sp = dynamic_cast< const OneSurfacePrimitive * > (GetSurface(i));\n\tconst ExtrusionFace * ef = dynamic_cast< const ExtrusionFace * > (GetSurface(i));\n\tconst RevolutionFace * rf = dynamic_cast< const RevolutionFace * > (GetSurface(i));\n\tconst DummySurface * dummyf = dynamic_cast< const DummySurface * > (GetSurface(i));\n        const SplineSurface * splines = dynamic_cast<const SplineSurface *> (GetSurface(i));\n\n        if (splines)\n          {\n            splines->GetBase()->GetPrimitiveData(classname,coeffs);\n            out << classname << \" \" << coeffs.Size() << \"\\n\";\n            for (int j=0; j<coeffs.Size(); j++)\n              out << coeffs[j] << \" \";\n            out << \"\\n\";\n            for (auto cut : *(splines->GetCuts()))\n              {\n                cut->GetPrimitiveData(classname,coeffs);\n                out << classname << \" \" << coeffs.Size() << \"\\n\";\n                for (int j=0; j<coeffs.Size(); j++)\n                  out << coeffs[j] << \" \";\n                out << \"\\n\";\n              }\n            return;\n          }\n\n\tif(sp)\n\t  {\n\t    sp->GetPrimitiveData(classname,coeffs);\n\t\n\t    out << classname << \" \";\n\t  }\n\telse if(ef)\n\t  {\n\t    out << \"extrusionface \";\n\t    ef->GetRawData(coeffs);\n\t  }\n\telse if(rf)\n\t  {\n\t    out << \"revolutionface \";\n\t    rf->GetRawData(coeffs);\n\t  }\n\telse if(dummyf)\n\t  {\n\t    out << \"dummy \";\n            coeffs.SetSize(0);\n\t  }\n\telse\n\t  throw NgException (\"Cannot write csg surface. Please, contact developers!\");\n      \n\t\n\tout << coeffs.Size() << \"\\n\";\n\tfor(int j=0; j<coeffs.Size(); j++)\n\t  out << coeffs[j] << \" \";\n\t    \n\tout << \"\\n\";\n      }\n  }\n\n  void CSGeometry :: LoadSurfaces (istream & in)\n  {\n    NgArray<double> coeffs;\n    string classname;\n    int nsurfaces,size;\n\n    in >> classname;\n    \n    if(classname == \"csgsurfaces\")\n      in >> nsurfaces;\n    else\n      nsurfaces = atoi(classname.c_str());\n    \n    Point<3> dummypoint(0,0,0);\n    Vec<3> dummyvec(0,0,0);\n    double dummydouble(0.1);\n\n    for(int i=0; i<nsurfaces; i++)\n      {\n\tin >> classname;\n\tin >> size;\n\n\tcoeffs.SetSize(size);\n\n\tfor(int j=0; j<size; j++)\n\t  in >> coeffs[j];\n\n\tif(classname == \"plane\")\n\t  {\n\t    Plane * plane = new Plane(dummypoint,dummyvec);\n\t    plane->SetPrimitiveData(coeffs);\n\n\t    AddSurface(plane);\n\t    delete_them.Append(plane);\n\t  }\n\n\telse if(classname == \"sphere\")\n\t  {\n\t    Sphere * sphere = new Sphere(dummypoint,dummydouble);\n\t    sphere->SetPrimitiveData(coeffs);\n\n\t    AddSurface(sphere);\n\t    delete_them.Append(sphere);\n\t  }\n\n\telse if(classname == \"cylinder\")\n\t  {\n\t    Cylinder * cylinder = new Cylinder(coeffs);\n\n\t    AddSurface(cylinder);\n\t    delete_them.Append(cylinder);\n\t  }\n\n\telse if(classname == \"ellipticcylinder\")\n\t  {\n\t    EllipticCylinder * cylinder = new EllipticCylinder(coeffs);\n\t    AddSurface(cylinder);\n\t    delete_them.Append(cylinder);\n\t  }\n\n\n\telse if(classname == \"torus\")\n\t  {\n\t    Torus * torus = new Torus(dummypoint,dummyvec,dummydouble, dummydouble);\n\t    torus->SetPrimitiveData(coeffs);\n\t    AddSurface(torus);\n\t    delete_them.Append(torus);\n\t  }\n\n\n\telse if(classname == \"cone\")\n\t  {\n\t    Cone * cone = new Cone(dummypoint,dummypoint,dummydouble,dummydouble);\n\t    cone->SetPrimitiveData(coeffs);\n\n\t    AddSurface(cone);\n\t    delete_them.Append(cone);\n\t  }\n\n\telse if(classname == \"ellipsoid\")\n\t  {\n\t    Ellipsoid * ellipsoid = new Ellipsoid(dummypoint,dummyvec,dummyvec,dummyvec);\n\t    ellipsoid->SetPrimitiveData(coeffs);\n\n\t    AddSurface(ellipsoid);\n\t    delete_them.Append(ellipsoid);\n\t  }\n\n       else if(classname == \"ellipticcone\")\n         {\n\t    EllipticCone * ellipticcone = new EllipticCone(dummypoint,dummyvec,dummyvec,dummydouble,dummydouble);\n\n\t    ellipticcone->SetPrimitiveData(coeffs);\n\n\t    AddSurface(ellipticcone);\n\t    delete_them.Append(ellipticcone);\n\t  }\n\telse if(classname == \"extrusionface\")\n\t  {\n\t    ExtrusionFace * ef =\n\t      new ExtrusionFace(coeffs);\n\n\t    AddSurface(ef);\n\t    delete_them.Append(ef);\n\t  }\n\n\telse if(classname == \"revolutionface\")\n\t  {\n\t    RevolutionFace * rf =\n\t      new RevolutionFace(coeffs);\n\n\t    AddSurface(rf);\n\t    delete_them.Append(rf);\n\t  }\n\n\telse if(classname == \"dummy\")\n\t  {\n\t    Surface * surf = new DummySurface();\n            \n\t    AddSurface(surf);\n\t    delete_them.Append(surf);\n\t  }\n\n      }    \n  }\n    \n\n  void CSGeometry :: SaveToMeshFile (ostream & ost) const\n  {\n    SaveSurfaces (ost);\n  }\n\n\n\n\n  void CSGeometry :: AddSurface (Surface * surf)\n  {\n    static int cntsurfs = 0;\n    cntsurfs++;\n    char name[20];\n    snprintf (name, size(name), \"nnsurf%d\", cntsurfs);\n    AddSurface (name, surf);\n  }\n \n  void CSGeometry :: AddSurface (char * name, Surface * surf)\n  { \n    (*testout) << \"Adding surface \" << name << \": \" << (*surf) << endl;\n    surfaces.Set (name, surf); \n    surf->SetName (name);\n    changeval++; \n  }\n\n  void CSGeometry :: AddSurfaces (Primitive * prim)\n  {\n    for (int i = 0; i < prim->GetNSurfaces(); i++)\n      {\n\tAddSurface (&prim->GetSurface(i));\n\tprim->SetSurfaceId (i, GetNSurf()-1);\n\tsurf2prim.Append (prim);\n      }\n  }\n\n  const Surface * CSGeometry :: GetSurface (const char * name) const\n  {\n    if (surfaces.Used(name))\n      return surfaces[name];\n    else\n      return NULL;\n  }\n\n  /*\n  const Surface * CSGeometry :: GetSurface (int i) const\n  {\n    if (i >= 0 && i < surfaces.Size()) \n      return surfaces[i];\n    else\n      throw NgException (\"CSGeometry::GetSurface out of range\");\n  }\n  */\n\n\n\n\n  void CSGeometry :: SetSolid (const char * name, Solid * sol)\n  {\n    Solid * oldsol = NULL;\n\n    if (solids.Used (name))\n      oldsol = solids[name];\n\n    solids.Set (name, sol);\n    sol->SetName (name);\n\n    if (oldsol)\n      {\n\tif (oldsol->op != Solid::ROOT ||\n\t    sol->op != Solid::ROOT)\n\t  {\n\t    cerr << \"Setsolid: old or new no root\" << endl;\n\t  }\n\toldsol -> s1 = sol -> s1;\n      }\n    changeval++;\n  }\n\n  const Solid * CSGeometry :: GetSolid (const char * name) const\n  {\n    if (solids.Used(name))\n      return solids[name];\n    else\n      return NULL;\n  }\n\n  \n\n\n\n  const Solid * CSGeometry :: GetSolid (const string & name) const\n  {\n    if (solids.Used(name))\n      return solids[name];\n    else\n      return NULL;\n  }\n\n\n\n\n  void CSGeometry :: SetSplineCurve (const char * name, shared_ptr<SplineGeometry<2>> spl)\n  {\n    splinecurves2d.Set(name,spl);\n  }\n  void CSGeometry :: SetSplineCurve (const char * name, shared_ptr<SplineGeometry<3>> spl)\n  {\n    splinecurves3d.Set(name,spl);\n  }\n\n\n  shared_ptr<SplineGeometry<2>> CSGeometry :: GetSplineCurve2d (const string & name) const\n  {\n    if (splinecurves2d.Used(name))\n      return splinecurves2d[name];\n    else\n      return NULL;\n  }\n  shared_ptr<SplineGeometry<3>> CSGeometry :: GetSplineCurve3d (const string & name) const\n  {\n    if (splinecurves3d.Used(name))\n      return splinecurves3d[name];\n    else\n      return NULL;\n  }\n\n\n\n    /*\n  class RemoveDummyIterator : public SolidIterator\n  {\n  public:\n  \n    RemoveDummyIterator() { ; }\n    virtual ~RemoveDummyIterator() { ; }\n    virtual void Do(Solid * sol);\n  };\n\n  void RemoveDummyIterator :: Do(Solid * sol)\n  {\n    cerr << \"remove dummy iterator is obsolete\" << endl;\n\n    if ( (sol->op == Solid::SUB || sol->op == Solid::SECTION || \n\t  sol->op == Solid::UNION)\n\t && sol->s1->op == Solid::DUMMY)\n      sol->s1 = sol->s1->s1;\n    if ( (sol->op == Solid::SECTION || sol->op == Solid::UNION)\n\t && sol->s2->op == Solid::DUMMY)\n      sol->s2 = sol->s2->s1;\n  }\n    */\n\n\n\n\n\n\n  int CSGeometry :: SetTopLevelObject (Solid * sol, Surface * surf)\n  {\n    toplevelobjects.Append (new TopLevelObject (sol, surf));\n    return toplevelobjects.Size()-1;\n  }\n\n  TopLevelObject * CSGeometry :: \n  GetTopLevelObject (const Solid * sol, const Surface * surf)\n  {\n    for (int i = 0; i < toplevelobjects.Size(); i++)\n      {\n\tif (toplevelobjects[i]->GetSolid() == sol &&\n\t    toplevelobjects[i]->GetSurface() == surf)\n\t  return (toplevelobjects[i]);\n      }\n    return NULL;\n  }\n\n  void CSGeometry :: RemoveTopLevelObject (Solid * sol, Surface * surf)\n  {\n    for (int i = 0; i < toplevelobjects.Size(); i++)\n      {\n\tif (toplevelobjects[i]->GetSolid() == sol &&\n\t    toplevelobjects[i]->GetSurface() == surf)\n\t  {\n\t    delete toplevelobjects[i];\n\t    toplevelobjects.DeleteElement (i+1);\n\t    changeval++;\n\t    break;\n\t  }\n      }\n  }\n\n  void CSGeometry :: AddIdentification (Identification * ident)\n  {\n    identifications.Append (ident);\n  }\n\n  void CSGeometry :: SetFlags (const char * solidname, const Flags & flags)\n  {\n    Solid * solid = solids[solidname];\n    NgArray<int> surfind;\n\n    int i;\n    double maxh = flags.GetNumFlag (\"maxh\", -1);\n    if (maxh > 0 && solid)\n      {\n\tsolid->GetSurfaceIndices (surfind);\n\n\tfor (i = 0; i < surfind.Size(); i++)\n\t  {\n\t    if (surfaces[surfind[i]]->GetMaxH() > maxh)\n\t      surfaces[surfind[i]] -> SetMaxH (maxh);\n\t  }\n\n\tsolid->SetMaxH (maxh);\n      }\n\n    if ( flags.StringFlagDefined (\"bcname\") )\n      {\n\tsolid->GetSurfaceIndices (surfind);\n\tstring bcn = flags.GetStringFlag(\"bcname\", \"default\");\n\tfor (i = 0; i < surfind.Size(); i++)\n\t  {\n\t    if(surfaces[surfind[i]]->GetBCName() == \"default\")\n\t      surfaces[surfind[i]]->SetBCName(bcn);\n\t  }\n      }\n\n    if (flags.StringListFlagDefined (\"bcname\"))\n      {\n\tauto& bcname = flags.GetStringListFlag(\"bcname\");\n\n\tPolyhedra * polyh;\n\tif(solid->S1())\n\t  polyh = dynamic_cast<Polyhedra *>(solid->S1()->GetPrimitive());\n\telse\n\t  polyh = dynamic_cast<Polyhedra *>(solid->GetPrimitive());\n\n\tif(polyh)\n\t  {\n\t    NgArray < NgArray<int> * > polysurfs;\n\t    polyh->GetPolySurfs(polysurfs);\n\t    if(bcname.Size() != polysurfs.Size())\n\t      cerr << \"WARNING: solid \\\"\" << solidname << \"\\\" has \" << polysurfs.Size()\n\t\t   << \" surfaces and should get \" << bcname.Size() << \" bc-names!\" << endl;\n\t    \n\t    for ( i = 0; i < min2(polysurfs.Size(),bcname.Size()); i++)\n\t      {\n\t\tfor (int j = 0; j < polysurfs[i]->Size(); j++)\n\t\t  {\n\t\t    if(surfaces[(*polysurfs[i])[j]]->GetBCName() == \"default\")\n\t\t      surfaces[(*polysurfs[i])[j]]->SetBCName(bcname[i]);\n\t\t  }\n\t\tdelete polysurfs[i];\n\t      }\n\t  }\n\telse\n\t  {\n\t    solid->GetSurfaceIndices (surfind);\n\t    if(bcname.Size() != surfind.Size())\n\t      cerr << \"WARNING: solid \\\"\" << solidname << \"\\\" has \" << surfind.Size()\n\t\t   << \" surfaces and should get \" << bcname.Size() << \" bc-names!\" << endl;\n\t    \n\t    for (i = 0; i < min2(surfind.Size(),bcname.Size()); i++)\n\t      {\n\t\tif(surfaces[surfind[i]]->GetBCName() == \"default\")\n\t\t  surfaces[surfind[i]]->SetBCName(bcname[i]);\n\t      }\n\t  }\n      }\n\n    if (flags.NumFlagDefined (\"bc\"))\n      {\n\tsolid->GetSurfaceIndices (surfind);\n\tint bc = int (flags.GetNumFlag(\"bc\", -1));\n\tfor (i = 0; i < surfind.Size(); i++)\n\t  {\n\t    if (surfaces[surfind[i]]->GetBCProperty() == -1)\n\t      surfaces[surfind[i]]->SetBCProperty(bc);\n\t  }\n      }\n   \n    if (flags.NumListFlagDefined (\"bc\"))\n      {\n\tconst auto& bcnum = flags.GetNumListFlag(\"bc\");\n\n\tPolyhedra * polyh;\n\tif(solid->S1())\n\t  polyh = dynamic_cast<Polyhedra *>(solid->S1()->GetPrimitive());\n\telse\n\t  polyh = dynamic_cast<Polyhedra *>(solid->GetPrimitive());\n\n\tif(polyh)\n\t  {\n\t    NgArray < NgArray<int> * > polysurfs;\n\t    polyh->GetPolySurfs(polysurfs);\n\t    if(bcnum.Size() != polysurfs.Size())\n\t      cerr << \"WARNING: solid \\\"\" << solidname << \"\\\" has \" << polysurfs.Size()\n\t\t   << \" surfaces and should get \" << bcnum.Size() << \" bc-numbers!\" << endl;\n\t    \n\t    for ( i = 0; i < min2(polysurfs.Size(),bcnum.Size()); i++)\n\t      {\n\t\tfor (int j = 0; j < polysurfs[i]->Size(); j++)\n\t\t  {\n\t\t    if ( surfaces[(*polysurfs[i])[j]]->GetBCProperty() == -1 )\n\t\t      surfaces[(*polysurfs[i])[j]]->SetBCProperty(int(bcnum[i]));\n\t\t  }\n\t\tdelete polysurfs[i];\n\t      }\n\t  }\n\telse\n\t  {\n\t    solid->GetSurfaceIndices (surfind);\n\t    if(bcnum.Size() != surfind.Size())\n\t      cerr << \"WARNING: solid \\\"\" << solidname << \"\\\" has \" << surfind.Size()\n\t\t   << \" surfaces and should get \" << bcnum.Size() << \" bc-numbers!\" << endl;\n\t    \n\t    for (i = 0; i < min2(surfind.Size(),bcnum.Size()); i++)\n\t      {\n\t\tif (surfaces[surfind[i]]->GetBCProperty() == -1)\n\t\t  surfaces[surfind[i]]->SetBCProperty(int(bcnum[i]));\n\t      }\n\t  }\n      }\n\n  }\n\n  void CSGeometry :: FindIdenticSurfaces (double eps)\n  {\n    int inv;\n    int nsurf = GetNSurf();\n    identicsurfaces.DeleteData();\n\n\n    isidenticto.SetSize(nsurf);\n    for (int i = 0; i < nsurf; i++)\n      isidenticto[i] = i;\n  \n    for (int i = 0; i < nsurf; i++)\n      for (int j = i+1; j < nsurf; j++)\n\t{\n\t  if (GetSurface(j) -> IsIdentic (*GetSurface(i), inv, eps))\n\t    {\n\t      INDEX_2 i2(i, j);\n\t      identicsurfaces.Set (i2, inv);\n\t      isidenticto[j] = isidenticto[i];\n\t    }\n\t}\n\n    (*testout) << \"identicmap:\" << endl;\n    for (int i = 0; i < isidenticto.Size(); i++)\n      (*testout) << i << \" -> \" << isidenticto[i] << endl;\n  }\n  \n\n  \n  void CSGeometry ::\n  GetSurfaceIndices (const Solid * sol, \n\t\t     const BoxSphere<3> & box, \n\t\t     NgArray<int> & locsurf) const\n  {\n    ReducePrimitiveIterator rpi(box);\n    UnReducePrimitiveIterator urpi;\n\n    const_cast<Solid*> (sol) -> IterateSolid (rpi);\n    sol -> GetSurfaceIndices (locsurf);\n    const_cast<Solid*> (sol) -> IterateSolid (urpi);\n\n    for (int i = locsurf.Size()-1; i >= 0; i--)\n      {\n\tbool indep = 1;\n\tfor (int j = 0; j < i; j++)\n\t  if (locsurf[i] == locsurf[j])\n\t    {\n\t      indep = 0;\n\t      break;\n\t    }\n\n\tif (!indep) locsurf.Delete(i);\n      }\n  }\n\n\n\n  \n  void CSGeometry ::\n  GetIndependentSurfaceIndices (const Solid * sol, \n\t\t\t\tconst BoxSphere<3> & box, \n\t\t\t\tNgArray<int> & locsurf) const\n  {\n    ReducePrimitiveIterator rpi(box);\n    UnReducePrimitiveIterator urpi;\n\n    ((Solid*)sol) -> IterateSolid (rpi);\n    sol -> GetSurfaceIndices (locsurf);\n    ((Solid*)sol) -> IterateSolid (urpi);\n\n    for (int i = 0; i < locsurf.Size(); i++)\n      locsurf[i] = isidenticto[locsurf[i]];\n\n    for (int i = locsurf.Size()-1; i >= 0; i--)\n      {\n\tbool indep = 1;\n\tfor (int j = 0; j < i; j++)\n\t  if (locsurf[i] == locsurf[j])\n\t    {\n\t      indep = 0;\n\t      break;\n\t    }\n\n\tif (!indep) locsurf.Delete(i);\n      }\n\n\n    /*\n    // delete identified\n    for (int i = locsurf.Size()-1; i >= 0; i--)\n      {\n\tbool indep = 1;\n\tfor (int j = 0; j < i; j++)\n\t  {\n\t    if (identicsurfaces.Used (INDEX_2::Sort (locsurf[i], locsurf[j])) !=\n\t\t(isidenticto[locsurf[i]] == isidenticto[locsurf[j]]))\n\t      {\n\t\tcerr << \"different result\" << endl;\n\t\texit(1);\n\t      }\n\n\t    if (isidenticto[locsurf[i]] == isidenticto[locsurf[j]])\n\t      {\n\t\tindep = 0;\n\t\tbreak;\n\t      }\n\t  }\n\tif (!indep)\n\t  locsurf.Delete(i);\n      }\n\n    for (int i = 0; i < locsurf.Size(); i++)\n      locsurf[i] = isidenticto[locsurf[i]];\n    */\n  }\n\n  /*\n  void CSGeometry ::\n  GetIndependentSurfaceIndices (const Solid * sol, \n\t\t\t\tconst Point<3> & p, Vec<3> & v,\n\t\t\t\tNgArray<int> & locsurf) const\n  {\n    cout << \"very dangerous\" << endl;\n    Point<3> p2 = p + 1e-2 * v;\n    BoxSphere<3> box (p2, p2);\n    box.Increase (1e-3);\n    box.CalcDiamCenter();\n    GetIndependentSurfaceIndices (sol, box, locsurf);\n  }\n  */\n\n  void CSGeometry ::\n  GetIndependentSurfaceIndices (NgArray<int> & locsurf) const\n  {\n    for (int i = 0; i < locsurf.Size(); i++)\n      locsurf[i] = isidenticto[locsurf[i]];\n\n    for (int i = locsurf.Size()-1; i >= 0; i--)\n      {\n\tbool indep = 1;\n\tfor (int j = 0; j < i; j++)\n\t  if (locsurf[i] == locsurf[j])\n\t    {\n\t      indep = 0;\n\t      break;\n\t    }\n\n\tif (!indep) locsurf.Delete(i);\n      }\n  }\n\n\n\n\n\n\n\n\n\n  void CSGeometry :: \n  CalcTriangleApproximation(double detail, double facets)\n  {\n    PrintMessage (1, \"Calc Triangle Approximation\");\n\n    try\n      {\n    //    FindIdenticSurfaces (1e-6);\n  \n    int ntlo = GetNTopLevelObjects();\n\n    for (int i = 0; i < triapprox.Size(); i++)\n      delete triapprox[i];\n    triapprox.SetSize (ntlo);\n\n    NgArray<int> surfind;\n    IndexSet iset(GetNSurf());\n\n    for (int i = 0; i < ntlo; i++)\n      {\n\tSolid * sol;\n\tSurface * surf;\n\tGetTopLevelObject (i, sol, surf);\n\n\tsol -> CalcSurfaceInverse ();\n\n\tTriangleApproximation * tams = new TriangleApproximation();\n\ttriapprox[i] = tams;\n\n\t// sol -> GetSurfaceIndices (surfind);\n\tfor (int j = 0; j < GetNSurf(); j++)\n\t  // for (int jj = 0; jj < surfind.Size(); jj++)\n\t  {\n\t    // int j = surfind[jj];\n\n\t    PrintMessageCR (3, \"Surface \", j, \"/\", GetNSurf());\n\t    // PrintMessageCR (3, \"Surface \", j, \"/\", surfind.Size());\n\n\t    if (surf && surf != GetSurface(j))\n\t      continue;\n\n\t    TriangleApproximation tas;\n\t    GetSurface (j) -> GetTriangleApproximation (tas, boundingbox, facets);\n\n\t    int oldnp = tams -> GetNP();\n\n\t    if (!tas.GetNP())\n\t      continue;\n\n\t    for (int k = 0; k < tas.GetNP(); k++)\n\t      {\n\t\ttams -> AddPoint (tas.GetPoint(k));\n                Vec<3> n = GetSurface(j) -> GetNormalVector (tas.GetPoint(k)); \n\t\tn.Normalize();\n\t\tif (GetSurface(j)->Inverse()) n *= -1;\n\t\ttams -> AddNormal (n);\n\t      }\n\t  \n\t    BoxSphere<3> surfbox;\n\n\t    if (tas.GetNP())\n\t      surfbox.Set (tas.GetPoint(0));\n\t    for (int k = 1; k < tas.GetNP(); k++)\n\t      surfbox.Add (tas.GetPoint(k));\n\t    surfbox.Increase (1e-6);\n\t    surfbox.CalcDiamCenter();\n\n\t    Solid * surflocsol = sol -> GetReducedSolid (surfbox);\n\t    if (!surflocsol)\n\t      continue;\n\n\t    for (int k = 0; k < tas.GetNT(); k++)\n\t      {\n\t\tconst TATriangle & tri = tas.GetTriangle (k);\n\n\t\t// check triangle\n\t\tBoxSphere<3> box;\n\t\tbox.Set (tas.GetPoint (tri[0]));\n\t\tbox.Add (tas.GetPoint (tri[1]));\n\t\tbox.Add (tas.GetPoint (tri[2]));\n\t\tbox.Increase (1e-6);\n\t\tbox.CalcDiamCenter();\n\n\n\t\tSolid * locsol = surflocsol -> GetReducedSolid (box);\n\t\t\n\t\tif (locsol)\n\t\t  {\n\t\t    TATriangle tria(j, \n\t\t\t\t    tri[0] + oldnp,\n\t\t\t\t    tri[1] + oldnp,\n\t\t\t\t    tri[2] + oldnp);\n                    \n                    // tams -> AddTriangle (tria);\n\n\t\t    RefineTriangleApprox (locsol, j, box, detail, \n\t\t\t\t\t  tria, *tams, iset, 1);\n\n\t\t    delete locsol;\n\t\t  }\n\t      }\n\t  }\n\n\ttams->RemoveUnusedPoints ();\n\tPrintMessage (2, \"Object \", i, \" has \", tams->GetNT(), \" triangles\");\n      }\n      }\n    catch (const std::exception &)\n      {\n\tcerr << \"*************************************************************\" << endl\n\t     << \"****   out of memory problem in CSG visualization        ****\" << endl\n\t     << \"****   Restart netgen, and disable                       ****\" << endl\n\t     << \"****   'Draw Geometry' in Geometry -> CSG Options        ****\" << endl\n\t     << \"****   before loading the geometry                       ****\" << endl\n\t     << \"****   meshing will still work !                         ****\" << endl\n\t     << \"*************************************************************\" << endl;\n\texit(1);\n      }\n    Change();\n  }\n\n\n\n  void CSGeometry ::\n  RefineTriangleApprox (Solid * locsol, \n\t\t\tint surfind,\n\t\t\tconst BoxSphere<3> & box, \n\t\t\tdouble detail,\n\t\t\tconst TATriangle & tria, \n\t\t\tTriangleApproximation & tams,\n\t\t\tIndexSet & iset,\n                        int level)\n  {\n    // if (level > 10) return;\n\n    //tams.AddTriangle (tria);\n    //(*testout) << \"tria \" << tams.GetPoint(tria[0]) << \" - \" << tams.GetPoint(tria[1]) << \" - \" << tams.GetPoint(tria[2]) \n    //       << \" ( \" << tria[0] << \" \" << tria[1] << \" \" << tria[2] << \")\" <<endl;\n    //return;\n\n    int pinds[6];\n    NgArrayMem<int,500> surfused(GetNSurf());\n  \n    ReducePrimitiveIterator rpi(box);\n    UnReducePrimitiveIterator urpi;\n\n    locsol -> IterateSolid (rpi);\n    //  locsol -> GetSurfaceIndices (lsurfi);\n\n\n    //    IndexSet iset(GetNSurf());\n    locsol -> GetSurfaceIndices (iset);\n    const NgArray<int> & lsurfi = iset.GetArray();\n\n    locsol -> IterateSolid (urpi);\n\n    int surfii = -1;\n    for (int i = 0; i < lsurfi.Size(); i++)\n      if (lsurfi[i] == surfind)\n\t{\n\t  surfii = i;\n\t  break;\n\t}\n\n    if (surfii == -1)\n      return;\n\n    int cntindep = 0;\n\n    for (int i = 0; i < lsurfi.Size(); i++)\n      {\n\tint linkto = isidenticto[lsurfi[i]];\n\tsurfused[linkto] = 0;\n      }\n\n    for (int i = 0; i < lsurfi.Size(); i++)\n      {\n\tint linkto = isidenticto[lsurfi[i]];\n\tif (!surfused[linkto])\n\t  {\n\t    surfused[linkto] = 1;\n\t    cntindep++;\n\t  }\n      }\n\n    int inverse = surfaces[surfind]->Inverse();\n\n    if (cntindep == 1)\n      {\n\ttams.AddTriangle (tria);\n\t//(*testout) << \"pos1 \" << tams.GetPoint(tria[0]) << \" - \" << tams.GetPoint(tria[1]) << \" - \" << tams.GetPoint(tria[2]) << endl;\n\treturn;\n      }\n\n    if (cntindep == 2)\n      {\n\t// just 2 surfaces:\n\t// if smooth, project inner points to edge and finish\n\n\tint otherind = -1;\n\n\tfor (int i = 0; i < lsurfi.Size(); i++)\n\t  {\n\t    INDEX_2 i2 (lsurfi[i], surfind);\n\t    i2.Sort();\n\t  \n\t    if (i != surfii && !identicsurfaces.Used(i2))\n\t      otherind = lsurfi[i];\n\t  }\n\n\tdouble kappa = GetSurface(otherind)-> MaxCurvature ();\n\n\tif (kappa * box.Diam() < 0.1)\n\t  {\n\t    int pnums[6];\n\t    static int between[3][3] =\n\t      { { 1, 2, 3 },\n\t\t{ 0, 2, 4 },\n\t\t{ 0, 1, 5 } };\n\t    int onsurface[3];\n\n\t    for (int j = 0; j < 3; j++)\n\t      {\n\t\tint pi = tria[j];\n\t\tpnums[j] = pi;\n\n\n\t\tonsurface[j] =  \n\t\t  !locsol->IsStrictIn (tams.GetPoint (pi), 1e-6) &&\n\t\t  locsol->IsIn (tams.GetPoint (pi), 1e-6);\n\t\t\n\t\t//\n\t\t/*\n\t\tstatic int nos=0;\n\t\tif(!onsurface[j])\n\t\t  {\n\t\t    nos++;\n\t\t    cout << \"NOT ON SURFACE!! \"<< nos << endl;\n\t\t  }\n\t\t*/\n\t      }\n\t  \n\t    for (int j = 0; j < 3; j++)\n\t      {\n\t\tint lpi1 = between[j][0];\n\t\tint lpi2 = between[j][1];\n\t\tint lpin = between[j][2];\n\t\tif (onsurface[lpi1] == onsurface[lpi2])\n\t\t  pnums[lpin] = -1;\n\t\telse\n\t\t  {\n\t\t    const Point<3> & p1 = tams.GetPoint (pnums[lpi1]);\n\t\t    const Point<3> & p2 = tams.GetPoint (pnums[lpi2]);\n\t\t    double f1 = GetSurface(otherind)->CalcFunctionValue (p1);\n\t\t    double f2 = GetSurface(otherind)->CalcFunctionValue (p2);\n\n\t\t    Point<3> pn;\n\n\t\t    double l2(100),l1(100);\n\t\t    if ( fabs (f1-f2) > 1e-20 )\n\t\t      {\n\t\t\tl2 = -f1/(f2-f1);\n\t\t\tl1 = f2/(f2-f1);\n\t\t\tpn = Point<3>(l1 * p1(0) + l2 * p2(0),\n\t\t\t\t      l1 * p1(1) + l2 * p2(1),\n\t\t\t\t      l1 * p1(2) + l2 * p2(2));\n\t\t      }\n\t\t    else\n\t\t      pn = p1;\n\n// \t\t    if(fabs(pn(0)) > 4 || fabs(pn(1)) > 4 || fabs(pn(2)) > 4)\n// \t\t      {\n// \t\t\tcout << \"p1 \" << p1 << \" p2 \" << p2 \n// \t\t\t     << \" f1 \" << f1 << \" f2 \" << f2\n// \t\t\t     << \" l1 \" << l1 << \" l2 \" << l2 \n// \t\t\t     << \" pn \" << pn << endl;\n\n// \t\t      }\n\n\t\t    \n\t\t    //GetSurface (surfind)->Project (pn);\n\t\t    \n\t\t    pnums[lpin] = tams.AddPoint (pn);\n\n\t\t    GetSurface (surfind)->Project (pn);\n\t\t    \n\t\t    Vec<3> n;\n\t\t    n = GetSurface (surfind)->GetNormalVector (pn);\n\t\t    if (inverse) n *= -1;\n\t\t    tams.AddNormal(n);\n\t\t  }\n\t      }\n\t  \n\t    int vcase = 0;\n\t    if (onsurface[0]) vcase++;\n\t    if (onsurface[1]) vcase+=2;\n\t    if (onsurface[2]) vcase+=4;\n\t  \n\t    static int trias[8][6] =\n\t      { { 0, 0, 0,   0, 0, 0 },\n\t\t{ 1, 6, 5,   0, 0, 0 },\n\t\t{ 2, 4, 6,   0, 0, 0 },\n\t\t{ 1, 2, 4,   1, 4, 5 },\n\t\t{ 3, 5, 4,   0, 0, 0 },\n\t\t{ 1, 6, 4,   1, 4, 3 },\n\t\t{ 2, 3, 6,   3, 5, 6 },\n\t\t{ 1, 2, 3,   0, 0, 0 } };\n\t    static int ntrias[4] =\n\t      { 0, 1, 2, 1 };\n\n\t    int nvis = 0;\n\t    for (int j = 0; j < 3; j++)\n\t      if (onsurface[j])\n\t\tnvis++;\n\n\t    for (int j = 0; j < ntrias[nvis]; j++)\n\t      {\n\t\tTATriangle ntria(tria.SurfaceIndex(),\n\t\t\t\t pnums[trias[vcase][3*j]-1],\n\t\t\t\t pnums[trias[vcase][3*j+1]-1],\n\t\t\t\t pnums[trias[vcase][3*j+2]-1]);\n\t\t//(*testout) << \"pos2 \" << tams.GetPoint(ntria[0]) << \" - \" << tams.GetPoint(ntria[1]) << \" - \" << tams.GetPoint(ntria[2]) << endl\n\t\t//\t   << \"( \" << ntria[0] << \" - \" << ntria[1] << \" - \" << ntria[2] << \")\" << endl;\n\t\ttams.AddTriangle (ntria);\n\t      }\n\n\t    /* saturn changes:\n\n\t    int pvis[3];\n\t    for (j = 0; j < 3; j++)\n\t    pvis[j] = !locsol->IsStrictIn (tams.GetPoint (j+1), 1e-6) &&\n\t    locsol->IsIn (tams.GetPoint (j+1), 1e-6);\n\t  \n\t    int newpi[3];\n\t    for (j = 0; j < 3; j++)\n\t    {\n\t    int pi1 = j;\n\t    int pi2 = (j+1) % 3;\n\t    int pic = j;\n\n\t    if (pvis[pi1] != pvis[pi2])\n\t    {\n\t    Point<3> hp = Center (tams.GetPoint (tria.PNum (pi1+1)),\n\t    tams.GetPoint (tria.PNum (pi2+1)));\n\n\t    newpi[j] = tams.AddPoint (hp);\n\t    Vec<3> n = tams.GetNormal (pi1);\n\t    tams.AddNormal (n);\n\t    }\n\t    else\n\t    newpi[j] = 0;\n\t    }\n\n\t    int nvis = 0;\n\t    for (j = 0; j <= nvis; j++)\n\t    if (pvis[j]) nvis++;\n\n\t    int si = tria.SurfaceIndex();\n\t    switch (nvis)\n\t    {\n\t    case 0:\n\t    break;\n\t    case 1:\n\t    {\n\t    int visj;\n\t    for (j = 0; j < 3; j++)\n\t    if (pvis[j]) visj = j;\n\t    int pivis = tria.PNum (visj+1);\n\t    int pic1 = newpi[(visj+1)%3];\n\t    int pic2 = newpi[(visj+2)%3];\n\t\t\n\t    cout << pivis << \",\" << pic1 << \",\" << pic2 << endl;\n\t\t\n\t    tams.AddTriangle (TATriangle (si, pivis, pic1,pic2));\n\t    break;\n\t    }\n\t    case 2:\n\t    {\n\t    int nvisj;\n\t    for (j = 0; j < 3; j++)\n\t    if (!pvis[j]) nvisj = j;\n\n\t    int pivis1 = tria.PNum ((nvisj+1)%3+1);\n\t    int pivis2 = tria.PNum ((nvisj+2)%3+1);\n\t    int pic1 = newpi[nvisj];\n\t    int pic2 = newpi[(nvisj+2)%3];\n\n\t    tams.AddTriangle (TATriangle (si, pivis1, pic1,pic2));\n\t    tams.AddTriangle (TATriangle (si, pivis1, pic1,pivis2));\n\t    break;\n\t    }\n\t    case 3:\n\t    {\n\t    tams.AddTriangle (tria);\n\t    break;\n\t    }\n\t    }\n\n\t    */\n\t    return;\n\t  }\n      }\n\n    // bisection\n    if (box.Diam() < detail)\n      {\n\t//cout << \"returning\" << endl;\n\treturn;\n      }\n\n    for (int i = 0; i < 3; i++)\n      pinds[i] = tria[i];\n  \n    static int between[3][3] =\n      { { 0, 1, 5 },\n\t{ 0, 2, 4 },\n\t{ 1, 2, 3 } };\n  \n    for (int i = 0; i < 3; i++)\n      {\n\t// int pi1 = tria[between[i][0]];\n\n\tPoint<3> newp = Center (tams.GetPoint (tria[between[i][0]]),\n\t\t\t\ttams.GetPoint (tria[between[i][1]]));\n\tVec<3> n;\n\t\n\tGetSurface(surfind)->Project (newp);\n\n\tn = GetSurface(surfind)->GetNormalVector (newp);\n      \n\tpinds[between[i][2]] = tams.AddPoint (newp);\n\tif (inverse) n *= -1;\n\ttams.AddNormal (n);\n      }\n  \n    static int trias[4][4] =\n      { { 0, 5, 4 },\n\t{ 5, 1, 3 },\n\t{ 4, 3, 2 },\n\t{ 3, 4, 5 } };\n \n    for (int i = 0; i < 4; i++)\n      {\n\tTATriangle ntri(surfind,\n\t\t\tpinds[trias[i][0]],\n\t\t\tpinds[trias[i][1]],\n\t\t\tpinds[trias[i][2]]);\n\n\t// check triangle\n\tBoxSphere<3> nbox;\n\tnbox.Set (tams.GetPoint (ntri[0]));\n\tnbox.Add (tams.GetPoint (ntri[1]));\n\tnbox.Add (tams.GetPoint (ntri[2]));\n\tnbox.Increase (1e-8);\n\tnbox.CalcDiamCenter();\n\n\tSolid * nsol = locsol -> GetReducedSolid (nbox);\n\n\tif (nsol)\n\t  {\n\t    RefineTriangleApprox (nsol, surfind, nbox, \n\t\t\t\t  detail, ntri, tams, iset, level+1);\n\t  \n\t    delete nsol;\n\t  }\n      }\n  }\n\n\n\n\n  class ClearVisitedIt : public SolidIterator\n  {\n  public:\n    ClearVisitedIt () { ; }\n    virtual ~ClearVisitedIt () { ; }\n\n    virtual void Do (Solid * sol)\n    { \n      sol -> visited = 0;\n    }\n  };\n\n\n  void CSGeometry :: \n  IterateAllSolids (SolidIterator & it, bool only_once) const\n  {\n    if (only_once)\n      {\n\tClearVisitedIt clit;\n\tfor (int i = 0; i < solids.Size(); i++)\n\t  solids[i] -> IterateSolid (clit, 0);\n      }\n\n    for (int i = 0; i < solids.Size(); i++)\n      solids[i] -> IterateSolid (it, only_once);\n  }\n\n\n  double CSGeometry ::  MaxSize () const\n  {\n    double maxs, mins;\n    maxs = max3 (boundingbox.PMax()(0), \n\t\t boundingbox.PMax()(1), \n\t\t boundingbox.PMax()(2));\n    mins = min3 (boundingbox.PMin()(0), \n\t\t boundingbox.PMin()(1), \n\t\t boundingbox.PMin()(2));\n    return max2 (maxs, -mins) * 1.1;\n  }\n\n\n\n  class CSGeometryRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const;\n    virtual NetgenGeometry * LoadFromMeshFile (istream & ist, string token) const;\n    // virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;\n  };\n\n  extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr);\n\n  NetgenGeometry *  CSGeometryRegister :: Load (const filesystem::path & filename) const\n  {\n    string extension = filename.extension().string();\n    if (extension == \".geo\")\n      {\n\tPrintMessage (1, \"Load CSG geometry file \", filename);\n\n\tifstream infile(filename);\n\n\tCSGeometry * hgeom = ParseCSG (infile);\n\tif (!hgeom)\n\t  throw NgException (\"geo-file should start with 'algebraic3d'\");\n\n\thgeom -> FindIdenticSurfaces(1e-8 * hgeom->MaxSize()); \n\treturn hgeom;\n      }\n\n    if (extension == \".ngg\")\n      {\n\tPrintMessage (1, \"Load new CSG geometry file \", filename);\n\n\tifstream infile(filename);\n\tCSGeometry * hgeom = new CSGeometry(\"\");\n\thgeom -> Load (infile);\n\n\treturn hgeom;\n      }\n    \n    return NULL;\n  }\n\n  NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist, string token) const\n  {\n\tif (token != \"csgsurfaces\")\n        return nullptr;\n\n    CSGeometry * geometry = new CSGeometry (\"\");\n\tgeometry -> LoadSurfaces(ist);\n\treturn geometry;\n  }\n\n\n  class CSGInit\n  {\n  public:\n    CSGInit()\n    {\n      GeometryRegister().Append (new CSGeometryRegister);\n    }\n  };\n\n  CSGInit csginit;\n  static RegisterClassForArchive<CSGeometry, NetgenGeometry> regcsg;\n}\n"
  },
  {
    "path": "libsrc/csg/csgeom.hpp",
    "content": "#ifndef FILE_CSGEOM\n#define FILE_CSGEOM\n\n/**************************************************************************/\n/* File:   csgeom.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   27. Nov. 97                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  /**\n     Constructive Solid Geometry\n  */\n\n\n  class TriangleApproximation;\n  class TATriangle;\n\n  /**\n     A top level object is an entity to be meshed.\n     I can be either a solid, or one surface patch of a solid.\n  */\n  class DLL_HEADER TopLevelObject\n  {\n    Solid * solid;\n    Surface * surface;\n\n    double red, blue, green;\n    bool visible, transp;\n    double maxh;\n    string material;\n    int layer;\n    int bc;     // for surface patches, only\n    string bcname;\n\n  public:\n    TopLevelObject (Solid * asolid,\n\t\t    Surface * asurface = NULL);\n    // default constructor for archive\n    TopLevelObject() {}\n\n    void DoArchive(Archive& archive)\n    {\n      archive & solid & surface & red & blue & green & visible & transp & maxh\n        & material & layer & bc & bcname;\n    }\n    const Solid * GetSolid() const { return solid; }\n    Solid * GetSolid() { return solid; }\n\n    const Surface * GetSurface () const { return surface; }\n    Surface  * GetSurface () { return surface; }\n\n    void GetData (ostream & ost);\n    void SetData (istream & ist);\n\n    void SetMaxH (double amaxh) { maxh = amaxh; } \n    double GetMaxH () const { return maxh; }\n\n    void SetRGB (double ared, double agreen, double ablue)\n    {\n      red = ared;\n      green = agreen;\n      blue = ablue;\n    }\n\n    double GetRed () const { return red; }\n    double GetGreen () const { return green; }\n    double GetBlue () const { return blue; }\n\n    void SetTransparent (bool atransp) \n    { transp = atransp; }\n    bool GetTransparent () const { return transp; }\n\n    void SetVisible (bool avisible)\n    { visible = avisible; }\n    bool GetVisible () const { return visible; }\n\n    const string GetMaterial () const { return material; }\n    void SetMaterial (const string & mat) { material = mat; }\n\n    int GetLayer () const { return layer; }\n    void SetLayer (int alayer) { layer = alayer; }\n\n    void SetBCProp (int abc) { bc = abc; }\n    int GetBCProp () const { return bc; }\n\n    void SetBCName (string abc) { bcname = abc; }\n    const string GetBCName () const { return bcname; }\n  };\n\n\n\n\n\n  /**\n     CSGeometry has the whole geometric information\n  */\n  class DLL_HEADER CSGeometry : public NetgenGeometry\n  {\n  private:\n    /// all surfaces\n    SymbolTable<Surface*> surfaces;\n\n  public:\n    /// primitive of surface\n    NgArray<const Primitive*> surf2prim;\n\n  private:\n    NgArray<Surface*> delete_them;\n\n    /// all named solids\n    SymbolTable<Solid*> solids;\n\n    /// all 2d splinecurves\n    SymbolTable<shared_ptr<SplineGeometry<2>>> splinecurves2d;\n    /// all 3d splinecurves\n    SymbolTable<shared_ptr<SplineGeometry<3>>> splinecurves3d;\n\n    /// all top level objects: solids and surfaces\n    NgArray<TopLevelObject*> toplevelobjects;\n\n  public:\n    /// additional points specified by user\n    class UserPoint : public Point<3>\n    {\n      int index;\n      string name;\n    public:\n      UserPoint() = default;\n      UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; }\n      UserPoint (Point<3> p, const string & _name) : Point<3>(p), index(-1), name(_name) { ; } \n      int GetIndex() const { return index; }\n      const string & GetName() const { return name; } \n      void DoArchive(Archive& archive)\n      {\n        archive & index & name;\n        Point<3>::DoArchive(archive);\n      }\n    };\n    \n  private:\n    // NgArray<Point<3> > userpoints;\n    NgArray<UserPoint> userpoints;\n    NgArray<double> userpoints_ref_factor;\n\n    mutable NgArray<Point<3> > identpoints;\n\n    /// triangular approximation of top level objects\n    NgArray<TriangleApproximation*> triapprox;\n\n    /// increment, if geometry is changed\n    static int changeval;\n  \n    /// bounding box of geometry\n    Box<3> boundingbox;\n\n    /// bounding box, if not set by input file\n    static Box<3> default_boundingbox;\n\n    /// identic surfaces are stored by pair of indizes, val = inverse\n    INDEX_2_HASHTABLE<int> identicsurfaces;\n    NgArray<int> isidenticto;\n    /// identification of boundaries (periodic, thin domains, ...)\n\n    double ideps;\n\n    /// filename of inputfile\n    string filename;\n\n    /// store splinesurfaces, such that added ones do not get deleted before geometry does\n    NgArray<shared_ptr<SplineSurface>> spline_surfaces;\n\n    shared_ptr<BlockAllocator> solid_ball = Solid::ball;\n    \n  public:\n    CSGeometry ();\n    CSGeometry (const string & afilename);\n    virtual ~CSGeometry ();\n\n    void Clean ();\n\n    virtual void Save (const filesystem::path & filename) const override;\n    void Save (ostream & ost) const;\n    void Load (istream & ist);\n\n    void SaveSurfaces (ostream & out) const;\n    void LoadSurfaces (istream & in);\n\n    virtual void SaveToMeshFile (ostream & ost) const override;\n\n    PointGeomInfo ProjectPoint(INDEX surfind, Point<3> & p) const override;\n    bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const override;\n    void ProjectPointEdge(INDEX surfind, INDEX surfind2, Point<3> & p,\n                          EdgePointGeomInfo* gi = nullptr) const override;\n    Vec<3> GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi = nullptr) const override;\n\n    void PointBetween(const Point<3> & p1, const Point<3> & p2,\n                      double secpoint, int surfi,\n                      const PointGeomInfo & gi1,\n                      const PointGeomInfo & gi2,\n                      Point<3> & newp, PointGeomInfo & newgi) const override;\n\n    void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\n                      int surfi1, int surfi2,\n                      const EdgePointGeomInfo & ap1,\n                      const EdgePointGeomInfo & ap2,\n                      Point<3> & newp, EdgePointGeomInfo & newgi) const override;\n\n    Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2,\n                       const EdgePointGeomInfo & ap1) const override;\n\n    int GetChangeVal() { return changeval; }\n    void Change() { changeval++; }\n\n    void AddSurface (Surface * surf);\n    void AddSurface (char * name, Surface * surf);\n    void AddSurfaces (Primitive * prim);\n\n    int GetNSurf () const { return surfaces.Size(); }\n    const Surface * GetSurface (const char * name) const;\n    const Surface * GetSurface (int i) const\n    { return surfaces[i]; }\n\n    void SetSolid (const char * name, Solid * sol);\n    const Solid * GetSolid (const char * name) const;\n    const Solid * GetSolid (const string & name) const;\n    int GetNSolids () const { return solids.Size(); }\n    const Solid * GetSolid (int i) const { return solids[i]; }\n    const SymbolTable<Solid*> & GetSolids () const { return solids; }\n\n\n    void SetSplineCurve (const char * name, shared_ptr<SplineGeometry<2>> spl);\n    void SetSplineCurve (const char * name, shared_ptr<SplineGeometry<3>> spl);\n    shared_ptr<SplineGeometry<2>> GetSplineCurve2d (const string & name) const;\n    shared_ptr<SplineGeometry<3>> GetSplineCurve3d (const string & name) const;\n\n    void DoArchive(Archive& archive) override;\n    \n\n    void SetFlags (const char * solidname, const Flags & flags);\n\n\n    int GetNTopLevelObjects () const\n    { return toplevelobjects.Size(); }\n    int SetTopLevelObject (Solid * sol, Surface * surf = NULL);\n    void GetTopLevelObject (int nr, Solid *& sol, Surface *& surf)\n    {\n      sol = toplevelobjects[nr]->GetSolid();\n      surf = toplevelobjects[nr]->GetSurface();\n    }\n    void GetTopLevelObject (int nr, const Solid *& sol, const Surface *& surf) const\n    {\n      sol = toplevelobjects[nr]->GetSolid();\n      surf = toplevelobjects[nr]->GetSurface();\n    }\n\n    TopLevelObject * GetTopLevelObject (const Solid * sol, const Surface * surf = NULL);\n    TopLevelObject * GetTopLevelObject (int nr) const\n    { return toplevelobjects[nr]; }\n    // const TopLevelObject * GetTopLevelObject (int nr) const\n    // { return toplevelobjects[nr]; }\n    void RemoveTopLevelObject (Solid * sol, Surface * surf = NULL); \n\n\n    void AddUserPoint (const Point<3> & p, double ref_factor = 0)      \n    { userpoints.Append (UserPoint(p,userpoints.Size()+1)); userpoints_ref_factor.Append (ref_factor); }\n    void AddUserPoint (const UserPoint up, double ref_factor = 0)\n    { userpoints.Append (up); userpoints_ref_factor.Append (ref_factor); }\n    int GetNUserPoints () const\n    { return userpoints.Size(); }\n    const UserPoint & GetUserPoint (int nr) const\n    { return userpoints[nr]; }\n    double GetUserPointRefFactor (int nr) const\n    { return userpoints_ref_factor[nr]; }\n  \n    void AddIdentPoint (const Point<3> & p) const\n    { identpoints.Append(p);}\n    int GetNIdentPoints (void) const\n    { return identpoints.Size();}\n    const Point<3> & GetIdentPoint(int nr) const\n    { return identpoints[nr]; }\n    void DeleteIdentPoints(void) const\n    { identpoints.DeleteAll();}\n\n\n    // quick implementations:\n    NgArray<SingularFace*> singfaces;\n    NgArray<SingularEdge*> singedges;\n    NgArray<SingularPoint*> singpoints;\n    NgArray<Identification*> identifications;\n\n    int GetNIdentifications (void) const { return identifications.Size(); }\n    void AddIdentification (Identification * ident);\n\n\n    ///\n    void CalcTriangleApproximation(double detail, double facets);\n\n    ///\n    void FindIdenticSurfaces (double eps);\n    ///\n    void GetSurfaceIndices (const Solid * sol, \n\t\t\t    const BoxSphere<3> & box, \n\t\t\t    NgArray<int> & locsurf) const;\n    ///\n    void GetIndependentSurfaceIndices (const Solid * sol, \n\t\t\t\t       const BoxSphere<3> & box, \n\t\t\t\t       NgArray<int> & locsurf) const;\n    ///\n    /*\n    void GetIndependentSurfaceIndices (const Solid * sol, \n\t\t\t\t       const Point<3> & p, Vec<3> & v,\n\t\t\t\t       NgArray<int> & locsurf) const;\n    */\n    ///\n    void GetIndependentSurfaceIndices (NgArray<int> & locsurf) const;\n\n    ///\n    int GetSurfaceClassRepresentant (int si) const\n    { return isidenticto[si]; }\n\n    ///\n    const TriangleApproximation * GetTriApprox (int msnr)\n    {\n      if (msnr < triapprox.Size())\n\treturn triapprox[msnr];\n      return 0;\n    }\n  \n\n    void IterateAllSolids (SolidIterator & it, bool only_once = false) const;\n\n    void RefineTriangleApprox (Solid * locsol, \n\t\t\t       int surfind,\n\t\t\t       const BoxSphere<3> & box, \n\t\t\t       double detail,\n\t\t\t       const TATriangle & tria, \n\t\t\t       TriangleApproximation & tams,\n\t\t\t       IndexSet & iset,\n\t\t\t       int level);\n\n    const Box<3> & BoundingBox () const { return boundingbox; }\n\n    void SetBoundingBox (const Box<3> & abox)\n    {\n      boundingbox = abox;\n    }\n\n\n    static void SetDefaultBoundingBox (const Box<3> & abox)\n    {\n      default_boundingbox = abox;\n    }\n\n    double MaxSize () const;\n\n    void SetIdEps(double eps){ideps = eps;}\n    double GetIdEps(void) const {return ideps;}\n\n    class BCModification {\n    public:\n      int si;\n      int tlonr;\n      int bcnr;\n      string * bcname;\n    };\n\n    NgArray<BCModification> bcmodifications;\n\n\n    map<tuple<Surface*,Surface*>, string> named_edges;\n      \n\n    \n    virtual int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam) override;\n\n    void AddSplineSurface (shared_ptr<SplineSurface> ss) { spline_surfaces.Append(ss); }\n  };\n\n\n  \n\n\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/csg/csgparser.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n  static kwstruct defkw[] =\n    {\n      { TOK_RECO,    \"algebraic3d\" },\n      { TOK_SOLID,   \"solid\" },\n      { TOK_TLO,     \"tlo\" },\n      { TOK_CURVE2D, \"curve2d\" },\n      { TOK_CURVE3D, \"curve3d\" },\n      { TOK_BOUNDINGBOX, \"boundingbox\" },\n      { TOK_OR,      \"or\" },\n      { TOK_AND,     \"and\" },\n      { TOK_NOT,     \"not\" },\n      { TOK_SINGULAR, \"singular\" },\n      { TOK_EDGE,     \"edge\" },\n      { TOK_FACE,     \"face\" },\n      { TOK_POINT,    \"point\" },\n      { TOK_IDENTIFY, \"identify\" },\n      { TOK_CLOSESURFACES, \"closesurfaces\" },\n      { TOK_CLOSEEDGES, \"closeedges\" },\n      { TOK_PERIODIC,  \"periodic\" },\n      { TOK_BOUNDARYCONDITION, \"boundarycondition\" },\n      { TOK_BOUNDARYCONDITIONNAME, \"boundaryconditionname\" },\n      { TOK_DEFINE, \"define\" },\n      { TOK_CONSTANT, \"constant\" },\n      { TOKEN_TYPE(0), 0 }\n    };\n\n  static primstruct defprim[] =\n    {\n      { TOK_PLANE,     \"plane\" },\n      { TOK_SPHERE,    \"sphere\" },\n      { TOK_CYLINDER,  \"cylinder\" },\n      { TOK_CONE,      \"cone\" },\n      { TOK_ELLIPTICCONE, \"ellipticcone\" },\n      { TOK_ELLIPTICCYLINDER, \"ellipticcylinder\" },\n      { TOK_ELLIPSOID, \"ellipsoid\" },\n      { TOK_ORTHOBRICK, \"orthobrick\" },\n      { TOK_POLYHEDRON, \"polyhedron\" },\n      { TOK_TORUS,      \"torus\" },\n\n      { TOK_TUBE,      \"tube\" },\n      { TOK_GENCYL,    \"gencyl\" },\n      { TOK_EXTRUSION,  \"extrusion\" },\n      { TOK_REVOLUTION, \"revolution\" },\n\n      { TOK_TRANSLATE, \"translate\" },\n      { TOK_MULTITRANSLATE, \"multitranslate\" },\n      { TOK_ROTATE,   \"rotate\" },\n      { TOK_MULTIROTATE, \"multirotate\" },\n      { PRIMITIVE_TYPE(0), 0 }\n    };\n\n  static CSGeometry * geom;\n\n\n  CSGScanner :: CSGScanner (istream & ascanin)\n  {\n    scanin = &ascanin;\n    token = TOK_END;\n    num_value = 0;\n    linenum = 1;\n  }\n\n\n  void CSGScanner :: ReadNext ()\n  {\n    char ch;\n  \n\n    // scan whitespaces\n    do\n      { \n\tscanin->get(ch);\n\n\t//if (ch == '\\n') \n\t//  linenum++;\n\n\t// end of file reached\n\tif (scanin->eof())\n\t  {\n\t    token = TOK_END;\n\t    return;\n\t  }\n\tif (ch == '\\n') \n\t  linenum++;\n\n\n\t// skip comment line\n\tif (ch == '#')\n\t  {\n\t    while (ch != '\\n')\n\t      {\n\t\tscanin->get(ch);\n\t\tif (scanin->eof())\n\t\t  {\n\t\t    token = TOK_END;\n\t\t    return;\n\t\t  }\n\t      }\n\t    linenum++;\n\t  }\t\n      }\n    while (isspace(ch));\n  \n    switch (ch)\n      {\n      case '(': case ')': \n      case '[': case ']': \n      case '-':\n      case '=': case ',': case ';':\n\t{\n\t  token = TOKEN_TYPE (ch);\n\t  break;\n\t}\n  \n      default:\n\t{\n\t  if (isdigit (ch) || ch == '.')\n\t    {\n\t      scanin->putback (ch);\n\t      (*scanin) >> num_value;\n\t      token = TOK_NUM;\n\t      return;\n\t    }\n\n\t  if (isalpha (ch))\n\t    {\n\t      string_value = string (1, ch);\n\t      scanin->get(ch);\n\t      while (isalnum(ch) || ch == '_')\n\t\t{\n\t\t  string_value += ch;\n\t\t  scanin->get(ch);\n\t\t}\n\t      scanin->putback (ch);\n\t    }\n\n\t  int nr = 0;\n\t  while (defkw[nr].kw)\n\t    {\n\t      if (string_value == defkw[nr].name)\n\t\t{\n\t\t  token = defkw[nr].kw;\n\t\t  return;\n\t\t}\n\t      nr++;\n\t    }\n\n\t  nr = 0;\n\t  while (defprim[nr].kw)\n\t    {\n\t      if (string_value == defprim[nr].name)\n\t\t{\n\t\t  token = TOK_PRIMITIVE;\n\t\t  prim_token = defprim[nr].kw;\n\t\t  return;\n\t\t}\n\t      nr++;\n\t    }\n\n\t  token = TOK_STRING;\n\t}\n      }\n  }\n\n  void CSGScanner :: Error (const string & err)\n  {\n    stringstream errstr;\n    errstr << \"Parsing error in line \" << linenum << \": \" << endl << err << endl;\n    throw string(errstr.str());\n  }\n\n\n  /*\n    Solid = Term { OR Term }\n    Term  = Primary { AND Primary }\n    Primary = PRIM | IDENT | ( Solid ) | NOT Primary\n  */\n\n  void ParseChar (CSGScanner & scan, char ch)\n  {\n    if (scan.GetToken() != TOKEN_TYPE(ch)) \n      scan.Error (string (\"token '\") + string(1, ch) + string(\"' expected\"));\n    scan.ReadNext();\n  }\n  \n  double ParseNumber(CSGScanner & scan)\n  {\n    if (scan.GetToken() == '-')\n      {\n\tscan.ReadNext();\n\treturn -ParseNumber (scan);\n      }\n    if (scan.GetToken() != TOK_NUM) scan.Error (\"number expected\");\n    double val = scan.GetNumValue();\n    scan.ReadNext();\n    return val;\n  }\n\n  Vec<3> ParseVector (CSGScanner & scan)\n  {\n    Vec<3> v;\n    v(0) = ParseNumber (scan);\n    ParseChar (scan, ',');\n    v(1) = ParseNumber (scan);\n    ParseChar (scan, ',');\n    v(2) = ParseNumber (scan);\n    return v;\n  }\n\n\n  CSGScanner & operator>> (CSGScanner & scan, char ch)\n  {\n    if (scan.GetToken() != TOKEN_TYPE(ch)) \n      scan.Error (string (\"token '\") + string(1, ch) + string(\"' expected\"));\n    scan.ReadNext();\n    return scan;\n  }\n\n  CSGScanner & operator>> (CSGScanner & scan, double & d)\n  {\n    d = ParseNumber (scan);\n    return scan;\n  }\n\n  CSGScanner & operator>> (CSGScanner & scan, int & i)\n  {\n    i = int (ParseNumber (scan));\n    return scan;\n  }\n\n  CSGScanner & operator>> (CSGScanner & scan, Point<3> & p)\n  {\n    scan >> p(0) >> ',' >> p(1) >> ',' >> p(2);\n    return scan;\n  }\n\n  CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v)\n  {\n    scan >> v(0) >> ',' >> v(1) >> ',' >> v(2);\n    return scan;\n  }\n\n\n  Solid * ParseSolid (CSGScanner & scan);\n  Solid * ParseTerm (CSGScanner & scan);\n  Solid * ParsePrimary (CSGScanner & scan);\n \n\n  Solid * ParsePrimary (CSGScanner & scan)\n  {\n    if (scan.GetToken() == TOK_PRIMITIVE)\n      {\n\tswitch (scan.GetPrimitiveToken())\n\t  {\n\t  case TOK_PLANE:\n\t    {\n\t      Point<3> p;\n\t      Vec<3> v;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> p >> ';' >> v >> ')';\n\n\t      OneSurfacePrimitive * surf = new Plane ( p, v );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\t  case TOK_CYLINDER:\n\t    {\n\t      Point<3> pa, pb;\n\t      double r;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pa >> ';' >> pb >> ';' >> r >> ')';\n\n\t      OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\t  case TOK_ELLIPTICCYLINDER:\n\t    {\n\t      Point<3> pa;\n\t      Vec<3> vl, vs;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pa >> ';' >> vl >> ';' >> vs >> ')';\n\n\t      OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs);\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\n\t  case TOK_ELLIPSOID:\n\t    {\n\t      Point<3> pa;\n\t      Vec<3> v1, v2, v3;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pa >> ';' >> v1 >> ';' >> v2 >> ';' >> v3 >> ')';\n\n\t      OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3);\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\n\t  case TOK_CONE:\n\t    {\n\t      Point<3> pa, pb;\n\t      double ra, rb;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pa >> ';' >> ra >> ';' >> pb >> ';' >> rb >> ')';\n\n\t      OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\t  case TOK_ELLIPTICCONE:\n\t    {\n              Point<3> a;\n\t      Vec<3> vl, vs;\n\t      double h, vlr;\n\n\t      scan.ReadNext();\n\t      scan >> '(' >> a >> ';' >> vl >> ';' >> vs >> ';' >> h >>';' >> vlr >>  ')';\n\n\t      OneSurfacePrimitive * surf = new EllipticCone ( a, vl, vs, h, vlr );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\t  case TOK_SPHERE:\n\t    {\n\t      Point<3> p;\n\t      double r;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> p >> ';' >> r >> ')';\n\n\t      OneSurfacePrimitive * surf = new Sphere ( p, r );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\n\t  case TOK_ORTHOBRICK:\n\t    {\n\t      Point<3> pa, pb;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pa >> ';' >> pb >> ')';\n\t      \n\n\t      Primitive * nprim = new OrthoBrick (pa, pb);\n\t      geom->AddSurfaces (nprim);\n\t      return new Solid (nprim);\n\t    } \n\n\t  case TOK_POLYHEDRON:\n\t    {\n\t      // Added by Dalibor Lukas, October 15, 2003\n\n\t      Point<3> p;\n\t      //int pi1, pi2, pi3, pi4;\n\t      \n\t      scan.ReadNext();\n\t      ParseChar (scan, '(');\n\t      \n\t      Polyhedra * polyhedron = new Polyhedra;\n\n\t      // scanning the points\n\t      while (1)\n\t\t{\n\t\t  p = Point<3> (ParseVector (scan));\n\t\t  ParseChar (scan, ';');\n\n\t\t  polyhedron->AddPoint(p);\n\n\t\t  if (scan.GetToken() == ';')\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      break;\n\t\t    }\n\t\t}\n\n\t      // scanning the faces\n\t      int inputface = 0;\n\t      while (1)\n\t\t{\n\t\t  NgArray<int> pnums,cleaned_pnums;\n\t\t  for(int i=0; i<3; i++)\n\t\t    {\n\t\t      pnums.Append((int) (ParseNumber (scan)));\n\t\t      if(i<2) \n\t\t\tParseChar (scan, ',');\n\t\t    }\n\n\t\t  if (scan.GetToken() == TOK_COMMA)\n\t\t    {\n\t\t      ParseChar (scan, ',');\n\t\t      pnums.Append((int) (ParseNumber (scan)));\t\n\t\t    }\n\n\t\t  for(int i=0; i<pnums.Size(); i++)\n\t\t    if(!cleaned_pnums.Contains(pnums[i]))\n\t\t      cleaned_pnums.Append(pnums[i]);\n\n\t\t  if(cleaned_pnums.Size() == 3)\n\t\t    {\n\t\t      polyhedron->AddFace(cleaned_pnums[0]-1,\n\t\t\t\t\t  cleaned_pnums[1]-1,\n\t\t\t\t\t  cleaned_pnums[2]-1,\n\t\t\t\t\t  inputface);\n\t\t    }\n\t\t  else if(cleaned_pnums.Size() == 4)\n\t\t    {\n\t\t      polyhedron->AddFace(cleaned_pnums[0]-1,\n\t\t\t\t\t  cleaned_pnums[1]-1,\n\t\t\t\t\t  cleaned_pnums[2]-1,\n\t\t\t\t\t  inputface);\n\t\t      polyhedron->AddFace(cleaned_pnums[0]-1,\n\t\t\t\t\t  cleaned_pnums[2]-1,\n\t\t\t\t\t  cleaned_pnums[3]-1,\n\t\t\t\t\t  inputface);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      ostringstream msg;\n\t\t      msg << \"Something wrong with polyhedron face:\";\n\t\t      for(int i=0; i<pnums.Size(); i++)\n\t\t\tmsg << \" \" << pnums[i];\n\t\t      throw NgException(msg.str());\n\t\t    }\n\t\t  \n\t\t      \n\n\t\t  if (scan.GetToken() == ')')\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      break;\n\t\t    }\n\t\t  scan.ReadNext();\n\t\t  inputface++;\n\t\t}\n\n\t      geom->AddSurfaces (polyhedron);\n\t      return new Solid (polyhedron);\n\t    }\n\n\n\t  case TOK_REVOLUTION:\n\t    {\n\t      Point<3> p0,p1;\n\n\t      scan.ReadNext();\n\t      scan >> '(' >> p0 >> ';' >> p1 >> ';';\n\n\t      string spline = scan.GetStringValue();\n\t      \n\t      scan.ReadNext();\n\t      scan >> ')';\n\t      \n\t      if(!geom->GetSplineCurve2d(spline))\n\t\t{\n\t\t  scan.Error ( string(\"2D Spline curve not found: \") + spline );\n\t\t  break;\n\t\t}\n\n\t      Primitive * nprim = new Revolution(p0,p1,\n\t\t\t\t\t\t geom->GetSplineCurve2d(spline));\n\n\t      geom->AddSurfaces (nprim);\n\t      return new Solid(nprim);\n\t    }\n\n\n\t  case TOK_EXTRUSION: \n\t    {   \n\t      scan.ReadNext();\n\t      scan >> '(';\n\t      string epath = scan.GetStringValue();\n\t      scan.ReadNext();\n\t      scan >> ';';\n\t      string profile = scan.GetStringValue();\n\n\t      \n\t      scan.ReadNext();\n\t      Vec<3> z_dir;\n\t      scan >> ';' >> z_dir(0) >> ',' >> z_dir(1) >> ',' >> z_dir(2) >> ')';\n\t      \n\t      if(!geom->GetSplineCurve2d(profile))\n\t\t{\n\t\t  scan.Error ( string(\"2D Spline curve not found: \") + profile );\n\t\t  break;\n\t\t}\n\t      if(!geom->GetSplineCurve3d(epath))\n\t\t{\n\t\t  scan.Error ( string(\"2D Spline curve not found: \") + epath );\n\t\t  break;\n\t\t}\n\t      \n\t      Primitive * nprim = new Extrusion(geom->GetSplineCurve3d(epath),\n\t\t\t\t\t\tgeom->GetSplineCurve2d(profile),\n\t\t\t\t\t\tz_dir);\n\t      geom->AddSurfaces (nprim);\n\t      return new Solid(nprim);\n\t    }\n\n\n\t  /// Torus \n    \t  /// Lorenzo Codecasa (codecasa@elet.polimi.it)\n    \t  /// April 27th, 2005 \n\t  ///\n\t  /// begin...\n\t  case TOK_TORUS:\n\t    {     \n\t      Point<3> pc; \n\t      Vec<3> vn;\n\t      double R, r;\n\t      \n\t      scan.ReadNext();\n\t      scan >> '(' >> pc >> ';' >> vn >> ';' >> R >> ';' >> r >> ')';\n\n\t      OneSurfacePrimitive * surf = new Torus ( pc, vn, R, r );\n\t      geom->AddSurfaces (surf);\n\t      return new Solid (surf);\n\t    }\n\t  /// ..end\n\n\n\n\n\t  case TOK_TRANSLATE: \n\t    {\n\t      Vec<3> v;\n\t      scan.ReadNext();\n\n\t      ParseChar (scan, '(');\n\t      v = ParseVector (scan);\n\t      ParseChar (scan, ';');\n\t      \n\t      Solid * sol1 = ParseSolid (scan);\n\n\t      ParseChar (scan, ')');\n\n\t      Solid * nsol = sol1 -> Copy(*geom);\n\t      Transformation<3> trans(v);\n\t      nsol -> Transform (trans);\n\t      return nsol;\n\t    }\n\n\n\t  case TOK_ROTATE: \n\t    {\n\t      Point<3> c;\n\t      Vec<3> v;\n\t      scan.ReadNext();\n\n\t      scan >> '(' >> c >> ';' >> v >> ';';\n\n\t      Solid * sol1 = ParseSolid (scan);\n\n\t      ParseChar (scan, ')');\n\n\t      Solid * nsol = sol1 -> Copy(*geom);\n\t      Transformation<3> trans(c,v(0),v(1),v(2));\n\t      nsol -> Transform (trans);\n\t      return nsol;\n\t    }\n\n\n\t  case TOK_MULTITRANSLATE: \n\t    {\n\t      Vec<3> v;\n\t      int n;\n\t      \n\t      scan.ReadNext();\n\n\t      scan >> '(' >> v >> ';' >> n >> ';';\n\n\t      Solid * sol1 = ParseSolid (scan);\n\t      \n\t      scan >> ')';\n\t      \n\t      Solid * hsol = sol1;\n\t      for (int i = 1; i <= n; i++)\n\t\t{\n\t\t  Solid * nsol = sol1 -> Copy(*geom);\n\t\t  Transformation<3> trans(double(i) * v);\n\t\t  \n\t\t  nsol -> Transform (trans);\n\t\t  hsol = new Solid (Solid::UNION, hsol, nsol); \n\t\t}\n\t      return hsol;\n\t    }\n\n\n\t  case TOK_MULTIROTATE: \n\t    {\n\t      Point<3> c;\n\t      Vec<3> v;\n\t      int n;\n\t      \n\t      scan.ReadNext();\n\n\t      scan >> '(' >> c >> ';' >> v >> ';' >> n >> ';';\n\t      Solid * sol1 = ParseSolid (scan);\n\t      scan >> ')';\n\n\t      Transformation<3> trans(c, v(0), v(1), v(2));\n\t      Transformation<3> multi(Vec<3>(0,0,0));\n\t      Transformation<3> ht;\n\n\t      Solid * hsol = sol1;\n\t      for (int i = 1; i <= n; i++)\n\t\t{\n\t\t  Solid * nsol = sol1 -> Copy(*geom);\n\n\t\t  nsol -> Transform (multi);\n\t\t  hsol = new Solid (Solid::UNION, hsol, nsol); \n\n\t\t  ht=multi;\n\t\t  multi.Combine (trans, ht);\n\t\t}\n\t      return hsol;\n\t    }\n\n\n\t  default:\n\t    {\n\t      scan.Error (string (\"unknown primary \") + scan.GetStringValue());\n\t    }\n\n\t  }\n      }\n\n    else if (scan.GetToken() == TOK_STRING &&\n\t     geom->GetSolid(scan.GetStringValue()))\n\n      {\n\tSolid * sol = const_cast<Solid*> (geom->GetSolid(scan.GetStringValue()));\n\tscan.ReadNext();\n\treturn sol;\n      }\n\n    else if (scan.GetToken() == TOK_NOT)\n\n      {\n\tscan.ReadNext();\n\tSolid * sol1 = ParsePrimary (scan);\n\treturn new Solid (Solid::SUB, sol1);\n      }\n\n    else if (scan.GetToken() == '(')\n\n      {\n\tscan.ReadNext();\n\tSolid * sol1 = ParseSolid (scan);\n\tscan.ReadNext();\n\treturn sol1;\n      }\n\n    scan.Error (string (\"not a primary, name = \")+\n\t\tscan.GetStringValue());\n    return 0;\n  }\n\n\n\n  Solid * ParseTerm (CSGScanner & scan)\n  {\n    Solid * sol = ParsePrimary(scan);\n    while (scan.GetToken() == TOK_AND)\n      {\n\tscan.ReadNext();\n\tSolid * sol2 = ParsePrimary(scan);\n\tsol = new Solid (Solid::SECTION, sol, sol2);\n      }\n    return sol;\n  }\n\n\n  Solid * ParseSolid (CSGScanner & scan)\n  {\n    Solid * sol = ParseTerm(scan);\n    while (scan.GetToken() == TOK_OR)\n      {\n\tscan.ReadNext();\n\tSolid * sol2 = ParseTerm(scan);\n\tsol = new Solid (Solid::UNION, sol, sol2);\n      }\n    return sol;\n  }\n\n\n  template <int D>\n  void LoadSpline (SplineGeometry<D> & spline, CSGScanner & scan)\n  {\n    double hd;\n    Point<D> x;\n    int nump, numseg;\n    \n    //scan.ReadNext();\n    scan >> nump >> ';';\n    \n    hd = 1;\n    spline.geompoints.SetSize(nump);\n    for(int i = 0; i<nump; i++)\n      {\n\tif(D==2)\n\t  scan >> x(0) >> ',' >> x(1) >> ';';\n\telse if(D==3)\n\t  scan >> x(0) >> ',' >> x(1) >> ',' >> x(2) >> ';';\n\t\n\tspline.geompoints[i] = GeomPoint<D>(x,hd);\n      }\n    \n    scan >> numseg;// >> ';';\n\n    spline.splines.SetSize(numseg);\n\n  int pnums,pnum1,pnum2,pnum3;\n    \n\n  for(int i = 0; i<numseg; i++)\n    {\n      scan >> ';' >> pnums >> ',';\n      if (pnums == 2)\n\t{\n\t  scan >> pnum1 >> ',' >> pnum2;// >> ';';\n\t  spline.splines[i] = new LineSeg<D>(spline.geompoints[pnum1-1],\n\t\t\t\t\t     spline.geompoints[pnum2-1]);\n\t}\n      else if (pnums == 3)\n\t{\n\t  scan >> pnum1 >> ',' >> pnum2 >> ',' \n\t       >> pnum3;// >> ';';\n\t  spline.splines[i] = new SplineSeg3<D>(spline.geompoints[pnum1-1],\n\t\t\t\t\t\tspline.geompoints[pnum2-1],\n\t\t\t\t\t\tspline.geompoints[pnum3-1]);\n\t}\n      else if (pnums == 4)\n\t{\n\t  scan >> pnum1 >> ',' >> pnum2 >> ',' \n\t       >> pnum3;// >> ';';\n\t  spline.splines[i] = new CircleSeg<D>(spline.geompoints[pnum1-1],\n\t\t\t\t\t       spline.geompoints[pnum2-1],\n\t\t\t\t\t       spline.geompoints[pnum3-1]);\n\t}\n    }\n  }\n\n\n\n\n  void ParseFlags (CSGScanner & scan, Flags & flags)\n  {\n    while (scan.GetToken() == '-')\n      {\n\tscan.ReadNext();\n\tstring name = scan.GetStringValue();\n\tscan.ReadNext();\n\tif (scan.GetToken() == '=')\n\t  {\n\t    scan.ReadNext();\n\t    if (scan.GetToken() == TOK_STRING)\n\t      {\n\t\tflags.SetFlag (name.c_str(), scan.GetStringValue().c_str());\n\t\tscan.ReadNext();\n\t      }\n\t    else if (scan.GetToken() == '[')\n\t      {\n\t\tscan.ReadNext();\n\n\t\tif(scan.GetToken() == '-' || scan.GetToken() == TOK_NUM)\n\t\t  {\n\t\t    Array<double> vals;\n\t\t    vals.Append (ParseNumber(scan));\n\t\t    while (scan.GetToken() == ',')\n\t\t      {\n\t\t\tscan.ReadNext();\n\t\t\tvals.Append (ParseNumber(scan));\n\t\t      }\n\t\t    ParseChar (scan, ']');\n\t\t    flags.SetFlag (name, vals);\n\t\t  }\n\t\telse\n\t\t  { // string list\n\t\t    Array<string> vals;\n                    vals.Append(scan.GetStringValue());\n\t\t    scan.ReadNext();\n\n\t\t    while (scan.GetToken() == ',')\n\t\t      {\n\t\t\tscan.ReadNext();\n                        vals.Append(scan.GetStringValue());\n\t\t\tscan.ReadNext();\n\t\t      }\n\t\t    ParseChar (scan, ']');\n\t\t    flags.SetFlag (name, vals);\n\t\t  }\n\t      }\n\t    else if (scan.GetToken() == TOK_NUM)\n\t      {\n\t\tflags.SetFlag (name.c_str(), scan.GetNumValue());\n\t\tscan.ReadNext();\n\t      }\n\t  }     \n\telse\n\t  {\n\t    flags.SetFlag (name.c_str());\n\t  }\n      }\n  }\n\n\n  /*\n    Main parsing function for CSG geometry\n  */\n  CSGeometry * ParseCSG (istream & istr, CSGeometry * instance=nullptr)\n  {\n    CSGScanner scan(istr);\n    \n    if (instance)\n    {\n      new (instance) CSGeometry;\n      geom = instance;\n    }\n    else\n      geom = new CSGeometry;\n\n    scan.ReadNext();\n    if (scan.GetToken() != TOK_RECO)  // keyword 'algebraic3d'\n      return 0;\n\n    scan.ReadNext();\n\n    try\n      {\n\twhile (1)\n\t  {\n\t    if (scan.GetToken() == TOK_END) break;\n\t    \n\t    if (scan.GetToken() == TOK_SOLID)\n\t      {\n\t\tscan.ReadNext();\n\t\tif (scan.GetToken() != TOK_STRING)\n\t\t  scan.Error (\"name identifier expected\");\n\t\tstring solidname = scan.GetStringValue();\n\n\t\tscan.ReadNext();\n\n\t\tParseChar (scan, '=');\n\t\tSolid * solid = ParseSolid (scan);\n\n\t\tFlags flags;\n\t\tParseFlags (scan, flags);\n\n\t\tgeom->SetSolid (solidname.c_str(), new Solid (Solid::ROOT, solid)); \n\t\tgeom->SetFlags (solidname.c_str(), flags); \n\t\t\n\t\tParseChar (scan, ';');\n\t\t\n\t\tPrintMessage (4, \"define solid \", solidname);\n\t      }\n\n\t    else if (scan.GetToken() == TOK_TLO)\n\n\t      { // a TopLevelObject definition\n\n\t\tscan.ReadNext();\n\t\t\n\t\tstring name = scan.GetStringValue();\n\t\tscan.ReadNext();\n\n\t\tif (scan.GetToken() != TOK_STRING)\n\n\t\t  { // a solid TLO\n\n\t\t    Flags flags;\n\t\t    ParseFlags (scan, flags);\n\t\t    \n\t\t    ParseChar (scan, ';');\n\t\t    if (!geom->GetSolid (name))\n\t\t      scan.Error (\"Top-Level-Object \"+name+\" not defined\");\n\n\t\t    int tlonr = \n\t\t      geom->SetTopLevelObject ((Solid*)geom->GetSolid(name));\n\t\t    TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);\n\n\t\t    if (flags.NumListFlagDefined (\"col\"))\n\t\t      {\n\t\t\tconst Array<double> & col =\n\t\t\t  flags.GetNumListFlag (\"col\");\n\t\t\ttlo->SetRGB (col[0], col[1], col[2]);\n\t\t      }\n\n\t\t    if (flags.GetDefineFlag (\"transparent\"))\n\t\t      tlo->SetTransparent (1);\n\n\t\t    tlo->SetMaterial (flags.GetStringFlag (\"material\", \"\"));\n\t\t    tlo->SetLayer (int(flags.GetNumFlag (\"layer\", 1)));\n\t\t    if (flags.NumFlagDefined (\"maxh\"))\n\t\t      tlo->SetMaxH (flags.GetNumFlag(\"maxh\", 1e10));\n\t\t  }\n\n\t\telse\n\t\t  \n\t\t  { // a surface TLO\n\n\t\t    string surfname = scan.GetStringValue();\n\t\t    scan.ReadNext();\n\n\t\t    Flags flags;\n\t\t    ParseFlags (scan, flags);\n\t\t    \n\t\t    ParseChar (scan, ';');\n\n\t\t    NgArray<int> si;\n\t\t    geom->GetSolid(surfname)->GetSurfaceIndices(si);\n\t\t    int tlonr = \n\t\t      geom->SetTopLevelObject ((Solid*)geom->GetSolid(name),\n\t\t\t\t\t       (Surface*)geom->GetSurface(si.Get(1)));\n\t\t    TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);\n\t\t    if (flags.NumListFlagDefined (\"col\"))\n\t\t      {\n\t\t\tconst auto& col = flags.GetNumListFlag (\"col\");\n\t\t\ttlo->SetRGB (col[0], col[1], col[2]);\n\t\t      }\n\t\t    if (flags.GetDefineFlag (\"transparent\"))\n\t\t      tlo->SetTransparent (1);\n\n\t\t    if (flags.NumFlagDefined (\"maxh\"))\n\t\t      tlo->SetMaxH (flags.GetNumFlag(\"maxh\", 1e10));\n\t\t    tlo->SetLayer (int(flags.GetNumFlag (\"layer\", 1)));\n\t\t    tlo->SetBCProp (int(flags.GetNumFlag (\"bc\", -1)));\n\t\t    if ( flags.StringFlagDefined(\"bcname\") )\n\t\t      tlo->SetBCName ( flags.GetStringFlag (\"bcname\", \"default\") );\n\t\t  }\n\t      }\n\t    \n\t    else if (scan.GetToken() == TOK_IDENTIFY)\n\n\t      {\n\t\t\n\t\tscan.ReadNext();\n\t\tswitch (scan.GetToken())\n\t\t  {\n\t\t  case TOK_CLOSESURFACES:\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name1 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name2 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\n\t\t      Flags flags;\n\t\t      ParseFlags (scan, flags);\n\t\t      \n\t\t      ParseChar (scan, ';');\n\t\t      \n\t\t      \n\t\t      NgArray<int> si1, si2;\n\t\t      geom->GetSolid(name1)->GetSurfaceIndices(si1);\n\t\t      geom->GetSolid(name2)->GetSurfaceIndices(si2);\n\n\t\t      const TopLevelObject * domain = 0;\n\t\t      if (flags.StringFlagDefined (\"tlo\"))\n\t\t\t{\n\t\t\t  domain = \n\t\t\t    geom->GetTopLevelObject (geom->GetSolid(flags.GetStringFlag (\"tlo\",\"\")));\n\t\t\t  if (!domain) \n\t\t\t    scan.Error (\"identification needs undefined tlo\");\n\t\t\t}\n\n\t\t      geom->AddIdentification \n\t\t\t(new CloseSurfaceIdentification \n\t\t\t (geom->GetNIdentifications()+1, *geom, \n\t\t\t  geom->GetSurface (si1[0]), geom->GetSurface (si2[0]),\n\t\t\t  domain,\n\t\t\t  flags));\n\n\t\t      break;\n\t\t    }\n\t\t    \n\t\t  case TOK_PERIODIC:\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name1 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\n\t\t      string name2 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\n\t\t      ParseChar (scan, ';');\n\n\t\t      \n\t\t      NgArray<int> si1, si2;\n\t\t      geom->GetSolid(name1)->GetSurfaceIndices(si1);\n\t\t      geom->GetSolid(name2)->GetSurfaceIndices(si2);\n\t\t      \n\t\t      geom->AddIdentification \n\t\t\t(new PeriodicIdentification \n\t\t\t (geom->GetNIdentifications()+1,\n\t\t\t  *geom,\n\t\t\t  geom->GetSurface (si1.Get(1)),\n\t\t\t  geom->GetSurface (si2.Get(1))));\n\t\t      break;\n\t\t    }\n\n\t\t  default:\n\t\t    scan.Error (\"keyword 'closesurfaces' or 'periodic' expected\");\n\t\t  }\n\t\t\n\t      }\n\n\t    else if (scan.GetToken() == TOK_SINGULAR)\n\n\t      {\n\t\t\n\t\tscan.ReadNext();\n\t\tswitch (scan.GetToken())\n\t\t  {\n\t\t  case TOK_FACE:\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name1 = scan.GetStringValue();  // tlo\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name2 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      Flags flags;\n\t\t      ParseFlags (scan, flags);\n\t\t      int factor = int(flags.GetNumFlag(\"factor\",1)); \n\t\t      // cout << \"Singular Face with factor \" << factor << endl; \n\t\t      PrintMessageCR (3, \"Singular Face  with factor \", factor);\n\n\t\t      ParseChar (scan, ';');\n\t\t      \n\t\t      const Solid * sol = geom->GetSolid(name2);\n\n\t\t      if(!sol)\n\t\t\tscan.Error (\"unknown solid in singular face definition\");\n\t\t      else\n\t\t\tfor (int i = 0; i < geom->GetNTopLevelObjects(); i++)\n\t\t\t  if (name1 == geom->GetTopLevelObject (i)->GetSolid()->Name())\n\t\t\t    geom->singfaces.Append (new SingularFace (i+1, sol,factor));\n\n\t\t      break;\n\t\t    }\n\n\t\t  case TOK_EDGE:\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name1 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name2 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      Flags flags;\n\t\t      ParseFlags (scan, flags);\n\t\t      int factor = int(flags.GetNumFlag(\"factor\",1));\n\t\t      double maxhinit = flags.GetNumFlag(\"maxh\",-1);\n\t\t      ParseChar (scan, ';');\n\t\t      \n\t\t      const Solid * s1 = geom->GetSolid(name1);\n\t\t      const Solid * s2 = geom->GetSolid(name2);\n\t\t      PrintMessageCR (3, \"Singular Edge  with factor \", factor);\n\n\t\t      int domnr = -1;\n\t\t      if (flags.StringFlagDefined (\"tlo\"))\n\t\t\t{\n\t\t\t  const Solid * sol =\n\t\t\t    geom->GetSolid(flags.GetStringFlag (\"tlo\",\"\"));\n\t\t\t  \n\t\t\t  for (int i = 0; i < geom->GetNTopLevelObjects(); i++)\n\t\t\t    if (geom->GetTopLevelObject(i)->GetSolid() == sol)\n\t\t\t      domnr = i;\n\t\t\t  \n\t\t\t  // cout << \"domnr = \" << domnr;\n\t\t\t}\n\n\t\t      if(!s1 || !s2)\n\t\t\tscan.Error (\"unknown solid ins singular edge definition\");\n\t\t      else\n\t\t\tgeom->singedges.Append (new SingularEdge (1, domnr, \n\t\t\t\t\t\t\t\t  *geom, s1, s2, factor,\n\t\t\t\t\t\t\t\t  maxhinit));\n\t\t      break;\n\t\t    }\n\n\t\t  case TOK_POINT:\n\t\t    {\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      string name1 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      string name2 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      string name3 = scan.GetStringValue();\n\t\t      scan.ReadNext();\n\t\t      \n\t\t      Flags flags;\n\t\t      ParseFlags (scan, flags);\n\t\t      int factor = int(flags.GetNumFlag(\"factor\",1)); \n\t\t      ParseChar (scan, ';');\n\t\t      \n\t\t      const Solid * s1 = geom->GetSolid(name1);\n\t\t      const Solid * s2 = geom->GetSolid(name2);\n\t\t      const Solid * s3 = geom->GetSolid(name3);\n\t\t      // cout << \"Singular Point with factor \" << factor << endl; \n\t\t      PrintMessageCR (3, \"Singular Point  with factor \", factor);\n\t\t      geom->singpoints.Append (new SingularPoint (1, s1, s2, s3, factor));\n\t\t      break;\n\t\t    }\n\t\t  default:\n\t\t    scan.Error (\"keyword 'face' or 'edge' or 'point' expected\");\n\t\t  }\n\t      }\n\n\t    \n\t    else if (scan.GetToken() == TOK_POINT)\n\t      {\n\t\tPoint<3> p;\n\n\t\tscan.ReadNext();\n\t\tParseChar (scan, '(');\n\t\tp = Point<3> (ParseVector (scan));\n\t\tParseChar (scan, ')');\n\n\n\t\tFlags flags;\n\t\tParseFlags (scan, flags);\n\t\tint factor = int(flags.GetNumFlag(\"factor\",0)); \n\n\t\tParseChar (scan, ';');\n\n\t\tgeom->AddUserPoint (p, factor);\n\t      }\n\n\t    else if (scan.GetToken() == TOK_BOUNDINGBOX)\n\t      {\n\t\tPoint<3> p1, p2;\n\t\t\n\t\tscan.ReadNext();\n\t\tParseChar (scan, '(');\n\t\tp1 = Point<3> (ParseVector (scan));\n\t\tParseChar (scan, ';');\n\t\tp2 = Point<3> (ParseVector (scan));\n\t\tParseChar (scan, ')');\n\t\tParseChar (scan, ';');\n\n\t\tgeom->SetBoundingBox (Box<3> (p1, p2));\n\t      }\n\n\t    else if (scan.GetToken() == TOK_CURVE2D)\n\t      {\n\t\tscan.ReadNext();\n\n\t\t\n\t\tif (scan.GetToken() != TOK_STRING)\n\t\t  scan.Error (\"name identifier expected\");\n\t\tstring curvename = scan.GetStringValue();\n\n\t\tscan.ReadNext();\n\n\t\tParseChar (scan, '=');\n\t\tParseChar (scan, '(');\n\t\t\n\t\tauto newspline = make_shared<SplineGeometry<2>>();\n\t\t// newspline->CSGLoad(scan);\n\t\tLoadSpline (*newspline, scan);\n\n\t\tParseChar (scan, ')');\n\t\tParseChar (scan, ';');\n\n\t\tgeom->SetSplineCurve(curvename.c_str(),newspline);\n\n\t\tPrintMessage (4, \"define 2d curve \", curvename);\n\t      }\n\n\t    else if (scan.GetToken() == TOK_CURVE3D)\n\t      {\n\t\tscan.ReadNext();\n\n\t\t\n\t\tif (scan.GetToken() != TOK_STRING)\n\t\t  scan.Error (\"name identifier expected\");\n\t\tstring curvename = scan.GetStringValue();\n\n\t\tscan.ReadNext();\n\n\t\tParseChar (scan, '=');\n\t\tParseChar (scan, '(');\n\t\t\n\t\tauto newspline = make_shared<SplineGeometry<3>>();\n\t\t// newspline->CSGLoad(scan);\n\t\tLoadSpline (*newspline, scan);\n\n\t\tParseChar (scan, ')');\n\t\tParseChar (scan, ';');\n\n\t\tgeom->SetSplineCurve(curvename.c_str(),newspline);\n\n\t\tPrintMessage (4, \"define 3d curve \", curvename);\n\t      }\n\n\t    else if (scan.GetToken() == TOK_BOUNDARYCONDITION)\n\t      {\n\t\tscan.ReadNext();\n\t\t\n\t\tstring name1 = scan.GetStringValue();\n\t\tscan.ReadNext();\n\t\t\n\t\tstring name2 = scan.GetStringValue();\n\t\tscan.ReadNext();\n\t\t\n\t\tint num = int (ParseNumber (scan));\n\t\tParseChar (scan, ';');\n\n\n\t\tCSGeometry::BCModification bcm;\n\t\tbcm.bcname = NULL;\n\t\tNgArray<int> si;\n\t\t\n\t\tgeom->GetSolid(name1)->GetSurfaceIndices(si);\n\t\tif(si.Size() == 0)\n\t\t  {\n\t\t    string errstring = \"solid \\\"\"; errstring += name1; errstring += \"\\\" has no surfaces\";\n\t\t    scan.Error (errstring);\n\t\t  }\n\t\n\t\tbcm.tlonr = -1;\n\t\tint i;\t\n\t\tfor (i = 0; i < geom->GetNTopLevelObjects(); i++)\n\t\t  if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())\n\t\t      == name2)\n\t\t    {\n\t\t      bcm.tlonr = i;\n\t\t      break;\n\t\t    }\n\t\tif(bcm.tlonr == -1)\n\t\t  {\n\t\t    string errstring = \"tlo \\\"\"; errstring += name2; errstring += \"\\\" not found\";\n\t\t    scan.Error(errstring);\n\t\t  }\n\t\t\n\t\t\n\t\tbcm.bcnr = num;\n\t\tfor (i = 0; i < si.Size(); i++)\n\t\t  {\n\t\t    bcm.si = si[i];\n\t\t    geom->bcmodifications.Append (bcm);\n\t\t  }\n\t      }\n\t    \n\t    else if (scan.GetToken() == TOK_BOUNDARYCONDITIONNAME)\n\t      {\n\t\tscan.ReadNext();\n\t\t\n\t\tstring name1 = scan.GetStringValue();\n\t\tscan.ReadNext();\n\t\t\n\t\tstring name2 = scan.GetStringValue();\n\t\tscan.ReadNext();\n\n\t\tstring bcname = scan.GetStringValue();\n\t\tscan.ReadNext();\n\t\tParseChar(scan, ';');\n\t\t\n\n\t\tCSGeometry::BCModification bcm;\n\t\tbcm.bcname = NULL;\n\n\n\t\tNgArray<int> si;\n\t\t\n\t\tgeom->GetSolid(name1)->GetSurfaceIndices(si);\n\t\tif(si.Size() == 0)\n\t\t  {\n\t\t    string errstring = \"solid \\\"\"; errstring += name1; errstring += \"\\\" has no surfaces\";\n\t\t    scan.Error (errstring);\n\t\t  }\n\t\n\t\tbcm.tlonr = -1;\n\t\tint i;\t\n\t\tfor (i = 0; i < geom->GetNTopLevelObjects(); i++)\n\t\t  if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())\n\t\t      == name2)\n\t\t    {\n\t\t      bcm.tlonr = i;\n\t\t      break;\n\t\t    }\n\t\tif(bcm.tlonr == -1)\n\t\t  {\n\t\t    string errstring = \"tlo \\\"\"; errstring += name2; errstring += \"\\\" not found\";\n\t\t    scan.Error(errstring);\n\t\t  }\n\t\t\n\t\t\n\t\tbcm.bcnr = -1;\n\t\tfor (i = 0; i < si.Size(); i++)\n\t\t  {\n\t\t    bcm.si = si[i];\n\t\t    geom->bcmodifications.Append (bcm);\n\t\t    geom->bcmodifications.Last().bcname = new string(bcname);\n\t\t  }\n\t      }\n\t    \n\t    else if (scan.GetToken() == TOK_DEFINE)\n\t      {\n\t\tscan.ReadNext();\n\t\tstring name;\n\t\tdouble val;\n\t\t\n\t\tswitch (scan.GetToken())\n\t\t  {\n\t\t  case TOK_CONSTANT:\n\t\t    scan.ReadNext();\n\t\t      \n\t\t    name = scan.GetStringValue();\n\t\t    scan.ReadNext();\n\n\t\t    ParseChar(scan, '=');\n\t\t    val = ParseNumber(scan);\n\n\t\t    if(name == \"identprec\")\n\t\t      geom->SetIdEps(val);\n\t\t    \n\t\t    \n\n\t\t    break;\n\t\t  default:\n\t\t    scan.Error (\"keyword 'constant' expected\");\n\t\t  }\n\t      }\n\n\n\t    else\n\t      {\n\t\tcout << \"read unidentified token \" << scan.GetToken() \n\t\t     << \" (as char: \\\"\" << char(scan.GetToken()) << \"\\\")\"\n\t\t     << \" string = \" << scan.GetStringValue() << endl;\n\t\tscan.ReadNext();\n\t      }\n\t  }\n      }\n    catch (string errstr)\n      {\n\tcout << \"caught error \" << errstr << endl;\n\tthrow NgException (errstr);\n      }\n\n\n\n    (*testout) << geom->GetNTopLevelObjects() << \" TLOs:\" << endl;\n    for (int i = 0; i < geom->GetNTopLevelObjects(); i++)\n      {\n\tconst TopLevelObject * tlo = geom->GetTopLevelObject(i);\n\tif (tlo->GetSolid())\n\t  (*testout) << i << \": \" << *tlo->GetSolid() << endl;\n      }\n\n    (*testout) << geom->GetNSurf() << \" Surfaces\" << endl;\n    for (int i = 0; i < geom->GetNSurf(); i++)\n      (*testout) << i << \": \" << *geom->GetSurface(i) << endl;\n\n    return geom;\n    /*\n      do\n      {\n      scan.ReadNext();\n      if (scan.GetToken() == TOK_STRING)\n      cout << \"found string \" << scan.GetStringValue() << endl;\n      else\n      cout << \"token = \" << int(scan.GetToken()) << endl;\n      }\n      while (scan.GetToken() != TOK_END);\n    */\n  }\n\n\n};\n\n"
  },
  {
    "path": "libsrc/csg/csgparser.hpp",
    "content": "#ifndef _CSGPARSER_HPP\n#define _CSGPARSER_HPP\n\n\nnamespace netgen\n{\n\n  enum TOKEN_TYPE\n    { \n      TOK_MINUS = '-', TOK_LP = '(', OK_RP = ')', TOK_LSP = '[', TOK_RSP = ']',\n      TOK_EQU = '=', TOK_COMMA = ',', TOK_SEMICOLON = ';',\n      TOK_NUM = 100, TOK_STRING, TOK_NAMED_SOLID, TOK_PRIMITIVE, \n      TOK_OR, TOK_AND, TOK_NOT, \n      TOK_SINGULAR, TOK_EDGE, TOK_POINT, TOK_FACE, TOK_IDENTIFY, TOK_CLOSESURFACES,\n      TOK_CLOSEEDGES, TOK_PERIODIC,\n      TOK_SOLID, TOK_RECO, TOK_TLO, TOK_CURVE2D, TOK_CURVE3D, TOK_BOUNDINGBOX,\n      TOK_BOUNDARYCONDITION, TOK_BOUNDARYCONDITIONNAME,\n      TOK_DEFINE, TOK_CONSTANT,\n      TOK_END };\n\n  struct kwstruct\n  {\n    TOKEN_TYPE kw; \n    const char * name;\n  };\n\n  enum PRIMITIVE_TYPE\n    {\n      TOK_SPHERE = 1, TOK_CYLINDER, TOK_PLANE, TOK_ELLIPTICCYLINDER, \n      TOK_ELLIPSOID, TOK_CONE, TOK_ELLIPTICCONE,\n      TOK_ORTHOBRICK, TOK_POLYHEDRON, \n      TOK_TORUS,\n      TOK_TUBE, TOK_GENCYL, TOK_EXTRUSION, TOK_REVOLUTION,\n\n      TOK_TRANSLATE, TOK_MULTITRANSLATE, TOK_ROTATE, TOK_MULTIROTATE\n    };\n\n  struct primstruct\n  {\n    PRIMITIVE_TYPE kw; \n    const char * name;\n  };\n\n\n  class CSGScanner\n  {\n    TOKEN_TYPE token;\n    PRIMITIVE_TYPE prim_token;\n    double num_value;\n    string string_value;\n    \n    int linenum;\n    istream * scanin;\n\n  public:\n\n    CSGScanner (istream & ascanin);\n\n    TOKEN_TYPE GetToken() const\n    { return token; }\n\n    double GetNumValue() const\n    { return num_value; }\n\n    const string & GetStringValue() const\n    { return string_value; }\n\n    char GetCharValue() const\n    { return string_value[0]; }\n\n    PRIMITIVE_TYPE GetPrimitiveToken() const\n    { return prim_token; }\n  \n    void ReadNext();\n\n    /*\n    CSGScanner & Parse (char ch);\n    CSGScanner & Parse (int & i);\n    CSGScanner & Parse (double & d);\n    CSGScanner & Parse (Point<3> & p);\n    CSGScanner & Parse (Vec<3> & p);\n    */\n    void Error (const string & err);\n  };\n\n\n  \n  CSGScanner & operator>> (CSGScanner & scan, char ch);\n  CSGScanner & operator>> (CSGScanner & scan, double & d);\n  CSGScanner & operator>> (CSGScanner & scan, int & i);\n  CSGScanner & operator>> (CSGScanner & scan, Point<3> & p);\n  CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v);\n  \n\n\n}\n\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/csg/csgpkg.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\n#include <inctcl.hpp>\n#include <visual.hpp>\n\n\n#include \"vscsg.hpp\"\n\n\nextern \"C\" int Ng_CSG_Init (Tcl_Interp * interp);\n\n\n\nnamespace netgen\n{\n  extern DLL_HEADER shared_ptr<NetgenGeometry> ng_geometry;\n  extern DLL_HEADER shared_ptr<Mesh> mesh;\n\n  static VisualSceneGeometry vsgeom;\n \n  char * err_needscsgeometry = (char*) \"This operation needs an CSG geometry\";\n  char * err_needsmesh = (char*) \"This operation needs a mesh\";\n  char * err_jobrunning = (char*) \"Meshing Job already running\";\n\n \n\n\n  int Ng_ParseGeometry (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    CSGeometry * csgeom = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (csgeom)\n      {\n\tdouble detail = atof (Tcl_GetVar (interp, \"::geooptions.detail\", 0));\n\tdouble facets = atof (Tcl_GetVar (interp, \"::geooptions.facets\", 0));\n      \n\tif (atoi (Tcl_GetVar (interp, \"::geooptions.drawcsg\", 0)))\n\t  csgeom->CalcTriangleApproximation(detail, facets);\n      }\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_GeometryOptions (ClientData clientData,\n\t\t\t  Tcl_Interp * interp,\n\t\t\t  int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n\n\n    const char * command = argv[1];\n\n    if (strcmp (command, \"get\") == 0)\n      {\n\tif (geometry)\n\t  {\n\t    char buf[20];\n\t    Point3d pmin = geometry->BoundingBox ().PMin();\n\t    Point3d pmax = geometry->BoundingBox ().PMax();\n\t    \n\t    snprintf (buf, size(buf), \"%5.1lf\", pmin.X());\n\t    Tcl_SetVar (interp, \"::geooptions.minx\", buf, 0);\n\t    snprintf (buf, size(buf), \"%5.1lf\", pmin.Y());\n\t    Tcl_SetVar (interp, \"::geooptions.miny\", buf, 0);\n\t    snprintf (buf, size(buf), \"%5.1lf\", pmin.Z());\n\t    Tcl_SetVar (interp, \"::geooptions.minz\", buf, 0);\n\t    \n\t    snprintf (buf, size(buf), \"%5.1lf\", pmax.X());\n\t    Tcl_SetVar (interp, \"::geooptions.maxx\", buf, 0);\n\t    snprintf (buf, size(buf), \"%5.1lf\", pmax.Y());\n\t    Tcl_SetVar (interp, \"::geooptions.maxy\", buf, 0);\n\t    snprintf (buf, size(buf), \"%5.1lf\", pmax.Z());\n\t    Tcl_SetVar (interp, \"::geooptions.maxz\", buf, 0);\n\t  }\n      }\n    else if (strcmp (command, \"set\") == 0)\n      {\n        Point<3> pmin (atof (Tcl_GetVar (interp, \"::geooptions.minx\", 0)),\n                       atof (Tcl_GetVar (interp, \"::geooptions.miny\", 0)),\n                       atof (Tcl_GetVar (interp, \"::geooptions.minz\", 0)));\n        Point<3> pmax (atof (Tcl_GetVar (interp, \"::geooptions.maxx\", 0)),\n                       atof (Tcl_GetVar (interp, \"::geooptions.maxy\", 0)),\n                       atof (Tcl_GetVar (interp, \"::geooptions.maxz\", 0)));\n\tBox<3> box (pmin, pmax);\n\tif (geometry)\n\t  geometry -> SetBoundingBox (box);\n\tCSGeometry::SetDefaultBoundingBox (box);\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n\n  // attempt of a simple modeller\n\n  int Ng_CreatePrimitive (ClientData clientData,\n\t\t\t  Tcl_Interp * interp,\n\t\t\t  int argc, tcl_const char *argv[])\n  {/*\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * classname = argv[1];\n    tcl_const char * name = argv[2];\n\n    cout << \"Create primitive, class = \" << classname\n\t << \", name = \" << name << endl;\n\n    Primitive * nprim = Primitive::CreatePrimitive (classname);\n    Solid * nsol = new Solid (nprim);\n\n    char sname[100];\n    for (int j = 1; j <= nprim->GetNSurfaces(); j++)\n      {\n\tsprintf (sname, \"%s,%d\", name, j);\n\tgeometry -> AddSurface (sname, &nprim->GetSurface(j));\n\tnprim -> SetSurfaceId (j, geometry->GetNSurf());\n      }\n\n    geometry->SetSolid (name, nsol);\n\t*/\n    return TCL_OK;\n  }\n\n\n  int Ng_SetPrimitiveData (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * name = argv[1];\n    tcl_const char * value = argv[2];\n\n    NgArray<double> coeffs;\n\n\n    cout << \"Set primitive data, name = \" << name\n\t << \", value = \" << value  << endl;\n\n\n    istringstream vst (value);\n    double val;\n    while (!vst.eof())\n      {\n\tvst >> val;\n\tcoeffs.Append (val);\n      }\n\n    ((Primitive*)\n     geometry->GetSolid (name)->GetPrimitive())->SetPrimitiveData (coeffs);\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_SetSolidData (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {/*\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * name = argv[1];\n    tcl_const char * val = argv[2];\n\n    cout << \"Set Solid Data, name = \" << name\n\t << \", value = \" << val << endl;\n\n    istringstream vst (val);\n\n    Solid * nsol = Solid::CreateSolid (vst, geometry->GetSolids());\n    geometry->SetSolid (name, nsol);\n\t*/\n    return TCL_OK;\n  }\n\n\n  int Ng_GetPrimitiveData (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * name = argv[1];\n    tcl_const char * classnamevar = argv[2];\n    tcl_const char * valuevar = argv[3];\n\n    const char * classname;\n\n    NgArray<double> coeffs;\n\n    geometry->GetSolid (name)->GetPrimitive()->GetPrimitiveData (classname, coeffs);\n\n    ostringstream vst;\n    for (int i = 1; i <= coeffs.Size(); i++)\n      vst << coeffs.Get(i) << \" \";\n\n    cout << \"GetPrimitiveData, name = \" << name\n\t << \", classnamevar = \" << classnamevar\n\t << \", classname = \" << classname << endl\n\t << \" valuevar = \" << valuevar\n\t << \", values = \" << vst.str() << endl;\n\n    Tcl_SetVar  (interp, classnamevar, (char*)classname, 0);\n    Tcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n\n    return TCL_OK;\n  }\n\n  int Ng_GetSolidData (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {/*\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    tcl_const char * name = argv[1];\n    tcl_const char * valuevar = argv[2];\n\n    ostringstream vst;\n\n    const Solid * sol = geometry->GetSolid (name);\n    sol->GetSolidData (vst);\n\n    cout << \"GetSolidData, name = \" << name << \", data = \" << vst.str() << endl;\n\n    Tcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n\t*/\n    return TCL_OK;\n  }\n\n\n  int Ng_GetPrimitiveList (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * valuevar = argv[1];\n    int i;\n\n    stringstream vst;\n\n    for (i = 1; i <= geometry->GetNSolids(); i++)\n      {\n\tconst Solid * sol = geometry->GetSolid(i);\n\tif (sol->GetPrimitive())\n\t  vst << sol->Name() << \" \";\n      }\n\n    cout << \"primnames = \" << vst.str() << endl;\n\n    Tcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_GetSurfaceList (ClientData clientData,\n\t\t\t Tcl_Interp * interp,\n\t\t\t int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    tcl_const char * valuevar = argv[1];\n    int i;\n\n    stringstream vst;\n\n    for (i = 1; i <= geometry->GetNSurf(); i++)\n      {\n\tconst Surface * surf = geometry->GetSurface(i);\n\tvst << surf->Name() << \" \";\n      }\n\n    cout << \"surfnames = \" << vst.str() << endl;\n\n    Tcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_GetSolidList (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    tcl_const char * valuevar = argv[1];\n    int i;\n\n    stringstream vst;\n\n    for (i = 1; i <= geometry->GetNSolids(); i++)\n      {\n\tconst Solid * sol = geometry->GetSolid(i);\n\tif (!sol->GetPrimitive())\n\t  vst << sol->Name() << \" \";\n      }\n\n    cout << \"solnames = \" << vst.str() << endl;\n\n    Tcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_TopLevel (ClientData clientData,\n\t\t   Tcl_Interp * interp,\n\t\t   int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    int i;\n    /*\n      for (i = 0; i < argc; i++)\n      cout << argv[i] << \", \";\n      cout << endl;\n    */\n\n    if (strcmp (argv[1], \"getlist\") == 0)\n      {\n\tstringstream vst;\n\n\tfor (i = 0; i < geometry->GetNTopLevelObjects(); i++)\n\t  {\n\t    const Solid * sol;\n\t    const Surface * surf;\n\t    geometry->GetTopLevelObject (i, sol, surf);\n\n\t    if (!surf)\n\t      vst << \"{ \" << sol->Name() << \" } \";\n\t    else\n\t      vst << \"{ \" << sol->Name() << \" \" << surf->Name() << \" } \";\n\t  }\n\n\ttcl_const char * valuevar = argv[2];\n\tTcl_SetVar  (interp, valuevar, (char*)vst.str().c_str(), 0);\n      }\n\n    if (strcmp (argv[1], \"set\") == 0)\n      {\n\ttcl_const char * solname = argv[2];\n\ttcl_const char * surfname = argv[3];\n\tSolid * sol = (Solid*)geometry->GetSolid (solname);\n\tSurface * surf = (Surface*)geometry->GetSurface (surfname);\n\tgeometry->SetTopLevelObject (sol, surf);\n      }\n\n    if (strcmp (argv[1], \"remove\") == 0)\n      {\n\ttcl_const char * solname = argv[2];\n\ttcl_const char * surfname = argv[3];\n\tSolid * sol = (Solid*)geometry->GetSolid (solname);\n\tSurface * surf = (Surface*)geometry->GetSurface (surfname);\n\tgeometry->RemoveTopLevelObject (sol, surf);\n      }\n\n    if (strcmp (argv[1], \"setprop\") == 0)\n      {\n\ttcl_const char * solname = argv[2];\n\ttcl_const char * surfname = argv[3];\n\ttcl_const char * propvar = argv[4];\n\tSolid * sol = (Solid*)geometry->GetSolid (solname);\n\tSurface * surf = (Surface*)geometry->GetSurface (surfname);\n\tTopLevelObject * tlo = geometry->GetTopLevelObject (sol, surf);\n\n\tif (!tlo) return TCL_OK;\n\n\tchar varname[50];\n\tsnprintf (varname, size(varname), \"%s(red)\", propvar);\n\tdouble red = atof (Tcl_GetVar (interp, varname, 0));\n\tsnprintf (varname, size(varname), \"%s(blue)\", propvar);\n\tdouble blue = atof (Tcl_GetVar (interp, varname, 0));\n\tsnprintf (varname, size(varname), \"%s(green)\", propvar);\n\tdouble green = atof (Tcl_GetVar (interp, varname, 0));\n\ttlo -> SetRGB (red, green, blue);\n\n\tsnprintf (varname, size(varname), \"%s(visible)\", propvar);\n\ttlo -> SetVisible (bool(atoi (Tcl_GetVar (interp, varname, 0))));\n\tsnprintf (varname, size(varname), \"%s(transp)\", propvar);\n\ttlo -> SetTransparent (bool(atoi (Tcl_GetVar (interp, varname, 0))));\n      }\n\n    if (strcmp (argv[1], \"getprop\") == 0)\n      {\n\ttcl_const char * solname = argv[2];\n\ttcl_const char * surfname = argv[3];\n\ttcl_const char * propvar = argv[4];\n\n\tSolid * sol = (Solid*)geometry->GetSolid (solname);\n\tSurface * surf = (Surface*)geometry->GetSurface (surfname);\n\tTopLevelObject * tlo = geometry->GetTopLevelObject (sol, surf);\n\n\tif (!tlo) return TCL_OK;\n\n\tchar varname[50], varval[10];\n\n\tsnprintf (varname, size(varname), \"%s(red)\", propvar);\n\tsnprintf (varval, size(varval), \"%lf\", tlo->GetRed());\n\tTcl_SetVar (interp, varname, varval, 0);\n\n\tsnprintf (varname, size(varname), \"%s(green)\", propvar);\n\tsnprintf (varval, size(varval), \"%lf\", tlo->GetGreen());\n\tTcl_SetVar (interp, varname, varval, 0);\n\n\tsnprintf (varname, size(varname), \"%s(blue)\", propvar);\n\tsnprintf (varval, size(varval), \"%lf\", tlo->GetBlue());\n\tTcl_SetVar (interp, varname, varval, 0);\n\n\tsnprintf (varname, size(varname), \"%s(visible)\", propvar);\n\tsnprintf (varval, size(varval), \"%d\", tlo->GetVisible());\n\tTcl_SetVar (interp, varname, varval, 0);\n\n\tsnprintf (varname, size(varname), \"%s(transp)\", propvar);\n\tsnprintf (varval, size(varval), \"%d\", tlo->GetTransparent());\n\tTcl_SetVar (interp, varname, varval, 0);\n      }\n\n\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_SingularEdgeMS (ClientData clientData,\n\t\t\t Tcl_Interp * interp,\n\t\t\t int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    // double globh = mparam.maxh;\n    for (int i = 1; i <= geometry->singedges.Size(); i++)\n      geometry->singedges.Get(i)->SetMeshSize (*mesh, 1e99 /* globh*/);\n    return TCL_OK;\n  }\n\n\n  int Ng_SingularPointMS (ClientData clientData,\n\t\t\t  Tcl_Interp * interp,\n\t\t\t  int argc, tcl_const char *argv[])\n  {\n    CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    if (!geometry)\n      {\n\tTcl_SetResult (interp, err_needscsgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    // double globh = mparam.maxh;\n    for (int i = 1; i <= geometry->singpoints.Size(); i++)\n      geometry->singpoints.Get(i)->SetMeshSize (*mesh, 1e99 /* globh */ );\n    return TCL_OK;\n  }\n\n\n\n  int Ng_SelectSurface (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    int surfnr = atoi (argv[1]);\n    vsgeom.SelectSurface (surfnr);\n    return TCL_OK;\n  }\n\n\n  class CSGeometryVisRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const { return NULL; }\n    virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;\n  };\n\n  VisualScene * CSGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const\n  {\n    const CSGeometry * geometry = dynamic_cast<const CSGeometry*> (geom);\n    if (geometry)\n      {\n\tvsgeom.SetGeometry (const_cast<CSGeometry*>(geometry));\n\treturn &vsgeom;\n      }\n    return NULL;\n  }\n}\n\n\nusing namespace netgen;\n\nint Ng_CSG_Init (Tcl_Interp * interp)\n{\n  GeometryRegister().Append(new CSGeometryVisRegister);\n  if (interp == NULL) return TCL_OK;\n  \n\n  Tcl_CreateCommand (interp, \"Ng_ParseGeometry\", Ng_ParseGeometry,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  // geometry\n  Tcl_CreateCommand (interp, \"Ng_CreatePrimitive\", Ng_CreatePrimitive,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_SetPrimitiveData\", Ng_SetPrimitiveData,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_GetPrimitiveData\", Ng_GetPrimitiveData,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_GetPrimitiveList\", Ng_GetPrimitiveList,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n\n  Tcl_CreateCommand (interp, \"Ng_GetSurfaceList\", Ng_GetSurfaceList,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n\n\n  Tcl_CreateCommand (interp, \"Ng_SetSolidData\", Ng_SetSolidData,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_GetSolidData\", Ng_GetSolidData,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_GetSolidList\", Ng_GetSolidList,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n\n  Tcl_CreateCommand (interp, \"Ng_TopLevel\", Ng_TopLevel,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_GeometryOptions\", Ng_GeometryOptions,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_SingularEdgeMS\", Ng_SingularEdgeMS,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n  \n  Tcl_CreateCommand (interp, \"Ng_SingularPointMS\", Ng_SingularPointMS,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SelectSurface\", Ng_SelectSurface,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n  return TCL_OK;\n}\n\n\n\n"
  },
  {
    "path": "libsrc/csg/curve2d.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <csg.hpp>\n\nnamespace netgen\n{\nCircleCurve2d :: CircleCurve2d (const Point<2> & acenter, double arad)\n  {\n  center = acenter;\n  rad = arad;\n  }\n  \nvoid CircleCurve2d :: Project (Point<2> & p) const\n  {\n  Vec<2> v = p - center;\n  v *= rad/v.Length();\n  p = center + v;\n  }\n\nvoid CircleCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const\n  {\n  n = p - center;\n  n /= n.Length();\n  }\n\n\n\n\n\n\nQuadraticCurve2d ::  QuadraticCurve2d ()\n{\n  cxx = cyy = cxy = cx = cy = c = 0;\n}\n\nvoid QuadraticCurve2d :: Read (istream & ist)\n{\n  ist >> cxx >> cyy >> cxy >> cx >> cy >> c;\n}\n\n\nvoid QuadraticCurve2d :: Project (Point<2> & p) const\n{\n  double f, x, y, gradx, grady, grad2;\n  int its = 0;\n\n  x = p(0);\n  y = p(1);\n\n  do\n    {\n      f = cxx * x * x + cyy * y * y + cxy * x * y + cx * x + cy * y + c;\n      gradx = 2 * cxx * x + cxy * y + cx;\n      grady = 2 * cyy * y + cxy * x + cy;\n      grad2 = gradx * gradx + grady * grady;\n      \n      x -= f * gradx / grad2;\n      y -= f * grady / grad2;\n\n      //      (*mycout) << \"x = \" << x << \" y = \" << y << \" f = \" << f << endl;\n      its++;\n    }\n  while (fabs (f) > 1e-8 && its < 20);\n  if (its >= 20)\n    cerr << \"QuadraticCurve2d::Project:  many iterations, f = \" << f << endl;\n  p(0) = x;\n  p(1) = y;\n}\n\n\nvoid QuadraticCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const\n{\n  n(0) = 2 * cxx * p(0) + cxy * p(1) + cx;\n  n(1) = 2 * cyy * p(1) + cxy * p(0) + cy;\n  n.Normalize();\n}\n}\n"
  },
  {
    "path": "libsrc/csg/curve2d.hpp",
    "content": "#ifndef FILE_CURVE2D\n#define FILE_CURVE2D\n\n/**************************************************************************/\n/* File:   curve2d.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   24. Jul. 96                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n  /*\n\n  2D Curve representation\n\n  */\n\n\n\n  ///\n  class Curve2d : public Manifold\n  {\n  public:\n    ///\n    virtual void Project (Point<2> & p) const = 0;\n    ///\n    virtual void NormalVector (const Point<2> & p, Vec<2> & n) const = 0;\n  };\n  \n  ///\n  class CircleCurve2d : public Curve2d\n  {\n    ///\n    Point<2> center;\n    ///\n    double rad;\n  public:\n    ///\n    CircleCurve2d (const Point<2> & acenter, double arad);\n    ///\n    virtual void Project (Point<2> & p) const;\n    ///\n    virtual void NormalVector (const Point<2> & p, Vec<2> & n) const;\n  };\n  \n  ///\n  class QuadraticCurve2d : public Curve2d\n  {\n    ///\n    double cxx, cyy, cxy, cx, cy, c;\n  public:\n    ///\n    QuadraticCurve2d ();\n    ///\n    void Read (istream & ist);\n    ///\n    virtual void Project (Point<2> & p) const;\n    ///\n    virtual void NormalVector (const Point<2> & p, Vec<2> & n) const;\n  };\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/edgeflw.cpp",
    "content": "#include <mystdlib.h>\n#include <meshing.hpp>\n#include <csg.hpp>\n\n// #undef DEVELOP\n// #define DEVELOP\n\nnamespace netgen\n{\n\n  EdgeCalculation :: \n  EdgeCalculation (const CSGeometry & ageometry,\n\t\t   NgArray<SpecialPoint> & aspecpoints,\n                   MeshingParameters & amparam)\n    : geometry(ageometry), specpoints(aspecpoints), mparam(amparam)\n  {\n    Box<3> bbox = geometry.BoundingBox();\n\n    searchtree = new Point3dTree (bbox.PMin(), bbox.PMax());\n    meshpoint_tree = new Point3dTree (bbox.PMin(), bbox.PMax());\n\n    for (int i = 0; i < specpoints.Size(); i++)\n      searchtree->Insert (specpoints[i].p, i);\n\n    ideps = 1e-9;\n  }\n\n  EdgeCalculation :: ~EdgeCalculation()\n  {\n    delete searchtree;\n    delete meshpoint_tree;\n  }\n\n\n  void EdgeCalculation :: Calc(double h, Mesh & mesh)\n  {\n    static int timer = NgProfiler::CreateTimer (\"CSG: mesh edges\");\n    NgProfiler::RegionTimer reg (timer);\n\n\n    PrintMessage (1, \"Find edges\");\n    PushStatus (\"Find edges\");\n\n    for (PointIndex pi : mesh.Points().Range())    \n      meshpoint_tree->Insert (mesh[pi], pi);\n\n\n    // add all special points before edge points (important for periodic identification)\n    // JS, Jan 2007\n    const double di=1e-7*geometry.MaxSize();\n    NgArray<int> locsearch;\n\n    for (int i = 0; i < specpoints.Size(); i++)\n      if (specpoints[i].unconditional)\n\t{\n\t  Point<3> p = specpoints[i].p;\n          meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di),\n                                             p+Vec<3> (di,di,di), locsearch);\n          \n\t  if (locsearch.Size() == 0)\n            {\n              PointIndex pi = mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT);\n              meshpoint_tree -> Insert (p, pi); \n            }\n        }\n           \n\n    /*\n      // slow version\n    for (int i = 0; i < specpoints.Size(); i++)\n      if (specpoints[i].unconditional)\n\t{\n\t  Point<3> p = specpoints[i].p;\n\t  bool found = false;\n\t  for (int j = 1; j <= mesh.GetNP(); j++)\n\t    if (Dist (p, mesh.Point(j)) < 1e-8)\n\t      found = true;\n\t  if (!found)\n\t    mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT);\n\t}\n    */\n\n\n\n    CalcEdges1 (h, mesh);\n    SplitEqualOneSegEdges (mesh);\n    FindClosedSurfaces (h, mesh);\n    PrintMessage (3, cntedge, \" edges found\");\n\n    PopStatus ();\n  }\n\n\n\n\n\n  void EdgeCalculation :: CalcEdges1 (double h, Mesh & mesh)\n  {\n    NgArray<int> hsp(specpoints.Size());\n    NgArray<int> glob2hsp(specpoints.Size());\n    NgArray<int> startpoints, endpoints;\n\n\n    int pos, ep;\n    int layer;\n\n    Point<3> p, np; \n    int pi1, s1, s2, s1_orig, s2_orig;\n\n    NgArray<Point<3> > edgepoints;\n    NgArray<double> curvelength;\n    int copyedge = 0, copyfromedge = -1, copyedgeidentification = -1;\n\n    NgArray<int> locsurfind, locind;\n\n    int checkedcopy = 0;\n\n    // double size = geometry.MaxSize(); \n    // double epspointdist2 = sqr (size) * 1e-12;\n    \n\n    // copy special points to work with\n    for (int i = 0; i < specpoints.Size(); i++)\n      {\n\thsp[i] = i;\n\tglob2hsp[i] = i;\n      }\n\n    //for(int i=0; i<hsp.Size(); i++)\n    //  (*testout) << \"hsp[\"<<i<<\"] ... \" << specpoints[hsp[i]].p << endl;\n     \n\n    cntedge = 0;\n    INDEX_2_HASHTABLE<int> identification_used(100);  // identification i already used for startpoint j\n\n    mesh.GetIdentifications().Delete();\n    \n    TABLE<int> specpoint2surface(specpoints.Size());\n    if (geometry.identifications.Size())\n      {\n\tfor (int i = 0; i < specpoints.Size(); i++)\n\t  for (int j = 0; j < geometry.GetNSurf(); j++)\n\t    if (geometry.GetSurface(j)->PointOnSurface (specpoints[i].p))\n\t      specpoint2surface.Add (i, j);\n      }\n\n    TABLE<int> specpoint2tlo(specpoints.Size());\n    if (geometry.identifications.Size())\n      {\n\tfor (int i = 0; i < specpoints.Size(); i++)\n\t  for (int j = 0; j < geometry.GetNTopLevelObjects(); j++)\n\t    {\n\t      const TopLevelObject * tlo = geometry.GetTopLevelObject (j);\n\t      if (tlo->GetSolid() && tlo->GetSolid()->VectorIn (specpoints[i].p,specpoints[i].v))\n\t\t//if (tlo->GetSolid() && tlo->GetSolid()->IsIn (specpoints[i].p))\n\t\t{\n#ifdef DEVELOP\n\t\t  (*testout) << \"point \" << specpoints[i].p << \" v \" <<specpoints[i].v <<\" is in \" << tlo->GetSolid()->Name() << endl;\n#endif\n\t\t  specpoint2tlo.Add (i, j);\n\t\t}\n\t    }\n      }\n\n    for (int i = 0; i < specpoints.Size(); i++)\n      specpoints[i].nr = i;\n\n    while (hsp.Size())\n      {\n\tSetThreadPercent(100 - 100 * double (hsp.Size()) / specpoints.Size());\n\n#ifdef DEVELOP\n\t(*testout) << \"hsp.Size() \" << hsp.Size() << \" specpoints.Size() \" << specpoints.Size() << endl;\n\t(*testout) << endl << \"edge nr \" << cntedge+1 << endl;\n#endif\n\n\tedgepoints.SetSize (0);\n\tcurvelength.SetSize (0);\n      \n\n\tpi1 = 0;\n\tcopyedge = 0;\n\t// identifiable point available ?\n\n\t\n\tfor (int i = 0; i < geometry.identifications.Size() && !pi1; i++)\n\t  for (int j = checkedcopy; j < startpoints.Size() && !pi1; j++)\n\t    {\n#ifdef DEVELOP\n\t      (*testout) << \"checking point \" << specpoints[startpoints[j]].p\n\t\t\t << \", v = \" << specpoints[startpoints[j]].v \n\t\t\t << \" for copying (i,j = \" << i << \", \" << j << \")\" << endl;\t  \n#endif\n \t      if (geometry.identifications[i]->IdentifiableCandidate (specpoints[startpoints[j]]) &&\n\t\t  geometry.identifications[i]->IdentifiableCandidate (specpoints[endpoints[j]]))\n\t\t  \n\t      \n\t\t{\n\t\t  int pi1cand = 0;\n\t\t  double mindist = 1e10;\n\t\t\n\t\t  for (int k = 0; k < hsp.Size() && !pi1; k++)\n\t\t    {\n\t\t      //(*testout) << \"   ? identifiable with \" << specpoints[hsp[k]].p \n\t\t      //<< \", v = \" << specpoints[hsp[k]].v\n\t\t      //\t\t << endl;\n\t\t      if (identification_used.Used (INDEX_2(i, startpoints[j])) ||\n\t\t\t  identification_used.Used (INDEX_2(i, hsp[k])))\n\t\t\t{\n\t\t\t  //(*testout) << \"failed at pos0\" << endl;\n\t\t\t  continue;\n\t\t\t}\n\t\t      \n\t\t      if (geometry.identifications[i]\n\t\t\t  ->Identifiable(specpoints[startpoints[j]], specpoints[hsp[k]], specpoint2tlo, specpoint2surface) ||\n\t\t\t  geometry.identifications[i]\n\t\t\t  ->Identifiable(specpoints[hsp[k]], specpoints[startpoints[j]], specpoint2tlo, specpoint2surface))\n\t\t\t{\n#ifdef DEVELOP\n\t\t\t  (*testout) << \"identifiable: \" << specpoints[hsp[k]].p << \", v = \" << specpoints[hsp[k]].v\n\t\t\t\t     << \" and \" << specpoints[startpoints[j]].p << \", v = \" << specpoints[startpoints[j]].v \n\t\t\t\t     << \" (identification \" << i+1 << \")\" << endl;\n#endif\n\n\t\t\t  if (Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p) < mindist)\n\t\t\t    {\n\t\t\t      mindist = Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p);\n\t\t\t      pi1cand = k+1;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\n\t\n\t\t  if (pi1cand)\n\t\t    {\n\t\t      pi1 = pi1cand;\n\t\t      copyedge = 1;\n\t\t      copyfromedge = j+1;\n\t\t      copyedgeidentification = i+1;\n\t\t    \n\t\t      identification_used.Set (INDEX_2(i, startpoints[j]), 1);\n\t\t      identification_used.Set (INDEX_2(i, hsp.Get(pi1)), 1);\n\t\t    }\n\t\t}\n\t    }\n\t\n      \n\t// cannot copy from other edge ?\n\tif (!pi1)\n\t  checkedcopy = startpoints.Size();\n      \n\t// unconditional special point available ?\n\tif (!pi1)\n\t  for (int i = 1; i <= hsp.Size(); i++)\n\t    if (specpoints[hsp.Get(i)].unconditional == 1)\n\t      {\n\t\tpi1 = i;\n\t\tbreak;\n\t      }\n \n     \n\tif (!pi1)\n\t  {\n\t    // no unconditional points available, choose first conitional\n\t    pi1 = 1;\t     \n\t  }\n\n\tlayer = specpoints[hsp.Get(pi1)].GetLayer();\n      \n\n\tif (!specpoints[hsp.Get(pi1)].unconditional)\n\t  {\n\t    specpoints[hsp.Elem(pi1)].unconditional = 1;\n\t    for (int i = 1; i <= hsp.Size(); i++)\n\t      if (i != pi1 && \n\t\t  Dist (specpoints[hsp.Get(pi1)].p, specpoints[hsp.Get(i)].p) < 1e-8*geometry.MaxSize() &&\n\t\t  (specpoints[hsp.Get(pi1)].v + specpoints[hsp.Get(i)].v).Length() < 1e-4)\n\t\t{\n\t\t  // opposite direction\n\t\t  specpoints[hsp.Elem(i)].unconditional = 1;\n\t\t}\n\t  }\n\n\tcntedge++;\n\tstartpoints.Append (hsp.Get(pi1));\n\n#ifdef DEVELOP\n\t(*testout) << \"start followedge: p1 = \" << specpoints[hsp.Get(pi1)].p \n\t\t   << \", v = \" << specpoints[hsp.Get(pi1)].v << endl;\n#endif\n\n\tFollowEdge (pi1, ep, pos, hsp, h, mesh,\n\t\t    edgepoints, curvelength);\n\n\n\tif (multithread.terminate)\n\t  return;\n      \n\tif (!ep)\n\t  {\n\t    // ignore starting point\n\t    hsp.DeleteElement (pi1);\n\t    cout << \"yes, this happens\" << endl;\n\t    continue;\n\t  }\n\n\n\n\tendpoints.Append (hsp.Get(ep));\n\n\n\tdouble elen = 0;\n\tfor (int i = 1; i <= edgepoints.Size()-1; i++)\n\t  elen += Dist (edgepoints.Get(i), edgepoints.Get(i+1));\n\n\n\tint shortedge = 0;\n\tfor (int i = 1; i <= geometry.identifications.Size(); i++)\n\t  if (geometry.identifications.Get(i)->ShortEdge(specpoints[hsp.Get(pi1)], specpoints[hsp.Get(ep)]))\n\t    shortedge = 1;\n\t// (*testout) << \"shortedge = \" << shortedge << endl;\n\n\n\tif (!shortedge)\n\t  {\n\t    mesh.RestrictLocalHLine (Point3d (specpoints[hsp.Get(pi1)].p), \n\t\t\t\t     Point3d (specpoints[hsp.Get(ep)].p), \n\t\t\t\t     elen / mparam.segmentsperedge);\n\t  }\n      \n\ts1 = specpoints[hsp.Get(pi1)].s1;\n\ts2 = specpoints[hsp.Get(pi1)].s2;\n\ts1_orig = specpoints[hsp.Get(pi1)].s1_orig;\n\ts2_orig = specpoints[hsp.Get(pi1)].s2_orig;\n\n\n\t// delete initial, terminal and conditional points\n\n#ifdef DEVELOP\n\t(*testout) << \"terminal point: p = \" << specpoints[hsp.Get(ep)].p \n\t\t   << \", v = \" << specpoints[hsp.Get(ep)].v << endl;      \n#endif\n\n\tsearchtree -> DeleteElement (hsp.Get(ep));\n\tsearchtree -> DeleteElement (hsp.Get(pi1));\n\n\tif (ep > pi1)\n\t  {\n\t    glob2hsp[hsp[ep-1]] = -1;\n\t    glob2hsp[hsp.Last()] = ep-1;\n\t    hsp.DeleteElement (ep);\n\n\t    glob2hsp[hsp[pi1-1]] = -1;\n\t    glob2hsp[hsp.Last()] = pi1-1;\n\t    hsp.DeleteElement (pi1);\n\t  }\n\telse\n\t  {\n\t    glob2hsp[hsp[pi1-1]] = -1;\n\t    glob2hsp[hsp.Last()] = pi1-1;\n\t    hsp.DeleteElement (pi1);\n\n\t    glob2hsp[hsp[ep-1]] = -1;\n\t    glob2hsp[hsp.Last()] = ep-1;\n\t    hsp.DeleteElement (ep);\n\t  }\n\n\n\tfor (int j = 1; j <= edgepoints.Size()-1; j++)\n\t  {\n\t    p = edgepoints.Get(j);\n\t    np = Center (p, edgepoints.Get(j+1));\n\t    double hd = Dist (p, np);\n \n\n\t    Box<3> boxp (np - (1.2 * hd) * Vec<3> (1, 1, 1),\n\t\t\t np + (1.2 * hd) * Vec<3> (1, 1, 1));\n\t    searchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind);\t    \n\n\t    for (int i = 0; i < locind.Size(); i++)\n\t      {\n\t\tif ( specpoints[locind[i]].HasSurfaces (s1, s2) &&\n\t\t     specpoints[locind[i]].unconditional == 0)\n\t\t  {\n\t\t    searchtree -> DeleteElement (locind[i]);\n\n\t\t    int li = glob2hsp[locind[i]];\n\t\t    glob2hsp[locind[i]] = -1;\n\t\t    glob2hsp[hsp.Last()] = li;\n\t\t    hsp.Delete (li);\n\t\t  }\n\t      }\n\n\n\t    /*\n\t    for (int i = 1; i <= hsp.Size(); i++)\n\t      if ( specpoints[hsp.Get(i)].HasSurfaces (s1, s2) &&\n\t\t   specpoints[hsp.Get(i)].unconditional == 0 &&\n\t\t   Dist2 (np, specpoints[hsp.Get(i)].p) < 1.2 * hd)\n\t\t{\n\t\t  searchtree -> DeleteElement (hsp.Get(i)+1);\n\t\t  hsp.DeleteElement (i);\n\t\t  i--;\n\t\t}\n\t    */\n\t  }\n\n      \n\tNgArray<Segment> refedges;\n\tNgArray<bool> refedgesinv;\n      \n\n\tAnalyzeEdge (s1_orig, s2_orig, s1, s2, pos, layer,\n\t\t     edgepoints,\n\t\t     refedges, refedgesinv);\n\n\n\tfor (int i = 0; i < refedges.Size(); i++)\n          {\n            refedges[i].edgenr = cntedge;\n            refedges[i].index = cntedge;\n          }\n\n\t\n#ifdef DEVELOP\n\t(*testout) << \"edge \" << cntedge << endl\n\t\t   << \"startp: \" << specpoints[startpoints.Last()].p \n\t\t   << \", v = \" << specpoints[startpoints.Last()].v << endl\n\t\t   << \"copy = \" << copyedge << endl\n\t\t   << refedges.Size() << \" refedges: \";\n\tfor (int i = 1; i <= refedges.Size(); i++)\n\t  (*testout) << \" \" << refedges.Get(i).si;\n\t(*testout) << endl;\n\tif (refedgesinv.Size())\n\t  (*testout) << \"inv[1] = \" << refedgesinv.Get(1) << endl;\n#endif\n\n\tif (refedges.Size() == 0)\n\t  throw NgException (\"Problem in edge detection\");\n\n      \n\tif (!copyedge)\n\t  {\n\t    // (*testout) << \"store edge\" << endl;\n\t    // int oldnseg = mesh.GetNSeg();\n\n\t    if (!shortedge)\n\t      StoreEdge (refedges, refedgesinv, \n\t\t\t edgepoints, curvelength, layer, mesh);\n\t    else\n\t      StoreShortEdge (refedges, refedgesinv, \n\t\t\t      edgepoints, curvelength, layer, mesh);\n\n\n\t    for(int i = 0; i < refedges.Size(); i++)\n\t      {\n\t\trefedges[i].surfnr1 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr1);\n\t\trefedges[i].surfnr2 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr2);\n\t      }\n\n\t    /*\n\t      for (int i = oldnseg+1; i <= mesh.GetNSeg(); i++)\n\t      for (int j = 1; j <= oldnseg; j++)\n\t      {\n\t      const Point<3> & l1p1 = mesh.Point (mesh.LineSegment(i).p1);\n\t      const Point<3> & l1p2 = mesh.Point (mesh.LineSegment(i).p2);\n\t      const Point<3> & l2p1 = mesh.Point (mesh.LineSegment(j).p1);\n\t      const Point<3> & l2p2 = mesh.Point (mesh.LineSegment(j).p2);\n\t      Vec<3> vl1(l1p1, l1p2);\n\t      for (double lamk = 0; lamk <= 1; lamk += 0.1)\n\t      {\n\t      Point<3> l2p = l1p1 + lamk * vl1;\n\t      double dist = sqrt (MinDistLP2 (l2p1, l2p2, l2p));\n\t      if (dist > 1e-12)\n\t      mesh.RestrictLocalH (l2p, 3*dist);\n\t      }\n\t      }\n\t    */\n\t  }\n\telse\n\t  {\n\t    CopyEdge (refedges, refedgesinv,\n\t\t      copyfromedge, \n\t\t      specpoints[startpoints.Get(copyfromedge)].p,\n\t\t      specpoints[endpoints.Get(copyfromedge)].p,\n\t\t      edgepoints.Get(1), edgepoints.Last(),\n\t\t      copyedgeidentification, \n\t\t      layer,\n\t\t      mesh);\n\t  }\n\n\n        {\n          // named edge ?\n          // cout << \"check edge name, size = \" << geometry.named_edges.size() << endl;\n          // for (auto pair : geometry.named_edges)\n          // cout << \"key = \" << get<0> (pair.first) << \"-\" << get<1> (pair.first) << \", val = \" << pair.second << endl;\n          \n          Surface * sp1 = const_cast<Surface*> (geometry.GetSurface(s1));\n          Surface * sp2 = const_cast<Surface*> (geometry.GetSurface(s2));\n          // cout << \"sp1 = \" << sp1 << \", sp2 = \" << sp2 << endl;\n\n          auto ptr = geometry.named_edges.find(tuple(sp1, sp2));\n          if (ptr != geometry.named_edges.end())\n            for (int i = 0; i < refedges.Size(); i++)\n              mesh.SetCD2Name(refedges[i].edgenr, ptr->second);\n          \n          ptr = geometry.named_edges.find(tuple(sp2, sp1));\n          if (ptr != geometry.named_edges.end())\n            for (int i = 0; i < refedges.Size(); i++)\n              mesh.SetCD2Name(refedges[i].edgenr, ptr->second);\n        }\n        \n\tfor(int i=0; i<refedges.Size(); i++)\n\t  {\n\t    auto splinesurface = dynamic_cast<const SplineSurface*>(geometry.GetSurface(refedges[i].surfnr1));\n\t    if(splinesurface)\n\t      {\n\t\tauto name = splinesurface->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p);\n\t\tmesh.SetCD2Name(refedges[i].edgenr,name);\n\t      }\n\t    else\n\t      {\n\t\tauto splinesurface2 = dynamic_cast<const SplineSurface*>(geometry.GetSurface(refedges[i].surfnr2));\n\t    if(splinesurface2)\n\t      {\n\t\tauto name = splinesurface2->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p);\n\t\tmesh.SetCD2Name(refedges[i].edgenr,name);\n\t      }\n\t\t\n\t      }\n\t    \n\t  }\n\n\t/*\n\t  // not available ...\n\tfor (int i = 0; i < refedges.Size(); i++)\n\t  {\n\t    EdgeDescriptor ed;\n\t    ed.SetSurfNr(0, refedges[i].surfnr1);\n\t    ed.SetSurfNr(1, refedges[i].surfnr2);\n\t    int hnr = mesh.AddEdgeDescriptor(ed);\n\t    if (hnr != refedges[i].edgenr)\n\t      {\n\t\tcerr << \"edgedescriptor index wrong: new : \" << hnr << \" old = \" << refedges[i].edgenr << endl;\n\t      }\n\t  }\n\t*/\n\n\n\n// \tfor(int i=0; i<hsp.Size(); i++)\n// \t  {\n// \t    (*testout) << \"pos2 hsp[\"<<i<<\"] ... \" << specpoints[hsp[i]].p << endl;\n// \t  }\n      }\n  }\n  \n\n\n\n\n\n  /*\n    If two or more edges share the same initial and end-points,\n    then they need at least two segments \n  */\n  void EdgeCalculation ::\n  SplitEqualOneSegEdges (Mesh & mesh)\n    {\n    //    int i, j;\n    SegmentIndex si;\n    // PointIndex pi;\n\n    NgArray<int> osedges(cntedge);\n    INDEX_2_HASHTABLE<int> osedgesht (cntedge+1);\n\n    osedges = 2;\n\n    // count segments on edges\n    for (si = 0; si < mesh.GetNSeg(); si++)\n      {\n\tconst Segment & seg = mesh[si];\n\tif (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge)\n\t  osedges.Elem(seg.edgenr)--;\n      }\n\n    // flag one segment edges\n    for (int i = 0; i < cntedge; i++)\n      osedges[i] = (osedges[i] > 0) ? 1 : 0;\n\n    for (si = 0; si < mesh.GetNSeg(); si++)\n      {\n\tconst Segment & seg = mesh[si];\n\tif (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge)\n\t  {\n\t    if (osedges.Get(seg.edgenr))\n\t      {\n\t\tINDEX_2 i2(seg[0], seg[1]);\n\t\ti2.Sort ();\n\t\tif (osedgesht.Used (i2))\n\t\t  osedgesht.Set (i2, 2);\n\t\telse\n\t\t  osedgesht.Set (i2, 1);\n\t      }\n\t  }\n      }\n\n\n    // one edge 1 segment, other 2 segments \n    // yes, it happens !\n    point_on_edge_problem = 0;\n    for (int i = 1; i <= osedgesht.GetNBags(); i++)\n      for (int j = 1; j <= osedgesht.GetBagSize(i); j++)\n\t{\n\t  PointIndices<2> i2; \n\t  int val;\n\t  osedgesht.GetData (i, j, i2, val);\n\n\t  const Point<3> & p1 = mesh[PointIndex(i2.I1())];\n\t  const Point<3> & p2 = mesh[PointIndex(i2.I2())];\n\t  Vec<3> v = p2 - p1;\n\t  double vlen = v.Length();\n\t  v /= vlen;\n\t  for (PointIndex pi = IndexBASE<PointIndex>(); \n\t       pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n\n\t    if (pi != i2.I1() && pi != i2.I2())\n\t      {\n\t\tconst Point<3> & p = mesh[pi];\n\t\tVec<3> v2 = p - p1;\n\t\tdouble lam = (v2 * v);\n\t\tif (lam > 0 && lam < vlen)\n\t\t  {\n\t\t    Point<3> hp = p1 + lam * v;\n\t\t    if (Dist (p, hp) < 1e-4 * vlen)\n\t\t      {\n\t\t\tPrintWarning (\"Point on edge !!!\");\n\t\t\tcout << \"seg: \" << i2 << \", p = \" << pi << endl;\n\t\t\tosedgesht.Set (i2, 2);\t\t      \n\t\t\tpoint_on_edge_problem = 1;\n\n\t\t\t(*testout) << \"Point on edge\" << endl\n\t\t\t\t   << \"seg = \" << i2 << \", p = \" << pi << endl\n\t\t\t\t   << \"pos = \" << p << \", projected = \" << hp << endl\n                                   << \"seg is = \"\n                                   << mesh.Point(PointIndex(i2.I1())) << \" - \"\n                                   << mesh.Point(PointIndex(i2.I2())) << endl;\n\t\t      }\n\t\t  }\n\t      }\n\t}\n\n\n    // insert new points\n    osedges = -1;\n\n    int nseg = mesh.GetNSeg();\n    for (si = 0; si < nseg; si++)\n      {\n\tconst Segment & seg = mesh[si];\n\tif (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge)\n\t  {\n\t    INDEX_2 i2(seg[0], seg[1]);\n\t    i2.Sort ();\n\t    if (osedgesht.Used (i2) &&\n\t\tosedgesht.Get (i2) == 2 &&\n\t\tosedges.Elem(seg.edgenr) == -1)\n\t      {\n\t\tPoint<3> newp = Center (mesh[PointIndex(seg[0])],\n\t\t\t\t\tmesh[PointIndex(seg[1])]);\n\n\t\tProjectToEdge (geometry.GetSurface(seg.surfnr1), \n\t\t\t       geometry.GetSurface(seg.surfnr2), \n\t\t\t       newp);\n\n\t\tosedges.Elem(seg.edgenr) = \n\t\t  mesh.AddPoint (newp, mesh[PointIndex(seg[0])].GetLayer(), EDGEPOINT);\n\t\tmeshpoint_tree -> Insert (newp, osedges.Elem(seg.edgenr));\n\t      }\n\t  }\n      }\n    \n\n    // for (int i = 1; i <= nseg; i++)\n    for (Segment & seg : mesh.LineSegments())\n      {\n\t// Segment & seg = mesh.LineSegment (i);\n\tif (seg.edgenr >= 1 && seg.edgenr <= cntedge)\n\t  {\n\t    if (osedges.Get(seg.edgenr) != -1)\n\t      {\n\t\tSegment newseg = seg;\n\t\tnewseg[0] = osedges.Get(seg.edgenr);\n\t\tseg[1] = osedges.Get(seg.edgenr);\n\t\tmesh.AddSegment (newseg);\n\t      }\n\t  }\n      }\n\n  }\n\n\n\n  void EdgeCalculation :: \n  FollowEdge (int pi1, int & ep, int & pos,\n\t      const NgArray<int> & hsp,\n\t      double h, const Mesh & mesh,\n\t      NgArray<Point<3> > & edgepoints,\n\t      NgArray<double> & curvelength)\n  {\n    int s1, s2, s1_rep, s2_rep;\n    double len, steplen, cursteplen, loch;\n    Point<3> p, np, pnp;\n    Vec<3> a1, a2, t;\n\n    NgArray<int> locind;\n\n    double size = geometry.MaxSize();  \n    double epspointdist2 = size * 1e-6;\n    epspointdist2 = sqr (epspointdist2);\n    int uselocalh = mparam.uselocalh;\n\n\n    s1_rep = specpoints[hsp.Get(pi1)].s1;\n    s2_rep = specpoints[hsp.Get(pi1)].s2;\n    s1 = specpoints[hsp.Get(pi1)].s1_orig;\n    s2 = specpoints[hsp.Get(pi1)].s2_orig;\n  \n    p = specpoints[hsp.Get(pi1)].p;\n    //ProjectToEdge (geometry.GetSurface(s1), \n    //               geometry.GetSurface(s2), p);\n    geometry.GetSurface(s1) -> CalcGradient (p, a1);\n    geometry.GetSurface(s2) -> CalcGradient (p, a2);\n\n    t = Cross (a1, a2);\n    t.Normalize();\n\n    pos = (specpoints[hsp.Get(pi1)].v * t) > 0;\n    if (!pos) t *= -1;\n\n  \n    edgepoints.Append (p);\n    curvelength.Append (0);\n    len = 0;\n\n    // (*testout) << \"geometry.GetSurface(s1) -> LocH (p, 3, 1, h) \" << geometry.GetSurface(s1) -> LocH (p, 3, 1, h)\n    // << \" geometry.GetSurface(s2) -> LocH (p, 3, 1, h) \" << geometry.GetSurface(s2) -> LocH (p, 3, 1, h) << endl;\n\n    loch = min2 (geometry.GetSurface(s1) -> LocH (p, 3, 1, mparam, h), \n\t\t geometry.GetSurface(s2) -> LocH (p, 3, 1, mparam, h));\n  \n  \n  \n    if (uselocalh)\n      {\n\tdouble lh = mesh.GetH(p);\n\t// (*testout) << \"lh \" << lh << endl;\n\tif (lh < loch)\n\t  loch = lh;\n      }\n\n    steplen = 0.1 * loch;\n  \n    do\n      {\n\tif (multithread.terminate)\n\t  return;\n      \n\tif (fabs (p(0)) + fabs (p(1)) + fabs (p(2)) > 100000*size)\n\t  {\n\t    ep = 0;\n\t    PrintWarning (\"Give up line\");\n\t    break;\n\t  }\n\n\tif (steplen > 0.1 * loch) steplen = 0.1 * loch;\n      \n\tsteplen *= 2;\n\tdo\n\t  {\n\t    steplen *= 0.5;\n\t    np = p + steplen * t;\n\t    pnp = np;\n\t    ProjectToEdge (geometry.GetSurface(s1), \n\t\t\t   geometry.GetSurface(s2), pnp);\n\t  }\n\twhile (Dist (np, pnp) > 0.1 * steplen);\n\n      \n\tcursteplen = steplen;\n\tif (Dist (np, pnp) < 0.01 * steplen) steplen *= 2;\n      \n \n\tnp = pnp;\n\tep = 0;\n      \n\tdouble hvtmin = 1.5 * cursteplen;\n      \n\tBox<3> boxp (p - (2 * cursteplen) * Vec<3> (1, 1, 1),\n\t\t     p + (2 * cursteplen) * Vec<3> (1, 1, 1));\n\n\tsearchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind);\n\t\n\tfor (int i = 0; i < locind.Size(); i++)\n\t  {\n\t    Vec<3> hv = specpoints[locind[i]].p - p;\n\t    if (hv.Length2() > 9 * cursteplen * cursteplen)\n\t      continue;\n\n\t    double hvt = hv * t;\n\t    hv -= hvt * t;\n\n\t    if (hv.Length() < 0.2 * cursteplen &&\n\t\thvt > 0 && \n\t\t//\t\t  hvt < 1.5 * cursteplen &&\n\t\thvt < hvtmin && \n\t\tspecpoints[locind[i]].unconditional == 1 &&\n\t\t(specpoints[locind[i]].v + t).Length() < 0.4  ) \n\t      {\n\t\tPoint<3> hep = specpoints[locind[i]].p;\n\t\tProjectToEdge (geometry.GetSurface(s1), \n\t\t\t       geometry.GetSurface(s2), hep);            \n\t      \n\t      \n\t\tif (Dist2 (hep, specpoints[locind[i]].p) < epspointdist2 )\n\t\t  {\n\t\t    geometry.GetSurface(s1) -> CalcGradient (hep, a1);\n\t\t    geometry.GetSurface(s2) -> CalcGradient (hep, a2);\n\t\t    Vec<3> ept = Cross (a1, a2);\n\t\t    ept /= ept.Length();\n\t\t    if (!pos) ept *= -1;\n\t\t  \n\t\t    if ( (specpoints[locind[i]].v + ept).Length() < 1e-4 )\n\t\t      {\n\t\t\tnp = specpoints[locind[i]].p;\n\n\t\t\tfor (int jj = 0; jj < hsp.Size(); jj++)\n\t\t\t  if (hsp[jj] == locind[i])\n\t\t\t    ep = jj+1;\n\t\t\t    \n\t\t\tif (!ep) \n\t\t\t  cerr << \"endpoint not found\" << endl;\n\t\t\t  //\t\t\tep = i;\n\t\t\thvtmin = hvt;\n\t\t\t//\t\t\t  break;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\n\n\n\n\t/*\n\tfor (int i = 1; i <= hsp.Size(); i++)\n\t  {\n\t    if (!boxp.IsIn (specpoints[hsp.Get(i)].p))\n\t      continue;\n\t  \n\t    Vec<3> hv = specpoints[hsp.Get(i)].p - p;\n\t    if (hv.Length2() > 9 * cursteplen * cursteplen)\n\t      continue;\n\n\t    double hvt = hv * t;\n\t    hv -= hvt * t;\n\t  \n\t    if (hv.Length() < 0.2 * cursteplen &&\n\t\thvt > 0 && \n\t\t//\t\t  hvt < 1.5 * cursteplen &&\n\t\thvt < hvtmin && \n\t\tspecpoints[hsp.Get(i)].unconditional == 1 &&\n\t\t(specpoints[hsp.Get(i)].v + t).Length() < 0.4  ) \n\t      {\n\t\tPoint<3> hep = specpoints[hsp.Get(i)].p;\n\t\tProjectToEdge (geometry.GetSurface(s1), \n\t\t\t       geometry.GetSurface(s2), hep);            \n\t      \n\t      \n\t\tif (Dist2 (hep, specpoints[hsp.Get(i)].p) < epspointdist2 )\n\t\t  {\n\t\t    geometry.GetSurface(s1) -> CalcGradient (hep, a1);\n\t\t    geometry.GetSurface(s2) -> CalcGradient (hep, a2);\n\t\t    Vec<3> ept = Cross (a1, a2);\n\t\t    ept /= ept.Length();\n\t\t    if (!pos) ept *= -1;\n\t\t  \n\t\t    if ( (specpoints[hsp.Get(i)].v + ept).Length() < 1e-4 )\n\t\t      {\n\t\t\tnp = specpoints[hsp.Get(i)].p;\n\t\t\tep = i;\n\t\t\thvtmin = hvt;\n\t\t\t//\t\t\t  break;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\t*/\n\n\tloch = min2 (geometry.GetSurface(s1_rep) -> LocH (np, 3, 1, mparam, h), \n\t\t     geometry.GetSurface(s2_rep) -> LocH (np, 3, 1, mparam, h));\n        loch = max2 (loch, mparam.minh);\n\n\tif (uselocalh)\n\t  {\n\t    double lh = mesh.GetH(np);\n\t    if (lh < loch) loch = lh;\n\t  }\n        \n\tlen += Dist (p, np) / loch;\n\tedgepoints.Append (np);\n\tcurvelength.Append (len);\n      \n\tp = np;\n      \n\tgeometry.GetSurface(s1) -> CalcGradient (p, a1);\n\tgeometry.GetSurface(s2) -> CalcGradient (p, a2);\n\tt = Cross (a1, a2);\n\tt.Normalize();\n\tif (!pos) t *= -1;\n      }\n    while (! ep);\n  }\n\n\n\n\n\n\n\n  void EdgeCalculation :: \n  AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer,\n\t       const NgArray<Point<3> > & edgepoints,\n\t       NgArray<Segment> & refedges,\n\t       NgArray<bool> & refedgesinv)\n  {\n    Segment seg;\n    NgArray<int> locsurfind, locsurfind2;\n\n    NgArray<int> edges_priority;\n\n    double size = geometry.MaxSize();\n    bool debug = 0;\n\n#ifdef DEVELOP\n    debug = 1;\n#endif\n    \n    if (debug)\n      {\n\t(*testout) << \"debug edge !!!\" << endl;\n\t(*testout) << \"edgepoints = \" << edgepoints << endl;\n\t(*testout) << \"s1, s2 = \" << s1 << \" - \" << s2 << endl;\n\t(*testout) << \"s1_rep, s2_rep = \" << s1_rep << \" - \" << s2_rep << endl;\n      }\n\n    refedges.SetSize(0);\n    refedgesinv.SetSize(0);\n    Point<3> hp = Center (edgepoints[0], edgepoints[1]);\n    ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hp);\n    \n    if (debug)\n      *testout << \"hp = \" << hp << endl;\n\n    Vec<3> t, a1, a2;\n    geometry.GetSurface(s1) -> CalcGradient (hp, a1);\n    geometry.GetSurface(s2) -> CalcGradient (hp, a2);\n    t = Cross (a1, a2);\n    t.Normalize();\n    if (!pos) t *= -1;    \n\n\n  \n    for (int i = 0; i < geometry.GetNTopLevelObjects(); i++)\n      {\n\t// Solid * locsol;\n\n\tif (geometry.GetTopLevelObject(i)->GetLayer() != layer) \n\t  continue;\n      \n\tconst Solid * sol = geometry.GetTopLevelObject(i)->GetSolid();\n\tconst Surface * surf = geometry.GetTopLevelObject(i)->GetSurface();\n\n\t// sol -> TangentialSolid (hp, locsol, locsurfind, size*ideps);\n        auto locsol = sol -> TangentialSolid (hp, locsurfind, size*ideps);\n\n\t//*testout << \"hp = \" << hp << endl;\n\t//(*testout) << \"locsol: \" << endl;\n\t//if (locsol) locsol->Print(*testout);\n\t//(*testout) << endl;\n\n\n\tif (!locsol) continue;\n\n\tBoxSphere<3> boxp (hp, hp);\n\tboxp.Increase (1e-8*size);\n\tboxp.CalcDiamCenter();\n      \n\tReducePrimitiveIterator rpi(boxp);\n\tUnReducePrimitiveIterator urpi;\n      \n\t// ((Solid*)locsol) -> IterateSolid (rpi);\n        locsol -> IterateSolid (rpi);\n\n\tlocsol -> CalcSurfaceInverse ();\n      \n\tif (!surf)\n\t  {\n\t    locsol -> GetTangentialSurfaceIndices (hp,locsurfind,ideps*size);\n\t  }\n\telse\n\t  {\n\t    /*\n\t      if (fabs (surf->CalcFunctionValue (hp)) < 1e-6)\n\t      continue;\n\t    */\n\t    locsurfind.SetSize(1);\n\t    locsurfind[0] = -1;\n\t    for (int j = 0; j < geometry.GetNSurf(); j++)\n\t      if (geometry.GetSurface(j) == surf)\n\t\t{\n\t\t  locsurfind[0] = j;\n\t\t  //\t\t      geometry.GetSurfaceClassRepresentant(j);\n\t\t  break;\n\t\t}\n\t  }\n\n\t// ((Solid*)locsol) -> IterateSolid (urpi);\n        locsol -> IterateSolid (urpi);\n\n      \n\tif (debug)\n\t  (*testout) << \"edge of tlo \" << i << \", has \" << locsurfind.Size() << \" faces.\" << endl;\n      \n\n\tfor (int j = locsurfind.Size()-1; j >= 0; j--)\n\t  if (fabs (geometry.GetSurface(locsurfind[j])\n\t\t    ->CalcFunctionValue (hp) ) > ideps*size)\n\t    locsurfind.Delete(j);\n      \n\tif (debug)\n\t  (*testout) << locsurfind.Size() << \" faces on hp\" << endl;\n\n\n\n\tfor (int j = 0; j < locsurfind.Size(); j++)\n\t  {      \n\t    int lsi = locsurfind[j];\n\t    int rlsi = geometry.GetSurfaceClassRepresentant(lsi);\n\t  \n\n\t    // n is outer normal to solid\n\t    Vec<3> n = geometry.GetSurface(lsi) -> GetNormalVector (hp);\n            if (debug)\n              *testout << \"n1 = \" << n << endl;\n\t    if (geometry.GetSurface (lsi)->Inverse())\n\t      n *= -1;\n\t  \n\t    if (fabs (t * n) > 1e-4) continue;\n\t    if (debug)\n\t      {\n\t\t(*testout) << \"face \" << locsurfind[j] << \", rep = \" << rlsi \n\t\t\t   << \" has (t*n) = \" << (t*n) << endl;\n\t\t(*testout) << \"n = \" << n << endl;\n\t      }\n\t  \n\t    // rn is normal to class representant\n\t    Vec<3> rn = geometry.GetSurface(rlsi) -> GetNormalVector (hp);\n\t    if (debug)\n\t      {\n\t\t(*testout) << \"rn = \" << rn << endl;\n\t      }\n\t    \n\t    //if( n*rn < 0)\n\t    // rn *= -1;\n\n\t    bool sameasref = ((n * rn) > 0);\n\n\t    //m = Cross (t, rn);\n\t    Vec<3> m = Cross (t, n); \n\t    if(!sameasref) m*=-1.;\n\t    \n\t    m.Normalize();\n\n\t    \n\t    if (debug)\n\t      (*testout) << \"m = \" << m << endl;\n\n\n\t    //bool founddirection = false;\n\t    //int k;\n\t    double eps = 1e-8*size;\n\n            ArrayMem<bool,2> pre_ok(2);\n            bool flip = false;\n\n \t    do\n \t      {\n \t\teps *= 0.5;\n                auto in00 = locsol -> VectorIn2 (hp, m, n, eps);\n                auto in01 = locsol -> VectorIn2 (hp, m, -1. * n, eps);\n                pre_ok[0] = in00 == IS_OUTSIDE && in01 == IS_INSIDE;\n\n                if(in00 == IS_INSIDE && in01 == IS_OUTSIDE)\n                  pre_ok[0] = flip = true;\n\n                auto in10 = locsol -> VectorIn2 (hp, -1.*m, n, eps);\n                auto in11 = locsol -> VectorIn2 (hp, -1.*m, -1. * n, eps);\n                pre_ok[1] = (in10 == IS_OUTSIDE && in11 == IS_INSIDE);\n\n                if(in10 == IS_INSIDE && in11 == IS_OUTSIDE)\n                  pre_ok[1] = flip = true;\n\t\t\n\t\tif (debug)\n\t\t  {\n\t\t    *testout << \"eps = \" << eps << endl;\n                    *testout << \"in,1 = \" << in00 << endl;\n                    *testout << \"in,1 = \" << in01 << endl;\n                    *testout << \"in,1 = \" << in10 << endl;\n                    *testout << \"in,1 = \" << in11 << endl;\n\t\t  }\n \t      }\n \t    while(pre_ok[0] && pre_ok[1] && eps > 1e-16*size);\n\n            if (debug)\n              {\n                *testout << \"eps = \" << eps << \", size = \" << size << endl;\n                *testout << \"pre_ok[0,1] = \" << pre_ok[0] << \",\" << pre_ok[1] << endl;\n              }\n\n\t    eps = 1e-8*size;\n\t    \n\n\t    for (int k = 1; k <= 2; k ++)\n\t      {\n\t\tbool edgeinv = (k == 2);\n\t      \n\t\tif (debug)\n\t\t  {\n\t\t    (*testout) << \"onface(\" << hp << \", \" << m << \")= \" << flush;\n\t\t    (*testout) << locsol->OnFace (hp, m, eps) << flush;\n\t\t    (*testout) << \" n \" << n << flush;\n\t\t    (*testout) << \" vec2in = \"\n\t\t\t       << locsol -> VectorIn2 (hp, m, n, eps) << \" and \" \n\t\t\t       << locsol -> VectorIn2 (hp, m, -1 * n, eps) << endl;\n\t\t  }\n\n\t\t//\t      if (locsol -> OnFace (hp, m))\n\t\t\n\n\t\t// one side must be inside, the other must be outside\n\t\tbool ok = (pre_ok[k-1] || \n\t\t\t   (locsol -> VectorIn2 (hp, m, n, eps) == IS_OUTSIDE &&\n\t\t\t    locsol -> VectorIn2 (hp, m, -1 * n, eps) == IS_INSIDE));\n\n\t\tif (debug)\n\t\t  (*testout) << \"ok (before) \" << ok <<  endl;\n\n\t\t// compute second order approximation\n\t\t// curve = hp + t m + t*t/2 m2\n\t\tVec<3> grad, m2;\n\t\tMat<3> hesse;\n\t\tgeometry.GetSurface(lsi) -> CalcGradient (hp, grad);\n\t\tgeometry.GetSurface(lsi) -> CalcHesse (hp, hesse);\n\t\tdouble fac = -(m * (hesse * m)) / (grad * grad);\n\t\tm2 = fac * grad;\n\t\t// (*testout) << \"hp = \" << hp << \", m = \" << m << \", m2 = \" << m2 << endl;\n\n\t\t// Solid * locsol2;\n\t\tauto locsol2 = locsol -> TangentialSolid3 (hp, m, m2, locsurfind2, ideps*size);\n\t\tif (!locsol2) ok = 0;\n\t\t// delete locsol2;\n\n\n\t\tif (ok)\n\t\t  {\n\t\t    if (debug)\n\t\t      (*testout) << \"is true\" << endl;\n\t\t    int hi = 0;\n\t\t    for (int l = 1; !hi && l <= refedges.Size(); l++)\n\t\t      {\n\t\t\t   if (refedges.Get(l).si == rlsi &&     // JS sept 2006\n\t\t\t       // if (refedges.Get(l).si == lsi &&\n\t\t\t       refedgesinv.Get(l) == edgeinv)\n\t\t\t     {\n\t\t\t       hi = l;\n\t\t\t     }\n\t\t      }\n\t\t  \n\t\t    if (!hi)\n\t\t      {\n\t\t\t seg.si = rlsi;  // JS Sept 2006\n\t\t\t // seg.si = lsi;\n\t\t\tseg.domin = -1;\n\t\t\tseg.domout = -1;\n\t\t\tseg.tlosurf = -1;\n\t\t\t//seg.surfnr1 = s1_rep;\n\t\t\t//seg.surfnr2 = s2_rep;\n\t\t\tseg.surfnr1 = s1;\n\t\t\tseg.surfnr2 = s2;\n                        refedges.Append (seg);\n                        hi = refedges.Size();\n\t\t\trefedgesinv.Append (edgeinv);\n\t\t\tedges_priority.Append((pre_ok[k-1]) ? 1 : 0);\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\tif(edges_priority[hi-1] / 10 == -i-1)\n\t\t\t  edges_priority[hi-1] = 10*(i+1);\n\t\t\telse\n\t\t\t  edges_priority[hi-1] = -10*(i+1);\n\t\t      }\n\t\t  \n\t\t    if (!surf)\n\t\t      {\n                        bool inside = sameasref;\n                        if(flip)\n                          inside = !inside;\n                        if (inside)\n\t\t\t  refedges.Elem(hi).domin = i;\n\t\t\telse \n\t\t\t  refedges.Elem(hi).domout = i;\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t      refedges.Elem(hi).tlosurf = i;\n\t\t      for(int kk = 0; kk < geometry.GetNTopLevelObjects(); kk++)\n\t\t\t{\n\t\t\t  auto othersolid = geometry.GetTopLevelObject(kk)->GetSolid();\n\t\t\t  auto othersurf = geometry.GetTopLevelObject(kk)->GetSurface();\n\t\t\t  if(!othersurf && dynamic_cast<SplineSurface*>(othersurf))\n\t\t\t    {\n\t\t\t      if(othersolid->IsIn(edgepoints[0])  &&\n\t\t\t\t othersolid->IsIn(edgepoints[edgepoints.Size()-1]))\n\t\t\t\t{\n\t\t\t\t  refedges.Elem(hi).domin = kk;\n\t\t\t\t  refedges.Elem(hi).domout = kk;\n\t\t\t\t}\n\t\t\t    }\n\t\t\t}\n\t\t      }\n\n\t\t    if(pre_ok[k-1])\n\t\t      edges_priority[hi-1] = 1;\n\t\t    \n\n\t\t    if (debug)\n\t\t      (*testout) << \"add ref seg:\" \n\t\t\t\t << \"si = \" << refedges.Get(hi).si\n\t\t\t\t << \", domin = \" << refedges.Get(hi).domin\n\t\t\t\t << \", domout = \" << refedges.Get(hi).domout\n\t\t\t\t << \", surfnr1/2 = \" << refedges.Get(hi).surfnr1\n\t\t\t\t << \", \" << refedges.Get(hi).surfnr2\n\t\t\t\t << \", inv = \" << refedgesinv.Get(hi) \n\t\t\t\t << \", refedgenr = \" << hi\n\t\t\t\t << \", priority = \" << edges_priority[hi-1]\n\t\t\t\t << \", hi = \" << hi \n\t\t\t\t << endl;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    if (debug)\n\t\t      (*testout) << \"is false\" << endl;\n\t\t  }\n\t\tm *= -1;\n\t      } \n\t  }\n\t// delete locsol;          \n      }\n\n   \n    if (debug)\n      {\n\t*testout << \"Refsegments, before delete: \" << endl << refedges << endl;\n\t*testout << \"inv: \" << endl << refedgesinv << endl;\n      }\n\n    if(refedges.Size() == 0)\n      throw Exception(\"No edges found, something wrong.\");\n    \n    NgBitArray todelete(refedges.Size());\n    todelete.Clear();\n\n\n    for(int i=0; i<refedges.Size()-1; i++)\n      {\n\tfor(int j=i+1; !todelete.Test(i) && j<refedges.Size(); j++)\n\t  {\n\t    if(todelete.Test(j))\n\t      continue;\n\n\t    if(refedges[i].si == refedges[j].si &&\n\t       refedges[i].domin == refedges[j].domin &&\n\t       refedges[i].domout == refedges[j].domout &&\n\t       geometry.GetSurfaceClassRepresentant(refedges[i].surfnr1) == geometry.GetSurfaceClassRepresentant(refedges[j].surfnr1) &&\n\t       geometry.GetSurfaceClassRepresentant(refedges[i].surfnr2) == geometry.GetSurfaceClassRepresentant(refedges[j].surfnr2)\n\t       // && refedgesinv[i] == refedgesinv[j] // JS, 20060802\n\t       )\n\t      {\n\t\tif(debug)\n\t\t  (*testout) << \"equal segments: \" << refedges[i] << \" pri \" << edges_priority[i] \n\t\t\t     << \" tlosurf \" << refedges[i].tlosurf\n\t\t\t     << \"\\n and \" << refedges[j] << \" pri \" << edges_priority[j]\n\t\t\t     << \" tlosurf \" << refedges[i].tlosurf << endl;\n\t\t\n\t\tif(edges_priority[i] < 10 && edges_priority[i] < edges_priority[j])\n\t\t  {\n\t\t    todelete.Set(i);\n\t\t  }\n\t\telse if (edges_priority[j] < 10 && edges_priority[i] > edges_priority[j])\n\t\t  {\n\t\t    todelete.Set(j);\n\t\t  }\n\t      }\n\t  }\n\t  \n      }\n    \n    int num = refedges.Size();\n\n    for(int i=refedges.Size()-1; num>2 && i>=0; i--)\n      if(todelete.Test(i))\n\t{\n\t  refedges.Delete(i);\n\t  refedgesinv.Delete(i);\n\t  num--;\n\t}\n\n    \n    if (debug)\n      {\n\t*testout << \"Refsegments: \" << endl << refedges << endl;\n      }\n  }\n\n\n\n  void EdgeCalculation :: \n  StoreEdge (const NgArray<Segment> & refedges,\n\t     const NgArray<bool> & refedgesinv,\n\t     const NgArray<Point<3> > & edgepoints,\n\t     const NgArray<double> & curvelength,\n\t     int layer,\n\t     Mesh & mesh)\n  {\n  \n    // Calculate optimal element-length\n    int i, j, k;\n    // PointIndex pi;\n    int ne;\n\n    double len, corr, lam;\n    PointIndex thispi, lastpi;\n    Point<3> p, np;\n    Segment seg;\n\n    const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1);\n    const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2);\n\n    (*testout) << \"s1 \" << refedges.Get(1).surfnr1 << \" s2 \" << refedges.Get(1).surfnr2\n\t       << \" rs1 \" << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr1)\n\t       << \" rs2 \" << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr2) << endl;\n\n    len = curvelength.Last();\n    ne = int (len + 0.5);\n    if (ne == 0) ne = 1;\n    if (Dist (edgepoints.Get(1), edgepoints.Last()) < 1e-8*geometry.MaxSize() && \n\tne <= 6) \n      ne = 6;\n    corr = len / ne;\n\n    // generate initial point\n    p = edgepoints.Get(1);\n    lastpi = PointIndex::INVALID;\n\n    /*\n    for (pi = IndexBASE<PointIndex>(); \n\t pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n      if (Dist (mesh[pi], p) < 1e-6)\n\t{\n\t  lastpi = pi;\n\t  break;\n\t}\n    */\n\n    const double di=1e-7*geometry.MaxSize();\n\n    NgArray<int> locsearch;\n    meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di),\n\t\t\t\t       p+Vec<3> (di,di,di), locsearch);\n    if (locsearch.Size())\n      lastpi = locsearch[0];\n\t\t\t\t       \n\n\n    if (!lastpi.IsValid())\n      {\n\tlastpi = mesh.AddPoint (p, layer, FIXEDPOINT);\n\tmeshpoint_tree -> Insert (p, lastpi); \n\t// (*testout) << \"test1, store point \" << lastpi << \", p = \" << p << endl;\n      }\n  \n    j = 1;\n    for (i = 1; i <= ne; i++)\n      {\n\twhile (curvelength.Get(j) < i * corr && j < curvelength.Size()) j++;\n\n\n\tlam = (i * corr - curvelength.Get(j-1)) / \n\t  (curvelength.Get(j) - curvelength.Get(j-1));\n\n\tnp(0) = (1-lam) * edgepoints.Get(j-1)(0) + lam * edgepoints.Get(j)(0);\n\tnp(1) = (1-lam) * edgepoints.Get(j-1)(1) + lam * edgepoints.Get(j)(1);\n\tnp(2) = (1-lam) * edgepoints.Get(j-1)(2) + lam * edgepoints.Get(j)(2);\n      \n        thispi = PointIndex::INVALID;\n\tif (i == ne)\n\t  {\n\t    /*\n\t  for (pi = IndexBASE<PointIndex>(); \n\t       pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n\t    if (Dist(mesh[pi], np) < 1e-6)\n\t      thispi = pi;\n\t    */\n\t    \n\t    meshpoint_tree -> GetIntersecting (np-Vec<3> (di,di,di),\n\t\t\t\t\t       np+Vec<3> (di,di,di), locsearch);\n\t    if (locsearch.Size())\n\t      thispi = locsearch[0];\n\t  }\n\n\tif (!thispi.IsValid())\n\t  {\n\t    ProjectToEdge (surf1, surf2, np);\n\t    thispi = mesh.AddPoint (np, layer, (i==ne) ? FIXEDPOINT : EDGEPOINT);\n\t   \n\t    meshpoint_tree -> Insert (np, thispi);\n\t    // (*testout) << \"test2, store point \" << thispi << \", p = \" << np << endl;\n\t  }\n\n\tfor (k = 1; k <= refedges.Size(); k++)\n\t  {\n\t    if (refedgesinv.Get(k))\n\t      {\n\t\tseg[0] = lastpi;\n\t\tseg[1] = thispi;\n\t      }\n\t    else\n\t      {\n\t\tseg[0] = thispi;\n\t\tseg[1] = lastpi;\n\t      }\n\t    seg.si = refedges.Get(k).si;\n\t    seg.domin = refedges.Get(k).domin;\n\t    seg.domout = refedges.Get(k).domout;\n\t    seg.tlosurf = refedges.Get(k).tlosurf;\n\t    seg.edgenr = refedges.Get(k).edgenr;\n\t    seg.index = refedges.Get(k).index;            \n\t    seg.surfnr1 = refedges.Get(k).surfnr1;\n\t    seg.surfnr2 = refedges.Get(k).surfnr2;\n\t    seg.seginfo = 0;\n\t    if (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1;\n\t    mesh.AddSegment (seg);\n\t    //(*testout) << \"add seg \" << mesh[seg.p1] << \"-\" << mesh[seg.p2] << endl;\n\t    //(*testout) << \"refedge \" << k << \" surf1 \" << seg.surfnr1 << \" surf2 \" << seg.surfnr2 << \" inv \" << refedgesinv.Get(k) << endl;\n\t  \n\t    double maxh = min2 (geometry.GetSurface(seg.surfnr1)->GetMaxH(),\n\t\t\t\tgeometry.GetSurface(seg.surfnr2)->GetMaxH());\n\t\t\t      \n\t    if (seg.domin != -1)\n\t      {\n\t\tconst Solid * s1 = \n\t\t  geometry.GetTopLevelObject(seg.domin) -> GetSolid();\n\t\tmaxh = min2 (maxh, s1->GetMaxH());\n\t\tmaxh = min2 (maxh, geometry.GetTopLevelObject(seg.domin)->GetMaxH());\n\t\tmesh.RestrictLocalH (p, maxh);\n\t\tmesh.RestrictLocalH (np, maxh);\n\t      }\n\t    if (seg.domout != -1)\n\t      {\n\t\tconst Solid * s1 = \n\t\t  geometry.GetTopLevelObject(seg.domout) -> GetSolid();\n\t\tmaxh = min2 (maxh, s1->GetMaxH());\n\t\tmaxh = min2 (maxh, geometry.GetTopLevelObject(seg.domout)->GetMaxH());\n\t\tmesh.RestrictLocalH (p, maxh);\n\t\tmesh.RestrictLocalH (np, maxh);\n\t      }\n\t    if (seg.tlosurf != -1)\n\t      {\n\t\tdouble hi = geometry.GetTopLevelObject(seg.tlosurf) -> GetMaxH();\n\t\tmaxh = min2 (maxh, hi);\n\t\tmesh.RestrictLocalH (p, maxh);\n\t\tmesh.RestrictLocalH (np, maxh);\n\t      }\t  \n\t  }\n      \n\tp = np;\n\tlastpi = thispi;\n      }\n\n#ifdef DEVELOP\n    (*testout) << \" eplast = \" << lastpi << \" = \" << p << endl;\n#endif\n  }\n  \n\n\n\n\n\n  void EdgeCalculation :: \n  StoreShortEdge (const NgArray<Segment> & refedges,\n\t\t  const NgArray<bool> & refedgesinv,\n\t\t  const NgArray<Point<3> > & edgepoints,\n\t\t  const NgArray<double> & curvelength,\n\t\t  int layer,\n\t\t  Mesh & mesh)\n  {\n  \n    // Calculate optimal element-length\n    PointIndex pi;\n    // int ne;\n    Segment seg;\n\n    /*\n      double len, corr, lam;\n      int thispi, lastpi;\n      Point<3> p, np;\n\n\n      const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1);\n      const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2);\n\n      len = curvelength.Last();\n      ne = int (len + 0.5);\n      if (ne == 0) ne = 1;\n      if (Dist2 (edgepoints[1], edgepoints.Last()) < 1e-8 && \n      ne <= 6) \n      ne = 6;\n      corr = len / ne;\n    */\n\n    // generate initial point\n    Point<3> p = edgepoints[0];\n    PointIndex pi1 = PointIndex::INVALID;\n    for (PointIndex pi = IndexBASE<PointIndex>(); \n\t pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n\n      if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())\n\t{\n\t  pi1 = pi;\n\t  break;\n\t}\n\n    if (!pi1.IsValid())\n      {\n\tpi1 = mesh.AddPoint (p, layer, FIXEDPOINT);\n\tmeshpoint_tree -> Insert (p, pi1);\n\t// (*testout) << \"test3, store point \" << pi1 << \", p = \" << p << endl;\n      }\n\n    p = edgepoints.Last();\n    PointIndex pi2 = PointIndex::INVALID;\n    for (pi = IndexBASE<PointIndex>(); \n\t pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n\n      if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())\n\t{\n\t  pi2 = pi;\n\t  break;\n\t}\n    if (!pi2.IsValid())\n      {\n\tpi2 = mesh.AddPoint (p, layer, FIXEDPOINT);\n\tmeshpoint_tree -> Insert (p, pi2);\n\t// (*testout) << \"test4, store point \" << pi2 << \", p = \" << p << endl;\n      }\n\n    /*\n  \n    j = 1;\n    for (i = 1; i <= ne; i++)\n    {\n    while (curvelength[j] < i * corr && j < curvelength.Size()) j++;\n      \n    lam = (i * corr - curvelength[j-1]) / \n    (curvelength[j] - curvelength[j-1]);\n      \n    np(0) = (1-lam) * edgepoints[j-1](0) + lam * edgepoints[j](0);\n    np(1) = (1-lam) * edgepoints[j-1](1) + lam * edgepoints[j](1);\n    np(2) = (1-lam) * edgepoints[j-1](2) + lam * edgepoints[j](2);\n      \n      \n    thispi = 0;\n    if (i == ne)\n    for (j = 1; j <= mesh.GetNP(); j++)\n    if (Dist(mesh.Point(j), np) < 1e-6)\n    thispi = j;\n      \n    if (!thispi)\n    {\n    ProjectToEdge (surf1, surf2, np);\n    thispi = mesh.AddPoint (np);\n    }\n    */\n\n    // (*testout) << \"short edge \" << pi1 << \" - \" << pi2 << endl;\n  \n    for (int k = 1; k <= refedges.Size(); k++)\n      {\n\tif (refedgesinv.Get(k))\n\t  {\n\t    seg[0] = pi1;\n\t    seg[1] = pi2;\n\t  }\n\telse\n\t  {\n\t    seg[0] = pi2;\n\t    seg[1] = pi1;\n\t  }\n\n\tseg.si = refedges.Get(k).si;\n\tseg.domin = refedges.Get(k).domin;\n\tseg.domout = refedges.Get(k).domout;\n\tseg.tlosurf = refedges.Get(k).tlosurf;\n\tseg.edgenr = refedges.Get(k).edgenr;\n\tseg.index = refedges.Get(k).index;        \n\tseg.surfnr1 = refedges.Get(k).surfnr1;\n\tseg.surfnr2 = refedges.Get(k).surfnr2;\n\tseg.seginfo = 0;\n\tif (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1;\n\tmesh.AddSegment (seg);\n\t//\t  (*testout) << \"add seg \" << seg[0] << \"-\" << seg[1] << endl;\n      }\n  }\n  \n\n\n\n\n\n\n  void EdgeCalculation :: \n  CopyEdge (const NgArray<Segment> & refedges,\n\t    const NgArray<bool> & refedgesinv,\n\t    int copyfromedge, \n\t    const Point<3> & fromstart, const Point<3> & fromend,\n\t    const Point<3> & tostart, const Point<3> & toend,\n\t    int copyedgeidentification, \n\t    int layer,\n\t    Mesh & mesh)\n  {\n    int k;\n    // PointIndex pi;\n\n    double size = geometry.MaxSize();\n    \n    // copy start and end points\n    for (int i = 1; i <= 2; i++)\n      {\n\tPoint<3> fromp =\n\t  (i == 1) ? fromstart : fromend;\n\tPoint<3> top =\n\t  (i == 1) ? tostart : toend;\n      \n\tPointIndex frompi = PointIndex::INVALID;\n\tPointIndex topi = PointIndex::INVALID;\n\tfor (PointIndex pi = IndexBASE<PointIndex>(); \n\t     pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n\t  {\n\t    if (Dist2 (mesh[pi], fromp) <= 1e-16*size)\n\t      frompi = pi;\n\t    if (Dist2 (mesh[pi], top) <= 1e-16*size)\n\t      topi = pi;\n\t  }\n\n\t\n\tif (!topi.IsValid())\n\t  {\n\t    topi = mesh.AddPoint (top, layer, FIXEDPOINT);\n\t    meshpoint_tree -> Insert (top, topi);\n\t  }\n\n\tconst Identification & csi = \n\t  (*geometry.identifications.Get(copyedgeidentification));\n\n\n\tif (csi.Identifiable (mesh[frompi], mesh[topi]))\n\t  mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification);\n\telse if (csi.Identifiable (mesh[topi], mesh[frompi]))\n\t  mesh.GetIdentifications().Add(topi, frompi, copyedgeidentification);\n\telse\n\t  {\n\t    cerr << \"edgeflw.cpp: should identify, but cannot\";\n\t    exit(1);\n\t  }\n#ifdef DEVELOP\n\t(*testout) << \"adding identification \" << mesh[frompi] << \"; \" << mesh[topi]\n\t\t   << \" (id \" << copyedgeidentification <<\")\" << endl;\n#endif\n\n\n\t/*\n\t  (*testout) << \"Add Identification from CopyEdge, p1 = \" \n\t  << mesh[PointIndex(frompi)] << \", p2 = \" \n\t  << mesh[PointIndex(topi)] << endl;\n\n\t  mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification);\n\t*/\n      }\n\n    int oldns = mesh.GetNSeg();\n    for (int i = 1; i <= oldns; i++)\n      {\n\t// real copy, since array might be reallocated !!\n\tconst Segment oldseg = mesh.LineSegment(i);\n\tif (oldseg.edgenr != copyfromedge)\n\t  continue;\n\tif (oldseg.seginfo == 0)\n\t  continue;\n\n\tPointIndex pi1 = oldseg[0];\n\tPointIndex pi2 = oldseg[1];\n\n\tPointIndex npi1 = geometry.identifications.Get(copyedgeidentification)\n\t  -> GetIdentifiedPoint (mesh, pi1);\n\tPointIndex npi2 = geometry.identifications.Get(copyedgeidentification)\n\t  -> GetIdentifiedPoint (mesh, pi2);\n\n\t//(*testout) << \"copy edge, pts = \" << npi1 << \" - \" << npi2 << endl;\n\n\tSegment seg;\n\n\tfor (k = 1; k <= refedges.Size(); k++)\n\t  {\n\t    bool inv = refedgesinv.Get(k);\n\n\t    // other edge is inverse\n\t    if (oldseg.seginfo == 1)\n\t      inv = !inv;\n\n\t    //\t  (*testout) << \"inv, now = \" << inv << endl;\n\n\t    if (inv)\n\t      {\n\t\tseg[0] = npi1;\n\t\tseg[1] = npi2;\n\t      }\n\t    else\n\t      {\n\t\tseg[0] = npi2;\n\t\tseg[1] = npi1;\n\t      }\n\t    seg.si = refedges.Get(k).si;\n\t    seg.domin = refedges.Get(k).domin;\n\t    seg.domout = refedges.Get(k).domout;\n\t    seg.tlosurf = refedges.Get(k).tlosurf;\n\t    seg.edgenr = refedges.Get(k).edgenr;\n\t    seg.index = refedges.Get(k).index;            \n\t    seg.surfnr1 = refedges.Get(k).surfnr1;\n\t    seg.surfnr2 = refedges.Get(k).surfnr2;\n\t    seg.seginfo = 0;\n\t    if (k == 1) seg.seginfo = refedgesinv.Get(k) ? 2 : 1;\n\t    mesh.AddSegment (seg);\n\t    //\t  (*testout) << \"copy seg \" << seg[0] << \"-\" << seg[1] << endl;\n#ifdef DEVELOP\n\n\t    (*testout) << \"copy seg, face = \" << seg.si << \": \" \n\t\t       << \" inv = \" << inv << \", refinv = \" << refedgesinv.Get(k)\n\t\t       << mesh.Point(seg[0]) << \", \" << mesh.Point(seg[1]) << endl;\n#endif\n\n\t  }\n      \n      }   \n  }\n  \n\n\n\n\n\n\n  void EdgeCalculation :: \n  FindClosedSurfaces (double h, Mesh & mesh)\n  {\n    // if there is no special point at a sphere, one has to add a segment pair\n  \n    int nsurf = geometry.GetNSurf();\n    int layer = 0;\n\n    // Solid * tansol;\n    NgArray<int> tansurfind;\n\n    double size = geometry.MaxSize();\n    int nsol = geometry.GetNTopLevelObjects();\n    \n\n    NgBitArray pointatsurface (nsurf);\n    pointatsurface.Clear();\n  \n    for (int i = 1; i <= mesh.GetNSeg(); i++)\n      {\n\tconst Segment & seg = mesh.LineSegment(i);\n\n#ifdef DEVELOP      \n\t(*testout) << seg.surfnr1 << \", \" << seg.surfnr2 << \", si = \" << seg.si << endl;\n#endif\n\tint classrep = geometry.GetSurfaceClassRepresentant (seg.si);\n\tpointatsurface.Set (classrep);\n      }\n\n  \n    for (int i = 0; i < nsurf; i++)\n      {\n\tint classrep = geometry.GetSurfaceClassRepresentant (i);\n\n\tif (!pointatsurface.Test(classrep))\n\t  {\n\t    const Surface * s = geometry.GetSurface(i);\n\t    Point<3> p1 = s -> GetSurfacePoint();\n\t    Vec<3> nv = s -> GetNormalVector (p1);\n\t\t    \n\t    double hloc = \n\t      min2 (s->LocH (p1, 3, 1, mparam, h), mesh.GetH(p1));\n\n\t  \n\t\t    \n\t    Segment seg1;\n\t    seg1.si = i;\n\t    seg1.domin = -1;\n\t    seg1.domout = -1;\n\n\t    Segment seg2;\n\t    seg2.si = i;\n\t    seg2.domin = -1;\n\t    seg2.domout = -1;\n\n\t    seg1.surfnr1 = i;\n\t    seg2.surfnr1 = i;\n\t    seg1.surfnr2 = i;\n\t    seg2.surfnr2 = i;\n\n\t    for (int j = 0; j < nsol; j++)\n\t      {\n\t\tif (geometry.GetTopLevelObject(j)->GetSurface())\n\t\t  continue;\n\t\t  \n\t\tconst Solid * sol = geometry.GetTopLevelObject(j)->GetSolid();\n\t\t// sol -> TangentialSolid (p1, tansol, tansurfind, ideps*size);\n                auto tansol = sol -> TangentialSolid (p1, tansurfind, ideps*size);\n\t\tlayer = geometry.GetTopLevelObject(j)->GetLayer();\n\n\t\t\n\t\tif (tansol)\n\t\t  {\n\t\t    tansol -> GetSurfaceIndices (tansurfind);\n\t\t\n\t\t    if (tansurfind.Size() == 1 && tansurfind.Get(1) == i)\n\t\t      {\n\t\t\thloc = min2 (hloc, geometry.GetTopLevelObject(j)->GetMaxH());\n\n\t\t\tif (!tansol->VectorIn(p1, nv))\n\t\t\t  {\n\t\t\t    seg1.domin = j;\n\t\t\t    seg2.domin = j;\n\t\t\t    seg1.tlosurf = -1;\n\t\t\t    seg2.tlosurf = -1;\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    seg1.domout = j;\n\t\t\t    seg2.domout = j;\n\t\t\t    seg1.tlosurf = -1;\n\t\t\t    seg2.tlosurf = -1;\n\t\t\t  }\n\t\t\t//        seg.s2 = i;\n\t\t\t//        seg.invs1 = surfaces[i] -> Inverse();\n\t\t\t//        seg.invs2 = ! (surfaces[i] -> Inverse());\n\t\t      }\n\t\t    // delete tansol;\n\t\t  }\n\t      }\n\n\t    \n\t    Vec<3> tv = nv.GetNormal ();\n\t    tv *=  (hloc / tv.Length());\n\t    Point<3> p2 = p1 + tv;\n\t    s->Project (p2);\n\n\n\t    if (seg1.domin != -1 || seg1.domout != -1)\n\t      {\n                seg1[0] = mesh.AddPoint (p1, layer, EDGEPOINT);\n                seg1[1] = mesh.AddPoint (p2, layer, EDGEPOINT);\n                seg2[0] = seg1[1];\n                seg2[1] = seg1[0];\n\t\tseg1.geominfo[0].trignum = 1;\n\t\tseg1.geominfo[1].trignum = 1;\n\t\tseg2.geominfo[0].trignum = 1;\n\t\tseg2.geominfo[1].trignum = 1;\n\t\tmesh.AddSegment (seg1);\n\t\tmesh.AddSegment (seg2);\n\n\t\tPrintMessage (5, \"Add line segment to smooth surface\");\n\n#ifdef DEVELOP\n\t\t(*testout) << \"Add segment at smooth surface \" << i;\n\t\tif (i != classrep) (*testout) << \", classrep = \" << classrep;\n\t\t(*testout) << \": \"\n\t\t\t   << mesh.Point (mesh.GetNP()-1) << \" - \"\n\t\t\t   << mesh.Point (mesh.GetNP()) << endl;\n#endif\n\t      }\n\t  }\n      }\n  }\n\n}\n"
  },
  {
    "path": "libsrc/csg/edgeflw.hpp",
    "content": "#ifndef FILE_EDGEFLW\n#define FILE_EDGEFLW\n\n/**************************************************************************/\n/* File:   edgeflw.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n\n  /*\n  \n  Edge - following function and\n  Projection to edge of implicitly given edge\n\n  */\n \n\n  /**\n     Calculates edges.\n     The edges of a solid geometry are computed. Special\n     points have to be given.\n  */\n  extern void CalcEdges (const CSGeometry & geometry,\n\t\t\t const NgArray<SpecialPoint> & specpoints,\n\t\t\t double h, Mesh & mesh);\n\n\n\n\n\n  class EdgeCalculation\n  {\n    const CSGeometry & geometry;\n    NgArray<SpecialPoint> & specpoints;\n    Point3dTree * searchtree;\n    Point3dTree * meshpoint_tree;\n    int cntedge;\n\n    double ideps;\n    MeshingParameters & mparam;\n\n  public:\n    EdgeCalculation (const CSGeometry & ageometry,\n\t\t     NgArray<SpecialPoint> & aspecpoints,\n                     MeshingParameters & amparam);\n\n    ~EdgeCalculation();\n\n    void SetIdEps(const double epsin) {ideps = epsin;}\n\n    void Calc(double h, Mesh & mesh);\n\n\n  private:\n    void CalcEdges1 (double h, Mesh & mesh);\n  \n\n    void FollowEdge (int pi1, int & ep, int & pos,\n\t\t     // const NgArray<SpecialPoint> & hsp,\n\t\t     const NgArray<int> & hsp,\n\t\t     double h, const Mesh & mesh,\n\t\t     NgArray<Point<3> > & edgepoints,\n\t\t     NgArray<double> & curvelength);\n\t\t   \n\n    void AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer,\n\t\t      const NgArray<Point<3> > & edgepoints,\n\t\t      NgArray<Segment> & refedges,\n\t\t      NgArray<bool> & refedgesinv);\n\n    void StoreEdge (const NgArray<Segment> & refedges,\n\t\t    const NgArray<bool> & refedgesinv,\n\t\t    const NgArray<Point<3> > & edgepoints,\n\t\t    const NgArray<double> & curvelength,\n\t\t    int layer,\n\t\t    Mesh & mesh);\n\n    void StoreShortEdge (const NgArray<Segment> & refedges,\n\t\t\t const NgArray<bool> & refedgesinv,\n\t\t\t const NgArray<Point<3> > & edgepoints,\n\t\t\t const NgArray<double> & curvelength,\n\t\t\t int layer,\n\t\t\t Mesh & mesh);\n\n    void CopyEdge (const NgArray<Segment> & refedges,\n\t\t   const NgArray<bool> & refedgesinv,\n\t\t   int copyfromedge, \n\t\t   const Point<3> & fromstart, const Point<3> & fromend,\n\t\t   const Point<3> & tostart, const Point<3> & toend,\n\t\t   int copyedgeidentification,\n\t\t   int layer,\n\t\t   Mesh & mesh);\n\n  \n    void SplitEqualOneSegEdges (Mesh & mesh);\n    void FindClosedSurfaces (double h, Mesh & mesh);\n\n\n  public:\n    bool point_on_edge_problem;\n\n  };\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/explicitcurve2d.cpp",
    "content": "#include <mystdlib.h>\n#include <csg.hpp>\n\nnamespace netgen\n{\nExplicitCurve2d :: ExplicitCurve2d ()\n  {\n    ;\n  }\n  \n  \nvoid ExplicitCurve2d :: Project (Point<2> & p) const\n  {\n  double t;\n  t = ProjectParam (p);\n  p = Eval (t);\n  }\n\ndouble ExplicitCurve2d :: NumericalProjectParam (const Point<2> & p, double lb, double ub) const\n  {\n  double t(-1);\n  Vec<2> tan;\n  Vec<2> curv;\n  Point<2> cp;\n  double f, fl, fu;\n  int cnt;\n  \n  tan = EvalPrime (lb);\n  cp = Eval (lb);\n  fl = tan * (cp - p);\n  if (fl > 0)\t\t\t// changed by wmf, originally fl >= 0\n    {\n      //      cerr << \"tan = \" << tan << \" cp - p = \" << (cp - p) << endl;\n      //      cerr << \"ExplicitCurve2d::NumericalProject: lb wrong\" << endl;\n      return 0;\n    }\n  \n  tan = EvalPrime (ub);\n  cp = Eval (ub);\n  fu = tan * (cp - p);\n  if (fu < 0)\t\t\t// changed by wmf, originally fu <= 0\n    {\n      //    cerr << \"tan = \" << tan << \" cp - p = \" << (cp - p) << endl;\n      //    cerr << \"ExplicitCurve2d::NumericalProject: ub wrong\" << endl;\n    return 0;\n    }\n    \n  cnt = 0;\n  while (ub - lb > 1e-12 && fu - fl > 1e-12)\n    {\n    cnt++;\n    if (cnt > 50)\n      {\n      (*testout) << \"Num Proj, cnt = \" << cnt << endl;\n      }\n     \n    t = (lb * fu - ub * fl) / (fu - fl);\n    if (t > 0.9 * ub + 0.1 * lb) t = 0.9 * ub + 0.1 * lb;\n    if (t < 0.1 * ub + 0.9 * lb) t = 0.1 * ub + 0.9 * lb;\n    \n    tan = EvalPrime (t);\n    cp = Eval (t);\n    f = tan * (cp - p);\n    \n    if (f >= 0)\n      {\n      ub = t;\n      fu = f;\n      }\n    else\n      {\n      lb = t;\n      fl = f;\n      }\n    }\n    \n  return t;\n  }\n\n\nVec<2> ExplicitCurve2d :: Normal (double t) const\n{\n  Vec<2> tan = EvalPrime (t);\n  tan.Normalize();\n  return Vec<2> (tan(1), -tan(0));\n}\n\n\nvoid ExplicitCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const\n  {\n  double t = ProjectParam (p);\n  n = Normal (t);\n  }\n\n\nPoint<2> ExplicitCurve2d :: CurvCircle (double t) const\n  {\n  Point<2> cp;\n  Vec<2> tan, n, curv;\n  double den;\n  \n  cp = Eval (t);\n  tan = EvalPrime (t);\n  n = Normal (t);\n  curv = EvalPrimePrime (t);\n  \n  den = n * curv;\n  if (fabs (den) < 1e-12)\n    return cp + 1e12 * n;  \n    \n  return cp + (tan.Length2() / den) * n;  \n  }\n\n\ndouble ExplicitCurve2d :: MaxCurvature () const\n  {\n  double t, tmin, tmax, dt;\n  double curv;\n  Vec<2> tan;\n  double maxcurv;\n\n  maxcurv = 0;  \n  \n  tmin = MinParam ();\n  tmax = MaxParam ();\n  dt = (tmax - tmin) / 1000;\n  for (t = tmin; t <= tmax+dt; t += dt)\n    if (SectionUsed (t))\n      {\n      tan = EvalPrime (t);\n      curv = fabs ( (Normal(t) * EvalPrimePrime(t)) / tan.Length2());\n      if (curv > maxcurv) maxcurv = curv; \n      }\n  return maxcurv;\n  }  \n  \ndouble ExplicitCurve2d :: MaxCurvatureLoc (const Point<2> & p, double rad) const\n  {\n  double t, tmin, tmax, dt;\n  double curv;\n  Vec<2> tan;\n  double maxcurv;\n\n  maxcurv = 0;  \n  \n  tmin = MinParam ();\n  tmax = MaxParam ();\n  dt = (tmax - tmin) / 1000;\n  for (t = tmin; t <= tmax+dt; t += dt)\n    if (Dist (Eval(t), p) < rad)\n      {\n      tan = EvalPrime (t);\n      curv = fabs ( (Normal(t) * EvalPrimePrime(t)) / tan.Length2());\n      if (curv > maxcurv) maxcurv = curv; \n      }\n    \n  return maxcurv;\n  }  \n  \n}\n"
  },
  {
    "path": "libsrc/csg/explicitcurve2d.hpp",
    "content": "#ifndef FILE_EXPLICITCURVE2D\n#define FILE_EXPLICITCURVE2D\n\n/**************************************************************************/\n/* File:   explicitcurve2d.hh                                             */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   14. Oct. 96                                                    */\n/**************************************************************************/\n\n\nnamespace netgen\n{\n\n  /*\n\n  Explicit 2D Curve representation\n\n  */\n\n\n\n  ///\n  class ExplicitCurve2d : public Curve2d\n  {\n  public:\n    ///\n    ExplicitCurve2d ();\n\n    ///\n    virtual void Project (Point<2> & p) const;\n    ///\n    virtual double ProjectParam (const Point<2> & p) const = 0;\n    ///\n    virtual double NumericalProjectParam (const Point<2> & p, double lb, double ub) const;\n    ///\n    virtual double MinParam () const = 0;\n    ///\n    virtual double MaxParam () const = 0;\n    ///\n    virtual Point<2> Eval (double t) const = 0;\n    ///\n    virtual Vec<2> EvalPrime (double t) const = 0;\n    ///\n    virtual Vec<2> Normal (double t) const;\n    ///\n    virtual void NormalVector (const Point<2> & p, Vec<2> & n) const;\n    ///\n    virtual Vec<2> EvalPrimePrime (double t) const = 0;\n\n    ///\n    virtual double MaxCurvature () const;\n    ///\n    virtual double MaxCurvatureLoc (const Point<2> & p, double rad) const;\n\n    ///\n    virtual Point<2> CurvCircle (double t) const;\n    ///\n    virtual void Print (ostream & /* str */) const { };\n  \n    ///\n    virtual int SectionUsed (double /* t */) const { return 1; }\n    ///\n    virtual void Reduce (const Point<2> & /* p */, double /* rad */) { };\n    ///\n    virtual void UnReduce () { };\n  }; \n  \n  \n  ///\n  class BSplineCurve2d : public ExplicitCurve2d\n  {\n    ///\n    NgArray<Point<2> > points;\n    ///\n    NgArray<int> intervallused;\n    ///\n    int redlevel;\n  \n  public:\n    ///\n    BSplineCurve2d ();\n    ///\n    void AddPoint (const Point<2> & apoint);\n\n    bool Inside (const Point<2> & p, double & dist) const;\n  \n    ///\n    virtual double ProjectParam (const Point<2> & p) const;\n    ///\n    virtual double MinParam () const { return 0; }\n    ///\n    virtual double MaxParam () const { return points.Size(); }\n    ///\n    virtual Point<2> Eval (double t) const;\n    ///\n    virtual Vec<2> EvalPrime (double t) const;  \n    ///\n    virtual Vec<2> EvalPrimePrime (double t) const;\n    ///\n    virtual void Print (ostream & str) const;\n\n    ///\n    virtual int SectionUsed (double t) const;\n    ///\n    virtual void Reduce (const Point<2> & p, double rad);\n    ///\n    virtual void UnReduce ();\n  };  \n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/extrusion.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n  NgArray<Point<3> > project1, project2;\n\n\n\n  void ExtrusionFace :: Init(void)\n  {\n    p0.SetSize(path->GetNSplines());\n    x_dir.SetSize(path->GetNSplines());\n    y_dir.SetSize(path->GetNSplines());\n    z_dir.SetSize(path->GetNSplines());\n    loc_z_dir.SetSize(path->GetNSplines());\n    spline3_path.SetSize(path->GetNSplines());\n    line_path.SetSize(path->GetNSplines());\n\n    for(int i=0; i<path->GetNSplines(); i++)\n      {\n\tspline3_path[i] = dynamic_cast < const SplineSeg3<3>* >(&path->GetSpline(i));\n\tline_path[i] = dynamic_cast < const LineSeg<3>* >(&path->GetSpline(i));\n\t\n\tif(line_path[i])\n\t  {\n\t    y_dir[i] = line_path[i]->EndPI() - line_path[i]->StartPI();\n\t    y_dir[i].Normalize();\n\t    z_dir[i] = glob_z_direction;\n\t    Orthogonalize(y_dir[i],z_dir[i]);\n\t    x_dir[i] = Cross(y_dir[i],z_dir[i]);\n\t    loc_z_dir[i] = z_dir[i];\n\t  }\n\telse\n\t  {\n\t    z_dir[i] = glob_z_direction;\n\t    loc_z_dir[i] = glob_z_direction;\n\t  }\n      }\n\n    double cum_angle = 0.;\n    for(auto i : Range(path->GetSplines()))\n      {\n        const auto& sp = path->GetSpline(i);\n        auto t1 = sp.GetTangent(0.);\n        t1.Normalize();\n        auto t2 = sp.GetTangent(1.);\n        t2.Normalize();\n        cum_angle += acos(t1 * t2);\n        angles.Append(cum_angle);\n      }\n    \n    profile->GetCoeff(profile_spline_coeff);\n    latest_point3d = -1.111e30;\n  }\n\n  \n  ExtrusionFace :: ExtrusionFace(const SplineSeg<2> * profile_in,\n\t\t\t\t const SplineGeometry<3> * path_in,\n\t\t\t\t const Vec<3> & z_direction) :\n    profile(profile_in), path(path_in), glob_z_direction(z_direction)\n  {\n    deletable = false;\n\n    Init();\n  }\n\n  ExtrusionFace :: ExtrusionFace(const NgArray<double> & raw_data)\n  {\n    deletable = true;\n\n    int pos=0;\n\n    NgArray< Point<2> > p(3);\n\n    int ptype = int(raw_data[pos]); pos++;\n\n    for(int i=0; i<ptype; i++)\n      {\n\tp[i](0) = raw_data[pos]; pos++;\n\tp[i](1) = raw_data[pos]; pos++;\n      }\n    if(ptype == 2)\n      {\n\tprofile = new LineSeg<2>(GeomPoint<2>(p[0],1),\n\t\t\t\t GeomPoint<2>(p[1],1));\n      }\n    else if(ptype == 3)\n      {\n\tprofile = new SplineSeg3<2>(GeomPoint<2>(p[0],1),\n\t\t\t\t    GeomPoint<2>(p[1],1),\n\t\t\t\t    GeomPoint<2>(p[2],1));\n      }\n\n    path = new SplineGeometry<3>;\n    pos = const_cast< SplineGeometry<3> *>(path)->Load(raw_data,pos);\n\n    for(int i = 0; i < 3; i++)\n      {\n\tglob_z_direction(i) = raw_data[pos]; \n\tpos++;\n      }\n    \n    Init();\n  }\n\n  ExtrusionFace :: ~ExtrusionFace()\n  {\n    if(deletable)\n      {\n\tdelete profile;\n\tdelete path;\n      }\n  }\n\n  \n  int ExtrusionFace :: IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const ExtrusionFace * ext2 = dynamic_cast<const ExtrusionFace*>(&s2);\n\n    if(!ext2) return 0;\n\n    if(ext2 == this)\n      return 1;\n\n    return 0;\n  } \n  \n  void ExtrusionFace :: Orthogonalize(const Vec<3> & v1, Vec<3> & v2) const\n  {\n    v2 -= (v1*v2)*v1;\n    v2.Normalize();\n  }\n\n\n  void ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t\t\t int & seg, double & t) const\n  {\n    static mutex set_latest_point;\n\n    auto eps = 1e-25 * Dist2(path->GetSpline(0).StartPI(), path->GetSpline(0).EndPI());\n    if (Dist2 (point3d, latest_point3d) < eps)\n      {\n        std::lock_guard<std::mutex> guard(set_latest_point);\n        if (Dist2 (point3d, latest_point3d) < eps)\n        {\n            point2d = latest_point2d;\n            seg = latest_seg;\n            t = latest_t;\n            return;\n        }\n      }\n    \n\n    double cutdist = -1;\n    \n\n    NgArray<double> mindist(path->GetNSplines());\n\n    for(int i = 0; i < path->GetNSplines(); i++)\n      {\n\tdouble auxcut = -1;\n\tdouble auxmin = -1;\n\n\tif(spline3_path[i])\n\t  {\n\t    Point<3> startp(path->GetSpline(i).StartPI());\n\t    Point<3> endp(path->GetSpline(i).EndPI());\n\t    Point<3> tanp(spline3_path[i]->TangentPoint());\n            \n            // lower bound for dist\n            auxmin = sqrt (MinDistTP2 (startp, endp, tanp, point3d)); \n            \n            // upper bound for dist\n            auxcut = min2 (Dist (startp, point3d), Dist (endp, point3d));\n\t  }\n\telse if(line_path[i])\n\t  {\n            auxmin = auxcut = sqrt (MinDistLP2 (path->GetSpline(i).StartPI(),\n                                                path->GetSpline(i).EndPI(),\n                                                point3d));\n\t  }\n\t\n\tmindist[i] = auxmin;\n\t\n\tif(i==0 || auxcut < cutdist)\n\t  cutdist = auxcut;\n      }\n\t\n\n\n    Point<2> testpoint2d;\n    Point<3> testpoint3d;\n    \n    double minproj(-1);\n    bool minproj_set(false);\n\n\n\n    for(int i=0; i<path->GetNSplines(); i++)\n      {\n\tif(mindist[i] > cutdist*(1+1e-10)) continue;\n\n\tdouble thist = CalcProj(point3d,testpoint2d,i);\n\n\ttestpoint3d = p0[i] + testpoint2d(0)*x_dir[i] + testpoint2d(1)*loc_z_dir[i];\n\tdouble d = Dist2(point3d,testpoint3d);\n\n\n\tif(!minproj_set || d < minproj)\n\t  {\n\t    minproj_set = true;\n\t    minproj = d;\n\t    point2d = testpoint2d;\n\t    t = thist;\n\t    seg = i;\n\t  }\n      }\n    std::lock_guard<std::mutex> guard(set_latest_point);\n    latest_seg = seg;\n    latest_t = t;\n    latest_point2d = point2d;\n    latest_point3d = point3d;\n  }\n\n  double ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t\t\t   int seg) const\n  {\n    double t = -1;\n\n    if(line_path[seg])\n      {\n\tpoint2d(0) = (point3d-line_path[seg]->StartPI())*x_dir[seg];\n\tpoint2d(1) = (point3d-line_path[seg]->StartPI())*z_dir[seg];\n\tdouble l = Dist(line_path[seg]->StartPI(),\n\t\t\tline_path[seg]->EndPI());\n\tt = min2(max2((point3d - line_path[seg]->StartPI()) * y_dir[seg],0.),\n\t\t l);\t\n\tp0[seg] = line_path[seg]->StartPI() + t*y_dir[seg];\n\tt *= 1./l;\n      }\n    else if(spline3_path[seg])\n      {\n\tspline3_path[seg]->Project(point3d,p0[seg],t);\n\t\n\ty_dir[seg] = spline3_path[seg]->GetTangent(t); \n        y_dir[seg].Normalize();\n\tloc_z_dir[seg] = z_dir[seg];\n\tOrthogonalize(y_dir[seg],loc_z_dir[seg]);\n\tx_dir[seg] = Cross(y_dir[seg],loc_z_dir[seg]);\n\tVec<3> dir = point3d-p0[seg];\n\tpoint2d(0) = x_dir[seg]*dir;\n\tpoint2d(1) = loc_z_dir[seg]*dir;\t\n      }\n    return t;\n  }\n\n\n\n  double ExtrusionFace :: CalcFunctionValue (const Point<3> & point) const\n  {\n    Point<2> p;\n\n    double dummyd;\n    int dummyi;\n\n    CalcProj(point, p, dummyi, dummyd);\n\n    return \n      profile_spline_coeff(0)*p(0)*p(0) + \n      profile_spline_coeff(1)*p(1)*p(1) + \n      profile_spline_coeff(2)*p(0)*p(1) + \n      profile_spline_coeff(3)*p(0) + \n      profile_spline_coeff(4)*p(1) + \n      profile_spline_coeff(5);    \n  }\n\n\n\n\n  void ExtrusionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const\n  {\n    Point<2> p2d;\n\n    double t_path;\n    int seg;\n    CalcProj (point, p2d, seg, t_path);\n\n\n    Point<3> phi;\n    Vec<3> phip, phipp, phi_minus_point;\n\n    path->GetSpline(seg).GetDerivatives(t_path, phi, phip, phipp);\n    phi_minus_point = phi-point;\n\n    Vec<3> grad_t = (1.0/(phipp*phi_minus_point + phip*phip)) * phip;\n    Vec<3> grad_xbar, grad_ybar;\n\n    Vec<3> hex, hey, hez, dex, dey, dez;\n    CalcLocalCoordinatesDeriv (seg, t_path, hex, hey, hez, dex, dey, dez);\n\n    grad_xbar = hex - (phi_minus_point*dex + hex*phip) * grad_t;\n    grad_ybar = hez - (phi_minus_point*dez + hez*phip) * grad_t;\n\n    double dFdxbar = 2.*profile_spline_coeff(0)*p2d(0) +\n      profile_spline_coeff(2)*p2d(1) + profile_spline_coeff(3);\n\n    double dFdybar = 2.*profile_spline_coeff(1)*p2d(1) +\n      profile_spline_coeff(2)*p2d(0) + profile_spline_coeff(4);\n    \n\n    grad = dFdxbar * grad_xbar + dFdybar * grad_ybar;    \n  }\n\n  void ExtrusionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const\n  {\n    const double eps = 1e-7*Dist(path->GetSpline(0).StartPI(),path->GetSpline(0).EndPI());\n    \n\n    Point<3> auxpoint1(point),auxpoint2(point);\n    Vec<3> auxvec,auxgrad1,auxgrad2;\n\n    for(int i=0; i<3; i++)\n      {\n\tauxpoint1(i) -= eps;\n\tauxpoint2(i) += eps;\n\tCalcGradient(auxpoint1,auxgrad1);\n\tCalcGradient(auxpoint2,auxgrad2);\n\tauxvec = (1./(2.*eps)) * (auxgrad2-auxgrad1);\n\tfor(int j=0; j<3; j++)\n\t  hesse(i,j) = auxvec(j);\n\tauxpoint1(i) = point(i);\n\tauxpoint2(i) = point(i);\n      }\n\n    /*\n    Vec<3> grad;\n    CalcGradient(point,grad);\n\n    Point<3> auxpoint(point);\n    Vec<3> auxvec,auxgrad;\n\n    for(int i=0; i<3; i++)\n      {\n\tauxpoint(i) -= eps;\n\tCalcGradient(auxpoint,auxgrad);\n\tauxvec = (1./eps) * (grad-auxgrad);\n\tfor(int j=0; j<3; j++)\n\t  hesse(i,j) = auxvec(j);\n\tauxpoint(i) = point(i);\n      }\n    */\n\n    \n    for(int i=0; i<3; i++)\n      for(int j=i+1; j<3; j++)\n\thesse(i,j) = hesse(j,i) = 0.5*(hesse(i,j)+hesse(j,i));\n  }\n  \n\n\n  double ExtrusionFace :: HesseNorm () const\n  {\n    return fabs(profile_spline_coeff(0) + profile_spline_coeff(1)) +\n      sqrt(pow(profile_spline_coeff(0)+profile_spline_coeff(1),2)+4.*pow(profile_spline_coeff(2),2));\n  }\n\n  double ExtrusionFace :: MaxCurvature () const\n  {\n    double retval,actmax;\n    \n    retval = profile->MaxCurvature();\n    for(int i=0; i<path->GetNSplines(); i++)\n      {\n\tactmax = path->GetSpline(i).MaxCurvature();\n\tif(actmax > retval)\n\t  retval = actmax;\n      }\n\n    return 2.*retval;\n  }\n\n\n  void ExtrusionFace :: Project (Point<3> & p) const\n  {\n    double dummyt;\n    int seg;\n    Point<2> p2d;\n\n    CalcProj(p,p2d,seg,dummyt);\n\n    profile->Project(p2d,p2d,profile_par);\n    \n    p = p0[seg] + p2d(0)*x_dir[seg] + p2d(1)*loc_z_dir[seg];\n\n    Vec<2> tangent2d = profile->GetTangent(profile_par);\n    profile_tangent = tangent2d(0)*x_dir[seg] + tangent2d(1)*y_dir[seg];\n  }\n\n\n  \n  Point<3> ExtrusionFace :: GetSurfacePoint () const\n  {\n    p0[0] = path->GetSpline(0).GetPoint(0.5);\n    if(!line_path[0])\n      {\n\ty_dir[0] = path->GetSpline(0).GetTangent(0.5);\n\ty_dir[0].Normalize();\n\tloc_z_dir[0] = z_dir[0];\n\tOrthogonalize(y_dir[0],loc_z_dir[0]);\n\tx_dir[0] = Cross(y_dir[0],loc_z_dir[0]);\n      }\n\n    Point<2> locpoint = profile->GetPoint(0.5);\n\n    return p0[0] + locpoint(0)*x_dir[0] + locpoint(1)*loc_z_dir[0];\n  }\n  \n\n  bool ExtrusionFace :: BoxIntersectsFace(const Box<3> & box) const\n  {\n    Point<3> center = box.Center();\n\n    Project(center);\n\n    //(*testout) << \"box.Center() \" << box.Center() << \" projected \" << center << \" diam \" << box.Diam() \n    //       << \" dist \" << Dist(box.Center(),center) << endl;\n\n    return (Dist(box.Center(),center) < 0.5*box.Diam());\n  }\n\n\n  bool ExtrusionFace :: PointInFace (const Point<3> & p, const double eps) const\n  {\n    Point<3> hp = p;\n    Project(hp);\n    return Dist2(p,hp) < sqr(eps);\n  }\n  \n\n  void ExtrusionFace :: LineIntersections ( const Point<3> & p,\n\t\t\t\t\t    const Vec<3> & v,\n\t\t\t\t\t    const double eps,\n\t\t\t\t\t    int & before,\n\t\t\t\t\t    int & after,\n\t\t\t\t\t    bool & intersecting ) const\n  {\n    Point<2> p2d;\n    Vec<2> v2d;\n\n    intersecting = false;\n\n    double segt;\n    int seg;\n\n    CalcProj(p,p2d,seg,segt);\n\n    if(seg == 0 && segt < 1e-20)\n      {\n\tVec<3> v1,v2;\n\tv1 = path->GetSpline(0).GetTangent(0);\n\tv2 = p-p0[seg];\n\tif(v1*v2 < -eps)\n\t  return;\n      }\n    if(seg == path->GetNSplines()-1 && 1.-segt < 1e-20)\n      {\n\tVec<3> v1,v2;\n\tv1 = path->GetSpline(seg).GetTangent(1);\n\tv2 = p-p0[seg];\n\tif(v1*v2 > eps)\n\t  return;\n      }\n\n    v2d(0) = v * x_dir[seg];\n    v2d(1) = v * loc_z_dir[seg];\n    \n    Vec<2> n(v2d(1),-v2d(0));\n    NgArray < Point<2> > ips;\n\n\n    profile->LineIntersections(v2d(1),\n\t\t\t      -v2d(0),\n\t\t\t      -v2d(1)*p2d(0) + v2d(0)*p2d(1),\n\t\t\t      ips,eps);\n    int comp;\n\n    if(fabs(v2d(0)) >= fabs(v2d(1)))\n      comp = 0;\n    else\n      comp = 1;\n\n    //(*testout) << \"p2d \" << p2d;\n\n    for(int i=0; i<ips.Size(); i++)\n      {\n\t//(*testout) << \" ip \" << ips[i];\n\n\tdouble t = (ips[i](comp)-p2d(comp))/v2d(comp);\n\n\tif(t < -eps)\n\t  before++;\n\telse if(t > eps)\n\t  after++;\n\telse\n\t  intersecting = true;\n      }\n    //(*testout) << endl;\n  }\n\n  void ExtrusionFace :: Print (ostream & str) const{}\n\n  INSOLID_TYPE ExtrusionFace :: VecInFace ( const Point<3> & p,\n\t\t\t\t\t    const Vec<3> & v,\n\t\t\t\t\t    const double eps ) const\n  {\n    \n    Vec<3> normal1;\n    CalcGradient(p,normal1); normal1.Normalize();\n\n    double d1 = normal1*v;\n\n\n    if(d1 > eps)\n      return IS_OUTSIDE;\n    if(d1 < -eps)\n      return IS_INSIDE;\n    \n\n    return DOES_INTERSECT;\n\n    /*\n    Point<2> p2d;\n\n    double t_path;\n    int seg;\n    CalcProj(p,p2d,seg,t_path);\n\n    double t;\n    profile.Project(p2d,p2d,t);\n\n\n    \n    Vec<2> profile_tangent = profile.GetTangent(t);\n\n    double d;\n\n    Vec<3> normal1;\n    CalcGradient(p,normal1); normal1.Normalize();\n\n    double d1 = normal1*v;\n\n    Vec<2> v2d;\n\n    v2d(0) = v*x_dir[seg];\n    v2d(1) = v*loc_z_dir[seg];\n\n\t\t\t    \t    \n    Vec<2> normal(-profile_tangent(1),profile_tangent(0));\n    \n    //d = normal*v2d;\n    \n\n    d = d1;\n\n\n    if(d > eps)\n      return IS_OUTSIDE;\n    if(d < -eps)\n      return IS_INSIDE;\n    \n\n    return DOES_INTERSECT;\n    */\n  }\n\n\n  void ExtrusionFace :: GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t\t  const Box<3> & boundingbox, \n\t\t\t\t\t\t  double facets) const\n  {\n    int n = int(facets) + 1;\n\n    for(int k = 0; k < path -> GetNSplines(); k++)\n      {\n\tfor(int i = 0; i <= n; i++)\n\t  {\n\t    Point<3> origin = path -> GetSpline(k).GetPoint(double(i)/double(n));\n\t    if(!line_path[k])\n\t      {\n\t\ty_dir[k] = path->GetSpline(k).GetTangent(double(i)/double(n));\n\t\ty_dir[k].Normalize();\n\t      }\n\t    loc_z_dir[k] = z_dir[k];\n\t    Orthogonalize(y_dir[k],loc_z_dir[k]);\n\t    if(!line_path[k])\n\t      x_dir[k] = Cross(y_dir[k],loc_z_dir[k]);\n\t    \n\t    for(int j = 0; j <= n; j++)\n\t      {\n\t\tPoint<2> locp = profile->GetPoint(double(j)/double(n));\n\t\ttas.AddPoint(origin + locp(0)*x_dir[k] + locp(1)*loc_z_dir[k]);\n\t      }\n\t  }\n      }\n    \n    for(int k = 0; k < path->GetNSplines(); k++)\n      for(int i = 0; i < n; i++)\n\tfor(int j = 0; j < n; j++)\n\t  {\n\t    int pi = k*(n+1)*(n+1) + (n+1)*i +j;\n\t  \n\t    tas.AddTriangle( TATriangle (0, pi,pi+1,pi+n+1) );\n\t    tas.AddTriangle( TATriangle (0, pi+1,pi+n+1,pi+n+2) );\n\t  }\n  }\n  \n\n  void ExtrusionFace :: GetRawData(NgArray<double> & data) const\n  {\n    data.DeleteAll();\n    profile->GetRawData(data);\n    path->GetRawData(data);\n    for(int i=0; i<3; i++)\n      data.Append(glob_z_direction[i]);\n  }\n\n\n  void ExtrusionFace :: \n  CalcLocalCoordinates (int seg, double t, \n                        Vec<3> & ex, Vec<3> & ey, Vec<3> & ez) const\n  {\n    ey = path->GetSpline(seg).GetTangent(t); \n    ey /= ey.Length();\n    ex = Cross (ey, glob_z_direction);\n    ex /= ex.Length();\n    ez = Cross (ex, ey);\n  }\n\n  void ExtrusionFace :: \n  CalcLocalCoordinatesDeriv (int seg, double t, \n                             Vec<3> & ex, Vec<3> & ey, Vec<3> & ez,\n                             Vec<3> & dex, Vec<3> & dey, Vec<3> & dez) const\n  {\n    Point<3> point;\n    Vec<3> first, second;\n    path->GetSpline(seg).GetDerivatives (t, point, first, second);\n\n    ey = first;\n    ex = Cross (ey, glob_z_direction);\n    ez = Cross (ex, ey);\n    \n    dey = second;\n    dex = Cross (dey, glob_z_direction);\n    dez = Cross (dex, ey) + Cross (ex, dey);\n    \n    double lenx = ex.Length();\n    double leny = ey.Length();\n    double lenz = ez.Length();\n\n    ex /= lenx;\n    ey /= leny;\n    ez /= lenz;\n    \n    dex /= lenx;\n    dex -= (dex * ex) * ex;\n\n    dey /= leny;\n    dey -= (dey * ey) * ey;\n\n    dez /= lenz;\n    dez -= (dez * ez) * ez;\n  }\n\n  void ExtrusionFace :: DefineTangentialPlane(const Point<3>& ap1,\n                                              const Point<3>& ap2)\n  {\n    Surface::DefineTangentialPlane(ap1, ap2);\n    tangential_plane_seg = latest_seg;\n  }\n\n  void ExtrusionFace :: ToPlane(const Point<3>& p3d, Point<2>& p2d,\n                                double h, int& zone) const\n  {\n    Surface::ToPlane(p3d, p2d, h, zone);\n    double angle = angles[tangential_plane_seg] - angles[latest_seg];\n    if(fabs(angle) > 3.14/2.)\n      zone = -1;\n  }\n\n  Extrusion :: Extrusion(shared_ptr<SplineGeometry<3>> path_in,\n\t\t\t shared_ptr<SplineGeometry<2>> profile_in,\n\t\t\t const Vec<3> & z_dir) :\n    path(path_in), profile(profile_in), z_direction(z_dir)\n  {\n    surfaceactive.SetSize(0);\n    surfaceids.SetSize(0);\n\n    for(int j=0; j<profile->GetNSplines(); j++)\n      {\n\tExtrusionFace * face = new ExtrusionFace(&(profile->GetSpline(j)),\n\t\t\t\t\t\t path.get(),\n\t\t\t\t\t\t z_direction);\n\tfaces.Append(face);\n\tsurfaceactive.Append(true);\n\tsurfaceids.Append(0);\n      }\n\n  }\n\n\n  Extrusion :: ~Extrusion()\n  {\n    for(int i=0; i<faces.Size(); i++)\n      delete faces[i];\n  }\n\n\n\n\n\n  INSOLID_TYPE Extrusion :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    for(int i=0; i<faces.Size(); i++)\n      {\n\tif(faces[i]->BoxIntersectsFace(box))\n\t  return DOES_INTERSECT;\n      }\n\n    return PointInSolid(box.Center(),0);\n  }\n\n\n  INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p,\n\t\t\t\t\t  const double eps,\n\t\t\t\t\t  NgArray<int> * const facenums) const\n  {\n    Vec<3> random_vec(-0.4561,0.7382,0.4970247);\n\n    int before(0), after(0);\n    bool intersects(false);\n    bool does_intersect(false);\n\n    for(int i=0; i<faces.Size(); i++)\n      {\n\tfaces[i]->LineIntersections(p,random_vec,eps,before,after,intersects);\n\n\t//(*testout) << \"intersects \" << intersects << \" before \" << before << \" after \" << after << endl;\n\tif(intersects)\n\t  {\n\t    if(facenums)\n\t      {\n\t\tfacenums->Append(i);\n\t\tdoes_intersect = true;\n\t      }\n\t    else\n\t      return DOES_INTERSECT;\n\t  }\n      }\n\n    if(does_intersect)\n      return DOES_INTERSECT;\n\n\n    if(before % 2 == 0)\n      return IS_OUTSIDE;\n\n    return IS_INSIDE;\n  }\n\n\n  INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p,\n\t\t\t\t\t  double eps) const\n  {\n    return PointInSolid(p,eps,NULL);    \n  }\n\n  void Extrusion :: GetTangentialSurfaceIndices (const Point<3> & p, \n                                                 NgArray<int> & surfind, double eps) const\n  {\n    for (int j = 0; j < faces.Size(); j++)\n      if (faces[j] -> PointInFace(p, eps))\n        if (!surfind.Contains (GetSurfaceId(j)))\n          surfind.Append (GetSurfaceId(j));\n  }\n\n  \n  INSOLID_TYPE Extrusion :: VecInSolid (const Point<3> & p,\n\t\t\t\t\tconst Vec<3> & v,\n\t\t\t\t\tdouble eps) const\n  {\n    NgArray<int> facenums;\n    INSOLID_TYPE pInSolid = PointInSolid(p,eps,&facenums);\n\n    if(pInSolid != DOES_INTERSECT)\n      return pInSolid;\n\n\n    double d(0);\n\n    if(facenums.Size() == 1)\n      {\n\tVec<3> normal;\n\tfaces[facenums[0]]->CalcGradient(p,normal);\n\tnormal.Normalize();\n\td = normal*v;\n\t\n\tlatestfacenum = facenums[0];\n      }\n    else if (facenums.Size() == 2)\n      {\n\tVec<3> checkvec;\n\n\tPoint<3> dummy(p);\n\tfaces[facenums[0]]->Project(dummy);\n\tif(fabs(faces[facenums[0]]->GetProfilePar()) < 0.1)\n\t  {\n\t    int aux = facenums[0];\n\t    facenums[0] = facenums[1]; facenums[1] = aux;\n\t  }\n\t\n\tcheckvec = faces[facenums[0]]->GetYDir();\n     \n\tVec<3> n0, n1;\n\tfaces[facenums[0]]->CalcGradient(p,n0);\n\tfaces[facenums[1]]->CalcGradient(p,n1);\n\tn0.Normalize();\n\tn1.Normalize();\n\t\n\n\tVec<3> t = Cross(n0,n1);\n\tif(checkvec*t < 0) t*= (-1.);\n\t\n\tVec<3> t0 = Cross(n0,t);\n\tVec<3> t1 = Cross(t,n1);\n\t\n\tt0.Normalize();\n\tt1.Normalize();\n\t\n\n\tconst double t0v = t0*v;\n\tconst double t1v = t1*v;\n\n\tif(t0v > t1v)\n\t  {\n\t    latestfacenum = facenums[0];\n\t    d = n0*v;\n\t  }\n\telse\n\t  {\n\t    latestfacenum = facenums[1];\n\t    d = n1*v;\n\t  }\n\n\tif(fabs(t0v) < eps && fabs(t1v) < eps)\n\t  latestfacenum = -1;\n      }\n\n    else\n      {\n\tcerr << \"WHY ARE THERE \" << facenums.Size() << \" FACES?\" << endl;\n      }\n\n    if(d > eps)\n      return IS_OUTSIDE;\n    if(d < -eps)\n      return IS_INSIDE;\n      \n    return DOES_INTERSECT;\n  }\n\n\n\n  // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n  INSOLID_TYPE Extrusion :: VecInSolid2 (const Point<3> & p,\n\t\t\t\t\t const Vec<3> & v1,\n\t\t\t\t\t const Vec<3> & v2,\n\t\t\t\t\t double eps) const\n  {\n    INSOLID_TYPE retval;\n    retval = VecInSolid(p,v1,eps);\n\n    // *testout << \"extr, vecinsolid=\" << int(retval) << endl;\n\n    if(retval != DOES_INTERSECT)\n      return retval;\n\n    if(latestfacenum >= 0)\n      return faces[latestfacenum]->VecInFace(p,v2,eps);\n    else\n      return VecInSolid(p,v2,eps);\n  }\n\n  \n  int Extrusion :: GetNSurfaces() const\n  {\n    return faces.Size();\n  }\n\n  Surface & Extrusion :: GetSurface (int i)\n  {\n    return *faces[i];\n  }\n\n  const Surface & Extrusion :: GetSurface (int i) const\n  {\n    return *faces[i];\n  }\n\n\n  void Extrusion :: Reduce (const BoxSphere<3> & box)\n  {\n    for(int i = 0; i < faces.Size(); i++)\n      surfaceactive[i] = faces[i]->BoxIntersectsFace(box);\n  }\n\n  void Extrusion :: UnReduce ()\n  {\n    for(int i = 0; i < faces.Size(); i++)\n      surfaceactive[i] = true;\n  }\n\n  RegisterClassForArchive<ExtrusionFace, Surface> regexf;\n  RegisterClassForArchive<Extrusion, Primitive> regextr;\n}\n"
  },
  {
    "path": "libsrc/csg/extrusion.hpp",
    "content": "#ifndef _EXTRUSION_HPP\n#define _EXTRUSION_HPP\n\nnamespace netgen\n{\n\n  class Extrusion;\n\n  class ExtrusionFace : public Surface\n  {\n  private:\n    const SplineSeg<2> * profile;\n    const SplineGeometry<3> * path;\n    Vec<3> glob_z_direction;\n    Array<double> angles;\n\n    bool deletable;\n    int tangential_plane_seg;\n  \n    NgArray< const SplineSeg3<3> * > spline3_path;\n    NgArray< const LineSeg<3> * > line_path;\n  \n    mutable NgArray < Vec<3> > x_dir, y_dir, z_dir, loc_z_dir;\n    mutable NgArray < Point<3> > p0;\n\n    mutable Vec<3> profile_tangent;\n    mutable double profile_par;\n  \n    mutable Vector profile_spline_coeff;\n\n    mutable int latest_seg;\n    mutable double latest_t;\n    mutable Point<2> latest_point2d;\n    mutable Point<3> latest_point3d;\n\n\n  private:\n    void Orthogonalize(const Vec<3> & v1, Vec<3> & v2) const;\n\n    void Init(void);\n\n  public:\n    double CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t    int seg) const;\n    void CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t  int & seg, double & t) const;\n\n  public:\n    ExtrusionFace(const SplineSeg<2> * profile_in,\n\t\t  const SplineGeometry<3> * path_in,\n\t\t  const Vec<3> & z_direction);\n\n    ExtrusionFace(const NgArray<double> & raw_data);\n    // default constructor for archive\n    ExtrusionFace() {}\n\n    ~ExtrusionFace();\n\n    void DoArchive(Archive& ar) override\n    {\n      Surface::DoArchive(ar);\n      ar & profile & path & glob_z_direction & deletable & spline3_path & line_path &\n        x_dir & y_dir & z_dir & loc_z_dir & p0 & profile_tangent & profile_par &\n        profile_spline_coeff & latest_seg & latest_t & latest_point2d & latest_point3d;\n    }\n  \n    int IsIdentic (const Surface & s2, int & inv, double eps) const override;\n  \n    double CalcFunctionValue (const Point<3> & point) const override;\n    void CalcGradient (const Point<3> & point, Vec<3> & grad) const override;\n    void CalcHesse (const Point<3> & point, Mat<3> & hesse) const override;\n    double HesseNorm () const override;\n\n    double MaxCurvature () const override;\n    //virtual double MaxCurvatureLoc (const Point<3> & /* c */ , \n    //\t\t\t\t  double /* rad */) const;\n\n    void Project (Point<3> & p) const override;\n\n    Point<3> GetSurfacePoint () const override;\n    void Print (ostream & str) const override;\n  \n    void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & boundingbox, \n\t\t\t\t\t   double facets) const override;\n\n    const SplineGeometry<3> & GetPath(void) const {return *path;}\n    const SplineSeg<2> & GetProfile(void) const {return *profile;}\n\n    bool BoxIntersectsFace(const Box<3> & box) const;\n\n    void LineIntersections ( const Point<3> & p,\n\t\t\t     const Vec<3> & v,\n\t\t\t     const double eps,\n\t\t\t     int & before,\n\t\t\t     int & after,\n\t\t\t     bool & intersecting ) const;\n\n\n    bool PointInFace (const Point<3> & p, const double eps) const;\n    \n    INSOLID_TYPE VecInFace ( const Point<3> & p,\n\t\t\t     const Vec<3> & v,\n\t\t\t     const double eps ) const;\n\n    const Vec<3> & GetYDir ( void ) const {return y_dir[latest_seg];}\n    const Vec<3> & GetProfileTangent (void) const {return profile_tangent;}\n    double GetProfilePar(void) const {return profile_par;}\n\n    void GetRawData(NgArray<double> & data) const;\n\n    void CalcLocalCoordinates (int seg, double t, \n\t\t\t       Vec<3> & ex, Vec<3> & ey, Vec<3> & ez) const;\n\n    void CalcLocalCoordinatesDeriv (int seg, double t, \n\t\t\t\t    Vec<3> & ex, Vec<3> & ey, Vec<3> & ez,\n\t\t\t\t    Vec<3> & dex, Vec<3> & dey, Vec<3> & dez) const;\n\n    void DefineTangentialPlane(const Point<3>& ap1,\n                               const Point<3>& ap2) override;\n    void ToPlane(const Point<3>& p3d, Point<2>& p2d,\n                 double h, int& zone) const override;\n\n  };\n\n\n\n  class Extrusion : public Primitive\n  {\n  private:\n    shared_ptr<SplineGeometry<3>> path;\n    shared_ptr<SplineGeometry<2>> profile; // closed, clockwise oriented curve\n\n    Vec<3> z_direction;\n\n    NgArray<ExtrusionFace*> faces;\n\n    mutable int latestfacenum;\n\n  public:\n    Extrusion(shared_ptr<SplineGeometry<3>> path_in,\n\t      shared_ptr<SplineGeometry<2>> profile_in,\n\t      const Vec<3> & z_dir);\n    // default constructor for archive\n    Extrusion() {}\n    ~Extrusion();\n\n    void DoArchive(Archive& ar) override\n    {\n      Primitive::DoArchive(ar);\n      ar & path & profile & z_direction & faces & latestfacenum;\n    }\n    INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const override;\n    INSOLID_TYPE PointInSolid (const Point<3> & p,\n                               double eps) const override;\n    INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t       double eps,\n\t\t\t       NgArray<int> * const facenums) const;\n\n    void GetTangentialSurfaceIndices (const Point<3> & p, \n                                      NgArray<int> & surfind, double eps) const override;\n\n    INSOLID_TYPE VecInSolid (const Point<3> & p,\n                             const Vec<3> & v,\n                             double eps) const override;\n\n    // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n    INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n                              const Vec<3> & v1,\n                              const Vec<3> & v2,\n                              double eps) const override;\n\n  \n    int GetNSurfaces() const override;\n    Surface & GetSurface (int i = 0) override;\n    const Surface & GetSurface (int i = 0) const override;\n\n\n    void Reduce (const BoxSphere<3> & box) override;\n    void UnReduce () override;\n  };\n\n}\n\n#endif //_EXTRUSION_HPP\n"
  },
  {
    "path": "libsrc/csg/gencyl.cpp",
    "content": "#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n  GeneralizedCylinder :: GeneralizedCylinder (ExplicitCurve2d & acrosssection,\n                                              Point<3> ap, Vec<3> ae1, Vec<3> ae2)\n    : crosssection(acrosssection)\n  {\n    planep = ap;\n    planee1 = ae1;\n    planee2 = ae2;\n    planee3 = Cross (planee1, planee2);\n    (*testout) << \"Vecs = \" << planee1 << \" \" << planee2 << \" \" << planee3 << endl;\n  };\n  \n\n  void GeneralizedCylinder :: Project (Point<3> & p) const\n  {\n    Point<2> p2d;\n    double z;\n  \n    p2d = Point<2> (planee1 * (p - planep), planee2 * (p - planep));\n    z = planee3 * (p - planep);\n\n    crosssection.Project (p2d);\n  \n    p = planep + p2d(0) * planee1 + p2d(1) * planee2 + z * planee3;\n  }\n\n  int GeneralizedCylinder ::BoxInSolid (const BoxSphere<3> & box) const\n  {\n    Point<3> p3d;\n    Point<2> p2d, projp;\n    double t;\n    Vec<2> tan, n;\n  \n    p3d = box.Center();\n  \n    p2d = Point<2> (planee1 * (p3d - planep), planee2 * (p3d - planep));\n    t = crosssection.ProjectParam (p2d);\n  \n    projp = crosssection.Eval (t);\n    tan = crosssection.EvalPrime (t);\n    n(0) = tan(1);\n    n(1) = -tan(0);\n    \n    if (Dist (p2d, projp) < box.Diam()/2)\n      return 2;\n    \n    if (n * (p2d - projp) > 0) \n      {\n        return 0;   \n      }\n    \n    return 1;\n  }\n\n  double GeneralizedCylinder :: CalcFunctionValue (const Point<3> & point) const\n  {\n    Point<2> p2d, projp;\n    double t;\n    Vec<2> tan, n;\n  \n  \n    p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep));\n    t = crosssection.ProjectParam (p2d);\n  \n    projp = crosssection.Eval (t);\n    tan = crosssection.EvalPrime (t);\n    n(0) = tan(1);\n    n(1) = -tan(0);\n    \n    n /= n.Length();\n    return n * (p2d - projp);\n  }\n  \n  void GeneralizedCylinder :: CalcGradient (const Point<3> & point, Vec<3> & grad) const\n  {\n    Point<2> p2d, projp;\n    double t;\n    Vec<2> tan, n;\n  \n  \n    p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep));\n    t = crosssection.ProjectParam (p2d);\n  \n    projp = crosssection.Eval (t);\n    tan = crosssection.EvalPrime (t);\n    n(0) = tan(1);\n    n(1) = -tan(0);\n    \n    n /= n.Length();\n    grad = n(0) * planee1 + n(1) * planee2;\n  }\n  \n  \n  void GeneralizedCylinder :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const\n  {\n    Point<2> p2d, projp;\n    double t, dist, val;\n    Point<2> curvp;\n    Vec<2> curvpp;\n    Mat<2> h2d;\n    Mat<3,2> vmat;\n    int i, j, k, l;\n  \n    p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep));\n    t = crosssection.ProjectParam (p2d);\n\n    curvp = crosssection.CurvCircle (t);\n    curvpp = p2d-curvp;\n    dist = curvpp.Length();\n    curvpp /= dist;\n    \n    h2d(0, 0) = (1 - curvpp(0) * curvpp(0) ) / dist;  \n    h2d(0, 1) = h2d(1, 0) = (- curvpp(0) * curvpp(1) ) / dist;  \n    h2d(1, 1) = (1 - curvpp(1) * curvpp(1) ) / dist;  \n  \n    vmat(0,0) = planee1(0);\n    vmat(1,0) = planee1(1);\n    vmat(2,0) = planee1(2);\n    vmat(0,1) = planee2(0);\n    vmat(1,1) = planee2(1);\n    vmat(2,1) = planee2(2);\n  \n    for (i = 0; i < 3; i++)\n      for (j = 0; j < 3; j++)\n        {\n          val = 0;\n          for (k = 0; k < 2; k++)\n            for (l = 0; l < 2; l++)\n              val += vmat(i,k) * h2d(k,l) * vmat(j,l);\n          hesse(i,j) = val;\n        }\n  }\n\n\n  double GeneralizedCylinder :: HesseNorm () const\n  {\n    return crosssection.MaxCurvature();\n  }\n\n  double GeneralizedCylinder :: MaxCurvatureLoc (const Point<3> & c, double rad) const\n  {\n    Point<2> c2d = Point<2> (planee1 * (c - planep), planee2 * (c - planep));\n    return crosssection.MaxCurvatureLoc(c2d, rad);\n  }\n  \n\n  \n  Point<3> GeneralizedCylinder :: GetSurfacePoint () const\n  {\n    Point<2> p2d; \n    p2d = crosssection.Eval(0);\n    return planep + p2d(0) * planee1 + p2d(1) * planee2;\n  }\n\n  void GeneralizedCylinder :: Reduce (const BoxSphere<3> & box)\n  {\n    Point<2> c2d = Point<2> (planee1 * (box.Center() - planep), \n                             planee2 * (box.Center() - planep));\n    crosssection.Reduce (c2d, box.Diam()/2);\n  }\n\n  void GeneralizedCylinder :: UnReduce ()\n  {\n    crosssection.UnReduce ();\n  }\n\n  void GeneralizedCylinder :: Print (ostream & str) const\n  {\n    str << \"Generalized Cylinder\" << endl;\n    crosssection.Print (str);\n  }\n  \n}\n"
  },
  {
    "path": "libsrc/csg/gencyl.hpp",
    "content": "#ifndef FILE_GENCYL\n#define FILE_GENCYL\n\n/**************************************************************************/\n/* File:   gencyl.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   14. Oct. 96                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n  /*\n  \n  Generalized Cylinder\n  \n  */\n\n\n  ///\n  class GeneralizedCylinder : public Surface\n  {\n    ///\n    ExplicitCurve2d & crosssection;\n    ///\n    Point<3> planep;\n    ///\n    Vec<3> planee1, planee2, planee3;\n  \n    ///  Vec<3> ex, ey, ez;\n    Vec2d e2x, e2y;\n    ///\n    Point<3> cp;\n  \n  public:\n    ///\n    GeneralizedCylinder (ExplicitCurve2d & acrosssection,\n\t\t\t Point<3> ap, Vec<3> ae1, Vec<3> ae2);\n  \n    ///\n    virtual void Project (Point<3> & p) const;\n  \n    ///\n    virtual int BoxInSolid (const BoxSphere<3> & box) const;\n    /// 0 .. no, 1 .. yes, 2 .. maybe\n  \n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    ///\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    ///\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n    ///\n    virtual double HesseNorm () const;\n    ///\n    virtual double MaxCurvatureLoc (const Point<3> & c, double rad) const;\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n    ///\n    virtual void Print (ostream & str) const;\n  \n    ///\n    virtual void Reduce (const BoxSphere<3> & box);\n    ///\n    virtual void UnReduce ();\n  };  \n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/genmesh.cpp",
    "content": "#include <mystdlib.h>\n\n\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n\nnamespace netgen\n{\n\n  DLL_HEADER NgArray<SpecialPoint> global_specpoints;  // for visualization\n  //static NgArray<MeshPoint> spoints;\n  \n#define TCL_OK 0\n#define TCL_ERROR 1\n\n\n\n  static void FindPoints (CSGeometry & geom,\n                          NgArray<SpecialPoint> &  specpoints,\n                          NgArray<MeshPoint> & spoints,\n                          Mesh & mesh)\n  {\n    PrintMessage (1, \"Start Findpoints\");\n\n    const char * savetask = multithread.task;\n    multithread.task = \"Find points\";\n\n    mesh.pointelements.SetSize(0);\n    for (int i = 0; i < geom.GetNUserPoints(); i++)\n      {\n        auto up = geom.GetUserPoint(i);\n\tauto pnum = mesh.AddPoint(up);\n\tmesh.Points().Last().Singularity (geom.GetUserPointRefFactor(i));\n\tmesh.AddLockedPoint (pnum);\n        int index = up.GetIndex();\n        if (index == -1)\n          index = mesh.AddCD3Name (up.GetName())+1;\n        // cout << \"adding 0d element, pnum = \" << pnum << \", material index = \" << index << endl;\n        mesh.pointelements.Append (Element0d(pnum, index));\n      }\n\n    SpecialPointCalculation spc;\n\n    spc.SetIdEps(geom.GetIdEps());\n\n    if (spoints.Size() == 0)\n      spc.CalcSpecialPoints (geom, spoints);\n    \n    PrintMessage (2, \"Analyze spec points\");\n    spc.AnalyzeSpecialPoints (geom, spoints, specpoints);\n\n    {\n      static mutex mut;\n      lock_guard<mutex> guard(mut);\n      global_specpoints = specpoints;\n    }\n    \n    PrintMessage (5, \"done\");\n\n    (*testout) << specpoints.Size() << \" special points:\" << endl;\n    for (int i = 0; i < specpoints.Size(); i++)\n      specpoints[i].Print (*testout);\n\n    /*\n      for (int i = 1; i <= geom.identifications.Size(); i++)\n      geom.identifications.Elem(i)->IdentifySpecialPoints (specpoints);\n    */\n    multithread.task = savetask;\n  }\n\n\n\n\n\n\n  static void FindEdges (CSGeometry & geom, Mesh & mesh,\n                         NgArray<SpecialPoint> &  specpoints,\n                         NgArray<MeshPoint> & spoints,\n                         MeshingParameters & mparam,\n                         const bool setmeshsize = false)\n  {\n    EdgeCalculation ec (geom, specpoints, mparam);\n    ec.SetIdEps(geom.GetIdEps());\n    ec.Calc (mparam.maxh, mesh);\n\n    for (int i = 0; i < geom.singedges.Size(); i++)\n      {\n\tgeom.singedges[i]->FindPointsOnEdge (mesh);\n\tif(setmeshsize)\n\t  geom.singedges[i]->SetMeshSize(mesh,10.*geom.BoundingBox().Diam());\n      }\n    for (int i = 0; i < geom.singpoints.Size(); i++)\n      geom.singpoints[i]->FindPoints (mesh);\n\n    for (int i = 1; i <= mesh.GetNSeg(); i++)\n      {\n\t//(*testout) << \"segment \" << mesh.LineSegment(i) << endl;\n\tint ok = 0;\n\tfor (int k = 1; k <= mesh.GetNFD(); k++)\n\t  if (mesh.GetFaceDescriptor(k).SegmentFits (mesh.LineSegment(i)))\n\t    {\n\t      ok = k;\n\t      //(*testout) << \"fits to \" << k << endl;\n\t    }\n\n\tif (!ok)\n\t  {\n\t    ok = mesh.AddFaceDescriptor (FaceDescriptor (mesh.LineSegment(i)));\n\t    //(*testout) << \"did not find, now \" << ok << endl;\n\t  }\n\n\t//(*testout) << \"change from \" << mesh.LineSegment(i).si;\n\tmesh.LineSegment(i).si = ok;\n\t//(*testout) << \" to \" << mesh.LineSegment(i).si << endl;\n      }\n\n    for(int k = 1; k<=mesh.GetNFD(); k++)\n      {\n\t*testout << \"face: \" << k << endl\n\t\t << \"FD: \" << mesh.GetFaceDescriptor(k) << endl;\n      }\n\n    if (geom.identifications.Size())\n      {\n\tPrintMessage (3, \"Find Identifications\");\n\tfor (int i = 0; i < geom.identifications.Size(); i++)\n\t  {\n\t    geom.identifications[i]->IdentifyPoints (mesh);\n\t    //(*testout) << \"identification \" << i << \" is \" \n\t    //\t       << *geom.identifications[i] << endl;\n\t    \n\t  }\n\tfor (int i = 0; i < geom.identifications.Size(); i++)\n\t  geom.identifications[i]->IdentifyFaces (mesh);\n      }\n\n\n    // find intersecting segments\n    PrintMessage (3, \"Check intersecting edges\");\n    \n    Point3d pmin, pmax;\n    mesh.GetBox (pmin, pmax);\n    BoxTree<3> segtree (pmin, pmax);\n    \n    for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n      {\n\tif (mesh[si].seginfo)\n\t  {\n\t    Box<3> hbox;\n\t    hbox.Set (mesh[mesh[si][0]]);\n\t    hbox.Add (mesh[mesh[si][1]]);\n\t    segtree.Insert (hbox.PMin(), hbox.PMax(), si);\n\t  }\n      }\n\n    NgArray<int> loc;\n    if (!ec.point_on_edge_problem)\n      for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n\t{\n\t  if (!mesh[si].seginfo) continue;\n\n\t  Box<3> hbox;\n\t  hbox.Set (mesh[mesh[si][0]]);\n\t  hbox.Add (mesh[mesh[si][1]]);\n\t  hbox.Increase (1e-6);\n\t  segtree.GetIntersecting (hbox.PMin(), hbox.PMax(), loc);\n\t  \t  \n\t  // for (SegmentIndex sj = 0; sj < si; sj++)\n\t  for (int j = 0; j < loc.Size(); j++)\n\t    {\n\t      SegmentIndex sj = loc[j];\n\t      if (sj >= si) continue;\n\t      if (!mesh[si].seginfo || !mesh[sj].seginfo) continue;\n\t      if (mesh[mesh[si][0]].GetLayer() != mesh[mesh[sj][1]].GetLayer()) continue;\n\t      \n\t      Point<3> pi1 = mesh[mesh[si][0]];\n\t      Point<3> pi2 = mesh[mesh[si][1]];\n\t      Point<3> pj1 = mesh[mesh[sj][0]];\n\t      Point<3> pj2 = mesh[mesh[sj][1]];\n\t      Vec<3> vi = pi2 - pi1;\n\t      Vec<3> vj = pj2 - pj1;\n\t      \n\t      if (sqr (vi * vj) > (1.-1e-6) * Abs2 (vi) * Abs2 (vj)) continue;\n\t      \n\t      // pi1 + vi t = pj1 + vj s\n\t      Mat<3,2> mat;\n\t      Vec<3> rhs;\n\t      Vec<2> sol;\n\t      \n\t      for (int jj = 0; jj < 3; jj++)\n\t\t{ \n\t\t  mat(jj,0) = vi(jj); \n\t\t  mat(jj,1) = -vj(jj); \n\t\t  rhs(jj) = pj1(jj)-pi1(jj); \n\t\t}\n\t      \n\t      mat.Solve (rhs, sol);\n\n\t      //(*testout) << \"mat \" << mat << endl << \"rhs \" << rhs << endl << \"sol \" << sol << endl;\n\t      \n\t      if (sol(0) > 1e-6 && sol(0) < 1-1e-6 &&\n\t\t  sol(1) > 1e-6 && sol(1) < 1-1e-6 &&\n\t\t  Abs (rhs - mat*sol) < 1e-6)\n\t\t{\n\t\t  Point<3> ip = pi1 + sol(0) * vi;\n\t\t  \n\t\t  //(*testout) << \"ip \" << ip << endl;\n\n\t\t  Point<3> pip = ip;\n\t\t  ProjectToEdge (geom.GetSurface (mesh[si].surfnr1),\n\t\t\t\t geom.GetSurface (mesh[si].surfnr2), pip);\n\t\t  \n\t\t  //(*testout) << \"Dist (ip, pip_si) \" << Dist (ip, pip) << endl;\n\t\t  if (Dist (ip, pip) > 1e-6*geom.MaxSize()) continue;\n\t\t  pip = ip;\n\t\t  ProjectToEdge (geom.GetSurface (mesh[sj].surfnr1),\n\t\t\t\t geom.GetSurface (mesh[sj].surfnr2), pip);\n\n\t\t  //(*testout) << \"Dist (ip, pip_sj) \" << Dist (ip, pip) << endl;\n\t\t  if (Dist (ip, pip) > 1e-6*geom.MaxSize()) continue;\n\t\t  \n\t\t  \n\t\t  \n\t\t  cout << \"Intersection at \" << ip << endl;\n\t\t  \n\t\t  geom.AddUserPoint (ip);\n\t\t  spoints.Append (MeshPoint (ip, mesh[mesh[si][0]].GetLayer()));\n\t\t  mesh.AddPoint (ip);\n\t\t  \n\t\t  (*testout) << \"found intersection at \" << ip << endl;\n\t\t  (*testout) << \"sol = \" << sol << endl;\n\t\t  (*testout) << \"res = \" << (rhs - mat*sol) << endl;\n\t\t  (*testout) << \"segs = \" << pi1 << \" - \" << pi2 << endl;\n\t\t  (*testout) << \"and = \" << pj1 << \" - \" << pj2 << endl << endl;\n\t\t}\n\t    }\n\t}  \n  }\n\n\n  \n  \n\n\n  static void MeshSurface (CSGeometry & geom, Mesh & mesh, MeshingParameters & mparam)\n  {\n    const char * savetask = multithread.task;\n    multithread.task = \"Surface meshing\";\n  \n    NgArray<Segment> segments;\n    int noldp = mesh.GetNP();\n\n    double starttime = GetTime();\n\n    // find master faces from identified\n    NgArray<int> masterface(mesh.GetNFD());\n    for (int i = 1; i <= mesh.GetNFD(); i++)\n      masterface.Elem(i) = i;\n  \n    NgArray<INDEX_2> fpairs;\n    bool changed;\n    do\n      {\n\tchanged = 0;\n\tfor (int i = 0; i < geom.identifications.Size(); i++)\n\t  {\n\t    geom.identifications[i]->GetIdentifiedFaces (fpairs);\n\n\t    for (int j = 0; j < fpairs.Size(); j++)\n\t      {\n\t\tif (masterface.Get(fpairs[j].I1()) <\n\t\t    masterface.Get(fpairs[j].I2()))\n\t\t  {\n\t\t    changed = 1;\n\t\t    masterface.Elem(fpairs[j].I2()) =\n\t\t      masterface.Elem(fpairs[j].I1());\n\t\t  }\n\t\tif (masterface.Get(fpairs[j].I2()) <\n\t\t    masterface.Get(fpairs[j].I1()))\n\t\t  {\n\t\t    changed = 1;\n\t\t    masterface.Elem(fpairs[j].I1()) =\n\t\t      masterface.Elem(fpairs[j].I2());\n\t\t  }\n\t      }\n\t  }\n      }\n    while (changed);\n\n\n    int bccnt=0;\n    for (int k = 0; k < geom.GetNSurf(); k++)\n      bccnt = max2 (bccnt, geom.GetSurface(k)->GetBCProperty());\n\n    for (int k = 1; k <= mesh.GetNFD(); k++)\n      {\n\tbool increased = false;\n\n\tFaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\tconst Surface * surf = geom.GetSurface(fd.SurfNr());\n\n\tif (fd.TLOSurface() && \n\t    geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCProp() > 0)\n\t  fd.SetBCProperty (geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCProp());\n\telse if (surf -> GetBCProperty() != -1)\n\t  fd.SetBCProperty (surf->GetBCProperty());\n\telse\n\t  {\n\t    bccnt++;\n\t    fd.SetBCProperty (bccnt);\n\t    increased = true;\n\t  }      \n\n\tfor (int l = 0; l < geom.bcmodifications.Size(); l++)\n\t  {\n\t    if (geom.GetSurfaceClassRepresentant (fd.SurfNr()) == \n\t\tgeom.GetSurfaceClassRepresentant (geom.bcmodifications[l].si) &&\n\t\t(fd.DomainIn() == geom.bcmodifications[l].tlonr+1 ||\n\t\t fd.DomainOut() == geom.bcmodifications[l].tlonr+1))\n\t      {\n\t\tif(geom.bcmodifications[l].bcname == NULL)\n\t\t  fd.SetBCProperty (geom.bcmodifications[l].bcnr);\n\t\telse\n\t\t  {\n\t\t    if(!increased)\n\t\t      {\n\t\t\tbccnt++;\n\t\t\tfd.SetBCProperty (bccnt);\n\t\t\tincreased = true;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n      }\n\n    mesh.SetNBCNames( bccnt );\n\n    for (int k = 1; k <= mesh.GetNFD(); k++)\n      {\n\tFaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\tconst Surface * surf = geom.GetSurface(fd.SurfNr());\n\tif (fd.TLOSurface() )\n\t  {\n\t    int bcp = fd.BCProperty();\n\t    string nextbcname = geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCName();\n\t    if ( nextbcname != \"default\" )\n\t      mesh.SetBCName ( bcp - 1 , nextbcname );\n\t  }\n\telse // if (surf -> GetBCProperty() != -1)\n\t  {\n\t    int bcp = fd.BCProperty();\n\t    string nextbcname = surf->GetBCName();\n\t    if ( nextbcname != \"default\" )\n\t      mesh.SetBCName ( bcp - 1, nextbcname );\n\t  }\n      }\n    \n    for (int k = 1; k <= mesh.GetNFD(); k++)\n      {\n\tFaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\tfd.SetBCName ( mesh.GetBCNamePtr ( fd.BCProperty() - 1 ) );\n      }\n\n    //!!\n    \n    for (int k = 1; k <= mesh.GetNFD(); k++)\n      {\n\tFaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\t//const Surface * surf = geom.GetSurface(fd.SurfNr());\n\n\tfor (int l = 0; l < geom.bcmodifications.Size(); l++)\n\t  {\n\t    if (geom.GetSurfaceClassRepresentant (fd.SurfNr()) == \n\t\tgeom.GetSurfaceClassRepresentant (geom.bcmodifications[l].si) &&\n\t\t(fd.DomainIn() == geom.bcmodifications[l].tlonr+1 ||\n\t\t fd.DomainOut() == geom.bcmodifications[l].tlonr+1) &&\n\t\tgeom.bcmodifications[l].bcname != NULL\n\t\t)\n\t      {\n\t\tint bcp = fd.BCProperty();\n\t\tmesh.SetBCName ( bcp - 1, *(geom.bcmodifications[l].bcname) );\n\t\tfd.SetBCName ( mesh.GetBCNamePtr ( bcp - 1) );\n\t      }\n\t  }\n      }\n\n    for(int k = 0; k<geom.bcmodifications.Size(); k++)\n      {\n\tdelete geom.bcmodifications[k].bcname;\n\tgeom.bcmodifications[k].bcname = NULL;\n      }\n\n    //!!\n\n\n    for (int j = 0; j < geom.singfaces.Size(); j++)\n      {\n\tNgArray<int> surfs;\n\tgeom.GetIndependentSurfaceIndices (geom.singfaces[j]->GetSolid(),\n\t\t\t\t\t   geom.BoundingBox(), surfs);\n\tfor (int k = 1; k <= mesh.GetNFD(); k++)\n\t  {\n\t    FaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\t    for (int l = 0; l < surfs.Size(); l++)\n\t      if (surfs[l] == fd.SurfNr())\n\t\t{\n\t\t  if (geom.singfaces[j]->GetDomainNr() == fd.DomainIn())\n\t\t    fd.SetDomainInSingular (1);\n\t\t  if (geom.singfaces[j]->GetDomainNr() == fd.DomainOut())\n\t\t    fd.SetDomainOutSingular (1);\n\t\t}\n\t  }\n      }\n    \n\n    // assemble edge hash-table\n    mesh.CalcSurfacesOfNode();\n\n    for (int k = 1; k <= mesh.GetNFD(); k++)\n      {\n\tmultithread.percent = 100.0 * k / (mesh.GetNFD()+1e-10);\n\n\tif (masterface.Get(k) != k)\n\t  continue;\n\n\tFaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\n\t(*testout) << \"Surface \" << k << endl;\n\t(*testout) << \"Face Descriptor: \" << fd << endl;\n\tPrintMessage (1, \"Surface \", k, \" / \", mesh.GetNFD());\n\n\tint oldnf = mesh.GetNSE();\n      \n\tconst Surface * surf =\n\t  geom.GetSurface((mesh.GetFaceDescriptor(k).SurfNr()));\n\n\n\tMeshing2Surfaces meshing(geom, *surf, mparam, geom.BoundingBox());\n\tmeshing.SetStartTime (starttime);\n\n        double eps = 1e-8 * geom.MaxSize();\n\tfor (PointIndex pi = IndexBASE<PointIndex>(); pi < noldp+IndexBASE<PointIndex>(); pi++)\n\t  { \n\t    // if(surf->PointOnSurface(mesh[pi]))\n\t    meshing.AddPoint (mesh[pi], pi, NULL,\n\t\t\t      (surf->PointOnSurface(mesh[pi], eps) != 0));\n\t  }\n\n\tsegments.SetSize (0);\n\n\tfor (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n\t  if (mesh[si].si == k)\n\t    {\n\t      segments.Append (mesh[si]);\n\t      (*testout) << \"appending segment \" << mesh[si] << endl;\n\t      //<< \" from \" << mesh[mesh[si][0]]\n\t      //\t << \" to \" <<mesh[mesh[si][1]]<< endl;\n\t    }\n\n\t(*testout) << \"num-segments \" << segments.Size() << endl;\n\n\tfor (int i = 1; i <= geom.identifications.Size(); i++)\n\t  {\n\t    geom.identifications.Get(i)->\n\t      BuildSurfaceElements(segments, mesh, surf);\n\t  }\n\n\tfor (int si = 0; si < segments.Size(); si++)\n\t  {\n\t    PointGeomInfo gi;\n\t    gi.trignum = k;\n\t    meshing.AddBoundaryElement (segments[si][0] + 1 - IndexBASE<PointIndex>(), \n\t\t\t\t\tsegments[si][1] + 1 - IndexBASE<PointIndex>(), \n\t\t\t\t\tgi, gi);\n\t  }\n\n\tdouble maxh = mparam.maxh;\n\tif (fd.DomainIn() != 0)\n\t  {\n\t    const Solid * s1 = \n\t      geom.GetTopLevelObject(fd.DomainIn()-1) -> GetSolid();\n\t    if (s1->GetMaxH() < maxh)\n\t      maxh = s1->GetMaxH();\n\t    maxh = min2(maxh, geom.GetTopLevelObject(fd.DomainIn()-1)->GetMaxH());\n\t  }\n\tif (fd.DomainOut() != 0)\n\t  {\n\t    const Solid * s1 = \n\t      geom.GetTopLevelObject(fd.DomainOut()-1) -> GetSolid();\n\t    if (s1->GetMaxH() < maxh)\n\t      maxh = s1->GetMaxH();\n\t    maxh = min2(maxh, geom.GetTopLevelObject(fd.DomainOut()-1)->GetMaxH());\n\t  }\n\tif (fd.TLOSurface() != 0)\n\t  {\n\t    double hi = geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetMaxH();\n\t    if (hi < maxh) maxh = hi;\n\t  }\n\n\t(*testout) << \"domin = \" << fd.DomainIn() << \", domout = \" << fd.DomainOut()\n\t\t   << \", tlo-surf = \" << fd.TLOSurface()\n\t\t   << \" mpram.maxh = \" << mparam.maxh << \", maxh = \" << maxh << endl;\n\n\tmparam.checkoverlap = 0;\n\n\tMESHING2_RESULT res =\n\t  meshing.GenerateMesh (mesh, mparam, maxh, k);\n\n\tif (res != MESHING2_OK)\n\t  {\n\t    PrintError (\"Problem in Surface mesh generation\");\n\t    throw NgException (\"Problem in Surface mesh generation\");\n\t  }\n\n\tif (multithread.terminate) return;\n        \n\tfor (SurfaceElementIndex sei = oldnf; sei < mesh.GetNSE(); sei++)\n\t  mesh[sei].SetIndex (k);\n\n        auto n_illegal_trigs = mesh.FindIllegalTrigs();\n        PrintMessage (3, n_illegal_trigs, \" illegal triangles\");\n\n\t//      mesh.CalcSurfacesOfNode();\n\n\tif (segments.Size())   \n\t  { \n\t    // surface was meshed, not copied\n\n\t    static int timer = NgProfiler::CreateTimer (\"total surface mesh optimization\");\n\t    NgProfiler::RegionTimer reg (timer);\n\n\n\t    PrintMessage (2, \"Optimize Surface\");\n\t    for (int i = 1; i <= mparam.optsteps2d; i++)\n\t      {\n\t\tif (multithread.terminate) return;\n\t\t\n\t\t{\n\t\t  MeshOptimize2d meshopt(mesh);\n\t\t  meshopt.SetFaceIndex (k);\n\t\t  meshopt.SetImproveEdges (0);\n\t\t  meshopt.SetMetricWeight (mparam.elsizeweight);\n\t\t  meshopt.SetWriteStatus (0);\n\t\t  \n\t\t  meshopt.EdgeSwapping (i > mparam.optsteps2d/2);\n\t\t}\n\t\t\n\t\tif (multithread.terminate) return;\n\t\t{\n\t\t  //\t\tmesh.CalcSurfacesOfNode();\n\t\t\n\t\t  MeshOptimize2d meshopt(mesh);\n\t\t  meshopt.SetFaceIndex (k);\n\t\t  meshopt.SetImproveEdges (0);\n\t\t  meshopt.SetMetricWeight (mparam.elsizeweight);\n\t\t  meshopt.SetWriteStatus (0);\n\n\t\t  meshopt.ImproveMesh(mparam);\n\t\t}\n\t\t\n\t\t{\n\t\t  MeshOptimize2d meshopt(mesh);\n\t\t  meshopt.SetFaceIndex (k);\n\t\t  meshopt.SetImproveEdges (0);\n\t\t  meshopt.SetMetricWeight (mparam.elsizeweight);\n\t\t  meshopt.SetWriteStatus (0);\n\n\t\t  meshopt.CombineImprove();\n\t\t  //\t\tmesh.CalcSurfacesOfNode();\n\t\t}\n\t\t\n\t\tif (multithread.terminate) return;\n\t\t{\n\t\t  MeshOptimize2d meshopt(mesh);\n\t\t  meshopt.SetFaceIndex (k);\n\t\t  meshopt.SetImproveEdges (0);\n\t\t  meshopt.SetMetricWeight (mparam.elsizeweight);\n\t\t  meshopt.SetWriteStatus (0);\n\n\t\t  meshopt.ImproveMesh(mparam);\n\t\t}\n\t      }\n\t  }\n\n\n\tPrintMessage (3, (mesh.GetNSE() - oldnf), \" elements, \", mesh.GetNP(), \" points\");\n\n\tmparam.Render();\n      }\n    \n    mesh.Compress();\n\n    do\n      {\n\tchanged = 0;\n\tfor (int k = 1; k <= mesh.GetNFD(); k++)\n\t  {\n\t    multithread.percent = 100.0 * k / (mesh.GetNFD()+1e-10);\n\t  \n\t    if (masterface.Get(k) == k)\n\t      continue;\n\n\t    FaceDescriptor & fd = mesh.GetFaceDescriptor(k);\n\n\t    (*testout) << \"Surface \" << k << endl;\n\t    (*testout) << \"Face Descriptor: \" << fd << endl;\n\t    PrintMessage (2, \"Surface \", k);\n\n\t    int oldnf = mesh.GetNSE();\n      \n\t    const Surface * surf =\n\t      geom.GetSurface((mesh.GetFaceDescriptor(k).SurfNr()));\n\n\t    /*\n\t      if (surf -> GetBCProperty() != -1)\n\t      fd.SetBCProperty (surf->GetBCProperty());\n\t      else\n\t      {\n\t      bccnt++;\n\t      fd.SetBCProperty (bccnt);\n\t      }\n\t    */\n  \n\t    segments.SetSize (0);\n\t    for (int i = 1; i <= mesh.GetNSeg(); i++)\n\t      {\n\t\tSegment * seg = &mesh.LineSegment(i);\n\t\tif (seg->si == k)\n\t\t  segments.Append (*seg);\n\t      }\n\n\t    for (int i = 1; i <= geom.identifications.Size(); i++)\n\t      {\n\t\tgeom.identifications.Elem(i)->GetIdentifiedFaces (fpairs);\n\t\tint found = 0;\n\t\tfor (int j = 1; j <= fpairs.Size(); j++)\n\t\t  if (fpairs.Get(j).I1() == k || fpairs.Get(j).I2() == k)\n\t\t    found = 1;\n\n\t\tif (!found)\n\t\t  continue;\n\n\t\tgeom.identifications.Get(i)->\n\t\t  BuildSurfaceElements(segments, mesh, surf);\n\t\tif (!segments.Size())\n\t\t  break;\n\t      }\n\n\t  \n\t    if (multithread.terminate) return;\n\n\t    for (SurfaceElementIndex  sei = oldnf; sei < mesh.GetNSE(); sei++)\n\t      mesh[sei].SetIndex (k);\n\n\n\t    if (!segments.Size())\n\t      {\n\t\tmasterface.Elem(k) = k;\n\t\tchanged = 1; \n\t      }\n\n\t    PrintMessage (3, (mesh.GetNSE() - oldnf), \" elements, \", mesh.GetNP(), \" points\");\n\t  }\n      \n        mparam.Render();\n      }\n    while (changed);\n\n    \n    mesh.SplitSeparatedFaces();\n    mesh.CalcSurfacesOfNode();\n\n    multithread.task = savetask;\n  }\n\n\n\n  int CSGGenerateMesh (CSGeometry & geom, \n\t\t       shared_ptr<Mesh> & mesh, MeshingParameters & mparam)\n  {\n    NgArray<SpecialPoint> specpoints;\n    NgArray<MeshPoint> spoints;\n\n    \n    if (mesh && mesh->GetNSE() &&\n\t!geom.GetNSolids())\n      {\n\tif (mparam.perfstepsstart < MESHCONST_MESHVOLUME)\n\t  mparam.perfstepsstart = MESHCONST_MESHVOLUME;\n      }\n\n    if (mparam.perfstepsstart <= MESHCONST_ANALYSE)\n      {\n        if (mesh)\n          mesh -> DeleteMesh();\n        else\n          mesh = make_shared<Mesh>();\n\n\tmesh->SetGlobalH (mparam.maxh);\n\tmesh->SetMinimalH (mparam.minh);\n\n\tNgArray<double> maxhdom(geom.GetNTopLevelObjects());\n\tfor (int i = 0; i < maxhdom.Size(); i++)\n\t  maxhdom[i] = geom.GetTopLevelObject(i)->GetMaxH();\n\n\tmesh->SetMaxHDomain (maxhdom);\n\n\tif (mparam.uselocalh)\n\t  {\n\t    double maxsize = geom.MaxSize(); \n\t    mesh->SetLocalH (Point<3>(-maxsize, -maxsize, -maxsize),\n\t\t\t     Point<3>(maxsize, maxsize, maxsize),\n\t\t\t     mparam.grading);\n\n\t    mesh -> LoadLocalMeshSize (mparam.meshsizefilename);\n            for (auto mspnt : mparam.meshsize_points)\n              mesh -> RestrictLocalH (mspnt.pnt, mspnt.h, mspnt.layer);\n\t  }\n\n\tspoints.SetSize(0);\n\tFindPoints (geom, specpoints, spoints, *mesh);\n      \n\tPrintMessage (5, \"find points done\");\n\n#ifdef LOG_STREAM\n\t(*logout) << \"Special points found\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl << endl;\n#endif\n      }\n\n\n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_ANALYSE) \n      return TCL_OK;\n\n\n    if (mparam.perfstepsstart <= MESHCONST_MESHEDGES)\n      {\n\tFindEdges (geom, *mesh, specpoints, spoints, mparam, true);\n\tif (multithread.terminate) return TCL_OK;\n#ifdef LOG_STREAM      \n\t(*logout) << \"Edges meshed\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl;\n#endif\n      \n      \n\tif (multithread.terminate)\n\t  return TCL_OK;\n  \n\tif (mparam.uselocalh)\n\t  {\n\t    mesh->CalcLocalH(mparam.grading);\n\t    mesh->DeleteMesh();\n\t    \n\t    FindPoints (geom, specpoints, spoints, *mesh);\n\t    if (multithread.terminate) return TCL_OK;\n\t    FindEdges (geom, *mesh, specpoints, spoints, mparam, true);\n\t    if (multithread.terminate) return TCL_OK;\n\t    \n\t    mesh->DeleteMesh();\n\t  \n\t    FindPoints (geom, specpoints, spoints, *mesh);\n\t    if (multithread.terminate) return TCL_OK;\n\t    FindEdges (geom, *mesh, specpoints, spoints, mparam);\n\t    if (multithread.terminate) return TCL_OK;\n\t  }\n      }\n  \n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)\n      return TCL_OK;\n\n\n    if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)\n      {\n\tMeshSurface (geom, *mesh, mparam);  \n\tif (multithread.terminate) return TCL_OK;\n      \n#ifdef LOG_STREAM\n\t(*logout) << \"Surfaces meshed\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl;\n#endif      \n\n        /*\n\tif (mparam.uselocalh)\n\t  {\n\t    mesh->CalcLocalH(mparam.grading);      \n\t    mesh->DeleteMesh();\n\n\t    FindPoints (geom, *mesh);\n\t    if (multithread.terminate) return TCL_OK;\n\t    FindEdges (geom, *mesh, mparam);\n\t    if (multithread.terminate) return TCL_OK;\n\n\t    MeshSurface (geom, *mesh, mparam);  \n\t    if (multithread.terminate) return TCL_OK;\n\t  }\n        */\n\n#ifdef LOG_STREAM      \n\t(*logout) << \"Surfaces remeshed\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl;\n#endif      \n      \n#ifdef STAT_STREAM\n\t(*statout) << mesh->GetNSeg() << \" & \"\n\t\t   << mesh->GetNSE() << \" & - &\" \n\t\t   << GetTime() << \" & \" << endl;\n#endif  \n\n\tMeshQuality2d (*mesh);\n\tmesh->CalcSurfacesOfNode();\n      }\n  \n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_OPTSURFACE)\n      return TCL_OK;\n\n\n    if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME)\n      {\n\tmultithread.task = \"Volume meshing\";\n\n\tfor (int i = 0; i < geom.GetNTopLevelObjects(); i++)\n\t  mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str());\n\n\tMESHING3_RESULT res =\n\t  MeshVolume (mparam, *mesh);\n\n\tif (res != MESHING3_OK) return TCL_ERROR;\n      \n\tif (multithread.terminate) return TCL_OK;\n      \n\tRemoveIllegalElements (*mesh);\n\tif (multithread.terminate) return TCL_OK;\n\n\tMeshQuality3d (*mesh);\n      \n#ifdef STAT_STREAM\n\t(*statout) << GetTime() << \" & \";\n#endif      \n      \n#ifdef LOG_STREAM\n\t(*logout) << \"Volume meshed\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl;\n#endif\n      }\n\n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME)\n      return TCL_OK;\n\n\n    if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME)\n      {\n\tmultithread.task = \"Volume optimization\";\n      \n\tOptimizeVolume (mparam, *mesh);\n\tif (multithread.terminate) return TCL_OK;\n      \n#ifdef STAT_STREAM\n\t(*statout) << GetTime() << \" & \"\n\t\t   << mesh->GetNE() << \" & \"\n\t\t   << mesh->GetNP() << \" \" << '\\\\' << '\\\\' << \" \\\\\" << \"hline\" << endl;\n#endif      \n\n#ifdef LOG_STREAM      \n\t(*logout) << \"Volume optimized\" << endl\n\t\t  << \"time = \" << GetTime() << \" sec\" << endl\n\t\t  << \"points: \" << mesh->GetNP() << endl;\n#endif\n      }\n\n    mesh -> OrderElements();\n    return TCL_OK;\n  }\n}\n"
  },
  {
    "path": "libsrc/csg/geoml.hpp",
    "content": "#ifndef FILE_GEOML\n#define FILE_GEOML\n\n/* *************************************************************************/\n/* File:   geoml.hh                                                        */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   21. Jun. 98                                                     */\n/* *************************************************************************/\n\n#include <geom/geom.hh>\n\n#include <geom/solid.hh>\n#include <geom/algprim.hh>\n#include <geom/adtree.hh>\n#include <geom/csgeom.hh>\n#endif\n"
  },
  {
    "path": "libsrc/csg/identify.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n\nnamespace netgen\n{\nIdentification :: Identification (int anr, const CSGeometry & ageom)\n  : geom(ageom), identfaces(10)\n{\n  nr = anr;\n}\n\nIdentification :: ~Identification ()\n{\n  ;\n}\n\n\nostream & operator<< (ostream & ost, Identification & ident)\n{\n  ident.Print (ost);\n  return ost;\n}\n\n\n/*\nvoid Identification :: IdentifySpecialPoints (NgArray<class SpecialPoint> & points)\n{\n  ;\n}\n*/\n\n\nint Identification :: \nIdentifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t      const TABLE<int> & specpoint2solid,\n\t      const TABLE<int> & specpoint2surface) const\n{\n  cout << \"Identification::Identifiable called for base-class\" << endl;\n  return 0;\n}\n\nint Identification :: \nIdentifiable (const Point<3> & p1, const Point<3> & sp2) const\n{\n  cout << \"Identification::Identifiable called for base-class\" << endl;\n  return 0;\n}\n\n\nint Identification :: \nIdentifiableCandidate (const SpecialPoint & sp1) const\n{\n  return 1;\n}\n\n\nint Identification :: \nShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const\n{\n  return 0;\n}\n\nPointIndex Identification :: GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)\n{\n  cout << \"Identification::GetIdentifiedPoint called for base-class\" << endl;\n  return PointIndex::INVALID;\n}\n\nvoid Identification :: IdentifyPoints (Mesh & mesh)\n{\n  cout << \"Identification::IdentifyPoints called for base-class\" << endl;\n  ;\n}\n\nvoid Identification :: IdentifyFaces (class Mesh & mesh)\n{\n  cout << \"Identification::IdentifyFaces called for base-class\" << endl;\n  ;\n}\n\nvoid Identification :: \nBuildSurfaceElements (NgArray<Segment> & segs,\n\t\t      Mesh & mesh, const Surface * surf)\n{\n  cout << \"Identification::BuildSurfaceElements called for base-class\" << endl;\n  ;\n}\n\n\nvoid Identification :: \nBuildVolumeElements (NgArray<class Element2d> & surfels,\n\t\t\t  class Mesh & mesh)\n{\n  ;\n}\n\nvoid Identification :: \nGetIdentifiedFaces (NgArray<INDEX_2> & idfaces) const\n{\n  idfaces.SetSize(0);\n  for (int i = 1; i <= identfaces.GetNBags(); i++)\n    for (int j = 1; j <= identfaces.GetBagSize(i); j++)\n      {\n\tINDEX_2 i2;\n\tint val;\n\tidentfaces.GetData (i, j, i2, val);\n\tidfaces.Append (i2);\n      }\n}\n\n\n\n\nPeriodicIdentification ::\nPeriodicIdentification (int anr,\n\t\t\tconst CSGeometry & ageom,\n\t\t\tconst Surface * as1,\n\t\t\tconst Surface * as2,\n                        Transformation<3> atrafo)\n  : Identification(anr, ageom), trafo(atrafo)\n{\n  inv_trafo = trafo.CalcInverse();\n  s1 = as1;\n  s2 = as2;\n}\n\nPeriodicIdentification :: ~PeriodicIdentification ()\n{\n  ;\n}\n\n/*\nvoid PeriodicIdentification :: IdentifySpecialPoints \n(NgArray<class SpecialPoint> & points)\n{\n  int i, j;\n  int bestj;\n  double bestval, val;\n\n  for (i = 1; i <= points.Size(); i++)\n    {\n      Point<3> p1 = points.Get(i).p;\n      Point<3> hp1 = p1;\n      s1->Project (hp1);\n      if (Dist (p1, hp1) > 1e-6) continue;\n\n      Vec<3> n1;\n      s1->GetNormalVector (p1, n1);\n      n1 /= n1.Length();\n      if ( fabs(n1 * points.Get(i).v) > 1e-3)\n\tcontinue;\n\n      bestval = 1e8;\n      bestj = 1;\n      for (j = 1; j <= points.Size(); j++)\n\t{\n\t  Point<3> p2= points.Get(j).p;\n\t  Point<3> hp2 = p2;\n\t  s2->Project (hp2);\n\t  if (Dist (p2, hp2) > 1e-6) continue;\n\t  \n\t  Vec<3> n2;\n\t  s2->GetNormalVector (p2, n2);\n\t  n2 /= n2.Length();\n\t  if ( fabs(n2 * points.Get(j).v) > 1e-3)\n\t    continue;\n\n\n\t  Vec<3> v(p1, p2);\n\t  double vl = v.Length();\n\t  double cl = fabs (v*n1);\n\n\t  val = 1 - cl*cl/(vl*vl);\n\n\t  val += (points.Get(i).v - points.Get(j).v).Length();\n\n\t  if (val < bestval)\n\t    {\n\t      bestj = j;\n\t      bestval = val;\n\t    }\n\t}\n\n      (*testout) << \"Identify Periodic special points: pi = \" \n\t\t << points.Get(i).p << \", vi = \" << points.Get(i).v \n\t\t << \" pj = \" << points.Get(bestj).p \n\t\t << \", vj = \" << points.Get(bestj).v \n\t\t << \" bestval = \" << bestval << endl;\n    }\n}\n*/\n\nint PeriodicIdentification :: \nIdentifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t      const TABLE<int> & specpoint2solid,\n\t      const TABLE<int> & specpoint2surface) const\n{\n  SpecialPoint hsp1 = sp1;\n  SpecialPoint hsp2 = sp2;\n\n  for (int i = 1; i <= 1; i++)\n    {\n      //      Swap (hsp1, hsp2);\n\n      if (!s1->PointOnSurface (hsp1.p))\n\tcontinue;\n\n      Vec<3> n1;\n      n1 = s1->GetNormalVector (hsp1.p);\n      n1 /= n1.Length();\n      if ( fabs(n1 * hsp1.v) > 1e-3)\n\tcontinue;\n\n\n      if (!s2->PointOnSurface(hsp2.p))\n\tcontinue;\n\n      Vec<3> n2;\n      n2 = s2->GetNormalVector (hsp2.p);\n      n2 /= n2.Length();\n      if ( fabs(n2 * hsp2.v) > 1e-3)\n\tcontinue;\n      \n      if ((trafo(hsp1.v)-hsp2.v).Length2() > 1e-12)\n        return false;\n\n      double d2typ = Dist2(hsp1.p, hsp2.p);\n      \n      if (Dist2 (trafo(hsp1.p),hsp2.p) < 1e-18*d2typ)\n        return true;\n      \n      if (Dist2 (hsp1.p, trafo(hsp1.p)) < 1e-18*d2typ)\n        { // old style without trafo, but normal projection\n          Vec<3> v = hsp2.p - hsp1.p;\n          double vl = v.Length();\n          double cl = fabs (v*n1);\n          \n          double val1 = 1 - cl*cl/(vl*vl);\n          double val2 = (hsp1.v - hsp2.v).Length();\n          \n          if (val1 < 1e-10 && val2 < 1e-6)\n            return true;\n        }\n    }\n\n  return false;\n}\n\nint PeriodicIdentification :: \nIdentifiable (const Point<3> & p1, const Point<3> & p2) const\n{\n  return (s1->PointOnSurface (p1) &&\n\t  s2->PointOnSurface (p2));\n}\n  \n\n\n\nPointIndex PeriodicIdentification :: \nGetIdentifiedPoint (class Mesh & mesh, PointIndex pi)\n{\n  const Surface *snew;\n  const Point<3> & p = mesh.Point (pi);\n\n  Point<3> hp = p;\n  if (s1->PointOnSurface (p))\n    {\n      snew = s2;\n      hp = trafo(hp);\n    }\n  else\n    {\n      if (s2->PointOnSurface (p))\n\t{\n\t  snew = s1;\n          hp = inv_trafo(hp);\n\t}\n      else\n\t{\n          throw NgException(\"GetIdenfifiedPoint: Not possible\");\n\t}    \n    }\n  \n  // project to other surface\n  snew->Project (hp);\n\n  PointIndex newpi(PointIndex::INVALID);\n  for (PointIndex pi : Range(mesh.Points()))\n    if (Dist2 (mesh.Point(pi), hp) < 1e-12)\n      {\n\tnewpi = pi;\n\tbreak;\n      }\n  if (!newpi.IsValid())\n    newpi = mesh.AddPoint (hp);\n\n  if (snew == s2)\n    mesh.GetIdentifications().Add (pi, newpi, nr);\n  else\n    mesh.GetIdentifications().Add (newpi, pi, nr);\n\n  mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC);\n\t   \n  /* \n  (*testout) << \"Identify points(periodic), nr = \" << nr << \": \" << mesh.Point(pi)\n\t     << \" and \" << mesh.Point(newpi) \n\t     << ((snew == s2) ? \"\" : \" inverse\")\n\t     << endl;\n  */\n  return newpi;\n}\n\n\nvoid PeriodicIdentification :: IdentifyPoints (class Mesh & mesh)\n{\n  Point3d p1, p2;\n  mesh.GetBox(p1, p2);\n  auto eps = 1e-6 * (p2-p1).Length();\n\n  /*\n  for (int i = 1; i <= mesh.GetNP(); i++)\n    {\n      Point<3> p = mesh.Point(i);\n      if (s1->PointOnSurface (p))\n\t{\n\t  Point<3> pp = p;\n          pp = trafo(pp);\n\t  s2->Project (pp);\n\t  for (int j = 1; j <= mesh.GetNP(); j++)\n\t    if (Dist2(mesh.Point(j), pp) < eps)\n\t      {\n\t\tmesh.GetIdentifications().Add (i, j, nr);\n\t      }\n\t}\n    }\n  */\n\n  for (auto pi : Range(mesh.Points()))\n    {\n      Point<3> p = mesh[pi];\n      if (s1->PointOnSurface (p))\n\t{\n\t  Point<3> pp = p;\n          pp = trafo(pp);\n\t  s2->Project (pp);\n          for (PointIndex pj : Range(mesh.Points()))\n\t    if (Dist2(mesh[pj], pp) < eps)\n              mesh.GetIdentifications().Add (pi, pj, nr);\n\t}\n    }\n\n  mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC);\n}\n\n\nvoid PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)\n{\n  int i, j, k, l;\n  int fi1, fi2, side;\n  for (i = 1; i <= mesh.GetNFD(); i++)\n    for (j = 1; j <= mesh.GetNFD(); j++)\n      {\n\tint surfi = mesh.GetFaceDescriptor(i).SurfNr();\n\tint surfj = mesh.GetFaceDescriptor(j).SurfNr();\n\tif (surfi == surfj)\n\t  continue;\n\t\n\tif (geom.GetSurface (surfi) != s1 ||\n\t    geom.GetSurface (surfj) != s2)\n\t  continue;\n\t    \n\tint idok = 1;\n\n\n\t//\t(*testout) << \"check faces \" << i << \" and \" << j << endl;\n\tfor (side = 1; side <= 2 && idok; side++)\n\t  {\n\t    if (side == 1)\n\t      {\n\t\tfi1 = i; \n\t\tfi2 = j;\n\t      }\n\t    else\n\t      {\n\t\tfi1 = j;\n\t\tfi2 = i;\n\t      }\n\n\t    for (k = 1; k <= mesh.GetNSeg(); k++)\n\t      {\n\t\tconst Segment & seg1 = mesh.LineSegment(k);\n\t\tif (seg1.si != fi1)\n\t\t  continue;\n\n\t\tint foundother = 0;\n\t\tfor (l = 1; l <= mesh.GetNSeg(); l++)\n\t\t  {\n\t\t    const Segment & seg2 = mesh.LineSegment(l);\n\t\t    if (seg2.si != fi2)\n\t\t      continue;\n\t\t    \n\t\t    //\t\t    (*testout) << \"seg1 = \" << seg1[0] << \"-\" << seg1[1] << \", seg2 = \" << seg2[0] << \"-\" << seg2[1];\n\n\t\t    if (side == 1)\n\t\t      {\n\t\t\tif (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&\n\t\t\t    mesh.GetIdentifications().Used (seg1[1], seg2[1]))\n\t\t\t  {\n\t\t\t    foundother = 1;\n\t\t\t    break;\n\t\t\t  }\n\t\t\t\n\t\t\tif (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&\n\t\t\t    mesh.GetIdentifications().Used (seg1[1], seg2[0]))\n\t\t\t  {\n\t\t\t    foundother = 1;\n\t\t\t    break;\n\t\t\t  }\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\tif (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&\n\t\t\t    mesh.GetIdentifications().Used (seg2[1], seg1[1]))\n\t\t\t  {\n\t\t\t    foundother = 1;\n\t\t\t    break;\n\t\t\t  }\n\t\t\t\n\t\t\tif (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&\n\t\t\t    mesh.GetIdentifications().Used (seg2[1], seg1[0]))\n\t\t\t  {\n\t\t\t    foundother = 1;\n\t\t\t    break;\n\t\t\t  }\n\t\t      }\n\t\t  }\n\n\t\tif (!foundother)\n\t\t  {\n\t\t    idok = 0;\n\t\t    break;\n\t\t  }\n\t      }\n\t  }\n\n\n\tif (idok)\n\t  {\n\t    // (*testout) << \"Identify faces \" << i << \" and \" << j << endl;\n\t    INDEX_2 fpair(i,j);\n\t    fpair.Sort();\n\t    identfaces.Set (fpair, 1);\n\t  }\n      }\n}\n\n\n\nvoid PeriodicIdentification :: \nBuildSurfaceElements (NgArray<Segment> & segs,\n\t\t      Mesh & mesh, const Surface * surf)\n{\n  int found = 0;\n  int fother = -1;\n\n  int facei = segs.Get(1).si;\n  int surfnr = mesh.GetFaceDescriptor(facei).SurfNr();\n\n  if (geom.GetSurface(surfnr) == s1 ||\n      geom.GetSurface(surfnr) == s2)\n    {\n      NgArray<int> copy_points;\n\n      for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t{\n\t  const Element2d & sel = mesh[sei];\n\t  INDEX_2 fpair (facei, sel.GetIndex());\n\t  fpair.Sort();\n\t  if (identfaces.Used (fpair))\n            {\n\t      for (int k = 0; k < sel.GetNP(); k++)\n                if (!copy_points.Contains (sel[k]))\n                  copy_points.Append (sel[k]);\n            }      \n        }\n      BubbleSort (copy_points);\n      for (int k = 0; k < copy_points.Size(); k++)\n        GetIdentifiedPoint (mesh, copy_points[k]);\n\n\n\n      for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t{\n\t  const Element2d & sel = mesh[sei];\n\t  INDEX_2 fpair (facei, sel.GetIndex());\n\t  fpair.Sort();\n\t  if (identfaces.Used (fpair))\n\t    {\n\t      found = 1;\n\t      fother = sel.GetIndex();\n\n\t      // copy element\n\t      Element2d newel(sel.GetType());\n\t      newel.SetIndex (facei);\n\t      for (int k = 0; k < sel.GetNP(); k++)\n                newel[k] = GetIdentifiedPoint (mesh, sel[k]);\n\n\t      Vec<3> nt = Cross (Point<3> (mesh[newel[1]])- Point<3> (mesh[newel[0]]),\n\t\t\t\t Point<3> (mesh[newel[2]])- Point<3> (mesh[newel[0]]));\n\t      \n\t      Vec<3> nsurf = geom.GetSurface (surfnr)->GetNormalVector (mesh[newel[0]]);\n\t      if (nsurf * nt < 0)\n                Swap (newel[0], newel[2]);\n\t\t\t\t\n\t      mesh.AddSurfaceElement (newel);\n\t    }\n\t}\n    }\n  \n  if (found)\n    {\n      // (*mycout) << \" copy face \" << facei << \" from face \" << fother;\n      PrintMessage (4, \" copy face \", facei, \" from face \", fother);\n      \n      segs.SetSize(0);\n    }\n}\n\n\n\n\n\n\n\n\nvoid PeriodicIdentification :: Print (ostream & ost) const\n{\n  ost << \"Periodic Identifiaction, surfaces: \" \n      << s1->Name() << \" - \" << s2->Name() << endl;\n  s1->Print (ost);\n  ost << \" - \";\n  s2->Print (ost);\n  ost << endl;\n}\n\n\nvoid PeriodicIdentification :: GetData (ostream & ost) const\n{\n  ost << \"periodic \" << s1->Name() << \" \" << s2->Name();\n}\n\n\n\n\n\n\n\nCloseSurfaceIdentification ::\nCloseSurfaceIdentification (int anr,\n\t\t\t    const CSGeometry & ageom,\n\t\t\t    const Surface * as1,\n\t\t\t    const Surface * as2,\n\t\t\t    const TopLevelObject * adomain,\n\t\t\t    const Flags & flags)\n  : Identification(anr, ageom)\n{\n  s1 = as1;\n  s2 = as2;\n  domain = adomain;\n  ref_levels = int (flags.GetNumFlag (\"reflevels\", 2));\n  ref_levels_s1 = int (flags.GetNumFlag (\"reflevels1\", 0));\n  ref_levels_s2 = int (flags.GetNumFlag (\"reflevels2\", 0));\n  slices = flags.GetNumListFlag (\"slices\");\n  for(int i=0; i<slices.Size(); i++)\n    if((i==0 && slices[i] <= 0) ||\n       (i>0 && slices[i] <= slices[i-1]) ||\n       (slices[i] >= 1))\n      throw NgException (\"slices have to be in ascending order, between 0 and 1\");\n\n  // eps_n = 1e-3;\n  eps_n = 1e-6;\n\n  dom_surf_valid = 0;\n\n  if (domain)\n    for (int i = 0; i < geom.GetNTopLevelObjects(); i++)\n      if (domain == geom.GetTopLevelObject(i))\n\tdom_nr = i;\n\n  usedirection = flags.NumListFlagDefined(\"direction\");\n  if(usedirection)\n    {\n      for(int i=0; i<3; i++)\n\tdirection(i) = flags.GetNumListFlag(\"direction\")[i];\n\n      direction.Normalize();\n    }\n}\n\nCloseSurfaceIdentification :: ~CloseSurfaceIdentification ()\n{\n  ;\n}\n\nvoid CloseSurfaceIdentification :: Print (ostream & ost) const\n{\n  ost << \"CloseSurface Identifiaction, surfaces: \" \n      << s1->Name() << \" - \" << s2->Name() << endl;\n  s1->Print (ost);\n  s2->Print (ost);\n  ost << endl;\n}\n\n\nvoid CloseSurfaceIdentification :: GetData (ostream & ost) const\n{\n  ost << \"close surface \" << s1->Name() << \" \" << s2->Name();\n}\n\n\n/*\nvoid CloseSurfaceIdentification :: IdentifySpecialPoints \n(NgArray<class SpecialPoint> & points)\n{\n  int i, j;\n  int bestj;\n  double bestval, val;\n\n  for (i = 1; i <= points.Size(); i++)\n    {\n      Point<3> p1 = points.Get(i).p;\n      Vec<3> n1;\n\n      if (!s1->PointOnSurface (p1))\n\tcontinue;\n\n\ts1->GetNormalVector (p1, n1);\n      n1 /= n1.Length();\n      if ( fabs(n1 * points.Get(i).v) > 1e-3)\n\tcontinue;\n\n      bestval = 1e8;\n      bestj = 1;\n      for (j = 1; j <= points.Size(); j++)\n\t{\n\t  Point<3> p2= points.Get(j).p;\n\t  if (!s2->PointOnSurface (p2))\n\t    continue;\n\t  \n\t  Vec<3> n2;\n\t  s2->GetNormalVector (p2, n2);\n\t  n2 /= n2.Length();\n\t  if ( fabs(n2 * points.Get(j).v) > 1e-3)\n\t    continue;\n\n\n\t  Vec<3> v(p1, p2);\n\t  double vl = v.Length();\n\t  double cl = fabs (v*n1);\n\n\t  val = 1 - cl*cl/(vl*vl);\n\n\t  val += (points.Get(i).v - points.Get(j).v).Length();\n\n\t  if (val < bestval)\n\t    {\n\t      bestj = j;\n\t      bestval = val;\n\t    }\n\t}\n\n      (*testout) << \"Identify close surfaces special points: pi = \" \n\t\t << points.Get(i).p << \", vi = \" << points.Get(i).v \n\t\t << \" pj = \" << points.Get(bestj).p \n\t\t << \", vj = \" << points.Get(bestj).v \n\t\t << \" bestval = \" << bestval << endl;\n    }\n}\n*/\n\nint CloseSurfaceIdentification :: \nIdentifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t      const TABLE<int> & specpoint2solid,\n\t      const TABLE<int> & specpoint2surface) const\n{\n  //(*testout) << \"identcheck: \" << sp1.p << \"; \" << sp2.p << endl;\n\n  if (!dom_surf_valid)\n    {\n      const_cast<bool&> (dom_surf_valid) = 1;\n      NgArray<int> & hsurf = const_cast<NgArray<int>&> (domain_surfaces);\n\n      if (domain)\n\t{\n\t  BoxSphere<3> hbox (geom.BoundingBox());\n\t  geom.GetIndependentSurfaceIndices (domain->GetSolid(), hbox, hsurf);\n\t  //(*testout) << \"surfs of identification \" << nr << \": \" << endl << hsurf << endl;\n\t}\n      else\n\t{\n\t  hsurf.SetSize (geom.GetNSurf());\n\t  for (int j = 0; j < hsurf.Size(); j++)\n\t    hsurf[j] = j;\n\t}\n    }\n\n  if (domain)\n    {\n      bool has1 = 0, has2 = 0;\n      for (int i = 0; i < specpoint2solid[sp1.nr].Size(); i++)\n\tif (specpoint2solid[sp1.nr][i] == dom_nr)\n\t  { has1 = 1; break; }\n      for (int i = 0; i < specpoint2solid[sp2.nr].Size(); i++)\n\tif (specpoint2solid[sp2.nr][i] == dom_nr)\n\t  { has2 = 1; break; }\n\n      if (!has1 || !has2) \n\t{\n\t  //(*testout) << \"failed at pos1\" << endl;\n\t  return 0;\n\t}\n    }\n\n  if (!s1->PointOnSurface (sp1.p))\n    {\n      //(*testout) << \"failed at pos2\" << endl;\n      return 0;\n    }\n\n//   (*testout) << \"sp1 \" << sp1.p << \" sp2 \" << sp2.p << endl\n// \t     << \"specpoint2solid[sp1.nr] \" << specpoint2solid[sp1.nr] << endl\n// \t     << \"specpoint2solid[sp2.nr] \" << specpoint2solid[sp2.nr] << endl;\n\n\n  Vec<3> n1 = s1->GetNormalVector (sp1.p);\n  n1.Normalize();\n  if ( fabs(n1 * sp1.v) > eps_n)\n    {\n      //(*testout) << \"failed at pos3\" << endl;\n      return 0;\n    }\n\n  if (!s2->PointOnSurface(sp2.p))\n    {\n      //(*testout) << \"failed at pos4\" << endl;\n      return 0;\n    }\n\n\n  Vec<3> n2 = s2->GetNormalVector (sp2.p);\n  n2.Normalize();\n  if ( fabs(n2 * sp2.v) > eps_n)\n    {\n      //(*testout) << \"failed at pos5\" << endl;\n      return 0;\n    }\n  \n  // must have joint surface \n  bool joint = 0;\n\n  int j = 0, k = 0;\n  while (1)\n    {\n      int snr1 = specpoint2surface[sp1.nr][j];\n      int snr2 = specpoint2surface[sp2.nr][k];\n      if (snr1 < snr2) \n\t{\n\t  j++;\n\t  if (j == specpoint2surface[sp1.nr].Size()) break;\n\t}\n      else if (snr2 < snr1) \n\t{\n\t  k++;\n\t  if (k == specpoint2surface[sp2.nr].Size()) break;\n\t}\n      else\n\t{\n\t  bool dom_surf = 0;\n\t  for (int l = 0; l < domain_surfaces.Size(); l++)\n\t    if (domain_surfaces[l] == snr1)\n\t      dom_surf = 1;\n\n\t  if (dom_surf)\n\t    {\n\t      Vec<3> hn1 = geom.GetSurface(snr1)->GetNormalVector (sp1.p);\n\t      Vec<3> hn2 = geom.GetSurface(snr1)->GetNormalVector (sp2.p);\n\t      \n\t      if (hn1 * hn2 > 0)\n\t\t{\n\t\t  joint = 1;\n\t\t  break;\n\t\t}\n\t    }\n\n\t  j++;\n\t  if (j == specpoint2surface[sp1.nr].Size()) break;\n\t  k++;\n\t  if (k == specpoint2surface[sp2.nr].Size()) break;\n\t}\n    }\n\n  if (!joint)\n    {\n      //(*testout) << \"failed at pos6\" << endl;\n      return 0;\n    }\n\n  Vec<3> v = sp2.p - sp1.p;\n  double vl = v.Length();\n  double cl = (usedirection) ? fabs(v*direction) : fabs (v*n1);\n\n\n  if(cl <= (1-eps_n*eps_n) * vl)\n    {\n      //(*testout) << \"failed at pos7\" << endl;\n      return 0;\n    }\n  \n  double dl;\n\n  if(usedirection)\n    {\n      Vec<3> v1 = sp1.v - (sp1.v*direction)*direction; v1.Normalize();\n      Vec<3> v2 = sp2.v - (sp2.v*direction)*direction; v2.Normalize();\n      \n      dl = (v1 - v2).Length();\n    }\n  else\n    dl = (sp1.v - sp2.v).Length();\n\n  if (dl < 0.1)\n    return 1;\n   \n\n  //(*testout) << \"failed at pos8\" << endl;\n  return 0;\n}\n\nint CloseSurfaceIdentification :: \nIdentifiable (const Point<3> & p1, const Point<3> & p2) const\n{  \n//   if (domain)\n//     if (!domain->GetSolid()->IsIn (p1) || !domain->GetSolid()->IsIn (p2))\n//       return 0;\n  return (s1->PointOnSurface (p1) && s2->PointOnSurface (p2));\n}\n  \n\n\n\nint CloseSurfaceIdentification :: \nIdentifiableCandidate (const SpecialPoint & sp1) const\n{\n  if (domain)\n    if (!domain->GetSolid()->IsIn (sp1.p))\n      return 0;\n\n  if (s1->PointOnSurface (sp1.p))\n    {\n      Vec<3> n1;\n      n1 = s1->GetNormalVector (sp1.p);\n      n1.Normalize();\n      if ( fabs(n1 * sp1.v) > eps_n)\n\treturn 0;\n      return 1;\n    }\n\n  if (s2->PointOnSurface (sp1.p))\n    {\n      Vec<3> n1;\n      n1 = s2->GetNormalVector (sp1.p);\n      n1.Normalize();\n      if ( fabs(n1 * sp1.v) > eps_n)\n\treturn 0;\n      return 1;\n    }\n  return 0;\n}\n\n\n\nint CloseSurfaceIdentification :: \nShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const\n{  \n  if ( (s1->PointOnSurface (sp1.p) && s2->PointOnSurface (sp2.p)) ||\n       (s1->PointOnSurface (sp2.p) && s2->PointOnSurface (sp1.p)) )\n    {\n      return 1;\n    }\n  return 0;\n}\n\n\n\nPointIndex CloseSurfaceIdentification :: \nGetIdentifiedPoint (class Mesh & mesh, PointIndex pi)\n{\n  const Surface *snew;\n  const Point<3> & p = mesh.Point (pi);\n\n  idmap_type identmap(mesh.GetNP());\n  mesh.GetIdentifications().GetMap (nr, identmap);\n  /*\n  if (identmap.Get(pi))\n    return identmap.Get(pi);\n  */\n  if (identmap[pi].IsValid())\n    return identmap[pi];\n  \n  \n  if (s1->PointOnSurface (p))\n    snew = s2;\n  else if (s2->PointOnSurface (p))\n    snew = s1;\n  else\n    {\n      (*testout)  << \"GetIdenfifiedPoint: Not possible\" << endl;\n      (*testout) << \"p = \" << p << endl;\n      (*testout) << \"surf1: \" << (*s1) << endl\n\t\t << \"surf2: \" << (*s2) << endl;\n      \n      cerr << \"GetIdenfifiedPoint: Not possible\" << endl;\n      throw NgException (\"GetIdenfifiedPoint: Not possible\");\n    }    \n\n  // project to other surface\n  Point<3> hp = p;\n  if(usedirection)\n    snew->SkewProject(hp,direction);\n  else\n    snew->Project (hp);\n\n  //(*testout) << \"projecting \" << p << \" to \" << hp << endl;\n\n  int newpi = 0;\n  for (int i = 1; i <= mesh.GetNP(); i++)\n    if (Dist2 (mesh.Point(i), hp) < 1e-12)\n      //    if (Dist2 (mesh.Point(i), hp) < 1 * Dist2 (hp, p))\n      {\n\tnewpi = i;\n\tbreak;\n      }\n  if (!newpi)\n    newpi = mesh.AddPoint (hp);\n\n  if (snew == s2)\n    {\n      mesh.GetIdentifications().Add (pi, newpi, nr);\n      //(*testout) << \"add identification(1) \" << pi << \" - \" << newpi << \", \" << nr << endl;\n    }\n  else\n    {\n      mesh.GetIdentifications().Add (newpi, pi, nr);\n      //(*testout) << \"add identification(2) \" << newpi << \" - \" << pi << \", \" << nr << endl;\n    }\n  mesh.GetIdentifications().SetType(nr,Identifications::CLOSESURFACES);\n\t   \n\n  /*\n  (*testout) << \"Identify points(closesurface), nr = \" << nr << \": \" << mesh.Point(pi)\n\t     << \" and \" << mesh.Point(newpi) \n\t     << ((snew == s2) ? \"\" : \" inverse\")\n\t     << endl;\n  */\n  return newpi;\n}\n\n\n\n\n\nvoid CloseSurfaceIdentification :: IdentifyPoints (Mesh & mesh)\n{\n  int np = mesh.GetNP();\n\n  NgArray<int> points_on_surf2;\n\n  for (int i2 = 1; i2 <= np; i2++)\n    if (s2->PointOnSurface (mesh.Point(i2)))\n      points_on_surf2.Append (i2);\n    \n  NgArray<int> surfs_of_p1;\n\n  for (int i1 = 1; i1 <= np; i1++)\n    {\n      Point<3> p1 = mesh.Point(i1);\n      //      (*testout) << \"p1 = \" << i1 << \" = \" << p1 << endl;\n      if (domain && !domain->GetSolid()->IsIn (p1))\n\tcontinue;\n      \n      //if(domain) (*testout) << \"p1 is in \" << domain->GetSolid()->Name() << endl;\n\n      if (s1->PointOnSurface (p1))\n\t{\n\t  int candi2 = 0;\n\t  double mindist = 1e10;\n\n\t  Vec<3> n1;\n\t  n1 = s1->GetNormalVector (p1);\n\t  n1.Normalize();\n\t   \n\t  surfs_of_p1.SetSize(0);\n\t  for (int jj = 0; jj < domain_surfaces.Size(); jj++)\n\t    {\n\t      int j = domain_surfaces[jj];\n\t      if (geom.GetSurface(j) -> PointOnSurface(p1))\n\t\tsurfs_of_p1.Append (j);\n\t    }\n\t  //(*testout) << \" surfs of p1 = \" << endl << surfs_of_p1 << endl;\n\n\t  for (int ii2 = 0; ii2 < points_on_surf2.Size(); ii2++)\n\t    {\n\t      int i2 = points_on_surf2[ii2];\n\t      if (i2 == i1) continue;\n\t      const Point<3> p2 = mesh.Point(i2);\n\t      \n\t      Vec<3> n = p2 - p1;\n\t      n.Normalize();\n\t      \n\t      bool joint = 0;\n\t      for (int jj = 0; jj < surfs_of_p1.Size(); jj++)\n\t\t{\n\t\t  int j = surfs_of_p1[jj];\n\t\t  if (geom.GetSurface(j) -> PointOnSurface(p2))\n\t\t    {\n\t\t      Vec<3> hn1 = geom.GetSurface(j)->GetNormalVector (p1);\n\t\t      Vec<3> hn2 = geom.GetSurface(j)->GetNormalVector (p2);\n\t\t      \n\t\t      if (hn1 * hn2 > 0)\n\t\t\t{\n\t\t\t  joint = 1;\n\t\t\t  break;\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t      if (!joint) continue;\n\t      \n\t      if(usedirection)\n\t\t{\n\t\t  if (fabs (n*direction) > 0.9)\n\t\t    {\n\t\t      Vec<3> p1p2 = p2-p1;\n\t\t      double ndist = p1p2.Length2() - pow(p1p2*direction,2);\n\t\t      if(ndist < mindist)\n\t\t\t{\n\t\t\t  candi2 = i2;\n\t\t\t  mindist = ndist;\n\t\t\t}\n\t\t    }\n\t\t      \n\t\t}\n\t      else\n\t\t{\n\t\t  if (fabs (n * n1) > 0.9 &&\n\t\t      Dist (p1, p2) < mindist)\n\t\t    {\n\t\t      candi2 = i2;\n\t\t      mindist = Dist (p1, p2);\n\t\t    }\n\t\t}\n\t    \n\t    }\n\n\t  if (candi2)\n\t    {\n\t      //(*testout) << \"identify points \" << p1 << \" - \" << mesh.Point(candi2) << endl;\n\n\t      /*\n\t      (*testout) << \"Add Identification from CSI2, nr = \" << nr << \", p1 = \" \n\t\t\t << i1 << \" = \" \n\t\t\t << mesh[PointIndex(i1)] << \", p2 = \" << candi2 << \" = \" \n\t\t\t << mesh[PointIndex(candi2)] << endl;\n\t      */\n\t      mesh.GetIdentifications().Add (i1, candi2, nr);\n\t      mesh.GetIdentifications().SetType(nr,Identifications::CLOSESURFACES);\n\t      //(*testout) << \"add identification \" << i1 << \" - \" << candi2 << \", \" << nr << endl;\n\t    }\n\t}\n    }\n}\n\n\n\nvoid CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)\n{\n  int fi1, fi2, side;\n  int s1rep = -1, s2rep = -1;\n\n  for (int i = 0; i < geom.GetNSurf(); i++)\n    {\n      if (geom.GetSurface (i) == s1) \n\ts1rep = geom.GetSurfaceClassRepresentant(i);\n      if (geom.GetSurface (i) == s2) \n\ts2rep = geom.GetSurfaceClassRepresentant(i);\n    }\n\n  NgArray<int> segs_on_face1, segs_on_face2;\n\n  identfaces.DeleteData();\n\n  //(*testout) << \"identify faces, nr = \" << nr << endl;\n  \n  for (int i = 1; i <= mesh.GetNFD(); i++)\n    {\n      auto & fdi = mesh.GetFaceDescriptor(i);\n      int surfi = mesh.GetFaceDescriptor(i).SurfNr();\n      if (s1rep != surfi) continue;\n\n\n      if (domain &&\n\t  domain != geom.GetTopLevelObject (mesh.GetFaceDescriptor(i).DomainIn()-1) &&\n\t  domain != geom.GetTopLevelObject (mesh.GetFaceDescriptor(i).DomainOut()-1))\n\tcontinue;\n\n      for (int j = 1; j <= mesh.GetNFD(); j++)\n\t{\n          auto & fdj = mesh.GetFaceDescriptor(j);          \n\t  int surfj = mesh.GetFaceDescriptor(j).SurfNr();\n\n\t  if (surfi == surfj) continue;\n\t  if (s2rep != surfj) continue;\n\n          bool have_common = false;\n          if (fdi.DomainIn() != 0)\n            if (fdi.DomainIn() == fdj.DomainIn() || fdi.DomainIn() == fdj.DomainOut())\n              have_common = true;\n          if (fdi.DomainOut() != 0)\n            if (fdi.DomainOut() == fdj.DomainIn() || fdi.DomainOut() == fdj.DomainOut())\n              have_common = true;\n          if (!have_common) continue;\n          \n\t  int idok = 1;\n\t  \n\t  for (side = 1; side <= 2 && idok; side++)\n\t    {\n\t      if (side == 1)\n\t\t{\n\t\t  fi1 = i; \n\t\t  fi2 = j;\n\t\t}\n\t      else\n\t\t{\n\t\t  fi1 = j;\n\t\t  fi2 = i;\n\t\t}\n\t      \n\n\t      segs_on_face1.SetSize(0);\n\t      segs_on_face2.SetSize(0);\n\n\t      for (int k = 1; k <= mesh.GetNSeg(); k++)\n\t\t{\n\t\t  if (mesh.LineSegment(k).si == fi1)\n\t\t    segs_on_face1.Append (k);\n\t\t  if (mesh.LineSegment(k).si == fi2)\n\t\t    segs_on_face2.Append (k);\n\t\t}\n\n\n\t      for (int k = 1; k <= mesh.GetNSeg(); k++)\n\t\t{\n\t\t  const Segment & seg1 = mesh.LineSegment(k);\n\t\t  if (seg1.si != fi1)\n\t\t    continue;\n\t\t  \n\t\t  int foundother = 0;\n\t\t  /*\n\t\t  for (int l = 1; l <= mesh.GetNSeg(); l++)\n\t\t    {\n\t\t      const Segment & seg2 = mesh.LineSegment(l);\n\t\t      if (seg2.si != fi2)\n\t\t\tcontinue;\n\t\t  */\n\t\t  for (int ll = 0; ll < segs_on_face2.Size(); ll++)\n\t\t    {\n\t\t      int l = segs_on_face2[ll];\n\t\t      const Segment & seg2 = mesh.LineSegment(l);\n\t\t      \n\t\t      if (side == 1)\n\t\t\t{\n\t\t\t  if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&\n\t\t\t      mesh.GetIdentifications().Used (seg1[1], seg2[1]))\n\t\t\t    {\n\t\t\t      foundother = 1;\n\t\t\t      break;\n\t\t\t    }\n\t\t\t  \n\t\t\t  if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&\n\t\t\t      mesh.GetIdentifications().Used (seg1[1], seg2[0]))\n\t\t\t    {\n\t\t\t      foundother = 1;\n\t\t\t      break;\n\t\t\t    }\n\t\t\t}\n\t\t      else\n\t\t\t{\n\t\t\t  if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&\n\t\t\t      mesh.GetIdentifications().Used (seg2[1], seg1[1]))\n\t\t\t    {\n\t\t\t      foundother = 1;\n\t\t\t      break;\n\t\t\t    }\n\t\t\t  \n\t\t\t  if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&\n\t\t\t      mesh.GetIdentifications().Used (seg2[1], seg1[0]))\n\t\t\t    {\n\t\t\t      foundother = 1;\n\t\t\t      break;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t  \n\t\t  if (!foundother)\n\t\t    {\n\t\t      idok = 0;\n\t\t      break;\n\t\t    }\n\t\t}\n\t    }\n\t  \n\t  \n\t  if (idok)\n\t    {\n\t      //(*testout) << \"Identification \" << nr << \", identify faces \" << i << \" and \" << j << endl;\n\t      INDEX_2 fpair(i,j);\n\t      fpair.Sort();\n\t      identfaces.Set (fpair, 1);\n\t    }\n\t}\n    }\n}\n\n\n\nvoid CloseSurfaceIdentification :: \nBuildSurfaceElements (NgArray<Segment> & segs,\n\t\t      Mesh & mesh, const Surface * surf)\n{\n  bool found = 0;\n  int cntquads = 0;\n\n  idmap_type identmap;\n  identmap = 0;\n\n  mesh.GetIdentifications().GetMap (nr, identmap);\n  \n  for (int i = PointIndex::BASE; i < identmap.Size()+PointIndex::BASE; i++)\n    if (identmap[i])  identmap[identmap[i]] = i;\n\n    \n  //(*testout) << \"identification nr = \" << nr << endl;\n  //(*testout) << \"surf = \" << (*surf) << endl;\n  //(*testout) << \"domain = \" << domain->GetSolid()->Name() << endl;\n  //(*testout) << \"segs = \" << endl << segs << endl;\n  //(*testout) << \"identmap = \" << endl << identmap << endl;\n  \n  //NgArray<bool> foundseg(segs.Size());\n  //foundseg = false;\n\n  // insert quad layer:\n  for (int i1 = 0; i1 < segs.Size(); i1++)\n    {\n      const Segment & s1 = segs[i1];\n      if (identmap[s1[0]] && identmap[s1[1]])\n\tfor (int i2 = 0; i2 < i1; i2++)\n\t  {\n\t    const Segment & s2 = segs[i2];\n\t    //(*testout) << \"checking \" << s1 << \" and \" << s2 << \" for ident.\" << endl;\n\n\t    if(domain && !((s1.domin == dom_nr ||\n\t\t\t    s1.domout == dom_nr) &&\n\t\t\t   (s2.domin == dom_nr ||\n\t\t\t    s2.domout == dom_nr)))\n\t      continue;\n\t \n\t    if ((mesh.GetIdentifications().Get (s1[0], s2[1], nr) && \n\t\t mesh.GetIdentifications().Get (s1[1], s2[0], nr))    || \n\t\t(mesh.GetIdentifications().Get (s2[0], s1[1], nr) && \n\t\t mesh.GetIdentifications().Get (s2[1], s1[0], nr)))\n\t      {\n\t\tVec<3> ns = surf->GetNormalVector (mesh[s1[0]]);\n\n                Vec<3> t1 = mesh[s1[1]] - mesh[s1[0]];\n                // Vec<3> t2 = mesh[s2[1]] - mesh[s2[0]];\n                Vec<3> nst1 = Cross(t1, ns);\n                // Vec<3> nst2 = Cross(t2, ns);\n                Vec<3> dvec = Center(mesh[s1[0]], mesh[s1[1]])-Center(mesh[s2[0]], mesh[s2[1]]);\n                if (nst1 * dvec < 0) continue;\n                \n\t\tElement2d el(s1[0], s1[1], s2[0], s2[1]);\n                el.SetIndex(s1.si);\n\n\t\tVec<3> n = Cross (mesh[el[1]] - mesh[el[0]],\n\t\t\t\t  mesh[el[3]] - mesh[el[0]]);\n\n\t\tif (n * ns < 0)\n\t\t  {\n\t\t    Swap (el.PNum(1), el.PNum(2));\n\t\t    Swap (el.PNum(3), el.PNum(4));\n\t\t  }\n\t\t\t     \n\t\tmesh.AddSurfaceElement (el);\n//  \t\t(*testout) << \"(id nr \"<< nr <<\") add rect element: \"\n//  \t\t\t   << mesh.Point (el.PNum(1)) << \" - \"\n//  \t\t\t   << mesh.Point (el.PNum(2)) << \" - \"\n//  \t\t\t   << mesh.Point (el.PNum(3)) << \" - \"\n//  \t\t\t   << mesh.Point (el.PNum(4)) << endl;\n\t\tfound = true;\n\t\t//foundseg[i1]=foundseg[i2] = true;\n\t\tcntquads++;\n\t      }\n\t  }\n    }\n  if (found)\n    {\n      PrintMessage(3, \"insert quad layer of \", cntquads,\n\t\t   \" elements at face \", segs.Get(1).si);\n      //NgArray<Segment> aux;\n      //for(int i=0; i<segs.Size();i++)\n      //\tif(!foundseg[i])\n      //\t  aux.Append(segs[i]);\n      segs.SetSize(0);\n    }\n  else\n    {\n      BuildSurfaceElements2 (segs, mesh, surf);\n    }\n}\n\n\n\n\n\n\nvoid CloseSurfaceIdentification :: \nBuildSurfaceElements2 (NgArray<Segment> & segs,\n\t\t       Mesh & mesh, const Surface * surf)\n{\n  // copy mesh\n\n\n  //  (*testout) << \"copy trig face, identnr = \" << nr << endl;\n  //  (*testout) << \"identfaces = \" << endl << identfaces << endl;\n\n  if (!segs.Size()) return;\n\n  bool found = 0;\n  int fother = -1;\n\n  int facei = segs[0].si;\n  int surfnr = mesh.GetFaceDescriptor(facei).SurfNr();\n\n  \n  bool foundid = 0;\n  for (INDEX_2_HASHTABLE<int>::Iterator it = identfaces.Begin();\n       it != identfaces.End(); it++)\n    {\n      INDEX_2 i2;\n      int data;\n      identfaces.GetData (it, i2, data);\n      if (i2.I1() == facei || i2.I2() == facei)\n\tfoundid = 1;\n    }\n\n  /*\n  for (int i = 1; i <= identfaces.GetNBags(); i++)\n    for (int j = 1; j <= identfaces.GetBagSize(i); j++)\n      {\n\tINDEX_2 i2;\n\tint data;\n\tidentfaces.GetData (i, j, i2, data);\n\tif (i2.I1() == facei || i2.I2() == facei)\n\t  foundid = 1;\n\n\t(*testout) << \"identface = \" << i2 << endl;\n\t(*testout) << \"face \" << i2.I1() << \" = \" << mesh.GetFaceDescriptor(i2.I1()) << endl;\n\t(*testout) << \"face \" << i2.I2() << \" = \" << mesh.GetFaceDescriptor(i2.I2()) << endl;\n      }\n  */\n\n  if (foundid)\n    {\n      //\t  (*testout) << \"surfaces found\" << endl;\n      // copy surface\n      for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t{\n\t  const Element2d & sel = mesh[sei];\n\t  INDEX_2 fpair (facei, sel.GetIndex());\n\t  fpair.Sort();\n\t  if (identfaces.Used (fpair))\n\t    {\n\t      found = 1;\n\t      fother = sel.GetIndex();\n\t      \n\t      // copy element\n\t      Element2d newel(sel.GetType());\n\t      newel.SetIndex (facei);\n\t      for (int k = 1; k <= sel.GetNP(); k++)\n                newel.PNum(k) = GetIdentifiedPoint (mesh, sel.PNum(k));\n\t      \n\t      Vec<3> nt = Cross (Point<3> (mesh.Point (newel.PNum(2)))- \n\t\t\t\t Point<3> (mesh.Point (newel.PNum(1))),\n\t\t\t\t Point<3> (mesh.Point (newel.PNum(3)))- \n\t\t\t\t Point<3> (mesh.Point (newel.PNum(1))));\n\t      Vec<3> nsurf;\n\t      nsurf = geom.GetSurface (surfnr)->GetNormalVector (mesh.Point(newel.PNum(1)));\n\t      if (nsurf * nt < 0)\n\t\tSwap (newel.PNum(2), newel.PNum(3));\n\t      \n\t      mesh.AddSurfaceElement (newel);\n\t    }\n\t}\n    }\n  \n  if (found)\n    {\n      // (*mycout) << \" copy face \" << facei << \" from face \" << fother;\n      PrintMessage (4, \" copy face \", facei, \" from face \", fother);\n      segs.SetSize(0);\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid CloseSurfaceIdentification :: \nBuildVolumeElements (NgArray<class Element2d> & surfels,\n\t\t     class Mesh & mesh)\n{\n  ;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n/*   ***************** Close Edges Identification ********** */\n\n\n\nCloseEdgesIdentification ::\nCloseEdgesIdentification (int anr,\n\t\t\t  const CSGeometry & ageom,\n\t\t\t  const Surface * afacet,\n\t\t\t  const Surface * as1,\n\t\t\t  const Surface * as2)\n  : Identification(anr, ageom)\n{\n  facet = afacet;\n  s1 = as1;\n  s2 = as2;\n}\n\nCloseEdgesIdentification :: ~CloseEdgesIdentification ()\n{\n  ;\n}\n\nvoid CloseEdgesIdentification :: Print (ostream & ost) const\n{\n  ost << \"CloseEdges Identifiaction, facet = \" \n      << facet->Name() << \", surfaces: \" \n      << s1->Name() << \" - \" << s2->Name() << endl;\n  facet->Print (ost);\n  s1->Print (ost);\n  s2->Print (ost);\n  ost << endl;\n}\n\n\nvoid CloseEdgesIdentification :: GetData (ostream & ost) const\n{\n  ost << \"closeedges \" << facet->Name() << \" \" \n      << s1->Name() << \" \" << s2->Name();\n}\n\n\n/*\nvoid CloseEdgesIdentification :: IdentifySpecialPoints \n(NgArray<class SpecialPoint> & points)\n{\n  int i, j;\n  int bestj;\n  double bestval, val;\n\n  for (i = 1; i <= points.Size(); i++)\n    {\n      Point<3> p1 = points.Get(i).p;\n      Vec<3> n1;\n\n      if (!s1->PointOnSurface (p1))\n\tcontinue;\n\n\ts1->GetNormalVector (p1, n1);\n      n1 /= n1.Length();\n      if ( fabs(n1 * points.Get(i).v) > 1e-3)\n\tcontinue;\n\n      bestval = 1e8;\n      bestj = 1;\n      for (j = 1; j <= points.Size(); j++)\n\t{\n\t  Point<3> p2= points.Get(j).p;\n\t  if (!s2->PointOnSurface (p2))\n\t    continue;\n\t  \n\t  Vec<3> n2;\n\t  s2->GetNormalVector (p2, n2);\n\t  n2 /= n2.Length();\n\t  if ( fabs(n2 * points.Get(j).v) > 1e-3)\n\t    continue;\n\n\n\t  Vec<3> v(p1, p2);\n\t  double vl = v.Length();\n\t  double cl = fabs (v*n1);\n\n\t  val = 1 - cl*cl/(vl*vl);\n\n\t  val += (points.Get(i).v - points.Get(j).v).Length();\n\n\t  if (val < bestval)\n\t    {\n\t      bestj = j;\n\t      bestval = val;\n\t    }\n\t}\n\n      (*testout) << \"Identify close surfaces special points: pi = \" \n\t\t << points.Get(i).p << \", vi = \" << points.Get(i).v \n\t\t << \" pj = \" << points.Get(bestj).p \n\t\t << \", vj = \" << points.Get(bestj).v \n\t\t << \" bestval = \" << bestval << endl;\n    }\n}\n*/\n\nint CloseEdgesIdentification :: \nIdentifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t      const TABLE<int> & specpoint2solid,\n\t      const TABLE<int> & specpoint2surface) const\n{\n  int i;\n  double val;\n  \n  SpecialPoint hsp1 = sp1;\n  SpecialPoint hsp2 = sp2;\n\n  for (i = 1; i <= 1; i++)\n    {\n      if (!s1->PointOnSurface (hsp1.p))\n\tcontinue;\n\n      Vec<3> n1;\n      n1 = s1->GetNormalVector (hsp1.p);\n      n1 /= n1.Length();\n      if ( fabs(n1 * hsp1.v) > 1e-3)\n\tcontinue;\n\n\n      if (!s2->PointOnSurface(hsp2.p))\n\tcontinue;\n\n      Vec<3> n2;\n      n2 = s2->GetNormalVector (hsp2.p);\n      n2 /= n2.Length();\n      if ( fabs(n2 * hsp2.v) > 1e-3)\n\tcontinue;\n\n\n      Vec<3> v = hsp2.p - hsp1.p;\n      double vl = v.Length();\n      double cl = fabs (v*n1);\n      \n\n      val = 1 - cl*cl/(vl*vl);\n      val += (hsp1.v - hsp2.v).Length();\n    \n      if (val < 1e-3)\n\t{\n\t  return 1;\n\t}\n    }\n\n  return 0;\n}\n\n\n\n\nvoid CloseEdgesIdentification :: IdentifyPoints (Mesh & mesh)\n{\n  int np = mesh.GetNP();\n  for (int i1 = 1; i1 <= np; i1++)\n    for (int i2 = 1; i2 <= np; i2++)\n      {\n\tif (i2 == i1)\n\t  continue;\n\t\n\tconst Point<3> p1 = mesh.Point(i1);\n\tconst Point<3> p2 = mesh.Point(i2);\n\tPoint<3> pp1 = p1;\n\tPoint<3> pp2 = p2;\n\t\n\ts1->Project (pp1);\n\tfacet->Project (pp1);\n\ts2->Project (pp2);\n\tfacet->Project (pp2);\n\n\tif (Dist (p1, pp1) > 1e-6 || Dist (p2, pp2) > 1e-6)\n\t  continue;\n\n\tVec<3> n1, nf, t;\n\tVec<3> n = p2 - p1;\n\tn.Normalize();\n\n\tn1 = s1->GetNormalVector (p1);\n\tnf = facet->GetNormalVector (p1);\n\tt = Cross (n1, nf);\n\tt /= t.Length();\n\n\tif (fabs (n * t) < 0.5)\n\t  {\n\t    (*testout) << \"close edges identify points \" << p1 << \" - \" << p2 << endl;\n\t    mesh.GetIdentifications().Add (i1, i2, nr);\n\t    mesh.GetIdentifications().SetType(nr,Identifications::CLOSEEDGES);\n\t  }\n      }\n}\n\nvoid CloseEdgesIdentification :: \nBuildSurfaceElements (NgArray<Segment> & segs,\n\t\t      Mesh & mesh, const Surface * surf)\n{\n  int found = 0;\n\n  if (surf != facet)\n    return;\n\n  for (int i1 = 1; i1 <= segs.Size(); i1++)\n    for (int i2 = 1; i2 < i1; i2++)\n      {\n\tconst Segment & s1 = segs.Get(i1);\n\tconst Segment & s2 = segs.Get(i2);\n\tif (mesh.GetIdentifications().Used (s1[0], s2[1]) &&\n\t    mesh.GetIdentifications().Used (s1[1], s2[0]))\n\t  {\n\t    Element2d el(QUAD);\n\t    el.PNum(1) = s1[0];\n\t    el.PNum(2) = s1[1];\n\t    el.PNum(3) = s2[1];\n\t    el.PNum(4) = s2[0];\n\n\t    Vec<3> n = Cross (Point<3> (mesh.Point(el.PNum(2)))-\n\t\t\t      Point<3> (mesh.Point(el.PNum(1))),\n\t\t\t      Point<3> (mesh.Point(el.PNum(3)))-\n\t\t\t      Point<3> (mesh.Point(el.PNum(1))));\n\t    Vec<3> ns;\n\t    ns = surf->GetNormalVector (mesh.Point(el.PNum(1)));\n\t    //(*testout) << \"n = \" << n << \" ns = \" << ns << endl;\n\t    if (n * ns < 0)\n\t      {\n\t\t//(*testout) << \"Swap the quad\" << endl;\n\t\tSwap (el.PNum(1), el.PNum(2));\n\t\tSwap (el.PNum(3), el.PNum(4));\n\t      }\n\t\t\t     \n\t    \n\t    Swap (el.PNum(3), el.PNum(4));\n\t    mesh.AddSurfaceElement (el);\n//  \t    (*testout) << \"add rect element: \"\n//  \t\t       << mesh.Point (el.PNum(1)) << \" - \"\n//  \t\t       << mesh.Point (el.PNum(2)) << \" - \"\n//  \t\t       << mesh.Point (el.PNum(3)) << \" - \"\n//  \t\t       << mesh.Point (el.PNum(4)) << endl;\n\t    found = 1;\n\t  }\n      }\n\n  if (found)\n    segs.SetSize(0);\n}\n\n}\n\n"
  },
  {
    "path": "libsrc/csg/identify.hpp",
    "content": "\n#ifndef FILE_IDENTIFY\n#define FILE_IDENTIFY\n\n/**************************************************************************/\n/* File:   identify.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   1. Aug. 99                                                    */\n/**************************************************************************/\n\n\nnamespace netgen\n{\n\n  /**\n     Identify surfaces for periodic b.c. or\n     thin domains\n  */\n\n\n  class SpecialPoint;\n  class Identification\n  {\n  protected:\n    const CSGeometry & geom;\n    // identified faces, index sorted\n    INDEX_2_HASHTABLE<int> identfaces;\n    int nr;\n\n  public:\n    DLL_HEADER Identification (int anr, const CSGeometry & ageom);\n    DLL_HEADER virtual ~Identification ();\n    DLL_HEADER virtual void Print (ostream & ost) const = 0;\n    DLL_HEADER virtual void GetData (ostream & ost) const = 0;\n\n    /// obsolete\n    //  virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);\n\n    /// can identify both special points (fixed direction)\n    /// (identified points, same tangent)\n    virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t\t\t      const TABLE<int> & specpoint2solid,\t\t\t  \n\t\t\t      const TABLE<int> & specpoint2surface) const;\n    ///\n    virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const;\n    /// is it possible to identify sp1 with some other ?\n    virtual int IdentifiableCandidate (const SpecialPoint & sp1) const;\n  \n    /// are points (if connected) by a short edge (direction anyhow) ?\n    virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const;\n\n    /// add entries in mesh identification tables\n    virtual void IdentifyPoints (class Mesh & mesh);\n\n    /// add entries to identified faces (based on segment infos)\n    virtual void IdentifyFaces (class Mesh & mesh);\n\n    /// get point on other surface, add entry in mesh identifications\n    virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);\n\n    /// copy surfaces, or fill rectangles\n    virtual void BuildSurfaceElements (NgArray<class Segment> & segs,\n\t\t\t\t       class Mesh & mesh,\n\t\t\t\t       const Surface * surf);\n\n    /// insert volume elements in thin layers\n    virtual void BuildVolumeElements (NgArray<class Element2d> & surfels,\n\t\t\t\t      class Mesh & mesh);\n\n    /// get list of identified faces\n    virtual void GetIdentifiedFaces (NgArray<INDEX_2> & idfaces) const;\n\n    friend ostream & operator<< (ostream & ost, Identification & ident);\n  };\n\n\n  class PeriodicIdentification : public Identification\n  {\n    const Surface * s1;\n    const Surface * s2;\n    Transformation<3> trafo; // from s1 to s2\n    Transformation<3> inv_trafo; // from s2 to s1\n  public:\n    PeriodicIdentification (int anr,\n\t\t\t    const CSGeometry & ageom,\n\t\t\t    const Surface * as1,\n\t\t\t    const Surface * as2,\n                            Transformation<3> atrafo = Vec<3>(0,0,0));\n    virtual ~PeriodicIdentification () override;\n    virtual void Print (ostream & ost) const override;\n    virtual void GetData (ostream & ost) const override;\n\n\n    //  virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);\n    virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t\t\t      const TABLE<int> & specpoint2solid,\n\t\t\t      const TABLE<int> & specpoint2surface) const override;\n\n    virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const override;\n    virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1) override;\n    virtual void IdentifyPoints (class Mesh & mesh) override;\n    virtual void IdentifyFaces (class Mesh & mesh) override;\n    virtual void BuildSurfaceElements (NgArray<class Segment> & segs,\n\t\t\t\t       class Mesh & mesh,\n\t\t\t\t       const Surface * surf) override;\n  };\n\n\n  ///\n  class TopLevelObject;\n  class CloseSurfaceIdentification : public Identification\n  {\n    const Surface * s1;\n    const Surface * s2;\n    const TopLevelObject * domain;\n    ///\n    int dom_nr;\n    /// number of refinement levels (in Z-refinement)\n    int ref_levels;\n    /// number of refinement levels for layer next to s1 (in Z-refinement)\n    int ref_levels_s1;\n    /// number of refinement levels for layer next to s2 (in Z-refinement)\n    int ref_levels_s2;\n    ///\n    double eps_n;\n    Array<double> slices;\n    /// used only for domain-local identification:\n    NgArray<int> domain_surfaces;\n    ///\n    bool dom_surf_valid;\n\n    ///\n    Vec<3> direction;\n    ///\n    bool usedirection;\n  public:\n    CloseSurfaceIdentification (int anr, \n\t\t\t\tconst CSGeometry & ageom,\n\t\t\t\tconst Surface * as1,\n\t\t\t\tconst Surface * as2,\n\t\t\t\tconst TopLevelObject * adomain,\n\t\t\t\tconst Flags & flags);\n    virtual ~CloseSurfaceIdentification ();\n\n    virtual void Print (ostream & ost) const;\n    virtual void GetData (ostream & ost) const;\n\n\n    //  virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);\n    virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t\t\t      const TABLE<int> & specpoint2solid,\n\t\t\t      const TABLE<int> & specpoint2surface) const;\n    virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const;\n    virtual int IdentifiableCandidate (const SpecialPoint & sp1) const;\n    virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const;\n    virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);\n    const Array<double> & GetSlices () const { return slices; }\n    virtual void IdentifyPoints (class Mesh & mesh);\n    virtual void IdentifyFaces (class Mesh & mesh);\n    virtual void BuildSurfaceElements (NgArray<class Segment> & segs,\n\t\t\t\t       class Mesh & mesh,\n\t\t\t\t       const Surface * surf);\n    void BuildSurfaceElements2 (NgArray<class Segment> & segs,\n\t\t\t\tclass Mesh & mesh,\n\t\t\t\tconst Surface * surf);\n\n    virtual void BuildVolumeElements (NgArray<class Element2d> & surfels,\n\t\t\t\t      class Mesh & mesh);\n\n    int RefLevels () const { return ref_levels; }\n    int RefLevels1 () const { return ref_levels_s1; }\n    int RefLevels2 () const { return ref_levels_s2; }\n\n    bool IsSkewIdentification(void) const {return usedirection;}\n    const Vec<3> & GetDirection(void) const {return direction;}\n\n    const Surface & GetSurface1(void) const\n    { return *s1;}\n    const Surface & GetSurface2(void) const\n    { return *s2;}\n  };\n\n\n  class CloseEdgesIdentification : public Identification\n  {\n    const Surface * facet;\n    const Surface * s1;\n    const Surface * s2;\n  public:\n    CloseEdgesIdentification (int anr,\n\t\t\t      const CSGeometry & ageom,\n\t\t\t      const Surface * afacet,\n\t\t\t      const Surface * as1,\n\t\t\t      const Surface * as2);\n    virtual ~CloseEdgesIdentification ();\n    virtual void Print (ostream & ost) const;\n    virtual void GetData (ostream & ost) const;\n\n    //  virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);\n    virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,\n\t\t\t      const TABLE<int> & specpoint2solid,\n\t\t\t      const TABLE<int> & specpoint2surface) const;\n\n\n    virtual void IdentifyPoints (class Mesh & mesh);\n    virtual void BuildSurfaceElements (NgArray<class Segment> & segs,\n\t\t\t\t       class Mesh & mesh,\n\t\t\t\t       const Surface * surf);\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/manifold.cpp",
    "content": "#include <csg.hpp>\n\nnamespace netgen\n{\nManifold :: Manifold () \n{\n  ;\n}\n\nManifold :: ~Manifold () \n{\n  ;\n}\n}\n"
  },
  {
    "path": "libsrc/csg/manifold.hpp",
    "content": "#ifndef FILE_MANIFOLD\n#define FILE_MANIFOLD\n\n/**************************************************************************/\n/* File:   manifold.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   7. Aug. 96                                                     */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n  /**\n     Basis class for manifolds in 2d and 3d\n  */\n  class Manifold\n  {\n  public:\n    ///\n    Manifold ();\n    ///\n    virtual ~Manifold ();\n  };\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/meshsurf.cpp",
    "content": "#include <mystdlib.h>\n\n#include <csg.hpp>\n#include <meshing.hpp>\n\n\n\nnamespace netgen\n{\n  /*\nMeshing2Surfaces :: Meshing2Surfaces (const Surface & asurface)\n  : surface(asurface)\n{\n  ;\n}\n  */\n  Meshing2Surfaces :: Meshing2Surfaces (const CSGeometry& geo,\n                                        const Surface & asurf,\n                                        const MeshingParameters & mp,\n                                        const Box<3> & abb)\n    : Meshing2(geo, mp, abb), surface(asurf), mparam (mp)\n  {\n    ;\n  }\n\n\nvoid Meshing2Surfaces :: DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n\t\t\t\t\t       const PointGeomInfo * geominfo1,\n\t\t\t\t\t       const PointGeomInfo * geominfo2)\n{\n  ((Surface&)surface).DefineTangentialPlane (p1, p2);\n}\n\nvoid Meshing2Surfaces :: TransformToPlain (const Point<3> & locpoint, \n\t\t\t\t\t   const MultiPointGeomInfo & geominfo,\n\t\t\t\t\t   Point<2> & planepoint, \n\t\t\t\t\t   double h, int & zone)\n{\n  surface.ToPlane (locpoint, planepoint, h, zone);\n}\n\nint Meshing2Surfaces :: TransformFromPlain (const Point<2> & planepoint,\n                                            Point<3> & locpoint, \n                                            PointGeomInfo & gi,\n                                            double h)\n{\n  surface.FromPlane (planepoint, locpoint, h);\n  gi.trignum = 1;\n  return 0;\n}\n\n\n\ndouble Meshing2Surfaces :: CalcLocalH (const Point<3> & p, double gh) const\n{\n  return surface.LocH (p, 3, 1, mparam, gh);\n  /*\n    double loch = mesh.lochfunc->GetH(p);\n    if (gh < loch) loch = gh;\n    return loch;\n    */\n}\n}\n"
  },
  {
    "path": "libsrc/csg/meshsurf.hpp",
    "content": "#ifndef FILE_MESHSURF\n#define FILE_MESHSURF\n\nnamespace netgen\n{\n\n  ///\n  class Meshing2Surfaces : public Meshing2\n  {\n    ///\n    const Surface & surface;\n    \n    /// should be movec to base ... \n    const MeshingParameters & mparam;\n  public:\n    ///\n    //  Meshing2Surfaces (const Surface & asurf);\n    ///\n    Meshing2Surfaces (const CSGeometry& geo,\n                      const Surface & asurf,\n                      const MeshingParameters & mp,\n\t\t      const Box<3> & aboundingbox);\n\n  protected:\n    ///\n    void DefineTransformation(const Point<3> & p1,\n                              const Point<3> & p2,\n                              const PointGeomInfo * geominfo1,\n                              const PointGeomInfo * geominfo2) override;\n    ///\n    void TransformToPlain(const Point<3> & locpoint, \n                          const MultiPointGeomInfo & geominfo,\n                          Point<2> & plainpoint, \n                          double h, int & zone) override;\n    ///\n    int TransformFromPlain(const Point<2>& plainpoint,\n                           Point<3>& locpoint, \n                           PointGeomInfo & gi,\n                           double h) override;\n    ///\n    double CalcLocalH(const Point<3> & p, double gh) const override;\n  };\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/csg/polyhedra.cpp",
    "content": "#include <mystdlib.h>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\nnamespace netgen\n{\n\n  Polyhedra::Face::Face (int pi1, int pi2, int pi3,\n                         const NgArray<Point<3> > & points,\n                         int ainputnr)\n  {\n    inputnr = ainputnr;\n\n    pnums[0] = pi1;\n    pnums[1] = pi2;\n    pnums[2] = pi3;\n\n\n    bbox.Set (points[pi1]);\n    bbox.Add (points[pi2]);\n    bbox.Add (points[pi3]);\n\n    v1 = points[pi2] - points[pi1];\n    v2 = points[pi3] - points[pi1];\n\n    n = Cross (v1, v2);\n\n    nn = n;\n    nn.Normalize();\n    //  PseudoInverse (v1, v2, w1, w2);\n  \n    Mat<2,3> mat;\n    Mat<3,2> inv;\n    for (int i = 0; i < 3; i++)\n      {\n        mat(0,i) = v1(i);\n        mat(1,i) = v2(i);\n      }\n    CalcInverse (mat, inv);\n    for (int i = 0; i < 3; i++)\n      {\n        w1(i) = inv(i,0);\n        w2(i) = inv(i,1);\n      }\n  }\n\n\n  Polyhedra :: Polyhedra ()\n  {\n    surfaceactive.SetSize(0);\n    surfaceids.SetSize(0);\n    eps_base1 = 1e-8;\n  }\n\n  Polyhedra :: ~Polyhedra ()\n  {\n    ;\n  }\n\n  Primitive * Polyhedra :: CreateDefault ()\n  {\n    return new Polyhedra();\n  }\n\n  INSOLID_TYPE Polyhedra :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    /*\n      for (i = 1; i <= faces.Size(); i++)\n      if (FaceBoxIntersection (i, box))\n      return DOES_INTERSECT;\n    */\n    for (int i = 0; i < faces.Size(); i++)\n      {\n        if (!faces[i].bbox.Intersect (box))\n          continue;\n        //(*testout) << \"face \" << i << endl;\n\n        const Point<3> & p1 = points[faces[i].pnums[0]];\n        const Point<3> & p2 = points[faces[i].pnums[1]];\n        const Point<3> & p3 = points[faces[i].pnums[2]];\n\n        if (fabs (faces[i].nn * (p1 - box.Center())) > box.Diam()/2)\n          continue;\n\n        //(*testout) << \"still in loop\" << endl;\n\n        double dist2 = MinDistTP2 (p1, p2, p3, box.Center());\n        //(*testout) << \"p1 \" << p1 << \" p2 \" << p2 << \" p3 \" << p3 << endl\n        //\t\t << \" box.Center \" << box.Center() << \" box.Diam() \" << box.Diam() << endl\n        //\t << \" dist2 \" << dist2 << \" sqr(box.Diam()/2) \" << sqr(box.Diam()/2) << endl;\n        if (dist2 < sqr (box.Diam()/2))\n          {\n            //(*testout) << \"DOES_INTERSECT\" << endl;\n            return DOES_INTERSECT;\n          }\n      };\n\n    return PointInSolid (box.Center(), 1e-3 * box.Diam());\n  }\n\n\n  // check how many faces a ray starting in p intersects\n  INSOLID_TYPE Polyhedra :: PointInSolid (const Point<3> & p,\n                                          double eps) const\n  {\n    if (!poly_bbox.IsIn (p, eps))\n      return IS_OUTSIDE;\n\n    // random (?) direction:\n    Vec<3> n(-0.424621, 0.1543, 0.89212238);\n\n    int cnt = 0;\n    for (auto & face : faces)\n      {\n        Vec<3> v0 = p - points[face.pnums[0]];\n\n        double lam3 = face.nn * v0;\n\n        if (fabs(lam3) < eps)    // point is in plance of face\n          {\n            double lam1 = face.w1 * v0;\n            double lam2 = face.w2 * v0;\n            if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)\n              return DOES_INTERSECT;\n          }\n        else\n          {\n            double lam3 = -(face.n * v0) / (face.n * n);\n\n            if (lam3 < 0) continue;    // ray goes not in direction of face\n\n            Vec<3> rs = v0 + lam3 * n;\n\t  \n            double lam1 = face.w1 * rs;\n            double lam2 = face.w2 * rs;\n            if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1)\n              cnt++;\n          }\n      }\n\n    return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE;\n  }\n\n\n\n\n  void Polyhedra :: GetTangentialSurfaceIndices (const Point<3> & p, \n                                                 NgArray<int> & surfind, double eps) const\n  {\n    for (int i = 0; i < faces.Size(); i++)\n      {\n        auto & face = faces[i];\n        const Point<3> & p1 = points[face.pnums[0]];\n      \n        Vec<3> v0 = p - p1;\n        double lam3 = -(face.nn * v0); // n->nn\n\n        if (fabs (lam3) > eps) continue;\n\n        double lam1 = (face.w1 * v0);\n        double lam2 = (face.w2 * v0);\n\n        if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)\n          if (!surfind.Contains (GetSurfaceId(i)))\n            surfind.Append (GetSurfaceId(i));\n      }\n\n  }\n\n  INSOLID_TYPE Polyhedra :: VecInSolidOld (const Point<3> & p,\n                                           const Vec<3> & v,\n                                           double eps) const\n  {\n    NgArray<int> point_on_faces;\n    INSOLID_TYPE res(DOES_INTERSECT);\n\n    Vec<3> vn = v;\n    vn.Normalize();\n    for (int i = 0; i < faces.Size(); i++)\n      {\n        const Point<3> & p1 = points[faces[i].pnums[0]];\n      \n        Vec<3> v0 = p - p1;\n        double lam3 = -(faces[i].nn * v0); // n->nn \n\n\n        if (fabs (lam3) > eps) continue;\n        //(*testout) << \"lam3 <= eps\" << endl;\n\n        double lam1 = (faces[i].w1 * v0);\n        double lam2 = (faces[i].w2 * v0);\n\n        if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)\n          {\n            point_on_faces.Append(i);\n\n            double scal = vn * faces[i].nn; // n->nn\n\t\n            res = DOES_INTERSECT;\n            if (scal > eps_base1) res = IS_OUTSIDE;\n            if (scal < -eps_base1) res = IS_INSIDE;\n          }\n      }\n  \n    //(*testout) << \"point_on_faces.Size() \" << point_on_faces.Size() \n    //\t     << \" res \" << res << endl;\n\n    if (point_on_faces.Size() == 0)\n      return PointInSolid (p, 0);\n    if (point_on_faces.Size() == 1)\n      return res;\n\n\n\n  \n    double mindist(0);\n    bool first = true;\n\n    for(int i=0; i<point_on_faces.Size(); i++)\n      {\n        for(int j=0; j<3; j++)\n          {\n            double dist = Dist(p,points[faces[point_on_faces[i]].pnums[j]]);\n            if(dist > eps && (first || dist < mindist))\n              {\n                mindist = dist;\n                first = false;\n              }\n          }\n      }\n  \n    Point<3> p2 = p + (1e-4*mindist) * vn;\n    res = PointInSolid (p2, eps);\n\n    //  (*testout) << \"mindist \" << mindist << \" res \" << res << endl;\n\n    return res;\n  }\n\n\n\n  // check how many faces a ray starting in p+alpha*v intersects\n  INSOLID_TYPE Polyhedra :: VecInSolidNew (const Point<3> & p,\n                                           const Vec<3> & v,\n                                           double eps, bool printing) const\n  {\n    if (!poly_bbox.IsIn (p, eps))\n      return IS_OUTSIDE;\n\n    // random (?) direction:\n    Vec<3> n(-0.424621, 0.1543, 0.89212238);\n\n    int cnt = 0;\n    for (auto & face : faces)\n      {\n        Vec<3> v0 = p - points[face.pnums[0]];\n        if (printing)\n          {\n            *testout << \"face: \";\n            for (int j = 0; j < 3; j++)\n              *testout << points[face.pnums[j]] << \" \";\n            *testout << endl;\n          }\n        double lamn = face.nn * v0;\n\n        if (fabs(lamn) < eps)    // point is in plane of face\n          {\n            double lam1 = face.w1 * v0;\n            double lam2 = face.w2 * v0;\n            double lam3 = 1-lam1-lam2;\n            if (printing)\n              *testout << \"lam = \" << lam1 << \" \" << lam2 << \" \" << lam3 << endl;\n            if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam3 >= -eps_base1)\n              {  // point is close to triangle, perturbed by alpha*v \n                double dlamn = face.nn*v;\n\n                if (fabs(dlamn) < 1e-8) // vec also in plane\n                  {\n                    if (printing)\n                      *testout << \"tang in plane\" << endl;\n                    double dlam1 = face.w1 * v;\n                    double dlam2 = face.w2 * v;\n                    double dlam3 = -dlam1-dlam2;\n                    if (printing)\n                      *testout << \"dlam = \" << dlam1 << \" \" << dlam2 << \" \" << dlam3 << endl;\n                    bool in1 = lam1 > eps_base1 || dlam1 > -eps_base1;\n                    bool in2 = lam2 > eps_base1 || dlam2 > -eps_base1;\n                    bool in3 = lam3 > eps_base1 || dlam3 > -eps_base1;\n                    if (in1 && in2 && in3)\n                      return DOES_INTERSECT;\n                  }\n                else // vec out of plane\n                  {\n                    if (printing)\n                      *testout << \"out of plane\";\n                    double dlamn = -(face.n * v) / (face.n * n);\n                    if (printing)\n                      *testout << \"dlamn = \" << dlamn << endl;\n                    if (dlamn < 0) continue;    // ray goes not in direction of face\n\n                    Vec<3> drs = v + dlamn * n;\n                    if (printing)\n                      {\n                        *testout << \"drs = \" << drs << endl;\n                        *testout << \"face.w1 = \" << face.w1 << endl;\n                        *testout << \"face.w2 = \" << face.w2 << endl;\n                      }\n                    \n                    double dlam1 = face.w1 * drs;\n                    double dlam2 = face.w2 * drs;\n                    double dlam3 = -dlam1-dlam2;\n\n                    if (printing)\n                      *testout << \"dlam = \" << dlam1 << \" \" << dlam2 << \" \" << dlam3 << endl;\n                  \n                    bool in1 = lam1 > eps_base1 || dlam1 > -eps_base1;\n                    bool in2 = lam2 > eps_base1 || dlam2 > -eps_base1;\n                    bool in3 = lam3 > eps_base1 || dlam3 > -eps_base1;\n                    \n                    if (in1 && in2 && in3)\n                      {\n                        if (printing)\n                          *testout << \"hit\" << endl;\n                        cnt++;\n                      }\n                  }\n              }\n          }\n        else\n          {\n            double lamn = -(face.n * v0) / (face.n * n);\n\n            if (lamn < 0) continue;    // ray goes not in direction of face\n\n            Vec<3> rs = v0 + lamn * n;\n\t  \n            double lam1 = face.w1 * rs;\n            double lam2 = face.w2 * rs;\n            double lam3 = 1-lam1-lam2;\n            if (lam1 >= 0 && lam2 >= 0 && lam3 >= 0)\n              {\n                if (printing)\n                  *testout << \"hit\" << endl;\n                cnt++;\n              }\n          }\n      }\n\n    return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE;\n  }\n\n\n  INSOLID_TYPE Polyhedra :: VecInSolid (const Point<3> & p,\n                                        const Vec<3> & v,\n                                        double eps) const\n  {\n    return VecInSolidNew (p, v, eps);\n    /*\n    auto oldval = VecInSolidOld (p, v, eps);\n    auto newval = VecInSolidNew (p, v, eps);\n    if (oldval != newval)\n      {\n        *testout << \"different decision: oldval = \" << oldval \n                 << \" newval = \" << newval << endl;\n        *testout << \"p = \" << p << \", v = \" << v << endl;\n        VecInSolidNew (p, v, eps, true);\n        *testout << \"Poly:\" << endl;\n        for (auto & face : faces)\n          {\n            for (int j = 0; j < 3; j++)\n              *testout << points[face.pnums[j]] << \" \";\n            *testout << endl;\n          }\n      }\n    return newval;\n    */\n  }\n\n\n\n\n\n\n\n  \n    /*\n      INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p,\n      const Vec<3> & v1,\n      const Vec<3> & v2,\n      double eps) const\n      {\n      INSOLID_TYPE res;\n\n      res = VecInSolid(p,v1,eps);\n      if(res != DOES_INTERSECT)\n      return res;\n\n      int point_on_n_faces = 0;\n\n      Vec<3> v1n = v1;\n      v1n.Normalize();\n      Vec<3> v2n = v2;\n      v2n.Normalize();\n\n\n      for (int i = 0; i < faces.Size(); i++)\n      {\n      const Point<3> & p1 = points[faces[i].pnums[0]];\n      \n      Vec<3> v0 = p - p1;\n      double lam3 = -(faces[i].n * v0);\n\n      if (fabs (lam3) > eps) continue;\n\n      double lam1 = (faces[i].w1 * v0);\n      double lam2 = (faces[i].w2 * v0);\n\n      if (lam1 >= -eps && lam2 >= -eps && lam1+lam2 <= 1+eps)\n      {\n      double scal1 = v1n * faces[i].n;\n      if (fabs (scal1) > eps) continue;\n\n\n      point_on_n_faces++;\n\n      double scal2 = v2n * faces[i].n;\n      res = DOES_INTERSECT;\n      if (scal2 > eps) res = IS_OUTSIDE;\n      if (scal2 < -eps) res = IS_INSIDE;\n      }\n      }\n\n      if (point_on_n_faces == 1)\n      return res;\n\n      cerr << \"primitive::vecinsolid2 makes nonsense for polyhedra\" << endl;\n\n      return Primitive :: VecInSolid2 (p, v1, v2, eps);\n      }\n    */\n\n\n  // #define OLDVECINSOLID2\n#ifdef OLDVECINSOLID2\n    INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p,\n                                           const Vec<3> & v1,\n                                           const Vec<3> & v2,\n                                           double eps) const\n    {\n      //(*testout) << \"VecInSolid2 eps \" << eps << endl;\n      INSOLID_TYPE res = VecInSolid(p,v1,eps);\n      //(*testout) << \"VecInSolid = \" <<res <<endl;\n\n      if(res != DOES_INTERSECT)\n        return res;\n\n      int point_on_n_faces = 0;\n\n      Vec<3> v1n = v1;\n      v1n.Normalize();\n      Vec<3> v2n = v2 - (v2 * v1n) * v1n;\n      v2n.Normalize();\n\n      double cosv2, cosv2max = -99;\n\n  \n      for (int i = 0; i < faces.Size(); i++)\n        {\n          const Point<3> & p1 = points[faces[i].pnums[0]];\n      \n          Vec<3> v0 = p - p1;\n          if (fabs (faces[i].nn * v0) > eps) continue; // n->nn\n          if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn\n\n          double lam1 = (faces[i].w1 * v0);\n          double lam2 = (faces[i].w2 * v0);\n\n          if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)\n            {\n              // v1 is in face\n\n              Point<3> fc = Center (points[faces[i].pnums[0]],\n                                    points[faces[i].pnums[1]],\n                                    points[faces[i].pnums[2]]);\n\n              Vec<3> vpfc = fc - p;\n              cosv2 = (v2n * vpfc) / vpfc.Length();\n              if (cosv2 > cosv2max)\n                {\n                  cosv2max = cosv2;\n                  point_on_n_faces++;\n\n                  double scal2 = v2n * faces[i].nn; // n->nn\n                  res = DOES_INTERSECT;\n                  if (scal2 > eps_base1) res = IS_OUTSIDE;\n                  if (scal2 < -eps_base1) res = IS_INSIDE;\n\n                }\n            }\n        }\n\n      if (point_on_n_faces >= 1)\n        return res;\n\n      (*testout) << \"primitive::vecinsolid2 makes nonsense for polyhedra\" << endl;\n      cerr << \"primitive::vecinsolid2 makes nonsense for polyhedra\" << endl;\n\n      return Primitive :: VecInSolid2 (p, v1, v2, eps);\n    }\n\n\n\n#else\n\n\n  // check how many faces a ray starting in p+alpha*v+alpha^2/2 v2 intersects:\n  // if p + alpha v is in plane, use v2\n  INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p,\n                                         const Vec<3> & v,\n                                         const Vec<3> & v2,\n                                         double eps) const\n  {\n    if (!poly_bbox.IsIn (p, eps))\n      return IS_OUTSIDE;\n\n    // random (?) direction:\n    Vec<3> n(-0.424621, 0.1543, 0.89212238);\n\n    int cnt = 0;\n    for (auto & face : faces)\n      {\n        Vec<3> v0 = p - points[face.pnums[0]];\n        double lamn = face.nn * v0;\n\n        if (fabs(lamn) < eps)    // point is in plane of face\n          {\n            double lam1 = face.w1 * v0;\n            double lam2 = face.w2 * v0;\n            double lam3 = 1-lam1-lam2;\n\n            if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam3 >= -eps_base1)\n              {  // point is close to triangle, perturbed by alpha*v\n                double dlamn = face.nn*v;\n\n                if (fabs(dlamn) < 1e-8) // vec also in plane\n                  {\n                    double dlam1 = face.w1 * v;\n                    double dlam2 = face.w2 * v;\n                    double dlam3 = -dlam1-dlam2;\n\n                    bool in1 = lam1 > eps_base1 || dlam1 > -eps_base1;\n                    bool in2 = lam2 > eps_base1 || dlam2 > -eps_base1;\n                    bool in3 = lam3 > eps_base1 || dlam3 > -eps_base1;\n\n                    // and the same thing for v2\n                    if (in1 && in2 && in3)\n                      {  \n                        double ddlamn = face.nn*v2;\n                        \n                        if (fabs(ddlamn) < 1e-8) // vec2 also in plane\n                          {\n                            double ddlam1 = face.w1 * v2;\n                            double ddlam2 = face.w2 * v2;\n                            double ddlam3 = -ddlam1-ddlam2;\n                            \n                            bool ddin1 = lam1 > eps_base1 || dlam1 > eps_base1 || ddlam1 > -eps_base1;\n                            bool ddin2 = lam2 > eps_base1 || dlam2 > eps_base1 || ddlam2 > -eps_base1;\n                            bool ddin3 = lam3 > eps_base1 || dlam3 > eps_base1 || ddlam3 > -eps_base1;\n                            if (ddin1 && ddin2 && ddin3)\n                              return DOES_INTERSECT;\n                          }\n                        else // vec2 out of plane\n                          {\n                            double ddlamn = -(face.n * v2) / (face.n * n);\n                            if (ddlamn < 0) continue;    // ray goes not in direction of face\n                            \n                            Vec<3> drs = v; //  + dlamn * n;   but dlamn==0\n                            Vec<3> ddrs = v2 + ddlamn * n;\n                            \n                            double dlam1 = face.w1 * drs;\n                            double dlam2 = face.w2 * drs;\n                            double dlam3 = -dlam1-dlam2;\n                            \n                            double ddlam1 = face.w1 * ddrs;\n                            double ddlam2 = face.w2 * ddrs;\n                            double ddlam3 = -ddlam1-ddlam2;\n                            \n                            bool ddin1 = lam1 > eps_base1 || dlam1 > eps_base1 || ddlam1 > -eps_base1;\n                            bool ddin2 = lam2 > eps_base1 || dlam2 > eps_base1 || ddlam2 > -eps_base1;\n                            bool ddin3 = lam3 > eps_base1 || dlam3 > eps_base1 || ddlam3 > -eps_base1;\n                            \n                            if (ddin1 && ddin2 && ddin3)\n                              cnt++;\n                          }\n                      } \n                  }\n                else // vec out of plane\n                  {\n                    double dlamn = -(face.n * v) / (face.n * n);\n                    if (dlamn < 0) continue;    // ray goes not in direction of face\n\n                    Vec<3> drs = v + dlamn * n;\n                    \n                    double dlam1 = face.w1 * drs;\n                    double dlam2 = face.w2 * drs;\n                    double dlam3 = -dlam1-dlam2;\n                  \n                    bool in1 = lam1 > eps_base1 || dlam1 > -eps_base1;\n                    bool in2 = lam2 > eps_base1 || dlam2 > -eps_base1;\n                    bool in3 = lam3 > eps_base1 || dlam3 > -eps_base1;\n\n                    if (in1 && in2 && in3)\n                      cnt++;\n\n                  }\n              }\n          }\n        else\n          {\n            double lamn = -(face.n * v0) / (face.n * n);\n\n            if (lamn < 0) continue;    // ray goes not in direction of face\n\n            Vec<3> rs = v0 + lamn * n;\n\t  \n            double lam1 = face.w1 * rs;\n            double lam2 = face.w2 * rs;\n            double lam3 = 1-lam1-lam2;\n            if (lam1 >= 0 && lam2 >= 0 && lam3 >= 0)\n              cnt++;\n          }\n      }\n\n    return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE;\n  }\n#endif\n\n\n\n\n\n  \n\n  INSOLID_TYPE Polyhedra :: VecInSolid3 (const Point<3> & p,\n                                         const Vec<3> & v1,\n                                         const Vec<3> & v2,\n                                         double eps) const \n  {\n    return VecInSolid2 (p, v1, v2, eps);\n  }\n  \n  INSOLID_TYPE Polyhedra :: VecInSolid4 (const Point<3> & p,\n                                         const Vec<3> & v,\n                                         const Vec<3> & v2,\n                                         const Vec<3> & m,\n                                         double eps) const\n  {\n    auto res = VecInSolid2 (p, v, v2, eps);\n    \n    if (res == DOES_INTERSECT)   // following edge second order, let m decide\n      return VecInSolid2 (p, v, m, eps);\n    \n    return res;\n  }\n\n\n  \n\n  void Polyhedra :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n                                                     NgArray<int> & surfind, double eps) const\n  {\n    Vec<3> v1n = v1;\n    v1n.Normalize();\n    Vec<3> v2n = v2; //  - (v2 * v1n) * v1n;\n    v2n.Normalize();\n\n\n    for (int i = 0; i < faces.Size(); i++)\n      {\n        const Point<3> & p1 = points[faces[i].pnums[0]];\n      \n        Vec<3> v0 = p - p1;\n        if (fabs (v0 * faces[i].nn) > eps) continue; // n->nn\n        if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn\n        if (fabs (v2n * faces[i].nn) > eps_base1) continue; // n->nn\n\n        double lam01 = (faces[i].w1 * v0);\n        double lam02 = (faces[i].w2 * v0);\n        double lam03 = 1-lam01-lam02;\n        double lam11 = (faces[i].w1 * v1);\n        double lam12 = (faces[i].w2 * v1);\n        double lam13 = -lam11-lam12;\n        double lam21 = (faces[i].w1 * v2);\n        double lam22 = (faces[i].w2 * v2);\n        double lam23 = -lam21-lam22;\n\n        bool ok1 = lam01 > eps_base1 ||\n          (lam01 > -eps_base1 && lam11 > eps_base1) ||\n          (lam01 > -eps_base1 && lam11 > -eps_base1 && lam21 > eps_base1);\n\n        bool ok2 = lam02 > eps_base1 ||\n          (lam02 > -eps_base1 && lam12 > eps_base1) ||\n          (lam02 > -eps_base1 && lam12 > -eps_base1 && lam22 > eps_base1);\n      \n        bool ok3 = lam03 > eps_base1 ||\n          (lam03 > -eps_base1 && lam13 > eps_base1) ||\n          (lam03 > -eps_base1 && lam13 > -eps_base1 && lam23 > eps_base1);\n\n        if (ok1 && ok2 && ok3)\n          {\n            if (!surfind.Contains (GetSurfaceId(faces[i].planenr)))\n              surfind.Append (GetSurfaceId(faces[i].planenr));\n          }\n      }  \n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  void Polyhedra :: GetPrimitiveData (const char *& classname, \n                                      NgArray<double> & coeffs) const\n  {\n    classname = \"Polyhedra\";\n    coeffs.SetSize(0);\n    coeffs.Append (points.Size());\n    coeffs.Append (faces.Size());\n    coeffs.Append (planes.Size());\n\n    /*\n      int i, j;\n      for (i = 1; i <= planes.Size(); i++)\n      {\n      planes.Elem(i)->Print (*testout);\n      }\n      for (i = 1; i <= faces.Size(); i++)\n      {\n      (*testout) << \"face \" << i << \" has plane \" << faces.Get(i).planenr << endl;\n      for (j = 1; j <= 3; j++)\n      (*testout) << points.Get(faces.Get(i).pnums[j-1]);\n      (*testout) << endl;\n      }\n    */\n  }\n\n  void Polyhedra :: SetPrimitiveData (NgArray<double> & /* coeffs */)\n  {\n    ;\n  }\n\n  void Polyhedra :: Reduce (const BoxSphere<3> & box)\n  {\n    for (int i = 0; i < planes.Size(); i++)\n      surfaceactive[i] = 0;\n\n    for (int i = 0; i < faces.Size(); i++)\n      if (FaceBoxIntersection (i, box))\n        surfaceactive[faces[i].planenr] = 1;\n  }\n\n  void Polyhedra :: UnReduce ()\n  {\n    for (int i = 0; i < planes.Size(); i++)\n      surfaceactive[i] = 1;\n  }\n\n  int Polyhedra :: AddPoint (const Point<3> & p)\n  {\n    if(points.Size() == 0)\n      poly_bbox.Set(p);\n    else\n      poly_bbox.Add(p);\n\n    points.Append (p);\n    return points.Size();\n  }\n\n  int Polyhedra :: AddFace (int pi1, int pi2, int pi3, int inputnum)\n  {\n    (*testout) << \"polyhedra, add face \" << pi1 << \", \" << pi2 << \", \" << pi3 << endl;\n\n    if(pi1 == pi2 || pi2 == pi3 || pi3 == pi1)\n      {\n        ostringstream msg;\n        msg << \"Illegal point numbers for polyhedron face: \" << pi1+1 << \", \" << pi2+1 << \", \" << pi3+1;\n        throw NgException(msg.str());\n      }\n\n    faces.Append (Face (pi1, pi2, pi3, points, inputnum));\n  \n    Point<3> p1 = points[pi1];\n    Point<3> p2 = points[pi2];\n    Point<3> p3 = points[pi3];\n\n    Vec<3> v1 = p2 - p1;\n    Vec<3> v2 = p3 - p1;\n\n    Vec<3> n = Cross (v1, v2); \n    n.Normalize();\n\n    Plane pl (p1, n);\n    //   int inverse;\n    //   int identicto = -1;\n    //   for (int i = 0; i < planes.Size(); i++)\n    //     if (pl.IsIdentic (*planes[i], inverse, 1e-9*max3(v1.Length(),v2.Length(),Dist(p2,p3))))\n    //       {\n    // \tif (!inverse)\n    // \t  identicto = i;\n    //       }\n    //   //  cout << \"is identic = \" << identicto << endl;\n    //   identicto = -1;    // changed April 10, JS\n\n    //   if (identicto != -1)\n    //     faces.Last().planenr = identicto;\n    //   else\n    {\n      planes.Append (new Plane (p1, n));\n      surfaceactive.Append (1);\n      surfaceids.Append (0);\n      faces.Last().planenr = planes.Size()-1;\n    }\n\n    //  (*testout) << \"is plane nr \" << faces.Last().planenr << endl;\n\n    return faces.Size();\n  }\n\n\n\n  int Polyhedra :: FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const\n  {\n    /*\n      (*testout) << \"check face box intersection, fnr = \" << fnr << endl;\n      (*testout) << \"box = \" << box << endl;\n      (*testout) << \"face-box = \" << faces[fnr].bbox << endl;\n    */\n\n    if (!faces[fnr].bbox.Intersect (box))\n      return 0;\n\n    const Point<3> & p1 = points[faces[fnr].pnums[0]];\n    const Point<3> & p2 = points[faces[fnr].pnums[1]];\n    const Point<3> & p3 = points[faces[fnr].pnums[2]];\n\n    double dist2 = MinDistTP2 (p1, p2, p3, box.Center());\n    /*\n      (*testout) << \"p1 = \" << p1 << endl;\n      (*testout) << \"p2 = \" << p2 << endl;\n      (*testout) << \"p3 = \" << p3 << endl;\n\n      (*testout) << \"box.Center() = \" << box.Center() << endl;\n      (*testout) << \"center = \" << box.Center() << endl;\n      (*testout) << \"dist2 = \" << dist2 << endl;\n      (*testout) << \"diam = \" << box.Diam() << endl;\n    */\n    if (dist2 < sqr (box.Diam()/2))\n      {\n        //      (*testout) << \"intersect\" << endl;\n        return 1;\n      }\n    return 0;\n  }\n\n\n  void Polyhedra :: GetPolySurfs(NgArray < NgArray<int> * > & polysurfs)\n  {\n    int maxnum = -1;\n  \n    for(int i = 0; i<faces.Size(); i++)\n      {\n        if(faces[i].inputnr > maxnum)\n          maxnum = faces[i].inputnr;\n      }\n  \n    polysurfs.SetSize(maxnum+1);\n    for(int i=0; i<polysurfs.Size(); i++)\n      polysurfs[i] = new NgArray<int>;\n\n    for(int i = 0; i<faces.Size(); i++)\n      polysurfs[faces[i].inputnr]->Append(faces[i].planenr);\n  }\n\n\n  void Polyhedra::CalcSpecialPoints (NgArray<Point<3> > & pts) const\n  {\n    for (int i = 0; i < points.Size(); i++)\n      pts.Append (points[i]);\n  }\n\n\n  void Polyhedra :: AnalyzeSpecialPoint (const Point<3> & /* pt */, \n                                         NgArray<Point<3> > & /* specpts */) const\n  {\n    ;\n  }\n\n  Vec<3> Polyhedra :: SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const\n  {\n    const double eps = 1e-10*poly_bbox.Diam();\n\n    for (int fi1 = 0; fi1 < faces.Size(); fi1++)\n      for (int fi2 = 0; fi2 < faces.Size(); fi2++)\n        {\n          int si1 = faces[fi1].planenr;\n          int si2 = faces[fi2].planenr;\n\n          if (surfaceids[si1] != s1 || surfaceids[si2] != s2) continue;\n\n          //(*testout) << \"check pair fi1/fi2 \" << fi1 << \"/\" << fi2 << endl;\n\t\n          Vec<3> n1 = GetSurface(si1) . GetNormalVector (p);\n          Vec<3> n2 = GetSurface(si2) . GetNormalVector (p);\n          Vec<3> t = Cross (n1, n2);\n\n          //(*testout) << \"t = \" << t << endl;\n\n\n          /*\n            int samepts = 0;\n            for (int j = 0; j < 3; j++)\n            for (int k = 0; k < 3; k++)\n\t    if (Dist(points[faces[fi1].pnums[j]],\n            points[faces[fi2].pnums[k]]) < eps)\n            samepts++;\n            if (samepts < 2) continue;\n          */\n\n          bool shareedge = false;\n          for(int j = 0; !shareedge && j < 3; j++)\n            {\n              Vec<3> v1 = points[faces[fi1].pnums[(j+1)%3]] - points[faces[fi1].pnums[j]];\n              double smax = v1.Length();\n              v1 *= 1./smax;\n\t    \n              int pospos;\n              if(fabs(v1(0)) > 0.5)\n                pospos = 0;\n              else if(fabs(v1(1)) > 0.5)\n                pospos = 1;\n              else\n                pospos = 2;\n\n              double sp = (p(pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);\n              if(sp < -eps || sp > smax+eps)\n                continue;\n\n              for (int k = 0; !shareedge && k < 3; k ++)\n                {\n                  Vec<3> v2 = points[faces[fi2].pnums[(k+1)%3]] - points[faces[fi2].pnums[k]];\n                  v2.Normalize();\n                  if(v2 * v1 > 0)\n                    v2 -= v1;\n                  else\n                    v2 += v1;\n\t\t \n                  //(*testout) << \"v2.Length2() \" << v2.Length2() << endl;\n\n                  if(v2.Length2() > 1e-18)\n                    continue;\n\n                  double sa,sb;\n\n                  sa = (points[faces[fi2].pnums[k]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);\n                  sb = (points[faces[fi2].pnums[(k+1)%3]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);\n\t\t \n\n                  if(Dist(points[faces[fi1].pnums[j]] + sa*v1, points[faces[fi2].pnums[k]]) > eps)\n                    continue;\n\n                  if(sa > sb)\n                    {\n                      double aux = sa; sa = sb; sb = aux;\n                    }\n\n                  //testout->precision(20);\n                  //(*testout) << \"sa \" << sa << \" sb \" << sb << \" smax \" << smax << \" sp \" << sp  << \" v1 \" << v1 << endl;\n                  //testout->precision(8);\n\n\n                  shareedge = (sa < -eps && sb > eps) ||\n                    (sa < smax-eps && sb > smax+eps) ||\n                    (sa > -eps && sb < smax+eps);\n\n                  if(!shareedge)\n                    continue;\n\n                  sa = max2(sa,0.);\n                  sb = min2(sb,smax);\n\n                  if(sp < sa+eps)\n                    shareedge = (t * v1 > 0);\n                  else if (sp > sb-eps)\n                    shareedge = (t * v1 < 0);\n\t\t   \n                }\n            }\n          if (!shareedge) continue;\n\n          t.Normalize();\n\t  \n\t\n          return t;\n        }\n\n    return Vec<3> (0,0,0);\n  }\n\n\n}\n\n\n"
  },
  {
    "path": "libsrc/csg/polyhedra.hpp",
    "content": "#ifndef FILE_POLYHEDRA\n#define FILE_POLYHEDRA\n\n\n/**************************************************************************/\n/* File:   polyhedra.hh                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   19. Mar. 2000                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  /*\n\n  Polyhedral primitive\n  \n  */\n\n  class Polyhedra : public Primitive\n  {\n    class Face {\n    public:\n      int pnums[3];\n      int planenr;\n\n      int inputnr;\n\n      Box<3> bbox;\n      //    Point<3> center;\n      Vec<3> v1, v2;   // edges\n      Vec<3> w1, w2;   // pseudo-inverse\n      Vec<3> n;        // normal to face\n      Vec<3> nn;       // normed normal\n\n      Face () { ; }\n      Face (int pi1, int pi2, int pi3, \n\t    const NgArray<Point<3> > & points,\n\t    int ainputnr);\n    };\n\n    NgArray<Point<3> > points;\n    NgArray<Face> faces;\n    NgArray<Plane*> planes;\n    Box<3> poly_bbox;\n\n    double eps_base1;\n\n  public:\n    Polyhedra ();\n    virtual ~Polyhedra () override;\n    static Primitive * CreateDefault ();\n\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const override;\n    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t\t       double eps) const override;\n    virtual INSOLID_TYPE VecInSolidNew (const Point<3> & p,\n                                        const Vec<3> & v,\n                                        double eps, bool printing = false) const;\n    virtual INSOLID_TYPE VecInSolidOld (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const;\n    \n    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const override;\n\n    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const override;\n    \n    virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const override;\n\n    virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      const Vec<3> & m,\n\t\t\t\t      double eps) const override;\n    \n    virtual void GetTangentialSurfaceIndices (const Point<3> & p, \n\t\t\t\t\t      NgArray<int> & surfind, double eps) const override;\n\n\n    virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t\t\t\t\t  NgArray<int> & surfind, double eps) const override;\n\n    virtual void CalcSpecialPoints (NgArray<Point<3> > & pts) const override;\n    virtual void AnalyzeSpecialPoint (const Point<3> & pt, \n\t\t\t\t      NgArray<Point<3> > & specpts) const override;\n    virtual Vec<3> SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const override;\n\n    virtual int GetNSurfaces() const override\n    { return planes.Size(); }\n    virtual Surface & GetSurface (int i) override\n    { return *planes[i]; }\n    virtual const Surface & GetSurface (int i) const override\n    { return *planes[i]; }\n\n    virtual void GetPrimitiveData (const char *& classname, NgArray<double> & coeffs) const override;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs) override;\n\n    virtual void Reduce (const BoxSphere<3> & box) override;\n    virtual void UnReduce () override;\n\n    int AddPoint (const Point<3> & p);\n    int AddFace (int pi1, int pi2, int pi3, int inputnum);\n\n    void GetPolySurfs(NgArray < NgArray<int> * > & polysurfs);\n  \n  protected:\n    int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const;\n    //  void CalcData();\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/python_csg.cpp",
    "content": "#ifdef NG_PYTHON\n\n#include \"../general/ngpython.hpp\"\n#include \"../core/python_ngcore.hpp\"\n#include \"csg.hpp\"\n#include \"../meshing/python_mesh.hpp\"\n#include \"../general/gzstream.h\"\n\n\nusing namespace netgen;\nusing namespace pybind11::literals;\n\nnamespace netgen\n{\n  extern shared_ptr<NetgenGeometry> ng_geometry;\n}\n\n\n\n// a shadow solid tree using shared pointers.\n\nclass SPSolid\n{\n  shared_ptr<SPSolid> s1, s2;\n  Solid * solid;\n  int bc = -1;\n  string bcname = \"\";\n  double maxh = -1;\n  string material;\n  bool owner;\n  double red = 0, green = 0, blue = 1;\n  bool transp = false;\npublic:\n  enum optyp { TERM, SECTION, UNION, SUB, EXISTING };\n\n  SPSolid (Solid * as) : solid(as), owner(true), op(TERM) { ; }\n  SPSolid (Solid * as, int /*dummy*/)\n    : solid(as), owner(false), op(EXISTING) { ; }\n  ~SPSolid () \n  {\n    ; // if (owner) delete solid;\n  }  \n  SPSolid (optyp aop, shared_ptr<SPSolid> as1, shared_ptr<SPSolid> as2) \n    : s1(as1), s2(as2), owner(true), op(aop) \n  { \n    if (aop == UNION)\n      solid = new Solid (Solid::UNION, s1->GetSolid(), s2->GetSolid());\n    else if (aop == SECTION)\n      solid = new Solid (Solid::SECTION, s1->GetSolid(), s2->GetSolid());\n    else if (aop == SUB)\n      solid = new Solid (Solid::SUB, s1->GetSolid()); // , s2->GetSolid());\n  }\n\n  Solid * GetSolid() { return solid; }\n  const Solid * GetSolid() const { return solid; }\n\n  void GiveUpOwner() \n  { \n    owner = false; \n    if (s1) s1 -> GiveUpOwner();\n    if (s2) s2 -> GiveUpOwner();\n  }\n\n  void AddSurfaces(CSGeometry & geom)\n  {\n    if (op == TERM)\n      geom.AddSurfaces (solid->GetPrimitive());\n    if (s1) s1 -> AddSurfaces (geom);\n    if (s2) s2 -> AddSurfaces (geom);\n  }\n\n  void SetMaterial (string mat)  { material = mat; }\n\n  string GetMaterial ()\n  {\n    if (!material.empty()) return material;\n    if (s1)\n      {\n        string s1mat = s1->GetMaterial();\n        if (!s1mat.empty()) return s1mat;\n      }\n    if (s2)\n      {\n        string s2mat = s2->GetMaterial();\n        if (!s2mat.empty()) return s2mat;\n      }\n    return material;\n  }\n\n  void SetBC(int abc) \n  {\n    if (bc == -1) \n      {\n        bc = abc;\n        if (s1) s1 -> SetBC(bc);\n        if (s2) s2 -> SetBC(bc);\n        if (op == TERM)\n          {\n            Primitive * prim = solid -> GetPrimitive();\n            for (int i = 0; i < prim->GetNSurfaces(); i++)\n              prim->GetSurface(i).SetBCProperty (abc);\n            // cout << \"set \" << prim->GetNSurfaces() << \" surfaces to bc \" << bc << endl;\n          }\n      }\n  }\n\n  void SetBCName(string name) \n  {\n    if (bcname == \"\") \n      {\n        bcname = name;\n        if (s1) s1 -> SetBCName(name);\n        if (s2) s2 -> SetBCName(name);\n        if (op == TERM)\n          {\n            Primitive * prim = solid -> GetPrimitive();\n            for (int i = 0; i < prim->GetNSurfaces(); i++)\n              prim->GetSurface(i).SetBCName (name);\n            // cout << \"set \" << prim->GetNSurfaces() << \" surfaces to bc \" << bc << endl;\n          }\n      }\n  }\n\n\n\n  void SetMaxH(double amaxh) \n  {\n    if (maxh == -1) \n      {\n        maxh = amaxh;\n        if (s1) s1 -> SetMaxH(maxh);\n        if (s2) s2 -> SetMaxH(maxh);\n        if (op == TERM)\n          {\n            Primitive * prim = solid -> GetPrimitive();\n            for (int i = 0; i < prim->GetNSurfaces(); i++)\n              prim->GetSurface(i).SetMaxH (maxh);\n          }\n      }\n  }\n\n  void SetColor(double ared, double agreen, double ablue)\n  {\n    red = ared;\n    green = agreen;\n    blue = ablue;\n  }\n\n  double GetRed() const { return red; }\n  double GetGreen() const { return green; }\n  double GetBlue() const { return blue; }\n\n  void SetTransparent() { transp = true; }\n  bool IsTransparent() { return transp; }\n\nprivate:\n  optyp op;\n};\n\ninline ostream & operator<< (ostream & ost, const SPSolid & sol)\n{\n  ost << *sol.GetSolid();\n  return ost;\n}\n\nnamespace netgen\n{\n  extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr);\n}\n\n\n\nDLL_HEADER void ExportCSG(py::module &m)\n{\n  py::class_<SplineGeometry<2>, shared_ptr<SplineGeometry<2>>>\n    (m, \"SplineCurve2d\")\n    .def(py::init<>())\n    .def (\"AddPoint\", FunctionPointer\n          ([] (SplineGeometry<2> & self, double x, double y)\n           {\n             self.geompoints.Append (GeomPoint<2> (Point<2> (x,y)));\n             return self.geompoints.Size()-1;\n           }))\n    .def (\"AddSegment\", [] (SplineGeometry<2> & self, int i1, int i2,\n                            string bcname, double maxh)\n    {\n      self.splines.Append (new LineSeg<2> (self.geompoints[i1], self.geompoints[i2], maxh, bcname));\n    }, \"p1\"_a, \"p2\"_a, \"bcname\"_a=\"default\", \"maxh\"_a=1e99)\n    .def (\"AddSegment\", [] (SplineGeometry<2> & self, int i1, int i2,\n                            int i3, string bcname, double maxh)\n    {\n      self.splines.Append (new SplineSeg3<2> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3], bcname, maxh));\n    }, \"p1\"_a, \"p2\"_a, \"p3\"_a, \"bcname\"_a=\"default\", \"maxh\"_a=1e99)\n    ;\n\n  py::class_<SplineGeometry<3>,shared_ptr<SplineGeometry<3>>> (m,\"SplineCurve3d\")\n    .def(py::init<>())\n    .def (\"AddPoint\", FunctionPointer\n          ([] (SplineGeometry<3> & self, double x, double y, double z)\n           {\n             self.geompoints.Append (GeomPoint<3> (Point<3> (x,y,z)));\n             return self.geompoints.Size()-1;\n           }))\n    .def (\"AddSegment\", FunctionPointer\n          ([] (SplineGeometry<3> & self, int i1, int i2)\n           {\n             self.splines.Append (new LineSeg<3> (self.geompoints[i1], self.geompoints[i2]));\n           }))\n    .def (\"AddSegment\", FunctionPointer\n          ([] (SplineGeometry<3> & self, int i1, int i2, int i3)\n           {\n             self.splines.Append (new SplineSeg3<3> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3]));\n           }))\n    ;\n\n  py::class_<SplineSurface, shared_ptr<SplineSurface>> (m, \"SplineSurface\",\n                        \"A surface for co dim 2 integrals on the splines\")\n    .def(py::init([](shared_ptr<SPSolid> base, py::list cuts)\n\t     {\n\t       auto primitive = dynamic_cast<OneSurfacePrimitive*> (base->GetSolid()->GetPrimitive());\n\t       auto acuts = make_shared<NgArray<shared_ptr<OneSurfacePrimitive>>>();\n\t       for(int i = 0; i<py::len(cuts);i++)\n\t\t {\n\t\t   py::extract<shared_ptr<SPSolid>> sps(cuts[i]);\n\t\t   if(!sps.check())\n\t\t     throw NgException(\"Cut must be SurfacePrimitive in constructor of SplineSurface!\");\n\t\t   auto sp = dynamic_cast<OneSurfacePrimitive*>(sps()->GetSolid()->GetPrimitive());\n\t\t   if(sp)\n\t\t     acuts->Append(shared_ptr<OneSurfacePrimitive>(sp));\n\t\t   else\n\t\t     throw Exception(\"Cut must be SurfacePrimitive in constructor of SplineSurface!\");\n\t\t }\n\t       if(!primitive)\n\t\t throw Exception(\"Base is not a SurfacePrimitive in constructor of SplineSurface!\");\n\t       return make_shared<SplineSurface>(shared_ptr<OneSurfacePrimitive>(primitive),acuts);\n\t     }),py::arg(\"base\"), py::arg(\"cuts\")=py::list())\n    .def(\"AddPoint\", FunctionPointer\n\t ([] (SplineSurface & self, double x, double y, double z, bool hpref)\n\t  {\n\t    self.AppendPoint(Point<3>(x,y,z),hpref);\n\t    return self.GetNP()-1;\n\t  }),\n\t py::arg(\"x\"),py::arg(\"y\"),py::arg(\"z\"),py::arg(\"hpref\")=false)\n    .def(\"AddSegment\", [] (SplineSurface & self, int i1, int i2, string bcname, double maxh)\n\t  {\n            auto seg = make_shared<LineSeg<3>>(self.GetPoint(i1),self.GetPoint(i2));\n\t    self.AppendSegment(seg,bcname,maxh);\n\t  },\n\t py::arg(\"pnt1\"),py::arg(\"pnt2\"),py::arg(\"bcname\")=\"default\", py::arg(\"maxh\")=-1.)\n    .def(\"AddSegment\", [] (SplineSurface& self, int i1, int i2, int i3, string bcname, double maxh)\n         {\n           auto seg = make_shared<SplineSeg3<3>>(self.GetPoint(i1), self.GetPoint(i2), self.GetPoint(i3));\n           self.AppendSegment(seg, bcname, maxh);\n         }, py::arg(\"pnt1\"),py::arg(\"pnt2\"), py::arg(\"pnt3\"),py::arg(\"bcname\")=\"default\", py::arg(\"maxh\")=-1.)\n    ;\n  \n  py::class_<SPSolid, shared_ptr<SPSolid>> (m, \"Solid\")\n    .def (\"__str__\", &ToString<SPSolid>)\n    .def (\"__add__\", FunctionPointer( [] ( shared_ptr<SPSolid> self, shared_ptr<SPSolid> other) { return make_shared<SPSolid> (SPSolid::UNION, self, other); }))\n    .def (\"__mul__\", FunctionPointer( [] ( shared_ptr<SPSolid> self, shared_ptr<SPSolid> other) { return make_shared<SPSolid> (SPSolid::SECTION, self, other); }))\n    .def (\"__sub__\", FunctionPointer\n          ([] ( shared_ptr<SPSolid> self, shared_ptr<SPSolid> other) \n           { return make_shared<SPSolid> (SPSolid::SECTION, self, \n                                          make_shared<SPSolid> (SPSolid::SUB, other, nullptr)); }))\n\n    .def (\"bc\", FunctionPointer([](shared_ptr<SPSolid> & self, int nr) -> shared_ptr<SPSolid> \n                                { self->SetBC(nr); return self; }))\n    .def (\"bc\", FunctionPointer([](shared_ptr<SPSolid> & self, string name) -> shared_ptr<SPSolid> \n                                { self->SetBCName(name); return self; }))\n    .def (\"maxh\", FunctionPointer([](shared_ptr<SPSolid> & self, double maxh) -> shared_ptr<SPSolid> \n                                { self->SetMaxH(maxh); return self; }))\n    .def (\"mat\", FunctionPointer([](shared_ptr<SPSolid> & self, string mat) -> shared_ptr<SPSolid> \n                                 { self->SetMaterial(mat); return self; }))\n    .def (\"mat\", &SPSolid::GetMaterial)\n    .def(\"col\", FunctionPointer([](shared_ptr<SPSolid> & self, py::list rgb) -> shared_ptr<SPSolid>\n                                { \n                                  py::extract<double> red(rgb[0]);\n                                  py::extract<double> green(rgb[1]);\n                                  py::extract<double> blue(rgb[2]);\n                                  self->SetColor(red(),green(),blue());\n                                  return self; \n                                }))\n    .def(\"transp\", FunctionPointer([](shared_ptr<SPSolid> & self)->shared_ptr < SPSolid > { self->SetTransparent(); return self; }))\n    ;\n\n  m.def (\"Sphere\", FunctionPointer([](Point<3> c, double r)\n                                     {\n                                       Sphere * sp = new Sphere (c, r);\n                                       Solid * sol = new Solid (sp);\n                                       return make_shared<SPSolid> (sol);\n                                     }));\n  m.def (\"Ellipsoid\", FunctionPointer([](Point<3> m, Vec<3> a, Vec<3> b, Vec<3> c)\n                                     {\n                                       Ellipsoid * ell = new Ellipsoid (m, a, b, c);\n                                       Solid * sol = new Solid (ell);\n                                       return make_shared<SPSolid> (sol);\n                                     }));\n  m.def (\"Plane\", FunctionPointer([](Point<3> p, Vec<3> n)\n                                    {\n                                      Plane * sp = new Plane (p,n);\n                                      Solid * sol = new Solid (sp);\n                                      return make_shared<SPSolid> (sol);\n                                    }));\n  m.def (\"Cone\", FunctionPointer([](Point<3> a, Point<3> b, double ra, double rb)\n                                       {\n                                         Cone * cyl = new Cone (a, b, ra, rb);\n                                         Solid * sol = new Solid (cyl);\n                                         return make_shared<SPSolid> (sol);\n                                       }));\n  m.def (\"Cylinder\", FunctionPointer([](Point<3> a, Point<3> b, double r)\n                                       {\n                                         Cylinder * cyl = new Cylinder (a, b, r);\n                                         Solid * sol = new Solid (cyl);\n                                         return make_shared<SPSolid> (sol);\n                                       }));\n  m.def (\"OrthoBrick\", FunctionPointer([](Point<3> p1, Point<3> p2)\n                                         {\n                                           OrthoBrick * brick = new OrthoBrick (p1,p2);\n                                           Solid * sol = new Solid (brick);\n                                           return make_shared<SPSolid> (sol);\n                                         }));\n  m.def (\"Torus\", FunctionPointer([](Point<3> c, Vec<3> n, double R, double r)\n                                         {\n                                           Torus * torus = new Torus (c,n,R,r);\n                                           Solid * sol = new Solid (torus);\n                                           return make_shared<SPSolid> (sol);\n                                         }));\n  m.def (\"Revolution\", [](Point<3> p1, Point<3> p2,\n                          shared_ptr<SplineGeometry<2>> spline)\n  {\n    Revolution * rev = new Revolution (p1, p2, spline);\n    Solid * sol = new Solid(rev);\n    return make_shared<SPSolid> (sol);\n  });\n  m.def (\"Extrusion\", [](shared_ptr<SplineGeometry<3>> path,\n                         shared_ptr<SplineGeometry<2>> profile,\n                         Vec<3> d)\n  {\n    Extrusion * extr = new Extrusion (path,profile,d);\n    Solid * sol = new Solid(extr);\n    return make_shared<SPSolid> (sol);\n  }, py::arg(\"path\"), py::arg(\"profile\"), py::arg(\"d\"),\n     R\"delimiter(A body of extrusion is defined by its profile\n(which has to be a closed, clockwiseoriented 2D curve),\n by a path (a 3D curve) and a vector d. It is constructed\n as follows: Take a point p on the path and denote the\n (unit-)tangent of the path in this point by t. If we cut\n the body by the plane given by p and t as normal vector,\n the cut is the profile. The profile is oriented by the\n (local) y-direction `y:=d−(d·t)t` and the (local) x-direction\n `x:=t \\times y`.\nThe following points have to be noticed:\n * If the path is not closed, then also the body is NOT closed.\n   In this case e.g. planes or orthobricks have to be used to\n   construct a closed body.\n * The path has to be smooth, i.e. the tangents at the end- resp.\n   start-point of two consecutive spline or line patches have to\n   have the same directions.\n)delimiter\");\n  m.def(\"EllipticCone\", [](const Point<3>& a, const Vec<3>& v, const Vec<3>& w,\n                            double h, double r)\n        {\n          auto ellcone = new EllipticCone(a,v,w,h,r);\n          auto sol = new Solid(ellcone);\n          return make_shared<SPSolid>(sol);\n        }, py::arg(\"a\"), py::arg(\"vl\"), py::arg(\"vs\"), py::arg(\"h\"), py::arg(\"r\"),\n        R\"raw_string(\nAn elliptic cone, given by the point 'a' at the base of the cone along the main axis,\nthe vectors v and w of the long and short axis of the ellipse, respectively,\nthe height of the cone, h, and ratio of base long axis length to top long axis length, r\n\nNote: The elliptic cone has to be truncated by planes similar to a cone or an elliptic cylinder.\nWhen r =1, the truncated elliptic cone becomes an elliptic cylinder.\nWhen r tends to zero, the truncated elliptic cone tends to a full elliptic cone.\nHowever, when r = 0, the top part becomes a point(tip) and meshing fails!\n)raw_string\");\n\n  m.def(\"Polyhedron\", [](py::list points, py::list faces)\n  {\n    auto poly = new Polyhedra();\n    for(auto p : points)\n      poly->AddPoint(py::cast<Point<3>>(p));\n    int fnr = 0;\n    for(auto face : faces)\n      {\n        auto lface = py::cast<py::list>(face);\n        if(py::len(lface) == 3)\n          poly->AddFace(py::cast<int>(lface[0]),\n                        py::cast<int>(lface[1]),\n                        py::cast<int>(lface[2]),\n                        fnr++);\n        else if(py::len(lface) == 4)\n          {\n            poly->AddFace(py::cast<int>(lface[0]),\n                          py::cast<int>(lface[1]),\n                          py::cast<int>(lface[2]),\n                          fnr);\n            poly->AddFace(py::cast<int>(lface[0]),\n                          py::cast<int>(lface[2]),\n                          py::cast<int>(lface[3]),\n                          fnr++);\n          }\n      }\n    return make_shared<SPSolid>(new Solid(poly));\n  });\n  \n  m.def (\"Or\", FunctionPointer([](shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2)\n                                 {\n                                   return make_shared<SPSolid> (SPSolid::UNION, s1, s2);\n                                 }));\n  m.def (\"And\", FunctionPointer([](shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2)\n                                  {\n                                    return make_shared<SPSolid> (SPSolid::SECTION, s1, s2);\n                                  }));\n\n\n  py::class_<CSGeometry, NetgenGeometry, shared_ptr<CSGeometry>> (m, \"CSGeometry\")\n    .def(py::init<>())\n    .def(py::init([](const string& filename)\n                  {\n                    ifstream ist (filename);\n                    auto geo = make_shared<CSGeometry>();\n                    ParseCSG(ist, geo.get());\n                    geo->FindIdenticSurfaces(1e-8 * geo->MaxSize());\n                    return geo;\n                  }), py::arg(\"filename\"))\n    .def(NGSPickle<CSGeometry>())\n    .def(\"Save\", FunctionPointer([] (CSGeometry & self, string filename)\n                                 {\n                                   cout << \"save geometry to file \" << filename << endl;\n                                   self.Save (filename);\n                                 }))\n    .def(\"Add\",\n         [] (CSGeometry & self, shared_ptr<SPSolid> solid, py::list bcmod, double maxh,\n             py::tuple col, bool transparent, int layer)\n          {\n            solid->AddSurfaces (self);\n            solid->GiveUpOwner();\n            int tlonr = self.SetTopLevelObject (solid->GetSolid());\n            self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial());\n            self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue());\n            // self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent());\n            self.GetTopLevelObject(tlonr)->SetTransparent(transparent);\n            self.GetTopLevelObject(tlonr)->SetMaxH(maxh);\n            self.GetTopLevelObject(tlonr)->SetLayer(layer);\n\n            // cout << \"rgb = \" << py::len(rgb) << endl;\n            if (py::len(col)==3)\n              self.GetTopLevelObject(tlonr) -> SetRGB(py::cast<double>(col[0]),\n                                                      py::cast<double>(col[1]),\n                                                      py::cast<double>(col[2]));\n            \n            // bcmod is list of tuples ( solid, bcnr )\n            for (int i = 0; i < py::len(bcmod); i++)\n              {\n                py::tuple tup = py::extract<py::tuple> (bcmod[i]) ();\n                auto mod_solid = py::extract<shared_ptr<SPSolid>> (tup[0]) ();\n                int mod_nr = -1;\n                string * bcname = nullptr;\n                py::object val = tup[1];\n                if (py::extract<int>(val).check()) mod_nr = py::extract<int> (val)();\n                if (py::extract<string>(val).check()) bcname = new string ( py::extract<string> (val)());\n\n                NgArray<int> si;\n                mod_solid -> GetSolid() -> GetSurfaceIndices (si);\n                // cout << \"change bc on surfaces: \" << si << \" to \" << mod_nr << endl;\n\n                for (int j = 0; j < si.Size(); j++)\n                  {\n                    CSGeometry::BCModification bcm;\n                    bcm.bcname = bcname ? new string (*bcname) : nullptr;\n                    bcm.tlonr = tlonr;\n                    bcm.si = si[j];\n\t\t    bcm.bcnr = mod_nr;\n\t\t    self.bcmodifications.Append (bcm);\n                  }\n                delete bcname;\n              }\n            return tlonr;\n          },\n         py::arg(\"solid\"), py::arg(\"bcmod\")=py::list(), py::arg(\"maxh\")=1e99,\n         py::arg(\"col\")=py::tuple(), py::arg(\"transparent\")=false, py::arg(\"layer\")=1\n         )\n\n    .def(\"AddSurface\", FunctionPointer\n         ([] (CSGeometry & self, shared_ptr<SPSolid> surface, shared_ptr<SPSolid> solid)\n          {\n            solid->AddSurfaces (self);\n            solid->GiveUpOwner();\n            Surface & surf = surface->GetSolid()->GetPrimitive()->GetSurface();\n            int tlonr = self.SetTopLevelObject (solid->GetSolid(), &surf);\n            // self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial());\n            self.GetTopLevelObject(tlonr) -> SetBCProp(surf.GetBCProperty());\n            self.GetTopLevelObject(tlonr) -> SetBCName(surf.GetBCName());\n            \n            self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue());\n            self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent());\n          }),\n         py::arg(\"surface\"), py::arg(\"solid\")\n         )\n    .def(\"AddSplineSurface\", FunctionPointer\n\t ([] (CSGeometry & self, shared_ptr<SplineSurface> surf)\n\t  {\n\t    auto cuttings = surf->CreateCuttingSurfaces();\n\t    auto spsol = make_shared<SPSolid>(new Solid(surf.get()));\n\t    for(auto cut : (*cuttings)){\n\t      spsol = make_shared<SPSolid>(SPSolid::SECTION,spsol,make_shared<SPSolid>(new Solid(cut.get())));\n\t    }\n\t    spsol->AddSurfaces(self);\n\t    int tlonr = self.SetTopLevelObject(spsol->GetSolid(), surf.get());\n\t    self.GetTopLevelObject(tlonr) -> SetBCProp(surf->GetBase()->GetBCProperty());\n\t    self.GetTopLevelObject(tlonr) -> SetBCName(surf->GetBase()->GetBCName());\n\t    self.GetTopLevelObject(tlonr) -> SetMaxH(surf->GetBase()->GetMaxH());\n            NgArray<Point<3>> non_midpoints;\n            for(auto spline : surf->GetSplines())\n              {\n                non_midpoints.Append(spline->GetPoint(0));\n              }\n\t    for(auto p : non_midpoints)\n\t\tself.AddUserPoint(p);\n            self.AddSplineSurface(surf);\n\t  }),\n\t  py::arg(\"SplineSurface\"))\n    .def(\"SingularFace\", [] (CSGeometry & self, shared_ptr<SPSolid> sol, shared_ptr<SPSolid> surfaces, double factor)\n         {\n           int tlonum = -1;\n           for (int i = 0; i < self.GetNTopLevelObjects(); i++)\n             if (self.GetTopLevelObject(i)->GetSolid() == sol->GetSolid())\n               tlonum = i;\n           if (tlonum == -1) throw NgException(\"not a top-level-object\");\n           if (!surfaces) surfaces = sol;\n           auto singface = new SingularFace(tlonum+1, surfaces->GetSolid(), factor);\n           self.singfaces.Append(singface);\n         }, py::arg(\"solid\"), py::arg(\"surfaces\")=nullptr, py::arg(\"factor\")=0.25)\n    .def(\"SingularEdge\", [] (CSGeometry & self, shared_ptr<SPSolid> s1,shared_ptr<SPSolid> s2, double factor)\n         {\n           auto singedge = new SingularEdge(1, -1, self, s1->GetSolid(), s2->GetSolid(), factor);\n           self.singedges.Append (singedge);\n         })\n    .def(\"SingularPoint\", [] (CSGeometry & self, shared_ptr<SPSolid> s1,shared_ptr<SPSolid> s2,\n                             shared_ptr<SPSolid> s3, double factor)\n         {\n           auto singpoint = new SingularPoint(1, s1->GetSolid(), s2->GetSolid(), s3->GetSolid(), factor);\n           self.singpoints.Append (singpoint);\n         })\n    .def(\"CloseSurfaces\", FunctionPointer\n         ([] (CSGeometry & self, shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2, py::list aslices )\n          {\n            NgArray<int> si1, si2;\n            s1->GetSolid()->GetSurfaceIndices (si1);\n            s2->GetSolid()->GetSurfaceIndices (si2);\n            Flags flags;\n\n            try\n            {\n                int n = py::len(aslices);\n                Array<double> slices(n);\n                for(int i=0; i<n; i++)\n                {\n                    slices[i]= py::extract<double>(aslices[i])();\n                }\n                flags.SetFlag(\"slices\", slices);\n            }\n            catch( py::error_already_set const & ) {\n                cout << \"caught python error:\" << endl;\n                PyErr_Print();\n            }\n\n            const TopLevelObject * domain = nullptr;\n            self.AddIdentification\n              (new CloseSurfaceIdentification\n               (self.GetNIdentifications()+1, self,\n                self.GetSurface (si1[0]), self.GetSurface (si2[0]),\n                domain,\n                flags));\n          }),\n         py::arg(\"solid1\"), py::arg(\"solid2\"), py::arg(\"slices\")\n         )\n    .def(\"CloseSurfaces\", FunctionPointer\n         ([] (CSGeometry & self, shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2,\n              int reflevels, shared_ptr<SPSolid> domain_solid)\n          {\n            NgArray<int> si1, si2;\n            s1->GetSolid()->GetSurfaceIndices (si1);\n            s2->GetSolid()->GetSurfaceIndices (si2);\n            cout << IM(3) << \"surface ids1 = \" << si1 << endl;\n            cout << IM(3) << \"surface ids2 = \" << si2 << endl;\n\n            Flags flags;\n            const TopLevelObject * domain = nullptr;\n            if (domain_solid)\n              domain = self.GetTopLevelObject(domain_solid->GetSolid());\n              \n            self.AddIdentification \n              (new CloseSurfaceIdentification \n               (self.GetNIdentifications()+1, self, \n                self.GetSurface (si1[0]), self.GetSurface (si2[0]),\n                domain,\n                flags));\n          }),\n         py::arg(\"solid1\"), py::arg(\"solid2\"), py::arg(\"reflevels\")=2, py::arg(\"domain\")=nullptr\n         )\n    \n    .def(\"PeriodicSurfaces\", FunctionPointer\n         ([] (CSGeometry & self, shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2,\n              Transformation<3> trafo)\n          {\n            NgArray<int> si1, si2;\n            s1->GetSolid()->GetSurfaceIndices (si1);\n            s2->GetSolid()->GetSurfaceIndices (si2);\n            cout << \"identify surfaces \" << si1[0] << \" and \" << si2[0] << endl;\n            self.AddIdentification \n              (new PeriodicIdentification \n               (self.GetNIdentifications()+1, self, \n                self.GetSurface (si1[0]), self.GetSurface (si2[0]),\n                trafo));\n          }),\n         py::arg(\"solid1\"), py::arg(\"solid2\"),\n         py::arg(\"trafo\")=Transformation<3>(Vec<3>(0,0,0))\n         )\n    .def(\"NameEdge\", [] (CSGeometry & self, shared_ptr<SPSolid> s1, shared_ptr<SPSolid> s2, string name)\n         {\n           Array<Surface*> surfs1, surfs2;\n           s1->GetSolid()->ForEachSurface( [&surfs1] (Surface * s, bool inv) { surfs1.Append(s); });\n           s2->GetSolid()->ForEachSurface( [&surfs2] (Surface * s, bool inv) { surfs2.Append(s); });\n           for (auto s1 : surfs1)\n             for (auto s2 : surfs2)\n               self.named_edges[tuple(s1,s2)] = name;\n         })\n         \n    .def(\"AddPoint\", [] (CSGeometry & self, Point<3> p, variant<int,string> index) -> CSGeometry&\n         {\n           if (auto pint = std::get_if<int> (&index))\n             self.AddUserPoint(CSGeometry::UserPoint(p, *pint));\n           if (auto pstr = std::get_if<string> (&index))\n             self.AddUserPoint(CSGeometry::UserPoint(p, *pstr));\n           return self;\n         })\n    \n    .def(\"GetTransparent\", FunctionPointer\n         ([] (CSGeometry & self, int tlonr)\n          {\n            return self.GetTopLevelObject(tlonr)->GetTransparent();\n          }),\n         py::arg(\"tlonr\")\n         )\n    .def(\"SetTransparent\", FunctionPointer\n         ([] (CSGeometry & self, int tlonr, bool transparent)\n          {\n            self.GetTopLevelObject(tlonr)->SetTransparent(transparent);\n          }),\n         py::arg(\"tlonr\"), py::arg(\"transparent\")\n         )\n\n    .def(\"GetVisible\", FunctionPointer\n         ([] (CSGeometry & self, int tlonr)\n          {\n            return self.GetTopLevelObject(tlonr)->GetVisible();\n          }),\n         py::arg(\"tlonr\")\n         )\n    .def(\"SetVisible\", FunctionPointer\n         ([] (CSGeometry & self, int tlonr, bool visible)\n          {\n            self.GetTopLevelObject(tlonr)->SetVisible(visible);\n          }),\n         py::arg(\"tlonr\"), py::arg(\"visible\")\n         )\n    .def(\"SetBoundingBox\", FunctionPointer\n         ([] (CSGeometry & self, Point<3> pmin, Point<3> pmax)\n          {\n            self.SetBoundingBox(Box<3> (pmin, pmax));\n          }),\n         py::arg(\"pmin\"), py::arg(\"pmax\")\n         )\n    .def(\"Draw\", FunctionPointer\n         ([] (shared_ptr<CSGeometry> self)\n          {\n             self->FindIdenticSurfaces(1e-8 * self->MaxSize());\n             self->CalcTriangleApproximation(0.01, 20);\n             ng_geometry = self;\n          })\n         )\n    .def(\"GetSolids\", [](CSGeometry& self)\n                      {\n                        py::list lst;\n                        for(auto i : Range(self.GetSolids().Size()))\n                          lst.append(make_shared<SPSolid>(self.GetSolids()[i], 1234));\n                        return lst;\n                      })\n    .def_property_readonly (\"ntlo\", &CSGeometry::GetNTopLevelObjects)\n    .def(\"_visualizationData\", [](shared_ptr<CSGeometry> csg_geo)\n         {\n           std::vector<float> vertices;\n           std::vector<int> trigs;\n           std::vector<float> normals;\n           std::vector<float> min = {std::numeric_limits<float>::max(),\n                                     std::numeric_limits<float>::max(),\n                                     std::numeric_limits<float>::max()};\n           std::vector<float> max = {std::numeric_limits<float>::lowest(),\n                                     std::numeric_limits<float>::lowest(),\n                                     std::numeric_limits<float>::lowest()};\n           std::vector<string> surfnames;\n           for (int i = 0; i < csg_geo->GetNSurf(); i++)\n             {\n               auto surf = csg_geo->GetSurface(i);\n               surfnames.push_back(surf->GetBCName());\n             }\n           csg_geo->FindIdenticSurfaces(1e-8 * csg_geo->MaxSize());\n           csg_geo->CalcTriangleApproximation(0.01,20);\n           auto nto = csg_geo->GetNTopLevelObjects();\n           size_t np = 0;\n           size_t ntrig = 0;\n           for (int i = 0; i < nto; i++){\n             np += csg_geo->GetTriApprox(i)->GetNP();\n             ntrig += csg_geo->GetTriApprox(i)->GetNT();\n           }\n           vertices.reserve(np*3);\n           trigs.reserve(ntrig*4);\n           normals.reserve(np*3);\n           int offset_points = 0;\n           for (int i = 0; i < nto; i++)\n             {\n               auto triapprox = csg_geo->GetTriApprox(i);\n               for (int j = 0; j < triapprox->GetNP(); j++)\n                 for(int k = 0; k < 3; k++) {\n                   float val = triapprox->GetPoint(j)[k];\n                   vertices.push_back(val);\n                   min[k] = min2(min[k], val);\n                   max[k] = max2(max[k],val);\n                   normals.push_back(triapprox->GetNormal(j)[k]);\n                 }\n               for (int j = 0; j < triapprox->GetNT(); j++)\n                 {\n                   for(int k = 0; k < 3; k++)\n                     trigs.push_back(triapprox->GetTriangle(j)[k]+offset_points);\n                   trigs.push_back(triapprox->GetTriangle(j).SurfaceIndex());\n                 }\n               offset_points += triapprox->GetNP();\n             }\n           py::gil_scoped_acquire ac;\n           py::dict res;\n           py::list snames;\n           for(auto name : surfnames)\n             snames.append(py::cast(name));\n           res[\"vertices\"] = MoveToNumpy(vertices);\n           res[\"triangles\"] = MoveToNumpy(trigs);\n           res[\"normals\"] = MoveToNumpy(normals);\n           res[\"surfnames\"] = snames;\n           res[\"min\"] = MoveToNumpy(min);\n           res[\"max\"] = MoveToNumpy(max);\n           return res;\n         }, py::call_guard<py::gil_scoped_release>())\n  .def(\"GenerateMesh\", [](shared_ptr<CSGeometry> geo,\n                          MeshingParameters* pars, py::kwargs kwargs)\n           {\n             MeshingParameters mp;\n             if(pars) mp = *pars;\n             CreateMPfromKwargs(mp, kwargs);\n             py::gil_scoped_release gil_rel;\n             auto mesh = make_shared<Mesh>();\n             SetGlobalMesh (mesh);\n             mesh->SetGeometry(geo);\n\t     ng_geometry = geo;\n             geo->FindIdenticSurfaces(1e-8 * geo->MaxSize());\n             auto result = geo->GenerateMesh (mesh, mp);\n             if(result != 0)\n               throw Exception(\"Meshing failed!\");\n             return mesh;\n           }, py::arg(\"mp\") = nullptr,\n       meshingparameter_description.c_str())\n    ;\n\n  m.def(\"Save\", FunctionPointer \n          ([](const Mesh & self, const string & filename, const CSGeometry & geom)\n           {\n             ostream * outfile;\n             if (filename.substr (filename.length()-3, 3) == \".gz\")\n               outfile = new ogzstream (filename.c_str());\n             else\n               outfile = new ofstream (filename.c_str());\n             \n             self.Save (*outfile);\n             *outfile << endl << endl << \"endmesh\" << endl << endl;\n             geom.SaveToMeshFile (*outfile);\n             delete outfile;\n           }),py::call_guard<py::gil_scoped_release>())\n    ;\n\n\n\n  m.def(\"ZRefinement\", FunctionPointer\n          ([](Mesh & mesh, CSGeometry & geom)\n          {\n            ZRefinementOptions opt;\n            opt.minref = 5;\n            ZRefinement (mesh, &geom, opt);\n          }),py::call_guard<py::gil_scoped_release>())\n    ;\n}\n\nPYBIND11_MODULE(libcsg, m) {\n  ExportCSG(m);\n}\n#endif\n\n"
  },
  {
    "path": "libsrc/csg/revolution.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\nnamespace netgen\n{\n  void RevolutionFace :: Init(void)\n  {\n    const LineSeg<2> * line = dynamic_cast<const LineSeg<2>*>(spline);\n    const SplineSeg3<2> * spline3 = dynamic_cast<const SplineSeg3<2>*>(spline);\n\n    if(line)\n      {\n\tchecklines_start.Append(new Point<2>(line->StartPI()));\n\tchecklines_vec.Append(new Vec<2>(line->EndPI() - line->StartPI()));\n\t(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!\n      }\n    else if (spline3)\n      {\n\tchecklines_start.Append(new Point<2>(spline3->EndPI()));\n\tchecklines_start.Append(new Point<2>(spline3->TangentPoint()));\n\tchecklines_start.Append(new Point<2>(spline3->StartPI()));\n\tchecklines_vec.Append(new Vec<2>(spline3->StartPI() - spline3->EndPI()));\n\t(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!\n\tchecklines_vec.Append(new Vec<2>(spline3->EndPI() - spline3->TangentPoint()));\n\t(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!\n\tchecklines_vec.Append(new Vec<2>(spline3->TangentPoint() - spline3->StartPI()));\n\t(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!\n\t\n      }\n    \n    for(int i=0; i<checklines_vec.Size(); i++)\n      {\n\tchecklines_normal.Append(new Vec<2>);\n\t(*checklines_normal.Last())(0) = - (*checklines_vec[i])(1);\n\t(*checklines_normal.Last())(1) = (*checklines_vec[i])(0);\n\tchecklines_normal.Last()->Normalize();\n      }\n  }\n\n  RevolutionFace :: RevolutionFace(const SplineSeg<2> & spline_in,\n\t\t\t\t   const Point<3> & p,\n\t\t\t\t   const Vec<3> & vec,\n\t\t\t\t   bool first,\n\t\t\t\t   bool last,\n\t\t\t\t   const int id_in) :\n    isfirst(first), islast(last), spline(&spline_in), p0(p), v_axis(vec),  id(id_in)\n  {    \n    deletable = false;\n    maxh = spline_in.GetMaxh();\n    bcname = spline_in.GetBCName();\n    Init();\n  }\n\n\n  RevolutionFace :: RevolutionFace(const NgArray<double> & raw_data)\n  {\n    deletable = true;\n    \n    int pos = 0;\n\n    NgArray< Point<2> > p(3);\n\n    int stype = int(raw_data[pos]); pos++;\n\n    for(int i=0; i<stype; i++)\n      {\n\tp[i](0) = raw_data[pos]; pos++;\n\tp[i](1) = raw_data[pos]; pos++;\n      }\n\n    if(stype == 2)\n      {\n\tspline = new LineSeg<2>(GeomPoint<2>(p[0],1),\n\t\t\t\tGeomPoint<2>(p[1],1));\n\t//(*testout) << \"appending LineSeg<2> \" << p[0] \n\t//\t   << \" to \" << p[1] << endl;\n      }\n    else if(stype == 3)\n      {\n\tspline = new SplineSeg3<2>(GeomPoint<2>(p[0],1),\n\t\t\t\t   GeomPoint<2>(p[1],1),\n\t\t\t\t   GeomPoint<2>(p[2],1));\n\t//(*testout) << \"appending SplineSeg<3> \"\n\t//\t   << p[0] << \" -- \" << p[1] << \" -- \" << p[2] << endl;\n      }\n\n    for(int i=0; i<3; i++)\n      {\n\tp0(i) = raw_data[pos];\n\tpos++;\n      }\n    for(int i=0; i<3; i++)\n      {\n\tv_axis(i) = raw_data[pos];\n\tpos++;\n      }\n    isfirst = (raw_data[pos] > 0.9);\n    pos++;\n    islast = (raw_data[pos] < 0.1);\n    pos++;\n    \n\n  }\n\n  \n  RevolutionFace :: ~RevolutionFace()\n  {\n    for(int i=0; i<checklines_start.Size(); i++)\n      {\n\tdelete checklines_start[i];\n\tdelete checklines_vec[i];\n\tdelete checklines_normal[i];\n      }\n\n    if(deletable)\n      delete spline;\n  }\n  \n  void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t\t\t  const Vec<3> & vector3d, Vec<2> & vector2d) const\n  {\n    Vec<3> pmp0 = point3d-p0;\n    CalcProj0(pmp0,point2d);\n    Vec<3> y=pmp0-point2d(0)*v_axis; y.Normalize();\n    vector2d(0) = vector3d*v_axis;\n    vector2d(1) = vector3d*y;\n  }\n  \n\n  void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d) const\n  {\n    Vec<3> pmp0 = point3d-p0;\n    CalcProj0(pmp0,point2d);\n  }\n  \n  void RevolutionFace :: CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const\n  {\n    point2d(0) = point3d_minus_p0 * v_axis;\n    point2d(1) = sqrt( point3d_minus_p0 * point3d_minus_p0 - point2d(0)*point2d(0) );\n  }\n  \n\n  int  RevolutionFace ::IsIdentic (const Surface & s2, int & inv, double eps) const\n  {\n    const RevolutionFace * rev2 = dynamic_cast<const RevolutionFace*>(&s2);\n    \n    if(!rev2) return 0;\n    \n    if(rev2 == this)\n      return 1;\n        \n    return 0;\n  }\n\n  double RevolutionFace :: CalcFunctionValue (const Point<3> & point) const\n  {\n    if(spline_coefficient.Size() == 0)\n      spline->GetCoeff(spline_coefficient);\n    if(spline_coefficient_shifted.Size() == 0)\n        spline->GetCoeff(spline_coefficient_shifted, spline->StartPI());\n\n    Point<2> p;\n    CalcProj(point,p);\n\n    /*\n    double val = spline_coefficient(0)*p(0)*p(0) + spline_coefficient(1)*p(1)*p(1)\n      + spline_coefficient(2)*p(0)*p(1) + spline_coefficient(3)*p(0)\n      + spline_coefficient(4)*p(1) + spline_coefficient(5);\n    */\n    Vec<2> pr = p-spline->StartPI();\n\n\n    // cout << \"spline_coefficinet = \" << spline_coefficient << endl;\n    // cout << \"shifted = \" << spline_coefficient_shifted << endl;\n    \n    double val2 = spline_coefficient_shifted(0)*pr(0)*pr(0) + spline_coefficient_shifted(1)*pr(1)*pr(1)\n      + spline_coefficient_shifted(2)*pr(0)*pr(1) + spline_coefficient_shifted(3)*pr(0)\n      + spline_coefficient_shifted(4)*pr(1) + spline_coefficient_shifted(5);\n\n    // cout << \"val = \" << val << \" =?= \" << val2 << endl;\n    return val2;\n  }\n\n  void RevolutionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const\n  {\n    if(spline_coefficient.Size() == 0)\n      spline->GetCoeff(spline_coefficient);\n    if(spline_coefficient_shifted.Size() == 0)\n        spline->GetCoeff(spline_coefficient_shifted, spline->StartPI());\n\n    Vec<3> point_minus_p0 = point-p0;\n\n    Point<2> p;\n    CalcProj0(point_minus_p0,p);\n    /*\n    const double dFdxbar = 2.*spline_coefficient(0)*p(0) + spline_coefficient(2)*p(1) + spline_coefficient(3);\n\n    if(fabs(p(1)) > 1e-10)\n      {\n\tconst double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4);\n\n\tgrad(0) = dFdxbar*v_axis(0) + dFdybar * ( point_minus_p0(0)-v_axis(0)*p(0) )/p(1);\n\tgrad(1) = dFdxbar*v_axis(1) + dFdybar * ( point_minus_p0(1)-v_axis(1)*p(0) )/p(1);\n\tgrad(2) = dFdxbar*v_axis(2) + dFdybar * ( point_minus_p0(2)-v_axis(2)*p(0) )/p(1);\n\t//(*testout) << \"grad1(\"<<point<<\") = \" << grad << endl;\n      }\n    else\n      {\n\tgrad(0) = dFdxbar*v_axis(0);\n\tgrad(1) = dFdxbar*v_axis(1);\n\tgrad(2) = dFdxbar*v_axis(2);\n\t//(*testout) << \"grad2(\"<<point<<\") = \" << grad << endl;\n      }\n    */\n    Vec<2> pr = p-spline->StartPI();\n    const double dFdxbar = 2.*spline_coefficient_shifted(0)*pr(0) + spline_coefficient_shifted(2)*pr(1) + spline_coefficient_shifted(3);\n\n    if(fabs(p(1)) > 1e-10)\n      {\n\tconst double dFdybar = 2.*spline_coefficient_shifted(1)*pr(1) + spline_coefficient_shifted(2)*pr(0) + spline_coefficient_shifted(4);\n\n\tgrad(0) = dFdxbar*v_axis(0) + dFdybar * ( point_minus_p0(0)-v_axis(0)*p(0) )/p(1);\n\tgrad(1) = dFdxbar*v_axis(1) + dFdybar * ( point_minus_p0(1)-v_axis(1)*p(0) )/p(1);\n\tgrad(2) = dFdxbar*v_axis(2) + dFdybar * ( point_minus_p0(2)-v_axis(2)*p(0) )/p(1);\n\t//(*testout) << \"grad1(\"<<point<<\") = \" << grad << endl;\n      }\n    else\n      {\n\tgrad(0) = dFdxbar*v_axis(0);\n\tgrad(1) = dFdxbar*v_axis(1);\n\tgrad(2) = dFdxbar*v_axis(2);\n\t//(*testout) << \"grad2(\"<<point<<\") = \" << grad << endl;\n      }\n    \n  }\n\n  \n  void RevolutionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const\n  {\n    if(spline_coefficient.Size() == 0)\n      spline->GetCoeff(spline_coefficient);\n\n    Vec<3> point_minus_p0 = point-p0;\n\n    Point<2> p;\n    CalcProj0(point_minus_p0,p);\n\n\n    if(fabs(p(1)) > 1e-10)\n      {\n\tconst double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4);\n\t\n\tconst double aux = -pow(p(1),-3);\n\tconst double aux0 = point_minus_p0(0) - v_axis(0)*p(0);\n\tconst double aux1 = point_minus_p0(1) - v_axis(1)*p(0);\n\tconst double aux2 = point_minus_p0(2) - v_axis(2)*p(0);\n\t\n\n\tconst double dybardx = aux0/p(1);\n\tconst double dybardy = aux1/p(1);\n\tconst double dybardz = aux2/p(1);\n    \n\tconst double dybardxx = aux*aux0*aux0 + (1.-v_axis(0)*v_axis(0))/p(1);\n\tconst double dybardyy = aux*aux1*aux1 + (1.-v_axis(1)*v_axis(1))/p(1);\n\tconst double dybardzz = aux*aux2*aux2 + (1.-v_axis(2)*v_axis(2))/p(1);\n\tconst double dybardxy = aux*aux0*aux1 - v_axis(0)*v_axis(1)/p(1);\n\tconst double dybardxz = aux*aux0*aux2 - v_axis(0)*v_axis(2)/p(1);\n\tconst double dybardyz = aux*aux1*aux2 - v_axis(1)*v_axis(2)/p(1);\n\t\n\thesse(0,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(0) + 2.*spline_coefficient(2)*v_axis(0)*dybardx + 2.*spline_coefficient(1)*dybardx*dybardx\n\t  + dFdybar*dybardxx;\n\thesse(1,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(1) + 2.*spline_coefficient(2)*v_axis(1)*dybardy + 2.*spline_coefficient(1)*dybardy*dybardy\n\t  + dFdybar*dybardyy;\n\thesse(2,2) = 2.*spline_coefficient(0)*v_axis(2)*v_axis(2) + 2.*spline_coefficient(2)*v_axis(2)*dybardz + 2.*spline_coefficient(1)*dybardz*dybardz\n\t  + dFdybar*dybardzz;\n\t\n\thesse(0,1) = hesse(1,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(1) + spline_coefficient(2)*v_axis(0)*dybardy + spline_coefficient(2)*dybardx*v_axis(1)\n\t  + 2.*spline_coefficient(2)*dybardx*dybardy + dFdybar*dybardxy;\n\thesse(0,2) = hesse(2,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(2) + spline_coefficient(2)*v_axis(0)*dybardz + spline_coefficient(2)*dybardx*v_axis(2)\n\t  + 2.*spline_coefficient(2)*dybardx*dybardz + dFdybar*dybardxz;\n\thesse(1,2) = hesse(2,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(2) + spline_coefficient(2)*v_axis(1)*dybardz + spline_coefficient(2)*dybardy*v_axis(2)\n\t  + 2.*spline_coefficient(2)*dybardy*dybardz + dFdybar*dybardyz;\n\n\t//(*testout) << \"hesse1: \" << hesse <<endl;\n      }\n    else if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&\n\t     fabs(spline_coefficient(0)) > 1e-10)\n      {\n\tdouble aux = spline_coefficient(0)-spline_coefficient(1);\n\t\n\thesse(0,0) = aux*v_axis(0)*v_axis(0) + spline_coefficient(1);\n\thesse(0,0) = aux*v_axis(1)*v_axis(1) + spline_coefficient(1);\n\thesse(0,0) = aux*v_axis(2)*v_axis(2) + spline_coefficient(1);\n\n\thesse(0,1) = hesse(1,0) = aux*v_axis(0)*v_axis(1);\n\thesse(0,2) = hesse(2,0) = aux*v_axis(0)*v_axis(2);\n\thesse(1,2) = hesse(2,1) = aux*v_axis(1)*v_axis(2);\n\t//(*testout) << \"hesse2: \" << hesse <<endl;\n\t\n      }\n    else if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line\n      {\n\thesse = 0;\n\t//(*testout) << \"hesse3: \" << hesse <<endl;\n      }\n    else\n      {\n        hesse = 0;\n\t(*testout) << \"hesse4: \" << hesse <<endl;\n      }\n  }\n\n  \n\n  double RevolutionFace ::HesseNorm () const\n  {\n    if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line\n      return 0;\n      \n    if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&\n\tfabs(spline_coefficient(0)) > 1e-10)\n      return 2.*max2(fabs(spline_coefficient(0)),fabs(spline_coefficient(1)));\n\n\n    double alpha = fabs(spline_coefficient(2)*(spline->StartPI()(0)-spline->EndPI()(0))) /\n      max2(fabs(spline->StartPI()(1)),fabs(spline->EndPI()(1)));\n\n    return max2(2.*fabs(spline_coefficient(0))+sqrt(2.)*fabs(spline_coefficient(2)),\n\t\t2.*fabs(spline_coefficient(1))+spline_coefficient(2)+1.5*alpha);\n  }\n\n  double  RevolutionFace :: MaxCurvature() const\n  {\n    double retval = spline->MaxCurvature();\n\n    NgArray < Point<2> > checkpoints;\n\n    const SplineSeg3<2> * ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);\n    const LineSeg<2> * ls = dynamic_cast<const LineSeg<2> *>(spline);\n    \n    if(ss3)\n      {\n\tcheckpoints.Append(ss3->StartPI());\n\tcheckpoints.Append(ss3->TangentPoint());\n\tcheckpoints.Append(ss3->TangentPoint());\n\tcheckpoints.Append(ss3->EndPI());\n      }\n    else if(ls)\n      {\n\tcheckpoints.Append(ls->StartPI());\n\tcheckpoints.Append(ls->EndPI());\n      }\n\n    for(int i=0; i<checkpoints.Size(); i+=2)\n      {\n\tVec<2> v = checkpoints[i+1]-checkpoints[i];\n\tVec<2> n(v(1),-v(0)); n.Normalize();\n\n\t//if(ss3)\n\t//  (*testout) << \"n \" << n << endl;\n\n\tif(fabs(n(1)) < 1e-15)\n\t  continue;\n\n\tdouble t1 = -checkpoints[i](1)/n(1);\n\tdouble t2 = -checkpoints[i+1](1)/n(1);\n\t\n\tdouble c1 = (t1 > 0) ? (1./t1) : -1;\n\tdouble c2 = (t2 > 0) ? (1./t2) : -1;\n\t\n\t//if(ss3)\n\t//  (*testout) << \"t1 \" << t1 << \" t2 \" << t2 << \" c1 \" << c1 << \" c2 \" << c2 << endl;\n\n\tif(c1 > retval)\n\t  retval = c1;\n\tif(c2 > retval)\n\t  retval = c2;\n      }\n\t\n    //if(ss3)\n    //  (*testout) << \"curvature \" << retval << endl;\n\n    return retval;\n\n    /*\n\n\n    // find smallest y value of spline:\n    NgArray<double> testt;\n\n    if(!isfirst)\n      testt.Append(0);\n    if(!islast)\n      testt.Append(1);\n    \n    const SplineSegment3 * s3 = dynamic_cast<const SplineSegment3 *>(&spline);\n\n    if(s3)\n      {\n\tdouble denom = (2.-sqrt(2.))*(s3->EndPI()(1) - s3->StartPI()(1));\n\t\n\tif(fabs(denom) < 1e-20)\n\t  testt.Append(0.5);\n\telse\n\t  {\n\t    double sD = sqrt(pow(s3->TangentPoint()(1) - s3->StartPI()(1),2)+\n\t\t\t     pow(s3->TangentPoint()(1) - s3->EndPI()(1),2));\n\t    testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) + sD)/denom);\n\t    testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) - sD)/denom);\n\t  }\t\n      }\n\n    double miny = fabs(spline.GetPoint(testt[0])(1));\n    for(int i=1; i<testt.Size(); i++)\n      {\n\tdouble thisy = fabs(spline.GetPoint(testt[i])(1));\n\tif(thisy < miny)\n\t  miny = thisy;\n      }\n\n    return max2(splinecurvature,1./miny);\n    */\n  }\n\n  void RevolutionFace :: Project (Point<3> & p) const\n  {\n    Point<2> p2d;\n\n    CalcProj(p,p2d);\n\n    const Vec<3> y = (p-p0)-p2d(0)*v_axis;\n    const double yl = y.Length();\n\n    double dummy;\n\n    spline->Project(p2d,p2d,dummy);\n\n    p = p0 + p2d(0)*v_axis;\n\n    if(yl > 1e-20*Dist(spline->StartPI(),spline->EndPI()))\n      p+= (p2d(1)/yl)*y;\n  }\n\n\n\n  \n  Point<3>  RevolutionFace :: GetSurfacePoint () const\n  {\n    Vec<3> random_vec(0.760320,-0.241175,0.60311534);\n\n    Vec<3> n = Cross(v_axis,random_vec); n.Normalize();\n\n    Point<2> sp = spline->GetPoint(0.5);\n\n    Point<3> retval = p0 + sp(0)*v_axis + sp(1)*n;\n\n    return retval;\n  }\n\n\n  void RevolutionFace :: Print (ostream & str) const\n  {\n    if(spline_coefficient.Size() == 0)\n      spline->GetCoeff(spline_coefficient);\n\n    str << p0(0) << \" \" << p0(1) << \" \" << p0(2) << \" \"\n\t<< v_axis(0) << \" \" << v_axis(1) << \" \" << v_axis(2) << \" \";\n    for(int i=0; i<6; i++) str << spline_coefficient(i) << \" \";\n    str << endl;\n  }\n\n\n  void RevolutionFace :: GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t\t   const Box<3> & boundingbox, \n\t\t\t\t\t\t   double facets) const\n  {\n    Vec<3> random_vec(0.760320,-0.241175,0.60311534);\n\n    Vec<3> v1 = Cross(v_axis,random_vec); v1.Normalize();\n    Vec<3> v2 = Cross(v1,v_axis); v2.Normalize();\n\n    int n = int(2.*facets) + 1;\n\n    for(int i=0; i<=n; i++)\n      {\n\tPoint<2> sp = spline->GetPoint(double(i)/double(n));\n\tfor(int j=0; j<=n; j++)\n\t  {\n\t    double phi = 2.*M_PI*double(j)/double(n);\n\t    \n\t    Point<3> p = p0 + sp(0)*v_axis + sp(1)*cos(phi)*v1 + sp(1)*sin(phi)*v2;\n\t    tas.AddPoint(p);   \n\t  }\n      }\n    \n    for(int i=0; i<n; i++)\n      for(int j=0; j<n; j++)\n\t{\n\t  int pi = (n+1)*i+j;\n\n\t  tas.AddTriangle( TATriangle (id, pi,pi+1,pi+n+1));\n\t  tas.AddTriangle( TATriangle (id, pi+1,pi+n+1,pi+n+2));\n\t}\n  }\n  \n\n  bool RevolutionFace :: BoxIntersectsFace(const Box<3> & box) const\n  {\n    Point<3> center = box.Center();\n\n    Project(center);\n\n    return (Dist(box.Center(),center) < 0.5*box.Diam());\n  }\n\n\n  /*\n  bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const\n  {\n    Point<2> c,pmin,pmax;\n    CalcProj(box.Center(),c);\n    double aux = box.Diam()/sqrt(8.);\n    pmin(0) = c(0)-aux; pmin(1) = c(1)-aux;\n    pmax(0) = c(0)+aux; pmax(1) = c(1)+aux;\n    \n    BoxSphere<2> box2d(pmin,pmax);\n    return BoxIntersectsFace(box2d, uncertain);\n  }\n\n  bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const\n  {\n    const LineSegment * line = dynamic_cast<const LineSegment*>(&spline);\n    const SplineSegment3 * spline3 = dynamic_cast<const SplineSegment3*>(&spline);\n\n    bool always_right = true, always_left = true;\n\n    bool retval = false;\n    bool thisint;\n    bool intdirect = false;\n    bool inttangent = false;\n    uncertain = false;\n\n    if(line) inttangent = true;\n  \n    for(int i=0; i<checklines_start.Size(); i++)\n      {\n\tVec<2> b = box.Center()- (*checklines_start[i]);\n\n\tdouble d;\n\n\tdouble checkdist = b * (*checklines_vec[i]);\n\tdouble ncomp = b * (*checklines_normal[i]);\n\n\tif(checkdist < 0)\n\t  d = b.Length();\n\telse if (checkdist > 1)\n\t  {\n\t    if(spline3)\n\t      d = Dist(box.Center(),*checklines_start[(i+1)%3]);\n\t    else\n\t      d = Dist(box.Center(),(*checklines_start[i]) \n\t\t       + pow(checklines_vec[i]->Length(),2)*(*checklines_vec[i]));\n\t  }\n\telse \n\t  d = fabs(ncomp);\n\t  \n\tthisint = (box.Diam() >= 2.*d);\n\tretval = retval || thisint;\n\tif(thisint)\n\t  {\n\t    if(i==0)\n\t      intdirect = true;\n\t    else\n\t      inttangent = true;\n\t  }\n\n\tif(ncomp > 0) always_right = false;\n\telse if(ncomp < 0) always_left = false;\n      }\n\n    if(retval && !(intdirect && inttangent))\n      uncertain = true;\n\n    if(!retval && spline3 && (always_right || always_left))\n      {\n\tretval = true;\n\tuncertain = true;\n      }\n    \n    return retval;\t\n  }  \n  */\n  \n  \n  /* INSOLID_TYPE */ bool RevolutionFace :: PointInFace (const Point<3> & p, const double eps) const\n  {\n    Point<2> p2d;\n    CalcProj(p,p2d);\n\n    if (!spline -> InConvexHull(p2d, eps)) return false;\n\n    /*\n    double val = spline_coefficient(0)*p2d(0)*p2d(0) + spline_coefficient(1)*p2d(1)*p2d(1) + spline_coefficient(2)*p2d(0)*p2d(1) +\n      spline_coefficient(3)*p2d(0) + spline_coefficient(4)*p2d(1) + spline_coefficient(5);\n    */\n    Vec<2> pr = p2d - spline->StartPI();\n    double val = spline_coefficient_shifted(0)*pr(0)*pr(0)\n      + spline_coefficient_shifted(1)*pr(1)*pr(1)\n      + spline_coefficient_shifted(2)*pr(0)*pr(1) \n      + spline_coefficient_shifted(3)*pr(0)\n      + spline_coefficient_shifted(4)*pr(1)\n      + spline_coefficient_shifted(5);\n    \n    return (fabs(val) < eps);\n      /*\n    if(val > eps)\n      return IS_OUTSIDE;\n    if(val < -eps)\n      return IS_INSIDE;\n     \n    return DOES_INTERSECT;\n      */\n  }\n\n  \n\n  void RevolutionFace :: GetRawData(NgArray<double> & data) const\n  {\n    data.DeleteAll();\n    spline->GetRawData(data);\n    for(int i=0; i<3; i++)\n      data.Append(p0(i));\n    for(int i=0; i<3; i++)\n      data.Append(v_axis(i));\n    data.Append((isfirst) ? 1. : 0.);\n    data.Append((islast) ? 1. : 0.);\n  }\n\n\n\n  Revolution :: Revolution(const Point<3> & p0_in,\n\t\t\t   const Point<3> & p1_in,\n\t\t\t   shared_ptr<SplineGeometry<2>> spline_in) :\n    p0(p0_in), p1(p1_in), splinegeo(spline_in)\n  {\n    auto nsplines = spline_in->GetNSplines();\n    surfaceactive.SetSize(0);\n    surfaceids.SetSize(0);\n\n    v_axis = p1-p0;\n\n    v_axis.Normalize();\n\n    if(spline_in->GetSpline(0).StartPI()(1) <= 0. &&\n       spline_in->GetSpline(nsplines-1).EndPI()(1) <= 0.)\n      type = 2;\n    else if (Dist(spline_in->GetSpline(0).StartPI(),\n\t\t  spline_in->GetSpline(nsplines-1).EndPI()) < 1e-7)\n      type = 1;\n    else\n      cerr << \"Surface of revolution cannot be constructed\" << endl;\n\n    for(int i=0; i<spline_in->GetNSplines(); i++)\n      {\n\tfaces.Append(new RevolutionFace\n                     (spline_in->GetSpline(i),\n                      p0,v_axis,\n                      type==2 && i==0,\n                      type==2 && i==spline_in->GetNSplines()-1));\n        surfaceactive.Append(1);\n\tsurfaceids.Append(0);\n      }\n\n    // checking\n    if (type == 2)\n      {\n        auto t0 = spline_in->GetSpline(0).GetTangent(0);\n        cout << \"tstart (must be vertically): \" << t0 << endl;\n\n        auto tn = spline_in->GetSpline(nsplines-1).GetTangent(1);\n        cout << \"tend (must be vertically): \" << tn << endl;\n\n        for (int i = 0; i < nsplines-1; i++)\n          {\n            auto ta = spline_in->GetSpline(i).GetTangent(1);\n            auto tb = spline_in->GetSpline(i+1).GetTangent(0);\n            cout << \"sin (must not be 0) = \" << abs(ta(0)*tb(1)-ta(1)*tb(0)) / (Abs(ta)*Abs(tb)); \n          }\n      }\n  }\n  \n  Revolution::~Revolution()\n  {\n    for(int i=0; i<faces.Size(); i++)\n      delete faces[i];\n  }\n\n\n  INSOLID_TYPE Revolution :: BoxInSolid (const BoxSphere<3> & box) const\n  {\n    for(int i=0; i<faces.Size(); i++)\n      if(faces[i]->BoxIntersectsFace(box))\n\treturn DOES_INTERSECT;\n    \n    \n    return PointInSolid(box.Center(),0);\n\t \n\n    /*\n    Point<2> c,pmin,pmax;\n    faces[0]->CalcProj(box.Center(),c);\n    double aux = box.Diam()/sqrt(8.);\n    pmin(0) = c(0)-aux; pmin(1) = c(1)-aux;\n    pmax(0) = c(0)+aux; pmax(1) = c(1)+aux;\n    \n\n    BoxSphere<2> box2d(pmin,pmax);\n\n    bool intersection = false;\n    bool uncertain = true;\n\n    for(int i=0; !(intersection && !uncertain) && i<faces.Size(); i++)\n      {\n\tbool thisintersects;\n\tbool thisuncertain;\n\tthisintersects = faces[i]->BoxIntersectsFace(box2d,thisuncertain);\n\tintersection = intersection || thisintersects;\n\tif(thisintersects && !thisuncertain)\n\t  uncertain = false;\n      }\n\n    if(intersection)\n      {\n\tif(!uncertain)\n\t  return DOES_INTERSECT;\n\telse\n\t  {\n\t    NgArray < Point<3> > pext(2);\n\t    Point<3> p;\n\n\t    pext[0] = box.PMin();\n\t    pext[1] = box.PMax();\n\n\t    INSOLID_TYPE position;\n\t    bool firsttime = true;\n\n\t    for(int i=0; i<2; i++)\n\t      for(int j=0; j<2; j++)\n\t\tfor(int k=0; k<2; k++)\n\t\t  {\n\t\t    p(0) = pext[i](0);\n\t\t    p(1) = pext[j](1);\n\t\t    p(2) = pext[k](2);\n\t\t    INSOLID_TYPE ppos = PointInSolid(p,0);\n\t\t    if(ppos == DOES_INTERSECT)\n\t\t      return DOES_INTERSECT;\n\t\t    \n\t\t    if(firsttime)\n\t\t      {\n\t\t\tfirsttime = false;\n\t\t\tposition = ppos;\n\t\t      }\n\t\t    if(position != ppos)\n\t\t      return DOES_INTERSECT;\t    \n\t\t  }\n\t    return position;\n\n\t  }\n      }\n\n    return PointInSolid(box.Center(),0);\n    */ \n  }\n\n  INSOLID_TYPE Revolution :: PointInSolid (const Point<3> & p,\n\t\t\t\t\t   double eps) const\n  {\n    Point<2> p2d;\n    faces[0]->CalcProj(p,p2d);\n\n    [[maybe_unused]] int intersections_before(0), intersections_after(0);\n    double randomx = 7.42357;\n    double randomy = 1.814756;\n    double randomlen = sqrt(randomx*randomx+randomy*randomy);\n    randomx *= 1./randomlen;\n    randomy *= 1./randomlen;\n    \n\n    const double a = randomy;\n    const double b = -randomx;\n    const double c = -a*p2d(0)-b*p2d(1);\n\n    NgArray < Point<2> > points;\n\n    //(*testout) << \"face intersections at: \" << endl;\n    for(int i=0; i<faces.Size(); i++)\n      {\n\tfaces[i]->GetSpline().LineIntersections(a,b,c,points,eps);\n\t\n\tfor(int j=0; j<points.Size(); j++)\n\t  {\n\t    double t = (points[j](0)-p2d(0))/randomx;\n\n\t    //(*testout) << t << endl;\n\t    if ( t < -eps )\n\t      intersections_before++;\n\t    else if ( t > eps )\n\t      intersections_after++;\n\t    else\n\t      {\n\t\tintersecting_face = i;\n\t\treturn DOES_INTERSECT;\n\t      }\n\t  }\n      }\n\n    if(intersections_after % 2 == 0)\n      return IS_OUTSIDE;\n    else\n      return IS_INSIDE;\n  }\n\n  void Revolution :: GetTangentialSurfaceIndices (const Point<3> & p, \n                                                 NgArray<int> & surfind, double eps) const\n  {\n    for (int j = 0; j < faces.Size(); j++)\n      if (faces[j] -> PointInFace(p, eps))\n        if (!surfind.Contains (GetSurfaceId(j)))\n          surfind.Append (GetSurfaceId(j));\n  }\n\n  INSOLID_TYPE Revolution :: VecInSolid (const Point<3> & p,\n\t\t\t\t\t const Vec<3> & v,\n\t\t\t\t\t double eps) const\n  {\n    INSOLID_TYPE pInSolid = PointInSolid(p,eps);\n\n    if(pInSolid != DOES_INTERSECT)\n      {\n\t//(*testout) << \"pInSolid\" << endl;\n\treturn pInSolid;\n      }\n\n    NgArray<int> intersecting_faces;\n\n    for(int i=0; i<faces.Size(); i++)\n      if(faces[i]->PointInFace(p,eps)) //  == DOES_INTERSECT)\n\tintersecting_faces.Append(i);\n\n     Vec<3> hv;\n\n    if(intersecting_faces.Size() == 1)\n      {\n\tfaces[intersecting_faces[0]]->CalcGradient(p,hv);\n\n\tdouble hv1;\n\thv1 = v * hv;\n\t\n\tif (hv1 <= -eps)\n\t  return IS_INSIDE;\n\tif (hv1 >= eps)\n\t  return IS_OUTSIDE;\n\t\n\treturn DOES_INTERSECT; \n      }\n    else if(intersecting_faces.Size() == 2)\n      {\n\tPoint<2> p2d;\n\tVec<2> v2d;\n\tfaces[intersecting_faces[0]]->CalcProj(p,p2d,v,v2d);\n\n\tif(Dist(faces[intersecting_faces[0]]->GetSpline().StartPI(),p2d) <\n\t   Dist(faces[intersecting_faces[0]]->GetSpline().EndPI(),p2d))\n\t  {\n\t    int aux = intersecting_faces[0];\n\t    intersecting_faces[0] = intersecting_faces[1];\n\t    intersecting_faces[1] = aux;\n\t  }\n\t\n\tconst SplineSeg3<2> * splinesegment3 = \n\t  dynamic_cast<const SplineSeg3<2> *>(&faces[intersecting_faces[0]]->GetSpline());\n\tconst LineSeg<2> * linesegment = \n\t  dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[0]]->GetSpline());\n\t\t\n\tVec<2> t1(0),t2(0);\n\n\tif(linesegment)\n\t  t1 = linesegment->StartPI() - linesegment->EndPI();\n\telse if(splinesegment3)\n\t  t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI();\n\n\tlinesegment = \n\t  dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[1]]->GetSpline());\n\tsplinesegment3 = \n\t  dynamic_cast<const SplineSeg3<2> *>(&faces[intersecting_faces[1]]->GetSpline());\n\t\n\tif(linesegment)\n\t  t2 = linesegment->EndPI() - linesegment->StartPI();\n\telse if(splinesegment3)\n\t  t2 = splinesegment3->TangentPoint() - splinesegment3->StartPI();\n\n\tt1.Normalize();\n\tt2.Normalize();\n\n\tdouble d1 = v2d*t1;\n\tdouble d2 = v2d*t2;\n\n\tVec<2> n;\n\n\tif(d1 > d2)\n\t  {\n\t    n(0) = t1(1);\n\t    n(1) = -t1(0);\n\t  }\n\telse\n\t  {\n\t    n(0) = -t2(1);\n\t    n(1) = t2(0);\n\t  }\n\n\tdouble d = v2d*n;\n\n\tif(d > eps)\n\t  return IS_OUTSIDE;\n\telse if (d < -eps)\n\t  return IS_INSIDE;\n\telse\n\t  return DOES_INTERSECT;\n\n\n      }\n    else\n      {\n\tcerr << \"Jo gibt's denn des?\" << endl;\n      }\n\n    return DOES_INTERSECT;    \n  }\n\n  INSOLID_TYPE Revolution :: VecInSolid2 (const Point<3> & p,\n\t\t\t\t\t  const Vec<3> & v1,\n\t\t\t\t\t  const Vec<3> & v2,\n\t\t\t\t\t  double eps) const\n  {\n    INSOLID_TYPE ret1 = VecInSolid(p,v1,eps);\n    if(ret1 != DOES_INTERSECT)\n      return ret1;\n\n    return VecInSolid(p,v1+0.01*v2,eps);\n  }\n\n  void Revolution ::\n  GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n                                   NgArray<int> & surfind, double eps) const\n  {\n    *testout << \"tangentialvecsurfind2, p = \" << p << endl;\n    for (int i = 0; i < faces.Size(); i++)\n      if (faces[i]->PointInFace (p, eps))\n        {\n          *testout << \"check face \" << i << endl;\n          Point<2> p2d;\n          Vec<2> v12d;\n          faces[i]->CalcProj(p,p2d,v1,v12d);\n          *testout << \"v12d = \" << v12d << endl;\n          auto & spline = faces[i]->GetSpline();\n          if (Dist2 (spline.StartPI(), p2d) < sqr(eps))\n            {\n              *testout << \"start pi\" << endl;\n              Vec<2> tang = spline.GetTangent(0);\n              double ip = tang*v12d;\n              *testout << \"ip = \" << ip << endl;\n              if (ip > eps)\n                surfind.Append(GetSurfaceId(i));\n              else if (ip > -eps)\n                {\n                  Vec<2> v22d;\n                  faces[i]->CalcProj(p,p2d,v2,v22d);\n                  double ip2 = tang*v22d;\n                  *testout << \"ip2 = \" << ip2 << endl;\n                  if (ip2 > -eps)\n                    surfind.Append(GetSurfaceId(i));                    \n                }\n            }\n          else if (Dist2 (faces[i]->GetSpline().EndPI(), p2d) < sqr(eps))\n            {\n              *testout << \"end pi\" << endl;\n              \n              Vec<2> tang = spline.GetTangent(1);\n              double ip = tang*v12d;\n              *testout << \"ip = \" << ip << endl;\n              if (ip < -eps)\n                surfind.Append(GetSurfaceId(i));\n              else if (ip < eps)\n                {\n                  Vec<2> v22d;\n                  faces[i]->CalcProj(p,p2d,v2,v22d);\n                  double ip2 = tang*v22d;\n                  *testout << \"ip2 = \" << ip2 << endl;                  \n                  if (ip2 < eps)\n                    surfind.Append(GetSurfaceId(i));                    \n                }\n            }\n          else\n            {\n              *testout << \"inner point\" << endl;\n              surfind.Append(GetSurfaceId(i));\n            }\n        }\n  }\n\n\n  \n  int Revolution :: GetNSurfaces() const\n  {\n    return faces.Size();\n  }\n\n  Surface & Revolution :: GetSurface (int i)\n  {\n    return *faces[i];\n  }\n\n  const Surface & Revolution :: GetSurface (int i) const\n  {\n    return *faces[i];\n  }\n\n\n  void Revolution :: Reduce (const BoxSphere<3> & box)\n  { \n    //bool dummy;\n    for(int i=0; i<faces.Size(); i++)\n      surfaceactive[i] = (faces[i]->BoxIntersectsFace(box));\n    //surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy));\n  }\n\n  void Revolution :: UnReduce ()\n  {\n    for(int i=0; i<faces.Size(); i++)\n      surfaceactive[i] = true;\n  }\n\n  RegisterClassForArchive<RevolutionFace, Surface> regrevf;\n  RegisterClassForArchive<Revolution, Primitive> regrev;\n}\n"
  },
  {
    "path": "libsrc/csg/revolution.hpp",
    "content": "#ifndef _REVOLUTION_HPP\n#define _REVOLUTION_HPP\n\nnamespace netgen\n{\n\n  class Revolution;\n\n  class RevolutionFace : public Surface\n  {\n  private:\n    bool isfirst, islast;\n    const SplineSeg<2> * spline;\n    bool deletable;\n\n    Point<3> p0;\n    Vec<3> v_axis;\n\n    int id;\n\n    // coefficient for implicizt polynomial\n    mutable Vector spline_coefficient;\n    mutable Vector spline_coefficient_shifted;\n\n\n    NgArray < Vec<2>* > checklines_vec;\n    NgArray < Point<2>* > checklines_start;\n    NgArray < Vec<2>* > checklines_normal;\n  \n  private:\n    void Init (void);\n\n  public:\n    void CalcProj(const Point<3> & point3d, Point<2> & point2d) const;\n    void CalcProj(const Point<3> & point3d, Point<2> & point2d,\n\t\t  const Vec<3> & vector3d, Vec<2> & vector2d) const;\n    void CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const;\n\n  public:\n    RevolutionFace(const SplineSeg<2> & spline_in,\n\t\t   const Point<3> & p,\n\t\t   const Vec<3> & vec,\n\t\t   bool first = false,\n\t\t   bool last = false,\n\t\t   const int id_in = 0);\n\n    RevolutionFace(const NgArray<double> & raw_data);\n    // default constructor for archive\n    RevolutionFace() {}\n\n    ~RevolutionFace();\n\n    virtual void DoArchive(Archive& ar)\n    {\n      Surface::DoArchive(ar);\n      ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient\n        & spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal;\n    }\n\n    virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; \n  \n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n    virtual double HesseNorm () const;\n\n    virtual double MaxCurvature () const;\n    //virtual double MaxCurvatureLoc (const Point<3> & /* c */ , \n    //\t\t\t\t  double /* rad */) const;\n    \n    Point<3> P0() const { return p0; }\n    Vec<3> Axis() const { return v_axis; }\n    \n    virtual void Project (Point<3> & p) const;\n\n    virtual Point<3> GetSurfacePoint () const;\n    virtual void Print (ostream & str) const;\n  \n    virtual void GetTriangleApproximation (TriangleApproximation & tas, \n\t\t\t\t\t   const Box<3> & boundingbox, \n\t\t\t\t\t   double facets) const;\n\n    bool BoxIntersectsFace (const Box<3> & box) const;\n    /*\n      bool BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const;\n      bool BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const;\n    */\n\n    const SplineSeg<2> & GetSpline(void) const {return *spline;}\n\n    /* INSOLID_TYPE */ bool PointInFace (const Point<3> & p, const double eps) const;\n\n    void GetRawData(NgArray<double> & data) const;\n\n  };\n\n\n\n  /*\n\n  Primitive of revolution\n  \n  */\n\n\n  class Revolution : public Primitive\n  {\n  private:\n    Point<3> p0,p1;\n    Vec<3> v_axis;\n\n    // 1 ... torus-like\n    // 2 ... sphere-like\n    int type;\n  \n\n    Array<RevolutionFace*> faces;\n    shared_ptr<SplineGeometry<2>> splinegeo;\n\n    mutable int intersecting_face;\n\n  public:\n    Revolution(const Point<3> & p0_in,\n\t       const Point<3> & p1_in,\n\t       shared_ptr<SplineGeometry<2>> spline_in);\n    // default constructor for archive\n    Revolution() {}\n\n    ~Revolution();\n\n    virtual void DoArchive(Archive& ar)\n    {\n      Primitive::DoArchive(ar);\n      ar & p0 & p1 & v_axis & type & faces & intersecting_face;\n    }\n  \n    /*\n      Check, whether box intersects solid defined by surface.\n\n      return values:\n      0 .. box outside solid \\\\\n      1 .. box in solid \\\\\n      2 .. can't decide (allowed, iff box is close to solid)\n    */\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;\n    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t\t       double eps) const;\n\n    virtual void GetTangentialSurfaceIndices (const Point<3> & p, \n\t\t\t\t\t      NgArray<int> & surfind, double eps) const;\n    \n    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const;\n\n    // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t\t\t\t\t  NgArray<int> & surfind, double eps) const;\n\n    \n    virtual int GetNSurfaces() const;\n    virtual Surface & GetSurface (int i = 0);\n    virtual const Surface & GetSurface (int i = 0) const;\n\n\n    virtual void Reduce (const BoxSphere<3> & box);\n    virtual void UnReduce ();\n  \n\t     \n  };\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/singularref.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\nnamespace netgen\n{\n\n  SingularEdge :: SingularEdge (double abeta, int adomnr, \n                                const CSGeometry & ageom,\n                                const Solid * asol1, \n                                const Solid * asol2, double sf,\n                                const double maxh_at_initialization)\n    : domnr(adomnr), geom(ageom)\n  {\n  beta = abeta;\n  maxhinit = maxh_at_initialization;\n\n  if (beta > 1) \n    {\n      beta = 1;\n      cout << \"Warning: beta set to 1\" << endl;\n    }\n  if (beta <= 1e-3)\n    {\n      beta = 1e-3;\n      cout << \"Warning: beta set to minimal value 0.001\" << endl;\n    }\n\n  sol1 = asol1;\n  sol2 = asol2;\n  factor = sf; \n}\n\nvoid SingularEdge :: FindPointsOnEdge (class Mesh & mesh)\n{\n  (*testout) << \"find points on edge\" << endl;\n  points.SetSize(0);\n  segms.SetSize(0);\n\n\n  NgArray<int> si1, si2;\n  sol1->GetSurfaceIndices (si1);\n  sol2->GetSurfaceIndices (si2);\n\n  for (int i = 0; i < si1.Size(); i++)\n    si1[i] = geom.GetSurfaceClassRepresentant(si1[i]);\n  for (int i = 0; i < si2.Size(); i++)\n    si2[i] = geom.GetSurfaceClassRepresentant(si2[i]);\n\n\n  for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n    {\n      PointIndices<2> i2 (mesh[si][0], mesh[si][1]);\n      /*\n      \n      bool onedge = 1;\n      for (j = 1; j <= 2; j++)\n\t{\n\t  const Point<3> p = mesh[ PointIndex (i2.I(j)) ];\n\t  if (sol1->IsIn (p, 1e-3) && sol2->IsIn(p, 1e-3) &&\n\t      !sol1->IsStrictIn (p, 1e-3) && !sol2->IsStrictIn(p, 1e-3))\n\t    {\n\t      ;\n\t    }\n\t  else\n\t    onedge = 0;\n\t}\n      */\n\n      if (domnr != -1 && domnr != mesh[si].domin && domnr != mesh[si].domout)\n\tcontinue;\n\n      /*\n      bool onedge = 1;\n      for (int j = 0; j < 2; j++)\n\t{\n\t  int surfi = (j == 0) ? mesh[si].surfnr1 : mesh[si].surfnr2;\n\t  surfi = geom.GetSurfaceClassRepresentant(surfi);\n\t  if (!si1.Contains(surfi) && !si2.Contains(surfi))\n\t    onedge = 0;\n\t}\n      */\n      int surfi1 = geom.GetSurfaceClassRepresentant(mesh[si].surfnr1);\n      int surfi2 = geom.GetSurfaceClassRepresentant(mesh[si].surfnr2);\n\n      if ( (si1.Contains(surfi1) && si2.Contains(surfi2)) ||\n           (si1.Contains(surfi2) && si2.Contains(surfi1)) )\n\n\t// if (onedge)\n\t{\n\t  segms.Append (i2);\n\t  //\t  PrintMessage (5, \"sing segment \", i2.I1(), \" - \", i2.I2());\n\t  points.Append (mesh[i2.I1()]);\n\t  points.Append (mesh[i2.I2()]);\n\t  mesh[si].singedge_left = factor;\n\t  mesh[si].singedge_right = factor;\n\t}\t    \n    }\n  \n  /*\n  (*testout) << \"Singular edge points:\" << endl;\n  for (int i = 0; i < points.Size(); i++)\n    (*testout) << points[i] << endl;\n  */\n \n}\n\nvoid SingularEdge :: SetMeshSize (class Mesh & mesh, double globalh)\n{\n  double hloc = pow (globalh, 1/beta);\n  if(maxhinit > 0 && maxhinit < hloc)\n    {\n      hloc = maxhinit;\n      if(points.Size() > 1)\n\t{\n\t  for (int i = 0; i < points.Size()-1; i++)\n\t    mesh.RestrictLocalHLine(points[i],points[i+1],hloc);\n\t}\n      else\n\t{\n\t  for (int i = 0; i < points.Size(); i++)\n\t    mesh.RestrictLocalH (points[i], hloc);\n\t}\n    }\n  else\n    {\n      for (int i = 0; i < points.Size(); i++)\n\tmesh.RestrictLocalH (points[i], hloc);\n    }\n}\n\n\n\nSingularPoint :: SingularPoint (double abeta, \n\t\t\t\tconst Solid * asol1, \n\t\t\t\tconst Solid * asol2,\n\t\t\t\tconst Solid * asol3, double sf)\n{\n  beta = abeta;\n  sol1 = asol1;\n  sol2 = asol2;\n  sol3 = asol3;\n  factor = sf; \n}\n\n\nvoid SingularPoint :: FindPoints (class Mesh & mesh)\n{\n  points.SetSize(0);\n  NgArray<int> surfk, surf;\n\n\n  for (PointIndex pi = IndexBASE<PointIndex>(); \n       pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)\n    {\n      if (mesh[pi].Type() != FIXEDPOINT) continue;\n      const Point<3> p = mesh[pi];\n\n      (*testout) << \"check singular point\" << p << endl;\n\n      if (sol1->IsIn (p) && sol2->IsIn(p) && sol3->IsIn(p) &&\n\t  !sol1->IsStrictIn (p) && !sol2->IsStrictIn(p) && !sol3->IsStrictIn(p))\n\t{\n\t  surf.SetSize (0);\n\t  for (int k = 1; k <= 3; k++)\n\t    {\n\t      const Solid * solk(NULL);\n\t      // Solid *tansol;\n\t      switch (k)\n\t\t{\n\t\tcase 1:  solk = sol1; break;\n\t\tcase 2:  solk = sol2; break;\n\t\tcase 3:  solk = sol3; break;\n\t\t}\n\n\t      auto tansol = solk -> TangentialSolid (p, surfk, 1e-3);\n\t      (*testout) << \"Tansol = \" << *tansol << endl;\n\n\t      if (!tansol) continue;\n\n\t      ReducePrimitiveIterator rpi(Box<3> (p-Vec<3> (1e-3,1e-3,1e-3),\n\t\t\t\t\t\t  p+Vec<3> (1e-3,1e-3,1e-3)));\n\t      UnReducePrimitiveIterator urpi;\n\t      \n\t      tansol -> IterateSolid (rpi);\n\t      tansol->GetSurfaceIndices (surfk);\n\t      tansol -> IterateSolid (urpi);\n\n\t      (*testout) << \"surfinds = \" << surfk << endl;\n\n\t      for (int i = 0; i < surfk.Size(); i++)\n\t\tif (!surf.Contains (surfk[i]))\n\t\t  surf.Append (surfk[i]);\n\t      \n\t      // delete tansol;\n\t    }\n\n\t  if (surf.Size() < 3) continue;\n\n\t  points.Append (p);\n\t  PrintMessage (5, \"Point (\", p(0), \", \", p(1), \", \", p(2), \") is singular\");\n\t  mesh[pi].Singularity(factor);\n\t}\n    }  \n}\n\n\nvoid SingularPoint :: SetMeshSize (class Mesh & mesh, double globalh)\n{\n  double hloc = pow (globalh, 1/beta);\n  for (int i = 1; i <= points.Size(); i++)\n    mesh.RestrictLocalH (points.Get(i), hloc);  \n}\n}\n"
  },
  {
    "path": "libsrc/csg/singularref.hpp",
    "content": "#ifndef FILE_SINGULARREF\n#define FILE_SINGULARREF\n\n/**************************************************************************/\n/* File:   singularref.hh                                                 */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   25. Sep. 99                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n  /**\n     Control for local refinement\n  */\n\n\n\n  /**\n     Singular Face.\n     Causes a boundary layer mesh refinement.\n     All elements in subdomain domnr will get a boundary layer\n     on faces sharing the solid sol\n  */\n  class DLL_HEADER SingularFace \n  {\n  public:\n    int domnr;\n    const Solid *sol;\n    double factor; \n    // NgArray<Point<3> > points;\n    // NgArray<INDEX_2> segms;\n  public:\n    SingularFace (int adomnr, const Solid * asol, double sf)\n      : domnr(adomnr), sol(asol), factor(sf) { ; }\n    const Solid * GetSolid() const { return sol; }\n    int GetDomainNr () const { return domnr; }\n  };\n\n\n  ///\n  class DLL_HEADER SingularEdge\n  {\n  public:\n    double beta;\n    int domnr;\n    const CSGeometry& geom;\n    const Solid *sol1, *sol2;\n    NgArray<Point<3> > points;\n    NgArray<INDEX_2> segms;\n    double factor; \n\n    double maxhinit;\n  public:\n    SingularEdge (double abeta, int adomnr, \n\t\t  const CSGeometry & ageom,\n\t\t  const Solid * asol1, const Solid * asol2, double sf,\n\t\t  const double maxh_at_initialization = -1);\n    void FindPointsOnEdge (class Mesh & mesh);\n    void SetMeshSize (class Mesh & mesh, double globalh);\n  };\n\n\n  ///\n  class DLL_HEADER SingularPoint\n  {\n  public:\n    double beta;\n    const Solid *sol1, *sol2, *sol3;\n    NgArray<Point<3> > points;\n    double factor; \n \n  public:\n    SingularPoint (double abeta, const Solid * asol1, const Solid * asol2,\n\t\t   const Solid * asol3, double sf);\n    void FindPoints (class Mesh & mesh);\n    void SetMeshSize (class Mesh & mesh, double globalh);\n  };\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/solid.cpp",
    "content": "#include <mystdlib.h>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n\n  // int Solid :: cntnames = 0;\n  \n  Solid :: Solid (Primitive * aprim)\n  {\n    op = TERM;\n    prim = aprim;\n    s1 = s2 = NULL;\n    maxh = 1e10;\n    name = NULL;\n    num_surfs = prim->GetNSurfaces();\n  }\n\n  Solid :: Solid (optyp aop, Solid * as1, Solid * as2)\n  {\n    op = aop;\n    s1 = as1;\n    s2 = as2;\n    prim = NULL;\n    name = NULL;\n    maxh = 1e10;\n    num_surfs = 0;\n    if (s1) num_surfs += s1->num_surfs;\n    if (s2) num_surfs += s2->num_surfs;\n  }\n\n  Solid :: ~Solid ()\n  {\n    // cout << \"delete solid, op = \" << int(op) << endl;\n    delete [] name;\n\n    switch (op)\n      {\n      case UNION:\n      case SECTION:\n\t{\n\t  if (s1->op != ROOT) delete s1;\n\t  if (s2->op != ROOT) delete s2;\n\t  break;\n\t}\n      case SUB:\n\t// case ROOT:\n\t{\n\t  if (s1->op != ROOT) delete s1;\n\t  break;\n\t}\n      case TERM:\n\t{\n\t  // cout << \"has term\" << endl;\n\t  delete prim;\n\t  break;\n\t}\n      default:\n\tbreak;\n      }\n  }\n\n  void Solid :: SetName (const char * aname)\n  {\n    delete [] name;\n    name = new char[strlen (aname)+1];\n    strcpy (name, aname);\n  }\n\n\n  Solid * Solid :: Copy (CSGeometry & geom) const\n  {\n    Solid * nsol(NULL);\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  Primitive * nprim = prim->Copy();\n\t  geom.AddSurfaces (nprim);\n\t  nsol = new Solid (nprim);\n\t  break;\n\t}\n\n      case SECTION:\n      case UNION:\n\t{\n\t  nsol = new Solid (op, s1->Copy(geom), s2->Copy(geom));\n\t  break;\n\t}\n\n      case SUB:\n\t{\n\t  nsol = new Solid (SUB, s1 -> Copy (geom));\n\t  break;\n\t}\n      \n      case ROOT:\n\t{\n\t  nsol = s1->Copy(geom);\n\t  break;\n\t}\n      }\n\n    return nsol;\n  }\n\n \n  void Solid :: Transform (Transformation<3> & trans)\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  prim -> Transform (trans);\n\t  break;\n\t}\n      case SECTION:\n      case UNION:\n\t{\n\t  s1 -> Transform (trans);\n\t  s2 -> Transform (trans);\n\t  break;\n\t}\n\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> Transform (trans);\n\t  break;\n\t}\n      }  \n  }\n\n\n\n  void Solid :: IterateSolid (SolidIterator & it,\n\t\t\t      bool only_once)\n  {\n    if (only_once)\n      {\n\tif (visited)\n\t  return;\n\n\tvisited = 1; \n      }\n\n    it.Do (this);\n\n    switch (op)\n      {\n      case SECTION:\n\t{\n\t  s1->IterateSolid (it, only_once);\n\t  s2->IterateSolid (it, only_once);\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  s1->IterateSolid (it, only_once);\n\t  s2->IterateSolid (it, only_once);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1->IterateSolid (it, only_once);\n\t  break;\n\t}\n      case TERM:\n      case TERM_REF:\n\tbreak;   // do nothing\n      } \n  }\n\n\n\n  INSOLID_TYPE Solid ::\n  PointInSolid (const Point<3> & p, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n        return prim->PointInSolid (p, eps);\n      case SECTION:\n        return Intersection (s1->PointInSolid (p, eps), s2->PointInSolid (p, eps));\n      case UNION:\n        return Union (s1->PointInSolid (p, eps), s2->PointInSolid (p, eps));          \n      case SUB:\n        return Complement (s1->PointInSolid (p, eps));\n      case ROOT:\n\treturn s1->PointInSolid (p, eps);\n      }\n      throw Exception(\"PointInSolid: invalid op\");\n  }\n\n  \n  INSOLID_TYPE Solid ::\n  VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n        return prim->VecInSolid (p, v, eps);\n      case SECTION:\n        return Intersection (s1->VecInSolid (p, v, eps), s2->VecInSolid (p, v, eps));        \n      case UNION:\n        return Union (s1->VecInSolid (p, v, eps), s2->VecInSolid (p, v, eps));                \n      case SUB:\n        return Complement (s1->VecInSolid (p, v, eps));\n      case ROOT:\n\treturn s1->VecInSolid (p, v, eps);\n      }\n      throw Exception(\"VecInSolid: invalid op\");\n  }\n  \n  // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n  INSOLID_TYPE Solid ::\n  VecInSolid2 (const Point<3> & p, const Vec<3> & v1,\n               const Vec<3> & v2, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n        return prim->VecInSolid2 (p, v1, v2, eps);\n      case SECTION:\n        return Intersection (s1->VecInSolid2 (p, v1, v2, eps), s2->VecInSolid2 (p, v1, v2, eps));\n      case UNION:\n        return Union (s1->VecInSolid2 (p, v1, v2, eps), s2->VecInSolid2 (p, v1, v2, eps));          \n      case SUB:\n        return Complement (s1->VecInSolid2 (p, v1, v2, eps));\n      case ROOT:\n\treturn s1->VecInSolid2 (p, v1, v2, eps);\n      }\n      throw Exception(\"VecInSolid2: invalid op\");\n  }\n\n  \n\n\n  bool Solid :: IsIn (const Point<3> & p, double eps) const\n  {\n    return PointInSolid (p,eps) != IS_OUTSIDE;\n      /*\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->PointInSolid (p, eps);\n\t  return ( (ist == IS_INSIDE) || (ist == DOES_INTERSECT) ) ? 1 : 0;\n\t}\n      case SECTION:\n\treturn s1->IsIn (p, eps) && s2->IsIn (p, eps);\n      case UNION:\n\treturn s1->IsIn (p, eps) || s2->IsIn (p, eps);\n      case SUB:\n\treturn !s1->IsStrictIn (p, eps);\n      case ROOT:\n\treturn s1->IsIn (p, eps);\n      }\n    return 0;\n      */\n  }\n\n  bool Solid :: IsStrictIn (const Point<3> & p, double eps) const\n  {\n    return PointInSolid (p,eps) == IS_INSIDE;\n    /*\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->PointInSolid (p, eps);\n\t  return (ist == IS_INSIDE) ? 1 : 0;\n\t}\n      case SECTION:\n\treturn s1->IsStrictIn(p, eps) && s2->IsStrictIn(p, eps);\n      case UNION:\n\treturn s1->IsStrictIn(p, eps) || s2->IsStrictIn(p, eps);\n      case SUB:\n\treturn !s1->IsIn (p, eps);\n      case ROOT:\n\treturn s1->IsStrictIn (p, eps);\n      }\n    return 0;\n    */\n  }\n\n  bool Solid :: VectorIn (const Point<3> & p, const Vec<3> & v, \n\t\t\t double eps) const\n  {\n    return VecInSolid (p,v,eps) != IS_OUTSIDE;\n    /*\n    Vec<3> hv;\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);\n\t  return (ist == IS_INSIDE || ist == DOES_INTERSECT) ? 1 : 0;\n\t}\n      case SECTION:\n\treturn s1 -> VectorIn (p, v, eps) && s2 -> VectorIn (p, v, eps);\n      case UNION:\n\treturn s1 -> VectorIn (p, v, eps) || s2 -> VectorIn (p, v, eps);\n      case SUB:\n\treturn !s1->VectorStrictIn(p, v, eps);\n      case ROOT:\n\treturn s1->VectorIn(p, v, eps);\n      }\n    return 0;\n    */\n  }\n\n  bool Solid :: VectorStrictIn (const Point<3> & p, const Vec<3> & v,\n\t\t\t       double eps) const\n  {\n    return VecInSolid (p,v,eps) == IS_INSIDE;\n    /*\n    Vec<3> hv;\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);\n\t  return (ist == IS_INSIDE) ? true : false;\n\t}\n      case SECTION:\n\treturn s1 -> VectorStrictIn (p, v, eps) && \n\t  s2 -> VectorStrictIn (p, v, eps);\n      case UNION:\n\treturn s1 -> VectorStrictIn (p, v, eps) || \n\t  s2 -> VectorStrictIn (p, v, eps);\n      case SUB:\n\treturn !s1->VectorIn(p, v, eps);\n      case ROOT:\n\treturn s1->VectorStrictIn(p, v, eps);\n      }\n    return 0;\n    */\n  }\n\n\n  /*\n  bool Solid::VectorIn2 (const Point<3> & p, const Vec<3> & v1, \n\t\t\tconst Vec<3> & v2, double eps) const\n  {\n    if (VectorStrictIn (p, v1, eps))\n      return 1;\n    if (!VectorIn (p, v1, eps))\n      return 0;\n  \n    bool res = VectorIn2Rec (p, v1, v2, eps);\n    return res;\n  }\n\n  bool Solid::VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, \n\t\t\t   const Vec<3> & v2, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\treturn (prim->VecInSolid2 (p, v1, v2, eps) != IS_OUTSIDE); // Is this correct????\n      case SECTION:\n\treturn s1->VectorIn2Rec (p, v1, v2, eps) && \n\t  s2->VectorIn2Rec (p, v1, v2, eps);\n      case UNION:\n\treturn s1->VectorIn2Rec (p, v1, v2, eps) ||\n\t  s2->VectorIn2Rec (p, v1, v2, eps);\n      case SUB:\n\treturn !s1->VectorIn2Rec (p, v1, v2, eps);\n      case ROOT:\n\treturn s1->VectorIn2Rec (p, v1, v2, eps);\n      }\n    return 0;  \n  }\n  */\n\n\n  bool Solid::VectorIn2 (const Point<3> & p, const Vec<3> & v1, \n                         const Vec<3> & v2, double eps) const\n  {\n    return VecInSolid2 (p,v1,v2,eps) != IS_OUTSIDE;\n    /*\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n        {\n          auto res = prim->VecInSolid2 (p, v1, v2, eps);\n          return res != IS_OUTSIDE;\n        }\n      case SECTION:\n\treturn s1->VectorIn2 (p, v1, v2, eps) && s2->VectorIn2 (p, v1, v2, eps);\n      case UNION:\n\treturn s1->VectorIn2 (p, v1, v2, eps) || s2->VectorIn2 (p, v1, v2, eps);\n      case SUB:\n\treturn !s1->VectorStrictIn2 (p, v1, v2, eps);\n      case ROOT:\n\treturn s1->VectorIn2 (p, v1, v2, eps);\n      }\n    // return 0;  \n    */\n  }\n\n  bool Solid :: VectorStrictIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n                                 double eps) const\n  {\n    return VecInSolid2 (p,v1,v2,eps) == IS_INSIDE;\n    /*\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n        {\n          auto res = prim->VecInSolid2 (p, v1, v2, eps);\n          return (res == IS_INSIDE);\n        }\n      case SECTION:\n\treturn s1->VectorStrictIn2 (p, v1, v2, eps) && s2->VectorStrictIn2 (p, v1, v2, eps);\n      case UNION:\n\treturn s1->VectorStrictIn2 (p, v1, v2, eps) || s2->VectorStrictIn2 (p, v1, v2, eps);\n      case SUB:\n\treturn !s1->VectorIn2 (p, v1, v2, eps);\n      case ROOT:\n\treturn s1->VectorStrictIn2 (p, v1, v2, eps);\n      }\n    */\n  }\n\n\n  void Solid :: Print (ostream & str) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  str << prim->GetSurfaceId(0);\n\t  for (int i = 1; i < prim->GetNSurfaces(); i++)\n\t    str << \",\" << prim->GetSurfaceId(i);\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  str << \"(\";\n\t  s1 -> Print (str);\n\t  str << \" AND \";\n\t  s2 -> Print (str);\n\t  str << \")\";\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  str << \"(\";\n\t  s1 -> Print (str);\n\t  str << \" OR \";\n\t  s2 -> Print (str);\n\t  str << \")\";\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  str << \" NOT \";\n\t  s1 -> Print (str);\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  str << \" [\" << name << \"=\";\n\t  s1 -> Print (str);\n\t  str << \"] \";\n\t  break;\n\t}\n      }\n  }\n\n\n\n  void Solid :: GetSolidData (ostream & ost, int first) const\n  {\n    switch (op)\n      {\n      case SECTION:\n\t{\n\t  ost << \"(\";\n\t  s1 -> GetSolidData (ost, 0);\n\t  ost << \" AND \";\n\t  s2 -> GetSolidData (ost, 0);\n\t  ost << \")\";\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  ost << \"(\";\n\t  s1 -> GetSolidData (ost, 0);\n\t  ost << \" OR \";\n\t  s2 -> GetSolidData (ost, 0);\n\t  ost << \")\";\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  ost << \"NOT \";\n\t  s1 -> GetSolidData (ost, 0);\n\t  break;\n\t}\n      case TERM: case TERM_REF:\n\t{\n\t  if (name)\n\t    ost << name;\n\t  else\n\t    ost << \"(noname)\";\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  if (first)\n\t    s1 -> GetSolidData (ost, 0);\n\t  else\n\t    ost << name;\n\t  break;\n\t}\n      }\n  }\n\n\n\n  static Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids);\n  static Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids);\n  static Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids);\n\n  static void ReadString (istream & ist, char * str)\n  {\n    //char * hstr = str;\n    char ch;\n\n    while (1)\n      {\n\tist.get(ch);\n\tif (!ist.good()) break;\n\n\tif (!isspace (ch))\n\t  {\n\t    ist.putback (ch);\n\t    break;\n\t  }\n      }\n\n    while (1)\n      {\n\tist.get(ch);\n\tif (!ist.good()) break;\n\tif (isalpha(ch) || isdigit(ch))\n\t  {\n\t    *str = ch;\n\t    str++;\n\t  }\n\telse\n\t  {\n\t    ist.putback (ch);\n\t    break;\n\t  }\n      }\n    *str = 0;\n    //  cout << \"Read string (\" << hstr << \")\" \n    //       << \"put back: \" << ch << endl;\n  }\n\n\n  Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids)\n  {\n    //  cout << \"create expr\" << endl;\n\n    Solid *s1, *s2;\n    char str[100];\n\n    s1 = CreateSolidTerm (ist, solids);\n    ReadString (ist, str);\n    if (strcmp (str, \"OR\") == 0)\n      {\n\t//      cout << \" OR \";\n\ts2 = CreateSolidExpr (ist, solids);\n\treturn new Solid (Solid::UNION, s1, s2);\n      }\n\n    //  cout << \"no OR found, put back string: \" << str << endl;\n    for (int i = int(strlen(str))-1; i >= 0; i--)\n      ist.putback (str[i]);\n\n    return s1;\n  }\n\n  Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids)\n  {\n    //  cout << \"create term\" << endl;\n\n    Solid *s1, *s2;\n    char str[100];\n\n    s1 = CreateSolidPrim (ist, solids);\n    ReadString (ist, str);\n    if (strcmp (str, \"AND\") == 0)\n      {\n\t//      cout << \" AND \";\n\ts2 = CreateSolidTerm (ist, solids);\n\treturn new Solid (Solid::SECTION, s1, s2);\n      }\n\n\n    //  cout << \"no AND found, put back string: \" << str << endl;\n    for (int i = int(strlen(str))-1; i >= 0; i--)\n      ist.putback (str[i]);\n\n    return s1;\n  }\n\n  Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids)\n  {\n    Solid * s1;\n    char ch;\n    char str[100];\n\n    ist >> ch;\n    if (ch == '(')\n      {\n\ts1 = CreateSolidExpr (ist, solids);\n\tist >> ch;  // ')'\n\t//      cout << \"close back \" << ch << endl;\n\treturn s1;\n      }\n    ist.putback (ch);\n  \n    ReadString (ist, str);\n    if (strcmp (str, \"NOT\") == 0)\n      {\n\t//      cout << \" NOT \";\n\ts1 = CreateSolidPrim (ist, solids);\n\treturn new Solid (Solid::SUB, s1);\n      }\n\n    (*testout) << \"get terminal \" << str << endl;\n    s1 = solids[str];\n    if (s1)\n      {\n\t//      cout << \"primitive: \" << str << endl;\n\treturn s1;\n      }\n    cerr << \"syntax error\" << endl;\n\n    return NULL;\n  }\n\n\n  Solid * Solid :: CreateSolid (istream & ist, const SymbolTable<Solid*> & solids)\n  {\n    Solid * nsol =  CreateSolidExpr (ist, solids);\n    nsol = new Solid (ROOT, nsol);\n    (*testout) << \"Print new sol: \";\n    nsol -> Print (*testout);\n    (*testout) << endl;\n    return nsol;\n  }\n\n\n\n  void Solid :: Boundaries (const Point<3> & p, NgArray<int> & bounds) const\n  {\n    int in, strin;\n    bounds.SetSize (0);\n    RecBoundaries (p, bounds, in, strin);\n  }\n\n  void Solid :: RecBoundaries (const Point<3> & p, NgArray<int> & bounds,\n\t\t\t       int & in, int & strin) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  /*\n\t    double val;\n\t    val = surf->CalcFunctionValue (p);\n\t    in = (val < 1e-6);\n\t    strin = (val < -1e-6);\n\t    if (in && !strin) bounds.Append (id);\n\t  */\n\t  if (prim->PointInSolid (p, 1e-6) == DOES_INTERSECT)\n\t    bounds.Append (prim->GetSurfaceId (1));\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  int i, in1, in2, strin1, strin2;\n\t  NgArray<int> bounds1, bounds2;\n\n\t  s1 -> RecBoundaries (p, bounds1, in1, strin1);\n\t  s2 -> RecBoundaries (p, bounds2, in2, strin2);\n\n\t  if (in1 && in2)\n\t    {\n\t      for (i = 1; i <= bounds1.Size(); i++)\n\t\tbounds.Append (bounds1.Get(i));\n\t      for (i = 1; i <= bounds2.Size(); i++)\n\t\tbounds.Append (bounds2.Get(i));\n\t    }\n\t  in = (in1 && in2);\n\t  strin = (strin1 && strin2);\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  int i, in1, in2, strin1, strin2;\n\t  NgArray<int> bounds1, bounds2;\n\n\t  s1 -> RecBoundaries (p, bounds1, in1, strin1);\n\t  s2 -> RecBoundaries (p, bounds2, in2, strin2);\n\n\t  if (!strin1 && !strin2)\n\t    {\n\t      for (i = 1; i <= bounds1.Size(); i++)\n\t\tbounds.Append (bounds1.Get(i));\n\t      for (i = 1; i <= bounds2.Size(); i++)\n\t\tbounds.Append (bounds2.Get(i));\n\t    }\n\t  in = (in1 || in2);\n\t  strin = (strin1 || strin2);\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  int hin, hstrin;\n\t  s1 -> RecBoundaries (p, bounds, hin, hstrin);\n\t  in = !hstrin;\n\t  strin = !hin;\n\t  break;\n\t}\n\n      case ROOT:\n\t{\n\t  s1 -> RecBoundaries (p, bounds, in, strin);\n\t  break;\n\t}\n      }\n  }\n\n\n  unique_ptr<Solid> Solid :: TangentialSolid (const Point<3> & p, NgArray<int> & surfids, double eps) const\n  {\n    bool in, strin;\n    Solid * tansol = nullptr;\n    RecTangentialSolid (p, tansol, surfids, in, strin, eps);\n    surfids.SetSize (0);\n    if (tansol)\n      tansol -> GetTangentialSurfaceIndices (p, surfids, eps);\n    return unique_ptr<Solid> (tansol);\n  }\n\n\n  void Solid :: RecTangentialSolid (const Point<3> & p, Solid *& tansol, NgArray<int> & surfids,\n\t\t\t\t    bool & in, bool & strin, double eps) const\n  {\n    tansol = NULL;\n\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->PointInSolid(p, eps);\n\n\t  in = (ist == IS_INSIDE || ist == DOES_INTERSECT);\n\t  strin = (ist == IS_INSIDE);\n\n\t  if (ist == DOES_INTERSECT)\n\t    {\n\t      tansol = new Solid (prim);\n\t      tansol -> op = TERM_REF;\n\t    }\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps);\n\n\t  if (in1 && in2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (SECTION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 && in2;\n\t  strin = strin1 && strin2;\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1 = 0, * tansol2 = 0;\n\n\t  s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps);\n\n\t  if (!strin1 && !strin2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (UNION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  else\n\t    {\n\t      delete tansol1;\n\t      delete tansol2;\n\t    }\n\t  in = in1 || in2;\n\t  strin = strin1 || strin2;\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  bool hin, hstrin;\n\t  Solid * tansol1;\n\n\t  s1 -> RecTangentialSolid (p, tansol1, surfids, hin, hstrin, eps);\n\n\t  if (tansol1)\n\t    tansol = new Solid (SUB, tansol1);\n\t  in = !hstrin;\n\t  strin = !hin;\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> RecTangentialSolid (p, tansol, surfids, in, strin, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n  unique_ptr<Solid> Solid :: TangentialSolid2 (const Point<3> & p, \n                                               const Vec<3> & t,\n                                               NgArray<int> & surfids, double eps) const\n  {\n    Solid * tansol = nullptr;\n    bool in, strin;\n    surfids.SetSize (0);\n    RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps);\n    if (tansol)\n      tansol -> GetTangentialSurfaceIndices2 (p, t, surfids, eps);\n    return unique_ptr<Solid> (tansol);\n  }\n\n  void Solid :: RecTangentialSolid2 (const Point<3> & p, const Vec<3> & t,\n\t\t\t\t     Solid *& tansol, NgArray<int> & surfids, \n\t\t\t\t     bool & in, bool & strin, double eps) const\n  {\n    tansol = nullptr;\n\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  /*\n\t    double val;\n\t    val = surf->CalcFunctionValue (p);\n\t    in = (val < 1e-6);\n\t    strin = (val < -1e-6);\n\t    if (in && !strin)\n\t    tansol = new Solid (surf, id);\n\t  */\n\n\t  INSOLID_TYPE ist = prim->PointInSolid(p, eps);\n\t  if (ist == DOES_INTERSECT)\n\t    ist = prim->VecInSolid (p, t, eps);\n\n\t  in = (ist == IS_INSIDE) || (ist == DOES_INTERSECT);\n\t  strin = ist == IS_INSIDE;\n\n\t  if (ist == DOES_INTERSECT)\n\t    {\n\t      tansol = new Solid (prim);\n\t      tansol -> op = TERM_REF;\n\t    }\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps);\n\n\t  if (in1 && in2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (SECTION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 && in2;\n\t  strin = strin1 && strin2;\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps);\n\n\t  if (!strin1 && !strin2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (UNION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 || in2;\n\t  strin = strin1 || strin2;\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  bool hin, hstrin;\n\t  Solid * tansol1;\n\n\t  s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, hin, hstrin, eps);\n\n\t  if (tansol1)\n\t    tansol = new Solid (SUB, tansol1);\n\t  in = !hstrin;\n\t  strin = !hin;\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n\n\n  unique_ptr<Solid> Solid :: TangentialSolid3 (const Point<3> & p, \n                                               const Vec<3> & t, const Vec<3> & t2,\n                                               NgArray<int> & surfids, \n                                               double eps) const\n  {\n    bool in, strin;\n    Solid * tansol = nullptr;\n    surfids.SetSize (0);\n    RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps);\n\n    if (tansol)\n      tansol -> GetTangentialSurfaceIndices3 (p, t, t2, surfids, eps);\n\n    return unique_ptr<Solid>(tansol);\n  }\n\n  void Solid :: RecTangentialSolid3 (const Point<3> & p, \n\t\t\t\t     const Vec<3> & t, const Vec<3> & t2,\n\t\t\t\t     Solid *& tansol, NgArray<int> & surfids, \n\t\t\t\t     bool & in, bool & strin, double eps) const\n  {\n    tansol = nullptr;\n\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->PointInSolid(p, eps);\n\n\t  if (ist == DOES_INTERSECT)\n\t    ist = prim->VecInSolid3 (p, t, t2, eps);\n\t  in = (ist == IS_INSIDE) || (ist == DOES_INTERSECT);\n\t  strin = ist == IS_INSIDE;\n\n\t  if (ist == DOES_INTERSECT)\n\t    {\n\t      tansol = new Solid (prim);\n\t      tansol -> op = TERM_REF;\n\t    }\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps);\n\n\t  if (in1 && in2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (SECTION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 && in2;\n\t  strin = strin1 && strin2;\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps);\n\n\t  if (!strin1 && !strin2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (UNION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 || in2;\n\t  strin = strin1 || strin2;\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  bool hin, hstrin;\n\t  Solid * tansol1;\n\n\t  s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, hin, hstrin, eps);\n\n\t  if (tansol1)\n\t    tansol = new Solid (SUB, tansol1);\n\t  in = !hstrin;\n\t  strin = !hin;\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n  unique_ptr<Solid> Solid :: TangentialEdgeSolid (const Point<3> & p, \n                                                  const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m, \n                                                  NgArray<int> & surfids, \n                                                  double eps) const\n  {\n    Solid * tansol = nullptr;\n    bool in, strin;\n    surfids.SetSize (0);\n\n    // *testout << \"tangentialedgesolid,sol = \" << (*this) << endl;\n    RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps);\n\n    if (tansol)\n      tansol -> RecGetTangentialEdgeSurfaceIndices (p, t, t2, m, surfids, eps);\n\n    return unique_ptr<Solid> (tansol);\n  }\n\n  void Solid :: RecTangentialEdgeSolid (const Point<3> & p, \n\t\t\t\t\tconst Vec<3> & t, const Vec<3> & t2, const Vec<3> & m,\n\t\t\t\t\tSolid *& tansol, NgArray<int> & surfids, \n\t\t\t\t\tbool & in, bool & strin, double eps) const\n  {\n    tansol = NULL;\n\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->PointInSolid(p, eps);\n\n\t  /*\n\t  (*testout) << \"tangedgesolid, p = \" << p << \", t = \" << t \n\t\t     << \" for prim \" << typeid (*prim).name() \n\t\t     << \" with surf \" << prim->GetSurface() << endl;\n\t  (*testout) << \"ist = \" << ist << endl;\n\t  */\n\n\t  if (ist == DOES_INTERSECT)\n\t    ist = prim->VecInSolid4 (p, t, t2, m, eps);\n\n\t  // (*testout) << \"ist2 = \" << ist << endl;\n\n\t  in = (ist == IS_INSIDE) || (ist == DOES_INTERSECT);\n\t  strin = ist == IS_INSIDE;\n\n\t  if (ist == DOES_INTERSECT)\n\t    {\n\t      tansol = new Solid (prim);\n\t      tansol -> op = TERM_REF;\n\t    }\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps);\n\n\t  if (in1 && in2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (SECTION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 && in2;\n\t  strin = strin1 && strin2;\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n\t  Solid * tansol1, * tansol2;\n\n\t  s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps);\n\t  s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps);\n\n\t  if (!strin1 && !strin2)\n\t    {\n\t      if (tansol1 && tansol2)\n\t\ttansol = new Solid (UNION, tansol1, tansol2);\n\t      else if (tansol1)\n\t\ttansol = tansol1;\n\t      else if (tansol2)\n\t\ttansol = tansol2;\n\t    }\n\t  in = in1 || in2;\n\t  strin = strin1 || strin2;\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  bool hin, hstrin;\n\t  Solid * tansol1;\n\n\t  s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, hin, hstrin, eps);\n\n\t  if (tansol1)\n\t    tansol = new Solid (SUB, tansol1);\n\t  in = !hstrin;\n\t  strin = !hin;\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  int Solid :: Edge (const Point<3> & p, const Vec<3> & v, double eps) const\n  {\n    bool in, strin;\n    int faces;\n    RecEdge (p, v, in, strin, faces, eps);\n    return faces >= 2;\n  }\n\n  int Solid :: OnFace (const Point<3> & p, const Vec<3> & v, double eps) const\n  {\n    bool in, strin;\n    int faces;\n    RecEdge (p, v, in, strin, faces, eps);\n    return faces >= 1;\n  }\n\n\n  void Solid :: RecEdge (const Point<3> & p, const Vec<3> & v,\n\t\t\t bool & in, bool & strin, int & faces, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);\n\t  in = (ist == IS_INSIDE) || (ist == DOES_INTERSECT);\n\t  strin = ist == IS_INSIDE;\n\t  /*\n\t    in = VectorIn (p, v);\n\t    strin = VectorStrictIn (p, v);\n\t  */\n\t  faces = 0;\n\n\t  if (in && ! strin)\n\t    {\n\t      //\t    faces = 1;\n\t      int i; \n\t      Vec<3> grad;\n\t      for (i = 0; i < prim->GetNSurfaces(); i++)\n\t\t{\n\t\t  double val = prim->GetSurface(i).CalcFunctionValue(p);\n\t\t  prim->GetSurface(i).CalcGradient (p, grad);\n\t\t  if (fabs (val) < eps && fabs (v * grad) < 1e-6)\n\t\t    faces++;\n\t\t}\n\t    }\n\t  //\telse\n\t  //\t  faces = 0;\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n          int faces1, faces2;\n\n\t  s1 -> RecEdge (p, v, in1, strin1, faces1, eps);\n\t  s2 -> RecEdge (p, v, in2, strin2, faces2, eps);\n\n\t  faces = 0;\n\t  if (in1 && in2)\n\t    faces = faces1 + faces2;\n\t  in = in1 && in2;\n\t  strin = strin1 && strin2;\n\t  break;\n\t}\n      case UNION:\n\t{\n\t  bool in1, in2, strin1, strin2;\n          int faces1, faces2;\n\n\t  s1 -> RecEdge (p, v, in1, strin1, faces1, eps);\n\t  s2 -> RecEdge (p, v, in2, strin2, faces2, eps);\n\n\t  faces = 0;\n\t  if (!strin1 && !strin2)\n\t    faces = faces1 + faces2;\n\t  in = in1 || in2;\n\t  strin = strin1 || strin2;\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  bool in1, strin1;\n\t  s1 -> RecEdge (p, v, in1, strin1, faces, eps);\n\t  in = !strin1;\n\t  strin = !in1;\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> RecEdge (p, v, in, strin, faces, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n  void Solid :: CalcSurfaceInverse ()\n  {\n    CalcSurfaceInverseRec (0);\n  }\n\n  void Solid :: CalcSurfaceInverseRec (int inv)\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  bool priminv;\n\t  for (int i = 0; i < prim->GetNSurfaces(); i++)\n\t    {\n\t      priminv = (prim->SurfaceInverted(i) != 0);\n\t      if (inv) priminv = !priminv;\n\t      prim->GetSurface(i).SetInverse (priminv);\n\t    }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> CalcSurfaceInverseRec (inv);\n\t  s2 -> CalcSurfaceInverseRec (inv);\n\t  break;\n\t}\n      case SUB:\n\t{\n\t  s1 -> CalcSurfaceInverseRec (1 - inv);\n\t  break;\n\t}\n      case ROOT:\n\t{\n\t  s1 -> CalcSurfaceInverseRec (inv);\n\t  break;\n\t}\n      }\n  }\n\n\n  Solid * Solid :: GetReducedSolid (const BoxSphere<3> & box) const\n  {\n    INSOLID_TYPE in;\n    return RecGetReducedSolid (box, in);\n  }\n\n  Solid * Solid :: RecGetReducedSolid (const BoxSphere<3> & box, INSOLID_TYPE & in) const\n  {\n    if (num_surfs <= 2)\n    {\n      // checking special case for degenerated plane - cylinder, Dec 2014\n      int cnt_plane = 0, cnt_cyl = 0;\n      bool inv_plane, inv_cyl;\n      Plane * plane;\n      Cylinder * cyl;\n\n      ForEachSurface ( [&] (Surface * surf, bool inv)\n                       {\n                         if (dynamic_cast<Plane*>(surf))\n                           {\n                             cnt_plane++;\n                             plane = dynamic_cast<Plane*>(surf);\n                             inv_plane = inv;\n                           }\n                         if (dynamic_cast<Cylinder*>(surf))\n                           {\n                             cnt_cyl++;\n                             cyl = dynamic_cast<Cylinder*>(surf);\n                             inv_cyl = inv;\n                           }\n                       });\n\n      if (cnt_plane == 1 && cnt_cyl == 1)\n        {\n          double scala = (cyl->A()-plane->P()) * plane->N();\n          double scalb = (cyl->B()-plane->P()) * plane->N();\n          double scal = plane->N() * plane->N();\n          if ( ( fabs (scala*scala - cyl->R()*cyl->R()*scal) < 1e-10*cyl->R()*cyl->R() ) &&\n               ( fabs (scalb*scalb - cyl->R()*cyl->R()*scal) < 1e-10*cyl->R()*cyl->R() ) )\n            {\n              // intersection edge in box ?\n              Point<3> p0 = cyl->A() - (scala/scal) * plane->N();\n              Vec<3> vedge = cyl->B() - cyl->A();\n              Vec<3> ve_center = box.Center()-p0;\n\n              // dist(lam) = \\| ve_center \\|^2 - 2 lam (vedge, ve_center) + lam^2 \\| vedge \\|^2\n\n              double num = vedge*ve_center;\n              double den = vedge*vedge;\n\n              double dist_edge_center2 = ve_center*ve_center  - num * num /den;\n              \n                \n              bool edge_in_box =  dist_edge_center2 < sqr (box.Diam());\n\n                \n              if (!edge_in_box)\n                {\n                  if (op == SECTION)\n                    {\n                      // cout << \"solid = \" << *this << endl;\n                      if (!inv_cyl && !inv_plane && scala < 0) \n                        {\n                          // cout << \"fix for degenerated cyl-plane edge: just the cylinder\" << endl;\n                          Solid * sol = new Solid (cyl);\n                          sol -> op = TERM_REF;\n                          return sol;\n                        }\n                    }\n\n                  if (op == UNION)\n                    {\n                      // cout << \"solid = \" << *this << \", inv_plane = \" << inv_plane << \" inv_cyl = \" << inv_cyl << \" scalb \" << scalb << endl;\n                      if (!inv_plane && !inv_cyl && (scala < 0))\n                        {\n                          // cout << \"fix for degenerated cyl-plane edge: just the plane\" << endl;\n                          // return new Solid (plane);\n                          Solid * sol = new Solid (plane);\n                          sol -> op = TERM_REF;\n                          return sol;\n                        }\n                    }\n                  ; // *testout << \"have 1 plane and 1 cyl, degenerated\" << endl;\n                }\n            }\n        }\n    }\n\n\n    Solid * redsol = NULL;\n\n    switch (op)\n      {\n      case TERM: \n      case TERM_REF:\n\t{\n\t  in = prim -> BoxInSolid (box);\n\t  if (in == DOES_INTERSECT)\n\t    {\n\t      redsol = new Solid (prim);\n\t      redsol -> op = TERM_REF;\n\t    }\n\t  break;\n\t}\n      case SECTION:\n\t{\n\t  INSOLID_TYPE in1, in2;\n\t  Solid * redsol1, * redsol2;\n\n\t  redsol1 = s1 -> RecGetReducedSolid (box, in1);\n\t  redsol2 = s2 -> RecGetReducedSolid (box, in2);\n\n\t  if (in1 == IS_OUTSIDE || in2 == IS_OUTSIDE)\n\t    {\n\t      if (in1 == DOES_INTERSECT) delete redsol1;\n\t      if (in2 == DOES_INTERSECT) delete redsol2;\n\t      in = IS_OUTSIDE;\n\t    }\n\t  else\n\t    {\n\t      if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT) \n\t\tin = DOES_INTERSECT;\n\t      else \n\t\tin = IS_INSIDE;\n\n\t      if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT)\n\t\tredsol = new Solid (SECTION, redsol1, redsol2);\n\t      else if (in1 == DOES_INTERSECT)\n\t\tredsol = redsol1;\n\t      else if (in2 == DOES_INTERSECT)\n\t\tredsol = redsol2;\n\t    }\n\t  break;\n\t}\n\n      case UNION:\n\t{\n\t  INSOLID_TYPE in1, in2;\n\t  Solid * redsol1, * redsol2;\n\n\t  redsol1 = s1 -> RecGetReducedSolid (box, in1);\n\t  redsol2 = s2 -> RecGetReducedSolid (box, in2);\n\n\t  if (in1 == IS_INSIDE || in2 == IS_INSIDE)\n\t    {\n\t      if (in1 == DOES_INTERSECT) delete redsol1;\n\t      if (in2 == DOES_INTERSECT) delete redsol2;\n\t      in = IS_INSIDE;\n\t    }\n\t  else\n\t    {\n\t      if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT) in = DOES_INTERSECT;\n\t      else in = IS_OUTSIDE;\n\n\t      if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT)\n\t\tredsol = new Solid (UNION, redsol1, redsol2);\n\t      else if (in1 == DOES_INTERSECT)\n\t\tredsol = redsol1;\n\t      else if (in2 == DOES_INTERSECT)\n\t\tredsol = redsol2;\n\t    }\n\t  break;\n\t}\n\n      case SUB:\n\t{\n\t  INSOLID_TYPE in1;\n\t  Solid * redsol1 = s1 -> RecGetReducedSolid (box, in1);\n\n\t  switch (in1)\n\t    {\n\t    case IS_OUTSIDE: in = IS_INSIDE; break;\n\t    case IS_INSIDE:  in = IS_OUTSIDE; break;\n\t    case DOES_INTERSECT: in = DOES_INTERSECT; break;\n\t    }\n\n\t  if (redsol1)\n\t    redsol = new Solid (SUB, redsol1);\n\t  break;\n\t}\n      \n      case ROOT:\n\t{\n\t  INSOLID_TYPE in1;\n\t  redsol = s1 -> RecGetReducedSolid (box, in1);\n\t  in = in1;\n\t  break;\n\t}\n      }\n\n    /*\n    if (redsol)\n      (*testout) << \"getrecsolid, redsol = \" << endl << (*redsol) << endl;\n    else\n      (*testout) << \"redsol is null\" << endl;\n    */\n\n    return redsol;\n  }\n\n\n  int Solid :: NumPrimitives () const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  return 1;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  return s1->NumPrimitives () + s2 -> NumPrimitives();\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  return s1->NumPrimitives ();\n\t}\n      }\n    return 0;\n  }\n\n  void Solid :: GetSurfaceIndices (NgArray<int> & surfind) const\n  {\n    surfind.SetSize (0);\n    RecGetSurfaceIndices (surfind);\n  }\n\n  void Solid :: RecGetSurfaceIndices (NgArray<int> & surfind) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  /*\n\t    int i;\n\t    for (i = 1; i <= surfind.Size(); i++)\n\t    if (surfind.Get(i) == prim->GetSurfaceId())\n\t    return;\n\t    surfind.Append (prim->GetSurfaceId());\n\t    break;\n\t  */\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    if (prim->SurfaceActive (j))\n\t      {\n\t\tbool found = 0;\n\t\tint siprim = prim->GetSurfaceId(j);\n\n\t\tfor (int i = 0; i < surfind.Size(); i++)\n\t\t  if (surfind[i] == siprim)\n\t\t    {\n\t\t      found = 1;\n\t\t      break;\n\t\t    }\n\t\tif (!found) surfind.Append (siprim);\n\t      }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetSurfaceIndices (surfind);\n\t  s2 -> RecGetSurfaceIndices (surfind);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetSurfaceIndices (surfind);\n\t  break;\n\t}\n      }\n  }\n  void Solid :: ForEachSurface (const std::function<void(Surface*,bool)> & lambda, bool inv) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    if (prim->SurfaceActive (j))\n              lambda (&prim->GetSurface(j), inv);\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> ForEachSurface (lambda, inv);\n\t  s2 -> ForEachSurface (lambda, inv);\n\t  break;\n\t}\n      case SUB:\n        {\n\t  s1 -> ForEachSurface (lambda, !inv);\n\t  break;\n        }\n      case ROOT:\n\t{\n\t  s1 -> ForEachSurface (lambda, inv);\n\t  break;\n\t}\n      }\n  }\n\n\n  void Solid :: GetTangentialSurfaceIndices (const Point<3> & p, NgArray<int> & surfind, double eps) const\n  {\n    surfind.SetSize (0);\n    RecGetTangentialSurfaceIndices (p, surfind, eps);\n  }\n\n  void Solid :: RecGetTangentialSurfaceIndices (const Point<3> & p, NgArray<int> & surfind, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  /*\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)\n\t      if (!surfind.Contains (prim->GetSurfaceId(j)))\n\t\tsurfind.Append (prim->GetSurfaceId(j));\n\t  */\n\t  prim->GetTangentialSurfaceIndices (p, surfind, eps);\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps);\n\t  s2 -> RecGetTangentialSurfaceIndices (p, surfind, eps);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n  void Solid :: GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v,\n\t\t\t\t\t     NgArray<int> & surfind, double eps) const\n  {\n    surfind.SetSize (0);\n    RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);\n  }\n\n  void Solid :: RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v,\n\t\t\t\t\t\t NgArray<int> & surfind, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    {\n\t      if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)\n\t\t{\n\t\t  Vec<3> grad;\n\t\t  prim->GetSurface(j).CalcGradient (p, grad);\n\t\t  if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2())\n\t\t    {\n\t\t      if (!surfind.Contains (prim->GetSurfaceId(j)))\n\t\t\tsurfind.Append (prim->GetSurfaceId(j));\n\t\t    }\n\t\t}\n\t    }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);\n\t  s2 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n\n\n  void Solid :: GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, \n\t\t\t\t\t     NgArray<int> & surfind, double eps) const\n  {\n    surfind.SetSize (0);\n    RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);\n  }\n\n  void Solid :: RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, \n\t\t\t\t\t\t NgArray<int> & surfind, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    {\n\t      if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)\n\t\t{\n\t\t  Vec<3> grad;\n\t\t  prim->GetSurface(j).CalcGradient (p, grad);\n\t\t  if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2())\n\t\t    {\n\t\t      Mat<3> hesse;\n\t\t      prim->GetSurface(j).CalcHesse (p, hesse);\n\t\t      double hv2 = v2 * grad + v * (hesse * v);\n\t\t      \n\t\t      if (fabs (hv2) < 1e-6) \n\t\t\t{\n\t\t\t  if (!surfind.Contains (prim->GetSurfaceId(j)))\n\t\t\t    surfind.Append (prim->GetSurfaceId(j));\n\t\t\t}\n\t\t      /*\n\t\t      else\n\t\t\t{\n\t\t\t  *testout << \"QUAD NOT OK\" << endl;\n\t\t\t  *testout << \"v = \" << v << \", v2 = \" << v2 << endl;\n\t\t\t  *testout << \"v * grad = \" << v*grad << endl;\n\t\t\t  *testout << \"v2 * grad = \" << v2*grad << endl;\n\t\t\t  *testout << \"v H v = \" << v*(hesse*v) << endl;\n\t\t\t  *testout << \"grad = \" << grad << endl;\n\t\t\t  *testout << \"hesse = \" << hesse << endl;\n\t\t\t  *testout << \"hv2 = \" << v2 * grad + v * (hesse * v) << endl;\n\t\t\t}\n\t\t      */\n\t\t    }\n\t\t}\n\t    }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);\n\t  s2 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n  void Solid :: RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m,\n\t\t\t\t\t\t    NgArray<int> & surfind, double eps) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  // *testout << \"check vecinsolid4, p = \" << p << \", v = \" << v << \"; m = \" << m << endl;\n\t  if (prim->VecInSolid4 (p, v, v2, m, eps) == DOES_INTERSECT)\n\t    {\n\t      prim->GetTangentialVecSurfaceIndices2 (p, v, m, surfind, eps);\n\t      /*\n\t      for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t\t{\n\t\t  if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)\n\t\t    {\n\t\t      Vec<3> grad;\n\t\t      prim->GetSurface(j).CalcGradient (p, grad);\n\t\t      *testout << \"grad = \" << grad << endl;\n\t\t      if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2()  && \n\t\t\t  sqr (grad * m) < 1e-6 * m.Length2() * grad.Length2() )   // new, 18032006 JS\n\t\t\t  \n\t\t\t{\n\t\t\t  *testout << \"add surf \" << prim->GetSurfaceId(j) << endl;\n\t\t\t  if (!surfind.Contains (prim->GetSurfaceId(j)))\n\t\t\t    surfind.Append (prim->GetSurfaceId(j));\n\t\t\t}\n\t\t    }\n\t\t}\n\t      */\n\t    }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);\n\t  s2 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);\n\t  break;\n\t}\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  void Solid :: GetSurfaceIndices (IndexSet & iset) const\n  {\n    iset.Clear();\n    RecGetSurfaceIndices (iset);\n  }\n\n  void Solid :: RecGetSurfaceIndices (IndexSet & iset) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  /*\n\t    int i;\n\t    for (i = 1; i <= surfind.Size(); i++)\n\t    if (surfind.Get(i) == prim->GetSurfaceId())\n\t    return;\n\t    surfind.Append (prim->GetSurfaceId());\n\t    break;\n\t  */\n\t  for (int j = 0; j < prim->GetNSurfaces(); j++)\n\t    if (prim->SurfaceActive (j))\n\t      {\n\t\tint siprim = prim->GetSurfaceId(j);\n\t\tiset.Add (siprim);\n\t      }\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecGetSurfaceIndices (iset);\n\t  s2 -> RecGetSurfaceIndices (iset);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecGetSurfaceIndices (iset);\n\t  break;\n\t}\n      }\n  }\n\n\n  void Solid :: CalcOnePrimitiveSpecialPoints (const Box<3> & box, NgArray<Point<3> > & pts) const\n  {\n    double eps = 1e-8 * box.Diam ();\n\n    pts.SetSize (0);\n    this -> RecCalcOnePrimitiveSpecialPoints (pts);\n    for (int i = pts.Size()-1; i >= 0; i--)\n      {\n\tif (!IsIn (pts[i],eps) || IsStrictIn (pts[i],eps))\n\t  pts.Delete (i);\n      }\n  }\n\n  void Solid :: RecCalcOnePrimitiveSpecialPoints (NgArray<Point<3> > & pts) const\n  {\n    switch (op)\n      {\n      case TERM: case TERM_REF:\n\t{\n\t  prim -> CalcSpecialPoints (pts);\n\t  break;\n\t}\n      case UNION:\n      case SECTION:\n\t{\n\t  s1 -> RecCalcOnePrimitiveSpecialPoints (pts);\n\t  s2 -> RecCalcOnePrimitiveSpecialPoints (pts);\n\t  break;\n\t}\n      case SUB:\n      case ROOT:\n\t{\n\t  s1 -> RecCalcOnePrimitiveSpecialPoints (pts);\n\t  break;\n\t}\n      } \n  }\n\n\n\n\n  // BlockAllocator Solid :: ball(sizeof (Solid));\n  shared_ptr<BlockAllocator> Solid :: ball = make_shared<BlockAllocator>(sizeof (Solid));\n}\n"
  },
  {
    "path": "libsrc/csg/solid.hpp",
    "content": "#ifndef FILE_SOLID\n#define FILE_SOLID\n\n/**************************************************************************/\n/* File:   solid.hh                                                       */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   1. Dez. 95                                                     */\n/**************************************************************************/\n\n#include <functional>\n\nnamespace netgen \n{\n\n  \n  /*\n    \n  Constructive Solid Model (csg)\n  \n  */\n  \n\n\n\n  class Solid;\n  \n  class SolidIterator\n  {\n  public:\n    SolidIterator () { ; }\n    virtual ~SolidIterator () { ; }\n    virtual void Do (Solid * sol) = 0;\n  };\n\n\n  inline INSOLID_TYPE Intersection (INSOLID_TYPE ina, INSOLID_TYPE inb)\n  {\n    if (ina == IS_INSIDE && inb == IS_INSIDE) return IS_INSIDE;\n    if (ina == IS_OUTSIDE || inb == IS_OUTSIDE) return IS_OUTSIDE;\n    return DOES_INTERSECT;\n  }\n  \n  inline INSOLID_TYPE Union (INSOLID_TYPE ina, INSOLID_TYPE inb)\n  {\n    if (ina == IS_INSIDE || inb == IS_INSIDE) return IS_INSIDE;\n    if (ina == IS_OUTSIDE && inb == IS_OUTSIDE) return IS_OUTSIDE;\n    return DOES_INTERSECT;\n  }\n\n  inline INSOLID_TYPE Complement (INSOLID_TYPE in)\n  {\n    if (in == IS_INSIDE) return IS_OUTSIDE;\n    if (in == IS_OUTSIDE) return IS_INSIDE;\n    return DOES_INTERSECT;\n  }\n\n  class Solid\n  {\n  public:\n  \n    typedef enum optyp1 { TERM, TERM_REF, SECTION, UNION, SUB, ROOT /*, DUMMY */ } optyp;\n  \n  private:\n    char * name;\n    Primitive * prim;\n    Solid * s1, * s2;\n  \n    optyp op;\n    bool visited;\n    double maxh;\n    int num_surfs;\n\n    // static int cntnames;\n\n  public:\n    Solid (Primitive * aprim);\n    Solid (optyp aop, Solid * as1, Solid * as2 = NULL);\n    // default constructor for archive\n    Solid () {}\n    ~Solid ();\n\n    void DoArchive(Archive& archive)\n    {\n      archive & name & prim & s1 & s2 & visited & maxh & num_surfs;\n      if(archive.Output())\n        archive << int(op);\n      else\n        {\n          int iop;\n          archive & iop;\n          op = optyp(iop);\n        }\n    }\n    const char * Name () const { return name; }\n    void SetName (const char * aname);\n\n    Solid * Copy (class CSGeometry & geom) const;\n    void Transform (Transformation<3> & trans);\n\n  \n    void IterateSolid (SolidIterator & it, bool only_once = 0);\n\n  \n    void Boundaries (const Point<3> & p, NgArray<int> & bounds) const;\n    int NumPrimitives () const;\n    void GetSurfaceIndices (NgArray<int> & surfind) const;\n    void GetSurfaceIndices (IndexSet & iset) const;\n\n    void GetTangentialSurfaceIndices (const Point<3> & p, NgArray<int> & surfids, double eps) const;\n    void GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, NgArray<int> & surfids, double eps) const;\n    void GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, NgArray<int> & surfids, double eps) const;\n\n    void ForEachSurface (const std::function<void(Surface*,bool)> & lambda, bool inv = false) const;\n\n    Primitive * GetPrimitive ()\n    { return (op == TERM || op == TERM_REF) ? prim : NULL; }\n    const Primitive * GetPrimitive () const\n    { return (op == TERM || op == TERM_REF) ? prim : NULL; }\n\n    Solid * S1() { return s1; }\n    Solid * S2() { return s2; }\n\n    // geometric tests\n\n    INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const;\n    INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const;\n\n    // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n    INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1,\n                              const Vec<3> & v2, double eps) const;\n\n    \n    bool IsIn (const Point<3> & p, double eps = 1e-6) const;\n    bool IsStrictIn (const Point<3> & p, double eps = 1e-6) const;\n    bool VectorIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const;\n    bool VectorStrictIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const;\n  \n    bool VectorIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t    double eps) const;\n    /*\n    bool VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t       double eps) const;\n    */\n    bool VectorStrictIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n                          double eps) const;\n\n    /// compute localization in point p\n    unique_ptr<Solid> TangentialSolid (const Point<3> & p, NgArray<int> & surfids, double eps) const;\n\n    /// compute localization in point p tangential to vector t\n    unique_ptr<Solid> TangentialSolid2 (const Point<3> & p, const Vec<3> & t,\n                                        NgArray<int> & surfids, double eps) const;\n\n    /** compute localization in point p, with second order approximation to edge\n\tp + s t + s*s/2 t2 **/\n    unique_ptr<Solid> TangentialSolid3 (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, \n                                        NgArray<int> & surfids, double eps) const;\n\n\n\n    /** tangential solid, which follows the edge\n\tp + s t + s*s/2 t2\n\twith second order, and the neighbouring face\n\tp + s t + s*s/2 t2 + r m\n\twith first order\n    **/\n    unique_ptr<Solid> TangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, \n                                           const Vec<3> & m, \n                                           NgArray<int> & surfids, double eps) const;\n\n\n    void CalcOnePrimitiveSpecialPoints (const Box<3> & box, NgArray<Point<3> > & pts) const;\n\n    ///\n    int Edge (const Point<3> & p, const Vec<3> & v, double eps) const;\n    ///\n    int OnFace (const Point<3> & p, const Vec<3> & v, double eps) const;\n    ///\n    void Print (ostream & str) const;\n    ///\n    void CalcSurfaceInverse ();\n    ///\n    Solid * GetReducedSolid (const BoxSphere<3> & box) const;\n  \n\n    void SetMaxH (double amaxh)\n    { maxh = amaxh; }\n    double GetMaxH () const\n    { return maxh; }\n\n    void GetSolidData (ostream & ost, int first = 1) const;\n    static Solid * CreateSolid (istream & ist, const SymbolTable<Solid*> & solids);\n\n\n    static shared_ptr<BlockAllocator> ball;\n    void * operator new(size_t /* s */) \n    {\n      return ball->Alloc();\n    }\n\n    void operator delete (void * p)\n    {\n      ball->Free (p);\n    }\n\n\n  protected:\n    ///\n\n    void RecBoundaries (const Point<3> & p, NgArray<int> & bounds, \n\t\t\tint & in, int & strin) const;\n    ///\n    void RecTangentialSolid (const Point<3> & p, Solid *& tansol, NgArray<int> & surfids, \n                             bool & in, bool & strin, double eps) const;\n\n    void RecTangentialSolid2 (const Point<3> & p, const Vec<3> & vec, \n\t\t\t      Solid *& tansol, NgArray<int> & surfids, \n\t\t\t      bool & in, bool & strin, double eps) const;\n    ///\n    void RecTangentialSolid3 (const Point<3> & p, const Vec<3> & vec,const Vec<3> & vec2, \n\t\t\t      Solid *& tansol, NgArray<int> & surfids, \n\t\t\t      bool & in, bool & strin, double eps) const;\n    ///\n    void RecTangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, \n\t\t\t\t const Vec<3> & m, \n\t\t\t\t Solid *& tansol, NgArray<int> & surfids, \n\t\t\t\t bool & in, bool & strin, double eps) const;\n\n    ///\n    void RecEdge (const Point<3> & p, const Vec<3> & v,\n\t\t  bool & in, bool & strin, int & faces, double eps) const;\n    ///\n    void CalcSurfaceInverseRec (int inv);\n    ///\n    Solid * RecGetReducedSolid (const BoxSphere<3> & box, INSOLID_TYPE & in) const;\n    ///\n    void RecGetSurfaceIndices (NgArray<int> & surfind) const;\n    void RecGetTangentialSurfaceIndices (const Point<3> & p, NgArray<int> & surfids, double eps) const;\n    void RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, NgArray<int> & surfids, double eps) const;\n    void RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, \n\t\t\t\t\t  NgArray<int> & surfids, double eps) const;\n    void RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m,\n\t\t\t\t\t     NgArray<int> & surfids, double eps) const;\n    void RecGetSurfaceIndices (IndexSet & iset) const;\n\n    void RecCalcOnePrimitiveSpecialPoints (NgArray<Point<3> > & pts) const;\n\n    friend class SolidIterator;\n    friend class ClearVisitedIt;\n    friend class RemoveDummyIterator;\n    friend class CSGeometry;\n  };\n\n\n  inline ostream & operator<< (ostream & ost, const Solid & sol)\n  {\n    sol.Print (ost);\n    return ost;\n  }\n\n\n\n\n\n\n  class ReducePrimitiveIterator : public SolidIterator\n  {\n    BoxSphere<3> box;\n  public:\n    ReducePrimitiveIterator (const BoxSphere<3> & abox)\n      : SolidIterator(), box(abox) { ; }\n    virtual ~ReducePrimitiveIterator () { ; }\n    virtual void Do (Solid * sol)\n    {\n      if (sol -> GetPrimitive())\n\tsol -> GetPrimitive() -> Reduce (box);\n    }\n  };\n\n\n  class UnReducePrimitiveIterator : public SolidIterator\n  {\n  public:\n    UnReducePrimitiveIterator () { ; }\n    virtual ~UnReducePrimitiveIterator () { ; }\n    virtual void Do (Solid * sol)\n    {\n      if (sol -> GetPrimitive())\n\tsol -> GetPrimitive() -> UnReduce ();\n    }\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/specpoin.cpp",
    "content": "#include <mystdlib.h>\n#include <meshing.hpp>\n#include <csg.hpp>\n\n\n/*\n  Special Point calculation uses the global Flags:\n\n  relydegtest       when to rely on degeneration ?\n  calccp            calculate points of intersection ?\n  cpeps1            eps for degenerated poi\n  calcep            calculate points of extreme coordinates ?\n  epeps1            eps for degenerated edge\n  epeps2            eps for axis parallel pec\n  epspointdist      eps for distance of special points \n*/\n\n\n// #define DEVELOP\n\n\nnamespace netgen\n{\n  DLL_HEADER NgArray<Box<3> > boxes; // for visualization\n\n\n  void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp);\n\n  enum { check_crosspoint = 5 };\n\n  SpecialPoint :: SpecialPoint (const SpecialPoint & sp)\n  {\n    p = sp.p;\n    v = sp.v;\n    s1 = sp.s1;\n    s2 = sp.s2;\n    s1_orig = sp.s1_orig;\n    s2_orig = sp.s2_orig;\n    layer = sp.layer;\n    unconditional = sp.unconditional;\n  }\n  \n  SpecialPoint & SpecialPoint :: operator= (const SpecialPoint & sp)\n  {\n    p = sp.p;\n    v = sp.v;\n    s1 = sp.s1;\n    s2 = sp.s2;\n    s1_orig = sp.s1_orig;\n    s2_orig = sp.s2_orig;\n    layer = sp.layer;\n    unconditional = sp.unconditional;\n    return *this;\n  }\n\n\n  void SpecialPoint :: Print (ostream & str) const\n  {\n    str << \"p = \" << p << \"   v = \" << v \n\t<< \" s1/s2 = \" << s1 << \"/\" << s2;\n    str << \" layer = \" << layer\n\t<< \" unconditional = \" << unconditional\n\t<< endl;\n  }\n\n\n  // static NgArray<int> numprim_hist;\n\n  SpecialPointCalculation :: SpecialPointCalculation ()\n  {\n    ideps = 1e-9;\n  }\n\n  void SpecialPointCalculation :: \n  CalcSpecialPoints (const CSGeometry & ageometry, \n\t\t     NgArray<MeshPoint> & apoints)\n  {\n    // static int timer = NgProfiler::CreateTimer (\"CSG: find special points\");\n    // NgProfiler::RegionTimer reg (timer);\n\n\n    geometry = &ageometry;\n    points = &apoints;\n\n    size = geometry->MaxSize();\n    (*testout) << \"Find Special Points\" << endl;\n    (*testout) << \"maxsize = \" << size << endl;\n\n    cpeps1 = 1e-6; \n    epeps1 = 1e-3; \n    epeps2 = 1e-6; \n\n    epspointdist2 = sqr (size * 1e-8); \n    relydegtest = size * 1e-4; \n\n\n    BoxSphere<3> box (Point<3> (-size, -size, -size),\n\t\t      Point<3> ( size,  size,  size));\n\n    box.CalcDiamCenter();\n    PrintMessage (3, \"main-solids: \", geometry->GetNTopLevelObjects());\n\n    // numprim_hist.SetSize (geometry->GetNSurf()+1);\n    // numprim_hist = 0;\n\n    for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)\n      {\n\tconst TopLevelObject * tlo = geometry->GetTopLevelObject(i);\n\n\t(*testout) << \"tlo \" << i << \":\" << endl\n\t\t   << *tlo->GetSolid() << endl;\n\n\tif (tlo->GetSolid())\n\t  {\n\t    NgArray<Point<3> > hpts;\n\t    tlo->GetSolid()->CalcOnePrimitiveSpecialPoints (box, hpts);\n            // if (hpts.Size())\n            //  cout << \"oneprimitivespecialpoints = \" << hpts << endl;\n\t    for (int j = 0; j < hpts.Size(); j++)\n\t      AddPoint (hpts[j], tlo->GetLayer());\n\t  }\n\n\tCalcSpecialPointsRec (tlo->GetSolid(), tlo->GetLayer(),\n\t\t\t      box, 1, 1, 1);\n      }\n \n  \n    geometry->DeleteIdentPoints();\n    for (int i = 0; i < geometry->GetNIdentifications(); i++)\n      {\n\tCloseSurfaceIdentification * ident =\n\t  dynamic_cast<CloseSurfaceIdentification * >(geometry->identifications[i]);\n\t\n\tif(!ident || !ident->IsSkewIdentification())\n\t  continue;\n\n\tfor(int j=0; j<points->Size(); j++)\n\t  {\n\t    if(fabs(ident->GetSurface1().CalcFunctionValue((*points)[j])) < 1e-15)\n\t      {\n\t\tPoint<3> auxpoint = (*points)[j];\n\t\tident->GetSurface2().SkewProject(auxpoint,ident->GetDirection());\n\t\tgeometry->AddIdentPoint(auxpoint);\n\t\tgeometry->AddIdentPoint((*points)[j]);\n\t\tAddPoint (auxpoint,1);\n\n#ifdef DEVELOP\n\t\t(*testout) << \"added identpoint \" << auxpoint << \"; proj. of \"\n\t\t\t   <<  (*points)[j] << endl;\n#endif\n\t\tbreak;\n\t      }\n\t  }\n      }\n    \n\n    // add user point:\n    for (int i = 0; i < geometry->GetNUserPoints(); i++)\n      AddPoint (geometry->GetUserPoint(i), 1);\n\t\n\n    PrintMessage (3, \"Found points \", apoints.Size());\n\n    /*\n    for (int i = 0; i < boxesinlevel.Size(); i++)\n      (*testout) << \"level \" << i << \" has \" \n\t\t << boxesinlevel[i] << \" boxes\" << endl;\n    (*testout) << \"numprim_histogramm = \" << endl << numprim_hist << endl;\n    */\n  }\n  \n\n\n  void SpecialPointCalculation :: \n  CalcSpecialPointsRec (const Solid * sol, int layer,\n\t\t\tconst BoxSphere<3> & box, \n\t\t\tint level, bool calccp, bool calcep)\n  {\n    // boxes.Append (box);\n\n#ifdef DEVELOP\n    *testout << \"lev \" << level << \", box = \" << box << endl;\n    *testout << \"calccp = \" << calccp << \", calcep = \" << calcep << endl;\n    *testout << \"locsol = \" << *sol << endl;\n#endif\n\n    if (multithread.terminate)\n      {\n\t// *testout << \"boxes = \" << boxes << endl;\n\t// *testout << \"boxesinlevel = \" << boxesinlevel << endl;\n\tthrow NgException (\"Meshing stopped\");\n      }\n\n\n    if (!sol) return;\n\n    if (level >= 100)\n      {\n\tMyStr err =\n\t  MyStr(\"Problems in CalcSpecialPoints\\nPoint: \") + MyStr (box.Center());\n\tthrow NgException (err.c_str());\n      }\n\n    if (level == 40 || level == 41 || level == 45)\n      {\n        *testout << \"level = \" << level << \" cp = \" << calccp << \" ep = \" << calcep << \", box = \" << box << \", solid = \" << *sol << endl;\n      }\n\n\n\n    bool decision;\n    bool possiblecrossp, possibleexp;  // possible cross or extremalpoint\n    bool surecrossp = 0, sureexp = 0;          // sure ...\n  \n    // static NgArray<int> locsurf;  // attention: array is static\n    NgArrayMem<int,100> locsurf; \n\n    // static int cntbox = 0;\n    // cntbox++;\n    /*\n    if (level <= boxesinlevel.Size())\n      boxesinlevel.Elem(level)++;\n    else\n      boxesinlevel.Append (1);\n    */\n    \n    /*\n      numprim = sol -> NumPrimitives();\n      sol -> GetSurfaceIndices (locsurf);\n    */\n\n    geometry -> GetIndependentSurfaceIndices (sol, box, locsurf);\n    int numprim = locsurf.Size();\n\n#ifdef DEVELOP\n    (*testout) << \"numprim = \" << numprim << endl;\n#endif\n\n    // numprim_hist[numprim]++;\n\n    Point<3> p = box.Center();\n\n\n    // explicit solution for planes only and at most one quadratic\n    if (numprim <= check_crosspoint)\n      {\n\tint nplane = 0, nquad = 0, quadi = -1, nsphere = 0;\n\tconst QuadraticSurface *qsurf = 0, *qsurfi;\n\n\tfor (int i = 0; i < numprim; i++)\n\t  {\n\t    qsurfi = dynamic_cast<const QuadraticSurface*> \n\t      (geometry->GetSurface(locsurf[i]));\n\n\t    if (qsurfi) nquad++;\n\t    if (dynamic_cast<const Plane*> (qsurfi))\n\t      nplane++;\n\t    else\n\t      {\n\t\tquadi = i;\n\t\tqsurf = qsurfi;\n\t      }\n\n\t    if (dynamic_cast<const Sphere*> (qsurfi))\n\t      nsphere++;\n\t  }\n\n\t/*\n\tif (nquad == numprim && nplane == numprim-2)\n\t  return;\n\t*/\n\n#ifdef DEVELOP\n\t(*testout) << \"nquad \" << nquad << \" nplane \" << nplane << endl;\n#endif\n\n\tif (nquad == numprim && nplane >= numprim-1)\n\t  {\n\t    NgArray<Point<3> > pts;\n\t    NgArray<int> surfids;\n\n\t    for (int k1 = 0; k1 < numprim - 2; k1++)\n\t      for (int k2 = k1 + 1; k2 < numprim - 1; k2++)\n\t\tfor (int k3 = k2 + 1; k3 < numprim; k3++)\n\t\t  if (k1 != quadi && k2 != quadi && k3 != quadi)\n\t\t    {\n\t\t      ComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),\n\t\t\t\t\t  dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),\n\t\t\t\t\t  dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k3])),\n\t\t\t\t\t  pts);\n\n                      for (auto pnt : pts)\n                        if (Dist (pnt, box.Center()) < box.Diam()/2)                        \n\t\t\t  {\n\t\t\t    auto tansol = sol -> TangentialSolid (pnt, surfids, 1e-9*size);\n                            if (tansol)\n                              {\n                                bool ok1 = false, ok2 = false, ok3 = false;\n                                int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);\n                                int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);\n                                int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]);\n                                \n                                for (auto surfid : surfids)\n                                  {\n                                    int actrep = geometry->GetSurfaceClassRepresentant(surfid);\n                                    if (actrep == rep1) ok1 = true;\n                                    if (actrep == rep2) ok2 = true;\n                                    if (actrep == rep3) ok3 = true;\t\t\t\t  \n                                  }\n                                \n                                if (ok1 && ok2 && ok3)\n                                  if (AddPoint (pnt, layer))\n                                    (*testout) << \"cross point found, 1: \" << pnt << endl;\n                              }\n                          }\n\t\t    }\n\n\n\t    if (qsurf)\n\t      {\n\t\tfor (int k1 = 0; k1 < numprim - 1; k1++)\n\t\t  for (int k2 = k1 + 1; k2 < numprim; k2++)\n\t\t    if (k1 != quadi && k2 != quadi)\n\t\t      {\n\t\t\tComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),\n\t\t\t\t\t    dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),\n\t\t\t\t\t    qsurf, pts);\n\t\t\t//(*testout) << \"checking pot. crosspoints: \" << pts << endl;\n\n                        for (auto pnt : pts)\n                          if (Dist (pnt, box.Center()) < box.Diam()/2)\n\t\t\t    {\n\t\t\t      auto tansol = sol -> TangentialSolid (pnt, surfids, 1e-9*size);\n                              if (tansol)\n                                {\n                                  bool ok1 = false, ok2 = false, ok3 = true;//false;\n                                  int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);\n                                  int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);\n                                  \n                                  for (auto surfid : surfids)\n                                    {\n                                      int actrep = geometry->GetSurfaceClassRepresentant(surfid);\n                                      if (actrep == rep1) ok1 = true;\n                                      if (actrep == rep2) ok2 = true;\n                                    }\n                                  \n                                  if (ok1 && ok2 && ok3)\n                                    if (AddPoint (pnt, layer))\n                                      (*testout) << \"cross point found, 2: \" << pnt << endl;\n                                }\n\t\t\t    }\n\t\t      }\n\n\t\tfor (int k1 = 0; k1 < numprim; k1++)\n\t\t  if (k1 != quadi)\n\t\t    {\n\t\t      ComputeExtremalPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),\n\t\t\t\t\t     qsurf, pts);\n\t\t      \n\t\t      for (int j = 0; j < pts.Size(); j++)\n\t\t\tif (Dist (pts[j], box.Center()) < box.Diam()/2)\n\t\t\t  {\n\t\t\t    auto tansol = sol -> TangentialSolid (pts[j], surfids, 1e-9*size);\n\t\t\t    if (tansol)\n                              if (AddPoint (pts[j], layer))\n                                (*testout) << \"extremal point found, 1: \" << pts[j] << endl;\n\t\t\t  }\n\t\t    }\n\t      }\n\t    \n\t    return;\n\t  }\n\n\n\n\tif (nsphere == numprim) //  && calccp == false)\n\t  {\n\t    NgArray<Point<3> > pts;\n\t    NgArray<int> surfids;\n\n\t    for (int k1 = 0; k1 < numprim; k1++)\n\t      for (int k2 = 0; k2 < k1; k2++)\n\t\tfor (int k3 = 0; k3 < k2; k3++)\n\t\t  {\n\t\t    ComputeCrossPoints (dynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k1])),\n\t\t\t\t\tdynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k2])),\n\t\t\t\t\tdynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k3])),\n\t\t\t\t\tpts);\n\t\t    \n\t\t    for (int j = 0; j < pts.Size(); j++)\n\t\t      if (Dist (pts[j], box.Center()) < box.Diam()/2)\n\t\t\t{\n\t\t\t  auto tansol = sol -> TangentialSolid (pts[j], surfids, 1e-9*size);\n\t\t\t  if (!tansol) continue;\n\t\t\t  \n\t\t\t  bool ok1 = false, ok2 = false, ok3 = false;\n\t\t\t  int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);\n\t\t\t  int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);\n\t\t\t  int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]);\n                          \n\t\t\t  for(int jj=0; jj<surfids.Size(); jj++)\n\t\t\t    {\n\t\t\t      int actrep = geometry->GetSurfaceClassRepresentant(surfids[jj]);\n\t\t\t      if(actrep == rep1) ok1 = true;\n\t\t\t      if(actrep == rep2) ok2 = true;\n\t\t\t      if(actrep == rep3) ok3 = true;\t\t\t\t  \n\t\t\t    }\n\t\t\t  \n\t\t\t  if (ok1 && ok2 && ok3)\n                            if (AddPoint (pts[j], layer))\n                              (*testout) << \"cross point found, 1: \" << pts[j] << endl;\n\t\t\t}\n\t\t  }\n\t    \n\n\t    for (int k1 = 0; k1 < numprim; k1++)\n\t      for (int k2 = 0; k2 < k1; k2++)\n\t\t{\n\t\t  ComputeExtremalPoints (dynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k1])),\n\t\t\t\t\t dynamic_cast<const Sphere*> (geometry->GetSurface(locsurf[k2])),\n\t\t\t\t\t pts);\n\t\t  \n\t\t  for (int j = 0; j < pts.Size(); j++)\n\t\t    if (Dist (pts[j], box.Center()) < box.Diam()/2)\n\t\t      {\n\t\t\tauto tansol = sol -> TangentialSolid (pts[j], surfids, 1e-9*size);\n\t\t\tif (tansol)\n                          if (AddPoint (pts[j], layer))\n                            (*testout) << \"extremal point found, spheres: \" << pts[j] << endl;\n\t\t      }\n\t\t}\n\t    \n\t    return;\n\t  }\n\n\n        if (numprim == 2)\n          {\n            auto rev0 = dynamic_cast<const RevolutionFace*> (geometry->GetSurface(locsurf[0]));\n            auto rev1 = dynamic_cast<const RevolutionFace*> (geometry->GetSurface(locsurf[1]));\n            if (rev0 && rev1)\n              {\n                NgArray<Point<3>> pts;\n                bool check = ComputeExtremalPoints (rev0, rev1, pts);\n                if (check)\n                  {\n                    for (auto p : pts)\n                      if (box.IsIn(p))\n                        AddPoint (p, layer);\n                    return;\n                  }\n              }\n          }\n      } // end if (numprim <= check_crosspoint)\n    \n\n    \n    possiblecrossp = (numprim >= 3) && calccp;\n    surecrossp = 0;\n\n    if (possiblecrossp && (locsurf.Size() <= check_crosspoint || level > 50))\n      {\n\tdecision = 1;\n\tsurecrossp = 0;\n\n\tfor (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)\n\t  for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)\n\t    for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)\n\t      {\n\t\tint nc, deg;\n\t\tnc = CrossPointNewtonConvergence \n\t\t  (geometry->GetSurface(locsurf.Get(k1)), \n\t\t   geometry->GetSurface(locsurf.Get(k2)), \n\t\t   geometry->GetSurface(locsurf.Get(k3)), box );\n\t      \n\t\tdeg = CrossPointDegenerated \n\t\t  (geometry->GetSurface(locsurf.Get(k1)), \n\t\t   geometry->GetSurface(locsurf.Get(k2)), \n\t\t   geometry->GetSurface(locsurf.Get(k3)), box );\n\t      \n#ifdef DEVELOP\n\t\t(*testout) << \"k1,2,3 = \" << k1 << \",\" << k2 << \",\" << k3 << \", nc = \" << nc << \", deg = \" << deg << endl;\n#endif\n\n\t\tif (!nc && !deg) decision = 0;\n\t\tif (nc) surecrossp = 1;\n\t      }\n\n#ifdef DEVELOP\n        (*testout) << \"dec = \" << decision << \", surcp = \" << surecrossp << endl;\n#endif\n\n\tif (decision && surecrossp)\n\t  {\n\t    for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)\n\t      for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)\n\t\tfor (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)\n\t\t  {\n\t\t    if (CrossPointNewtonConvergence \n\t\t\t(geometry->GetSurface(locsurf.Get(k1)), \n\t\t\t geometry->GetSurface(locsurf.Get(k2)), \n\t\t\t geometry->GetSurface(locsurf.Get(k3)), box ) )\n\t\t      {\n                        \n\t\t\tPoint<3> pp = p;\n\t\t\tCrossPointNewton \n\t\t\t  (geometry->GetSurface(locsurf.Get(k1)), \n\t\t\t   geometry->GetSurface(locsurf.Get(k2)), \n\t\t\t   geometry->GetSurface(locsurf.Get(k3)), pp);\n              \n\t\t\tBoxSphere<3> hbox (pp, pp);\n\t\t\thbox.Increase (1e-8*size);\n\n\t\t\tif (pp(0) > box.PMin()(0) - 1e-5*size && \n\t\t\t    pp(0) < box.PMax()(0) + 1e-5*size &&\n\t\t\t    pp(1) > box.PMin()(1) - 1e-5*size && \n\t\t\t    pp(1) < box.PMax()(1) + 1e-5*size &&\n\t\t\t    pp(2) > box.PMin()(2) - 1e-5*size && \n\t\t\t    pp(2) < box.PMax()(2) + 1e-5*size &&\n\t\t\t    sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) &&\n\t\t\t    !CrossPointDegenerated\n\t\t\t    (geometry->GetSurface(locsurf.Get(k1)), \n\t\t\t     geometry->GetSurface(locsurf.Get(k2)), \n\t\t\t     geometry->GetSurface(locsurf.Get(k3)), hbox ))\n\n\t\t\t  { \n\t\t\t    //                AddCrossPoint (locsurf, sol, p);\n\t\t\t    BoxSphere<3> boxp (pp, pp);\n\t\t\t    boxp.Increase (1e-3*size);\n\t\t\t    boxp.CalcDiamCenter();\n\t\t\t    NgArray<int> locsurf2;\n\n\t\t\t    geometry -> GetIndependentSurfaceIndices (sol, boxp, locsurf2);\n\t\t\t  \n\t\t\t    bool found1 = false, found2 = false, found3 = false;\n\t\t\t    for (int i = 0; i < locsurf2.Size(); i++)\n\t\t\t      {\n\t\t\t\tif (locsurf2[i] == locsurf.Get(k1)) found1 = true;\n\t\t\t\tif (locsurf2[i] == locsurf.Get(k2)) found2 = true;\n\t\t\t\tif (locsurf2[i] == locsurf.Get(k3)) found3 = true;\n\t\t\t      }\n\n\t\t\t    if (found1 && found2 && found3)\n\t\t\t      if (AddPoint (pp, layer))\n\t\t\t\t{\n\t\t\t\t  (*testout) << \"Crosspoint found: \" << pp \n\t\t\t\t\t     << \" diam = \" << box.Diam()\n\t\t\t\t\t     << \",  surfs: \" \n\t\t\t\t\t     << locsurf.Get(k1) << \",\" \n\t\t\t\t\t     << locsurf.Get(k2) << \",\" \n\t\t\t\t\t     << locsurf.Get(k3) << endl;\n\t\t\t\t}\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t  }\n      \n\tif (decision)\n\t  possiblecrossp = 0;\n      }\n\n\n    possibleexp = (numprim >= 2) && calcep;\n\n    // (*testout) << \"l = \" << level << \"locsize = \" << locsurf.Size() << \" possexp = \" << possibleexp << \"\\n\";\n    if (possibleexp && (numprim <= check_crosspoint || level >= 50))\n      {\n\tdecision = 1;\n\tsureexp = 0;\n\n\t/*\n\t(*testout) << \"extremal surfs = \";\n\tfor (int k5 = 0; k5 < locsurf.Size(); k5++)\n\t  (*testout) << typeid(*geometry->GetSurface(locsurf[k5])).name() << \" \";\n\t(*testout) << \"\\n\";\n\t*/\n\n\tfor (int k1 = 0; k1 < locsurf.Size() - 1; k1++)\n\t  for (int k2 = k1+1; k2 < locsurf.Size(); k2++)\n\t    {\n\t      const Surface * surf1 = geometry->GetSurface(locsurf[k1]);\n\t      const Surface * surf2 = geometry->GetSurface(locsurf[k2]);\n\t      /*\n\t      (*testout) << \"edgecheck, types = \" << typeid(*surf1).name() << \", \" << typeid(*surf2).name()\n\t\t\t << \"edge-newton-conv = \" << EdgeNewtonConvergence (surf1, surf2, p)\n\t\t\t << \"edge-deg = \" << EdgeDegenerated (surf1, surf2, box)\n\t\t\t << \"\\n\";\n\t      */\n\n\t      if (EdgeNewtonConvergence (surf1, surf2, p) ) \n\t\tsureexp = 1;\n\t      else\n\t\t{\n\t\t  if (!EdgeDegenerated (surf1, surf2, box)) \n\t\t    decision = 0;\n\t\t}\n\t    }\n#ifdef DEVELOP\n        (*testout) << \"edgepnt decision = \" << decision << \" sure = \" << sureexp << endl;\n#endif\n\tif (decision && sureexp)\n\t  {\n\t    for (int k1 = 0; k1 < locsurf.Size() - 1; k1++)\n\t      for (int k2 = k1+1; k2 < locsurf.Size(); k2++)\n\t\t{\n\t\t  const Surface * surf1 = geometry->GetSurface(locsurf[k1]);\n\t\t  const Surface * surf2 = geometry->GetSurface(locsurf[k2]);\n\n\t\t  if (EdgeNewtonConvergence (surf1, surf2, p))\n\t\t    {\n\t\t      EdgeNewton (surf1, surf2, p);\n\t\t    \n\t\t      Point<3> pp;\n\t\t      if (IsEdgeExtremalPoint (surf1, surf2, p, pp, box.Diam()/2))\n\t\t\t{\n\t\t\t  (*testout) << \"extremalpoint (nearly) found:\" << pp \n                                     << \"box.diam = \" << box.Diam() << \", dist = \" << Dist(pp,box.Center())\n                                     << endl;\n                          \n\t\t\t  if (Dist (pp, box.Center()) < box.Diam()/2 &&\n\t\t\t      sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) )\n\t\t\t    {\n\t\t\t      if (AddPoint (pp, layer))\n\t\t\t\t(*testout) << \"Extremal point found: \" << pp << endl;//\"(eps=\"<<1e-9*size<<\")\"<< endl;\n\t\t\t    }  \n\t\t\t}            \n\t\t    }\n\t\t}\n\t  }\n\tif (decision)\n\t  possibleexp = 0;\n      }\n \n\n    // (*testout) << \"l = \" << level << \" poss cp/ep sure exp = \" << possiblecrossp << \" \" << possibleexp << \" \" << sureexp << \"\\n\";\n    if (possiblecrossp || possibleexp)\n      {\n\tBoxSphere<3> sbox;\n\tfor (int i = 0; i < 8; i++)\n\t  {\n\t    box.GetSubBox (i, sbox);\n\t    sbox.Increase (1e-4 * sbox.Diam());\n\t    sbox.CalcDiamCenter();\n\t    Solid * redsol = sol -> GetReducedSolid (sbox);\n\n\t    if (redsol)\n\t      {\n\t\tCalcSpecialPointsRec (redsol, layer, sbox, level+1, calccp, calcep);\n\t\tdelete redsol;\n\t      }\n\t  }\n      }\n  }\n\n\n\n\n\n  /******* Tests for Point of intersection **********************/\n\n\n\n  bool SpecialPointCalculation :: \n  CrossPointNewtonConvergence (const Surface * f1, \n\t\t\t       const Surface * f2, \n\t\t\t       const Surface * f3,\n\t\t\t       const BoxSphere<3> & box)\n  {\n    Vec<3> grad, rs, x;\n    Mat<3> jacobi, inv;\n    Point<3> p = box.Center();\n\n    f1->CalcGradient (p, grad);\n    jacobi(0,0) = grad(0);\n    jacobi(0,1) = grad(1);\n    jacobi(0,2) = grad(2);\n\n    f2->CalcGradient (p, grad);\n    jacobi(1,0) = grad(0);\n    jacobi(1,1) = grad(1);\n    jacobi(1,2) = grad(2);\n\n    f3->CalcGradient (p, grad);\n    jacobi(2,0) = grad(0);\n    jacobi(2,1) = grad(1);\n    jacobi(2,2) = grad(2);\n\n    if (fabs (Det (jacobi)) > 1e-8)\n      {\n\tdouble gamma = f1 -> HesseNorm() + f2 -> HesseNorm() + f3 -> HesseNorm();\n\tif (gamma == 0.0) return 1;\n\n\tCalcInverse (jacobi, inv);\n\n\trs(0) = f1->CalcFunctionValue (p);\n\trs(1) = f2->CalcFunctionValue (p);\n\trs(2) = f3->CalcFunctionValue (p);\n\n\tx = inv * rs;\n\n\tdouble beta = 0;\n\tfor (int i = 0; i < 3; i++)\n\t  {\n\t    double sum = 0;\n\t    for (int j = 0; j < 3; j++)\n\t      sum += fabs (inv(i,j));\n\t    if (sum > beta)  beta = sum;\n\t  }\n\tdouble eta = Abs (x);\n\n\n#ifdef DEVELOP\n        *testout << \"check Newton: \" << \"beta = \" << beta << \", gamma = \" << gamma << \", eta = \" << eta << endl;\n        double rad = 1.0 / (beta * gamma);\n        *testout << \"rad = \" << rad << endl;\n\t*testout << \"rs = \" << rs << endl;\n#endif\n        \n\treturn (beta * gamma * eta < 0.1) && (2 > box.Diam()*beta*gamma);\n      }\n    return 0;\n\n  }\n\n\n\n\n  bool SpecialPointCalculation :: \n  CrossPointDegenerated (const Surface * f1,\n\t\t\t const Surface * f2, \n\t\t\t const Surface * f3, \n\t\t\t const BoxSphere<3> & box) const\n  {\n    Mat<3> mat;\n    Vec<3> g1, g2, g3;\n    double normprod;\n\n    if (box.Diam() > relydegtest) return 0;\n\n    f1->CalcGradient (box.Center(), g1);\n    normprod = Abs2 (g1);\n\n    f2->CalcGradient (box.Center(), g2);\n    normprod *= Abs2 (g2);\n \n    f3->CalcGradient (box.Center(), g3);\n    normprod *= Abs2 (g3);\n\n    for (int i = 0; i < 3; i++)\n      {\n\tmat(i,0) = g1(i);\n\tmat(i,1) = g2(i);\n\tmat(i,2) = g3(i);\n      }\n\n    return sqr (Det (mat)) < sqr(cpeps1) * normprod;\n  }\n \n\n\n\n\n  void SpecialPointCalculation :: CrossPointNewton (const Surface * f1, \n\t\t\t\t\t\t    const Surface * f2, \n\t\t\t\t\t\t    const Surface * f3, Point<3> & p)\n  {\n    Vec<3> g1, g2, g3;\n    Vec<3> rs, sol;\n    Mat<3> mat;\n\n    int i = 10;\n    while (i > 0)\n      {\n\ti--;\n\trs(0) = f1->CalcFunctionValue (p);\n\trs(1) = f2->CalcFunctionValue (p);\n\trs(2) = f3->CalcFunctionValue (p);\n\n\tf1->CalcGradient (p, g1);\n\tf2->CalcGradient (p, g2);\n\tf3->CalcGradient (p, g3);\n\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    mat(0, j) = g1(j);\n\t    mat(1, j) = g2(j);\n\t    mat(2, j) = g3(j);\n\t  }\n\tmat.Solve (rs, sol);\n\tif (sol.Length2() < 1e-24 && i > 1) i = 1;\n\n#ifdef DEVELOP\n        *testout << \"CrossPointNewton, err = \" << sol.Length2() << endl;\n#endif\n\tp -= sol;\n      }\n  }\n\n\n\n\n  /******* Tests for Point on edges **********************/\n\n\n\n\n  bool SpecialPointCalculation :: \n  EdgeNewtonConvergence (const Surface * f1, const Surface * f2, \n\t\t\t const Point<3> & p)\n  {\n    Vec<3> g1, g2, sol;\n    Vec<2> vrs;\n    Mat<2,3> mat;\n    Mat<3,2> inv;\n\n    f1->CalcGradient (p, g1);\n    f2->CalcGradient (p, g2);\n\n    if ( sqr(g1 * g2) < (1 - 1e-8) * Abs2 (g1) * Abs2 (g2))\n      {\n\tdouble gamma = f1 -> HesseNorm() + f2 -> HesseNorm();\n\tif (gamma < 1e-32) return 1;\n\tgamma = sqr (gamma);\n      \n\tfor (int i = 0; i < 3; i++)\n\t  {\n\t    mat(0,i) = g1(i);\n\t    mat(1,i) = g2(i);\n\t  }\n\n\tCalcInverse (mat, inv);\n\n\tvrs(0) = f1->CalcFunctionValue (p);\n\tvrs(1) = f2->CalcFunctionValue (p);\n\tsol = inv * vrs;\n\n\tdouble beta = 0;\n\tfor (int i = 0; i < 3; i++)\n\t  for (int j = 0; j < 2; j++)\n\t    beta += inv(i,j) * inv(i,j);\n\t// beta = sqrt (beta);\n\n\tdouble eta = Abs2 (sol);\n\n\t// alpha = beta * gamma * eta;\n\treturn (beta * gamma * eta < 0.01);\n      }\n    return 0;\n  }\n\n\n\n\n  bool SpecialPointCalculation :: \n  EdgeDegenerated (const Surface * f1,\n\t\t   const Surface * f2, \n\t\t   const BoxSphere<3> & box) const\n  {\n    // perform newton steps. normals parallel ?\n    // if not decidable: return 0 \n  \n    Point<3> p = box.Center();\n    Vec<3> g1, g2, sol;\n    Vec<2> vrs;\n    Mat<2,3> mat;\n\n    int i = 20;\n    while (i > 0)\n      {\n\tif (Dist2 (p, box.Center()) > sqr(box.Diam()))\n\t  return 0;\n\n\ti--;\n\tvrs(0) = f1->CalcFunctionValue (p);\n\tvrs(1) = f2->CalcFunctionValue (p);\n\n\tf1->CalcGradient (p, g1);\n\tf2->CalcGradient (p, g2);\n\n\t// if ( sqr (g1 * g2) > (1 - 1e-10) * Abs2 (g1) * Abs2 (g2))\n        // return 1;\n        if ( Abs2 (Cross(g1,g2)) < 1e-10 * Abs2 (g1) * Abs2 (g2))  // same, but stable\n          {\n            if (Abs2(vrs) < 1e-12*sqr(size))  // degenerate only if on both surfaces\n              return 1;\n            else\n              return 0;\n          }\n\n\n        \n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    mat(0,j) = g1(j);\n\t    mat(1,j) = g2(j);\n\t  }\n\tmat.Solve (vrs, sol);\n\n\tif (Abs2 (sol) < 1e-24 && i > 1) i = 1;\n\tp -= sol;\n      }\n\n    return 0;\n  }\n\n\n\n\n\n\n  void SpecialPointCalculation :: EdgeNewton (const Surface * f1, \n\t\t\t\t\t      const Surface * f2, Point<3> & p)\n  {\n    Vec<3> g1, g2, sol;\n    Vec<2> vrs;\n    Mat<2,3> mat;\n\n    int i = 10;\n    while (i > 0)\n      {\n\ti--;\n\tvrs(0) = f1->CalcFunctionValue (p);\n\tvrs(1) = f2->CalcFunctionValue (p);\n\n\tf1->CalcGradient (p, g1);\n\tf2->CalcGradient (p, g2);\n\n\t//(*testout) << \"p \" << p << \" f1 \" << vrs(0) << \" f2 \" << vrs(1) << \" g1 \" << g1 << \" g2 \" << g2 << endl;\n\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    mat(0,j) = g1(j);\n\t    mat(1,j) = g2(j);\n\t  }\n\tmat.Solve (vrs, sol);\n\t\n\tif (Abs2 (sol) < 1e-24 && i > 1) i = 1;\n\tp -= sol;\n      }\n  }\n\n\n\n  bool SpecialPointCalculation :: \n  IsEdgeExtremalPoint (const Surface * f1, const Surface * f2, \n\t\t       const Point<3> & p, Point<3> & pp, double rad)\n  {\n    Vec<3> g1, g2, t, t1, t2;\n\n    f1->CalcGradient (p, g1);\n    f2->CalcGradient (p, g2);\n  \n    t = Cross (g1, g2);\n    t.Normalize();\n\n    Point<3> p1 = p + rad * t;\n    Point<3> p2 = p - rad * t;\n\n    EdgeNewton (f1, f2, p1);\n    EdgeNewton (f1, f2, p2);\n  \n    f1->CalcGradient (p1, g1);\n    f2->CalcGradient (p1, g2);\n    t1 = Cross (g1, g2);\n    t1.Normalize();\n\n    f1->CalcGradient (p2, g1);\n    f2->CalcGradient (p2, g2);\n    t2 = Cross (g1, g2);\n    t2.Normalize();\n\n    double val = 1e-8 * rad * rad;\n    for (int j = 0; j < 3; j++)\n      if ( (t1(j) * t2(j) < -val) )\n\t{\n\t  pp = p;\n\t  ExtremalPointNewton (f1, f2, j+1, pp);\n\t  return 1;\n\t}\n\n    return 0;\n  }\n\n\n\n\n\n\n\n\n\n  /********** Tests of Points of extremal coordinates  ****************/\n\n\n  void SpecialPointCalculation :: ExtremalPointNewton (const Surface * f1, \n\t\t\t\t\t\t       const Surface * f2, \n\t\t\t\t\t\t       int dir, Point<3> & p)\n  {\n    Vec<3> g1, g2, v, curv;\n    Vec<3> rs, x, y1, y2, y;\n    Mat<3> h1, h2;\n    Mat<3> jacobi;\n\n    int i = 50;\n    while (i > 0)\n      {\n\ti--;\n\trs(0) = f1->CalcFunctionValue (p);\n\trs(1) = f2->CalcFunctionValue (p);\n\n\tf1 -> CalcGradient (p, g1);\n\tf2 -> CalcGradient (p, g2);\n\n\tf1 -> CalcHesse (p, h1);\n\tf2 -> CalcHesse (p, h2);\n\n\tv = Cross (g1, g2);\n\n\trs(2) = v(dir-1);\n\n\tjacobi(0,0) = g1(0);\n\tjacobi(0,1) = g1(1);\n\tjacobi(0,2) = g1(2);\n\n\tjacobi(1,0) = g2(0);\n\tjacobi(1,1) = g2(1);\n\tjacobi(1,2) = g2(2);\n\n\n\tswitch (dir)\n\t  {\n\t  case 1:\n\t    {\n\t      y1(0) = 0;\n\t      y1(1) = g2(2);\n\t      y1(2) = -g2(1);\n\t      y2(0) = 0;\n\t      y2(1) = -g1(2);\n\t      y2(2) = g1(1);\n\t      break;\n\t    }\n\t  case 2:\n\t    {\n\t      y1(0) = -g2(2);\n\t      y1(1) = 0;\n\t      y1(2) = g2(0);\n\t      y2(0) = g1(2);\n\t      y2(1) = 0;\n\t      y2(2) = -g1(0);\n\t      break;\n\t    }\n\t  case 3:\n\t    {\n\t      y1(0) = g2(1);\n\t      y1(1) = -g2(0);\n\t      y1(2) = 0;\n\t      y2(0) = -g1(1);\n\t      y2(1) = g1(0);\n\t      y2(2) = 0;\n\t      break;\n\t    }\n\t  }\n\n\ty = h1 * y1 + h2 * y2;\n\n\tjacobi(2,0) = y(0);\n\tjacobi(2,1) = y(1);\n\tjacobi(2,2) = y(2);\n\n\t/*\n\t(*testout) << \"p \" << p << \" f1 \" << rs(0) << \" f2 \" << rs(1) << endl\n\t\t   << \" jacobi \" << jacobi << endl\n\t\t   << \" rhs \" << rs << endl;\n\t*/\t\n\n\tjacobi.Solve (rs, x);\n\n\tif (Abs2 (x) < 1e-24 && i > 1)\n\t  {\n\t    i = 1;\n\t  }\n\n\t\n\tdouble minval(Abs2(rs)),minfac(1);\n\tdouble startval(minval);\n\tfor(double fac = 1; fac > 1e-7; fac *= 0.6)\n\t  {\n\t    Point<3> testpoint = p-fac*x;\n\n\t    rs(0) = f1->CalcFunctionValue (testpoint);\n\t    rs(1) = f2->CalcFunctionValue (testpoint);\n\n\t    f1 -> CalcGradient (testpoint, g1);\n\t    f2 -> CalcGradient (testpoint, g2);\n\n\t    v = Cross (g1, g2);\n\n\t    rs(2) = v(dir-1);\n\n\t    double val = Abs2(rs);\n\n\t    if(val < minval)\n\t      {\n\t\tminfac = fac;\n\t\tif(val < 0.5 * startval)\n\t\t  break;\n\t\tminval = val;\n\t      }\n\n\t  }\n\tp -= minfac*x;\n\t\n\n\t//p -= x;\n      }\n\n\n    if (Abs2 (x) > 1e-20)\n      {\n\t(*testout) << \"Error: extremum Newton not convergent\" << endl;\n\t(*testout) << \"dir = \" << dir << endl;\n\t(*testout) << \"p = \" << p << endl;\n\t(*testout) << \"x = \" << x << endl;\n      }\n  }\n\n  void SpecialPointCalculation :: \n  ComputeCrossPoints (const Plane * plane1, \n\t\t      const Plane * plane2, \n\t\t      const Plane * plane3, \n\t\t      NgArray<Point<3> > & pts)\n  {\n    Mat<3> mat;\n    Vec<3> rhs, sol;\n    Point<3> p0(0,0,0);\n\n    pts.SetSize (0);\n    for (int i = 0; i < 3; i++)\n      {\n\tconst Plane * pi(NULL);\n\tswitch (i)\n\t  {\n\t  case 0: pi = plane1; break;\n\t  case 1: pi = plane2; break;\n\t  case 2: pi = plane3; break;\n\t  }\n\n\tdouble val;\n\tVec<3> hvec;\n\tval = pi -> CalcFunctionValue(p0);\n\tpi -> CalcGradient (p0, hvec);\n\n\tfor (int j = 0; j < 3; j++)\n\t  mat(i,j) = hvec(j);\n\trhs(i) = -val;\n      }\n\n    if (fabs (Det (mat)) > 1e-8)\n      {\n\tmat.Solve (rhs, sol);\n\tpts.Append (Point<3> (sol));\n      }\n  }\n\n\n\n\n\n  void SpecialPointCalculation :: \n  ComputeCrossPoints (const Plane * plane1, \n\t\t      const Plane * plane2, \n\t\t      const QuadraticSurface * quadric, \n\t\t      NgArray<Point<3> > & pts)\n  {\n    Mat<2,3> mat;\n    Mat<3,2> inv;\n    Vec<2> rhs;\n    Vec<3> sol, t;\n    Point<3> p0(0,0,0);\n\n    pts.SetSize (0);\n    for (int i = 0; i < 2; i++)\n      {\n\tconst Plane * pi(NULL);\n\tswitch (i)\n\t  {\n\t  case 0: pi = plane1; break;\n\t  case 1: pi = plane2; break;\n\t  }\n\n\tdouble val;\n\tVec<3> hvec;\n\tval = pi -> CalcFunctionValue(p0);\n\tpi -> CalcGradient (p0, hvec);\n\n\tfor (int j = 0; j < 3; j++)\n\t  mat(i,j) = hvec(j);\n\trhs(i) = -val;\n      }\n    CalcInverse (mat, inv);\n    sol = inv * rhs;\n    t = Cross (mat.Row(0), mat.Row(1));\n\n    if (t.Length() > 1e-8)\n      {\n\tPoint<3> p (sol);\n\t// quadratic on  p + s t = 0\n\tdouble quad_a;\n\tVec<3> quad_b;\n\tMat<3> quad_c;\n\t\n\tquad_a = quadric -> CalcFunctionValue(p);\n\tquadric -> CalcGradient (p, quad_b);\n\tquadric -> CalcHesse (p, quad_c);\n\t\n\tdouble a, b, c;\n\ta = quad_a;\n\tb = quad_b * t;\n\tc = 0.5 * t * (quad_c * t);\n\n\t// a  + s b + s^2 c = 0;\n\tdouble disc = b*b-4*a*c;\n\tif (disc > 1e-10 * fabs (b))\n\t  {\n\t    disc = sqrt (disc);\n\t    double s1 = (-b-disc) / (2*c);\n\t    double s2 = (-b+disc) / (2*c);\n\n\t    pts.Append (p + s1 * t);\n\t    pts.Append (p + s2 * t);\n\t  }\n      }\n  }\n\n\n\n\n\n  void SpecialPointCalculation :: \n  ComputeCrossPoints (const Sphere * sphere1, \n\t\t      const Sphere * sphere2, \n\t\t      const Sphere * sphere3, \n\t\t      NgArray<Point<3> > & pts)\n  {\n    Mat<2,3> mat;\n    Mat<3,2> inv;\n    Vec<2> rhs;\n    Vec<3> sol, t;\n    Point<3> p0(0,0,0);\n\n    pts.SetSize (0);\n\n\n    Point<3> c1 = sphere1 -> Center();\n    Point<3> c2 = sphere2 -> Center();\n    Point<3> c3 = sphere3 -> Center();\n    double r1 = sphere1 -> Radius();\n    double r2 = sphere2 -> Radius();\n    double r3 = sphere3 -> Radius();\n\n\n    Vec<3> a1 = c2-c1;\n    double b1 = 0.5 * (sqr(r1) - sqr(r2) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c2)) );\n\n    Vec<3> a2 = c3-c1;\n    double b2 = 0.5 * (sqr(r1) - sqr(r3) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c3)) );\n\n\n    for (int j = 0; j < 3; j++)\n      {\n\tmat(0,j) = a1(j);\n\tmat(1,j) = a2(j);\n      }\n    \n    rhs(0) = b1;\n    rhs(1) = b2;\n\n\n    CalcInverse (mat, inv);\n    sol = inv * rhs;\n    t = Cross (mat.Row(0), mat.Row(1));\n\n    if (t.Length() > 1e-8)\n      {\n\tPoint<3> p (sol);\n\t// quadratic on  p + s t = 0\n\tdouble quad_a;\n\tVec<3> quad_b;\n\tMat<3> quad_c;\n\t\n\tquad_a = sphere1 -> CalcFunctionValue(p);\n\tsphere1 -> CalcGradient (p, quad_b);\n\tsphere1 -> CalcHesse (p, quad_c);\n\t\n\tdouble a, b, c;\n\ta = quad_a;\n\tb = quad_b * t;\n\tc = 0.5 * t * (quad_c * t);\n\n\t// a  + s b + s^2 c = 0;\n\tdouble disc = b*b-4*a*c;\n\tif (disc > 1e-10 * fabs (b))\n\t  {\n\t    disc = sqrt (disc);\n\t    double s1 = (-b-disc) / (2*c);\n\t    double s2 = (-b+disc) / (2*c);\n\n\t    pts.Append (p + s1 * t);\n\t    pts.Append (p + s2 * t);\n\t  }\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n  void SpecialPointCalculation :: \n  ComputeExtremalPoints (const Plane * plane, \n\t\t\t const QuadraticSurface * quadric, \n\t\t\t NgArray<Point<3> > & pts)\n  {\n    // 3 equations:\n    // surf1 = 0  <===> plane_a + plane_b x = 0;\n    // surf2 = 0  <===> quad_a + quad_b x + x^T quad_c x = 0\n    // (grad 1 x grad 2)(i) = 0  <====> (grad 1 x e_i) . grad_2 = 0\n\n    pts.SetSize (0);\n\n    Point<3> p0(0,0,0);\n    double plane_a, quad_a;\n    Vec<3> plane_b, quad_b, ei;\n    Mat<3> quad_c;\n\n    plane_a = plane -> CalcFunctionValue(p0);\n    plane -> CalcGradient (p0, plane_b);\n\n    quad_a = quadric -> CalcFunctionValue(p0);\n    quadric -> CalcGradient (p0, quad_b);\n    quadric -> CalcHesse (p0, quad_c);\n    for (int i = 0; i < 3; i++)\n      for (int j = 0; j < 3; j++)\n\tquad_c(i,j) *= 0.5;\n\n    for (int dir = 0; dir <= 2; dir++)\n      {\n\tei = 0.0; ei(dir) = 1;\n\tVec<3> v1 = Cross (plane_b, ei);\n\t\n\t// grad_2 . v1 ... linear:\n\tdouble g2v1_c = v1 * quad_b;\n\tVec<3> g2v1_l = 2.0 * (quad_c * v1);\n\n\t// find line of two linear equations:\n\t\n\tVec<2> rhs;\n\tVec<3> sol;\n\tMat<2,3> mat;\n\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    mat(0,j) = plane_b(j);\n\t    mat(1,j) = g2v1_l(j);\n\t  }\n\trhs(0) = -plane_a;\n\trhs(1) = -g2v1_c;\n\n\tVec<3> t = Cross (plane_b, g2v1_l);\n\tif (Abs2(t) > 0)\n\t  {\n\t    mat.Solve (rhs, sol);\n\t    \n\t    // solve quadratic equation along line  sol + alpha t ....\n\t    double a = quad_a + quad_b * sol + sol * (quad_c * sol);\n\t    double b = quad_b * t + 2 * (sol * (quad_c * t));\n\t    double c = t * (quad_c * t);\n\n\t    // solve a + b alpha + c alpha^2:\n\n\t    if (fabs (c) > 1e-32)\n\t      {\n\t\tdouble disc = sqr (0.5*b/c) - a/c;\n\t\tif (disc > 0)\n\t\t  {\n\t\t    disc = sqrt (disc);\n\t\t    double alpha1 = -0.5*b/c + disc;\n\t\t    double alpha2 = -0.5*b/c - disc;\n\n\t\t    pts.Append (Point<3> (sol+alpha1*t));\n\t\t    pts.Append (Point<3> (sol+alpha2*t));\n\t\t    /*\n\t\t    cout << \"sol1 = \" << sol + alpha1 * t\n\t\t\t << \", sol2 = \" << sol + alpha2 * t << endl;\n\t\t    */\n\t\t  }\n\t      }\n\t  }\n      }\n  }\n\n\n\n\n\n\n\n  void SpecialPointCalculation :: \n  ComputeExtremalPoints (const Sphere * sphere1,\n\t\t\t const Sphere * sphere2,\n\t\t\t NgArray<Point<3> > & pts)\n  {\n    // 3 equations:\n    // surf1 = 0  <===> |x-c1|^2 - r1^2 = 0;\n    // surf2 = 0  <===> |x-c2|^2 - r2^2 = 0;\n    // (grad 1 x grad 2)(i) = 0  <====> (x-p1) x (p1-p2) . e_i = 0;\n\n    pts.SetSize (0);\n\n    Point<3> c1 = sphere1 -> Center();\n    Point<3> c2 = sphere2 -> Center();\n    double r1 = sphere1 -> Radius();\n    double r2 = sphere2 -> Radius();\n\n    /*\n    *testout << \"\\n\\ncompute extremalpoint, sphere-sphere\" << endl;\n    *testout << \"c1 = \" << c1 << \", r1 = \" << r1 << endl;\n    *testout << \"c2 = \" << c2 << \", r2 = \" << r2 << endl;\n    *testout << \"dist = \" << Abs (c2-c1) << \", r1+r2 = \" << r1+r2 << endl;\n    */\n\n    Vec<3> v12 = c2 - c1;\n\n    Vec<3> a1, a2;\n    double b1, b2;\n\n    // eqn: ai . x = bi\n\n    a1 = v12;\n    b1 = 0.5 * (sqr(r1) - sqr(r2) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c2)) );\n\n    int dir = 0;\n    for (int j = 1; j < 3; j++)\n      if (fabs (v12(j)) < fabs(v12(dir)))\n\tdir = j;\n    \n    Vec<3> ei = 0.0;\n    ei(dir) = 1;\n    a2 = Cross (v12, ei);\n    b2 = Vec<3>(c1) * a2;\n    \n    \n    Point<3> p0 (0,0,0);\n    double quad_a;\n    Vec<3> quad_b;\n    Mat<3> quad_c;\n\n    quad_a = sphere1 -> CalcFunctionValue(p0);\n    sphere1 -> CalcGradient (p0, quad_b);\n    sphere1 -> CalcHesse (p0, quad_c);\n    for (int i = 0; i < 3; i++)\n      for (int j = 0; j < 3; j++)\n\tquad_c(i,j) *= 0.5;\n\n    \n    // find line of two linear equations:\n    \n    Vec<2> rhs;\n    Vec<3> sol;\n    Mat<2,3> mat;\n    \n    for (int j = 0; j < 3; j++)\n      {\n\tmat(0,j) = a1(j);\n\tmat(1,j) = a2(j);\n      }\n    rhs(0) = b1;\n    rhs(1) = b2;\n\n\n    // *testout << \"mat = \" << endl << mat << endl;\n    // *testout << \"rhs = \" << endl << rhs << endl;\n\n    Vec<3> t = Cross (a1, a2);\n    if (Abs2(t) > 0)\n      {\n\tmat.Solve (rhs, sol);\n\t\n\t/*\n\t*testout << \"sol = \" << endl << sol << endl;\n\n\t*testout << \"a * sol = \" << mat * sol << endl;\n\n\t*testout << \"c1-sol = \" << Abs (Vec<3>(c1)-sol) << endl;\n\t*testout << \"c2-sol = \" << Abs (Vec<3>(c2)-sol) << endl;\n\t*/\n\n\t// solve quadratic equation along line  sol + alpha t ....\n\tdouble a = quad_a + quad_b * sol + sol * (quad_c * sol);\n\tdouble b = quad_b * t + 2 * (sol * (quad_c * t));\n\tdouble c = t * (quad_c * t);\n\n\t// solve a + b alpha + c alpha^2:\n\t\n\tif (fabs (c) > 1e-32)\n\t  {\n\t    double disc = sqr (0.5*b/c) - a/c;\n\t    if (disc > 0)\n\t      {\n\t\tdisc = sqrt (disc);\n\t\tdouble alpha1 = -0.5*b/c + disc;\n\t\tdouble alpha2 = -0.5*b/c - disc;\n\t\t\n\t\tpts.Append (Point<3> (sol+alpha1*t));\n\t\tpts.Append (Point<3> (sol+alpha2*t));\n\n\t\t// *testout << \"pts = \" << endl << pts << endl;\n\n\t\t/*\n\t\t  cout << \"sol1 = \" << sol + alpha1 * t\n\t\t  << \", sol2 = \" << sol + alpha2 * t << endl;\n\t\t*/\n\t      }\n\t  }\n      }\n  }\n\n\n  bool SpecialPointCalculation :: \n  ComputeExtremalPoints (const RevolutionFace * rev1, \n\t\t\t const RevolutionFace * rev2, \n\t\t\t NgArray<Point<3> > & pts)\n  {\n    // if (rev1 -> P0() != rev2 -> P0()) return false; // missing ????\n    if (Dist2 (rev1 -> P0(), rev2 -> P0()) > 1e-20*sqr(size)) return false;\n    // if (rev1 -> Axis() != rev2 -> Axis()) return false;\n    if ( (rev1 -> Axis()-rev2 -> Axis()).Length2() > 1e-16) return false;\n\n    Point<2> p1s = rev1->GetSpline().StartPI();\n    Point<2> p1e = rev1->GetSpline().EndPI();\n    Point<2> p2s = rev2->GetSpline().StartPI();\n    Point<2> p2e = rev2->GetSpline().EndPI();\n\n    Point<2> p2d;\n    if (Dist2(p1s,p2e) < 1e-20*sqr(size))\n      p2d = p1s;\n    else if (Dist2(p1e, p2s) < 1e-20*sqr(size))\n      p2d = p1e;\n    else\n      return false;\n    *testout << \"Norm axis = \" << rev1->Axis().Length() << endl;\n    Point<3> center = rev1->P0() + p2d(0)*rev1->Axis();\n    Vec<3> n = rev1->Axis();\n    // extremal points of circle, center, normal axis, radius p2d(1)\n    // Lagrange:\n    // L(x, lam1, lam2) = x_i + lam1 * (x-c)*v + lam2 * ( |x-c|^2 - r^2 )\n    for (double i = 0; i < 3; i++)\n      {\n        double lam1 = -n(i) / n.Length2();\n        Vec<3> ei(0,0,0); ei(i) = 1;\n        // double lam2 = 1/(2*p2d(1)) * sqrt(1 - sqr(n(i))/n.Length2());\n        double fac = 1-sqr(n(i))/n.Length2();\n        // if (fabs(lam2) > 1e-10)\n        if (fac > 1e-10)\n          {\n            double lam2 = 1/(2*p2d(1)) * sqrt(fac);\n            Point<3> x = center - 1.0/(2*lam2) * (ei + lam1*n);\n            pts.Append (x);\n            x = center + 1.0/(2*lam2) * (ei + lam1*n);\n            pts.Append (x);\n\n            /*\n            // check:\n            Point<2> p2d;\n            rev1 -> CalcProj (x, p2d);\n            *testout << \"special solution, p2d = \" << p2d << endl;\n            rev2 -> CalcProj (x, p2d);\n            *testout << \"special solution, p2d = \" << p2d << endl;\n            */\n          }\n      }\n    return true;\n  }\n\n\n\n\n\n\n\n  /*\n    bool SpecialPointCalculation :: ExtremalPointPossible (const Surface * f1, \n    const Surface * f2, \n    int dir, \n    const BoxSphere<3> & box)\n    {\n    double hn1, hn2, gn1, gn2;\n    Point<3> p;\n    Vec<3> g1, g2, v;\n    double f3;\n    double r = box.Diam()/2;\n\n    p = box.Center();\n\n    f1 -> CalcGradient (p, g1);\n    f2 -> CalcGradient (p, g2);\n\n    gn1 = g1.Length();\n    gn2 = g2.Length();\n\n    hn1 = f1 -> HesseNorm ();\n    hn2 = f2 -> HesseNorm ();\n\n    v = Cross (g1, g2);\n    f3 = fabs (v(dir-1));\n\n    //  (*testout) << \"f3 = \" << f3 << \"  r = \" << r \n    //             << \"normbound = \" \n    //             << (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)) << endl;\n \n    return (f3 <= 3 * r * (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)));\n    }\n\n\n\n    bool SpecialPointCalculation :: \n    ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2, \n    int dir, \n    const BoxSphere<3> & box)\n    {\n    return box.Diam() < 1e-8;\n    }\n\n\n    bool SpecialPointCalculation :: \n    ExtremalPointDegenerated (const Surface * f1, const Surface * f2, \n    int dir, const BoxSphere<3> & box)\n    {\n    double gn1, gn2;\n    Point<3> p;\n    Vec<3> g1, g2, v;\n    double maxderiv;\n    double minv;\n    Vec<3> curv, t;\n    Vec<2> rs, x;\n    Mat<3> h1, h2;\n    Mat<2> a, inv;\n    double leftside;\n\n    if (box.Diam() > relydegtest) return 0;\n\n    p = box.Center();\n\n    f1 -> CalcGradient (p, g1);\n    f2 -> CalcGradient (p, g2);\n    gn1 = g1.Length();\n    gn2 = g2.Length();\n\n    v = Cross (g1, g2);\n    if (Abs (v) < epeps1 * gn1 * gn2) return 1;       // irregular edge\n\n    f1 -> CalcHesse (p, h1);\n    f2 -> CalcHesse (p, h2);\n\n    //  hn1 = f1 -> HesseNorm ();\n    //  hn2 = f2 -> HesseNorm ();\n\n    t = v;\n    a(0, 0) = g1 * g1;\n    a(0, 1) = \n    a(1, 0) = g1 * g2;\n    a(1, 1) = g2 * g2;\n  \n    rs(0) = g1(dir-1);\n    rs(1) = g2(dir-1);\n\n    a.Solve (rs, x);\n\n    //  (*testout) << \"g1 = \" << g1 << \" g2 = \" << g2 << endl;\n    //  (*testout) << \"lam = \" << x << endl;\n    //  (*testout) << \"h2 = \" << h2 << endl;\n\n    leftside = fabs (x(0) * ( t * (h1 * t)) + \n    x(1) * ( t * (h2 * t)));\n\n    //  (*testout) << \"leftside = \" << leftside << endl;\n\n    if (leftside < epeps2 * Abs2 (v)) return 1;  \n\n    return 0;\n    }\n  */\n \n\n  bool SpecialPointCalculation :: AddPoint (const Point<3> & p, int layer)\n  {\n    for (int i = 0; i < points->Size(); i++)\n      if (Dist2 ( (*points)[i], p) < epspointdist2 &&\n\t  (*points)[i].GetLayer() == layer)\n\treturn false;\n\n    points->Append (MeshPoint(p, layer));\n    PrintMessageCR (3, \"Found points \", points->Size());\n    return true;\n  }\n\n\n\n\n\n\n\n  void SpecialPointCalculation :: \n  AnalyzeSpecialPoints (const CSGeometry & ageometry,\n\t\t\tNgArray<MeshPoint> & apoints, \n\t\t\tNgArray<SpecialPoint> & specpoints)\n  {\n    static int timer = NgProfiler::CreateTimer (\"CSG: analyze special points\");\n    NgProfiler::RegionTimer reg (timer);\n\n\n    NgArray<int> surfind, rep_surfind, surfind2, rep_surfind2, surfind3;\n\n    NgArray<Vec<3> > normalvecs;\n    Vec<3> nsurf = 0.0;\n\n    NgArray<int> specpoint2point;\n    specpoints.SetSize (0);\n\n    geometry = &ageometry;\n\n    double geomsize = ageometry.MaxSize();\n \n    (*testout) << \"AnalyzeSpecialPoints\\n\";\n\n    if (!apoints.Size()) return;\n\n\n    {\n      /*\n\tsort points in the (arbitrary) direction dir\n\timportant for periodic boundaries: \n\tcorner points on the left and the right boundary come in the same ordering\n      */\n      Vec<3> dir(1.2, 1.7, 0.9);\n      \n      NgArray<double> coord(apoints.Size());\n      for (int i = 0; i < apoints.Size(); i++)\n\tcoord[i] = dir * Vec<3> (apoints[i]);\n      \n      QuickSort (coord, apoints);\n    }\n\n\n\n\n\n    Box<3> bbox (apoints[0], apoints[0]);\n    for (int i = 1; i < apoints.Size(); i++)\n      bbox.Add (apoints[i]);\n    bbox.Increase (0.1 * bbox.Diam());\n\n    (*testout) << \"points = \" << apoints << endl;\n\n    Point3dTree searchtree (bbox.PMin(), bbox.PMax());\n    NgArray<int> locsearch;\n\n    for (int si = 0; si < ageometry.GetNTopLevelObjects(); si++)\n      {\n\tconst TopLevelObject * tlo = ageometry.GetTopLevelObject(si);\n\n\tconst Solid * sol = tlo->GetSolid();\n\tconst Surface * surf = tlo->GetSurface();\n\n\n\tfor (int i = 0; i < apoints.Size(); i++)\n\t  {\n\t    Point<3> p = apoints[i];\n\t    \n#ifdef DEVELOP\n\t    *testout << \"                               test point \" << p << endl;\n#endif\t    \n\n\t    if (tlo->GetLayer() != apoints[i].GetLayer())\n\t      continue;\n\t    \n\n\t    auto locsol = sol -> TangentialSolid (p, surfind, ideps*geomsize);\n\n\t    rep_surfind.SetSize (surfind.Size());\n\t    int num_indep_surfs = 0;\n\t    \n\t    for (int j = 0; j < surfind.Size(); j++)\n\t      {\n\t\trep_surfind[j] = ageometry.GetSurfaceClassRepresentant (surfind[j]);\n\t\tbool found = false;\n\t\tfor (int k = 0; !found && k < j; k++)\n\t\t  found = (rep_surfind[k] == rep_surfind[j]);\n\t\tif(!found)\n\t\t  num_indep_surfs++;\n\t      }\n\t    \n\n#ifdef DEVELOP\n\t    *testout << \"surfs = \" << surfind << endl;\n\t    *testout << \"rep_surfs = \" << rep_surfind << endl;\n#endif\n\n\t    if (!locsol) continue;\n\n\t  \n\t    // get all surface indices, \n\t    if (surf)\n\t      {\n\t\t// locsol -> GetSurfaceIndices (surfind);\n\t\tbool hassurf = false;\n\t\tfor (int m = 0; m < surfind.Size(); m++)\n\t\t  if (ageometry.GetSurface(surfind[m]) == surf)\n\t\t    hassurf = true;\n\n\t\tif (!hassurf)\n\t\t  continue;\n\n\t\tnsurf = surf->GetNormalVector (p);\n\t      }\n\n\t    /*\n\t    // get independent surfaces of tangential solid\n\t    BoxSphere<3> box(p,p);\n\t    box.Increase (1e-6*geomsize);\n\t    box.CalcDiamCenter();\n\t    ageometry.GetIndependentSurfaceIndices (locsol, box, surfind);\n\t    */\n\n\t    // ageometry.GetIndependentSurfaceIndices (surfind);\n\n\n\t    normalvecs.SetSize(surfind.Size());\n\t    for (int j = 0; j < surfind.Size(); j++)\n\t      normalvecs[j] = \n\t\tageometry.GetSurface(surfind[j]) -> GetNormalVector(apoints[i]);\n\n\n\t    for (int j = 0; j < normalvecs.Size(); j++)\n\t      for (int k = 0; k < normalvecs.Size(); k++)\n\t\t{\n\t\t  if (rep_surfind[j] == rep_surfind[k]) continue;\n\t\t  //if (j == k) continue;\n\n\t\t  Vec<3> t;\n\n\t\t  if (dynamic_cast<const Polyhedra*> (ageometry.surf2prim[surfind[j]]) && \n\t\t      ageometry.surf2prim[surfind[j]] == \n\t\t      ageometry.surf2prim[surfind[k]])\n\t\t    {\n\t\t      t = ageometry.surf2prim[surfind[j]] -> \n\t\t\tSpecialPointTangentialVector (p, surfind[j], surfind[k]);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      t = Cross (normalvecs[j], normalvecs[k]);\n\t\t    }\n\n\n\t\t  if (Abs2 (t) < 1e-16)\n                    {\n                      // cerr << \"normal vectors degenerated\" << endl;\n                      continue;\n                    }\n\n#ifdef DEVELOP\n\t\t  *testout << \"           tangential vector \" << t << endl;\n#endif\n\n\t\t  t.Normalize();\n\n\t\t  \n\t\t  // try tangential direction t\n\t\t  if (surf && fabs (nsurf * t) > 1e-6)\n\t\t    continue;\n\n\t\t\n#ifdef DEVELOP\n\t\t  *testout << \"           j \" << j << \" k \" << k << endl;\n#endif  \n\n\t\t  if (!surf)\n\t\t    {\n\t\t      // compute second order approximation\n\t\t      // c(s) = p + s t + s*s/2 t2\n\t\t      Vec<3> gradj, gradk;\n\t\t      Mat<3> hessej, hessek;\n\t\t      ageometry.GetSurface (surfind[j]) -> CalcGradient (p, gradj);\n\t\t      ageometry.GetSurface (surfind[k]) -> CalcGradient (p, gradk);\n\t\t      ageometry.GetSurface (surfind[j]) -> CalcHesse (p, hessej);\n\t\t      ageometry.GetSurface (surfind[k]) -> CalcHesse (p, hessek);\n\t\t      \n\t\t      Vec<2> rhs;\n\t\t      Vec<3> t2;\n\t\t      Mat<2,3> mat;\n\t\t      Mat<3,2> inv;\n\t\t      for (int l = 0; l < 3; l++)\n\t\t\t{\n\t\t\t  mat(0,l) = gradj(l);\n\t\t\t  mat(1,l) = gradk(l);\n\t\t\t}\n\t\t      rhs(0) = -t * (hessej * t);\n\t\t      rhs(1) = -t * (hessek * t);\n\n                      CalcInverse (mat, inv);\n                      t2 = inv * rhs;\n#ifdef DEVELOP\n                      *testout << \"t = \" << t << \", t2 = \" << t2 << endl;\n#endif\n\t\t      /*\n\t\t      ageometry.GetIndependentSurfaceIndices \n\t\t\t(locsol, p, t, surfind2);\n\t\t      */\n\n\t\t      auto locsol2 = locsol -> TangentialSolid3 (p, t, t2, surfind2, ideps*geomsize); \n\t\t      if (!locsol2) continue;\n\t\t      \n\t\t      // locsol2 -> GetTangentialSurfaceIndices3 (p, t, t2, surfind2, 1e-9*geomsize);\n\n\t\t      rep_surfind2.SetSize (surfind2.Size());\n\t\t      for (int j2 = 0; j2 < surfind2.Size(); j2++)\n\t\t\trep_surfind2[j2] = ageometry.GetSurfaceClassRepresentant (surfind2[j2]);\n\n#ifdef DEVELOP\n\t\t      (*testout) << \"surfind2 = \" << endl << surfind2 << endl;\n#endif\n\t\t      NgArray<int> surfind2_aux(surfind2);\n\t\t      ageometry.GetIndependentSurfaceIndices (surfind2_aux);\n#ifdef DEVELOP\n\t\t      (*testout) << \"surfind2,rep = \" << endl << surfind2_aux << endl;\n#endif\n\n\t\t      bool ok = true;\n\n\t\t      // intersecting surfaces must be in second order tangential solid\n\t\t      /*\n\t\t      if (!surfind2.Contains(surfind[j]) ||\n\t\t\t  !surfind2.Contains(surfind[k]))\n\t\t\tok = false;\n\t\t      */\n\t\t      if (!surfind2_aux.Contains(rep_surfind[j]) ||\n\t\t\t  !surfind2_aux.Contains(rep_surfind[k]))\n\t\t\tok = false;\n\n#ifdef DEVELOP\n\t\t      (*testout) << \"ok,1 = \" << ok << endl;\n#endif\n\n\t\t      // there must be 2 different tangential faces to the edge\n\t\t      int cnt_tang_faces = 0;\n\t\t      for (int l = 0; l < surfind2.Size(); l++)\n\t\t\t{\n\t\t\t  Vec<3> nv =\n\t\t\t    ageometry.GetSurface(surfind2[l]) -> GetNormalVector(p);\n\n\t\t\t  Vec<3> m1 = Cross (t, nv);\n\t\t\t  Vec<3> m2 = -m1;\n\t\t\t  bool isface1 = 0, isface2 = 0;\n\t\t\t  \n\t\t\t  // locsol2 -> TangentialSolid2 (p, m1, locsol3, surfind3, 1e-9*geomsize);\n\t\t\t  auto locsol3 = locsol -> TangentialEdgeSolid (p, t, t2, m1, surfind3, ideps*geomsize);\n#ifdef DEVELOP\n                          (*testout) << \"m1 = \" << m1 << \", surfind3 = \" << surfind3 << endl;\n#endif\n\t\t\t  //ageometry.GetIndependentSurfaceIndices (surfind3);\n\n\t\t\t  if (surfind3.Contains(surfind2[l]))\n\t\t\t    isface1 = 1;\n\t\t\t  \n\t\t\t  // locsol2 -> TangentialSolid2 (p, m2, locsol3, surfind3, 1e-9*geomsize);\n\t\t\t  locsol3 = locsol -> TangentialEdgeSolid (p, t, t2, m2, surfind3, ideps*geomsize); \n#ifdef DEVELOP\n                          (*testout) << \"m2 = \" << m2 << \", surfind3 = \" << surfind3 << endl;\n#endif\n\n\t\t\t  // ageometry.GetIndependentSurfaceIndices (surfind3);\n\n\t\t\t  \n\t\t\t  if (surfind3.Contains(surfind2[l]))\n\t\t\t    isface2 = 1;\n\n\t\t\t  if (isface1 != isface2)\n\t\t\t    cnt_tang_faces++;\n\t\t\t}\n\n#ifdef DEVELOP\n\t\t      (*testout) << \"cnt_tang = \" << cnt_tang_faces << endl;\n#endif\n\n\t\t      if (cnt_tang_faces < 1)\n\t\t\tok = false;\n\n\t\t      if (!ok) continue;\n\t\t    }\n\n\t\t  \n\t\t  // edge must be on tangential surface\n\t\t  bool isedge = \n\t\t    locsol->VectorIn (p, t) &&\n\t\t    !locsol->VectorStrictIn (p, t);\n\t\t  \n#ifdef DEVELOP\n\t\t  (*testout) << \"isedge,1 = \" << isedge << \"\\n\";\n#endif\t\t\n  \n\t\t  // there must exist at least two different faces on edge\n\t\t  if (isedge)\n\t\t    {\n\t\t      // *testout << \"succ 1\" << endl;\n\t\t      int cnts = 0;\n\t\t      for (int m = 0; m < surfind.Size(); m++)\n\t\t\t{\n\t\t\t  if (fabs (normalvecs[m] * t) > 1e-6)\n\t\t\t    continue;\n\t\t\t  \n\t\t\t  Vec<3> s = Cross (normalvecs[m], t);\n\n\t\t\t  Vec<3> t2a = t + 0.01 *s;\n\t\t\t  Vec<3> t2b = t - 0.01 *s;\n\n\t\t\t  bool isfaceold =\n\t\t\t    (locsol->VectorIn (p, t2a, 1e-6*geomsize) &&\n\t\t\t     !locsol->VectorStrictIn (p, t2a, 1e-6*geomsize))\n\t\t\t    ||\n\t\t\t    (locsol->VectorIn (p, t2b, 1e-6*geomsize) &&\n\t\t\t     !locsol->VectorStrictIn (p, t2b, 1e-6*geomsize));\n\n                          bool isfacenew =\n                            locsol -> VecInSolid2(p, t, s, 1e-6*geomsize) == DOES_INTERSECT ||\n                            locsol -> VecInSolid2(p, t, -s, 1e-6*geomsize) == DOES_INTERSECT;\n                            /*\n                            (locsol->VectorIn2 (p, t, s, 1e-6*geomsize) && !locsol->VectorStrictIn2 (p, t, s, 1e-6*geomsize)) || \n                            (locsol->VectorIn2 (p, t, -s, 1e-6*geomsize) && !locsol->VectorStrictIn2 (p, t, -s, 1e-6*geomsize));\n                            */\n\n                          bool isface = isfacenew;\n                          \n                          if (isfaceold != isfacenew)\n                            {\n                              *testout << \"different, p = \" << p << \", t = \" << t << \", s = \" << s << endl;\n                              *testout << \"tlo = \" << si << endl;\n                              *testout << \"isface, old = \" << isface << \", isfacenew = \" << isfacenew << endl;\n                              \n                              *testout << \"t2a = \" << t2a << endl;\n                              *testout << \"vecin(p,t2a) = \" << locsol->VectorIn (p, t2a, 1e-6*geomsize) << endl;\n                              *testout << \"vecstrictin(p,t2a) = \" << locsol->VectorStrictIn (p, t2a, 1e-6*geomsize) << endl;\n                              *testout << \"vectorin2 = \" << locsol->VectorIn2 (p, t, s, 1e-6*geomsize)  << endl;\n                              *testout << \"vectorstrictin2 = \" << locsol->VectorStrictIn2 (p, t, s, 1e-6*geomsize)  << endl;\n                              \n                              *testout << \"t2b = \" << t2b << endl;\n                              *testout << \"vecin(p,t2b) = \" << locsol->VectorIn (p, t2b, 1e-6*geomsize) << endl;\n                              *testout << \"vecstrictin(p,t2b) = \" << locsol->VectorStrictIn (p, t2b, 1e-6*geomsize) << endl;\n                              *testout << \"vectorin2- = \" << locsol->VectorIn2 (p, t, -s, 1e-6*geomsize)  << endl;\n                              *testout << \"vectorstrictin2- = \" << locsol->VectorStrictIn2 (p, t, -s, 1e-6*geomsize)  << endl;\n                            }\n                          \n                          \n\t\t\t  /*\n\t\t\t  bool isface =\n\t\t\t    (locsol->VectorIn (p, t2a) &&\n\t\t\t     !locsol->VectorStrictIn (p, t2a))\n\t\t\t    ||\n\t\t\t    (locsol->VectorIn (p, t2b) &&\n\t\t\t     !locsol->VectorStrictIn (p, t2b));\n\t\t\t  */\n\n                          if (isface)\n                            cnts++;\n\t\t\t}\n\t\t      if (cnts < 2) isedge = 0;\n\t\t    }\n\t\t  \n\t\t  if (isedge)\n\t\t    {\n#ifdef DEVELOP\n\t\t      *testout << \"success\" << endl;\n#endif\n\t\t      int spi = -1;\n\t\t      \n\t\t      const double searchradius = 1e-4*geomsize;//1e-5*geomsize;\n\t\t      searchtree.GetIntersecting (apoints[i]-Vec3d(searchradius,searchradius,searchradius), \n\t\t\t\t\t\t  apoints[i]+Vec3d(searchradius,searchradius,searchradius), \n\t\t\t\t\t\t  locsearch);\n\t\t      \n\t\t      for (int m = 0; m < locsearch.Size(); m++)\n\t\t\t{\n\t\t\t  if (Dist2 (specpoints[locsearch[m]].p, apoints[i]) < sqr(1e-8*geomsize)\n\t\t\t      && Abs2(specpoints[locsearch[m]].v - t) < 1e-8)\n\t\t\t    {\n\t\t\t      spi = locsearch[m];\n\t\t\t      break;\n\t\t\t    }\n\t\t\t}\n\t\t      \n\t\t      \n\t\t      if (spi == -1)\n\t\t\t{\n\t\t\t  specpoints.Append (SpecialPoint());\n                          spi = specpoints.Size()-1;\n\t\t\t  specpoint2point.Append (i);\n\t\t\t  specpoints.Last().unconditional = 0;\n\t\t\t  searchtree.Insert (apoints[i], spi);\n\t\t\t}\n\n\t\t      if(!specpoints[spi].unconditional)\n\t\t\t{\n\t\t\t  specpoints[spi].p = apoints[i];\n\t\t\t  specpoints[spi].v = t;\n\t\t\t  //if (surfind.Size() >= 3)\n\t\t\t  if (num_indep_surfs >= 3)\n\t\t\t    specpoints[spi].unconditional = 1;\n\t\t\t  specpoints[spi].s1 = rep_surfind[j];\n\t\t\t  specpoints[spi].s2 = rep_surfind[k];\n\t\t\t  specpoints[spi].s1_orig = surfind[j];\n\t\t\t  specpoints[spi].s2_orig = surfind[k];\n\t\t\t  specpoints[spi].layer = apoints[i].GetLayer();\n\t\t\t  for (int up = 0; up < geometry->GetNUserPoints(); up++)\n\t\t\t    if (Dist (geometry->GetUserPoint(up), apoints[i]) < 1e-8*geomsize)\n\t\t\t      specpoints[spi].unconditional = 1;\n\t\t\t  for (int ip = 0; ip < geometry->GetNIdentPoints(); ip++)\n\t\t\t    if (Dist (geometry->GetIdentPoint(ip), apoints[i]) < 1e-8*geomsize)\n\t\t\t      specpoints[spi].unconditional = 1;\n\t\t\t}\n\t\t    }\n\t\t  \n\t\t}\n\t  }\n      }\n\n\n    \n    // if special point is unconditional on some solid,\n    // it must be unconditional everywhere:\n\n    BitArray uncond (apoints.Size());\n    uncond.Clear();\n\n    for (int i = 0; i < specpoints.Size(); i++)\n      if (specpoints[i].unconditional)\n\tuncond.SetBit (specpoint2point[i]);\n  \n    for (int i = 0; i < specpoints.Size(); i++)\n      specpoints[i].unconditional = uncond.Test (specpoint2point[i]);\n  }\n}\n"
  },
  {
    "path": "libsrc/csg/specpoin.hpp",
    "content": "#ifndef FILE_SPECPOIN\n#define FILE_SPECPOIN\n\n\n/**************************************************************************/\n/* File:   specpoin.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  // extern DLL_HEADER MeshingParameters mparam;\n\n  /*\n\n  Special Point Calculation\n  \n  */\n\n  class Surface;\n  class Solid;\n\n  /// Special point.\n  class SpecialPoint\n  {\n  public:\n    /// coordinates\n    Point<3> p;\n    /// tangential to edge\n    Vec<3> v;\n    ///\n    int layer;\n    /// point must be used in mesh \n    bool unconditional; \n\n    /// surfaces defining edge \n    int s1, s2;\n    /// if s1 and s2 are only representatives, then these are the original indices\n    int s1_orig, s2_orig;\n    int nr;\n    ///\n    SpecialPoint () : p(0,0,0), v(0,0,0), layer(0), unconditional(0), s1(0), s2(0), s1_orig(0), s2_orig(0)\n    { ; }\n\n    ///\n    SpecialPoint (const SpecialPoint & sp2);\n\n    ///\n    SpecialPoint & operator= (const SpecialPoint & sp2);\n  \n    ///\n    void Print (ostream & str) const;\n\n\n    int GetLayer() const { return layer; }\n\n    ///\n    bool HasSurfaces (int as1, int as2) const\n    {\n      return ( (s1 == as1 && s2 == as2) || (s1 == as2 && s2 == as1) );\n    }\n  };\n\n  inline ostream & operator<< (ostream & ost, const SpecialPoint & sp)\n  {\n    sp.Print (ost);\n    return ost;\n  }\n\n\n\n\n  ///\n  class SpecialPointCalculation\n  {\n  private:\n    ///\n    const CSGeometry * geometry;\n    ///\n    NgArray<MeshPoint> * points;\n    ///\n    NgArray<long int> boxesinlevel;\n\n    ///\n    double size;\n    ///\n    double relydegtest;   // maximal dimension of bisection interval for\n    /// test of degeneration parameters\n    double cpeps1, epeps1, epeps2, epspointdist2;\n\n    double ideps;\n\n  public: \n\n    ///\n    SpecialPointCalculation (); \n  \n    ///\n    void SetIdEps(const double epsin) {ideps = epsin;}\n\n    ///\n    void CalcSpecialPoints (const CSGeometry & ageometry, \n\t\t\t    NgArray<MeshPoint> & points);\n    ///\n    void AnalyzeSpecialPoints (const CSGeometry & geometry, \n\t\t\t       NgArray<MeshPoint> & points, \n\t\t\t       NgArray<SpecialPoint> & specpoints);\n\n  protected:\n    ///\n    void CalcSpecialPointsRec (const Solid * sol, int layer,\n\t\t\t       const BoxSphere<3> & box, \n\t\t\t       int level, \n\t\t\t       bool calccp, bool calcep);\n\n\n    ///\n    bool CrossPointNewtonConvergence (const Surface * f1, const Surface * f2, \n\t\t\t\t      const Surface * f3, const BoxSphere<3> & box);  \n    ///\n    bool CrossPointDegenerated (const Surface * f1, const Surface * f2,\n\t\t\t\tconst Surface * f3, const BoxSphere<3> & box) const;\n    ///\n    void CrossPointNewton (const Surface * f1, const Surface * f2, \n\t\t\t   const Surface * f3, Point<3> & p);\n  \n    bool EdgeNewtonConvergence (const Surface * f1, const Surface * f2, \n\t\t\t\tconst Point<3> & p);  \n    ///\n    bool EdgeDegenerated (const Surface * f1, const Surface * f2,\n\t\t\t  const BoxSphere<3> & box) const;\n    ///\n    void EdgeNewton (const Surface * f1, const Surface * f2, \n\t\t     Point<3> & p);\n    ///\n    bool IsEdgeExtremalPoint (const Surface * f1, const Surface * f2, \n\t\t\t      const Point<3> & p, Point<3> & pp, double rad);\n\n\n\n    /*\n   ///\n   bool ExtremalPointPossible (const Surface * f1, const Surface * f2, \n   int dir, const BoxSphere<3> & box);\n   ///\n   bool ExtremalPointDegenerated (const Surface * f1, const Surface * f2, \n   int dir, const BoxSphere<3> & box);\n   ///\n   bool ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2, \n   int dir, const BoxSphere<3> & box);\n    */\n    ///\n    void ExtremalPointNewton (const Surface * f1, const Surface * f2, \n\t\t\t      int dir, Point<3> & p);\n\n\n    ///\n    bool AddPoint (const Point<3> & p, int layer);\n\n    void ComputeExtremalPoints (const Plane * plane, \n\t\t\t\tconst QuadraticSurface * quadric, \n\t\t\t\tNgArray<Point<3> > & pts);\n\n    void ComputeExtremalPoints (const Sphere * sphere1, \n\t\t\t\tconst Sphere * sphere2, \n\t\t\t\tNgArray<Point<3> > & pts);\n\n    bool ComputeExtremalPoints (const RevolutionFace * rev1, \n\t\t\t\tconst RevolutionFace * rev2, \n\t\t\t\tNgArray<Point<3> > & pts);\n\n    void ComputeCrossPoints (const Plane * plane1, \n\t\t\t     const Plane * plane2, \n\t\t\t     const Plane * plane3, \n\t\t\t     NgArray<Point<3> > & pts);\n\n    void ComputeCrossPoints (const Plane * plane1, \n\t\t\t     const Plane * plane2, \n\t\t\t     const QuadraticSurface * quadratic, \n\t\t\t     NgArray<Point<3> > & pts);\n\n    void ComputeCrossPoints (const Sphere * sphere1, \n\t\t\t     const Sphere * sphere2, \n\t\t\t     const Sphere * sphere3, \n\t\t\t     NgArray<Point<3> > & pts);\n  };\n\n}\n\n#endif\n\n\n"
  },
  {
    "path": "libsrc/csg/spline3d.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\nsplinesegment3d :: splinesegment3d (const Point<3> & ap1, const Point<3> & ap2, \n\t\t\t\t    const Point<3> & ap3)\n{\n  p1 = ap1;\n  p2 = ap2;\n  p3 = ap3;\n}\n\n\n/*\n  todo\n  Tip von Joerg Stiller:\n  setzt Du in \n  void splinesegment3d :: Evaluate\n  Zeilen 54 und 56\n  b2 = 2 * t * (1-t);\n  b2 /= sqrt(2);\n  Das heisst, Du wichtest das zweite Bersteinpolynom mit \n  w2 = 1 / sqrt(2);\n  Das ist aber nur fuer 45-Grad-Segmente korrekt. Fuer den\n  allgemeinen Fall funktioniert\n  w2 = ( e(p3 - p1), e(p2 - p1) );  // also cos(winkel(p3-p1, p2-p1))\n  bzw. schoen symmetrisch\n  w2 = ( e(p3 - p1), e(p2 - p1) )/2 + ( e(p1 - p3), e(p2 - p3) )/2;\n  Das ist natuerlich kein C++ Code sondern symbolisch, wobei\n  e(p3 - p1)    ist der von p1 zu p3 zeigende Einheitsvektor und\n  (a, b)        steht fuer das Skalarprodukt zweier Vektoren etc.\n\n  Eine vergleichbare Information steht auch irgendwo im Hoscheck & Lasser.\n  Ich habe das Buch aber eben nicht zur Hand.\n*/\n\nvoid splinesegment3d :: Evaluate (double t, Point<3> & p) const\n{\n  double x, y, z, w;\n  double b1, b2, b3;\n\n  b1 = (1-t)*(1-t);\n  b2 = 2 * t * (1-t);\n  b3 = t * t;\n\n  b2 /= sqrt(double(2));\n\n  x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3;\n  y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3;\n  z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3;\n  w = b1 + b2 + b3;\n\n  p(0) = x / w;\n  p(1) = y / w;\n  p(2) = z / w;\n}\n\nvoid splinesegment3d :: EvaluateTangent (double t, Vec<3> & tang) const\n{\n  double x, y, z, w, xprime, yprime, zprime, wprime;\n  double b1, b2, b3, b1prime, b2prime, b3prime;\n\n  b1 = (1-t)*(1-t);\n  b2 = 2 * t * (1-t);\n  b3 = t * t;\n  b2 /= sqrt(double(2));\n\n  b1prime = 2 * t - 2;\n  b2prime = - 4 * t + 2;\n  b3prime = 2 * t;\n  b2prime /= sqrt(double(2));\n\n \n  x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3;\n  y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3;\n  z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3;\n  w = b1 + b2 + b3;\n\n  xprime = p1(0) * b1prime + p2(0) * b2prime + p3(0) * b3prime;\n  yprime = p1(1) * b1prime + p2(1) * b2prime + p3(1) * b3prime;\n  zprime = p1(2) * b1prime + p2(2) * b2prime + p3(2) * b3prime;\n  wprime = b1prime + b2prime + b3prime;\n\n  tang(0) = (w * xprime - x * wprime) / (w * w);\n  tang(1) = (w * yprime - y * wprime) / (w * w);\n  tang(2) = (w * zprime - z * wprime) / (w * w);\n}\n \n\nvoid spline3d :: AddSegment (const Point<3> & ap1, const Point<3> & ap2, \n\t\t\t     const Point<3> & ap3)\n{\n  segments.Append (new splinesegment3d (ap1, ap2, ap3));\n}\n\nvoid spline3d :: Evaluate (double t, Point<3> & p) const\n{\n  int nr;\n  double loct;\n  static int cnt = 0;\n  \n  cnt++;\n  if (cnt % 10000 == 0) (*mycout) << \"Evaluate calls: \" << cnt << endl;\n\n  while (t < 0) t += GetNumSegments();\n  while (t >= GetNumSegments()) t -= GetNumSegments();\n  nr = 1 + int (t);\n  loct = t - nr + 1;\n  segments.Get(nr)->Evaluate (loct, p);\n}\n  \nvoid spline3d :: EvaluateTangent (double t, Vec<3> & tang) const\n{\n  int nr;\n  double loct;\n\n  while (t < 0) t += GetNumSegments();\n  while (t >= GetNumSegments()) t -= GetNumSegments();\n  nr = 1 + int (t);\n  loct = t - nr + 1;\n  segments.Get(nr)->EvaluateTangent (loct, tang);\n}\n\n\ndouble spline3d :: ProjectToSpline (Point<3> & p) const\n{\n  double t, tl, tu, dt, dist, mindist, optt(0);\n  Point<3> hp;\n  Vec<3> tanx, px;\n  \n  dt = 0.01;\n  mindist = 0;\n  for (t = 0; t <= GetNumSegments() + dt/2; t += dt)\n    {\n      Evaluate (t, hp);\n      dist = Dist (hp, p);\n      if (t == 0 || dist < mindist)\n\t{\n\t  optt = t;\n\t  mindist = dist;\n\t} \n    }\n\n  \n  tu = optt + dt;\n  tl = optt - dt;\n  while (tu - tl > 1e-2)\n    {\n      optt = 0.5 * (tu + tl);\n      Evaluate (optt, hp);\n      EvaluateTangent (optt, tanx);\n      if (tanx * (hp - p) > 0)\n\ttu = optt;\n      else\n\ttl = optt;\n    } \n\n  optt = 0.5 * (tu + tl);\n\n  optt = ProjectToSpline (p, optt);\n  return optt;\n}\n \n \ndouble spline3d :: ProjectToSpline (Point<3> & p, double optt) const\n{ \n  double tl, tu, dt, val, dval, valu, vall;\n  Point<3> hp;\n  Vec<3> tanx, px;\n  int its = 0;\n  int cnt = 1000;\n  do\n    {\n      dt = 1e-8;\n      tl = optt - dt;\n      tu = optt + dt;\n    \n      EvaluateTangent (optt, tanx); \n      Evaluate (optt, hp);\n      px = hp - p;\n      val =  px * tanx;\n    \n      EvaluateTangent (tl, tanx); \n      Evaluate (tl, hp);\n      px = hp - p;\n      vall =  px * tanx;\n    \n      EvaluateTangent (tu, tanx); \n      Evaluate (tu, hp);\n      px = hp - p;\n      valu =  px * tanx;\n    \n      dval = (valu - vall) / (2 * dt);\n\n      if (its % 100 == 99)    \n\t(*testout) << \"optt = \" << optt \n\t\t   << \" val = \" << val \n\t\t   << \" dval = \" << dval << endl;\n      optt -= val / dval;\n      its++;\n      if (fabs(val) < 1e-8 && cnt > 5) cnt = 5;\n      cnt--;\n    }\n  while (cnt > 0);\n        \n  Evaluate (optt, p);\n  return optt;\n}\n  \n  \nsplinetube :: splinetube (const spline3d & amiddlecurve, double ar)\n  : Surface(), middlecurve (amiddlecurve), r(ar)\n{\n  (*mycout) << \"Splinetube Allocated, r = \" << r << endl;\n\n}\n  \nvoid splinetube :: DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t\t  const Point<3> & ap2)\n{\n  double t;\n  double phi, z;\n  \n  p1 = ap1;\n  p2 = ap2;\n  cp = p1;\n  t = middlecurve.ProjectToSpline (cp);\n  ex = p1 - cp;\n  middlecurve.EvaluateTangent (t, ez); \n  ex.Normalize();\n  ez.Normalize();\n  ey = Cross (ez, ex);\n  \n  phi = r * atan2 (ey * (p2-cp), ex * (p2-cp));\n  z = ez * (p2 - cp); \n  e2x(0) = phi;\n  e2x(1) = z;\n  e2x.Normalize();\n  e2y(1) = e2x(0);\n  e2y(0) = -e2x(1);\n  \n  //  (*testout) << \"Defineplane: \" << endl\n  //  \t<< \"p1 = \" << p1 << \"   p2 = \" << p2 << endl\n  //  \t<< \"pc = \" << cp << endl\n  //  \t<< \"ex = \" << ex << \" ey = \" << ey << \" ez = \" << ez << endl\n  //  \t<< \"phi = \" << phi << \"  z = \" << z << endl\n  //  \t<< \"e2x = \" << e2x << \" e2y = \" << e2y << endl;\n}\n  \nvoid splinetube :: ToPlane (const Point<3> & p3d, Point<2> & pplain, double h, \n\t\t\t    int & zone) const\n{\n  Vec<2> v;\n  v(0) = r * atan2 (ey * (p3d-cp), ex * (p3d-cp));\n  v(1) = ez * (p3d - cp); \n  zone = 0;\n  if (v(0) > r * 2) zone = 1;\n  if (v(0) < r * 2) zone = 2;\n  \n  pplain(0) = (v * e2x) / h;\n  pplain(1) = (v * e2y) / h;\n}\n  \nvoid splinetube :: FromPlane (const Point<2> & pplain, Point<3> & p3d, double h) const\n{\n  Vec<2> v;\n  \n  v(0) = pplain(0) * h * e2x(0) + pplain(1) * h * e2y(0);\n  v(1) = pplain(0) * h * e2x(1) + pplain(1) * h * e2y(1);\n  \n  p3d = p1 + v(0) * ey + v(1) * ez;\n\n  Project (p3d);\n}\n  \nvoid splinetube :: Project (Point<3> & p3d) const\n{\n  Point<3> hp;\n  \n  hp = p3d;\n  middlecurve.ProjectToSpline (hp);\n  \n  p3d = hp + (r / Dist(p3d, hp)) * (p3d - hp); \n}\n\n\n\ndouble splinetube :: CalcFunctionValue (const Point<3> & point) const\n{\n  Point<3> hcp;\n  double rad;\n\n  hcp = point;\n  middlecurve.ProjectToSpline (hcp);\n  rad = Dist (hcp, point);\n  return 0.5 * (rad * rad / r - r);\n}\n  \nvoid splinetube :: CalcGradient (const Point<3> & point, Vec<3> & grad) const\n{\n  Point<3> hcp;\n\n  hcp = point;\n  middlecurve.ProjectToSpline (hcp);\n\n  grad = point - hcp;\n  grad /= r;\n}\n  \n  \n\n\nPoint<3> splinetube :: GetSurfacePoint () const\n{\n  Point<3> p;\n  Vec<3> t, n;\n  \n  middlecurve.Evaluate (0, p);\n  middlecurve.EvaluateTangent (0, t);\n  n = t.GetNormal ();\n  n *= r;\n  (*mycout) << \"p = \" << p << \" t = \" << t << \"  n = \" << n << endl;\n  return p + n;\n}\n\nvoid splinetube :: Print (ostream & str) const\n{\n  int i;\n  str << \"SplineTube, \" \n      << middlecurve.GetNumSegments () << \" segments, r = \" << r << endl;\n  for (i = 1; i <= middlecurve.GetNumSegments(); i++)\n    str << middlecurve.P1(i) << \" - \" \n\t<< middlecurve.P2(i) << \" - \" \n\t<< middlecurve.P3(i) << endl;\n}\n\n\nint splinetube :: BoxInSolid (const BoxSphere<3> & box) const\n  // 0 .. no, 1 .. yes, 2 .. maybe\n{\n  Point<3> pc = box.Center();\n  middlecurve.ProjectToSpline (pc);\n  double d = Dist (pc, box.Center());\n  \n  if (d < r - box.Diam()/2) return 1;\n  if (d > r + box.Diam()/2) return 0;\n  return 2;\n}\n}\n"
  },
  {
    "path": "libsrc/csg/spline3d.hpp",
    "content": "namespace netgen\n{\n\n  ///\n  class splinesegment3d\n  {\n    ///\n    Point<3> p1, p2, p3;\n  \n  public:\n    ///\n    splinesegment3d (const Point<3> & ap1, const Point<3> & ap2, \n\t\t     const Point<3> & ap3);\n    ///\n    void Evaluate (double t, Point<3> & p) const;\n    ///\n    void EvaluateTangent (double t, Vec<3> & tang) const;\n    ///\n    const Point<3> & P1() const { return p1; }\n    ///\n    const Point<3> & P2() const { return p2; }\n    ///\n    const Point<3> & P3() const { return p3; }\n  };\n\n  ///\n  class spline3d\n  {\n    ///\n    NgArray<splinesegment3d *> segments;\n  \n  public:\n    ///\n    spline3d () { };\n    ///\n    void AddSegment (const Point<3> & ap1, const Point<3> & ap2, const Point<3> & ap3);\n    ///\n    int GetNumSegments () const { return segments.Size(); }\n    ///\n    double ProjectToSpline (Point<3> & p) const;\n    ///\n    double ProjectToSpline (Point<3> & p, double t) const;\n    ///\n    void Evaluate (double t, Point<3> & p) const;\n    ///\n    void EvaluateTangent (double t, Vec<3> & tang) const;\n    ///\n    const Point<3> & P1(int i) const { return segments.Get(i)->P1(); }\n    ///\n    const Point<3> & P2(int i) const { return segments.Get(i)->P2(); }\n    ///\n    const Point<3> & P3(int i) const { return segments.Get(i)->P3(); }\n  };\n  \n  ///\n  class splinetube : public Surface\n  {\n    ///\n    const spline3d & middlecurve;\n    ///\n    double r;\n    ///  Vec<3> ex, ey, ez;\n    Vec<2> e2x, e2y;\n    ///\n    Point<3> cp;\n  \n  public:\n    ///\n    splinetube (const spline3d & amiddlecurve, double ar);\n  \n    ///\n    virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2);\n    ///\n    virtual void ToPlane (const Point<3> & p, Point<2> & pplain, double h, int & zone) const;\n    ///\n    virtual void FromPlane (const Point<2> & pplain, Point<3> & p, double h) const;\n    ///\n    virtual void Project (Point<3> & p) const;\n\n    //  virtual int RootInBox (const box3d & box) const { return 0; }\n    /// 0 .. no, 1 .. yes, 2 .. maybe\n\n    virtual int BoxInSolid (const BoxSphere<3> & box) const;\n    /// 0 .. no, 1 .. yes, 2 .. maybe\n\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    ///\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    ///\n    virtual double HesseNorm () const { return 0.5 / r; }\n    ///\n    virtual Point<3> GetSurfacePoint () const;\n    ///\n    virtual void Print (ostream & str) const;\n  };  \n\n\n}\n\n"
  },
  {
    "path": "libsrc/csg/splinesurface.cpp",
    "content": "\n#include <csg.hpp>\n#include <core/register_archive.hpp>\n\nnamespace netgen\n{\nvoid SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const bool hpref)\n{\n  auto pp = p;\n  Project(pp);\n  geompoints.Append(GeomPoint<3>(pp,reffac));\n  geompoints.Last().hpref = hpref;\n}\n  \n  void SplineSurface :: AppendSegment(shared_ptr<SplineSeg<3>> sp, string & bcname, double amaxh)\n  {\n    splines.Append(sp);\n    bcnames.Append(bcname);\n    maxh.Append(amaxh);\n  }\n\n  string SplineSurface :: GetBCNameOf (Point<3> p1, Point<3> p2) const\n  {\n    \n    for(int i=0; i<splines.Size(); i++)\n      {\n\tauto pp1 = Point<3>(splines[i]->GetPoint(0));\n\tProject(pp1);\n\tauto pp2 = Point<3>(splines[i]->GetPoint(1));\n\tProject(pp2);\n        double eps = (p1-p2).Length() * 1e-4;\n\tif (((pp1-p1).Length()<eps && (pp2-p2).Length() < eps) || ((pp1-p2).Length() < eps && (pp2-p1).Length() < eps))\n\t  {\n\t    return bcnames[i];\n\t  }\n      }\n    return \"default\";\n  }\n\n  const shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> SplineSurface :: CreateCuttingSurfaces()\n  {\n    if(all_cuts)\n      return all_cuts;\n    auto cuttings = make_shared<NgArray<shared_ptr<OneSurfacePrimitive>>>();\n    for (auto cut : *cuts)\n      cuttings->Append(cut);\n    for(int i = 0; i<splines.Size(); i++)\n      {\n\tauto spline = splines[i];\n\tauto lineseg = dynamic_cast<LineSeg<3>*>(spline.get());\n        if(lineseg)\n          {\n            auto p1 = Point<3>(spline->GetPoint(0));\n            Project(p1);\n            auto p2 = Point<3>(spline->GetPoint(1));\n            Project(p2);\n            auto vec = Vec<3>(p2)-Vec<3>(p1);\n            auto plane = make_shared<Plane>(p1,-Cross(vec,baseprimitive->GetNormalVector(p1)));\n            if(maxh[i]>0)\n              {\n                plane->SetMaxH(maxh[i]);\n              }\n            cuttings->Append(plane);\n          }\n        else\n          {\n            auto spline3 = dynamic_cast<SplineSeg3<3>*>(spline.get());\n            if(spline3)\n              {\n                auto p1 = Point<3>(spline3->StartPI());\n                Project(p1);\n                auto p2 = Point<3>(spline3->TangentPoint());\n                Project(p2);\n                auto p3 = Point<3>(spline3->EndPI());\n                Project(p3);\n                Vec<3> v1 = p2-p1;\n                Vec<3> v2 = p2-p3;\n                Point<3> mid = p1 - v2;\n                cout << \"mid point = \" << mid << endl;\n                cout << \"v1 = \" << v1 << endl;\n                cout << \"v2 = \" << v2 << endl;\n                auto cyl = make_shared<EllipticCylinder>(mid, v1, v2);\n                if(maxh[i] > 0)\n                  cyl->SetMaxH(maxh[i]);\n                cuttings->Append(cyl);\n              }\n            else\n              throw NgException(\"Spline type not implemented for SplineSurface!\");\n          }\n      }\n    all_cuts = cuttings;\n    return cuttings;\n  }\n  \n  void SplineSurface :: Print(ostream & str) const\n{\n  str << \"SplineSurface with base \" << *baseprimitive << endl;\n}\n\n  static RegisterClassForArchive<SplineSurface, OneSurfacePrimitive> regss;\n}\n"
  },
  {
    "path": "libsrc/csg/splinesurface.hpp",
    "content": "#ifndef FILE_SPLINESURFACE\n#define FILE_SPLINESURFACE\n\n\nnamespace netgen\n{\n  class SplineSurface  : public  OneSurfacePrimitive\n  {\n  protected:\n    NgArray<GeomPoint<3>> geompoints;\n    NgArray<shared_ptr<SplineSeg<3>>> splines;\n    NgArray<string> bcnames;\n    NgArray<double> maxh;\n    shared_ptr<OneSurfacePrimitive> baseprimitive;\n    shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> cuts;\n    shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> all_cuts;\n    \n  public:\n    SplineSurface(shared_ptr<OneSurfacePrimitive> abaseprimitive, shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> acuts) :\n      OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts)\n    { ; }\n    // default constructor for archive\n    SplineSurface() {}\n    virtual ~SplineSurface() { ; }\n    \n    const auto & GetSplines() const { return splines; }\n    int GetNSplines() const { return splines.Size(); }\n    const NgArray<GeomPoint<3>>& GetPoints() const { return geompoints; }\n    string GetSplineType(const int i) const { return splines[i]->GetType(); }\n    SplineSeg<3> & GetSpline(const int i) { return *splines[i]; }\n    const SplineSeg<3> & GetSpline(const int i) const { return *splines[i]; }\n    int GetNP() const { return geompoints.Size(); }\n    const GeomPoint<3> & GetPoint(int i) const { return geompoints[i]; }\n    string GetBCName(int i) const { return bcnames[i]; }\n    string GetBCNameOf(Point<3> p1, Point<3> p2) const;\n    \n    DLL_HEADER void AppendPoint(const Point<3> & p, const double reffac = 1., const bool hpref=false);\n    void AppendSegment(shared_ptr<SplineSeg<3>> spline, string & bcname, double amaxh = -1);\n\n    const shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> CreateCuttingSurfaces();\n    const shared_ptr<NgArray<shared_ptr<OneSurfacePrimitive>>> GetCuts() const { return all_cuts; }\n    const shared_ptr<OneSurfacePrimitive> GetBase() const { return baseprimitive; }\n    \n    virtual void Project (Point<3> & p3d) const { baseprimitive->Project(p3d); }\n    virtual double CalcFunctionValue (const Point<3> & point) const\n    { return baseprimitive->CalcFunctionValue (point); }\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const\n    { baseprimitive->CalcGradient (point,grad); }\n    virtual double HesseNorm () const\n    { return baseprimitive->HesseNorm(); }\n    virtual Point<3> GetSurfacePoint () const\n    { return baseprimitive->GetSurfacePoint(); }\n    virtual void CalcSpecialPoints(NgArray<Point<3>> & pts) const\n    { baseprimitive->CalcSpecialPoints(pts); }\n\n    virtual INSOLID_TYPE BoxInSolid(const BoxSphere<3> & box) const\n    { return baseprimitive->BoxInSolid(box); }\n\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & geompoints & splines & bcnames & maxh & baseprimitive & cuts & all_cuts;\n    }\n    \n    /*\n    virtual void Project (Point<3> & p3d) const;\n    virtual double CalcFunctionValue (const Point<3> & point) const;\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const;\n    virtual double HesseNorm () const;\n    virtual Point<3> GetSurfacePoint () const;\n    virtual void CalcSpecialPoints(NgArray<Point<3>> & pts) const;\n\n    virtual INSOLID_TYPE BoxInSolid(const BoxSphere<3> & box) const;\n\n    */\n    \n    virtual void Print (ostream & str) const;\n    \n    \n  };\n\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/surface.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n#include <myadt.hpp>\n#include <csg.hpp>\n\n#include <linalg.hpp>\n#include <meshing.hpp>\n\n\nnamespace netgen\n{\nSurface :: Surface ()\n{\n  maxh = 1e10;\n  name = new char[7];\n  strcpy (name, \"noname\");\n  bcprop = -1;\n  bcname = \"default\";\n  inverse = false;\n}\n\nSurface :: ~Surface()\n{\n  delete [] name;\n}\n\n\nvoid Surface :: SetName (const char * aname)\n{\n  delete [] name;\n  name = new char[strlen (aname)+1];\n  strcpy (name, aname);\n}\n\n\nint Surface :: PointOnSurface (const Point<3> & p,\n\t\t\t       double eps) const\n{\n  double val = CalcFunctionValue (p);\n  return fabs (val) < eps;\n}\n\n\nvoid Surface :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const\n{\n  double dx = 1e-5;\n  Point<3> hp1, hp2;\n  Vec<3> g1, g2;\n\n  for (int i = 0; i < 3; i++)\n    {\n      hp1 = point;\n      hp2 = point;\n\n      hp1(i) += dx;\n      hp2(i) -= dx;\n\n      CalcGradient (hp1, g1);\n      CalcGradient (hp2, g2);\n      \t\n      for (int j = 0; j < 3; j++)\n\thesse(i, j) = (g1(j) - g2(j)) / (2 * dx);\n    }\n}\n  \n/*\nvoid Surface :: GetNormalVector (const Point<3> & p, Vec<3> & n) const\n{\n  CalcGradient (p, n);\n  n.Normalize();\n}\n*/\nVec<3> Surface :: GetNormalVector (const Point<3> & p) const\n{\n  Vec<3> n;\n  CalcGradient (p, n);\n  n.Normalize();\n  return n;\n}\n\nvoid Surface :: DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t       const Point<3> & ap2)\n{\n  p1 = ap1;\n  p2 = ap2;\n  \n  ez = GetNormalVector (p1);\n  ex = p2 - p1;\n  ex -= (ex * ez) * ez;\n  ex.Normalize();\n  ey = Cross (ez, ex);  \n}\n\nvoid Surface :: ToPlane (const Point<3> & p3d, Point<2> & pplane, \n\t\t\t double h, int & zone) const\n{\n  Vec<3> p1p, n;\n\n  n = GetNormalVector (p3d);\n  if (n * ez < 0)\n    {\n      zone = -1;\n      pplane(0) = 1e8;\n      pplane(1) = 1e9;\n      return;\n    }\n  \n  p1p = p3d - p1;\n  pplane(0) = (p1p * ex) / h;\n  pplane(1) = (p1p * ey) / h;\n  zone = 0;\n}\t\n\nvoid Surface :: FromPlane (const Point<2> & pplane, \n\t\t\t   Point<3> & p3d, double h) const \n{ \n  p3d = p1 \n    + (h * pplane(0)) * ex \n    + (h * pplane(1)) * ey;\n  \n  Project (p3d);\n}\n\nvoid Surface :: Project (Point<3> & p) const\n{\n  Vec<3> n;\n  double val;\n\n  for (int i = 1; i <= 10; i++)\n    {\n      val = CalcFunctionValue (p);\n      if (fabs (val) < 1e-12) return;\n\t\n      CalcGradient (p, n);\n      p -= (val / Abs2 (n)) * n;\n    }\n}\n\nvoid Surface :: SkewProject (Point<3> & p, const Vec<3> & direction) const\n{\n  Point<3> startp(p);\n  double t_old(0),t_new(1);\n  Vec<3> grad;\n  for(int i=0; fabs(t_old-t_new) > 1e-20 && i<15; i++)\n    {\n      t_old = t_new;\n      CalcGradient(p,grad);\n      t_new = t_old - CalcFunctionValue(p)/(grad*direction);\n      p = startp + t_new*direction;\n    }\n}\n\n\ndouble Surface :: MaxCurvature () const\n{ \n  return 0.5 * HesseNorm (); \n}\n\ndouble Surface :: \nMaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const\n{ \n  return MaxCurvature (); \n}\n              \n\n\ndouble Surface :: LocH (const Point<3> & p, double x, double c, \n                        const MeshingParameters & mparam,\n                        double hmax) const\n  // finds h <= hmax, s.t.  h * \\kappa_x*h < c\n{\n  /*\n    double h, hmin, kappa;\n    hmin = 0;\n  \n    while (hmin < 0.9 * hmax)\n    {\n    h = 0.5 * (hmin + hmax);\n    kappa = 2 * MaxCurvatureLoc (p, x * h);\n      \n    if (kappa * h >= c)\n    hmax = h;\n    else\n    hmin = h;\n    }\n    return h;\n  */\n\n  double hret;\n  double kappa = MaxCurvatureLoc (p, x*hmax);\n\n  kappa *= c *  mparam.curvaturesafety;\n  \n  if (hmax * kappa < 1)\n    hret = hmax;\n  else\n    hret = 1 / kappa;\n\n  if (maxh < hret)\n    hret = maxh;\n\n  return hret;\n}\n\n\n\n\nPrimitive :: Primitive ()\n{\n  surfaceids.SetSize (1);\n  surfaceactive.SetSize (1);\n  surfaceactive[0] = 1;\n}\n\nPrimitive :: ~Primitive()\n{\n  ;\n}\n\nint Primitive :: GetSurfaceId (int i) const\n{\n  return surfaceids[i];\n}\n\nvoid Primitive :: SetSurfaceId (int i, int id) \n{\n  surfaceids[i] = id;\n}\n\n\n\n\nvoid Primitive :: GetPrimitiveData (const char *& classname, \n\t\t\t\t    NgArray<double> & coeffs) const\n{\n  classname = \"undef\";\n  coeffs.SetSize (0);\n}\n\nvoid Primitive :: SetPrimitiveData (NgArray<double> & coeffs)\n{\n  ;\n}\n\nPrimitive * Primitive :: CreatePrimitive (const char * classname)\n{\n  if (strcmp (classname, \"sphere\") == 0)\n    return Sphere::CreateDefault();\n  if (strcmp (classname, \"plane\") == 0)\n    return Plane::CreateDefault();\n  if (strcmp (classname, \"cylinder\") == 0)\n    return Cylinder::CreateDefault();\n  if (strcmp (classname, \"cone\") == 0)\n    return Cone::CreateDefault();\n  if (strcmp (classname, \"brick\") == 0)\n    return Brick::CreateDefault();\n\n\n  stringstream ost;\n  ost << \"Primitive::CreatePrimitive not implemented for \" << classname << endl;\n  throw NgException (ost.str());\n}\n\n\nPrimitive * Primitive :: Copy () const\n{\n  stringstream ost;\n  ost << \"Primitive::Copy not implemented for \" << typeid(*this).name() << endl;\n  throw NgException (ost.str());\n}\n\n\nvoid Primitive :: Transform (Transformation<3> & trans)\n{\n  stringstream ost;\n  ost << \"Primitive::Transform not implemented for \" << typeid(*this).name() << endl;\n  throw NgException (ost.str());\n}\n\nvoid Primitive :: GetTangentialSurfaceIndices (const Point<3> & p, \n\t\t\t\t\t       NgArray<int> & surfind, double eps) const\n{\n  for (int j = 0; j < GetNSurfaces(); j++)\n    if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)\n      if (!surfind.Contains (GetSurfaceId(j)))\n\tsurfind.Append (GetSurfaceId(j));\n}\n\n\nvoid Primitive :: \nGetTangentialVecSurfaceIndices (const Point<3> & p, const Vec<3> & v,\n\t\t\t\tNgArray<int> & surfind, double eps) const\n{\n  cout << \"get tangvecsurfind not implemented\" << endl;\n  surfind.SetSize (0);\n}\n\nvoid Primitive :: \nGetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t\t\t NgArray<int> & surfind, double eps) const\n{\n  for (int j = 0; j < GetNSurfaces(); j++)\n    {\n      if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)\n\t{\n\t  Vec<3> grad;\n\t  GetSurface(j).CalcGradient (p, grad);\n\t  if (sqr (grad * v1) < 1e-6 * v1.Length2() * grad.Length2()  && \n\t      sqr (grad * v2) < 1e-6 * v2.Length2() * grad.Length2() )   // new, 18032006 JS\n\t    {\n\t      if (!surfind.Contains (GetSurfaceId(j)))\n\t\tsurfind.Append (GetSurfaceId(j));\n\t    }\n\t}\n    }\n}\n\n\n\n\nINSOLID_TYPE Primitive :: \nVecInSolid2 (const Point<3> & p,\n\t     const Vec<3> & v1,\n\t     const Vec<3> & v2,\n\t     double eps) const\n{\n  //(*testout) << \"Primitive::VecInSolid2\" << endl;\n  Point<3> hp = p + 1e-3 * v1 + 1e-5 * v2;\n\n  INSOLID_TYPE res = PointInSolid (hp, eps);\n  //  (*testout) << \"vectorin2, type = \" << typeid(*this).name() << \", res = \" << res << endl;\n\n  return res;\n}\n\nINSOLID_TYPE Primitive :: \nVecInSolid3 (const Point<3> & p,\n\t     const Vec<3> & v1,\n\t     const Vec<3> & v2,\n\t     double eps) const\n{\n  //(*testout) << \"Primitive::VecInSolid3\" << endl;\n  return VecInSolid (p, v1, eps);\n}\n\nINSOLID_TYPE Primitive :: \nVecInSolid4 (const Point<3> & p,\n\t     const Vec<3> & v,\n\t     const Vec<3> & v2,\n\t     const Vec<3> & m,\n\t     double eps) const\n{\n  return VecInSolid2 (p, v, m, eps);\n}\n\n\n\n\n\nOneSurfacePrimitive :: OneSurfacePrimitive()\n{\n  ;\n}\n\nOneSurfacePrimitive :: ~OneSurfacePrimitive()\n{\n  ;\n}\n\n\nINSOLID_TYPE OneSurfacePrimitive :: \nPointInSolid (const Point<3> & p,\n\t      double eps) const\n{\n  double hv1 = (GetSurface(0).CalcFunctionValue(p));\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n  return DOES_INTERSECT;\n}\n \n\nINSOLID_TYPE OneSurfacePrimitive :: \nVecInSolid (const Point<3> & p, const Vec<3> & v,\n\t    double eps) const\n{\n  double hv1 = (GetSurface(0).CalcFunctionValue(p));\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n\n  Vec<3> hv;\n  GetSurface(0).CalcGradient (p, hv);\n\n  hv1 = v * hv;\n\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n  return DOES_INTERSECT;\n}\n\n\nINSOLID_TYPE OneSurfacePrimitive :: \nVecInSolid2 (const Point<3> & p,\n\t     const Vec<3> & v1,\n\t     const Vec<3> & v2,\n\t     double eps) const\n{\n  double hv1 = (GetSurface(0).CalcFunctionValue(p));\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n  Vec<3> hv;\n\n  GetSurface(0).CalcGradient (p, hv);\n\n  hv1 = v1 * hv;\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n  double hv2 = v2 * hv;\n  if (hv2 <= -eps)\n    return IS_INSIDE;\n  if (hv2 >= eps)\n    return IS_OUTSIDE;\n  return DOES_INTERSECT;\n  \n  /*\n  double hv2 = v2 * hv;\n  if (hv2 <= 0)\n    return IS_INSIDE;\n  else\n    return IS_OUTSIDE;\n  */\n}\n  \n\n\nINSOLID_TYPE OneSurfacePrimitive :: \nVecInSolid3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,\n\t     double eps) const\n{\n  //(*testout) << \"OneSurfacePrimitive::VecInSolid3\" << endl;\n  double hv1 = (GetSurface(0).CalcFunctionValue(p));\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n  Vec<3> grad;\n  GetSurface(0).CalcGradient (p, grad);\n\n  hv1 = v * grad;\n  if (hv1 <= -eps) return IS_INSIDE;\n  if (hv1 >= eps) return IS_OUTSIDE;\n\n  Mat<3> hesse;\n  GetSurface(0).CalcHesse (p, hesse);\n\n  double hv2 = v2 * grad + v * (hesse * v);\n\n  if (hv2 <= -eps) return IS_INSIDE;\n  if (hv2 >= eps) return IS_OUTSIDE;\n\n  return DOES_INTERSECT;\n}\n\n\n\n\nINSOLID_TYPE OneSurfacePrimitive :: \nVecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,\n\t     const Vec<3> & m,\n\t     double eps) const\n{\n  double hv1 = (GetSurface(0).CalcFunctionValue(p));\n  if (hv1 <= -eps)\n    return IS_INSIDE;\n  if (hv1 >= eps)\n    return IS_OUTSIDE;\n\n  Vec<3> grad;\n  GetSurface(0).CalcGradient (p, grad);\n\n  hv1 = v * grad;\n  if (hv1 <= -eps) return IS_INSIDE;\n  if (hv1 >= eps) return IS_OUTSIDE;\n\n  Mat<3> hesse;\n  GetSurface(0).CalcHesse (p, hesse);\n\n  double hv2 = v2 * grad + v * (hesse * v);\n\n  if (hv2 <= -eps) return IS_INSIDE;\n  if (hv2 >= eps) return IS_OUTSIDE;\n\n\n  double hv3 = m * grad;\n  if (hv3 <= -eps) return IS_INSIDE;\n  if (hv3 >= eps) return IS_OUTSIDE;\n\n  return DOES_INTERSECT;\n}\n\n\n\n\n\n\n\nint OneSurfacePrimitive :: GetNSurfaces() const\n{\n  return 1;\n}\n\nSurface & OneSurfacePrimitive :: GetSurface (int i)\n{\n  return *this;\n}\n\nconst Surface & OneSurfacePrimitive :: GetSurface (int i) const\n{\n  return *this;\n}\n\n\n\n\n\n\nvoid ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp)\n{\n  Vec<2> rs, lam;\n  Vec<3> a1, a2;\n  Mat<2> a;\n\n  int i = 10;\n  while (i > 0)\n    {\n      i--;\n      rs(0) = f1 -> CalcFunctionValue (hp);\n      rs(1) = f2 -> CalcFunctionValue (hp);\n      f1->CalcGradient (hp, a1);\n      f2->CalcGradient (hp, a2);\n\n      double alpha = fabs(a1*a2)/sqrt(a1.Length2()*a2.Length2());\n      if(fabs(1.-alpha) < 1e-6)\n\t{\n\t  if(fabs(rs(0)) >= fabs(rs(1)))\n\t    f1 -> Project(hp);\n\t  else\n\t    f2 -> Project(hp);\n\t}\n      else\n\t{\n\n\t  a(0,0) = a1 * a1;\n\t  a(0,1) = a(1,0) = a1 * a2;\n\t  a(1,1) = a2 * a2;\n\t  \n\t  a.Solve (rs, lam);\n\n\t  hp -= lam(0) * a1 + lam(1) * a2;\n\t}\n\n      if (Abs2 (rs) < 1e-24 && i > 1) i = 1;\n    }\n}\n\nRegisterClassForArchive<Surface> regsurf;\nRegisterClassForArchive<Primitive> regprim;\nRegisterClassForArchive<OneSurfacePrimitive, tuple<Surface, Primitive>> regosf;\n}\n"
  },
  {
    "path": "libsrc/csg/surface.hpp",
    "content": "#ifndef FILE_SURFACE\n#define FILE_SURFACE\n\n/**************************************************************************/\n/* File:   surface.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   1. Dez. 95                                                     */\n/**************************************************************************/\n\n\nnamespace netgen \n{\n\n  class TriangleApproximation;\n\n\n  /**\n     Basis class for implicit surface geometry.\n     This class is used for generation of surface meshes\n     in NETGEN \n  */\n  class Surface\n  {\n  protected:\n    /// invert normal vector\n    bool inverse;\n    /// maximal h in surface\n    double maxh;\n    /// name of surface\n    char * name;\n    /// boundary condition nr\n    int bcprop;\n    /// boundary condition label\n    string bcname;\n  \n  public:\n    Surface ();\n    /** @name Tangential plane.\n\tThe tangential plane is used for surface mesh generation.\n    */\n  \n    virtual ~Surface();\n\n  protected:\n    /** @name Points in the surface defining tangential plane.\n\tTangential plane is taken in p1, the local x-axis\n\tis directed to p2.\n    */\n    //@{\n    ///\n    Point<3> p1;\n    ///\n    Point<3> p2;\n    //@}\n    /** @name Base-vectos for local coordinate system. */\n    //@{\n    /// in plane, directed p1->p2\n    Vec<3> ex;\n    /// in plane\n    Vec<3> ey;\n    /// outer normal direction\n    Vec<3> ez;\n    //@}\n  public:\n\n    virtual void DoArchive(Archive& archive)\n    {\n      archive & inverse & maxh & name & bcprop & bcname\n        & p1 & p2 & ex & ey & ez;\n    }\n\n    void SetName (const char * aname);\n    const char * Name () const { return name; }\n\n    //@{\n    /**\n       Defines tangential plane in ap1.\n       The local x-coordinate axis points to the direction of ap2 */\n    virtual void DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t\t\tconst Point<3> & ap2);\n\n    /// Transforms 3d point p3d to local coordinates pplane\n    virtual void ToPlane (const Point<3> & p3d, Point<2> & pplane, \n\t\t\t  double h, int & zone) const;\n  \n    /// Transforms point pplane in local coordinates to 3d point\n    virtual void FromPlane (const Point<2> & pplane, \n\t\t\t    Point<3> & p3d, double h) const;\n    //@}\n\n\n    /// Project point p onto surface (closest point)\n    virtual void Project (Point<3> & p) const;\n\n    /// Project along direction\n    virtual void SkewProject(Point<3> & p, const Vec<3> & direction) const;\n\n    /// Is current surface identic to surface 2 ?\n    virtual int IsIdentic (const Surface & /* s2 */, int & /* inv */, \n\t\t\t   double /* eps */) const\n    { return 0; }\n  \n    ///\n    virtual int PointOnSurface (const Point<3> & p,\n\t\t\t\tdouble eps = 1e-6) const;\n  \n\n    /** @name Implicit function.\n\tCalculate function value and derivatives.\n    */\n    //@{\n    /// Calculate implicit function value in point point\n    virtual double CalcFunctionValue (const Point<3> & point) const = 0;\n\n    /**\n       Calc gradient of implicit function.\n       gradient should be O(1) at surface\n    */\n    virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const = 0;\n\n    /**\n       Calculate second derivatives of implicit function.\n    */\n    virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const;\n\n    /**\n       Returns outer normal vector.\n    */\n    // virtual void GetNormalVector (const Point<3> & p, Vec<3> & n) const;\n    virtual Vec<3> GetNormalVector (const Point<3> & p) const;\n\n    /**\n       Upper bound for spectral norm of Hesse-matrix\n    */\n    virtual double HesseNorm () const = 0;\n\n    /**\n       Upper bound for spectral norm of Hesse-matrix in the\n       rad - environment of point c.\n    */\n    virtual double HesseNormLoc (const Point<3> & /* c */, \n\t\t\t\t double /* rad */) const\n    { return HesseNorm (); }\n    //@}\n\n\n    ///\n    virtual double MaxCurvature () const;\n    ///\n    virtual double MaxCurvatureLoc (const Point<3> & /* c */ , \n\t\t\t\t    double /* rad */) const;\n\n    /** Returns any point in the surface.\n\tNeeded to start surface mesh generation e.g. on sphere */\n    virtual Point<3> GetSurfacePoint () const = 0;\n\n    ///\n    bool Inverse () const { return inverse; }\n    ///\n    void SetInverse (bool ainverse) { inverse = ainverse; }\n    /// \n    virtual void Print (ostream & str) const = 0;\n  \n    ///\n    virtual void Reduce (const BoxSphere<3> & /* box */) { };\n    ///\n    virtual void UnReduce () { };\n\n    /// set max h in surface\n    void SetMaxH (double amaxh) { maxh = amaxh; }\n    ///\n    double GetMaxH () const { return maxh; }\n    ///\n    int GetBCProperty () const { return bcprop; }\n    ///\n    void SetBCProperty (int abc) { bcprop = abc; }\n\n    /** Determine local mesh-size.\n\tFind \n\t\\[ h \\leq hmax, \\]\n\tsuch that\n\t\\[ h  \\times \\kappa (x) \\leq c \\qquad \\mbox{in} B(x, h), \\]\n\twhere kappa(x) is the curvature in x. */\n    virtual double LocH (const Point<3> & p, double x, \n\t\t\t double c, \n                         const MeshingParameters & mparam,\n                         double hmax) const;\n\n    /**\n       Gets Approximation by triangles,\n       where qual is about the number of triangles per radius\n    */\n    virtual void GetTriangleApproximation (TriangleApproximation & /* tas */, \n\t\t\t\t\t   const Box<3> & /* boundingbox */, \n\t\t\t\t\t   double /* facets */ ) const { };\n\n\n    string GetBCName() const { return bcname; }\n\n    void SetBCName( string abc ) { bcname = abc; }\n  };\n\n\n  inline ostream & operator<< (ostream & ost, const Surface & surf)\n  {\n    surf.Print(ost);\n    return ost;\n  }\n\n\n\n  typedef enum { IS_OUTSIDE = 0, IS_INSIDE = 1, DOES_INTERSECT = 2}\n    INSOLID_TYPE;\n\n\n  class DummySurface : public Surface\n  {\n    virtual double CalcFunctionValue (const Point<3> & /* point */) const\n    { return 0; }\n\n    virtual void CalcGradient (const Point<3> & /* point */, Vec<3> & grad) const\n    { grad = Vec<3> (0,0,0); }\n  \n    virtual Point<3> GetSurfacePoint () const\n    { return Point<3> (0,0,0); }\n\n    virtual double HesseNorm () const\n    { return 0; }\n\n    virtual void Project (Point<3> & /* p */) const\n    { ; }\n\n    virtual void Print (ostream & ost) const\n    { ost << \"dummy surface\"; }\n  };\n\n\n\n  class Primitive\n  {\n  protected:\n    NgArray<int> surfaceids;\n    NgArray<int> surfaceactive;\n\n  public:\n\n    Primitive ();\n\n    virtual ~Primitive();\n\n    virtual void DoArchive(Archive& archive)\n    {\n      archive & surfaceids & surfaceactive;\n    }\n  \n    /*\n      Check, whether box intersects solid defined by surface.\n\n      return values:\n      0 .. box outside solid \\\\\n      1 .. box in solid \\\\\n      2 .. can't decide (allowed, iff box is close to solid)\n    */\n    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const = 0;\n    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t\t       double eps) const = 0;\n\n    virtual void GetTangentialSurfaceIndices (const Point<3> & p, \n\t\t\t\t\t      NgArray<int> & surfind, double eps) const;\n\n    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const = 0;\n\n    // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid\n    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    // checks if  p + s v1 + s*s/2 v2 is inside\n    virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    // like VecInSolid2, but second order approximation\n    virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      const Vec<3> & m,\n\t\t\t\t      double eps) const;\n\n    // for a point p in the surface, into which (closed) surfaces does v point into ? \n    virtual void GetTangentialVecSurfaceIndices (const Point<3> & p, const Vec<3> & v,\n\t\t\t\t\t\t NgArray<int> & surfind, double eps) const;\n\n    // a point p in the surface, and v a tangential vector\n    // for arbitrary small, but positive t consider q := Project(p+t*v)\n    // into which (closed) surfaces does v2 point into, when starting from q ?     \n    virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,\n\t\t\t\t\t\t  NgArray<int> & surfind, double eps) const;\n\n\n    virtual void CalcSpecialPoints (NgArray<Point<3> > & /* pts */) const { ; }\n    virtual void AnalyzeSpecialPoint (const Point<3> & /* pt */, \n\t\t\t\t      NgArray<Point<3> > & /* specpts */) const { ; }\n    virtual Vec<3> SpecialPointTangentialVector (const Point<3> & /* p */, \n\t\t\t\t\t\t int /* s1 */, int /* s2 */) const \n    { return Vec<3> (0,0,0); }\n\n  \n    virtual int GetNSurfaces() const = 0;\n    virtual Surface & GetSurface (int i = 0) = 0;\n    virtual const Surface & GetSurface (int i = 0) const = 0;\n\n    int GetSurfaceId (int i = 0) const;\n    void SetSurfaceId (int i, int id);\n    int SurfaceActive (int i) const { return surfaceactive[i]; }\n    virtual int SurfaceInverted (int /* i */ = 0) const { return 0; }\n\n    virtual void GetPrimitiveData (const char *& classname, \n\t\t\t\t   NgArray<double> & coeffs) const;\n    virtual void SetPrimitiveData (NgArray<double> & coeffs);\n    static Primitive * CreatePrimitive (const char * classname);\n\n\n    virtual void Reduce (const BoxSphere<3> & /* box */) { };\n    virtual void UnReduce () { };\n\n    virtual Primitive * Copy () const;\n    virtual void Transform (Transformation<3> & trans);\n  };\n\n\n\n\n  class OneSurfacePrimitive : public Surface, public Primitive\n  {\n  public:\n    OneSurfacePrimitive();\n    ~OneSurfacePrimitive();\n\n    virtual void DoArchive(Archive& archive)\n    {\n      Surface::DoArchive(archive);\n      Primitive::DoArchive(archive);\n    }\n\n    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,\n\t\t\t\t       double eps) const;\n    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,\n\t\t\t\t     const Vec<3> & v,\n\t\t\t\t     double eps) const;\n    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v1,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      double eps) const;\n\n    virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p,\n\t\t\t\t      const Vec<3> & v,\n\t\t\t\t      const Vec<3> & v2,\n\t\t\t\t      const Vec<3> & m,\n\t\t\t\t      double eps) const;\n\n    virtual int GetNSurfaces() const;\n    virtual Surface & GetSurface (int i = 0);\n    virtual const Surface & GetSurface (int i = 0) const;\n  };\n\n\n\n\n\n\n  /**\n     Projects point to edge.\n     The point hp is projected to the edge described by f1 and f2.\n     It is assumed that the edge is non-degenerated, and the\n     (generalized) Newton method converges.\n  */\n  extern void ProjectToEdge (const Surface * f1, \n\t\t\t     const Surface * f2,\n\t\t\t     Point<3> & hp);\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/triapprox.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n\n\nnamespace netgen\n{\n\n  TriangleApproximation :: TriangleApproximation ()\n  {\n    ;\n  }\n\n  int TriangleApproximation :: \n  AddTriangle (const TATriangle & tri, bool invert)\n  { \n    trigs.Append (tri);\n    if (invert)\n      {\n\ttrigs.Last()[1] = tri[2];\n\ttrigs.Last()[2] = tri[1];\n      }\n    return trigs.Size()-1;\n  }\n\n\n  void TriangleApproximation :: RemoveUnusedPoints ()\n  {\n    NgBitArray used(GetNP());\n    NgArray<int> map (GetNP());\n    int i, j;\n    int cnt = 0;\n\n    used.Clear();\n    for (i = 0; i < GetNT(); i++)\n      for (j = 0; j < 3; j++)\n\tused.Set (GetTriangle (i)[j]);\n\n    for (i = 0; i < GetNP(); i++)\n      if (used.Test(i))\n\tmap[i] = cnt++;\n  \n    for (i = 0; i < GetNT(); i++)\n      for (j = 0; j < 3; j++)\n\ttrigs[i][j] = map[trigs[i][j]];\n\n    for (i = 0; i < GetNP(); i++)\n      if (used.Test(i))\n\t{\n\t  points[map[i]] = points[i];\n\t  normals[map[i]] = normals[i];\n\t}\n\n    points.SetSize (cnt);\n    normals.SetSize (cnt);\n  }\n}\n"
  },
  {
    "path": "libsrc/csg/triapprox.hpp",
    "content": "#ifndef FILE_TRIAPPROX\n#define FILE_TRIAPPROX\n\n/**************************************************************************/\n/* File:   triapprox.hh                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   2. Mar. 98                                                    */\n/**************************************************************************/\n\n\nnamespace netgen\n{\n\n  /**\n     Triangulated approximation to true surface\n  */\n \n\n  class TATriangle\n  {\n    int pi[3];\n    int surfind;\n  public:\n    TATriangle () { ; }\n\n    TATriangle (int si, int pi1, int pi2, int pi3)\n    { surfind = si; pi[0] = pi1; pi[1] = pi2; pi[2] = pi3; }\n\n    int SurfaceIndex() const { return surfind; }\n    int & SurfaceIndex() { return surfind; }\n\n    int & operator[] (int i) { return pi[i]; }\n    const int & operator[] (int i) const { return pi[i]; }\n  };\n\n\n  class TriangleApproximation\n  {\n    NgArray<Point<3> > points;\n    NgArray<Vec<3> > normals;\n    NgArray<TATriangle> trigs;\n\n  public:\n    TriangleApproximation();\n    int GetNP () const { return points.Size(); }\n    int GetNT () const { return trigs.Size(); }\n\n    int AddPoint (const Point<3> & p) { points.Append (p); return points.Size()-1; }\n    int AddNormal (const Vec<3> & n) { normals.Append (n); return normals.Size()-1; }\n    int AddTriangle (const TATriangle & tri, bool invert = 0);\n\n    const Point<3> & GetPoint (int i) const { return points[i]; }\n    const TATriangle & GetTriangle (int i) const { return trigs[i]; }\n    const Vec<3> & GetNormal (int i) const { return normals[i]; }\n\n    void RemoveUnusedPoints ();\n\n    friend class CSGeometry;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/vscsg.cpp",
    "content": "#include <mystdlib.h>\n#include \"incopengl.hpp\"\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n\n#include <visual.hpp>\n\n#include \"vscsg.hpp\"\n\nnamespace netgen\n{\n\n\n\n  /* *********************** Draw Geometry **************** */\n\n  DLL_HEADER extern shared_ptr<Mesh> mesh;\n  DLL_HEADER extern NgArray<SpecialPoint> global_specpoints;\n  NgArray<SpecialPoint> & specpoints = global_specpoints;\n  \n  DLL_HEADER extern NgArray<Box<3> > boxes;\n\n\n\n\n  VisualSceneGeometry :: VisualSceneGeometry ()\n    : VisualScene()\n  {\n    selsurf = 0;\n  }\n\n  VisualSceneGeometry :: ~VisualSceneGeometry ()\n  {\n    ;\n  }\n\n  void VisualSceneGeometry :: SelectSurface (int aselsurf)\n  {\n    selsurf = aselsurf;\n    DrawScene();\n  }\n\n\n  void VisualSceneGeometry :: DrawScene ()\n  {  \n    if (changeval != geometry->GetChangeVal())\n      BuildScene();\n    changeval = geometry->GetChangeVal();\n\n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n  \n    SetLight();\n\n\n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n    SetClippingPlane ();\n\n    glShadeModel (GL_SMOOTH);\n    glDisable (GL_COLOR_MATERIAL);\n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n    glEnable (GL_BLEND);\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n    /*\n      float mat_spec_col[] = { 1, 1, 1, 1 };\n      glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col);\n    */\n\n    double shine = vispar.shininess;\n    double transp = vispar.transp;\n    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);\n    glLogicOp (GL_COPY);\n  \n    glEnable (GL_NORMALIZE);\n\n    for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)\n      {\n\tconst TopLevelObject * tlo = geometry -> GetTopLevelObject (i);\n\tif (tlo->GetVisible() && !tlo->GetTransparent())\n\t  {\n\t    float mat_col[] = { float(tlo->GetRed()), float(tlo->GetGreen()), \n\t\t\t\tfloat(tlo->GetBlue()), 1 };\n\t    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\t  \n\t    glCallList (trilists[i]);\n\t  }\n      }\n\n    glPolygonOffset (1, 1);\n    glEnable (GL_POLYGON_OFFSET_FILL);\n\n    glLogicOp (GL_NOOP);\n    for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)\n      {\n\tconst TopLevelObject * tlo = geometry -> GetTopLevelObject (i);\n\tif (tlo->GetVisible() && tlo->GetTransparent())\n\t  {\n\t    float mat_col[] = { float(tlo->GetRed()), float(tlo->GetGreen()), \n\t\t\t\tfloat(tlo->GetBlue()), float(transp) };\n\n\t    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\t  \n\t    glCallList (trilists[i]);\n\t  }\n      }\n\n    glDisable (GL_POLYGON_OFFSET_FILL);\n\n    glPopMatrix();\n    glDisable(GL_CLIP_PLANE0);\n \n\n\n    DrawCoordinateCross ();\n    DrawNetgenLogo ();  \n\n    glFinish();  \n  }\n\n\n  void VisualSceneGeometry :: BuildScene (int zoomall)\n  {\n    VisualScene::BuildScene(zoomall); // setting light ...\n    Box<3> box;\n    int hasp = 0;\n    for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)\n      {\n\tconst TriangleApproximation * ta =\n\t  geometry->GetTriApprox(i);\n\tif (!ta) continue;\n\n\tfor (int j = 0; j < ta->GetNP(); j++)      \n\t  {\n\t    if (hasp)\n\t      box.Add (ta->GetPoint(j));\n\t    else\n\t      {\n\t\thasp = 1;\n\t\tbox.Set (ta->GetPoint(j));\n\t      }\n\t  }\n      }\n    if (hasp)\n      {\n\tcenter = box.Center();\n\trad = box.Diam() / 2;\n      }\n    else\n      {\n\tcenter = Point3d(0,0,0);\n\trad = 1;\n      }\n\n    CalcTransformationMatrices();\n\n    for (int i = 0; i < trilists.Size(); i++)\n      glDeleteLists (trilists[i], 1);\n    trilists.SetSize(0);\n\n    for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)\n      {\n\ttrilists.Append (glGenLists (1));\n\tglNewList (trilists.Last(), GL_COMPILE); \n\tglEnable (GL_NORMALIZE);\n\tconst TriangleApproximation * ta =\n\t  geometry->GetTriApprox(i);\n\tif (ta) \n\t  {\n\t    glEnableClientState(GL_VERTEX_ARRAY);\n\t    glVertexPointer(3, GL_DOUBLE, 0, &ta->GetPoint(0)(0));\n\n\t    glEnableClientState(GL_NORMAL_ARRAY);\n\t    glNormalPointer(GL_DOUBLE, 0, &ta->GetNormal(0)(0));\n\t    \n\t    for (int j = 0; j < ta->GetNT(); j++)\n\t      glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, & (ta->GetTriangle(j)[0]));\n\n\t    glDisableClientState(GL_VERTEX_ARRAY);\n\t    glDisableClientState(GL_NORMAL_ARRAY);\n            /*\n\t    for (int j = 0; j < ta.GetNT(); j++)\n\t      {\n\t\tglBegin (GL_TRIANGLES);\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  {\n\t\t    int pi = ta.GetTriangle(j)[k];\n\t\t    glNormal3dv (ta.GetNormal(pi));\n\t\t    glVertex3dv (ta.GetPoint(pi));\n                    cout << \"v = \" << ta.GetPoint(pi) << endl;\n\t\t  }\n\t\tglEnd ();\n\t      }\n            */\n\t  }\n\tglEndList ();\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  VisualSceneSpecPoints :: VisualSceneSpecPoints ()\n    : VisualScene()\n  {\n    ;\n  }\n\n  VisualSceneSpecPoints :: ~VisualSceneSpecPoints ()\n  {\n    ;\n  }\n\n\n  void VisualSceneSpecPoints :: DrawScene ()\n  {\n    if (!mesh) \n      {\n\tVisualScene::DrawScene();\n\treturn;\n      }\n\n    if (changeval != specpoints.Size())\n      BuildScene();\n    changeval = specpoints.Size();\n\n\n\n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glColor3f (1.0f, 1.0f, 1.0f);\n    glLineWidth (1.0f);\n\n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n    //  glEnable (GL_COLOR);\n    //  glDisable (GL_COLOR_MATERIAL);\n    if (vispar.drawedtangents)\n      {\n\tglColor3d (1, 0, 0);\n\tglBegin (GL_LINES);\n\tfor (int i = 1; i <= specpoints.Size(); i++)\n\t  {\n\t    const Point3d p1 = specpoints.Get(i).p;\n\t    const Point3d p2 = specpoints.Get(i).p + len * specpoints.Get(i).v;\n\t    glVertex3d (p1.X(), p1.Y(), p1.Z());\n\t    glVertex3d (p2.X(), p2.Y(), p2.Z());\n\t  }\n\tglEnd();\n      }\n\n    if (vispar.drawededges)\n      {\n\tglColor3d (1, 0, 0);\n\tglBegin (GL_LINES);\n\tfor (int i = 1; i <= mesh->GetNSeg(); i++)\n\t  {\n\t    const Segment & seg = mesh -> LineSegment (i);\n\t    glVertex3dv ( (*mesh)[seg[0]] );\n            glVertex3dv ( (*mesh)[seg[1]] );\n\t    // glVertex3dv ( &(*mesh)[seg[0]].X() );\n\t    // glVertex3dv ( &(*mesh)[seg[1]].X() );\n\t  }\n\tglEnd();\n      }\n\n    glColor3d (1, 0, 0);\n    glBegin (GL_LINES);\n    int edges[12][2] = \n      { { 0, 1 },\n\t{ 2, 3 },\n\t{ 4, 5 },\n\t{ 6, 7 },\n\t{ 0, 2 },\n\t{ 1, 3 },\n\t{ 4, 6 },\n\t{ 5, 7 },\n\t{ 0, 4 },\n\t{ 1, 5 },\n\t{ 2, 6 },\n\t{ 3, 7 } };\n    for (int i = 0; i < boxes.Size(); i++)\n      {\n\tfor (int j = 0; j < 12; j++)\n\t  {\n\t    glVertex3dv ( boxes[i].GetPointNr(edges[j][0]) );\n\t    glVertex3dv ( boxes[i].GetPointNr(edges[j][1]) );\n\t  }\n\t/*\n\tglVertex3dv ( boxes[i].PMin() );\n\tglVertex3dv ( boxes[i].PMax() );\n\t*/\n      }\n    glEnd();\n\n\n\n    if (vispar.drawededgenrs)\n      {\n\tglEnable (GL_COLOR_MATERIAL);\n\tGLfloat textcol[3] = { GLfloat(1 - backcolor),\n\t\t\t       GLfloat(1 - backcolor), \n\t\t\t       GLfloat(1 - backcolor) };\n\tglColor3fv (textcol);\n\tglNormal3d (0, 0, 1);\n\tglPushAttrib (GL_LIST_BIT);\n\t// glListBase (fontbase);\n\n\tchar buf[20];\n\tfor (int i = 1; i <= mesh->GetNSeg(); i++)\n\t  {\n\t    const Segment & seg = mesh -> LineSegment (i);\n\t    const Point3d p1 = mesh -> Point (seg[0]);\n\t    const Point3d p2 = mesh -> Point (seg[1]);\n\n\t    const Point3d p = Center (p1, p2);\n\t    glRasterPos3d (p.X(), p.Y(), p.Z());\n\t  \n\t    snprintf (buf, sizeof(buf), \"%d\", seg.edgenr);\n\t    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n\t    MyOpenGLText (buf);\n\t  }\n      \n\tglPopAttrib ();\n\tglDisable (GL_COLOR_MATERIAL);\n      }\n\n\n    if (vispar.drawedpoints)\n      {\n\n\tglColor3d (0, 0, 1);\n\t/*\n\t  glPointSize( 3.0 );\n\n\tfloat range[2];\n\tglGetFloatv(GL_POINT_SIZE_RANGE, &range[0]);\n\tcout << \"max ptsize = \" << range[0] << \"-\" << range[1] << endl;\n      \n\n\tglBegin( GL_POINTS );\n\tfor (int i = 1; i <= mesh -> GetNP(); i++)\n\t  {\n\t    const Point3d & p = mesh -> Point(i);\n\t    if (i % 2)\n\t      glVertex3f( p.X(), p.Y(), p.Z());\n\t  }\n\tglEnd();\n\t*/\n\n\tstatic GLubyte knoedel[] = \n\t  {\n\t    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,\n\t  };\n\tglPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n\n\tglDisable (GL_COLOR_MATERIAL);\n\tglDisable (GL_LIGHTING);\n\tglDisable (GL_CLIP_PLANE0);\n\n        /*\n\tfor (int i = 1; i <= mesh -> GetNP(); i++)\n\t  {\n\t    const Point3d & p = mesh -> Point(i);\n\t    glRasterPos3d (p.X(), p.Y(), p.Z());\n\t    glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);\n\t  }\n        */\n        for (Point<3> p : mesh->Points())\n          {\n\t    glRasterPos3d (p(0), p(1), p(2));\n\t    glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);\n          }\n      }\n\n    if (vispar.drawedpointnrs)\n      {\n\tglEnable (GL_COLOR_MATERIAL);\n\tGLfloat textcol[3] = { GLfloat(1 - backcolor),\n\t\t\t       GLfloat(1 - backcolor),\n\t\t\t       GLfloat(1 - backcolor) };\n\tglColor3fv (textcol);\n\tglNormal3d (0, 0, 1);\n\tglPushAttrib (GL_LIST_BIT);\n\t// glListBase (fontbase);\n      \n\tchar buf[20];\n\t// for (int i = 1; i <= mesh->GetNP(); i++)\n        for (auto i : mesh->Points().Range())\n\t  {\n\t    const Point3d & p = mesh->Point(i);\n\t    glRasterPos3d (p.X(), p.Y(), p.Z());\n\t  \n\t    snprintf (buf, sizeof(buf), \"%d\", int(i));\n\t    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n\t    MyOpenGLText (buf);\n\t  }\n      \n\tglPopAttrib ();\n\tglDisable (GL_COLOR_MATERIAL);\n      }\n\n\n    \n    \n    \n\n    glPopMatrix();\n\n    if (vispar.drawcoordinatecross)\n      DrawCoordinateCross ();\n    DrawNetgenLogo ();\n\n    glFinish();  \n  }\n\n\n  void VisualSceneSpecPoints :: BuildScene (int zoomall)\n  {\n    if (!mesh) \n      {\n\tVisualScene::BuildScene(zoomall);\n\treturn;\n      }\n  \n    Box3d box;\n  \n    if (mesh->GetNSeg())\n      {\n\tbox.SetPoint (mesh->Point (mesh->LineSegment(1)[0]));\n\tfor (int i = 1; i <= mesh->GetNSeg(); i++)\n\t  {\n\t    box.AddPoint (mesh->Point (mesh->LineSegment(i)[0]));\n\t    box.AddPoint (mesh->Point (mesh->LineSegment(i)[1]));\n\t  }\n      }\n    else if (specpoints.Size() >= 2)\n      {\n\tbox.SetPoint (specpoints.Get(1).p);\n\tfor (int i = 2; i <= specpoints.Size(); i++)\n\t  box.AddPoint (specpoints.Get(i).p);\n      }\n    else\n      {\n\tbox = Box3d (Point3d (0,0,0), Point3d (1,1,1));\n      }\n  \n    if (zoomall == 2 && ((vispar.centerpoint-IndexBASE<PointIndex>() >= 0 &&\n                          vispar.centerpoint-IndexBASE<PointIndex>() < mesh->GetNP()) ||\n\t\t\t vispar.use_center_coords))\n      {\n\tif (vispar.use_center_coords)\n\t  {\n\t    center.X() = vispar.centerx; center.Y() = vispar.centery; center.Z() = vispar.centerz; \n\t  }\n\telse\n\t  center = mesh->Point (vispar.centerpoint);\n      }\n    else\n      center = Center (box.PMin(), box.PMax());\n        \n\n    rad = 0.5 * Dist (box.PMin(), box.PMax());\n  \n  \n    CalcTransformationMatrices();\n  }\n\n}\n\n\n\n\n#ifdef NG_PYTHON\n#include <../general/ngpython.hpp>\n\nNGGUI_API void ExportCSGVis(py::module &m)\n{\n\tusing namespace netgen;\n\n\tpy::class_<VisualSceneGeometry, shared_ptr<VisualSceneGeometry>>\n\t\t(m, \"VisualSceneGeometry\")\n\t\t.def(\"Draw\", &VisualSceneGeometry::DrawScene)\n\t\t;\n\n    m.def(\"SetBackGroundColor\", &VisualSceneGeometry::SetBackGroundColor);\n\n\tm.def(\"VS\",\n\t\t[](CSGeometry & geom)\n\t{\n\t\tgeom.FindIdenticSurfaces(1e-6);\n\t\tgeom.CalcTriangleApproximation(0.01, 20);\n\t\tauto vs = make_shared<VisualSceneGeometry>();\n\n\t\tvs->SetGeometry(&geom);\n\t\treturn vs;\n\t});\n\n\tm.def(\"MouseMove\",\n\t\t[](VisualSceneGeometry &vsgeom, int oldx, int oldy, int newx, int newy, char mode)\n\t{\n\t\tvsgeom.MouseMove(oldx, oldy, newx, newy, mode);\n\t});\n}\n\nPYBIND11_MODULE(libcsgvis, m) {\n  ExportCSGVis(m);\n}\n#endif\n\n\n"
  },
  {
    "path": "libsrc/csg/vscsg.hpp",
    "content": "#ifndef FILE_VSCSG\n#define FILE_VSCSG\n\n/**************************************************************************/\n/* File:   vscsg.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   05. Jan. 2011                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  class NGGUI_API VisualSceneGeometry : public VisualScene\n  {\n    class CSGeometry * geometry;\n    NgArray<int> trilists;\n    int selsurf;\n  public:\n    VisualSceneGeometry ();\n    virtual ~VisualSceneGeometry ();\n\n    void SetGeometry (class CSGeometry * ageometry) { geometry = ageometry; }\n    virtual void SelectSurface (int aselsurf);\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n  };\n\n\n\n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/csg/zrefine.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n#include <csg.hpp>\n\nnamespace netgen\n{\n\n  // find singular edges\n  void SelectSingularEdges (const Mesh & mesh, const CSGeometry & geom, \n\t\t\t    INDEX_2_HASHTABLE<int> & singedges,\n\t\t\t    ZRefinementOptions & opt)\n  {\n    // edges selected in csg input file\n    for (int i = 1; i <= geom.singedges.Size(); i++)\n      {\n\t//if(geom.singedges.Get(i)->maxhinit > 0)\n\t//  continue; //!!!!\n\n\tconst SingularEdge & se = *geom.singedges.Get(i);\n\tfor (int j = 1; j <= se.segms.Size(); j++)\n\t  {\n\t    INDEX_2 i2 = se.segms.Get(j);\n\t    singedges.Set (i2, 1);\n\t  }\n      }\n\n    // edges interactively selected\n    for (int i = 1; i <= mesh.GetNSeg(); i++)\n      {\n\tconst Segment & seg = mesh.LineSegment(i);\n\tif (seg.singedge_left || seg.singedge_right)\n\t  {\n\t    INDEX_2 i2(seg[0], seg[1]);\n\t    i2.Sort();\n\t    singedges.Set (i2, 1);\n\t  }\n      }\n  }\n\n\n  /**\n     Convert elements (vol-tets, surf-trigs) into prisms/quads\n  */\n  void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE<int> & singedges)\n  {\n    // volume elements\n    // for (int i = 1; i <= mesh.GetNE(); i++)\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tElement & el = mesh.VolumeElement(ei);\n\tif (el.GetType() != TET) continue;\n\n\tfor (int j = 1; j <= 3; j++)\n\t  for (int k = j+1; k <= 4; k++)\n\t    {\n\t      INDEX_2 edge(el.PNum(j), el.PNum(k));\n\t      edge.Sort();\n\t      if (singedges.Used (edge))\n\t\t{\n\t\t  int pi3 = 1, pi4 = 1;\n\t\t  while (pi3 == j || pi3 == k) pi3++;\n\t\t  pi4 = 10 - j - k - pi3;\n\t\t\n\t\t  int p3 = el.PNum(pi3);\n\t\t  int p4 = el.PNum(pi4);\n\n\t\t  el.SetType(PRISM);\n\t\t  el.PNum(1) = edge.I1();\n\t\t  el.PNum(2) = p3;\n\t\t  el.PNum(3) = p4;\n\t\t  el.PNum(4) = edge.I2();\n\t\t  el.PNum(5) = p3;\n\t\t  el.PNum(6) = p4;\n\t\t}\n\t    }\n      }\n\n    // surface elements\n    for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tElement2d & el = mesh.SurfaceElement(sei);\n\tif (el.GetType() != TRIG) continue;\n\n\tfor (int j = 1; j <= 3; j++)\n\t  {\n\t    int k = (j % 3) + 1;\n\t    INDEX_2 edge(el.PNum(j), el.PNum(k));\n\t    edge.Sort();\n\n\t    if (singedges.Used (edge))\n\t      {\n\t\tint pi3 = 6-j-k;\n\t\tint p3 = el.PNum(pi3);\n\t\tint p1 = el.PNum(j);\n\t\tint p2 = el.PNum(k);\n\n\t\tel.SetType(QUAD);\n\t\tel.PNum(1) = p2;\n\t\tel.PNum(2) = p3;\n\t\tel.PNum(3) = p3;\n\t\tel.PNum(4) = p1;\n\t      }\n\t  }\n      }\n  }\n\n\n  /*\n    Convert tets and pyramids next to close (identified) points into prisms\n  */\n  void MakePrismsClosePoints (Mesh & mesh)\n  {\n    // int i, j, k;\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tElement & el = mesh.VolumeElement(ei);\n\tif (el.GetType() == TET)\n\t  {\n\t    for (int j = 1; j <= 3; j++)\n\t      for (int k = j+1; k <= 4; k++)\n\t\t{\n\t\t  INDEX_2 edge(el.PNum(j), el.PNum(k));\n\t\t  edge.Sort();\n\t\t  if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))\n\t\t    {\n\t\t      int pi3 = 1, pi4 = 1;\n\t\t      while (pi3 == j || pi3 == k) pi3++;\n\t\t      pi4 = 10 - j - k - pi3;\n\t\t    \n\t\t      int p3 = el.PNum(pi3);\n\t\t      int p4 = el.PNum(pi4);\n\t\t    \n\t\t      el.SetType(PRISM);\n\t\t      el.PNum(1) = edge.I1();\n\t\t      el.PNum(2) = p3;\n\t\t      el.PNum(3) = p4;\n\t\t      el.PNum(4) = edge.I2();\n\t\t      el.PNum(5) = p3;\n\t\t      el.PNum(6) = p4;\n\t\t    }\n\t\t}\n\t  }\n\n\tif (el.GetType() == PYRAMID)\n\t  {\n\t    // pyramid, base face = 1,2,3,4\n\t  \n\t    for (int j = 0; j <= 1; j++)\n\t      {\n\t\tPointIndex pi1 = el.PNum( (j+0) % 4 + 1);\n\t\tPointIndex pi2 = el.PNum( (j+1) % 4 + 1);\n\t\tPointIndex pi3 = el.PNum( (j+2) % 4 + 1);\n\t\tPointIndex pi4 = el.PNum( (j+3) % 4 + 1);\n\t\tPointIndex pi5 = el.PNum(5);\n\n\t\tINDEX_2 edge1(pi1, pi4);\n\t\tINDEX_2 edge2(pi2, pi3);\n\t\tedge1.Sort();\n\t\tedge2.Sort();\n\t\tif (mesh.GetIdentifications().UsedSymmetric (pi1, pi4) &&\n\t\t    mesh.GetIdentifications().UsedSymmetric (pi2, pi3))\n\t\t  {\n\t\t    //int p3 = el.PNum(pi3);\n\t\t    //int p4 = el.PNum(pi4);\n\t\t  \n\t\t    el.SetType(PRISM);\n\t\t    el.PNum(1) = pi1;\n\t\t    el.PNum(2) = pi2;\n\t\t    el.PNum(3) = pi5;\n\t\t    el.PNum(4) = pi4;\n\t\t    el.PNum(5) = pi3;\n\t\t    el.PNum(6) = pi5;\n\t\t  }\n\t      }\n\t  }\n      }\n  \n    for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tElement2d & el = mesh.SurfaceElement(sei);\n\tif (el.GetType() != TRIG) continue;\n\n\tfor (int j = 1; j <= 3; j++)\n\t  {\n\t    int k = (j % 3) + 1;\n\t    INDEX_2 edge(el.PNum(j), el.PNum(k));\n\t    edge.Sort();\n\n\t    if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))\n\t      {\n\t\tint pi3 = 6-j-k;\n\t\tint p3 = el.PNum(pi3);\n\t\tint p1 = el.PNum(j);\n\t\tint p2 = el.PNum(k);\n\n\t\tel.SetType(QUAD);\n\t\tel.PNum(1) = p2;\n\t\tel.PNum(2) = p3;\n\t\tel.PNum(3) = p3;\n\t\tel.PNum(4) = p1;\n\t      }\n\t  }\n      }\n  }\n\n\n\n#ifdef OLD\n  void MakeCornerNodes (Mesh & mesh,\n\t\t\tINDEX_HASHTABLE<int> & cornernodes)\n  {\n    int i, j;\n    int nseg = mesh.GetNSeg();\n    NgArray<int> edgesonpoint(mesh.GetNP());\n    for (i = 1; i <= mesh.GetNP(); i++)\n      edgesonpoint.Elem(i) = 0;\n\n    for (i = 1; i <= nseg; i++)\n      {\n\tfor (j = 1; j <= 2; j++)\n\t  {\n\t    int pi = (j == 1) ? \n\t      mesh.LineSegment(i)[0] :\n\t      mesh.LineSegment(i)[1];\n\t    edgesonpoint.Elem(pi)++;\n\t  }\n      }\n\n    /*\n      cout << \"cornernodes: \";\n      for (i = 1; i <= edgesonpoint.Size(); i++)\n      if (edgesonpoint.Get(i) >= 6)\n      {\n      cornernodes.Set (i, 1);\n      cout << i << \" \";\n      }\n      cout << endl;\n    */\n    //  cornernodes.Set (5, 1);\n  }\n#endif\n\n\n  void RefinePrisms (Mesh & mesh, const CSGeometry * geom, \n\t\t     ZRefinementOptions & opt)\n  {\n    // int i, j;\n    bool found, change;\n    int cnt = 0;\n\n\n    // markers for z-refinement:  p1, p2, levels  \n    // p1-p2 is an edge to be refined\n    NgArray<INDEX_3> ref_uniform;\n    NgArray<INDEX_3> ref_singular;\n    NgArray<INDEX_4 > ref_slices;\n\n    NgBitArray first_id(geom->identifications.Size());\n    first_id.Set();\n\n  \n    // if (mesh.GetIdentifications().HasIdentifiedPoints())\n      {\n        auto & identpts =\n          mesh.GetIdentifications().GetIdentifiedPoints ();\n\n        /*\n\tfor (int i = 1; i <= identpts.GetNBags(); i++)\n\t  for (int j = 1; j <= identpts.GetBagSize(i); j++)\n\t    {\n\t      INDEX_3 pair;\n\t      int dummy;\n\t      identpts.GetData(i, j, pair, dummy);\n        */\n        for (auto [hash, val] : identpts)\\\n          {\n            auto [hash_pts, idnr] = hash;\n            auto [pi1, pi2] = hash_pts;\n            // auto idnr = pair[2];\n            \n\t      const CloseSurfaceIdentification * csid = \n\t\tdynamic_cast<const CloseSurfaceIdentification*> \n\t\t(geom->identifications.Get(idnr));\n\t      if (csid)\n\t\t{\n\t\t  if (!csid->GetSlices().Size())\n\t\t    {\n\t\t      if (first_id.Test (idnr))\n\t\t\t{\n\t\t\t  first_id.Clear(idnr);\n                          /*\n\t\t\t  ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels()));\n\t\t\t  ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1()));\n\t\t\t  ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2()));\n                          */\n\t\t\t  ref_uniform.Append (INDEX_3 (pi1, pi2, csid->RefLevels()));\n\t\t\t  ref_singular.Append (INDEX_3 (pi1, pi2, csid->RefLevels1()));\n\t\t\t  ref_singular.Append (INDEX_3 (pi2, pi1, csid->RefLevels2()));\n                          \n\t\t\t}\n\t\t    }\n\t\t  else\n\t\t    {   \n\t\t      //const NgArray<double> & slices = csid->GetSlices();\n\t\t      INDEX_4 i4;\n\t\t      // i4[0] = pair.I1();\n\t\t      // i4[1] = pair.I2();\n\t\t      i4[0] = pi1; \n\t\t      i4[1] = pi2; \n\t\t      i4[2] = idnr;\n\t\t      i4[3] = csid->GetSlices().Size();\n\t\t      ref_slices.Append (i4);\n\t\t    }\n\t\t}\n\t    }\n      }\n\n  \n  \n    NgArray<EdgePointGeomInfo> epgi;\n\n    while (1)\n      {\n\tcnt++;\n\tPrintMessage (3, \"Z-Refinement, level = \", cnt);\n\tINDEX_2_HASHTABLE<int> refedges(mesh.GetNSE()+1);\n\n\n\tfound = 0;\n\t// mark prisms due to close surface flags:\n\tint oldsize = ref_uniform.Size();\n\tfor (int i = 1; i <= oldsize; i++)\n\t  {\n\t    int pi1 = ref_uniform.Get(i).I1();\n\t    int pi2 = ref_uniform.Get(i).I2();\n\t    int levels = ref_uniform.Get(i).I3();\n\n\t    if (levels > 0)\n\t      {\n\t\tconst Point3d & p1 = mesh.Point(pi1);\n\t\tconst Point3d & p2 = mesh.Point(pi2);\n\t\tint npi(0);\n\t      \n\t\tINDEX_2 edge(pi1, pi2);\n\t\tedge.Sort();\n\t\tif (!refedges.Used(edge))\n\t\t  {\n\t\t    Point3d np = Center (p1, p2);\n\t\t    npi = mesh.AddPoint (np);\n\t\t    refedges.Set (edge, npi);\n\t\t    found = 1;\n\t\t  }\n\n\t\tref_uniform.Elem(i) = INDEX_3(pi1, npi, levels-1);\n\t\tref_uniform.Append (INDEX_3(pi2, npi, levels-1));\n\t      }\n\t  }\n\tfor (int i = 1; i <= ref_singular.Size(); i++)\n\t  {\n\t    int pi1 = ref_singular.Get(i).I1();\n\t    int pi2 = ref_singular.Get(i).I2();\n\t    int levels = ref_singular.Get(i).I3();\n\n\t    if (levels > 0)\n\t      {\n\t\tconst Point3d & p1 = mesh.Point(pi1);\n\t\tconst Point3d & p2 = mesh.Point(pi2);\n\t\tint npi;\n\t      \n\t\tINDEX_2 edge(pi1, pi2);\n\t\tedge.Sort();\n\t\tif (!refedges.Used(edge))\n\t\t  {\n\t\t    Point3d np = Center (p1, p2);\n\t\t    npi = mesh.AddPoint (np);\n\t\t    refedges.Set (edge, npi);\n\t\t    found = 1;\n\t\t  }\n\t\telse\n\t\t  npi = refedges.Get (edge);\n\n\t\tref_singular.Elem(i) = INDEX_3(pi1, npi, levels-1);\n\t      }\n\t  }\n\n\tfor (int i = 1; i <= ref_slices.Size(); i++)\n\t  {\n\t    int pi1 = ref_slices.Get(i)[0];\n\t    int pi2 = ref_slices.Get(i)[1];\n\t    int idnr = ref_slices.Get(i)[2];\n\t    int slicenr = ref_slices.Get(i)[3];\n\n\t    if (slicenr > 0)\n\t      {\n\t\tconst Point3d & p1 = mesh.Point(pi1);\n\t\tconst Point3d & p2 = mesh.Point(pi2);\n\t\tint npi;\n\n\t\tconst CloseSurfaceIdentification * csid = \n\t\t  dynamic_cast<const CloseSurfaceIdentification*> \n\t\t  (geom->identifications.Get(idnr));\n\n\t      \n\t\tINDEX_2 edge(pi1, pi2);\n\t\tedge.Sort();\n\t\tif (!refedges.Used(edge))\n\t\t  {\n\t\t    const auto& slices = csid->GetSlices();\n\t\t    //(*testout) << \"idnr \" << idnr << \" i \" << i << endl;\n\t\t    //(*testout) << \"slices \" << slices << endl;\n\t\t    double slicefac = slices[slicenr-1];\n\t\t    double slicefaclast = \n\t\t      (slicenr == slices.Size()) ? 1 : slices[slicenr];\n\t\t    \n\t\t    Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1);\n\t\t    //(*testout) << \"slicenr \" << slicenr << \" slicefac \" << slicefac << \" quot \" << (slicefac / slicefaclast) << \" np \" << np << endl;\n\t\t    npi = mesh.AddPoint (np);\n\t\t    refedges.Set (edge, npi);\n\t\t    found = 1;\n\t\t  }\n\t\telse\n\t\t  npi = refedges.Get (edge);\n\t\t\n\t\tref_slices.Elem(i)[1] = npi;\n\t\tref_slices.Elem(i)[3] --;\n\t      }\n\t  }\n\n\n\n\n\tfor (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n\t  {\n\t    Element & el = mesh.VolumeElement (ei);\n\t    if (el.GetType() != PRISM)\n\t      continue;\n\n\t    for (int j = 1; j <= 3; j++)\n\t      {\n\t\tint pi1 = el.PNum(j);\n\t\tint pi2 = el.PNum(j+3);\n\t\tconst Point3d & p1 = mesh.Point(pi1);\n\t\tconst Point3d & p2 = mesh.Point(pi2);\n\n\t\tbool ref = 0;\n\n\t\t/*\n\t\t  if (Dist (p1, p2) > mesh.GetH (Center (p1, p2)))\n\t\t  ref = 1;\n\t\t*/\n\n\t\t/*\n\t\t  if (cnt <= opt.minref)\n\t\t  ref = 1;\n\t\t*/\n\n\t\t/*\n\t\t  if ((pi1 == 460 || pi2 == 460 ||\n\t\t  pi1 == 461 || pi2 == 461) && cnt <= 8) ref = 1;\n\t\t*/\n\t\tif (ref == 1)\n\t\t  {\n\t\t    INDEX_2 edge(pi1, pi2);\n\t\t    edge.Sort();\n\t\t    if (!refedges.Used(edge))\n\t\t      {\n\t\t\tPoint3d np = Center (p1, p2);\n\t\t\tint npi = mesh.AddPoint (np);\n\t\t\trefedges.Set (edge, npi);\n\t\t\tfound = 1;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n      \n\tif (!found) break;\n\n\t// build closure:\n\tPrintMessage (5, \"start closure\");\n\tdo\n\t  {\n\t    PrintMessage (5, \"start loop\");\n\t    change = 0;\n\t    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n\t      {\n\t\tElement & el = mesh.VolumeElement (ei);\n\t\tif (el.GetType() != PRISM)\n\t\t  continue;\n\t      \n\t\tbool hasref = 0, hasnonref = 0;\n\t\tfor (int j = 1; j <= 3; j++)\n\t\t  {\n\t\t    int pi1 = el.PNum(j);\n\t\t    int pi2 = el.PNum(j+3);\n\t\t    if (pi1 != pi2)\n\t\t      {\n\t\t\tINDEX_2 edge(pi1, pi2);\n\t\t\tedge.Sort();\n\t\t\tif (refedges.Used(edge))\n\t\t\t  hasref = 1;\n\t\t\telse \n\t\t\t  hasnonref = 1;\n\t\t      }\n\t\t  }\n\n\t\tif (hasref && hasnonref)\n\t\t  {\n\t\t    //\t\t  cout << \"el \" << i << \" in closure\" << endl;\n\t\t    change = 1;\n\t\t    for (int j = 1; j <= 3; j++)\n\t\t      {\n\t\t\tint pi1 = el.PNum(j);\n\t\t\tint pi2 = el.PNum(j+3);\n\t\t\tconst Point3d & p1 = mesh.Point(pi1);\n\t\t\tconst Point3d & p2 = mesh.Point(pi2);\n\t\t      \n\t\t\tINDEX_2 edge(pi1, pi2);\n\t\t\tedge.Sort();\n\t\t\tif (!refedges.Used(edge))\n\t\t\t  {\n\t\t\t    Point3d np = Center (p1, p2);\n\t\t\t    int npi = mesh.AddPoint (np);\n\t\t\t    refedges.Set (edge, npi);\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\twhile (change);\n\n\tPrintMessage (5, \"Do segments\");\n\n\t//      (*testout) << \"closure formed, np = \" << mesh.GetNP() << endl;\n\n\tint oldns = mesh.GetNSeg();\n\n\tfor (int i = 1; i <= oldns; i++)\n\t  {\n\t    const Segment & el = mesh.LineSegment(i);\n\n\t    INDEX_2 i2(el[0], el[1]);\n\t    i2.Sort();\n\t  \n\t    int pnew;\n\t    EdgePointGeomInfo ngi;\n      \n\t    if (refedges.Used(i2))\n\t      {\n\t\tpnew = refedges.Get(i2);\n\t\t//\t      ngi = epgi.Get(pnew);\n\t      }\n\t    else\n\t      {\n\t\tcontinue;\n\n\t\t// \t      Point3d pb;\n\n\t\t// \t      /*\n\t\t// \t      geom->PointBetween (mesh.Point (el[0]),\n\t\t// \t\t\t\t  mesh.Point (el[1]),\n\t\t// \t\t\t\t  el.surfnr1, el.surfnr2,\n\t\t// \t\t\t\t  el.epgeominfo[0], el.epgeominfo[1],\n\t\t// \t\t\t\t  pb, ngi);\n\t\t// \t      */\n\t\t// \t      pb = Center (mesh.Point (el[0]), mesh.Point (el[1]));\n\n\t\t// \t      pnew = mesh.AddPoint (pb);\n\t      \n\t\t// \t      refedges.Set (i2, pnew);\n\t      \n\t\t// \t      if (pnew > epgi.Size())\n\t\t// \t\tepgi.SetSize (pnew);\n\t\t// \t      epgi.Elem(pnew) = ngi;\n\t      }\n\t  \n\t    Segment ns1 = el;\n\t    Segment ns2 = el;\n\t    ns1[1] = pnew;\n\t    ns1.epgeominfo[1] = ngi;\n\t    ns2[0] = pnew;\n\t    ns2.epgeominfo[0] = ngi;\n\n\t    mesh.LineSegment(i) = ns1;\n\t    mesh.AddSegment (ns2);\n\t  }\n      \n\tPrintMessage (5, \"Segments done, NSeg = \", mesh.GetNSeg());\n\n\t// do refinement\n\tint oldne = mesh.GetNE();\n\tfor (ElementIndex ei = 0; ei < oldne; ei++)\n\t  {\n\t    Element & el = mesh.VolumeElement (ei);\n\t    if (el.GetNP() != 6)\n\t      continue;\n\n\t    int npi[3];\n\t    for (int j = 1; j <= 3; j++)\n\t      {\n\t\tint pi1 = el.PNum(j);\n\t\tint pi2 = el.PNum(j+3);\n\n\t\tif (pi1 == pi2)\n\t\t  npi[j-1] = pi1;\n\t\telse\n\t\t  {\n\t\t    INDEX_2 edge(pi1, pi2);\n\t\t    edge.Sort();\n\t\t    if (refedges.Used (edge))\n\t\t      npi[j-1] = refedges.Get(edge);\n\t\t    else\n\t\t      {\n\t\t\t/*\n\t\t\t  (*testout) << \"ERROR: prism \" << i << \" has hanging node !!\" \n\t\t\t  << \", edge = \" << edge << endl;\n\t\t\t  cerr << \"ERROR: prism \" << i << \" has hanging node !!\" << endl;\n\t\t\t*/\n\t\t\tnpi[j-1] = 0;\n\t\t      }\n\t\t  }\n\t      }\n\n\t    if (npi[0])\n\t      {\n\t\tElement nel1(6), nel2(6);\n\t\tfor (int j = 1; j <= 3; j++)\n\t\t  {\n\t\t    nel1.PNum(j) = el.PNum(j);\n\t\t    nel1.PNum(j+3) = npi[j-1];\n\t\t    nel2.PNum(j) = npi[j-1];\n\t\t    nel2.PNum(j+3) = el.PNum(j+3);\n\t\t  }\n\t\tnel1.SetIndex (el.GetIndex());\n\t\tnel2.SetIndex (el.GetIndex());\n\t\tmesh.VolumeElement (ei) = nel1;\n\t\tmesh.AddVolumeElement (nel2);\n\t      }\n\t  }\n\n      \n\tPrintMessage (5, \"Elements done, NE = \", mesh.GetNE());\n\n\n\t// do surface elements\n\tint oldnse = mesh.GetNSE();\n\t//      cout << \"oldnse = \" << oldnse << endl;\n\tfor (SurfaceElementIndex sei = 0; sei < oldnse; sei++)\n\t  {\n\t    Element2d & el = mesh.SurfaceElement (sei);\n\t    if (el.GetType() != QUAD)\n\t      continue;\n\n\t    int index = el.GetIndex();\n\t    int npi[2];\n\t    for (int j = 1; j <= 2; j++)\n\t      {\n\t\tint pi1, pi2;\n\n\t\tif (j == 1)\n\t\t  {\n\t\t    pi1 = el.PNum(1);\n\t\t    pi2 = el.PNum(4);\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    pi1 = el.PNum(2);\n\t\t    pi2 = el.PNum(3);\n\t\t  }\n\n\t\tif (pi1 == pi2)\n\t\t  npi[j-1] = pi1;\n\t\telse\n\t\t  {\n\t\t    INDEX_2 edge(pi1, pi2);\n\t\t    edge.Sort();\n\t\t    if (refedges.Used (edge))\n\t\t      npi[j-1] = refedges.Get(edge);\n\t\t    else\n\t\t      {\n\t\t\tnpi[j-1] = 0;\n\t\t      }\n\t\t  }\n\t      }\n\n\t    if (npi[0])\n\t      {\n\t\tElement2d nel1(QUAD), nel2(QUAD);\n\t\tfor (int j = 1; j <= 4; j++)\n\t\t  {\n\t\t    nel1.PNum(j) = el.PNum(j);\n\t\t    nel2.PNum(j) = el.PNum(j);\n\t\t  }\n\t\tnel1.PNum(3) = npi[1];\n\t\tnel1.PNum(4) = npi[0];\n\t\tnel2.PNum(1) = npi[0];\n\t\tnel2.PNum(2) = npi[1];\n\t\t/*\n\t\t  for (j = 1; j <= 2; j++)\n\t\t  {\n\t\t  nel1.PNum(j) = el.PNum(j);\n\t\t  nel1.PNum(j+2) = npi[j-1];\n\t\t  nel2.PNum(j) = npi[j-1];\n\t\t  nel2.PNum(j+2) = el.PNum(j+2);\n\t\t  }\n\t\t*/\n\t\tnel1.SetIndex (el.GetIndex());\n\t\tnel2.SetIndex (el.GetIndex());\n\n\t\tmesh.SurfaceElement (sei) = nel1;\n\t\tmesh.AddSurfaceElement (nel2);\n\n\t\tint si = mesh.GetFaceDescriptor (index).SurfNr();\n\n\t\tPoint<3> hp = mesh.Point(npi[0]);\n\t\tgeom->GetSurface(si)->Project (hp);\n\t\tmesh.Point (npi[0]).SetPoint (hp);\n\n\t\thp = mesh.Point(npi[1]);\n\t\tgeom->GetSurface(si)->Project (hp);\n\t\tmesh.Point (npi[1]).SetPoint (hp);\n\n\t\t//\t      geom->GetSurface(si)->Project (mesh.Point(npi[0]));\n\t\t//\t      geom->GetSurface(si)->Project (mesh.Point(npi[1]));\n\t      }\n\t  }\n\n        mesh.RebuildSurfaceElementLists();\n\tPrintMessage (5, \"Surface elements done, NSE = \", mesh.GetNSE());\n      }\n    \n  }\n\n  void CombineSingularPrisms(Mesh& mesh)\n  {\n    for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n        Element& el = mesh.VolumeElement(ei);\n        if(el.GetType() != PRISM)\n          continue;\n        if(el.PNum(3) == el.PNum(6))\n          {\n            if(el.PNum(2) == el.PNum(5))\n              {\n                el.SetType(TET);\n              }\n            else\n              {\n                el.SetType(PYRAMID);\n                int pnr5 = el.PNum(3);\n                el.PNum(3) = el.PNum(5);\n                el.PNum(5) = pnr5;\n              }\n          }\n      }\n  }\n\n  void ZRefinement (Mesh & mesh, const NetgenGeometry * hgeom,\n\t\t    ZRefinementOptions & opt)\n  {\n    const CSGeometry * geom = dynamic_cast<const CSGeometry*> (hgeom);\n    if (!geom) return;\n\n    INDEX_2_HASHTABLE<int> singedges(mesh.GetNSeg());\n\n    SelectSingularEdges (mesh, *geom, singedges, opt);\n    //MakePrismsSingEdge (mesh, singedges);\n    MakePrismsClosePoints (mesh);\n\n    RefinePrisms (mesh, geom, opt);\n\n    CombineSingularPrisms(mesh);\n  }\n\n\n\n  ZRefinementOptions :: ZRefinementOptions()\n  {\n    minref = 0;\n  }\n\n}\n"
  },
  {
    "path": "libsrc/general/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n    gzstream.cpp\n    hashtabl.cpp\n    mystring.cpp\n    ngbitarray.cpp\n    optmem.cpp\n    parthreads.cpp\n    seti.cpp\n    sort.cpp\n    spbita2d.cpp\n    table.cpp\n)\n\n# dynamicmem.cpp\n\ninstall(FILES\n  ngarray.hpp autodiff.hpp autoptr.hpp ngbitarray.hpp\n  hashtabl.hpp myadt.hpp\n  mystring.hpp netgenout.hpp ngpython.hpp\n  optmem.hpp parthreads.hpp seti.hpp sort.hpp\n  spbita2d.hpp stack.hpp table.hpp template.hpp\n  gzstream.h\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel\n)\n# dynamicmem.hpp \n"
  },
  {
    "path": "libsrc/general/autodiff.hpp",
    "content": "#ifndef FILE_AUTODIFF\n#define FILE_AUTODIFF\n\n/**************************************************************************/\n/* File:   autodiff.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   24. Oct. 02                                                    */\n/**************************************************************************/\n\n// Automatic differentiation datatype\n\nnamespace netgen\n{\n\n/**\n   Datatype for automatic differentiation.\n   Contains function value and D derivatives. Algebraic\n   operations are overloaded by using product-rule etc. etc. \n**/\ntemplate <int D, typename SCAL = double>\nclass AutoDiff\n{\n  SCAL val;\n  SCAL dval[D];\npublic:\n\n  typedef AutoDiff<D,SCAL> TELEM;\n  typedef SCAL TSCAL;\n\n\n  /// elements are undefined\n  AutoDiff  () throw() { }; \n  // { val = 0; for (int i = 0; i < D; i++) dval[i] = 0; }  // !\n\n  /// copy constructor\n  AutoDiff  (const AutoDiff & ad2) throw()\n  {\n    val = ad2.val;\n    for (int i = 0; i < D; i++)\n      dval[i] = ad2.dval[i];\n  }\n\n  /// initial object with constant value\n  AutoDiff  (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n  }\n\n  /// init object with (val, e_diffindex)\n  AutoDiff  (SCAL aval, int diffindex)  throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    dval[diffindex] = 1;\n  }\n\n  /// assign constant value\n  AutoDiff & operator= (SCAL aval) throw()\n  {\n    val = aval;\n    for (int i = 0; i < D; i++)\n      dval[i] = 0;\n    return *this;\n  }\n\n  /// returns value\n  SCAL Value() const throw() { return val; }\n\n  /// returns partial derivative\n  SCAL DValue (int i) const throw() { return dval[i]; }\n\n  /// access value\n  SCAL & Value() throw() { return val; }\n\n  /// accesses partial derivative \n  SCAL & DValue (int i) throw() { return dval[i]; }\n\n  /// \n  AutoDiff<D,SCAL> & operator+= (const AutoDiff<D,SCAL> & y) throw()\n  {\n    val += y.val;\n    for (int i = 0; i < D; i++)\n      dval[i] += y.dval[i];\n    return *this;\n  }\n\n  ///\n  AutoDiff<D,SCAL> & operator-= (const AutoDiff<D,SCAL> & y) throw()\n  {\n    val -= y.val;\n    for (int i = 0; i < D; i++)\n      dval[i] -= y.dval[i];\n    return *this;\n\n  }\n\n  ///\n  AutoDiff<D,SCAL> & operator*= (const AutoDiff<D,SCAL> & y) throw()\n  {\n    for (int i = 0; i < D; i++)\n      {\n\t// dval[i] *= y.val;\n\t// dval[i] += val * y.dval[i];\n        dval[i] = dval[i] * y.val + val * y.dval[i];\n      }\n    val *= y.val;\n    return *this;\n  }\n\n  ///\n  AutoDiff<D,SCAL> & operator*= (const SCAL & y) throw()\n  {\n    val *= y;\n    for (int i = 0; i < D; i++)\n      dval[i] *= y;\n    return *this;\n  }\n\n  ///\n  AutoDiff<D,SCAL> & operator/= (const SCAL & y) throw()\n  {\n    SCAL iy = 1.0 / y;\n    val *= iy;\n    for (int i = 0; i < D; i++)\n      dval[i] *= iy;\n    return *this;\n  }\n\n  /// \n  bool operator== (SCAL val2) throw()\n  {\n    return val == val2;\n  }\n\n  ///\n  bool operator!= (SCAL val2) throw()\n  {\n    return val != val2;\n  }\n\n  ///\n  bool operator< (SCAL val2) throw()\n  {\n    return val < val2;\n  }\n  \n  ///\n  bool operator> (SCAL val2) throw()\n  {\n    return val > val2;\n  }\n};\n\n\n//@{  AutoDiff helper functions.\n\n/// prints AutoDiff\ntemplate<int D, typename SCAL>\ninline ostream & operator<< (ostream & ost, const AutoDiff<D,SCAL> & x)\n{\n  ost << x.Value() << \", D = \";\n  for (int i = 0; i < D; i++)\n    ost << x.DValue(i) << \" \";\n  return ost;\n}\n\n/// AutoDiff plus AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value () = x.Value()+y.Value();\n  // AutoDiff<D,SCAL> res(x.Value()+y.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) + y.DValue(i);\n  return res;\n}\n\n\n/// AutoDiff minus AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x.Value()-y.Value();\n  // AutoDiff<D,SCAL> res (x.Value()-y.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i) - y.DValue(i);\n  return res;\n}\n\n/// double plus AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator+ (double x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  return res;\n}\n\n/// AutoDiff plus double\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & y, double x) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x+y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = y.DValue(i);\n  return res;\n}\n\n\n/// minus AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = -x.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i);\n  return res;\n}\n\n/// AutoDiff minus double\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, double y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x.Value()-y;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x.DValue(i);\n  return res;\n}\n\n///\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator- (double x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x-y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -y.DValue(i);\n  return res;\n}\n\n\n/// double times AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator* (double x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  return res;\n}\n\n/// AutoDiff times double\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & y, double x) throw()\n{\n  AutoDiff<D,SCAL> res;\n  res.Value() = x*y.Value();\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = x*y.DValue(i);\n  return res;\n}\n\n/// AutoDiff times AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()\n{\n  AutoDiff<D,SCAL> res;\n  SCAL hx = x.Value();\n  SCAL hy = y.Value();\n\n  res.Value() = hx*hy;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);\n\n  return res;\n}\n\n\n/// Inverse of AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> Inv (const AutoDiff<D,SCAL> & x)\n{\n  AutoDiff<D,SCAL> res(1.0 / x.Value());\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());\n  return res;\n}\n\n\n/// AutoDiff div AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y)\n{\n  return x * Inv (y);\n}\n\n/// AutoDiff div double\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, double y)\n{\n  return (1/y) * x;\n}\n\n/// double div AutoDiff\ntemplate<int D, typename SCAL>\ninline AutoDiff<D,SCAL> operator/ (double x, const AutoDiff<D,SCAL> & y)\n{\n  return x * Inv(y);\n}\n\n} // namespace netgen\n\nnamespace ngcore\n{\n/// AutoDiff times AutoDiff\ntemplate<int D, typename SCAL>\ninline netgen::AutoDiff<D,SCAL> sqr (const netgen::AutoDiff<D,SCAL> & x) throw()\n{\n  netgen::AutoDiff<D,SCAL> res;\n  SCAL hx = x.Value();\n  res.Value() = hx*hx;\n  hx *= 2;\n  for (int i = 0; i < D; i++)\n    res.DValue(i) = hx*x.DValue(i);\n  return res;\n}\n} // namespace ngcore\n\nnamespace std\n{\ntemplate<int D, typename SCAL>\ninline netgen::AutoDiff<D,SCAL> fabs (const netgen::AutoDiff<D,SCAL> & x)\n{\n  double abs = fabs (x.Value());\n  netgen::AutoDiff<D,SCAL> res( abs );\n  if (abs != 0.0)\n    for (int i = 0; i < D; i++)\n      res.DValue(i) = x.DValue(i) / abs;\n  else\n    for (int i = 0; i < D; i++)\n      res.DValue(i) = 0.0;\n  return res;\n}\n} // namespace std\n#endif\n"
  },
  {
    "path": "libsrc/general/autoptr.hpp",
    "content": "braucht man nicht mehr\n\n#ifndef FILE_AUTOPTR\n#define FILE_AUTOPTR\n\n/**************************************************************************/\n/* File:   autoptr.hpp                                                    */\n/* Author: STL, Joachim Schoeberl                                         */\n/* Date:   29. Dec. 02                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  /*\ntemplate <typename T>\nclass AutoPtr\n{\nprivate:\n  T * ptr;\npublic:\n  typedef T* pT;\n  explicit AutoPtr (T * p = 0)  { ptr = p; }\n  ~AutoPtr () { delete ptr; }\n  \n  T & operator*() const { return *ptr; }\n  T* operator->() const { return ptr; }\n  T *& Ptr() { return ptr; }\n  T * Ptr() const { return ptr; }\n  void Reset(T * p = 0) { if (p != ptr) { delete ptr; ptr = p; } }\n  operator bool () { return ptr != 0; }\nprivate:\n  AutoPtr (AutoPtr &) { ; }\n  AutoPtr & operator= (AutoPtr &) { ; }\n};\n  */\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/dynamicmem.cpp",
    "content": "#include <myadt.hpp>\n\nusing namespace std;\n\nnamespace netgen\n{\n\n  BaseDynamicMem * BaseDynamicMem::first = 0;\n  BaseDynamicMem * BaseDynamicMem::last = 0;\n\n\n  BaseDynamicMem :: BaseDynamicMem ()\n  {\n    prev = last;\n    next = 0;\n\n    if (last) last->next = this;\n    last = this;\n    if (!first) first = this;\n\n    size = 0;\n    ptr = 0;\n    name = 0;\n  }\n \n  BaseDynamicMem :: ~BaseDynamicMem ()\n  {\n    Free();\n\n    if (next) next->prev = prev;\n    else last = prev;\n    if (prev) prev->next = next;\n    else first = next;\n\n    delete [] name;\n  }\n\n  void BaseDynamicMem :: SetName (const char * aname)\n  {\n    delete [] name;\n    name = NULL;\n    if (aname)\n      {\n\tname = new char[strlen(aname)+1];\n\tstrcpy (name, aname);\n      }\n  }\n\n\n  void BaseDynamicMem :: Alloc (size_t s)\n  {\n    size = s;\n    ptr = new char[s];\n\n    if (!ptr)\n      {\n\tcerr << \"BaseynamicMem, cannot allocate \" << s << \" bytes\" << endl;\n\tPrint ();\n\tthrow (\"BaseDynamicMem::Alloc: out of memory\");\n      }\n    // ptr = (char*)malloc (s);\n    // ptr = (char*) _mm_malloc (s,16);\n  }\n\n  void BaseDynamicMem :: ReAlloc (size_t s)\n  {\n    if (size == s) return;\n\n    char * old = ptr;\n    ptr = new char[s];\n\n    if (!ptr)\n      {\n\tcerr << \"BaseynamicMem, cannot Reallocate \" << s << \" bytes\" << endl;\n\tPrint ();\n\tthrow (\"BaseDynamicMem::Alloc: out of memory\");\n      }\n\n\n    // ptr = (char*)malloc(s);\n    // ptr = (char*) _mm_malloc (s,16);\n    memmove (ptr, old, (s < size) ? s : size);\n    delete [] old;\n    // free (old);\n    // _mm_free (old);\n    size = s;\n  }\n\n  void BaseDynamicMem :: Free ()\n  {\n    delete [] ptr;\n    // free (ptr);\n    // _mm_free (ptr);\n    ptr = 0;\n  }\n\n  void BaseDynamicMem :: Swap (BaseDynamicMem & m2)\n  {\n    size_t hi;\n    char * cp;\n    hi = size; size  = m2.size; m2.size = hi;\n    cp = ptr; ptr = m2.ptr; m2.ptr = cp;\n    cp = name; name = m2.name; m2.name = cp;\n  }\n\n\n  void BaseDynamicMem :: Print ()\n  {\n    cout << \"****************** Dynamic Mem Report ****************\" << endl;\n    BaseDynamicMem * p = first;\n    size_t mem = 0;\n    int cnt = 0;\n    while (p)\n      {\n\tmem += p->size;\n\tcnt++;\n\n\tcout << setw(10) << p->size << \" Bytes\";\n\tcout << \", addr = \" << (void*)p->ptr;\n\tif (p->name)\n\t  cout << \" in block \" << p->name;\n\tcout << endl;\n\n\tp = p->next;\n      }\n\n    if (mem > 100000000)\n      cout << \"memory in dynamic memory: \" << mem/1048576 << \" MB\" << endl;\n    else if (mem > 100000)\n      cout << \"memory in dynamic memory: \" << mem/1024 << \" kB\" << endl;\n    else\n      cout << \"memory in dynamic memory: \" << mem << \" Bytes\" << endl;\n    cout << \"number of blocks:         \" << cnt << endl;\n    //  cout << \"******************************************************\" << endl;\n  }\n\n\n#ifdef __INTEL_COMPILER\n#pragma warning(push)\n#pragma warning(disable:1684)\n#endif\n\n  void BaseDynamicMem :: GetUsed (int nr, char * ch)\n  {\n    BaseDynamicMem * p = first;\n\n    for (int i = 0; i < nr; i++)\n      ch[i] = '0';\n\n    while (p)\n      {\n        long unsigned hptr = (long unsigned) (p->ptr);\n\t// uintptr_t hptr = reinterpret_cast<uintptr_t>(p->ptr); //??\n\n\thptr /= (1024*1024);\n\thptr /= (4096/nr);\n\n\tsize_t blocks = p->size / (1024*1024);\n\tblocks /= (4096/nr);\n\t\n\t// cout << \"ptr = \" << (void*)(p->ptr) << \", size = \" << p->size << \", hptr = \" << hptr << \" blocks = \" << blocks << endl;\n\n\tfor (size_t i = 0; i <= blocks; i++)\n\t  ch[hptr+i] = '1';\n\n\tp = p->next;\n      }\n    \n    {\n\n      /*\n    BaseMoveableMem * pm = BaseMoveableMem::first;\n    while (pm)\n      {\n        long unsigned hptr = (long unsigned) pm->ptr;\n        // uintptr_t hptr = reinterpret_cast<uintptr_t>(pm->ptr);\n\n\thptr /= (1024*1024);\n\thptr /= (4096/nr);\n\n\tsize_t blocks = pm->size / (1024*1024);\n\tblocks /= (4096/nr);\n\t\n\t// cout << \"moveable, ptr = \" << (void*)(pm->ptr) << \", size = \" << pm->size << \", hptr = \" << hptr << \" blocks = \" << blocks << endl;\n\n\tfor (size_t i = 0; i <= blocks; i++)\n\t  ch[hptr+i] = '1';\n\n\tpm = pm->next;\n      }\n      */\n    }\n\n\n\n  }\n\n#ifdef __INTEL_COMPILER\n#pragma warning(pop)\n#endif\n\n}\n"
  },
  {
    "path": "libsrc/general/dynamicmem.hpp",
    "content": "not needed anymore ? \n\n\n#ifndef FILE_DYNAMICMEM\n#define FILE_DYNAMICMEM\n\n/**************************************************************************/\n/* File:   dynamicmem.hpp                                                 */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   12. Feb. 2003                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\nclass BaseDynamicMem\n{\nprivate:\n  static BaseDynamicMem *first, *last;\n\n  BaseDynamicMem *prev, *next;\n  size_t size;\n  char * ptr;\n  char * name;\n\nprotected:\n  BaseDynamicMem ();\n  ~BaseDynamicMem ();\n  void Alloc (size_t s);\n  void ReAlloc (size_t s);\n  void Free ();\n  // char * Ptr() { return ptr; }\n  char * Ptr() const { return ptr; }\n  void Swap (BaseDynamicMem & m2);\npublic:\n  void SetName (const char * aname);\n  static void Print ();\n  static void GetUsed (int nr, char * ch);\n};\n\n\ntemplate <typename T>\nclass DynamicMem : public BaseDynamicMem\n{\npublic:\n  DynamicMem ()\n    : BaseDynamicMem () \n  {\n    ;\n  }\n  DynamicMem (size_t s)\n    : BaseDynamicMem () \n  {\n    Alloc (s);\n  }\n  void Alloc (size_t s)\n  {\n    BaseDynamicMem::Alloc (sizeof(T) * s);\n  }\n  void ReAlloc (size_t s)\n  {\n    BaseDynamicMem::ReAlloc (sizeof(T) * s);\n  }\n  void Free ()\n  {\n    BaseDynamicMem::Free ();\n  }\n\n  /*\n  const T * Ptr() const\n  {\n    return reinterpret_cast<const T*> (BaseDynamicMem::Ptr());\n  }\n  */\n  const T * Ptr()\n  {\n    return reinterpret_cast<T*> (BaseDynamicMem::Ptr());\n  }\n\n  /*\n  operator const T* () const\n  {\n    return reinterpret_cast<const T*> (BaseDynamicMem::Ptr());\n  }\n  */\n  operator T* () const\n  {\n    return reinterpret_cast<T*> (BaseDynamicMem::Ptr());\n  }\n\n  void Swap (DynamicMem<T> & m2)\n  {\n    BaseDynamicMem::Swap (m2);\n  }\nprotected:\n  DynamicMem (const DynamicMem & m);\n  DynamicMem & operator= (const DynamicMem & m);\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/gzstream.cpp",
    "content": "// ============================================================================\n// gzstream, C++ iostream classes wrapping the zlib compression library.\n// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner\n//\n// This library is free software; you can redistribute it and/or\n// modify it under the terms of the GNU Lesser General Public\n// License as published by the Free Software Foundation; either\n// version 2.1 of the License, or (at your option) any later version.\n//\n// This library is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n// Lesser General Public License for more details.\n//\n// You should have received a copy of the GNU Lesser General Public\n// License along with this library; if not, write to the Free Software\n// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n// ============================================================================\n//\n// File          : gzstream.C\n// Revision      : $Revision: 1.7 $\n// Revision_date : $Date: 2003/01/08 14:41:27 $\n// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner\n// \n// Standard streambuf implementation following Nicolai Josuttis, \"The \n// Standard C++ Library\".\n// ============================================================================\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n#include \"gzstream.h\"\n//#include <iostream>\n//#include <string.h>  // for memcpy\n\n#ifdef GZSTREAM_NAMESPACE\nnamespace GZSTREAM_NAMESPACE {\n#endif\n\n// ----------------------------------------------------------------------------\n// Internal classes to implement gzstream. See header file for user classes.\n// ----------------------------------------------------------------------------\n\n// --------------------------------------\n// class gzstreambuf:\n// --------------------------------------\n\n  gzstreambuf* gzstreambuf::open( const std::filesystem::path & name, int open_mode) {\n    if ( is_open())\n        return (gzstreambuf*)0;\n    mode = open_mode;\n    // no append nor read/write mode\n    if ((mode & std::ios::ate) || (mode & std::ios::app)\n        || ((mode & std::ios::in) && (mode & std::ios::out)))\n        return (gzstreambuf*)0;\n    char  fmode[10];\n    char* fmodeptr = fmode;\n    if ( mode & std::ios::in)\n        *fmodeptr++ = 'r';\n    else if ( mode & std::ios::out)\n        *fmodeptr++ = 'w';\n    *fmodeptr++ = 'b';\n    *fmodeptr = '\\0';\n#ifdef WIN32\n    file = gzopen_w( name.c_str(), fmode);\n#else // WIN32\n    file = gzopen( name.c_str(), fmode);\n#endif // WIN32\n    if (file == 0)\n        return (gzstreambuf*)0;\n    opened = 1;\n    return this;\n}\n\ngzstreambuf * gzstreambuf::close() {\n    if ( is_open()) {\n        sync();\n        opened = 0;\n        if ( gzclose( file) == Z_OK)\n            return this;\n    }\n    return (gzstreambuf*)0;\n}\n\nint gzstreambuf::underflow() { // used for input buffer only\n    if ( gptr() && ( gptr() < egptr()))\n        return * reinterpret_cast<unsigned char *>( gptr());\n\n    if ( ! (mode & std::ios::in) || ! opened)\n        return EOF;\n    // Josuttis' implementation of inbuf\n    int n_putback = gptr() - eback();\n    if ( n_putback > 4)\n        n_putback = 4;\n    memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);\n\n    int num = gzread( file, buffer+4, bufferSize-4);\n    if (num <= 0) // ERROR or EOF\n        return EOF;\n\n    // reset buffer pointers\n    setg( buffer + (4 - n_putback),   // beginning of putback area\n          buffer + 4,                 // read position\n          buffer + 4 + num);          // end of buffer\n\n    // return next character\n    return * reinterpret_cast<unsigned char *>( gptr());    \n}\n\nint gzstreambuf::flush_buffer() {\n    // Separate the writing of the buffer from overflow() and\n    // sync() operation.\n    int w = pptr() - pbase();\n    if ( gzwrite( file, pbase(), w) != w)\n        return EOF;\n    pbump( -w);\n    return w;\n}\n\nint gzstreambuf::overflow( int c) { // used for output buffer only\n    if ( ! ( mode & std::ios::out) || ! opened)\n        return EOF;\n    if (c != EOF) {\n        *pptr() = c;\n        pbump(1);\n    }\n    if ( flush_buffer() == EOF)\n        return EOF;\n    return c;\n}\n\nint gzstreambuf::sync() {\n    // Changed to use flush_buffer() instead of overflow( EOF)\n    // which caused improper behavior with std::endl and flush(),\n    // bug reported by Vincent Ricard.\n    if ( pptr() && pptr() > pbase()) {\n        if ( flush_buffer() == EOF)\n            return -1;\n    }\n    return 0;\n}\n\n// --------------------------------------\n// class gzstreambase:\n// --------------------------------------\n\n  gzstreambase::gzstreambase( const std::filesystem::path & name, int mode) {\n    init( &buf);\n    open( name.c_str(), mode);\n}\n\ngzstreambase::~gzstreambase() {\n    buf.close();\n}\n\n  void gzstreambase::open( const std::filesystem::path & name, int open_mode) {\n    if ( ! buf.open( name.c_str(), open_mode))\n        clear( rdstate() | std::ios::badbit);\n}\n\nvoid gzstreambase::close() {\n    if ( buf.is_open())\n        if ( ! buf.close())\n            clear( rdstate() | std::ios::badbit);\n}\n\n#ifdef GZSTREAM_NAMESPACE\n} // namespace GZSTREAM_NAMESPACE\n#endif\n\n// ============================================================================\n// EOF //\n"
  },
  {
    "path": "libsrc/general/gzstream.h",
    "content": "// ============================================================================\n// gzstream, C++ iostream classes wrapping the zlib compression library.\n// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner\n//\n// This library is free software; you can redistribute it and/or\n// modify it under the terms of the GNU Lesser General Public\n// License as published by the Free Software Foundation; either\n// version 2.1 of the License, or (at your option) any later version.\n//\n// This library is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n// Lesser General Public License for more details.\n//\n// You should have received a copy of the GNU Lesser General Public\n// License along with this library; if not, write to the Free Software\n// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n// ============================================================================\n//\n// File          : gzstream.h\n// Revision      : $Revision: 1.5 $\n// Revision_date : $Date: 2002/04/26 23:30:15 $\n// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner\n// \n// Standard streambuf implementation following Nicolai Josuttis, \"The \n// Standard C++ Library\".\n// ============================================================================\n\n#ifndef GZSTREAM_H\n#define GZSTREAM_H 1\n\n// standard C++ with new header file names and std:: namespace\n#include <iostream>\n#include <fstream>\n#include <zlib.h>\n\n#ifdef GZSTREAM_NAMESPACE\nnamespace GZSTREAM_NAMESPACE {\n#endif\n\n// ----------------------------------------------------------------------------\n// Internal classes to implement gzstream. See below for user classes.\n// ----------------------------------------------------------------------------\n\nclass gzstreambuf : public std::streambuf {\nprivate:\n    static const int bufferSize = 47+256;    // size of data buff\n    // totals 512 bytes under g++ for igzstream at the end.\n\n    gzFile           file;               // file handle for compressed file\n    char             buffer[bufferSize]; // data buffer\n    char             opened;             // open/close state of stream\n    int              mode;               // I/O mode\n\n    int flush_buffer();\npublic:\n    gzstreambuf() : opened(0) {\n        setp( buffer, buffer + (bufferSize-1));\n        setg( buffer + 4,     // beginning of putback area\n              buffer + 4,     // read position\n              buffer + 4);    // end position      \n        // ASSERT: both input & output capabilities will not be used together\n    }\n    int is_open() { return opened; }\n    gzstreambuf* open( const std::filesystem::path & name, int open_mode);\n    gzstreambuf* close();\n    ~gzstreambuf() { close(); }\n    \n    virtual int     overflow( int c = EOF);\n    virtual int     underflow();\n    virtual int     sync();\n};\n\nclass DLL_HEADER gzstreambase : virtual public std::ios {\nprotected:\n    gzstreambuf buf;\npublic:\n    gzstreambase() { init(&buf); }\n    gzstreambase( const std::filesystem::path & name, int open_mode);\n    ~gzstreambase();\n    void open( const std::filesystem::path & name, int open_mode);\n    void close();\n    gzstreambuf* rdbuf() { return &buf; }\n};\n\n// ----------------------------------------------------------------------------\n// User classes. Use igzstream and ogzstream analogously to ifstream and\n// ofstream respectively. They read and write files based on the gz* \n// function interface of the zlib. Files are compatible with gzip compression.\n// ----------------------------------------------------------------------------\n\nclass DLL_HEADER igzstream : public gzstreambase, public std::istream {\npublic:\n    igzstream() : std::istream( &buf) {} \n    igzstream( const std::filesystem::path & name, int open_mode = std::ios::in)\n        : gzstreambase( name, open_mode), std::istream( &buf) {}  \n    gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }\n    void open( const std::filesystem::path & name, int open_mode = std::ios::in) {\n        gzstreambase::open( name, open_mode);\n    }\n};\n\nclass DLL_HEADER ogzstream : public gzstreambase, public std::ostream {\npublic:\n    ogzstream() : std::ostream( &buf) {}\n    ogzstream( const std::filesystem::path & name, int mode = std::ios::out)\n        : gzstreambase( name, mode), std::ostream( &buf) {}  \n    gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }\n    void open( const std::filesystem::path & name, int open_mode = std::ios::out) {\n        gzstreambase::open( name, open_mode);\n    }\n};\n\n#ifdef GZSTREAM_NAMESPACE\n} // namespace GZSTREAM_NAMESPACE\n#endif\n\n#endif // GZSTREAM_H\n// ============================================================================\n// EOF //\n\n"
  },
  {
    "path": "libsrc/general/hashtabl.cpp",
    "content": "/**************************************************************************/\n/* File:   hashtabl.cpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/* \n   Abstract data type HASHTABLE\n*/\n\n#include <algorithm>\n#include <mystdlib.h>\n#include <myadt.hpp>\n\nnamespace netgen\n{\n  //using namespace netgen;\n\n  void INDEX_4 :: Sort ()\n  {\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    if (i[2] > i[3]) Swap (i[2], i[3]);\n    if (i[0] > i[2]) Swap (i[0], i[2]);\n    if (i[1] > i[3]) Swap (i[1], i[3]);\n    if (i[1] > i[2]) Swap (i[1], i[2]);\n  }\n\n\n\n  void INDEX_4Q :: Sort ()\n  {\n    if (min2 (i[1], i[2]) < min2 (i[0], i[3]))\n      { Swap (i[0], i[1]); Swap (i[2], i[3]);}\n    if (i[3] < i[0])\n      { Swap (i[0], i[3]); Swap (i[1], i[2]);}\n    if (i[3] < i[1])\n      { Swap (i[1], i[3]); }\n  }\n\n\n  ostream & operator<<(ostream  & s, const INDEX_2 & i2)\n  {\n    return s << i2.I1() << \", \" << i2.I2();\n  }\n\n  ostream & operator<<(ostream  & s, const INDEX_3 & i3)\n  {\n    return s << i3.I1() << \", \" << i3.I2() << \", \" << i3.I3();\n  }\n\n  ostream & operator<<(ostream  & s, const INDEX_4 & i4)\n  {\n    return s << i4.I1() << \", \" << i4.I2() << \", \" << i4.I3() << \", \" << i4.I4();\n  }\n\n  ostream & operator<<(ostream  & s, const INDEX_4Q & i4)\n  {\n    return s << i4.I1() << \", \" << i4.I2() << \", \" << i4.I3() << \", \" << i4.I4();\n  }\n\n\n  int BASE_INDEX_HASHTABLE :: Position (int bnr, const INDEX & ind) const\n  {\n    for (int i = 1; i <= hash.EntrySize (bnr); i++)\n      if (hash.Get(bnr, i) == ind)\n\treturn i;\n    return 0;\n  }\n\n\n\n  /*\n  int BASE_INDEX_2_HASHTABLE :: Position (int bnr, const INDEX_2 & ind) const\n  {\n    int i;\n    for (i = 1; i <= hash.EntrySize (bnr); i++)\n      if (hash.Get(bnr, i) == ind)\n\treturn i;\n    return 0;\n  }\n  */  \n\n  void BASE_INDEX_2_HASHTABLE :: PrintStat (ostream & ost) const\n  {\n    int n = hash.Size();\n    int i;\n    int sumn = 0, sumnn = 0;\n\n    for (i = 1; i <= n; i++)\n      {\n\tsumn += hash.EntrySize(i);\n\tsumnn += sqr (hash.EntrySize(i));\n      }\n\n    ost << \"Hashtable: \" << endl\n\t<< \"size             : \" << n << endl\n\t<< \"elements per row : \" << (double(sumn) / double(n)) << endl\n\t<< \"av. access time  : \" \n\t<< (sumn ? (double (sumnn) / double(sumn)) : 0) << endl;\n  }\n\n\n  /*\n    int BASE_INDEX_3_HASHTABLE :: Position (int bnr, const INDEX_3 & ind) const\n    {\n    int i;\n    const INDEX_3 * pi = &hash.Get(bnr, 1);\n    int n = hash.EntrySize(bnr);\n    for (i = 1; i <= n; ++i, ++pi)\n    {\n    if (*pi == ind)\n    return i;\n    }\n\n    return 0;\n    }\n  */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  BASE_INDEX_CLOSED_HASHTABLE ::\n  BASE_INDEX_CLOSED_HASHTABLE (int size)\n    : hash(size)\n  {\n    // hash.SetName (\"index-hashtable, hash\");\n\n    invalid = -1;\n    for (int i = 1; i <= size; i++)\n      hash.Elem(i) = invalid;\n  }\n\n  void BASE_INDEX_CLOSED_HASHTABLE ::\n  BaseSetSize (int size)\n  {\n    hash.SetSize(size);\n    for (int i = 1; i <= size; i++)\n      hash.Elem(i) = invalid;\n  }\n\n  int BASE_INDEX_CLOSED_HASHTABLE ::\n  Position2 (const INDEX & ind) const\n  {\n    int i = HashValue(ind);\n    while (1)\n      {\n\ti++;\n\tif (i > hash.Size()) i = 1;\n\tif (hash.Get(i) == ind) return i;\n\tif (hash.Get(i) == invalid) return 0;\n      }\n  }\n\n  int BASE_INDEX_CLOSED_HASHTABLE ::\n  PositionCreate2 (const INDEX & ind, int & apos) \n  {\n    int i = HashValue(ind);\n    int startpos = i;\n    while (1)\n      {\n\ti++;\n\tif (i > hash.Size()) i = 1;\n\tif (hash.Get(i) == ind) \n\t  {\n\t    apos = i;\n\t    return 0;\n\t  }\n\tif (hash.Get(i) == invalid) \n\t  {\n\t    hash.Elem(i) = ind;\n\t    apos = i;\n\t    return 1;\n\t  }\n\tif (i == startpos)\n\t  throw NgException (\"Try to set new element in full closed hashtable\");\n      }\n  }\n\n  int BASE_INDEX_CLOSED_HASHTABLE :: UsedElements () const\n  {\n    int n = hash.Size();\n    int cnt = 0;\n    for (int i = 1; i <= n; i++)\n      if (hash.Get(i) != invalid)\n\tcnt++;\n    return cnt;\n  }\n\n\n\n\n\n\n\n\n\n\n\n  BASE_INDEX_2_CLOSED_HASHTABLE ::\n  BASE_INDEX_2_CLOSED_HASHTABLE (size_t size)\n    : hash(RoundUp2(size))\n  {\n    size = hash.Size();\n    mask = size-1;\n    // hash.SetName (\"i2-hashtable, hash\");\n\n    invalid = -1;\n    for (size_t i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n\n  void BASE_INDEX_2_CLOSED_HASHTABLE ::\n  BaseSetSize (int size)\n  {\n    size = RoundUp2 (size);\n    mask = size-1;\n    \n    hash.SetSize(size);\n    for (size_t i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n\n\n  int BASE_INDEX_2_CLOSED_HASHTABLE ::\n  Position2 (const INDEX_2 & ind) const\n  {\n    int i = HashValue(ind);\n    while (1)\n      {\n\ti++;\n\tif (i > hash.Size()) i = 1;\n\tif (hash.Get(i) == ind) return i;\n\tif (hash.Get(i).I1() == invalid) return 0;\n      }\n  }\n\n  bool BASE_INDEX_2_CLOSED_HASHTABLE ::\n  PositionCreate2 (const INDEX_2 & ind, int & apos) \n  {\n    int i = HashValue(ind);\n    int startpos = i;\n    while (1)\n      {\n        /*\n\ti++;\n\tif (i > hash.Size()) i = 1;\n        */\n        i = (i+1) % hash.Size();\n\tif (hash[i] == ind) \n\t  {\n\t    apos = i;\n\t    return false;\n\t  }\n\tif (hash[i].I1() == invalid) \n\t  {\n\t    hash[i] = ind;\n\t    apos = i;\n\t    return true;\n\t  }\n\tif (i == startpos)\n\t  throw NgException (\"Try to set new element in full closed hashtable\");\n      }\n  }\n\n  int BASE_INDEX_2_CLOSED_HASHTABLE :: UsedElements () const\n  {\n    int n = hash.Size();\n    int cnt = 0;\n    for (int i = 1; i <= n; i++)\n      if (hash.Get(i).I1() != invalid)\n\tcnt++;\n    return cnt;\n  }\n\n\n\n\n\n  BASE_INDEX_3_CLOSED_HASHTABLE ::\n  BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)\n    : hash(RoundUp2(size))\n  {\n    // cout << \"orig size = \" << size\n    // << \", roundup size = \" << hash.Size();\n    size = hash.Size();\n    mask = size-1;\n    // cout << \"mask = \" << mask << endl;\n    invalid = -1;\n    for (size_t i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n\n\n  void BASE_INDEX_3_CLOSED_HASHTABLE ::\n  BaseSetSize (int size)\n  {\n    size = RoundUp2 (size);\n    mask = size-1;\n    \n    hash.SetSize(size);\n    for (int i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n\n  bool BASE_INDEX_3_CLOSED_HASHTABLE ::\n  PositionCreate2 (const INDEX_3 & ind, int & apos) \n  {\n    int i = HashValue(ind);\n    int startpos = i;\n    while (1)\n      {\n        /*\n\ti++;\n\tif (i >= hash.Size()) i = 0;\n        */\n        i = (i+1) % hash.Size();\n\tif (hash[i] == ind) \n\t  {\n\t    apos = i;\n\t    return false;\n\t  }\n\tif (hash[i].I1() == invalid) \n\t  {\n\t    hash[i] = ind;\n\t    apos = i;\n\t    return true;\n\t  }\n\tif (i == startpos)\n\t  throw NgException (\"Try to set new element in full closed hashtable\");\n      }\n  }\n}\n\n"
  },
  {
    "path": "libsrc/general/hashtabl.hpp",
    "content": "#ifndef FILE_HASHTABL\n#define FILE_HASHTABL\n\n/**************************************************************************/\n/* File:   hashtabl.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include \"table.hpp\"\n\nnamespace netgen\n{\n\n/**\n   Abstract data type HASHTABLE.\n   Hash is done by one INDEX\n*/\nclass BASE_INDEX_HASHTABLE\n{\nprotected:\n  /// keys are stored in this table\n  TABLE<INDEX,1> hash;\n  \npublic:\n  ///\n  BASE_INDEX_HASHTABLE (int size)\n    : hash (size) { };\n  \nprotected:\n  ///\n  int HashValue (const INDEX & ind) const\n    {\n      return ind % hash.Size() + 1;\n    }\n\n  ///\n  int Position (int bnr, const INDEX & ind) const;\n};\n\n///\ntemplate <class T>\nclass INDEX_HASHTABLE : private BASE_INDEX_HASHTABLE\n{\n  ///\n  TABLE<T,1> cont;\n  \npublic: \n  ///\n  inline INDEX_HASHTABLE (int size);\n  ///\n  inline void Set (const INDEX & hash, const T & acont);\n  ///\n  inline const T & Get (const INDEX & ahash) const;\n  ///\n  inline bool Used (const INDEX & ahash) const;\n  ///\n  inline int GetNBags () const;\n  ///\n  inline int GetBagSize (int bnr) const;\n  ///\n  inline void GetData (int bnr, int colnr, INDEX & ahash, T & acont) const;\n\n  ///\n  inline void PrintMemInfo (ostream & ost) const;\n};\n\n\n\n\n\n\n\n\n\n\n///\nclass BASE_INDEX_2_HASHTABLE\n{\nprotected:\n  ///\n  TABLE<INDEX_2> hash;\n  \npublic:\n  ///\n  BASE_INDEX_2_HASHTABLE () { ; } \n\n  BASE_INDEX_2_HASHTABLE (int size)\n    : hash (size) { };\n\n  ///\n  void PrintStat (ostream & ost) const;\n  void BaseSetSize(int s) {hash.SetSize(s);}\n  //protected:\n  ///\n  int HashValue (const INDEX_2 & ind) const\n    {\n      return (ind.I1() + ind.I2()) % hash.Size() + 1;\n    }\n  ///\n  int Position (int bnr, const INDEX_2 & ind) const\n  {\n    for (int i = 1; i <= hash.EntrySize (bnr); i++)\n      if (hash.Get(bnr, i) == ind)\n\treturn i;\n    return 0;\n  }\n};\n\n\n///\ntemplate <class T>\nclass INDEX_2_HASHTABLE : public BASE_INDEX_2_HASHTABLE\n{\n  ///\n  TABLE<T> cont;\n  \npublic:\n  ///\n  INDEX_2_HASHTABLE () { ; } \n\n INDEX_2_HASHTABLE (int size)\n   : BASE_INDEX_2_HASHTABLE (size), cont(size)\n  { ; }  \n\n  ///\n  void SetSize(int s) \n  { \n    cont.SetSize(s); \n    BaseSetSize(s);\n  }\n\n  ///\n  void Set (const INDEX_2 & ahash, const T & acont)\n  {\n    int bnr = HashValue (ahash);\n      int pos = Position (bnr, ahash);\n      if (pos)\n\tcont.Set (bnr, pos, acont);\n      else\n\t{\n\t  hash.Add1 (bnr, ahash);\n\t  cont.Add1 (bnr, acont);\n\t}    \n  }\n  \n  ///\n  const T & Get (const INDEX_2 & ahash) const\n  {\n    int bnr = HashValue (ahash);\n    int pos = Position (bnr, ahash);\n    return cont.Get (bnr, pos);\n  }\n\n  T & Get (const INDEX_2 & ahash)\n  {\n    int bnr = HashValue (ahash);\n    int pos = Position (bnr, ahash);\n    return cont.Get (bnr, pos);\n  }\n\n  ///\n  bool Used (const INDEX_2 & ahash) const\n  {\n    return Position (HashValue (ahash), ahash) > 0;\n  }\n ///\n  int GetNBags () const\n  {\n    return cont.Size();\n  }\n  \n  ///\n  int GetBagSize (int bnr) const\n  {\n    return cont.EntrySize (bnr);\n  }\n    \n  ///\n  void GetData (int bnr, int colnr, \n\t\tINDEX_2 & ahash, T & acont) const\n  {\n    ahash = hash.Get(bnr, colnr);\n    acont = cont.Get(bnr, colnr);\n  }\n\n  ///\n  void SetData (int bnr, int colnr, \n\t\tconst INDEX_2 & ahash, const T & acont) \n  {\n    hash.Set(bnr, colnr, ahash);\n    cont.Set(bnr, colnr, acont);\n  }\n  \n  ///\n  void PrintMemInfo (ostream & ost) const\n  {\n    ost << \"Hash: \" << endl;\n    hash.PrintMemInfo (ost);\n    ost << \"Cont: \" << endl;\n    cont.PrintMemInfo (ost);\n  }\n\n\n  void DeleteData ()\n  {\n    int n = hash.Size();\n    hash.SetSize (n);\n    cont.SetSize (n);\n  }\n\n\n  class Iterator\n  {\n    const INDEX_2_HASHTABLE & ht;    \n    int bagnr, pos;\n  public:\n    Iterator (const INDEX_2_HASHTABLE & aht,\n\t      int abagnr, int apos)\n      : ht(aht), bagnr(abagnr), pos(apos)\n    { ; }\n\n    int BagNr() const { return bagnr; }\n    int Pos() const { return pos; }\n\n    Iterator operator++ (int)\n    {\n      Iterator it(ht, bagnr, pos);\n      ++(*this);\n      return it;\n    }\n    Iterator& operator++()\n    {\n      pos++;\n      while (bagnr < ht.GetNBags() && \n\t     pos == ht.GetBagSize(bagnr+1))\n\t{\n\t  pos = 0;\n\t  bagnr++;\n\t}\n      return *this;\n    }\n\n    std::pair<INDEX_2, T> operator*()\n    {\n      return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);\n    }\n\n    bool operator != (int i) const\n    {\n      return bagnr != i;\n    }\n\n  };\n  \n  Iterator Begin () const\n  {\n    Iterator it(*this, 0, -1);\n    it++;\n    return it;\n  }\n\n  int End() const\n  {\n    return GetNBags();\n  }\n\n  Iterator begin () const\n  {\n    Iterator it(*this, 0, -1);\n    it++;\n    return it;\n  }\n\n  int end() const\n  {\n    return GetNBags();\n  }\n\n  void GetData (const Iterator & it,\n\t\tINDEX_2 & ahash, T & acont) const\n  {\n    ahash = hash[it.BagNr()][it.Pos()];\n    acont = cont[it.BagNr()][it.Pos()];\n  }\n\n  const INDEX_2 & GetHash (const Iterator & it) const\n  { return hash[it.BagNr()][it.Pos()]; }\n\n  const T & GetData (const Iterator & it) const\n  { return cont[it.BagNr()][it.Pos()]; }\n\n  void DoArchive (Archive & ar)\n  {\n    ar & hash & cont;\n  }    \n  \n};\n\ntemplate <typename T> \ninline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE<T> & ht)\n{\n  for (typename INDEX_2_HASHTABLE<T>::Iterator it = ht.Begin();\n       it != ht.End(); it++)\n    {\n      ost << ht.GetHash(it) << \": \" << ht.GetData(it) << endl;\n    }\n\n  return ost;\n}\n\n\n\n\n\n\n\n///\nclass BASE_INDEX_3_HASHTABLE\n{\nprotected:\n  ///\n  TABLE<INDEX_3> hash;\n\npublic:\n  ///\n  BASE_INDEX_3_HASHTABLE () { ; } \n  BASE_INDEX_3_HASHTABLE (int size)\n    : hash (size) { };\n\nprotected:\n  ///\n  int HashValue (const INDEX_3 & ind) const\n    {\n      return (ind.I1() + ind.I2() + ind.I3()) % hash.Size() + 1;\n    }\n\n  ///\n  int Position (int bnr, const INDEX_3 & ind) const\n  {\n    const INDEX_3 * pi = &hash.Get(bnr, 1);\n    int n = hash.EntrySize(bnr);\n    for (int i = 1; i <= n; ++i, ++pi)\n      {\n\tif (*pi == ind)\n\treturn i;\n      }\n    \n    return 0;\n  }\n\n\n};\n\n\n///\ntemplate <class T>\nclass INDEX_3_HASHTABLE : private BASE_INDEX_3_HASHTABLE\n{\n  ///\n  TABLE<T> cont;\n\npublic:\n  ///\n  inline INDEX_3_HASHTABLE () { ; }\n  inline INDEX_3_HASHTABLE (int size);\n  ///\n  inline void Set (const INDEX_3 & ahash, const T & acont);\n  ///\n  inline const T & Get (const INDEX_3 & ahash) const;\n  ///\n  inline bool Used (const INDEX_3 & ahash) const;\n  ///\n  inline int GetNBags () const;\n  ///\n  inline int GetBagSize (int bnr) const;\n  ///\n  inline void SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont);\n  ///\n  inline void GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const;\n  /// returns position, if not existing, will create (create == return 1)\n  inline int PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr);\n  ///\n  inline void SetSize (int size);\n\n  ///\n  inline void PrepareSet (const INDEX_3 & ahash);\n  ///\n  inline void AllocateElements ();\n\n  ///\n  inline void PrintMemInfo (ostream & ost) const;\n  ///\n  inline void DeleteData ();\n\n\n\n\n\n\n\n\n\n  class Iterator\n  {\n    const INDEX_3_HASHTABLE & ht;    \n    int bagnr, pos;\n  public:\n    Iterator (const INDEX_3_HASHTABLE & aht,\n\t      int abagnr, int apos)\n      : ht(aht), bagnr(abagnr), pos(apos)\n    { ; }\n\n    int BagNr() const { return bagnr; }\n    int Pos() const { return pos; }\n\n    Iterator operator++ (int)\n    {\n      Iterator it(ht, bagnr, pos);\n      ++(*this);\n      return it;\n    }\n    Iterator& operator++()\n    {\n      pos++;\n      while (bagnr < ht.GetNBags() && \n\t     pos == ht.GetBagSize(bagnr+1))\n\t{\n\t  pos = 0;\n\t  bagnr++;\n\t}\n      return *this;\n    }\n\n    std::pair<INDEX_3, T> operator*()\n    {\n      return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);\n    }\n\n    bool operator != (int i) const\n    {\n      return bagnr != i;\n    }\n\n  };\n  \n  Iterator Begin () const\n  {\n    Iterator it(*this, 0, -1);\n    it++;\n    return it;\n  }\n\n  int End() const\n  {\n    return GetNBags();\n  }\n\n  Iterator begin () const\n  {\n    Iterator it(*this, 0, -1);\n    it++;\n    return it;\n  }\n\n  int end() const\n  {\n    return GetNBags();\n  }\n\n  void GetData (const Iterator & it,\n\t\tINDEX_3 & ahash, T & acont) const\n  {\n    ahash = hash[it.BagNr()][it.Pos()];\n    acont = cont[it.BagNr()][it.Pos()];\n  }\n\n  const INDEX_3 & GetHash (const Iterator & it) const\n  { return hash[it.BagNr()][it.Pos()]; }\n\n  const T & GetData (const Iterator & it) const\n  { return cont[it.BagNr()][it.Pos()]; }\n\n\n  void DoArchive (Archive & ar)\n  {\n    ar & hash & cont;\n  }    \n\n\n};\n\n\ntemplate <typename T> \ninline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE<T> & ht)\n{\n  for (typename INDEX_3_HASHTABLE<T>::Iterator it = ht.Begin();\n       it != ht.End(); it++)\n    {\n      ost << ht.GetHash(it) << \": \" << ht.GetData(it) << endl;\n    }\n\n  return ost;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/// Closed Hashing HT\n\nclass BASE_INDEX_CLOSED_HASHTABLE\n{\nprotected:\n  ///\n  // MoveableArray<INDEX> hash;\n  NgArray<INDEX> hash;\n  ///\n  int invalid;\npublic:\n  ///\n  BASE_INDEX_CLOSED_HASHTABLE (int size);\n\n  int Size() const { return hash.Size(); }\n  int UsedPos (int pos) const { return ! (hash.Get(pos) == invalid); }\n  int UsedElements () const;\n\n  ///\n  int HashValue (const INDEX & ind) const\n  {\n    return (3*ind) % hash.Size() + 1;\n  }\n\n\n  int Position (const INDEX & ind) const\n  {\n    int i = HashValue(ind);\n    while (1)\n      {\n\tif (hash.Get(i) == ind) return i;\n\tif (hash.Get(i) == invalid) return 0;\n\ti++;\n\tif (i > hash.Size()) i = 1;\n      }\n  }\n\n  int CalcPositionCosts (const INDEX & ind) const\n  {\n    int i = HashValue(ind);\n    int costs = 1;\n    while (1)\n      {\n\tif (hash.Get(i) == ind) return costs;\n\tif (hash.Get(i) == invalid) return costs;\n\ti++;\n\tif (i > hash.Size()) i = 1;\n\tcosts++;\n      }\n  }\n\n\n\n  // returns 1, if new position is created\n  int PositionCreate (const INDEX & ind, int & apos)\n  {\n    int i = HashValue (ind);\n    if (hash.Get(i) == ind) \n      {\n\tapos = i;\n\treturn 0;\n      }\n    if (hash.Get(i) == invalid)\n      {\n\thash.Elem(i) = ind; \n\tapos = i;\n\treturn 1;\n      }\n    return PositionCreate2 (ind, apos);    \n  }\n\nprotected:\n  int Position2 (const INDEX & ind) const;\n  int PositionCreate2 (const INDEX & ind, int & apos);\n  void BaseSetSize (int asize);\n};\n\n\ntemplate <class T>\nclass INDEX_CLOSED_HASHTABLE : public BASE_INDEX_CLOSED_HASHTABLE\n{\n  ///\n// MoveableArray<T> cont;\n  NgArray<T> cont;\n\npublic:\n  ///\n  INDEX_CLOSED_HASHTABLE (int size)\n    : BASE_INDEX_CLOSED_HASHTABLE(size), cont(size)\n  {\n    ; // cont.SetName (\"ind-hashtable, contents\");\n  }\n\n\n  void Set (const INDEX & ahash, const T & acont)\n  {\n    int pos;\n    PositionCreate (ahash, pos);\n    hash.Elem(pos) = ahash;\n    cont.Elem(pos) = acont;\n  }\n\n  const T & Get (const INDEX & ahash) const\n  {\n    int pos = Position (ahash);\n    return cont.Get(pos);\n  }\n\n  ///\n  bool Used (const INDEX & ahash) const\n  {\n    int pos = Position (ahash);\n    return (pos != 0);\n  }\n  \n  \n  ///\n  inline void SetData (int pos, const INDEX & ahash, const T & acont)\n  {\n    hash.Elem(pos) = ahash;\n    cont.Elem(pos) = acont;\n  }\n\n  ///\n  void GetData (int pos, INDEX & ahash, T & acont) const\n  {\n    ahash = hash.Get(pos);\n    acont = cont.Get(pos);\n  }\n  \n  ///\n  inline void SetData (int pos, const T & acont)\n  {\n    cont.Elem(pos) = acont;\n  }\n  \n  ///\n  void GetData (int pos, T & acont) const\n  {\n    acont = cont.Get(pos);\n  }\n  \n  ///\n  const T & GetData (int pos) { return cont.Get(pos); }\n  ///\n  inline void SetSize (int size)\n  {\n    BaseSetSize(size);\n  cont.SetSize(size);\n  }\n  \n  ///\n  inline void DeleteData ()\n  { SetSize (cont.Size()); }\n\n  void SetName (const char * aname)\n  {\n    // cont.SetName(aname);\n    // hash.SetName(aname);\n  }\n};\n\n\n\n\n\n  inline size_t RoundUp2 (size_t i)\n  {\n    size_t res = 1;\n    while (res < i) res *= 2; // hope it will never be too large \n    return res; \n  }\n\n/// Closed Hashing HT\n\nclass BASE_INDEX_2_CLOSED_HASHTABLE\n{\nprotected:\n  ///\n  // MoveableArray<INDEX_2> hash;\n  NgArray<INDEX_2> hash;\n  ///\n  int invalid;\n  size_t mask;\npublic:\n  ///\n  DLL_HEADER BASE_INDEX_2_CLOSED_HASHTABLE (size_t size);\n\n  int Size() const { return hash.Size(); }\n  bool UsedPos0 (int pos) const { return ! (hash[pos].I1() == invalid); }\n  int UsedElements () const;\n\n  ///\n  int HashValue (const INDEX_2 & ind) const\n    {\n      // return (ind.I1() + 71 * ind.I2()) % hash.Size() + 1;\n      return (ind.I1() + 71 * ind.I2()) & mask; \n    }\n\n\n  int Position0 (const INDEX_2 & ind) const\n  {\n    int i = HashValue(ind);\n    while (1)\n      {\n\tif (hash[i] == ind) return i;\n\tif (hash[i].I1() == invalid) return -1;\n        i = (i+1) & mask;        \n        /*\n\ti++;\n\tif (i > hash.Size()) i = 1;\n        */\n      }\n  }\n\n  // returns 1, if new position is created\n  bool PositionCreate0 (const INDEX_2 & ind, int & apos)\n  {\n    int i = HashValue (ind);\n    if (hash[i] == ind) \n      {\n\tapos = i;\n\treturn false;\n      }\n    if (hash[i].I1() == invalid)\n      {\n\thash[i] = ind; \n\tapos = i;\n\treturn true;\n      }\n    return PositionCreate2 (ind, apos);    \n  }\n\nprotected:\n  ///\n\n  DLL_HEADER int Position2 (const INDEX_2 & ind) const;\n  DLL_HEADER bool PositionCreate2 (const INDEX_2 & ind, int & apos);\n  DLL_HEADER void BaseSetSize (int asize);\n};\n\n\ntemplate <class T>\nclass INDEX_2_CLOSED_HASHTABLE : public BASE_INDEX_2_CLOSED_HASHTABLE\n{\n  NgArray<T> cont;\npublic:\n  INDEX_2_CLOSED_HASHTABLE (size_t size)\n    : BASE_INDEX_2_CLOSED_HASHTABLE(size), cont(RoundUp2(size))\n  { ; }\n\n  void Set (const INDEX_2 & ahash, const T & acont)\n  {\n    int pos;\n    PositionCreate0 (ahash, pos);\n    hash[pos] = ahash;\n    cont[pos] = acont;\n  }\n    \n  const T & Get (const INDEX_2 & ahash) const\n  {\n    int pos = Position0 (ahash);\n    return cont[pos];\n  }\n    \n  inline bool Used (const INDEX_2 & ahash) const\n  {\n    int pos = Position0 (ahash);\n    return (pos != -1);\n  }\n\n  inline optional<T> GetIfUsed (const INDEX_2 & ahash) const\n  {\n    int pos = Position0 (ahash);\n    if (pos != -1)\n      return cont[pos];\n    else\n      return nullopt;\n  }\n    \n  inline void SetData0 (int pos, const INDEX_2 & ahash, const T & acont)\n  {\n    hash[pos] = ahash;\n    cont[pos] = acont;\n  }\n    \n  ///\n  inline void GetData0 (int pos, INDEX_2 & ahash, T & acont) const\n  {\n    ahash = hash[pos];\n    acont = cont[pos];\n  }\n    \n  inline void SetData0 (int pos, const T & acont)\n  {\n    cont[pos] = acont;\n  }\n  \n  inline void GetData0 (int pos, T & acont) const\n  {\n    acont = cont[pos];\n  }\n  \n  ///\n  const T & GetData0 (int pos) { return cont[pos]; }\n  ///\n  inline void SetSize (size_t size)\n  {\n    BaseSetSize(size);\n    cont.SetSize(RoundUp2(size));\n  }\n\n    \n  ///\n  inline void PrintMemInfo (ostream & ost) const;\n  ///\n  inline void DeleteData ()\n  { SetSize (cont.Size()); }\n\n  void SetName (const char * aname)\n  {\n    ; \n    // cont.SetName(aname);\n    // hash.SetName(aname);\n  }\n};\n\n\n\ntemplate <typename T> \ninline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> & ht)\n{\n  for (int i = 0; i < ht.Size(); i++)\n    if (ht.UsedPos(i))\n      {\n\t// INDEX_2 hash;\n\t// T data;\n\t// ht.GetData0 (i, hash, data);\n        auto [hash,data] = ht.GetBoth(i);\n\tost << \"hash = \" << hash << \", data = \" << data << endl;\n      }\n  return ost;\n}\n\n\n\n\nclass BASE_INDEX_3_CLOSED_HASHTABLE\n{\nprotected:\n  NgArray<INDEX_3> hash;\n  int invalid;\n  size_t mask;\n\nprotected: \n  BASE_INDEX_3_CLOSED_HASHTABLE (size_t size);\n  /*\n    : hash(RoundUp2(size))\n  {\n    // cout << \"orig size = \" << size\n    // << \", roundup size = \" << hash.Size();\n    size = hash.Size();\n    mask = size-1;\n    // cout << \"mask = \" << mask << endl;\n    invalid = -1;\n    for (size_t i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n  */\n\npublic:\n  int Size() const \n  {\n    return hash.Size(); \n  }\n\n  bool UsedPos (int pos) const \n  { \n    return ! (hash[pos].I1() == invalid); \n  }\n\n  int UsedElements () const\n  {\n    int n = hash.Size();\n    int cnt = 0;\n    for (int i = 0; i < n; i++)\n      if (hash[i].I1() != invalid)\n\tcnt++;\n    return cnt;\n  }\n\n  int HashValue (const INDEX_3 & ind) const\n  {\n    // return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) % hash.Size();\n    return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) & mask;\n  }\n  \n  int Position (const INDEX_3 & ind) const\n  {\n    int i = HashValue(ind);\n    while (1)\n      {\n\tif (hash[i] == ind) return i;\n\tif (hash[i].I1() == invalid) return -1;\n        // i = (i+1) % hash.Size();\n        i = (i+1) & mask;\n      }\n  }\n\n  int Costs (const INDEX_3 & ind) const\n  {\n    int i = HashValue(ind);\n    int c = 1;\n    while (1)\n      {\n\tif (hash[i] == ind) return c;\n\tif (hash[i].I1() == invalid) return c;\n        // i = (i+1) % hash.Size();\n        i = (i+1) & mask;\n        c++;\n      }\n  }\n\n\n  \n  // returns true, if new position is created\n  bool PositionCreate (const INDEX_3 & ind, int & apos)\n  {\n    int i = HashValue (ind);\n    if (hash[i] == ind) \n      {\n\tapos = i;\n\treturn false;\n      }\n    if (hash[i].I1() == invalid)\n      {\n\thash[i] = ind; \n\tapos = i;\n\treturn true;\n      }\n    return PositionCreate2 (ind, apos);    \n  }\n\n  void DeleteData()\n  {\n    size_t size = hash.Size();\n    for (size_t i = 0; i < size; i++)\n      hash[i].I1() = invalid;\n  }\n\nprotected:\n  bool PositionCreate2 (const INDEX_3 & ind, int & apos);\n  void BaseSetSize (int asize);\n};\n\n\n\ntemplate <class T>\nclass INDEX_3_CLOSED_HASHTABLE : public BASE_INDEX_3_CLOSED_HASHTABLE\n{\n  // MoveableArray<T,0> cont;\n  NgArray<T,0> cont;\n\npublic:\n  INDEX_3_CLOSED_HASHTABLE (int size)\n    : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(RoundUp2(size))\n  {\n    ; //cont.SetName (\"i3-hashtable, contents\");\n  }\n  \n  void Set (const INDEX_3 & ahash, const T & acont)\n  {\n    int pos;\n    PositionCreate (ahash, pos);\n    hash[pos] = ahash;\n    cont[pos] = acont;\n  }\n\n  const T & Get (const INDEX_3 & ahash) const\n  {\n    return cont[Position (ahash)];\n  }\n\n  bool Used (const INDEX_3 & ahash) const\n  {\n    return (Position (ahash) != -1);\n  }\n\n  void SetData (int pos, const INDEX_3 & ahash, const T & acont)\n  {\n    hash[pos] = ahash;\n    cont[pos] = acont;\n  }\n\n  void GetData (int pos, INDEX_3 & ahash, T & acont) const\n  {\n    ahash = hash[pos];\n    acont = cont[pos];\n  }\n\n  void SetData (int pos, const T & acont)\n  {\n    cont[pos] = acont;\n  }\n\n  void GetData (int pos, T & acont) const\n  {\n    acont = cont[pos];\n  }\n\n  const T & GetData (int pos) const\n  {\n    return cont[pos];\n  }\n\n   void SetSize (int size)\n  {\n    BaseSetSize(size);\n    cont.SetSize(hash.Size());\n  }\n\n  void PrintMemInfo (ostream & ost) const\n  {\n    cout << \"Hashtable: \" << Size() \n         << \" entries of size \" << sizeof(INDEX_3) << \" + \" << sizeof(T) \n         << \" = \" << Size() * (sizeof(INDEX_3) + sizeof(T)) << \" bytes\" << endl;\n    \n  }\n\n  void DeleteData ()\n  { \n    SetSize (cont.Size()); \n  }\n\n  void SetName (const char * aname)\n  {\n    ; \n    // cont.SetName(aname);\n    // hash.SetName(aname);\n  }\n};\n\n\n\ntemplate <typename T> \ninline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> & ht)\n{\n  for (int i = 0; i < ht.Size(); i++)\n    if (ht.UsedPos(i))\n      {\n        /*\n\tINDEX_3 hash;\n\tT data;\n        ht.GetData (i, hash, data);\n        */\n        auto [hash, data] = ht.GetBoth();\n\tost << \"hash = \" << hash << \", data = \" << data << endl;\n      }\n  return ost;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ntemplate<class T>\ninline INDEX_3_HASHTABLE<T> :: INDEX_3_HASHTABLE (int size)\n  : BASE_INDEX_3_HASHTABLE (size), cont(size)\n{\n  ;\n}\n\ntemplate<class T>\t\ninline int INDEX_3_HASHTABLE<T> :: PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr)\n{\n  bnr = HashValue (ahash);\n  colnr = Position (bnr, ahash);\n  if (!colnr)\n    {\n      hash.Add (bnr, ahash);\n      cont.AddEmpty (bnr);\n      colnr = cont.EntrySize (bnr);\n      return 1;\n    }\n  return 0;\n}\n\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: Set (const INDEX_3 & ahash, const T & acont)\n{\n  int bnr = HashValue (ahash);\n  int pos = Position (bnr, ahash);\n  if (pos)\n    cont.Set (bnr, pos, acont);\n  else\n    {\n      hash.Add1 (bnr, ahash);\n      cont.Add1 (bnr, acont);\n    }\n}\n\ntemplate<class T>\ninline const T & INDEX_3_HASHTABLE<T> :: Get (const INDEX_3 & ahash) const\n{\n  int bnr = HashValue (ahash);\n  int pos = Position (bnr, ahash);\n  return cont.Get (bnr, pos);\n}\n\ntemplate<class T>\ninline bool INDEX_3_HASHTABLE<T> :: Used (const INDEX_3 & ahash) const\n{\n  return (Position (HashValue (ahash), ahash)) ? 1 : 0;\n}\n\ntemplate<class T>\ninline int INDEX_3_HASHTABLE<T> :: GetNBags () const\n{\n  return cont.Size();\n}\n\ntemplate<class T>\ninline int INDEX_3_HASHTABLE<T> :: GetBagSize (int bnr) const\n{\n  return cont.EntrySize (bnr);\n}\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const\n{\n  ahash = hash.Get(bnr, colnr);\n  acont = cont.Get(bnr, colnr);\n}    \n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont)\n{\n  hash.Set(bnr, colnr, ahash);\n  cont.Set(bnr, colnr, acont);\n}    \n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: SetSize (int size)\n{\n  hash.SetSize (size);\n  cont.SetSize (size);\n}\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: DeleteData ()\n{\n  int n = hash.Size();\n  hash.SetSize (n);\n  cont.SetSize (n);\n}\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: PrepareSet (const INDEX_3 & ahash)\n{\n  int bnr = HashValue (ahash);\n  hash.IncSizePrepare (bnr-1);\n  cont.IncSizePrepare (bnr-1);\n}\n\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: AllocateElements ()\n{\n  hash.AllocateElementsOneBlock();\n  cont.AllocateElementsOneBlock();\n}\n\n\n\ntemplate<class T>\ninline void INDEX_3_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const\n  {\n    ost << \"Hash: \" << endl;\n    hash.PrintMemInfo (ost);\n    ost << \"Cont: \" << endl;\n    cont.PrintMemInfo (ost);\n  }\n\n\n\n\n\ntemplate<class T>\ninline INDEX_HASHTABLE<T> :: INDEX_HASHTABLE (int size)\n  : BASE_INDEX_HASHTABLE (size), cont(size)\n  {\n    ;\n  }\n\t\ntemplate<class T>\ninline void INDEX_HASHTABLE<T> :: Set (const INDEX & ahash, const T & acont)\n    {\n    int bnr = HashValue (ahash);\n    int pos = Position (bnr, ahash);\n    if (pos)\n      cont.Set (bnr, pos, acont);\n    else\n      {\n      hash.Add (bnr, ahash);\n      cont.Add (bnr, acont);\n      }\n    }\n\ntemplate<class T>\ninline const T & INDEX_HASHTABLE<T> :: Get (const INDEX & ahash) const\n    {\n    int bnr = HashValue (ahash);\n    int pos = Position (bnr, ahash);\n    return cont.Get (bnr, pos);\n    }\n\ntemplate<class T>\ninline bool INDEX_HASHTABLE<T> :: Used (const INDEX & ahash) const\n    {\n    return (Position (HashValue (ahash), ahash)) ? 1 : 0;\n    }\n\ntemplate<class T>\ninline int INDEX_HASHTABLE<T> :: GetNBags () const\n    {\n    return hash.Size();\n    }\n\ntemplate<class T>\ninline int INDEX_HASHTABLE<T> :: GetBagSize (int bnr) const\n    {\n    return hash.EntrySize(bnr);\n    }\n\ntemplate<class T>\ninline void INDEX_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX & ahash, T & acont) const\n    {\n    ahash = hash.Get(bnr, colnr);   \n    acont = cont.Get(bnr, colnr);\n    }\n    \ntemplate<class T>\ninline void INDEX_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const\n  {\n    ost << \"Hash: \" << endl;\n    hash.PrintMemInfo (ost);\n    ost << \"Cont: \" << endl;\n    cont.PrintMemInfo (ost);\n  }\n\n\n    \n    \n    \n    \n    \n\n\n\n\n\n\n\n\n/* *********** Closed Hashing ************************* */\n  \ntemplate<class T>\ninline void INDEX_2_CLOSED_HASHTABLE<T> :: \nPrintMemInfo (ostream & ost) const\n{\n  cout << \"Hashtable: \" << Size() \n       << \" entries of size \" << sizeof(INDEX_2) << \" + \" << sizeof(T) \n       << \" = \" << Size() * (sizeof(INDEX_2) + sizeof(T)) << \" bytes.\" \n       << \" Used els: \" << UsedElements() \n       << endl;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/*\ntemplate<class T>\ninline INDEX_3_CLOSED_HASHTABLE<T> :: \nINDEX_3_CLOSED_HASHTABLE (int size)\n  : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size)\n{\n  cont.SetName (\"i3-hashtable, contents\");\n}\n\ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nSet (const INDEX_3 & ahash, const T & acont)\n{\n  int pos;\n  PositionCreate (ahash, pos);\n  hash.Elem(pos) = ahash;\n  cont.Elem(pos) = acont;\n}\n\ntemplate<class T>\ninline const T & INDEX_3_CLOSED_HASHTABLE<T> :: \nGet (const INDEX_3 & ahash) const\n{\n  int pos = Position (ahash);\n  return cont[pos];\n}\n\ntemplate<class T>\ninline bool INDEX_3_CLOSED_HASHTABLE<T> :: \nUsed (const INDEX_3 & ahash) const\n{\n  int pos = Position (ahash);\n  return (pos != 0);\n}\n\ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nSetData (int pos, const INDEX_3 & ahash, const T & acont)\n{\n  hash.Elem(pos) = ahash;\n  cont.Elem(pos) = acont;\n}\n  \ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nGetData (int pos, INDEX_3 & ahash, T & acont) const\n{\n  ahash = hash.Get(pos);\n  acont = cont.Get(pos);\n}\n\ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nSetData (int pos, const T & acont)\n{\n  cont.Elem(pos) = acont;\n}\n  \ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nGetData (int pos, T & acont) const\n{\n  acont = cont.Get(pos);\n}\n\ntemplate<class T>\ninline const T & INDEX_3_CLOSED_HASHTABLE<T> :: \nGetData (int pos) const\n{\n  return cont.Get(pos);\n}\n\n\ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nSetSize (int size)\n{\n  BaseSetSize(size);\n  cont.SetSize(size);\n}\n  \ntemplate<class T>\ninline void INDEX_3_CLOSED_HASHTABLE<T> :: \nPrintMemInfo (ostream & ost) const\n{\n  cout << \"Hashtable: \" << Size() \n       << \" entries of size \" << sizeof(INDEX_3) << \" + \" << sizeof(T) \n       << \" = \" << Size() * (sizeof(INDEX_3) + sizeof(T)) << \" bytes\" << endl;\n}\n*/\n\n\ninline void SetInvalid (INDEX & i) { i = -1; }\ninline bool IsInvalid (INDEX i) { return i == -1; }\ninline size_t HashValue (INDEX i, size_t size) { return (113*size_t(i)) % size; }\n\ninline void SetInvalid (INDEX_2 & i2) { i2[0] = -1; }\ninline bool IsInvalid (INDEX_2 i2) { return i2[0] == -1; }\ninline size_t HashValue (INDEX_2 i2, size_t size) { return (113*size_t(i2[0])+size_t(i2[1])) % size; }\n\ninline void SetInvalid (INDEX_3 & i3) { i3[0] = -1; }\ninline bool IsInvalid (INDEX_3 i3) { return i3[0] == -1; }\ninline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1])+41*size_t(i3[2])) % size; }\n\n\n  /**\n     A closed hash-table.\n     All information is stored in one fixed array.\n     The array should be allocated with the double size of the expected number of entries.\n  */\n  template <class T_HASH, class T>\n  class NgClosedHashTable\n  {\n  protected:\n    ///\n    size_t size;\n    ///\n    size_t used;\n    ///\n    NgArray<T_HASH> hash;\n    ///\n    NgArray<T> cont;\n  public:\n    ///\n    NgClosedHashTable (size_t asize = 128)\n      : size(asize), used(0), hash(asize), cont(asize)\n    {\n      for (auto & v : hash)\n        SetInvalid(v);\n    }\n\n    NgClosedHashTable (NgClosedHashTable && ht2) = default;\n\n    NgClosedHashTable (NgFlatArray<T_HASH> _hash, NgFlatArray<T> _cont)\n      : size(_hash.Size()), used(0), hash(_hash.Size(), _hash.Addr(0)), cont(_cont.Size(), _cont.Addr(0))\n    {\n      for (auto & v : hash)\n        SetInvalid(v);\n    }\n\n\n    NgClosedHashTable & operator= (NgClosedHashTable && ht2) = default;\n\n    /// \n    size_t Size() const\n    {\n      return size;\n    }\n\n    /// is position used\n    bool UsedPos (size_t pos) const\n    {\n      return ! (IsInvalid(hash[pos]));\n    }\n\n    /// number of used elements\n    size_t UsedElements () const\n    {\n      return used;\n    }\n\n    size_t Position (const T_HASH ind) const\n    {\n      size_t i = HashValue(ind, size);\n      while (1)\n\t{\n\t  if (hash[i] == ind) return i;\n\t  if (IsInvalid(hash[i])) return size_t(-1);\n\t  i++;\n\t  if (i >= size) i = 0;\n\t}\n    }\n\n    void DoubleSize()\n    {\n      NgClosedHashTable tmp(2*Size());\n      for (auto both : *this)\n        tmp[both.first] = both.second;\n      *this = std::move(tmp);\n    }\n    \n    // returns true if new position is created\n    bool PositionCreate (const T_HASH ind, size_t & apos)\n    {\n      if (UsedElements()*2 > Size()) DoubleSize();\n      \n      size_t i = HashValue (ind, size);\n\n      while (1)\n\t{\n\t  if (IsInvalid(hash[i]))\n\t    { \n\t      hash[i] = ind; \n\t      apos = i;\n              used++;\n\t      return true;\n\t    }\n\t  if (hash[i] == ind) \n\t    { \n\t      apos = i; \n\t      return false; \n\t    }\n\t  i++;\n\t  if (i >= size) i = 0;\n\t}\n    }\n\n\n    ///\n    void Set (const T_HASH & ahash, const T & acont)\n    {\n      size_t pos;\n      PositionCreate (ahash, pos);\n      hash[pos] = ahash;\n      cont[pos] = acont;\n    }\n\n    ///\n    const T & Get (const T_HASH & ahash) const\n    {\n      size_t pos = Position (ahash);\n      if (pos == size_t(-1))\n        throw Exception (string(\"illegal key: \") + ToString(ahash) );\n      return cont[pos];\n    }\n\n    ///\n    bool Used (const T_HASH & ahash) const\n    {\n      return (Position (ahash) != size_t(-1));\n    }\n\n    void SetData (size_t pos, const T_HASH & ahash, const T & acont)\n    {\n      hash[pos] = ahash;\n      cont[pos] = acont;\n    }\n\n    void GetData (size_t pos, T_HASH & ahash, T & acont) const\n    {\n      ahash = hash[pos];\n      acont = cont[pos];\n    }\n  \n    void SetData (size_t pos, const T & acont)\n    {\n      cont[pos] = acont;\n    }\n\n    void GetData (size_t pos, T & acont) const\n    {\n      acont = cont[pos];\n    }\n\n    pair<T_HASH,T> GetBoth (size_t pos) const\n    {\n      return pair<T_HASH,T> (hash[pos], cont[pos]);\n    }\n\n    const T & operator[] (T_HASH key) const { return Get(key); }\n    T & operator[] (T_HASH key)\n    {\n      size_t pos;\n      PositionCreate(key, pos);\n      return cont[pos];\n    }\n    \n    void SetSize (size_t asize)\n    {\n      size = asize;\n      hash.Alloc(size);\n      cont.Alloc(size);\n\n      // for (size_t i = 0; i < size; i++)\n      // hash[i] = invalid;\n      // hash = T_HASH(invalid);\n      for (auto & v : hash)\n        SetInvalid(v);\n    }\n\n    void Delete (T_HASH key)\n    {\n      size_t pos = Position(key);\n      if (pos == size_t(-1)) return;\n      SetInvalid (hash[pos]); used--;\n      \n      while (1)\n        {\n          size_t nextpos = pos+1;\n          if (nextpos == size) nextpos = 0;\n          if (IsInvalid(hash[nextpos])) break;\n\n          auto key = hash[nextpos];\n          auto val = cont[nextpos];\n          SetInvalid (hash[nextpos]); used--;\n          \n          Set (key, val);\n          pos = nextpos;\n        }\n    }\n\n    void DeleteData()\n    {\n      for (auto & v : hash)\n        SetInvalid(v);\n      used = 0;\n    }\n    \n    class Iterator\n    {\n      const NgClosedHashTable & tab;\n      size_t nr;\n    public:\n      Iterator (const NgClosedHashTable & _tab, size_t _nr)\n        : tab(_tab), nr(_nr)\n      {\n        while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;\n      }\n      Iterator & operator++()\n      {\n        nr++;\n        while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;\n        return *this;\n      }\n      bool operator!= (const Iterator & it2) { return nr != it2.nr; }\n      auto operator* () const\n      {\n        T_HASH hash;\n        T val;\n        tab.GetData(nr, hash,val);\n        return std::make_pair(hash,val);\n      }\n    };\n\n    Iterator begin() const { return Iterator(*this, 0); }\n    Iterator end() const { return Iterator(*this, Size()); } \n  };\n\n  template <class T_HASH, class T>  \n  ostream & operator<< (ostream & ost,\n                        const NgClosedHashTable<T_HASH,T> & tab)\n  {\n    for (size_t i = 0; i < tab.Size(); i++)\n      if (tab.UsedPos(i))\n        {\n          T_HASH key;\n          T val;\n          tab.GetData (i, key, val);\n          ost << key << \": \" << val << \", \";\n        }\n    return ost;\n  }\n    \n\n  \n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/general/myadt.hpp",
    "content": "#ifndef FILE_MYADT\n#define FILE_MYADT\n\n/**************************************************************************/\n/* File:   myadt.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/* \n   include for all abstract data types\n*/\n\n\n#include \"../include/mystdlib.h\"\n#include \"../include/mydefs.hpp\"\n\n\n#include <core/ngcore.hpp>\nnamespace netgen\n{\n  using namespace ngcore;\n  using NgException = Exception;\n}\n#include \"parthreads.hpp\"\n// #include \"moveablemem.hpp\"\n// #include \"dynamicmem.hpp\"\n\n#include \"template.hpp\"\n#include \"ngarray.hpp\"\n#include \"table.hpp\"\n#include \"hashtabl.hpp\"\n\n\n#include \"ngbitarray.hpp\"\n#include \"spbita2d.hpp\"\n\n#include \"seti.hpp\"\n#include \"optmem.hpp\"\n// #include \"autoptr.hpp\"\n#include \"sort.hpp\"\n#include \"stack.hpp\"\n#include \"mystring.hpp\"\n\n// #include \"mpi_interface.hpp\"\n#include \"netgenout.hpp\"\n\n#endif\n"
  },
  {
    "path": "libsrc/general/mystring.cpp",
    "content": "\n//**************************************************************\n//\n// filename:             mystring.cpp\n//\n// project:              doctoral thesis\n//\n// author:               Dipl.-Ing. Gerstmayr Johannes\n//\n// generated:            20.12.98\n// last change:          20.12.98\n// description:          implementation for strings\n// remarks:\n//\n//**************************************************************\n\n// string class\n#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n\nnamespace netgen\n{\n\n  void ReadEnclString(istream & in, string & str, const char encl)\n  {\n    char currchar;\n    str = \"\";\n\n    in.get(currchar);\n    while(in && (currchar == ' ' || currchar == '\\t' || currchar == '\\n') )\n      in.get(currchar);\n\t\n    if(currchar == encl)\n      {\n\tin.get(currchar);\n\twhile(in && currchar != encl)\n\t  {\n\t    str += currchar;\n\t    in.get(currchar);\n\t  }\n      }\n    else\n      {\n\tin.putback(currchar);\n\tin >> str;\n      }\n  }\n\t    \n\t\n    \n  \n\n\nvoid DefaultStringErrHandler()\n{\n  cerr << \"Error : string operation out of range\\n\" << flush;\n}\n\nvoid (*MyStr::ErrHandler)() = DefaultStringErrHandler;\n\n  /*     \nMyStr::MyStr()\n{\n  length = 0;\n  str = shortstr;\n  str[0] = 0;\n}\n  */\n\nMyStr::MyStr(const char *s)\n{\n  length = unsigned(strlen(s));\n\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, s);\n}\n\n/*\nMyStr::MyStr(char s)\n{\n  length = 1;\n  str = shortstr;\n  str[0] = s;\n  str[1] = (char)0;\n}\n*/\n\nMyStr::MyStr(const MyStr& s)\n{\n  length = s.length;\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, s.str);\n}\n\nMyStr::MyStr(int i)\n{\n  char buffer[32];\n  snprintf(buffer, 32, \"%d\", i);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n  /*\nMyStr::MyStr(unsigned int i)\n{\n  char buffer[32];\n  sprintf(buffer, \"%d\", i);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n  */\nMyStr::MyStr(void * p)\n{\n  char buffer[32];\n  snprintf(buffer, 32, \"%p\", p);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n\n  /*\nMyStr::MyStr(long l)\n{\n  char buffer[32];\n  sprintf(buffer, \"%ld\", l);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n  */\n\nMyStr::MyStr(size_t l)\n{\n  char buffer[32];\n  snprintf(buffer, 32, \"%zu\", l);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n\nMyStr::MyStr(double d)\n{\n  char buffer[32];\n  //if (fabs(d) < 1E-100) {d = 0;}\n  snprintf(buffer, 32, \"%g\", d);\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n\nMyStr::MyStr(const Point3d& p)\n{\n  char buffer[80];\n  //if (fabs(d) < 1E-100) {d = 0;}\n  snprintf(buffer, 80, \"[%g, %g, %g]\", p.X(), p.Y(), p.Z());\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n\nMyStr::MyStr(const Vec3d& p)\n{\n  char buffer[80];\n  //if (fabs(d) < 1E-100) {d = 0;}\n  snprintf(buffer, 80, \"[%g, %g, %g]\", p.X(), p.Y(), p.Z());\n  length = unsigned(strlen(buffer));\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, buffer);\n}\n\nMyStr::MyStr(unsigned n, int)\n{\n  length = n;\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  str[n] = 0;\n}\n\nMyStr::MyStr(const string & st)\n{\n  length = unsigned(st.length());\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy (str, st.c_str());\n}\n\nMyStr::MyStr(string_view sv)\n{\n  length = unsigned(sv.length());\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy (str, sv.data());\n}\n\nMyStr::MyStr(const filesystem::path & path)\n    : MyStr(path.string())\n{ }\n\n\n\nMyStr MyStr::Left(unsigned r)\n{\n  if(r > length)\n    {\n      MyStr::ErrHandler();\n      MyStr s;\n      return s;\n    }\n  else\n    {\n      MyStr tmp(r, 0);\n      strncpy(tmp.str, str, r);\n      return tmp;\n    }\n}\n\nMyStr MyStr::Right(unsigned l)\n{\n  if(l > length)\n    {\n      MyStr::ErrHandler();\n      MyStr s;\n      return s;\n    }\n  else\n    {\n      MyStr tmp(l, 0);\n      strncpy(tmp.str, str + length - l, l);\n      return tmp;\n    }\n}\n\nMyStr& MyStr::InsertAt(unsigned pos, const MyStr& s)\n{\n  if(pos > length)\n    {\n      MyStr::ErrHandler();\n      return *this;\n    }\n  int newLength = length + s.length;\n  char *tmp = new char[newLength + 1];\n  strncpy(tmp, str, pos);\n  strcpy(tmp + pos, s.str);\n  strcpy(tmp + pos + s.length, str + pos);\n\n  if (length > SHORTLEN) delete [] str;\n  length = newLength;\n  if (length > SHORTLEN)\n    str = tmp;\n  else\n    {\n      strcpy (shortstr, tmp);\n      delete [] tmp;\n      str = shortstr;\n    }\n  return *this;\n}\n\nMyStr &MyStr::WriteAt(unsigned pos, const MyStr& s)\n{\n  if(pos > length)\n  {\n    MyStr::ErrHandler();\n    return *this;\n  }\n  unsigned n = length - pos;\n  if(s.length < n)\n    n = s.length;\n  strncpy(str + pos, s.str, n);\n  return *this;\n}\n\nvoid MyStr::ConvertTextToExcel()\n{\n  /*\n  for (int i = 0; i < Length(); i++)\n    {\n      if ((*this)[i]==',') {(*this)[i] = ';';}\n      else if ((*this)[i]=='.') {(*this)[i] = ',';}\n    }\n  */\n}\n\nvoid MyStr::ConvertExcelToText()\n{\n  /*\n  for (int i = 0; i < Length(); i++)\n    {\n      if ((*this)[i]==',') {(*this)[i] = '.';}\n      else if ((*this)[i]==';') {(*this)[i] = ',';}\n    }\n  */\n}\n\nMyStr& MyStr::operator = (const MyStr& s)\n{\n  if (length > SHORTLEN) delete [] str;\n  length = s.length;\n  if (length > SHORTLEN)\n    str = new char[length + 1];\n  else\n    str = shortstr;\n  strcpy(str, s.str);\n  return *this;\n}\n\nMyStr operator + (const MyStr& s1, const MyStr& s2)\n{\n  MyStr tmp(s1.length + s2.length, 0);\n  if (s1.length != 0) strcpy(tmp.str, s1.str);\n  if (s2.length != 0) strcpy(tmp.str + s1.length, s2.str);\n  return tmp;\n}\n\nvoid MyStr::operator += (const MyStr& s)\n{\n  if (length+s.length <= SHORTLEN)\n    {\n      if (s.length != 0) strcpy(shortstr + length, s.str);\n    }\n  else\n    {\n      char *tmp = new char[length + s.length + 1];\n      if (length != 0) strcpy(tmp, str);\n      if (s.length != 0) strcpy(tmp + length, s.str);\n      if (length > SHORTLEN) delete [] str;\n      length += s.length;\n      str = tmp;\n    }\n}\n\nchar& MyStr::operator [] (unsigned n)\n{\n  static char dummy;\n  if(n < length)\n    return str[n];\n  else\n  {\n    MyStr::ErrHandler();\n    return dummy;\n  }\n}\n\nchar MyStr::operator [] (unsigned n) const\n{\n  static char dummy;\n  if(n < length)\n    return str[n];\n  else\n  {\n    MyStr::ErrHandler();\n    return dummy;\n  }\n}\n\nMyStr MyStr::operator () (unsigned l, unsigned r)\n{\n  if((l > r) || (r > length))\n  {\n    MyStr::ErrHandler();\n    MyStr s;\n    return s;\n  }\n  else\n  {\n    int n = r - l + 1;\n    MyStr tmp(n, 0);\n    strncpy(tmp.str, str + 1, n);\n    return tmp;\n  }\n}\n\nstring MyStr::cpp_string(void) const\n{\n  string aux(str,length);\n  return aux;\n}\n\n/*\nistream& operator >> (istream& is, MyStr& s)\n{\n  const int buflen = 1000;\n  char buffer[buflen+1];\n\n  int end = 0;\n  s = \"\";\n  MyStr str;\n\n  while (!end)\n  {\n    is.get(buffer, buflen);\n    str = MyStr(buffer);\n    s += str;\n    if (is.peek() == EOF) {end = 1;}\n  }\n\n  return is;\n}\n*/\n/*\n#ifdef __borland\n::ifstream& operator >> (::ifstream& is, MyStr& s)       // wb\n{                                                        // wb\n  const int buflen = 1000;                               // wb\n  char buffer[buflen+1];                                 // wb\n                                                         // wb\n  int end = 0;                                           // wb\n  s = \"\";                                                // wb\n  MyStr str;                                             // wb\n                                                         // wb\n  while (!end)                                           // wb\n  {                                                      // wb\n    is.get(buffer, buflen);                              // wb\n    str = MyStr(buffer);                                 // wb\n    s += str;                                            // wb\n    if (is.peek() == EOF) {end = 1;}                     // wb\n  }                                                      // wb\n                                                         // wb\n  return is;                                             // wb\n}          \n\n#endif\n*/\n}\n"
  },
  {
    "path": "libsrc/general/mystring.hpp",
    "content": "\n//**************************************************************\n//\n// filename:             mystring.h\n//\n// project:              doctoral thesis, program smart\n//\n// author:               Dipl.-Ing. Gerstmayr Johannes\n//\n// generated:            20.12.98\n// last change:          20.12.98\n// description:          base class for strings\n// remarks:              string with n characters has\n//                       0..n-1 characters and at pos n a 0\n//\n//**************************************************************\n\n\n#ifndef MYSTRING__H\n#define MYSTRING__H\n\n#include <filesystem>\n\nnamespace netgen\n{\n\nclass Point3d;\nclass Vec3d;\n\n\n// extract string str which is enclosed by the given character encl from a given string in\nvoid ReadEnclString(istream & in, string & str, const char encl);\n\n\nclass MyStr;\n\nDLL_HEADER MyStr operator + (const MyStr &, const MyStr &);\nDLL_HEADER int operator == (const MyStr &, const MyStr &);\nDLL_HEADER int operator < (const MyStr &, const MyStr &);\nDLL_HEADER int operator <= (const MyStr &, const MyStr &);\nDLL_HEADER int operator > (const MyStr &, const MyStr &);\nDLL_HEADER int operator >= (const MyStr &, const MyStr &);\nDLL_HEADER int operator != (const MyStr &, const MyStr &);\nDLL_HEADER ostream& operator << (ostream &, const MyStr &);\nDLL_HEADER istream& operator >> (istream &, MyStr &);\n\nclass DLL_HEADER MyStr\n{\npublic:\n  MyStr();\n  MyStr(const char *);\n  MyStr(char);\n  MyStr(const MyStr &);\n  MyStr(int);\n  MyStr(size_t);\n  MyStr(void *);\n  // MyStr(long);\n  // MyStr(unsigned long);\n  MyStr(double);\n  MyStr(const Point3d& p);\n  MyStr(const Vec3d& p);\n  MyStr(const string & st);\n  MyStr(string_view sv);\n  MyStr(const filesystem::path & st);\n\n  ~MyStr();\n  MyStr Left(unsigned);\n  MyStr Right(unsigned);\n  MyStr& InsertAt(unsigned, const MyStr &);\n  MyStr& WriteAt(unsigned, const MyStr &);\n  unsigned Length() const;\n  int Find(const char);\n  int Find(const char *);\n  int Find(const MyStr &);\n  MyStr& operator = (const MyStr &);\n  DLL_HEADER friend MyStr operator + (const MyStr &, const MyStr &);\n  void operator += (const MyStr &);\n  char* c_str();\n  string cpp_string(void) const;\n\n  //change every ',' -> ';', '.' -> ','\n  void ConvertTextToExcel();\n  //change every ','->'.', ';'->','\n  void ConvertExcelToText();\n\n  MyStr operator () (unsigned, unsigned);\n  operator int();\n  operator double();\n  operator long();\n  operator char *();\n  char& operator [] (unsigned int);\n  char operator [] (unsigned int) const;\n\n  DLL_HEADER friend int operator == (const MyStr &, const MyStr &);\n  DLL_HEADER friend int operator < (const MyStr &, const MyStr &);\n  DLL_HEADER friend int operator <= (const MyStr &, const MyStr &);\n  DLL_HEADER friend int operator > (const MyStr &, const MyStr &);\n  DLL_HEADER friend int operator >= (const MyStr &, const MyStr &);\n  DLL_HEADER friend int operator != (const MyStr &, const MyStr &);\n  DLL_HEADER friend ostream& operator << (ostream &, const MyStr &);\n  DLL_HEADER friend istream& operator >> (istream &, MyStr &);\n  static void SetToErrHandler(void (*)());\nprivate:\n  MyStr(unsigned, int);\n  char *str;\n  unsigned length;\n  enum { SHORTLEN = 24 };\n  char shortstr[SHORTLEN+1];\n  static void(*ErrHandler)();\n};\n\n\ninline MyStr::MyStr()\n{\n  length = 0;\n  str = shortstr;\n  str[0] = 0;\n}\n\ninline MyStr::MyStr(char s)\n{\n  length = 1;\n  str = shortstr;\n  str[0] = s;\n  str[1] = (char)0;\n}\n\ninline MyStr::~MyStr()\n{\n  if (length > SHORTLEN)\n    delete [] str;\n}\n\ninline unsigned MyStr::Length() const\n{\n  return length;\n}\n\ninline int MyStr::Find(const char c)\n{\n  char *pos = strchr(str, int(c));\n  return pos ? int(pos - str) : -1;\n}\n\ninline int MyStr::Find(const MyStr &s)\n{\n  char *pos = strstr(str, s.str);\n  return pos ? int(pos - str) : -1;\n}\n\ninline int MyStr::Find(const char *s)\n{\n  char *pos = strstr(str, s);\n  return pos ? int(pos - str) : -1;\n}\n\ninline MyStr::operator int()\n{\n  return atoi(str);\n}\n\ninline MyStr::operator double()\n{\n  return atof(str);\n}\n\ninline MyStr::operator long()\n{\n  return atol(str);\n}\n\ninline MyStr::operator char *()\n{\n  return str;\n}\n\ninline char* MyStr::c_str()\n{\n  return str;\n}\n\n\ninline int operator == (const MyStr &s1, const MyStr& s2)\n{\n  return strcmp(s1.str, s2.str) == 0;\n}\n\ninline int operator < (const MyStr &s1, const MyStr& s2)\n{\n  return strcmp(s1.str, s2.str) < 0;\n}\n\ninline int operator <= (const MyStr &s1, const MyStr& s2)\n{\n  return strcmp(s1.str, s2.str) <= 0;\n}\n\ninline int operator > (const MyStr &s1, const MyStr& s2)\n{\n  return strcmp(s1.str, s2.str) > 0;\n}\n\ninline int operator >= (const MyStr &s1, const MyStr& s2)\n{\n  return strcmp(s1.str, s2.str) >= 0;\n}\n\ninline int operator != (const MyStr &s1, const MyStr& s2)\n{\n  return !(s1 == s2);\n}\n\ninline ostream& operator << (ostream& os, const MyStr& s)\n{\n  return os << s.str;\n}\n\ninline void MyStr::SetToErrHandler(void (*Handler)())\n{\n  ErrHandler = Handler;\n};\n\n}\n#endif\n\n   \n"
  },
  {
    "path": "libsrc/general/netgenout.hpp",
    "content": "#ifndef NETGEN_OUT_STREAM_HPP__\n#define NETGEN_OUT_STREAM_HPP__\n\n// #include <ostream>\n// #include <mystdlib.h>\n// #include <meshing.hpp>\n// #include \"mpi_interface.hpp\"\n\nnamespace netgen\n{\n\n  //DLL_HEADER extern int printmessage_importance;\nDLL_HEADER extern int printdots;\n\n\n\nclass Imp\n{\n  int importance;\npublic:\n  Imp () : importance(0) { ; }\n\n  Imp ( int aimportance ) : importance(aimportance) { ; }\n\n  int GetImp () const { return importance; }\n};\n\n\nclass Proc\n{\n  int proc;\npublic:\n  Proc () : proc(0) { ; }\n\n  Proc ( int aproc ) : proc(aproc) { ; }\n\n  int GetProc () const { return proc; }\n};\n\nclass Procs\n{\n  const netgen::NgFlatArray<int> procs;\n\npublic:\n\n  Procs ( const netgen::NgFlatArray<int> & aprocs ) : procs (aprocs) { ; }\n\n  const netgen::NgFlatArray<int> & GetProcs () const { return procs; }\n};\n\n\n\nclass NetgenOutStream\n{\n  ostream * out;\n\n  bool print;\n  bool printheader;\n\n\npublic:\n  NetgenOutStream() :\n    out(&std::cout),\n    print(1),\n    printheader(1)\n  {\n    ;\n  }  \n\n  NetgenOutStream(ostream * aout, Imp imp ) :\n    out(aout),\n    printheader(1)\n  { \n    if ( netgen::printmessage_importance >= imp.GetImp() )\n      print = true;\n    else\n      print = false;\n  }\n\n  NetgenOutStream(ostream * aout, Proc proc ) :\n    out(aout),\n    printheader(1)\n  { \n#ifdef PARALLEL\n    if ( netgen::id == proc.GetProc() )\n      print = true;\n    else\n      print = false;\n#else\n    if ( 0 == proc.GetProc() )\n      print = true;\n    else\n      print = false;\n\n#endif\n  }\n\n  NetgenOutStream(ostream * aout, Procs & procs ) :\n    out(aout),\n    printheader(1)\n  { \n#ifdef PARALLEL\n    if ( procs.GetProcs().Contains(netgen::id) )\n      print = true;\n    else\n      print = false;\n#else\n    if ( procs.GetProcs().Contains(0) )\n      print = true;\n    else\n      print = false;\n\n#endif\n  }\n\n  ostream & OStream ()\n  {\n    return *out;\n  }\n\n  template <typename T>\n  NetgenOutStream & operator<< (T & var)\n  {\n    if ( print )\n      {\n#ifdef PARALLEL\n\tif ( printheader )\n\t  {\n\t    *out << \"proc \" << netgen::id << \": \";\n\t    printheader = false;\n\t  }\n#endif\n\t*out << var;\n      }\n    return (*this); \n  }\n\n  NetgenOutStream& operator<< (ostream& ( *pf )(ostream&))\n  {\n    if ( print )\n      *out << (*pf) ;\n\n    return (*this);\n  }\n\n  NetgenOutStream& operator<< (ios& ( *pf )(ios&))\n  {\n    if ( print)\n      *out << (*pf) ;\n\n    printheader = 1;\n\n    return (*this);\n  }\n\n  NetgenOutStream& operator<< (ios_base& ( *pf )(ios_base&))\n  {\n    if (print )\n      *out << (*pf) ;\n    return (*this);\n  }\n\n\n};\n\n/*\nNetgenOutStream operator<< ( ostream & ost, Imp  imp );\nNetgenOutStream operator<< ( ostream & ost, Proc proc );\nNetgenOutStream operator<< ( ostream & ost, Procs & procs );\n*/\n\ninline NetgenOutStream operator<< ( ostream & ost, Imp  imp )\n  {\n    return ( NetgenOutStream ( &ost, imp ) );\n  }\n\ninline   NetgenOutStream operator<< ( ostream & ost, Proc proc )\n  {\n    return ( NetgenOutStream ( &ost, proc ) );\n  }\n\n\ninline   NetgenOutStream operator<< ( ostream & ost, Procs & procs )\n  {\n    return ( NetgenOutStream ( &ost, procs ) );\n  }\n\n\n\n// {\n//   return ( NetgenOutStream ( &ost, imp.GetImp() ) );\n// }\n\n// template <typename T>\n// NetgenOutStream& operator<< (NetgenOutStream& out, T c )\n// {\n//   out.OStream() << c << endl;\n//   return out;\n// }\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/general/ngarray.hpp",
    "content": "#ifndef NGARRAY_HPP_INCLUDED\n#define NGARRAY_HPP_INCLUDED\n\n/**************************************************************************/\n/* File:   ngarray.hpp                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <core/array.hpp>\n\nnamespace netgen\n{\n  using namespace ngcore;\n\n  // template <class T, int B1, int B2> class IndirectArray;\n  template <class TA1, class TA2> class NgIndirectArray;\n\n\n\n\n  template <typename TSIZE>\n  class ArrayRangeIterator\n  {\n    TSIZE ind;\n  public:\n    ArrayRangeIterator (TSIZE ai) : ind(ai) { ; }\n    ArrayRangeIterator operator++ (int) { return ind++; }\n    ArrayRangeIterator operator++ () { return ++ind; }\n    TSIZE operator*() const { return ind; }\n    bool operator != (ArrayRangeIterator d2) { return ind != d2.ind; }\n  };\n\n  /// a range of integers\n  template <typename T>\n  class T_Range\n  {\n    T first, next;\n  public: \n    T_Range (T f, T n) : first(f), next(n) {;} \n    T Size() const { return next-first; }\n    T operator[] (T i) const { return first+i; }\n    bool Contains (T i) const { return ((i >= first) && (i < next)); }\n    T_Range Modify (int inc_begin, int inc_end) const\n    { return T_Range(first+inc_begin, next+inc_end); }\n    ArrayRangeIterator<T> begin() const { return first; }\n    ArrayRangeIterator<T> end() const { return next; }\n  };\n\n\n  template <typename T, int BASE = 0, typename TIND = int>\n  class NgFlatArray;\n\n  template <typename T, int BASE, typename TIND>\n  class ArrayIterator\n  {\n    NgFlatArray<T,BASE,TIND> ar;\n    TIND ind;\n  public:\n    ArrayIterator (NgFlatArray<T,BASE,TIND> aar, TIND ai) : ar(aar), ind(ai) { ; }\n    ArrayIterator operator++ (int)  { return ArrayIterator(ar, ind++); }\n    ArrayIterator operator++ ()   { return ArrayIterator(ar, ++ind); }\n    T operator*() const { return ar[ind]; }\n    T & operator*() { return ar[ind]; }\n    bool operator != (ArrayIterator d2) { return ind != d2.ind; }\n    bool operator == (ArrayIterator d2) { return ind == d2.ind; }\n  };\n\n\n\n  /**\n     A simple array container.\n     NgArray represented by size and data-pointer.\n     No memory allocation and deallocation, must be provided by user.\n     Helper functions for printing. \n     Optional range check by macro RANGE_CHECK\n  */\n\n  template <typename T, int BASE, typename TIND>\n  class NgFlatArray\n  {\n  protected:\n    /// the size\n    size_t size;\n    /// the data\n    T * data;\n  public:\n    typedef T TELEM;\n    using index_type = TIND;\n\n    /// provide size and memory\n    NgFlatArray (size_t asize, T * adata) \n      : size(asize), data(adata) { ; }\n\n    /// the size\n    size_t Size() const { return size; }\n\n    ArrayIterator<T,BASE,TIND> begin() const\n    { return ArrayIterator<T,BASE,TIND> (*this, BASE); }\n    ArrayIterator<T,BASE,TIND> end() const\n    { return ArrayIterator<T,BASE,TIND> (*this, BASE+size); }\n\n    // TIND Begin() const { return TIND(BASE); }\n    // TIND End() const { return TIND(size+BASE); }\n    T_Range<TIND> Range() const { return T_Range<TIND>(BASE, size+BASE); }\n\n    [[deprecated(\"Use *Range().begin() instead\")]]\n    auto Begin() const { return *Range().begin(); }\n    [[deprecated(\"Use *Range().end() instead\")]]\n    auto End() const { return *Range().end(); }\n    \n    /// Access array. BASE-based\n    T & operator[] (TIND i) const\n    {\n      NETGEN_CHECK_RANGE(i,BASE,size+BASE);\n      return data[i-BASE]; \n    }\n\n    template <typename T2, int B2>\n    NgIndirectArray<NgFlatArray, NgFlatArray<T2,B2> > operator[] (const NgFlatArray<T2,B2> & ia) const\n    {\n      return NgIndirectArray<NgFlatArray, NgFlatArray<T2,B2> > (*this, ia);\n    }\n\n\n\n    /// Access array, one-based  (old fashioned)\n    T & Elem (int i)\n    {\n      NETGEN_CHECK_RANGE(i,1,size+1);\n      return ((T*)data)[i-1]; \n    }\n  \n    /// Access array, one-based  (old fashioned)\n    // [[deprecated(\"Use operator[] instead\")]]    \n    const T & Get (int i) const \n    {\n      NETGEN_CHECK_RANGE(i,1,size+1);\n      return ((const T*)data)[i-1]; \n    }\n\n    /// Access array, one-based  (old fashioned)\n    void Set (int i, const T & el)\n    { \n      NETGEN_CHECK_RANGE(i,1,size+1);\n      ((T*)data)[i-1] = el; \n    }\n\n    /// access first element\n    T & First () const\n    {\n      NETGEN_CHECK_RANGE(0,0,size);\n      return data[0];\n    }\n\n\n    /// access last element. check by macro CHECK_RANGE\n    T & Last () const\n    {\n      NETGEN_CHECK_RANGE(size-1,0,size);\n      return data[size-1];\n    }\n\n    /// Fill array with value val\n    NgFlatArray & operator= (const T & val)\n    {\n      for (int i = 0; i < size; i++)\n\tdata[i] = val;\n      return *this;\n    }\n\n    /// takes range starting from position start of end-start elements\n    const NgFlatArray<T> Range (TIND start, TIND end)\n    {\n      return NgFlatArray<T> (end-start, data+start);\n    }\n\n    /// first position of element elem, returns -1 if element not contained in array \n    TIND Pos(const T & elem) const\n    {\n      TIND pos = -1;\n      for(TIND i=0; pos==-1 && i < this->size; i++)\n\tif(elem == data[i]) pos = i;\n      return pos;\n    }\n\n    /// does the array contain element elem ?\n    bool Contains(const T & elem) const\n    {\n      return ( Pos(elem) >= 0 );\n    }\n\n    operator ngcore::FlatArray<T> () const\n    {\n      static_assert (BASE==0);\n      return ngcore::FlatArray<T>(size, data);\n    }\n  };\n\n\n\n  // print array\n  template <typename T, int BASE, typename TIND>\n  inline ostream & operator<< (ostream & s, const NgFlatArray<T,BASE,TIND> & a)\n  {\n    // for (TIND i = a.Begin(); i < a.End(); i++)\n    for (auto i : a.Range())\n      s << i << \": \" << a[i] << endl;\n    return s;\n  }\n\n\n  /** \n      Dynamic array container.\n   \n      NgArray<T> is an automatically increasing array container.\n      The allocated memory doubles on overflow. \n      Either the container takes care of memory allocation and deallocation,\n      or the user provides one block of data.\n  */\n  template <class T, int BASE = 0, typename TIND = int> \n  class NgArray : public NgFlatArray<T, BASE, TIND>\n  {\n  protected:\n    using NgFlatArray<T,BASE,TIND>::size;\n    using NgFlatArray<T,BASE,TIND>::data;\n\n    /// physical size of array\n    size_t allocsize = 0;\n    /// memory is responsibility of container\n    bool ownmem;\n\n  public:\n\n    /// Generate array of logical and physical size asize\n    explicit NgArray()\n      : NgFlatArray<T, BASE, TIND> (0, NULL)\n    {\n      allocsize = 0; \n      ownmem = 1;\n    }\n\n    explicit NgArray(size_t asize)\n      : NgFlatArray<T, BASE, TIND> (asize, asize ? new T[asize] : nullptr)\n    {\n      allocsize = asize;\n      ownmem = (asize == 0) ? 0 : 1;\n    }\n\n    /// Generate array in user data\n    NgArray(TIND asize, T* adata)\n      : NgFlatArray<T, BASE, TIND> (asize, adata)\n    {\n      allocsize = asize; \n      ownmem = 0;\n    }\n\n    /// array copy \n    explicit NgArray (const NgArray<T,BASE,TIND> & a2)\n      : NgFlatArray<T, BASE, TIND> (a2.Size(), a2.Size() ? new T[a2.Size()] : 0)\n    {\n      allocsize = size;\n      ownmem = 1;\n      for (TIND i = BASE; i < size+BASE; i++)\n\t(*this)[i] = a2[i];\n    }\n\n    /// array move\n    NgArray (NgArray && a2)\n      : NgFlatArray<T,BASE,TIND> (a2.size, a2.data), allocsize(a2.allocsize), ownmem(a2.ownmem)\n    {\n      a2.size = 0;\n      a2.data = nullptr;\n      a2.allocsize = 0;\n      a2.ownmem = false;\n    }\n\n\n    /// if responsible, deletes memory\n    ~NgArray()\n    {\n      if (ownmem)\n\tdelete [] data;\n    }\n\n    /// Change logical size. If necessary, do reallocation. Keeps contents.\n    void SetSize(size_t nsize)\n    {\n      if (nsize > allocsize) \n\tReSize (nsize);\n      size = nsize; \n    }\n\n    void SetSize0()\n    {\n      size = 0; \n    }\n\n    /// Change physical size. Keeps logical size. Keeps contents.\n    void SetAllocSize (size_t nallocsize)\n    {\n      if (nallocsize > allocsize)\n\tReSize (nallocsize);\n    }\n\n\n    /// Add element at end of array. reallocation if necessary.\n    void Append (const T & el)\n    {\n      if (size == allocsize) \n\tReSize (size+1);\n      data[size] = el;\n      size++;\n      // return size;\n    }\n\n    template <typename T2, int B2>\n    void Append (NgFlatArray<T2, B2> a2)\n    {\n      if (size+a2.Size() > allocsize)\n\tReSize (size+a2.Size());\n      for (int i = 0; i < a2.Size(); i++)\n\tdata[size+i] = a2[i+B2];\n      size += a2.Size();\n    }\n\n\n    /// Delete element i (0-based). Move last element to position i.\n    void Delete (TIND i)\n    {\n      NETGEN_CHECK_RANGE(i,0,size);\n      data[i] = std::move(data[size-1]);\n      size--;\n      //    DeleteElement (i+1);\n    }\n\n\n    /// Delete element i (1-based). Move last element to position i.\n    void DeleteElement (TIND i)\n    {\n      NETGEN_CHECK_RANGE(i,1,size+1);\n      data[i-1] = std::move(data[size-1]);\n      size--;\n    }\n\n    /// Delete last element. \n    void DeleteLast ()\n    {\n      size--;\n    }\n\n    /// Deallocate memory\n    void DeleteAll ()\n    {\n      if (ownmem)\n\tdelete [] data;\n      data = 0;\n      size = allocsize = 0;\n    }\n\n    /// Fill array with val\n    NgArray & operator= (const T & val)\n    {\n      NgFlatArray<T, BASE, TIND>::operator= (val);\n      return *this;\n    }\n\n    /// array copy\n    NgArray & operator= (const NgArray & a2)\n    {\n      SetSize (a2.Size());\n      for (TIND i (BASE); i < size+BASE; i++)\n\t(*this)[i] = a2[i];\n      return *this;\n    }\n\n    /// array copy\n    NgArray & operator= (const NgFlatArray<T> & a2)\n    {\n      SetSize (a2.Size());\n      for (TIND i = BASE; i < size+BASE; i++)\n\t(*this)[i] = a2[i];\n      return *this;\n    }\n\n    NgArray & operator= (NgArray && a2)\n    {\n      ngcore::Swap (data, a2.data);\n      ngcore::Swap (size, a2.size);\n      ngcore::Swap (allocsize, a2.allocsize);\n      ngcore::Swap (ownmem, a2.ownmem);\n      return *this;\n    }\n\n    T * Release()\n    {\n      ownmem = false;\n      return data;\n    }\n\n    // Only provide this function if T is archivable\n    template<typename ARCHIVE>\n    auto DoArchive(ARCHIVE& archive)\n      -> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>\n    {\n      if(archive.Output())\n        archive << size;\n      else\n        {\n          size_t s;\n          archive & s;\n          SetSize(s);\n        }\n      archive.Do(data, size);\n    }\n    \n  private:\n\n    /// resize array, at least to size minsize. copy contents\n    void ReSize (size_t minsize)\n    {\n      size_t nsize = 2 * allocsize;\n      if (nsize < minsize) nsize = minsize;\n\n      if (data)\n\t{\n\t  T * p = new T[nsize];\n\t\n\t  size_t mins = (nsize < size) ? nsize : size; \n\n          if constexpr(std::is_trivially_copyable<T>::value)\n            memcpy (p, data, sizeof(T)*mins);\n          else\n            for (size_t i = 0; i < mins; i++) p[i] = std::move(data[i]);\n\n\t  if (ownmem)\n\t    delete [] data;\n\t  ownmem = 1;\n\t  data = p;\n\t}\n      else\n\t{\n\t  data = new T[nsize];\n\t  ownmem = 1;\n\t}\n    \n      allocsize = nsize;\n    }\n  };\n\n\n\n  template <class T, int S> \n  class NgArrayMem : public NgArray<T>\n  {\n    using NgArray<T>::size;\n    using NgArray<T>::data;\n    using NgArray<T>::ownmem;\n\n    T mem[S];     // Intel C++ calls dummy constructor\n    // char mem[S*sizeof(T)];\n    // double mem[(S*sizeof(T)+7) / 8];\n  public:\n    /// Generate array of logical and physical size asize\n    explicit NgArrayMem(size_t asize = 0)\n      : NgArray<T> (S, static_cast<T*> (static_cast<void*>(&mem[0])))\n    {\n      size = asize;\n      if (asize > S)\n\t{\n\t  data = new T[asize];\n\t  ownmem = 1;\n\t}\n      // SetSize (asize);\n    }\n\n    NgArrayMem & operator= (const T & val)  \n    {\n      NgArray<T>::operator= (val);\n      return *this;\n    }\n\n    /// array copy\n    NgArrayMem & operator= (const NgFlatArray<T> & a2)\n    {\n      this->SetSize (a2.Size());\n      for (size_t i = 0; i < size; i++)\n\t(*this)[i] = a2[i];\n      return *this;\n    }\n\n  };\n\n\n\n\n  /*\n  template <class T, int B1, int B2>\n  class IndirectArray\n  {\n    const NgFlatArray<T, B1> & array;\n    const NgFlatArray<int, B2> & ia; \n    \n  public:\n    IndirectArray (const NgFlatArray<T,B1> & aa, const NgFlatArray<int, B2> & aia)\n    : array(aa), ia(aia) { ; }\n    int Size() const { return ia.Size(); }\n    const T & operator[] (int i) const { return array[ia[i]]; }\n  };\n  */\n\n  template <class TA1, class TA2>\n  class NgIndirectArray\n  {\n    const TA1 & array;\n    const TA2 & ia; \n    \n  public:\n    NgIndirectArray (const TA1 & aa, const TA2 & aia)\n    : array(aa), ia(aia) { ; }\n    int Size() const { return ia.Size(); }\n    [[deprecated(\"Use *Range().begin() instead\")]]    \n    int Begin() const { return ia.Begin(); }\n    [[deprecated(\"Use *Range().end() instead\")]]    \n    int End() const { return ia.End(); }\n\n    const typename TA1::TELEM & operator[] (int i) const { return array[ia[i]]; }\n    auto Range() const { return ia.Range(); }\n    // auto begin() const { return ia.begin(); }\n    // auto end() const { return ia.end(); }\n  };\n\n\n  template <typename T1, typename T2>\n  inline ostream & operator<< (ostream & s, const NgIndirectArray<T1,T2> & ia)\n  {\n    for (int i = ia.Begin(); i < ia.End(); i++)\n      s << i << \": \" << ia[i] << endl;\n    return s;\n  }\n  \n\n\n  /*\n\n  ///\n  template <class T, int BASE = 0> \n  class MoveableArray \n  {\n    int size;\n    int allocsize;\n    DynamicMem<T> data;\n\n  public:\n\n    MoveableArray()\n    { \n      size = allocsize = 0; \n      data.SetName (\"MoveableArray\");\n    }\n\n    MoveableArray(int asize)\n      : size(asize), allocsize(asize), data(asize)\n    { ; }\n  \n    ~MoveableArray () { ; }\n\n    int Size() const { return size; }\n\n    void SetSize(int nsize)\n    {\n      if (nsize > allocsize) \n\t{\n\t  data.ReAlloc (nsize);\n\t  allocsize = nsize;\n\t}\n      size = nsize;\n    }\n\n    void SetAllocSize (int nallocsize)\n    {\n      data.ReAlloc (nallocsize);\n      allocsize = nallocsize;\n    }\n\n    ///\n    T & operator[] (int i)\n    { return ((T*)data)[i-BASE]; }\n\n    ///\n    const T & operator[] (int i) const\n    { return ((const T*)data)[i-BASE]; }\n\n    ///\n    T & Elem (int i)\n    { return ((T*)data)[i-1]; }\n  \n    ///\n    const T & Get (int i) const \n    { return ((const T*)data)[i-1]; }\n\n    ///\n    void Set (int i, const T & el)\n    { ((T*)data)[i-1] = el; }\n\n    ///\n    T & Last ()\n    { return ((T*)data)[size-1]; }\n  \n    ///\n    const T & Last () const\n    { return ((const T*)data)[size-1]; }\n  \n    ///\n    int Append (const T & el)\n    {\n      if (size == allocsize) \n\t{\n\t  SetAllocSize (2*allocsize+1);\n\t}\n      ((T*)data)[size] = el;\n      size++;\n      return size;\n    }\n  \n    ///\n    void Delete (int i)\n    {\n      DeleteElement (i+1);\n    }\n\n    ///\n    void DeleteElement (int i)\n    {\n      ((T*)data)[i-1] = ((T*)data)[size-1];\n      size--;\n    }\n  \n    ///\n    void DeleteLast ()\n    { size--; }\n\n    ///\n    void DeleteAll ()\n    {\n      size = allocsize = 0;\n      data.Free();\n    }\n\n    ///\n    void PrintMemInfo (ostream & ost) const\n    {\n      ost << Size() << \" elements of size \" << sizeof(T) << \" = \" \n\t  << Size() * sizeof(T) << endl;\n    }\n\n    MoveableArray & operator= (const T & el)\n    {\n      for (int i = 0; i < size; i++)\n\t((T*)data)[i] = el;\n      return *this;\n    }\n\n\n    MoveableArray & Copy (const MoveableArray & a2)\n    {\n      SetSize (a2.Size());\n      for (int i = 0; i < this->size; i++)\n\tdata[i] = a2.data[i];\n      return *this;\n    }\n\n    /// array copy\n    MoveableArray & operator= (const MoveableArray & a2)\n    {\n      return Copy(a2);\n    }\n\n\n    void SetName (const char * aname)\n    {\n      data.SetName(aname);\n    }\n  private:\n    ///\n    //MoveableArray & operator= (MoveableArray &); //???\n    ///\n    //MoveableArray (const MoveableArray &); //???\n  };\n\n\n  template <class T>\n  inline ostream & operator<< (ostream & ost, MoveableArray<T> & a)\n  {\n    for (int i = 0; i < a.Size(); i++)\n      ost << i << \": \" << a[i] << endl;\n    return ost;\n  }\n  */\n\n\n  /// bubble sort array\n  template <class T>\n  inline void BubbleSort (const NgFlatArray<T> & data)\n  {\n    for (int i = 0; i < data.Size(); i++)\n      for (int j = i+1; j < data.Size(); j++)\n\tif (data[i] > data[j])\n\t  {\n\t    T hv = data[i];\n\t    data[i] = data[j];\n\t    data[j] = hv;\n\t  }\n  }\n\n  /// bubble sort array\n  template <class T, class S>\n  inline void BubbleSort (NgFlatArray<T> & data, NgFlatArray<S> & index)\n  {\n    for (int i = 0; i < data.Size(); i++)\n      for (int j = i+1; j < data.Size(); j++)\n\tif (data[i] > data[j])\n\t  {\n\t    T hv = data[i];\n\t    data[i] = data[j];\n\t    data[j] = hv;\n\t    \n\t    S hvs = index[i];\n\t    index[i] = index[j];\n\t    index[j] = hvs;\n\t  }\n  }\n\n\n  template <class T, class S>\n  void QuickSortRec (NgFlatArray<T> & data,\n\t\t     NgFlatArray<S> & index,\n\t\t     int left, int right)\n  {\n    int i = left;\n    int j = right;\n    T midval = data[(left+right)/2];\n  \n    do\n      {\n\twhile (data[i] < midval) i++;\n\twhile (midval < data[j]) j--;\n      \n\tif (i <= j)\n\t  {\n            ngcore::Swap (data[i], data[j]);\n            ngcore::Swap (index[i], index[j]);\n\t    i++; j--;\n\t  }\n      }\n    while (i <= j);\n    if (left < j) QuickSortRec (data, index, left, j);\n    if (i < right) QuickSortRec (data, index, i, right);\n  }\n\n  template <class T, class S>\n  void QuickSort (NgFlatArray<T> & data, NgFlatArray<S> & index)\n  {\n    if (data.Size() > 1)\n      QuickSortRec (data, index, 0, data.Size()-1);\n  }\n\n\n\n\n\n\n\n\n\n  template <class T> \n  void Intersection (const NgFlatArray<T> & in1, const NgFlatArray<T> & in2, \n\t\t     NgArray<T> & out)\n  {\n    out.SetSize(0);\n    for(int i=0; i<in1.Size(); i++)\n      if(in2.Contains(in1[i]))\n\tout.Append(in1[i]);\n  }\n  template <class T> \n  void Intersection (const NgFlatArray<T> & in1, const NgFlatArray<T> & in2, const NgFlatArray<T> & in3,\n\t\t     NgArray<T> & out)\n  {\n    out.SetSize(0);\n    for(int i=0; i<in1.Size(); i++)\n      if(in2.Contains(in1[i]) && in3.Contains(in1[i]))\n\tout.Append(in1[i]);\n  }\n}\n\n#endif // NGARRAY_HPP_INCLUDED\n\n"
  },
  {
    "path": "libsrc/general/ngbitarray.cpp",
    "content": "/**************************************************************************/\n/* File:   bitarray.cc                                                    */\n/* Autho: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/* \n   data type NgBitArray\n*/\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n\n\nnamespace netgen\n{\n  //using namespace netgen;\n\n  NgBitArray :: NgBitArray ()\n  {\n    size = 0;\n    data = NULL;\n  }\n\n  NgBitArray :: NgBitArray (int asize)\n  {\n    size = 0;\n    data = NULL;\n    SetSize (asize);\n  }\n\n  NgBitArray :: ~NgBitArray ()\n  {\n    delete [] data;\n  }\n\n  void NgBitArray :: SetSize (int asize)\n  {\n    if (size == asize) return;\n    delete [] data;\n\n    size = asize;\n    data = new unsigned char [Addr (size)+1];\n  }\n\n  void NgBitArray :: Set ()\n  {\n    if (!size) return;\n    for (int i = 0; i <= Addr (size); i++)\n      data[i] = UCHAR_MAX;\n  }\n\n  void NgBitArray :: Clear ()\n  {\n    if (!size) return;\n    for (int i = 0; i <= Addr (size); i++)\n      data[i] = 0;\n  }\n\n\n\n  void NgBitArray :: Invert ()\n  {\n    if (!size) return;\n    for (int i = 0; i <= Addr (size); i++)\n      data[i] ^= 255;\n  }\n\n  void NgBitArray :: And (const NgBitArray & ba2)\n  {\n    if (!size) return;\n    for (int i = 0; i <= Addr (size); i++)\n      data[i] &= ba2.data[i];\n  }\n\n\n  void NgBitArray :: Or (const NgBitArray & ba2)\n  {\n    if (!size) return;\n    for (int i = 0; i <= Addr (size); i++)\n      data[i] |= ba2.data[i];\n  }\n\n\n}\n"
  },
  {
    "path": "libsrc/general/ngbitarray.hpp",
    "content": "#ifndef FILE_BitArray\n#define FILE_BitArray\n\n/**************************************************************************/\n/* File:   bitarray.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <limits.h>\n\nnamespace netgen\n{\n\n/**\n   data type NgBitArray\n   \n   NgBitArray is a compressed array of Boolean information. By Set and Clear\n   the whole array or one bit can be set or reset, respectively. \n   Test returns the state of the occurring bit.\n   No range checking is done.\n\n   index ranges from 0 to size-1\n*/\nclass NgBitArray\n{\n  INDEX size;\n  unsigned char * data;\n\npublic:\n  \n  // [[ deprecated (\"use BitArray instead\")]]  \n  DLL_HEADER NgBitArray ();\n  ///\n  // [[ deprecated (\"use BitArray instead\")]]  \n  DLL_HEADER NgBitArray (INDEX asize);\n  ///\n  DLL_HEADER ~NgBitArray ();\n\n  /// \n  DLL_HEADER void SetSize (INDEX asize);\n  ///\n  INDEX Size () const\n  {\n    return size;\n  }\n\n  ///\n  DLL_HEADER void Set ();\n  ///\n  void Set (INDEX i)\n  {\n    data[Addr(i)] |= Mask(i);\n  }\n  \n  DLL_HEADER void Clear ();\n\n\n  void Clear (INDEX i)\n  {\n    data[Addr(i)] &= ~Mask(i);\n  }\n\n  bool Test (INDEX i) const\n  {\n    return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? true : false;\n  }\n\n  ///\n  void Invert ();\n  ///\n  void And (const NgBitArray & ba2);\n  ///\n  void Or (const NgBitArray & ba2);\nprivate:\n  ///\n  inline unsigned char Mask (INDEX i) const\n  {\n    return char(1) << (i % CHAR_BIT);\n  }\n  ///\n  inline INDEX Addr (INDEX i) const\n  {\n  return (i / CHAR_BIT);\n  }\n\n  ///\n  NgBitArray & operator= (NgBitArray &);\n  ///\n  NgBitArray (const NgBitArray &);\n};\n\n\n\n// print bitarray\ninline ostream & operator<< (ostream & s, const NgBitArray & a)\n{\n  for (int i = 1; i <= a.Size(); i++)\n    {\n      s << int (a.Test(i));\n      if (i % 40 == 0) s << \"\\n\";\n    }\n  if (a.Size() % 40 != 0) s << \"\\n\";\n  return s;\n}\n\n\n/*\ninline\nINDEX NgBitArray :: Size () const\n  {\n  return size;\n  }\n\ninline\nunsigned char NgBitArray :: Mask (INDEX i) const\n  {\n  return char(1) << (i % CHAR_BIT);\n  }\n\ninline\nINDEX NgBitArray :: Addr (INDEX i) const\n  {\n  return (i / CHAR_BIT);\n  }\ninline\nvoid NgBitArray :: Set (INDEX i)\n  {\n  data[Addr(i)] |= Mask(i);\n  }\n\ninline\nvoid NgBitArray :: Clear (INDEX i)\n  {\n  data[Addr(i)] &= ~Mask(i);\n  }\n\n\ninline\nint NgBitArray :: Test (INDEX i) const\n  {\n  return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? 1 : 0;\n  }\n\n*/\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/ngpython.hpp",
    "content": "#ifdef NG_PYTHON\n\n#include <core/python_ngcore.hpp>\n\n#include <pybind11/operators.h>\n#include <pybind11/numpy.h>\n#include <pybind11/stl.h>\n#include <iostream>\n#include <sstream>\n\n// using namespace ngcore;\n\ntemplate <typename T>\npy::array MoveToNumpy(std::vector<T>& vec)\n{\n  auto newvec = new std::vector<T>();\n  std::swap(*newvec, vec);\n  auto capsule = py::capsule(newvec, [](void *v) { delete reinterpret_cast<std::vector<T>*>(v); });\n  return py::array(newvec->size(), newvec->data(), capsule);\n}\n\nnamespace PYBIND11_NAMESPACE {\ntemplate<typename T>\nbool CheckCast( py::handle obj ) {\n  try{\n    obj.cast<T>();\n    return true;\n  }\n  catch (py::cast_error &e) {\n    return false;\n  }\n}\n\n\ntemplate <typename T>\nstruct extract\n{\n  py::handle obj;\n  extract( py::handle aobj ) : obj(aobj) {}\n\n  bool check() { return CheckCast<T>(obj); }\n  T operator()() { return obj.cast<T>(); }\n};\n}\n\nstruct NGDummyArgument {};\n\ninline void NOOP_Deleter(void *) { ; }\n\nnamespace netgen\n{\n\n  //////////////////////////////////////////////////////////////////////\n  // Lambda to function pointer conversion\n  template <typename Function>\n  struct function_traits\n    : public function_traits<decltype(&Function::operator())> {};\n\n  template <typename ClassType, typename ReturnType, typename... Args>\n  struct function_traits<ReturnType(ClassType::*)(Args...) const> {\n    typedef ReturnType (*pointer)(Args...);\n    typedef ReturnType return_type;\n  };\n\n  template <typename Function>\n  typename function_traits<Function>::pointer\n  FunctionPointer (const Function& lambda) {\n    return static_cast<typename function_traits<Function>::pointer>(lambda);\n  }\n\n} // namespace netgen\n\n#endif\n\n"
  },
  {
    "path": "libsrc/general/optmem.cpp",
    "content": "/**************************************************************************/\n/* File:   optmem.cpp                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   04. Apr. 97                                                    */\n/**************************************************************************/\n\n/* \n   Abstract data type NgArray\n*/\n\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n\nnamespace netgen\n{\n  // static mutex block_allocator_mutex;\n\n  BlockAllocator :: BlockAllocator (unsigned asize, unsigned ablocks)\n    : bablocks (0)\n  {\n    if (asize < sizeof(void*))\n      asize = sizeof(void*);\n    size = asize;\n    blocks = ablocks;\n    freelist = NULL;\n  }\n\n  BlockAllocator :: ~BlockAllocator ()\n  {\n    lock_guard<mutex> guard(block_allocator_mutex);     \n    // cout << \"****************** delete BlockAllocator \" << endl;\n    for (int i = 0; i < bablocks.Size(); i++)\n      delete [] bablocks[i];\n    bablocks.SetSize(0);\n  }\n\n  void * BlockAllocator :: Alloc ()\n  {\n    void * p;\n    {\n      lock_guard<mutex> guard(block_allocator_mutex); \n      //  return new char[size];\n      if (!freelist)\n        {\n          // cout << \"freelist = \" << freelist << endl;\n          // cout << \"BlockAlloc: \" << size*blocks << endl;\n          char * hcp = new char [size * blocks];\n          bablocks.Append (hcp);\n          bablocks.Last() = hcp;\n          for (unsigned i = 0; i < blocks-1; i++)\n            *(void**)&(hcp[i * size]) = &(hcp[ (i+1) * size]);\n          *(void**)&(hcp[(blocks-1)*size]) = NULL;\n          freelist = hcp;\n        }\n      \n      p = freelist;\n      freelist = *(void**)freelist;\n    }\n    return p;\n  }\n\n  void BlockAllocator :: Free (void * p)\n  {\n    {\n      lock_guard<mutex> guard(block_allocator_mutex); \n      if (bablocks.Size())\n        {\n          *(void**)p = freelist;\n          freelist = p;\n        }\n    }\n  }\n\n}\n"
  },
  {
    "path": "libsrc/general/optmem.hpp",
    "content": "#ifndef FILE_OPTMEM\n#define FILE_OPTMEM\n\n/**************************************************************************/\n/* File:   optmem.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   04. Apr. 97                                                    */\n/**************************************************************************/\n\n#include <mydefs.hpp>\n\n#include \"ngarray.hpp\"\n\nnamespace netgen\n{\n\n/** \n    Optimized Memory allocation classes\n*/\n\nclass BlockAllocator\n{\nprivate:\n  ///\n  unsigned size, blocks;\n  ///\n  void * freelist;\n  ///\n  NgArray<char*> bablocks;\n  mutex block_allocator_mutex;\npublic:\n  ///\n  DLL_HEADER BlockAllocator (unsigned asize, unsigned ablocks = 100);\n  ///\n  DLL_HEADER ~BlockAllocator ();\n  ///\n  DLL_HEADER void * Alloc ();\n  ///\n  DLL_HEADER void Free (void * p);\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/parthreads.cpp",
    "content": "/**************************************************************************/\r\n/* File:   parthreads.cpp                                                 */\r\n/* Author: Joachim Schoeberl                                              */\r\n/* Date:   01. Jun. 95                                                    */\r\n/**************************************************************************/\r\n\r\n\r\n#include <mystdlib.h>\r\n#include <myadt.hpp>\r\n\r\n/*\r\n\r\nnamespace netgen\r\n{\r\n  using namespace netgen;\r\n\r\n#ifdef WIN32\r\n\r\n  NgLock :: NgLock (NgMutex & mut)\r\n    : sl(&mut.cs)\r\n  {\r\n    ;\r\n  }\r\n\r\n  void NgLock :: Lock ()\r\n  {\r\n    sl.Lock();\r\n  }\r\n  void NgLock :: UnLock ()\r\n  {\r\n    sl.Unlock();\r\n  }\r\n\r\n\r\n#else\r\n\r\n#endif\r\n}\r\n\r\n*/\r\n"
  },
  {
    "path": "libsrc/general/parthreads.hpp",
    "content": "#ifndef FILE_PARTHREADS\n#define FILE_PARTHREADS\n\n/**************************************************************************/\n/* File:   parthreads.hh                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   22. Nov. 2000                                                  */\n/**************************************************************************/\n\n/*\n  Parallel thread, Mutex,\n*/\n#include <functional>\n\nnamespace netgen\n{\n\n#ifdef NO_PARALLEL_THREADS\n\nclass NgMutex { };\n\nclass NgLock\n{\npublic:\n  NgLock (NgMutex & mut, bool lock = 0) { ; }\n  void Lock () { ; }\n  void UnLock () { ; }\n};\n\n#else\n\ntypedef std::mutex NgMutex;\n\nclass NgLock\n{\n  NgMutex & mut;\n  bool locked;\npublic:\n  NgLock (NgMutex & ngmut, bool lock = false)\n    : mut (ngmut)\n  {\n    if (lock)\n      mut.lock();\n\n    locked = lock;\n  };\n\n  ~NgLock()\n  {\n    if (locked)\n      mut.unlock();\n  }\n\n  void Lock ()\n  {\n    mut.lock();\n    locked = true;\n  }\n  void UnLock ()\n  {\n    mut.unlock();\n    locked = false;\n  }\n  /*\n  int TryLock ()\n  {\n    return mut.try_lock();\n  }\n  */\n};\n\n\n#endif\n\n\n// Simple ParallelFor function to replace OpenMP\ntemplate<typename TFunc>\nvoid ParallelFor( int first, int next, const TFunc & f )\n{\n  int nthreads = std::thread::hardware_concurrency();\n  std::thread * threads = new std::thread[nthreads];\n  for (int i=0; i<nthreads; i++)\n    {\n      int myfirst = first + (next-first)*i/nthreads;\n      int mynext = first + (next-first)*(i+1)/nthreads;\n      threads[i] = std::thread( [myfirst,mynext,&f] ()\n        {\n          f(myfirst, mynext);\n        });\n    }\n\n  for (int i=0; i<nthreads; i++)\n    threads[i].join();\n  delete [] threads;\n}\n\n\n  \n  typedef void (*NgTaskManager)(std::function<void(int,int)>);\n  typedef void (*NgTracer)(std::string, bool);  // false .. start, true .. stop\n\n  inline void DummyTaskManager (std::function<void(int,int)> func)\n  {\n    func(0,2);\n    func(1,2);\n  }\n\n  inline void DummyTracer (std::string, bool) { ; }\n  \n  template <typename FUNC>\n  inline void ParallelFor (NgTaskManager tm, size_t n, FUNC func)\n  {\n    (*tm) ([n,func] (size_t nr, size_t nums)\n           {\n             size_t begin = nr*n / nums;\n             size_t end = (nr+1)*n / nums;\n\n             for (size_t i = begin; i < end; i++)\n               func(i);\n           });\n  }\n  \n  template <typename FUNC>\n  inline void ParallelForRange (NgTaskManager tm, size_t n, FUNC func)\n  {\n    (*tm) ([n,func] (size_t nr, size_t nums)\n           {\n             size_t begin = nr*n / nums;\n             size_t end = (nr+1)*n / nums;\n             func(begin, end);\n           });\n  }\n                    \n\n  \n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/seti.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n\nnamespace netgen\n{\n  //using namespace netgen;\n\n  IndexSet :: IndexSet (int maxind)\n  {\n    SetMaxIndex (maxind);\n  }\n\n  IndexSet :: ~IndexSet ()\n  {\n    Clear();\n  }\n\n\n  void IndexSet :: SetMaxIndex (int maxind)\n  {\n    if (maxind > flags.Size())\n      {\n\tflags.SetSize (2 * maxind);\n\tflags.Clear();\n      }\n  }\n\n  /*\n    int IndexSet :: IsIn (int ind) const\n    {\n    return flags.Test (ind);\n    }\n  */\n\n  /*\n    void IndexSet :: Add (int ind)\n    {\n    if (ind > flags.Size())\n    {\n    cerr << \"out of range\" << endl;\n    exit (1);\n    }\n\n    if (!flags.Test(ind))\n    {\n    set.Append (ind);\n    flags.Set (ind);\n    }\n    }\n  */\n\n  void IndexSet :: Del (int ind)\n  {\n    for (int i = 1; i <= set.Size(); i++)\n      if (set.Get(i) == ind)\n\t{\n\t  set.DeleteElement (ind);\n\t  break;\n\t}\n    flags.Clear (ind);\n  }\n\n  void IndexSet :: Clear ()\n  {\n    for (int i = 1; i <= set.Size(); i++)\n      flags.Clear (set.Get(i));\n    set.SetSize (0);\n  }\n}\n"
  },
  {
    "path": "libsrc/general/seti.hpp",
    "content": "#ifndef FILE_SETI\n#define FILE_SETI\n\n\n/**************************************************************************/\n/* File:   seti.hh                                                        */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   20. Mar. 98                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n/**\n  Set of Integers\n  */\nclass IndexSet\n{\n  NgArray<int> set;\n  NgBitArray flags;\npublic:\n  IndexSet (int maxind);\n  \n  ~IndexSet ();\n  /// increase range to maxind\n  void SetMaxIndex (int maxind);\n  int IsIn (int ind) const\n  { \n    return flags.Test (ind); \n  }\n\n  void Add (int ind)\n  {\n    if (!flags.Test(ind))\n      {\n\tset.Append (ind);\n\tflags.Set (ind);\n      }\n  }\n\n  void Del (int ind);\n  void Clear ();\n  \n  const NgArray<int> & GetArray() { return set; }\n};\n\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/general/sort.cpp",
    "content": "/**************************************************************************/\n/* File:   sort.cc                                                        */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   07. Jan. 00                                                    */\n/**************************************************************************/\n\n/* \n   Sorting\n*/\n\n\n#include <algorithm>\n#include <mystdlib.h>\n#include <myadt.hpp>\n\nnamespace netgen\n{\n\n  void Sort (const NgArray<double> & values,\n\t     NgArray<int> & order)\n  {\n    int n = values.Size();\n    int i, j;\n\n    order.SetSize (n);\n\n    for (i = 1; i <= n; i++)\n      order.Elem(i) = i;\n    for (i = 1; i <= n-1; i++)\n      for (j = 1; j <= n-1; j++)\n\tif (values.Get(order.Elem(j)) > values.Get(order.Elem(j+1)))\n\t  {\n\t    Swap (order.Elem(j), order.Elem(j+1));\n\t  }\n  }\n\n\n  void QuickSortRec (const NgArray<double> & values,\n\t\t     NgArray<int> & order, \n\t\t     int left, int right)\n  {\n    int i, j;\n    double midval;\n\n    i = left;\n    j = right;\n    midval = values.Get(order.Get((i+j)/2));\n  \n    do\n      {\n\twhile (values.Get(order.Get(i)) < midval) i++;\n\twhile (midval < values.Get(order.Get(j))) j--;\n      \n\tif (i <= j)\n\t  {\n\t    Swap (order.Elem(i), order.Elem(j));\n\t    i++; j--;\n\t  }\n      }\n    while (i <= j);\n    if (left < j) QuickSortRec (values, order, left, j);\n    if (i < right) QuickSortRec (values, order, i, right);\n  }\n\n  void QuickSort (const NgArray<double> & values,\n\t\t NgArray<int> & order)\n  {\n    int i, n = values.Size();\n    order.SetSize (n);\n    for (i = 1; i <= n; i++)\n      order.Elem(i) = i;\n\n    QuickSortRec (values, order, 1, order.Size());\n  }\n}\n"
  },
  {
    "path": "libsrc/general/sort.hpp",
    "content": "#ifndef FILE_SORT\n#define FILE_SORT\n\n/**************************************************************************/\n/* File:   sort.hh                                                        */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   07. Jan. 00                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n// order(i) is sorted index of element i\nextern void Sort (const NgArray<double> & values,\n\t\t  NgArray<int> & order);\n\nextern void QuickSort (const NgArray<double> & values,\n\t\t      NgArray<int> & order);\n\n\n\n\ntemplate <class T>\ninline void BubbleSort (int size, T * data)\n{\n  T hv;\n  for (int i = 0; i < size; i++)\n    for (int j = i+1; j < size; j++)\n      if (data[i] > data[j])\n\t{\n\t  hv = data[i];\n\t  data[i] = data[j];\n\t  data[j] = hv;\n\t}\n}\n\ntemplate <class T>\ninline void BubbleSort (NgArray<T> & data)\n{\n  if(data.Size() > 0)\n    // BubbleSort (data.Size(), &data[data.Begin()]);\n    BubbleSort (data.Size(), &data[*data.Range().begin()]);\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/spbita2d.cpp",
    "content": "/**************************************************************************/\n/* File:   spbita2d.cpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/* \n   Implementation of sparse 2 dimensional bitarray\n*/\n\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n\nnamespace netgen\n{\n  //using namespace netgen;\n\n  SPARSE_BIT_Array_2D :: SPARSE_BIT_Array_2D (int ah, int aw)\n  {\n    lines = NULL;\n    SetSize (ah, aw);\n  }\n\n  SPARSE_BIT_Array_2D :: ~SPARSE_BIT_Array_2D ()\n  {\n    DeleteElements ();\n    delete lines;\n  }\n\n\n  void SPARSE_BIT_Array_2D :: SetSize (int ah, int aw)\n  {\n    DeleteElements();\n    if (lines)\n      {\n\tdelete lines;\n\tlines = NULL;\n      }\n\n    if (!aw) aw = ah;\n\n    height = ah;\n    width = aw;\n\n    if (!ah) return;\n    lines = new linestruct[ah];\n\n    if (lines)\n      {\n\tfor (int i = 0; i < ah; i++)\n\t  {\n\t    lines[i].size = 0;\n\t    lines[i].maxsize = 0;\n\t    lines[i].col = NULL;\n\t  }\n      }\n    else\n      {\n\theight = width = 0;\n\tMyError (\"SPARSE_Array::SetSize: Out of memory\");\n      }\n  }\n\n\n\n  void SPARSE_BIT_Array_2D :: DeleteElements ()\n  {\n    if (lines)\n      {\n\tfor (int i = 0; i < height; i++)\n\t  {\n\t    if (lines[i].col)\n\t      {\n\t\tdelete [] lines[i].col;\n\t\tlines[i].col = NULL;\n\t\tlines[i].size = 0;\n\t\tlines[i].maxsize = 0;\n\t      }\n\t  }\n      }\n  }\n\n\n  int SPARSE_BIT_Array_2D :: Test (int i, int j) const\n  {\n    int k, max, *col;\n\n    if (!lines) return 0;\n    if (i < 1 || i > height) return 0;\n\n    col = lines[i-1].col;\n    max = lines[i-1].size;\n\n    for (k = 0; k < max; k++, col++)\n      if (*col == j) return 1;\n\n    return 0;\n  }\n\n\n\n  void SPARSE_BIT_Array_2D :: Set(int i, int j)\n  {\n    int k, max, *col;\n\n    i--;\n    col = lines[i].col;\n    max = lines[i].size;\n\n    for (k = 0; k < max; k++, col++)\n      if (*col == j)\n\treturn;\n\n    if (lines[i].size)\n      {\n\tif (lines[i].size == lines[i].maxsize)\n\t  {\n\t    col = new int[lines[i].maxsize+2];\n\t    if (col)\n\t      {\n\t\tlines[i].maxsize += 2;\n\t\tmemcpy (col, lines[i].col, sizeof (int) * lines[i].size);\n\t\tdelete [] lines[i].col;\n\t\tlines[i].col = col;\n\t      }\n\t    else\n\t      {\n\t\tMyError (\"SPARSE_BIT_Array::Set: Out of mem 1\");\n\t\treturn;\n\t      }\n\t  }\n\telse\n\t  col = lines[i].col;\n\n\tif (col)\n\t  {\n\t    k = lines[i].size-1;\n\t    while (k >= 0 && col[k] > j)\n\t      {\n\t\tcol[k+1] = col[k];\n\t\tk--;\n\t      }\n\n\t    k++;\n\t    lines[i].size++;\n\t    col[k] = j;\n\t    return;\n\t  }\n\telse\n\t  {\n\t    MyError (\"SPARSE_Array::Set: Out of memory 2\");\n\t  }\n      }\n    else\n      {\n\tlines[i].col = new int[4];\n\tif (lines[i].col)\n\t  {\n\t    lines[i].maxsize = 4;\n\t    lines[i].size = 1;\n\t    lines[i].col[0] = j;\n\t    return;\n\t  }\n\telse\n\t  {\n\t    MyError (\"SparseMatrix::Elem: Out of memory 3\");\n\t  }\n      }\n  }\n\n}\n"
  },
  {
    "path": "libsrc/general/spbita2d.hpp",
    "content": "#ifndef FILE_SPBITA2D\n#define FILE_SPBITA2D\n\n/**************************************************************************/\n/* File:   spbita2d.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/** \n   Implementation of sparse 2 dimensional bitarray\n*/\n\nnamespace netgen\n{\n\nclass SPARSE_BIT_Array_2D\n  {\n  class linestruct { public: INDEX size; INDEX maxsize; INDEX * col; };\n\n  ///\n  linestruct * lines;\n  ///\n  INDEX height, width;\n\n  public:\n\n  ///\n  SPARSE_BIT_Array_2D (INDEX ah = 0, INDEX aw = 0);\n  ///\n  ~SPARSE_BIT_Array_2D ();\n\n  ///\n  void SetSize (INDEX ah, INDEX aw = 0);\n  ///\n  void DeleteElements ();\n\n  ///\n  int Get (INDEX i, INDEX j) const;\n\n  ///\n  INDEX Height () const { return height; }\n  ///\n  INDEX Width () const { return width; }\n\n  ///\n  void Set (INDEX i, INDEX j);\n  ///\n  int Test (INDEX i, INDEX j) const;\n\n  ///\n  INDEX BitsInLine (INDEX i) const { return lines[i-1].size; }\n  ///\n  INDEX GetIndex (INDEX i, INDEX nr) const { return lines[i-1].col[nr-1]; }\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/stack.hpp",
    "content": "#ifndef FILE_STACK\n#define FILE_STACK\n\n/*****************************************************************************/\n/*  File: stack.hh                                                           */\n/*  Author: Wolfram Muehlhuber                                               */\n/*  Date: September 98                                                       */\n/*****************************************************************************/\n\n/*\n  \n  Stack class, based on a resizable array\n\n */\n\n\n// #include \"array.hpp\"\n\nnamespace netgen\n{\n\n///\ntemplate <class T> class STACK\n{\npublic:\n  ///\n  inline STACK (INDEX asize = 0, INDEX ainc = 0);\n  ///\n  inline ~STACK ();\n\n  ///\n  inline void Push (const T & el);\n  ///\n  inline T & Pop ();\n  ///\n  const inline T & Top () const;\n  ///\n  inline int IsEmpty () const;\n  ///\n  inline void MakeEmpty ();\n\nprivate:\n  ///\n  NgArray<T> elems;\n  ///\n  INDEX size;\n};\n\n\n\n\n/*\n  \n  Stack class, based on a resizable array\n\n */\n\ntemplate <class T>\ninline STACK<T> :: STACK (INDEX asize, INDEX ainc)\n  : elems(asize, ainc)\n{\n  size = 0;\n}\n\n\ntemplate <class T>\ninline STACK<T> :: ~STACK ()\n{\n  ;\n}\n\n\ntemplate <class T> \ninline void STACK<T> :: Push (const T & el)\n{\n  if (size < elems.Size())\n    elems.Elem(++size) = el;\n  else\n    {\n      elems.Append(el);\n      size++;\n    }\n}\n\n\ntemplate <class T> \ninline T & STACK<T> :: Pop ()\n{\n  return elems.Elem(size--);\n}\n\n\ntemplate <class T>\nconst inline T & STACK<T> :: Top () const\n{\n  return elems.Get(size);\n}\n\ntemplate <class T>\ninline int STACK<T> :: IsEmpty () const\n{\n  return (size == 0);\n}\n\n\ntemplate <class T>\ninline void STACK<T> :: MakeEmpty ()\n{\n  size = 0;\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/general/table.cpp",
    "content": "/**************************************************************************/\n/* File:   table.cpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n/* \n   Abstract data type TABLE\n*/\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n\nnamespace netgen\n{\n  //using namespace netgen;\n\n  BASE_TABLE :: BASE_TABLE (int size)\n    : data(size)\n  {\n    for (int i = 0; i < size; i++)\n      {\n\tdata[i].maxsize = 0;\n\tdata[i].size = 0;\n\tdata[i].col = NULL;\n      }\n    oneblock = NULL;\n  }\n\n  BASE_TABLE :: BASE_TABLE (const NgFlatArray<int> & entrysizes, int elemsize)\n    : data(entrysizes.Size())\n  {\n    size_t cnt = 0;\n    size_t n = entrysizes.Size();\n\n    for (size_t i = 0; i < n; i++)\n      cnt += entrysizes[i];\n    oneblock = new char[elemsize * cnt];\n    // mem_total_alloc_table += elemsize * cnt;\n\n    cnt = 0;\n    for (size_t i = 0; i < n; i++)\n      {\n\tdata[i].maxsize = entrysizes[i];\n\tdata[i].size = 0;\n\n\tdata[i].col = &oneblock[elemsize * cnt];\n\tcnt += entrysizes[i];\n      }\n  }\n\n  BASE_TABLE :: ~BASE_TABLE ()\n  {\n    if (oneblock)\n      delete [] oneblock;\n    else\n      {\n\tfor (int i = 0; i < data.Size(); i++)\n\t  delete [] (char*)data[i].col;\n      }\n  }\n  \n  void BASE_TABLE :: SetSize (int size)\n  {\n    for (int i = 0; i < data.Size(); i++)\n      delete [] (char*)data[i].col;\n    \n    data.SetSize(size);\n    for (int i = 0; i < size; i++)\n      {\n\tdata[i].maxsize = 0;\n\tdata[i].size = 0;\n\tdata[i].col = NULL;\n      }    \n  }\n  \n  void BASE_TABLE :: ChangeSize (int size)\n  {\n    int oldsize = data.Size();\n    if (size == oldsize) \n      return;\n\n    if (size < oldsize)\n      for (int i = size; i < oldsize; i++)\n\tdelete [] (char*)data[i].col;\n    \n    data.SetSize(size);\n\n    for (int i = oldsize; i < size; i++)\n      {\n\tdata[i].maxsize = 0;\n\tdata[i].size = 0;\n\tdata[i].col = NULL;\n      }    \n  }\n\n  void BASE_TABLE :: IncSize2 (int i, int elsize)\n  {\n#ifdef DEBUG\n    if (i < 0 || i >= data.Size())\n      {\n\tMyError (\"BASE_TABLE::Inc: Out of range\");\n\treturn;\n      }\n#endif\n\n    linestruct & line = data[i];\n    if (line.size == line.maxsize)\n      {\n\tvoid * p = new char [(line.maxsize+5) * elsize];\n\n        if (line.maxsize && elsize)\n          memcpy (p, line.col, line.maxsize * elsize);\n\tdelete [] (char*)line.col;\n\n\tline.col = p;\n\tline.maxsize += 5;\n      }\n  \n    line.size++;\n  }\n\n\n\n\n  void BASE_TABLE :: SetEntrySize2 (int i, int newsize, int elsize)\n  {\n    linestruct & line = data[i];\n    if (newsize > line.maxsize)\n      {\n\tvoid * p = new char [newsize * elsize];\n      \n\tmemcpy (p, line.col, min2 (newsize, line.size) * elsize);\n\tdelete [] (char*)line.col;\n\n\tline.col = p;\n      }\n\n    line.size = newsize;\n  }\n\n\n\n\n\n  /*\n  void BASE_TABLE :: DecSize (int i)\n  {\n#ifdef DEBUG\n    if (i < 0 || i >= data.Size())\n      {\n\tMyError (\"BASE_TABLE::Dec: Out of range\");\n\treturn;\n      }\n#endif\n\n    linestruct & line = data[i];\n  \n#ifdef DEBUG\n    if (line.size == 0)\n      {\n\tMyError (\"BASE_TABLE::Dec: EntrySize < 0\");\n\treturn;      \n      }\n#endif\n  \n    line.size--;\n  }\n  */\n\n\n\n  void BASE_TABLE :: AllocateElementsOneBlock (int elemsize)\n  {\n    size_t cnt = 0;\n    size_t n = data.Size();\n\n    for (size_t i = 0; i < n; i++)\n      cnt += data[i].maxsize;\n    oneblock = new char[elemsize * cnt];\n\n    cnt = 0;\n    for (size_t i = 0; i < n; i++)\n      {\n\tdata[i].size = 0;\n\tdata[i].col = &oneblock[elemsize * cnt];\n\tcnt += data[i].maxsize;\n      }\n  }\n\n\n\n  size_t BASE_TABLE :: AllocatedElements () const\n  {\n    size_t els = 0;\n    for (size_t i = 0; i < data.Size(); i++)\n      els += data[i].maxsize;\n    return els;\n  }\n  \n  size_t BASE_TABLE :: UsedElements () const\n  {\n    size_t els = 0;\n    for (size_t i = 0; i < data.Size(); i++)\n      els += data[i].size;\n    return els;\n  }\n\n  void BASE_TABLE :: SetElementSizesToMaxSizes ()\n  {\n    for (int i = 0; i < data.Size(); i++)\n      data[i].size = data[i].maxsize;\n  }\n\n\n  \n  void BASE_TABLE :: DoArchive (Archive & ar, int elemsize)\n  {\n    if (ar.Output())\n      {\n        size_t entries = 0, size = data.Size();\n        for (size_t i = 0; i < data.Size(); i++)\n          entries += data[i].size;\n        ar & size & entries;\n        for (size_t i = 0; i < data.Size(); i++)\n          {\n            ar & data[i].size;\n            ar.Do ((unsigned char*)data[i].col, data[i].size*elemsize);\n            /*\n            for (size_t j = 0; j < data[i].size*elemsize; j++)\n              ar &  ((unsigned char*) data[i].col)[j];\n            cout << \"write \" << data[i].size*elemsize << \" chars\" << endl;\n            */\n          }\n      }\n    else\n      {\n        size_t entries, size;\n        ar & size & entries;\n        data.SetSize(size);\n        oneblock = new char [entries*elemsize];\n        size_t cnt = 0;\n        for (size_t i = 0; i < size; i++)\n          {\n            ar & data[i].size;\n            data[i].col = oneblock+cnt;\n            data[i].maxsize = data[i].size;\n            ar.Do ((unsigned char*)(oneblock+cnt), data[i].size*elemsize);\n            cnt += data[i].size*elemsize;\n          }\n      }\n  }    \n\n  \n}\n"
  },
  {
    "path": "libsrc/general/table.hpp",
    "content": "#ifndef FILE_TABLE\n#define FILE_TABLE\n\n/**************************************************************************/\n/* File:   table.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n/// Base class to generic class TABLE.\nclass BASE_TABLE\n{\nprotected:\n  \n  ///\n  class linestruct\n  {\n  public:\n    ///\n    int size;\n    /// \n    int maxsize;\n    ///\n    void * col;\n  };\n  \n  ///\n  NgArray<linestruct> data;\n  char * oneblock;\n\npublic:\n  ///\n  BASE_TABLE (BASE_TABLE && table2)\n    : data(std::move(table2.data)), oneblock(table2.oneblock)\n  {\n    table2.oneblock = nullptr;\n  }\n\n  DLL_HEADER BASE_TABLE (int size);\n  ///\n  DLL_HEADER BASE_TABLE (const NgFlatArray<int> & entrysizes, int elemsize);\n  ///\n  DLL_HEADER ~BASE_TABLE ();\n\n  BASE_TABLE & operator= (BASE_TABLE && table2)\n  {\n    data = std::move(table2.data);\n    Swap (oneblock, table2.oneblock);\n    return *this;\n  }\n  \n  ///\n  void SetSize (int size);\n  ///\n  void ChangeSize (int size);\n\n  /// increment size of entry i by one, i is 0-based\n  void IncSize (int i, int elsize)\n  {\n    if (data[i].size < data[i].maxsize)\n      data[i].size++;\n    else\n      IncSize2 (i, elsize);\n  }\n\n  void SetEntrySize (int i, int newsize, int elsize)\n  {\n    if (newsize < data[i].maxsize)\n      data[i].size = newsize;\n    else\n      SetEntrySize2 (i, newsize, elsize);\n  }\n\n  ///\n  void IncSize2 (int i, int elsize);\n  void SetEntrySize2 (int i, int newsize, int elsize);\n\n  //  void DecSize (int i);\n\n  ///\n  void AllocateElementsOneBlock (int elemsize);\n  \n  size_t AllocatedElements () const;\n  size_t UsedElements () const;\n\n  void SetElementSizesToMaxSizes ();\n\n  void DoArchive (Archive & ar, int elemsize);\n};\n\n\n\n\n\n\n\n/** \n   Abstract data type TABLE.\n   \n   To an integer i in the range from 1 to size a set of elements of the\n   generic type T is associated. \n*/\ntemplate <class T, int BASE = 0>\nclass TABLE : public BASE_TABLE\n{\npublic:\n  /// Creates table.\n  inline TABLE () : BASE_TABLE(0) { ; }\n  \n  /// Creates table of size size\n  inline TABLE (int size) : BASE_TABLE (size) { ; }\n\n  TABLE (TABLE && tab2)\n    : BASE_TABLE(move(tab2))\n  { }\n  \n  /// Creates fixed maximal element size table\n  inline TABLE (const NgFlatArray<int,BASE> & entrysizes)\n    : BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), entrysizes.Size() ? const_cast<int*>(&entrysizes[BASE]) : nullptr), \n\t\t  sizeof(T))\n  { ; }\n\n  TABLE & operator= (TABLE && tab2)\n  {\n    BASE_TABLE::operator=(move(tab2));\n    return *this;\n  }\n\n  \n  /// Changes Size of table to size, deletes data\n  inline void SetSize (int size)\n  {\n    BASE_TABLE::SetSize (size);\n  }\n\n  /// Changes Size of table to size, keep data\n  inline void ChangeSize (int size)\n  {\n    BASE_TABLE::ChangeSize (size);\n  }\n\n\n  /// Inserts element acont into row i, BASE-based. Does not test if already used.\n  inline void Add (int i, const T & acont)\n  {\n    IncSize (i-BASE, sizeof (T));\n    ((T*)data[i-BASE].col)[data[i-BASE].size-1] = acont;\n  }\n\n\n  /// Inserts element acont into row i, 1-based. Does not test if already used.\n  inline void Add1 (int i, const T & acont)\n  {\n    IncSize (i-1, sizeof (T));\n    ((T*)data.Elem(i).col)[data.Elem(i).size-1] = acont;\n  }\n  \n  ///\n  void IncSizePrepare (int i)\n  {\n    data[i-BASE].maxsize++;\n  }\n\n\n  /// Inserts element acont into row i. BASE-based. Does not test if already used, assumes to have enough memory\n  inline void AddSave (int i, const T & acont)\n    {\n      NETGEN_CHECK_RANGE(i, BASE, data.Size()+BASE);\n      ((T*)data[i-BASE].col)[data[i-BASE].size] = acont;\n      data[i-BASE].size++;\n    }\n\n  inline void ParallelAdd (int i, const T & acont)\n    {\n      auto oldval = AsAtomic (data[i-BASE].size)++;\n      ((T*)data[i-BASE].col)[oldval] = acont;\n    }\n\n  /// Inserts element acont into row i. 1-based. Does not test if already used, assumes to have mem\n  inline void AddSave1 (int i, const T & acont)\n    {\n      ((T*)data.Elem(i).col)[data.Elem(i).size] = acont;\n      data.Elem(i).size++;\n    }\n\n  /// Inserts element acont into row i. Does not test if already used.\n  inline void AddEmpty (int i)\n  {\n    IncSize (i-BASE, sizeof (T));\n  }\n\n  /** Set the nr-th element in the i-th row to acont.\n    Does not check for overflow. */\n  inline void Set (int i, int nr, const T & acont)\n    { ((T*)data.Get(i).col)[nr-1] = acont; }\n  /** Returns the nr-th element in the i-th row.\n    Does not check for overflow. */\n  inline const T & Get (int i, int nr) const\n    { return ((T*)data.Get(i).col)[nr-1]; }\n\n  inline T & Get (int i, int nr)\n    { return ((T*)data.Get(i).col)[nr-1]; }\n\n  /** Returns pointer to the first element in row i. */\n  inline const T * GetLine (int i) const\n  {\n    return ((const T*)data.Get(i).col);\n  }\n\n\n  /// Returns size of the table.\n  inline int Size () const\n  {\n    return data.Size();\n  }\n\n  /// Returns size of the i-th row.\n  inline int EntrySize (int i) const\n    { return data.Get(i).size; }\n\n  /*\n  inline void DecEntrySize (int i)\n    { DecSize(i); }\n  */\n  void AllocateElementsOneBlock ()\n    { BASE_TABLE::AllocateElementsOneBlock (sizeof(T)); }\n\n\n  inline void PrintMemInfo (ostream & ost) const\n  {\n    int els = AllocatedElements(); \n    ost << \"table: allocated \" << els \n\t<< \" a \" << sizeof(T) << \" Byts = \" \n\t<< els * sizeof(T) \n\t<< \" bytes in \" << Size() << \" bags.\"\n\t<< \" used: \" << UsedElements()\n\t<< endl;\n  }\n\n  /// Access entry.\n  NgFlatArray<T> operator[] (int i) const\n  { \n#ifdef DEBUG\n    if (i-BASE < 0 || i-BASE >= data.Size())\n      cout << \"table out of range, i = \" << i << \", s = \" << data.Size() << endl;\n#endif\n\n    return NgFlatArray<T> (data[i-BASE].size, (T*)data[i-BASE].col);\n  }\n\n  void DoArchive (Archive & ar)\n  {\n    BASE_TABLE::DoArchive(ar, sizeof(T));\n  }\n\n};\n\ntemplate <class T, int BASE>\ninline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table)\n{\n  for (int i = BASE; i < table.Size()+BASE; i++)\n    {\n      ost << i << \": \";\n      NgFlatArray<T> row = table[i];\n      ost << \"(\" << row.Size() << \") \";\n      for (int j = 0; j < row.Size(); j++)\n\tost << row[j] << \" \";\n      ost << endl;\n    }\n  return ost;\n}\n\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/general/template.hpp",
    "content": "#ifndef FILE_TEMPLATE\n#define FILE_TEMPLATE\n\n/**************************************************************************/\n/* File:   template.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n#include <core/utils.hpp>\n\nnamespace netgen \n{\n  using namespace ngcore;\n/*\n   templates, global types, defines and variables\n*/\n\n  DLL_HEADER extern const std::string netgen_version;\n\n///\tThe following value may be adapted to the hardware !\n#ifndef CLOCKS_PER_SEC\n#define CLOCKS_PER_SEC 1000000\n#endif\n\n\n// #include <iostream>\n/** output stream for testing.\n  testout is opened by main */\n\n/** use instead of cout */\nDLL_HEADER extern ostream * mycout;\n\n/** error output stream */\nDLL_HEADER extern ostream * myerr;\n\n/** Error messages display.\n  Error messages are displayed by this function */\nDLL_HEADER extern void MyError (const char * ch);\n\n\n/** Rings the bell.\n  Produces nr beeps. */\nDLL_HEADER extern void MyBeep (int nr = 1);\n\n\n/**\n  INDEX is a typedef for (at least) 4-byte integer\n */\ntypedef int INDEX;\n\n/**\n  BOOL is a typedef for boolean variables\n  */\n// typedef int BOOL;\n\ntypedef int ELIND;\ntypedef int PIND;\n\n\nclass twoint \n{ \npublic: ///\n  int i1, i2; ///\n  twoint() {};\n  ///\n  twoint(int ii1, int ii2) {i1 = ii1; i2 = ii2;}\n  friend int operator== (const twoint& t1, const twoint& t2);\n  ///\n  void Swap() {int x = i1; i1 = i2; i2 = x;}\n  void Sort() {if (i1 > i2) {Swap();}}\n};\n\ninline int operator== (const twoint& t1, const twoint& t2) \n{\n  return t1.i1 == t2.i1 && t1.i2 == t2.i2;\n}\n\nclass threeint \n{ \npublic: /// \n  int i1, i2, i3; ///\n  threeint() {}; \n  ///\n  threeint(int ii1, int ii2, int ii3) {i1 = ii1; i2 = ii2; i3 = ii3;}\n};\n\n///\nclass twodouble\n{\npublic:\n  ///\n  double d1, d2;\n  ///\n  twodouble() {d1 = 0; d2 = 0;};\n  ///\n  twodouble(double id1, double id2) {d1 = id1; d2 = id2;}\n  ///\n  void Swap() {double x = d1; d1 = d2; d2 = x;}\n};\n\nclass fourint { public: int i1, i2, i3, i4; fourint() {}; };\n\n\n///\nclass INDEX_2;\nostream & operator<<(ostream  & s, const INDEX_2 & i2);\n\n\nclass INDEX_2\n{\n  ///\n  INDEX i[2];\n\npublic:\n  ///\n  // protected:\n  INDEX_2 () { }\n  INDEX_2 (const INDEX_2&) = default;\npublic:\n  INDEX_2 (INDEX_2&&) = default;\n\n  INDEX_2 & operator= (const INDEX_2&) = default;\n  INDEX_2 & operator= (INDEX_2&&) = default;\n  ///\n  constexpr INDEX_2 (INDEX ai1, INDEX ai2)\n    : i{ai1, ai2} { } \n  // { i[0] = ai1; i[1] = ai2; }\n\n  ///\n  // constexpr INDEX_2 (const INDEX_2 & in2)\n  // : i{in2.i[0], in2.i[1]} { } \n  \n  // { i[0] = in2.i[0]; i[1] = in2.i[1]; }\n\n  ///\n  int operator== (const INDEX_2 & in2) const\n    { return i[0] == in2.i[0] && i[1] == in2.i[1]; }\n\n  ///\n\n\n  constexpr INDEX_2 Sort ()\n  {\n    if (i[0] > i[1]) \n      {\n\tINDEX hi = i[0];\n\ti[0] = i[1];\n\ti[1] = hi;\n      }\n    return *this;\n  }\n\n  static INDEX_2 Sort (int i1, int i2)\n  {\n    if (i1 > i2)\n      return INDEX_2 (i2,i1);\n    else\n      return INDEX_2 (i1,i2);\n  }\n\n  operator std::array<INDEX,2>() { return { i[0], i[1] }; }\n  ///\n  INDEX & I1 () { return i[0]; }\n  ///\n  INDEX & I2 () { return i[1]; }\n  ///\n  INDEX & I (int j) { return i[j-1]; }\n  ///\n  const INDEX & I1 () const { return i[0]; }\n  ///\n  const INDEX & I2 () const { return i[1]; }\n  ///\n  const INDEX & I (int j) const { return i[j-1]; }\n  ///\n  int & operator[] (int j) { return i[j]; }\n  ///\n  constexpr const int & operator[] (int j) const { return i[j]; }\n  ///\n  friend ostream & operator<<(ostream  & s, const INDEX_2 & i2);\n};\n\n  /*\ninline INDEX_2 Sort (const INDEX_2 & i2)\n{\n  INDEX_2 tmp = i2;\n  tmp.Sort();\n  return tmp;\n}\n  */\ninline INDEX_2 Sort (INDEX_2 i2)\n{\n  i2.Sort();\n  return i2;\n}\n\ninline bool operator< (const INDEX_2 ia, const INDEX_2 ib)\n{\n  if (ia[0] < ib[0]) return true;\n  if (ia[0] > ib[0]) return false;\n  if (ia[1] < ib[1]) return true;\n  return false;\n}\n  \n\n///\nclass INDEX_3\n{\n  ///\n  INDEX i[3];\n\npublic:\n  ///\n  INDEX_3 () { }\n  ///\n  constexpr INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3)\n    : i{ai1, ai2, ai3} { }\n\n  /// \n  constexpr INDEX_3 (const INDEX_3 & in2)\n    : i{in2.i[0], in2.i[1], in2.i[2]} { } \n\n  static INDEX_3 Sort (INDEX_3 i3)\n  {\n    return i3.Sort();\n  }\n\n  static INDEX_3 Sort (int i1, int i2, int i3)\n  {\n    if (i1 > i2) Swap (i1, i2);\n    if (i2 > i3) Swap (i2, i3);\n    if (i1 > i2) Swap (i1, i2);\n    return INDEX_3 (i1, i2, i3);\n  }\n\n  INDEX_3 Sort ()\n  {\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    if (i[1] > i[2]) Swap (i[1], i[2]);\n    if (i[0] > i[1]) Swap (i[0], i[1]);\n    return *this;\n  }\n\n  int operator== (const INDEX_3 & in2) const\n    { return i[0] == in2.i[0] && i[1] == in2.i[1] && i[2] == in2.i[2];}\n\n  ///\n  INDEX & I1 () { return i[0]; }\n  ///\n  INDEX & I2 () { return i[1]; }\n  ///\n  INDEX & I3 () { return i[2]; }\n  ///\n  INDEX & I (int j) { return i[j-1]; }\n  ///\n  const INDEX & I1 () const { return i[0]; }\n  ///\n  const INDEX & I2 () const { return i[1]; }\n  ///\n  const INDEX & I3 () const { return i[2]; }\n  ///\n  const INDEX & I (int j) const { return i[j-1]; }\n  ///\n  int & operator[] (int j) { return i[j]; }\n  ///\n  const int & operator[] (int j) const { return i[j]; }\n\n  ///\n  friend ostream & operator<<(ostream  & s, const INDEX_3 & i3);\n};\n\n\n\n///\nclass INDEX_4\n{\n  ///\n  INDEX i[4];\n\npublic:\n  ///\n  INDEX_4 () { }\n  ///\n  INDEX_4 (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4)\n    { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; }\n\n  ///\n  INDEX_4 (const INDEX_4 & in2)\n    { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; }\n\n  ///\n  void Sort ();\n\n  ///\n  int operator== (const INDEX_4 & in2) const\n    { return \n\ti[0] == in2.i[0] && i[1] == in2.i[1] && \n\ti[2] == in2.i[2] && i[3] == in2.i[3]; }\n\n  ///\n  INDEX & I1 () { return i[0]; }\n  ///\n  INDEX & I2 () { return i[1]; }\n  ///\n  INDEX & I3 () { return i[2]; }\n  ///\n  INDEX & I4 () { return i[3]; }\n  ///\n  INDEX & I (int j) { return i[j-1]; }\n  ///\n  const INDEX & I1 () const { return i[0]; }\n  ///\n  const INDEX & I2 () const { return i[1]; }\n  ///\n  const INDEX & I3 () const { return i[2]; }\n  ///\n  const INDEX & I4 () const { return i[3]; }\n  ///\n  const INDEX & I (int j) const { return i[j-1]; }\n  ///\n  int & operator[] (int j) { return i[j]; }\n  ///\n  const int & operator[] (int j) const { return i[j]; }\n\n  ///\n  friend ostream & operator<<(ostream  & s, const INDEX_4 & i4);\n};\n\n\n\n\n\n\n\n\n/// The sort preserves quads !!!\nclass INDEX_4Q\n{\n  ///\n  INDEX i[4];\n\npublic:\n  ///\n  INDEX_4Q () { }\n  ///\n  INDEX_4Q (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4)\n    { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; }\n\n  ///\n  INDEX_4Q (const INDEX_4Q & in2)\n    { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; }\n\n  ///\n  void Sort ();\n\n  ///\n  int operator== (const INDEX_4Q & in2) const\n    { return \n\ti[0] == in2.i[0] && i[1] == in2.i[1] && \n\ti[2] == in2.i[2] && i[3] == in2.i[3]; }\n\n  ///\n  INDEX & I1 () { return i[0]; }\n  ///\n  INDEX & I2 () { return i[1]; }\n  ///\n  INDEX & I3 () { return i[2]; }\n  ///\n  INDEX & I4 () { return i[3]; }\n  ///\n  INDEX & I (int j) { return i[j-1]; }\n  ///\n  const INDEX & I1 () const { return i[0]; }\n  ///\n  const INDEX & I2 () const { return i[1]; }\n  ///\n  const INDEX & I3 () const { return i[2]; }\n  ///\n  const INDEX & I4 () const { return i[3]; }\n  ///\n  const INDEX & I (int j) const { return i[j-1]; }\n  ///\n  friend ostream & operator<<(ostream  & s, const INDEX_4Q & i4);\n};\n\n\ninline bool operator< (const INDEX_4 & a, const INDEX_4 & b)\n{\n  for (int j = 0; j < 4; j++)\n    {\n      if (a[j] < b[j]) return true;\n      if (a[j] > b[j]) return false;\n    }\n  return false;\n}\n\n\n\n\n\n/*\n\n\n\n\n///\ntemplate <class T>\ninline T min2 (T a, T b)\n{\n  ///\n  return (a < b) ? a : b;\n}\n///\ntemplate <class T>\ninline T max2 (T a, T b)\n{\n  ///\n  return (a > b) ? a : b;\n}\n///\ntemplate <class T>\ninline T min3 (T a, T b, T c)\n{\n  ///\n  return (a < b) ? (a < c) ? a : c\n    : (b < c) ? b : c;\n}\n///\ntemplate <class T>\ninline T max3 (T a, T b, T c)\n{\n  ///\n  return (a > b) ? ((a > c) ? a : c)\n    : ((b > c) ? b : c);\n}\n\n///\n\n\n///\ntemplate <class T>\ninline int sgn (T a)\n{\n  return (a > 0) ? 1 : (   ( a < 0) ? -1 : 0 );\n}\n\n///\ntemplate <class T>\ninline T sqr (const T a)\n{\n  return a * a; \n}\n\n///\ntemplate <class T>\ninline T pow3 (const T a)\n{\n  return a * a * a; \n}\n*/\n\n\n\n/*\ntemplate <class T>\nvoid BubbleSort (int size, T * data);\n\ntemplate <class T>\nvoid MergeSort (int size, T * data, T * help);\n*/\n\n\n\n}\n\nnamespace ngcore\n{\n  // template <>\n  // constexpr inline netgen::INDEX_2 InvalidHash<netgen::INDEX_2> () { return netgen::INDEX_2{-1,-1}; }\n\n\n  template <>\n  struct CHT_trait<netgen::INDEX_2>\n  {\n    constexpr static inline netgen::INDEX_2 Invalid() { return { -1, -1 } ; }\n    constexpr static inline size_t HashValue (const netgen::INDEX_2 & hash, size_t mask)\n    { return HashValue2(IVec<2,netgen::INDEX>(hash[0], hash[1]), mask); }\n  };\n\n  \n}\n\nnamespace netgen\n{\n  /*\n  inline size_t HashValue2 (const netgen::INDEX_2 & ind, size_t mask)\n  {\n    return HashValue2(IVec<2,netgen::INDEX>(ind[0], ind[1]), mask);\n  }\n  */\n  \n  inline size_t HashValue2 (const netgen::INDEX_3 & ind, size_t mask)\n  {\n    return HashValue2(IVec<3,netgen::INDEX>(ind[0], ind[1], ind[2]), mask);\n  }\n\n\n}\n#endif\n"
  },
  {
    "path": "libsrc/geom2d/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n    csg2d.cpp\n    genmesh2d.cpp\n    geometry2d.cpp\n    python_geom2d.cpp\n)\n\nif(USE_GUI)\n    target_sources(nggui PRIVATE vsgeom2d.cpp geom2dpkg.cpp)\nendif(USE_GUI)\n\ninstall(FILES\n  geometry2d.hpp spline2d.hpp\n  vsgeom2d.hpp csg2d.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/geom2d COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/geom2d/csg2d.cpp",
    "content": "#include <iostream>\n#include <cstdlib>\n#include <cmath>\n#include <string>\n#include <set>\n\n#include \"csg2d.hpp\"\n\n// Polygon clipping algorithm based on:\n// Foster, Erich & Hormann, Kai & Popa, Romeo. (2019). Clipping Simple Polygons with Degenerate Intersections. Computers & Graphics: X. 2. 100007. 10.1016/j.cagx.2019.100007.\n// extended to handle quadratic spline segments\n\nnamespace netgen\n{\nconstexpr static double EPSILON=0.000000001;\n\nvoid ComputeWeight( Spline & s, Point<2> p )\n{\n  Point<2> a = s.StartPI();\n  Point<2> b = s.TangentPoint();\n  Point<2> c = s.EndPI();\n\n  double A = (p[1]-a[1])*(b[0]-p[0]) - (p[0]-a[0])*(b[1]-p[1]);\n  double B = (p[1]-c[1])*(b[0]-p[0]) - (p[0]-c[0])*(b[1]-p[1]);\n  double det = sqrt(-A*B);\n  double tt = fabs(A+det)<EPSILON ? 1 : (B-det)/(A+det);\n  auto v = b-p;\n  int dim = fabs(v[0]) > fabs(v[1]) ? 0 : 1;\n  double weight = fabs(tt*(p[dim]-a[dim])/v[dim] + 1.0/tt*(p[dim]-c[dim])/v[dim]);\n  s.SetWeight(weight);\n}\n\nvoid ToggleLabel(EntryExitLabel& status)\n{\n  if (status == ENTRY)\n  {\n    status = EXIT;\n    return;\n  }\n  if (status == EXIT)\n  {\n    status = ENTRY;\n    return;\n  }\n}\n\nSpline Split( const Spline & s, double t0, double t1 )\n{\n  if(t0==0.0 && t1==1.0) return s;\n\n  Point<2> a = s.StartPI();\n  if(t0!=0.0)\n    a = s.GetPoint(t0);\n\n  Point<2> c = s.EndPI();\n  if(t1!=1.0)\n    c = s.GetPoint(t1);\n\n  // Find new midpoints by cutting the tangents at the new end points\n  auto tang0 = s.GetTangent(t0);\n  auto tang1 = s.GetTangent(t1);\n\n  netgen::Mat<2,2> m, minv;\n  m(0,0) = tang0[0];\n  m(1,0) = tang0[1];\n  m(0,1) = -tang1[0];\n  m(1,1) = -tang1[1];\n\n  CalcInverse(m, minv);\n\n  Vec<2> lam = minv*(c-a);\n\n  Point<2> b = a+lam[0]*tang0;\n\n  auto res = Spline{a, b, c};\n\n  // compute weight of new spline such that p lies on it\n  Point<2> p = s.GetPoint(0.5*(t0+t1));\n  ComputeWeight(res, p);\n  return res;\n}\n\nVertex * Vertex :: Insert(Point<2> p, double lam)\n{\n  auto vnew = make_unique<Vertex>(p);\n  vnew->lam = lam;\n\n  Vertex * current = this;\n\n  if(lam > -1.0)\n  {\n    do {\n      current = current->next;\n    } while (!current->is_source && current->lam < lam);\n  }\n  else\n    current = current->next;\n\n  auto pre = current->prev;\n  if(lam > -1.0)\n    vnew->info = pre->info;\n\n  pre->next = vnew.get();\n  vnew->prev = pre;\n  vnew->next = current;\n\n  vnew->pnext = std::move(current->prev->pnext);\n\n  current->prev = vnew.get();\n\n  pre->pnext = std::move(vnew);\n\n  return pre->next;\n}\n\nIntersectionType ClassifyNonOverlappingIntersection( double alpha, double beta )\n{\n  // classify alpha\n  bool alpha_is_0 = false;\n  bool alpha_in_0_1 = false;\n\n  if ( (alpha > EPSILON) && (alpha < 1.0-EPSILON) )\n    alpha_in_0_1 = true;\n  else\n    if (fabs(alpha) <= EPSILON)\n      alpha_is_0 = true;\n\n  // classify beta\n  bool beta_is_0 = false;\n  bool beta_in_0_1 = false;\n\n  if ( (beta > EPSILON) && (beta < 1.0-EPSILON) )\n    beta_in_0_1 = true;\n  else\n    if (fabs(beta) <= EPSILON)\n      beta_is_0 = true;\n\n  // distinguish intersection types\n  if (alpha_in_0_1 && beta_in_0_1)\n    return (X_INTERSECTION);\n\n  if (alpha_is_0 && beta_in_0_1)\n    return (T_INTERSECTION_Q);\n\n  if (beta_is_0 && alpha_in_0_1)\n    return (T_INTERSECTION_P);\n\n  if (alpha_is_0 && beta_is_0)\n    return (V_INTERSECTION);\n\n  return NO_INTERSECTION;\n}\n\nIntersectionType ClassifyOverlappingIntersection( double alpha, double beta )\n{\n  // classify alpha\n  bool alpha_is_0 = false;\n  bool alpha_in_0_1 = false;\n  bool alpha_not_in_0_1 = false;\n\n  if ( (alpha > EPSILON) && (alpha < 1.0-EPSILON) )\n    alpha_in_0_1 = true;\n  else\n    if (fabs(alpha) <= EPSILON)\n      alpha_is_0 = true;\n    else\n      alpha_not_in_0_1 = true;\n\n  // classify beta\n  bool beta_is_0 = false;\n  bool beta_in_0_1 = false;\n  bool beta_not_in_0_1 = false;\n\n  if ( (beta > EPSILON) && (beta < 1.0-EPSILON) )\n    beta_in_0_1 = true;\n  else\n    if (fabs(alpha) <= EPSILON)\n      beta_is_0 = true;\n    else\n      beta_not_in_0_1 = true;\n\n  // distinguish intersection types\n  if (alpha_in_0_1 && beta_in_0_1)\n    return (X_OVERLAP);\n\n  if (alpha_not_in_0_1 && beta_in_0_1)\n    return (T_OVERLAP_Q);\n\n  if (beta_not_in_0_1 && alpha_in_0_1)\n    return (T_OVERLAP_P);\n\n  if (alpha_is_0 && beta_is_0)\n    return (V_OVERLAP);\n\n  return NO_INTERSECTION;\n}\n\nIntersectionType intersect(const Point<2> P1, const Point<2> P2, const Point<2> Q1, const Point<2> Q2, double& alpha, double& beta)\n{\n  double AP1 = Area(P1,Q1,Q2);\n  double AP2 = Area(P2,Q1,Q2);\n\n  if (fabs(AP1-AP2) > EPSILON)\n  {\n    // (P1,P2) and (Q1,Q2) are not parallel\n\n    double AQ1 = Area(Q1,P1,P2);\n    double AQ2 = Area(Q2,P1,P2);\n\n    alpha = AP1 / (AP1-AP2);\n    beta  = AQ1 / (AQ1-AQ2);\n\n    return ClassifyNonOverlappingIntersection(alpha, beta);\n  }\n  else\n    if (fabs(AP1) < EPSILON)\n    {\n      // (P1,P2) and (Q1,Q2) are collinear\n\n      auto dP = P2-P1;\n      auto dQ = Q2-Q1;\n      auto PQ = Q1-P1;\n\n      alpha = (PQ*dP) / (dP*dP);\n      beta = -(PQ*dQ) / (dQ*dQ);\n\n      return ClassifyOverlappingIntersection(alpha, beta);\n    }\n  return NO_INTERSECTION;\n}\n\nIntersectionType IntersectSplineSegment( const Spline & s, const Point<2> & r0, const Point<2> & r1, double& alpha, double& beta )\n{\n  Point<2> p0 = s.StartPI();\n  Point<2> p1 = s.TangentPoint();\n  Point<2> p2 = s.EndPI();\n\n  auto vr = r1-r0;\n  double a0 = vr[1]*(p0[0] - r0[0]) - vr[0]*(p0[1] - r0[1]);\n  double a1 = vr[1]*(p1[0] - r0[0]) - vr[0]*(p1[1] - r0[1]);\n  double a2 = vr[1]*(p2[0] - r0[0]) - vr[0]*(p2[1] - r0[1]);\n  a1 *= s.GetWeight();\n\n  double a_ = a0-a1+a2;\n  double b_ = a1-2*a0;\n  double c_ = a0;\n\n  double det =  b_*b_ - 4*a_*c_;\n  if(det<0.0)\n    return NO_INTERSECTION;\n\n  double t;\n\n  if(fabs(a_)>EPSILON)\n  {\n    double sqrt_det =  sqrt(det);\n    double t1 = 1.0/(2*a_) * (-b_ + sqrt_det);\n    double t2 = 1.0/(2*a_) * (-b_ - sqrt_det);\n    t = min(t1, t2);\n    if(t<alpha)\n      t = max(t1,t2);\n  }\n  else // degenerate quadratic equation\n    t = -c_/b_;\n\n  if(t+EPSILON<alpha)\n    return NO_INTERSECTION;\n\n  alpha = t;\n\n  int dim = fabs(vr[0]) > fabs(vr[1]) ? 0 : 1;\n  beta = 1.0/vr[dim] * (s.GetPoint(t)[dim] - r0[dim]);\n\n  return ClassifyNonOverlappingIntersection(alpha, beta);\n}\n\nIntersectionType IntersectSplineSegment1( const Spline & s, const Point<2> & r0, const Point<2> & r1, double& alpha, double& beta, bool first=false)\n{\n  Point<2> p0 = s.StartPI();\n  Point<2> p1 = s.TangentPoint();\n  Point<2> p2 = s.EndPI();\n\n  auto vr = r1-r0;\n  double a0 = vr[1]*(p0[0] - r0[0]) - vr[0]*(p0[1] - r0[1]);\n  double a1 = vr[1]*(p1[0] - r0[0]) - vr[0]*(p1[1] - r0[1]);\n  double a2 = vr[1]*(p2[0] - r0[0]) - vr[0]*(p2[1] - r0[1]);\n  a1 *= s.GetWeight();\n\n  double a_ = a0-a1+a2;\n  double b_ = a1-2*a0;\n  double c_ = a0;\n\n  double det =  b_*b_ - 4*a_*c_;\n  if(det<-EPSILON)\n      return NO_INTERSECTION;\n\n  if(det<EPSILON)\n      det = 0;\n\n  double sqrt_det =  sqrt(det);\n  double vbeta[2];\n\n  if(fabs(a_)>EPSILON)\n  {\n    vbeta[0] = 1.0/(2*a_) * (-b_ + sqrt_det);\n    vbeta[1] = 1.0/(2*a_) * (-b_ - sqrt_det);\n  }\n  else // degenerate quadratic equation\n    vbeta[0] = vbeta[1] = -c_/b_;\n\n  int dim = fabs(vr[0]) > fabs(vr[1]) ? 0 : 1;\n  double valpha[2];\n  valpha[0] = 1.0/vr[dim] * (s.GetPoint(vbeta[0])[dim] - r0[dim]);\n  valpha[1] = 1.0/vr[dim] * (s.GetPoint(vbeta[1])[dim] - r0[dim]);\n\n\n  IntersectionType vtype[2];\n  vtype[0] = ClassifyNonOverlappingIntersection(valpha[0], vbeta[0]);\n  vtype[1] = ClassifyNonOverlappingIntersection(valpha[1], vbeta[1]);\n\n  if(valpha[0]>valpha[1])\n  {\n    swap(valpha[0], valpha[1]);\n    swap(vbeta[0], vbeta[1]);\n    swap(vtype[0], vtype[1]);\n  }\n\n  int choice = 0;\n  if(!first)\n  {\n    if(vtype[0]==NO_INTERSECTION && vtype[1]!=NO_INTERSECTION)\n      choice = 1;\n\n    if(valpha[0] < alpha+EPSILON)\n      choice = 1;\n  }\n\n  if(valpha[choice] < alpha+EPSILON)\n    return NO_INTERSECTION;\n\n  alpha = valpha[choice];\n  beta = vbeta[choice];\n  return vtype[choice];\n}\n\nbool IsOverlapping( Spline p, Spline s, double & alpha, double & beta, IntersectionType & type )\n{\n\n  auto p_mid = Center(p.StartPI(), p.EndPI());\n  auto s_mid = Center(s.StartPI(), s.EndPI());\n\n  double lam0 = -1e3*EPSILON;\n  double lam1 = -1e3*EPSILON;\n  double lam2 = -1e3*EPSILON;\n  double lam3 = -1e3*EPSILON;\n  alpha=-1e8;\n  beta=-1e8;\n  double alpha_mid=-1e8;\n  double beta_mid=-1e8;\n\n  // Check if s.p0 lies on p and vice versa, also check if tangents are in same direction (TODO: TEST)\n  // If so, assume overlapping splines\n  // TODO: Better checks! False positives could happen here!\n  if(Dist(s.StartPI(), p.StartPI())<EPSILON)\n    {\n      lam0 = 0.0;\n      alpha = 0.0;\n    }\n  else if(Dist(s.StartPI(), p.EndPI())<EPSILON)\n    {\n      lam0 = 0.0;\n      alpha = 1.0;\n    }\n  else\n      IntersectSplineSegment1( p, s.StartPI(), p_mid, lam0, alpha, true );\n\n  if(Dist(p.StartPI(), s.StartPI())<EPSILON)\n    {\n      lam1 = 0.0;\n      beta = 0.0;\n    }\n  else if(Dist(p.StartPI(), s.EndPI())<EPSILON)\n    {\n      lam1 = 0.0;\n      beta = 1.0;\n    }\n  else\n      IntersectSplineSegment1( s, p.StartPI(), s_mid, lam1, beta, true );\n\n  // Also check if midpoints lie on other spline\n  IntersectSplineSegment1( p, s.GetPoint(0.4), p_mid, lam2, alpha_mid, true );\n  IntersectSplineSegment1( s, p.GetPoint(0.4), s_mid, lam3, beta_mid, true );\n\n  auto tang0 = s.GetTangent(0.);\n  auto tang1 = p.GetTangent(alpha);\n  double err = tang0*tang1;\n  err*=err;\n  err *= 1.0/(tang0.Length2()*tang1.Length2());\n\n  double constexpr eps = 1e3*EPSILON;\n  if(fabs(lam0)>eps) return false;\n  if(fabs(lam1)>eps) return false;\n  if(fabs(lam2)>eps) return false;\n  if(fabs(lam3)>eps) return false;\n  if(fabs(1.0-err)>eps) return false;\n\n  type = ClassifyOverlappingIntersection( alpha, beta );\n  return true;\n}\n\nbool IsInsideTrig( const array<Point<2>,3> & t, Point<2> r )\n{\n  int w = 0;\n  Point<2> trig[4] = {t[0],t[1],t[2],t[0]};\n  for(auto i : Range(3))\n    w += CalcSide(trig[i], trig[i+1], r);\n  return ( (w % 2) != 0 );\n}\n\nbool IsCloseToTrig( const array<Point<2>,3> & t, Point<2> r, double eps=1e-4 )\n{\n  r += eps * (Center(t[0], t[1], t[2])-r); // move point a bit to center of trig\n  return IsInsideTrig( t, r );\n}\n\nbool IsLeft( const Spline & s, Point<2> p )\n{\n  Point<2> a = s.StartPI();\n  Point<2> b = s.TangentPoint();\n  Point<2> c = s.EndPI();\n\n  // simple check by approximating spline with segment\n  bool is_left = Area(p, a, c) > 0.0;\n\n  // not close to spline -> simple check valid\n  if(!IsCloseToTrig( {a, b, c} , p ))\n      return is_left;\n\n  // p is control point -> simple check valid\n  auto bp = p-b;\n  if(bp.Length2() < EPSILON)\n      return is_left;\n\n  double sab = Area(p, a, b);\n  double sbc = Area(p, b, c);\n  if(fabs(sab)<EPSILON)\n      return is_left;\n  if(fabs(sbc)<EPSILON)\n      return is_left;\n\n  // r close to spline, need exact test\n  // idea: compute weight, such that r lies on spline\n  // weight increases -> same side of spline as control point, simple test gives correct result \n  // weight decreases -> opposite side of spline as control point, adding control point to test polygon gives correct result\n  double old_weight = s.GetWeight();\n  auto s_tmp = s;\n  ComputeWeight( s_tmp, p );\n  double new_weight = s_tmp.GetWeight();\n\n  if(new_weight>old_weight)\n      return is_left;\n\n  double sabc = Area(a, b, c);\n\n  if (sabc > 0)\n  {\n    // chain makes a left turn\n    if (sab > 0 && sbc > 0)\n      return true;\n    else\n      return false;\n  }\n  else\n  {\n    // chain makes a right turn (or is straight)\n    if (sab < 0 && sbc < 0)\n      return false;\n    else\n      return true;\n  }\n}\n\n\n\nIntersectionType IntersectTrig( Point<2> p0, Point<2> p1, const array<Point<2>,3> & trig)\n{\n  Point<2> lt[4] = { trig[0], trig[1], trig[2], trig[0] };\n\n  double alpha, beta;\n  for(auto i : IntRange(3))\n  {\n    auto type = intersect(p0, p1, lt[i], lt[i+1], alpha, beta);\n    if(type != NO_INTERSECTION)\n      return type;\n  }\n\n  return NO_INTERSECTION;\n}\n\nbool IntersectTrigs( const array<Point<2>,3> & trig0, const array<Point<2>,3> & trig1)\n{\n  Point<2> lt0[4] = { trig0[0], trig0[1], trig0[2], trig0[0] };\n\n  for(auto i : IntRange(3))\n  {\n    if(IntersectTrig(lt0[i], lt0[i+1], trig1))\n      return true;\n    if(IsInsideTrig(trig0, trig1[i]))\n      return true;\n    if(IsInsideTrig(trig1, trig0[i]))\n      return true;\n  }\n  return false;\n}\n\nbool BisectIntersect( Spline p, Spline s, double &t0, double &t1, double &s0, double &s1, int depth=-50)\n{\n  if(depth==0)\n  {\n    s0 = s1;\n    t0 = t1;\n    return true;\n  }\n\n  bool side = depth%2==0;\n\n  double & lam0 = side ? t0 : s0;\n  double & lam1 = side ? t1 : s1;\n  Spline & spline = side ? p : s;\n  Spline & spline_other = side ? s : p;\n\n  double lam_mid = 0.5*(lam0+lam1);\n  auto left = Split(spline, lam0, lam_mid);\n  auto right = Split(spline, lam_mid, lam1);\n\n  double & lam0_other = side ? s0 : t0;\n  double & lam1_other = side ? s1 : t1;\n  auto curr = Split(spline_other, lam0_other, lam1_other);\n\n  bool left_hull_intersecting = IntersectTrigs( {left.StartPI(), left.TangentPoint(), left.EndPI()}, {curr.StartPI(), curr.TangentPoint(), curr.EndPI()});\n  bool right_hull_intersecting = IntersectTrigs( {right.StartPI(), right.TangentPoint(), right.EndPI()}, {curr.StartPI(), curr.TangentPoint(), curr.EndPI()});\n\n  // TODO: Additionally check if one spline intersects with convex hull of other?\n  //   // Check if one spline intersects with convex hull of spline\n  //   if(left_hull_intersecting)\n  //   {\n  //     double a,b;\n  //     left_hull_intersecting  = left.Intersect( curr.p0, curr.p1, a, b );\n  //     left_hull_intersecting |= left.Intersect( curr.p1, curr.p2, a, b );\n  //     left_hull_intersecting |= left.Intersect( curr.p2, curr.p0, a, b );\n  //   }\n  //\n  //   if(right_hull_intersecting)\n  //   {\n  //     double a,b;\n  //     right_hull_intersecting  = right.Intersect( curr.p0, curr.p1, a, b );\n  //     right_hull_intersecting |= right.Intersect( curr.p1, curr.p2, a, b );\n  //     right_hull_intersecting |= right.Intersect( curr.p2, curr.p0, a, b );\n  //   }\n\n\n  if(!left_hull_intersecting && !right_hull_intersecting)\n    return false;\n\n  if(left_hull_intersecting && right_hull_intersecting)\n  {\n    // cout << \"intersect both sides \" << endl;\n    double temp_lam;\n    temp_lam = lam1;\n    lam1 = lam_mid;\n\n    double t0_ = t0;\n    double t1_ = t1;\n    double s0_ = s0;\n    double s1_ = s1;\n\n    // cout << \"recursive bisect \" << t0 << ',' << t1 << ',' << s0 << ',' << s1 << endl;\n    bool first_intersecting = BisectIntersect(p, s, t0_, t1_, s0_, s1_, depth+1);\n    if(first_intersecting)\n    {\n      t0 = t0_;\n      t1 = t1_;\n      s0 = s0_;\n      s1 = s1_;\n      return true;\n    }\n    else\n    {\n      // cout << \"search other side \" << endl;\n      // no first intersection -> search other side\n      lam1 = temp_lam;\n      left_hull_intersecting = false;\n    }\n  }\n\n  if(left_hull_intersecting)\n    lam1 = lam_mid;\n  else\n    lam0 = lam_mid;\n\n  return BisectIntersect(p, s, t0, t1, s0, s1, depth+1);\n}\n\nbool NewtonIntersect( Spline p, Spline s, double & alpha, double & beta )\n{\n\n  Point<2> p0, s0;\n  Vec<2> dp, ds, ddp, dds;\n\n  p.GetDerivatives(alpha, p0, dp, ddp);\n  s.GetDerivatives(beta,  s0, ds, dds);\n\n  netgen::Mat<2,2> m, minv;\n\n  m(0,0) = dp[0];\n  m(1,0) = dp[1];\n  m(0,1) = -ds[0];\n  m(1,1) = -ds[1];\n\n  CalcInverse(m, minv);\n\n  Vec<2> res = s0-p0;\n  Vec<2> h = minv*res;\n  alpha +=h[0];\n  beta  +=h[1];\n  return true;\n}\n\n\nIntersectionType Intersect( Spline p, Spline s, double &alpha, double &beta)\n{\n  bool is_convex_hull_intersecting = IntersectTrigs( {p.StartPI(), p.TangentPoint(), p.EndPI()}, {s.StartPI(), s.TangentPoint(), s.EndPI()});\n  if(!is_convex_hull_intersecting)\n    return NO_INTERSECTION;\n\n  {\n    // Check if splines overlap\n    double alpha_ = alpha;\n    double beta_ = beta;\n    IntersectionType overlap_type;\n    bool have_overlap = IsOverlapping( p, s, alpha_, beta_, overlap_type );\n    if(have_overlap)\n    {\n      alpha = alpha_;\n      beta = beta_;\n      return overlap_type;\n    }\n  }\n\n  // Bisection\n  double t1 = 1.0;\n  double s1 = 1.0;\n\n  bool have_intersection = false;\n  if(alpha>0.0) // alpha > 0 means, we have found one intersection already\n  {\n    // reverse parametrization of first spline to make sure, we find the second intersection first\n    auto p_ = Spline{p.EndPI(), p.TangentPoint(), p.StartPI(), p.GetWeight()};\n    t1 = 1.0-alpha;\n    alpha = 0.0;\n    beta = 0.0;\n\n    have_intersection = BisectIntersect(p_,s,alpha,t1,beta,s1);\n    alpha = 1.0-alpha;\n  }\n  else\n    have_intersection = BisectIntersect(p,s,alpha,t1,beta,s1);\n\n  if(have_intersection)\n  {\n    for([[maybe_unused]] auto i : IntRange(10))\n      NewtonIntersect(p, s, alpha, beta);\n    return ClassifyNonOverlappingIntersection( alpha, beta );\n  }\n\n  return NO_INTERSECTION;\n}\n\n\nIntersectionType intersect(const Edge& edgeP, const Edge& edgeQ, double& alpha, double& beta)\n{\n  const Point<2>& P1 = *edgeP.v0;\n  const Point<2>& P2 = *edgeP.v1;\n  const Point<2>& Q1 = *edgeQ.v0;\n  const Point<2>& Q2 = *edgeQ.v1;\n\n  if(edgeP.v0->spline)\n  {\n    if(edgeQ.v0->spline)\n      return Intersect(*edgeP.v0->spline, *edgeQ.v0->spline, alpha, beta);\n    else\n      return IntersectSplineSegment(*edgeP.v0->spline, Q1, Q2, alpha, beta);\n  }\n  else\n  {\n    if(edgeQ.v0->spline)\n      return IntersectSplineSegment1(*edgeQ.v0->spline, P1, P2, alpha, beta);\n    else\n      return intersect(P1, P2, Q1, Q2, alpha, beta);\n  }\n}\n\nvoid AddIntersectionPoint(Edge edgeP, Edge edgeQ, IntersectionType i, double alpha, double beta)\n{\n  Point<2> I;\n  Vertex* I_P;\n  Vertex* I_Q;\n\n  Vertex* P1 = edgeP.v0;\n  Vertex* Q1 = edgeQ.v0;\n\n  switch(i)\n  {\n    case X_INTERSECTION:\n      if(edgeP.v0->spline)\n        I = edgeP.v0->spline->GetPoint(alpha);\n      else\n        I = *edgeP.v0 + alpha*(*edgeP.v1 - *edgeP.v0);\n      I_P = edgeP.v0->Insert(I, alpha);\n      I_Q = edgeQ.v0->Insert(I, beta);\n      I_P->Link(I_Q);\n      break;\n\n    case X_OVERLAP:\n      I_Q = edgeQ.v0->Insert(*P1, beta);\n      P1->Link( I_Q);\n\n      I_P = edgeP.v0->Insert(*Q1, alpha);\n      I_P->Link( Q1);\n      break;\n\n    case T_INTERSECTION_Q:\n    case T_OVERLAP_Q:\n      I_Q = edgeQ.v0->Insert(*P1, beta);\n      P1->Link( I_Q);\n      break;\n\n    case T_INTERSECTION_P:\n    case T_OVERLAP_P:\n      I_P = edgeP.v0->Insert(*Q1, alpha);\n      I_P->Link( Q1);\n      break;\n\n    case V_INTERSECTION:\n    case V_OVERLAP:\n      P1->Link(Q1);\n      break;\n    default:\n      break;\n  }\n}\n\nvoid RemoveDuplicates(Loop & poly)\n{\n  if(poly.first==nullptr)\n    return;\n\n  Vertex * last = poly.first->prev;\n  for(auto v : poly.Vertices(ALL))\n  {\n    if(Dist2(*v, *last)<EPSILON*EPSILON)\n      poly.Remove(last);\n    last = v;\n  }\n}\n\nvoid RemoveDuplicates(Solid2d & sr)\n{\n  static Timer tall(\"RemoveDuplicates\"); RegionTimer rtall(tall);\n  for(auto & poly : sr.polys)\n    RemoveDuplicates(poly);\n}\n\n\nvoid SplitSplines( Loop & l)\n{\n  // Split splines at new vertices\n  for (Vertex* v : l.Vertices(SOURCE))\n  {\n    if(!v->spline)\n      continue;\n    Spline ori{*v->spline};\n    Vertex * curr = v;\n    do\n    {\n      auto next = curr->next;\n      if(!curr->is_source || !next->is_source)\n      {\n        double t0 = curr->is_source ? 0.0 : curr->lam;\n        double t1 = next->is_source ? 1.0 : next->lam;\n        curr->spline = Split(ori, t0, t1);\n        curr->lam = -1;\n        curr->is_source = true;\n      }\n      curr = next;\n    } while(!curr->is_source);\n  };\n  RemoveDuplicates(l);\n}\n\nvoid ComputeIntersections(Edge edgeP , Loop & l2)\n{\n  for (Edge edgeQ : l2.Edges(SOURCE))\n  {\n    double alpha = -EPSILON;\n    double beta = -EPSILON;\n    IntersectionType i = intersect(edgeP, edgeQ, alpha, beta);\n    AddIntersectionPoint(edgeP, edgeQ, i, alpha, beta);\n    if(i==X_INTERSECTION && (edgeP.v0->spline || edgeQ.v0->spline))\n    {\n      double alpha1 = alpha+1e2*EPSILON;\n      double beta1 = 0.0; //beta+1e2*EPSILON;\n\n      // search for possible second intersection\n      i = intersect(edgeP, edgeQ, alpha1, beta1);\n      if(i!=NO_INTERSECTION && alpha+EPSILON<alpha1)\n      {\n        // Add midpoint of two intersection points to avoid false overlap detection of splines\n        // TODO: Check if this is really necessary\n        auto alpha_mid = 0.5*(alpha+alpha1);\n        auto beta_mid = 0.5*(beta+beta1);\n        Point<2> MP;\n        if(edgeP.v0->spline)\n        {\n          MP = edgeP.v0->spline->GetPoint(alpha_mid);\n          edgeP.v0->Insert(MP, alpha_mid);\n        }\n        else\n          MP = edgeQ.v0->spline->GetPoint(beta_mid);\n\n        if(edgeQ.v0->spline)\n          edgeQ.v0->Insert(MP, beta_mid);\n\n        AddIntersectionPoint(edgeP, edgeQ, i, alpha1, beta1);\n      }\n    }\n  }\n}\n\nvoid ComputeIntersections(Loop & l1, Loop & l2)\n{\n  static Timer t_intersect(\"find intersections\");\n  static Timer t_split(\"split splines\");\n\n  t_intersect.Start();\n  for (Edge edgeP : l1.Edges(SOURCE))\n    ComputeIntersections(edgeP, l2);\n  t_intersect.Stop();\n\n  RegionTimer rt_split(t_split);\n\n  SplitSplines(l1);\n  SplitSplines(l2);\n}\n\nvoid ComputeIntersections(Solid2d & s1, Solid2d & s2)\n{\n  static Timer tall(\"ComputeIntersections\"); RegionTimer rtall(tall);\n\n  for (Loop& l1 : s1.polys)\n    for (Edge edgeP : l1.Edges(SOURCE))\n      for (Loop& l2 : s2.polys)\n        ComputeIntersections(edgeP, l2);\n\n  for (Loop& l1 : s1.polys)\n    SplitSplines(l1);\n\n  for (Loop& l2 : s2.polys)\n    SplitSplines(l2);\n}\n\nenum RelativePositionType\n{\n  LEFT,\n  RIGHT,\n  IS_P_m,\n  IS_P_p\n};\n\ninline RelativePositionType oracle_decide( double s1, double s2, double s3 )\n{\n  if (s3 > 0)\n  {\n    // chain makes a left turn\n    if (s1 > 0 && s2 > 0)\n      return(LEFT);\n    else\n      return(RIGHT);\n  }\n  else\n  {\n    // chain makes a right turn (or is straight)\n    if (s1 < 0 && s2 < 0)\n      return(RIGHT);\n    else\n      return(LEFT);\n  }\n}\n\n// no splines involved here\n// decides if Point q is left or right of chain (p1,p2,p3)\nRelativePositionType oracle_simple(Point<2> q, Point<2> p1, Point<2> p2, Point<2> p3)\n{\n  double s1 = Area(  q, p1, p2);\n  double s2 = Area(  q, p2, p3);\n  double s3 = Area( p1, p2, p3);\n\n  // check relative position of q with respect to chain (p1,p2,p3)\n  return oracle_decide(s1, s2, s3);\n}\n\n// (p1,p2) or (p2,p3) is a spline segment, compare with tangent (p1t,p2) instead of Segment (p1,p2)\n// BUT take care if tangent is collinear with (q,p2) (then use the segment (p1,p2) again)\nRelativePositionType oracle_spline_p(Point<2> q, Point<2> p1, Point<2> p1t, Point<2> p2, Point<2> p3, Point<2> p3t)\n{\n  double s1 = Area(  q, p1t, p2);\n  double s2 = Area(  q, p2, p3t);\n\n  if(fabs(s1) < EPSILON)\n    {\n      p1t = p1;\n      s1 = Area( q, p1t, p2 );\n    }\n\n  if(fabs(s2) < EPSILON)\n    {\n      p3t = p3;\n      s2 = Area( q, p2, p3t );\n    }\n\n  double s3 = Area( p1t, p2, p3t);\n\n  return oracle_decide(s1, s2, s3);\n}\n\n// (q,p2) is a spline segment, compare with tangent (qt,p2) instead of Segment (q,p2)\n// BUT take care if tangent at p2 is collinear with either (p1,p2) or (p2,p3) (then use the segment (q,p2) again)\nRelativePositionType oracle_spline_q(Point<2> q, Point<2> qt, Point<2> p1, Point<2> p2, Point<2> p3)\n{\n  double s1 = Area( qt, p1, p2);\n  double s2 = Area( qt, p2, p3);\n  double s3 = Area( p1, p2, p3);\n\n  if(fabs(s1) < EPSILON)\n      s1 = Area( q, p1, p2 );\n\n  if(fabs(s2) < EPSILON)\n      s2 = Area( q, p2, p3 );\n\n  return oracle_decide(s1, s2, s3);\n}\n\n// splines at (Q,P2) and either (P1,P2) or (P2,P3)\n// first use tangents to decide local orientation\n// if tangents of two splines match, use IsLeft(spline, other end point)\n// if tangent of spline and segment match, use simple methond (just end points)\nRelativePositionType oracle_spline(bool prev, Vertex *Q, Vertex *P1, Vertex *P2, Vertex *P3)\n{\n  Point<2> p1t =  *P1;\n  Point<2> p3t =  *P3;\n\n  auto sq = prev ? Q->spline : Q->prev->spline;\n  auto qt = sq->TangentPoint();\n  if(P1->spline) p1t = P1->spline->TangentPoint();\n  if(P2->spline) p3t = P2->spline->TangentPoint();\n\n  // Check using tangent directions first\n  double s1 = Area( qt, p1t, *P2 );\n  double s2 = Area( qt, *P2 , p3t);\n  double s3 = Area( p1t, *P2, p3t);\n\n  // tangents are facing in same direction\n  if(fabs(s1) < EPSILON)\n    {\n      if(P1->spline)\n          s1 = IsLeft(*P1->spline, *Q) ? 1 : -1;\n      else\n          s1 = Area( *Q, *P1, *P2 );\n    }\n\n  // tangents are facing in same direction\n  if(fabs(s2) < EPSILON)\n    {\n      if(P2->spline)\n          s2 = IsLeft(*P2->spline, *Q) ? 1 : -1;\n      else\n          s2 = Area( *Q, *P2, *P3 );\n    }\n\n  return oracle_decide(s1, s2, s3);\n}\n\n\nRelativePositionType oracle(bool prev, Vertex* P2)\n{\n  auto Q = prev ? P2->neighbour->prev : P2->neighbour->next;\n  auto sq = prev ? Q->spline : Q->prev->spline;\n  Vertex* P1 = P2->prev;\n  Vertex* P3 = P2->next;\n\n  // is Q linked to P1 ?\n  if ( P1->is_intersection && (P1->neighbour == Q) )\n    return(IS_P_m);\n\n  // is Q linked to P2 ?\n  if ( P3->is_intersection && (P3->neighbour == Q) )\n    return(IS_P_p);\n\n  // no splines -> simple variant\n  if(!P1->spline && !P2->spline && !Q->spline)\n      return oracle_simple(*Q, *P1, *P2, *P3);\n\n  Point<2> qt=*Q, p1t=*P1, p3t=*P3;\n\n  // splines -> also consider tangent points\n  if( sq) qt  =  Q->spline->TangentPoint();\n  if(P1->spline) p1t = P1->spline->TangentPoint();\n  if(P2->spline) p3t = P2->spline->TangentPoint();\n\n  // only spline at Q\n  if(!P1->spline && !P2->spline && Q->spline)\n      return oracle_spline_q(*Q, qt, *P1, *P2, *P3);\n\n  // only spline at P\n  if((P1->spline || !P2->spline) && !Q->spline)\n      return oracle_spline_p(*Q, *P1, p1t, *P2, *P3, p3t);\n\n  // spline at Q and P1 or P2\n  return oracle_spline(prev, Q, P1, P2, P3);\n}\n\n\nvoid LabelIntersections(Solid2d & sp, Solid2d & sq, Solid2d & sr, bool UNION)\n{\n  auto & PP = sp.polys;\n  auto & QQ = sq.polys;\n  auto & RR = sr.polys;\n\n  // 1) initial classification\n  for (Loop& P : PP)\n    for (Vertex* I : P.Vertices(INTERSECTION))\n    {\n\n      // determine local configuration at this intersection vertex\n      // check positions of Q- and Q+ relative to (P-, I, P+)\n      RelativePositionType Q_m_type = oracle(true,  I);\n      RelativePositionType Q_p_type = oracle(false, I);\n\n      // check non-overlapping cases\n      if ((Q_m_type == LEFT  && Q_p_type == RIGHT) ||\n          (Q_m_type == RIGHT && Q_p_type == LEFT ))\n      {\n        I->label = CROSSING;\n      }\n\n      if ((Q_m_type == LEFT  && Q_p_type == LEFT ) ||\n          (Q_m_type == RIGHT && Q_p_type == RIGHT))\n      {\n        I->label = BOUNCING;\n      }\n\n      // check overlapping cases\n      if ( ( (Q_p_type == IS_P_p) && (Q_m_type == RIGHT) ) ||\n          ( (Q_m_type == IS_P_p) && (Q_p_type == RIGHT) ) )\n        I->label = LEFT_ON;\n\n      if ( ( (Q_p_type == IS_P_p) && (Q_m_type == LEFT) ) ||\n          ( (Q_m_type == IS_P_p) && (Q_p_type == LEFT) ) )\n        I->label = RIGHT_ON;\n\n      if ( ( (Q_p_type == IS_P_p) && (Q_m_type == IS_P_m) ) ||\n          ( (Q_m_type == IS_P_p) && (Q_p_type == IS_P_m) ) )\n        I->label = ON_ON;\n\n      if ( ( (Q_m_type == IS_P_m) && (Q_p_type == RIGHT) ) ||\n          ( (Q_p_type == IS_P_m) && (Q_m_type == RIGHT) ) )\n        I->label = ON_LEFT;\n\n      if ( ( (Q_m_type == IS_P_m) && (Q_p_type == LEFT) ) ||\n          ( (Q_p_type == IS_P_m) && (Q_m_type == LEFT) ) )\n        I->label = ON_RIGHT;\n    }\n\n  // 2) classify intersection chains\n  for (Loop& P : PP)\n    for (Vertex* I : P.Vertices(INTERSECTION))\n    {\n\n      // start of an intersection chain ?\n      if (I->label == LEFT_ON ||\n          I->label == RIGHT_ON)\n      {\n\n        // remember status of the first chain vertex and vertex itself\n        RelativePositionType x;\n        if (I->label == LEFT_ON)\n          x = LEFT;\n        else\n          x = RIGHT;\n        Vertex* X = I;\n\n        // proceed to end of intersection chain and mark all visited vertices as NONE\n        do {\n          I->label = NONE;\n          I = I->next;\n        } while (I->label == ON_ON);\n\n        RelativePositionType y;\n        if (I->label == ON_LEFT)\n          y = LEFT;\n        else\n          y = RIGHT;\n\n        // determine type of intersection chain\n        IntersectionLabel chainType;\n        if (x != y)\n          chainType = DELAYED_CROSSING;\n        else\n          chainType = DELAYED_BOUNCING;\n\n        // mark both ends of an intersection chain with chainType (i.e., as DELAYED_*)\n        X->label = chainType;\n        I->label = chainType;\n      }\n    }\n\n  // 3) copy labels from P to Q\n  // loop over intersection vertices of P\n  for (Loop& P : PP)\n    for (Vertex* I : P.Vertices(INTERSECTION))\n      I->neighbour->label = I->label;\n\n  // 3.5) check for special cases\n\n  set<Loop*> noIntersection[2];\n  set<Loop*> identical[2];\n\n  for (int i=0; i<2; ++i)\n  {\n    Array<Loop>* P_or_Q = &PP;      // if i=0, then do it for P w.r.t. Q\n    Array<Loop>* Q_or_P = &QQ;\n\n    if (i==1) {                         // if i=1, then do it for Q w.r.t. P\n      P_or_Q = &QQ;\n      Q_or_P = &PP;\n    }\n\n    // loop over all components of P (or Q)\n    for (Loop& P : *P_or_Q)\n      if (P.noCrossingVertex(UNION))\n      {\n        // P_ has no crossing vertex (but may have bounces or delayed bounces, except for UNION),\n        // hence it does not intersect with Q_or_P\n        noIntersection[i].insert(&P);   // remember component, and ignore it later in step 4\n\n        // is P identical to some component of and Q_or_P?\n        if (P.allOnOn())\n        {\n          identical[i].insert(&P);      // -> remember for further processing below\n        }\n        else\n        {\n          // is P inside Q_or_P?\n          bool isInside = false;\n          auto p = P.getNonIntersectionPoint();\n          for (Loop& Q : *Q_or_P)\n            if ( Q.IsInside(p) )\n              isInside = !isInside;\n          if (isInside ^ UNION)\n            RR.Append(P);             // -> add P to the result\n        }\n      }\n  }\n\n  // handle components of P that are identical to some component of Q\n  for (Loop* P : identical[0])\n  {\n    // is P a hole?\n    bool P_isHole = false;\n    for (Loop& P_ : PP)\n      if ( ( P_.first.get() != P->first.get() ) && (P_.IsInside(*P->first)) )\n        P_isHole = !P_isHole;\n\n    for (Loop* Q : identical[1])\n      for (Vertex* V : Q->Vertices(ALL))\n        if (V == P->first->neighbour) {  // found Q that matches P\n          // is Q a hole?\n          bool Q_isHole = false;\n          for (Loop& Q_ : QQ)\n            if ( ( Q_.first.get() != Q->first.get() ) && (Q_.IsInside(*Q->first)) )\n              Q_isHole = !Q_isHole;\n\n          // if P and Q are both holes or both are not holes\n          if (P_isHole == Q_isHole)\n            RR.Append(*P);           // -> add P to the result\n          goto next_P;\n        }\nnext_P: ;\n  }\n\n  // 4) set entry/exit flags\n  set<Vertex*> split[2];                // split vertex candidates for P and Q\n  set<Vertex*> crossing[2];             // CROSSING vertex candidates for P and Q\n\n  for (int i=0; i<2; ++i)\n  {\n    Array<Loop>* P_or_Q = &PP;      // if i=0, then do it for P w.r.t. Q\n    Array<Loop>* Q_or_P = &QQ;\n\n    if (i==1) {                         // if i=1, then do it for Q w.r.t. P\n      P_or_Q = &QQ;\n      Q_or_P = &PP;\n    }\n\n    // loop over all components of P (or Q)\n    for (Loop& P : *P_or_Q)\n    {\n\n      // ignore P if it does not intersect with Q_or_P (detected in step 3.5 above)\n      if(noIntersection[i].find(&P) != noIntersection[i].end())\n        continue;\n\n      // start at a non-intersection vertex of P\n      Vertex* V = P.getNonIntersectionVertex();\n\n      // check if it is inside or outside Q (or P)\n      // and set ENTRY/EXIT status accordingly\n      EntryExitLabel status = ENTRY;\n      for (Loop& Q : *Q_or_P)\n        if (Q.IsInside(*V))\n          ToggleLabel(status);\n\n      // starting at V, loop over those vertices of P, that are either\n      // a crossing intersection or marked as ends of an intersection chain\n      bool first_chain_vertex = true;     // needed for dealing with crossing chains\n\n      for (Vertex* I : P.Vertices(INTERSECTION, V))\n      {\n        // in the case of normal crossings, we...\n        if (I->label == CROSSING)\n        {\n          // mark vertex with current ENTRY/EXIT status\n          I->enex = status;\n          // toggle status from ENTRY to EXIT or vice versa\n          ToggleLabel(status);\n        }\n\n        // identify split vertex candidates (INTERIOR bouncing vertices)\n        if ( (I->label == BOUNCING) && ((status == EXIT) ^ UNION) )\n          split[i].insert(I);\n\n        //\n        // in the case of a delayed crossing chain, we\n        // mark both end points of the chain with the current ENTRY/EXIT status,\n        // toggling the status only at the end last chain vertex,\n        // and, in case of a delayed EXIT  crossing, the first vertex\n        //  or, in case of a delayed ENTRY crossing, the last  vertex,\n        // of the chain as CROSSING\n        //\n        if (I->label == DELAYED_CROSSING)\n        {\n          // mark vertex with current ENTRY/EXIT status\n          I->enex = status;\n\n          if (first_chain_vertex) {       // are we at the first vertex of a delayed crossing chain?\n            if ((status == EXIT) ^ UNION)\n              I->label = CROSSING;        // mark first vertex as CROSSING\n            first_chain_vertex = false;\n          }\n          else {                          // here we are at the last vertex of a delayed crossing chain\n            if ((status == ENTRY) ^ UNION)\n              I->label = CROSSING;        // mark last vertex as CROSSING\n            first_chain_vertex = true;\n\n            // toggle status from ENTRY to EXIT or vice versa (only for last chain vertex)\n            ToggleLabel(status);\n          }\n        }\n\n        //\n        // in the case of a delayed bouncing chain, we\n        // mark both end points of the chain with the current ENTRY/EXIT status\n        // toggling the status at both end points of the chain,\n        // and, in case of a delayed INTERIOR bouncing, both end points\n        // of the chain as CROSSING candidates\n        //\n        if (I->label == DELAYED_BOUNCING)\n        {\n          // mark vertex with current ENTRY/EXIT status\n          I->enex = status;\n\n          if (first_chain_vertex) {       // are we at the first vertex of a delayed crossing chain?\n            if ((status == EXIT) ^ UNION)\n              crossing[i].insert(I);      // mark first EXIT vertex as CROSSING candidate\n            first_chain_vertex = false;\n          }\n          else {                          // here we are at the last vertex of a delayed crossing chain\n            if ((status == ENTRY) ^ UNION)\n              crossing[i].insert(I);      // mark last ENTRY vertex as CROSSING candidate\n            first_chain_vertex = true;\n\n          }\n          // toggle status from ENTRY to EXIT or vice versa (for first AND last chain vertex)\n          ToggleLabel(status);\n        }\n      }\n    }\n  }\n\n  // 5) handle split vertex pairs\n  // loop over P's split candidates\n  for (Vertex* I_P : split[0])\n  {\n    Vertex* I_Q = I_P->neighbour;\n\n    // check if the neighbour on Q is also a split candidate\n    if (split[1].find(I_Q) != split[1].end())\n    {\n      // compute areas to compare local orientation\n      Point<2> p_prev = *I_P->prev;\n      if(I_P->prev->spline)\n        p_prev = I_P->prev->spline->TangentPoint();\n\n      Point<2> p_next = *I_P->next;\n      if(I_P->spline)\n        p_next = I_P->spline->TangentPoint();\n\n      Point<2> q_prev = *I_Q->prev;\n      if(I_Q->prev->spline)\n        q_prev = I_Q->prev->spline->TangentPoint();\n\n      Point<2> q_next = *I_Q->next;\n      if(I_Q->spline)\n        q_next = I_Q->spline->TangentPoint();\n\n\n      double sP = Area( p_prev, *I_P, p_next );\n      double sQ = Area( q_prev, *I_Q, q_next );\n\n      // add duplicate vertices to P and Q\n      auto V_P = I_P->Insert(*I_P, I_P->lam);\n      V_P->spline = I_P->spline;\n      V_P->pinfo = I_P->pinfo;\n      auto V_Q = I_Q->Insert(*I_Q, I_Q->lam);\n      V_Q->spline = I_Q->spline;\n      V_Q->pinfo = I_Q->pinfo;\n\n      // link vertices correctly\n      if (sP*sQ > 0) {                  // same local orientation\n        I_P->Link( V_Q);\n        I_Q->Link( V_P);\n      }\n      else {                            // different local orientation\n        V_P->Link( V_Q);\n      }\n\n      // mark all four vertices correctly\n      if (!UNION)\n      {\n        I_P->enex = EXIT;\n        V_P->enex = ENTRY;\n        I_Q->enex = EXIT;\n        V_Q->enex = ENTRY;\n      }\n      else\n      {\n        I_P->enex = ENTRY;\n        V_P->enex = EXIT;\n        I_Q->enex = ENTRY;\n        V_Q->enex = EXIT;\n      }\n\n      I_P->label = CROSSING;\n      V_P->label = CROSSING;\n      I_Q->label = CROSSING;\n      V_Q->label = CROSSING;\n    }\n  }\n\n  // 6) handle CROSSING vertex candidates\n  // loop over P's CROSSING candidates\n  for (Vertex* I_P : crossing[0])\n  {\n    Vertex* I_Q = I_P->neighbour;\n\n    // check if the neighbour on Q is also a CROSSING candidate\n    if (crossing[1].find(I_Q) != crossing[1].end())\n    {\n      // mark CROSSING candidate pair as such\n      I_P->label = CROSSING;\n      I_Q->label = CROSSING;\n    }\n  }\n}\n\nvoid CreateResult(Solid2d & sp, Solid2d & sr, bool UNION)\n{\n  auto & PP = sp.polys;\n  auto & RR = sr.polys;\n  //\n  // for all crossing vertices\n  //\n  // NOTE: all crossing vertices that are visited while constructing a\n  //       component of the result polygon are marked as \"not intersection\",\n  //       so that they cannot serve as start vertex of another component\n  //\n\n  for (Loop& P : PP)\n  {\n    for (Vertex* I : P.Vertices(CROSSING_INTERSECTION))\n    {\n      Loop R;                         // result polygon component\n\n      Vertex* V = I;                      // start traversal at I\n      V->is_intersection = false;            // mark visited vertices\n\n      do {\n        EntryExitLabel status = V->enex;\n        ToggleLabel(status);\n        while ( !(V->enex == status))    // ... we arrive at a vertex with opposite entry/exit flag, or\n        {\n          auto & vnew = R.AppendVertex(*V);\n          if ((status == EXIT) ^ UNION)\n          {\n            vnew.info = V->info;\n            vnew.pinfo = V->pinfo;\n            if(V->spline)\n              vnew.spline = *V->spline;\n            else\n              vnew.spline = nullopt;\n            V = V->next;                  // move forward  from an ENTRY vertex to the next EXIT  vertex\n            V->is_intersection = false;        // mark visited vertices\n          }\n          else\n          {\n            V = V->prev;                  // move backward from an EXIT  vertex to the next ENTRY vertex\n            if(V->spline)\n            {\n              auto & s = *V->spline;\n              vnew.spline = Spline{s.EndPI(), s.TangentPoint(), s.StartPI(), s.GetWeight()};\n            }\n            else\n              vnew.spline = nullopt;\n            vnew.info = V->info;\n            vnew.pinfo = V->pinfo;\n            V->is_intersection = false;        // mark visited vertices\n          }\n          if(V == I)\n            break;\n        }\n\n        if (V != I)\n        {\n          V = V->neighbour;               // switch from P to Q or vice versa\n          V->is_intersection = false;        // mark visited vertices\n        }\n      } while (V != I);                   // the result polygon component is complete,\n      // if we are back to the initial vertex I\n      RR.Append(R);\n    }\n  }\n}\n\n// Check if vertex v is not necessary (i.e. is on the line v->prev, v->next and has same info as v->prev and no pinfo\nbool canRemoveVertex( Vertex * v )\n{\n  return false;\n  if(v->spline)\n    return false;\n  if(v->pinfo.name != POINT_NAME_DEFAULT)\n    return false;\n  if(v->pinfo.maxh != MAXH_DEFAULT)\n    return false;\n\n  if(v->info.bc != v->prev->info.bc || v->info.maxh != v->prev->info.maxh )\n    return false;\n\n  if(fabs(Area(*v->prev,*v,*v->next)) >= EPSILON)\n    return false;\n\n  return true;\n}\n\nvoid CleanUpResult(Solid2d & sr)\n{\n  auto & RR = sr.polys;\n  for (Loop& R : RR)\n  {\n    while ( (R.first.get() != NULL) && canRemoveVertex(R.first.get())) \n      R.Remove(R.first.get());\n\n    if (R.first.get() != NULL)\n      for (Vertex* V : R.Vertices(ALL))\n        if (canRemoveVertex(V))\n          R.Remove(V);\n  }\n  for (int i = RR.Size()-1; i>=0; i--)\n    if(RR[i].Size()==0)\n      RR.RemoveElement(i);\n}\n\nLoop RectanglePoly(double x0, double x1, double y0, double y1, string bc)\n{\n  Loop r;\n  r.Append( {x0, y0} );\n  r.Append( {x1, y0} );\n  r.Append( {x1, y1} );\n  r.Append( {x0, y1} );\n  r.SetBC(bc);\n  return r;\n}\n\nSolid2d Rectangle(Point<2> p0, Point<2> p1, string name, string bc)\n{\n  using P = Point<2>;\n  return { {p0, P{p1[0],p0[1]}, p1, P{p0[0],p1[1]}}, name, bc };\n}\n\nSolid2d Circle(Point<2> center, double r, string name, string bc)\n{\n  double x = center[0];\n  double y = center[1];\n  using P = Point<2>;\n\n  Point<2> p[] =\n  {\n    {x+r, y+0},\n    {x+0, y+r},\n    {x-r, y+0},\n    {x+0, y-r},\n  };\n\n  EdgeInfo cp[] =\n  {\n    P{x+r, y+r},\n    P{x-r, y+r},\n    P{x-r, y-r},\n    P{x+r, y-r}\n  };\n\n  return Solid2d( { p[0], cp[0], p[1], cp[1], p[2], cp[2], p[3], cp[3] }, name, bc );\n}\n\nvoid AddIntersectionPoints ( Solid2d & s1, Solid2d & s2 )\n{\n  ComputeIntersections(s1, s2);\n  RemoveDuplicates(s1);\n  RemoveDuplicates(s2);\n}\n\nvoid AddIntersectionPoints ( Loop & l1, Loop & l2 )\n{\n  ComputeIntersections(l1, l2);\n  RemoveDuplicates(l1);\n  RemoveDuplicates(l2);\n}\n\n\nSolid2d ClipSolids ( const Solid2d & s1, const Solid2d & s2, char op)\n{\n  return ClipSolids(Solid2d{s1}, Solid2d{s2}, op);\n}\n\nSolid2d ClipSolids ( const Solid2d & s1, Solid2d && s2, char op)\n{\n  return ClipSolids(Solid2d{s1}, std::move(s2), op);\n}\n\nSolid2d ClipSolids ( Solid2d && s1, const Solid2d & s2, char op)\n{\n  return ClipSolids(std::move(s1), Solid2d{s2}, op);\n}\n\nSolid2d ClipSolids ( Solid2d && s1, Solid2d && s2, char op)\n{\n  static Timer tall(\"ClipSolids\"); RegionTimer rtall(tall);\n  static Timer t0(\"copy\");\n  static Timer t02(\"tree\");\n  static Timer t03(\"search intersections\");\n  static Timer t01(\"prepare\");\n  static Timer t1(\"intersection\");\n  static Timer t2(\"label\");\n  static Timer t3(\"cut\");\n  static Timer t4(\"cleanup\");\n  static Timer t6(\"trivial union\");\n\n  bool intersect = (op=='*' || op=='-');\n\n  Solid2d res;\n  res.name = s1.name;\n\n  t0.Start();\n  // Try to quickly handle parts of both solids that cannot intersect with the other one\n  int n1 = s1.polys.Size();\n  int n2 = s2.polys.Size();\n  Array<Loop> res_polys(n1+n2);\n  res_polys.SetSize(0);\n\n  t02.Start();\n  auto s1_box = s1.GetBoundingBox();\n  netgen::BoxTree <2, int> tree1(s1_box);\n\n  for(auto li : IntRange(n1))\n  {\n    auto box = s1.polys[li].GetBoundingBox();\n    tree1.Insert(box, li);\n  }\n\n  auto s2_box = s2.GetBoundingBox();\n  netgen::BoxTree <2, int> tree2(s2.GetBoundingBox());\n\n  for(auto li : IntRange(n2))\n  {\n    auto box = s2.polys[li].GetBoundingBox();\n    tree2.Insert(box, li);\n  }\n  t02.Stop();\n\n  t03.Start();\n\n  for(auto li : IntRange(n1))\n  {\n    bool have_intersections = false;\n    auto & poly = s1.polys[li];\n    auto box = poly.GetBoundingBox();\n    tree2.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (int li2)\n        {\n          return have_intersections = true;\n        });\n    if(!have_intersections)\n    {\n      if(op=='+' || op=='-')\n        res_polys.Append(std::move(poly));\n      else\n        poly.Clear();\n    }\n  }\n  t03.Stop();\n\n  for(auto li: IntRange(n1))\n    while(s1.polys.Size()>li && s1.polys[li].Size()==0)\n      s1.polys.DeleteElement(li);\n\n  t03.Start();\n  for(auto li : IntRange(n2))\n  {\n    bool have_intersections = false;\n    auto & poly = s2.polys[li];\n    auto box = poly.GetBoundingBox();\n    tree1.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (int li2)\n        {\n          return have_intersections = true;\n        });\n    if(!have_intersections)\n    {\n      if(op=='+')\n        res_polys.Append(std::move(poly));\n      else\n        poly.Clear();\n    }\n  }\n  t03.Stop();\n\n  for(auto li: IntRange(n2))\n    while(s2.polys.Size()>li && s2.polys[li].Size()==0)\n      s2.polys.DeleteElement(li);\n\n  t0.Stop();\n\n  if(s1.polys.Size()==0 || s2.polys.Size()==0)\n  {\n    res.polys = std::move(res_polys);\n    return res;\n  }\n\n  t01.Start();\n\n  if(op=='-')\n  {\n    // take complement of s2 by adding loop around everything\n    auto box = s1_box;\n    box.Add(s2_box.PMin());\n    box.Add(s2_box.PMax());\n    box.Increase(2);\n    auto pmin = box.PMin();\n    auto pmax = box.PMax();\n    s2.Append(RectanglePoly(pmin[0], pmax[0], pmin[1], pmax[1], \"JUST_FOR_CLIPPING\"));\n  }\n\n\n  for(auto & poly : s1.polys)\n    for(auto v : poly.Vertices(ALL))\n    {\n      v->is_source = true;\n      v->neighbour = nullptr;\n      v->lam = -1.0;\n      v->is_intersection = false;\n      v->label = NONE;\n      v->enex = NEITHER;\n    }\n\n  for(auto & poly : s2.polys)\n    for(auto v : poly.Vertices(ALL))\n    {\n      v->is_source = true;\n      v->neighbour = nullptr;\n      v->lam = -1.0;\n      v->is_intersection = false;\n      v->label = NONE;\n      v->enex = NEITHER;\n    }\n\n  t01.Stop();\n\n  t1.Start();\n  ComputeIntersections(s1, s2);\n  t1.Stop();\n\n  t2.Start();\n  LabelIntersections(s1, s2, res, !intersect);\n  t2.Stop();\n\n  t3.Start();\n  CreateResult(s1, res, !intersect);\n  t3.Stop();\n\n  t4.Start();\n  CleanUpResult(res);\n  RemoveDuplicates(res);\n  t4.Stop();\n\n  res.polys.Append(std::move(res_polys));\n\n  return res;\n}\n\nVertex* Loop :: getNonIntersectionVertex()\n  {\n    for (Vertex* v : Vertices(ALL))\n      if (!v->is_intersection)\n        return(v);\n\n    // no non-intersection vertex found -> generate and return temporary vertex\n    for (Vertex* v : Vertices(ALL))\n      // make sure that edge from V to V->next is not collinear with other polygon\n      if ( (v->next->neighbour != v->neighbour->prev) && (v->next->neighbour != v->neighbour->next) )\n      {\n        // add edge midpoint as temporary vertex\n        if(v->spline)\n        {\n          auto p = v->spline->GetPoint(0.5);\n          auto s = *v->spline;\n          v->spline = Split(s, 0, 0.5);\n          auto vnew = v->Insert(p);\n          vnew->info = v->info;\n          vnew->spline = Split(s, 0.5, 1.0);\n          return vnew;\n        }\n        else\n        {\n          auto p = Center(*v, *v->next);\n          auto vnew = v->Insert(p);\n          vnew->info = v->info;\n          return vnew;\n        }\n      }\n    return(NULL);\n  }\n\nbool Loop :: IsInside( Point<2> r ) const\n{\n  int w = 0;\n  for(auto e : Edges(ALL))\n  {\n    int w_simple = CalcSide(*e.v0, *e.v1, r);\n    if(!e.v0->spline)\n      w += w_simple;\n    else\n    {\n      auto s = *e.v0->spline;\n      auto s0 = s.StartPI();\n      auto s1 = s.TangentPoint();\n      auto s2 = s.EndPI();\n      if(!IsCloseToTrig( {s0, s1, s2} , r ))\n        w += w_simple;\n      else\n      {\n        // r close to spline, need exact test\n        // idea: compute weight, such that r lies on spline\n        // weight increases -> same side of spline as control point, simple test gives correct result \n        // weight decreases -> opposite side of spline as control point, adding control point to test polygon gives correct result\n        double old_weight = s.GetWeight();\n        ComputeWeight( s, r );\n        double new_weight = s.GetWeight();\n\n        if(new_weight >= old_weight)\n          w += w_simple;\n        else\n          w += CalcSide(s0, s1, r) + CalcSide(s1, s2, r); \n      }\n    }\n  }\n  return ( (w % 2) != 0 );\n}\n\n\nSolid2d :: Solid2d(const Array<std::variant<Point<2>, EdgeInfo, PointInfo>> & points, string name_, string bc)\n    : name(name_)\n{\n  Loop l;\n  for (auto & v : points)\n    {\n      if(auto point = std::get_if<Point<2>>(&v))\n          l.Append(*point, true);\n      if(auto edge_info = std::get_if<EdgeInfo>(&v))\n          l.first->prev->info.Assign( *edge_info );\n      if(auto point_info = std::get_if<PointInfo>(&v))\n          l.first->prev->pinfo.Assign(*point_info);\n    }\n\n  for(auto v : l.Vertices(ALL))\n    {\n      if(v->info.bc==BC_DEFAULT)\n          v->info.bc = bc;\n\n      if(v->info.control_point)\n          v->spline = Spline(*v, *v->info.control_point, *v->next);\n    }\n\n  polys.Append(l);\n}\n\nSolid2d Solid2d :: operator+(const Solid2d & other) const\n{\n  static Timer t(\"Solid2d::operator+\"); RegionTimer rt(t);\n  return ClipSolids(*this, other, '+');\n}\n\nSolid2d Solid2d :: operator*(const Solid2d & other) const\n{\n  static Timer t(\"Solid2d::operator*\"); RegionTimer rt(t);\n  return ClipSolids(*this, other, '*');\n}\n\nSolid2d Solid2d :: operator-(const Solid2d & other) const\n{\n  static Timer t(\"Solid2d::operator-\"); RegionTimer rt(t);\n  return ClipSolids(*this, other, '-');\n}\n\nSolid2d & Solid2d :: operator+=(const Solid2d & other)\n{\n  static Timer t(\"Solid2d::operator+=\"); RegionTimer rt(t);\n  *this = ClipSolids(std::move(*this), other, '+');\n  return *this;\n}\n\nSolid2d & Solid2d :: operator*=(const Solid2d & other)\n{\n  *this = ClipSolids(std::move(*this), other, '*');\n  return *this;\n}\n\nSolid2d & Solid2d :: operator-=(const Solid2d & other)\n{\n  *this = ClipSolids(std::move(*this), other, '-');\n  return *this;\n}\n\nSolid2d & Solid2d :: Move( Vec<2> v )\n{\n  return Transform( [v](Point<2> p) -> Point<2> { return p+v; } );\n}\n\nSolid2d & Solid2d :: Scale( double s )\n{\n  return Transform( [s](Point<2> p) -> Point<2> { return{p[0]*s, p[1]*s}; } );\n}\n\nSolid2d & Solid2d :: Scale( Vec<2> s )\n{\n  return Transform( [s](Point<2> p) -> Point<2> { return{p[0]*s[0], p[1]*s[1]}; } );\n}\n\nSolid2d & Solid2d :: RotateRad( double ang, Point<2> center )\n{\n  double sina = sin(ang);\n  double cosa = cos(ang);\n  Vec<2> c = { center[0], center[1] };\n  return Transform( [c, sina, cosa](Point<2> p) -> Point<2>\n      {\n          p -= c;\n          double x = p[0];\n          double y = p[1];\n          p[0] = cosa*x-sina*y;\n          p[1] = sina*x+cosa*y;\n          p += c;\n          return p;\n      } );\n}\n\n\nbool Solid2d :: IsInside( Point<2> r ) const\n{\n  int w = 0;\n  for(auto & poly : polys)\n    w += poly.IsInside(r);\n  return ( (w % 2) != 0 );\n}\n\nbool Loop :: IsLeftInside( const Vertex & p0 )\n{\n  auto & p1 = *p0.next;\n  if(p0.spline)\n  {\n    auto s = *p0.spline;\n    auto v = s.GetTangent(0.5);\n    auto n = Vec<2>{-v[1], v[0]};\n    auto q = s.GetPoint(0.5) + 1e-6*n;\n    return IsInside(q);\n  }\n  auto v = p1-p0;\n  auto n = Vec<2>{-v[1], v[0]};\n  auto q = p0 + 0.5*v + 1e-6*n;\n  \n  return IsInside(q);\n}\n\nbool Loop :: IsRightInside( const Vertex & p0 )\n{\n  auto & p1 = *p0.next;\n  if(p0.spline)\n  {\n    auto s = *p0.spline;\n    auto v = s.GetTangent(0.5);\n    auto n = Vec<2>{v[1], -v[0]};\n    auto q = s.GetPoint(0.5) + 1e-6*n;\n    return IsInside(q);\n  }\n\n  auto v = p1-p0;\n  auto n = Vec<2>{v[1], -v[0]};\n  auto q = p0 + 0.5*v + 1e-6*n;\n  return IsInside(q);\n}\n\nbool Solid2d :: IsLeftInside( const Vertex & p0 )\n{\n  auto & p1 = *p0.next;\n  if(p0.spline)\n  {\n    auto s = *p0.spline;\n    auto v = s.GetTangent(0.5);\n    auto n = Vec<2>{-v[1], v[0]};\n    auto q = s.GetPoint(0.5) + 1e-6*n;\n    return IsInside(q);\n  }\n  auto v = p1-p0;\n  auto n = Vec<2>{-v[1], v[0]};\n  auto q = p0 + 0.5*v + 1e-6*n;\n  \n  return IsInside(q);\n}\n\nbool Solid2d :: IsRightInside( const Vertex & p0 )\n{\n  auto & p1 = *p0.next;\n  if(p0.spline)\n  {\n    auto s = *p0.spline;\n    auto v = s.GetTangent(0.5);\n    auto n = Vec<2>{v[1], -v[0]};\n    auto q = s.GetPoint(0.5) + 1e-6*n;\n    return IsInside(q);\n  }\n\n  auto v = p1-p0;\n  auto n = Vec<2>{v[1], -v[0]};\n  auto q = p0 + 0.5*v + 1e-6*n;\n  return IsInside(q);\n}\n\nnetgen::Box<2> Solid2d :: GetBoundingBox() const\n{\n  static Timer tall(\"Solid2d::GetBoundingBox\"); RegionTimer rtall(tall);\n  netgen::Box<2> box(netgen::Box<2>::EMPTY_BOX);\n  for(auto & poly : polys)\n  {\n    auto pbox = poly.GetBoundingBox();\n    box.Add(pbox.PMin());\n    box.Add(pbox.PMax());\n  }\n\n  return box;\n}\n\nshared_ptr<netgen::SplineGeometry2d> CSG2d :: GenerateSplineGeometry()\n{\n  static Timer tall(\"CSG2d - GenerateSplineGeometry()\");\n  static Timer t_points(\"add points\");\n  static Timer t_segments_map(\"build segments map\");\n  static Timer t_is_inside(\"is inside check\");\n  static Timer t_segments(\"add segments\");\n  static Timer t_intersections(\"add intersections\");\n  static Timer t_segtree(\"seg trees\");\n  RegionTimer rt(tall);\n\n  struct Seg\n  {\n    int p0;\n    int p1;\n    int left;\n    int right;\n    int bc;\n    int p2;\n    double weight;\n    double maxh = 1e99;\n  };\n\n  auto geo = std::make_shared<netgen::SplineGeometry2d>();\n  std::map<std::tuple<int,int,int>, Seg> seg_map;\n  Array<string> bcnames;\n  Array<int> points;\n\n  // Cut each solid with each other one to add all possible intersection points and have conforming edges from both domains\n  t_intersections.Start();\n\n  // First build bounding boxes for each solid to skip non-overlapping pairs\n  netgen::Box<2> box(netgen::Box<2>::EMPTY_BOX);\n  for(auto i : Range(solids))\n    {\n      auto sbox = solids[i].GetBoundingBox();\n      box.Add(sbox.PMin());\n      box.Add(sbox.PMax());\n    }\n\n  netgen::BoxTree <2> solid_tree(box);\n  Array<IVec<2>> loop_list;\n\n  for(auto i : Range(solids))\n    for(auto li : Range(solids[i].polys))\n    {\n      solid_tree.Insert(solids[i].polys[li].GetBoundingBox(), loop_list.Size());\n      loop_list.Append(IVec<2>(i, li));\n    }\n\n  for(auto i1 : Range(solids))\n    for(auto li1 : Range(solids[i1].polys))\n    {\n      auto & poly1 = solids[i1].polys[li1];\n      auto box = poly1.GetBoundingBox();\n      solid_tree.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (int ii)\n        {\n          auto i2 = loop_list[ii][0];\n          auto li2 = loop_list[ii][1];\n          if(i1<i2)\n            AddIntersectionPoints(poly1, solids[i2].polys[li2]);\n          return false;\n        });\n    }\n\n\n  t_intersections.Stop();\n\n  // Add geometry points to SplineGeometry\n\n  netgen::BoxTree <2, int> ptree(box);\n\n  auto getPoint = [&](Point<2> p )\n  {\n    int res = -1;\n    ptree.GetFirstIntersecting(p, p, [&] (int pi)\n        {\n        res = pi;\n        return true;\n        });\n    return res;\n  };\n\n  t_points.Start();\n  auto insertPoint = [&](const Vertex& p )\n  {\n    int pi = getPoint(p);\n    if(pi==-1)\n    {\n      // not found -> insert to tree\n      netgen::GeomPoint<2> gp(p);\n      geo->geompoints.Append(gp);\n      pi = geo->geompoints.Size()-1;\n      ptree.Insert(p,p,geo->geompoints.Size()-1);\n    }\n    geo->geompoints[pi].hmax = min2(geo->geompoints[pi].hmax, p.pinfo.maxh);\n    if(p.pinfo.name != POINT_NAME_DEFAULT)\n      geo->geompoints[pi].name = p.pinfo.name;\n  };\n\n  for(auto & s : solids)\n    for(auto & poly : s.polys)\n      for(auto v : poly.Vertices(ALL))\n      {\n        box.Add(*v);\n        insertPoint(*v);\n        if(v->spline)\n          insertPoint(v->spline->TangentPoint());\n      }\n  t_points.Stop();\n\n\n  // Generate segments from polygon edges and find left/right domain of each segment\n  t_segments_map.Start();\n  int dom = 0;\n  int bc = 1;\n  for(auto & s : solids)\n  {\n    dom++;\n    bool is_solid_degenerated = true; // Don't create new domain for degenerated solids\n    for(auto & poly : s.polys)\n    {\n      bool first = true;\n      bool is_poly_left_inside = false;\n      bool is_poly_right_inside = false;\n\n      for(auto v : poly.Vertices(ALL))\n      {\n        auto & p0 = *v;\n        auto & p1 = *v->next;\n\n        auto pi0 = getPoint(p0);\n        auto pi1 = getPoint(p1);\n        int pi2 = -1;\n        double weight = 0.0;\n\n        if(v->spline)\n        {\n          auto p2 = v->spline->TangentPoint();\n          pi2 = getPoint(p2);\n          weight = v->spline->GetWeight();\n        }\n\n        bool flip = false;\n        if(pi1<pi0)\n        {\n          flip = true;\n          Swap(pi1,pi0);\n        }\n\n        if(first)\n        {\n          RegionTimer rt_inside(t_is_inside);\n          is_poly_left_inside = s.IsLeftInside(p0);\n          is_poly_right_inside = s.IsRightInside(p0);\n          first = true;\n        }\n\n        auto li = is_poly_left_inside; // == poly.IsLeftInside(p0);\n        auto ri = is_poly_right_inside; // == poly.IsRightInside(p0);\n\n        auto & ls = seg_map[{pi0,pi1,pi2}];\n        ls.p0 = pi0;\n        ls.p1 = pi1;\n        ls.p2 = pi2;\n        ls.weight = weight;\n\n        if(ls.bc==0 || p0.info.bc != BC_DEFAULT)\n        {\n            ls.bc = bc++;\n            bcnames.Append(p0.info.bc);\n        }\n\n        ls.maxh = min(ls.maxh, p0.info.maxh);\n\n        if(li!=ri)\n        {\n          if(li != flip)\n            ls.left = dom;\n          else\n            ls.right = dom;\n\n          is_solid_degenerated = false;\n        }\n      }\n    }\n    if(!is_solid_degenerated)\n    {\n      geo->SetMaterial(dom, s.name);\n      geo->SetDomainMaxh(dom, s.maxh);\n      if(s.layer != 1)\n          geo->SetDomainLayer(dom, s.layer);\n    }\n    else\n      dom--; // degenerated solid, use same domain index again\n  }\n  t_segments_map.Stop();\n\n  for(auto bc : Range(bcnames))\n    geo->SetBCName(bc+1, bcnames[bc]);\n\n  t_segments.Start();\n  for(auto const &m : seg_map)\n  {\n    auto ls = m.second;\n    netgen::SplineSegExt * seg;\n    if(ls.p2!=-1)\n    {\n      // spline segment\n      auto * seg3 = new netgen::SplineSeg3<2>( geo->GetPoint(ls.p0), geo->GetPoint(ls.p2), geo->GetPoint(ls.p1), ls.weight );\n      seg = new netgen::SplineSegExt(*seg3);\n    }\n    else\n    {\n      // line segment\n      auto * l = new netgen::LineSeg<2>(geo->GetPoint(ls.p0), geo->GetPoint(ls.p1));\n      seg = new netgen::SplineSegExt(*l);\n    }\n\n    seg->leftdom = ls.left;\n    seg->rightdom = ls.right;\n    seg->bc = ls.bc;\n    seg->reffak = 1;\n    seg->copyfrom = -1;\n    seg->hmax = ls.maxh;\n    seg->hpref_left = 0.;\n    seg->hpref_right = 0.;\n    geo->AppendSegment(seg);\n  }\n  t_segments.Stop();\n  return geo;\n}\n\nshared_ptr<netgen::Mesh> CSG2d :: GenerateMesh(MeshingParameters & mp)\n{\n  auto geo = GenerateSplineGeometry();\n  auto mesh = make_shared<netgen::Mesh>();\n  geo->GenerateMesh(mesh, mp);\n  return mesh;\n}\n\n}\n"
  },
  {
    "path": "libsrc/geom2d/csg2d.hpp",
    "content": "#ifndef NETGEN_CSG2D_HPP_INCLUDED\n#define NETGEN_CSG2D_HPP_INCLUDED\n\n#include <variant>\n\n#include \"geometry2d.hpp\"\n\nnamespace netgen\n{\nusing namespace std;\nusing namespace ngcore;\nusing netgen::Point;\nusing netgen::Vec;\nusing Spline = SplineSeg3<2>;\nusing netgen::Box;\n\ninline double Area(const Point<2>& P, const Point<2>& Q, const Point<2>& R)\n{\n  return (Q[0]-P[0]) * (R[1]-P[1]) - (Q[1]-P[1]) * (R[0]-P[0]);\n}\n\n// compute weight of spline such that p lies on it\nvoid ComputeWeight( Spline & s, Point<2> p );\n\nenum IntersectionType\n{                 // types of intersection (detected in the first phase)\n  NO_INTERSECTION = 0,\n  X_INTERSECTION,\n  T_INTERSECTION_Q,\n  T_INTERSECTION_P,\n  V_INTERSECTION,\n  X_OVERLAP,      // Q0 -- P1 -- Q1 -- P0   (different direction)\n  T_OVERLAP_Q,    // same direction or P inside Q\n  T_OVERLAP_P,    // same direction or Q inside P\n  V_OVERLAP       // one common point\n};\n\nenum IntersectionLabel\n{      // for the classification of intersection vertices in the second phase\n  NONE,\n  CROSSING,\n  BOUNCING,\n  LEFT_ON,\n  RIGHT_ON,\n  ON_ON,\n  ON_LEFT,\n  ON_RIGHT,\n  DELAYED_CROSSING,\n  DELAYED_BOUNCING\n};\n\nenum EntryExitLabel\n{         // for marking intersection vertices as \"entry\" or \"exit\"\n  EXIT,\n  ENTRY,\n  NEITHER\n};\n\nenum IteratorType\n{\n  SOURCE,\n  INTERSECTION,\n  CROSSING_INTERSECTION,\n  ALL\n};\n\ninline constexpr const double MAXH_DEFAULT{1e99};\ninline const string POINT_NAME_DEFAULT{\"\"};\ninline const string BC_DEFAULT{\"\"};\ninline const string MAT_DEFAULT{\"\"};\n\nstruct EdgeInfo\n{\n  optional<Point<2>> control_point = nullopt; // for spline segments\n  double maxh = MAXH_DEFAULT;\n  string bc = BC_DEFAULT;\n\n  EdgeInfo() = default;\n  EdgeInfo(Point<2> p) : control_point(p) {}\n  EdgeInfo(double h) : maxh(h) {}\n  EdgeInfo(string s) : bc(s) {}\n  EdgeInfo(optional<Point<2>> p, double h, string s)\n      : control_point(p), maxh(h), bc(s)\n    {}\n\n  void Assign( EdgeInfo other )\n    {\n      if(other.control_point != nullopt)\n          control_point = other.control_point;\n      if(other.bc != BC_DEFAULT)\n          bc = other.bc;\n      if(other.maxh != MAXH_DEFAULT)\n          maxh = min(maxh, other.maxh);\n    }\n};\n\nstruct PointInfo\n{\n  double maxh = MAXH_DEFAULT;\n  string name = POINT_NAME_DEFAULT;\n  PointInfo() = default;\n  PointInfo(const PointInfo& other) = default;\n  PointInfo(double amaxh) : maxh(amaxh) {}\n  PointInfo(string aname) : name(aname) {}\n  PointInfo(double amaxh, string aname) : maxh(amaxh), name(aname) {}\n\n  void Assign(const PointInfo& other)\n  {\n    maxh = min(maxh, other.maxh);\n    if(other.name != POINT_NAME_DEFAULT)\n      name = other.name;\n  }\n};\n\nstruct Vertex : Point<2>\n{\n  Vertex (Point<2> p) : Point<2>(p) {}\n  Vertex (const Vertex & v) : Point<2>(v)\n  {\n    spline = v.spline;\n    info = v.info;\n    pinfo = v.pinfo;\n    is_source = true;\n  }\n\n  Vertex * prev = nullptr;\n  Vertex * next = nullptr;\n  unique_ptr<Vertex> pnext = nullptr;\n  Vertex * neighbour = nullptr; // same vertex in other polygon (at intersections)\n  double lam = -1.0;\n  bool is_intersection = false;\n  bool is_source = false;\n\n  IntersectionLabel label = NONE;    // type of intersection vertex\n  EntryExitLabel enex = NEITHER;        // entry/exit \"flag\"\n\n  // In case the edge this - next is curved, store the spline information here\n  optional<Spline> spline = nullopt;\n  EdgeInfo info;\n  PointInfo pinfo;\n\n  DLL_HEADER Vertex * Insert(Point<2> p, double lam = -1.0);\n\n  void Link( Vertex * v )\n  {\n    neighbour = v;\n    v->neighbour = this;\n    is_intersection = true;\n    v->is_intersection = true;\n  }\n};\n\nstruct VertexIterator\n{\n  struct iterator\n  {\n    iterator(Vertex* root, IteratorType IterType) :\n      root(root), V(NULL), iterType(IterType)\n    {\n      if (root == NULL)\n        return;\n\n      if (nextVertex() == NULL)         // no (source/intersection) vertex found\n        root = V = NULL;                // -> mark iterator as \"end\"\n    }\n\n    const iterator& operator++()\n    {\n      nextVertex();\n      return *this;\n    }\n\n    Vertex* operator*()\n    {\n      return V;\n    }\n\n    bool operator!=(const iterator& other) const\n    {\n      return (root != other.root) || (V != other.V);\n    }\n\n    private:\n    Vertex* root;\n    Vertex* V;\n    IteratorType iterType;\n\n    //\n    // find the next vertex\n    // if iterType is ALL, then it is just the next vertex\n    // if iterType is SOURCE, then it is the next source vertex\n    // if iterType is INTERSECTION, then it is the next intersection vertex\n    // if iterType is CROSSING_INTERSECTION, then it is the next intersection vertex with CROSSING label\n    //\n    Vertex* nextVertex()\n    {\n      bool nextFound = false;\n\n      if (V == NULL)\n      {                  // find first (source/intersection) vertex\n        V = root;\n        switch(iterType)\n        {\n          case ALL:\n            nextFound = true;\n            break;\n          case SOURCE:\n            if (V->is_source)\n              nextFound = true;\n            break;\n          case INTERSECTION:\n            if (V->is_intersection)\n              nextFound = true;\n            break;\n          case CROSSING_INTERSECTION:\n            if (V->is_intersection && (V->label == CROSSING))\n              nextFound = true;\n            break;\n        }\n      }\n\n      while (!nextFound)\n      {              // find next (source/intersection) vertex\n        switch(iterType)\n        {\n          case ALL:\n            V = V->next;\n            break;\n          case SOURCE:\n            do {\n              V = V->next;\n            } while (!V->is_source && V != root);\n            break;\n          case INTERSECTION:\n            do {\n              V = V->next;\n            } while (!V->is_intersection && V != root);\n            break;\n          case CROSSING_INTERSECTION:\n            do {\n              V = V->next;\n            } while ( ( !V->is_intersection || (V->label != CROSSING) ) && V != root);\n            break;\n        }\n\n        if (V == root)\n        {                // back at the root vertex?\n          root = V = NULL;              // -> mark iterator as \"end\"\n          return(V);\n        }\n\n        switch(iterType)\n        {\n          case ALL:\n            nextFound = true;\n            break;\n          case SOURCE:\n            if (V->is_source)\n              nextFound = true;\n            break;\n          case INTERSECTION:\n            if (V->is_intersection)\n              nextFound = true;\n            break;\n          case CROSSING_INTERSECTION:\n            if (V->is_intersection && (V->label == CROSSING))\n              nextFound = true;\n            break;\n        }\n      }\n      return(V);\n    }\n  };\n\n  public:\n  VertexIterator() : root(NULL) {};\n\n  iterator begin() { return iterator(root, iterType); }\n  iterator end()   { return iterator(NULL, iterType); }\n\n  Vertex* root;\n  IteratorType iterType;\n};\n\n\nstruct Edge\n{\n  Vertex * v0 = nullptr;\n  Vertex * v1 = nullptr;\n\n  Edge (Vertex* v, Vertex* w) : v0(v), v1(w) { };\n};\n\nstruct EdgeIterator\n{\n  struct iterator\n  {\n    iterator(Vertex* root, IteratorType IterType) :\n      root(root), one(NULL), two(NULL), iterType(IterType)\n    {\n      if (root == NULL)\n        return;\n\n      if (nextEdge() == NULL)           // no source edge found\n        root = one = two = NULL;        // -> mark iterator as \"end\"\n    }\n\n    const iterator& operator++() { nextEdge(); return *this; }\n\n    Edge operator*()\n    {\n      return Edge(one,two);\n    }\n\n    bool operator!=(const iterator& other) const\n    {\n      return (root != other.root) || (one != other.one) || (two != other.two);\n    }\n\n    private:\n    Vertex* root;\n    Vertex* one;\n    Vertex* two;\n    IteratorType iterType;\n\n    //\n    // find the next vertex, starting at curr\n    // if iterType is ALL, then it is just the next vertex\n    // if iterType is SOURCE, then it is the next source vertex\n    //\n    Vertex* nextVertex(Vertex* curr)\n    {\n      if (curr == NULL)\n        return(NULL);\n\n      switch(iterType)\n      {\n        case ALL:\n          curr = curr->next;\n          break;\n\n        case SOURCE:\n          do {\n            curr = curr->next;\n          } while (!curr->is_source);\n          break;\n        default:\n          ;\n      }\n\n      return(curr);\n    }\n\n    //\n    // find the next edge\n    //\n    Vertex* nextEdge()\n    {\n      if (root == NULL)                 // empty polygon?\n        return (NULL);\n\n      if (one == NULL)\n      {                // find one (source) vertex\n        one = root;                     // note: root is always a (source) vertex\n        two = nextVertex(one);\n        if (two == one)                 // just one (source) vertex\n          return(NULL);                 // -> no (source) edges\n        return(one);\n      }\n\n      if (two == root)\n      {                // back at the root vertex?\n        root = one = two = NULL;        // -> mark iterator as \"end\"\n        return(NULL);\n      }\n\n      one = two;\n      two = nextVertex(one);\n\n      return (one);\n    }\n  };\n\n  public:\n  EdgeIterator() : root(NULL) {};\n\n  iterator begin() { return iterator(root, iterType); }\n  iterator end()   { return iterator(NULL, iterType); }\n\n  Vertex* root;\n  IteratorType iterType;\n};\n\n\ninline int CalcSide( const Point<2> & p0, const Point<2> & p1, const Point<2> & r )\n{\n  if ( (p0[1] < r[1]) != (p1[1] < r[1]) )\n  {\n    if (p0[0] >= r[0])\n    {\n      if (p1[0] > r[0])\n        return 2 * (p1[1] > p0[1]) - 1;\n      else\n        if ( (Area(p0,p1,r) > 0) == (p1[1] > p0[1]) )\n          return 2 * (p1[1] > p0[1]) - 1;\n    }\n    else\n    {\n      if (p1[0] > r[0])\n        if ( (Area(p0,p1,r) > 0) == (p1[1] > p0[1]) )\n          return 2 * (p1[1] > p0[1]) - 1;\n    }\n  }\n  return 0;\n}\n\nstruct Loop\n{\n  unique_ptr<Vertex> first = nullptr;\n  unique_ptr<Box<2>> bbox = nullptr;\n\n  Loop() = default;\n\n  Loop(const Loop & p)\n    : first(nullptr)\n  {\n    for(auto v : p.Vertices(ALL))\n      AppendVertex(*v);\n  }\n\n  Loop(Loop && p) = default;\n\n  Loop & operator=(Loop && p) = default;\n\n  Loop & operator=(const Loop & p)\n  {\n    // static Timer t(\"Loop::operator=\"); RegionTimer rt(t);\n    first = nullptr;\n    if(p.first)\n    {\n      size_t n = p.Size();\n      Array<unique_ptr<Vertex>> new_verts(n);\n      {\n        size_t i = 0;\n        for(const auto v : p.Vertices(ALL))\n          new_verts[i++] = make_unique<Vertex>(*v);\n      }\n\n      for(auto i : IntRange(n-1))\n      {\n        Vertex * v  = new_verts[i].get();\n        Vertex * vn = new_verts[i+1].get();\n        v->next = vn;\n        vn->prev = v;\n      }\n      Vertex * vfirst = new_verts[0].get();\n      Vertex * vlast = new_verts[n-1].get();\n      vfirst->prev = vlast;\n      vlast->next = vfirst;\n\n      for(auto i : IntRange(1,n))\n        new_verts[n-1-i]->pnext = std::move(new_verts[n-i]);\n\n      first = std::move(new_verts[0]);\n    }\n    bbox = nullptr;\n    return *this;\n  }\n\n  void Clear()\n  {\n    first = nullptr;\n  }\n\n  Vertex & AppendVertex(const Vertex & v)\n  {\n    auto & vnew = Append( static_cast<Point<2>>(v), true );\n    vnew.info = v.info;\n    vnew.pinfo = v.pinfo;\n    if(v.spline)\n      vnew.spline = *v.spline;\n    if(bbox)\n      bbox->Add(v);\n    return vnew;\n  }\n\n  Vertex & Append(Point<2> p, bool source = false)\n  {\n    Vertex * vnew;\n    if(first==nullptr)\n    {\n      first = make_unique<Vertex>(p);\n      first->next = first.get();\n      first->prev = first.get();\n      vnew = first.get();\n    }\n    else\n    {\n      vnew = first->prev->Insert(p);\n    }\n\n    vnew->is_source = source;\n    //     cout << \"size after \" << Size() << endl;\n    if(bbox)\n      bbox->Add(p);\n    return *vnew;\n  }\n\n  void Remove (Vertex* v)\n  {\n    v->prev->next = v->next;\n    v->next->prev = v->prev;\n    if(first.get() == v)\n      first = std::move(v->pnext);\n    else\n      v->prev->pnext = std::move(v->pnext);\n    bbox.reset();\n  }\n\n  bool IsInside( Point<2> r ) const;\n  bool IsLeftInside( const Vertex & p0 );\n  bool IsRightInside( const Vertex & p0 );\n\n  EdgeIterator Edges(IteratorType iterType) const\n  {\n    EdgeIterator it;\n    it.iterType = iterType;\n    it.root = first.get();\n    return it;\n  }\n\n  VertexIterator Vertices(IteratorType iterType, Vertex* first_ = nullptr) const\n  {\n    VertexIterator it;\n    it.iterType = iterType;\n    it.root = (first_ == nullptr) ? first.get() : first_;\n    return it;\n  }\n\n  //\n  // check, if all vertices have the ON_ON label\n  //\n  bool allOnOn()\n  {\n    for (Vertex* v : Vertices(ALL))\n      if (v->label != ON_ON)\n        return(false);\n    return(true);\n  }\n\n  //\n  // check, if the polygon does not contain any crossing intersection vertex\n  // or crossing intersection chain or (if we want to compute the union instead\n  // of the intersection) a bouncing vertex or a bouncing intersection chain\n  //\n  bool noCrossingVertex(bool union_case = false)\n  {\n    for (Vertex* v : Vertices(ALL))\n      if (v->is_intersection)\n      {\n        if ( (v->label == CROSSING) || (v->label == DELAYED_CROSSING) )\n          return(false);\n\n        if (union_case && ( (v->label == BOUNCING) || (v->label == DELAYED_BOUNCING) ) )\n          return(false);\n      }\n    return(true);\n  }\n\n  //\n  // return a non-intersection point\n  //\n  Point<2> getNonIntersectionPoint()\n  {\n    for (Vertex* v : Vertices(ALL))\n      if (!v->is_intersection)\n        return *v;\n\n    // no non-intersection vertex found -> find suitable edge midpoint\n    for (Vertex* v : Vertices(ALL))\n      // make sure that edge from V to V->next is not collinear with other polygon\n      if ( (v->next->neighbour != v->neighbour->prev) && (v->next->neighbour != v->neighbour->next) )\n        // return edge midpoint\n        return Center(*v, *v->next);\n    throw Exception(\"no point found\");\n  }\n\n  //\n  // return and insert a non-intersection vertex\n  //\n  Vertex* getNonIntersectionVertex();\n\n  void SetBC(string bc)\n  {\n    for(auto v : Vertices(ALL))\n      v->info.bc = bc;\n  }\n\n  size_t Size() const\n  {\n    if(first==nullptr) return 0;\n\n    size_t cnt = 0;\n\n    for([[maybe_unused]] auto v : Vertices(ALL))\n      cnt++;\n\n    return cnt;\n  }\n\n  const Box<2> & GetBoundingBox()\n  {\n    if(bbox==nullptr)\n    {\n      static Timer tall(\"Loop::GetBoundingBox\"); RegionTimer rt(tall);\n      bbox = make_unique<Box<2>>(Box<2>::EMPTY_BOX);\n      for(auto v : Vertices(ALL))\n      {\n        bbox->Add(*v);\n        if(v->spline)\n          bbox->Add(v->spline->TangentPoint());\n      }\n    }\n    return *bbox;\n  }\n};\n\n\nstruct Solid2d\n{\n  Array<Loop> polys;\n\n  int layer = 1;\n  string name = MAT_DEFAULT;\n  double maxh = MAXH_DEFAULT;\n\n  Solid2d() = default;\n  Solid2d(string name_) : name(name_) {}\n  DLL_HEADER Solid2d(const Array<std::variant<Point<2>, EdgeInfo, PointInfo>> & points, string name_=MAT_DEFAULT, string bc_=BC_DEFAULT);\n  Solid2d(Solid2d && other) = default;\n  Solid2d(const Solid2d & other) = default;\n\n  DLL_HEADER Solid2d operator+(const Solid2d & other) const;\n  DLL_HEADER Solid2d operator*(const Solid2d & other) const;\n  DLL_HEADER Solid2d operator-(const Solid2d & other) const;\n\n  Solid2d& operator=(Solid2d && other) = default;\n  Solid2d& operator=(const Solid2d & other) = default;\n  DLL_HEADER Solid2d& operator+=(const Solid2d & other);\n  DLL_HEADER Solid2d& operator*=(const Solid2d & other);\n  DLL_HEADER Solid2d& operator-=(const Solid2d & other);\n\n  void Append( const Loop & poly )\n  {\n    polys.Append(poly);\n  }\n\n  bool IsInside( Point<2> r ) const;\n  bool IsLeftInside( const Vertex & p0 );\n  bool IsRightInside( const Vertex & p0 );\n\n  template<typename TFunc>\n  Solid2d & Transform( const TFunc & func )\n    {\n      for(auto & poly : polys)\n          for(auto v : poly.Vertices(ALL))\n            {\n              auto p = func(*v);\n              (*v)[0] = p[0];\n              (*v)[1] = p[1];\n              if(v->spline)\n                {\n                  auto &s = *v->spline;\n                  auto pmid = func(s.GetPoint(0.5));\n                  s = Spline(func(s.StartPI()), func(s.TangentPoint()), func(s.EndPI()));\n                  ComputeWeight(s, pmid);\n                }\n            }\n      return *this;\n    }\n\n  Solid2d & Move( Vec<2> v );\n  Solid2d & Scale( double s );\n  Solid2d & Scale( Vec<2> s );\n  Solid2d & RotateRad( double ang, Point<2> center = {0,0} );\n  Solid2d & RotateDeg( double ang, Point<2> center = {0,0} )\n    {\n      return RotateRad( ang/180.*M_PI, center );\n    }\n\n  Solid2d & BC(string bc)\n  {\n    for(auto & p : polys)\n      for(auto v : p.Vertices(ALL))\n        v->info.bc = bc;\n    return *this;\n  }\n\n  Solid2d & Maxh(double maxh)\n  {\n    this->maxh = maxh;\n    for(auto & p : polys)\n      for(auto v : p.Vertices(ALL))\n        v->info.maxh = maxh;\n    return *this;\n  }\n\n  Solid2d & Mat(string mat)\n  {\n    name = mat;\n    return *this;\n  }\n\n  Solid2d & Layer(int layer_)\n  {\n    layer = layer_;\n    return *this;\n  }\n\n  Box<2> GetBoundingBox() const;\n};\n\n\nclass CSG2d\n{\n  public:\n    Array<Solid2d> solids;\n\n    void Add ( Solid2d s )\n    {\n      solids.Append(s);\n    }\n\n    DLL_HEADER shared_ptr<netgen::SplineGeometry2d> GenerateSplineGeometry();\n    DLL_HEADER shared_ptr<netgen::Mesh> GenerateMesh(MeshingParameters & mp);\n};\n\nDLL_HEADER Solid2d Circle( Point<2> center, double r, string name=\"\", string bc=\"\");\nDLL_HEADER Solid2d Rectangle( Point<2> p0, Point<2> p1, string mat=MAT_DEFAULT, string bc=BC_DEFAULT );\n\nDLL_HEADER void AddIntersectionPoints ( Solid2d & s1, Solid2d & s2 );\nDLL_HEADER Solid2d ClipSolids ( const Solid2d & s1, const Solid2d & s2, char op);\nDLL_HEADER Solid2d ClipSolids ( const Solid2d & s1, Solid2d && s2, char op);\nDLL_HEADER Solid2d ClipSolids ( Solid2d && s1, const Solid2d & s2, char op);\nDLL_HEADER Solid2d ClipSolids ( Solid2d && s1, Solid2d && s2, char op);\n\nDLL_HEADER IntersectionType intersect(const Point<2> P1, const Point<2> P2, const Point<2> Q1, const Point<2> Q2, double& alpha, double& beta);\n\n}\n#endif // NETGEN_CSG2D_HPP_INCLUDED\n"
  },
  {
    "path": "libsrc/geom2d/genmesh2d.cpp",
    "content": "#include <meshing.hpp>\n#include <geometry2d.hpp>\n\nnamespace netgen\n{\n  // extern DLL_HEADER MeshingParameters mparam;\n\n  extern void Optimize2d (Mesh & mesh, MeshingParameters & mp, int faceindex=0);\n\n\n\n\n  void CalcPartition (const SplineSegExt & spline, \n\t\t      // double l, \n\t\t      MeshingParameters & mp, Mesh & mesh, \n\t\t      // double h, double h1, double h2, double hcurve, \n\t\t      double elto0, NgArray<double> & points)\n  {\n    double fperel, oldf, f;\n\n    int n = 1;\n    NgArray<Point<2> > xi;\n    NgArray<double> hi;\n\n    // do one extra step\n    int not_fine_enough = 2;\n\n    while(not_fine_enough && n < 10000)\n    {\n      not_fine_enough--;\n      n*=4;\n\n      xi.SetSize(n);\n      hi.SetSize(n);\n\n      for (int i = 0; i < n; i++)\n      {\n        xi[i] = spline.GetPoint ( (i+0.5) / n );\n        hi[i] = mesh.GetH (Point<3> (xi[i](0), xi[i](1), 0));\n      }\n\n      // limit slope\n      double gradh = min(1/elto0,mp.grading);\n      for (int i = 0; i < n-1; i++)\n      {\n        double hnext = hi[i] + gradh * (xi[i+1]-xi[i]).Length();\n        if(hnext > 2*hi[i])\n          not_fine_enough = 2;\n        hi[i+1] = min(hi[i+1], hnext);\n      } \n      for (int i = n-1; i > 1; i--)\n      {\n        double hnext = hi[i] + gradh * (xi[i-1]-xi[i]).Length();\n        if(hnext > 2*hi[i])\n          not_fine_enough = 2;\n        hi[i-1] = min(hi[i-1], hnext);\n      }\n    }\n\n    points.SetSize (0);\n\n    double len = spline.Length();\n    double dt =  len / n;\n\n    double sum = 0;\n    for (int i = 1; i <= n; i++)\n      {\n\t// double t = (i-0.5)*dt;\n\tdouble fun = hi[i-1];\n\tsum += dt / fun;\n      }\n\n    int nel = int (sum+0.5);\n    if (nel == 0) nel = 1;\n    fperel = sum / nel;\n\n    points.Append (0);\n\n    int i = 1;\n    oldf = 0;\n\n    for (int j = 1; j <= n && i < nel; j++)\n      {\n\t// double t = (j-0.5)*dt;\n\tdouble fun = hi[j-1];\n\n\tf = oldf + dt / fun;\n\n\twhile (i * fperel < f && i < nel)\n\t  {\n\t    points.Append ( dt * (j-1) +  (i * fperel - oldf) * fun);\n\t    i++;\n\t  }\n\toldf = f;\n\t// t += dt;\n      }\n    points.Append (len);\n  }\n\n\n\n\n\n\n\n\n\n  // partitionizes spline curve\n  void Partition (const SplineSegExt & spline,\n\t\t  MeshingParameters & mp, double hxxx, double elto0,\n\t\t  Mesh & mesh, Point3dTree & searchtree, int segnr) \n  {\n    int n = 100;\n\n    Point<2> mark, oldmark;\n    NgArray<double> curvepoints;\n    double edgelength, edgelengthold;\n\n    CalcPartition (spline, mp, mesh, elto0, curvepoints);\n\n    double dt = 1.0 / n;\n\n    int j = 1;\n\n    Point<2> pold = spline.GetPoint (0);\n    double lold = 0;\n    oldmark = pold;\n    edgelengthold = 0;\n    NgArray<int> locsearch;\n    \n    for (int i = 1; i <= n; i++)\n      {\n\tPoint<2> p = spline.GetPoint (i*dt);\n\tdouble l = lold + Dist (p, pold);\n\twhile (j < curvepoints.Size() && (l >= curvepoints[j] || i == n))\n\t  {\n\t    double frac = (curvepoints[j]-lold) / (l-lold);\n\t    edgelength = i*dt + (frac-1)*dt;\n\t    mark = spline.GetPoint (edgelength);\n\t  \n\t    {\n\t      PointIndex pi1{PointIndex::INVALID};\n\t      PointIndex pi2{PointIndex::INVALID};\n\n\t  \n\t      Point3d mark3(mark(0), mark(1), 0);\n\t      Point3d oldmark3(oldmark(0), oldmark(1), 0);\n\n\t      double h = mesh.GetH (Point<3> (oldmark(0), oldmark(1), 0));\n\t      Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h);\n\t      searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch);\n\n\t      for (int k = 0; k < locsearch.Size(); k++)\n\t\tif ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer)\n\t\t  pi1 = locsearch[k];\n\t      \n\t      searchtree.GetIntersecting (mark3 - v, mark3 + v, locsearch);\n\t      for (int k = 0; k < locsearch.Size(); k++)\n\t\tif ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer)\n\t\t  pi2 = locsearch[k];\n\n\t      if (!pi1.IsValid())\n\t\t{\n\t\t  pi1 = mesh.AddPoint(oldmark3, spline.layer);\n\t\t  searchtree.Insert (oldmark3, pi1);\n\t\t}\n\t      if (!pi2.IsValid())\n\t\t{\n\t\t  pi2 = mesh.AddPoint(mark3, spline.layer);\n\t\t  searchtree.Insert (mark3, pi2);\n\t\t}\n\n\t      Segment seg;\n\t      seg.edgenr = segnr;\n\t      seg.index = spline.bc;\n\t      seg.si = spline.bc; // segnr;\n\t      seg[0] = pi1;\n\t      seg[1] = pi2;\n\t      seg.domin = spline.leftdom;\n\t      seg.domout = spline.rightdom;\n\t      seg.epgeominfo[0].edgenr = segnr;\n\t      seg.epgeominfo[0].dist = edgelengthold;\n\t      seg.epgeominfo[1].edgenr = segnr;\n\t      seg.epgeominfo[1].dist = edgelength;\n\t      seg.singedge_left = spline.hpref_left;\n\t      seg.singedge_right = spline.hpref_right;\n\t      mesh.AddSegment (seg);\n\t    }\n\t\n\t    oldmark = mark;\n\t    edgelengthold = edgelength;\n\t    j++;\n\t  }\n    \n\tpold = p;\n\tlold = l;\n      }\n  }\n\n\n\n  void SplineGeometry2d :: PartitionBoundary (MeshingParameters & mp, double h, Mesh & mesh2d)\n  {\n    enum { D = 2 };\n    Box<D> bbox;\n    GetBoundingBox (bbox);\n    double dist = Dist (bbox.PMin(), bbox.PMax());\n    Point<3> pmin;\n    Point<3> pmax;\n  \n    pmin(2) = -dist; pmax(2) = dist;\n    for(int j=0;j<D;j++)\n      {\n\tpmin(j) = bbox.PMin()(j);\n\tpmax(j) = bbox.PMax()(j);\n      }\n\n    Point3dTree searchtree (pmin, pmax);\n\n    for (int i = 0; i < splines.Size(); i++)\n      for (int side = 0; side <= 1; side++)\n\t{\n\t  int dom = (side == 0) ? GetSpline(i).leftdom : GetSpline(i).rightdom;\n\t  if (dom != 0) GetSpline(i).layer = GetDomainLayer (dom);\n\t}\n\n\n    // mesh size restrictions ...\n\n    for (auto & point : geompoints)\n      mesh2d.RestrictLocalH (Point<3> (point(0), point(1), 0), point.hmax);\n    \n    for (int i = 0; i < splines.Size(); i++)\n      {\n\tconst SplineSegExt & spline = GetSpline(i);\n\tconst GeomPoint<2> & p1 = spline.StartPI();\n\tconst GeomPoint<2> & p2 = spline.EndPI();\n\n\tdouble h1 = min (p1.hmax, h/p1.refatpoint);\n\tmesh2d.RestrictLocalH (Point<3>(p1(0),p1(1),0), h1);\n\tdouble h2 = min (p2.hmax, h/p2.refatpoint);\n\tmesh2d.RestrictLocalH (Point<3>(p2(0),p2(1),0), h2);\n\n\tdouble len = spline.Length();\n\tmesh2d.RestrictLocalHLine (Point<3>(p1(0),p1(1),0), \n\t\t\t\t   Point<3>(p2(0),p2(1),0), len/mp.segmentsperedge);\n\n\tdouble hcurve = min (spline.hmax, h/spline.reffak);\n\tdouble hl = GetDomainMaxh (spline.leftdom);\n\tif (hl > 0) hcurve = min2 (hcurve, hl);\n\tdouble hr = GetDomainMaxh (spline.rightdom);\n\tif (hr > 0) hcurve = min2 (hcurve, hr);\n\n        // skip curvature restrictions for straight lines\n        if(spline.MaxCurvature()==0)\n        {\n          mesh2d.RestrictLocalHLine (Point<3>(p1(0),p1(1),0), \n                                     Point<3>(p2(0),p2(1),0), hcurve);\n        }\n        else\n        {\n          int np = 1000;\n          for (double t = 0.5/np; t < 1; t += 1.0/np)\n            {\n              Point<2> x = spline.GetPoint(t);\n              double hc = 1.0/mp.curvaturesafety / (1e-99+spline.CalcCurvature (t));\n              mesh2d.RestrictLocalH (Point<3> (x(0), x(1), 0), min2(hc, hcurve));\n            }\n        }\n      }\n    \n    for (auto mspnt : mp.meshsize_points)\n      mesh2d.RestrictLocalH (mspnt.pnt, mspnt.h);\n\n    // add point elements\n    for (auto & point : geompoints)\n      if (point.name.length())\n        {\n          Point<3> newp(point(0), point(1), 0);\n          PointIndex npi = mesh2d.AddPoint (newp, 1, FIXEDPOINT);\n          mesh2d.AddLockedPoint(npi);\n          Element0d el(npi, npi);\n          el.name = point.name;\n          mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, point.name);\n          mesh2d.pointelements.Append (el);\n          searchtree.Insert (newp, npi);          \n        }\n\n    // first add all vertices (for compatible orientation on periodic bnds)\n    {\n      double diam2 = Dist2(pmin, pmax);\n      for (int i = 0; i < splines.Size(); i++)\n        for (int j : { 1, 2 })\n          {\n            Point<2> hnewp = (j == 1) ? splines[i]->StartPI() : splines[i]->EndPI();\n            Point<3> newp(hnewp(0), hnewp(1), 0);\n            int layer = GetSpline(i).layer;\n            PointIndex npi(PointIndex::INVALID);\n            for (PointIndex pi = IndexBASE<PointIndex>(); \n                 pi < mesh2d.GetNP()+IndexBASE<PointIndex>(); pi++)\n              if (Dist2 (mesh2d.Point(pi), newp) < 1e-12 * diam2 && mesh2d.Point(pi).GetLayer() == layer)\n                npi = pi;\n            \n\t    if (!npi.IsValid())\n\t      {\n\t\tnpi = mesh2d.AddPoint (newp, layer);\n\t\tsearchtree.Insert (newp, npi);\n                mesh2d.AddLockedPoint(npi);\n                Element0d el(npi, npi-IndexBASE<PointIndex>()+1);\n                el.name = \"\";\n                mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, \"\");\n                mesh2d.pointelements.Append (el);\n\t      }\n          }\n    }\n    \n    for (int i = 0; i < splines.Size(); i++)\n      if (GetSpline(i).copyfrom == -1)\n\t{\n\t  // astrid - set boundary meshsize to  domain meshsize h\n\t  // if no domain mesh size is given, the max h value from the bounding box is used\n\t  double hl = GetDomainMaxh ( GetSpline(i).leftdom );\n\t  double hr = GetDomainMaxh ( GetSpline(i).rightdom );\n\n\t  double useh = h;\n\t  if (hl > 0) useh = min2 (h, hl);\n\t  if (hr > 0) useh = min2 (h, hr);\n\t  Partition(GetSpline(i), mp, useh, elto0, mesh2d, searchtree, i+1);\t    \n\t}\n      else\n\t{\n\t  CopyEdgeMesh (GetSpline(i).copyfrom, i+1, mesh2d, searchtree);\n\t}\n  }\n\n\n\n\n\n\n  void SplineGeometry2d :: CopyEdgeMesh (int from, int to, Mesh & mesh, Point3dTree & searchtree)\n  {\n    Array<PointIndex, PointIndex> mappoints (mesh.GetNP());\n    Array<double, PointIndex> param (mesh.GetNP());\n    mappoints = PointIndex::INVALID;\n    param = 0;\n\n    Point3d pmin, pmax;\n    mesh.GetBox (pmin, pmax);\n    double diam2 = Dist2(pmin, pmax);\n\n    PrintMessage(3, string(\"Copy edge, from \") + ToString(from) + \" to \" + ToString(to));\n  \n    for (const auto& seg : mesh.LineSegments())\n      {\n\tif (seg.edgenr == from)\n\t  {\n\t    mappoints[seg[0]] = 1;\n\t    param[seg[0]] = seg.epgeominfo[0].dist;\n\n\t    mappoints[seg[1]] = 1;\n\t    param[seg[1]] = seg.epgeominfo[1].dist;\n\t  }\n      }\n\n    bool mapped = false;\n    for (auto i : Range(mappoints))\n      {\n\tif (mappoints[i].IsValid())\n\t  {\n\t    Point<2> newp = splines.Get(to)->GetPoint (param[i]);\n\t    Point<3> newp3 (newp(0), newp(1), 0);\n\t  \n\t    PointIndex npi = PointIndex::INVALID;\n\t  \n\t    for (auto pi : Range(mesh.Points()))\n\t      if (Dist2 (mesh.Point(pi), newp3) < 1e-12 * diam2)\n\t\tnpi = pi;\n\t  \n\t    if (!npi.IsValid())\n\t      {\n\t\tnpi = mesh.AddPoint (newp3);\n\t\tsearchtree.Insert (newp3, npi);\n\t      }\n\n\t    mappoints[i] = npi;\n\n\t    mesh.GetIdentifications().Add (i, npi, to);\n\t    mapped = true;\n\t  }\n      }\n    if(mapped)\n      mesh.GetIdentifications().SetType(to,Identifications::PERIODIC);\n\n    // copy segments\n    int oldnseg = mesh.GetNSeg();\n    for (int i = 1; i <= oldnseg; i++)\n      {\n\tconst Segment & seg = mesh.LineSegment(i);\n\tif (seg.edgenr == from)\n\t  {\n\t    Segment nseg;\n\t    nseg.edgenr = to;\n\t    nseg.si = GetSpline(to-1).bc;      // splines.Get(to)->bc;\n\t    nseg.index = GetSpline(to-1).bc;   // ???\n\t    nseg[0] = mappoints[seg[0]];\n\t    nseg[1] = mappoints[seg[1]];\n\t    nseg.domin = GetSpline(to-1).leftdom;\n\t    nseg.domout = GetSpline(to-1).rightdom;\n\t  \n\t    nseg.epgeominfo[0].edgenr = to;\n\t    nseg.epgeominfo[0].dist = param[seg[0]];\n\t    nseg.epgeominfo[1].edgenr = to;\n\t    nseg.epgeominfo[1].dist = param[seg[1]];\n\t    mesh.AddSegment (nseg);\n\t  }\n      }\n  }\n\n\n\n\n\n  void MeshFromSpline2D (SplineGeometry2d & geometry,\n\t\t\t shared_ptr<Mesh> & mesh, \n\t\t\t MeshingParameters & mp)\n  {\n    static Timer tall(\"MeshFromSpline2D\"); RegionTimer rtall(tall);\n    static Timer t_h(\"SetH\");\n    static Timer t_tensor(\"tensor domain meshing\");\n    static Timer t_part_boundary(\"PartitionBoundary\");\n    static Timer t_hpref(\"mark hpref points\");\n    PrintMessage (1, \"Generate Mesh from spline geometry\");\n\n    Box<2> bbox = geometry.GetBoundingBox ();\n    bbox.Increase (1e-2*bbox.Diam());\n    t_h.Start();\n    if (bbox.Diam() < mp.maxh) \n      mp.maxh = bbox.Diam();\n\n    // double h = mp.maxh;\n\n    // mesh = make_shared<Mesh>();\n    mesh->SetDimension (2);\n\n    Point3d pmin(bbox.PMin()(0), bbox.PMin()(1), -bbox.Diam());\n    Point3d pmax(bbox.PMax()(0), bbox.PMax()(1), bbox.Diam());\n\n    mesh->SetLocalH (pmin, pmax, mp.grading);\n    mesh->SetGlobalH (mp.maxh);\n\n    \n\n    t_part_boundary.Start();\n    geometry.PartitionBoundary (mp, mp.maxh, *mesh);\n    t_part_boundary.Stop();\n    \n    PrintMessage (3, \"Boundary mesh done, np = \", mesh->GetNP());\n\n\n    t_hpref.Start();\n    // marks mesh points for hp-refinement\n    for (int i = 0; i < geometry.GetNP(); i++)\n      if (geometry.GetPoint(i).hpref)\n\t{\n\t  double mindist = 1e99;\n\t  PointIndex mpi(0);\n\t  Point<2> gp = geometry.GetPoint(i);\n\t  Point<3> gp3(gp(0), gp(1), 0);\n\t  for (PointIndex pi = IndexBASE<PointIndex>(); \n\t       pi < mesh->GetNP()+IndexBASE<PointIndex>(); pi++)\n\t    if (Dist2(gp3, (*mesh)[pi]) < mindist)\n\t      {\n\t\tmpi = pi;\n\t\tmindist = Dist2(gp3, (*mesh)[pi]);\n\t      }\n\t  (*mesh)[mpi].Singularity(geometry.GetPoint(i).hpref);\n\t}\n    t_hpref.Stop();\n\n\n    int maxdomnr = 0;\n    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n      {\n\tif ( (*mesh)[si].domin > maxdomnr) maxdomnr = (*mesh)[si].domin;\n\tif ( (*mesh)[si].domout > maxdomnr) maxdomnr = (*mesh)[si].domout;\n      }\n\n    TableCreator<const Segment*> dom2seg_creator(maxdomnr+1);\n    for ( ; !dom2seg_creator.Done(); dom2seg_creator++)\n      for (const Segment & seg : mesh->LineSegments())\n        {\n          dom2seg_creator.Add (seg.domin, &seg);\n          if (seg.domin != seg.domout)\n            dom2seg_creator.Add (seg.domout, &seg);\n        }\n    auto dom2seg = dom2seg_creator.MoveTable();\n    \n    mesh->ClearFaceDescriptors();\n    for (int i = 1; i <= maxdomnr; i++)\n      mesh->AddFaceDescriptor (FaceDescriptor (i, 0, 0, i));\n\n    // set NgArray<string*> bcnames... \n    // number of bcnames\n    int maxsegmentindex = 0;\n    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n      if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si;\n\n    mesh->SetNBCNames(maxsegmentindex);\n\n    for ( int sindex = 0; sindex < maxsegmentindex; sindex++ )\n      mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) );\n\n    mesh->CalcLocalH(mp.grading);\n    t_h.Stop();\n\n    int bnp = mesh->GetNP(); // boundary points\n    // auto BndPntRange = mesh->Points().Range();\n\n    int hquad = mp.quad;\n\n\n    for (int domnr = 1; domnr <= maxdomnr; domnr++)\n      if (geometry.GetDomainTensorMeshing (domnr))\n        { // tensor product mesh\n          RegionTimer rt(t_tensor);\n          \n          Array<PointIndex, PointIndex> nextpi(bnp);\n          Array<int, PointIndex> si1(bnp), si2(bnp);\n          // PointIndex firstpi;\n          \n          nextpi = -1;\n          si1 = -1;\n          si2 = -1;\n          for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n            {\n              int p1 = -1, p2 = -2;\n\n              if ( (*mesh)[si].domin == domnr)\n                { p1 = (*mesh)[si][0]; p2 = (*mesh)[si][1]; }\n              if ( (*mesh)[si].domout == domnr)\n                { p1 = (*mesh)[si][1]; p2 = (*mesh)[si][0]; }\n              \n              if (p1 == -1) continue;\n\n              nextpi[p1] = p2;       // counter-clockwise\n              \n              int index = (*mesh)[si].si;\n              if (si1[p1] != index && si2[p1] != index)\n                { si2[p1] = si1[p1]; si1[p1] = index; }\n              if (si1[p2] != index && si2[p2] != index)\n                { si2[p2] = si1[p2]; si1[p2] = index; }\n            }\n\n          PointIndex c1(0), c2, c3, c4;  // 4 corner points\n          int nex = 1, ney = 1;\n\n          // for (PointIndex pi = 1; pi <= si2.Size(); pi++)\n          for (PointIndex pi : si2.Range())\n            if (si2[pi] != -1)\n              { c1 = pi; break; }      \n\n          for (c2 = nextpi[c1]; si2[c2] == -1; c2 = nextpi[c2], nex++);\n          for (c3 = nextpi[c2]; si2[c3] == -1; c3 = nextpi[c3], ney++);\n          for (c4 = nextpi[c3]; si2[c4] == -1; c4 = nextpi[c4]);\n\n\n\n          NgArray<PointIndex> pts ( (nex+1) * (ney+1) );   // x ... inner loop\n          pts = -1;\n\n          int i = 0;\n          for (PointIndex pi = c1; pi != c2; pi = nextpi[pi], i++)\n            pts[i] = pi;\n          i = 0;\n          for (PointIndex pi = c2; pi != c3; pi = nextpi[pi], i++)\n            pts[(nex+1)*i+nex] = pi;\n          i = 0;\n          for (PointIndex pi = c3; pi != c4; pi = nextpi[pi], i++)\n            pts[(nex+1)*(ney+1)-i-1] = pi;\n          i = 0;\n          for (PointIndex pi = c4; pi != c1; pi = nextpi[pi], i++)\n            pts[(nex+1)*(ney-i)] = pi;\n\n\n          for (PointIndex pix = nextpi[c1], ix = 0; pix != c2; pix = nextpi[pix], ix++)\n          {\n            Point<3> px = (*mesh)[pix];\n            for (PointIndex piy = nextpi[c2], iy = 0; piy != c3; piy = nextpi[piy], iy++)\n              {\n                double lam = Dist((*mesh)[piy],(*mesh)[c2]) / Dist((*mesh)[c3],(*mesh)[c2]);\n                auto pix1 = pts[(nex+1)*ney+ix+1];\n                auto pnew = px + lam*((*mesh)[pix1]-px);\n                pts[(nex+1)*(iy+1) + ix+1] = mesh -> AddPoint (pnew, 1, FIXEDPOINT);\n              }\n          }\n\n          for (int i = 0; i < ney; i++)\n            for (int j = 0; j < nex; j++)\n              {\n                Element2d el(QUAD);\n                el[0] = pts[i*(nex+1)+j];\n                el[1] = pts[i*(nex+1)+j+1];\n                el[2] = pts[(i+1)*(nex+1)+j+1];\n                el[3] = pts[(i+1)*(nex+1)+j];\n                el.SetIndex (domnr);\n\n                mesh -> AddSurfaceElement (el);\n              }\n          char* material;\n          geometry.GetMaterial(domnr, material);\n          if(material)\n            mesh->SetMaterial(domnr, material);\n        }\n\n\n\n\n    static Timer t_domain(\"Mesh domain\");\n    static Timer t_points(\"Mesh domain - find points\");\n    for (int domnr = 1; domnr <= maxdomnr; domnr++)\n      {\n        RegionTimer rt(t_domain);\n        if (geometry.GetDomainTensorMeshing (domnr)) continue;\n        \n        double h = mp.maxh;\n\tif ( geometry.GetDomainMaxh ( domnr ) > 0 )\n\t  h = geometry.GetDomainMaxh(domnr);\n\n\n\tPrintMessage (3, \"Meshing domain \", domnr, \" / \", maxdomnr);\n\n\tint oldnf = mesh->GetNSE();\n\n        mp.quad = hquad || geometry.GetDomainQuadMeshing (domnr);\n\n\tMeshing2 meshing (geometry, mp, Box<3> (pmin, pmax));\n\n\tNgArray<int, PointIndex::BASE> compress(mesh->GetNP());\n\tcompress = -1;\n\tint cnt = 0;\n\n        t_points.Start();\n        /*\n        for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n        {\n          const auto & s = (*mesh)[si];\n          if ( s.domin==domnr || s.domout==domnr )\n          {\n            for (auto pi : {s[0], s[1]})\n            {\n              if(compress[pi]==-1)\n              {\n                meshing.AddPoint((*mesh)[pi], pi);\n                cnt++;\n                compress[pi] = cnt;\n              }\n            }\n          }\n        }\n        */\n        for (const Segment * seg : dom2seg[domnr])\n          if (seg->domin==domnr || seg->domout==domnr )\n            for (auto pi : {(*seg)[0], (*seg)[1]})\n              if (compress[pi]==-1)\n                {\n                  meshing.AddPoint((*mesh)[pi], pi);\n                  cnt++;\n                  compress[pi] = cnt;\n                }\n\n\n\tPointGeomInfo gi;\n\tgi.trignum = 1;\n        /*\n\tfor (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n\t  {\n\t    if ( (*mesh)[si].domin == domnr)\n\t      {\n\t\tmeshing.AddBoundaryElement (compress[(*mesh)[si][0]], \n                                            compress[(*mesh)[si][1]], gi, gi);\n\t      }\n\t    if ( (*mesh)[si].domout == domnr)\n\t      {\n\t\tmeshing.AddBoundaryElement (compress[(*mesh)[si][1]],\n                                            compress[(*mesh)[si][0]], gi, gi);\n\t      }\n\t  }\n        */\n\n\tfor (const Segment * seg : dom2seg[domnr])\n\t  {\n\t    if (seg->domin == domnr)\n              meshing.AddBoundaryElement (compress[(*seg)[0]], \n                                          compress[(*seg)[1]], gi, gi);\n            \n\t    if (seg->domout == domnr)\n              meshing.AddBoundaryElement (compress[(*seg)[1]],\n                                          compress[(*seg)[0]], gi, gi);\n\t  }\n\n        \n        t_points.Stop();\n\n        if(mp.delaunay2d && cnt>1)\n          meshing.Delaunay(*mesh, domnr, mp);\n        else\n        {\n          // mp.checkoverlap = 0;\n          auto res = meshing.GenerateMesh (*mesh, mp, h, domnr);\n          if (res != 0)\n            throw NgException(\"meshing failed\");\n        }\n        \n\tfor (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++)\n\t  (*mesh)[sei].SetIndex (domnr);\n\n\t// astrid\n\tchar * material;\n\tgeometry.GetMaterial (domnr, material);\n\tif (material)\n          mesh->SetMaterial (domnr, material);\n      }\n\n    mesh->Compress();\n\n    mp.quad = hquad;\n\n\n\n    int hsteps = mp.optsteps2d;\n\n    mp.optimize2d = \"smcm\"; \n    mp.optsteps2d = hsteps/2;\n    Optimize2d (*mesh, mp);\n\n    mp.optimize2d = \"Smcm\"; \n    mp.optsteps2d = (hsteps+1)/2;\n    Optimize2d (*mesh, mp);\n\n    mp.optsteps2d = hsteps;\n\n    mesh->Compress();\n    mesh->OrderElements();\n    mesh -> SetNextMajorTimeStamp();\n\n    mp.Render();\n  }\n\n\n\n\n\n\n\n\n}\n"
  },
  {
    "path": "libsrc/geom2d/geom2dpkg.cpp",
    "content": "#include <meshing.hpp>\n#include <geometry2d.hpp>\n#include <visual.hpp>\n#include <inctcl.hpp>\n\n#include \"vsgeom2d.hpp\"\n\n// extern \"C\" int Ng_CSG_Init (Tcl_Interp * interp);\n\nnamespace netgen\n{\n\t\n\n  // extern DLL_HEADER NetgenGeometry * ng_geometry;\n  static VisualSceneGeometry2d vsgeom2d;\n\n\n\n\n\n  class SplineGeometryVisRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const { return NULL; }\n    virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;\n  };\n\n\n  VisualScene * SplineGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const\n  {\n    const SplineGeometry2d * geometry = dynamic_cast<const SplineGeometry2d*> (geom);\n    if (geometry)\n      {\n\tvsgeom2d.SetGeometry (geometry);\n\treturn &vsgeom2d;\n      }\n    return NULL;\n  }\n\n\n}\n\n\nusing namespace netgen;\n#ifdef WIN32\nextern \"C\" __declspec(dllexport) int Ng_geom2d_Init (Tcl_Interp * interp);\n#else\nextern \"C\" int Ng_geom2d_Init (Tcl_Interp * interp);\n#endif\n\nint Ng_geom2d_Init (Tcl_Interp * interp)\n{\n  GeometryRegister().Append(new SplineGeometryVisRegister);\n  return TCL_OK;\n}\n"
  },
  {
    "path": "libsrc/geom2d/geometry2d.cpp",
    "content": "/*\n\n2d Spline curve for Mesh generator\n\n*/\n\n#include <meshing.hpp>\n#include <geometry2d.hpp>\n#include <core/register_archive.hpp>\n\nnamespace netgen\n{\n\n\n\n  SplineGeometry2d :: ~SplineGeometry2d()\n  {\n    for ( int i = 0; i < bcnames.Size(); i++ )\n      delete bcnames[i];\n    for (int i=0; i<materials.Size(); i++)\n      delete [] materials[i];\n  }\n\n\n  void SplineGeometry2d :: ProjectPointEdge (int surfind, int surfind2, Point<3> & p, EdgePointGeomInfo* gi) const\n  {\n    if (!gi) return;\n    \n    // copied from PointBetween, but should work easier\n    auto spline = GetSplines().Get(gi->edgenr);\n    const SplineSeg3<2> * ss3;\n    const LineSeg<2> * ls;\n    auto ext = dynamic_cast<const SplineSegExt *>(spline);\n    if(ext)\n      {\n        ss3 = dynamic_cast<const SplineSeg3<2> *>(ext->seg);\n        ls = dynamic_cast<const LineSeg<2> *>(ext->seg);\n      }\n    else\n      {\n        ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);\n        ls = dynamic_cast<const LineSeg<2> *>(spline);\n      }\n    \n    Point<2> p2d(p(0),p(1));\n    Point<2> p_proj(0.0,0.0);\n    double t_proj = 0.0;\n\n    if(ss3)\n      ss3->Project(p2d,p_proj,t_proj);\n    else if(ls)\n      ls->Project(p2d,p_proj,t_proj);\n\n    p(0) = p_proj(0);\n    p(1) = p_proj(1);\n    gi->dist = t_proj;\n  }\n  \n  void SplineGeometry2d :: PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\n                                         int surfi1, int surfi2,\n                                         const EdgePointGeomInfo & ap1,\n                                         const EdgePointGeomInfo & ap2,\n                                         Point<3> & newp, EdgePointGeomInfo & newgi) const\n  {\n    Point<2> p2d;\n    double newdist;\n    auto spline = GetSplines().Get(ap1.edgenr);\n    if( (ap1.dist == 0.0) && (ap2.dist == 0.0) )\n      {\n        // used for manually generated meshes\n        const SplineSeg3<2> * ss3;\n        const LineSeg<2> * ls;\n        auto ext = dynamic_cast<const SplineSegExt *>(spline);\n        if(ext)\n          {\n            ss3 = dynamic_cast<const SplineSeg3<2> *>(ext->seg);\n            ls = dynamic_cast<const LineSeg<2> *>(ext->seg);\n          }\n        else\n          {\n            ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);\n            ls = dynamic_cast<const LineSeg<2> *>(spline);\n          }\n        Point<2> p12d(p1(0),p1(1)), p22d(p2(0),p2(1));\n        Point<2> p1_proj(0.0,0.0), p2_proj(0.0,0.0);\n        double t1_proj = 0.0;\n        double t2_proj = 0.0;\n        if(ss3)\n          {\n            ss3->Project(p12d,p1_proj,t1_proj);\n            ss3->Project(p22d,p2_proj,t2_proj);\n          }\n        else if(ls)\n          {\n            ls->Project(p12d,p1_proj,t1_proj);\n            ls->Project(p22d,p2_proj,t2_proj);\n          }\n        p2d = spline->GetPoint (((1-secpoint)*t1_proj+secpoint*t2_proj));\n        newdist = (1-secpoint)*t1_proj+secpoint*t2_proj;\n      }\n    else\n      {\n        p2d = spline->GetPoint (((1-secpoint)*ap1.dist+secpoint*ap2.dist));\n        newdist = (1-secpoint)*ap1.dist+secpoint*ap2.dist;\n      }\n\n    //  (*testout) << \"refine 2d line, ap1.dist, ap2.dist = \" << ap1.dist << \", \" << ap2.dist << endl;\n    //  (*testout) << \"p1, p2 = \" << p1 << p2 << \", newp = \" << p2d << endl;\n\n    newp = Point3d (p2d(0), p2d(1), 0);\n    newgi.edgenr = ap1.edgenr;\n    newgi.dist = newdist;\n  };\n\n\n\n  Vec<3> SplineGeometry2d :: GetTangent(const Point<3> & p, int surfi1, int surfi2,\n                                     const EdgePointGeomInfo & ap1) const\n  {\n    Vec<2> t2d = GetSplines().Get(ap1.edgenr) -> GetTangent(ap1.dist);\n    return Vec<3> (t2d(0), t2d(1), 0);\n  }\n\n  Vec<3> SplineGeometry2d :: GetNormal(int surfi1, const Point<3> & p,\n                                       const PointGeomInfo* gi) const\n  {\n    return Vec<3> (0,0,1);\n  }\n\n  void SplineGeometry2d :: Load (const filesystem::path & filename)\n  {\n\n    ifstream infile;\n    Point<2> x;\n    char buf[50];\n\n\n    infile.open (filename);\n  \n    if ( ! infile.good() )\n      throw NgException(string (\"Input file '\") + \n\t\t\tfilename.string() +\n\t\t\tstring (\"' not available!\"));\n\n    TestComment ( infile );\n  \n    infile >> buf;   // file recognition\n\n    tensormeshing.SetSize(0);\n    quadmeshing.SetSize(0);\n\n    TestComment ( infile );\n    if ( strcmp (buf, \"splinecurves2dnew\") == 0 )\n      {\n\tLoadDataNew ( infile );\n      }\n    else if ( strcmp (buf, \"splinecurves2dv2\") == 0 )\n      {\n\tLoadDataV2 ( infile );\n      }\n    else\n      {\n\tLoadData(infile );\n      }\n    infile.close();\n  }\n\n\n\n  // herbert: fixed TestComment\n  void SplineGeometry2d :: TestComment ( ifstream & infile )\n  {\n    bool comment = true;\n    char ch;\n    while ( comment == true && !infile.eof() ) {\n      infile.get(ch);\n      if ( ch == '#' ) { // skip comments\n\twhile (  ch != '\\n' && !infile.eof() ) {\n\t  infile.get(ch);\n\t}\n      }\n      else if ( ch == '\\n' )  { // skip empty lines\n\t;\n      }\n      else if ( isspace(ch) ) { // skip whitespaces\n\t; \n      }\n      else { // end of comment\n\tinfile.putback(ch);\n\tcomment = false;\n      }\n    }\n    return;\n  }\n\n\n\n\n  void SplineGeometry2d :: LoadData ( ifstream & infile )\n  {      \n    enum { D = 2 };\n\n    int nump, numseg, leftdom, rightdom;\n    Point<D> x;\n    int hi1, hi2, hi3;\n    double hd;\n    char buf[50], ch;\n\n    materials.SetSize(0);\n    maxh.SetSize(0);\n    infile >> elto0;\n\n    TestComment ( infile );\n\n    infile >> nump;\n    for (int i = 0; i < nump; i++)\n      {\n\tTestComment ( infile );\n\tfor(int j=0; j<D; j++)\n\t  infile >> x(j);\n\tinfile >> hd;\n\n\tFlags flags;\n\n\tch = 'a';\n\t// infile >> ch;\n\tdo {\n\t  infile.get (ch);\n\t} while (isspace(ch) && ch != '\\n');\n\twhile (ch == '-')\n\t  {\n\t    char flag[100];\n\t    flag[0]='-';\n\t    infile >> (flag+1);\n\t    flags.SetCommandLineFlag (flag);\n\t    ch = 'a';\n\t    do {\n\t      infile.get (ch);\n\t    } while (isspace(ch) && ch != '\\n');\n\t  }\n    \n\tif (infile.good())\n\t  infile.putback (ch);\n\n\tgeompoints.Append (GeomPoint<D>(x, hd));\n\tgeompoints.Last().hpref = flags.GetDefineFlag (\"hpref\");\n\tgeompoints.Last().hmax = flags.GetNumFlag(\"hmax\", 1e99);\n      }\n\n    PrintMessage (3, nump, \" points loaded\");\n    TestComment ( infile );\n\n    infile >> numseg;\n    bcnames.SetSize(numseg);\n    for ( int i = 0; i < numseg; i++ )\n      bcnames[i] = 0; // \"default\";\n\n    SplineSeg<D> * spline = 0;\n\n    PrintMessage (3, numseg, \" segments loaded\");\n    for (int i = 0; i < numseg; i++)\n      {\n\tTestComment ( infile );\n      \n\tinfile >> leftdom >> rightdom;\n\n\t// cout << \"add spline \" << i << \", left = \" << leftdom << \", right = \" << rightdom << endl;\n      \n\tinfile >> buf;\n\t// type of spline segment\n\tif (strcmp (buf, \"2\") == 0)\n\t  { // a line\n\t    infile >> hi1 >> hi2;\n\t    spline = new LineSeg<D>(geompoints[hi1-1],\n\t\t\t\t    geompoints[hi2-1]);\n\t  }\n\telse if (strcmp (buf, \"3\") == 0)\n\t  { // a rational spline\n\t    infile >> hi1 >> hi2 >> hi3;\n\t    spline = new SplineSeg3<D> (geompoints[hi1-1],\n\t\t\t\t\tgeompoints[hi2-1],\n\t\t\t\t\tgeompoints[hi3-1]);\n\t  }\n\telse if (strcmp (buf, \"4\") == 0)\n\t  { // an arc\n\t    infile >> hi1 >> hi2 >> hi3;\n\t    spline = new CircleSeg<D> (geompoints[hi1-1],\n\t\t\t\t       geompoints[hi2-1],\n\t\t\t\t       geompoints[hi3-1]);\n\t    // \t  break;\n\t  }\n\telse if (strcmp (buf, \"discretepoints\") == 0)\n\t  {\n\t    int npts;\n\t    infile >> npts;\n\t    NgArray< Point<D> > pts(npts);\n\t    for (int j = 0; j < npts; j++)\n\t      for(int k=0; k<D; k++)\n\t\tinfile >> pts[j](k);\n\n\t    spline = new DiscretePointsSeg<D> (pts);\n\t  }\n    \n\n\tSplineSegExt * spex = new SplineSegExt (*spline);\n\t\n\tinfile >> spex->reffak;\n\tspex -> leftdom = leftdom;\n\tspex -> rightdom = rightdom;\n\tsplines.Append (spex);\n\n\n\tFlags flags;\n\tch = 'a';\n\tinfile >> ch;\n\twhile (ch == '-')\n\t  {\n\t    char flag[100];\n\t    flag[0]='-';\n\t    infile >> (flag+1);\n\t    flags.SetCommandLineFlag (flag);\n\t    ch = 'a';\n\t    infile >> ch;\n\t  }\n    \n\tif (infile.good())\n\t  infile.putback (ch);\n    \n\tspex->bc = int (flags.GetNumFlag (\"bc\", i+1));\n\tspex->hpref_left = int (flags.GetDefineFlag (\"hpref\")) || \n\t  int (flags.GetDefineFlag (\"hprefleft\"));\n\tspex->hpref_right = int (flags.GetDefineFlag (\"hpref\")) || \n\t  int (flags.GetDefineFlag (\"hprefright\"));\n\tspex->copyfrom = int (flags.GetNumFlag (\"copy\", -1));\n\tif ( flags.StringFlagDefined(\"bcname\") )\n\t  {\n\t    int mybc = spex->bc-1;\n\t    delete bcnames[mybc];\n\t    bcnames[mybc] = new string (flags.GetStringFlag(\"bcname\",\"\") );\n\t  }\n\tspex -> hmax = flags.GetNumFlag(\"hmax\", 1e99);\n      }\n  }\n\n\n\n\n  void SplineGeometry2d :: LoadDataNew ( ifstream & infile )\n  {\n    enum { D = 2 };\n    int nump, numseg, leftdom, rightdom;\n    Point<D> x;\n    int hi1, hi2, hi3;\n    double hd;\n    char buf[50], ch;\n    int pointnr;\n\n\n    TestComment ( infile );\n    infile >> elto0;\n    TestComment ( infile );\n      \n    infile >> nump;\n    geompoints.SetSize(nump);\n      \n    for (int i = 0; i < nump; i++)\n      {\n\tTestComment ( infile );\n\tinfile >> pointnr;\n\tif ( pointnr > nump )\n\t  {\n\t    throw NgException(string (\"Point number greater than total number of points\") );\n\t  }\n\tfor(int j=0; j<D; j++)\n\t  infile >> x(j);\n\n\n\t// hd is now optional, default 1\n\t//  infile >> hd;\n\thd = 1;\n\n\tFlags flags;\n\n\n\t// get flags, \n\tch = 'a';\n\t// infile >> ch;\n\tdo \n\t  {\n\n\t    infile.get (ch);\n\t    // if another int-value, set refinement flag to this value\n\t    // (corresponding to old files)\n\t    if ( int (ch) >= 48 && int(ch) <= 57 )\n\t      {\n\t\tinfile.putback(ch);\n\t\tinfile >> hd;\n\t\tinfile.get(ch);\n\t      }\n\t  } \n\twhile (isspace(ch) && ch != '\\n');\n\twhile (ch == '-')\n\t  {\n\t    char flag[100];\n\t    flag[0]='-';\n\t    infile >> (flag+1);\n\t    flags.SetCommandLineFlag (flag);\n\t    ch = 'a';\n\t    do {\n\t      infile.get (ch);\n\t    } while (isspace(ch) && ch != '\\n');\n\t  }\n    \n\tif (infile.good())\n\t  infile.putback (ch);\n\n\tif ( hd == 1 )\n\t  hd = flags.GetNumFlag ( \"ref\", 1.0);\n\t//       geompoints.Append (GeomPoint<D>(x, hd));\n\tgeompoints[pointnr-1] = GeomPoint<D>(x, hd);\n\tgeompoints[pointnr-1].hpref = flags.GetDefineFlag (\"hpref\");\n      }\n\n    TestComment ( infile );\n\n    infile >> numseg;\n    bcnames.SetSize(numseg);\n    for ( int i = 0; i < numseg; i++ )\n      bcnames[i] = 0;//new\"default\";\n\n    SplineSeg<D> * spline = 0;\n    for (int i = 0; i < numseg; i++)\n      {\n\tTestComment ( infile );\n      \n\tinfile >> leftdom >> rightdom;\n\n\t// cout << \"add spline \" << i << \", left = \" << leftdom << endl;\n\n\tinfile >> buf;\n\t// type of spline segment\n\tif (strcmp (buf, \"2\") == 0)\n\t  { // a line\n\t    infile >> hi1 >> hi2;\n\t    spline = new LineSeg<D> (geompoints[hi1-1],\n\t\t\t\t     geompoints[hi2-1]);\n\t  }\n\telse if (strcmp (buf, \"3\") == 0)\n\t  { // a rational spline\n\t    infile >> hi1 >> hi2 >> hi3;\n\t    spline = new SplineSeg3<D> (geompoints[hi1-1],\n\t\t\t\t\tgeompoints[hi2-1],\n\t\t\t\t\tgeompoints[hi3-1]);\n\t  }\n\telse if (strcmp (buf, \"4\") == 0)\n\t  { // an arc\n\t    infile >> hi1 >> hi2 >> hi3;\n\t    spline = new CircleSeg<D> (geompoints[hi1-1],\n\t\t\t\t       geompoints[hi2-1],\n\t\t\t\t       geompoints[hi3-1]);\n\t    // \t  break;\n\t  }\n\telse if (strcmp (buf, \"discretepoints\") == 0)\n\t  {\n\t    int npts;\n\t    infile >> npts;\n\t    NgArray< Point<D> > pts(npts);\n\t    for (int j = 0; j < npts; j++)\n\t      for(int k=0; k<D; k++)\n\t\tinfile >> pts[j](k);\n\n\t    spline = new DiscretePointsSeg<D> (pts);\n\t  }\n    \n\t//      infile >> spline->reffak;\n\n\tSplineSegExt * spex = new SplineSegExt (*spline);\n\n\tspex -> leftdom = leftdom;\n\tspex -> rightdom = rightdom;\n\tsplines.Append (spex);\n\n\t// hd is now optional, default 1\n\t//  infile >> hd;\n\thd = 1;\n\tinfile >> ch;\n      \n\t// get refinement parameter, if it is there\n\t// infile.get (ch);\n\t// if another int-value, set refinement flag to this value\n\t// (corresponding to old files)\n\tif ( int (ch) >= 48 && int(ch) <= 57 )\n\t  {\n\t    infile.putback(ch);\n\t    infile >> hd;\n\t    infile >> ch ;\n\t  }\n      \n\tFlags flags;\n\twhile (ch == '-')\n\t  {\n\t    char flag[100];\n\t    flag[0]='-';\n\t    infile >> (flag+1);\n\t    flags.SetCommandLineFlag (flag);\n\t    ch = 'a';\n\t    infile >> ch;\n\t  }\n    \n\tif (infile.good())\n\t  infile.putback (ch);\n    \n\tspex->bc = int (flags.GetNumFlag (\"bc\", i+1));\n\tspex->hpref_left = int (flags.GetDefineFlag (\"hpref\")) || \n\t  int (flags.GetDefineFlag (\"hprefleft\"));\n\tspex->hpref_right = int (flags.GetDefineFlag (\"hpref\")) || \n\t  int (flags.GetDefineFlag (\"hprefright\"));\n\tspex->copyfrom = int (flags.GetNumFlag (\"copy\", -1));\n\tspex->reffak = flags.GetNumFlag (\"ref\", 1 );\n\tspex->hmax = flags.GetNumFlag (\"maxh\", 1e99 );\n\n\tif ( flags.StringFlagDefined(\"bcname\") )\n\t  {\n\t    int mybc = spex->bc-1;\n\t    if ( bcnames[mybc] ) delete bcnames[mybc];\n\t    bcnames[mybc] = new string (flags.GetStringFlag(\"bcname\",\"\") );\n\t  }\n\n\tif ( hd != 1 )\n\t  spex->reffak = hd;\n      }\n    if ( !infile.good() )\n      return;\n    TestComment ( infile );\n    int numdomains;\n    int domainnr;\n    char material[100];\n\n    if ( !infile.good() ) \n      return;\n\n    infile >> numdomains;\n    materials.SetSize(numdomains) ;\n    maxh.SetSize ( numdomains ) ;\n    maxh = 1e99;\n\n    TestComment ( infile );\n\n    for ( int i=0; i<numdomains; i++)\n      materials [ i ] = new char (100);\n\n    for ( int i=0; i<numdomains && infile.good(); i++)\n      {\n\tTestComment ( infile );\n\tinfile >> domainnr;\n\tinfile >> material;\n\tstrcpy(materials[domainnr-1], material);\n\n\tFlags flags;\n\tch = 'a';\n\tinfile >> ch;\n\twhile (ch == '-')\n\t  {\n\t    char flag[100];\n\t    flag[0]='-';\n\t    infile >> (flag+1);\n\t    flags.SetCommandLineFlag (flag);\n\t    ch = 'a';\n\t    infile >> ch;\n\t  }\n    \n\tif (infile.good())\n\t  infile.putback (ch);\n\t \n\tmaxh[domainnr-1] = flags.GetNumFlag ( \"maxh\", 1e99);\n      }\n    return;\n  }\n\n\n\n\n  void SplineGeometry2d :: LoadDataV2 ( ifstream & infile )\n  { \n    enum { D = 2 };\n    // new parser by Astrid Sinwel\n    \n    PrintMessage (1, \"Load 2D Geometry V2\");\n    int nump, leftdom, rightdom;\n    Point<D> x;\n    int hi1, hi2, hi3;\n    double hd;\n    char buf[50], ch;\n    int pointnr;\n\n    string keyword;\n\n    NgArray < GeomPoint<D> > infilepoints (0);\n    NgArray <int> pointnrs (0);\n    nump = 0;\n    int numdomains = 0;\n\n\n    TestComment ( infile );\n    // refinement factor\n    infile >> elto0;\n    TestComment ( infile );\n      \n\n    // test if next ch is a letter, i.e. new keyword starts\n    bool ischar = false;\n\n    while ( infile.good() )\n      {\n\tinfile >> keyword;\n\n\tischar = false;\n\n\tif ( keyword == \"points\" )\n\t  {\n\t    PrintMessage (3, \"load points\");\n\t    infile.get(ch);\n\t    infile.putback(ch);\n\n\t    // test if ch is a letter\n\t    if ( int(ch) >= 65 && int(ch) <=90 )\n\t      ischar = true;\n\t    if ( int(ch) >= 97 && int(ch) <= 122 )\n\t      ischar = true;\n\n\t    while ( ! ischar )\n\t      {\n\t\tTestComment ( infile );\n\t\tinfile >> pointnr;\n\t\t// pointnrs 1-based\n\t\tif ( pointnr > nump ) nump = pointnr; \n\t\tpointnrs.Append(pointnr);\n\t      \n\t\tfor(int j=0; j<D; j++)\n\t\t  infile >> x(j);\n\t\t// hd is now optional, default 1\n\t\t//  infile >> hd;\n\t\thd = 1;\n\t      \n\t\tFlags flags;\n\t      \n\t      \n\t\t// get flags, \n\t\tch = 'a';\n\t\t// infile >> ch;\n\t\tdo \n\t\t  {\n\t\t    infile.get (ch);\n\t\t    // if another int-value, set refinement flag to this value\n\t\t    // (corresponding to old files)\n\t\t    if ( int (ch) >= 48 && int(ch) <= 57 )\n\t\t      {\n\t\t\tinfile.putback(ch);\n\t\t\tinfile >> hd;\n\t\t\tinfile.get(ch);\n\t\t      }\n\t\t  } \n\t\twhile (isspace(ch) && ch != '\\n');\n\t\twhile (ch == '-')\n\t\t  {\n\t\t    char flag[100];\n\t\t    flag[0]='-';\n\t\t    infile >> (flag+1);\n\t\t    flags.SetCommandLineFlag (flag);\n\t\t    ch = 'a';\n\t\t    do {\n\t\t      infile.get (ch);\n\t\t    } while (isspace(ch) && ch != '\\n');\n\t\t  }\n\t\tif (infile.good())\n\t\t  infile.putback (ch);\n\t      \n\t\tif ( hd == 1 )\n\t\t  hd = flags.GetNumFlag ( \"ref\", 1.0);\n\t\t//       geompoints.Append (GeomPoint<D>(x, hd));\n\n\t\tinfilepoints.Append ( GeomPoint<D>(x, hd) );\n\t\tinfilepoints.Last().hpref = flags.GetDefineFlag (\"hpref\");\n\t\tinfilepoints.Last().hmax = flags.GetNumFlag (\"maxh\", 1e99);\n\n\t\tTestComment(infile);\n\t\tinfile.get(ch);\n\t\tinfile.putback(ch);\n\n\t\t// test if letter\n\t\tif ( int(ch) >= 65 && int(ch) <=90 )\n\t\t  ischar = true;\n\t\tif ( int(ch) >= 97 && int(ch) <= 122 )\n\t\t  ischar = true;\n\t      }\n\n\t    //\t  infile.putback (ch);\n\n\t    geompoints.SetSize(nump);\n\t    for ( int i = 0; i < nump; i++ )\n\t      {\n\t\tgeompoints[pointnrs[i] - 1] = infilepoints[i];\n\t\tgeompoints[pointnrs[i] - 1].hpref = infilepoints[i].hpref; \n\t      }\n\t    TestComment(infile);\n\t  }\n\n\telse if ( keyword == \"segments\" )\n\t  {\n\t    PrintMessage (3, \"load segments\");\n\n\t    bcnames.SetSize(0);\n\t    infile.get(ch);\n\t    infile.putback(ch);\n\t    int i = 0;\n\n\t    // test if ch is a letter\n\t    if ( int(ch) >= 65 && int(ch) <=90 )\n\t      ischar = true;\n\t    if ( int(ch) >= 97 && int(ch) <= 122 )\n\t      ischar = true;\n\n\t    while ( !ischar ) //ch != 'p' && ch != 'm' )\n\t      {\n\t\ti++;\n\t\tTestComment ( infile );\n\n\t\tSplineSeg<D> * spline = 0;\n\t\tTestComment ( infile );\n\t\t  \n\t\tinfile >> leftdom >> rightdom;\n\t      \n\t\tif ( leftdom > numdomains ) numdomains = leftdom;\n\t\tif ( rightdom > numdomains ) numdomains = rightdom;\n\n\t      \n\t\tinfile >> buf;\n\t\t// type of spline segment\n\t\tif (strcmp (buf, \"2\") == 0)\n\t\t  { // a line\n\t\t    infile >> hi1 >> hi2;\n\t\t    spline = new LineSeg<D>(geompoints[hi1-1],\n\t\t\t\t\t    geompoints[hi2-1]);\n\t\t  }\n\t\telse if (strcmp (buf, \"3\") == 0)\n\t\t  { // a rational spline\n\t\t    infile >> hi1 >> hi2 >> hi3;\n\t\t    spline = new SplineSeg3<D> (geompoints[hi1-1],\n\t\t\t\t\t\tgeompoints[hi2-1],\n\t\t\t\t\t\tgeompoints[hi3-1]);\n\t\t  }\n\t\telse if (strcmp (buf, \"4\") == 0)\n\t\t  { // an arc\n\t\t    infile >> hi1 >> hi2 >> hi3;\n\t\t    spline = new CircleSeg<D> (geompoints[hi1-1],\n\t\t\t\t\t       geompoints[hi2-1],\n\t\t\t\t\t       geompoints[hi3-1]);\n\t\t  }\n\t\telse if (strcmp (buf, \"discretepoints\") == 0)\n\t\t  {\n\t\t    int npts;\n\t\t    infile >> npts;\n\t\t    NgArray< Point<D> > pts(npts);\n\t\t    for (int j = 0; j < npts; j++)\n\t\t      for(int k=0; k<D; k++)\n\t\t\tinfile >> pts[j](k);\n\t\t  \n\t\t    spline = new DiscretePointsSeg<D> (pts);\n\t\t  }\n\t\telse if (strcmp (buf, \"bsplinepoints\") == 0)\n\t\t  {\n\t\t    int npts,order;\n\t\t    infile >> npts;    \n\t\t    infile >> order;\n\t\t    NgArray< Point<D> > pts(npts);\n\t\t    for (int j = 0; j < npts; j++)\n\t\t      for(int k=0; k<D; k++)\n\t\t\tinfile >> pts[j](k);\t    \t\t    \n\t\t    if(order<2)\t\t      \n\t\t\tcerr<<\"Minimum order of 2 is required!!\"<<endl;\n\t\t    else if(order==2)\n\t\t      spline = new BSplineSeg<D,2> (pts);\n\t\t      else if(order==3)\n\t\t\tspline = new BSplineSeg<D,3> (pts);\n\t\t      else if(order==4)\n\t\t\tspline = new BSplineSeg<D,4> (pts);\n\t\t      else if(order>4)\t\t      \n\t\t\tcerr<<\"Maximum allowed order is 4!!\"<<endl;\n\t\t  }\n\t      \n\t\t//      infile >> spline->reffak;\n\t\tSplineSegExt * spex = new SplineSegExt (*spline);\n\n\t\tspex -> leftdom = leftdom;\n\t\tspex -> rightdom = rightdom;\n\t\tsplines.Append (spex);\n\t      \n\t      \n\t\t// hd is now optional, default 1\n\t\t//  infile >> hd;\n\t\thd = 1;\n\n\t\tinfile >> ch;\n\t      \n\t\t// get refinement parameter, if it is there\n\t\t//infile.get (ch);\n\t\t// if another int-value, set refinement flag to this value\n\t\t// (corresponding to old files)\n                /*\n\t\tif ( int (ch) >= 48 && int(ch) <= 57 )\n\t\t  {\n\t\t    infile.putback(ch);\n\t\t    infile >> hd;\n\t\t    infile >> ch ;\n\t\t  }\n                */\n\t\t// get flags, \n\t\tFlags flags;\n\t\twhile (ch == '-')\n\t\t  {\n\t\t    char flag[100];\n\t\t    flag[0]='-';\n\t\t    infile >> (flag+1);\n\t\t    flags.SetCommandLineFlag (flag);\n\t\t    ch = 'a';\n\t\t    infile >> ch;\n\t\t  }\n\t      \n\t\tif (infile.good())\n\t\t  infile.putback (ch);\n\t      \n\t\tspex->bc = int (flags.GetNumFlag (\"bc\", i+1));\n\t\tspex->hpref_left = int (flags.GetDefineFlag (\"hpref\")) || \n\t\t  int (flags.GetDefineFlag (\"hprefleft\"));\n\t\tspex->hpref_right = int (flags.GetDefineFlag (\"hpref\")) || \n\t\t  int (flags.GetDefineFlag (\"hprefright\"));\n\t\tspex->copyfrom = int (flags.GetNumFlag (\"copy\", -1));\n\t\tspex->reffak = flags.GetNumFlag (\"ref\", 1 );\n\t\tspex->hmax = flags.GetNumFlag (\"maxh\", 1e99 );\n\t\tif ( hd != 1 ) spex->reffak = hd;\n\n\t\tif ( flags.StringFlagDefined(\"bcname\") )\n\t\t  {\n\t\t    int mybc = spex->bc-1;\n\t\t    for ( int ii = bcnames.Size(); ii <= mybc; ii++ )\n\t\t      bcnames.Append ( new string (\"default\"));\n\t\t    if ( bcnames[mybc] ) delete bcnames[mybc];\n\t\t    bcnames[mybc] = new string (flags.GetStringFlag(\"bcname\",\"\") );\n\t\t  }\n\n\t\tTestComment(infile);\n\t\tinfile.get(ch);\n\t\tinfile.putback(ch);\n\n\t\t// test if ch is a letter\n\t\tif ( int(ch) >= 65 && int(ch) <=90 )\n\t\t  ischar = true;\n\t\tif ( int(ch) >= 97 && int(ch) <= 122 )\n\t\t  ischar = true;\n\n\t      }\n\t  \n\t    infile.get(ch);\n\t    infile.putback(ch);\n\t\n\n\t  }\n\telse if ( keyword == \"materials\" )\n\t  {\n\t    TestComment ( infile );\n\t    int domainnr;\n\t    char material[100];\n\t  \n\t    if ( !infile.good() ) \n\t      return;\n\t  \n\t    materials.SetSize(numdomains) ;\n\t    maxh.SetSize ( numdomains ) ;\n\t    for ( int i = 0; i < numdomains; i++)\n\t      maxh[i] = 1000;\n\t    quadmeshing.SetSize ( numdomains );\n\t    quadmeshing = false;\n\t    tensormeshing.SetSize ( numdomains );\n\t    tensormeshing = false;\n\t    layer.SetSize ( numdomains );\n\t    layer = 1;\n\n\t  \n\t    TestComment ( infile );\n\t  \n\t    for ( int i=0; i<numdomains; i++)\n\t      materials [ i ] = new char[100];\n\t  \n\t    for ( int i=0; i<numdomains && infile.good(); i++)\n\t      {\n\t\tTestComment ( infile );\n\t\tinfile >> domainnr;\n\t\tinfile >> material;\n\n\t\tstrcpy (materials[domainnr-1], material);\n\t      \n\t\tFlags flags;\n\t\tch = 'a';\n\t\tinfile >> ch;\n\t\twhile (ch == '-')\n\t\t  {\n\t\t    char flag[100];\n\t\t    flag[0]='-';\n\t\t    infile >> (flag+1);\n\t\t    flags.SetCommandLineFlag (flag);\n\t\t    ch = 'a';\n\t\t    infile >> ch;\n\t\t  }\n\t      \n\t\tif (infile.good())\n\t\t  infile.putback (ch);\n\t      \n\t\tmaxh[domainnr-1] = flags.GetNumFlag ( \"maxh\", 1000);\n\t\tif (flags.GetDefineFlag(\"quad\")) quadmeshing[domainnr-1] = true;\n\t\tif (flags.GetDefineFlag(\"tensor\")) tensormeshing[domainnr-1] = true;\n\t\tlayer[domainnr-1] = int(flags.GetNumFlag (\"layer\", 1));\n\t      }\n\t  }\n      }\n    return;\n  }\n\n\n\n\n\n\n\n\n\n  /*\n  void CalcPartition (const SplineSegExt & spline,\n\t\t      double l, double h, double h1, double h2,\n\t\t      double hcurve, double elto0, NgArray<double> & points)\n  {\n    double fperel, oldf, f;\n\n    int n = 1000;\n\n    points.SetSize (0);\n\n    double dt = l / n;\n\n    double sum = 0;\n    for (int i = 1; i <= n; i++)\n      {\n\tdouble t = (i-0.5)*dt;\n\tdouble fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2);\n\tdouble curv = spline.CalcCurvature (t/l);\n\tcout << \"curv = \" << curv << endl;\n\tif (curv < 1e-10) curv = 1e-10;\n\tfun = min2 (fun, 0.1/curv);\n\tsum += dt / fun;\n      }\n\n    int nel = int (sum+1);\n    fperel = sum / nel;\n\n    points.Append (0);\n\n    int i = 1;\n    oldf = 0;\n    // t = 0.5 * dt;\n    for (int j = 1; j <= n && i < nel; j++)\n      {\n\tdouble t = (j-0.5)*dt;\n\tdouble fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2);\n\tdouble curv = spline.CalcCurvature (t/l);\n\tif (curv < 1e-10) curv = 1e-10;\n\tfun = min2 (fun, 0.1/curv);\n\n\tf = oldf + dt / fun;\n\n\twhile (i * fperel < f && i < nel)\n\t  {\n\t    points.Append ( dt * (j-1) +  (i * fperel - oldf) * fun);\n\t    i++;\n\t  }\n\toldf = f;\n\tt += dt;\n      }\n    points.Append (l);\n  }\n  */\n\n\n\n\n\n\n  void SplineGeometry2d :: SetBCName (int bcnr, string name) \n  {\n    if (bcnr < 1)\n      throw NgException (\"Illegal nr in SetBCName\");\n    int new_to_add = bcnr - bcnames.Size();\n    for (int i = 0; i < new_to_add; i++)\n      bcnames.Append (new string(\"default\"));\n    delete bcnames[bcnr-1];\n    bcnames[bcnr-1] = new string(name);\n  }\n  \n  string SplineGeometry2d :: GetBCName( int  bcnr ) const\n  {\n    if (bcnames.Size() >= bcnr)\n      if (bcnames[bcnr-1] )\n\treturn *bcnames[bcnr-1];\n    return \"default\";\n  }\n\n  string * SplineGeometry2d :: BCNamePtr( int bcnr ) \n  {\n    if ( bcnr > bcnames.Size() )\n      return nullptr;\n    else\n      return bcnames[bcnr-1];\n  }\n\n\n  int SplineGeometry2d :: GetBCNumber (string name) const\n  {\n    for (int i = 0; i < bcnames.Size(); i++)\n      if (*bcnames[i] == name)\n        return i+1;\n    return 0;\n  }\n\n  int SplineGeometry2d :: AddBCName (string name)\n  {\n    bcnames.Append (new string(name));\n    return bcnames.Size();\n  }\n\n\n\n  void SplineGeometry2d :: GetMaterial (int  domnr, char* & material )\n  {\n    if ( materials.Size() >= domnr)\n      material =  materials[domnr-1];\n    else \n      material = 0;\n  }\n\n  void SplineGeometry2d :: SetMaterial (int  domnr, const string & material)\n  {\n    int oldsize = materials.Size();\n    if (domnr > materials.Size()) materials.SetSize (domnr);\n    for (int i = oldsize; i < domnr; i++)\n      materials[i] = nullptr;\n    \n    if (domnr >= 1) //  && domnr <= materials.Size())\n      {\n        delete materials[domnr-1];\n        materials[domnr-1] = new char[material.size()+1];\n        strcpy(materials[domnr-1], material.c_str());\n      }\n    else\n      throw NgException (\"material index out of range\");\n  }\n\n  \n\n  double SplineGeometry2d :: GetDomainMaxh (const int domnr )\n  {\n    if ( maxh.Size() >= domnr  && domnr > 0)\n      return maxh[domnr-1];\n    else\n      return -1;\n  }\n\n  void SplineGeometry2d :: SetDomainMaxh (int domnr, double h)\n  {\n    int oldsize = maxh.Size();\n    if (domnr > maxh.Size()) maxh.SetSize (domnr);\n    for (int i = oldsize; i < domnr; i++)\n      maxh[i] = 1e99;\n    \n    if (domnr >= 1) \n      maxh[domnr-1] = h;\n    else\n      throw NgException (\"material index out of range\");\n  }\n\n  \n\n  extern void MeshFromSpline2D (SplineGeometry2d & geometry,\n\t\t\t\tshared_ptr<Mesh> & mesh, \n\t\t\t\tMeshingParameters & mp);\n\n\n  int SplineGeometry2d :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)\n  {\n    if(restricted_h.Size())\n      {\n        // copy so that we don't change mparam outside\n        MeshingParameters mp = mparam;\n        for(const auto& [pnt, maxh] : restricted_h)\n          mp.meshsize_points.Append({pnt, maxh});\n        MeshFromSpline2D (*this, mesh, mp);\n      }\n    else\n      MeshFromSpline2D (*this, mesh, mparam);\n    return 0;\n  }\n\n  class SplineGeometryRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const;\n  };\n\n  NetgenGeometry *  SplineGeometryRegister :: Load (const filesystem::path & filename) const\n  {\n    string ext = ToLower(filename.extension());\n    if (ext == \".in2d\")\n      {\n\tPrintMessage (1, \"Load 2D-Spline geometry file \", filename);\n\n\tifstream infile(filename);\n\n\tSplineGeometry2d * hgeom = new SplineGeometry2d();\n\thgeom -> Load (filename);\n\treturn hgeom;\n      }\n    \n    return NULL;\n  }\n\n  class SplineGeoInit\n  {\n  public:\n    SplineGeoInit()\n    {\n      GeometryRegister().Append(new SplineGeometryRegister);\n    }\n  };\n\n  SplineGeoInit sginit;\n  static RegisterClassForArchive<SplineGeometry2d, tuple<SplineGeometry<2>, NetgenGeometry>> regspg2;\n  static RegisterClassForArchive<SplineSegExt, SplineSeg<2>> regssext;\n}\n"
  },
  {
    "path": "libsrc/geom2d/geometry2d.hpp",
    "content": "#ifndef FILE_GEOMETRY2D\n#define FILE_GEOMETRY2D\n\n/* *************************************************************************/\n/* File:   geometry2d.hpp                                                  */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   20. Jul. 02                                                     */\n/* *************************************************************************/\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n#include <meshing.hpp>\n\n\n// #include \"../gprim/spline.hpp\"\n// #include \"../gprim/splinegeometry.hpp\"\n\nnamespace netgen\n{\n\n  class SplineSegExt : public SplineSeg<2>\n  {\n  public:\n    SplineSeg<2>* seg;\n    \n    /// left domain\n    int leftdom;\n    /// right domain\n    int rightdom;\n    /// refinement at line\n    double reffak;\n    /// maximal h;\n    double hmax;\n    /// boundary condition number\n    int bc;\n    /// copy spline mesh from other spline (-1.. do not copy)\n    int copyfrom;\n    /// perform anisotropic refinement (hp-refinement) to edge\n    double hpref_left;\n    /// perform anisotropic refinement (hp-refinement) to edge\n    double hpref_right;\n    ///\n    int layer;\n\n    SplineSegExt (SplineSeg<2> & hseg)\n      : seg(&hseg)\n    {\n      layer = 1;\n    }\n    // default constructor for archive\n    SplineSegExt() {}\n\n    ~SplineSegExt ()\n    {\n      delete seg;\n    }\n\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom\n        & hpref_left & hpref_right & layer;\n    }\n    \n    virtual const GeomPoint<2> & StartPI () const \n    { \n      return seg->StartPI();\n    }\n\n    virtual const GeomPoint<2> & EndPI () const \n    {\n      return seg->EndPI();\n    }\n\n    virtual Point<2> GetPoint (double t) const \n    {\n      return seg->GetPoint(t);\n    }\n\n    virtual Vec<2> GetTangent (const double t) const\n    {\n      return seg->GetTangent(t);\n    }\n\n    virtual void GetDerivatives (const double t,  \n\t\t\t\t Point<2> & point,\n\t\t\t\t Vec<2> & first,\n\t\t\t\t Vec<2> & second) const\n    {\n      seg->GetDerivatives (t, point, first, second);\n    }\n\n    virtual void GetCoeff (Vector & coeffs) const \n    {\n      seg->GetCoeff (coeffs);\n    }\n\n    virtual void GetPoints (int n, NgArray<Point<2> > & points) const\n    {\n      seg->GetPoints (n, points);\n    }\n\n    virtual double MaxCurvature () const \n    {\n      return seg->MaxCurvature();\n    }\n\n    virtual string GetType () const\n    {\n      return seg->GetType();\n    }\n\n    virtual double CalcCurvature (double t) const\n    {\n      Point<2> point;\n      Vec<2> first, second;\n      GetDerivatives (t, point, first, second);\n      double curv = fabs(first(0)*second(1)-first(1)*second(0)) / pow(first.Length(), 3);\n      return curv;\n    }\n\n    virtual bool InConvexHull (Point<2> p, double eps) const\n    {\n      return seg->InConvexHull (p, eps);\n    }\n\n  };\n\n\n\n\n  class DLL_HEADER SplineGeometry2d : public SplineGeometry<2>, public NetgenGeometry\n  {\n  protected:\n    NgArray<char*> materials;\n    NgArray<double> maxh;\n    NgArray<bool> quadmeshing;\n    Array<bool> tensormeshing;\n    NgArray<int> layer;\n    NgArray<string*> bcnames;\n    double elto0 = 1.0;\n\n\n  public:\n    virtual ~SplineGeometry2d();\n\n    void Load (const filesystem::path & filename);\n\n    void LoadData( ifstream & infile );\n    void LoadDataNew ( ifstream & infile );\n    void LoadDataV2 ( ifstream & infile );\n\n    void TestComment ( ifstream & infile ) ;\n\n    void DoArchive(Archive& ar) override\n    {\n      SplineGeometry<2>::DoArchive(ar);\n      ar & materials & maxh & quadmeshing & tensormeshing & layer & bcnames & elto0;\n    }\n\n    bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const override\n    {\n      p(2) = 0.0;\n      return true;\n    }\n\n    void ProjectPointEdge (int surfind, int surfind2, Point<3> & p, EdgePointGeomInfo* gi = nullptr) const override;\n\n\n    void PointBetween(const Point<3> & p1, const Point<3> & p2, double secpoint,\n                      int surfi,\n                      const PointGeomInfo & gi1,\n                      const PointGeomInfo & gi2,\n                      Point<3> & newp, PointGeomInfo & newgi) const override\n    {\n      newp = p1+secpoint*(p2-p1);\n      newgi.trignum = 1;\n    }\n\n    void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\n                          int surfi1, int surfi2,\n                          const EdgePointGeomInfo & ap1,\n                          const EdgePointGeomInfo & ap2,\n                          Point<3> & newp, EdgePointGeomInfo & newgi) const override;\n\n\n    Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2,\n                       const EdgePointGeomInfo & ap1) const override;\n    Vec<3> GetNormal(int surfi1, const Point<3> & p,\n                     const PointGeomInfo* gi) const override;\n\n    const SplineSegExt & GetSpline (const int i) const \n    { \n      return dynamic_cast<const SplineSegExt&> (*splines[i]);\n    }\n\n    SplineSegExt & GetSpline (const int i) \n    { \n      return dynamic_cast<SplineSegExt&> (*splines[i]);\n    }\n\n    \n    int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam) override;\n    \n    void PartitionBoundary (MeshingParameters & mp, double h, Mesh & mesh2d);\n\n    void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree);\n\n\n    size_t GetNDomains() const { return materials.Size(); }\n    void GetMaterial (int  domnr, char* & material );\n    void SetMaterial (int  domnr, const string & material);\n\n    double GetDomainMaxh ( const int domnr );\n    void SetDomainMaxh ( const int domnr, double maxh );\n    \n    bool GetDomainQuadMeshing ( int domnr ) \n    { \n      if ( quadmeshing.Size() ) return quadmeshing[domnr-1]; \n      else return false;\n    }\n    void SetDomainQuadMeshing ( int domnr, bool quad_meshing )\n    {\n      auto oldsize = quadmeshing.Size();\n\n      if ( oldsize<domnr )\n        {\n          quadmeshing.SetSize(domnr);\n          for(auto dom : IntRange(oldsize, domnr-1))\n              quadmeshing[dom] = false;\n        }\n\n      quadmeshing[domnr-1] = quad_meshing;\n    }\n\n    bool GetDomainTensorMeshing ( int domnr ) \n    { \n      if ( tensormeshing.Size()>=domnr ) return tensormeshing[domnr-1];\n      else return false;\n    }\n    void SetDomainTensorMeshing ( int domnr, bool tm )\n    {\n      if ( tensormeshing.Size()<domnr )\n      {\n        auto oldsize = tensormeshing.Size();\n        tensormeshing.SetSize(domnr);\n        for(auto i : IntRange(oldsize, domnr-1))\n          tensormeshing[i] = false;\n      }\n      tensormeshing[domnr-1] = tm;\n    }\n    int GetDomainLayer ( int domnr ) \n    { \n      if ( layer.Size() ) return layer[domnr-1]; \n      else return 1;\n    }\n    void SetDomainLayer (int domnr, int layernr)\n    {\n      auto old_size = layer.Size();\n      if(domnr > old_size)\n        {\n          layer.SetSize(domnr);\n          for(size_t i = old_size; i < domnr; i++)\n            layer[i] = 1;\n        }\n      layer[domnr-1] = layernr;\n    }\n\n    string GetBCName (int bcnr) const;\n    void SetBCName (int bcnr, string name);\n    int GetBCNumber (string name) const; // 0 if not exists\n    int AddBCName (string name);\n\n    string * BCNamePtr ( const int bcnr );\n  };\n}\n\n\n\n\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/geom2d/python_geom2d.cpp",
    "content": "#ifdef NG_PYTHON\r\n\r\n#include \"../general/ngpython.hpp\"\r\n#include \"../core/python_ngcore.hpp\"\r\n#include \"../meshing/python_mesh.hpp\"\r\n\r\n#include \"../include/meshing.hpp\"\r\n#include \"../include/geometry2d.hpp\"\r\n#include \"csg2d.hpp\"\r\n\r\nusing namespace netgen;\r\nusing namespace pybind11::literals;\r\n\r\nnamespace netgen\r\n{\r\n  extern std::shared_ptr<NetgenGeometry> ng_geometry;\r\n}\r\n\r\n\r\nNGCORE_API_EXPORT void ExportGeom2d(py::module &m) \r\n{\r\n  py::class_<SplineSegExt, shared_ptr<SplineSegExt>>\r\n    (m, \"Spline\", \"Spline of a SplineGeometry object\")\r\n    .def_property(\"leftdom\", [] (SplineSegExt& self) { return self.leftdom; },\r\n                  [](SplineSegExt& self, int dom) { self.leftdom = dom; })\r\n    .def_property(\"rightdom\", [] (SplineSegExt& self) { return self.rightdom; },\r\n                  [](SplineSegExt& self, int dom) { self.rightdom = dom; })\r\n    .def_property_readonly(\"bc\", [] (SplineSegExt& self) { return self.bc; })\r\n    .def(\"GetNormal\", [](SplineSegExt& self, double t)\r\n                      {\r\n                        auto tang = self.GetTangent(t).Normalize();\r\n                        return Vec<2>(tang[1], -tang[0]);\r\n                      })\r\n    .def(\"StartPoint\", [](SplineSegExt& self) { return Point<2>(self.StartPI()); })\r\n    .def(\"EndPoint\", [](SplineSegExt& self) { return Point<2>(self.EndPI()); })\r\n    ;\r\n    \r\n  py::class_<SplineGeometry2d, NetgenGeometry, shared_ptr<SplineGeometry2d>>\r\n    (m, \"SplineGeometry\",\r\n     \"a 2d boundary representation geometry model by lines and splines\",\r\n     py::multiple_inheritance())\r\n    .def(py::init<>())\r\n    .def(py::init([](const string& filename)\r\n                  {\r\n                    auto geo = make_shared<SplineGeometry2d>();\r\n                    geo->Load(filename.c_str());\r\n                    ng_geometry = geo;\r\n                    return geo;\r\n                  }))\r\n    .def(NGSPickle<SplineGeometry2d>())\r\n    .def(\"Load\",&SplineGeometry2d::Load)\r\n    .def(\"SetDomainLayer\", &SplineGeometry2d::SetDomainLayer)\r\n    .def(\"AppendPoint\", FunctionPointer\r\n         ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref, string name)\r\n          {\r\n            Point<2> p;\r\n            p(0) = px;\r\n            p(1) = py;\r\n            GeomPoint<2> gp(p);\r\n            gp.hmax = maxh;\r\n            gp.hpref = hpref;\r\n            gp.name = name;\r\n            self.geompoints.Append(gp);\r\n            return self.geompoints.Size()-1;\r\n\t  }),\r\n         py::arg(\"x\"), py::arg(\"y\"), py::arg(\"maxh\") = 1e99, py::arg(\"hpref\")=0, py::arg(\"name\")=\"\")\r\n    .def(\"Append\", FunctionPointer([](SplineGeometry2d &self, py::list segment, int leftdomain, int rightdomain,\r\n                                      optional<variant<int, string>> bc, optional<int> copy, double maxh,\r\n                                      double hpref, double hprefleft, double hprefright)\r\n\t  {\r\n            SplineSegExt * seg;\r\n            if(py::isinstance<py::str>(segment[0]))\r\n              {\r\n                auto segtype = py::cast<std::string>(segment[0]);\r\n            \r\n                if (segtype == \"line\")\r\n                  {\r\n                    LineSeg<2> * l = new LineSeg<2>(self.GetPoint(py::cast<int>(segment[1])),\r\n                                                    self.GetPoint(py::cast<int>(segment[2])));\r\n                    seg = new SplineSegExt(*l);\r\n                  }\r\n                else if (segtype == \"spline3\")\r\n                  {\r\n                    SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(py::cast<int>(segment[1])),\r\n                                                             self.GetPoint(py::cast<int>(segment[2])),\r\n                                                             self.GetPoint(py::cast<int>(segment[3])));\r\n                    seg = new SplineSegExt(*seg3);\r\n                  }\r\n                else\r\n                  throw Exception(\"Appended segment is not a line or a spline3\");\r\n              }\r\n            else\r\n              {\r\n                if(py::len(segment) == 2)\r\n                  {\r\n                    auto l = new LineSeg<2>(self.GetPoint(py::cast<int>(segment[0])),\r\n                                            self.GetPoint(py::cast<int>(segment[1])));\r\n                    seg = new SplineSegExt(*l);\r\n                  }\r\n                else if(py::len(segment) == 3)\r\n                  {\r\n                    SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(py::cast<int>(segment[0])),\r\n                                                             self.GetPoint(py::cast<int>(segment[1])),\r\n                                                             self.GetPoint(py::cast<int>(segment[2])));\r\n                    seg = new SplineSegExt(*seg3);\r\n                  }\r\n                else\r\n                  throw Exception(\"Appended segment must either have 2 or 3 points\");\r\n              }\r\n            seg->leftdom = leftdomain;\r\n            seg->rightdom = rightdomain;\r\n            seg->hmax = maxh;\r\n            seg->hpref_left = max(hpref, hprefleft);\r\n            seg->hpref_right = max(hpref,hprefright);\r\n            seg->reffak = 1;\r\n            seg->copyfrom = -1;\r\n            if (copy.has_value())\r\n              seg->copyfrom = *copy+1;\r\n\r\n            if (bc.has_value())\r\n              {\r\n                if(auto intptr = get_if<int>(&*bc); intptr)\r\n                  seg->bc = *intptr;\r\n                else\r\n                  {\r\n                    auto bcname = get_if<string>(&*bc);\r\n                    seg->bc = self.GetNSplines() + 1;\r\n                    self.SetBCName(seg->bc, *bcname);\r\n                  }\r\n              }\r\n            else\r\n              seg->bc = self.GetNSplines()+1;\r\n            self.AppendSegment(seg);\r\n            return self.GetNSplines()-1;\r\n\t  }), py::arg(\"point_indices\"), py::arg(\"leftdomain\") = 1, py::arg(\"rightdomain\") = py::int_(0),\r\n         py::arg(\"bc\")=nullopt, py::arg(\"copy\")=nullopt, py::arg(\"maxh\")=1e99,\r\n         py::arg(\"hpref\")=0,py::arg(\"hprefleft\")=0,py::arg(\"hprefright\")=0)\r\n\r\n    \r\n    .def(\"AppendSegment\", FunctionPointer([](SplineGeometry2d &self, py::list point_indices, int leftdomain, int rightdomain)\r\n                                          {\r\n\t\t  int npts = py::len(point_indices);\r\n\t\t  SplineSegExt * seg;\r\n\t\t  //int a = py::extract<int>(point_indices[0]);\r\n\t\t  if (npts == 2)\r\n\t\t  {\r\n\t\t\t  LineSeg<2> * l = new LineSeg<2>(self.GetPoint(py::extract<int>(point_indices[0])()), self.GetPoint(py::extract<int>(point_indices[1])()));\r\n\t\t\t  seg = new SplineSegExt(*l);\r\n\t\t\t  \r\n\t\t  }\r\n\t\t  else if (npts == 3)\r\n\t\t  {\r\n\t\t\t  SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(py::extract<int>(point_indices[0])()), self.GetPoint(py::extract<int>(point_indices[1])()), self.GetPoint(py::extract<int>(point_indices[2])()));\r\n\t\t\t  seg = new SplineSegExt(*seg3);\r\n\r\n\t\t  }\r\n                  else\r\n                    throw Exception(\"Can only append segments with 2 or 3 points!\");\r\n\t\t  seg->leftdom = leftdomain;\r\n\t\t  seg->rightdom = rightdomain;\r\n\t\t  seg->hmax = 1e99;\r\n\t\t  seg->reffak = 1;\r\n\t\t  seg->copyfrom = -1;\r\n\t\t  self.AppendSegment(seg);\r\n                  }), py::arg(\"point_indices\"), py::arg(\"leftdomain\") = 1, py::arg(\"rightdomain\") = py::int_(0))\r\n\r\n\r\n    .def(\"AddCurve\", \r\n         [] (SplineGeometry2d & self, py::object func,\r\n                         int leftdomain, int rightdomain, py::object bc, double maxh)\r\n         {\r\n           int n = 1000;\r\n           NgArray<Point<2>> points;\r\n           for (int i = 0; i <= n; i++)\r\n             {\r\n               double t = double(i)/n;\r\n               py::tuple xy = func(t);\r\n               double x = py::cast<double>(xy[0]);\r\n               double y = py::cast<double>(xy[1]);\r\n               points.Append (Point<2>(x,y));\r\n             }\r\n           auto spline = new DiscretePointsSeg<2> (points);\r\n           SplineSegExt * spex = new SplineSegExt (*spline);\r\n           \r\n           spex -> leftdom = leftdomain;\r\n           spex -> rightdom = rightdomain;\r\n           spex->hmax = maxh;\r\n           spex->reffak = 1;\r\n           spex->copyfrom = -1;\r\n           \r\n           if (py::extract<int>(bc).check())\r\n             spex->bc = py::extract<int>(bc)();\r\n           else if (py::extract<string>(bc).check())\r\n             {\r\n               string bcname = py::extract<string>(bc)();\r\n               spex->bc = self.GetNSplines()+1;\r\n               self.SetBCName(spex->bc, bcname);\r\n             }\r\n           else\r\n             spex->bc = self.GetNSplines()+1;\r\n\r\n           \r\n           self.AppendSegment (spex);\r\n         }, py::arg(\"func\"), py::arg(\"leftdomain\") = 1, py::arg(\"rightdomain\") = py::int_(0),\r\n         py::arg(\"bc\")=NGDummyArgument(), py::arg(\"maxh\")=1e99,\r\n         \"Curve is given as parametrization on the interval [0,1]\")\r\n    \r\n    .def(\"SetMaterial\", &SplineGeometry2d::SetMaterial)\r\n    .def(\"SetDomainMaxH\", &SplineGeometry2d::SetDomainMaxh)\r\n\r\n    .def(\"GetBCName\", [](SplineGeometry2d& self, size_t index) { return self.GetBCName(index); })\r\n\r\n    .def(\"GetNDomains\", [](SplineGeometry2d& self) { return self.GetNDomains(); })\r\n\r\n    .def(\"GetNSplines\", [](SplineGeometry2d& self) { return self.splines.Size(); })\r\n    .def(\"GetSpline\", [](SplineGeometry2d& self, size_t index)\r\n                      { return shared_ptr<SplineSegExt>(&self.GetSpline(index), NOOP_Deleter); },\r\n         py::return_value_policy::reference_internal)\r\n    .def(\"GetNPoints\", [](SplineGeometry2d& self) { return self.GetNP(); })\r\n    .def(\"GetPoint\", [](SplineGeometry2d& self, size_t index) { return Point<2>(self.GetPoint(index)); })\r\n\r\n\t.def(\"PlotData\", FunctionPointer([](SplineGeometry2d &self)\r\n\t  {\r\n\t\t  Box<2> box(self.GetBoundingBox());\r\n\t\t  double xdist = box.PMax()(0) - box.PMin()(0);\r\n\t\t  double ydist = box.PMax()(1) - box.PMin()(1);\r\n\t\t  py::tuple xlim = py::make_tuple(box.PMin()(0) - 0.1*xdist, box.PMax()(0) + 0.1*xdist);\r\n\t\t  py::tuple ylim = py::make_tuple(box.PMin()(1) - 0.1*ydist, box.PMax()(1) + 0.1*ydist);\r\n\r\n\t\t  py::list xpoints, ypoints;\r\n\r\n\t\t  for (int i = 0; i < self.splines.Size(); i++)\r\n\t\t  {\r\n\t\t\t  py::list xp, yp;\r\n\t\t\t  if (self.splines[i]->GetType().compare(\"line\")==0)\r\n\t\t\t  {\r\n\t\t\t\t  GeomPoint<2> p1 = self.splines[i]->StartPI();\r\n\t\t\t\t  GeomPoint<2> p2 = self.splines[i]->EndPI();\r\n\t\t\t\t  xp.append(py::cast(p1(0)));\r\n\t\t\t\t  xp.append(py::cast(p2(0)));\r\n\t\t\t\t  yp.append(py::cast(p1(1)));\r\n\t\t\t\t  yp.append(py::cast(p2(1)));\r\n\t\t\t  }\r\n\t\t\t  else if (self.splines[i]->GetType().compare(\"spline3\")==0)\r\n\t\t\t  {\r\n\t\t\t\t  double len = self.splines[i]->Length();\r\n\t\t\t\t  int n = floor(len/(0.05*min(xdist,ydist)));\r\n\t\t\t\t  \r\n\t\t\t\t  for (int j = 0; j <= n; j++)\r\n\t\t\t\t  {\r\n\t\t\t\t\t  GeomPoint<2> point = self.splines[i]->GetPoint(j*1./n);\r\n\t\t\t\t\t  xp.append(py::cast(point(0)));\r\n\t\t\t\t\t  yp.append(py::cast(point(1)));\r\n\t\t\t\t  }\r\n\t\t\t  }\r\n\t\t\t  else\r\n\t\t\t  {\r\n\t\t\t\t  cout << \"spline is neither line nor spline3\" << endl;\r\n\t\t\t  }\r\n\t\t\t  xpoints.append(xp);\r\n\t\t\t  ypoints.append(yp);\r\n\t\t\t\t  \r\n\t\t  }\r\n\t\t  return py::tuple(py::make_tuple(xlim, ylim, xpoints, ypoints));\r\n\r\n\t  }))\r\n    .def(\"_visualizationData\", [](SplineGeometry2d &self)\r\n         {\r\n           Box<2> box(self.GetBoundingBox());\r\n           double xdist = box.PMax()(0) - box.PMin()(0);\r\n           double ydist = box.PMax()(1) - box.PMin()(1);\r\n           py::dict data;\r\n           py::dict segment_data;\r\n           auto min_val = py::make_tuple(box.PMin()(0), box.PMin()(1),0);\r\n           auto max_val = py::make_tuple(box.PMax()(1),box.PMax()(1),0);\r\n           py::list vertices;\r\n           py::list domains;\r\n           py::list segment_points;\r\n           py::list segment_normals;\r\n           py::list leftdom;\r\n           py::list rightdom;\r\n           int max_bcnr = 0;\r\n           for(int i = 0; i < self.splines.Size(); i++)\r\n             {\r\n               std::vector<netgen::GeomPoint<2>> lst;\r\n               if (self.splines[i]->GetType().compare(\"line\") == 0)\r\n                 lst = { self.splines[i]->StartPI(), self.splines[i]->EndPI() };\r\n               else if(self.splines[i]->GetType().compare(\"spline3\") == 0)\r\n                 {\r\n                   double len = self.splines[i]->Length();\r\n                   int n = floor(len/(0.05*min(xdist,ydist)));\r\n                   n = max(3, n);\r\n                   lst.push_back(self.splines[i]->StartPI());\r\n                   for (int j = 1; j < n; j++){\r\n                     lst.push_back(self.splines[i]->GetPoint(j*1./n));\r\n                     lst.push_back(self.splines[i]->GetPoint(j*1./n));\r\n                   }\r\n                   lst.push_back(self.splines[i]->EndPI());\r\n                   }\r\n               else\r\n                 {\r\n                   throw NgException(\"Spline is neither line nor spline3\");\r\n                 }\r\n               for (auto point : lst)\r\n                 {\r\n                   for(auto val : {point(0), point(1), 0.})\r\n                      vertices.append(val);\r\n                    int bcnr = self.GetSpline(i).bc;\r\n                    max_bcnr = max2(max_bcnr, bcnr);\r\n                    domains.append(bcnr);\r\n                    domains.append(self.GetSpline(i).leftdom);\r\n                    domains.append(self.GetSpline(i).rightdom);\r\n                 }\r\n\r\n               // segment data\r\n               auto pnt = self.splines[i]->GetPoint(0.5);\r\n               segment_points.append(py::make_tuple(pnt(0),pnt(1)));\r\n               auto normal = self.GetSpline(i).GetTangent(0.5);\r\n               std::swap(normal(0),normal(1));\r\n               normal(1) *= -1;\r\n               normal *= 1./sqrt(normal(0) * normal(0) + normal(1)*normal(1));\r\n               segment_normals.append(py::make_tuple(normal(0),normal(1)));\r\n               leftdom.append(self.GetSpline(i).leftdom);\r\n               rightdom.append(self.GetSpline(i).rightdom);\r\n             }\r\n           py::list bcnames;\r\n           for (int i = 1; i<max_bcnr + 1; i++)\r\n             bcnames.append(self.GetBCName(i));\r\n           segment_data[\"midpoints\"] = segment_points;\r\n           segment_data[\"normals\"] = segment_normals;\r\n           segment_data[\"leftdom\"] = leftdom;\r\n           segment_data[\"rightdom\"] = rightdom;\r\n           data[\"segment_data\"] = segment_data;\r\n           data[\"vertices\"] = vertices;\r\n           data[\"domains\"] = domains;\r\n           data[\"min\"] = min_val;\r\n           data[\"max\"] = max_val;\r\n           data[\"bcnames\"] = bcnames;\r\n           return data;\r\n         })\r\n\t.def(\"PointData\", FunctionPointer([](SplineGeometry2d &self)\r\n\t  {\r\n\t\t  py::list xpoints, ypoints, pointindex;\r\n\t\t  \r\n\t\t  for (int i = 0; i < self.geompoints.Size(); i++)\r\n\t\t  {\r\n\t\t\t  pointindex.append(py::cast(i));\r\n\t\t\t  xpoints.append(py::cast(self.geompoints[i][0]));\r\n\t\t\t  ypoints.append(py::cast(self.geompoints[i][1]));\r\n\t\t  }\r\n\t\t  return py::tuple(py::make_tuple(xpoints, ypoints, pointindex));\r\n\t\t  \r\n\t  }))\r\n\t.def(\"SegmentData\", FunctionPointer([](SplineGeometry2d &self)\r\n\t  {\r\n\t\t  py::list leftpoints, rightpoints, leftdom, rightdom;\r\n\r\n\t\t  for (int i = 0; i < self.splines.Size(); i++)\r\n\t\t  {\r\n\t\t\t  GeomPoint<2> point = self.splines[i]->GetPoint(0.5);\r\n\t\t\t  Vec<2> normal = self.GetSpline(i).GetTangent(0.5);\r\n\t\t\t  double temp = normal(0);\r\n\t\t\t  normal(0) = normal(1);\r\n\t\t\t  normal(1) = -temp;\r\n\r\n\t\t\t  leftdom.append(py::cast(self.GetSpline(i).leftdom));\r\n\t\t\t  rightdom.append(py::cast(self.GetSpline(i).rightdom));\r\n\r\n\t\t\t  rightpoints.append(py::make_tuple(point(0), point(1), normal(0)<0, normal(1)<0));\r\n\t\t\t  leftpoints.append(py::make_tuple(point(0), point(1), normal(0)<0, normal(1)<0));\r\n\t\t  }\r\n\t\t  return py::tuple(py::make_tuple(leftpoints, rightpoints, leftdom, rightdom));\r\n\r\n\t  }))\r\n\t.def(\"Print\", FunctionPointer([](SplineGeometry2d &self)\r\n\t  {\r\n\t\t  for (int i = 0; i < self.geompoints.Size(); i++)\r\n\t\t  {\r\n\t\t\t  cout << i << \" : \" << self.geompoints[i][0] << \" , \" << self.geompoints[i][1] << endl;\r\n\t\t  }\r\n\t\t  //Box<2> box(self.GetBoundingBox());\r\n\t\t  //cout << box.PMin() << endl;\r\n\t\t  //cout << box.PMax() << endl;\r\n\t\t  cout << self.splines.Size() << endl;\r\n\t\t  for (int i = 0; i < self.splines.Size(); i++)\r\n\t\t  {\r\n\t\t\t  cout << self.splines[i]->GetType() << endl;\r\n\t\t\t  //cout << i << \" : \" << self.splines[i]->GetPoint(0.1) << \" , \" << self.splines[i]->GetPoint(0.5) << endl;\r\n\t\t  }\r\n\t  }))\r\n    .def(\"Draw\", FunctionPointer\r\n         ([] (shared_ptr<SplineGeometry2d> self)\r\n          {\r\n             ng_geometry = self;\r\n             py::module::import(\"netgen\").attr(\"Redraw\")();\r\n          })\r\n         )\r\n    \r\n    .def(\"GenerateMesh\", [](shared_ptr<SplineGeometry2d> self,\r\n                            optional<MeshingParameters> pars, py::kwargs kwargs)\r\n\t\t{\r\n                  MeshingParameters mp;\r\n                  if(pars) mp = *pars;\r\n                  CreateMPfromKwargs(mp, kwargs);\r\n                  py::gil_scoped_release gil_release;\r\n\t\t  auto mesh = make_shared<Mesh>();\r\n                  mesh->SetGeometry(self);\r\n                  SetGlobalMesh (mesh);\r\n                  ng_geometry = self;\r\n\t\t  auto result = self->GenerateMesh(mesh, mp);\r\n                  if(result != 0)\r\n                    throw Exception(\"Meshing failed!\");\r\n\t\t  return mesh;\r\n                }, py::arg(\"mp\") = nullopt,\r\n      meshingparameter_description.c_str())\r\n    .def(\"_SetDomainTensorMeshing\", &SplineGeometry2d::SetDomainTensorMeshing)\r\n    ;\r\n  \r\n  py::class_<Solid2d>(m, \"Solid2d\")\r\n    .def(py::init<>())\r\n    .def(py::init<Array<std::variant<Point<2>, EdgeInfo, PointInfo>>, std::string, std::string>(), py::arg(\"points\"), py::arg(\"mat\")=MAT_DEFAULT, py::arg(\"bc\")=BC_DEFAULT)\r\n\r\n    .def(py::self+py::self)\r\n    .def(py::self-py::self)\r\n    .def(py::self*py::self)\r\n    .def(py::self+=py::self)\r\n    // .def(py::self-=py::self) // false clange warning, see  https://github.com/pybind/pybind11/issues/1893\r\n    .def(\"__isub__\", [](Solid2d& lhs, const Solid2d& rhs) { return lhs -= rhs; }, py::is_operator())\r\n    .def(py::self*=py::self)\r\n\r\n    .def(\"Mat\", &Solid2d::Mat)\r\n    .def(\"BC\", &Solid2d::BC)\r\n    .def(\"Maxh\", &Solid2d::Maxh)\r\n    .def(\"Layer\", &Solid2d::Layer)\r\n\r\n    .def(\"Copy\", [](Solid2d & self) -> Solid2d { return self; })\r\n    .def(\"Move\", &Solid2d::Move)\r\n    .def(\"Scale\", static_cast<Solid2d& (Solid2d::*)(double)>(&Solid2d::Scale))\r\n    .def(\"Scale\", static_cast<Solid2d& (Solid2d::*)(Vec<2>)>(&Solid2d::Scale))\r\n    .def(\"Rotate\", &Solid2d::RotateDeg, py::arg(\"angle\"), py::arg(\"center\")=Point<2>{0,0})\r\n    ;\r\n  \r\n\r\n  m.def(\"Rectangle\", [](Point<2> p0, Point<2> p1, string mat, string bc, optional<string> bottom, optional<string> right, optional<string> top, optional<string> left) -> Solid2d\r\n\t\t  {\r\n                      using P = Point<2>;\r\n                      return { {\r\n                              p0,    EdgeInfo{bottom ? *bottom : bc},\r\n                              P{p1[0],p0[1]}, EdgeInfo {right  ? *right  : bc},\r\n                              p1,             EdgeInfo {top    ? *top    : bc},\r\n                              P{p0[0],p1[1]}, EdgeInfo {left   ? *left   : bc},\r\n                             }, mat};\r\n                  },\r\n\t\t  \"pmin\"_a, \"pmax\"_a, \"mat\"_a=MAT_DEFAULT, \"bc\"_a=BC_DEFAULT,\r\n                  \"bottom\"_a=nullopt, \"right\"_a=nullopt, \"top\"_a=nullopt, \"left\"_a=nullopt\r\n       );\r\n  m.def(\"Circle\", Circle, py::arg(\"center\"), py::arg(\"radius\"), py::arg(\"mat\")=MAT_DEFAULT, py::arg(\"bc\")=BC_DEFAULT);\r\n\r\n  py::class_<CSG2d>(m, \"CSG2d\")\r\n    .def(py::init<>())\r\n    .def(\"GenerateSplineGeometry\", &CSG2d::GenerateSplineGeometry)\r\n    .def(\"Add\", &CSG2d::Add)\r\n    .def(\"GenerateMesh\", [](CSG2d & self, optional<MeshingParameters> pars, py::kwargs kwargs)\r\n\t\t{\r\n                  MeshingParameters mp;\r\n                  if(pars) mp = *pars;\r\n                    CreateMPfromKwargs(mp, kwargs);\r\n                  py::gil_scoped_release gil_release;\r\n\t\t  auto mesh = make_shared<Mesh>();\r\n                  auto geo = self.GenerateSplineGeometry();\r\n                  mesh->SetGeometry(geo);\r\n                  SetGlobalMesh (mesh);\r\n                  ng_geometry = geo;\r\n\t\t  auto result = geo->GenerateMesh(mesh, mp);\r\n                  if(result != 0)\r\n                    throw Exception(\"Meshing failed!\");\r\n\t\t  return mesh;\r\n                }, py::arg(\"mp\") = nullopt,\r\n      meshingparameter_description.c_str())\r\n    ;\r\n\r\n  py::class_<EdgeInfo>(m, \"EdgeInfo\")\r\n    .def(py::init<>())\r\n    .def(py::init<const Point<2>&>(), py::arg(\"control_point\"))\r\n    .def(py::init<double>(), py::arg(\"maxh\"))\r\n    .def(py::init<string>(), py::arg(\"bc\"))\r\n    .def(py::init<optional<Point<2>>, double, string>(), py::arg(\"control_point\")=nullopt, py::arg(\"maxh\")=MAXH_DEFAULT, py::arg(\"bc\")=BC_DEFAULT)\r\n    ;\r\n  py::class_<PointInfo>(m, \"PointInfo\")\r\n    .def(py::init<>())\r\n    .def(py::init<double>(), \"maxh\"_a)\r\n    .def(py::init<string>(), \"name\"_a)\r\n    .def(py::init<double, string>(), \"maxh\"_a, \"name\"_a)\r\n    ;\r\n}\r\n\r\nPYBIND11_MODULE(libgeom2d, m) {\r\n  ExportGeom2d(m);\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "libsrc/geom2d/spline2d.hpp",
    "content": "\n\n\n\ndas File sollte nicht mehr verwendet werden ---> spline.hpp\n\n\n\n\n\n\n\n#ifndef FILE_SPLINE2D\n#define FILE_SPLINE2D\n\n/**************************************************************************/\n/* File:   spline2d.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   24. Jul. 96                                                    */\n/**************************************************************************/\n\n\n/*\n  Spline curves for 2D mesh generation\n  */\n\n#include \"spline.hpp\"\n\n\n//#define OLDSPLINEVERSION\n#ifdef OLDSPLINEVERSION\n\n/// Geometry point\nclass GeomPoint2d : public Point<2>\n{\npublic:\n  /// refinement to point\n  double refatpoint;\n  bool hpref;\n\n  GeomPoint2d ()\n  { ; }\n\n  ///\n  GeomPoint2d (double ax, double ay, double aref = 1)\n    : Point<2> (ax, ay), refatpoint(aref) { ; }\n};\n\n\n\n/// base class for 2d - segment\nclass SplineSegment\n{\npublic:\n  /// left domain\n  int leftdom;\n  /// right domain\n  int rightdom;\n  /// refinement at line\n  double reffak;\n  /// boundary condition number\n  int bc;\n  /// copy spline mesh from other spline (-1.. do not copy)\n  int copyfrom;\n  /// perform anisotropic refinement (hp-refinement) to edge\n  bool hpref_left;\n  bool hpref_right;\n  /// calculates length of curve\n  virtual double Length () const;\n  /// returns point at curve, 0 <= t <= 1\n  virtual Point<2> GetPoint (double t) const = 0;\n  /// partitionizes curve\n  void Partition (double h, double elto0,\n\t\t  Mesh & mesh, Point3dTree & searchtree, int segnr) const;\n  /// returns initial point on curve\n  virtual const GeomPoint2d & StartPI () const = 0;\n  /// returns terminal point on curve\n  virtual const GeomPoint2d & EndPI () const = 0;\n  /** writes curve description for fepp:\n    for implicitly given quadratic curves, the 6 coefficients of\n    the polynomial\n    $$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$\n    are written to ost */\n  void PrintCoeff (ostream & ost) const;\n\n  virtual void GetCoeff (Vector & coeffs) const = 0;\n\n  virtual void GetPoints (int n, NgArray<Point<2> > & points);\n\n  /** calculates lineintersections:\n      for lines $$ a x + b y + c = 0 $$ the intersecting points are calculated\n      and stored in points */\n  virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t  NgArray < Point<2> > & points, const double eps) const\n  {points.SetSize(0);}\n\n  virtual double MaxCurvature(void) const = 0;\n\n  virtual string GetType(void) const {return \"splinebase\";}\n};\n\n\n/// Straight line form p1 to p2\nclass LineSegment : public SplineSegment\n{\n  ///\n  const GeomPoint2d &p1, &p2;\npublic:\n  ///\n  LineSegment (const GeomPoint2d & ap1, const GeomPoint2d & ap2);\n  ///\n  virtual double Length () const;\n  ///\n  virtual Point<2> GetPoint (double t) const;\n  ///\n  virtual const GeomPoint2d & StartPI () const { return p1; };\n  ///\n  virtual const GeomPoint2d & EndPI () const { return p2; }\n  ///\n  //virtual void PrintCoeff (ostream & ost) const;\n  virtual void GetCoeff (Vector & coeffs) const;\n\n  virtual string GetType(void) const {return \"line\";}\n\n  virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t  NgArray < Point<2> > & points, const double eps) const;\n\n  virtual double MaxCurvature(void) const {return 0;}\n};\n\n\n/// curve given by a rational, quadratic spline (including ellipses)\nclass SplineSegment3 : public SplineSegment\n{\n  ///\n  const GeomPoint2d &p1, &p2, &p3;\npublic:\n  ///\n  SplineSegment3 (const GeomPoint2d & ap1, \n\t\t  const GeomPoint2d & ap2, \n\t\t  const GeomPoint2d & ap3);\n  ///\n  virtual Point<2> GetPoint (double t) const;\n  ///\n  virtual const GeomPoint2d & StartPI () const { return p1; };\n  ///\n  virtual const GeomPoint2d & EndPI () const { return p3; }\n  ///\n  //virtual void PrintCoeff (ostream & ost) const;\n  virtual void GetCoeff (Vector & coeffs) const;\n\n  virtual string GetType(void) const {return \"spline3\";}\n\n  const GeomPoint2d & TangentPoint (void) const { return p2; }\n\n  virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t  NgArray < Point<2> > & points, const double eps) const;\n\n  virtual double MaxCurvature(void) const;\n};\n\n\n// Gundolf Haase  8/26/97\n/// A circle\nclass CircleSegment : public SplineSegment\n{\n  ///\nprivate:\n  const GeomPoint2d\t&p1, &p2, &p3;\n  Point<2>\t\tpm;\n  double\t\tradius, w1,w3;\npublic:\n  ///\n  CircleSegment (const GeomPoint2d & ap1, \n\t\t const GeomPoint2d & ap2, \n\t\t const GeomPoint2d & ap3);\n  ///\n  virtual Point<2> GetPoint (double t) const;\n  ///\n  virtual const GeomPoint2d & StartPI () const { return p1; }\n  ///\n  virtual const GeomPoint2d & EndPI () const { return p3; }\n  ///\n  //virtual void PrintCoeff (ostream & ost) const;\n  virtual void GetCoeff (Vector & coeffs) const;\n  ///\n  double Radius() const { return radius; }\n  ///\n  double StartAngle() const { return w1; }\n  ///\n  double EndAngle() const { return w3; }\n  ///\n  const Point<2> & MidPoint(void) const {return pm; }\n\n  virtual string GetType(void) const {return \"circle\";}\n\n  virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t  NgArray < Point<2> > & points, const double eps) const;\n\n  virtual double MaxCurvature(void) const {return 1./radius;}\n};\n\n\n\n\n\n\n/// \nclass DiscretePointsSegment : public SplineSegment\n{\n  NgArray<Point<2> > pts;\n  GeomPoint2d p1, p2;\npublic:\n  ///\n  DiscretePointsSegment (const NgArray<Point<2> > & apts);\n  ///\n  virtual ~DiscretePointsSegment ();\n  ///\n  virtual Point<2> GetPoint (double t) const;\n  ///\n  virtual const GeomPoint2d & StartPI () const { return p1; };\n  ///\n  virtual const GeomPoint2d & EndPI () const { return p2; }\n  ///\n  //virtual void PrintCoeff (ostream & /* ost */) const { ; }\n  virtual void GetCoeff (Vector & coeffs) const {;}\n\n  virtual double MaxCurvature(void) const {return 1;}\n};\n\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libsrc/geom2d/vsgeom2d.cpp",
    "content": "#include <meshing.hpp>\n#include <geometry2d.hpp>\n#include <visual.hpp>\n\n#include \"vsgeom2d.hpp\"\n\nnamespace netgen\n{\n\n\n  /* *********************** Draw 2D Geometry **************** */\n\n\n  VisualSceneGeometry2d :: VisualSceneGeometry2d ()\n    : VisualScene()\n  {\n    ;\n  }\n\n  VisualSceneGeometry2d :: ~VisualSceneGeometry2d ()\n  {\n    ;\n  }\n\n\n\n  void VisualSceneGeometry2d :: DrawScene ()\n  {\n    if (changeval != geometry2d->GetSplines().Size())\n      BuildScene();\n    changeval = geometry2d->GetSplines().Size();\n\n  \n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    SetLight();\n\n    //  glEnable (GL_LIGHT0);\n    glDisable (GL_LIGHTING);\n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n    //  SetClippingPlane ();\n\n    glShadeModel (GL_SMOOTH);\n    glEnable (GL_COLOR_MATERIAL);\n    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n  \n    //  float mat_col[] = { 0, 0, 1, 1 };\n    //  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n    glColor3f (0, 0, 1);\n  \n\n    NgArray<Point<2> > points, otherpoints;\n\n    for (int i = 1; i <= geometry2d->GetSplines().Size(); i++)\n      {\n\tgeometry2d->GetSplines().Get(i)->GetPoints (200, points);\n      \n\tglBegin (GL_LINE_STRIP);\n\tfor (int j = 0; j < points.Size(); j++)\n\t  glVertex3d (points[j](0), points[j](1), 0);\n\tglEnd(); \n      } \n\n    glColor3f (1, 0, 0);\n\n    for (int i = 1; i <= geometry2d->GetSplines().Size(); i++)\n      {\n\tint other = geometry2d->GetSpline(i-1).copyfrom;\n\tif (other != -1)\n\t  {\n\t    geometry2d->GetSplines().Get(i)->GetPoints (6, points);\n\t    geometry2d->GetSplines().Get(other)->GetPoints (6, otherpoints);\n\t    glBegin (GL_LINES);\n\t    for (int j = 1; j < 5; j++)\n\t      {\n\t\tglVertex3d (points[j](0), points[j](1), 0);\n\t\tglVertex3d (otherpoints[j](0), otherpoints[j](1), 0);\n\t      }\n\t    glEnd ();\n\t  }\n      }\n\n\n\n    glPopMatrix();\n  \n    DrawCoordinateCross ();\n    DrawNetgenLogo ();\n\n    glFinish();  \n  }\n\n\n  void VisualSceneGeometry2d :: BuildScene (int zoomall)\n  {\n    Box<2> bbox;\n\n    geometry2d->GetBoundingBox (bbox);\n  \n    Point<2> c = Center (bbox.PMin(), bbox.PMax());\n\n    center = Point3d (c(0), c(1), 0);\n    rad = Dist (bbox.PMin(), bbox.PMax()) / 2;\n\n    CalcTransformationMatrices();\n  }\n}\n"
  },
  {
    "path": "libsrc/geom2d/vsgeom2d.hpp",
    "content": "#ifndef FILE_VSGEOM2D\n#define FILE_VSGEOM2D\n\n/**************************************************************************/\n/* File:   vsgeom2d.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   05. Jan. 2011                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  class NGGUI_API VisualSceneGeometry2d : public VisualScene\n  {\n    const class SplineGeometry2d * geometry2d;\n  public:\n    VisualSceneGeometry2d ();\n    virtual ~VisualSceneGeometry2d ();\n    void SetGeometry (const class SplineGeometry2d * ageometry2d) { geometry2d = ageometry2d; }\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n  };\n\n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n    adtree.cpp\n    geom2d.cpp\n    geom3d.cpp\n    geomfuncs.cpp\n    geomtest3d.cpp\n    spline.cpp\n    splinegeometry.cpp\n    transform3d.cpp\n)\n\ninstall(FILES\n  adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp\n  geomobjects.hpp geomops.hpp geomtest3d.hpp gprim.hpp\n  splinegeometry.hpp spline.hpp transform3d.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/gprim COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/gprim/adtree.cpp",
    "content": "#include <mystdlib.h>\n\n\n#include <myadt.hpp>\n// class DenseMatrix;\n#include <gprim.hpp>\n\nnamespace netgen\n{\n\n\n  /* ******************************* ADTree ******************************* */\n\n\n  ADTreeNode :: ADTreeNode(int adim)\n  {\n    pi = -1;\n\n    left = NULL;\n    right = NULL;\n    father = NULL;\n    nchilds = 0;\n    dim = adim;\n    data = new float [dim];\n    boxmin = NULL;\n    boxmax = NULL;\n  }\n\n\n\n\n  ADTreeNode :: ~ADTreeNode()\n  {\n    delete data;\n  }\n\n\n  ADTree :: ADTree (int adim, const float * acmin, \n\t\t    const float * acmax)\n    : ela(0), stack(1000), stackdir(1000)\n  {\n    dim = adim;\n    cmin = new float [dim];\n    cmax = new float [dim];\n    memcpy (cmin, acmin, dim * sizeof(float));\n    memcpy (cmax, acmax, dim * sizeof(float));\n\n    root = new ADTreeNode (dim);\n    root->sep = (cmin[0] + cmax[0]) / 2;\n    root->boxmin = new float [dim];\n    root->boxmax = new float [dim];\n    memcpy (root->boxmin, cmin, dim * sizeof(float));\n    memcpy (root->boxmax, cmax, dim * sizeof(float));\n  }\n\n  ADTree :: ~ADTree ()\n  {\n    ;\n  }\n\n  void ADTree :: Insert (const float * p, int pi)\n  {\n    ADTreeNode *node(NULL);\n    ADTreeNode *next;\n    int dir;\n    int lr(1);\n\n    float * bmin = new float [dim];\n    float * bmax = new float [dim];\n  \n    memcpy (bmin, cmin, dim * sizeof(float));\n    memcpy (bmax, cmax, dim * sizeof(float));\n\n\n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tif (node->pi == -1)\n\t  {    \n\t    memcpy (node->data, p, dim * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi+1)\n\t      ela.SetSize (pi+1);\n\t    ela[pi] = node;\n\n\t    return;\n\t  }\n\n\tif (node->sep > p[dir])\n\t  {\n\t    next = node->left;\n\t    bmax[dir] = node->sep;\n\t    lr = 0;\n\t  }\n\telse\n\t  {\n\t    next = node->right;\n\t    bmin[dir] = node->sep;\n\t    lr = 1;\n\t  }\n\n\tdir++;\n\tif (dir == dim)\n\t  dir = 0;\n      }\n\n\n    next = new ADTreeNode(dim);\n    memcpy (next->data, p, dim * sizeof(float));\n    next->pi = pi;\n    next->sep = (bmin[dir] + bmax[dir]) / 2;\n    next->boxmin = bmin;\n    next->boxmax = bmax;\n\n    if (ela.Size() < pi+1)\n      ela.SetSize (pi+1);\n    ela[pi] = next;\n\n\n    if (lr)\n      node->right = next;\n    else\n      node->left = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree :: DeleteElement (int pi)\n  {\n    ADTreeNode * node = ela[pi];\n\n    node->pi = -1;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n\n  void ADTree :: SetCriterion (ADTreeCriterion & acriterion)\n  {\n    criterion = & acriterion;\n  }\n\n\n  void ADTree :: Reset ()\n  {\n    stack.Elem(1) = root;\n    stackdir.Elem(1) = 0;\n    stackindex = 1;\n  }\n\n\n  int ADTree:: Next ()\n  {\n    ADTreeNode *node;\n    int dir;\n\n    if (stackindex == 0)\n      return -1;\n\n    do \n      {\n\tnode = stack.Get(stackindex);\n\tdir = stackdir.Get(stackindex);\n\tstackindex --;\n\n\tif (criterion -> Eval(node))\n\t  {\n\t    int ndir = dir + 1;\n\t    if (ndir == dim)\n\t      ndir = 0;\n\n\t    if (node -> left && criterion -> Eval (node->left))\n\t      {\n\t\tstackindex ++;\n\t\tstack.Elem(stackindex) = node -> left;\n\t\tstackdir.Elem(stackindex) = ndir;\n\t      }\n\t    if (node->right && criterion -> Eval (node -> right))\n\t      {\n\t\tstackindex++;\n\t\tstack.Elem(stackindex) = node->right;\n\t\tstackdir.Elem(stackindex) = ndir;\n\t      }\n\t  \n\t    if (node -> pi != -1)\n\t      return node->pi;\n\t  }\n      }\n    while (stackindex > 0);\n\n    return -1;\n  }\n\n\n  void ADTree :: GetMatch (NgArray <int> & matches)\n  {\n    int nodenr;\n\n    Reset();\n\n    while ( (nodenr = Next()) != -1)\n      matches.Append (nodenr);\n  }\n\n\n  void ADTree :: PrintRec (ostream & ost, const ADTreeNode * node) const\n  {\n  \n    if (node->data)\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < dim; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    if (node->left)\n      {\n\tost << \"l \";\n\tPrintRec (ost, node->left);\n      }\n    if (node->right)\n      {\n\tost << \"r \";\n\tPrintRec (ost, node->right);\n      }\n  }\n\n\n  /* ******************************* ADTree3 ******************************* */\n\n\n  ADTreeNode3 :: ADTreeNode3()\n  {\n    pi = -1;\n\n    left = NULL;\n    right = NULL;\n    father = NULL;\n    nchilds = 0;\n  }\n\n  void ADTreeNode3 :: DeleteChilds ()\n  {\n    if (left)\n      {\n\tleft->DeleteChilds();\n\tdelete left;\n\tleft = NULL;\n      }\n    if (right)\n      {\n\tright->DeleteChilds();\n\tdelete right;\n\tright = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode3 :: ball(sizeof (ADTreeNode3));\n\n\n  void * ADTreeNode3 :: operator new(size_t s)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode3 :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree3 :: ADTree3 (const float * acmin, \n\t\t      const float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 3 * sizeof(float));\n    memcpy (cmax, acmax, 3 * sizeof(float));\n\n    root = new ADTreeNode3;\n    root->sep = (cmin[0] + cmax[0]) / 2;\n  }\n\n  ADTree3 :: ~ADTree3 ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree3 :: Insert (const float * p, int pi)\n  {\n    ADTreeNode3 *node(NULL);\n    ADTreeNode3 *next;\n    int dir;\n    int lr(0);\n\n    float bmin[3];\n    float bmax[3];\n  \n    memcpy (bmin, cmin, 3 * sizeof(float));\n    memcpy (bmax, cmax, 3 * sizeof(float));\n\n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tif (node->pi == -1)\n\t  {    \n\t    memcpy (node->data, p, 3 * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi+1)\n\t      ela.SetSize (pi+1);\n\t    ela[pi] = node;\n\n\t    return;\n\t  }\n\n\tif (node->sep > p[dir])\n\t  {\n\t    next = node->left;\n\t    bmax[dir] = node->sep;\n\t    lr = 0;\n\t  }\n\telse\n\t  {\n\t    next = node->right;\n\t    bmin[dir] = node->sep;\n\t    lr = 1;\n\t  }\n\n\tdir++;\n\tif (dir == 3)\n\t  dir = 0;\n      }\n\n\n    next = new ADTreeNode3;\n    memcpy (next->data, p, 3 * sizeof(float));\n    next->pi = pi;\n    next->sep = (bmin[dir] + bmax[dir]) / 2;\n\n\n    if (ela.Size() < pi+1)\n      ela.SetSize (pi+1);\n    ela[pi] = next;\t\t\n\n\n    if (lr)\n      node->right = next;\n    else\n      node->left = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3 :: DeleteElement (int pi)\n  {\n    ADTreeNode3 * node = ela[pi];\n\n    node->pi = -1;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3 :: GetIntersecting (const float * bmin, \n\t\t\t\t   const float * bmax,\n\t\t\t\t   NgArray<int> & pis) const\n  {\n    ArrayMem<ADTreeNode3*, 1000> stack(1000);\n    ArrayMem<int, 1000> stackdir(1000);\n    ADTreeNode3 * node;\n    int dir, stacks;\n\n    // stack.SetSize (1000);\n    // stackdir.SetSize(1000);\n    pis.SetSize(0);\n\n    stack[0] = root;\n    stackdir[0] = 0;\n    stacks = 0;\n\n    while (stacks >= 0)\n      {\n\tnode = stack[stacks];\n\tdir = stackdir[stacks]; \n\tstacks--;\n\n\tif (node->pi != -1)\n\t  {\n\t    if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] &&\n\t\tnode->data[1] >= bmin[1] && node->data[1] <= bmax[1] &&\n\t\tnode->data[2] >= bmin[2] && node->data[2] <= bmax[2])\n\n\t      pis.Append (node->pi);\n\t  }\n\n\n\tint ndir = dir+1;\n\tif (ndir == 3)\n\t  ndir = 0;\n\n\tif (node->left && bmin[dir] <= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks] = node->left;\n\t    stackdir[stacks] = ndir;\n\t  }\n\tif (node->right && bmax[dir] >= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks] = node->right;\n\t    stackdir[stacks] = ndir;\n\t  }\n      }\n  }\n\n  void ADTree3 :: PrintRec (ostream & ost, const ADTreeNode3 * node) const\n  {\n  \n    // if (node->data)  // true anyway\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < 3; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    if (node->left)\n      PrintRec (ost, node->left);\n    if (node->right)\n      PrintRec (ost, node->right);\n  }\n\n\n\n\n\n\n\n\n#ifdef ABC\n\n  /* ******************************* ADTree3Div ******************************* */\n\n\n  ADTreeNode3Div :: ADTreeNode3Div()\n  {\n    pi = 0;\n  \n    int i;\n    for (i = 0; i < ADTN_DIV; i++)\n      childs[i] = NULL;\n\n    father = NULL;\n    nchilds = 0;\n    minx = 0;\n    dist = 1;\n  }\n\n  void ADTreeNode3Div :: DeleteChilds ()\n  {\n    int i;\n    for (i = 0; i < ADTN_DIV; i++)\n      if (childs[i])\n\t{\n\t  childs[i]->DeleteChilds();\n\t  delete childs[i];\n\t  childs[i] = NULL;\n\t}\n  }\n\n\n  BlockAllocator ADTreeNode3Div :: ball(sizeof (ADTreeNode3Div));\n\n  void * ADTreeNode3Div :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode3Div :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree3Div :: ADTree3Div (const float * acmin, \n\t\t\t    const float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 3 * sizeof(float));\n    memcpy (cmax, acmax, 3 * sizeof(float));\n\n    root = new ADTreeNode3Div;\n\n    root->minx = cmin[0];\n    root->dist = (cmax[0] - cmin[0]) / ADTN_DIV;\n\n    //  root->sep = (cmin[0] + cmax[0]) / 2;\n  }\n\n  ADTree3Div :: ~ADTree3Div ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree3Div :: Insert (const float * p, int pi)\n  {\n    ADTreeNode3Div *node;\n    ADTreeNode3Div *next;\n    int dir;\n    int bag;\n  \n    float bmin[3];\n    float bmax[3];\n  \n    memcpy (bmin, cmin, 3 * sizeof(float));\n    memcpy (bmax, cmax, 3 * sizeof(float));\n\n\n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tif (!node->pi)\n\t  {    \n\t    memcpy (node->data, p, 3 * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi)\n\t      ela.SetSize (pi);\n\t    ela.Elem(pi) = node;\n\n\t    return;\n\t  }\n\n\tdouble dx = (bmax[dir] - bmin[dir]) / ADTN_DIV;\n\tbag = int ((p[dir]-bmin[dir]) / dx);\n\n\t//      (*testout) << \"insert, bag = \" << bag << endl;\n\n\tif (bag < 0) bag = 0;\n\tif (bag >= ADTN_DIV) bag = ADTN_DIV-1;\n      \n\tdouble nbmin = bmin[dir] + bag * dx;\n\tdouble nbmax = bmin[dir] + (bag+1) * dx;\n\n\t/*      \n\t\t(*testout) << \"bmin, max = \" << bmin[dir] << \"-\" << bmax[dir]\n\t\t<< \" p = \" << p[dir];\n\t*/\n\tnext = node->childs[bag];\n\tbmin[dir] = nbmin;\n\tbmax[dir] = nbmax;\n\n\t//      (*testout) << \"new bmin, max = \" << bmin[dir] << \"-\" << bmax[dir] << endl;\n\n      \n\t/*      \n\t\tif (node->sep > p[dir])\n\t\t{\n\t\tnext = node->left;\n\t\tbmax[dir] = node->sep;\n\t\tlr = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\tnext = node->right;\n\t\tbmin[dir] = node->sep;\n\t\tlr = 1;\n\t\t}\n\t*/\n\n\tdir++;\n\tif (dir == 3)\n\t  dir = 0;\n      }\n\n\n    next = new ADTreeNode3Div;\n    memcpy (next->data, p, 3 * sizeof(float));\n    next->pi = pi;\n\n    next->minx = bmin[dir];\n    next->dist = (bmax[dir] - bmin[dir]) / ADTN_DIV;\n    //  next->sep = (bmin[dir] + bmax[dir]) / 2;\n\n\n    if (ela.Size() < pi)\n      ela.SetSize (pi);\n    ela.Elem(pi) = next;\n\n    node->childs[bag] = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3Div :: DeleteElement (int pi)\n  {\n    ADTreeNode3Div * node = ela.Get(pi);\n\n    node->pi = 0;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3Div :: GetIntersecting (const float * bmin, \n\t\t\t\t      const float * bmax,\n\t\t\t\t      NgArray<int> & pis) const\n  {\n    static NgArray<ADTreeNode3Div*> stack(1000);\n    static NgArray<int> stackdir(1000);\n    ADTreeNode3Div * node;\n    int dir, i, stacks;\n\n    stack.SetSize (1000);\n    stackdir.SetSize(1000);\n    pis.SetSize(0);\n\n    stack.Elem(1) = root;\n    stackdir.Elem(1) = 0;\n    stacks = 1;\n\n    while (stacks)\n      {\n\tnode = stack.Get(stacks);\n\tdir = stackdir.Get(stacks); \n\tstacks--;\n\n\tif (node->pi)\n\t  {\n\t    if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] &&\n\t\tnode->data[1] >= bmin[1] && node->data[1] <= bmax[1] &&\n\t\tnode->data[2] >= bmin[2] && node->data[2] <= bmax[2])\n\n\t      pis.Append (node->pi);\n\t  }\n\n\n\tint ndir = dir+1;\n\tif (ndir == 3)\n\t  ndir = 0;\n\n\tint mini = int ( (bmin[dir] - node->minx) / node->dist );\n\tint maxi = int ( (bmax[dir] - node->minx) / node->dist );\n      \n\t//      (*testout) << \"get int, mini, maxi = \" << mini << \", \" << maxi << endl;\n\tif (mini < 0) mini = 0;\n\tif (maxi >= ADTN_DIV) maxi = ADTN_DIV-1;\n\n\tfor (i = mini; i <= maxi; i++)\n\t  if (node->childs[i])\n\t    {\n\t      stacks++;\n\t      stack.Elem(stacks) = node->childs[i];\n\t      stackdir.Elem(stacks) = ndir;\n\t    }\n\n\n\t/*\n\t  if (node->left && bmin[dir] <= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->left;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t  if (node->right && bmax[dir] >= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->right;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t*/\n      }\n  }\n\n  void ADTree3Div :: PrintRec (ostream & ost, const ADTreeNode3Div * node) const\n  {\n  \n    if (node->data)\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tost << \" from \" << node->minx << \" - \" << node->minx + node->dist*ADTN_DIV << \"  \";\n\tfor (int i = 0; i < 3; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    int i;\n    for (i = 0; i < ADTN_DIV; i++)\n      if (node->childs[i])\n\tPrintRec (ost, node->childs[i]);\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  /* ******************************* ADTree3M ******************************* */\n\n\n  ADTreeNode3M :: ADTreeNode3M()\n  {\n    int i;\n    for (i = 0; i < ADTN_SIZE; i++)\n      pi[i] = 0;\n\n    left = NULL;\n    right = NULL;\n    father = NULL;\n    nchilds = 0;\n  }\n\n  void ADTreeNode3M :: DeleteChilds ()\n  {\n    if (left)\n      {\n\tleft->DeleteChilds();\n\tdelete left;\n\tleft = NULL;\n      }\n    if (right)\n      {\n\tright->DeleteChilds();\n\tdelete right;\n\tright = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode3M :: ball(sizeof (ADTreeNode3M));\n\n  void * ADTreeNode3M :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode3M :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree3M :: ADTree3M (const float * acmin, \n\t\t\tconst float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 3 * sizeof(float));\n    memcpy (cmax, acmax, 3 * sizeof(float));\n\n    root = new ADTreeNode3M;\n    root->sep = (cmin[0] + cmax[0]) / 2;\n  }\n\n  ADTree3M :: ~ADTree3M ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree3M :: Insert (const float * p, int pi)\n  {\n    ADTreeNode3M *node;\n    ADTreeNode3M *next;\n    int dir;\n    int lr;\n    int i;\n    float bmin[3];\n    float bmax[3];\n  \n    memcpy (bmin, cmin, 3 * sizeof(float));\n    memcpy (bmax, cmax, 3 * sizeof(float));\n\n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tfor (i = 0; i < ADTN_SIZE; i++)\n\t  if (!node->pi[i])\n\t    {    \n\t      memcpy (node->data[i], p, 3 * sizeof(float));\n\t      node->pi[i] = pi;\n\t    \n\t      if (ela.Size() < pi)\n\t\tela.SetSize (pi);\n\t      ela.Elem(pi) = node;\n\t    \n\t      return;\n\t    }\n\n\tif (node->sep > p[dir])\n\t  {\n\t    next = node->left;\n\t    bmax[dir] = node->sep;\n\t    lr = 0;\n\t  }\n\telse\n\t  {\n\t    next = node->right;\n\t    bmin[dir] = node->sep;\n\t    lr = 1;\n\t  }\n\n\tdir++;\n\tif (dir == 3)\n\t  dir = 0;\n      }\n\n\n    next = new ADTreeNode3M;\n    memcpy (next->data[0], p, 3 * sizeof(float));\n    next->pi[0] = pi;\n    next->sep = (bmin[dir] + bmax[dir]) / 2;\n\n\n    if (ela.Size() < pi)\n      ela.SetSize (pi);\n    ela.Elem(pi) = next;\n\n\n    if (lr)\n      node->right = next;\n    else\n      node->left = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3M :: DeleteElement (int pi)\n  {\n    ADTreeNode3M * node = ela.Get(pi);\n\n    int i;\n    for (i = 0; i < ADTN_SIZE; i++)\n      if (node->pi[i] == pi)\n\tnode->pi[i] = 0;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3M :: GetIntersecting (const float * bmin, \n\t\t\t\t    const float * bmax,\n\t\t\t\t    NgArray<int> & pis) const\n  {\n    static NgArray<ADTreeNode3M*> stack(1000);\n    static NgArray<int> stackdir(1000);\n    ADTreeNode3M * node;\n    int dir, i, stacks;\n\n    stack.SetSize (1000);\n    stackdir.SetSize(1000);\n    pis.SetSize(0);\n\n    stack.Elem(1) = root;\n    stackdir.Elem(1) = 0;\n    stacks = 1;\n\n    while (stacks)\n      {\n\tnode = stack.Get(stacks);\n\tdir = stackdir.Get(stacks); \n\tstacks--;\n\n\tint * hpi = node->pi;\n\tfor (i = 0; i < ADTN_SIZE; i++)\n\t  if (hpi[i])\n\t    {\n\t      float * datai = &node->data[i][0];\n\t      if (datai[0] >= bmin[0] && datai[0] <= bmax[0] &&\n\t\t  datai[1] >= bmin[1] && datai[1] <= bmax[1] &&\n\t\t  datai[2] >= bmin[2] && datai[2] <= bmax[2])\n\t      \n\t\tpis.Append (node->pi[i]);\n\t    }\n\n\n\tint ndir = dir+1;\n\tif (ndir == 3)\n\t  ndir = 0;\n\n\tif (node->left && bmin[dir] <= node->sep)\n\t  {\n\t    stacks++;\n\t    stack.Elem(stacks) = node->left;\n\t    stackdir.Elem(stacks) = ndir;\n\t  }\n\tif (node->right && bmax[dir] >= node->sep)\n\t  {\n\t    stacks++;\n\t    stack.Elem(stacks) = node->right;\n\t    stackdir.Elem(stacks) = ndir;\n\t  }\n      }\n  }\n\n  void ADTree3M :: PrintRec (ostream & ost, const ADTreeNode3M * node) const\n  {\n  \n    if (node->data)\n      {\n\t//      ost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < 3; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    if (node->left)\n      PrintRec (ost, node->left);\n    if (node->right)\n      PrintRec (ost, node->right);\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  /* ******************************* ADTree3F ******************************* */\n\n\n  ADTreeNode3F :: ADTreeNode3F()\n  {\n    pi = 0;\n    father = NULL;\n    nchilds = 0;\n    int i;\n    for (i = 0; i < 8; i++)\n      childs[i] = NULL;\n  }\n\n  void ADTreeNode3F :: DeleteChilds ()\n  {\n    int i;\n\n    for (i = 0; i < 8; i++)\n      {\n\tif (childs[i])\n\t  childs[i]->DeleteChilds();\n\tdelete childs[i];\n\tchilds[i] = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode3F :: ball(sizeof (ADTreeNode3F));\n\n  void * ADTreeNode3F :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode3F :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree3F :: ADTree3F (const float * acmin, \n\t\t\tconst float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 3 * sizeof(float));\n    memcpy (cmax, acmax, 3 * sizeof(float));\n\n    root = new ADTreeNode3F;\n    for (int i = 0; i < 3; i++)\n      root->sep[i] = (cmin[i] + cmax[i]) / 2;\n  }\n\n  ADTree3F :: ~ADTree3F ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree3F :: Insert (const float * p, int pi)\n  {\n    ADTreeNode3F *node;\n    ADTreeNode3F *next;\n    int lr;\n\n    float bmin[3];\n    float bmax[3];\n    int i, dir;\n  \n    memcpy (bmin, cmin, 3 * sizeof(float));\n    memcpy (bmax, cmax, 3 * sizeof(float));\n\n\n    next = root;\n    while (next)\n      {\n\tnode = next;\n      \n\tif (!node->pi)\n\t  {    \n\t    memcpy (node->data, p, 3 * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi)\n\t      ela.SetSize (pi);\n\t    ela.Elem(pi) = node;\n\n\t    return;\n\t  }\n\n\tdir = 0;\n\tfor (i = 0; i < 3; i++)\n\t  {\n\t    if (node->sep[i] > p[i])\n\t      {\n\t\tbmax[i] = node->sep[i];\n\t      }\n\t    else\n\t      {\n\t\tbmin[i] = node->sep[i];\n\t\tdir += (1 << i);\n\t      }\n\t  }\n\tnext = node->childs[dir];\n\n\t/*\n\t  if (node->sep > p[dir])\n\t  {\n\t  next = node->left;\n\t  bmax[dir] = node->sep;\n\t  lr = 0;\n\t  }\n\t  else\n\t  {\n\t  next = node->right;\n\t  bmin[dir] = node->sep;\n\t  lr = 1;\n\t  }\n\t*/\n      }\n\n\n    next = new ADTreeNode3F;\n    memcpy (next->data, p, 3 * sizeof(float));\n    next->pi = pi;\n\n    for (i = 0; i < 3; i++)\n      next->sep[i] = (bmin[i] + bmax[i]) / 2;\n  \n\n    if (ela.Size() < pi)\n      ela.SetSize (pi);\n    ela.Elem(pi) = next;\n\n    node->childs[dir] = next;\n    next->father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3F :: DeleteElement (int pi)\n  {\n    ADTreeNode3F * node = ela.Get(pi);\n\n    node->pi = 0;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3F :: GetIntersecting (const float * bmin, \n\t\t\t\t    const float * bmax,\n\t\t\t\t    NgArray<int> & pis) const\n  {\n    static NgArray<ADTreeNode3F*> stack(1000);\n    ADTreeNode3F * node;\n    int dir, i, stacks;\n\n    stack.SetSize (1000);\n    pis.SetSize(0);\n\n    stack.Elem(1) = root;\n    stacks = 1;\n\n    while (stacks)\n      {\n\tnode = stack.Get(stacks);\n\tstacks--;\n\n\tif (node->pi)\n\t  {\n\t    if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] &&\n\t\tnode->data[1] >= bmin[1] && node->data[1] <= bmax[1] &&\n\t\tnode->data[2] >= bmin[2] && node->data[2] <= bmax[2])\n\n\t      pis.Append (node->pi);\n\t  }\n\n      \n\tint i1min = (bmin[0] <= node->sep[0]) ? 0 : 1;\n\tint i1max = (bmax[0] < node->sep[0]) ? 0 : 1;\n\tint i2min = (bmin[1] <= node->sep[1]) ? 0 : 1;\n\tint i2max = (bmax[1] < node->sep[1]) ? 0 : 1;\n\tint i3min = (bmin[2] <= node->sep[2]) ? 0 : 1;\n\tint i3max = (bmax[2] < node->sep[2]) ? 0 : 1;\n\n\tint i1, i2, i3;\n\tfor (i1 = i1min; i1 <= i1max; i1++)\n\t  for (i2 = i2min; i2 <= i2max; i2++)\n\t    for (i3 = i3min; i3 <= i3max; i3++)\n\t      {\n\t\ti = i1+2*i2+4*i3;\n\t\tif (node->childs[i])\n\t\t  {\n\t\t    stacks++;\n\t\t    stack.Elem(stacks) = node->childs[i];\n\t\t  }\n\t      }\n      \n\t/*\n\t  if (node->left && bmin[dir] <= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->left;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t  if (node->right && bmax[dir] >= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->right;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t*/\n      }\n  }\n\n  void ADTree3F :: PrintRec (ostream & ost, const ADTreeNode3F * node) const\n  {\n    int i;\n    if (node->data)\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (i = 0; i < 3; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n\n    for (i = 0; i < 8; i++)\n      if (node->childs[i])\n\tPrintRec (ost, node->childs[i]);\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n  /* ******************************* ADTree3FM ******************************* */\n\n\n  ADTreeNode3FM :: ADTreeNode3FM()\n  {\n    father = NULL;\n    nchilds = 0;\n    int i;\n\n    for (i = 0; i < ADTN_SIZE; i++)\n      pi[i] = 0;\n\n    for (i = 0; i < 8; i++)\n      childs[i] = NULL;\n  }\n\n  void ADTreeNode3FM :: DeleteChilds ()\n  {\n    int i;\n\n    for (i = 0; i < 8; i++)\n      {\n\tif (childs[i])\n\t  childs[i]->DeleteChilds();\n\tdelete childs[i];\n\tchilds[i] = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode3FM :: ball(sizeof (ADTreeNode3FM));\n\n  void * ADTreeNode3FM :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode3FM :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree3FM :: ADTree3FM (const float * acmin, \n\t\t\t  const float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 3 * sizeof(float));\n    memcpy (cmax, acmax, 3 * sizeof(float));\n\n    root = new ADTreeNode3FM;\n    for (int i = 0; i < 3; i++)\n      root->sep[i] = (cmin[i] + cmax[i]) / 2;\n  }\n\n  ADTree3FM :: ~ADTree3FM ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree3FM :: Insert (const float * p, int pi)\n  {\n    ADTreeNode3FM *node;\n    ADTreeNode3FM *next;\n    int lr;\n\n    float bmin[3];\n    float bmax[3];\n    int i, dir;\n  \n    memcpy (bmin, cmin, 3 * sizeof(float));\n    memcpy (bmax, cmax, 3 * sizeof(float));\n\n    next = root;\n    while (next)\n      {\n\tnode = next;\n      \n\tfor (i = 0; i < ADTN_SIZE; i++)\n\t  if (!node->pi[i])\n\t    {    \n\t      memcpy (node->data[i], p, 3 * sizeof(float));\n\t      node->pi[i] = pi;\n\t    \n\t      if (ela.Size() < pi)\n\t\tela.SetSize (pi);\n\t      ela.Elem(pi) = node;\n\t    \n\t      return;\n\t    }\n\n\tdir = 0;\n\tfor (i = 0; i < 3; i++)\n\t  {\n\t    if (node->sep[i] > p[i])\n\t      {\n\t\tbmax[i] = node->sep[i];\n\t      }\n\t    else\n\t      {\n\t\tbmin[i] = node->sep[i];\n\t\tdir += (1 << i);\n\t      }\n\t  }\n\tnext = node->childs[dir];\n\n\t/*\n\t  if (node->sep > p[dir])\n\t  {\n\t  next = node->left;\n\t  bmax[dir] = node->sep;\n\t  lr = 0;\n\t  }\n\t  else\n\t  {\n\t  next = node->right;\n\t  bmin[dir] = node->sep;\n\t  lr = 1;\n\t  }\n\t*/\n      }\n\n\n    next = new ADTreeNode3FM;\n    memcpy (next->data[0], p, 3 * sizeof(float));\n    next->pi[0] = pi;\n\n    for (i = 0; i < 3; i++)\n      next->sep[i] = (bmin[i] + bmax[i]) / 2;\n  \n\n    if (ela.Size() < pi)\n      ela.SetSize (pi);\n    ela.Elem(pi) = next;\n\n    node->childs[dir] = next;\n    next->father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3FM :: DeleteElement (int pi)\n  {\n    ADTreeNode3FM * node = ela.Get(pi);\n\n    int i;\n    for (i = 0; i < ADTN_SIZE; i++)\n      if (node->pi[i] == pi)\n\tnode->pi[i] = 0;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree3FM :: GetIntersecting (const float * bmin, \n\t\t\t\t     const float * bmax,\n\t\t\t\t     NgArray<int> & pis) const\n  {\n    static NgArray<ADTreeNode3FM*> stack(1000);\n    ADTreeNode3FM * node;\n    int dir, i, stacks;\n\n    stack.SetSize (1000);\n    pis.SetSize(0);\n\n    stack.Elem(1) = root;\n    stacks = 1;\n\n    while (stacks)\n      {\n\tnode = stack.Get(stacks);\n\tstacks--;\n\n\tint * hpi = node->pi;\n\tfor (i = 0; i < ADTN_SIZE; i++)\n\t  if (hpi[i])\n\t    {\n\t      float * datai = &node->data[i][0];\n\t      if (datai[0] >= bmin[0] && datai[0] <= bmax[0] &&\n\t\t  datai[1] >= bmin[1] && datai[1] <= bmax[1] &&\n\t\t  datai[2] >= bmin[2] && datai[2] <= bmax[2])\n\t      \n\t\tpis.Append (node->pi[i]);\n\t    }\n\n\t/*\n\t  if (node->pi)\n\t  {\n\t  if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] &&\n\t  node->data[1] >= bmin[1] && node->data[1] <= bmax[1] &&\n\t  node->data[2] >= bmin[2] && node->data[2] <= bmax[2])\n\n\t  pis.Append (node->pi);\n\t  }\n\t*/\n      \n\tint i1min = (bmin[0] <= node->sep[0]) ? 0 : 1;\n\tint i1max = (bmax[0] < node->sep[0]) ? 0 : 1;\n\tint i2min = (bmin[1] <= node->sep[1]) ? 0 : 1;\n\tint i2max = (bmax[1] < node->sep[1]) ? 0 : 1;\n\tint i3min = (bmin[2] <= node->sep[2]) ? 0 : 1;\n\tint i3max = (bmax[2] < node->sep[2]) ? 0 : 1;\n\n\tint i1, i2, i3;\n\tfor (i1 = i1min; i1 <= i1max; i1++)\n\t  for (i2 = i2min; i2 <= i2max; i2++)\n\t    for (i3 = i3min; i3 <= i3max; i3++)\n\t      {\n\t\ti = i1+2*i2+4*i3;\n\t\tif (node->childs[i])\n\t\t  {\n\t\t    stacks++;\n\t\t    stack.Elem(stacks) = node->childs[i];\n\t\t  }\n\t      }\n      \n\t/*\n\t  if (node->left && bmin[dir] <= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->left;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t  if (node->right && bmax[dir] >= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->right;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t*/\n      }\n  }\n\n  void ADTree3FM :: PrintRec (ostream & ost, const ADTreeNode3FM * node) const\n  {\n    int i;\n    if (node->data)\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (i = 0; i < 3; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n\n    for (i = 0; i < 8; i++)\n      if (node->childs[i])\n\tPrintRec (ost, node->childs[i]);\n  }\n\n\n\n\n#endif\n  \n\n\n\n\n\n  /* ******************************* ADTree6 ******************************* */\n\n\n  ADTreeNode6 :: ADTreeNode6()\n  {\n    pi = -1;\n\n    left = NULL;\n    right = NULL;\n    father = NULL;\n    nchilds = 0;\n  }\n\n  void ADTreeNode6 :: DeleteChilds ()\n  {\n    if (left)\n      {\n\tleft->DeleteChilds();\n\tdelete left;\n\tleft = NULL;\n      }\n    if (right)\n      {\n\tright->DeleteChilds();\n\tdelete right;\n\tright = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode6 :: ball (sizeof (ADTreeNode6));\n  void * ADTreeNode6 :: operator new(size_t s)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode6 :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n  ADTree6 :: ADTree6 (const float * acmin, \n\t\t      const float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 6 * sizeof(float));\n    memcpy (cmax, acmax, 6 * sizeof(float));\n\n    root = new ADTreeNode6;\n    root->sep = (cmin[0] + cmax[0]) / 2;\n  }\n\n  ADTree6 :: ~ADTree6 ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n  void ADTree6 :: Insert (const float * p, int pi)\n  {\n    ADTreeNode6 *node(NULL);\n    ADTreeNode6 *next;\n    int dir;\n    int lr(0);\n\n    float bmin[6];\n    float bmax[6];\n\n  \n    memcpy (bmin, cmin, 6 * sizeof(float));\n    memcpy (bmax, cmax, 6 * sizeof(float));\n\n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tif (node->pi == -1)\n\t  {    \n\t    memcpy (node->data, p, 6 * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi+1)\n\t      ela.SetSize (pi+1);\n\t    ela[pi] = node;\n\n\t    return;\n\t  }\n\n\tif (node->sep > p[dir])\n\t  {\n\t    next = node->left;\n\t    bmax[dir] = node->sep;\n\t    lr = 0;\n\t  }\n\telse\n\t  {\n\t    next = node->right;\n\t    bmin[dir] = node->sep;\n\t    lr = 1;\n\t  }\n\n\tdir++;\n\tif (dir == 6) dir = 0;\n      }\n\n\n    next = new ADTreeNode6;\n    memcpy (next->data, p, 6 * sizeof(float));\n    next->pi = pi;\n    next->sep = (bmin[dir] + bmax[dir]) / 2;\n\n    if (ela.Size() < pi+1)\n      ela.SetSize (pi+1);\n    ela[pi] = next;\n\n    if (lr)\n      node->right = next;\n    else\n      node->left = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree6 :: DeleteElement (int pi)\n  {\n    ADTreeNode6 * node = ela[pi];\n\n    node->pi = -1;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree6 :: PrintMemInfo (ostream & ost) const\n  {\n    ost << Elements() << \" elements a \" << sizeof(ADTreeNode6) \n\t<< \" Bytes = \"\n\t<< Elements() * sizeof(ADTreeNode6) << endl;\n    ost << \"maxind = \" << ela.Size() << \" = \" << sizeof(ADTreeNode6*) * ela.Size() << \" Bytes\" << endl;\n  }\n\n\n\n  class inttn6 {\n  public:\n    int dir;\n    ADTreeNode6 * node;\n  };\n\n\n\n\n  void ADTree6 :: GetIntersecting (const float * bmin, \n\t\t\t\t   const float * bmax,\n\t\t\t\t   NgArray<int> & pis) const\n  {\n    // static NgArray<inttn6> stack(10000);\n    // stack.SetSize (10000);\n    NgArrayMem<inttn6,10000> stack(10000);\n    pis.SetSize(0);\n\n    stack[0].node = root;\n    stack[0].dir = 0;\n    int stacks = 0;\n\n    while (stacks >= 0)\n      {\n\tADTreeNode6 * node = stack[stacks].node;\n\tint dir = stack[stacks].dir; \n\n\tstacks--;\n\tif (node->pi != -1)\n\t  {\n\t    if (node->data[0] > bmax[0] || \n\t\tnode->data[1] > bmax[1] || \n\t\tnode->data[2] > bmax[2] || \n\t\tnode->data[3] < bmin[3] || \n\t\tnode->data[4] < bmin[4] || \n\t\tnode->data[5] < bmin[5])\n\t      ;\n\t    else\n              {\n                pis.Append (node->pi);\n              }\n\t  }\n\n\tint ndir = (dir+1) % 6;\n\n\tif (node->left && bmin[dir] <= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->left;\n\t    stack[stacks].dir = ndir;\n\t  }\n\tif (node->right && bmax[dir] >= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->right;\n\t    stack[stacks].dir = ndir;\n\t  }\n      }\n  }\n\n  void ADTree6 :: PrintRec (ostream & ost, const ADTreeNode6 * node) const\n  {\n    \n    // if (node->data)     // true anyway\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < 6; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    if (node->left)\n      PrintRec (ost, node->left);\n    if (node->right)\n      PrintRec (ost, node->right);\n  }\n\n\n  int ADTree6 :: DepthRec (const ADTreeNode6 * node) const\n  {\n    int ldepth = 0;\n    int rdepth = 0;\n\n    if (node->left)\n      ldepth = DepthRec(node->left);\n    if (node->right)\n      rdepth = DepthRec(node->right);\n    return 1 + max2 (ldepth, rdepth);\n  }\n\n  int ADTree6 :: ElementsRec (const ADTreeNode6 * node) const\n  {\n    int els = 1;\n    if (node->left)\n      els += ElementsRec(node->left);\n    if (node->right)\n      els += ElementsRec(node->right);\n    return els;\n  }\n\n\n\n\n\n\n  /*\n  template <int dim, typename T>\n  T_ADTree<dim,T> :: T_ADTree (Point<dim> acmin, Point<dim> acmax)\n  // : ela(0)\n  {\n    cmin = acmin;\n    cmax = acmax;\n    \n    root = new T_ADTreeNode<dim,T>;\n    root->sep = (cmin[0] + cmax[0]) / 2;\n  }\n  */\n\n  /*\n  template <int dim, typename T>  \n  T_ADTree<dim,T> :: ~T_ADTree ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  void T_ADTree<dim,T> :: Insert (Point<dim> p, T pi)\n  {\n    T_ADTreeNode<dim,T> *node(NULL);\n    T_ADTreeNode<dim,T> *next;\n    int dir;\n    int lr(0);\n\n    Point<dim> bmin = cmin;\n    Point<dim> bmax = cmax;\n  \n    next = root;\n    dir = 0;\n    while (next)\n      {\n\tnode = next;\n\n\tif (IsInvalid(node->pi))\n\t  {    \n\t    // memcpy (node->data, p, dim * sizeof(float));\n            node->data = p;\n\t    node->pi = pi;\n\n\t    // if (ela.Size() < pi+1)\n            // ela.SetSize (pi+1);\n\t    ela[pi] = node;\n\n\t    return;\n\t  }\n\n\tif (node->sep > p[dir])\n\t  {\n\t    next = node->left;\n\t    bmax(dir) = node->sep;\n\t    lr = 0;\n\t  }\n\telse\n\t  {\n\t    next = node->right;\n\t    bmin(dir) = node->sep;\n\t    lr = 1;\n\t  }\n\n\tdir++;\n\tif (dir == dim) dir = 0;\n      }\n\n\n    next = new T_ADTreeNode<dim,T>;\n    // memcpy (next->data, p, dim * sizeof(float));\n    next->data = p;\n    next->pi = pi;\n    next->sep = (bmin[dir] + bmax[dir]) / 2;\n\n    // if (ela.Size() < pi+1)\n    // ela.SetSize (pi+1);\n    ela[pi] = next;\n\n    if (lr)\n      node->right = next;\n    else\n      node->left = next;\n    next -> father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  void T_ADTree<dim,T> :: DeleteElement (T pi)\n  {\n    T_ADTreeNode<dim,T> * node = ela[pi];\n    ela.Delete(pi);\n    \n    SetInvalid(node->pi); //  = -1;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  void T_ADTree<dim,T> :: PrintMemInfo (ostream & ost) const\n  {\n    ost << Elements() << \" elements a \" << sizeof(ADTreeNode6) \n\t<< \" Bytes = \"\n\t<< Elements() * sizeof(T_ADTreeNode<dim,T>) << endl;\n    ost << \"maxind = \" << ela.Size() << \" = \" << sizeof(T_ADTreeNode<dim,T>*) * ela.Size() << \" Bytes\" << endl;\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  class inttn {\n  public:\n    int dir;\n    T_ADTreeNode<dim,T> * node;\n  };\n\n\n  template <int dim, typename T>\n  void T_ADTree<dim,T> :: GetIntersecting (Point<dim> bmin, Point<dim> bmax,\n                                           NgArray<T> & pis) const\n  {\n    // static NgArray<inttn6> stack(10000);\n    // stack.SetSize (10000);\n    NgArrayMem<inttn<dim,T>,10000> stack(10000);\n    pis.SetSize(0);\n\n    stack[0].node = root;\n    stack[0].dir = 0;\n    int stacks = 0;\n\n    while (stacks >= 0)\n      {\n\tT_ADTreeNode<dim,T> * node = stack[stacks].node;\n\tint dir = stack[stacks].dir; \n\n\tstacks--;\n\tif (!IsInvalid(node->pi)) //  != -1)\n\t  {\n            bool found = true;\n            for (int i = 0; i < dim/2; i++)\n              if (node->data[i] > bmax[i])\n                found = false;\n            for (int i = dim/2; i < dim; i++)\n              if (node->data[i] < bmin[i])\n                found = false;\n            if (found)\n              pis.Append (node->pi);            \n\n            //\tif (node->data[0] > bmax[0] || \n            // node->data[1] > bmax[1] || \n            // node->data[2] > bmax[2] || \n            // node->data[3] < bmin[3] || \n            // node->data[4] < bmin[4] || \n            // node->data[5] < bmin[5])\n            // ;\n\t    // else\n            // {\n            // pis.Append (node->pi);\n            // }\n\t  }\n\n\tint ndir = (dir+1) % dim;\n\n\tif (node->left && bmin[dir] <= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->left;\n\t    stack[stacks].dir = ndir;\n\t  }\n\tif (node->right && bmax[dir] >= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->right;\n\t    stack[stacks].dir = ndir;\n\t  }\n      }\n  }\n*/\n\n  /*\n  template <int dim, typename T>\n  void T_ADTree<dim,T> :: PrintRec (ostream & ost, const T_ADTreeNode<dim,T> * node) const\n  {\n    \n    // if (node->data)     // true anyway\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < dim; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n    if (node->left)\n      PrintRec (ost, node->left);\n    if (node->right)\n      PrintRec (ost, node->right);\n  }\n\n  template <int dim, typename T>\n  int T_ADTree<dim,T> :: DepthRec (const T_ADTreeNode<dim,T> * node) const\n  {\n    int ldepth = 0;\n    int rdepth = 0;\n\n    if (node->left)\n      ldepth = DepthRec(node->left);\n    if (node->right)\n      rdepth = DepthRec(node->right);\n    return 1 + max2 (ldepth, rdepth);\n  }\n\n  template <int dim, typename T>\n  int T_ADTree<dim,T> :: ElementsRec (const T_ADTreeNode<dim,T> * node) const\n  {\n    int els = 1;\n    if (node->left)\n      els += ElementsRec(node->left);\n    if (node->right)\n      els += ElementsRec(node->right);\n    return els;\n  }\n*/\n\n\n  \n\n\n\n#ifdef ABC\n\n  /* ******************************* ADTree6F ******************************* */\n\n\n  ADTreeNode6F :: ADTreeNode6F()\n  {\n    pi = 0;\n    father = NULL;\n    nchilds = 0;\n    int i;\n    for (i = 0; i < 64; i++)\n      childs[i] = NULL;\n  }\n\n  void ADTreeNode6F :: DeleteChilds ()\n  {\n    int i;\n\n    for (i = 0; i < 64; i++)\n      {\n\tif (childs[i])\n\t  childs[i]->DeleteChilds();\n\tdelete childs[i];\n\tchilds[i] = NULL;\n      }\n  }\n\n\n  BlockAllocator ADTreeNode6F :: ball(sizeof (ADTreeNode6F));\n\n  void * ADTreeNode6F :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void ADTreeNode6F :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n\n\n  ADTree6F :: ADTree6F (const float * acmin, \n\t\t\tconst float * acmax)\n    : ela(0)\n  {\n    memcpy (cmin, acmin, 6 * sizeof(float));\n    memcpy (cmax, acmax, 6 * sizeof(float));\n\n    root = new ADTreeNode6F;\n    for (int i = 0; i < 6; i++)\n      root->sep[i] = (cmin[i] + cmax[i]) / 2;\n  }\n\n  ADTree6F :: ~ADTree6F ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n\n  void ADTree6F :: Insert (const float * p, int pi)\n  {\n    ADTreeNode6F *node;\n    ADTreeNode6F *next;\n    int lr;\n\n    float bmin[6];\n    float bmax[6];\n    int i, dir;\n  \n    memcpy (bmin, cmin, 6 * sizeof(float));\n    memcpy (bmax, cmax, 6 * sizeof(float));\n\n    next = root;\n    while (next)\n      {\n\tnode = next;\n      \n\tif (!node->pi)\n\t  {    \n\t    memcpy (node->data, p, 6 * sizeof(float));\n\t    node->pi = pi;\n\n\t    if (ela.Size() < pi)\n\t      ela.SetSize (pi);\n\t    ela.Elem(pi) = node;\n\n\t    return;\n\t  }\n\n\tdir = 0;\n\tfor (i = 0; i < 6; i++)\n\t  {\n\t    if (node->sep[i] > p[i])\n\t      {\n\t\tbmax[i] = node->sep[i];\n\t      }\n\t    else\n\t      {\n\t\tbmin[i] = node->sep[i];\n\t\tdir += (1 << i);\n\t      }\n\t  }\n\tnext = node->childs[dir];\n\n\t/*\n\t  if (node->sep > p[dir])\n\t  {\n\t  next = node->left;\n\t  bmax[dir] = node->sep;\n\t  lr = 0;\n\t  }\n\t  else\n\t  {\n\t  next = node->right;\n\t  bmin[dir] = node->sep;\n\t  lr = 1;\n\t  }\n\t*/\n      }\n\n\n    next = new ADTreeNode6F;\n    memcpy (next->data, p, 6 * sizeof(float));\n    next->pi = pi;\n\n    for (i = 0; i < 6; i++)\n      next->sep[i] = (bmin[i] + bmax[i]) / 2;\n  \n\n    if (ela.Size() < pi)\n      ela.SetSize (pi);\n    ela.Elem(pi) = next;\n\n    node->childs[dir] = next;\n    next->father = node;\n\n    while (node)\n      {\n\tnode->nchilds++;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree6F :: DeleteElement (int pi)\n  {\n    ADTreeNode6F * node = ela.Get(pi);\n\n    node->pi = 0;\n\n    node = node->father;\n    while (node)\n      {\n\tnode->nchilds--;\n\tnode = node->father;\n      }\n  }\n\n  void ADTree6F :: GetIntersecting (const float * bmin, \n\t\t\t\t    const float * bmax,\n\t\t\t\t    NgArray<int> & pis) const\n  {\n    static NgArray<ADTreeNode6F*> stack(1000);\n    ADTreeNode6F * node;\n    int dir, i, stacks;\n\n    stack.SetSize (1000);\n    pis.SetSize(0);\n\n    stack.Elem(1) = root;\n    stacks = 1;\n\n    while (stacks)\n      {\n\tnode = stack.Get(stacks);\n\tstacks--;\n\n\tif (node->pi)\n\t  {\n\t    if (\n\t\tnode->data[0] >= bmin[0] && node->data[0] <= bmax[0] &&\n\t\tnode->data[1] >= bmin[1] && node->data[1] <= bmax[1] &&\n\t\tnode->data[2] >= bmin[2] && node->data[2] <= bmax[2] &&\n\t\tnode->data[3] >= bmin[3] && node->data[3] <= bmax[3] &&\n\t\tnode->data[4] >= bmin[4] && node->data[4] <= bmax[4] &&\n\t\tnode->data[5] >= bmin[5] && node->data[5] <= bmax[5]\n\t\t)\n\n\t      pis.Append (node->pi);\n\t  }\n\n      \n\tint i1min = (bmin[0] <= node->sep[0]) ? 0 : 1;\n\tint i1max = (bmax[0] < node->sep[0]) ? 0 : 1;\n\tint i2min = (bmin[1] <= node->sep[1]) ? 0 : 1;\n\tint i2max = (bmax[1] < node->sep[1]) ? 0 : 1;\n\tint i3min = (bmin[2] <= node->sep[2]) ? 0 : 1;\n\tint i3max = (bmax[2] < node->sep[2]) ? 0 : 1;\n\n\tint i4min = (bmin[3] <= node->sep[3]) ? 0 : 1;\n\tint i4max = (bmax[3] <  node->sep[3]) ? 0 : 1;\n\tint i5min = (bmin[4] <= node->sep[4]) ? 0 : 1;\n\tint i5max = (bmax[4] <  node->sep[4]) ? 0 : 1;\n\tint i6min = (bmin[5] <= node->sep[5]) ? 0 : 1;\n\tint i6max = (bmax[5] <  node->sep[5]) ? 0 : 1;\n\n\tint i1, i2, i3, i4, i5, i6;\n\tfor (i1 = i1min; i1 <= i1max; i1++)\n\t  for (i2 = i2min; i2 <= i2max; i2++)\n\t    for (i3 = i3min; i3 <= i3max; i3++)\n\t      for (i4 = i4min; i4 <= i4max; i4++)\n\t\tfor (i5 = i5min; i5 <= i5max; i5++)\n\t\t  for (i6 = i6min; i6 <= i6max; i6++)\n\t\t    {\n\t\t      i = i1 + 2*i2 + 4*i3 + 8*i4 + 16*i5 +32*i6;\n\t\t      if (node->childs[i])\n\t\t\t{\n\t\t\t  stacks++;\n\t\t\t  stack.Elem(stacks) = node->childs[i];\n\t\t\t}\n\t\t    }\n      \n\t/*\n\t  if (node->left && bmin[dir] <= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->left;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t  if (node->right && bmax[dir] >= node->sep)\n\t  {\n\t  stacks++;\n\t  stack.Elem(stacks) = node->right;\n\t  stackdir.Elem(stacks) = ndir;\n\t  }\n\t*/\n      }\n  }\n\n  void ADTree6F :: PrintRec (ostream & ost, const ADTreeNode6F * node) const\n  {\n    int i;\n    if (node->data)\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (i = 0; i < 6; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n\n    for (i = 0; i < 64; i++)\n      if (node->childs[i])\n\tPrintRec (ost, node->childs[i]);\n  }\n\n\n\n#endif\n\n\n\n  /* ************************************* Point3dTree ********************** */\n\n\n\n  Point3dTree :: Point3dTree (const Point<3> & pmin, const Point<3> & pmax)\n  {\n    float pmi[3], pma[3];\n    for (int i = 0; i < 3; i++)\n      {\n\tpmi[i] = pmin(i);\n\tpma[i] = pmax(i);\n      }\n    tree = new ADTree3 (pmi, pma);\n  }\n\n  Point3dTree :: ~Point3dTree ()\n  {\n    delete tree;\n  }\n\n\n\n  void Point3dTree :: Insert (const Point<3> & p, int pi)\n  {\n    float pd[3];\n    pd[0] = p(0);\n    pd[1] = p(1);\n    pd[2] = p(2);\n    tree->Insert (pd, pi);\n  }\n\n  void Point3dTree :: GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, \n\t\t\t\t       NgArray<int> & pis) const\n  {\n    float pmi[3], pma[3];\n    for (int i = 0; i < 3; i++)\n      {\n\tpmi[i] = pmin(i);\n\tpma[i] = pmax(i);\n      }\n    tree->GetIntersecting (pmi, pma, pis);\n  }\n\n\n\n\n\n\n\n  /*\n  template <int dim, typename T>\n  BoxTree<dim,T> :: BoxTree (const Box<dim> & abox)\n  {\n    boxpmin = abox.PMin();\n    boxpmax = abox.PMax();\n    Point<2*dim> tpmin, tpmax;\n    for (int i = 0; i < dim; i++)\n      {\n\ttpmin(i) = tpmin(i+dim) = boxpmin(i);\n\ttpmax(i) = tpmax(i+dim) = boxpmax(i);\n      }\n    tree = new T_ADTree<2*dim,T> (tpmin, tpmax);\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  BoxTree<dim,T> :: BoxTree (const Point<dim> & apmin, const Point<dim> & apmax)\n  {\n    boxpmin = apmin;\n    boxpmax = apmax;\n    Point<2*dim> tpmin, tpmax;\n    for (int i = 0; i < dim; i++)\n      {\n\ttpmin(i) = tpmin(i+dim) = boxpmin(i);\n\ttpmax(i) = tpmax(i+dim) = boxpmax(i);\n      }\n    tree = new T_ADTree<2*dim,T> (tpmin, tpmax);\n  }\n\n  template <int dim, typename T>\n  BoxTree<dim,T> :: ~BoxTree ()\n  {\n    delete tree;\n  }\n\n  template <int dim, typename T>\n  void BoxTree<dim,T> :: Insert (const Point<dim> & bmin, const Point<dim> & bmax, T pi)\n  {\n    Point<2*dim> tp;\n\n    for (size_t i = 0; i < dim; i++)\n      {\n\ttp(i) = bmin(i);\n\ttp(i+dim) = bmax(i);\n      }\n\n    tree->Insert (tp, pi);\n  }\n  */\n\n  /*\n  template <int dim, typename T>\n  void BoxTree<dim,T> ::GetIntersecting (const Point<dim> & pmin, const Point<dim> & pmax, \n                                         NgArray<T> & pis) const\n  {\n    Point<2*dim> tpmin, tpmax;\n    double tol = Tolerance();\n    for (size_t i = 0; i < dim; i++)\n      {\n\ttpmin(i) = boxpmin(i);\n\ttpmax(i) = pmax(i)+tol;\n        \n\ttpmin(i+dim) = pmin(i)-tol;\n\ttpmax(i+dim) = boxpmax(i);\n      }\n\n    tree->GetIntersecting (tpmin, tpmax, pis);\n  }\n  */\n  \n  /*\n  template<> BlockAllocator T_ADTreeNode<4,INDEX> :: ball(sizeof (T_ADTreeNode<4,INDEX>));\n  template class T_ADTree<4,INDEX>;\n  template class BoxTree<2,INDEX>;\n\n  template<> BlockAllocator T_ADTreeNode<4,INDEX_2> :: ball(sizeof (T_ADTreeNode<4,INDEX_2>));\n  template class T_ADTree<4,INDEX_2>;\n  template class BoxTree<2,INDEX_2>;\n  \n  \n  template<> BlockAllocator T_ADTreeNode<6,INDEX> :: ball(sizeof (T_ADTreeNode<6,INDEX>));\n  template class T_ADTree<6,INDEX>;\n  template class BoxTree<3,INDEX>;\n  */\n  \n}\n"
  },
  {
    "path": "libsrc/gprim/adtree.hpp",
    "content": "#ifndef FILE_ADTREE\n#define FILE_ADTREE\n\n/* *************************************************************************/\n/* File:   adtree.hh                                                       */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   16. Feb. 98                                                     */\n/* Redesigned by Wolfram Muehlhuber, May 1998                              */\n/* *************************************************************************/\n\n#include <general/optmem.hpp>\n#include <general/template.hpp>\n#include <general/hashtabl.hpp>\n\n#include \"geomfuncs.hpp\"\n\nnamespace netgen\n{\n\n/**\n  Alternating Digital Tree\n */\n\n// #include \"../include/mystdlib.h\"\n// #include \"../include/myadt.hpp\"\n\nclass ADTreeNode\n{\npublic:\n  ADTreeNode *left, *right, *father;\n  int dim;\n  float sep;\n  float *data;\n  float *boxmin;\n  float *boxmax;\n  int pi;\n  int nchilds;\n\n  ADTreeNode (int adim);\n  ~ADTreeNode ();\n\n  friend class ADTree;\n};\n\n\nclass ADTreeCriterion\n{\npublic:\n  ADTreeCriterion() { }\n  virtual int Eval (const ADTreeNode * node) const = 0;\n};\n\n\nclass ADTree\n{\n  int dim;\n  ADTreeNode * root;\n  float *cmin, *cmax;\n  NgArray<ADTreeNode*> ela;\n  const ADTreeCriterion * criterion; \n\n  NgArray<ADTreeNode*> stack;\n  NgArray<int> stackdir;\n  int stackindex;\n\npublic:\n  ADTree (int adim, const float * acmin, \n\t   const float * acmax);\n  ~ADTree ();\n\n  void Insert (const float * p, int pi);\n  // void GetIntersecting (const float * bmin, const float * bmax,\n  //\t\t\tNgArray<int> & pis) const;\n  void SetCriterion (ADTreeCriterion & acriterion);\n  void Reset ();\n  int Next ();\n  void GetMatch (NgArray<int> & matches);\n\n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode * node) const;\n};\n\n\n\nclass ADTreeNode3\n{\npublic:\n  ADTreeNode3 *left, *right, *father;\n  float sep;\n  float data[3];\n  int pi;\n  int nchilds;\n\n  ADTreeNode3 ();\n  void DeleteChilds ();\n  friend class ADTree3;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n\nclass ADTree3\n{\n  ADTreeNode3 * root;\n  float cmin[3], cmax[3];\n  NgArray<ADTreeNode3*> ela;\n\npublic:\n  ADTree3 (const float * acmin, \n\t   const float * acmax);\n  ~ADTree3 ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode3 * node) const;\n};\n\n\n/*\n\n// divide each direction\n#define ADTN_DIV 10\nclass ADTreeNode3Div\n{\npublic:\n  ADTreeNode3Div *father;\n  ADTreeNode3Div *childs[ADTN_DIV];\n\n  float minx, dist;\n  float data[3];\n  int pi;\n  int nchilds;\n\n  ADTreeNode3Div ();\n  void DeleteChilds ();\n  friend class ADTree3Div;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n\nclass ADTree3Div\n{\n  ADTreeNode3Div * root;\n  float cmin[3], cmax[3];\n  NgArray<ADTreeNode3Div*> ela;\n\npublic:\n  ADTree3Div (const float * acmin, \n\t   const float * acmax);\n  ~ADTree3Div ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode3Div * node) const;\n};\n\n\n\n\n#define ADTN_SIZE 10\n\n// multiple entries\nclass ADTreeNode3M\n{\npublic:\n  ADTreeNode3M *left, *right, *father;\n  float sep;\n  float data[ADTN_SIZE][3];\n  int pi[ADTN_SIZE];\n  int nchilds;\n\n  ADTreeNode3M ();\n  void DeleteChilds ();\n  friend class ADTree3M;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n\nclass ADTree3M\n{\n  ADTreeNode3M * root;\n  float cmin[3], cmax[3];\n  NgArray<ADTreeNode3M*> ela;\n\npublic:\n  ADTree3M (const float * acmin, \n\t   const float * acmax);\n  ~ADTree3M ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode3M * node) const;\n};\n\n\n\n\n\n\nclass ADTreeNode3F\n{\npublic:\n  ADTreeNode3F *father;\n  ADTreeNode3F *childs[8];\n  float sep[3];\n  float data[3];\n  int pi;\n  int nchilds;\n\n  ADTreeNode3F ();\n  void DeleteChilds ();\n  friend class ADTree3F;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n// fat tree\nclass ADTree3F\n{\n  ADTreeNode3F * root;\n  float cmin[3], cmax[3];\n  NgArray<ADTreeNode3F*> ela;\n\npublic:\n  ADTree3F (const float * acmin, \n\t   const float * acmax);\n  ~ADTree3F ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode3F * node) const;\n};\n\n\n\n\nclass ADTreeNode3FM\n{\npublic:\n  ADTreeNode3FM *father;\n  ADTreeNode3FM *childs[8];\n  float sep[3];\n  float data[ADTN_SIZE][3];\n  int pi[ADTN_SIZE];\n  int nchilds;\n\n  ADTreeNode3FM ();\n  void DeleteChilds ();\n  friend class ADTree3FM;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n// fat tree\nclass ADTree3FM\n{\n  ADTreeNode3FM * root;\n  float cmin[3], cmax[3];\n  NgArray<ADTreeNode3FM*> ela;\n\npublic:\n  ADTree3FM (const float * acmin, \n\t   const float * acmax);\n  ~ADTree3FM ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode3FM * node) const;\n};\n\n\n\n*/\n\n\n\n\n\nclass ADTreeNode6\n{\npublic:\n  ADTreeNode6 *left, *right, *father;\n  float sep;\n  float data[6];\n  int pi;\n  int nchilds;\n\n  ADTreeNode6 ();\n  void DeleteChilds ();\n  friend class ADTree6;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n\nclass ADTree6\n{\n  ADTreeNode6 * root;\n  float cmin[6], cmax[6];\n  NgArray<ADTreeNode6*> ela;\n\npublic:\n  ADTree6 (const float * acmin, \n\t   const float * acmax);\n  ~ADTree6 ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n  \n  void Print (ostream & ost) const\n  { PrintRec (ost, root); }\n  int Depth () const\n  { return DepthRec (root); }\n  int Elements () const\n  { return ElementsRec (root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode6 * node) const;\n  int DepthRec (const ADTreeNode6 * node) const;\n  int ElementsRec (const ADTreeNode6 * node) const;\n\n  void PrintMemInfo (ostream & ost) const;\n};\n\n\n\n\n\n  template <int DIM, typename T>\nclass T_ADTreeNode\n{\npublic:\n  T_ADTreeNode *left, *right, *father;\n  float sep;\n  // float data[DIM];\n  Point<DIM,float> data;\n  T pi;\n  int nchilds;\n\n  T_ADTreeNode ()\n  {\n    // pi = -1;\n    SetInvalid(pi);\n    left = NULL;\n    right = NULL;\n    father = NULL;\n    nchilds = 0;\n  }\n  \n  void DeleteChilds (BlockAllocator & ball)\n  {\n    if (left)\n      {\n\tleft->DeleteChilds(ball);\n        ball.Free(left);\n\tleft = NULL;\n      }\n    if (right)\n      {\n\tright->DeleteChilds(ball);\n        ball.Free(right);\n\tright = NULL;\n      }\n  }\n};\n\n\n\n  template <int dim, typename T = INDEX>\n  class T_ADTree\n  {\n    T_ADTreeNode<dim,T> * root;\n    // float cmin[dim], cmax[dim];\n    Point<dim> cmin, cmax;\n    // NgArray<T_ADTreeNode<dim>*> ela;\n    NgClosedHashTable<T, T_ADTreeNode<dim,T>*> ela;\n\n    BlockAllocator ball{sizeof(T_ADTreeNode<dim,T>)};\n  public:\n    T_ADTree (Point<dim> acmin, Point<dim> acmax)\n    {\n      cmin = acmin;\n      cmax = acmax;\n      \n      root = new (ball.Alloc()) T_ADTreeNode<dim,T>;\n      root->sep = (cmin[0] + cmax[0]) / 2;\n    }\n    \n    ~T_ADTree ()\n    {\n      root->DeleteChilds(ball);\n      ball.Free(root);\n    }\n    \n    void Insert (Point<dim> p, T pi)\n    {\n      T_ADTreeNode<dim,T> *node(NULL);\n      T_ADTreeNode<dim,T> *next;\n      int dir;\n      int lr(0);\n      \n      Point<dim> bmin = cmin;\n      Point<dim> bmax = cmax;\n      \n      next = root;\n      dir = 0;\n      while (next)\n        {\n          node = next;\n          \n          if (IsInvalid(node->pi))\n            {    \n              // memcpy (node->data, p, dim * sizeof(float));\n              node->data = p;\n              node->pi = pi;\n              \n              // if (ela.Size() < pi+1)\n              // ela.SetSize (pi+1);\n              ela[pi] = node;\n              \n\t    return;\n            }\n          \n          if (node->sep > p[dir])\n            {\n              next = node->left;\n              bmax(dir) = node->sep;\n              lr = 0;\n            }\n          else\n            {\n              next = node->right;\n              bmin(dir) = node->sep;\n              lr = 1;\n            }\n          \n          dir++;\n          if (dir == dim) dir = 0;\n        }\n      \n      \n      next = new (ball.Alloc()) T_ADTreeNode<dim,T>;\n      next->data = p;\n      next->pi = pi;\n      next->sep = (bmin[dir] + bmax[dir]) / 2;\n      \n      // if (ela.Size() < pi+1)\n      // ela.SetSize (pi+1);\n      ela[pi] = next;\n      \n      if (lr)\n        node->right = next;\n      else\n        node->left = next;\n      next -> father = node;\n\n      while (node)\n        {\n          node->nchilds++;\n          node = node->father;\n        }\n    }\n\n    \n    class inttn {\n    public:\n      int dir;\n      T_ADTreeNode<dim,T> * node;\n    };\n    \n    void GetIntersecting (Point<dim> bmin, Point<dim> bmax,\n                          NgArray<T> & pis) const\n  {\n    NgArrayMem<inttn,10000> stack(10000);\n    pis.SetSize(0);\n\n    stack[0].node = root;\n    stack[0].dir = 0;\n    int stacks = 0;\n\n    while (stacks >= 0)\n      {\n\tT_ADTreeNode<dim,T> * node = stack[stacks].node;\n\tint dir = stack[stacks].dir; \n\n\tstacks--;\n\tif (!IsInvalid(node->pi)) //  != -1)\n\t  {\n            bool found = true;\n            for (int i = 0; i < dim/2; i++)\n              if (node->data[i] > bmax[i])\n                found = false;\n            for (int i = dim/2; i < dim; i++)\n              if (node->data[i] < bmin[i])\n                found = false;\n            if (found)\n              pis.Append (node->pi);            \n            /*\n\t    if (node->data[0] > bmax[0] || \n\t\tnode->data[1] > bmax[1] || \n\t\tnode->data[2] > bmax[2] || \n\t\tnode->data[3] < bmin[3] || \n\t\tnode->data[4] < bmin[4] || \n\t\tnode->data[5] < bmin[5])\n\t      ;\n\t    else\n              {\n                pis.Append (node->pi);\n              }\n            */\n\t  }\n\n\tint ndir = (dir+1) % dim;\n\n\tif (node->left && bmin[dir] <= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->left;\n\t    stack[stacks].dir = ndir;\n\t  }\n\tif (node->right && bmax[dir] >= node->sep)\n\t  {\n\t    stacks++;\n\t    stack[stacks].node = node->right;\n\t    stack[stacks].dir = ndir;\n\t  }\n      }\n  }\n    \n      \n    \n    void DeleteElement (T pi)\n    {\n      T_ADTreeNode<dim,T> * node = ela[pi];\n      ela.Delete(pi);\n      \n      SetInvalid(node->pi); //  = -1;\n      \n      node = node->father;\n      while (node)\n        {\n          node->nchilds--;\n          node = node->father;\n        }\n    }\n    \n    \n    void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n    int Depth () const\n    { return DepthRec (root); }\n    int Elements () const\n    { return ElementsRec (root); }\n    \n    void PrintRec (ostream & ost, const T_ADTreeNode<dim,T> * node) const\n    {\n      \n      // if (node->data)     // true anyway\n      {\n\tost << node->pi << \": \";\n\tost << node->nchilds << \" childs, \";\n\tfor (int i = 0; i < dim; i++)\n\t  ost << node->data[i] << \" \";\n\tost << endl;\n      }\n      if (node->left)\n        PrintRec (ost, node->left);\n      if (node->right)\n        PrintRec (ost, node->right);\n    }\n\n    int DepthRec (const T_ADTreeNode<dim,T> * node) const\n    {\n      int ldepth = 0;\n      int rdepth = 0;\n      \n      if (node->left)\n        ldepth = DepthRec(node->left);\n      if (node->right)\n        rdepth = DepthRec(node->right);\n      return 1 + max2 (ldepth, rdepth);\n    }\n    \n    int ElementsRec (const T_ADTreeNode<dim,T> * node) const\n    {\n      int els = 1;\n      if (node->left)\n        els += ElementsRec(node->left);\n      if (node->right)\n      els += ElementsRec(node->right);\n      return els;\n    }\n    \n    \n    void PrintMemInfo (ostream & ost) const\n    {\n      ost << Elements() << \" elements a \" << sizeof(ADTreeNode6) \n          << \" Bytes = \"\n          << Elements() * sizeof(T_ADTreeNode<dim,T>) << endl;\n      ost << \"maxind = \" << ela.Size() << \" = \" << sizeof(T_ADTreeNode<dim,T>*) * ela.Size() << \" Bytes\" << endl;\n    }\n    \n  };\n  \n  \n\n\n\n\n/*\n\nclass ADTreeNode6F\n{\npublic:\n  ADTreeNode6F * father;\n  ADTreeNode6F * childs[64];\n  \n  float sep[6];\n  float data[6];\n  int pi;\n  int nchilds;\n\n  ADTreeNode6F ();\n  void DeleteChilds ();\n  friend class ADTree6F;\n\n  static BlockAllocator ball;\n  void * operator new(size_t);\n  void operator delete (void *);\n};\n\n\nclass ADTree6F\n{\n  ADTreeNode6F * root;\n  float cmin[6], cmax[6];\n  NgArray<ADTreeNode6F*> ela;\n\npublic:\n  ADTree6F (const float * acmin, \n\t   const float * acmax);\n  ~ADTree6F ();\n\n  void Insert (const float * p, int pi);\n  void GetIntersecting (const float * bmin, const float * bmax,\n\t\t\tNgArray<int> & pis) const;\n  \n  void DeleteElement (int pi);\n\n\n  void Print (ostream & ost) const\n    { PrintRec (ost, root); }\n  int Depth () const\n    { return DepthRec (root); }\n\n  void PrintRec (ostream & ost, const ADTreeNode6F * node) const;\n  int DepthRec (const ADTreeNode6F * node) const;\n};\n\n\n\n\n\n\n\n*/\n\n\n\n\n\nclass Point3dTree \n{\n  ADTree3 * tree;\n\npublic:\n  DLL_HEADER Point3dTree (const Point<3> & pmin, const Point<3> & pmax);\n  DLL_HEADER ~Point3dTree ();\n  DLL_HEADER void Insert (const Point<3> & p, int pi);\n  void DeleteElement (int pi) \n    { tree->DeleteElement(pi); }\n  DLL_HEADER void GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, \n\t\t\tNgArray<int> & pis) const;\n  const ADTree3 & Tree() const { return *tree; };\n};\n\ntemplate<int dim, typename T=INDEX>\nclass BoxTree\n{\npublic:\n  // Number of entries per leaf\n  static constexpr int N = 100;\n\n  struct Node;\n\n  struct Leaf\n  {\n    Point<2*dim> p[N];\n    T index[N];\n    int n_elements;\n\n    Leaf() : n_elements(0)\n    { }\n\n    void Add( NgClosedHashTable<T, Leaf*> &leaf_index, const Point<2*dim> &ap, T aindex )\n      {\n        p[n_elements] = ap;\n        index[n_elements] = aindex;\n        n_elements++;\n        leaf_index[aindex] = this;\n      }\n  };\n\n  struct Node\n  {\n    union\n    {\n      Node *children[2];\n      Leaf *leaf;\n    };\n    double sep;\n    int level;\n\n    Node()\n        : children{nullptr,nullptr}\n    { }\n\n    ~Node()\n     { }\n\n    Leaf *GetLeaf() const\n      {\n        return children[1] ? nullptr : leaf;\n      }\n  };\n\nprivate:\n  Node root;\n\n  NgClosedHashTable<T, Leaf*> leaf_index;\n\n  Point<dim> global_min, global_max;\n  double tol;\n  size_t n_leaves;\n  size_t n_nodes;\n  BlockAllocator ball_nodes;\n  BlockAllocator ball_leaves;\n\npublic:\n\n  BoxTree (const Point<dim> & pmin, const Point<dim> & pmax)\n      : global_min(pmin), global_max(pmax), n_leaves(1), n_nodes(1), ball_nodes(sizeof(Node)), ball_leaves(sizeof(Leaf))\n    {\n      root.leaf = (Leaf*) ball_leaves.Alloc(); new (root.leaf) Leaf();\n      root.level = 0;\n      tol = 1e-7 * Dist(pmax, pmin);\n    }\n\n  BoxTree (const Box<dim> & box)\n      : BoxTree(box.PMin(), box.PMax())\n    { }\n\n  void SetTolerance(double _tol) { tol = _tol; }\n  double GetTolerance() { return tol; }\n\n  size_t GetNLeaves()\n    {\n      return n_leaves;\n    }\n\n  size_t GetNNodes()\n    {\n      return n_nodes;\n    }\n\n  template<typename TFunc>\n  void GetFirstIntersecting (const Point<dim> & pmin, const Point<dim> & pmax,\n          TFunc func=[](auto pi){return false;}) const\n    {\n      // static Timer timer(\"BoxTree::GetIntersecting\"); RegionTimer rt(timer);\n      // static Timer timer1(\"BoxTree::GetIntersecting-LinearSearch\");\n      ArrayMem<const Node*, 100> stack;\n      ArrayMem<int, 100> dir_stack;\n\n\n      Point<2*dim> tpmin, tpmax;\n\n      for (size_t i : IntRange(dim))\n        {\n          tpmin(i) = global_min(i);\n          tpmax(i) = pmax(i)+tol;\n\n          tpmin(i+dim) = pmin(i)-tol;\n          tpmax(i+dim) = global_max(i);\n        }\n\n      stack.SetSize(0);\n      stack.Append(&root);\n      dir_stack.SetSize(0);\n      dir_stack.Append(0);\n\n      while(stack.Size())\n        {\n          const Node *node = stack.Last();\n          stack.DeleteLast();\n\n          int dir = dir_stack.Last();\n          dir_stack.DeleteLast();\n\n          if(Leaf *leaf = node->GetLeaf())\n            {\n              //               RegionTimer rt1(timer1);\n              for (auto i : IntRange(leaf->n_elements))\n                {\n                  bool intersect = true;\n                  const auto p = leaf->p[i];\n\n                  for (int d = 0; d < dim; d++)\n                      if (p[d] > tpmax[d])\n                          intersect = false;\n                  for (int d = dim; d < 2*dim; d++)\n                      if (p[d] < tpmin[d])\n                          intersect = false;\n                  if(intersect)\n                      if(func(leaf->index[i])) return;\n                }\n            }\n          else\n            {\n              int newdir = dir+1;\n              if(newdir==2*dim) newdir = 0;\n              if (tpmin[dir] <= node->sep)\n                {\n                  stack.Append(node->children[0]);\n                  dir_stack.Append(newdir);\n                }\n              if (tpmax[dir] >= node->sep)\n                {\n                  stack.Append(node->children[1]);\n                  dir_stack.Append(newdir);\n                }\n            }\n        }\n    }\n\n  void GetIntersecting (const Point<dim> & pmin, const Point<dim> & pmax,\n          NgArray<T> & pis) const\n    {\n      pis.SetSize(0);\n      GetFirstIntersecting(pmin, pmax, [&pis](auto pi) { pis.Append(pi); return false;});\n    }\n\n  void GetIntersecting(const Point<dim> & pmin,\n                       const Point<dim> & pmax,\n                       Array<T> & pis) const\n    {\n      pis.SetSize0();\n      GetFirstIntersecting(pmin, pmax, [&pis](auto pi) { pis.Append(pi); return false;});\n    }\n\n  void Insert (const Box<dim> & box, T pi)\n    {\n      Insert (box.PMin(), box.PMax(), pi);\n    }\n\n  void Insert (const Point<dim> & pmin, const Point<dim> & pmax, T pi)\n    {\n      // static Timer timer(\"BoxTree::Insert\"); RegionTimer rt(timer);\n      int dir = 0;\n      Point<2*dim> p;\n      for (auto i : IntRange(dim))\n        {\n          p(i) = pmin[i];\n          p(i+dim) = pmax[i];\n        }\n\n      Node * node = &root;\n      Leaf * leaf = node->GetLeaf();\n\n      // search correct leaf to add point\n      while(!leaf)\n        {\n          node = p[dir] < node->sep ? node->children[0] : node->children[1];\n          dir++;\n          if(dir==2*dim) dir = 0;\n          leaf = node->GetLeaf();\n        }\n\n      // add point to leaf\n      if(leaf->n_elements < N)\n          leaf->Add(leaf_index, p,pi);\n      else // assume leaf->n_elements == N\n        {\n          // add two new nodes and one new leaf\n          int n_elements = leaf->n_elements;\n          ArrayMem<double, N> coords(n_elements);\n          ArrayMem<int, N> order(n_elements);\n\n          // separate points in two halves, first sort all coordinates in direction dir\n          for (auto i : IntRange(n_elements))\n            {\n              order[i] = i;\n              coords[i] = leaf->p[i][dir];\n            }\n\n          QuickSortI(coords, order);\n          int isplit = N/2;\n          Leaf *leaf1 = (Leaf*) ball_leaves.Alloc(); new (leaf1) Leaf();\n          Leaf *leaf2 = (Leaf*) ball_leaves.Alloc(); new (leaf2) Leaf();\n\n          for (auto i : order.Range(0, isplit))\n              leaf1->Add(leaf_index, leaf->p[i], leaf->index[i] );\n          for (auto i : order.Range(isplit, N))\n              leaf2->Add(leaf_index, leaf->p[i], leaf->index[i] );\n\n          Node *node1 = (Node*) ball_nodes.Alloc(); new (node1) Node();\n          node1->leaf = leaf1;\n          node1->level = node->level+1;\n\n          Node *node2 = (Node*) ball_nodes.Alloc(); new (node2) Node();\n          node2->leaf = leaf2;\n          node2->level = node->level+1;\n\n          node->children[0] = node1;\n          node->children[1] = node2;\n          node->sep = 0.5 * (leaf->p[order[isplit-1]][dir] + leaf->p[order[isplit]][dir]);\n\n          // add new point to one of the new leaves\n          if (p[dir] < node->sep)\n              leaf1->Add( leaf_index, p, pi );\n          else\n              leaf2->Add( leaf_index, p, pi );\n\n          ball_leaves.Free(leaf);\n          n_leaves++;\n          n_nodes+=2;\n        }\n    }\n\n  void DeleteElement (T pi)\n    {\n      // static Timer timer(\"BoxTree::DeleteElement\"); RegionTimer rt(timer);\n      Leaf *leaf = leaf_index[pi];\n      leaf_index.Delete(pi);\n      auto & n_elements = leaf->n_elements;\n      auto & index = leaf->index;\n      auto & p = leaf->p;\n\n      for (auto i : IntRange(n_elements))\n        {\n          if(index[i] == pi)\n            {\n              n_elements--;\n              if(i!=n_elements)\n                {\n                  index[i] = index[n_elements];\n                  p[i] = p[n_elements];\n                }\n              return;\n            }\n        }\n    }\n};\n\n//   template <int dim, typename T = INDEX>\n//   class BoxTree\n//   {\n//     T_ADTree<2*dim,T> * tree;\n//     Point<dim> boxpmin, boxpmax;\n//   public:\n//     BoxTree (const Box<dim> & abox)\n//     {\n//       boxpmin = abox.PMin();\n//       boxpmax = abox.PMax();\n//       Point<2*dim> tpmin, tpmax;\n//       for (int i = 0; i < dim; i++)\n//         {\n//           tpmin(i) = tpmin(i+dim) = boxpmin(i);\n//           tpmax(i) = tpmax(i+dim) = boxpmax(i);\n//         }\n//       tree = new T_ADTree<2*dim,T> (tpmin, tpmax);\n//     }\n//\n//     BoxTree (const Point<dim> & apmin, const Point<dim> & apmax)\n//     {\n//       boxpmin = apmin;\n//       boxpmax = apmax;\n//       Point<2*dim> tpmin, tpmax;\n//       for (int i = 0; i < dim; i++)\n//         {\n//           tpmin(i) = tpmin(i+dim) = boxpmin(i);\n//           tpmax(i) = tpmax(i+dim) = boxpmax(i);\n//         }\n//       tree = new T_ADTree<2*dim,T> (tpmin, tpmax);\n//     }\n//\n//     ~BoxTree ()\n//     {\n//       delete tree;\n//     }\n//\n//     void Insert (const Point<dim> & bmin, const Point<dim> & bmax, T pi)\n//     {\n//       Point<2*dim> tp;\n//\n//       for (size_t i = 0; i < dim; i++)\n//         {\n//           tp(i) = bmin(i);\n//           tp(i+dim) = bmax(i);\n//         }\n//\n//       tree->Insert (tp, pi);\n//     }\n//\n//     void Insert (const Box<dim> & box, T pi)\n//     {\n//       Insert (box.PMin(), box.PMax(), pi);\n//     }\n//\n//     void DeleteElement (T pi)\n//     {\n//       tree->DeleteElement(pi);\n//     }\n//\n//     void GetIntersecting (const Point<dim> & pmin, const Point<dim> & pmax,\n//                           NgArray<T> & pis) const\n//     {\n//       Point<2*dim> tpmin, tpmax;\n//       double tol = Tolerance();\n//       for (size_t i = 0; i < dim; i++)\n//         {\n//           tpmin(i) = boxpmin(i);\n//           tpmax(i) = pmax(i)+tol;\n//\n//           tpmin(i+dim) = pmin(i)-tol;\n//           tpmax(i+dim) = boxpmax(i);\n//         }\n//\n//       tree->GetIntersecting (tpmin, tpmax, pis);\n//     }\n//\n//\n//     double Tolerance() const { return 1e-7 * Dist(boxpmax, boxpmin); } // single precision\n//     const auto & Tree() const { return *tree; };\n//     auto & Tree() { return *tree; };\n//   };\n\n  template<int dim, typename T=INDEX, typename TSCAL=double>\n  class DelaunayTree\n  {\n  public:\n    // Number of entries per leaf\n    static constexpr int N = 100;\n\n    struct Node;\n\n    struct Leaf\n    {\n      Point<2*dim, TSCAL> p[N];\n      T index[N];\n      int n_elements;\n      int nr;\n\n      Leaf() : n_elements(0)\n      { }\n\n\n      void Add( Array<Leaf*> &leaves, Array<T> &leaf_index, const Point<2*dim> &ap, T aindex )\n        {\n          p[n_elements] = ap;\n          index[n_elements] = aindex;\n          n_elements++;\n          if(leaf_index.Size()<aindex+1)\n              leaf_index.SetSize(aindex+1);\n          leaf_index[aindex] = nr;\n        }\n    };\n\n    struct Node\n    {\n      union\n      {\n        Node *children[2];\n        Leaf *leaf;\n      };\n      double sep;\n      int level;\n\n      Node()\n          : children{nullptr,nullptr}\n      { }\n\n      ~Node()\n       { }\n\n      Leaf *GetLeaf() const\n        {\n          return children[1] ? nullptr : leaf;\n        }\n    };\n\n  private:\n    Node root;\n\n    Array<Leaf*> leaves;\n    Array<T> leaf_index;\n\n    Point<dim> global_min, global_max;\n    double tol;\n    size_t n_leaves;\n    size_t n_nodes;\n    BlockAllocator ball_nodes;\n    BlockAllocator ball_leaves;\n\n  public:\n\n    DelaunayTree (const Point<dim> & pmin, const Point<dim> & pmax)\n        : global_min(pmin), global_max(pmax), n_leaves(1), n_nodes(1), ball_nodes(sizeof(Node)), ball_leaves(sizeof(Leaf))\n      {\n        root.leaf = (Leaf*) ball_leaves.Alloc(); new (root.leaf) Leaf();\n        root.leaf->nr = 0;\n        leaves.Append(root.leaf);\n        root.level = 0;\n        tol = 1e-7 * Dist(pmax, pmin);\n      }\n\n    DelaunayTree (const Box<dim> & box)\n        : DelaunayTree(box.PMin(), box.PMax())\n      { }\n\n    double GetTolerance() { return tol; }\n\n    size_t GetNLeaves()\n      {\n        return n_leaves;\n      }\n\n    size_t GetNNodes()\n      {\n        return n_nodes;\n      }\n\n    template<typename TFunc>\n    void GetFirstIntersecting (const Point<dim> & pmin, const Point<dim> & pmax,\n            TFunc func=[](auto pi){return false;}) const\n      {\n        // static Timer timer(\"DelaunayTree::GetIntersecting\"); RegionTimer rt(timer);\n        // static Timer timer1(\"DelaunayTree::GetIntersecting-LinearSearch\");\n        ArrayMem<const Node*, 100> stack;\n        ArrayMem<int, 100> dir_stack;\n\n\n        Point<2*dim> tpmin, tpmax;\n\n        for (size_t i : IntRange(dim))\n          {\n            tpmin(i) = global_min(i);\n            tpmax(i) = pmax(i)+tol;\n\n            tpmin(i+dim) = pmin(i)-tol;\n            tpmax(i+dim) = global_max(i);\n          }\n\n        stack.SetSize(0);\n        stack.Append(&root);\n        dir_stack.SetSize(0);\n        dir_stack.Append(0);\n\n        while(stack.Size())\n          {\n            const Node *node = stack.Last();\n            stack.DeleteLast();\n\n            int dir = dir_stack.Last();\n            dir_stack.DeleteLast();\n\n            if(Leaf *leaf = node->GetLeaf())\n              {\n                //               RegionTimer rt1(timer1);\n                for (auto i : IntRange(leaf->n_elements))\n                  {\n                    bool intersect = true;\n                    const auto p = leaf->p[i];\n\n                    for (int d = 0; d < dim; d++)\n                        if (p[d] > tpmax[d])\n                            intersect = false;\n                    for (int d = dim; d < 2*dim; d++)\n                        if (p[d] < tpmin[d])\n                            intersect = false;\n                    if(intersect)\n                        if(func(leaf->index[i])) return;\n                  }\n              }\n            else\n              {\n                int newdir = dir+1;\n                if(newdir==2*dim) newdir = 0;\n                if (tpmin[dir] <= node->sep)\n                  {\n                    stack.Append(node->children[0]);\n                    dir_stack.Append(newdir);\n                  }\n                if (tpmax[dir] >= node->sep)\n                  {\n                    stack.Append(node->children[1]);\n                    dir_stack.Append(newdir);\n                  }\n              }\n          }\n      }\n\n    void GetIntersecting (const Point<dim> & pmin, const Point<dim> & pmax,\n            NgArray<T> & pis) const\n      {\n        pis.SetSize(0);\n        GetFirstIntersecting(pmin, pmax, [&pis](auto pi) { pis.Append(pi); return false;});\n      }\n\n    void Insert (const Box<dim> & box, T pi)\n      {\n        Insert (box.PMin(), box.PMax(), pi);\n      }\n\n    void Insert (const Point<dim> & pmin, const Point<dim> & pmax, T pi)\n      {\n        // static Timer timer(\"DelaunayTree::Insert\"); RegionTimer rt(timer);\n        int dir = 0;\n        Point<2*dim> p;\n        for (auto i : IntRange(dim))\n          {\n            p(i) = pmin[i];\n            p(i+dim) = pmax[i];\n          }\n\n        Node * node = &root;\n        Leaf * leaf = node->GetLeaf();\n\n        // search correct leaf to add point\n        while(!leaf)\n          {\n            node = p[dir] < node->sep ? node->children[0] : node->children[1];\n            dir++;\n            if(dir==2*dim) dir = 0;\n            leaf = node->GetLeaf();\n          }\n\n        // add point to leaf\n        if(leaf->n_elements < N)\n            leaf->Add(leaves, leaf_index, p,pi);\n        else // assume leaf->n_elements == N\n          {\n            // add two new nodes and one new leaf\n            int n_elements = leaf->n_elements;\n            ArrayMem<TSCAL, N> coords(n_elements);\n            ArrayMem<int, N> order(n_elements);\n\n            // separate points in two halves, first sort all coordinates in direction dir\n            for (auto i : IntRange(n_elements))\n              {\n                order[i] = i;\n                coords[i] = leaf->p[i][dir];\n              }\n\n            QuickSortI(coords, order);\n            int isplit = N/2;\n            Leaf *leaf1 = (Leaf*) ball_leaves.Alloc(); new (leaf1) Leaf();\n            Leaf *leaf2 = (Leaf*) ball_leaves.Alloc(); new (leaf2) Leaf();\n\n            leaf1->nr = leaf->nr;\n            leaf2->nr = leaves.Size();\n            leaves.Append(leaf2);\n            leaves[leaf1->nr] = leaf1;\n\n            for (auto i : order.Range(0,isplit))\n                leaf1->Add(leaves, leaf_index, leaf->p[i], leaf->index[i] );\n            for (auto i : order.Range(isplit, N))\n                leaf2->Add(leaves, leaf_index, leaf->p[i], leaf->index[i] );\n\n            Node *node1 = (Node*) ball_nodes.Alloc(); new (node1) Node();\n            node1->leaf = leaf1;\n            node1->level = node->level+1;\n\n            Node *node2 = (Node*) ball_nodes.Alloc(); new (node2) Node();\n            node2->leaf = leaf2;\n            node2->level = node->level+1;\n\n            node->children[0] = node1;\n            node->children[1] = node2;\n            node->sep = 0.5 * (leaf->p[order[isplit-1]][dir] + leaf->p[order[isplit]][dir]);\n\n            // add new point to one of the new leaves\n            if (p[dir] < node->sep)\n                leaf1->Add( leaves, leaf_index, p, pi );\n            else\n                leaf2->Add( leaves, leaf_index, p, pi );\n\n            ball_leaves.Free(leaf);\n            n_leaves++;\n            n_nodes+=2;\n          }\n      }\n\n    void DeleteElement (T pi)\n      {\n        // static Timer timer(\"DelaunayTree::DeleteElement\"); RegionTimer rt(timer);\n        Leaf *leaf = leaves[leaf_index[pi]];\n        leaf_index[pi] = -1;\n        auto & n_elements = leaf->n_elements;\n        auto & index = leaf->index;\n        auto & p = leaf->p;\n\n        for (auto i : IntRange(n_elements))\n          {\n            if(index[i] == pi)\n              {\n                n_elements--;\n                if(i!=n_elements)\n                  {\n                    index[i] = index[n_elements];\n                    p[i] = p[n_elements];\n                  }\n                return;\n              }\n          }\n      }\n  };\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geom2d.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n\nnamespace netgen\n{\n\nostream & operator<<(ostream  & s, const Point2d & p)\n{\n  return s << \"(\" << p.px << \", \" << p.py << \")\";\n}\n\nostream & operator<<(ostream  & s, const Vec2d & v)\n{\n  return s << \"(\" << v.vx << \", \" << v.vy << \")\";\n}\n\n#ifdef none\nostream & operator<<(ostream  & s, const Line2d & l)\n  {\n  return s << l.p1 << \"-\" << l.p2;\n}\n\nostream & operator<<(ostream  & s, const TRIANGLE2D & t)\n{\n  return s << t.p1 << \"-\" << t.p2 << \"-\" << t.p3;\n}\n#endif\n\n\ndouble Fastatan2 (double x, double y)\n{\n  if (y > 0)\n    {\n      if (x > 0)\n\treturn y / (x+y);\n      else\n\treturn 1 - x / (y-x);\n    }\n  else if (y < 0)\n    {\n      if (x < 0)\n\treturn 2 + y / (x+y);\n      else\n\treturn 3 - x / (y-x);\n    }\n  else \n    {\n      if (x >= 0)\n\treturn 0;\n      else\n\treturn 2;\n    }\n}\n\n\ndouble Angle (const Vec2d & v)\n{\n  if (v.X() == 0 && v.Y() == 0)\n    return 0;\n    \n  double ang = atan2 (v.Y(), v.X());\n  if (ang < 0) ang+= 2 * M_PI;\n  return ang;\n}\n\ndouble FastAngle (const Vec2d & v)\n{\n  return Fastatan2 (v.X(), v.Y());\n}\n\ndouble Angle (const Vec2d & v1, const Vec2d & v2)\n{\n  double ang = Angle(v2) - Angle(v1);\n  if (ang < 0) ang += 2 * M_PI;\n  return ang;\n}\n\ndouble FastAngle (const Vec2d & v1, const Vec2d & v2)\n{\n  double ang = FastAngle(v2) - FastAngle(v1);\n  if (ang < 0) ang += 4;\n  return ang;\n}\n\n/*\nint CW (const Point2d & p1,const Point2d & p2,const Point2d & p3)\n{\n  return Cross (p2 - p1, p3 - p2) < 0;\n}\n\nint CCW (const Point2d & p1,const Point2d & p2,const Point2d & p3)\n{\n  return Cross (p2 - p1, p3 - p2) > 0;\n}\n*/\n\ndouble  Dist2(const Line2d & g, const Line2d & h )\n  {\n  double   dd = 0.0, d1,d2,d3,d4;\n  Point2d  cp = CrossPoint(g,h);\n  \n  if ( Parallel(g,h) || !IsOnLine(g,cp) || !IsOnLine(h,cp) )\n    {\n      d1 = Dist2(g.P1(),h.P1());\n      d2 = Dist2(g.P1(),h.P2());\n      d3 = Dist2(g.P2(),h.P1());\n      d4 = Dist2(g.P2(),h.P2());\n      if (d1<d2)  d2 = d1;\n      if (d3<d4)  d4 = d3;\n      dd = ( d2 < d4 ) ? d2 : d4;\n    }\n  return dd;\n}\n\n\nPoint2d CrossPoint (const Line2d & l1, const Line2d & l2)\n  {\n  double den = Cross (l1.Delta(), l2.Delta());\n  double num = Cross ( (l2.P1() - l1.P1()), l2.Delta());\n\n  if (den == 0)\n    return l1.P1();\n  else\n    return l1.P1() + (num/den) * l1.Delta();\n}\n\n\nint CrossPointBarycentric (const Line2d & l1, const Line2d & l2,\n\t\t\t   double & lam1, double & lam2, double eps)\n{\n  // p = l1.1 + lam1 (l1.2-l1.1) = l2.1 + lam2 (l2.2-l2.1)\n  double a11 = l1.p2.X() - l1.p1.X();\n  double a21 = l1.p2.Y() - l1.p1.Y();\n  double a12 = -(l2.p2.X() - l2.p1.X());\n  double a22 = -(l2.p2.Y() - l2.p1.Y());\n\n  double b1 = l2.p1.X() - l1.p1.X();\n  double b2 = l2.p1.Y() - l1.p1.Y();\n  \n  double det = a11*a22 - a12 * a21;\n  /*\n  if (det == 0)\n    return 1;\n  */\n  if (fabs (det) < eps * (fabs(a11*a22)+fabs(a12*a21))) return 1;\n    \n  lam1 = (a22 * b1 - a12 * b2) / det;\n  lam2 = (a11 * b2 - a21 * b1) / det;\n  return 0;\n}\n\n\n\n\nint Parallel (const Line2d & l1, const Line2d & l2, double peps)\n  {\n  double p = fabs (Cross (l1.Delta(), l2.Delta()));\n  //  (*mycout) << endl << p << \"  \" <<  l1.Length() << \"  \" << l2.Length() << endl;\n  return p <= peps * l1.Length() * l2.Length();\n}\n\nint IsOnLine (const Line2d & l, const Point2d & p, double heps)\n  {\n  double c1 = (p - l.P1()) * l.Delta();\n  double c2 = (p - l.P2()) * l.Delta();\n  double d = fabs (Cross ( (p - l.P1()), l.Delta()));\n  double len2 = l.Length2();\n\n  return c1 >= -heps * len2 && c2 <= heps * len2 && d <= heps * len2;\n}\n\n#ifdef none\nint IsOnLine (const PLine2d & l, const Point2d & p, double heps)\n  {\n  double c1 = (p - l.P1()) * l.Delta();\n  double c2 = (p - l.P2()) * l.Delta();\n  double d = fabs (Cross ( (p - l.P1()), l.Delta()));\n  double len2 = l.Length2();\n\n  return c1 >= -heps * len2 && c2 <= heps * len2 && d <= heps * len2;\n}\n\nint IsOnLongLine (const Line2d & l, const Point2d & p)\n  {\n  double d = fabs (Cross ( (p - l.P1()), l.Delta()));\n  return d <= EPSGEOM * l.Length();\n}\n\nint Hit (const Line2d & l1, const Line2d & l2, double heps)\n  {\n  double den =  Cross ( (l1.P2() - l1.P1()), (l2.P1() - l2.P2()));\n  double num1 = Cross ( (l2.P1() - l1.P1()), (l2.P1() - l2.P2()));\n  double num2 = Cross ( (l1.P2() - l1.P1()), (l2.P1() - l1.P1()));\n  num1 *= sgn (den);\n  num2 *= sgn (den);\n  den = fabs (den);\n\n  int ch = (-den * heps <= num1 && num1 <= den * (1 + heps) &&\n\t    -den * heps <= num2 && num2 <= den * (1 + heps));\n  return ch;\n}\n\n\nvoid Line2d :: GetNormal (Line2d & n) const\n{\n  double \tax  = P2().X()-P1().X(),\n    ay  = P2().Y()-P1().Y();\n  Point2d \tmid(P1().X()+.5*ax, P1().Y()+.5*ay);\n \n n=Line2d(mid,Point2d(mid.X()+ay,mid.Y()-ax)) ;\n}\n\nVec2d Line2d :: NormalDelta () const\n{\n Line2d tmp;\n GetNormal(tmp);\n return tmp.Delta();\n}\n\nint TRIANGLE2D :: IsOn (const Point2d & p) const\n  {\n  return IsOnLine (Line2d (p1, p2), p) ||\n         IsOnLine (Line2d (p1, p3), p) ||\n         IsOnLine (Line2d (p2, p3), p);\n  }\n\n\nint TRIANGLE2D :: IsIn (const Point2d & p) const\n{\n  return ::CW(p, p1, p2) == ::CW(p, p2, p3) &&\n         ::CW(p, p1, p2) == ::CW(p, p3, p1);\n}\n\n\n\nint PTRIANGLE2D :: IsOn (const Point2d & p) const\n{\n  return IsOnLine (Line2d (*p1, *p2), p) ||\n         IsOnLine (Line2d (*p1, *p3), p) ||\n         IsOnLine (Line2d (*p2, *p3), p);\n}\n\n\nint PTRIANGLE2D :: IsIn (const Point2d & p) const\n{\n  return ::CW(p, *p1, *p2) == ::CW(p, *p2, *p3) &&\n         ::CW(p, *p1, *p2) == ::CW(p, *p3, *p1);\n}\n\n#endif\n}\n"
  },
  {
    "path": "libsrc/gprim/geom2d.hpp",
    "content": "#ifndef FILE_GEOM2D\n#define FILE_GEOM2D\n\n/* *************************************************************************/\n/* File:   geom2d.hh                                                       */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   5. Aug. 95                                                      */\n/* *************************************************************************/\n\n#include <mydefs.hpp>\n\n#include <general/template.hpp>\n#include \"geomobjects.hpp\"\n#include <meshing/global.hpp>\n\nnamespace netgen \n{\n\n  /* Geometric Algorithms */\n\n#define EPSGEOM 1E-5\n\n\n  DLL_HEADER void MyError (const char * ch);\n\n  class Point2d;\n  class Vec2d;\n\n  class LINE2D;\n  class Line2d;\n  class PLine2d;\n  class TRIANGLE2D;\n  class PTRIANGLE2D;\n\n\n  inline Vec2d operator- (const Point2d & p1, const Point2d & p2);\n  inline Point2d operator- (const Point2d & p1, const Vec2d & v);\n  inline Point2d operator+ (const Point2d & p1, const Vec2d & v);\n  inline Point2d Center (const Point2d & p1, const Point2d & p2);\n\n  inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);\n  inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);\n  ostream & operator<<(ostream  & s, const Point2d & p);\n  inline Vec2d operator- (const Point2d & p1, const Point2d & p2);\n  inline Point2d operator- (const Point2d & p1, const Vec2d & v);\n  inline Point2d operator+ (const Point2d & p1, const Vec2d & v);\n  inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);\n  inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);\n  inline Vec2d operator* (double scal, const Vec2d & v);\n  DLL_HEADER double Angle (const Vec2d & v);\n  DLL_HEADER double FastAngle (const Vec2d & v);\n  DLL_HEADER double Angle (const Vec2d & v1, const Vec2d & v2);\n  DLL_HEADER double FastAngle (const Vec2d & v1, const Vec2d & v2);\n  ostream & operator<<(ostream  & s, const Vec2d & v);\n  double Dist2(const Line2d & g, const Line2d & h );\t\t// GH\n  int Near (const Point2d & p1, const Point2d & p2, const double eps);\n\n  int Parallel (const Line2d & l1, const Line2d & l2, double peps = EPSGEOM);\n  int IsOnLine (const Line2d & l, const Point2d & p, double heps = EPSGEOM);\n  int IsOnLongLine (const Line2d & l, const Point2d & p);\n  int Hit (const Line2d & l1, const Line2d & l2, double heps = EPSGEOM);\n  ostream & operator<<(ostream  & s, const Line2d & l);\n  DLL_HEADER Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);\n  DLL_HEADER Point2d CrossPoint (const Line2d & l1, const Line2d & l2);\n  int Parallel (const PLine2d & l1, const PLine2d & l2, double peps = EPSGEOM);\n  int IsOnLine (const PLine2d & l, const Point2d & p, double heps = EPSGEOM);\n  int IsOnLongLine (const PLine2d & l, const Point2d & p);\n  int Hit (const PLine2d & l1, const Line2d & l2, double heps = EPSGEOM);\n  ostream & operator<<(ostream  & s, const Line2d & l);\n  ostream & operator<<(ostream  & s, const TRIANGLE2D & t); \n  ostream & operator<<(ostream & s, const PTRIANGLE2D & t);\n  double Dist2 (const Point2d & p1, const Point2d & p2);\n\n  ///\n  class Point2d\n  {\n    ///\n    friend class Vec2d;\n\n  protected:\n    ///\n    double px, py;\n\n  public:\n    ///\n    Point2d() { /* px = py = 0; */ }\n    ///\n    Point2d(double ax, double ay) { px = ax; py = ay; }\n    ///\n    Point2d(const Point2d & p2) { px = p2.px; py = p2.py; }\n\n    Point2d (const Point<2> & p2)\n    {\n      px = p2(0);\n      py = p2(1);\n    }\n    ///\n    Point2d & operator= (const Point2d & p2)\n    { px = p2.px; py = p2.py; return *this; }\n    \n    ///\n    int operator== (const Point2d & p2) const\t\t\t// GH\n    { return (px == p2.px  &&  py == p2.py) ; }\n\n    ///\n    double & X() { return px; }\n    ///\n    double & Y() { return py; }\n    ///\n    double X() const { return px; }\n    ///\n    double Y() const { return py; }\n\n    operator Point<2> () const\n    {\n      return Point<2> (px, py);\n    }\n\n\n    ///\n    friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);\n    ///\n    friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);\n    ///\n    friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);\n\n    ///\n    friend inline Point2d Center (const Point2d & p1, const Point2d & p2);\n\n    const Point2d & SetToMin (const Point2d & p2)\n    {\n      if (p2.px < px) px = p2.px;\n      if (p2.py < py) py = p2.py;\n      return *this;\n    }\n\n\n    ///\n    const Point2d & SetToMax (const Point2d & p2)\n    {\n      if (p2.px > px) px = p2.px;\n      if (p2.py > py) py = p2.py;\n      return *this;\n    }\n\n    ///\n    friend double Dist (const Point2d & p1, const Point2d & p2)\n    { return sqrt ( (p1.px - p2.px) * (p1.px - p2.px) +\n\t\t    (p1.py - p2.py) * (p1.py - p2.py) ); }\n    //    { return sqrt ( sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ); }\n\n    ///\n    friend double Dist2 (const Point2d & p1, const Point2d & p2)\n    { return ( (p1.px - p2.px) * (p1.px - p2.px) +\n\t       (p1.py - p2.py) * (p1.py - p2.py) ); }\n    //    { return sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ; }\n\n\n    /**\n       Points clock-wise ?\n       Are the points (p1, p2, p3) clock-wise ?\n    */\n    friend inline int CW (const Point2d & p1, const Point2d & p2, const Point2d & p3)\n    {\n      //      return Cross (p2 - p1, p3 - p2) < 0;      \n      return\n\t(p2.px - p1.px) * (p3.py - p2.py) - \n\t(p2.py - p1.py) * (p3.px - p2.px) < 0;\n    }\n    /**\n       Points counter-clock-wise ?\n       Are the points (p1, p2, p3) counter-clock-wise ?\n    */\n    friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3)\n    {\n      //      return Cross (p2 - p1, p3 - p2) > 0;\n      return\n\t(p2.px - p1.px) * (p3.py - p2.py) - \n\t(p2.py - p1.py) * (p3.px - p2.px) > 0;\n    }  /**\n\t  Points counter-clock-wise ?\n\t  Are the points (p1, p2, p3) counter-clock-wise ?\n       */\n    friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3, double eps)\n    {\n      //      return Cross (p2 - p1, p3 - p2) > 0;\n      double ax = p2.px - p1.px;\n      double ay = p2.py - p1.py;\n      double bx = p3.px - p2.px;\n      double by = p3.py - p2.py;\n\n      return ax*by - ay*bx > eps*eps*max2(ax*ax+ay*ay,bx*bx+by*by);\n    }\n\n    ///\n    friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);\n    ///\n    friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);\n\n    ///\n    friend ostream & operator<<(ostream  & s, const Point2d & p);\n  };\n\n\n  inline int Near (const Point2d & p1, const Point2d & p2, \n\t\t   const double eps = 1e-4 )\n  { \n    return  Dist2(p1,p2) <= eps*eps; \n  }\n\n\n\n\n\n\n  ///\n  class Vec2d\n  {\n  protected:\n    ///\n    double vx, vy;\n\n  public:\n    ///\n    Vec2d() { /* vx = vy = 0; */ }\n    ///\n    Vec2d(double ax, double ay)\n    { vx = ax; vy = ay; }\n    ///\n    Vec2d(const Vec2d & v2) { vx = v2.vx; vy = v2.vy; }\n\n    ///\n    explicit Vec2d(const Vec<2> & v2) { vx = v2(0); vy = v2(1); }\n\n    ///\n    Vec2d(const Point2d & p1, const Point2d & p2)\n    { vx = p2.px - p1.px; vy = p2.py - p1.py; }\n    \n    ///\n    Vec2d & operator= (const Vec2d & p2)\n    { vx = p2.vx; vy = p2.vy; return *this; }\n\n    ///\n    double & X() { return vx; }\n    ///\n    double & Y() { return vy; }\n    ///\n    double X() const { return vx; }\n    ///\n    double Y() const { return vy; }\n\n    ///\n    double Length() const { return sqrt (vx * vx + vy * vy); }\n    ///\n    double Length2() const { return vx * vx + vy * vy; }\n\n    void GetNormal (Vec2d & n) const { n.vx=-vy; n.vy=vx; }\t\t// GH\n\n    ///\n    inline Vec2d & operator+= (const Vec2d & v2);\n    ///\n    inline Vec2d & operator-= (const Vec2d & v2);\n    ///\n    inline Vec2d & operator*= (double s);\n    ///\n    inline Vec2d & operator/= (double s);\n\n    ///\n    friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);\n    ///\n    friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);\n    ///\n    friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);\n    ///\n    friend inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);\n    ///\n    friend inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);\n    ///\n    friend inline Vec2d operator* (double scal, const Vec2d & v);\n\n    ///\n    friend double operator* (const Vec2d & v1, const Vec2d & v2)\n    { return v1.X() * v2.X() + v1.Y() * v2.Y(); }\n\n\n    ///\n    friend double Cross (const Vec2d & v1, const Vec2d & v2)\n    { return double(v1.X()) * double(v2.Y()) -\n\tdouble(v1.Y()) * double(v2.X()); }\n\n    ///\n    friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);\n    ///\n    friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);\n\n    ///\t\t\t\t\t\tAngle in [0,2*PI)\n\n    ///\n    friend DLL_HEADER double Angle (const Vec2d & v);\n    ///\n    friend DLL_HEADER double FastAngle (const Vec2d & v);\n    ///\n    friend DLL_HEADER double Angle (const Vec2d & v1, const Vec2d & v2);\n    ///\n    friend DLL_HEADER double FastAngle (const Vec2d & v1, const Vec2d & v2);\n\n    ///\n    friend ostream & operator<<(ostream  & s, const Vec2d & v);\n  };\n\n\n\n  ///\n  class Line2d\n  {\n  protected:\n    ///\n    Point2d p1, p2;\n\n  public:\n    ///\n    Line2d() : p1(), p2() { };\n    ///\n    Line2d(const Point2d & ap1, const Point2d & ap2)\n    { p1 = ap1; p2 = ap2; }\n\n    ///\n    Line2d & operator= (const Line2d & l2)\n    { p1 = l2.p1; p2 = l2.p2; return *this;}\n\n    ///\n    Point2d & P1() { return p1; }\n    ///\n    Point2d & P2() { return p2; }\n    ///\n    const Point2d & P1() const { return p1; }\n    ///\n    const Point2d & P2() const { return p2; }\n\n    ///\n    double XMax() const { return max2 (p1.X(), p2.X()); }\n    ///\n    double YMax() const { return max2 (p1.Y(), p2.Y()); }\n    ///\n    double XMin() const { return min2 (p1.X(), p2.X()); }\n    ///\n    double YMin() const { return min2 (p1.Y(), p2.Y()); }\n\n    ///\n    Vec2d Delta () const { return Vec2d (p2.X()-p1.X(), p2.Y()-p1.Y()); }\n    ///\n    double Length () const { return Delta().Length(); }\n    ///\n    double Length2 () const\n    { return sqr (p1.X() - p2.X()) +\n\tsqr (p1.Y() - p2.Y()); }\n\n    void GetNormal (Line2d & n) const;\t\t\t\t\t// GH\n    Vec2d NormalDelta () const;\t\t\t\t\t\t// GH\n\n    /// square of the distance between two 2d-lines.\n    friend double Dist2(const Line2d & g, const Line2d & h );\t\t// GH\n\n    ///\n    friend DLL_HEADER Point2d CrossPoint (const Line2d & l1, const Line2d & l2);\n    /// returns 1 iff parallel\n    friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,\n\t\t\t\t      double & lam1, double & lam2, double eps);\n    \n    ///\n    friend int Parallel (const Line2d & l1, const Line2d & l2, double peps);\n    ///\n    friend int IsOnLine (const Line2d & l, const Point2d & p, double heps);\n    ///\n    friend int IsOnLongLine (const Line2d & l, const Point2d & p);\n    ///\n    friend int Hit (const Line2d & l1, const Line2d & l2, double heps);\n\n    ///\n    friend ostream & operator<<(ostream  & s, const Line2d & l);\n  };\n\n\n#ifdef NONE\n  ///\n  class PLine2d\n  {\n  protected:\n    ///\n    Point2d const * p1, *p2;\n\n  public:\n    ///\n    PLine2d() { };\n    ///\n    PLine2d(Point2d const * ap1, Point2d const * ap2)\n    { p1 = ap1; p2 = ap2; }\n\n    ///\n    PLine2d & operator= (const PLine2d & l2)\n    { p1 = l2.p1; p2 = l2.p2; return *this;}\n\n    ///\n    const Point2d *& P1() { return p1; }\n    ///\n    const Point2d *& P2() { return p2; }\n    ///\n    const Point2d & P1() const { return *p1; }\n    ///\n    const Point2d & P2() const { return *p2; }\n\n    ///\n    double XMax() const { return max2 (p1->X(), p2->X()); }\n    ///\n    double YMax() const { return max2 (p1->Y(), p2->Y()); }\n    ///\n    double XMin() const { return min2 (p1->X(), p2->X()); }\n    ///\n    double YMin() const { return min2 (p1->Y(), p2->Y()); }\n\n\n    ///\n    Vec2d Delta () const { return Vec2d (p2->X()-p1->X(), p2->Y()-p1->Y()); }\n    ///\n    double Length () const { return Delta().Length(); }\n    ///\n    double Length2 () const\n    { return sqr (p1->X() - p2->X()) +\n\tsqr (p1->Y() - p2->Y()); }\n\n\n    \n    ///\n    friend Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);\n    ///\n    friend int Parallel (const PLine2d & l1, const PLine2d & l2, double peps);\n    ///\n    friend int IsOnLine (const PLine2d & l, const Point2d & p, double heps);\n    ///\n    friend int IsOnLongLine (const PLine2d & l, const Point2d & p);\n    ///\n    friend int Hit (const PLine2d & l1, const Line2d & l2, double heps);\n\n    ///\n    friend ostream & operator<<(ostream  & s, const Line2d & l);\n  };\n\n\n\n  ///\n  class ILINE\n  {\n    ///\n    INDEX i[2];\n\n  public:\n    ///\n    ILINE() {};\n    ///\n    ILINE(INDEX i1, INDEX i2) { i[0] = i1; i[1] = i2; }\n    ///\n    ILINE(const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; }\n\n    ///\n    ILINE & operator= (const ILINE & l)\n    { i[0] = l.i[0]; i[1] = l.i[1]; return *this; }\n\n    ///\n    const INDEX & I(int ai) const { return i[ai-1]; }\n    ///\n    const INDEX & X() const { return i[0]; }\n    ///\n    const INDEX & Y() const { return i[1]; }\n    ///\n    const INDEX & I1() const { return i[0]; }\n    ///\n    const INDEX & I2() const { return i[1]; }\n\n    ///\n    INDEX & I(int ai) { return i[ai-1]; }\n    ///\n    INDEX & X() { return i[0]; }\n    ///\n    INDEX & Y() { return i[1]; }\n    ///\n    INDEX & I1() { return i[0]; }\n    ///\n    INDEX & I2() { return i[1]; }\n  };\n\n\n\n\n  ///\n  class TRIANGLE2D\n  {\n  private:\n    ///\n    Point2d p1, p2, p3;\n\n  public:\n    ///\n    TRIANGLE2D() { };\n    ///\n    TRIANGLE2D (const Point2d & ap1, const Point2d & ap2,\n\t\tconst Point2d & ap3)\n    { p1 = ap1; p2 = ap2; p3 = ap3;}\n\n    ///\n    TRIANGLE2D & operator= (const TRIANGLE2D & t2)\n    { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }\n\n    ///\n    Point2d & P1() { return p1; }\n    ///\n    Point2d & P2() { return p2; }\n    ///\n    Point2d & P3() { return p3; }\n    ///\n    const Point2d & P1() const { return p1; }\n    ///\n    const Point2d & P2() const { return p2; }\n    ///\n    const Point2d & P3() const { return p3; }\n\n    ///\n    double XMax() const { return max3 (p1.X(), p2.X(), p3.X()); }\n    ///\n    double YMax() const { return max3 (p1.Y(), p2.Y(), p3.Y()); }\n    ///\n    double XMin() const { return min3 (p1.X(), p2.X(), p3.X()); }\n    ///\n    double YMin() const { return min3 (p1.Y(), p2.Y(), p3.Y()); }\n\n    ///\n    inline Point2d Center () const\n    { return Point2d( (p1.X()+p2.X()+p3.X())/3, (p1.Y()+p2.Y()+p3.Y())/3); }\n\n    ///\n    int Regular() const;\n    /// \n    int CW () const;\n    ///\n    int CCW () const;\n\n    ///\n    int IsOn (const Point2d & p) const;\n    ///\n    int IsIn (const Point2d & p) const;\n    ///\n    friend ostream & operator<<(ostream  & s, const TRIANGLE2D & t);\n  };\n\n\n  ///\n  class PTRIANGLE2D\n  {\n  private:\n    ///\n    Point2d const *p1, *p2, *p3;\n\n  public:\n    ///\n    PTRIANGLE2D() { };\n    ///\n    PTRIANGLE2D (const Point2d * ap1, const Point2d * ap2,\n\t\t const Point2d * ap3)\n    { p1 = ap1; p2 = ap2; p3 = ap3;}\n\n    ///\n    PTRIANGLE2D & operator= (const PTRIANGLE2D & t2)\n    { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }\n\n    ///\n    const Point2d *& P1() { return p1; }\n    ///\n    const Point2d *& P2() { return p2; }\n    ///\n    const Point2d *& P3() { return p3; }\n    ///\n    const Point2d * P1() const { return p1; }\n    ///\n    const Point2d * P2() const { return p2; }\n    ///\n    const Point2d * P3() const { return p3; }\n\n    ///\n    double XMax() const { return max3 (p1->X(), p2->X(), p3->X()); }\n    ///\n    double YMax() const { return max3 (p1->Y(), p2->Y(), p3->Y()); }\n    ///\n    double XMin() const { return min3 (p1->X(), p2->X(), p3->X()); }\n    ///\n    double YMin() const { return min3 (p1->Y(), p2->Y(), p3->Y()); }\n\n    ///\n    Point2d Center () const\n    { return Point2d( (p1->X()+p2->X()+p3->X())/3, (p1->Y()+p2->Y()+p3->Y())/3); }\n\n\n    ///\n    int Regular() const;\n    ///\n    int CW () const;\n    ///\n    int CCW () const;\n\n    ///\n    int IsOn (const Point2d & p) const;\n    ///\n    int IsIn (const Point2d & p) const;\n    ///\n    friend ostream & operator<<(ostream & s, const PTRIANGLE2D & t);\n  };\n#endif\n\n\n  /** Cheap approximation to atan2.\n      A monotone function of atan2(x,y) is computed.\n  */\n  extern double Fastatan2 (double x, double y);\n\n\n  inline Vec2d & Vec2d :: operator+= (const Vec2d & v2)\n  {\n    vx += v2.vx;\n    vy += v2.vy;\n    return *this;\n  }\n\n  inline Vec2d & Vec2d :: operator-= (const Vec2d & v2)\n  {\n    vx -= v2.vx;\n    vy -= v2.vy;\n    return *this;\n  }\n\n  inline Vec2d & Vec2d :: operator*= (double s)\n  {\n    vx *= s;\n    vy *= s;\n    return *this;\n  }\n\n\n  inline Vec2d & Vec2d :: operator/= (double s)\n  {\n    if (s != 0)\n      {\n\tvx /= s;\n\tvy /= s;\n      }\n    else\n      {\n\tMyError (\"Vec2d::operator /=: Division by zero\");\n      }\n    return *this;\n  }\n\n\n\n  inline Vec2d operator- (const Point2d & p1, const Point2d & p2)\n  {\n    return Vec2d (p1.X() - p2.X(), p1.Y() - p2.Y());\n  }\n\n\n  inline Point2d operator- (const Point2d & p1, const Vec2d & v)\n  {\n    return Point2d (p1.X() - v.X(), p1.Y() - v.Y());\n  }\n\n\n  inline Point2d operator+ (const Point2d & p1, const Vec2d & v)\n  {\n    return Point2d (p1.X() + v.X(), p1.Y() + v.Y());\n  }\n\n\n  inline Point2d Center (const Point2d & p1, const Point2d & p2)\n  {\n    return Point2d ((p1.X() + p2.X()) / 2, (p1.Y() + p2.Y()) / 2);\n  }\n\n\n  inline Vec2d operator- (const Vec2d & v1, const Vec2d & v2)\n  {\n    return Vec2d (v1.X() - v2.X(), v1.Y() - v2.Y());\n  }\n\n\n  inline Vec2d operator+ (const Vec2d & v1, const Vec2d & v2)\n  {\n    return Vec2d (v1.X() + v2.X(), v1.Y() + v2.Y());\n  }\n\n\n  inline Vec2d operator* (double scal, const Vec2d & v)\n  {\n    return Vec2d (scal * v.X(), scal * v.Y());\n  }\n\n\n  inline void PpSmV (const Point2d & p1, double s,\n\t\t     const Vec2d & v, Point2d & p2)\n  {\n    p2.X() = p1.X() + s * v.X();\n    p2.Y() = p1.Y() + s * v.Y();\n  }\n\n\n  inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v)\n  {\n    v.X() = p1.X() - p2.X();\n    v.Y() = p1.Y() - p2.Y();\n  }\n\n\n\n\n\n#ifdef none\n  inline int TRIANGLE2D :: Regular() const\n  {\n    return fabs(Cross ( p2 - p1, p3 - p2)) > EPSGEOM;\n  }\n\n\n  inline int TRIANGLE2D :: CW () const\n  {\n    return Cross ( p2 - p1, p3 - p2) < 0;\n  }\n\n\n  inline int TRIANGLE2D :: CCW () const\n  {\n    return Cross ( p2 - p1, p3 - p2) > 0;\n  }\n\n\n\n\n  inline int PTRIANGLE2D :: Regular() const\n  {\n    return fabs(Cross ( *p2 - *p1, *p3 - *p2)) > EPSGEOM;\n  }\n\n\n  inline int PTRIANGLE2D :: CW () const\n  {\n    return Cross ( *p2 - *p1, *p3 - *p2) < 0;\n  }\n\n\n  inline int PTRIANGLE2D :: CCW () const\n  {\n    return Cross ( *p2 - *p1, *p3 - *p2) > 0;\n  }\n\n\n#endif\n\n\n  ///\n  class Mat2d\n  {\n  protected:\n    ///\n    double coeff[4];\n\n  public:\n    ///\n    Mat2d() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; }\n    ///\n    Mat2d(double a11, double a12, double a21, double a22)\n    { coeff[0] = a11; coeff[1] = a12; coeff[2] = a21; coeff[3] = a22; }\n    ///\n    Mat2d(const Mat2d & m2)\n    { for (int i = 0; i < 4; i++) coeff[i] = m2.Get(i); }\n\n    ///\n    double & Elem (INDEX i, INDEX j) { return coeff[2*(i-1)+j-1]; }\n    ///\n    double & Elem (INDEX i) {return coeff[i]; }\n    ///\n    double Get (INDEX i, INDEX j) const { return coeff[2*(i-1)+j-1]; }\n    ///\n    double Get (INDEX i) const {return coeff[i]; }\n\n    ///  \n    double Det () const { return coeff[0] * coeff[3] - coeff[1] * coeff[2]; }\n\n    ///\n    void Mult (const Vec2d & v, Vec2d & prod) const;\n    ///\n    void MultTrans (const Vec2d & v , Vec2d & prod) const;\n    ///\n    void Solve (const Vec2d & rhs, Vec2d & x) const;\n    /// Solves mat * x = rhs, but using a positive definite matrix instead of mat\n    void SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const;\n    /// add a term \\alpha * v * v^T\n    void AddDiadicProduct (double alpha, Vec2d & v);\n  };\n\n\n\n  inline void Mat2d :: Mult (const Vec2d & v, Vec2d & prod) const\n  {\n    prod.X() = coeff[0] * v.X() + coeff[1] * v.Y();\n    prod.Y() = coeff[2] * v.X() + coeff[3] * v.Y();\n  }\n\n\n  inline  void Mat2d :: MultTrans (const Vec2d & v, Vec2d & prod) const\n  {\n    prod.X() = coeff[0] * v.X() + coeff[2] * v.Y();\n    prod.Y() = coeff[1] * v.X() + coeff[3] * v.Y();\n  }\n\n\n\n  inline void Mat2d :: Solve (const Vec2d & rhs, Vec2d & x) const\n  {\n    double det = Det();\n  \n    if (det == 0)\n      MyError (\"Mat2d::Solve: zero determinant\");\n    else\n      {\n\tx.X() = (coeff[3] * rhs.X() - coeff[1] * rhs.Y()) / det;\n\tx.Y() = (-coeff[2] * rhs.X() + coeff[0] * rhs.Y()) / det;\n      }\n  }\n\n\n  inline void Mat2d :: SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const\n  {\n    double a = max2(coeff[0], 1e-8);\n    double b = coeff[1] / a;\n    double c = coeff[2] / a;\n    double d = max2(coeff[3] - a *b * c, 1e-8);\n\n    x.X() = (rhs.X() - b * rhs.Y()) / a;\n    x.Y() = rhs.Y() / d - c * x.X();\n  }\n\n\n  inline void Mat2d :: AddDiadicProduct (double alpha, Vec2d & v)\n  {\n    coeff[0] += alpha * v.X() * v.X();\n    coeff[1] += alpha * v.X() * v.Y();\n    coeff[2] += alpha * v.Y() * v.X();\n    coeff[3] += alpha * v.Y() * v.Y();\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geom3d.cpp",
    "content": "#include <algorithm>\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n\nnamespace netgen\n{\nostream & operator<<(ostream  & s, const Point3d & p)\n  {\n  return s << \"(\" << p.x[0] << \", \" << p.x[1] << \", \" << p.x[2] << \")\";\n  }\n\nostream & operator<<(ostream  & s, const Vec3d & v)\n  {\n  return s << \"(\" << v.x[0] << \", \" << v.x[1] << \", \" << v.x[2] << \")\";\n  }\n\ndouble Angle (const Vec3d & v1, const Vec3d & v2)\n{\n  double co = (v1 * v2) / (v1.Length() * v2.Length());\n  if (co > 1) co = 1;\n  if (co < -1) co = -1;\n  return acos ( co );\n}\n\n\nvoid Vec3d :: GetNormal (Vec3d & n) const\n  {\n  if (fabs (X()) > fabs (Z()))\n    {\n    n.X() = -Y();\n    n.Y() = X();\n    n.Z() = 0;\n    }\n  else\n    {\n    n.X() = 0;\n    n.Y() = Z();\n    n.Z() = -Y();\n    }\n  double len = n.Length();\n  if (len == 0)\n    {\n    n.X() = 1;\n    n.Y() = n.Z() = 0;\n    }\n  else\n    n /= len;\n  }\n\n/*\nostream & operator<<(ostream  & s, const ROTDenseMatrix3D & r)\n  {\n  return s << \"{ (\" << r.txx << \", \" << r.txy << \", \" << r.txz << \") , (\"\n                    << r.tyx << \", \" << r.tyy << \", \" << r.tyz << \") , (\"\n                    << r.tzx << \", \" << r.tzy << \", \" << r.tzz << \") }\";\n  }\n*/\n\n/*\nVec3d operator- (const Point3d & p1, const Point3d & p2)\n  {\n  return Vec3d (p1.X() - p2.X(), p1.Y() - p2.Y(),p1.Z() - p2.Z());\n  }\n\nPoint3d operator- (const Point3d & p1, const Vec3d & v)\n  {\n  return Point3d (p1.X() - v.X(), p1.Y() - v.Y(),p1.Z() - v.Z());\n  }\n\nPoint3d operator+ (const Point3d & p1, const Vec3d & v)\n  {\n  return Point3d (p1.X() + v.X(), p1.Y() + v.Y(),p1.Z() + v.Z());\n  }\n\nVec3d operator- (const Vec3d & v1, const Vec3d & v2)\n  {\n  return Vec3d (v1.X() - v2.X(), v1.Y() - v2.Y(),v1.Z() - v2.Z());\n  }\n\nVec3d operator+ (const Vec3d & v1, const Vec3d & v2)\n  {\n  return Vec3d (v1.X() + v2.X(), v1.Y() + v2.Y(),v1.Z() + v2.Z());\n  }\n\nVec3d operator* (double scal, const Vec3d & v)\n  {\n  return Vec3d (scal * v.X(), scal * v.Y(), scal * v.Z());\n  }\n*/\n/*\ndouble operator* (const Vec3d & v1, const Vec3d & v2)\n  {\n  return v1.X() * v2.X() + v1.Y() * v2.Y() + v1.Z() * v2.Z();\n  }\n\ndouble Cross (const Vec3d & v1, const Vec3d & v2)\n  {\n  return v1.X() * v2.Y() - v1.Y() * v2.X();\n  }\n*/\n\n/*\nvoid ROTDenseMatrix3D :: CalcRotMat(double ag, double bg, double lg, double size2, Vec3d r)\n  {\n  size = size2;\n  txx=size * ( cos(bg) * cos(lg) );\n  txy=size * ( cos(bg) * sin(lg) );\n  txz=size * (-sin(bg)           );\n\n  tyx=size * ( sin(ag) * sin(bg) * cos(lg) - cos(ag) * sin(lg) );\n  tyy=size * ( sin(ag) * sin(bg) * sin(lg) + cos(ag) * cos(lg) );\n  tyz=size * ( sin(ag) * cos(bg)                               );\n\n  tzx=size * ( cos(ag) * sin(bg) * cos(lg) + sin(ag) * sin(lg) );\n  tzy=size * ( cos(ag) * sin(bg) * sin(lg) - sin(ag) * cos(lg) );\n  tzz=size * ( cos(ag) * cos(bg)                               );\n\n  deltaR=r;\n  }\nROTDenseMatrix3D :: ROTDenseMatrix3D(double ag, double bg, double lg, double size2, Vec3d r)\n  {CalcRotMat(ag, bg, lg, size2, r); }\n\nROTDenseMatrix3D :: ROTDenseMatrix3D(Vec3d rot2)\n  {\n  Vec3d r2(0,0,0);\n  CalcRotMat(rot2.X(), rot2.Y(), rot2.Z(), 1, r2);\n  }\n\nROTDenseMatrix3D ROTDenseMatrix3D :: INV()\n  {\n  ROTDenseMatrix3D rinv(txx/sqr(size),tyx/sqr(size),tzx/sqr(size),\n                   txy/sqr(size),tyy/sqr(size),tzy/sqr(size),\n                   txz/sqr(size),tyz/sqr(size),tzz/sqr(size),\n                   1/size,deltaR);\n  return rinv;\n  }\n\nVec3d operator* (const ROTDenseMatrix3D & r, const Vec3d & v)\n  {\n  return Vec3d (r.XX() * v.X() + r.XY() * v.Y() + r.XZ() * v.Z(),\n                r.YX() * v.X() + r.YY() * v.Y() + r.YZ() * v.Z(),\n                r.ZX() * v.X() + r.ZY() * v.Y() + r.ZZ() * v.Z() );\n  }\n\nPoint3d operator* (const ROTDenseMatrix3D & r, const Point3d & p)\n  {\n  return Point3d (r.XX() * p.X() + r.XY() * p.Y() + r.XZ() * p.Z(),\n                  r.YX() * p.X() + r.YY() * p.Y() + r.YZ() * p.Z(),\n                  r.ZX() * p.X() + r.ZY() * p.Y() + r.ZZ() * p.Z() );\n  }\n*/\n\n\n\n\n\n\n\nBox3d :: Box3d ( double aminx, double amaxx,\n                 double aminy, double amaxy,\n                 double aminz, double amaxz )\n{\n  minx[0] = aminx; maxx[0] = amaxx;\n  minx[1] = aminy; maxx[1] = amaxy;\n  minx[2] = aminz; maxx[2] = amaxz;\n}\n\nBox3d :: Box3d ( const Box3d & b2 )\n{\n  for (int i = 0; i < 3; i++)\n    {\n      minx[i] = b2.minx[i];\n      maxx[i] = b2.maxx[i];\n    }\n}\n\nBox3d :: Box3d ( const Box<3> & b2 )\n{\n  for (int i = 0; i < 3; i++)\n    {\n      minx[i] = b2.PMin()(i);\n      maxx[i] = b2.PMax()(i);\n    }\n}\n\n\n/*\nint Box3d :: Intersect (const Box3d & box2) const\n{\n  int i;\n  for (i = 0; i <= 2; i++)\n    if (minx[i] > box2.maxx[i] || maxx[i] < box2.minx[i])\n      return 0;\n  return 1;\n}\n*/\n\n/*\nvoid Box3d :: SetPoint (const Point3d & p)\n{\n  minx[0] = maxx[0] = p.X();\n  minx[1] = maxx[1] = p.Y();\n  minx[2] = maxx[2] = p.Z();\n}\n\nvoid Box3d :: AddPoint (const Point3d & p)\n{\n  if (p.X() < minx[0]) minx[0] = p.X();\n  if (p.X() > maxx[0]) maxx[0] = p.X();\n  if (p.Y() < minx[1]) minx[1] = p.Y();\n  if (p.Y() > maxx[1]) maxx[1] = p.Y();\n  if (p.Z() < minx[2]) minx[2] = p.Z();\n  if (p.Z() > maxx[2]) maxx[2] = p.Z();\n}\n*/\n\nvoid Box3d :: GetPointNr (int i, Point3d & point) const\n{\n  i--;\n  point.X() = (i & 1) ? maxx[0] : minx[0];\n  point.Y() = (i & 2) ? maxx[1] : minx[1];\n  point.Z() = (i & 4) ? maxx[2] : minx[2];\n}\n\n\nvoid Box3d :: Increase (double d)\n{\n  for (int i = 0; i <= 2; i++)\n    {\n      minx[i] -= d;\n      maxx[i] += d;\n    }\n}\n\nvoid Box3d :: IncreaseRel (double /* rel */)\n{\n  for (int i = 0; i <= 2; i++)\n    {\n      double d = 0.5 * (maxx[i] - minx[i]);\n      minx[i] -= d;\n      maxx[i] += d;\n    }\n}\n\n\nBox3d :: Box3d (const Point3d& p1, const Point3d& p2)\n{\n  minx[0] = min2 (p1.X(), p2.X());\n  minx[1] = min2 (p1.Y(), p2.Y());\n  minx[2] = min2 (p1.Z(), p2.Z());\n  maxx[0] = max2 (p1.X(), p2.X());\n  maxx[1] = max2 (p1.Y(), p2.Y());\n  maxx[2] = max2 (p1.Z(), p2.Z());\n}\n\nconst Box3d& Box3d :: operator+=(const Box3d& b)\n{\n  minx[0] = min2 (minx[0], b.minx[0]);\n  minx[1] = min2 (minx[1], b.minx[1]);\n  minx[2] = min2 (minx[2], b.minx[2]);\n  maxx[0] = max2 (maxx[0], b.maxx[0]);\n  maxx[1] = max2 (maxx[1], b.maxx[1]);\n  maxx[2] = max2 (maxx[2], b.maxx[2]);\n\n  return *this;\n}\n\nPoint3d Box3d :: MaxCoords() const\n{\n  return Point3d(maxx[0], maxx[1], maxx[2]);\n}\n\nPoint3d Box3d :: MinCoords() const\n{\n  return Point3d(minx[0], minx[1], minx[2]);\n}\n\n/*\nvoid Box3d :: CreateNegMinMaxBox()\n{\n  minx[0] = MAXDOUBLE;\n  minx[1] = MAXDOUBLE;\n  minx[2] = MAXDOUBLE;\n  maxx[0] = MINDOUBLE;\n  maxx[1] = MINDOUBLE;\n  maxx[2] = MINDOUBLE;\n\n}\n*/\n\nvoid Box3d :: WriteData(ofstream& fout) const\n{\n  for(int i = 0; i < 3; i++)\n    {\n      fout << minx[i] << \" \" << maxx[i] << \" \";\n    }\n  fout << \"\\n\";\n}\n\nvoid Box3d :: ReadData(ifstream& fin)\n{\n  for(int i = 0; i < 3; i++)\n    {\n      fin >> minx[i];\n      fin >> maxx[i];\n    }\n}\n\n\n\n\nBox3dSphere :: Box3dSphere ( double aminx, double amaxx,\n\t\t\t     double aminy, double amaxy,\n\t\t\t     double aminz, double amaxz )\n  : Box3d (aminx, amaxx, aminy, amaxy, aminz, amaxz)\n{\n  CalcDiamCenter ();\n}\n\n\nvoid Box3dSphere :: CalcDiamCenter ()\n{\n  diam = sqrt( sqr (maxx[0] - minx[0]) +\n\t       sqr (maxx[1] - minx[1]) + \n\t       sqr (maxx[2] - minx[2]));\n  \n  c.X() = 0.5 * (minx[0] + maxx[0]);\n  c.Y() = 0.5 * (minx[1] + maxx[1]);\n  c.Z() = 0.5 * (minx[2] + maxx[2]);\n  \n  inner = min2 ( min2 (maxx[0] - minx[0], maxx[1] - minx[1]), maxx[2] - minx[2]) / 2;\n}\n\n\nvoid Box3dSphere :: GetSubBox (int i, Box3dSphere & sbox) const\n{\n  i--;\n  if (i & 1)\n    {\n      sbox.minx[0] = c.X();\n      sbox.maxx[0] = maxx[0];\n    }\n  else\n    {\n      sbox.minx[0] = minx[0];\n      sbox.maxx[0] = c.X();\n    }\n  if (i & 2)\n    {\n      sbox.minx[1] = c.Y();\n      sbox.maxx[1] = maxx[1];\n    }\n  else\n    {\n      sbox.minx[1] = minx[1];\n      sbox.maxx[1] = c.Y();\n    }\n  if (i & 4)\n    {\n      sbox.minx[2] = c.Z();\n      sbox.maxx[2] = maxx[2];\n    }\n  else\n    {\n      sbox.minx[2] = minx[2];\n      sbox.maxx[2] = c.Z();\n    }\n  \n  //  sbox.CalcDiamCenter ();\n\n  sbox.c.X() = 0.5 * (sbox.minx[0] + sbox.maxx[0]);\n  sbox.c.Y() = 0.5 * (sbox.minx[1] + sbox.maxx[1]);\n  sbox.c.Z() = 0.5 * (sbox.minx[2] + sbox.maxx[2]);\n  sbox.diam = 0.5 * diam;\n  sbox.inner = 0.5 * inner;\n}\n\n\n\n\n/*\ndouble Determinant (const Vec3d & col1,\n\t\t    const Vec3d & col2,\n\t\t    const Vec3d & col3)\n{\n  return\n    col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) +\n    col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) +\n    col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]);\n}\n*/\n\nvoid Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3)\n{\n  Swap (v1.Y(), v2.X());\n  Swap (v1.Z(), v3.X());\n  Swap (v2.Z(), v3.Y());\n}\n\n\n/*\n  gcc4.8.3  warning: array subscript is above array bounds [-Warray-bounds]\n */\n#ifdef __GNUC__\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n#endif\n\nint SolveLinearSystem (const Vec3d & col1, const Vec3d & col2,\n\t\t       const Vec3d & col3, const Vec3d & rhs,\n\t\t       Vec3d & sol)\n{\n  // changed by MW\n  double matrix[3][3];\n  double locrhs[3];\n  int retval = 0;\n\n  for(int i=0; i<3; i++)\n    {\n      matrix[i][0] = col1.X(i+1);\n      matrix[i][1] = col2.X(i+1);\n      matrix[i][2] = col3.X(i+1);\n      locrhs[i] = rhs.X(i+1);\n    }\n\n  for(int i=0; i<2; i++)\n    {\n      int pivot = i;\n      double maxv = fabs(matrix[i][i]);\n      for(int j=i+1; j<3; j++)\n\tif(fabs(matrix[j][i]) > maxv)\n\t  {\n\t    maxv = fabs(matrix[j][i]);\n\t    pivot = j;\n\t  }\n\n      if(fabs(maxv) > 1e-40)\n\t{\n\t  if(pivot != i)\n\t    {\n\t      swap(matrix[i][0],matrix[pivot][0]);\n\t      swap(matrix[i][1],matrix[pivot][1]);\n\t      swap(matrix[i][2],matrix[pivot][2]);\n\t      swap(locrhs[i],locrhs[pivot]);\n\t    }\n\t  for(int j=i+1; j<3; j++)\n\t    {\n\t      double fac = matrix[j][i] / matrix[i][i];\n\t      \n\t      for(int k=i+1; k<3; k++)\n\t\tmatrix[j][k] -= fac*matrix[i][k];\n\t      locrhs[j] -= fac*locrhs[i];\n\t    }\n\t}\n      else\n\tretval = 1;\n    }\n\n  if(fabs(matrix[2][2]) < 1e-40)\n    retval = 1;\n\n  if(retval != 0)\n    return retval;\n  \n\n  for(int i=2; i>=0; i--)\n    {\n      double sum = locrhs[i];\n      for(int j=2; j>i; j--)\n\tsum -= matrix[i][j]*sol.X(j+1);\n\n      sol.X(i+1) = sum/matrix[i][i];\n    }\n\n  return 0;\n  \n  \n  \n\n\n  /*\n  double det = Determinant (col1, col2, col3);\n  if (fabs (det) < 1e-40)\n    return 1;\n  \n  sol.X() = Determinant (rhs, col2, col3) / det;\n  sol.Y() = Determinant (col1, rhs, col3) / det;\n  sol.Z() = Determinant (col1, col2, rhs) / det;\n\n  return 0;\n  */\n  /*\n  Vec3d cr;\n  Cross (col1, col2, cr);\n  double det = cr * col3;\n\n  if (fabs (det) < 1e-40)\n    return 1;\n\n  if (fabs(cr.Z()) > 1e-12)\n    {\n      // solve for 3. component\n      sol.Z() = (cr * rhs) / det;\n      \n      // 2x2 system for 1. and 2. component\n      double res1 = rhs.X() - sol.Z() * col3.X();\n      double res2 = rhs.Y() - sol.Z() * col3.Y();\n      \n      sol.X() = (col2.Y() * res1 - col2.X() * res2) / cr.Z();\n      sol.Y() = (col1.X() * res2 - col1.Y() * res1) / cr.Z();\n  \n    }\n  else\n    {\n      det = Determinant (col1, col2, col3);\n      if (fabs (det) < 1e-40)\n\treturn 1;\n      \n      sol.X() = Determinant (rhs, col2, col3) / det;\n      sol.Y() = Determinant (col1, rhs, col3) / det;\n      sol.Z() = Determinant (col1, col2, rhs) / det;\n    }\n\n  return 0;\n  */\n}\n\n#ifdef __GNUC__\n#pragma GCC diagnostic pop\n#endif\n\n\n\nint SolveLinearSystemLS (const Vec3d & col1,\n\t\t\t const Vec3d & col2,\n\t\t\t const Vec2d & rhs,\n\t\t\t Vec3d & sol)\n{\n  double a11 = col1 * col1;\n  double a12 = col1 * col2;\n  double a22 = col2 * col2;\n  \n  double det = a11 * a22 - a12 * a12;\n\n  if (det*det <= 1e-24 * a11 * a22)\n    {\n      sol = Vec3d (0, 0, 0);\n      return 1;\n    }\n  \n  Vec2d invrhs;\n  invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det;\n  invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det;\n\n  sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X();\n  sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y();\n  sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z();\n\n  return 0;\n\n  /*\n  Vec3d inv1, inv2;\n  int err = \n    PseudoInverse (col1, col2, inv1, inv2);\n\n   sol = rhs.X() * inv1 + rhs.Y() * inv2;\n   return err;\n  */\n}\n\nint SolveLinearSystemLS2 (const Vec3d & col1,\n\t\t\t const Vec3d & col2,\n\t\t\t const Vec2d & rhs,\n\t\t\t Vec3d & sol, double & x, double & y)\n{\n  double a11 = col1 * col1;\n  double a12 = col1 * col2;\n  double a22 = col2 * col2;\n  \n  double det = a11 * a22 - a12 * a12;\n\n  if (fabs (det) <= 1e-12 * col1.Length() * col2.Length() || \n      col1.Length2() == 0 || col2.Length2() == 0)\n    {\n      sol = Vec3d (0, 0, 0);\n      x = 0; y = 0;\n      return 1;\n    }\n  \n  Vec2d invrhs;\n  invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det;\n  invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det;\n\n  sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X();\n  sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y();\n  sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z();\n\n  x = invrhs.X();\n  y = invrhs.Y();\n\n  return 0;\n\n  /*\n  Vec3d inv1, inv2;\n  int err = \n    PseudoInverse (col1, col2, inv1, inv2);\n\n   sol = rhs.X() * inv1 + rhs.Y() * inv2;\n   return err;\n  */\n}\n\nint PseudoInverse (const Vec3d & col1,\n\t\t   const Vec3d & col2,\n\t\t   Vec3d & inv1,\n\t\t   Vec3d & inv2)\n{\n  double a11 = col1 * col1;\n  double a12 = col1 * col2;\n  double a22 = col2 * col2;\n  \n  double det = a11 * a22 - a12 * a12;\n\n  if (fabs (det) < 1e-12 * col1.Length() * col2.Length())\n    {\n      inv1 = Vec3d (0, 0, 0);\n      inv2 = Vec3d (0, 0, 0);\n      return 1;\n    }\n\n  double ia11 = a22 / det;\n  double ia12 = -a12 / det;\n  double ia22 = a11 / det;\n\n  inv1 = ia11 * col1 + ia12 * col2;\n  inv2 = ia12 * col1 + ia22 * col2;\n\n  return 0;\n}\n\n\n\n\nQuadraticFunction3d :: \nQuadraticFunction3d (const Point3d & p, const Vec3d & v)\n{\n  Vec3d hv(v);\n  hv /= (hv.Length() + 1e-12);\n  Vec3d t1, t2;\n  hv.GetNormal (t1);\n  Cross (hv, t1, t2);\n  \n  double t1p = t1.X() * p.X() + t1.Y() * p.Y() + t1.Z() * p.Z();\n  double t2p = t2.X() * p.X() + t2.Y() * p.Y() + t2.Z() * p.Z();\n  c0 = sqr (t1p) + sqr (t2p);\n  cx = -2 * (t1p * t1.X() + t2p * t2.X());\n  cy = -2 * (t1p * t1.Y() + t2p * t2.Y());\n  cz = -2 * (t1p * t1.Z() + t2p * t2.Z());\n\n  cxx = t1.X() * t1.X() + t2.X() * t2.X();\n  cyy = t1.Y() * t1.Y() + t2.Y() * t2.Y();\n  czz = t1.Z() * t1.Z() + t2.Z() * t2.Z();\n\n  cxy = 2 * t1.X() * t1.Y() + 2 * t2.X() * t2.Y();\n  cxz = 2 * t1.X() * t1.Z() + 2 * t2.X() * t2.Z();\n  cyz = 2 * t1.Y() * t1.Z() + 2 * t2.Y() * t2.Z();\n\n  /*\n  (*testout) << \"c0 = \" << c0\n\t     << \" clin = \" << cx << \" \" << cy << \" \" << cz \n\t     << \" cq = \" << cxx << \" \" << cyy << \" \" << czz\n\t     << cxy << \" \" << cyz << \" \" << cyz << endl;\n  */\n}\n\n// QuadraticFunction3d gqf (Point3d (0,0,0), Vec3d (1, 0, 0));\n\n\n\n\n\nvoid referencetransform :: Set (const Point3d & p1, const Point3d & p2,\n                                const Point3d & p3, double ah)\n{\n  ex = p2 - p1;\n  ex /= ex.Length();\n  ey = p3 - p1;\n  ey -= (ex * ey) * ex;\n  ey /= ey.Length();\n  ez = Cross (ex, ey);\n  rp = p1;\n  h = ah;\n\n  exh = ah * ex;\n  eyh = ah * ey;\n  ezh = ah * ez;\n  ah = 1 / ah;\n  ex_h = ah * ex;\n  ey_h = ah * ey;\n  ez_h = ah * ez;\n}\n\nvoid referencetransform :: ToPlain (const Point3d & p, Point3d & pp) const\n{\n  Vec3d v;\n  v = p - rp;\n  pp.X() = (ex_h * v);\n  pp.Y() = (ey_h * v);\n  pp.Z() = (ez_h * v);\n}\n\nvoid referencetransform :: ToPlain (const NgArray<Point3d> & p,\n                                    NgArray<Point3d> & pp) const\n{\n  Vec3d v;\n  int i;\n\n  pp.SetSize (p.Size());\n  for (i = 1; i <= p.Size(); i++)\n    {\n      v = p.Get(i) - rp;\n      pp.Elem(i).X() = (ex_h * v);\n      pp.Elem(i).Y() = (ey_h * v);\n      pp.Elem(i).Z() = (ez_h * v);\n    }\n}\n\nvoid referencetransform :: FromPlain (const Point3d & pp, Point3d & p) const\n{\n  Vec3d v;\n  //  v = (h * pp.X()) * ex + (h * pp.Y()) * ey + (h * pp.Z()) * ez;\n  //  p = rp + v;\n  v.X() = pp.X() * exh.X() + pp.Y() * eyh.X() + pp.Z() * ezh.X();\n  v.Y() = pp.X() * exh.Y() + pp.Y() * eyh.Y() + pp.Z() * ezh.Y();\n  v.Z() = pp.X() * exh.Z() + pp.Y() * eyh.Z() + pp.Z() * ezh.Z();\n  p.X() = rp.X() + v.X();\n  p.Y() = rp.Y() + v.Y();\n  p.Z() = rp.Z() + v.Z();\n}\n\n\n}\n"
  },
  {
    "path": "libsrc/gprim/geom3d.hpp",
    "content": "#ifndef FILE_GEOM3D\n#define FILE_GEOM3D\n\n/* *************************************************************************/\n/* File:   geom3d.hh                                                       */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   5. Aug. 95                                                      */\n/* *************************************************************************/\n\n#include <mydefs.hpp>\n#include \"geom2d.hpp\"\n\nnamespace netgen\n{\n\n\n  extern DLL_HEADER void MyError (const char * ch);\n\n  class Point3d;\n  class Vec3d;\n\n  inline Vec3d operator- (const Point3d & p1, const Point3d & p2);\n  inline Point3d operator- (const Point3d & p1, const Vec3d & v);\n  inline Point3d operator+ (const Point3d & p1, const Vec3d & v);\n  Point3d & Add (double d, const Vec3d & v);\n  Point3d & Add2 (double d, const Vec3d & v,\n\t\t  double d2, const Vec3d & v2);\n  inline Point3d Center (const Point3d & p1, const Point3d & p2);\n  inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3);\n  inline Point3d Center (const Point3d & p1, const Point3d & p2, \n\t\t\t const Point3d & p3, const Point3d & p4);\n  ostream & operator<<(ostream  & s, const Point3d & p);\n  inline Vec3d operator- (const Vec3d & p1, const Vec3d & v);\n  inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v);\n  inline Vec3d operator* (double scal, const Vec3d & v);\n  inline double operator* (const Vec3d & v1, const Vec3d & v2);\n  inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2);\n  inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod);\n  double Angle (const Vec3d & v);\n  double FastAngle (const Vec3d & v);\n  double Angle (const Vec3d & v1, const Vec3d & v2);\n  double FastAngle (const Vec3d & v1, const Vec3d & v2);\n  ostream & operator<<(ostream  & s, const Vec3d & v);\n  void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3);\n  int SolveLinearSystem (const Vec3d & col1,\n\t\t\t const Vec3d & col2,\n\t\t\t const Vec3d & col3,\n\t\t\t const Vec3d & rhs,\n\t\t\t Vec3d & sol);\n  int SolveLinearSystemLS (const Vec3d & col1,\n\t\t\t   const Vec3d & col2,\n\t\t\t   const Vec2d & rhs,\n\t\t\t   Vec3d & sol);\n  int SolveLinearSystemLS2 (const Vec3d & col1,\n\t\t\t    const Vec3d & col2,\n\t\t\t    const Vec2d & rhs, \n\t\t\t    Vec3d & sol,\n\t\t\t    double & x, double & y);\n  int PseudoInverse (const Vec3d & col1,\n\t\t     const Vec3d & col2,\n\t\t     Vec3d & inv1,\n\t\t     Vec3d & inv2);\n  double Determinant (const Vec3d & col1,\n\t\t      const Vec3d & col2,\n\t\t      const Vec3d & col3);\n\n  inline double Dist2 (const Point3d & p1, const Point3d & p2);\n\n  /// Point in R3\n  class Point3d\n  {\n  protected:\n    ///\n    double x[3];\n  \n  public:\n    ///\n    Point3d () { x[0] = x[1] = x[2] = 0; }\n    ///\n    Point3d(double ax, double ay, double az) \n    { x[0] = ax; x[1] = ay; x[2] = az; }\n    ///\n    Point3d(double ax[3])\n    { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; }\n\n    ///\n    Point3d(const Point3d & p2) \n    { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; }\n\n    Point3d (const Point<3> & p2)\n    {\n      for (int i = 0; i < 3; i++)\n\tx[i] = p2(i);\n    }\n  \n    ///\n    Point3d & operator= (const Point3d & p2)\n    { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; return *this; }\n  \n    ///\n    int operator== (const Point3d& p) const\n    { return (x[0] == p.x[0] && x[1] == p.x[1] && x[2] == p.x[2]); }\n  \n    ///\n    double & X() { return x[0]; }\n    ///\n    double & Y() { return x[1]; }\n    ///\n    double & Z() { return x[2]; }\n    ///\n    double X() const { return x[0]; }\n    ///\n    double Y() const { return x[1]; }\n    ///\n    double Z() const { return x[2]; }\n    ///\n    double & X(int i) { return x[i-1]; }\n    ///\n    double X(int i) const { return x[i-1]; }\n    ///\n    const Point3d & SetToMin (const Point3d & p2)\n    {\n      if (p2.x[0] < x[0]) x[0] = p2.x[0];\n      if (p2.x[1] < x[1]) x[1] = p2.x[1];\n      if (p2.x[2] < x[2]) x[2] = p2.x[2];\n      return *this;\n    }\n\n    ///\n    const Point3d & SetToMax (const Point3d & p2)\n    {\n      if (p2.x[0] > x[0]) x[0] = p2.x[0];\n      if (p2.x[1] > x[1]) x[1] = p2.x[1];\n      if (p2.x[2] > x[2]) x[2] = p2.x[2];\n      return *this;\n    }\n\n    ///\n    friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2);\n    ///\n    friend inline Point3d operator- (const Point3d & p1, const Vec3d & v);\n    ///\n    friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v);\n    ///\n    inline Point3d & operator+= (const Vec3d & v);\n    inline Point3d & operator-= (const Vec3d & v);\n    ///\n    inline Point3d & Add (double d, const Vec3d & v);\n    ///\n    inline Point3d & Add2 (double d, const Vec3d & v,\n\t\t\t   double d2, const Vec3d & v2);\n    ///\n    friend inline double Dist (const Point3d & p1, const Point3d & p2)\n    { return sqrt (  (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + \n\t\t     (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) +\n                     (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); }\n    ///\n    inline friend double Dist2 (const Point3d & p1, const Point3d & p2)\n    { return  (  (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + \n\t\t (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) +\n\t\t (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); }\n\n    ///\n    friend inline Point3d Center (const Point3d & p1, const Point3d & p2);\n    ///\n    friend inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3);\n    ///\n    friend inline Point3d Center (const Point3d & p1, const Point3d & p2, \n\t\t\t\t  const Point3d & p3, const Point3d & p4);\n    ///\n    friend ostream & operator<<(ostream  & s, const Point3d & p);\n  \n    ///\n    friend class Vec3d;\n    ///\n    friend class Box3d;\n\n\n    operator Point<3> () const\n    {\n      return Point<3> (x[0], x[1], x[2]);\n    }\n  };\n\n\n  ///\n  class Vec3d\n  {\n  protected:\n    ///\n    double x[3];\n\n  public:\n    ///\n    inline Vec3d() { x[0] = x[1] = x[2] = 0; }\n    ///\n    inline Vec3d(double ax, double ay, double az)\n    { x[0] = ax; x[1] = ay; x[2] = az; }\n    ///\n    Vec3d(double ax[3])\n    { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; }\n    ///\n    inline Vec3d(const Vec3d & v2) \n    { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; }\n    ///\n    inline Vec3d(const Point3d & p1, const Point3d & p2)\n    { \n      x[0] = p2.x[0] - p1.x[0];\n      x[1] = p2.x[1] - p1.x[1];\n      x[2] = p2.x[2] - p1.x[2]; \n    }\n    ///\n    inline Vec3d(const Point3d & p1)\n    { \n      x[0] = p1.x[0];\n      x[1] = p1.x[1];\n      x[2] = p1.x[2];\n    }\n  \n    Vec3d (const Vec<3> & v2)\n    {\n      for (int i = 0; i < 3; i++)\n\tx[i] = v2(i);\n    }\n\n    operator Vec<3> () const\n    {\n      return Vec<3> (x[0], x[1], x[2]);\n    }\n\n\n    Vec3d & operator= (const Vec3d & v2)\n    { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; return *this; }\n    ///\n    Vec3d & operator= (double val)\n    { x[0] = x[1] = x[2] = val; return *this; }\n    ///\n    double & X() { return x[0]; }\n    ///\n    double & Y() { return x[1]; }\n    ///\n    double & Z() { return x[2]; }\n    ///\n    double & X(int i) { return x[i-1]; }\n\n    ///\n    double X() const { return x[0]; }\n    ///\n    double Y() const { return x[1]; }\n    ///\n    double Z() const { return x[2]; }\n    ///\n    double X(int i) const { return x[i-1]; }\n\n    ///\n    double Length() const \n    { return sqrt (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); }\n    ///\n    double Length2() const \n    { return x[0] * x[0] + x[1] * x[1] + x[2] * x[2]; }\n\n    ///\n    inline friend double Dist (const Vec3d & v1, const Vec3d & v2)\n    { return sqrt (  (v1.x[0]-v2.x[0]) * (v1.x[0]-v2.x[0]) + \n\t\t     (v1.x[1]-v2.x[1]) * (v1.x[1]-v2.x[1]) +\n                     (v1.x[2]-v2.x[2]) * (v1.x[2]-v2.x[2])); }\n    ///\n    inline friend double Dist2 (const Vec3d & v1, const Vec3d & v2)\n    { return  (  (v1.x[0]-v2.x[0]) * (v1.x[0]-v2.x[0]) + \n\t\t (v1.x[1]-v2.x[1]) * (v1.x[1]-v2.x[1]) +\n\t\t (v1.x[2]-v2.x[2]) * (v1.x[2]-v2.x[2])); }\n\n    ///\n    Vec3d & operator+= (const Vec3d & v2);\n    ///\n    Vec3d & operator-= (const Vec3d & v2);\n    ///\n    Vec3d & operator*= (double s);\n    ///\n    Vec3d & operator/= (double s);\n    ///\n    inline Vec3d & Add (double d, const Vec3d & v);\n    ///\n    inline Vec3d & Add2 (double d, const Vec3d & v,\n\t\t\t double d2, const Vec3d & v2);\n\n    ///\n    friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2);\n    ///\n    friend inline Point3d operator- (const Point3d & p1, const Vec3d & v);\n    ///\n    friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v);\n    ///\n    friend inline Vec3d operator- (const Vec3d & p1, const Vec3d & v);\n    ///\n    friend inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v);\n    ///\n    friend inline Vec3d operator* (double scal, const Vec3d & v);\n\n    ///\n    friend inline double operator* (const Vec3d & v1, const Vec3d & v2);\n    ///\n    friend inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2);\n    ///\n    friend inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod);\n\n    /// Returns one normal-vector to n\n    DLL_HEADER void GetNormal (Vec3d & n) const;\n    ///\n    friend double Angle (const Vec3d & v);\n    ///\n    friend double FastAngle (const Vec3d & v);\n    ///\n    friend double Angle (const Vec3d & v1, const Vec3d & v2);\n    ///\n    friend double FastAngle (const Vec3d & v1, const Vec3d & v2);\n\n    void Normalize() \n    {\n      double len = (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);\n      if (len == 0) return;\n      len = sqrt (len);\n      x[0] /= len; x[1] /= len; x[2] /= len;\n    }\n\n    ///\n    friend ostream & operator<<(ostream  & s, const Vec3d & v);\n\n    ///\n    friend class Point3d;\n    friend void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3);\n    friend int SolveLinearSystem (const Vec3d & col1,\n\t\t\t\t  const Vec3d & col2,\n\t\t\t\t  const Vec3d & col3,\n\t\t\t\t  const Vec3d & rhs,\n\t\t\t\t  Vec3d & sol);\n    friend int SolveLinearSystemLS (const Vec3d & col1,\n\t\t\t\t    const Vec3d & col2,\n\t\t\t\t    const Vec2d & rhs,\n\t\t\t\t    Vec3d & sol);\n    friend int SolveLinearSystemLS2 (const Vec3d & col1,\n\t\t\t\t     const Vec3d & col2,\n\t\t\t\t     const Vec2d & rhs, \n\t\t\t\t     Vec3d & sol,\n\t\t\t\t     double & x, double & y);\n    friend int PseudoInverse (const Vec3d & col1,\n\t\t\t      const Vec3d & col2,\n\t\t\t      Vec3d & inv1,\n\t\t\t      Vec3d & inv2);\n    friend double Determinant (const Vec3d & col1,\n\t\t\t       const Vec3d & col2,\n\t\t\t       const Vec3d & col3);\n  };\n\n\n\n  class QuadraticFunction3d\n  {\n    double c0, cx, cy, cz;\n    double cxx, cyy, czz, cxy, cxz, cyz;\n\n  public:\n    QuadraticFunction3d (const Point3d & p, const Vec3d & v);\n    double Eval (const Point3d & p)\n    {\n      return \n\tc0 \n\t+ p.X() * (cx + cxx * p.X() + cxy * p.Y() + cxz * p.Z())\n\t+ p.Y() * (cy + cyy * p.Y() + cyz * p.Z())\n\t+ p.Z() * (cz + czz * p.Z());\n    }\n  };\n\n\n\n  inline Point3d Center (const Point3d & p1, const Point3d & p2)\n  {\n    return Point3d (0.5 * (p1.x[0] + p2.x[0]),\n\t\t    0.5 * (p1.x[1] + p2.x[1]),\n\t\t    0.5 * (p1.x[2] + p2.x[2]));\n  }\n\n\n  inline Point3d Center (const Point3d & p1, const Point3d & p2,\n\t\t\t const Point3d & p3)\n  {\n    return Point3d (1.0/3.0 * (p1.x[0] + p2.x[0] + p3.x[0]),\n\t\t    1.0/3.0 * (p1.x[1] + p2.x[1] + p3.x[1]),\n\t\t    1.0/3.0 * (p1.x[2] + p2.x[2] + p3.x[2]));\n  }\n\n  inline Point3d Center (const Point3d & p1, const Point3d & p2,\n\t\t\t const Point3d & p3, const Point3d & p4)\n  {\n    return Point3d (0.25 * (p1.x[0] + p2.x[0] + p3.x[0] + p4.x[0]),\n\t\t    0.25 * (p1.x[1] + p2.x[1] + p3.x[1] + p4.x[1]),\n\t\t    0.25 * (p1.x[2] + p2.x[2] + p3.x[2] + p4.x[2]));\n  }\n\n\n\n  inline Vec3d & Vec3d :: operator+= (const Vec3d & v2)\n  {\n    x[0] += v2.x[0];\n    x[1] += v2.x[1];\n    x[2] += v2.x[2];\n    return *this;\n  }\n\n  inline Vec3d & Vec3d :: operator-= (const Vec3d & v2)\n  {\n    x[0] -= v2.x[0];\n    x[1] -= v2.x[1];\n    x[2] -= v2.x[2];\n    return *this;\n  }\n\n\n  inline Vec3d & Vec3d :: operator*= (double s)\n  {\n    x[0] *= s;\n    x[1] *= s;\n    x[2] *= s;\n    return *this;\n  }\n\n\n  inline Vec3d & Vec3d :: operator/= (double s)\n  {\n    if (s != 0)\n      {\n\tx[0] /= s;\n\tx[1] /= s;\n\tx[2] /= s;\n      }\n#ifdef DEBUG\n    else\n      {\n\tcerr << \"Vec div by 0, v = \" << (*this) << endl;\n\t//      MyError (\"Vec3d::operator /=: Divisioin by zero\");\n      }\n#endif\n    return *this;\n  }\n\n  inline Vec3d & Vec3d::Add (double d, const Vec3d & v)\n  {\n    x[0] += d * v.x[0]; \n    x[1] += d * v.x[1]; \n    x[2] += d * v.x[2];\n    return *this;\n  }\n\n  inline Vec3d & Vec3d::Add2 (double d, const Vec3d & v,\n\t\t\t      double d2, const Vec3d & v2)\n  {\n    x[0] += d * v.x[0] + d2 * v2.x[0]; \n    x[1] += d * v.x[1] + d2 * v2.x[1]; \n    x[2] += d * v.x[2] + d2 * v2.x[2]; \n    return *this;\n  }\n\n\n\n\n\n\n\n\n  inline Vec3d operator- (const Point3d & p1, const Point3d & p2)\n  {\n    return Vec3d (p1.x[0] - p2.x[0], p1.x[1] - p2.x[1],p1.x[2] - p2.x[2]);\n  }\n\n\n  inline Point3d operator- (const Point3d & p1, const Vec3d & v)\n  {\n    return Point3d (p1.x[0] - v.x[0], p1.x[1] - v.x[1],p1.x[2] - v.x[2]);\n  }\n\n\n  inline Point3d operator+ (const Point3d & p1, const Vec3d & v)\n  {\n    return Point3d (p1.x[0] + v.x[0], p1.x[1] + v.x[1],p1.x[2] + v.x[2]);\n  }\n\n  inline Point3d & Point3d::operator+= (const Vec3d & v) \n  {\n    x[0] += v.x[0]; \n    x[1] += v.x[1]; \n    x[2] += v.x[2];\n    return *this;\n  }\n\n  inline Point3d & Point3d::operator-= (const Vec3d & v) \n  {\n    x[0] -= v.x[0]; \n    x[1] -= v.x[1]; \n    x[2] -= v.x[2];\n    return *this;\n  }\n\n  inline Point3d & Point3d::Add (double d, const Vec3d & v)\n  {\n    x[0] += d * v.x[0]; \n    x[1] += d * v.x[1]; \n    x[2] += d * v.x[2];\n    return *this;\n  }\n\n  inline Point3d & Point3d::Add2 (double d, const Vec3d & v,\n\t\t\t\t  double d2, const Vec3d & v2)\n  {\n    x[0] += d * v.x[0] + d2 * v2.x[0]; \n    x[1] += d * v.x[1] + d2 * v2.x[1]; \n    x[2] += d * v.x[2] + d2 * v2.x[2]; \n    return *this;\n  }\n\n\n  inline Vec3d operator- (const Vec3d & v1, const Vec3d & v2)\n  {\n    return Vec3d (v1.x[0] - v2.x[0], v1.x[1] - v2.x[1],v1.x[2] - v2.x[2]);\n  }\n\n\n  inline Vec3d operator+ (const Vec3d & v1, const Vec3d & v2)\n  {\n    return Vec3d (v1.x[0] + v2.x[0], v1.x[1] + v2.x[1],v1.x[2] + v2.x[2]);\n  }\n\n\n  inline Vec3d operator* (double scal, const Vec3d & v)\n  {\n    return Vec3d (scal * v.x[0], scal * v.x[1], scal * v.x[2]);\n  }\n\n\n\n  inline double operator* (const Vec3d & v1, const Vec3d & v2)\n  {\n    return v1.x[0] * v2.x[0] + v1.x[1] * v2.x[1] + v1.x[2] * v2.x[2];\n  }\n\n\n\n  inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2)\n  {\n    return Vec3d\n      ( v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1],\n\tv1.x[2] * v2.x[0] - v1.x[0] * v2.x[2],\n\tv1.x[0] * v2.x[1] - v1.x[1] * v2.x[0]);\n  }\n\n  inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod)\n  {\n    prod.x[0] = v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1];\n    prod.x[1] = v1.x[2] * v2.x[0] - v1.x[0] * v2.x[2];\n    prod.x[2] = v1.x[0] * v2.x[1] - v1.x[1] * v2.x[0];\n  }\n\n  inline double Determinant (const Vec3d & col1,\n\t\t\t     const Vec3d & col2,\n\t\t\t     const Vec3d & col3)\n  {\n    return\n      col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) +\n      col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) +\n      col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]);\n  }\n\n\n  ///\n  class Box3d\n  {\n  protected:\n    ///\n    double minx[3], maxx[3];\n\n  public:\n    ///\n    Box3d () { };\n    ///\n    DLL_HEADER Box3d ( double aminx, double amaxx,\n\t    double aminy, double amaxy,\n\t    double aminz, double amaxz );\n    ///\n    DLL_HEADER Box3d ( const Box3d & b2 );\n    ///\n    DLL_HEADER Box3d (const Point3d& p1, const Point3d& p2);\n    ///\n    DLL_HEADER Box3d (const Box<3> & b2);\n    ///\n    double MinX () const { return minx[0]; }\n    ///\n    double MaxX () const { return maxx[0]; }\n    ///\n    double MinY () const { return minx[1]; }\n    ///\n    double MaxY () const { return maxx[1]; }\n    ///\n    double MinZ () const { return minx[2]; }\n    ///\n    double MaxZ () const { return maxx[2]; }\n\n    ///\n    double Mini (int i) const { return minx[i-1]; }\n    ///\n    double Maxi (int i) const { return maxx[i-1]; }\n\n    ///\n    Point3d PMin () const { return Point3d(minx[0], minx[1], minx[2]); }\n    ///\n    Point3d PMax () const { return Point3d(maxx[0], maxx[1], maxx[2]); }\n\n    ///\n    void GetPointNr (int i, Point3d & point) const;\n    /// increase Box at each side with dist \n    void Increase (double dist);\n    /// increase Box by factor rel\n    void IncreaseRel (double rel);\n    /// return 1 if closures are intersecting\n    int Intersect (const Box3d & box2) const\n    {\n      if (minx[0] > box2.maxx[0] || maxx[0] < box2.minx[0] ||\n\t  minx[1] > box2.maxx[1] || maxx[1] < box2.minx[1] ||\n\t  minx[2] > box2.maxx[2] || maxx[2] < box2.minx[2])\n\treturn 0;\n      return 1;\n    }\n    /// return 1 if point p in closure\n    int IsIn (const Point3d & p) const\n    {\n      if (minx[0] <= p.x[0] && maxx[0] >= p.x[0] &&\n\t  minx[1] <= p.x[1] && maxx[1] >= p.x[1] &&\n\t  minx[2] <= p.x[2] && maxx[2] >= p.x[2])\n\treturn 1;\n      return 0;\n    }\n    ///\n    inline void SetPoint (const Point3d & p)\n    {\n      minx[0] = maxx[0] = p.X();\n      minx[1] = maxx[1] = p.Y();\n      minx[2] = maxx[2] = p.Z();    \n    }\n\n    ///\n    inline void AddPoint (const Point3d & p)\n    {\n      if (p.x[0] < minx[0]) minx[0] = p.x[0];\n      if (p.x[0] > maxx[0]) maxx[0] = p.x[0];\n      if (p.x[1] < minx[1]) minx[1] = p.x[1];\n      if (p.x[1] > maxx[1]) maxx[1] = p.x[1];\n      if (p.x[2] < minx[2]) minx[2] = p.x[2];\n      if (p.x[2] > maxx[2]) maxx[2] = p.x[2];\n    }\n\n    ///\n    const Box3d& operator+=(const Box3d& b);\n\n    ///\n    Point3d MaxCoords() const;\n    ///\n    Point3d MinCoords() const;\n\n    /// Make a negative sized box;\n    //  void CreateNegMinMaxBox();\n  \n    ///\n    Point3d CalcCenter () const { return Point3d(0.5*(minx[0] + maxx[0]),\n\t\t\t\t\t\t 0.5*(minx[1] + maxx[1]),\n\t\t\t\t\t\t 0.5*(minx[2] + maxx[2])); }\n    ///\n    double CalcDiam () const { return sqrt(sqr(maxx[0]-minx[0])+\n\t\t\t\t\t   sqr(maxx[1]-minx[1])+\n\t\t\t\t\t   sqr(maxx[2]-minx[2])); }\n\n    ///\n    void WriteData(ofstream& fout) const;\n    ///\n    void ReadData(ifstream& fin);\n  };\n\n\n  class Box3dSphere : public Box3d\n  {\n  protected:\n    ///\n    double diam, inner;\n    ///\n    Point3d c;\n  public:\n    ///\n    Box3dSphere () { };\n    ///\n    Box3dSphere ( double aminx, double amaxx,\n\t\t  double aminy, double amaxy,\n\t\t  double aminz, double amaxz);\n    ///\n    const Point3d & Center () const { return c; }\n\n    ///\n    double Diam () const { return diam; }\n    ///\n    double Inner () const { return inner; }\n    ///\n    void GetSubBox (int i, Box3dSphere & sbox) const;\n\n    // private:\n    ///\n    void CalcDiamCenter ();\n  };\n\n\n\n\n  ///\n  class referencetransform\n  {\n    ///\n    Vec3d ex, ey, ez;\n    ///\n    Vec3d exh, eyh, ezh;\n    ///\n    Vec3d ex_h, ey_h, ez_h;\n    ///\n    Point3d rp;\n    ///\n    double h;\n\n  public:\n\n    ///\n    void Set (const Point3d & p1, const Point3d & p2,\n\t      const Point3d & p3, double ah);\n\n    ///\n    void ToPlain (const Point3d & p, Point3d & pp) const;\n    ///\n    void ToPlain (const NgArray<Point3d> & p, NgArray<Point3d> & pp) const;\n    ///\n    void FromPlain (const Point3d & pp, Point3d & p) const;\n  };\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geomfuncs.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n\nnamespace netgen\n{\n\n  /*\n  // template <>\ninline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv)\n{\n  double det = m(0,0) * m(1,1) - m(0,1) * m(1,0);\n  if (det == 0) \n    {\n      inv = 0;\n      return;\n    }\n\n  double idet = 1.0 / det;\n  inv(0,0) =  idet * m(1,1);\n  inv(0,1) = -idet * m(0,1);\n  inv(1,0) = -idet * m(1,0);\n  inv(1,1) =  idet * m(0,0);\n}\n  */\n\n\n\n  // template <>\nvoid CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv)\n{\n  double det = Det (m);\n  if (det == 0) \n    {\n      inv = 0;\n      return;\n    }\n\n  double idet = 1.0 / det;\n  inv(0,0) =  idet * (m(1,1) * m(2,2) - m(1,2) * m(2,1));\n  inv(1,0) = -idet * (m(1,0) * m(2,2) - m(1,2) * m(2,0));\n  inv(2,0) =  idet * (m(1,0) * m(2,1) - m(1,1) * m(2,0));\n\n  inv(0,1) = -idet * (m(0,1) * m(2,2) - m(0,2) * m(2,1));\n  inv(1,1) =  idet * (m(0,0) * m(2,2) - m(0,2) * m(2,0));\n  inv(2,1) = -idet * (m(0,0) * m(2,1) - m(0,1) * m(2,0));\n\n  inv(0,2) =  idet * (m(0,1) * m(1,2) - m(0,2) * m(1,1));\n  inv(1,2) = -idet * (m(0,0) * m(1,2) - m(0,2) * m(1,0));\n  inv(2,2) =  idet * (m(0,0) * m(1,1) - m(0,1) * m(1,0));\n}\n\n/*\n// template <>\nvoid CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv)\n{\n  Mat<2,2> a = m * Trans (m);\n  Mat<2,2> ainv;\n  CalcInverse (a, ainv);\n  inv = Trans (m) * ainv;\n}\n*/\n\n\n\ndouble Det (const Mat<2,2> & m) \n{\n  return  m(0,0) * m(1,1) - m(0,1) * m(1,0);\n}\n\ndouble Det (const Mat<3,3> & m) \n{\n  return \n    m(0,0) * m(1,1) * m(2,2)\n    + m(1,0) * m(2,1) * m(0,2)\n    + m(2,0) * m(0,1) * m(1,2)\n    - m(0,0) * m(2,1) * m(1,2)\n    - m(1,0) * m(0,1) * m(2,2)\n    - m(2,0) * m(1,1) * m(0,2);\n}\n\n\nvoid EigenValues (const Mat<3,3> & m, Vec<3> & ev)\n{\n  const double pi = M_PI;\n  double a, b, c, d;\n  double p, q;\n  double arg;\n\n  a = -1.;\n  b = m(0,0) + m(1,1) + m(2,2);\n  c = -( m(0,0)*m(2,2) + m(1,1)*m(2,2) + m(0,0)*m(1,1) - sqr(m(0,1)) - sqr(m(0,2)) - sqr(m(1,2)) );\n  d = Det (m);\n  p = 3.*a*c - sqr(b);\n  q = 27.*sqr(a)*d - 9.*a*b*c + 2.*sqr(b)*b;\n\n\n  arg = acos((-q/2)/sqrt(-(p*p*p)));\n\n\n  ev(0) = (2. * sqrt(-p) * cos(arg/3.) - b) / 3.*a;\n  ev(1) = (-2. * sqrt(-p) * cos(arg/3.+pi/3) - b) / 3.*a;\n  ev(2) = (-2. * sqrt(-p) * cos(arg/3.-pi/3)- b) / 3.*a;\n\n\n\n}\n\n\n}\n"
  },
  {
    "path": "libsrc/gprim/geomfuncs.hpp",
    "content": "#ifndef FILE_GEOMFUNCS\n#define FILE_GEOMFUNCS\n\n/* *************************************************************************/\n/* File:   geomfuncs.hpp                                                   */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   20. Jul. 02                                                     */\n/* *************************************************************************/\n\n#include \"geomobjects.hpp\"\n#include \"geomops.hpp\"\n\nnamespace netgen \n{\n\n  template <int D>\n  inline double Abs (const Vec<D> & v)\n  {\n    double sum = 0;\n    for (int i = 0; i < D; i++)\n      sum += v(i) * v(i);\n    return sqrt (sum);\n  }\n\n\n  template <int D>\n  inline double Abs2 (const Vec<D> & v)\n  {\n    double sum = 0;\n    for (int i = 0; i < D; i++)\n      sum += v(i) * v(i);\n    return sum;\n  }\n\n\n\n  template <int D>\n  inline double Dist (const Point<D> & a, const Point<D> & b)\n  {\n    return Abs (a-b);\n  }\n\n  template <int D>\n  inline double Dist2 (const Point<D> & a, const Point<D> & b)\n  {\n    return Abs2 (a-b);\n  }\n\n\n  template <int D>\n  inline Point<D> Center (const Point<D> & a, const Point<D> & b)\n  {\n    Point<D> res;\n    for (int i = 0; i < D; i++)\n      res(i) = 0.5 * (a(i) + b(i));\n    return res;\n  }\n\n  template <int D>\n  inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c)\n  {\n    Point<D> res;\n    for (int i = 0; i < D; i++)\n      res(i) = (1.0/3.0) * (a(i) + b(i) + c(i));\n    return res;\n  }\n\n  template <int D>\n  inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c, const Point<D> & d)\n  {\n    Point<D> res;\n    for (int i = 0; i < D; i++)\n      res(i) = (1.0/4.0) * (a(i) + b(i) + c(i) + d(i));\n    return res;\n  }\n\n\n\n\n  /*\n    new wrong code problem with MSVC2010:\n    using Cross ( & , & ) computes wrong cross-product, problem arises in \n    Surface::DefineTangentialPlane, e.g. with example boxcyl.geo\n   */\n  // inline Vec<3> Cross (const Vec<3> & v1, const Vec<3> & v2)\n\n  template <typename T>\n  inline Vec<3,T> Cross (Vec<3,T> v1, Vec<3,T> v2)\n  {\n    return Vec<3,T> \n      ( v1(1) * v2(2) - v1(2) * v2(1),\n\tv1(2) * v2(0) - v1(0) * v2(2),\n\tv1(0) * v2(1) - v1(1) * v2(0) );\n  }\n\n\n  inline double Determinant (const Vec<3> & col1,\n\t\t\t     const Vec<3> & col2,\n\t\t\t     const Vec<3> & col3)\n  {\n    return\n      col1(0) * ( col2(1) * col3(2) - col2(2) * col3(1)) +\n      col1(1) * ( col2(2) * col3(0) - col2(0) * col3(2)) +\n      col1(2) * ( col2(0) * col3(1) - col2(1) * col3(0));\n  }\n\n\n\n  template <>\n  inline  Vec<2> Vec<2> :: GetNormal () const\n  {\n    return Vec<2> (-x[1], x[0]);\n  }\n\n  template <>\n  inline  Vec<3> Vec<3> :: GetNormal () const\n  {\n    if (fabs (x[0]) > fabs (x[2]))\n      return Vec<3> (-x[1], x[0], 0);\n    else\n      return Vec<3> (0, x[2], -x[1]);\n  }\n\n\n\n  // template <int H, int W>\n  inline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv)\n  {\n    double det = m(0,0) * m(1,1) - m(0,1) * m(1,0);\n    if (det == 0) \n      {\n\tinv = 0;\n\treturn;\n      }\n\n    double idet = 1.0 / det;\n    inv(0,0) =  idet * m(1,1);\n    inv(0,1) = -idet * m(0,1);\n    inv(1,0) = -idet * m(1,0);\n    inv(1,1) =  idet * m(0,0);\n  }\n\n  void CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv);\n\n  inline void CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv)\n  {\n    Vec<3> a0 = m.Row(0);\n    Vec<3> a1 = m.Row(1);\n    Vec<3> n = Cross(a0, a1);\n    Vec<3> d0 = Cross(a1, n);\n    Vec<3> d1 = Cross(a0, n);\n    double s0 = 1.0/(a0*d0);\n    double s1 = 1.0/(a1*d1);\n    for (int i = 0; i < 3; i++)\n      {\n        inv(i,0) = s0*d0(i);\n        inv(i,1) = s1*d1(i);\n      }\n    /*\n    Mat<2,2> a = m * Trans (m);\n    Mat<2,2> ainv;\n    CalcInverse (a, ainv);\n    inv = Trans (m) * ainv;\n    */\n  }\n\n  void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv);\n\n  inline void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv)\n  {\n    Mat<2,2> a = Trans (m) * m;\n    Mat<2,2> ainv;\n    CalcInverse (a, ainv);\n    inv = ainv * Trans (m);\n  }\n\n\n  double Det (const Mat<2,2> & m);\n  double Det (const Mat<3,3> & m);\n\n  // eigenvalues of a symmetric matrix\n  DLL_HEADER void EigenValues (const Mat<3,3> & m, Vec<3> & ev);\n  DLL_HEADER void EigenValues (const Mat<2,2> & m, Vec<3> & ev);\n\n\n  template <typename T> \n  Vec<3,T> StableSolve (Mat<2,3,T> mat, Vec<2,T> rhs)\n  {\n    Vec<3> a0 = mat.Row(0);\n    Vec<3> a1 = mat.Row(1);\n    /*\n    Vec<3> d = Cross ( Cross (a0, a1), a0);\n\n    double alpha = rhs(0) / a0.Length2();\n    double beta = (rhs(1)-alpha* (a0*a1)) / (d*a1);\n    return alpha * a0 + beta * d;\n    */\n    Vec<3> n = Cross(a0, a1);\n    Vec<3> d0 = Cross(a1, n);\n    Vec<3> d1 = Cross(a0, n);\n    double alpha = rhs(0) / (a0*d0);\n    double beta = rhs(1) / (a1*d1);\n    return alpha * d0 + beta * d1;\n  }\n\n\n\n\n  \n}\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geomobjects.hpp",
    "content": "#ifndef FILE_OBJECTS\n#define FILE_OBJECTS\n\n/* *************************************************************************/\n/* File:   geomobjects.hpp                                                 */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   20. Jul. 02                                                     */\n/* *************************************************************************/\n\n#include <core/array.hpp>\n\n#include <general/ngarray.hpp>\n\nnamespace netgen\n{\n  using namespace ngcore;\n\n  template <int D, typename T = double> class Vec;\n  template <int D, typename T = double> class Point;\n\n\n  template <int D, typename T>\n  class Point\n  {\n\n  protected:\n    T x[D];\n\n  public:\n    Point () { ; }\n    Point (T ax) { for (int i = 0; i < D; i++) x[i] = ax; }\n    Point (T ax, T ay) \n    { \n      // static_assert(D==2, \"Point<D> constructor with 2 args called\");\n      x[0] = ax; x[1] = ay; \n    }\n    Point (T ax, T ay, T az) \n    {\n      // static_assert(D==3, \"Point<D> constructor with 3 args called\");\n      x[0] = ax; x[1] = ay; x[2] = az; \n    }\n    Point (T ax, T ay, T az, T au)\n    { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au;}\n\n    template <typename T2>\n    Point (const Point<D,T2> & p2)\n    { for (int i = 0; i < D; i++) x[i] = p2(i); }\n\n    explicit Point (const Vec<D,T> & v)\n    { for (int i = 0; i < D; i++) x[i] = v(i); }\n\n\n    template <typename T2>\n    Point & operator= (const Point<D,T2> & p2)\n    {\n      for (int i = 0; i < D; i++) x[i] = p2(i);\n      return *this;\n    }\n\n    Point & operator= (T val)\n    {\n      for (int i = 0; i < D; i++) x[i] = val;\n      return *this;\n    }\n\n    T & operator() (int i) { return x[i]; }\n    const T & operator() (int i) const { return x[i]; }\n\n    T& operator[] (int i) { return x[i]; }\n    const T& operator[] (int i) const { return x[i]; }\n\n    operator const T* () const { return x; }\n\n    template<typename ARCHIVE>\n    void DoArchive(ARCHIVE& archive)\n    {\n      for(int i=0; i<D; i++)\n        archive & x[i];\n    }\n  };\n\n  template <int D, typename T>\n  class Vec\n  {\n\n  protected:\n    T x[D];\n\n  public:\n    Vec () { ; } // for (int i = 0; i < D; i++) x[i] = 0; }\n    Vec (T ax) { for (int i = 0; i < D; i++) x[i] = ax; }\n    Vec (T ax, T ay) \n    { \n      // static_assert(D==2, \"Vec<D> constructor with 2 args called\");\n      x[0] = ax; x[1] = ay; \n    }\n    Vec (T ax, T ay, T az)\n    { \n      // static_assert(D==3, \"Vec<D> constructor with 3 args called\");\n      x[0] = ax; x[1] = ay; x[2] = az; \n    }\n    Vec (T ax, T ay, T az, T au)\n    { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au; }\n\n    Vec (const Vec<D> & p2)\n    { for (int i = 0; i < D; i++) x[i] = p2.x[i]; }\n\n    explicit Vec (const Point<D,T> & p)\n    { for (int i = 0; i < D; i++) x[i] = p(i); }\n\n    explicit Vec(const Point<D,T>& p1, const Point<D,T>& p2)\n    { for(int i=0; i<D; i++) x[i] = p2(i)-p1(i); }\n\n    template <typename T2>\n    Vec & operator= (const Vec<D,T2> & p2)\n    {\n      for (int i = 0; i < D; i++) x[i] = p2(i);\n      return *this;\n    }\n\n    Vec & operator= (T s)\n    {\n      for (int i = 0; i < D; i++) x[i] = s;\n      return *this;\n    }\n\n    bool operator== (const Vec<D,T> &a) const\n    {\n      bool res = true;\n      for (auto i : Range(D))\n        res &= (x[i]==a.x[i]);\n      return res;\n    }\n\n    T & operator() (int i) { return x[i]; }\n    const T & operator() (int i) const { return x[i]; }\n\n    T& operator[] (int i) { return x[i]; }\n    const T& operator[] (int i) const { return x[i]; }\n\n    operator const T* () const { return x; }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE& archive)\n    {\n      for(int i=0; i<D; i++)\n        archive & x[i];\n    }\n\n    T Length () const\n    {\n      T l = 0;\n      for (int i = 0; i < D; i++)\n\tl += x[i] * x[i];\n      return sqrt (l);\n    }\n\n    T Length2 () const\n    {\n      T l = 0;\n      for (int i = 0; i < D; i++)\n\tl += x[i] * x[i];\n      return l;\n    }\n\n    Vec & Normalize ()\n    {\n      T l = Length();\n      // if (l != 0)\n      for (int i = 0; i < D; i++)\n        x[i] /= (l+1e-40);\n      return *this;\n    }\n\n    Vec<D> GetNormal () const;\n  };\n\n  template <int D>\n  inline ostream & operator<< (ostream & ost, const Vec<D> & a)\n  {\n    ost << \"(\";\n    for (int i = 0; i < D-1; i++)\n      ost << a(i) << \", \";\n    ost << a(D-1) << \")\";\n    return ost;\n  }\n\n  template <int D>\n  inline ostream & operator<< (ostream & ost, const Point<D> & a)\n  {\n    ost << \"(\";\n    for (int i = 0; i < D-1; i++)\n      ost << a(i) << \", \";\n    ost << a(D-1) << \")\";\n    return ost;\n  }\n\n  template<int D>\n  inline Vec<D> operator-(const Point<D>& p1, const Point<D>& p2)\n  {\n    Vec<D> result;\n    for(auto i : Range(D))\n      result[i] = p1[i] - p2[i];\n    return result;\n  }\n\n  template<int D>\n  inline Vec<D> operator*(const Vec<D>& v, double d)\n  {\n    Vec<D> result;\n    for(auto i : Range(D))\n      result[i] = d*v[i];\n    return result;\n  }\n\n  inline double Cross2(const Vec<2>& v1, const Vec<2>& v2)\n  {\n    return v1[0] * v2[1] - v1[1] * v2[0];\n  }\n\n  // are points clockwise?\n  inline bool CW(const Point<2>& p1, const Point<2>& p2,\n                  const Point<2>& p3)\n  {\n    return Cross2(p2-p1, p3-p2) < 0;\n  }\n\n  // are points counterclockwise?\n  inline bool CCW(const Point<2>& p1, const Point<2>& p2,\n                  const Point<2>& p3)\n  {\n    return Cross2(p2-p1, p3-p2) > 0;\n  }\n\n  // are strictly points counterclockwise?\n  inline bool CCW(const Point<2>& p1, const Point<2>& p2,\n                  const Point<2>& p3, double eps)\n  {\n    auto v1 = p2-p1;\n    auto v2 = p3-p2;\n    return Cross2(v1, v2) > eps*eps*max2(v1.Length2(),\n                                         v2.Length2());\n  }\n\n\n  template <int H, int W=H, typename T = double>\n  class Mat\n  {\n\n  protected:\n    T x[H*W];\n\n  public:\n    Mat () { ; }\n    Mat (const Mat & b)\n    { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; }\n  \n    Mat & operator= (T s)\n    {\n      for (int i = 0; i < H*W; i++) x[i] = s;\n      return *this;\n    }\n\n    Mat & operator= (const Mat & b)\n    {\n      for (int i = 0; i < H*W; i++) x[i] = b.x[i]; \n      return *this;\n    }\n\n    T & operator() (int i, int j) { return x[i*W+j]; }\n    const T & operator() (int i, int j) const { return x[i*W+j]; }\n    T & operator() (int i) { return x[i]; }\n    const T & operator() (int i) const { return x[i]; }\n\n    Vec<H,T> Col (int i) const\n    {\n      Vec<H,T> hv; \n      for (int j = 0; j < H; j++)\n\thv(j) = x[j*W+i];\n      return hv; \n    }\n\n    Vec<W,T> Row (int i) const\n    {\n      Vec<W,T> hv; \n      for (int j = 0; j < W; j++)\n\thv(j) = x[i*W+j];\n      return hv; \n    }\n\n    void Solve (const Vec<H,T> & rhs, Vec<W,T> & sol) const\n    {\n      Mat<W,H,T> inv;\n      CalcInverse (*this, inv);\n      sol = inv * rhs;\n    }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE & ar)\n    {\n      ar.Do(x, H*W);\n    }\n  };\n\n\n\n\n  template <int D>\n  class Box\n  {\n  protected:\n    Point<D> pmin, pmax;\n  public:\n    Box () { ; }\n\n    Box ( const Point<D> & p1)\n    {\n      for (int i = 0; i < D; i++)\n\tpmin(i) = pmax(i) = p1(i);\n    }\n\n\n    Box ( const Point<D> & p1, const Point<D> & p2)\n    {\n      for (int i = 0; i < D; i++)\n\t{\n\t  pmin(i) = min2(p1(i), p2(i));\n\t  pmax(i) = max2(p1(i), p2(i));\n\t}\n    }\n\n    Box (const Point<D> & p1, const Point<D> & p2, const Point<D> & p3)\n      : Box(p1,p2)\n    {\n      Add (p3);\n    }\n\n    enum EB_TYPE { EMPTY_BOX = 1 };\n    Box ( EB_TYPE et ) \n    {\n      for (int i = 0; i < D; i++)\n        {\n          pmin(i) = 1e99;\n          pmax(i) = -1e99;\n        }\n    }\n\n    const Point<D> & PMin () const { return pmin; }\n    const Point<D> & PMax () const { return pmax; }\n  \n    void Set (const Point<D> & p)\n    { pmin = pmax = p; }\n\n    void Add (const Point<D> & p)\n    { \n      for (int i = 0; i < D; i++)\n\t{\n\t  if (p(i) < pmin(i)) pmin(i) = p(i);\n\t  /* else */ if (p(i) > pmax(i)) pmax(i) = p(i);\n          // optimization invalid for empty-box !\n\t}\n    }\n\n    template <typename T1, typename T2>\n    void Set (const NgIndirectArray<T1, T2> & points)\n    {\n      // Set (points[points.Begin()]);\n      Set (points[*points.Range().begin()]);\n      // for (int i = points.Begin()+1; i < points.End(); i++)\n      for (int i : points.Range().Modify(1,0))\n        Add (points[i]);\n    }\n\n    template <typename T1, typename T2>\n    void Add (const NgIndirectArray<T1, T2> & points)\n    {\n      // for (int i = points.Begin(); i < points.End(); i++)\n      for (int i : points.Range())\n        Add (points[i]);\n    }\n\n\n    Point<D> Center () const \n    { \n      Point<D> c;\n      for (int i = 0; i < D; i++)\n\tc(i) = 0.5 * (pmin(i)+pmax(i)); \n      return c;\n    }\n    double Diam () const { return Abs (pmax-pmin); }\n\n    Point<D> GetPointNr (int nr) const\n    {\n      Point<D> p;\n      for (int i = 0; i < D; i++)\n\t{\n\t  p(i) = (nr & 1) ? pmax(i) : pmin(i);\n\t  nr >>= 1;\n\t}\n      return p;\n    }\n\n\n    bool Intersect (const Box<D> & box2) const\n    {\n      for (int i = 0; i < D; i++)\n\tif (pmin(i) > box2.pmax(i) ||\n\t    pmax(i) < box2.pmin(i)) return 0;\n      return 1;\n    }\n\n\n    bool IsIn (const Point<D> & p) const\n    {\n      for (int i = 0; i < D; i++)\n\tif (p(i) < pmin(i) || p(i) > pmax(i)) return false;\n      return true;\n    }\n\n    // is point in eps-increased box\n    bool IsIn (const Point<D> & p, double eps) const\n    {\n      for (int i = 0; i < D; i++)\n\tif (p(i) < pmin(i)-eps || p(i) > pmax(i)+eps) return false;\n      return true;\n    }\n\n\n    void Increase (double dist)\n    {\n      for (int i = 0; i < D; i++)\n\t{\n\t  pmin(i) -= dist;\n\t  pmax(i) += dist;\n\t}\n    }\n\n    void Scale (double factor)\n    {\n      auto center = Center();\n      pmin = center + factor*(pmin-center);\n      pmax = center + factor*(pmax-center);\n    }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE & archive)\n    { archive & pmin & pmax; }\n  };\n\n\n\n\n  template <int D>\n  class BoxSphere : public Box<D>\n  {\n  protected:\n    ///\n    Point<D> c;\n    ///\n    double diam;\n    ///\n    double inner;\n  public:\n    ///\n    BoxSphere () { };\n    ///\n    BoxSphere (const Box<D> & box) \n      : Box<D> (box) \n    { \n      CalcDiamCenter();\n    };\n\n    ///\n    BoxSphere ( Point<D> apmin, Point<D> apmax )\n      : Box<D> (apmin, apmax)\n    {\n      CalcDiamCenter();\n    }\n\n    ///\n    const Point<D> & Center () const { return c; }\n    ///\n    double Diam () const { return diam; }\n    ///\n    double Inner () const { return inner; }\n\n\n    ///\n    void GetSubBox (int nr, BoxSphere & sbox) const\n    {\n      for (int i = 0; i < D; i++)\n\t{\n\t  if (nr & 1)\n\t    {\n\t      sbox.pmin(i) = c(i);\n\t      sbox.pmax(i) = this->pmax(i);\n\t    }\n\t  else\n\t    {\n\t      sbox.pmin(i) = this->pmin(i);\n\t      sbox.pmax(i) = c(i);\n\t    }\n\t  sbox.c(i) = 0.5 * (sbox.pmin(i) + sbox.pmax(i));\n\t  nr >>= 1;\n\t}\n      sbox.diam = 0.5 * diam;\n      sbox.inner = 0.5 * inner;\n    }\n\n\n    ///\n    void CalcDiamCenter ()\n    {\n      c = Box<D>::Center ();\n      diam = Dist (this->pmin, this->pmax);\n\n      inner = this->pmax(0) - this->pmin(0);\n      for (int i = 1; i < D; i++)\n\tif (this->pmax(i) - this->pmin(i) < inner)\n\t  inner = this->pmax(i) - this->pmin(i);\n    }\n\n  };\n\n\n#ifdef PARALLEL_OLD\n  template <> \n  inline MPI_Datatype MyGetMPIType<Vec<3, double> > ()\n  {\n    static MPI_Datatype MPI_T = 0;\n    if (!MPI_T)\n      {\n\tMPI_Type_contiguous ( 3, MPI_DOUBLE, &MPI_T);\n\tMPI_Type_commit ( &MPI_T );\n      }\n    return MPI_T;\n  };\n#endif\n  \n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geomops.hpp",
    "content": "#ifndef FILE_GEOMOPS\n#define FILE_GEOMOPS\n\n/* *************************************************************************/\n/* File:   geomops.hpp                                                     */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   20. Jul. 02                                                     */\n/* *************************************************************************/\n\n\nnamespace netgen\n{\n\n  /*\n\n  Point - Vector operations\n\n  */\n\n\n  template <int D, typename T>\n  inline Vec<D,T> operator+ (Vec<D,T> a, Vec<D,T> b)\n  {\n    Vec<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = a(i) + b(i);\n    return res;\n  }\n\n\n\n  template <int D, typename T>\n  inline Point<D,T> operator+ (Point<D,T> a, Vec<D,T> b)\n  {\n    Point<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = a(i) + b(i);\n    return res;\n  }\n\n\n\n  template <int D, typename T>\n  inline Vec<D,T> operator- (Point<D,T> a, Point<D,T> b)\n  {\n    Vec<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = a(i) - b(i);\n    return res;\n  }\n\n  template <int D, typename T>\n  inline Point<D,T> operator- (Point<D,T> a, Vec<D,T> b)\n  {\n    Point<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = a(i) - b(i);\n    return res;\n  }\n\n  template <int D, typename T>\n  inline Vec<D,T> operator- (Vec<D,T> a, Vec<D,T> b)\n  {\n    Vec<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = a(i) - b(i);\n    return res;\n  }\n\n\n\n  template <int D, typename T>\n  inline Vec<D,T> operator* (T s, Vec<D,T> b)\n  {\n    Vec<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = s * b(i);\n    return res;\n  }\n\n  template <int D, int SW>\n  inline Vec<D, SIMD<double,SW>> operator* (SIMD<double,SW> s, Vec<D,double> b)\n  {\n    Vec<D,SIMD<double,SW>> res;\n    for (int i = 0; i < D; i++)\n      res(i) = s * b(i);\n    return res;\n  }\n  \n\n  template <int D>\n  inline double operator* (Vec<D> a, Vec<D> b)\n  {\n    double sum = 0;\n    for (int i = 0; i < D; i++)\n      sum += a(i) * b(i);\n    return sum;\n  }\n\n\n\n  template <int D, typename T>\n  inline Vec<D,T> operator- (Vec<D,T> b)\n  {\n    Vec<D,T> res;\n    for (int i = 0; i < D; i++)\n      res(i) = -b(i);\n    return res;\n  }\n\n\n  template <int D, typename T>\n  inline Point<D,T> & operator+= (Point<D,T> & a, Vec<D,T> b)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) += b(i);\n    return a;\n  }\n\n  template <int D, typename T>\n  inline Vec<D,T> & operator+= (Vec<D,T> & a, Vec<D> b)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) += b(i);\n    return a;\n  }\n\n\n  template <int D>\n  inline Point<D> & operator-= (Point<D> & a, const Vec<D> & b)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) -= b(i);\n    return a;\n  }\n\n  template <int D>\n  inline Vec<D> & operator-= (Vec<D> & a, const Vec<D> & b)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) -= b(i);\n    return a;\n  }\n\n\n\n  template <int D, typename T1, typename T2>\n  inline Vec<D,T1> & operator*= (Vec<D,T1> & a, T2 s)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) *= s;\n    return a;\n  }\n\n\n  template <int D>\n  inline Vec<D> & operator/= (Vec<D> & a, double s)\n  {\n    for (int i = 0; i < D; i++)\n      a(i) /= s;\n    return a;\n  }\n\n\n\n\n  // Matrix - Vector operations\n\n  /*\n    template <int H, int W>\n    inline Vec<H> operator* (const Mat<H,W> & m, const Vec<W> & v)\n    {\n    Vec<H> res;\n    for (int i = 0; i < H; i++)\n    {\n    res(i) = 0;\n    for (int j = 0; j < W; j++)\n    res(i) += m(i,j) * v(j);\n    }\n    return res;\n    }\n  */\n\n  // thanks to VC60 partial template specialization features !!!\n\n  inline Vec<2> operator* (const Mat<2,2> & m, const Vec<2> & v)\n  {\n    Vec<2> res;\n    for (int i = 0; i < 2; i++)\n      {\n\tres(i) = 0;\n\tfor (int j = 0; j < 2; j++)\n\t  res(i) += m(i,j) * v(j);\n      }\n    return res;\n  }\n\n  inline Vec<2> operator* (const Mat<2,3> & m, const Vec<3> & v)\n  {\n    Vec<2> res;\n    for (int i = 0; i < 2; i++)\n      {\n\tres(i) = 0;\n\tfor (int j = 0; j < 3; j++)\n\t  res(i) += m(i,j) * v(j);\n      }\n    return res;\n  }\n\n\n  inline Vec<3> operator* (const Mat<3,2> & m, const Vec<2> & v)\n  {\n    Vec<3> res;\n    for (int i = 0; i < 3; i++)\n      {\n\tres(i) = 0;\n\tfor (int j = 0; j < 2; j++)\n\t  res(i) += m(i,j) * v(j);\n      }\n    return res;\n  }\n\n\n  inline Vec<3> operator* (const Mat<3,3> & m, const Vec<3> & v)\n  {\n    Vec<3> res;\n    for (int i = 0; i < 3; i++)\n      {\n\tres(i) = 0;\n\tfor (int j = 0; j < 3; j++)\n\t  res(i) += m(i,j) * v(j);\n      }\n    return res;\n  }\n\n\n\n\n\n\n\n  /*\n    template <int H1, int W1, int H2, int W2>\n    inline Mat<H1,W2> operator* (const Mat<H1,W1> & a, const Mat<H2,W2> & b)\n    {\n    Mat<H1,W2> m;\n    for (int i = 0; i < H1; i++)\n    for (int j = 0; j < W2; j++)\n    {\n    double sum = 0;\n    for (int k = 0; k < W1; k++)\n    sum += a(i,k) * b(k, j);\n    m(i,j) = sum; \n    }\n    return m;\n    }\n  */\n\n  template <typename T>\n  inline Mat<2,2,T> operator* (const Mat<2,2,T> & a, const Mat<2,2,T> & b)\n  {\n    Mat<2,2,T> m;\n    for (int i = 0; i < 2; i++)\n      for (int j = 0; j < 2; j++)\n\t{\n          T sum(0);\n\t  for (int k = 0; k < 2; k++)\n\t    sum += a(i,k) * b(k, j);\n\t  m(i,j) = sum; \n\t}\n    return m;\n  }\n\n  inline Mat<2,2> operator* (const Mat<2,3> & a, const Mat<3,2> & b)\n  {\n    Mat<2,2> m;\n    for (int i = 0; i < 2; i++)\n      for (int j = 0; j < 2; j++)\n\t{\n\t  double sum = 0;\n\t  for (int k = 0; k < 3; k++)\n\t    sum += a(i,k) * b(k, j);\n\t  m(i,j) = sum; \n\t}\n    return m;\n  }\n\n  template <typename T>\n  inline Mat<3,2,T> operator* (const Mat<3,2,T> & a, const Mat<2,2,T> & b)\n  {\n    Mat<3,2,T> m;\n    for (int i = 0; i < 3; i++)\n      for (int j = 0; j < 2; j++)\n\t{\n\t  T sum(0.0);\n\t  for (int k = 0; k < 2; k++)\n\t    sum += a(i,k) * b(k, j);\n\t  m(i,j) = sum; \n\t}\n    return m;\n  }\n\n\n\n  inline Mat<2,3> operator* (const Mat<2,2> & a, const Mat<2,3> & b)\n  {\n    Mat<2,3> m;\n    for (int i = 0; i < 2; i++)\n      for (int j = 0; j < 3; j++)\n\t{\n\t  double sum = 0;\n\t  for (int k = 0; k < 2; k++)\n\t    sum += a(i,k) * b(k, j);\n\t  m(i,j) = sum; \n\t}\n    return m;\n  }\n\n  template <typename T>\n  inline Mat<3,3,T> operator* (const Mat<3,3,T> & a, const Mat<3,3,T> & b)\n  {\n    Mat<3,3,T> m;\n    for (int i = 0; i < 3; i++)\n      for (int j = 0; j < 3; j++)\n\t{\n\t  T sum = T(0);\n\t  for (int k = 0; k < 3; k++)\n\t    sum += a(i,k) * b(k, j);\n\t  m(i,j) = sum; \n\t}\n    return m;\n  }\n\n\n\n\n\n\n\n\n  template <int H, int W>\n  inline Mat<W,H> Trans (const Mat<H,W> & m)\n  {\n    Mat<W,H> res;\n    for (int i = 0; i < H; i++)\n      for (int j = 0; j < W; j++)\n\tres(j,i) = m(i,j);\n    return res;\n  }\n\n\n\n\n\n\n\n\n\n\n\n  template <int D, typename T>\n  inline ostream & operator<< (ostream & ost, const Vec<D,T> & a)\n  {\n    ost << \"(\";\n    for (int i = 0; i < D-1; i++)\n      ost << a(i) << \", \";\n    ost << a(D-1) << \")\";\n    return ost;\n  }\n\n  template <int D, typename T>\n  inline ostream & operator<< (ostream & ost, const Point<D,T> & a)\n  {\n    ost << \"(\";\n    for (int i = 0; i < D-1; i++)\n      ost << a(i) << \", \";\n    ost << a(D-1) << \")\";\n    return ost;\n  }\n\n  template <int D>\n  inline ostream & operator<< (ostream & ost, const Box<D> & b)\n  {\n    ost << b.PMin() << \" - \" << b.PMax();\n    return ost;\n  }\n\n  template <int H, int W, typename T>\n  inline ostream & operator<< (ostream & ost, const Mat<H,W,T> & m)\n  {\n    ost << \"(\";\n    for (int i = 0; i < H; i++)\n      {\n\tfor (int j = 0; j < W; j++)\n\t  ost << m(i,j) << \"   \";\n\tost << endl;\n      }\n    return ost;\n  }\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/geomtest3d.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <gprim.hpp>\n\nnamespace netgen\n{\n\nint\nIntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line)\n{\n  Vec3d vl(*line[0], *line[1]);\n  Vec3d vt1(*tri[0], *tri[1]);\n  Vec3d vt2(*tri[0], *tri[2]);\n  Vec3d vrs(*tri[0], *line[0]);\n\n  // static DenseMatrix a(3), ainv(3);\n  // static Vector rs(3), lami(3);\n  Mat<3,3> a, ainv;\n  Vec<3> rs, lami;\n  int i;\n\n  /*\n  (*testout) << \"Tri-Line inters: \" << endl\n\t     << \"tri = \" << *tri[0] << \", \" << *tri[1] << \", \" << *tri[2] << endl\n\t     << \"line = \" << *line[0] << \", \" << *line[1] << endl;\n  */\n  for (i = 0; i < 3; i++)\n    {\n      a(i, 0) = -vl.X(i+1);\n      a(i, 1) = vt1.X(i+1);\n      a(i, 2) = vt2.X(i+1);\n      rs(i) = vrs.X(i+1);\n    }\n\n  // double det = a.Det();\n  double det = Det(a); \n\n  double arel = vl.Length() * vt1.Length() * vt2.Length();\n  /*\n  double amax = 0;\n  for (i = 1; i <= 9; i++)\n    if (fabs (a.Get(i)) > amax)\n      amax = fabs(a.Get(i));\n  */\n  // new !!!!\n  if (fabs (det) <= 1e-10 * arel)\n    {\n#ifdef DEVELOP      \n      // line parallel to triangle !\n      // cout << \"ERROR: IntersectTriangleLine degenerated\" << endl;\n      //      (*testout) << \"WARNING: IntersectTriangleLine degenerated\\n\";\n      /*\n      (*testout) << \"lin-tri intersection: \" << endl\n\t\t << \"line = \" << *line[0] << \" - \" << *line[1] << endl\n\t\t << \"tri = \" << *tri[0] << \" - \" << *tri[1] << \" - \" << *tri[2] << endl\n\t\t << \"lami = \" << lami << endl\n\t\t << \"pc = \" << ( *line[0] + lami.Get(1) * vl ) << endl\n\t\t << \"   = \" << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl\n\t\t << \" a = \" << a << endl\n\t\t << \" ainv = \" << ainv << endl\n\t\t << \" det(a) = \" << det << endl\n\t\t << \" rs = \" << rs << endl;\n      */\n#endif\n      return 0;\n    }\n\n  CalcInverse (a, ainv);\n  // ainv.Mult (rs, lami);\n  lami = ainv * rs;\n\n  //  (*testout) << \"lami = \" << lami << endl;\n\n  double eps = 1e-6;\n  if (\n      (lami(0) >= -eps && lami(0) <= 1+eps && \n       lami(1) >= -eps && lami(2) >= -eps && \n       lami(1) + lami(2) <= 1+eps)  && !\n      (lami(0) >= eps && lami(0) <= 1-eps && \n       lami(1) >= eps && lami(2) >= eps && \n       lami(1) + lami(2) <= 1-eps) )\n\n\n     {\n#ifdef DEVELOP\n       //      cout << \"WARNING: IntersectTriangleLine degenerated\" << endl;\n      (*testout) << \"WARNING: IntersectTriangleLine numerical inexact\" << endl;\n\n      (*testout) << \"lin-tri intersection: \" << endl\n\t\t << \"line = \" << *line[0] << \" - \" << *line[1] << endl\n\t\t << \"tri = \" << *tri[0] << \" - \" << *tri[1] << \" - \" << *tri[2] << endl\n\t\t << \"lami = \" << lami << endl\n\t\t << \"pc = \" << ( *line[0] + lami(0) * vl ) << endl\n\t\t << \"   = \" << ( *tri[0] + lami(1) * vt1 + lami(2) * vt2) << endl\n\t\t << \" a = \" << a << endl\n\t\t << \" ainv = \" << ainv << endl\n\t\t << \" det(a) = \" << det << endl\n\t\t << \" rs = \" << rs << endl;\n#endif\n    }\n      \n\n  if (lami(0) >= 0 && lami(0) <= 1 && \n      lami(1) >= 0 && lami(2) >= 0 && lami(1) + lami(2) <= 1)\n    {\n\n      return 1;\n    }\n\n  return 0;\n}\n\n\n\n\n\nint IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri,\n\t\t\t  const int * tetpi, const int * tripi)\n{\n  int i, j;\n  double diam = Dist (*tri[0], *tri[1]);\n  double epsrel = 1e-8;\n  double eps = diam * epsrel;\n\n  double eps2 = eps * eps;\n  int cnt = 0;\n\n  int tetp1 = -1, tetp2 = -1;\n  int trip1 = -1, trip2 = -1;\n  int tetp3, tetp4, trip3;\n\n  /*\n  for (i = 0; i < 4; i++)\n    loctetpi[i] = -1;\n  */\n\n\n  if (!tetpi)\n    {\n      for (i = 0; i <= 2; i++)\n\t{\n\t  //\t  loctripi[i] = -1;\n\t  for (j = 0; j <= 3; j++)\n\t    {\n\t      if (Dist2 (*tet[j], *tri[i]) < eps2)\n\t\t{\n\t\t  //\t\t  loctripi[i] = j;\n\t\t  //\t\t  loctetpi[j] = i;\n\t\t  cnt++;\n\t\t  tetp2 = tetp1;\n\t\t  tetp1 = j;\n\t\t  trip2 = trip1;\n\t\t  trip1 = i;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n    }\n  else\n    {\n      for (i = 0; i <= 2; i++)\n\t{\n\t  //\t  loctripi[i] = -1;\n\t  for (j = 0; j <= 3; j++)\n\t    {\n\t      if (tetpi[j] == tripi[i])\n\t\t{\n\t\t  //\t\t  loctripi[i] = j;\n\t\t  //\t\t  loctetpi[j] = i;\n\t\t  cnt++;\n\t\t  tetp2 = tetp1;\n\t\t  tetp1 = j;\n\t\t  trip2 = trip1;\n\t\t  trip1 = i;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n    }  \n  \n  //  (*testout) << \"cnt = \" << cnt << endl;\n\n\n  //  (*testout) << \"tet-trig inters, cnt = \" << cnt << endl;\n  \n  // cnt .. number of common points\n  switch (cnt)\n    {\n    case 0:\n      {\n\tVec3d no, n;\n\tint inpi[3];\n\n\t// check, if some trigpoint is in tet:\n\n\tfor (j = 0; j < 3; j++)\n\t  inpi[j] = 1;\n\n\tfor (i = 1; i <= 4; i++)\n\t  {\n\t    int pi1 = i % 4;\n\t    int pi2 = (i+1) % 4;\n\t    int pi3 = (i+2) % 4;\n\t    int pi4 = (i+3) % 4;\n\n\t    Vec3d v1 (*tet[pi1], *tet[pi2]);\n\t    Vec3d v2 (*tet[pi1], *tet[pi3]);\n\t    Vec3d v3 (*tet[pi1], *tet[pi4]);\n\t    Cross (v1, v2, n);\n\n\t    // n /= n.Length();\n\t    double nl = n.Length();\n\n\t    if (v3 * n > 0)\n\t      n *= -1;\n\n\t    int outeri = 1;\n\t    for (j = 0; j < 3; j++)\n\t      {\n\t\tVec3d v(*tet[pi1], *tri[j]);\n\t\tif ( v * n < eps * nl)\n\t\t  outeri = 0;\n\t\telse\n\t\t  inpi[j] = 0;\n\t      }\n\n\t    if (outeri)\n\t      return 0;\n\t  }\n\n\tif (inpi[0] || inpi[1] || inpi[2])\n\t  {\n\t    return 1;\n\t  }\n\n\n\t// check, if some tet edge intersects triangle:\n\tconst Point<3> * line[2], *tetf[3];\n\tfor (i = 0; i <= 2; i++)\n\t  for (j = i+1; j <= 3; j++)\n\t    {\n\t      line[0] = tet[i];\n\t      line[1] = tet[j];\n\n\t      if (IntersectTriangleLine (tri, &line[0]))\n\t\treturn 1;\n\t    }\n\n\t// check, if triangle line intersects tet face:\n\tfor (i = 0; i <= 3; i++)\n\t  {\n\t    for (j = 0; j <= 2; j++)\n\t      tetf[j] = tet[(i+j) % 4];\n\t    \n\t    for (j = 0; j <= 2; j++)\n\t      {\n\t\tline[0] = tri[j];\n\t\tline[1] = tri[(j+1) % 3];\n\t\t\n\t\tif (IntersectTriangleLine (&tetf[0], &line[0]))\n\t\t  return 1;\n\t      }\n\t  }\n\n\n\treturn 0;\n//GH\tbreak;\n      }\n    case 1:\n      {\n\ttrip2 = 0;\n\twhile (trip2 == trip1)\n\t  trip2++;\n\ttrip3 = 3 - trip1 - trip2;\n\n\ttetp2 = 0;\n\twhile (tetp2 == tetp1)\n\t  tetp2++;\n\ttetp3 = 0;\n\twhile (tetp3 == tetp1 || tetp3 == tetp2)\n\t  tetp3++;\n\ttetp4 = 6 - tetp1 - tetp2 - tetp3;\n\n\tVec3d vtri1 = *tri[trip2] - *tri[trip1];\n\tVec3d vtri2 = *tri[trip3] - *tri[trip1];\n\tVec3d ntri;\n\tCross (vtri1, vtri2, ntri);\n\n\t// tri durch tet ?\n\t// fehlt noch\n\n\n\t// test 3 tet-faces:\n\tfor (i = 1; i <= 3; i++)\n\t  {\n\t    Vec3d vtet1, vtet2;\n\t    switch (i)\n\t      {\n\t      case 1:\n\t\t{\n\t\t  vtet1 = *tet[tetp2] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp3] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      case 2:\n\t\t{\n\t\t  vtet1 = *tet[tetp3] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp4] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      case 3:\n\t\t{\n\t\t  vtet1 = *tet[tetp4] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp2] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      }\n\t    \n\t    Vec3d ntet;\n\t    Cross (vtet1, vtet2, ntet);\n\t    \n\t    Vec3d crline = Cross (ntri, ntet);\n\n\t    double lcrline = crline.Length();\n\n\t    if (lcrline < eps * eps * eps * eps)  // new change !\n\t      continue;\n\n\t    if (vtri1 * crline + vtri2 * crline < 0)\n\t      crline *= -1;\n\n\t    crline /= lcrline;\n\n\t    double lam1, lam2, lam3, lam4;\n\t    LocalCoordinates (vtri1, vtri2, crline, lam1, lam2);\n\t    LocalCoordinates (vtet1, vtet2, crline, lam3, lam4);\n\t    \n\t    if (lam1 > -epsrel && lam2 > -epsrel &&\n\t\tlam3 > -epsrel && lam4 > -epsrel)\n\t      {\n\t\t\n\t\t/*\n\t\t(*testout) << \"lcrline = \" << lcrline \n\t\t\t   << \" eps = \" << eps << \" diam = \" << diam << endl;\n\t\t \n\t\t(*testout) << \"hit, cnt == 1 \" \n\t\t\t   << \"lam1,2,3,4 = \" << lam1 << \", \" \n\t\t\t   << lam2 << \", \" << lam3 << \", \" << lam4\n\t\t\t   << \"\\n\";\n\t\t*/\n\t\treturn 1;\n\t      }\n\t  }\n\treturn 0;\n//GH\tbreak;\n      }\n    case 2:\n      {\n\t// common edge\n\ttetp3 = 0;\n\twhile (tetp3 == tetp1 || tetp3 == tetp2)\n\t  tetp3++;\n\ttetp4 = 6 - tetp1 - tetp2 - tetp3;\n\ttrip3 = 3 - trip1 - trip2;\n\n\t//\t(*testout) << \"trip1,2,3 = \" << trip1 << \", \" << trip2 << \", \" << trip3 << endl;\n\t//\t(*testout) << \"tetp1,2,3,4 = \" << tetp1 << \", \" << tetp2 \n\t//\t\t   << \", \" << tetp3 << \", \" << tetp4 << endl;\n\n\tVec3d vtri = *tri[trip3] - *tri[trip1];\n\tVec3d vtet1 = *tet[tetp3] - *tri[trip1];\n\tVec3d vtet2 = *tet[tetp4] - *tri[trip1];\n\n\tVec3d n = *tri[trip2] - *tri[trip1];\n\tn /= n.Length();\n\n\tvtet1 -= (n * vtet1) * n;\n\tvtet2 -= (n * vtet2) * n;\n\n\n\tdouble lam1, lam2;\n\tLocalCoordinates (vtet1, vtet2, vtri, lam1, lam2);\n\t\n\tif (lam1 < -epsrel || lam2 < -epsrel)\n\t  return 0;\n\telse\n\t  {\n\t    /*\n\n\t    (*testout) << \"vtet1 = \" << vtet1 << endl;\n\t    (*testout) << \"vtet2 = \" << vtet2 << endl;\n\t    (*testout) << \"vtri = \" << vtri << endl;\n\t    (*testout) << \"lam1 = \" << lam1 << \" lam2 = \" << lam2 << endl;\n\t    (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2))\n\t\t       << \" = \" << (vtet1 * vtri) << endl;\n\t    (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2))\n\t\t       << \" = \" << (vtet2 * vtri) << endl;\n\t    \n\t    (*testout) << \"tet = \";\n\t    for (j = 0; j < 4; j++)\n\t      (*testout) << (*tet[j]) << \" \";\n\t    (*testout) << endl;\n\t    (*testout) << \"tri = \";\n\t    for (j = 0; j < 3; j++)\n\t      (*testout) << (*tri[j]) << \" \";\n\t    (*testout) << endl;\n\n\t    (*testout) << \"hit, cnt == 2\" << endl;\n\t    */\n\t    \n\t    return 1;\n\t  }\n\t  \n\tbreak;\n      }\n    case 3:\n      {\n\t// common face\n\treturn 0;\n      }\n    }\n\n  (*testout) << \"hit, cnt = \" << cnt << endl;\n  return 1;\n}\n\n\n\n\n\nint IntersectTetTriangleRef (const Point<3> ** tri, const int * tripi)\n{\n  int i, j;\n  double eps = 1e-8;\n  // double eps2 = eps * eps;\n\n  static Point<3> rtetp1(0, 0, 0);\n  static Point<3> rtetp2(1, 0, 0);  \n  static Point<3> rtetp3(0, 1, 0); \n  static Point<3> rtetp4(0, 0, 1);\n\n  static const Point<3> * tet[] = { &rtetp1, &rtetp2, &rtetp3, &rtetp4 };\n  static int tetpi[] = { 1, 2, 3, 4 };\n\n\n  //  return IntersectTetTriangle (tet, tri, tetpi, tripi);\n\n  \n  int cnt = 0;\n\n  int tetp1 = -1, tetp2 = -1;\n  int trip1 = -1, trip2 = -1;\n  int tetp3, tetp4, trip3;\n\n  /*\n  if (!tetpi)\n    {\n      for (i = 0; i <= 2; i++)\n\t{\n\t  for (j = 0; j <= 3; j++)\n\t    {\n\t      if (Dist2 (*tet[j], *tri[i]) < eps2)\n\t\t{\n\t\t  cnt++;\n\t\t  tetp2 = tetp1;\n\t\t  tetp1 = j;\n\t\t  trip2 = trip1;\n\t\t  trip1 = i;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n    }\n  else\n  */\n    {\n      for (i = 0; i <= 2; i++)\n\t{\n\t  for (j = 0; j <= 3; j++)\n\t    {\n\t      if (tetpi[j] == tripi[i])\n\t\t{\n\t\t  cnt++;\n\t\t  tetp2 = tetp1;\n\t\t  tetp1 = j;\n\t\t  trip2 = trip1;\n\t\t  trip1 = i;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n    }  \n  \n  //  (*testout) << \"cnt = \" << cnt << endl;\n\n\n  switch (cnt)\n    {\n    case 0:\n      {\n\tVec3d no, n;\n\t//\tint inpi[3];\n\tint pside[3][4];\n\n\tfor (j = 0; j < 3; j++)\n\t  {\n\t    pside[j][0] = (*tri[j])(0) > -eps;\n\t    pside[j][1] = (*tri[j])(1) > -eps;\n\t    pside[j][2] = (*tri[j])(2) > -eps;\n\t    pside[j][3] = (*tri[j])(0) + (*tri[j])(1) + (*tri[j])(2) < 1+eps;\n\t  }\n\n\t\n\tfor (j = 0; j < 4; j++)\n\t  {\n\t    if (!pside[0][j] && !pside[1][j] && !pside[2][j])\n\t      return 0;\n\t  }\n\n\tfor (j = 0; j < 3; j++)\n\t  {\n\t    if (pside[j][0] && pside[j][1] && pside[j][2] && pside[j][3])\n\t      return 1;\n\t  }\n\n\n\tconst Point<3> * line[2], *tetf[3];\n\tfor (i = 0; i <= 2; i++)\n\t  for (j = i+1; j <= 3; j++)\n\t    {\n\t      line[0] = tet[i];\n\t      line[1] = tet[j];\n\n\t      if (IntersectTriangleLine (tri, &line[0]))\n\t\treturn 1;\n\t    }\n\n\tfor (i = 0; i <= 3; i++)\n\t  {\n\t    for (j = 0; j <= 2; j++)\n\t      tetf[j] = tet[(i+j) % 4];\n\t    \n\t    for (j = 0; j <= 2; j++)\n\t      {\n\t\tline[0] = tri[j];\n\t\tline[1] = tri[(j+1) % 3];\n\n\t      if (IntersectTriangleLine (&tetf[0], &line[0]))\n\t\treturn 1;\n\t      }\n\t  }\n\n\n\treturn 0;\n\tbreak;\n      }\n    case 1:\n      {\n\ttrip2 = 0;\n\tif (trip2 == trip1)\n\t  trip2++;\n\ttrip3 = 3 - trip1 - trip2;\n\n\ttetp2 = 0;\n\twhile (tetp2 == tetp1)\n\t  tetp2++;\n\ttetp3 = 0;\n\twhile (tetp3 == tetp1 || tetp3 == tetp2)\n\t  tetp3++;\n\ttetp4 = 6 - tetp1 - tetp2 - tetp3;\n\n\tVec3d vtri1 = *tri[trip2] - *tri[trip1];\n\tVec3d vtri2 = *tri[trip3] - *tri[trip1];\n\tVec3d ntri;\n\tCross (vtri1, vtri2, ntri);\n\n\t// tri durch tet ?\n\n\t/*\n\tVec3d vtet1(*tet[tetp1], *tet[tetp2]);\n\tVec3d vtet2(*tet[tetp1], *tet[tetp3]);\n\tVec3d vtet3(*tet[tetp1], *tet[tetp4]);\n\tVec3d sol;\n\t\n\tSolveLinearSystem (vtet1, vtet2, vtet3, vtri1, sol);\n\tif (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0)\n\t  return 1;\n\n\tSolveLinearSystem (vtet1, vtet2, vtet3, vtri2, sol);\n\tif (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0)\n\t  return 1;\n\t*/\n\n\t// test 3 tet-faces:\n\tfor (i = 1; i <= 3; i++)\n\t  {\n\t    Vec3d vtet1, vtet2;\n\t    switch (i)\n\t      {\n\t      case 1:\n\t\t{\n\t\t  vtet1 = *tet[tetp2] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp3] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      case 2:\n\t\t{\n\t\t  vtet1 = *tet[tetp3] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp4] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      case 3:\n\t\t{\n\t\t  vtet1 = *tet[tetp4] - *tet[tetp1];\n\t\t  vtet2 = *tet[tetp2] - *tet[tetp1];\n\t\t  break;\n\t\t}\n\t      }\n\t    \n\t    Vec3d ntet;\n\t    Cross (vtet1, vtet2, ntet);\n\t    \n\t    Vec3d crline = Cross (ntri, ntet);\n\n\t    double lcrline = crline.Length();\n\t    if (lcrline < eps * eps)\n\t      continue;\n\n\n\t    if (vtri1 * crline + vtri2 * crline < 0)\n\t      crline *= -1;\n\n\t    double lam1, lam2, lam3, lam4;\n\t    LocalCoordinates (vtri1, vtri2, crline, lam1, lam2);\n\t    LocalCoordinates (vtet1, vtet2, crline, lam3, lam4);\n\t    \n\t    if (lam1 > -eps && lam2 > -eps &&\n\t\tlam3 > -eps && lam4 > -eps)\n\t      {\n\t\t//\t\t(*testout) << \"hit, cnt == 1\" << \"\\n\";\n\t\treturn 1;\n\t      }\n\t  }\n\n\treturn 0;\n\tbreak;\n      }\n    case 2:\n      {\n\t// common edge\n\ttetp3 = 0;\n\twhile (tetp3 == tetp1 || tetp3 == tetp2)\n\t  tetp3++;\n\ttetp4 = 6 - tetp1 - tetp2 - tetp3;\n\ttrip3 = 3 - trip1 - trip2;\n\n\t//\t(*testout) << \"trip1,2,3 = \" << trip1 << \", \" << trip2 << \", \" << trip3 << endl;\n\t//\t(*testout) << \"tetp1,2,3,4 = \" << tetp1 << \", \" << tetp2 \n\t//\t\t   << \", \" << tetp3 << \", \" << tetp4 << endl;\n\n\tVec3d vtri = *tri[trip3] - *tri[trip1];\n\tVec3d vtet1 = *tet[tetp3] - *tri[trip1];\n\tVec3d vtet2 = *tet[tetp4] - *tri[trip1];\n\n\tVec3d n = *tri[trip2] - *tri[trip1];\n\tn /= n.Length();\n\n\tvtet1 -= (n * vtet1) * n;\n\tvtet2 -= (n * vtet2) * n;\n\n\n\tdouble lam1, lam2;\n\tLocalCoordinates (vtet1, vtet2, vtri, lam1, lam2);\n\t\n\tif (lam1 < -eps || lam2 < -eps)\n\t  return 0;\n\telse\n\t  {\n\n// \t    (*testout) << \"vtet1 = \" << vtet1 << endl;\n// \t    (*testout) << \"vtet2 = \" << vtet2 << endl;\n// \t    (*testout) << \"vtri = \" << vtri << endl;\n// \t    (*testout) << \"lam1 = \" << lam1 << \" lam2 = \" << lam2 << endl;\n\n// \t    (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2))\n// \t\t       << \" = \" << (vtet1 * vtri) << endl;\n// \t    (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2))\n// \t\t       << \" = \" << (vtet2 * vtri) << endl;\n\t    \n// \t    (*testout) << \"tet = \";\n// \t    for (j = 0; j < 4; j++)\n// \t      (*testout) << (*tet[j]) << \" \";\n// \t    (*testout) << endl;\n// \t    (*testout) << \"tri = \";\n// \t    for (j = 0; j < 3; j++)\n// \t      (*testout) << (*tri[j]) << \" \";\n// \t    (*testout) << endl;\n\n// \t    (*testout) << \"hit, cnt == 2\" << endl;\n\n\t    return 1;\n\t  }\n\t  \n\tbreak;\n      }\n    case 3:\n      {\n\t// common face\n\treturn 0;\n      }\n    }\n\n  (*testout) << \"hit, cnt = \" << cnt << endl;\n  return 1;\n}\n\n\n\n\n\n\n\n\n\n\n\nint IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2)\n{\n  int i, j;\n  double diam = Dist (*tri1[0], *tri1[1]);\n  double epsrel = 1e-8;\n  double eps = diam * epsrel;\n  double eps2 = eps * eps;\n\n\n\n  int cnt = 0;\n  /*\n  int tri1pi[3];\n  int tri2pi[3];\n  */\n\n  //  int tri1p1 = -1; \n  /// int tri1p2 = -1;\n  //  int tri2p1 = -1;\n  //   int tri2p2 = -1;\n  //  int tri1p3, tri2p3;\n\n  /*\n  for (i = 0; i < 3; i++)\n    tri1pi[i] = -1;\n  */\n  for (i = 0; i <= 2; i++)\n    {\n      //      tri2pi[i] = -1;\n      for (j = 0; j <= 2; j++)\n\t{\n\t  if (Dist2 (*tri1[j], *tri2[i]) < eps2)\n\t    {\n\t      //\t      tri2pi[i] = j;\n\t      //\t      tri1pi[j] = i;\n\t      cnt++;\n\t      //\t      tri1p2 = tri1p1;\n\t      //\t      tri1p1 = j;\n\t      //\t      tri2p2 = tri2p1;\n\t      //\t      tri2p1 = i;\n\t      break;\n\t    }\n\t}\n    }\n  \n  switch (cnt)\n    {\n    case 0:\n      {\n\tconst Point<3> * line[2];\n\t\n\tfor (i = 0; i <= 2; i++)\n\t  {\n\t    line[0] = tri2[i];\n\t    line[1] = tri2[(i+1)%3];\n\n\t    if (IntersectTriangleLine (tri1, &line[0]))\n\t      {\n\t\t(*testout) << \"int1, line = \" << *line[0] << \" - \" << *line[1] << endl;\n\t\treturn 1;\n\t      }\n\t  }\t\n\n\tfor (i = 0; i <= 2; i++)\n\t  {\n\t    line[0] = tri1[i];\n\t    line[1] = tri1[(i+1)%3];\n\n\t    if (IntersectTriangleLine (tri2, &line[0]))\n\t      {\n\t\t(*testout) << \"int2, line = \" << *line[0] << \" - \" << *line[1] << endl;\n\t\treturn 1;\n\t      }\n\t  }\t\n\tbreak;\n      }\n    default:\n      return 0;\n    }\n\n  return 0;\n}\n\n\n\nvoid\nLocalCoordinates (const Vec3d & e1, const Vec3d & e2,\n\t\t  const Vec3d & v, double & lam1, double & lam2)\n{\n  double m11 = e1 * e1;\n  double m12 = e1 * e2;\n  double m22 = e2 * e2;\n  double rs1 = v * e1;\n  double rs2 = v * e2;\n  \n  double det = m11 * m22 - m12 * m12;\n  lam1 = (rs1 * m22 - rs2 * m12)/det;\n  lam2 = (m11 * rs2 - m12 * rs1)/det;\n}\n\n\n\n\n\nint CalcSphereCenter (const Point<3> ** pts, Point<3> & c)\n{\n  Vec3d row1 (*pts[0], *pts[1]);\n  Vec3d row2 (*pts[0], *pts[2]);\n  Vec3d row3 (*pts[0], *pts[3]);\n\n  Vec3d rhs(0.5 * (row1*row1),\n\t    0.5 * (row2*row2),\n\t    0.5 * (row3*row3));\n  Transpose (row1, row2, row3);\n  \n  Vec3d sol;\n  if (SolveLinearSystem (row1, row2, row3, rhs, sol))\n    {\n      (*testout) << \"CalcSphereCenter: degenerated\" << endl;\n      return 1;\n    }\n\n  c = *pts[0] + sol;\n  return 0;\n}\n\n\n\n\n\nint CalcTriangleCenter (const Point3d ** pts, Point3d & c)\n{\n  static DenseMatrix a(2), inva(2);\n  static Vector rs(2), sol(2);\n  double h = Dist(*pts[0], *pts[1]);\n\n  Vec3d v1(*pts[0], *pts[1]);\n  Vec3d v2(*pts[0], *pts[2]);\n\n  rs(0) = v1 * v1;\n  rs(1) = v2 * v2;\n\n  a(0,0) = 2 * rs(0);\n  a(0,1) = a(1,0) = 2 * (v1 * v2);\n  a(1,1) = 2 * rs(1);\n\n  if (fabs (a.Det()) <= 1e-12 * h * h)\n    {\n      (*testout) << \"CalcTriangleCenter: degenerated\" << endl;\n      return 1;\n    }\n\n  CalcInverse (a, inva);\n  inva.Mult (rs, sol);\n\n  c = *pts[0];\n  v1 *= sol(0);\n  v2 *= sol(1);\n\n  c += v1;\n  c += v2;\n\n  return 0;\n}\n\n\n\ndouble ComputeCylinderRadius (const Point3d & p1, \n\t\t\t      const Point3d & p2,\n\t\t\t      const Point3d & p3, \n\t\t\t      const Point3d & p4)\n{\n  Vec3d v12(p1, p2);\n  Vec3d v13(p1, p3);\n  Vec3d v14(p1, p4);\n\n  Vec3d n1 = Cross (v12, v13);\n  Vec3d n2 = Cross (v14, v12);\n\t\t\n  double n1l = n1.Length();\n  double n2l = n2.Length();\n  n1 /= n1l;\n  n2 /= n2l;\n\n  double v12len = v12.Length();\n  double h1 = n1l / v12len;\n  double h2 = n2l / v12len;\n  \n  /*\n  (*testout) << \"n1 = \" << n1 << \" n2 = \" << n2 \n\t     << \"h1 = \" << h1 << \" h2 = \" << h2 << endl;\n  */\n  return ComputeCylinderRadius (n1, n2, h1, h2);\n}\n\n\n\n\n/*\n  Two triangles T1 and T2 have normals n1 and n2.\n  The height over the common edge is h1, and h2.\n */\ndouble ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2,\n\t\t\t\t     double h1, double h2)\n{\n  Vec3d t1, t2;\n  double n11 = n1 * n1;\n  double n12 = n1 * n2;\n  double n22 = n2 * n2;\n  double det = n11 * n22 - n12 * n12;\n  \n  if (fabs (det) < 1e-14 * n11 * n22)\n    return 1e20;\n\n  // a biorthogonal bases   (ti * nj) = delta_ij:\n  t1 = (n22/det) * n1 + (-n12/det) * n2;\n  t2 = (-n12/det) * n1 + (n11/det) * n2;\n\n  // normalize:\n  t1 /= t1.Length();\n  t2 /= t2.Length();\n\n  /*\n    vector to center point has form\n    v = lam1 n1 + lam2 n2\n    and fulfills\n    t2 v = h1/2\n    t1 v = h2/2\n  */\n\n  double lam1 = 0.5 * h2 / (n1 * t1);\n  double lam2 = 0.5 * h1 / (n2 * t2);\n  \n  double rad = (lam1 * n1 + lam2 * n2).Length();\n  /*\n  (*testout) << \"n1 = \" << n1\n\t     << \" n2 = \" << n2\n\t     << \" t1 = \" << t1\n\t     << \" t2 = \" << t2\n\t     << \" rad = \" << rad << endl;\n  */\n  return rad;\n}\n    \n\n\n\n\n\ndouble MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p)\n{\n  Vec2d v(lp1, lp2);\n  Vec2d vlp(lp1, p);\n\n  // dist(lam) = \\| vlp \\|^2 - 2 lam (v1p, v) + lam^2 \\| v \\|^2\n\n  // lam = (v * vlp) / (v * v);\n  // if (lam < 0) lam = 0;\n  // if (lam > 1) lam = 1;\n\n  double num = v*vlp;\n  double den = v*v;\n\n  if (num <= 0) \n    return Dist2 (lp1, p);\n\n  if (num >= den) \n    return Dist2 (lp2, p);\n  \n  if (den > 0)\n    {\n      return vlp.Length2() - num * num /den;\n    }\n  else\n    return vlp.Length2();\n}\n\n\n\n\ndouble MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p)\n{\n  Vec3d v(lp1, lp2);\n  Vec3d vlp(lp1, p);\n\n  // dist(lam) = \\| vlp \\|^2 - 2 lam (v1p, v) + lam^2 \\| v \\|^2\n\n  // lam = (v * vlp) / (v * v);\n  // if (lam < 0) lam = 0;\n  // if (lam > 1) lam = 1;\n\n  double num = v*vlp;\n  double den = v*v;\n\n  if (num <= 0) \n    return Dist2 (lp1, p);\n\n  if (num >= den) \n    return Dist2 (lp2, p);\n  \n  if (den > 0)\n    {\n      return vlp.Length2() - num * num /den;\n    }\n  else\n    return vlp.Length2();\n}\n\n\ndouble MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p, double & lam)\n{\n  Vec3d v(lp1, lp2);\n  Vec3d vlp(lp1, p);\n\n  // dist(lam) = \\| vlp \\|^2 - 2 lam (v1p, v) + lam^2 \\| v \\|^2\n\n  // lam = (v * vlp) / (v * v);\n  // if (lam < 0) lam = 0;\n  // if (lam > 1) lam = 1;\n\n  double num = v*vlp;\n  double den = v*v;\n\n  if (num <= 0) \n  {\n    lam = 0.0;\n    return Dist2 (lp1, p);\n  }\n\n  if (num >= den) \n  {\n    lam = 1.0;\n    return Dist2 (lp2, p);\n  }\n  \n  lam = num/den;\n  if (den > 0)\n      return vlp.Length2() - num * num /den;\n  else\n    return vlp.Length2();\n}\n\n\ndouble MinDistTP2 (const Point3d & tp1, const Point3d & tp2, \n\t\t   const Point3d & tp3, const Point3d & p)\n{\n  double lam1, lam2;\n  double res;\n\n  LocalCoordinates (Vec3d (tp1, tp2), Vec3d (tp1, tp3),\n\t\t    Vec3d (tp1, p), lam1, lam2);\n  int in1 = lam1 >= 0;\n  int in2 = lam2 >= 0;\n  int in3 = lam1+lam2 <= 1;\n  \n  if (in1 && in2 && in3)\n    {\n      Point3d pp = tp1 + lam1 * Vec3d(tp1, tp2) + lam2 *  Vec3d (tp1, tp3);\n      res = Dist2 (p, pp);\n    }\n  else\n    {\n      res = Dist2 (tp1, p);\n      if (!in1)\n\t{\n\t  double hv = MinDistLP2 (tp1, tp3, p);\n\t  if (hv < res) res = hv; \n\t}\n      if (!in2)\n\t{\n\t  double hv = MinDistLP2 (tp1, tp2, p);\n\t  if (hv < res) res = hv; \n\t}\n      if (!in3)\n\t{\n\t  double hv = MinDistLP2 (tp2, tp3, p);\n\t  if (hv < res) res = hv; \n\t}\n      /*\n      double d1 = MinDistLP2 (tp1, tp2, p);\n      double d2 = MinDistLP2 (tp1, tp3, p);\n      double d3 = MinDistLP2 (tp2, tp3, p);\n      res = min3 (d1, d2, d3);\n      */\n    }\n\n  return res;\n\n  Vec3d pp1(tp1, p);\n  Vec3d v1(tp1, tp2), v2(tp1, tp3);\n\n  double c = pp1.Length2();\n  double cx = -2 * (pp1 * v1);\n  double cy = -2 * (pp1 * v2);\n  double cxx = v1.Length2();\n  double cxy = 2 * (v1 * v2);\n  double cyy = v2.Length2();\n\n  QuadraticPolynomial2V pol (-c, -cx, -cy, -cxx, -cxy, -cyy);\n  double res2 =  - pol.MaxUnitTriangle ();\n\n  if (fabs (res - res2) > 1e-8)\n    cout << \"res and res2 differ: \" << res << \" != \" << res2 << endl;\n  return res2;\n}\n\n\n// 0 checks !!!\ndouble MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2,\n\t\t  const Point3d & l2p1, const Point3d & l2p2, double & lam1, double & lam2 )\n{\n  // dist(lam1,lam2) = \\| l2p1+lam2v2 - (l1p1+lam1 v1) \\|\n  // min !\n\n  Vec3d l1l2 (l1p1, l2p1);\n  Vec3d v1 (l1p1, l1p2);\n  Vec3d v2 (l2p1, l2p2);\n\n  double a11, a12, a22, rs1, rs2;\n  double det;\n\n  a11 = v1*v1;\n  a12 = -(v1*v2);\n  a22 = v2*v2;\n  rs1 = l1l2 * v1;\n  rs2 = - (l1l2 * v2);\n  \n  det = a11 * a22 - a12 * a12;\n  if (det < 1e-14 * a11 * a22) \n    det = 1e-14 * a11 * a22;  // regularization should be stable\n\n  if (det < 1e-20)\n    det = 1e-20;\n\n\n  lam1 = (a22 * rs1 - a12 * rs2) / det;\n  lam2 = (-a12 * rs1 + a11 * rs2) / det;\n\n  if (lam1 >= 0 && lam2 >= 0 && lam1 <= 1 && lam2 <= 1)\n    {\n      Vec3d v = l1l2 + (-lam1) * v1 + lam2 * v2;\n      return v.Length2();\n    }\n\n  double minv, hv;\n  minv = MinDistLP2 (l1p1, l1p2, l2p1, lam1);\n  lam2 = 0.;\n  hv =  MinDistLP2 (l1p1, l1p2, l2p2, lam1);\n  if (hv < minv)\n  {\n    lam2 = 1.;\n    minv = hv;\n  }\n\n  hv =  MinDistLP2 (l2p1, l2p2, l1p1, lam2);\n  if (hv < minv)\n  {\n    lam1 = 0.;\n    minv = hv;\n  }\n  hv =  MinDistLP2 (l2p1, l2p2, l1p2, lam2);\n  if (hv < minv)\n  {\n    lam1 = 1.;\n    minv = hv;\n  }\n\n  return minv;\n}\n\t\t\t \n}\n\n\n"
  },
  {
    "path": "libsrc/gprim/geomtest3d.hpp",
    "content": "#ifndef FILE_GEOMTEST3D\n#define FILE_GEOMTEST3D\n\n/* *************************************************************************/\n/* File:   geomtest3d.hh                                                   */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   13. Feb. 98                                                     */\n/* *************************************************************************/\n\n#include \"geom3d.hpp\"\n#include \"geomobjects.hpp\"\n\nnamespace netgen\n{\n\n\nextern int\nIntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line);\n\n\n\n/**\n  Returns 0, iff\n  closure (tet)  cup  closure (tri)  is empty, one corner point of tet,\n  one edge of tet or one face of tet\n */\nextern int \nIntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri,\n\t\t      const int * tetpi = NULL, const int * tripi = NULL);\n\n/**\n  Same test as above, but tet int reference position (0, ex, ey, ez),\n  tetpi = 1, 2, 4, 5\n */\nextern int \nIntersectTetTriangleRef (const Point3d ** tri, const int * tripi = NULL);\n\n\n// 1, iff not regular triangulation\nextern int \nIntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2);\n\n\nextern void\nLocalCoordinates (const Vec3d & e1, const Vec3d & e2,\n\t\t  const Vec3d & v, double & lam1, double & lam2);\n\n/// return 1 = degenerated sphere\nextern int\nCalcSphereCenter (const Point<3> ** pts, Point<3> & c);\n\n/// return 1 = degenerated triangle\nextern int\nCalcTriangleCenter (const Point3d ** pts, Point3d & c);\n\n\n\n/*\n  Compute radius of cylinder fitting 4 points.\n  cylinder axis is in the direction of p1-p2\n*/\nextern double ComputeCylinderRadius (const Point3d & p1, const Point3d & p2,\n\t\t\t\t     const Point3d & p3, const Point3d & p4);\n\n/*\n  Two triangles T1 and T2 have normals n1 and n2.\n  The height over the common edge is h1, and h2.\n  Radius of cylinder fitting both triangles\n*/\nextern double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2,\n\t\t\t\t     double h1, double h2);\n\n/// Minimal distance of point p to the line segment [lp1,lp2]\nDLL_HEADER double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p);\n\n/// Minimal distance of point p to the line segment [lp1,lp2]\nDLL_HEADER double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p);\n\n/// Minimal distance of point p to the triangle segment [tp1,tp2,pt3]\nDLL_HEADER double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, \n\t\t\t  const Point3d & tp3, const Point3d & p);\n\n  inline double MinDistTP2 (const Point<2> & tp1, const Point<2> & tp2, \n                            const Point<2> & tp3, const Point<2> & p)\n  {\n    return MinDistTP2 (Point<3> (tp1(0), tp1(1),0),\n                       Point<3> (tp2(0), tp2(1),0),\n                       Point<3> (tp3(0), tp3(1),0),\n                       Point<3> (p(0), p(1),0));\n  }\n\n/// Minimal distance of the 2 lines [l1p1,l1p2] and [l2p1,l2p2]\nextern double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2,\n\t\t\t  const Point3d & l2p1, const Point3d & l2p2);\n\nextern double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2,\n\t\t  const Point3d & l2p1, const Point3d & l2p2, double & lam1, double & lam2 );\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/gprim.hpp",
    "content": "#ifndef FILE_GPRIM\n#define FILE_GPRIM\n\n/* *************************************************************************/\n/* File:   gprim.hpp                                                        */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   14. Aug. 97                                                     */\n/* *************************************************************************/\n\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n\n\n\n\n#include \"geomobjects.hpp\"\n#include \"geomops.hpp\"\n#include \"geomfuncs.hpp\"\n\n#include \"geom2d.hpp\"\n#include \"geom3d.hpp\"\n\n#include \"geomtest3d.hpp\"\n#include \"transform3d.hpp\"\n\n#include \"adtree.hpp\"\n\n#include \"spline.hpp\"\n#include \"splinegeometry.hpp\"\n\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/spline.cpp",
    "content": "/*\n\nSpline curve for Mesh generator\n\n*/\n\n#include <mystdlib.h>\n#include <linalg.hpp>\n#include <gprim.hpp>\n#include \"spline.hpp\"\n\n#include <core/register_archive.hpp>\n\nnamespace netgen\n{\n\n  // just for testing (JS)\n  template <int D>\n  void ProjectTrivial (const SplineSeg3<D> & seg, \n                       const Point<D> point, Point<D> & point_on_curve, double & t)\n  {\n    double mindist = -1;\n    for (int i = 0; i <= 1000; i++)\n      {\n        double ht = double(i)/1000;\n        Point<D> p = seg.GetPoint(ht);\n        double dist = Dist2 (p, point);\n        if (i == 0 || dist < mindist)\n          {\n            mindist = dist;\n            t = ht;\n          }\n      }\n    point_on_curve = seg.GetPoint(t);\n  }\n\n\n  template <> \n  void CircleSeg<3> :: LineIntersections (const double a, const double b, const double c,\n\t\t\t\t\t  NgArray < Point<3> > & points, const double eps) const\n  {\n    cerr << \"CircleSeg<3>::LineIntersections not implemented\" << endl;\n  }\n  \n  template <> \n  void CircleSeg<2> :: LineIntersections (const double a, const double b, const double c,\n\t\t\t\t\t  NgArray < Point<2> > & points, const double eps) const\n  {\n    points.SetSize(0);\n\n    double px=0,py=0;\n\n    if(fabs(b) > 1e-20)\n      py = -c/b;\n    else\n      px = -c/a;\n\n    const double c1 = a*a + b*b;\n    const double c2 = 2. * ( a*(py-pm(1)) - b*(px-pm(0)));\n    const double c3 = pow(px-pm(0),2) + pow(py-pm(1),2) - pow(Radius(),2);\n    \n    const double discr = c2*c2 - 4*c1*c3;\n\n    if(discr < 0)\n      return;\n\n    NgArray<double> t;\n\n    if(fabs(discr) < 1e-20)\n      t.Append(-0.5*c2/c1);\n    else\n      {\n\tt.Append((-c2+sqrt(discr))/(2.*c1));\n\tt.Append((-c2-sqrt(discr))/(2.*c1));\n      }\n\n    for(int i=0; i<t.Size(); i++)\n      {\n\tPoint<2> p (px-t[i]*b,py+t[i]*a);\n\n\tdouble angle = atan2(p(1),p(0))+M_PI;\n\n\tif(angle > StartAngle()-eps && angle < EndAngle()+eps)\n\t  points.Append(p);\n      }\n  }\n\n\n\n\n  template<int D>\n  SplineSeg3<D> :: SplineSeg3 (const GeomPoint<D> & ap1, \n\t\t\t       const GeomPoint<D> & ap2,\n\t\t\t       const GeomPoint<D> & ap3,\n                               string bcname,\n                               double maxh)\n    : SplineSeg<D>(maxh, bcname), p1(ap1), p2(ap2), p3(ap3)\n  {\n    weight = Dist (p1, p3) / sqrt (0.5 * (Dist2 (p1, p2) + Dist2 (p2, p3)));\n    // weight = sqrt(2);\n    // cout << \"weight = \" << weight << endl;\n    proj_latest_t = 0.5;\n  }\n\n  template<int D>\n  SplineSeg3<D> :: SplineSeg3 (const GeomPoint<D> & ap1,\n\t\t\t       const GeomPoint<D> & ap2,\n\t\t\t       const GeomPoint<D> & ap3,\n                               double aweight,\n                               string bcname,\n                               double maxh)\n    : SplineSeg<D>(maxh, bcname), p1(ap1), p2(ap2), p3(ap3), weight(aweight)\n  {\n    proj_latest_t = 0.5;\n  }\n\n  template<int D>\n  Point<D> SplineSeg3<D> :: GetPoint (double t) const\n  {\n    double b1, b2, b3;\n\n    b1 = (1-t)*(1-t);\n    b2 = weight * t * (1-t);\n    b3 = t * t;\n\n    Vec<D> hp = b1 * Vec<D>(p1) + b2 * Vec<D>(p2) + b3 * Vec<D>(p3);\n    double w = b1+b2+b3;\n    return Point<D> ((1.0/w)*hp);\n    /*\n    double x, y, w;\n    x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3;\n    y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3;\n    w = b1 + b2 + b3;\n\n    if(D==3)\n      {\n\tdouble z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3;\n\treturn Point<D> (x/w, y/w, z/w);\n      }\n    else\n      return Point<D> (x/w, y/w);\n    */\n  }\n\n\n\n\n  template<int D>\n  Vec<D> SplineSeg3<D> :: GetTangent (const double t) const\n  {\n    const double b1 = (1.-t)*((weight-2.)*t-weight);\n    const double b2 = weight*(1.-2.*t);\n    const double b3 = t*((weight-2)*t+2.);\n\n\n    Vec<D> retval;\n    for(int i=0; i<D; i++) \n      retval(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);\n\n    return retval;\n\n  }\n\n\n  template<int D>\n  void SplineSeg3<D> :: GetCoeff (Vector & u) const\n  {\n    DenseMatrix a(6, 6);\n    DenseMatrix ata(6, 6);\n    Vector f(6);\n\n    u.SetSize(6);\n\n    //  ata.SetSymmetric(1);\n\n    double t = 0;\n    for (int i = 0; i < 5; i++, t += 0.25)\n      {\n\tPoint<D> p = GetPoint (t);\n\ta(i, 0) = p(0) * p(0);\n\ta(i, 1) = p(1) * p(1);\n\ta(i, 2) = p(0) * p(1);\n\ta(i, 3) = p(0);\n\ta(i, 4) = p(1);\n\ta(i, 5) = 1;\n      }\n    a(5, 0) = 1;\n\n    CalcAtA (a, ata);\n\n    u = 0;\n    u(5) = 1;\n    a.MultTrans (u, f);\n    ata.Solve (f, u);\n\n    // the sign\n    Point<D> p0 = GetPoint(0);\n    Vec<D> ht = GetTangent(0);\n    Vec<2> tang(ht(0), ht(1));\n\n    double gradx = 2.*u(0)*p0(0) + u(2)*p0(1) + u(3);\n    double grady = 2.*u(1)*p0(1) + u(2)*p0(0) + u(4);\n    Vec<2> gradn (grady, -gradx);\n  \n    if (tang * gradn < 0) u *= -1;\n  }\n\n\n  template<int D>\n  void SplineSeg3<D> :: GetCoeff (Vector & u, Point<D> pref) const\n  {\n    DenseMatrix a(6, 6);\n    DenseMatrix ata(6, 6);\n    Vector f(6);\n\n    u.SetSize(6);\n\n    //  ata.SetSymmetric(1);\n\n    double t = 0;\n    for (int i = 0; i < 5; i++, t += 0.25)\n      {\n\tVec<D> p = GetPoint (t)-pref;\n\ta(i, 0) = p(0) * p(0);\n\ta(i, 1) = p(1) * p(1);\n\ta(i, 2) = p(0) * p(1);\n\ta(i, 3) = p(0);\n\ta(i, 4) = p(1);\n\ta(i, 5) = 1;\n      }\n    a(5, 0) = 1;\n\n    CalcAtA (a, ata);\n\n    u = 0;\n    u(5) = 1;\n    a.MultTrans (u, f);\n    ata.Solve (f, u);\n\n    // the sign\n    // Point<D> p0 = GetPoint(0);\n    Vec<D> ht = GetTangent(0);\n    Vec<2> tang(ht(0), ht(1));\n\n    double gradx = u(3);\n    double grady = u(4);\n    // double gradx = 2.*u(0)*p0(0) + u(2)*p0(1) + u(3);\n    // double grady = 2.*u(1)*p0(1) + u(2)*p0(0) + u(4);\n    Vec<2> gradn (grady, -gradx);\n  \n    if (tang * gradn < 0) u *= -1;\n  }\n  \n\n\n  template<int D>\n  void SplineSeg3<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const\n  {\n    double t_old = -1;\n\n    /*\n    if(proj_latest_t > 0. && proj_latest_t < 1.)\n      t = proj_latest_t;\n    else\n      t = 0.5;\n    */\n    double tmin = 1;\n    double dist_min2 = Dist2 (GetPoint(tmin), point);\n    for (double ti = 0; ti < 0.99; ti += 0.25)\n      {\n        double di = Dist2(GetPoint(ti), point);\n        if (di < dist_min2)\n          {\n            tmin = ti;\n            dist_min2 = di;\n          }\n      }\n    t = tmin;\n    \n    Point<D> phi;\n    Vec<D> phip,phipp,phimp;\n    \n    int i=0;\n\n    while(t > -0.5 && t < 1.5 && i<20 && fabs(t-t_old) > 1e-15 )\n      {\n        GetDerivatives(t,phi,phip,phipp);\n\t\n        t_old = t;\n\n        phimp = phi-point;\n\n        //t = min2(max2(t-(phip*phimp)/(phipp*phimp + phip*phip),0.),1.);\n        t -= (phip*phimp)/(phipp*phimp + phip*phip);\n\n        i++;\n      }\n    \n    //if(i<10 && t > 0. && t < 1.)\n    if(i<20 && t > -0.4 && t < 1.4)\n      {\n        if(t < 0)\n          {\n            t = 0.;\n          }\n        if(t > 1)\n          {\n            t = 1.;\n          }\n\n        point_on_curve = SplineSeg3<D>::GetPoint(t);\n\t\n        double dist = Dist(point,point_on_curve);\n\t\n        phi =  SplineSeg3<D> ::GetPoint(0);\n        double auxdist = Dist(phi,point);\n        if(auxdist < dist)\n          {\n            t = 0.;\n            point_on_curve = phi;\n            dist = auxdist;\n          }\n        phi =  SplineSeg3<D> ::GetPoint(1);\n        auxdist = Dist(phi,point);\n        if(auxdist < dist)\n          {\n            t = 1.;\n            point_on_curve = phi;\n            dist = auxdist;\n          }\n      }\n    else\n      {\n        double t0 = 0;\n        double t1 = 0.5;\n        double t2 = 1.;\n\n        double d0,d1,d2;\n\n\t\n        //(*testout) << \"newtonersatz\" << endl;\n        while(t2-t0 > 1e-8)\n          {\n\t    \n            phi =  SplineSeg3<D> ::GetPoint(t0); d0 = Dist(phi,point);\n            phi =  SplineSeg3<D> ::GetPoint(t1); d1 = Dist(phi,point);\n            phi =  SplineSeg3<D> ::GetPoint(t2); d2 = Dist(phi,point);\n\n            double a = (2.*d0 - 4.*d1 +2.*d2)/pow(t2-t0,2);\n\n            if(a <= 0)\n              {\n                if(d0 < d2)\n                  t2 -= 0.3*(t2-t0);\n                else\n                  t0 += 0.3*(t2-t0);\n\n                t1 = 0.5*(t2+t0);\n              }\n            else\n              {\n                double b = (d1-d0-a*(t1*t1-t0*t0))/(t1-t0);\n\n                double auxt1 = -0.5*b/a;\n\n                if(auxt1 < t0)\n                  {\n                    t2 -= 0.4*(t2-t0);\n                    t0 = max2(0.,t0-0.1*(t2-t0));\n                  }\n                else if (auxt1 > t2)\n                  {\n                    t0 += 0.4*(t2-t0);\n                    t2 = min2(1.,t2+0.1*(t2-t0));\n                  }\n                else\n                  {\n                    t1 = auxt1;\n                    auxt1 = 0.25*(t2-t0);\n                    t0 = max2(0.,t1-auxt1);\n                    t2 = min2(1.,t1+auxt1);\n                  }\n\t\t\n                t1 = 0.5*(t2+t0);\n              }  \n\n          }\n\n\t\n        phi =  SplineSeg3<D> ::GetPoint(t0); d0 = Dist(phi,point);\n        phi =  SplineSeg3<D> ::GetPoint(t1); d1 = Dist(phi,point);\n        phi =  SplineSeg3<D> ::GetPoint(t2); d2 = Dist(phi,point);\n\n        double mind = d0;\n        t = t0;\n        if(d1 < mind)\n          {\n            t = t1;\n            mind = d1;\n          }\n        if(d2 < mind)\n          {\n            t = t2;\n            mind = d2;\n          }\n\n        point_on_curve =  SplineSeg3<D> ::GetPoint(t);\n      }\n    //(*testout) << \" latest_t \" << proj_latest_t << \" t \" << t << endl;\n\n    proj_latest_t = t;\n\n    /*\n    // test it by trivial sampling\n    double ht;\n    Point<D> hp;\n    ProjectTrivial (*this, point, hp, ht);\n    if (fabs (t-ht) > 1e-3)\n    {\n    // if (Dist2 (point, hp) < Dist2 (point, point_on_curve))\n    cout << \"project is wrong\" << endl;\n    cout << \"t = \" << t << \", ht = \" << ht << endl;\n    cout << \"dist org = \" << Dist(point, point_on_curve) << endl;\n    cout << \"dist trivial = \" << Dist(point, hp) << endl;\n    }\n    */\n  }\n\n\n\n\n\n\n  template<int D>\n  void SplineSeg3<D> :: GetDerivatives (const double t, \n                                        Point<D> & point,\n                                        Vec<D> & first,\n                                        Vec<D> & second) const\n  {\n    Vec<D> v1(p1), v2(p2), v3(p3);\n\n    double b1 = (1.-t)*(1.-t);\n    double b2 = weight*t*(1.-t);\n    double b3 = t*t;\n    double w = b1+b2+b3;\n    b1 *= 1./w; b2 *= 1./w; b3 *= 1./w;\n\n    double b1p = 2.*(t-1.);\n    double b2p = weight*(1.-2.*t);\n    double b3p = 2.*t;\n    const double wp = b1p+b2p+b3p;\n    const double fac1 = wp/w;\n    b1p *= 1./w; b2p *= 1./w; b3p *= 1./w;\n\n    const double b1pp = 2.;\n    const double b2pp = -2.*weight;\n    const double b3pp = 2.;\n    const double wpp = b1pp+b2pp+b3pp;\n    const double fac2 = (wpp*w-2.*wp*wp)/(w*w);\n\n    for(int i=0; i<D; i++)\n      point(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);\n    \n \n    first = (b1p - b1*fac1) * v1 +\n      (b2p - b2*fac1) * v2 +\n      (b3p - b3*fac1) * v3;\n\n    second = (b1pp/w - 2*b1p*fac1 - b1*fac2) * v1 +\n      (b2pp/w - 2*b2p*fac1 - b2*fac2) * v2 +\n      (b3pp/w - 2*b3p*fac1 - b3*fac2) * v3;\n  }\n\n\n\n  template<>\n  double SplineSeg3<2> :: MaxCurvature(void) const\n  {\n    Vec<2> v1 = p1-p2;\n    Vec<2> v2 = p3-p2;\n    double l1 = v1.Length();\n    double l2 = v2.Length();\n        \n    double cosalpha = (v1*v2)/(l1*l2);\n    \n            \n    return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha));\n  }\n\n  template<>\n  double SplineSeg3<3> :: MaxCurvature(void) const\n  {\n    Vec<3> v1 = p1-p2;\n    Vec<3> v2 = p3-p2;\n    double l1 = v1.Length();\n    double l2 = v2.Length();\n        \n    double cosalpha = v1*v2/(l1*l2);\n    \n        \n    return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha));\n  }\n\n\n  template<int D>\n  void SplineSeg3<D> :: LineIntersections (const double a, const double b, const double c,\n\t\t\t\t\t   NgArray < Point<D> > & points, const double eps) const\n  {\n    points.SetSize(0);\n\n    double t;\n\n    const double c1 = a*p1(0) - weight*a*p2(0) + a*p3(0) \n      + b*p1(1) - weight*b*p2(1) + b*p3(1) \n      + (2.-weight)*c;\n    const double c2 = -2.*a*p1(0) + weight*a*p2(0) -2.*b*p1(1) + weight*b*p2(1) + (weight-2.)*c;\n    const double c3 = a*p1(0) + b*p1(1) + c;\n\n    if(fabs(c1) < 1e-20)\n      {\n\tif(fabs(c2) < 1e-20)\n\t  return;\n\n\tt = -c3/c2;\n\tif((t > -eps) && (t < 1.+eps))\n\t  points.Append(GetPoint(t));\n\treturn;\n      }\n\n    const double discr = c2*c2-4.*c1*c3;\n\n    if(discr < 0)\n      return;\n\n    if(fabs(discr/(c1*c1)) < 1e-14)\n      {\n\tt = -0.5*c2/c1;\n\tif((t > -eps) && (t < 1.+eps))\n\t  points.Append(GetPoint(t));\n\treturn;\n      }\n\n    t = (-c2 + sqrt(discr))/(2.*c1);\n    if((t > -eps) && (t < 1.+eps))\n      points.Append(GetPoint(t));\n\n    t = (-c2 - sqrt(discr))/(2.*c1);\n    if((t > -eps) && (t < 1.+eps))\n      points.Append(GetPoint(t));\n  }\n\n\n  template < int D >\n  void SplineSeg3<D> :: GetRawData (NgArray<double> & data) const\n  {\n    data.Append(3);\n    for(int i=0; i<D; i++)\n      data.Append(p1[i]);\n    for(int i=0; i<D; i++)\n      data.Append(p2[i]);\n    for(int i=0; i<D; i++)\n      data.Append(p3[i]);\n  }\n\n\n\n  template class  SplineSeg3<2>;\n  template class  SplineSeg3<3>;\n\n  RegisterClassForArchive<SplineSeg<2>> regss2;\n  RegisterClassForArchive<SplineSeg<3>> regss3;\n  RegisterClassForArchive<LineSeg<2>, SplineSeg<2>> regls2;\n  RegisterClassForArchive<LineSeg<3>, SplineSeg<3>> regls3;\n  RegisterClassForArchive<SplineSeg3<2>, SplineSeg<2>> regsss2;\n  RegisterClassForArchive<SplineSeg3<3>, SplineSeg<3>> regsss3;\n}\n"
  },
  {
    "path": "libsrc/gprim/spline.hpp",
    "content": "#ifndef FILE_SPLINE_HPP\n#define FILE_SPLINE_HPP\n\n/**************************************************************************/\n/* File:   spline.hpp                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   24. Jul. 96                                                    */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n\n\n  /*\n    Spline curves for 2D mesh generation\n  */\n\n\n  /// Geometry point\n  template < int D >\n  class GeomPoint : public Point<D>\n  {\n  public:\n    /// refinement factor at point\n    double refatpoint;\n    /// max mesh-size at point\n    double hmax;\n    /// hp-refinement\n    double hpref;\n    /// \n    string name;\n    ///\n    GeomPoint () { ; }\n\n    ///\n    GeomPoint (const Point<D> & ap, double aref = 1, double ahpref=0)\n      : Point<D>(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; }\n    void DoArchive(Archive& ar)\n    {\n      Point<D>::DoArchive(ar);\n      ar & refatpoint & hmax & hpref;\n    }\n  };\n\n\n\n\n  /// base class for 2d - segment\n  template < int D >\n  class SplineSeg\n  {\n    double maxh;\n    string bcname;\n  public:\n    SplineSeg (double amaxh = 1e99, string abcname = \"default\")\n      : maxh(amaxh), bcname(abcname) { ; }\n    ///\n    virtual ~SplineSeg() { ; }\n    /// calculates length of curve\n    virtual double Length () const;\n    /// returns point at curve, 0 <= t <= 1\n    virtual Point<D> GetPoint (double t) const = 0;\n    /// returns a (not necessarily unit-length) tangent vector for 0 <= t <= 1\n    virtual Vec<D> GetTangent (const double t) const\n    { \n      cerr << \"GetTangent not implemented for spline base-class\"  << endl; \n      Vec<D> dummy; return dummy;\n    }\n\n    virtual void GetDerivatives (const double t, \n\t\t\t\t Point<D> & point,\n\t\t\t\t Vec<D> & first,\n\t\t\t\t Vec<D> & second) const \n    {\n      double eps = 1e-6;\n      point = GetPoint (t);\n      Point<D> pl = GetPoint (t-eps);\n      Point<D> pr = GetPoint (t+eps);\n      first = 1.0/(2*eps) * (pr-pl);\n      second = 1.0/sqr(eps) * ( (pr-point)+(pl-point));\n    }\n\n    virtual void DoArchive(Archive& ar) = 0;\n\n    /// returns initial point on curve\n    virtual const GeomPoint<D> & StartPI () const = 0;\n    /// returns terminal point on curve\n    virtual const GeomPoint<D> & EndPI () const = 0;\n    /** writes curve description for fepp:\n\tfor implicitly given quadratic curves, the 6 coefficients of\n\tthe polynomial\n\t$$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$\n\tare written to ost */\n    void PrintCoeff (ostream & ost) const;\n\n    virtual void GetCoeff (Vector & coeffs) const = 0;\n    virtual void GetCoeff (Vector & coeffs, Point<D> p0) const { ; } \n\n    virtual void GetPoints (int n, NgArray<Point<D> > & points) const;\n\n    /** calculates (2D) lineintersections:\n\tfor lines $$ a x + b y + c = 0 $$ the intersecting points are calculated\n\tand stored in points */\n    virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t    NgArray < Point<D> > & points, const double eps) const\n    {points.SetSize(0);}\n\n    // is the point in the convex hull (increased by eps) of the spline ?\n    virtual bool InConvexHull (Point<D> p, double eps) const = 0; \n\n    virtual double MaxCurvature(void) const = 0;\n\n    virtual string GetType(void) const {return \"splinebase\";}\n\n    virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const\n    { cerr << \"Project not implemented for spline base-class\" << endl;}\n\n    virtual void GetRawData (NgArray<double> & data) const\n    { cerr << \"GetRawData not implemented for spline base-class\" << endl;}\n\n    double GetMaxh() const { return maxh; }\n    string GetBCName() const { return bcname; }\n  };\n\n\n  /// Straight line form p1 to p2\n  template< int D >\n  class LineSeg : public SplineSeg<D>\n  {\n    ///\n    GeomPoint<D> p1, p2;\n  public:\n    ///\n    LineSeg (const GeomPoint<D> & ap1, const GeomPoint<D> & ap2,\n             double maxh=1e99, string bcname=\"default\");\n    ///\n    // default constructor for archive\n    LineSeg() {}\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & p1 & p2;\n    }\n    virtual double Length () const;\n    ///\n    inline virtual Point<D> GetPoint (double t) const;\n    ///\n    virtual Vec<D> GetTangent (const double t) const;\n\n  \n    virtual void GetDerivatives (const double t, \n\t\t\t\t Point<D> & point,\n\t\t\t\t Vec<D> & first,\n\t\t\t\t Vec<D> & second) const;\n    ///\n    virtual const GeomPoint<D> & StartPI () const { return p1; };\n    ///\n    virtual const GeomPoint<D> & EndPI () const { return p2; }\n    ///\n    virtual void GetCoeff (Vector & coeffs) const;\n    virtual void GetCoeff (Vector & coeffs, Point<D> p0) const;\n    \n    virtual string GetType(void) const {return \"line\";}\n\n    virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t    NgArray < Point<D> > & points, const double eps) const;\n    \n    virtual bool InConvexHull (Point<D> p, double eps) const\n    {\n      return MinDistLP2 (p1, p2, p) < sqr(eps);\n    }\n    \n    virtual double MaxCurvature(void) const {return 0;}\n\n    virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;\n\n    virtual void GetRawData (NgArray<double> & data) const;\n  };\n\n\n  /// curve given by a rational, quadratic spline (including ellipses)\n  template< int D >\n  class SplineSeg3 : public SplineSeg<D>\n  {\n    ///\n    GeomPoint<D> p1, p2, p3;\n    double weight;\n    mutable double proj_latest_t;\n  public:\n    ///\n    DLL_HEADER SplineSeg3 (const GeomPoint<D> & ap1,\n\t\tconst GeomPoint<D> & ap2, \n\t\tconst GeomPoint<D> & ap3,\n                string bcname=\"default\",\n                double maxh=1e99);\n    DLL_HEADER SplineSeg3 (const GeomPoint<D> & ap1,\n\t\tconst GeomPoint<D> & ap2,\n\t\tconst GeomPoint<D> & ap3,\n                double aweight,\n                string bcname=\"default\",\n                double maxh=1e99);\n    // default constructor for archive\n    SplineSeg3() {}\n    ///\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & p1 & p2 & p3 & weight & proj_latest_t;\n    }\n    ///\n    double GetWeight () const { return weight; }\n    void SetWeight (double w) { weight = w; }\n    ///\n    DLL_HEADER virtual Point<D> GetPoint (double t) const;\n    ///\n    DLL_HEADER virtual Vec<D> GetTangent (const double t) const;\n\n  \n    DLL_HEADER virtual void GetDerivatives (const double t, \n\t\t\t\t Point<D> & point,\n\t\t\t\t Vec<D> & first,\n\t\t\t\t Vec<D> & second) const;\n    ///\n    DLL_HEADER virtual const GeomPoint<D> & StartPI () const { return p1; };\n    ///\n    DLL_HEADER virtual const GeomPoint<D> & EndPI () const { return p3; }\n    ///\n    DLL_HEADER virtual void GetCoeff (Vector & coeffs) const;\n    DLL_HEADER virtual void GetCoeff (Vector & coeffs, Point<D> p0) const;\n    \n    virtual string GetType(void) const {return \"spline3\";}\n\n    const GeomPoint<D> & TangentPoint (void) const { return p2; }\n\n    DLL_HEADER virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t    NgArray < Point<D> > & points, const double eps) const;\n\n    virtual bool InConvexHull (Point<D> p, double eps) const\n    {\n      return MinDistTP2 (p1, p2, p3, p) < sqr(eps);\n    }\n\n    DLL_HEADER virtual double MaxCurvature(void) const;\n\n    DLL_HEADER virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;\n\n    DLL_HEADER virtual void GetRawData (NgArray<double> & data) const;\n  };\n\n\n  // Gundolf Haase  8/26/97\n  /// A circle\n  template < int D >\n  class CircleSeg : public SplineSeg<D>\n  {\n    ///\n  private:\n    GeomPoint<D>\tp1, p2, p3;\n    //const GeomPoint<D>\t&p1, &p2, &p3;\n    Point<D>\t\tpm;\n    double\t\tradius, w1,w3;\n  public:\n    ///\n    CircleSeg (const GeomPoint<D> & ap1, \n\t       const GeomPoint<D> & ap2, \n\t       const GeomPoint<D> & ap3);\n    // default constructor for archive\n    CircleSeg() {}\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & p1 & p2 & p3 & pm & radius & w1 & w3;\n    }\n    ///\n    virtual Point<D> GetPoint (double t) const;\n    ///\n    virtual const GeomPoint<D> & StartPI () const { return p1; }\n    ///\n    virtual const GeomPoint<D> & EndPI () const { return p3; }\n    ///\n    virtual void GetCoeff (Vector & coeffs) const;\n    ///\n    double Radius() const { return radius; }\n    ///\n    double StartAngle() const { return w1; }\n    ///\n    double EndAngle() const { return w3; }\n    ///\n    const Point<D> & MidPoint(void) const {return pm; }\n\n    virtual string GetType(void) const {return \"circle\";}\n\n    virtual void LineIntersections (const double a, const double b, const double c,\n\t\t\t\t    NgArray < Point<D> > & points, const double eps) const;\n\n    virtual bool InConvexHull (Point<D> p, double eps) const\n    {\n      return (Dist2 (p, pm) < sqr(radius+eps));\n    }\n\n    virtual double MaxCurvature(void) const {return 1./radius;}\n  };\n\n\n\n\n\n\n  /// \n  template<int D>\n  class DiscretePointsSeg : public SplineSeg<D>\n  {\n    NgArray<Point<D> > pts;\n    GeomPoint<D> p1n, p2n;\n  public:\n    ///\n    DiscretePointsSeg (const NgArray<Point<D> > & apts);\n    // default constructor for archive\n    DiscretePointsSeg() {}\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & pts & p1n & p2n;\n    }\n    ///\n    virtual ~DiscretePointsSeg ();\n    ///\n    virtual Point<D> GetPoint (double t) const;\n    ///\n    virtual const GeomPoint<D> & StartPI () const { return p1n; };\n    ///\n    virtual const GeomPoint<D> & EndPI () const { return p2n; }\n    ///\n    virtual void GetCoeff (Vector & coeffs) const {;}\n\n    virtual double MaxCurvature(void) const {return 1;}\n\n    // needs implementation ...\n    virtual bool InConvexHull (Point<D> p, double eps) const\n    { return true; }\n  };\n\n\n\n\n\n\n  // calculates length of spline-curve\n  template<int D>\n  double SplineSeg<D> :: Length () const\n  {\n    int n = 100;\n    double dt = 1.0 / n;\n\n    Point<D> pold = GetPoint (0);\n\n    double l = 0;\n    for (int i = 1; i <= n; i++)\n      {\n\tPoint<D> p = GetPoint (i * dt);\n\tl += Dist (p, pold);\n\tpold = p;\n      }\n\n    return l;\n  }\n\n\n  template<int D>\n  void SplineSeg<D> :: GetPoints (int n, NgArray<Point<D> > & points) const\n  {\n    points.SetSize (n);\n    if (n >= 2)\n      for (int i = 0; i < n; i++)\n\tpoints[i] = GetPoint(double(i) / (n-1));\n  }\n\n\n  template<int D>\n  void SplineSeg<D> :: PrintCoeff (ostream & ost) const\n  {\n    Vector u(6);\n\n    GetCoeff(u);\n\n    for ( int i=0; i<6; i++)\n      ost << u[i] << \"  \";\n    ost << endl;\n  }\n\n\n\n  /* \n     Implementation of line-segment from p1 to p2\n  */\n\n\n  template<int D>\n  LineSeg<D> :: LineSeg (const GeomPoint<D> & ap1, \n\t\t\t const GeomPoint<D> & ap2,\n                         double maxh, string bcname)\n    : SplineSeg<D>(maxh, bcname), p1(ap1), p2(ap2)\n  {\n    ;\n  }\n\n\n  template<int D>\n  inline Point<D> LineSeg<D> :: GetPoint (double t) const\n  {\n    return p1 + t * (p2 - p1);\n  }\n\n  template<int D>\n  Vec<D> LineSeg<D> :: GetTangent (const double t) const\n  {\n    return p2-p1;\n  }\n\n  template<int D>\n  void LineSeg<D> :: GetDerivatives (const double t, \n\t\t\t\t     Point<D> & point,\n\t\t\t\t     Vec<D> & first,\n\t\t\t\t     Vec<D> & second) const\n  {\n    first = p2 - p1;\n    point = p1 + t * first;\n    second = 0;\n  }\n\n\n  template<int D>\n  double LineSeg<D> :: Length () const\n  {\n    return Dist (p1, p2);\n  }\n\n\n  template<int D>\n  void LineSeg<D> :: GetCoeff (Vector & coeffs) const\n  {\n    coeffs.SetSize(6);\n\n    double dx = p2(0) - p1(0);\n    double dy = p2(1) - p1(1);\n\n    coeffs[0] = coeffs[1] = coeffs[2] = 0;\n    coeffs[3] = -dy;\n    coeffs[4] = dx;\n    coeffs[5] = -dx * p1(1) + dy * p1(0);\n  }\n\n  template<int D>\n  void LineSeg<D> :: GetCoeff (Vector & coeffs, Point<D> p) const\n  {\n    coeffs.SetSize(6);\n\n    double dx = p2(0) - p1(0);\n    double dy = p2(1) - p1(1);\n\n    coeffs[0] = coeffs[1] = coeffs[2] = 0;\n    coeffs[3] = -dy;\n    coeffs[4] = dx;\n    coeffs[5] = -dx * (p1(1)-p(1)) + dy * (p1(0)-p(0));\n  }\n\n\n  template<int D>\n  void LineSeg<D> :: LineIntersections (const double a, const double b, const double c,\n\t\t\t\t\tNgArray < Point<D> > & points, const double eps) const\n  {\n    points.SetSize(0);\n\n    double denom = -a*p2(0)+a*p1(0)-b*p2(1)+b*p1(1);\n    if(fabs(denom) < 1e-20)\n      return;\n\n    double t = (a*p1(0)+b*p1(1)+c)/denom;\n    if((t > -eps) && (t <  1.+eps))\n      points.Append(GetPoint(t));\n  }\n\n\n\n  template<int D>\n  void LineSeg<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const\n  {\n    Vec<D> v = p2-p1;\n    double l = v.Length();\n    v *= 1./l;\n    t = (point-p1)*v;\n\n    if(t<0) t = 0;\n    if(t>l) t = l;\n\n    point_on_curve = p1+t*v;\n\n    t *= 1./l;\n  }\n\n\n  template<int D>\n  void LineSeg<D> :: GetRawData (NgArray<double> & data) const\n  {\n    data.Append(2);\n    for(int i=0; i<D; i++)\n      data.Append(p1[i]);\n    for(int i=0; i<D; i++)\n      data.Append(p2[i]);\n  }\n\n\n\n\n\n  /*\n    template<int D>\n    double SplineSeg3<D> :: MaxCurvature(void) const\n    {\n    Vec<D> v1 = p1-p2;\n    Vec<D> v2 = p3-p2;\n    double l1 = v1.Length();\n    double l2 = v2.Length();\n    (*testout) << \"v1 \" << v1 << \" v2 \" << v2 << endl;\n\n    double cosalpha = v1*v2/(l1*l2);\n\n    (*testout) << \"cosalpha \" << cosalpha << endl;\n\n    return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha));\n    }\n  */\n  \n\n\n  //########################################################################\n  //\t\tcirclesegment\n\n  template<int D>\n  CircleSeg<D> :: CircleSeg (const GeomPoint<D> & ap1, \n\t\t\t     const GeomPoint<D> & ap2,\n\t\t\t     const GeomPoint<D> & ap3)\n    : p1(ap1), p2(ap2), p3(ap3)\n  {\n    Vec<D> v1,v2;\n  \n    v1 = p1 - p2;\n    v2 = p3 - p2;\n  \n    Point<D> p1t(p1+v1);\n    Point<D> p2t(p3+v2);\n\n    // works only in 2D!!!!!!!!!\n    \n    Line2d g1t,g2t;\n\n    g1t.P1() = Point<2>(p1(0),p1(1));\n    g1t.P2() = Point<2>(p1t(0),p1t(1));\n    g2t.P1() = Point<2>(p3(0),p3(1));\n    g2t.P2() = Point<2>(p2t(0),p2t(1));\n\n    Point<2> mp = CrossPoint (g1t,g2t);\n\n    pm(0) = mp(0); pm(1) = mp(1);\n    radius  = Dist(pm,StartPI());\n    Vec2d auxv;\n    auxv.X() = p1(0)-pm(0); auxv.Y() = p1(1)-pm(1);\n    w1      = Angle(auxv);\n    auxv.X() = p3(0)-pm(0); auxv.Y() = p3(1)-pm(1);\n    w3      = Angle(auxv);\n    if ( fabs(w3-w1) > M_PI )\n      {  \n\tif ( w3>M_PI )   w3 -= 2*M_PI;\n\tif ( w1>M_PI )   w1 -= 2*M_PI;\n      }\n  }\n\n  /*\n  template<int D>\n  Point<D> CircleSeg<D> :: GetPoint (double t) const\n  {\n    if (t >= 1.0)  { return p3; }\n    double phi = StartAngle() + t*(EndAngle()-StartAngle());\n    Vec<D>  tmp(cos(phi),sin(phi));\n    return pm + Radius()*tmp;\n  }\n  */\n  template<>\n  inline Point<3> CircleSeg<3> :: GetPoint (double t) const\n  {\n    // not really useful, but keep it as it was ...\n    if (t >= 1.0)  { return p3; }\n    double phi = StartAngle() + t*(EndAngle()-StartAngle());\n    Vec<3>  tmp(cos(phi),sin(phi),0);\n    return pm + Radius()*tmp;\n  }\n  \n  template<>\n  inline Point<2> CircleSeg<2> :: GetPoint (double t) const\n  {\n    if (t >= 1.0)  { return p3; }\n     \n    double phi = StartAngle() + t*(EndAngle()-StartAngle());\n    Vec<2>  tmp(cos(phi),sin(phi));\n     \n    return pm + Radius()*tmp;\n  }\n\n  template<int D>\n  void CircleSeg<D> :: GetCoeff (Vector & coeff) const\n  { \n    coeff[0] = coeff[1] = 1.0;\n    coeff[2] = 0.0;\n    coeff[3] = -2.0 * pm[0];\n    coeff[4] = -2.0 * pm[1];\n    coeff[5] = sqr(pm[0]) + sqr(pm[1]) - sqr(Radius());\n  }\n\n  \n\n\n\n  template<int D>\n  DiscretePointsSeg<D> ::   DiscretePointsSeg (const NgArray<Point<D> > & apts)\n    : pts (apts)\n  { \n    for(int i=0; i<D; i++)\n      {\n\tp1n(i) = apts[0](i);\n\tp2n(i) = apts.Last()(i);\n      }\n    p1n.refatpoint = 1;\n    p2n.refatpoint = 1;\n    p1n.hmax = 1e99;\n    p2n.hmax = 1e99;\n  }\n\n\n  template<int D>\n  DiscretePointsSeg<D> :: ~DiscretePointsSeg ()\n  { ; }\n\n  template<int D>\n  Point<D> DiscretePointsSeg<D> :: GetPoint (double t) const\n  {\n    double t1 = t * (pts.Size()-1);\n    int segnr = int(t1);\n    if (segnr < 0) segnr = 0;\n    if (segnr >= pts.Size()) segnr = pts.Size()-1;\n\n    double rest = t1 - segnr;\n    \n    return pts[segnr] + rest*Vec<D>(pts[segnr+1]-pts[segnr]);\n  }\n\n\n\n\n\n\n\n  \n\n  // *************************************\n  // Template for B-Splines of order ORDER\n  // thx to Gerhard Kitzler\n  // *************************************\n  \n  template<int D, int ORDER>\n  class BSplineSeg : public SplineSeg<D>\n  {\n    NgArray<Point<D> > pts;\n    GeomPoint<D> p1n, p2n;    \n    NgArray<int> ti; \n\n  public:\n    ///\n    BSplineSeg (const NgArray<Point<D> > & apts);\n    ///\n    //default constructor for archive\n    BSplineSeg() {}\n    virtual ~BSplineSeg();\n    ///\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & pts & p1n & p2n & ti;\n    }\n    virtual Point<D> GetPoint (double t) const;\n    ///\n    virtual const GeomPoint<D> & StartPI () const { return p1n; };\n    ///\n    virtual const GeomPoint<D> & EndPI () const { return p2n; }\n    ///\n    virtual void GetCoeff (Vector & coeffs) const {;}\n\n    virtual double MaxCurvature(void) const {return 1;}\n\n    // needs implementation ...\n    virtual bool InConvexHull (Point<D> p, double eps) const\n    { return true; }    \n  };\n\n  // Constructor\n  template<int D,int ORDER>\n  BSplineSeg<D,ORDER> :: BSplineSeg (const NgArray<Point<D> > & apts)\n    : pts (apts)\n  { \n    /*\n    for(int i=0; i<D; i++)\n      {\n\tp1n(i) = apts[0](i);\n\tp2n(i) = apts.Last()(i);\n      }\n    */\n    p1n = apts[0];\n    p2n = apts.Last();\n\n    /*\n    p1n.refatpoint = 1;\n    p2n.refatpoint = 1;\n    p1n.hmax = 1e99;\n    p2n.hmax = 1e99;\n    */\n\n    int m=pts.Size()+ORDER;\n    ti.SetSize(m);\n    // b.SetSize(m-1);\n    ti=0;    \n    //    b=0.0;\n    for(int i=ORDER;i<m-ORDER+1;i++)\n      ti[i]=i-ORDER+1;   \n    for(int i=m-ORDER+1;i<m;i++)\n      ti[i]=m-2*ORDER+1;\n  }\n  // Destructor\n  template<int D,int ORDER>\n  BSplineSeg<D, ORDER> :: ~BSplineSeg ()\n  { ; }\n\n\n  // GetPoint Method...(evaluation of BSpline Curve)\n  template<int D,int ORDER>\n  Point<D> BSplineSeg<D,ORDER> :: GetPoint (double t_in) const\n  {    \n    int m=pts.Size()+ORDER;           \n\n    double t = t_in * (m-2*ORDER+1);    \n\n    double b[ORDER];\n    \n    int interval_nr = int(t)+ORDER-1;    \n    if (interval_nr < ORDER-1) interval_nr = ORDER-1;\n    if (interval_nr > m-ORDER-1) interval_nr = m-ORDER-1;\n\n    b[ORDER-1] = 1.0;\n    \n    for(int degree=1;degree<ORDER;degree++)\n      for (int k = 0; k <= degree; k++)\n\t{\n\t  int j = interval_nr-degree+k;\n\t  double bnew = 0;\n\n\t  if (k != 0) \n\t    bnew += (t-ti[j]) / ( ti[j+degree]-ti[j] ) * b[k-degree+ORDER-1];\n\t  if (k != degree)\n\t    bnew += (ti[j+degree+1]-t) / ( ti[j+degree+1]-ti[j+1] ) * b[k-degree+ORDER];\n\t  b[k-degree+ORDER-1] = bnew;\n\t}\n\n    Point<D> p = 0.0;\n    for(int i=0; i < ORDER; i++) \n      p += b[i] * Vec<D> (pts[i+interval_nr-ORDER+1]);\n    return p;\n  }\n\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/gprim/splinegeometry.cpp",
    "content": "/*\n\n2d Spline curve for Mesh generator\n\n*/\n\n\n#include <mystdlib.h>\n#include <linalg.hpp>\n#include <gprim.hpp>\n#include <core/register_archive.hpp>\n#include \"splinegeometry.hpp\"\n \nnamespace netgen\n{\n\n\n  template<int D>\n  SplineGeometry<D> :: ~SplineGeometry()\n  {\n    for(int i = 0; i < splines.Size(); i++)\n      delete splines[i];\n  }\n\n\n  template<int D>\n  void SplineGeometry<D> :: GetRawData (NgArray<double> & raw_data) const\n  {\n    raw_data.Append(D);\n    // raw_data.Append(elto0);\n\n    raw_data.Append(splines.Size()); \n    for(int i=0; i<splines.Size(); i++)\n      splines[i]->GetRawData(raw_data);\n  }\n\n\n\n  template<int D>\n  int SplineGeometry<D> :: Load (const NgArray<double> & raw_data, const int startpos)\n  {\n    int pos = startpos;\n    if(raw_data[pos] != D)\n      throw NgException(\"wrong dimension of spline raw_data\");\n\n    pos++;\n\n    // elto0 = raw_data[pos]; pos++;\n\n    splines.SetSize(int(raw_data[pos]));\n    pos++;\n\n    NgArray< Point<D> > pts(3);\n\n    for(int i=0; i<splines.Size(); i++)\n      {\n\tint type = int(raw_data[pos]);\n\tpos++;\n      \n\tfor(int j=0; j<type; j++)\n\t  for(int k=0; k<D; k++)\n\t    {\n\t      pts[j](k) = raw_data[pos];\n\t      pos++;\n\t    }\n\n\tif (type == 2)\n\t  {\n\t    splines[i] = new LineSeg<D>(GeomPoint<D>(pts[0],1),\n\t\t\t\t\tGeomPoint<D>(pts[1],1));\n\t  }\n\telse if (type == 3)\n\t  {\n\t    splines[i] = new SplineSeg3<D>(GeomPoint<D>(pts[0],1),\n\t\t\t\t\t   GeomPoint<D>(pts[1],1),\n\t\t\t\t\t   GeomPoint<D>(pts[2],1));\n\t  }\n\telse\n\t  throw NgException(\"something wrong with spline raw data\");\n\n      }\n    return pos;\n  }\n\n\n\n\n\n\n\n  \n\n  template<int D>\n  void SplineGeometry<D> :: GetBoundingBox (Box<D> & box) const\n  {\n    if (!splines.Size())\n      {\n\tPoint<D> auxp = 0.;\n\tbox.Set (auxp);\n\treturn;\n      }\n\n    NgArray<Point<D> > points;\n    for (int i = 0; i < splines.Size(); i++)\n      {\n\tsplines[i]->GetPoints (20, points);\n\n\tif (i == 0) box.Set(points[0]);\n\tfor (int j = 0; j < points.Size(); j++)\n\t  box.Add (points[j]);\n      }\n  }\n\n  /*\n  template<int D>\n  void SplineGeometry<D> :: SetGrading (const double grading)\n  { \n    elto0 = grading;\n  }\n  */\n\n  template<int D>\n  void SplineGeometry<D> :: AppendPoint (const Point<D> & p, const double reffac, const bool hpref)\n  {\n    geompoints.Append (GeomPoint<D>(p, reffac));\n    geompoints.Last().hpref = hpref;\n  }\n\n\n\n  template class SplineGeometry<2>;\n  template class SplineGeometry<3>;\n  static RegisterClassForArchive<SplineGeometry<2>> regsp2;\n  static RegisterClassForArchive<SplineGeometry<3>> regsp3;\n}\n\n\n"
  },
  {
    "path": "libsrc/gprim/splinegeometry.hpp",
    "content": "/*\n\n\nJS, Nov 2007\n\n\nThe 2D/3D template-base classes should go into the libsrc/gprim directory\n\nin geom2d only 2D - Geometry classes (with material properties etc.)\n\n\n*/\n\n#include \"spline.hpp\"\n\n\n#ifndef _FILE_SPLINEGEOMETRY\n#define _FILE_SPLINEGEOMETRY\n\nnamespace netgen\n{\n\n\n  template < int D >\n  class DLL_HEADER SplineGeometry\n  {\n    // protected:\n  public:  \n    NgArray < GeomPoint<D> > geompoints;\n    NgArray < SplineSeg<D>* > splines;\n\n    SplineGeometry() : geompoints{}, splines{} { ; }\n    virtual ~SplineGeometry();\n\n    int Load (const NgArray<double> & raw_data, const int startpos = 0);\n\n    virtual void DoArchive(Archive& ar)\n    {\n      ar & geompoints & splines;\n    }\n\n    void GetRawData (NgArray<double> & raw_data) const;\n\n\n    const NgArray<SplineSeg<D>*> & GetSplines () const\n    { return splines; }\n\n    int GetNSplines (void) const { return splines.Size(); }\n    string GetSplineType (const int i) const { return splines[i]->GetType(); }\n    SplineSeg<D> & GetSpline (const int i) {return *splines[i];}\n    const SplineSeg<D> & GetSpline (const int i) const {return *splines[i];}\n\n    void GetBoundingBox (Box<D> & box) const;\n    Box<D> GetBoundingBox () const \n    { Box<D> box; GetBoundingBox (box); return box; }\n\n    int GetNP () const { return geompoints.Size(); }\n    const GeomPoint<D> & GetPoint(int i) const { return geompoints[i]; }\n\n    // void SetGrading (const double grading);\n    void AppendPoint (const Point<D> & p, const double reffac = 1., const bool hpref = false);\n\n    void AppendSegment(SplineSeg<D> * spline)\n    {\n      splines.Append (spline);\n    }\n  };\n\n\n\n}\n\n#endif // _FILE_SPLINEGEOMETRY\n"
  },
  {
    "path": "libsrc/gprim/transform3d.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <gprim.hpp>\n#include <linalg.hpp>\n\nnamespace netgen\n{\n\nTransformation3d :: Transformation3d ()\n{\n  for (int i = 0; i < 3; i++)\n    {\n      offset[i] = 0;\n      for (int j = 0; j < 3; j++)\n\tlin[i][j] = 0;\n    }\n}\n\nTransformation3d :: Transformation3d (const Vec3d & translate)\n{\n  for (int i = 0; i < 3; i++)\n    for (int j = 0; j < 3; j++)\n      lin[i][j] = 0;\n  for (int i = 0; i < 3; i++)\n    {\n      offset[i] = translate.X(i+1);\n      lin[i][i] = 1;\n    }\n}\n\n\nTransformation3d :: \nTransformation3d (const Point3d & c, double alpha, \n\t\t  double beta, double gamma)\n{\n  // total = T_c x Rot_0 x T_c^{-1}\n  // Use Euler angles, see many books from tech mech, e.g. \n  // Shabana \"multibody systems\"\n\n  Transformation3d tc(c);\n  Transformation3d tcinv;\n  tc.CalcInverse (tcinv);\n\n  Transformation3d r1, r2, r3, ht, ht2;\n  r1.SetAxisRotation (3, alpha);\n  r2.SetAxisRotation (1, beta);\n  r3.SetAxisRotation (3, gamma);\n\n  ht.Combine (tc, r3);\n  ht2.Combine (ht, r2);\n  ht.Combine (ht2, r1);\n  Combine (ht, tcinv);\n\n  // cout << \"Rotation - Transformation:\" << (*this) << endl;\n  //  (*testout) << \"Rotation - Transformation:\" << (*this) << endl;\n}\n\n\n\n\nTransformation3d :: Transformation3d (const Point3d ** pp)\n{\n  for (int i = 1; i <= 3; i++)\n    {\n      offset[i-1] = (*pp[0]).X(i);\n      for (int j = 1; j <= 3; j++)\n\tlin[i-1][j-1] = (*pp[j]).X(i) - (*pp[0]).X(i);\n    }\n}\n\nTransformation3d :: Transformation3d (const Point3d pp[])\n{\n  for (int i = 1; i <= 3; i++)\n    {\n      offset[i-1] = pp[0].X(i);\n      for (int j = 1; j <= 3; j++)\n\tlin[i-1][j-1] = pp[j].X(i) - pp[0].X(i);\n    }\n}\n\n\nvoid Transformation3d :: CalcInverse (Transformation3d & inv) const\n{\n  static DenseMatrix a(3), inva(3);\n  static Vector b(3), sol(3);\n  \n  for (int i = 0; i < 3; i++)\n    {\n      b(i) = offset[i];\n      for (int j = 0; j < 3; j++)\n\ta(i, j) = lin[i][j];\n    }\n\n  ::netgen::CalcInverse (a, inva);\n  inva.Mult (b, sol);\n\n  for (int i = 0; i < 3; i++)\n    {\n      inv.offset[i] = -sol(i);\n      for (int j = 0; j < 3; j++)\n\tinv.lin[i][j] = inva(i, j);\n    }\n}\n\n\nvoid  Transformation3d:: \nCombine (const Transformation3d & ta, const Transformation3d & tb)\n{\n  // o = o_a+ m_a o_b\n  // m = m_a m_b\n\n  for (int i = 0; i <= 2; i++)\n    {\n      offset[i] = ta.offset[i];\n      for (int j = 0; j <= 2; j++)\n\toffset[i] += ta.lin[i][j] * tb.offset[j];\n    }\n  \n  for (int i = 0; i <= 2; i++)\n    for (int j = 0; j <= 2; j++)\n      {\n\tlin[i][j] = 0;\n\tfor (int k = 0; k <= 2; k++)\n\t  lin[i][j] += ta.lin[i][k] * tb.lin[k][j];\n      }\n}\nvoid Transformation3d :: SetAxisRotation (int dir, double alpha)\n{\n  double co = cos(alpha);\n  double si = sin(alpha);\n  dir--;\n  int pos1 = (dir+1) % 3;\n  int pos2 = (dir+2) % 3;\n\n  int i, j;\n  for (i = 0; i <= 2; i++)\n    {\n      offset[i] = 0;\n      for (j = 0; j <= 2; j++)\n\tlin[i][j] = 0;\n    }\n\n  lin[dir][dir] = 1;\n  lin[pos1][pos1] = co;\n  lin[pos2][pos2] = co;\n  lin[pos1][pos2] = si;\n  lin[pos2][pos1] = -si;\n}\n\nostream & operator<< (ostream & ost, Transformation3d & trans)\n{\n  ost << \"offset = \";\n  for (int i = 0; i <= 2; i++)\n    ost << trans.offset[i] << \" \";\n  ost << endl << \"linear = \" << endl;\n  for (int i = 0; i <= 2; i++)\n    {\n      for (int j = 0; j <= 2; j++)\n\tost << trans.lin[i][j] << \" \";\n      ost << endl;\n    }\n  return ost;\n}\n\n  template <>\n  Transformation<3> :: Transformation (const Point<3> & c, const Vec<3> & axes, double angle)\n  {\n    Vec<3> vc(c);\n    Transformation<3> tc(vc);\n    Transformation<3> tcinv(-vc);\n    Transformation<3> r, ht, ht2;\n\n    // r.SetAxisRotation (3, alpha);\n    Vec<3> naxes = axes;\n    naxes.Normalize();\n    Vec<3> n1 = naxes.GetNormal();\n    Vec<3> n2 = Cross(naxes, n1);\n    r.v = Vec<3>(0,0,0);\n    double co = cos(angle);\n    double si = sin(angle);\n    for (int i = 0; i < 3; i++)\n      for (int j = 0; j < 3; j++)\n        r.m(i,j) = naxes(i)*naxes(j) + co*(n1(i)*n1(j)+n2(i)*n2(j)) + si*( (n2(i)*n1(j)-n2(j)*n1(i)) );\n\n    ht.Combine (tc, r);\n    Combine (ht, tcinv);\n  }\n\n  \n  template <int D>\n  Transformation<D> :: Transformation (const Point<D> * pp)\n  {\n    v = Vec<D> (pp[0]);\n    for (int i = 0; i < D; i++)\n      for (int j = 0; j < D; j++)\n        m(j,i) = pp[i+1](j)-pp[0](j);\n  }\n  \n  template class Transformation<3>;\n}\n"
  },
  {
    "path": "libsrc/gprim/transform3d.hpp",
    "content": "#ifndef FILE_TRANSFORM3D\n#define FILE_TRANSFORM3D\n\n/* *************************************************************************/\n/* File:   transform3d.hh                                                  */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   22. Mar. 98                                                     */\n/* *************************************************************************/\n\n/*\n  Affine - Linear mapping in 3D space\n */\n\n#include \"geom3d.hpp\"\n#include \"geomfuncs.hpp\"\n\nnamespace netgen\n{\n\nclass Transformation3d;\nostream & operator<< (ostream & ost, Transformation3d & trans);\n\nclass Transformation3d\n{\n  double lin[3][3];\n  double offset[3];\npublic:\n  ///\n  Transformation3d ();\n  /// Unit tet is mapped to tet described by pp\n  Transformation3d (const Point3d ** pp);\n  /// Unit tet is mapped to tet described by pp\n  Transformation3d (const Point3d pp[]);\n  /// translation\n  Transformation3d (const Vec3d & translate);\n  /// rotation with ...\n  Transformation3d (const Point3d & c, double alpha, double beta, double gamma);\n  /// \n  void CalcInverse (Transformation3d & inv) const;\n  /// this = ta x tb\n  void Combine (const Transformation3d & ta, const Transformation3d & tb);\n  /// dir = 1..3 (== x..z)\n  void SetAxisRotation (int dir, double alpha);\n  ///\n  void Transform (const Point3d & from, Point3d & to) const\n    {\n      for (int i = 1; i <= 3; i++)\n\t{\n\t  to.X(i) = offset[i-1] + lin[i-1][0] * from.X(1) + \n\t    lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3);\n\t}\n    }\n\n  ///\n  void Transform (Point3d & p) const\n  {\n    Point3d hp;\n    Transform (p, hp);\n    p = hp;\n  }\n\n  /// transform vector, apply only linear part, not offset\n  void Transform (const Vec3d & from, Vec3d & to) const\n    {\n      for (int i = 1; i <= 3; i++)\n\t{\n\t  to.X(i) = lin[i-1][0] * from.X(1) + \n\t    lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3);\n\t}\n    }\n  friend ostream & operator<< (ostream & ost, Transformation3d & trans);\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ntemplate <int D>\nclass Transformation\n{\n  Mat<D> m;\n  Vec<D> v;\npublic:\n  ///\n  Transformation () { m = 0; v = 0; }\n\n  /// Unit tet is mapped to tet described by pp\n  Transformation (const Point<D> * pp);\n\n  /// translation\n  Transformation (const Vec<D> & translate)\n  {\n    v = translate;\n    m = 0;\n    for (int i = 0; i < D; i++)\n      m(i,i) = 1;\n  }\n\n  Transformation (const Point<D> & c, const Vec<3> & axes, double angle);\n  \n  // rotation with ...\n  Transformation (const Point<D> & c, double alpha, double beta, double gamma)\n  {\n    // total = T_c x Rot_0 x T_c^{-1}\n    // Use Euler angles, see many books from tech mech, e.g. \n    // Shabana \"multibody systems\"\n    \n    Vec<D> vc(c);\n    Transformation<D> tc(vc);\n    Transformation<D> tcinv(-vc);\n    // tc.CalcInverse (tcinv);\n    \n    Transformation<D> r1, r2, r3, ht, ht2;\n    r1.SetAxisRotation (3, alpha);\n    r2.SetAxisRotation (1, beta);\n    r3.SetAxisRotation (3, gamma);\n    \n    ht.Combine (tc, r3);\n    ht2.Combine (ht, r2);\n    ht.Combine (ht2, r1);\n    Combine (ht, tcinv);\n    \n    // cout << \"Rotation - Transformation:\" << (*this) << endl;\n    //  (*testout) << \"Rotation - Transformation:\" << (*this) << endl;\n  }\n\n  Mat<D> & GetMatrix() { return m; }\n  Vec<D> & GetVector() { return v; }\n\n  void DoArchive(Archive& ar)\n  {\n      ar & m & v;\n  }\n\n  /// \n  Transformation CalcInverse () const\n  {\n    Transformation inv;\n    // inv.m = Inv(m);\n    ::netgen::CalcInverse (m, inv.m);\n    inv.v = inv.m * (-v);\n    return inv;\n  }\n\n  /// this = ta x tb\n  void Combine (const Transformation & ta, const Transformation & tb)\n  {\n    v = ta.v + ta.m * tb.v;\n    m = ta.m * tb.m;\n  }\n\n\n\n  /// dir = 1..3 (== x..z)\n  void SetAxisRotation (int dir, double alpha)\n  {\n    double co = cos(alpha);\n    double si = sin(alpha);\n    dir--;\n    int pos1 = (dir+1) % 3;\n    int pos2 = (dir+2) % 3;\n    \n    int i, j;\n    for (i = 0; i <= 2; i++)\n    {\n      v(i) = 0;\n      for (j = 0; j <= 2; j++)\n\tm(i,j) = 0;\n    }\n    \n    m(dir,dir) = 1;\n    m(pos1, pos1) = co;\n    m(pos2, pos2) = co;\n    m(pos1, pos2) = si;\n    m(pos2, pos1) = -si;\n  }\n\n  ///\n  void Transform (const Point<D> & from, Point<D> & to) const\n  {\n    to = Point<D> (v + m * Vec<D>(from));\n  }\n\n  void Transform (Point<D> & p) const\n  {\n    p = Point<D> (v + m * Vec<D>(p));\n  }\n\n\n\n  /// transform vector, apply only linear part, not offset\n  void Transform (const Vec<D> & from, Vec<D> & to) const\n  {\n    to = m * from;\n  }\n\n  Point<D> operator() (Point<D> from) const { Point<D> to; Transform(from, to); return to; }\n  Vec<D> operator() (Vec<D> from) const { Vec<D> to; Transform(from, to); return to; }\n};\n\ntemplate <int D>\nostream & operator<< (ostream & ost, Transformation<D> & trans);\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/include/CMakeLists.txt",
    "content": "install(FILES nginterface.h nginterface_v2.hpp mydefs.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)\n\ninstall(FILES\n  acisgeom.hpp csg.hpp geometry2d.hpp gprim.hpp incopengl.hpp\n  inctcl.hpp incvis.hpp linalg.hpp meshing.hpp myadt.hpp mydefs.hpp\n  mystdlib.h nginterface_v2_impl.hpp occgeom.hpp ngsimd.hpp\n  opti.hpp parallel.hpp  stlgeom.hpp visual.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/include COMPONENT netgen_devel\n  )\n\n"
  },
  {
    "path": "libsrc/include/acisgeom.hpp",
    "content": "#ifdef ACIS\n#include \"../acisgeom/acisgeom.hpp\"\n#endif\n"
  },
  {
    "path": "libsrc/include/csg.hpp",
    "content": "#include \"../csg/csg.hpp\"\n"
  },
  {
    "path": "libsrc/include/geometry2d.hpp",
    "content": "#include \"../geom2d/geometry2d.hpp\"\n"
  },
  {
    "path": "libsrc/include/gprim.hpp",
    "content": "#include \"../gprim/gprim.hpp\"\n"
  },
  {
    "path": "libsrc/include/incopengl.hpp",
    "content": "#ifndef INCOPENGL_HPP___\n#define INCOPENGL_HPP___\n#define GL_GLEXT_PROTOTYPES\n\n#include <mystdlib.h>\n#include <mydefs.hpp>\n\n#ifdef WIN32\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#endif\n\n#  ifdef __APPLE__\n#define GL_SILENCE_DEPRECATION\n#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED\n#    include <OpenGL/gl3.h>\n#    include <OpenGL/glu.h>\n#  else\n#    include <GL/gl.h>\n#    include <GL/glu.h>\n#  endif\n\n\n#ifdef TOGL_X11\n// parallel\n#define GLX_GLXEXT_PROTOTYPES\n#include <GL/glx.h>\n#include <GL/glxext.h>\n#endif\n\n#ifdef WIN32\n// part of OpenGL 1.2, but not in Microsoft's OpenGL 1.1 header:\n// GL version should be checked at runtime\n#define GL_CLAMP_TO_EDGE                  0x812F\n#define GL_ARRAY_BUFFER                   0x8892\n#define GL_ELEMENT_ARRAY_BUFFER           0x8893\n#define GL_STATIC_DRAW                    0x88E4\n#define GL_FRAMEBUFFER_COMPLETE           0x8CD5\n#define GL_FRAMEBUFFER                    0x8D40\n#define GL_RENDERBUFFER                   0x8D41\n#define GL_DEPTH_ATTACHMENT               0x8D00\n#define GL_COLOR_ATTACHMENT0              0x8CE0\ntypedef ptrdiff_t GLintptr;\ntypedef ptrdiff_t GLsizeiptr;\nextern void (*glBindBuffer) (GLenum a, GLuint b);\nextern void (*glDeleteBuffers) (GLsizei a, const GLuint *b);\nextern void (*glGenBuffers) (GLsizei a, GLuint *b);\nextern void (*glBufferData) (GLenum a, GLsizeiptr b, const GLvoid *c, GLenum d);\nextern void (*glBufferSubData) (GLenum a, GLintptr b, GLsizeiptr c, const GLvoid *d);\n\nextern GLenum (*glCheckFramebufferStatus) (GLenum target);\nextern void (*glBindFramebuffer) (GLenum target, GLuint framebuffer);\nextern void (*glBindRenderbuffer) (GLenum target, GLuint renderbuffer);\nextern void (*glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers);\nextern void (*glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers);\nextern void (*glGenFramebuffers) (GLsizei n, GLuint *framebuffers);\nextern void (*glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers);\nextern void (*glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);\nextern void (*glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\n#endif\nDLL_HEADER void LoadOpenGLFunctionPointers();\n#endif // INCOPENGL_HPP___\n"
  },
  {
    "path": "libsrc/include/inctcl.hpp",
    "content": "#ifdef WIN32\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#endif\n\n#include <tcl.h>\n#include <tk.h>\n\n#if TK_MAJOR_VERSION==8 && TK_MINOR_VERSION>=4\n#define tcl_const const\n#else\n#define tcl_const\n#endif\n"
  },
  {
    "path": "libsrc/include/incvis.hpp",
    "content": "// libraries for User interface:\n\nnicht mehr verwendet\n\n#include \"inctcl.hpp\"\n#include \"incopengl.hpp\"\n"
  },
  {
    "path": "libsrc/include/linalg.hpp",
    "content": "#include \"../linalg/linalg.hpp\"\n"
  },
  {
    "path": "libsrc/include/meshing.hpp",
    "content": "#include <../meshing/meshing.hpp>\n"
  },
  {
    "path": "libsrc/include/myadt.hpp",
    "content": "#include <../general/myadt.hpp>\n"
  },
  {
    "path": "libsrc/include/mydefs.hpp",
    "content": "#ifndef FILE_MYDEFS\n#define FILE_MYDEFS\n\n/**************************************************************************/\n/* File:   mydefs.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   10. Mar. 98                                                    */\n/**************************************************************************/\n\n/*\n  defines for graphics, testmodes, ...\n*/\n\n#include <core/ngcore.hpp>\n#define PACKAGE_VERSION \"6.2-dev\"\n\n// #define DEBUG\n\n#if defined(nglib_EXPORTS)\n   #define DLL_HEADER   NGCORE_API_EXPORT\n#else\n   #define DLL_HEADER   NGCORE_API_IMPORT\n#endif\n\n\n\n\n#ifndef __assume\n#ifdef __GNUC__\n#define __assume(cond) if (!(cond)) __builtin_unreachable(); else;\n#else\n#define __assume(cond)\n#endif\n#endif\n\n\n#ifndef NG_INLINE\n#ifdef __INTEL_COMPILER\n#ifdef WIN32\n#define NG_INLINE __forceinline inline\n#else\n#define NG_INLINE __forceinline inline\n#endif\n#else\n#ifdef __GNUC__\n#define NG_INLINE __attribute__ ((__always_inline__)) inline\n#define VLA\n#else\n#define NG_INLINE inline\n#endif\n#endif\n#endif\n\n\n// #define BASE0\n// #define DEBUG\n\n\n#define noDEMOVERSION\n#define noDEVELOP\n#define noSTEP\n#define noSOLIDGEOM\n\n#define noDEMOAPP\n#define noMODELLER\n\n#define noSTAT_STREAM\n#define noLOG_STREAM\n\n#endif\n"
  },
  {
    "path": "libsrc/include/mystdlib.h",
    "content": "#ifndef FILE_MYSTDLIB\n#define FILE_MYSTDLIB\n\n#include <iostream>\n#include <iomanip>\n#include <fstream>\n#include <sstream>\n\n\n#include <cstdlib>\n#include <cstdio>\n#include <cmath>\n#include <cctype>\n#include <ctime>\n#include <cstring>\n#include <climits>\n#include <algorithm>\n#include <memory>\n#include <thread>\n#include <mutex>\n#include <atomic>\n#include <optional>\n#include <cassert>\n\n#include <new>\n#include <string>\n#include <typeinfo>\n\n\n#ifndef M_PI\n#define M_PI 3.14159265358979323846\n#endif\n\n/*** Windows headers ***/\n#ifdef _MSC_VER\n# define WIN32_LEAN_AND_MEAN\n# ifndef NO_PARALLEL_THREADS\n#  ifdef MSVC_EXPRESS\n#  else\n// #   include <afxwin.h>\n// #   include <afxmt.h>\n#  endif // MSVC_EXPRESS\n# endif\n// # include <windows.h>\n# undef WIN32_LEAN_AND_MEAN\n// # include <winnt.h>\n#else // Not using MC VC++\n#endif\n\n\n// using namespace std;\nnamespace netgen\n{\n  using namespace std;  \n}\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/include/nginterface.h",
    "content": "#ifndef NGINTERFACE\n#define NGINTERFACE\n\n\n\n\n\n/**************************************************************************/\n/* File:   nginterface.h                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   20. Nov. 99                                                    */\n/**************************************************************************/\n\n#include \"mydefs.hpp\"\n#include <meshing/visual_interface.hpp>\n\n/*\n  Application program interface to Netgen\n\n*/\n\n// max number of nodes per element\n#define NG_ELEMENT_MAXPOINTS 20\n\n// max number of nodes per surface element\n#define NG_SURFACE_ELEMENT_MAXPOINTS 8\n\n// #ifndef PARALLEL\n// typedef int MPI_Comm;\n// #endif\n// namespace netgen { extern DLL_HEADER ngcore::NgMPI_Comm ng_comm; }\n\n\n// implemented element types:\nenum NG_ELEMENT_TYPE { \n  NG_PNT = 0,\n  NG_SEGM = 1, NG_SEGM3 = 2,\n  NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14,\n  NG_TET = 20, NG_TET10 = 21, \n  NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28,\n  NG_HEX = 25, NG_HEX20 = 26, NG_HEX7 = 29\n};\n\ntypedef double NG_POINT[3];  // coordinates\ntypedef int NG_EDGE[2];      // initial point, end point\ntypedef int NG_FACE[4];      // points, last one is 0 for trig\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n  \n  // load geometry from file \n  DLL_HEADER void Ng_LoadGeometry (const char * filename);\n\n  // load netgen mesh\n  DLL_HEADER void Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm = ngcore::NgMPI_Comm{});\n\n  // load netgen mesh\n  DLL_HEADER void Ng_LoadMeshFromString (const char * mesh_as_string);\n\n  // space dimension (2 or 3)\n  DLL_HEADER int Ng_GetDimension ();\n\n  // number of mesh points\n  DLL_HEADER int Ng_GetNP ();\n  \n  // number of mesh vertices (differs from GetNP for 2nd order elements)\n  DLL_HEADER int Ng_GetNV ();\n  \n  // number of mesh elements\n  DLL_HEADER int Ng_GetNE ();\n  \n  // number of surface triangles\n  DLL_HEADER int Ng_GetNSE ();\n  \n  // Get Point coordinates, index from 1 .. np\n  DLL_HEADER void Ng_GetPoint (int pi, double * p);\n  \n  // Get Element Points\n  DLL_HEADER NG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np = 0);\n\n  // Get Element Type\n  DLL_HEADER NG_ELEMENT_TYPE Ng_GetElementType (int ei);\n\n  // Get sub-domain of element ei\n  DLL_HEADER int Ng_GetElementIndex (int ei);\n\n  DLL_HEADER void Ng_SetElementIndex(const int ei, const int index);\n\n  // Get Material of element ei\n  DLL_HEADER const char * Ng_GetElementMaterial (int ei);\n\n  // Get Material of domain dom\n  DLL_HEADER const char * Ng_GetDomainMaterial (int dom);\n  \n  // Get User Data\n  DLL_HEADER int Ng_GetUserDataSize (char * id);\n  DLL_HEADER void Ng_GetUserData (char * id, double * data);\n\n  // Get Surface Element Points\n  DLL_HEADER NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np = 0);\n\n  // Get Surface Element Type\n  DLL_HEADER NG_ELEMENT_TYPE Ng_GetSurfaceElementType (int ei);\n\n  // Get Surface Element Index\n  DLL_HEADER int Ng_GetSurfaceElementIndex (int ei);\n\n  // Get Surface Element Surface Number\n  DLL_HEADER int Ng_GetSurfaceElementSurfaceNumber (int ei);\n  \n  // Get Surface Element Number\n  DLL_HEADER int Ng_GetSurfaceElementFDNumber (int ei);\n\n  // Get BCName for Surface Element  \n  DLL_HEADER char * Ng_GetSurfaceElementBCName (int ei);\n  //void Ng_GetSurfaceElementBCName (int ei, char * name);\n\n  // Get BCName for bc-number\n  DLL_HEADER char * Ng_GetBCNumBCName (int bcnr);\n  //void Ng_GetBCNumBCName (int bcnr, char * name);\n\n  // Get BCName for bc-number of co dim 2\n  DLL_HEADER char * Ng_GetCD2NumCD2Name (int cd2nr);\n\n  // Get normal vector of surface element node\n  // DLL_HEADER void Ng_GetNormalVector (int sei, int locpi, double * nv);     \n  \n\n  DLL_HEADER void Ng_SetPointSearchStartElement(int el);\n  \n  // Find element of point, returns local coordinates\n  DLL_HEADER int Ng_FindElementOfPoint (double * p, double * lami,\n                                        int build_searchtrees = 0, \n                                        const int * const indices = NULL, const int numind = 0);\n  \n  // Find surface element of point, returns local coordinates\n  DLL_HEADER int Ng_FindSurfaceElementOfPoint (double * p, double * lami,\n                                               int build_searchtrees = 0, \n                                               const int * const indices = NULL, const int numind = 0);\n  \n\n  // is element ei curved ?\n  DLL_HEADER int Ng_IsElementCurved (int ei);\n  // is element sei curved ?\n  DLL_HEADER int Ng_IsSurfaceElementCurved (int sei);\n\n  /// Curved Elements:\n  /// xi..local coordinates\n  /// x ..global coordinates\n  /// dxdxi...D x D Jacobian matrix (row major storage)\n  DLL_HEADER void Ng_GetElementTransformation (int ei, const double * xi, \n                                               double * x, double * dxdxi);\n\n  \n  /// buffer must be at least 100 doubles, alignment of double\n  DLL_HEADER void Ng_GetBufferedElementTransformation (int ei, const double * xi, \n                                                       double * x, double * dxdxi,\n                                                       void * buffer, int buffervalid);\n  \n\n\n  /// Curved Elements:\n  /// xi..local coordinates\n  /// x ..global coordinates\n  /// dxdxi...D x D-1 Jacobian matrix (row major storage)\n  /// curved ...is element curved ?\n  DLL_HEADER void Ng_GetSurfaceElementTransformation (int sei, const double * xi, \n                                                      double * x, double * dxdxi);\n  \n  /// Curved Elements:\n  /// xi..local coordinates\n  /// sxi..step xi\n  /// x ..global coordinates\n  /// dxdxi...D x D Jacobian matrix (row major storage)\n  DLL_HEADER void Ng_GetMultiElementTransformation (int ei, int n,\n                                                    const double * xi, size_t sxi,\n                                                    double * x, size_t sx,\n                                                    double * dxdxi, size_t sdxdxi);\n\n  \n  \n  DLL_HEADER int Ng_GetSegmentIndex (int elnr);\n  DLL_HEADER NG_ELEMENT_TYPE Ng_GetSegment (int elnr, int * epi, int * np = 0);\n\n\n\n\n  // Mark element for refinement\n  DLL_HEADER void Ng_SetRefinementFlag (int ei, int flag);\n  DLL_HEADER void Ng_SetSurfaceRefinementFlag (int sei, int flag);\n\n  // Do local refinement\n  enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 };\n  DLL_HEADER void Ng_Refine (NG_REFINEMENT_TYPE reftype);\n\n  // Use second order elements\n  DLL_HEADER void Ng_SecondOrder ();\n  DLL_HEADER void Ng_HighOrder (int order, bool rational = false);\n  //void Ng_HPRefinement (int levels, double parameter = 0.125);\n  DLL_HEADER void Ng_HPRefinement (int levels, double parameter = 0.125,\n                                   bool setorders = true,bool ref_level = false);\n  // void Ng_HPRefinement (int levels);\n  // void Ng_HPRefinement (int levels, double parameter);\n\n\n  // Topology and coordinate information of master element:\n\n  DLL_HEADER int Ng_ME_GetNVertices (NG_ELEMENT_TYPE et);\n  DLL_HEADER int Ng_ME_GetNEdges (NG_ELEMENT_TYPE et);\n  DLL_HEADER int Ng_ME_GetNFaces (NG_ELEMENT_TYPE et);\n\n  DLL_HEADER const NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et);\n  DLL_HEADER const NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et);\n  DLL_HEADER const NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et);\n\n  DLL_HEADER void Ng_UpdateTopology();\n\n  DLL_HEADER int Ng_GetNEdges();\n  DLL_HEADER int Ng_GetNFaces();\n\n  [[deprecated(\"orientation is not supported anymore\")]]                          \n  DLL_HEADER int Ng_GetElement_Edges (int elnr, int * edges, int * orient = 0);\n  // [[deprecated(\"orientation is not supported anymore\")]]                            \n  DLL_HEADER int Ng_GetElement_Faces (int elnr, int * faces, int * orient = 0);\n  [[deprecated(\"orientation is not supported anymore\")]]                          \n  DLL_HEADER int Ng_GetSurfaceElement_Edges (int selnr, int * edges, int * orient = 0);\n  // [[deprecated(\"orientation is not supported anymore\")]]                            \n  DLL_HEADER int Ng_GetSurfaceElement_Face (int selnr, int * orient = 0);\n\n  DLL_HEADER void Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out);\n       \n  DLL_HEADER int Ng_GetFace_Vertices (int fnr, int * vert);\n  DLL_HEADER void Ng_GetEdge_Vertices (int ednr, int * vert);\n  DLL_HEADER int Ng_GetFace_Edges (int fnr, int * edge);\n\n  DLL_HEADER int Ng_GetNVertexElements (int vnr);\n  DLL_HEADER void Ng_GetVertexElements (int vnr, int * els);\n\n  DLL_HEADER int Ng_GetElementOrder (int enr);\n  DLL_HEADER void Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz);\n\n  DLL_HEADER void Ng_SetElementOrder (int enr, int order);\n  DLL_HEADER void Ng_SetElementOrders (int enr, int ox, int oy, int oz);\n\n  DLL_HEADER int Ng_GetSurfaceElementOrder (int enr);\n  DLL_HEADER void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy);\n\n  DLL_HEADER void Ng_SetSurfaceElementOrder (int enr, int order);\n  DLL_HEADER void Ng_SetSurfaceElementOrders (int enr, int ox, int oy);\n\n  // Multilevel functions:\n\n  // number of levels:\n  DLL_HEADER int Ng_GetNLevels ();\n  // get two parent nodes (indeed vertices !) of node ni\n  DLL_HEADER void Ng_GetParentNodes (int ni, int * parents);\n\n  // get parent element (first child has always same number)\n  DLL_HEADER int Ng_GetParentElement (int ei);\n\n  // get parent surface element (first child has always same number)\n  DLL_HEADER int Ng_GetParentSElement (int ei);\n\n  // representant of anisotropic cluster\n  DLL_HEADER int Ng_GetClusterRepVertex (int vi);\n  DLL_HEADER int Ng_GetClusterRepEdge (int edi);\n  DLL_HEADER int Ng_GetClusterRepFace (int fai);\n  DLL_HEADER int Ng_GetClusterRepElement (int eli);\n\n\n  void Ng_SurfaceElementTransformation (int eli, double x, double y, \n\t\t\t\t\tdouble * p3d, double * jacobian);\n\n#ifdef PARALLEL\n\n  // the following functions are 0-base  !!\n\n  // number on distant processor \n  // returns pairs  (dist_proc, num_on_dist_proc)\n  int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * pnums );\n  int NgPar_GetNDistantNodeNums ( int nodetype, int locnum );\n  \n  DLL_HEADER int NgPar_GetGlobalNodeNum (int nodetype, int locnum);\n\n#endif\n  \n  namespace netgen {\n  // #include \"../visualization/soldata.hpp\"\n    class SolutionData;\n    class MouseEventHandler;\n    class UserVisualizationObject;\n  }\n\n  enum Ng_SolutionType\n  { NG_SOLUTION_NODAL = 1, \n    NG_SOLUTION_ELEMENT = 2, \n    NG_SOLUTION_SURFACE_ELEMENT = 3, \n    NG_SOLUTION_NONCONTINUOUS = 4,\n    NG_SOLUTION_SURFACE_NONCONTINUOUS = 5,\n    NG_SOLUTION_VIRTUAL_FUNCTION = 6,\n    NG_SOLUTION_MARKED_ELEMENTS = 10,\n    NG_SOLUTION_ELEMENT_ORDER = 11\n  };\n  \n  struct Ng_SolutionData\n  {\n    std::string name;      // name of gridfunction\n    std::string title = \"\"; // name of gridfunction ( printed on top of window )\n    std::string number_format = \"%.3e\"; // printf-style string to format colormap values\n    std::string unit = \"\"; // string to append to last number in colormap (ASCII only)\n    double * data;    // solution values\n    int components;   // relevant (double) components in solution vector\n    int dist;         // # doubles per entry alignment! \n    int iscomplex;    // complex vector ? \n    bool draw_surface;\n    bool draw_volume;\n    std::shared_ptr<netgen::BitArray> draw_surfaces, draw_volumes;\n    int order;        // order of elements, only partially supported \n    Ng_SolutionType soltype;  // type of solution function\n    netgen::SolutionData * solclass;\n  };\n  \n  // initialize solution data with default arguments\n  DLL_HEADER void Ng_InitSolutionData (Ng_SolutionData * soldata);\n  // set solution data\n  DLL_HEADER void Ng_SetSolutionData (Ng_SolutionData * soldata);\n  /// delete gridfunctions\n  DLL_HEADER void Ng_ClearSolutionData();\n  // redraw \n  DLL_HEADER void Ng_Redraw(bool blocking = false);\n  ///\n  DLL_HEADER void Ng_TclCmd(std::string cmd);\n  ///\n  DLL_HEADER void Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler);\n  ///\n  DLL_HEADER void Ng_SetUserVisualizationObject (netgen::UserVisualizationObject * vis);\n  //\n  DLL_HEADER void Ng_SetVisualizationParameter (const char * name, \n                                                const char * value);\n  \n\n  // number of periodic vertices  \n  DLL_HEADER int Ng_GetNPeriodicVertices (int idnr);\n  // pairs should be an integer array of 2*npairs\n  DLL_HEADER void Ng_GetPeriodicVertices (int idnr, int * pairs); \n\n  // number of periodic edges  \n  DLL_HEADER int Ng_GetNPeriodicEdges (int idnr);\n  // pairs should be an integer array of 2*npairs\n  DLL_HEADER void Ng_GetPeriodicEdges (int idnr, int * pairs); \n\n  DLL_HEADER void RunParallel ( void * (*fun)(void *), void * in);\n\n  #define NG_STATUS_USES_STD_STRING\n  DLL_HEADER void Ng_PushStatus (const std::string& str);\n  DLL_HEADER void Ng_PopStatus ();\n  DLL_HEADER void Ng_SetThreadPercentage (double percent);\n  DLL_HEADER void Ng_GetStatus (std::string& str, double & percent);\n\n  DLL_HEADER void Ng_SetTerminate(void);\n  DLL_HEADER void Ng_UnSetTerminate(void);\n  DLL_HEADER int Ng_ShouldTerminate(void);\n  DLL_HEADER void Ng_SetRunning(int flag);\n  DLL_HEADER int Ng_IsRunning();\n  \n  //// added by Roman Stainko ....\n  DLL_HEADER int Ng_GetVertex_Elements( int vnr, int* elems);\n  DLL_HEADER int Ng_GetVertex_SurfaceElements( int vnr, int* elems );\n  DLL_HEADER int Ng_GetVertex_NElements( int vnr );\n  DLL_HEADER int Ng_GetVertex_NSurfaceElements( int vnr );\n\n\n#ifdef SOCKETS\n  int Ng_SocketClientOpen( const int port, const char * host );\n  void Ng_SocketClientWrite( const char * write, char ** reply);\n  void Ng_SocketClientClose ( void );\n  void Ng_SocketClientGetServerHost ( const int number, char ** host );\n  void Ng_SocketClientGetServerPort ( const int number, int * port );\n  void Ng_SocketClientGetServerClientID ( const int number, int * id );\n#endif\n\n  DLL_HEADER void Ng_InitPointCurve(double red, double green, double blue);\n  DLL_HEADER void Ng_AddPointCurvePoint(const double * point);\n\n  \n  // #ifdef PARALLEL\n  // void Ng_SetElementPartition ( int elnr, int part );\n  // int  Ng_GetElementPartition ( int elnr );\n  // #endif\n\n  DLL_HEADER void Ng_SaveMesh ( const char * meshfile );\n  DLL_HEADER void Ng_Bisect ( const char * refinementfile );\n\n  // if qualityloss is not equal to NULL at input, a (1-based) list of qualitylosses (due to projection)\n  // is saved in *qualityloss, its size is the return value\n  DLL_HEADER int Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss);\n\n  typedef void * Ng_Mesh;\n  DLL_HEADER Ng_Mesh Ng_SelectMesh (Ng_Mesh mesh);\n\n  DLL_HEADER void Ng_GetArgs (int & argc, char ** &argv);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n\n\n\n\n\n/*\n  The new node interface ...\n  it is 0-based !\n */\n\nextern \"C\" {\n  \n  /*\n    number of nodes of type nt\n    nt = 0 is Vertex\n    nt = 1 is Edge\n    nt = 2 is Face\n    nt = 3 is Cell\n   */\n  DLL_HEADER int Ng_GetNNodes (int nt);\n\n  /*\n    closure nodes of node (nt, nodenr):\n    nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc\n    E.g., nodeset = 6 includes edge and face nodes\n    nodes consists of pairs of integers (nodetype, nodenr) \n    return value is number of nodes\n   */\n  DLL_HEADER int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes);\n\n  \n  /*\n    number of dim-dimensional elements \n    dim = 3 ... volume elements\n    dim = 2 ... surface elements\n    dim = 1 ... segments\n    dim = 0 ... not available\n  */\n  DLL_HEADER int Ng_GetNElements (int dim);\n\n  /*\n    closure nodes of dim-dimensional element elmentnr:\n    nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc\n    E.g., nodeset = 6 includes edge and face nodes\n    nodes consists of pairs of integers (nodetype, nodenr) \n    return value is number of nodes\n   */\n  DLL_HEADER int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes);\n}\n\n\n\n\n\n#ifdef __cplusplus\n#include <iostream>\nnamespace ngcore\n{\n  NGCORE_API extern int printmessage_importance;\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/include/nginterface_v2.hpp",
    "content": "#ifndef NGINTERFACE_V2\n#define NGINTERFACE_V2\n\n\n/**************************************************************************/\n/* File:   nginterface_v2.hpp                                             */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   May  09                                                        */\n/**************************************************************************/\n\n#include \"mydefs.hpp\"\n#include <core/mpi_wrapper.hpp>\n\n/*\n  C++ interface to Netgen\n*/\n\n#ifndef NGINTERFACE\n  // implemented element types:\nenum NG_ELEMENT_TYPE { \n  NG_PNT = 0,\n  NG_SEGM = 1, NG_SEGM3 = 2,\n  NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14,\n  NG_TET = 20, NG_TET10 = 21, \n  NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28,\n  NG_HEX = 25, NG_HEX20 = 26, NG_HEX7 = 29\n};\n\nenum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 };\n#endif\n\n// #ifndef PARALLEL\n// typedef int MPI_Comm;\n// #endif\n\n\nnamespace netgen\n{\n  using namespace std;\n  using namespace ngcore;\n  \n  \n  static constexpr int POINTINDEX_BASE = 1;\n\n  typedef int T_EDGE2; \n  typedef int T_FACE2; \n\n  template <typename T>\n  class Ng_Buffer\n  {\n    size_t s;\n    T * data;\n  public:\n    Ng_Buffer (size_t as, T * adata)\n      : s(as), data(adata) { ; }\n    Ng_Buffer (Ng_Buffer && buffer)\n      : s(buffer.Size()), data(buffer.Release()) { ; }\n    ~Ng_Buffer () { delete [] data; }\n    size_t Size() const { return s; }\n    T * Release() { T * hd = data; data = nullptr; return hd; }\n  };\n\n  template <typename T, int S>\n  class Ng_BufferMS\n  {\n    size_t s;\n    T data[S];\n  public:\n    Ng_BufferMS (size_t as) : s(as) { ; } \n    size_t Size() const { return s; }\n    T & operator[] (size_t i) { return data[i]; }\n    T operator[] (size_t i) const { return data[i]; }\n  };\n\n  \n  class Ng_Element\n  {\n\n    class Ng_Points\n    {\n    public:\n      size_t num;\n      const int * ptr;\n  \n      size_t Size() const { return num; }\n      int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; }\n    };\n\n\n    class Ng_Vertices\n    {\n    public:\n      size_t num;\n      const int * ptr;\n  \n      size_t Size() const { return num; }\n      int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; }\n    };\n\n    class Ng_Facets\n    {\n    public:\n      size_t num;\n      int base;\n      const int * ptr;\n      \n      size_t Size() const { return num; }\n      int operator[] (size_t i) const { return ptr[i]-base; }\n    };\n\n    \n  public:\n    NG_ELEMENT_TYPE type;\n    int index;           // material / boundary condition \n    string_view mat;   // material / boundary label\n    NG_ELEMENT_TYPE GetType() const { return type; }\n    int GetIndex() const { return index-1; }\n    Ng_Points points;      // all points\n    Ng_Vertices vertices;\n    FlatArray<T_EDGE2> edges;\n    FlatArray<T_FACE2> faces;    \n    Ng_Facets facets;\n    bool is_curved;\n    int8_t newest_vertex;\n  };\n\n  \n  class Ng_Point\n  {\n    double * pt;\n  public:\n    Ng_Point (double * apt) : pt(apt) { ; }\n    double operator[] (size_t i)\n    { return pt[i]; }\n    operator const double * () { return pt; }\n  };\n\n\n\n\n  template <int DIM> class Ng_Node;\n\n  template <>\n  class Ng_Node<0>\n  {\n    class Ng_Elements\n    {\n    public:\n      size_t ne;\n      const int * ptr;\n  \n      size_t Size() const { return ne; }\n      int operator[] (size_t i) const { return ptr[i]; }\n    };\n\n\n  public:\n    Ng_Elements elements;\n    Ng_Elements bnd_elements;\n  };\n\n\n\n  \n  template <>\n  class Ng_Node<1>\n  {\n    class Ng_Vertices\n    {\n    public:\n      const int * ptr;\n  \n      size_t Size() const { return 2; }\n      int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; }\n    };\n\n\n  public:\n    Ng_Vertices vertices;\n  };\n\n\n\n  template <>\n  class Ng_Node<2>\n  {\n    class Ng_Vertices\n    {\n    public:\n      size_t nv;\n      const int * ptr;\n  \n      size_t Size() const { return nv; }\n      int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; }\n    };\n\n    /*\n    class Ng_Edges\n    {\n    public:\n      size_t ned;\n      const int * ptr;\n  \n      size_t Size() const { return ned; }\n      int operator[] (size_t i) const { return ptr[i]-1; }\n    };\n    */\n\n  public:\n    Ng_Vertices vertices;\n    // Ng_Edges edges;\n    int surface_el;  // -1 if face not on surface\n  };\n\n\n\n    \n\n\n\n\n  class Mesh;\n\n\n  inline void DummyTaskManager2 (function<void(int,int)> func)\n  { func(0,1); }\n  inline void DummyTracer2 (string, bool) { ; } \n  \n  class DLL_HEADER Ngx_Mesh\n  {\n  private:\n    shared_ptr<Mesh> mesh;\n    \n  public:\n    // Ngx_Mesh () { ; }\n    // Ngx_Mesh(class Mesh * amesh) : mesh(amesh) { ; }\n\n    /** reuse a netgen-mesh **/\n    Ngx_Mesh (shared_ptr<Mesh> amesh); \n    /** load a new mesh **/\n    Ngx_Mesh (string filename, NgMPI_Comm acomm = NgMPI_Comm{});\n    \n    void LoadMesh (const string & filename, NgMPI_Comm comm = NgMPI_Comm{});\n\n    void LoadMesh (istream & str, NgMPI_Comm comm = NgMPI_Comm{});\n    void SaveMesh (ostream & str) const;\n    void UpdateTopology ();\n    void DoArchive (Archive & archive);\n\n    const NgMPI_Comm & GetCommunicator() const;\n    \n    virtual ~Ngx_Mesh();\n\n    bool Valid () const { return mesh != NULL; }\n    \n    int GetDimension() const;\n    int GetNLevels() const;\n    size_t GetNVLevel (int level) const;\n    \n    int GetNElements (int dim) const;\n    int GetNNodes (int nt) const;\n\n    Ng_Point GetPoint (int nr) const;\n\n    template <int DIM> \n    Ng_Element GetElement (size_t nr) const;\n\n    template <int DIM> \n    int GetElementIndex (size_t nr) const;\n\n    /// material/boundary label of region, template argument is co-dimension\n    template <int DIM> \n    string_view GetMaterialCD (int region_nr) const;\n\n    /// Curved Elements:\n    /// elnr .. element nr\n    /// xi..... DIM_EL local coordinates\n    /// x ..... DIM_SPACE global coordinates \n    /// dxdxi...DIM_SPACE x DIM_EL Jacobian matrix (row major storage)\n    template <int DIM_EL, int DIM_SPACE> \n    void ElementTransformation (int elnr,\n                                const double * xi, \n                                double * x, \n                                double * dxdxi) const;\n    \n    \n    /// Curved Elements:\n    /// elnr .. element nr\n    /// npts .. number of points\n    /// xi..... DIM_EL local coordinates\n    /// sxi ... step xi\n    /// x ..... DIM_SPACE global coordinates\n    /// dxdxi...DIM_SPACE x DIM_EL Jacobian matrix (row major storage)\n    template <int DIM_EL, int DIM_SPACE, typename T> \n    void MultiElementTransformation (int elnr, int npts,\n                                     const T * xi, size_t sxi,\n                                     T * x, size_t sx,\n                                     T * dxdxi, size_t sdxdxi) const;\n    \n\n    template <int DIM>\n    const Ng_Node<DIM> GetNode (int nr) const;\n\n    Ng_BufferMS<int,4> GetFaceEdges (int fnr) const;\n    \n    template <int DIM>\n    int GetNNodes ();\n\n    // returns domain numbers of domains next to boundary bnr -> (domin, domout)\n    // 3D only\n    // std::pair<int,int> GetBoundaryNeighbouringDomains (int bnr);\n\n    template <int DIM>\n      void SetRefinementFlag (size_t elnr, bool flag);\n    \n    void Curve (int order);\n    int GetCurveOrder ();\n\n    void EnableTable (string name, bool set);\n\n    void Refine (NG_REFINEMENT_TYPE reftype, bool onlyonce,\n                 void (*taskmanager)(function<void(int,int)>) = &DummyTaskManager2,\n                 void (*tracer)(string, bool) = &DummyTracer2);\n\n    int GetHPElementLevel (int ei, int dir) const;\n  \n    void GetParentNodes (int ni, int * parents) const;\n    int GetParentElement (int ei) const;\n    int GetParentSElement (int ei) const;\n\n    bool HasParentEdges() const;\n    std::tuple<int, std::array<int,3>> GetParentEdges (int enr) const;\n    std::tuple<int, std::array<int,4>> GetParentFaces (int fnr) const;\n    \n    int GetNIdentifications() const;\n    int GetIdentificationType(int idnr) const;\n    Ng_Buffer<int[2]> GetPeriodicVertices(int idnr) const;\n\n    // Find element of point, returns local coordinates\n    template <int DIM>\n    int FindElementOfPoint \n    (double * p, double * lami,\n     bool build_searchtrees = false, \n     int * const indices = NULL, int numind = 0, double tol = 1e-4) const;\n    \n\n    // for MPI-parallel\n    FlatArray<int> GetDistantProcs (int nodetype, int locnum) const;\n    size_t GetGlobalVertexNum (int locnum) const;\n                               \n    shared_ptr<Mesh> GetMesh () const { return mesh; } \n    shared_ptr<Mesh> SelectMesh () const;\n    inline auto GetTimeStamp() const;\n\n\n    // also added from nginterface.h, still 1-based, need redesign\n    void HPRefinement (int levels, double parameter = 0.125,\n                       bool setorders = true,bool ref_level = false);\n    void SplitAlfeld ();\n    \n    size_t GetNP() const;\n    int GetSurfaceElementSurfaceNumber (size_t ei) const;\n    int GetSurfaceElementFDNumber (size_t ei) const;\n\n    int GetElementOrder (int enr) const;\n    void GetElementOrders (int enr, int * ox, int * oy, int * oz) const;\n    void SetElementOrder (int enr, int order);\n    void SetElementOrders (int enr, int ox, int oy, int oz);\n    int GetSurfaceElementOrder (int enr) const;\n    void GetSurfaceElementOrders (int enr, int * ox, int * oy) const;\n    void SetSurfaceElementOrder (int enr, int order);\n    void SetSurfaceElementOrders (int enr, int ox, int oy);\n    int GetClusterRepVertex (int vi) const;\n    int GetClusterRepEdge (int edi) const;\n    int GetClusterRepFace (int fai) const;\n    int GetClusterRepElement (int eli) const;\n\n    // just copied from nginterface, now 0-based\n    int GetElement_Faces (int elnr, int * faces, int * orient = 0) const;\n    int GetSurfaceElement_Face (int selnr, int * orient = 0) const;\n  };\n\n\n\n  DLL_HEADER Ngx_Mesh * LoadMesh (const string & filename);\n}\n\n\n#ifdef HAVE_NETGEN_SOURCES\n#include <meshing.hpp>\n\nnamespace netgen\n{\n#ifdef __GNUC__\n#define NGX_INLINE  __attribute__ ((__always_inline__)) inline\n#else\n#define NGX_INLINE inline\n#endif  \n#include <nginterface_v2_impl.hpp>\n}\n\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/include/nginterface_v2_impl.hpp",
    "content": "NGX_INLINE DLL_HEADER Ng_Point Ngx_Mesh :: GetPoint (int nr) const\n{\n  return Ng_Point (&mesh->Point(PointIndex(nr+PointIndex::BASE))(0));\n}\n\n\ntemplate <>\nNGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<0> (size_t nr) const\n{\n  return (*mesh).pointelements[nr].index;\n}\n\ntemplate <>\nNGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<1> (size_t nr) const\n{\n  /*\n  if(mesh->GetDimension()==3)\n    return (*mesh)[SegmentIndex(nr)].edgenr;\n  else\n    return (*mesh)[SegmentIndex(nr)].si;\n  */\n  /*\n  if(mesh->GetDimension()==3)\n    return mesh->LineSegments()[nr].edgenr;\n  else\n    return mesh->LineSegments()[nr].si;\n  */\n  return mesh->LineSegments()[nr].GetIndex();\n}\n  \ntemplate <>\nNGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<2> (size_t nr) const\n{\n  // int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); \n  // return mesh->GetFaceDescriptor(ind).BCProperty();\n  const Element2d & el = (*mesh)[SurfaceElementIndex(nr)];\n  return mesh->GetFaceDescriptor(el).BCProperty();\n}\n\ntemplate <>\nNGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<3> (size_t nr) const\n{\n  return (*mesh)[ElementIndex(nr)].GetIndex();\n}\n\n\ntemplate <>\nNGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const\n{\n  const Element0d & el = mesh->pointelements[nr];\n  \n  Ng_Element ret;\n  ret.type = NG_PNT;\n  ret.index = el.index;\n  ret.mat = el.name;\n  \n  ret.points.num = 1;\n  ret.points.ptr = (int*)&el.pnum;\n  \n  ret.vertices.num = 1;\n  ret.vertices.ptr = (int*)&el.pnum;\n\n  /*\n  ret.edges.num = 0;\n  ret.edges.ptr = NULL;\n  */\n  ret.edges.Assign ( FlatArray<T_EDGE2> (0, nullptr) );\n  /*\n  ret.faces.num = 0;\n  ret.faces.ptr = NULL;\n  */\n  ret.faces.Assign ( { 0, nullptr } );  \n  \n  ret.facets.num = 1;\n  ret.facets.base = POINTINDEX_BASE;\n  ret.facets.ptr = (int*)&el.pnum;\n\n  /*\n  if (mesh->GetDimension() == 1)\n    ret.mat = *(mesh->GetBCNamePtr(el.index-1));\n  else if (mesh->GetDimension() == 2)\n    ret.mat = *(mesh->GetCD2NamePtr(el.index-1));\n  else\n    ret.mat = *(mesh->GetCD3NamePtr(el.index-1));\n  */\n  ret.mat = mesh->GetRegionName(0, el.index);\n    \n  ret.is_curved = false;\n  return ret;\n}\n\n\n\ntemplate <> \nNGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const\n{\n  // const Segment & el = mesh->LineSegment (SegmentIndex(nr));\n  const Segment & el = mesh->LineSegments()[nr];\n\n  Ng_Element ret;\n  ret.type = NG_ELEMENT_TYPE(el.GetType());\n  /*\n  if(mesh->GetDimension()==3)\n    ret.index = el.edgenr;\n  else\n    ret.index = el.si;\n  */\n  ret.index = el.GetIndex();\n\n  \n  /*\n  if (mesh->GetDimension() == 2)\n    ret.mat = *(mesh->GetBCNamePtr(el.si-1));\n  else\n    {\n      if (mesh->GetDimension() == 3)\n        ret.mat = *(mesh->GetCD2NamePtr(el.edgenr-1));\n      else\n        ret.mat = *(mesh->GetMaterialPtr(el.si));\n    }\n  */\n  ret.mat = mesh->GetRegionName(1, ret.index);\n\n  ret.points.num = el.GetNP();\n  ret.points.ptr = (int*)&(el[0]);\n\n  ret.vertices.num = 2;\n  ret.vertices.ptr = (int*)&(el[0]);\n\n  /*\n  ret.edges.num = 1;\n  ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr);\n  */\n  ret.edges.Assign ( FlatArray<T_EDGE2> (1, const_cast<T_EDGE2*>((const int*)  mesh->GetTopology().GetSegmentElementEdgesPtr (nr))));\n\n  /*\n  ret.faces.num = 0;\n  ret.faces.ptr = NULL;\n  */\n  ret.faces.Assign ( { 0, nullptr });\n  \n  if (mesh->GetDimension() == 3)\n    {\n      ret.facets.num = 0;\n      ret.facets.base = 0;\n      ret.facets.ptr = nullptr;\n    }\n  else if (mesh->GetDimension() == 2)\n    {\n      ret.facets.num = 1;\n      ret.facets.base = 0;\n      ret.facets.ptr = ret.edges.Data();\n    }\n  else\n    {\n      ret.facets.num = 2;\n      ret.facets.base = POINTINDEX_BASE;\n      ret.facets.ptr = (int*)&(el[0]);\n    }\n\n  // ret.is_curved = mesh->GetCurvedElements().IsSegmentCurved(nr);\n  ret.is_curved = el.IsCurved();\n\n  return ret;\n}\n\ntemplate <> \nNGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (size_t nr) const\n{\n  const Element2d & el = mesh->SurfaceElements()[nr];\n  \n  Ng_Element ret;\n  ret.type = NG_ELEMENT_TYPE(el.GetType());\n  const FaceDescriptor & fd = mesh->GetFaceDescriptor(el); // .GetIndex());\n  ret.index = fd.BCProperty();\n  if (mesh->GetDimension() == 3)\n    ret.mat = fd.GetBCName();\n  else\n    ret.mat = *(mesh -> GetMaterialPtr(ret.index));\n  ret.points.num = el.GetNP();\n  ret.points.ptr  = (int*)&el[0];\n\n  ret.vertices.num = el.GetNV();\n  ret.vertices.ptr = (int*)&(el[0]);\n\n  /*\n  ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n  ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr);\n  */\n\n  // ret.edges.Assign (mesh->GetTopology().GetEdges (SurfaceElementIndex(nr)));\n  auto hedges = mesh->GetTopology().GetEdges (SurfaceElementIndex(nr));\n  ret.edges.Assign ( { hedges.Size(), (int*)hedges.Data() } );\n  \n  /*\n  ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n  ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr);\n  */\n\n  // ret.faces.Assign ( { 1, const_cast<int*>(mesh->GetTopology().GetSurfaceElementFacesPtr (nr)) });\n  ret.faces.Assign ( { 1, (int*)(mesh->GetTopology().GetSurfaceElementFacesPtr (nr)) });\n  \n  if (mesh->GetDimension() == 3)\n    {\n      ret.facets.num = ret.faces.Size();\n      ret.facets.base = 0;\n      ret.facets.ptr = ret.faces.Data();\n    }\n  else\n    {\n      ret.facets.num = ret.edges.Size();\n      ret.facets.base = 0;      \n      ret.facets.ptr = ret.edges.Data();\n    }\n  ret.is_curved = el.IsCurved();\n  ret.newest_vertex = el.NewestVertex();\n  return ret;\n}\n\ntemplate <> \nNGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (size_t nr) const\n{\n  const Element & el = mesh->VolumeElements()[nr];\n  \n  Ng_Element ret;\n  ret.type = NG_ELEMENT_TYPE(el.GetType());\n  ret.index = el.GetIndex();\n  ret.mat = *(mesh -> GetMaterialPtr(ret.index));\n  ret.points.num = el.GetNP();\n  ret.points.ptr = (int*)&el[0];\n\n  ret.vertices.num = el.GetNV();\n  ret.vertices.ptr = (int*)&(el[0]);\n\n  /*\n  ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n  ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr);\n  */\n  // ret.edges.Assign (mesh->GetTopology().GetEdges (ElementIndex(nr)));\n  auto hedges = mesh->GetTopology().GetEdges (ElementIndex(nr));\n  ret.edges.Assign ( { hedges.Size(), (int*)hedges.Data() } );\n  \n\n  /*\n  ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n  ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr);\n  */\n  // ret.faces.Assign (mesh->GetTopology().GetFaces (ElementIndex(nr)));\n  auto hfaces = mesh->GetTopology().GetFaces (ElementIndex(nr));\n  ret.faces.Assign ( { hfaces.Size(), (int*)hfaces.Data() } );\n  \n  ret.facets.num = ret.faces.Size();\n  ret.facets.base = 0;\n  ret.facets.ptr = ret.faces.Data();\n\n  ret.is_curved = el.IsCurved();\n  ret.newest_vertex = el.NewestVertex();\n  return ret;\n}\n\n\n\ntemplate <> NGX_INLINE DLL_HEADER\nstring_view Ngx_Mesh :: GetMaterialCD<0> (int region_nr) const\n{\n  return mesh->GetMaterial(region_nr+1);\n}\n\ntemplate <> NGX_INLINE DLL_HEADER\nstring_view Ngx_Mesh :: GetMaterialCD<1> (int region_nr) const\n{\n  return mesh->GetBCName(region_nr);\n}\n\ntemplate <> NGX_INLINE DLL_HEADER\nstring_view Ngx_Mesh :: GetMaterialCD<2> (int region_nr) const\n{\n  return mesh->GetCD2Name(region_nr);\n}\n\ntemplate <> NGX_INLINE DLL_HEADER\nstring_view Ngx_Mesh :: GetMaterialCD<3> (int region_nr) const\n{\n  return mesh->GetCD3Name(region_nr);\n}\n\n\n\n\n\ntemplate <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<1> ()\n{\n  return mesh->GetTopology().GetNEdges();\n}\n\ntemplate <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<2> ()\n{\n  return mesh->GetTopology().GetNFaces();\n}\n\ntemplate <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr_) const\n{\n  Ng_Node<0> node;\n  PointIndex vnr = IndexBASE<PointIndex>() + vnr_;\n  switch (mesh->GetDimension())\n    {\n    case 3:\n      {\n        auto ia = mesh->GetTopology().GetVertexElements(vnr);\n        node.elements.ne = ia.Size();\n        node.elements.ptr = (int*)ia.Data();\n        \n        auto bia = mesh->GetTopology().GetVertexSurfaceElements(vnr);\n        node.bnd_elements.ne = bia.Size();\n        node.bnd_elements.ptr = (int*)bia.Data();\n        break;\n      }\n    case 2:\n      {\n        auto ia = mesh->GetTopology().GetVertexSurfaceElements(vnr);\n        node.elements.ne = ia.Size();\n        node.elements.ptr = (int*)ia.Data();\n        \n        auto bia = mesh->GetTopology().GetVertexSegments(vnr);\n        node.bnd_elements.ne = bia.Size();\n        node.bnd_elements.ptr = (int*)bia.Data();\n        break;\n      }\n    case 1:\n      {\n        auto ia = mesh->GetTopology().GetVertexSegments(vnr);\n        node.elements.ne = ia.Size();\n        node.elements.ptr = (int*)ia.Data();\n        \n        auto bia = mesh->GetTopology().GetVertexPointElements(vnr);\n        node.bnd_elements.ne = bia.Size();\n        node.bnd_elements.ptr = (int*)bia.Data();\n        break;\n      }\n    default:\n      ;\n    }\n  return node;\n}\n  \ntemplate <> NGX_INLINE DLL_HEADER const Ng_Node<1> Ngx_Mesh :: GetNode<1> (int nr) const\n{\n  Ng_Node<1> node;\n  node.vertices.ptr = (const int*)mesh->GetTopology().GetEdgeVerticesPtr(nr);\n  return node;\n}\n\ntemplate <> NGX_INLINE DLL_HEADER const Ng_Node<2> Ngx_Mesh :: GetNode<2> (int nr) const\n{\n  Ng_Node<2> node;\n  node.vertices.ptr = (const int*)mesh->GetTopology().GetFaceVerticesPtr(nr);\n  node.vertices.nv = (node.vertices.ptr[3]+1 == PointIndex::BASE) ? 3 : 4;\n  node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr);\n  return node;\n}\n\n\nNGX_INLINE DLL_HEADER Ng_Buffer<int[2]> Ngx_Mesh :: GetPeriodicVertices(int idnr) const\n{\n  NgArray<INDEX_2> apairs;\n  mesh->GetIdentifications().GetPairs (idnr+1, apairs);\n  for(auto& ind : apairs)\n    {\n      ind.I1() -= IndexBASE<PointIndex>();\n      ind.I2() -= IndexBASE<PointIndex>();\n    }\n  typedef int ti2[2];\n  return { apairs.Size(), (ti2*)(void*)apairs.Release() };\n}\n\n\nNGX_INLINE void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const\n{\n  if (ni < mesh->mlbetweennodes.Size())\n    for (int j = 0; j < 2; j++)\n      parents[j] = mesh->mlbetweennodes[IndexBASE<PointIndex>()+ni][j] - IndexBASE<PointIndex>();\n  else\n    parents[0] = parents[1] = -1;\n}\n\ninline bool Ngx_Mesh :: HasParentEdges() const\n{\n  return mesh->GetTopology().HasParentEdges();\n}\n\ninline tuple<int, std::array<int,3>> Ngx_Mesh :: GetParentEdges (int enr) const\n{\n  return mesh->GetTopology().GetParentEdges(enr);\n}\n\ninline tuple<int, std::array<int,4>> Ngx_Mesh :: GetParentFaces (int fnr) const\n{\n  return mesh->GetTopology().GetParentFaces(fnr);\n}\n\n\ninline auto Ngx_Mesh :: GetTimeStamp() const { return mesh->GetTimeStamp(); }\n"
  },
  {
    "path": "libsrc/include/ngsimd.hpp",
    "content": "#include <../general/ngsimd.hpp>\n"
  },
  {
    "path": "libsrc/include/occgeom.hpp",
    "content": "#include \"../occ/occgeom.hpp\"\n"
  },
  {
    "path": "libsrc/include/opti.hpp",
    "content": "#include \"../linalg/opti.hpp\"\n"
  },
  {
    "path": "libsrc/include/parallel.hpp",
    "content": "#include \"../parallel/parallel.hpp\"\n"
  },
  {
    "path": "libsrc/include/stlgeom.hpp",
    "content": "#include <../stlgeom/stlgeom.hpp>\n"
  },
  {
    "path": "libsrc/include/visual.hpp",
    "content": "#include \"../visualization/visual.hpp\"\n"
  },
  {
    "path": "libsrc/interface/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE writeuser.cpp\n        nginterface.cpp nginterface_v2.cpp \n        read_fnf_mesh.cpp readtetmesh.cpp readuser.cpp writeabaqus.cpp writediffpack.cpp \n        writedolfin.cpp writeelmer.cpp writefeap.cpp writefluent.cpp writegmsh.cpp writejcm.cpp \n        writepermas.cpp writetecplot.cpp writetet.cpp writetochnog.cpp\n        wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp rw_cgns.cpp rw_medit.cpp\n)\n\ninstall(FILES\n  writeuser.hpp rw_medit.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/interface COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/interface/nginterface.cpp",
    "content": "#include <mystdlib.h>\n\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <geometry2d.hpp>\n\n#ifdef SOCKETS\n#include \"../sockets/sockets.hpp\"\n#endif\n\n#include \"../general/gzstream.h\"\n\n#include \"nginterface.h\"\n// #include \"../visualization/soldata.hpp\"\n// #include <visual.hpp>\n\n\n\nnamespace netgen\n{\n  DLL_HEADER MeshingParameters mparam;\n\n  /** Force linking of geom2d library (for SplineGeometryRegister)**/\n  SplineGeometry2d dummy_2dgeom; \n}\n\nstatic std::thread meshingthread;\nvoid RunParallel ( void * (*fun)(void *), void * in)\n{\n  if (netgen::mparam.parthread)\n    {\n      meshingthread = std::thread(fun, in);\n      meshingthread.detach();\n    }\n  else\n    fun (in);\n}\n\n\n\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n  extern shared_ptr<Mesh> mesh;\n  extern shared_ptr<NetgenGeometry> ng_geometry;\n\n  extern Tcl_Interp * tcl_interp;\n\n#ifdef SOCKETS\n  extern AutoPtr<ClientSocket> clientsocket;\n  //extern NgArray< AutoPtr < ServerInfo > > servers;\n  extern NgArray< ServerInfo* > servers;\n#endif\n\n  \n}\n\n\nusing namespace netgen;\n\n\nvoid Ng_LoadGeometry (const char * filename)\n{\n  // he: if filename is empty, return\n  // can be used to reset geometry\n  if (!filename || strcmp(filename,\"\")==0) \n    {\n      ng_geometry.reset (new NetgenGeometry());\n      return;\n    }\n\n  for (auto loader : GeometryRegister())\n    {\n      NetgenGeometry * hgeom = loader->Load (filename);\n      if (hgeom)\n\t{\n          ng_geometry.reset (hgeom);\n\t  mesh.reset();\n\t  return;\n\t}\n    }\n\n\n  // if (id == 0)\n  cerr << \"cannot load geometry '\" << filename << \"'\" << \", id = \" << id << endl;\n}                          \n\n\nvoid Ng_LoadMeshFromStream ( istream & input )\n{\n  mesh.reset (new Mesh());\n  mesh -> Load(input);\n\n  SetGlobalMesh (mesh);\n  ng_geometry = GeometryRegister().LoadFromMeshFile (input);\n\n  if (!ng_geometry)\n    ng_geometry = make_shared<NetgenGeometry>();\n  mesh->SetGeometry (ng_geometry);\n}\n\n\nvoid Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm)\n{\n  int id = comm.Rank();\n  int ntasks = comm.Size();\n\n  {\n    ifstream infile(filename);\n    if(!infile.good())\n      throw NgException(string(\"Error opening file \") + filename);\n  }\n\n  if ( string(filename).find(\".vol\") == string::npos )\n    {\n      if(ntasks>1)\n\tthrow NgException(\"Not sure what to do with this?? Does this work with MPI??\");\n      mesh.reset (new Mesh());\n      mesh->SetCommunicator(comm);\n      ReadFile(*mesh,filename);\n      //mesh->SetGlobalH (mparam.maxh);\n      //mesh->CalcLocalH();\n      return;\n    }\n\n  istream * infile;\n  Array<char> buf; // for distributing geometry!\n  int strs;\n\n  if( id == 0) {\n\n    mesh.reset (new Mesh());\n    mesh->SetCommunicator(comm);\n    \n    string fn(filename);\n    if (fn.length() > 8 && fn.substr (fn.length()-8, 8) == \".vol.bin\")\n      {\n        mesh -> Load(fn);\n        SetGlobalMesh (mesh);        \n      }\n    else\n      {\n        if (fn.substr (fn.length()-3, 3) == \".gz\")\n          infile = new igzstream (filename);\n        else\n          infile = new ifstream (filename);\n        mesh -> Load(*infile);\n        SetGlobalMesh (mesh);\n        \n        // make string from rest of file (for geometry info!)\n        // (this might be empty, in which case we take the global ng_geometry)\n        stringstream geom_part;\n        geom_part << infile->rdbuf();\n        string geom_part_string = geom_part.str();\n        strs = geom_part_string.size();\n        // buf = new char[strs];\n        buf.SetSize(strs);\n        memcpy(buf.Data(), geom_part_string.c_str(), strs*sizeof(char));\n        \n        delete infile;\n      }\n\n    \n    if (ntasks > 1)\n      {\n\n\tchar * weightsfilename = new char [strlen(filename)+1];\n\tstrcpy (weightsfilename, filename);            \n\tweightsfilename[strlen (weightsfilename)-3] = 'w';\n\tweightsfilename[strlen (weightsfilename)-2] = 'e';\n\tweightsfilename[strlen (weightsfilename)-1] = 'i';\n\n\tifstream weightsfile(weightsfilename);      \n\tdelete [] weightsfilename;  \n\t  \n\tif (!(weightsfile.good()))\n\t  {\n\t    // cout << \"regular distribute\" << endl;\n\t    mesh -> Distribute();\n\t  }\n\telse\n\t  {\n\t    char str[20];   \n\t    bool endfile = false;\n\t    int n, dummy;\n\t      \n\t    NgArray<int> segment_weights;\n\t    NgArray<int> surface_weights;\n\t    NgArray<int> volume_weights;\n\t      \n\t    while (weightsfile.good() && !endfile)\n\t      {\n\t\tweightsfile >> str;\n\t\t  \n\t\tif (strcmp (str, \"edgeweights\") == 0)\n\t\t  {\n\t\t    weightsfile >> n;\n\t\t    segment_weights.SetSize(n);\n\t\t    for (int i = 0; i < n; i++)\n\t\t      weightsfile >> dummy >> segment_weights[i];\n\t\t  }\n\t\t  \n\t\tif (strcmp (str, \"surfaceweights\") == 0)\n\t\t  {\n\t\t    weightsfile >> n;\n\t\t    surface_weights.SetSize(n);\n\t\t    for (int i=0; i<n; i++)\n\t\t      weightsfile >> dummy >> surface_weights[i];\n\t\t  }\n\t\t  \n\t\tif (strcmp (str, \"volumeweights\") == 0)\n\t\t  {\n\t\t    weightsfile >> n;\n\t\t    volume_weights.SetSize(n);\n\t\t    for (int i=0; i<n; i++)\n\t\t      weightsfile >> dummy >> volume_weights[i];\n\t\t  }\n\t\t  \n\t\tif (strcmp (str, \"endfile\") == 0)\n\t\t  endfile = true;  \n\t      }     \n\t      \n\t    mesh -> Distribute(volume_weights, surface_weights, segment_weights);\n\t  }\n      } // ntasks>1 end\n  } // id==0 end\n  else {\n    mesh.reset (new Mesh());\n    mesh->SetCommunicator(comm);\n    SetGlobalMesh (mesh);\n    mesh->SendRecvMesh();\n  }\n\n    /*\n  if(ntasks>1) {\n#ifdef PARALLEL\n    // Scatter the geometry-string (no dummy-implementation in mpi_interface) \n    int strs = buf.Size();\n    MyMPI_Bcast(strs, comm);\n    if(strs>0)\n      MyMPI_Bcast(buf, comm);\n #endif\n }\n  */\n  comm.Bcast(buf);\n\n  shared_ptr<NetgenGeometry> geo;\n  if(buf.Size()) { // if we had geom-info in the file, take it\n    istringstream geom_infile(string((const char*)&buf[0], buf.Size()));\n    geo = GeometryRegister().LoadFromMeshFile(geom_infile);\n  }\n  if(geo!=nullptr) {\n    ng_geometry = geo;\n    mesh->SetGeometry(geo);\n  }\n  else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry);\n}\n\nvoid Ng_LoadMeshFromString (const char * mesh_as_string)\n{\n  istringstream instream(mesh_as_string);\n  Ng_LoadMeshFromStream(instream);\n}\n  \n\n\n\nint Ng_GetDimension ()\n{\n  return (mesh) ? mesh->GetDimension() : -1;\n}\n\nint Ng_GetNP ()\n{\n  return (mesh) ? mesh->GetNP() : 0;\n}\n\nint Ng_GetNV ()\n{\n  return (mesh) ? mesh->GetNV() : 0;\n}\n\nint Ng_GetNE ()\n{\n  if(!mesh) return 0;\n  if (mesh->GetDimension() == 3)\n    return mesh->GetNE();\n  else\n    return mesh->GetNSE();\n}\n\nint Ng_GetNSE ()\n{\n  if(!mesh) return 0;\n  if (mesh->GetDimension() == 3)\n    return mesh->GetNSE();\n  else\n    return mesh->GetNSeg();\n}\n\nvoid Ng_GetPoint (int pi, double * p)\n{\n  if (pi < 1 || pi > mesh->GetNP())\n    {\n      if (printmessage_importance>0)\n        cout << \"Ng_GetPoint: illegal point \" << pi << endl;\n      return;\n    }\n\n  const Point3d & hp = mesh->Point (pi);\n  p[0] = hp.X();\n  p[1] = hp.Y();\n  if (mesh->GetDimension() == 3)\n    p[2] = hp.Z();\n}\n\n\nNG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      int i;\n      const Element & el = mesh->VolumeElement (ei);\n      for (i = 0; i < el.GetNP(); i++)\n\tepi[i] = el.PNum(i+1);\n      \n      if (np)\n\t*np = el.GetNP();\n\n      if (el.GetType() == PRISM)\n\t{\n\t  // degenerated prism, (should be obsolete)\n\t  const int map1[] = { 3, 2, 5, 6, 1 };\n\t  const int map2[] = { 1, 3, 6, 4, 2 };\n\t  const int map3[] = { 2, 1, 4, 5, 3 };\n\t  \n\t  const int * map = NULL;\n\t  int deg1 = 0, deg2 = 0, deg3 = 0;\n\t  //int deg = 0;\n\t  if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; }\n\t  if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; }\n\t  if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; }\n\t  \n\t  switch (deg1+deg2+deg3)\n\t    {\n\t      {\n\t      case 1:\n                if (printmessage_importance>0)\n                  cout << \"degenerated prism found, deg = 1\" << endl;\n\t\tfor (i = 0; i < 5; i++)\n\t\t  epi[i] = el.PNum (map[i]);\n\t\t\n\t\tif (np) *np = 5;\n\t\treturn NG_PYRAMID;\n\t\tbreak;\n\t      }\n\t    case 2:\n\t      {\n                if (printmessage_importance>0)\n                  cout << \"degenerated prism found, deg = 2\" << endl;\n\t\tif (!deg1) epi[3] = el.PNum(4);\n\t\tif (!deg2) epi[3] = el.PNum(5);\n\t\tif (!deg3) epi[3] = el.PNum(6);\n\t\t\n\t\tif (np) *np = 4;\n\t\treturn NG_TET;\n\t\tbreak;\n\t      }\n\t    default:\n\t      ;\n\t    }\n\t  \n\t}\n\n      return NG_ELEMENT_TYPE (el.GetType());\n    }\n  else\n    {\n      const Element2d & el = mesh->SurfaceElement (ei);\n      for (int i = 0; i < el.GetNP(); i++)\n\tepi[i] = el.PNum(i+1);      \n\n      if (np) *np = el.GetNP();\n      return NG_ELEMENT_TYPE (el.GetType());\n    }\n\n  // should not occur\n  return NG_TET;\n}\n\n\nNG_ELEMENT_TYPE Ng_GetElementType (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      return NG_ELEMENT_TYPE (mesh->VolumeElement (ei).GetType());\n    }\n  else\n    {\n      const Element2d & el = mesh->SurfaceElement (ei);\n      switch (el.GetNP())\n\t{\n\tcase 3: return NG_TRIG; \n\tcase 4: return NG_QUAD; \n\tcase 6: return NG_TRIG6; \n\t}\n    }\n\n  // should not occur\n  return NG_TET;\n}\n\n\n\nint Ng_GetElementIndex (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->VolumeElement(ei).GetIndex();\n  else\n    {\n      int ind = mesh->SurfaceElement(ei).GetIndex(); \n      ind = mesh->GetFaceDescriptor(ind).BCProperty();\n      return ind;\n    }\n}\n\nvoid Ng_SetElementIndex(const int ei, const int index)\n{\n  mesh->VolumeElement(ei).SetIndex(index);\n}\n\nconst char * Ng_GetElementMaterial (int ei)\n{\n  static char empty[] = \"\";\n  if (mesh->GetDimension() == 3)\n    {\n      int ind = mesh->VolumeElement(ei).GetIndex();\n      // cout << \"ind = \" << ind << endl;\n      const string * mat = mesh->GetMaterialPtr (ind);\n      if (mat)\n\t// return const_cast<char*> (mat);\n        return mat->c_str();\n      else \n\treturn empty;\n    }\n  // add astrid\n  else\n    {\n      int ind = mesh->SurfaceElement(ei).GetIndex();\n      ind = mesh->GetFaceDescriptor(ind).BCProperty();\n      const string * mat = mesh->GetMaterialPtr ( ind );\n      if (mat)\n\treturn mat->c_str();\n      else\n\treturn empty;\n    }\n  return 0;\n}\n\nconst char * Ng_GetDomainMaterial (int dom)\n{\n  static char empty[] = \"\";\n  // astrid\n  if ( 1 ) // mesh->GetDimension() == 3)\n    {\n      const string * mat = mesh->GetMaterialPtr(dom);\n      if (mat)\n\treturn mat->c_str();\n      else \n\treturn empty;      \n    }\n\n  return 0;\n}\n\nint Ng_GetUserDataSize (char * id)\n{\n  NgArray<double> da;\n  mesh->GetUserData (id, da);\n  return da.Size();\n}\n\nvoid Ng_GetUserData (char * id, double * data)\n{\n  NgArray<double> da;\n  mesh->GetUserData (id, da);\n  for (int i = 0; i < da.Size(); i++)\n    data[i] = da[i];\n}\n\n\nNG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      const Element2d & el = mesh->SurfaceElement (ei);\n      for (int i = 0; i < el.GetNP(); i++)\n\tepi[i] = el[i];\n      \n      if (np) *np = el.GetNP();\n      \n      return NG_ELEMENT_TYPE (el.GetType());\n    }\n  else\n    {\n      const Segment & seg = mesh->LineSegment (ei);\n\n      if (!seg[2].IsValid())\n\t{\n\t  epi[0] = seg[0];\n\t  epi[1] = seg[1];\n\t  \n\t  if (np) *np = 2;\n\t  return NG_SEGM;\n\t}\n      else\n\t{\n\t  epi[0] = seg[0];\n\t  epi[1] = seg[1];\n\t  epi[2] = seg[2];\n\n\t  if (np) *np = 3;\n\t  return NG_SEGM3;\n\t}\n    }\n\n  return NG_TRIG;\n}\n\nint Ng_GetSurfaceElementIndex (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).BCProperty();\n  else\n    return mesh->LineSegment(ei).si;\n}\n\nint Ng_GetSurfaceElementSurfaceNumber (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr();\n  else\n    return mesh->LineSegment(ei).si;\n}\nint Ng_GetSurfaceElementFDNumber (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->SurfaceElement(ei).GetIndex();\n  else\n    return -1;\n}\n\n\nchar * Ng_GetSurfaceElementBCName (int ei)\n{\n  if ( mesh->GetDimension() == 3 )\n    return const_cast<char *>(mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str());\n  else\n    return const_cast<char *>(mesh->GetBCName(mesh->LineSegment(ei).si).c_str());\n}\n\n\n// Inefficient (but maybe safer) version:\n//void Ng_GetSurfaceElementBCName (int ei, char * name)\n//{\n//  if ( mesh->GetDimension() == 3 )\n//      strcpy(name,mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str());\n//  else\n//      strcpy(name,mesh->LineSegment(ei).GetBCName().c_str());\n//}\n\nchar * Ng_GetBCNumBCName (int bcnr)\n{\n  return const_cast<char *>(mesh->GetBCName(bcnr).c_str());\n}\n\nchar * Ng_GetCD2NumCD2Name (int cd2nr)\n{\n  return const_cast<char *>(mesh->GetCD2Name(cd2nr).c_str());\n}\n\n\n// Inefficient (but maybe safer) version:\n//void Ng_GetBCNumBCName (int bcnr, char * name)\n//{\n//    strcpy(name,mesh->GetBCName(bcnr).c_str());\n//}\n\n/*\nvoid Ng_GetNormalVector (int sei, int locpi, double * nv)\n{\n  nv[0] = 0; \n  nv[1] = 0;\n  nv[2] = 1;\n  \n  if (mesh->GetDimension() == 3)\n    {\n      Vec<3> n;\n      Point<3> p;\n      p = mesh->Point (mesh->SurfaceElement(sei).PNum(locpi));\n\n      int surfi = mesh->GetFaceDescriptor(mesh->SurfaceElement(sei).GetIndex()).SurfNr();\n      \n      (*testout) << \"surfi = \" << surfi << endl;\n#ifdef OCCGEOMETRYxxx\n      OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry);\n      if (occgeometry)\n\t{\n\t  PointGeomInfo gi = mesh->SurfaceElement(sei).GeomInfoPi(locpi);\n\t  occgeometry->GetSurface (surfi).GetNormalVector(p, gi, n);\n\t  nv[0] = n(0);\n\t  nv[1] = n(1);\n\t  nv[2] = n(2);\n\t}\n#endif\n      CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n      if (geometry)\n\t{\n\t  n = geometry->GetSurface (surfi) -> GetNormalVector(p);\n\t  nv[0] = n(0);\n\t  nv[1] = n(1);\n\t  nv[2] = n(2);\n\t}\n    }\n}\n*/\n\n\nvoid Ng_SetPointSearchStartElement(const int el)\n{\n  mesh->SetPointSearchStartElement(el);\n}\n\n\nint Ng_FindElementOfPoint (double * p, double * lami, int build_searchtree, \n\t\t\t   const int * const indices, const int numind)\n  \n{\n  NgArray<int> * dummy(NULL);\n  int ind = -1;\n\n  if(indices != NULL)\n    {\n      dummy = new NgArray<int>(numind);\n      for(int i=0; i<numind; i++) (*dummy)[i] = indices[i];\n    }\n\n  if (mesh->GetDimension() == 3)\n    {\n      Point3d p3d(p[0], p[1], p[2]);\n      ind = \n\tmesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;\n    }\n  else\n    {\n      double lam3[3];\n      Point3d p2d(p[0], p[1], 0);\n      ind = \n\tmesh->GetSurfaceElementOfPoint(p2d, lam3, dummy, build_searchtree != 0) + 1;\n\n      if (ind > 0)\n\t{\n\t  if(mesh->SurfaceElement(ind).GetType()==QUAD)\n\t    {\n\t      lami[0] = lam3[0];\n\t      lami[1] = lam3[1];\n\t    }\n\t  else \n\t    {\n\t      lami[0] = 1-lam3[0]-lam3[1];\n\t      lami[1] = lam3[0];\n\t    }\n\t}\n    }\n\n  delete dummy;\n\n  return ind;\n}\n\nint Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtree, \n\t\t\t\t  const int * const indices, const int numind)\n  \n{\n  NgArray<int> * dummy(NULL);\n  int ind = -1;\n\n  if(indices != NULL)\n    {\n      dummy = new NgArray<int>(numind);\n      for(int i=0; i<numind; i++) (*dummy)[i] = indices[i];\n    }\n\n  if (mesh->GetDimension() == 3)\n    {\n      Point3d p3d(p[0], p[1], p[2]);\n      ind = \n\tmesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;\n    }\n  else\n    {\n      //throw NgException(\"FindSurfaceElementOfPoint for 2D meshes not yet implemented\");\n      cerr << \"FindSurfaceElementOfPoint for 2D meshes not yet implemented\" << endl;\n    }\n\n  delete dummy;\n\n  return ind;\n}\n\n\nint Ng_IsElementCurved (int ei)\n{\n  switch (mesh->GetDimension())\n    {\n    case 1: return mesh->GetCurvedElements().IsSegmentCurved (ei-1);\n    case 2: return mesh->GetCurvedElements().IsSurfaceElementCurved (ei-1);\n    case 3: return mesh->GetCurvedElements().IsElementCurved (ei-1);\n    }\n  return 0;\n  /*\n  if (mesh->GetDimension() == 2)\n    return mesh->GetCurvedElements().IsSurfaceElementCurved (ei-1);\n  else\n    return mesh->GetCurvedElements().IsElementCurved (ei-1);\n  */\n}\n\n\nint Ng_IsSurfaceElementCurved (int sei)\n{\n  if (mesh->GetDimension() == 2)\n    return mesh->GetCurvedElements().IsSegmentCurved (sei-1);\n  else\n    return mesh->GetCurvedElements().IsSurfaceElementCurved (sei-1);\n}\n\n\n\n\nvoid Ng_GetElementTransformation (int ei, const double * xi, \n\t\t\t\t  double * x, double * dxdxi)\n{\n  if (mesh->GetDimension() == 2)\n    {\n      Point<2> xl(xi[0], xi[1]);\n      Point<3> xg;\n      Mat<3,2> dx;\n\n      mesh->GetCurvedElements().CalcSurfaceTransformation (xl, ei-1, xg, dx);\n\n      if (x)\n\t{\n\t  for (int i = 0; i < 2; i++)\n\t    x[i] = xg(i);\n\t}\n\t  \n      if (dxdxi)\n\t{\n\t  for (int i=0; i<2; i++)\n\t    {\n\t      dxdxi[2*i] = dx(i,0);\n\t      dxdxi[2*i+1] = dx(i,1);\n\t    }\n\t}\n    }\n  else\n    {\n      Point<3> xl(xi[0], xi[1], xi[2]);\n      Point<3> xg;\n      Mat<3,3> dx;\n\n      mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx);\n\n      if (x)\n\t{\n\t  for (int i = 0; i < 3; i++)\n\t    x[i] = xg(i);\n\t}\n\n      if (dxdxi)\n\t{\n\t  for (int i=0; i<3; i++)\n\t    {\n\t      dxdxi[3*i] = dx(i,0);\n\t      dxdxi[3*i+1] = dx(i,1);\n              dxdxi[3*i+2] = dx(i,2);\n\t    }\n\t}\n    }\n}\n\n\n\n\nvoid Ng_GetMultiElementTransformation (int ei, int n,\n                                       const double * xi, size_t sxi,\n                                       double * x, size_t sx,\n                                       double * dxdxi, size_t sdxdxi)\n{\n  if (mesh->GetDimension() == 2)\n    mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (ei-1, n, xi, sxi, x, sx, dxdxi, sdxdxi);\n  else\n    mesh->GetCurvedElements().CalcMultiPointElementTransformation (ei-1, n, xi, sxi, x, sx, dxdxi, sdxdxi);\n}\n\n\n\nvoid Ng_GetSurfaceElementTransformation (int sei, const double * xi, \n\t\t\t\t\t double * x, double * dxdxi)\n{\n  if (mesh->GetDimension() == 2)\n    {\n      Point<3> xg;\n      Vec<3> dx;\n\n      mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], sei-1, xg, dx);\n\n      if (x)\n        for (int i = 0; i < 2; i++)\n\t  x[i] = xg(i);\n\t  \n      if (dxdxi)\n        for (int i=0; i<2; i++)\n\t  dxdxi[i] = dx(i);\n\n    }\n  else\n    {\n      Point<2> xl(xi[0], xi[1]);\n      Point<3> xg;\n      Mat<3,2> dx;\n      \n      mesh->GetCurvedElements().CalcSurfaceTransformation (xl, sei-1, xg, dx);\n      \n      for (int i=0; i<3; i++)\n\t{\n\t  if (x)\n\t    x[i] = xg(i);\n\t  if (dxdxi)\n\t    {\n\t      dxdxi[2*i] = dx(i,0);\n\t      dxdxi[2*i+1] = dx(i,1);\n\t    }\n\t}\n    }\n}\n\n\n\n\n\nint Ng_GetSegmentIndex (int ei)\n{\n  const Segment & seg = mesh->LineSegment (ei);\n  return seg.edgenr;\n}\n\n\nNG_ELEMENT_TYPE Ng_GetSegment (int ei, int * epi, int * np)\n{\n  const Segment & seg = mesh->LineSegment (ei);\n  \n  epi[0] = seg[0];\n  epi[1] = seg[1];\n\n  if (!seg[2].IsValid())\n    {\n      if (np) *np = 2;\n      return NG_SEGM;\n    }\n  else\n    {\n      epi[2] = seg[2];\n      if (np) *np = 3;\n      return NG_SEGM3;\n    }\n}\n\n\n\n\n\n\nvoid Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out)\n{\n  if ( mesh->GetDimension() == 3 )\n    {\n      in = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainIn();\n      out = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainOut();\n    }\n  else\n    {\n      in = mesh -> LineSegment(selnr) . domin;\n      out = mesh -> LineSegment(selnr) . domout;\n    }\n}\n\n\n#ifdef PARALLEL\n\n// gibt anzahl an distant pnums zurueck\n// * pnums entspricht ARRAY<int[2] >\n[[deprecated(\"Use GetDistantNodeNums(locnum) -> FlatArray instead!\")]]                    \nint NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * distnums )\n{\n  int size = NgPar_GetNDistantNodeNums (nodetype, locnum);\n  locnum++;\n  switch ( nodetype )\n    {\n    case 0:\n      mesh->GetParallelTopology().GetDistantPNums( locnum, distnums ); \n      break;\n    case 1:\n      mesh->GetParallelTopology().GetDistantEdgeNums( locnum, distnums ); \n      break;\n    case 2:\n      mesh->GetParallelTopology().GetDistantFaceNums( locnum, distnums );\n      break;\n    case 3:\n      // mesh->GetParallelTopology().GetDistantElNums( locnum, distnums );\n      break;\n    default:\n      cerr << \"NgPar_GetDistantNodeNums() Unknown nodetype \" << nodetype << endl;\n      size = -1;\n    }\n\n  return size;\n}\n\n[[deprecated(\"Use GetDistantNodeNums(locnum) -> FlatArray instead!\")]]                    \nint NgPar_GetNDistantNodeNums ( int nodetype, int locnum )\n{\n  locnum++;\n  switch ( nodetype )\n    {\n    case 0: return mesh->GetParallelTopology().GetNDistantPNums (locnum);\n    case 1: return mesh->GetParallelTopology().GetNDistantEdgeNums (locnum);\n    case 2: return mesh->GetParallelTopology().GetNDistantFaceNums(locnum );\n    case 3: return 0; \n    }\n  return -1;\n}\n\n[[deprecated(\"Use GetDistantNodeNums(locnum) -> FlatArray instead!\")]]                    \nint NgPar_GetGlobalNodeNum (int nodetype, int locnum)\n{\n  locnum++;\n  switch (nodetype)\n    {\n    case 0: return mesh->GetParallelTopology().GetGlobalPNum (locnum)-1;\n    case 1: return mesh->GetParallelTopology().GetGlobalEdgeNum (locnum)-1;\n    case 2: return mesh->GetParallelTopology().GetGlobalFaceNum (locnum)-1;\n    case 3: return mesh->GetParallelTopology().GetGlobalElNum (locnum)-1;\n    }\n  return -1;\n}\n\n\n#endif\n\nvoid Ng_SetRefinementFlag (int ei, int flag)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      mesh->VolumeElement(ei).SetRefinementFlag (flag != 0);\n      mesh->VolumeElement(ei).SetStrongRefinementFlag (flag >= 10);\n    }\n  else\n    {\n      mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0);\n      mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10);\n    }\n}\n\nvoid Ng_SetSurfaceRefinementFlag (int ei, int flag)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0);\n      mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10);\n    }\n}\n\n\nvoid Ng_Refine (NG_REFINEMENT_TYPE reftype)\n{\n  NgLock meshlock (mesh->MajorMutex(), 1);\n\n  BisectionOptions biopt;\n  biopt.usemarkedelements = 1;\n  biopt.refine_p = 0;\n  biopt.refine_hp = 0;\n  if (reftype == NG_REFINE_P)\n    biopt.refine_p = 1;\n  if (reftype == NG_REFINE_HP)\n    biopt.refine_hp = 1;\n\n  const Refinement & ref = mesh->GetGeometry()->GetRefinement();\n\n  // Refinement * ref;\n  MeshOptimize2d * opt = NULL;\n\n  /*\n    if (geometry2d)\n    ref = new Refinement2d(*geometry2d);\n    else if (stlgeometry)\n    ref = new RefinementSTLGeometry(*stlgeometry);\n    #ifdef OCCGEOMETRY\n    else if (occgeometry)\n    ref = new OCCRefinementSurfaces (*occgeometry);\n    #endif\n    #ifdef ACIS\n    else if (acisgeometry)\n    {\n    ref = new ACISRefinementSurfaces (*acisgeometry);\n    opt = new ACISMeshOptimize2dSurfaces(*acisgeometry);\n    ref->Set2dOptimizer(opt);\n    }\n    #endif\n    else if (geometry && mesh->GetDimension() == 3)\n    {\n    ref = new RefinementSurfaces(*geometry);\n    opt = new MeshOptimize2dSurfaces(*geometry);\n    ref->Set2dOptimizer(opt);\n    }\n    else\n    {\n    ref = new Refinement();\n    }\n  */\n\n  ref.Bisect (*mesh, biopt);\n\n  mesh -> UpdateTopology();\n  mesh -> GetCurvedElements().SetIsHighOrder (false);\n\n  // mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder);\n  // delete ref;\n  delete opt;\n}\n\nvoid Ng_SecondOrder ()\n{\n  const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder(*mesh);\n  /*\n    if (stlgeometry)\n    {\n    RefinementSTLGeometry ref (*stlgeometry);\n    ref.MakeSecondOrder (*mesh);\n    }\n\n    else if (geometry2d)\n    {\n    Refinement2d ref (*geometry2d);\n    ref.MakeSecondOrder (*mesh);\n    }\n\n    else if (geometry && mesh->GetDimension() == 3)\n\n    {\n    RefinementSurfaces ref (*geometry);\n    ref.MakeSecondOrder (*mesh);\n    }\n    else\n    {\n    if (printmessage_importance>0)\n    cout << \"no geom\" << endl;\n    Refinement ref;\n    ref.MakeSecondOrder (*mesh);\n    }\n  */\n  mesh -> UpdateTopology();\n}\n\n/*\n  void Ng_HPRefinement (int levels)\n  {\n  Refinement * ref;\n\n  if (stlgeometry)\n  ref = new RefinementSTLGeometry (*stlgeometry);\n  else if (geometry2d)\n  ref = new Refinement2d (*geometry2d);\n  else\n  ref = new RefinementSurfaces (*geometry);\n\n\n  HPRefinement (*mesh, ref, levels);\n  }\n\n  void Ng_HPRefinement (int levels, double parameter)\n  {\n  Refinement * ref;\n\n  if (stlgeometry)\n  ref = new RefinementSTLGeometry (*stlgeometry);\n  else if (geometry2d)\n  ref = new Refinement2d (*geometry2d);\n  else\n  ref = new RefinementSurfaces (*geometry);\n\n\n  HPRefinement (*mesh, ref, levels, parameter);\n  }\n*/\n\nvoid Ng_HPRefinement (int levels, double parameter, bool setorders,\n                      bool ref_level)\n{\n  NgLock meshlock (mesh->MajorMutex(), true);\n  Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n  HPRefinement (*mesh, &ref, SPLIT_HP, levels, parameter, setorders, ref_level);\n  /*\n    Refinement * ref;\n\n    if (stlgeometry)\n    ref = new RefinementSTLGeometry (*stlgeometry);\n    else if (geometry2d)\n    ref = new Refinement2d (*geometry2d);\n    else\n    ref = new RefinementSurfaces (*geometry);\n\n    HPRefinement (*mesh, ref, levels, parameter, setorders, ref_level);\n  */\n}\n\n\nvoid Ng_HighOrder (int order, bool rational)\n{\n  NgLock meshlock (mesh->MajorMutex(), true);\n  /*\n  mesh -> GetCurvedElements().BuildCurvedElements \n    (&const_cast<Refinement&> (ng_geometry -> GetRefinement()),\n     order, rational);\n  */\n  /*\n  if (!mesh->GetGeometry())\n    throw NgException (\"don't have a geometry for mesh curving\");\n  mesh->BuildCurvedElements \n    (&const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()),\n     order, rational);\n  mesh -> SetNextMajorTimeStamp();\n  */\n  mesh->BuildCurvedElements(order);\n}\n\n\n\n\n\n\n\n\n\n\n\n\nint Ng_ME_GetNVertices (NG_ELEMENT_TYPE et)\n{\n  switch (et)\n    {\n    case NG_SEGM:\n    case NG_SEGM3:\n      return 2;\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return 3;\n\n    case NG_QUAD:\n      return 4;\n\n    case NG_TET:\n    case NG_TET10:\n      return 4;\n\n    case NG_PYRAMID:\n      return 5;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return 6;\n\n    case NG_HEX:\n      return 8;\n\n    default:\n      cerr << \"Ng_ME_GetNVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\nint Ng_ME_GetNEdges (NG_ELEMENT_TYPE et)\n{\n  switch (et)\n    {\n    case NG_SEGM:\n    case NG_SEGM3:\n      return 1;\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return 3;\n\n    case NG_QUAD:\n      return 4;\n\n    case NG_TET:\n    case NG_TET10:\n      return 6;\n\n    case NG_PYRAMID:\n      return 8;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return 9;\n\n    case NG_HEX:\n      return 12;\n\n    default:\n      cerr << \"Ng_ME_GetNEdges, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\nint Ng_ME_GetNFaces (NG_ELEMENT_TYPE et)\n{\n  switch (et)\n    {\n    case NG_SEGM:\n    case NG_SEGM3:\n      return 0;\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return 1;\n\n    case NG_QUAD:\n    case NG_QUAD6:\n      return 1;\n\n    case NG_TET:\n    case NG_TET10:\n      return 4;\n\n    case NG_PYRAMID:\n      return 5;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return 5;\n\n    case NG_HEX:\n      return 6;\n\n    default:\n      cerr << \"Ng_ME_GetNVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\nconst NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et)\n{\n  static double segm_points [][3] = \n    { { 1, 0, 0 },\n      { 0, 0, 0 } };\n\n  static double trig_points [][3] = \n    { { 1, 0, 0 },\n      { 0, 1, 0 },\n      { 0, 0, 0 } };\n\n  static double quad_points [][3] = \n    { { 0, 0, 0 },\n      { 1, 0, 0 },\n      { 1, 1, 0 },\n      { 0, 1, 0 } };\n\n  static double tet_points [][3] = \n    { { 1, 0, 0 },\n      { 0, 1, 0 },\n      { 0, 0, 1 },\n      { 0, 0, 0 } };\n\n  static double pyramid_points [][3] =\n    {\n      { 0, 0, 0 },\n      { 1, 0, 0 },\n      { 1, 1, 0 },\n      { 0, 1, 0 },\n      { 0, 0, 1-1e-7 },\n    };    \n  \n  static double prism_points[][3] = \n    {\n      { 1, 0, 0 },\n      { 0, 1, 0 },\n      { 0, 0, 0 },\n      { 1, 0, 1 },\n      { 0, 1, 1 },\n      { 0, 0, 1 }\n    };\n\n  switch (et)\n    {\n    case NG_SEGM:\n    case NG_SEGM3:\n      return segm_points;\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return trig_points;\n\n    case NG_QUAD:\n    case NG_QUAD6:\n      return quad_points;\n\n    case NG_TET:\n    case NG_TET10:\n      return tet_points;\n\n    case NG_PYRAMID:\n      return pyramid_points;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return prism_points;\n\n    case NG_HEX:\n    default:\n      cerr << \"Ng_ME_GetVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\n\nconst NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et)\n{\n  static int segm_edges[1][2] =\n    { { 1, 2 }};\n\n  static int trig_edges[3][2] =\n    { { 3, 1 },\n      { 3, 2 },\n      { 1, 2 }};\n\n  static int quad_edges[4][2] =\n    { { 1, 2 },\n      { 4, 3 },\n      { 1, 4 },\n      { 2, 3 }};\n\n\n  static int tet_edges[6][2] =\n    { { 4, 1 },\n      { 4, 2 },\n      { 4, 3 }, \n      { 1, 2 },\n      { 1, 3 },\n      { 2, 3 }};\n\n  static int prism_edges[9][2] =\n    { { 3, 1 },\n      { 1, 2 },\n      { 3, 2 },\n      { 6, 4 },\n      { 4, 5 },\n      { 6, 5 },\n      { 3, 6 },\n      { 1, 4 },\n      { 2, 5 }};\n\n  static int pyramid_edges[8][2] =\n    { { 1, 2 },\n      { 2, 3 },\n      { 1, 4 },\n      { 4, 3 },\n      { 1, 5 },\n      { 2, 5 },\n      { 3, 5 },\n      { 4, 5 }};\n\n\n\n  switch (et)\n    {\n    case NG_SEGM:\n    case NG_SEGM3:\n      return segm_edges;\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return trig_edges;\n\n    case NG_QUAD:\n    case NG_QUAD6:\n      return quad_edges;\n\n    case NG_TET:\n    case NG_TET10:\n      return tet_edges;\n\n    case NG_PYRAMID:\n      return pyramid_edges;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return prism_edges;\n\n    case NG_HEX:\n    default:\n      cerr << \"Ng_ME_GetEdges, illegal element type \" << et << endl;\n    }\n  return 0;  \n}\n\n\nconst NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et)\n{\n  static int tet_faces[4][4] =\n    { { 4, 2, 3, 0 },\n      { 4, 1, 3, 0 },\n      { 4, 1, 2, 0 },\n      { 1, 2, 3, 0 } };\n  \n  static int prism_faces[5][4] =\n    {\n      { 1, 2, 3, 0 },\n      { 4, 5, 6, 0 },\n      { 3, 1, 4, 6 },\n      { 1, 2, 5, 4 },\n      { 2, 3, 6, 5 } \n    };\n  \n  static int pyramid_faces[5][4] =\n    {\n      { 1, 2, 5, 0 },\n      { 2, 3, 5, 0 },\n      { 3, 4, 5, 0 },\n      { 4, 1, 5, 0 },\n      { 1, 2, 3, 4 } \n    };\n  \n  static int trig_faces[1][4] = \n    {\n      { 1, 2, 3, 0 },\n    };\n\n  switch (et)\n    {\n    case NG_TET:\n    case NG_TET10:\n      return tet_faces;\n\n    case NG_PRISM:\n    case NG_PRISM12:\n      return prism_faces;\n\n    case NG_PYRAMID:\n      return pyramid_faces;\n\n\n    case NG_SEGM:\n    case NG_SEGM3:\n\n    case NG_TRIG:\n    case NG_TRIG6:\n      return trig_faces;\n    case NG_QUAD:\n\n\n    case NG_HEX:\n\n    default:\n      cerr << \"Ng_ME_GetFaces, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\n\nvoid Ng_UpdateTopology()\n{\n  if (mesh)\n    mesh -> UpdateTopology();\n}\n\nNg_Mesh Ng_SelectMesh (Ng_Mesh newmesh)\n{\n  Mesh * hmesh = mesh.get();\n  mesh.reset((Mesh*)newmesh);\n  return hmesh;\n}\n\n\n\nint Ng_GetNEdges()\n{\n  return mesh->GetTopology().GetNEdges();\n}\nint Ng_GetNFaces()\n{\n  return mesh->GetTopology().GetNFaces();\n}\n\n\n\nint Ng_GetElement_Edges (int elnr, int * edges, int * orient)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  if (mesh->GetDimension() == 3)\n    return topology.GetElementEdges (elnr, edges, orient);\n  else\n    return topology.GetSurfaceElementEdges (elnr, edges, orient);\n}\n\nint Ng_GetElement_Faces (int elnr, int * faces, int * orient)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  if (mesh->GetDimension() == 3)\n    return topology.GetElementFaces (elnr, faces, orient);\n  else\n    {\n      faces[0] = elnr;\n      if (orient) orient[0] = 0;\n      return 1;\n    }\n}\n\nint Ng_GetSurfaceElement_Edges (int elnr, int * edges, int * orient)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  if (mesh->GetDimension() == 3)\n    return topology.GetSurfaceElementEdges (elnr, edges, orient);\n  else\n    {\n      if (orient)\n\ttopology.GetSegmentEdge(elnr, edges[0], orient[0]);\n      else\n\tedges[0] = topology.GetSegmentEdge(elnr);\n    }\n  return 1;\n  /*\n    int i, ned;\n    const MeshTopology & topology = mesh->GetTopology();\n    NgArray<int> ia;\n    topology.GetSurfaceElementEdges (elnr, ia);\n    ned = ia.Size();\n    for (i = 1; i <= ned; i++)\n    edges[i-1] = ia.Get(i);\n\n    if (orient)\n    {\n    topology.GetSurfaceElementEdgeOrientations (elnr, ia);\n    for (i = 1; i <= ned; i++)\n    orient[i-1] = ia.Get(i);\n    }\n    return ned;\n  */\n}\n\nint Ng_GetSurfaceElement_Face (int selnr, int * orient)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      SurfaceElementIndex sei = selnr-1;\n      const MeshTopology & topology = mesh->GetTopology();\n      if (orient)\n\t*orient = topology.GetSurfaceElementFaceOrientation (selnr);\n      return topology.GetFace(sei);\n    }\n  return -1;\n}\n\nint Ng_GetFace_Vertices (int fnr, int * vert)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  NgArrayMem<int,4> ia;\n  topology.GetFaceVertices (fnr, ia);\n  for (int i = 0; i < ia.Size(); i++)\n    vert[i] = ia[i];\n  //  cout << \"face verts = \" << ia << endl;\n  return ia.Size();\n}\n\n\nint Ng_GetFace_Edges (int fnr, int * edge)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  NgArrayMem<int,4> ia;\n  topology.GetFaceEdges (fnr, ia);\n  for (int i = 0; i < ia.Size(); i++)\n    edge[i] = ia[i];\n  return ia.Size();\n}\n\nvoid Ng_GetEdge_Vertices (int ednr, int * vert)\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  // topology.GetEdgeVertices (ednr, vert[0], vert[1]);\n  // tie(vert[0], vert[1]) = topology.GetEdgeVertices(ednr-1);\n  auto [v1,v2] = topology.GetEdgeVertices(ednr-1);\n  vert[0] = v1-IndexBASE<PointIndex>()+1;\n  vert[1] = v2-IndexBASE<PointIndex>()+1;\n}\n\n\nint Ng_GetNVertexElements (int vnr)\n{\n  switch (mesh->GetDimension())\n    {\n    case 3:\n      return mesh->GetTopology().GetVertexElements(vnr).Size();\n    case 2:\n      return mesh->GetTopology().GetVertexSurfaceElements(vnr).Size();\n    case 1:\n      return mesh->GetTopology().GetVertexSegments(vnr).Size();\n      /*\n      {\n        int cnt = 0;\n        for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++)\n          if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) cnt++;\n        return cnt;\n      }\n      */\n    default:\n      cerr << \"error: mesh->GetDimension() gives \" \n           << mesh->GetDimension() << endl;\n      return 0;\n    }\n}\n\nvoid Ng_GetVertexElements (int vnr, int * els)\n{\n  switch (mesh->GetDimension())\n    {\n    case 3:\n      {\n        auto ia = mesh->GetTopology().GetVertexElements(vnr);\n        for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1;\n        break;\n      }\n    case 2:\n      {\n        auto ia = mesh->GetTopology().GetVertexSurfaceElements(vnr);\n        for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1;\n        break;\n      }\n    case 1:\n      {\n        auto ia = mesh->GetTopology().GetVertexSegments(vnr);\n        for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1;\n        break;\n        /*\n        int cnt = 0;\n        for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++)\n          if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) \n            els[cnt++] = i+1;\n        break;\n        */\n      }\n    }\n}\n\n\nint Ng_GetElementOrder (int enr)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->VolumeElement(enr).GetOrder();\n  else\n    return mesh->SurfaceElement(enr).GetOrder();\n}\n\nvoid Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz)\n{\n  if (mesh->GetDimension() == 3)\n    mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz);\n  else\n    mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz);\n}\n\nvoid Ng_SetElementOrder (int enr, int order)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->VolumeElement(enr).SetOrder(order);\n  else\n    return mesh->SurfaceElement(enr).SetOrder(order);\n}\n\nvoid Ng_SetElementOrders (int enr, int ox, int oy, int oz)\n{\n  if (mesh->GetDimension() == 3)\n    mesh->VolumeElement(enr).SetOrder(ox, oy, oz);\n  else\n    mesh->SurfaceElement(enr).SetOrder(ox, oy);\n}\n\n\nint Ng_GetSurfaceElementOrder (int enr)\n{\n  return mesh->SurfaceElement(enr).GetOrder();\n}\n\n//HERBERT: falsche Anzahl von Argumenten\n//void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz)\nvoid Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy)\n{\n  int d; \n  mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d);\n}\n\nvoid Ng_SetSurfaceElementOrder (int enr, int order)\n{\n  return mesh->SurfaceElement(enr).SetOrder(order);\n}\n\nvoid Ng_SetSurfaceElementOrders (int enr, int ox, int oy)\n{\n  mesh->SurfaceElement(enr).SetOrder(ox, oy);\n}\n\n\nint Ng_GetNLevels ()\n{\n  if (!mesh) return 0;\n  return max(size_t(1), mesh -> level_nv.Size());  \n  // return (mesh) ? mesh->mglevels : 0;\n}\n\n\nvoid Ng_GetParentNodes (int ni, int * parents)\n{\n  if (ni <= mesh->mlbetweennodes.Size())\n    {\n      parents[0] = mesh->mlbetweennodes[ni].I1();\n      parents[1] = mesh->mlbetweennodes[ni].I2();\n    }\n  else\n    parents[0] = parents[1] = 0;\n}\n\n\nint Ng_GetParentElement (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      if (ei <= mesh->mlparentelement.Size())\n\treturn mesh->mlparentelement[ei-1]+1;\n    }\n  else\n    {\n      if (ei <= mesh->mlparentsurfaceelement.Size())\n\treturn mesh->mlparentsurfaceelement[ei-1]+1;\n    }\n  return 0;\n}\n\n\nint Ng_GetParentSElement (int ei)\n{\n  if (mesh->GetDimension() == 3)\n    {\n      if (ei <= mesh->mlparentsurfaceelement.Size())\n\treturn mesh->mlparentsurfaceelement[ei-1]+1;\n    }\n  else\n    {\n      return 0;\n    }\n  return 0;\n}\n\n\n\n\n\nint Ng_GetClusterRepVertex (int pi)\n{\n  return mesh->GetClusters().GetVertexRepresentant(pi);\n}\n\nint Ng_GetClusterRepEdge (int pi)\n{\n  return mesh->GetClusters().GetEdgeRepresentant(pi);\n}\n\nint Ng_GetClusterRepFace (int pi)\n{\n  return mesh->GetClusters().GetFaceRepresentant(pi);\n}\n\nint Ng_GetClusterRepElement (int pi)\n{\n  return mesh->GetClusters().GetElementRepresentant(pi);\n}\n\n\n\n\n\t\t\nint Ng_GetNPeriodicVertices (int idnr)\n{\n  NgArray<INDEX_2> apairs;\n  mesh->GetIdentifications().GetPairs (idnr, apairs);\n  return apairs.Size();\n}\n\n\n// pairs should be an integer array of 2*npairs\nvoid Ng_GetPeriodicVertices (int idnr, int * pairs)\n{\n  NgArray<INDEX_2> apairs;\n  mesh->GetIdentifications().GetPairs (idnr, apairs);\n  for (int i = 0; i < apairs.Size(); i++)\n    {\n      pairs[2*i] = apairs[i].I1();\n      pairs[2*i+1] = apairs[i].I2();\n    }\n      \n}\n\n\n\nint Ng_GetNPeriodicEdges (int idnr)\n{\n  idmap_type map;\n  //const MeshTopology & top = mesh->GetTopology();\n  int nse = mesh->GetNSeg();\n\n  int cnt = 0;\n  //  for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++)\n  {\n    mesh->GetIdentifications().GetMap(idnr, map);\n    //(*testout) << \"ident-map \" << id << \":\" << endl << map << endl;\n\n    for (SegmentIndex si = 0; si < nse; si++)\n      {\n\tPointIndex other1 = PointIndex (map[(*mesh)[si][0]]);\n\tPointIndex other2 = PointIndex (map[(*mesh)[si][1]]);\n\t//  (*testout) << \"seg = \" << (*mesh)[si] << \"; other = \" \n\t//     << other1 << \"-\" << other2 << endl;\n\tif (other1 && other2 && mesh->IsSegment (other1, other2))\n\t  {\n\t    cnt++;\n\t  }\n      }\n  }\n  return cnt;\n}\n\nvoid Ng_GetPeriodicEdges (int idnr, int * pairs)\n{\n  idmap_type map;\n  const MeshTopology & top = mesh->GetTopology();\n  int nse = mesh->GetNSeg();\n\n  int cnt = 0;\n  //  for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++)\n  {\n    mesh->GetIdentifications().GetMap(idnr, map);\n      \n    //(*testout) << \"map = \" << map << endl;\n\n    for (SegmentIndex si = 0; si < nse; si++)\n      {\n\tPointIndex other1 = PointIndex (map[(*mesh)[si][0]]);\n\tPointIndex other2 = PointIndex (map[(*mesh)[si][1]]);\n\tif (other1 && other2 && mesh->IsSegment (other1, other2))\n\t  {\n\t    SegmentIndex otherseg = mesh->SegmentNr (other1, other2);\n\t    // pairs[cnt++] = top.GetSegmentEdge (si+1);\n\t    // pairs[cnt++] = top.GetSegmentEdge (otherseg+1);\n\t    pairs[cnt++] = top.GetEdge (si)+1;\n\t    pairs[cnt++] = top.GetEdge (otherseg)+1;\n\t  }\n      }\n  }\n}\n\n\n\nvoid Ng_PushStatus (const std::string& str)\n{\n  PushStatus (str);\n}\n\nvoid Ng_PopStatus ()\n{\n  PopStatus ();\n}\n\nvoid Ng_SetThreadPercentage (double percent)\n{\n  SetThreadPercent (percent);\n}\n\nvoid Ng_GetStatus (std::string & str, double & percent)\n{\n  /*\n  MyStr s;\n  GetStatus(s,percent);\n  *str = new char[s.Length()+1];\n  strcpy(*str,s.c_str());\n  */\n  GetStatus (str, percent);\n}\n\n\nvoid Ng_SetTerminate(void)\n{\n  multithread.terminate = 1;\n}\nvoid Ng_UnSetTerminate(void)\n{\n  multithread.terminate = 0;\n}\n\nint Ng_ShouldTerminate(void)\n{\n  return multithread.terminate;\n}\n\nvoid Ng_SetRunning(int flag)\n{\n  multithread.running = flag;\n}\nint Ng_IsRunning()\n{\n  return multithread.running;\n}\n\n///// Added by Roman Stainko ....\nint Ng_GetVertex_Elements( int vnr, int* elems )\n{\n  const MeshTopology& topology = mesh->GetTopology();\n  // ArrayMem<ElementIndex,4> indexArray;\n  // topology.GetVertexElements( vnr, indexArray );\n  auto indexArray = topology.GetVertexElements( vnr );\n  \n  for( int i=0; i<indexArray.Size(); i++ )\n    elems[i] = indexArray[i]+1;\n  \n  return indexArray.Size();\n}\n\n///// Added by Roman Stainko ....\nint Ng_GetVertex_SurfaceElements( int vnr_, int* elems )\n{\n  PointIndex vnr = vnr_ + IndexBASE<PointIndex>()-1;\n  \n  switch (mesh->GetDimension())\n    {\n    case 3:\n      {\n        const MeshTopology& topology = mesh->GetTopology();\n        // ArrayMem<SurfaceElementIndex,4> indexArray;\n        // topology.GetVertexSurfaceElements( vnr, indexArray );\n        auto indexArray = topology.GetVertexSurfaceElements( vnr );\n        \n        for( int i=0; i<indexArray.Size(); i++ )\n          elems[i] = indexArray[i]+1;\n        \n        return indexArray.Size();\n      }\n    case 2:\n      {\n        int cnt = 0;\n        for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++)\n          if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) \n            elems[cnt++] = i+1;\n        return cnt;\n      }\n    case 1:\n      {\n        int cnt = 0;\n        for (int i = 0; i < mesh->pointelements.Size(); i++)\n          if (mesh->pointelements[i].pnum == vnr)\n            elems[cnt++] = i+1;\n        return cnt;\n      }\n    }\n  return 0;\n}\n\n///// Added by Roman Stainko ....\nint Ng_GetVertex_NElements( int vnr )\n{\n  const MeshTopology& topology = mesh->GetTopology();\n  /*\n  ArrayMem<ElementIndex,4> indexArray;\n  topology.GetVertexElements( vnr, indexArray );\n  return indexArray.Size();\n  */\n  return topology.GetVertexElements(vnr).Size();\n}\n\n///// Added by Roman Stainko ....\nint Ng_GetVertex_NSurfaceElements( int vnr_ )\n{\n  PointIndex vnr = vnr_ + IndexBASE<PointIndex>()-1;\n  switch (mesh->GetDimension())\n    {\n    case 3:\n      {\n        const MeshTopology& topology = mesh->GetTopology();\n        // ArrayMem<SurfaceElementIndex,4> indexArray;\n        // topology.GetVertexSurfaceElements( vnr, indexArray );\n        auto indexArray = topology.GetVertexSurfaceElements( vnr );\n        return indexArray.Size();\n      }\n    case 2:\n      {\n        int cnt = 0;\n        for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++)\n          if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) cnt++;\n        return cnt;\n      }\n    }\n  return 0;\n}\n\n\n\n#ifdef SOCKETS\nint Ng_SocketClientOpen( const int port, const char * host )\n{\n  try\n    {\n      if(host)\n\tclientsocket.Reset(new ClientSocket(port,host));\n      else\n\tclientsocket.Reset(new ClientSocket(port));\n    }\n  catch( SocketException e)\n    {\n      cerr << e.Description() << endl;\n      return 0;\n    }\n  return 1;\n}\n \nvoid Ng_SocketClientWrite( const char * write, char** reply)\n{\n  string output = write;\n  (*clientsocket) << output;\n  string sreply;\n  (*clientsocket) >> sreply;\n  *reply = new char[sreply.size()+1];\n  strcpy(*reply,sreply.c_str());\n}\n\n\nvoid Ng_SocketClientClose ( void )\n{\n  clientsocket.Reset(NULL);\n}\n\n\nvoid Ng_SocketClientGetServerHost ( const int number, char ** host )\n{\n  *host = new char[servers[number]->host.size()+1];\n  strcpy(*host,servers[number]->host.c_str());\n}\n\nvoid Ng_SocketClientGetServerPort ( const int number, int * port )\n{\n  *port = servers[number]->port;\n}\n\nvoid Ng_SocketClientGetServerClientID ( const int number, int * id )\n{\n  *id = servers[number]->clientid;\n}\n\n#endif // SOCKETS\n\n\n\n/*\n#ifdef PARALLEL\nvoid Ng_SetElementPartition ( const int elnr, const int part )\n{\n  mesh->VolumeElement(elnr+1).SetPartition(part);\n\n}\nint Ng_GetElementPartition ( const int elnr )\n{\n  return mesh->VolumeElement(elnr+1).GetPartition();\n}\n#endif\n*/\n\n\nvoid Ng_InitPointCurve(double red, double green, double blue)\n{\n  mesh->InitPointCurve(red, green, blue);\n}\n\nvoid Ng_AddPointCurvePoint(const double * point)\n{\n  Point3d pt;\n  pt.X() = point[0];\n  pt.Y() = point[1];\n  pt.Z() = point[2];\n  mesh->AddPointCurvePoint(pt);\n}\n\n\nvoid Ng_SaveMesh ( const char * meshfile )\n{\n  mesh -> Save(string(meshfile));\n}\n\n\nint Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss, int * qualityloss_size )\n{\n  BisectionOptions biopt;\n  biopt.outfilename = NULL; // \"ngfepp.vol\";\n  biopt.femcode = \"fepp\";\n  biopt.refinementfilename = refinementfile;\n  \n  Refinement * ref = const_cast<Refinement*> (&mesh->GetGeometry()->GetRefinement());\n  MeshOptimize2d * opt = NULL;\n  /*\n    if (stlgeometry)\n    ref = new RefinementSTLGeometry(*stlgeometry);\n    #ifdef OCCGEOMETRY\n    else if (occgeometry)\n    ref = new OCCRefinementSurfaces (*occgeometry);\n    #endif\n    #ifdef ACIS\n    else if (acisgeometry)\n    {\n    ref = new ACISRefinementSurfaces(*acisgeometry);\n    opt = new ACISMeshOptimize2dSurfaces(*acisgeometry);\n    ref->Set2dOptimizer(opt);\n    }\n    #endif\n    else\n    {\n    ref = new RefinementSurfaces(*geometry);\n    opt = new MeshOptimize2dSurfaces(*geometry);\n    ref->Set2dOptimizer(opt);\n    }\n  */\n#ifdef ACIS\n  if (acisgeometry)\n    {\n      // ref = new ACISRefinementSurfaces(*acisgeometry);\n      opt = new ACISMeshOptimize2dSurfaces(*acisgeometry);\n      ref->Set2dOptimizer(opt);\n    }\n  else\n#endif\n    {\n      // ref = new RefinementSurfaces(*geometry);\n      /*\n        // joachim, oct 2014\n      CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n      if (geometry)\n\t{\n\t  opt = new MeshOptimize2dSurfaces(*geometry);\n\t  ref->Set2dOptimizer(opt);\n\t}\n      */\n    }\n\n  if(!mesh->LocalHFunctionGenerated())\n    mesh->CalcLocalH(mparam.grading);\n  \n  mesh->LocalHFunction().SetGrading (mparam.grading);\n\n  NgArray<double> * qualityloss_arr = NULL;\n  if(qualityloss != NULL)\n    qualityloss_arr = new NgArray<double>;\n\n  ref -> Bisect (*mesh, biopt, qualityloss_arr);\n\n  int retval = 0;\n\n  if(qualityloss != NULL)\n    {\n      *qualityloss = new double[qualityloss_arr->Size()+1];\n\n      for(int i = 0; i<qualityloss_arr->Size(); i++)\n\t(*qualityloss)[i+1] = (*qualityloss_arr)[i];\n\n      retval = qualityloss_arr->Size();\n\n      delete qualityloss_arr;\n    }\n\n  mesh -> UpdateTopology();\n  mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder);\n  \n  multithread.running = 0;\n  delete ref;\n  delete opt;\n\n  return retval;\n}\n\nvoid Ng_Bisect ( const char * refinementfile )\n{\n  Ng_Bisect_WithInfo( refinementfile, NULL, NULL );\n}\n\n\n\n\n\n/*\n  number of nodes of type nt\n  nt = 0 is Vertex\n  nt = 1 is Edge\n  nt = 2 is Face\n  nt = 3 is Cell\n*/\nint Ng_GetNNodes (int nt)\n{\n  switch (nt)\n    {\n    case 0: return mesh -> GetNV();\n    case 1: return mesh->GetTopology().GetNEdges();\n    case 2: return mesh->GetTopology().GetNFaces();\n    case 3: return mesh -> GetNE();\n    }\n  return -1;\n}\n\n\nint Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes)\n{\n  switch (nt)\n    {\n    case 3:  // The closure of a cell\n      {\n        int cnt = 0;\n        if (nodeset & 1)  // Vertices\n          {\n            const Element & el = (*mesh)[ElementIndex(nodenr)];\n            for (int i = 0; i < el.GetNP(); i++)\n              { \n                nodes[cnt++] = 0;\n                nodes[cnt++] = el[i] - IndexBASE<PointIndex>();\n              }\n          }\n\n        if (nodeset & 2)  // Edges\n          {\n            auto edges = mesh->GetTopology().GetEdges (ElementIndex(nodenr));\n            for (int i = 0; i < edges.Size(); i++)\n              {\n                nodes[cnt++] = 1;\n                nodes[cnt++] = edges[i]-1;\n              }\n          }\n\n        if (nodeset & 4)  // Faces\n          {\n            int faces[12];\n            int nfa;\n            nfa = mesh->GetTopology().GetElementFaces (nodenr+1, faces, 0);\n            for (int i = 0; i < nfa; i++)\n              {\n                nodes[cnt++] = 2;\n                nodes[cnt++] = faces[i]-1;\n              }\n          }\n\n        if (nodeset & 8)  // Cell\n          {\n            nodes[cnt++] = 3;\n            nodes[cnt++] = nodenr;\n          }\n\n        return cnt/2;\n      }\n    default:\n      {\n        cerr << \"GetClosureNodes not implemented for Nodetype \" << nt << endl;\n      }\n    }\n  return 0;\n}\n\n\n\nint Ng_GetNElements (int dim)\n{\n  switch (dim)\n    {\n    case 0: return mesh -> GetNV();\n    case 1: return mesh -> GetNSeg();\n    case 2: return mesh -> GetNSE();\n    case 3: return mesh -> GetNE();\n    }\n  return -1;\n}\n\n\n\n/*\n  closure nodes of element\n  nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc\n  E.g., nodeset = 6 includes edge and face nodes\n  nodes is pair of integers (nodetype, nodenr) \n  return value is number of nodes\n*/\nint Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes)\n{\n  switch (dim)\n    {\n    case 3:  // The closure of a volume element = CELL\n      {\n        return Ng_GetClosureNodes (3, elementnr, nodeset, nodes);\n      }\n    case 2:\n      {\n        int cnt = 0;\n        if (nodeset & 1)  // Vertices\n          {\n            const Element2d & el = (*mesh)[SurfaceElementIndex(elementnr)];\n            for (int i = 0; i < el.GetNP(); i++)\n              { \n                nodes[cnt++] = 0;\n                nodes[cnt++] = el[i] - IndexBASE<PointIndex>();\n              }\n          }\n\n        if (nodeset & 2)  // Edges\n          {\n            int edges[12];\n            int ned;\n            ned = mesh->GetTopology().GetSurfaceElementEdges (elementnr+1, edges, 0);\n            for (int i = 0; i < ned; i++)\n              {\n                nodes[cnt++] = 1;\n                nodes[cnt++] = edges[i]-1;\n              }\n          }\n\n        if (nodeset & 4)  // Faces\n          {\n            int face = mesh->GetTopology().GetFace (SurfaceElementIndex(elementnr))+1;\n            nodes[cnt++] = 2;\n            nodes[cnt++] = face-1;\n          }\n\n        return cnt/2;\n      }\n    default:\n      {\n        cerr << \"GetClosureNodes not implemented for Element of dimension \" << dim << endl;\n      }\n    }\n  return 0;\n}\n\n\n\nvoid Ng_GetArgs (int & argc, char ** &argv)\n{\n  argc = h_argc;\n  argv = h_argv;\n}\n\n\n\nvoid Ng_TclCmd(string cmd)\n{\n  lock_guard<mutex> guard(tcl_todo_mutex);\n  *(multithread.tcl_todo) += cmd;\n}\n"
  },
  {
    "path": "libsrc/interface/nginterface_v2.cpp",
    "content": "#include <meshing.hpp>\n\n#ifdef SOCKETS\n#include \"../sockets/sockets.hpp\"\n#endif\n\n#include \"nginterface.h\"\n#include \"nginterface_v2.hpp\"\n// #include <visual.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n  extern shared_ptr<Mesh> mesh;\n}\n\n\nnamespace netgen\n{\n#define NGX_INLINE\n#include \"nginterface_v2_impl.hpp\"\n\n  shared_ptr<Mesh> Ngx_Mesh :: SelectMesh () const\n  {\n    shared_ptr<Mesh> hmesh = netgen::mesh;\n\n    netgen::mesh = mesh;\n    SetGlobalMesh (mesh);\n\n    return hmesh;\n  }\n  \n  Ngx_Mesh :: Ngx_Mesh (shared_ptr<Mesh> amesh)\n  { mesh = amesh ? amesh : netgen::mesh; }\n  Ngx_Mesh :: Ngx_Mesh (string filename, NgMPI_Comm acomm)\n  { LoadMesh(filename, acomm); }\n  \n  Ngx_Mesh * LoadMesh (const string & filename, NgMPI_Comm comm)\n  {\n    netgen::mesh.reset();\n    Ng_LoadMesh (filename.c_str(), comm);\n    return new Ngx_Mesh (netgen::mesh);\n  }\n\n  void Ngx_Mesh :: LoadMesh (const string & filename, NgMPI_Comm comm)\n  {\n    netgen::mesh.reset();\n    Ng_LoadMesh (filename.c_str(), comm);\n    // mesh = move(netgen::mesh);\n    mesh = netgen::mesh;\n  }\n\n  void Ngx_Mesh :: LoadMesh (istream & ist, NgMPI_Comm comm)\n  {\n    netgen::mesh = make_shared<Mesh>();\n    netgen::mesh->SetCommunicator(comm);\n    netgen::mesh -> Load (ist);\n    // mesh = move(netgen::mesh);\n    mesh = netgen::mesh;\n    SetGlobalMesh (mesh);\n  }\n\n  const NgMPI_Comm & Ngx_Mesh :: GetCommunicator() const\n  {\n    // return Valid() ? mesh->GetCommunicator() : NgMPI_Comm{};\n    if (!Valid()) throw Exception(\"Ngx_mesh::GetCommunicator: don't have a valid mesh\");\n    return mesh->GetCommunicator();\n  }\n\n  void Ngx_Mesh :: SaveMesh (ostream & ost) const\n  {\n    mesh -> Save (ost);\n  }\n\n  void Ngx_Mesh :: DoArchive (Archive & archive)\n  {\n#ifdef PARALLEL\n    if (archive.Input()) {\n      mesh = make_shared<Mesh>();\n      mesh->SetCommunicator(GetCommunicator());\n    }\n#endif\n    mesh->DoArchive(archive);\n    if (archive.Input())\n      {\n        netgen::mesh = mesh;\n        SetGlobalMesh (mesh);\n      }\n    /*\n    if (archive.Output())\n      {\n        stringstream str;\n        SaveMesh (str);\n        string st = str.str();\n        archive & st;\n      }\n    else\n      {\n        string st;\n        archive & st;\n        stringstream str(st);\n        LoadMesh (str);\n      }\n    */\n  }\n\n  void Ngx_Mesh :: UpdateTopology ()\n  {\n    if (mesh)\n      mesh -> UpdateTopology();\n  }\n\n\n  /*\n  Ngx_Mesh :: Ngx_Mesh (Mesh * amesh)\n    : mesh(amesh)\n  { ; }\n  */\n\n  Ngx_Mesh :: ~Ngx_Mesh ()\n  { \n    // causes crashes when global variable netgen::mesh is destructed\n    // before visualization data \n    \n    if (mesh == netgen::mesh)\n      netgen::mesh = nullptr;\n  }\n\n  int Ngx_Mesh :: GetDimension() const\n  {\n    return mesh -> GetDimension();\n  }\n\n  int Ngx_Mesh :: GetNLevels() const\n  {\n    return max(size_t(1), mesh -> level_nv.Size());\n  }\n\n  size_t Ngx_Mesh :: GetNVLevel(int level) const\n  {\n    if (level >= mesh->level_nv.Size())\n      return mesh->GetNV();\n    else\n      return mesh->level_nv[level];\n  }\n  \n  int Ngx_Mesh :: GetNElements (int dim) const\n  {\n    switch (dim)\n      {\n      case 0: return mesh -> pointelements.Size();\n      case 1: return mesh -> GetNSeg();\n      case 2: return mesh -> GetNSE();\n      case 3: return mesh -> GetNE();\n      }\n    return -1;\n  }\n  \n  int Ngx_Mesh :: GetNNodes (int nt) const\n  {\n    switch (nt)\n      {\n      case 0: return mesh -> GetNV();\n      case 1: return mesh->GetTopology().GetNEdges();\n      case 2: return mesh->GetTopology().GetNFaces();\n      case 3: return mesh -> GetNE();\n      }\n    return -1;\n  }\n\n  /*\n  Ng_Point Ngx_Mesh :: GetPoint (int nr) const\n  {\n    return Ng_Point (&mesh->Point(nr + PointIndex::BASE)(0));\n  }\n  */\n\n  /*\n  template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (int nr) const\n  {\n    const Element0d & el = mesh->pointelements[nr];\n    \n    Ng_Element ret;\n    ret.type = NG_PNT;\n    ret.index = el.index;\n\n    ret.points.num = 1;\n    ret.points.ptr = (int*)&el.pnum;\n\n    ret.vertices.num = 1;\n    ret.vertices.ptr = (int*)&el.pnum;\n\n    ret.edges.num = 0;\n    ret.edges.ptr = NULL;\n\n    ret.faces.num = 0;\n    ret.faces.ptr = NULL;\n\n    return ret;\n  }\n  */\n  /*\n  template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (int nr) const\n  {\n    const Segment & el = mesh->LineSegment (SegmentIndex(nr));\n\n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n\n    ret.points.num = el.GetNP();\n    ret.points.ptr = (int*)&(el[0]);\n\n    ret.vertices.num = 2;\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = 1;\n    ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr);\n\n    ret.faces.num = 0;\n    ret.faces.ptr = NULL;\n\n    return ret;\n  }\n\n  template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (int nr) const\n  {\n    const Element2d & el = mesh->SurfaceElement (SurfaceElementIndex (nr));\n  \n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n    ret.points.num = el.GetNP();\n    ret.points.ptr  = (int*)&el[0];\n\n    ret.vertices.num = el.GetNV();\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n    ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr);\n\n    ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n    ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr);\n\n    return ret;\n  }\n\n  template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (int nr) const\n  {\n    const Element & el = mesh->VolumeElement (ElementIndex (nr));\n  \n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n    ret.points.num = el.GetNP();\n    ret.points.ptr = (int*)&el[0];\n\n    ret.vertices.num = el.GetNV();\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n    ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr);\n\n    ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n    ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr);\n\n    return ret;\n  }\n  */\n\n  \n  /*\n  template <>\n  DLL_HEADER int Ngx_Mesh :: GetElementIndex<0> (int nr) const\n  {\n    return 0;\n  }\n\n  template <>\n  DLL_HEADER int Ngx_Mesh :: GetElementIndex<1> (int nr) const\n  {\n    return (*mesh)[SegmentIndex(nr)].si;\n  }\n  \n  template <>\n  DLL_HEADER int Ngx_Mesh :: GetElementIndex<2> (int nr) const\n  {\n    int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); \n    return mesh->GetFaceDescriptor(ind).BCProperty();\n  }\n  \n  template <>\n  DLL_HEADER int Ngx_Mesh :: GetElementIndex<3> (int nr) const\n  {\n    return (*mesh)[ElementIndex(nr)].GetIndex();\n  }\n  */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  /*\n  DLL_HEADER Ng_Point Ng_GetPoint (int nr)\n  {\n    Ng_Point ret;\n    ret.pt = &mesh->Point(nr + PointIndex::BASE)(0);\n    return ret;\n  }\n\n\n  template <>\n  DLL_HEADER int Ng_GetElementIndex<1> (int nr)\n  {\n    return (*mesh)[SegmentIndex(nr)].si;\n  }\n  \n  template <>\n  DLL_HEADER int Ng_GetElementIndex<2> (int nr)\n  {\n    int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); \n    return mesh->GetFaceDescriptor(ind).BCProperty();\n  }\n  \n  template <>\n  DLL_HEADER int Ng_GetElementIndex<3> (int nr)\n  {\n    return (*mesh)[ElementIndex(nr)].GetIndex();\n  }\n\n  template <> int DLL_HEADER Ng_GetNElements<0> ()\n  {\n    return 0;\n  }\n\n  template <> int DLL_HEADER Ng_GetNElements<1> ()\n  {\n    return mesh->GetNSeg();\n  }\n\n  template <> DLL_HEADER int Ng_GetNElements<2> ()\n  {\n    return mesh->GetNSE();\n  }\n\n  template <> DLL_HEADER int Ng_GetNElements<3> ()\n  {\n    return mesh->GetNE();\n  }\n\n  template <> DLL_HEADER Ng_Element Ng_GetElement<0> (int nr)\n  {\n    cout << \"Netgen does not support 0-D elements\" << endl;\n\tNg_Element ret;\n\treturn ret;\n  }\n\n  template <> DLL_HEADER Ng_Element Ng_GetElement<1> (int nr)\n  {\n    const Segment & el = mesh->LineSegment (SegmentIndex(nr));\n\n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n\n    ret.points.num = el.GetNP();\n    ret.points.ptr = (int*)&(el[0]);\n\n    ret.vertices.num = 2;\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = 1;\n    ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr);\n\n    ret.faces.num = 0;\n    ret.faces.ptr = NULL;\n\n    return ret;\n  }\n\n  template <> DLL_HEADER Ng_Element Ng_GetElement<2> (int nr)\n  {\n    const Element2d & el = mesh->SurfaceElement (SurfaceElementIndex (nr));\n  \n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n    ret.points.num = el.GetNP();\n    ret.points.ptr  = (int*)&el[0];\n\n    ret.vertices.num = el.GetNV();\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n    ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr);\n\n    ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n    ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr);\n\n    return ret;\n  }\n\n  template <> DLL_HEADER Ng_Element Ng_GetElement<3> (int nr) \n  {\n    const Element & el = mesh->VolumeElement (ElementIndex (nr));\n  \n    Ng_Element ret;\n    ret.type = NG_ELEMENT_TYPE(el.GetType());\n    ret.points.num = el.GetNP();\n    ret.points.ptr = (int*)&el[0];\n\n    ret.vertices.num = el.GetNV();\n    ret.vertices.ptr = (int*)&(el[0]);\n\n    ret.edges.num = MeshTopology::GetNEdges (el.GetType());\n    ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr);\n\n    ret.faces.num = MeshTopology::GetNFaces (el.GetType());\n    ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr);\n\n    return ret;\n  }\n  */\n\n\n\n\n\n\n\n  \n  \n  template <> DLL_HEADER void Ngx_Mesh :: \n  ElementTransformation<3,3> (int elnr, \n                              const double * xi,\n                              double * x, \n                              double * dxdxi) const\n  {\n    Point<3> xl(xi[0], xi[1], xi[2]);\n    Point<3> xg;\n    Mat<3,3> dx;\n    mesh->GetCurvedElements().CalcElementTransformation (xl, elnr, xg, dx);\n\n    if (x)\n      for (int i = 0; i < 3; i++) x[i] = xg(i);\n    \n    if (dxdxi)\n      for (int i=0; i<3; i++)\n        {\n          dxdxi[3*i] = dx(i,0);\n          dxdxi[3*i+1] = dx(i,1);\n          dxdxi[3*i+2] = dx(i,2);\n        }\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  ElementTransformation<2,3> (int elnr,\n                              const double * xi, \n                              double * x, \n                              double * dxdxi) const\n  {\n    Point<2> xl(xi[0], xi[1]);\n    Point<3> xg;\n    Mat<3,2> dx;\n\n    mesh->GetCurvedElements().CalcSurfaceTransformation (xl, elnr, xg, dx);\n    \n    if (x)\n      for (int i = 0; i < 3; i++) x[i] = xg(i);\n    \n    if (dxdxi)\n      for (int i=0; i<3; i++)\n        {\n          dxdxi[2*i] = dx(i,0);\n          dxdxi[2*i+1] = dx(i,1);\n        }\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  ElementTransformation<1,3> (int elnr,\n\t\t\t      const double * xi,\n\t\t\t      double * x,\n\t\t\t      double * dxdxi) const\n  {\n    Point<3> xg;\n    Vec<3> dx;\n    mesh->GetCurvedElements().CalcSegmentTransformation(xi[0],elnr,xg,dx);\n    if(x)\n      for(int i=0;i<3;i++) x[i] = xg(i);\n\n    if(dxdxi)\n      for(int i=0;i<3;i++) dxdxi[i] = dx(i);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  ElementTransformation<0,3> (int elnr,\n\t\t\t      const double * xi,\n\t\t\t      double * x,\n\t\t\t      double * dxdxi) const\n  {\n    PointIndex pi = mesh->pointelements[elnr].pnum;\n    Point<3> xg = mesh->Point(pi);\n    if (x)\n      for(int i=0;i<3;i++) x[i] = xg(i);\n  }\n\n  \n  template <> DLL_HEADER void Ngx_Mesh ::\n  ElementTransformation<2,2> (int elnr,\n                                 const double * xi, \n                                 double * x, \n                                 double * dxdxi) const\n  {\n    Point<2> xl(xi[0], xi[1]);\n    Point<3> xg;\n    Mat<3,2> dx;\n\n    mesh->GetCurvedElements().CalcSurfaceTransformation (xl, elnr, xg, dx);\n    \n    if (x)\n      for (int i = 0; i < 2; i++) x[i] = xg(i);\n    \n    if (dxdxi)\n      for (int i=0; i<2; i++)\n        {\n          dxdxi[2*i] = dx(i,0);\n          dxdxi[2*i+1] = dx(i,1);\n        }\n  }\n\n\n\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  ElementTransformation<1,2> (int elnr,\n                              const double * xi,\n                              double * x,\n                              double * dxdxi) const\n  {\n    Point<3> xg;\n    Vec<3> dx;\n\n    mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], elnr, xg, dx);\n    \n    if (x)\n      for (int i = 0; i < 2; i++) x[i] = xg(i);\n    \n    if (dxdxi)\n      for (int i=0; i < 2; i++)\n        dxdxi[i] = dx(i);\n  }\n\n\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  ElementTransformation<1,1> (int elnr,\n                              const double * xi,\n                              double * x,\n                              double * dxdxi) const\n  {\n    Point<3> xg;\n    Vec<3> dx;\n\n    mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], elnr, xg, dx);\n    \n    if (x) x[0] = xg(0);\n    if (dxdxi) dxdxi[0] = dx(0);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  ElementTransformation<0,2> (int elnr,\n\t\t\t      const double *xi,\n\t\t\t      double * x,\n\t\t\t      double * dxdxi) const\n  {\n    PointIndex pnum = mesh->pointelements[elnr].pnum;\n    if (x)\n      for (int i = 0; i< 2; i++) x[i] = (*mesh)[pnum](i);\n  }\n\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  ElementTransformation<0,1> (int elnr, \n                              const double * xi,\n                              double * x,\n                              double * dxdxi) const\n  {\n    PointIndex pnum = mesh->pointelements[elnr].pnum;\n    if (x) x[0] = (*mesh)[pnum](0);\n    // if (dxdxi) dxdxi[0] = 0;\n    // Jacobi-matrix is 1 x 0 !!!\n  }\n\n\n\n\n\n  \n  \n  template <> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<3,3> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointElementTransformation (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n  }\n  \n  template <> DLL_HEADER void Ngx_Mesh ::\n  MultiElementTransformation<2,2> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<2,3> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<3> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  MultiElementTransformation<1,3> (int elnr, int npts,\n\t\t\t\t   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<3> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  MultiElementTransformation<0,3> (int elnr, int npts,\n\t\t\t\t   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    for (int i = 0; i < npts; i++)\n      ElementTransformation<0,3> (elnr, xi+i*sxi, x+i*sx, dxdxi+i*sdxdxi);\n  }\n    \n  template <> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<1,2> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<1,1> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    for (int i = 0; i < npts; i++)\n      ElementTransformation<1,1> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi);\n  }\n\n  template <> DLL_HEADER void Ngx_Mesh ::\n  MultiElementTransformation<0,2> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    for (int i = 0; i < npts; i++)\n      ElementTransformation<0,2> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi);\n  }\n\n\n  template <> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<0,1> (int elnr, int npts,\n                                   const double * xi, size_t sxi,\n                                   double * x, size_t sx,\n                                   double * dxdxi, size_t sdxdxi) const\n  {\n    for (int i = 0; i < npts; i++)\n      ElementTransformation<0,1> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi);\n  }\n\n\n  int Ngx_Mesh :: GetHPElementLevel (int ei, int dir) const\n  {\n    ei++;\n    int level = -1;\n    \n    if (mesh->hpelements)\n      {\n\tint hpelnr = -1;\n\tif (mesh->GetDimension() == 2)\n\t  hpelnr = mesh->SurfaceElement(ei).GetHpElnr();\n\telse\n\t  hpelnr = mesh->VolumeElement(ei).GetHpElnr();\n\n        if (hpelnr < 0)\n          throw NgException(\"Ngx_Mesh::GetHPElementLevel: Wrong hp-element number!\");\n        \n        if (dir == 1)\n          level = (*mesh->hpelements)[hpelnr].levelx;\n        else if (dir == 2)\n          level = (*mesh->hpelements)[hpelnr].levely;\n        else if (dir == 3)\n          level = (*mesh->hpelements)[hpelnr].levelz;\n        else\n          throw NgException(\"Ngx_Mesh::GetHPElementLevel: dir has to be 1, 2 or 3!\");\n      }\n    //else\n    //  throw NgException(\"Ngx_Mesh::GetHPElementLevel only for HPRefinement implemented!\");\n\n    return level;\t  \n  }\n  \n  int Ngx_Mesh :: GetParentElement (int ei) const\n  {\n    if (mesh->GetDimension() == 3)\n      {\n        if (ei < mesh->mlparentelement.Size())\n          return mesh->mlparentelement[ei];\n      }\n    else\n      {\n        if (ei < mesh->mlparentsurfaceelement.Size())\n          return mesh->mlparentsurfaceelement[ei];\n      }\n    return -1;\n  }\n\n\n  int Ngx_Mesh :: GetParentSElement (int ei) const\n  {\n    if (mesh->GetDimension() == 3)\n      {\n        if (ei < mesh->mlparentsurfaceelement.Size())\n          return mesh->mlparentsurfaceelement[ei];\n      }\n    else\n      {\n        return -1;\n      }\n    return -1;\n  }\n\n  int Ngx_Mesh :: GetNIdentifications () const\n  {\n    return mesh->GetIdentifications().GetMaxNr();\n  }\n\n  int Ngx_Mesh :: GetIdentificationType(int idnr) const\n  {\n    return mesh->GetIdentifications().GetType(idnr+1);\n  }\n\n  Ng_BufferMS<int,4> Ngx_Mesh::GetFaceEdges (int fnr) const\n  {\n    const MeshTopology & topology = mesh->GetTopology();\n    NgArrayMem<int,4> ia;\n    topology.GetFaceEdges (fnr+1, ia);\n    Ng_BufferMS<int,4> res(ia.Size());\n    for (size_t i = 0; i < ia.Size(); i++)\n      res[i] = ia[i]-1;\n    return res;\n  }\n\n\n\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<1,1> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    cout << \"multi-eltrafo simd called, 1,1,simd\" << endl;\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<2,2> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2>\n      (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n    /*\n    for (int i = 0; i < npts; i++)\n      {\n        double hxi[4][2];\n        double hx[4][2];\n        double hdxdxi[4][4];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 2; k++)\n            hxi[j][k] = ((double*)&(xi[k]))[j];\n        MultiElementTransformation<2,2> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 2, &hdxdxi[0][0], 4);\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 2; k++)\n            ((double*)&(x[k]))[j] = hx[j][k];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 4; k++)\n            ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k];\n        \n        xi += sxi;\n        x += sx;\n        dxdxi += sdxdxi;\n      }\n    */\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<3,3> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointElementTransformation\n      (elnr, npts,\n       xi, sxi,\n       x, sx,\n       dxdxi, sdxdxi);\n    /*\n    for (int i = 0; i < npts; i++)\n      {\n        double hxi[4][3];\n        double hx[4][3];\n        double hdxdxi[4][9];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 3; k++)\n            hxi[j][k] = ((double*)&(xi[k]))[j];\n        MultiElementTransformation<3,3> (elnr, 4, &hxi[0][0], 3, &hx[0][0], 3, &hdxdxi[0][0], 9);\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 3; k++)\n            ((double*)&(x[k]))[j] = hx[j][k];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 9; k++)\n            ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k];\n        \n        xi += sxi;\n        x += sx;\n        dxdxi += sdxdxi;\n      }\n    */\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh ::\n  MultiElementTransformation<0,2> (int elnr, int npts,\n\t\t\t\t   const SIMD<double> *xi, size_t sxi,\n\t\t\t\t   SIMD<double> * x, size_t sx,\n\t\t\t\t   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    //cout << \"MultiElementtransformation<0,2> simd not implemented\" << endl;\n\n    PointIndex pi = mesh->pointelements[elnr].pnum;\n    Point<3> xg = mesh->Point(pi);\n    if (x)\n      for (int j = 0; j < npts; j++)\n\tfor (int i = 0; i < 2; i++)\n\t  x[j*sx+i] = xg(i);\n  }\n  \n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<0,1> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    //cout << \"multi-eltrafo simd called, 0,1,simd\" << endl;\n    PointIndex pi = mesh->pointelements[elnr].pnum;\n    Point<3> xg = mesh->Point(pi);\n    if (x)\n      for (int j = 0; j < npts; j++)\n\tfor (int i = 0; i < 1; i++)\n\t  x[j*sx+i] = xg(i);\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<1,3> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<3>\n      (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n    /*\n    double hxi[4][1];\n    double hx[4][3];\n    double hdxdxi[4][3];\n    for (int j = 0; j<4;j++)\n      hxi[j][0] = ((double*)&(xi[0]))[j];\n    MultiElementTransformation<1,3> (elnr, 4, &hxi[0][0], 1, &hx[0][0], 3, &hdxdxi[0][0],3);\n    for(int j=0; j<4; j++)\n      for(int k=0; k<3; k++)\n\t((double*)&(x[k]))[j] = hx[j][k];\n    for(int j=0; j< 4; j++)\n      for (int k = 0; k<3; k++)\n\t((double*) & (dxdxi[k]))[j] = hdxdxi[j][k];\n\n    xi += sxi;\n    x += sx;\n    dxdxi += sdxdxi;\n    */\n  }\n  \n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<1,2> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<2>\n      (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n    /*\n    for (int i = 0; i < npts; i++)\n      {\n        double hxi[4][1];\n        double hx[4][2];\n        double hdxdxi[4][2];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 1; k++)\n            hxi[j][k] = ((double*)&(xi[k]))[j];\n        MultiElementTransformation<1,2> (elnr, 4, &hxi[0][0], 1, &hx[0][0], 2, &hdxdxi[0][0], 2);\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 2; k++)\n            ((double*)&(x[k]))[j] = hx[j][k];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 2; k++)\n            ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k];\n        \n        xi += sxi;\n        x += sx;\n        dxdxi += sdxdxi;\n      }\n    */\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<2,3> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<3>\n      (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi);\n    /*\n    for (int i = 0; i < npts; i++)\n      {\n        double hxi[4][2];\n        double hx[4][3];\n        double hdxdxi[4][6];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 2; k++)\n            hxi[j][k] = ((double*)&(xi[k]))[j];\n        MultiElementTransformation<2,3> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 3, &hdxdxi[0][0], 6);\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 3; k++)\n            ((double*)&(x[k]))[j] = hx[j][k];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 6; k++)\n            ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k];\n        \n        xi += sxi;\n        x += sx;\n        dxdxi += sdxdxi;\n      }\n    */\n  }\n\n  template<> DLL_HEADER void Ngx_Mesh :: \n  MultiElementTransformation<0,3> (int elnr, int npts,\n                                   const SIMD<double> * xi, size_t sxi,\n                                   SIMD<double> * x, size_t sx,\n                                   SIMD<double> * dxdxi, size_t sdxdxi) const\n  {\n    for (int i = 0; i < npts; i++)\n      {\n        double hxi[4][1];\n        double hx[4][3];\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 1; k++)\n            hxi[j][k] = ((double*)&(xi[k]))[j];\n        MultiElementTransformation<0,3> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 3, (double*)nullptr, 0);\n        for (int j = 0; j < 4; j++)\n          for (int k = 0; k < 3; k++)\n            ((double*)&(x[k]))[j] = hx[j][k];\n        xi += sxi;\n        x += sx;\n        dxdxi += sdxdxi;\n      }\n  }\n\n\n\n  \n\n\n  template <>\n  DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <1> \n  (double * hp, double * lami,\n   bool build_searchtree, \n   int * const indices, int numind, double tol) const\n\n  {\n    Point<3> p(hp[0], 0., 0.);\n    if(mesh->GetDimension() > 1)\n      p[1] = hp[1];\n    if(mesh->GetDimension() == 3)\n      p[2] = hp[2];\n\n    for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)\n      {\n        auto & seg = (*mesh)[si];\n        Point<3> p1 = (*mesh)[seg[0]];\n        Point<3> p2 = (*mesh)[seg[1]];\n        Vec<3> v1 = p2-p1;\n        Vec<3> v2 = p-p1;\n        double lam = v1*v2 / v1.Length2();\n        double lam2 = (v2 - lam * v1).Length() / v1.Length();\n\n        if (lam >= -1e-10 && lam <= 1+1e-10 && lam2 < 1e-10)\n          {\n            lami[0] = 1-lam;\n            return si;\n          }\n      }\n    return -1;\n  }\n\n  template <>\n  DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <2> \n  (double * p, double * lami,\n   bool build_searchtree, \n   int * const indices, int numind, double tol) const\n\n  {\n    Point<3> pp(p[0], p[1], 0.);\n    if(mesh->GetDimension() == 3)\n      pp[2] = p[2];\n    FlatArray<int> ind(numind, indices);\n    double lam3[3];\n    auto elnr = mesh->GetSurfaceElementOfPoint(pp, lam3, ind, build_searchtree);\n    if(elnr.IsValid())\n      {\n        if((*mesh)[elnr].GetType() == QUAD || (*mesh)[elnr].GetType() == TRIG6)\n          {\n            lami[0] = lam3[0];\n            lami[1] = lam3[1];\n          }\n        else\n          {\n            lami[0] = 1-lam3[0]-lam3[1];\n            lami[1] = lam3[0];\n          }\n      }\n    return elnr;\n  }\n\n\n  template <>\n  DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <3>\n  (double * p, double * lami,\n   bool build_searchtree, \n   int * const indices, int numind,\n   double tol) const\n\n  {\n    Point<3> pp(p[0], p[1], p[2]);\n    FlatArray<int> ind(numind, indices);\n    return mesh->GetElementOfPoint(pp, lami, ind, build_searchtree, true, tol);\n  }\n\n  void Ngx_Mesh :: Curve (int order)\n  {\n    NgLock meshlock (mesh->MajorMutex(), true);\n    mesh->BuildCurvedElements(order);\n  }\n\n  int Ngx_Mesh :: GetCurveOrder ()\n  {\n    return mesh->GetCurvedElements().GetOrder();\n  }\n\n  void Ngx_Mesh :: EnableTable (string name, bool set)\n  {\n    mesh->GetTopology().EnableTable (name, set);\n    mesh->SetNextTimeStamp();  // update topology will do work\n  }\n\n\n  \n  template <>\n  DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag)\n  {\n    mesh->SurfaceElement(elnr+1).SetRefinementFlag(flag);\n  }\n\n  template <>\n  DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag)\n  {\n    mesh->VolumeElement(elnr+1).SetRefinementFlag(flag);    \n  }\n  \n  void Ngx_Mesh :: Refine (NG_REFINEMENT_TYPE reftype, bool onlyonce,\n                           void (*task_manager)(function<void(int,int)>),\n                           NgTracer tracer)\n  {\n    NgLock meshlock (mesh->MajorMutex(), 1);\n    \n    BisectionOptions biopt;\n    biopt.usemarkedelements = 1;\n    biopt.refine_p = 0;\n    biopt.refine_hp = 0;\n    biopt.onlyonce = onlyonce;\n    if (reftype == NG_REFINE_P)\n      biopt.refine_p = 1;\n    if (reftype == NG_REFINE_HP)\n      biopt.refine_hp = 1;\n    biopt.task_manager = task_manager;\n    biopt.tracer = tracer;\n\n    mesh->GetGeometry()->GetRefinement().Bisect (*mesh, biopt);\n    (*tracer)(\"call updatetop\", false);\n    mesh -> UpdateTopology(task_manager, tracer);\n    (*tracer)(\"call updatetop\", true);\n    if(mesh->GetCurvedElements().IsHighOrder())\n      mesh->GetCurvedElements()\n        .BuildCurvedElements(&mesh->GetGeometry()->GetRefinement(),\n                                mesh->GetCurvedElements().GetOrder());\n  }\n\n\n\n\n\n  // just copied with redesign\n\n  size_t Ngx_Mesh::GetNP() const\n  {\n    return mesh->GetNP();\n  }\n\n  \n  int Ngx_Mesh::GetSurfaceElementSurfaceNumber (size_t ei) const\n  {\n    if (mesh->GetDimension() == 3)\n      return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr();\n    else\n      return mesh->LineSegment(ei).si;\n  }\n  int Ngx_Mesh::GetSurfaceElementFDNumber (size_t ei) const\n  {\n    if (mesh->GetDimension() == 3)\n      return mesh->SurfaceElement(ei).GetIndex();\n    else\n      return -1;\n  }\n\n  \n  void Ngx_Mesh::HPRefinement (int levels, double parameter, bool setorders,\n                               bool ref_level)\n  {\n    NgLock meshlock (mesh->MajorMutex(), true);\n    Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n    ::netgen::HPRefinement (*mesh, &ref, SPLIT_HP, levels, parameter, setorders, ref_level);\n  }\n\n  void Ngx_Mesh::SplitAlfeld ()\n  {\n    NgLock meshlock (mesh->MajorMutex(), true);\n    Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n    ::netgen::HPRefinement (*mesh, &ref, SPLIT_ALFELD, 1, 1.0 / (mesh->GetDimension()+1), true, true);\n  }\n\n  \nint Ngx_Mesh::GetElementOrder (int enr) const\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->VolumeElement(enr).GetOrder();\n  else\n    return mesh->SurfaceElement(enr).GetOrder();\n}\n\nvoid Ngx_Mesh::GetElementOrders (int enr, int * ox, int * oy, int * oz) const\n{\n  if (mesh->GetDimension() == 3)\n    {\n      ElementIndex ei = IndexBASE<ElementIndex>() + enr-1;\n      mesh->VolumeElement(ei).GetOrder(*ox, *oy, *oz);\n    }\n  else\n    {\n      SurfaceElementIndex sei = IndexBASE<SurfaceElementIndex>() + enr-1;      \n      mesh->SurfaceElement(sei).GetOrder(*ox, *oy, *oz);\n    }\n}\n\nvoid Ngx_Mesh::SetElementOrder (int enr, int order)\n{\n  if (mesh->GetDimension() == 3)\n    return mesh->VolumeElement(enr).SetOrder(order);\n  else\n    return mesh->SurfaceElement(enr).SetOrder(order);\n}\n\nvoid Ngx_Mesh::SetElementOrders (int enr, int ox, int oy, int oz)\n{\n  if (mesh->GetDimension() == 3)\n    mesh->VolumeElement(enr).SetOrder(ox, oy, oz);\n  else\n    mesh->SurfaceElement(enr).SetOrder(ox, oy);\n}\n\n\nint Ngx_Mesh::GetSurfaceElementOrder (int enr) const\n{\n  return mesh->SurfaceElement(enr).GetOrder();\n}\n\nint Ngx_Mesh::GetClusterRepVertex (int pi) const\n{\n  return mesh->GetClusters().GetVertexRepresentant(pi);\n}\n\nint Ngx_Mesh::GetClusterRepEdge (int pi) const\n{\n  return mesh->GetClusters().GetEdgeRepresentant(pi);\n}\n\nint Ngx_Mesh::GetClusterRepFace (int pi) const\n{\n  return mesh->GetClusters().GetFaceRepresentant(pi);\n}\n\nint Ngx_Mesh::GetClusterRepElement (int pi) const\n{\n  return mesh->GetClusters().GetElementRepresentant(pi);\n}\n\n\nint Ngx_Mesh::GetElement_Faces (int elnr, int * faces, int * orient) const\n{\n  const MeshTopology & topology = mesh->GetTopology();\n  if (mesh->GetDimension() == 3)\n    {\n      int num = topology.GetElementFaces (elnr+1, faces, orient);\n      for (int i = 0; i < num; i++)\n        faces[i]--;\n      return num;\n    }\n  else\n    {\n      faces[0] = elnr;\n      if (orient) orient[0] = 0;\n      return 1;\n    }\n}\n\nint Ngx_Mesh::GetSurfaceElement_Face (int selnr, int * orient) const\n{\n  if (mesh->GetDimension() == 3)\n    {\n      const MeshTopology & topology = mesh->GetTopology();\n      if (orient)\n\t*orient = topology.GetSurfaceElementFaceOrientation (selnr+1);\n      return topology.GetFace (SurfaceElementIndex(selnr));\n    }\n  return -1;\n}\n\n\n\n//HERBERT: falsche Anzahl von Argumenten\n//void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz)\nvoid Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy) const\n{\n  int d; \n  mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d);\n}\n\nvoid Ngx_Mesh::SetSurfaceElementOrder (int enr, int order)\n{\n  return mesh->SurfaceElement(enr).SetOrder(order);\n}\n\nvoid Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy)\n{\n  mesh->SurfaceElement(enr).SetOrder(ox, oy);\n}\n\n  \n\nsize_t Ngx_Mesh :: GetGlobalVertexNum (int locnum) const\n{\n#ifdef PARALLEL  \n  return mesh->GetParallelTopology().GetGlobalPNum (locnum+1)-1;\n#else\n  return locnum;\n#endif\n}\n\n  \nFlatArray<int>  Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const\n  {\n#ifdef PARALLEL\n    if (mesh->GetCommunicator().Size() == 1)\n      return FlatArray<int>(0,nullptr);\n    \n    switch (nodetype)\n      {\n      case 0:\n        // return mesh->GetParallelTopology().GetDistantPNums(locnum);\n        return mesh->GetParallelTopology().GetDistantProcs(locnum+PointIndex::BASE);\n      case 1:\n        // return mesh->GetParallelTopology().GetDistantEdgeNums(locnum);\n        return mesh->GetParallelTopology().GetDistantEdgeProcs(locnum);\n      case 2:\n        // return mesh->GetParallelTopology().GetDistantFaceNums(locnum);\n        return mesh->GetParallelTopology().GetDistantFaceProcs(locnum);\n      default:\n\treturn FlatArray<int>(0, nullptr);\n      }\n#else\n    return FlatArray<int>(0,nullptr);\n#endif\n  }\n}\n\n\nint link_it_nginterface_v2;\n\n"
  },
  {
    "path": "libsrc/interface/read_fnf_mesh.cpp",
    "content": "\n//\n//  Read Pro/ENGINEER neutral format\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include <sys/stat.h>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n  bool ReadLine (istream & in, string & buf)\n  {\n    do\n      {\n        buf = \"\";\n        \n        while (in.good())\n          {\n            char ch = in.get();\n            if (ch == '\\n') break;\n            if (ch == '\\r') break;\n            if (ch == '\\\\')\n              {\n                // while (iswhite (ch = in.get() )\n                ch = in.get();   // '\\n'   CR\n                ch = in.get();   // '\\n'   LF\n              }\n            else\n              buf += ch;\n          }\n      }\n    while (in.good() && (buf == \"\" || buf[0] == '#'));\n    \n    return in.good();\n  }\n  \n\n\n\n  \n  class LoadType\n  {\n  public:\n    int id;\n    string name;\n    string placement;\n    string valuetype;\n    NgArray<double> places;\n  };\n\n\n\n  \n  void ReadFNFFormat (Mesh & mesh, \n                      const filesystem::path & filename)\n  {\n    ifstream fin (filename);\n\n    string buf;\n\n    mesh.SetDimension (3);\n\n    while (ReadLine (fin, buf))\n      {\n        stringstream sbuf(buf);\n        string start_sect, token; char ch;\n        \n        sbuf >> start_sect;\n\n        if (start_sect == \"%START_SECT\")\n          {\n            sbuf >> ch >> token;\n            \n            if (token == \"HEADER\")\n              {\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    \n                    sbuf >> token;\n                    \n                    if (token == \"%TITLE\")\n                      {\n                        char ch;\n                        string name;\n                        sbuf >> ch >> name;\n                        PrintMessage(3, \"Title: \", name);\n                      }\n                    else if (token == \"%STATISTICS\")\n                      {\n                        ;\n                      }\n                    else if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION HEADER, unknown field: \",buf);\n                      }\n                  }                \n              }\n \n\n            else if (token == \"ELEM_TYPES\")\n              {\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    \n                    sbuf >> token;\n                    \n                    if (token == \"%ELEM_TYPE\")\n                      {\n\t\t\tint nr;\n\t\t\tstring def;\n                        char ch;\n                        sbuf >> nr >> def >> ch;\n\t\t\tif (def == \"DEF\")\n\t\t\t  {\n\t\t\t    string classname, type;\n\t\t\t    sbuf >> classname >> type;\n\t\t\t    if (classname != \"SOLID\" || type != \"TETRA\")\n\t\t\t      cerr << \"Element not supported: \" << buf << endl;\n\t\t\t  }\n                      }\n                    else if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION ELEM_TYPE, unknown field: \", buf);\n                      }\n                  }                \n              }\n \n\n            else if (token == \"COORD_SYSTEMS\")\n              {\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    \n                    sbuf >> token;\n                    \n                    if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                    else\n                      {\n                        // cout << \"COORD_SYSTEMS, unknown field: \" << buf << endl;\n                      }\n                  }                \n              }\n\n            else if (token == \"ANALYSIS\")\n              {\n                // ignore this section\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    sbuf >> token;\n                    if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                  }                \n              }\n \n            else if (token == \"MATERIALS\")\n              {\n\t\t*testout << \"parse materials\" << endl;\n                NgArray<double> young_modulus, poisson_ratio, mass_density;\n\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    \n                    sbuf >> token;\n                    \n                    if (token == \"%MATERIAL\")\n                      {\n                        int nr;\n                        string prop;\n                        char ch;\n                        double val;\n\n                        sbuf >> nr >> prop >> ch;\n                        if (prop == \"DEF\")\n                          {\n                            string name;\n                            sbuf >> name;\n                            mesh.SetMaterial(nr, name);\n                          }\n                        else\n                          {\n                            sbuf >> val;\n\t\t\t    *testout << \"prop = \" << prop << \", val = \" << val << endl;\n                            if (prop == \"YOUNG_MODULUS\")\n                              young_modulus.Append (val);\n                            else if  (prop == \"POISSON_RATIO\")\n                              poisson_ratio.Append (val);\n                            else if  (prop == \"MASS_DENSITY\")\n                              mass_density.Append (val);\n                          }\n                      }\n                    else if (token == \"%END_SECT\")\n                      {\n                        mesh.SetUserData (\"YOUNG_MODULUS\", young_modulus);\n                        mesh.SetUserData (\"POISSON_RATIO\", poisson_ratio);\n                        mesh.SetUserData (\"MASS_DENSITY\", mass_density);\n\t\t\t*testout << \"young = \" << young_modulus << endl;\n\t\t\t*testout << \"poisson = \" << poisson_ratio << endl;\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION MATERIALS, unknown field: \", buf);\n                      }\n                  }\n              }\n\n            \n            else if (token == \"MESH\")\n              {\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    sbuf >> token;\n                    if (token == \"%NODE\")\n                      {\n                        string st;\n                        char ch;\n                        int nr, ks_id;\n                        double x,y,z;\n                        sbuf >> nr >> st >> ch >> x >> y >> z >> ks_id;\n                        mesh.AddPoint (Point3d (x,y,z) );\n                      }\n                    else if (token == \"%ELEM\")\n                      {\n                        string elemid, def;\n                        char ch;\n                        int elnr, typid, matid;\n                        string propid;\n                        sbuf >> elnr >> def >> ch;\n                        sbuf >> typid >> matid >> propid;\n                        NgArray<int> pnums;\n                        while (1)\n                          {\n                            int pn;\n                            sbuf >> pn;\n                            if (!sbuf.good()) break;\n                            pnums.Append (pn);\n                          }\n                        int pe2ng [] = { 0, 1, 2, 3, 4, 7, 5, 6,  8, 9 };\n                        Element el(pnums.Size());\n                        for (int j = 0; j < pnums.Size(); j++)\n                          el[pe2ng[j]] = pnums[j];\n                        el.SetIndex (matid);\n                        mesh.AddVolumeElement (el);\n                      }\n                    else if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION MESH, unknown: \", buf);\n                      }\n                  }\n              }\n            else if (token == \"MESH_TOPOLOGY\")\n              {\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token, kw;\n                    int nr;\n                    char ch;\n\n                    sbuf >> token;\n                    if (token == \"%EDGE\")\n                      {\n                        sbuf >> nr >> kw >> ch;\n                        if (kw == \"NODES\")\n                          {\n                            NgArray<int> enums;\n                            while (1)\n                              {\n                                int en;\n                                sbuf >> en;\n                                if (!sbuf.good()) break;\n                                enums.Append (en);\n                              }\n                            for (int j = 0; j+2 < enums.Size(); j+=2)\n                              {\n                                Segment seg;\n                                seg[0] = enums[j];\n                                seg[1] = enums[j+2];\n                                seg[2] = enums[j+1];\n                                seg.edgenr = nr;\n                                mesh.AddSegment (seg);\n                              }\n                          }\n                      }\n                    else if (token == \"%SURFACE\")\n                      {\n                        sbuf >> nr >> kw >> ch;\n                        if (kw == \"FACES\")\n                          {\n                            NgArray<int> fnums;\n                            while (1)\n                              {\n                                int fn;\n                                sbuf >> fn;\n                                if (!sbuf.good()) break;\n                                fnums.Append (fn);\n                              }                            \n\n                            FaceDescriptor fd(-1, -1, -1, -1);\n                            fd.SetBCProperty (nr);\n\t\t\t    *testout << \"add fd \" << mesh.GetNFD() << \", nr = \" << nr << endl;\n                            mesh.AddFaceDescriptor (fd);\n                              \n                            for (int j = 0; j < fnums.Size(); j += 2)\n                              {\n                                int elnr = fnums[j];\n                                int fnr = fnums[j+1];\n                                \n                                const Element & el = mesh.VolumeElement (elnr);\n                                if(j == 0)\n                                  mesh.GetFaceDescriptor(nr).SetDomainIn(el.GetIndex());\n                                Element2d el2d;\n                                el.GetFace (fnr, el2d);\n                                el2d.SetIndex (nr);\n                                  \n                                mesh.AddSurfaceElement (el2d);\n                              }\n                          }\n                      }\n                    else if (token == \"%END_SECT\")\n                      {\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION MESH, unknown: \", buf);\n                      }\n                  }\n              }\n\n\n\n \n            else if (token == \"LOADS\")\n              {\n                NgArray<LoadType*> loadtypes;\n\n                while (1)\n                  {\n                    ReadLine (fin, buf);\n                    stringstream sbuf(buf);\n                    string token;\n                    \n                    sbuf >> token;\n                    \n                    if (token == \"%LOAD_TYPE\")\n                      {\n                        string def;\n                        char ch;\n\n                        LoadType * lt = new LoadType;\n                        sbuf >> lt->id >> def >> ch >> lt->name >> lt->placement >> lt->valuetype;\n                        \n                        if (lt->name == \"DISPLACEMENT\")\n                          PrintMessage(3, \"loadtype DISPLACEMENT found\");\n\n                        if (lt->placement != \"FACE\" && lt->placement != \"EDGE\" && lt->placement != \"NODE\")\n                          PrintMessage(1, \"unsupported placement \", lt->placement);\n\n                        loadtypes.Append (lt);\n                      }\n\n                    else if (token == \"%LOAD\")\n                      {\n                        int id;\n                        string def;\n                        char ch;\n                        int placement;\n                        int load_type_id, con_case_id;\n                        sbuf >> id >> def >> ch;\n                        \n                        if (def == \"DEF\")\n                          {\n                            sbuf >> load_type_id >> con_case_id;\n                          }\n                        if (def == \"VAL\")\n                          {\n                            sbuf >> placement;\n                            for (int i = 0; i < loadtypes.Size(); i++)\n                              if (load_type_id == loadtypes[i]->id)\n                                loadtypes[i]->places.Append (placement);\n                          }\n                      }\n                    else if (token == \"%CON_CASE\")\n                      { ; }\n                    \n                    else if (token == \"%END_SECT\")\n                      {\n                        for (int i = 0; i < loadtypes.Size(); i++)\n                          {\n                            stringstream str;\n                            str << loadtypes[i]->places;\n                            if (loadtypes[i]->placement == \"FACE\" && loadtypes[i]->name == \"DISPLACEMENT\")\n                              {\n                                mesh.SetUserData (\"CONSTRAINT_DISP_FACE\", loadtypes[i]->places);\n                                PrintMessage(3, \"constrained faces: \", str.str());\n                              }\n                            if (loadtypes[i]->placement == \"EDGE\" && loadtypes[i]->name == \"DISPLACEMENT\")\n                              {\n                                mesh.SetUserData (\"CONSTRAINT_DISP_EDGE\", loadtypes[i]->places);\n                                PrintMessage(3,\"constrained edges: \", str.str());\n                              }\n                            if (loadtypes[i]->placement == \"NODE\" && loadtypes[i]->name == \"DISPLACEMENT\")\n                              {\n                                mesh.SetUserData (\"CONSTRAINT_DISP_NODE\", loadtypes[i]->places);\n                                PrintMessage(3, \"constrained nodes: \", str.str());\n                              }\n                          }\n                        break;\n                      }\n                    else\n                      {\n                        PrintMessage(1, \"SECTION LOADS, unknown field: \", buf);\n                      }\n                  }\n              }\n\n\n\n            else\n              {\n                PrintMessage(1, \"unknown section \", token);\n              }\n          }\n        else\n          PrintMessage(3, \"parse line: (\", buf, \")\");\n      }\n    mesh.ComputeNVertices();\n  }\nstatic RegisterUserFormat reg_fnf (\"Pro/ENGINEER Format\", {\".fnf\"}, ReadFNFFormat, nullopt);\n}\n"
  },
  {
    "path": "libsrc/interface/readtetmesh.cpp",
    "content": "\n//\n//  Read CST file format\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include <sys/stat.h>\n\n\nnamespace netgen\n{\n#include \"writeuser.hpp\"\n\n\n\n\n  void ReadTETFormat (Mesh & mesh, \n                      const filesystem::path & filename)\n  {\n    cout << \"Reading .tet mesh\" << endl;\n\n    ifstream in (filename);\n\n    int inputsection = 0;\n    bool done = false;\n\n    char ch;\n    string str;\n\n    string version;\n\n    int unitcode;\n    double tolerance;\n    double dS1, dS2, alphaDeg, x3D, y3D, z3D;\n    int nelts,nfaces,nedges,nnodes;\n    int nperiodicmasternodes,ncornerperiodicmasternodes,ncubicperiodicmasternodes;\n    int nperiodicmasteredges,ncornerperiodicmasteredges;\n    int nperiodicmasterfaces;\n    int nodeid,type,pid;\n    int dummyint;\n    int modelverts,modeledges,modelfaces,modelcells;\n    Point3d p;\n    int numObj3D,numObj2D,numObj1D,numObj0D;\n    // bool nullstarted;\n    NgArray<int> eldom;\n    int minId3D = -1, minId2D = -1;\n    int maxId3D(-1), maxId2D(-1), maxId1D(-1), maxId0D(-1);\n    NgArray<NgArray<int> *> segmentdata;\n    NgArray<Element2d* > tris;\n\n    NgArray<int> userdata_int;  // just save data for 1:1 output\n    NgArray<double> userdata_double;\n    NgArray<int> point_pids;\n    NgArray<int> tetfacedata;\n    NgArray<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D;\n\n    while(!done)\n      {\n        // skip \"//\" comment\n        bool comment = true;\n        while(comment)\n          {\n            ch = in.get();\n            while(ch == ' ' || ch == '\\n' || ch == '\\t' || ch =='\\r')\n              ch = in.get();\n\t      \n            if(ch != '/')\n              {\n                comment = false;\n                in.putback(ch);\n              }\n            else\n              {\n                ch = in.get();\n                if(ch != '/')\n                  {\n                    comment = false;\n                    in.putback(ch);\n                    in.putback('/');\n                  }\n                else\n                  {\n                    in.ignore(10000,'\\n');\n                  }\n              }\n          }\n\n\t  \n        switch(inputsection)\n          {\n          case 0:\n            // version number\n            in >> version;\n            cout << \"Version number \" << version << endl;\n            if(version != \"1.1\" && version != \"2\" && version != \"2.0\")\n              {\n                cerr << \"WARNING: import only tested for versions 1.1 and 2\" << endl;\n                //done = true;\n              }\n            userdata_double.Append(atof(version.c_str()));\n            break;\n\n          case 1:\n            // unit code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL)\n            in >> unitcode;\n            cout << \"unit code \" << unitcode << endl;\n            userdata_int.Append(unitcode);\n            break;\n\n          case 2:\n            // Geometric coord \"zero\" tolerance threshold\n            in >> tolerance;\n            cout << \"tolerance \" << tolerance << endl;\n            userdata_double.Append(tolerance);\n            break;\n\n          case 3:\n            // Periodic UnitCell dS1 , dS2 , alphaDeg\n            in >> dS1 >> dS2 >> alphaDeg;\n            userdata_double.Append(dS1);\n            userdata_double.Append(dS2);\n            userdata_double.Append(alphaDeg);\n            break;\n\n          case 4:\n            // Periodic UnitCell origin in global coords (x3D,y3D,z3D)\n            in >> x3D >> y3D >> z3D;\n            userdata_double.Append(x3D);\n            userdata_double.Append(y3D);\n            userdata_double.Append(z3D);\n            break;\n\n          case 5:\n            // Model entity count: Vertices, Edges, Faces, Cells (Version 2)\n            in >> modelverts >> modeledges >> modelfaces >> modelcells;\n            userdata_int.Append(modelverts);\n            userdata_int.Append(modeledges);\n            userdata_int.Append(modelfaces);\n            userdata_int.Append(modelcells);\n            break;\n\n          case 6:\n            // Topological mesh-entity counts (#elements,#faces,#edges,#nodes)\n            in >> nelts >> nfaces >> nedges >> nnodes;\n            cout << nelts << \" elements, \" << nfaces << \" faces, \" << nedges << \" edges, \" << nnodes << \" nodes\" << endl;\n            mesh.SetAllocSize(nnodes,2*nedges,nfaces,nelts);\n            break;\n\n          case 7:\n            // NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PMinion 3=CPMaster 4=CPMinion), PID:\n            {\n              cout << \"read nodes\" << endl;\n              for(int i=0; i<nnodes; i++)\n                {\n                  in >> nodeid >> p.X() >> p.Y() >> p.Z() >> type >> pid;\n                  mesh.AddPoint(p);\t\t  \n                  point_pids.Append(pid);\n                  if(pid > maxId0D)\n                    maxId0D = pid;\n                  //(*testout) << \"point \" << p << \" type \" << type << \" mastersexist \" << mastersexist << endl;\n                }\n            }\n            break;\n\n          case 8:\n            // Number of Periodic Master Nodes\n            in >> nperiodicmasternodes;\n            break;\n\n          case 9:\n            // MasterNodeID, MinionNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2)\n            for(int i=0; i<nperiodicmasternodes; i++)\n              {\n                for(int j=0; j<2; j++)\n                  in >> dummyint;\n\n                in >> dummyint;\n              }\n            break;\n\n          case 10:\n            // Number of Corner Periodic Master Nodes\n            in >> ncornerperiodicmasternodes;\n            break;\n\n          case 11:\n            // MasterNodeID, 3-MinionNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2)\n            for(int i=0; i<ncornerperiodicmasternodes; i++)\n              {\n                for(int j=0; j<4; j++)\n                  in >> dummyint;\n\n                for(int j=0; j<3; j++)\n                  in >> dummyint;\n              }\n            break;\n\n          case 12:\n            // Number of Cubic Periodic Master Nodes\n            in >> ncubicperiodicmasternodes;\n            break;\n\n          case 13:\n            //MasterNodeID, 7-MinionNodeID's, TranslCodes\n            for(int i=0; i<ncubicperiodicmasternodes; i++)\n              {\n                for(int j=0; j<8; j++)\n                  in >> dummyint;\n\n                for(int j=0; j<7; j++)\n                  in >> dummyint;\n              }\n            break;\n\n          case 14:\n            // EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PMinion 3=CPMaster 4=CPMinion), PID\n            cout << \"read edges\" << endl;\n            // nullstarted = false;\n            segmentdata.SetSize(nedges);\n            for(int i=0; i<nedges; i++)\n              {\n                segmentdata[i] = new NgArray<int>(7);\n                *segmentdata[i] = -1;\n                in >> dummyint;\n                in >> (*segmentdata[i])[0] >> (*segmentdata[i])[1];\n                in >> type;\n                in >> (*segmentdata[i])[2];\n                if((*segmentdata[i])[2] > maxId1D)\n                  maxId1D = (*segmentdata[i])[2];\n              }\n            break;\n\n          case 15:\n            // Number of Periodic Master Edges\n            in >> nperiodicmasteredges;\n            break;\n\n          case 16:\n            // MasterEdgeID, MinionEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2)\n            for(int i=0; i<nperiodicmasteredges; i++)\n              in >> dummyint >> dummyint >> dummyint;\n            break;\n\n          case 17:\n            // Number of Corner Periodic Master Edges\n            in >> ncornerperiodicmasteredges;\n            break;\n\n          case 18:\n            // MasterEdgeID, 3 MinionEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2)\n            for(int i=0; i<ncornerperiodicmasteredges; i++)\n              {\n                in >> dummyint;\n                for(int j=0; j<3; j++)\n                  in >> dummyint;\n                for(int j=0; j<3; j++)\n                  in >> dummyint;\n              }\n            break;\n\n          case 19:\n            // FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PMinion), PID\n            {\n              //Segment seg;\n              int segnum_ng[3];\n              bool neg[3];\n              cout << \"read faces\" << endl;\n              // nullstarted = false;\n              for(int i=0; i<nfaces; i++)\n                {\n                  int trinum;\n                  int segnum;\n\t\t    \n                  tris.Append(new Element2d(TRIG));\n\n                  in >> trinum;\n                  for(int j=0; j<3; j++)\n                    {\n                      in >> segnum;\n                      neg[j] = (segnum<0);\n                      if(!neg[j])\n                        segnum_ng[j] = segnum-1;\n                      else\n                        segnum_ng[j] = -segnum-1;\n\t\t\t\n                      if(neg[j])\n                        tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[1];\n                      else\n                        tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[0];\n\n                      tris.Last()->GeomInfoPi(j+1).trignum = trinum;\n                    }\n                  in >> type;\n                  int faceid;\n                  in >> faceid;\n\t\t    \n                  if(faceid > maxId2D)\n                    maxId2D = faceid;\n\n                  if(i==0 || faceid < minId2D)\n                    minId2D = faceid;\n\t\t    \n                  tris.Last()->SetIndex(faceid);\n\n                  if(faceid > 0)\n                    {\n                      //if(nullstarted)\n                      //  {\n                      //    cout << \"Faces: Assumption about index 0 wrong (face\"<<trinum <<\")\" << endl;\n                      //  }\n                      //mesh.AddSurfaceElement(tri);\n\t\t\t\n                      for(int j=0; j<3; j++)\n                        {\n                          if(neg[j])\n                            {\n                              (*segmentdata[segnum_ng[j]])[4] = faceid;\n                              (*segmentdata[segnum_ng[j]])[6] = trinum;\n                            }\n                          else\n                            {\n                              (*segmentdata[segnum_ng[j]])[3] = faceid;\n                              (*segmentdata[segnum_ng[j]])[5] = trinum;\n                            }\n                        }\n                    }\n                  // else\n                  //   nullstarted = true;\n                }\n            }\n            break;\n\n          case 20:\n            // Number of Periodic Master Faces\n            in >> nperiodicmasterfaces;\n            break;\n\n          case 21:\n            // MasterFaceID, MinionFaceID, TranslCode (1=dS1 2=dS2)\n            {\n              Vec<3> randomvec(-1.32834,3.82399,0.5429151);\n              int maxtransl = -1;\n              for(int i=0; i<nperiodicmasterfaces; i++)\n                {\n                  int tri1,tri2,transl;\n                  NgArray<PointIndex> nodes1(3),nodes2(3);\n                  NgArray<double> sortval1(3),sortval2(3);\n                  in >> tri1 >> tri2 >> transl;\n\n                  if(transl > maxtransl)\n                    maxtransl = transl;\n\t\t    \n\t\t    \n                  for(int j=0; j<3; j++)\n                    {\n                      nodes1[j] = tris[tri1-1]->PNum(j+1);\n                      sortval1[j] = Vec<3>(mesh[nodes1[j]])*randomvec;\n                      nodes2[j] = tris[tri2-1]->PNum(j+1);\n                      sortval2[j] = Vec<3>(mesh[nodes2[j]])*randomvec;\n                    }\n\n                  BubbleSort(sortval1,nodes1);\n                  BubbleSort(sortval2,nodes2);\n\n                  for(int j=0; j<3; j++)\n                    mesh.GetIdentifications().Add(nodes1[j],nodes2[j],transl);\n\t\t\t\n                }\n              for(int i=1; i<= maxtransl; i++)\n                mesh.GetIdentifications().SetType(i,Identifications::PERIODIC);\n            }\t      \n            break;\n\n          case 22:\n            // ElemID, FaceID0, FaceID1, FaceID2, FaceID3, PID\n            {\n              cout << \"read elements (1)\" << endl;\n\n              //SurfaceElementIndex surf[4];\n              bool neg[4];\n              int elemid;\n              int domain;\n\t\t\n              eldom.SetSize(nelts);\n\n              for(int i=0; i<nelts; i++)\n                {\n                  if(int(100.*i/nelts) % 5 == 0)\n                    cout << int(100.*i/nelts)\n#ifdef WIN32\n                         << \"%%\\r\"\n#else\n                         << \"%\\r\"\n#endif \n                         << flush;\n                  in >> elemid;\n                  for(int j=0; j<4;j++)\n                    {\n                      in >> dummyint;\n                      neg[j] = (dummyint < 0);\n                      if(neg[j])\n                        tetfacedata.Append(-dummyint-1);\n                      //surf[j] = -dummyint-1;\n                      else\n                        tetfacedata.Append(dummyint-1);\n                      tetfacedata.Append(((neg[j]) ? 1 : 0));\n                      //surf[j] = dummyint-1;\n                    }\n\t\t    \n                  in >> domain;\n                  eldom[i] = domain;\n                  tetfacedata.Append(domain);\n\n                  if(i==0 || domain < minId3D)\n                    minId3D = domain;\n\n                  if(domain > maxId3D)\n                    maxId3D = domain;\n\t\t    \n                  // \t\t    for(int j=0; j<4; j++)\n                  // \t\t      {\n                  // \t\t\tif(mesh.GetNSE() <= surf[j])\n                  // \t\t\t  continue;\n\n                  // \t\t\tint faceind = 0;\n                  // \t\t\tfor(int k=1; k<=mesh.GetNFD(); k++)\n                  // \t\t\t  {\n                  // \t\t\t    if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf[j]].GetIndex())\n                  // \t\t\t      faceind = k;\n                  // \t\t\t  }\n                  // \t\t\tif(faceind)\n                  // \t\t\t  {\n                  // \t\t\t    if(neg[j])\n                  // \t\t\t      mesh.GetFaceDescriptor(faceind).SetDomainOut(domain);\n                  // \t\t\t    else\n                  // \t\t\t      mesh.GetFaceDescriptor(faceind).SetDomainIn(domain);\n                  // \t\t\t  }\n                  // \t\t\telse\n                  // \t\t\t  {\n                  // \t\t\t    if(neg[j])\n                  // \t\t\t      faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),0,domain,0));\n                  // \t\t\t    else\n                  // \t\t\t      faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),domain,0,0));\n                  // \t\t\t    mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf[j]].GetIndex());\n                  // \t\t\t  }\n                  // \t\t      }\n                }\n              cout << endl;\n\t\t\n\t\t\n              // \t\tNgArray<int> indextodescriptor(maxId2D+1);\n\t\t\n              // \t\tfor(int i=1; i<=mesh.GetNFD(); i++)\n              // \t\t  indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i;\n\t\t\n\t\t\n              // \t\tfor(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++)\n              // \t\t  mesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]);\n            }\n            break;\n\n          case 23:\n            // ElemID, NodeID0, NodeID1, NodeID2, NodeID3\n            { \n              cout << \"read elements (2)\" << endl;\n              Element el(TET);\n              for(ElementIndex i=0; i<nelts; i++)\n                {\n                  in >> dummyint;\n                  for(int j=1; j<=4; j++)\n                    in >> el.PNum(j);\n                  swap(el.PNum(1),el.PNum(2));\n\t\t    \n                  el.SetIndex(eldom[i]);\n                  mesh.AddVolumeElement(el);\n                }\t\n            }\t  \n            break;\n\t      \n          case 24:\n            // Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D)\n            {\n              in >> numObj3D;\n              userdata_int.Append(numObj3D);\n              in >> numObj2D;\n              userdata_int.Append(numObj2D);\n              in >> numObj1D;\n              userdata_int.Append(numObj1D);\n              in >> numObj0D;\n              userdata_int.Append(numObj0D);\n            }\n            break;\n\n          case 25:\n            // Number of Ports (Ports are a subset of Object2D list)\n            {\n              in >> dummyint;\n              //userdata_int.Append(dummyint);\n            }\n            break;\n\n          case 26:\n            // Object3D GroupID, #Elems <immediately followed by> ElemID List\n            {\n              uid_to_group_3D.SetSize(maxId3D+1);\n              uid_to_group_3D = -1;\n              for(int i=0; i<numObj3D; i++)\n                {\n                  int groupid;\n                  in >> groupid;\n                  (*testout) << \"3d groupid \" << groupid << endl;\n                  //userdata_int.Append(groupid);\n                  int nelems;\n                  in >> nelems;\n                  //userdata_int.Append(nelems);\n                  for(int j=0; j<nelems; j++)\n                    {\n                      in >> dummyint;\n\t\t\t\n                      (*testout) << \"read \" << dummyint << endl;\n                      //userdata_int.Append(dummyint);\n\t\t\t\n                      if(dummyint < 0) \n                        dummyint *= -1;\n                      uid_to_group_3D[eldom[dummyint-1]] = groupid;\n                    }\n                }\n            }\n            break;\n\n          case 27:\n            // Object2D GroupID, #Faces <immediately followed by> FaceID List\n            {\n              NgArray<int> ports;\n              //int totnum = 0;\n              uid_to_group_2D.SetSize(maxId2D+1);\n              uid_to_group_2D = -1;\n\n              for(int i=0; i<numObj2D; i++)\n                {\n                  int groupid;\n                  in >> groupid;\n                  (*testout) << \"2d groupid \" << groupid << endl;\n                  //userdata_int.Append(groupid);\n                  int nelems;\n                  in >> nelems;\n                  //userdata_int.Append(nelems);\n                  for(int j=0; j<nelems; j++)\n                    {\n                      in >> dummyint;\n                      char port;\n                      while((port = in.get()) == ' ')\n                        ;\n\n                      (*testout) << \"read \" << dummyint << endl;\n                      if(dummyint < 0) \n                        dummyint *= -1;\n                      int uid = tris[dummyint-1]->GetIndex();\n\n                      if(port == 'P' || port == 'p')\n                        {\n                          if(!ports.Contains(uid))\n                            ports.Append(uid);\n                        }\n                      else\n                        in.putback(port);\n\t\t\t\n                      //userdata_int.Append(dummyint);\n\t\t\t\n                      uid_to_group_2D[uid] = groupid;\n                      (*testout) << \"setting \" << uid << endl;\n\n                      //totnum++;\n                    }\n                }\n              mesh.SetUserData(\"TETmesh:ports\",ports);\n            }\n            break;\n\n          case 28:\n            // Object1D GroupID, #Edges <immediately followed by> EdgeID List\n            {\n              uid_to_group_1D.SetSize(maxId1D+1);\n              uid_to_group_1D = -1;\n\n              for(int i=0; i<numObj1D; i++)\n                {\n                  int groupid;\n                  in >> groupid;\n                  //userdata_int.Append(groupid);\n                  int nelems;\n                  in >> nelems;\n                  //userdata_int.Append(nelems);\n                  for(int j=0; j<nelems; j++)\n                    {\n                      in >> dummyint;\n                      //userdata_int.Append(dummyint);\n\n                      if(dummyint < 0) \n                        dummyint *= -1;\n                      uid_to_group_1D[(*segmentdata[dummyint-1])[2]] = groupid;\n                    }\n                }\n            }\n            break;\n\n          case 29:\n            // Object0D GroupID, #Nodes <immediately followed by> NodeID List\n            {\n              uid_to_group_0D.SetSize(maxId0D+1);\n              uid_to_group_0D = -1;\n              for(int i=0; i<numObj0D; i++)\n                {\n                  int groupid;\n                  in >> groupid;\n                  //userdata_int.Append(groupid);\n                  int nelems;\n                  in >> nelems;\n                  //userdata_int.Append(nelems);\n                  for(int j=0; j<nelems; j++)\n                    {\n                      in >> dummyint;\n                      //userdata_int.Append(dummyint);\n\n                      if(dummyint < 0) \n                        dummyint *= -1;\n                      uid_to_group_0D[point_pids[dummyint-1]] = groupid;\n                    }\n                }\n            }\n            break;\n\n\n\n          default:\n            done = true;\n\t      \n          }\n\t  \n        if(inputsection == 4 && version == \"1.1\")\n          inputsection++;\n\n        inputsection++;\n      }\n    in.close();\n\n\n    mesh.SetUserData(\"TETmesh:double\",userdata_double);\n    userdata_int.Append(minId2D);\n    userdata_int.Append(minId3D);\n    mesh.SetUserData(\"TETmesh:int\",userdata_int);   \n    //if(version == \"1.1\")\n    mesh.SetUserData(\"TETmesh:point_id\",point_pids);\n\n    mesh.SetUserData(\"TETmesh:uid_to_group_3D\",uid_to_group_3D);\n    mesh.SetUserData(\"TETmesh:uid_to_group_2D\",uid_to_group_2D);\n    mesh.SetUserData(\"TETmesh:uid_to_group_1D\",uid_to_group_1D);\n    mesh.SetUserData(\"TETmesh:uid_to_group_0D\",uid_to_group_0D);\n\n\n    NgArray<SurfaceElementIndex> surfindices(tris.Size());\n    surfindices = -1;\n\n    for(int i=0; i<tris.Size(); i++)\n      {\n        if(atof(version.c_str()) <= 1.999999)\n          {\n            if(tris[i]->GetIndex() > 0)\n              surfindices[i] = mesh.AddSurfaceElement(*tris[i]);\n          }\n        else\n          {\n            if(tris[i]->GetIndex() > 0 &&\n               tris[i]->GetIndex() < minId3D)\n              {\n                tris[i]->SetIndex(tris[i]->GetIndex()-minId2D+1);\n                surfindices[i] = mesh.AddSurfaceElement(*tris[i]);\n              }\n          }\n        delete tris[i];\n      }\n\n      \n    mesh.ClearFaceDescriptors();\n    if(atof(version.c_str()) <= 1.999999)\n      for(int i = 1; i <= maxId2D; i++)\n        mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0));\n    else\n      for(int i=minId2D; i<minId3D; i++)\n        mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0));\n\t\n\n    for(int i=0; i<tetfacedata.Size(); i+=9)\n      {\n        for(int j=0; j<4; j++)\n          {\n            SurfaceElementIndex surf = surfindices[tetfacedata[i+2*j]];\n\t      \n            //if(mesh.GetNSE() <= surf)\n            if(surf == -1)\n              continue;\n\n            if(tetfacedata[i+2*j+1] == 1)\n              mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainOut(tetfacedata[i+8]);\n            else\n              mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainIn(tetfacedata[i+8]);\n\t\t\t\n\n            /*\n\t      int faceind = 0;\n\t      for(int k=1; k<=mesh.GetNFD(); k++)\n              {\n              if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf].GetIndex())\n              faceind = k;\n              }\n\t      if(faceind)\n              {\n              if(tetfacedata[i+4+j] == 1)\n              mesh.GetFaceDescriptor(faceind).SetDomainOut(tetfacedata[i+8]);\n              else\n              mesh.GetFaceDescriptor(faceind).SetDomainIn(tetfacedata[i+8]);\n              }\n\t      else\n              {\n              if(tetfacedata[i+4+j] == 1)\n              faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),0,tetfacedata[i+8],0));\n              else\n              faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),tetfacedata[i+8],0,0));\n              mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf].GetIndex());\n              }\n            */\n          }\n\n      }\n      \n    //       NgArray<int> indextodescriptor(maxId2D+1);\n\t\t\n    //       for(int i=1; i<=mesh.GetNFD(); i++)\n    // \tindextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i;\n\t\t\n\t\t\n    //       for(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++)\n    // \tmesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]);\n\n\n    for(int i=0; i<segmentdata.Size(); i++)\n      {\n        Segment seg;\n\n\t  \n        if((atof(version.c_str()) <= 1.999999 && (*segmentdata[i])[2] > 0) ||\n           (atof(version.c_str()) > 1.999999  && (*segmentdata[i])[2] > 0 && (*segmentdata[i])[2] < minId2D))\n          {\n            seg[0] = (*segmentdata[i])[0];\n            seg[1] = (*segmentdata[i])[1];\n            seg.edgenr = (*segmentdata[i])[2];\n            seg.epgeominfo[0].edgenr = (*segmentdata[i])[2];\n            seg.epgeominfo[1].edgenr = (*segmentdata[i])[2];\n            seg.si = (*segmentdata[i])[3]-minId2D+1;\n            seg.surfnr1 = -1;//(*segmentdata[i])[3];\n            seg.surfnr2 = -1;//(*segmentdata[i])[4];\n            seg.geominfo[0].trignum = (*segmentdata[i])[5];\n            seg.geominfo[1].trignum = (*segmentdata[i])[5];\n            mesh.AddSegment(seg);\n\n            seg[0] = (*segmentdata[i])[1];\n            seg[1] = (*segmentdata[i])[0];\n            seg.si = (*segmentdata[i])[4]-minId2D+1;\n            seg.surfnr1 = -1;//(*segmentdata[i])[3];\n            seg.surfnr2 = -1;//(*segmentdata[i])[4];\n            seg.geominfo[0].trignum = (*segmentdata[i])[6];\n            seg.geominfo[1].trignum = (*segmentdata[i])[6];\n            mesh.AddSegment(seg);\n          }\n        delete segmentdata[i];\n      }\n\n    /*\n      for(int i=mesh.GetNSeg(); i>=1; i--)\n      if(mesh.LineSegment(i).epgeominfo[0].edgenr == 0 ||\n      mesh.LineSegment(i).epgeominfo[1].edgenr == 0)\n      mesh.FullDeleteSegment(i);\n    */\t\n  \n    mesh.CalcSurfacesOfNode();\n      \n  }\n}\n\n\n"
  },
  {
    "path": "libsrc/interface/readuser.cpp",
    "content": "//\n//  Read user dependent output file\n//\n\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n#include <meshing.hpp>\n#include <algorithm>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n  extern void ReadTETFormat (Mesh & mesh, const filesystem::path & filename);\n  extern void ReadFNFFormat (Mesh & mesh, const filesystem::path & filename);\n#ifdef NG_CGNS\n  extern void ReadCGNSMesh (Mesh & mesh, const filesystem::path & filename);\n#endif // NG_CGNS\n\n  void ReadFile (Mesh & mesh,\n                 const filesystem::path & filename)\n  {\n    PrintMessage(3, \"Read User File\");\n\n    auto ext = filename.extension();\n\n    char reco[100];\n    int np, nbe;\n\n\n\n    if ( ext == \".surf\" )\n      {\n        cout << IM(3) << \"Surface file\" << endl;\n      \n        ifstream in (filename);\n      \n        in >> reco;\n        in >> np;\n        for (int i = 1; i <= np; i++)\n          {\n            Point3d p;\n            in >> p.X() >> p.Y() >> p.Z();\n            mesh.AddPoint (p);\n          }\n\n        mesh.ClearFaceDescriptors();\n        mesh.AddFaceDescriptor (FaceDescriptor(1,1,0,0));\n      \n        in >> nbe;\n        //      int invert = globflags.GetDefineFlag (\"invertsurfacemesh\");\n        for (int i = 1; i <= nbe; i++)\n          {\n            Element2d el;\n            el.SetIndex(1);\n\n            for (int j = 1; j <= 3; j++)\n              {\n                in >> el.PNum(j);\n                // el.PNum(j)++;\n                if (el.PNum(j) < PointIndex(1) || \n                    el.PNum(j) > PointIndex(np))\n                  {\n                    cerr << \"Point Number \" << el.PNum(j) << \" out of range 1...\"\n                         << np << endl;\n                    return;\n                  }\n              }\n            /*\n              if (invert)\n              swap (el.PNum(2), el.PNum(3));\n            */\n\t  \n            mesh.AddSurfaceElement (el);\n          }\n      \n      \n        cout << IM(3) << \"points: \" << np << \" faces: \" << nbe << endl;\n      }\n  \n  \n    if ( ext == \".unv\" )\n      {  \n        char reco[100];\n        // int invert;\n\t// read files that are stored with D instead of E as exponent prefix\n\t// such files are for example exported by GMSH\n\tbool Dnotation;\n\tbool DnotationSet = false;\n      \n        ifstream in(filename);\n\n        mesh.ClearFaceDescriptors();\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(1).SetBCProperty (1);\n        // map from unv element nr to our element number + an index if it is vol (0), bnd(1), ...\n        std::map<size_t, std::tuple<size_t, int>> element_map;\n\tint dim = 3;\n\tint bccounter = 0;\n\n        NgArray<Segment> tmp_segments;\n        while (in.good())\n          {\n            in >> reco;\n            if (strcmp(reco, \"-1\") == 0)\n              continue;\n\n            else if (strcmp (reco, \"2411\") == 0)\n              {\n                cout << IM(3) << \"nodes found\" << endl;\n\n                while (1)\n                  {\n                    int pi, hi;\n\t\t    Point<3> p;\n\t\t    string p1tmp, p2tmp, p3tmp;\n\n                    in >> pi;\n                    if (pi == -1)\n                      break;\n\t\t    \n                    in >> hi >> hi >> hi;\n\t\t    // check if D in first line\n\t\t    if (DnotationSet == false) {\n\t\t\tin >> p1tmp >> p2tmp >> p3tmp;\n\t\t\tif (p1tmp.find(\"D\") != std::string::npos){\n\t\t\t    Dnotation = true;\n\t\t\t    cout << IM(3) << \"Attention: in your UNV file, D is used as an exponent prefix instead of E\" << endl;\n\t\t\t    std::replace(p1tmp.begin(), p1tmp.end(), 'D', 'E');\n\t\t\t    std::replace(p2tmp.begin(), p2tmp.end(), 'D', 'E');\n\t\t\t    std::replace(p3tmp.begin(), p3tmp.end(), 'D', 'E');\n\t\t\t}\n\t\t\tp(0) = std::stod(p1tmp);\n\t\t\tp(1) = std::stod(p2tmp);\n\t\t\tp(2) = std::stod(p3tmp);\n\t\t    \tmesh.AddPoint(p);\n\n\t\t\tDnotationSet = true;\n\t\t\tcontinue;\n\t\t    }\n\n\t\t    if (Dnotation == true) {\n\t\t        in >> p1tmp >> p2tmp >> p3tmp;\n\t\t\tstd::replace(p1tmp.begin(), p1tmp.end(), 'D', 'E');\n\t\t\tstd::replace(p2tmp.begin(), p2tmp.end(), 'D', 'E');\n\t\t\tstd::replace(p3tmp.begin(), p3tmp.end(), 'D', 'E');\n\t\t\tp(0) = std::stod(p1tmp);\n\t\t\tp(1) = std::stod(p2tmp);\n\t\t\tp(2) = std::stod(p3tmp);\n\t\t    }\n\t\t    else{\n\t\t\tin >> p(0) >> p(1) >> p(2);\n\t\t    }\n\t\t    mesh.AddPoint(p);\n                  }\n\t\tcout << IM(3) << \"read \" << mesh.GetNP() << \" points\" << endl;\n                Point3d pmin, pmax;\n\t\tcout << IM(5) << \"Get Box\" << endl;\n                mesh.GetBox (pmin, pmax);\n\t\tcout << IM(5)  << \"Pmin: \" << pmin << \" Pmax: \" << pmax << endl;\n                if(fabs(pmin.Z() - pmax.Z()) < 1e-10 * Dist(pmin, pmax))\n                {\n                       cout << IM(5)  << \"Set Dimension to 2.\" << endl;\n                       mesh.SetDimension(2);\n                       dim = 2 ;\n\t\t}\n\n              }\n\n            else if (strcmp (reco, \"2412\") == 0)\n              {\n                cout << IM(3)  << \"elements found\" << endl;\n\n                while (1)\n                  {\n\t\t    int label, fe_id, phys_prop, mat_prop, color, nnodes;\n\t\t    int nodes[100];\n\t\t    int hi;\n\n\t\t    in >> label;\n\t\t    if (label == -1) break;\n\t\t    in >> fe_id >> phys_prop >> mat_prop >> color >> nnodes;\n\t\t    \n\t\t    if (fe_id >= 11 && fe_id <= 32)\n\t\t      in >> hi >> hi >> hi;\n\t\t      \n\n\t\t    for (int j = 0; j < nnodes; j++)\n\t\t      in >> nodes[j];\n\t\t    \n\t\t    switch (fe_id)\n\t\t      {\n                      case 11: // (Rod) SEGM\n                        {\n                          Segment el;\n                          el[0] = nodes[0];\n                          el[1] = nodes[1];\n                          el[2] = -1;\n\n                          if(dim == 3){\n                            auto nr = tmp_segments.Size();\n                            tmp_segments.Append(el);\n                            element_map[label] = std::make_tuple(nr+1, 2);\n                          }\n                          else if(dim == 2){\n\t\t            el.si = -1; // add label to segment, will be changed later when BC's are assigned\n                            auto nr = mesh.AddSegment(el);\n                            element_map[label] = std::make_tuple(nr+1, 2);\n                          }\n                          break;\n                        }\n\n                      case 22: // (Tapered beam) SEGM\n                        {\n                          Segment el;\n                          el[0] = nodes[0];\n                          el[1] = nodes[2];\n                          el[2] = nodes[1];\n                          \n                          if(dim == 3){\n                            auto nr = tmp_segments.Size();\n                            tmp_segments.Append(el);\n                            element_map[label] = std::make_tuple(nr+1, 2);\n                          }\n                          else if(dim == 2){\n\t\t            el.si = -1; // add label to segment, will be changed later when BC's are assigned\n                            auto nr = mesh.AddSegment(el);\n                            element_map[label] = std::make_tuple(nr+1, 2);\n                          }\n\n                          break;\n                        }\n\t\t      case 41: // TRIG\n\t\t\t{\n\t\t\t  Element2d el (TRIG);\n\t\t\t  el.SetIndex (1);\n\t\t\t  for (int j = 0; j < nnodes; j++)\n\t\t\t    el[j] = nodes[j];\n\t\t\t  auto nr = mesh.AddSurfaceElement (el);\n                          element_map[label] = std::make_tuple(nr+1, 1);\n\t\t\t  break;\n\t\t\t}\n                      case 42: // TRIG6\n                        {\n                          Element2d el(TRIG6);\n                          el.SetIndex(1);\n                          int jj = 0;\n                          for(auto j : {0,2,4,3,5,1})\n                              el[jj++] = nodes[j];\n                          auto nr = mesh.AddSurfaceElement(el);\n                          element_map[label] = std::make_tuple(nr+1, 1);\n                          break;\n                        }\n\t\t      case 111: // TET\n\t\t\t{\n\t\t\t  Element el (TET);\n\t\t\t  el.SetIndex (1);\n\t\t\t  for (int j = 0; j < nnodes; j++)\n\t\t\t    el[j] = nodes[j];\n\t\t\t  auto nr = mesh.AddVolumeElement (el);\n\t\t\t  element_map[label] = std::make_tuple(nr+1, 0);\n\t\t\t  break;\n\t\t\t}\n                      case 118: // TET10\n                        {\n                          Element el(TET10);\n                          el.SetIndex(1);\n                          int jj = 0;\n                          for(auto j : {0,2,4,9,1,5,6,3,7,8})\n                            el[jj++] = nodes[j];\n                          auto nr = mesh.AddVolumeElement(el);\n                          element_map[label] = std::make_tuple(nr+1, 0);\n                          break;\n                        }\n                      default:\n                        cout << IM(3)  << \"Do not know fe_id = \" << fe_id << \", skipping it.\" << endl;\n                        break;\n\t\t      }\n                  }\n                cout << IM(3)  << mesh.GetNE() << \" elements found\" << endl;\n                cout << IM(3)  << mesh.GetNSE() << \" surface elements found\" << endl;\n\n              }\n            else if(strcmp (reco, \"2467\") == 0)\n              {\n                int matnr = 1;\n                cout << IM(3)  << \"Groups found\" << endl;\n                while(in.good())\n                  {\n                    int len;\n                    string name;\n                    in >> len;\n                    if(len == -1)\n                      break;\n                    for(int i=0; i < 7; i++)\n                      in >> len;\n                    in >> name;\n                    cout << IM(3)  << len << \" element are in group \" << name << endl;\n                    int hi, index;\n                    int fdnr=-1, ednr=-1;\n\n                    in >> hi >> index >> hi >> hi;\n                    int codim = get<1>(element_map[index]);\n                    // use first element to determine if boundary or volume\n                    \n                    switch (codim)\n                      {\n                      case 0:\n                        {\n                          mesh.SetMaterial(++matnr, name);\n                          mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr);\n                          break;\n                        }\n                      case 1:\n                        {\n                          if(dim == 3)\n                          {\n                            int bcpr = mesh.GetNFD();\n                            fdnr = mesh.AddFaceDescriptor(FaceDescriptor(bcpr, 0,0,0));\n                            mesh.GetFaceDescriptor(fdnr).SetBCProperty(bcpr+1);\n                            mesh.SetBCName(bcpr, name);\n                            mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr);\n                            bccounter++;\n                          }\n                          else if(dim == 2)\n                          {\n                            mesh.SetMaterial(matnr, name);\n                            fdnr = mesh.AddFaceDescriptor(FaceDescriptor(matnr, 0,0,0));\n                            mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(matnr);\n                            mesh.GetFaceDescriptor(fdnr).SetBCProperty(matnr);\n\t\t\t    matnr++;\n                          }\n                          break;\n\n                        }\n                      case 2:\n                        {\n                         if(dim == 3)\n                          {\n                            int bcpr = mesh.GetNCD2Names()+1;\n                            auto ed = EdgeDescriptor();\n                            ed.SetSurfNr(0,bcpr);//?\n                            ednr = mesh.AddEdgeDescriptor(ed);\n                            mesh.SetCD2Name(bcpr, name);\n                            auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]);\n                            mesh[nr].edgenr = ednr+1;\n                          }\n                          else if(dim == 2)\n                          {\n                            Segment & seg = mesh.LineSegment(get<0>(element_map[index]));\n\t\t\t    seg.si = bccounter + 1;\n\t\t\t    mesh.SetBCName(bccounter, name);\n\t\t            bccounter++;\n                          }\n                          break;\n\n                        }\n                      default:\n                        {\n                          cout << IM(3)  << \"Codim \" << codim << \" not implemented yet!\" << endl;\n                        }\n                      }\n                        \n                    for(int i=0; i<len-1; i++)\n                      {\n                        in >> hi >> index >> hi >> hi;\n                        switch (codim)\n                          {\n                          case 0:\n                            mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr);\n                            break;\n                          case 1:\n\t\t\t    if(dim == 3) mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr);\n\t\t\t    else if (dim == 2){\n                                    mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(matnr-1);\n\t\t\t\t    mesh.GetFaceDescriptor(fdnr).SetBCProperty(matnr);\n\t\t\t    }\n                            break;\n                          case 2:\n\t   \t\t    if(dim == 3)\n                            {\n                              auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]);\n                              mesh[nr].edgenr = ednr+1;\n                            }\n\t\t\t    else if(dim == 2)\n\t\t\t    {\n\t \t\t\t    Segment & seg = mesh.LineSegment(get<0>(element_map[index]));\n\t\t\t            seg.si = bccounter;\n\t\t\t    }\n                            break;\n                          default:\n                            break;\n                          }\n                      }\n                  }\n              }\n            else\n              {\n                cout << IM(3)  << \"Do not know data field type \" << reco << \", skipping it\" << endl;\n                while(in.good())\n                  {\n                    in >> reco;\n                    if(strcmp(reco, \"-1\") == 0)\n                      break;\n                  }\n              }\n          }\n\n\tif(dim == 2){\n\t\t// loop through segments to assign default BC to unmarked edges\n\t\tint bccounter_tmp = bccounter;\n\t\tfor(int index=1; index <= mesh.GetNSeg(); index++){\n                \tSegment & seg = mesh.LineSegment(index);\n\t\t\tif(seg.si == -1){\n\t\t\t  seg.si = bccounter + 1;\n\t\t\t  if(bccounter_tmp == bccounter) mesh.SetBCName(bccounter, \"default\"); // could be more efficient\n\t\t\t  bccounter_tmp++;\n\t\t\t}\n\t\t}\n\t\tif(bccounter_tmp > bccounter) bccounter++;\n\t}\n      \n\n\tcout << IM(5)  << \"Finalize mesh\" << endl;\n        Point3d pmin, pmax;\n\tcout << IM(5)  << \"ComputeNVertices\" << endl;\n        mesh.ComputeNVertices();\n\tcout << IM(5)  << \"RebuildSurfaceElementLists\" << endl;\n        mesh.RebuildSurfaceElementLists();\n\tcout << IM(5)  << \"GetBox\" << endl;\n        mesh.GetBox (pmin, pmax);\n\tcout << IM(5)  << \"UpdateTopology\" << endl;\n        mesh.UpdateTopology();\n\tcout << IM(5)  << \"increment bccounter\" << endl;\n        if(dim == 3) bccounter++;\n        cout << IM(5)  << \"bounding-box = \" << pmin << \"-\" << pmax << endl;\n\tcout << IM(5)  << \"Created \" << bccounter << \" boundaries.\" << endl;\n\tfor(int i=0; i<bccounter; i++){\n\t\tcout << IM(5)  << mesh.GetBCName(i) << endl;\n\t}\n      }\n\n\n\n    // fepp format2d:\n  \n    if ( ext == \".mesh2d\" )\n      {\n        cout << IM(3)  << \"Reading FEPP2D Mesh\" << endl;\n      \n        char buf[100];\n        int np, ne, nseg, i, j;\n\n        ifstream in (filename);\n\n        in >> buf;\n\n        in >> nseg;\n        for (i = 1; i <= nseg; i++)\n          {\n            int bound, p1, p2;\n            in >> bound >> p1 >> p2;\n            // forget them\n          }\n\n        in >> ne;\n        for (i = 1; i <= ne; i++)\n          {\n            int mat, nelp;\n            in >> mat >> nelp;\n            Element2d el (nelp == 3 ? TRIG : QUAD);\n            el.SetIndex (mat);\n            for (j = 1; j <= nelp; j++)\n              in >> el.PNum(j);\n            mesh.AddSurfaceElement (el);\n          }\n\n        in >> np;\n        for (i = 1; i <= np; i++)\n          {\n            Point3d p(0,0,0);\n            in >> p.X() >> p.Y();\n            mesh.AddPoint (p);\n          }\n      }\n\n  \n    else if ( ext == \".mesh\" )\n      {\n        cout << IM(3)  << \"Reading Neutral Format\" << endl;\n      \n        int np, ne, nse, i, j;\n\n        ifstream in (filename);\n\n        in >> np;\n\n        if (in.good())\n          {\n            // file starts with an integer\n\n            for (i = 1; i <= np; i++)\n              {\n                Point3d p(0,0,0);\n                in >> p.X() >> p.Y() >> p.Z();\n                mesh.AddPoint (p);\n              }\n\t  \n            in >> ne;\n            for (i = 1; i <= ne; i++)\n              {\n                int mat;\n                in >> mat;\n                Element el (4);\n                el.SetIndex (mat);\n                for (j = 1; j <= 4; j++)\n                  in >> el.PNum(j);\n                mesh.AddVolumeElement (el);\n              }\n\n            mesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));\n            int nfd = 1;\n\n            in >> nse;\n            for (i = 1; i <= nse; i++)\n              {\n                int mat; // , nelp;\n                in >> mat;\n                Element2d el (TRIG);\n                el.SetIndex (mat);\n                while(nfd<mat)\n                  {\n                    ++nfd;\n                    mesh.AddFaceDescriptor(FaceDescriptor(nfd,nfd,0,0));\n                  }\n                for (j = 1; j <= 3; j++)\n                  in >> el.PNum(j);\n                mesh.AddSurfaceElement (el);\n              }\n          }\n        else\n          {\n            char buf[100];\n            in.clear();\n            do\n              {\n                in >> buf;\n                cout << IM(5)  << \"buf = \" << buf << endl;\n                if (strcmp (buf, \"points\") == 0)\n                  {\n                    in >> np;\n                    cout << IM(5)  << \"np = \" << np << endl;\n                  }\n              }\n            while (in.good());\n          }\n      }\n\n\n    if ( ext == \".emt\" )\n      {\n        ifstream inemt (filename);\n      \n        auto pktfile = filename;\n        pktfile.replace_extension(\"pkt\");\n        cout << IM(3) << \"pktfile = \" << pktfile << endl;\n\n        int np, nse, i;\n        int bcprop;\n        ifstream inpkt (pktfile);\n        inpkt >> np;\n        NgArray<double> values(np);\n        for (i = 1; i <= np; i++)\n          {\n            Point3d p(0,0,0);\n            inpkt >> p.X() >> p.Y() >> p.Z()\n                  >> bcprop >> values.Elem(i);\n            mesh.AddPoint (p);\n          }      \n\n        mesh.ClearFaceDescriptors();\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(1).SetBCProperty (1);\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(2).SetBCProperty (2);\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(3).SetBCProperty (3);\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(4).SetBCProperty (4);\n        mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0));\n        mesh.GetFaceDescriptor(5).SetBCProperty (5);\n\n        int p1, p2, p3;\n        double value;\n        inemt >> nse;\n        for (i = 1; i <= nse; i++)\n          {\n            inemt >> p1 >> p2 >> p3 >> bcprop >> value;\n\n            if (bcprop < 1 || bcprop > 4)\n              cerr << \"bcprop out of range, bcprop = \" << bcprop << endl;\n            p1++;\n            p2++;\n            p3++;\n            if (p1 < 1 || p1 > np || p2 < 1 || p2 > np || p3 < 1 || p3 > np)\n              {\n                cout << IM(3)  << \"p1 = \" << p1 << \" p2 = \" << p2 << \" p3 = \" << p3 << endl;\n              }\n\n            if (i > 110354) Swap (p2, p3);\n            if (mesh.Point(p1)(0) < 0.25)\n              Swap (p2,p3);\n\n            Element2d el(TRIG);\n\n            if (bcprop == 1)\n              {\n                if (values.Get(p1) < -69999)\n                  el.SetIndex(1);\n                else\n                  el.SetIndex(2);\n              }\n            else\n              el.SetIndex(3);\n\n\n            el.PNum(1) = p1;\n            el.PNum(2) = p2;\n            el.PNum(3) = p3;\n            mesh.AddSurfaceElement (el);\n          }\n\n\n        ifstream incyl (\"ngusers/guenter/cylinder.surf\");\n        int npcyl, nsecyl; \n        incyl >> npcyl;\n        cout << IM(3) << \"npcyl = \" << npcyl << endl;\n        for (i = 1; i <= npcyl; i++)\n          {\n            Point3d p(0,0,0);\n            incyl >> p.X() >> p.Y() >> p.Z();\n            mesh.AddPoint (p);\n          }\n        incyl >> nsecyl;\n        cout << IM(3) << \"nsecyl = \" << nsecyl << endl;\n        for (i = 1; i <= nsecyl; i++)\n          {\n            incyl >> p1 >> p2 >> p3;\n            p1 += np;\n            p2 += np;\n            p3 += np;\n            Element2d el(TRIG);\n            el.SetIndex(5);\n            el.PNum(1) = p1;\n            el.PNum(2) = p2;\n            el.PNum(3) = p3;\n            mesh.AddSurfaceElement (el);\n          }\n      }\n\n\n    // .tet mesh\n    if ( ext == \".tet\" )\n        ReadTETFormat (mesh, filename);\n\n    // .fnf mesh (FNF - PE neutral format)\n    if ( ext == \".fnf\" )\n        ReadFNFFormat (mesh, filename);\n\n#ifdef NG_CGNS\n    // .cgns file - CFD General Notation System\n    if ( ext == \".cgns\" )\n        ReadCGNSMesh (mesh, filename);\n#endif // NG_CGNS\n\n    if ( ext == \".stl\" || ext == \".stlb\" )\n      {\n        ifstream ist{filename};\n        auto geom = shared_ptr<STLGeometry>(STLGeometry::Load(ist));\n\n        mesh.SetDimension (3);\n\n        auto & points = geom->GetPoints();\n\n        for (auto & p : points)\n          mesh.AddPoint(MeshPoint(p));\n\n        mesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 1));\n\n        for (auto ti : IntRange(geom->GetNT()))\n        {\n          Element2d el(TRIG);\n          for (auto i : IntRange(3))\n            el[i] = int((*geom)[STLTrigId(ti+IndexBASE<netgen::STLTrigId>())][i]);\n\n          el.SetIndex(1);\n\n          mesh.AddSurfaceElement(el);\n        }\n      }\n  }\n\n  void ReadUserFormat(Mesh & mesh, const filesystem::path & filename, const string & format)\n  {\n    if(format == \"\")\n      return ReadFile(mesh, filename);\n\n    if(!UserFormatRegister::HaveFormat(format))\n      throw Exception(\"Unknown format: \" + format);\n\n    const auto entry = UserFormatRegister::Get(format);\n    if(!entry.read)\n      throw Exception(\"Reading format \" + format + \" is not implemented\");\n\n    (*entry.read)(mesh, filename);\n  }\n\nstatic RegisterUserFormat reg_uni (\"Universial Format\", {\".unv\"}, ReadFile, nullopt);\nstatic RegisterUserFormat reg_olaf (\"Olaf Format\", {\".emt\"}, ReadFile, nullopt);\n  \n}\n\n"
  },
  {
    "path": "libsrc/interface/rw_cgns.cpp",
    "content": "#include <meshing.hpp>\n#include \"writeuser.hpp\"\n\n#ifdef NG_CGNS\n#include <variant>\n\n#include <cgnslib.h>\n\nnamespace netgen::cg\n{\n  typedef ngcore::ClosedHashTable<ngcore::IVec<3,size_t>, size_t> PointTable;\n\n  int getDim(ElementType_t type)\n    {\n      switch(type)\n        {\n          case BAR_2:\n          case BAR_3:\n              return 1;\n          case TRI_3:\n          case TRI_6:\n          case QUAD_4:\n          case QUAD_8:\n              return 2;\n          case TETRA_4:\n          case TETRA_10:\n          case PYRA_5:\n          case PYRA_13:\n          case HEXA_8:\n          case HEXA_20:\n          case PENTA_6:\n          case PENTA_15:\n              return 3;\n          default:\n              throw Exception(\"Read CGNS: unknown element type \" + string(cg_ElementTypeName(type)));\n        }\n    }\n\n  Segment ReadCGNSElement1D( ElementType_t type, FlatArray<cgsize_t> verts )\n    {\n      int np;\n      cg_npe(type, &np);\n\n      Segment s;\n      for (auto i : Range(np))\n          s[i] = verts[i];\n      return s;\n    }\n\n  Element2d ReadCGNSElement2D( ElementType_t type, FlatArray<cgsize_t> verts )\n    {\n//       static constexpr int map_tri3[]  = {0,2,1};\n      static constexpr int map_tri6[]  = {0,2,1,3,5,4}; // untested\n//       static constexpr int map_quad4[] = {0,3,2,1};\n      static constexpr int map_quad8[] = {0,3,2,1,4,7,6,5}; // untested\n\n      const int * map = nullptr;\n      switch(type)\n        {\n          case TRI_3:\n//               map = map_tri3;\n              break;\n          case QUAD_4:\n//               map = map_quad4;\n              break;\n          case TRI_6:\n              map = map_tri6;\n              break;\n          case QUAD_8:\n              map = map_quad8;\n              break;\n          default:\n              throw Exception(\"Read CGNS: unknown element type \" + string(cg_ElementTypeName(type)));\n        }\n\n      int np;\n      cg_npe(type, &np);\n\n      Element2d el(np);\n      for (auto i : Range(np))\n          el[i] = verts[i];\n      return el;\n    }\n\n  Element ReadCGNSElement3D( ElementType_t type, FlatArray<cgsize_t> verts )\n    {\n      static constexpr int map_tet4[]   = {0,2,1,3};\n      static constexpr int map_prism6[] = {0,2,1,3,5,4};\n      static constexpr int map_pyra5[]  = {0,3,2,1,4};\n      static constexpr int map_hexa8[]  = {0,3,2,1,4,7,6,5};\n      int np;\n      cg_npe(type, &np);\n\n      const int * map = nullptr;\n      switch(type)\n        {\n          case TETRA_4:\n              map = map_tet4; break;\n          case PYRA_5:\n              map = map_pyra5; break;\n          case PENTA_6:\n              map = map_prism6; break;\n          case HEXA_8:\n              map = map_hexa8; break;\n              // TODO: Second order elements\n          case TETRA_10:\n          case PYRA_13:\n          case HEXA_20:\n          case PENTA_15:\n          default:\n              throw Exception(\"Read CGNS: unknown element type \" + string(cg_ElementTypeName(type)));\n        }\n\n      Element el(np);\n      for (auto i : Range(np))\n          el[i] = verts[map[i]];\n      return el;\n    }\n\n  void WriteCGNSElement( const Segment & el, Array<cgsize_t> & verts )\n    {\n      verts.Append(BAR_2);\n      verts.Append(el[0]);\n      verts.Append(el[1]);\n    }\n\n  void WriteCGNSElement( const Element2d & el, Array<cgsize_t> & verts )\n    {\n      static constexpr int map_tri6[]  = {0,2,1,3,5,4}; // untested\n      static constexpr int map_quad8[] = {0,3,2,1,4,7,6,5}; // untested\n\n      ElementType_t type;\n\n      const int * map = nullptr;\n      switch(el.GetType())\n        {\n          case TRIG:\n              type = TRI_3;\n              break;\n          case QUAD:\n              type = QUAD_4;\n              break;\n          case TRIG6:\n              type = TRI_6;\n              map = map_tri6;\n              break;\n          case QUAD8:\n              type = QUAD_8;\n              map = map_quad8;\n              break;\n              // TODO: Second order elements\n          default:\n              throw Exception(\"Write CGNS: unknown element type \" + ToString(el.GetType()));\n        }\n\n      verts.Append(type);\n\n      for (auto i : Range(el.GetNP()))\n          verts.Append(el[i]);\n    }\n\n  void WriteCGNSElement( const Element & el, Array<cgsize_t> & verts )\n    {\n      static constexpr int map_tet4[]   = {0,2,1,3};\n      static constexpr int map_prism6[] = {0,2,1,3,5,4};\n      static constexpr int map_pyra5[]  = {0,3,2,1,4};\n      static constexpr int map_hexa8[]  = {0,3,2,1,4,7,6,5};\n\n      ElementType_t type;\n\n      const int * map = nullptr;\n      switch(el.GetType())\n        {\n          case TET:\n              map = map_tet4;\n              type = TETRA_4;\n              break;\n          case PYRAMID:\n              type = PYRA_5;\n              map = map_pyra5;\n              break;\n          case PRISM:\n              type = PENTA_6;\n              map = map_prism6;\n              break;\n          case HEX:\n              type = HEXA_8;\n              map = map_hexa8;\n              break;\n              // TODO: Second order elements\n          default:\n              throw Exception(\"Write CGNS: unknown element type \" + ToString(el.GetType()));\n        }\n\n      verts.Append(type);\n\n      for (auto i : Range(el.GetNP()))\n          verts.Append(el[map[i]]);\n    }\n\n  int WriteCGNSRegion( const Mesh & mesh, int dim, int index, int fn, int base, int zone, int ne_before )\n  {\n    int meshdim = mesh.GetDimension();\n    int codim = meshdim-dim;\n\n    if(codim < 0 || codim > 2)\n      return 0;\n\n    // make sure that each material/boundary name is unique\n    string prefix[] = { \"dom_\", \"bnd_\", \"bbnd_\" };\n    string name = prefix[meshdim-dim] + ToString(index) + \"_\";\n\n    if(codim==0) name += mesh.GetMaterial(index+1);\n    if(codim==1) name += *mesh.GetBCNamePtr(index);\n    if(codim==2) name += mesh.GetCD2Name(index);\n\n    int ne = 0;\n    Array<int> data;\n\n    if(dim==3)\n      for(const auto el : mesh.VolumeElements())\n        if(el.GetIndex()==index)\n        {\n          ne++;\n          WriteCGNSElement(el, data);\n        }\n\n    if(dim==2)\n      for(const auto el : mesh.SurfaceElements())\n        if(el.GetIndex()==index)\n        {\n          ne++;\n          WriteCGNSElement(el, data);\n        }\n\n    if(dim==1)\n      for(const auto el : mesh.LineSegments())\n        if(el.si==index)\n        {\n          ne++;\n          WriteCGNSElement(el, data);\n        }\n\n    if(ne==0)\n      return 0;\n\n    int section;\n    // int start = 1;\n    // int end = ne;\n#if CGNS_VERSION < 3400\n    cg_section_write(fn,base,zone, name.c_str(), MIXED, ne_before+1, ne_before+ne, 0, &data[0], &section);\n#else\n    cg_poly_section_write(fn,base,zone, name.c_str(), MIXED, ne_before+1, ne_before+ne, 0, &data[0], nullptr, &section);\n#endif\n\n    return ne;\n  }\n\n  // maps cgns node type to ngsolve node type\n  // enum NODE_TYPE { NT_VERTEX = 0, NT_EDGE = 1, NT_FACE = 2, NT_CELL = 3, NT_ELEMENT = 4, NT_FACET = 5 };\n  int getNodeType( GridLocation_t location )\n    {\n      switch(location)\n        {\n          case Vertex:\n              return 0;\n          case CellCenter:\n              return 3;\n          case FaceCenter:\n              return 2;\n          case EdgeCenter:\n              return 1;\n          default:\n              throw Exception(\"Read CGNS: unknown grid location \" + string(cg_GridLocationName(location)));\n        }\n    }\n\n  GridLocation_t getCGNodeType( int node_type )\n  {\n    switch(node_type)\n    {\n      case 0:\n        return Vertex;\n      case 1:\n        return EdgeCenter;\n      case 2:\n        return FaceCenter;\n      case 3:\n        return CellCenter;\n      default:\n        throw Exception(\"Write CGNS: unknown node type \" + ToString(node_type));\n    }\n  }\n\n\n  struct Solution\n    {\n      int fn, base, zone, solution;\n      string name;\n      GridLocation_t location; // solution is defined on either cells, faces, edges or vertices\n      PointSetType_t  point_type;\n      cgsize_t n_points;\n\n      Array<string> field_names;\n      Array<DataType_t> field_datatypes;\n\n      Solution() = default;\n\n      Solution(int fn_, int base_, int zone_, int solution_)\n          : fn(fn_), base(base_), zone(zone_), solution(solution_)\n        {\n          char solname[100];\n          cg_sol_info(fn, base, zone, solution, solname, &location);\n          name = solname;\n          cg_sol_ptset_info(fn, base, zone, solution, &point_type, &n_points);\n\n          int n_fields = 0;\n          cg_nfields(fn, base, zone, solution, &n_fields);\n\n          field_names.SetSize(n_fields);\n          field_datatypes.SetSize(n_fields);\n          for(auto fi : Range(n_fields))\n            {\n              char buf[100];\n              cg_field_info(fn, base, zone, solution, fi+1, &field_datatypes[fi], buf);\n              field_names[fi] = buf;\n            }\n        }\n    };\n\n  struct Zone\n    {\n      ZoneType_t zone_type;\n      int fn, base, zone;\n      int first_index_1d, first_index_2d, first_index_3d;\n      int nv=0, ne_1d=0, ne_2d=0, ne_3d=0;\n\n      Array<string> names_1d, names_2d, names_3d;\n\n      string name;\n      cgsize_t size[3];\n\n      Array<Solution> solutions;\n\n      Zone(int fn_, int base_, int zone_)\n          : fn(fn_), base(base_), zone(zone_)\n        {\n          cg_zone_type(fn, base, zone, &zone_type);\n          char zone_name[100];\n          cg_zone_read(fn,base,zone, zone_name, size);\n          nv = size[0];\n\n          int n_solutions;\n          cg_nsols(fn, base, zone, &n_solutions);\n\n          solutions.SetSize(n_solutions);\n          for(auto si : Range(n_solutions))\n              solutions[si] = Solution{fn, base, zone, si+1};\n        }\n\n      void ReadSolutions( int meshdim, std::vector<string> & sol_names, std::vector<Array<double>> & sol_values, std::vector<int> & sol_locations )\n        {\n          static Timer tall(\"CGNS::ReadSolutions\"); RegionTimer rtall(tall);\n          for (auto & sol : solutions)\n            {\n              for (auto fi : Range(sol.field_names.Size()))\n                {\n                  cgsize_t size = sol.n_points;\n                  size=0; // TODO: check if sol.point_type is a list or range, and handle appropriately\n                  if(size==0)\n                    {\n                      switch(sol.location)\n                        {\n                          case Vertex:\n                              size = nv;\n                              break;\n                          case CellCenter:\n                              size = (meshdim == 3 ? ne_3d : ne_2d);\n                              break;\n                          case FaceCenter:\n                          case IFaceCenter:\n                          case JFaceCenter:\n                          case KFaceCenter:\n                          case EdgeCenter:\n                          default:\n                              throw Exception(\"Read CGNS: unknown grid location \" + string(cg_GridLocationName(sol.location)));\n                        }\n                    }\n\n                  auto values = Array<double>(size);\n\n                  cgsize_t imin = 1UL;\n                  cg_field_read(fn, base, zone, sol.solution, sol.field_names[fi].c_str(), RealDouble, &imin, &size, &values[0]);\n                  sol_names.push_back(sol.field_names[fi]);\n                  sol_values.emplace_back(std::move(values));\n                  sol_locations.push_back(getNodeType(sol.location));\n                }\n            }\n        }\n\n      void ReadMesh( Mesh & mesh, PointTable & point_table )\n        {\n          static Timer tall(\"CGNS::ReadMesh-Zone\"); RegionTimer rtall(tall);\n          static Timer tsection(\"CGNS::ReadMesh-Section\");\n          first_index_1d = mesh.GetRegionNamesCD(2).Size();\n          first_index_2d = mesh.GetRegionNamesCD(1).Size();\n          first_index_3d = mesh.GetRegionNamesCD(0).Size();\n\n          Array<double> x(nv), y(nv), z(nv);\n          cgsize_t imin=1;\n          cg_coord_read(fn,base,zone, \"CoordinateX\", RealDouble, &imin, &nv, &x[0]);\n          cg_coord_read(fn,base,zone, \"CoordinateY\", RealDouble, &imin, &nv, &y[0]);\n          cg_coord_read(fn,base,zone, \"CoordinateZ\", RealDouble, &imin, &nv, &z[0]);\n\n          Array<cgsize_t> point_map(nv);\n\n          for(auto i : Range(nv))\n          {\n            ngcore::IVec<3,size_t> hash = {*reinterpret_cast<size_t*>(&x[i]), *reinterpret_cast<size_t*>(&y[i]), *reinterpret_cast<size_t*>(&z[i])};\n            size_t pi_ng;\n            size_t pos;\n            // check if this point is new\n            if( point_table.PositionCreate (hash, pos) )\n            {\n              pi_ng = mesh.AddPoint( {x[i], y[i], z[i]} );\n              point_table.SetData(pos, pi_ng);\n            }\n            else\n              point_table.GetData(pos, pi_ng);\n\n            point_map[i] = pi_ng;\n          }\n\n          int nsections;\n          cg_nsections(fn, base, zone, &nsections);\n\n          int index_1d = first_index_1d;\n          int index_2d = first_index_2d;\n          int index_3d = first_index_3d;\n\n          for (auto section : Range(1,nsections+1))\n            {\n              RegionTimer rtsection(tsection);\n              char sec_name[100];\n              ElementType_t type;\n              cgsize_t start, end;\n              int nbndry, parent_flag;\n\n              cg_section_read(fn, base, zone, section, sec_name,  &type, &start, &end, &nbndry, &parent_flag);\n              PrintMessage(4, \"Read section \", section, \" with name \", sec_name, \" and element type \", cg_ElementTypeName(type));\n\n              string ngname{sec_name};\n\n              for (char & c : ngname)\n                  if(c==' ')\n                      c = '_';\n\n\n              if(type==MIXED)\n                {\n                  bool have_1d_elements = false;\n                  bool have_2d_elements = false;\n                  bool have_3d_elements = false;\n\n                  cgsize_t nv;\n                  cg_ElementDataSize(fn, base, zone, section, &nv);\n\n                  Array<cgsize_t> vertices(nv);\n#if CGNS_VERSION < 3400\n                  cg_elements_read(fn, base, zone, section, &vertices[0], nullptr);\n#else\n                  cg_poly_elements_read(fn, base, zone, section, &vertices[0], nullptr, nullptr);\n#endif\n\n                  size_t vi = 0;\n                  while(vi<nv)\n                    {\n                      auto type = static_cast<ElementType_t>(vertices[vi++]);\n                      int dim = getDim(type);\n\n                      int np;\n                      cg_npe(type, &np);\n\n                      for (auto & v : vertices.Range(vi, vi+np))\n                        v = point_map[v-1];\n\n                      if(dim==1)\n                        {\n                          if(!have_1d_elements)\n                          {\n                            index_1d++;\n                            have_1d_elements = true;\n                            mesh.AddEdgeDescriptor(EdgeDescriptor{});\n                            names_1d.Append(ngname);\n                          }\n                          auto el = ReadCGNSElement1D(type, vertices.Range(vi, vertices.Size()));\n                          el.si = index_1d;\n                          mesh.AddSegment(el);\n                          vi += el.GetNP();\n                          ne_1d++;\n                        }\n\n                      if(dim==2)\n                        {\n                          if(!have_2d_elements)\n                          {\n                            index_2d++;\n                            have_2d_elements = true;\n                            mesh.AddFaceDescriptor(FaceDescriptor(index_2d, 1, 0, 1));\n                            names_2d.Append(ngname);\n                          }\n                          auto el = ReadCGNSElement2D(type, vertices.Range(vi, vertices.Size()));\n                          el.SetIndex(index_2d);\n                          mesh.AddSurfaceElement(el);\n                          vi += el.GetNP();\n                          ne_2d++;\n                        }\n\n                      if(dim==3)\n                        {\n                          if(!have_3d_elements)\n                          {\n                            index_3d++;\n                            have_3d_elements = true;\n                            names_3d.Append(ngname);\n                          }\n\n                          auto el = ReadCGNSElement3D(type, vertices.Range(vi, vertices.Size()));\n                          el.SetIndex(index_3d);\n                          mesh.AddVolumeElement(el);\n                          vi += el.GetNP();\n                          ne_3d++;\n                        }\n                    }\n                }\n              else\n                {\n                  int dim = getDim(type);\n\n                  cgsize_t nv;\n                  cg_ElementDataSize(fn, base, zone, section, &nv);\n                  int np=0;\n                  cg_npe(type, &np);\n\n                  Array<cgsize_t> vertices(nv);\n                  cg_elements_read(fn, base, zone, section, &vertices[0], nullptr);\n                  for (auto & v : vertices)\n                    v = point_map[v-1];\n                  int ne_section = nv/np;\n\n                  if(dim==1)\n                    {\n                      index_1d++;\n                      mesh.AddEdgeDescriptor(EdgeDescriptor{});\n                      names_1d.Append(ngname);\n                      for(auto i : Range(ne_section))\n                        {\n                          auto el = ReadCGNSElement1D(type, vertices.Range(np*i, np*(i+1)));\n                          el.si = index_1d;\n                          mesh.AddSegment(el);\n                        }\n                      ne_1d += ne_section;\n                    }\n\n                  if(dim==2)\n                    {\n                      index_2d++;\n                      mesh.AddFaceDescriptor(FaceDescriptor(index_2d, 1, 0, 1));\n                      names_2d.Append(ngname);\n                      for(auto i : Range(ne_section))\n                        {\n                          auto el = ReadCGNSElement2D(type, vertices.Range(np*i, np*(i+1)));\n                          el.SetIndex(index_2d);\n                          mesh.AddSurfaceElement(el);\n                        }\n                      ne_2d += ne_section;\n                    }\n\n                  if(dim==3)\n                    {\n                      index_3d++;\n                      names_3d.Append(ngname);\n                      for(auto i : Range(ne_section))\n                        {\n                          auto el = ReadCGNSElement3D(type, vertices.Range(np*i, np*(i+1)));\n                          el.SetIndex(index_3d);\n                          mesh.AddVolumeElement(el);\n                        }\n                      ne_3d += ne_section;\n                    }\n                }\n            }\n\n          mesh.GetRegionNamesCD(2).SetSize(index_1d);\n          mesh.GetRegionNamesCD(1).SetSize(index_2d);\n          mesh.GetRegionNamesCD(0).SetSize(index_3d);\n          mesh.GetRegionNamesCD(2) = nullptr;\n          mesh.GetRegionNamesCD(1) = nullptr;\n          mesh.GetRegionNamesCD(0) = nullptr;\n        }\n\n      void SetNames( Mesh & mesh )\n        {\n          if(mesh.GetDimension() == 2)\n          {\n            for (auto i : Range(names_1d.Size()))\n              mesh.SetBCName(first_index_1d + i, names_1d[i]);\n\n            for (auto i : Range(names_2d.Size()))\n              mesh.SetMaterial(first_index_2d + i +1, names_2d[i]);\n          }\n          else\n          {\n            for (auto i : Range(names_1d.Size()))\n              mesh.SetCD2Name(first_index_1d + i +1, names_1d[i]);\n\n            for (auto i : Range(names_2d.Size()))\n            {\n              mesh.SetBCName(first_index_2d + i, names_2d[i]);\n              mesh.GetFaceDescriptor(first_index_2d + i +1).SetDomainIn(first_index_3d+1);\n            }\n\n            for (auto i : Range(names_3d.Size()))\n              mesh.SetMaterial(first_index_3d + i +1, names_3d[i]);\n          }\n        }\n    };\n}\n\nnamespace netgen\n{\n  int ReadCGNSMesh (Mesh & mesh, const filesystem::path & filename, Array<unique_ptr<cg::Zone>> & zones)\n    {\n      mesh.SetDimension(3);\n      static Timer tall(\"CGNS::ReadMesh\"); RegionTimer rtall(tall);\n      int fn;\n      cg_open(filename.string().c_str(),CG_MODE_READ,&fn);\n\n      int base = 1;\n      int nzones;\n      cg_nzones(fn, base, &nzones);\n\n      int n_vertices = 0;\n      for (auto zi : Range(1, nzones+1))\n      {\n        int size[3];\n        char name[100];\n        cg_zone_read(fn,base,zi, name, size);\n        n_vertices += size[0];\n      }\n\n      cg::PointTable points(2*n_vertices);\n\n      for (auto zi : Range(1, nzones+1))\n        {\n          ZoneType_t zone_type;\n          cg_zone_type(fn, base, zi, &zone_type);\n          if(zone_type != Unstructured )\n            {\n              PrintMessage(2, \"skipping zone with type \", cg_ZoneTypeName(zone_type) );\n              continue;\n            }\n          auto zone = make_unique<cg::Zone>(fn, base, zi);\n          zone->ReadMesh( mesh, points );\n          zones.Append(std::move(zone));\n        }\n\n      if(mesh.GetNE() == 0)\n        mesh.SetDimension(2);\n\n      for (auto & zone : zones)\n        zone->SetNames(mesh);\n\n      mesh.UpdateTopology();\n      const auto & topo = mesh.GetTopology();\n\n      for (auto sei : Range(mesh.SurfaceElements()))\n      {\n        int ei0, ei1;\n        topo.GetSurface2VolumeElement (sei+1, ei0, ei1);\n        auto si = mesh.SurfaceElement(sei).GetIndex();\n        auto & fd = mesh.GetFaceDescriptor(si);\n\n        if(ei0>0)\n        {\n          int i0 = mesh.VolumeElement(ei0).GetIndex();\n          if(fd.DomainIn()!=i0)\n            fd.SetDomainOut(i0);\n        }\n\n        if(ei1>0)\n        {\n          int i1 = mesh.VolumeElement(ei1).GetIndex();\n          if(fd.DomainIn()!=i1)\n            fd.SetDomainOut(i1);\n        }\n      }\n      return fn;\n    }\n\n  void ReadCGNSMesh (Mesh & mesh, const filesystem::path & filename)\n    {\n      Array<unique_ptr<cg::Zone>> zones;\n      int fn = ReadCGNSMesh(mesh, filename, zones);\n      cg_close(fn);\n    }\n\n  // Reads mesh and solutions of .csns file\n  tuple<shared_ptr<Mesh>, vector<string>, vector<Array<double>>, vector<int>> ReadCGNSFile(const filesystem::path & filename, int base)\n    {\n      static Timer tall(\"CGNS::ReadFile\"); RegionTimer rtall(tall);\n\n      auto mesh = make_shared<Mesh>();\n      Array<unique_ptr<cg::Zone>> zones;\n      int fn = ReadCGNSMesh(*mesh, filename, zones);\n\n      std::vector<string> names;\n      std::vector<Array<double>> values;\n      std::vector<int> locations;\n\n      for (auto & zone : zones)\n        zone->ReadSolutions( mesh->GetDimension(), names, values, locations );\n\n      cg_close(fn);\n      return std::make_tuple(mesh, names, values, locations);\n    }\n\n  void WriteCGNSMesh (const Mesh & mesh, int fn, int & base, int & zone)\n    {\n      int dim = mesh.GetDimension();\n      cg_base_write(fn, \"mesh\", dim, dim, &base);\n\n      int nv = static_cast<int>(mesh.GetNV());\n      int ne = mesh.GetNE();\n\n      Array<double> x, y, z;\n      for(auto & p : mesh.Points())\n      {\n        x.Append(p[0]);\n        y.Append(p[1]);\n        z.Append(p[2]);\n      }\n\n      cgsize_t isize[3] = { nv, ne, 0 };\n      cg_zone_write(fn,base, \"mesh\", isize, Unstructured, &zone);\n\n      int coord;\n      cg_coord_write(fn,base,zone, RealDouble, \"CoordinateX\", &x[0], &coord);\n      cg_coord_write(fn,base,zone, RealDouble, \"CoordinateY\", &y[0], &coord);\n      cg_coord_write(fn,base,zone, RealDouble, \"CoordinateZ\", &z[0], &coord);\n\n      int imax3 = 0;\n      for(const auto & el : mesh.VolumeElements())\n        imax3 = max(imax3, el.GetIndex());\n\n      int imax2 = 0;\n      for(const auto & el : mesh.SurfaceElements())\n        imax2 = max(imax2, el.GetIndex());\n\n      int imax1 = 0;\n      for(const auto & el : mesh.LineSegments())\n        imax1 = max(imax1, el.si);\n\n      int ne_written = 0;\n      // int meshdim = mesh.GetDimension();\n\n      for(const auto i : IntRange(imax3))\n        ne_written += cg::WriteCGNSRegion(mesh, 3, i+1, fn, base, zone, ne_written);\n\n      for(const auto i : IntRange(imax2))\n        ne_written += cg::WriteCGNSRegion(mesh, 2, i+1, fn, base, zone, ne_written);\n\n      for(const auto i : IntRange(imax1))\n        ne_written += cg::WriteCGNSRegion(mesh, 1, i+1, fn, base, zone, ne_written);\n\n    }\n\n  void WriteCGNSMesh (const Mesh & mesh, const filesystem::path & filename)\n    {\n      static Timer tall(\"CGNS::WriteMesh\"); RegionTimer rtall(tall);\n      int fn, base, zone;\n      cg_open(filename.string().c_str(),CG_MODE_WRITE,&fn);\n\n      WriteCGNSMesh(mesh, fn, base, zone);\n\n      cg_close(fn);\n    }\n\n\n  void WriteCGNSFile(shared_ptr<Mesh> mesh, const filesystem::path & filename, vector<string> fields, vector<Array<double>> values, vector<int> locations)\n  {\n      static Timer tall(\"CGNS::WriteFile\"); RegionTimer rtall(tall);\n      int fn, base, zone;\n      cg_open(filename.string().c_str(),CG_MODE_WRITE,&fn);\n\n      WriteCGNSMesh(*mesh, fn, base, zone);\n\n      for(auto i : IntRange(fields.size()))\n      {\n        int section, field;\n        string name = \"solution_\" + ToString(i);\n\n\n        cg_sol_write(fn, base, zone, name.c_str(), cg::getCGNodeType(locations[i]), &section);\n        cg_field_write(fn, base, zone, section, RealDouble, fields[i].c_str(), &values[i][0], &field);\n      }\n\n      cg_close(fn);\n  }\n\n  static RegisterUserFormat reg_cgns (\"CGNS Format\", {\".cgns\"},\n                                      static_cast<void(*)(Mesh &, const filesystem::path&)>(&ReadCGNSMesh),\n                                      static_cast<void(*)(const Mesh &, const filesystem::path&)>(&WriteCGNSMesh));\n}\n\n#endif // NG_CGNS\n"
  },
  {
    "path": "libsrc/interface/rw_medit.cpp",
    "content": "#include <regex>\n\n#include <meshing.hpp>\n#include \"rw_medit.hpp\"\n\nnamespace netgen\n{\nvoid ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<int,int>, int> & index_map)\n{\n  static Timer tall(\"ReadMeditMesh\"); RegionTimer rtall(tall);\n  if(!filesystem::exists(filename))\n    throw Exception(\"File does not exist: \" + filename.string());\n  auto fin = ifstream(filename);\n  string token;\n  int version, dim;\n  mesh.ClearFaceDescriptors();\n\n  int index_cnt[4] = {0,0,0,0};\n  auto getIndex = [&](int eldim, int index) {\n    if(index_map.count({eldim,index})==0) {\n      auto n = ++index_cnt[eldim];\n      index_map[{eldim, index}] = n;\n      if(eldim==2) {\n        auto fd = FaceDescriptor(n-1,1,0,0);\n        fd.SetBCProperty(n);\n        mesh.AddFaceDescriptor (fd);\n      }\n    }\n    return index_map[{eldim, index}];\n  };\n\n  while(true) {\n    fin >> token;\n    int index;\n    // cout << \"token: \" << token << endl;\n    if(token == \"End\") {\n      break;\n    }\n    else if(token == \"\" || std::regex_match(token, std::regex(\"^[\\\\s]*$\"))) {\n      continue;\n    }\n    else if(token == \"MeshVersionFormatted\") {\n      fin >> version;\n    }\n    else if(token == \"Dimension\") {\n      fin >> dim;\n      mesh.SetDimension(dim);\n    }\n    else if(token == \"Vertices\") {\n      int nvert;\n      fin >> nvert;\n      Point<3> p{0.,0.,0.};\n      for([[maybe_unused]] auto k : Range(nvert)) {\n        for(auto i : Range(dim))\n          fin >> p[i];\n        fin >> index;\n        mesh.AddPoint(p);\n      }\n    }\n    else if(token == \"Edges\") {\n      int nedge;\n      fin >> nedge;\n      Segment seg;\n      for([[maybe_unused]] auto k : Range(nedge)) {\n        for(auto i : Range(2))\n          fin >> seg[i];\n        fin >> seg.edgenr;\n        seg.edgenr = getIndex(1, seg.edgenr);\n        seg.si = seg.edgenr;\n        mesh.AddSegment(seg);\n      }\n    }\n    else if(token == \"Triangles\") {\n      int ntrig, index;\n      fin >> ntrig;\n      Element2d sel;\n      for([[maybe_unused]] auto k : Range(ntrig)) {\n        for(auto i : Range(3))\n          fin >> sel[i];\n        fin >> index;\n        sel.SetIndex(getIndex(2, index));\n        mesh.AddSurfaceElement(sel);\n      }\n    }\n    else if(token == \"Tetrahedra\") {\n      int ntet;\n      fin >> ntet;\n      Element el(4);\n      for([[maybe_unused]] auto k : Range(ntet)) {\n        for(auto i : Range(4))\n          fin >> el[i];\n        fin >> index;\n        el.SetIndex(getIndex(3, index));\n        el.Invert();\n        mesh.AddVolumeElement(el);\n      }\n    }\n    else if(token == \"Corners\") {\n      int ncorners;\n      fin >> ncorners;\n      Element0d el;\n      for([[maybe_unused]] auto k : Range(ncorners)) {\n          fin >> el.pnum;\n      }\n    }\n    else if(token == \"RequiredVertices\") {\n      int nverts;\n      fin >> nverts;\n      int vert;\n      for([[maybe_unused]] auto k : Range(nverts)) {\n          fin >> vert;\n      }\n    }\n    else if(token == \"Normals\") {\n      int nnormals;\n      fin >> nnormals;\n      Vec<3> normal;\n      for([[maybe_unused]] auto k : Range(nnormals)) {\n          fin >> normal[0];\n          fin >> normal[1];\n          fin >> normal[2];\n      }\n    }\n    else if(token == \"NormalAtVertices\") {\n      int nnormals;\n      fin >> nnormals;\n      int vert;\n      int normal;\n      for([[maybe_unused]] auto k : Range(nnormals)) {\n        fin >> normal;\n        fin >> vert;\n      }\n    }\n    else if(token == \"Tangents\") {\n      int ntangents;\n      fin >> ntangents;\n      Vec<3> tangent;\n      for([[maybe_unused]] auto k : Range(ntangents)) {\n        fin >> tangent[0];\n        fin >> tangent[1];\n        fin >> tangent[2];\n      }\n    }\n    else if(token == \"TangentAtVertices\") {\n      int ntangents;\n      fin >> ntangents;\n      int vert;\n      int tangent;\n      for([[maybe_unused]] auto k : Range(ntangents)) {\n        fin >> tangent;\n        fin >> vert;\n      }\n    }\n    else if(token == \"Ridges\") {\n      int nridges;\n      fin >> nridges;\n      int ridge;\n      for([[maybe_unused]] auto k : Range(nridges)) {\n        fin >> ridge;\n      }\n    }\n    else {\n      cout << \"unknown token \" << token << endl;\n      int nitems;\n      fin >> nitems;\n      string s;\n      for([[maybe_unused]] auto i : Range(nitems))\n        fin >> s; // read one line\n    }\n  }\n}\n\nvoid ReadMeditFormat (Mesh & mesh, const filesystem::path & filename)\n{\n  map<tuple<int, int>, int> index_map;\n  ReadMeditFormat(mesh, filename, index_map);\n}\n\n\nvoid WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename, map<tuple<int,int>, int> & index_map)\n{\n  static Timer tall(\"WriteMeditFormat\"); RegionTimer rtall(tall);\n  auto fout = ofstream(filename);\n  fout << \"MeshVersionFormatted 2\\n\";\n  fout << \"Dimension\\n\" << mesh.GetDimension() << endl;\n  fout << \"Vertices\\n\" << mesh.GetNP() << endl;\n  int base_index = 0;\n  int max_index = 0;\n  auto getIndex = [&](int i, int dim) {\n    max_index = max(max_index, i+base_index);\n    auto index = base_index+i;\n    index_map[{dim,i}] = index;\n    return index;\n  };\n  fout << setprecision(16);\n\n  for(const auto & p : mesh.Points())\n  {\n    for(auto i : Range(mesh.GetDimension()))\n      fout << p[i] << ' ';\n    fout << getIndex(1, 0) << endl;\n  }\n\n  base_index = max_index;\n  fout << \"Edges\\n\" << mesh.GetNSeg() << endl;\n  for(const auto & seg : mesh.LineSegments())\n    fout << seg[0] << ' ' << seg[1] << ' ' << getIndex(seg.edgenr, 1) << endl;\n\n  base_index = max_index;\n  fout << \"Triangles\\n\" << mesh.GetNSE() << endl;\n  for(const auto & sel : mesh.SurfaceElements())\n    fout << sel[0] << ' ' << sel[1] << ' ' << sel[2] << ' ' << getIndex(sel.GetIndex(), 2) << endl;\n\n  base_index = max_index;\n  fout << \"Tetrahedra\\n\" << mesh.GetNE() << endl;\n  for(const auto & el : mesh.VolumeElements())\n    fout << el[0] << ' ' << el[1] << ' ' << el[2] << ' ' << el[3] << '\\t' << getIndex(el.GetIndex(), 3) << endl;\n\n  fout << \"End\" << endl;\n}\n\nvoid WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename)\n{\n  map<tuple<int,int>, int> index_map;\n  WriteMeditFormat(mesh, filename, index_map);\n}\n\nstatic RegisterUserFormat reg_medit (\"Medit Format\", {\".mesh\"},\n                                     static_cast<void(*)(Mesh &, const filesystem::path&)>(ReadMeditFormat),\n                                     static_cast<void(*)(const Mesh &, const filesystem::path&)>(WriteMeditFormat));\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/interface/rw_medit.hpp",
    "content": "#include <meshing.hpp>\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\nDLL_HEADER void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<int, int>, int> & index_map);\nDLL_HEADER void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename);\n\nDLL_HEADER void WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename, map<tuple<int,int>, int> & index_map);\nDLL_HEADER void WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename);\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/interface/writeOpenFOAM15x.cpp",
    "content": "/*! \\file writeOpenFOAM15x.cpp\r\n*  \\brief Export Netgen Mesh in the OpenFOAM 1.5+ File format\r\n*  \\author Philippose Rajan\r\n*  \\date 25 October 2009\r\n*\r\n*  This function extends the export capabilities of\r\n*  Netgen to include the OpenFOAM 1.5+ File Format.\r\n*\r\n*  The OpenFOAM 1.5+ mesh format consists of a set of 5 files \r\n*  which together define the mesh points, faces, cells and \r\n*  boundary conditions. \r\n*\r\n*  The files are:\r\n*  1. points    -> A list of the point co-ordinates\r\n*  2. faces     -> A list of the faces with format <n>(pnt_ind1 pnt_ind2 .... pnt_ind<n>)\r\n*  3. owner     -> The owner cell of each face \r\n*  4. neighbour -> The neighbour cell of each face\r\n*  5. boundary  -> The set of boundaries with name, start face, and num. of faces\r\n*\r\n*  For a detailed description of the format, refer to the following link:\r\n*  http://openfoamwiki.net/index.php/Write_OpenFOAM_meshes\r\n*\r\n*/\r\n\r\n#include <mystdlib.h>\r\n\r\n#include <myadt.hpp>\r\n#include <linalg.hpp>\r\n#include <csg.hpp>\r\n#include <meshing.hpp>\r\n#include <sys/stat.h>\r\n\r\n#include \"../general/gzstream.h\"\r\n#include \"writeuser.hpp\"\r\n\r\nnamespace netgen\r\n{\r\n\r\n  extern MeshingParameters mparam;\r\n\r\n   // Global arrays used to maintain the owner, neighbour and face lists \r\n   // so that they are accessible across functions\r\n   static NgArray<int> owner_facelist;\r\n   static NgArray<int> owner_celllist;\r\n   static NgArray<int> neighbour_celllist;\r\n   static NgArray<int> surfelem_bclist;\r\n   static NgArray<INDEX_2> surfelem_lists;\r\n\r\n\r\n\r\n   static void WriteOpenFOAM15xBanner(ostream * outfile)\r\n   {\r\n      static char FOAMversion[4] = \"1.5\";\r\n      static char spaces[40];\r\n\r\n      memset(spaces, ' ', 40);\r\n      spaces[38 - strlen(FOAMversion)] = '\\0';\r\n      \r\n      *outfile << \r\n              \"/*--------------------------------*- C++ -*----------------------------------*\\\\\\n\";\r\n\r\n      *outfile <<\r\n              \"| =========                 |                                                 |\\n\"\r\n              \"| \\\\\\\\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |\\n\"\r\n              \"|  \\\\\\\\    /   O peration     | Version:  \" << FOAMversion << spaces << \"|\\n\"\r\n              \"|   \\\\\\\\  /    A nd           | Web:      http://www.OpenFOAM.org               |\\n\"\r\n              \"|    \\\\\\\\/     M anipulation  |                                                 |\\n\"\r\n              \"\\\\*---------------------------------------------------------------------------*/\\n\";\r\n\r\n   }\r\n\r\n\r\n\r\n   static void WriteOpenFOAM15xDividerStart(ostream * outfile)\r\n   {\r\n      *outfile  <<\r\n               \"// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\\n\";\r\n   }\r\n\r\n\r\n\r\n   static void WriteOpenFOAM15xDividerEnd(ostream * outfile)\r\n   {\r\n      *outfile <<\r\n              \"// ************************************************************************* //\\n\";\r\n   }\r\n\r\n\r\n\r\n   static bool BuildOwnerNeighbourLists (const Mesh & mesh)\r\n   {\r\n      // Clear all the arrays\r\n      owner_facelist.DeleteAll();\r\n      owner_celllist.DeleteAll();\r\n      neighbour_celllist.DeleteAll();\r\n      surfelem_bclist.DeleteAll();\r\n      surfelem_lists.DeleteAll();\r\n\r\n      const MeshTopology& meshtopo = mesh.GetTopology();\r\n      \r\n      // Update the mesh topology structures\r\n      const_cast<MeshTopology&> (meshtopo).SetBuildEdges(true);\r\n      const_cast<MeshTopology&> (meshtopo).SetBuildFaces(true);\r\n      const_cast<MeshTopology&> (meshtopo).Update();\r\n\r\n      // Extract important mesh metrics\r\n      int ne = mesh.GetNE();\r\n      int nse = mesh.GetNSE();\r\n      int totfaces = meshtopo.GetNFaces();\r\n\r\n      // Preset the size of the arrays to speed up future operations\r\n      // Number of internal faces = total faces - num. of surface faces\r\n      owner_facelist.SetSize(totfaces - nse);\r\n      owner_celllist.SetSize(totfaces - nse);\r\n      neighbour_celllist.SetSize(totfaces - nse);\r\n      surfelem_bclist.SetSize(nse);\r\n      surfelem_lists.SetSize(nse);\r\n\r\n      // Initialise arrays to zero if required\r\n      neighbour_celllist = 0;\r\n\r\n      // NgArray used to keep track of Faces which have already been \r\n      // processed and added to the Owner list... In addition, also the \r\n      // location where the face appears in the Owner list is also stored \r\n      // to speed up creation of the Neighbour list\r\n      NgArray<int> ownerfaces(totfaces);\r\n      ownerfaces = 0;\r\n\r\n      // NgArray to hold the set of local faces of each volume element \r\n      // while running through the set of volume elements\r\n      // NOTE: The size is set automatically by the Netgen topology function\r\n      NgArray<int> locfaces;\r\n\r\n      // Secondary indices used to independently advance the owner \r\n      // and boundary condition arrays within the main loop\r\n      int owner_ind = 1;\r\n      int bc_ind = 1;\r\n\r\n      // Loop through all the volume elements\r\n      for(int elind = 1; elind <= ne; elind++)\r\n      {\r\n         // Extract the current volume element\r\n\t// const Element & el = mesh.VolumeElement(elind);\r\n\r\n         // Get the face numbers of the faces of the current volume element\r\n         // The values returned are given a sign depending on the orientation \r\n         // of the faces. This is used while writing the faces file, to \r\n         // determine whether or not to invert the face triangle before writing \r\n         // it to file\r\n         meshtopo.GetElementFaces(elind,locfaces,true);\r\n\r\n         // Loop through the faces\r\n         for(int i = 1; i <= locfaces.Size(); i++)\r\n         {\r\n            // The absolute value of a face number (because the faces \r\n            // returned by the GetElementFaces function prepend it \r\n            // with a sign depending on the face orientation)\r\n            int absfacenr = abs(locfaces.Elem(i));\r\n\r\n            // If the face already exists in the owner list, add \r\n            // the current cell into the neighbour list, in the \r\n            // same location where the face appears in the owner list\r\n            int owner_face = ownerfaces.Elem(absfacenr);\r\n            if(owner_face)\r\n            {\r\n               neighbour_celllist.Elem(owner_face) = elind;\r\n\r\n               // From this point on, the code within this \"if\" block \r\n               // basically sorts the order of the Neighbour cells (along \r\n               // with the faces list) in ascending order.\r\n               // The approach used is..... to traverse the owner and neighbour cell lists\r\n               // up and down, and sort the neighbour cells of a given owner cell \r\n               // as the list evolves.\r\n               // NOTE: A value of \"zero\" in the neighbour list implies that \r\n               // the neighbour has not been found yet, so the \"zero\" locations need \r\n               // to be skipped while sorting in ascending order\r\n               int curr_owner = owner_celllist.Elem(owner_face);\r\n\r\n               int peek_loc = owner_face - 1;\r\n               int new_loc = owner_face;\r\n\r\n               // Traversing upwards in the list\r\n               while((owner_celllist.Elem(peek_loc) == curr_owner) && (peek_loc >= 1))\r\n               {\r\n                  if((neighbour_celllist.Elem(peek_loc) != 0) \r\n                     && (neighbour_celllist.Elem(new_loc) < neighbour_celllist.Elem(peek_loc)))\r\n                  {\r\n                     Swap(neighbour_celllist.Elem(new_loc),neighbour_celllist.Elem(peek_loc));\r\n                     Swap(owner_facelist.Elem(new_loc),owner_facelist.Elem(peek_loc));\r\n                     new_loc = peek_loc;\r\n                  }\r\n\r\n                  peek_loc--;\r\n               }\r\n\r\n               peek_loc = owner_face + 1;\r\n\r\n               // Traversing downwards in the list\r\n               while((owner_celllist.Elem(peek_loc) == curr_owner) && (peek_loc <= owner_ind))\r\n               {\r\n                  if((neighbour_celllist.Elem(peek_loc) != 0) \r\n                     && (neighbour_celllist.Elem(new_loc) > neighbour_celllist.Elem(peek_loc)))\r\n                  {\r\n                     Swap(neighbour_celllist.Elem(new_loc),neighbour_celllist.Elem(peek_loc));\r\n                     Swap(owner_facelist.Elem(new_loc),owner_facelist.Elem(peek_loc));\r\n                     new_loc = peek_loc;\r\n                  }\r\n\r\n                  peek_loc++;\r\n               }\r\n\r\n               continue;\r\n            }\r\n\r\n            // Check if the face is a surface element (boundary face)\r\n            // if not, add the current volume element and the corresponding face into \r\n            // the owner list\r\n            // int surfelem = meshtopo.GetFace2SurfaceElement1(absfacenr);\r\n            int surfelem = meshtopo.GetFace2SurfaceElement(absfacenr-1)+1;\r\n            if(!surfelem)\r\n            {\r\n               // If it is a new face which has not been listed before, \r\n               // add the current cell into the owner list, and save \r\n               // the index location to be used later by the neighbour list\r\n               owner_celllist.Elem(owner_ind) = elind;\r\n               owner_facelist.Elem(owner_ind) = locfaces.Elem(i);\r\n               // Update the array to indicate that the face is already processed\r\n               ownerfaces.Elem(absfacenr) = owner_ind;\r\n\r\n               owner_ind++;\r\n            }\r\n            // If the face is a boundary face, extract the boundary condition number of the \r\n            // face, and append that along with the face number and the current cell \r\n            // into the various surface elements lists\r\n            else\r\n            {\r\n               Element2d sel = mesh.SurfaceElement(surfelem);\r\n               surfelem_bclist.Elem(bc_ind) = mesh.GetFaceDescriptor(sel.GetIndex()).BCProperty();\r\n               surfelem_lists.Elem(bc_ind) = INDEX_2(locfaces.Elem(i),elind);\r\n\r\n               bc_ind++;\r\n            }\r\n         }\r\n      }\r\n\r\n      // This correction is required in cases where the mesh has been \"uniform refined\".... for \r\n      // some reason, the number of faces reported by Netgen is higher than the actual number \r\n      // of faces in the mesh\r\n      owner_facelist.SetSize(owner_ind-1);\r\n      owner_celllist.SetSize(owner_ind-1);\r\n      neighbour_celllist.SetSize(owner_ind-1);\r\n\r\n\r\n      // Sort the list of surface elements in ascending order of boundary condition number\r\n      // also sort the cell list in the same manner\r\n      QuickSort(surfelem_bclist,surfelem_lists);\r\n\r\n/*    \r\n      // Debugging output to a file \r\n      ofstream dbg(\"OpenFOAMDebug.log\");\r\n\r\n      dbg << \" ------- Boundary List -------- \\n\";\r\n\r\n      for(int i = 1; i <= surfelem_bclist.Size(); i++)\r\n      {\r\n         dbg << \"bc = \" << surfelem_bclist.Elem(i) \r\n              << \" : face = \" << surfelem_lists.Elem(i).I1()\r\n              << \" : cell = \" << surfelem_lists.Elem(i).I2() << \"\\n\";\r\n      }\r\n\r\n      dbg << \"\\n ------- Owner / Face / Neighbour List ------- \\n\";\r\n\r\n      for(int i = 1; i <= owner_celllist.Size(); i++)\r\n      {\r\n         dbg << \"Ind:\" << i << \" :: (\" \r\n              << owner_celllist.Elem(i) << \" \"\r\n              << owner_facelist.Elem(i) << \"  \"\r\n              << neighbour_celllist.Elem(i) << \")\\n\";\r\n      }\r\n\r\n      dbg.close();\r\n*/\r\n      return(false);\r\n   }\r\n\r\n\r\n\r\n   static void WriteNeighbourFile (ostream * outfile)\r\n   {\r\n      // Write the OpenFOAM standard banner and dividers, etc...\r\n      WriteOpenFOAM15xBanner(outfile);\r\n      *outfile << \"FoamFile \\n\"\r\n              << \"{ \\n\"\r\n              << \"    version     2.0; \\n\"\r\n              << \"    format      ascii; \\n\"\r\n              << \"    class       labelList; \\n\"\r\n              << \"    note        \\\"Mesh generated and converted using NETGEN-\" << PACKAGE_VERSION << \"\\\"; \\n\"\r\n              << \"    location    \\\"constant\\\\polyMesh\\\"; \\n\"\r\n              << \"    object      neighbour; \\n\"\r\n              << \"} \\n\";\r\n      WriteOpenFOAM15xDividerStart(outfile);\r\n\r\n      *outfile << \"\\n\\n\";\r\n\r\n      int nneighbours = neighbour_celllist.Size();\r\n\r\n      *outfile << nneighbours << \"\\n\";\r\n\r\n      *outfile << \"(\\n\";\r\n\r\n      // Write the neighbour cells to file\r\n      for(int i = 1; i <= neighbour_celllist.Size(); i++)\r\n      {\r\n         *outfile << neighbour_celllist.Elem(i) - 1 << \"\\n\";\r\n      }\r\n      *outfile << \")\\n\\n\";\r\n      WriteOpenFOAM15xDividerEnd(outfile);\r\n   }\r\n\r\n\r\n\r\n   static void WriteOwnerFile (ostream * outfile)\r\n   {\r\n      // Write the OpenFOAM standard banner and dividers, etc...\r\n      WriteOpenFOAM15xBanner(outfile);\r\n      *outfile << \"FoamFile \\n\"\r\n              << \"{ \\n\"\r\n              << \"    version     2.0; \\n\"\r\n              << \"    format      ascii; \\n\"\r\n              << \"    class       labelList; \\n\"\r\n              << \"    note        \\\"Mesh generated and converted using NETGEN-\" << PACKAGE_VERSION << \"\\\"; \\n\"\r\n              << \"    location    \\\"constant\\\\polyMesh\\\"; \\n\"\r\n              << \"    object      owner; \\n\"\r\n              << \"} \\n\";\r\n      WriteOpenFOAM15xDividerStart(outfile);\r\n\r\n      *outfile << \"\\n\\n\";\r\n\r\n      int nowners = owner_celllist.Size() + surfelem_lists.Size();\r\n\r\n      *outfile << nowners << \"\\n\";\r\n\r\n      *outfile << \"(\\n\";\r\n\r\n      // Write the owners of the internal cells to file\r\n      for(int i = 1; i <= owner_celllist.Size(); i++)\r\n      {\r\n         *outfile << owner_celllist.Elem(i) - 1 << \"\\n\";\r\n      }\r\n\r\n      // Write the owners of the boundary cells to file\r\n      // (Written in order of ascending boundary condition numbers)\r\n      for(int i = 1; i <= surfelem_lists.Size(); i++)\r\n      {\r\n         *outfile << surfelem_lists.Elem(i).I2() - 1 << \"\\n\";\r\n      }\r\n      *outfile << \")\\n\\n\";\r\n      WriteOpenFOAM15xDividerEnd(outfile);\r\n   }\r\n\r\n\r\n\r\n   static void WriteFacesFile (ostream * outfile, const Mesh & mesh)\r\n   {\r\n      const MeshTopology& meshtopo = mesh.GetTopology();\r\n\r\n      // Write the OpenFOAM standard banner and dividers, etc...\r\n      WriteOpenFOAM15xBanner(outfile);\r\n      *outfile << \"FoamFile \\n\"\r\n              << \"{ \\n\"\r\n              << \"    version     2.0; \\n\"\r\n              << \"    format      ascii; \\n\"\r\n              << \"    class       faceList; \\n\"\r\n              << \"    note        \\\"Mesh generated and converted using NETGEN-\" << PACKAGE_VERSION << \"\\\"; \\n\"\r\n              << \"    location    \\\"constant\\\\polyMesh\\\"; \\n\"\r\n              << \"    object      faces; \\n\"\r\n              << \"} \\n\";\r\n      WriteOpenFOAM15xDividerStart(outfile);\r\n\r\n      *outfile << \"\\n\\n\";\r\n\r\n      int nfaces = owner_facelist.Size() + surfelem_lists.Size();\r\n\r\n      *outfile << nfaces << \"\\n\";\r\n\r\n      *outfile << \"(\\n\";\r\n\r\n      // NgArray to hold the indices of the points of each face to \r\n      // flip if required \r\n      NgArray<int> facepnts;\r\n\r\n      // Write the faces in the order specified in the owners lists of the \r\n      // internal cells and the boundary cells\r\n      for(int i = 1; i <= owner_facelist.Size(); i++)\r\n      {\r\n         int face_w_orientation = owner_facelist.Elem(i);\r\n         int facenr = abs(face_w_orientation);\r\n\r\n         meshtopo.GetFaceVertices(facenr,facepnts);\r\n\r\n         // Get the orientation of the face, and invert it if required\r\n         // Since the faces already have the orientation \"embedded\" into \r\n         // them by means of the prepended sign, only this needs to be \r\n         // checked for...\r\n         if(face_w_orientation > 0)\r\n         {\r\n            int tmppnts = 0;\r\n\r\n            if(facepnts.Size() == 4)\r\n            {\r\n               tmppnts = facepnts.Elem(1);\r\n               facepnts.Elem(1) = facepnts.Elem(2);\r\n               facepnts.Elem(2) = tmppnts;\r\n               \r\n               tmppnts = facepnts.Elem(3);\r\n               facepnts.Elem(3) = facepnts.Elem(4);\r\n               facepnts.Elem(4) = tmppnts;\r\n            }\r\n            else if(facepnts.Size() == 3)\r\n            {\r\n               tmppnts = facepnts.Elem(1);\r\n               facepnts.Elem(1) = facepnts.Elem(3);\r\n               facepnts.Elem(3) = tmppnts;\r\n            }\r\n         }\r\n\r\n         *outfile << facepnts.Size();\r\n         *outfile << \"(\";\r\n         for(int j = 1; j <= facepnts.Size(); j++)\r\n         {\r\n            *outfile << facepnts.Elem(j)-1;\r\n            if(j != facepnts.Size()) *outfile << \" \";\r\n         }\r\n         *outfile << \")\\n\";\r\n      }\r\n\r\n      // Now append the faces of the surface elements (written in \r\n      // ascending order of boundary condition number) also into \r\n      // the faces file\r\n      for(int i = 1; i <= surfelem_lists.Size(); i++)\r\n      {\r\n         int face_w_orientation = surfelem_lists.Elem(i).I1();\r\n         int facenr = abs(face_w_orientation);\r\n\r\n         meshtopo.GetFaceVertices(facenr,facepnts);\r\n\r\n         // Get the orientation of the face, and invert it if required\r\n         if(face_w_orientation > 0)\r\n         {\r\n            int tmppnts = 0;\r\n\r\n            if(facepnts.Size() == 4)\r\n            {\r\n               tmppnts = facepnts.Elem(1);\r\n               facepnts.Elem(1) = facepnts.Elem(2);\r\n               facepnts.Elem(2) = tmppnts;\r\n               \r\n               tmppnts = facepnts.Elem(3);\r\n               facepnts.Elem(3) = facepnts.Elem(4);\r\n               facepnts.Elem(4) = tmppnts;\r\n            }\r\n            else if(facepnts.Size() == 3)\r\n            {\r\n               tmppnts = facepnts.Elem(1);\r\n               facepnts.Elem(1) = facepnts.Elem(3);\r\n               facepnts.Elem(3) = tmppnts;\r\n            }\r\n         }\r\n\r\n         *outfile << facepnts.Size();\r\n         *outfile << \"(\";\r\n         for(int j = 1; j <= facepnts.Size(); j++)\r\n         {\r\n            *outfile << facepnts.Elem(j)-1;\r\n            if(j != facepnts.Size()) *outfile << \" \";\r\n         }\r\n         *outfile << \")\\n\";\r\n      }\r\n\r\n      *outfile << \")\\n\\n\";\r\n      WriteOpenFOAM15xDividerEnd(outfile);\r\n   }\r\n\r\n\r\n \r\n   static void WritePointsFile (ostream * outfile, const Mesh & mesh)\r\n   {\r\n      int np = mesh.GetNP();\r\n\r\n      // Write the OpenFOAM standard banner and dividers, etc...\r\n      WriteOpenFOAM15xBanner(outfile);\r\n      *outfile << \"FoamFile \\n\"\r\n              << \"{ \\n\"\r\n              << \"    version     2.0; \\n\"\r\n              << \"    format      ascii; \\n\"\r\n              << \"    class       vectorField; \\n\"\r\n              << \"    note        \\\"Mesh generated and converted using NETGEN-\" << PACKAGE_VERSION << \"\\\"; \\n\"\r\n              << \"    location    \\\"constant\\\\polyMesh\\\"; \\n\"\r\n              << \"    object      points; \\n\"\r\n              << \"} \\n\";\r\n      WriteOpenFOAM15xDividerStart(outfile);\r\n\r\n      *outfile << \"\\n\\n\";\r\n\r\n      // Number of points in the following list\r\n      *outfile << np << \"\\n\";\r\n\r\n      outfile->precision(6);\r\n      outfile->setf (ios::fixed, ios::floatfield);\r\n      outfile->setf (ios::showpoint);\r\n\r\n      // Coordinate list starts here\r\n      *outfile << \"(\\n\";\r\n\r\n      for(int i = 1; i <= np; i++)\r\n      {\r\n         const Point3d & p = mesh.Point(i);\r\n\r\n         // Write coordinates to file\r\n         *outfile << \"(\";\r\n         *outfile << p.X() << \" \";\r\n         *outfile << p.Y() << \" \";\r\n         *outfile << p.Z();\r\n         *outfile << \")\\n\";\r\n      }\r\n      *outfile << \")\\n\\n\";\r\n      WriteOpenFOAM15xDividerEnd(outfile);\r\n   }\r\n\r\n\r\n\r\n   static void WriteBoundaryFile (ostream * outfile)\r\n   {\r\n      // Write the OpenFOAM standard banner and dividers, etc...\r\n      WriteOpenFOAM15xBanner(outfile);\r\n      *outfile << \"FoamFile \\n\"\r\n              << \"{ \\n\"\r\n              << \"    version     2.0; \\n\"\r\n              << \"    format      ascii; \\n\"\r\n              << \"    class       polyBoundaryMesh; \\n\"\r\n              << \"    note        \\\"Mesh generated and converted using NETGEN-\" << PACKAGE_VERSION << \"\\\"; \\n\"\r\n              << \"    location    \\\"constant\\\\polyMesh\\\"; \\n\"\r\n              << \"    object      boundary; \\n\"\r\n              << \"} \\n\";\r\n      WriteOpenFOAM15xDividerStart(outfile);\r\n\r\n      *outfile << \"\\n\";\r\n\r\n\r\n      NgArray<INDEX_3> bcarray;\r\n      int ind = 1;\r\n\r\n      // Since the boundary conditions are already sorted in ascending \r\n      // order, the last element will give the maximum number of possible \r\n      // boundary condition entries\r\n      int bcmax = surfelem_bclist.Elem(surfelem_bclist.Size());\r\n\r\n      bcarray.SetSize(bcmax+1);\r\n\r\n      bcarray.Elem(ind) = INDEX_3(surfelem_bclist.Elem(1),1,0);\r\n            \r\n      for(int i = 2; i <= surfelem_bclist.Size(); i++)\r\n      {\r\n         if(surfelem_bclist.Elem(i) == bcarray.Elem(ind).I1())\r\n         {\r\n            bcarray.Elem(ind).I2() = bcarray.Elem(ind).I2()+1;\r\n         }\r\n         else\r\n         {\r\n            ind++;\r\n            bcarray.Elem(ind) = INDEX_3(surfelem_bclist.Elem(i),1,i-1);\r\n         }\r\n      }\r\n\r\n      bcarray.SetSize(ind);\r\n\r\n      *outfile << bcarray.Size() << \"\\n\";\r\n      *outfile << \"(\\n\";\r\n\r\n      int startface = 0;\r\n\r\n      for(int i = 1; i <= bcarray.Size(); i++)\r\n      {\r\n         startface = owner_celllist.Size() + bcarray.Elem(i).I3();\r\n\r\n         *outfile << \"    patch\" << bcarray.Elem(i).I1() << \"\\n\"\r\n                 << \"    {\\n\"\r\n                 << \"        type            patch;\\n\"\r\n                 << \"        physicalType    patch;\\n\"\r\n                 << \"        nFaces          \" << bcarray.Elem(i).I2() << \";\\n\"\r\n                 << \"        startFace       \" << startface << \";\\n\"\r\n                 << \"    }\\n\";\r\n      }\r\n\r\n      *outfile << \")\\n\\n\";\r\n      WriteOpenFOAM15xDividerEnd(outfile);\r\n   }\r\n\r\n\r\n\r\n   void WriteOpenFOAM15xFormat (const Mesh & mesh, const filesystem::path & dirname, const bool compressed)\r\n   {\r\n      bool error = false;\r\n      // char casefiles[256];\r\n\r\n      // Make sure that the mesh data has been updated\r\n      const_cast<Mesh&> (mesh).Compress();\r\n      const_cast<Mesh&> (mesh).CalcSurfacesOfNode();\r\n      const_cast<Mesh&> (mesh).RebuildSurfaceElementLists();\r\n      const_cast<Mesh&> (mesh).BuildElementSearchTree(3);\r\n\r\n\r\n      int np = mesh.GetNP();\r\n      int nse = mesh.GetNSE();\r\n      int ne = mesh.GetNE();\r\n\r\n      cout << \"Write OpenFOAM 1.5+ Mesh Files....\\n\";\r\n\r\n      // Abort if there are no points, surface elements or volume elements\r\n      if((np <= 0) || (ne <= 0) || (nse <= 0))\r\n      {\r\n         cout << \"Export Error: Invalid mesh.... Aborting!\\n\";\r\n         return;\r\n      }\r\n\r\n      // OpenFOAM only supports linear meshes!\r\n      if(mparam.secondorder || mesh.GetCurvedElements().IsHighOrder())\r\n      {\r\n         cout << \"Export Error: OpenFOAM 1.5+ does not support non-linear elements.... Aborting!\\n\";\r\n         return;\r\n      }\r\n\r\n      if(( (mesh.SurfaceElement(nse/2).GetType() != TRIG) \r\n\t   && (mesh.SurfaceElement(nse/2).GetType() != QUAD) )\r\n         || (mesh.VolumeElement(ne/2).GetType() == TET10)\r\n         || (mesh.VolumeElement(ne/2).GetType() == PRISM12))\r\n      {\r\n         cout << \"Export Error: OpenFOAM 1.5+ does not support non-linear elements.... Aborting!\\n\";\r\n         return;\r\n      }\r\n\r\n\r\n      cout << \"Writing OpenFOAM 1.5+ Mesh files to case: \" << dirname.string() << \"\\n\";\r\n\r\n      // Create the case directory if it does not already exist\r\n      // NOTE: This needs to be improved for the Linux variant....!!!\r\n      auto mesh_dir = filesystem::path(dirname).append(\"constant\").append(\"polyMesh\");\r\n      filesystem::create_directories(mesh_dir);\r\n\r\n      // Open handles to the five required mesh files\r\n      // points\r\n      // faces\r\n      // owner\r\n      // neighbour\r\n      // boundary\r\n\r\n      auto get_name = [compressed, &mesh_dir]( string s ) {\r\n          auto p = filesystem::path(mesh_dir).append(s);\r\n          if(compressed)\r\n              p.concat(\".gz\");\r\n          return p;\r\n      };\r\n\r\n      auto outfile_pnts  = make_unique<ofstream>(get_name(\"points\"));\r\n      auto outfile_faces = make_unique<ofstream>(get_name(\"faces\"));\r\n      auto outfile_own   = make_unique<ofstream>(get_name(\"owner\"));\r\n      auto outfile_nei   = make_unique<ofstream>(get_name(\"neighbor\"));\r\n\r\n      // Note... the boundary file is not compressed\r\n      auto outfile_bnd   = make_unique<ofstream>(mesh_dir.append(\"boundary\"));\r\n\r\n      ResetTime();\r\n\r\n      // Build the owner, neighbour, faces and boundary lists \r\n      // from the Netgen mesh\r\n      cout << \"\\nBuilding Owner, Neighbour and Face Lists: \";\r\n\r\n      error = BuildOwnerNeighbourLists(mesh);\r\n\r\n      cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n\r\n\r\n      // Write the \"owner\" file\r\n      if(outfile_own->good() && !error)\r\n      {\r\n         cout << \"Writing the owner file: \";\r\n         WriteOwnerFile(outfile_own.get());\r\n         cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Export Error: Error creating file: owner.... Aborting\\n\";\r\n         error = true;\r\n      }\r\n\r\n\r\n      // Write the \"neighbour\" file\r\n      if(outfile_nei->good() && !error)\r\n      {\r\n         cout << \"Writing the neighbour file: \";\r\n         WriteNeighbourFile(outfile_nei.get());\r\n         cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Export Error: Error creating file: neighbour.... Aborting\\n\";\r\n         error = true;\r\n      }\r\n\r\n\r\n      // Write the \"faces\" file\r\n      if(outfile_faces->good() && !error)\r\n      {\r\n         cout << \"Writing the faces file: \";\r\n         WriteFacesFile(outfile_faces.get(), mesh);\r\n         cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Export Error: Error creating file: faces.... Aborting\\n\";\r\n         error = true;\r\n      }\r\n\r\n\r\n      // Write the \"points\" file\r\n      if(outfile_pnts->good() && !error)\r\n      {\r\n         cout << \"Writing the points file: \";\r\n         WritePointsFile(outfile_pnts.get(),mesh);\r\n         cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Export Error: Error creating file: points.... Aborting\\n\";\r\n         error = true;\r\n      }\r\n\r\n\r\n      // Write the \"boundary\" file\r\n      if(outfile_bnd->good() && !error)\r\n      {\r\n         cout << \"Writing the boundary file: \";\r\n         WriteBoundaryFile(outfile_bnd.get());\r\n         cout << \"Done! (Time Elapsed = \" << GetTime() << \" sec)\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Export Error: Error creating file: boundary.... Aborting\\n\";\r\n         error = true;\r\n      }\r\n\r\n      if(!error)\r\n      {\r\n         cout << \"OpenFOAM 1.5+ Export successfully completed (Time elapsed = \" << GetTime() << \" sec) !\\n\";\r\n      }\r\n      else\r\n      {\r\n         cout << \"Error in OpenFOAM 1.5+ Export.... Aborted!\\n\";\r\n      }\r\n   }\r\n\r\nvoid WriteOpenFOAM15xFormatCompressed (const Mesh & mesh, const filesystem::path & dirname) { WriteOpenFOAM15xFormat(mesh, dirname, true); }\r\nvoid WriteOpenFOAM15xFormatUncompressed (const Mesh & mesh, const filesystem::path & dirname) { WriteOpenFOAM15xFormat(mesh, dirname, false); }\r\n\r\nstatic RegisterUserFormat reg_openfoam (\"OpenFOAM 1.5+ Format\", {\"*\"}, nullopt, WriteOpenFOAM15xFormatUncompressed);\r\nstatic RegisterUserFormat reg_openfoam_compressed (\"OpenFOAM 1.5+ Compressed\", {\"*\"}, nullopt, WriteOpenFOAM15xFormatCompressed);\r\n}\r\n\r\n"
  },
  {
    "path": "libsrc/interface/writeabaqus.cpp",
    "content": "//\n//  Write Abaqus file\n//\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\nusing std::vector;\n\nstruct AbaqusElementType\n{\n  const char * name;\n  const vector<int> permutation;\n\n  AbaqusElementType(const char * name, const vector<int> & permutation)\n    : name(name), permutation(permutation)\n  {}\n};\n\nstatic inline const AbaqusElementType & GetAbaqusType(int dim, int num_nodes)\n{\n  // maps num_nodes to AbaqusElementType for each dimension\n  typedef std::map<int, AbaqusElementType> AbaqusElementTypes;\n  static const std::map<int, AbaqusElementType> abaqus_eltypes[3] =\n  {\n    // 1D\n    AbaqusElementTypes{\n      {2, AbaqusElementType{\"T2D2\", vector{0,1}}},\n    },\n    // 2D\n    AbaqusElementTypes{\n      {3, AbaqusElementType{\"CPS3\", vector{0,1,2}}},\n      {6, AbaqusElementType{\"CPS6\", vector{0,1,2,5,6,4}}},      \n    },\n    // 3D\n    AbaqusElementTypes{\n      {4, AbaqusElementType{\"C3D4\", vector{0,1,3,2}}},\n      {10, AbaqusElementType{\"C3D10\", vector{0,1,3,2,4,8,6,5,7,9}}},\n    }\n  };\n\n  const auto & eltypes = abaqus_eltypes[dim-1];\n  if (eltypes.count(num_nodes) > 0)\n    return eltypes.at(num_nodes);\n  else\n    throw Exception(\"unsupported \" + ToString(dim)+\"d Element type with \" + ToString(num_nodes) + \" nodes\");\n}\n\nstatic void WritePoints ( const Mesh & mesh, ostream & out )\n{\n  out << \"*Node\" << endl;\n  for(auto pi : mesh.Points().Range() )\n  {\n    out << pi+1-IndexBASE<PointIndex>() << \", \";\n    auto p = mesh[pi];\n    out << p[0] << \", \" << p[1] << \", \" << p[2] << '\\n';\n  }\n}\n\ntemplate <typename ElIndex>\nstatic void WriteElement(ostream & out, const Mesh& mesh, ElIndex ei, const vector<int> & permutation, int & el_counter)\n{\n  el_counter++;\n  auto el = mesh[ei];\n  out << el_counter;\n  for(auto i : Range(el.PNums()))\n    out << \", \" << el[permutation[i]]+1-IndexBASE<PointIndex>();\n  out << '\\n';\n}\n\ntemplate <typename ElIndex, typename Elements>\nstatic void WriteElements ( ostream & out, const Mesh & mesh, int dim, const Elements & el_range, int & el_counter)\n{\n  // map index, num_nodes to elements\n  std::map<std::tuple<int, int>, Array<ElIndex>> elset_map;\n\n  for(auto ei : el_range)\n    {\n      const auto & el = mesh[ei];\n      int index = 0;\n      if constexpr(std::is_same_v<ElIndex,SegmentIndex>)\n        index = el.edgenr;\n      else\n        index = el.GetIndex();\n      elset_map[{index, el.GetNP()}].Append(ei);\n    }\n\n  for(auto & [key, elems] : elset_map)\n    {\n      auto [index, num_nodes] = key;\n      auto name = mesh.GetRegionName(elems[0]);\n      if (name == \"\") name = \"default\";\n      PrintMessage (5, index, \": \", name);\n      const auto & eltype = GetAbaqusType(dim, num_nodes) ;\n      out << \"*Element, type=\" << eltype.name << \", ELSET=\" << name << endl;\n      for(auto ei : elems)\n        WriteElement(out, mesh, ei, eltype.permutation, el_counter);\n    }\n}\n\nvoid WriteAbaqusFormat (const Mesh & mesh,\n\t\t\tconst filesystem::path & filename)\n\n{\n  PrintMessage (1, \"Write Abaqus Mesh\");\n\n  ofstream outfile (filename);\n\n  outfile << \"*Heading\" << endl;\n  outfile << \" \" << filename << endl;\n\n  outfile.precision(8);\n\n  int element_counter = 0;\n  WritePoints(mesh, outfile);\n  if(mesh.GetDimension() < 3)\n    WriteElements<SegmentIndex>(outfile, mesh, 1, mesh.LineSegments().Range(), element_counter);\n  WriteElements<SurfaceElementIndex>(outfile, mesh, 2, mesh.SurfaceElements().Range(), element_counter);\n  WriteElements<ElementIndex>(outfile, mesh, 3, mesh.VolumeElements().Range(), element_counter);\n\n  // Write identifications (untested!)\n  if (mesh.GetIdentifications().GetMaxNr())\n    {\n      const auto np = mesh.GetNP();\n      // periodic identification, implementation for\n      // Helmut J. Boehm, TU Vienna\n\t  \n      auto mpcfilename = filename;\n      if (filename.extension() == \".inp\")\n        mpcfilename.replace_extension(\".mpc\");\n      else\n        mpcfilename.concat(\".mpc\");\n\t  \n      ofstream mpc (mpcfilename);\n\n      int masternode(0);\n\n      NgArray<INDEX_2> pairs;\n      NgBitArray master(np), help(np);\n      master.Set();\n      for (int i = 1; i <= 3; i++)\n\t{\n\t  mesh.GetIdentifications().GetPairs (i, pairs);\n\t  help.Clear();\n\t  for (int j = 1; j <= pairs.Size(); j++)\n\t    {\n\t      help.Set (pairs.Get(j).I1());\n\t    }\n\t  master.And (help);\n\t}\n      for (int i = 1; i <= np; i++)\n\tif (master.Test(i))\n\t  masternode = i;\n\n      cout << \"masternode = \" << masternode << \" = \"\n\t   << mesh.Point(masternode) << endl;\n      NgArray<int> minions(3);\n      for (int i = 1; i <= 3; i++)\n\t{\n\t  mesh.GetIdentifications().GetPairs (i, pairs);\n\t  for (int j = 1; j <= pairs.Size(); j++)\n\t    {\n\t      if (pairs.Get(j).I1() == masternode)\n\t\tminions.Elem(i) = pairs.Get(j).I2();\n\t    }\n\t  cout << \"minion(\" << i << \") = \" << minions.Get(i)\n\t       << \" = \" << mesh.Point(minions.Get(i)) << endl;\n\t}\n\t  \n\t  \n      outfile << \"**\\n\"\n\t      << \"*NSET,NSET=CTENODS\\n\"\n\t      << minions.Get(1) << \", \" \n\t      << minions.Get(2) << \", \" \n\t      << minions.Get(3) << endl;\n\n\t  \n      outfile << \"**\\n\"\n\t      << \"**POINT_fixed\\n\"\n\t      << \"**\\n\"\n\t      << \"*BOUNDARY, OP=NEW\\n\";\n      for (int j = 1; j <= 3; j++)\n\toutfile << masternode << \", \" << j << \",,    0.\\n\";\n\n      outfile << \"**\\n\"\n\t      << \"*BOUNDARY, OP=NEW\\n\";\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  Vec3d v(mesh.Point(masternode), mesh.Point(minions.Get(j)));\n\t  double vlen = v.Length();\n\t  int dir = 0;\n\t  if (fabs (v.X()) > 0.9 * vlen) dir = 2;\n\t  if (fabs (v.Y()) > 0.9 * vlen) dir = 3;\n\t  if (fabs (v.Z()) > 0.9 * vlen) dir = 1;\n\t  if (!dir)\n\t    cout << \"ERROR: Problem with rigid body constraints\" << endl;\n\t  outfile << minions.Get(j) << \", \" << dir << \",,    0.\\n\";\n\t}\n\n      outfile << \"**\\n\"\n\t      << \"*EQUATION, INPUT=\" << mpcfilename << endl;\n\t  \n\n      NgBitArray eliminated(np);\n      eliminated.Clear();\n      for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)\n\t{\n\t  mesh.GetIdentifications().GetPairs (i, pairs);\n\t  if (!pairs.Size())\n\t    continue;\n\t      \n\t  for (int j = 1; j <= pairs.Size(); j++)\n\t    if (pairs.Get(j).I1() != masternode && \n\t\t!eliminated.Test(pairs.Get(j).I2()))\n\t      {\n\t\teliminated.Set (pairs.Get(j).I2());\n\t\tfor (int k = 1; k <= 3; k++)\n\t\t  {\n\t\t    mpc << \"4\" << \"\\n\";\n\t\t    mpc << pairs.Get(j).I2() << \",\" << k << \", -1.0, \";\n\t\t    mpc << pairs.Get(j).I1() << \",\" << k << \", 1.0, \";\n\t\t    mpc << minions.Get(i) << \",\" << k << \", 1.0, \";\n\t\t    mpc << masternode << \",\" << k << \", -1.0 \\n\";\n\t\t  }\n\t      }\n\t}\n    }\n\n\n  PrintMessage(1, \"done\");\n}\n\nstatic RegisterUserFormat reg_abaqus (\"Abaqus Format\", {\".mesh\"}, nullopt, WriteAbaqusFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writediffpack.cpp",
    "content": "//\n//  Write diffpack file\n//\n//  by\n//  Bartosz Sawicki <sawickib@ee.pw.edu.pl>\n//  extended by\n//  Jacques Lechelle <jacques.lechelle@wanadoo.fr>\n//\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n\nvoid WriteDiffPackFormat (const Mesh & mesh,\n\t\t\t  const filesystem::path & filename)\n{\n  //   double scale = globflags.GetNumFlag (\"scale\", 1);\n  double scale = 1;\n\n  ofstream outfile(filename);\n  outfile.precision(14);\n\n\n  if (mesh.GetDimension() == 3)\n\n    {\n      // Output compatible to Diffpack grid format\n      // Bartosz Sawicki <sawickib@ee.pw.edu.pl>\n\n      int np = mesh.GetNP();\n      int ne = mesh.GetNE();\n      int nse = mesh.GetNSE();\n      NgArray <int> BIname;\n      NgArray <int> BCsinpoint;\n      // int i, j, k, l;\n\n\n      outfile.precision(6);\n      outfile.setf (ios::fixed, ios::floatfield);\n      outfile.setf (ios::showpoint);\n\n      const Element & eldummy = mesh.VolumeElement((int)1);\n      outfile << \"\\n\\n\"\n\t\"Finite element mesh (GridFE):\\n\\n\"\n\t\"  Number of space dim. =   3\\n\"\n\t\"  Number of elements   =  \" << ne << \"\\n\"\n\t\"  Number of nodes      =  \" << np << \"\\n\\n\"\n\t\"  All elements are of the same type : dpTRUE\\n\"\n\t\"  Max number of nodes in an element: \"<< eldummy.GetNP() << \"\\n\"\n\t\"  Only one subdomain               : dpFALSE\\n\"\n\t\"  Lattice data                     ? 0\\n\\n\\n\\n\";\n      \n      for (int i = 1; i <= nse; i++) \n\t{\n\t  int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty();\n\t  int nbi=BIname.Size();\n\t  int found=0;\n\t  for (int j = 1; j <= nbi; j++)\n\t    if(BI == BIname.Get(j)) found = 1;\n\t  if( ! found ) BIname.Append(BI);\t    \t     \n\t}\n      \n      outfile << \"  \" << BIname.Size() <<  \" Boundary indicators:  \";\n      for (int i =1 ; i <= BIname.Size(); i++)\n\toutfile << BIname.Get(i) << \" \";\n      outfile << \"\\n\\n\\n\";\n      \n      outfile << \"  Nodal coordinates and nodal boundary indicators,\\n\"\n\t\"  the columns contain:\\n\"\n\t\"   - node number\\n\"\n\t\"   - coordinates\\n\"\n\t\"   - no of boundary indicators that are set (ON)\\n\"\n\t\"   - the boundary indicators that are set (ON) if any.\\n\"\n\t\"#\\n\";\n\n\n      // setup point-to-surfaceelement table \n      TABLE<SurfaceElementIndex, PointIndex::BASE> point2sel(np);\n      for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n\t{\n\t  const Element2d & el = mesh[sei];\n\t  for (int j = 0; j < el.GetNP(); j++)\n\t    point2sel.Add (el[j], sei);\n\t}\n\n\n      // for (int i = 1; i <= np; i++)\n      for (PointIndex i : mesh.Points().Range())\n        {\n          const Point3d & p = mesh.Point(i);\n\n          outfile.width(12);\n          outfile << i << \"  (\";\n          outfile.width(16);\n          outfile << p.X()/scale << \", \";\n          outfile.width(16);\n          outfile << p.Y()/scale << \", \";\n          outfile.width(16);\n          outfile << p.Z()/scale << \") \";\n\t \n\t  if(mesh[PointIndex(i)].Type() != INNERPOINT) \n\t    {\n\t      BCsinpoint.DeleteAll();\n\t      /*\n\t      for (j = 1; j <= nse; j++) \n\t      */\n\t      NgFlatArray<SurfaceElementIndex> sels = point2sel[i];\n\t      for (int jj = 0; jj < sels.Size(); jj++)\n\t\t{\n\t\t  for (int k = 1; k <= mesh[sels[jj]].GetNP(); k++) \n\t\t    {\n\t\t      if(mesh[sels[jj]].PNum(k)==i) \n\t\t\t{\n\t\t\t  int BC=mesh.GetFaceDescriptor(mesh[sels[jj]].GetIndex()).BCProperty();\n\t\t\t  int nbcsp=BCsinpoint.Size();\n\t\t\t  int found = 0;\n\t\t\t  for (int l = 1; l <= nbcsp; l++)\n\t\t\t    if(BC == BCsinpoint.Get(l)) found = 1;\n\t\t\t  if( ! found ) BCsinpoint.Append(BC); \t    \t     \n\t\t\t}\n\t\t    }\n\t\t}\n\t      int nbcsp = BCsinpoint.Size();\n\t      outfile << \"[\" << nbcsp << \"] \";\n\t      for (int j = 1; j <= nbcsp; j++)\n\t\toutfile << BCsinpoint.Get(j) << \" \";\n\t      outfile << \"\\n\";\n            }\n          else outfile << \"[0]\\n\";\n\n        }\n\n      outfile << \"\\n\"\n\t\"  Element types and connectivity\\n\"\n\t\"  the columns contain:\\n\"\n\t\"   - element number\\n\"\n\t\"   - element type\\n\"\n\t\"   - subdomain number\\n\"\n\t\"   - the global node numbers of the nodes in the element.\\n\"\n\t\"#\\n\";\n\n      for (int i = 1; i <= ne; i++)\n        {\n          const Element & el = mesh.VolumeElement(i);\n          outfile.width(5);\n          if(el.GetNP()==4)\n            outfile << i << \"  ElmT4n3D \";\n          else\n            outfile << i << \"  ElmT10n3D \";\n          outfile.width(4);\n          outfile << el.GetIndex() << \"    \";\n          if(el.GetNP()==10)\n            {\n\t      outfile.width(8);\n\t      outfile << el.PNum(1);\n\t      outfile.width(8);\n\t      outfile << el.PNum(3);\n\t      outfile.width(8);\n\t      outfile << el.PNum(2);\n\t      outfile.width(8);\n\t      outfile << el.PNum(4);\n\t      outfile.width(8);\n\t      outfile << el.PNum(6);\n\t      outfile.width(8);\n\t      outfile << el.PNum(8);\n\t      outfile.width(8);\n\t      outfile << el.PNum(5);\n\t      outfile.width(8);\n\t      outfile << el.PNum(7);\n\t      outfile.width(8);\n\t      outfile << el.PNum(10);\n\t      outfile.width(8);\n\t      outfile << el.PNum(9);\n            }\n          else\n            {\n\t      outfile.width(8);\n\t      outfile << el.PNum(1);\n\t      outfile.width(8);\n\t      outfile << el.PNum(3);\n\t      outfile.width(8);\n\t      outfile << el.PNum(2);\n\t      outfile.width(8);\n\t      outfile << el.PNum(4);\n            }\n          outfile << \"\\n\";\n        }\n    } /* Diffpack */\n\n  else\n\n    {\n      // Output compatible to Diffpack grid format 2D\n\n      int np = mesh.GetNP();\n      //int ne = mesh.GetNE();\n      int nse = mesh.GetNSE();\n      NgArray <int> BIname;\n      NgArray <int> BCsinpoint;\n      int i, j, k, l;\n\n\n      outfile.precision(6);\n      outfile.setf (ios::fixed, ios::floatfield);\n      outfile.setf (ios::showpoint);\n      const Element2d & eldummy = mesh.SurfaceElement((int)1);\n      outfile << \"\\n\\n\"\n\t\"Finite element mesh (GridFE):\\n\\n\"\n\t\"  Number of space dim. =  2\\n\"\n\t\"  Number of elements   =  \" << nse << \"\\n\"\n\t\"  Number of nodes      =  \" << np << \"\\n\\n\"\n\t\"  All elements are of the same type : dpTRUE\\n\"\n\t\"  Max number of nodes in an element: \"<<eldummy.GetNP()<<\"\\n\"\n\t\"  Only one subdomain               : dpFALSE\\n\"\n\t\"  Lattice data                     ? 0\\n\\n\\n\\n\";\n      \n      for (i = 1; i <= nse; i++) \n\t{\n\t  int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty();\n\t  int nbi=BIname.Size();\n\t  int found=0;\n\t  for (j = 1; j <= nbi; j++)\n\t    if(BI == BIname.Get(j)) found = 1;\n\t  if( ! found ) BIname.Append(BI);\t    \t     \n\t}\n      \n      outfile << \"  \" << BIname.Size() <<  \" Boundary indicators:  \";\n      for (i =1 ; i <= BIname.Size(); i++)\n\toutfile << BIname.Get(i) << \" \";\n      outfile << \"\\n\\n\\n\";\n      \n      outfile << \"  Nodal coordinates and nodal boundary indicators,\\n\"\n\t\"  the columns contain:\\n\"\n\t\"   - node number\\n\"\n\t\"   - coordinates\\n\"\n\t\"   - no of boundary indicators that are set (ON)\\n\"\n\t\"   - the boundary indicators that are set (ON) if any.\\n\"\n\t\"#\\n\";\n\n      // for (i = 1; i <= np; i++)\n      for (PointIndex i : mesh.Points().Range())\n        {\n          const Point3d & p = mesh.Point(i);\n\n          outfile.width(12);\n          outfile << i << \"  (\";\n          outfile.width(16);\n          outfile << p.X()/scale << \", \";\n          outfile.width(16);\n          outfile << p.Y()/scale << \") \";\n\t \n\t  if(mesh[PointIndex(i)].Type() != INNERPOINT) \n\t    {\n\t      BCsinpoint.DeleteAll();\n\t      for (j = 1; j <= nse; j++) \n\t\t{\n\t\t  for (k = 1; k <= 2; k++) \n\t\t    {\n\t\t      if(mesh.SurfaceElement(j).PNum(k)==i) \n\t\t\t{\n\t\t\t  int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).GetIndex()).BCProperty();\n\t\t\t  int nbcsp=BCsinpoint.Size();\n\t\t\t  int found = 0;\n\t\t\t  for (l = 1; l <= nbcsp; l++)\n\t\t\t    if(BC == BCsinpoint.Get(l)) found = 1;\n\t\t\t  if( ! found ) BCsinpoint.Append(BC); \t    \t     \n\t\t\t}\n\t\t    }\n\t\t}\n\t      int nbcsp = BCsinpoint.Size();\n\t      outfile << \"[\" << nbcsp << \"] \";\n\t      for (j = 1; j <= nbcsp; j++)\n\t\toutfile << BCsinpoint.Get(j) << \" \";\n\t      outfile << \"\\n\";\n            }\n          else outfile << \"[0]\\n\";\n\n        }\n\n      outfile << \"\\n\"\n\t\"  Element types and connectivity\\n\"\n\t\"  the columns contain:\\n\"\n\t\"   - element number\\n\"\n\t\"   - element type\\n\"\n\t\"   - subdomain number\\n\"\n\t\"   - the global node numbers of the nodes in the element.\\n\"\n\t\"#\\n\";\n\n      for (i = 1; i <= nse; i++)\n        {\n          const Element2d & el = mesh.SurfaceElement(i);\n          outfile.width(12);\n          if(eldummy.GetNP()==3)\n            outfile << i << \"  ElmT3n2D \";\n          else\n            outfile << i << \"  ElmT6n2D \";\n          outfile.width(12);\n          outfile << el.GetIndex() << \"    \";\n\t  outfile.width(16);\n\t  outfile << el.PNum(1);\n\t  outfile.width(16);\n\t  outfile << el.PNum(2);\n\t  outfile.width(16);\n\t  outfile << el.PNum(3);\n          if(eldummy.GetNP()==6)\n            {\n\t     outfile.width(16);\n\t     outfile << el.PNum(6);\n\t     outfile.width(16);\n\t     outfile << el.PNum(4);\n\t     outfile.width(16);\n\t     outfile << el.PNum(5);\n            }\n          outfile << \"\\n\";\n        }\n    }\n}\nstatic RegisterUserFormat reg_surface(\"DIFFPACK Format\", {\".mesh\"}, nullopt, WriteDiffPackFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writedolfin.cpp",
    "content": "//\n//  Write dolfin file\n//\n//  by\n//  Kent-Andre Mardal <kent-and@simula.no>\n\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\nnamespace netgen\n{\n\n#include \"writeuser.hpp\"\n\n\n\n  void WriteDolfinFormat (const Mesh & mesh, const filesystem::path & filename)\n  {\n    cout << \"start writing dolfin export\" << endl;\n\n    int np = mesh.GetNP();\n    int ne = mesh.GetNE();\n    // int nse = mesh.GetNSE();\n    int nsd = mesh.GetDimension(); \n    // int invertsurf = mparam.inverttrigs;\n    // int i, j;\n\n    ofstream outfile (filename);\n\n    // char str[100];\n    outfile.precision(8);\n    outfile.setf (ios::fixed, ios::floatfield);\n    outfile.setf (ios::showpoint);\n\n    if ( nsd == 3) {\n\n      outfile << \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" <<endl; \n      outfile << \"\"<<endl; \n\n      outfile << \"<dolfin xmlns:dolfin=\\\"http://www.phi.chalmers.se/dolfin/\\\">\"<<endl;\n      outfile << \"  <mesh celltype=\\\"tetrahedron\\\" dim=\\\"3\\\">\" <<endl; \n      outfile << \"      <vertices size=\\\"\"<<np<<\"\\\">\"<<endl; \n      for (int i = 1; i <= np; i++) { \n        const Point3d & p = mesh.Point(i);\n        outfile << \"      <vertex index=\\\"\"<<i-1<<\"\\\" x=\\\"\"<<p.X()<<\"\\\" y=\\\"\"<<p.Y()<<\"\\\" z=\\\"\"<<p.Z()<<\"\\\"/>\"<<endl; \n      }\n      outfile << \"      </vertices>\"<<endl; \n\n\n\n      outfile << \"      <cells size=\\\"\"<<ne<<\"\\\">\"<<endl; \n      for (int i = 1; i <= ne; i++) {\n        const Element & el = mesh.VolumeElement(i);\n\n        outfile << \"      <tetrahedron index=\\\"\"<<i-1<<\"\\\" v0=\\\"\"<<el.PNum(1)-1<<\"\\\" v1=\\\"\"<<el.PNum(2)-1<<\"\\\" v2=\\\"\"<<el.PNum(3)-1<<\"\\\" v3=\\\"\"<<el.PNum(4)-1<<\"\\\"/>\"<<endl; \n      }\n      outfile << \"      </cells>\"<<endl; \n    }\n    outfile << \"   </mesh>\"<<endl; \n    outfile << \"</dolfin>\"<<endl; \n\n    cout << \"done writing dolfin export\" << endl;\n  }\n}\n"
  },
  {
    "path": "libsrc/interface/writeelmer.cpp",
    "content": "\n//\n//  Write Elmer file\n//\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include <sys/stat.h>\n\n#include \"writeuser.hpp\"\n\n\nnamespace netgen\n{\n  extern MeshingParameters mparam;\n\n\nvoid WriteElmerFormat (const Mesh &mesh,\n                       const filesystem::path &dirname)\n{\n  cout << \"write elmer mesh files\" << endl;\n\n  std::map<ELEMENT_TYPE, int> tmap;\n  tmap[TRIG] = 303;\n  tmap[TRIG6] = 306;\n  tmap[QUAD] = 404;\n  tmap[QUAD8] = 408;\n  tmap[TET] = 504;\n  tmap[TET10] = 510;\n  tmap[PYRAMID] = 605;\n  tmap[PYRAMID13] = 613;\n  tmap[PRISM] = 706;\n  tmap[PRISM15] = 715;\n  tmap[HEX] = 808;\n  tmap[HEX20] = 820;\n\n  std::map<int, Array<int,int>> pmap;\n  pmap[TRIG]  = {1,2,3};\n  pmap[TRIG6] = {1,2,3, 6,4,5};\n  pmap[QUAD]  = {1,2,3,4};\n  pmap[QUAD8] = {1,2,3,4, 5,8,6,7};\n  pmap[TET]   = {1,2,3,4};\n  pmap[TET10] = {1,2,3,4, 5,8,6,7,9,10};\n  pmap[PYRAMID]={1,2,3,4,5};\n  pmap[PYRAMID13]= {1,2,3,4,5,6,7,8,9,10,11,12,13};\n  pmap[PRISM] = {1,2,3,4,5,6};\n  pmap[PRISM15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};\n  pmap[HEX]   = {1,2,3,4,5,6,7,8};\n  pmap[HEX20] = {1,2,3,4,5,8,6,7,8, 9,12,10,11, 17,20,19,18, 13,16,14,15};\n\n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int nse = mesh.GetNSE();\n  int i, j;\n  // char str[200];\n  \n  int inverttets = mparam.inverttets;\n  int invertsurf = mparam.inverttrigs;\n\n  filesystem::create_directories(dirname);\n\n  auto get_name = [&dirname]( string s ) {\n      return filesystem::path(dirname).append(s);\n  };\n\n  ofstream outfile_h(get_name(\"mesh.header\"));\n  ofstream outfile_n(get_name(\"mesh.nodes\"));\n  ofstream outfile_e(get_name(\"mesh.elements\"));\n  ofstream outfile_b(get_name(\"mesh.boundary\"));\n  ofstream outfile_names(get_name(\"mesh.names\"));\n\n  for( auto codim : IntRange(0, mesh.GetDimension()-1) )\n  {\n    auto & names = const_cast<Mesh&>(mesh).GetRegionNamesCD(codim);\n\n    for (auto i0 : Range(names) )\n    {\n      if(names[i0] == nullptr)\n        continue;\n      string name = *names[i0];\n      if(name == \"\" || name == \"default\")\n        continue;\n      outfile_names << \"$\" << name << \"=\" << i0+1 << \"\\n\";\n    }\n  }\n\n  auto get3FacePoints = [](const Element2d & el)\n  {\n      INDEX_3 i3;\n      INDEX_4 i4;\n      auto eltype = el.GetType();\n      switch (eltype)\n      {\n          case TRIG:\n          case TRIG6:\n              i3 = {el[0], el[1], el[2]};\n              i3.Sort();\n              break;\n          case QUAD:\n          case QUAD8:\n              i4 = {el[0], el[1], el[2], el[3]};\n              i4.Sort();\n              i3 = {i4[0], i4[1], i4[2]};\n              break;\n          default:\n             throw Exception(\"Got invalid type (no face)\");\n      }\n      return i3;\n  };\n\n  // fill hashtable\n\n  // use lowest three point numbers of lowest-order face to index faces\n  INDEX_3_HASHTABLE<int> face2volelement(ne);\n\n  for (int i = 1; i <= ne; i++)\n    {\n      const Element & el = mesh.VolumeElement(i);\n\n      // getface not working for second order elements -> reconstruct linear element here\n      Element linear_el = el;\n      linear_el.SetNP(el.GetNV()); // GetNV returns 8 for HEX20 for instance\n\n      for (auto j : Range(1,el.GetNFaces()+1))\n\t{\n          Element2d face;\n          linear_el.GetFace(j, face);\n\t  face2volelement.Set (get3FacePoints(face), i);\n          cout << \"set \" << get3FacePoints(face) << \"\\tto \" << i << endl;\n\t}\n    }\n\n//  outfile.precision(6);\n//  outfile.setf (ios::fixed, ios::floatfield);\n//  outfile.setf (ios::showpoint);\n  \n  std::map<ELEMENT_TYPE, size_t> elcount;\n  \n  for (i = 1; i <= np; i++)\n    {\n      const Point3d & p = mesh.Point(i);\n      \n      outfile_n << i << \" -1 \";\n      outfile_n << p.X() << \" \";\n      outfile_n << p.Y() << \" \";\n      outfile_n << p.Z() << \"\\n\";\n    }\n\n  for (i = 1; i <= ne; i++)\n    {\n      Element el = mesh.VolumeElement(i);\n      if (inverttets) el.Invert();\n      auto eltype = el.GetType();\n      elcount[eltype]++;\n      outfile_e << i << \" \" << el.GetIndex() << \" \" << tmap[eltype] <<  \"  \";\n\n      auto & map = pmap[eltype];\n      for (j = 1; j <= el.GetNP(); j++)\n\t{\n\t  outfile_e << \" \";\n\t  outfile_e << el.PNum(map[j-1]);\n\t}\n      outfile_e << \"\\n\";\n    }\n\n  for (i = 1; i <= nse; i++)\n    {\n      Element2d el = mesh.SurfaceElement(i);\n      if (invertsurf) el.Invert();\n      auto eltype = el.GetType();\n      elcount[eltype]++;\n            \n      int elind = face2volelement.Get(get3FacePoints(el));\n      cout << \"get \" << get3FacePoints(el) << \"\\t \" << elind << endl;\n\n      outfile_b << i << \" \" << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << \n         \" \" << elind << \" 0 \"  << tmap[eltype] << \"    \";\n\n      auto & map = pmap[el.GetType()];\n      for (j = 1; j <= el.GetNP(); j++)\n\t{\n\t  outfile_b << \" \";\n\t  outfile_b << el.PNum(map[j-1]);\n\t}\n      outfile_b << \"\\n\";\n    }\n\n  outfile_h << np << \" \" << ne << \" \" << nse << \"\\n\";\n  outfile_h << \"2\"     << \"\\n\";\n\n  for( auto & [eltype,count] : elcount )\n      outfile_h << tmap[eltype] << \" \" << count << \"\\n\";\n}\n\nstatic RegisterUserFormat reg_elmer (\"Elmer Format\", {\"*\"}, nullopt, WriteElmerFormat);\n\n}\n"
  },
  {
    "path": "libsrc/interface/writefeap.cpp",
    "content": "//\n// Write FEAP file\n// FEAP by Bob Taylor, Berkely\n//\n// contact Peter Wriggers or Albrecht Rieger, Hannover\n// rieger@ibnm.uni-hannover.de\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n  extern MeshingParameters mparam;\n\n\n\nvoid WriteFEAPFormat (const Mesh & mesh,\n\t\t      const filesystem::path & filename)\n  \n{\n  // Feap format by A. Rieger \n  // rieger@ibnm.uni-hannover.de\n\n  int inverttets = mparam.inverttets;\n  //int invertsurf = mparam.inverttrigs;\n\n  int i, j;\n\n  double scale = 1;   // globflags.GetNumFlag (\"scale\", 1);\n  \n  ofstream outfile(filename);\n \n  outfile << \"feap\" << \"\\n\";\n  outfile << mesh.GetNP();\n  outfile << \",\";\n  outfile << mesh.GetNE();\n  outfile << \",\";\n  outfile << \"1,3,3,4\" << \"\\n\" << \"\\n\"; \n  outfile << \"!numnp,numel,nummat,ndm,ndf,nen\";\n  outfile << \"\\n\";\n      \n  outfile << \"\\n\" << \"\\n\";\n  outfile << \"!node,,         X           Y           Z\" << \"\\n\";\n  outfile << \"COOR\" << \"\\n\";\n  outfile.precision(4);\n  outfile.setf (ios::fixed, ios::floatfield);\n  outfile.setf (ios::showpoint);\n\n  for (i = 1; i <= mesh.GetNP(); i++)\n    {\n      outfile.width(5);\n      outfile << i;\n      outfile << \",,\";\n      outfile.width(10);\n      outfile << mesh.Point(i)(0)/scale << \"  \";\n      outfile.width(10);\n      outfile << mesh.Point(i)(1)/scale << \"  \";\n      outfile.width(10);\n      outfile << mesh.Point(i)(2)/scale << \"\\n\";\n    }   \n      \n  outfile << \"\\n\" << \"\\n\";\n  outfile << \"!elm,,mat,     n1      n2      n3      n4\" << \"\\n\";\n  outfile << \"ELEM\" << \"\\n\";\n\n  for (i = 1; i <= mesh.GetNE(); i++)\n    {\n      Element el = mesh.VolumeElement(i);\n      if (inverttets)\n\tel.Invert();\n\n\n      outfile.width(5);\n      outfile << i;\n      outfile << \",,\";\n      outfile << el.GetIndex();\n      outfile << \",\";\n\n\n      for (j = 1; j <= el.NP(); j++)\n\t{\n\t  outfile.width(8);\n\t  outfile << el.PNum(j);\n\t}\n      outfile << \"\\n\";\n    }\n      \n  outfile << \"\\n\" << \"\\n\";\n      \n      \n  /*\n\n  //outfile << \"SLOA\" << \"\\n\";\n  //outfile << \"2,3,3\" << \"\\n\";\n  //outfile << GetNSE() << \"\\n\";\n  outfile << \"selm\" << \"\\n\" << GetNSE() << \"\\n\";\n  for (i = 1; i <= GetNSE(); i++)\n  {\n  if (SurfaceElement(i).GetIndex())\n  {\n  outfile.width(8);\n  outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr;\n  //outfile.width(8);\t  \n  //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domin;\n  //outfile.width(8);\t  \n  //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domout;\n  }\n  else\n  outfile << \"       0       0       0\";\n  \n  \n  Element2d sel = SurfaceElement(i);\n  if (invertsurf)\n  sel.Invert();\n  //outfile.width(8);\n  //outfile << sel.GetNP();\n  //if (facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr == 4)\n  //{\n  for (j = 1; j <= sel.GetNP(); j++)\n  {\n  outfile.width(8);\t  \n  outfile << sel.PNum(j);\n  }\n  //outfile.width(8);\t\n  //outfile << \"0.0\";\n  //outfile.width(8);\t\n  //outfile << \"0.0\";\n  //outfile.width(8);\t\n  //outfile << \"1.0\" << \"\\n\";\n  //}\n  outfile << \"\\n\";\n  //outfile << endl;\n  }\n  */\n\n\n\n  // BEGIN CONTACT OUTPUT\n  /*      \n\t  int masterindex, minionindex;\n\t  cout << \"Master Surface index = \";\n\t  cin >> masterindex;\n\t  cout << \"Minion Surface index  = \";\n\t  cin >> minionindex;\n\n\n\t  // CONTACT SURFACE 1\n\t  outfile << \"\\n\";\n\t  outfile << \"\\n\";\n\t  outfile << \"surface,1\" << \"\\n\";;\n\t  outfile.width(6);\n\t  outfile << \"tria\" << \"\\n\";;\n\t  outfile.width(13);\n\t  outfile << \"facet\" << \"\\n\";;\n\t  zz = 0;\n\t  for (i = 1; i <= mesh.GetNSE(); i++)\n\t  {\n\t  Element2d sel = mesh.SurfaceElement(i);\n\t  if (invertsurf)\n\t  sel.Invert();\n\t  if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == masterindex)\n\t  {\n\t  zz++;\n\t  outfile.width(14);\n\t  outfile << zz;\n\t  outfile << \",,\";\n\t  for (j = 1; j <= sel.GetNP(); j++)\n\t  {\n\t  outfile << sel.PNum(j);\n\t  outfile << \",\";\n\t  }\n\t  outfile << \"\\n\";\n\t  }\n\t  }\n\n\n\t  // CONTACT SURFACE 2\n\t  outfile << \"\\n\";\n\t  outfile << \"\\n\";\n\t  outfile << \"surface,2\" << \"\\n\";;\n\t  outfile.width(6);\n\t  outfile << \"tria\" << \"\\n\";;\n\t  outfile.width(13);\n\t  outfile << \"facet\" << \"\\n\";;\n\t  zz = 0;\n\t  for (i = 1; i <= mesh.GetNSE(); i++)\n\t  {\n\t  \n\t  Element2d sel = mesh.SurfaceElement(i);\n\t  if (invertsurf)\n\t  sel.Invert();\n\t  if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == minionindex)\n\t  {\n\t  zz++;\n\t  outfile.width(14);\n\t  outfile << zz;\n\t  outfile << \",,\";\n\t  for (j = 1; j <= sel.GetNP(); j++)\n\t  {\n\t  outfile << sel.PNum(j);\n\t  outfile << \",\";\n\t  }\n\t  outfile << \"\\n\";\n\t  }\n\t  }\n      \n\t  outfile << \"\\n\";\n\t  outfile << \"\\n\";\n  */      \n      \n  // END CONTACT OUTPUT\n\n  cout << \"done\" << endl;\n}\nstatic RegisterUserFormat reg_feap (\"FEAP Format\", {\".mesh\"}, nullopt, WriteFEAPFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writefluent.cpp",
    "content": "//\n//  Write Fluent file\n//  Johannes Gerstmayr, University Linz\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n\nvoid WriteFluentFormat (const Mesh & mesh,\n\t\t\tconst filesystem::path & filename)\n\n{\n  cout << \"start writing fluent export\" << endl;\n      \n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int nse = mesh.GetNSE();\n  int i, j;\n\n  ofstream outfile (filename);\n  char str[100];\n\n  outfile.precision(6);\n  //outfile.setf (ios::fixed, ios::floatfield);\n  //outfile.setf (ios::showpoint);\n      \n  outfile << \"(0 \\\"Exported file from NETGEN \\\")\" << endl;\n  outfile << \"(0 \\\"Dimension:\\\")\" << endl;\n  outfile << \"(2 3)\" << endl << endl;\n\n  outfile << \"(0 \\\"Nodes:\\\")\" << endl;\n\n  //number of nodes:\n  snprintf (str, size(str), \"(10 (0 1 %x 1))\",np); //hexadecimal!!!\n  outfile << str << endl;\n\n  //nodes of zone 1:\n  snprintf (str, size(str), \"(10 (7 1 %x 1)(\",np); //hexadecimal!!!\n  outfile << str << endl;\n  for (i = 1; i <= np; i++)\n    {\n      const Point3d & p = mesh.Point(i);\n\n      //outfile.width(10);\n      outfile << p.X() << \" \";\n      outfile << p.Y() << \" \";\n      outfile << p.Z() << \"\\n\";\n    }\n  outfile << \"))\" << endl << endl;\n\n  //write faces with elements\n\n  outfile << \"(0 \\\"Faces:\\\")\" << endl;\n\n  Element2d face, face2;\n  int /* i2, */ j2;\n  NgArray<INDEX_3> surfaceelp;\n  NgArray<int> surfaceeli;\n  Array<ElementIndex> locels;\n\n  //no cells=no tets\n  //no faces=2*tets\n\n  int noverbface = 2*ne-nse/2;\n      \n  snprintf (str, size(str), \"(13 (0 1 %x 0))\",(noverbface+nse)); //hexadecimal!!!\n  outfile << str << endl;\n      \n  snprintf (str, size(str), \"(13 (4 1 %x 2 3)(\",noverbface); //hexadecimal!!!\n  outfile << str << endl;\n\n  const_cast<Mesh&> (mesh).BuildElementSearchTree(3);\n\n  for (i = 1; i <= ne; i++)\n    {\n      if (ne > 2000)\n\t{\n\t  if (i%2000 == 0)\n\t    {\n\t      cout << (double)i/(double)ne*100. << \"%\" << endl;\n\t    }\n\t}\n\n      Element el = mesh.VolumeElement(i);\n      //if (inverttets)\n      //  el.Invert();\n\t  \n      //outfile << el.GetIndex() << \"    \";\n      if (el.GetNP() != 4) {cout << \"only tet-meshes supported in write fluent!\" << endl;}\n\t  \n      //faces:\n\t  \n      Box3d box;\n      el.GetBox(mesh.Points(), box);\n      box.IncreaseRel(1e-6);\n\n      mesh.GetIntersectingVolEls(box.PMin(),box.PMax(),locels);\n      // int nel = locels.Size();\n      // int locind;\n\n      //cout << \"nel=\" << nel << endl;\n\n      for (j = 1; j <= el.GetNFaces(); j++)\n\t{\n\t  el.GetFace(j, face);\n\t  face.Invert();\n\t  int eli2 = 0;\n\t  int stopsig = 0;\n\t      \n\t  for (auto locind : locels)\n\t    {\n\t      Element el2 = mesh[locind];\n\t      //if (inverttets)\n\t      //  el2.Invert();\n\n\t      for (j2 = 1; j2 <= el2.GetNFaces(); j2++)\n\t\t{\n\t\t  el2.GetFace(j2, face2);\n\n\t\t  if (face2.HasFace(face)) {eli2 = locind+1; stopsig = 1; break;}\n\t\t}\n\t      if (stopsig) break;\n\t    }\n\t      \n\t  if (eli2==i) cout << \"error in WRITE_FLUENT!!!\" << endl;\n\t      \n\t  if (eli2 > i) //don't write faces two times!\n\t    {\n\t      //i: left cell, eli: right cell\n\t      outfile << hex << face.PNum(2) << \" \"\n\t\t<< hex << face.PNum(1) << \" \"\n\t\t<< hex << face.PNum(3) << \" \"\n\t\t<< hex << i  << \" \"\n\t\t<< hex << eli2 << \"\\n\";\n\t    }\n\t  if (eli2 == 0) \n\t    {\n\t      surfaceelp.Append(INDEX_3(face.PNum(2),face.PNum(1),face.PNum(3)));\n\t      surfaceeli.Append(i);\n\t    }\n\t}\n    }\n  outfile << \"))\" << endl;\n      \n  snprintf (str, size(str), \"(13 (2 %x %x 3 3)(\",(noverbface+1),noverbface+nse); //hexadecimal!!!\n  outfile << str << endl;\n\n  for (i = 1; i <= surfaceelp.Size(); i++)\n    {\n      outfile << hex << surfaceelp.Get(i).I1() << \" \"\n\t      << hex << surfaceelp.Get(i).I2() << \" \"\n\t      << hex << surfaceelp.Get(i).I3() << \" \"\n\t      << hex << surfaceeli.Get(i) << \" \" << 0 << \"\\n\";\n    }\n\n  outfile << \"))\" << endl << endl;\n\n  outfile << \"(0 \\\"Cells:\\\")\" << endl;\n      \n  snprintf (str, size(str), \"(12 (0 1 %x 0))\",ne); //hexadecimal!!!\n  outfile << str << endl;\n\n  snprintf (str, size(str), \"(12 (1 1 %x 1 2))\",ne); //hexadecimal!!!\n  outfile << str << endl << endl;\n\n\n\n\n  outfile << \"(0 \\\"Zones:\\\")\\n\"\n\t  << \"(45 (1 fluid fluid)())\\n\"\n    //      << \"(45 (2 velocity-inlet velocity_inlet.1)())\\n\"\n    //      << \"(45 (3 pressure-outlet pressure_outlet.2)())\\n\"\n\t  << \"(45 (2 wall wall)())\\n\"\n\t  << \"(45 (4 interior default-interior)())\\n\" << endl;\n\n  cout << \"done\" << endl;\n}\n\nstatic RegisterUserFormat reg_fluent (\"Fluent Format\", {\".mesh\"}, nullopt, WriteFluentFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writegmsh.cpp",
    "content": "/*************************************\n * Write Gmsh file\n * First issue the 04/26/2004 by Paul CARRICO (paul.carrico@free.fr)\n * At the moment, the GMSH format is available for\n * linear tetrahedron elements i.e. in 3D\n * (based on Neutral Format)\n *\n * Second issue the 05/05/2004 by Paul CARRICO\n * Thanks to Joachim Schoeberl for the correction of a minor bug\n * the 2 initial Gmsh Format (i.e. volume format and surface format) are group together)\n * in only one file\n **************************************/\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n  extern MeshingParameters mparam;\n\n\n/*\n *  GMSH mesh format\n *  points, elements, surface elements and physical entities\n */\n\nvoid WriteGmshFormat (const Mesh & mesh,\n                      const filesystem::path & filename)\n{\n  ofstream outfile (filename);\n  outfile.precision(6);\n  outfile.setf (ios::fixed, ios::floatfield);\n  outfile.setf (ios::showpoint);\n\n  int np = mesh.GetNP();  /// number of point\n  int ne = mesh.GetNE();  /// number of element\n  int nse = mesh.GetNSE();  /// number of surface element (BC)\n  int i, j, k, l;\n\n\n  /*\n   * 3D section : Linear volume elements (only tetrahedra)\n   */\n\n   if (ne > 0 && mesh.VolumeElement(1).GetNP() == 4)\n      {\n      cout << \"Write GMSH Format \\n\";\n      cout << \"The GMSH format is available for linear tetrahedron elements only in 3D\\n\" << endl;\n\n      int inverttets = mparam.inverttets;\n      int invertsurf = mparam.inverttrigs;\n\n\n      /// Write nodes\n      outfile << \"$NOD\\n\";\n      outfile << np << \"\\n\";\n  \n      for (i = 1; i <= np; i++)\n          {\n          const Point3d & p = mesh.Point(i);\n          outfile << i << \" \"; /// node number\n          outfile << p.X() << \" \";\n          outfile << p.Y() << \" \";\n          outfile << p.Z() << \"\\n\";\n          }\n      outfile << \"$ENDNOD\\n\";\n\n      /// write elements\n      outfile << \"$ELM\\n\";\n      outfile << ne + nse << \"\\n\";  ////  number of elements + number of surfaces BC\n\n     for (i = 1; i <= nse; i++)\n         {\n         Element2d el = mesh.SurfaceElement(i);\n         if (invertsurf) el.Invert();\n         outfile << i;\n         outfile << \" \";\n         outfile << \"2\";\n         outfile << \" \";\n         outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n         /// that means that physical entity = elementary entity (arbitrary approach)\n         outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n         outfile << \"3\";\n         outfile << \" \";\n                 for (j = 1; j <= el.GetNP(); j++)\n                     {\n                     outfile << \" \";\n                     outfile << el.PNum(j);\n                     }\n                     outfile << \"\\n\";\n         }\n\n\n         for (i = 1; i <= ne; i++)\n             {\n             Element el = mesh.VolumeElement(i);\n             if (inverttets) el.Invert();\n             outfile << nse + i; /// element number\n             outfile << \" \";\n             outfile << \"4\"; /// element type i.e. Tetraedron == 4\n             outfile << \" \";\n             outfile << 100000 + el.GetIndex();\n             /// that means that physical entity = elementary entity (arbitrary approach)\n             outfile << \" \";\n             outfile << 100000 + el.GetIndex();   /// volume number\n             outfile << \" \";\n             outfile << \"4\";  /// number of nodes i.e. 4 for a tetrahedron\n                                                                                                        \n             for (j = 1; j <= el.GetNP(); j++)\n                 {\n                 outfile << \" \";\n                 outfile << el.PNum(j);\n                 }\n             outfile << \"\\n\";\n             }\n\n\n             outfile << \"$ENDELM\\n\";\n   }\n\n   /*\n    * End of 3D section\n    */\n\n\n\n\n\n  /*\n   * 2D section : available for triangles and quadrangles\n   */\n      else if (ne == 0)   /// means that there's no 3D element\n              {\n              cout << \"\\n Write Gmsh Surface Mesh (triangle and/or quadrangles)\" << endl;\n\n              /// Write nodes\n              outfile << \"$NOD\\n\";\n              outfile << np << \"\\n\";\n\n              for (i = 1; i <= np; i++)\n              {\n              const Point3d & p = mesh.Point(i);\n              outfile << i << \" \"; /// node number\n              outfile << p.X() << \" \";\n              outfile << p.Y() << \" \";\n              outfile << p.Z() << \"\\n\";\n              }\n              outfile << \"$ENDNOD\\n\";\n\n\n              /// write triangles & quadrangles\n              outfile << \"$ELM\\n\";\n              outfile << nse << \"\\n\";\n\n              for (k = 1; k <= nse; k++)\n              {\n              const Element2d & el = mesh.SurfaceElement(k);\n\n\n              outfile << k;\n              outfile << \" \";\n              outfile << (el.GetNP()-1);   // 2 for a triangle and 3 for a quadrangle\n              outfile << \" \";\n              outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n              /// that means that physical entity = elementary entity (arbitrary approach)\n              outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n              outfile << (el.GetNP());    // number of node per surfacic element\n              outfile << \" \";\n\n              for (l = 1; l <= el.GetNP(); l++)\n                  {\n                  outfile << \" \";\n                  outfile << el.PNum(l);\n                  }\n\t              outfile << \"\\n\";\n\t\t  \n               }\n               outfile << \"$ENDELM$ \\n\";\n    }\n\n   /*\n    * End of 2D section\n    */\n\n     else\n    {\n    cout << \" Invalid element type for Gmsh volume Format !\\n\";\n    }\n\n\n}\nstatic RegisterUserFormat reg_gmsh (\"Gmsh Format\", {\".gmsh\"}, nullopt, WriteGmshFormat);\n}\n\n\n"
  },
  {
    "path": "libsrc/interface/writegmsh2.cpp",
    "content": "/*! \\file writegmsh2.cpp\n*  \\brief Export Netgen Mesh in the GMSH v2.xx File format\n*  \\author Philippose Rajan\n*  \\date 02 November 2008\n*\n*  This function extends the export capabilities of\n*  Netgen to include the GMSH v2.xx File Format.\n*\n*  Current features of this function include:\n*\n*  1. Exports Triangles, Quadrangles and Tetrahedra \\n\n*  2. Supports upto second order elements of each type\n*\n*/\n\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n  extern MeshingParameters mparam;\n\n   // Mapping of entities from Netgen definitions to GMSH definitions\n   enum GMSH_ELEMENTS {GMSH_TRIG = 2, GMSH_TRIG6 = 9,\n      GMSH_QUAD = 3, GMSH_QUAD8 = 16,\n      GMSH_TET = 4, GMSH_TET10 = 11};\n   const int triGmsh[7] = {0,1,2,3,6,4,5};\n   const int quadGmsh[9] = {0,1,2,3,4,5,8,6,7};\n   const int tetGmsh[11] = {0,1,2,3,4,5,8,6,7,10,9};\n\n\n   /*! GMSH v2.xx mesh format export function\n   *\n   *  This function extends the export capabilities of\n   *  Netgen to include the GMSH v2.xx File Format.\n   *\n   *  Current features of this function include:\n   *\n   *  1. Exports Triangles, Quadrangles and Tetrahedra \\n\n   *  2. Supports upto second order elements of each type\n   *\n   */\n   void WriteGmsh2Format (const Mesh & mesh,\n      const filesystem::path & filename)\n   {\n      ofstream outfile (filename);\n      outfile.precision(6);\n      outfile.setf (ios::fixed, ios::floatfield);\n      outfile.setf (ios::showpoint);\n\n      int np = mesh.GetNP();  /// number of points in mesh\n      int ne = mesh.GetNE();  /// number of 3D elements in mesh\n      int nse = mesh.GetNSE();  /// number of surface elements (BC)\n      // int i, j, k, l;\n\n\n      /*\n      * 3D section : Volume elements (currently only tetrahedra)\n      */\n\n      if ((ne > 0)\n          && (mesh.VolumeElements().First().GetNP() <= 10)\n          && (mesh.SurfaceElements().First().GetNP() <= 6))\n      {\n         cout << \"Write GMSH v2.xx Format \\n\";\n         cout << \"The GMSH v2.xx export is currently available for elements upto 2nd Order\\n\" << endl;\n\n         int inverttets = mparam.inverttets;\n         int invertsurf = mparam.inverttrigs;\n\n         /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation)\n         outfile << \"$MeshFormat\\n\";\n         outfile << (float)2.0 << \" \"\n            << (int)0 << \" \"\n            << (int)sizeof(double) << \"\\n\";\n         outfile << \"$EndMeshFormat\\n\";\n\n         /// Write nodes\n         outfile << \"$Nodes\\n\";\n         outfile << np << \"\\n\";\n\n         for (int i = 1; i <= np; i++)\n         {\n            const Point3d & p = mesh.Point(i);\n            outfile << i << \" \"; /// node number\n            outfile << p.X() << \" \";\n            outfile << p.Y() << \" \";\n            outfile << p.Z() << \"\\n\";\n         }\n\n         outfile << \"$EndNodes\\n\";\n\n         /// write elements (both, surface elements and volume elements)\n         outfile << \"$Elements\\n\";\n         outfile << ne + nse << \"\\n\";  ////  number of elements + number of surfaces BC\n\n         for (auto sei : Range(mesh.SurfaceElements()))\n         {\n            int elType = 0;\n\n            Element2d el = mesh[sei]; // .SurfaceElement(i);\n            if(invertsurf) el.Invert();\n            \n            if(el.GetNP() == 3) elType = GMSH_TRIG;\t//// GMSH Type for a 3 node triangle\n            if(el.GetNP() == 6) elType = GMSH_TRIG6;  //// GMSH Type for a 6 node triangle\n            if(elType == 0)\n            {\n               cout << \" Invalid surface element type for Gmsh 2.0 3D-Mesh Export Format !\\n\";\n               return;\n            }\n\n            outfile << sei-IndexBASE(sei)+1;  \n            outfile << \" \";\n            outfile << elType;\n            outfile << \" \";\n            outfile << \"2\";                  //// Number of tags (2 => Physical and elementary entities)\n            outfile << \" \";\n            outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n            /// that means that physical entity = elementary entity (arbitrary approach)\n            outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n            for (int j = 1; j <= el.GetNP(); j++)\n            {\n               outfile << \" \";\n               outfile << el.PNum(triGmsh[j]);\n            }\n            outfile << \"\\n\";\n         }\n\n         for (ElementIndex ei : Range(mesh.VolumeElements()))\n         {\n           int i = ei-IndexBASE(ei)+1;\n            int elType = 0;\n\n            Element el = mesh[ei];\n            if (inverttets) el.Invert();\n\n            if(el.GetNP() == 4) elType = GMSH_TET;    //// GMSH Element type for 4 node tetrahedron\n            if(el.GetNP() == 10) elType = GMSH_TET10; //// GMSH Element type for 10 node tetrahedron\n            if(elType == 0)\n            {\n               cout << \" Invalid volume element type for Gmsh 2.0 3D-Mesh Export Format !\\n\";\n               return;\n            }\n\n            outfile << nse + i;                       //// element number (Remember to add on surface elements)\n            outfile << \" \";\n            outfile << elType;\n            outfile << \" \";\n            outfile << \"2\";                   //// Number of tags (2 => Physical and elementary entities)\n            outfile << \" \";\n            outfile << 100000 + el.GetIndex();\n            /// that means that physical entity = elementary entity (arbitrary approach)\n            outfile << \" \";\n            outfile << 100000 + el.GetIndex();   /// volume number\n            outfile << \" \";\n            for (int j = 1; j <= el.GetNP(); j++)\n            {\n               outfile << \" \";\n               outfile << el.PNum(tetGmsh[j]);\n            }\n            outfile << \"\\n\";\n         }\n         outfile << \"$EndElements\\n\";\n      }\n      /*\n      * End of 3D section\n      */\n\n\n      /*\n      * 2D section : available for triangles and quadrangles\n      *              upto 2nd Order\n      */\n      else if(ne == 0)   /// means that there's no 3D element\n      {\n         cout << \"\\n Write Gmsh v2.xx Surface Mesh (triangle and/or quadrangles upto 2nd Order)\" << endl;\n\n         /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation)\n         outfile << \"$MeshFormat\\n\";\n         outfile << (float)2.0 << \" \"\n            << (int)0 << \" \"\n            << (int)sizeof(double) << \"\\n\";\n         outfile << \"$EndMeshFormat\\n\";\n\n         /// Write nodes\n         outfile << \"$Nodes\\n\";\n         outfile << np << \"\\n\";\n\n         for (int i = 1; i <= np; i++)\n         {\n            const Point3d & p = mesh.Point(i);\n            outfile << i << \" \"; /// node number\n            outfile << p.X() << \" \";\n            outfile << p.Y() << \" \";\n            outfile << p.Z() << \"\\n\";\n         }\n         outfile << \"$EndNodes\\n\";\n\n         /// write triangles & quadrangles\n         outfile << \"$Elements\\n\";\n         outfile << nse << \"\\n\";\n\n         for (int k = 1; k <= nse; k++)\n         {\n            int elType = 0;\n\n            const Element2d & el = mesh.SurfaceElement(k);\n\n            if(el.GetNP() == 3) elType = GMSH_TRIG;   //// GMSH Type for a 3 node triangle\n            if(el.GetNP() == 6) elType = GMSH_TRIG6;  //// GMSH Type for a 6 node triangle\n            if(el.GetNP() == 4) elType = GMSH_QUAD;   //// GMSH Type for a 4 node quadrangle\n            if(el.GetNP() == 8) elType = GMSH_QUAD8;  //// GMSH Type for an 8 node quadrangle\n            if(elType == 0)\n            {\n               cout << \" Invalid surface element type for Gmsh 2.0 2D-Mesh Export Format !\\n\";\n               return;\n            }\n\n            outfile << k;\n            outfile << \" \";\n            outfile << elType;\n            outfile << \" \";\n            outfile << \"2\";\n            outfile << \" \";\n            outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n            /// that means that physical entity = elementary entity (arbitrary approach)\n            outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \" \";\n            for (int l = 1; l <= el.GetNP(); l++)\n            {\n               outfile << \" \";\n               if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6))\n               {\n                  outfile << el.PNum(triGmsh[l]);\n               }\n               else if((elType == GMSH_QUAD) || (elType == GMSH_QUAD8))\n               {\n                  outfile << el.PNum(quadGmsh[l]);\n               }\n            }\n            outfile << \"\\n\";\n         }\n         outfile << \"$EndElements\\n\";\n      }\n      /*\n      * End of 2D section\n      */\n\n      else\n      {\n         cout << \" Invalid element type for Gmsh v2.xx Export Format !\\n\";\n      }\n   } // End: WriteGmsh2Format\nstatic RegisterUserFormat reg_gmsh2 (\"Gmsh2 Format\", {\".gmsh2\"}, nullopt, WriteGmsh2Format);\n} // End: namespace netgen\n\n\n"
  },
  {
    "path": "libsrc/interface/writejcm.cpp",
    "content": "//\n//  Write JCMwave file\n//  07.07.2005, Sven Burger, ZIB Berlin\n//\n\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n#include <sys/stat.h>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\nvoid WriteJCMFormat (const Mesh & mesh,\n                     const filesystem::path & filename)\n{\n  if (mesh.GetDimension() != 3)\n  {\n    cout <<\"\\n Error: Dimension 3 only supported by this output format!\"<<endl;\n    return;\n  }\n\n  int bc_at_infinity = 0;\n  int i, j, jj, ct(0), counter;\n  double dx1, dx2, dx3, dy1, dy2, dy3, dz1, dz2, dz3, vol;\n\n  // number of points\n  int np = mesh.GetNP();\n\n  // Identic points\n  idmap_type identmap1, identmap2, identmap3;\n  mesh.GetIdentifications().GetMap(1, identmap1);\n  mesh.GetIdentifications().GetMap(2, identmap2);\n  mesh.GetIdentifications().GetMap(3, identmap3);\n\n  // number of volume elements\n  int ne = mesh.GetNE();\n  int ntets = 0;\n  int nprisms = 0;\n  for (i = 1; i <= ne; i++)\n  {\n    Element el = mesh.VolumeElement(i);\n    if (el.GetNP() == 4)\n    {\n      ntets++;\n      // Check that no two points on a tetrahedron are identified with each other\n      for (j = 1; j <= 4; j++)\n        for (jj = 1; jj <=4; jj++)\n        {\n          // if (identmap1.Elem(el.PNum(j)) == el.PNum(jj))\n          if (identmap1[el.PNum(j)] == el.PNum(jj))          \n          {\n            cout << \"\\n Error: two points on a tetrahedron identified (1) with each other\"\n                 << \"\\n REFINE MESH !\" << endl;\n            return;\n          }\n          // if (identmap2.Elem(el.PNum(j)) == el.PNum(jj))\n          if (identmap2[el.PNum(j)] == el.PNum(jj))          \n          {\n            cout << \"\\n Error: two points on a tetrahedron identified (2) with each other\"\n                 << \"\\n REFINE MESH !\" << endl;\n            return;\n          }\n          if (identmap3[el.PNum(j)] == el.PNum(jj))\n          {\n            cout << \"\\n Error: two points on a tetrahedron identified (3) with each other\"\n                 << \"\\n REFINE MESH !\" << endl;\n            return;\n          }\n        }      \n      \n    }\n    else if (el.GetNP() == 6)\n      nprisms++;\n  }\n  if ( ne != (ntets+nprisms))\n  {\n    cout<< \"\\n Error in determining number of volume elements!\\n\"\n        << \"\\n Prisms and tetrahedra only implemented in the JCMwave format!\\n\"<<endl;\n    return;\n  }\n\n  if (nprisms > 0)\n    cout << \" Please note: Boundaries at infinity have to carry the bc-attribute '-bc=\"\n         << bc_at_infinity <<\"'.\"<<endl; \n\n  // number of surface elements\n  int nse = mesh.GetNSE();\n  // number of boundary triangles\n  int nbtri = 0;\n  // number of boundary quadrilaterals\n  int nbquad = 0;\n  // array with 1 if point on any tetra, 0 else \n  // this is needed in order to arrange the prism points in the right order\n  NgArray<int,1> pointsOnTetras;\n  pointsOnTetras.SetSize (mesh.GetNP());\n  pointsOnTetras = 0;\n  for (i = 1; i <= ne; i++)\n  {\n    Element el = mesh.VolumeElement(i);\n    if (el.GetNP() == 4)\n    {\n      for (j = 1; j <= 4; j++)\n        pointsOnTetras.Set(int (el.PNum(j)),1);     \n    }\n  }\n\n  // number of boundary triangles and boundary quadrilaterals\n  for (i = 1; i <= nse; i++)\n  {\n    Element2d el = mesh.SurfaceElement(i);\n    if (el.GetNP() == 3 &&\n        ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0  ||\n          mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) )\n      nbtri++;\n    else if (el.GetNP() == 4 &&\n             ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 ||\n               mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) )\n      nbquad++;\n  }\n  \n  ofstream outfile (filename);\n  outfile.precision(6);\n  outfile.setf (ios::fixed, ios::floatfield);\n  outfile.setf (ios::showpoint);\n  \n  outfile << \"/* <BLOBHead>\\n\";\n  outfile << \"__BLOBTYPE__=Grid\\n\";\n  outfile << \"__OWNER__=JCMwave\\n\";\n  outfile << \"<I>SpaceDim=3\\n\";\n  outfile << \"<I>ManifoldDim=3\\n\";\n  outfile << \"<I>NRefinementSteps=0\\n\";\n  outfile << \"<I>NPoints=\"<<np<<\"\\n\";\n  outfile << \"<I>NTetrahedra=\"<<ntets<<\"\\n\";\n  outfile << \"<I>NPrisms=\"<<nprisms<<\"\\n\";\n  outfile << \"<I>NBoundaryTriangles=\"<<nbtri<<\"\\n\";\n  outfile << \"<I>NBoundaryQuadrilaterals=\"<<nbquad<<\"\\n\";\n  outfile << \"*/\\n\";\n  outfile << \"\\n\";\n  outfile << \"# output from Netgen\\n\\n\";\n  int nDomains=mesh.GetNDomains();\n  for (i=1; i<=nDomains; i++)\n  {\n    if (mesh.GetMaterialPtr(i))\n      outfile << \"#\" << mesh.GetMaterial(i) \n              << \": Material ID = \" \n              << i << \"\\n\";\n  }\n\n  outfile << \"# Points\\n\";\n  cout << \" Please note: The unit of length in the .geo file is assumed to be 'microns'.\"<<endl; \n  for (i = 1; i <= np; i++)\n  {\n    const Point<3> & p = mesh.Point(i);\n    outfile << i << \"\\n\";\n    outfile << p(0) << \"e-6\\n\";\n    outfile << p(1) << \"e-6\\n\";\n    outfile << p(2) << \"e-6\\n\\n\";\n  }\n\n  outfile << \"\\n\";\n  outfile << \"# Tetrahedra\\n\";\n  counter = 0;\n  for (i = 1; i <= ne; i++)\n  {\n    Element el = mesh.VolumeElement(i);\n    if (el.GetNP() == 4)\n    {\n      counter++;\n      dx1 = mesh.Point(el.PNum(2))(0) - mesh.Point(el.PNum(1))(0);\n      dx2 = mesh.Point(el.PNum(3))(0) - mesh.Point(el.PNum(1))(0);\n      dx3 = mesh.Point(el.PNum(4))(0) - mesh.Point(el.PNum(1))(0);\n      dy1 = mesh.Point(el.PNum(2))(1) - mesh.Point(el.PNum(1))(1);\n      dy2 = mesh.Point(el.PNum(3))(1) - mesh.Point(el.PNum(1))(1);\n      dy3 = mesh.Point(el.PNum(4))(1) - mesh.Point(el.PNum(1))(1);\n      dz1 = mesh.Point(el.PNum(2))(2) - mesh.Point(el.PNum(1))(2);\n      dz2 = mesh.Point(el.PNum(3))(2) - mesh.Point(el.PNum(1))(2);\n      dz3 = mesh.Point(el.PNum(4))(2) - mesh.Point(el.PNum(1))(2);\n      vol = (dy1*dz2-dz1*dy2)*dx3 + (dz1*dx2-dx1*dz2)*dy3 + (dx1*dy2-dy1*dx2)*dz3;\n\n      if ( vol > 0 )\n        for (j = 1; j <= 4; j++)\n          outfile << el.PNum(j)<<\"\\n\";\n      else\n      {\n        for (j = 2; j >= 1; j--)\n          outfile << el.PNum(j)<<\"\\n\";\n        for (j = 3; j <= 4; j++)\n          outfile << el.PNum(j)<<\"\\n\";\n      }  \n      outfile << el.GetIndex() << \"\\n\\n\";\n    }\n  }\n  if ( counter != ntets)\n  {\n    cout<< \"\\n Error in determining number of tetras!\\n\"<<endl;\n    return;\n  }\n\n  outfile << \"\\n\";\n  outfile << \"# Prisms\\n\";\n  counter = 0;\n  for (i = 1; i <= ne; i++)\n  {\n    Element el = mesh.VolumeElement(i);\n    if (el.GetNP() == 6)\n    {\n      counter++;\n      dx1 = mesh.Point(el.PNum(2))(0) - mesh.Point(el.PNum(1))(0);\n      dx2 = mesh.Point(el.PNum(3))(0) - mesh.Point(el.PNum(1))(0);\n      dx3 = mesh.Point(el.PNum(4))(0) - mesh.Point(el.PNum(1))(0);\n      dy1 = mesh.Point(el.PNum(2))(1) - mesh.Point(el.PNum(1))(1);\n      dy2 = mesh.Point(el.PNum(3))(1) - mesh.Point(el.PNum(1))(1);\n      dy3 = mesh.Point(el.PNum(4))(1) - mesh.Point(el.PNum(1))(1);\n      dz1 = mesh.Point(el.PNum(2))(2) - mesh.Point(el.PNum(1))(2);\n      dz2 = mesh.Point(el.PNum(3))(2) - mesh.Point(el.PNum(1))(2);\n      dz3 = mesh.Point(el.PNum(4))(2) - mesh.Point(el.PNum(1))(2);\n      vol = (dy1*dz2-dz1*dy2)*dx3 + (dz1*dx2-dx1*dz2)*dy3 + (dx1*dy2-dy1*dx2)*dz3;\n\n      if (pointsOnTetras.Get(el.PNum(1)) &&\n          pointsOnTetras.Get(el.PNum(2)) &&\n          pointsOnTetras.Get(el.PNum(3)))\n      {\n        if (vol > 0)\n          for (j = 1; j <= 6; j++)\n            outfile << el.PNum(j)<<\"\\n\";\n        else\n        {\n          for (j = 3; j >= 1; j--)\n            outfile << el.PNum(j)<<\"\\n\";\n          for (j = 6; j >= 4; j--)\n            outfile << el.PNum(j)<<\"\\n\";\n        }\n      }\n      else if ( pointsOnTetras.Get(el.PNum(4)) &&\n                pointsOnTetras.Get(el.PNum(5)) &&\n                pointsOnTetras.Get(el.PNum(6))    )\n      {\n        if ( vol < 0 )\n        {\n          for (j = 4; j <= 6; j++)\n            outfile << el.PNum(j)<<\"\\n\";\n          for (j = 1; j <= 3; j++)\n            outfile << el.PNum(j)<<\"\\n\";\n        }\n        else\n        {\n          for (j = 6; j >= 4; j--)\n            outfile << el.PNum(j)<<\"\\n\";\n          for (j = 3; j >= 1; j--)\n            outfile << el.PNum(j)<<\"\\n\";\n        }\n      }\n      else \n      {\n        cout << \"\\n Error in determining prism point numbering!\\n\"<<endl;\n        return;\n      }\n      outfile << el.GetIndex() << \"\\n\\n\";\n    }\n  }\n  if ( counter != nprisms)\n  {\n    cout<< \"\\n Error in determining number of prisms!\\n\"<<endl;\n    return;\n  }\n\n  int npid1 = 0;\n  int npid2 = 0;\n  int npid3 = 0;\n  /*\n  for (i=1; i<=np; i++)\n  {\n    if (identmap1.Elem(i))\n      npid1++;\n    if (identmap2.Elem(i))\n      npid2++;\n    if (identmap3.Elem(i))\n      npid3++;\n  }\n  */\n  for (auto pi : identmap1) if (pi.IsValid()) npid1++;\n  for (auto pi : identmap2) if (pi.IsValid()) npid1++;\n  for (auto pi : identmap3) if (pi.IsValid()) npid1++;\n\n  outfile << \"\\n\";\n  outfile << \"# Boundary triangles\\n\";  \n  outfile << \"# Number of identified points in 1-direction: \" << npid1 << \"\\n\";\n  outfile << \"# Number of identified points in 2-direction: \" << npid2 << \"\\n\";\n  outfile << \"# Number of identified points in 3-direction: \" << npid3 << \"\\n\";\n  for (i = 1; i <= nse; i++)\n  {\n    Element2d el = mesh.SurfaceElement(i);\n    if (el.GetNP() == 3\n        && (mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0\n            || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0))\n    {\n      outfile <<\"# T\\n\";\n      for (j = 1; j <= 3; j++)\n        outfile << el.PNum(j)<<\"\\n\";\n      if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty()==bc_at_infinity)\n        outfile << 1000 << \"\\n\";      \n      else\n        outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \"\\n\";      \n      if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity)\n        outfile << \"-2\\n\\n\";\n      else if (identmap1[el.PNum(1)].IsValid()\n               &&identmap1[el.PNum(2)].IsValid()\n               &&identmap1[el.PNum(3)].IsValid())\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 3; j++)\n          outfile << identmap1[el.PNum(j)]<<\"\\n\";\n        outfile << \"\\n\";\n      }\n      else if (identmap2[el.PNum(1)].IsValid()\n               &&identmap2[el.PNum(2)].IsValid()\n               &&identmap2[el.PNum(3)].IsValid())\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 3; j++)\n          outfile << identmap2[el.PNum(j)]<<\"\\n\";\n        outfile << \"\\n\";\n      }\n      else if (identmap3[el.PNum(1)].IsValid()\n               &&identmap3[el.PNum(2)].IsValid()\n               &&identmap3[el.PNum(3)].IsValid())\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 3; j++)\n          outfile << identmap3[el.PNum(j)]<<\"\\n\";\n        outfile << \"\\n\";\n      }\n      else\n        outfile << \"1\\n\\n\";\n        \n    }\n  }\n\n  outfile << \"\\n\";\n  outfile << \"# Boundary quadrilaterals\\n\";\n  for (i = 1; i <= nse; i++)\n  {\n    Element2d el = mesh.SurfaceElement(i);\n\n    if (el.GetNP() == 4\n        && (mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0\n            || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0))\n    {\n      if      (pointsOnTetras.Get(el.PNum(1)) &&\n               pointsOnTetras.Get(el.PNum(2)))\n        ct = 0;\n      else if (pointsOnTetras.Get(el.PNum(2)) &&\n               pointsOnTetras.Get(el.PNum(3)))\n        ct = 1;\n      else if (pointsOnTetras.Get(el.PNum(3)) &&\n               pointsOnTetras.Get(el.PNum(4)))\n        ct = 2;\n      else if (pointsOnTetras.Get(el.PNum(4)) &&\n               pointsOnTetras.Get(el.PNum(1)))\n        ct = 3;\n      else\n        cout << \"\\nWarning: Quadrilateral with inconsistent points found!\"<<endl;\n      \n      for (j = 1; j <= 4; j++)\n      {\n        jj = j + ct;\n        if ( jj >= 5 )\n          jj = jj - 4;\n        outfile << el.PNum(jj)<<\"\\n\";\n      }\n      outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \"\\n\";      \n      if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity)\n      {\n        outfile << \"-2\\n\\n\";\n        cout << \"\\nWarning: Quadrilateral at infinity found (this should not occur)!\"<<endl;\n      }\n      else if ( identmap1[el.PNum(1)].IsValid() &&\n                identmap1[el.PNum(2)].IsValid() &&\n                identmap1[el.PNum(3)].IsValid() &&\n                identmap1[el.PNum(4)].IsValid())\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 4; j++)\n        {\n          jj = j + ct;\n          if ( jj >= 5 )\n            jj = jj - 4;\n          outfile << identmap1[el.PNum(jj)]<<\"\\n\";\n        }\n        outfile << \"\\n\";\n      }\n      else if ( identmap2[el.PNum(1)].IsValid() &&\n                identmap2[el.PNum(2)].IsValid() &&\n                identmap2[el.PNum(3)].IsValid() &&\n                identmap2[el.PNum(4)].IsValid() )\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 4; j++)\n        {\n          jj = j + ct;\n          if ( jj >= 5 )\n            jj = jj - 4;\n          outfile << identmap2[el.PNum(jj)] <<\"\\n\";\n        }\n        outfile << \"\\n\";\n      }\n      else if ( identmap3[el.PNum(1)].IsValid() &&\n                identmap3[el.PNum(2)].IsValid() &&\n                identmap3[el.PNum(3)].IsValid() &&\n                identmap3[el.PNum(4)].IsValid() )\n      {\n        outfile << \"-1\\n\";\n        for (j = 1; j <= 4; j++)\n        {\n          jj = j + ct;\n          if ( jj >= 5 )\n            jj = jj - 4;\n          outfile << identmap3[el.PNum(jj)]<<\"\\n\";\n        }\n        outfile << \"\\n\";\n      }\n      else\n        outfile << \"1\\n\\n\";\n    }\n  }\n\n  cout << \" JCMwave grid file written.\" << endl;\n}\n\nstatic RegisterUserFormat reg_jcmwave (\"JCMwave Format\", {\".jcm\"}, nullopt, WriteJCMFormat);\n}\n\n"
  },
  {
    "path": "libsrc/interface/writepermas.cpp",
    "content": "//\n// Write Permas file\n// for Intes GmbH, Stuttgart\n//\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include <string>\n\n#include \"writeuser.hpp\"\nusing namespace std;\n\nnamespace netgen\n{\n    // Forward declarations (don't know, where to define them, sorry)\n    int addComponent(string &strComp, string &strSitu, ofstream &out);\n\n    void WritePermasFormat (const Mesh &mesh, const filesystem::path &filename);\n\n    // This should be the new function to export a PERMAS file\n    void WritePermasFormat (const Mesh &mesh, const filesystem::path &filename, \n                            string &strComp, string &strSitu) \n    {\n        ofstream outfile (filename);\n        addComponent(strComp, strSitu, outfile);\n        WritePermasFormat ( mesh, filename);\n    }\n\n    void WritePermasFormat (const Mesh &mesh, const filesystem::path &filename)\n    {\n        string strComp, strSitu;\n        ofstream outfile (filename);\n        \n        outfile.precision(8);\n\n        strSitu = strComp = \"\";\n        if (addComponent(strComp, strSitu, outfile) == 1) {\n            printf(\"Error while exporting PERMAS dat!\\n\");\n            return;\n        }\n    \n        int np = mesh.GetNP();\n        int ne = mesh.GetNE();\n        int nse = mesh.GetNSE();\n        int i, j, k;\n    \n        if (ne == 0)\n        {\n            // pure surface mesh\n            cout << \"\\nWrite Permas Surface Mesh\" << endl;\n            \n            int elnr = 0;\n            for (j = 1; j <= 2; j++)\n            {\n                int nelp(0);\n                switch (j)\n                {\n                case 1:\n                    nelp = 3;\n                    outfile << \"$ELEMENT TYPE = TRIA3  ESET = ALLQUAD\" << endl;\t\t  \n                    break;\n                case 2:\n                    nelp = 4;\n                    outfile << \"$ELEMENT TYPE = QUAD4  ESET = ALLQUAD\" << endl;\t\t  \n                    break;\n                }\n                \n                for (i = 1; i <= nse; i++)\n                {\n                    const Element2d & el = mesh.SurfaceElement(i);\n                    if (el.GetNP() != nelp)\n                        continue;\n                    \n                    elnr++;\n                    outfile << elnr << \"  \";\n                    for (k = 1; k <= nelp; k++)\n                        outfile << \" \" << el.PNum(k);\n                    outfile << endl;\n                    \n                }\n            }\n        }\n        else\n        {\n            cout << \"\\nWrite Permas Volume Mesh\" << endl;\n            \n            int secondorder = (mesh.VolumeElement(1).GetNP() == 10);\n            \n            if (!secondorder)\n            {\n                outfile << \"$ELEMENT TYPE = TET4  ESET = ALLTET\" << endl;\n                for (i = 1; i <= ne; i++)\n                {\n                    const Element & el = mesh.VolumeElement(i);\n                    outfile << i \n                            << \" \" << el.PNum(1) \n                            << \" \" << el.PNum(2) \n                            << \" \" << el.PNum(4) \n                            << \" \" << el.PNum(3) << endl;\n                }\n            }\n            else\n            {\n                outfile << \"$ELEMENT TYPE = TET10  ESET = ALLTET\" << endl;\n                for (i = 1; i <= ne; i++)\n                {\n                    const Element & el = mesh.VolumeElement(i);\n                    outfile << i \n                            << \" \" << el.PNum(1) \n                            << \" \" << el.PNum(5) \n                            << \" \" << el.PNum(2) \n                            << \" \" << el.PNum(8) \n                            << \" \" << el.PNum(3) \n                            << \" \" << el.PNum(6) << endl << \"& \"\n                            << \" \" << el.PNum(7) \n                            << \" \" << el.PNum(9) \n                            << \" \" << el.PNum(10) \n                            << \" \" << el.PNum(4) << endl;\n                }\n            }\n            \n            outfile << endl << endl;\n            \n            \n            outfile << \"$SURFACE GEO  SURFID = 1  SFSET = ALLSUR\" << endl;\n            for (i = 1; i <= nse; i++)\n            {\n                const Element2d & el = mesh.SurfaceElement(i);\n                if (el.GetNP() == 3)\n                    outfile << \"STRIA3\"\n                            << \" \" << el.PNum(1) \n                            << \" \" << el.PNum(2) \n                            << \" \" << el.PNum(3) << endl;\n            }    \n            \n            for (i = 1; i <= nse; i++)\n            {\n                const Element2d & el = mesh.SurfaceElement(i);\n                if (el.GetNP() == 4)\n                    outfile << \"SQUAD4\"\n                            << \" \" << el.PNum(1) \n                            << \" \" << el.PNum(2) \n                            << \" \" << el.PNum(3) \n                            << \" \" << el.PNum(4) << endl;\n            }      \n            \n            for (i = 1; i <= nse; i++)\n            {\n                const Element2d & el = mesh.SurfaceElement(i);\n                if (el.GetNP() == 6)\n                    outfile << \"STRIA6\"\n                            << \" \" << el.PNum(1) \n                            << \" \" << el.PNum(4) \n                            << \" \" << el.PNum(2) \n                            << \" \" << el.PNum(5) \n                            << \" \" << el.PNum(3) \n                            << \" \" << el.PNum(6) << endl;\n            }      \n        }\n        \n        \n        outfile << endl << endl;\n        \n        outfile << \"$COOR  NSET = ALLNODES\" << endl;\n        \n        outfile.precision(6);\n        outfile.setf (ios::fixed, ios::floatfield);\n        outfile.setf (ios::showpoint);\n        \n        for (i = 1; i <= np; i++)\n        {\n            outfile << i << \" \";\n            outfile << mesh.Point(i)(0) << \" \";\n            outfile << mesh.Point(i)(1) << \" \";\n            outfile << mesh.Point(i)(2) << \"\\n\";\n        }\n    }\n    ////////////////////////////////////////////////////////////////////////////////// \n    // \\brief Writes PERMAS configuration header into export file\n    //        Returns >0 in case of errors\n    // \\par string &strComp  : Reference to component description\n    // \\par string &strComp  : Reference to situation description\n    ////////////////////////////////////////////////////////////////////////////////// \n    int addComponent(string &strComp, string &strSitu, ofstream &out)\n    {\n        if (strComp.size() > 12 || strSitu > 12) \n            return 1;\n\n        if (0 == strComp.size()) \n            strComp = \"KOMPO1\";\n        \n        if (0 == strSitu.size())\n            strSitu = \"SIT1\";\n\n        // Writing description header of configuration\n        out << \"$ENTER COMPONENT  NAME = \" << strComp << \"  DOFTYPE = DISP MATH\" << endl << endl;\n        out << \"   $SITUATION  NAME = \" << strSitu << endl;\n        out << \"   $END SITUATION\" << endl << endl;\n        out << \"   $STRUCTURE\" << endl;\n        \n        return 0;\n    }\n    \nstatic RegisterUserFormat reg_permas (\"Permas Format\", {\".mesh\"}, nullopt, static_cast<void(*)(const Mesh &, const filesystem::path&)>(&WritePermasFormat));\n}\n"
  },
  {
    "path": "libsrc/interface/writetecplot.cpp",
    "content": "//\n//\n// TECPLOT file by Jawor Georgiew\n//\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\n\nnamespace netgen\n{\n\nvoid WriteTecPlotFormat (const Mesh & mesh,\n\t\t\t const filesystem::path & filename)\n{\n  auto geom = dynamic_pointer_cast<CSGeometry>(mesh.GetGeometry());\n  if(geom == nullptr)\n    throw Exception(\"TecPlot format requires a CSGeometry\");\n\n  INDEX i;\n  int j, k, e, z;\n  Vec<3> n;\n  \n  INDEX np = mesh.GetNP();\n  INDEX ne = mesh.GetNE();\n  INDEX nse = mesh.GetNSE();\n  \n  NgArray<int> sn(np);\n  ofstream outfile(filename);\n  \n  outfile << \"TITLE=\\\" \" << filename.string() << \"\\\"\" << endl;\n\n  // fill hashtable\n\n  INDEX_3_HASHTABLE<int> face2volelement(ne);\n\n  for (i = 1; i <= ne; i++)\n    {\n      const Element & el = mesh.VolumeElement(i);\n      INDEX_3 i3;\n      int l;\n      for (j = 1; j <= 4; j++)   // loop over faces of tet\n\t{\n\t  l = 0;\n\t  for (k = 1; k <= 4; k++)\n\t    if (k != j)\n\t      {\n\t\tl++;\n\t\ti3.I(l) = el.PNum(k);\n\t      }\n\t  i3.Sort();\n\t  face2volelement.Set (i3, i);\n\t}\n    }\n      \n      \n  for (j = 1; j <= geom->GetNSurf(); j++)       /* Flaeche Nummer j */\n    {\n      for (i = 1; i <= np; i++)\n\tsn.Elem(i) = 0;\n\n      e = 0;\n       \n      for (i = 1; i <= nse; i++)\n\t{\n\t  const Element2d & el = mesh.SurfaceElement(i);\n\t  if (j ==  mesh.GetFaceDescriptor (el.GetIndex ()).SurfNr())\n\t    {\n\t      for (k = 1; k <= 3; k++)\n\t\tsn.Elem(el.PNum(k)) = 1;\n\t      e++;                     /* e= Anzahl der neuen Elemente */\n\t    }\n\t}\n\n      z = 0;\n      for (i = 1; i <= np; i++)\n\tif (sn.Elem(i) == 1)\n\t  sn.Elem(i) = ++z;\n\n      outfile << \"ZONE T=\\\" Surface \" << j << \" \\\", N=\" << z\n\t      << \", E=\" << e << \", ET=TRIANGLE, F=FEPOINT\" << endl;\n\n      for (i = 1; i <= np; i++)\n\tif (sn.Elem(i) != 0)\n\t  {\n\t    n = geom->GetSurface(j) -> GetNormalVector ( mesh.Point(i) );\n\t\t\n\t    outfile << mesh.Point(i)(0) << \" \" /* Knoten Koordinaten */\n\t\t    << mesh.Point(i)(1) << \" \"\n\t\t    << mesh.Point(i)(2) << \" \"\n\t\t    << n(0) << \" \"\n\t\t    << n(1) << \" \"\n\t\t    << n(2) << \" \"\n\t\t    << i     << endl;\n\t  }\n\t  \n\n      for (i = 1; i <= nse; i++)\n\t{\n\t  const Element2d & el = mesh.SurfaceElement(i);\n\t  if (j ==  mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr())\n\t    /* FlaechenKnoten (3) */\n\t    outfile << sn.Get(el.PNum(1)) << \" \" \n\t\t    << sn.Get(el.PNum(2)) << \" \"\n\t\t    << sn.Get(el.PNum(3)) << endl;\n\t      \n\t  /// Hier soll noch die Ausgabe der Nummer des angrenzenden\n\t      /// Vol.elements erfolgen !\n\n\t      for (k = 1; k <= nse; k++)\n\t\t{\n\t\t  const Element2d & sel = mesh.SurfaceElement(k);\n\t\t  INDEX_3 i3;\n\t\t  for (j = 1; j <= 3; j++)\n\t\t    i3.I(j) = sel.PNum(j);\n\t\t  i3.Sort();\n\t\t  \n\t\t  //int elind = face2volelement.Get(i3);\n\t\t}\n\t}\n    }\n}\n\nstatic RegisterUserFormat reg_tecplot (\"TecPlot Format\", {\".mesh\"}, nullopt, WriteTecPlotFormat);\n\n}\n"
  },
  {
    "path": "libsrc/interface/writetet.cpp",
    "content": "\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <acisgeom.hpp>\n#include <meshing.hpp>\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n  extern void ReadTETFormat (Mesh & mesh, const filesystem::path & filename);\n  \n  void WriteTETFormat (const Mesh & mesh,\n\t\t       const filesystem::path & filename)//, const string& problemType )\n  {\n    string problemType = \"\";\n    if(!mesh.PureTetMesh())\n      throw NgException(\"Can only export pure tet mesh in this format\");\n\n    cout << \"starting .tet export to file \" << filename.string() << endl;\n\n\n    NgArray<int> point_ids,edge_ids,face_ids;\n    NgArray<int> elnum(mesh.GetNE());\n    elnum = -1;\n\n    \n    NgArray<int> userdata_int;\n    NgArray<double> userdata_double;\n    NgArray<int> ports;\n\n    NgArray<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D;\n\n    int pos_int = 0;\n    int pos_double = 0;\n    \n    bool haveuserdata = \n      (mesh.GetUserData(\"TETmesh:double\",userdata_double) &&\n       mesh.GetUserData(\"TETmesh:int\",userdata_int) && \n       mesh.GetUserData(\"TETmesh:ports\",ports) &&\n       mesh.GetUserData(\"TETmesh:point_id\",point_ids,PointIndex::BASE) &&\n       mesh.GetUserData(\"TETmesh:uid_to_group_3D\",uid_to_group_3D) &&\n       mesh.GetUserData(\"TETmesh:uid_to_group_2D\",uid_to_group_2D) &&\n       mesh.GetUserData(\"TETmesh:uid_to_group_1D\",uid_to_group_1D) &&\n       mesh.GetUserData(\"TETmesh:uid_to_group_0D\",uid_to_group_0D));\n\n\n    int version,subversion;\n\n    if(haveuserdata)\n      {\n\tversion = int(userdata_double[0]);\n\tsubversion = int(10*(userdata_double[0] - version));\n\tpos_double++;\n      }\n    else\n      {\n\tversion = 2;\n\tsubversion = 0;\n      }\n\n    \n    if(version >= 2)\n      {\n\t// test if ids are disjunct, if not version 2.0 not possible\n\tint maxbc(-1),mindomain(-1);\n\t\n\tfor(ElementIndex i=0; i<mesh.GetNE(); i++)\n\t  if(i==0 || mesh[i].GetIndex() < mindomain)\n\t    mindomain = mesh[i].GetIndex();\n\tfor(int i=1; i<=mesh.GetNFD(); i++)\n\t  if(i==1 || mesh.GetFaceDescriptor(i).BCProperty() > maxbc)\n\t    maxbc = mesh.GetFaceDescriptor(i).BCProperty();\n\t\n\tif(maxbc >= mindomain)\n\t  {\n\t    cout << \"WARNING: writing version \" << version << \".\" << subversion << \" tetfile not possible, \";\n\t    version = 1; subversion = 1;\n\t    cout << \"using version \" << version << \".\" << subversion << endl;\n\t  }\n      }\n\n\n\n    int startsize = point_ids.Size();\n    point_ids.SetSize(mesh.GetNP()+1);\n    for(int i=startsize; i<point_ids.Size(); i++)\n      point_ids[i] = -1;\n\n\n    for(int i=0; i<PointIndex::BASE; i++)\n      point_ids[i] = -1;\n\n\n    INDEX_2_CLOSED_HASHTABLE<int> edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());;\n    INDEX_3_CLOSED_HASHTABLE<int> facenumbers(4*mesh.GetNE()+mesh.GetNSE());\n\n    NgArray<INDEX_2> edge2node;\n    NgArray<INDEX_3> face2edge;\n    NgArray<INDEX_4> element2face;\n\n    int numelems(0),numfaces(0),numedges(0),numnodes(0);\n\n    for(SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n      {\n\tconst Segment & seg = mesh[si];\n\tINDEX_2 i2(seg[0],seg[1]);\n\ti2.Sort();\n\tif(edgenumbers.Used(i2))\n\t  continue;\n\n\tnumedges++;\n\tedgenumbers.Set(i2,numedges);\n\tedge2node.Append(i2);\n\n\tedge_ids.Append(seg.edgenr);\n\n\tif(point_ids[seg[0]] == -1)\n\t  point_ids[seg[0]] = (version >= 2) ? seg.edgenr : 0;\n\tif(point_ids[seg[1]] == -1)\n\t  point_ids[seg[1]] = (version >= 2) ? seg.edgenr : 0;\n      }\n\n    for(SurfaceElementIndex si = 0; si < mesh.GetNSE(); si++)\n      {\n\tif(mesh[si].IsDeleted())\n\t  continue;\n\n\tconst Element2d & elem = mesh[si];\n\n\tnumfaces++;\n\tINDEX_3 i3(elem[0], elem[1], elem[2]);\n\n\tint min = i3[0];\n\tint minpos = 0;\n\tfor(int j=1; j<3; j++)\n\t  if(i3[j] < min)\n\t    {\n\t      min = i3[j]; minpos = j;\n\t    }\n\tif(minpos == 1)\n\t  {\n\t    int aux = i3[0]; i3[0] = i3[1]; i3[1] = i3[2]; i3[2] = aux;\n\t  }\n\telse if(minpos == 2)\n\t  {\n\t    int aux = i3[0]; i3[0] = i3[2]; i3[2] = i3[1]; i3[1] = aux;\n\t  }\n\tfacenumbers.Set(i3,numfaces);\n\n\tint bc = mesh.GetFaceDescriptor(elem.GetIndex()).BCProperty();\n\tface_ids.Append(bc);\n\n\tfor(int j=0; j<3; j++)\n\t  if(point_ids[elem[j]] == -1)\n\t    point_ids[elem[j]] = (version >= 2) ? bc : 0;\n\n\tINDEX_2 i2a,i2b;\n\tINDEX_3 f_to_n;\n\tfor(int j=0; j<3; j++)\n\t  {\n\t    i2a = INDEX_2(i3[j],i3[(j+1)%3]);\n\t    i2b[0] = i2a[1]; i2b[1] = i2a[0];\n\t    if(edgenumbers.Used(i2a))\n\t      f_to_n[j] = edgenumbers.Get(i2a);\n\t    else if(edgenumbers.Used(i2b))\n\t      f_to_n[j] = -edgenumbers.Get(i2b);\n\t    else\n\t      {\n\t\tnumedges++;\n\t\tedgenumbers.Set(i2a,numedges);\n\t\tedge2node.Append(i2a);\n\t\tf_to_n[j] = numedges;\n\t\tif(version >= 2)\n\t\t  edge_ids.Append(bc);\n\t\telse\n\t\t  edge_ids.Append(0);\n\t      }\n\t  }\n\tface2edge.Append(f_to_n);\n      }\n    \n    for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tconst Element & el = mesh[ei];\n\n\tif(el.IsDeleted())\n\t  continue;\n\n\tnumelems++;\n\telnum[ei] = numelems;\n\n\tstatic int tetfaces[4][3] =\n\t  { { 0, 2, 1 },\n\t    { 0, 1, 3 },\n\t    { 1, 2, 3 },\n\t    { 2, 0, 3 } };\n\t\n\tfor(int j=0; j<4; j++)\n\t  if(point_ids[el[j]] == -1)\n\t    point_ids[el[j]] = (version >= 2) ? el.GetIndex() : 0;\n\n\tINDEX_4 e_to_f;\n\n\tfor(int i = 0; i < 4; i++)\n\t  {\n\t    INDEX_3 i3a(el[tetfaces[i][0]],el[tetfaces[i][1]],el[tetfaces[i][2]]);\n\t    \n\t    int min = i3a[0];\n\t    int minpos = 0;\n\t    for(int j=1; j<3; j++)\n\t      if(i3a[j] < min)\n\t\t{\n\t\t  min = i3a[j]; minpos = j;\n\t\t}\n\t    if(minpos == 1)\n\t      {\n\t\tint aux = i3a[0]; i3a[0] = i3a[1]; i3a[1] = i3a[2]; i3a[2] = aux;\n\t      }\n\t    else if(minpos == 2)\n\t      {\n\t\tint aux = i3a[0]; i3a[0] = i3a[2]; i3a[2] = i3a[1]; i3a[1] = aux;\n\t      }\n\t    INDEX_3 i3b(i3a[0],i3a[2],i3a[1]);\n\t    \n\n\t    if(facenumbers.Used(i3a))\n\t      e_to_f[i] = facenumbers.Get(i3a);\n\t    else if(facenumbers.Used(i3b))\n\t      e_to_f[i] = -facenumbers.Get(i3b);\n\t    else\n\t      {\n\t\tnumfaces++;\n\t\tfacenumbers.Set(i3a,numfaces);\n\t\te_to_f[i] = numfaces;\n\t\tif(version >= 2)\n\t\t  face_ids.Append(el.GetIndex());\n\t\telse\n\t\t  face_ids.Append(0);\n\n\t\tINDEX_2 i2a,i2b;\n\t\tINDEX_3 f_to_n;\n\t\tfor(int j=0; j<3; j++)\n\t\t  {\n\t\t    i2a = INDEX_2(i3a[j],i3a[(j+1)%3]);\n\t\t    i2b[0] = i2a[1]; i2b[1] = i2a[0];\n\t\t    if(edgenumbers.Used(i2a))\n\t\t      f_to_n[j] = edgenumbers.Get(i2a);\n\t\t    else if(edgenumbers.Used(i2b))\n\t\t      f_to_n[j] = -edgenumbers.Get(i2b);\n\t\t    else\n\t\t      {\n\t\t\tnumedges++;\n\t\t\tedgenumbers.Set(i2a,numedges);\n\t\t\tedge2node.Append(i2a);\n\t\t\tf_to_n[j] = numedges;\n\t\t\tif(version >= 2)\n\t\t\t  edge_ids.Append(el.GetIndex());\n\t\t\telse\n\t\t\t  edge_ids.Append(0);\n\t\t      }\n\t\t  }\n\t\tface2edge.Append(f_to_n);\t  \n\t      }\n\t  }\n\telement2face.Append(e_to_f);\n      }\n\n\n\n\n    ofstream outfile(filename);\n\n    outfile.precision(16);\n\n    int unitcode;\n    double tolerance;\n    double dS1,dS2, alphaDeg;\n    double x3D,y3D,z3D;\n    int modelverts(0), modeledges(0), modelfaces(0), modelcells(0);\n\n    int numObj0D,numObj1D,numObj2D,numObj3D;\n    int numports = ports.Size();\n\n    NgArray<int> nodenum(point_ids.Size()+1);\n\n    nodenum = -1;\n\t    \n\n\n    numnodes = 0;\n    for(int i=0; i<point_ids.Size(); i++)\n      {\n\tif(point_ids[i] != -1)\n\t  {\n\t    numnodes++;\n\t    nodenum[i] = numnodes;\n\t  }\n      }\n\n\n    if(haveuserdata)\n      {\n\tunitcode = userdata_int[pos_int];\n\tpos_int++;\n\n\ttolerance = userdata_double[pos_double];\n\tpos_double++;\n\n\tdS1 = userdata_double[pos_double];\n\tpos_double++;\n\tdS2 = userdata_double[pos_double];\n\tpos_double++;\n\talphaDeg = userdata_double[pos_double];\n\tpos_double++;\n\n\tx3D = userdata_double[pos_double];\n\tpos_double++;\n\ty3D = userdata_double[pos_double];\n\tpos_double++;\n\tz3D = userdata_double[pos_double];\n\tpos_double++;\n\n\tif(version == 2)\n\t  {\n\t    modelverts = userdata_int[pos_int];\n\t    pos_int++;\n\t    modeledges = userdata_int[pos_int];\n\t    pos_int++;\n\t    modelfaces = userdata_int[pos_int];\n\t    pos_int++;\n\t    modelcells = userdata_int[pos_int];\n\t    pos_int++;\n\t  }\n\n\tnumObj3D = userdata_int[pos_int];\n\tpos_int++;\n\tnumObj2D = userdata_int[pos_int];\n\tpos_int++;\n\tnumObj1D = userdata_int[pos_int];\n\tpos_int++;\n\tnumObj0D = userdata_int[pos_int];\n\tpos_int++;\n      }\n    else\n      {\n\tunitcode = 3;\n\n\ttolerance = 1e-5;\n\n\tdS1 = dS2 = alphaDeg = 0;\n\n\tx3D = y3D = z3D = 0;\n\n\tmodelverts = modeledges = modelfaces = modelcells = 0;\n\t\n\tnumObj3D = numObj2D = numObj1D = numObj0D = 0;\n      }\n\n    string uidpid;\n    if(version == 1)\n      uidpid = \"PID\";\n    else if (version == 2)\n      uidpid = \"UID\";\n    \n\n    NgArray< idmap_type* > idmaps;\n    for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tif(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)\n\t  {\n\t    idmaps.Append(new idmap_type);\n\t    mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true);\n\t  }\n      }\n\n    NgArray<int> id_num,id_type;\n    NgArray< NgArray<int> *> id_groups;\n\n\n\t// sst 2008-03-12: Write problem class...\n\t{\n\t\tstd::string block;\n\t\tblock  = \"// CST Tetrahedral \";\n\t\tblock += !problemType.empty() ? problemType : \"High Frequency\";\n\t\tblock += \" Mesh, Version no.:\\n\";\n\t\t\n\t\tsize_t size = block.size()-3;\n\t\tblock += \"// \";\n\t\tblock.append( size, '^' );\n\t\tblock += \"\\n\";\n\n\t\toutfile\n\t\t\t<< block\n\t\t\t<< version << \".\" << subversion << \"\\n\\n\";\n\t}\n\n\toutfile \n\t    << \"// User Units Code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << unitcode << \"\\n\\n\"\t\t\t\t\t\\\n\t    << \"// Geometric coord \\\"zero\\\" tolerance threshold:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << tolerance << \"\\n\\n\"\t\t\t\t  \\\n\t    << \"// Periodic UnitCell dS1 , dS2 , alphaDeg:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << dS1 << \" \" << dS2 << \" \" << alphaDeg <<\"\\n\\n\"\t\\\n\t    << \"// Periodic UnitCell origin in global coords (x3D,y3D,z3D):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << x3D << \" \" << y3D << \" \" << z3D << \"\\n\" << endl;\n\n    if(version == 2)\n      {\n\toutfile << \"// Model entity count: Vertices, Edges, Faces, Cells:\\n\" \\\n\t\t<< \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t\t<< modelverts << \" \" << modeledges << \" \" << modelfaces << \" \" << modelcells << endl << endl;\n      }\n\n\n    outfile << \"// Topological mesh-entity counts (#elements,#faces,#edges,#nodes):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    outfile << numelems << \" \" \n\t    << numfaces << \" \"\n\t    << numedges << \" \" \n\t    << numnodes << endl << endl;\n\n    outfile << \"// NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PMinion 3=CPMaster 4=CPMinion), \"<< uidpid <<\":\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n       \n\n\n    id_num.SetSize(mesh.GetNP()+1);\n    id_type.SetSize(mesh.GetNP()+1);\n    id_num = 0;\n    id_type = 0;\n\n    int n2,n4,n8;\n    n2 = n4 = n8 = 0;\n\n \n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      {\n\tif(id_num[i] != 0)\n\t  continue;\n\n\tif(nodenum[i] == -1)\n\t  continue;\n\n\tNgArray<int> group;\n\tgroup.Append(i);\n\tfor(int j=0; j<idmaps.Size(); j++)\n\t  {\n\t    startsize = group.Size();\n\t    for(int k=0; k<startsize; k++)\n\t      {\n\t\tint id = (*idmaps[j])[group[k]];\n\t\tif(id != 0 && !group.Contains(id) && nodenum[id] != -1)\n\t\t  {\n\t\t    group.Append(id);\n\t\t    id_num[id] = j+1+id_num[group[k]];\n\t\t  }\n\t      }\n\t  }\n\tif(group.Size() > 1)\n\t  {\n\t    id_groups.Append(new NgArray<int>(group));\n\t    if(group.Size() == 2)\n\t      {\n\t\tid_type[i] = 1;\n\t\tid_type[group[1]] = 2;\n\t\tn2++;\n\t      }\n\t    else if(group.Size() == 4)\n\t      {\n\t\tid_type[i] = 3;\n\t\tfor(int j=1; j<group.Size(); j++)\n\t\t  id_type[group[j]] = 4;\n\t\tn4++;\n\t      }\n\t    else if(group.Size() == 8)\n\t      {\n\t\tid_type[i] = 5;\n\t\tfor(int j=1; j<group.Size(); j++)\n\t\t  id_type[group[j]] = 6;\n\t\tn8++;\n\t      }\n\t    else\n\t      cerr << \"ERROR: Identification group size = \" << group.Size() << endl;\n\t  }\n\t\n      }\n\n\n    // for(PointIndex i = mesh.Points().Begin(); i < mesh.Points().End(); i++)\n    for(PointIndex i : mesh.Points().Range())\n      {\n\tif(nodenum[i] == -1)\n\t  continue;\n\toutfile << nodenum[i] << \" \"\n\t\t<< mesh[i](0) << \" \"\n\t\t<< mesh[i](1) << \" \"\n\t\t<< mesh[i](2) << \" \" << id_type[i] << \" \";\n\tif(i-IndexBASE<PointIndex>() < point_ids.Size())\n\t  outfile << point_ids[i];\n\telse\n\t  outfile << \"0\";\n\toutfile << \"\\n\";\n      }\n    outfile << endl;\n\n    outfile << \"\\n// Number of Periodic Master Nodes:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << n2 << \"\\n\"\t\t\t       \\\n\t    << \"\\n\" \\\n\t    << \"// MasterNodeID, MinionNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(id_groups[i]->Size() != 2)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << nodenum[(*id_groups[i])[j]] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  outfile << id_num[(*id_groups[i])[j]] << \" \";\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n\tid_groups[i] = NULL;\n      }\n    outfile << endl;\n\t\n\t\n    outfile << \"// Number of Corner Periodic Master Nodes:\\n\"\t      \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << n4 << \"\\n\"\t\t\t\t      \\\n\t    << \"\\n\" \\\n\t    << \"// MasterNodeID, 3-MinionNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n\n\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(!id_groups[i] || id_groups[i]->Size() != 4)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << nodenum[(*id_groups[i])[j]] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  {\n\t    outfile << id_num[(*id_groups[i])[j]] << \" \";\n\t  }\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n\tid_groups[i] = NULL;\n      }\n    outfile << endl;\n\n\n    outfile << \"// Number of Cubic Periodic Master Nodes:\\n\"\t     \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << n8 << \"\\n\"\t\t\t\t     \\\n\t    << \"\\n\" \\\n\t    << \"// MasterNodeID, 7-MinionNodeID's, TranslCodes:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(!id_groups[i] || id_groups[i]->Size() != 8)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << nodenum[(*id_groups[i])[j]] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  outfile << id_num[(*id_groups[i])[j]] << \" \";\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n\tid_groups[i] = NULL;\n      }\n    outfile << endl;\n\n    \n\n\n    outfile << \"// EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PMinion 3=CPMaster 4=CPMinion), \"<<uidpid<<\":\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n\n    \n      \n    NgArray< NgArray<int>* > vertex_to_edge(mesh.GetNP()+1);\n    for(int i=0; i<=mesh.GetNP(); i++)\n      vertex_to_edge[i] = new NgArray<int>;\n\n    NgArray< NgArray<int,PointIndex::BASE>* > idmaps_edge(idmaps.Size());\n    for(int i=0; i<idmaps_edge.Size(); i++)\n      {\n\tidmaps_edge[i] = new NgArray<int,PointIndex::BASE>(numedges);\n\t(*idmaps_edge[i]) = 0;\n      }\n\n    NgArray<int> possible;\n    for(int i=0; i<edge2node.Size(); i++)\n      {\n\tconst INDEX_2 & v = edge2node[i];\n\tfor(int j=0; j<idmaps.Size(); j++)\n\t  {\n\t    INDEX_2 vid((*idmaps[j])[v[0]], (*idmaps[j])[v[1]]);\n\t    if(vid[0] != 0 && vid[0] != v[0] && vid[1] != 0 && vid[1] != v[1])\n\t      {\n\t\tIntersection(*vertex_to_edge[vid[0]],*vertex_to_edge[vid[1]],possible);\n\t\tif(possible.Size() == 1)\n\t\t  {\n\t\t    (*idmaps_edge[j])[possible[0]] = i+1;\n\t\t    (*idmaps_edge[j])[i+1] = possible[0];\n\t\t  }\n\t\telse if(possible.Size() > 0)\n\t\t  {\n\t\t    cerr << \"ERROR: too many possible edge identifications\" << endl;\n\t\t    (*testout) << \"ERROR: too many possible edge identifications\" << endl\n\t\t\t       << \"*vertex_to_edge[\"<<vid[0]<<\"] \" << *vertex_to_edge[vid[0]] << endl\n\t\t\t       << \"*vertex_to_edge[\"<<vid[1]<<\"] \" << *vertex_to_edge[vid[1]] << endl\n\t\t\t       << \"possible \" << possible << endl;\n\t\t  }\n\t      }\n\t  }\n\tvertex_to_edge[v[0]]->Append(i+1);\n\tvertex_to_edge[v[1]]->Append(i+1);\n      }\n\n\n    for(int i=0; i<vertex_to_edge.Size(); i++)\n      delete vertex_to_edge[i];\n\n\n    id_groups.SetSize(0);\n    id_num.SetSize(numedges+1);\n    id_num = 0;\n    id_type.SetSize(numedges+1);\n    id_type = 0;\n\n    n2 = n4 = n8 = 0;\n\n    for(int i=1; i<=edge2node.Size(); i++)\n      {\n\tif(id_num[i] != 0)\n\t  continue;\n\n\n\tNgArray<int> group;\n\tgroup.Append(i);\n\tfor(int j=0; j<idmaps_edge.Size(); j++)\n\t  {\n\t    startsize = group.Size();\n\t    for(int k=0; k<startsize; k++)\n\t      {\n\t\tint id = (*idmaps_edge[j])[group[k]];\n\t\tif(id != 0 && !group.Contains(id))\n\t\t  {\n\t\t    group.Append(id);\n\t\t    id_num[id] = j+1+id_num[group[k]];\n\t\t  }\n\t      }\n\t  }\n\tif(group.Size() > 1)\n\t  {\n\t    id_num[i] = 1;\n\t    id_groups.Append(new NgArray<int>(group));\n\t    if(group.Size() == 2)\n\t      {\n\t\tid_type[i] = 1;\n\t\tid_type[group[1]] = 2;\n\t\tn2++;\n\t      }\n\t    else if(group.Size() == 4)\n\t      {\n\t\tid_type[i] = 3;\n\t\tfor(int j=1; j<group.Size(); j++)\n\t\t  id_type[group[j]] = 4;\n\t\tn4++;\n\t      }\n\t    else\n\t      {\n\t\tcerr << \"ERROR: edge identification group size = \" << group.Size() << endl;\n\t\t(*testout) << \"edge group \" << group << endl;\n\t\tfor(int j=0; j<idmaps_edge.Size(); j++)\n\t\t  {\n\t\t    (*testout) << \"edge id map \" << j << endl << *idmaps_edge[j] << endl;\n\t\t  }\n\t      }\n\t  }\n      }\n\n\n\n    for(int i=1; i<=edge2node.Size(); i++)\n      {\n\tif(id_num[i] != 0)\n\t  continue;\n\n\n\tNgArray<int> group;\n\tgroup.Append(i);\n\tfor(int j=0; j<idmaps_edge.Size(); j++)\n\t  {\n\t    startsize = group.Size();\n\t    for(int k=0; k<startsize; k++)\n\t      {\n\t\tint id = (*idmaps_edge[j])[group[k]];\n\t\tif(id != 0 && !group.Contains(id))\n\t\t  {\n\t\t    group.Append(id);\n\t\t    id_num[id] = j+1+id_num[group[k]];\n\t\t  }\n\t      }\n\t  }\n\tif(group.Size() > 1)\n\t  {\n\t    id_num[i] = 1;\n\t    id_groups.Append(new NgArray<int>(group));\n\t    if(group.Size() == 2)\n\t      {\n\t\tid_type[i] = 1;\n\t\tid_type[group[1]] = 2;\n\t\tn2++;\n\t      }\n\t    else if(group.Size() == 4)\n\t      {\n\t\tid_type[i] = 3;\n\t\tfor(int j=1; j<group.Size(); j++)\n\t\t  id_type[group[j]] = 4;\n\t\tn4++;\n\t      }\n\t    else\n\t      {\n\t\tcerr << \"ERROR: edge identification group size = \" << group.Size() << endl;\n\t\t(*testout) << \"edge group \" << group << endl;\n\t\tfor(int j=0; j<idmaps_edge.Size(); j++)\n\t\t  {\n\t\t    (*testout) << \"edge id map \" << j << endl << *idmaps_edge[j] << endl;\n\t\t  }\n\t      }\n\t  }\n\t\n      }\n\n    \n    for(int i=0; i<edge2node.Size(); i++)\n      outfile << i+1 << \" \" << nodenum[edge2node[i][0]] << \" \" << nodenum[edge2node[i][1]] \n\t      << \" \" << id_type[i+1] << \" \" << edge_ids[i] << \"\\n\";\n\n    outfile << endl;\n\n    \n\n    outfile << \"// Number of Periodic Master Edges:\\n\"\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\"\\\n\t    << n2 << \"\\n\"\t\t\t      \\\n\t    << \"\\n\"\\\n\t    << \"// MasterEdgeID, MinionEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\\n\"\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(id_groups[i]->Size() != 2)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << (*id_groups[i])[j] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  outfile << id_num[(*id_groups[i])[j]] << \" \";\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n\tid_groups[i] = NULL;\n      }\n    outfile << endl;\n\n    outfile << \"// Number of Corner Periodic Master Edges:\\n\"\t\t\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\"\\\n\t    << n4 << \"\\n\"\t\t\t\t     \\\n\t    << \"\\n\"\\\n\t    << \"// MasterEdgeID, 3 MinionEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2):\\n\"\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(!id_groups[i] || id_groups[i]->Size() != 4)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << (*id_groups[i])[j] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  outfile << id_num[(*id_groups[i])[j]] << \" \";\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n\tid_groups[i] = NULL;\n      }\n    outfile << endl;\n\n\n    outfile << \"// FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PMinion), \"<<uidpid<<\":\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n\n    \n    \n    NgArray< NgArray<int>* > edge_to_face(numedges+1);\n    for(int i=0; i<edge_to_face.Size(); i++)\n      edge_to_face[i] = new NgArray<int>;\n\n    \n    for(int i=0; i<idmaps.Size(); i++)\n      {\n\tidmaps[i]->SetSize(numfaces);\n\t(*idmaps[i]) = 0;\n      }\n\n    \n    for(int i=0; i<face2edge.Size(); i++)\n      {\n\tfor(int j=0; j<idmaps_edge.Size(); j++)\n\t  {\n\t    int e1id,e2id,e3id;\n\t    e1id = (*idmaps_edge[j])[abs(face2edge[i][0])];\n\t    e2id = (*idmaps_edge[j])[abs(face2edge[i][1])];\n\t    e3id = (*idmaps_edge[j])[abs(face2edge[i][2])];\n\t    if(e1id != 0 && e1id != abs(face2edge[i][0]) &&\n\t       e2id != 0 && e2id != abs(face2edge[i][1]) &&\n\t       e3id != 0 && e3id != abs(face2edge[i][2]))\n\t      {\n\t\tIntersection(*edge_to_face[e1id],*edge_to_face[e2id],*edge_to_face[e3id],possible);\n\t\tif(possible.Size() == 1)\n\t\t  {\n\t\t    (*idmaps[j])[possible[0]] = i+1;\n\t\t    (*idmaps[j])[i+1] = possible[0];\n\t\t  }\n\t\telse if(possible.Size() > 0)\n\t\t  cerr << \"ERROR: too many possible face identifications\" << endl;\n\t      }\n\t  }\n\n\tedge_to_face[abs(face2edge[i][0])]->Append(i+1);\n\tedge_to_face[abs(face2edge[i][1])]->Append(i+1);\n\tedge_to_face[abs(face2edge[i][2])]->Append(i+1);\n      }\n\n    for(int i=0; i<edge_to_face.Size(); i++)\n      delete edge_to_face[i];\n\n\n    for(int i=0; i<idmaps_edge.Size(); i++)\n      delete idmaps_edge[i];\n\n    \n    id_groups.SetSize(0);\n    id_num.SetSize(numfaces+1);\n    id_num = 0;\n\n    n2 = n4 = n8 = 0;\n\n    for(int i=1; i<=numfaces; i++)\n      {\n\tif(id_num[i] != 0)\n\t  continue;\n\n\tNgArray<int> group;\n\tgroup.Append(i);\n\tfor(int j=0; j<idmaps.Size(); j++)\n\t  {\n\t    startsize = group.Size();\n\t    for(int k=0; k<startsize; k++)\n\t      {\n\t\tint id = (*idmaps[j])[group[k]];\n\t\tif(id != 0 && !group.Contains(id))\n\t\t  {\n\t\t    group.Append(id);\n\t\t    id_num[id] = j+1+id_num[group[k]];\n\t\t  }\n\t      }\n\t  }\n\tif(group.Size() > 1)\n\t  {\n\t    id_num[i] = -1;\n\t    id_groups.Append(new NgArray<int>(group));\n\t    if(group.Size() == 2)\n\t      n2++;\n\t    else\n\t      cerr << \"ERROR: face identification group size = \" << group.Size() << endl;\n\t  }\n\t\n      }\n\n\n    for(int i=0; i<idmaps.Size(); i++)\n      delete idmaps[i];\n\n\n\n\n    for(int i=0; i<face2edge.Size(); i++)\n      {\t\n\toutfile << i+1 << \" \";\n\tfor(int j=0; j<3; j++)\n\t  outfile << face2edge[i][j] << \" \";\n\n\tif(id_num[i+1] == 0)\n\t  outfile << 0;\n\telse if(id_num[i+1] == -1)\n\t  outfile << 1;\n\telse\n\t  outfile << 2;\n\n\toutfile << \" \" << face_ids[i] <<\"\\n\";\n      }\n    outfile << endl;\n\n\n    outfile << \"// Number of Periodic Master Faces:\\n\"\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\"\\\n\t    << n2 << \"\\n\"\t\t\t      \\\n\t    << \"\\n\"\\\n\t    << \"// MasterFaceID, MinionFaceID, TranslCode (1=dS1 2=dS2):\\n\"\\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<id_groups.Size(); i++)\n      {\n\tif(id_groups[i]->Size() != 2)\n\t  continue;\n\n\tfor(int j=0; j<id_groups[i]->Size(); j++)\n\t  outfile << (*id_groups[i])[j] << \" \";\n\tfor(int j=1; j<id_groups[i]->Size(); j++)\n\t  outfile << id_num[(*id_groups[i])[j]] << \" \";\n\toutfile << \"\\n\";\n\n\tdelete id_groups[i];\n      }\n    outfile << endl;\n\n    \n\n\n    outfile << \"// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, \"<<uidpid<<\":\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n\n    for(ElementIndex i=0; i<mesh.GetNE(); i++)\n      {\n\tif(elnum[i] >= 0)\n\t  {\n\t    outfile << elnum[i] << \" \";\n\t    for(int j=0; j<4; j++)\n\t      outfile << element2face[elnum[i]-1][j] << \" \";\n\n\t    outfile << mesh[i].GetIndex() << \"\\n\";\n\t  }\n      }\n    outfile << endl;\n\n    outfile << \"// ElemID, NodeID0, NodeID1, NodeID2, NodeID3:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n\n    \n    for(ElementIndex i=0; i<mesh.GetNE(); i++)\n      {\n\tif(elnum[i] >= 0)\n\t  outfile << elnum[i] << \" \"\n\t\t  << nodenum[mesh[i][1]] << \" \" << nodenum[mesh[i][0]] << \" \" << nodenum[mesh[i][2]] << \" \" << nodenum[mesh[i][3]] << \"\\n\";\n      }\n    outfile << endl;\n    \n\n    \n\n    outfile << \"// Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D):\\n\"\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\"\n\t    << \" \"<< numObj3D << \" \" << numObj2D << \" \" << numObj1D << \" \" << numObj0D << \"\\n\" \\\n\t    << \"\\n\" \\\n\t    << \"// Number of Ports (Ports are a subset of Object2D list):\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\" \\\n\t    << numports << \"\\n\"\t\t\t\t\t\t\\\n\t    << endl;\n\n\n    NgArray< NgArray<int> * > groups;\n\n    int maxg = -1;\n    for(int i = 0; i<uid_to_group_3D.Size(); i++)\n      if(uid_to_group_3D[i] > maxg)\n\tmaxg = uid_to_group_3D[i];\n    for(int i = 0; i<uid_to_group_2D.Size(); i++)\n      if(uid_to_group_2D[i] > maxg)\n\tmaxg = uid_to_group_2D[i];\n    for(int i = 0; i<uid_to_group_1D.Size(); i++)\n      if(uid_to_group_1D[i] > maxg)\n\tmaxg = uid_to_group_1D[i];\n    for(int i = 0; i<uid_to_group_0D.Size(); i++)\n      if(uid_to_group_0D[i] > maxg)\n\tmaxg = uid_to_group_0D[i];\n\n    groups.SetSize(maxg+1);\n    for(int i=0; i<groups.Size(); i++)\n      groups[i] = new NgArray<int>;\n\n    for(ElementIndex i=0; i<mesh.GetNE(); i++)\n      if(uid_to_group_3D[mesh[i].GetIndex()] >= 0)\n\tgroups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1);\n      \n    \n\n\n    outfile << \"// Object3D GroupID, #Elems <immediately followed by> ElemID List:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<numObj3D; i++)\n      {\n\toutfile << i << \" \" << groups[i]->Size() << \"\\n\";\n\tfor(int j=0; j<groups[i]->Size(); j++)\n\t  outfile << (*groups[i])[j] << \"\\n\";\n      }\n\n    for(int i=0; i<groups.Size(); i++)\n      groups[i]->SetSize(0);\n\n    for(int i=0; i<face_ids.Size(); i++)\n      if(uid_to_group_2D[face_ids[i]] >= 0)\n\tgroups[uid_to_group_2D[face_ids[i]]]->Append(i+1);\n      \n\n    outfile << \"// Object2D GroupID, #Faces <immediately followed by> FaceID List:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<numObj2D; i++)\n      {\n\toutfile << i << \" \" << groups[i]->Size() << \"\\n\";\n\tfor(int j=0; j<groups[i]->Size(); j++)\n\t  {\n\t    outfile << (*groups[i])[j];\n\t    if(ports.Contains(face_ids[(*groups[i])[j]-1]))\n\t      outfile << \" P\";\n\t    outfile << \"\\n\";\n\t  }\n      }\n    outfile << endl;\n\n    \n    for(int i=0; i<groups.Size(); i++)\n      groups[i]->SetSize(0);\n\n    for(int i=0; i<edge_ids.Size(); i++)\n      if(uid_to_group_1D[edge_ids[i]] >= 0)\n\tgroups[uid_to_group_1D[edge_ids[i]]]->Append(i+1);\n\n\n\n    outfile << \"// Object1D GroupID, #Edges <immediately followed by> EdgeID List:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<numObj1D; i++)\n      {\n\toutfile << i << \" \" << groups[i]->Size() << \"\\n\";\n\tfor(int j=0; j<groups[i]->Size(); j++)\n\t  outfile << (*groups[i])[j] << \"\\n\";\n      }\n    outfile << endl;\n\n    \n    for(int i=0; i<groups.Size(); i++)\n      groups[i]->SetSize(0);\n    //     for(PointIndex i = mesh.Points().Begin(); i < mesh.Points().End(); i++)\n    for(PointIndex i : mesh.Points().Range())\n      {\n\tif(i-IndexBASE<PointIndex>() < point_ids.Size())\n\t  {\n\t    if(uid_to_group_0D[point_ids[i]] >= 0)\n\t      groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-IndexBASE<PointIndex>());\n\t  }\n\telse\n\t  groups[uid_to_group_0D[0]]->Append(i+1-IndexBASE<PointIndex>());\n      }\n\n\n    outfile << \"// Object0D GroupID, #Nodes <immediately followed by> NodeID List:\\n\" \\\n\t    << \"// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n\";\n    for(int i=0; i<numObj0D; i++)\n      {\n\toutfile << i << \" \" << groups[i]->Size() << \"\\n\";\n\tfor(int j=0; j<groups[i]->Size(); j++)\n\t  outfile << (*groups[i])[j] << \"\\n\";\n      }\n    outfile << endl;\n\n    for(int i=0; i<groups.Size(); i++)\n      delete groups[i];\n\n\n    outfile.close();\n\n    cout << \".tet export done\" << endl;\n  }\nstatic RegisterUserFormat reg_tet (\"TET Format\", {\".tet\"}, ReadTETFormat, WriteTETFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writetochnog.cpp",
    "content": "//\n//  Write Tochnog file\n//\n//  by\n//\n//  Andreas Seltmann\n//  email:  A.Seltmann@lsw.uni-heidelberg.de\n//\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n\nvoid WriteTochnogFormat (const Mesh & mesh,\n\t\t\t const filesystem::path & filename)\n{\n  cout << \"\\nWrite Tochnog Volume Mesh\" << endl;\n\n  ofstream outfile (filename);\n\n  outfile << \"(Nodes and Elements generated with NETGEN\" << endl;\n  outfile << \" \" << filename << \")\" << endl;\n\n  outfile.precision(8);\n\n  outfile << \"(Nodes)\" << endl;\n\n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int i, j;\n\n  for (i = 1; i <= np; i++)\n    {\n      outfile << \"node \" << \" \" << i << \" \";\n      outfile << mesh.Point(i)(0) << \" \";\n      outfile << mesh.Point(i)(1) << \" \";\n      outfile << mesh.Point(i)(2) << \"\\n\";\n    }\n\n  int elemcnt = 0; //element counter\n  int finished = 0;\n  int indcnt = 1; //index counter\n\n  while (!finished)\n    {\n      int actcnt = 0;\n      const Element & el1 = mesh.VolumeElement(1);\n      int non = el1.GetNP();\n      if (non == 4)\n\t{\n\t  outfile << \"(Elements, type=-tet4)\" << endl;\n\t} \n      else\n\t{\n\t  cout << \"unsupported Element type!!!\" << endl;\t  \n\t}\n\n      for (i = 1; i <= ne; i++)\n\t{\n\t  const Element & el = mesh.VolumeElement(i);\n\t      \n\t  if (el.GetIndex() == indcnt)\n\t    {\n\t      actcnt++;\n\t      if (el.GetNP() != non) \n\t\t{\n\t\t  cout << \"different element-types in a subdomain are not possible!!!\" << endl;\n\t\t  continue;\n\t\t}\n\t\t  \n\t      elemcnt++;\n\t      outfile << \"element \" << elemcnt << \" -tet4 \";\n\t      if (non == 4)\n\t\t{\n\t\t  outfile << el.PNum(1) << \" \";\n\t\t  outfile << el.PNum(2) << \" \";\n\t\t  outfile << el.PNum(4) << \" \";\n\t\t  outfile << el.PNum(3) << \"\\n\";\n\t\t}\n\t      else\n\t\t{\n\t\t  cout << \"unsupported Element type!!!\" << endl;\n\t\t  for (j = 1; j <= el.GetNP(); j++)\n\t\t    {\n\t\t      outfile << el.PNum(j);\n\t\t      if (j != el.GetNP()) outfile << \", \";\n\t\t    }\n\t\t  outfile << \"\\n\";\n\t\t}\n\t    }\n\t}\t  \n      indcnt++;\n      if (elemcnt == ne) {finished = 1; cout << \"all elements found by Index!\" << endl;}\n      if (actcnt == 0) {finished = 1;}\n    }\n\n  cout << \"done\" << endl;\n}\n\nstatic RegisterUserFormat reg_tochnog (\"Tochnog Format\", {\".mesh\"}, nullopt, WriteTochnogFormat);\n}\n"
  },
  {
    "path": "libsrc/interface/writeuser.cpp",
    "content": "//\r\n//  Write user dependent output file\r\n//\r\n\r\n#include <mystdlib.h>\r\n\r\n#include <myadt.hpp>\r\n#include <linalg.hpp>\r\n#include <csg.hpp>\r\n#include <geometry2d.hpp>\r\n#include <meshing.hpp>\r\n\r\n#include \"writeuser.hpp\"\r\n#include \"../general/gzstream.h\"\r\n\r\n\r\nnamespace netgen\r\n{\r\n  std::map<std::string, UserFormatRegister::UserFormatEntry>& UserFormatRegister::getFormats()\r\n  {\r\n      static std::map<std::string, UserFormatRegister::UserFormatEntry> formats = {};\r\n      return formats;\r\n  }\r\n\r\n  void UserFormatRegister::Register(UserFormatRegister::UserFormatEntry && entry)\r\n  {\r\n      getFormats()[entry.format] = std::move(entry);\r\n  }\r\n\r\n  const bool UserFormatRegister::HaveFormat(string format)\r\n  {\r\n      const auto formats = getFormats();\r\n      return formats.find(format) != formats.end();\r\n  }\r\n\r\n  const UserFormatRegister::UserFormatEntry & UserFormatRegister::Get(string format)\r\n  {\r\n      return getFormats()[format];\r\n  }\r\n\r\n  extern MeshingParameters mparam;\r\n\r\n  void RegisterUserFormats (NgArray<const char*> & names,\r\n\t\t\t    NgArray<const char*> & extensions)\r\n\t\t\t    \r\n{\r\n  for (const auto & entry : UserFormatRegister::getFormats())\r\n    {\r\n      names.Append (entry.second.format.c_str());\r\n      extensions.Append (entry.second.extensions[0].c_str());\r\n    }\r\n}\r\n  \r\nbool WriteUserFormat (const string & format,\r\n\t\t      const Mesh & mesh,\r\n\t\t      const filesystem::path & filename)\r\n{\r\n  if(!UserFormatRegister::HaveFormat(format))\r\n    return true;\r\n\r\n  const auto entry = UserFormatRegister::Get(format);\r\n  if(!entry.write)\r\n    return true;\r\n\r\n  (*entry.write)(mesh, filename);\r\n  return false;\r\n}\r\n\r\n\r\n\r\n/*\r\n *  Neutral mesh format\r\n *  points, elements, surface elements\r\n */\r\n\r\nvoid WriteNeutralFormat (const Mesh & mesh,\r\n\t\t\t const filesystem::path & filename)\r\n{\r\n  cout << \"write neutral, new\" << endl;\r\n  int np = mesh.GetNP();\r\n  int ne = mesh.GetNE();\r\n  int nse = mesh.GetNSE();\r\n  int nseg = mesh.GetNSeg();\r\n  // int i, j;\r\n\r\n  int inverttets = mparam.inverttets;\r\n  int invertsurf = mparam.inverttrigs;\r\n\r\n  ofstream outfile (filename);\r\n\r\n  outfile.precision(6);\r\n  outfile.setf (ios::fixed, ios::floatfield);\r\n  outfile.setf (ios::showpoint);\r\n\r\n  outfile << np << \"\\n\";\r\n\r\n  for (int i = 1; i <= np; i++)\r\n    {\r\n      const Point3d & p = mesh.Point(i);\r\n\r\n      outfile.width(10);\r\n      outfile << p.X() << \" \";\r\n      outfile.width(9);\r\n      outfile << p.Y() << \" \";\r\n      if (mesh.GetDimension() == 3)\r\n\t{\r\n\t  outfile.width(9);\r\n\t  outfile << p.Z();\r\n\t  }\r\n      outfile << \"\\n\";\r\n    }\r\n\r\n  if (mesh.GetDimension() == 3)\r\n    {\r\n      outfile << ne << \"\\n\";\r\n      /*\r\n      for (int i = 1; i <= ne; i++)\r\n\t{\r\n\t  Element el = mesh.VolumeElement(i);\r\n      */\r\n      for (Element el : mesh.VolumeElements())\r\n        {\r\n\t  if (inverttets)\r\n\t    el.Invert();\r\n\t  outfile.width(4);\r\n\t  outfile << el.GetIndex() << \"  \";\r\n\t  for (int j = 1; j <= el.GetNP(); j++)\r\n\t    {\r\n\t      outfile << \" \";\r\n\t      outfile.width(8);\r\n\t      outfile << el.PNum(j);\r\n\t    }\r\n\t  outfile << \"\\n\";\r\n\t}\r\n    }\r\n\r\n  outfile << nse << \"\\n\";\r\n  /*\r\n  for (int i = 1; i <= nse; i++)\r\n    {\r\n      Element2d el = mesh.SurfaceElement(i);\r\n  */\r\n  for (Element2d el : mesh.SurfaceElements())\r\n    {\r\n      if (invertsurf)\r\n\tel.Invert();\r\n      outfile.width(4);\r\n      outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \"    \";\r\n      for (int j = 1; j <= el.GetNP(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << el.PNum(j);\r\n\t}\r\n      outfile << \"\\n\";\r\n    }\r\n\r\n\r\n  if (mesh.GetDimension() == 2)\r\n    {\r\n      outfile << nseg << \"\\n\";\r\n      for (int i = 1; i <= nseg; i++)\r\n\t{\r\n\t  const Segment & seg = mesh.LineSegment(i);\r\n\t  outfile.width(4);\r\n\t  outfile << seg.si << \"    \";\r\n\r\n          for (int j = 0; j < seg.GetNP(); j++)\r\n            {\r\n              outfile << \" \";\r\n              outfile.width(8);\r\n              outfile << seg[j];\r\n            }\r\n          /*\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << seg[0];\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << seg[1];\r\n          if (seg[2] != -1)\r\n            {\r\n              outfile.width(8);\r\n              outfile << seg[2];\r\n            }\r\n          */\r\n\t  outfile << \"\\n\";\r\n\t}\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid WriteSurfaceFormat (const Mesh & mesh,\r\n\t\t\t const filesystem::path & filename)\r\n{\r\n  // surface mesh\r\n  int i, j;\r\n\r\n  cout << \"Write Surface Mesh\" << endl;\r\n\r\n  ofstream outfile (filename);\r\n\r\n  outfile << \"surfacemesh\" << endl;\r\n\r\n  outfile << mesh.GetNP() << endl;\r\n  for (i = 1; i <= mesh.GetNP(); i++)\r\n    {\r\n      for (j = 0; j < 3; j++)\r\n\t{\r\n\t  outfile.width(10);\r\n\t  outfile << mesh.Point(i)(j) << \" \";\r\n\t}\r\n      outfile << endl;\r\n    }\r\n  outfile << mesh.GetNSE() << endl;\r\n  for (i = 1; i <= mesh.GetNSE(); i++)\r\n    {\r\n      for (j = 1; j <= 3; j++)\r\n\t{\r\n\t  outfile.width(8);\r\n\t  outfile << mesh.SurfaceElement(i).PNum(j);\r\n\t}\r\n      outfile << endl;\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n *  save surface mesh as STL file\r\n */\r\n\r\nvoid WriteSTLFormat (const Mesh & mesh,\r\n\t\t     const filesystem::path & filename)\r\n{\r\n  cout << \"\\nWrite STL Surface Mesh\" << endl;\r\n\r\n  auto ext = filename.extension();\r\n  ostream *outfile;\r\n\r\n  if(ext == \".gz\")\r\n\t  outfile = new ogzstream(filename);\r\n  else\r\n\t  outfile = new ofstream(filename);\r\n\r\n  int i;\r\n\r\n  outfile->precision(10);\r\n\r\n  *outfile << \"solid\" << endl;\r\n\r\n  for (i = 1; i <= mesh.GetNSE(); i++)\r\n    {\r\n      *outfile << \"facet normal \";\r\n      const Point3d& p1 = mesh.Point(mesh.SurfaceElement(i).PNum(1));\r\n      const Point3d& p2 = mesh.Point(mesh.SurfaceElement(i).PNum(2));\r\n      const Point3d& p3 = mesh.Point(mesh.SurfaceElement(i).PNum(3));\r\n\r\n      Vec3d normal = Cross(p2-p1,p3-p1);\r\n      if (normal.Length() != 0)\r\n\t{\r\n\t  normal /= (normal.Length());\r\n\t}\r\n\r\n      *outfile << normal.X() << \" \" << normal.Y() << \" \" << normal.Z() << \"\\n\";\r\n      *outfile << \"outer loop\\n\";\r\n\r\n      *outfile << \"vertex \" << p1.X() << \" \" << p1.Y() << \" \" << p1.Z() << \"\\n\";\r\n      *outfile << \"vertex \" << p2.X() << \" \" << p2.Y() << \" \" << p2.Z() << \"\\n\";\r\n      *outfile << \"vertex \" << p3.X() << \" \" << p3.Y() << \" \" << p3.Z() << \"\\n\";\r\n\r\n      *outfile << \"endloop\\n\";\r\n      *outfile << \"endfacet\\n\";\r\n    }\r\n  *outfile << \"endsolid\" << endl;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n *  Philippose - 16 August 2010\r\n *  Save surface mesh as STL file\r\n *  with a separate solid definition\r\n *  for each face\r\n *  - This helps in splitting up the\r\n *    STL into named boundary faces\r\n *    when using a third-party mesher\r\n */\r\nvoid WriteSTLExtFormat (const Mesh & mesh,\r\n\t\t     const filesystem::path & filename)\r\n{\r\n  cout << \"\\nWrite STL Surface Mesh (with separated boundary faces)\" << endl;\r\n\r\n  auto ext = filename.extension();\r\n  ostream *outfile;\r\n\r\n  if(ext == \".gz\")\r\n\t  outfile = new ogzstream(filename);\r\n  else\r\n\t  outfile = new ofstream(filename);\r\n\r\n  outfile->precision(10);\r\n\r\n  int numBCs = 0;\r\n\r\n  NgArray<int> faceBCs;\r\n  TABLE<int> faceBCMapping;\r\n\r\n  faceBCs.SetSize(mesh.GetNFD());\r\n  faceBCMapping.SetSize(mesh.GetNFD());\r\n\r\n  faceBCs = -1;\r\n\r\n  // Collect the BC numbers used in the mesh\r\n  for(int faceNr = 1; faceNr <= mesh.GetNFD(); faceNr++)\r\n  {\r\n\t  int bcNum = mesh.GetFaceDescriptor(faceNr).BCProperty();\r\n\r\n\t  if(faceBCs.Pos(bcNum) < 0)\r\n\t  {\r\n        numBCs++;\r\n\t\t  faceBCs.Set(numBCs,bcNum);\r\n        faceBCMapping.Add1(numBCs,faceNr);        \r\n\t  }\r\n     else\r\n     {\r\n        faceBCMapping.Add1(faceBCs.Pos(bcNum)+1,faceNr);\r\n     }\r\n  }\r\n\r\n  faceBCs.SetSize(numBCs);\r\n  faceBCMapping.ChangeSize(numBCs);\r\n\r\n  // Now actually write the data to file\r\n  for(int bcInd = 1; bcInd <= faceBCs.Size(); bcInd++)\r\n  {\r\n      *outfile << \"solid Boundary_\" << faceBCs.Elem(bcInd) << \"\\n\";\r\n\r\n      for(int faceNr = 1;faceNr <= faceBCMapping.EntrySize(bcInd); faceNr++)\r\n      {\r\n        Array<SurfaceElementIndex> faceSei;\r\n          mesh.GetSurfaceElementsOfFace(faceBCMapping.Get(bcInd,faceNr),faceSei);\r\n\r\n          for (int i = 0; i < faceSei.Size(); i++)\r\n          {\r\n        \t  *outfile << \"facet normal \";\r\n        \t  const Point3d& p1 = mesh.Point(mesh[faceSei[i]].PNum(1));\r\n        \t  const Point3d& p2 = mesh.Point(mesh[faceSei[i]].PNum(2));\r\n        \t  const Point3d& p3 = mesh.Point(mesh[faceSei[i]].PNum(3));\r\n\r\n        \t  Vec3d normal = Cross(p2-p1,p3-p1);\r\n        \t  if (normal.Length() != 0)\r\n        \t  {\r\n        \t\t  normal /= (normal.Length());\r\n        \t  }\r\n\r\n        \t  *outfile << normal.X() << \" \" << normal.Y() << \" \" << normal.Z() << \"\\n\";\r\n        \t  *outfile << \"outer loop\\n\";\r\n\r\n        \t  *outfile << \"vertex \" << p1.X() << \" \" << p1.Y() << \" \" << p1.Z() << \"\\n\";\r\n        \t  *outfile << \"vertex \" << p2.X() << \" \" << p2.Y() << \" \" << p2.Z() << \"\\n\";\r\n        \t  *outfile << \"vertex \" << p3.X() << \" \" << p3.Y() << \" \" << p3.Z() << \"\\n\";\r\n\r\n        \t  *outfile << \"endloop\\n\";\r\n        \t  *outfile << \"endfacet\\n\";\r\n          }\r\n      }\r\n      *outfile << \"endsolid Boundary_\" << faceBCs.Elem(bcInd) << \"\\n\";\r\n  }\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n *\r\n *  write surface mesh as VRML file\r\n *\r\n */\r\n\r\nvoid WriteVRMLFormat (const Mesh & mesh,\r\n\t\t      bool faces,\r\n\t\t      const filesystem::path & filename)\r\n{\r\n\r\n  if (faces)\r\n\r\n    {\r\n      // Output in VRML, IndexedFaceSet is used\r\n      // Bartosz Sawicki <sawickib@ee.pw.edu.pl>\r\n\r\n      int np = mesh.GetNP();\r\n      int nse = mesh.GetNSE();\r\n      int i, j;\r\n\r\n      ofstream outfile (filename);\r\n\r\n      outfile.precision(6);\r\n      outfile.setf (ios::fixed, ios::floatfield);\r\n      outfile.setf (ios::showpoint);\r\n\r\n      outfile << \"#VRML V2.0 utf8 \\n\"\r\n\t         \"Background {\\n\"\r\n\t\t \"    skyColor [1 1 1]\\n\"\r\n     \t\t \"    groundColor [1 1 1]\\n\"\r\n\t\t \"}\\n\"\r\n\t\t \"Group{ children [\\n\"\r\n\t\t \"Shape{ \\n\"\r\n\t\t \"appearance Appearance { material Material { }} \\n\"\r\n                 \"geometry IndexedFaceSet { \\n\"\r\n                 \"coord Coordinate { point [ \\n\";\r\n\r\n\r\n      for (i = 1; i <= np; i++)\r\n        {\r\n          const Point3d & p = mesh.Point(i);\r\n          outfile.width(10);\r\n          outfile << p.X() << \" \";\r\n          outfile << p.Y() << \" \";\r\n          outfile << p.Z() << \" \\n\";\r\n\t}\r\n\r\n      outfile << \"  ] } \\n\"\r\n                 \"coordIndex [ \\n\";\r\n\r\n      for (i = 1; i <= nse; i++)\r\n\t{\r\n\t  const Element2d & el = mesh.SurfaceElement(i);\r\n\r\n\t  for (j = 1; j <= 3; j++)\r\n\t    {\r\n\t      outfile.width(8);\r\n\t      outfile << el.PNum(j)-1;\r\n\t    }\r\n\t  outfile << \" -1 \\n\";\r\n\t}\r\n\r\n      outfile << \"  ] \\n\";\r\n\r\n      //define number and RGB definitions of colors\r\n      outfile << \"color Color { color [1 0 0, 0 1 0, 0 0 1, 1 1 0]} \\n\"\r\n                 \"colorIndex [\\n\";\r\n\r\n      for (i = 1; i <= nse; i++)\r\n\t{\r\n\t  outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty();\r\n          outfile << endl;\r\n\t}\r\n\r\n      outfile << \" ] \\n\"\r\n                 \"colorPerVertex FALSE \\n\"\r\n                 \"creaseAngle 0 \\n\"\r\n\t\t \"solid FALSE \\n\"\r\n                 \"ccw FALSE \\n\"\r\n\t\t \"convex TRUE \\n\"\r\n                 \"} } # end of Shape\\n\"\r\n\t\t \"] }\\n\";\r\n\r\n    } /* end of VRMLFACES */\r\n\r\n\r\n  else\r\n\r\n    {\r\n        // Output in VRML, IndexedLineSet is used\r\n\t// Bartosz Sawicki <sawickib@ee.pw.edu.pl>\r\n\r\n      int np = mesh.GetNP();\r\n      int nse = mesh.GetNSE();\r\n      int i, j;\r\n\r\n      ofstream outfile (filename);\r\n\r\n      outfile.precision(6);\r\n      outfile.setf (ios::fixed, ios::floatfield);\r\n      outfile.setf (ios::showpoint);\r\n\r\n      outfile << \"#VRML V2.0 utf8 \\n\"\r\n\t         \"Background {\\n\"\r\n\t\t \"    skyColor [1 1 1]\\n\"\r\n     \t\t \"    groundColor [1 1 1]\\n\"\r\n\t\t \"}\\n\"\r\n\t\t \"Group{ children [\\n\"\r\n\t         \"Shape{ \\n\"\r\n\t\t \"appearance Appearance { material Material { }} \\n\"\r\n                 \"geometry IndexedLineSet { \\n\"\r\n                 \"coord Coordinate { point [ \\n\";\r\n\r\n\r\n      for (i = 1; i <= np; i++)\r\n        {\r\n          const Point3d & p = mesh.Point(i);\r\n          outfile.width(10);\r\n          outfile << p.X() << \" \";\r\n          outfile << p.Y() << \" \";\r\n          outfile << p.Z() << \" \\n\";\r\n\t}\r\n\r\n      outfile << \"  ] } \\n\"\r\n                 \"coordIndex [ \\n\";\r\n\r\n      for (i = 1; i <= nse; i++)\r\n\t{\r\n\t  const Element2d & el = mesh.SurfaceElement(i);\r\n\r\n\t  for (j = 1; j <= 3; j++)\r\n\t    {\r\n\t      outfile.width(8);\r\n\t      outfile << el.PNum(j)-1;\r\n\t    }\r\n\t  outfile.width(8);\r\n\t  outfile << el.PNum(1)-1;\r\n\t  outfile << \" -1 \\n\";\r\n\t}\r\n\r\n      outfile << \"  ] \\n\";\r\n\r\n/* Uncomment if you want color mesh\r\n      outfile << \"color Color { color [1 1 1, 0 1 0, 0 0 1, 1 1 0]} \\n\"\r\n                 \"colorIndex [\\n\";\r\n\r\n      for (i = 1; i <= nse; i++)\r\n\t{\r\n\t  outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty();\r\n          outfile << endl;\r\n\t}\r\n\r\n      outfile << \" ] \\n\"\r\n*/\r\n      outfile << \"colorPerVertex FALSE \\n\"\r\n                 \"} } #end of Shape\\n\"\r\n\t\t \"] } \\n\";\r\n\r\n    }\r\n\r\n}\r\n\r\nvoid WriteVRMLFormatLineset (const Mesh & mesh, const filesystem::path & filename)\r\n{\r\n  WriteVRMLFormat(mesh, false, filename);\r\n}\r\n\r\nvoid WriteVRMLFormatFaceset (const Mesh & mesh, const filesystem::path & filename)\r\n{\r\n  WriteVRMLFormat(mesh, true, filename);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n * FEPP .. a finite element package developed at University Linz, Austria\r\n */\r\nvoid WriteFEPPFormat (const Mesh & mesh,\r\n\t\t      const filesystem::path & filename)\r\n{\r\n\r\n  ofstream outfile (filename);\r\n\r\n  if (mesh.GetDimension() == 3)\r\n\r\n    {\r\n\r\n      // output for FEPP\r\n\r\n      int np = mesh.GetNP();\r\n      int ne = mesh.GetNE();\r\n      int nse = mesh.GetNSE();\r\n      // int ns = mesh.GetNFD();\r\n      int i, j;\r\n\r\n      outfile.precision(5);\r\n      outfile.setf (ios::fixed, ios::floatfield);\r\n      outfile.setf (ios::showpoint);\r\n\r\n      outfile << \"volumemesh4\" << endl;\r\n      outfile << nse << endl;\r\n      for (i = 1; i <= nse; i++)\r\n\t{\r\n\t  const Element2d & el = mesh.SurfaceElement(i);\r\n\r\n\t  //\t  int facenr = mesh.facedecoding.Get(el.GetIndex()).surfnr;\r\n\t  outfile.width(4);\r\n\t  outfile << el.GetIndex() << \" \";\r\n\t  outfile.width(4);\r\n\t  //\t  outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << \" \";\r\n\t  outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << \" \";\r\n\t  outfile.width(4);\r\n\t  outfile << el.GetNP() << \"    \";\r\n\t  for (j = 1; j <= el.GetNP(); j++)\r\n\t    {\r\n\t      outfile.width(8);\r\n\t      outfile << el.PNum(j);\r\n\t    }\r\n\t  outfile << \"\\n\";\r\n\t}\r\n\r\n\r\n      outfile << ne << \"\\n\";\r\n      /*\r\n      for (i = 1; i <= ne; i++)\r\n\t{\r\n\t  const Element & el = mesh.VolumeElement(i);\r\n      */\r\n      for (const Element & el : mesh.VolumeElements())\r\n        {\r\n\t  outfile.width(4);\r\n\t  outfile << el.GetIndex() << \" \";\r\n\t  outfile.width(4);\r\n\t  outfile << el.GetNP() << \" \";\r\n\t  for (j = 1; j <= el.GetNP(); j++)\r\n\t    {\r\n\t      outfile.width(8);\r\n\t      outfile << el.PNum(j);\r\n\t    }\r\n\t  outfile << \"\\n\";\r\n\t}\r\n\r\n      outfile << np << \"\\n\";\r\n      for (i = 1; i <= np; i++)\r\n\t{\r\n\t  const Point3d & p = mesh.Point(i);\r\n\r\n\t  outfile.width(10);\r\n\t  outfile << p.X() << \" \";\r\n\t  outfile.width(9);\r\n\t  outfile << p.Y() << \" \";\r\n\t  outfile.width(9);\r\n\t  outfile << p.Z() << \"\\n\";\r\n\t}\r\n\r\n      /*\r\n      if (typ == WRITE_FEPPML)\r\n\t{\r\n\t  int nbn =  mesh.mlbetweennodes.Size();\r\n\t  outfile << nbn << \"\\n\";\r\n\t  for (i = 1; i <= nbn; i++)\r\n\t    outfile << mesh.mlbetweennodes.Get(i).I1() << \" \"\r\n\t\t    << mesh.mlbetweennodes.Get(i).I2() << \"\\n\";\r\n\r\n\r\n\t  //\t  int ncon = mesh.connectedtonode.Size();\r\n\t  //\t  outfile << ncon << \"\\n\";\r\n\t  //\t  for (i = 1; i <= ncon; i++)\r\n\t  //\t    outfile << i << \" \" << mesh.connectedtonode.Get(i) << endl;\r\n\t}\r\n      */\r\n\r\n      /*\r\n      // write CSG surfaces\r\n      if (&geom && geom.GetNSurf() >= ns)\r\n\t{\r\n\t  outfile << ns << endl;\r\n\t  for (i = 1; i <= ns; i++)\r\n\t    geom.GetSurface(mesh.GetFaceDescriptor(i).SurfNr())->Print(outfile);\r\n\t}\r\n      else\r\n      */\r\n\toutfile << \"0\" << endl;\r\n    }\r\n\r\n\r\n  else\r\n\r\n    { // 2D fepp format\r\n\r\n      ;\r\n      /*\r\n      extern SplineGeometry2d * geometry2d;\r\n      if (geometry2d)\r\n\tSave2DMesh (mesh, &geometry2d->GetSplines(), outfile);\r\n      else\r\n\tSave2DMesh (mesh, 0, outfile);\r\n      */\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n *  Edge element mesh format\r\n *  points, elements, edges\r\n */\r\n\r\nvoid WriteEdgeElementFormat (const Mesh & mesh,\r\n\t\t\t     const filesystem::path & filename)\r\n{\r\n  cout << \"write edge element format\" << endl;\r\n\r\n  const MeshTopology * top = &mesh.GetTopology();\r\n  int npoints = mesh.GetNP();\r\n  int nelements = mesh.GetNE();\r\n  int nsurfelem = mesh.GetNSE();\r\n  int nedges = top->GetNEdges();\r\n\r\n  int inverttets = mparam.inverttets;\r\n  int invertsurf = mparam.inverttrigs;\r\n  NgArray<int> edges;\r\n\r\n  ofstream outfile (filename);\r\n\r\n  outfile.precision(6);\r\n  outfile.setf (ios::fixed, ios::floatfield);\r\n  outfile.setf (ios::showpoint);\r\n\r\n\r\n  // vertices with coordinates\r\n  outfile << npoints << \"\\n\";\r\n  for (int i = 1; i <= npoints; i++)\r\n    {\r\n      const Point3d & p = mesh.Point(i);\r\n\r\n      outfile.width(10);\r\n      outfile << p.X() << \" \";\r\n      outfile.width(9);\r\n      outfile << p.Y() << \" \";\r\n      outfile.width(9);\r\n      outfile << p.Z() << \"\\n\";\r\n    }\r\n\r\n  // element - edge - list\r\n  outfile << nelements << \" \" << nedges << \"\\n\";\r\n  /*\r\n  for (i = 1; i <= nelements; i++)\r\n    {\r\n      Element el = mesh.VolumeElement(i);\r\n  */\r\n  for (ElementIndex ei : Range(mesh.VolumeElements()))\r\n    {\r\n      int i = ei-IndexBASE(ei)+1;\r\n      \r\n      Element el = mesh.VolumeElement(ei);\r\n\r\n      if (inverttets)\r\n      \tel.Invert();\r\n      outfile.width(4);\r\n      outfile << el.GetIndex() << \"  \";\r\n      outfile.width(8);\r\n      outfile << el.GetNP();\r\n      for (int j = 1; j <= el.GetNP(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << el.PNum(j);\r\n\t}\r\n\r\n      // top->GetElementEdges(i,edges);\r\n      auto eledges = top->GetEdges(ei);\r\n      outfile << endl << \"      \";\r\n      outfile.width(8);\r\n      outfile << eledges.Size();\r\n      for (int j=1; j <= eledges.Size(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << eledges[j-1]+1;\r\n\t}\r\n      outfile << \"\\n\";\r\n\r\n      // orientation:\r\n      top->GetElementEdgeOrientations(i,edges);\r\n      outfile << \"              \";\r\n      for (int j=1; j <= edges.Size(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << edges[j-1];\r\n\t}\r\n      outfile << \"\\n\";\r\n    }\r\n\r\n  // surface element - edge - list (with boundary conditions)\r\n  outfile << nsurfelem << \"\\n\";\r\n  for (int i = 1; i <= nsurfelem; i++)\r\n    {\r\n      SurfaceElementIndex sei(i-1);\r\n      Element2d el = mesh[sei];\r\n      if (invertsurf)\r\n\tel.Invert();\r\n      outfile.width(4);\r\n      outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << \"  \";\r\n      outfile.width(8);\r\n      outfile << el.GetNP();\r\n      for (int j = 1; j <= el.GetNP(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << el.PNum(j);\r\n\t}\r\n\r\n      // top->GetSurfaceElementEdges(i,edges);\r\n      auto edges = top->GetEdges(sei);\r\n      outfile << endl << \"      \";\r\n      outfile.width(8);\r\n      outfile << edges.Size();\r\n      for (int j=0; j < edges.Size(); j++)\r\n\t{\r\n\t  outfile << \" \";\r\n\t  outfile.width(8);\r\n\t  outfile << edges[j]+1;\r\n\t}\r\n      outfile << \"\\n\";\r\n    }\r\n\r\n\r\n  // int v1, v2;\r\n  // edge - vertex - list\r\n  outfile << nedges << \"\\n\";\r\n  for (int i=1; i <= nedges; i++)\r\n    {\r\n      // top->GetEdgeVertices(i,v1,v2);\r\n      auto [v1,v2] = top->GetEdgeVertices(i-1);\r\n      outfile.width(4);\r\n      outfile << v1;\r\n      outfile << \" \";\r\n      outfile.width(8);\r\n      outfile << v2 << endl;\r\n    }\r\n}\r\n\r\nstatic RegisterUserFormat reg_neutral(\"Neutral Format\", {\".mesh\"}, ReadFile, WriteNeutralFormat);\r\nstatic RegisterUserFormat reg_surface(\"Surface Mesh Format\", {\".mesh\", \".surf\"} ,ReadFile, WriteSurfaceFormat);\r\nstatic RegisterUserFormat reg_stl (\"STL Format\", {\".stl\", \".stlb\"}, ReadFile, WriteSTLFormat);\r\nstatic RegisterUserFormat reg_stlx (\"STL Extended Format\", {\".stl\", \".stlb\"}, nullopt, WriteSTLExtFormat);\r\nstatic RegisterUserFormat reg_vrml (\"VRML Format\", {\".*\"}, nullopt, WriteVRMLFormatLineset);\r\nstatic RegisterUserFormat reg_vrml_faces (\"VRML Format Faces\", {\".*\"}, nullopt, WriteVRMLFormatFaceset);\r\nstatic RegisterUserFormat reg_fepp (\"Fepp Format\", {\"*\"}, nullopt, WriteFEPPFormat);\r\nstatic RegisterUserFormat reg_edgeelement (\"EdgeElement Format\", {\"*\"}, nullopt, WriteEdgeElementFormat);\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "libsrc/interface/writeuser.hpp",
    "content": "#ifndef WRITEUSER\r\n#define WRITEUSER\r\n\r\n/**************************************************************************/\r\n/* File:    writeuser.hh                                                  */\r\n/* Authors: many                                                          */\r\n/* Date:    10. Dec. 97                                                   */\r\n/**************************************************************************/\r\n\r\n#include <filesystem>\r\n#include <functional>\r\n#include <optional>\r\n\r\n#include <meshing.hpp>\r\n\r\nnamespace netgen {\r\n\r\nusing namespace std::filesystem;\r\n\r\ntypedef std::function<void (const Mesh & mesh, const filesystem::path & filename)> FWrite;\r\ntypedef std::function<void (Mesh & mesh, const filesystem::path & filename)> FRead;\r\ntypedef std::function<bool (const filesystem::path & filename)> FTest;\r\n\r\nstruct UserFormatRegister {\r\n  struct UserFormatEntry {\r\n    string format;\r\n    Array<string> extensions;\r\n    optional<FRead> read;\r\n    optional<FWrite> write;\r\n  };\r\n  static void Register(UserFormatEntry && entry);\r\n\r\n  static const bool HaveFormat(string format);\r\n  DLL_HEADER static const UserFormatEntry & Get(string format);\r\n\r\n  template<typename TFunc>\r\n  static void IterateFormats(TFunc func, bool need_read=false, bool need_write=false) {\r\n    Array<string> import_formats;\r\n    for(const auto & e: getFormats())\r\n    if((!need_read || e.second.read) && (!need_write || e.second.write))\r\n      import_formats.Append(e.second.format);\r\n    QuickSort(import_formats);\r\n    for(auto format : import_formats)\r\n      func(Get(format));\r\n  }\r\n\r\n  DLL_HEADER static std::map<std::string, UserFormatEntry>& getFormats();\r\n};\r\n\r\nstruct RegisterUserFormat {\r\n  RegisterUserFormat(string format, Array<string> extensions, optional<FRead> read, optional<FWrite> write, FTest ftest = [](const filesystem::path & ){return true;})\r\n  {\r\n    UserFormatRegister::Register({format, std::move(extensions), std::move(read), std::move(write)});\r\n  }\r\n};\r\n\r\nDLL_HEADER void ReadFile(Mesh & mesh, const filesystem::path & filename);\r\nDLL_HEADER void ReadUserFormat(Mesh & mesh, const filesystem::path & filename, const string & format = \"\");\r\n\r\n\r\nextern bool DLL_HEADER WriteUserFormat (const string & format,\r\n                                        const Mesh & mesh,\r\n                                        const filesystem::path & filename);\r\n\r\nextern void DLL_HEADER RegisterUserFormats (NgArray<const char*> & names,\r\n                                 NgArray<const char*> & extensions);\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "libsrc/interface/wuchemnitz.cpp",
    "content": "// Write Chemnitz file format\n\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include \"writeuser.hpp\"\n\nnamespace netgen\n{\n\n  class POINT3D\n  {\n  public:\n    POINT3D () { };\n    double x, y, z;\n  };\n\n  class VOLELEMENT\n  {\n  public:\n    int domnr, p1, p2, p3, p4;\n    int faces[4];\n\n    VOLELEMENT () \n    { for (int i = 0; i < 4; i++) faces[i] = 0; }\n  };\n  \n  class SURFELEMENT\n  {\n  public:\n    SURFELEMENT () { };\n    int snr, p1, p2, p3;\n  };\n  \n\n  class FACE\n  {\n  public:\n    int p1, p2, p3;\n    int edges[3];\n\n    FACE () \n    { for (int i = 0; i < 3; i++) edges[i] = 0; }\n  };\n\n  class EDGE\n  {\n  public:\n    EDGE () { };\n    int p1, p2;\n  };\n\n  static NgArray<POINT3D> points;\n  static NgArray<VOLELEMENT> volelements;\n  static NgArray<SURFELEMENT> surfelements;\n\n  static NgArray<FACE> faces;\n  static NgArray<EDGE> edges;\n\n\n  void ReadFile (char * filename)\n  {\n    int i, n;\n    ifstream infile(filename);\n    char reco[100];\n  \n  \n    infile >> reco;  // file format recognition\n  \n    infile >> n;   // number of surface elements\n    cout << n << \" Surface elements\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        SURFELEMENT sel;\n        infile >> sel.snr >> sel.p1 >> sel.p2 >> sel.p3;\n        surfelements.Append (sel);\n      }\n    \n    infile >> n;   // number of volume elements\n    cout << n << \" Volume elements\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        VOLELEMENT el;\n        infile >> el.p1 >> el.p2 >> el.p3 >> el.p4;\n        volelements.Append (el);\n      }\n    \n    infile >> n;   // number of points \n    cout << n << \" Points\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        POINT3D p;\n        infile >> p.x >> p.y >> p.z;\n        points.Append (p);\n      }\n  }\n  \n  \n\n  void ReadFileMesh (const Mesh & mesh)\n  {\n    int i, n;\n  \n    n = mesh.GetNSE();   // number of surface elements\n    cout << n << \" Surface elements\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        SURFELEMENT sel;\n        const Element2d & el = mesh.SurfaceElement(i);\n        sel.snr = el.GetIndex();\n        sel.p1 = el.PNum(1);\n        sel.p2 = el.PNum(2);\n        sel.p3 = el.PNum(3);\n        surfelements.Append (sel);\n      }\n    \n    n = mesh.GetNE();   // number of volume elements\n    cout << n << \" Volume elements\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        VOLELEMENT el;\n        const Element & nel = mesh.VolumeElement(i);\n        el.p1 = nel.PNum(1);\n        el.p2 = nel.PNum(2);\n        el.p3 = nel.PNum(3);\n        el.p4 = nel.PNum(4);\n        //      infile >> el.p1 >> el.p2 >> el.p3 >> el.p4;\n        volelements.Append (el);\n      }\n    \n    n = mesh.GetNP();   // number of points \n    cout << n << \" Points\" << endl;\n  \n    for (i = 1; i <= n; i++)\n      {\n        POINT3D p;\n        Point3d mp = mesh.Point(i);\n        p.x = mp.X();\n        p.y = mp.Y();\n        p.z = mp.Z();\n        //      infile >> p.x >> p.y >> p.z;\n        points.Append (p);\n      }\n  }\n  \n\n\n\n  void Convert ()\n  {\n    int i, j, facei, edgei;\n    INDEX_3 i3;\n    INDEX_2 i2;\n\n    INDEX_3_HASHTABLE<int> faceindex(volelements.Size()/5 + 1);\n    INDEX_2_HASHTABLE<int> edgeindex(volelements.Size()/5 + 1);\n  \n    for (i = 1; i <= volelements.Size(); i++)\n      {\n        for (j = 1; j <= 4; j++)\n          {\n            switch (j)\n              {\n              case 1:\n                i3.I1() = volelements.Get(i).p2;\n                i3.I2() = volelements.Get(i).p3;\n                i3.I3() = volelements.Get(i).p4;\n                break;\n              case 2:\n                i3.I1() = volelements.Get(i).p1;\n                i3.I2() = volelements.Get(i).p3;\n                i3.I3() = volelements.Get(i).p4;\n                break;\n              case 3:\n                i3.I1() = volelements.Get(i).p1;\n                i3.I2() = volelements.Get(i).p2;\n                i3.I3() = volelements.Get(i).p4;\n                break;\n              case 4:\n                i3.I1() = volelements.Get(i).p1;\n                i3.I2() = volelements.Get(i).p2;\n                i3.I3() = volelements.Get(i).p3;\n                break;\n              default:\n                i3.I1()=i3.I2()=i3.I3()=0;\n              }\n            i3.Sort();\n            if (faceindex.Used (i3)) \n              facei = faceindex.Get(i3);\n            else\n              {\n                FACE fa;\n                fa.p1 = i3.I1();\n                fa.p2 = i3.I2();\n                fa.p3 = i3.I3();\n                faces.Append (fa);\n                facei = faces.Size();\n                faceindex.Set (i3, facei);\n              } \n        \n            volelements.Elem(i).faces[j-1] = facei;  \n          }    \n    \n      } \n \n\n    for (i = 1; i <= faces.Size(); i++)\n      {\n        for (j = 1; j <= 3; j++)\n          {\n            switch (j)\n              {\n              case 1:\n                i2.I1() = faces.Get(i).p2;\n                i2.I2() = faces.Get(i).p3;\n                break;\n              case 2:\n                i2.I1() = faces.Get(i).p1;\n                i2.I2() = faces.Get(i).p3;\n                break;\n              case 3:\n                i2.I1() = faces.Get(i).p1;\n                i2.I2() = faces.Get(i).p2;\n                break;\n              default:\n                i2.I1()=i2.I2()=0;\n              }\n            if (i2.I1() > i2.I2()) swap (i2.I1(), i2.I2());\n            if (edgeindex.Used (i2)) \n              edgei = edgeindex.Get(i2);\n            else\n              {\n                EDGE ed;\n                ed.p1 = i2.I1();\n                ed.p2 = i2.I2();\n                edges.Append (ed);\n                edgei = edges.Size();\n                edgeindex.Set (i2, edgei);\n              } \n        \n            faces.Elem(i).edges[j-1] = edgei;  \n          }    \n    \n      }  \n \n  }  \n  \n  \n  void WriteFile (ostream & outfile)\n  {\n    int i;\n  \n    outfile \n      << \"#VERSION: 1.0\" << endl\n      << \"#PROGRAM: NETGEN\" << endl\n      << \"#EQN_TYPE: POISSON\" << endl\n      << \"#DIMENSION: 3D\" << endl\n      << \"#DEG_OF_FREE: 1\" << endl\n      << \"#DESCRIPTION: I don't know\" << endl\n      << \"##RENUM: not done\" << endl\n      << \"#USER: Kleinzen\" << endl\n      << \"DATE: 10.06.1996\" << endl;\n  \n    outfile << \"#HEADER:   8\" << endl\n            << points.Size() << \"  \" << edges.Size() << \"  \" \n            << faces.Size() << \"  \" << volelements.Size() << \"  0  0  0  0\" << endl;\n  \n    outfile << \"#VERTEX:   \" << points.Size() << endl;\n    for (i = 1; i <= points.Size(); i++)\n      outfile << \"  \" << i << \"  \" << points.Get(i).x << \"  \" << points.Get(i).y \n              << \"  \" << points.Get(i).z << endl;\n    \t\n    outfile << \"#EDGE:  \" << edges.Size() << endl;\n    for (i = 1; i <= edges.Size(); i++)\n      outfile << \"  \" << i << \"  1  \" \n              << edges.Get(i).p1 << \"  \" \n              << edges.Get(i).p2 \n              << \"  0\" << endl;\n    \n    outfile << \"#FACE:  \" << faces.Size() << endl;  \n    for (i = 1; i <= faces.Size(); i++)\n      outfile << \"  \" << i << \"  1  3  \" \n              << faces.Get(i).edges[0] << \"  \" \n              << faces.Get(i).edges[1] << \"  \" \n              << faces.Get(i).edges[2] << endl;\n    \t\n    outfile << \"#SOLID:  \" << volelements.Size() << endl;\n    for (i = 1; i <= volelements.Size(); i++)\n      outfile << \"  \" << i << \"  1  4  \" \n              << volelements.Get(i).faces[0] << \"  \"\n              << volelements.Get(i).faces[1] << \"  \"\n              << volelements.Get(i).faces[2] << \"  \"\n              << volelements.Get(i).faces[3] << endl;\n    \t\n    outfile << \"#END_OF_DATA\" << endl;\n  }\n    \n\n  void WriteUserChemnitz (const Mesh & mesh,\n                          const filesystem::path & filename)\n  {\n    ofstream outfile (filename);\n\n    ReadFileMesh (mesh);\n    Convert ();\n  \n    WriteFile (outfile);\n    cout << \"Wrote Chemnitz standard file\" << endl;\n  }\nstatic RegisterUserFormat reg_chemnitz (\"Chemnitz Format\", {\"*\"}, nullopt, WriteUserChemnitz );\n}\n"
  },
  {
    "path": "libsrc/linalg/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n  bfgs.cpp\n  densemat.cpp\n  linopt.cpp\n  linsearch.cpp\n  polynomial.cpp\n)\n\ninstall(FILES\n  densemat.hpp linalg.hpp opti.hpp\n  polynomial.hpp vector.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/linalg COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/linalg/bfgs.cpp",
    "content": "/***************************************************************************/\n/*                                                                         */\n/* Vorlesung Optimierung I, Gfrerer, WS94/95                               */\n/* BFGS-Verfahren zur Lösung freier nichtlinearer Optimierungsprobleme     */\n/*                                                                         */\n/* Programmautor:  Joachim Schöberl                                        */\n/* Matrikelnummer: 9155284                                                 */\n/*                                                                         */\n/***************************************************************************/\n\n#include <mystdlib.h>\n#include <myadt.hpp> \n\n#include <linalg.hpp>\n#include \"opti.hpp\"\n\n\nnamespace netgen\n{\n\nvoid Cholesky (const DenseMatrix & a,\n\t       DenseMatrix & l, Vector & d)\n{\n  // Factors   A = L D L^T\n\n  double x;\n\n  int n = a.Height();\n  \n  //  (*testout) << \"a = \" << a << endl;\n\n  l = a;\n\n  for (int i = 1; i <= n; i++)\n    {\n      for (int j = i; j <= n; j++)\n\t{\n\t  x = l.Get(i, j);\n\n\t  for (int k = 1; k < i; k++)\n\t    x -= l.Get(i, k) * l.Get(j, k) * d(k-1); \n          \n\t  if (i == j)\n\t    {\n\t      d(i-1) = x;\n\t    }\n\t  else\n\t    {\n\t      l.Elem(j, i) = x / d(i-1);\n\t    }\n\t}\n    }\n\n  for (int i = 1; i <= n; i++)\n    {\n      l.Elem(i, i) = 1;\n      for (int j = i+1; j <= n; j++)\n\tl.Elem(i, j) = 0;\n    }\n\n  /*\n  // Multiply:\n  (*testout) << \"multiplied factors: \" << endl;\n  for (i = 1; i <= n; i++)\n    for (j = 1; j <= n; j++)\n      {\n\tx = 0;\n\tfor (k = 1; k <= n; k++)\n\t  x += l.Get(i, k) * l.Get(j, k) * d.Get(k);\n\t(*testout) << x << \" \";\n      }\n  (*testout) << endl;\n  */\n}\n\n\nvoid MultLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)\n{\n  /*\n  int i, j, n;\n  double val;\n\n  n = l.Height();\n  p = g;\n  for (i = 1; i <= n; i++)\n    {\n      val = 0;\n      for (j = i; j <= n; j++)\n\tval += p.Get(j) * l.Get(j, i);\n      p.Set(i, val);\n    }\n  for (i = 1; i <= n; i++)\n    p.Elem(i) *= d.Get(i);\n\n  for (i = n; i >= 1; i--)\n    {\n      val = 0;\n      for (j = 1; j <= i; j++)\n\tval += p.Get(j) * l.Get(i, j);\n      p.Set(i, val);\n    }\n  */\n\n\n\n  double val;\n\n  int n = l.Height();\n  p = g;\n  \n  for (int i = 0; i < n; i++)\n    {\n      val = 0;\n      for (int j = i; j < n; j++)\n\tval += p(j) * l(j, i);\n      p(i) = val;\n    }\n\n  for (int i = 0; i < n; i++)\n    p(i) *= d(i);\n\n  for (int i = n-1; i >= 0; i--)\n    {\n      val = 0;\n      for (int j = 0; j <= i; j++)\n\tval += p(j) * l(i, j);\n      p(i) = val;\n    }\n}\n\nvoid SolveLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)\n{\n  double val;\n\n  int n = l.Height();\n  p = g;\n\n  for (int i = 0; i < n; i++)\n    {\n      val = 0;\n      for (int j = 0; j < i; j++)\n\tval += p(j) * l(i,j);\n      p(i) -= val;\n    }\n\n  for (int i = 0; i < n; i++)\n    p(i) /= d(i);\n  \n  for (int i = n-1; i >= 0; i--)\n    {\n      val = 0;\n      for (int j = i+1; j < n; j++)\n\tval += p(j) * l(j, i);\n      p(i) -= val;\n    }\n}\n\nint LDLtUpdate (DenseMatrix & l, Vector & d, double a, const Vector & u)\n{\n  // Bemerkung: Es wird a aus R erlaubt\n  // Rueckgabewert: 0 .. D bleibt positiv definit\n  //                1 .. sonst\n\n  int n = l.Height();\n\n  Vector v(n);\n  double t, told, xi;\n\n  told = 1;\n  v = u;\n\n  for (int j = 1; j <= n; j++)\n    {\n      t = told + a * sqr (v(j-1)) / d(j-1);\n\n      if (t <= 0) \n\t{\n\t  (*testout) << \"update err, t = \" << t << endl;\n\t  return 1;\n\t}\n\n      xi = a * v(j-1) / (d(j-1) * t);\n\n      d(j-1) *= t / told;\n\n      for (int i = j + 1; i <= n; i++)\n\t{\n\t  v(i-1) -= v(j-1) * l.Elem(i, j);\n\t  l.Elem(i, j) += xi * v(i-1);\n\t}\n\n      told = t;\n    }\n\n  return 0;\n}\n\n\ndouble BFGS (\n\t     Vector & x,         // i: Startwert\n\t     // o: Loesung, falls IFAIL = 0\n\t     const MinFunction & fun,\n\t     const OptiParameters & par,\n\t     double eps\n\t     )\n\n\n{\n  int n = x.Size();\n  long it;\n  char a1crit, a3acrit;\n\n\n  Vector d(n), g(n), p(n), temp(n), bs(n), xneu(n), y(n), s(n), x0(n);\n  DenseMatrix l(n);\n  DenseMatrix hesse(n);\n\n  double /* normg, */ alphahat, hd, fold;\n  double a1, a2;\n  const double mu1 = 0.1, sigma = 0.1, xi1 = 1, xi2 = 10;\n  const double tau = 0.1, tau1 = 0.1, tau2 = 0.6;\n\n  Vector typx(x.Size());      // i: typische Groessenordnung der Komponenten\n  double f, f0;\n  double typf;               // i: typische Groessenordnung der Loesung\n  double fmin = -1e5;           // i: untere Schranke fuer Funktionswert\n  //  double eps = 1e-8;            // i: Abbruchschranke fuer relativen Gradienten\n  double tauf = 0.1;            // i: Abbruchschranke fuer die relative Aenderung der\n                                //    Funktionswerte\n  int ifail;                    // o:  0 .. Erfolg\n                                //    -1 .. Unterschreitung von fmin\n                                //     1 .. kein Erfolg bei Liniensuche\n                                //     2 .. Überschreitung von itmax\n\n  typx = par.typx;\n  typf = par.typf;\n\n\n  l = 0;\n  for (int i = 1; i <= n; i++)\n    l.Elem(i, i) = 1;\n\n  f = fun.FuncGrad (x, g);\n  f0 = f;\n  x0 = x;\n\n  it = 0;\n  do\n    {\n      // Restart\n      // cout << \"it \" << it << \"f = \" << f << endl;\n      if (it % (5 * n) == 0)\n\t{\n\n\t  for (int i = 1; i <= n; i++)\n\t    d(i-1) = typf/ sqr (typx(i-1));   // 1;\n\t  for (int i = 2; i <= n; i++)\n\t    for (int j = 1; j < i; j++)\n\t      l.Elem(i, j) = 0;\n\n\t  /*\n\t  hesse = 0;\n\t  for (i = 1; i <= n; i++)\n\t    hesse.Elem(i, i) = typf / sqr (typx.Get(i));  \n\n\t  fun.ApproximateHesse (x, hesse);\n\n\t  Cholesky (hesse, l, d);\n\t  */\n\t}\n\n      it++;\n      if (it > par.maxit_bfgs)\n\t{\n\t  ifail = 2;\n\t  break;\n\t}\n\n\n      // Solve with factorized B\n\n      SolveLDLt (l, d, g, p);\n\n //      (*testout) << \"l \" << l << endl\n// \t\t << \"d \" << d << endl\n// \t\t << \"g \" << g << endl\n// \t\t << \"p \" << p << endl;\n\n\n      p *= -1;\n      y = g;\n\n      fold = f;\n\n      // line search\n\n      alphahat = 1;\n      lines (x, xneu, p, f, g, fun, par, alphahat, fmin,\n\t     mu1, sigma, xi1, xi2, tau, tau1, tau2, ifail);\n\n      if(ifail == 1)\n\t(*testout) << \"no success with linesearch\" << endl;\n\n       /*\n      // if (it > par.maxit_bfgs/2)\n\t{\n\t  (*testout) << \"x = \" << x << endl;\n\t  (*testout) << \"xneu = \" << xneu << endl;\n\t  (*testout) << \"f = \" << f << endl;\n\t  (*testout) << \"g = \" << g << endl;\n\t}\n      */\n\n      //      (*testout) << \"it = \" << it << \" f = \" << f << endl;\n      //      if (ifail != 0) break;\n\n      s.Set2 (1, xneu, -1, x);\n      y *= -1;\n      y.Add (1,g); // y += g;\n\n      x = xneu;\n\n      // BFGS Update\n\n      MultLDLt (l, d, s, bs);\n\n      a1 = y * s;\n      a2 = s * bs;\n\n      if (a1 > 0 && a2 > 0)\n\t{\n\t  if (LDLtUpdate (l, d, 1 / a1, y) != 0)\n\t    {\n              // cerr << \"BFGS update error1\" << endl;\n\t      (*testout) << \"BFGS update error1\" << endl;\n\t      (*testout) << \"l \" << endl << l << endl\n\t\t\t << \"d \" << d << endl;\n\t      ifail = 1;\n\t      break;\n\t    }\n\n\t  if (LDLtUpdate (l, d, -1 / a2, bs) != 0)\n\t    {\n              // cerr << \"BFGS update error2\" << endl;\n\t      (*testout) << \"BFGS update error2\" << endl;\n\t      (*testout) << \"l \" << endl << l << endl\n\t\t\t << \"d \" << d << endl;\n\t      ifail = 1;\n\t      break;\n\t    }\n\t}\n\n      // Calculate stop conditions\n\n      hd = eps * max2 (typf, fabs (f));\n      a1crit = 1;\n      for (int i = 1; i <= n; i++)\n\tif ( fabs (g(i-1)) * max2 (typx(i-1), fabs (x(i-1))) > hd)\n\t  a1crit = 0;\n\n\n      a3acrit = (fold - f <= tauf * max2 (typf, fabs (f)));\n\n      //    testout << \"g = \" << g << endl;\n      //    testout << \"a1crit, a3crit = \" << int(a1crit) << \", \" << int(a3acrit) << endl;\n\n      /*\n\t// Output for tests\n\n\tnormg = sqrt (g * g);\n\n\ttestout << \"it =\" << setw (5) << it\n\t<< \" f =\" << setw (12) << setprecision (5) << f\n\t<< \" |g| =\" << setw (12) << setprecision (5) << normg;\n\n\ttestout << \" x = (\" << setw (12) << setprecision (5) << x.Elem(1);\n\tfor (i = 2; i <= n; i++)\n\ttestout << \",\" << setw (12) << setprecision (5) << x.Elem(i);\n\ttestout << \")\" << endl;\n\t*/\n\n      //(*testout) << \"it = \" << it << \" f = \" << f << \" x = \" << x << endl\n      //\t << \" g = \" << g << \" p = \" << p << endl << endl;\n\n      //      (*testout) << \"|g| = \" << g.L2Norm() << endl;\n\n      if (g.L2Norm() < fun.GradStopping (x)) break;\n\n    }\n  while (!a1crit || !a3acrit);\n\n  /*\n  (*testout) << \"it = \" << it << \" g = \" << g << \" f = \" << f \n\t     << \" fail = \" << ifail << endl;\n  */\n  if (f0 < f || (ifail == 1))\n    {\n      (*testout) << \"fail, f = \" << f << \" f0 = \" << f0 << endl;\n      f = f0;\n      x = x0;\n    }\n\n  // cout << endl;\n\n  //  (*testout) << \"x = \" << x << \", x0 = \" << x0 << endl;\n  return f;\n}\n\n}\n"
  },
  {
    "path": "libsrc/linalg/densemat.cpp",
    "content": "#include <mystdlib.h>\n\n#include <linalg.hpp>\n\n\nnamespace netgen\n{\n  DenseMatrix :: DenseMatrix () \n  {\n    data = NULL;\n    height = 0;\n    width = 0;\n  }\n\n  DenseMatrix :: DenseMatrix (int h, int w)\n  {\n    if (!w) w = h;\n    width = w; \n    height = h;\n    int hw = h*w;\n    if (hw)\n      data = new double[hw];\n    else \n      data = 0;\n\n    for (int i = 0 ; i < (hw); i++)\n      data[i] = 0;\n  }\n\n  /*\n    DenseMatrix :: DenseMatrix (int h, int w, const double * d) \n    : BaseMatrix (h, w)\n    {\n    int size = h * w;  \n    int i;\n  \n    if (size)\n    {\n    data = new double[size]; \n    for (i = 0; i < size; i++)\n    data[i] = d[i];\n    }\n    else\n    data = NULL;\n    }    \n  */\n\n  DenseMatrix :: DenseMatrix (const DenseMatrix & m2)\n  {\n    data = NULL; height = width = 0;\n    SetSize (m2.Height(), m2.Width());\n    if (Height() && Width())\n      memcpy (data, m2.data, sizeof(double) * (Height() * Width()));\n  }\n\n  DenseMatrix :: ~DenseMatrix ()\n  {\n    delete [] data;\n  }\n  \n  \n  void DenseMatrix :: SetSize (int h, int w)\n  {\n    if (!w) w = h;\n    if (height == h && width == w)\n      return;\n          \n    height = h;\n    width = w;\n    \n    delete[] data;\n    \n    if (h && w)  \n      data = new double[h*w];\n    else\n      data = NULL;\n  }\n\n\n  /*\n    DenseMatrix & DenseMatrix :: operator= (const BaseMatrix & m2)\n    {\n    int i, j;\n\n    SetSize (m2.Height(), m2.Width());\n\n    if (data)\n    for (i = 1; i <= Height(); i++)\n    for (j = 1; j <= Width(); j++)\n    Set (i, j, m2(i, j));\n    else\n    (*myerr) << \"DenseMatrix::Operator=: Matrix not allocated\" << endl;\n\n    return *this;\n    }\n  */\n\n\n  DenseMatrix & DenseMatrix :: operator= (const DenseMatrix & m2)\n  {\n    SetSize (m2.Height(), m2.Width());\n    \n    if (data) memcpy (data, m2.data, sizeof(double) * m2.Height() * m2.Width());\n    return *this;\n  }\n\n\n  DenseMatrix & DenseMatrix :: operator+= (const DenseMatrix & m2)\n  {\n    int i;\n    double * p, * q;\n    \n    if (Height() != m2.Height() || Width() != m2.Width())\n      {\n        (*myerr) << \"DenseMatrix::Operator+=: Sizes don't fit\" << endl;\n        return *this;\n      }\n    \n    if (data)\n      {\n\tp = data;\n\tq = m2.data;\n\tfor (i = Width() * Height(); i > 0; i--)\n          {\n            *p += *q;\n            p++;\n            q++;\n          }\n      }\n    else\n      (*myerr) << \"DenseMatrix::Operator+=: Matrix not allocated\" << endl;\n\n    return *this;\n  }\n\n\n  DenseMatrix & DenseMatrix :: operator-= (const DenseMatrix & m2)\n  {\n    int i;\n    double * p, * q;\n\n    if (Height() != m2.Height() || Width() != m2.Width())\n      {\n        (*myerr) << \"DenseMatrix::Operator-=: Sizes don't fit\" << endl;\n        return *this;\n      }\n\n    if (data)\n      {\n        p = data;\n        q = m2.data;\n        for (i = Width() * Height(); i > 0; i--)\n          {\n            *p -= *q;\n            p++;\n            q++;\n          }\n      }\n    else\n      (*myerr) << \"DenseMatrix::Operator-=: Matrix not allocated\" << endl;\n\n    return *this;\n  }\n\n  DenseMatrix & DenseMatrix :: operator= (double v)\n  {\n    double * p = data;\n\n    if (data)\n      for (int i = width*height; i > 0; i--, p++)\n        *p = v;\n\n    return *this;\n  }\n\n\n\n  DenseMatrix & DenseMatrix :: operator*= (double v)\n  {\n    double * p = data;\n\n    if (data)\n      for (int i = width*height; i > 0; i--, p++)\n        *p *= v;\n\n    return *this;\n  }\n\n\n  double DenseMatrix :: Det () const\n  {\n    if (width != height)\n      {\n        (*myerr) << \"DenseMatrix :: Det: width != height\" << endl;\n        return 0;\n      }\n\n    switch (width)\n      {\n      case 1: return data[0];\n      case 2: return data[0] * data[3] - data[1] * data[2];\n      case 3: return data[0] * data[4] * data[8]\n          + data[1] * data[5] * data[6]\n          + data[2] * data[3] * data[7] \n          - data[0] * data[5] * data[7]\n          - data[1] * data[3] * data[8]\n          - data[2] * data[4] * data[6];\n      default:\n        {\n          (*myerr) << \"Matrix :: Det:  general size not implemented (size=\" << width << \")\" << endl;\n          return 0;\n        }\n      }\n  }\n\n\n  void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2)\n  {\n    double det;\n\n    if (m1.Width() != m1.Height())\n      {\n        (*myerr) << \"CalcInverse: matrix not symmetric\" << endl;\n        return;\n      }\n    if (m1.Width() != m2.Width() || m1.Height() != m2.Height())\n      {\n        (*myerr) << \"CalcInverse: dim(m2) != dim(m1)\" << endl;\n        return;\n      }\n\n\n    if (m1.Width() <= 3)\n      {\n        det = m1.Det();\n        if (det == 0)\n          {\n            (*myerr) << \"CalcInverse: Matrix singular\" << endl;\n            (*testout) << \"CalcInverse: Matrix singular\" << endl;\n            return;\n          }\n\n        det = 1.0 / det;\n        switch (m1.Width())\n          {\n          case 1:\n            {\n              m2(0,0) = det;\n              return;\n            }\n          case 2:\n            {\n              m2(0,0) = det * m1(3);\n              m2(1,1) = det * m1(0);  \n              m2(0,1) = -det * m1(1);\n              m2(1,0) = - det * m1(2);\n              return;\n            }\n          case 3:\n            {\n              m2(0, 0) =  det * (m1(4) * m1(8) - m1(5) * m1(7));\n              m2(1, 0) = -det * (m1(3) * m1(8) - m1(5) * m1(6));\n              m2(2, 0) =  det * (m1(3) * m1(7) - m1(4) * m1(6));\n\n              m2(0, 1) = -det * (m1(1) * m1(8) - m1(2) * m1(7));\n              m2(1, 1) =  det * (m1(0) * m1(8) - m1(2) * m1(6));\n              m2(2, 1) = -det * (m1(0) * m1(7) - m1(1) * m1(6));\n\n              m2(0, 2) =  det * (m1(1) * m1(5) - m1(2) * m1(4));\n              m2(1, 2) = -det * (m1(0) * m1(5) - m1(2) * m1(3));\n              m2(2, 2) =  det * (m1(0) * m1(4) - m1(1) * m1(3));\n              return;\n            }\n          }\n      }\n    \n    else\n      {\n        int i, j, k, n;\n        n = m1.Height();\n      \n\n#ifdef CHOL\n        int dots = (n > 200);\n\n        // Cholesky\n      \n        double x;\n        Vector p(n);\n\n        m2 = m1;\n        /*\n          m2.SetSymmetric();\n          if (!m2.Symmetric())\n          cerr << \"m should be symmetric for Cholesky\" << endl;\n        */\n\n        for (i = 1; i <= n; i++)\n          for (j = 1; j < i; j++)\n            m2.Elem(j, i) = m2.Get(i, j);\n      \n        for (i = 1; i <= n; i++)\n          {\n            if (dots && i % 10 == 0)\n              (*mycout) << \".\" << flush;\n\n            for (j = i; j <= n; j++)\n              {\n                x = m2.Get(i, j);\n\n                const double * pik = &m2.Get(i, 1);\n                const double * pjk = &m2.Get(j, 1);\n\n                for (k = i-2; k >= 0; --k, ++pik, ++pjk)\n                  x -= (*pik) * (*pjk);\n\t\t  \n                // for (k = i-1; k >= 1; --k)\n                //   x -= m2.Get(j, k) * m2.Get(i, k);\n\n                if (i == j)\n                  {\n                    if (x <= 0)\n                      {\n                        cerr << \"Matrix indefinite 1\" << endl;\n                        return;\n                      }\n\t\t  \n                    p.Elem(i) = 1 / sqrt(x);\n                  }\n                else\n                  {\n                    m2.Elem(j, i) = x * p.Get(i);\n                  }\n              }\n          }\n\n        for (i = 1; i <= n; i++)\n          m2.Elem(i, i) = 1 / p.Get(i);\n\n        // check: A = L L^t\n\n        //       for (i = 1; i <= n; i++)\n        // \tfor (j = 1; j <= n; j++)\n        // \t  {\n        // \t    x = 0;\n        // \t    for (k = 1; k <= i && k <= j; k++)\n        // \t      x += m2.Get(i, k) * m2.Get(j, k);\n        // \t    (*testout) << \"err \" << i << \",\" << j << \" = \" << (m1.Get(i, j) - x) << endl;\n        // \t  }\n\n\n      \n        // calc L^{-1}, store upper triangle\n      \n        //      DenseMatrix hm(n);\n        //      hm = m2;\n\n        for (i = 1; i <= n; i++)\n          {\n            if (dots && i % 10 == 0)\n              (*mycout) << \"+\" << flush;\n\n            for (j = i; j <= n; j++)\n              {\n                x = 0;\n                if (j == i) x = 1;\n\n                const double * pjk = &m2.Get(j, i);\n                const double * pik = &m2.Get(i, i);\n                for (k = i; k < j; k++, ++pjk, ++pik)\n                  x -= *pik * *pjk;\n\n                //  for (k = i; k < j; k++)\n                //  x -= m2.Get(j, k) * m2.Get(i, k);\n\n                m2.Elem(i, j) = x / m2.Get(j, j);\n              }\n          }\n      \n        //      (*testout) << \"check L^-1\" << endl;\n        //      for (i = 1; i <= n; i++)\n        // \tfor (j = 1; j <= n; j++)\n        // \t  {\n        // \t    x = 0;\n        // \t    for (k = j; k <= i; k++)\n        // \t      x += hm.Get(i, k) * m2.Get(j, k);\n        // \t    (*testout) << \"i, j = \" << i << \",\" << j << \" x = \" << x << endl;\n        // \t  }\n\n\n        // calc A^-1 = L^-T * L^-1\n\n        for (i = 1; i <= n; i++)\n          {\n            if (dots && i % 10 == 0)\n              (*mycout) << \"-\" << flush;\n\n            for (j = 1; j <= i; j++)\n              {\n                x = 0;\n                k = i;\n                if (j > i) k = j;\n\n                const double * pik = &m2.Get(i, k);\n                const double * pjk = &m2.Get(j, k);\n\n                for ( ; k <= n; ++k, ++pik, ++pjk)\n                  x += *pik * *pjk;\n                // for (  ; k <= n; k++)\n                //   x += m2.Get(i, k) * m2.Get(j, k);\n\t      \n                m2.Elem(i, j) = x;\n              }\n          }\n\t  \n        for (i = 1; i <= n; i++)\n          for (j = 1; j < i; j++)\n            m2.Elem(j, i) = m2.Get(i, j);\n      \n        if (dots) (*mycout) << endl;\n#endif\n\n\n\n        // Gauss - Jordan - algorithm\n      \n        int r, hi;\n        double max, hr;\n      \n\n        NgArray<int> p(n);   // pivot-permutation\n        Vector hv(n);\n    \n      \n        m2 = m1;\n\n        /*      \n                if (m2.Symmetric())\n                for (i = 1; i <= n; i++)\n                for (j = 1; j < i; j++)\n                m2.Elem(j, i) = m2.Get(i, j);\n        */\n      \n        // Algorithm of Stoer, Einf. i. d. Num. Math, S 145\n      \n        for (j = 1; j <= n; j++)\n          p.Set(j, j);\n      \n        for (j = 1; j <= n; j++)\n          {\n            // pivot search\n\t  \n            max = fabs(m2.Get(j, j));\n            r = j;\n\t  \n            for (i = j+1; i <= n ;i++)\n              if (fabs (m2.Get(i, j)) > max)\n                {\n                  r = i;\n                  max = fabs (m2.Get(i, j));\n                }\n\t  \n            if (max < 1e-20)\n              {\n                cerr << \"Inverse matrix: matrix singular\" << endl;\n                *testout << \"Inverse matrix: matrix singular\" << endl;\n                return;\n              }\n\t  \n            r = j;\n\t  \n            // exchange rows\n            if (r > j)\n              {\n                for (k = 1; k <= n; k++)\n                  {\n                    hr = m2.Get(j, k);\n                    m2.Elem(j, k) = m2.Get(r, k);\n                    m2.Elem(r, k) = hr;\n                  }\n                hi = p.Get(j);\n                p.Elem(j) = p.Get(r);\n                p.Elem(r) = hi;\n              }\n\t  \n\t  \n            // transformation\n\t  \n            hr = 1 / m2.Get(j, j);\n            for (i = 1; i <= n; i++)\n              m2.Elem(i, j) *= hr;\n            m2.Elem(j, j) = hr;\n\t  \n            for (k = 1; k <= n; k++)\n              if (k != j)\n                {\n                  for (i = 1; i <= n; i++)\n                    if (i != j)\n                      m2.Elem(i, k) -= m2.Elem(i, j) * m2.Elem(j, k);\n                  m2.Elem(j, k) *= -hr;\n                }\n          }\n      \n        // col exchange\n      \n        for (i = 1; i <= n; i++)\n          {\n            for (k = 1; k <= n; k++)\n              hv(p.Get(k)-1) = m2.Get(i, k);\n            for (k = 1; k <= n; k++)\n              m2.Elem(i, k) = hv(k-1);\n          }\n\n\n\n        /*\n          if (m1.Symmetric())\n          for (i = 1; i <= n; i++)\n          for (j = 1; j < i; j++)\n\t  m1.Elem(j, i) = m1.Get(i, j);\n\n          m2 = 0;\n    \n          for (i = 1; i <= n; i++)\n          m2.Elem(i, i) = 1;\n      \n          for (i = 1; i <= n; i++)\n          {\n          //\t(*mycout) << '.' << flush;\n          q = m1.Get(i, i);\n          for (k = 1; k <= n; k++)\n          {\n          m1.Elem(i, k) /= q;\n          m2.Elem(i, k) /= q;\n          }\n        \n          for (j = i+1; j <= n; j++)\n          {\n          q = m1.Elem(j, i);\n\n          double * m1pi = &m1.Elem(i, i);\n          double * m1pj = &m1.Elem(j, i);\n\n          for (k = n; k >= i; --k, ++m1pi, ++m1pj)\n          *m1pj -= q * (*m1pi);\n\n          double * m2pi = &m2.Elem(i, 1);\n          double * m2pj = &m2.Elem(j, 1);\n\n          for (k = i; k > 0; --k, ++m2pi, ++m2pj)\n          *m2pj -= q * (*m2pi);\n\n          //        for (k = 1; k <= n; k++)  \n          //          {\n          //          m1.Elem(j, k) -= q * m1.Elem(i, k);\n          //          m2.Elem(j, k) -= q * m2.Elem(i, k);\n          //          }\n\t  \n          }\n          }  \n            \n          for (i = n; i >= 1; i--)\n          {\n          //\t(*mycout) << \"+\" << flush;\n          for (j = 1; j < i; j++)\n\t  {\n          q = m1.Elem(j, i);\n\n          double * m2pi = &m2.Elem(i, 1);\n          double * m2pj = &m2.Elem(j, 1);\n\n          for (k = n; k > 0; --k, ++m2pi, ++m2pj)\n          *m2pj -= q * (*m2pi);\t    \n\n\t    \n          //\t    for (k = 1; k <= n; k++)\n          //\t      {\n          //\t\tm1.Elem(j, k) -= q * m1.Elem(i, k);\n          //\t\tm2.Elem(j, k) -= q * m2.Elem(i, k);\n          //\t      }    \n\t  }         \n          }\n\n          if (m2.Symmetric())\n          {\n          for (i = 1; i <= n; i++)\n\t  for (j = 1; j < i; j++)\n          m2.Elem(i, j) = m2.Elem(j, i);\n          }\n        */\n      }\n  }\n\n\n  void CalcAAt (const DenseMatrix & a, DenseMatrix & m2)\n  {\n    int n1 = a.Height();\n    int n2 = a.Width();\n    int i, j, k;\n    double sum;\n    const double *p, *q, *p0;\n\n    if (m2.Height() != n1 || m2.Width() != n1)\n      {\n        (*myerr) << \"CalcAAt: sizes don't fit\" << endl;\n        return;\n      }\n\n    for (i = 1; i <= n1; i++)\n      {\n        sum = 0;\n        p = &a.ConstElem(i, 1);\n        for (k = 1; k <= n2; k++)\n          {\n            sum += *p * *p;\n            p++;\n          }\n        m2.Set(i, i, sum);\n\n        p0 = &a.ConstElem(i, 1);\n        q = a.data;\n        for (j = 1; j < i; j++)\n          {\n            sum = 0;\n            p = p0;\n\n            for (k = 1; k <= n2; k++)\n              {\n                sum += *p * *q;\n                p++;\n                q++;\n              }\n            m2.Set(i, j, sum);\n            m2.Set(j, i, sum);\n          }\n      }\n  }\n\n\n\n  void CalcAtA (const DenseMatrix & a, DenseMatrix & m2)\n  {\n    int n1 = a.Height();\n    int n2 = a.Width();\n    int i, j, k;\n    double sum;\n\n    if (m2.Height() != n2 || m2.Width() != n2)\n      {\n        (*myerr) << \"CalcAtA: sizes don't fit\" << endl;\n        return;\n      }\n\n    for (i = 1; i <= n2; i++)\n      for (j = 1; j <= n2; j++)\n        {\n          sum = 0;\n          for (k = 1; k <= n1; k++)\n            sum += a.Get(k, i) * a.Get(k, j);\n          m2.Elem(i, j) = sum;\n        }\n  }\n\n\n\n  void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2)\n  {\n    int n1 = a.Height();\n    int n2 = a.Width();\n    int n3 = b.Height();\n    int i, j, k;\n    double sum;\n\n    if (m2.Height() != n1 || m2.Width() != n3 || b.Width() != n2)\n      {\n        (*myerr) << \"CalcABt: sizes don't fit\" << endl;\n        return;\n      }\n\n    double * pm2 = &m2.Elem(1, 1);\n    const double * pa1 = &a.Get(1, 1);\n\n    for (i = 1; i <= n1; i++)\n      {\n        const double * pb = &b.Get(1, 1);\n        for (j = 1; j <= n3; j++)\n          {\n            sum = 0;\n            const double * pa = pa1;\n\t  \n            for (k = 1; k <= n2; k++)\n              {\n                sum += *pa * *pb;\n                pa++; pb++;\n              }\n\t  \n            *pm2 = sum;\n            pm2++;\n          }\n        pa1 += n2;\n      }\n  }\n\n\n  void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2)\n  {\n    int n1 = a.Height();\n    int n2 = a.Width();\n    int n3 = b.Width();\n    int i, j, k;\n\n    if (m2.Height() != n2 || m2.Width() != n3 || b.Height() != n1)\n      {\n        (*myerr) << \"CalcAtB: sizes don't fit\" << endl;\n        return;\n      }\n\n    for (i = 1; i <= n2 * n3; i++)\n      m2.data[i-1] = 0;\n\n    for (i = 1; i <= n1; i++)\n      for (j = 1; j <= n2; j++)\n        {\n          const double va = a.Get(i, j);\n          double * pm2 = &m2.Elem(j, 1);\n          const double * pb = &b.Get(i, 1);\n\n          for (k = 1; k <= n3; ++k, ++pm2, ++pb)\n            *pm2 += va * *pb;\n          //\tfor (k = 1; k <= n3; k++)\n          //\t  m2.Elem(j, k) += va * b.Get(i, k);\n        }\n    /*\n      for (i = 1; i <= n2; i++)\n      for (j = 1; j <= n3; j++)\n      {\n      sum = 0;\n      for (k = 1; k <= n1; k++)\n      sum += a.Get(k, i) * b.Get(k, j);\n      m2.Elem(i, j) = sum;\n      }\n    */\n  }\n\n\n\n\n\n\n\n  DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2)\n  {\n    DenseMatrix temp (m1.Height(), m2.Width());\n\n    if (m1.Width() != m2.Height())\n      {\n        (*myerr) << \"DenseMatrix :: operator*: Matrix Size does not fit\" << endl;\n      }\n    else if (temp.Height() != m1.Height())\n      {\n        (*myerr) << \"DenseMatrix :: operator*: temp not allocated\" << endl;\n      }\n    else\n      {\n        Mult (m1, m2, temp);\n      }\n    return temp;\n  }\n\n\n  void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3)\n  {\n    double sum;\n    double *p1, *p1s, *p1sn, *p1snn, *p2, *p2s, *p2sn, *p3;\n\n    if (m1.Width() != m2.Height() || m1.Height() != m3.Height() ||\n        m2.Width() != m3.Width() )\n      {\n        (*myerr) << \"DenseMatrix :: Mult: Matrix Size does not fit\" << endl;\n        (*myerr) << \"m1: \" << m1.Height() << \" x \" << m1.Width() << endl;\n        (*myerr) << \"m2: \" << m2.Height() << \" x \" << m2.Width() << endl;\n        (*myerr) << \"m3: \" << m3.Height() << \" x \" << m3.Width() << endl;\n        return;\n      }\n    /*\n      else if (m1.Symmetric() || m2.Symmetric() || m3.Symmetric())\n      {\n      (*myerr) << \"DenseMatrix :: Mult: not implemented for symmetric matrices\" << endl;\n      return;\n      }\n    */\n    else\n      {\n        //      int i, j, k;\n        int n1 = m1.Height();\n        int n2 = m2.Width();\n        int n3 = m1.Width();\n\n        /*\n          for (i = n1 * n2-1; i >= 0; --i)\n          m3.data[i] = 0;\n\n          const double * pm1 = &m1.Get(1, 1);\n          for (i = 1; i <= n1; i++)\n          {\n\t  const double * pm2 = &m2.Get(1, 1);\n\t  double * pm3i = &m3.Elem(i, 1);\n\n\t  for (j = 1; j <= n3; j++)\n          {\n          const double vm1 = *pm1;\n          ++pm1;\n          //\t      const double vm1 = m1.Get(i, j);\n          double * pm3 = pm3i;\n          //\t      const double * pm2 = &m2.Get(j, 1);\n\n          for (k = 0; k < n2; k++)\n          {\n          *pm3 += vm1 * *pm2;\n          ++pm2;\n          ++pm3;\n          }\n\n          //\t    for (k = 1; k <= n2; k++)\n          //\t      m3.Elem(i, k) += m1.Get(i, j) * m2.Get(j, k);\n          }\n          }\n\t*/\n\n        /*\n          for (i = 1; i <= n1; i++)\n          for (j = 1; j <= n2; j++)\n\t  {\n          sum = 0;\n          for (k = 1; k <= n3; k++)\n          sum += m1.Get(i, k) * m2.Get(k, j);\n          m3.Set(i, j, sum);\n\t  }\n        */\n\n\n        /*\n          for (i = 1; i <= n1; i++)\n          {\n\t  const double pm1i = &m1.Get(i, 1);\n\t  const double pm2j = &m2.Get(1, 1);\n\n\t  for (j = 1; j <= n2; j++)\n          {\n          double sum = 0;\n          const double * pm1 = pm1i;\n          const double * pm2 = pm2j;\n          pm2j++;\n\n          for (k = 1; k <= n3; k++)\n          {\n          sum += *pm1 * *pm2;\n          ++pm1;\n          pm2 += n2;\n          }\n\t      \n          m3.Set (i, j, sum);\n          }\n          }\n\t*/\n\n\n        p3 = m3.data;\n        p1s = m1.data;\n        p2sn = m2.data + n2;\n        p1snn = p1s + n1 * n3;\n\n        while (p1s != p1snn)\n          {\n            p1sn = p1s + n3;\n            p2s = m2.data;\n\t  \n            while (p2s != p2sn)\n              {\n                sum = 0;\n                p1 = p1s;\n                p2 = p2s;\n                p2s++;\n\n                while (p1 != p1sn)\n                  {\n                    sum += *p1 * *p2;\n                    p1++;\n                    p2 += n2;\n                  }\n                *p3++ = sum;\n              }\n            p1s = p1sn;\n          }\n      }\n  }  \n\n\n\n  DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2)\n  {\n    DenseMatrix temp (m1.Height(), m1.Width());\n    int i, j;\n\n    if (m1.Width() != m2.Width() || m1.Height() != m2.Height())\n      {\n        (*myerr) << \"BaseMatrix :: operator+: Matrix Size does not fit\" << endl;\n      }\n    else if (temp.Height() != m1.Height())\n      {\n        (*myerr) << \"BaseMatrix :: operator+: temp not allocated\" << endl;\n      }\n    else\n      {\n        for (i = 1; i <= m1.Height(); i++)\n          for (j = 1; j <= m1.Width(); j++)\n            {\n              temp.Set(i, j, m1.Get(i, j) + m2.Get(i, j));\n            }\n      }\n    return temp;\n  }\n\n\n\n\n  void Transpose (const DenseMatrix & m1, DenseMatrix & m2)\n  {\n    int w = m1.Width();\n    int h = m1.Height();\n    int i, j;\n\n    m2.SetSize (w, h);\n\n    double * pm2 = &m2.Elem(1, 1);\n    for (j = 1; j <= w; j++)\n      {\n        const double * pm1 = &m1.Get(1, j);\n        for (i = 1; i <= h; i++)\n          {\n            *pm2 = *pm1;\n            pm2 ++;\n            pm1 += w;\n          }\n      }\n  }\n\n\n  /*\n    void DenseMatrix :: Mult (const Vector & v, Vector & prod) const\n    {\n    double sum, val;\n    const double * mp, * sp;\n    double * dp;\n    // const Vector & v = bv.CastToVector();\n    // Vector & prod = bprod.CastToVector();\n  \n\n    int n = Height();\n    int m = Width();\n\n    if (prod.Size() != n)\n    prod.SetSize (n);\n\n    #ifdef DEVELOP\n    if (!n) \n    {\n    cout << \"DenseMatrix::Mult  mheight = 0\" << endl;\n    }\n    if (!m) \n    {\n    cout << \"DenseMatrix::Mult mwidth = 0\" << endl;\n    }\n\n    if (m != v.Size())\n    {\n    (*myerr) << \"\\nMatrix and Vector don't fit\" << endl;\n    }\n    else if (Height() != prod.Size())\n    {\n    (*myerr) << \"Base_Matrix::operator*(Vector): prod vector not ok\" << endl;\n    }\n    else\n    #endif\n    {\n    if (Symmetric())\n    {\n    int i, j;\n\n\n    for (i = 1; i <= n; i++)\n    {\n    sp = &v.Get(1);\n    dp = &prod.Elem(1);\n    mp = &Get(i, 1);\n\n    val = v.Get(i);\n    sum = Get(i, i) * val;\n\n    for (j = 1; j < i; ++j, ++mp, ++sp, ++dp)\n    {\n    sum += *mp * *sp;\n    *dp += val * *mp;\n    }\n\n    prod.Elem(i) = sum;\n    }\n    }\n    else\n    {\n    mp = data;\n    dp = &prod.Elem(1);\n    for (int i = 1; i <= n; i++)\n    {\n    sum = 0;\n    sp = &v.Get(1);\n\t      \n    for (int j = 1; j <= m; j++)\n    {\n    //        sum += Get(i,j) * v.Get(j);\n    sum += *mp * *sp;\n    mp++;\n    sp++;\n    }\n\t      \n    //      prod.Set (i, sum);\n    *dp = sum;\n    dp++;\n    }\n    }\n    }\n    }\n  */\n\n  void DenseMatrix :: MultTrans (const Vector & v, Vector & prod) const\n  {\n    // const Vector & v = (const Vector&)bv; // .CastToVector();\n    // Vector & prod = (Vector & )bprod;     // .CastToVector();\n\n    /*\n      if (Height() != v.Size())\n      {\n      (*myerr) << \"\\nMatrix and Vector don't fit\" << endl;\n      }\n      else if (Width() != prod.Size())\n      {\n      (*myerr) << \"Base_Matrix::operator*(Vector): prod vector not ok\" << endl;\n      }\n      else\n    */\n    {\n      int i, j;\n      int w = Width(), h = Height();\n      if (prod.Size() != w)\n\tprod.SetSize (w);\n\n      const double * pmat = &Get(1, 1);\n      const double * pv = &v(0);\n\n      prod = 0;\n\n      for (i = 1; i <= h; i++)\n\t{\n\t  double val = *pv;\n\t  ++pv;\n\n\t  double * pprod = &prod(0);\n\n\t  for (j = w-1; j >= 0; --j, ++pmat, ++pprod)\n\t    {\n\t      *pprod += val * *pmat;\n\t    }\n\t}\n\t\n      /*\n        double sum;\n\n        for (i = 1; i <= Width(); i++)\n\t{\n        sum = 0;\n\t  \n        for (int j = 1; j <= Height(); j++)\n        sum += Get(j, i) * v.Get(j);\n\t  \n        prod.Set (i, sum);\n\t}\n      */\n    }\n  }\n\n\n  void DenseMatrix :: Residuum (const Vector & x, const Vector & b,\n                                Vector & res) const\n  {\n    double sum;\n    //   const Vector & x = bx.CastToVector();\n    //  const Vector & b = bb.CastToVector();\n    //  Vector & res = bres.CastToVector();\n\n    res.SetSize (Height());\n\n    if (Width() != x.Size() || Height() != b.Size())\n      {\n        (*myerr) << \"\\nMatrix and Vector don't fit\" << endl;\n      }\n    else if (Height() != res.Size())\n      {\n        (*myerr) << \"Base_Matrix::operator*(Vector): prod vector not ok\" << endl;\n      }\n    else\n      {\n        int h = Height(); \n        int w = Width();\n        const double * mp = &Get(1, 1);\n\n        for (int i = 1; i <= h; i++)\n          {\n            sum = b(i-1);\n            const double * xp = &x(0);\n\n            for (int j = 1; j <= w; ++j, ++mp, ++xp)\n              sum -= *mp * *xp;\n\t  \n            res(i-1) = sum;\n          }\n      }\n  }\n\n#ifdef ABC\n  double DenseMatrix :: EvaluateBilinearform (const Vector & hx) const\n  {\n    double sum = 0, hsum;\n    // const Vector & hx = x.CastToVector();\n    int i, j;\n\n    if (Width() != hx.Size() || Height() != hx.Size())\n      {\n        (*myerr) << \"Matrix::EvaluateBilinearForm: sizes don't fit\" << endl;\n      }\n    else\n      {\n        for (i = 1; i <= Height(); i++)\n          {\n            hsum = 0;\n            for (j = 1; j <= Height(); j++)\n              {\n                hsum += Get(i, j) * hx.Get(j);\n              }\n            sum += hsum * hx.Get(i);\n          }\n      }\n\n    //  testout << \"sum = \" << sum << endl;\n    return sum;\n  }\n\n\n  void DenseMatrix :: MultElementMatrix (const NgArray<int> & pnum, \n                                         const Vector & hx, Vector & hy)\n  {\n    int i, j;\n    //  const Vector & hx = x.CastToVector();\n    //  Vector & hy = y.CastToVector();\n\n    if (Symmetric())\n      {\n        for (i = 1; i <= Height(); i++)\n          {\n            for (j = 1; j < i; j++)\n              {\n                hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j));\n                hy.Elem(pnum.Get(j)) += Get(i, j) * hx.Get(pnum.Get(i));\n              }\n            hy.Elem(pnum.Get(j)) += Get(i, i) * hx.Get(pnum.Get(i));\t\n          }\n      }\n    else\n      for (i = 1; i <= Height(); i++)\n        for (j = 1; j <= Width(); j++)\n          hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j));\n    \n  }\n  \n  void DenseMatrix :: MultTransElementMatrix (const NgArray<int> & pnum, \n                                              const Vector & hx, Vector & hy)\n  {\n    int i, j;\n    //  const Vector & hx = x.CastToVector();\n    //  Vector & hy = y.CastToVector();\n\n    if (Symmetric())\n      MultElementMatrix (pnum, hx, hy);\n    else\n      for (i = 1; i <= Height(); i++)\n        for (j = 1; j <= Width(); j++)\n          hy.Elem(pnum.Get(i)) += Get(j, i) * hx.Get(pnum.Get(j));\n  }\n#endif\n\n\n  void DenseMatrix :: Solve (const Vector & v, Vector & sol) const\n  {\n    DenseMatrix temp (*this);\n    temp.SolveDestroy (v, sol);\n  }\n\n\n  void DenseMatrix :: SolveDestroy (const Vector & v, Vector & sol)\n  {\n    double q;\n\n    if (Width() != Height())\n      {\n        (*myerr) << \"SolveDestroy: Matrix not square\";\n        return;\n      }\n    if (Width() != v.Size())\n      {\n        (*myerr) << \"SolveDestroy: Matrix and Vector don't fit\";\n        return;\n      }\n\n    sol = v;\n    if (Height() != sol.Size())\n      {\n        (*myerr) << \"SolveDestroy: Solution Vector not ok\";\n        return;\n      }\n\n\n    if (0 /* Symmetric() */)\n      {\n      \n        // Cholesky factorization\n\n        int i, j, k, n;\n        n = Height();\n      \n        // Cholesky\n      \n        double x;\n        Vector p(n);\n\n        for (i = 1; i <= n; i++)\n          for (j = 1; j < i; j++)\n            Elem(j, i) = Get(i, j);\n      \n        for (i = 1; i <= n; i++)\n          {\n            // (*mycout) << \".\" << flush;\n            for (j = i; j <= n; j++)\n              {\n                x = Get(i, j);\n\n                const double * pik = &Get(i, 1);\n                const double * pjk = &Get(j, 1);\n\n                for (k = i-2; k >= 0; --k, ++pik, ++pjk)\n                  x -= (*pik) * (*pjk);\n\t\t  \n                // for (k = i-1; k >= 1; --k)\n                //   x -= Get(j, k) * Get(i, k);\n\n                if (i == j)\n                  {\n                    if (x <= 0)\n                      {\n                        cerr << \"Matrix indefinite\" << endl;\n                        return;\n                      }\n\t\t  \n                    p(i-1) = 1 / sqrt(x);\n                  }\n                else\n                  {\n                    Elem(j, i) = x * p(i-1);\n                  }\n              }\n          }\n\n        for (int i = 1; i <= n; i++)\n          Elem(i, i) = 1 / p(i-1);\n\n        // A = L L^t \n        // L stored in left-lower triangle\n\n\n        sol = v;\n\n        // Solve L sol = sol\n\n        for (int i = 1; i <= n; i++)\n          {\n            double val = sol(i-1);\n\n            const double * pij = &Get(i, 1);\n            const double * solj = &sol(0);\n\n            for (int j = 1; j < i; j++, ++pij, ++solj)\n              val -= *pij * *solj;\n            //\t  for (j = 1; j < i; j++)\n            //\t    val -= Get(i, j) * sol.Get(j);\n\n            sol(i-1) = val / Get(i, i);\n          }\n\n        // Solve L^t sol = sol\n\n        for (int i = n; i >= 1; i--)\n          {\n            double val = sol(i-1) / Get(i, i);\n            sol(i-1) = val;\n\n            double * solj = &sol(0);\n            const double * pij = &Get(i, 1);\n\n            for (j = 1; j < i; ++j, ++pij, ++solj)\n              *solj -= val * *pij;\n            //\t  for (j = 1; j < i; j++)\n            //\t    sol.Elem(j) -= Get(i, j) * val;\n          }\n\n\n      }\n    else\n      {\n        //      (*mycout) << \"gauss\" << endl;\n        int n = Height();\n        for (int i = 1; i <= n; i++)\n          {\n            for (int j = i+1; j <= n; j++)\n              {\n                q = Get(j,i) / Get(i,i);\n                if (q)\n                  {\n                    const double * pik = &Get(i, i+1);\n                    double * pjk = &Elem(j, i+1);\n\n                    for (int k = i+1; k <= n; ++k, ++pik, ++pjk)\n                      *pjk -= q * *pik;\n\t\t  \n                    //  for (k = i+1; k <= Height(); k++)\n                    //\tElem(j, k) -= q * Get(i,k);\n\n\n                    sol(j-1) -= q * sol(i-1);\n                  }\n              }\n          }\n      \n        for (int i = n; i >= 1; i--)\n          {\n            q = sol(i-1);\n            for (int j = i+1; j <= n; j++)\n\t      q -= Get(i,j) * sol(j-1);\n\n            sol(i-1) = q / Get(i,i);\n          }\n      }\n  }\n\n\n  /*\n    BaseMatrix * DenseMatrix :: Copy () const\n    {\n    return new DenseMatrix (*this);\n    }\n  */\n\n\n\n\n  ostream & operator<< (ostream & ost, const DenseMatrix & m)\n  {\n    for (int i = 0; i < m.Height(); i++)\n      {\n        for (int j = 0; j < m.Width(); j++)\n          ost << m.Get(i+1,j+1) << \" \";\n        ost << endl;\n      }\n    return ost;\n  }\n\n  \n\n}\n"
  },
  {
    "path": "libsrc/linalg/densemat.hpp",
    "content": "#ifndef FILE_DENSEMAT\n#define FILE_DENSEMAT\n\n/**************************************************************************/\n/* File:   densemat.hpp                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Oct. 94                                                    */\n/**************************************************************************/\n\n/** \n    Data type dense matrix\n*/\n\n#include <mydefs.hpp>\n#include \"vector.hpp\"\n\nnamespace netgen\n{\nclass DenseMatrix\n{\nprotected:\n  int height;\n  int width;\n  double * data;\n\npublic:\n  ///\n  DLL_HEADER DenseMatrix ();\n  ///\n  DLL_HEADER DenseMatrix (int h, int w = 0);\n  ///\n  DLL_HEADER DenseMatrix (const DenseMatrix & m2);\n  ///\n  DLL_HEADER ~DenseMatrix ();\n\n  ///\n  DLL_HEADER void SetSize (int h, int w = 0);\n\n  int Height() const { return height; }\n  int Width() const {return width; }\n\n  double & operator() (int i, int j) { return data[i*width+j]; }\n  double operator() (int i, int j) const { return data[i*width+j]; }\n  double & operator() (int i) { return data[i]; }\n  double operator() (int i) const { return data[i]; }\n\n  ///\n  DLL_HEADER DenseMatrix & operator= (const DenseMatrix & m2);\n  ///\n  DLL_HEADER DenseMatrix & operator+= (const DenseMatrix & m2);\n  ///\n  DLL_HEADER DenseMatrix & operator-= (const DenseMatrix & m2);\n\n  ///\n  DLL_HEADER DenseMatrix & operator= (double v);\n  ///\n  DLL_HEADER DenseMatrix & operator*= (double v);\n\n  ///\n  DLL_HEADER void Mult (const FlatVector & v, FlatVector & prod) const\n  {\n    double sum;\n    const double * mp, * sp;\n    double * dp;\n    \n#ifdef DEBUG\n    if (prod.Size() != height)\n      {\n\t(*myerr) << \"Mult: wrong vector size \" << endl;\n      }\n    if (!height) \n      {\n\tcout << \"DenseMatrix::Mult height = 0\" << endl;\n      }\n    if (!width) \n      {\n\tcout << \"DenseMatrix::Mult width = 0\" << endl;\n      }\n    \n    if (width != v.Size())\n      {\n\t(*myerr) << \"\\nMatrix and Vector don't fit\" << endl;\n      }\n    else if (Height() != prod.Size())\n      {\n\t(*myerr) << \"Base_Matrix::operator*(Vector): prod vector not ok\" << endl;\n      }\n    else\n#endif\n      {      \n\tmp = data;\n\tdp = &prod(0);\n        for (int i = 0; i < height; i++)\n\t  {\n\t    sum = 0;\n\t    sp = &v(0);\n\t    \n\t    for (int j = 0; j < width; j++)\n\t      {\n\t\t//        sum += Get(i,j) * v.Get(j);\n\t\tsum += *mp * *sp;\n\t\tmp++;\n\t\tsp++;\n\t      }\n\t    \n\t    *dp = sum;\n\t    dp++;\n\t  }\n      }\n  }\n\n  ///\n  DLL_HEADER void MultTrans (const Vector & v, Vector & prod) const;\n  ///\n  DLL_HEADER void Residuum (const Vector & x, const Vector & b, Vector & res) const;\n  ///\n  DLL_HEADER double Det () const;\n\n  ///\n  friend DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2);\n  ///\n  friend DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2);\n\n  /// \n  friend void Transpose (const DenseMatrix & m1, DenseMatrix & m2);\n  ///\n  friend void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3);\n  ///\n//  friend void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2);\n  ///\n  friend void CalcAAt (const DenseMatrix & a, DenseMatrix & m2);\n  ///\n//  friend void CalcAtA (const DenseMatrix & a, DenseMatrix & m2);\n  ///\n  friend void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2);\n  ///\n  friend void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2);\n  ///\n  DLL_HEADER void Solve (const Vector & b, Vector & x) const;\n  ///\n  void SolveDestroy (const Vector & b, Vector & x);\n  ///\n  const double & Get(int i, int j) const { return data[(i-1)*width+j-1]; }\n  ///\n  const double & Get(int i) const { return data[i-1]; }\n  ///\n  void Set(int i, int j, double v) { data[(i-1)*width+j-1] = v; }\n  ///\n  double & Elem(int i, int j) { return data[(i-1)*width+j-1]; }\n  ///\n  const double & ConstElem(int i, int j) const { return data[(i-1)*width+j-1]; }\n};\n\n\nextern ostream & operator<< (ostream & ost, const DenseMatrix & m);\n\n\n\ntemplate <int WIDTH, typename T = double>\nclass MatrixFixWidth\n{\nprotected:\n  int height;\n  T * __restrict data;\n  bool ownmem;\npublic:\n  ///\n  MatrixFixWidth () \n  { height = 0; data = 0; ownmem = false; }\n  ///\n  MatrixFixWidth (int h)\n  { height = h; data = new T[WIDTH*height]; ownmem = true; }\n  /// \n  MatrixFixWidth (int h, T * adata)\n  { height = h; data = adata; ownmem = false; }\n  ///\n  MatrixFixWidth (const MatrixFixWidth & m2)\n    : height(m2.height), ownmem(true)\n  {\n    data = new T[height*WIDTH];\n    for (int i = 0; i < WIDTH*height; i++)\n      data[i] = m2.data[i];\n  }\n  // : height(m2.height), data(m2.data), ownmem(false)\n  //{ ; } \n  ///\n  ~MatrixFixWidth ()\n  { if (ownmem) delete [] data; }\n\n  void SetSize (int h)\n  {\n    if (h != height)\n      {\n\tif (ownmem) delete data;\n\theight = h;\n\tdata = new T[WIDTH*height]; \n\townmem = true;\n      }\n  }\n\n  ///\n  int Height() const { return height; }\n\n  ///\n  int Width() const { return WIDTH; }\n  MatrixFixWidth & operator= (const MatrixFixWidth & m2)\n  {\n    for (int i = 0; i < height*WIDTH; i++)\n      data[i] = m2.data[i];\n  }\n  ///\n  MatrixFixWidth & operator= (T v)\n  {\n    for (int i = 0; i < height*WIDTH; i++)\n      data[i] = v; \n    return *this;\n  }\n\n  /*  \n  ///\n  void Mult (const FlatVector & v, FlatVector & prod) const\n  {\n    T sum;\n    const T * mp, * sp;\n    T * dp;\n\n    mp = data;\n    dp = &prod[0];\n    for (int i = 0; i < height; i++)\n      {\n\tsum = 0;\n\tsp = &v[0];\n\t\n\tfor (int j = 0; j < WIDTH; j++)\n\t  {\n\t    sum += *mp * *sp;\n\t    mp++;\n\t    sp++;\n\t  }\n\t    \n\t*dp = sum;\n\tdp++;\n      }\n  }\n  */\n\n  T & operator() (int i, int j)\n  { return data[i*WIDTH+j]; }\n\n  const T & operator() (int i, int j) const\n  { return data[i*WIDTH+j]; }\n\n\n  MatrixFixWidth & operator*= (T v)\n  {\n    if (data)\n      for (int i = 0; i < height*WIDTH; i++)\n        data[i] *= v;\n    return *this;\n  }\n\n\n\n  const T & Get(int i, int j) const { return data[(i-1)*WIDTH+j-1]; }\n  ///\n  const T & Get(int i) const { return data[i-1]; }\n  ///\n  void Set(int i, int j, T v) { data[(i-1)*WIDTH+j-1] = v; }\n  ///\n  T & Elem(int i, int j) { return data[(i-1)*WIDTH+j-1]; }\n  ///\n  const T & ConstElem(int i, int j) const { return data[(i-1)*WIDTH+j-1]; }\n};\n\n\ntemplate <int WIDTH>\nclass MatrixFixWidth<WIDTH,double>\n{\nprotected:\n  int height;\n  double * data;\n  bool ownmem;\npublic:\n  ///\n  MatrixFixWidth () \n  { height = 0; data = 0; ownmem = false; }\n  ///\n  MatrixFixWidth (int h)\n  { height = h; data = new double[WIDTH*height]; ownmem = true; }\n  \n  MatrixFixWidth (const MatrixFixWidth & m2)\n    : height(m2.height), ownmem(true)\n  {\n    data = new double[height*WIDTH];\n    for (int i = 0; i < WIDTH*height; i++)\n      data[i] = m2.data[i];\n  }\n\n  /// \n  MatrixFixWidth (int h, double * adata)\n  { height = h; data = adata; ownmem = false; }\n  ///\n  ~MatrixFixWidth ()\n  { if (ownmem) delete [] data; }\n\n  void SetSize (int h)\n  {\n    if (h != height)\n      {\n\tif (ownmem) delete data;\n\theight = h;\n\tdata = new double[WIDTH*height]; \n\townmem = true;\n      }\n  }\n\n  ///\n  int Height() const { return height; }\n\n  ///\n  int Width() const { return WIDTH; }\n\n  ///\n  MatrixFixWidth & operator= (double v)\n  {\n    for (int i = 0; i < height*WIDTH; i++)\n      data[i] = v; \n    return *this;\n  }\n\n  ///\n  void Mult (const FlatVector & v, FlatVector & prod) const\n  {\n    double sum;\n    const double * mp, * sp;\n    double * dp;\n\n    /*    \n    if (prod.Size() != height)\n      {\n\tcerr << \"MatrixFixWidth::Mult: wrong vector size \" << endl;\n\tassert (1);\n      }\n    */    \n\n    mp = data;\n    dp = &prod[0];\n    for (int i = 0; i < height; i++)\n      {\n\tsum = 0;\n\tsp = &v[0];\n\t\n\tfor (int j = 0; j < WIDTH; j++)\n\t  {\n\t    sum += *mp * *sp;\n\t    mp++;\n\t    sp++;\n\t  }\n\t    \n\t*dp = sum;\n\tdp++;\n      }\n  }\n\n  double & operator() (int i, int j)\n  { return data[i*WIDTH+j]; }\n\n  const double & operator() (int i, int j) const\n  { return data[i*WIDTH+j]; }\n\n\n  MatrixFixWidth & operator*= (double v)\n  {\n    if (data)\n      for (int i = 0; i < height*WIDTH; i++)\n        data[i] *= v;\n    return *this;\n  }\n\n\n\n  const double & Get(int i, int j) const { return data[(i-1)*WIDTH+j-1]; }\n  ///\n  const double & Get(int i) const { return data[i-1]; }\n  ///\n  void Set(int i, int j, double v) { data[(i-1)*WIDTH+j-1] = v; }\n  ///\n  double & Elem(int i, int j) { return data[(i-1)*WIDTH+j-1]; }\n  ///\n  const double & ConstElem(int i, int j) const { return data[(i-1)*WIDTH+j-1]; }\n};\n\n\n\n\n\ntemplate <int WIDTH>\nextern ostream & operator<< (ostream & ost, const MatrixFixWidth<WIDTH> & m)\n{\n  for (int i = 0; i < m.Height(); i++)\n    {\n      for (int j = 0; j < m.Width(); j++)\n\tost << m.Get(i+1,j+1) << \" \";\n      ost << endl;\n    }\n  return ost;\n};\n\n\nextern DLL_HEADER void CalcAtA (const DenseMatrix & a, DenseMatrix & m2);\nextern DLL_HEADER void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2);\n\n} // namespace netgen\n#endif\n"
  },
  {
    "path": "libsrc/linalg/linalg.hpp",
    "content": "#ifndef FILE_LINALG\n#define FILE_LINALG\n\n/* *************************************************************************/\n/* File:   linalg.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Oct. 94                                                    */\n/* *************************************************************************/\n\n/* \n\n   Data types for basic linear algebra\n   \n   The basic concepts include the data types \n   \n    Vector\n    SparseMatrix\n    DenseMatrix\n\n*/\n\n\n#include \"../include/myadt.hpp\"\n#include \"vector.hpp\"\n#include \"densemat.hpp\"\n#include \"polynomial.hpp\"\n#endif\n\n\n"
  },
  {
    "path": "libsrc/linalg/linopt.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include \"opti.hpp\"\n\nnamespace netgen\n{\n\nvoid LinearOptimize (const DenseMatrix & a, const Vector & b, \n    const Vector & c, Vector & x)\n    \n  {\n  int i1, i2, i3, j;\n  DenseMatrix m(3), inv(3);\n  Vector rs(3), hx(3), res(a.Height()), res2(3);\n  double f, fmin;\n  int nrest;\n    \n  if (a.Width() != 3)\n    {\n    cerr << \"LinearOptimize only implemented for 3 unknowns\" << endl;\n    return;\n    }\n    \n  fmin = 1e10;\n  x = 0;\n  nrest = a.Height();\n  for (i1 = 1; i1 <= nrest; i1++)\n    for (i2 = i1 + 1; i2 <= nrest; i2++)\n      for (i3 = i2 + 1; i3 <= nrest; i3++)\n        {\n        for (j = 1; j <= 3; j++)\n          {\n          m.Elem(1, j) = a.Get(i1, j);\n          m.Elem(2, j) = a.Get(i2, j);\n          m.Elem(3, j) = a.Get(i3, j);\n          }\n          \n        rs(0) = b(i1-1);\n        rs(1) = b(i2-1);\n        rs(2) = b(i3-1);\n        \n        if (fabs (m.Det()) < 1e-12) continue;\n        \n        CalcInverse (m, inv);\n        inv.Mult (rs, hx);\n        \n        a.Residuum (hx, b, res);\n//        m.Residuum (hx, rs, res2);\n        f = c * hx;\n\n/*        \n        testout -> precision(12);\n        (*testout) << \"i = (\" << i1 << \",\" << i2 << \",\" << i3 \n           << \"), f = \" << f << \" x = \" << x << \" res = \" << res \n           <<  \" resmin = \" << res.Min() \n           << \" res2 = \" << res2 << \" prod = \" << prod << endl;\n*/\n\n\t\n\tdouble rmin = res(0);\n\tfor (int hi = 1; hi < res.Size(); hi++)\n\t  if (res(hi) < rmin) rmin = res(hi);\n        \n        if ( (f < fmin) && rmin >= -1e-8)\n          {\n          fmin = f;\n          x = hx;\n          }\n        }\n  }\n}\n"
  },
  {
    "path": "libsrc/linalg/linsearch.cpp",
    "content": "/***************************************************************************/\n/*                                                                         */\n/* Problem:        Liniensuche                                             */\n/*                                                                         */\n/* Programmautor:  Joachim Schöberl                                        */\n/* Matrikelnummer: 9155284                                                 */\n/*                                                                         */\n/* Algorithmus nach:                                                       */\n/*                                                                         */\n/*   Optimierung I, Gfrerer, WS94/95                                       */\n/*   Algorithmus 2.1: Liniensuche Problem (ii)                             */\n/*                                                                         */\n/***************************************************************************/\n\n\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>  // min, max, sqr\n\n#include <linalg.hpp>\n#include \"opti.hpp\"\n\n\nnamespace netgen\n{\nconst double eps0 = 1E-15;\n\n// Liniensuche\n\n\ndouble MinFunction :: Func (const Vector & /* x */) const\n{\n  cerr << \"Func of MinFunction called\" << endl;\n  return 0;\n}\n\nvoid MinFunction :: Grad (const Vector & /* x */, Vector & /* g */) const\n{\n  cerr << \"Grad of MinFunction called\" << endl;\n}\n  \ndouble MinFunction :: FuncGrad (const Vector & x, Vector & g) const\n{\n  cerr << \"Grad of MinFunction called\" << endl;\n  return 0;\n  /*\n  int n = x.Size();\n\n  Vector xr(n);\n  Vector xl(n);\n\n  double eps = 1e-6;\n  double fl, fr;\n  \n  for (int i = 1; i <= n; i++)\n    {\n      xr.Set (1, x);\n      xl.Set (1, x);\n\n      xr.Elem(i) += eps;\n      fr = Func (xr);\n\n      xl.Elem(i) -= eps;\n      fl = Func (xl);\n\n      g.Elem(i) = (fr - fl) / (2 * eps);\n    }\n\n  double f = Func(x);\n  //  (*testout) << \"f = \" << f << \" grad = \" << g << endl;\n  return f;\n  */\n}\n\n\ndouble MinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n{\n  Vector g(x.Size());\n  double f = FuncGrad (x, g);\n  deriv = (g * dir);\n\n  //  (*testout) << \"g = \" << g << \", dir = \" << dir << \", deriv = \" << deriv << endl;\n  return f;\n}\n\nvoid MinFunction :: ApproximateHesse (const Vector & x,\n\t\t\t\t      DenseMatrix & hesse) const\n{\n  int n = x.Size();\n  int i, j;\n\n  static Vector hx;\n  hx.SetSize(n);\n\n  double eps = 1e-6;\n  double f, f11, f12, f21, f22;\n  \n  for (i = 0; i < n; i++)\n    {\n      for (j = 0; j < i; j++)\n\t{\n\t  hx = x;\n\t  hx(i) = x(i) + eps;\n\t  hx(j) = x(j) + eps;\n\t  f11 = Func(hx);\n\t  hx(i) = x(i) + eps;\n\t  hx(j) = x(j) - eps;\n\t  f12 = Func(hx);\n\t  hx(i) = x(i) - eps;\n\t  hx(j) = x(j) + eps;\n\t  f21 = Func(hx);\n\t  hx(i) = x(i) - eps;\n\t  hx(j) = x(j) - eps;\n\t  f22 = Func(hx);\n\n\t  hesse(i, j) = hesse(j, i) =\n\t    (f11 + f22 - f12 - f21) / (2 * eps * eps);\n\t}\n\n      hx = x;\n      f = Func(x);\n      hx(i) = x(i) + eps;\n      f11 = Func(hx);\n      hx(i) = x(i) - eps;\n      f22 = Func(hx);\n\n      hesse(i, i) = (f11 + f22 - 2 * f) / (eps * eps);\n    }\n  //  (*testout) << \"hesse = \" << hesse << endl;\n}\n\n\n\n\n\n\n\n/// Line search, modified Mangasarien conditions\nvoid lines (Vector & x,         // i: initial point of line-search\n\t    Vector & xneu,      // o: solution, if successful\n\t    Vector & p,         // i: search direction\n\t    double & f,         // i: function-value at x\n\t    // o: function-value at xneu, iff ifail = 0\n\t    Vector & g,         // i: gradient at x\n\t    // o: gradient at xneu, iff ifail = 0\n\t    const MinFunction & fun,  // function to minimize\n\t    const OptiParameters & par,\n\t    double & alphahat,  // i: initial value for alpha_hat\n\t    // o: solution alpha iff ifail = 0\n\t    double fmin,        // i: lower bound for f\n\t    double mu1,         // i: Parameter mu_1 of Alg.2.1\n\t    double sigma,       // i: Parameter sigma of Alg.2.1\n\t    double xi1,         // i: Parameter xi_1 of Alg.2.1\n\t    double xi2,         // i: Parameter xi_1 of Alg.2.1\n\t    double tau,         // i: Parameter tau of Alg.2.1\n\t    double tau1,        // i: Parameter tau_1 of Alg.2.1\n\t    double tau2,        // i: Parameter tau_2 of Alg.2.1\n\t    int & ifail)        // o: 0 on success\n  //    -1 bei termination because lower limit fmin\n  //     1 bei illegal termination due to different reasons\n\n{\n  double phi0, phi0prime, phi1, phi1prime, phihatprime;\n  double alpha1, alpha2, alphaincr, c;\n  char flag = 1;\n  long it;\n\n  alpha1 = 0;\n  alpha2 = 1e50;\n  phi0 = phi1 = f;\n\n  phi0prime = g * p;\n\n  if (phi0prime > 0)\n    {\n      ifail = 1;\n      return;\n    }\n\n  ifail = 1;  // Markus\n\n  phi1prime = phi0prime;\n\n  //  (*testout) << \"phi0prime = \" << phi0prime << endl;\n\n  //  it = 100000l;\n  it = 0;\n\n  // cout << \"lin: \";\n  while (it++ <= par.maxit_linsearch)\n    {\n      // cout << \"i = \" << it << \" f = \" << f << \" \";\n      xneu.Set2 (1, x, alphahat, p);\n\n\n      //    f = fun.FuncGrad (xneu, g);\n      //      f = fun.Func (xneu);\n      f = fun.FuncDeriv (xneu, p, phihatprime);\n\n      // (*testout) << \"lines, f = \" << f << \" phip = \" << phihatprime << endl;\n\n      if (f < fmin)\n\t{\n\t  ifail = -1;\n\t  break;\n\t}\n\n\n      if (alpha2 - alpha1 < eps0 * alpha2)\n\t{\n\t  ifail = 0;\n\t  break;\n\t}\n\n      // (*testout) << \"i = \" << it << \" al = \" << alphahat << \" f = \" << f << \" fprime \" << phihatprime << endl;;\n\n      if (f - phi0 > mu1 * alphahat * phi1prime + eps0 * fabs (phi0))\n\n\t{\n\n\t  flag = 0;\n\t  alpha2 = alphahat;\n\n\t  c = \n\t    (f - phi1 - phi1prime * (alphahat-alpha1)) / \n\t    sqr (alphahat-alpha1);\n\n\t  alphahat = alpha1 - 0.5 * phi1prime / c;\n\n\t  if (alphahat > alpha2)\n\t    alphahat = alpha1 + 1/(4*c) *\n\t      ( (sigma+mu1) * phi0prime - 2*phi1prime\n\t\t+ sqrt (sqr(phi1prime - mu1 * phi0prime) -\n\t\t\t4 * (phi1 - phi0 - mu1 * alpha1 * phi0prime) * c));\n\n\t  alphahat = max2 (alphahat, alpha1 + tau * (alpha2 - alpha1));\n\t  alphahat = min2 (alphahat, alpha2 - tau * (alpha2 - alpha1));\n\t  \n\t  //\t  (*testout) << \" if-branch\" << endl;\n\n\t}\n\n      else\n\n\t{\n\t  /*\n\t  f = fun.FuncGrad (xneu, g);\n\t  phihatprime = g * p;\n\t  */\n\t  f = fun.FuncDeriv (xneu, p, phihatprime);\n\n\t  if (phihatprime < sigma * phi0prime * (1 + eps0))\n\n\t    {\n\t      if (phi1prime < phihatprime)   \n\t\t// Approximationsfunktion ist konvex\n\n\t\talphaincr = (alphahat - alpha1) * phihatprime /\n\t\t  (phi1prime - phihatprime);\n\n\t      else\n\t\talphaincr = 1e99; // MAXDOUBLE;\n\n\t      if (flag)\n\t\t{\n\t\t  alphaincr = max2 (alphaincr, xi1 * (alphahat-alpha1));\n\t\t  alphaincr = min2 (alphaincr, xi2 * (alphahat-alpha1));\n\t\t}\n\t      else\n\t\t{\n\t\t  alphaincr = max2 (alphaincr, tau1 * (alpha2 - alphahat));\n\t\t  alphaincr = min2 (alphaincr, tau2 * (alpha2 - alphahat));\n\t\t}\n\n\t      alpha1 = alphahat;\n\t      alphahat += alphaincr;\n\t      phi1 = f;\n\t      phi1prime = phihatprime;\n\t    }\n\n\t  else\n\n\t    {\n\t      ifail = 0;     // Erfolg !!\n\t      break;\n\t    }\n\t  \n\t  //\t  (*testout) << \" else, \" << endl;\n\n\t}\n\n    }\n\n  //  (*testout) << \"linsearch: it = \" << it << \" ifail = \" << ifail << endl;\n  // cout << endl;\n  fun.FuncGrad (xneu, g);\n\n\n  if (it < 0)\n    ifail = 1;\n\n  //  (*testout) << \"fail = \" << ifail << endl;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid SteepestDescent (Vector & x, const MinFunction & fun,\n\t\t      const OptiParameters & par)\n{\n  int it, n = x.Size();\n  Vector xnew(n), p(n), g(n), g2(n);\n  double val, alphahat;\n  int fail;\n\n  val = fun.FuncGrad(x, g);\n\n  alphahat = 1;\n  //  testout << \"f = \";\n  for (it = 0; it < 10; it++)\n    {\n      //    testout << val << \" \";\n\n      // p = -g;\n      p.Set (-1, g);\n\n      lines (x, xnew, p, val, g, fun, par, alphahat, -1e5,\n\t     0.1, 0.1, 1, 10, 0.1, 0.1, 0.6, fail);\n\n      x = xnew;\n    }\n  //  testout << endl;\n}\n}\n"
  },
  {
    "path": "libsrc/linalg/opti.hpp",
    "content": "#ifndef FILE_OPTI\n#define FILE_OPTI\n\n/**************************************************************************/\n/* File:   opti.hpp                                                       */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Jun. 95                                                    */\n/**************************************************************************/\n\n\n\nnamespace netgen\n{\n\n  /** \n      Function to be minimized.\n  */\n  class MinFunction \n  {\n  public:\n    ///\n    virtual double Func (const Vector & x) const;\n    ///\n    virtual void Grad (const Vector & x, Vector & g) const;\n    /// function and gradient\n    virtual double FuncGrad (const Vector & x, Vector & g) const;\n    /// directional derivative\n    virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n    /// if |g| < gradaccuray, then stop bfgs\n    virtual double GradStopping (const Vector & /* x */) const { return 0; } \n\n    ///\n    virtual void ApproximateHesse (const Vector & /* x */,\n\t\t\t\t   DenseMatrix & /* hesse */) const;\n  };\n\n\n  class OptiParameters\n  {\n  public:\n    int maxit_linsearch;\n    int maxit_bfgs;\n    double typf;\n    double typx;\n\n    OptiParameters ()\n    {\n      maxit_linsearch = 100;\n      maxit_bfgs = 100;\n      typf = 1;\n      typx = 1;\n    }\n  };\n  \n  \n  /** Implementation of BFGS method.\n      Efficient method for non-linear minimiztion problems.\n      @param x initial value and solution \n      @param fun function to be minimized\n  */\n  extern double BFGS (Vector & x, const MinFunction & fun, \n\t\t      const OptiParameters & par,\n\t\t      double eps = 1e-8);\n\n  /** Steepest descent method.\n      Simple method for non-linear minimization problems.\n      @param x initial value and solution \n      @param fun function to be minimized\n  */\n  void SteepestDescent (Vector & x, const MinFunction & fun,\n\t\t\tconst OptiParameters &  par);\n\n\n  extern void lines (\n\t\t     Vector & x,         // i: Ausgangspunkt der Liniensuche\n\t\t     Vector & xneu,      // o: Loesung der Liniensuche bei Erfolg\n\t\t     Vector & p,         // i: Suchrichtung\n\t\t     double & f,         // i: Funktionswert an der Stelle x\n\t\t     // o: Funktionswert an der Stelle xneu, falls ifail = 0\n\t\t     Vector & g,         // i: Gradient an der Stelle x\n\t\t     // o: Gradient an der Stelle xneu, falls ifail = 0\n\n\t\t     const MinFunction & fun,  // function to minmize\n\t\t     const OptiParameters & par, // parameters\n\t\t     double & alphahat,  // i: Startwert fr alpha_hat\n\t\t     // o: Loesung falls ifail = 0\n\t\t     double fmin,        // i: untere Schranke fr f\n\t\t     double mu1,         // i: Parameter mu_1 aus Alg.2.1\n\t\t     double sigma,       // i: Parameter sigma aus Alg.2.1\n\t\t     double xi1,         // i: Parameter xi_1 aus Alg.2.1\n\t\t     double xi2,         // i: Parameter xi_1 aus Alg.2.1\n\t\t     double tau,         // i: Parameter tau aus Alg.2.1\n\t\t     double tau1,        // i: Parameter tau_1 aus Alg.2.1\n\t\t     double tau2,        // i: Parameter tau_2 aus Alg.2.1\n\t\t     int & ifail);        // o:  0 bei erfolgreicher Liniensuche\n  //    -1 bei Abbruch wegen Unterschreiten von fmin\n  //    1 bei Abbruch, aus sonstigen Grnden\n\n\n\n\n  /**  \n       Solver for linear programming problem.\n\n       \\begin{verbatim}\n       min      c^t x\n       A x <= b    \n       \\end{verbatim}\n  */\n  extern void LinearOptimize (const DenseMatrix & a, const Vector & b, \n\t\t\t      const Vector & c, Vector & x);\n\n\n#ifdef NONE\n\n  /**\n     Simple projection iteration.\n  \n     find $u = argmin_{v >= 0}  0.5 u A u - f u$\n  */\n  extern void ApproxProject (const BaseMatrix & a, Vector & u, \n\t\t\t     const Vector & f,\n\t\t\t     double tau, int its);\n \n\n  /**\n     CG Algorithm for quadratic programming problem.\n     See: Dostal ...\n\n     d ... diag(A) ^{-1}\n  */\n  extern void ApproxProjectCG (const BaseMatrix & a, Vector & x, \n\t\t\t       const Vector & b, const class DiagMatrix & d,\n\t\t\t       double gamma, int & steps, int & changes);\n\n#endif\n\n\n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/linalg/polynomial.cpp",
    "content": "#include <mystdlib.h>\n#include <linalg.hpp>\n\nnamespace netgen\n{\n\nQuadraticPolynomial1V :: \nQuadraticPolynomial1V (double ac, double acx, double acxx)\n{\n  c = ac;\n  cx = acx;\n  cxx = acxx;\n}\n\ndouble QuadraticPolynomial1V :: \nValue (double x)\n{\n  return c + cx * x + cxx * x * x;\n}\n\ndouble QuadraticPolynomial1V ::  MaxUnitInterval ()\n{\n  // inner max\n  if (cxx < 0 && cx > 0 && cx < -2 * cxx)\n    {\n      return c - 0.25 * cx * cx / cxx;\n    }\n\n  \n  if (cx + cxx > 0)   // right edge\n    return c + cx + cxx;\n\n  // left end\n  return c;\n}\n\n\n\n\nLinearPolynomial2V :: \nLinearPolynomial2V (double ac, double acx, double acy)\n{\n  c = ac;\n  cx = acx;\n  cy = acy;\n};\n\n\nQuadraticPolynomial2V ::   \nQuadraticPolynomial2V ()\n{\n  ;\n}\n\n\nQuadraticPolynomial2V :: \nQuadraticPolynomial2V (double ac, double acx, double acy,\n\t\t       double acxx, double acxy, double acyy)\n{\n  c = ac;\n  cx = acx;\n  cy = acy;\n  cxx = acxx;\n  cxy = acxy;\n  cyy = acyy;\n}\n\nvoid QuadraticPolynomial2V :: \nSquare (const LinearPolynomial2V & lp)\n{\n  c = lp.c * lp.c;\n  cx = 2 * lp.c * lp.cx;\n  cy = 2 * lp.c * lp.cy;\n\n  cxx = lp.cx * lp.cx;\n  cxy = 2 * lp.cx * lp.cy;\n  cyy = lp.cy * lp.cy;\n}\n\nvoid QuadraticPolynomial2V :: \nAdd (double lam, const QuadraticPolynomial2V & qp2)\n{\n  c += lam * qp2.c;\n  cx += lam * qp2.cx;\n  cy += lam * qp2.cy;\n  cxx += lam * qp2.cxx;\n  cxy += lam * qp2.cxy;\n  cyy += lam * qp2.cyy;\n}\n\ndouble QuadraticPolynomial2V :: \nValue (double x, double y)\n{\n  return c + cx * x + cy * y + cxx * x * x + cxy * x * y + cyy * y * y;\n}\n\n/*\ndouble QuadraticPolynomial2V :: \nMinUnitSquare ()\n{\n  double x, y;\n  double minv = 1e8;\n  double val;\n  for (x = 0; x <= 1; x += 0.1)\n    for (y = 0; y <= 1; y += 0.1)\n      {\n\tval = Value (x, y);\n\tif (val < minv)\n\t  minv = val;\n      }\n  return minv;\n};\n*/\n\ndouble QuadraticPolynomial2V :: \nMaxUnitSquare ()\n{\n  // find critical point\n\n  double maxv = c;\n  double hv;\n\n  double det, x0, y0;\n  det = 4 * cxx * cyy - cxy * cxy;\n\n  if (det > 0)\n    {\n      // definite surface\n      \n      x0 = (-2 * cyy * cx + cxy * cy) / det;\n      y0 = (cxy * cx -2 * cxx * cy) / det;\n\n      if (x0 >= 0 && x0 <= 1 && y0 >= 0 && y0 <= 1)\n\t{\n\t  hv = Value (x0, y0);\n\t  if (hv > maxv) maxv = hv;\n\t}\n    }\n  \n  QuadraticPolynomial1V e1(c, cx, cxx);\n  QuadraticPolynomial1V e2(c, cy, cyy);\n  QuadraticPolynomial1V e3(c+cy+cyy, cx+cxy, cxx);\n  QuadraticPolynomial1V e4(c+cx+cxx, cy+cxy, cyy);\n  \n  hv = e1.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n  hv = e2.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n  hv = e3.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n  hv = e4.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n\n  return maxv;\n};\n\n\n\n\ndouble QuadraticPolynomial2V :: \nMaxUnitTriangle ()\n{\n  // find critical point\n  \n  double maxv = c;\n  double hv;\n\n  double det, x0, y0;\n  det = 4 * cxx * cyy - cxy * cxy;\n\n  if (cxx < 0 && det > 0)\n    { \n      // definite surface\n      \n      x0 = (-2 * cyy * cx + cxy * cy) / det;\n      y0 = (cxy * cx -2 * cxx * cy) / det;\n\n      if (x0 >= 0 && y0 >= 0 && x0+y0 <= 1)\n\t{\n\t  return Value (x0, y0);\n\t}\n    }\n  \n  \n  QuadraticPolynomial1V e1(c, cx, cxx);\n  QuadraticPolynomial1V e2(c, cy, cyy);\n  QuadraticPolynomial1V e3(c+cy+cyy, cx-cy+cxy-2*cyy, cxx-cxy+cyy);\n  \n  hv = e1.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n  hv = e2.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n  hv = e3.MaxUnitInterval();\n  if (hv > maxv) maxv = hv;\n\n  return maxv;\n}\n}\n"
  },
  {
    "path": "libsrc/linalg/polynomial.hpp",
    "content": "#ifndef FILE_POLYNOMIAL\n#define FILE_POLYNOMIAL\n\n/* *************************************************************************/\n/* File:   polynomial.hh                                                   */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   25. Nov. 99                                                     */\n/* *************************************************************************/\n\nnamespace netgen\n{\n\nclass QuadraticPolynomial1V \n{\n  double c, cx, cxx;\npublic:\n  QuadraticPolynomial1V (double ac, double acx, double acxx);\n  double Value (double x);\n  double MaxUnitInterval ();\n};\n\nclass LinearPolynomial2V\n{\n  double c, cx, cy;\npublic:\n  LinearPolynomial2V (double ac, double acx, double acy);\n  friend class QuadraticPolynomial2V;\n};\n\n\nclass QuadraticPolynomial2V\n{\n  double c, cx, cy, cxx, cxy, cyy;\npublic:\n  QuadraticPolynomial2V ();\n  QuadraticPolynomial2V (double ac, double acx, double acy,\n\t\t\t double acxx, double acxy, double acyy);\n  void Square (const LinearPolynomial2V & lp);\n  void Add (double lam, const QuadraticPolynomial2V & qp);\n\n  double Value (double x, double y);\n  //  double MinUnitSquare ();\n  double MaxUnitSquare ();\n  double MaxUnitTriangle ();\n};\n} // namespace netgen\n#endif\n"
  },
  {
    "path": "libsrc/linalg/vector.hpp",
    "content": "#ifndef FILE_VECTOR\n#define FILE_VECTOR\n\n/* *************************************************************************/\n/* File:   vector.hpp                                                      */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   01. Oct. 94                                                     */\n/* *************************************************************************/\n\nnamespace netgen\n{\n\ntemplate <typename T>\nclass TFlatVector\n{\nprotected:\n  int s;\n  T * data;\npublic:\n  TFlatVector () { ; }\n  TFlatVector (int as, T * adata)\n  { s = as; data = adata; }\n    \n  int Size () const\n  { return s; }\n\n  TFlatVector & operator= (const TFlatVector & v) \n  { memcpy (data, v.data, s*sizeof(T)); return *this; }\n\n  TFlatVector & operator= (T scal) \n  {\n    for (int i = 0; i < s; i++) data[i] = scal; \n    return *this;\n  }\n\n  T & operator[] (int i) { return data[i]; }\n  const T & operator[] (int i) const { return data[i]; }\n  T & operator() (int i) { return data[i]; }\n  const T & operator() (int i) const { return data[i]; }\n\n  // double & Elem (int i) { return data[i-1]; }\n  // const double & Get (int i) const { return data[i-1]; }\n  // void Set (int i, double val) { data[i-1] = val; }\n\n  TFlatVector & operator*= (T scal)\n  {\n    for (int i = 0; i < s; i++) data[i] *= scal;\n    return *this;\n  }\n};\n\n\n\n\nclass FlatVector\n{\nprotected:\n  int s;\n  double *data;\npublic:\n  FlatVector () { ; }\n  FlatVector (int as, double * adata)\n  { s = as; data = adata; }\n\n  int Size () const\n  { return s; }\n\n  FlatVector & operator= (const FlatVector & v) \n  { memcpy (data, v.data, s*sizeof(double)); return *this; }\n\n  FlatVector & operator= (double scal) \n  {\n    for (int i = 0; i < s; i++) data[i] = scal; \n    return *this;\n  }\n\n  double & operator[] (int i) { return data[i]; }\n  const double & operator[] (int i) const { return data[i]; }\n  double & operator() (int i) { return data[i]; }\n  const double & operator() (int i) const { return data[i]; }\n\n  // double & Elem (int i) { return data[i-1]; }\n  // const double & Get (int i) const { return data[i-1]; }\n  // void Set (int i, double val) { data[i-1] = val; }\n\n  FlatVector & operator*= (double scal)\n  {\n    for (int i = 0; i < s; i++) data[i] *= scal;\n    return *this;\n  }\n\n  FlatVector & Add (double scal, const FlatVector & v2)\n  {\n    for (int i = 0; i < s; i++) \n      data[i] += scal * v2[i];\n    return *this;\n  }\n\n  FlatVector & Set (double scal, const FlatVector & v2)\n  {\n    for (int i = 0; i < s; i++) \n      data[i] = scal * v2[i];\n    return *this;\n  }\n\n  FlatVector & Set2 (double scal1, const FlatVector & v1,\n\t\t double scal2, const FlatVector & v2)\n  {\n    for (int i = 0; i < s; i++) \n      data[i] = scal1 * v1[i] + scal2 * v2[i];\n    return *this;\n  }\n  \n  double L2Norm() const\n  {\n    double sum = 0;\n    for (int i = 0; i < s; i++)\n      sum += data[i] * data[i];\n    return sqrt (sum);\n  }\n\n  operator TFlatVector<double> () const { return TFlatVector<double> (s, data); } \n  friend double operator* (const FlatVector & v1, const FlatVector & v2);\n};\n\n\n\n\nclass Vector : public FlatVector\n{\n  bool ownmem;\npublic:\n  Vector () \n  { s = 0; data = 0; ownmem = false; }\n  Vector (int as)\n  { s = as; data = new double[s]; ownmem = true; }\n  Vector (int as, double * mem)\n  { s = as; data = mem; ownmem = false; }\n  ~Vector ()\n  { if (ownmem) delete [] data; }\n\n  template<typename ARCHIVE>\n  void DoArchive(ARCHIVE& ar)\n  {\n    auto size = s;\n    ar & ownmem & size;\n    if(!ar.Output())\n      SetSize(size);\n    ar.Do(data, size);\n  }\n  Vector & operator= (const FlatVector & v) \n  { memcpy (data, &v(0), s*sizeof(double)); return *this; }\n\n  Vector & operator= (double scal) \n  {\n    for (int i = 0; i < s; i++) data[i] = scal; \n    return *this;\n  }\n\n  void SetSize (int as)\n  {\n    if (s != as)\n      {\n\ts = as;\n\tif (ownmem) delete [] data;\n\tdata = new double [s];\n        ownmem = true;\n      }\n  }\n\n  operator TFlatVector<double> () const { return TFlatVector<double> (s, data); } \n};\n\ntemplate <int S>\nclass VectorMem : public Vector\n{\n  double mem[S];\npublic:\n  VectorMem () : Vector(S, &mem[0]) { ; }\n\n  VectorMem & operator= (const FlatVector & v) \n  { memcpy (data, &v(0), S*sizeof(double)); return *this; }\n\n  VectorMem & operator= (double scal) \n  {\n    for (int i = 0; i < S; i++) data[i] = scal; \n    return *this;\n  }\n};\n\n\n\n\n\ninline double operator* (const FlatVector & v1, const FlatVector & v2)\n{\n  double sum = 0;\n  for (int i = 0; i < v1.s; i++)\n    sum += v1.data[i] * v2.data[i];\n  return sum;\n}\n\n\n\n\ninline ostream & operator<< (ostream & ost, const FlatVector & v)\n{\n  for (int i = 0; i < v.Size(); i++)\n    ost << \" \" << setw(7) << v[i];\n  return ost;\n}\n\n} //namespace netgen\n\n#endif\n\n\n"
  },
  {
    "path": "libsrc/meshing/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n        adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp \n        clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp\t    \n        geomsearch.cpp global.cpp hprefinement.cpp improve2.cpp\t\t    \n        improve2gen.cpp improve3.cpp localh.cpp meshclass.cpp\t\t    \n        meshfunc.cpp meshfunc2d.cpp meshing2.cpp meshing3.cpp\t\t    \n        meshtool.cpp meshtype.cpp msghandler.cpp netrule2.cpp\t\t    \n        netrule3.cpp parser2.cpp parser3.cpp refine.cpp\t\t    \n        ruler2.cpp ruler3.cpp secondorder.cpp smoothing2.5.cpp\t\t    \n        smoothing2.cpp smoothing3.cpp specials.cpp\n        topology.cpp validate.cpp bcfunctions.cpp   \n        parallelmesh.cpp  paralleltop.cpp  basegeom.cpp\n        python_mesh.cpp surfacegeom.cpp\n        debugging.cpp fieldlines.cpp visual_interface.cpp\n        boundarylayer2d.cpp boundarylayer_interpolate.cpp\n)\n\ntarget_link_libraries( nglib PRIVATE $<BUILD_INTERFACE:netgen_metis> $<BUILD_INTERFACE:netgen_python> )\n\ninstall(FILES\n  adfront2.hpp adfront3.hpp basegeom.hpp bcfunctions.hpp bisect.hpp\n  boundarylayer.hpp classifyhpel.hpp clusters.hpp curvedelems.hpp\n  findip2.hpp findip.hpp geomsearch.hpp global.hpp hpref_hex.hpp\n  hprefinement.hpp hpref_prism.hpp hpref_pyramid.hpp hpref_quad.hpp\n  hpref_segm.hpp hpref_tet.hpp hpref_trig.hpp improve2.hpp improve3.hpp\n  localh.hpp meshclass.hpp meshfunc.hpp meshing2.hpp meshing3.hpp\n  meshing.hpp meshtool.hpp meshtype.hpp msghandler.hpp paralleltop.hpp\n  ruler2.hpp ruler3.hpp specials.hpp topology.hpp validate.hpp\n  python_mesh.hpp surfacegeom.hpp delaunay2d.hpp\n  fieldlines.hpp soldata.hpp visual_interface.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/meshing COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/meshing/adfront2.cpp",
    "content": "/*\n  Advancing front class for surfaces\n*/\n\n#include <mystdlib.h>\n#include <gprim/geom2d.hpp>\n#include <gprim/geomfuncs.hpp>\n#include \"adfront2.hpp\"\n\nnamespace netgen\n{\n  FrontPoint2 :: FrontPoint2 (const Point<3> & ap, PointIndex agi,\n\t\t\t      MultiPointGeomInfo * amgi, bool aonsurface)\n  {\n    p = ap;\n    globalindex = agi;\n    nlinetopoint = 0;\n    frontnr = INT_MAX-10;\n    onsurface = aonsurface;\n\n    if (amgi)\n      {\n\tmgi = new MultiPointGeomInfo (*amgi);\n\tfor (int i = 1; i <= mgi->GetNPGI(); i++)\n\t  if (mgi->GetPGI(i).trignum <= 0)\n\t    cout << \"WARNING: Add FrontPoint2, illegal geominfo = \" << mgi->GetPGI(i).trignum << endl;\n      }\n    else\n      mgi = NULL;\n  }\n\n\n  AdFront2 :: AdFront2 (const Box3d & aboundingbox)\n    : boundingbox(aboundingbox), \n      linesearchtree(boundingbox.PMin(), boundingbox.PMax()),\n      pointsearchtree(boundingbox.PMin(), boundingbox.PMax()),\n      cpointsearchtree(boundingbox.PMin(), boundingbox.PMax())\n  {\n    nfl = 0;\n    allflines = 0;\n\n    minval = 0;\n    // starti = lines.Begin();\n    starti = *lines.Range().begin();\n  }\n\n  AdFront2 :: ~AdFront2 ()\n  {\n    delete allflines;\n  }\n\n\n  void AdFront2 :: PrintOpenSegments (ostream & ost) const\n  {\n    if (nfl > 0)\n      {\n\tost << nfl << \" open front segments left:\" << endl;\n\t// for (int i = lines.Begin(); i < lines.End(); i++)\n        for (int i : lines.Range())\n\t  if (lines[i].Valid())\n\t    ost << i << \": \" \n                << GetGlobalIndex (lines[i].L().I1()) << \"-\"\n\t\t<< GetGlobalIndex (lines[i].L().I2()) << endl;\n      }\n  }\n\n  /*\n  void AdFront2 :: GetPoints (NgArray<Point<3> > & apoints) const\n  {\n    apoints.Append (points);\n    // for (int i = 0; i < points.Size(); i++)\n    // apoints.Append (points[i].P());\n  }\n  */\n\n\n\n  int AdFront2 :: AddPoint (const Point<3> & p, PointIndex globind, \n                            MultiPointGeomInfo * mgi,\n                            bool pointonsurface)\n  {\n    // inserts at empty position or resizes array\n    int pi;\n\n    if (delpointl.Size() != 0)\n      {\n\tpi = delpointl.Last();\n\tdelpointl.DeleteLast ();\n\n\tpoints[pi] = FrontPoint2 (p, globind, mgi, pointonsurface);\n      }\n    else\n      {\n\tpoints.Append (FrontPoint2 (p, globind, mgi, pointonsurface));\n        pi = points.Size()-1;\n      }\n\n    if (mgi)\n      cpointsearchtree.Insert (p, pi);\n\n    if (pointonsurface)\n      pointsearchtree.Insert (p, pi);\n    \n    return pi;\n  }\n\n\n  int AdFront2 :: AddLine (int pi1, int pi2,\n                           const PointGeomInfo & gi1, const PointGeomInfo & gi2)\n  {\n    int minfn;\n    int li;\n\n    FrontPoint2 & p1 = points[pi1];\n    FrontPoint2 & p2 = points[pi2];\n\n\n    nfl++;\n\n    p1.AddLine();\n    p2.AddLine();\n\n    minfn = min2 (p1.FrontNr(), p2.FrontNr());\n    p1.DecFrontNr (minfn+1);\n    p2.DecFrontNr (minfn+1);\n\n    if (dellinel.Size() != 0)\n      {\n\tli = dellinel.Last();\n\tdellinel.DeleteLast ();\n\tlines[li] = FrontLine (INDEX_2(pi1, pi2));\n      }\n    else\n      {\n\tlines.Append(FrontLine (INDEX_2(pi1, pi2)));\n        li = lines.Size()-1;\n      }\n\n  \n    if (!gi1.trignum || !gi2.trignum)\n      {\n\tcout << \"WARNING: in AdFront::AddLine, illegal geominfo\" << endl;\n      }\n  \n    lines[li].SetGeomInfo (gi1, gi2);\n\n    Box3d lbox;\n    lbox.SetPoint(p1.P());\n    lbox.AddPoint(p2.P());\n\n    linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li);\n\n    if (allflines)\n      {\n\tif (allflines->Used (PointIndices<2>(GetGlobalIndex (pi1), \n                                             GetGlobalIndex (pi2))))\n\t  {\n\t    cerr << \"ERROR Adfront2::AddLine: line exists\" << endl;\n\t    (*testout) << \"ERROR Adfront2::AddLine: line exists\" << endl;\n\t  }\n\n\tallflines->Set (PointIndices<2>(GetGlobalIndex (pi1), \n                                        GetGlobalIndex (pi2)), 1);\n      }\n\n    return li;\n  }\n\n\n  void AdFront2 :: DeleteLine (int li)\n  {\n    int pi;\n\n    nfl--;\n\n    for (int i = 1; i <= 2; i++)\n      {\n\tpi = lines[li].L().I(i);\n\tpoints[pi].RemoveLine();\n\n\tif (!points[pi].Valid())\n\t  {\n\t    delpointl.Append (pi);\n\t    if (points[pi].mgi)\n\t      {\n\t\tcpointsearchtree.DeleteElement (pi);\n\t\tdelete points[pi].mgi;\n\t\tpoints[pi].mgi = NULL;\n\t      }\n\n            pointsearchtree.DeleteElement (pi);\n\t  }\n      }\n\n    if (allflines)\n      {\n\tallflines->Set (PointIndices<2>(GetGlobalIndex (lines[li].L().I1()),\n                                        GetGlobalIndex (lines[li].L().I2())), 2);\n      }\n\n    lines[li].Invalidate();\n    linesearchtree.DeleteElement (li);\n\n    dellinel.Append (li);\n  }\n\n\n  int AdFront2 :: ExistsLine (int pi1, int pi2)\n  {\n    if (!allflines)\n      return 0;\n    if (allflines->Used (INDEX_2(pi1, pi2)))\n      return allflines->Get (INDEX_2 (pi1, pi2));\n    else\n      return 0;\n  }\n\n\n  int AdFront2 :: SelectBaseLine (Point<3>  & p1, Point<3>  & p2, \n\t\t\t\t  const PointGeomInfo *& geominfo1,\n\t\t\t\t  const PointGeomInfo *& geominfo2,\n\t\t\t\t  int & qualclass)\n  {\n    int baselineindex = -1; \n    \n    // for (int i = starti; i < lines.End(); i++)\n    for (int i = starti; i < *lines.Range().end(); i++)\n      {\n\tif (lines[i].Valid())\n\t  {\n\t    int hi = lines[i].LineClass() +\n\t      points[lines[i].L().I1()].FrontNr() +\n\t      points[lines[i].L().I2()].FrontNr();\n\t  \n\t    if (hi <= minval)\n\t      {\n\t\tminval = hi;\n\t\tbaselineindex = i;\n\t\tbreak;\n\t      }\n\t  }\n      }\n  \n    if (baselineindex == -1)\n      {\n\tminval = INT_MAX;\n\t// for (int i = lines.Begin(); i < lines.End(); i++)\n        for (int i : lines.Range())\n\t  if (lines[i].Valid())\n\t    {\n\t      int hi = lines[i].LineClass() +\n\t\tpoints[lines[i].L().I1()].FrontNr() +\n\t\tpoints[lines[i].L().I2()].FrontNr();\n\t    \n\t      if (hi < minval)\n\t\t{\n\t\t  minval = hi;\n\t\t  baselineindex = i;\n\t\t}\n\t    }\n      }\n    starti = baselineindex+1;\n\n    p1 = points[lines[baselineindex].L().I1()].P();\n    p2 = points[lines[baselineindex].L().I2()].P();\n    geominfo1 = &lines[baselineindex].GetGeomInfo(1);\n    geominfo2 = &lines[baselineindex].GetGeomInfo(2);\n\n    qualclass = lines[baselineindex].LineClass();\n\n    return baselineindex;\n  }\n\n\n\n\n  int AdFront2 :: GetLocals (int baselineindex,\n\t\t\t     NgArray<Point<3>> & locpoints,\n\t\t\t     NgArray<MultiPointGeomInfo> & pgeominfo,\n\t\t\t     NgArray<INDEX_2> & loclines,   // local index\n\t\t\t     NgArray<INDEX> & pindex,\n\t\t\t     NgArray<INDEX> & lindex,\n\t\t\t     double xh)\n  {\n    // static Timer timer(\"adfront2::GetLocals\"); RegionTimer reg (timer);\n    \n    int pstind;\n    Point<3>  midp, p0;\n\n    pstind = lines[baselineindex].L().I1();\n    p0 = points[pstind].P();\n\n    loclines.Append(lines[baselineindex].L());\n    lindex.Append(baselineindex);  \n\n    ArrayMem<int, 1000> nearlines(0);\n    NgArrayMem<int, 1000> nearpoints(0);\n\n    // dominating costs !!\n    linesearchtree.GetIntersecting (p0 - Vec3d(xh, xh, xh),\n\t\t\t\t    p0 + Vec3d(xh, xh, xh),\n\t\t\t\t    nearlines);\n\n    // only special points that are not in adfront,\n    // other points are from linesearchtree\n    cpointsearchtree.GetIntersecting(p0 - Vec3d(xh, xh, xh),\n                                     p0 + Vec3d(xh, xh, xh),\n                                     nearpoints);\n\n    for(auto i : nearlines)\n      {\n\tif (lines[i].Valid() && i != baselineindex) \n\t  {\n            loclines.Append(lines[i].L());\n            lindex.Append(i);\n\t  }\n      }\n\n    // static NgArray<int> invpindex;\n    invpindex.SetSize (points.Size()); \n    // invpindex = -1;\n    for(auto pi : nearpoints)\n      invpindex[pi] = -1;\n\n    for(const auto& li : loclines)\n      {\n\tinvpindex[li.I1()] = 0;\n\tinvpindex[li.I2()] = 0;\n      }\n\n\n    for(auto& line : loclines)\n      {\n        for(auto i : Range(2))\n          {\n            auto& pi = line[i];\n\t    if (invpindex[pi] == 0)\n\t      {\n\t\tpindex.Append (pi);\n\t\tinvpindex[pi] = pindex.Size();\n                locpoints.Append (points[pi].P());\n\t\tpi = locpoints.Size();\n\t      }\n\t    else\n\t      pi = invpindex[pi];\n\t  }\n      }\n\n\n    // double xh2 = xh*xh;\n    for(auto i : nearpoints)\n      {\n\tif (points[i].Valid() && \n\t    points[i].OnSurface() &&\n\t    // Dist2 (points.Get(i).P(), p0) <= xh2 &&\n\t    invpindex[i] <= 0)\n\t  {\n            locpoints.Append (points[i].P());\n\t    invpindex[i] = locpoints.Size();\n\t    pindex.Append(i);\n\t  }\n      }\n    /*\n    double xh2 = xh*xh;\n    for (i = 1; i <= points.Size(); i++)\n      {\n\tif (points.Get(i).Valid() && \n\t    points.Get(i).OnSurface() &&\n\t    Dist2 (points.Get(i).P(), p0) <= xh2 &&\n\t    invpindex.Get(i) <= 0)\n\t  {\n\t    invpindex.Elem(i) =\n\t      locpoints.Append (points.Get(i).P());\n\t    pindex.Append(i);\n\t  }\n      }\n    */\n\n    pgeominfo.SetSize (locpoints.Size());\n    for (int i = 0; i < pgeominfo.Size(); i++)\n      pgeominfo[i].Init();\n\n\n    for (int i = 0; i < loclines.Size(); i++)\n      for (int j = 0; j < 2; j++)\n\t{\n\t  int lpi = loclines[i][j];\n\t\n\t  const PointGeomInfo & gi = \n\t    lines[lindex[i]].GetGeomInfo (j+1);\n\t  pgeominfo.Elem(lpi).AddPointGeomInfo (gi);\n\t\n\t  /*\n\t    if (pgeominfo.Elem(lpi).cnt == MULTIPOINTGEOMINFO_MAX)\n\t    break;\n\n\t    const PointGeomInfo & gi = \n\t    lines.Get(lindex.Get(i)).GetGeomInfo (j);\n\t\n\t    PointGeomInfo * pgi = pgeominfo.Elem(lpi).mgi;\n\n\t    int found = 0;\n\t    for (k = 0; k < pgeominfo.Elem(lpi).cnt; k++)\n\t    if (pgi[k].trignum == gi.trignum)\n\t    found = 1;\n\n\t    if (!found)\n\t    {\n\t    pgi[pgeominfo.Elem(lpi).cnt] = gi;\n\t    pgeominfo.Elem(lpi).cnt++;\n\t    }\n\t  */\n\t}\n\n    for (int i = 0; i < locpoints.Size(); i++)\n      {\n\tint pi = pindex[i];\n      \n\tif (points[pi].mgi)\n\t  for (int j = 1; j <= points[pi].mgi->GetNPGI(); j++)\n\t    pgeominfo[i].AddPointGeomInfo (points[pi].mgi->GetPGI(j));\n      }\n   \n    if (loclines.Size() == 1)\n      {\n\tcout << IM(5) << \"loclines.Size = 1\" << endl;\n\t(*testout) << \"loclines.size = 1\" << endl\n\t\t   << \" h = \" << xh << endl\n\t\t   << \" nearline.size = \" << nearlines.Size() << endl\n\t\t   << \" p0 = \" << p0 << endl;\n      }\n\n    return lines[baselineindex].LineClass();\n  }\n\n\n\n  void AdFront2 :: SetStartFront ()\n  {\n    // for (int i = lines.Begin(); i < lines.End(); i++)\n    for (int i : lines.Range())\n      if (lines[i].Valid())\n\tfor (int j = 1; j <= 2; j++)\n\t  points[lines[i].L().I(j)].DecFrontNr(0);\n  }\n\n\n  void AdFront2 :: Print (ostream & ost) const\n  {\n    ost << points.Size() << \" Points: \" << endl;\n    // for (int i = points.Begin(); i < points.End(); i++)\n    for (int i : points.Range())\n      if (points[i].Valid())\n\tost << i << \"  \" << points[i].P() << endl;\n\n    ost << nfl << \" Lines: \" << endl;\n    // for (int i = lines.Begin(); i < lines.End(); i++)\n    for (int i : lines.Range())\n      if (lines[i].Valid())\n\tost << lines[i].L().I1() << \" - \" << lines[i].L().I2() << endl;\n\n    ost << flush;\n  }\n\n\n  bool AdFront2 :: Inside (const Point<2> & p) const\n  {\n    int cnt;\n    Vec<2> n;\n    Vec<3> v1;\n    DenseMatrix a(2), ainv(2);\n    Vector b(2), u(2);\n    \n    // quasi-random numbers:\n    n(0) = 0.123871;\n    n(1) = 0.15432;\n    \n    cnt = 0;\n    for (int i = 0; i < lines.Size(); i++)\n      if (lines[i].Valid())\n\t{\n\t  const Point<3> & p1 = points[lines[i].L().I1()].P();\n\t  const Point<3> & p2 = points[lines[i].L().I2()].P();\n\t  \n\t  v1 = p2 - p1;\n\t  \n\t  a(0, 0) = v1(0);\n\t  a(1, 0) = v1(1);\n\t  \n\t  a(0, 1) = -n(0);\n\t  a(1, 1) = -n(1);\n\n\t  b(0) = p(0) - p1(0);\n\t  b(1) = p(1) - p1(1);\n\t  \n\t  CalcInverse (a, ainv);\n\t  ainv.Mult (b, u);\n\t  \n\t  if (u(0) >= 0 && u(0) <= 1 && u(1) > 0)\n\t    cnt++;\n\t}\n    \n    return ((cnt % 2) != 0);\n  }\n\n  bool AdFront2 :: SameSide (const Point<2> & lp1, const Point<2> & lp2, \n                             const FlatArray<int> * testfaces) const\n  {\n    int cnt = 0;\n\n    if (testfaces)\n      {\n        for (int ii = 0; ii < testfaces->Size(); ii++)\n          if (lines[(*testfaces)[ii]].Valid())\n            {\n              int i = (*testfaces)[ii];\n              const Point<3> & p13d = points[lines[i].L().I1()].P();\n              const Point<3> & p23d = points[lines[i].L().I2()].P();\n              \n              Point<2> p1(p13d(0), p13d(1));\n              Point<2> p2(p23d(0), p23d(1));\n              \n              // p1 + alpha v = lp1 + beta vl\n              Vec<2> v = p2-p1;\n              Vec<2> vl = lp2 - lp1;\n              Mat<2,2> mat, inv;\n              Vec<2> rhs, sol;\n              mat(0,0) = v(0);\n              mat(1,0) = v(1);\n              mat(0,1) = -vl(0);\n              mat(1,1) = -vl(1);\n              rhs = lp1-p1;\n              \n              if (Det(mat) == 0) continue;\n              CalcInverse (mat, inv);\n              sol = inv * rhs;\n              if ( (sol(0) >= 0) && (sol(0) <= 1) && (sol(1) >= 0) && (sol(1) <= 1))\n                { cnt++; }\n            }\n\n      }\n    else\n      {\n        for (int i = 0; i < lines.Size(); i++)\n          if (lines[i].Valid())\n            {\n              const Point<3> & p13d = points[lines[i].L().I1()].P();\n              const Point<3> & p23d = points[lines[i].L().I2()].P();\n              \n              Point<2> p1(p13d(0), p13d(1));\n              Point<2> p2(p23d(0), p23d(1));\n              \n              // p1 + alpha v = lp1 + beta vl\n              Vec<2> v = p2-p1;\n              Vec<2> vl = lp2 - lp1;\n              Mat<2,2> mat, inv;\n              Vec<2> rhs, sol;\n              mat(0,0) = v(0);\n              mat(1,0) = v(1);\n              mat(0,1) = -vl(0);\n              mat(1,1) = -vl(1);\n              rhs = lp1-p1;\n              \n              if (Det(mat) == 0) continue;\n              CalcInverse (mat, inv);\n              sol = inv * rhs;\n              if ((sol(0) >= 0) && (sol(0) <= 1) && (sol(1) >= 0) && (sol(1) <= 1))\n                { cnt++; }\n            }\n      }\n    return ((cnt % 2) == 0);\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/adfront2.hpp",
    "content": "#ifndef NETGEN_ADFRONT2_HPP\n#define NETGEN_ADFRONT2_HPP\n\n/**************************************************************************/\n/* File:   adfront2.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\n\n/**\n\n    Advancing front class for surfaces\n\n*/\n\n#include <gprim/geomobjects.hpp>\n#include <gprim/adtree.hpp>\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n  ///\n  class FrontPoint2\n  {\n    /// coordinates\n    Point<3> p;            \n    /// global node index\n    PointIndex globalindex;   \n    /// number of front lines connected to point \n    int nlinetopoint;    \n    /// distance to original boundary\n    int frontnr;          \n\n    bool onsurface;\n\n  public:\n    ///\n    MultiPointGeomInfo * mgi;\n\n    ///\n    FrontPoint2 ()\n    {\n      globalindex.Invalidate(); //  = -1;\n      nlinetopoint = 0;\n      frontnr = INT_MAX-10;    // attention: overflow on calculating  INT_MAX + 1\n      mgi = NULL;\n      onsurface = true;\n    }\n\n    ///\n    FrontPoint2 (const Point<3> & ap, PointIndex agi,\n\t\t MultiPointGeomInfo * amgi, bool aonsurface = true);\n    ///\n    ~FrontPoint2 () { ; }\n\n    ///\n    const Point<3> & P () const { return p; }\n    ///\n    operator const Point<3> & () const { return p; }\n    ///\n    PointIndex GlobalIndex () const { return globalindex; }\n\n    ///\n    void AddLine () { nlinetopoint++; }\n    ///\n    void RemoveLine ()\n    {\n      nlinetopoint--;\n      if (nlinetopoint == 0)\n\tnlinetopoint = -1;\n    }\n\n    ///\n    bool Valid () const\n    { return nlinetopoint >= 0; }\n\n    ///\n    bool OnSurface() const\n    { return onsurface; }\n\n    ///\n    void DecFrontNr (int afrontnr)\n    {\n      if (frontnr > afrontnr) frontnr = afrontnr;\n    }\n    \n    ///\n    int FrontNr () const { return frontnr; }\n  };\n\n  \n  ///\n  class FrontLine\n  {\n  private:\n    /// Point Indizes\n    INDEX_2 l;  // want to replace by std::array<int,2> l;\n    /// quality class \n    int lineclass;      \n    /// geometry specific data\n    PointGeomInfo geominfo[2];\n  public:\n\n    FrontLine ()\n    {\n      lineclass = 1;\n    }\n\n    ///\n    FrontLine (const INDEX_2 & al)\n      : l(al), lineclass(1) { } \n\n    ///\n    const auto & L () const { return l; }\n    ///\n    int LineClass() const { return lineclass; }\n\n    ///\n    void IncrementClass ()\n    {\n      lineclass++;\n    }\n    ///\n    void ResetClass ()\n    {\n      lineclass = 1;\n    }\n\n    ///\n    bool Valid () const\n    {\n      return l[0] != -1;\n    }\n    ///\n    void Invalidate ()\n    {\n      l[0] = -1;\n      l[1] = -1;\n      lineclass = 1000;\n    }\n\n    void SetGeomInfo (const PointGeomInfo & gi1, const PointGeomInfo & gi2)\n      {\n\tgeominfo[0] = gi1;\n\tgeominfo[1] = gi2;\n      }\n\n    const PointGeomInfo * GetGeomInfo () const\n    { return geominfo; }\n    \n    const PointGeomInfo & GetGeomInfo (int endp) const\n    { return geominfo[endp-1]; }\n\n    friend class AdFront2;\n  };\n\n\nclass AdFront2\n{\n\n  ///\n  Array<FrontPoint2> points;  /// front points\n  Array<FrontLine> lines;     /// front lines\n\n  Box3d boundingbox;\n  BoxTree<3> linesearchtree;       /// search tree for lines\n  Point3dTree pointsearchtree;    /// search tree for points\n  Point3dTree cpointsearchtree;   /// search tree for cone points (not used ???)\n\n  Array<int> delpointl;     /// list of deleted front points\n  Array<int> dellinel;      /// list of deleted front lines\n\n  int nfl;                  /// number of front lines;\n  INDEX_2_HASHTABLE<int> * allflines; /// all front lines ever have been\n\n  Array<int> invpindex;\n\n  int minval;\n  int starti;\n\npublic:\n  ///\n  //  AdFront2 ();\n  AdFront2 (const Box3d & aboundingbox);\n  ///\n  ~AdFront2 ();\n\n  ///\n  // void GetPoints (NgArray<Point<3> > & apoints) const;\n  ///\n  void Print (ostream & ost) const;\n\n  ///\n  bool Empty () const\n  {\n    return nfl == 0;\n  }\n  ///\n  int GetNFL () const { return nfl; }\n\n  const FrontLine & GetLine (int nr) const { return lines[nr]; }\n  const FrontPoint2 & GetPoint (int nr) const { return points[nr]; }\n  const auto & GetLines () const { return lines; }\n\n  ///\n  int SelectBaseLine (Point<3> & p1, Point<3> & p2, \n\t\t      const PointGeomInfo *& geominfo1,\n\t\t      const PointGeomInfo *& geominfo2,\n\t\t      int & qualclass);\n\n  ///\n  int GetLocals (int baseline, \n\t\t NgArray<Point<3>> & locpoints,\n\t\t NgArray<MultiPointGeomInfo> & pgeominfo,\n                 NgArray<INDEX_2> & loclines,   // local index\n                 NgArray<int> & pindex,\n                 NgArray<int> & lindex,\n                 double xh);\n\n  ///\n  void DeleteLine (int li);\n  ///\n  int AddPoint (const Point<3> & p, PointIndex globind, \n                MultiPointGeomInfo * mgi = NULL,\n                bool pointonsurface = true);\n  ///\n  int AddLine (int pi1, int pi2, \n               const PointGeomInfo & gi1, const PointGeomInfo & gi2);\n  ///\n  int ExistsLine (int gpi1, int gpi2);\n\n  ///\n  void IncrementClass (int li)\n  {\n    lines[li].IncrementClass();\n  }\n\n  ///\n  void ResetClass (int li)\n  {\n    lines[li].ResetClass();\n  }\n\n  ///\n  const PointGeomInfo & GetLineGeomInfo (int li, int lend) const\n    { return lines[li].GetGeomInfo (lend); }\n  ///\n\n  PointIndex GetGlobalIndex (int pi) const\n  {\n    return points[pi].GlobalIndex();\n  }\n\n\n  /// is Point p inside Surface (flat geometry only)\n  bool Inside (const Point<2> & p) const;\n\n  bool SameSide (const Point<2> & lp1, const Point<2> & lp2, \n                 const FlatArray<int> * /* testfaces */ = NULL) const;\n  /*\n  {\n    return Inside (lp1) == Inside (lp2);\n  }\n  */\n\n  ///\n  void SetStartFront ();\n  ///\n  void PrintOpenSegments (ostream & ost) const;\n};\n\n} // namespace netgen\n#endif // NETGEN_ADFRONT2_HPP\n"
  },
  {
    "path": "libsrc/meshing/adfront3.cpp",
    "content": "#include <mystdlib.h>\n\n#include <gprim/geomtest3d.hpp>\n#include \"adfront3.hpp\"\n\n/* ********************** FrontPoint ********************** */\n\nnamespace netgen\n{\n\nFrontPoint3 :: FrontPoint3 () \n{ \n  globalindex.Invalidate(); //  = -1;\n  nfacetopoint = 0; \n  frontnr = 1000; \n  cluster = PointIndex::INVALID;\n}\n\n\nFrontPoint3 :: FrontPoint3 (const Point<3> & ap, PointIndex agi)\n{ \n  p = ap; \n  globalindex = agi;\n  nfacetopoint = 0; \n  frontnr = 1000; \n  cluster = PointIndex::INVALID;\n}\n\n\n\n/* ********************** FrontFace ********************** */\n\nFrontFace :: FrontFace () \n{ \n  qualclass = 1; \n  oldfront = 0; \n  hashvalue = 0;\n  cluster = PointIndex::INVALID;\n}\n\nFrontFace :: FrontFace (const MiniElement2d & af)\n{ \n  f = af; \n  oldfront = 0; \n  qualclass = 1; \n  hashvalue = 0;\n}\n\nvoid FrontFace :: Invalidate ()\n{ \n  f.Delete(); \n  oldfront = 0; \n  qualclass = 1000; \n}\n\n\n\n\n/* ********************** AddFront ********************** */\n \n\nAdFront3 :: AdFront3 ()\n{\n  nff = 0;\n  nff4 = 0;\n  vol = 0;\n\n  hashon = 1;\n  hashcreated = 0;\n  if (hashon) \n    hashtable.Init(&points, &faces);\n\n  facetree = NULL;\n  // connectedpairs = NULL;\n\n  rebuildcounter = -1;\n  lasti = 0;\n  minval = -1;\n}\n\n\nAdFront3 :: ~AdFront3 ()\n{\n  delete facetree;\n  // delete connectedpairs;\n}\n\nvoid AdFront3 :: GetPoints (NgArray<Point<3> > & apoints) const\n{\n  /*\n  for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n    \n    apoints.Append (points[pi].P());\n  */\n  for (auto & p : points)\n    apoints.Append(p.P());\n}\n\n\nPointIndex AdFront3 :: AddPoint (const Point<3> & p, PointIndex globind)\n{\n  if (delpointl.Size())\n    {\n      PointIndex pi = delpointl.Last();\n      delpointl.DeleteLast ();\n      \n      points[pi] = FrontPoint3 (p, globind);\n      return pi;\n    }\n  else\n    {\n      points.Append (FrontPoint3 (p, globind));\n      // return --points.End();\n      return *points.Range().end()-1;\n      // return points.Size()-1+PointIndex::BASE;\n    }\n}\n\n\nINDEX AdFront3 :: AddFace (const MiniElement2d & aface)\n{\n  int i, minfn;\n\n  nff++;\n\n  for (i = 0; i < aface.GetNP(); i++)\n    points[aface[i]].AddFace();\n\n  const Point3d & p1 = points[aface[0]].P();\n  const Point3d & p2 = points[aface[1]].P();\n  const Point3d & p3 = points[aface[2]].P();\n\n  vol += 1.0/6.0 * (p1.X() + p2.X() + p3.X()) *\n    ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) -\n      (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) );\n\n  if (aface.GetNP() == 4)\n    {\n      nff4++;\n      const Point3d & p4 = points[aface[3]].P();      \n      vol += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) *\n\t( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) -\n\t  (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) );\n    }\n\n\n  minfn = 1000;\n  for (i = 0; i < aface.GetNP(); i++)\n    {\n      int fpn = points[aface[i]].FrontNr();\n      if (i == 0 || fpn < minfn)\n\tminfn = fpn;\n    }\n\n\n  PointIndex cluster = PointIndex::INVALID;\n  for (i = 1; i <= aface.GetNP(); i++)\n    {\n      if (points[aface.PNum(i)].cluster.IsValid())\n\tcluster = points[aface.PNum(i)].cluster;\n    }\n  for (i = 1; i <= aface.GetNP(); i++)\n    points[aface.PNum(i)].cluster = cluster;\n\n\n  for (i = 1; i <= aface.GetNP(); i++)\n    points[aface.PNum(i)].DecFrontNr (minfn+1);\n  \n  faces.Append(FrontFace (aface));\n  int nfn = faces.Size();\n  faces.Elem(nfn).cluster = cluster;\n\n  if (hashon && hashcreated) \n    hashtable.AddElem(aface, nfn);\n\n  return nfn;\n}\n\n\n\nvoid AdFront3 :: DeleteFace (INDEX fi)\n{\n  nff--;\n\n  /*\n  for (int i = 1; i <= faces.Get(fi).Face().GetNP(); i++)\n    {\n      PointIndex pi = faces.Get(fi).Face().PNum(i);\n  */\n  for (PointIndex pi : faces.Get(fi).Face().PNums())\n    {\n      points[pi].RemoveFace();\n      if (!points[pi].Valid())\n\tdelpointl.Append (pi);\n    }\n\n  const MiniElement2d & face = faces.Get(fi).Face();\n  const Point3d & p1 = points[face.PNum(1)].P();\n  const Point3d & p2 = points[face.PNum(2)].P();\n  const Point3d & p3 = points[face.PNum(3)].P();\n\n  vol -= 1.0/6.0 * (p1.X() + p2.X() + p3.X()) *\n    ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) -\n      (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) );\n\n  if (face.GetNP() == 4)\n    {\n      const Point3d & p4 = points[face.PNum(4)].P();      \n      vol -= 1.0/6.0 * (p1.X() + p3.X() + p4.X()) *\n\t( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) -\n\t  (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) );\n\n      nff4--;\n    }\n\n  faces.Elem(fi).Invalidate();\n}\n\n\nINDEX AdFront3 :: AddConnectedPair (PointIndices<2> apair)\n{\n  if (!connectedpairs)\n    connectedpairs = make_unique<DynamicTable<PointIndex, PointIndex>> (GetNP());\n\n  connectedpairs->Add (apair[0], apair[1]);\n  connectedpairs->Add (apair[1], apair[0]);\n\n  return 0;\n}\n\n\nvoid AdFront3 :: CreateTrees ()\n{\n  int i, j;\n  PointIndex pi;\n  Point3d pmin, pmax;\n\n  for (pi = IndexBASE<PointIndex>(); \n       pi < GetNP()+IndexBASE<PointIndex>(); pi++)\n    {\n      const Point<3> & p = GetPoint(pi);\n      if (pi == IndexBASE<PointIndex>())\n\t{\n\t  pmin = p;\n\t  pmax = p;\n\t}\n      else\n\t{\n\t  pmin.SetToMin (p);\n\t  pmax.SetToMax (p);\n\t}\n    }\n\n  pmax = pmax + 0.5 * (pmax - pmin);\n  pmin = pmin + 0.5 * (pmin - pmax);\n\n  delete facetree;\n  facetree = new BoxTree<3> (pmin, pmax);\n  \n  for (i = 1; i <= GetNF(); i++)\n    {\n      const MiniElement2d & el = GetFace(i);\n      pmin = GetPoint (el[0]);\n      pmax = pmin;\n      for (j = 1; j < 3; j++)\n\t{\n\t  const Point<3> & p = GetPoint (el[j]);\n\t  pmin.SetToMin (p);\n\t  pmax.SetToMax (p);\n\t}\n      pmax = pmax + 0.01 * (pmax - pmin);\n      pmin = pmin + 0.01 * (pmin - pmax);\n      //      (*testout) << \"insert \" << i << \": \" << pmin << \" - \" << pmax << \"\\n\";\n      facetree -> Insert (pmin, pmax, i);\n    }\n}\n\n\nvoid AdFront3 :: GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, \n\t\t\t\t       NgArray<int> & ifaces) const\n{\n  facetree -> GetIntersecting (pmin, pmax, ifaces);\n}\n\nvoid AdFront3 :: GetFaceBoundingBox (int i, Box3d & box) const\n{\n  const FrontFace & face = faces.Get(i);\n  box.SetPoint (points[face.f[0]].p);\n  box.AddPoint (points[face.f[1]].p);\n  box.AddPoint (points[face.f[2]].p);\n}\n\nvoid AdFront3 :: RebuildInternalTables ()\n{\n  static int timer_a = NgProfiler::CreateTimer (\"Adfront3::RebuildInternal A\");\n  static int timer_b = NgProfiler::CreateTimer (\"Adfront3::RebuildInternal B\");\n  static int timer_c = NgProfiler::CreateTimer (\"Adfront3::RebuildInternal C\");\n  static int timer_d = NgProfiler::CreateTimer (\"Adfront3::RebuildInternal D\");\n\n\n  NgProfiler::StartTimer (timer_a);\t  \n  int hi = 0;\n  for (int i = 1; i <= faces.Size(); i++)\n    if (faces.Get(i).Valid())\n      {\n\thi++;\n\tif (hi < i)\n\t  faces.Elem(hi) = faces.Get(i);\n      }\n  \n  faces.SetSize (nff);\n\n  int np = points.Size();\n\n  // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n  for (PointIndex pi : points.Range())\n    points[pi].cluster = pi;\n  \n  NgProfiler::StopTimer (timer_a);\t  \n  NgProfiler::StartTimer (timer_b);\t  \n\n  int change;\n  do\n    {\n      change = 0;\n      for (int i = 1; i <= faces.Size(); i++)\n\t{\n\t  const MiniElement2d & el = faces.Get(i).Face();\n\n\t  PointIndex mini = points[el.PNum(1)].cluster;\n\t  PointIndex maxi = mini;\n\t  \n\t  for (int j = 2; j <= 3; j++)\n\t    {\n\t      PointIndex ci = points[el.PNum(j)].cluster;\n\t      if (ci < mini) mini = ci;\n\t      if (ci > maxi) maxi = ci;\n\t    }\n\n\t  if (mini < maxi)\n\t    {\n\t      change = 1;\n\t      for (int j = 1; j <= 3; j++)\n\t\tpoints[el.PNum(j)].cluster = mini;\n\t    }\n\t}\n    }\n  while (change);\n\n\n  NgProfiler::StopTimer (timer_b);\t  \n  NgProfiler::StartTimer (timer_c);\t  \n\n\n\n\n  Array<bool, PointIndex> usecl(np);\n  usecl = false;\n  for (int i = 1; i <= faces.Size(); i++)\n    {\n      usecl[points[faces.Get(i).Face().PNum(1)].cluster] = true;\n      faces.Elem(i).cluster =\n\tpoints[faces.Get(i).Face().PNum(1)].cluster;\n    }\n  /*\n  int cntcl = 0;\n  for (int i = PointIndex::BASE; \n       i < np+PointIndex::BASE; i++)\n    if (usecl[i])\n      cntcl++;\n  */\n  \n  Array<double, PointIndex> clvol (np);\n  clvol = 0.0;\n\n  for (int i = 1; i <= faces.Size(); i++)\n    {\n      const MiniElement2d & face = faces.Get(i).Face();\n\n      const Point3d p1 = points[face.PNum(1)].P();      \n      const Point3d p2 = points[face.PNum(2)].P();      \n      const Point3d p3 = points[face.PNum(3)].P();      \n      \n      double vi = 1.0/6.0 * (p1.X() + p2.X() + p3.X()) *\n\t( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) -\n\t  (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) );\n      \n      if (face.GetNP() == 4)\n\t{\n\t  const Point3d p4 = points[face.PNum(4)].P();      \n\t  vi += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) *\n\t    ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) -\n\t      (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) );\n\t}\n     \n      clvol[faces.Get(i).cluster] += vi;\n    }\n\n  NgProfiler::StopTimer (timer_c);\t  \n  NgProfiler::StartTimer (timer_d);\t  \n\n\n\n  bool negvol = false;\n  for (auto i : clvol.Range())\n    if (clvol[i] < 0)\n      negvol = true;\n  \n  if (negvol)\n    {\n      for (int i = 1; i <= faces.Size(); i++)\n\tfaces.Elem(i).cluster = IndexBASE<PointIndex>();\n      // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n      for (PointIndex pi : points.Range())\n\tpoints[pi].cluster = IndexBASE<PointIndex>();\n    }\n\n  if (hashon) \n    hashtable.Create();\n\n  NgProfiler::StopTimer (timer_d);\t  \n}\n\n\n\nint AdFront3 :: SelectBaseElement ()\n{\n  /*\n  static int minval = -1;\n  static int lasti = 0;\n  static int counter = 0;\n  */\n  if (rebuildcounter <= 0)\n    {\n      RebuildInternalTables();\n      rebuildcounter = nff / 10 + 1;\n      \n      lasti = 0;\n    }\n  rebuildcounter--;\n\n  /*\n  if (faces.Size() > 2 * nff)\n    {\n      // compress facelist\n\n      RebuildInternalTables ();\n      lasti = 0;\n    }\n    */\n  \n  int fstind = 0;\n\n  for (int i = lasti+1; i <= faces.Size() && !fstind; i++)\n    if (faces.Elem(i).Valid())\n      {\n\tint hi = faces.Get(i).QualClass() +\n\t  points[faces.Get(i).Face().PNum(1)].FrontNr() +\n\t  points[faces.Get(i).Face().PNum(2)].FrontNr() +\n\t  points[faces.Get(i).Face().PNum(3)].FrontNr();\n\t\n\tif (hi <= minval)\n\t  {\n\t    minval = hi;\n\t    fstind = i;\n\t    lasti = fstind;\n\t  }\n      }\n  \n  if (!fstind)\n    {\n      minval = INT_MAX;\n      for (int i = 1; i <= faces.Size(); i++)\n\tif (faces.Elem(i).Valid())\n\t  {\n\t    int hi = faces.Get(i).QualClass() +\n\t      points[faces.Get(i).Face().PNum(1)].FrontNr() +\n\t      points[faces.Get(i).Face().PNum(2)].FrontNr() +\n\t      points[faces.Get(i).Face().PNum(3)].FrontNr();\n\t    \n\t    if (hi <= minval)\n\t      {\n\t\tminval = hi;\n\t\tfstind = i;\n\t\tlasti = 0;\n\t      }\n\t  }\n    }\n\n\n  return fstind;\n}\n\n\n\nint AdFront3 :: GetLocals (int fstind,\n\t\t\t   Array<Point3d, PointIndex> & locpoints,\n\t\t\t   Array<MiniElement2d> & locfaces,   // local index\n\t\t\t   Array<PointIndex, PointIndex> & pindex,\n\t\t\t   Array<INDEX> & findex,\n\t\t\t   INDEX_2_HASHTABLE<int> & getconnectedpairs,\n\t\t\t   float xh,\n\t\t\t   float relh,\n\t\t\t   INDEX& facesplit)\n{\n  // static int timer = NgProfiler::CreateTimer (\"AdFront3::GetLocals\");\n  // NgProfiler::RegionTimer reg (timer);\n\n\n  if (hashon && faces.Size() < 500) { hashon=0; }\n  if (hashon && !hashcreated) \n    {\n      hashtable.Create(); \n      hashcreated=1;\n    }\n\n  INDEX i;\n  PointIndex pstind;\n  Point3d midp, p0;\n\n  //  static NgArray<int, PointIndex::BASE> invpindex;\n  \n  NgArray<MiniElement2d> locfaces2;           //all local faces in radius xh\n  NgArray<int> locfaces3;           // all faces in outer radius relh\n  NgArray<INDEX> findex2;\n\n  locfaces2.SetSize(0);\n  locfaces3.SetSize(0);\n  findex2.SetSize(0);\n\n  PointIndex cluster = faces.Get(fstind).cluster;\n\n  pstind = faces.Get(fstind).Face().PNum(1);\n  p0 = points[pstind].P();\n  \n  locfaces2.Append(faces.Get(fstind).Face());\n  findex2.Append(fstind);\n\n\n  Box3d b1 (p0 - Vec3d(xh, xh, xh), p0 + Vec3d (xh, xh, xh));\n\n  if (hashon)\n    {\n      hashtable.GetLocals(locfaces2, findex2, fstind, p0, xh);\n    }\n  else\n    {\n      for (i = 1; i <= faces.Size(); i++)\n\t{\n\t  const MiniElement2d & face = faces.Get(i).Face();\n\t  if (faces.Get(i).cluster == cluster && faces.Get(i).Valid() && i != fstind)\n\t    {\n\t      Box3d b2;\n\t      b2.SetPoint (points[face[0]].P());\n\t      b2.AddPoint (points[face[1]].P());\n\t      b2.AddPoint (points[face[2]].P());\n\n\t      if (b1.Intersect (b2))\n\t\t{\n\t\t  locfaces2.Append(faces.Get(i).Face());\n\t\t  findex2.Append(i);\n\t\t}\n\t    }\n\t}\n    }\n\n  //local faces for inner radius:\n  for (i = 1; i <= locfaces2.Size(); i++)\n    {\n      const MiniElement2d & face = locfaces2.Get(i);\n      const Point3d & p1 = points[face[0]].P();\n      const Point3d & p2 = points[face[1]].P();\n      const Point3d & p3 = points[face[2]].P();\n\n      midp = Center (p1, p2, p3);\n\n      if (Dist2 (midp, p0) <= relh * relh || i == 1)\n\t{\n          locfaces.Append(locfaces2.Get(i));\n\t  findex.Append(findex2.Get(i));\n\t}\n      else\n\tlocfaces3.Append (i);\n    }\n  \n  facesplit=locfaces.Size();\n  \n  \n  //local faces for outer radius:\n  for (i = 1; i <= locfaces3.Size(); i++)\n    {\n      locfaces.Append (locfaces2.Get(locfaces3.Get(i)));\n      findex.Append (findex2.Get(locfaces3.Get(i)));\n    }\n\n\n  invpindex.SetSize (points.Size());\n  /*\n  for (i = 1; i <= locfaces.Size(); i++)\n    for (j = 1; j <= locfaces.Get(i).GetNP(); j++)\n      {\n\tPointIndex pi = locfaces.Get(i).PNum(j);\n        invpindex[pi] = PointIndex::INVALID;\n      }\n  */\n  for (auto & f : locfaces)\n    for (int j = 1; j <= f.GetNP(); j++)\n      {\n\tPointIndex pi = f.PNum(j);\n        invpindex[pi] = PointIndex::INVALID;\n      }\n\n  // for (i = 1; i <= locfaces.Size(); i++)\n  for (auto & f : locfaces)\n    {\n      // for (j = 1; j <= locfaces.Get(i).GetNP(); j++)\n      for (int j = 1; j <= f.GetNP(); j++)\n\t{\n\t  // PointIndex pi = locfaces.Get(i).PNum(j);\n          PointIndex pi = f.PNum(j);\n\t  if (!invpindex[pi].IsValid())\n\t    {\n\t      pindex.Append (pi);\n              locpoints.Append (points[pi].P());\n\t      invpindex[pi] = pindex.Size()-1+IndexBASE<PointIndex>();\n            }\n          // locfaces.Elem(i).PNum(j) = invpindex[pi];\n          f.PNum(j) = invpindex[pi];          \n\t}\n    }\n\n\n\n  if (connectedpairs)\n    {\n      // for (i = 1; i <= locpoints.Size(); i++)\n      for (auto i : locpoints.Range())\n\t{\n\t  PointIndex pind = pindex[i]; // .Get(i);\n\t  // if (pind.IsValid() && pind <= connectedpairs->Size ())\n          if (connectedpairs->Range().Contains(pind))\n\t    {\n\t      // for (int j = 1; j <= connectedpairs->EntrySize(pind); j++)\n              for (auto j : (*connectedpairs)[pind].Range())\n\t\t{\n\t\t  //PointIndex oi = connectedpairs->Get(pind, j);\n                  PointIndex oi = (*connectedpairs)[pind][j];\n\t\t  PointIndex other = invpindex[oi];\n\t\t  // if (other >= 1 && other <= pindex.Size() &&\n                  if (pindex.Range().Contains(other) &&\n\t\t      pindex[other] == oi)\n\t\t    {\n\t\t      // INDEX_2 coned(i, other);\n\t\t      // coned.Sort();\n\t\t      // (*testout) << \"connected: \" << locpoints.Get(i) << \"-\" << locpoints.Get(other) << endl;\n\t\t      getconnectedpairs.Set (PointIndices<2>::Sort (i, other), 1);\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n  \n\n  /*\n    // add isolated points\n  for (i = 1; i <= points.Size(); i++)\n    if (points.Elem(i).Valid() && Dist (points.Elem(i).P(), p0) <= xh)\n      {\n\tif (!invpindex.Get(i))\n\t  {\n\t    locpoints.Append (points.Get(i).P());\n\t    pindex.Append (i);\n\t    invpindex.Elem(i) = pindex.Size();\n\t  }\n      }\n      */\n  return faces.Get(fstind).QualClass();\n}\n\n\n// returns all points connected with fi\nvoid AdFront3 :: GetGroup (int fi,\n\t\t\t   Array<MeshPoint, PointIndex> & grouppoints,\n\t\t\t   Array<MiniElement2d> & groupelements,\n\t\t\t   Array<PointIndex, PointIndex> & pindex,\n\t\t\t   Array<INDEX> & findex) \n{\n  // static NgArray<char> pingroup;\n  int changed;\n\n  pingroup.SetSize(points.Size());\n\n  pingroup = 0;\n  for (int j = 1; j <= 3; j++)\n    pingroup[faces.Get(fi).Face().PNum(j)] = 1;\n\n  do\n    {\n      changed = 0;\n\n      /*\n      for (i = 1; i <= faces.Size(); i++)\n\tif (faces.Get(i).Valid())\n\t  {\n\t    const MiniElement2d & face = faces.Get(i).Face();\n\n\t    int fused = 0;\n\t    for (j = 1; j <= 3; j++)\n\t      if (pingroup.Elem(face.PNum(j))) \n\t\tfused++;\n            \n\t    if (fused >= 2)\n\t      for (j = 1; j <= 3; j++)\n\t\tif (!pingroup.Elem(face.PNum(j)))\n\t\t  {\n\t\t    pingroup.Elem(face.PNum(j)) = 1;\n\t\t    changed = 1;\n\t\t  }\n\t  }\n      */\n      for (auto & f : faces)\n\tif (f.Valid())\n\t  {\n\t    const MiniElement2d & face = f.Face();\n\n\t    int fused = 0;\n\t    for (int j = 1; j <= 3; j++)\n\t      if (pingroup[face.PNum(j)]) \n\t\tfused++;\n            \n\t    if (fused >= 2)\n\t      for (int j = 1; j <= 3; j++)\n\t\tif (!pingroup[face.PNum(j)])\n\t\t  {\n\t\t    pingroup[face.PNum(j)] = 1;\n\t\t    changed = 1;\n\t\t  }\n\t  }\n\n    }\n  while (changed);\n\n  invpindex.SetSize (points.Size());\n\n  // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n  for (PointIndex pi : points.Range())\n    if (points[pi].Valid())\n      {\n\tgrouppoints.Append (points[pi].P());\n        pindex.Append (pi);\n        // invpindex[pi] = pindex.Size();\n\tinvpindex[pi] = pindex.Size()-1 + IndexBASE<PointIndex>();\n      }\n\n  for (int i = 1; i <= faces.Size(); i++)\n    if (faces.Get(i).Valid())\n      {\n\tint fused = 0;\n\tfor (int j = 1; j <= 3; j++)\n\t  if (pingroup[faces.Get(i).Face().PNum(j)])\n\t    fused++;\n\n\tif (fused >= 2)\n\t  {\n\t    groupelements.Append (faces.Get(i).Face());\n\t    findex.Append (i);\n\t  }\n      }\n\n  /*\n  for (int i = 1; i <= groupelements.Size(); i++)\n    for (int j = 1; j <= 3; j++)\n      {\n\tgroupelements.Elem(i).PNum(j) =\n\t  invpindex.Get(groupelements.Elem(i).PNum(j));\n      }\n  */\n  for (auto & e : groupelements)\n    for (int j = 1; j <= 3; j++)\n      e.PNum(j) = invpindex[e.PNum(j)];\n}\n\n\nvoid AdFront3 :: SetStartFront (int /* baseelnp */)\n{\n  for (INDEX i = 1; i <= faces.Size(); i++)\n    if (faces.Get(i).Valid())\n      {\n\tconst MiniElement2d & face = faces.Get(i).Face();\n\tfor (int j = 1; j <= 3; j++)\n\t  points[face.PNum(j)].DecFrontNr(0);\n      }\n\n  /*\n  if (baseelnp)\n    {\n      for (i = 1; i <= faces.Size(); i++)\n\tif (faces.Get(i).Valid() && faces.Get(i).Face().GetNP() != baseelnp)\n\t  faces.Elem(i).qualclass = 1000;\n    }\n    */\n}\n\nbool AdFront3 :: PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,\n                                  const Array<MiniElement2d> &groupfaces) const\n{\n  for(auto pi : Range(points))\n    {\n      const auto& p = points[pi].P();\n      bool found = false;\n      for(const auto& f : groupfaces)\n        {\n          for(auto i : Range(3))\n            if(grouppindex[f.PNum(i+1)] == pi)\n              {\n                found = true;\n                break;\n              }\n        }\n      if(found)\n        continue;\n\n      // \"random\" direction\n      Vec<3> dir = { 0.123871, 0.15432,-0.43989 };\n      DenseMatrix a(3), ainv(3);\n      Vector b(3), u(3);\n\n      int count = 0;\n      for(const auto& f : groupfaces)\n        {\n          const auto& p1 = points[grouppindex[f.PNum(1)]].P();\n          auto v1 = points[grouppindex[f.PNum(2)]].P() - p1;\n          auto v2 = points[grouppindex[f.PNum(3)]].P() - p1;\n          for(auto i : Range(3))\n            {\n              a(i,0) = v1[i];\n              a(i,1) = v2[i];\n              a(i,2) = -dir[i];\n              b(i) = p[i] - p1[i];\n            }\n          CalcInverse (a, ainv);\n          ainv.Mult (b, u);\n          if (u(0) >= 0 && u(1) >= 0 && u(0)+u(1) <= 1 &&\n\t    u(2) > 0)\n\t    count++;\n        }\n        if (count % 2 == 1)\n          return true;\n    }\n  return false;\n}\n\nbool AdFront3 :: Inside (const Point<3> & p) const\n{\n  static Timer timer(\"AdFront3::Inside\"); RegionTimer rt(timer);\n  int cnt;\n  Vec3d n, v1, v2;\n  DenseMatrix a(3), ainv(3);\n  Vector b(3), u(3);\n\n  // random numbers:\n  n.X() = 0.123871;\n  n.Y() = 0.15432;\n  n.Z() = -0.43989;\n\n  cnt = 0;\n  for (int i = 1; i <= faces.Size(); i++)\n    if (faces.Get(i).Valid())\n      {\n\tconst Point<3> & p1 = points[faces.Get(i).Face().PNum(1)].P();\n\tconst Point<3> & p2 = points[faces.Get(i).Face().PNum(2)].P();\n\tconst Point<3> & p3 = points[faces.Get(i).Face().PNum(3)].P();\n\n\tv1 = p2 - p1;\n\tv2 = p3 - p1;\n\n\ta(0, 0) = v1.X();\n\ta(1, 0) = v1.Y();\n\ta(2, 0) = v1.Z();\n\ta(0, 1) = v2.X();\n\ta(1, 1) = v2.Y();\n\ta(2, 1) = v2.Z();\n\ta(0, 2) = -n.X();\n\ta(1, 2) = -n.Y();\n\ta(2, 2) = -n.Z();\n\n\tb(0) = p(0) - p1(0);\n\tb(1) = p(1) - p1(1);\n\tb(2) = p(2) - p1(2);\n\n\tCalcInverse (a, ainv);\n\tainv.Mult (b, u);\n\n\tif (u(0) >= 0 && u(1) >= 0 && u(0)+u(1) <= 1 &&\n\t    u(2) > 0)\n\t  {\n\t    cnt++;\n\t  }\n      }\n\n  return ((cnt % 2) != 0);\n}\n\n\n\n\n\nint AdFront3 :: SameSide (const Point<3> & lp1, const Point<3> & lp2,\n\t\t\t  const NgArray<int> * testfaces) const\n{\n  const Point<3> *line[2];\n  line[0] = &lp1;\n  line[1] = &lp2;\n\n\n  Point3d pmin(lp1);\n  Point3d pmax(lp1);\n  pmin.SetToMin (lp2);\n  pmax.SetToMax (lp2);\n  \n  NgArrayMem<int, 100> aprif;\n  aprif.SetSize(0);\n  \n  if (!testfaces)\n    facetree->GetIntersecting (pmin, pmax, aprif);\n  else\n    for (int i = 1; i <= testfaces->Size(); i++)\n      aprif.Append (testfaces->Get(i));\n\n  int cnt = 0;\n  for (int ii = 1; ii <= aprif.Size(); ii++)\n    {\n      int i = aprif.Get(ii);\n      \n      if (faces.Get(i).Valid())\n\t{\n\t  const Point<3> *tri[3];\n\t  tri[0] = &points[faces.Get(i).Face().PNum(1)].P();\n\t  tri[1] = &points[faces.Get(i).Face().PNum(2)].P();\n\t  tri[2] = &points[faces.Get(i).Face().PNum(3)].P();\n\t  \t  \n\t  if (IntersectTriangleLine (&tri[0], &line[0]))\n\t    cnt++;\n\t}\n    }\n\n  return ((cnt+1) % 2);\n}\n}\n"
  },
  {
    "path": "libsrc/meshing/adfront3.hpp",
    "content": "#ifndef FILE_ADFRONT3\n#define FILE_ADFRONT3\n\n/**************************************************************************/\n/* File:   adfront3.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\n/*\n  Advancing front class for volume meshing\n*/\n\n#include <gprim/geomobjects.hpp>\n#include <gprim/adtree.hpp>\n#include \"meshtype.hpp\"\n#include \"geomsearch.hpp\"\n\nnamespace netgen\n{\n\n/// Point in advancing front\nclass FrontPoint3\n{\n  /// coordinates\n  Point<3> p;           \n  /// global node index\n  PointIndex globalindex;   \n  /// number of faces connected to point \n  int nfacetopoint;    \n  /// distance to original boundary\n  int frontnr;\n  /// \n  PointIndex cluster;\npublic:\n  ///\n  FrontPoint3 ();\n  ///\n  FrontPoint3 (const Point<3> & ap, PointIndex agi);\n  \n  ///\n  const Point<3> & P () const\n  { return p; }\n  ///\n  PointIndex GlobalIndex () const\n  { return globalindex; }\n  \n  ///\n  void AddFace ()\n  { nfacetopoint++; }\n\n  /// if last face is removed, then point is invalidated\n  void RemoveFace()\n  { \n    nfacetopoint--;\n    if (nfacetopoint == 0) nfacetopoint = -1;\n  }\n  \n  ///\n  bool Valid () const\n  { return nfacetopoint >= 0; }\n\n  ///\n  void DecFrontNr (int afrontnr)\n  {\n    if (frontnr > afrontnr) frontnr = afrontnr;\n  }\n  \n  ///\n  int FrontNr () const\n  { return frontnr; }\n\n  ///\n  friend class AdFront3;\n};\n\n\n\nclass MiniElement2d\n{\nprotected:\n  int np;\n  PointIndex pnum[4]; // can be global or local nums\n  bool deleted;\npublic:\n  MiniElement2d ()\n  { np = 3; deleted = 0; }\n  MiniElement2d (int anp)\n  { np = anp; deleted = 0; }\n\n  int GetNP() const { return np; }\n  PointIndex & operator[] (int i) { return pnum[i]; }\n  const PointIndex operator[] (int i) const { return pnum[i]; }\n\n  const PointIndex PNum (int i) const { return pnum[i-1]; }\n  PointIndex & PNum (int i) { return pnum[i-1]; }\n  const PointIndex PNumMod (int i) const { return pnum[(i-1)%np]; }\n  auto PNums() { return FlatArray<PointIndex> (np, &pnum[0]); }\n  auto PNums() const { return FlatArray<const PointIndex> (np, &pnum[0]); }\n  void Delete () { deleted = true; for (PointIndex & p : pnum) p.Invalidate(); }\n  bool IsDeleted () const { return deleted; }\n};\n\n\ninline ostream & operator<<(ostream  & s, const MiniElement2d & el)\n{\n  s << \"np = \" << el.GetNP();\n  for (int j = 0; j < el.GetNP(); j++)\n    s << \" \" << el[j];\n  return s;\n}\n\n\n\n\n/// Face in advancing front\nclass FrontFace\n{\nprivate:\n  ///\n  MiniElement2d f;\n  ///\n  int qualclass;\n  ///\n  char oldfront;\n  ///\n  int hashvalue;\n  ///\n  PointIndex cluster;\n  \npublic:\n  ///\n  FrontFace ();\n  ///\n  FrontFace (const MiniElement2d & af);\n  ///\n  const MiniElement2d & Face () const\n  { return f; }\n  \n  ///\n  int QualClass () const\n  { return qualclass; }\n\n  ///\n  void IncrementQualClass ()\n  { qualclass++; }\n\n  ///\n  void ResetQualClass ()\n  {\n    if (qualclass > 1)\n      {\n\tqualclass = 1;\n\toldfront = 0;\n      }\n  }\n  \n  ///\n  bool Valid () const\n  { return !f.IsDeleted(); }\n\n  ///\n  void Invalidate ();\n\n  ///\n  int HashValue() const \n  { return hashvalue; }\n\n  ///\n  void SetHashValue(int hv) \n  { hashvalue = hv; }\n\n  ///\n  friend class AdFront3;\n\n  PointIndex Cluster () const { return cluster; }\n};  \n\n\n\n\n/// Advancing front, 3D.\nclass AdFront3\n{\n  ///\n  // NgArray<FrontPoint3, PointIndex::BASE, PointIndex> points;\n  Array<FrontPoint3, PointIndex> points\n;\n  ///\n  NgArray<FrontFace> faces;\n  ///\n  Array<PointIndex> delpointl;\n  \n  /// which points are connected to pi ?\n  // TABLE<PointIndex, PointIndex::BASE> * connectedpairs;\n  unique_ptr<DynamicTable<PointIndex, PointIndex>> connectedpairs;\n  \n  /// number of total front faces;\n  int nff;\n  /// number of quads in front\n  int nff4; \n  \n  ///\n  double vol;\n  \n  ///\n  GeomSearch3d hashtable;\n  \n  /// \n  int hashon;\n\n  ///\n  int hashcreated;\n  \n  /// counter for rebuilding internal tables\n  int rebuildcounter;\n  /// last base element\n  int lasti;\n  /// minimal selection-value of baseelements\n  int minval;\n  Array<PointIndex, PointIndex> invpindex;\n  Array<char, PointIndex> pingroup;\n  \n  ///\n  class BoxTree<3> * facetree;\npublic:\n  \n  ///\n  AdFront3 ();\n  ///\n  ~AdFront3 ();\n  ///\n  void GetPoints (NgArray<Point<3> > & apoints) const;\n  ///\n  int GetNP() const \n  { return points.Size(); }\n  ///\n  const Point<3> & GetPoint (PointIndex pi) const\n  { return points[pi].P(); }\n  ///\n  int GetNF() const\n  { return nff; }\n  /// 1-based\n  const MiniElement2d & GetFace (int i) const\n  { return faces[i-1].Face(); }\n  const auto & Faces() const { return faces; }\n  ///\n  void Print () const;\n  ///\n  bool Empty () const\n  { return nff == 0; }\n  ///\n  bool Empty (int elnp) const\n  {\n    if (elnp == 4)\n      return (nff4 == 0);\n    return (nff - nff4 == 0);\n  }\n  ///\n  int SelectBaseElement ();\n\n  ///\n  void CreateTrees ();\n\n  ///\n  void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, \n\t\t\t     NgArray<int> & ifaces) const;\n\n  bool PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,\n                        const Array<MiniElement2d>& groupfaces) const;\n\n  ///\n  void GetFaceBoundingBox (int i, Box3d & box) const;\n\n  ///\n  int GetLocals (int baseelement,\n\t\t Array<Point3d, PointIndex> & locpoints,\n                 Array<MiniElement2d> & locfaces,   // local index\n                 Array<PointIndex, PointIndex> & pindex,\n                 Array<INDEX> & findex,\n\t\t INDEX_2_HASHTABLE<int> & connectedpairs,\n                 float xh,\n\t\t float relh,\n\t\t INDEX& facesplit);\n  \n  ///\n  void GetGroup (int fi,\n                 Array<MeshPoint, PointIndex> & grouppoints,\n                 Array<MiniElement2d> & groupelements,\n                 Array<PointIndex, PointIndex> & pindex,\n                 Array<INDEX> & findex);\n\n  ///\n  void DeleteFace (INDEX fi);\n  ///\n  PointIndex AddPoint (const Point<3> & p, PointIndex globind);\n  ///\n  INDEX AddFace (const MiniElement2d & e);\n  ///\n  INDEX AddConnectedPair (PointIndices<2> pair);\n  ///\n  void IncrementClass (INDEX fi)\n  { faces[fi-1].IncrementQualClass(); }\n\n  ///\n  void ResetClass (INDEX fi)\n  { faces[fi-1].ResetQualClass(); }\n\n  ///\n  void SetStartFront (int baseelnp = 0);\n\n  /// is Point p inside Surface ?\n  bool Inside (const Point<3> & p) const;\n  /// both points on same side ?\n  int SameSide (const Point<3> & lp1, const Point<3> & lp2, \n\t\tconst NgArray<int> * testfaces = NULL) const;\n\n\n  ///\n  PointIndex GetGlobalIndex (PointIndex pi) const\n  { return points[pi].GlobalIndex(); }\n  ///\n  double Volume () const\n  { return vol; }\n\n\nprivate:\n  void RebuildInternalTables();\n};\n\n} // namespace netgen\n#endif\n"
  },
  {
    "path": "libsrc/meshing/basegeom.cpp",
    "content": "#include <set>\n\n#include <mystdlib.h>\n#include \"meshing.hpp\"\n#include <core/register_archive.hpp>\n\nnamespace netgen\n{\n  struct PointTree\n  {\n      std::map<int, BoxTree<3>> tree;\n      Box<3> bounding_box;\n\n      PointTree( Box<3> bb ) : bounding_box(bb) {}\n\n      void Insert(Point<3> p, PointIndex n, int index)\n      {\n        if(tree.count(index) == 0)\n          tree.emplace(index, bounding_box);\n        tree.at(index).Insert(p, p, n);\n      }\n\n      PointIndex Find(Point<3> p, int index) const\n      {\n          ArrayMem<int, 1> points;\n          tree.at(index).GetIntersecting(p, p, points);\n          if(points.Size()==0)\n              throw Exception(\"cannot find mapped point \" + ToString(p));\n          return points[0];\n      }\n  };\n\n  void ShapeProperties :: DoArchive( Archive & ar )\n  {\n      ar & name & col & maxh & hpref & layer;\n      if(ar.GetVersion(\"netgen\") > \"v6.2.2506-14\")\n          ar & partition & quad_dominated;\n  }\n\n  GeometryRegisterArray& GeometryRegister()\n  {\n    static GeometryRegisterArray geometryregister;\n    return geometryregister;\n  }\n\n  GeometryRegister :: ~GeometryRegister()\n  { ; }\n\n  bool GeometryShape :: IsMappedShape( const GeometryShape & other_, const Transformation<3> & trafo, double tol ) const\n  {\n      throw Exception(\"GeometryShape::IsMappedShape not implemented for class \" + Demangle(typeid(this).name()));\n  }\n\n  bool GeometryVertex :: IsMappedShape( const GeometryShape & other_, const Transformation<3> & trafo, double tol ) const\n  {\n      const auto other_ptr = dynamic_cast<const GeometryVertex*>(&other_);\n      if(!other_ptr)\n          return false;\n\n      return Dist(trafo(GetPoint()), other_ptr->GetPoint()) < tol;\n  }\n\n  bool GeometryEdge :: IsMappedShape( const GeometryShape & other_, const Transformation<3> & trafo, double tol ) const\n  {\n      const auto other_ptr = dynamic_cast<const GeometryEdge*>(&other_);\n      if(!other_ptr)\n          return false;\n      auto & e = *other_ptr;\n      if (IsDegenerated(tol) || e.IsDegenerated(tol))\n        return false;\n\n      if(tol < Dist(trafo(GetCenter()), e.GetCenter()))\n          return false;\n\n      auto v0 = trafo(GetStartVertex().GetPoint());\n      auto v1 = trafo(GetEndVertex().GetPoint());\n      auto w0 = e.GetStartVertex().GetPoint();\n      auto w1 = e.GetEndVertex().GetPoint();\n\n      // have two closed edges, use midpoints to compare\n      if(Dist(v0,v1) < tol && Dist(w0,w1) < tol)\n      {\n          v1 = trafo(GetPoint(0.5));\n          w1 = other_ptr->GetPoint(0.5);\n      }\n\n      return( (Dist(v0, w0) < tol && Dist(v1, w1) < tol) ||\n              (Dist(v0, w1) < tol && Dist(v1, w0) < tol) );\n  }\n\n  bool GeometryFace :: IsMappedShape( const GeometryShape & other_, const Transformation<3> & trafo, double tol ) const\n  {\n      const auto other_ptr = dynamic_cast<const GeometryFace*>(&other_);\n      if(!other_ptr)\n          return false;\n      auto & f = *other_ptr;\n\n      if(tol < Dist(GetCenter(), f.GetCenter()))\n          return false;\n\n      // simple check: check if there is a bijective mapping of mapped edges\n      auto & other_edges = f.edges;\n      if(edges.Size() != other_edges.Size())\n          return false;\n\n      auto nedges = edges.Size();\n      Array<bool> is_mapped(nedges);\n      is_mapped = false;\n\n      for(auto e : edges)\n      {\n          int found_mapping = 0;\n          for(auto other_e : other_edges)\n              if(e->IsMappedShape(*other_e, trafo, tol))\n                  found_mapping++;\n          if(found_mapping != 1)\n              return false;\n      }\n\n      return true;\n  }\n\n  bool GeometryFace :: IsConnectingCloseSurfaces() const\n  {\n    std::map<const GeometryShape*, bool> verts;\n    for(const auto& edge : edges)\n      {\n        verts[&edge->GetStartVertex()] = false;\n        verts[&edge->GetEndVertex()] = false;\n      }\n    for(const auto& [v, is_mapped] : verts)\n      {\n        if(is_mapped)\n          continue;\n        for(const auto& v_ident : v->identifications)\n          {\n            const auto& other = v_ident.to == v ? v_ident.from : v_ident.to;\n            if(v_ident.type == Identifications::CLOSESURFACES &&\n               verts.count(other))\n              {\n                verts[v] = true;\n                verts[other] = true;\n              }\n          }\n      }\n    for(auto& [v, is_mapped] : verts)\n      if(!is_mapped)\n        return false;\n    return true;\n  }\n\n  void GeometryFace :: RestrictHTrig(Mesh& mesh,\n                                     const PointGeomInfo& gi0,\n                                     const PointGeomInfo& gi1,\n                                     const PointGeomInfo& gi2,\n                                     const MeshingParameters& mparam,\n                                     int depth, double h) const\n  {\n    auto p0 = GetPoint(gi0);\n    auto p1 = GetPoint(gi1);\n    auto p2 = GetPoint(gi2);\n    auto longest = (p0-p1).Length();\n    int cutedge = 2;\n    if(auto len = (p0-p2).Length(); len > longest)\n      {\n        longest = len;\n        cutedge = 1;\n      }\n    if(auto len = (p1-p2).Length(); len > longest)\n      {\n        longest = len;\n        cutedge = 0;\n      }\n    PointGeomInfo gi_mid;\n    gi_mid.u = (gi0.u + gi1.u + gi2.u)/3;\n    gi_mid.v = (gi0.v + gi1.v + gi2.v)/3;\n\n    if(depth % 3 == 0)\n      {\n        double curvature = 0.;\n        curvature = max({curvature, GetCurvature(gi_mid),\n                         GetCurvature(gi0), GetCurvature(gi1),\n                         GetCurvature(gi2)});\n        if(curvature < 1e-3)\n          return;\n        double kappa = curvature * mparam.curvaturesafety;\n        h = mparam.maxh * kappa < 1 ? mparam.maxh : 1./kappa;\n        if(h < 1e-4 * longest)\n          return;\n      }\n\n    if(h < longest && depth < 10)\n      {\n        if(cutedge == 0)\n          {\n            PointGeomInfo gi_m;\n            gi_m.u = 0.5 * (gi1.u + gi2.u);\n            gi_m.v = 0.5 * (gi1.v + gi2.v);\n            RestrictHTrig(mesh, gi_m, gi2, gi0, mparam, depth+1, h);\n            RestrictHTrig(mesh, gi_m, gi0, gi1, mparam, depth+1, h);\n          }\n        else if(cutedge == 1)\n          {\n            PointGeomInfo gi_m;\n            gi_m.u = 0.5 * (gi0.u + gi2.u);\n            gi_m.v = 0.5 * (gi0.v + gi2.v);\n            RestrictHTrig(mesh, gi_m, gi1, gi2, mparam, depth+1, h);\n            RestrictHTrig(mesh, gi_m, gi0, gi1, mparam, depth+1, h);\n          }\n        else if(cutedge == 2)\n          {\n            PointGeomInfo gi_m;\n            gi_m.u = 0.5 * (gi0.u + gi1.u);\n            gi_m.v = 0.5 * (gi0.v + gi1.v);\n            RestrictHTrig(mesh, gi_m, gi1, gi2, mparam, depth+1, h);\n            RestrictHTrig(mesh, gi_m, gi2, gi0, mparam, depth+1, h);\n          }\n      }\n    else\n      {\n        auto pmid = GetPoint(gi_mid);\n        for(const auto& p : {p0, p1, p2, pmid})\n          mesh.RestrictLocalH(p, h);\n      }\n  }\n\n  namespace {\n    struct Line\n    {\n      Point<3> p0, p1;\n      inline double Length() const { return (p1-p0).Length(); }\n      inline double Dist(const Line& other) const\n      {\n        Vec<3> n = p1-p0;\n        Vec<3> q = other.p1-other.p0;\n        double nq = n*q;\n        Point<3> p = p0 + 0.5*n;\n        double lambda = (p-other.p0)*n / (nq + 1e-10);\n        if (lambda >= 0 && lambda <= 1)\n          return (p-other.p0-lambda*q).Length();\n        return 1e99;\n      }\n    };\n  }\n\n  void NetgenGeometry :: Clear()\n  {\n      vertices.SetSize0();\n      edges.SetSize0();\n      faces.SetSize0();\n      solids.SetSize0();\n  }\n\n  void NetgenGeometry :: ProcessIdentifications()\n  {\n      for(auto i : Range(vertices))\n          vertices[i]->nr = i;\n      for(auto i : Range(edges))\n          edges[i]->nr = i;\n      for(auto i : Range(faces))\n          faces[i]->nr = i;\n      for(auto i : Range(solids))\n          solids[i]->nr = i;\n\n      auto mirror_identifications = [&] ( auto & shapes )\n      {\n          for(auto i : Range(shapes))\n          {\n              auto &s = shapes[i];\n              s->nr = i;\n              for(auto & ident : s->identifications)\n                if(s.get() == ident.from && s.get() != ident.to)\n                  ident.to->identifications.Append(ident);\n          }\n      };\n\n      auto tol = 1e-8 * bounding_box.Diam();\n      for(auto & f : faces)\n        for(auto & ident: f->identifications)\n          for(auto e : static_cast<GeometryFace*>(ident.from)->edges)\n            for(auto e_other : static_cast<GeometryFace*>(ident.to)->edges)\n              if(ident.trafo && e->IsMappedShape(*e_other, *ident.trafo, tol))\n                e->identifications.Append( {e, e_other, ident.trafo, ident.type, ident.name} );\n\n      for(auto & e : edges)\n        for(auto & ident: e->identifications)\n          {\n              auto & from = static_cast<GeometryEdge&>(*ident.from);\n              auto & to = static_cast<GeometryEdge&>(*ident.to);\n\n              GeometryVertex * pfrom[] = { &from.GetStartVertex(), &from.GetEndVertex() };\n              GeometryVertex * pto[] = { &to.GetStartVertex(), &to.GetEndVertex() };\n\n              if(!ident.trafo) continue;\n\n              // swap points of other edge if necessary\n              Point<3> p_from0 = (*ident.trafo)(from.GetStartVertex().GetPoint());\n              Point<3> p_from1 = (*ident.trafo)(from.GetEndVertex().GetPoint());\n              Point<3> p_to0 = to.GetStartVertex().GetPoint();\n\n              if(Dist(p_from1, p_to0) < Dist(p_from0, p_to0))\n                  swap(pto[0], pto[1]);\n\n              for(auto i : Range(2))\n                  pfrom[i]->identifications.Append( {pfrom[i], pto[i], ident.trafo, ident.type, ident.name} );\n          }\n\n      mirror_identifications(vertices);\n      mirror_identifications(edges);\n      mirror_identifications(faces);\n\n\n      auto find_primary = [&] (auto & shapes)\n      {\n          for(auto &s : shapes)\n              s->primary = s.get();\n\n          bool changed = true;\n\n          while(changed) {\n            changed = false;\n            for(auto &s : shapes)\n            {\n              for(auto & ident : s->identifications)\n              {\n                  bool need_inverse = ident.from == s.get();\n                  auto other = need_inverse ? ident.to : ident.from;\n                  if(other->primary->nr < s->primary->nr)\n                  {\n                      s->primary = other->primary;\n                      if(ident.trafo)\n                      {\n                        auto trafo = *ident.trafo;\n                        if(need_inverse)\n                            trafo = trafo.CalcInverse();\n                        if(!s->primary_to_me)\n                          s->primary_to_me = Transformation<3>( Vec<3>{0., 0., 0.} );\n                        if(!other->primary_to_me)\n                          other->primary_to_me = Transformation<3>( Vec<3>{0., 0., 0.} );\n                        s->primary_to_me->Combine(trafo, *other->primary_to_me);\n                        changed = true;\n                    }\n                  }\n              }\n            }\n          }\n      };\n\n      find_primary(vertices);\n      find_primary(edges);\n      find_primary(faces);\n  }\n\n  void NetgenGeometry :: Analyse(Mesh& mesh,\n                                 const MeshingParameters& mparam) const\n  {\n    static Timer t1(\"SetLocalMeshsize\"); RegionTimer regt(t1);\n    mesh.SetGlobalH(mparam.maxh);\n    mesh.SetMinimalH(mparam.minh);\n\n    mesh.SetLocalH(bounding_box.PMin(), bounding_box.PMax(),\n                   mparam.grading);\n\n    // only set meshsize for edges longer than this\n    double mincurvelength = 1e-3 * bounding_box.Diam();\n\n    if(mparam.uselocalh)\n      {\n        double eps = 1e-10 * bounding_box.Diam();\n        const char* savetask = multithread.task;\n        multithread.task = \"Analyse Edges\";\n\n        // restrict meshsize on edges\n        for(auto i : Range(edges))\n          {\n            multithread.percent = 100. * i/edges.Size();\n            const auto & edge = edges[i];\n            auto length = edge->GetLength();\n            // skip very short edges\n            if(length < mincurvelength)\n              continue;\n            static constexpr int npts = 20;\n            // restrict mesh size based on edge length\n            for(auto i : Range(npts+1))\n              mesh.RestrictLocalH(edge->GetPoint(double(i)/npts), length/mparam.segmentsperedge);\n\n            // restrict mesh size based on edge curvature\n            double t = 0.;\n            auto p_old = edge->GetPoint(t);\n            while(t < 1.-eps)\n              {\n                t += edge->CalcStep(t, 1./mparam.curvaturesafety);\n                if(t < 1.)\n                  {\n                    auto p = edge->GetPoint(t);\n                    auto dist = (p-p_old).Length();\n                    mesh.RestrictLocalH(p, dist);\n                    p_old = p;\n                  }\n              }\n          }\n\n        multithread.task = \"Analyse Faces\";\n        // restrict meshsize on faces\n        for(auto i : Range(faces))\n          {\n            multithread.percent = 100. * i/faces.Size();\n            const auto& face = faces[i];\n            face->RestrictH(mesh, mparam);\n          }\n\n        if(mparam.closeedgefac.has_value())\n          {\n            multithread.task = \"Analyse close edges\";\n            constexpr int sections = 100;\n            Array<Line> lines;\n            lines.SetAllocSize(sections*edges.Size());\n            BoxTree<3> searchtree(bounding_box.PMin(),\n                                  bounding_box.PMax());\n            for(const auto& edge : edges)\n              {\n                if(edge->GetLength() < eps)\n                  continue;\n                double t = 0.;\n                auto p_old = edge->GetPoint(t);\n                auto t_old = edge->GetTangent(t);\n                t_old.Normalize();\n                for(auto i : IntRange(1, sections+1))\n                  {\n                    t = double(i)/sections;\n                    auto p_new = edge->GetPoint(t);\n                    auto t_new = edge->GetTangent(t);\n                    t_new.Normalize();\n                    auto cosalpha = fabs(t_old * t_new);\n                    if((i == sections) || (cosalpha < cos(10./180 * M_PI)))\n                      {\n                        auto index = lines.Append({p_old, p_new});\n                        searchtree.Insert(p_old, p_new, index);\n                        p_old = p_new;\n                        t_old = t_new;\n                      }\n                  }\n              }\n            Array<int> linenums;\n            for(auto i : Range(lines))\n              {\n                const auto& line = lines[i];\n                if(line.Length() < eps) continue;\n                multithread.percent = 100.*i/lines.Size();\n                Box<3> box;\n                box.Set(line.p0);\n                box.Add(line.p1);\n                // box.Increase(max2(mesh.GetH(line.p0), mesh.GetH(line.p1)));\n                box.Increase(line.Length());\n                double mindist = 1e99;\n                linenums.SetSize0();\n                searchtree.GetIntersecting(box.PMin(), box.PMax(),\n                                           linenums);\n                for(auto num : linenums)\n                  {\n                    if(i == num) continue;\n                    const auto & other = lines[num];\n                    if((line.p0 - other.p0).Length2() < eps ||\n                       (line.p0 - other.p1).Length2() < eps ||\n                       (line.p1 - other.p0).Length2() < eps ||\n                       (line.p1 - other.p1).Length2() < eps)\n                      continue;\n                    mindist = min2(mindist, line.Dist(other));\n                  }\n                if(mindist == 1e99) continue;\n                mindist /= *mparam.closeedgefac + 1e-10;\n                if(mindist < 1e-3 * bounding_box.Diam())\n                  {\n                    (*testout) << \"extremely small local h: \" << mindist\n                               << \" --> setting to \" << 1e-3 * bounding_box.Diam() << endl;\n                    (*testout) << \"somewhere near \" << line.p0 << \" - \" << line.p1 << endl\n;\n                    mindist = 1e-3 * bounding_box.Diam();\n                  }\n                mesh.RestrictLocalHLine(line.p0, line.p1, mindist);\n              }\n          }\n        multithread.task = savetask;\n      }\n\n    for(const auto& mspnt : mparam.meshsize_points)\n      mesh.RestrictLocalH(mspnt.pnt, mspnt.h, mspnt.layer);\n\n    mesh.LoadLocalMeshSize(mparam.meshsizefilename);\n  }\n\n  void GeometryEdge :: Divide(const MeshingParameters & mparam, const Mesh & mesh, Array<Point<3>> & points, Array<double> & params)\n  {\n    static Timer tdivedgesections(\"Divide edge sections\");\n    static Timer tdivide(\"Divide Edges\");\n    RegionTimer rt(tdivide);\n    // -------------------- DivideEdge -----------------\n    if(properties.partition)\n      {\n        points.SetSize(properties.partition->Size());\n        params.SetSize(properties.partition->Size()+2);\n        params[0] = 0.0;\n        params.Last() = 1.0;\n        for(auto i : Range(properties.partition->Size()))\n          {\n            params[i+1] = (*properties.partition)[i];\n            points[i] = GetPoint(params[i+1]);\n          }\n        return;\n      }\n\n    tdivedgesections.Start();\n    auto layer = properties.layer;\n    double safety = 0.5*(1.-mparam.grading);\n\n    double lam = 0.0;\n    Point<3> p = GetPoint(0.0);\n    auto old_p = p;\n    Array<double> hvalue, fine_params;\n    hvalue.Append(.0);\n\n    while (lam<1. && hvalue.Size() < 20000) {\n      fine_params.Append(lam);\n      auto h = mesh.GetH(old_p, layer);\n      auto step = safety * h/GetTangent(lam).Length();\n      lam += step;\n      lam = min2(lam, 1.0);\n      p = GetPoint(lam);\n      hvalue.Append((hvalue.Size()==0 ? 0.0 : hvalue.Last()) + 1./h * (p-old_p).Length());\n      old_p = p;\n    }\n\n    fine_params.Append(1.0);\n\n    if(hvalue.Size()==20000 && lam<1.0)\n      cout << \"Warning: Could not divide Edge\" << endl;\n\n    tdivedgesections.Stop();\n\n    // auto n = hvalue.Size()-1;\n    int nsubedges = max2(1, int(floor(hvalue.Last()+0.5)));\n    points.SetSize(nsubedges-1);\n    params.SetSize(nsubedges+1);\n\n    int i1 = 0;\n    for(auto i : Range(1,nsubedges))\n    {\n      auto h_target = i*hvalue.Last()/nsubedges;\n      while(hvalue[i1]<h_target && i1<hvalue.Size())\n        i1++;\n\n      if(i1==hvalue.Size())\n      {\n        points.SetSize(i-1);\n        params.SetSize(i+1);\n        cout << \"divide edge: local h too small\" << endl;\n        break;\n      }\n\n      // interpolate lam between points\n      auto lam0 = fine_params[i1-1];\n      auto lam1 = fine_params[i1];\n      auto h0 = hvalue[i1-1];\n      auto h1 = hvalue[i1];\n\n      auto fac = (h_target-h0)/(h1-h0);\n      auto lam = lam0 + fac*(lam1-lam0);\n      params[i] = lam;\n      points[i-1] = MeshPoint(GetPoint(params[i]));\n    }\n\n    params[0] = 0.;\n    params[nsubedges] = 1.;\n\n    if(params[nsubedges] <= params[nsubedges-1])\n    {\n        cout << \"CORRECTED\" << endl;\n        points.SetSize (nsubedges-2);\n        params.SetSize (nsubedges);\n        params[nsubedges-1] = 1.;\n    }\n  }\n\n  void NetgenGeometry :: FindEdges(Mesh& mesh,\n                                   const MeshingParameters& mparam) const\n  {\n    static Timer t1(\"MeshEdges\"); RegionTimer regt(t1);\n    const char* savetask = multithread.task;\n    multithread.task = \"Mesh Edges\";\n\n    PointTree tree( bounding_box );\n\n    auto & identifications = mesh.GetIdentifications();\n\n    Array<PointIndex> vert2meshpt(vertices.Size());\n    vert2meshpt = PointIndex::INVALID;\n\n    for(auto & vert : vertices)\n      {\n        auto pi = mesh.AddPoint(vert->GetPoint(), vert->properties.layer);\n        vert2meshpt[vert->nr] = pi;\n        mesh[pi].Singularity(vert->properties.hpref);\n        mesh[pi].SetType(FIXEDPOINT);\n        \n        Element0d el(pi, pi-IndexBASE<PointIndex>()+1);\n        el.name = vert->properties.GetName();\n        mesh.SetCD3Name(pi-IndexBASE<PointIndex>()+1, el.name);\n        mesh.pointelements.Append (el);\n      }\n\n    for(auto & vert : vertices)\n        for(auto & ident : vert->identifications)\n            identifications.Add(vert2meshpt[ident.from->nr],\n                                vert2meshpt[ident.to->nr],\n                                ident.name,\n                                ident.type);\n\n    // size_t segnr = 0;\n    auto nedges = edges.Size();\n    Array<Array<PointIndex>> all_pnums(nedges);\n    Array<Array<double>> all_params(nedges);\n\n    for (auto edgenr : Range(edges))\n    {\n        auto edge = edges[edgenr].get();\n        PointIndex startp, endp;\n        // throws if points are not found\n        startp = vert2meshpt[edge->GetStartVertex().nr];\n        endp = vert2meshpt[edge->GetEndVertex().nr];\n\n        // ignore collapsed edges\n        if(edge->IsDegenerated())\n          continue;\n\n        // ----------- Add Points to mesh and create segments -----\n        auto & pnums = all_pnums[edgenr];\n        auto & params = all_params[edgenr];\n        Array<Point<3>> edge_points;\n        Array<double> edge_params;\n\n        if(edge->primary == edge)\n        {\n            // check if start and end vertex are identified (if so, we only insert one segment and do z-refinement later)\n            bool is_identified_edge = false;\n            auto v0 = vertices[edge->GetStartVertex().nr].get();\n            auto v1 = vertices[edge->GetEndVertex().nr].get();\n            for(auto & ident : v0->identifications)\n            {\n                auto other = ident.from == v0 ? ident.to : ident.from;\n                if(other->nr == v1->nr && ident.type == Identifications::CLOSESURFACES)\n                {\n                    is_identified_edge = true;\n                    break;\n                }\n            }\n\n            if(is_identified_edge)\n            {\n                params.SetSize(2);\n                params[0] = 0.;\n                params[1] = 1.;\n            }\n            else\n            {\n                edge->Divide(mparam, mesh, edge_points, params);\n            }\n        }\n        else\n        {\n            auto nr_primary = edge->primary->nr;\n            auto & pnums_primary = all_pnums[nr_primary];\n            // auto & params_primary = all_params[nr_primary];\n            auto trafo = edge->primary_to_me;\n\n            auto np = pnums_primary.Size();\n            edge_points.SetSize(np-2);\n            edge_params.SetSize(np-2);\n            for(auto i : Range(np-2))\n            {\n                edge_points[i] = mesh[pnums_primary[i+1]];\n                if(trafo)\n                  edge_points[i] = (*trafo)(edge_points[i]);\n                EdgePointGeomInfo gi;\n                edge->ProjectPoint(edge_points[i], &gi);\n                edge_params[i] = gi.dist;\n            }\n\n            params.SetSize(edge_params.Size()+2);\n\n            for(auto i : Range(edge_params))\n                params[i+1] = edge_params[i];\n\n            if(edge_params.Size()>1)\n            {\n              // Just projecting (code below) does not work for closed edges (startp == endp)\n              // In this case, there are at least 2 inner points which we use to check edge orientation\n              bool reversed = edge_params[1] < edge_params[0];\n              if(reversed)\n              {\n                params[0] = 1.0;\n                params.Last() = 0.0;\n              }\n              else\n              {\n                params.Last() = 1.0;\n                params[0] = 0.0;\n              }\n            }\n            else\n            {\n              for(size_t i : std::vector{0UL, pnums_primary.Size()-1})\n              {\n                auto p_mapped = mesh[pnums_primary[i]];\n                if(trafo) p_mapped = (*trafo)(p_mapped);\n                EdgePointGeomInfo gi;\n                edge->ProjectPoint(p_mapped, &gi);\n                params[i] = gi.dist;\n              }\n            }\n        }\n\n        pnums.SetSize(edge_points.Size() + 2);\n\n        bool is_reversed = params.Last() < params[0];\n        pnums[0] = is_reversed ? endp : startp;\n        pnums.Last() = is_reversed ? startp : endp;\n\n\n        for(auto i : Range(edge_points))\n        {\n            auto pi = mesh.AddPoint(edge_points[i], edge->properties.layer);\n            if(edge->identifications.Size())\n              tree.Insert(mesh[pi], pi, edge->nr);\n            pnums[i+1] = pi;\n        }\n\n        for(auto i : Range(pnums.Size()-1))\n        {\n          // segnr++;\n            Segment seg;\n            seg[0] = pnums[i];\n            seg[1] = pnums[i+1];\n            seg.edgenr = edgenr+1;\n            seg.index = edgenr+1;\n            seg.si = edgenr+1;\n            seg.epgeominfo[0].dist = params[i];\n            seg.epgeominfo[1].dist = params[i+1];\n            seg.epgeominfo[0].edgenr = edgenr;\n            seg.epgeominfo[1].edgenr = edgenr;\n            seg.singedge_left = edge->properties.hpref;\n            seg.singedge_right = edge->properties.hpref;\n            seg.domin = edge->domin+1;\n            seg.domout = edge->domout+1;\n            mesh.AddSegment(seg);\n        }\n        mesh.SetCD2Name(edgenr+1, edge->properties.GetName());\n    }\n\n    for (auto & edge : edges)\n    {\n        // identify points on edge\n        for(auto & ident : edge->identifications)\n          if(ident.from == edge.get())\n          {\n            auto & pnums = all_pnums[edge->nr];\n            if(pnums.Size() < 2) continue; // degenerated edge\n            // start and end vertex are already identified\n            for(auto pi : pnums.Range(1, pnums.Size()-1))\n            {\n                Point<3> p_other = mesh[pi];\n                if(ident.trafo)\n                  p_other = (*ident.trafo)(mesh[pi]);\n                else\n                  static_cast<GeometryEdge*>(ident.to)->ProjectPoint(p_other, nullptr);\n                auto pi_other = tree.Find(p_other, ident.to->nr);\n                identifications.Add(pi, pi_other, ident.name, ident.type);\n            }\n          }\n    }\n    mesh.CalcSurfacesOfNode();\n    multithread.task = savetask;\n  }\n\n  bool NetgenGeometry :: MeshFace(Mesh& mesh, const MeshingParameters& mparam,\n                     int k, FlatArray<int, PointIndex> glob2loc) const\n  {\n    multithread.percent = 100. * k/faces.Size();\n    const auto& face = *faces[k];\n    auto bb = face.GetBoundingBox();\n    bb.Increase(bb.Diam()/10);\n    Meshing2 meshing(*this, mparam, bb);\n    glob2loc = 0;\n    int cntp = 0;\n\n    auto segments = face.GetBoundary(mesh);\n    for(auto& seg : segments)\n      {\n        for(auto j : Range(2))\n          {\n            auto pi = seg[j];\n            if(glob2loc[pi] == 0)\n              {\n                meshing.AddPoint(mesh[pi], pi);\n                cntp++;\n                glob2loc[pi] = cntp;\n              }\n          }\n      }\n    for(const auto& vert : GetFaceVertices(face))\n      {\n        PointIndex pi = vert->nr + 1;\n        if(glob2loc[pi] == 0)\n          {\n            auto gi = face.Project(mesh[pi]);\n            MultiPointGeomInfo mgi;\n            mgi.AddPointGeomInfo(gi);\n            meshing.AddPoint(mesh[pi], pi, &mgi);\n            cntp++;\n            glob2loc[pi] = cntp;\n          }\n      }\n    for(auto & seg : segments)\n      {\n        PointGeomInfo gi0, gi1;\n        gi0.trignum = gi1.trignum = k+1;\n        gi0.u = seg.epgeominfo[0].u;\n        gi0.v = seg.epgeominfo[0].v;\n        gi1.u = seg.epgeominfo[1].u;\n        gi1.v = seg.epgeominfo[1].v;\n        meshing.AddBoundaryElement(glob2loc[seg[0]],\n                                   glob2loc[seg[1]],\n                                   gi0, gi1);\n      }\n\n    // TODO Set max area 2* area of face\n\n    auto noldsurfels = mesh.GetNSE();\n\n\n    static Timer t(\"GenerateMesh\"); RegionTimer reg(t);\n    MESHING2_RESULT res = meshing.GenerateMesh(mesh, mparam, mparam.maxh, k+1, face.properties.layer);\n\n    for(auto i : Range(noldsurfels, mesh.GetNSE()))\n      {\n        mesh.SurfaceElements()[i].SetIndex(k+1);\n      }\n    return res != MESHING2_OK;\n  }\n\n  void NetgenGeometry :: MeshSurface(Mesh& mesh,\n                                     const MeshingParameters& mparam) const\n  {\n    static Timer t1(\"Surface Meshing\"); RegionTimer regt(t1);\n    const char* savetask = multithread.task;\n    multithread.task = \"Mesh Surface\";\n    mesh.ClearFaceDescriptors();\n\n    size_t n_failed_faces = 0;\n    Array<int, PointIndex> glob2loc(mesh.GetNP());\n    for(auto k : Range(faces))\n    {\n        auto & face = *faces[k];\n        FaceDescriptor fd(k+1, face.domin+1, face.domout+1, k+1);\n        if(face.properties.col)\n          fd.SetSurfColour(*face.properties.col);\n        mesh.AddFaceDescriptor(fd);\n        mesh.SetBCName(k, face.properties.GetName());\n        if(face.primary == &face)\n        {\n            // check if this face connects two identified closesurfaces\n            // auto & idents = mesh.GetIdentifications();\n            std::set<int> relevant_edges;\n            auto segments = face.GetBoundary(mesh);\n            for(const auto &s : segments)\n                relevant_edges.insert(s.edgenr-1);\n\n            Array<bool, PointIndex> is_point_in_tree(mesh.Points().Size());\n            is_point_in_tree = false;\n            PointTree tree( bounding_box );\n            for(const auto &s : segments)\n                for(auto pi : s.PNums())\n                    if(!is_point_in_tree[pi])\n                    {\n                        tree.Insert(mesh[pi], pi, -1);\n                        is_point_in_tree[pi] = true;\n                    }\n\n            Array<int> mapped_edges(edges.Size());\n            constexpr int UNINITIALIZED = -2;\n            constexpr int NOT_MAPPED = -1;\n            mapped_edges = UNINITIALIZED;\n\n            optional<Transformation<3>> trafo;\n\n            if(face.IsConnectingCloseSurfaces())\n            {\n                Array<ArrayMem<int, 2>, PointIndex> p2seg(mesh.Points().Size());\n                for(int si : Range(segments))\n                {\n                    const auto & s = segments[si];\n                    p2seg[s[0]].Append(si);\n                    p2seg[s[1]].Append(si);\n                }\n                for(const auto & s : segments)\n                {\n                    auto edgenr = s.edgenr-1;\n                    auto & edge = *edges[edgenr];\n                    // ShapeIdentification *edge_mapping;\n\n                    // have edgenr first time, search for closesurface identification\n\n                    if(mapped_edges[edgenr] == UNINITIALIZED)\n                    {\n                        mapped_edges[edgenr] = NOT_MAPPED;\n                        for(auto & edge_ident : edge.identifications)\n                        {\n                            if(edge_ident.type == Identifications::CLOSESURFACES &&\n                                    edge_ident.from->nr == edgenr &&\n                                    relevant_edges.count(edge_ident.to->nr) > 0\n                              )\n                            {\n                                trafo = edge_ident.trafo;\n                                mapped_edges[edgenr] = edge_ident.to->nr;\n                                break;\n                            }\n                        }\n                    }\n\n                    // this edge has a closesurface mapping to another -> make connecting quad\n                    if(mapped_edges[edgenr] != NOT_MAPPED)\n                    {\n                        Element2d sel(4);\n                        sel[0] = s[0];\n                        sel[1] = s[1];\n                        auto gis = sel.GeomInfo();\n                        for(auto i : Range(2))\n                        {\n                            gis[i].u = s.epgeominfo[i].u;\n                            gis[i].v = s.epgeominfo[i].v;\n                        }\n\n                        Point<3> p2 = mesh[s[1]];\n                        Point<3> p3 = mesh[s[0]];\n                        if(trafo)\n                        {\n                          p2 = (*trafo)(p2);\n                          p3 = (*trafo)(p3);\n                        }\n                        else \n                        {\n                          edges[mapped_edges[edgenr]]->ProjectPoint(p2, nullptr);\n                          edges[mapped_edges[edgenr]]->ProjectPoint(p3, nullptr);\n                        }\n                        sel[2] = tree.Find(p2, -1);\n                        sel[3] = tree.Find(p3, -1);\n\n                        // find mapped segment to set PointGeomInfo correctly\n                        Segment s_other;\n                        for(auto si_other : p2seg[sel[2]])\n                        {\n                            s_other = segments[si_other];\n                            if(s_other[0] == sel[2] && s_other[1] == sel[3])\n                                break;\n                            if(s_other[0] == sel[3] && s_other[1] == sel[2])\n                                break;\n                        }\n                        for(auto i : Range(2))\n                        {\n                            auto i_other = sel[i+2] == s_other[i] ? i : 1-i;\n                            gis[i+2].u = s_other.epgeominfo[i_other].u;\n                            gis[i+2].v = s_other.epgeominfo[i_other].v;\n                        }\n\n                        sel.SetIndex(face.nr+1);\n                        mesh.AddSurfaceElement(sel);\n                    }\n                }\n            }\n            else\n                if(MeshFace(mesh, mparam, k, glob2loc))\n                    n_failed_faces++;\n        }\n    }\n\n    if(n_failed_faces) \n    {\n        cout << \"WARNING! NOT ALL FACES HAVE BEEN MESHED\" << endl;\n        cout << \"SURFACE MESHING ERROR OCCURRED IN \" << n_failed_faces << \" FACES:\" << endl;\n        return;\n    }\n\n    if (mparam.perfstepsend >= MESHCONST_OPTSURFACE)\n    {\n      mesh.CalcSurfacesOfNode();\n      OptimizeSurface(mesh, mparam);\n    }\n\n    bool have_identifications = false;\n    std::map<tuple<PointIndex, int>, PointIndex> mapto;\n    for(auto & face : faces)\n        if(face->primary != face.get())\n        {\n            have_identifications = true;\n            MapSurfaceMesh(mesh, *face, mapto);\n        }\n\n    // identify points on faces\n    if(have_identifications)\n    {\n        mesh.CalcSurfacesOfNode();\n        BitArray is_identified_face(faces.Size());\n        is_identified_face = false;\n        for(auto & face : faces)\n            for(auto & ident : face->identifications)\n            {\n                is_identified_face.SetBit(ident.from->nr);\n                is_identified_face.SetBit(ident.to->nr);\n            }\n\n        PointTree tree( bounding_box );\n        Array<int, PointIndex> pi_to_face(mesh.GetNP());\n        pi_to_face = -1;\n        Array<SurfaceElementIndex> si_of_face;\n        Array<Array<PointIndex>> pi_of_face(faces.Size());\n        for(auto & face : faces)\n            if(is_identified_face[face->nr])\n            {\n                mesh.GetSurfaceElementsOfFace(face->nr+1, si_of_face);\n                for(auto si : si_of_face)\n                    for(auto pi : mesh[si].PNums())\n                    {\n                        if(mesh[pi].Type() == SURFACEPOINT && pi_to_face[pi]==-1)\n                        {\n                            pi_to_face[pi] = face->nr;\n                            tree.Insert(mesh[pi], pi, -1);\n                            pi_of_face[face->nr].Append(pi);\n                        }\n                    }\n            }\n\n        auto & mesh_ident = mesh.GetIdentifications();\n        for(auto & face : faces)\n            for(auto & ident : face->identifications)\n            {\n                if(ident.from == face.get())\n                    for(auto pi : pi_of_face[face->nr])\n                    {\n                        auto pi_primary = ident.from->primary->nr == ident.from->nr ? pi : mapto[{pi, ident.to->primary->nr}];\n                        auto pi_other = ident.to->primary->nr == ident.to->nr ? pi_primary : mapto[{pi_primary, ident.to->nr}];\n                        mesh_ident.Add(pi, pi_other, ident.name, ident.type);\n                    }\n            }\n    }\n\n    mesh.CalcSurfacesOfNode();\n    multithread.task = savetask;\n  }\n\n  void NetgenGeometry :: MapSurfaceMesh( Mesh & mesh, const GeometryFace & dst, std::map<tuple<PointIndex, int>, PointIndex> & mapto ) const\n  {\n    static Timer timer(\"MapSurfaceMesh\");\n    RegionTimer rt(timer);\n\n    const auto & src = dynamic_cast<const GeometryFace&>(*dst.primary);\n    auto trafo = dst.primary_to_me;\n\n    PrintMessage(2, \"Map face \", src.nr+1, \" -> \", dst.nr+1);\n\n    // point map from src to dst\n    auto np = mesh.Points().Size();\n    Array<PointIndex, PointIndex> pmap(np);\n    pmap = PointIndex::INVALID;\n    BitArray is_double_edge_point(np);\n    is_double_edge_point.Clear();\n\n    // first map points on edges (mapped points already in mesh, use search tree)\n    Array<bool, PointIndex> is_point_in_tree(mesh.Points().Size());\n    is_point_in_tree = false;\n    PointTree tree( bounding_box );\n    for (Segment & seg : src.GetBoundary(mesh))\n        for(auto i : Range(2))\n          {\n            auto pi = seg[i];\n            if(!is_point_in_tree[pi])\n            {\n              auto p = mesh[pi];\n              if(trafo)\n                p = (*trafo)(p);\n              else\n                for(auto& edge: dst.edges)\n                  if (edge->primary->nr == seg.edgenr-1)\n                    {\n                      if (mesh[pi].Type() == FIXEDPOINT) {\n                        if((edge->GetStartVertex().GetPoint() - p).Length2() >\\\n                           (edge->GetEndVertex().GetPoint() - p).Length2())\n                          p = edge->GetEndVertex().GetPoint();\n                        else\n                          p = edge->GetStartVertex().GetPoint();\n                      }\n                      else\n                        edge->ProjectPoint(p, nullptr);\n                    }\n              tree.Insert(p, pi, -1);\n              is_point_in_tree[pi] = true;\n            }\n          }\n\n    Array<ArrayMem<tuple<double,double>, 2>, PointIndex> uv_values(np);\n    for (Segment & seg : dst.GetBoundary(mesh))\n    {\n        for(auto i : Range(2))\n          {\n            auto pi = seg[i];\n            if(!pmap[pi].IsValid())\n              pmap[tree.Find(mesh[pi], -1)] = pi;\n\n            // store uv values (might be different values for same point in case of internal edges)\n            double u = seg.epgeominfo[i].u;\n            double v = seg.epgeominfo[i].v;\n            auto & vals = uv_values[pi];\n            bool found = false;\n            for(const auto & [u1,v1] : vals)\n                if((u-u1)*(u-u1)+(v-v1)*(v-v1) < 1e-7)\n                    found = true;\n            if(!found)\n                vals.Append({u,v});\n          }\n    }\n\n    xbool do_invert = maybe;\n    if(!trafo) do_invert = true;\n\n    // now insert mapped surface elements\n    for(auto sei : mesh.SurfaceElements().Range())\n      {\n        auto sel = mesh[sei];\n        if(sel.GetIndex() != src.nr+1)\n          continue;\n\n        auto sel_new = sel;\n        sel_new.SetIndex(dst.nr+1);\n        for(auto i : Range(sel.PNums()))\n          {\n            auto pi = sel[i];\n            if(!pmap[pi].IsValid())\n              {\n                auto p = mesh[pi];\n                if(trafo)\n                  p = (*trafo)(p);\n                else\n                  dst.Project(p);\n                pmap[pi] = mesh.AddPoint(p, 1, SURFACEPOINT);\n              }\n              sel_new[i] = pmap[pi];\n              mapto[{pi, dst.nr}] = pmap[pi];\n              mapto[{pmap[pi], src.nr}] = pi;\n          }\n        if(do_invert.IsMaybe())\n        {\n            auto n_src = src.GetNormal(mesh[sel[0]]);\n            auto n_dist = dst.GetNormal(mesh[sel_new[0]]);\n            Mat<3> normal_matrix;\n            CalcInverse(Trans(trafo->GetMatrix()), normal_matrix);\n            do_invert = (normal_matrix * n_src) * n_dist < 0.0;\n        }\n        if(do_invert.IsTrue())\n            sel_new.Invert();\n\n        for(auto i : Range(sel.PNums()))\n        {\n            auto pi = sel_new[i];\n            if(uv_values.Range().Next() <= pi)\n            {\n                // new point (inner surface point)\n                PointGeomInfo gi;\n                dst.CalcPointGeomInfo(mesh[sel_new[i]], gi);\n                sel_new.GeomInfo()[i] = gi;\n                continue;\n            }\n\n            const auto & uvs = uv_values[pi];\n            if(uvs.Size() == 1)\n            {\n                // appears only once -> take uv values from edgepointgeominfo\n                const auto & [u,v] = uvs[0];\n                PointGeomInfo gi;\n                gi.u = u;\n                gi.v = v;\n                sel_new.GeomInfo()[i] = gi;\n            }\n            else if(uvs.Size() > 1)\n            {\n                // multiple uv pairs -> project to close point and select closest uv pair\n                double eps = 1e-3;\n                auto p = Point<3>((1.0-eps)*Vec<3>(mesh[sel_new.PNumMod(i+1)]) +\n                                      eps/2*Vec<3>(mesh[sel_new.PNumMod(i+2)]) +\n                                      eps/2*Vec<3>(mesh[sel_new.PNumMod(i+3)]));\n                PointGeomInfo gi_p, gi;\n                dst.CalcPointGeomInfo(p, gi_p);\n                gi.trignum = gi_p.trignum;\n                double min_dist = numeric_limits<double>::max();\n                for(const auto & [u,v] : uvs)\n                {\n                    double dist = (gi_p.u-u)*(gi_p.u-u) + (gi_p.v-v)*(gi_p.v-v);\n                    if(dist < min_dist)\n                    {\n                        min_dist = dist;\n                        gi.u = u;\n                        gi.v = v;\n                    }\n                }\n                sel_new.GeomInfo()[i] = gi;\n            }\n            else\n                throw Exception(string(__FILE__) + \":\"+ToString(__LINE__) + \" shouldn't come here\");\n          }\n          mesh.AddSurfaceElement(sel_new);\n      }\n  }\n\n  void NetgenGeometry :: OptimizeSurface(Mesh& mesh, const MeshingParameters& mparam) const\n  {\n    const auto savetask = multithread.task;\n    multithread.task = \"Optimizing surface\";\n\n    static Timer timer_opt2d(\"Optimization 2D\");\n    RegionTimer reg(timer_opt2d);\n    auto meshopt = MeshOptimize2d(mesh);\n    for(auto i : Range(mparam.optsteps2d))\n    for(auto k : Range(mesh.GetNFD()))\n      {\n        PrintMessage(3, \"Optimization step \", i);\n        meshopt.SetFaceIndex(k+1);\n        meshopt.SetMetricWeight (mparam.elsizeweight);\n        int innerstep = 0;\n        for(auto optstep : mparam.optimize2d)\n          {\n            multithread.percent = 100. * (double(innerstep++)/mparam.optimize2d.size() + i)/mparam.optsteps2d;\n            switch(optstep)\n              {\n              case 's':\n                meshopt.EdgeSwapping(0);\n                break;\n              case 'S':\n                meshopt.EdgeSwapping(1);\n                break;\n              case 'm':\n                meshopt.ImproveMesh(mparam);\n                break;\n              case 'c':\n                meshopt.CombineImprove();\n                break;\n              }\n          }\n      }\n    mesh.CalcSurfacesOfNode();\n    mesh.Compress();\n    multithread.task = savetask;\n  }\n\n  void NetgenGeometry :: FinalizeMesh(Mesh& mesh) const\n  {\n      for (int i = 0; i < std::min(solids.Size(), (size_t)mesh.GetNDomains()); i++)\n        if (auto name = solids[i]->properties.name)\n          mesh.SetMaterial (i+1, *name);\n\n    mesh.OrderElements();\n  }\n  \n  shared_ptr<NetgenGeometry> GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const\n  {\n    if (!ist.good())\n        return nullptr;\n\n    string token;\n    ist >> token;\n    if(token == \"TextOutArchive\")\n    {\n        NetgenGeometry *geo = nullptr;\n        size_t string_length;\n        ist >> string_length;\n        string buffer(string_length+1, '\\0');\n        ist.read(&buffer[0], string_length);\n        auto ss = make_shared<stringstream>(buffer);\n        TextInArchive in(ss);\n        in & geo;\n\n        return shared_ptr<NetgenGeometry>(geo);\n    }\n    for (int i = 0; i < Size(); i++)\n      {\n        NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist, token);\n        if (hgeom)\n          return shared_ptr<NetgenGeometry>(hgeom);\n      }\n    return nullptr;\n  }\n\n\n\n  \n  int NetgenGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mp)\n  {\n    multithread.percent = 0;\n\n    // copy so that we don't change them outside\n    MeshingParameters mparam = mp;\n    if(restricted_h.Size())\n      for(const auto& [pnt, maxh] : restricted_h)\n        mparam.meshsize_points.Append({pnt, maxh});\n\n    if(mparam.perfstepsstart <= MESHCONST_ANALYSE)\n      {\n        if(!mesh)\n          mesh = make_shared<Mesh>();\n        mesh->geomtype = GetGeomType();\n        Analyse(*mesh, mparam);\n      }\n\n    if(multithread.terminate || mparam.perfstepsend <= MESHCONST_ANALYSE)\n      return 0;\n\n    if(mparam.perfstepsstart <= MESHCONST_MESHEDGES)\n      FindEdges(*mesh, mparam);\n\n    if(multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)\n      return 0;\n\n    if(dimension == 1)\n      {\n        FinalizeMesh(*mesh);\n        mesh->SetDimension(1);\n        return 0;\n      }\n\n    if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)\n      {\n        MeshSurface(*mesh, mparam);\n      }\n\n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_OPTSURFACE)\n      return 0;\n\n    if(dimension == 2)\n    {\n        FinalizeMesh(*mesh);\n        mesh->SetDimension(2);\n        return 0;\n    }\n\n    if(mparam.perfstepsstart <= MESHCONST_MESHVOLUME)\n      {\n        multithread.task = \"Volume meshing\";\n\n        MESHING3_RESULT res = MeshVolume (mparam, *mesh);\n\n        if (res != MESHING3_OK) return 1;\n        if (multithread.terminate) return 0;\n\n        MeshQuality3d (*mesh);\n      }\n\n    if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME)\n      return 0;\n\n\n    if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME)\n      {\n\tmultithread.task = \"Volume optimization\";\n\n\tOptimizeVolume (mparam, *mesh);\n\tif (multithread.terminate) return 0;\n      }\n    FinalizeMesh(*mesh);\n    return 0;\n  }\n\n  void NetgenGeometry :: Save (const filesystem::path & filename) const\n  {\n    throw NgException(\"Cannot save geometry - no geometry available\");\n  }\n\n  static RegisterClassForArchive<NetgenGeometry> regnggeo;\n}\n"
  },
  {
    "path": "libsrc/meshing/basegeom.hpp",
    "content": "#ifndef FILE_BASEGEOM\n#define FILE_BASEGEOM\n\n/**************************************************************************/\n/* File:   basegeom.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   23. Aug. 09                                                    */\n/**************************************************************************/\n\n#include <gprim/geomobjects.hpp>\n#include <gprim/transform3d.hpp>\n\n#include \"meshtype.hpp\"\n#include \"meshclass.hpp\"\n\nstruct Tcl_Interp;\n\nnamespace netgen\n{\n  class Refinement;\n\n  struct ShapeProperties\n  {\n    optional<string> name;\n    optional<Vec<4>> col;\n    double maxh = 1e99;\n    double hpref = 0;  // number of hp refinement levels (will be multiplied by factor later)\n    int layer = 1;\n    optional<bool> quad_dominated;\n    optional<Array<double>> partition;\n    void Merge(const ShapeProperties & prop2)\n    {\n      if (!name && prop2.name) name = prop2.name;\n      if (!col && prop2.col) col = prop2.col;\n      if (!partition && prop2.partition) partition = prop2.partition;\n      maxh = min2(maxh, prop2.maxh);\n      hpref = max2(hpref, prop2.hpref);\n      if(!quad_dominated.has_value()) quad_dominated = prop2.quad_dominated;\n      layer = max(layer, prop2.layer);\n    }\n\n    string GetName() const { return name ? *name : \"default\"; }\n    Vec<4> GetColor() { return col ? *col : Vec<4>{0., 1., 0., 1.}; }\n\n    void DoArchive(Archive& ar);\n  };\n\n  class GeometryShape;\n\n  struct ShapeIdentification\n  {\n    GeometryShape * from;\n    GeometryShape * to;\n    optional<Transformation<3>> trafo;\n    Identifications::ID_TYPE type;\n    string name = \"\";\n  };\n\n  class DLL_HEADER GeometryShape\n  {\n  public:\n    int nr = -1;\n    int layer = 1;\n    ShapeProperties properties;\n    Array<ShapeIdentification> identifications;\n    GeometryShape * primary;\n    optional<Transformation<3>> primary_to_me = nullopt;\n\n    virtual ~GeometryShape() {}\n    virtual bool IsMappedShape( const GeometryShape & other, const Transformation<3> & trafo, double tolerance ) const;\n  };\n\n\n  class DLL_HEADER GeometryVertex : public GeometryShape\n  {\n  public:\n    virtual Point<3> GetPoint() const = 0;\n    virtual bool IsMappedShape( const GeometryShape & other, const Transformation<3> & trafo, double tolerance ) const override;\n  };\n\n  class DLL_HEADER GeometryEdge : public GeometryShape\n  {\n  protected:\n      GeometryVertex *start, *end;\n  public:\n    // Neighboring domains in 2d\n    // In 3d unused, EXCEPT for free floating edges in a domain,\n    // then both are pointing to the containing domain\n    int domin=-1, domout=-1;\n\n    GeometryEdge( GeometryVertex &start_, GeometryVertex &end_ )\n        : start(&start_), end(&end_)\n    {}\n\n    virtual const GeometryVertex& GetStartVertex() const { return *start; }\n    virtual const GeometryVertex& GetEndVertex() const { return *end; }\n    virtual GeometryVertex& GetStartVertex() { return *start; }\n    virtual GeometryVertex& GetEndVertex() { return *end; }\n    virtual double GetLength() const = 0;\n    virtual Point<3> GetCenter() const = 0;\n    virtual Point<3> GetPoint(double t) const = 0;\n    // Calculate parameter step respecting edges sag value\n    virtual double CalcStep(double t, double sag) const = 0;\n    virtual bool IsDegenerated(double tol = 1e-10) const {\n      return GetLength() < tol;\n    }\n    virtual void ProjectPoint(Point<3>& p, EdgePointGeomInfo* gi) const = 0;\n    virtual void PointBetween(const Point<3>& p1,\n                              const Point<3>& p2,\n                              double secpoint,\n                              const EdgePointGeomInfo& gi1,\n                              const EdgePointGeomInfo& gi2,\n                              Point<3>& newp,\n                              EdgePointGeomInfo& newgi) const\n    {\n      newp = p1 + secpoint * (p2-p1);\n      newgi = gi1;\n      ProjectPoint(newp, &newgi);\n    }\n    virtual Vec<3> GetTangent(double t) const = 0;\n    virtual bool IsMappedShape( const GeometryShape & other, const Transformation<3> & trafo, double tolerance ) const override;\n    virtual void Divide(const MeshingParameters & mparam, const Mesh & mesh, Array<Point<3>> & points, Array<double> & params);\n  };\n\n  class DLL_HEADER GeometryFace : public GeometryShape\n  {\n  public:\n    Array<GeometryEdge*> edges;\n    int domin=-1, domout=-1;\n\n    virtual Point<3> GetCenter() const = 0;\n    virtual size_t GetNBoundaries() const = 0;\n    virtual Array<Segment> GetBoundary(const Mesh& mesh) const = 0;\n\n    virtual PointGeomInfo Project(Point<3>& p) const = 0;\n    // Project point using geo info. Fast if point is close to\n    // parametrization in geo info.\n    virtual bool ProjectPointGI(Point<3>& p, PointGeomInfo& gi) const =0;\n    virtual bool CalcPointGeomInfo(const Point<3>& p, PointGeomInfo& gi) const\n    {\n      auto pnew = p;\n      gi = Project(pnew);\n      return (p-pnew).Length() < 1e-10 * GetBoundingBox().Diam() ;\n    }\n    virtual Point<3> GetPoint(const PointGeomInfo& gi) const = 0;\n    virtual void CalcEdgePointGI(const GeometryEdge& edge,\n                                 double t,\n                                 EdgePointGeomInfo& egi) const = 0;\n    virtual Box<3> GetBoundingBox() const = 0;\n\n    // Get curvature in point from local coordinates in PointGeomInfo\n    virtual double GetCurvature(const PointGeomInfo& gi) const = 0;\n\n    virtual void RestrictH(Mesh& mesh, const MeshingParameters& mparam) const = 0;\n    virtual Vec<3> GetNormal(const Point<3>& p, const PointGeomInfo* gi = nullptr) const = 0;\n\n    virtual void PointBetween(const Point<3>& p1,\n                              const Point<3>& p2,\n                              double secpoint,\n                              const PointGeomInfo& gi1,\n                              const PointGeomInfo& gi2,\n                              Point<3>& newp,\n                              PointGeomInfo& newgi) const\n    {\n      newp = p1 + secpoint * (p2-p1);\n      newgi.trignum = gi1.trignum;\n      /*\n      newgi.u = 0.5 * (gi1.u + gi1.u);\n      newgi.v = 0.5 * (gi1.v + gi2.v);\n      */\n      newgi.u = gi1.u + secpoint*(gi2.u - gi1.u);\n      newgi.v = gi1.v + secpoint*(gi2.v - gi1.v);\n      if(!ProjectPointGI(newp, newgi))\n        newgi = Project(newp);\n    }\n\n    virtual bool IsMappedShape( const GeometryShape & other, const Transformation<3> & trafo, double tolerance ) const override;\n    virtual bool IsConnectingCloseSurfaces() const;\n\n  protected:\n    void RestrictHTrig(Mesh& mesh,\n                       const PointGeomInfo& gi0,\n                       const PointGeomInfo& gi1,\n                       const PointGeomInfo& gi2,\n                       const MeshingParameters& mparam,\n                       int depth = 0, double h = 0.) const;\n  };\n\n  class DLL_HEADER GeometrySolid : public GeometryShape\n  {\n  public:\n    Array<GeometryEdge*> free_edges; // edges with no adjacent face\n  };\n\n  class DLL_HEADER NetgenGeometry\n  {\n    unique_ptr<Refinement> ref;\n  protected:\n    Array<unique_ptr<GeometryVertex>> vertices;\n    Array<unique_ptr<GeometryEdge>> edges;\n    Array<unique_ptr<GeometryFace>> faces;\n    Array<unique_ptr<GeometrySolid>> solids;\n    Array<std::pair<Point<3>, double>> restricted_h;\n    Box<3> bounding_box;\n    int dimension = 3;\n\n  public:\n\n    NetgenGeometry()\n    {\n      ref = make_unique<Refinement>(*this);\n    }\n    virtual ~NetgenGeometry () { ; }\n\n    size_t GetNVertices() const { return vertices.Size(); }\n    size_t GetNEdges() const { return edges.Size(); }\n    size_t GetNFaces() const { return faces.Size(); }\n    size_t GetNSolids() const { return solids.Size(); }\n\n    const GeometrySolid & GetSolid(int i) const { return *solids[i]; }\n    const GeometryFace & GetFace(int i) const { return *faces[i]; }\n    const GeometryEdge & GetEdge(int i) const { return *edges[i]; }\n    const GeometryVertex & GetVertex(int i) const { return *vertices[i]; }\n\n    auto Solids() const { return FlatArray{solids}; }\n    auto Faces() const { return FlatArray{faces}; }\n    auto Edges() const { return FlatArray{edges}; }\n    auto Vertices() const { return FlatArray{vertices}; }\n\n    virtual Array<const GeometryVertex*> GetFaceVertices(const GeometryFace& face) const { return Array<const GeometryVertex*>{}; }\n\n    void Clear();\n\n    virtual int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam);\n\n    void RestrictH(const Point<3>& pnt, double maxh)\n    {\n      restricted_h.Append({pnt, maxh});\n    }\n\n    virtual const Refinement & GetRefinement () const\n    {\n      return *ref;\n    }\n\n    virtual void DoArchive(Archive&)\n  { throw NgException(\"DoArchive not implemented for \" + Demangle(typeid(*this).name())); }\n\n    virtual Mesh::GEOM_TYPE GetGeomType() const { return Mesh::NO_GEOM; }\n    virtual void ProcessIdentifications();\n    virtual void Analyse(Mesh& mesh,\n                         const MeshingParameters& mparam) const;\n    virtual void FindEdges(Mesh& mesh, const MeshingParameters& mparam) const;\n    virtual void MeshSurface(Mesh& mesh, const MeshingParameters& mparam) const;\n    virtual bool MeshFace(Mesh& mesh, const MeshingParameters& mparam,\n                     int nr, FlatArray<int, PointIndex> glob2loc) const;\n    virtual void MapSurfaceMesh( Mesh & mesh, const GeometryFace & dst, std::map<tuple<PointIndex, int>, PointIndex> & mapto) const;\n    virtual void OptimizeSurface(Mesh& mesh, const MeshingParameters& mparam) const;\n\n    virtual void FinalizeMesh(Mesh& mesh) const;\n\n    virtual PointGeomInfo ProjectPoint (int surfind, Point<3> & p) const\n    {\n      if(surfind <= faces.Size() && surfind > 0)\n        return faces[surfind-1]->Project(p);\n      return PointGeomInfo();\n    }\n\n  virtual void ProjectPointEdge (int surfind, int surfind2, Point<3> & p, EdgePointGeomInfo* gi = nullptr) const\n  {\n    if(gi && gi->edgenr < edges.Size() && gi->edgenr >= 0)\n      edges[gi->edgenr]->ProjectPoint(p, gi);\n  }\n\n    virtual bool CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const\n    {\n      return faces[surfind-1]->CalcPointGeomInfo(p3, gi);\n    }\n    virtual bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const\n    {\n      if(surfind > 0 && surfind <= faces.Size())\n        return faces[surfind-1]->ProjectPointGI(p, gi);\n      return false;\n    }\n\n    virtual Vec<3> GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi = nullptr) const\n    {\n      if(surfind > 0 && surfind <= faces.Size())\n        return faces[surfind-1]->GetNormal(p, gi);\n      else\n        return {0., 0., 0.};\n    }\n\n    virtual void PointBetween (const Point<3> & p1,\n                               const Point<3> & p2, double secpoint,\n                               int surfi,\n                               const PointGeomInfo & gi1,\n                               const PointGeomInfo & gi2,\n                               Point<3> & newp,\n                               PointGeomInfo & newgi) const\n    {\n      if(faces.Size() >= surfi && surfi > 0)\n        {\n          faces[surfi-1]->PointBetween(p1, p2, secpoint, gi1, gi2, newp, newgi);\n          return;\n        }\n      newp = p1 + secpoint * (p2-p1);\n    }\n\n    virtual void PointBetweenEdge(const Point<3> & p1,\n                                  const Point<3> & p2, double secpoint,\n                                  int surfi1, int surfi2,\n                                  const EdgePointGeomInfo & ap1,\n                                  const EdgePointGeomInfo & ap2,\n                                  Point<3> & newp,\n                                  EdgePointGeomInfo & newgi) const\n    {\n      if(ap1.edgenr < edges.Size() && ap1.edgenr >= 0)\n        {\n          edges[ap1.edgenr]->PointBetween(p1, p2, secpoint,\n                                          ap1, ap2, newp, newgi);\n          return;\n        }\n      newp = p1+secpoint*(p2-p1);\n      newgi.edgenr = ap1.edgenr;\n      newgi.dist = ap1.dist + secpoint*(ap2.dist-ap1.dist);\n    }\n\n    virtual Vec<3> GetTangent(const Point<3> & p, int surfi1,\n                              int surfi2,\n                              const EdgePointGeomInfo & egi) const\n    {\n      throw Exception(\"Base geometry get tangent called\");\n    }\n\n    virtual void Save (const filesystem::path & filename) const;\n    virtual void SaveToMeshFile (ostream & /* ost */) const { ; }\n  };\n\n\n\n\n\n  class DLL_HEADER GeometryRegister\n  {\n  public:\n    virtual ~GeometryRegister();\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const = 0;\n    virtual NetgenGeometry * LoadFromMeshFile (istream & /* ist */, string) const { return NULL; }\n    virtual class VisualScene * GetVisualScene (const NetgenGeometry * /* geom */) const\n    { return NULL; }\n    virtual void SetParameters (Tcl_Interp * /* interp */) { ; }\n  };\n\n  class DLL_HEADER GeometryRegisterArray : public NgArray<GeometryRegister*>\n  {\n  public:\n    virtual ~GeometryRegisterArray()\n    {\n      for (int i = 0; i < Size(); i++)\n        delete (*this)[i];\n    }\n\n    virtual shared_ptr<NetgenGeometry> LoadFromMeshFile (istream & ist) const;\n  };\n\n  DLL_HEADER GeometryRegisterArray& GeometryRegister();\n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/bcfunctions.cpp",
    "content": "\n#include <mystdlib.h>\n#include <meshing.hpp>\n#include \"bcfunctions.hpp\"\n\n\nnamespace netgen\n{\n   // Default colour to be used for boundary condition number \"0\"\n   #define DEFAULT_R       0.0\n   #define DEFAULT_G       1.0\n   #define DEFAULT_B       0.0\n\n   // Boundary condition number to use if a face does not have a \n   // colour assigned to it, or if the colour is the above defined \n   // default colour\n   #define DEFAULT_BCNUM   1\n\n   // Default tolerance for colour matching (using Euclidean distance)\n   #define DEFAULT_EPS     2.5e-05\n\n\n\n\n   /*! Philippose - 11/07/2009\n       Function to check if two RGB colours are equal\n\n       Note#1: Currently uses unweighted Euclidean Distance \n       for colour matching.\n\n       Note#2: The tolerance used for deciding whether two \n       colours match is defined as \"eps\" and is currently \n       2.5e-5 (for square of distance)\n   */\n   bool ColourMatch(Vec<4> col1, Vec<4> col2, double eps)\n   {\n      if(eps <= 0.0) eps = DEFAULT_EPS;\n      \n      bool colmatch = false;\n\n      if((col1-col2).Length2() < eps) colmatch = true;\n\n      return colmatch;\n   }\n      \n\n\n\n\n   /*! Philippose - 11/07/2009\n       Function to create a list of all the unique colours \n       available in a given mesh\n   */\n  void GetFaceColours(Mesh & mesh, NgArray<Vec<4>> & face_colours)\n   {\n      face_colours.SetSize(1);\n      face_colours.Elem(1) = mesh.GetFaceDescriptor(1).SurfColour();\n      \n      for(int i = 1; i <= mesh.GetNFD(); i++)\n      {\n         auto face_colour = mesh.GetFaceDescriptor(i).SurfColour();\n         bool col_found = false;\n         \n         for(int j = 1; j <= face_colours.Size(); j++)\n         {\n            if(ColourMatch(face_colours.Elem(j),face_colour))\n            {\n               col_found = true;\n               break;\n            }\n         }\n         \n         if(!col_found) face_colours.Append(face_colour);\n      }\n\n      if(printmessage_importance >= 3)\n      {\n         cout << endl << \"-------- Face Colours --------\" << endl;\n         for( int i = 1; i <= face_colours.Size(); i++)\n         {\n            cout << face_colours.Elem(i) << endl;\n         }\n         cout << \"------------------------------\" << endl;\n      }\n   }\n\n\n\n\n\n\n   /*! Philippose - 11/07/2009\n       Assign boundary condition numbers based on a user defined \n       colour profile file.\n\n       The default profile file is \"netgen.ocf\"\n\n       If the mesh contains colours not defined in the profile,\n       netgen automatically starts assigning each new colour a \n       new boundary condition number starting from the highest \n       boundary condition number specified in the profile file.\n   */\n   void AutoColourAlg_UserProfile(Mesh & mesh, ifstream & ocf)\n   {\n      char ocf_inp[100];\n      bool header_found = false;\n\n      // Number of colour specifications in the \n      // user profile file\n      int numentries = 0;\n      while((ocf.good()) && (!header_found))\n      {\n         ocf >> ocf_inp;\n         if(strcmp(ocf_inp,\"boundary_colours\") == 0) header_found = true;\n      }\n\n      if(!header_found)\n      {\n         ocf.close();\n         throw NgException(\"AutoColourAlg_UserProfile: Invalid or empty Boundary Colour Profile file\\n\");\n         return;\n      }\n\n      // Read in the number of entries from file\n      ocf >> numentries;\n      if(numentries > 0)\n      {\n         if(!ocf.good())\n         {\n            ocf.close();\n            throw NgException(\"AutoColourAlg_UserProfile: Invalid or empty Boundary Colour Profile file\\n\");\n            return;\n         }\n\n         PrintMessage(3, \"Number of colour entries: \", numentries);\n      }\n      else\n      {\n         ocf.close();\n         PrintMessage(3, \"AutoColourAlg_UserProfile: No Boundary Colour entries found.... no changes made!\");\n         return;\n      }\n\n      // Arrays to hold the specified RGB colour triplets as well \n      // as the associated boundary condition number\n      NgArray<Vec<4>> bc_colours(numentries);\n      NgArray<int> bc_num(numentries);\n      NgArray<bool> bc_used(numentries);\n      \n      // Actually read in the data from the file\n      for(int i = 1; i <= numentries; i++)\n      {\n         int bcnum;\n         // double col_red, col_green, col_blue;\n\n         ocf >> bcnum;\n         // Boundary condition number DEFAULT_BCNUM is reserved for \n         // faces which have the default colour Green (0.0,1.0,0.0)\n         // To prevent confusion, no boundary numbery below this default \n         // are permitted\n         if(bcnum < (DEFAULT_BCNUM + 1)) bcnum = DEFAULT_BCNUM+1;\n\n         bc_num.Elem(i) = bcnum;\n         bc_used.Elem(i) = false;\n         ocf >> bc_colours.Elem(i)[0]\n             >> bc_colours.Elem(i)[1]\n             >> bc_colours.Elem(i)[2];\n\n         if(!ocf.good())\n         {\n            ocf.close();\n            throw NgException(\"Boundary Colour file error: Number of entries do not match specified list size!!\\n\");\n            return;\n         }\n\n         // Bound checking of the values\n         // The RGB values should be between 0.0 and 1.0\n         for(auto i : Range(3))\n           bc_colours.Elem(bcnum)[i] = max2(min2(bc_colours.Elem(bcnum)[i], 1.), 0.);\n      }\n\n      PrintMessage(3, \"Successfully loaded Boundary Colour Profile file....\");\n      ocf.close();\n\n      // Find the highest boundary condition number in the list\n      // All colours in the geometry which are not specified in the \n      // list will be given boundary condition numbers higher than this \n      // number\n      int max_bcnum = DEFAULT_BCNUM;\n      for(int i = 1; i <= bc_num.Size();i++)\n      {\n         if(bc_num.Elem(i) > max_bcnum) max_bcnum = bc_num.Elem(i);\n      }\n\n      PrintMessage(3, \"Highest boundary number in list = \",max_bcnum);\n\n      NgArray<Vec<4>> all_colours;\n      \n      // Extract all the colours to see how many there are\n      GetFaceColours(mesh,all_colours);\n      PrintMessage(3,\"\\nNumber of colours defined in Mesh: \", all_colours.Size());\n\n      if(all_colours.Size() == 0)\n      {\n         PrintMessage(3,\"No colour data detected in Mesh... no changes made!\");\n         return;\n      }\n\n      int nfd = mesh.GetNFD();\n\n      for(int face_index = 1; face_index <= nfd; face_index++)\n      {\n         // Get the colour of the face being currently processed\n         auto face_colour = mesh.GetFaceDescriptor(face_index).SurfColour();\n         if(!ColourMatch(face_colour,Vec<4>(DEFAULT_R,DEFAULT_G,DEFAULT_B, 1.0)))\n         {\n            // Boolean variable to check if the boundary condition was applied \n            // or not... not applied would imply that the colour of the face \n            // does not exist in the list of colours in the profile file\n            bool bc_assigned = false;\n\n            for(int col_index = 1; col_index <= bc_colours.Size(); col_index++)\n            {\n               if((ColourMatch(face_colour,bc_colours.Elem(col_index))) && (!bc_assigned))\n               {\n                  mesh.GetFaceDescriptor(face_index).SetBCProperty(bc_num.Elem(col_index));\n                  bc_used.Elem(col_index) = true;\n                  bc_assigned = true;\n                  break;\n               }\n            }\n\n            // If the colour was not found in the list, add it to the list, and assign \n            // the next free boundary condition number to it\n            if(!bc_assigned)\n            {\n               max_bcnum++;\n               bc_num.Append(max_bcnum);\n               bc_colours.Append(face_colour);\n               bc_used.Append(true);\n\n               mesh.GetFaceDescriptor(face_index).SetBCProperty(max_bcnum);\n            }\n         }\n         else\n         {\n            // Set the boundary condition number to the default one\n            mesh.GetFaceDescriptor(face_index).SetBCProperty(DEFAULT_BCNUM);\n         }\n      }\n\n      // User Information of the results of the operation\n      Vec<4> ref_colour(0.0,1.0,0.0,1.0);\n      PrintMessage(3,\"Colour based Boundary Condition Property details:\");\n      for(int bc_index = 0; bc_index <= bc_num.Size(); bc_index++)\n      {\n         if(bc_index > 0) ref_colour = bc_colours.Elem(bc_index);\n\n         if(bc_index == 0) \n         {\n            PrintMessage(3, \"BC Property: \",DEFAULT_BCNUM);\n            PrintMessage(3, \"   RGB Face Colour = \",Vec3d{ref_colour[0], ref_colour[1], ref_colour[2]},\"\",\"\\n\");\n         }\n         else if(bc_used.Elem(bc_index))\n         {\n            PrintMessage(3, \"BC Property: \",bc_num.Elem(bc_index));\n            PrintMessage(3, \"   RGB Face Colour = \",Vec3d{ref_colour[0], ref_colour[1], ref_colour[2]},\"\",\"\\n\");\n         }\n      }\n   }\n\n\n\n\n   \n   /*! Philippose - 11/07/2009\n       Assign boundary condition numbers based on the colours \n       assigned to each face in the mesh using an automated \n       algorithm.\n\n       The particular algorithm used has been briefly explained \n       in the header file \"occauxfunctions.hpp\"\n   */\n   void AutoColourAlg_Sorted(Mesh & mesh)\n   {\n      NgArray<Vec<4>> all_colours;\n      NgArray<int> faces_sorted;\n      NgArray<int> colours_sorted;\n\n      // Extract all the colours to see how many there are\n      GetFaceColours(mesh,all_colours);\n\n      // Delete the default colour from the list since it will be accounted \n      // for automatically\n      for(int i = 1; i <= all_colours.Size(); i++)\n      {\n        if(ColourMatch(all_colours.Elem(i),Vec<4>(DEFAULT_R,DEFAULT_G,DEFAULT_B,1.0)))\n         {\n            all_colours.DeleteElement(i);\n            break;\n         }\n      }\n      PrintMessage(3,\"\\nNumber of colours defined in Mesh: \", all_colours.Size());\n\n      if(all_colours.Size() == 0)\n      {\n         PrintMessage(3,\"No colour data detected in Mesh... no changes made!\");\n         return;\n      }\n\n      // One more slot than the number of colours are required, to \n      // account for individual faces which have no colour data \n      // assigned to them in the CAD software\n      faces_sorted.SetSize(all_colours.Size()+1);\n      colours_sorted.SetSize(all_colours.Size()+1);\n      faces_sorted = 0;\n      \n      // Index NgArray to identify the colours the faces were assigned to, \n      // after the bubble sort routine to sort the automatic boundary \n      // identifiers according to the number of surface mesh elements \n      // of a given colour\n      for(int i = 0; i <= all_colours.Size(); i++) colours_sorted[i] = i;\n\n      // Used to hold the number of surface elements without any OCC \n      // colour definition\n      int no_colour_faces = 0;\n\n      // Index in the faces array assigned to faces without any \n      // or the default colour definition\n      int no_colour_index = 0;\n\n      int nfd = mesh.GetNFD();\n\n      // Extract the number of surface elements having a given colour\n      // And save this number into an array for later sorting\n      for(int face_index = 1; face_index <= nfd; face_index++)\n        {\n          Array<SurfaceElementIndex> se_face;\n          \n         mesh.GetSurfaceElementsOfFace(face_index, se_face);\n\n         auto face_colour = mesh.GetFaceDescriptor(face_index).SurfColour();\n         if(!ColourMatch(face_colour,Vec<4>(DEFAULT_R,DEFAULT_G,DEFAULT_B,1.0)))\n         {\n            for(int i = 1; i <= all_colours.Size(); i++)\n            {\n               if(ColourMatch(face_colour, all_colours.Elem(i)))\n               {\n                  faces_sorted[i] = faces_sorted[i] + se_face.Size();\n               }\n            }\n         }\n         else\n         {\n            // Add the number of surface elements without any colour \n            // definition separately\n            no_colour_faces = no_colour_faces + se_face.Size();\n         }\n      }\n\n      // Sort the face colour indices according to the number of surface \n      // mesh elements which have a specific colour\n      BubbleSort(faces_sorted,colours_sorted);\n\n      // Now update the array position assigned for surface elements \n      // without any colour definition with the number of elements\n      faces_sorted[no_colour_index] = no_colour_faces;\n\n      // Now actually assign the BC Property to the respective faces\n      for(int face_index = 1; face_index <= nfd; face_index++)\n      {\n         auto face_colour = mesh.GetFaceDescriptor(face_index).SurfColour();\n         if(!ColourMatch(face_colour,Vec<4>(DEFAULT_R,DEFAULT_G,DEFAULT_B, 1.0)))\n         {\n            for(int i = 0; i < colours_sorted.Size(); i++)\n            {\n               Vec<4> ref_colour;\n               if(i != no_colour_index) ref_colour = all_colours.Elem(colours_sorted[i]);\n\n               if(ColourMatch(face_colour, ref_colour))\n               {\n                  mesh.GetFaceDescriptor(face_index).SetBCProperty(i + DEFAULT_BCNUM);\n               }\n            }\n         }\n         else\n         {\n            mesh.GetFaceDescriptor(face_index).SetBCProperty(DEFAULT_BCNUM);\n         }\n\n         PrintMessage(4,\"Face number: \",face_index,\" ; BC Property = \",mesh.GetFaceDescriptor(face_index).BCProperty());\n      }\n\n      // User Information of the results of the operation\n      Vec<4> ref_colour(0.0,1.0,0.0,1.0);\n      PrintMessage(3,\"Colour based Boundary Condition Property details:\");\n      for(int i = 0; i < faces_sorted.Size(); i++)\n      {\n         if(colours_sorted[i] > 0) ref_colour = all_colours.Elem(colours_sorted[i]);\n\n         PrintMessage(3, \"BC Property: \",i + DEFAULT_BCNUM);\n         PrintMessage(3, \"   Nr. of Surface Elements = \", faces_sorted[i]);\n         PrintMessage(3, \"   Colour Index = \", colours_sorted[i]);\n         PrintMessage(3, \"   RGB Face Colour = \",Vec3d{ref_colour[0], ref_colour[1], ref_colour[2]},\"\",\"\\n\");\n      }\n   }\n\n\n\n\n\n   /*! Philippose - 13/07/2009\n       Main function implementing automated assignment of \n       Boundary Condition numbers based on face colours\n\n       This functionality is currently implemtented at the mesh \n       level, and hence allows colour based assignment of boundary \n       conditions for any geometry type within netgen which \n       supports face colours\n   */\n   void AutoColourBcProps(Mesh & mesh, const char * bccolourfile)\n   {\n      // Go directly to the alternate algorithm if no colour profile file was specified\n      if(!bccolourfile)\n      {\n         PrintMessage(1,\"AutoColourBcProps: Using Automatic Colour based boundary property assignment algorithm\");\n         AutoColourAlg_Sorted(mesh);\n      }\n      else\n      {\n         ifstream ocf(bccolourfile);\n\n         // If there was an error opening the Colour profile file, jump to the alternate \n         // algorithm after printing a message\n         if(!ocf)\n         {\n            PrintMessage(1,\"AutoColourBcProps: Error loading Boundary Colour Profile file \", \n                         bccolourfile, \" ....\",\"Switching to Automatic Assignment algorithm!\");\n\n            AutoColourAlg_Sorted(mesh);\n         }\n         // If the file opens successfully, call the function which assigns boundary conditions \n         // based on the colour profile file\n         else\n         {\n            PrintMessage(1, \"AutoColourBcProps: Using Boundary Colour Profile file: \");\n            PrintMessage(1, \"  \", bccolourfile);\n            AutoColourAlg_UserProfile(mesh, ocf);\n\n            // Make sure the file is closed before exiting the function\n            if(ocf.is_open())\n            {\n               ocf.close();\n            }\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "libsrc/meshing/bcfunctions.hpp",
    "content": "#ifndef FILE_BCFUNCTIONS\n#define FILE_BCFUNCTIONS\n\n// Philippose - 14/03/2009\n// Auxiliary functions for OCC Geometry\n// Use this file and the corresponding \".cpp\" \n// file to add miscellaneous functionality \n// to the OpenCascade Geometry support in Netgen\nnamespace netgen\n{\n   /*! \\brief Automatically assign boundary conditions for meshes\n\n       This function allows the boundary condition numbers of a \n       mesh created in Netgen to be automatically assigned based on \n       the colours of each face.\n\n       Currently, two algorithms are utilised to assign the BC Properties:\n       1. Automatic assignment using a user defined colour profile file \n          which defines which RGB colours are to be assigned to which \n          BC Property number\n          - A default profile file exists in the Netgen folder called \n            \"netgen.ocf\"\n       \n       2. The second algorithm uses the following automated algorithm:\n          - Extract all the colours present in the mesh\n          - Use colour index 0 (zero) for all faces with no colour defined\n          - Calculate the number of faces of the surface mesh for each colour\n          - Sort the number of surface elements in ascending order, with the \n            colour indices as a index\n          - Use the indices of the sorted array as the BC property number\n\n          Example: If there are 3 colours, present in the mesh and the number \n          of surface elements for each colour are:\n          - Colour 0: 8500\n          - Colour 1: 120\n          - Colour 2: 2200\n          - Colour 3: 575\n\n          The above is sorted in ascending order and assigned as BC Properties:\n          - BC Prop 0: 120  : Colour 1\n          - BC Prop 1: 575  : Colour 3\n          - BC Prop 2: 2200 : Colour 2\n          - BC Prop 3: 8500 : Colour 0 (no colour defined)\n   */\n   //extern void OCCAutoColourBcProps(Mesh & mesh, OCCGeometry & occgeometry, const char *occcolourfile);\n   extern DLL_HEADER void AutoColourBcProps(Mesh & mesh, const char *bccolourfile);\n\n  extern DLL_HEADER void GetFaceColours(Mesh & mesh, NgArray<Vec<4>> & face_colours);\n\n   extern DLL_HEADER bool ColourMatch(Vec<4> col1, Vec<4> col2, double eps = 2.5e-05);\n}\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/bisect.cpp",
    "content": "#include <mystdlib.h>\n#include <core/array.hpp>\n\n#include \"meshclass.hpp\" \n#include \"bisect.hpp\"\n#include \"validate.hpp\"\n#include \"paralleltop.hpp\"\n\n// #include \"meshing.hpp\"  // quickfix for parallel\n\n#define noDEBUG\n\nnamespace netgen\n{\n  class MarkedTet\n  {\n  public:\n    /// pnums of tet\n    PointIndex pnums[4];\n    /// material number\n    int matindex;\n    /// element marked for refinement\n    /// marked = 1: marked by element marker, marked = 2 due to closure\n    unsigned int marked:2;\n    /// flag of Arnold-Mukherjee algorithm\n    unsigned int flagged:1;\n    /// tetedge (local coordinates 0..3)\n    unsigned int tetedge1:3;\n    unsigned int tetedge2:3;\n    // marked edge of faces\n    // face_j : face without node j,\n    // mark_k : edge without node k\n    \n    char faceedges[4];\n    // unsigned char faceedges[4];\n    bool incorder;\n    unsigned int order:6;\n    int8_t newest_vertex;\n\n    MarkedTet() = default;\n    /*\n    { \n      for (int i = 0; i < 4; i++) { faceedges[i] = 127; }\n    }\n    */\n    MarkedTet (const MarkedTet&) = default;\n    MarkedTet (MarkedTet &&) = default;\n    MarkedTet & operator= (const MarkedTet&) = default;\n    MarkedTet & operator= (MarkedTet&&) = default;\n    \n  };\n\n  ostream & operator<< (ostream & ost, const MarkedTet & mt)\n  {\n    for(int i=0; i<4; i++)\n      ost << mt.pnums[i] << \" \";\n\n    ost << mt.matindex << \" \" << int(mt.marked) << \" \" << int(mt.flagged) << \" \" << int(mt.tetedge1) << \" \" << int(mt.tetedge2) << \" \";\n    \n    ost << \"faceedges = \";\n    for(int i=0; i<4; i++)\n      ost << int(mt.faceedges[i]) << \" \";\n\n    ost << \" order = \";\n    ost << mt.incorder << \" \" << int(mt.order) << \"\\n\";\n    return ost;\n  }\n  istream & operator>> (istream & ost, MarkedTet & mt)\n  {\n    for(int i=0; i<4; i++)\n      ost >> mt.pnums[i];\n\n    ost >> mt.matindex;\n\n    int auxint;\n    ost >> auxint;\n    mt.marked = auxint;\n    ost >> auxint;\n    mt.flagged = auxint;\n    ost >> auxint;\n    mt.tetedge1 = auxint;\n    ost >> auxint;\n    mt.tetedge2 = auxint;\n    \n    char auxchar;\n\n    for(int i=0; i<4; i++)\n      {\n\tost >> auxchar;\n\tmt.faceedges[i] = auxchar;\n      }\n\n    ost >> mt.incorder;\n    ost >> auxint;\n    mt.order = auxint;\n    return ost;\n  }\n\n  class MarkedPrism\n  {\n  public:\n    /// 6 point numbers\n    PointIndex pnums[6];\n    /// material number\n    int matindex;\n    /// marked for refinement\n    int marked;\n    /// edge without node k (0,1,2)\n    int markededge;\n\n    bool incorder;\n    unsigned int order:6;\n  };\n\n  \n  ostream & operator<< (ostream & ost, const MarkedPrism & mp)\n  {\n    for(int i=0; i<6; i++)\n      ost << mp.pnums[i] << \" \";\n\n    ost << mp.matindex << \" \" << mp.marked << \" \" << mp.markededge << \" \" << mp.incorder << \" \" << int(mp.order) << \"\\n\";\n    return ost;\n  }\n  istream & operator>> (istream & ist, MarkedPrism & mp)\n  {\n    for(int i=0; i<6; i++)\n      ist >> mp.pnums[i];\n\n    ist >> mp.matindex >> mp.marked >> mp.markededge >> mp.incorder;\n    int auxint;\n    ist >> auxint;\n    mp.order = auxint;\n    return ist;\n  }\n\n\n  class MarkedIdentification\n  {\n  public:\n    // number of points of one face (3 or 4) - or edge (in 2d)\n    int np;\n    /// 6 or 8 point numbers - or 4 in 2d\n    PointIndex pnums[8];\n    /// marked for refinement\n    int marked;\n    /// edge starting with node k (0,1,2, or 3)\n    int markededge;\n\n    bool incorder;\n    unsigned int order:6;\n  };\n    \n  \n  ostream & operator<< (ostream & ost, const MarkedIdentification & mi)\n  {\n    ost << mi.np << \" \";\n    for(int i=0; i<2*mi.np; i++)\n      ost << mi.pnums[i] << \" \";\n    ost << mi.marked << \" \" << mi.markededge << \" \" << mi.incorder << \" \" << int(mi.order) << \"\\n\";\n    return ost;\n  }\n  istream & operator>> (istream & ist, MarkedIdentification & mi)\n  {\n    ist >> mi.np;\n    for(int i=0; i<2*mi.np; i++)\n      ist >> mi.pnums[i];\n    ist >> mi.marked >> mi.markededge >> mi.incorder;\n    int auxint;\n    ist >> auxint;\n    mi.order = auxint;\n    return ist;\n  }\n  \n\n\n\n\n  class MarkedTri\n  {\n  public:\n    MarkedTri () = default;\n    MarkedTri (const MarkedTri&) = default;\n    MarkedTri (MarkedTri &&) = default;\n    MarkedTri & operator= (const MarkedTri&) = default;\n    MarkedTri & operator= (MarkedTri&&) = default;\n    \n    /// three point numbers\n    PointIndex pnums[3];\n    /// three geominfos\n    PointGeomInfo pgeominfo[3];\n    /// marked for refinement\n    int marked;\n    /// edge without node k\n    int markededge;\n    /// surface id\n    int surfid;\n\n    bool incorder;\n    unsigned int order:6;\n    int8_t newest_vertex;\n  };\n  \n  ostream & operator<< (ostream & ost, const MarkedTri & mt)\n  {\n    for(int i=0; i<3; i++)\n      ost << mt.pnums[i] << \" \";\n    for(int i=0; i<3; i++)\n      ost << mt.pgeominfo[i] << \" \";\n    ost << mt.marked << \" \" << mt.markededge << \" \" << mt.surfid << \" \" << mt.incorder << \" \" << int(mt.order) << \"\\n\";\n    return ost;\n  } \n  istream & operator>> (istream & ist, MarkedTri & mt)\n  {\n    for(int i=0; i<3; i++)\n      ist >> mt.pnums[i];\n    for(int i=0; i<3; i++)\n      ist >> mt.pgeominfo[i];\n    ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;\n    int auxint;\n    ist >> auxint;\n    mt.order = auxint;\n    return ist;\n  }\n    \n\n\n  class MarkedQuad\n  {\n  public:\n    /// point numbers\n    PointIndex pnums[4];\n    ///\n    PointGeomInfo pgeominfo[4];\n    /// marked for refinement\n    int marked;\n    /// marked edge: 0/2 = vertical, 1/3 = horizontal\n    int markededge;\n    /// surface id\n    int surfid;\n\n    bool incorder;\n    unsigned int order:6;\n  };\n\n  ostream & operator<< (ostream & ost, const MarkedQuad & mt)\n  {\n    for(int i=0; i<4; i++)\n      ost << mt.pnums[i] << \" \";\n    for(int i=0; i<4; i++)\n      ost << mt.pgeominfo[i] << \" \";\n    ost << mt.marked << \" \" << mt.markededge << \" \" << mt.surfid << \" \" << mt.incorder << \" \" << int(mt.order) << \"\\n\";\n    return ost;\n  } \n  istream & operator>> (istream & ist, MarkedQuad & mt)\n  {\n    for(int i=0; i<4; i++)\n      ist >> mt.pnums[i];\n    for(int i=0; i<4; i++)\n      ist >> mt.pgeominfo[i];\n    ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;\n    int auxint;\n    ist >> auxint;\n    mt.order = auxint;\n    return ist;\n  }\n\n\n\n\n  void PrettyPrint(ostream & ost, const MarkedTet & mt)\n  {\n    int te1 = mt.tetedge1;\n    int te2 = mt.tetedge2;\n    int order = mt.order;\n\n    ost << \"MT: \" << mt.pnums[0] << \" - \" << mt.pnums[1] << \" - \" \n\t<< mt.pnums[2] << \" - \" << mt.pnums[3] << endl\n\t<< \"marked edge: \" << te1 << \" - \" << te2\n\t<< \", order = \" << order << endl;\n    //for (int k = 0; k < 4; k++)\n    //  ost << int(mt.faceedges[k]) << \"  \";\n    for (int k = 0; k < 4; k++)\n      {\n\tost << \"face\";\n\tfor (int j=0; j<4; j++)\n\t  if(j != k)\n\t    ost << \" \" << mt.pnums[j];\n\tfor(int i=0; i<3; i++)\n\t  for(int j=i+1; j<4; j++)\n\t    if(i != k && j != k && int(mt.faceedges[k]) == 6-k-i-j)\n\t      ost << \" marked edge \" << mt.pnums[i] << \" \" << mt.pnums[j] << endl;\n      }\n    ost << endl;\n  }\n\n\n\n  template <typename HASHTABLE_EDGENUMBER>\n  int BTSortEdges (const Mesh & mesh,\n\t\t   const NgArray<idmap_type*> & idmaps,\n                   HASHTABLE_EDGENUMBER & edgenumber)\n  {\n    PrintMessage(4,\"sorting ... \");\n\n    //  if (mesh.PureTetMesh())\n    if (true)\n      {\n\t// new, fast version\n\tArray<PointIndices<2>> edges;\n      \n\t// int i, j, k;\n\tint cntedges = 0;\n\tbool go_on;\n\tint ned(0);\n      \n\t// enumerate edges:\n\n        for (const Element & el : mesh.VolumeElements())\n          {\n\t    static int tetedges[6][2] =\n\t      { { 1, 2 },\n\t\t{ 1, 3 },\n\t\t{ 1, 4 },\n\t\t{ 2, 3 },\n\t\t{ 2, 4 },\n\t\t{ 3, 4 } } ;\n\t    static int prismedges[9][2] =\n\t      { { 1, 2 },\n\t\t{ 1, 3 },\n\t\t{ 2, 3 },\n\t\t{ 4, 5 },\n\t\t{ 4, 6 },\n\t\t{ 5, 6 },\n\t\t{ 1, 4 },\n\t\t{ 2, 5 },\n\t\t{ 3, 6 } };\n\t    int pyramidedges[6][2] =\n\t      { { 1, 2 },\n\t\t{ 3, 4 },\n\t\t{ 1, 5 },\n\t\t{ 2, 5 },\n\t\t{ 3, 5 },\n\t\t{ 4, 5 } };\n\t  \n\t    int (*tip)[2] = NULL;\n\t  \n\t    switch (el.GetType())\n\t      {\n\t      case TET:\n\t      case TET10:\n\t\t{\n\t\t  tip = tetedges;\n\t\t  ned = 6;\n\t\t  break;\n\t\t}\n\t      case PRISM:\n\t      case PRISM12:\n\t\t{\n\t\t  tip = prismedges;\n\t\t  ned = 6;\n\t\t  break;\n\t\t}\n\t      case PYRAMID:\n\t\t{\n\t\t  tip = pyramidedges;\n\t\t  ned = 6;\n\t\t  break;\n\t\t}\n              default:\n                throw NgException(\"Bisect, element type not handled in switch\");\n\t      }\n\t      \n\t    for (int j = 0; j < ned; j++)\n\t      {\n\t\tPointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));\n\t\ti2.Sort();\n\t\tif (!edgenumber.Used(i2))\n\t\t  {\n\t\t    cntedges++;\n\t\t    edges.Append (i2);\n\t\t    edgenumber.Set(i2, cntedges);\n\t\t  }\n\t      }\n\t  }\n      \n\t// additional surface edges:\n\n        for (const Element2d & el : mesh.SurfaceElements())\n          {\n\t    static int trigedges[3][2] =\n\t      { { 1, 2 },\n\t\t{ 2, 3 },\n\t\t{ 3, 1 } };\n\n\t    static int quadedges[4][2] =\n\t      { { 1, 2 },\n\t\t{ 2, 3 },\n\t\t{ 3, 4 },\n\t\t{ 4, 1 } };\n\n\n\t    int (*tip)[2] = NULL;\n\t  \n\t    switch (el.GetType())\n\t      {\n\t      case TRIG:\n\t      case TRIG6:\n\t\t{\n\t\t  tip = trigedges;\n\t\t  ned = 3;\n\t\t  break;\n\t\t}\n\t      case QUAD:\n\t      case QUAD6:\n\t\t{\n\t\t  tip = quadedges;\n\t\t  ned = 4;\n\t\t  break;\n\t\t}\n\t      default:\n\t\t{\n\t\t  cerr << \"Error: Sort for Bisect, SE has \" << el.GetNP() << \" points\" << endl;\n\t\t  ned = 0;\n\t\t}\n\t      }\n\t      \n\t    for (int j = 0; j < ned; j++)\n\t      {\n\t\tPointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));\n\t\ti2.Sort();\n\t\tif (!edgenumber.Used(i2))\n\t\t  {\n\t\t    cntedges++;\n\t\t    edges.Append (i2);\n\t\t    edgenumber.Set(i2, cntedges);\n\t\t  }\n\t      }\n\t  }\n\n\n\tNgArray<int> eclasses(cntedges);\n\tfor (int i = 1; i <= cntedges; i++)\n\t  eclasses.Elem(i) = i;\n\n\t// identify edges in element stack\n\tdo\n\t  {\n\t    go_on = false;\n            for (auto ei : mesh.VolumeElements().Range())\n\t      {\n\t\tconst Element & el = mesh[ei];\n\t      \n\t\tif (el.GetType() != PRISM &&\n\t\t    el.GetType() != PRISM12 &&\n\t\t    el.GetType() != PYRAMID)\n\t\t  continue;\n\n\t\tint prismpairs[3][4] =\n\t\t  { { 1, 2, 4, 5 },\n\t\t    { 2, 3, 5, 6 },\n\t\t    { 1, 3, 4, 6 } };\n\t      \n\t\tint pyramidpairs[3][4] =\n\t\t  { { 1, 2, 4, 3 },\n\t\t    { 1, 5, 4, 5 },\n\t\t    { 2, 5, 3, 5 } };\n                \n\t\tint (*pairs)[4] = NULL;\n\t\tswitch (el.GetType())\n\t\t  {\n\t\t  case PRISM:\n\t\t  case PRISM12:\n\t\t    {\n\t\t      pairs = prismpairs;\n\t\t      break;\n\t\t    }\n\t\t  case PYRAMID:\n\t\t    {\n\t\t      pairs = pyramidpairs;\n\t\t      break;\n\t\t    }\n                  default:\n                    throw NgException(\"Bisect, element type not handled in switch, 2\");\n\t\t  }\n\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  {\n\t\t    PointIndices<2> e1 (el.PNum(pairs[j][0]), \n                                        el.PNum(pairs[j][1]));\n\t\t    PointIndices<2> e2 (el.PNum(pairs[j][2]), \n                                        el.PNum(pairs[j][3]));\n\t\t    e1.Sort();\n\t\t    e2.Sort();\n\t\t      \n\t\t    int eclass1 = edgenumber.Get (e1);\n\t\t    int eclass2 = edgenumber.Get (e2);\n\n\t\t    //\t\t  (*testout) << \"identify edges \" << eclass1 << \"-\" << eclass2 << endl;\n\n\t\t    if (eclasses.Get(eclass1) >\n\t\t\teclasses.Get(eclass2))\n\t\t      {\n\t\t\teclasses.Elem(eclass1) = \n\t\t\t  eclasses.Get(eclass2);\n\t\t\tgo_on = true;\n\t\t      }\n\t\t    else if (eclasses.Get(eclass2) >\n\t\t\t     eclasses.Get(eclass1))\n\t\t      {\n\t\t\teclasses.Elem(eclass2) = \n\t\t\t  eclasses.Get(eclass1);\n\t\t\tgo_on = true;\n\t\t      }\n\t\t  }\n\t      }\n\n            for (const Element2d & el2d : mesh.SurfaceElements())\n              {\n\t\tfor(int i = 0; i < el2d.GetNP(); i++)\n\t\t  {\n\t\t    PointIndices<2> e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);\n\t\t    e1.Sort();\n\t\t    PointIndices<2> e2;\n\t\t    \n\t\t    for(int k = 0; k < idmaps.Size(); k++)\n\t\t      {\n\t\t\te2[0] = (*idmaps[k])[e1[0]];\n\t\t\te2[1] = (*idmaps[k])[e1[1]];\n\t\t\t\n\t\t\tif(!e2.I1().IsValid() || !e2.I2().IsValid() ||\n\t\t\t   e1.I1() == e2.I1() || e1.I2() == e2.I2())\n\t\t\t  continue;\n\t\t\t\n\t\t\te2.Sort();\n\t\t\tif(!edgenumber.Used(e2))\n\t\t\t  continue;\n\t\t\t\n\n\t\t\tint eclass1 = edgenumber.Get (e1);\n\t\t\tint eclass2 = edgenumber.Get (e2);\n\t\t\t\n\t\t\tif (eclasses.Get(eclass1) >\n\t\t\t    eclasses.Get(eclass2))\n\t\t\t  {\n\t\t\t    eclasses.Elem(eclass1) = \n\t\t\t      eclasses.Get(eclass2);\n\n\n\t\t\t    go_on = true;\n\t\t\t  }\n\t\t\telse if (eclasses.Get(eclass2) >\n\t\t\t\t eclasses.Get(eclass1))\n\t\t\t  {\n\t\t\t    eclasses.Elem(eclass2) = \n\t\t\t      eclasses.Get(eclass1);\n\t\t\t    go_on = true;\n\t\t\t  }\n\t\t      }\t\t      \n\t\t  }\n\t\t\n\t      }\n\n\t  }\n\twhile (go_on);\n\n// \tfor (i = 1; i <= cntedges; i++)\n// \t  {\n// \t    (*testout) << \"edge \" << i << \": \" \n// \t\t       << edges.Get(i).I1() << \"-\" << edges.Get(i).I2()\n// \t\t       << \", class = \" << eclasses.Get(i) << endl;\n// \t  }\n\t\n\t// compute classlength:\n\tNgArray<double> edgelength(cntedges);\n\n\t/*\n\tfor (i = 1; i <= cntedges; i++)\n\t  edgelength.Elem(i) = 1e20;\n\t*/\n\n\tfor (int i = 0; i < cntedges; i++)\n          edgelength[i] = Dist (mesh[edges[i][0]], mesh[edges[i][1]]);\n\n\t/*\n\t  for (i = 1; i <= mesh.GetNE(); i++)\n\t  {\n\t  const Element & el = mesh.VolumeElement (i);\n\t  \n\t  if (el.GetType() == TET)\n\t  {\n\t  for (j = 1; j <= 3; j++)\n\t  for (k = j+1; k <= 4; k++)\n\t  {\n\t  INDEX_2 i2(el.PNum(j), el.PNum(k));\n\t  i2.Sort();\n\t\t    \n\t  int enr = edgenumber.Get(i2);\n\t  double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));\n\t  if (elen < edgelength.Get(enr))\n\t  edgelength.Set (enr, elen);\n\t  }\n\t  }\n\t  else if (el.GetType() == PRISM)\n\t  {\n\t  for (j = 1; j <= 3; j++)\n\t  {\n\t  k = (j % 3) + 1;\n\t\t  \n\t  INDEX_2 i2(el.PNum(j), el.PNum(k));\n\t  i2.Sort();\n\t\t  \n\t  int enr = edgenumber.Get(i2);\n\t  double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));\n\t  if (elen < edgelength.Get(enr))\n\t  edgelength.Set (enr, elen);\n\t\t  \n\t  i2 = INDEX_2(el.PNum(j+3), el.PNum(k+3));\n\t  i2.Sort();\n\t\t  \n\t  enr = edgenumber.Get(i2);\n\t  elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));\n\t  if (elen < edgelength.Get(enr))\n\t  edgelength.Set (enr, elen);\n\t\t  \n\t  if (!edgenumber.Used(i2))\n\t  {\n\t  cntedges++;\n\t  edgenumber.Set(i2, cntedges);\n\t  }\n\t  i2 = INDEX_2(el.PNum(j), el.PNum(j+3));\n\t  i2.Sort();\n\t\t  \n\t  enr = edgenumber.Get(i2);\n\t  elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));\n\t  if (elen < edgelength.Get(enr))\n\t  edgelength.Set (enr, elen);\n\t  }\n\t  }\n\t  }\n\t*/\n\n      \n\tfor (int i = 1; i <= cntedges; i++)\n\t  {\n\t    if (eclasses.Get(i) != i)\n\t      {\n\t\tif (edgelength.Get(i) < edgelength.Get(eclasses.Get(i)))\n\t\t  edgelength.Elem(eclasses.Get(i)) = edgelength.Get(i);\n\t\tedgelength.Elem(i) = 1e20;\n\t      }\n\t  }\n\n\n\tTABLE<int> eclasstab(cntedges);\n\tfor (int i = 1; i <= cntedges; i++)\n\t  eclasstab.Add1 (eclasses.Get(i), i-1);\n\n\n\t// sort edges:\n\tNgArray<int> sorted(cntedges);\n      \n\tQuickSort (edgelength, sorted);\n      \n\tint cnt = 0;\n\tfor (int i = 1; i <= cntedges; i++)\n\t  {\n\t    int ii = sorted.Get(i);\n\t    for (int j = 1; j <= eclasstab.EntrySize(ii); j++)\n              edgenumber.Set (edges[eclasstab.Get(ii, j)], ++cnt);\n            \n\t  }\n\treturn cnt;\n      }\n\n    else\n    \n      {\n\t// old version\n      \n\t// int i, j;\n\tint cnt = 0;\n\tbool found;\n\tdouble len2, maxlen2;\n\tINDEX_2 ep;\n      \n\t// sort edges by length, parallel edges (on prisms)\n\t// are added in blocks\n      \n\tdo\n\t  {\n\t    found = false;\n\t    maxlen2 = 1e30;\n\t  \n\t    // for (int i = 1; i <= mesh.GetNE(); i++)\n            for (auto ei : mesh.VolumeElements().Range())\n\t      {\n\t\tconst Element & el = mesh[ei]; // .VolumeElement (i);\n\t\tint ned;\n\t\tint tetedges[6][2] =\n\t\t  { { 1, 2 },\n\t\t    { 1, 3 },\n\t\t    { 1, 4 },\n\t\t    { 2, 3 },\n\t\t    { 2, 4 },\n\t\t    { 3, 4 } };\n\t\tint prismedges[6][2] =\n\t\t  { { 1, 2 },\n\t\t    { 1, 3 },\n\t\t    { 2, 4 },\n\t\t    { 4, 5 },\n\t\t    { 4, 6 },\n\t\t    { 5, 6 } };\n\t\tint pyramidedges[6][2] =\n\t\t  { { 1, 2 },\n\t\t    { 3, 4 },\n\t\t    { 1, 5 },\n\t\t    { 2, 5 },\n\t\t    { 3, 5 },\n\t\t    { 4, 5 } };\n\n\t\tint (*tip)[2];\n\n\t\tswitch (el.GetType())\n\t\t  {\n\t\t  case TET:\n\t\t    {\n\t\t      tip = tetedges;\n\t\t      ned = 6;\n\t\t      break;\n\t\t    }\n\t\t  case PRISM:\n\t\t    {\n\t\t      tip = prismedges;\n\t\t      ned = 6;\n\t\t      break;\n\t\t    }\n\t\t  case PYRAMID:\n\t\t    {\n\t\t      tip = pyramidedges;\n\t\t      ned = 6;\n\t\t      break;\n\t\t    }\n                  default:\n                    throw NgException(\"Bisect, element type not handled in switch, 3\");\n\t\t  }\n\t      \n\t\tfor (int j = 0; j < ned; j++)\n\t\t  {\n\t\t    PointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));\n\t\t    i2.Sort();\n\t\t    if (!edgenumber.Used(i2))\n\t\t      {\n\t\t\tlen2 = Dist (mesh.Point (i2.I1()),\n\t\t\t\t     mesh.Point (i2.I2()));\n\t\t\tif (len2 < maxlen2)\n\t\t\t  {\n\t\t\t    maxlen2 = len2;\n\t\t\t    ep = i2;\n\t\t\t    found = true;\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t    if (found)\n\t      {\n\t\tcnt++;\n\t\tedgenumber.Set (ep, cnt);\n\t      \n\t      \n\t\t// find connected edges:\n\t\tbool go_on = false;\n\t\tdo\n\t\t  {\n\t\t    go_on = false;\n\t\t    //for (int i = 1; i <= mesh.GetNE(); i++)\n                    for (auto ei : mesh.VolumeElements().Range())\n\t\t      {\n\t\t\tconst Element & el = mesh[ei]; // .VolumeElement (i);\t      \n\t\t\tif (el.GetNP() != 6) continue;\n\n\t\t\tint prismpairs[3][4] =\n\t\t\t  { { 1, 2, 4, 5 },\n\t\t\t    { 2, 3, 5, 6 },\n\t\t\t    { 1, 3, 4, 6 } };\n\n\t\t\tint pyramidpairs[3][4] =\n\t\t\t  { { 1, 2, 4, 3 },\n\t\t\t    { 1, 5, 4, 5 },\n\t\t\t    { 2, 5, 3, 5 } };\n\t\t      \n\t\t\tint (*pairs)[4];\n\t\t\tswitch (el.GetType())\n\t\t\t  {\n\t\t\t  case PRISM:\n\t\t\t    {\n\t\t\t      pairs = prismpairs;\n\t\t\t      break;\n\t\t\t    }\n\t\t\t  case PYRAMID:\n\t\t\t    {\n\t\t\t      pairs = pyramidpairs;\n\t\t\t      break;\n\t\t\t    }\n                          default:\n                            throw NgException(\"Bisect, element type not handled in switch, 3a\");\n\t\t\t  }\n\n\t\t\tfor (int j = 0; j < 3; j++)\n\t\t\t  {\n\t\t\t    PointIndices<2> e1 (el.PNum(pairs[j][0]), \n                                                el.PNum(pairs[j][1]));\n\t\t\t    PointIndices<2> e2 (el.PNum(pairs[j][2]), \n                                                el.PNum(pairs[j][3]));\n\t\t\t    e1.Sort();\n\t\t\t    e2.Sort();\n\t\t\t  \n\t\t\t    bool used1 = edgenumber.Used (e1);\n\t\t\t    bool used2 = edgenumber.Used (e2);\n\t\t\t  \n\t\t\t    if (used1 && !used2)\n\t\t\t      {\n\t\t\t\tcnt++;\n\t\t\t\tedgenumber.Set (e2, cnt);\n\t\t\t\tgo_on = true;\n\t\t\t      }\n\t\t\t    if (used2 && !used1)\n\t\t\t      {\n\t\t\t\tcnt++;\n\t\t\t\tedgenumber.Set (e1, cnt);\n\t\t\t\tgo_on = true;\n\t\t\t      }\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t\twhile (go_on);\n\t      }\n\t  }\n\twhile (found);\n\n\treturn cnt;\n      }\n  }\n\n\n\n  template <typename T_EDGENUMBER>\n  void BTDefineMarkedTet (const Element & el,\n\t\t\t  T_EDGENUMBER & edgenumber,\n\t\t\t  MarkedTet & mt)\n  {\n    for (int i = 0; i < 4; i++)\n      mt.pnums[i] = el[i];\n\n    mt.marked = 0;\n    mt.flagged = 0;\n\n    mt.incorder = 0;\n    mt.order = 1;\n  \n    int val = 0;\n    // find marked edge of tet:\n    for (int i = 0; i < 3; i++)\n      for (int j = i+1; j < 4; j++)\n\t{\n\t  PointIndices<2> i2(mt.pnums[i], mt.pnums[j]);\n\t  i2.Sort();\n\t  int hval = edgenumber.Get(i2);\n\t  if (hval > val)\n\t    {\n\t      val = hval;\n\t      mt.tetedge1 = i;\n\t      mt.tetedge2 = j;    \n\t    }\n\t}\n\n\n    // find marked edges of faces:\n    for (int k = 0; k < 4; k++)\n      {\n\tval = 0;\n\tfor (int i = 0; i < 3; i++)\n\t  for (int j = i+1; j < 4; j++)\n\t    if (i != k && j != k)\n\t      {\n                /*\n\t\tPointIndices<2> i2(mt.pnums[i], mt.pnums[j]);\n\t\ti2.Sort();\n\t\tint hval = edgenumber.Get(i2);\n                */\n\t\tint hval = edgenumber[ { mt.pnums[i], mt.pnums[j] } ];\n\t\tif (hval > val)\n\t\t  {\n\t\t    val = hval;\n                    int hi = 6 - k - i - j;\n                    mt.faceedges[k] = char(hi);\n\t\t  }\n\t      }\n      }\n  }\n\n\n\n  template <typename T_EDGENUMBER>  \n  void BTDefineMarkedPrism (const Element & el,\n\t\t\t    T_EDGENUMBER & edgenumber,\n\t\t\t    MarkedPrism & mp)\n  {\n    if (el.GetType() == PRISM ||\n\tel.GetType() == PRISM12)\n      {\n\tfor (int i = 0; i < 6; i++)\n\t  mp.pnums[i] = el[i];\n      }\n    else if (el.GetType() == PYRAMID)\n      {\n\tstatic int map[6] = \n\t  { 1, 2, 5, 4, 3, 5 };\n\tfor (int i = 0; i < 6; i++)\n\t  mp.pnums[i] = el.PNum(map[i]);\n      }\n    else if (el.GetType() == TET ||\n\t     el.GetType() == TET10)\n      {\n\tstatic int map[6] = \n\t  { 1, 4, 3, 2, 4, 3 };\n\tfor (int i = 0; i < 6; i++)\n\t  mp.pnums[i] = el.PNum(map[i]);\n      \n      }\n    else\n      {\n\tPrintSysError (\"Define marked prism called for non-prism and non-pyramid\");\n      }\n  \n\n\n    mp.marked = 0;\n\n    mp.incorder = 0;\n    mp.order = 1;\n\n    int val = 0;\n    for (int i = 0; i < 2; i++)\n      for (int j = i+1; j < 3; j++)\n\t{\n\t  PointIndices<2> i2(mp.pnums[i], mp.pnums[j]);\n\t  i2.Sort();\n\t  int hval = edgenumber.Get(i2);\n\t  if (hval > val)\n\t    {\n\t      val = hval;\n\t      mp.markededge = 3 - i - j;\n\t    }\n\t}\n  }\n\n\n  template <typename T_EDGENUMBER>\n  bool BTDefineMarkedId(const Element2d & el, \n\t\t\tT_EDGENUMBER & edgenumber, \n\t\t\tconst idmap_type & idmap,\n\t\t\tMarkedIdentification & mi)\n  {\n\n    bool identified = true;\n    mi.np = el.GetNP();\n    // int min1(0),min2(0);\n    PointIndex min1(PointIndex::INVALID), min2(PointIndex::INVALID);\n    for(int j = 0; identified && j < mi.np; j++)\n      {\n\tmi.pnums[j] = el[j];\n\tmi.pnums[j+mi.np] = idmap[el[j]];\n\n\tif(j == 0 || el[j] < min1)\n\t  min1 = el[j];\n\tif(j == 0 || mi.pnums[j+mi.np] < min2)\n\t  min2 = mi.pnums[j+mi.np];\n\n\tidentified = (mi.pnums[j+mi.np].IsValid() && mi.pnums[j+mi.np] != mi.pnums[j]);\n      }\n\n    identified = identified && (min1 < min2);\n\n    if(identified)\n      {\n\tmi.marked = 0;\n\t\n\tmi.incorder = 0;\n\tmi.order = 1;\n\n\tint val = 0;\n\tfor (int i = 0; i < mi.np; i++)\n\t  {\n\t    PointIndices<2> i2(mi.pnums[i], mi.pnums[(i+1)%mi.np]);\n\t    i2.Sort();\n\t    int hval = edgenumber.Get(i2);\n\t    if (hval > val)\n\t      {\n\t\tval = hval;\n\t\tmi.markededge = i;\n\t      }\n\t  }\n      }\n\n    return identified;\n  }\n\n  \n  template <typename T_EDGENUMBER>\n  void BTDefineMarkedTri (const Element2d & el,\n\t\t\t  T_EDGENUMBER & edgenumber,\n\t\t\t  MarkedTri & mt)\n  {\n    for (int i = 0; i < 3; i++)\n      {\n\tmt.pnums[i] = el[i];\n\tmt.pgeominfo[i] = el.GeomInfoPi (i+1);\n      }\n\n    mt.marked = 0;\n    mt.surfid = el.GetIndex();\n\n    mt.incorder = 0;\n    mt.order = 1;\n\n    int val = -1;\n    for (int i = 0; i < 2; i++)\n      for (int j = i+1; j < 3; j++)\n\t{\n          /*\n\t  PointIndices<2> i2(mt.pnums[i], mt.pnums[j]);\n\t  i2.Sort();\n\t  int hval = edgenumber.Get(i2);\n          */\n          int hval = edgenumber[ SortedPointIndices<2>(mt.pnums[i], mt.pnums[j]) ];\n          // int hval = edgenumber[ { mt.pnums[i], mt.pnums[j] }];\n\t  if (hval > val)\n\t    {\n\t      val = hval;\n\t      mt.markededge = 3 - i - j;\n\t    }\n\t}\n  }\n  \n\n  \n  void PrettyPrint(ostream & ost, const MarkedTri & mt)\n  {\n    ost << \"MarkedTrig: \" << endl;\n    ost << \"  pnums = \"; for (int i=0; i<3; i++) ost << mt.pnums[i] << \" \"; ost << endl; \n    ost << \"  marked = \" << mt.marked << \", markededge=\" << mt.markededge << endl;\n    for(int i=0; i<2; i++)\n      for(int j=i+1; j<3; j++)\n\tif(mt.markededge == 3-i-j)\n\t  ost << \"  marked edge pnums = \" << mt.pnums[i] << \" \" << mt.pnums[j] << endl;\n  }\n\n\n  void PrettyPrint(ostream & ost, const MarkedQuad & mq)\n  {\n    ost << \"MarkedQuad: \" << endl;\n    ost << \"  pnums = \"; for (int i=0; i<4; i++) ost << mq.pnums[i] << \" \"; ost << endl; \n    ost << \"  marked = \" << mq.marked << \", markededge=\" << mq.markededge << endl;\n  }\n\n\n\n\n  template <typename T_EDGENUMBER>\n  void BTDefineMarkedQuad (const Element2d & el,\n\t\t\t   T_EDGENUMBER & edgenumber,\n\t\t\t   MarkedQuad & mq)\n  {\n    for (int i = 0; i < 4; i++)\n      {\n        mq.pnums[i] = el[i];\n        mq.pgeominfo[i] = el.GeomInfoPi (i+1);\n      }\n    Swap (mq.pnums[2], mq.pnums[3]);\n    Swap (mq.pgeominfo[2], mq.pgeominfo[3]);\n\n    mq.marked = 0;\n    mq.markededge = 0;\n    mq.surfid = el.GetIndex();\n  }\n\n\n\n\n  // mark elements due to local h\n  int BTMarkTets (T_MTETS & mtets,\n\t\t  T_MPRISMS & mprisms,\n\t\t  const Mesh & mesh)\n  {\n    int marked = 0;\n\n    int np = mesh.GetNP();\n    Vector hv(np);\n    for (int i = 0; i < np; i++)\n      hv(i) = mesh.GetH (mesh.Point(i+1));\n\n    double hfac = 1;\n  \n    for (int step = 1; step <= 2; step++)\n      {\n\t// for (int i = 1; i <= mtets.Size(); i++)\n        for (ElementIndex ei : mtets.Range())\n\t  {\n\t    double h = 0;\n\t  \n\t    for (int j = 0; j < 3; j++)\n\t      for (int k = j+1; k < 4; k++)\n\t\t{\n\t\t  const Point<3> & p1 = mesh.Point (mtets[ei].pnums[j]);\n\t\t  const Point<3> & p2 = mesh.Point (mtets[ei].pnums[k]);\n\t\t  double hh = Dist2 (p1, p2);\n\t\t  if (hh > h) h = hh;\n\t\t}\n\t    h = sqrt (h);\n\t  \n\t    double hshould = 1e10;\n\t    for (int j = 0; j < 4; j++)\n\t      {\n\t\tdouble hi = hv (mtets[ei].pnums[j]-IndexBASE<PointIndex>());\n\t\tif (hi < hshould)\n\t\t  hshould = hi;\n\t      }\n\t  \n\t\n\t    if (step == 1)\n\t      {\n\t\tif (h / hshould > hfac)\n\t\t  hfac = h / hshould;\n\t      }\n\t    else\n\t      {\n\t\tif (h > hshould * hfac)\n\t\t  {\n\t\t    mtets[ei].marked = 1;\n\t\t    marked = 1;\n\t\t  }\n\t\telse\n\t\t  mtets[ei].marked = 0;\n\t      }\n\t  }\n\tfor (int i = 1; i <= mprisms.Size(); i++)\n\t  {\n\t    double h = 0;\n\t  \n\t    for (int j = 0; j < 2; j++)\n\t      for (int k = j+1; k < 3; k++)\n\t\t{\n\t\t  const Point<3> & p1 = mesh.Point (mprisms.Get(i).pnums[j]);\n\t\t  const Point<3> & p2 = mesh.Point (mprisms.Get(i).pnums[k]);\n\t\t  double hh = Dist2 (p1, p2);\n\t\t  if (hh > h) h = hh;\n\t\t}\n\t    h = sqrt (h);\n\t  \n\t    double hshould = 1e10;\n\t    for (int j = 0; j < 6; j++)\n\t      {\n\t\tdouble hi = hv (mprisms.Get(i).pnums[j]-IndexBASE<PointIndex>());\n\t\tif (hi < hshould)\n\t\t  hshould = hi;\n\t      }\n\t  \n\t\n\t    if (step == 1)\n\t      {\n\t\tif (h / hshould > hfac)\n\t\t  hfac = h / hshould;\n\t      }\n\t    else\n\t      {\n\t\tif (h > hshould * hfac)\n\t\t  {\n\t\t    mprisms.Elem(i).marked = 1;\n\t\t    marked = 1;\n\t\t  }\n\t\telse\n\t\t  mprisms.Elem(i).marked = 0;\n\t      }\n\t  \n\t  }\n\n\n\n\tif (step == 1)\n\t  {\n\t    if (hfac > 2)\n\t      hfac /= 2;\n\t    else\n\t      hfac = 1;\n\t  }\n\n      }\n    return marked;\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void BTBisectTet (const MarkedTet & oldtet, PointIndex newp, \n\t\t    MarkedTet & newtet1, MarkedTet & newtet2)\n  {\n#ifdef DEBUG\n    *testout << \"bisect tet \" << oldtet << endl;\n#endif    \n    \n  \n    // points vis a vis from tet-edge\n    int vis1, vis2;\n    vis1 = 0;\n    while (vis1 == oldtet.tetedge1 || vis1 == oldtet.tetedge2)\n      vis1++;\n    vis2 = 6 - vis1 - oldtet.tetedge1 - oldtet.tetedge2;\n\n\n    \n\n\n    // is tet of type P ?\n    int istypep = 0;\n    for (int i = 0; i < 4; i++)\n      {\n\tint cnt = 0;\n\tfor (int j = 0; j < 4; j++)\n\t  if (oldtet.faceedges[j] == i)\n\t    cnt++;\n\tif (cnt == 3)\n\t  istypep = 1;\n      }\n\n\n  \n    for (int i = 0; i < 4; i++)\n      {\n\tnewtet1.pnums[i] = oldtet.pnums[i];\n\tnewtet2.pnums[i] = oldtet.pnums[i];\n      }\n    newtet1.flagged = istypep && !oldtet.flagged;\n    newtet2.flagged = istypep && !oldtet.flagged;\n\n    int nm = oldtet.marked - 1;\n    if (nm < 0) nm = 0;\n    newtet1.marked = nm;\n    newtet2.marked = nm;\n\n    newtet1.newest_vertex = oldtet.newest_vertex;\n\n#ifdef DEBUG\n    *testout << \"newtet1,before = \" << newtet1 << endl;\n    *testout << \"newtet2,before = \" << newtet2 << endl;\n#endif\n\n    for (int i = 0; i < 4; i++)\n      {\n\tif (i == oldtet.tetedge1)\n\t  {\n            newtet2.newest_vertex = i;\n\t    newtet2.pnums[i] = newp;\n\t    newtet2.faceedges[i] = oldtet.faceedges[i];  // inherited face\n\t    newtet2.faceedges[vis1] = i;        // cut faces\n\t    newtet2.faceedges[vis2] = i;\n\n\t    int j = 0;\n\t    while (j == i || j == oldtet.faceedges[i])\n\t      j++;\n\t    int k = 6 - i - oldtet.faceedges[i] - j;\n\t    newtet2.tetedge1 = j;                        // tet-edge\n\t    newtet2.tetedge2 = k;         \n\n\t    // new face:\n\t    if (istypep && oldtet.flagged)\n              {\n                int hi = 6 - oldtet.tetedge1 - j - k;\n                newtet2.faceedges[oldtet.tetedge2] = char(hi);\n              }\n\t    else\n\t      newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1;\n            \n#ifdef DEBUG\n            *testout << \"i = \" << i << \", j = \" << j << \" k = \" << k \n                     << \" oldtet.tetedge1 = \" << oldtet.tetedge1 \n                     << \" oldtet.tetedge2 = \" << oldtet.tetedge2\n                     << \"   6-oldtet.tetedge1-j-k = \" <<  6 - oldtet.tetedge1 - j - k \n                     << \"   6-oldtet.tetedge1-j-k = \" <<  short(6 - oldtet.tetedge1 - j - k)\n                     << endl;\n            *testout << \"vis1 = \" << vis1 << \", vis2 = \" << vis2 << endl;\n            for (int j = 0; j < 4; j++)\n              if (newtet2.faceedges[j] > 3)\n                {\n                  *testout << \"ERROR1\" << endl;\n                }\n#endif\n\t  }\n\n\tif (i == oldtet.tetedge2)\n\t  {\n\t    newtet1.pnums[i] = newp;\n\t    newtet1.faceedges[i] = oldtet.faceedges[i];  // inherited face\n\t    newtet1.faceedges[vis1] = i;\n\t    newtet1.faceedges[vis2] = i;\n\t    int j = 0;\n\t    while (j == i || j == oldtet.faceedges[i])\n\t      j++;\n\t    int k = 6 - i - oldtet.faceedges[i] - j;\n\t    newtet1.tetedge1 = j;        \n\t    newtet1.tetedge2 = k;\n\n\t    // new face:\n\t    if (istypep && oldtet.flagged)\n              {\n                int hi = 6 - oldtet.tetedge2 - j - k;\n                newtet1.faceedges[oldtet.tetedge1] = char(hi);\n              }\n\t    else\n\t      newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2;\n\n#ifdef DEBUG\n            for (int j = 0; j < 4; j++)\n              if (newtet2.faceedges[j] > 3)\n                {\n                  *testout << \"ERROR2\" << endl;\n                }\n#endif\n\t  }\n      }\n\n    newtet1.matindex = oldtet.matindex;\n    newtet2.matindex = oldtet.matindex;\n    newtet1.incorder = 0;\n    newtet1.order = oldtet.order;\n    newtet2.incorder = 0;\n    newtet2.order = oldtet.order;\n\n    // *testout << \"newtet1 =  \" << newtet1 << endl;\n    // *testout << \"newtet2 =  \" << newtet2 << endl;\n  }\n\n\n  \n\n  void BTBisectPrism (const MarkedPrism & oldprism, PointIndex newp1, PointIndex newp2,\n\t\t      MarkedPrism & newprism1, MarkedPrism & newprism2)\n  {\n    for (int i = 0; i < 6; i++)\n      {\n\tnewprism1.pnums[i] = oldprism.pnums[i];\n\tnewprism2.pnums[i] = oldprism.pnums[i];\n      }  \n    \n    int pe1 = 0;\n    if (pe1 == oldprism.markededge)\n      pe1++;\n    int pe2 = 3 - oldprism.markededge - pe1;\n\n    newprism1.pnums[pe2] = newp1;\n    newprism1.pnums[pe2+3] = newp2;\n    newprism1.markededge = pe2;\n    newprism2.pnums[pe1] = newp1;\n    newprism2.pnums[pe1+3] = newp2;\n    newprism2.markededge = pe1;\n\n    newprism1.matindex = oldprism.matindex;\n    newprism2.matindex = oldprism.matindex;\n\n    int nm = oldprism.marked - 1;\n    if (nm < 0) nm = 0;\n    newprism1.marked = nm;\n    newprism2.marked = nm;\n\n    newprism1.incorder = 0;\n    newprism1.order = oldprism.order;\n    newprism2.incorder = 0;\n    newprism2.order = oldprism.order;\n  }\n\n\n  void BTBisectIdentification (const MarkedIdentification & oldid,\n\t\t\t       Array<PointIndex> & newp,\n\t\t\t       MarkedIdentification & newid1,\n\t\t\t       MarkedIdentification & newid2)\n  {\n    for(int i=0; i<2*oldid.np; i++)\n      {\n\tnewid1.pnums[i] = oldid.pnums[i];\n\tnewid2.pnums[i] = oldid.pnums[i];\n      }\n    newid1.np = newid2.np = oldid.np;\n\n    if(oldid.np == 2)\n      {\n        newid1.pnums[1] = newp[0];\n        newid2.pnums[0] = newp[0];\n        newid1.pnums[3] = newp[1];\n        newid2.pnums[2] = newp[1];\n        newid1.markededge = 0;\n        newid2.markededge = 0;\n      }\n\n    if(oldid.np == 3)\n      {\n\tnewid1.pnums[(oldid.markededge+1)%3] = newp[0];\n\tnewid1.pnums[(oldid.markededge+1)%3+3] = newp[1];\n\tnewid1.markededge = (oldid.markededge+2)%3;\n\n\tnewid2.pnums[oldid.markededge] = newp[0];\n\tnewid2.pnums[oldid.markededge+3] = newp[1];\n\tnewid2.markededge = (oldid.markededge+1)%3;\n      }\n    else if(oldid.np == 4)\n      {\n\tnewid1.pnums[(oldid.markededge+1)%4] = newp[0];\n\tnewid1.pnums[(oldid.markededge+2)%4] = newp[2];\n\tnewid1.pnums[(oldid.markededge+1)%4+4] = newp[1];\n\tnewid1.pnums[(oldid.markededge+2)%4+4] = newp[3];\n\tnewid1.markededge = (oldid.markededge+3)%4;\n\n\tnewid2.pnums[oldid.markededge] = newp[0];\n\tnewid2.pnums[(oldid.markededge+3)%4] = newp[2];\n\tnewid2.pnums[oldid.markededge+4] = newp[1];\n\tnewid2.pnums[(oldid.markededge+3)%4+4] = newp[3];\n\tnewid2.markededge = (oldid.markededge+1)%4;\n      }\n\n    \n    int nm = oldid.marked - 1;\n    if (nm < 0) nm = 0;\n    newid1.marked = newid2.marked = nm;\n\n    newid1.incorder = newid2.incorder = 0;\n    newid1.order = newid2.order = oldid.order;\n  }\n\n\n  void BTBisectTri (const MarkedTri & oldtri, PointIndex newp, const PointGeomInfo & newpgi,\n\t\t    MarkedTri & newtri1, MarkedTri & newtri2)\n  {\n    for (int i = 0; i < 3; i++)\n      {\n\tnewtri1.pnums[i] = oldtri.pnums[i];\n\tnewtri1.pgeominfo[i] = oldtri.pgeominfo[i];\n\tnewtri2.pnums[i] = oldtri.pnums[i];\n\tnewtri2.pgeominfo[i] = oldtri.pgeominfo[i];\n      }  \n\n    int pe1 = 0;\n    if (pe1 == oldtri.markededge)\n      pe1++;\n    int pe2 = 3 - oldtri.markededge - pe1;\n\n    newtri1.pnums[pe2] = newp;\n    newtri1.pgeominfo[pe2] = newpgi;\n    newtri1.markededge = pe2;\n    newtri1.newest_vertex = oldtri.newest_vertex;\n\n    newtri2.pnums[pe1] = newp;\n    newtri2.pgeominfo[pe1] = newpgi;\n    newtri2.markededge = pe1;\n    newtri2.newest_vertex = pe1;\n\n    newtri1.surfid = oldtri.surfid;\n    newtri2.surfid = oldtri.surfid;\n\n    int nm = oldtri.marked - 1;\n    if (nm < 0) nm = 0;\n    newtri1.marked = nm;\n    newtri2.marked = nm;\n\n    newtri1.incorder = 0;\n    newtri1.order = oldtri.order;\n    newtri2.incorder = 0;\n    newtri2.order = oldtri.order;\n  }\n\n\n  void BTBisectQuad (const MarkedQuad & oldquad, \n\t\t     PointIndex newp1, const PointGeomInfo & npgi1, \n\t\t     PointIndex newp2, const PointGeomInfo & npgi2, \n\t\t     MarkedQuad & newquad1, MarkedQuad & newquad2)\n  {\n    for (int i = 0; i < 4; i++)\n      {\n\tnewquad1.pnums[i] = oldquad.pnums[i];\n\tnewquad1.pgeominfo[i] = oldquad.pgeominfo[i];\n\tnewquad2.pnums[i] = oldquad.pnums[i];\n\tnewquad2.pgeominfo[i] = oldquad.pgeominfo[i];\n      }  \n\n/*    if (oldquad.marked==1) // he/sz: 2d quads or 3d prism\n    {   \n      newquad1.pnums[1] = newp1;\n      newquad1.pgeominfo[1] = npgi1;\n      newquad1.pnums[3] = newp2;\n      newquad1.pgeominfo[3] = npgi2;\n\n      newquad2.pnums[0] = newp1;\n      newquad2.pgeominfo[0] = npgi1;\n      newquad2.pnums[2] = newp2;\n      newquad2.pgeominfo[2] = npgi2;\n    }\n      \n    else if (oldquad.marked==2) // he/sz: 2d quads only\n    {\n      newquad1.pnums[0] = newp1;\n      newquad1.pnums[1] = newp2;\n      newquad1.pnums[3] = oldquad.pnums[2];  \n      newquad1.pnums[2] = oldquad.pnums[0]; \n      newquad1.pgeominfo[0] = npgi1;\n      newquad1.pgeominfo[1] = npgi2;\n      newquad1.pgeominfo[3] = oldquad.pgeominfo[2]; \n      newquad1.pgeominfo[2] = oldquad.pgeominfo[0];\n\n      newquad2.pnums[0] = newp2;\n      newquad2.pnums[1] = newp1;\n      newquad2.pnums[3] = oldquad.pnums[1];  \n      newquad2.pnums[2] = oldquad.pnums[3]; \n      newquad2.pgeominfo[0] = npgi2;\n      newquad2.pgeominfo[1] = npgi1;\n      newquad2.pgeominfo[3] = oldquad.pgeominfo[1]; \n      newquad2.pgeominfo[2] = oldquad.pgeominfo[3];\n    }\n      \n    */\n      \n    if (oldquad.markededge==0 || oldquad.markededge==2)\n    {\n      newquad1.pnums[1] = newp1;\n      newquad1.pgeominfo[1] = npgi1;\n      newquad1.pnums[3] = newp2;\n      newquad1.pgeominfo[3] = npgi2;\n\n      newquad2.pnums[0] = newp1;\n      newquad2.pgeominfo[0] = npgi1;\n      newquad2.pnums[2] = newp2;\n      newquad2.pgeominfo[2] = npgi2;\n    }\n    else // 1 || 3 \n    {\n      newquad1.pnums[2] = newp1;\n      newquad1.pgeominfo[2] = npgi1;\n      newquad1.pnums[3] = newp2;\n      newquad1.pgeominfo[3] = npgi2;\n\n      newquad2.pnums[0] = newp1;\n      newquad2.pgeominfo[0] = npgi1;\n      newquad2.pnums[1] = newp2;\n      newquad2.pgeominfo[1] = npgi2;\n    }\n    newquad1.surfid = oldquad.surfid;\n    newquad2.surfid = oldquad.surfid;\n\n    int nm = oldquad.marked - 1;\n    if (nm < 0) nm = 0;\n\n    newquad1.marked = nm;\n    newquad2.marked = nm;\n    \n    if (nm==1)\n    {\n      newquad1.markededge=1;\n      newquad2.markededge=1;\n    }\n    else\n    {\n      newquad1.markededge=0;\n      newquad2.markededge=0;\n    }\n    \n  }\n\n  template <typename HASHTABLE_CUTEDGES>\n  int MarkHangingIdentifications(T_MIDS & mids, \n\t\t\t\t const HASHTABLE_CUTEDGES & cutedges)\n  {\n    int hanging = 0;\n    for (int i = 1; i <= mids.Size(); i++)\n      {\n\tif (mids.Elem(i).marked)\n\t  {\n\t    hanging = 1;\n\t    continue;\n\t  }\n\n\tconst int np = mids.Get(i).np;\n\tfor(int j = 0; j < np; j++)\n\t  {\n\t    PointIndices<2> edge1(mids.Get(i).pnums[j],\n                                  mids.Get(i).pnums[(j+1) % np]);\n\t    PointIndices<2> edge2(mids.Get(i).pnums[j+np],\n                                  mids.Get(i).pnums[((j+1) % np) + np]);\n\n\t    edge1.Sort();\n\t    edge2.Sort();\n\t    if (cutedges.Used (edge1) ||\n\t\tcutedges.Used (edge2))\n\t      {\n\t\tmids.Elem(i).marked = 1;\n\t\thanging = 1;\n\t      }\n\t  }\n      }\n\n    return hanging;\n  }\n\n\n  /*\n  void IdentifyCutEdges(Mesh & mesh,\n\t\t\tINDEX_2_CLOSED_HASHTABLE<int> & cutedges)\n  {\n    int i,j,k;\n\n    NgArray< NgArray<int,PointIndex::BASE>* > idmaps;\n    for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tidmaps.Append(new NgArray<int,PointIndex::BASE>);\n\tmesh.GetIdentifications().GetMap(i,*idmaps.Last());\n      }\n\n\n    \n    for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tconst Element2d & el2d = mesh[sei];\n\t\n\tfor(i = 0; i < el2d.GetNP(); i++)\n\t  {\n\t    INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);\n\t    e1.Sort();\n\n\t    if(!cutedges.Used(e1))\n\t      continue;\n\n\t    \n\t    for(k = 0; k < idmaps.Size(); k++)\n\t      {\n\t\tINDEX_2 e2((*idmaps[k])[e1.I1()],\n\t\t\t   (*idmaps[k])[e1.I2()]);\n\t\t\n\t\tif(e2.I1() == 0 || e2.I2() == 0 ||\n\t\t   e1.I1() == e2.I1() || e1.I2() == e2.I2())\n\t\t  continue;\n\t\t\n\t\te2.Sort();\n\n\t\tif(cutedges.Used(e2))\n\t\t  continue;\n\n\t\tPoint3d np = Center(mesh.Point(e2.I1()),\n\t\t\t\t    mesh.Point(e2.I2()));\n\t\tint newp = mesh.AddPoint(np);\n\t\tcutedges.Set(e2,newp);\n\t\t(*testout) << \"DAAA\" << endl;\n\t      }\n\t  }\n      }\n\n    \n    for(i=0; i<idmaps.Size(); i++)\n      delete idmaps[i];\n    idmaps.DeleteAll();\n  }\n  */\n\n\n  template <typename HASHTABLE_CUTEDGES>  \n  int MarkHangingTets (T_MTETS & mtets, \n\t\t       const HASHTABLE_CUTEDGES & cutedges,\n                       NgTaskManager tm)                       \n  {\n    static int timer = NgProfiler::CreateTimer (\"MarkHangingTets\");    \n    NgProfiler::RegionTimer reg (timer);    \n    \n    int hanging = 0;\n    // for (int i = 1; i <= mtets.Size(); i++)\n    ngcore::ParallelForRange\n      // (tm, mtets.Size(), [&] (size_t begin, size_t end)\n      (mtets.Range(), [&] (auto myrange)\n       {\n         bool my_hanging = false;\n         // for (size_t i = begin; i < end; i++)\n         for (auto ei : myrange)\n           {\n             MarkedTet & teti = mtets[ei];\n             \n             if (teti.marked)\n               {\n                 my_hanging = true;\n                 continue;\n               }\n             \n             for (int j = 0; j < 3; j++)\n               for (int k = j+1; k < 4; k++)\n                 {\n                   PointIndices<2> edge(teti.pnums[j],\n                                        teti.pnums[k]);\n                   edge.Sort();\n                   if (cutedges.Used (edge))\n                     {\n                       teti.marked = 1;\n                       my_hanging = true;\n                     }\n                 }\n           }\n         if (my_hanging) hanging = true;         \n       });\n\n    return hanging;\n  }\n\n\n  template <typename HASHTABLE_CUTEDGES>  \n  int MarkHangingPrisms (T_MPRISMS & mprisms, \n\t\t\t const HASHTABLE_CUTEDGES & cutedges)\n  {\n    int hanging = 0;\n    for (int i = 1; i <= mprisms.Size(); i++)\n      {\n\tif (mprisms.Elem(i).marked)\n\t  {\n\t    hanging = 1;\n\t    continue;\n\t  }\n\n\tfor (int j = 0; j < 2; j++)\n\t  for (int k = j+1; k < 3; k++)\n\t    {\n\t      PointIndices<2> edge1(mprisms.Get(i).pnums[j],\n                                    mprisms.Get(i).pnums[k]);\n\t      PointIndices<2> edge2(mprisms.Get(i).pnums[j+3],\n                                    mprisms.Get(i).pnums[k+3]);\n\t      edge1.Sort();\n\t      edge2.Sort();\n\t      if (cutedges.Used (edge1) ||\n\t\t  cutedges.Used (edge2))\n\t\t{\n\t\t  mprisms.Elem(i).marked = 1;\n\t\t  hanging = 1;\n\t\t}\n\t    }\n      }\n    return hanging;\n  }\n\n\n  template <typename HASHTABLE_CUTEDGES>\n  bool MarkHangingTris (T_MTRIS & mtris, \n                        const HASHTABLE_CUTEDGES & cutedges,\n                        NgTaskManager tm)\n  {\n    bool hanging = false;\n    // for (int i = 1; i <= mtris.Size(); i++)\n    // for (auto & tri : mtris)\n    ParallelForRange\n      (tm, mtris.Size(), [&] (size_t begin, size_t end)\n       {\n         bool my_hanging = false;\n         for (size_t i = begin; i < end; i++)\n           {\n             auto & tri = mtris[i];\n             if (tri.marked)\n               {\n                 my_hanging = true;\n                 continue; \n               }\n             for (int j = 0; j < 2; j++)\n               for (int k = j+1; k < 3; k++)\n                 {\n                   /*\n                   PointIndices<2> edge(tri.pnums[j],\n                                        tri.pnums[k]);\n                   edge.Sort();\n                   if (cutedges.Used (edge))\n                   */\n                   if (cutedges.Used( { tri.pnums[j], tri.pnums[k] } ))\n                     {\n                       tri.marked = 1;\n                       my_hanging = true;\n                     }\n                 }\n           }\n         if (my_hanging) hanging = true;\n      });\n    return hanging;\n  }\n\n\n  template <typename HASHTABLE_CUTEDGES>\n  int MarkHangingQuads (T_MQUADS & mquads, \n\t\t\tconst HASHTABLE_CUTEDGES & cutedges)\n  {\n    int hanging = 0;\n    for (int i = 1; i <= mquads.Size(); i++)\n      {\n\tif (mquads.Elem(i).marked)\n\t  {\n\t    hanging = 1;\n\t    continue;\n\t  }\n\n\tPointIndices<2> edge1(mquads.Get(i).pnums[0],\n                              mquads.Get(i).pnums[1]);\n\tPointIndices<2> edge2(mquads.Get(i).pnums[2],\n                              mquads.Get(i).pnums[3]);\n\tedge1.Sort();\n\tedge2.Sort();\n\tif (cutedges.Used (edge1) ||\n\t    cutedges.Used (edge2))\n\t  {\n\t    mquads.Elem(i).marked = 1;\n            mquads.Elem(i).markededge = 0;\n\t    hanging = 1;\n            continue;\n\t  }\n          \n        // he/sz: second case: split horizontally\n        PointIndices<2> edge3(mquads.Get(i).pnums[1],\n                              mquads.Get(i).pnums[3]);\n        PointIndices<2> edge4(mquads.Get(i).pnums[2],\n                              mquads.Get(i).pnums[0]);\n\n        edge3.Sort();\n        edge4.Sort();\n        if (cutedges.Used (edge3) ||\n            cutedges.Used (edge4))\n        {\n          mquads.Elem(i).marked = 1;\n          mquads.Elem(i).markededge = 1;\n          hanging = 1; \n          continue; \n        }\n    \n      }\n    return hanging;\n  }\n\n\n\n  void ConnectToNodeRec (int node, int tonode, \n\t\t\t const TABLE<int> & conto, NgArray<int> & connecttonode)\n  {\n    //  (*testout) << \"connect \" << node << \" to \" << tonode << endl;\n    for (int i = 1; i <= conto.EntrySize(node); i++)\n      {\n\tint n2 = conto.Get(node, i);\n\tif (!connecttonode.Get(n2))\n\t  {\n\t    connecttonode.Elem(n2) = tonode;\n\t    ConnectToNodeRec (n2, tonode, conto, connecttonode);\n\t  }\n      }\n  }\n\n  BisectionInfo::BisectionInfo()\n  {\n    mtets = make_unique<T_MTETS>();\n    mprisms = make_unique<T_MPRISMS>();\n    mids = make_unique<T_MIDS>();\n    mtris = make_unique<T_MTRIS>();\n    mquads = make_unique<T_MQUADS>();\n  }\n\n  BisectionInfo::~BisectionInfo() {}\n\n  void WriteMarkedElements(const Mesh& mesh, ostream & ost)\n  {\n    ost << \"Marked Elements\\n\";\n    const auto& mtets = *mesh.bisectioninfo.mtets;\n    const auto& mprisms = *mesh.bisectioninfo.mprisms;\n    const auto& mids = *mesh.bisectioninfo.mids;\n    const auto& mtris = *mesh.bisectioninfo.mtris;\n    const auto& mquads = *mesh.bisectioninfo.mquads;\n    ost << mtets.Size() << \"\\n\";\n    for(auto ei : mtets.Range())\n      ost << mtets[ei];\n\n    ost << mprisms.Size() << \"\\n\";\n    for(int i=0; i<mprisms.Size(); i++)\n      ost << mprisms[i];\n\n    ost << mids.Size() << \"\\n\";\n    for(int i=0; i<mids.Size(); i++)\n      ost << mids[i];\n\n    ost << mtris.Size() << \"\\n\";\n    for(int i=0; i<mtris.Size(); i++)\n      ost << mtris[i];\n\n    ost << mquads.Size() << \"\\n\";\n    for(int i=0; i<mquads.Size(); i++)\n      ost << mquads[i];\n    ost << endl;\n  }\n\n  bool ReadMarkedElements(istream & ist, const Mesh & mesh)\n  {\n    auto& mtets = *mesh.bisectioninfo.mtets;\n    auto& mprisms = *mesh.bisectioninfo.mprisms;\n    auto& mids = *mesh.bisectioninfo.mids;\n    auto& mtris = *mesh.bisectioninfo.mtris;\n    auto& mquads = *mesh.bisectioninfo.mquads;\n\n    string auxstring(\"\");\n    if(ist)\n      ist >> auxstring;\n\n    if(auxstring != \"Marked\")\n      return false;\n\n    if(ist)\n      ist >> auxstring;\n\n    if(auxstring != \"Elements\")\n      return false;\n\n    int size;\n\n    ist >> size;\n    mtets.SetSize(size);\n    constexpr auto PI0 = IndexBASE<PointIndex>();\n    // for(int i=0; i<size; i++)\n    for (auto ei : ngcore::T_Range<ElementIndex>(size) )\n      {\n        ist >> mtets[ei];\n        if(mtets[ei].pnums[0] >= PI0+mesh.GetNV() || \n           mtets[ei].pnums[1] >= PI0+mesh.GetNV() || \n           mtets[ei].pnums[2] >= PI0+mesh.GetNV() || \n           mtets[ei].pnums[3] >= PI0+mesh.GetNV())\n          return false;\n      }\n\n    ist >> size;\n    mprisms.SetSize(size);\n    for(int i=0; i<size; i++)\n      ist >> mprisms[i];\n\n    ist >> size;\n    mids.SetSize(size);\n    for(int i=0; i<size; i++)\n      ist >> mids[i];\n\n    ist >> size;\n    mtris.SetSize(size);\n    for(int i=0; i<size; i++)\n      ist >> mtris[i];\n\n    ist >> size;\n    mquads.SetSize(size);\n    for(int i=0; i<size; i++)\n      ist >> mquads[i];\n\n    return true;\n  }\n\n\n\n\n\n  void BisectTetsCopyMesh (Mesh & mesh, const NetgenGeometry *,\n\t\t\t   BisectionOptions & opt,\n\t\t\t   const NgArray<idmap_type*> & idmaps,\n\t\t\t   const string & refinfofile)\n  {\n    auto& mtets = *mesh.bisectioninfo.mtets;\n    auto& mprisms = *mesh.bisectioninfo.mprisms;\n    auto& mids = *mesh.bisectioninfo.mids;\n    auto& mtris = *mesh.bisectioninfo.mtris;\n    auto& mquads = *mesh.bisectioninfo.mquads;\n    if (mesh.GetDimension() < 2)\n      throw Exception (\"Mesh bisection is available in 2D and 3D\");\n    // mtets.SetName (\"bisection, tets\");\n    // mprisms.SetName (\"bisection, prisms\");\n    // mtris.SetName (\"bisection, trigs\");\n    // nmquads.SetName (\"bisection, quads\");\n    // mids.SetName (\"bisection, identifications\");\n\n    //int np = mesh.GetNP();\n    int ne = mesh.GetNE();\n    int nse = mesh.GetNSE();\n\n    /*\n      if (mtets.Size() + mprisms.Size() == mesh.GetNE())\n      return;\n    */\n\n    bool readok = false;\n\n    if(refinfofile != \"\")\n      {\n\tPrintMessage(3,\"Reading marked-element information from \\\"\",refinfofile,\"\\\"\");\n\tifstream ist(refinfofile.c_str());\n\n\treadok = ReadMarkedElements(ist,mesh);\n\n\tist.close();\n      }\n\n    if(!readok)\n      {\n\tPrintMessage(3,\"resetting marked-element information\");\n\tmtets.SetSize(0);\n\tmprisms.SetSize(0);\n\tmids.SetSize(0);\n\tmtris.SetSize(0);\n\tmquads.SetSize(0);\n\t\n\t\n\tINDEX_2_HASHTABLE<int> shortedges(100);\n\t// for (int i = 1; i <= ne; i++)\n        for (auto ei : mesh.VolumeElements().Range())\n\t  {\n\t    const Element & el = mesh[ei];\n\t    if (el.GetType() == PRISM ||\n\t\tel.GetType() == PRISM12)\n\t      {\n\t\tfor (int j = 1; j <= 3; j++)\n\t\t  {\n\t\t    PointIndices<2> se(el.PNum(j), el.PNum(j+3));\n\t\t    se.Sort();\n\t\t    shortedges.Set (se, 1);\n\t\t  }\n\t      }\n\t  }\n\t\n\t\n\t\n\t// INDEX_2_HASHTABLE<int> edgenumber(np);\n        // INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);  \n        // ClosedHashTable<INDEX_2, int> edgenumber(9*ne+4*nse);\n        ClosedHashTable<SortedPointIndices<2>, int> edgenumber(9*ne+4*nse);\n\tBTSortEdges (mesh, idmaps, edgenumber);\n\t\n\t\n\t// for (int i = 1; i <= ne; i++)\n        for (auto ei : mesh.VolumeElements().Range())\n\t  {\n\t    const Element & el = mesh[ei];\n\t    \n\t    switch (el.GetType())\n\t      {\n\t      case TET:\n\t      case TET10:\n\t\t{\n\t\t  // if tet has short edge, it is handled as degenerated prism\n\t\t  \n\t\t  int foundse = 0;\n\t\t  for (int j = 1; j <= 3; j++)\n\t\t    for (int k = j+1; k <= 4; k++)\n\t\t      {\n\t\t\tPointIndices<2> se(el.PNum(j), el.PNum(k));\n\t\t\tse.Sort();\n\t\t\tif (shortedges.Used (se))\n\t\t\t  {\n\t\t\t    //\t\t      cout << \"tet converted to prism\" << endl;\n\t\t\t    \n\t\t\t    foundse = 1;\n\t\t\t    int p3 = 1;\n\t\t\t    while (p3 == j || p3 == k)\n\t\t\t      p3++;\n\t\t\t    int p4 = 10 - j - k - p3;\n\t\t\t    \n\t\t\t    // even permutation ?\n\t\t\t    int pi[4];\n\t\t\t    pi[0] = j;\n\t\t\t    pi[1] = k;\n\t\t\t    pi[2] = p3;\n\t\t\t    pi[3] = p4;\n\t\t\t    int cnt = 0;\n\t\t\t    for (int l = 1; l <= 4; l++)\n\t\t\t      for (int m = 0; m < 3; m++)\n\t\t\t\tif (pi[m] > pi[m+1])\n\t\t\t\t  {\n\t\t\t\t    Swap (pi[m], pi[m+1]);\n\t\t\t\t    cnt++;\n\t\t\t\t  }\n\t\t\t    if (cnt % 2)\n\t\t\t      Swap (p3, p4);\n\t\t\t    \n\t\t\t    Element hel = el;\n\t\t\t    hel.PNum(1) = el.PNum(j);\n\t\t\t    hel.PNum(2) = el.PNum(k);\n\t\t\t    hel.PNum(3) = el.PNum(p3);\n\t\t\t    hel.PNum(4) = el.PNum(p4);\n\t\t\t    \n\t\t\t    MarkedPrism mp;\n\t\t\t    BTDefineMarkedPrism (hel, edgenumber, mp);\n\t\t\t    mp.matindex = el.GetIndex();\n\t\t\t    mprisms.Append (mp);\n\t\t\t  }\n\t\t      }\n\t\t  if (!foundse)\n\t\t    {\n\t\t      MarkedTet mt;\n\t\t      BTDefineMarkedTet (el, edgenumber, mt);\n\t\t      mt.matindex = el.GetIndex();\n\t\t      mtets.Append (mt);\n\t\t    }\n\t\t  break;\n\t\t}\n\t      case PYRAMID:\n\t\t{\n\t\t  // eventually rotate\n\t\t  MarkedPrism mp;\n\t\t  \n\t\t  PointIndices<2> se(el.PNum(1), el.PNum(2));\n\t\t  se.Sort();\n\t\t  if (shortedges.Used (se))\n\t\t    {\n\t\t      Element hel = el;\n\t\t      hel.PNum(1) = el.PNum(2);\n\t\t      hel.PNum(2) = el.PNum(3);\n\t\t      hel.PNum(3) = el.PNum(4);\n\t\t      hel.PNum(4) = el.PNum(1);\n\t\t      BTDefineMarkedPrism (hel, edgenumber, mp);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      BTDefineMarkedPrism (el, edgenumber, mp);\n\t\t    }\n\t\t  \n\t\t  mp.matindex = el.GetIndex();\n\t\t  mprisms.Append (mp);\n\t\t  break;\n\t\t}\n\t      case PRISM:\n\t      case PRISM12:\n\t\t{\n\t\t  MarkedPrism mp;\n\t\t  BTDefineMarkedPrism (el, edgenumber, mp);\n\t\t  mp.matindex = el.GetIndex();\n\t\t  mprisms.Append (mp);\n\t\t  break;\n\t\t}\n              default:\n                throw NgException(\"Bisect, element type not handled in switch, 4\");\n\t      }\n\t  }\n\t\n\t// for (int i = 1; i <= nse; i++)\n        /*\n        for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n\t  {\n\t    const Element2d & el = mesh[sei];\n        */\n        for (const Element2d & el  : mesh.SurfaceElements())\n          {\n\t    if (el.GetType() == TRIG ||\n\t\tel.GetType() == TRIG6)\n\t      {\n\t\tMarkedTri mt;\n\t\tBTDefineMarkedTri (el, edgenumber, mt);\n\t\tmtris.Append (mt);\n\t      }\n\t    else\n\t      {\n\t\tMarkedQuad mq;\n\t\tBTDefineMarkedQuad (el, edgenumber, mq);\n\t\tmquads.Append (mq);\n\t      }\n\n            if(mesh.GetDimension() == 3)\n              {\n                MarkedIdentification mi;\n                for(int j=0; j<idmaps.Size(); j++)\n                  if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))\n                    mids.Append(mi);\n              }\n\t  }\n        if(mesh.GetDimension() == 2)\n          {\n            /*\n            for (SegmentIndex j=0; j<mesh.GetNSeg(); j++)\n              {\n                auto seg = mesh[j];\n            */\n            for (const Segment & seg : mesh.LineSegments())\n              {\n                for (auto map : idmaps)\n                  {\n                    if (seg[0].IsValid() && seg[1].IsValid() && (*map)[seg[0]].IsValid() && (*map)[seg[1]].IsValid())\n                      {\n                        MarkedIdentification mi;\n                        mi.np = 2;\n                        mi.pnums[0] = seg[0];\n                        mi.pnums[1] = seg[1];\n                        mi.pnums[2] = (*map)[seg[0]];\n                        mi.pnums[3] = (*map)[seg[1]];\n                        auto min1 = mi.pnums[0] < mi.pnums[1] ? mi.pnums[0] : mi.pnums[1];\n                        auto min2 = mi.pnums[2] < mi.pnums[3] ? mi.pnums[2] : mi.pnums[3];\n                        if (min1 > min2)\n                          continue;\n                        mi.marked = 0;\n                        mi.markededge = 0;\n                        mi.incorder = 0;\n                        mids.Append(mi);\n                      }\n                  }\n              }\n          }\n      }\n\t\n\n\n\n    mesh.mlparentelement.SetSize(ne);\n    // for (int i = 1; i <= ne; i++)\n    // mesh.mlparentelement.Elem(i) = 0;\n    mesh.mlparentelement = ElementIndex::INVALID;\n    \n    mesh.mlparentsurfaceelement.SetSize(nse);\n    // for (int i = 1; i <= nse; i++)\n    // mesh.mlparentsurfaceelement.Elem(i) = 0;\n    mesh.mlparentsurfaceelement = SurfaceElementIndex::INVALID;    \n  \n    if (printmessage_importance>0)\n    {\n      ostringstream str1,str2;\n      str1 << \"copied \" << mtets.Size() << \" tets, \" << mprisms.Size() << \" prisms\";\n      str2 << \"       \" << mtris.Size() << \" trigs, \" << mquads.Size() << \" quads\";\n\n      PrintMessage(4,str1.str());\n      PrintMessage(4,str2.str());\n    }\n  }\n\n\n  /*\n  void UpdateEdgeMarks2(Mesh & mesh,\n\t\t\tconst NgArray< NgArray<int,PointIndex::BASE>* > & idmaps)\n  {\n    NgArray< NgArray<MarkedTet>*,PointIndex::BASE > mtets_old(mesh.GetNP());\n    NgArray< NgArray<MarkedPrism>*,PointIndex::BASE > mprisms_old(mesh.GetNP());\n    NgArray< NgArray<MarkedIdentification>*,PointIndex::BASE > mids_old(mesh.GetNP());\n    NgArray< NgArray<MarkedTri>*,PointIndex::BASE > mtris_old(mesh.GetNP());\n    NgArray< NgArray<MarkedQuad>*,PointIndex::BASE > mquads_old(mesh.GetNP());\n\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      mtets_old[i] = new NgArray<MarkedTet>;\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      mprisms_old[i] = new NgArray<MarkedPrism>;\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      mids_old[i] = new NgArray<MarkedIdentification>;\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      mtris_old[i] = new NgArray<MarkedTri>;\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      mquads_old[i] = new NgArray<MarkedQuad>;\n\n    for(int i=0; i<mtets.Size(); i++)\n      mtets_old[mtets[i].pnums[0]]->Append(mtets[i]);\n    for(int i=0; i<mprisms.Size(); i++)\n      mprisms_old[mprisms[i].pnums[0]]->Append(mprisms[i]);\n    for(int i=0; i<mids.Size(); i++)\n      mids_old[mids[i].pnums[0]]->Append(mids[i]);\n    for(int i=0; i<mtris.Size(); i++)\n      {\n\t(*testout) << \"i \" << i << endl;\n\t(*testout) << \"mtris[i] \" << mtris[i].pnums[0] << \" \" << mtris[i].pnums[1] << \" \" << mtris[i].pnums[2] << endl; \n\tmtris_old[mtris[i].pnums[0]]->Append(mtris[i]);\n      }\n    for(int i=0; i<mquads.Size(); i++)\n      mquads_old[mquads[i].pnums[0]]->Append(mquads[i]);\n\n   \n    \n    int np = mesh.GetNP();\n    int ne = mesh.GetNE();\n    int nse = mesh.GetNSE();\n    int i, j, k, l, m;\n\n\n//       if (mtets.Size() + mprisms.Size() == mesh.GetNE())\n//       return;\n\n    \n\n    mtets.SetSize(0);\n    mprisms.SetSize(0);\n    mids.SetSize(0);\n    mtris.SetSize(0);\n    mquads.SetSize(0);\n\n\n    INDEX_2_HASHTABLE<int> shortedges(100);\n    for (i = 1; i <= ne; i++)\n      {\n\tconst Element & el = mesh.VolumeElement(i);\n\tif (el.GetType() == PRISM ||\n\t    el.GetType() == PRISM12)\n\t  {\n\t    for (j = 1; j <= 3; j++)\n\t      {\n\t\tINDEX_2 se(el.PNum(j), el.PNum(j+3));\n\t\tse.Sort();\n\t\tshortedges.Set (se, 1);\n\t      }\n\t  }\n      }\n\n\n\n    // INDEX_2_HASHTABLE<int> edgenumber(np);\n    INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);  \n\n    BTSortEdges (mesh, idmaps, edgenumber);\n\n\n    for (i = 1; i <= ne; i++)\n      {\n\tconst Element & el = mesh.VolumeElement(i);\n\t  \n\tswitch (el.GetType())\n\t  {\n\t  case TET:\n\t  case TET10:\n\t    {\n\t      // if tet has short edge, it is handled as degenerated prism\n\n\t      int foundse = 0;\n\t      for (j = 1; j <= 3; j++)\n\t\tfor (k = j+1; k <= 4; k++)\n\t\t  {\n\t\t    INDEX_2 se(el.PNum(j), el.PNum(k));\n\t\t    se.Sort();\n\t\t    if (shortedges.Used (se))\n\t\t      {\n//\t\t      cout << \"tet converted to prism\" << endl;\n\n\t\t\tfoundse = 1;\n\t\t\tint p3 = 1;\n\t\t\twhile (p3 == j || p3 == k)\n\t\t\t  p3++;\n\t\t\tint p4 = 10 - j - k - p3;\n\n\t\t\t// even permutation ?\n\t\t\tint pi[4];\n\t\t\tpi[0] = j;\n\t\t\tpi[1] = k;\n\t\t\tpi[2] = p3;\n\t\t\tpi[3] = p4;\n\t\t\tint cnt = 0;\n\t\t\tfor (l = 1; l <= 4; l++)\n\t\t\t  for (m = 0; m < 3; m++)\n\t\t\t    if (pi[m] > pi[m+1])\n\t\t\t      {\n\t\t\t\tSwap (pi[m], pi[m+1]);\n\t\t\t\tcnt++;\n\t\t\t      }\n\t\t\tif (cnt % 2)\n\t\t\t  Swap (p3, p4);\n\n\t\t\tElement hel = el;\n\t\t\thel.PNum(1) = el.PNum(j);\n\t\t\thel.PNum(2) = el.PNum(k);\n\t\t\thel.PNum(3) = el.PNum(p3);\n\t\t\thel.PNum(4) = el.PNum(p4);\n\n\t\t\tMarkedPrism mp;\n\n\t\t\tBTDefineMarkedPrism (hel, edgenumber, mp);\n\t\t\tmp.matindex = el.GetIndex();\n\t\t\tmprisms.Append (mp);\n\t\t      }\n\t\t  }\n\t      if (!foundse)\n\t\t{\n\t\t  MarkedTet mt;\n\t\t  \n\t\t  int oldind = -1;\n\t\t  for(l = 0; oldind < 0 && l<mtets_old[el[0]]->Size(); l++)\n\t\t    if(el[1] == (*mtets_old[el[0]])[l].pnums[1] &&\n\t\t       el[2] == (*mtets_old[el[0]])[l].pnums[2] &&\n\t\t       el[3] == (*mtets_old[el[0]])[l].pnums[3])\n\t\t      oldind = l;\n\n\t\t  if(oldind >= 0)\n\t\t    mtets.Append((*mtets_old[el[0]])[oldind]);\n\t\t  else\n\t\t    {\n\t\t      BTDefineMarkedTet (el, edgenumber, mt);\n\t\t      mt.matindex = el.GetIndex();\n\t\t      mtets.Append (mt);\n\t\t    }\n\t\t}\n\t      break;\n\t    }\n\t  case PYRAMID:\n\t    {\n\t      // eventually rotate\n\t      MarkedPrism mp;\n\t    \n\t      INDEX_2 se(el.PNum(1), el.PNum(2));\n\t      se.Sort();\n\t      if (shortedges.Used (se))\n\t\t{\n\t\t  Element hel = el;\n\t\t  hel.PNum(1) = el.PNum(2);\n\t\t  hel.PNum(2) = el.PNum(3);\n\t\t  hel.PNum(3) = el.PNum(4);\n\t\t  hel.PNum(4) = el.PNum(1);\n\t\t  BTDefineMarkedPrism (hel, edgenumber, mp);\n\t\t}\n\t      else\n\t\t{\n\t\t  BTDefineMarkedPrism (el, edgenumber, mp);\n\t\t}\n\n\t      mp.matindex = el.GetIndex();\n\t      mprisms.Append (mp);\n\t      break;\n\t    }\n\t  case PRISM:\n\t  case PRISM12:\n\t    {\n\t      MarkedPrism mp;\n\t      BTDefineMarkedPrism (el, edgenumber, mp);\n\t      mp.matindex = el.GetIndex();\n\t      mprisms.Append (mp);\n\t      break;\n\t    }\n\t  }\n      }\n\n    for (i = 1; i <= nse; i++)\n      {\n\tconst Element2d & el = mesh.SurfaceElement(i);\n\tif (el.GetType() == TRIG ||\n\t    el.GetType() == TRIG6)\n\t  {\n\t    MarkedTri mt;\n\t    BTDefineMarkedTri (el, edgenumber, mt);\n\t    mtris.Append (mt);\n\t  }\n\telse\n\t  {\n\t    MarkedQuad mq;\n\t    BTDefineMarkedQuad (el, edgenumber, mq);\n\t    mquads.Append (mq);\n\t  }\n\t\n\tMarkedIdentification mi;\n\n\t\n\n\tfor(j=0; j<idmaps.Size(); j++)\n\t  if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))\n\t    {\n\t      mids.Append(mi);\n\t\t\n\t      int oldind = -1;\n\t      for(l = 0; oldind < 0 && l<mids_old[mi.pnums[0]]->Size(); l++)\n\t\t{\n\t\t  bool equal = true;\n\t\t  for(int m = 1; equal && m < mi.np; m++)\n\t\t    equal = (mi.pnums[m] == (*mids_old[el[0]])[l].pnums[m]);\n\t\t  if(equal)\n\t\t    oldind = l;\n\t\t}\n\n\t      if(oldind >= 0)\n\t\tmids.Last() = (*mids_old[mi.pnums[0]])[oldind];\n\t    }\n\n      }\n\n\n\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      delete mtets_old[i];\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      delete mprisms_old[i];\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      delete mids_old[i];\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      delete mtris_old[i];\n    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)\n      delete mquads_old[i];\n  }\n*/\n\n  \n  void UpdateEdgeMarks (Mesh & mesh,\n\t\t\tconst NgArray< idmap_type* > & idmaps)\n  //const NgArray < NgArray<Element>* > & elements_before,\n  //const NgArray < NgArray<int>* > & markedelts_num,\n  //\t\tconst NgArray < NgArray<Element2d>* > & surfelements_before,\n  //\t\tconst NgArray < NgArray<int>* > & markedsurfelts_num)\n  {\n    /*\n    T_MTETS mtets_old; mtets_old.Copy(mtets);\n    T_MPRISMS mprisms_old; mprisms_old.Copy(mprisms);\n    T_MIDS mids_old; mids_old.Copy(mids);\n    T_MTRIS mtris_old; mtris_old.Copy(mtris);\n    T_MQUADS mquads_old; mquads_old.Copy(mquads);\n    */\n\n    auto& mtets = *mesh.bisectioninfo.mtets;\n    auto& mprisms = *mesh.bisectioninfo.mprisms;\n    auto& mids = *mesh.bisectioninfo.mids;\n    auto& mtris = *mesh.bisectioninfo.mtris;\n    auto& mquads = *mesh.bisectioninfo.mquads;\n\n    T_MTETS mtets_old (mtets);\n    T_MPRISMS mprisms_old (mprisms);\n    T_MIDS mids_old (mids);\n    T_MTRIS mtris_old (mtris);\n    T_MQUADS mquads_old (mquads);\n\n\n    \n    mtets.SetSize(0);\n    mprisms.SetSize(0);\n    mids.SetSize(0);\n    mtris.SetSize(0);\n    mquads.SetSize(0);\n\n    //int nv = mesh.GetNV();\n\n\n    // INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*mesh.GetNE()+4*mesh.GetNSE());\n    ClosedHashTable<PointIndices<2>, int> edgenumber;\n    \n    int maxnum = BTSortEdges (mesh, idmaps, edgenumber);\n\n    // for(int m = 0; m < mtets_old.Size(); m++)\n    for (auto mi : mtets_old.Range())\n      {\n\tMarkedTet & mt = mtets_old[mi];\n\n\t//(*testout) << \"old mt \" << mt;\n\t\n\tPointIndices<2> edge (mt.pnums[mt.tetedge1],mt.pnums[mt.tetedge2]);\n\tedge.Sort();\n\tif(edgenumber.Used(edge))\n\t  {\n\t    int val = edgenumber.Get(edge);\n\t    //(*testout) << \"set voledge \" << edge << \" from \" << val;\n\t    if(val <= maxnum)\n\t      {\n\t\tval += 2*maxnum;\n\t\tedgenumber.Set(edge,val);\n\t      }\n\t    else if(val <= 2*maxnum)\n\t      {\n\t\tval += maxnum;\n\t\tedgenumber.Set(edge,val);\n\t      }\n\t    //(*testout) << \" to \" << val << endl;\n\t  }\n\t\n\tfor(int k=0; k<4; k++)\n\t  for(int i=0; i<3; i++)\n\t    for(int j=i+1; i != k && j<4; j++)\n\t      if(j != k && int(mt.faceedges[k]) == 6-k-i-j)\n\t\t{\n\t\t  edge[0] = mt.pnums[i];\n\t\t  edge[1] = mt.pnums[j];\n\t\t  edge.Sort();\n\t\t  if(edgenumber.Used(edge))\n\t\t    {\n\t\t      int val = edgenumber.Get(edge);\n\t\t      //(*testout) << \"set faceedge \" << edge << \" from \" << val;\n\t\t      if(val <= maxnum)\n\t\t\t{\n\t\t\t  val += maxnum;\n\t\t\t  edgenumber.Set(edge,val);\n\t\t\t}\n\t\t      //(*testout) << \" to \" << val << endl;\n\t\t    }\t\t      \n\t\t}\n      }\n\n\t\n    \n    /*\n    for (auto ei : mesh.VolumeElements().Range())\n      {\n\tconst Element & el = mesh[ei];\n    */\n\n    for (const Element & el : mesh.VolumeElements())\n      {\n\t//int pos = elements_before[el[0]]->Pos(el);\n\t//int elnum = (pos >= 0) ? (*markedelts_num[el[0]])[pos] : -1;\n\t \n\tswitch (el.GetType())\n\t  {\n\t  case TET:\n\t  case TET10:\n\t    {\n\t      //if(elnum >= 0)\n\t      // {\n\t      //   mtets.Append(mtets_old[elnum]);\n\t      // } \n\t      //else\n\t      // {\n\t      MarkedTet mt;\n\t      BTDefineMarkedTet (el, edgenumber, mt);\n\t      mt.matindex = el.GetIndex();\n\t      \n\t      mtets.Append (mt);\n\t    \n\t      //(*testout) << \"mtet \" << mtets.Last() << endl;\n\t      break;\n\t    }\n\t  case PYRAMID:\n\t    {\n\t      cerr << \"Refinement :: UpdateEdgeMarks not yet implemented for pyramids\"\n\t\t   << endl;\n\t      break;\n\t    }\n\t    \n\t  case PRISM:\n\t  case PRISM12:\n\t    {\n\t      cerr << \"Refinement :: UpdateEdgeMarks not yet implemented for prisms\"\n\t\t   << endl;\n\t      break;\n\t    }\n          default:\n            throw NgException(\"Bisect, element type not handled in switch, 6\");\n\t  }\n\t\n      }\n    \n    /*\n    for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n       {\n\t const Element2d & el = mesh[sei];\n    */\n\n    for (const Element2d & el : mesh.SurfaceElements())\n      {\n\t /*\n\t for(int k=0; k<3; k++)\n\t   auxind3[k] = el[k];\n\n\t auxind3.Sort();\n\t \n\t int pos = oldfaces[auxind3[0]]->Pos(auxind3);\n\t if(pos < 0)\n\t   cout << \"UIUIUI\" << endl;\n\t */\t \n\t \n\t switch (el.GetType())\n\t   {\n\t   case TRIG:\n\t   case TRIG6:\n\t     {\n\t       MarkedTri mt;\n\t       BTDefineMarkedTri (el, edgenumber, mt);\n\t       mtris.Append (mt);\n\t       break;\n\t     }\n\t     \n\t   case QUAD:\n\t   case QUAD6:\n\t     {\n\t       MarkedQuad mt;\n\t       BTDefineMarkedQuad (el, edgenumber, mt);\n\t       mquads.Append (mt);\n\t       break;\n\t     }\n           default:\n             throw NgException(\"Bisect, element type not handled in switch, 5\");\n\t   }\n\n\t \n\tMarkedIdentification mi;\n\tfor(int j=0; j<idmaps.Size(); j++)\n\t  if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))\n\t    mids.Append(mi);\n\n\n\t /*\n\t int pos = surfelements_before[el[0]]->Pos(el);\n\t int elnum = (pos >= 0) ? (*markedsurfelts_num[el[0]])[pos] : -1;\n\t \n\t \n\t switch (el.GetType())\n\t   {\n\t   case TRIG:\n\t   case TRIG6:\n\t     {\n\t       if(elnum >= 0)\n\t\t mtris.Append(mtris_old[elnum]);\n\t       else\n\t\t {\n\t\t   MarkedTri mt;\n\t\t   BTDefineMarkedTri (el, edgenumber, mt);\n\t\t   mtris.Append (mt);\n\t\t   (*testout) << \"(new) \";\n\t\t }\n\t       (*testout) << \"mtri \" << mtris.Last();\n\t       break;\n\t     }\n\t     \n\t   case QUAD:\n\t   case QUAD6:\n\t     {\n\t       if(elnum >= 0)\n\t\t mquads.Append(mquads_old[elnum]);\n\t       else\n\t\t {\n\t\t   MarkedQuad mt;\n\t\t   BTDefineMarkedQuad (el, edgenumber, mt);\n\t\t   mquads.Append (mt);\n\t\t }\n\t       break;\n\t     }\n\t   }\n\t */\n       }\n     \n     /*\n     for(int i=0; i<oldfaces.Size(); i++)\n       {\n\t delete oldfaces[i];\n\t delete oldmarkededges[i];\n       }\n     */\n     \n  }\n\t\t\t\t      \n\n\n\n  void Refinement :: Bisect (Mesh & mesh, \n\t\t\t     BisectionOptions & opt,\n\t\t\t     NgArray<double> * quality_loss) const\n  {\n    PrintMessage(1,\"Mesh bisection\");\n    PushStatus(\"Mesh bisection\");\n\n    auto& mtets = *mesh.bisectioninfo.mtets;\n    auto& mprisms = *mesh.bisectioninfo.mprisms;\n    auto& mids = *mesh.bisectioninfo.mids;\n    auto& mtris = *mesh.bisectioninfo.mtris;\n    auto& mquads = *mesh.bisectioninfo.mquads;\n\n    static int timer = NgProfiler::CreateTimer (\"Bisect\");\n    static int timer1 = NgProfiler::CreateTimer (\"Bisect 1\");\n    static int timer1a = NgProfiler::CreateTimer (\"Bisect 1a\");\n    static int timer1b = NgProfiler::CreateTimer (\"Bisect 1b\");\n    static int timer2 = NgProfiler::CreateTimer (\"Bisect 2\");\n    static int timer2a = NgProfiler::CreateTimer (\"Bisect 2a\");\n    static int timer2b = NgProfiler::CreateTimer (\"Bisect 2b\");\n    // static int timer2c = NgProfiler::CreateTimer (\"Bisect 2c\");\n    static int timer3 = NgProfiler::CreateTimer (\"Bisect 3\");\n    static int timer3a = NgProfiler::CreateTimer (\"Bisect 3a\");\n    static int timer3b = NgProfiler::CreateTimer (\"Bisect 3b\");\n    static int timer_bisecttet = NgProfiler::CreateTimer (\"Bisect tets\");\n    static int timer_bisecttrig = NgProfiler::CreateTimer (\"Bisect trigs\");\n    static int timer_bisectsegms = NgProfiler::CreateTimer (\"Bisect segms\");\n\n    \n    NgProfiler::RegionTimer reg1 (timer);\n\n    (*opt.tracer)(\"Bisect\", false);\n    \n    NgProfiler::StartTimer (timer1);\n    NgProfiler::StartTimer (timer1a);\n    static int localizetimer = NgProfiler::CreateTimer(\"localize edgepoints\");\n    NgProfiler::RegionTimer * loct = new NgProfiler::RegionTimer(localizetimer);   \n    LocalizeEdgePoints(mesh);\n    delete loct;\n\n    NgArray< idmap_type* > idmaps;\n    for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tif(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)\n\t  {\n\t    idmaps.Append(new idmap_type);\n\t    mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true);\n\t  }\n      }\n\n    \n    string refelementinfofileread = \"\";\n    string refelementinfofilewrite = \"\";\n\n    if(opt.refinementfilename)\n      {\n\tifstream inf(opt.refinementfilename);\n\tstring st;\n\tinf >> st;\n\tif(st == \"refinementinfo\")\n\t  {\n\t    while(inf)\n\t      {\n\t\twhile(inf && st != \"markedelementsfile\")\n\t\t  inf >> st;\n\t\t\n\t\tif(inf)\n\t\t  inf >> st;\n\t\t\n\t\tif(st == \"read\" && inf)\n\t\t  ReadEnclString(inf,refelementinfofileread,'\\\"');\n\t\telse if(st == \"write\" && inf)\n\t\t  ReadEnclString(inf,refelementinfofilewrite,'\\\"');\n\t      }\n\t  }\n\tinf.close();\n      }\n\t\n    mesh.ComputeNVertices();\n\n    // if (mesh.mglevels == 1 || idmaps.Size() > 0)\n    if (mesh.level_nv.Size() == 0)  // || idmaps.Size()  ????\n      {\n        BisectTetsCopyMesh(mesh, NULL, opt, idmaps, refelementinfofileread);\n        mesh.level_nv.Append (mesh.GetNV());\n      }\n\n    int np = mesh.GetNV();\n    mesh.SetNP(np);\n\n\n#ifdef PARALLEL\n    if (mesh.GetCommunicator().Size() > 1)\n      {\n        mesh.GetParallelTopology().IdentifyVerticesAfterRefinement();\n        mesh.GetCommunicator().Barrier();\n        mesh.GetParallelTopology().EnumeratePointsGlobally();\n      }\n#endif\n\n\n\n\n    \n    // int ne = mesh.GetNE();\n    // int nse = mesh.GetNSE();\n    // int i, j, l;\n\n    // int initnp = np;\n    //  int maxsteps = 3;\n\n    // mesh.mglevels++;\n\n    /*\n      if (opt.refinementfilename || opt.usemarkedelements)\n      maxsteps = 3;\n    */\n\n\n    if (opt.refine_p)   \n      {\n\t// int ne = mesh.GetNE();\n\tint nse = mesh.GetNSE();\n\tint ox,oy,oz; \n\t// for (ElementIndex ei = 0; ei < ne; ei++)\n        for (auto ei : mesh.VolumeElements().Range())\n\t  if (mesh[ei].TestRefinementFlag())\n\t    {\n\t      mesh[ei].GetOrder(ox,oy,oz);\n\t      mesh[ei].SetOrder (ox+1,oy+1,oz+1);\n\t      if (mesh[ei].TestStrongRefinementFlag())\n\t\tmesh[ei].SetOrder (ox+2,oy+2,oz+2);\n\t    }\n\tfor (SurfaceElementIndex sei = 0; sei < nse; sei++)\n\t  if (mesh[sei].TestRefinementFlag())\n\t    {\n\t      mesh[sei].GetOrder(ox,oy);\n\t      mesh[sei].SetOrder(ox+1,oy+1);\n\t      if (mesh[sei].TestStrongRefinementFlag())\n\t\tmesh[sei].SetOrder(ox+2,oy+2);\n\t    }\n\n#ifndef SABINE //Nachbarelemente mit ordx,ordy,ordz \n        \n        // NgArray<int,PointIndex::BASE> v_order (mesh.GetNP());\n          Array<int,PointIndex> v_order (mesh.GetNP());\n\t  v_order = 0;\n\n\t  // for (ElementIndex ei = 0; ei < ne; ei++)\n          for (auto ei : mesh.VolumeElements().Range())\n            for (int j = 0; j < mesh[ei].GetNP(); j++)\n              if (mesh[ei].GetOrder() > v_order[mesh[ei][j]])\n                v_order[mesh[ei][j]] = mesh[ei].GetOrder();\n\n\t  for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n            for (int j = 0; j < mesh[sei].GetNP(); j++)\n              if (mesh[sei].GetOrder() > v_order[mesh[sei][j]])\n                v_order[mesh[sei][j]] = mesh[sei].GetOrder();\n\n\t  // for (ElementIndex ei = 0; ei < ne; ei++)\n          for (auto ei : mesh.VolumeElements().Range())          \n            for (int j = 0; j < mesh[ei].GetNP(); j++)\n              if (mesh[ei].GetOrder() < v_order[mesh[ei][j]]-1)\n                mesh[ei].SetOrder(v_order[mesh[ei][j]]-1);\n\n\t  for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n            for (int j = 0; j < mesh[sei].GetNP(); j++)\n              if (mesh[sei].GetOrder() < v_order[mesh[sei][j]]-1)\n                mesh[sei].SetOrder(v_order[mesh[sei][j]]-1);\n          \n#endif\n          \n          PopStatus();\n          return;\n      }\n\n\n\n    // INDEX_2_HASHTABLE<int> cutedges(10 + 5 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));\n    // INDEX_2_CLOSED_HASHTABLE<PointIndex> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));\n    // ClosedHashTable<INDEX_2, PointIndex> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));\n    ClosedHashTable<SortedPointIndices<2>, PointIndex> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));\n\n    bool noprojection = false;\n    NgProfiler::StopTimer (timer1a);\n    \n    for (int l = 1; l <= 1; l++)\n      {\n\tint marked = 0;\n\tif (opt.refinementfilename)\n\t  {\n\t    ifstream inf(opt.refinementfilename);\n\t    PrintMessage(3,\"load refinementinfo from file \",opt.refinementfilename);\n\n\t    string st;\n\t    inf >> st;\n\t    if(st == \"refinementinfo\")\n\t      // new version\n\t      {\n                /*\n\t\tfor(int i=1; i<=mtets.Size(); i++)\n\t\t  mtets[i-1].marked = 0;\n                */\n\t\tfor(auto ei : mtets.Range())\n\t\t  mtets[ei].marked = 0;\n\t\tfor(int i=1; i<=mprisms.Size(); i++)\n\t\t  mprisms.Elem(i).marked = 0;\n\t\tfor(int i=1; i<=mtris.Size(); i++)\n\t\t  mtris.Elem(i).marked = 0;\n\t\tfor(int i=1; i<=mquads.Size(); i++)\n\t\t  mquads.Elem(i).marked = 0;\n\t\tfor(int i=1; i<=mprisms.Size(); i++)\n\t\t  mids.Elem(i).marked = 0;\n\n\t\tinf >> st;\n\t\twhile(inf)\n\t\t  {\n\t\t    if(st[0] == '#')\n\t\t      {\n\t\t\tinf.ignore(10000,'\\n');\n\t\t\tinf >> st;\n\t\t      }\n\t\t    else if(st == \"markedelementsfile\")\n\t\t      {\n\t\t\tinf >> st;\n\t\t\tReadEnclString(inf,st,'\\\"');\n\t\t\tinf >> st;\n\t\t      }\n\t\t    else if(st == \"noprojection\")\n\t\t      {\n\t\t\tnoprojection = true;\n\t\t\tinf >> st;\n\t\t      }\n\t\t    else if(st == \"refine\")\n\t\t      {\n\t\t\tinf >> st;\n\t\t\tif(st == \"elements\")\n\t\t\t  {\n\t\t\t    inf >> st;\n\t\t\t    bool isint = true;\n\t\t\t\tfor(string::size_type ii=0; isint && ii<st.size(); ii++)\n\t\t\t      isint = (isdigit(st[ii]) != 0);\n\t\t\t    \n\t\t\t    while(inf && isint)\n\t\t\t      {\n\t\t\t\t// mtets[atoi(st.c_str())-1].marked = 3;\n                                mtets[IndexBASE<ElementIndex>()+(atoi(st.c_str())-1)].marked = 3;\n\t\t\t\tmarked = 1;\n\n\t\t\t\tinf >> st;\n\t\t\t\tisint = true;\n\t\t\t\tfor(string::size_type ii=0; isint && ii<st.size(); ii++)\n\t\t\t\t  isint = (isdigit(st[ii]) != 0);\n\t\t\t      }\n\t\t\t  }\n\t\t\telse if(st == \"orthobrick\")\n\t\t\t  {\n\t\t\t    double bounds[6];\n\t\t\t    for(int i=0; i<6; i++)\n\t\t\t      inf >> bounds[i];\n\t\t\t    \n\t\t\t    int cnt = 0;\n\n\t\t\t    // for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n                            for (auto ei : mesh.VolumeElements().Range())\n\t\t\t      {\n\t\t\t\tconst Element & el = mesh[ei];\n\t\t\t\t\n\t\t\t\t//\n\t\t\t\tPoint<3> center(0,0,0);\n\t\t\t\tfor(int i=0; i<el.GetNP(); i++)\n\t\t\t\t  {\n\t\t\t\t    const MeshPoint & point = mesh[el[i]];\n\t\t\t\t    center(0) += point(0);\n\t\t\t\t    center(1) += point(1);\n\t\t\t\t    center(2) += point(2);\n\t\t\t\t  }\n\t\t\t\tfor(int i=0; i<3; i++)\n\t\t\t\t  center(i) *= 1./double(el.GetNP());\n\t\t\t\tif(bounds[0] <= center(0) && center(0) <= bounds[3] &&\n\t\t\t\t   bounds[1] <= center(1) && center(1) <= bounds[4] &&\n\t\t\t\t   bounds[2] <= center(2) && center(2) <= bounds[5])\n\t\t\t\t  {\n\t\t\t\t    mtets[ei].marked = 3;\n\t\t\t\t    cnt++;\n\t\t\t\t  }\n\t\t\t\t\n\t\t\t\t  \n// \t\t\t\tbool contained = false;\n// \t\t\t\tfor(int i=0; !contained && i<el.GetNP(); i++)\n// \t\t\t\t  {\n// \t\t\t\t    const MeshPoint & point = mesh[el[i]];\n// \t\t\t\t    contained = (bounds[0] <= point.X() && point.X() <= bounds[3] &&\n// \t\t\t\t\t\t bounds[1] <= point.Y() && point.Y() <= bounds[4] &&\n// \t\t\t\t\t\t bounds[2] <= point.Z() && point.Z() <= bounds[5]);\n// \t\t\t\t  }\n// \t\t\t\tif(contained)\n// \t\t\t\t  {\n// \t\t\t\t    mtets[ei].marked = 3;\n// \t\t\t\t    cnt++;\n// \t\t\t\t  }\n\t\t\t      }\n\n\n\t\t\t    ostringstream strstr;\n\t\t\t    strstr.precision(2);\n\t\t\t    strstr << \"marked \" << float(cnt)/float(mesh.GetNE())*100. \n#ifdef WIN32\n\t\t\t\t   << \"%%\"\n#else\n\t\t\t\t   << \"%\"\n#endif\n\t\t\t\t   <<\" of the elements\";\n\t\t\t    PrintMessage(4,strstr.str());\n\n\t\t\t    if(cnt > 0)\n\t\t\t      marked = 1;\n\n\n\t\t\t    inf >> st;\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    throw NgException(\"something wrong with refinementinfo file\");\n\t\t\t  }\n\t\t      }\n\t\t  }\t\t\n\t      }\n\t    else\n\t      {\n\t\tinf.close();\n\t\tinf.open(opt.refinementfilename);\n\n\t\tchar ch;\n\t\t// for (int i = 1; i <= mtets.Size(); i++)\n                for (auto ei : mtets.Range())\n\t\t  {\n\t\t    inf >> ch;\n\t\t    if(!inf)\n\t\t      throw NgException(\"something wrong with refinementinfo file (old format)\");\n\t\t    mtets[ei].marked = (ch == '1');\n\t\t  }\n\t\tmarked = 1;\n\t      }\n\t    inf.close();\n\t  }\n\n\telse if (opt.usemarkedelements)\n\t  {\n\t    int cntm = 0;\n\n\t    // all in one !\n\t    if (mprisms.Size())\n\t      {\n\t\tElementIndex cnttet = IndexBASE<ElementIndex>();\n\t\tint cntprism = 0;\n\t\t// for (int i = 1; i <= mesh.GetNE(); i++)\n                for (auto ei : mesh.VolumeElements().Range())\n\t\t  {\n\t\t    if (mesh.VolumeElement(ei).GetType() == TET ||\n\t\t\tmesh.VolumeElement(ei).GetType() == TET10)\n\t\t      {\n\t\t\tmtets[cnttet].marked =\n\t\t\t  (opt.onlyonce ? 3 : 1) * mesh.VolumeElement(ei).TestRefinementFlag();\n\t\t\tif (mtets[cnttet].marked)\n\t\t\t  cntm++;\n\t\t\tcnttet++;\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\tcntprism++;\n\t\t\tmprisms.Elem(cntprism).marked =\n\t\t\t  2 * mesh.VolumeElement(ei).TestRefinementFlag();\n\t\t\tif (mprisms.Elem(cntprism).marked)\n\t\t\t  cntm++;\n\t\t      }\n\n\t\t  }\n\t      }\n\t    else\n\t      // for (int i = 1; i <= mtets.Size(); i++)\n              for (auto ei : mtets.Range())\n\t\t{\n\t\t  mtets[ei].marked =\n\t\t    (opt.onlyonce ? 1 : 3) * mesh.VolumeElement(ei).TestRefinementFlag();\n\t\t  if (mtets[ei].marked)\n\t\t    cntm++;\n\t\t}\n\n\t    // (*testout) << \"mtets = \" << mtets << endl;\n\n\t    /*\n\t      for (i = 1; i <= mtris.Size(); i++)\n\t      mtris.Elem(i).marked = 0;\n\t      for (i = 1; i <= mquads.Size(); i++)\n\t      mquads.Elem(i).marked = 0;\n\t    */\n\n\t    if (printmessage_importance>0)\n\t      {\n\t\tostringstream str;\n\t\tstr << \"marked elements: \" << cntm;\n\t\tPrintMessage(4,str.str());\n\t      }\n\n\t    int cnttrig = 0;\n\t    int cntquad = 0;\n\t    // for (int i = 1; i <= mesh.GetNSE(); i++)\n            for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t      {\n\t\tif (mesh[sei].GetType() == TRIG ||\n\t\t    mesh[sei].GetType() == TRIG6)\n\t\t  {\n\t\t    cnttrig++;\n\t\t    mtris.Elem(cnttrig).marked =\n\t\t      mesh[sei].TestRefinementFlag() ? (opt.onlyonce ? 1 : 2) : 0;\n\t\t    // mtris.Elem(cnttrig).marked = 0;\n\t\t    if (mtris.Elem(cnttrig).marked)\n\t\t      cntm++;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    cntquad++;\n                    // 2d: marked=2, 3d prisms: marked=1\n\t\t    mquads.Elem(cntquad).marked =\n                        mesh[sei].TestRefinementFlag() ? 4-mesh.GetDimension() : 0 ;\n\t\t    // mquads.Elem(cntquad).marked = 0;\n\t\t    if (mquads.Elem(cntquad).marked)\n\t\t      cntm++;\n\t\t  }\n\t      }\n\n              if (printmessage_importance>0)\n\t\t{\n\t\t  ostringstream str;\n\t\t  str << \"with surface-elements: \" << cntm;\n\t\t  PrintMessage(4,str.str());\n\t\t}\n\n            // he/sz: das wird oben schon richtig gemacht.\n            // hier sind die quads vergessen!\n            /*\n\t    if (mesh.GetDimension() == 2)\n\t      {\n\t\tcntm = 0;\n\t\tfor (i = 1; i <= mtris.Size(); i++)\n\t\t  {\n\t\t    mtris.Elem(i).marked =\n\t\t      2 * mesh.SurfaceElement(i).TestRefinementFlag();\n\t\t    //\t\t  mtris.Elem(i).marked = 2;\n\t\t    if (mtris.Elem(i).marked)\n\t\t      cntm++;\n\t\t  }\n\n\t\tif (!cntm)\n\t\t  {\n\t\t    for (i = 1; i <= mtris.Size(); i++)\n\t\t      {\n\t\t\tmtris.Elem(i).marked = 2;\n\t\t\tcntm++;\n\t\t      }\n\t\t  }\n\t\tcout << \"trigs: \" << mtris.Size() << \" \";\n\t\tcout << \"marked: \" << cntm << endl;\n\t      }\n            */ \n            \n\t    marked = (cntm > 0);\n\t  }\n\telse\n\t  {\n\t    marked = BTMarkTets (mtets, mprisms, mesh);\n\t  }\n\n\tif (!marked) break;\n        \n\n\t//(*testout) << \"mtets \" << mtets << endl;\n\n\tif (opt.refine_p)\n\t  {\n\t    PrintMessage(3,\"refine p\");\n\n\t    for (auto ei : mtets.Range())\n\t      mtets[ei].incorder = mtets[ei].marked ? 1 : 0;\n\n\t    for (auto ei : mtets.Range())              \n\t      if (mtets[ei].incorder)\n\t\tmtets[ei].marked = 0;\n\n\n\t    for (int i = 1; i <= mprisms.Size(); i++)\n\t      mprisms.Elem(i).incorder = mprisms.Elem(i).marked ? 1 : 0;\n\n\t    for (int i = 1; i <= mprisms.Size(); i++)\n\t      if (mprisms.Elem(i).incorder)\n\t\tmprisms.Elem(i).marked = 0;\n\n\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      mtris.Elem(i).incorder = mtris.Elem(i).marked ? 1 : 0;\n\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      {\n\t\tif (mtris.Elem(i).incorder)\n\t\t  mtris.Elem(i).marked = 0;\n\t      }\n\t  }\n\n\tif (opt.refine_hp)\n\t  {\n\t    PrintMessage(3,\"refine hp\");\n\t    TBitArray<PointIndex> singv(np);\n\t    singv.Clear();\n\n\t    if (mesh.GetDimension() == 3)\n\t      {\n\t\tfor (int i = 1; i <= mesh.GetNSeg(); i++)\n\t\t  {\n\t\t    const Segment & seg = mesh.LineSegment(i);\n\t\t    singv.SetBit (seg[0]);\n\t\t    singv.SetBit (seg[1]);\n\t\t  }\n\t\t/*\n\t\t  for ( i=1; i<= mesh.GetNSE(); i++)\n\t\t  {\n\t\t  const Element2d & sel = mesh.SurfaceElement(i);\n\t\t  for(int j=1; j<=sel.GetNP(); j++)\n\t\t  singv.Set(sel.PNum(j));\n\t\t  }\n\t\t*/\n\t      }\n\t    else\n\t      {\n\t\t// vertices with 2 different bnds\n\t\tArray<int,PointIndex> bndind(np);\n\t\tbndind = 0;\n\t\tfor (int i = 1; i <= mesh.GetNSeg(); i++)\n\t\t  {\n\t\t    const Segment & seg = mesh.LineSegment(i);\n\t\t    for (int j = 0; j < 2; j++)\n\t\t      {\n\t\t\tPointIndex pi = (j == 0) ? seg[0] : seg[1];\n\t\t\tif (bndind[pi] == 0)\n\t\t\t  bndind[pi] = seg.edgenr;\n\t\t\telse if (bndind[pi] != seg.edgenr)\n\t\t\t  singv.SetBit (pi);\n\t\t      }\n\t\t  }\n\t      }\n\n\n\n\t    // for (int i = 1; i <= mtets.Size(); i++)\n            for (auto ei : mtets.Range())\n\t      mtets[ei].incorder = 1;\n\t    // for (int i = 1; i <= mtets.Size(); i++)\n            for (auto ei : mtets.Range())              \n\t      {\n\t\tif (!mtets[ei].marked)\n\t\t  mtets[ei].incorder = 0;\n\t\tfor (int j = 0; j < 4; j++)\n\t\t  if (singv.Test (mtets[ei].pnums[j]))\n\t\t    mtets[ei].incorder = 0;\n\t      }\n\t    // for (int i = 1; i <= mtets.Size(); i++)\n            for (auto ei : mtets.Range())\n\t      if (mtets[ei].incorder)\n\t\tmtets[ei].marked = 0;\n\n\n\t    for (int i = 1; i <= mprisms.Size(); i++)\n\t      mprisms.Elem(i).incorder = 1;\n\t    for (int i = 1; i <= mprisms.Size(); i++)\n\t      {\n\t\tif (!mprisms.Elem(i).marked)\n\t\t  mprisms.Elem(i).incorder = 0;\n\t\tfor (int j = 0; j < 6; j++)\n\t\t  if (singv.Test (mprisms.Elem(i).pnums[j]))\n\t\t    mprisms.Elem(i).incorder = 0;\n\t      }\n\t    for (int i = 1; i <= mprisms.Size(); i++)\n\t      if (mprisms.Elem(i).incorder)\n\t\tmprisms.Elem(i).marked = 0;\n\n\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      mtris.Elem(i).incorder = 1;\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      {\n\t\tif (!mtris.Elem(i).marked)\n\t\t  mtris.Elem(i).incorder = 0;\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  if (singv.Test (mtris.Elem(i).pnums[j]))\n\t\t    mtris.Elem(i).incorder = 0;\n\t      }\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      {\n\t\tif (mtris.Elem(i).incorder)\n\t\t  mtris.Elem(i).marked = 0;\n\t      }\n\t  }\n\n\n\n\tint hangingvol, hangingsurf, hangingedge;\n\n\t//cout << \"write?\" << endl;\n\t//string yn;\n\t//cin >> yn;\n        \n    \n        (*testout) << \"refine volume elements\" << endl;\n\tdo\n\t  {\n\t    // refine volume elements\n            NgProfiler::StartTimer (timer_bisecttet);\n            (*opt.tracer)(\"bisecttet\", false);\n\t    size_t nel = mtets.Size();\n\t    // for (size_t i = 0; i < nel; i++)\n            for (auto ei : ngcore::T_Range<ElementIndex>(nel))\n\t      if (mtets[ei].marked)\n\t\t{\n\t\t  MarkedTet oldtet = mtets[ei];\n                  \n\t\t  SortedPointIndices<2> edge(oldtet.pnums[oldtet.tetedge1],\n                                             oldtet.pnums[oldtet.tetedge2]);\n\n\t\t  PointIndex newp;\n                  if (auto optnewp = cutedges.GetIfUsed(edge))\n                    {\n                      newp = *optnewp;\n                    }\n\t\t  else\n\t\t    {\n\t\t      Point<3> npt = Center (mesh[edge[0]], mesh[edge[1]]);\n                      newp = mesh.AddPoint (npt);\n\t\t      cutedges.Set (edge, newp);\n\t\t    }\n\n\t\t  MarkedTet newtet1, newtet2;\n\t\t  BTBisectTet (oldtet, newp, newtet1, newtet2);\n\n\t\t  mtets[ei] = newtet1;\n\t\t  mtets.Append (newtet2);\n\t\t  mesh.mlparentelement.Append (ei);\n\t\t}\n            NgProfiler::StopTimer (timer_bisecttet);\n            (*opt.tracer)(\"bisecttet\", true);            \n\t    int npr = mprisms.Size();\n\t    for (int i = 1; i <= npr; i++)\n\t      if (mprisms.Elem(i).marked)\n\t\t{\n\t\t  MarkedPrism oldprism;\n\t\t  MarkedPrism newprism1, newprism2;\n\t\t  PointIndex newp1, newp2;\n\n\t\t  oldprism = mprisms.Get(i);\n\t\t  int pi1 = 0;\n\t\t  if (pi1 == oldprism.markededge)\n\t\t    pi1++;\n\t\t  int pi2 = 3-pi1-oldprism.markededge;\n                  \n\t\t  SortedPointIndices<2> edge1(oldprism.pnums[pi1],\n                                              oldprism.pnums[pi2]);\n\t\t  SortedPointIndices<2> edge2(oldprism.pnums[pi1+3],\n                                              oldprism.pnums[pi2+3]);\n\n\t\t  if (cutedges.Used (edge1))\n\t\t    newp1 = cutedges.Get(edge1);\n\t\t  else\n\t\t    {\n\t\t      Point<3> npt = Center (mesh[edge1[0]], mesh[edge1[1]]);\n                      newp1 = mesh.AddPoint (npt);\n\t\t      cutedges.Set (edge1, newp1);\n\t\t    }\n\t\t  if (cutedges.Used (edge2))\n\t\t    newp2 = cutedges.Get(edge2);\n\t\t  else\n\t\t    {\n\t\t      Point<3> npt = Center (mesh[edge2[0]], mesh[edge2[1]]);\n                      newp2 = mesh.AddPoint (npt);\n\t\t      cutedges.Set (edge2, newp2);\n\t\t    }\n\t\t\n\n\t\t  BTBisectPrism (oldprism, newp1, newp2, newprism1, newprism2);\n\t\t  //if(yn == \"y\")\n\t\t  //  (*testout) << \"bisected prism \" << oldprism << \"and got \" << newprism1 << \"and \" << newprism2 << endl;\n\t\t  mprisms.Elem(i) = newprism1;\n\t\t  mprisms.Append (newprism2);\n\t\t}\n\n\t    int nid = mids.Size();\n\t    for (int i = 1; i <= nid; i++)\n\t      if (mids.Elem(i).marked)\n\t\t{\n\t\t  MarkedIdentification oldid,newid1,newid2;\n\t\t  Array<PointIndex> newp;\n\n\t\t  oldid = mids.Get(i);\n\t\t  \n\t\t  NgArray<PointIndices<2>> edges;\n\t\t  edges.Append( {\n                      oldid.pnums[oldid.markededge],\n                      oldid.pnums[(oldid.markededge+1)%oldid.np] } );\n\t\t  edges.Append( {\n                      oldid.pnums[oldid.markededge + oldid.np],\n                      oldid.pnums[(oldid.markededge+1)%oldid.np + oldid.np] } );\n                  \n\t\t  if(oldid.np == 4)\n\t\t    {\n\t\t      edges.Append( {\n                          oldid.pnums[(oldid.markededge+2)%oldid.np],\n                          oldid.pnums[(oldid.markededge+3)%oldid.np]} );\n\t\t      edges.Append( {\n                          oldid.pnums[(oldid.markededge+2)%oldid.np + oldid.np],\n                          oldid.pnums[(oldid.markededge+3)%oldid.np + oldid.np] } );\n\t\t    }\n\t\t  for (int j = 0; j < edges.Size(); j++)\n\t\t    {\n\t\t      edges[j].Sort();\n\n\t\t      if(cutedges.Used(edges[j]))\n\t\t\tnewp.Append(cutedges.Get(edges[j]));\n\t\t      else\n\t\t\t{\n\t\t\t  Point<3> npt = Center (mesh.Point (edges[j].I1()),\n\t\t\t\t\t\tmesh.Point (edges[j].I2()));\n\t\t\t  newp.Append(mesh.AddPoint(npt));\n\t\t\t  cutedges.Set(edges[j],newp[j]);\n\t\t\t}\t\t\t \n\t\t    }\n\t\t  \n\t\t  BTBisectIdentification(oldid,newp,newid1,newid2);\n\t\t  mids.Elem(i) = newid1;\n\t\t  mids.Append(newid2);\t\t  \n\t\t}\n\n\t    \n\t    //IdentifyCutEdges(mesh, cutedges);\n            \n            (*opt.tracer)(\"mark elements\", false);\n\n\t    hangingvol = \n\t      MarkHangingTets (mtets, cutedges, opt.task_manager) +\n\t      MarkHangingPrisms (mprisms, cutedges) +\n\t      MarkHangingIdentifications (mids, cutedges);\n\n            (*opt.tracer)(\"mark elements\", true);\n\n\t    size_t nsel = mtris.Size();\n            NgProfiler::StartTimer (timer_bisecttrig);\n            (*opt.tracer)(\"Bisect trigs\", false);            \n\t    for (size_t i = 0; i < nsel; i++)\n\t      if (mtris[i].marked)\n\t\t{\n\t\t  MarkedTri newtri1, newtri2;\n\t\t  PointIndex newp;\n\t\t\n\t\t  MarkedTri oldtri = mtris[i];\n\t\t  PointIndex oldpi1 = oldtri.pnums[(oldtri.markededge+1)%3];\n\t\t  PointIndex oldpi2 = oldtri.pnums[(oldtri.markededge+2)%3];\n\t\t  PointIndices<2> edge(oldpi1, oldpi2);\n\t\t  edge.Sort();\n\n                  int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr();\n                  PointGeomInfo npgi;\n                  PointGeomInfo gi1 = oldtri.pgeominfo[(oldtri.markededge+1)%3];\n                  PointGeomInfo gi2 = oldtri.pgeominfo[(oldtri.markededge+2)%3];\n\n\t\t  if (cutedges.Used (edge))\n\t\t    {\n\t\t      newp = cutedges.Get(edge);\n                      npgi.u = 0.5*(gi1.u + gi2.u);\n                      npgi.v = 0.5*(gi1.v + gi2.v);\n                      geo.ProjectPointGI (si, mesh[newp], npgi);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      Point<3> npt = Center (mesh.Point (edge[0]),\n                                             mesh.Point (edge[1]));\n\t\t      newp = mesh.AddPoint (npt);\n                      cutedges.Set (edge, newp);\n                      geo.PointBetween (mesh.Point (oldpi1), mesh.Point (oldpi2),\n                                      0.5, si, gi1, gi2, mesh.Point (newp), npgi);\n\t\t    }\n\t\t\n\t\t  BTBisectTri (oldtri, newp, npgi, newtri1, newtri2);\n\t\t\n\t\t  mtris[i] = newtri1;\n\t\t  mtris.Append (newtri2);\n\t\t  mesh.mlparentsurfaceelement.Append (i);\n\t\t}\n\n            NgProfiler::StopTimer (timer_bisecttrig);\n            (*opt.tracer)(\"Bisect trigs\", true);                        \n            \n\t    int nquad = mquads.Size();\n\t    for (int i = 1; i <= nquad; i++)\n\t      if (mquads.Elem(i).marked)\n\t\t{\n\t\t  MarkedQuad oldquad;\n\t\t  MarkedQuad newquad1, newquad2;\n\t\t  PointIndex newp1, newp2;\n\t\t\n\t\t  oldquad = mquads.Get(i);\n                  /*\n\t\t  INDEX_2 edge1(oldquad.pnums[0],\n\t\t\t\toldquad.pnums[1]);\n\t\t  INDEX_2 edge2(oldquad.pnums[2],\n\t\t\t\toldquad.pnums[3]);\n                  */\n                  PointIndices<2> edge1, edge2;\n                  PointGeomInfo pgi11, pgi12, pgi21, pgi22;\n                  if (oldquad.markededge==0 || oldquad.markededge==2)\n                  {\n                    edge1[0] = oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0];\n                    edge1[1] = oldquad.pnums[1]; pgi12=oldquad.pgeominfo[1];\n                    edge2[0] = oldquad.pnums[2]; pgi21=oldquad.pgeominfo[2];\n                    edge2[1] = oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3];\n                  }\n                  else // 3 || 1\n                  {\n                    edge1[0] = oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0];\n                    edge1[1] = oldquad.pnums[2]; pgi12=oldquad.pgeominfo[2];\n                    edge2[0] = oldquad.pnums[1]; pgi21=oldquad.pgeominfo[1];\n                    edge2[1] = oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3];\n                  }\n                  \n                  edge1.Sort();\n\t\t  edge2.Sort();\n\n\t\t  if (cutedges.Used (edge1))\n\t\t    {\n\t\t      newp1 = cutedges.Get(edge1);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      Point<3> np1 = Center (mesh.Point (edge1[0]),\n                                             mesh.Point (edge1[1]));\n                      newp1 = mesh.AddPoint (np1);\n\t\t      cutedges.Set (edge1, newp1);\n                    }\n\n\t\t  if (cutedges.Used (edge2))\n\t\t    {\n\t\t      newp2 = cutedges.Get(edge2);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      Point<3> np2 = Center (mesh.Point (edge2[0]),\n                                             mesh.Point (edge2[1]));\n\t\t      newp2 = mesh.AddPoint (np2);\n\t\t      cutedges.Set (edge2, newp2);\n                    }\n\n\t\t  PointGeomInfo npgi1, npgi2;\n\t\t\n\t\t  int si = mesh.GetFaceDescriptor (oldquad.surfid).SurfNr();\n                  geo.PointBetween(mesh.Point (edge1.I1()), mesh.Point (edge1.I2()),\n                                   0.5, si,\n                                   pgi11,\n                                   pgi12,\n                                   mesh.Point (newp1), npgi1);\n                  geo.PointBetween (mesh.Point (edge2.I1()), mesh.Point (edge2.I2()),\n                                    0.5, si,\n                                    pgi21,\n                                    pgi22,\n                                    mesh.Point (newp2), npgi2);\n\n\t\t  BTBisectQuad (oldquad, newp1, npgi1, newp2, npgi2,\n\t\t\t\tnewquad1, newquad2);\n                  \n\t\t  mquads.Elem(i) = newquad1;\n\t\t  mquads.Append (newquad2);\n\t\t}\n\n            NgProfiler::StartTimer (timer1b);            \n\t    hangingsurf = \n\t      MarkHangingTris (mtris, cutedges, opt.task_manager) +\n\t      MarkHangingQuads (mquads, cutedges);\n\n\t    hangingedge = mesh.GetDimension() == 3 ? 0 : MarkHangingIdentifications(mids, cutedges);\n            NgProfiler::StopTimer (timer1b);                        \n            NgProfiler::StartTimer (timer_bisectsegms);            \t  \n\t    int nseg = mesh.GetNSeg ();\n\t    for (int i = 1; i <= nseg; i++)\n\t      {\n\t\tSegment & seg = mesh.LineSegment (i);\n\t\tPointIndices<2> edge(seg[0], seg[1]);\n\t\tedge.Sort();\n\t\tif (cutedges.Used (edge))\n\t\t  {\n\t\t    hangingedge = 1;\n\t\t    Segment nseg1 = seg;\n\t\t    Segment nseg2 = seg;\n\t\t  \n\t\t    PointIndex newpi = cutedges.Get(edge);\n\t\t  \n\t\t    nseg1[1] = newpi;\n\t\t    nseg2[0] = newpi;\n\t\t  \n\t\t    EdgePointGeomInfo newepgi;\n\t\t  \n\t\t    geo.PointBetweenEdge(mesh.Point (seg[0]), mesh.Point (seg[1]),\n                                         0.5, seg.surfnr1, seg.surfnr2,\n                                         seg.epgeominfo[0], seg.epgeominfo[1],\n                                         mesh.Point (newpi), newepgi);\n\t\t    nseg1.epgeominfo[1] = newepgi;\n\t\t    nseg2.epgeominfo[0] = newepgi;\n\t\t  \n\t\t    mesh.LineSegment (i) = nseg1;\n\t\t    mesh.AddSegment (nseg2);\n\t\t  }\n\t      }\n\n            NgProfiler::StopTimer (timer_bisectsegms);            \t              \n\t  }\n\twhile (hangingvol || hangingsurf || hangingedge);\n        \n\t/*\n        if (printmessage_importance>0)\n\t  {\n\t    ostringstream strstr;\n\t    strstr << mtets.Size() << \" tets\" << endl\n\t\t   << mtris.Size() << \" trigs\" << endl;\n\t    if (mprisms.Size())\n\t      {\n\t\tstrstr << mprisms.Size() << \" prisms\" << endl\n\t\t       << mquads.Size() << \" quads\" << endl;\n\t      }\n\t    strstr << mesh.GetNP() << \" points\";\n\t    PrintMessage(4,strstr.str());\n\t  }\n\t*/\n\tPrintMessage (4, mtets.Size(), \" tets\");\n\tPrintMessage (4, mtris.Size(), \" trigs\");\n\tif (mprisms.Size())\n\t  {\n\t    PrintMessage (4, mprisms.Size(), \" prisms\");\n\t    PrintMessage (4, mquads.Size(), \" quads\");\n\t  }\n\tPrintMessage (4, mesh.GetNP(), \" points\");\n      }\n\n    NgProfiler::StopTimer (timer1);\n\n\n    // (*testout) << \"mtets = \" << mtets << endl;\n\n    if (opt.refine_hp)\n      {\n\t//\n\tArray<int,PointIndex> v_order (mesh.GetNP());\n\tv_order = 0;\n\tif (mesh.GetDimension() == 3)\n\t  {\n\t    // for (int i = 1; i <= mtets.Size(); i++)\n            for (auto ei : mtets.Range())\n\t      if (mtets[ei].incorder)\n\t\tmtets[ei].order++;\n      \n\t    // for (int i = 0; i < mtets.Size(); i++)\n            for (auto ei : mtets.Range())              \n\t      for (int j = 0; j < 4; j++)\n\t\tif (int(mtets[ei].order) > v_order[mtets[ei].pnums[j]])\n\t\t  v_order[mtets[ei].pnums[j]] = mtets[ei].order;\n\t    // for (int i = 0; i < mtets.Size(); i++)\n            for (auto ei : mtets.Range())                            \n\t      for (int j = 0; j < 4; j++)\n\t\tif (int(mtets[ei].order) < v_order[mtets[ei].pnums[j]]-1)\n\t\t  mtets[ei].order = v_order[mtets[ei].pnums[j]]-1;\n\t  }\n\telse\n\t  {\n\t    for (int i = 1; i <= mtris.Size(); i++)\n\t      if (mtris.Elem(i).incorder)\n\t\t{\n\t\t  mtris.Elem(i).order++;\n\t\t}\n\n\t    for (int i = 0; i < mtris.Size(); i++)\n\t      for (int j = 0; j < 3; j++)\n\t\tif (int(mtris[i].order) > v_order[mtris[i].pnums[j]])\n\t\t  v_order[mtris[i].pnums[j]] = mtris[i].order;\n\t    for (int i = 0; i < mtris.Size(); i++)\n\t      {\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  if (int(mtris[i].order) < v_order[mtris[i].pnums[j]]-1)\n\t\t    mtris[i].order = v_order[mtris[i].pnums[j]]-1;\n\t      }\n\t  }\n      }\n\n    NgProfiler::StartTimer (timer2);\n\n    NgProfiler::StartTimer (timer2a);    \n    \n    mtets.SetAllocSize (mtets.Size());\n    mprisms.SetAllocSize (mprisms.Size());\n    mids.SetAllocSize (mids.Size());\n    mtris.SetAllocSize (mtris.Size());\n    mquads.SetAllocSize (mquads.Size());\n  \n    (*opt.tracer)(\"copy tets\", false);\n    mesh.ClearVolumeElements();\n    mesh.VolumeElements().SetAllocSize (mtets.Size()+mprisms.Size());\n    mesh.VolumeElements().SetSize(mtets.Size());\n    /*\n    for (int i = 1; i <= mtets.Size(); i++)\n      {\n\tElement el(TET);\n\tel.SetIndex (mtets.Get(i).matindex);\n\tfor (int j = 1; j <= 4; j++)\n\t  el.PNum(j) = mtets.Get(i).pnums[j-1];\n\tel.SetOrder (mtets.Get(i).order);\n\tmesh.AddVolumeElement (el);\n      }\n    */\n    ngcore::ParallelForRange\n      (mtets.Range(), [&] (auto myrange)\n       {\n         for (auto ei : myrange)\n          {\n            Element el(TET);\n            auto & tet = mtets[ei];\n            el.SetIndex (tet.matindex);\n            el.SetOrder (tet.order);\n            for (int j = 0; j < 4; j++)\n              el[j] = tet.pnums[j];\n            el.NewestVertex() = tet.newest_vertex;\n            mesh.SetVolumeElement (ei, el);\n          }\n       });\n\n    (*opt.tracer)(\"copy tets\", true);\n    \n    for (int i = 1; i <= mprisms.Size(); i++)\n      {\n\tElement el(PRISM);\n\tel.SetIndex (mprisms.Get(i).matindex);\n\tfor (int j = 1; j <= 6; j++)\n\t  el.PNum(j) = mprisms.Get(i).pnums[j-1];\n\tel.SetOrder (mprisms.Get(i).order);\n\n\t// degenerated prism ?\n\tstatic const int map1[] = { 3, 2, 5, 6, 1 };\n\tstatic const int map2[] = { 1, 3, 6, 4, 2 };\n\tstatic const int map3[] = { 2, 1, 4, 5, 3 };\n      \n\n\tconst int * map = NULL;\n\tint deg1 = 0, deg2 = 0, deg3 = 0;\n\t// int deg = 0;\n\tif (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; }\n\tif (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; }\n\tif (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; }\n\t  \n\tswitch (deg1+deg2+deg3)\n\t  {\n\t  case 1:\n\t    {\n\t      for (int j = 1; j <= 5; j++)\n\t\tel.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1];\n\t    \n\t      el.SetType (PYRAMID);\n\t      break;\n\t    }\n\t  case 2:\n\t    {\n\t      static const int tetmap1[] = { 1, 2, 3, 4 };\n\t      static const int tetmap2[] = { 2, 3, 1, 5 };\n\t      static const int tetmap3[] = { 3, 1, 2, 6 };\n\t      if (!deg1) map = tetmap1;\n\t      if (!deg2) map = tetmap2;\n\t      if (!deg3) map = tetmap3; \n\t      for (int j = 1; j <= 4; j++)\n\t\tel.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1];\n\t      /*\n\t\tif (!deg1) el.PNum(4) = el.PNum(4);\n\t\tif (!deg2) el.PNum(4) = el.PNum(5);\n\t\tif (!deg3) el.PNum(4) = el.PNum(6);\n\t      */\n\t      el.SetType(TET);\n\t      break;\n\t    }\n\t  default:\n\t    ;\n\t  }\n\tmesh.AddVolumeElement (el);\n      }\n  \n    mesh.ClearSurfaceElements();\n    mesh.SurfaceElements().SetAllocSize (mtris.Size()+mquads.Size());    \n    NgProfiler::StopTimer (timer2a);        \n    NgProfiler::StartTimer (timer2b);\n    /*\n    for (auto & trig : mtris)\n      {\n\tElement2d el(TRIG);\n\tel.SetIndex (trig.surfid);\n\tel.SetOrder (trig.order);\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    el[j] = trig.pnums[j];\n\t    el.GeomInfoPi(j+1) = trig.pgeominfo[j];\n\t  }\n\tmesh.AddSurfaceElement (el);\n      }\n    */\n\n    mesh.SurfaceElements().SetSize(mtris.Size());\n    // for (size_t i = 0; i < mtris.Size(); i++)\n    ParallelForRange\n      (opt.task_manager, mtris.Size(), [&] (size_t begin, size_t end)\n       {\n         for (size_t i = begin; i < end; i++)\n          {\n            Element2d el(TRIG);\n            auto & trig = mtris[i];\n            el.SetIndex (trig.surfid);\n            el.SetOrder (trig.order);\n            for (int j = 0; j < 3; j++)\n              {\n                el[j] = trig.pnums[j];\n                el.GeomInfoPi(j+1) = trig.pgeominfo[j];\n              }\n            el.NewestVertex() = trig.newest_vertex;\n            mesh.SetSurfaceElement (SurfaceElementIndex(i), el);\n          }\n       });\n    mesh.RebuildSurfaceElementLists();\n    \n    for (int i = 1; i <= mquads.Size(); i++)\n      {\n\tElement2d el(QUAD);\n\tel.SetIndex (mquads.Get(i).surfid);\n\tfor (int j = 1; j <= 4; j++)\n\t  el.PNum(j) = mquads.Get(i).pnums[j-1];\n\tSwap (el.PNum(3), el.PNum(4));\n\tmesh.AddSurfaceElement (el);\n      }\n    NgProfiler::StopTimer (timer2b);        \n\n      \n    // write multilevel hierarchy to mesh:\n    np = mesh.GetNP();\n    mesh.mlbetweennodes.SetSize(np);\n    // if (mesh.mglevels <= 2)\n    if (mesh.level_nv.Size() <= 1)\n      {\n\tPrintMessage(4,\"RESETTING mlbetweennodes\");\n        /*\n\tfor (int i = 1; i <= np; i++)\n\t  {\n\t    mesh.mlbetweennodes.Elem(i).I1() = 0;\n\t    mesh.mlbetweennodes.Elem(i).I2() = 0;\n\t  }\n        */\n        for (auto i : mesh.mlbetweennodes.Range())\n          mesh.mlbetweennodes[i] = { PointIndex::INVALID, PointIndex::INVALID };\n      }\n\n    mesh.level_nv.Append (np);\n\n    \n    /*\n      for (i = 1; i <= cutedges.GetNBags(); i++)\n      for (j = 1; j <= cutedges.GetBagSize(i); j++)\n      {\n      INDEX_2 edge;\n      int newpi;\n      cutedges.GetData (i, j, edge, newpi);\n      mesh.mlbetweennodes.Elem(newpi) = edge;\n      }\n    */\n\n    \n    TBitArray<PointIndex> isnewpoint(np);\n    isnewpoint.Clear();\n\n    {\n    static Timer t(\"update mlbetween\"); RegionTimer reg(t);\n    /*\n    for (int i = 0; i < cutedges.Size(); i++)\n      if (cutedges.UsedPos0(i))\n\t{\n\t  INDEX_2 edge;\n\t  PointIndex newpi;\n\t  cutedges.GetData0 (i, edge, newpi);\n\t  isnewpoint.SetBit(newpi);\n\t  mesh.mlbetweennodes[newpi] = edge;\n\t}\n    */\n    for (auto [edge,newpi] : cutedges)\n      {\n        isnewpoint.SetBit(newpi);\n        mesh.mlbetweennodes[newpi] = edge;\n      }\n    }\n\n    \n    /*\n      mesh.PrintMemInfo (cout);\n      cout << \"tets \";\n      mtets.PrintMemInfo (cout);\n      cout << \"prims \";\n      mprisms.PrintMemInfo (cout);\n      cout << \"tris \";\n      mtris.PrintMemInfo (cout);\n      cout << \"quads \";\n      mquads.PrintMemInfo (cout);\n      cout << \"cutedges \";\n      cutedges.PrintMemInfo (cout);\n    */\n\n\n    /*\n\n    // find connected nodes (close nodes)\n    TABLE<int> conto(np);\n    for (i = 1; i <= mprisms.Size(); i++)\n    for (j = 1; j <= 6; j++)\n    {\n    int n1 = mprisms.Get(i).pnums[j-1];\n    int n2 = mprisms.Get(i).pnums[(j+2)%6];\n    //\t    if (n1 != n2)\n    {\n    int found = 0;\n    for (k = 1; k <= conto.EntrySize(n1); k++)\n    if (conto.Get(n1, k) == n2)\n    {\n    found = 1;\n    break;\n    }\n    if (!found)\n    conto.Add (n1, n2);\n    }\n    }\n    mesh.connectedtonode.SetSize(np);\n    for (i = 1; i <= np; i++)\n    mesh.connectedtonode.Elem(i) = 0;\n  \n\n    //       (*testout) << \"connection table: \" << endl;\n    //       for (i = 1; i <= np; i++)\n    //       {\n    //       (*testout) << \"node \" << i << \": \";\n    // \t  for (j = 1; j <= conto.EntrySize(i); j++)\n    // \t  (*testout) << conto.Get(i, j) << \" \";\n    // \t  (*testout) << endl;\n    // \t}\n\n  \n    for (i = 1; i <= np; i++)\n    if (mesh.connectedtonode.Elem(i) == 0)\n    {\n    mesh.connectedtonode.Elem(i) = i;\n    ConnectToNodeRec (i, i, conto, mesh.connectedtonode);\n    }\n    */  \n\n    //  mesh.BuildConnectedNodes();\n\n    \n    {\n    static Timer t(\"ComputeNV\"); RegionTimer reg(t);\n    mesh.ComputeNVertices();\n    }\n    \n    (*opt.tracer)(\"call RebuildSurfElList\", false);\n    mesh.RebuildSurfaceElementLists();\n    (*opt.tracer)(\"call RebuildSurfElList\", true);\n  \n    \n    // update identification tables    \n    for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tidmap_type identmap;\n\n\tmesh.GetIdentifications().GetMap (i, identmap);\n\n\n\t/*\n\t  for (j = 1; j <= cutedges.GetNBags(); j++)\n\t  for (k = 1; k <= cutedges.GetBagSize(j); k++)\n\t  {\n\t  INDEX_2 i2;\n\t  int newpi;\n\t  cutedges.GetData (j, k, i2, newpi);\n\t  INDEX_2 oi2(identmap.Get(i2.I1()),\n\t  identmap.Get(i2.I2()));\n\t  oi2.Sort();\n\t  if (cutedges.Used (oi2))\n\t  {\n\t  int onewpi = cutedges.Get(oi2);\n\t  mesh.GetIdentifications().Add (newpi, onewpi, i);\n\t  }\n\t  }\n\t*/\n\n\n        /*\n\tfor (int j = 0; j < cutedges.Size(); j++)\n\t  if (cutedges.UsedPos0(j))\n\t    {\n\t      PointIndices<2> i2;\n\t      PointIndex newpi;\n\t      cutedges.GetData0 (j, i2, newpi);\n\t      PointIndices<2> oi2(identmap[i2[0]], \n                                  identmap[i2[1]]);\n\t      oi2.Sort();\n\t      if (cutedges.Used (oi2))\n\t\t{\n\t\t  PointIndex onewpi = cutedges.Get(oi2);\n\t\t  mesh.GetIdentifications().Add (newpi, onewpi, i);\n\t\t}\n\t    }\n        */\n        for (auto [i2, newpi] : cutedges)\n          {\n            PointIndices<2> oi2(identmap[i2[0]], \n                                identmap[i2[1]]);\n            if((!oi2[0].IsValid()) || (!oi2[1].IsValid()))\n              continue;\n            oi2.Sort();\n            if (cutedges.Used (oi2))\n              {\n                PointIndex onewpi = cutedges.Get(oi2);\n                mesh.GetIdentifications().Add (newpi, onewpi, i);\n              }\n          }\n      }\n    \n    (*opt.tracer)(\"Bisect\", true);\n\n    // Repair works only for tets!\n    bool do_repair = mesh.PureTetMesh ();\n\n    do_repair = false;   // JS, March 2009: multigrid crashes\n\n    //if(mesh.mglevels == 3)\n    //  noprojection = true;\n\n    //noprojection = true;\n\n    if(noprojection)\n      {\n\tdo_repair = false;\n\t// for(int ii=1; ii<=mesh.GetNP(); ii++)\n        for (auto ii : mesh.Points().Range())\n\t  {\n\t    if(isnewpoint.Test(ii) && mesh.mlbetweennodes[ii][0].IsValid())\n\t      {\n\t\tmesh.Point(ii) = Center(mesh.Point(mesh.mlbetweennodes[ii][0]),\n                                        mesh.Point(mesh.mlbetweennodes[ii][1]));\n\t      }\n\t  }\n      }\n\n    \n    // Check/Repair\n\n    static bool repaired_once;\n    // if(mesh.mglevels == 1)\n    if(mesh.level_nv.Size() == 1)\n      repaired_once = false;\n\n    //mesh.Save(\"before.vol\");\n\n    static int reptimer = NgProfiler::CreateTimer(\"check/repair\");\n\tNgProfiler::RegionTimer * regt(NULL);\n    regt = new NgProfiler::RegionTimer(reptimer); \n\n    NgArray<ElementIndex> bad_elts;\n    NgArray<double> pure_badness;\n   \n    if(do_repair || quality_loss != NULL)\n      {\n\tpure_badness.SetSize(mesh.GetNP()+2);\n\tGetPureBadness(mesh,pure_badness,isnewpoint);\n      }\n\n\n    if(do_repair)  // by Markus W\n      {\n\tconst double max_worsening = 1;\n\t\n\tconst bool uselocalworsening = false;\n\t\n\t// bool repaired = false;\n\t\n\tValidate(mesh,bad_elts,pure_badness,max_worsening,uselocalworsening);\n\t\n        if (printmessage_importance>0)\n\t  {\n\t    ostringstream strstr;\n\t    for(int ii=0; ii<bad_elts.Size(); ii++)\n\t      strstr << \"bad element \" << bad_elts[ii] << \"\\n\";\n\t    PrintMessage(1,strstr.str());\n\t  }\n\tif(repaired_once || bad_elts.Size() > 0)\n\t  {\n\t    clock_t t1(clock());\n\t    \n\t    \n\t    // update id-maps\n\t    int j=0;\n\t    for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)\n\t      {\n\t\tif(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)\n\t\t  {\n\t\t    mesh.GetIdentifications().GetMap(i,*idmaps[j],true);\n\t\t    j++;\n\t\t  }\n\t      }\n\n    \n\t    // do the repair\n\t    try\n\t      {\n\t\tRepairBisection(mesh,bad_elts,isnewpoint,*this,\n\t\t\t\tpure_badness,\n\t\t\t\tmax_worsening,uselocalworsening,\n\t\t\t\tidmaps);\n\t\t// repaired = true;\n\t\trepaired_once = true;\n\t      }\n\t    catch(NgException & ex)\n\t      {\n\t\tPrintMessage(1,string(\"Problem: \") + ex.What());\n\t      }\n\n\n            if (printmessage_importance>0)\n            {\n\t      ostringstream strstr;\n              strstr << \"Time for Repair: \" << double(clock() - t1)/double(CLOCKS_PER_SEC) << endl\n\t\t     << \"bad elements after repair: \" << bad_elts << endl;\n\t      PrintMessage(1,strstr.str());\n            }\n\t    \n\t    if(quality_loss != NULL)\n\t      Validate(mesh,bad_elts,pure_badness,1e100,uselocalworsening,quality_loss);\n\n\t    if(idmaps.Size() == 0)\n\t      UpdateEdgeMarks(mesh,idmaps);\n\t    \n\t    /*\n\t    if(1==1)\n\t      UpdateEdgeMarks(mesh,idmaps);\n\t    else\n\t      mesh.mglevels = 1;\n\t    */\n\t    \n\t    //mesh.ImproveMesh();\n\t    \n\t  }\n      }\n    delete regt;\n\n\n    \n    for(int i=0; i<idmaps.Size(); i++)\n      delete idmaps[i];\n    idmaps.DeleteAll();\n\n    NgProfiler::StopTimer (timer2);\n    NgProfiler::StartTimer (timer3);\n\n    NgProfiler::StartTimer (timer3a);\n    (*opt.tracer)(\"topology from bisect\", false);\n    mesh.UpdateTopology(opt.task_manager, opt.tracer);\n    (*opt.tracer)(\"topology from bisect\", true);\n    NgProfiler::StopTimer (timer3a);    \n\n\n\n    if(refelementinfofilewrite != \"\")\n      {\n\tPrintMessage(3,\"writing marked-elements information to \\\"\",refelementinfofilewrite,\"\\\"\");\n\tofstream ofst(refelementinfofilewrite.c_str());\n\n\tWriteMarkedElements(mesh, ofst);\n\n\tofst.close();\n      }\n\n    NgProfiler::StartTimer (timer3b);    \n    mesh.CalcSurfacesOfNode();\n    NgProfiler::StopTimer (timer3b);        \n\n    PrintMessage (1, \"Bisection done\");\n\n    PopStatus();\n    NgProfiler::StopTimer (timer3);    \n  }\n\n  \n\n  BisectionOptions :: BisectionOptions ()\n  {\n    outfilename = NULL;\n    mlfilename = NULL;\n    refinementfilename = NULL;\n    femcode = NULL;\n    maxlevel = 50;\n    usemarkedelements = 0;\n    refine_hp = 0;\n    refine_p = 0;\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/bisect.hpp",
    "content": "#ifndef NETGEN_BISECT_HPP\n#define NETGEN_BISECT_HPP\n\n#include <mydefs.hpp>\n#include <general/parthreads.hpp>\n#include \"basegeom.hpp\"\n#include \"meshclass.hpp\"\n\nnamespace netgen\n{\n\nclass BisectionOptions\n{\npublic:\n  const char * outfilename;\n  const char * mlfilename;\n  const char * refinementfilename;\n  const char * femcode;\n  int maxlevel;\n  int usemarkedelements;\n  bool refine_hp = false;\n  bool refine_p = false;\n  bool onlyonce = false;\n  NgTaskManager task_manager = &DummyTaskManager;\n  NgTracer tracer = &DummyTracer;\n  DLL_HEADER BisectionOptions ();\n};\n\nclass ZRefinementOptions\n{\npublic:\n  int minref;\n  DLL_HEADER ZRefinementOptions();\n};\n\n\n\nDLL_HEADER extern void BisectTetsCopyMesh (Mesh &, const NetgenGeometry *,\n\t\t\t\tBisectionOptions & opt);\n\nDLL_HEADER extern void ZRefinement (Mesh &, const class NetgenGeometry *,\n\t\t\t ZRefinementOptions & opt);\n\n\n\n\n\nclass DLL_HEADER Refinement\n{\n const NetgenGeometry& geo;\n\npublic:\n Refinement (const NetgenGeometry& ageo) : geo(ageo) {}\n virtual ~Refinement () {}\n  \n  void Refine (Mesh & mesh) const;\n  void Refine (Mesh & mesh);\n  void Bisect (Mesh & mesh, class BisectionOptions & opt, NgArray<double> * quality_loss = NULL) const;\n\n  void MakeSecondOrder (Mesh & mesh) const;\n  void MakeSecondOrder (Mesh & mesh);\n\n  void ValidateSecondOrder (Mesh & mesh);\n  void ValidateRefinedMesh (Mesh & mesh, \n\t\t\t    NgArray<INDEX_2> & parents);\n  \n  virtual void LocalizeEdgePoints(Mesh & /* mesh */) const {;}\n};\n\n} // namespace netgen\n\n#endif // NETGEN_BISECT_HPP\n"
  },
  {
    "path": "libsrc/meshing/boundarylayer.cpp",
    "content": "#include \"boundarylayer.hpp\"\n#include \"boundarylayer_limiter.hpp\"\n\n#include <regex>\n#include <set>\n#include <variant>\n\n#include \"debugging.hpp\"\n#include \"global.hpp\"\n#include \"meshfunc.hpp\"\n\nnamespace netgen\n{\n\nstruct SpecialPointException : public Exception\n{\n  SpecialPointException ()\n    : Exception(\"\") {}\n};\n\nstd::tuple<int, int> FindCloseVectors (FlatArray<Vec<3>> ns,\n                                       bool find_max = true)\n{\n  int maxpos1 = 0;\n  int maxpos2 = 0;\n\n  double val = find_max ? -1e99 : 1e99;\n  for (auto i : Range(ns))\n    for (auto j : Range(i + 1, ns.Size()))\n      {\n        double ip = ns[i] * ns[j];\n        if ((find_max && (ip > val)) || (!find_max && (ip < val)))\n          {\n            val = ip;\n            maxpos1 = i;\n            maxpos2 = j;\n          }\n      }\n  return {maxpos1, maxpos2};\n}\n\nVec<3> CalcGrowthVector (FlatArray<Vec<3>> ns)\n{\n  if (ns.Size() == 0)\n    return {0, 0, 0};\n  if (ns.Size() == 1)\n    return ns[0];\n  if (ns.Size() == 2)\n    {\n      auto gw = ns[0];\n      auto n = ns[1];\n      auto npn = gw * n;\n      auto npnp = gw * gw;\n      auto nn = n * n;\n      if (fabs(nn - npn * npn / npnp) < 1e-6)\n        return n;\n      gw += (nn - npn) / (nn - npn * npn / npnp) * (n - npn / npnp * gw);\n      return gw;\n    }\n  if (ns.Size() == 3)\n    {\n      DenseMatrix mat(3, 3);\n      for (auto i : Range(3))\n        for (auto j : Range(3))\n          mat(i, j) = ns[i][j];\n\n      if (fabs(mat.Det()) > 1e-2)\n        {\n          DenseMatrix mat(3, 3);\n          for (auto i : Range(3))\n            for (auto j : Range(3))\n              mat(i, j) = ns[i] * ns[j];\n          if (fabs(mat.Det()) > 1e-2)\n            {\n              Vector rhs(3);\n              rhs = 1.;\n              Vector res(3);\n              DenseMatrix inv(3, ns.Size());\n              CalcInverse(mat, inv);\n              inv.Mult(rhs, res);\n              Vec<3> growth = 0.;\n              for (auto i : Range(ns))\n                growth += res[i] * ns[i];\n              return growth;\n            }\n        }\n    }\n  auto [maxpos1, maxpos2] = FindCloseVectors(ns);\n  Array<Vec<3>> new_normals;\n  new_normals = ns;\n  // const auto dot = ns[maxpos1] * ns[maxpos2];\n  auto average = 0.5 * (ns[maxpos1] + ns[maxpos2]);\n  average.Normalize();\n  new_normals[maxpos1] = average;\n  new_normals.DeleteElement(maxpos2);\n  auto gw = CalcGrowthVector(new_normals);\n\n  for (auto n : ns)\n    if (n * gw < 0)\n      throw SpecialPointException();\n  return gw;\n}\n\nSpecialBoundaryPoint ::GrowthGroup ::GrowthGroup (FlatArray<int> faces_,\n                                                  FlatArray<Vec<3>> normals)\n{\n  faces = faces_;\n  growth_vector = CalcGrowthVector(normals);\n}\n\nSpecialBoundaryPoint ::SpecialBoundaryPoint (\n  const std::map<int, Vec<3>>& normals)\n{\n  // find opposing face normals\n  Array<Vec<3>> ns;\n  Array<int> faces;\n  for (auto [face, normal] : normals)\n    {\n      ns.Append(normal);\n      faces.Append(face);\n    }\n\n  auto [minface1, minface2] = FindCloseVectors(ns, false);\n  minface1 = faces[minface1];\n  minface2 = faces[minface2];\n  Array<int> g1_faces;\n  g1_faces.Append(minface1);\n  Array<int> g2_faces;\n  g2_faces.Append(minface2);\n  auto n1 = normals.at(minface1);\n  auto n2 = normals.at(minface2);\n  separating_direction = 0.5 * (n2 - n1);\n\n  Array<Vec<3>> normals1, normals2;\n  for (auto [facei, normali] : normals)\n    if (facei != minface1 && facei != minface2)\n      {\n        g1_faces.Append(facei);\n        g2_faces.Append(facei);\n      }\n  for (auto fi : g1_faces)\n    normals1.Append(normals.at(fi));\n  for (auto fi : g2_faces)\n    normals2.Append(normals.at(fi));\n  growth_groups.Append(GrowthGroup(g1_faces, normals1));\n  growth_groups.Append(GrowthGroup(g2_faces, normals2));\n}\n\nVec<3> BoundaryLayerTool ::getEdgeTangent (PointIndex pi, int index, FlatArray<Segment*> segs)\n{\n  Vec<3> tangent = 0.0;\n  ArrayMem<PointIndex, 2> pts;\n  for (auto* p_seg : segs)\n    {\n      auto& seg = *p_seg;\n      if (seg.index != index)\n        continue;\n      PointIndex other = seg[0] - pi + seg[1];\n      if (!pts.Contains(other))\n        pts.Append(other);\n    }\n  if (pts.Size() != 2)\n    {\n      cout << \"getEdgeTangent pi = \" << pi << \", index = \" << index << endl;\n      cout << pts << endl;\n      for (auto* p_seg : segs)\n        cout << *p_seg << endl;\n      throw NG_EXCEPTION(\"Something went wrong in getEdgeTangent!\");\n    }\n  tangent = mesh[pts[1]] - mesh[pts[0]];\n  return tangent.Normalize();\n}\n\nvoid BoundaryLayerTool ::LimitGrowthVectorLengths ()\n{\n  static Timer tall(\"BoundaryLayerTool::LimitGrowthVectorLengths\");\n  RegionTimer rtall(tall);\n\n  GrowthVectorLimiter limiter(*this);\n  limiter.Perform();\n}\n\n// depending on the geometry type, the mesh contains segments multiple times\n// (once for each face)\nbool HaveSingleSegments (const Mesh& mesh)\n{\n  auto& topo = mesh.GetTopology();\n  NgArray<SurfaceElementIndex> surf_els;\n\n  for (auto segi : Range(mesh.LineSegments()))\n    {\n      mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);\n      if (surf_els.Size() < 2)\n        continue;\n\n      auto seg = mesh[segi];\n      auto pi0 = min(seg[0], seg[1]);\n      auto pi1 = max(seg[0], seg[1]);\n      auto p0_segs = topo.GetVertexSegments(seg[0]);\n\n      for (auto segi_other : p0_segs)\n        {\n          if (segi_other == segi)\n            continue;\n\n          auto seg_other = mesh[segi_other];\n          auto pi0_other = min(seg_other[0], seg_other[1]);\n          auto pi1_other = max(seg_other[0], seg_other[1]);\n          if (pi0_other == pi0 && pi1_other == pi1)\n            return false;\n        }\n\n      // found segment with multiple adjacent surface elements but no other\n      // segments with same points -> have single segments\n      return true;\n    }\n\n  return true;\n}\n\n// duplicates segments (and sets seg.si accordingly) to have a unified data\n// structure for all geometry types\nvoid BuildSegments (Mesh& mesh, bool have_single_segments, Array<Segment>& segments, Array<Segment>& free_segments)\n{\n  // auto& topo = mesh.GetTopology();\n\n  NgArray<SurfaceElementIndex> surf_els;\n\n  for (auto segi : Range(mesh.LineSegments()))\n    {\n      auto seg = mesh[segi];\n      if (seg.domin == seg.domout && seg.domin > 0)\n        {\n          free_segments.Append(seg);\n          continue;\n        }\n      if (!have_single_segments)\n        {\n          segments.Append(seg);\n          continue;\n        }\n      mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);\n      for (auto seli : surf_els)\n        {\n          const auto& sel = mesh[seli];\n          seg.si = sel.GetIndex();\n\n          auto np = sel.GetNP();\n          for (auto i : Range(np))\n            {\n              if (sel[i] == seg[0])\n                {\n                  if (sel[(i + 1) % np] != seg[1])\n                    swap(seg[0], seg[1]);\n                  break;\n                }\n            }\n\n          segments.Append(seg);\n        }\n    }\n}\n\nvoid MergeAndAddSegments (Mesh& mesh, FlatArray<Segment> segments, FlatArray<Segment> new_segments)\n{\n  INDEX_2_HASHTABLE<bool> already_added(segments.Size() + 2 * new_segments.Size());\n\n  mesh.LineSegments().SetSize0();\n\n  auto addSegment = [&] (auto seg) {\n    SortedPointIndices<2> i2(seg[0], seg[1]);\n    if (!already_added.Used(i2))\n      {\n        seg.si = seg.index + 1;\n        mesh.AddSegment(seg);\n        already_added.Set(i2, true);\n      }\n  };\n\n  for (const auto& seg : segments)\n    addSegment(seg);\n\n  for (const auto& seg : new_segments)\n    addSegment(seg);\n}\n\nBoundaryLayerTool::BoundaryLayerTool (Mesh& mesh_,\n                                      const BoundaryLayerParameters& params_)\n  : mesh(mesh_), topo(mesh_.GetTopology()), params(params_)\n{\n  static Timer timer(\"BoundaryLayerTool::ctor\");\n  RegionTimer regt(timer);\n  ProcessParameters();\n  if (domains.NumSet() == 0)\n    return;\n\n  topo.SetBuildVertex2Element(true);\n  mesh.UpdateTopology();\n\n  old_segments = mesh.LineSegments();\n  have_single_segments = HaveSingleSegments(mesh);\n\n  BuildSegments(mesh, have_single_segments, segments, free_segments);\n\n  np = mesh.GetNP();\n  first_new_pi = IndexBASE<PointIndex>() + np;\n  ne = mesh.GetNE();\n  nse = mesh.GetNSE();\n  nseg = segments.Size();\n\n  p2sel = mesh.CreatePoint2SurfaceElementTable();\n\n  nfd_old = mesh.GetNFD();\n  moved_surfaces.SetSize(nfd_old + 1);\n  moved_surfaces.Clear();\n  si_map.SetSize(nfd_old + 1);\n  for (auto i : Range(nfd_old + 1))\n    si_map[i] = i;\n}\n\nvoid BoundaryLayerTool ::CreateNewFaceDescriptors ()\n{\n  surfacefacs.SetSize(nfd_old + 1);\n  surfacefacs = 0.0;\n  // create new FaceDescriptors\n  for (auto i : Range(1, nfd_old + 1))\n    {\n      const auto& fd = mesh.GetFaceDescriptor(i);\n      string name = fd.GetBCName();\n      if (par_surfid.Contains(i))\n        {\n          if (auto isIn = domains.Test(fd.DomainIn());\n              isIn != domains.Test(fd.DomainOut()))\n            {\n              int new_si = mesh.GetNFD() + 1;\n              surfacefacs[i] = isIn ? 1. : -1.;\n              moved_surfaces.SetBit(i);\n              if (!insert_only_volume_elements)\n                {\n                  // -1 surf nr is so that curving does not do anything\n                  FaceDescriptor new_fd(-1, isIn ? new_mat_nrs[i] : fd.DomainIn(), isIn ? fd.DomainOut() : new_mat_nrs[i], -1);\n                  new_fd.SetBCProperty(new_si);\n                  new_fd.SetSurfColour(fd.SurfColour());\n                  mesh.AddFaceDescriptor(new_fd);\n                  si_map[i] = new_si;\n                  mesh.SetBCName(new_si - 1, \"mapped_\" + name);\n                }\n            }\n          // curving of surfaces with boundary layers will often\n          // result in pushed through elements, since we do not (yet)\n          // curvature through layers.\n          // Therefore we disable curving for these surfaces.\n          if (params.disable_curving)\n            mesh.GetFaceDescriptor(i).SetSurfNr(-1);\n        }\n    }\n\n  for (auto si : par_surfid)\n    if (surfacefacs[si] == 0.0)\n      throw Exception(\"Surface \" + to_string(si) + \" is not a boundary of the domain to be grown into!\");\n}\n\nvoid BoundaryLayerTool ::CreateFaceDescriptorsSides ()\n{\n  if (insert_only_volume_elements)\n    return;\n  BitArray face_done(mesh.GetNFD() + 1);\n  face_done.Clear();\n  for (const auto& sel : mesh.SurfaceElements())\n    {\n      auto facei = sel.GetIndex();\n      if (face_done.Test(facei))\n        continue;\n      bool point_moved = false;\n      // bool point_fixed = false;\n      for (auto pi : sel.PNums())\n        {\n          if (growthvectors[pi].Length() > 0)\n            point_moved = true;\n          /*\n          else\n            point_fixed = true;\n          */\n        }\n      if (point_moved && !moved_surfaces.Test(facei))\n        {\n          int new_si = mesh.GetNFD() + 1;\n          const auto& fd = mesh.GetFaceDescriptor(facei);\n          // auto isIn = domains.Test(fd.DomainIn());\n          // auto isOut = domains.Test(fd.DomainOut());\n          int si = params.sides_keep_surfaceindex ? facei : -1;\n          // domin and domout can only be set later\n          FaceDescriptor new_fd(si, -1, -1, si);\n          new_fd.SetBCProperty(new_si);\n          mesh.AddFaceDescriptor(new_fd);\n          si_map[facei] = new_si;\n          mesh.SetBCName(new_si - 1, fd.GetBCName());\n          face_done.SetBit(facei);\n        }\n    }\n}\n\nvoid BoundaryLayerTool ::CalculateGrowthVectors ()\n{\n  growthvectors.SetSize(np);\n  growthvectors = 0.;\n\n  for (auto pi : mesh.Points().Range())\n    {\n      const auto& p = mesh[pi];\n      if (p.Type() == INNERPOINT)\n        continue;\n\n      std::map<int, Vec<3>> normals;\n\n      // calculate one normal vector per face (average with angles as weights for\n      // multiple surface elements within a face)\n      for (auto sei : p2sel[pi])\n        {\n          const auto& sel = mesh[sei];\n          auto facei = sel.GetIndex();\n          if (!par_surfid.Contains(facei))\n            continue;\n\n          auto n = surfacefacs[sel.GetIndex()] * getNormal(sel);\n\n          int itrig = sel.PNums().Pos(pi);\n          itrig += sel.GetNP();\n          auto v0 = (mesh[sel.PNumMod(itrig + 1)] - mesh[pi]).Normalize();\n          auto v1 = (mesh[sel.PNumMod(itrig - 1)] - mesh[pi]).Normalize();\n          if (normals.count(facei) == 0)\n            normals[facei] = {0., 0., 0.};\n          normals[facei] += acos(v0 * v1) * n;\n        }\n\n      for (auto& [facei, n] : normals)\n        n *= 1.0 / n.Length();\n\n      // combine normal vectors for each face to keep uniform distances\n      ArrayMem<Vec<3>, 5> ns;\n      for (auto& [facei, n] : normals)\n        {\n          ns.Append(n);\n        }\n\n      try\n        {\n          growthvectors[pi] = CalcGrowthVector(ns);\n        }\n      catch (const SpecialPointException& e)\n        {\n          special_boundary_points.emplace(pi, normals);\n          growthvectors[pi] =\n            special_boundary_points[pi].growth_groups[0].growth_vector;\n        }\n    }\n}\n\nArray<Array<pair<SegmentIndex, int>>, SegmentIndex>\nBoundaryLayerTool ::BuildSegMap ()\n{\n  // Bit array to keep track of segments already processed\n  BitArray segs_done(nseg + 1);\n  segs_done.Clear();\n\n  // map for all segments with same points\n  // points to pair of SegmentIndex, int\n  // int is type of other segment, either:\n  // 0 == adjacent surface grows layer\n  // 1 == adjacent surface doesn't grow layer, but layer ends on it\n  // 2 == adjacent surface is interior surface that ends on layer\n  // 3 == adjacent surface is exterior surface that ends on layer (not allowed\n  // yet)\n  Array<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap(segments.Size());\n\n  // moved segments\n  is_edge_moved.SetSize(max_edge_nr + 1);\n  is_edge_moved = false;\n\n  // boundaries to project endings to\n  is_boundary_projected.SetSize(nfd_old + 1);\n  is_boundary_projected.Clear();\n  is_boundary_moved.SetSize(nfd_old + 1);\n  is_boundary_moved.Clear();\n\n  for (auto si : Range(segments))\n    {\n      if (segs_done[si])\n        continue;\n      const auto& segi = segments[si];\n      if (!moved_surfaces.Test(segi.si))\n        continue;\n      segs_done.SetBit(si);\n      segmap[si].Append(make_pair(si, 0));\n      moved_segs.Append(si);\n      is_edge_moved.SetBit(segi.index);\n      for (auto sj : Range(segments))\n        {\n          if (segs_done.Test(sj))\n            continue;\n          const auto& segj = segments[sj];\n          if ((segi[0] == segj[0] && segi[1] == segj[1]) || (segi[0] == segj[1] && segi[1] == segj[0]))\n            {\n              segs_done.SetBit(sj);\n              int type;\n              if (moved_surfaces.Test(segj.si))\n                {\n                  type = 0;\n                  moved_segs.Append(sj);\n                }\n              else if (const auto& fd = mesh.GetFaceDescriptor(segj.si);\n                       domains.Test(fd.DomainIn()) && domains.Test(fd.DomainOut()))\n                {\n                  type = 2;\n                  if (fd.DomainIn() == 0 || fd.DomainOut() == 0)\n                    is_boundary_projected.SetBit(segj.si);\n                }\n              else if (const auto& fd = mesh.GetFaceDescriptor(segj.si);\n                       !domains.Test(fd.DomainIn()) && !domains.Test(fd.DomainOut()))\n                {\n                  type = 3;\n                  // cout << \"set is_moved boundary to type 3 for \" << segj.si << endl;\n                  is_boundary_moved.SetBit(segj.si);\n                }\n              else\n                {\n                  type = 1;\n                  // in case 1 we project the growthvector onto the surface\n                  is_boundary_projected.SetBit(segj.si);\n                }\n              segmap[si].Append(make_pair(sj, type));\n            }\n        }\n    }\n\n  return segmap;\n}\n\nBitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface ()\n{\n  BitArray in_surface_direction(nfd_old + 1);\n  in_surface_direction.Clear();\n  // project growthvector on surface for inner angles\n  if (params.grow_edges)\n    {\n      for (const auto& sel : mesh.SurfaceElements())\n        if (is_boundary_projected.Test(sel.GetIndex()))\n          {\n            auto n = getNormal(sel);\n            for (auto i : Range(sel.PNums()))\n              {\n                auto pi = sel.PNums()[i];\n                if (growthvectors[pi].Length2() == 0.)\n                  continue;\n                auto next = sel.PNums()[(i + 1) % sel.GetNV()];\n                auto prev = sel.PNums()[i == 0 ? sel.GetNV() - 1 : i - 1];\n                auto v1 = (mesh[next] - mesh[pi]).Normalize();\n                auto v2 = (mesh[prev] - mesh[pi]).Normalize();\n                auto v3 = growthvectors[pi];\n                v3.Normalize();\n                auto tol = v1.Length() * 1e-12;\n                if ((v1 * v3 > -tol) && (v2 * v3 > -tol))\n                  in_surface_direction.SetBit(sel.GetIndex());\n                else\n                  continue;\n\n                if (!par_project_boundaries.Contains(sel.GetIndex()))\n                  continue;\n                auto& g = growthvectors[pi];\n                auto ng = n * g;\n                auto gg = g * g;\n                auto nn = n * n;\n                // if(fabs(ng*ng-nn*gg) < 1e-12 || fabs(ng) < 1e-12) continue;\n                auto a = -ng * ng / (ng * ng - nn * gg);\n                auto b = ng * gg / (ng * ng - nn * gg);\n                g += a * g + b * n;\n              }\n          }\n    }\n  else\n    {\n      for (const auto& seg : segments)\n        {\n          int count = 0;\n          for (const auto& seg2 : segments)\n            if (((seg[0] == seg2[0] && seg[1] == seg2[1]) || (seg[0] == seg2[1] && seg[1] == seg2[0])) && par_surfid.Contains(seg2.si))\n              count++;\n          if (count == 1)\n            {\n              growthvectors[seg[0]] = {0., 0., 0.};\n              growthvectors[seg[1]] = {0., 0., 0.};\n            }\n        }\n    }\n\n  return in_surface_direction;\n}\n\nvoid BoundaryLayerTool ::InsertNewElements (\n  FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap,\n  const BitArray& in_surface_direction)\n{\n  static Timer timer(\"BoundaryLayerTool::InsertNewElements\");\n  RegionTimer rt(timer);\n  mapto.SetSize(0);\n  mapto.SetSize(np);\n  mapfrom.SetSize(mesh.GetNP());\n  mapfrom = PointIndex::INVALID;\n\n  auto changed_domains = domains;\n  if (!params.outside)\n    changed_domains.Invert();\n\n  auto& identifications = mesh.GetIdentifications();\n  const int identnr = identifications.GetNr(\"boundarylayer\");\n\n  auto add_points = [&] (PointIndex pi, Vec<3>& growth_vector, Array<PointIndex>& new_points) {\n    Point<3> p = mesh[pi];\n    PointIndex pi_last = pi;\n    double height = 0.0;\n    for (auto i : Range(par_heights))\n      {\n        height += par_heights[i];\n        auto pi_new = mesh.AddPoint(p);\n        // mesh.AddLockedPoint(pi_new);\n        mapfrom.Append(pi);\n        new_points.Append(pi_new);\n        growth_vector_map[pi_new] = {&growth_vector, height};\n        // if (special_boundary_points.count(pi) > 0)\n        //   mesh.AddLockedPoint(pi_new);\n        pi_last = pi_new;\n      }\n  };\n\n  // insert new points\n  // for (PointIndex pi = 1; pi <= np; pi++)\n  for (PointIndex pi = IndexBASE<PointIndex>();\n       pi < IndexBASE<PointIndex>() + np;\n       pi++)\n    {\n      if (growthvectors[pi].Length2() != 0)\n        {\n          if (special_boundary_points.count(pi))\n            {\n              for (auto& group : special_boundary_points[pi].growth_groups)\n                add_points(pi, group.growth_vector, group.new_points);\n            }\n          else\n            add_points(pi, growthvectors[pi], mapto[pi]);\n        }\n    }\n\n  // get point from mapto (or the group if point is mapped to multiple new\n  // points) layer = -1 means last point (top of boundary layer)\n  auto newPoint = [&] (PointIndex pi, int layer = -1, int group = 0) {\n    if (layer == -1)\n      layer = par_heights.Size() - 1;\n    if (special_boundary_points.count(pi))\n      return special_boundary_points[pi].growth_groups[group].new_points[layer];\n    else\n      return mapto[pi][layer];\n  };\n\n  auto hasMoved = [&] (PointIndex pi) {\n    return mapto[pi].Size() > 0 || special_boundary_points.count(pi);\n  };\n\n  auto numGroups = [&] (PointIndex pi) -> size_t {\n    if (special_boundary_points.count(pi))\n      return special_boundary_points[pi].growth_groups.Size();\n    else\n      return 1;\n  };\n\n  auto getGroups = [&] (PointIndex pi, int face_index) -> Array<int> {\n    auto n = numGroups(pi);\n    Array<int> groups;\n    if (n == 1)\n      {\n        groups.Append(0);\n        return groups;\n      }\n    const auto& all_groups = special_boundary_points[pi].growth_groups;\n    for (auto i : Range(n))\n      if (all_groups[i].faces.Contains(face_index))\n        groups.Append(i);\n    // cout << \"groups \" << pi << \", \" << face_index << endl << groups;\n    return groups;\n  };\n\n  // add 2d quads on required surfaces\n  map<pair<PointIndex, PointIndex>, int> seg2edge;\n  map<int, int> edge_map;\n  int edge_nr = max_edge_nr;\n  auto getIndex = [&] (int ei) {\n    if (edge_map.count(ei) == 0)\n      edge_map[ei] = ++edge_nr;\n    return edge_map[ei];\n  };\n  if (params.grow_edges)\n    {\n      for (auto sei : moved_segs)\n        {\n          // copy here since we will add segments and this would\n          // invalidate a reference!\n          // auto segi = segments[sei];\n          for (auto [sej, type] : segmap[sei])\n            {\n              auto segj = segments[sej];\n              if (type == 0)\n                {\n                  auto addSegment = [&] (PointIndex p0, PointIndex p1, bool extra_edge_nr = false) {\n                    Segment s;\n                    s[0] = p0;\n                    s[1] = p1;\n                    s[2] = PointIndex::INVALID;\n                    [[maybe_unused]] auto pair =\n                      s[0] < s[1] ? make_pair(s[0], s[1]) : make_pair(s[1], s[0]);\n                    if (extra_edge_nr)\n                      s.index = ++edge_nr;\n                    else\n                      s.index = getIndex(segj.index);\n                    s.si = si_map[segj.si];\n                    new_segments.Append(s);\n                    // cout << __LINE__ <<\"\\t\" << s << endl;\n                    return s;\n                  };\n\n                  auto p0 = segj[0], p1 = segj[1];\n                  auto g0 = getGroups(p0, segj.si);\n                  auto g1 = getGroups(p1, segj.si);\n\n                  if (g0.Size() == 1 && g1.Size() == 1)\n                    {\n                      auto p0_new = newPoint(p0, -1, g0[0]);\n                      auto p1_new = newPoint(p1, -1, g1[0]);\n                      addSegment(p0_new, p1_new);\n                    }\n                  else\n                    {\n                      if (g0.Size() == 2)\n                        addSegment(newPoint(p0, -1, g0[0]), newPoint(p0, -1, g0[1]));\n                      if (g1.Size() == 2)\n                        addSegment(newPoint(p1, -1, g1[0]), newPoint(p1, -1, g1[1]));\n                    }\n                }\n              // here we need to grow the quad elements\n              else if (type == 1)\n                {\n                  PointIndex pp1 = segj[1];\n                  PointIndex pp2 = segj[0];\n                  if (in_surface_direction.Test(segj.si))\n                    {\n                      Swap(pp1, pp2);\n                      is_boundary_moved.SetBit(segj.si);\n                    }\n                  PointIndex p1 = pp1;\n                  PointIndex p2 = pp2;\n                  PointIndex p3, p4;\n                  Segment s0;\n                  s0[0] = p1;\n                  s0[1] = p2;\n                  s0[2] = PointIndex::INVALID;\n                  s0.index = segj.index;\n                  s0.si = segj.si;\n                  new_segments.Append(s0);\n                  if (type == 3)\n                    new_segments_on_moved_bnd.Append(s0);\n\n                  for (auto i : Range(par_heights))\n                    {\n                      Element2d sel(QUAD);\n                      p3 = newPoint(pp2, i);\n                      p4 = newPoint(pp1, i);\n                      sel[0] = p1;\n                      sel[1] = p2;\n                      sel[2] = p3;\n                      sel[3] = p4;\n                      for (auto i : Range(4))\n                        {\n                          sel.GeomInfo()[i].u = 0.0;\n                          sel.GeomInfo()[i].v = 0.0;\n                        }\n                      identifications.Add(p1, p4, identnr);\n                      identifications.Add(p2, p3, identnr);\n                      sel.SetIndex(si_map[segj.si]);\n                      new_sels.Append(sel);\n                      new_sels_on_moved_bnd.Append(sel);\n\n                      // TODO: Too many, would be enough to only add outermost ones\n                      Segment s1;\n                      s1[0] = p2;\n                      s1[1] = p3;\n                      s1[2] = PointIndex::INVALID;\n                      auto pair = make_pair(p2, p3);\n                      s1.index = getIndex(segj.index);\n                      s1.si = segj.si;\n                      // new_segments.Append(s1);\n                      Segment s2;\n                      s2[0] = p4;\n                      s2[1] = p1;\n                      s2[2] = PointIndex::INVALID;\n                      pair = make_pair(p1, p4);\n                      s2.index = getIndex(segj.index);\n                      s2.si = segj.si;\n                      // new_segments.Append(s2);\n                      p1 = p4;\n                      p2 = p3;\n                    }\n                  Segment s3;\n                  s3[0] = p3;\n                  s3[1] = p4;\n                  s3[2] = PointIndex::INVALID;\n                  // auto pair = p3 < p4 ? make_pair(p3, p4) : make_pair(p4, p3);\n                  s3.index = getIndex(segj.index);\n                  s3.si = segj.si;\n                  new_segments.Append(s3);\n                  if (type == 3)\n                    new_segments_on_moved_bnd.Append(s0);\n                }\n              else if (type == 3)\n                {\n                  PointIndex pp1 = segj[1];\n                  PointIndex pp2 = segj[0];\n                  if (!in_surface_direction.Test(segj.si))\n                    {\n                      Swap(pp1, pp2);\n                    }\n                  PointIndex p1 = pp1;\n                  PointIndex p2 = pp2;\n                  PointIndex p3, p4;\n\n                  for (auto i : Range(par_heights))\n                    {\n                      Element2d sel(QUAD);\n                      p3 = newPoint(pp2, i);\n                      p4 = newPoint(pp1, i);\n                      sel[0] = p1;\n                      sel[1] = p2;\n                      sel[2] = p3;\n                      sel[3] = p4;\n                      for (auto i : Range(4))\n                        {\n                          sel.GeomInfo()[i].u = 0.0;\n                          sel.GeomInfo()[i].v = 0.0;\n                        }\n                      identifications.Add(p1, p4, identnr);\n                      identifications.Add(p2, p3, identnr);\n                      sel.SetIndex(si_map[segj.si]);\n                      new_sels.Append(sel);\n                      new_sels_on_moved_bnd.Append(sel);\n                      p1 = p4;\n                      p2 = p3;\n                    }\n                }\n            }\n        }\n    }\n\n  auto getClosestGroup = [&] (PointIndex pi, SurfaceElementIndex sei) {\n    auto n = numGroups(pi);\n    if (n == 1)\n      return 0;\n    const auto& sel = mesh[sei];\n    auto groups = getGroups(pi, sel.GetIndex());\n    if (groups.Size() == 1)\n      return groups[0];\n\n    // auto& growth_groups = special_boundary_points[pi].growth_groups;\n\n    auto vdir = Center(mesh[sel[0]], mesh[sel[1]], mesh[sel[2]]) - mesh[pi];\n    auto dot = vdir * special_boundary_points[pi].separating_direction;\n\n    return dot > 0 ? 1 : 0;\n  };\n\n  BitArray fixed_points(np + 1);\n  fixed_points.Clear();\n  auto p2el = mesh.CreatePoint2ElementTable();\n  for (SurfaceElementIndex si = 0; si < nse; si++)\n    {\n      const auto sel = mesh[si];\n      const auto iface = sel.GetIndex();\n\n      if (moved_surfaces.Test(iface))\n        {\n          const auto np = sel.GetNP();\n          ArrayMem<PointIndex, 4> points(sel.PNums());\n          if (surfacefacs[iface] > 0)\n            Swap(points[0], points[2]);\n          ArrayMem<int, 4> groups(points.Size());\n          for (auto i : Range(points))\n            groups[i] = getClosestGroup(points[i], si);\n          bool add_volume_element = true;\n          for (auto pi : points)\n            if (numGroups(pi) > 1)\n              add_volume_element = false;\n\n          Element el(2 * np);\n          el.PNums().Range(np, 2 * np) = points;\n          auto new_index = new_mat_nrs[iface];\n          if (new_index == -1)\n            throw Exception(\"Boundary \" + ToString(iface) + \" with name \" + mesh.GetBCName(iface - 1) + \" extruded, but no new material specified for it!\");\n          el.SetIndex(new_index);\n\n          for (auto j : Range(par_heights))\n            {\n              el.PNums().Range(0, np) = el.PNums().Range(np, 2 * np);\n              for (auto i : Range(np))\n                el[np + i] = newPoint(points[i], j, groups[i]);\n              if (add_volume_element)\n                mesh.AddVolumeElement(el);\n              else\n                {\n                  // Let the volume mesher fill the hole with pyramids/tets\n                  // To insert pyramids, we need close surface identifications on open quads\n                  for (auto i : Range(np))\n                    if (numGroups(el[i]) == 1)\n                      {\n                        auto pi0 = el[i];\n                        auto pi1 = el[np + i];\n                        auto nr = identifications.Get(pi0, pi1);\n                        if (nr == 0)\n                          identifications.Add(pi0, pi1, identnr);\n                      }\n                }\n            }\n          Element2d newel = sel;\n          for (auto i : Range(np))\n            newel[i] = newPoint(points[i], -1, groups[i]);\n          if (surfacefacs[iface] > 0)\n            Swap(newel[0], newel[2]); // swap back\n          newel.SetIndex(si_map[iface]);\n          new_sels.Append(newel);\n        }\n      if (is_boundary_moved.Test(iface))\n        {\n          auto& sel = mesh[si];\n          for (auto& p : sel.PNums())\n            if (hasMoved(p))\n              p = newPoint(p);\n        }\n    }\n\n  for (SegmentIndex sei = 0; sei < nseg; sei++)\n    {\n      auto& seg = segments[sei];\n      if (is_boundary_moved.Test(seg.si))\n        {\n          // cout << \"moved setg \" << seg << endl;\n          for (auto& p : seg.PNums())\n            if (hasMoved(p))\n              {\n                p = newPoint(p);\n                if (params.disable_curving)\n                    seg.SetEdgeNr(-1);\n              }\n        }\n    }\n\n  // fill holes in surface mesh at special boundary points (i.e. points with >=4\n  // adjacent boundary faces)\n  auto p2sel = ngcore::CreateSortedTable<SurfaceElementIndex, PointIndex>(\n    new_sels.Range(),\n    [&] (auto& table, SurfaceElementIndex ei) {\n      for (PointIndex pi : new_sels[ei].PNums())\n        table.Add(pi, ei);\n    },\n    mesh.GetNP());\n\n  for (auto& [special_pi, special_point] : special_boundary_points)\n    {\n      if (special_point.growth_groups.Size() != 2)\n        throw Exception(\"special_point.growth_groups.Size() != 2\");\n\n      // Special points are split into two new points, when mapping a surface\n      // element, we choose the closer one to the center. Now, find points which\n      // are mapped to both new points (for different surface elements they belong\n      // to). At exactly these points we need to insert new surface elements to\n      // fill the hole.\n      std::map<int, std::array<std::set<PointIndex>, 2>> close_group;\n      for (auto sei : p2sel[special_pi])\n        {\n          const auto& sel = mesh[sei];\n          for (auto p : sel.PNums())\n            if (p != special_pi)\n              close_group[sel.GetIndex()][getClosestGroup(special_pi, sei)].insert(\n                p);\n        }\n\n      for (auto [fi, groups] : close_group)\n        {\n          const auto mapped_fi = si_map[fi];\n          std::set<PointIndex> common_points;\n          for (auto pi : groups[0])\n            if (groups[1].count(pi) == 1)\n              common_points.insert(pi);\n          if (common_points.size() > 0)\n            {\n              auto pi_common = mapto[*common_points.begin()].Last();\n              auto new_special_pi0 = special_point.growth_groups[0].new_points.Last();\n              auto new_special_pi1 = special_point.growth_groups[1].new_points.Last();\n              for (auto sei : p2sel[pi_common])\n                {\n                  if (mesh[sei].GetIndex() == mapped_fi && mesh[sei].PNums().Contains(new_special_pi0))\n                    {\n                      auto sel = mesh[sei];\n                      sel.Invert();\n                      for (auto& pi : sel.PNums())\n                        if (pi != pi_common && pi != new_special_pi0)\n                          pi = new_special_pi1;\n                      new_sels.Append(sel);\n                    }\n                }\n            }\n        }\n    }\n\n  for (auto& [pi, special_point] : special_boundary_points)\n    {\n      if (special_point.growth_groups.Size() != 2)\n        throw Exception(\"special_point.growth_groups.Size() != 2\");\n      for (auto igroup : Range(2))\n        {\n          auto& group = special_point.growth_groups[igroup];\n          std::set<int> faces;\n          for (auto face : group.faces)\n            faces.insert(si_map[face]);\n          auto pi_new = group.new_points.Last();\n          auto pi_new_other =\n            special_point.growth_groups[1 - igroup].new_points.Last();\n          for (auto sei : p2sel[pi_new])\n            faces.erase(mesh[sei].GetIndex());\n          for (auto face : faces)\n            for (auto seg : new_segments)\n              {\n                if ( // seg.si == face\n                  (seg[0] == pi_new || seg[1] == pi_new) && (seg[0] != pi_new_other && seg[1] != pi_new_other))\n                  {\n                    bool is_correct_face = false;\n                    auto pi_other = seg[0] == pi_new ? seg[1] : seg[0];\n                    for (auto sei : p2sel[pi_other])\n                      {\n                        if (mesh[sei].GetIndex() == face)\n                          {\n                            is_correct_face = true;\n                            break;\n                          }\n                      }\n                    if (is_correct_face)\n                      {\n                        Element2d sel;\n                        sel[0] = seg[1];\n                        sel[1] = seg[0];\n                        sel[2] = pi_new_other;\n                        sel.SetIndex(face);\n                        new_sels.Append(sel);\n                      }\n                  }\n              }\n        }\n    }\n}\n\nvoid BoundaryLayerTool ::SetDomInOut ()\n{\n  if (insert_only_volume_elements)\n    return;\n  for (auto i : Range(1, nfd_old + 1))\n    if (moved_surfaces.Test(i))\n      {\n        if (auto dom = mesh.GetFaceDescriptor(si_map[i]).DomainIn();\n            dom > ndom_old)\n          mesh.GetFaceDescriptor(i).SetDomainOut(dom);\n        else\n          mesh.GetFaceDescriptor(i).SetDomainIn(\n            mesh.GetFaceDescriptor(si_map[i]).DomainOut());\n      }\n}\n\nvoid BoundaryLayerTool ::SetDomInOutSides ()\n{\n  // Set the domin/domout entries for face descriptors on the \"side\" of new boundary layers\n  if (insert_only_volume_elements)\n    return;\n  BitArray done(mesh.GetNFD() + 1);\n  done.Clear();\n\n  std::map<int, int> inv_si_map;\n\n  for (auto i : Range(si_map.Size()))\n    inv_si_map[si_map[i]] = i;\n\n  for (auto sei : Range(mesh.SurfaceElements()))\n    {\n      auto& sel = mesh[sei];\n      auto index = sel.GetIndex();\n      if (done.Test(index))\n        continue;\n      done.SetBit(index);\n      if (index < nfd_old && moved_surfaces.Test(index))\n        continue;\n      auto& fd = mesh.GetFaceDescriptor(index);\n      if (fd.DomainIn() != -1)\n        continue;\n\n      // First check if there are adjacent volume elements, if so, use their domains\n      int e1 = 0, e2 = 0;\n      mesh.GetTopology().GetSurface2VolumeElement(sei + 1, e1, e2);\n\n      int dom[2] = {-1, -1};\n\n      if (e1)\n        dom[0] = mesh.VolumeElement(e1).GetIndex();\n      if (e2)\n        dom[1] = mesh.VolumeElement(e2).GetIndex();\n\n      const auto& fd_old = mesh.GetFaceDescriptor(inv_si_map[index]);\n      int dom_old[2] = {fd_old.DomainIn(), fd_old.DomainOut()};\n\n      for (auto i : Range(2))\n        {\n          if (dom[i] != -1)\n            continue; // adjacent volume element -> done\n          if (dom_old[i] == 0)\n            {\n              // outer boundary -> keep 0\n              dom[i] = 0;\n              continue;\n            }\n\n          // Check if the old domain adjacent to this face gets a new boundary layer domain, if so, use that number\n          int dom_new = dom_old[i];\n          if (domains.Test(dom_old[i]) && new_mat_nrs[dom_old[i]] > 0)\n            dom_new = new_mat_nrs[dom_old[i]];\n\n          // This case is tested by test_boundarylayer.py::test_pyramids[False] -> look at the generated mesh to understand the text below :)\n          // Special case check here: when growing \"outside\" the new face could have the same domain on both sides (before adding blayer elements).\n          // Thus we don't know in advance on which side the mapped domain will be. So check, if the other domain has already prisms (adjacent vol elements) with mapped domain. If so, use the original domain instead.\n          if (dom[1 - i] != dom_new)\n            {\n              dom[i] = dom_new;\n            }\n          else\n            {\n              dom[i] = dom_old[i];\n            }\n        }\n\n      fd.SetDomainIn(dom[0]);\n      fd.SetDomainOut(dom[1]);\n    }\n}\n\nvoid BoundaryLayerTool ::AddSegments ()\n{\n  if (insert_only_volume_elements)\n    {\n      if (params.disable_curving)\n        {\n          auto is_mapped = [&] (PointIndex pi) {\n            return pi >= mapto.Range().Next() || mapto[pi].Size() > 0;\n          };\n          for (auto& seg : old_segments)\n            if (is_mapped(seg[0]) || is_mapped(seg[1]))\n                seg.SetEdgeNr(-1);\n        }\n    }\n\n  auto& new_segs =\n    insert_only_volume_elements ? new_segments_on_moved_bnd : new_segments;\n\n  if (params.disable_curving)\n    {\n      auto is_mapped = [&] (PointIndex pi) {\n        return pi >= mapto.Range().Next() || mapto[pi].Size() > 0;\n      };\n      for (auto& seg : segments)\n        if (is_mapped(seg[0]) || is_mapped(seg[1]))\n            seg.SetEdgeNr(-1);\n\n      for (auto& seg : segments)\n        if (is_edge_moved[seg.index])\n            seg.SetEdgeNr(-1);\n\n      for (auto& seg : new_segs)\n          seg.SetEdgeNr(-1);\n    }\n\n  if (have_single_segments)\n    MergeAndAddSegments(mesh, segments, new_segs);\n  else\n    {\n      mesh.LineSegments() = segments;\n      for (auto& seg : new_segs)\n        mesh.AddSegment(seg);\n    }\n\n  for (auto& seg : free_segments)\n    mesh.AddSegment(seg);\n}\n\nvoid BoundaryLayerTool ::AddSurfaceElements ()\n{\n  for (auto& sel :\n       insert_only_volume_elements ? new_sels_on_moved_bnd : new_sels)\n    mesh.AddSurfaceElement(sel);\n}\n\nvoid BoundaryLayerTool ::ProcessParameters ()\n{\n  if (int* bc = get_if<int>(&params.boundary); bc)\n    {\n      for (int i = 1; i <= mesh.GetNFD(); i++)\n        if (mesh.GetFaceDescriptor(i).BCProperty() == *bc)\n          par_surfid.Append(i);\n    }\n  else if (string* s = get_if<string>(&params.boundary); s)\n    {\n      regex pattern(*s);\n      BitArray boundaries(mesh.GetNFD() + 1);\n      boundaries.Clear();\n      for (int i = 1; i <= mesh.GetNFD(); i++)\n        {\n          auto& fd = mesh.GetFaceDescriptor(i);\n          if (regex_match(fd.GetBCName(), pattern))\n            {\n              boundaries.SetBit(i);\n              auto dom_pattern = get_if<string>(&params.domain);\n              // only add if adjacent to domain\n              if (dom_pattern)\n                {\n                  regex pattern(*dom_pattern);\n                  bool mat1_match =\n                    fd.DomainIn() > 0 && regex_match(mesh.GetMaterial(fd.DomainIn()), pattern);\n                  bool mat2_match =\n                    fd.DomainOut() > 0 && regex_match(mesh.GetMaterial(fd.DomainOut()), pattern);\n                  // if boundary is inner or outer remove from list\n                  if (mat1_match == mat2_match)\n                    boundaries.Clear(i);\n                  // if((fd.DomainIn() > 0 &&\n                  // regex_match(mesh.GetMaterial(fd.DomainIn()), pattern)) ||\n                  // (fd.DomainOut() > 0 &&\n                  // regex_match(self.GetMaterial(fd.DomainOut()), pattern)))\n                  // boundaries.Clear(i);\n                  // par_surfid.Append(i);\n                }\n              // else\n              //   par_surfid.Append(i);\n            }\n        }\n      for (int i = 1; i <= mesh.GetNFD(); i++)\n        if (boundaries.Test(i))\n          par_surfid.Append(i);\n    }\n  else\n    {\n      auto& surfids = *get_if<std::vector<int>>(&params.boundary);\n      for (auto id : surfids)\n        par_surfid.Append(id);\n    }\n\n  insert_only_volume_elements = !params.new_material.has_value();\n  if (params.new_material)\n    {\n      if (string* mat = get_if<string>(&*params.new_material); mat)\n        par_new_mat = {{\".*\", *mat}};\n      else\n        {\n          par_new_mat = *get_if<map<string, string>>(&*params.new_material);\n          have_material_map = true;\n        }\n    }\n\n  if (params.project_boundaries.has_value())\n    {\n      auto proj_bnd = *params.project_boundaries;\n      if (string* s = get_if<string>(&proj_bnd); s)\n        {\n          regex pattern(*s);\n          for (int i = 1; i <= mesh.GetNFD(); i++)\n            if (regex_match(mesh.GetFaceDescriptor(i).GetBCName(), pattern))\n              par_project_boundaries.Append(i);\n        }\n      else\n        {\n          for (auto id : *get_if<std::vector<int>>(&proj_bnd))\n            par_project_boundaries.Append(id);\n        }\n    }\n\n  if (double* height = get_if<double>(&params.thickness); height)\n    {\n      par_heights.Append(*height);\n    }\n  else\n    {\n      auto& heights = *get_if<std::vector<double>>(&params.thickness);\n      for (auto val : heights)\n        par_heights.Append(val);\n    }\n\n  int nr_domains = mesh.GetNDomains();\n  domains.SetSize(nr_domains + 1); // one based\n  domains.Clear();\n  if (string* pdomain = get_if<string>(&params.domain); pdomain)\n    {\n      regex pattern(*pdomain);\n      for (auto i : Range(1, nr_domains + 1))\n        if (regex_match(mesh.GetMaterial(i), pattern))\n          domains.SetBit(i);\n    }\n  else if (int* idomain = get_if<int>(&params.domain); idomain)\n    {\n      domains.SetBit(*idomain);\n    }\n  else\n    {\n      for (auto i : *get_if<std::vector<int>>(&params.domain))\n        domains.SetBit(i);\n    }\n  if (domains.NumSet() == 0)\n    return;\n  total_height = 0.0;\n  for (auto h : par_heights)\n    total_height += h;\n\n  max_edge_nr = -1;\n  for (const auto& seg : mesh.LineSegments())\n    if (seg.index > max_edge_nr)\n      max_edge_nr = seg.index;\n\n  int ndom = mesh.GetNDomains();\n  ndom_old = ndom;\n\n  new_mat_nrs.SetSize(mesh.FaceDescriptors().Size() + 1);\n  new_mat_nrs = -1;\n  if (insert_only_volume_elements)\n    {\n      for (auto i : Range(1, mesh.GetNFD() + 1))\n        {\n          auto& fd = mesh.GetFaceDescriptor(i);\n          auto domin = fd.DomainIn();\n          auto domout = fd.DomainOut();\n          for (int dom : {domin, domout})\n            if (domains.Test(dom))\n              {\n                if (params.outside)\n                  {\n                    dom = domin + domout - dom;\n                    if (dom == 0)\n                      throw NG_EXCEPTION(\"No new material specified for boundarylayer \"\n                                         \"on the outside of domain\");\n                  }\n                new_mat_nrs[i] = dom;\n              }\n        }\n    }\n  else\n    {\n      for (auto [bcname, matname] : par_new_mat)\n        {\n          mesh.SetMaterial(++ndom, matname);\n          regex pattern(bcname);\n          for (auto i : Range(1, mesh.GetNFD() + 1))\n            {\n              auto& fd = mesh.GetFaceDescriptor(i);\n              if (regex_match(fd.GetBCName(), pattern))\n                new_mat_nrs[i] = ndom;\n            }\n        }\n    }\n\n  if (!params.outside)\n    domains.Invert();\n}\n\nvoid BoundaryLayerTool ::Perform ()\n{\n  if (domains.NumSet() == 0)\n    return;\n  CreateNewFaceDescriptors();\n  CalculateGrowthVectors();\n  CreateFaceDescriptorsSides();\n  auto segmap = BuildSegMap();\n\n  auto in_surface_direction = ProjectGrowthVectorsOnSurface();\n\n  InsertNewElements(segmap, in_surface_direction);\n\n  SetDomInOut();\n  AddSegments();\n\n  mesh.CalcSurfacesOfNode();\n  topo.SetBuildVertex2Element(true);\n  mesh.UpdateTopology();\n\n  InterpolateGrowthVectors();\n  InterpolateSurfaceGrowthVectors();\n\n  AddSurfaceElements();\n\n  if (params.limit_growth_vectors)\n    LimitGrowthVectorLengths();\n\n  FixSurfaceElements();\n\n  for (auto [pi, data] : growth_vector_map)\n    {\n      auto [gw, height] = data;\n      mesh[pi] += height * (*gw);\n    }\n\n  auto& identifications = mesh.GetIdentifications();\n  NgArray<INDEX_2> pairs;\n  for (auto nr : Range(0, identifications.GetMaxNr() + 1))\n    {\n      identifications.GetPairs(nr, pairs);\n      for (auto pair : pairs)\n        {\n          auto p0 = pair[0];\n          auto p1 = pair[1];\n          if (max(p0, p1) < first_new_pi && mapto[p0].Size() && mapto[p1].Size())\n            for (auto i : Range(mapto[p0].Size()))\n              identifications.Add(mapto[p0][i], mapto[p1][i], nr);\n        }\n    }\n\n  // there is still a bug with segment edge numbers in moved boundaries.\n  // As a workaround, don't add them at all if only volume elements are inserted\n  if (insert_only_volume_elements)\n    mesh.LineSegments() = old_segments;\n\n  mesh.CalcSurfacesOfNode();\n  mesh.GetTopology().ClearEdges();\n  mesh.SetNextMajorTimeStamp();\n  mesh.UpdateTopology();\n  SetDomInOutSides();\n\n  if (have_material_map)\n    {\n      AddFacesBetweenDomains(mesh);\n      mesh.SplitFacesByAdjacentDomains();\n    }\n}\n\nvoid GenerateBoundaryLayer (Mesh& mesh, const BoundaryLayerParameters& blp)\n{\n  static Timer timer(\"Create Boundarylayers\");\n  RegionTimer regt(timer);\n\n  BoundaryLayerTool tool(mesh, blp);\n  tool.Perform();\n}\n\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/boundarylayer.hpp",
    "content": "#ifndef NETGEN_BOUNDARYLAYER_HPP\n#define NETGEN_BOUNDARYLAYER_HPP\n\n#include <core/array.hpp>\n#include <mystdlib.h>\n#include <meshing.hpp>\n\nnamespace netgen\n{\n\n///\nDLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh& mesh);\n\n/// Create a typical prismatic boundary layer on the given\n/// surfaces\n\nstruct SpecialBoundaryPoint\n{\n  struct GrowthGroup\n  {\n    Array<int> faces;\n    Vec<3> growth_vector;\n    Array<PointIndex> new_points;\n\n    GrowthGroup (FlatArray<int> faces_, FlatArray<Vec<3>> normals);\n    GrowthGroup (const GrowthGroup&) = default;\n    GrowthGroup () = default;\n  };\n  Array<GrowthGroup> growth_groups;\n  Vec<3> separating_direction;\n\n  SpecialBoundaryPoint (const std::map<int, Vec<3>>& normals);\n  SpecialBoundaryPoint () = default;\n};\n\nDLL_HEADER void GenerateBoundaryLayer (Mesh& mesh,\n                                       const BoundaryLayerParameters& blp);\n\nDLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh& mesh, int domain, const Array<double>& thicknesses, bool should_make_new_domain = true, const Array<int>& boundaries = Array<int>{});\n\nclass BoundaryLayerTool\n{\npublic:\n  BoundaryLayerTool (Mesh& mesh_, const BoundaryLayerParameters& params_);\n  void ProcessParameters ();\n  void Perform ();\n\n  Mesh& mesh;\n  MeshTopology& topo;\n  BoundaryLayerParameters params;\n  Array<Vec<3>, PointIndex> growthvectors;\n  std::map<PointIndex, Vec<3>> non_bl_growth_vectors;\n  Table<SurfaceElementIndex, PointIndex> p2sel;\n\n  BitArray domains, is_edge_moved, is_boundary_projected, is_boundary_moved;\n  Array<SegmentIndex> moved_segs;\n  int max_edge_nr, nfd_old, ndom_old;\n  Array<int> new_mat_nrs;\n  BitArray moved_surfaces;\n  int np, nseg, nse, ne;\n  PointIndex first_new_pi;\n  double total_height;\n  Array<POINTTYPE, PointIndex> point_types;\n\n  // These parameters are derived from given BoundaryLayerParameters and the Mesh\n  Array<double> par_heights;\n  Array<int> par_surfid;\n  bool insert_only_volume_elements;\n  map<string, string> par_new_mat;\n  bool have_material_map = false;\n  Array<size_t> par_project_boundaries;\n\n  bool have_single_segments;\n  Array<Segment> old_segments, free_segments, segments, new_segments, new_segments_on_moved_bnd;\n  Array<Element2d, SurfaceElementIndex> new_sels, new_sels_on_moved_bnd;\n  Array<Array<PointIndex>, PointIndex> mapto;\n  Array<PointIndex, PointIndex> mapfrom;\n\n  Array<double> surfacefacs;\n  Array<int> si_map;\n\n  std::map<PointIndex, SpecialBoundaryPoint> special_boundary_points;\n  std::map<PointIndex, std::tuple<Vec<3>*, double>> growth_vector_map;\n\n  // major steps called in Perform()\n  void CreateNewFaceDescriptors ();\n  void CreateFaceDescriptorsSides ();\n  void CalculateGrowthVectors ();\n  Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap ();\n\n  BitArray ProjectGrowthVectorsOnSurface ();\n  void InterpolateSurfaceGrowthVectors ();\n  void InterpolateGrowthVectors ();\n  void LimitGrowthVectorLengths ();\n  void FixSurfaceElements ();\n\n  void InsertNewElements (FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray& in_surface_direction);\n  void SetDomInOut ();\n  void SetDomInOutSides ();\n  void AddSegments ();\n  void AddSurfaceElements ();\n\n  Vec<3> getNormal (const Element2d& el)\n  {\n    auto v0 = mesh[el[0]];\n    return Cross(mesh[el[1]] - v0, mesh[el[2]] - v0).Normalize();\n  }\n\n  Vec<3> getEdgeTangent (PointIndex pi, int edgenr, FlatArray<Segment*> segs);\n};\n\n} // namespace netgen\n#endif // NETGEN_BOUNDARYLAYER_HPP\n"
  },
  {
    "path": "libsrc/meshing/boundarylayer2d.cpp",
    "content": "#include <mystdlib.h>\n#include \"boundarylayer.hpp\"\n#include \"meshing2.hpp\"\n#include \"../geom2d/csg2d.hpp\"\n\nnamespace netgen\n{\n   void InsertVirtualBoundaryLayer (Mesh & mesh)\n   {\n      cout << \"Insert virt. b.l.\" << endl;\n\n      int surfid;\n\n      cout << \"Boundary Nr:\";\n      cin >> surfid;\n\n      int i;\n      int np = mesh.GetNP();\n\n      cout << \"Old NP: \" << mesh.GetNP() << endl;\n      cout << \"Trigs: \" << mesh.GetNSE() << endl;\n\n      NgBitArray bndnodes(np);\n      NgArray<int> mapto(np);\n\n      bndnodes.Clear();\n      for (i = 1; i <= mesh.GetNSeg(); i++)\n      {\n         int snr = mesh.LineSegment(i).edgenr;\n         cout << \"snr = \" << snr << endl;\n         if (snr == surfid)\n         {\n            bndnodes.Set (mesh.LineSegment(i)[0]);\n            bndnodes.Set (mesh.LineSegment(i)[1]);\n         }\n      }\n      for (i = 1; i <= mesh.GetNSeg(); i++)\n      {\n         int snr = mesh.LineSegment(i).edgenr;\n         if (snr != surfid)\n         {\n            bndnodes.Clear (mesh.LineSegment(i)[0]);\n            bndnodes.Clear (mesh.LineSegment(i)[1]);\n         }\n      }\n\n      for (i = 1; i <= np; i++)\n        {\n          if (bndnodes.Test(i))\n            mapto.Elem(i) = mesh.AddPoint (mesh.Point (i));\n          else\n            mapto.Elem(i) = 0;\n        }\n\n      for (i = 1; i <= mesh.GetNSE(); i++)\n      {\n         Element2d & el = mesh.SurfaceElement(i);\n         for (int j = 1; j <= el.GetNP(); j++)\n            if (mapto.Get(el.PNum(j)))\n               el.PNum(j) = mapto.Get(el.PNum(j));\n      }\n\n\n      int nq = 0;\n      for (i = 1; i <= mesh.GetNSeg(); i++)\n      {\n         int snr = mesh.LineSegment(i).edgenr;\n         if (snr == surfid)\n         {\n            int p1 = mesh.LineSegment(i)[0];\n            int p2 = mesh.LineSegment(i)[1];\n            int p3 = mapto.Get (p1);\n            if (!p3) p3 = p1;\n            int p4 = mapto.Get (p2);\n            if (!p4) p4 = p2;\n\n            Element2d el(QUAD);\n            el.PNum(1) = p1;\n            el.PNum(2) = p2;\n            el.PNum(3) = p3;\n            el.PNum(4) = p4;\n            el.SetIndex (2);\n            mesh.AddSurfaceElement (el);\n            nq++;\n         }\n      }\n\n      cout << \"New NP: \" << mesh.GetNP() << endl;\n      cout << \"Quads: \" << nq << endl;\n   }\n\n\n  void AddDirection( Vec<3> & a, Vec<3> b )\n  {\n     if(a.Length2()==0.)\n     {\n        a = b;\n        return;\n     }\n\n     if(b.Length2()==0.)\n        return;\n\n     auto ab = a * b;\n     if(fabs(ab)>1-1e-8)\n        return;\n\n     Mat<2> m;\n     m(0,0) = a[0];\n     m(0,1) = a[1];\n     m(1,0) = b[0];\n     m(1,1) = b[1];\n     Vec<2> lam;\n     Vec<2> rhs;\n     rhs[0] = a[0]-b[0];\n     rhs[1] = a[1]-b[1];\n\n     const auto Dot = [](Vec<3> a, Vec<3> b)\n     { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; };\n\n     rhs[0] = Dot(a,a);\n     rhs[1] = Dot(b,b);\n\n     m.Solve(rhs, lam);\n     a[0] = lam[0];\n     a[1] = lam[1];\n     a[2] = 0.0;\n     return;\n  }\n\n  static void Generate2dMesh( Mesh & mesh, int domain )\n  {\n     Box<3> box{Box<3>::EMPTY_BOX};\n     for(const auto & seg : mesh.LineSegments())\n        if (seg.domin == domain || seg.domout == domain)\n           for (auto pi : {seg[0], seg[1]})\n              box.Add(mesh[pi]);\n\n     MeshingParameters mp;\n     Meshing2 meshing (*mesh.GetGeometry(), mp, box);\n\n     Array<PointIndex, PointIndex> compress(mesh.GetNP());\n     compress = PointIndex::INVALID;\n\n     PointIndex cnt = PointIndex::BASE;\n\n     auto p2sel = mesh.CreatePoint2SurfaceElementTable();\n     PointGeomInfo gi;\n     gi.u = 0.0;\n     gi.v = 0.0;\n     gi.trignum = domain;\n     for(auto seg : mesh.LineSegments())\n     {\n         if(seg.domin == domain || seg.domout == domain)\n         for (auto pi : {seg[0], seg[1]})\n            if (compress[pi]==PointIndex{PointIndex::INVALID})\n            {\n               meshing.AddPoint(mesh[pi], pi);\n               compress[pi] = cnt++;\n            }\n         if(seg.domin == domain)\n             meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]], gi, gi);\n         if(seg.domout == domain)\n             meshing.AddBoundaryElement (compress[seg[1]], compress[seg[0]], gi, gi);\n     }\n\n     auto oldnf = mesh.GetNSE();\n     // auto res =\n     meshing.GenerateMesh (mesh, mp, mp.maxh, domain);\n     for (SurfaceElementIndex sei : Range(oldnf, mesh.GetNSE()))\n        mesh[sei].SetIndex (domain);\n     \n     // int hsteps = mp.optsteps2d;\n\n     const char * optstr = mp.optimize2d.c_str();\n     MeshOptimize2d meshopt(mesh);\n     meshopt.SetFaceIndex(domain);\n     meshopt.SetMetricWeight (mp.elsizeweight);\n     for (size_t j = 1; j <= strlen(optstr); j++)\n     {\n        switch (optstr[j-1])\n        {\n           case 's':\n              {  // topological swap\n                 meshopt.EdgeSwapping (0);\n                 break;\n              }\n           case 'S':\n              {  // metric swap\n                 meshopt.EdgeSwapping (1);\n                 break;\n              }\n           case 'm':\n              {\n                 meshopt.ImproveMesh(mp);\n                 break;\n              }\n           case 'c':\n              {\n                 meshopt.CombineImprove();\n                 break;\n              }\n           default:\n              cerr << \"Optimization code \" << optstr[j-1] << \" not defined\" << endl;\n        }\n     }\n\n     mesh.Compress();\n     mesh.CalcSurfacesOfNode();\n     mesh.OrderElements();\n     mesh.SetNextMajorTimeStamp();\n  }\n\n  int GenerateBoundaryLayer2 (Mesh & mesh, int domain, const Array<double> & thicknesses, bool should_make_new_domain, const Array<int> & boundaries)\n  {\n     mesh.GetTopology().SetBuildVertex2Element(true);\n     mesh.UpdateTopology();\n     const auto & line_segments = mesh.LineSegments();\n     SegmentIndex first_new_seg = mesh.LineSegments().Range().Next();\n\n     int np = mesh.GetNP();\n     int nseg = line_segments.Size();\n     // int ne = mesh.GetNSE();\n     mesh.UpdateTopology();\n\n     double total_thickness = 0.0;\n     for(auto thickness : thicknesses)\n        total_thickness += thickness;\n\n     Array<Array<PointIndex>, PointIndex> mapto(np);\n\n     // Bit array to keep track of segments already processed\n     BitArray segs_done(nseg);\n     segs_done.Clear();\n\n     // moved segments\n     Array<SegmentIndex> moved_segs;\n\n     Array<Vec<3>, PointIndex> growthvectors(np);\n     growthvectors = 0.;\n\n     auto & meshtopo = mesh.GetTopology();\n\n     Array<SegmentIndex> segments;\n\n    // int fd_old = mesh.GetNFD();\n\n    int max_edge_nr = -1;\n    int max_domain = -1;\n\n    for(const auto& seg : line_segments)\n    {\n      if(seg.edgenr > max_edge_nr)\n        max_edge_nr = seg.edgenr;\n      if(seg.domin > max_domain)\n         max_domain = seg.domin;\n      if(seg.domout > max_domain)\n         max_domain = seg.domout;\n    }\n\n    int new_domain = max_domain+1;\n    int new_edge_nr = max_edge_nr+1;\n\n    BitArray active_boundaries(max_edge_nr+1);\n    BitArray active_segments(nseg);\n    active_boundaries.Clear();\n    active_segments.Clear();\n\n    if(boundaries.Size() == 0)\n       active_boundaries.Set();\n    else\n       for(auto edgenr : boundaries)\n          active_boundaries.SetBit(edgenr);\n\n    for(auto segi : Range(line_segments))\n    {\n       const auto seg = line_segments[segi];\n       if(active_boundaries.Test(seg.epgeominfo[0].edgenr) && (seg.domin==domain || seg.domout==domain))\n          active_segments.SetBit(segi);\n    }\n\n    {\n      FaceDescriptor new_fd(0, 0, 0, -1);\n        new_fd.SetBCProperty(new_domain);\n        // int new_fd_index =\n        mesh.AddFaceDescriptor(new_fd);\n        if(should_make_new_domain)\n          {\n           mesh.SetMaterial(new_domain, \"layer_\" + mesh.GetMaterial(domain));\n           mesh.SetBCName(new_edge_nr - 1, \"moved\");\n          }\n    }\n\n    for(auto segi : Range(line_segments))\n      {\n        if(segs_done[segi]) continue;\n        segs_done.SetBit(segi);\n        const auto& seg = line_segments[segi];\n        if(seg.domin != domain && seg.domout != domain) continue;\n        if(!active_boundaries.Test(seg.epgeominfo[0].edgenr))\n           continue;\n        moved_segs.Append(segi);\n      }\n\n     // calculate growth vectors (average normal vectors of adjacent segments at each point)\n     for (auto si : moved_segs)\n     {\n       auto & seg = line_segments[si];\n\n       auto n = mesh[seg[1]] - mesh[seg[0]];\n       n = {-n[1], n[0], 0};\n       n.Normalize();\n\n       if(seg.domout == domain)\n           n = -n;\n\n       AddDirection(growthvectors[seg[0]], n);\n       AddDirection(growthvectors[seg[1]], n);\n     }\n\n     //////////////////////////////////////////////////////////////////////////\n     // average growthvectors along straight lines to avoid overlaps in corners\n     BitArray points_done(np+1);\n     points_done.Clear();\n\n     for(auto si : moved_segs)\n     {\n        auto current_seg = line_segments[si];\n        auto current_si = si;\n\n        auto first = current_seg[0];\n        PointIndex current(PointIndex::INVALID);\n        auto next =  current_seg[1];\n\n        if(points_done.Test(first))\n           continue;\n\n        Array<PointIndex> chain;\n        chain.Append(first);\n\n        // first find closed loops of segments\n        while(next != current && next != first)\n        {\n           current = next;\n           points_done.SetBit(current);\n           chain.Append(current);\n           for(auto sj : meshtopo.GetVertexSegments( current ))\n           {\n              if(!active_segments.Test(sj))\n                 continue;\n\n              if(sj!=current_si)\n              {\n                 current_si = sj;\n                 current_seg = mesh[sj];\n\n                 next = current_seg[0]-current + current_seg[1];\n                 break;\n              }\n           }\n        }\n\n        auto ifirst = 0;\n        auto n = chain.Size();\n\n        // angle of adjacent segments at points a[i-1], a[i], a[i+1]\n        auto getAngle = [&mesh, &growthvectors] (FlatArray<PointIndex> a, size_t i)\n        {\n           auto n = a.Size();\n           auto v0 = growthvectors[a[(i+n-1)%n]];\n           auto v1 = growthvectors[a[i]];\n           auto v2 = growthvectors[a[(i+1)%n]];\n\n           auto p0 = mesh[a[(i+n-1)%n]];\n           auto p1 = mesh[a[i]];\n           auto p2 = mesh[a[(i+1)%n]];\n\n           v0 = p1-p0;\n           v1 = p2-p1;\n\n           auto angle = abs(atan2(v1[0], v1[1]) - atan2(v0[0], v0[1]));\n           if(angle>M_PI)\n              angle = 2*M_PI-angle;\n\n           return angle;\n        };\n\n        // find first corner point\n        while(getAngle(chain, ifirst) < 1e-5 )\n           ifirst = (ifirst+1)%n;\n\n        // Copy points of closed loop in correct order, starting with a corner\n        Array<PointIndex> pis(n+1);\n        pis.Range(0, n-ifirst) = chain.Range(ifirst, n);\n        pis.Range(n-ifirst, n) = chain.Range(0, n-ifirst);\n        pis[n] = pis[0];\n\n        Array<double> lengths(n);\n\n        for(auto i : Range(n))\n           lengths[i] = (mesh[pis[(i+1)%n]] - mesh[pis[i]]).Length();\n\n        auto averageGrowthVectors = [&] (size_t first, size_t last)\n        {\n           if(first+1 >= last)\n              return;\n\n           double total_len = 0.0;\n           for(auto l : lengths.Range(first, last))\n              total_len += l;\n\n           double len = lengths[first];\n           auto v0 = growthvectors[pis[first]];\n           auto v1 = growthvectors[pis[last]];\n\n           for(auto i : Range(first+1, last))\n           {\n              auto pi = pis[i];\n              growthvectors[pi] = (len/total_len)*v1 + (1.0-len/total_len)*v0;\n              len += lengths[i];\n           }\n        };\n\n        auto icurrent = 0;\n\n        while(icurrent<n)\n        {\n           auto ilast = icurrent+1;\n\n           while(getAngle(pis, ilast) < 1e-5 && ilast < n)\n              ilast++;\n\n           // found straight line -> average growth vectors between end points\n           if(icurrent!=ilast)\n              averageGrowthVectors(icurrent, ilast);\n\n           icurrent = ilast;\n        }\n     }\n\n     //////////////////////////////////////////////////////////////////////\n     // reduce growthvectors where necessary to avoid overlaps/slim regions\n     const auto getSegmentBox = [&] (SegmentIndex segi)\n     {\n        PointIndex pi0=mesh[segi][0], pi1=mesh[segi][1];\n        Box<3> box( mesh[pi0], mesh[pi1] );\n        box.Add( mesh[pi0]+growthvectors[pi0] );\n        box.Add( mesh[pi1]+growthvectors[pi1] );\n        return box;\n     };\n\n     Array<double, PointIndex> growth(np);\n     growth = 1.0;\n\n     const auto Dot = [](auto a, auto b)\n     { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; };\n\n     const auto restrictGrowthVectors = [&] (SegmentIndex segi0, SegmentIndex segi1)\n     {\n        if(!active_segments.Test(segi0))\n           return;\n\n        const auto & seg0 = mesh[segi0];\n        const auto & seg1 = mesh[segi1];\n\n        if( (seg0.domin != domain && seg0.domout != domain) ||\n            (seg1.domin != domain && seg1.domout != domain) )\n            return;\n\n        if(segi0 == segi1)\n           return;\n\n        if(seg0[0]==seg1[0] || seg0[0]==seg1[1] || seg0[1]==seg1[0] || seg0[1] == seg1[1])\n           return;\n\n        auto n = mesh[seg0[0]] - mesh[seg0[1]];\n        n = {-n[1], n[0], 0};\n        n.Normalize();\n        if(Dot(n, growthvectors[seg0[0]])<0) n = -n;\n        if(Dot(n, growthvectors[seg0[1]])<0) n = -n;\n\n        auto n1 = mesh[seg1[0]] - mesh[seg1[1]];\n        n1 = {-n1[1], n1[0], 0};\n        n1.Normalize();\n        if(Dot(n1, growthvectors[seg1[0]])<0) n1 = -n;\n        if(Dot(n1, growthvectors[seg1[1]])<0) n1 = -n;\n\n        auto p10 = mesh[seg1[0]];\n        auto p11 = mesh[seg1[1]];\n\n        for ( auto pi : {seg0[0], seg0[1]} )\n        {\n           if(growthvectors[pi].Length2() == 0.0)\n              continue;\n\n           PointIndex pi1 = seg0[0] - pi + seg0[1];\n           auto p1 = mesh[pi1];\n           auto p = mesh[pi];\n\n           Point<3> points[] = { p10, p11, p10+total_thickness*growthvectors[seg1[0]], p11+total_thickness*growthvectors[seg1[1]], p1+total_thickness*growthvectors[pi1] };\n\n           Vec<3> gn{ growthvectors[pi][1], -growthvectors[pi][0], 0.0 };\n           if(Dot(gn, p1-p) < 0)\n              gn = -gn;\n\n           double d0 = Dot(gn, p);\n           double d1 = Dot(gn, p1);\n           if(d0>d1)\n              Swap(d0,d1);\n\n           bool all_left=true, all_right=true;\n\n           for (auto i: Range(4))\n           {\n              auto p_other = points[i];\n              auto dot = Dot(gn,p_other);\n              if(dot>d0) all_left = false;\n              if(dot<d1) all_right = false;\n           }\n\n           if(all_left || all_right)\n              return;\n\n           //for ( auto pi : {seg0[0], seg0[1]} )\n           {\n              double safety = 1.3;\n              double t = safety*total_thickness;\n              if(growthvectors[pi].Length2() == 0.0)\n                 continue;\n\n              Point<3> points[] = { p10, p10+t*growthvectors[seg1[0]], p11, p11+t*growthvectors[seg1[1]] };\n              auto p0 = mesh[pi];\n              auto p1 = p0 + t*growthvectors[pi];\n              auto P2 = [](Point<3> p) { return Point<2>{p[0], p[1]}; };\n              ArrayMem<pair<double, double>, 4> intersections;\n\n              double alpha, beta;\n\n              auto checkIntersection = [] (Point<2> p0, Point<2> p1, Point<2> q0, Point<2> q1, double & alpha, double & beta) {\n                auto intersection_type = intersect( p0, p1, q0, q1, alpha, beta );\n                return intersection_type == X_INTERSECTION || intersection_type == T_INTERSECTION_P || intersection_type == T_INTERSECTION_Q;\n              };\n\n              if(checkIntersection( P2(p0), P2(p1), P2(points[0]), P2(points[2]), alpha, beta ))\n                 intersections.Append({alpha, 0.0});\n\n              if(checkIntersection( P2(p0), P2(p1), P2(points[1]), P2(points[3]), alpha, beta ))\n                 intersections.Append({alpha, 1.0});\n\n              if(checkIntersection( P2(p0), P2(p1), P2(points[0]), P2(points[1]), alpha, beta ))\n                 intersections.Append({alpha, beta});\n\n              if(checkIntersection( P2(p0), P2(p1), P2(points[2]), P2(points[3]), alpha, beta ))\n                 intersections.Append({alpha, beta});\n\n              QuickSort(intersections);\n              for(auto [alpha,beta] : intersections)\n              {\n                 if(!active_segments.Test(segi1))\n                    growth[pi] = min(growth[pi], alpha);\n                 else\n                 {\n                    double mean = 0.5*(alpha+beta);\n                    growth[pi] = min(growth[pi], mean);\n                    growth[seg1[0]] = min(growth[seg1[0]], mean);\n                    growth[seg1[1]] = min(growth[seg1[1]], mean);\n                 }\n              }\n           }\n        }\n     };\n\n     Box<3> box(Box<3>::EMPTY_BOX);\n     for (auto segi : Range(mesh.LineSegments()))\n     {\n        auto segbox = getSegmentBox( segi );\n        box.Add(segbox.PMin());\n        box.Add(segbox.PMax());\n     }\n     BoxTree<3> segtree(box);\n\n     for (auto segi : Range(mesh.LineSegments()))\n     {\n        auto p2 = [](Point<3> p) { return Point<2>{p[0], p[1]}; };\n\n        auto seg = line_segments[segi];\n        double alpha=0.0;\n        double beta=0.0;\n        if (intersect(p2(mesh[seg[0]]), p2(mesh[seg[0]] + total_thickness * growthvectors[seg[0]]), p2(mesh[seg[1]]), p2(mesh[seg[1]] + total_thickness * growthvectors[seg[1]]), alpha, beta))\n          {\n            if (beta > 0 && alpha > 0 && alpha < 1.1)\n              growth[seg[0]] = min(growth[seg[0]], 0.8 * alpha);\n            if (alpha > 0 && beta > 0 && beta < 1.1)\n              growth[seg[1]] = min(growth[seg[1]], 0.8 * beta);\n          }\n\n        for (auto segj : Range(mesh.LineSegments()))\n           if(segi!=segj)\n              restrictGrowthVectors(segi, segj);\n     }\n\n     for( auto pi : Range(growthvectors))\n        growthvectors[pi] *= growth[pi];\n\n\n     // insert new points\n     for(PointIndex pi : Range(mesh.Points()))\n        if(growthvectors[pi].Length2()!=0)\n        {\n\n           auto & pnew = mapto[pi];\n           auto dist = 0.0;\n           for(auto t : thicknesses)\n           {\n              dist+=t;\n              pnew.Append( mesh.AddPoint( mesh[pi] + dist*growthvectors[pi] ) );\n              mesh[pnew.Last()].SetType(FIXEDPOINT);\n           }\n        }\n\n     // insert new elements ( and move old ones )\n     for(auto si : moved_segs)\n     {\n        auto seg = line_segments[si];\n\n        bool swap = false;\n        auto & pm0 = mapto[seg[0]];\n        auto & pm1 = mapto[seg[1]];\n\n        Segment s = seg;\n        s.geominfo[0] = {};\n        s.geominfo[1] = {};\n        s[0] = pm0.Last();\n        s[1] = pm1.Last();\n        s[2] = PointIndex::INVALID;\n        // auto pair = s[0] < s[1] ? make_pair(s[0], s[1]) : make_pair(s[1], s[0]);\n        s.edgenr = new_edge_nr;\n        s.epgeominfo[0].edgenr = -1;\n        s.epgeominfo[1].edgenr = -1;\n        s.si = s.edgenr;\n        mesh.AddSegment(s);\n\n        for ( auto i : Range(thicknesses))\n        {\n           PointIndex pi0, pi1, pi2, pi3;\n\n           if(i==0)\n           {\n              pi0 = seg[0];\n              pi1 = seg[1];\n           }\n           else\n           {\n              pi0 = pm0[i-1];\n              pi1 = pm1[i-1];\n           }\n\n           pi2 = pm1[i];\n           pi3 = pm0[i];\n\n           if(i==0)\n           {\n              auto p0 = mesh[pi0];\n              auto p1 = mesh[pi1];\n              auto q0 = mesh[pi2];\n              // auto q1 = mesh[pi3];\n\n              Vec<2> n = {-p1[1]+p0[1], p1[0]-p0[0]};\n              Vec<2> v = { q0[0]-p0[0], q0[1]-p0[1]};\n              if(n[0]*v[0]+n[1]*v[1]<0)\n                 swap = true;\n           }\n\n           Element2d newel;\n           newel.SetType(QUAD);\n           newel[0] = pi0;\n           newel[1] = pi1;\n           newel[2] = pi2;\n           newel[3] = pi3;\n           newel.SetIndex(new_domain);\n           newel.GeomInfo() = PointGeomInfo{};\n\n            if(swap)\n            {\n               Swap(newel[0], newel[1]);\n               Swap(newel[2], newel[3]);\n            }\n\n           for(auto i : Range(4))\n           {\n               newel.GeomInfo()[i].u = 0.0;\n               newel.GeomInfo()[i].v = 0.0;\n           }\n           mesh.AddSurfaceElement(newel);\n\n        }\n        // segment now adjacent to new 2d-domain!\n        if(line_segments[si].domin == domain)\n            line_segments[si].domin = new_domain;\n        if(line_segments[si].domout == domain)\n            line_segments[si].domout = new_domain;\n     }\n\n     for(auto pi : Range(mapto))\n     {\n        if(mapto[pi].Size() == 0)\n           continue;\n        auto pnew = mapto[pi].Last();\n        for(auto old_sei : meshtopo.GetVertexSurfaceElements( pi ))\n        {\n           if(mesh[old_sei].GetIndex() == domain)\n           {\n              auto & old_el = mesh[old_sei];\n              for(auto i : IntRange(old_el.GetNP()))\n                 if(old_el[i]==pi)\n                    old_el[i] = pnew;\n           }\n        }\n     }\n\n     for(auto & sel : mesh.SurfaceElements())\n        if(sel.GetIndex() == domain)\n           sel.Delete();\n\n     mesh.Compress();\n     mesh.CalcSurfacesOfNode();\n\n     Generate2dMesh(mesh, domain);\n\n     // even without new domain, we need temporarily a new domain to mesh the remaining area, without confusing the meshes with quads -> add segments temporarily and reset domain number and segments afterwards\n     if(!should_make_new_domain)\n     {\n        // map new domain back to old one\n        for(auto & sel : mesh.SurfaceElements())\n           if(sel.GetIndex()==new_domain)\n              sel.SetIndex(domain);\n\n        // remove (temporary) inner segments\n        for(auto segi : Range(first_new_seg, mesh.LineSegments().Range().Next()))\n        {\n           mesh[segi][0].Invalidate();\n           mesh[segi][1].Invalidate();\n        }\n\n        for(auto segi : moved_segs)\n        {\n            if(mesh[segi].domin == new_domain)\n                mesh[segi].domin = domain;\n            if(mesh[segi].domout == new_domain)\n                mesh[segi].domout = domain;\n        }\n\n        mesh.Compress();\n        mesh.CalcSurfacesOfNode();\n     }\n\n     return new_domain;\n   }\n\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/boundarylayer_interpolate.cpp",
    "content": "#include \"boundarylayer.hpp\"\n\nnamespace netgen\n{\n\nnamespace detail\n{\nstruct Neighbor\n{\n  PointIndex pi;\n  SurfaceElementIndex sei;\n  double weight;\n};\n} // namespace detail\n\nArray<ArrayMem<detail::Neighbor, 20>>\nBuildNeighbors (FlatArray<PointIndex> points, const Mesh& mesh)\n{\n  auto p2sel = mesh.CreatePoint2SurfaceElementTable();\n\n  Array<ArrayMem<detail::Neighbor, 20>> neighbors(points.Size());\n\n  ArrayMem<double, 20> angles;\n  ArrayMem<double, 20> inv_dists;\n  for (auto i : points.Range())\n    {\n      auto& p_neighbors = neighbors[i];\n      auto pi = points[i];\n      angles.SetSize(0);\n      inv_dists.SetSize(0);\n      for (auto sei : p2sel[pi])\n        {\n          const auto& sel = mesh[sei];\n          for (auto pi1 : sel.PNums())\n            {\n              if (pi1 == pi)\n                continue;\n              auto pi2 = pi1;\n              for (auto pi_ : sel.PNums())\n                {\n                  if (pi_ != pi && pi_ != pi1)\n                    {\n                      pi2 = pi_;\n                      break;\n                    }\n                }\n              p_neighbors.Append({pi1, sei, 0.0});\n              inv_dists.Append(1.0 / (mesh[pi1] - mesh[pi]).Length());\n              auto dot = (mesh[pi1] - mesh[pi]).Normalize() * (mesh[pi2] - mesh[pi]).Normalize();\n              angles.Append(acos(dot));\n            }\n        }\n      double sum_inv_dist = 0.0;\n      for (auto inv_dist : inv_dists)\n        sum_inv_dist += inv_dist;\n      double sum_angle = 0.0;\n      for (auto angle : angles)\n        sum_angle += angle;\n\n      double sum_weight = 0.0;\n      for (auto i : Range(inv_dists))\n        {\n          p_neighbors[i].weight =\n            inv_dists[i] * angles[i] / sum_inv_dist / sum_angle;\n          sum_weight += p_neighbors[i].weight;\n        }\n      for (auto i : Range(inv_dists))\n        p_neighbors[i].weight /= sum_weight;\n    }\n  return neighbors;\n}\n\nvoid BoundaryLayerTool ::InterpolateGrowthVectors ()\n{\n  point_types.SetSize(mesh.GetNP());\n  for (auto p : mesh.Points().Range())\n    point_types[p] = mesh[p].Type();\n\n  int new_max_edge_nr = max_edge_nr;\n  for (const auto& seg : segments)\n    if (seg.edgenr > new_max_edge_nr)\n      new_max_edge_nr = seg.edgenr;\n  for (const auto& seg : new_segments)\n    if (seg.edgenr > new_max_edge_nr)\n      new_max_edge_nr = seg.edgenr;\n\n  auto getGW = [&] (PointIndex pi) -> Vec<3> {\n    if (growth_vector_map.count(pi) == 0)\n      growth_vector_map[pi] = {&growthvectors[pi], total_height};\n    auto [gw, height] = growth_vector_map[pi];\n    return height * (*gw);\n  };\n  auto addGW = [&] (PointIndex pi, Vec<3> vec) {\n    if (growth_vector_map.count(pi) == 0)\n      growth_vector_map[pi] = {&growthvectors[pi], total_height};\n    auto [gw, height] = growth_vector_map[pi];\n    *gw += 1.0 / height * vec;\n  };\n\n  // interpolate tangential component of growth vector along edge\n  if (max_edge_nr >= new_max_edge_nr)\n    return;\n\n  auto edgenr2seg = ngcore::CreateSortedTable<Segment*, int>(\n    Range(segments.Size() + new_segments.Size()),\n    [&] (auto& table, size_t segi) {\n      auto& seg = segi < segments.Size()\n                    ? segments[segi]\n                    : new_segments[segi - segments.Size()];\n      table.Add(seg.edgenr, &seg);\n    },\n    new_max_edge_nr + 1);\n  auto point2seg = ngcore::CreateSortedTable<Segment*, PointIndex>(\n    Range(segments.Size() + new_segments.Size()),\n    [&] (auto& table, size_t segi) {\n      auto& seg = segi < segments.Size()\n                    ? segments[segi]\n                    : new_segments[segi - segments.Size()];\n      table.Add(seg[0], &seg);\n      table.Add(seg[1], &seg);\n    },\n    mesh.GetNP());\n\n  for (auto edgenr : Range(1, new_max_edge_nr + 1))\n    {\n      // \"inner\" edges between two flat faces are not treated as edges for interpolation\n      bool no_angles = true;\n      ArrayMem<SurfaceElementIndex, 4> faces;\n\n      for (auto* p_seg : edgenr2seg[edgenr])\n        {\n          auto& seg = *p_seg;\n          faces.SetSize(0);\n          // if (seg[0] <= p2sel.Size())\n          if (seg[0] < IndexBASE<PointIndex>() + p2sel.Size())\n            {\n              for (auto sei : p2sel[seg[0]])\n                if (moved_surfaces.Test(mesh[sei].GetIndex()) && p2sel[seg[1]].Contains(sei))\n                  faces.Append(sei);\n            }\n\n          if (faces.Size() == 2 && mesh[faces[0]].GetIndex() != mesh[faces[1]].GetIndex())\n            {\n              auto n0 = getNormal(mesh[faces[0]]);\n              auto n1 = getNormal(mesh[faces[1]]);\n              if (n0 * n1 < 0.99)\n                no_angles = false;\n            }\n          else\n            {\n              no_angles = false;\n            }\n        }\n\n      if (no_angles && faces.Size() == 2 && have_material_map)\n        if (par_new_mat[mesh.GetBCName(mesh[faces[0]].GetIndex() - 1)] != par_new_mat[mesh.GetBCName(mesh[faces[1]].GetIndex() - 1)])\n          no_angles = false;\n\n      if (no_angles)\n        {\n          for (auto* p_seg : edgenr2seg[edgenr])\n            for (auto pi : p_seg->PNums())\n              {\n                if (pi >= first_new_pi)\n                  continue;\n                if (point_types[pi] == EDGEPOINT)\n                  point_types[pi] = SURFACEPOINT;\n                else if (point_types[pi] == FIXEDPOINT)\n                  {\n                    // Check at edge corners if all adjacent surface elements have roughly the same normal.\n                    // If so, also treat this point as surface point for growth vector interpolation\n                    Vec<3> n = 0.0;\n                    for (auto si : p2sel[pi])\n                      n += getNormal(mesh[si]);\n                    n.Normalize();\n                    bool is_corner = false;\n                    for (auto si : p2sel[pi])\n                      if (getNormal(mesh[si]) * n < 0.99)\n                        is_corner = true;\n                    if (!is_corner)\n                      point_types[pi] = SURFACEPOINT;\n                  }\n              }\n          continue;\n        }\n    }\n\n  for (auto edgenr : Range(max_edge_nr + 1, new_max_edge_nr + 1))\n    {\n      double edge_len = 0.;\n      bool any_grows = false;\n\n      auto is_end_point = [&] (PointIndex pi) {\n        auto segs = point2seg[pi];\n        if (segs.Size() == 1)\n          return true;\n        auto first_edgenr = (*segs[0]).edgenr;\n        for (auto* p_seg : segs)\n          if (p_seg->edgenr != first_edgenr)\n            return true;\n        return false;\n      };\n\n      Array<PointIndex> points;\n      for (auto* p_seg : edgenr2seg[edgenr])\n        {\n          auto& seg = *p_seg;\n\n          if (getGW(seg[0]).Length2() != 0 || getGW(seg[1]).Length2() != 0)\n            any_grows = true;\n\n          if (points.Size() == 0)\n            for (auto i : Range(2))\n              if (is_end_point(seg[i]))\n                {\n                  points.Append(seg[i]);\n                  points.Append(seg[1 - i]);\n                  edge_len += (mesh[seg[1]] - mesh[seg[0]]).Length();\n                  break;\n                }\n        }\n\n      if (!any_grows)\n        {\n          PrintMessage(1, \"BLayer: skip interpolating growth vectors at edge \", edgenr + 1);\n          continue;\n        }\n\n      if (!points.Size())\n        {\n          if (debugparam.debugoutput)\n            cerr << \"Could not find startpoint for edge \" << edgenr << endl;\n          continue;\n        }\n\n      std::set<PointIndex> points_set;\n      points_set.insert(points[0]);\n      points_set.insert(points[1]);\n\n      bool point_found = true;\n      while (point_found)\n        {\n          if (is_end_point(points.Last()))\n            break;\n          point_found = false;\n          for (auto* p_seg : point2seg[points.Last()])\n            {\n              const auto& seg = *p_seg;\n              if (seg.edgenr != edgenr)\n                continue;\n              auto plast = points.Last();\n              if (plast != seg[0] && plast != seg[1])\n                continue;\n              auto pnew = plast == seg[0] ? seg[1] : seg[0];\n              if (pnew == points[0] && points.Size() > 1)\n                {\n                }\n              if (points_set.count(pnew) > 0 && (pnew != points[0] || points.Size() == 2))\n                continue;\n              edge_len += (mesh[points.Last()] - mesh[pnew]).Length();\n              points.Append(pnew);\n              points_set.insert(pnew);\n              point_found = true;\n              break;\n            }\n        }\n      if (!point_found)\n        {\n          if (debugparam.debugoutput)\n            {\n              cerr << \"Could not find connected list of line segments for edge \"\n                   << edgenr << endl;\n              cerr << \"current points: \" << endl\n                   << points << endl;\n            }\n          continue;\n        }\n\n      if (getGW(points[0]).Length2() == 0 && getGW(points.Last()).Length2() == 0)\n        continue;\n\n      // tangential part of growth vectors\n      auto t1 = (mesh[points[1]] - mesh[points[0]]).Normalize();\n      auto gt1 = getGW(points[0]) * t1 * t1;\n      auto t2 =\n        (mesh[points.Last()] - mesh[points[points.Size() - 2]]).Normalize();\n      auto gt2 = getGW(points.Last()) * t2 * t2;\n\n      double len = 0.;\n      for (auto i : IntRange(1, points.Size() - 1))\n        {\n          auto pi = points[i];\n          len += (mesh[pi] - mesh[points[i - 1]]).Length();\n          auto t = getEdgeTangent(pi, edgenr, point2seg[pi]);\n          auto lam = len / edge_len;\n          auto interpol = (1 - lam) * (gt1 * t) * t + lam * (gt2 * t) * t;\n          addGW(pi, interpol);\n        }\n    }\n}\n\nvoid BoundaryLayerTool ::InterpolateSurfaceGrowthVectors ()\n{\n  static Timer tall(\"InterpolateSurfaceGrowthVectors\");\n  RegionTimer rtall(tall);\n  static Timer tsmooth(\"InterpolateSurfaceGrowthVectors-Smoothing\");\n  auto np_old = this->np;\n  [[maybe_unused]] auto np = mesh.GetNP();\n\n  auto hasMoved = [&] (PointIndex pi) {\n    return (pi - IndexBASE<PointIndex>() >= np_old) || mapto[pi].Size() > 0 || special_boundary_points.count(pi);\n  };\n\n  std::set<PointIndex> points_set;\n  for (const auto& sel : mesh.SurfaceElements())\n    {\n      for (auto pi : sel.PNums())\n        if (point_types[pi] == SURFACEPOINT && hasMoved(pi))\n          points_set.insert(pi);\n    }\n\n  Array<PointIndex> points;\n  for (auto pi : points_set)\n    points.Append(pi);\n  QuickSort(points);\n\n  // smooth tangential part of growth vectors from edges to surface elements\n  Array<Vec<3>, PointIndex> corrections(mesh.GetNP());\n  corrections = 0.0;\n  RegionTimer rtsmooth(tsmooth);\n  auto neighbors = BuildNeighbors(points, mesh);\n\n  Array<Vec<3>, SurfaceElementIndex> surf_normals(mesh.GetNSE());\n  for (auto sei : mesh.SurfaceElements().Range())\n    surf_normals[sei] = getNormal(mesh[sei]);\n\n  BitArray interpolate_tangent(mesh.GetNP() + 1);\n  interpolate_tangent = false;\n  for (auto pi : points)\n    {\n      for (auto sei : p2sel[pi])\n        if (is_boundary_moved[mesh[sei].GetIndex()])\n          interpolate_tangent.SetBit(pi);\n    }\n\n  constexpr int N_STEPS = 64;\n  for ([[maybe_unused]] auto i : Range(N_STEPS))\n    {\n      for (auto i : points.Range())\n        {\n          auto pi = points[i];\n          auto& p_neighbors = neighbors[i];\n\n          ArrayMem<Vec<3>, 20> g_vectors;\n          double max_len = 0.0;\n          double sum_len = 0.0;\n\n          // average only tangent component on new bl points, average whole growth\n          // vector otherwise\n          bool do_average_tangent = true;\n          for (const auto& s : p_neighbors)\n            {\n              auto gw_other = growthvectors[s.pi] + corrections[s.pi];\n              if (do_average_tangent)\n                {\n                  auto n = surf_normals[s.sei];\n                  gw_other = gw_other - (gw_other * n) * n;\n                }\n              auto v = gw_other;\n              auto len = v.Length2();\n              sum_len += len;\n              max_len = max(max_len, len);\n              g_vectors.Append(v);\n            }\n\n          if (max_len == 0.0)\n            continue;\n\n          double lambda = 0;\n          if (i > N_STEPS / 4.)\n            lambda = 2.0 * (i - N_STEPS / 4.) / (N_STEPS / 2.);\n          lambda = min(1.0, lambda);\n\n          auto& correction = corrections[pi];\n          correction = 0.0;\n          for (const auto i : p_neighbors.Range())\n            {\n              auto v = g_vectors[i];\n              double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;\n              correction += weight * v;\n            }\n\n          if (!do_average_tangent)\n            correction -= growthvectors[pi];\n        }\n    }\n\n  for (auto pi : points)\n    growthvectors[pi] += corrections[pi];\n}\n\nvoid BoundaryLayerTool ::FixSurfaceElements ()\n{\n  static Timer tall(\"FixSurfaceElements\");\n  RegionTimer rtall(tall);\n  [[maybe_unused]] auto np_old = this->np;\n  [[maybe_unused]] auto np = mesh.GetNP();\n\n  non_bl_growth_vectors.clear();\n\n  auto getGW = [&] (PointIndex pi) -> Vec<3> {\n    // return growthvectors[pi];\n    if (growth_vector_map.count(pi) == 0)\n      {\n        non_bl_growth_vectors[pi] = .0;\n        growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};\n      }\n    auto [gw, height] = growth_vector_map[pi];\n    return height * (*gw);\n  };\n\n  auto addGW = [&] (PointIndex pi, Vec<3> vec) {\n    if (growth_vector_map.count(pi) == 0)\n      {\n        non_bl_growth_vectors[pi] = .0;\n        growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};\n      }\n    auto [gw, height] = growth_vector_map[pi];\n    *gw += 1.0 / height * vec;\n  };\n\n  std::set<PointIndex> points_set;\n  // only smooth over old surface elements\n  for (SurfaceElementIndex sei : Range(nse))\n    {\n      const auto& sel = mesh[sei];\n      if (sel.GetNP() == 3 && is_boundary_moved[sel.GetIndex()])\n        for (auto pi : sel.PNums())\n          if (point_types[pi] == SURFACEPOINT)\n            points_set.insert(pi);\n    }\n\n  Array<PointIndex> points;\n  for (auto pi : points_set)\n    points.Append(pi);\n  QuickSort(points);\n\n  Array<Vec<3>, PointIndex> corrections(mesh.GetNP());\n  corrections = 0.0;\n\n  auto neighbors = BuildNeighbors(points, mesh);\n\n  constexpr int N_STEPS = 32;\n  for ([[maybe_unused]] auto i : Range(N_STEPS))\n    {\n      for (auto i : points.Range())\n        {\n          auto pi = points[i];\n          auto& p_neighbors = neighbors[i];\n\n          ArrayMem<Vec<3>, 20> g_vectors;\n          double max_len = 0.0;\n          double sum_len = 0.0;\n\n          for (const auto& s : p_neighbors)\n            {\n              auto v = getGW(s.pi) + corrections[s.pi];\n              auto len = v.Length2();\n              sum_len += len;\n              max_len = max(max_len, len);\n              g_vectors.Append(v);\n            }\n\n          if (max_len == 0.0)\n            continue;\n\n          double lambda = 0;\n          if (i > N_STEPS / 4.)\n            lambda = 2.0 * (i - N_STEPS / 4.) / (N_STEPS / 2.);\n          lambda = min(1.0, lambda);\n\n          auto& correction = corrections[pi];\n          correction = 0.0;\n          for (const auto i : p_neighbors.Range())\n            {\n              auto v = g_vectors[i];\n              double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;\n              correction += weight * v;\n            }\n        }\n    }\n\n  for (auto pi : points)\n    addGW(pi, corrections[pi]);\n}\n\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/boundarylayer_limiter.hpp",
    "content": "#include \"boundarylayer.hpp\"\n#include <core/array.hpp>\n\nnamespace netgen\n{\n\nstruct Intersection_\n{\n  bool is_intersecting = false;\n  double lam0 = -1, lam1 = -1;\n  Point<3> p;\n  double bary[3];\n  operator bool() const { return is_intersecting; }\n};\n\nstruct GrowthVectorLimiter\n{\n  typedef std::array<Point<3>, 2> Seg;\n  typedef std::array<Point<3>, 3> Trig;\n\n  BoundaryLayerTool& tool;\n  const BoundaryLayerParameters& params;\n  Mesh& mesh;\n  double height;\n  Array<double, PointIndex> limits;\n  FlatArray<Vec<3>, PointIndex> growthvectors;\n  BitArray changed_domains;\n  unique_ptr<BoxTree<3>> tree;\n  Array<PointIndex, PointIndex> map_from;\n  Table<SurfaceElementIndex, PointIndex> p2sel;\n\n  GrowthVectorLimiter (BoundaryLayerTool& tool_)\n    : tool(tool_), params(tool_.params), mesh(tool_.mesh), height(tool_.total_height), growthvectors(tool_.growthvectors), map_from(mesh.Points().Size())\n  {\n    changed_domains = tool.domains;\n    if (!params.outside)\n      changed_domains.Invert();\n\n    map_from = tool.mapfrom;\n    p2sel = ngcore::CreateSortedTable<SurfaceElementIndex, PointIndex>(\n      tool.new_sels.Range(),\n      [&] (auto& table, SurfaceElementIndex ei) {\n        for (PointIndex pi : tool.new_sels[ei].PNums())\n          table.Add(pi, ei);\n      },\n      mesh.GetNP());\n  }\n\n  auto SurfaceElementsRange () { return Range(tool.nse + tool.new_sels.Size()); }\n\n  void WriteErrorMesh (string name)\n  {\n    if (!debugparam.write_mesh_on_error)\n      return;\n    Mesh out_mesh;\n    out_mesh = mesh;\n    for (auto [pi, data] : tool.growth_vector_map)\n      {\n        auto [gw, height] = data;\n        out_mesh[pi] += limits[pi] * height * (*gw);\n      }\n    out_mesh.Save(name);\n  }\n\n  const auto& Get (SurfaceElementIndex sei)\n  {\n    if (sei < tool.nse)\n      return mesh[sei];\n    return tool.new_sels[sei - tool.nse];\n  }\n\n  std::pair<double, double> GetMinMaxLimit (SurfaceElementIndex sei)\n  {\n    const auto& sel = Get(sei);\n    double min_limit = GetLimit(sel[0]);\n    double max_limit = min_limit;\n    for (auto i : IntRange(1, sel.GetNP()))\n      {\n        auto limit = GetLimit(sel[i]);\n        min_limit = min(min_limit, limit);\n        max_limit = max(max_limit, limit);\n      }\n    return {min_limit, max_limit};\n  }\n\n  double GetLimit (PointIndex pi)\n  {\n    if (pi < tool.first_new_pi)\n      return limits[pi];\n    return limits[map_from[pi]];\n  }\n\n  bool SetLimit (PointIndex pi, double new_limit)\n  {\n    double& limit = (pi < tool.first_new_pi) ? limits[pi] : limits[map_from[pi]];\n    if (limit <= new_limit)\n      return false;\n    limit = new_limit;\n    return true;\n  }\n\n  bool ScaleLimit (PointIndex pi, double factor)\n  {\n    double& limit = (pi < tool.first_new_pi) ? limits[pi] : limits[map_from[pi]];\n    return SetLimit(pi, limit * factor);\n  }\n\n  Vec<3> GetVector (PointIndex pi_to, double shift = 1., bool apply_limit = false)\n  {\n    auto [gw, height] = tool.growth_vector_map[pi_to];\n    if (apply_limit)\n      shift *= GetLimit(pi_to);\n    return shift * height * (*gw);\n  }\n\n  Point<3> GetPoint (PointIndex pi_to, double shift = 1., bool apply_limit = false)\n  {\n    if (pi_to < tool.first_new_pi || tool.growth_vector_map.count(pi_to) == 0)\n      return mesh[pi_to];\n\n    return mesh[pi_to] + GetVector(pi_to, shift, apply_limit);\n  }\n\n  Point<3> GetMappedPoint (PointIndex pi_from, double shift = 1., bool apply_limit = false)\n  {\n    auto pi_to = tool.mapto[pi_from].Last();\n    return GetPoint(pi_to, shift, apply_limit);\n  }\n\n  Seg GetMappedSeg (PointIndex pi_from, double shift = 1.)\n  {\n    return {mesh[pi_from], GetMappedPoint(pi_from, shift)};\n  }\n\n  Seg GetSeg (PointIndex pi_to, double shift = 1., bool apply_limit = false)\n  {\n    return {GetPoint(pi_to, 0), GetPoint(pi_to, shift, apply_limit)};\n  }\n\n  Trig GetTrig (SurfaceElementIndex sei, double shift = 0.0, bool apply_limit = false)\n  {\n    auto sel = Get(sei);\n    Trig trig;\n    for (auto i : Range(3))\n      trig[i] = GetPoint(sel[i], shift, apply_limit);\n    return trig;\n  }\n\n  Trig GetMappedTrig (SurfaceElementIndex sei, double shift = 0.0)\n  {\n    auto sel = Get(sei);\n    Trig trig;\n    for (auto i : Range(3))\n      trig[i] = GetMappedPoint(sel[i], shift);\n    return trig;\n  }\n\n  Trig GetSideTrig (SurfaceElementIndex sei, int index, double shift = 0.0, bool grow_first_vertex = true)\n  {\n    auto trig = GetMappedTrig(sei, 0.0);\n    auto sel = Get(sei);\n    auto index1 = (index + 1) % 3;\n    if (!grow_first_vertex)\n      index1 = (index + 2) % 3;\n    trig[index] = GetMappedPoint(sel[index1], shift, true);\n    return trig;\n  }\n\n  array<Trig, 4> GetSideTrigs (SurfaceElementIndex sei, int i0, double shift = 0.0)\n  {\n    auto trig = GetMappedTrig(sei, 0.0);\n    array<Trig, 4> trigs{trig, trig, trig, trig};\n\n    auto sel = Get(sei);\n    auto i1 = (i0 + 1) % 3;\n    auto i2 = (i0 + 2) % 3;\n    auto p1 = GetMappedPoint(sel[i1], shift, true);\n    auto p2 = GetMappedPoint(sel[i2], shift, true);\n\n    // create four trigs to span the quad from i1,i2 and their shifted points\n    // i1, i2, shifted i1\n    trigs[0][i0] = p1;\n\n    // i1, i2, shifted i2\n    trigs[1][i0] = p2;\n\n    // i1, shifted i1, shifted i2\n    trigs[2][i0] = p1;\n    trigs[2][i2] = p2;\n\n    // i2, shifted i1, shifted i2\n    trigs[2][i0] = p2;\n    trigs[2][i1] = p1;\n\n    return trigs;\n  }\n\n  static constexpr double INTERSECTION_SAFETY = .9;\n  bool LimitGrowthVector (PointIndex pi_to, SurfaceElementIndex sei, double trig_shift, double seg_shift, bool check_prism_sides = false)\n  {\n    auto pi_from = map_from[pi_to];\n    if (!pi_from.IsValid())\n      return false;\n\n    for (auto pi : Get(sei).PNums())\n      {\n        if (pi == pi_from)\n          return false;\n        if (map_from[pi] == pi_from)\n          return false;\n      }\n\n    if (check_prism_sides || trig_shift > .0)\n      {\n        auto [trig_min_limit, trig_max_limit] = GetMinMaxLimit(sei);\n        if (GetLimit(pi_to) < trig_min_limit)\n          return false;\n\n        auto getTrigs = [&] (double scaling = 1.0) -> ArrayMem<Trig, 3> {\n          ArrayMem<Trig, 12> trigs;\n          if (check_prism_sides)\n            for (auto i : Range(3))\n              for (auto trig : GetSideTrigs(sei, i, scaling * trig_shift))\n                trigs.Append(trig);\n          else\n            trigs.Append(GetTrig(sei, scaling * trig_shift, true));\n          return trigs;\n        };\n\n        if (!check_prism_sides)\n          {\n            // If the growth vectors of all points are pointing in the same direction,\n            // an intersection means, we also have an intersection with a prism side face\n            // this is an extra check and handled later\n            auto seg = GetSeg(pi_to, 1.0, false);\n            auto gw = seg[1] - seg[0];\n\n            bool have_same_growth_direction = true;\n            for (auto pi : Get(sei).PNums())\n              {\n                auto p_seg = GetSeg(pi, 1.0, false);\n                auto p_gw = p_seg[1] - p_seg[0];\n                have_same_growth_direction &= (gw * p_gw) > 0;\n              }\n            if (have_same_growth_direction)\n              return false;\n          }\n\n        double scaling = 1.0;\n        while (true)\n          {\n            bool have_intersection = false;\n            auto seg = GetSeg(pi_to, scaling * seg_shift, true);\n            for (auto trig : getTrigs(scaling))\n              have_intersection |= isIntersectingTrig(seg, trig);\n            if (!have_intersection)\n              break;\n            scaling *= 0.9;\n          }\n        if (scaling == 1.0)\n          return false;\n\n        double new_limit = scaling * max(GetLimit(pi_to), trig_max_limit);\n        SetLimit(pi_to, new_limit);\n        for (auto pi : Get(sei).PNums())\n          SetLimit(pi, new_limit);\n        return true;\n      }\n    else\n      {\n        auto seg = GetSeg(pi_to, seg_shift, false);\n        auto trig = GetTrig(sei, 0.0);\n        auto intersection = isIntersectingTrig(seg, trig);\n        // checking with original surface elements -> allow only half the distance\n        auto new_seg_limit = 0.40 * intersection.lam0 * seg_shift;\n        if (intersection && new_seg_limit < GetLimit(pi_from))\n          return SetLimit(pi_from, new_seg_limit);\n        return false;\n      }\n  }\n\n  void EqualizeLimits (double factor = .5)\n  {\n    static Timer t(\"GrowthVectorLimiter::EqualizeLimits\");\n    PrintMessage(5, \"GrowthVectorLimiter - equalize limits\");\n    RegionTimer reg(t);\n    if (factor == 0.0)\n      return;\n    // for (PointIndex pi : IntRange(tool.np, mesh.GetNP()))\n    for (PointIndex pi : mesh.Points().Range().Modify(tool.np, 0))\n      {\n        // auto pi_from = map_from[pi];\n        std::set<PointIndex> pis;\n        for (auto sei : p2sel[pi])\n          for (auto pi_ : tool.new_sels[sei].PNums())\n            pis.insert(pi_);\n        ArrayMem<double, 20> limits;\n        for (auto pi1 : pis)\n          {\n            auto limit = GetLimit(pi1);\n            if (limit > 0.0)\n              limits.Append(GetLimit(pi1));\n          }\n\n        if (limits.Size() == 0)\n          continue;\n\n        double average = 0.0;\n        for (auto l : limits)\n          average += l;\n        average /= limits.Size();\n\n        SetLimit(pi, factor * average + (1.0 - factor) * GetLimit(pi));\n      }\n  }\n\n  void LimitSelfIntersection (double safety = 1.4)\n  {\n    static Timer t(\"GrowthVectorLimiter::LimitSelfIntersection\");\n    PrintMessage(5, \"GrowthVectorLimiter - self intersection\");\n    RegionTimer reg(t);\n    // check for self-intersection within new elements (prisms/hexes)\n    auto isIntersecting = [&] (SurfaceElementIndex sei, double shift) {\n      // checks if surface element is self intersecting when growing with factor\n      // shift\n\n      // ignore new surface elements, side trigs are only built\n      // from original surface elements\n      if (sei >= tool.nse)\n        return false;\n      const auto sel = Get(sei);\n      auto np = sel.GetNP();\n      for (auto i : Range(np))\n        {\n          if (sel[i] >= tool.first_new_pi)\n            return false;\n          if (tool.mapto[sel[i]].Size() == 0)\n            return false;\n        }\n      for (auto i : Range(np))\n        {\n          auto seg = GetMappedSeg(sel[i], shift * limits[sel[i]]);\n          for (auto fi : Range(np - 2))\n            {\n              for (auto side : {true, false})\n                {\n                  auto trig = GetSideTrig(sei, i + fi, 1.0, side);\n                  if (isIntersectingPlane(seg, trig))\n                    return true;\n                }\n            }\n        }\n      return false;\n    };\n\n    for (SurfaceElementIndex sei : mesh.SurfaceElements().Range())\n      {\n        auto sel = mesh[sei];\n        if (sei >= tool.nse)\n          continue;\n        if (!tool.moved_surfaces[sel.GetIndex()])\n          continue;\n        if (sel.GetNP() == 4)\n          continue;\n\n        // const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());\n        auto np = sel.GetNP();\n\n        double shift = 1.0;\n        const double step_factor = 0.9;\n        while (isIntersecting(sei, shift * safety))\n          {\n            shift *= step_factor;\n            double max_limit = 0;\n            for (auto i : Range(np))\n              max_limit = max(max_limit, limits[sel[i]]);\n            for (auto i : Range(np))\n              if (max_limit == limits[sel[i]])\n                ScaleLimit(sel[i], step_factor);\n            // if (max_limit < 0.01) break;\n          }\n      }\n  }\n\n  // checks if a segment is intersecting a plane, spanned by three points, lam\n  // will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])\n  Intersection_ isIntersectingPlane (const Seg& seg,\n                                     const Trig& trig)\n  {\n    auto t1 = trig[1] - trig[0];\n    auto t2 = trig[2] - trig[0];\n    auto n = Cross(t1, t2);\n    auto v0n = (seg[0] - trig[0]) * n;\n    auto v1n = (seg[1] - trig[0]) * n;\n\n    Intersection_ intersection;\n    intersection.lam0 = -v0n / (v1n - v0n);\n    intersection.p = seg[0] + intersection.lam0 * (seg[1] - seg[0]);\n    intersection.is_intersecting = (v0n * v1n < 0) && (intersection.lam0 > -1e-8) && (intersection.lam0 < 1 + 1e-8);\n\n    return intersection;\n  }\n\n  Intersection_ isIntersectingTrig (const Seg& seg, const Trig& trig)\n  {\n    auto intersection = isIntersectingPlane(seg, trig);\n    if (!intersection)\n      return intersection;\n\n    auto p = seg[0] + intersection.lam0 * (seg[1] - seg[0]) - trig[0];\n\n    Vec3d col1 = trig[1] - trig[0];\n    Vec3d col2 = trig[2] - trig[0];\n    Vec3d col3 = Cross(col1, col2);\n    Vec3d rhs = p;\n    Vec3d bary;\n    SolveLinearSystem(col1, col2, col3, rhs, bary);\n\n    intersection.lam1 = 0;\n    double eps = 1e-4;\n    if (bary.X() >= -eps && bary.Y() >= -eps && bary.X() + bary.Y() <= 1 + eps)\n      {\n        intersection.bary[0] = bary.X();\n        intersection.bary[1] = bary.Y();\n        intersection.bary[2] = 1.0 - bary.X() - bary.Y();\n      }\n    else\n      intersection.is_intersecting = false;\n    return intersection;\n  }\n\n  Intersection_ isIntersectingTrig (PointIndex pi_from, PointIndex pi_to, SurfaceElementIndex sei, double shift = 0.0)\n  {\n    // JS: where is that GetSeg function ?\n    return isIntersectingTrig(GetSeg(pi_from, pi_to), GetTrig(sei, shift));\n  }\n\n  void BuildSearchTree (double trig_shift)\n  {\n    static Timer t(\"BuildSearchTree\");\n    RegionTimer rt(t);\n    Box<3> bbox(Box<3>::EMPTY_BOX);\n    for (PointIndex pi : mesh.Points().Range())\n      {\n        bbox.Add(mesh[pi]);\n        bbox.Add(GetPoint(pi, 1.1));\n      }\n\n    tree = make_unique<BoxTree<3>>(bbox);\n\n    for (auto sei : SurfaceElementsRange())\n      {\n        const auto& sel = Get(sei);\n        // auto sel_index = sel.GetIndex();\n\n        Box<3> box(Box<3>::EMPTY_BOX);\n        for (auto pi : sel.PNums())\n          {\n            box.Add(GetPoint(pi, 0.));\n            box.Add(GetPoint(pi, trig_shift * GetLimit(pi)));\n          }\n        tree->Insert(box, sei);\n      }\n  }\n\n  template <typename TFunc>\n  void FindTreeIntersections (double trig_shift, double seg_shift, TFunc f, TBitArray<PointIndex>* relevant_points = nullptr)\n  {\n    static Timer t(\"GrowthVectorLimiter::FindTreeIntersections\");\n    RegionTimer rt(t);\n    BuildSearchTree(trig_shift);\n    auto np_new = mesh.Points().Size();\n    // int counter = 0;\n    for (auto i : IntRange(tool.np, np_new))\n      {\n        PointIndex pi_to = i + IndexBASE<PointIndex>();\n        PointIndex pi_from = map_from[pi_to];\n        if (!pi_from.IsValid())\n          throw Exception(\"Point not mapped\");\n\n        if (relevant_points && !relevant_points->Test(pi_to) && !relevant_points->Test(pi_from))\n          continue;\n\n        Box<3> box(Box<3>::EMPTY_BOX);\n        // auto seg = GetSeg(pi_to, seg_shift);\n\n        box.Add(GetPoint(pi_to, 0));\n        box.Add(GetPoint(pi_to, GetLimit(pi_from)));\n        tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&] (SurfaceElementIndex sei) {\n          const auto& sel = Get(sei);\n          if (sel.PNums().Contains(pi_from))\n            return false;\n          if (sel.PNums().Contains(pi_to))\n            return false;\n          // counter++;\n          f(pi_to, sei);\n          return false;\n        });\n      }\n  }\n\n  void FixIntersectingSurfaceTrigs ()\n  {\n    static Timer t(\"GrowthVectorLimiter::FixIntersectingSurfaceTrigs\");\n    RegionTimer reg(t);\n    // check if surface trigs are intersecting each other\n    bool changed = true;\n    std::set<PointIndex> special_points;\n\n    if (tool.insert_only_volume_elements)\n      for (auto [pi, special_point] : tool.special_boundary_points)\n        {\n          special_points.insert(pi);\n          for (auto& group : special_point.growth_groups)\n            special_points.insert(group.new_points.Last());\n        }\n\n    auto skip_trig = [&] (const Element2d& tri) {\n      if (!tool.insert_only_volume_elements)\n        return false;\n      for (auto pi : tri.PNums())\n        if (special_points.find(pi) != special_points.end())\n          return true;\n      return false;\n    };\n\n    while (changed)\n      {\n        changed = false;\n        Point3d pmin, pmax;\n        mesh.GetBox(pmin, pmax);\n        BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);\n\n        for (auto sei : SurfaceElementsRange())\n          {\n            const Element2d& tri = Get(sei);\n\n            if (skip_trig(tri))\n              continue;\n\n            Box<3> box(Box<3>::EMPTY_BOX);\n            for (PointIndex pi : tri.PNums())\n              box.Add(GetPoint(pi, 1.0, true));\n\n            box.Increase(1e-3 * box.Diam());\n            setree.Insert(box, sei);\n          }\n\n        for (auto sei : SurfaceElementsRange())\n          {\n            const Element2d& tri = Get(sei);\n\n            if (skip_trig(tri))\n              continue;\n\n            Box<3> box(Box<3>::EMPTY_BOX);\n            for (PointIndex pi : tri.PNums())\n              box.Add(GetPoint(pi, 1.0, true));\n\n            setree.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (size_t sej) {\n              const Element2d& tri2 = Get(sej);\n\n              if (mesh[tri[0]].GetLayer() != mesh[tri2[0]].GetLayer())\n                return false;\n\n              netgen::Point<3> tri1_points[3], tri2_points[3];\n              const netgen::Point<3>*trip1[3], *trip2[3];\n              for (int k = 0; k < 3; k++)\n                {\n                  trip1[k] = &tri1_points[k];\n                  trip2[k] = &tri2_points[k];\n                }\n              auto set_points = [&] () {\n                for (int k = 0; k < 3; k++)\n                  {\n                    tri1_points[k] = GetPoint(tri[k], 1.0, true);\n                    tri2_points[k] = GetPoint(tri2[k], 1.0, true);\n                  }\n              };\n\n              set_points();\n\n              int counter = 0;\n              while (IntersectTriangleTriangle(&trip1[0], &trip2[0]))\n                {\n                  changed = true;\n                  PointIndex pi_max_limit = PointIndex::INVALID;\n                  for (PointIndex pi :\n                       {tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})\n                    if (pi >= tool.first_new_pi && (!pi_max_limit.IsValid() || GetLimit(pi) > GetLimit(pi_max_limit)))\n                      pi_max_limit = map_from[pi];\n\n                  if (!pi_max_limit.IsValid())\n                    break;\n\n                  ScaleLimit(pi_max_limit, 0.9);\n                  set_points();\n                  counter++;\n                  if (GetLimit(pi_max_limit) < 1e-10)\n                    {\n                      WriteErrorMesh(\"error_blayer_self_intersection_pi\" + ToString(pi_max_limit) + \".vol.gz\");\n                      throw NgException(\"Stop meshing in boundary layer thickness limitation: overlapping regions detected at elements \" + ToString(tri) + \" and \" + ToString(tri2));\n                    }\n                  if (debugparam.debugoutput && counter > 20)\n                    {\n                      cerr << \"Limit intersecting surface elements: too many \"\n                              \"limitation steps, sels: \"\n                           << Get(sei) << '\\t' << Get(sej) << endl;\n                      for (auto si : {sei, sej})\n                        {\n                          auto sel = Get(si);\n                          cerr << \"Limits: \";\n                          for (auto pi : sel.PNums())\n                            cerr << GetLimit(pi) << \",\\t\";\n                          cerr << endl;\n                          for (auto pi : sel.PNums())\n                            cerr << GetPoint(pi, 1.0, true) << \"\\t\";\n                          cerr << endl;\n                        }\n                      cerr << \"pi_max_limit \" << pi_max_limit << endl;\n                      break;\n                    }\n                }\n              return false;\n            });\n          }\n      }\n  }\n\n  void LimitOriginalSurface (double safety)\n  {\n    static Timer t(\"GrowthVectorLimiter::LimitOriginalSurface\");\n    RegionTimer reg(t);\n    PrintMessage(5, \"GrowthVectorLimiter - original surface\");\n    // limit to not intersect with other (original) surface elements\n    double trig_shift = 0;\n    double seg_shift = safety;\n    FindTreeIntersections(\n      trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {\n        if (sei >= tool.nse)\n          return; // ignore new surface elements in first pass\n        LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);\n      });\n  }\n\n  void LimitBoundaryLayer (double safety = 1.1)\n  {\n    static Timer t(\"GrowthVectorLimiter::LimitBoundaryLayer\");\n    PrintMessage(5, \"GrowthVectorLimiter - boundary layer\");\n    // now limit again with shifted surface elements\n    double trig_shift = safety;\n    double seg_shift = safety;\n    size_t limit_counter = 1;\n\n    TBitArray<PointIndex> relevant_points, relevant_points_next;\n    relevant_points.SetSize(mesh.Points().Size() + 1);\n    relevant_points_next.SetSize(mesh.Points().Size() + 1);\n    relevant_points.Set();\n\n    while (limit_counter)\n      {\n        RegionTimer reg(t);\n        size_t find_counter = 0;\n        limit_counter = 0;\n        relevant_points_next.Clear();\n        FindTreeIntersections(\n          trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {\n            find_counter++;\n            auto sel = Get(sei);\n\n            if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift))\n              {\n                limit_counter++;\n                relevant_points_next.SetBit(pi_to);\n                relevant_points_next.SetBit(map_from[pi_to]);\n                for (auto pi : sel.PNums())\n                  {\n                    relevant_points_next.SetBit(pi);\n                    if (pi >= tool.first_new_pi)\n                      relevant_points_next.SetBit(map_from[pi]);\n                  }\n              }\n\n            for (auto pi : sel.PNums())\n              {\n                if (pi >= tool.first_new_pi)\n                  return;\n                if (tool.mapto[pi].Size() == 0)\n                  return;\n              }\n            if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift, true))\n              limit_counter++;\n          },\n          &relevant_points);\n        relevant_points = relevant_points_next;\n      }\n  }\n\n  void CheckLimits (int line)\n  {\n    auto check_point = [&] (PointIndex pi) {\n      if (limits[pi] < 1e-8)\n        {\n          WriteErrorMesh(\"error_blayer_intersection_pi\" + ToString(pi) + \".vol.gz\");\n          throw NgException(__FILE__ + ToString(line) + \": Stop meshing in boundary layer thickness limitation: overlapping regions detected at point \" + ToString(pi));\n        }\n    };\n\n    for (auto pi : Range(growthvectors))\n      check_point(pi);\n\n    if (!tool.insert_only_volume_elements)\n      for (auto& [special_pi, special_point] : tool.special_boundary_points)\n        check_point(special_pi);\n  }\n\n  void Perform ()\n  {\n    limits.SetSize(mesh.Points().Size());\n    limits = 1.0;\n    if (tool.special_boundary_points.size())\n      {\n        auto point_to_sel = tool.mesh.CreatePoint2SurfaceElementTable();\n        for (auto& [pi, special_point] : tool.special_boundary_points)\n          {\n            auto maxh = mesh.GetH(mesh[pi]);\n            auto new_limit = min(0.3 * maxh / tool.total_height, 1.0);\n            if (new_limit < 1.0)\n              {\n                limits[pi] = new_limit;\n                for (auto sei : point_to_sel[pi])\n                  for (auto pi_ : Get(sei).PNums())\n                    limits[pi_] = new_limit;\n              }\n          }\n      }\n\n    std::array safeties = {0.5, 1.1, 1.5, 1.5};\n\n    // No smoothing in the last pass, to avoid generating new intersections\n    std::array smoothing_factors = {0.8, 0.7, 0.5, 0.0};\n\n    for (auto i_pass : Range(safeties.size()))\n      {\n        PrintMessage(4, \"GrowthVectorLimiter pass \", i_pass);\n        double safety = safeties[i_pass];\n        CheckLimits(__LINE__);\n        // intersect segment with original surface elements\n        LimitOriginalSurface(2.1);\n        CheckLimits(__LINE__);\n        // intersect prisms with themself\n        LimitSelfIntersection(1.3 * safety);\n        CheckLimits(__LINE__);\n        // intesect segment with prism\n        LimitBoundaryLayer(safety);\n        CheckLimits(__LINE__);\n\n        for ([[maybe_unused]] auto i : Range(10))\n          EqualizeLimits(smoothing_factors[i_pass]);\n        CheckLimits(__LINE__);\n\n        if (i_pass == safeties.size() - 1)\n          FixIntersectingSurfaceTrigs();\n        CheckLimits(__LINE__);\n      }\n\n    for (auto i : Range(growthvectors))\n      growthvectors[i] *= limits[i];\n\n    for (auto& [special_pi, special_point] : tool.special_boundary_points)\n      {\n        for (auto& group : special_point.growth_groups)\n          {\n            group.growth_vector *= limits[special_pi];\n          }\n      }\n  }\n};\n\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/classifyhpel.hpp",
    "content": "// typename INDEX_2_HASHTABLE<int> HT_EDGEPOINT_DOM;\ntypedef ClosedHashTable<tuple<int, PointIndex>, int> HT_EDGEPOINT_DOM;\n\n\nHPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                               TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                               INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n  int ep1(0), ep2(0), ep3(0), ep4(0), cp1(0), cp2(0), cp3(0), cp4(0), fp1, fp2, fp3, fp4;\n  int isedge1(0), isedge2(0), isedge3(0), isedge4(0), isedge5(0), isedge6(0);\n  int isfedge1, isfedge2, isfedge3, isfedge4, isfedge5, isfedge6;\n  bool isface[4];\n\n  HPREF_ELEMENT_TYPE type = HP_NONE; \n  \n  int debug = 0;\n  /*\n  for (int j = 0;j < 4; j++)\n    {\n      if (el.pnums[j] == 444) debug++;\n      if (el.pnums[j] == 115) debug++;\n      if (el.pnums[j] == 382) debug++;\n      if (el.pnums[j] == 281) debug++;\n    }\n  if (debug < 4) debug = 0;\n  */\n\n  // *testout << \"new el\" << endl;\n  \n  for (int j = 0; j < 4; j++)\n    for (int k = 0; k < 4; k++)\n      {\n\tif (j == k) continue;\n\tif (type) break;\n\t\n\tint pi3 = 0;\n\twhile (pi3 == j || pi3 == k) pi3++;\n\tint pi4 = 6 - j - k - pi3;\n\t\n\t// preserve orientation\n\tint sort[4];\n\tsort[0] = j; sort[1] = k; sort[2] = pi3; sort[3] = pi4;\n\tint cnt = 0;\n\tfor (int jj = 0; jj < 4; jj++)\n\t  for (int kk = 0; kk < 3; kk++)\n\t    if (sort[kk] > sort[kk+1])\n\t      {\n\t\tcnt++;\n\t\tSwap (sort[kk], sort[kk+1]); \n\t      }\n\tif (cnt % 2 == 1) Swap (pi3, pi4);\n\t\n\tep1 = edgepoint.Test (el.pnums[j]);\n\tep2 = edgepoint.Test (el.pnums[k]);\n\tep3 = edgepoint.Test (el.pnums[pi3]);\n\tep4 = edgepoint.Test (el.pnums[pi4]);\n\t\n\tcp1 = cornerpoint.Test (el.pnums[j]);\n\tcp2 = cornerpoint.Test (el.pnums[k]);\n\tcp3 = cornerpoint.Test (el.pnums[pi3]);\n\tcp4 = cornerpoint.Test (el.pnums[pi4]);\n\t\n\tisedge1 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[k]));\n\tisedge2 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[pi3]));\n\tisedge3 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[pi4]));\n\tisedge4 = edges.Used (PointIndices<2>::Sort (el.pnums[k], el.pnums[pi3]));\n\tisedge5 = edges.Used (PointIndices<2>::Sort (el.pnums[k], el.pnums[pi4]));\n\tisedge6 = edges.Used (PointIndices<2>::Sort (el.pnums[pi3], el.pnums[pi4]));\n\t\n\tif (debug)\n\t  {\n\t    cout << \"debug\" << endl;\n\t    *testout  << \"debug\" << endl;\n\t    *testout << \"ep = \" << ep1 << ep2 << ep3 << ep4 << endl;\n\t    *testout << \"cp = \" << cp1 << cp2 << cp3 << cp4 << endl;\n\t    *testout << \"edge = \" << isedge1 << isedge2 << isedge3 << isedge4 << isedge5 << isedge6 << endl;\n\t  }\n\n\n        for (int j = 0; j < 4; j++) isface[j] = false;\n\tfor (int l = 0; l < 4; l++)\n\t  {\n\t    PointIndices<3> i3(PointIndex::INVALID, PointIndex::INVALID, PointIndex::INVALID);\n\t    switch (l)\n\t      {\n              case 0: i3[0] = el.pnums[k]; i3[1] = el.pnums[pi3]; i3[2] = el.pnums[pi4]; break;\n              case 1: i3[0] = el.pnums[j]; i3[1] = el.pnums[pi3]; i3[2] = el.pnums[pi4]; break;\n              case 2: i3[0] = el.pnums[j]; i3[1] = el.pnums[k]; i3[2] = el.pnums[pi4]; break;\n              case 3: i3[0] = el.pnums[j]; i3[1] = el.pnums[k]; i3[2] = el.pnums[pi3]; break;\n\t      }\n\t    i3.Sort();\n\t    if (faces.Used (i3))\n\t      {\n\t\tint domnr = faces.Get(i3);\n\t\tif (domnr == -1 || domnr == el.GetIndex())\n                  isface[l] = true;\n\t      }\n\t  }\n\t/*\n\t  isface1 = faces.Used (INDEX_3::Sort (el.pnums[k], el.pnums[pi3], el.pnums[pi4]));\n\t  isface2 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[pi3], el.pnums[pi4]));\n\t  isface3 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi4]));\n\t  isface4 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi3]));\n\t*/\n\t\n\tisfedge1 = isfedge2 = isfedge3 = isfedge4 = isfedge5 = isfedge6 = 0;\n\tfor (int l = 0; l < 6; l++)\n\t  {\n\t    PointIndices<2> i2(PointIndex::INVALID, PointIndex::INVALID);\n\t    switch (l)\n\t      {\n              case 0: i2[0] = el.pnums[j]; i2[1] = el[k]; break;\n              case 1: i2[0] = el.pnums[j]; i2[1] = el.pnums[pi3]; break;\n              case 2: i2[0] = el.pnums[j]; i2[1] = el.pnums[pi4]; break;\n              case 3: i2[0] = el.pnums[k]; i2[1] = el.pnums[pi3]; break;\n              case 4: i2[0] = el.pnums[k]; i2[1] = el.pnums[pi4]; break;\n              case 5: i2[0] = el.pnums[pi3]; i2[1] = el.pnums[pi4]; break;\n\t      }\n\t    i2.Sort();\n\t    if (face_edges.Used (i2))\n\t      {\n\t\tint domnr = face_edges.Get(i2);\n\t\tif (domnr == -1 || domnr == el.GetIndex())\n\t\t  {\n\t\t    switch (l)\n\t\t      {\n\t\t      case 0: isfedge1 = 1; break;\n\t\t      case 1: isfedge2 = 1; break;\n\t\t      case 2: isfedge3 = 1; break;\n\t\t      case 3: isfedge4 = 1; break;\n\t\t      case 4: isfedge5 = 1; break;\n\t\t      case 5: isfedge6 = 1; break;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\t/*\n\t  isfedge1 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k]));\n\t  isfedge2 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3]));\n\t  isfedge3 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4]));\n\t  isfedge4 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3]));\n\t  isfedge5 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4]));\n\t  isfedge6 = face_edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4]));\n\t*/\n\t\n\tfp1 = fp2 = fp3 = fp4 = 0;\n\tfor (int l = 0; l < 4; l++)\n\t  {\n\t    PointIndex pti = PointIndex::INVALID;\n\t    switch (l)\n\t      {\n\t      case 0: pti = el.pnums[j]; break;\n\t      case 1: pti = el.pnums[k]; break;\n\t      case 2: pti = el.pnums[pi3]; break;\n\t      case 3: pti = el.pnums[pi4]; break;\n\t      }\n\t    int domnr = facepoint[pti];\n\t    if (domnr == -1 || domnr == el.GetIndex())\n\t      {\n\t\tswitch (l)\n\t\t  {\n\t\t  case 0: fp1 = 1; break;\n\t\t  case 1: fp2 = 1; break;\n\t\t  case 2: fp3 = 1; break;\n\t\t  case 3: fp4 = 1; break;\n\t\t  }\n\t      }\n\t  }\n\n        /*\n        ep1 |= cp1;\n        ep2 |= cp2;\n        ep3 |= cp3;\n        ep4 |= cp4;\n\n        fp1 |= ep1;\n        fp2 |= ep2;\n        fp3 |= ep3;\n        fp4 |= ep4;\n        */\n        \n\t/*\n\t  fp1 = facepoint[el.pnums[j]] != 0;\n\t  fp2 = facepoint[el.pnums[k]] != 0;\n\t  fp3 = facepoint[el.pnums[pi3]] != 0;\n\t  fp4 = facepoint[el.pnums[pi4]] != 0;\n\t*/\n\n        // cout << \"marked faces: \"\n            // << isface[0] << isface[1] << isface[2] << isface[3] \n            // << \", num = \" << isface[0]+isface[1]+isface[2]+isface[3] << endl;\n\n        \n        bool sp1 = cp1 \n          || (ep1 && !isedge1 && !isedge2 && !isedge3)\n          || (fp1 && !isfedge1 && !isfedge2 && !isfedge3);\n\n        bool sp2 = cp2 \n          || (ep2 && !isedge1 && !isedge4 && !isedge5)\n          || (fp2 && !isfedge1 && !isfedge4 && !isfedge5);\n\n        bool sp3 = cp3 \n          || (ep3 && !isedge2 && !isedge4 && !isedge6)\n          || (fp3 && !isfedge2 && !isfedge4 && !isfedge6);\n\n        bool sp4 = cp4 \n          || (ep4 && !isedge3 && !isedge5 && !isedge6)\n          || (fp4 && !isfedge3 && !isfedge5 && !isfedge6);\n\n        bool se1 = isedge1 || (isfedge1 && !isface[2] && !isface[3]);\n        bool se2 = isedge2 || (isfedge2 && !isface[1] && !isface[3]);\n        bool se3 = isedge3 || (isfedge3 && !isface[1] && !isface[2]);\n        bool se4 = isedge4 || (isfedge4 && !isface[0] && !isface[3]);\n        bool se5 = isedge5 || (isfedge5 && !isface[0] && !isface[2]);\n        bool se6 = isedge6 || (isfedge6 && !isface[0] && !isface[1]);\n\n        // *testout << \"sp = \" << sp1 << sp2 << sp3 << sp4 << endl;\n        // *testout << \"se = \" << se1 << se2 << se3 << se4 << se5 << se6 << endl;        \n        // *testout << \"sf = \" << isface[0] << isface[1] << isface[2] << isface[3] << endl;\n\n        \n\tswitch (isface[0]+isface[1]+isface[2]+isface[3])\n\t  {\n\t  case 0:\n\t    {\n\t      isedge1 |= isfedge1;\n\t      isedge2 |= isfedge2;\n\t      isedge3 |= isfedge3;\n\t      isedge4 |= isfedge4;\n\t      isedge5 |= isfedge5;\n\t      isedge6 |= isfedge6;\n\t      \n\t      ep1 |= fp1;\n\t      ep2 |= fp2;\n\t      ep3 |= fp3;\n\t      ep4 |= fp4;\n\t      \n\t      switch (isedge1+isedge2+isedge3+isedge4+isedge5+isedge6)\n\t\t{\n\t\tcase 0:\n\t\t  {\t\t\n\t\t    if (!sp1 && !sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET;\n\t\t\t\t\n\t\t    if (sp1 && !sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET_0E_1V;\n\t\t    \n\t\t    if (sp1 && sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET_0E_2V;\n\t\t    \n\t\t    if (sp1 && sp2 && sp3 && !sp4)\n\t\t      type = HP_TET_0E_3V;\n\t\t    \n\t\t    if (sp1 && sp2 && sp3 && sp4)\n\t\t      type = HP_TET_0E_4V;\n\t\t    \n\t\t    break;\n\t\t  }\n\t\t  \n\t\tcase 1:\n\t\t  {\n\t\t    if (!isedge1) break;\n\t\t    \n\t\t    if (!sp1 && !sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET_1E_0V;\n\t\t    \n\t\t    if (sp1 && !sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET_1E_1VA;\n\t\t    \n\t\t    if (!sp1 && !sp2 && !sp3 && sp4)\n\t\t      type = HP_TET_1E_1VB;\n\t\t    \n\t\t    if (sp1 && sp2 && !sp3 && !sp4)\n\t\t      type = HP_TET_1E_2VA;\n\t\t    \n\t\t    if (sp1 && !sp2 && sp3 && !sp4)\n\t\t      type = HP_TET_1E_2VB;\n\t\t    \n\t\t    if (sp1 && !sp2 && !sp3 && sp4)\n\t\t      type = HP_TET_1E_2VC;\n\t\t    \n\t\t    if (!sp1 && !sp2 && sp3 && sp4)\n\t\t      type = HP_TET_1E_2VD;\n\t\t    \n\t\t    if (sp1 && sp2 && sp3 && !sp4)\n\t\t      type = HP_TET_1E_3VA;\n\t\t    \n\t\t    if (sp1 && !sp2 && sp3 && sp4)\n\t\t      type = HP_TET_1E_3VB;\n\t\t    \n\t\t    if (sp1 && sp2 && sp3 && sp4)\n\t\t      type = HP_TET_1E_4V;\n\t\t    \n\t\t    break;\n\t\t  }\n\t\tcase 2:\n\t\t  {\n\t\t    if (isedge1 && isedge2)\n\t\t      {\n\t\t\tif (!sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_2EA_0V;\n\t\t\t\n\t\t\tif (sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_2EA_1VA;\n\t\t\tif (!sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_2EA_1VB;\n\t\t\t\n\t\t\tif (!sp2 && !sp3 && sp4)\n\t\t\t  type = HP_TET_2EA_1VC;\n\t\t\t\n\t\t\tif (sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_2EA_2VA;\n\t\t\tif (sp2 && !sp3 && sp4)\n\t\t\t  type = HP_TET_2EA_2VB;\n\t\t\tif (!sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_2EA_2VC;\n\t\t\t\n\t\t\tif (sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_2EA_3V;\n\t\t      }\n\t\t    if (isedge1 && isedge6)\n\t\t      {\n\t\t\tif (!sp1 && !sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_2EB_0V;\n\t\t\tif (sp1 && !sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_2EB_1V;\n\t\t\tif (sp1 && sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_2EB_2VA;\n\t\t\tif (sp1 && !sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_2EB_2VB;\n\t\t\tif (sp1 && !sp2 && !sp3 && sp4)\n\t\t\t  type = HP_TET_2EB_2VC;\n\t\t\tif (sp1 && sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_2EB_3V;\n\t\t\tif (sp1 && sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_2EB_4V;\n\t\t      }\n\t\t    break;\n\t\t  }\n\t\tcase 3:\n\t\t  {\n\t\t    if (isedge1 && isedge2 && isedge3)\n\t\t      {\n\t\t\tif (!sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_3EA_0V;\n\t\t\tif (sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_3EA_1V;\n\t\t\tif (sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_3EA_2V;\n\t\t\tif (sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_3EA_3V;\n\t\t      }\n\t\t    if (isedge1 && isedge3 && isedge4)\n\t\t      {\n\t\t\tif (!sp3 && !sp4)\n\t\t\t  type = HP_TET_3EB_0V;\n\t\t\tif (sp3 && !sp4)\n                          type = HP_TET_3EB_1V;\n\t\t\tif (sp3 && sp4)\n\t\t\t  type = HP_TET_3EB_2V;\n\t\t      }\n\t\t    if (isedge1 && isedge2 && isedge5)\n\t\t      {\n\t\t\tif (!sp3 && !sp4)\n\t\t\t  type = HP_TET_3EC_0V;\n\t\t\tif (sp3 && !sp4)\n\t\t\t  type = HP_TET_3EC_1V;\n\t\t\tif (sp3 && sp4)\n\t\t\t  type = HP_TET_3EC_2V;\n\t\t      }\n                    if (isedge1 && isedge2 && isedge4)\n                      {\n                        if (!sp4)\n                          type = HP_TET_3ED_3V; // a loop\n                      }\n\n\t\t    break;\n\t\t  }\n\t\t}\n\t      break;\n\t    }\n\t    \n\t    \n\t    \n\t  case 1:  // one singular face\n\t    {\n\t      if (!isface[0]) break;\n\n              /*\n              cout << \"1F and 1E, isedge = \" << isedge1 << isedge2 << isedge3 << isedge4 << isedge5 << isedge6 << endl;\n              cout << \"spoints = \" << sp1 << sp2 << sp3 << sp4 << endl;\n              cout << \"cpoints = \" << cp1 << cp2 << cp3 << cp4 << endl;                    \n              cout << \"epoints = \" << ep1 << ep2 << ep3 << ep4 << endl;\n              cout << \"fpoints = \" << fp1 << fp2 << fp3 << fp4 << endl;                                  \n              */\n\n\t      isedge1 |= isfedge1;\n\t      isedge2 |= isfedge2;\n\t      isedge3 |= isfedge3;\n              \n\t      // switch (isedge1+isedge2+isedge3+isedge4+isedge5+isedge6)\n              switch (se1+se2+se3+se4+se5+se6)\n\t\t{\n\t\tcase 0:\n\t\t  {\n\t\t    if (!fp1 && !ep2 && !ep3 && !ep4)\n\t\t      type = HP_TET_1F_0E_0V;\n\t\t    if (fp1 && !ep2 && !ep3 && !ep4)\n\t\t      type = HP_TET_1F_0E_1VB;\n\t\t    if (!fp1 && ep2 && !ep3 & !ep4)\n\t\t      type = HP_TET_1F_0E_1VA;\n\t\t    if (!fp1 && ep2 && ep3 & !ep4)\n\t\t      type = HP_TET_1F_0E_2V;\n\n                    if (!sp1 && sp2 && sp3 && sp4)\n                      type = HP_TET_1F_0E_3V;                        \n\t\t    break;\n\t\t  }\n\t\tcase 1:\n\t\t  {\n\t\t    if (se1)\n\t\t      {\n\t\t\tif (!sp1 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_1F_1EA_0V;\n\t\t\tif (!sp1 && sp2 && sp3 && !sp4)\n\t\t\t  type = HP_TET_1F_1E_2VA;\n\t\t\tif (!sp1 && sp2 && !sp3 && sp4)\n\t\t\t  type = HP_TET_1F_1E_2VB;\n\t\t\tif (!sp1 && !sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_1F_1E_2VC;\n\t\t\tif (!sp1 && sp2 && sp3 && sp4)\n\t\t\t  type = HP_TET_1F_1EA_3V;\n\t\t      }\n\t\t    if (se4) // V2-V3\n\t\t      {\n\t\t\tif (!sp1 && !sp2 && !sp3 && !sp4)\n\t\t\t  type = HP_TET_1F_1EB_0V;\n\t\t\tif (!sp1 && sp2 && !sp3 && !sp4)\n                          type = HP_TET_1F_1E_1VA;\n\t\t\tif (!sp1 && sp2 && sp3 && sp4)\n                          type = HP_TET_1F_1E_3V;\n\t\t      }\n                    if (se5) // V2-V4\n                      {\n\t\t\tif (!sp1 && sp2 && !sp3 && !sp4)\n                          type = HP_TET_1F_1E_1VB;\n                      }\n\t\t    break;\n\t\t  }\n                case 2:\n                  {\n                    if (isedge1 && isedge2)\n                      {\n                        if (sp1 && sp2 && sp3 && !sp4)\n                          type = HP_TET_1F_2Eoo_3V;\n                      }\n                    if (isedge6 && isedge3)\n                      if (!cp1 && !cp2 && !cp3)\n                        type = HP_TET_1F_2E_0VA;\n                    if (isedge6 && isedge2)\n                      {\n                        if (!cp1 && !cp2 && !cp4)\n                          type = HP_TET_1F_2E_0VB;\n                      }\n                    if (se4 && se5)\n                      { // 2 edges in face\n                        if (!sp1 && sp2 && !sp3 && !sp4)\n                          type = HP_TET_1F_2E_1V;\n                        if (!sp1 && sp2 && sp3 && sp4)\n                          type = HP_TET_1F_2E_3V;\n                      }\n                    break;\n                  }\n                default:\n                  ;\n\t\t}\n\t      break;\n\t    }\n\t    \n\t    \n\t  case 2:  // two singular faces\n\t    {\n\t      if (!isface[0] || !isface[1]) break;\n\t      \n\t      switch (isfedge1+isedge2+isedge3+isedge4+isedge5)\n\t\t{\n\t\tcase 0:\n\t\t  {\n\t\t    if (!ep1 && !ep2 && !cp3 && !cp4)\n                      {\n                        type = HP_TET_2F_0E_0V;\n                        break;\n                      }\n\t\t    if (!ep1 && !ep2 && !cp3 && cp4)\n                      {\n                        type = HP_TET_2F_0E_1V;\n                        break;\n                      }\n                    break;\n\t\t  }\n                case 1:\n                  {\n                    // *testout << \"so far: 2F, 1E, sp = \" << sp1 << sp2 << sp3 << sp4 << endl;\n\n                    if (isedge4)\n                      {\n                        if (!ep1 && !cp2 && !cp4)\n                          {\n                            type = HP_TET_2F_1E_0VA;\n                            break;\n                          }\n                        if (!sp1 && sp2 && sp3 && sp4)\n                          {\n                            type = HP_TET_2F_1E_3VA;\n                            break;\n                          }\n                        if (sp1 && sp2 && sp3 && sp4)\n                          {\n                            type = HP_TET_2F_1E_4VA;\n                            break;\n                          }\n                      }\n                    \n                    if (isedge5 && !ep1 && !cp2 && !cp3)\n                      {\n                        type = HP_TET_2F_1E_0VB;\n                        break;\n                      }\n                    break;\n                  }\n                default:\n                  *testout << \"2F, 2E or more not implemented so far\" << endl;\n\t\t}\n\t      break;\n\t    }\n\n          case 3:\n            {\n              if (!isface[3])\n                if (!cp1 && !cp2 && !cp3)\n                  {\n                    type = HP_TET_3F_0E_0V;\n                    break;\n                  }\n              break;\n            }\n          case 4:  \n            {\n              *testout << \"4 singular faces\" << endl;\n            }\n\t  }\n\t\n\tif (type != HP_NONE)\n\t  {\n\t    PointIndex pnums[4]; \n\t    pnums[0] = el.pnums[j];\n\t    pnums[1] = el.pnums[k];\n\t    pnums[2] = el.pnums[pi3];\n\t    pnums[3] = el.pnums[pi4];\n\t    for(k=0;k<4;k++) el.pnums[k] = pnums[k]; \n\t    break;\n\t  }\n      }\n  \n  \n  if (debug) cout << \"type = \" << type << endl;\n\n  if (type == HP_NONE)\n    {\n      //     cnt_undef++;\n      (*testout) << \"unclassified element \" \n                 << el.pnums[0] << \" \"\n                 << el.pnums[1] << \" \"\n                 << el.pnums[2] << \" \"\n                 << el.pnums[3] << endl\n\t\t << \"cp = \" << cp1 << cp2 << cp3 << cp4 << endl\n\t\t << \"ep = \" << ep1 << ep2 << ep3 << ep4 << endl\n\t\t << \"fp = \" << fp1 << fp2 << fp3 << fp4 << endl\n\t\t << \"isedge = \" << isedge1 << isedge2 << isedge3 \n\t\t << isedge4 << isedge5 << isedge6 << endl\n\t\t << \"isfedge = \" << isfedge1 << isfedge2 << isfedge3 \n\t\t << isfedge4 << isfedge5 << isfedge6 << endl\n\t\t << \"isface = \" << isface[0] << isface[1] << isface[2] << isface[3] << endl;\n      cout << \"unclassified element !!! \" << endl;\n\n      \n    }\n  return(type); \n}\n\n\n\nHPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                 TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                                 INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n\n  HPREF_ELEMENT_TYPE type = HP_NONE;\n  \n  int p[6];\n  for(int m=1;m<=6;m++)\n    {\n      int point_sing[6]={0,0,0,0,0,0}; \n      int face_sing[5]={0,0,0,0,0};\n      int edge_sing[9]={0,0,0,0,0,0,0,0,0}; \n      \n      if(m<4)\n\t{ \n\t  p[0]= m; p[1]=m%3+1; p[2]=(m%3+1)%3+1;\n\t  for(int l=3;l<6;l++) p[l]=p[l-3]+3;  \n\t}\n      else\n\t{\n\t  p[0] = m; p[1]=(m%3+1)%3+4; p[2]=m%3+4;\n\t  for(int l=3;l<6;l++) p[l]=p[l-3]-3; \n\t}\n      \n      for(int j=0;j<6;j++) \n\t{ \n\t  if(cornerpoint.Test(el.PNum(p[j])))  { point_sing[p[j]-1]=3;}\n\t  else if(edgepoint.Test(el.PNum(p[j]))) point_sing[p[j]-1]=2;\n\t  else if (facepoint[el.PNum(p[j])] == -1 || facepoint[el.PNum(p[j])] == el.GetIndex())\n\t    point_sing[p[j]-1] = 1;  \n\t}\n      \n      const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (PRISM);\n      for(int k=0;k<9;k++)\n\t{\n\t  PointIndices<2> i2 = PointIndices<2> :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); \n\t  if (edges.Used(i2)) edge_sing[k] = 2;\n\t  else edge_sing[k] = face_edges.Used(i2);\n\t}\n      \n      const ELEMENT_FACE * elfaces  = MeshTopology::GetFaces1 (PRISM);\n      for (int k=0;k<5;k++)\n\t{\n\t  PointIndices<3> i3; \n\t  \n\t  if(k<2) \n\t    i3 = PointIndices<3>::Sort(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], \n                                       el.pnums[p[elfaces[k][2]-1]-1]); \n\t  else \n\t    { \n\t      PointIndices<4> i4 (el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1],\n                                  el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); \n\t      i4.Sort();\n\t      i3 = PointIndices<3>(i4[0], i4[1], i4[2]);\n\t    }\n\t  \n\t  if (faces.Used (i3))\n\t    {\n\t      int domnr = faces.Get(i3); \n\t      if (domnr == -1 || domnr == el.GetIndex())\n\t\tface_sing[k] = 1; \n\t      \n\t    } \n\t} \n      if (face_sing[1] > face_sing[0]) {m=m+2; continue;}  \n      \n      \n      //int cp = 0;  \n      \n      int qfsing = face_sing[2] + face_sing[3] + face_sing[4];\n      int tfsing = face_sing[0] + face_sing[1]; \n      int evsing = edge_sing[6] + edge_sing[7] + edge_sing[8];\n      int ehsing = edge_sing[0] + edge_sing[1] + edge_sing[2] + edge_sing[3] + edge_sing[4] + edge_sing[5];\n      \n      if (qfsing + tfsing + evsing + ehsing == 0)  \n\t{ type = HP_PRISM;  break;}\n      \n      HPREF_ELEMENT_TYPE types[] = {HP_NONE,HP_NONE,HP_NONE};   \n      \n      int fb = (1-face_sing[4])* face_sing[3] * (face_sing[2] + face_sing[3]) + 3*face_sing[4]*face_sing[3]*face_sing[2];  \n      int sve[3] = {edge_sing[7] , edge_sing[8], edge_sing[6]}; \n      \n            \n      if(fb!=qfsing) continue; \n      \n      \n      switch(fb)\n\t{ \n\tcase 0: \n\t  if (evsing == 0 && ehsing==3*tfsing) \n\t    {\n\t      types[0] = HP_PRISM; \n\t      types[1] = HP_PRISM_1FA_0E_0V;   \n\t      types[2] = HP_PRISM_2FA_0E_0V; \n\t    } \n\t  if(evsing > 0 &&  sve[0] == evsing) // 1 vertical edge 1-4 \n\t    { \n\t      types[0] = HP_PRISM_SINGEDGE;\n\t      types[1] = HP_PRISM_1FA_1E_0V;\n\t      types[2] = HP_PRISM_2FA_1E_0V;   \n\t    }\n\t  \n\t  if(sve[0] > 0 && sve[1] > 0 && sve[2] == 0)\n\t    {\n\t      types[0] = HP_PRISM_SINGEDGE_V12;\n\t      types[1] = HP_PRISM_1FA_2E_0V; \n\t      types[2] = HP_PRISM_2FA_2E_0V; \n\t    }\n\t  if(sve[0] > 0 && sve[1] > 0 && sve[2] > 0) \n\t    {\n\t      types[0] = HP_PRISM_3E_0V;\n\t      types[1] = HP_PRISM_1FA_3E_0V;\n\t      types[2] = HP_PRISM_2FA_3E_0V;\n\t      \n\t      if ( edge_sing[0] > 1 && edge_sing[2] > 1 &&  \n\t\t   edge_sing[4] > 1 && edge_sing[5] > 1 && tfsing==0)\n\t\ttypes[0] = HP_PRISM_3E_4EH; \n\t    }\n\t  \n\t  break;\n\tcase 1:\n\t  if(sve[0] <= 1 && sve[1] <= 1)  \n            {\n              if(sve[2]==0)\n                { \n                  types[0] = HP_PRISM_1FB_0E_0V;\n                  types[1] = HP_PRISM_1FA_1FB_0E_0V;\n                  types[2] = HP_PRISM_2FA_1FB_0E_0V;  \n                }\n              else\n                { \n                  types[0] = HP_PRISM_1FB_1EC_0V;\n                  types[1] = HP_PRISM_1FA_1FB_1EC_0V;\n                  types[2] = HP_PRISM_2FA_1FB_1EC_0V; \n                }\n            }\n\n\t  if(sve[0] > 1 && sve[2] >= 1 && sve[1] <= 1)\n\t    { \n\t      types[0] = HP_PRISM_1FB_2EB_0V;  \n\t      types[1] = HP_PRISM_1FA_1FB_2EB_0V;\n\t      types[2] = HP_PRISM_2FA_1FB_2EB_0V; \n\t    }\n\t  \n\t  if(sve[0] > 1 && sve[1] <= 1 && sve[2] == 0) // ea && !eb  \n\t    {\n\t      types[0] = HP_PRISM_1FB_1EA_0V;\n\t      types[1] = HP_PRISM_1FA_1FB_1EA_0V;\n\t      types[2] = HP_PRISM_2FA_1FB_1EA_0V; \n\t    } \n\t  \n\t  if(sve[0] <= 1 && sve[1] > 1 && sve[2] == 0)\n\t    types[1] = HP_PRISM_1FA_1FB_1EB_0V; \n\t  \n\t  if(sve[0] > 1 && sve[1]>1) \n\t    if(sve[2] == 0)  // ea && eb \n\t      {\n\t\ttypes[0] = HP_PRISM_1FB_2EA_0V;\n\t\ttypes[1] = HP_PRISM_1FA_1FB_2EA_0V;\n\t\ttypes[2] = HP_PRISM_2FA_1FB_2EA_0V; \n\t      }\n\t  if(sve[0] <= 1 && sve[1] > 1 && sve[2] >0)\n\t    types[1] = HP_PRISM_1FA_1FB_2EC_0V; \n\t  \n\t  if(sve[0] > 1 && sve[1] > 1 && sve[2] >= 1) //sve[2] can also be a face-edge  \n\t    {\n\t      types[0] = HP_PRISM_1FB_3E_0V;  \n\t      types[1] = HP_PRISM_1FA_1FB_3E_0V; \n\t      types[2] = HP_PRISM_2FA_1FB_3E_0V; \n\t    } \n\t  \n\t  break;  \n\t  \n\tcase 2:\n\t  if(sve[0] <= 1) \n\t    cout << \" **** WARNING: Edge between to different singular faces should be marked singular \" << endl; \n\t\t      \n\t  if(sve[1] <= 1)   \n\t    if(sve[2] <=1) \n\t      { \n\t\ttypes[0] = HP_PRISM_2FB_0E_0V; \n\t\ttypes[1] = HP_PRISM_1FA_2FB_0E_0V;\n\t\ttypes[2] = HP_PRISM_2FA_2FB_0E_0V;\n\t      }\n\t    else\n\t      { \n\t\ttypes[0] = HP_PRISM_2FB_1EC_0V; \n\t\ttypes[1] = HP_PRISM_1FA_2FB_1EC_0V; \n\t\ttypes[2] = HP_PRISM_2FA_2FB_1EC_0V;   \n\t      }\n\t  else\n\t    if(sve[2] <= 1) \n\t      types[1] = HP_PRISM_1FA_2FB_1EB_0V; \n\t    else\n\t      { \n\t\ttypes[0] = HP_PRISM_2FB_3E_0V; \n\t\ttypes[1] = HP_PRISM_1FA_2FB_3E_0V; \n\t\ttypes[2] = HP_PRISM_2FA_2FB_3E_0V; \n\t      }\n\t  \n\t  break;\n\t  \n\tcase 3: \n\t  types[0] = HP_PRISM_3FB_0V; \n\t  types[1] = HP_PRISM_1FA_3FB_0V; \n\t  types[2] = HP_PRISM_2FA_3FB_0V; \n\t  break;\n\t}\n      type = types[tfsing];\n      \n         \n      if(type != HP_NONE)  \n\tbreak;\n    }\n\t \n  /*\n   *testout << \" Prism with pnums \" << endl; \n   for(int j=0;j<6;j++) *testout << el.pnums[j] << \"\\t\"; \n   *testout << endl; \n   */\n  \n  if(type != HP_NONE) \n    {\n      PointIndex pnums[6]; \n      for(int j=0;j<6;j++) pnums[j] = el.PNum (p[j]);\n      for(int k=0;k<6;k++) el.pnums[k] = pnums[k]; \n    }\n\n  /* *testout << \" Classified Prism with pnums \" << endl; \n     for(int j=0;j<6;j++) *testout << el.pnums[j] << \"\\t\"; \n     *testout << endl; \n     */ \n  return(type); \n}\n\n\n// #ifdef SABINE\n\n\nHPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int>  & face_edges, \n\t\t\t\tINDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int dim, const FaceDescriptor & fd)\n\n{\n  HPREF_ELEMENT_TYPE type = HP_NONE;\n  \n  PointIndex pnums[3]; \n  int p[3];   \n  \n  PointIndices<3> i3 (el.pnums[0], el.pnums[1], el.pnums[2]);\n  i3.Sort();\n  bool sing_face = faces.Used (i3);\n  \n  // *testout << \" facepoint \" << facepoint << endl;  \n      \n\n  // Try all rotations of the trig \n  for (int j=0;j<3;j++) \n    {\n      int point_sing[3] = {0,0,0}; \n      int edge_sing[3] = {0,0,0}; \n      // *testout << \" actual rotation of trig points \" ;  \n      for(int m=0;m<3;m++) \n\t{ \n\t  p[m] = (j+m)%3 +1; // local vertex number\n\t  pnums[m] = el.PNum(p[m]); // global vertex number \n\t  // *testout << pnums[m] << \" \\t \"; \n\t}\n      // *testout << endl ; \n      \n      if(dim == 3) \n\t{\n\t  // face point \n\t  for(int k=0;k<3;k++)\n\t    if(!sing_face)\n\t      { \n\t\t//\t*testout << \" fp [\" << k << \"] = \" << facepoint[pnums[k]] << endl;   \n\t\t//\t*testout << \" fd.DomainIn()\" <<  fd.DomainIn() << endl; \n\t\t//\t*testout  << \" fd.DomainOut()\" <<  fd.DomainOut() << endl; \n\t\tif( facepoint[pnums[k]]  && (facepoint[pnums[k]] ==-1 || \n\t\t\t\t\t     facepoint[pnums[k]] == fd.DomainIn() ||   facepoint[pnums[k]] == fd.DomainOut()))\n\t\t  point_sing[p[k]-1] = 1; \n\t      } \n\t  // if point is on face_edge in next step sing = 2 \n\n\t  /*\t  *testout << \" pointsing NACH FACEPOints ... FALLS EDGEPOINT UMSETZEN\" ; \n            for (int k=0;k<3;k++) *testout << \"\\t\" << point_sing[p[k]-1] ;\n            *testout << endl; */\n\t}\n      \n      const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1(TRIG); \n      \n      if(dim==3)\n\t{\n\t  for(int k=0;k<3;k++) \n\t    { \n\t      int ep1=p[eledges[k][0]-1];  \n\t      int ep2=p[eledges[k][1]-1];  \n\t      PointIndices<2> i2(el.PNum(ep1),el.PNum(ep2)); \n\t      \n\t      if(edges.Used(i2)) \n\t\t{\n\t\t  \n\t\t  edge_sing[k]=2;\n\t\t  point_sing[ep1-1] = 2; \n\t\t  point_sing[ep2-1] = 2; \n\t\t}\n\t      else // face_edge? \n\t\t{\t  \n\t\t  i2.Sort();  \n\t\t  if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1)  // edge not face_edge acc. to surface in which trig lies\n\t\t    {\n\t\t      if(face_edges.Get(i2)==-1 ||face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut() )\n\t\t\t{ \n\t\t\t  edge_sing[k]=1;\n\t\t\t} \n\t\t      else\n\t\t\t{ \n\t\t\t  point_sing[ep1-1] = 0; // set to edge_point \n\t\t\t  point_sing[ep2-1] = 0; // set to edge_point\n\t\t\t} \n\t\t    }\n\t\t}\n\t      \n\t      /*  *testout << \" pointsing NACH edges UND FACEEDGES UMSETZEN ... \" ; \n                  for (int k=0;k<3;k++) *testout << \"\\t\" << point_sing[p[k]-1] ; \n                  *testout << endl;          \n                  */\n\t    }\n\t}\n      /*\n       *testout << \" dim \" << dim << endl; \n       *testout << \" edgepoint_dom \" << edgepoint_dom << endl; \n       */\n      if(dim==2)\n\t{\n\t  for(int k=0;k<3;k++) \n\t    { \n\t      int ep1=p[eledges[k][0]-1];  \n\t      int ep2=p[eledges[k][1]-1];  \n\t     \n\t      PointIndices<2> i2 = PointIndices<2>::Sort(el.PNum(ep1),el.PNum(ep2));\n\t     \n\t      if(edges.Used(i2)) \n\t\t{\n\t\t  if(edgepoint_dom.Used( { fd.SurfNr(),pnums[ep1-1] } ) || \n\t\t     edgepoint_dom.Used( { -1,pnums[ep1-1] } ) || \n\t\t     edgepoint_dom.Used( { fd.SurfNr(), pnums[ep2-1]} ) || \n\t\t     edgepoint_dom.Used( { -1,pnums[ep2-1] } )) \n\t\t    {\n\t\t      edge_sing[k]=2;\n\t\t      point_sing[ep1-1] = 2;\n\t\t      point_sing[ep2-1] = 2; \n\t\t    }\n\t\t}\n\t     \n\t    }\n\t}\n\n     \n\t \n      for (int k=0;k<3;k++) \n        if (edgepoint.Test(pnums[k]) &&\n            (dim==3 || edgepoint_dom.Used( { fd.SurfNr(),pnums[k] } ) || edgepoint_dom.Used( { -1,pnums[k] } )))\n          //edgepoint, but not member of sing_edge on trig -> cp\n\t  {\n\t    PointIndices<2> i2a = PointIndices<2>::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3])); \n            PointIndices<2> i2b = PointIndices<2>::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3]));\n\t    \n\t    if(!edges.Used(i2a) && !edges.Used(i2b)) \n\t      point_sing[p[k]-1] = 3; \t\n\t  } \n      \n      for(int k=0;k<3;k++) \n\tif(cornerpoint.Test(el.PNum(p[k]))) \n\t  point_sing[p[k]-1] = 3;\n      \n      // *testout << \"point_sing = \" << point_sing[0] << point_sing[1] << point_sing[2] << endl;\n\n      if(edge_sing[0] + edge_sing[1] + edge_sing[2] == 0) \n        { \n          int ps = point_sing[0] + point_sing[1] + point_sing[2]; \n\t \n          if(ps==0) \n            type = HP_TRIG; \n          else if(point_sing[p[0]-1]  && !point_sing[p[1]-1] && !point_sing[p[2]-1])\n            type = HP_TRIG_SINGCORNER;\n          else if(point_sing[p[0]-1] && point_sing[p[1]-1] && !point_sing[p[2]-1]) \n            type = HP_TRIG_SINGCORNER12; \n          else if(point_sing[p[0]-1] && point_sing[p[1]-1] && point_sing[p[2]-1]) \n            { \n              if(dim==2) type = HP_TRIG_SINGCORNER123_2D; \n              else type = HP_TRIG_SINGCORNER123; \n            } \n        } \n      else\n        if (edge_sing[2] && !edge_sing[0] && !edge_sing[1]) //E[2]=(1,2) \n          { \n            int code = 0; \n            if(point_sing[p[0]-1] > edge_sing[2]) code+=1; \n            if(point_sing[p[1]-1] > edge_sing[2]) code+=2; \n            if(point_sing[p[2]-1]) code+=4; \n\t\n            HPREF_ELEMENT_TYPE types[] =\n              {\n                HP_TRIG_SINGEDGE, \n                HP_TRIG_SINGEDGECORNER1, \n                HP_TRIG_SINGEDGECORNER2,\n                HP_TRIG_SINGEDGECORNER12, \n                HP_TRIG_SINGEDGECORNER3, \n                HP_TRIG_SINGEDGECORNER13, \n                HP_TRIG_SINGEDGECORNER23, \n                HP_TRIG_SINGEDGECORNER123, \n              };\n            type = types[code]; \n\t\n          }  // E[0] = [0,2], E[1] =[1,2], E[2] = [0,1]\n        else \n          if(edge_sing[2] && !edge_sing[1] && edge_sing[0])\n            {\n              if(point_sing[p[2]-1] <= edge_sing[0] ) \n                { \n                  if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES; \n                  else type = HP_TRIG_SINGEDGES2; \n                } \n              else \n                {\n                  if(point_sing[p[1]-1]<= edge_sing[2]) \n                    type = HP_TRIG_SINGEDGES3; \n                  else type = HP_TRIG_SINGEDGES23; \n                }\n            }\n          else if (edge_sing[2] && edge_sing[1] && edge_sing[0])\n            type = HP_TRIG_3SINGEDGES; \n     \n      //  cout << \" run for \" <<  j << \" gives type \" << type << endl; \n      //*testout << \" run for \" <<  j << \" gives type \" << type << endl; \n\n      if(type!=HP_NONE) break;\n    }\n\n  // *testout << \"type = \" << type << endl;\n    \n  for(int k=0;k<3;k++) el[k] = pnums[k]; \n  /*if(type != HP_NONE) \n    {\n     \n    cout << \" TRIG with pnums \" << pnums[0] << \"\\t\"  << \n    pnums[1] << \"\\t\"  << pnums[2] << endl; \n    cout << \" type \"  << type << endl; \n    }\n  */\n      return(type);\n}\n#ifdef HPREF_OLD \nHPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, \n\t\t\t\tNgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n\t\t\t\tINDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd)\n{\n  HPREF_ELEMENT_TYPE type = HP_NONE; \n  \n  int pnums[3]; \n\t      \n  INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]);\n  i3.Sort();\n  bool sing_face = faces.Used (i3);\n   \n  \n  for (int j = 1; j <= 3; j++)\n    {\n      int ep1 = edgepoint.Test (el.PNumMod (j));\n      int ep2 = edgepoint.Test (el.PNumMod (j+1));\n      int ep3 = edgepoint.Test (el.PNumMod (j+2));\n      \n      if (dim == 2)\n\t{\n\t  // JS, Dec 11\n\t  ep1 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j))) ||\n\t    edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j)));\n\t  ep2 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+1))) ||\n\t    edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+1)));\n\t  ep3 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+2))) ||\n\t    edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+2)));\n\t  /*\n            ep1 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j)));\n            ep2 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+1)));\n            ep3 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+2)));\n\t  */\n\t  // ep3 = edgepoint_dom.Used (INDEX_2 (mesh.SurfaceElement(i).GetIndex(), el.PNumMod(j+2)));\n\t}\n      \n      \n      \n      int cp1 = cornerpoint.Test (el.PNumMod (j));\n      int cp2 = cornerpoint.Test (el.PNumMod (j+1));\n      int cp3 = cornerpoint.Test (el.PNumMod (j+2));\n      \n      ep1 |= cp1;\n      ep2 |= cp2;\n      ep3 |= cp3;\n      \n      \n      // (*testout) << \"cp = \" << cp1 << cp2 << cp3 << \", ep = \" << ep1 << ep2 << ep3 << endl;\n\n      int p[3] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2)};\n      if(ep1)\n\t{\n\t  INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); \n\t  INDEX_2 i2b=INDEX_2::Sort(p[0], p[2]); \n\t  if(!edges.Used(i2a) && !edges.Used(i2b)) \n\t    cp1 = 1; \n\t}\n      if(ep2)\n\t{\n\t  INDEX_2 i2a=INDEX_2::Sort(p[1], p[0]); \n\t  INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); \n\t  if(!edges.Used(i2a) && !edges.Used(i2b)) \n\t    cp2 = 1; \n\t}\n      if(ep3)\n\t{\n\t  INDEX_2 i2a=INDEX_2::Sort(p[2], p[0]); \n\t  INDEX_2 i2b=INDEX_2::Sort(p[2], p[1]); \n\t  if(!edges.Used(i2a) && !edges.Used(i2b)) \n\t    cp3= 1; \n\t}\t\t      \n      \n      \n      int isedge1=0, isedge2=0, isedge3=0; \n      if(dim == 3 )\n\t{\n\t  INDEX_2 i2;\n\t  i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1));\n\t  isedge1 = edges.Used (i2);\n\t  i2.Sort();\n\t  if(surf_edges.Used(i2) &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && \n\t     (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n\t    {\n\t      isedge1=1;\n\t      ep1 = 1; ep2=1;\n\t    }\n\t  \n\t  i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2));\n\t  isedge2 = edges.Used (i2);\n\t  i2.Sort();\n\t  if(surf_edges.Used(i2) &&  surf_edges.Get(i2)   != fd.SurfNr()+1 &&\n\t     (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n\t    {\n\t      isedge2=1;\n\t      ep2 = 1; ep3=1;\n\t    }\n\t  i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3));\n\t  isedge3 = edges.Used (i2);\n\t  i2.Sort();\n\t  if(surf_edges.Used(i2) &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && \n\t     (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n\t    {\n\t      isedge3=1;\n\t      ep1 = 1; ep3=1;\n\t    }\n\t  \n\t  // cout << \" isedge \" << isedge1 << \" \\t \" << isedge2 << \" \\t \" << isedge3 << endl;  \n\t\n\t  if (!sing_face)\n            {\n              /*\n                if (!isedge1)  { cp1 |= ep1; cp2 |= ep2; }\n                if (!isedge2)  { cp2 |= ep2; cp3 |= ep3; }\n                if (!isedge3)  { cp3 |= ep3; cp1 |= ep1; }\n              */\n              ep1 |= facepoint [el.PNumMod(j)] != 0;\n              ep2 |= facepoint [el.PNumMod(j+1)] != 0;\n              ep3 |= facepoint [el.PNumMod(j+2)] != 0;\n\t  \n\t  \n              isedge1 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1)));\n              isedge2 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+1), el.PNumMod(j+2)));\n              isedge3 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+2), el.PNumMod(j+3)));\n            }\n\t}\n      \n      if(dim ==2) \n\t{ \n\t  INDEX_2 i2;\n\t  i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1));\n\t  i2.Sort();\n\t  isedge1 = edges.Used (i2);\n\t  if(isedge1)\n\t    {\n\t      ep1 = 1; ep2=1;\n\t    }\n\t  \n\t  i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2));\n\t  i2.Sort();\n\t  isedge2 = edges.Used (i2);\n\t  if(isedge2)\n\t    {\n\t      ep2 = 1; ep3=1;\n\t    }\n\t  i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3));\n\t  i2.Sort();\n\t  isedge3 = edges.Used (i2);\n\t  if(isedge3)\n\t    {\n\t      ep1 = 1; ep3=1;\n\t    }\n\t  \n\t  \n\t}\n      \n\t\t  \n      /*\n        cout << \" used \" << face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))) << endl; \n\n        cout << \" isedge \" << isedge1 << \" \\t \" << isedge2 << \" \\t \" << isedge3 << endl; \n        cout << \" ep \" << ep1 << \"\\t\" << ep2 << \" \\t \" << ep3 << endl; \n        cout << \" cp \" << cp1 << \"\\t\" << cp2 << \" \\t \" << cp3 << endl; \n      */\n\t\t  \n\n      \n      if (isedge1 + isedge2 + isedge3 == 0)\n\t{\n\t  if (!ep1 && !ep2 && !ep3)\n\t    type = HP_TRIG;\n\t  \n\t  if (ep1 && !ep2 && !ep3)\n\t    type = HP_TRIG_SINGCORNER;\n\t  \n\t  if (ep1 && ep2 && !ep3)\n\t    type = HP_TRIG_SINGCORNER12;\n\t  \n\t  if (ep1 && ep2 && ep3)\n\t    {\n\t      if (dim == 2)\n                type = HP_TRIG_SINGCORNER123_2D;\n\t      else\n\t\ttype = HP_TRIG_SINGCORNER123;\n\t    }\n\t  \n\t  if (type != HP_NONE)\n\t    {\n\t      pnums[0] = el.PNumMod (j);\n\t      pnums[1] = el.PNumMod (j+1);\n\t      pnums[2] = el.PNumMod (j+2);\n\t      break;\n\t    }\n\t}\n      \n      if (isedge1 && !isedge2 && !isedge3)\n\t{\n\t  int code = 0;\n\t  if (cp1) code += 1;\n\t  if (cp2) code += 2;\n\t  if (ep3) code += 4;\n\t  \n\t  HPREF_ELEMENT_TYPE types[] =\n\t    {\n\t      HP_TRIG_SINGEDGE, \n\t      HP_TRIG_SINGEDGECORNER1, \n\t      HP_TRIG_SINGEDGECORNER2,\n\t      HP_TRIG_SINGEDGECORNER12, \n\t      HP_TRIG_SINGEDGECORNER3, \n\t      HP_TRIG_SINGEDGECORNER13, \n\t      HP_TRIG_SINGEDGECORNER23, \n\t      HP_TRIG_SINGEDGECORNER123, \n\t    };\n\t  type = types[code];\n\t  pnums[0] = el.PNumMod (j);\n\t  pnums[1] = el.PNumMod (j+1);\n\t  pnums[2] = el.PNumMod (j+2);\n\t  break;\n\t}\n      \n      \n      if (isedge1 && !isedge2 && isedge3)\n\t{\n\t  if (!cp3)\n\t    {\n\t      if (!cp2) type = HP_TRIG_SINGEDGES;\n\t      else      type = HP_TRIG_SINGEDGES2;\n\t    }\n\t  else\n\t    { \n\t      if (!cp2) type = HP_TRIG_SINGEDGES3;\n\t      else      type = HP_TRIG_SINGEDGES23;\n\t    }\n\t  \n\t  pnums[0] = el.PNumMod (j);\n\t  pnums[1] = el.PNumMod (j+1);\n\t  pnums[2] = el.PNumMod (j+2);\n\t  break;\n\t}\n       \n      if (isedge1 && isedge2 && isedge3)\n\t{\n\t  type = HP_TRIG_3SINGEDGES;\n\t  pnums[0] = el.PNumMod (j);\n\t  pnums[1] = el.PNumMod (j+1);\n\t  pnums[2] = el.PNumMod (j+2);\n\t  break;\n\t}\n    }\n  \n  for(int k=0;k<3;k++) el[k] = pnums[k]; \n  /*if(type != HP_NONE) \n    {\n     \n    cout << \" TRIG with pnums \" << pnums[0] << \"\\t\"  << \n    pnums[1] << \"\\t\"  << pnums[2] << endl; \n    cout << \" type \"  << type << endl; \n    }\n  */\n  return(type);\n}\n#endif\nHPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int>  & face_edges, \n\t\t\t\tINDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int dim, const FaceDescriptor & fd)\n{\n  HPREF_ELEMENT_TYPE type = HP_NONE; \n  \n  int ep1(-1), ep2(-1), ep3(-1), ep4(-1), cp1(-1), cp2(-1), cp3(-1), cp4(-1);\n  int isedge1, isedge2, isedge3, isedge4;\n\n  // *testout << \"edges = \" << edges << endl;\n  \n  for (int j = 1; j <= 4; j++)\n    {\n      ep1 = edgepoint.Test (el.PNumMod (j));\n      ep2 = edgepoint.Test (el.PNumMod (j+1));\n      ep3 = edgepoint.Test (el.PNumMod (j+2));\n      ep4 = edgepoint.Test (el.PNumMod (j+3));\n\n      if (dim == 2)\n        {\n          ep1 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j) } );\n          ep2 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+1) } );\n          ep3 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+2) });\n          ep4 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+3) });\n        }\n\n      cp1 = cornerpoint.Test (el.PNumMod (j));\n      cp2 = cornerpoint.Test (el.PNumMod (j+1));\n      cp3 = cornerpoint.Test (el.PNumMod (j+2));\n      cp4 = cornerpoint.Test (el.PNumMod (j+3));\n\n      ep1 |= cp1;\n      ep2 |= cp2;\n      ep3 |= cp3;\n      ep4 |= cp4;\n\t\t\n      PointIndex p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)};\n      //int epp[4] = { ep1, ep2, ep3, ep4}; \n      int cpp[4] = { cp1, cp2, cp3, cp4};\n      for(int k=0;k<0;k++)\n        {\n          INDEX_2 i2a=INDEX_2::Sort(p[k], p[(k+1)%4]); \n          INDEX_2 i2b=INDEX_2::Sort(p[k], p[(k-1)%4]); \n          if(!edges.Used(i2a) && !edges.Used(i2b)) \n            cpp[k] = 1; \n        }\n      cp1= cpp[0]; cp2=cpp[1]; cp3=cpp[2]; cp4=cpp[3];\n\t\t  \n\n      if(dim ==3) \n        { \n          PointIndices<2> i2 = PointIndices<2>(el.PNumMod (j), el.PNumMod (j+1));\n          // i2.Sort();\n          isedge1 = edges.Used (i2);\n          i2.Sort();\n          if(surf_edges.Used(i2)  &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && \n             (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n            {\n              isedge1=1;\n              ep1 = 1; ep2=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2));\n          // i2.Sort();\n          isedge2 = edges.Used (i2);\n          i2.Sort();\n          if(surf_edges.Used(i2)  &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && \n             (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n            {  \n              isedge2=1;\n              ep2=1; ep3=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3));\n          // i2.Sort();\n          isedge3 = edges.Used (i2); \n          i2.Sort();\n          if(surf_edges.Used(i2)   &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n            {\n              isedge3=1;\n              ep3=1; ep4=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4));\n          // i2.Sort();\n          isedge4 = edges.Used (i2);\n          i2.Sort();\n          if(surf_edges.Used(i2)  &&  surf_edges.Get(i2)   != fd.SurfNr()+1 && \n             (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) \n            { \n              isedge4=1;\n              ep4=1; ep1=1;\n            } \n\t\t    \n\n          //MH***********************************************************************************************************\n          if(ep1)\n            if(edgepoint.Test(p[0]))\n              {\n                INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); \n                INDEX_2 i2b=INDEX_2::Sort(p[0], p[3]); \n                if(!edges.Used(i2a) && !edges.Used(i2b)) \n                  cp1 = 1; \n              }\n          if(ep2)\n            if(edgepoint.Test(p[1]))\n              {\n                INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); \n                INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); \n                if(!edges.Used(i2a) && !edges.Used(i2b)) \n                  cp2 = 1; \n              }\n          if(ep3)\n            if(edgepoint.Test(p[2]))\n              {\n                INDEX_2 i2a=INDEX_2::Sort(p[2], p[1]); \n                INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); \n                if(!edges.Used(i2a) && !edges.Used(i2b)) \n                  cp3 = 1; \n              }\n          if(ep4)\n            if(edgepoint.Test(p[3]))\n              {\n                INDEX_2 i2a=INDEX_2::Sort(p[0], p[3]); \n                INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); \n                if(!edges.Used(i2a) && !edges.Used(i2b)) \n                  cp4 = 1; \n              }\n          //MH*****************************************************************************************************************************\n        }\n      else\n        { \n          INDEX_2 i2;\n          i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1));\n          i2.Sort();\n          isedge1 = edges.Used (i2);\n          if(isedge1)\n            {\n              ep1 = 1; ep2=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2));\n          i2.Sort();\n          isedge2 = edges.Used (i2);\n          if(isedge2)\n            {  \n              ep2=1; ep3=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3));\n          i2.Sort();\n          isedge3 = edges.Used (i2); \n\t\t      \n          if(isedge3)\n            {\n              ep3=1; ep4=1;\n            }\n          i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4));\n          i2.Sort();\n          isedge4 = edges.Used (i2);\n          if(isedge4)\n            { \n              ep4=1; ep1=1;\n            } \n        }\n\n      int sumcp = cp1 + cp2 + cp3 + cp4;\n      int sumep = ep1 + ep2 + ep3 + ep4;\n      int sumedge = isedge1 + isedge2 + isedge3 + isedge4;\n\n      *testout << \"isedge = \" << isedge1 << isedge2 << isedge3 << isedge4 << endl;\n      *testout << \"iscp = \" << cp1 << cp2 << cp3 << cp4 << endl;\n      *testout << \"isep = \" << ep1 << ep2 << ep3 << ep4 << endl;\n\n      switch (sumedge)\n        {\n        case 0:\n          {\n            switch (sumep)\n              {\n              case 0: \n                type = HP_QUAD; \n                break;\n              case 1: \n                if (ep1) type = HP_QUAD_SINGCORNER;\n                break; \n              case 2:\n                {\n                  if (ep1 && ep2) type = HP_QUAD_0E_2VA;\n                  if (ep1 && ep3) type = HP_QUAD_0E_2VB;\n                  break;\n                }\n              case 3: \n                if (!ep4) type = HP_QUAD_0E_3V; \n                break; \n              case 4: \n                type = HP_QUAD_0E_4V; \n                break; \n              }\n            break;\n          }\n        case 1:\n          {\n            if (isedge1)\n              {\n                switch (cp1+cp2+ep3+ep4)\n                  {\n                  case 0: \n                    type = HP_QUAD_SINGEDGE; \n                    break;\n                  case 1:\n                    {\n                      if (cp1) type = HP_QUAD_1E_1VA;\n                      if (cp2) type = HP_QUAD_1E_1VB;\n                      if (ep3) type = HP_QUAD_1E_1VC;\n                      if (ep4) type = HP_QUAD_1E_1VD; \n                      break; \n                    }\n                  case 2:\n                    {\n                      if (cp1 && cp2) type = HP_QUAD_1E_2VA; \n                      if (cp1 && ep3) type = HP_QUAD_1E_2VB; \n                      if (cp1 && ep4) type = HP_QUAD_1E_2VC; \n                      if (cp2 && ep3) type = HP_QUAD_1E_2VD; \n                      if (cp2 && ep4) type = HP_QUAD_1E_2VE; \n                      if (ep3 && ep4) type = HP_QUAD_1E_2VF; \n                      break; \n                    }\n                  case 3:\n                    {\n                      if (cp1 && cp2 && ep3) type = HP_QUAD_1E_3VA;\n                      if (cp1 && cp2 && ep4) type = HP_QUAD_1E_3VB;\n                      if (cp1 && ep3 && ep4) type = HP_QUAD_1E_3VC;\n                      if (cp2 && ep3 && ep4) type = HP_QUAD_1E_3VD;\n                      break;\n                    }\n                  case 4:\n                    {\n                      type = HP_QUAD_1E_4V; \n                      break;\n                    }\n                  }\n              }\n            break;\n          }\n        case 2:\n          {\n            if (isedge1 && isedge4)\n              {\n                if (!cp2 && !ep3 && !cp4)\n                  type = HP_QUAD_2E;\n\t\t\t  \n                if (cp2 && !ep3 && !cp4)\n                  type = HP_QUAD_2E_1VA;\n                if (!cp2 && ep3 && !cp4)\n                  type = HP_QUAD_2E_1VB;\n                if (!cp2 && !ep3 && cp4)\n                  type = HP_QUAD_2E_1VC;\n\n                if (cp2 && ep3 && !cp4)\n                  type = HP_QUAD_2E_2VA;\n                if (cp2 && !ep3 && cp4)\n                  type = HP_QUAD_2E_2VB;\n                if (!cp2 && ep3 && cp4)\n                  type = HP_QUAD_2E_2VC;\n\n                if (cp2 && ep3 && cp4)\n                  type = HP_QUAD_2E_3V;\n              }\n            if (isedge1 && isedge3)\n              {\n                switch (sumcp)\n                  {\n                  case 0: \n                    type = HP_QUAD_2EB_0V; break;\n                  case 1:\n                    {\n                      if (cp1) type = HP_QUAD_2EB_1VA; \n                      if (cp2) type = HP_QUAD_2EB_1VB; \n                      break;\n                    }\n                  case 2:\n                    {\n                      if (cp1 && cp2) { type = HP_QUAD_2EB_2VA; }\n                      if (cp1 && cp3) { type = HP_QUAD_2EB_2VB; }\n                      if (cp1 && cp4) { type = HP_QUAD_2EB_2VC; }\n                      if (cp2 && cp4) { type = HP_QUAD_2EB_2VD; }\n                      break;\n                    }\n                  case 3:\n                    {\n                      if (cp1 && cp2 && cp3) { type = HP_QUAD_2EB_3VA; }\n                      if (cp1 && cp2 && cp4) { type = HP_QUAD_2EB_3VB; }\n                      break;\n                    }\n                  case 4:\n                    {\n                      type = HP_QUAD_2EB_4V; break;\n                    }\n                  }\n              }\n            break;\n          }\n\n        case 3:\n          {\n            if (isedge1 && isedge2 && isedge4)\n              {\n                if (!cp3 && !cp4) type = HP_QUAD_3E;\n                if (cp3 && !cp4) type = HP_QUAD_3E_3VA;\n                if (!cp3 && cp4) type = HP_QUAD_3E_3VB;\n                if (cp3 && cp4) type = HP_QUAD_3E_4V;\n              }\n            break;\n          }\n\n        case 4:\n          {\n            type = HP_QUAD_4E;\n            break;\n          }\n        }\n\n      if (type != HP_NONE)\n        {\n          int pnums[4]; \n          pnums[0] = el.PNumMod (j); \n          pnums[1] = el.PNumMod (j+1);\n          pnums[2] = el.PNumMod (j+2); \n          pnums[3] = el.PNumMod (j+3);\n          for (int k=0;k<4;k++) el[k] = pnums[k]; \n\t\n          /*  cout << \" QUAD with pnums \" << pnums[0] << \"\\t\"  << \n              pnums[1] << \"\\t\"  << pnums[2] << \"\\t\"  << pnums[3] \n              << endl << \" of type \" << type << endl; */\n\t\t   \t\t      \n          break;\n        }\n    }\n  if (type == HP_NONE)\n    {\n      (*testout) << \"undefined element\" << endl\n                 << \"cp = \" << cp1 << cp2 << cp3 << cp4 << endl\n                 << \"ep = \" << ep1 << ep2 << ep3 << ep4 << endl\n                 << \"isedge = \" << isedge1 << isedge2 << isedge3 \n                 << isedge4 << endl;\n    }\n\t    \n  *testout << \"quad type = \" << type << endl;\n\n  return type;  \n}\t    \n\n\nHPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                               TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                               INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n  HPREF_ELEMENT_TYPE type = HP_NONE;\n  \n  // implementation only for HP_HEX_1F_0E_0V\n  //                         HP_HEX_1FA_1FB_0E_0V\n  //                         HP_HEX \n  // up to now other cases are refine dummies \n  \n  // indices of bot,top-faces combinations\n  int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; \n  int p[8]; \n  const ELEMENT_FACE * elfaces  = MeshTopology::GetFaces1 (HEX);\n  const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (HEX);\n  \n  for(int m=0;m<6 && type == HP_NONE;m++) \n    for(int j=0;j<4 && type == HP_NONE;j++) \n      { \n\tint point_sing[8]={0,0,0,0,0,0,0,0}; \n\tint face_sing[6] = {0,0,0,0,0,0};\n\tint edge_sing[12] = {0,0,0,0,0,0,0,0,0,0,0,0};\n\tint spoint=0, sface=0, sedge=0; \n\tfor(int l=0;l<4;l++) \n\t  {\n\t    p[l] = elfaces[index[m][0]][(4-j-l)%4]; \n\t    p[l+4] = elfaces[index[m][1]][(j+l)%4];\n\t  }\n\t\n\tfor(int l=0;l<8;l++) \n\t  if(cornerpoint.Test(el.PNum(p[l])))  \n\t    { \n\t      point_sing[p[l]-1]=3;\n\t      spoint++; \n\t    }\n\t  else if(edgepoint.Test(el.PNum(p[l]))) point_sing[p[l]-1]=2;\n\t  else if (facepoint[el.PNum(p[l])] == -1 || facepoint[el.PNum(p[l])] == el.GetIndex())\n\t    point_sing[p[l]-1] = 1;   \n\t\n\tfor(int k=0;k<12;k++)\n          {\n            INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); \n            if (edges.Used(i2)) \n              { \n                edge_sing[k] = 2;\n                sedge++; \n              }\n            else edge_sing[k] = face_edges.Used(i2);\n          }\n\t\n\tfor (int k=0;k<6;k++)\n          {\n            INDEX_3 i3; \n\t  \n\t\n            INDEX_4  i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); \n            i4.Sort();\n            i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); \n\t  \n            if (faces.Used (i3))\n              {\n\t      \n                int domnr = faces.Get(i3); \n                if (domnr == -1 || domnr == el.GetIndex())\n                  {\n                    face_sing[k] = 1;\n                    sface++;\n                  }\n\t      \n              } \n          } \n\t\n\tif(!sface && !sedge && !spoint) type = HP_HEX; \n\tif(!sedge && !spoint) \n\t  {\n\t    if(face_sing[0] && face_sing[2] && sface==2) \n\t      type = HP_HEX_1FA_1FB_0E_0V; \n\t    if (face_sing[0] && sface==1)  \n\t      type = HP_HEX_1F_0E_0V; \n\t  }\n\t\n\tel.type=type; \n\n\tif(type != HP_NONE) \n\t  {\n\t    int pnums[8]; \n\t    for(int l=0;l<8;l++) pnums[l] = el[p[l]-1];\n\t    for(int l=0;l<8;l++) el[l] = pnums[l];\n\t    /* cout << \" HEX with pnums \" << pnums[0] << \"\\t\"  << \n               pnums[1] << \"\\t\"  << pnums[2] << \"\\t\"  << pnums[3] << \"\\t\"  << \n               pnums[4] << \"\\t\"  <<  pnums[5] << endl << \" of type \" << type << endl; */\n\t    break; \n\t  }\n      }\n  \n  return (type); \n\n}\n\n\n\n\n\n\nHPREF_ELEMENT_TYPE ClassifyHex7 (HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                 TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,\n                                 INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                                 INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n  // HPREF_ELEMENT_TYPE type = HP_NONE;\n  \n  // no singular\n  // singular bottom\n  // singular top\n  \n  // indices of bot,top-faces combinations\n  // int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; \n  // int p[8]; \n  // const ELEMENT_FACE * elfaces  = MeshTopology::GetFaces1 (HEX);\n  // const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (HEX);\n\n  INDEX_4 fbot4 = { el.pnums[0], el.pnums[1], el.pnums[2], el.pnums[3] };\n  INDEX_3 ftop = { el.pnums[4], el.pnums[5], el.pnums[6] };\n  fbot4.Sort();\n  INDEX_3 fbot = { fbot4[0], fbot4[1], fbot4[2] };\n  ftop.Sort();\n  \n  bool singbot = faces.Used(fbot);\n  bool singtop = faces.Used(ftop);\n\n  if (singbot)\n    el.type =  HP_HEX7_1FA;\n  else if (singtop)\n    el.type = HP_HEX7_1FB;\n  else\n    el.type = HP_HEX7;\n\n  return el.type;\n}\n\n\n\n\n\nHPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,\n                                INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                                INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n  \n  int cp1 = cornerpoint.Test (hpel[0]);\n  int cp2 = cornerpoint.Test (hpel[1]);\n  \n  INDEX_2 i2;\n  i2 = INDEX_2(hpel[0], hpel[1]);\n  i2.Sort();\n  if (!edges.Used (i2))\n    {\n      cp1 = edgepoint.Test (hpel[0]);\n      cp2 = edgepoint.Test (hpel[1]);\n    }\n  \n  if(!edges.Used(i2) && !face_edges.Used(i2))\n    {\n      if(facepoint[hpel[0]]!=0) cp1=1; \n      if(facepoint[hpel[1]]!=0) cp2=1; \n    }\n  \n  if(edges.Used(i2) && !face_edges.Used(i2))\n    {\n      if(facepoint[hpel[0]]) cp1 = 1; \n      if(facepoint[hpel[1]]) cp2 = 1; \n    }\n  \n  if (!cp1 && !cp2)\n    hpel.type = HP_SEGM;\n  else if (cp1 && !cp2)\n    hpel.type = HP_SEGM_SINGCORNERL;\n  else if (!cp1 && cp2)\n    hpel.type = HP_SEGM_SINGCORNERR;\n  else\n    hpel.type = HP_SEGM_SINGCORNERS;\n  \n  // cout << \" SEGM found with \" << hpel[0] << \" \\t\" << hpel[1] << endl << \" of type \" << hpel.type << endl; \n  return(hpel.type) ; \n} \n\n\nHPREF_ELEMENT_TYPE ClassifyPyramid(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n                                   TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,\n                                   INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n                                   INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)\n{\n  // *testout << \"classify pyramid, pnums = \";\n  // for (int i = 0; i < 5; i++) *testout << el.pnums[i] << \" \";\n  // *testout << endl;\n\n  \n  HPREF_ELEMENT_TYPE type = HP_NONE;\n  \n  // implementation only for HP_PYRAMID\n  //                         HP_PYRAMID_0E_1V\n  //                         HP_PYRAMID_EDGES\n  //                         HP_PYRAMID_1FB_0E_1VA\n  // up to now other cases are refine dummies \n  \n  // indices of bot,top-faces combinations\n  // int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; \n\n  const ELEMENT_FACE * elfaces  = MeshTopology::GetFaces1 (PYRAMID);\n  const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (PYRAMID);\n  \n  int point_sing[5]={0,0,0,0,0}; \n  int face_sing[5] = {0,0,0,0,0};\n  int edge_sing[8] = {0,0,0,0,0,0,0,0};\n  \n  int spoint=0, sedge=0, sface=0; \n   \n  for(int m=0;m<4 && type == HP_NONE;m++) \n    {\n      *testout << \"m = \" << m << endl;\n      int p[5] = {m%4, m%4+1, m%4+2, m%4+3, 4}; \n\n      for(int l=0;l<5;l++) \n\t{\n\t  if(cornerpoint.Test(el.pnums[p[l]]))  \n\t    point_sing[l]=3;\n\t  \n          else if(edgepoint.Test(el.pnums[p[l]]))\n\t    point_sing[l]=2;\n\t  \n\t  else if (facepoint[el.pnums[p[l]]] == -1 || facepoint[el.pnums[p[l]]] == el.GetIndex())\n\t    point_sing[l] = 1;   \n\t  \n\t  spoint += point_sing[l]; \n\t}\n      \n      for(int k=0;k<8;k++)\n\t{\n\t  INDEX_2 i2 = INDEX_2 :: Sort(el.pnums[p[eledges[k][0]-1]],\n\t\t\t\t       el.pnums[p[eledges[k][1]-1]]); \n\t  if (edges.Used(i2)) \n\t    edge_sing[k] = 2;\n\t  else \n\t    edge_sing[k] = face_edges.Used(i2);\n\t  \n\t  sedge += edge_sing[k]; \n\t}\n  \n      for (int k=0;k<5;k++)\n\t{\n\t  INDEX_3 i3;\n          /*\n\t  INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]], el.pnums[p[elfaces[k][1]-1]], el.pnums[p[elfaces[k][2]-1]],\n\t\t\t\tel.pnums[p[elfaces[k][3]-1]]); \n\t  i4.Sort();\n\t  i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); \n\t  */\n          if (k < 4)\n            {\n              i3 = INDEX_3(el.pnums[p[elfaces[k][0]-1]], el.pnums[p[elfaces[k][1]-1]], el.pnums[p[elfaces[k][2]-1]]);\n              i3.Sort();\n            }\n          else\n            {\n              INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]], el.pnums[p[elfaces[k][1]-1]], el.pnums[p[elfaces[k][2]-1]],\n                                   el.pnums[p[elfaces[k][3]-1]]); \n              i4.Sort();\n              i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); \n            }\n\n          \n\t  if (faces.Used (i3))\n\t    {\n\t      \n\t      int domnr = faces.Get(i3); \n\t      if (domnr == -1 || domnr == el.GetIndex())\n\t\tface_sing[k] = 1;\n\t    } \n\t  sface +=face_sing[k]; \n\t} \n\n      *testout << \"point_sing: \";\n      for (int k = 0; k < 5; k++) *testout << point_sing[k] << \" \";\n      *testout << endl;\n      \n      *testout << \"edge_sing: \";\n      for (int k = 0; k < 4; k++) *testout << edge_sing[k] << \" \";\n      *testout << endl;\n      \n      *testout << \"face_sing: \";\n      for (int k = 0; k < 5; k++) *testout << face_sing[k] << \" \";\n      *testout << endl;\n      \n      if(!sface && !spoint && !sedge) return(HP_PYRAMID); \n      \n      if(!sface && !sedge && point_sing[p[0]] == spoint) \n\ttype = HP_PYRAMID_0E_1V; \n      \n      if(!sface && edge_sing[0] + edge_sing[2] == sedge && \n\t spoint == point_sing[0] + point_sing[1] + point_sing[3]) \n\ttype = HP_PYRAMID_EDGES; \n      \n      if(sface && sface == face_sing[0] && spoint == point_sing[4] + 2)\n        {\n          if (point_sing[4] == 1)\n            type = HP_PYRAMID_1FB_0E_0V;\n          else\n            type = HP_PYRAMID_1FB_0E_1VA;\n        }\n      \n      \n      if(type != HP_NONE) \n\t{ \n\t  int pnums[8]; \n\t  for(int l=0;l<5;l++) pnums[l] = el[p[l]];\n\t  for(int l=0;l<5;l++) el[l] = pnums[l];\n\t  el.type=type; \n\t  break; \n\t} \n    }\n  \n  return (type); \n  \n}\n"
  },
  {
    "path": "libsrc/meshing/clusters.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"clusters.hpp\"\n\nnamespace netgen\n{\n\n  AnisotropicClusters ::  AnisotropicClusters (const Mesh & amesh)\n    : mesh(amesh)\n  {\n    ;\n  }\n\n  AnisotropicClusters ::  ~AnisotropicClusters ()\n  {\n    ;\n  }\n  \n  void AnisotropicClusters ::  Update()\n  {\n    static Timer timer(\"clusters\");\n    // static int timer1 = NgProfiler::CreateTimer (\"clusters1\");\n    // static int timer2 = NgProfiler::CreateTimer (\"clusters2\");\n    // static int timer3 = NgProfiler::CreateTimer (\"clusters3\");\n    RegionTimer reg (timer);\n    constexpr auto PI0 = IndexBASE<PointIndex>();\n\n    const MeshTopology & top = mesh.GetTopology();\n\n    auto id = this->mesh.GetCommunicator().Rank();\n    // auto ntasks = this->mesh.GetCommunicator().Size();\n\n    bool hasedges = top.HasEdges();\n    bool hasfaces = top.HasFaces();\n\n    if (!hasedges || !hasfaces) return;\n\n    if (id == 0)\n      PrintMessage (3, \"Update clusters\");\n\n    nv = mesh.GetNV();\n    ned = top.GetNEdges();\n    nfa = top.GetNFaces();\n    ne = mesh.GetNE();\n    // int nse = mesh.GetNSE();\n\n    cluster_reps.SetSize (nv+ned+nfa+ne);\n    cluster_reps = -1;\n\n    NgArray<int> llist (nv+ned+nfa+ne);\n    llist = 0;\n  \n    NgArray<int> nnums, ednums, fanums;\n    int changed;\n\n    // NgProfiler::StartTimer(timer1);    \n\n  \n    /*\n    for (int i = 1; i <= ne; i++)\n      {\n\tconst Element & el = mesh.VolumeElement(i);\n\tELEMENT_TYPE typ = el.GetType();\n      \n\ttop.GetElementEdges (i, ednums);\n\ttop.GetElementFaces (i, fanums);\n      \n\tint elnv = top.GetNVertices (typ);\n\tint elned = ednums.Size();\n\tint elnfa = fanums.Size();\n\t  \n\tnnums.SetSize(elnv+elned+elnfa+1);\n\tfor (int j = 1; j <= elnv; j++)\n\t  nnums.Elem(j) = el.PNum(j);\n\tfor (int j = 1; j <= elned; j++)\n\t  nnums.Elem(elnv+j) = nv+ednums.Elem(j);\n\tfor (int j = 1; j <= elnfa; j++)\n\t  nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j);\n\tnnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i;\n\n\tfor (int j = 0; j < nnums.Size(); j++)\n\t  cluster_reps.Elem(nnums[j]) = nnums[j];\n      }\n    */\n    ngcore::ParallelForRange\n      (mesh.VolumeElements().Range(),\n       [&] (auto myrange)\n       {\n         NgArray<int> nnums; // , ednums, fanums;\n         for (auto i_ : myrange)\n           {\n             int i = i_-IndexBASE<ElementIndex>()+1;\n             const Element & el = mesh.VolumeElement(i_);\n             ELEMENT_TYPE typ = el.GetType();\n             \n             // top.GetElementEdges (i, ednums);\n             // auto ednums = top.GetEdges (ElementIndex(i_));\n             auto ednums = top.GetEdges (i_);\n             // top.GetElementFaces (i, fanums);\n             // auto fanums = top.GetFaces (ElementIndex(i_));\n             auto fanums = top.GetFaces (i_);\n             \n             int elnv = top.GetNVertices (typ);\n             int elned = ednums.Size();\n             int elnfa = fanums.Size();\n             \n             nnums.SetSize(elnv+elned+elnfa+1);\n             for (int j = 0; j < elnv; j++)\n               nnums[j] = el[j]+1-PI0;\n             for (int j = 0; j < elned; j++)\n               nnums[elnv+j] = nv+ednums[j]+1;\n             for (int j = 0; j < elnfa; j++)\n               nnums[elnv+elned+j] = nv+ned+fanums[j]+1;\n             nnums[elnv+elned+elnfa] = nv+ned+nfa+i;\n\n             for (int j = 0; j < nnums.Size(); j++)\n               cluster_reps.Elem(nnums[j]) = nnums[j];\n           }\n       }, ngcore::TasksPerThread(4));\n    \n    // NgProfiler::StopTimer(timer1);\n    // NgProfiler::StartTimer(timer2);      \n    /*\n    for (int i = 1; i <= nse; i++)\n      {\n\tconst Element2d & el = mesh.SurfaceElement(i);\n\tELEMENT_TYPE typ = el.GetType();\n      \n\ttop.GetSurfaceElementEdges (i, ednums);\n\tint fanum = top.GetSurfaceElementFace (i);\n      \n\tint elnv = top.GetNVertices (typ);\n\tint elned = ednums.Size();\n\t  \n\tnnums.SetSize(elnv+elned+1);\n\tfor (int j = 1; j <= elnv; j++)\n\t  nnums.Elem(j) = el.PNum(j)+1-PI0;\n\tfor (int j = 1; j <= elned; j++)\n\t  nnums.Elem(elnv+j) = nv+ednums.Elem(j);\n\tnnums.Elem(elnv+elned+1) = fanum;\n\n\tfor (int j = 0; j < nnums.Size(); j++)\n\t  cluster_reps.Elem(nnums[j]) = nnums[j];\n      }\n    */\n\n    \n    ngcore::ParallelForRange\n      (mesh.SurfaceElements().Range(),\n       [&] (auto myrange)\n       {\n         NgArrayMem<int,9> nnums; // , ednums;\n         for (SurfaceElementIndex i_ : myrange)\n           {\n             // int i = i_+1;\n             const Element2d & el = mesh[i_]; // .SurfaceElement(i);\n             ELEMENT_TYPE typ = el.GetType();\n             \n             // top.GetSurfaceElementEdges (i, ednums);\n             auto ednums = top.GetEdges (i_);\n             // cout << \"ednums = \" << ednums << endl;\n             \n             int fanum = top.GetFace(i_)+1;\n             \n             int elnv = top.GetNVertices (typ);\n             int elned = ednums.Size();\n             \n             nnums.SetSize(elnv+elned+1);\n             for (int j = 0; j < elnv; j++)\n               nnums[j] = el[j]+1-PI0;\n             for (int j = 0; j < elned; j++)\n               nnums[elnv+j] = nv+ednums[j]+1;\n             nnums[elnv+elned] = fanum;             \n             \n             for (int j = 0; j < nnums.Size(); j++)\n               cluster_reps.Elem(nnums[j]) = nnums[j];\n           }\n       }, ngcore::TasksPerThread(4));\n\n    \n    // NgProfiler::StopTimer(timer2);\n    // NgProfiler::StartTimer(timer3);      \n\n    \n    static const int hex_cluster[] =\n      { \n\t1, 2, 3, 4, 1, 2, 3, 4, \n\t5, 6, 7, 8, 5, 6, 7, 8, 1, 2, 3, 4, \n\t9, 9, 5, 8, 6, 7, \n\t9\n      };\n\n    static const int prism_cluster[] =\n      { \n\t1, 2, 3, 1, 2, 3,\n\t4, 5, 6, 4, 5, 6, 3, 1, 2,\n\t7, 7, 4, 5, 6, \n\t7\n      };\n\n    static const int pyramid_cluster[] =\n      { \n\t1, 2, 2, 1, 3,\n\t4, 2, 1, 4, 6, 5, 5, 6,\n\t7, 5, 7, 6, 4, \n\t7\n      };\n    static const int tet_cluster14[] =\n      { 1, 2, 3, 1,   1, 4, 5, 4, 5, 6,   7, 5, 4, 7, 7 };\n  \n    static const int tet_cluster12[] =\n      { 1, 1, 2, 3,   4, 4, 5, 1, 6, 6,   7, 7, 4, 6, 7 };\n\n    static const int tet_cluster13[] =\n      { 1, 2, 1, 3,   4, 6, 4, 5, 1, 5,   7, 4, 7, 5, 7 };\n\n    static const int tet_cluster23[] =\n      { 2, 1, 1, 3, 6, 5, 5, 4, 4, 1, 5, 7, 7, 4, 7 };\n\n    static const int tet_cluster24[] =\n      { 2, 1, 3, 1, 4, 1, 5, 4, 6, 5, 5, 7, 4, 7, 7 };\n\n    static const int tet_cluster34[] =\n      { 2, 3, 1, 1, 4, 5, 1, 6, 4, 5, 5, 4, 7, 7, 7 };\n\n    // int cnt = 0;\n    do\n      {\n        static Timer t(\"update cluster, identify\");\n        RegionTimer rtr(t);\n\t// cnt++;\n\tchanged = 0;\n      \n\tfor (int i = 1; i <= ne; i++)\n\t  {\n            ElementIndex ei(i-1);\n            \n\t    const Element & el = mesh[ei];\n\t    ELEMENT_TYPE typ = el.GetType();\n\t  \t  \n\t    const int * clustertab = NULL;\n\t    switch (typ)\n\t      {\n\t      case PRISM:\n\t      case PRISM12:\n\t\tclustertab = prism_cluster;\n\t\tbreak;\n\t      case HEX: \n\t\tclustertab = hex_cluster; \n\t\tbreak; \n\t      case PYRAMID:\n\t\tclustertab = pyramid_cluster;\n\t\tbreak;\n\t      case TET:\n\t      case TET10:\n\t\tif (cluster_reps.Get(el.PNum(1)+1-PI0) == \n\t\t    cluster_reps.Get(el.PNum(2)+1-PI0))\n\t\t  clustertab = tet_cluster12;\n\t\telse if (cluster_reps.Get(el.PNum(1)+1-PI0) == \n\t\t\t cluster_reps.Get(el.PNum(3)+1-PI0))\n\t\t  clustertab = tet_cluster13;\n\t\telse if (cluster_reps.Get(el.PNum(1)+1-PI0) == \n\t\t\t cluster_reps.Get(el.PNum(4)+1-PI0))\n\t\t  clustertab = tet_cluster14;\n\t\telse if (cluster_reps.Get(el.PNum(2)+1-PI0) == \n\t\t\t cluster_reps.Get(el.PNum(3)+1-PI0))\n\t\t  clustertab = tet_cluster23;\n\t\telse if (cluster_reps.Get(el.PNum(2)+1-PI0) == \n\t\t\t cluster_reps.Get(el.PNum(4)+1-PI0))\n\t\t  clustertab = tet_cluster24;\n\t\telse if (cluster_reps.Get(el.PNum(3)+1-PI0) == \n\t\t\t cluster_reps.Get(el.PNum(4)+1-PI0))\n\t\t  clustertab = tet_cluster34;\n\n\t\telse\n\t\t  clustertab = NULL;\n\t\tbreak;\n\t      default:\n\t\tclustertab = NULL;\n\t      }\n\t  \n\t    if (clustertab)\n              {\n                // top.GetElementEdges (i, ednums);\n                // top.GetElementFaces (i, fanums);\n                auto ednums = top.GetEdges (ei);\n                auto fanums = top.GetFaces (ei);\n                \n                int elnv = top.GetNVertices (typ);\n                int elned = ednums.Size();\n                int elnfa = fanums.Size();\n                \n                nnums.SetSize(elnv+elned+elnfa+1);\n                for (int j = 0; j < elnv; j++)\n                  nnums[j] = el[j]+1-IndexBASE<PointIndex>();\n                for (int j = 0; j < elned; j++)\n                  nnums[elnv+j] = nv+ednums[j]+1;\n                for (int j = 0; j < elnfa; j++)\n                  nnums[elnv+elned+j] = nv+ned+fanums[j]+1;\n                nnums[elnv+elned+elnfa] = nv+ned+nfa+i;\n                \n                \n\t      for (int j = 0; j < nnums.Size(); j++)\n\t\tfor (int k = 0; k < j; k++)\n\t\t  if (clustertab[j] == clustertab[k])\n\t\t    {\n\t\t      int jj = nnums[j];\n\t\t      int kk = nnums[k];\n\n\t\t      if (cluster_reps.Get(kk) < cluster_reps.Get(jj))\n\t\t\tswap (jj,kk);\n\n\t\t      if (cluster_reps.Get(jj) < cluster_reps.Get(kk))\n\t\t\t{\n\t\t\t  /*\n\t\t\t  cluster_reps.Elem(kk) = cluster_reps.Get(jj);\n\t\t\t  changed = 1;\n\t\t\t  */\n\t\t\t  \n\t\t\t  int rep  = cluster_reps.Get(jj);\n\t\t\t  int next = cluster_reps.Get(kk);\n\t\t\t  do\n\t\t\t    {\n\t\t\t      int cur = next;\n\t\t\t      next = llist.Elem(next);\n\t\t\t\t\n\t\t\t      cluster_reps.Elem(cur) = rep;\n\t\t\t      llist.Elem(cur) = llist.Elem(rep);\n\t\t\t      llist.Elem(rep) = cur;\n\t\t\t    }\n\t\t\t  while (next);\n\t\t\t  changed = 1;\n\t\t\t}\n\t\t    }\n              }\n\n\t    /*\n\t      if (clustertab)\n\t      {\n\t      if (typ == PYRAMID)\n\t      (*testout) << \"pyramid\";\n\t      else if (typ == PRISM || typ == PRISM12)\n\t      (*testout) << \"prism\";\n\t      else if (typ == TET || typ == TET10)\n\t      (*testout) << \"tet\";\n\t      else\n\t      (*testout) << \"unknown type\" << endl;\n\t\t\n\t      (*testout) << \", nnums  = \";\n\t      for (j = 0; j < nnums.Size(); j++)\n\t      (*testout) << \"node \" << j << \" = \" << nnums[j] << \", rep = \"\n\t      << cluster_reps.Get(nnums[j]) << endl;\n\t      }\n\t    */\n\t  }\n      }\n    while (changed);\n    // NgProfiler::StopTimer(timer3);\n    /*\n      (*testout) << \"cluster reps:\" << endl;\n      for (i = 1; i <= cluster_reps.Size(); i++)\n      {\n      (*testout) << i << \": \";\n      if (i <= nv)\n      (*testout) << \"v\" << i << \" \";\n      else if (i <= nv+ned)\n      (*testout) << \"e\" << i-nv << \" \";\n      else if (i <= nv+ned+nfa)\n      (*testout) << \"f\" << i-nv-ned << \" \";\n      else\n      (*testout) << \"c\" << i-nv-ned-nfa << \" \";\n      (*testout) << cluster_reps.Get(i) << endl;\n      }\n    */\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/clusters.hpp",
    "content": "#ifndef NETGEN_CLUSTERS_HPP\n#define NETGEN_CLUSTERS_HPP\n\n/**************************************************************************/\n/* File:   clusers.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   28. Apr. 01                                                    */\n/**************************************************************************/\n\n/*\n  Anisotropic clusters\n\n  nodes, edges, faces, elements\n*/\n\n#include \"meshclass.hpp\"\n\nnamespace netgen\n{\n\nclass AnisotropicClusters\n{\n  const Mesh & mesh;\n\n  int nv, ned, nfa, ne;\n\n  // connected nodes, nodes = vertices, edges, faces, elements\n  NgArray<int> cluster_reps;\n\npublic:\n  AnisotropicClusters (const Mesh & amesh);\n  ~AnisotropicClusters();\n\n  void Update();\n\n  int GetVertexRepresentant (int vnr) const\n  { return cluster_reps.Get(vnr); }\n  int GetEdgeRepresentant (int ednr) const\n  { return cluster_reps.Get(nv+ednr); }\n  int GetFaceRepresentant (int fnr) const\n  { return cluster_reps.Get(nv+ned+fnr); }\n  int GetElementRepresentant (int enr) const\n  { return cluster_reps.Get(nv+ned+nfa+enr); }\n};\n} // namespace netgen\n#endif // NETGEN_CLUSTERS_HPP\n"
  },
  {
    "path": "libsrc/meshing/curvedelems.cpp",
    "content": "#include <mystdlib.h>\n\n\n#include \"curvedelems.hpp\"\n#include \"basegeom.hpp\"\n#include \"hprefinement.hpp\"\n\n// #include \"meshing.hpp\"\n// #include \"../general/autodiff.hpp\"\n\n\nnamespace netgen\n{\n  using namespace std;\n  \n  //   bool rational = true;\n  static void ComputeGaussRule (int n, NgArray<double> & xi, NgArray<double> & wi)\n  {\n    xi.SetSize (n);\n    wi.SetSize (n);\n    \n    int m = (n+1)/2;\n    double p1, p2, p3;\n    double pp, z, z1;\n    for (int i = 1; i <= m; i++)\n      {\n\tz = cos ( M_PI * (i - 0.25) / (n + 0.5));\n\twhile(1)\n\t  {\n\t    p1 = 1; p2 = 0;\n\t    for (int j = 1; j <= n; j++)\n\t      {\n\t\tp3 = p2; p2 = p1;\n\t\tp1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j;\n\t      }\n\t    // p1 is legendre polynomial\n\t    \n\t    pp = n * (z*p1-p2) / (z*z - 1);\n\t    z1 = z;\n\t    z = z1-p1/pp;\n\t    \n\t    if (fabs (z - z1) < 1e-14) break;\n\t  }\n\t\n\txi[i-1] = 0.5 * (1 - z);\n\txi[n-i] = 0.5 * (1 + z);\n\twi[i-1] = wi[n-i] = 1.0 / ( (1  - z * z) * pp * pp);\n      }\n  }\n  \n  \n\n  // compute edge bubbles up to order n, x \\in (-1, 1)\n  // integrated Legendre pols, starting with order 2\n  template <typename T>\n  static void CalcEdgeShape (int n, T x, T * shape)\n  {\n    T p1 = x, p2 = -1, p3 = 0;\n    for (int j=2; j<=n; j++)\n      {\n\tp3=p2; p2=p1;\n\tp1=( (2*j-3) * x * p2 - (j-3) * p3) / j;\n\tshape[j-2] = p1;\n      } \n  }\n  template <typename T, typename FUNC>\n  static void CalcEdgeShapeLambda (int n, T x, FUNC func)\n  {\n    T p1(x), p2(-1.0), p3(0.0);\n    for (int j=2; j<=n; j++)\n      {\n\tp3=p2; p2=p1;\n\tp1=( (2*j-3) * x * p2 - (j-3) * p3) / j;\n\tfunc(j-2, p1);\n      } \n  }\n\n\n  template <typename T>\n  static void CalcEdgeDx (int n, T x, T * dshape)\n  {\n    T p1 = x, p2 = -1, p3 = 0;\n    T p1dx = 1, p2dx = 0, p3dx = 0;\n\n    for (int j=2; j<=n; j++)\n      {\n\tp3=p2; p2=p1;\n\tp3dx = p2dx; p2dx = p1dx;\n\n\tp1=( (2*j-3) * x * p2 - (j-3) * p3) / j;\n\tp1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;\n\n\tdshape[j-2] = p1dx;\n      }    \n  }\n\n  template <typename T>\n  static void CalcEdgeShapeDx (int n, T x, T * shape, T * dshape)\n  {\n    T p1 = x, p2 = -1, p3 = 0;\n    T p1dx = 1, p2dx = 0, p3dx = 0;\n\n    for (int j=2; j<=n; j++)\n      {\n\tp3=p2; p2=p1;\n\tp3dx = p2dx; p2dx = p1dx;\n\n\tp1=( (2*j-3) * x * p2 - (j-3) * p3) / j;\n\tp1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;\n\n\tshape[j-2] = p1;\n\tdshape[j-2] = p1dx;\n      }    \n  }\n\n  // compute L_i(x/t) * t^i\n  template <typename T>\n  static void CalcScaledEdgeShape (int n, T x, T t, T * shape)\n  {\n    static bool init = false;\n    static double coefs[100][2];\n    if (!init)\n      {\n        for (int j = 0; j < 100; j++)\n          {\n            coefs[j][0] = double(2*j+1)/(j+2);\n            coefs[j][1] = -double(j-1)/(j+2);\n          }\n        init = true;\n      }\n\n    T p1 = x, p2 = -1, p3 = 0;\n    T tt = t*t;\n    for (int j=0; j<=n-2; j++)\n      {\n\tp3=p2; p2=p1;\n        p1= coefs[j][0] * x * p2 + coefs[j][1] * tt*p3;\n\t// p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);\n\tshape[j] = p1;\n      }    \n  }\n  \n  template <typename T, typename FUNC>\n  static void CalcScaledEdgeShapeLambda (int n, T x, T t, FUNC func)\n  {\n    static bool init = false;\n    static double coefs[100][2];\n    if (!init)\n      {\n        for (int j = 0; j < 100; j++)\n          {\n            coefs[j][0] = double(2*j+1)/(j+2);\n            coefs[j][1] = -double(j-1)/(j+2);\n          }\n        init = true;\n      }\n\n    T p1(x), p2(-1.0), p3(0.0);\n    T tt = t*t;\n    for (int j=0; j<=n-2; j++)\n      {\n\tp3=p2; p2=p1;\n        p1= coefs[j][0] * x * p2 + coefs[j][1] * tt*p3;\n\t// p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);\n\tfunc(j, p1);\n      }    \n  }\n\n\n  \n  template <int DIST, typename T>\n  static void CalcScaledEdgeShapeDxDt (int n, T x, T t, T * dshape)\n  {\n    T p1 = x, p2 = -1, p3 = 0;\n    T p1dx = 1, p1dt = 0;\n    T p2dx = 0, p2dt = 0;\n    T p3dx = 0, p3dt = 0;\n     \n    for (int j=0; j<=n-2; j++)\n      {\n\tp3=p2; p3dx=p2dx; p3dt = p2dt;\n\tp2=p1; p2dx=p1dx; p2dt = p1dt;\n\n\tp1   = ( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);\n\tp1dx = ( (2*j+1) * (x * p2dx + p2) - t*t*(j-1) * p3dx) / (j+2);\n\tp1dt = ( (2*j+1) * x * p2dt - (j-1)* (t*t*p3dt+2*t*p3)) / (j+2);\n\n\t// shape[j] = p1;\n\tdshape[DIST*j  ] = p1dx;\n\tdshape[DIST*j+1] = p1dt;\n      }    \n  }\n\n\n  template <class Tx, class Tres>\n  static void LegendrePolynomial (int n, Tx x, Tres * values)\n  {\n    switch (n)\n      {\n      case 0:\n\tvalues[0] = 1;\n\tbreak;\n      case 1:\n\tvalues[0] = 1;\n\tvalues[1] = x;\n\tbreak;\n\n      default:\n\n\tif (n < 0) return;\n\n\tTx p1 = 1.0, p2 = 0.0, p3;\n\t\n\tvalues[0] = 1.0;\n\tfor (int j=1; j<=n; j++)\n\t  {\n\t    p3 = p2; p2 = p1;\n\t    p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j;\n\t    values[j] = p1;\n\t  }\n      }\n  }\n\n  template <class Tx, class Tt, class Tres>\n  static void ScaledLegendrePolynomial (int n, Tx x, Tt t, Tres * values)\n  {\n    switch (n)\n      {\n      case 0:\n\tvalues[0] = 1.0;\n\tbreak;\n\n      case 1:\n\tvalues[0] = 1.0;\n\tvalues[1] = x;\n\tbreak;\n\n      default:\n\n\tif (n < 0) return;\n\n\tTx p1 = 1.0, p2 = 0.0, p3;\n\tvalues[0] = 1.0;\n\tfor (int j=1; j<=n; j++)\n\t  {\n\t    p3 = p2; p2 = p1;\n\t    p1 = ((2.0*j-1.0)*x*p2 - t*t*(j-1.0)*p3) / j;\n\t    values[j] = p1;\n\t  }\n      }\n  }\n\n  class RecPol\n  {\n  protected:\n    int maxorder;\n    double *a, *b, *c;\n  public:\n    RecPol (int amaxorder)\n    {\n      maxorder = amaxorder;\n      a = new double[maxorder+1];\n      b = new double[maxorder+1];\n      c = new double[maxorder+1];\n    }\n    ~RecPol ()\n    {\n      delete [] a;\n      delete [] b;\n      delete [] c;\n    }\n    \n    template <class S, class T>\n    void Evaluate (int n, S x, T * values)\n    {\n      S p1(1.0), p2(0.0), p3;\n      \n      if (n >= 0) \n\tp2 = values[0] = 1.0;\n      if (n >= 1) \n\tp1 = values[1] = a[0]+b[0]*x;\n      \n      for (int i  = 1; i < n; i++)\n\t{\n\t  p3 = p2; p2=p1;\n\t  p1 = (a[i]+b[i]*x)*p2-c[i]*p3;\n\t  values[i+1] = p1;\n\t}\n    }\n\n    template <class S, class FUNC>\n    void EvaluateLambda (int n, S x, FUNC func)\n    {\n      S p1(1.0), p2(0.0), p3;\n      \n      if (n >= 0)\n        {\n          // p2 = values[0] = 1.0;\n          p2 = 1.0;\n          func(0,p2);\n        }\n      if (n >= 1)\n        {\n          // p1 = values[1] = a[0]+b[0]*x;\n          p1 = a[0]+b[0]*x;\n          func(1,p1);\n        }\n      \n      for (int i  = 1; i < n; i++)\n\t{\n\t  p3 = p2; p2=p1;\n\t  p1 = (a[i]+b[i]*x)*p2-c[i]*p3;\n\t  // values[i+1] = p1;\n          func(i+1, p1);\n\t}\n    }\n\n    \n    template <class S, class T>\n    void EvaluateScaled (int n, S x, S y, T * values)\n    {\n      S p1(1.0), p2(0.0), p3;\n      \n      if (n >= 0) \n\tp2 = values[0] = 1.0;\n      if (n >= 1) \n\tp1 = values[1] = a[0]*y+b[0]*x;\n      \n      for (int i  = 1; i < n; i++)\n\t{\n\t  p3 = p2; p2=p1;\n\t  p1 = (a[i]*y+b[i]*x)*p2-c[i]*y*y*p3;\n\t  values[i+1] = p1;\n\t}\n    }\n\n    template <class S, class FUNC>\n    void EvaluateScaledLambda (int n, S x, S y, FUNC func)\n    {\n      S p1(1.0), p2(0.0), p3;\n      \n      if (n >= 0)\n        {\n          p2 = 1.0;\n          func(0, p2);\n        }\n      if (n >= 1)\n        {\n          p1 = a[0]*y+b[0]*x;\n          func(1, p1);\n        }\n      \n      for (int i = 1; i < n; i++)\n\t{\n\t  p3 = p2; p2=p1;\n\t  p1 = (a[i]*y+b[i]*x)*p2-c[i]*y*y*p3;\n\t  func(i+1, p1);\n\t}\n    }\n\n\n  };\n\n  class JacobiRecPol : public RecPol\n  {\n  public:\n    JacobiRecPol (int amo, double al, double be)\n      : RecPol (amo)\n    {\n      for (int i = 0; i <= maxorder; i++)\n\t{\n\t  double den = 2*(i+1)*(i+al+be+1)*(2*i+al+be);\n\t  a[i] = (2*i+al+be+1)*(al*al-be*be) / den;\n\t  b[i] = (2*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / den;\n\t  c[i] = 2*(i+al)*(i+be)*(2*i+al+be+2) / den;\n\t}\n    }\n  };\n  \n  /*\n  template <class S, class T>\n  inline void JacobiPolynomial (int n, S x, double alpha, double beta, T * values)\n  {\n    S p1 = 1.0, p2 = 0.0, p3;\n\n    if (n >= 0) \n      p2 = values[0] = 1.0;\n    if (n >= 1) \n      p1 = values[1] = 0.5 * (2*(alpha+1)+(alpha+beta+2)*(x-1));\n\n    for (int i  = 1; i < n; i++)\n      {\n        p3 = p2; p2=p1;\n        p1 =\n          1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *\n          ( \n           ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) + \n             (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x) \n           * p2\n           - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3\n           );\n        values[i+1] = p1;\n      }\n  }\n  */\n  \n  /*\n  template <class S, class St, class T>\n  inline void ScaledJacobiPolynomial (int n, S x, St t, double alpha, double beta, T * values)\n  {\n  // S p1 = 1.0, p2 = 0.0, p3;\n  // if (n >= 0) values[0] = 1.0;\n\n    S p1(1.0), p2(0.0), p3;\n\n    if (n >= 0) \n      p2 = values[0] = 1.0;\n    if (n >= 1) \n      p1 = values[1] = 0.5 * (2*(alpha+1)*t+(alpha+beta+2)*(x-t));\n\n    for (int i=1; i < n; i++)\n      {\n        p3 = p2; p2=p1;\n        p1 =\n          1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *\n          ( \n           ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t + \n             (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x) \n           * p2\n           - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3\n           );\n        values[i+1] = p1;\n      }\n  }\n  */\n  \n  // Jacobi polynomials alpah, beta=2\n  struct JacobiRecPols\n  {\n    static constexpr size_t N = 100;\n    ArrayMem<unique_ptr<JacobiRecPol>, N> jacpols;\n\n    JacobiRecPols()\n    {\n      jacpols.SetSize (N);\n      for (int i = 0; i < N; i++)\n        jacpols[i] = make_unique<JacobiRecPol>(N, i, 2);\n    }\n\n    const unique_ptr<JacobiRecPol> & operator[] (int i) { \n      return jacpols[i];\n    }\n  };\n\n  static JacobiRecPols jacpols2;\n  \n  static JacobiRecPol jacpol00(100,0,0);\n  static JacobiRecPol jacpol11(100,1,1);\n  static JacobiRecPol jacpol22(100,2,2);\n\n  // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1\n  template <class Tx, class Ty, class Ts>\n  static void CalcTrigShape (int n, Tx x, Ty y, Ts * shape)\n  {\n    // cout << \"calc trig shape\" << endl;\n    if (n < 3) return;\n    Tx hx[50], hy[50*50];\n\n    jacpols2[2] -> EvaluateScaled (n-3, x, 1-y, hx);\n\n    for (int ix = 0; ix <= n-3; ix++)\n      jacpols2[2*ix+5] -> Evaluate (n-3, 2*y-1, hy+50*ix);\n\n    int ii = 0;\n\n    Tx bub = (1+x-y)*y*(1-x-y);\n    for (int ix = 0; ix <= n-3; ix++)\n      hx[ix] *= bub;\n\n    /*\n    for (int iy = 0; iy <= n-3; iy++)\n      for (int ix = 0; ix <= n-3-iy; ix++)\n\tshape[ii++] = hx[ix]*hy[iy+50*ix];\n    */\n    // change loops:\n    for (int ix = 0; ix <= n-3; ix++)\n      for (int iy = 0; iy <= n-3-ix; iy++)\n\tshape[ii++] = hx[ix]*hy[iy+50*ix];\n  }\n\n  template <typename T>\n  static void CalcTrigShapeDxDy (int n, T x, T y, T * dshape)\n  { \n    if (n < 3) return;\n\n    AutoDiff<2,T> adx(x, 0);\n    AutoDiff<2,T> ady(y, 1);\n    AutoDiff<2,T> res[2000];\n    CalcTrigShape (n, adx, ady, &res[0]);\n    int ndof = (n-1)*(n-2)/2;\n    for (int i = 0; i < ndof; i++)\n      {\n\tdshape[2*i] = res[i].DValue(0);\n\tdshape[2*i+1] = res[i].DValue(1);\n      }\n  }\n\n\n  // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1\n  template <class Tx, class Ty, class Tt, class Tr>\n  static void CalcScaledTrigShape (int n, Tx x, Ty y, Tt t, Tr * shape)\n  {\n    if (n < 3) return;\n\n    /*\n    Tx hx[50], hy[50];\n    ScaledJacobiPolynomial (n-3, x, t-y, 2, 2, hx);\n\n    int ii = 0;\n    Tx bub = (t+x-y)*y*(t-x-y);\n    for (int ix = 0; ix <= n-3; ix++)\n      {\n        jacpols2[2*ix+5] -> EvaluateScaled (n-3, 2*y-1, t, hy);\n        for (int iy = 0; iy <= n-3-ix; iy++)\n          shape[ii++] = bub * hx[ix]*hy[iy];\n      }\n    */\n\n    \n    int ii = 0;\n    Tx bub = (t+x-y)*y*(t-x-y);\n    jacpols2[2]->EvaluateScaledLambda\n      (n-3, x, t-y,\n       [&](int ix, Tx valx)\n       {\n         jacpols2[2*ix+5] -> EvaluateScaledLambda (n-3-ix, 2*y-1, t, [&](int iy, Ty valy)\n         {\n                                                     shape[ii++] = bub*valx*valy;\n                                                   });\n       });\n  }\n\n\n  template <class Tx, class Ty, class Tt, typename FUNC>\n  static void CalcScaledTrigShapeLambda (int n, Tx x, Ty y, Tt t, FUNC func)\n  {\n    if (n < 3) return;\n    int ii = 0;\n    Tx bub = (t+x-y)*y*(t-x-y);\n    jacpols2[2]->EvaluateScaledLambda\n      (n-3, x, t-y,\n       [&](int ix, Tx valx)\n       {\n         jacpols2[2*ix+5] -> EvaluateScaledLambda (n-3-ix, 2*y-1, t, [&](int iy, Ty valy)\n                                                   {\n                                                     func(ii++, bub*valx*valy);\n                                                   });\n       });\n  }\n\n  \n  // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1\n  template <typename T>\n  static void CalcScaledTrigShapeDxDyDt (int n, T x, T y, T t, T * dshape)\n  {\n    /*\n    if (n < 3) return;\n    AutoDiff<3,T> adx(x, 0);\n    AutoDiff<3,T> ady(y, 1);\n    AutoDiff<3,T> adt(t, 2);\n    AutoDiff<3,T> res[2000];\n    CalcScaledTrigShape (n, adx, ady, adt, &res[0]);\n    int ndof = (n-1)*(n-2)/2;\n    for (int i = 0; i < ndof; i++)\n      {\n\tdshape[3*i] = res[i].DValue(0);\n\tdshape[3*i+1] = res[i].DValue(1);\n\tdshape[3*i+2] = res[i].DValue(2);\n      }\n    */\n    if (n < 3) return;\n    AutoDiff<3,T> adx(x, 0);\n    AutoDiff<3,T> ady(y, 1);\n    AutoDiff<3,T> adt(t, 2);\n    CalcScaledTrigShapeLambda (n, adx, ady, adt,\n                               [&] (int i, AutoDiff<3,T> shape)\n                               {\n                                 dshape[3*i] = shape.DValue(0);\n                                 dshape[3*i+1] = shape.DValue(1);\n                                 dshape[3*i+2] = shape.DValue(2);\n                               });\n  }\n\n\n  // tensor product of Jacobi(2,2)\n  // x,y in (-1,1)\n  template <class Tx, class Ty, typename FUNC>\n  static void CalcQuadShapeLambda (int n, Tx x, Ty y, FUNC func)\n  {\n    if (n < 2) return;\n    int ii = 0;\n    Tx bub = (1-x*x)*(1-y*y);\n    jacpol22.EvaluateLambda\n      (n-2, x, [&](int ix, Tx valx) {\n        jacpol22.EvaluateLambda (n-2, y, [&](int iy, Ty valy) {\n          func(ii++, bub*valx*valy);\n        });\n      });\n  }\n\n  \n  template <class Tx, class Ty, class Tsx, class Tsy, typename FUNC>\n  static void CalcScaledQuadShapeLambda (int n, Tx x, Ty y, Tsx sx, Tsy sy, FUNC func)\n  {\n    if (n < 2) return;\n    int ii = 0;\n    Tx bub = (1-x*x)*(1-y*y);\n    jacpol22.EvaluateScaledLambda\n      (n-2, x, sx, [&](int ix, Tx valx) {\n        jacpol22.EvaluateScaledLambda (n-2, y, sy, [&](int iy, Ty valy) {\n          func(ii++, bub*valx*valy);\n        });\n      });\n  }\n\n      \n\n  CurvedElements :: CurvedElements (const Mesh & amesh)\n    : mesh(amesh)\n  {\n    order = 1;\n    rational = 0;\n    ishighorder = 0;\n  }\n\n\n  CurvedElements :: ~CurvedElements()\n  {\n  }\n\n\n  void CurvedElements :: DoArchive(Archive& ar)\n  {\n    ar & edgeorder & faceorder & edgecoeffsindex & facecoeffsindex & edgecoeffs & facecoeffs\n      & edgeweight & order & rational & ishighorder;\n  }\n\n  \n  void CurvedElements :: BuildCurvedElements(const Refinement * ref, int aorder,\n                                             bool arational)\n  {\n    auto & geo = *mesh.GetGeometry();\n\n    ishighorder = 0;\n    order = 1;\n\n    auto comm = mesh.GetCommunicator();\n#ifdef PARALLEL\n    enum { NG_MPI_TAG_CURVE = NG_MPI_TAG_MESH+20 };\n    const ParallelMeshTopology & partop = mesh.GetParallelTopology ();\n#endif\n    int ntasks = comm.Size();\n    bool working = (ntasks == 1) || (comm.Rank() > 0);\n\n    if (working)\n      order = aorder;\n\n    if (mesh.coarsemesh)\n      {\n\tmesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational);\n        order = aorder;\n        rational = arational;\n        ishighorder = (order > 1);\n\treturn;\n      }\n\n\n    PrintMessage (1, \"Curve elements, order = \", aorder);\n    if (rational) PrintMessage (1, \"curved elements with rational splines\");\n\n    // if (working)\n    const_cast<Mesh&> (mesh).UpdateTopology();\n    const MeshTopology & top = mesh.GetTopology();\n\n    rational = arational;\n\n    NgArray<int> edgenrs;\n    int nedges = top.GetNEdges();\n    int nfaces = top.GetNFaces();\n\n    edgeorder.SetSize (nedges);\n    faceorder.SetSize (nfaces);\n\n    edgeorder = 1;\n    faceorder = 1;\n\n    if (rational)\n      {\n        edgeweight.SetSize (nedges);\n        edgeweight = 1.0;\n      }\n\n    \n    if (aorder <= 1) \n      {\n\tfor (ElementIndex ei : mesh.VolumeElements().Range())\n\t  if (mesh[ei].GetType() == TET10)\n\t    ishighorder = 1;\n\treturn; \n      }\n\n\n    if (rational) aorder = 2;\n\n    if (working)\n      {\n\tif (mesh.GetDimension() == 3)\n\t  for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)\n\t    {\n\t      // top.GetEdges (i, edgenrs);\n              auto edgenrs = top.GetEdges (i);\n\t      for (int j = 0; j < edgenrs.Size(); j++)\n\t\tedgeorder[edgenrs[j]] = aorder;\n\t      faceorder[top.GetFace (i)] = aorder;\n\t    }\n\tfor (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)\n\t  edgeorder[top.GetEdge (i)] = aorder;\n      }\n\n    if (rational)\n      {\n        edgeorder = 2;\n        faceorder = 1;\n      }\n\n\n#ifdef PARALLEL\n    // TABLE<int> send_orders(ntasks), recv_orders(ntasks);\n    DynamicTable<int> send_orders(ntasks), recv_orders(ntasks);\n\n    if (ntasks > 1 && working)\n      {\n\tfor (int e = 0; e < edgeorder.Size(); e++)\n          for (int proc : partop.GetDistantEdgeProcs(e))\n            send_orders.Add (proc, edgeorder[e]);              \n\tfor (int f = 0; f < faceorder.Size(); f++)\n          for (int proc : partop.GetDistantFaceProcs(f))\n            send_orders.Add (proc, faceorder[f]);                          \n      }\n\n    if (ntasks > 1)\n      //  MyMPI_ExchangeTable (send_orders, recv_orders, NG_MPI_TAG_CURVE, comm);\n      comm.ExchangeTable (send_orders, recv_orders, NG_MPI_TAG_CURVE);\n\n    if (ntasks > 1 && working)\n      {\n\tArray<int> cnt(ntasks);\n\tcnt = 0;\n\tfor (int e = 0; e < edgeorder.Size(); e++)\n          for (auto proc : partop.GetDistantEdgeProcs(e))\n            edgeorder[e] = max(edgeorder[e], recv_orders[proc][cnt[proc]++]);              \n\tfor (int f = 0; f < faceorder.Size(); f++)\n          for (auto proc : partop.GetDistantFaceProcs(f))\n            faceorder[f] = max(faceorder[f], recv_orders[proc][cnt[proc]++]);              \n      }\n#endif\n\n\n    edgecoeffsindex.SetSize (nedges+1);\n    int nd = 0;\n    for (int i = 0; i < nedges; i++)\n      {\n\tedgecoeffsindex[i] = nd;\n\tnd += max (0, edgeorder[i]-1);\n      }\n    edgecoeffsindex[nedges] = nd;\n\n    edgecoeffs.SetSize (nd);\n    edgecoeffs = Vec<3> (0,0,0);\n    \n\n    facecoeffsindex.SetSize (nfaces+1);\n    nd = 0;\n    for (int i = 0; i < nfaces; i++)\n      {\n\tfacecoeffsindex[i] = nd;\n\tif (top.GetFaceType0(i) == TRIG)\n\t  nd += max2 (0, (faceorder[i]-1)*(faceorder[i]-2)/2);\n\telse\n\t  nd += max2 (0, sqr(faceorder[i]-1));\n      }\n    facecoeffsindex[nfaces] = nd;\n\n    facecoeffs.SetSize (nd);\n    facecoeffs = Vec<3> (0,0,0);\n\n\n    if (!ref || aorder <= 1) \n      {\n        order = aorder;\n\treturn; \n      }\n    \n    NgArray<double> xi, weight;\n\n    ComputeGaussRule (aorder+4, xi, weight);  // on (0,1)\n\n    PrintMessage (3, \"Curving edges\");\n\n    if (mesh.GetDimension() == 3 || rational)\n      {\n        static Timer tce(\"curve edges\"); RegionTimer reg(tce);\n\tNgArray<int> surfnr(nedges);\n\tNgArray<PointGeomInfo> gi0(nedges);\n\tNgArray<PointGeomInfo> gi1(nedges);\n\tsurfnr = -1;\n\n\tif (working)\n\t  for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)\n\t    {\n\t      // top.GetEdges (i, edgenrs);\n              auto edgenrs = top.GetEdges(i);\n\t      const Element2d & el = mesh[i];\n\t      const ELEMENT_EDGE * edges = MeshTopology::GetEdges0 (el.GetType());\n\n\t      for (int i2 = 0; i2 < edgenrs.Size(); i2++)\n\t\t{\n\t\t  auto enr = edgenrs[i2];\n                  surfnr[enr] = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr();\n                  if (el[edges[i2][0]] < el[edges[i2][1]])\n                    {\n                      gi0[enr] = el.GeomInfoPi(edges[i2][0]+1);\n                      gi1[enr] = el.GeomInfoPi(edges[i2][1]+1);\n                    }\n                  else\n                    {\n                      gi1[enr] = el.GeomInfoPi(edges[i2][0]+1);\n                      gi0[enr] = el.GeomInfoPi(edges[i2][1]+1);\n                    }\n                }\n\t    }\n\n\n#ifdef PARALLEL\n\tif (ntasks > 1)\n\t  {\n\t    // distribute it ...\n\t    // TABLE<double> senddata(ntasks), recvdata(ntasks);\n            DynamicTable<double> senddata(ntasks), recvdata(ntasks);\n            \n\t    if (working)\n\t      for (int e = 0; e < nedges; e++)\n                for (int proc : partop.GetDistantEdgeProcs(e))\n                  {\n                    senddata.Add (proc, surfnr[e]);\n                    if (surfnr[e] != -1)\n                      {\n                        senddata.Add (proc, gi0[e].trignum);\n                        senddata.Add (proc, gi0[e].u);\n                        senddata.Add (proc, gi0[e].v);\n                        senddata.Add (proc, gi1[e].trignum);\n                        senddata.Add (proc, gi1[e].u);\n                        senddata.Add (proc, gi1[e].v);\n                      }\n                  }\n\t    \n            // MyMPI_ExchangeTable (senddata, recvdata, NG_MPI_TAG_CURVE, comm);\n            comm.ExchangeTable (senddata, recvdata, NG_MPI_TAG_CURVE);\n\n\t    NgArray<int> cnt(ntasks);\n\t    cnt = 0;\n\t    if (working)\n\t      for (int e = 0; e < nedges; e++)\n                for (int proc : partop.GetDistantEdgeProcs(e))\n                  {\n                    int surfnr1 = recvdata[proc][cnt[proc]++];\n                    if (surfnr1 != -1)\n                      {\n                        surfnr[e] = surfnr1; \n                        gi0[e].trignum = int (recvdata[proc][cnt[proc]++]);\n                        gi0[e].u = recvdata[proc][cnt[proc]++];\n                        gi0[e].v = recvdata[proc][cnt[proc]++];\n                        gi1[e].trignum = int (recvdata[proc][cnt[proc]++]);\n                        gi1[e].u = recvdata[proc][cnt[proc]++];\n                        gi1[e].v = recvdata[proc][cnt[proc]++];\n                      }\n                  }\n\t  }\n#endif    \n\n\n\tif (working)\n\t  for (int e = 0; e < surfnr.Size(); e++)\n\t    {\n\t      if (surfnr[e] == -1) continue;\n\t      SetThreadPercent(double(e)/surfnr.Size()*100.);\n\n\t      // PointIndex pi1, pi2;\n\t      // top.GetEdgeVertices (e+1, pi1, pi2);\n              auto [pi1,pi2] = top.GetEdgeVertices(e);\n\t      bool swap = (pi1 > pi2);\n\n\t      Point<3> p1 = mesh[pi1];\n\t      Point<3> p2 = mesh[pi2];\n\n\t      int order1 = edgeorder[e];\n\t      int ndof = max (0, order1-1);\n\n\t      if (rational && order1 >= 2)\n\t\t{\n\t\t  Point<3> pm = Center (p1, p2);\n\n\t\t  Vec<3> n1 = geo.GetNormal (surfnr[e], p1, &gi0[e]);\n\t\t  Vec<3> n2 = geo.GetNormal (surfnr[e], p2, &gi1[e]);\n\n\t\t  // p3 = pm + alpha1 n1 + alpha2 n2\n\t\t\n\t\t  Mat<2> mat, inv;\n\t\t  Vec<2> rhs, sol;\n\t\t\n\t\t  mat(0,0) = n1*n1;\n\t\t  mat(0,1) = mat(1,0) = n1*n2;\n\t\t  mat(1,1) = n2*n2;\n                \n\t\t  rhs(0) = n1 * (p1-pm);\n\t\t  rhs(1) = n2 * (p2-pm);\n                  \n\n\t\t  Point<3> p3;\n\t\t\n\t\t  if (fabs (Det (mat)) > 1e-10)\n\t\t    {\n\t\t      CalcInverse (mat, inv);\n\t\t      sol = inv * rhs;\n\t\t    \n\t\t      p3 = pm + sol(0) * n1 + sol(1) * n2;\n\t\t    }\n\t\t  else\n\t\t    p3 = pm;\n\t\t\n\t\t  edgecoeffs[edgecoeffsindex[e]] = Vec<3> (p3);\n\t\t\n\n\t\t  double wold = 1, w = 1, dw = 0.1;\n\t\t  double dold = 1e99;\n\t\t  while (fabs (dw) > 1e-12)\n\t\t    {\n\t\t      Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);\n\t\t      v05 /= 1 + (w-1) * 0.5;\n\t\t      Point<3> p05 (v05), pp05(v05);\n\t\t      geo.ProjectPointGI(surfnr[e], pp05, gi0[e]);\n\t\t      double d = Dist (pp05, p05);\n                    \n\t\t      if (d < dold)\n\t\t\t{\n\t\t\t  dold = d;\n\t\t\t  wold = w;\n\t\t\t  w += dw;\n\t\t\t}\n\t\t      else\n\t\t\t{\n\t\t\t  dw *= -0.7;\n\t\t\t  w = wold + dw;\n\t\t\t}\n\t\t    }\n\t\t\n\t\t  edgeweight[e] = w;\n\t\t  continue;\n\t\t}\n\t    \n\t      Vector shape(ndof);\n\t      DenseMatrix mat(ndof, ndof), inv(ndof, ndof),\n\t\trhs(ndof, 3), sol(ndof, 3);\n\t    \n\t      rhs = 0.0;\n\t      mat = 0.0;\n\t      for (int j = 0; j < xi.Size(); j++)\n\t\t{\n\t\t  Point<3> p;\n\t\t  Point<3> pp;\n\t\t  PointGeomInfo ppgi;\n\t\t\n\t\t  if (swap)\n\t\t    {\n\t\t      p = p1 + xi[j] * (p2-p1);\n\t\t      geo.PointBetween (p1, p2, xi[j],\n                                        surfnr[e], gi0[e], gi1[e],\n                                        pp, ppgi);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      p = p2 + xi[j] * (p1-p2);\n\t\t      geo.PointBetween (p2, p1, xi[j],\n                                        surfnr[e], gi1[e], gi0[e],\n                                        pp, ppgi);\n\t\t    }\n\t\t\n\t\t  Vec<3> dist = pp - p;\n\t\t\n\t\t  CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));\n\t\t\n\t\t  for (int k = 0; k < ndof; k++)\n\t\t    for (int l = 0; l < ndof; l++)\n\t\t      mat(k,l) += weight[j] * shape(k) * shape(l);\n\t\t\n\t\t  for (int k = 0; k < ndof; k++)\n\t\t    for (int l = 0; l < 3; l++)\n\t\t      rhs(k,l) += weight[j] * shape(k) * dist(l);\n\t\t}\n\t    \n\t      CalcInverse (mat, inv);\n\t      Mult (inv, rhs, sol);\n\t    \n\t      int first = edgecoeffsindex[e];\n\t      for (int j = 0; j < ndof; j++)\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  edgecoeffs[first+j](k) = sol(j,k);\n\t    }\n      }\n\n\n    NgArray<int> use_edge(nedges);\n    NgArray<int> edge_surfnr1(nedges);\n    NgArray<int> edge_surfnr2(nedges);\n    NgArray<int> swap_edge(nedges);\n    NgArray<EdgePointGeomInfo> edge_gi0(nedges);\n    NgArray<EdgePointGeomInfo> edge_gi1(nedges);\n    use_edge = 0;\n\n    if (working)\n      for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)\n\t{\n\t  const Segment & seg = mesh[i];\n\t  int edgenr = top.GetEdge (i);\n\t  use_edge[edgenr] = 1;\n\t  edge_surfnr1[edgenr] = seg.surfnr1;\n\t  edge_surfnr2[edgenr] = seg.surfnr2;\n\t  edge_gi0[edgenr] = seg.epgeominfo[0];\n\t  edge_gi1[edgenr] = seg.epgeominfo[1];\n\t  swap_edge[edgenr] = int (seg[0] > seg[1]);\n\t}\n\n#ifdef PARALLEL\n    if (ntasks > 1)\n      {\n\t// distribute it ...\n\t// TABLE<double> senddata(ntasks), recvdata(ntasks);\n        DynamicTable<double> senddata(ntasks), recvdata(ntasks);\n        \n\tif (working)\n\t  for (int e = 0; e < nedges; e++)\n            for (int proc : partop.GetDistantEdgeProcs(e))\n              {\n                senddata.Add (proc, use_edge[e]);\n                if (use_edge[e])\n                  {\n                    senddata.Add (proc, edge_surfnr1[e]);\n                    senddata.Add (proc, edge_surfnr2[e]);\n                    senddata.Add (proc, edge_gi0[e].edgenr);\n                    senddata.Add (proc, edge_gi0[e].body);\n                    senddata.Add (proc, edge_gi0[e].dist);\n                    senddata.Add (proc, edge_gi0[e].u);\n                    senddata.Add (proc, edge_gi0[e].v);\n                    senddata.Add (proc, edge_gi1[e].edgenr);\n                    senddata.Add (proc, edge_gi1[e].body);\n                    senddata.Add (proc, edge_gi1[e].dist);\n                    senddata.Add (proc, edge_gi1[e].u);\n                    senddata.Add (proc, edge_gi1[e].v);\n                    senddata.Add (proc, swap_edge[e]);\n                  }\n              }\n\n\t// MyMPI_ExchangeTable (senddata, recvdata, NG_MPI_TAG_CURVE, comm);\n        comm.ExchangeTable (senddata, recvdata, NG_MPI_TAG_CURVE);\n        \n\tNgArray<int> cnt(ntasks);\n\tcnt = 0;\n\tif (working)\n\t  for (int e = 0; e < edge_surfnr1.Size(); e++)\n            for (int proc : partop.GetDistantEdgeProcs(e))\n              {\n                int get_edge = int(recvdata[proc][cnt[proc]++]);\n                if (get_edge)\n                  {\n                    use_edge[e] = 1;\n                    edge_surfnr1[e] = int (recvdata[proc][cnt[proc]++]);\n                    edge_surfnr2[e] = int (recvdata[proc][cnt[proc]++]);\n                    edge_gi0[e].edgenr = int (recvdata[proc][cnt[proc]++]);\n                    edge_gi0[e].body = int (recvdata[proc][cnt[proc]++]);\n                    edge_gi0[e].dist = recvdata[proc][cnt[proc]++];\n                    edge_gi0[e].u = recvdata[proc][cnt[proc]++];\n                    edge_gi0[e].v = recvdata[proc][cnt[proc]++];\n                    edge_gi1[e].edgenr = int (recvdata[proc][cnt[proc]++]);\n                    edge_gi1[e].body = int (recvdata[proc][cnt[proc]++]);\n                    edge_gi1[e].dist = recvdata[proc][cnt[proc]++];\n                    edge_gi1[e].u = recvdata[proc][cnt[proc]++];\n                    edge_gi1[e].v = recvdata[proc][cnt[proc]++];\n                    swap_edge[e] = recvdata[proc][cnt[proc]++];\n                  }\n              }\n      }\n#endif    \n\n    if (working)\n      for (int edgenr = 0; edgenr < use_edge.Size(); edgenr++)\n\t{\n\t  int segnr = edgenr;\n\t  if (!use_edge[edgenr]) continue;\n\n\t  SetThreadPercent(double(edgenr)/edge_surfnr1.Size()*100.);\n\n          //  PointIndex pi1, pi2;\n\t  // top.GetEdgeVertices (edgenr+1, pi1, pi2);\n          auto [pi1,pi2] = top.GetEdgeVertices(edgenr);\n\n\t  bool swap = swap_edge[edgenr]; // (pi1 > pi2);\n\t  if (swap) Swap (pi1, pi2);\n\n\t  Point<3> p1 = mesh[pi1];\n\t  Point<3> p2 = mesh[pi2];\n\n\t  int order1 = edgeorder[segnr];\n\t  int ndof = max (0, order1-1);\n\n\t  if (rational)\n\t    {\n\t      Vec<3> tau1 = geo.GetTangent(p1, edge_surfnr2[edgenr], edge_surfnr1[edgenr],\n                                           edge_gi0[edgenr]);\n\t      Vec<3> tau2 = geo.GetTangent(p2, edge_surfnr2[edgenr], edge_surfnr1[edgenr],\n                                           edge_gi1[edgenr]);\n\t      // p1 + alpha1 tau1 = p2 + alpha2 tau2;\n\n\t      Mat<3,2> mat;\n\t      Mat<2,3> inv;\n\t      Vec<3> rhs;\n\t      Vec<2> sol;\n\t      for (int j = 0; j < 3; j++)\n\t\t{\n\t\t  mat(j,0) = tau1(j); \n\t\t  mat(j,1) = -tau2(j); \n\t\t  rhs(j) = p2(j)-p1(j); \n\t\t}\n\t      CalcInverse (mat, inv);\n\t      sol = inv * rhs;\n\n\t      Point<3> p3 = p1+sol(0) * tau1;\n\t      edgecoeffs[edgecoeffsindex[segnr]] = Vec<3> (p3);\n\n\t      double wold = 1, w = 1, dw = 0.1;\n\t      double dold = 1e99;\n\t      while (fabs (dw) > 1e-12)\n\t\t{\n\t\t  Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);\n\t\t  v05 /= 1 + (w-1) * 0.5;\n\t\t  Point<3> p05 (v05), pp05(v05);\n\t\t  geo.ProjectPointEdge(edge_surfnr1[edgenr], edge_surfnr2[edgenr], pp05,\n                                       &edge_gi0[edgenr]);\n\t\t  double d = Dist (pp05, p05);\n\n\t\t  if (d < dold)\n\t\t    {\n\t\t      dold = d;\n\t\t      wold = w;\n\t\t      w += dw;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      dw *= -0.7;\n\t\t      w = wold + dw;\n\t\t    }\n\t\t  // *testout << \"w = \" << w << \", dw = \" << dw << endl;\n\t\t}\n\n\t      // cout << \"wopt = \" << w << \", dopt = \" << dold << endl;\n\t      edgeweight[segnr] = w;\n            \n\t      //             cout << \"p1 = \" << p1 << \", tau1 = \" << tau1 << \", alpha1 = \" << sol(0) << endl;\n\t      //             cout << \"p2 = \" << p2 << \", tau2 = \" << tau2 << \", alpha2 = \" << -sol(1) << endl;\n\t      //             cout << \"p+alpha tau = \" << p1 + sol(0) * tau1 \n\t      //                  << \" =?= \" << p2 +sol(1) * tau2 << endl;\n            \n\t    }\n\n\t  else\n          \n\t    {\n\t      Vector shape(ndof);\n\t      DenseMatrix mat(ndof, ndof), inv(ndof, ndof),\n\t\trhs(ndof, 3), sol(ndof, 3);\n\n\t      rhs = 0.0;\n\t      mat = 0.0;\n\t      for (int j = 0; j < xi.Size(); j++)\n\t\t{\n\t\t  Point<3> p, pp;\n\t\t  EdgePointGeomInfo ppgi;\n\t    \n\t\t  if (swap)\n\t\t    {\n\t\t      p = p1 + xi[j] * (p2-p1);\n\t\t      geo.PointBetweenEdge(p1, p2, xi[j],\n                                           edge_surfnr2[edgenr], edge_surfnr1[edgenr],\n                                           edge_gi0[edgenr], edge_gi1[edgenr],\n                                           pp, ppgi);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      p = p2 + xi[j] * (p1-p2);\n\t\t      geo.PointBetweenEdge(p2, p1, xi[j],\n\t\t\t\t\t   edge_surfnr2[edgenr], edge_surfnr1[edgenr],\n\t\t\t\t\t   edge_gi1[edgenr], edge_gi0[edgenr],\n\t\t\t\t\t   pp, ppgi);\n\t\t    }\n\t    \n\t\t  Vec<3> dist = pp - p;\n\n\t\t  CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));\n\n\t\t  for (int k = 0; k < ndof; k++)\n\t\t    for (int l = 0; l < ndof; l++)\n\t\t      mat(k,l) += weight[j] * shape(k) * shape(l);\n\n\t\t  for (int k = 0; k < ndof; k++)\n\t\t    for (int l = 0; l < 3; l++)\n\t\t      rhs(k,l) += weight[j] * shape(k) * dist(l);\n\t\t}\n\n\t      CalcInverse (mat, inv);\n\t      Mult (inv, rhs, sol);\n\n\t      int first = edgecoeffsindex[segnr];\n\t      for (int j = 0; j < ndof; j++)\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  edgecoeffs[first+j](k) = sol(j,k);\n\t    }\n\t}\n\n   \n    \n    PrintMessage (3, \"Curving faces\");\n\n    NgArray<int> surfnr(nfaces);\n    surfnr = -1;\n\n    if (working)\n      for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)\n\tsurfnr[top.GetFace(i)] = \n\t  mesh.GetFaceDescriptor(mesh[i].GetIndex()).SurfNr();\n\n#ifdef PARALLEL\n    // TABLE<int> send_surfnr(ntasks), recv_surfnr(ntasks);\n    DynamicTable<int> send_surfnr(ntasks), recv_surfnr(ntasks);\n\n    if (ntasks > 1 && working)\n      {\n\tfor (int f = 0; f < nfaces; f++)\n          for (int proc : partop.GetDistantFaceProcs(f))\n            send_surfnr.Add (proc, surfnr[f]);              \n      }\n\n    if (ntasks > 1)\n      // MyMPI_ExchangeTable (send_surfnr, recv_surfnr, NG_MPI_TAG_CURVE, comm);\n      comm.ExchangeTable (send_surfnr, recv_surfnr, NG_MPI_TAG_CURVE);\n\n    if (ntasks > 1 && working)\n      {\n\tNgArray<int> cnt(ntasks);\n\tcnt = 0;\n\tfor (int f = 0; f < nfaces; f++)\n          for (int proc : partop.GetDistantFaceProcs(f))\n            surfnr[f] = max(surfnr[f], recv_surfnr[proc][cnt[proc]++]);              \n      }\n#endif\n\n    if (mesh.GetDimension() == 3 && working)\n      {\n        static Timer tcf(\"curve faces\"); RegionTimer reg(tcf);\n\tfor (int f = 0; f < nfaces; f++)\n\t  {\n\t    int facenr = f;\n\t    if (surfnr[f] == -1) continue;\n\n            auto face_type = top.GetFaceType0(facenr);\n            bool has_inner =\n              (face_type == TRIG && order >= 3) ||\n              (face_type == QUAD && order >= 2);\n              \n\t    if (has_inner)\n\t      {\n                auto verts = top.GetFaceVertices(facenr);\n                                                 \n\t\tint fnums[] = { 0, 1, 2, 4 };\n                if (face_type == TRIG)\n                  {\n                    if (verts[fnums[0]] > verts[fnums[1]]) swap (fnums[0], fnums[1]);\n                    if (verts[fnums[1]] > verts[fnums[2]]) swap (fnums[1], fnums[2]);\n                    if (verts[fnums[0]] > verts[fnums[1]]) swap (fnums[0], fnums[1]);\n                  }\n                else\n                  {\n                    int fmin = 0;\n                    for (int j = 1; j < 4; j++)\n                      if (verts[j] < verts[fmin]) fmin = j;\n                    fnums[0] = fmin;\n                    fnums[1] = (fmin+1)%4;\n                    fnums[2] = (fmin+2)%4;\n                    fnums[3] = (fmin+3)%4;\n                    if (verts[fnums[3]] < verts[fnums[1]]) swap (fnums[1], fnums[3]);\n                  }\n\t\tint order1 = faceorder[facenr];\n\t\tint ndof = max (0, (face_type==TRIG) ? (order1-1)*(order1-2)/2 : sqr(order1-1));\n\t    \n\t\tVector shape(ndof), dmat(ndof);\n\t\tMatrixFixWidth<3> rhs(ndof), sol(ndof);\n\t    \n\t\trhs = 0.0;\n\t\tdmat = 0.0;\n                \n\t\tint np = sqr(xi.Size());\n\t\tNgArray<Point<2> > xia(np);\n\t\tNgArray<Point<3> > xa(np);\n\n                if (face_type==TRIG)\n                  for (int jx = 0, jj = 0; jx < xi.Size(); jx++)\n                    for (int jy = 0; jy < xi.Size(); jy++, jj++)\n                      xia[jj] = Point<2> ((1-xi[jy])*xi[jx], xi[jy]);\n                else\n                  for (int jx = 0, jj = 0; jx < xi.Size(); jx++)\n                    for (int jy = 0; jy < xi.Size(); jy++, jj++)\n                      xia[jj] = Point<2> (xi[jx], xi[jy]);\n                  \n\t\t// CalcMultiPointSurfaceTransformation (&xia, i, &xa, NULL);\n\n\n\t\tNgArray<int> edgenrs;\n\t\ttop.GetFaceEdges (facenr+1, edgenrs);\n\t\tfor (int k = 0; k < edgenrs.Size(); k++) edgenrs[k]--;\n                \n\t\tfor (int jj = 0; jj < np; jj++)\n\t\t  {\n\t\t    Point<3> pp(0,0,0);\n\t\t    double lami[4], mui[4];\n                    if (face_type==TRIG)\n                      {\n                        lami[0] = xia[jj](0);\n                        lami[1] = xia[jj](1);\n                        lami[2] = 1-xia[jj](0)-xia[jj](1);\n                        lami[3] = 0.0;\n                      }\n                    else\n                      {\n                        lami[0] = (1-xia[jj](0))*(1-xia[jj](1));\n                        lami[1] = (  xia[jj](0))*(1-xia[jj](1));                        \n                        lami[2] = (  xia[jj](0))*(  xia[jj](1));\n                        lami[3] = (1-xia[jj](0))*(  xia[jj](1));                        \n\n                        mui[0] = (1-xia[jj](0))+(1-xia[jj](1));\n                        mui[1] = (  xia[jj](0))+(1-xia[jj](1));                        \n                        mui[2] = (  xia[jj](0))+(  xia[jj](1));\n                        mui[3] = (1-xia[jj](0))+(  xia[jj](1));                        \n\n                      }\n                    \n\t\t    for (int k = 0; k < verts.Size(); k++)\n\t\t      pp += lami[k] * Vec<3> (mesh.Point(verts[k]));\n\n\t\t    for (int k = 0; k < edgenrs.Size(); k++)\n\t\t      {\n\t\t\tint eorder = edgeorder[edgenrs[k]];\n\t\t\tif (eorder < 2) continue;\n\n\t\t\tint first = edgecoeffsindex[edgenrs[k]];\n\t\t\tVector eshape(eorder-1);\n\n                        auto [vi1,vi2] = top.GetEdgeVertices(edgenrs[k]);\n\t\t\tif (vi1 > vi2) swap (vi1, vi2);\n\t\t\tint v1 = -1, v2 = -1;\n\t\t\tfor (int j = 0; j < verts.Size(); j++)\n\t\t\t  {\n\t\t\t    if (verts[j] == vi1) v1 = j;\n\t\t\t    if (verts[j] == vi2) v2 = j;\n\t\t\t  }\n\n                        if (face_type==TRIG)\n                          CalcScaledEdgeShape (eorder, lami[v1]-lami[v2], lami[v1]+lami[v2], &eshape(0));\n                        else\n                          {\n                            CalcEdgeShape (eorder, mui[v1]-mui[v2], &eshape(0));\n                            eshape *= lami[v1]+lami[v2];\n                          }\n                        \n\t\t\tfor (int n = 0; n < eshape.Size(); n++)\n\t\t\t  pp += eshape(n) * edgecoeffs[first+n];\n\t\t      }\n\t\t    xa[jj] = pp;\n\t\t  }\n                \n                // check JOACHIM\n\n                if (face_type == TRIG)\n                  for (int jx = 0, jj = 0; jx < xi.Size(); jx++)\n                    for (int jy = 0; jy < xi.Size(); jy++, jj++)\n                      {\n                        double y = xi[jy];\n                        double x = (1-y) * xi[jx];\n                        double lami[] = { x, y, 1-x-y };\n                        double wi = weight[jx]*weight[jy]*(1-y);\n                        \n                        Point<3> pp = xa[jj];\n                        // ref -> ProjectToSurface (pp, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr());\n                        /**\n                           with MPI and an interior surface element between volume elements assigned to different\n                           procs, only one of them has the surf-el\n                        **/\n                        SurfaceElementIndex sei = top.GetFace2SurfaceElement(f);\n                        if (sei != SurfaceElementIndex(-1)) {\n                          PointGeomInfo gi = mesh[sei].GeomInfoPi(1);\n                          // use improved initial guess\n                          gi.u = (lami[fnums[0]]*mesh[sei].GeomInfoPi(1).u+lami[fnums[1]]*mesh[sei].GeomInfoPi(2).u+lami[fnums[2]]*mesh[sei].GeomInfoPi(3).u);\n                          gi.v = (lami[fnums[0]]*mesh[sei].GeomInfoPi(1).v+lami[fnums[1]]*mesh[sei].GeomInfoPi(2).v+lami[fnums[2]]*mesh[sei].GeomInfoPi(3).v);\n                          \n                          geo.ProjectPointGI(surfnr[facenr], pp, gi);\n                        }\n                        else\n                          { geo.ProjectPoint(surfnr[facenr], pp); }\n                        Vec<3> dist = pp-xa[jj];\n                        \n                        CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]],\n                                       1-lami[fnums[1]]-lami[fnums[0]], &shape(0));\n                        \n                        for (int k = 0; k < ndof; k++)\n                          dmat(k) += wi * shape(k) * shape(k);\n\n                        dist *= wi;\n                        for (int k = 0; k < ndof; k++)\n                          for (int l = 0; l < 3; l++)\n                            rhs(k,l) += shape(k) * dist(l);\n                      }\n                else\n                  for (int jx = 0, jj = 0; jx < xi.Size(); jx++)\n                    for (int jy = 0; jy < xi.Size(); jy++, jj++)\n                      {\n                        double wi = weight[jx]*weight[jy];\n\n                        double lami[4];\n                        lami[0] = (1-xia[jj](0))*(1-xia[jj](1));\n                        lami[1] = (  xia[jj](0))*(1-xia[jj](1));                        \n                        lami[2] = (  xia[jj](0))*(  xia[jj](1));\n                        lami[3] = (1-xia[jj](0))*(  xia[jj](1));                        \n                        double mui[4];\n                        mui[0] = (1-xia[jj](0))+(1-xia[jj](1));\n                        mui[1] = (  xia[jj](0))+(1-xia[jj](1));                        \n                        mui[2] = (  xia[jj](0))+(  xia[jj](1));\n                        mui[3] = (1-xia[jj](0))+(  xia[jj](1));                        \n\n                        \n                        Point<3> pp = xa[jj];\n                        // ref -> ProjectToSurface (pp, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr());\n                        /**\n                           with MPI and an interior surface element between volume elements assigned to different\n                           procs, only one of them has the surf-el\n                        **/\n                        SurfaceElementIndex sei = top.GetFace2SurfaceElement(f);\n\n                        if (sei != SurfaceElementIndex(-1)) {\n                          PointGeomInfo gi = mesh[sei].GeomInfoPi(1);\n                          // use improved initial guess TODO JOACHIM\n                          gi.u = 0;\n                          gi.v = 0;\n                          for (int k = 0; k < 4; k++)\n                            {\n                              gi.u += lami[k] * mesh[sei].GeomInfoPi(k+1).u;\n                              gi.v += lami[k] * mesh[sei].GeomInfoPi(k+1).v;\n                            }\n                          geo.ProjectPointGI(surfnr[facenr], pp, gi);\n                        }\n                        else\n                          geo.ProjectPoint(surfnr[facenr], pp);\n                        \n                        Vec<3> dist = pp-xa[jj];\n\n                        /*\n                        CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]],\n                                       1-lami[fnums[1]]-lami[fnums[0]], &shape(0));\n                        */\n                        // CalcQuadShapeLambda (order1, 2*x-1, 2*y-1, [&](int i, double val) { shape(i) = val; });\n                        CalcQuadShapeLambda (order1, mui[fnums[1]]-mui[fnums[0]], mui[fnums[3]]-mui[fnums[0]], [&](int i, double val) { shape(i) = val; });                        \n                        for (int k = 0; k < ndof; k++)\n                          dmat(k) += wi * shape(k) * shape(k);\n\n                        dist *= wi;\n                        for (int k = 0; k < ndof; k++)\n                          for (int l = 0; l < 3; l++)\n                            rhs(k,l) += shape(k) * dist(l);\n                      }\n                \n                for (int i = 0; i < ndof; i++)\n                  for (int j = 0; j < 3; j++)\n                    sol(i,j) = rhs(i,j) / dmat(i);   // Orthogonal basis !\n                \n\t\tint first = facecoeffsindex[facenr];\n\t\tfor (int j = 0; j < ndof; j++)\n\t\t  for (int k = 0; k < 3; k++)\n\t\t    facecoeffs[first+j](k) = sol(j,k);\n\t      }\n\t  }\n      }\n\n\n    // compress edge and face tables\n    int newbase = 0;\n    for (int i = 0; i < edgeorder.Size(); i++)\n      {\n\tbool curved = 0;\n\tint oldbase = edgecoeffsindex[i];\n\tint nd = edgecoeffsindex[i+1] - edgecoeffsindex[i];\n\n\tfor (int j = 0; j < nd; j++)\n\t  if (edgecoeffs[oldbase+j].Length() > 1e-12)\n\t    curved = 1;\n\tif (rational) curved = 1;\n\n\tif (curved && newbase != oldbase)\n\t  for (int j = 0; j < nd; j++)\n\t    edgecoeffs[newbase+j] = edgecoeffs[oldbase+j];\n\n\tedgecoeffsindex[i] = newbase;\n\tif (!curved) edgeorder[i] = 1;\n\tif (curved) newbase += nd;\n      }\n    edgecoeffsindex.Last() = newbase;\n\n\n    newbase = 0;\n    for (int i = 0; i < faceorder.Size(); i++)\n      {\n\tbool curved = 0;\n\tint oldbase = facecoeffsindex[i];\n\tint nd = facecoeffsindex[i+1] - facecoeffsindex[i];\n\n\tfor (int j = 0; j < nd; j++)\n\t  if (facecoeffs[oldbase+j].Length() > 1e-12)\n\t    curved = 1;\n\n\tif (curved && newbase != oldbase)\n\t  for (int j = 0; j < nd; j++)\n\t    facecoeffs[newbase+j] = facecoeffs[oldbase+j];\n\n\tfacecoeffsindex[i] = newbase;\n\tif (!curved) faceorder[i] = 1;\n\tif (curved) newbase += nd;\n      }\n    facecoeffsindex.Last() = newbase;\n    \n    if (working)\n      ishighorder = (order > 1);\n    // (*testout) << \"edgecoeffs = \" << endl << edgecoeffs << endl;\n    // (*testout) << \"facecoeffs = \" << endl << facecoeffs << endl;\n\n\n#ifdef PARALLEL\n    comm.Barrier();\n#endif\n  }\n\n\n\n\n\n\n\n\n\n\n  // ***********************  Transform edges *****************************\n\n  \n  bool CurvedElements ::  IsSegmentCurved (SegmentIndex elnr) const\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].hp_elnr];\n        \n\treturn mesh.coarsemesh->GetCurvedElements().IsSegmentCurved (hpref_el.coarse_elnr);\n      }\n\n    SegmentInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = 2;\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\tinfo.edgenr = top.GetEdge (elnr);\t\n\tinfo.ndof += edgeorder[info.edgenr]-1;\n      }\n\n    return (info.ndof > info.nv);\n  }\n\n\n \n  \n  template <typename T>\n  void CurvedElements :: \n  CalcSegmentTransformation (const T & xi, SegmentIndex elnr,\n\t\t\t     Point<3,T> * x, Vec<3,T> * dxdxi, bool * curved)\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].hp_elnr];\n\t\n\t// xi umrechnen\n\tT lami[2] = { xi, 1-xi };\n\tT dlami[2] = { 1, -1 };\n\n\tT coarse_xi = 0;\n\tT trans = 0;\n\tfor (int i = 0; i < 2; i++)\n\t  {\n\t    coarse_xi += hpref_el.param[i][0] * lami[i];\n\t    trans += hpref_el.param[i][0] * dlami[i];\n\t  }\n\n\tmesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi, curved);\n\tif (dxdxi) *dxdxi *= trans;\n\t\n\treturn;\n      }\n    \n\n\n    // TVector<T> shapes, dshapes;\n    //     NgArray<Vec<3> > coefs;\n\n    SegmentInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = 2;\n\n    if (order == 1)\n      {\n        auto & seg = mesh.LineSegment(elnr);\n        if (seg.GetNP() == 2)\n          {\n            if (x)\n              *x = Point<3,T>(xi * Vec<3>(mesh[seg.PNums()[0]]) + (1-xi) * Vec<3>(mesh[seg.PNums()[1]]));\n            if (dxdxi)\n              *dxdxi = Vec<3>(mesh[seg.PNums()[0]])-Vec<3>(mesh[seg.PNums()[1]]);\n          }\n        else\n          {\n            if (x)\n              {\n                *x = Point<3,T>(2*(xi-1)*(xi-0.5) * Vec<3>(mesh[seg.PNums()[1]])\n                                + 4*xi*(1-xi) * Vec<3>(mesh[seg.PNums()[2]])\n                                + 2*xi*(xi-0.5) * Vec<3>(mesh[seg.PNums()[0]]));\n              }\n            if (dxdxi)\n              *dxdxi = (4*xi-1)*Vec<3>(mesh[seg.PNums()[0]])\n                + (4*xi-3)*Vec<3>(mesh[seg.PNums()[1]])\n                + (4-8*xi)*Vec<3>(mesh[seg.PNums()[2]]);\n\n          }\n        return;\n      }\n    \n    \n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\tinfo.edgenr = top.GetEdge (elnr);\t\n\tinfo.ndof += edgeorder[info.edgenr]-1;\n      }\n\n    NgArrayMem<Vec<3>,100> coefs(info.ndof);\n    NgArrayMem<T, 100> shapes_mem(info.ndof);\n    TFlatVector<T> shapes(info.ndof, &shapes_mem[0]);\n    NgArrayMem<T, 200> dshapes_mem(info.ndof);\n    TFlatVector<T> dshapes(info.ndof, &dshapes_mem[0]);\n\n    \n    CalcElementShapes (info, xi, shapes);\n    GetCoefficients (info, coefs);\n\n    *x = 0;\n    for (int i = 0; i < shapes.Size(); i++)\n      // *x += shapes(i) * coefs[i];\n      for (int j = 0; j < 3; j++)\n        (*x)(j) += shapes(i) * coefs[i](j);\n\n\n    if (dxdxi)\n      {\n\tCalcElementDShapes (info, xi, dshapes);\n\t\n\t*dxdxi = 0;\n\tfor (int i = 0; i < shapes.Size(); i++)\n\t  for (int j = 0; j < 3; j++)\n\t    (*dxdxi)(j) += dshapes(i) * coefs[i](j);\n      }\n\n    if (curved)\n      *curved = (info.order > 1);\n\n    // cout << \"Segment, |x| = \" << Abs2(Vec<3> (*x) ) << endl;\n  }\n\n\n  template <typename T>\n  void CurvedElements :: \n  CalcElementShapes (SegmentInfo & info, T xi, TFlatVector<T> shapes) const\n  {\n    /*\n    if (rational && info.order == 2)\n      {\n\tshapes.SetSize(3);\n\tdouble w = edgeweight[info.edgenr];\n\tshapes(0) = xi*xi;\n\tshapes(1) = (1-xi)*(1-xi);\n\tshapes(2) = 2*w*xi*(1-xi);\n\tshapes *= 1.0 / (1 + (w-1) *2*xi*(1-xi));\n\treturn;\n      }\n    */\n\n    // shapes.SetSize(info.ndof);\n    shapes(0) = xi;\n    shapes(1) = 1-xi;\n\n    if (info.order >= 2)\n      {\n\tif (mesh[info.elnr][0] > mesh[info.elnr][1])\n\t  xi = 1-xi;\n\tCalcEdgeShape (edgeorder[info.edgenr], 2*xi-1, &shapes(2));\n      }\n  }\n\n  template <typename T>\n  void CurvedElements :: \n  CalcElementDShapes (SegmentInfo & info, T xi, TFlatVector<T> dshapes) const\n  {\n    /*\n    if (rational && info.order == 2)\n      {\n\tdshapes.SetSize(3);\n\tdouble wi = edgeweight[info.edgenr];\n\tdouble shapes[3];\n\tshapes[0] = xi*xi;\n\tshapes[1] = (1-xi)*(1-xi);\n\tshapes[2] = 2*wi*xi*(1-xi);\n\tdouble w = 1 + (wi-1) *2*xi*(1-xi);\n\tdouble dw = (wi-1) * (2 - 4*xi);\n        \n\tdshapes(0) = 2*xi;\n\tdshapes(1) = 2*(xi-1);\n\tdshapes(2) = 2*wi*(1-2*xi);\n\n\tfor (int j = 0;j < 3; j++)\n\t  dshapes(j) = dshapes(j) / w - shapes[j] * dw / (w*w);\n\treturn;\n      }\n    */\n\n\n\n    // dshapes.SetSize(info.ndof);\n    dshapes = 0;\n    dshapes(0) = 1;\n    dshapes(1) = -1;\n\n    // int order = edgeorder[info.edgenr];\n\n    if (info.order >= 2)\n      {\n\tT fac = 2;\n\tif (mesh[info.elnr][0] > mesh[info.elnr][1])\n\t  {\n\t    xi = 1-xi; \n\t    fac *= -1;\n\t  }\n\tCalcEdgeDx (edgeorder[info.edgenr], 2*xi-1, &dshapes(2));\n\tfor (int i = 2; i < dshapes.Size(); i++)\n\t  dshapes(i) *= fac;\n      }\n\n    // ??? not implemented ????\n  }\n\n  void CurvedElements :: \n  GetCoefficients (SegmentInfo & info, NgArray<Vec<3> > & coefs) const\n  {\n    const Segment & el = mesh[info.elnr];\n\n    coefs.SetSize(info.ndof);\n\n    coefs[0] = Vec<3> (mesh[el[0]]);\n    coefs[1] = Vec<3> (mesh[el[1]]);\n\n    if (info.order >= 2)\n      {\n\tint first = edgecoeffsindex[info.edgenr]; \n\tint next = edgecoeffsindex[info.edgenr+1]; \n\tfor (int i = 0; i < next-first; i++)\n\t  coefs[i+2] = edgecoeffs[first+i];\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n  // ********************** Transform surface elements *******************\n\n\n  bool CurvedElements :: IsSurfaceElementCurved (SurfaceElementIndex elnr) const\n  {\n    if (mesh[elnr].GetType() != TRIG) return true;\n    if (!IsHighOrder()) return false;\n\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\treturn mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr);\n      }\n\n    const Element2d & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n    \n    SurfaceElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n\n    switch (type)\n      {\n      case TRIG : info.nv = 3; break;\n      case QUAD : info.nv = 4; break;\n      case TRIG6: return true;\n      default:\n\tcerr << \"undef element in CalcSurfaceTrafo\" << endl;\n      }\n    info.ndof = info.nv;\n\n    // info.ndof = info.nv = ( (type == TRIG) || (type == TRIG6) ) ? 3 : 4;\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        /*\n\ttop.GetSurfaceElementEdges (elnr+1, info.edgenrs);\n\tfor (int i = 0; i < info.edgenrs.Size(); i++)\n\t  info.edgenrs[i]--;\n        */\n        /*\n        auto edgs = top.GetEdges(SurfaceElementIndex(elnr));\n        info.edgenrs.SetSize(edgs.Size());\n        for (auto [i,nr] : Enumerate(edgs))\n          info.edgenrs[i] = nr;\n        */\n        info.SetEdges (top.GetEdges(SurfaceElementIndex(elnr)));\n        \n\tinfo.facenr = top.GetFace(elnr);\n\tfor (int i = 0; i < info.edgenrs.Size(); i++)\n\t  info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n\tinfo.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];\n      }\n\n    return (info.ndof > info.nv);\n  }\n  \n  void CurvedElements :: \n  CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr,\n\t\t\t     Point<3> * x, Mat<3,2> * dxdxi, bool * curved)\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\t// xi umrechnen\n\tdouble lami[4];\n\tFlatVector vlami(4, lami);\n\tvlami = 0;\n\tmesh[elnr].GetShapeNew (xi, vlami);\n\t\n\tMat<2,2> trans;\n\tMat<3,2> dxdxic;\n\tif (dxdxi)\n\t  {\n\t    MatrixFixWidth<2> dlami(4);\n\t    dlami = 0;\n\t    mesh[elnr].GetDShapeNew (xi, dlami);\t  \n\t    \n\t    trans = 0;\n\t    for (int k = 0; k < 2; k++)\n\t      for (int l = 0; l < 2; l++)\n\t\tfor (int i = 0; i < hpref_el.np; i++)\n\t\t  trans(l,k) += hpref_el.param[i][l] * dlami(i, k);\n\t  }\n\t\n\tPoint<2> coarse_xi(0,0);\n\tfor (int i = 0; i < hpref_el.np; i++)\n\t  for (int j = 0; j < 2; j++)\n\t    coarse_xi(j) += hpref_el.param[i][j] * lami[i];\n\t\n\tmesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic, curved);\n\t\n\tif (dxdxi)\n\t  *dxdxi = dxdxic * trans;\n\t\n\treturn;\n      }\n    \n\n\n\n    const Element2d & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    SurfaceElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n\n    switch (type)\n      {\n      case TRIG : info.nv = 3; break;\n      case QUAD : info.nv = 4; break;\n      case TRIG6: info.nv = 6; break;\n      case QUAD8 : info.nv = 8; break;\n      default:\n\tcerr << \"undef element in CalcSurfaceTrafo\" << endl;\n      }\n    info.ndof = info.nv;\n\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        /*\n\ttop.GetSurfaceElementEdges (elnr+1, info.edgenrs);\n\tfor (int i = 0; i < info.edgenrs.Size(); i++)\n\t  info.edgenrs[i]--;\n        */\n        info.SetEdges(top.GetEdges(SurfaceElementIndex(elnr)));\n\tinfo.facenr = top.GetFace(elnr);\n\n\n\tbool firsttry = true;\n\tbool problem = false;\n\n\twhile(firsttry || problem)\n\t  {\n\t    problem = false;\n\n\t    for (int i = 0; !problem && i < info.edgenrs.Size(); i++)\n\t      {\n\t\tif(info.edgenrs[i]+1 >= edgecoeffsindex.Size())\n\t\t  problem = true;\n\t\telse\n\t\t  info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n\t      }\n\t    if(info.facenr+1 >= facecoeffsindex.Size())\n\t      problem = true;\n\t    else\n\t      info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];\n\n\t    if(problem && !firsttry)\n\t      throw NgException(\"something wrong with curved elements\");\n\t    \n\t    if(problem)\n\t      BuildCurvedElements(NULL,order,rational);\n\n\t    firsttry = false;\n\t  }\n      }\n\n    \n    Point<2> _xi(xi);\n    Point<3> _x;\n    Mat<3,2> _dxdxi;\n    if (EvaluateMapping (info, _xi, _x, _dxdxi))\n      {\n        if (x) *x = _x;\n        if (dxdxi) *dxdxi = _dxdxi;\n        return;\n      }\n\n    \n    NgArrayMem<Vec<3>,100> coefs(info.ndof);\n    NgArrayMem<double, 100> shapes_mem(info.ndof);\n    TFlatVector<double> shapes(info.ndof, &shapes_mem[0]);\n    NgArrayMem<double, 200> dshapes_mem(2*info.ndof);\n    MatrixFixWidth<2> dshapes(info.ndof, &dshapes_mem[0]);\n\n\n    CalcElementShapes (info, xi, shapes);\n    GetCoefficients (info, coefs);\n\n    *x = 0;\n    for (int i = 0; i < coefs.Size(); i++)\n      *x += shapes(i) * coefs[i];\n\n    if (dxdxi)\n      {\n\tCalcElementDShapes (info, xi, dshapes);\n\t\n\t*dxdxi = 0;\n\tfor (int i = 0; i < coefs.Size(); i++)\n\t  for (int j = 0; j < 3; j++)\n\t    for (int k = 0; k < 2; k++)\n\t      (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);\n      }\n\n    if (curved)\n      *curved = (info.ndof > info.nv);\n  }\n\n\n\n  template <typename T>\n  void CurvedElements :: \n  CalcElementShapes (SurfaceElementInfo & info, const Point<2,T> xi, TFlatVector<T> shapes) const\n  {\n    const Element2d & el = mesh[info.elnr];\n    // shapes.SetSize(info.ndof);\n    \n    if (rational && info.order >= 2)\n      {\n\t// shapes.SetSize(6);\n\tT w(1);\n\tT lami[3] = { xi(0), xi(1), 1-xi(0)-xi(1) };\n\tfor (int j = 0; j < 3; j++)\n\t  shapes(j) = lami[j] * lami[j];\n\n\tconst ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG);\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    T wi = edgeweight[info.edgenrs[j]];\n\t    shapes(j+3) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t  }\n\n\tshapes *= 1.0 / w;\n\treturn;\n      }\n\n    switch (el.GetType())\n      {\n      case TRIG:\n\t{\n\t  shapes(0) = xi(0);\n\t  shapes(1) = xi(1);\n\t  shapes(2) = 1-xi(0)-xi(1);\n\n\t  if (info.order == 1) return;\n\n\t  int ii = 3;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges0 (TRIG);\n\t  \n\t  for (int i = 0; i < 3; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0], vi2 = edges[i][1];\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  int forder = faceorder[info.facenr];\n\t  if (forder >= 3)\n\t    {\n\t      int fnums[] = { 0, 1, 2 };\n\t      if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t      if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n\t      if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t      \n\t      CalcTrigShape (forder, \n\t\t\t     shapes(fnums[1])-shapes(fnums[0]),\n\t\t\t     1-shapes(fnums[1])-shapes(fnums[0]), &shapes(ii));\n\t    }\n\t  break;\n\t}\n\n      case TRIG6:\n\t{\n\t  if (shapes.Size() == 3)\n\t    {\n\t      shapes(0) = xi(0);\n\t      shapes(1) = xi(1);\n\t      shapes(2) = 1-xi(0)-xi(1);\n\t    }\n\t  else\n\t    {\n\t      T x = xi(0);\n\t      T y = xi(1);\n\t      T lam3 = 1-x-y;\n\t      \n\t      shapes(0) = x * (2*x-1);\n\t      shapes(1) = y * (2*y-1);\n\t      shapes(2) = lam3 * (2*lam3-1);\n\t      shapes(3) = 4 * y * lam3;\n\t      shapes(4) = 4 * x * lam3;\n\t      shapes(5) = 4 * x * y;\n\t    }\n\t  break;\n\t}\n\n      case QUAD:\n\t{\n\t  shapes(0) = (1-xi(0))*(1-xi(1));\n\t  shapes(1) =    xi(0) *(1-xi(1));\n\t  shapes(2) =    xi(0) *   xi(1) ;\n\t  shapes(3) = (1-xi(0))*   xi(1) ;\n\n\t  if (info.order == 1) return;\n\t  \n\t  T mu[4] = { \n\t    1 - xi(0) + 1 - xi(1), \n\t    xi(0) + 1 - xi(1), \n\t    xi(0) +     xi(1), \n\t    1 - xi(0) +     xi(1), \n\t  };\n\t    \n\t  int ii = 4;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (QUAD);\n\t  \n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii));\n\t\t  T lame = shapes(vi1)+shapes(vi2);\n\t\t  for (int j = 0; j < order-1; j++)\n\t\t    shapes(ii+j) *= lame;\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\t  \n\t  for (int i = ii; i < info.ndof; i++)\n\t    shapes(i) = 0;\n\n\t  break;\n\t}\n\n      case QUAD8:\n\t{\n          auto x = xi(0), y = xi(1);\n\t  shapes(0) = (1-x)*(1-y);\n\t  shapes(1) = x*(1-y);\n\t  shapes(2) = x*y;\n\t  shapes(3) = (1-x)*y;\n          shapes(4) = 4*(1-x)*x*(1-y);\n          shapes(5) = 4*(1-x)*x*y;\n          shapes(6) = 4*(1-y)*y*(1-x);\n          shapes(7) = 4*(1-y)*y*x;\n          shapes(0) -= 0.5*(shapes(4)+shapes(6));\n          shapes(1) -= 0.5*(shapes(4)+shapes(7));\n          shapes(2) -= 0.5*(shapes(5)+shapes(7));\n          shapes(3) -= 0.5*(shapes(5)+shapes(6));\n          break;\n        }\n        \n      default:\n\tthrow NgException(\"CurvedElements::CalcShape 2d, element type not handled\");\n      };\n  }\n\n  template <typename T>\n  void CurvedElements :: \n  CalcElementDShapes (SurfaceElementInfo & info, const Point<2,T> xi, MatrixFixWidth<2,T> & dshapes) const\n  {\n    const Element2d & el = mesh[info.elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    T lami[4];\n\n    dshapes.SetSize(info.ndof);\n    // dshapes = 0;\t  \n\n    // *testout << \"calcelementdshapes, info.ndof = \" << info.ndof << endl;\n\n    if (rational && info.order >= 2)\n      {\n\tT w = 1;\n\tT dw[2] = { 0, 0 };\n\n\n\tlami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1);\n\tT dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }};\n\tT shapes[6];\n\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    shapes[j] = lami[j] * lami[j];\n\t    dshapes(j,0) = 2 * lami[j] * dlami[j][0];\n\t    dshapes(j,1) = 2 * lami[j] * dlami[j][1];\n\t  }\n\n\tconst ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG);\n\tfor (int j = 0; j < 3; j++)\n\t  {\n\t    T wi = edgeweight[info.edgenrs[j]];\n\n\t    shapes[j+3] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    for (int k = 0; k < 2; k++)\n\t      dshapes(j+3,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +\n\t\t\t\t      lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);\n\n\t    w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    for (int k = 0; k < 2; k++)\n\t      dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +\n\t\t\t\t   lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);\n\t  }\n\t// shapes *= 1.0 / w;\n\tdshapes *= 1.0 / w;\n\tfor (int i = 0; i < 6; i++)\n\t  for (int j = 0; j < 2; j++)\n\t    dshapes(i,j) -= shapes[i] * dw[j] / (w*w);\n\treturn;\n      }\n\n\n\n\n\n    switch (type)\n      {\n      case TRIG:\n\t{\n\t  dshapes(0,0) = 1;\n\t  dshapes(0,1) = 0.0;\n\t  dshapes(1,0) = 0.0;\n\t  dshapes(1,1) = 1;\n\t  dshapes(2,0) = -1;\n\t  dshapes(2,1) = -1;\n\t  \n\t  if (info.order == 1) return;\n\n\t  // *testout << \"info.order = \" << info.order << endl;\n\n\n\t  lami[0] = xi(0);\n\t  lami[1] = xi(1);\n\t  lami[2] = 1-xi(0)-xi(1);\n\n\t  int ii = 3;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG);\n\t  \n\t  for (int i = 0; i < 3; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShapeDxDt<2> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));\n\n\t\t  Mat<2,2,T> trans;\n\t\t  for (int j = 0; j < 2; j++)\n\t\t    {\n\t\t      trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);\n\t\t      trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);\n\t\t    }\n\t\t  \n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    {\n\t\t      T ddx = dshapes(ii+j,0);\n\t\t      T ddt = dshapes(ii+j,1);\n\t\t      dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);\n\t\t      dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);\n\t\t    }\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  int forder = faceorder[info.facenr];\n\t  // *testout << \"forder = \" << forder << endl;\n\t  if (forder >= 3)\n\t    {\n\t      int fnums[] = { 0, 1, 2 };\n\t      if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t      if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n\t      if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t      \n\t      CalcTrigShapeDxDy (forder, \n\t\t\t\t lami[fnums[1]]-lami[fnums[0]],\n\t\t\t\t 1-lami[fnums[1]]-lami[fnums[0]], &dshapes(ii,0));\n\n\t      int nd = (forder-1)*(forder-2)/2;\n\t      Mat<2,2,T> trans;\n\t      for (int j = 0; j < 2; j++)\n\t\t{\n\t\t  trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);\n\t\t  trans(1,j) = -dshapes(fnums[1],j)-dshapes(fnums[0],j);\n\t\t}\n\n\t      for (int j = 0; j < nd; j++)\n\t\t{\n\t\t  T ddx = dshapes(ii+j,0);\n\t\t  T ddt = dshapes(ii+j,1);\n\t\t  dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);\n\t\t  dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);\n\t\t}\n\t    }\n\n\t  break;\n\t}\n\n      case TRIG6:\n\t{\n\t  if (dshapes.Height() == 3)\n\t    {\n\t      dshapes = T(0.0);\n\t      dshapes(0,0) = 1;\n\t      dshapes(1,1) = 1;\n\t      dshapes(2,0) = -1;\n\t      dshapes(2,1) = -1;\t    \n\t    }\n\t  else\n\t    {\n\t      AutoDiff<2,T> x(xi(0), 0);\n\t      AutoDiff<2,T> y(xi(1), 1);\n\t      AutoDiff<2,T> lam3 = 1-x-y;\n\t      AutoDiff<2,T> shapes[6];\n\t      shapes[0] = x * (2*x-1);\n\t      shapes[1] = y * (2*y-1);\n\t      shapes[2] = lam3 * (2*lam3-1);\n\t      shapes[3] = 4 * y * lam3;\n\t      shapes[4] = 4 * x * lam3;\n\t      shapes[5] = 4 * x * y;\n\n\t      for (int i = 0; i < 6; i++)\n\t\t{\n\t\t  dshapes(i,0) = shapes[i].DValue(0);\n\t\t  dshapes(i,1) = shapes[i].DValue(1);\n\t\t}\n\t      \n\t    }\n\t  break;\n\t}\n\n      case QUAD:\n\t{\n\t  dshapes(0,0) = -(1-xi(1));\n\t  dshapes(0,1) = -(1-xi(0));\n\t  dshapes(1,0) =  (1-xi(1));\n\t  dshapes(1,1) =    -xi(0);\n\t  dshapes(2,0) =     xi(1);\n\t  dshapes(2,1) =     xi(0);\n\t  dshapes(3,0) =    -xi(1);\n\t  dshapes(3,1) =  (1-xi(0));\n\n\t  if (info.order == 1) return;\n\n\t  T shapes[4] = {\n\t    (1-xi(0))*(1-xi(1)),\n\t    xi(0) *(1-xi(1)),\n\t    xi(0) *   xi(1) ,\n\t    (1-xi(0))*   xi(1) \n\t  };\n\n\t  T mu[4] = { \n\t    1 - xi(0) + 1 - xi(1), \n\t    xi(0) + 1 - xi(1), \n\t    xi(0) +     xi(1), \n\t    1 - xi(0) +     xi(1), \n\t  };\n\n\t  T dmu[4][2] = {\n\t    { -1, -1 },\n\t    { 1, -1 },\n\t    { 1, 1 },\n\t    { -1, 1 } };\n\t    \n\t  // double hshapes[20], hdshapes[20];\n\t  NgArrayMem<T, 20> hshapes(order+1), hdshapes(order+1);\n\n\t  int ii = 4;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (QUAD);\n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]);\n\n\t\t  T lame = shapes[vi1]+shapes[vi2];\n\t\t  T dlame[2] = {\n\t\t    dshapes(vi1, 0) + dshapes(vi2, 0),\n\t\t    dshapes(vi1, 1) + dshapes(vi2, 1) };\n\t\t    \n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    for (int k = 0; k < 2; k++)\n\t\t      dshapes(ii+j, k) = \n\t\t\tlame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k])\n\t\t\t+ dlame[k] * hshapes[j];\n\n\t\t  ii += eorder-1;\n\t\t}\n              \n              // TODO (if still needed???)\n              /*\n              int forder = faceorder[info.facenr];\n              if (forder >= 2)\n                {\n                  \n                }\n              */\n              for (int i = ii; i < info.ndof; i++)\n                for (int k = 0; k < 2; k++)                \n                  dshapes(i,k) = 0;\n\t    }\n\n\t  /*\t  \n\t   *testout << \"quad, dshape = \" << endl << dshapes << endl;\n\t   for (int i = 0; i < 2; i++)\n\t   {\n\t   Point<2> xil = xi, xir = xi;\n\t   Vector shapesl(dshapes.Height()), shapesr(dshapes.Height());\n\t   xil(i) -= 1e-6;\n\t   xir(i) += 1e-6;\n\t   CalcElementShapes (info, xil, shapesl);\n\t   CalcElementShapes (info, xir, shapesr);\n\t      \n\t   for (int j = 0; j < dshapes.Height(); j++)\n\t   dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j));\n\t   }\n\t  \n\t   *testout << \"quad, num dshape = \" << endl << dshapes << endl;\n\t   */\n\t  break;\n\t}\n      default:\n\tthrow NgException(\"CurvedElements::CalcDShape 2d, element type not handled\");\n\n      };\n  }\n\n  template <int DIM_SPACE, typename T>\n  bool CurvedElements ::\n  EvaluateMapping (SurfaceElementInfo & info, const Point<2,T> xi, Point<DIM_SPACE,T> & mx, Mat<DIM_SPACE,2,T> & jac) const\n  {\n    const Element2d & el = mesh[info.elnr];\n    if (rational && info.order >= 2) return false; // not supported     \n\n    AutoDiff<2,T> x(xi(0), 0);\n    AutoDiff<2,T> y(xi(1), 1);\n\n    AutoDiff<2,T> mapped_x[DIM_SPACE];\n    for (int i = 0; i < DIM_SPACE; i++)\n      mapped_x[i] = AutoDiff<2,T>(0.0);\n    \n    switch (el.GetType())\n      {\n      case TRIG6:\n        {\n          AutoDiff<2,T> lam3 = 1-x-y;\n          AutoDiff<2,T> lami[6] = { x * (2*x-1), y * (2*y-1), lam3 * (2*lam3-1),\n                                    4 * y * lam3, 4 * x * lam3, 4 * x * y };\n          for (int j = 0; j < 6; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < DIM_SPACE; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n          break;\n        }\n        \n      case TRIG:\n        {\n          // if (info.order >= 2) return false; // not yet supported\n          AutoDiff<2,T> lami[4] = { x, y, 1-x-y };\n          for (int j = 0; j < 3; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < DIM_SPACE; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n          if (info.order == 1) break;\n          \n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG);\n\t  for (int i = 0; i < 3; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];\n                  \n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShapeLambda (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2],\n                                             [&](int i, AutoDiff<2,T> shape)\n                                             {\n                                               for (int k = 0; k < DIM_SPACE; k++)\n                                                 mapped_x[k] += edgecoeffs[first+i](k) * shape;\n                                             });\n\t\t}              \n\t    }\n          \n          int forder = faceorder[info.facenr];\n          if (forder >= 3)\n            {\n              int first = facecoeffsindex[info.facenr];\n              \n              int fnums[] = { 0, 1, 2 };\n              if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n              if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n              if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n              \n              CalcScaledTrigShapeLambda (forder, \n                                         lami[fnums[1]]-lami[fnums[0]], lami[fnums[2]], AutoDiff<2,T>(1.0),\n                                         [&](int i, AutoDiff<2,T> shape)\n                                         {\n                                           for (int k = 0; k < DIM_SPACE; k++)\n                                             mapped_x[k] += facecoeffs[first+i](k) * shape;\n                                         });\n            }\n          break;\n        }\n      case QUAD: \n        {\n          AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y };\n          AutoDiff<2,T> mui[4] = { (1-x)+(1-y), x+(1-y), x+y, (1-x)+y };\n          for (int j = 0; j < 4; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < DIM_SPACE; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n          if (info.order == 1) break;\n\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (QUAD);\n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];\n                  \n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n                  auto lame = lami[vi1]+lami[vi2];\n                  CalcEdgeShapeLambda(eorder, mui[vi1]-mui[vi2],\n                                      [&](int i, AutoDiff<2,T> shape)\n                                      {\n                                        for (int k = 0; k < DIM_SPACE; k++)\n                                          mapped_x[k] += edgecoeffs[first+i](k) * (lame*shape);\n                                      });\n\n\t\t}              \n\t    }\n          \n          int forder = faceorder[info.facenr];\n          if (forder >= 2)\n            {\n              int first = facecoeffsindex[info.facenr];\n\n              int fnums[4];\n              int fmin = 0;\n              for (int j = 1; j < 4; j++)\n                if (el[j] < el[fmin]) fmin = j;\n              fnums[0] = fmin;\n              fnums[1] = (fmin+1)%4;\n              fnums[2] = (fmin+2)%4;\n              fnums[3] = (fmin+3)%4;\n              if (el[fnums[3]] < el[fnums[1]]) swap (fnums[1], fnums[3]);\n              \n              AutoDiff<2,T>  mui[4];\n              mui[0] = (1-x)+(1-y);\n              mui[1] = (  x)+(1-y);\n              mui[2] = (  x)+(  y);\n              mui[3] = (1-x)+(  y);\n              \n              CalcQuadShapeLambda (forder,\n                                   // 1-2*x, 1-2*y,\n                                   mui[fnums[1]]-mui[fnums[0]],\n                                   mui[fnums[3]]-mui[fnums[0]], \n                                   [&](int i, AutoDiff<2,T> shape)\n                                   {\n                                     for (int k = 0; k < DIM_SPACE; k++)\n                                       mapped_x[k] += facecoeffs[first+i](k) * shape;\n                                   });\n            }\n\n          \n          \n          break;\n        }\n      case QUAD8:\n        {\n          // AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y };\n          AutoDiff<2,T> lami[8] =\n            { (1-x)*(1-y),\n              x*(1-y),\n              x*y,\n              (1-x)*y,\n              4*(1-x)*x*(1-y),\n              4*(1-x)*x*y,\n              4*(1-y)*y*(1-x), \n              4*(1-y)*y*x };\n          \n          lami[0] -= 0.5*(lami[4]+lami[6]);\n          lami[1] -= 0.5*(lami[4]+lami[7]);\n          lami[2] -= 0.5*(lami[5]+lami[7]);\n          lami[3] -= 0.5*(lami[5]+lami[6]);\n          \n          for (int j = 0; j < 8; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < DIM_SPACE; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n          break;\n        }\n        \n      default:\n        return false;\n      }\n        \n    for (int i = 0; i < DIM_SPACE; i++)\n      {\n        mx(i) = mapped_x[i].Value();\n        for (int j = 0; j < 2; j++)\n          jac(i,j) = mapped_x[i].DValue(j);\n      }\n    return true;\n  }\n\n  template <int DIM_SPACE>\n  void CurvedElements :: \n  GetCoefficients (SurfaceElementInfo & info, NgArray<Vec<DIM_SPACE> > & coefs) const\n  {\n    const Element2d & el = mesh[info.elnr];\n    coefs.SetSize (info.ndof);\n    \n    for (int i = 0; i < info.nv; i++)\n      {\n\tPoint<3> hv = mesh[el[i]];\n\tfor (int j = 0; j < DIM_SPACE; j++)\n\t  coefs[i](j) = hv(j);\n      }\n    \n    if (info.order == 1) return;\n\n    int ii = info.nv;\n\t  \n    for (int i = 0; i < info.edgenrs.Size(); i++)\n      {\n\tint first = edgecoeffsindex[info.edgenrs[i]];\n\tint next = edgecoeffsindex[info.edgenrs[i]+1];\n\tfor (int j = first; j < next; j++, ii++)\n\t  for (int k = 0; k < DIM_SPACE; k++)\n\t    coefs[ii](k) = edgecoeffs[j](k);\n      }\n    \n    int first = facecoeffsindex[info.facenr];\n    int next = facecoeffsindex[info.facenr+1];\n    for (int j = first; j < next; j++, ii++)\n      for (int k = 0; k < DIM_SPACE; k++)\n\tcoefs[ii](k) = facecoeffs[j](k);\n  }\n\n\n  template void CurvedElements :: \n  GetCoefficients<2> (SurfaceElementInfo & info, NgArray<Vec<2> > & coefs) const;\n\n  template void CurvedElements :: \n  GetCoefficients<3> (SurfaceElementInfo & info, NgArray<Vec<3> > & coefs) const;\n\n\n\n\n\n  // ********************** Transform volume elements *******************\n\n\n  bool CurvedElements :: IsElementCurved (ElementIndex elnr) const\n  {\n    if (mesh[elnr].GetType() != TET) return true;\n    \n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\treturn mesh.coarsemesh->GetCurvedElements().IsElementCurved (ElementIndex(hpref_el.coarse_elnr));\n      }\n\n    const Element & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    int nfaces = MeshTopology::GetNFaces (type);\n    if (nfaces > 4)\n      { // not a tet\n\tconst ELEMENT_FACE * faces = MeshTopology::GetFaces0 (type);\n\tfor (int j = 0; j < nfaces; j++)\n\t  {\n\t    if (faces[j][3] != -1)\n\t      {  // a quad face\n\t\tPoint<3> pts[4];\n\t\tfor (int k = 0; k < 4; k++)\n\t\t  pts[k] = mesh.Point(el[faces[j][k]]);\n\t\tVec<3> twist = (pts[1] - pts[0]) - (pts[2]-pts[3]);\n\t\tif (twist.Length() > 1e-8 * (pts[1]-pts[0]).Length())\n\t\t  return true;\n\t      }\n\t  }\n      }\n      \n    \n\n    ElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = MeshTopology::GetNPoints (type);\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        for (auto e : top.GetEdges(elnr))\n          info.ndof += edgecoeffsindex[e+1] - edgecoeffsindex[e];\n        \n        for (auto f : top.GetFaces(elnr))\n          info.ndof += facecoeffsindex[f+1] - facecoeffsindex[f];\n      }\n\n    return (info.ndof > info.nv);\n  }\n\n\n  bool CurvedElements :: IsElementHighOrder (ElementIndex elnr) const\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\treturn mesh.coarsemesh->GetCurvedElements().IsElementHighOrder (ElementIndex(hpref_el.coarse_elnr));\n      }\n\n    const Element & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    ElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = MeshTopology::GetNPoints (type);\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        for (auto e : top.GetEdges(elnr))\n          if (edgecoeffsindex[e+1] > edgecoeffsindex[e]) return true;\n        \n        for (auto f : top.GetFaces(elnr))\n          if (facecoeffsindex[f+1] > facecoeffsindex[f]) return true;\n\n      }\n    return false;\n  }\n\n\n\n\n\n\n  void CurvedElements :: \n  CalcElementTransformation (Point<3> xi, ElementIndex elnr,\n\t\t\t     Point<3> * x, Mat<3,3> * dxdxi, //  bool * curved,\n\t\t\t     void * buffer, bool valid)\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t  \n\t// xi umrechnen\n\tdouble lami[8];\n\tFlatVector vlami(8, lami);\n\tvlami = 0;\n\tmesh[elnr].GetShapeNew<double> (xi, vlami);\n\n\tMat<3,3> trans, dxdxic;\n\tif (dxdxi)\n\t  {\n\t    MatrixFixWidth<3> dlami(8);\n\t    dlami = 0;\n\t    mesh[elnr].GetDShapeNew (xi, dlami);\t  \n\t      \n\t    trans = 0;\n\t    for (int k = 0; k < 3; k++)\n\t      for (int l = 0; l < 3; l++)\n\t\tfor (int i = 0; i < hpref_el.np; i++)\n\t\t  trans(l,k) += hpref_el.param[i][l] * dlami(i, k);\n\t  }\n\n\tPoint<3> coarse_xi(0,0,0);\n\tfor (int i = 0; i < hpref_el.np; i++)\n\t  for (int j = 0; j < 3; j++)\n\t    coarse_xi(j) += hpref_el.param[i][j] * lami[i];\n\n\tmesh.coarsemesh->GetCurvedElements().\n          CalcElementTransformation (coarse_xi, ElementIndex(hpref_el.coarse_elnr), x, &dxdxic /* , curved */);\n\n\tif (dxdxi)\n\t  *dxdxi = dxdxic * trans;\n\n\treturn;\n      }\n\n\n    const Element & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    ElementInfo hinfo;\n    ElementInfo & info = (buffer) ? *static_cast<ElementInfo*> (buffer) : hinfo;\n    \n\n    if (!valid)\n      {\n\tinfo.elnr = elnr;\n\tinfo.order = order;\n\tinfo.ndof = info.nv = MeshTopology::GetNPoints (type);\n\tif (info.order > 1)\n\t  {\n\t    const MeshTopology & top = mesh.GetTopology();\n\n            /*\n\t    info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);\n\t    for (int i = 0; i < info.nedges; i++)\n\t      info.edgenrs[i]--;\n            \n\t    info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);\n\t    for (int i = 0; i < info.nfaces; i++)\n\t      info.facenrs[i]--;\n            */\n            info.SetEdges (top.GetEdges(elnr));\n            info.SetFaces (top.GetFaces(elnr));\n\n            /*\n\t    for (int i = 0; i < info.nedges; i++)\n\t      info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n\t    for (int i = 0; i < info.nfaces; i++)\n\t      info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];\n            */\n\n            for (auto e : info.GetEdges())\n              info.ndof += edgecoeffsindex[e+1] - edgecoeffsindex[e];\n            \n            for (auto f : info.GetFaces())\n              info.ndof += facecoeffsindex[f+1] - facecoeffsindex[f];\n\t  }\n      }\n\n    NgArrayMem<double,100> mem(info.ndof);\n    TFlatVector<double> shapes(info.ndof, &mem[0]);\n    NgArrayMem<double,100> dshapes_mem(info.ndof*3);\n    MatrixFixWidth<3> dshapes(info.ndof, &dshapes_mem[0]);\n    \n    CalcElementShapes (info, xi, shapes);\n\n    Vec<3> * coefs =  (info.ndof <= 10) ? \n      &info.hcoefs[0] : new Vec<3> [info.ndof];\n\n    if (info.ndof > 10 || !valid)\n      GetCoefficients (info, coefs);\n\n    if (x)\n      {\n\t*x = 0;\n\tfor (int i = 0; i < shapes.Size(); i++)\n\t  *x += shapes(i) * coefs[i];\n      }\n\n    if (dxdxi)\n      {\n\tif (valid && info.order == 1 && info.nv == 4)   // a linear tet\n\t  {\n\t    *dxdxi = info.hdxdxi;\n\t  }\n\telse\n\t  {\n\t    CalcElementDShapes (info, xi, dshapes);\n            \n\t    *dxdxi = 0;\n\t    for (int i = 0; i < shapes.Size(); i++)\n\t      for (int j = 0; j < 3; j++)\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);\n            \n\t    info.hdxdxi = *dxdxi;\n\t  }\n      }\n\n    // *testout << \"curved_elements, dshapes = \" << endl << dshapes << endl;\n\n    //    if (curved) *curved = (info.ndof > info.nv);\n\n    if (info.ndof > 10) delete [] coefs;\n  }\n\n\n\n  template <typename T>\n  void CurvedElements :: CalcElementShapes (ElementInfo & info, Point<3,T> xi, TFlatVector<T> shapes) const\n  {\n    const Element & el = mesh[info.elnr];\n\n    if (rational && info.order >= 2)\n      {\n\t// shapes.SetSize(10);\n\tT w = 1;\n\tT lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };\n\tfor (int j = 0; j < 4; j++)\n\t  shapes(j) = lami[j] * lami[j];\n\n\tconst ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET);\n\tfor (int j = 0; j < 6; j++)\n\t  {\n\t    double wi = edgeweight[info.edgenrs[j]];\n\t    shapes(j+4) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t  }\n\n\tshapes *= 1.0 / w;\n\treturn;\n      }\n\n    // shapes.SetSize(info.ndof);\n    \n    switch (el.GetType())\n      {\n      case TET:\n\t{\n\t  shapes(0) = xi(0);\n\t  shapes(1) = xi(1);\n\t  shapes(2) = xi(2);\n\t  shapes(3) = 1-xi(0)-xi(1)-xi(2);\n\n\t  if (info.order == 1) return;\n\n\t  int ii = 4;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET);\n\t  for (int i = 0; i < 6; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET);\n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if (forder >= 3)\n\t\t{\n\t\t  int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; \n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t\t  if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\n\t\t  CalcScaledTrigShape (forder, \n\t\t\t\t       shapes(fnums[1])-shapes(fnums[0]), shapes(fnums[2]), \n\t\t\t\t       shapes(fnums[0])+shapes(fnums[1])+shapes(fnums[2]), &shapes(ii));\n\t\t  ii += (forder-1)*(forder-2)/2;\n\t\t}\n\t    }\n\n\t  break;\n\t}\n        \n      case TET10:\n\t{\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\t  T lam4 = 1 - x - y - z;\n\t  /*\n\t    shapes(0) = xi(0);\n\t    shapes(1) = xi(1);\n\t    shapes(2) = xi(2);\n\t    shapes(3) = 1-xi(0)-xi(1)-xi(2);\n\t  */\n          \n\t  shapes(0) = 2 * x * x - x;  \n\t  shapes(1) = 2 * y * y - y;\n\t  shapes(2) = 2 * z * z - z;\n\t  shapes(3) = 2 * lam4 * lam4 - lam4;\n          \n\t  shapes(4) = 4 * x * y;\n\t  shapes(5) = 4 * x * z;\n\t  shapes(6) = 4 * x * lam4;\n\t  shapes(7) = 4 * y * z;\n\t  shapes(8) = 4 * y * lam4;\n\t  shapes(9) = 4 * z * lam4;\n\n\t  break;\n\t}\n\n      case PRISM:\n\t{\n\t  T lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) };\n\t  T lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };\n\t  for (int i = 0; i < 6; i++)\n\t    shapes(i) = lami[i] * lamiz[i]; \n\t  for (int i = 6; i < info.ndof; i++)\n\t    shapes(i) = 0;\n\n\t  if (info.order == 1) return;\n\n\n\t  int ii = 6;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PRISM);\n\t  for (int i = 0; i < 6; i++)    // horizontal edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShape (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapes(ii));\n\t\t  T facz = (i < 3) ? (1-xi(2)) : xi(2);\n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    shapes(ii+j) *= facz;\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  for (int i = 6; i < 9; i++)    // vertical edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  T bubxy = lami[vi1];\n                  /*\n                  T bubz = lamiz[vi1]*lamiz[vi2];\n                  T polyz = lamiz[vi1] - lamiz[vi2];\n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    {\n\t\t      shapes(ii+j) = bubxy * bubz;\n\t\t      bubz *= polyz;\n\t\t    }\n                  */\n\t\t  CalcEdgeShape (eorder, lamiz[vi1]-lamiz[vi2], &shapes(ii));\n\t\t  for (int j = 0; j < eorder-1; j++)\n                    shapes(ii+j) *= bubxy;\n                  \n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  // FACE SHAPES\n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (PRISM);\n\t  for (int i = 0; i < 2; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if ( forder < 3 ) continue;\n\t      int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \n\t      if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \t\n\n\t      CalcTrigShape (forder, \n\t\t\t     lami[fav[2]]-lami[fav[1]], lami[fav[0]],\n\t\t\t     &shapes(ii));\n\t      \n\t      int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);\n\t      for ( int j = 0; j < ndf; j++ )\n\t\tshapes(ii+j) *= lamiz[fav[1]];\n\t      ii += ndf;\n\t    }\n\t  break;\n\t}\n\n      case PRISM15:\n        {\n\t  shapes = 0.0;\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n          T lam = 1-x-y;\n          T lamz = 1-z;\n          shapes[0] = (2*x*x-x) * (2*lamz*lamz-lamz);\n          shapes[1] = (2*y*y-y) * (2*lamz*lamz-lamz);\n          shapes[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz);\n          shapes[3] = (2*x*x-x) * (2*z*z-z);\n          shapes[4] = (2*y*y-y) * (2*z*z-z);\n          shapes[5] = (2*lam*lam-lam) * (2*z*z-z);\n          shapes[6] = 4 * x * y * (2*lamz*lamz-lamz);\n          shapes[7] = 4 * x * lam * (2*lamz*lamz-lamz);\n          shapes[8] = 4 * y * lam * (2*lamz*lamz-lamz);\n          shapes[9] = x * 4 * z * (1-z);\n          shapes[10] = y * 4 * z * (1-z);\n          shapes[11] = lam * 4 * z * (1-z);\n          shapes[12] = 4 * x * y * (2*z*z-z);\n          shapes[13] = 4 * x * lam * (2*z*z-z);\n          shapes[14] = 4 * y * lam * (2*z*z-z);\n          break;\n        }\n\n      case PYRAMID:\n\t{\n\t  shapes = 0.0;\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\t  \n\t  // if (z == 1.) z = 1-1e-10;\n          z *= (1-1e-12);\n\t  shapes[0] = (1-z-x)*(1-z-y) / (1-z);\n\t  shapes[1] = x*(1-z-y) / (1-z);\n\t  shapes[2] = x*y / (1-z);\n\t  shapes[3] = (1-z-x)*y / (1-z);\n\t  shapes[4] = z;\n          \n\t  if (info.order == 1) return;\n\n          T sigma[4] =\n            {\n              sigma[0] = ( (1-z-x) + (1-z-y) ),\n              sigma[1] = (       x + (1-z-y) ),\n              sigma[2] = (       x +       y ),\n              sigma[3] = ( (1-z-x) +       y ),\n            };\n\n\t  int ii = 5;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PYRAMID);\n\t  for (int i = 0; i < 4; i++)    // horizontal edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n                  CalcScaledEdgeShape (eorder, sigma[vi1]-sigma[vi2], 1-z, &shapes(ii));\n\t\t  T fac = (shapes[vi1]+shapes[vi2]) / (1-z);\n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    shapes(ii+j) *= fac;\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\n\n\t  break;\n\t}\n\n      case PYRAMID13:\n        {\n\t  shapes = 0.0;\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n          z *= 1-1e-12;\n          shapes[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25);\n          shapes[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2));\n          shapes[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75);\n          shapes[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2));\n          shapes[4] = z*(2*z - 1);\n          shapes[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          shapes[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2);\n          shapes[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          shapes[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2);\n          shapes[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1);\n          shapes[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1);\n          shapes[11] = 4*x*y*z/(-z + 1);\n          shapes[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1);\n          break;\n        }\n\n      case HEX:\n\t{\n\t  shapes = 0.0;\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\t  \n\t  shapes[0] = (1-x)*(1-y)*(1-z);\n\t  shapes[1] =    x *(1-y)*(1-z);\n\t  shapes[2] =    x *   y *(1-z);\n\t  shapes[3] = (1-x)*   y *(1-z);\n\t  shapes[4] = (1-x)*(1-y)*(z);\n\t  shapes[5] =    x *(1-y)*(z);\n\t  shapes[6] =    x *   y *(z);\n\t  shapes[7] = (1-x)*   y *(z);\n\n\t  if (info.order == 1) return;\n\t  \n\t  T mu[8] = {\n            (1-x)+(1-y)+(1-z),\n            x    +(1-y)+(1-z),\n            x    +   y +(1-z),\n            (1-x)+   y +(1-z),\n            (1-x)+(1-y)+(z),\n            x    +(1-y)+(z),\n            x    +   y +(z),\n            (1-x)+   y +(z),\n          };\n\t    \n\t  int ii = 8;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX);\n\t  \n\t  for (int i = 0; i < 12; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii));\n\t\t  T lame = shapes(vi1)+shapes(vi2);\n\t\t  for (int j = 0; j < order-1; j++)\n\t\t    shapes(ii+j) *= lame;\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n          \n\t  break;\n        }\n        \n      case HEX20:\n\t{\n\t  shapes = 0.0;\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\t  \n\t  shapes[0] = (1-x)*(1-y)*(1-z);\n\t  shapes[1] =    x *(1-y)*(1-z);\n\t  shapes[2] =    x *   y *(1-z);\n\t  shapes[3] = (1-x)*   y *(1-z);\n\t  shapes[4] = (1-x)*(1-y)*(z);\n\t  shapes[5] =    x *(1-y)*(z);\n\t  shapes[6] =    x *   y *(z);\n\t  shapes[7] = (1-x)*   y *(z);\n\n          T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z),\n                      (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; \n\n          static const int e[12][2] =\n            {\n              { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 },\n              { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 },\n              { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 },\n            };\n          \n          for (int i = 0; i < 12; i++)\n            {\n              T lame = shapes[e[i][0]]+shapes[e[i][1]];\n              T xi = sigma[e[i][1]]-sigma[e[i][0]];\n              shapes[8+i] = (1-xi*xi)*lame;\n            }\n          for (int i = 0; i < 12; i++)\n            {\n              shapes[e[i][0]] -= 0.5 * shapes[8+i];\n              shapes[e[i][1]] -= 0.5 * shapes[8+i];\n            }\n          break;\n\t}\n\n      default:\n\tthrow NgException(\"CurvedElements::CalcShape 3d, element type not handled\");\n\n      };\n  }\n\n\n  template <typename T>\n  void CurvedElements :: \n  CalcElementDShapes (ElementInfo & info, const Point<3,T> xi, MatrixFixWidth<3,T> & dshapes) const\n  {\n    // static int timer = NgProfiler::CreateTimer (\"calcelementdshapes\");\n    \n    const Element & el = mesh[info.elnr];\n\n    // dshapes.SetSize(info.ndof);\n    // if ( (long int)(&dshapes(0,0)) % alignof(T) != 0)\n    // throw NgException (\"alignment problem\");\n    if (dshapes.Height() != info.ndof)\n      throw NgException (\"wrong height\");\n    if (rational && info.order >= 2)\n      {\n\tT w = 1;\n\tT dw[3] = { 0, 0, 0 };\n\n\tT lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };\n\tT dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }};\n\tT shapes[10];\n\n\tfor (int j = 0; j < 4; j++)\n\t  {\n\t    shapes[j] = lami[j] * lami[j];\n\t    dshapes(j,0) = 2 * lami[j] * dlami[j][0];\n\t    dshapes(j,1) = 2 * lami[j] * dlami[j][1];\n\t    dshapes(j,2) = 2 * lami[j] * dlami[j][2];\n\t  }\n\n\tconst ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET);\n\tfor (int j = 0; j < 6; j++)\n\t  {\n\t    T wi = edgeweight[info.edgenrs[j]];\n\n\t    shapes[j+4] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    for (int k = 0; k < 3; k++)\n\t      dshapes(j+4,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +\n\t\t\t\t      lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);\n\n\t    w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];\n\t    for (int k = 0; k < 3; k++)\n\t      dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +\n\t\t\t\t   lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);\n\t  }\n\t// shapes *= 1.0 / w;\n\tdshapes *= 1.0 / w;\n\tfor (int i = 0; i < 10; i++)\n\t  for (int j = 0; j < 3; j++)\n\t    dshapes(i,j) -= shapes[i] * dw[j] / (w*w);\n\treturn;\n      }\n\n    /*\n    if (typeid(T) == typeid(SIMD<double>))\n      {\n        if (el.GetType() == HEX)\n          dshapes = T(0.0);\n        return;\n      }\n    */\n    switch (el.GetType())\n      {\n      case TET:\n\t{\n          // if (typeid(T) == typeid(SIMD<double>)) return;\n          \n          dshapes = T(0.0);\n          \n\t  dshapes(0,0) = 1;\n\t  dshapes(1,1) = 1;\n\t  dshapes(2,2) = 1;\n\t  dshapes(3,0) = -1;\n\t  dshapes(3,1) = -1;\n\t  dshapes(3,2) = -1;\n\n\t  if (info.order == 1) return;\n\n\t  T lami[] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };\n\t  int ii = 4;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET);\n\t  for (int i = 0; i < 6; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShapeDxDt<3> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));\n\n\t\t  Mat<2,3,T> trans;\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    {\n\t\t      trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);\n\t\t      trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);\n\t\t    }\n\t\t  \n\t\t  for (int j = 0; j < order-1; j++)\n\t\t    {\n\t\t      T ddx = dshapes(ii+j,0);\n\t\t      T ddt = dshapes(ii+j,1);\n\t\t      dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);\n\t\t      dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);\n\t\t      dshapes(ii+j,2) = ddx * trans(0,2) + ddt * trans(1,2);\n\t\t    }\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET);\n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if (forder >= 3)\n\t\t{\n\t\t  int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; \n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t\t  if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\n\t\t  CalcScaledTrigShapeDxDyDt (forder, \n\t\t\t\t\t     lami[fnums[1]]-lami[fnums[0]], \n\t\t\t\t\t     lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]],\n\t\t\t\t\t     &dshapes(ii,0));\n\n\t\t  Mat<3,3,T> trans;\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    {\n\t\t      trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);\n\t\t      trans(1,j) = dshapes(fnums[2],j);\n\t\t      trans(2,j) = dshapes(fnums[0],j)+dshapes(fnums[1],j)+dshapes(fnums[2],j);\n\t\t    }\n\t\t  \n\t\t  int nfd = (forder-1)*(forder-2)/2;\n\t\t  for (int j = 0; j < nfd; j++)\n\t\t    {\n\t\t      T ddx = dshapes(ii+j,0);\n\t\t      T ddy = dshapes(ii+j,1);\n\t\t      T ddt = dshapes(ii+j,2);\n\t\t      dshapes(ii+j,0) = ddx * trans(0,0) + ddy * trans(1,0) + ddt * trans(2,0);\n\t\t      dshapes(ii+j,1) = ddx * trans(0,1) + ddy * trans(1,1) + ddt * trans(2,1);\n\t\t      dshapes(ii+j,2) = ddx * trans(0,2) + ddy * trans(1,2) + ddt * trans(2,2);\n\t\t    }\n\n\t\t  ii += nfd;\n\t\t}\n\t    }\n\n\t  break;\n\t}\n\n      case TET10:\n\t{\n          // if (typeid(T) == typeid(SIMD<double>)) return;\n          \n\t  if (dshapes.Height() == 4)\n\t    {\n\t      dshapes = T(0.0);\n\n\t      dshapes(0,0) = 1;\n\t      dshapes(1,1) = 1;\n\t      dshapes(2,2) = 1;\n\t      dshapes(3,0) = -1;\n\t      dshapes(3,1) = -1;\n\t      dshapes(3,2) = -1;\n\t    }\n\t  else\n\t    {\n\t      AutoDiff<3,T> x(xi(0), 0);\n\t      AutoDiff<3,T> y(xi(1), 1);\n\t      AutoDiff<3,T> z(xi(2), 2);\n\t      AutoDiff<3,T> lam4 = 1-x-y-z;\n\t      AutoDiff<3,T> shapes[10];\n              \n\t      shapes[0] = 2 * x * x - x;  \n\t      shapes[1] = 2 * y * y - y;\n\t      shapes[2] = 2 * z * z - z;\n\t      shapes[3] = 2 * lam4 * lam4 - lam4;\n              \n\t      shapes[4] = 4 * x * y;\n\t      shapes[5] = 4 * x * z;\n\t      shapes[6] = 4 * x * lam4;\n\t      shapes[7] = 4 * y * z;\n\t      shapes[8] = 4 * y * lam4;\n\t      shapes[9] = 4 * z * lam4;\n\n\t      for (int i = 0; i < 10; i++)\n\t\t{\n\t\t  dshapes(i,0) = shapes[i].DValue(0);\n\t\t  dshapes(i,1) = shapes[i].DValue(1);\n\t\t  dshapes(i,2) = shapes[i].DValue(2);\n\t\t}\n\t      \n\t    }\n\t  break;\n\n\t  break;\n\t}\n\n\n      case PRISM:\n\t{\n\t  T lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1)  };\n\t  T lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };\n\t  T dlamiz[6] = { -1, -1, -1, 1, 1, 1 };\n\t  T dlami[6][2] = \n\t    { { 1, 0, },\n\t      { 0, 1, },\n\t      { -1, -1 },\n\t      { 1, 0, },\n\t      { 0, 1, },\n\t      { -1, -1 } };\n\t  for (int i = 0; i < 6; i++)\n\t    {\n\t      // shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) );\n\t      dshapes(i,0) = dlami[i%3][0] * ( (i < 3) ? (1-xi(2)) : xi(2) );\n\t      dshapes(i,1) = dlami[i%3][1] * ( (i < 3) ? (1-xi(2)) : xi(2) );\n\t      dshapes(i,2) = lami[i%3] * ( (i < 3) ? -1 : 1 );\n\t    }\n\n\t  int ii = 6;\n\n\t  if (info.order == 1) return;\n          \n\t  NgArrayMem<T, 20> hshapes(order+1), hdshapes(order+1);\n          \n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PRISM);\n\t  for (int i = 0; i < 6; i++)    // horizontal edges\n\t    {\n\t      int order = edgeorder[info.edgenrs[i]];\n\t      if (order >= 2)\n\t\t{\n\t\t  int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\t\t  vi1 = vi1 % 3;\n\t\t  vi2 = vi2 % 3;\n\n                  NgArrayMem<T,20> shapei_mem(order+1);\n\t\t  TFlatVector<T> shapei(order+1, &shapei_mem[0]);\n\t\t  CalcScaledEdgeShapeDxDt<3> (order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0) );\n\t\t  CalcScaledEdgeShape(order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapei(0) );\n\n\t\t  Mat<2,2,T> trans;\n\t\t  for (int j = 0; j < 2; j++)\n\t\t    {\n\t\t      trans(0,j) = dlami[vi1][j]-dlami[vi2][j];\n\t\t      trans(1,j) = dlami[vi1][j]+dlami[vi2][j];\n\t\t    }\n\t\t  \n\t\t  for (int j = 0; j < order-1; j++)\n\t\t    {\n\t\t      T ddx = dshapes(ii+j,0);\n\t\t      T ddt = dshapes(ii+j,1);\n\t\t      dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);\n\t\t      dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);\n\t\t    }\n\n\n\n\t\t  T facz = (i < 3) ? (1-xi(2)) : xi(2);\n\t\t  T dfacz = (i < 3) ? (-1) : 1;\n\t\t  for (int j = 0; j < order-1; j++)\n\t\t    {\n\t\t      dshapes(ii+j,0) *= facz;\n\t\t      dshapes(ii+j,1) *= facz;\n\t\t      dshapes(ii+j,2) = shapei(j) * dfacz;\n\t\t    }\n\n\t\t  ii += order-1;\n\t\t}\n\t    }\n\n          // if (typeid(T) == typeid(SIMD<double>)) return;\n\n\n\t  for (int i = 6; i < 9; i++)    // vertical edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  // T bubz = lamiz[vi1] * lamiz[vi2];\n\t\t  // T dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2];\n\t\t  // T polyz = lamiz[vi1] - lamiz[vi2];\n\t\t  // T dpolyz = dlamiz[vi1] - dlamiz[vi2];\n\t\t  T bubxy = lami[(vi1)%3];\n\t\t  T dbubxydx = dlami[(vi1)%3][0];\n\t\t  T dbubxydy = dlami[(vi1)%3][1];\n                  /*\n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    {\n\t\t      dshapes(ii+j,0) = dbubxydx * bubz;\n\t\t      dshapes(ii+j,1) = dbubxydy * bubz;\n\t\t      dshapes(ii+j,2) = bubxy * dbubz;\n\n\t\t      dbubz = bubz * dpolyz + dbubz * polyz;\n\t\t      bubz *= polyz;\n\t\t    }\n                  */\n\n   \t\t  CalcEdgeShapeDx (eorder, lamiz[vi1]-lamiz[vi2], &hshapes[0], &hdshapes[0]);\n\t\t  for (int j = 0; j < eorder-1; j++)\n                    {\n                      dshapes(ii+j,0) = dbubxydx * hshapes[j];\n                      dshapes(ii+j,1) = dbubxydy * hshapes[j];\n                      dshapes(ii+j,2) = bubxy * hdshapes[j];                      \n                    }\n\n\n                  \n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\n\t  if (info.order == 2) return;\n\t  // FACE SHAPES\n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (PRISM);\n\t  for (int i = 0; i < 2; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\n\t      if ( forder < 3 ) continue;\n\t      int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);\n\n\t      int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \n\t      if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \t\n\n              NgArrayMem<T,2*20> dshapei_mem(ndf);\n              NgArrayMem<T,20> shapei_mem(ndf);\n\t      MatrixFixWidth<2,T> dshapei(ndf, &dshapei_mem[0]);\n\t      TFlatVector<T> shapei(ndf, &shapei_mem[0]);\n\n\t      CalcTrigShapeDxDy (forder, \n\t\t\t\t lami[fav[2]]-lami[fav[1]], lami[fav[0]],\n\t\t\t\t &dshapei(0,0));\n\t      CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]],\n\t\t\t     &shapei(0));\n\t      \n\t      Mat<2,2,T> trans;\n\t      for (int j = 0; j < 2; j++)\n\t\t{\n\t\t  trans(0,j) = dlami[fav[2]][j]-dlami[fav[1]][j];\n\t\t  trans(1,j) = dlami[fav[0]][j];\n\t\t}\n\t\t  \n\t      for (int j = 0; j < ndf; j++)\n\t\t{\n\t\t  // double ddx = dshapes(ii+j,0);\n\t\t  // double ddt = dshapes(ii+j,1);\n\t\t  T ddx = dshapei(j,0);\n\t\t  T ddt = dshapei(j,1);\n\t\t  dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);\n\t\t  dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);\n\t\t}\n\n\t      for ( int j = 0; j < ndf; j++ )\n\t\t{\n\t\t  dshapes(ii+j,0) *= lamiz[fav[1]];\n\t\t  dshapes(ii+j,1) *= lamiz[fav[1]];\n\t\t  dshapes(ii+j,2) = shapei(j) * dlamiz[fav[1]];\n\t\t}\n\t      ii += ndf;\n\t    }\n\n\t  break;\n\n\t}\n\n      case PRISM15:\n        {\n          AutoDiff<3,T> x(xi(0), 0);\n          AutoDiff<3,T> y(xi(1), 1);\n          AutoDiff<3,T> z(xi(2), 2);\n          AutoDiff<3,T> ad[15];\n          AutoDiff<3,T> lam = 1-x-y;\n          AutoDiff<3,T> lamz = 1-z;\n\n          ad[0] = (2*x*x-x) * (2*lamz*lamz-lamz);\n          ad[1] = (2*y*y-y) * (2*lamz*lamz-lamz);\n          ad[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz);\n          ad[3] = (2*x*x-x) * (2*z*z-z);\n          ad[4] = (2*y*y-y) * (2*z*z-z);\n          ad[5] = (2*lam*lam-lam) * (2*z*z-z);\n          ad[6] = 4 * x * y * (2*lamz*lamz-lamz);\n          ad[7] = 4 * x * lam * (2*lamz*lamz-lamz);\n          ad[8] = 4 * y * lam * (2*lamz*lamz-lamz);\n          ad[9] = x * 4 * z * (1-z);\n          ad[10] = y * 4 * z * (1-z);\n          ad[11] = lam * 4 * z * (1-z);\n          ad[12] = 4 * x * y * (2*z*z-z);\n          ad[13] = 4 * x * lam * (2*z*z-z);\n          ad[14] = 4 * y * lam * (2*z*z-z);\n\n          for(int i=0; i<15; i++)\n            for(int j=0; j<3; j++)\n              dshapes(i,j) = ad[i].DValue(j);\n          break;\n        }\n      case PYRAMID:\n\t{\n          // if (typeid(T) == typeid(SIMD<double>)) return;\n          \n\t  dshapes = T(0.0);\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\t  \n\t  // if (z == 1.) z = 1-1e-10;\n          z *= 1-1e-12;\n\t  T z1 = 1-z;\n\t  T z2 = z1*z1;\n\t  \n\t  dshapes(0,0) = -(z1-y)/z1;\n\t  dshapes(0,1) = -(z1-x)/z1;\n\t  dshapes(0,2) = ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2;\n\n\t  dshapes(1,0) = (z1-y)/z1;\n\t  dshapes(1,1) = -x/z1;\n\t  dshapes(1,2) = (-x*z1+x*(z1-y))/z2;\n\n\t  dshapes(2,0) = y/z1;\n\t  dshapes(2,1) = x/z1;\n\t  dshapes(2,2) = x*y/z2;\n\n\t  dshapes(3,0) = -y/z1;\n\t  dshapes(3,1) = (z1-x)/z1;\n\t  dshapes(3,2) = (-y*z1+y*(z1-x))/z2;\n\n\t  dshapes(4,0) = 0;\n\t  dshapes(4,1) = 0;\n\t  dshapes(4,2) = 1;\n\n\t  if (info.order == 1) return;\n\n\t  int ii = 5;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PYRAMID);\n\t  // if (z == 1.) z = 1-1e-10;\n          z *= 1-1e-12;\n          T shapes[5];\n\t  shapes[0] = (1-z-x)*(1-z-y) / (1-z);\n\t  shapes[1] = x*(1-z-y) / (1-z);\n\t  shapes[2] = x*y / (1-z);\n\t  shapes[3] = (1-z-x)*y / (1-z);\n\t  shapes[4] = z;\n\n          T sigma[4] =\n            {\n              ( (1-z-x) + (1-z-y) ),\n              (       x + (1-z-y) ),\n              (       x +       y ),\n              ( (1-z-x) +       y ),\n            };\n          T dsigma[4][3] =\n            {\n              { -1, -1, -2 },\n              { 1, -1, -1 },\n              { 1, 1, 0 },\n              { -1, 1, -1 }\n            };\n          T dz[3] = { 0, 0, 1 };\n\t  for (int i = 0; i < 4; i++)    // horizontal edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n                  NgArrayMem<T,20> shapei_mem(eorder+1);\n\t\t  TFlatVector<T> shapei(eorder+1,&shapei_mem[0]);\n\t\t  CalcScaledEdgeShapeDxDt<3> (eorder, sigma[vi1]-sigma[vi2], 1-z, &dshapes(ii,0) );\n\t\t  CalcScaledEdgeShape(eorder, sigma[vi1]-sigma[vi2], 1-z, &shapei(0) );\n\t\t  T fac = (shapes[vi1]+shapes[vi2]) / (1-z);\n                  T dfac[3];\n                  for (int k = 0; k < 3; k++)\n                    dfac[k] = ( (dshapes(vi1,k)+dshapes(vi2,k)) * (1-z) -\n                                (shapes[vi1]+shapes[vi2]) *(-dshapes(4,k)) )\n                      / sqr(1-z);\n                      \n\t\t  for (int j = 0; j < eorder-1; j++)\n                    {\n                      T ddx = dshapes(ii+j,0);\n                      T ddt = dshapes(ii+j,1);\n                      for (int k = 0; k < 3; k++)\n                        dshapes(ii+j,k) = fac * (ddx * (dsigma[vi1][k]-dsigma[vi2][k]) - ddt*dz[k])\n                          + dfac[k] * shapei(j);\n                    }\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n          \n\t  break;\n\t}\n\n      case PYRAMID13:\n        {\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n          z *= 1-1e-12;\n          dshapes(0,0) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1) - 4);\n          dshapes(0,1) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1) - 4);\n          dshapes(0,2) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 5 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1));\n          dshapes(1,0) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(-2*y - z + 2) + (0.5*x - 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1) + 4);\n          dshapes(1,1) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*x + z)*(-2*y - z + 2) + (-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x - 0.5*y - 0.25);\n          dshapes(1,2) = (0.5*x - 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1));\n          dshapes(2,0) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75);\n          dshapes(2,1) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75);\n          dshapes(2,2) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (0.5*x + 0.5*y + 0.5*z - 0.75)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 1 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1));\n          dshapes(3,0) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1));\n          dshapes(3,1) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1) + 4);\n          dshapes(3,2) = (-0.5*x + 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1));\n          dshapes(4,0) = 0;\n          dshapes(4,1) = 0;\n          dshapes(4,2) = 4*z - 1;\n          dshapes(5,0) = -4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          dshapes(5,1) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2);\n          dshapes(5,2) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2) - 4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 4*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2));\n          dshapes(6,0) = -8*x*y/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)/(-2*z + 2);\n          dshapes(6,1) = 4*x*(-2*x - 2*z + 2)/(-2*z + 2);\n          dshapes(6,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*x - 2*z + 2)/((-2*z + 2)*(-2*z + 2));\n          dshapes(7,0) = -4*y*(-2*y - 2*z + 2)/(-2*z + 2);\n          dshapes(7,1) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          dshapes(7,2) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) - 4*y*(-2*y - 2*z + 2)/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2));\n          dshapes(8,0) = 4*y*(-2*y - 2*z + 2)/(-2*z + 2);\n          dshapes(8,1) = -8*x*y/(-2*z + 2) + 4*x*(-2*y - 2*z + 2)/(-2*z + 2);\n          dshapes(8,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2));\n          dshapes(9,0) = -2*z*(-2*y - 2*z + 2)/(-z + 1);\n          dshapes(9,1) = -2*z*(-2*x - 2*z + 2)/(-z + 1);\n          dshapes(9,2) = -2*z*(-2*x - 2*z + 2)/(-z + 1) - 2*z*(-2*y - 2*z + 2)/(-z + 1) + z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + (-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1);\n          dshapes(10,0) = 2*z*(-2*y - 2*z + 2)/(-z + 1);\n          dshapes(10,1) = -4*x*z/(-z + 1);\n          dshapes(10,2) = -4*x*z/(-z + 1) + 2*x*z*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*x*(-2*y - 2*z + 2)/(-z + 1);\n          dshapes(11,0) = 4*y*z/(-z + 1);\n          dshapes(11,1) = 4*x*z/(-z + 1);\n          dshapes(11,2) = 4*x*y*z/((-z + 1)*(-z + 1)) + 4*x*y/(-z + 1);\n          dshapes(12,0) = -4*y*z/(-z + 1);\n          dshapes(12,1) = 2*z*(-2*x - 2*z + 2)/(-z + 1);\n          dshapes(12,2) = -4*y*z/(-z + 1) + 2*y*z*(-2*x - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*y*(-2*x - 2*z + 2)/(-z + 1);\n          break;\n        }\n\n      case HEX:\n\t{\n          // if (typeid(T) == typeid(SIMD<double>)) return;\n          \n          // NgProfiler::StartTimer(timer);\n\t  T x = xi(0);\n\t  T y = xi(1);\n\t  T z = xi(2);\n\n\t  // shapes[0] = (1-x)*(1-y)*(1-z);\n\t  dshapes(0,0) = - (1-y)*(1-z);\n\t  dshapes(0,1) = (1-x) * (-1) * (1-z);\n\t  dshapes(0,2) = (1-x) * (1-y) * (-1);\n\n\t  // shapes[1] =    x *(1-y)*(1-z);\n\t  dshapes(1,0) = (1-y)*(1-z);\n\t  dshapes(1,1) = -x * (1-z);\n\t  dshapes(1,2) = -x * (1-y);\n\n\t  // shapes[2] =    x *   y *(1-z);\n\t  dshapes(2,0) = y * (1-z);\n\t  dshapes(2,1) = x * (1-z);\n\t  dshapes(2,2) = -x * y;\n\n\t  // shapes[3] = (1-x)*   y *(1-z);\n\t  dshapes(3,0) = -y * (1-z);\n\t  dshapes(3,1) = (1-x) * (1-z);\n\t  dshapes(3,2) = -(1-x) * y;\n\n\t  // shapes[4] = (1-x)*(1-y)*z;\n\t  dshapes(4,0) = - (1-y)*z;\n\t  dshapes(4,1) = (1-x) * (-1) * z;\n\t  dshapes(4,2) = (1-x) * (1-y) * 1;\n\n\t  // shapes[5] =    x *(1-y)*z;\n\t  dshapes(5,0) = (1-y)*z;\n\t  dshapes(5,1) = -x * z;\n\t  dshapes(5,2) = x * (1-y);\n\n\t  // shapes[6] =    x *   y *z;\n\t  dshapes(6,0) = y * z;\n\t  dshapes(6,1) = x * z;\n\t  dshapes(6,2) = x * y;\n\n\t  // shapes[7] = (1-x)*   y *z;\n\t  dshapes(7,0) = -y * z;\n\t  dshapes(7,1) = (1-x) * z;\n\t  dshapes(7,2) = (1-x) * y;\n\n          // NgProfiler::StopTimer(timer);\n\n\t  if (info.order == 1) return;          \n\n\t  T shapes[8] = {\n            (1-x)*(1-y)*(1-z),\n               x *(1-y)*(1-z),\n               x *   y *(1-z),\n            (1-x)*   y *(1-z),\n            (1-x)*(1-y)*(z),\n               x *(1-y)*(z),\n               x *   y *(z),\n            (1-x)*   y *(z),\n\t  };\n\n\t  T mu[8] = {\n            (1-x)+(1-y)+(1-z),\n            x    +(1-y)+(1-z),\n            x    +   y +(1-z),\n            (1-x)+   y +(1-z),\n            (1-x)+(1-y)+(z),\n            x    +(1-y)+(z),\n            x    +   y +(z),\n            (1-x)+   y +(z)\n\t  };\n\n\t  T dmu[8][3] = {\n\t    { -1, -1, -1 },\n\t    { 1, -1, -1 },\n\t    { 1, 1, -1 },\n\t    { -1, 1, -1 },\n\t    { -1, -1, 1 },\n\t    { 1, -1, 1 },\n\t    { 1, 1, 1 },\n\t    { -1, 1, 1 }\n          };\n\t    \n\t  NgArrayMem<T, 20> hshapes(order+1), hdshapes(order+1);\n\n\t  int ii = 8;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX);\n\t  for (int i = 0; i < 12; i++) \n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]);\n\n\t\t  T lame = shapes[vi1]+shapes[vi2];\n\t\t  T dlame[3] = {\n\t\t    dshapes(vi1, 0) + dshapes(vi2, 0),\n\t\t    dshapes(vi1, 1) + dshapes(vi2, 1),\n                    dshapes(vi1, 2) + dshapes(vi2, 2)\n                  };\n\t\t    \n\t\t  for (int j = 0; j < eorder-1; j++)\n\t\t    for (int k = 0; k < 3; k++)\n\t\t      dshapes(ii+j, k) = \n\t\t\tlame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k])\n\t\t\t+ dlame[k] * hshapes[j];\n\n\t\t  ii += eorder-1;\n\t\t}\n\t    }\n\n\t  /*\t  \n\t   *testout << \"quad, dshape = \" << endl << dshapes << endl;\n\t   for (int i = 0; i < 2; i++)\n\t   {\n\t   Point<2> xil = xi, xir = xi;\n\t   Vector shapesl(dshapes.Height()), shapesr(dshapes.Height());\n\t   xil(i) -= 1e-6;\n\t   xir(i) += 1e-6;\n\t   CalcElementShapes (info, xil, shapesl);\n\t   CalcElementShapes (info, xir, shapesr);\n\t      \n\t   for (int j = 0; j < dshapes.Height(); j++)\n\t   dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j));\n\t   }\n\t  \n\t   *testout << \"quad, num dshape = \" << endl << dshapes << endl;\n\t   */\n\t  break;\n\t}\n      case HEX20:\n        {\n          AutoDiff<3,T> x(xi(0), 0);\n          AutoDiff<3,T> y(xi(1), 1);\n          AutoDiff<3,T> z(xi(2), 2);\n          AutoDiff<3,T> ad[20];\n          \n          ad[0] = (1-x)*(1-y)*(1-z);\n\t  ad[1] =    x *(1-y)*(1-z);\n\t  ad[2] =    x *   y *(1-z);\n\t  ad[3] = (1-x)*   y *(1-z);\n\t  ad[4] = (1-x)*(1-y)*(z);\n\t  ad[5] =    x *(1-y)*(z);\n\t  ad[6] =    x *   y *(z);\n\t  ad[7] = (1-x)*   y *(z);\n          \n          AutoDiff<3,T> sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z),\n                                  (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; \n          \n          static const int e[12][2] =\n            {\n              { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 },\n              { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 },\n              { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 },\n            };\n          \n          for (int i = 0; i < 12; i++)\n            {\n              auto lame = ad[e[i][0]]+ad[e[i][1]];\n              auto xi = sigma[e[i][1]]-sigma[e[i][0]];\n              ad[8+i] = (1-xi*xi)*lame;\n            }\n          for (int i = 0; i < 12; i++)\n            {\n              ad[e[i][0]] -= 0.5 * ad[8+i];\n              ad[e[i][1]] -= 0.5 * ad[8+i];\n            }\n          for (int i = 0; i < 20; i++)\n            for (int j = 0; j < 3; j++)\n              dshapes(i,j) = ad[i].DValue(j);\n          break;\n        }\n      default:\n\tthrow NgException(\"CurvedElements::CalcDShape 3d, element type not handled\");\n      }\n    \n    /*\n      DenseMatrix dshapes2 (info.ndof, 3);\n      Vector shapesl(info.ndof); \n      Vector shapesr(info.ndof); \n    \n      double eps = 1e-6;\n      for (int i = 0; i < 3; i++)\n      {\n      Point<3> xl = xi;\n      Point<3> xr = xi;\n\t\n      xl(i) -= eps;\n      xr(i) += eps;\n      CalcElementShapes (info, xl, shapesl);\n      CalcElementShapes (info, xr, shapesr);\n\t\n      for (int j = 0; j < info.ndof; j++)\n      dshapes2(j,i) = (shapesr(j)-shapesl(j)) / (2*eps);\n      }\n      (*testout) << \"dshapes = \" << endl << dshapes << endl;\n      (*testout) << \"dshapes2 = \" << endl << dshapes2 << endl;\n      dshapes2 -= dshapes;\n      (*testout) << \"diff = \" << endl << dshapes2 << endl;\n    */\n  }\n\n  // extern int mappingvar;\n  template <typename T>\n  bool CurvedElements ::\n  EvaluateMapping (ElementInfo & info, Point<3,T> xi, Point<3,T> & mx, Mat<3,3,T> & jac) const\n  {\n    const Element & el = mesh[info.elnr];\n    if (rational && info.order >= 2) return false; // not supported     \n\n    AutoDiff<3,T> x(xi(0), 0);\n    AutoDiff<3,T> y(xi(1), 1);\n    AutoDiff<3,T> z(xi(2), 2);\n\n    AutoDiff<3,T> mapped_x[3] = { T(0.0), T(0.0), T(0.0) } ;\n    \n    switch (el.GetType())\n      {\n      case TET:\n        {\n          // if (info.order >= 2) return false; // not yet supported\n          AutoDiff<3,T> lami[4] = { x, y, z, 1-x-y-z };\n          for (int j = 0; j < 4; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < 3; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n          if (info.order == 1) break;\n\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET);\n\t  for (int i = 0; i < 6; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];\n                  \n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShapeLambda (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2],\n                                             [&](int i, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = edgecoeffs[first+i];\n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * shape;\n                                             });\n\t\t}              \n\t    }\n          \n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET);\n\t  for (int i = 0; i < 4; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if (forder >= 3)\n\t\t{\n                  int first = facecoeffsindex[info.facenrs[i]];\n                  \n\t\t  int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; \n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\t\t  if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);\n\t\t  if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);\n\n\t\t  CalcScaledTrigShapeLambda (forder, \n                                             lami[fnums[1]]-lami[fnums[0]], lami[fnums[2]], \n                                             lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]],\n                                             [&](int i, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = facecoeffs[first+i];\n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * shape;\n                                             });\n                }\n\t    }\n          \n          break;\n        }\n      case HEX:\n        {\n          // if (info.order >= 2) return false; // not yet supported          \n          AutoDiff<3,T> lami[8] =\n            { (1-x)*(1-y)*(1-z),\n              (  x)*(1-y)*(1-z),\n              (  x)*   y *(1-z),\n              (1-x)*   y *(1-z),\n              (1-x)*(1-y)*(z),\n              (  x)*(1-y)*(z),\n              (  x)*   y *(z),\n              (1-x)*   y *(z) };\n\n          for (int j = 0; j < 8; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < 3; k++)\n                mapped_x[k] += p(k) * lami[j];\n            }\n\n\t  if (info.order == 1) break;\n\n\t  AutoDiff<3,T> mu[8] = {\n            (1-x)+(1-y)+(1-z),\n            x    +(1-y)+(1-z),\n            x    +   y +(1-z),\n            (1-x)+   y +(1-z),\n            (1-x)+(1-y)+(z),\n            x    +(1-y)+(z),\n            x    +   y +(z),\n            (1-x)+   y +(z),\n          };\n\t  // int ii = 8;\n\t  const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX);\n\t  const ELEMENT_FACE * faces = MeshTopology::GetFaces0 (HEX);\n          \n\t  for (int i = 0; i < 12; i++)\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];                  \n\t\t  int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n                  AutoDiff<3,T> lame = lami[vi1]+lami[vi2];\n\t\t  CalcEdgeShapeLambda (eorder, mu[vi1]-mu[vi2], \n                                       [&](int i, AutoDiff<3,T> shape)\n                                       {\n                                         Vec<3> coef = edgecoeffs[first+i];\n                                         for (int k = 0; k < 3; k++)\n                                           mapped_x[k] += coef(k) * (lame*shape);\n                                       });\n                  \n\t\t}\n\t    }\n\n\n\t  for (int i = 0; i < 6; i++)\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if (forder >= 2)\n\t\t{\n                  int first = facecoeffsindex[info.facenrs[i]];\n                  \n                  int fmin = 0;\n                  for (int j = 1; j < 4; j++)\n                    if (el[faces[i][j]] < el[faces[i][fmin]]) fmin = j;\n\n                  int fx = (fmin+1)%4;\n                  int fy = (fmin+3)%4;\n                  if (el[faces[i][fy]] < el[faces[i][fx]]) swap(fx,fy);\n\n                  auto lamf = lami[faces[i][0]] + lami[faces[i][1]] + lami[faces[i][2]] + lami[faces[i][3]];\n                  CalcQuadShapeLambda (forder,\n                                       mu[faces[i][fx]]-mu[faces[i][fmin]],\n                                       mu[faces[i][fy]]-mu[faces[i][fmin]],\n                                       [&](int i, AutoDiff<3,T> shape)\n                                       {\n                                         for (int k = 0; k < 3; k++)\n                                           mapped_x[k] += facecoeffs[first+i](k) * lamf * shape;\n                                       });\n                }\n            }\n          \n          break;\n        }\n      case PRISM:\n\t{\n\t  AutoDiff<3,T> lami[6] = { x, y,1-x-y, x, y, 1-x-y };\n\t  AutoDiff<3,T> lamiz[6] = { 1-z, 1-z, 1-z, z, z, z };\n          AutoDiff<3,T> sigma[6];\n          for (int i = 0; i < 6; i++) sigma[i] = lami[i] + lamiz[i];\n\n\t  for (int j = 0; j < 6; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < 3; k++)\n                mapped_x[k] += p(k) * (lami[j]*lamiz[j]);\n            }\n\n\t  if (info.order == 1) break;\n\n\t  auto edges = MeshTopology::GetEdges (PRISM);\n\t  for (int i = 0; i < 6; i++)    // horizontal edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];                  \n\t\t  int vi1 = edges[i][0], vi2 = edges[i][1];\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\n\t\t  CalcScaledEdgeShapeLambda (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2],\n                                             [&](int j, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = edgecoeffs[first+j];\n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * (lamiz[vi1]*shape);\n                                             });\n\t\t}\n\t    }\n\n\t  for (int i = 6; i < 9; i++)    // vertical edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];                  \n\t\t  int vi1 = edges[i][0], vi2 = edges[i][1];\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n\t\t  auto bubxy = lami[vi1];\n                  \n\t\t  CalcEdgeShapeLambda (eorder, lamiz[vi1]-lamiz[vi2],\n                                       [&](int j, AutoDiff<3,T> shape)\n                                       {\n                                         Vec<3> coef = edgecoeffs[first+j];\n                                         for (int k = 0; k < 3; k++)\n                                           mapped_x[k] += coef(k) * (bubxy*shape);\n                                       });\n\t\t}\n\t    }\n\n\t  // FACE SHAPES\n\t  auto faces = MeshTopology::GetFaces0 (PRISM);\n\t  for (int i = 0; i < 2; i++)   // triangular faces\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if ( forder < 3 ) continue;\n              \n              int first = facecoeffsindex[info.facenrs[i]];              \n\t      int fav[3] = { faces[i][0], faces[i][1], faces[i][2] };\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \n\t      if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);\n\t      if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); \t\n\n              auto lamf = lamiz[fav[0]];\n\t      CalcScaledTrigShapeLambda (forder, \n                                         lami[fav[2]]-lami[fav[1]], lami[fav[0]], AutoDiff<3,T>(1.0),\n                                         [&](int j, AutoDiff<3,T> shape)\n                                         {\n                                           Vec<3> coef = facecoeffs[first+j];            \n                                           for (int k = 0; k < 3; k++)\n                                             mapped_x[k] += coef(k) * lamf * shape;\n                                         });\n\t    }\n\n\t  for (int i = 2; i < 5; i++)  // quad faces\n\t    {\n\t      int forder = faceorder[info.facenrs[i]];\n\t      if (forder >= 2)\n\t\t{\n                  int first = facecoeffsindex[info.facenrs[i]];\n                  \n                  int fmin = 0;\n                  for (int j = 1; j < 4; j++)\n                    if (el[faces[i][j]] < el[faces[i][fmin]]) fmin = j;\n\n                  int fx = (fmin+1)%4;\n                  int fy = (fmin+3)%4;\n                  if (el[faces[i][fy]] < el[faces[i][fx]]) swap(fx,fy);\n                  \n                  auto xi = sigma[faces[i][fx]]-sigma[faces[i][fmin]];\n                  auto eta = sigma[faces[i][fy]]-sigma[faces[i][fmin]];\n                    \n                  AutoDiff<3,T> scalexi(1.0), scaleeta(1.0);\n                  if (faces[i][fmin] / 3 == faces[i][fx] / 3)  \n                    scalexi = lami[faces[i][fmin]]+lami[faces[i][fx]];  // xi is horizontal\n                  else\n                    scaleeta = lami[faces[i][fmin]]+lami[faces[i][fy]];\n                  \n                  CalcScaledQuadShapeLambda (forder, \n                                             xi, eta, scalexi, scaleeta, \n                                             [&](int j, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = facecoeffs[first+j];            \n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * shape;\n                                             });\n                }\n            }\n\n          \n\t  break;\n        }\n          \n      case PYRAMID:\n\t{\n          z *= (1-1e-10);\n          \n          auto xt = x / (1-z);\n          auto yt = y / (1-z);\n          \n          AutoDiff<3,T> sigma[4]  = { (1-xt)+(1-yt), xt+(1-yt), xt+yt, (1-xt)+yt };\n          AutoDiff<3,T> lambda[4] = { (1-xt)*(1-yt), xt*(1-yt), xt*yt, (1-xt)*yt };\n          AutoDiff<3,T> lambda3d[5];\n          \n          for (int i = 0; i < 4; i++)  \n            lambda3d[i] = lambda[i] * (1-z);\n          lambda3d[4] = z;\n          \n\t  for (int j = 0; j < 5; j++)\n            {\n              Point<3> p = mesh[el[j]];\n              for (int k = 0; k < 3; k++)\n                mapped_x[k] += p(k) * lambda3d[j];\n            }\n\n\t  if (info.order == 1) break;\n\n\t  auto edges = MeshTopology::GetEdges (PYRAMID);\n\t  for (int i = 0; i < 4; i++)    // horizontal edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];                  \n\t\t  int vi1 = edges[i][0], vi2 = edges[i][1];\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n                  \n\t\t  CalcScaledEdgeShapeLambda (eorder, (sigma[vi1]-sigma[vi2])*(1-z),\n                                             1-z,\n                                             [&](int j, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = edgecoeffs[first+j];\n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * shape;\n                                             });\n\t\t}\n\t    }\n\n\t  for (int i = 4; i < 8; i++)    // vertical edges\n\t    {\n\t      int eorder = edgeorder[info.edgenrs[i]];\n\t      if (eorder >= 2)\n\t\t{\n                  int first = edgecoeffsindex[info.edgenrs[i]];                  \n\t\t  int vi1 = edges[i][0], vi2 = edges[i][1];\n\t\t  if (el[vi1] > el[vi2]) swap (vi1, vi2);\n                  \n\t\t  CalcScaledEdgeShapeLambda (eorder, lambda3d[vi1]-lambda3d[vi2],\n                                             lambda3d[vi1]+lambda3d[vi2],\n                                             [&](int j, AutoDiff<3,T> shape)\n                                             {\n                                               Vec<3> coef = edgecoeffs[first+j];\n                                               for (int k = 0; k < 3; k++)\n                                                 mapped_x[k] += coef(k) * shape;\n                                             });\n\t\t}\n\t    }\n          \n          // TODO: face dofs\n          break;\n        }\n        \n      default:\n        return false;\n      }\n\n    for (int i = 0; i < 3; i++)\n      {\n        mx(i) = mapped_x[i].Value();\n        for (int j = 0; j < 3; j++)\n          jac(i,j) = mapped_x[i].DValue(j);\n      }\n    return true;\n  }\n  \n\n\n\n  \n  void CurvedElements :: \n  GetCoefficients (ElementInfo & info, Vec<3> * coefs) const\n  {\n    const Element & el = mesh[info.elnr];\n\n    for (int i = 0; i < info.nv; i++)\n      coefs[i] = Vec<3> (mesh[el[i]]);\n\n    if (info.order == 1) return;\n\n    int ii = info.nv;\n\t  \n    for (int i = 0; i < info.nedges; i++)\n      {\n\tint first = edgecoeffsindex[info.edgenrs[i]];\n\tint next = edgecoeffsindex[info.edgenrs[i]+1];\n\tfor (int j = first; j < next; j++, ii++)\n\t  coefs[ii] = edgecoeffs[j];\n      }\n    for (int i = 0; i < info.nfaces; i++)\n      {\n\tint first = facecoeffsindex[info.facenrs[i]];\n\tint next = facecoeffsindex[info.facenrs[i]+1];\n\tfor (int j = first; j < next; j++, ii++)\n\t  coefs[ii] = facecoeffs[j];\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  /*\n  void CurvedElements :: \n  CalcMultiPointSegmentTransformation (NgArray<double> * xi, SegmentIndex segnr,\n\t\t\t\t       NgArray<Point<3> > * x,\n\t\t\t\t       NgArray<Vec<3> > * dxdxi)\n  {\n    ;\n  }\n  */\n\n  template <int DIM_SPACE, typename T>\n  void CurvedElements :: \n  CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n,\n\t\t\t\t       const T * xi, size_t sxi,\n\t\t\t\t       T * x, size_t sx,\n\t\t\t\t       T * dxdxi, size_t sdxdxi)\n  {\n    for (int ip = 0; ip < n; ip++)\n      {\n\tPoint<3,T> xg;\n\tVec<3,T> dx;\n\n\t// mesh->GetCurvedElements().\n\tCalcSegmentTransformation<T> (xi[ip*sxi], elnr, &xg, &dx);\n      \n\tif (x)\n\t  for (int i = 0; i < DIM_SPACE; i++)\n\t    x[ip*sx+i] = xg(i);\n\t  \n\tif (dxdxi)\n\t  for (int i=0; i<DIM_SPACE; i++)\n\t    dxdxi[ip*sdxdxi+i] = dx(i);\n      }\n  }\n\n\n  template void CurvedElements :: \n  CalcMultiPointSegmentTransformation<2> (SegmentIndex elnr, int npts,\n\t\t\t\t\t  const double * xi, size_t sxi,\n\t\t\t\t\t  double * x, size_t sx,\n\t\t\t\t\t  double * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcMultiPointSegmentTransformation<3> (SegmentIndex elnr, int npts,\n\t\t\t\t\t  const double * xi, size_t sxi,\n\t\t\t\t\t  double * x, size_t sx,\n\t\t\t\t\t  double * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcMultiPointSegmentTransformation<2> (SegmentIndex elnr, int npts,\n\t\t\t\t\t  const SIMD<double> * xi, size_t sxi,\n\t\t\t\t\t  SIMD<double> * x, size_t sx,\n\t\t\t\t\t  SIMD<double> * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcMultiPointSegmentTransformation<3> (SegmentIndex elnr, int npts,\n\t\t\t\t\t  const SIMD<double> * xi, size_t sxi,\n\t\t\t\t\t  SIMD<double> * x, size_t sx,\n\t\t\t\t\t  SIMD<double> * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcSegmentTransformation<double> (const double & xi, SegmentIndex elnr,\n                                     Point<3,double> * x, Vec<3,double> * dxdxi, bool * curved);\n\n\n  void CurvedElements :: \n  CalcMultiPointSurfaceTransformation (NgArray< Point<2> > * xi, SurfaceElementIndex elnr,\n\t\t\t\t       NgArray< Point<3> > * x,\n\t\t\t\t       NgArray< Mat<3,2> > * dxdxi)\n  {\n    double * px = (x) ? &(*x)[0](0) : NULL;\n    double * pdxdxi = (dxdxi) ? &(*dxdxi)[0](0) : NULL;\n\n    CalcMultiPointSurfaceTransformation <3> (elnr, xi->Size(),\n\t\t\t\t\t     &(*xi)[0](0), 2, \n\t\t\t\t\t     px, 3,\n\t\t\t\t\t     pdxdxi, 6);\n  }\n\n\n\n\n  template <int DIM_SPACE, typename T>\n  void CurvedElements :: \n  CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int npts,\n\t\t\t\t       const T * xi, size_t sxi,\n\t\t\t\t       T * x, size_t sx,\n\t\t\t\t       T * dxdxi, size_t sdxdxi)\n  {\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\t// xi umrechnen\n\tT lami[4];\n\tTFlatVector<T> vlami(4, lami);\n\n\tArrayMem<Point<2,T>, 50> coarse_xi (npts);\n\t\n\tfor (int pi = 0; pi < npts; pi++)\n\t  {\n\t    vlami = 0;\n\t    Point<2,T> hxi(xi[pi*sxi], xi[pi*sxi+1]);\n\t    mesh[elnr].GetShapeNew ( hxi, vlami);\n\t    \n\t    Point<2,T> cxi(0,0);\n\t    for (int i = 0; i < hpref_el.np; i++)\n\t      for (int j = 0; j < 2; j++)\n\t\tcxi(j) += hpref_el.param[i][j] * lami[i];\n\n\t    coarse_xi[pi] = cxi;\n\t  }\n\n\tmesh.coarsemesh->GetCurvedElements().\n\t  CalcMultiPointSurfaceTransformation<DIM_SPACE,T> (hpref_el.coarse_elnr, npts,\n                                                            &coarse_xi[0](0), sizeof(Point<2,T>)/sizeof(T),\n                                                            x, sx, dxdxi, sdxdxi);\n\n\t// Mat<3,2> dxdxic;\n\tif (dxdxi)\n\t  {\n            T mem_dlami[8]; // avoid alignment problems if T is SIMD\n\t    MatrixFixWidth<2,T> dlami(4, mem_dlami);\n\t    dlami = T(0.0);\n\n\t    for (int pi = 0; pi < npts; pi++)\n\t      {\n\t\tPoint<2,T> hxi(xi[pi*sxi], xi[pi*sxi+1]);\n\t\tmesh[elnr].GetDShapeNew ( hxi, dlami);\t  \n\t\t\n\t\tMat<2,2,T> trans;\n\t\ttrans = 0;\n\t\tfor (int k = 0; k < 2; k++)\n\t\t  for (int l = 0; l < 2; l++)\n\t\t    for (int i = 0; i < hpref_el.np; i++)\n\t\t      trans(l,k) += hpref_el.param[i][l] * dlami(i, k);\n\t\t\n\t\tMat<DIM_SPACE,2,T> hdxdxic, hdxdxi;\n\t\tfor (int k = 0; k < 2*DIM_SPACE; k++)\n\t\t  hdxdxic(k) = dxdxi[pi*sdxdxi+k];\n\n\t\thdxdxi = hdxdxic * trans;\n\n\t\tfor (int k = 0; k < 2*DIM_SPACE; k++)\n\t\t  dxdxi[pi*sdxdxi+k] = hdxdxi(k);\n                    \n\t\t// dxdxic = (*dxdxi)[pi];\n\t\t// (*dxdxi)[pi] = dxdxic * trans;\n\t      }\n\t  }\t\n\n\treturn;\n      }\n\n\n    const Element2d & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    SurfaceElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    switch (type)\n      {\n      case TRIG : info.nv = 3; break;\n      case QUAD : info.nv = 4; break;\n      case TRIG6: info.nv = 6; break;\n      case QUAD8 : info.nv = 8; break;\n      default:\n\tcerr << \"undef element in CalcMultPointSurfaceTrafo\" << endl;\n      }\n    info.ndof = info.nv;\n\n    // if (info.order > 1)\n    //   {\n    //     const MeshTopology & top = mesh.GetTopology();\n\t\n    //     top.GetSurfaceElementEdges (elnr+1, info.edgenrs);\n    //     for (int i = 0; i < info.edgenrs.Size(); i++)\n    //       info.edgenrs[i]--;\n    //     info.facenr = top.GetSurfaceElementFace (elnr+1)-1;\n\n    //     for (int i = 0; i < info.edgenrs.Size(); i++)\n    //       info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n    //     info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];\n    //   }\n\n// Michael Woopen: THESE FOLLOWING LINES ARE COPIED FROM CurvedElements::CalcSurfaceTransformation\n\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        /*\n\ttop.GetSurfaceElementEdges (elnr+1, info.edgenrs);\n\tfor (int i = 0; i < info.edgenrs.Size(); i++)\n\t  info.edgenrs[i]--;\n        */\n        info.SetEdges(top.GetEdges(elnr));  \n\tinfo.facenr = top.GetFace (elnr);\n\n\n\tbool firsttry = true;\n\tbool problem = false;\n\n\twhile(firsttry || problem)\n\t  {\n\t    problem = false;\n\n\t    for (int i = 0; !problem && i < info.edgenrs.Size(); i++)\n\t      {\n\t\tif(info.edgenrs[i]+1 >= edgecoeffsindex.Size())\n\t\t  problem = true;\n\t\telse\n\t\t  info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n\t      }\n\t    if(info.facenr+1 >= facecoeffsindex.Size())\n\t      problem = true;\n\t    else\n\t      info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];\n\n\t    if(problem && !firsttry)\n\t      throw NgException(\"something wrong with curved elements\");\n\t    \n\t    if(problem)\n\t      BuildCurvedElements(NULL,order,rational);\n\n\t    firsttry = false;\n\t  }\n      }\n\n\n\n    bool ok = true;\n    for (int i = 0; i < npts; i++)\n      {\n        Point<2,T> _xi(xi[i*sxi], xi[i*sxi+1]);\n        Point<DIM_SPACE,T> _x;\n        Mat<DIM_SPACE,2,T> _dxdxi;\n        if (!EvaluateMapping (info, _xi, _x, _dxdxi))\n          { ok = false; break; }\n        // *testout << \"x = \" << _x << \", dxdxi = \" << _dxdxi << endl;\n        if (x)\n          for (int j = 0; j < DIM_SPACE; j++)\n            x[i*sx+j] = _x[j];\n        if (dxdxi)\n          for (int j = 0; j < DIM_SPACE; j++)\n            for (int k = 0; k < 2; k++)\n              dxdxi[i*sdxdxi+2*j+k] = _dxdxi(j,k);\n      }\n    if (ok) return;\n\n    \n// THESE LAST LINES ARE COPIED FROM CurvedElements::CalcSurfaceTransformation\n\n    NgArrayMem<Vec<DIM_SPACE>,100> coefs(info.ndof);\n    GetCoefficients (info, coefs);\n    \n    NgArrayMem<T, 100> shapes_mem(info.ndof);\n    TFlatVector<T> shapes(info.ndof, &shapes_mem[0]);\n\n    NgArrayMem<T, 100> dshapes_mem(info.ndof*2);\n    MatrixFixWidth<2,T> dshapes(info.ndof,&shapes_mem[0]);\n\n\n\n    if (x)\n      {\n\tif (info.order == 1 && type == TRIG)\n\t  {\n\t    for (int j = 0; j < npts; j++)\n\t      {\n\t\tPoint<2,T> vxi(xi[j*sxi], xi[j*sxi+1]);\n\n\t\tPoint<DIM_SPACE,T> val;\n                for (int k = 0; k < DIM_SPACE; k++)\n                  val(k) = coefs[2](k) + (coefs[0](k)-coefs[2](k)) * vxi(0) + (coefs[1](k)-coefs[2](k)) * vxi(1);\n                /*\n                (coefs[2]);\n\t\tval += (coefs[0]-coefs[2]) * vxi(0);\n\t\tval += (coefs[1]-coefs[2]) * vxi(1);\n                */\n\t\tfor (int k = 0; k < DIM_SPACE; k++)\n\t\t  x[j*sx+k] = val(k);\n\t      }\n\t  }\n\telse\n\t  for (int j = 0; j < npts; j++)\n\t    {\n\t      Point<2,T> vxi(xi[j*sxi], xi[j*sxi+1]);\n\t      CalcElementShapes (info, vxi, shapes);\n\t      \n\t      Point<DIM_SPACE,T> val = T(0.0);\n\t      for (int i = 0; i < coefs.Size(); i++)\n                for (int k = 0; k < DIM_SPACE; k++)\n                  val(k) += shapes(i) * coefs[i](k);\n\t      \n\t      for (int k = 0; k < DIM_SPACE; k++)\n\t\tx[j*sx+k] = val(k);\n\t    }\n      }\n\n    if (dxdxi)\n      {\n\tif (info.order == 1 && type == TRIG)\n\t  {\n\t    Point<2,T> xij(xi[0], xi[1]);\n\t    CalcElementDShapes (info, xij, dshapes);\n\t    \n\t    Mat<3,2,T> dxdxij;\n\t    dxdxij = 0.0;\n\t    for (int i = 0; i < coefs.Size(); i++)\n\t      for (int j = 0; j < DIM_SPACE; j++)\n\t\tfor (int k = 0; k < 2; k++)\n\t\t  dxdxij(j,k) += dshapes(i,k) * coefs[i](j);\n\t    \n\t\t\n\t    for (int ip = 0; ip < npts; ip++)\n\t      for (int j = 0; j < DIM_SPACE; j++)\n\t\tfor (int k = 0; k < 2; k++)\n\t\t  dxdxi[ip*sdxdxi+2*j+k] = dxdxij(j,k);\n\t  }\n\telse\n\t  {\n\t    for (int j = 0; j < npts; j++)\n\t      {\n\t\tPoint<2,T> vxi(xi[j*sxi], xi[j*sxi+1]);\n\t\tCalcElementDShapes (info, vxi, dshapes);\n\t\t\n\t\tMat<DIM_SPACE,2,T> ds;\n\t\tds = 0.0;\n\t\tfor (int i = 0; i < coefs.Size(); i++)\n\t\t  for (int j = 0; j < DIM_SPACE; j++)\n\t\t    for (int k = 0; k < 2; k++)\n\t\t      ds(j,k) += dshapes(i,k) * coefs[i](j);\n\t\t// (*dxdxi)[ip] = ds;\n\t\t\n\t\tfor (int k = 0; k < 2*DIM_SPACE; k++)\n\t\t  dxdxi[j*sdxdxi+k] = ds(k);\n\t      }\n\t  }\n      }\n  }\n\n\n\n  template void CurvedElements :: \n  CalcMultiPointSurfaceTransformation<2> (SurfaceElementIndex elnr, int npts,\n\t\t\t\t\t  const double * xi, size_t sxi,\n\t\t\t\t\t  double * x, size_t sx,\n\t\t\t\t\t  double * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcMultiPointSurfaceTransformation<3> (SurfaceElementIndex elnr, int npts,\n\t\t\t\t\t  const double * xi, size_t sxi,\n\t\t\t\t\t  double * x, size_t sx,\n\t\t\t\t\t  double * dxdxi, size_t sdxdxi);\n  \n\n  template void CurvedElements :: \n  CalcMultiPointSurfaceTransformation<2> (SurfaceElementIndex elnr, int npts,\n\t\t\t\t\t  const SIMD<double> * xi, size_t sxi,\n\t\t\t\t\t  SIMD<double> * x, size_t sx,\n\t\t\t\t\t  SIMD<double> * dxdxi, size_t sdxdxi);\n\n  template void CurvedElements :: \n  CalcMultiPointSurfaceTransformation<3> (SurfaceElementIndex elnr, int npts,\n\t\t\t\t\t  const SIMD<double> * xi, size_t sxi,\n\t\t\t\t\t  SIMD<double> * x, size_t sx,\n\t\t\t\t\t  SIMD<double> * dxdxi, size_t sdxdxi);\n\n\n\n\n\n\n\n\n\n\n\n  void CurvedElements :: \n  CalcMultiPointElementTransformation (NgArray< Point<3> > * xi, ElementIndex elnr,\n\t\t\t\t       NgArray< Point<3> > * x,\n\t\t\t\t       NgArray< Mat<3,3> > * dxdxi)\n  {\n    double * px = (x) ? &(*x)[0](0) : NULL;\n    double * pdxdxi = (dxdxi) ? &(*dxdxi)[0](0) : NULL;\n\n    CalcMultiPointElementTransformation (elnr, xi->Size(),\n\t\t\t\t\t &(*xi)[0](0), 3, \n\t\t\t\t\t px, 3,\n\t\t\t\t\t pdxdxi, 9);\n    \n    return;\n#ifdef OLD\n\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].hp_elnr];\n\t\n\t// xi umrechnen\n\tdouble lami[8];\n\tFlatVector vlami(8, lami);\n\n\n\tNgArrayMem<Point<3>, 50> coarse_xi (xi->Size());\n\t\n\tfor (int pi = 0; pi < xi->Size(); pi++)\n\t  {\n\t    vlami = 0;\n\t    mesh[elnr].GetShapeNew ( (*xi)[pi], vlami);\n\t    \n\t    Point<3> cxi(0,0,0);\n\t    for (int i = 0; i < hpref_el.np; i++)\n\t      for (int j = 0; j < 3; j++)\n\t\tcxi(j) += hpref_el.param[i][j] * lami[i];\n\n\t    coarse_xi[pi] = cxi;\n\t  }\n\n\tmesh.coarsemesh->GetCurvedElements().\n\t  CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi);\n\n\n\tMat<3,3> trans, dxdxic;\n\tif (dxdxi)\n\t  {\n\t    MatrixFixWidth<3> dlami(8);\n\t    dlami = 0;\n\n\t    for (int pi = 0; pi < xi->Size(); pi++)\n\t      {\n\t\tmesh[elnr].GetDShapeNew ( (*xi)[pi], dlami);\t  \n\t\t\n\t\ttrans = 0;\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  for (int l = 0; l < 3; l++)\n\t\t    for (int i = 0; i < hpref_el.np; i++)\n\t\t      trans(l,k) += hpref_el.param[i][l] * dlami(i, k);\n\t\t\n\t\tdxdxic = (*dxdxi)[pi];\n\t\t(*dxdxi)[pi] = dxdxic * trans;\n\t      }\n\t  }\t\n\n\treturn;\n      }\n\n\n\n\n\n\n\n\n    Vector shapes;\n    MatrixFixWidth<3> dshapes;\n\n\n    const Element & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n    ElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = MeshTopology::GetNPoints (type);\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\t\n\tinfo.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);\n\tfor (int i = 0; i < info.nedges; i++)\n\t  info.edgenrs[i]--;\n\n\tinfo.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);\n\tfor (int i = 0; i < info.nfaces; i++)\n\t  info.facenrs[i]--;\n\n\tfor (int i = 0; i < info.nedges; i++)\n\t  info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];\n\tfor (int i = 0; i < info.nfaces; i++)\n\t  info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];\n\t// info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];\n      }\n\n    NgArray<Vec<3> > coefs(info.ndof);\n    GetCoefficients (info, &coefs[0]);\n    if (x)\n      {\n\tfor (int j = 0; j < xi->Size(); j++)\n\t  {\n\t    CalcElementShapes (info, (*xi)[j], shapes);\n\t    (*x)[j] = 0;\n\t    for (int i = 0; i < coefs.Size(); i++)\n\t      (*x)[j] += shapes(i) * coefs[i];\n\t  }\n      }\n\n    if (dxdxi)\n      {\n\tif (info.order == 1 && type == TET)\n\t  {\n\t    if (xi->Size() > 0)\n\t      {\n\t\tCalcElementDShapes (info, (*xi)[0], dshapes);\n\t\tMat<3,3> ds;\n\t\tds = 0;\n\t\tfor (int i = 0; i < coefs.Size(); i++)\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    for (int k = 0; k < 3; k++)\n\t\t      ds(j,k) += dshapes(i,k) * coefs[i](j);\n\t    \n\t\tfor (int ip = 0; ip < xi->Size(); ip++)\n\t\t  (*dxdxi)[ip] = ds;\n\t      }\n\t  }\n\telse\n\t  for (int ip = 0; ip < xi->Size(); ip++)\n\t    {\n\t      CalcElementDShapes (info, (*xi)[ip], dshapes);\n\t      \n\t      Mat<3,3> ds;\n\t      ds = 0;\n\t      for (int i = 0; i < coefs.Size(); i++)\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  for (int k = 0; k < 3; k++)\n\t\t    ds(j,k) += dshapes(i,k) * coefs[i](j);\n\t      (*dxdxi)[ip] = ds;\n\t    }\n      }\n#endif\n  }\n\n\n  // extern int multipointtrafovar;\n  template <typename T>\n  void  CurvedElements :: \n  CalcMultiPointElementTransformation (ElementIndex elnr, int n,\n\t\t\t\t       const T * xi, size_t sxi,\n\t\t\t\t       T * x, size_t sx,\n\t\t\t\t       T * dxdxi, size_t sdxdxi)\n  {\n    // multipointtrafovar++;\n    /*\n    static int timer = NgProfiler::CreateTimer (\"calcmultipointelementtrafo\");\n    static int timer1 = NgProfiler::CreateTimer (\"calcmultipointelementtrafo 1\");\n    static int timer2 = NgProfiler::CreateTimer (\"calcmultipointelementtrafo 2\");\n    static int timer3 = NgProfiler::CreateTimer (\"calcmultipointelementtrafo 3\");\n    static int timer4 = NgProfiler::CreateTimer (\"calcmultipointelementtrafo 4\");\n    static int timer5 = NgProfiler::CreateTimer (\"calcmultipointelementtrafo 5\");\n    NgProfiler::RegionTimer reg(timer);\n    */\n    // NgProfiler::StartTimer (timer);\n    // NgProfiler::StartTimer (timer1);\n    if (mesh.coarsemesh)\n      {\n\tconst HPRefElement & hpref_el =\n\t  (*mesh.hpelements) [mesh[elnr].GetHpElnr()];\n\t\n\t// xi umrechnen\n\tT lami[8];\n\tTFlatVector<T> vlami(8, &lami[0]);\n\n\n\tNgArrayMem<T, 100> coarse_xi (3*n);\n\t\n\tfor (int pi = 0; pi < n; pi++)\n\t  {\n\t    vlami = 0;\n\t    Point<3,T> pxi;\n\t    for (int j = 0; j < 3; j++)\n\t      pxi(j) = xi[pi*sxi+j];\n\n\t    mesh[elnr].GetShapeNew (pxi, vlami);\n\t    \n\t    Point<3,T> cxi(0,0,0);\n\t    for (int i = 0; i < hpref_el.np; i++)\n\t      for (int j = 0; j < 3; j++)\n\t\tcxi(j) += hpref_el.param[i][j] * lami[i];\n\n\t    for (int j = 0; j < 3; j++)\n\t      coarse_xi[3*pi+j] = cxi(j);\n\t  }\n\n\tmesh.coarsemesh->GetCurvedElements().\n\t  CalcMultiPointElementTransformation (ElementIndex(hpref_el.coarse_elnr), n, \n\t\t\t\t\t       &coarse_xi[0], 3, \n\t\t\t\t\t       x, sx, \n\t\t\t\t\t       dxdxi, sdxdxi);\n\n\tMat<3,3,T> trans, dxdxic;\n\tif (dxdxi)\n\t  {\n\t    MatrixFixWidth<3,T> dlami(8);\n\t    dlami = T(0);\n\n\t    for (int pi = 0; pi < n; pi++)\n\t      {\n\t\tPoint<3,T> pxi;\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  pxi(j) = xi[pi*sxi+j];\n\n\t\tmesh[elnr].GetDShapeNew (pxi, dlami);\t  \n\t\t\n\t\ttrans = 0;\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  for (int l = 0; l < 3; l++)\n\t\t    for (int i = 0; i < hpref_el.np; i++)\n\t\t      trans(l,k) += hpref_el.param[i][l] * dlami(i, k);\n\n\t\tMat<3,3,T> mat_dxdxic, mat_dxdxi;\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  for (int k = 0; k < 3; k++)\n\t\t    mat_dxdxic(j,k) = dxdxi[pi*sdxdxi+3*j+k];\n\t\t\n\t\tmat_dxdxi = mat_dxdxic * trans;\n\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  for (int k = 0; k < 3; k++)\n\t\t    dxdxi[pi*sdxdxi+3*j+k] = mat_dxdxi(j,k);\n\n\t\t// dxdxic = (*dxdxi)[pi];\n\t\t// (*dxdxi)[pi] = dxdxic * trans;\n\t      }\n\t  }\t\n\treturn;\n      }\n\n    // NgProfiler::StopTimer (timer1);\n    // NgProfiler::StartTimer (timer2);\n\n\n    const Element & el = mesh[elnr];\n    ELEMENT_TYPE type = el.GetType();\n\n\n    ElementInfo info;\n    info.elnr = elnr;\n    info.order = order;\n    info.ndof = info.nv = MeshTopology::GetNPoints (type);\n    if (info.order > 1)\n      {\n\tconst MeshTopology & top = mesh.GetTopology();\n\n        info.SetEdges (top.GetEdges(elnr));\n        info.SetFaces (top.GetFaces(elnr));\n\n        for (auto e : info.GetEdges())\n          info.ndof += edgecoeffsindex[e+1] - edgecoeffsindex[e];\n        \n        for (auto f : info.GetFaces())\n          info.ndof += facecoeffsindex[f+1] - facecoeffsindex[f];\n      }\n\n    // NgProfiler::StopTimer (timer2);\n    // NgProfiler::StartTimer (timer3);\n\n\n    bool ok = true;\n    for (int i = 0; i < n; i++)\n      {\n        Point<3,T> _xi(xi[i*sxi], xi[i*sxi+1], xi[i*sxi+2]);\n        Point<3,T> _x;\n        Mat<3,3,T> _dxdxi;\n        if (!EvaluateMapping (info, _xi, _x, _dxdxi))\n          { ok = false; break; }\n        // cout << \"x = \" << _x << \", dxdxi = \" << _dxdxi << endl;\n        if (x)\n          for (int j = 0; j < 3; j++)\n            x[i*sx+j] = _x[j];\n        if (dxdxi)\n          for (int j = 0; j < 3; j++)\n            for (int k = 0; k < 3; k++)\n              dxdxi[i*sdxdxi+3*j+k] = _dxdxi(j,k);\n      }\n    if (ok) return;\n\n    NgArrayMem<Vec<3>,100> coefs(info.ndof);\n    NgArrayMem<T,500> shapes_mem(info.ndof);\n    \n    TFlatVector<T> shapes(info.ndof, &shapes_mem[0]);\n\n    NgArrayMem<T,1500> dshapes_mem(3*info.ndof);\n    MatrixFixWidth<3,T> dshapes(info.ndof, &dshapes_mem[0]);\n\n    // NgProfiler::StopTimer (timer3);\n    // NgProfiler::StartTimer (timer4);\n\n    GetCoefficients (info, &coefs[0]);\n    if (x)\n      {\n\tfor (int j = 0; j < n; j++)\n\t  {\n\t    Point<3,T> xij, xj;\n\t    for (int k = 0; k < 3; k++)\n\t      xij(k) = xi[j*sxi+k];\n\t    CalcElementShapes (info, xij, shapes);\n\t    xj = T(0.0);\n\t    for (int i = 0; i < coefs.Size(); i++)\n              for (int k = 0; k < 3; k++)\n                xj(k) += shapes(i) * coefs[i](k);\n\n            // cout << \"old, xj = \" << xj << endl;\n\n\t    for (int k = 0; k < 3; k++)\n\t      x[j*sx+k] = xj(k);\n\t  }\n      }\n\n\n    // NgProfiler::StopTimer (timer4);\n    // NgProfiler::StartTimer (timer5);\n                \n    if (dxdxi)\n      {\n\tif (info.order == 1 && type == TET)\n\t  {\n\t    if (n > 0)\n\t      {\n\n\t\tPoint<3,T> xij;\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  xij(k) = xi[k];\n\t\t\n\t\tCalcElementDShapes (info, xij, dshapes);\n\t\t\n\t\tMat<3,3,T> dxdxij;\n\t\tdxdxij = 0.0;\n\t\tfor (int i = 0; i < coefs.Size(); i++)\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    for (int k = 0; k < 3; k++)\n\t\t      dxdxij(j,k) += dshapes(i,k) * coefs[i](j);\n\t\t\n\t\t\n\t\tfor (int ip = 0; ip < n; ip++)\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    for (int k = 0; k < 3; k++)\n\t\t      dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k);\n\t      }\n\t  }\n\telse\n\t  {\n\t    for (int ip = 0; ip < n; ip++)\n\t      {\n\t\tPoint<3,T> xij;\n\t\tfor (int k = 0; k < 3; k++)\n\t\t  xij(k) = xi[ip*sxi+k];\n\n                CalcElementDShapes (info, xij, dshapes);\n\n\n\t\tMat<3,3,T> dxdxij;\n\t\tdxdxij = 0.0;\n\t\tfor (int i = 0; i < coefs.Size(); i++)\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    for (int k = 0; k < 3; k++)\n\t\t      dxdxij(j,k) += dshapes(i,k) * coefs[i](j);\n                \n                // cout << \"old, jac = \" << dxdxij << endl;\n\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  for (int k = 0; k < 3; k++)\n\t\t    dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k);\n\n                /*\n                T dxdxi00 = T(0.0);\n                T dxdxi01 = T(0.0);\n                T dxdxi02 = T(0.0);\n                T dxdxi10 = T(0.0);\n                T dxdxi11 = T(0.0);\n                T dxdxi12 = T(0.0);\n                T dxdxi20 = T(0.0);\n                T dxdxi21 = T(0.0);\n                T dxdxi22 = T(0.0);\n                \n\t\tfor (int i = 0; i < coefs.Size(); i++)\n                  {\n                    T ds0 = dshapes(i,0);\n                    T ds1 = dshapes(i,1);\n                    T ds2 = dshapes(i,2);\n                    T cf0 = coefs[i](0);\n                    T cf1 = coefs[i](1);\n                    T cf2 = coefs[i](2);\n\n                    dxdxi00 += ds0*cf0;\n                    dxdxi01 += ds1*cf0;\n                    dxdxi02 += ds2*cf0;\n                    dxdxi10 += ds0*cf1;\n                    dxdxi11 += ds1*cf1;\n                    dxdxi12 += ds2*cf1;\n                    dxdxi20 += ds0*cf2;\n                    dxdxi21 += ds1*cf2;\n                    dxdxi22 += ds2*cf2;\n                  }\n\n                dxdxi[ip*sdxdxi+3*0+0] = dxdxi00;\n                dxdxi[ip*sdxdxi+3*0+1] = dxdxi01;\n                dxdxi[ip*sdxdxi+3*0+2] = dxdxi02;\n\n                dxdxi[ip*sdxdxi+3*1+0] = dxdxi10;\n                dxdxi[ip*sdxdxi+3*1+1] = dxdxi11;\n                dxdxi[ip*sdxdxi+3*1+2] = dxdxi12;\n                \n                dxdxi[ip*sdxdxi+3*2+0] = dxdxi20;\n                dxdxi[ip*sdxdxi+3*2+1] = dxdxi21;\n                dxdxi[ip*sdxdxi+3*2+2] = dxdxi22;\n                */\n\t      }\n\t  }\n      }\n    // NgProfiler::StopTimer (timer5);\n    // NgProfiler::StopTimer (timer);    \n  }\n\n\n  template\n  void  CurvedElements :: \n  CalcMultiPointElementTransformation\n  (ElementIndex elnr, int n,\n   const double * xi, size_t sxi,\n   double * x, size_t sx,\n   double * dxdxi, size_t sdxdxi);\n\n  template\n  void  CurvedElements :: \n  CalcMultiPointElementTransformation\n  (ElementIndex elnr, int n,\n   const SIMD<double> * xi, size_t sxi,\n   SIMD<double> * x, size_t sx,\n   SIMD<double> * dxdxi, size_t sdxdxi);\n\n};\n"
  },
  {
    "path": "libsrc/meshing/curvedelems.hpp",
    "content": "#ifndef NETGEN_CURVEDELEMS_HPP\n#define NETGEN_CURVEDELEMS_HPP\n\n/**************************************************************************/\n/* File:   curvedelems.hpp                                                */\n/* Author: Robert Gaisbauer (first version)                               */\n/*         redesign by Joachim Schoeberl                                  */\n/* Date:   27. Sep. 02, Feb 2006                                          */\n/**************************************************************************/\n\n#include <mydefs.hpp>\n#include <general/ngarray.hpp>\n#include <gprim/geomobjects.hpp>\n\n#include \"meshtype.hpp\"\n#include \"meshclass.hpp\"\n\nnamespace netgen\n{\nclass Refinement;\nclass Mesh;\n\nclass CurvedElements\n{\n  const Mesh & mesh;\n\n  NgArray<int> edgeorder;\n  NgArray<int> faceorder;\n\n  NgArray<int> edgecoeffsindex;\n  NgArray<int> facecoeffsindex;\n\n  NgArray< Vec<3> > edgecoeffs;\n  NgArray< Vec<3> > facecoeffs;\n\n  NgArray< double > edgeweight;  // for rational 2nd order splines\n\n  int order;\n  bool rational;\n\n  bool ishighorder;\n\npublic:\n  DLL_HEADER CurvedElements (const Mesh & amesh);\n  DLL_HEADER ~CurvedElements();\n\n  // bool IsHighOrder() const { return order > 1; }\n  bool IsHighOrder() const { return ishighorder; }\n\n  // void SetHighOrder (int aorder) { order=aorder; }\n  void SetIsHighOrder (bool ho) { ishighorder = ho; }\n  \n  DLL_HEADER void BuildCurvedElements(const Refinement * ref, int aorder, bool arational = false);\n\n  int GetOrder () { return order; }\n\n  void DoArchive(Archive& ar);\n\n  DLL_HEADER bool IsSegmentCurved (SegmentIndex segnr) const;\n  DLL_HEADER bool IsSurfaceElementCurved (SurfaceElementIndex sei) const;\n  DLL_HEADER bool IsElementCurved (ElementIndex ei) const;\n  DLL_HEADER bool IsElementHighOrder (ElementIndex ei) const;\n\n\n  void CalcSegmentTransformation (double xi, SegmentIndex segnr,\n\t\t\t\t  Point<3> & x)\n  { CalcSegmentTransformation<double> (xi, segnr, &x, NULL); };\n\n  void CalcSegmentTransformation (double xi, SegmentIndex segnr,\n\t\t\t\t  Vec<3> & dxdxi)\n  { CalcSegmentTransformation<double> (xi, segnr, NULL, &dxdxi); };\n\n  void CalcSegmentTransformation (double xi, SegmentIndex segnr,\n\t\t\t\t  Point<3> & x, Vec<3> & dxdxi)\n  { CalcSegmentTransformation<double> (xi, segnr, &x, &dxdxi, NULL); };\n\n  void CalcSegmentTransformation (double xi, SegmentIndex segnr,\n\t\t\t\t  Point<3> & x, Vec<3> & dxdxi, bool & curved)\n  { CalcSegmentTransformation (xi, segnr, &x, &dxdxi, &curved); };\n\n\n\n  void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr,\n\t\t\t\t  Point<3> & x)\n  { CalcSurfaceTransformation (xi, elnr, &x, NULL); };\n\n  void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr,\n\t\t\t\t  Mat<3,2> & dxdxi)\n  { CalcSurfaceTransformation (xi, elnr, NULL, &dxdxi); };\n\n  void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr,\n\t\t\t\t  Point<3> & x, Mat<3,2> & dxdxi)\n  { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, NULL); };\n\n  void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr,\n\t\t\t\t  Point<3> & x, Mat<3,2> & dxdxi, bool & curved)\n  { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, &curved); };\n\n\n\n\n\n  void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr,\n\t\t\t\t  Point<3> & x)\n  { CalcElementTransformation (xi, elnr, &x, NULL); };\n\n  void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr,\n\t\t\t\t  Mat<3,3> & dxdxi)\n  { CalcElementTransformation (xi, elnr, NULL, &dxdxi); };\n\n  void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr,\n\t\t\t\t  Point<3> & x, Mat<3,3> & dxdxi)\n  { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , NULL */ ); };\n\n  void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr,\n\t\t\t\t  Point<3> & x, Mat<3,3> & dxdxi,\n                                  void * buffer, bool valid)\n  { CalcElementTransformation (xi, elnr, &x, &dxdxi, /* NULL, */ buffer, valid ); };\n\n  // void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr,\n  // \t\t\t\t  Point<3> & x, Mat<3,3> & dxdxi) // , bool & curved)\n  //   { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , &curved * ); }\n\n\n  /*\n  void CalcMultiPointSegmentTransformation (NgArray<double> * xi, SegmentIndex segnr,\n\t\t\t\t\t    NgArray<Point<3> > * x,\n\t\t\t\t\t    NgArray<Vec<3> > * dxdxi);\n  */\n  \n  template <int DIM_SPACE, typename T>\n  void CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n,\n                                            const T * xi, size_t sxi,\n                                            T * x, size_t sx,\n                                            T * dxdxi, size_t sdxdxi);\n\n  DLL_HEADER void CalcMultiPointSurfaceTransformation (NgArray< Point<2> > * xi, SurfaceElementIndex elnr,\n\t\t\t\t\t    NgArray< Point<3> > * x,\n\t\t\t\t\t    NgArray< Mat<3,2> > * dxdxi);\n\n  template <int DIM_SPACE, typename T>\n  void CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int n,\n                                            const T * xi, size_t sxi,\n                                            T * x, size_t sx,\n                                            T * dxdxi, size_t sdxdxi);\n\n  DLL_HEADER void CalcMultiPointElementTransformation (NgArray< Point<3> > * xi, ElementIndex elnr,\n\t\t\t\t\t    NgArray< Point<3> > * x,\n\t\t\t\t\t    NgArray< Mat<3,3> > * dxdxi);\n\n  template <typename T>\n  void CalcMultiPointElementTransformation (ElementIndex elnr, int n,\n                                            const T * xi, size_t sxi,\n                                            T * x, size_t sx,\n                                            T * dxdxi, size_t sdxdxi);\n\n\n  \n\nprivate:\n\n  template <typename T>\n  DLL_HEADER void CalcSegmentTransformation (const T & xi, SegmentIndex segnr,\n\t\t\t\t  Point<3,T> * x = NULL, Vec<3,T> * dxdxi = NULL, bool * curved = NULL);\n\n  DLL_HEADER void CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr,\n\t\t\t\t  Point<3> * x = NULL, Mat<3,2> * dxdxi = NULL, bool * curved = NULL);\n\n  DLL_HEADER void CalcElementTransformation (Point<3> xi, ElementIndex elnr,\n\t\t\t\t  Point<3> * x = NULL, Mat<3,3> * dxdxi = NULL, // bool * curved = NULL,\n                                  void * buffer = NULL, bool valid = 0);\n\n\n\n\n\n\n  class SegmentInfo\n  {\n  public:\n    SegmentIndex elnr;\n    int order;\n    int nv;\n    int ndof;\n    int edgenr;\n  };\n\n  template <typename T>\n  void CalcElementShapes (SegmentInfo &  elnr, T xi, TFlatVector<T> shapes) const;\n  void GetCoefficients (SegmentInfo & elnr, NgArray<Vec<3> > & coefs) const;\n  template <typename T>\n  void CalcElementDShapes (SegmentInfo & elnr, T xi, TFlatVector<T> dshapes) const;\n\n\n  class ElementInfo\n  {\n  public:\n    ElementIndex elnr;\n    int order;\n    int nv;\n    int ndof;\n    int nedges;\n    int nfaces;\n    int edgenrs[12];\n    int facenrs[6];\n    Mat<3> hdxdxi;\n    Vec<3> hcoefs[10]; // enough for second order tets\n\n    void SetEdges (FlatArray<T_EDGE> edges)\n    {\n      nedges = edges.Size();\n      for (int i = 0; i < edges.Size(); i++)\n        edgenrs[i] = edges[i];\n    }\n    \n    auto GetEdges() const\n    { return FlatArray(nedges, edgenrs); }\n\n    void SetFaces (FlatArray<T_FACE> faces)\n    {\n      nfaces = faces.Size();\n      for (int i = 0; i < faces.Size(); i++)\n        facenrs[i] = faces[i];\n    }\n\n    auto GetFaces() const\n    { return FlatArray(nfaces, facenrs); }\n  };\n\n  template <typename T>\n  void CalcElementShapes (ElementInfo & info, Point<3,T> xi, TFlatVector<T> shapes) const;\n  void GetCoefficients (ElementInfo & info, Vec<3> * coefs) const;\n  template <typename T>  \n  void CalcElementDShapes (ElementInfo & info, const Point<3,T> xi, MatrixFixWidth<3,T> & dshapes) const;\n\n  template <typename T>\n  bool EvaluateMapping (ElementInfo & info, const Point<3,T> xi, Point<3,T> & x, Mat<3,3,T> & jac) const;  \n  \n  class SurfaceElementInfo\n  {\n  public:\n    SurfaceElementIndex elnr;\n    int order;\n    int nv;\n    int ndof;\n    NgArrayMem<int,4> edgenrs;\n    int facenr;\n\n    void SetEdges (FlatArray<T_EDGE> edges)\n    {\n      edgenrs.SetSize(edges.Size());\n      for (int i = 0; i < edges.Size(); i++)\n        edgenrs[i] = edges[i];\n    }\n    \n  };\n\n  template <typename T>\n  void CalcElementShapes (SurfaceElementInfo & elinfo, const Point<2,T> xi, TFlatVector<T> shapes) const;\n  template <int DIM_SPACE>\n  void GetCoefficients (SurfaceElementInfo & elinfo, NgArray<Vec<DIM_SPACE> > & coefs) const;\n  template <typename T>\n  void CalcElementDShapes (SurfaceElementInfo & elinfo, const Point<2,T> xi, MatrixFixWidth<2,T> & dshapes) const;\n\n  template <int DIM_SPACE, typename T>\n  bool EvaluateMapping (SurfaceElementInfo & info, const Point<2,T> xi, Point<DIM_SPACE,T> & x, Mat<DIM_SPACE,2,T> & jac) const;  \n};\n\n} //namespace netgen\n#endif // NETGEN_CURVEDELEMS_HPP\n"
  },
  {
    "path": "libsrc/meshing/debugging.cpp",
    "content": "#include <meshing.hpp>\n#include \"debugging.hpp\"\n\nnamespace netgen\n{\n    unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom, bool only_quads )\n    {\n        static Timer t(\"GetOpenElements\"); RegionTimer rt(t);\n        auto mesh = make_unique<Mesh>();\n        *mesh = m;\n\n        Array<bool, PointIndex> interesting_points(mesh->GetNP());\n        interesting_points = false;\n\n        mesh->FindOpenElements(dom);\n        NgArray<Element2d> openelements;\n        openelements = mesh->OpenElements();\n\n        for (auto & el : openelements)\n            for (auto i : el.PNums())\n                interesting_points[i] = true;\n\n        for (auto & el : mesh->VolumeElements())\n        {\n            int num_interesting_points = 0;\n\n            for (auto pi : el.PNums())\n                if(interesting_points[pi])\n                    num_interesting_points++;\n\n            if(num_interesting_points==0)\n                el.Delete();\n            el.SetIndex(num_interesting_points);\n        }\n\n        mesh->SetMaterial(1, \"1_point\");\n        mesh->SetMaterial(2, \"2_points\");\n        mesh->SetMaterial(3, \"3_points\");\n        mesh->SetMaterial(4, \"4_points\");\n\n        mesh->ClearSurfaceElements();\n\n        for (auto & el : openelements)\n            if(!only_quads || el.GetNP() == 4)\n                mesh->AddSurfaceElement( el );\n\n        mesh->Compress();\n        return mesh;\n    }\n\n    unique_ptr<Mesh> FilterMesh( const Mesh & m, FlatArray<PointIndex> points, FlatArray<SurfaceElementIndex> sels, FlatArray<ElementIndex> els )\n    {\n        static Timer t(\"GetOpenElements\"); RegionTimer rt(t);\n        auto mesh_ptr = make_unique<Mesh>();\n        auto & mesh = *mesh_ptr;\n        mesh = m;\n\n        Array<bool, PointIndex> keep_point(mesh.GetNP());\n        Array<bool, SurfaceElementIndex> keep_sel(mesh.GetNSE());\n        Array<bool, ElementIndex> keep_el(mesh.GetNE());\n        mesh.LineSegments().DeleteAll();\n\n        keep_point = false;\n        for(auto pi : points)\n            keep_point[pi] = true;\n\n        auto set_keep = [&] (auto & input, auto & keep_array, auto & els)\n        {\n            keep_array = false;\n            for(auto ind : input)\n                keep_array[ind] = true;\n\n            for(auto ind : Range(els))\n            {\n                bool & keep = keep_array[ind];\n                if(keep) continue;\n\n                for(auto pi : mesh[ind].PNums())\n                    keep |= keep_point[pi];\n\n                if(!keep)\n                    mesh[ind].Delete();\n            }\n\n            for(auto i = 0; i<els.Size(); i++)\n                if(els[i].IsDeleted())\n                {\n                    els.DeleteElement(i);\n                    i--;\n                }\n        };\n\n        set_keep(sels, keep_sel, mesh.SurfaceElements());\n        set_keep(els, keep_el, mesh.VolumeElements());\n        //mesh.Compress();\n\n        return mesh_ptr;\n    }\n\n    void CheckMesh (const Mesh& mesh, MESHING_STEP step)\n    {\n      if (step == MESHCONST_OPTVOLUME)\n        {\n          bool have_error = false;\n          for (auto el : mesh.VolumeElements())\n            {\n              double volume = el.Volume(mesh.Points());\n              if (volume < 0)\n                {\n                  have_error = true;\n                  cout << \"volume of element \" << el << \" is negative: \" << volume << endl;\n                }\n            }\n          if (have_error)\n            throw Exception(\"Negative volume\");\n\n        CheckElementsAroundEdges(mesh);\n        }\n    }\n\n    void CheckElementsAroundEdges (const Mesh& mesh)\n    {\n      static Mesh last_good_mesh;\n\n      Array<std::tuple<PointIndex, PointIndex>> edges;\n      auto elementsonnode = mesh.CreatePoint2ElementTable();\n      BuildEdgeList(mesh, elementsonnode, edges);\n      mesh.BoundaryEdge(1, 2); // trigger build of boundary edges\n\n      ArrayMem<ElementIndex, 20> hasbothpoints;\n      for (auto [pi0, pi1] : edges)\n        {\n          if (mesh.BoundaryEdge(pi0, pi1))\n            continue;\n\n          hasbothpoints.SetSize(0);\n          for (ElementIndex ei : elementsonnode[pi0])\n            if (mesh[ei].PNums().Contains(pi1))\n              hasbothpoints.Append(ei);\n\n          bool skip = false;\n          for (ElementIndex ei : hasbothpoints)\n            {\n              if (mesh[ei].GetType() != TET)\n                {\n                  skip = true;\n                  break;\n                }\n            }\n          if (skip)\n            continue;\n\n          int nsuround = hasbothpoints.Size();\n          ArrayMem<PointIndex, 50> suroundpts(nsuround + 1);\n          suroundpts = PointIndex::INVALID;\n          ArrayMem<bool, 50> tetused(nsuround);\n          tetused = false;\n          tetused[0] = true;\n\n          auto el = mesh[hasbothpoints[0]];\n          PointIndex pi2 = PointIndex::INVALID;\n          PointIndex pi3 = PointIndex::INVALID;\n          for (auto pi : el.PNums())\n            if (pi != pi0 && pi != pi1)\n              {\n                pi3 = pi2;\n                pi2 = pi;\n              }\n          suroundpts[0] = pi2;\n          suroundpts[1] = pi3;\n\n          for (auto i : Range(2, nsuround + 1))\n            {\n              PointIndex oldpi = suroundpts[i - 1];\n              PointIndex newpi = PointIndex::INVALID;\n\n              for (int k = 0; k < nsuround && !newpi.IsValid(); k++)\n                if (!tetused[k])\n                  {\n                    const Element& nel = mesh[hasbothpoints[k]];\n                    for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++)\n                      if (nel[k2] == oldpi)\n                        {\n                          newpi = nel[0] - pi0 + nel[1] - pi1 + nel[2] - oldpi + nel[3];\n                          tetused[k] = true;\n                          suroundpts[i] = newpi;\n\n                          ArrayMem<PointIndex, 4> nelpts{nel[0], nel[1], nel[2], nel[3]};\n                          ArrayMem<PointIndex, 4> check_points{pi0, pi1, oldpi, newpi};\n                          QuickSort(check_points);\n                          QuickSort(nelpts);\n                          if (check_points != nelpts)\n                            {\n                              cout << __FILE__ << \":\" << __LINE__ << \"\\tFound error\" << endl;\n                              cout << \"i = \" << i << endl;\n                              cout << \"oldpi = \" << oldpi << endl;\n                              cout << \"newpi = \" << newpi << endl;\n                              cout << \"Elements: \" << endl;\n                              cout << \"nel \" << nel << endl;\n                              for (auto ei : hasbothpoints)\n                                cout << mesh[ei] << endl;\n                              cout << endl;\n                              cout << \"check_points: \" << check_points << endl;\n                              cout << \"nelpts: \" << nelpts << endl;\n                              cout << \"hasbothpoints: \" << hasbothpoints << endl;\n                              cout << \"suroundpts: \" << suroundpts << endl;\n                              throw Exception(\"Found error\");\n                            }\n                        }\n                  }\n            }\n          if (suroundpts.Last() != suroundpts[0])\n            {\n              cout << __FILE__ << \":\" << __LINE__ << \"\\tFound error\" << endl;\n              cout << \"hasbothpoints: \" << hasbothpoints << endl;\n              cout << \"suroundpts: \" << suroundpts << endl;\n              for (auto ei : hasbothpoints)\n                cout << mesh[ei] << endl;\n              throw Exception(\"Found error\");\n            }\n        }\n    }\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/debugging.hpp",
    "content": "#include \"meshfunc.hpp\"\n\n\nnamespace netgen\n{\n    unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom = 0, bool only_quads = false );\n\n    unique_ptr<Mesh> FilterMesh( const Mesh & m, FlatArray<PointIndex> points, FlatArray<SurfaceElementIndex> sels = Array<SurfaceElementIndex>{}, FlatArray<ElementIndex> els = Array<ElementIndex>{} );\n\n    // Checks if the mesh is valid. This is called automatically on various places if debugparam.slowchecks is set\n    void CheckMesh( const Mesh & m, MESHING_STEP meshing_step );\n\n    // Sometimes during SwapImprove we discover topological errors in the mesh. For instance, an edge is adjacent to 8 tets around it, but\n    // the 8 \"other\" points of the tets don't form a closed path around the edge. Instead there are 2 sets of 4 points/tets each, which are not connected.\n    // This function checks for such errors and returns true if any are found.\n    void CheckElementsAroundEdges( const Mesh & m );\n}\n"
  },
  {
    "path": "libsrc/meshing/delaunay.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n  // typedef BoxTree<3> DTREE;\n  typedef DelaunayTree<3> DTREE;\n\n  static const int deltetfaces[][3] = \n    { { 1, 2, 3 },\n      { 2, 0, 3 },\n      { 0, 1, 3 },\n      { 1, 0, 2 } };\n\n\n  class DelaunayTet\n  {\n    PointIndex pnums[4];\n    int nb[4] = {0,0,0,0};\n\n  public:\n    DelaunayTet () = default;\n\n    DelaunayTet (const Element & el)\n    {\n      for (int i = 0; i < 4; i++)\n\tpnums[i] = el[i];\n    }\n    \n    PointIndex & operator[] (int i) { return pnums[i]; }\n    PointIndex operator[] (int i) const { return pnums[i]; }\n\n    int & NB(int i) { return nb[i]; }\n    int NB(int i) const { return nb[i]; }\n\n\n    int FaceNr (const PointIndices<3> & face) const  // which face nr is it ?\n    {\n      for (int i = 0; i < 3; i++)\n\tif (pnums[i] != face[0] && pnums[i] != face[1] && pnums[i] != face[2])\n\t  return i;\n      return 3;\n    }\n\n    PointIndices<3> GetFace (int i) const\n    {\n      return  { pnums[deltetfaces[i][0]],\n                pnums[deltetfaces[i][1]],\n                pnums[deltetfaces[i][2]] };\n    }\n\n    void GetFace (int i, Element2d & face) const\n    {\n      // face.SetType(TRIG);\n      face[0] = pnums[deltetfaces[i][0]];\n      face[1] = pnums[deltetfaces[i][1]];\n      face[2] = pnums[deltetfaces[i][2]];\n    }\n  };\n\n\n\n\n\n\n\n  /*\n    Table to maintain neighbour elements\n  */\n  class MeshNB\n  {\n    // face nodes -> one element\n    INDEX_3_CLOSED_HASHTABLE<int> faces;\n\n    // \n    NgArray<DelaunayTet> & tets;\n\n  public:\n\n    // estimated number of points\n    MeshNB (NgArray<DelaunayTet> & atets, int np)\n      : faces(200), tets(atets)\n    { ; }\n\n    // add element with 4 nodes\n    void Add (int elnr);\n\n    // delete element with 4 nodes\n    void Delete (int elnr)\n    {\n      DelaunayTet & el = tets.Elem(elnr);\n      for (int i = 0; i < 4; i++)\n\tfaces.Set (el.GetFace(i).Sort(), el.NB(i));\n    }\n\n    // get neighbour of element elnr in direction fnr \n    int GetNB (int elnr, int fnr)\n    { \n      return tets.Get(elnr).NB(fnr); \n    }\n\n    //\n    void ResetFaceHT (int size)\n    {\n      faces.SetSize (size);\n    }\n  };\n\n\n\n  void MeshNB :: Add (int elnr)\n  {\n    DelaunayTet & el = tets.Elem(elnr);\n\n    for (int i = 0; i < 4; i++)\n      {\n\tINDEX_3 i3 = INDEX_3::Sort (el.GetFace(i));\n\n\tint posnr;\n\t\n\tif (!faces.PositionCreate (i3, posnr))\n\t  {\n\t    // face already in use\n\t    int othertet = faces.GetData (posnr);\n\n\t    el.NB(i) = othertet;\n\t    if (othertet)\n\t      {\n\t\tint fnr = tets.Get(othertet).FaceNr (i3);\n\t\ttets.Elem(othertet).NB(fnr) = elnr;\n\t      }\n\t  }\n\telse\n\t  {\n\t    faces.SetData (posnr, elnr);\t\n\t    el.NB(i) = 0;\n\t  }\n      }\n  }\n\n\n\n\n\n  /*\n    connected lists of cosphereical elements\n  */\n  class SphereList \n  {\n    NgArray<int> links;\n  public:\n    SphereList () \n    { ; }\n\n    void AddElement (int elnr)\n    {\n      if (elnr > links.Size())\n\tlinks.Append (1);\n      links.Elem(elnr) = elnr;\n    }\n\n    void DeleteElement (int elnr)\n    {\n      links.Elem(elnr) = 0;\n    }    \n  \n    void ConnectElement (int eli, int toi)\n    {\n      links.Elem (eli) = links.Get (toi);\n      links.Elem (toi) = eli;\n    }\n      \n    void GetList (int eli, NgArray<int> & linked) const;\n\n    template <typename TFUNC>\n    void IterateList (int eli, TFUNC func)\n    {\n      int pi = eli;\n      do\n        {\n          func(pi);\n          pi = links.Get(pi);\n        }\n      while (pi != eli);\n    }\n    \n  };\n\n\n  void SphereList :: GetList (int eli, NgArray<int> & linked) const\n  {\n    linked.SetSize (0);\n    int pi = eli;\n\n    do\n      {\n#ifdef DELAUNAY_DEBUG\n\tif (pi <= 0 || pi > links.Size())\n\t  {\n\t    cerr << \"link, error \" << endl;\n\t    cerr << \"pi = \" << pi << \" linked.s = \" << linked.Size() << endl;\n\t    exit(1);\n\t  }\n\tif (linked.Size() > links.Size())\n\t  {\n\t    cerr << \"links have loop\" << endl;\n\t    exit(1);\n\t  }\n#endif\n\tlinked.Append (pi);\n\tpi = links.Get(pi);\n      }\n    while (pi != eli);\n  }\n\n\n\n\n\n  void AddDelaunayPoint (PointIndex newpi, const Point3d & newp, \n\t\t\t NgArray<DelaunayTet> & tempels, \n\t\t\t Mesh & mesh,\n\t\t\t DTREE & tettree,\n\t\t\t MeshNB & meshnb,\n\t\t\t NgArray<Point<3> > & centers, NgArray<double> & radi2,\n\t\t\t NgArray<int> & connected, NgArray<int> & treesearch, \n\t\t\t NgArray<int> & freelist, SphereList & list,\n\t\t\t IndexSet & insphere, IndexSet & closesphere, Array<DelaunayTet> & newels)\n  {\n    static Timer t(\"Meshing3::AddDelaunayPoint\", NoTracing, NoTiming); RegionTimer reg(t);\n    static Timer tsearch(\"addpoint, search\", NoTracing, NoTiming);\n    static Timer tfind(\"addpoint, find all tets\", NoTracing, NoTiming);\n    static Timer tnewtets(\"addpoint, build new tets\", NoTracing, NoTiming);\n    static Timer tinsert(\"addpoint, insert\", NoTracing, NoTiming);\n\n    /*\n      find any sphere, such that newp is contained in\n    */\n    // DelaunayTet el;\n    int cfelind = -1;\n\n    const Point<3> * pp[4];\n    Point<3> pc;\n    Point3d tpmin, tpmax;\n\n\n\n    /*\n    // stop search if intersecting point is close enough to center\n    tettree.GetFirstIntersecting (newp, newp, treesearch, [&](const auto pi)\n            {\n                double quot = Dist2 (centers.Get(pi), newp);\n                return (quot < 0.917632 * radi2.Get(pi));\n            } );\n    // tettree.GetIntersecting (newp, newp, treesearch);\n\n    double quot,minquot(1e20);\n\n    for (auto jjj : treesearch)\n      {\n\tquot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj);\n\t\n\tif((cfelind == -1 || quot < 0.99*minquot) && quot < 1)\n\t  {\n\t    minquot = quot;\n\t    el = tempels.Get(jjj);\n\t    cfelind = jjj;\n\t    if(minquot < 0.917632)\n\t      break;\n\t  }\n      }\n    */\n\n    tsearch.Start();\n    double minquot{1e20};\n    tettree.GetFirstIntersecting\n      (newp, newp, [&](const auto pi)\n       {\n         double rad2 = radi2.Get(pi);\n         double d2 = Dist2 (centers.Get(pi), newp); //  / radi2.Get(pi);\n         if (d2 >= rad2) return false;\n         \n         // if (d2 < 0.917632 * rad2)\n         if (d2 < 0.99 * rad2)\n           {\n             cfelind = pi;\n             return true;\n           }\n         \n\tif (cfelind == -1 || d2 < 0.99*minquot*rad2) \n\t  {\n\t    minquot = d2/rad2;\n\t    cfelind = pi;\n          }\n        return false;\n       } );\n    tsearch.Stop();\n\n    if (cfelind == -1)\n      {\n\tPrintWarning (\"Delaunay, point not in any sphere\");\n\treturn;\n      }\n\t\n    tfind.Start();\n    /*\n      insphere:     point is in sphere -> delete element\n      closesphere:  point is close to sphere -> considered for same center\n    */\n\n    // save overestimate\n    insphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());\n    closesphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());\n\n    insphere.Clear();\n    closesphere.Clear();\n\n\n    insphere.Add (cfelind);\n      \n    bool changed = true;\n    int nstarti = 1, starti;\n\n    while (changed)\n      {\n\tchanged = false;\n\tstarti = nstarti;\n\tnstarti = insphere.GetArray().Size()+1;\n\n\n\t// if point in sphere, then it is also closesphere\n\tfor (int j = starti; j < nstarti; j++)\n\t  {\n\t    int helind = insphere.GetArray().Get(j);\n\t    if (!closesphere.IsIn (helind))\n\t      closesphere.Add (helind);\n\t  }\n\n\t// add connected spheres to insphere - list\n\tfor (int j = starti; j < nstarti; j++)\n\t  {\n\t    list.IterateList (insphere.GetArray().Get(j),\n                              [&](int celind)\n                              {\n                                if (tempels.Get(celind)[0] != PointIndex(PointIndex::INVALID) && \n                                    !insphere.IsIn (celind))\n                                  {\n                                    changed = true;\n                                    insphere.Add (celind);\n                                  }\n                              });\n\t  }\n\t\n\t// check neighbour-tets\n\tfor (int j = starti; j < nstarti; j++)\n\t  for (int k = 0; k < 4; k++)\n\t    {\n\t      int helind = insphere.GetArray().Get(j);\n\t      int nbind = meshnb.GetNB (helind, k);\n\n\t      if (nbind && !insphere.IsIn (nbind) )\n\t\t{\n                  double d2 = Dist2 (centers.Get(nbind), newp);\n\t\t  if (d2 < radi2.Get(nbind) * (1+1e-8) )\n\t\t    closesphere.Add (nbind);\n\t\t    \n\t\t  if (d2 < radi2.Get(nbind) * (1 + 1e-12))\n\t\t    {\n\t\t      // point is in sphere -> remove tet\n\t\t      insphere.Add (nbind);\n\t\t      changed = true;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      PointIndices<3> i3 = tempels.Get(helind).GetFace (k);\n\t\t      const Point<3> & p1 = mesh[i3[0]];\n\t\t      const Point<3> & p2 = mesh[i3[1]];\n\t\t      const Point<3> & p3 = mesh[i3[2]];\n\n\t\t      Vec<3> n = Cross (p2-p1, p3-p1);\n                      n /= n.Length();\n\n\t\t      double dist = n * (newp-p1);\n                      double scal = n * (mesh.Point (tempels.Get(helind)[k])-p1);\n\t\t      if (scal > 0) dist *= -1;\n\n\t\t      if (dist > -1e-10)  // 1e-10\n\t\t\t{\n\t\t\t  insphere.Add (nbind);\n\t\t\t  changed = true;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n      } // while (changed)\n\n    tfind.Stop();\n    tnewtets.Start();\n    newels.SetSize(0);\n    \n    Element2d face(TRIG);\n\n    for (int celind : insphere.GetArray())\n      for (int k = 0; k < 4; k++)\n\t{\n\t  int nbind = meshnb.GetNB (celind, k);\n\n\t  if (!nbind || !insphere.IsIn (nbind))\n\t    {\n\t      tempels.Get (celind).GetFace (k, face);\n\t\t\n\t      // Element newel(TET);\n              DelaunayTet newel;\n\t      for (int l = 0; l < 3; l++)\n                newel[l] = face[l];\n              newel[3] = newpi;\n\n\t      newels.Append (newel);\n\n#ifdef DEBUG_DELAUNAY\n              Vec<3> v1 = mesh[face[1]] - mesh[face[0]];\n              Vec<3> v2 = mesh[face[2]] - mesh[face[0]];\n\t      Vec<3> n = Cross (v1, v2);\n\n              n.Normalize();\n\t      if (n * Vec3d(mesh.Point (face[0]), \n\t\t\t    mesh.Point (tempels.Get(celind)[k]))\n\t\t  > 0)\n\t\tn *= -1;\n\n              double hval = n *  ( newp - mesh[face[0]]);\n\t\t\n\t      if (hval > -1e-12)\n\t\t{\n\t\t  cerr << \"vec to outer\" << endl;\n\t\t  (*testout) << \"vec to outer, hval = \" << hval << endl;\n\t\t  (*testout) << \"v1 x v2 = \" << Cross (v1, v2) << endl;\n\t\t  (*testout) << \"facep: \"\n\t\t\t     << mesh.Point (face[0]) << \" \"\n\t\t\t     << mesh.Point (face[1]) << \" \"\n\t\t\t     << mesh.Point (face[2]) << endl;\n\t\t}\n#endif\n\t    }\n\t}\n\n    meshnb.ResetFaceHT (10*insphere.GetArray().Size()+1);\n\n    for (auto celind : insphere.GetArray())\n      {\n\tmeshnb.Delete (celind); \n\tlist.DeleteElement (celind);\n\t  \n\tfor (int k = 0; k < 4; k++)\n        tempels.Elem(celind)[k] = PointIndex::INVALID;\n        \n        tettree.DeleteElement (celind);\n\tfreelist.Append (celind);\n      }\n\n    bool hasclose = false;\n    for (int ind : closesphere.GetArray())\n      {\n\tif (!insphere.IsIn(ind) &&\n\t    fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 )\n\t  hasclose = true;\n      }\n\n    /*\n    for (int j = 1; j <= newels.Size(); j++)\n      {\n        const auto & newel = newels.Get(j);\n    */\n    for (const auto & newel : newels)\n      {\n\tint nelind;\n\n\tif (!freelist.Size())\n\t  {\n\t    tempels.Append (newel);\n\t    nelind = tempels.Size();\n\t  }\n\telse\n\t  {\n\t    nelind = freelist.Last();\n\t    freelist.DeleteLast();\n\n\t    tempels.Elem(nelind) = newel;\n\t  }\n\n\tmeshnb.Add (nelind);\n\tlist.AddElement (nelind);\n\n\tfor (int k = 0; k < 4; k++)\n\t  pp[k] = &mesh.Point (newel[k]);\n\n\tif (CalcSphereCenter (&pp[0], pc) )\n\t  {\n#ifdef DEBUG_DELAUNAY\n\t    PrintSysError (\"Delaunay: New tet is flat\");\n\n\t    (*testout) << \"new tet is flat\" << endl;\n\t    for (int k = 0; k < 4; k++)\n\t      (*testout) << newel[k] << \" \";\n\t    (*testout) << endl;\n\t    for (int k = 0; k < 4; k++)\n\t      (*testout) << *pp[k-1] << \" \";\n\t    (*testout) << endl;\n#endif\n            ;\n\t  }\n\n\tdouble r2 = Dist2 (*pp[0], pc);\n\tif (hasclose)\n          /*\n\t  for (int k = 1; k <= closesphere.GetArray().Size(); k++)\n\t    {\n\t      int csameind = closesphere.GetArray().Get(k); \n          */\n          for (int csameind : closesphere.GetArray())\n            {\n\t      if (!insphere.IsIn(csameind) &&\n\t\t  fabs (r2 - radi2.Get(csameind)) < 1e-10 && \n\t\t  Dist2 (pc, centers.Get(csameind)) < 1e-20)\n\t\t{\n\t\t  pc = centers.Get(csameind);\n\t\t  r2 = radi2.Get(csameind);\n\t\t  list.ConnectElement (nelind, csameind);\n\t\t  break;\n\t\t}\n\t    }\n      \n\tif (centers.Size() < nelind)\n\t  {\n\t    centers.Append (pc);\n\t    radi2.Append (r2);\n\t  }\n\telse\n\t  {\n\t    centers.Elem(nelind) = pc;\n\t    radi2.Elem(nelind) = r2;\n\t  }\n\n\tclosesphere.Add (nelind);\n\t  \n\ttpmax = tpmin = *pp[0];\n\tfor (int k = 1; k <= 3; k++)\n\t  {\n\t    tpmin.SetToMin (*pp[k]);\n\t    tpmax.SetToMax (*pp[k]);\n\t  }\n\ttpmax = tpmax + 0.01 * (tpmax - tpmin);\n        tinsert.Start();\n\ttettree.Insert (tpmin, tpmax, nelind);\n        tinsert.Stop();\n      }\n      tnewtets.Stop();\n  }\n\n\n\n\n\n\n  void Delaunay1 (Mesh & mesh, int domainnr, const MeshingParameters & mp, const AdFront3 & adfront,\n\t\t  NgArray<DelaunayTet> & tempels,\n\t\t  int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax)\n  {\n    static Timer t(\"Meshing3::Delaunay1\"); RegionTimer reg(t);\n    \n    NgArray<Point<3>> centers;\n    NgArray<double> radi2;\n  \n    Box<3> bbox(Box<3>::EMPTY_BOX);\n\n    for (auto & face : adfront.Faces())\n      for (PointIndex pi : face.Face().PNums())      \n        bbox.Add (mesh.Point(pi));\n\n    for (PointIndex pi : mesh.LockedPoints())\n      bbox.Add (mesh.Point (pi));\n    \n    pmin = bbox.PMin();\n    pmax = bbox.PMax();\n\n\n    Vec<3> vdiag = pmax-pmin;\n    // double r1 = vdiag.Length();\n    double r1 = sqrt (3.0) * max3(vdiag(0), vdiag(1), vdiag(2));\n    vdiag = Vec<3> (r1, r1, r1);\n    //double r2;\n\n    Point<3> pmin2 = pmin - 8 * vdiag;\n    Point<3> pmax2 = pmax + 8 * vdiag;\n\n    Point<3> cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2);\n    cp2(0) = pmin2(0);\n    cp3(1) = pmin2(1);\n    cp4(2) = pmin2(2);\n\n\n    size_t np = mesh.GetNP();\n\n    startel[0] = mesh.AddPoint (cp1);\n    startel[1] = mesh.AddPoint (cp2);\n    startel[2] = mesh.AddPoint (cp3);\n    startel[3] = mesh.AddPoint (cp4);\n\n    // flag points to use for Delaunay:\n    Array<bool, PointIndex> usep(np);\n    usep = false;\n\n    for (auto & face : adfront.Faces())\n      for (PointIndex pi : face.Face().PNums())      \n        usep[pi] = true;\n\n    /*\n    for (size_t i = oldnp + PointIndex::BASE; \n\t i < np + PointIndex::BASE; i++)\n    */\n    for (auto i : mesh.Points().Range().Modify(oldnp, -4))\n      usep[i] = true;\n\n    for (PointIndex pi : mesh.LockedPoints())\n      usep[pi] = true;\n    \n    // mark points of free edge segments (no adjacent face)\n    for (auto & seg : mesh.LineSegments())\n      if(seg.domin == domainnr && seg.domout == domainnr)\n      {\n        usep[seg[0]] = true;\n        usep[seg[1]] = true;\n      }\n\n    NgArray<int> freelist;\n\n    int cntp = 0;\n\n    MeshNB meshnb (tempels, mesh.GetNP() + 5);\n    SphereList list;\n\n    pmin2 = pmin2 + 0.1 * (pmin2 - pmax2);\n    pmax2 = pmax2 + 0.1 * (pmax2 - pmin2);\n\n    DTREE tettree(pmin2, pmax2);\n\n\n    tempels.Append (startel);\n    meshnb.Add (1);\n    list.AddElement (1);\n    NgArray<int> connected, treesearch;\n\n    Box<3> tbox(Box<3>::EMPTY_BOX);\n    for (size_t k = 0; k < 4; k++)\n      tbox.Add (mesh.Point(startel[k]));\n    Point<3> tpmin = tbox.PMin();\n    Point<3> tpmax = tbox.PMax();\n    \n    tpmax = tpmax + 0.01 * (tpmax - tpmin);\n    tettree.Insert (tpmin, tpmax, 1);\n\n    Point<3> pc;\n\t  \n    const Point<3> * pp[4];\n    for (int k = 0; k < 4; k++)\n      pp[k] = &mesh.Point (startel[k]);\n    CalcSphereCenter (&pp[0], pc);\n    \n    centers.Append (pc);\n    radi2.Append (Dist2 (*pp[0], pc));\n\n\n    IndexSet insphere(mesh.GetNP());\n    IndexSet closesphere(mesh.GetNP());\n\n    // \"random\" reordering of points  (speeds a factor 3 - 5 !!!)\n    Array<PointIndex, PointIndex> mixed(np);\n    // int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };\n    // int prims[] = { 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };\n    int prims[] = { 211, 223, 227, 229, 233, 239, 241, 251, 257, 263 }; \n    int prim;\n  \n    {\n      int i = 0;\n      while (np % prims[i] == 0) i++;\n      prim = prims[i];\n    }\n    \n    // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)\n    for (PointIndex pi : mesh.Points().Range().Modify(0, -4))\n      // mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE );\n      mixed[pi] = (prim * (pi-IndexBASE<PointIndex>()+1)) % np + IndexBASE<PointIndex>() ;\n\n    Array<DelaunayTet> newels;\n    // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)\n    for (PointIndex pi : mesh.Points().Range().Modify(0, -4))      \n      {\n\tif ((pi-IndexBASE<PointIndex>()) % 1000 == 0)\n\t  {\n\t    if ((pi-IndexBASE<PointIndex>()) % 10000 == 0)\n\t      PrintDot ('+');\n\t    else\n\t      PrintDot ('.');\n\t  }\n\n\tmultithread.percent = 100.0 * (pi-IndexBASE<PointIndex>()) / np;\n\tif (multithread.terminate)\n\t  break;\n\n\tPointIndex newpi = mixed[pi];\n\n\tif (!usep[newpi])\n\t  continue;\n\n\tcntp++;\n\n\tconst MeshPoint & newp = mesh[newpi];\n      \n\tAddDelaunayPoint (newpi, newp, tempels, mesh,\n\t\t\t  tettree, meshnb, centers, radi2, \n\t\t\t  connected, treesearch, freelist, list, insphere, closesphere, newels);\n\n      }\n    \n    for (int i = tempels.Size(); i >= 1; i--)\n      if (!tempels.Get(i)[0].IsValid())\n\ttempels.DeleteElement (i);\n\n    PrintDot ('\\n');\n\n    PrintMessage (3, \"Points: \", cntp);\n    PrintMessage (3, \"Elements: \", tempels.Size());\n    PrintMessage (3, \"Tree data entries per element: \", 1.0*tettree.N*tettree.GetNLeaves() / tempels.Size());\n    PrintMessage (3, \"Tree nodes per element: \", 1.0*tettree.GetNNodes() / tempels.Size());\n    //   (*mycout) << cntp << \" / \" << tempels.Size() << \" points/elements\" << endl;\n\n    /*\n      cout << \"tempels: \";\n      tempels.PrintMemInfo(cout);\n      cout << \"Searchtree: \";\n      tettree.Tree().PrintMemInfo(cout);\n      cout << \"MeshNB: \";\n      meshnb.PrintMemInfo(cout);\n    */\n  }\n\n\n  void DelaunayRemoveDegenerated( const Mesh::T_POINTS & points, NgArray<DelaunayTet> & tempels, int np )\n  {\n    static Timer tdegenerated(\"Delaunay - remove degenerated\"); RegionTimer rt(tdegenerated);\n\n    TBitArray<PointIndex> badnode(points.Size());\n    badnode.Clear();\n\n    int ndeg = 0;\n    for (int i = 1; i <= tempels.Size(); i++)\n      {\n\tElement el(4);\n\tfor (int j = 0; j < 4; j++)\n\t  el[j] = tempels.Elem(i)[j];\n\t//      Element & el = tempels.Elem(i);\n\tconst Point3d & lp1 = points[el[0]];\n\tconst Point3d & lp2 = points[el[1]];\n\tconst Point3d & lp3 = points[el[2]];\n\tconst Point3d & lp4 = points[el[3]];\n\tVec3d v1(lp1, lp2);\n\tVec3d v2(lp1, lp3);\n\tVec3d v3(lp1, lp4);\n\tVec3d n = Cross (v1, v2);\n\tdouble vol = n * v3;\n\n\tdouble h = v1.Length() + v2.Length() + v3.Length();\n\tif (fabs (vol) < 1e-8 * (h * h * h) &&\n\t    (el[0] < IndexBASE<PointIndex>()+np &&\n             el[1] < IndexBASE<PointIndex>()+np &&\n\t     el[2] < IndexBASE<PointIndex>()+np &&\n             el[3] < IndexBASE<PointIndex>()+np) )   // old: 1e-12\n\t  {\n\t    badnode.SetBitAtomic(el[0]);\n\t    badnode.SetBitAtomic(el[1]);\n\t    badnode.SetBitAtomic(el[2]);\n\t    badnode.SetBitAtomic(el[3]);\n\t    ndeg++;\n\t    (*testout) << \"vol = \" << vol << \" h = \" << h << endl;\n\t  }\n\n\tif (vol > 0)\n\t  Swap (el[2], el[3]);\n      }\n\n    auto ne = tempels.Size();\n    for (int i = ne; i >= 1; i--)\n      {\n\tconst DelaunayTet & el = tempels.Get(i);\n\tif (badnode.Test(el[0]) ||\n\t    badnode.Test(el[1]) ||\n\t    badnode.Test(el[2]) ||\n\t    badnode.Test(el[3]) )\n\t  tempels.DeleteElement(i);\n      }\n\n  \n    PrintMessage (3, ndeg, \" degenerated elements removed\");\n  }\n\n  // Remove flat tets containing two adjacent surface trigs\n  void DelaunayRemoveTwoTriaTets( const Mesh & mesh, NgArray<DelaunayTet> & tempels, NgArray<int> & openels )\n  {\n    static Timer topenel(\"Delaunay - find openel\"); RegionTimer rt(topenel);\n\n    // find surface triangles which are no face of any tet\n    TBitArray<PointIndex> bnd_points( mesh.GetNP() );\n    bnd_points.Clear();\n\n    for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n      {\n        const Element2d & tri = mesh.OpenElement(i);\n        bnd_points.SetBit(tri[0]);\n        bnd_points.SetBit(tri[1]);\n        bnd_points.SetBit(tri[2]);\n      }\n\n    auto ne = tempels.Size();\n    Array<int> tets_with_3_bnd_points(ne);\n    atomic<int> cnt = 0;\n\n    // table of tets with >= 2 boundary points, store in extra array tets with >=3 boundary points\n    auto p2el = ngcore::CreateSortedTable<int, PointIndex>( ne,\n               [&](auto & table, int ei)\n               {\n                 const auto & el = tempels[ei];\n                 int num_bnd_points = 0;\n\n                 for( auto i : Range(4) )\n                   if(bnd_points[el[i]])\n                     num_bnd_points++;\n\n                 if(num_bnd_points>1)\n                   {\n                     table.Add (el[0], ei);\n                     table.Add (el[1], ei);\n                     table.Add (el[2], ei);\n                     table.Add (el[3], ei);\n                   }\n\n                 // table creator is running this code 2 times, only store tets on last run\n                 if(table.GetMode()==3 && num_bnd_points>2)\n                   tets_with_3_bnd_points[cnt++] = ei;\n               }, mesh.GetNP());\n\n    tets_with_3_bnd_points.SetSize(cnt);\n\n    static Timer t1(\"Build face table\"); t1.Start();\n    // ngcore::ClosedHashTable< ngcore::IVec<3>, int > face_table( 4*cnt + 3 );\n    ngcore::ClosedHashTable< PointIndices<3>, int > face_table( 4*cnt + 3 );\n    for (auto ei : tets_with_3_bnd_points)\n      for (auto j : Range(4))\n        {\n          PointIndices<3> i3 = tempels[ei].GetFace (j);\n          // ngcore::IVec<3> i3 = {i3_[0], i3_[1], i3_[2]};\n          if(bnd_points[i3[0]] && bnd_points[i3[1]] && bnd_points[i3[2]])\n            {\n              i3.Sort();\n              face_table.Set( i3, true );\n            }\n        }\n    t1.Stop();\n\n    static Timer t2(\"check faces\"); t2.Start();\n\n    openels.SetSize(0);\n    for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n      {\n\tconst Element2d & tri = mesh.OpenElement(i);\n        // ngcore::IVec<3,PointIndex> i3(tri[0], tri[1], tri[2]);\n        PointIndices<3> i3(tri[0], tri[1], tri[2]);\n\ti3.Sort();\n        if(!face_table.Used(i3))\n            openels.Append(i);\n      }\n\n    t2.Stop();\n\n    auto p2sel = ngcore::CreateSortedTable<int, PointIndex>( Range(openels.Size()),\n           [&](auto & table, int i)\n           {\n             auto openel_i = openels[i];\n             const Element2d & tri = mesh.OpenElement(openel_i);\n             table.Add(tri[0], openel_i);\n             table.Add(tri[1], openel_i);\n             table.Add(tri[2], openel_i);\n           }, mesh.GetNP());\n\n    TBitArray<PointIndex> badnode(mesh.GetNP());\n    badnode.Clear();\n\n    ngcore::ParallelForRange(openels.Size(), [&] (auto myrange) {\n        for (auto i_ : myrange)\n          {\n            auto i = openels[i_];\n            const Element2d & tri = mesh.OpenElement(i);\n\n            for( auto edge : Range(3) )\n            {\n                auto pi0 = tri[edge];\n                auto pi1 = tri[(edge+1)%3];\n                if(pi0>pi1)\n                    Swap(pi0, pi1);\n\n                // find other trig with edge pi0, pi1\n                int i_other = -1;\n                for(auto ii : p2sel[pi0])\n                {\n                    if(ii==i)\n                        continue;\n                    auto & tri_other = mesh.OpenElement(ii);\n                    if(tri_other[0]==pi1 || tri_other[1]==pi1 || tri_other[2]==pi1)\n                    {\n                        i_other = ii;\n                        break;\n                    }\n                }\n\n                if(i_other>i)\n                {\n                    auto & tri_other = mesh.OpenElement(i_other);\n                    PointIndex pi2 = tri[(edge+2)%3];\n                    PointIndex pi3 = tri_other[0]-pi0+tri_other[1]-pi1+tri_other[2];\n                    if(pi2>pi3)\n                        Swap(pi2, pi3);\n\n                    // search for tet with edge pi2-pi3\n                    for(auto ei : p2el[pi2])\n                    {\n                        auto & el = tempels[ei];\n\n                        if(el[0]==pi3 || el[1]==pi3 || el[2]==pi3 || el[3]==pi3)\n                        {\n                            const Point3d & p1 = mesh[pi0];\n                            const Point3d & p2 = mesh[pi1];\n                            const Point3d & p3 = mesh[pi2];\n                            const Point3d & p4 = mesh[pi3];\n                            Vec3d v1(p1, p2);\n                            Vec3d v2(p1, p3);\n                            Vec3d v3(p1, p4);\n                            Vec3d n = Cross (v1, v2);\n                            double vol = n * v3;\n\n                            double h = v1.Length() + v2.Length() + v3.Length();\n                            if (fabs (vol) < 1e-4 * (h * h * h))   // old: 1e-12\n                            {\n                              badnode.SetBitAtomic(pi2);\n                              badnode.SetBitAtomic(pi3);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n          }\n    });\n\n    for (int i = ne; i >= 1; i--)\n      {\n\tconst DelaunayTet & el = tempels.Get(i);\n\tif (badnode[el[0]] ||\n\t    badnode[el[1]] ||\n\t    badnode[el[2]] ||\n\t    badnode[el[3]] )\n\t  tempels.DeleteElement(i);\n      }\n  }\n\n  void DelaunayRemoveIntersecting( const Mesh & mesh, NgArray<DelaunayTet> & tempels, NgArray<int> & openels, Point3d pmin, Point3d pmax )\n  {\n    static Timer trem_intersect(\"Delaunay - remove intersecting\"); RegionTimer rt(trem_intersect);\n\n    // find intersecting:\n    PrintMessage (3, \"Remove intersecting\");\n    if (openels.Size())\n      {\n\tBoxTree<3> setree(pmin, pmax);\n\n\t/*      \n\t\tcout << \"open elements in search tree: \" << openels.Size() << endl;\n\t\tcout << \"pmin, pmax = \" << pmin << \" - \" << pmax << endl;\n\t*/\n\n\tfor (int i = 1; i <= openels.Size(); i++)\n\t  {\n\t    int fnr;\n\t    fnr = openels.Get(i);\n\t    if (fnr)\n\t      {\n\t\tconst Element2d & tri = mesh.OpenElement(fnr);\n\t      \n\t\tPoint3d ltpmin (mesh.Point(tri[0]));\n\t\tPoint3d ltpmax (ltpmin);\n\t      \n\t\tfor (int k = 2; k <= 3; k++)\n\t\t  {\n\t\t    ltpmin.SetToMin (mesh.Point (tri.PNum(k)));\n\t\t    ltpmax.SetToMax (mesh.Point (tri.PNum(k)));\n\t\t  }\n\t\tsetree.Insert (ltpmin, ltpmax, fnr);\n\t      }\n\t  }\n      \n\tNgArray<int> neartrias;\n\tfor (int i = 1; i <= tempels.Size(); i++)\n\t  {\n\t    const Point<3> *pp[4];\n\t    int tetpi[4];\n\t    DelaunayTet & el = tempels.Elem(i);\n\t  \n\t    int intersect = 0;\n\t  \n\t    for (int j = 0; j < 4; j++)\n\t      {\n\t\tpp[j] = &mesh.Point(el[j]);\n\t\ttetpi[j] = el[j]-IndexBASE<PointIndex>()+1;\n\t      }\n\t  \n\t    Point3d tetpmin(*pp[0]);\n\t    Point3d tetpmax(tetpmin);\n\t    for (int j = 1; j < 4; j++)\n\t      {\n\t\ttetpmin.SetToMin (*pp[j]);\n\t\ttetpmax.SetToMax (*pp[j]);\n\t      }\n\t    tetpmin = tetpmin + 0.01 * (tetpmin - tetpmax);\n\t    tetpmax = tetpmax + 0.01 * (tetpmax - tetpmin);\n\t  \n\t    setree.GetIntersecting (tetpmin, tetpmax, neartrias);\n\t  \n\t  \n\t    //      for (j = 1; j <= mesh.GetNSE(); j++)\n\t    //\t{\n\t    for (int jj = 1; jj <= neartrias.Size(); jj++)\n\t      {\n\t\tint j = neartrias.Get(jj);\n\t      \n\t\tconst Element2d & tri = mesh.OpenElement(j);\n\t\tconst Point<3> *tripp[3];\n\t\tint tripi[3];\n\t      \n\t\tfor (int k = 1; k <= 3; k++)\n\t\t  {\n\t\t    tripp[k-1] = &mesh.Point (tri.PNum(k));\n\t\t    tripi[k-1] = tri.PNum(k)-IndexBASE<PointIndex>()+1;\n\t\t  }\n\t      \n\t\tif (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))\n\t\t  {\n\t\t    /*\n\t\t    int il1, il2;\n\t\t    (*testout) << \"intersect !\" << endl;\n\t\t    (*testout) << \"triind: \";\n\t\t    for (il1 = 0; il1 < 3; il1++)\n\t\t      (*testout) << \" \" << tripi[il1];\n\t\t    (*testout) << endl;\n\t\t    (*testout) << \"tetind: \";\n\t\t    for (il2 = 0; il2 < 4; il2++)\n\t\t      (*testout) << \" \" << tetpi[il2];\n\t\t    (*testout) << endl;\n\t\t  \n\t\t    (*testout) << \"trip: \";\n\t\t    for (il1 = 0; il1 < 3; il1++)\n\t\t      (*testout) << \" \" << *tripp[il1];\n\t\t    (*testout) << endl;\n\t\t    (*testout) << \"tetp: \";\n\t\t    for (il2 = 0; il2 < 4; il2++)\n\t\t      (*testout) << \" \" << *pp[il2];\n\t\t    (*testout) << endl;\n\t\t    */\n\t\t  \n\t\t  \n\t\t    intersect = 1;\n\t\t    break;\n\t\t  }\n\t      }\n\t  \n\t  \n\t    if (intersect)\n\t      {\n\t\ttempels.DeleteElement(i);\n\t\ti--;\n\t      }\n\t  }\n      }\n  }\n\n  void DelaunayRemoveOuter( const Mesh & mesh, NgArray<DelaunayTet> & tempels, const AdFront3 & adfront )\n  {\n    static Timer trem_outer(\"Delaunay - remove outer\"); RegionTimer rt(trem_outer);\n\n\n    PrintMessage (3, \"Remove outer\");\n\n    // find connected tets (with no face between, and no hole due\n    // to removed intersecting tets.\n    //  INDEX_3_HASHTABLE<INDEX_2> innerfaces(np);\n\n  \n    INDEX_3_HASHTABLE<int> boundaryfaces(mesh.GetNOpenElements()/3+1);\n    /*\n    for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n      {\n\tconst Element2d & tri = mesh.OpenElement(i);\n\tINDEX_3 i3 (tri[0], tri[1], tri[2]);\n\ti3.Sort();\n\tboundaryfaces.PrepareSet (i3);\n      }\n    */\n    for (const Element2d & tri : mesh.OpenElements())\n      {\n\tPointIndices<3> i3 (tri[0], tri[1], tri[2]);\n\ti3.Sort();\n\tboundaryfaces.PrepareSet (i3);\n      }\n    boundaryfaces.AllocateElements();\n    for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n      {\n\tconst Element2d & tri = mesh.OpenElement(i);\n\tPointIndices<3> i3 (tri[0], tri[1], tri[2]);\n\ti3.Sort();\n\tboundaryfaces.Set (i3, 1);\n      }\n\n    /*\n    for (int i = 0; i < tempels.Size(); i++)\n      for (int j = 0; j < 4; j++)\n\ttempels[i].NB(j) = 0;\n    */\n    for (auto & el : tempels)\n      for (int j = 0; j < 4; j++)\n\tel.NB(j) = 0;\n\n    /*\n    TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());\n\n    for (const DelaunayTet & el : tempels)\n      {\n\tPointIndices<4> i4(el[0], el[1], el[2], el[3]);\n\ti4.Sort();\n\telsonpoint.IncSizePrepare (i4.I1());\n\telsonpoint.IncSizePrepare (i4.I2());\n      }\n\n    elsonpoint.AllocateElementsOneBlock();\n\n    for (int i = 0; i < tempels.Size(); i++)\n      {\n\tconst DelaunayTet & el = tempels[i];\n\tPointIndices<4> i4(el[0], el[1], el[2], el[3]);\n\ti4.Sort();\n\telsonpoint.Add (i4.I1(), i+1);\n\telsonpoint.Add (i4.I2(), i+1);\n      }\n    */\n\n    TableCreator<int, PointIndex> creator(mesh.GetNP());\n    while (!creator.Done())\n      {\n        for (int i = 0; i < tempels.Size(); i++)\n          {\n            const DelaunayTet & el = tempels[i];\n            PointIndices<4> i4(el[0], el[1], el[2], el[3]);\n            i4.Sort();\n            creator.Add (i4[0], i+1);\n            creator.Add (i4[1], i+1);\n          }\n        creator++;\n      }\n    auto elsonpoint = creator.MoveTable();\n\n    \n    \n    //  cout << \"elsonpoint mem: \";\n    //  elsonpoint.PrintMemInfo(cout);\n\n    INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100);   \n  \n    Element2d hel(TRIG);\n    // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++)\n    for (PointIndex pi : mesh.Points().Range())\n      {\n\tfaceht.SetSize (4 * elsonpoint[pi].Size());\n\tfor (int ii = 0; ii < elsonpoint[pi].Size(); ii++)\n\t  {\n\t    int i = elsonpoint[pi][ii];\n\t    const DelaunayTet & el = tempels.Get(i);\n\n\t    for (int j = 1; j <= 4; j++)\n\t      {\n\t\tel.GetFace (j-1, hel);\n\t\thel.Invert();\n\t\thel.NormalizeNumbering();\n\t      \n\t\tif (hel[0] == pi)\n\t\t  {\n\t\t    PointIndices<3> i3(hel[0], hel[1], hel[2]);\n\t\t  \n\t\t    if (!boundaryfaces.Used (i3))\n\t\t      {\n\t\t\tif (faceht.Used (i3))\n\t\t\t  {\n\t\t\t    INDEX_2 i2 = faceht.Get(i3);\n\t\t\t  \n\t\t\t    tempels.Elem(i).NB(j-1) = i2.I1();\n\t\t\t    tempels.Elem(i2.I1()).NB(i2.I2()-1) = i;\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    hel.Invert();\n\t\t\t    hel.NormalizeNumbering();\n\t\t\t    PointIndices<3> i3i(hel[0], hel[1], hel[2]);\n\t\t\t    INDEX_2 i2(i, j);\n\t\t\t    faceht.Set (i3i, i2);\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n      }\n  \n    /*\n      for (i = 1; i <= tempels.Size(); i++)\n      {\n      const DelaunayTet & el = tempels.Get(i);\n      for (j = 1; j <= 4; j++)\n      {\n      INDEX_3 i3;\n      Element2d face;\n      el.GetFace1 (j, face);\n      for (int kk = 1; kk <= 3; kk++)\n      i3.I(kk) = face.PNum(kk);\n\n      i3.Sort();\n      if (!boundaryfaces.Used (i3))\n      {\n      if (innerfaces.Used(i3))\n      {\n      INDEX_2 i2;\n      i2 = innerfaces.Get(i3);\n      i2.I2() = i;\n      innerfaces.Set (i3, i2);\n      }\n      else\n      {\n      INDEX_2 i2;\n      i2.I1() = i;\n      i2.I2() = 0;\n      innerfaces.Set (i3, i2);\n      }\n      }\n      }\n      }\n    */\n\n    /*\n      (*testout) << \"nb elements:\" << endl;\n      for (i = 1; i <= tempels.Size(); i++)\n      {\n      (*testout) << i << \" \";\n      for (j = 1; j <= 4; j++)\n      (*testout) << tempels.Get(i).NB1(j) << \" \";\n      (*testout) << endl;\n      }\n  \n      (*testout) << \"pairs:\" << endl;\n      for (i = 1; i <= innerfaces.GetNBags(); i++)\n      for (j = 1; j <= innerfaces.GetBagSize(i); j++)\n      {\n      INDEX_3 i3;\n      INDEX_2 i2;\n      innerfaces.GetData (i, j, i3, i2);\n      (*testout) << i2 << endl;\n      }\n    */\n\n\n\n\n\n\n\n    /*\n      cout << \"innerfaces: \";\n      innerfaces.PrintMemInfo (cout);\n    */\n\n    //  cout << \"boundaryfaces: \";\n    //  boundaryfaces.PrintMemInfo (cout);\n\n\n    PrintMessage (5, \"tables filled\");\n \n\n    auto ne = tempels.Size();\n    BitArray inner(ne+1), outer(ne+1);\n    inner.Clear();\n    outer.Clear();\n    NgArray<int> elstack;\n\n    /*\n      int starti = 0;\n      for (i = 1; i <= ne; i++)\n      {\n      const Element & el = tempels.Get(i);\n      for (j = 1; j <= 4; j++)\n      for (k = 1; k <= 4; k++)\n      if (el.PNum(j) == startel.PNum(k))\n      {\n      outer.Set(i);\n      starti = i;\n      }\n      }\n    */\n\n    int lowest_undefined_el = 1;\n    while (1)\n      {\n\tint inside;\n\tbool done = 1;\n\n\tint i;\n\tfor (i = lowest_undefined_el; i <= ne; i++)\n\t  if (!inner.Test(i) && !outer.Test(i))\n\t    {\n              lowest_undefined_el = i+1;\n\t      done = 0;\n\t      break;\n\t    }\n\n\tif (done) break;\n      \n\tconst DelaunayTet & el = tempels.Get(i);\n\tconst Point3d & p1 = mesh.Point (el[0]);\n\tconst Point3d & p2 = mesh.Point (el[1]);\n\tconst Point3d & p3 = mesh.Point (el[2]);\n\tconst Point3d & p4 = mesh.Point (el[3]);\n      \n\tPoint3d ci = Center (p1, p2, p3, p4);\n\n\tinside = adfront.Inside (ci);\n\n\t/*\n\t  cout << \"startel: \" << i << endl;\n\t  cout << \"inside = \" << inside << endl;\n\t  cout << \"ins2 = \" << adfront->Inside (Center (ci, p1)) << endl;\n\t  cout << \"ins3 = \" << adfront->Inside (Center (ci, p2)) << endl;\n\t*/\n      \n\telstack.SetSize(0);\n\telstack.Append (i);\n  \n\twhile (elstack.Size())\n\t  {\n\t    int ei = elstack.Last();\n\t    elstack.DeleteLast();\n\t  \n\t    if (!inner.Test(ei) && !outer.Test(ei))\n\t      {\n\t\tif (inside)\n\t\t  inner.SetBit(ei);\n\t\telse\n\t\t  outer.SetBit(ei);\n\n\n\t\tfor (int j = 1; j <= 4; j++)\n\t\t  {\n\t\t    INDEX_3 i3 = tempels.Get(ei).GetFace(j-1);\n\t\t    /*\n\t\t    Element2d face;\n\t\t    tempels.Get(ei).GetFace(j, face);\n\t\t    for (int kk = 1; kk <= 3; kk++)\n\t\t      i3.I(kk) = face.PNum(kk);\n\t\t    */\n\t\t    i3.Sort();\n\t\t  \n\n\t\t    if (tempels.Get(ei).NB(j-1))\n\t\t      elstack.Append (tempels.Get(ei).NB(j-1));\n\n\t\t    /*\n\t\t      if (innerfaces.Used(i3))\n\t\t      {\n\t\t      INDEX_2 i2 = innerfaces.Get(i3);\n\t\t      int other = i2.I1() + i2.I2() - ei;\n\n\t\t      if (other != tempels.Get(ei).NB1(j))\n\t\t      cerr << \"different1 !!\" << endl;\n\n\t\t      if (other)\n\t\t      {\n\t\t      elstack.Append (other);\n\t\t      }\n\t\t      }\n\t\t      else\n\t\t      if (tempels.Get(ei).NB1(j))\n\t\t      cerr << \"different2 !!\" << endl;\n\t\t    */\n\n\t\t  }\n\t      }\n\t  }\n      }\n\n\n\n    // check outer elements\n    if (debugparam.slowchecks)\n      {\n\tfor (int i = 1; i <= ne; i++)\n\t  {\n\t    const DelaunayTet & el = tempels.Get(i);\n\t    const Point3d & p1 = mesh.Point (el[0]);\n\t    const Point3d & p2 = mesh.Point (el[1]);\n\t    const Point3d & p3 = mesh.Point (el[2]);\n\t    const Point3d & p4 = mesh.Point (el[3]);\n\t  \n\t    Point3d ci = Center (p1, p2, p3, p4);\n\t  \n\t    //       if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1)))\n\t    // \tcout << \"ERROR: outer test unclear !!!\" << endl;\t\n\t  \n\t    if (inner.Test(i) != adfront.Inside (ci))\n\t      {\n\t\t/*\n\t\t  cout << \"ERROR: outer test wrong !!!\" \n\t\t  << \"inner = \" << int(inner.Test(i))\n\t\t  << \"outer = \" << int(outer.Test(i))\n\t\t  << endl;\n\t      \n\t\t  cout << \"Vol = \" << Determinant(Vec3d(p1, p2),\n\t\t  Vec3d(p1, p3),\n\t\t  Vec3d(p1, p4)) << endl;\n\t      \n\t\t*/\t      \n\t\tfor (int j = 1; j <= 4; j++)\n\t\t  {\n\t\t    Point3d hp;\n\t\t    switch (j)\n\t\t      {\n\t\t      case 1: hp = Center (ci, p1); break;\n\t\t      case 2: hp = Center (ci, p2); break;\n\t\t      case 3: hp = Center (ci, p3); break;\n\t\t      case 4: hp = Center (ci, p4); break;\n\t\t      }\n\t\t    //\t\t  cout << \"inside(\" << hp << \") = \" << adfront->Inside(hp) << endl;\n\t\t  }\n\t      \n\t      }\n\t  \n\t    if (adfront.Inside(ci))\n\t      outer.Clear(i);\n\t    else\n\t      outer.SetBit(i);\n\t  }\n      }\n\n\n    /*\n\n    // find bug in innerfaces\n\n    tempmesh.DeleteVolumeElements();\n\n    for (i = 1; i <= innerfaces.GetNBags(); i++)\n    for (j = 1; j <= innerfaces.GetBagSize(i); j++)\n    {\n    INDEX_3 i3;\n    INDEX_2 i2;\n    innerfaces.GetData (i, j, i3, i2);\n    if (i2.I2())\n    {\n    if (outer.Test(i2.I1()) != outer.Test(i2.I2()))\n    {\n    tempmesh.AddVolumeElement (tempels.Get(i2.I1()));\n    tempmesh.AddVolumeElement (tempels.Get(i2.I2()));\n    cerr << \"outer flag different for connected els\" << endl;\n    }\n    }\n    }\n\n\n    cout << \"Check intersectiong once more\" << endl;\n\n    for (i = 1; i <= openels.Size(); i++)\n    {\n    tempmesh.SurfaceElement(2*openels.Get(i)).SetIndex(2);\n    tempmesh.SurfaceElement(2*openels.Get(i)-1).SetIndex(2);\n    }\n\n    //  for (i = 1; i <= tempmesh.GetNE(); i++)\n    //    for (j = 1; j <= tempmesh.GetNSE(); j++)\n    i = 6; j = 403;\n    if (i <= tempmesh.GetNE() && j <= tempmesh.GetNSE())\n    if (tempmesh.SurfaceElement(j).GetIndex()==2)\n    {\n    const Element & el = tempmesh.VolumeElement(i);\n    const Element2d & sel = tempmesh.SurfaceElement(j);\n\n    const Point3d *tripp[3];\n    const Point3d *pp[4];\n    int tetpi[4], tripi[3];\n\n    for (k = 1; k <= 4; k++)\n    {\n    pp[k-1] = &tempmesh.Point(el.PNum(k));\n    tetpi[k-1] = el.PNum(k);\n    }\n\n    for (k = 1; k <= 3; k++)\n    {\n    tripp[k-1] = &tempmesh.Point (sel.PNum(k));\n    tripi[k-1] = sel.PNum(k);\n    }\n\n    (*testout) << \"Check Triangle \" << j << \":\";\n    for (k = 1; k <= 3; k++)\n    (*testout) << \" \" << sel.PNum(k);\n    for (k = 1; k <= 3; k++)\n    (*testout) << \" \" << tempmesh.Point(sel.PNum(k));\n    (*testout) << endl;\n\n    (*testout) << \"Check Tet \" << i << \":\";\n    for (k = 1; k <= 4; k++)\n    (*testout) << \" \" << el.PNum(k);\n    for (k = 1; k <= 4; k++)\n    (*testout) << \" \" << tempmesh.Point(el.PNum(k));\n    (*testout) << endl;\n\n    if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))\n    {\n    cout << \"Intesection detected !!\" << endl;\n    }\n    }\n\n    tempmesh.Save (\"temp.vol\");\n\n    // end bug search\n    */\n\n\n    for (int i = ne; i >= 1; i--)\n      {\n\tif (outer.Test(i))\n\t  tempels.DeleteElement(i);\n      }\n\n\n    // mesh.points.SetSize(mesh.points.Size()-4);\n\n    PrintMessage (5, \"outer removed\");\n\n  }\n\n\n\n  void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp)\n  {\n    static Timer t(\"Meshing3::Delaunay\"); RegionTimer reg(t);\n    \n    PrintMessage (1, \"Delaunay meshing\");\n    PrintMessage (3, \"number of points: \", mesh.GetNP());\n    // PushStatus (\"Delaunay meshing\");\n\n\n    NgArray<DelaunayTet> tempels;\n    Point3d pmin, pmax;\n\n    DelaunayTet startel;\n\n    int oldnp = mesh.GetNP();\n    if (mp.blockfill)\n      {\n\tBlockFillLocalH (mesh, mp);\n\tPrintMessage (3, \"number of points: \", mesh.GetNP());\n      }\n\n    int np = mesh.GetNP();\n\n    Delaunay1 (mesh, domainnr, mp, *adfront, tempels, oldnp, startel, pmin, pmax);\n\n    {\n      // improve delaunay - mesh by swapping !!!!\n\n      Mesh tempmesh;\n      tempmesh.GetMemoryTracer().SetName(\"delaunay-tempmesh\");\n\n      for (auto & meshpoint : mesh.Points())\n        tempmesh.AddPoint (meshpoint);\n      \n      for (auto & tempel : tempels)\n\t{   \n\t  Element el(4);\n\t  for (int j = 0; j < 4; j++)\n            el[j] = tempel[j];\n\n\t  el.SetIndex (1);\n\n\t  const Point<3> & lp1 = mesh.Point (el[0]);\n\t  const Point<3> & lp2 = mesh.Point (el[1]);\n\t  const Point<3> & lp3 = mesh.Point (el[2]);\n\t  const Point<3> & lp4 = mesh.Point (el[3]);\n\t  Vec<3> v1 = lp2-lp1;\n\t  Vec<3> v2 = lp3-lp1;\n\t  Vec<3> v3 = lp4-lp1;\n\n\t  Vec<3> n = Cross (v1, v2);\n\t  double vol = n * v3;\n\t  if (vol > 0) swap (el[2], el[3]);\n\n\t  tempmesh.AddVolumeElement (el);\n\t}\n\n      tempels.DeleteAll();\n\n      MeshQuality3d (tempmesh);\n\n      tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));\n      tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0));\n\n\n    \n      for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n\t{\n\t  Element2d sel = mesh.OpenElement(i);\n\t  sel.SetIndex(1);\n\t  tempmesh.AddSurfaceElement (sel);\n\t  swap (sel[1], sel[2]);\n\t  tempmesh.AddSurfaceElement (sel);\n\t}\n\n\n      for (int i = 1; i <= 4; i++)\n\t{\n\t  Element2d self(TRIG);\n\t  self.SetIndex (1);\n\t  startel.GetFace (i-1, self);\n\t  tempmesh.AddSurfaceElement (self);\n\t}\n\n      \n      //  for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++)\n      //    tempmesh.AddLockedPoint (i);\n      for (auto pi : tempmesh.Points().Range())\n        tempmesh.AddLockedPoint (pi);\n      \n      //  tempmesh.PrintMemInfo(cout);\n      // tempmesh.Save (\"tempmesh.vol\");\n\n      {\n        MeshOptimize3d meshopt(tempmesh, mp);\n        meshopt.SetGoal(OPT_CONFORM);\n        tempmesh.Compress();\n        tempmesh.FindOpenElements ();\n      #ifndef EMSCRIPTEN\n        RegionTaskManager rtm(mp.parallel_meshing ? mp.nthreads : 0);\n      #endif // EMSCRIPTEN\n        for (auto i : Range(10))\n          {\n            PrintMessage (5, \"Num open: \", tempmesh.GetNOpenElements());\n\n            if(i%5==0)\n                tempmesh.FreeOpenElementsEnvironment (1);\n\n            meshopt.SwapImprove();\n          }\n        tempmesh.Compress();\n      }\n    \n      MeshQuality3d (tempmesh);\n    \n      tempels.SetSize(tempmesh.GetNE());\n      tempels.SetSize(0);\n      for (auto & el : tempmesh.VolumeElements())\n        tempels.Append (el);\n    }\n\n    DelaunayRemoveDegenerated(mesh.Points(), tempels, np);\n\n    NgArray<int> openels;\n    DelaunayRemoveTwoTriaTets(mesh, tempels, openels);\n    DelaunayRemoveIntersecting(mesh, tempels, openels, pmin, pmax);\n    DelaunayRemoveOuter(mesh, tempels, *adfront);\n\n    for (int i = 0; i < tempels.Size(); i++)\n      {\n\tElement el(4);\n\tfor (int j = 0; j < 4; j++)\n\t  el[j] = tempels[i][j];\n\tmesh.AddVolumeElement (el);\n      }\n\n    mesh.FindOpenElements(domainnr);\n\n    mesh.Compress();\n    // PopStatus ();\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/delaunay2d.cpp",
    "content": "#include <mystdlib.h>\n#include \"delaunay2d.hpp\"\n\n#include <geom2d/csg2d.hpp>\n\n\nnamespace netgen\n{\n  using namespace std;\n  void DelaunayTrig::CalcCenter (FlatArray<Point<2>, PointIndex> points)\n  {\n    Point<2> p1 = points[pnums[0]];\n    Point<2> p2 = points[pnums[1]];\n    Point<2> p3 = points[pnums[2]];\n\n    Vec<2> v1 = p2-p1;\n    Vec<2> v2 = p3-p1;\n\n    // without normal equation ...\n    Mat<2,2> mat, inv;\n    mat(0,0) = v1(0); mat(0,1) = v1(1);\n    mat(1,0) = v2(0); mat(1,1) = v2(1);\n    CalcInverse (mat, inv);\n    Vec<2> rhs, sol;\n    rhs(0) = 0.5 * v1*v1;\n    rhs(1) = 0.5 * v2*v2;\n    sol = inv * rhs;\n    c = p1 + sol;\n\n    rad2 = Dist2(c, p1);\n    r = sqrt(rad2);\n  }\n\n  int DelaunayMesh::GetNeighbour( int eli, int edge )\n  {\n    auto p0 = trigs[eli][(edge+1)%3];\n    auto p1 = trigs[eli][(edge+2)%3];\n    if(p1<p0)\n      Swap(p0,p1);\n\n    PointIndices<2> hash = {p0,p1};\n\n    auto pos = edge_to_trig.Position(hash);\n    if (pos == -1) return -1;\n    auto i2 = edge_to_trig.GetData(pos);\n    return i2[0] == eli ? i2[1] : i2[0];\n  }\n\n  void DelaunayMesh::SetNeighbour( int eli, int edge )\n  {\n    auto p0 = trigs[eli][(edge+1)%3];\n    auto p1 = trigs[eli][(edge+2)%3];\n    if(p1<p0)\n      Swap(p0,p1);\n\n    PointIndices<2> hash = {p0,p1};\n    auto pos = edge_to_trig.Position(hash);\n    if (pos == -1)\n      edge_to_trig[hash] = {eli, -1};\n    else\n      {\n        auto i2 = edge_to_trig.GetData(pos);\n        if(i2[0]==-1)\n          i2[0] = eli;\n        else\n          {\n            if(i2[1]==-1)\n              i2[1] = eli;\n          }\n        edge_to_trig.SetData (pos, i2);\n      }\n  }\n\n  void DelaunayMesh::UnsetNeighbours( int eli )\n  {\n    for(int edge : Range(3))\n    {\n      auto p0 = trigs[eli][(edge+1)%3];\n      auto p1 = trigs[eli][(edge+2)%3];\n      if(p1<p0)\n        Swap(p0,p1);\n\n      PointIndices<2> hash = {p0,p1};\n      auto pos = edge_to_trig.Position(hash);\n      auto i2 = edge_to_trig.GetData(pos);\n\n      if(i2[0]==eli)\n        i2[0] = i2[1];\n      i2[1] = -1;\n\n      edge_to_trig.SetData (pos, i2);\n    }\n  }\n\n\n  void DelaunayMesh::AppendTrig( PointIndex pi0, PointIndex pi1, PointIndex pi2 )\n  {\n    DelaunayTrig el;\n    el[0] = pi0;\n    el[1] = pi1;\n    el[2] = pi2;\n\n    el.CalcCenter(points);\n\n    trigs.Append(el);\n    int ti = trigs.Size()-1;\n    tree->Insert(el.BoundingBox(), ti);\n\n    for(int i : Range(3))\n      SetNeighbour(ti, i);\n  }\n\n  DelaunayMesh::DelaunayMesh( Array<Point<2>, PointIndex> & points_, Box<2> box  )\n    : points(points_)\n  {\n    Vec<2> vdiag = box.PMax()-box.PMin();\n\n    double w = vdiag(0);\n    double h = vdiag(1);\n\n    Point<2> p0 = box.PMin() + Vec<2> ( -3*h, -h);\n    Point<2> p1 = box.PMin() + Vec<2> (w+3*h, -h);\n    Point<2> p2 = box.Center() + Vec<2> (0, 1.5*h+0.5*w);\n\n    box.Add( p0 );\n    box.Add( p1 );\n    box.Add( p2 );\n\n    tree = make_unique<DelaunayTree<2>>(box);\n\n    auto pi0 = points.Append (p0);\n    auto pi1 = points.Append (p1);\n    auto pi2 = points.Append (p2);\n    AppendTrig(pi0, pi1, pi2);\n  }\n\n  void DelaunayMesh::CalcIntersecting( PointIndex pi_new )\n  {\n    static Timer t(\"CalcIntersecting\"); RegionTimer reg(t);\n\n    Point<2> newp = points[pi_new];\n    intersecting.SetSize(0);\n    edges.SetSize(0);\n\n    int definitive_overlapping_trig = -1;\n\n    double minquot{1e20};\n    tree->GetFirstIntersecting (newp, newp, [&] (const auto i_trig)\n        {\n           const auto trig = trigs[i_trig];\n           double rad2 = trig.Radius2();\n           double d2 = Dist2 (trig.Center(), newp);\n           if (d2 >= rad2) return false;\n\n           if (d2 < 0.999 * rad2)\n             {\n               definitive_overlapping_trig = i_trig;\n               return true;\n             }\n\n          if (definitive_overlapping_trig == -1 || d2 < 0.99*minquot*rad2)\n            {\n              minquot = d2/rad2;\n              definitive_overlapping_trig = i_trig;\n            }\n          return false;\n        });\n\n    if(definitive_overlapping_trig==-1)\n    {\n      static Timer t(\"slow check\"); RegionTimer reg(t);\n      PrintMessage (5, \"Warning in delaunay tree - didn't find overlapping circle, check all trigs again\");\n      for(auto i_trig : trigs.Range())\n      {\n        const auto trig = trigs[i_trig];\n\n        // if(trig[0]==-1)\n        if(!trig[0].IsValid())\n          continue;\n\n        double rad2 = trig.Radius2();\n        double d2 = Dist2 (trig.Center(), newp);\n\n        // if (d2 < 0.999 * rad2)\n        if (d2 < (1-1e-10)*rad2)\n        {\n          definitive_overlapping_trig = i_trig;\n          break;\n        }\n      }\n    }\n\n    if(definitive_overlapping_trig==-1)\n    {\n      // GetMesh(pi_new)->Save(\"error.vol.gz\");\n      throw Exception(\"point not in any circle \"+ ToString(pi_new));\n    }\n\n    Array<int> trigs_to_visit;\n    trigs_to_visit.Append(definitive_overlapping_trig);\n    intersecting.Append(definitive_overlapping_trig);\n    trigs[definitive_overlapping_trig].visited_pi = pi_new;\n\n    while(trigs_to_visit.Size())\n    {\n      int ti = trigs_to_visit.Last();\n      trigs_to_visit.DeleteLast();\n\n      auto & trig = trigs[ti];\n      trig.visited_pi = pi_new;\n\n      for(auto ei : Range(3))\n      {\n        auto nb = GetNeighbour(ti, ei);\n        if(nb==-1)\n          continue;\n\n        const auto & trig_nb = trigs[nb];\n        if (trig_nb.visited_pi == pi_new)\n          continue;\n\n        trig_nb.visited_pi = pi_new;\n\n        bool is_intersecting = Dist2(newp, trig_nb.Center()) < trig_nb.Radius2()*(1+1e-12);\n\n        if(!is_intersecting)\n        {\n          const Point<2> p0 = points[PointIndex (trig[(ei+1)%3])];\n          const Point<2> p1 = points[PointIndex (trig[(ei+2)%3])];\n          const Point<2> p2 = points[PointIndex (trig[ei])];\n          auto v = p1-p0;\n\n          Vec<2> n = {-v[1], v[0]};\n          n /= n.Length();\n\n          double dist = n * (newp-p1);\n          double scal = n * (p2 - p1);\n          if (scal > 0) dist *= -1;\n\n          if (dist > -1e-10)\n            is_intersecting = true;\n        }\n\n        if(is_intersecting)\n        {\n          trigs_to_visit.Append(nb);\n          intersecting.Append(nb);\n        }\n      }\n    }\n\n    // find outer edges\n    for (auto j : intersecting)\n    {\n      const DelaunayTrig & trig = trigs[j];\n      for (int k = 0; k < 3; k++)\n      {\n        PointIndex p1 = trig[k];\n        PointIndex p2 = trig[(k+1)%3];\n        PointIndices<2> edge{p1,p2};\n        edge.Sort();\n        bool found = false;\n        for (int l = 0; l < edges.Size(); l++)\n          if (edges[l] == edge)\n          {\n            edges.RemoveElement(l);\n            found = true;\n            break;\n          }\n        if (!found)\n          edges.Append (edge);\n      }\n    }\n  }\n\n  void DelaunayMesh::CalcWeights( PointIndex pi_new, std::map<PointIndex, double> & weights )\n  {\n      double eps = tree->GetTolerance();\n      weights.clear();\n      double sum = 0.0;\n      auto p = points[pi_new];\n      auto pi_last = *points.Range().end()-3;\n      for(auto edge : edges)\n      {\n          auto v0 = points[edge[0]] - p;\n          auto v1 = points[edge[1]] - p;\n          v0.Normalize();\n          v1.Normalize();\n          double angle = acos(v0*v1);\n          for(PointIndex pi : {edge[0], edge[1]})\n          {\n            if(pi>=pi_last)\n              continue;\n            double weight = angle/(eps+Dist(p, points[pi]));\n            sum += weight;\n            weights[pi] += weight;\n          }\n      }\n      double isum = 1.0/sum;\n      for(auto & [pi, weight] : weights)\n          weight *= isum;\n  }\n\n  void DelaunayMesh::AddPoint( PointIndex pi_new)\n  {\n      static Timer t(\"AddPoint\"); RegionTimer reg(t);\n\n      CalcIntersecting(pi_new);\n\n      for (int j : intersecting)\n        {\n          UnsetNeighbours(j);\n          trigs[j][0] = PointIndex::INVALID;\n          trigs[j][1] = PointIndex::INVALID;\n          trigs[j][2] = PointIndex::INVALID;\n        }\n\n      for (auto edge : edges)\n          AppendTrig( edge[0], edge[1], pi_new );\n\n      for (int j : intersecting)\n          tree->DeleteElement (j);\n  }\n\n  unique_ptr<Mesh> DelaunayMesh::GetMesh(PointIndex pi_new)\n  {\n      auto mesh = make_unique<Mesh>();\n      Mesh & m = *mesh;\n      m.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));\n      for(auto pi : points.Range())\n          m.AddPoint(P3(points[pi]));\n\n      for (DelaunayTrig & trig : trigs)\n      {\n        // if (trig[0] < 0) continue;\n        if (!trig[0].IsValid()) continue;\n\n        Vec<3> n = Cross (P3(points[trig[1]])-P3(points[trig[0]]),\n            P3(points[trig[2]])-P3(points[trig[0]]));\n        if (n(2) < 0) Swap (trig[1], trig[2]);\n\n        Element2d el(trig[0], trig[1], trig[2]);\n        el.SetIndex (1);\n        m.AddSurfaceElement (el);\n      }\n      m.Compress();\n      m.AddPoint(P3(points[pi_new]));\n      return mesh;\n  }\n\n  ostream & operator<< (ostream & ost, DelaunayTrig trig)\n  {\n    ost << trig[0] << \"-\" << trig[1] << \"-\" << trig[2] << endl;\n    return ost;\n  }\n\n  \n  void Meshing2 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp)\n  {\n    static Timer timer(\"Meshing2::BlockFill\");\n    static Timer timer1(\"Meshing2::BlockFill 1\");\n    static Timer timer2(\"Meshing2::BlockFill 2\");\n    static Timer timer3(\"Meshing2::BlockFill 3\");\n    static Timer timer4(\"Meshing2::BlockFill 4\");\n    RegionTimer reg (timer);\n\n    timer1.Start();\n\n    double filldist = mp.filldist;\n    \n    PrintMessage (6, \"blockfill local h\");\n\n    NgArray<Point<3> > npoints;\n    \n    // adfront -> CreateTrees();\n\n    Box<3> bbox ( Box<3>::EMPTY_BOX );\n    double maxh = 0;\n    \n    for (int i = 0; i < adfront.GetNFL(); i++)\n      {\n\tconst FrontLine & line = adfront.GetLine (i);\n\n\tconst Point<3> & p1 = adfront.GetPoint(line.L().I1());\n\tconst Point<3> & p2 = adfront.GetPoint(line.L().I2());\n\t\n        maxh = max (maxh, Dist (p1, p2));\n\t\n\tbbox.Add (p1);\n\tbbox.Add (p2);\n      }\n\n    \n    // Point<3> mpc = bbox.Center();\n    bbox.Increase (bbox.Diam()/2);\n    Box<3> meshbox = bbox;\n\n    timer1.Stop();\n    timer2.Start();\n\n\n    LocalH loch2 (bbox, 1, 2);\n    \n    if (mp.maxh < maxh) maxh = mp.maxh;\n    \n    bool changed;\n    do \n      {\n        static Timer tcf(\"clear flags\");\n        tcf.Start();\n        // mesh.LocalHFunction().ClearFlags();\n        mesh.LocalHFunction().ClearRootFlags();\n\ttcf.Stop();\n        \n        static Timer tcut(\"tcut\");\n        tcut.Start();\n\tfor (int i = 0; i < adfront.GetNFL(); i++)\n\t  {\n\t    const FrontLine & line = adfront.GetLine(i);\n\t    \n\t    Box<3> bbox (adfront.GetPoint (line.L().I1()));\n\t    bbox.Add (adfront.GetPoint (line.L().I2()));\n\n\t    \n\t    double filld = filldist * bbox.Diam();\n\t    bbox.Increase (filld);\n\t    \n\t    mesh.LocalHFunction().CutBoundary (bbox); \n\t  }\n\ttcut.Stop();\n\n\tmesh.LocalHFunction().FindInnerBoxes (adfront, NULL);\n\t\n\tnpoints.SetSize(0);\n\tmesh.LocalHFunction().GetInnerPoints (npoints);\n\n\tchanged = false;\n\tfor (int i = 0; i < npoints.Size(); i++)\n\t  {\n\t    if (mesh.LocalHFunction().GetH(npoints[i]) > 1.2 * maxh)\n\t      {\n\t\tmesh.LocalHFunction().SetH (npoints[i], maxh);\n\t\tchanged = true;\n\t      }\n\t  }\n      }\n    while (changed);\n\n    timer2.Stop();\n    timer3.Start();\n\n\n    if (debugparam.slowchecks)\n      {\n        (*testout) << \"Blockfill with points: \" << endl;\n        *testout << \"loch = \" << mesh.LocalHFunction() << endl;\n\n        *testout << \"npoints = \" << endl << npoints << endl;\n      }\n\n\n    int prims[] = { 211, 223, 227, 229, 233, 239, 241, 251, 257, 263 }; \n    int prim;\n  \n    {\n      int i = 0;\n      if (npoints.Size())\n        while (npoints.Size() % prims[i] == 0) i++;\n      prim = prims[i];\n    }\n\n    for (int i = 0; i < npoints.Size(); i++)\n      {\n        size_t hi = (size_t(prim) * size_t(i)) % npoints.Size();\n        \n\tif (meshbox.IsIn (npoints[hi]))\n\t  {\n\t    PointIndex gpnum = mesh.AddPoint (npoints[hi]);\n\t    adfront.AddPoint (npoints[hi], gpnum);\n\t    \n\t    if (debugparam.slowchecks)\n\t      {\n\t\t(*testout) << npoints[hi] << endl;\n\n\t\tPoint<2> p2d (npoints[hi](0), npoints[hi](1));\n\t\tif (!adfront.Inside(p2d))\n\t\t  {\n\t\t    cout << \"add outside point\" << endl;\n\t\t    (*testout) << \"outside\" << endl;\n\t\t  }\n\t      }\n\t    \n\t  }\n      }\n    \n    timer3.Stop();\n    timer4.Start();\n  \n\n  // find outer points\n  \n    loch2.ClearFlags();\n\n    for (int i = 0; i < adfront.GetNFL(); i++)\n      {\n\tconst FrontLine & line = adfront.GetLine(i);\n\t\n\tBox<3> bbox (adfront.GetPoint (line.L().I1()));\n\tbbox.Add (adfront.GetPoint (line.L().I2()));\n\t\n\tloch2.SetH (bbox.Center(), bbox.Diam());\n      }\n\n\n    for (int i = 0; i < adfront.GetNFL(); i++)\n      {\n\tconst FrontLine & line = adfront.GetLine(i);\n\t\n\tBox<3> bbox (adfront.GetPoint (line.L().I1()));\n\tbbox.Add (adfront.GetPoint (line.L().I2()));\n\n\tbbox.Increase (filldist * bbox.Diam());\n\tloch2.CutBoundary (bbox);\n      }\n    \n    loch2.FindInnerBoxes (adfront, NULL);\n\n      // outer points : smooth mesh-grading\n    npoints.SetSize(0);\n    loch2.GetOuterPoints (npoints);\n\n    /*\n    for (int i = 1; i <= npoints.Size(); i++)\n      {\n\tif (meshbox.IsIn (npoints.Get(i)))\n\t  {\n\t    PointIndex gpnum = mesh.AddPoint (npoints.Get(i));\n\t    adfront.AddPoint (npoints.Get(i), gpnum);\n\t  }\n      }  \n    */\n\n    for (const Point<3> p : npoints)\n      if (meshbox.IsIn(p))\n        {\n          PointIndex gpnum = mesh.AddPoint (p);\n          adfront.AddPoint (p, gpnum);\n        }\n    timer4.Stop();\n  }\n\n\n\n  \n  void Meshing2 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp)\n  {\n    static Timer timer(\"Meshing2::Delaunay\");\n    static Timer t1(\"Meshing2::Delaunay1\");\n    static Timer t2(\"Meshing2::Delaunay2\");\n    static Timer t3(\"Meshing2::Delaunay3\");\n    static Timer timer_addpoints(\"add points\");\n    RegionTimer reg (timer);\n\n    PrintMessage (4, \"2D Delaunay meshing\");\n\n    auto first_point_blockfill = mesh.Points().Range().Next();\n\n    BlockFillLocalH (mesh, mp);\n\n    auto last_point_blockfill = mesh.Points().Range().Next();\n\n    t1.Start();\n    // Bounding box for starting trig in delaunay\n    Box<2> bbox (Box<2>::EMPTY_BOX);\n\n    for (int i = 0; i < adfront.GetNFL(); i++)\n      {\n\tconst FrontLine & line = adfront.GetLine(i);\n        bbox.Add (P2(Point<3> (adfront.GetPoint (line.L()[0]))));\n        bbox.Add (P2(Point<3> (adfront.GetPoint (line.L()[1]))));\n      }\n\n    for (PointIndex pi : Range(first_point_blockfill, last_point_blockfill))\n      bbox.Add(P2(mesh[pi]));\n\n    for (int i = 0; i < mesh.LockedPoints().Size(); i++)\n      bbox.Add (P2(mesh.Point (mesh.LockedPoints()[i])));\n    t1.Stop();\n\n    t2.Start();\n    Array<PointIndex> old_points;\n    TBitArray<PointIndex> add_point(mesh.Points().Size()+1);\n    Array<PointIndex> addpoints;\n    add_point.Clear();\n    /*\n    for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n    {\n      const auto & s = mesh[si];\n      if ( s.domin==domainnr || s.domout==domainnr )\n      {\n        add_point.SetBit(s[0]);\n        add_point.SetBit(s[1]);\n      }\n    }\n    */\n    /*\n    for (int i = 0; i < adfront.GetNFL(); i++)\n      {\n\tconst FrontLine & line = adfront.GetLine(i);\n        for (int j = 0; j < 2; j++)\n          add_point.SetBit (adfront.GetGlobalIndex (line.L()[j]))adfront.GetGlobalIndex (line.L()[j]));\n      }\n    */\n    for (const auto & line : adfront.GetLines())\n      for (int j = 0; j < 2; j++)\n        {\n          PointIndex pnum = adfront.GetGlobalIndex (line.L()[j]);\n          if (!add_point.Test(pnum))\n            addpoints.Append(pnum);\n          add_point.SetBit (pnum);\n        }\n      \n    \n    t2.Stop();\n\n    t3.Start();\n    Mesh tempmesh;\n    tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));\n    tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0));\n    tempmesh.AddFaceDescriptor (FaceDescriptor (3, 1, 0, 0));\n\n    Array<PointIndex, PointIndex> compress;\n    Array<PointIndex, PointIndex> icompress(mesh.Points().Size());\n\n    Array<Point<2>, PointIndex> temp_points;\n    for (PointIndex pi : addpoints)\n      {\n        icompress[pi] = tempmesh.AddPoint(mesh[pi]);\n        compress.Append(pi);\n        temp_points.Append(P2(mesh[pi]));\n      }\n\n    for (PointIndex pi : Range(first_point_blockfill, last_point_blockfill))\n      {\n        icompress[pi] = tempmesh.AddPoint(mesh[pi]);\n        compress.Append(pi);\n        temp_points.Append(P2(mesh[pi]));\n      }\n    t3.Stop();\n    // DelaunayMesh adds surrounding trig (don't add the last 3 points to delaunay AGAIN!\n    auto points_range = temp_points.Range();\n\n    DelaunayMesh dmesh(temp_points, bbox);\n\n    timer_addpoints.Start();\n\n//     // reorder points\n//     NgArray<PointIndex, PointIndex::BASE, PointIndex> mixed(old_points.Size());\n//     int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };\n//     int prim;\n//   \n//     {\n//       int i = 0;\n//       while (old_points.Size() % prims[i] == 0) i++;\n//       prim = prims[i];\n//     }\n// \n//     for (PointIndex pi : old_points)\n//       mixed[pi] = PointIndex ( (prim * pi) % old_points.Size() + PointIndex::BASE );\n    \n    for (auto pi : points_range)\n      dmesh.AddPoint(pi);\n\n    auto first_new_point = points_range.Next();\n    tempmesh.AddPoint(P3(temp_points[first_new_point]));\n    tempmesh.AddPoint(P3(temp_points[first_new_point+1]));\n    tempmesh.AddPoint(P3(temp_points[first_new_point+2]));\n\n    timer_addpoints.Stop();\n\n    static Timer taddseg(\"addseg\");\n    taddseg.Start();\n\n    /*\n    for (auto seg : mesh.LineSegments())\n    {\n      if ( seg.domin == domainnr || seg.domout == domainnr )\n      {\n        if(seg.domin==domainnr)\n          seg.domout = 0;\n        if(seg.domout==domainnr)\n          seg.domin = 0;\n        seg[0] = icompress[seg[0]];\n        seg[1] = icompress[seg[1]];\n        tempmesh.AddSegment(seg);\n      }\n    }\n    */\n    for (const auto & line : adfront.GetLines())\n      {\n        Segment seg;\n        for (int j = 0; j < 2; j++)\n          seg[j] = icompress [adfront.GetGlobalIndex (line.L()[j])];\n        seg.domin = domainnr;\n        seg.domout = 0;\n        tempmesh.AddSegment(seg);\n      }\n           \n    taddseg.Stop();\n    \n    for (auto & trig : dmesh.GetElements())\n    {\n      // if (trig[0] < 0) continue;\n      if (!trig[0].IsValid()) continue;\n\n      Element2d el(trig[0], trig[1], trig[2]);\n      el.SetIndex (1);\n      tempmesh.AddSurfaceElement (el);\n    }\n\n    bool conforming = false;\n    while(!conforming)\n    {\n      conforming = true;\n      TBitArray<PointIndex> marked_points(tempmesh.Points().Size()+1);\n      marked_points = false;\n      // Check for trigs cutting a boundary edge (non-conforming mesh)\n      auto point_to_trigs = tempmesh.CreatePoint2SurfaceElementTable( 0 );\n      for (auto & seg : tempmesh.LineSegments())\n      {\n        int count_adjacent = 0;;\n        PointIndex pi0 = seg[0];\n        PointIndex pi1 = seg[1];\n        if(marked_points.Test(pi0)) continue;\n        if(marked_points.Test(pi1)) continue;\n\n        for(auto sei : point_to_trigs[pi0])\n          for( auto i : Range(3))\n            if(tempmesh[sei][i] == pi1)\n              count_adjacent++;\n\n        if(count_adjacent==2)\n          continue;\n\n        PointIndex pi2;\n        PointIndex pi3;\n        ArrayMem<SurfaceElementIndex, 2> cutting_trigs;\n        for(auto sei : point_to_trigs[pi0])\n        {\n          auto & el = tempmesh[sei];\n          pi2 = el[0] == pi0 ? el[1] : el[0];\n          pi3 = el[2] == pi0 ? el[1] : el[2];\n          double alpha, beta;\n          auto itype = intersect( P2(tempmesh[pi0]), P2(tempmesh[pi1]), P2(tempmesh[pi2]), P2(tempmesh[pi3]), alpha, beta );\n          if(itype == X_INTERSECTION)\n          {\n            cutting_trigs.Append(sei);\n            break;\n          }\n        }\n        if(cutting_trigs.Size()==0)\n          continue;\n        for(auto sei : point_to_trigs[pi2])\n        {\n          if(sei==cutting_trigs[0])\n            continue;\n          for(auto i : IntRange(3))\n            if(tempmesh[sei][i]==pi3)\n              cutting_trigs.Append(sei);\n        }\n\n        // Found two trigs cutting a boundary edge -> perform swap\n        if(cutting_trigs.Size()==2)\n        {\n          conforming = false;\n          if(marked_points.Test(pi2)) continue;\n          if(marked_points.Test(pi3)) continue;\n\n          auto & el0 = tempmesh[cutting_trigs[0]];\n          auto & el1 = tempmesh[cutting_trigs[1]];\n\n          pi1 = el1[0]-pi2+el1[1]-pi3+el1[2];\n\n          if(marked_points.Test(pi1)) continue;\n\n          marked_points.SetBit(pi0);\n          marked_points.SetBit(pi1);\n          marked_points.SetBit(pi2);\n          marked_points.SetBit(pi3);\n\n          el0[0] = pi2;\n          el0[1] = pi1;\n          el0[2] = pi0;\n\n          el1[0] = pi3;\n          el1[1] = pi0;\n          el1[2] = pi1;\n        }\n      }\n    }\n\n    auto point_to_trigs = tempmesh.CreatePoint2SurfaceElementTable( 0 );\n\n    // Mark edges and trigs as inside or outside, starting with boundary edges\n    enum POSITION { UNKNOWN, BOUNDARY, INSIDE, OUTSIDE };\n    Array<POSITION, SurfaceElementIndex> trig_pos(tempmesh.SurfaceElements().Size());\n    ngcore::ClosedHashTable<PointIndices<2>, POSITION> edge_pos(3*tempmesh.SurfaceElements().Size());\n    trig_pos = UNKNOWN;\n\n    for (auto & seg : tempmesh.LineSegments())\n    {\n      ArrayMem<SurfaceElementIndex, 2> els;\n      PointIndices<2> edge{seg[0], seg[1]};\n      edge.Sort();\n      edge_pos[edge] = BOUNDARY;\n      \n      for(auto sei : point_to_trigs[seg[0]])\n        for( auto i : Range(3))\n          if(tempmesh[sei][i] == seg[1])\n            els.Append(sei);\n\n      for(auto sei : els)\n      {\n        auto & el = tempmesh[sei];\n        PointIndex pi2 = el[0]-seg[0]+el[1]-seg[1]+el[2];\n        bool is_left = ::netgen::Area(P2(tempmesh[seg[0]]), P2(tempmesh[seg[1]]), P2(tempmesh[pi2]))>0.0;\n        POSITION pos;\n\n        if(is_left == (seg.domin==domainnr))\n          pos = INSIDE;\n        else\n          pos = OUTSIDE;\n\n        PointIndices<2> e1{seg[0], pi2};\n        PointIndices<2> e2{seg[1], pi2};\n        e1.Sort();\n        e2.Sort();\n        if(!edge_pos.Used(e1))\n          edge_pos[e1] = pos;\n        if(!edge_pos.Used(e2))\n          edge_pos[e2] = pos;\n        trig_pos[sei] = pos;\n      }\n    }\n\n    // Advance from boundary edges/trigs to all others\n    bool have_unknown_trigs = true;\n    while(have_unknown_trigs)\n    {\n      have_unknown_trigs = false;\n\n      for (auto sei : Range(tempmesh.SurfaceElements()))\n      {\n        auto & el = tempmesh[sei];\n\n        if(trig_pos[sei] == UNKNOWN)\n        {\n          have_unknown_trigs = true;\n\n          // any edge of unknown trig already marked?\n          for(auto i : IntRange(3))\n          {\n            PointIndices<2> edge{el[(i+1)%3], el[(i+2)%3]};\n            edge.Sort();\n            if(edge_pos.Used(edge) && edge_pos[edge]!=BOUNDARY)\n            {\n              trig_pos[sei] = edge_pos[edge];\n              break;\n            }\n          }\n        }\n\n        // if we could mark the trig -> also mark all edges\n        if(trig_pos[sei] != UNKNOWN)\n          for(auto i : IntRange(3))\n          {\n            PointIndices<2> edge{el[(i+1)%3], el[(i+2)%3]};\n            edge.Sort();\n            if(!edge_pos.Used(edge) || edge_pos[edge]==BOUNDARY)\n              edge_pos[edge] = trig_pos[sei];\n          }\n      }\n    }\n\n    // add inside trigs to actual mesh\n    for (auto sei : Range(tempmesh.SurfaceElements()))\n    {\n      if(trig_pos[sei] == INSIDE)\n      {\n        auto el = tempmesh[sei];\n\n        Vec<3> n = Cross (tempmesh[el[1]]-tempmesh[el[0]],\n            tempmesh[el[2]]-tempmesh[el[0]]);\n        if (n(2) < 0) Swap (el[1], el[2]);\n\n        el[0] = compress[el[0]];\n        el[1] = compress[el[1]];\n        el[2] = compress[el[2]];\n        el.SetIndex(domainnr);\n        mesh.AddSurfaceElement(el);\n      }\n    }\n\n    // mesh.Compress();  // don't compress whole mesh after every sub-domain\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/delaunay2d.hpp",
    "content": "#include \"meshing.hpp\"\n\nnamespace netgen\n{\n\n  static inline Point<2> P2( Point<3> p )\n  {\n    return {p[0], p[1]};\n  }\n\n  static inline Point<3> P3( Point<2> p )\n  {\n    return {p[0], p[1], 0};\n  }\n\n  class DelaunayTrig\n  {\n    PointIndex pnums[3];\n    Point<2> c;\n\n  public:\n    double r;\n    double rad2;\n    DelaunayTrig () = default;\n    DelaunayTrig (PointIndex p1, PointIndex p2, PointIndex p3)\n    {\n      pnums[0] = p1;\n      pnums[1] = p2;\n      pnums[2] = p3;\n    }\n\n    PointIndex & operator[] (int j) { return pnums[j]; }\n    const PointIndex & operator[] (int j) const { return pnums[j]; }\n\n    void CalcCenter (FlatArray<Point<2>, PointIndex> points);\n\n    Point<2> Center() const { return c; }\n    double Radius2() const { return rad2; }\n    Box<2> BoundingBox() const { return Box<2> (c-Vec<2>(r,r), c+Vec<2>(r,r)); }\n\n    mutable PointIndex visited_pi = PointIndex::INVALID; //  -1;\n  };\n\n  class DelaunayMesh\n  {\n    ngcore::ClosedHashTable<PointIndices<2>, IVec<2>> edge_to_trig;\n    Array<DelaunayTrig> trigs;\n    unique_ptr<DelaunayTree<2>> tree;\n    Array<Point<2>, PointIndex> & points;\n\n    Array<int> closeels;\n    Array<int> intersecting;\n    Array<PointIndices<2>> edges;\n\n    int GetNeighbour( int eli, int edge );\n\n    void SetNeighbour( int eli, int edge );\n\n    void UnsetNeighbours( int eli );\n\n    void AppendTrig( PointIndex pi0, PointIndex pi1, PointIndex pi2 );\n\n    public:\n    DelaunayMesh( Array<Point<2>, PointIndex> & points_, Box<2> box  );\n\n    void CalcIntersecting( PointIndex pi_new );\n    void CalcWeights( PointIndex pi_new, std::map<PointIndex, double> & weights );\n    void AddPoint( PointIndex pi_new );\n    Array<DelaunayTrig> & GetElements() { return trigs; }\n    unique_ptr<Mesh> GetMesh(PointIndex pi_new); // for debugging purposes\n  };\n\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/fieldlines.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n\n#include \"fieldlines.hpp\"\n\nnamespace netgen\n{\n  inline int GetVolElement(const Mesh& mesh, const Point<3>& p,\n                           double* lami)\n  {\n    if(mesh.GetDimension() == 3)\n      {\n        auto ei = mesh.GetElementOfPoint(p, lami, true);\n        if(!ei.IsValid())\n          return -1;\n        return ei;\n      }\n    else\n      {\n        auto ei = mesh.GetSurfaceElementOfPoint(p, lami, true);\n        if(!ei.IsValid())\n          return -1;\n        return ei;\n      }\n  }\n\n  RKStepper :: ~RKStepper() \n  {\n    delete a;\n  }\n    \n  RKStepper :: RKStepper(int type) : a(NULL), tolerance(1e100)\n  {\n    notrestarted = 0;\n\n    if (type == 0) // explicit Euler\n      {\n\tc.SetSize(1); c[0] = 0;\n\tb.SetSize(1); b[0] = 1;\n\tsteps = order = 1;\n      }\n    else if (type == 1) // Euler-Cauchy\n      {\n\tc.SetSize(2); c[0] = 0; c[1] = 0.5;\n\tb.SetSize(2); b[0] = 0; b[1] = 1;\n\tNgArray<int> size(2);\n\tsize[0] = 0; size[1] = 1;\n\ta = new TABLE<double>(size);\n\ta->Set(2,1,0.5);  // Set, Get: 1-based!\n\tsteps = order = 2;\n      }\n    else if (type == 2) // Simpson\n      {\n\tc.SetSize(3); c[0] = 0; c[1] = 1; c[2] = 0.5;\n\tb.SetSize(3); b[0] = b[1] = 1./6.; b[2] = 2./3.;\n\tNgArray<int> size(3);\n\tsize[0] = 0; size[1] = 1; size[2] = 2;\n\ta = new TABLE<double>(size);\n\ta->Set(2,1,1);\n\ta->Set(3,1,0.25); a->Set(3,2,0.25); \n\tsteps = order = 3;\n      }\n    else if (type == 3) // classical Runge-Kutta\n      {\n\tc.SetSize(4); c[0] = 0; c[1] = c[2] = 0.5; c[3] = 1;\n\tb.SetSize(4); b[0] = b[3] = 1./6.; b[1] = b[2] = 1./3.;\n\tNgArray<int> size(4);\n\tsize[0] = 0; size[1] = 1; size[2] = 2; size[3] = 3;\n\ta = new TABLE<double>(size);\n\ta->Set(2,1,0.5);\n\ta->Set(3,1,0); a->Set(3,2,0.5); \n\ta->Set(4,1,0); a->Set(4,2,0); a->Set(4,3,1); \n\tsteps = order = 4;\n      }\n    \n    K.SetSize(steps);\n  }\n\n  void RKStepper :: StartNextValCalc(const Point<3> & astartval, const double astartt, const double ah, const bool aadaptive)\n  {\n    //cout << \"Starting RK-Step with h=\" << ah << endl;\n\n    stepcount = 0;\n    h = ah;\n    startt = astartt;\n    startval = astartval;\n    adaptive = aadaptive;\n    adrun = 0;\n  }\n\n  bool RKStepper :: GetNextData(Point<3> & val, double & t, double & ah)\n  {\n    bool finished = false;\n    \n    if(stepcount <= steps && stepcount>0)\n      {\n\tt = startt + c[stepcount-1]*h;\n\tval = startval;\n\tfor(int i=0; i<stepcount-1; i++)\n\t  val += h * a->Get(stepcount,i+1) * K[i];\n      }\n    \n    \n    if(stepcount == steps)\n      {\n\tval = startval;\n\tfor(int i=0; i<steps; i++)\n\t  val += h * b[i] * K[i];\n\t\n\tif(adaptive)\n\t  {\n\t    if(adrun == 0)\n\t      {\n\t\tstepcount = 0;\n\t\th *= 0.5;\n\t\tadrun = 1;\n\t\tvalh = val;\n\t      }\n\t    else if (adrun == 1)\n\t      {\n\t\tstepcount = 0;\n\t\tstartval_bak = startval;\n\t\tstartval = val;\n\t\tstartt_bak = startt;\n\t\tstartt += h;//0.5*h;\n\t\tadrun = 2;\n\t      }\n\t    else if (adrun == 2)\n\t      {\n\t\tPoint<3> valh2 = val;\n\t\tval = valh2 + 1./(pow(2.,order)-1.) * (valh2 - valh);\n\t\tauto errvec = val - valh;\n\t\t\n\t\tdouble err = errvec.Length();\n\t\t\n\t\tdouble fac = 0.7 * pow(tolerance/err,1./(order+1.));\n\t\tif(fac > 1.3) fac = 1.3;\n\t\t\n\t\tif(fac < 1 || notrestarted >= 2)\n\t\t  ah = 2.*h * fac;\n\t\t\n\t\tif(err < tolerance) \n\t\t  {\n\t\t    finished = true;\n\t\t    notrestarted++;\n\t\t    //(*testout) << \"finished RK-Step, new h=\" << ah << \" tolerance \" << tolerance << \" err \" << err << endl;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    //ah *= 0.9;\n\t\t    notrestarted = 0;\n\t\t    //(*testout) << \"restarting h \" << 2.*h << \" ah \" << ah << \" tolerance \" << tolerance << \" err \" << err << endl;\n\t\t    StartNextValCalc(startval_bak,startt_bak, ah, adaptive);\n\t\t  }\n\t      }\n\t  }\n\telse \n\t  {\n\t    t = startt + h;\n\t    finished = true;\n\t  }\n\t\n      }\n    \n    if(stepcount == 0)\n      {\n\tt = startt + c[stepcount]*h;\n\tval = startval;\n\tfor(int i=0; i<stepcount; i++)\n\t  val += h * a->Get(stepcount,i) * K[i];\n      }\n    \n    return finished;\n  }\n\n\n  bool RKStepper :: FeedNextF(const Vec<3> & f)\n  {\n    K[stepcount] = f;\n    stepcount++;\n    return true;\n  }\n  \n\n\n  void FieldLineCalc :: GenerateFieldLines(Array<Point<3>> & potential_startpoints, const int numlines)\n  {\n\n    \n    Array<Point<3>> line_points;\n    Array<double> line_values;\n    Array<bool> drawelems;\n    Array<int> dirstart;\n    pstart.SetSize0();\n    pend.SetSize0();\n    values.SetSize0();\n\n    double crit = 1.0;\n\n    if(randomized)\n      {\n\tdouble sum = 0;\n\tdouble lami[3];\n        Vec<3> v;\n\t\n\tfor(int i=0; i<potential_startpoints.Size(); i++)\n\t  {\n\t    int elnr = GetVolElement(mesh, potential_startpoints[i], lami);\n            if (elnr == -1)\n              continue;\n\n\t    mesh.SetPointSearchStartElement(elnr);\n\t    \n            func(elnr, lami, v);\n            sum += v.Length();\n\t  }\n\n\tcrit = sum/double(numlines);\n      }\n\n\n    int calculated = 0;\n\n    for(int i=0; i<potential_startpoints.Size(); i++)\n      {\n\tif(randomized)\n\t  SetCriticalValue((double(rand())/RAND_MAX)*crit);\n\n\tif(calculated >= numlines) break;\n\n\tCalc(potential_startpoints[i],line_points,line_values,drawelems,dirstart);\n\n\tbool usable = false;\n\n\tfor(int j=1; j<dirstart.Size(); j++)\n\t  for(int k=dirstart[j-1]; k<dirstart[j]-1; k++)\n\t    {\n\t      if(!drawelems[k] || !drawelems[k+1]) continue;\n\t     \n\t      usable = true;\n              pstart.Append(line_points[k]);\n              pend.Append(line_points[k+1]);\n              values.Append( 0.5*(line_values[k]+line_values[k+1]) );\n\t    }\n\n\tif(usable) calculated++;\n      }\n    \n  }\n\n\n\n  FieldLineCalc :: FieldLineCalc(const Mesh & amesh, const VectorFunction & afunc,\n\t\t\t\t const double rel_length, const int amaxpoints, \n\t\t\t\t const double rel_thickness, const double rel_tolerance, const int rk_type, const int adirection) :\n    mesh(amesh), func(afunc), stepper(rk_type)\n  {\n    mesh.GetBox (pmin, pmax);\n    rad = 0.5 * Dist (pmin, pmax);\n    \n\n    maxlength = (rel_length > 0) ? rel_length : 0.5;\n    maxlength *= 2.*rad;\n\n    thickness = (rel_thickness > 0) ? rel_thickness : 0.0015;\n    thickness *= 2.*rad;\n    \n    double auxtolerance = (rel_tolerance > 0) ? rel_tolerance : 1.5e-3;\n    auxtolerance *= 2.*rad;\n\n    stepper.SetTolerance(auxtolerance);\n    \n    direction = adirection;\n    \n    \n    maxpoints = amaxpoints;\n\n    if(direction == 0)\n      {\n\tmaxlength *= 0.5;\n\tmaxpoints /= 2;\n      }\n    \n\n    critical_value = -1;\n\n    randomized = false;\n    \n  }\n  \n\n  FieldLineCalc :: ~FieldLineCalc() {;}\n\n  \n  void FieldLineCalc :: Calc(const Point<3> & startpoint, Array<Point<3>> & points, Array<double> & vals, Array<bool> & drawelems, Array<int> & dirstart)\n  {\n    Vec<3> v = 0.0;\n    double startlami[3] = {0.0, 0.0, 0.0};\n    \n    points.SetSize(0);\n    vals.SetSize(0);\n    drawelems.SetSize(0);\n\n    dirstart.SetSize(0);\n    dirstart.Append(0);\n\n    int startelnr = GetVolElement(mesh, startpoint,startlami);\n    (*testout) << \"p = \" << startpoint << \"; elnr = \" << startelnr << endl;\n    if (startelnr == -1)\n      return;\n      \n    mesh.SetPointSearchStartElement(startelnr);\n\n    Vec<3> startv;\n    bool startdraw = func(startelnr, startlami, startv);\n\n    double startval = startv.Length();\n\n    if(critical_value > 0 && fabs(startval) < critical_value)\n      return;\n\n    //cout << \"p = \" << startpoint << \"; elnr = \" << startelnr << endl;\n\n\n      \n    for(int dir = 1; dir >= -1; dir -= 2)\n      {\n\tif(dir*direction < 0) continue;\n\t  \n\tpoints.Append(startpoint);\n\tvals.Append(startval);\n\tdrawelems.Append(startdraw);\n\t  \n\tdouble h = 0.001*rad/startval; // otherwise no nice lines; should be made accessible from outside\n\t\n\tv = startv;\n\tif(dir == -1) v *= -1.;\n\n\tint elnr = startelnr;\n        double lami[3] = { startlami[0], startlami[1], startlami[2]}; \n\t  \n\n\tfor(double length = 0; length < maxlength; length += h*vals.Last())\n\t  {\n\t    if(v.Length() < 1e-12*rad)\n\t      {\n\t\t(*testout) << \"Current fieldlinecalculation came to a stillstand at \" << points.Last() << endl;\n\t\tbreak;\n\t      }\n\n            double dummyt{0};\n\t    stepper.StartNextValCalc(points.Last(),dummyt,h,true);\n\t    stepper.FeedNextF(v);\n            bool drawelem = false;\n\n            Point<3> newp;\n\t    while(!stepper.GetNextData(newp,dummyt,h) && elnr != -1)\n\t      {\n\t\telnr = GetVolElement(mesh, newp, lami);\n\t\tif(elnr != -1)\n\t\t  {\n\t\t    mesh.SetPointSearchStartElement(elnr);\n                    drawelem = func(elnr, lami, v);\n\t\t    if(dir == -1) v *= -1.;\n\t\t    stepper.FeedNextF(v);\n\t\t  }\n\t      }\n\n\t    if (elnr == -1)\n\t      {\n\t\t//cout << \"direction \" <<dir << \" reached the wall.\" << endl;\n\t\tbreak;\n\t      }\n\n\t    points.Append(newp);\n\t    vals.Append(v.Length());\n\t    drawelems.Append(drawelem);\n\n\t    if(points.Size() % 40 == 0 && points.Size() > 1)\n\t      (*testout) << \"Points in current fieldline: \" << points.Size() << \", current position: \" << newp << endl;\n\n\t    if(maxpoints > 0 && points.Size() >= maxpoints)\n\t      {\n\t\tbreak;\n\t      }\n\n\t    //cout << \"length \" << length << \" h \" << h << \" vals.Last() \" << vals.Last()  << \" maxlength \" << maxlength << endl;\n\t  }\n\tdirstart.Append(points.Size());\n      }\n  }\n  \n}\n"
  },
  {
    "path": "libsrc/meshing/fieldlines.hpp",
    "content": "#ifndef FIELDLINES_HPP_INCLUDED\n#define FIELDLINES_HPP_INCLUDED\n\nnamespace netgen\n{\n\nclass RKStepper\n{\nprivate:\n  Array<double> c,b;\n  TABLE<double> *a;\n  int steps;\n  int order;\n\n  double tolerance;\n\n  Array<Vec<3>> K;\n\n  int stepcount;\n\n  double h;\n  double startt;\n  double startt_bak;\n  Point<3> startval;\n  Point<3> startval_bak;\n\n  bool adaptive;\n  int adrun;\n  Point<3> valh;\n\n  int notrestarted;\n\npublic:\n\n  DLL_HEADER ~RKStepper();\n\n  RKStepper(int type = 0);\n\n  void SetTolerance(const double tol){tolerance = tol;}\n\n  void StartNextValCalc(const Point<3> & astartval, const double astartt, const double ah, const bool aadaptive = false);\n\n  bool GetNextData(Point<3> & val, double & t, double & ah);\n\n  bool FeedNextF(const Vec<3> & f);\n};\n\n\n\n\nclass FieldLineCalc\n{\nprivate:\n  const Mesh & mesh;\n\n  typedef std::function<bool (int elnr, const double *, Vec<3> &)> VectorFunction;\n\n  const VectorFunction & func;\n  RKStepper stepper;\n\n  Array<double> values;\n  Array<Point<3>> pstart, pend;\n\n  double maxlength;\n\n  int maxpoints;\n\n  int direction;\n\n  Point3d pmin, pmax;\n  double rad;\n\n  double critical_value;\n\n  bool randomized;\n\n  double thickness;\n\npublic:\n  DLL_HEADER FieldLineCalc(const Mesh & amesh, const VectorFunction & afunc,\n\t\tconst double rel_length, const int amaxpoints = -1,\n\t\tconst double rel_thickness = -1, const double rel_tolerance = -1, const int rk_type = 0, const int adirection = 0);\n\n  DLL_HEADER ~FieldLineCalc();\n\n  void SetCriticalValue(const double val) { critical_value = val; }\n\n  void Randomized(void) { randomized = true; }\n  void NotRandomized(void) { randomized = false; }\n\n  DLL_HEADER void Calc(const Point<3> & startpoint, Array<Point<3>> & points, Array<double> & vals, Array<bool> & drawelems, Array<int> & dirstart);\n\n  DLL_HEADER void GenerateFieldLines(Array<Point<3>> & potential_startpoints, const int numlines);\n\n  const auto & GetPStart() const { return pstart; }\n  const auto & GetPEnd() const { return pend; }\n  const auto & GetValues() const { return values; }\n  const auto GetThickness() const { return thickness; }\n};\n\n} // namespace netgen\n\n#endif // VSFIELDLINES_HPP_INCLUDED\n"
  },
  {
    "path": "libsrc/meshing/findip.hpp",
    "content": "#ifndef NETGEN_FINDIP_HPP\n#define NETGEN_FINDIP_HPP\n\n// find inner point\n\nnamespace netgen\n{\n\ninline void Minimize (const NgArray<Vec3d> & a,\n\t\t      const NgArray<double> & c,\n\t\t      int * act, \n\t\t      Vec<3> & x, double & f,\n\t\t      int * sol)\n{\n  int act1[4];\n  Mat<3> m, inv;\n  Vec<3> rs, xmax, center;\n\n  f = 1e99;\n\n  for (int j = 0; j < 5; j++)\n    {\n      for (int hk = 0, k = 0; hk < 4; hk++)\n\t{\n\t  if (hk == j) k++;\n\t  act1[hk] = act[k];\n\t  k++;\n\t}\n\n      for (int k = 0; k < 3; k++)\n\t{\n\t  m(k, 0) = a[act1[0]].X() - a[act1[k+1]].X();\n\t  m(k, 1) = a[act1[0]].Y() - a[act1[k+1]].Y();\n\t  m(k, 2) = a[act1[0]].Z() - a[act1[k+1]].Z();\n\t  rs(k) = c[act1[k+1]] - c[act1[0]];\n\t}\n\n      /*\n      (*testout) << \"act1 = \"\n\t\t << act1[0] << \" \"\n\t\t << act1[1] << \" \"\n\t\t << act1[2] << \" \"\n\t\t << act1[3] << endl;\n      (*testout) << \"Det = \" << Det(m) << endl;\n      */\n\n      if (fabs (Det (m)) > 1e-10)\n\t{\n\t  CalcInverse (m, inv);\n\t  xmax = inv * rs;\n\t  \n\t  double fmax = -1e10;\n\t  for (int k = 0; k < 5; k++)\n\t    {\n\t      double hd = \n\t\txmax(0) * a[act[k]].X() + xmax(1) * a[act[k]].Y() + xmax(2) * a[act[k]].Z() + c[act[k]];\n\t      if (hd > fmax) fmax = hd;\n\t    }\n\n\t  if (fmax < f)\n\t    {\n\t      f = fmax;\n\t      x = xmax;\n\t      for (int k = 0; k < 4; k++)\n\t\tsol[k] = act1[k];\n\t    }\n\t}\n    }\n}\n\n\n\n\ntemplate <typename POINTArray, typename FACEArray>\ninline int FindInnerPoint (POINTArray & points,\n\t\t\t   FACEArray & faces,\n\t\t\t   Point3d & p)\n{\n  static int timer = NgProfiler::CreateTimer (\"FindInnerPoint\");\n  NgProfiler::RegionTimer reg (timer);\n\n  NgArray<Vec3d> a;\n  NgArray<double> c;\n  Mat<3> m, inv;\n  Vec<3> rs, x = 0.0, center;\n  double f;\n\n  int nf = faces.Size();\n\n  // minimize_x  max_i  a_i x + c_i\n\n  a.SetSize (nf+4);\n  c.SetSize (nf+4);\n\n  for (int i = 0; i < nf; i++)\n    {\n      Point3d p1 = points[faces[i][0]];\n      a[i] = Cross (points[faces[i][1]] - p1,\n\t\t    points[faces[i][2]] - p1);\n      a[i] /= a[i].Length();\n      c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z());\n    }\n\n  /*\n  center = 0;\n  for (int i = 0; i < points.Size(); i++)\n    center += Vec<3> (points[i]);\n  center /= points.Size();\n  */\n\n  center = 0;\n  for (int i = 0; i < faces.Size(); i++)\n    for (int j = 0; j < 3; j++)\n      center += Vec<3> (points[faces[i][j]]);\n  center /= (3*faces.Size());\n\n\n  // (*testout) << \"center = \" << center << endl;\n\n  double hmax = 0;\n  for (int i = 0; i < nf; i++)\n    {\n      // const Element2d & el = faces[i];\n      // (*testout) << \"el[\" << i << \"] = \" << el << endl;\n      for (int j : Range(3))\n\t{\n\t  double hi = Dist (points[faces[i][j%3]],\n\t\t\t    points[faces[i][(j+1)%3]]);\n\t  if (hi > hmax) hmax = hi;\n\t}\n    }\n  \n  // (*testout) << \"hmax = \" << hmax << endl;\n  \n  a[nf] = Vec<3> (1, 0, 0);\n  c[nf] = -center(0) - hmax;\n  a[nf+1] = Vec<3> (0, 1, 0);\n  c[nf+1] = -center(1) - hmax;\n  a[nf+2] = Vec<3> (0, 0, 1);\n  c[nf+2] = -center(2) - hmax;\n  a[nf+3] = Vec<3> (-1, -1, -1);\n  c[nf+3] = center(0)+center(1)+center(2)-3*hmax;\n\n  /*\n  (*testout) << \"findip, a now = \" << endl << a << endl;\n  (*testout) << \"findip, c now = \" << endl << c << endl;\n  */\n\n  int act[5] = { 0, nf, nf+1, nf+2, nf+3 };\n  int sol[4];\n\n  while (1)\n    {\n      /*\n      (*testout) << \"try \";\n      for (int j = 0; j < 5; j++)\n\t(*testout)  << act[j] << \" \";\n      */\n\n      Minimize (a, c, act, x, f, sol);\n\n      /*\n      (*testout) << endl << \"sol = \";\n      for (int j = 0; j < 4; j++)\n\t(*testout)  << sol[j] << \" \";\n\n      (*testout) << \" fmin = \" << f << endl;\n      */\n      for (int j = 0; j < 4; j++) act[j] = sol[j];\n      \n      bool found = 0;\n      double maxval = f;\n      for (int j = 0; j < nf; j++)\n\t{\n\t  double val = x(0) * a[j].X() + x(1) * a[j].Y() + x(2) * a[j].Z() + c[j];\n\t  if (val > maxval + hmax * 1e-6)\n\t    {\n\t      found = 1;\n\t      maxval = val;\n\t      act[4] = j;\n\t    }\n\t}\n      \n      // (*testout) << \"maxval = \" << maxval << endl;\n      if (!found) break;\n    }\n  \n  // cout << \"converged, f = \" << f << endl;\n  \n  p = Point3d (x(0), x(1), x(2));\n  // (*testout) << \"findip, f = \" << f << \", hmax = \" << hmax << endl;\n  return (f < -1e-5 * hmax);\n}\n\n} // namespace netgen\n#endif // FILE_FINDINNERPOINT_HPP\n\n\n"
  },
  {
    "path": "libsrc/meshing/findip2.hpp",
    "content": "#ifndef NETGEN_FINDIP2_HPP\n#define NETGEN_FINDIP2_HPP\n\n// find inner point\n\nnamespace netgen\n{\n\ntemplate <typename POINTArray, typename FACEArray>\ninline int FindInnerPoint2 (POINTArray & points,\n\t\t\t    FACEArray & faces,\n\t\t\t    Point3d & p)\n{\n  static int timer = NgProfiler::CreateTimer (\"FindInnerPoint2\");\n  NgProfiler::RegionTimer reg (timer);\n\n  NgArray<Vec3d> a;\n  NgArray<double> c;\n  Mat<3> m, inv;\n  Vec<3> rs, x, pmin;\n\n  int nf = faces.Size();\n\n  a.SetSize (nf);\n  c.SetSize (nf);\n\n  for (int i = 0; i < nf; i++)\n    {\n      Point3d p1 = points.Get(faces[i][0]);\n      a[i] = Cross (points.Get(faces[i][1]) - p1,\n\t\t    points.Get(faces[i][2]) - p1);\n      a[i] /= a[i].Length();\n      c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z());\n    }\n\n\n  x = 0;\n  \n  \n  double hmax = 0;\n  for (int i = 0; i < nf; i++)\n    {\n      const Element2d & el = faces[i];\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  double hi = Dist (points.Get(el.PNumMod(j)),\n\t\t\t    points.Get(el.PNumMod(j+1)));\n\t  if (hi > hmax) hmax = hi;\n\t}\n    }\n\n  double fmin = 0;\n\n  for (int i1 = 1; i1 <= nf; i1++)\n    for (int i2 = i1+1; i2 <= nf; i2++)\n      for (int i3 = i2+1; i3 <= nf; i3++)\n        for (int i4 = i3+1; i4 <= nf; i4++)\n          {\n\t    m(0, 0) = a.Get(i1).X() - a.Get(i2).X();\n\t    m(0, 1) = a.Get(i1).Y() - a.Get(i2).Y();\n\t    m(0, 2) = a.Get(i1).Z() - a.Get(i2).Z();\n\t    rs(0) = c.Get(i2) - c.Get(i1);\n\n\t    m(1, 0) = a.Get(i1).X() - a.Get(i3).X();\n\t    m(1, 1) = a.Get(i1).Y() - a.Get(i3).Y();\n\t    m(1, 2) = a.Get(i1).Z() - a.Get(i3).Z();\n\t    rs(1) = c.Get(i3) - c.Get(i1);\n\n\t    m(2, 0) = a.Get(i1).X() - a.Get(i4).X();\n\t    m(2, 1) = a.Get(i1).Y() - a.Get(i4).Y();\n\t    m(2, 2) = a.Get(i1).Z() - a.Get(i4).Z();\n\t    rs(2) = c.Get(i4) - c.Get(i1);\n\n\n\t    if (fabs (Det (m)) > 1e-10)\n\t      {\n\t\tCalcInverse (m, inv);\n\t\tx = inv * rs;\n\n\t\tdouble f = -1e10;\n\t\tfor (int i = 0; i < nf; i++)\n\t\t  {\n\t\t    double hd = \n\t\t      x(0) * a[i].X() + x(1) * a[i].Y() + x(2) * a[i].Z() + c[i];\n\t\t    if (hd > f) f = hd;\n\t\t    if (hd > fmin) break;\n\t\t  }\n\n\t\tif (f < fmin)\n\t\t  {\n\t\t    fmin = f;\n\t\t    pmin = x;\n\t\t  }\n\t      }\n          }\n\n  p = Point3d (pmin(0), pmin(1), pmin(2));\n  (*testout) << \"fmin = \" << fmin << endl;\n  return (fmin < -1e-3 * hmax);\n}\n\n} // namespace netgen\n#endif // NETGEN_FINDIP2_HPP\n"
  },
  {
    "path": "libsrc/meshing/geomsearch.cpp",
    "content": "#include <mystdlib.h>\n#include \"geomsearch.hpp\"\n#include \"adfront3.hpp\"\n\n\nnamespace netgen\n{\n  GeomSearch3d :: GeomSearch3d() \n  {\n    size.i1 = 0; size.i2 = 0; size.i3 = 0; \n  };\n\n  GeomSearch3d :: ~GeomSearch3d()\n  {\n    //delete old Hashtable:\n    if (size.i1 != 0)\n      {\n\tfor (int i = 0; i < size.i1*size.i2*size.i3; i++)\n\t  delete hashtable[i];\n      } \n  }\n\n  void GeomSearch3d :: Init (Array <FrontPoint3,PointIndex> *pointsi, NgArray <FrontFace> *facesi)\n  {\n    points = pointsi;\n    faces = facesi;\n    size.i1 = 0; size.i2 = 0; size.i3 = 0; \n    reset = 1;\n    hashcount = 1;\n  }\n\n  void GeomSearch3d :: ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem)\n  {\n    maxp.X()=(*points)[elem.PNum(1)].P()(0);\n    maxp.Y()=(*points)[elem.PNum(1)].P()(1);\n    maxp.Z()=(*points)[elem.PNum(1)].P()(2);\n    minp.X()=(*points)[elem.PNum(1)].P()(0);\n    minp.Y()=(*points)[elem.PNum(1)].P()(1);\n    minp.Z()=(*points)[elem.PNum(1)].P()(2);\n  \n    for (int i=2; i <= 3; i++)\n      {\n\tmaxp.X()=max2((*points)[elem.PNum(i)].P()(0),maxp.X());\n\tmaxp.Y()=max2((*points)[elem.PNum(i)].P()(1),maxp.Y());\n\tmaxp.Z()=max2((*points)[elem.PNum(i)].P()(2),maxp.Z());\n\tminp.X()=min2((*points)[elem.PNum(i)].P()(0),minp.X());\n\tminp.Y()=min2((*points)[elem.PNum(i)].P()(1),minp.Y());\n\tminp.Z()=min2((*points)[elem.PNum(i)].P()(2),minp.Z());\n      }\n  }\n\n  void GeomSearch3d :: MinCoords(const Point3d& p1, Point3d& p2)\n  {\n    p2.X()=min2(p1.X(),p2.X());\n    p2.Y()=min2(p1.Y(),p2.Y());\n    p2.Z()=min2(p1.Z(),p2.Z());\n  }\n\n  void GeomSearch3d :: MaxCoords(const Point3d& p1, Point3d& p2)\n  {\n    p2.X()=max2(p1.X(),p2.X());\n    p2.Y()=max2(p1.Y(),p2.Y());\n    p2.Z()=max2(p1.Z(),p2.Z());\n  }\n\n  void GeomSearch3d :: Create()\n  {\n    INDEX i,j,k;\n    if (reset)\n      {\n\tconst double hashelemsizefactor = 4;\n\treset = 0;\n\t/*\n\t  minext=Point3d(MAXDOUBLE, MAXDOUBLE, MAXDOUBLE);\n\t  maxext=Point3d(MINDOUBLE, MINDOUBLE, MINDOUBLE);\n\t*/\n\tElemMaxExt(minext, maxext, faces->Get(1).Face());\n\tPoint3d maxp, minp;\n\tVec3d midext(0,0,0);\n      \n\t//get max Extension of Frontfaces\n\tfor (i = 1; i <= faces->Size(); i++)\n\t  {\n\t    ElemMaxExt(minp, maxp, faces->Get(i).Face());\n\t    MinCoords(minp, minext);\n\t    MaxCoords(maxp, maxext);\n\t    midext+=maxp-minp;\n\t  }\n\n\n\tmaxextreal = maxext;\n\tmaxext = maxext + 1e-4 * (maxext - minext);\n\n\tmidext*=1./faces->Size();\n\tVec3d boxext = maxext - minext;\n      \n\t//delete old Hashtable:\n\tif (size.i1 != 0)\n\t  {\n\t    for (i = 1; i <= size.i1*size.i2*size.i3; i++)\n\t      {\n\t\tdelete hashtable.Get(i);\n\t      }\n\t  } \n      \n\tsize.i1 = int (boxext.X()/midext.X()/hashelemsizefactor+1);\n\tsize.i2 = int (boxext.Y()/midext.Y()/hashelemsizefactor+1);\n\tsize.i3 = int (boxext.Z()/midext.Z()/hashelemsizefactor+1);\n\n\tint nfaces = faces->Size();\n\tsize.i1 = min(size.i1, nfaces);\n\tsize.i2 = min(size.i2, nfaces);\n\tsize.i3 = min(size.i3, nfaces);\n\n\t// PrintMessage (5, \"hashsizes = \", size.i1, \", \", size.i2, \", \", size.i3);\n      \n\telemsize.X()=boxext.X()/size.i1;\n\telemsize.Y()=boxext.Y()/size.i2;\n\telemsize.Z()=boxext.Z()/size.i3;\n\n\t//create Hasharrays:\n\thashtable.SetSize(size.i1*size.i2*size.i3);\n\tfor (i = 1; i <= size.i1; i++)\n\t  {\n\t    for (j = 1; j <= size.i2; j++)\n\t      {\n\t\tfor (k = 1; k <= size.i3; k++)\n\t\t  {\n\t\t    INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1;\n\t\t    hashtable.Elem(ind) = new NgArray <int> ();\n\t\t  }\n\t      }\n\t  }\n      }\n    else\n      {\n\t//Clear all Hash-Arrays\n\tfor (i = 1; i <= size.i1; i++)\n\t  {\n\t    for (j = 1; j <= size.i2; j++)\n\t      {\n\t\tfor (k = 1; k <= size.i3; k++)\n\t\t  {\n\t\t    INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1;\n\t\t    hashtable.Elem(ind)->SetSize(0);\n\t\t  }\n\t      }\n\t  }\t  \n      }\n  \n    //Faces in Hashtable einfuegen:\n    for (i = 1; i <= faces->Size(); i++)\n      {\n\tAddElem(faces->Get(i).Face(),i);\n      }\n  \n  }\n\n  void GeomSearch3d :: AddElem(const MiniElement2d& elem, INDEX elemnum)\n  {\n    Point3d minp, maxp;\n    ElemMaxExt(minp, maxp, elem);\n    int sx = int ((minp.X()-minext.X())/elemsize.X()+1.);\n    int ex = int ((maxp.X()-minext.X())/elemsize.X()+1.);\n    int sy = int ((minp.Y()-minext.Y())/elemsize.Y()+1.);\n    int ey = int ((maxp.Y()-minext.Y())/elemsize.Y()+1.);\n    int sz = int ((minp.Z()-minext.Z())/elemsize.Z()+1.);\n    int ez = int ((maxp.Z()-minext.Z())/elemsize.Z()+1.);\n  \n    for (int ix = sx; ix <= ex; ix++)\n      for (int iy = sy; iy <= ey; iy++)\n        for (int iz = sz; iz <= ez; iz++)\n          {\n            INDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1;\n            if (ind < 1 || ind > size.i1 * size.i2 * size.i3)\n              {\n                cerr << \"Illegal hash-position\";\n                cerr << \"Position: \" << ix << \",\" << iy << \",\" << iz << endl;\n\t\t    throw NgException (\"Illegal position in Geomsearch\");\n              }\n            hashtable.Elem(ind)->Append(elemnum);\t\t      \n          }\n  }\n\n  void GeomSearch3d :: GetLocals(NgArray<MiniElement2d> & locfaces,  NgArray<INDEX> & findex,\n\t\t\t\t INDEX fstind, const Point3d& p0, double xh)\n  {\n    hashcount++;\n  \n    Point3d minp, maxp, midp; \n\n    minp=p0-Vec3d(xh,xh,xh); //lay cube over sphere\n    maxp=p0+Vec3d(xh,xh,xh);\n\n    MaxCoords(minext,minp); //cube may not be out of hash-region\n    MinCoords(maxextreal,maxp);\n\n\n    PointIndex cluster = faces->Get(fstind).Cluster();\n  \n    int sx = int((minp.X()-minext.X())/elemsize.X()+1.);\n    int ex = int((maxp.X()-minext.X())/elemsize.X()+1.);\n    int sy = int((minp.Y()-minext.Y())/elemsize.Y()+1.);\n    int ey = int((maxp.Y()-minext.Y())/elemsize.Y()+1.);\n    int sz = int((minp.Z()-minext.Z())/elemsize.Z()+1.);\n    int ez = int((maxp.Z()-minext.Z())/elemsize.Z()+1.);\n    int ix,iy,iz,i,k;\n\n    [[maybe_unused]] int cnt1 = 0;  // test, how efficient hashtable is\n    [[maybe_unused]] int cnt2 = 0;\n    [[maybe_unused]] int cnt3 = 0;\n  \n    for (ix = sx; ix <= ex; ix++)\n      {\n\tfor (iy = sy; iy <= ey; iy++)\n\t  {\n\t    for (iz = sz; iz <= ez; iz++)\n\t      {\n\t\tINDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1;\n\t      \n\t\t//go through all elements in one hash area\n\t\tconst NgArray <int> & area = *hashtable.Elem(ind);\n\t\tfor (k = 1; k <= area.Size(); k++)\n\t\t  {\n\t\t    cnt2++;\n\t\t    i = area.Get(k);\n\t\t    if (faces->Get(i).Cluster() == cluster && \n\t\t\tfaces->Get(i).Valid() &&\n\t\t\tfaces->Get(i).HashValue() != hashcount && \n\t\t\ti != fstind)\n\t\t      {\n\t\t\tcnt1++;\n\t\t\tconst MiniElement2d & face = faces->Get(i).Face();\n\t\t      \n\t\t\tconst Point3d & p1 = (*points)[face.PNum(1)].P();\n\t\t\tconst Point3d & p2 = (*points)[face.PNum(2)].P();\n\t\t\tconst Point3d & p3 = (*points)[face.PNum(3)].P();\n\t\t      \n\t\t\tmidp = Center (p1, p2, p3);\n\t\t      \n\t\t\t// if (Dist2 (midp, p0) <= xh*xh)  \n                        if((Dist2 (p1, p0) <= xh*xh) ||\n                           (Dist2 (p2, p0) <= xh*xh) ||\n                           (Dist2 (p3, p0) <= xh*xh) ||\n                           (Dist2 (midp, p0) <= xh*xh) )  // by Jochen Wild\n\t\t\t  {\n\t\t\t    cnt3++;\n\t\t\t    locfaces.Append(faces->Get(i).Face());\n\t\t\t    findex.Append(i);\n\t\t\t    faces->Elem(i).SetHashValue(hashcount);\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n      }\n    /*\n      if (faces->Size() != 0 && hashcount % 200 == 0)\n      {\n      (*mycout) << \"n.o.f= \" << faces->Size();\n      (*mycout) << \", n.o.lf= \" << locfaces.Size();\n      (*mycout) << \", hashf= \" << (double)cnt2/(double)faces->Size();\n      (*mycout) << \" (\" << (double)cnt1/(double)faces->Size();\n      (*mycout) << \", \" << (double)cnt3/(double)faces->Size() << \")\" << endl;\n      }\n    */\n\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/geomsearch.hpp",
    "content": "#ifndef NETGEN_GEOMSEARCH_HPP\n#define NETGEN_GEOMSEARCH_HPP\n\n/**************************************************************************/\n/* File:   geomsearch.hh                                                  */\n/* Author: Johannes Gerstmayr                                             */\n/* Date:   19. Nov. 97                                                    */\n/**************************************************************************/\n\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n\nclass FrontPoint3;\nclass FrontFace;\nclass MiniElement2d;\n\n  /// class for quick access of 3D-elements; class cannot delete elements, but only append\nclass GeomSearch3d\n{\n\npublic:\n  ///\n  GeomSearch3d();\n  ///\n  virtual ~GeomSearch3d();\n\n  ///\n  void Init (Array <FrontPoint3,PointIndex> *pointsi, NgArray <FrontFace> *facesi);\n\n  ///get elements max extension\n  void ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem);\n  \n  ///get minimum coordinates of two points ->p2\n  void MinCoords(const Point3d& p1, Point3d& p2);\n\n  ///get minimum coordinates of two points ->p2\n  void MaxCoords(const Point3d& p1, Point3d& p2);\n\n  ///create a hashtable from an existing array of triangles\n  ///sizei = number of pieces in one direction\n  void Create();\n\n  ///add new element to Hashtable\n  void AddElem(const MiniElement2d& elem, INDEX elemnum);\n\n  ///GetLocal faces in sphere with radius xh and middlepoint p\n  void GetLocals(NgArray<MiniElement2d> & locfaces,  NgArray<INDEX> & findex,\n\t\t INDEX fstind, const Point3d& p0, double xh);\n\nprivate:\n  \n  NgArray <FrontFace> *faces; // Pointers to Arrays in Adfront\n  Array <FrontPoint3,PointIndex> *points;\n\n  NgArray <NgArray <int>*> hashtable;\n\n  Point3d minext; //extension of Hashdomain\n  Point3d maxext;\n  Point3d maxextreal;\n  Vec3d elemsize;  //size of one Hash-Element\n\n  threeint size; // size of Hashtable in each direction\n  int reset;\n  int hashcount;\n};\n} // namespace netgen\n#endif // NETGEN_GEOMSEARCH_HPP\n"
  },
  {
    "path": "libsrc/meshing/global.cpp",
    "content": "#include <mystdlib.h>\n#include \"global.hpp\"\n#include <netgen_version.hpp>\n#include \"msghandler.hpp\"\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n  class NetgenGeometry;\n  class TraceGlobal\n  {\n    string name;\n  public:\n    TraceGlobal(string _name) : name(_name) { cout << \"init global \" << name << endl; }\n    ~TraceGlobal() { cout << \"exit global \" << name << endl; }\n  };\n  \n  // stringstream emptystr;\n  // ostream * testout = &emptystr;\n  // testout -> clear(ios::failbit);\n\n  // ostream * testout = &cout;\n\n  // NetgenOutStream * testout = new NetgenOutStream;\n\n  const string netgen_version = NETGEN_VERSION;\n\n  ostream * mycout = &cout;\n  ostream * myerr = &cerr;\n\n  // some functions (visualization) still need a global mesh\n  // TraceGlobal glob1(\"global1\");\n  DLL_HEADER shared_ptr<Mesh> mesh;\n  DLL_HEADER shared_ptr<NetgenGeometry> ng_geometry;\n  // TraceGlobal glob2(\"global2\");\n\n  // global communicator for netgen\n  // DLL_HEADER NgMPI_Comm ng_comm;\n  \n  weak_ptr<Mesh> global_mesh;\n  void(*on_set_global_mesh)(shared_ptr<Mesh>) = nullptr;\n\n  void SetGlobalMesh (shared_ptr<Mesh> m)\n  {\n    if(GetGlobalMesh() == m)\n      return;\n    PrintMessage(5, \"set global mesh\");\n    global_mesh = m;\n    if (on_set_global_mesh)\n      on_set_global_mesh(m);\n  }\n\n  shared_ptr<Mesh> GetGlobalMesh ()\n  {\n    try {\n      return global_mesh.lock();\n    } catch (const bad_weak_ptr & e) {\n      return nullptr;\n    }\n  }\n  \n  // true if netgen was started using the netgen executable\n  // false if netgen.gui was imported from python\n  DLL_HEADER bool netgen_executable_started = false;\n  \n  //  Flags parameters;\n  int silentflag = 0;\n  int testmode = 0;\n\n\n  string ngdir = \".\";\n\n  void Ng_PrintDest(const char * s)\n  {\n    if (id == 0)\n      (*mycout) << s << flush;\n  }\n\n  DLL_HEADER void MyError(const char * ch)\n  {\n    cout << ch;\n    (*testout) << \"Error !!! \" << ch << endl << flush;\n  }\n\n  static double starttimea;\n  void ResetTime ()\n  {\n    starttimea = WallTime();\n  }\n\n  double GetTime ()\n  {\n    return WallTime() - starttimea;\n  }\n\n\n\n  mutex tcl_todo_mutex;\n\n  int h_argc = 0;\n  char ** h_argv = NULL;\n\n  DebugParameters debugparam;\n  bool verbose = 0;\n\n  size_t timestamp = 0;\n  /*\n  int GetTimeStamp() \n  { \n    return timestamp; \n  }\n\n  int NextTimeStamp()\n  {\n    timestamp++;\n    return timestamp;\n  }\n  */\n}\n"
  },
  {
    "path": "libsrc/meshing/global.hpp",
    "content": "#ifndef NETGEN_GLOBAL_HPP\n#define NETGEN_GLOBAL_HPP\n\n\n/**************************************************************************/\n/* File:   global.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\n/*\n  global functions and variables\n*/\n\n#include <mydefs.hpp>\n\nnamespace netgen\n{\n  using namespace ngcore;\n  ///\n  DLL_HEADER extern double GetTime ();\n  DLL_HEADER extern void ResetTime ();\n\n  ///\n  DLL_HEADER extern int testmode;\n\n  /// calling parameters\n  // extern Flags parameters;\n\n  // extern DLL_HEADER MeshingParameters mparam;\n\n  DLL_HEADER extern mutex tcl_todo_mutex;\n\n\n  class DebugParameters;\n  class Mesh;\n\n  DLL_HEADER extern string ngdir;\n  DLL_HEADER extern DebugParameters debugparam;\n  DLL_HEADER extern bool verbose;\n\n  DLL_HEADER extern int h_argc;\n  DLL_HEADER extern char ** h_argv;\n\n\n  DLL_HEADER extern void(*on_set_global_mesh)(shared_ptr<Mesh>);\n  DLL_HEADER extern weak_ptr<Mesh> global_mesh;\n  DLL_HEADER void SetGlobalMesh (shared_ptr<Mesh> m);\n  DLL_HEADER shared_ptr<Mesh> GetGlobalMesh ();\n\n  // global communicator for netgen (dummy if no MPI)\n  // extern DLL_HEADER NgMPI_Comm ng_comm;\n  \n} // namespace netgen\n\n#endif // NETGEN_GLOBAL_HPP\n"
  },
  {
    "path": "libsrc/meshing/hpref_hex.hpp",
    "content": "// SZ \n\n// HP_HEX  ... no refinement\nint refhex_splitedges[][3] =\n  {\n      { 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE refhex_newelstypes[] =\n  {\n    HP_HEX,\n    HP_NONE,\n  };\nint refhex_newels[][8] =\n  {\n    { 1, 2, 3, 4, 5, 6, 7, 8 }\n  };\nHPRef_Struct refhex =\n  {\n    HP_HEX,\n    refhex_splitedges, \n    0, 0,\n    refhex_newelstypes, \n    refhex_newels\n  };\n\n// HP_HEX_1F  ... face (1 - 4 - 3 -2) singular \nint refhex_1f_0e_0v_splitedges[][3] =\n  {\n    { 1, 5, 9 },\n    { 2, 6, 10 },\n    { 3, 7, 11 },\n    { 4, 8, 12 }, \n    { 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE refhex_1f_0e_0v_newelstypes[] =\n  {\n    HP_HEX,\n    HP_HEX_1F_0E_0V,\n    HP_NONE,\n  };\nint  refhex_1f_0e_0v_newels[][8] =\n  {\n    { 9, 10, 11, 12, 5, 6, 7, 8 }, \n    { 1, 2, 3, 4, 9, 10, 11, 12}  \n }; \nHPRef_Struct refhex_1f_0e_0v =\n  {\n    HP_HEX,\n    refhex_1f_0e_0v_splitedges, \n    0, 0,\n    refhex_1f_0e_0v_newelstypes, \n    refhex_1f_0e_0v_newels\n  };\n\n\n\n\n\n// HP_HEX_1FA_1FB  ... face (1 - 4 - 3 -2) and face (1-2-6-5) singular \nint refhex_1fa_1fb_0e_0v_splitedges[][3] =\n  {\n    { 1, 5, 9 },\n    { 2, 6, 10 },\n    { 3, 7, 11 },\n    { 4, 8, 12 },\n    { 1, 4, 13 },\n    { 2, 3, 14 },  \n    { 6, 7, 15 }, \n    { 5, 8, 16 }, \n    { 0, 0, 0 }\n  };\n\nint refhex_1fa_1fb_0e_0v_splitfaces[][4] =\n  {\n    { 2, 3, 6, 17 },\n    { 1, 4, 5, 18 },\n    { 0, 0, 0, 0 },\n  };\nHPREF_ELEMENT_TYPE refhex_1fa_1fb_0e_0v_newelstypes[] =\n  {\n    HP_HEX,\n    HP_HEX_1F_0E_0V,\n    HP_HEX_1F_0E_0V, \n    HP_HEX_1FA_1FB_0E_0V, \n    HP_NONE,\n  };\nint  refhex_1fa_1fb_0e_0v_newels[][8] =\n  {\n    {18, 17, 11, 12, 16, 15, 7, 8}, \n    {13, 14, 3, 4, 18, 17, 11, 12},\n    { 5, 6, 10, 9, 16, 15, 17, 18}, \n    { 1, 2, 14, 13, 9, 10, 17, 18} \n  }; \nHPRef_Struct refhex_1fa_1fb_0e_0v =\n  {\n    HP_HEX,\n    refhex_1fa_1fb_0e_0v_splitedges, \n    refhex_1fa_1fb_0e_0v_splitfaces, 0,\n    refhex_1fa_1fb_0e_0v_newelstypes, \n    refhex_1fa_1fb_0e_0v_newels\n  };\n\n\n\n// Refine Dummies \n  // HP_HEX_0E_1V\n  int refhex_0e_1v_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refhex_0e_1v_newelstypes[] =\n    {\n      HP_TET_0E_1V,\n      HP_TET,\n      HP_TET,\n      HP_TET,\n      HP_TET,\n      HP_TET,\n      HP_NONE,\n    };\n  int refhex_0e_1v_newels[][8] =\n    {\n      { 1, 5, 2, 4 },\n      { 7, 3, 6, 8 },\n      { 2, 8, 5, 6 },\n      { 2, 8, 6, 3 },\n      { 2, 8, 3, 4 },\n      { 2, 8, 4, 5 },\n    };\n  HPRef_Struct refhex_0e_1v =\n    {\n      HP_HEX,\n      refhex_0e_1v_splitedges, \n      0, 0,\n      refhex_0e_1v_newelstypes, \n      refhex_0e_1v_newels\n    };\n\n\n\n// Refine Dummies \n  // HP_HEX_1E_1V\n  int refhex_1e_1v_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refhex_1e_1v_newelstypes[] =\n    {\n      HP_TET_1E_1VA,\n      HP_TET,\n      HP_TET_0E_1V,\n      HP_TET_0E_1V,\n      HP_TET_0E_1V,\n      HP_TET_0E_1V,\n      HP_NONE,\n    };\n  int refhex_1e_1v_newels[][8] =\n    {\n      // { 1, 5, 2, 4 }, \n      { 1, 2, 4, 5 },\n      { 7, 3, 6, 8 },\n      { 2, 8, 5, 6 },\n      { 2, 8, 6, 3 },\n      { 2, 8, 3, 4 },\n      { 2, 8, 4, 5 },\n    };\n  HPRef_Struct refhex_1e_1v =\n    {\n      HP_HEX,\n      refhex_1e_1v_splitedges, \n      0, 0,\n      refhex_1e_1v_newelstypes, \n      refhex_1e_1v_newels\n    };\n\n\n// Refine Dummies \n  // HP_HEX_3E_0V\n  int refhex_3e_0v_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refhex_3e_0v_newelstypes[] =\n    {\n      HP_TET_1E_1VA,\n      HP_TET_1E_1VA,\n      HP_TET_1E_1VA,\n      HP_TET_0E_1V,\n      HP_TET,\n      HP_NONE,\n    };\n  int refhex_3e_0v_newels[][8] =\n    {\n      { 1, 2, 3, 6 },\n      { 1, 4, 8, 3 },\n      { 1, 5, 6, 8 },\n      { 1, 6, 3, 8 },\n      { 3, 8, 6, 7 },\n    };\n  HPRef_Struct refhex_3e_0v =\n    {\n      HP_HEX,\n      refhex_3e_0v_splitedges, \n      0, 0,\n      refhex_3e_0v_newelstypes, \n      refhex_3e_0v_newels\n    };\n\n\n\n// Refine Dummies \n  // HP_HEX_1E_0V \n  int refhex_1e_0v_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n\n  HPREF_ELEMENT_TYPE refhex_1e_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE,         // HP_PRISM_SINGEDGE_H1,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refhex_1e_0v_newels[][8] =\n    {\n      { 1, 4, 5, 2, 3, 6 },\n      { 5, 4, 8, 6, 3, 7 },\n    };\n  HPRef_Struct refhex_1e_0v =\n    {\n      HP_HEX,\n      refhex_1e_0v_splitedges, \n      0, 0,\n      refhex_1e_0v_newelstypes, \n      refhex_1e_0v_newels\n    };\n\n\n\n\n\n\n// HP_HEX  ... no refinement\nint refhex7_splitedges[][3] =\n  {\n      { 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE refhex7_newelstypes[] =\n  {\n    HP_HEX7,\n    HP_NONE,\n  };\nint refhex7_newels[][8] =\n  {\n    { 1, 2, 3, 4, 5, 6, 7 }\n  };\nHPRef_Struct refhex7 =\n  {\n    HP_HEX7,\n    refhex7_splitedges, \n    0, 0,\n    refhex7_newelstypes, \n    refhex7_newels\n  };\n\n// HP_HEX_1FA  ... face (1 - 4 - 3 -2) singular \nint refhex7_1fa_splitedges[][3] =\n  {\n    { 1, 5, 8 },\n    { 2, 6, 9 },\n    { 3, 7, 10 },\n    { 4, 7, 11 }, \n    { 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE refhex7_1fa_newelstypes[] =\n  {\n    HP_HEX_1F_0E_0V,\n    HP_HEX7,\n    HP_NONE,\n  };\nint  refhex7_1fa_newels[][8] =\n  {\n    { 1, 2, 3, 4, 8, 9, 10, 11 },\n    { 8, 9, 10, 11, 5, 6, 7 }\n }; \nHPRef_Struct refhex7_1fa =\n  {\n    HP_HEX7,\n    refhex7_1fa_splitedges, \n    0, 0,\n    refhex7_1fa_newelstypes, \n    refhex7_1fa_newels\n  };\n\n\n\n\n// HP_HEX_1FB  ... face (5,6,7) singular \nint refhex7_1fb_splitedges[][3] =\n  {\n    { 5, 1, 8 },\n    { 6, 2, 9 },\n    { 7, 3, 10 },\n    { 7, 4, 11 }, \n    { 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE refhex7_1fb_newelstypes[] =\n  {\n    HP_HEX,\n    HP_HEX7_1FB,\n    HP_NONE,\n  };\nint  refhex7_1fb_newels[][8] =\n  {\n    { 1, 2, 3, 4, 8, 9, 10, 11 },\n    { 8, 9, 10, 11, 5, 6, 7 }\n }; \nHPRef_Struct refhex7_1fb =\n  {\n    HP_HEX7,\n    refhex7_1fb_splitedges, \n    0, 0,\n    refhex7_1fb_newelstypes, \n    refhex7_1fb_newels\n  };\n\n\n\n\n\n"
  },
  {
    "path": "libsrc/meshing/hpref_prism.hpp",
    "content": "\n  // HP_PRISM  ... no refinement\n  int refprism_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_newels[][8] =\n    {\n      { 1, 2, 3, 4, 5, 6 }\n    };\n  HPRef_Struct refprism =\n    {\n      HP_PRISM,\n      refprism_splitedges, \n      0, 0,\n      refprism_newelstypes, \n      refprism_newels\n    };\n\n\n\n  // HP_PRISM_SINGEDGE  ... vertical edge 1-4 is singular\n  int refprism_singedge_splitedges[][3] =\n    {\n      { 1, 2, 7 },\n      { 1, 3, 8 },\n      { 4, 5, 9 },\n      { 4, 6, 10 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_singedge_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE,\n      HP_HEX,\n      HP_NONE,\n    };\n  int refprism_singedge_newels[][8] =\n    {\n      { 1, 7, 8, 4, 9, 10 },\n      { 3, 8, 7, 2, 6, 10, 9, 5 }\n    };\n  HPRef_Struct refprism_singedge =\n    {\n      HP_PRISM,\n      refprism_singedge_splitedges, \n      0, 0,\n      refprism_singedge_newelstypes, \n      refprism_singedge_newels\n    };\n\n\n\n\n\n\n  // HP_PRISM_SINGEDGE_V12  vertical edges 1-4 and 2-5 are singular \n  int refprism_singedge_v12_splitedges[][3] =\n    {\n      { 1, 2, 7 },\n      { 1, 3, 8 },\n      { 2, 1, 9 },\n      { 2, 3, 10 },\n      { 4, 5, 11 },\n      { 4, 6, 12 },\n      { 5, 4, 13 },\n      { 5, 6, 14},\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_singedge_v12_newelstypes[] =\n    {\n      HP_HEX,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_singedge_v12_newels[][8] =\n    {\n      { 7, 9, 10, 8, 11, 13, 14, 12 },\n      { 1, 7, 8, 4, 11, 12 },\n      { 2, 10, 9, 5, 14, 13 },\n      { 3, 8, 10, 6, 12, 14 },\n    };\n  HPRef_Struct refprism_singedge_v12 =\n    {\n      HP_PRISM,\n      refprism_singedge_v12_splitedges, \n      0, 0,\n      refprism_singedge_v12_newelstypes, \n      refprism_singedge_v12_newels\n    };\n\n\n\n\n\n\n  // HP_PRISM_SINGEDGE_H12\n  int refprism_singedge_h12_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 1, 8 },\n      { 2, 3, 9 },\n      { 3, 1, 10 },\n\n      { 4, 6, 12 },\n      { 5, 4, 13 },\n      { 5, 6, 14 },\n      { 6, 4, 15 },\n\n      { 0, 0, 0 }\n    };\n\n  int refprism_singedge_h12_splitfaces[][4] =\n    {\n      { 2, 1, 3, 11 },\n      { 5, 4, 6, 16 },\n      { 0, 0, 0, 0 },\n    };\n\n  HPREF_ELEMENT_TYPE refprism_singedge_h12_newelstypes[] =\n    {\n      HP_HEX,\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_singedge_h12_newels[][8] =\n    {\n      { 1, 8, 11, 7, 4, 13, 16, 12 },\n      { 9, 3, 10, 11, 14, 6, 15, 16 },\n      { 7, 11, 10, 12, 16, 15 },\n      { 2, 9, 11, 5, 14, 16 },\n      { 8, 2, 11, 13, 5, 16 }\n    };\n  HPRef_Struct refprism_singedge_h12 =\n    {\n      HP_PRISM,\n      refprism_singedge_h12_splitedges, \n      refprism_singedge_h12_splitfaces, \n      0,\n      refprism_singedge_h12_newelstypes, \n      refprism_singedge_h12_newels\n    };\n\n\n\n\n\n\n  // HP_PRISM_SINGEDGE_H1\n  int refprism_singedge_h1_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 4, 6, 9 },\n      { 5, 6, 10 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_singedge_h1_newelstypes[] =\n    {\n      HP_HEX,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_singedge_h1_newels[][8] =\n    {\n      { 1, 2, 8, 7, 4, 5, 10, 9 },\n      { 3, 7, 8, 6, 9, 10 }\n    };\n  HPRef_Struct refprism_singedge_h1 =\n    {\n      HP_PRISM,\n      refprism_singedge_h1_splitedges, \n      0, 0,\n      refprism_singedge_h1_newelstypes, \n      refprism_singedge_h1_newels\n    };\n\n\n\n//  HP_PRISM_1FA_0E_0V\n  int refprism_1fa_0e_0v_splitedges[][3] =\n    {\n      { 1, 4, 16 },\n      { 2, 5, 17 },\n      { 3, 6, 18 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fa_0e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_0e_0v_newels[][8] =\n    {\n      { 16, 17, 18, 4, 5, 6 },      \n      { 1, 2, 3, 16, 17, 18 }\n    };\n  HPRef_Struct refprism_1fa_0e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_0e_0v_splitedges, \n      0, 0,\n      refprism_1fa_0e_0v_newelstypes, \n      refprism_1fa_0e_0v_newels\n    };\n\n//  HP_PRISM_1FA_1E_0V\n  int refprism_1fa_1e_0v_splitedges[][3] =\n    {\n      { 1, 4, 16 },\n      { 2, 5, 17 },\n      { 3, 6, 18 },\n      { 1, 2, 7},\n      { 1, 3, 12},\n      { 4, 6, 45},\n      { 4, 5, 40},\n      { 0, 0, 0 }\n    };\n  int refprism_1fa_1e_0v_splitfaces[][4] =\n    {\n      {1,2,4,19},\n      {1,3,4,24},\n      {0,0,0,0}\n    }; \n\n  HPREF_ELEMENT_TYPE refprism_1fa_1e_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE,\n      HP_HEX,\n      HP_PRISM_1FA_1E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_1e_0v_newels[][8] =\n    {\n      { 16, 19, 24, 4, 40, 45 }, \n      { 24, 19,  17, 18, 45 , 40, 5, 6 }, \n      { 1, 7 , 12 , 16, 19, 24 }, \n      { 7, 2, 3, 12,  19, 17, 18, 24 }\n    };\n  HPRef_Struct refprism_1fa_1e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1e_0v_splitedges, \n      refprism_1fa_1e_0v_splitfaces, \n      0,\n      refprism_1fa_1e_0v_newelstypes, \n      refprism_1fa_1e_0v_newels\n    };\n\n//  HP_PRISM_2FA_1E_0V\n  int refprism_2fa_1e_0v_splitedges[][3] =\n    {\n      { 1, 4, 16 },\n      { 2, 5, 17 },\n      { 3, 6, 18 },\n      { 1, 2, 7}, \n      { 1, 3, 12},\n      { 4, 6, 45},\n      { 4, 5, 40},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 0, 0, 0 }\n    };\n  int refprism_2fa_1e_0v_splitfaces[][4] =\n    {\n      {1,2,4,19},\n      {1,3,4,24},\n      {4,1,5,31},\n      {4,1,6,36},\n      {0,0,0,0}\n    }; \n\n  HPREF_ELEMENT_TYPE refprism_2fa_1e_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE,\n      HP_HEX,\n      HP_PRISM_1FA_1E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_NONE,\n    };\n  int refprism_2fa_1e_0v_newels[][8] =\n    {\n      { 16, 19, 24, 28, 31, 36 }, \n      { 24, 19,  17, 18, 36, 31, 29, 30 }, \n      { 1, 7 , 12 , 16, 19, 24 }, \n      { 12, 7, 2, 3, 24, 19, 17, 18 },\n      { 4, 45, 40, 28, 36, 31 }, \n      { 40, 45, 6, 5, 31, 36, 30, 29,}\n    };\n  HPRef_Struct refprism_2fa_1e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1e_0v_splitedges, \n      refprism_2fa_1e_0v_splitfaces,\n      0,\n      refprism_2fa_1e_0v_newelstypes, \n      refprism_2fa_1e_0v_newels\n    };\n\n//  HP_PRISM_1FB_0E_0V   ... quad face 1-2-4-5\n  int refprism_1fb_0e_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 4, 6, 9 },\n      { 5, 6, 10 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_0e_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_1fb_0e_0v_newels[][8] =\n    {\n      { 1, 4, 5, 2, 7, 9, 10, 8  },\n      { 7, 8, 3, 9, 10, 6 }\n    };\n  HPRef_Struct refprism_1fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_0e_0v_splitedges, \n\n      0, 0,\n      refprism_1fb_0e_0v_newelstypes, \n      refprism_1fb_0e_0v_newels\n    };\n\n\n//  HP_PRISM_1FB_1EA_0V   ... quad face 1-2-4-5, edge is 1-4\n  int refprism_1fb_1ea_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 4, 6, 9 },\n      { 5, 6, 10 },\n      { 1, 2, 11 },\n      { 4, 5, 12 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_1ea_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_1fb_1ea_0v_newels[][8] =\n    {\n      { 11, 12, 5, 2, 7, 9, 10, 8  },\n      { 1, 11, 7, 4, 12, 9 },\n      { 7, 8, 3, 9, 10, 6 }\n    };\n  HPRef_Struct refprism_1fb_1ea_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_1ea_0v_splitedges, \n      0, 0,\n      refprism_1fb_1ea_0v_newelstypes, \n      refprism_1fb_1ea_0v_newels\n    };\n\n//  HP_PRISM_1FB_1EC_0V   ... quad face 1-2-4-5 with singular edge 3-6 \n  int refprism_1fb_1ec_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_NONE,\n    };\n  int refprism_1fb_1ec_0v_newels[][8] =\n    {\n      { 3, 11, 10, 6, 44, 43},\n      { 12, 9, 10, 11, 45, 42, 43, 44}, \n      { 4, 5, 2, 1, 45, 42, 9, 12 } \n    };\n  HPRef_Struct refprism_1fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_1ec_0v_splitedges, \n      0, 0,\n      refprism_1fb_1ec_0v_newelstypes, \n      refprism_1fb_1ec_0v_newels\n    };\n\n//  HP_PRISM_1FA_1FB_1EC_0V   ... bot-trig face, quad face 1-2-4-5 with singular edge 3-6 \n  int refprism_1fa_1fb_1ec_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      { 0, 0, 0 }\n    };\n\n int refprism_1fa_1fb_1ec_0v_splitfaces[][4] =\n   {\n     {2,3,5,21},\n     {3,2,6,22},\n     {3,1,6,23},\n     {1,3,4,24},\n     {0,0,0,0}\n   }; \n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_1fb_1ec_0v_newels[][8] =\n    {\n      { 18, 23, 22, 6, 44, 43},\n      { 24, 21, 22, 23, 45, 42, 43, 44}, \n      { 4, 5, 17, 16, 45, 42, 21, 24}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 12, 9, 10, 11, 24, 21, 22, 23},\n      { 1, 2, 9, 12, 16, 17, 21, 24}\n    };\n  HPRef_Struct refprism_1fa_1fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_1ec_0v_splitedges,\n      refprism_1fa_1fb_1ec_0v_splitfaces, 0,\n      refprism_1fa_1fb_1ec_0v_newelstypes, \n      refprism_1fa_1fb_1ec_0v_newels\n    };\n\n\n//  HP_PRISM_1FA_1FB_2EB_0V  \n  int refprism_1fa_1fb_2eb_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      { 4, 5, 40},\n      { 4, 6, 45},\n      { 1, 2, 7},\n      { 0, 0, 0 }\n    };\n\n int refprism_1fa_1fb_2eb_0v_splitfaces[][4] =\n   {\n     {2,3,5,21},\n     {3,2,6,22},\n     {3,1,6,23},\n     {1,3,4,24},\n     {1,2,4,19},\n     {0,0,0,0}\n   }; \n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_2eb_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_NONE,\n    };\n  int refprism_1fa_1fb_2eb_0v_newels[][8] =\n    {\n      { 18, 23, 22, 6, 44, 43},\n      { 24, 21, 22, 23, 45, 42, 43, 44}, \n      { 40, 5, 17, 19, 45, 42, 21, 24}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 12, 9, 10, 11, 24, 21, 22, 23},\n      { 7, 2, 9, 12, 19, 17, 21, 24},\n      {16,19,24,4,40,45},\n      {1,7,12,16,19,24}\n    };\n  HPRef_Struct refprism_1fa_1fb_2eb_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_2eb_0v_splitedges, \n      refprism_1fa_1fb_2eb_0v_splitfaces, 0,\n      refprism_1fa_1fb_2eb_0v_newelstypes, \n      refprism_1fa_1fb_2eb_0v_newels\n    };\n\n //  HP_PRISM_1FA_1FB_2EC_0V \n  int refprism_1fa_1fb_2ec_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,4,41},\n      {2,1,8},\n      { 0, 0, 0 }\n    };\n\n int refprism_1fa_1fb_2ec_0v_splitfaces[][4] =\n   {\n     {2,3,5,21},\n     {3,2,6,22},\n     {3,1,6,23},\n     {1,3,4,24},\n     {2,1,5,20},\n     {0,0,0,0}\n   }; \n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ec_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_1fb_2ec_0v_newels[][8] =\n    {\n      { 18, 23, 22, 6, 44, 43},\n      { 24, 21, 22, 23, 45, 42, 43, 44}, \n      { 4, 41, 20, 16, 45, 42, 21, 24}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 12, 9, 10, 11, 24, 21, 22, 23},\n      { 1, 8, 9, 12, 16, 20, 21, 24}, \n      {8,2,9,20,17,21}, \n      {5,41,42,17,20,21}\n    };\n  HPRef_Struct refprism_1fa_1fb_2ec_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_2ec_0v_splitedges, \n      refprism_1fa_1fb_2ec_0v_splitfaces,\n      0,\n      refprism_1fa_1fb_2ec_0v_newelstypes, \n      refprism_1fa_1fb_2ec_0v_newels\n    };\n\n\n\n\n\n\n\n//  HP_PRISM_2FA_1FB_1EC_0V   ... trig faces, quad face 1-2-4-5 with singular edge 3-6 \n  int refprism_2fa_1fb_1ec_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 0, 0, 0 }\n    };\n\n int refprism_2fa_1fb_1ec_0v_splitfaces[][4] =\n   {\n     {2,3,5,21},\n     {3,2,6,22},\n     {3,1,6,23},\n     {1,3,4,24},\n     {5,2,6,33},\n     {6,5,3,34},\n     {6,4,3,35},\n     {4,1,6,36},\n     {0,0,0,0}\n   }; \n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_NONE,\n    };\n  int refprism_2fa_1fb_1ec_0v_newels[][8] =\n    {\n      { 18, 23, 22, 30, 35, 34},\n      { 24, 21, 22, 23, 36, 33, 34, 35}, \n      { 28, 29, 17, 16, 36, 33, 21, 24}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 12, 9, 10, 11, 24, 21, 22, 23},\n      { 1, 2, 9, 12, 16, 17, 21, 24},\n      { 6, 43, 44, 30, 34, 35},\n      { 44, 43, 42, 45, 35, 34, 33, 36}, \n      { 5, 4, 45, 42, 29, 28, 36, 33 }, \n    };\n  HPRef_Struct refprism_2fa_1fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_1ec_0v_splitedges, \n      refprism_2fa_1fb_1ec_0v_splitfaces,\n      0,\n      refprism_2fa_1fb_1ec_0v_newelstypes, \n      refprism_2fa_1fb_1ec_0v_newels\n    };\n\n//  HP_PRISM_2FA_1FB_2EB_0V  \n  int refprism_2fa_1fb_2eb_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {3,2,10},\n      {3,1,11},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      {4,5,40},\n      {1,2,7},\n      { 0, 0, 0 }\n    };\n\n int refprism_2fa_1fb_2eb_0v_splitfaces[][4] =\n   {\n     {2,3,5,21},\n     {3,2,6,22},\n     {3,1,6,23},\n     {1,3,4,24},\n     {5,6,2,33},\n     {6,5,3,34},\n     {6,4,3,35},\n     {4,1,6,36},\n     {4,1,5,31},\n     {1,2,4,19},\n     {0,0,0,0}\n   }; \n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_2eb_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE, \n      HP_HEX, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_NONE,\n    };\n  int refprism_2fa_1fb_2eb_0v_newels[][8] =\n    {\n      { 18, 23, 22, 30, 35, 34},\n      { 24, 21, 22, 23, 36, 33, 34, 35}, \n      { 31, 29, 17, 19, 36, 33, 21, 24}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 12, 9, 10, 11, 24, 21, 22, 23},\n      { 7, 2, 9, 12, 19, 17, 21, 24},\n      { 6, 43, 44, 30, 34, 35},\n      { 44, 43, 42, 45, 35, 34, 33, 36}, \n      { 5, 40, 45, 42, 29, 31, 36, 33 }, \n      { 1, 7, 12, 16, 19, 24 }, \n      { 16, 19, 24, 28, 31, 36 }, \n      { 40, 4, 45, 31, 28, 36 }, \n    };\n  HPRef_Struct refprism_2fa_1fb_2eb_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_2eb_0v_splitedges, \n      refprism_2fa_1fb_2eb_0v_splitfaces, 0,\n      refprism_2fa_1fb_2eb_0v_newelstypes, \n      refprism_2fa_1fb_2eb_0v_newels\n    };\n\n//  HP_PRISM_1FB_2EA_0V   ... quad face 1-2-4-5 with singular edges 1-4, 2-5\n  int refprism_1fb_2ea_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 1, 2, 9 }, \n      { 2, 1, 10 }, \n      { 4, 6, 11 }, \n      { 5, 6, 12 }, \n      { 4, 5, 13 }, \n      { 5, 4, 14 }, \n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_2ea_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_PRISM_1FB_1EA_0V,\n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_NONE,\n    };\n  int refprism_1fb_2ea_0v_newels[][8] =\n    {\n      { 7, 8, 3, 11, 12, 6 }, \n      { 1, 9, 7, 4, 13, 11 }, \n      { 13, 14, 10, 9, 11, 12, 8, 7 }, \n      { 5, 14, 12, 2, 10, 8 }, \n    };\n  HPRef_Struct refprism_1fb_2ea_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_2ea_0v_splitedges, \n      0, 0,\n      refprism_1fb_2ea_0v_newelstypes, \n      refprism_1fb_2ea_0v_newels\n    };\n\n//  HP_PRISM_1FB_2EB_0V   ... quad face 1-2-4-5 with singular edges 1-4, 3-6 \n  int refprism_1fb_2eb_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 4, 5, 40},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nHPREF_ELEMENT_TYPE refprism_1fb_2eb_0v_newelstypes[] =\n    {\n      HP_PRISM_SINGEDGE,\n      HP_HEX, \n      HP_PRISM_1FB_1EA_0V, \n      HP_HEX_1F_0E_0V, \n      HP_NONE,\n    };\n  int refprism_1fb_2eb_0v_newels[][8] =\n    {\n      { 3, 11, 10, 6, 44, 43 },  \n      { 12, 9, 10, 11, 45, 42, 43, 44}, \n      { 1, 7, 12, 4, 40, 45}, \n      { 40, 5, 2, 7, 45, 42, 9, 12}\n    };\n  HPRef_Struct refprism_1fb_2eb_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_2eb_0v_splitedges, \n      0, 0,\n      refprism_1fb_2eb_0v_newelstypes, \n      refprism_1fb_2eb_0v_newels\n    };\n\n//  HP_PRISM_1FB_3E_0V   ... quad face 1-2-4-5 with singular edges 1-4, 3-6\n  int refprism_1fb_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_3e_0v_newelstypes[] =\n    { \n      HP_PRISM_SINGEDGE,\n      HP_HEX, \n      HP_PRISM_1FB_1EA_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_NONE,\n    };\n  int refprism_1fb_3e_0v_newels[][8] =\n    {\n      { 3, 11, 10, 6, 44, 43 }, \n      { 12, 9, 10, 11, 45, 42, 43, 44}, \n      { 1, 7, 12, 4, 40, 45 }, \n      { 40, 41, 8, 7, 45, 42, 9, 12}, \n      { 5, 41, 42, 2, 8, 9}, \n    };\n  HPRef_Struct refprism_1fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_3e_0v_splitedges, \n      0, 0,\n      refprism_1fb_3e_0v_newelstypes, \n      refprism_1fb_3e_0v_newels\n    };\n\n\n\n//  HP_PRISM_2FB    ... quad face 1-2-4-5 and quad face 1-4-6-3\n  int refprism_2fb_0e_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 1, 2, 9 }, \n      { 3, 2, 10 }, \n      { 4, 6, 11 },\n      { 5, 6, 12 },\n      { 4, 5, 13 },\n      { 6, 5, 14 },\n      { 0, 0, 0 }\n    };\n int refprism_2fb_0e_0v_splitfaces[][4] =\n    {\n      { 1, 2, 3, 15 },\n      { 4, 5, 6, 16 },\n      { 0, 0, 0, 0 },\n    };\n  HPREF_ELEMENT_TYPE refprism_2fb_0e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_NONE,\n    };\n  int refprism_2fb_0e_0v_newels[][8] =\n    {\n      { 15, 8, 10, 16, 12, 14 }, \n      { 13, 5, 2, 9, 16, 12, 8, 15}, \n      { 11, 7, 3, 6, 16, 15, 10, 14 }, \n      { 1, 9, 15, 4, 13, 16 }, \n      { 4, 11, 16, 1,7, 15 }\n    };\n  HPRef_Struct refprism_2fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_2fb_0e_0v_splitedges, \n      refprism_2fb_0e_0v_splitfaces,\n      0,\n      refprism_2fb_0e_0v_newelstypes, \n      refprism_2fb_0e_0v_newels\n    };\n\n//  HP_PRISM_2FB    ... quad face 1-2-4-5 and quad face 1-4-6-3 and sing edge 3-6\n  int refprism_2fb_1ec_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 1, 2, 9 }, \n      { 3, 2, 10 }, \n      { 4, 6, 11 },\n      { 5, 6, 12 },\n      { 4, 5, 13 },\n      { 6, 5, 14 },\n      { 3, 1, 17},\n      { 6, 4, 18}, \n      { 0, 0, 0 }\n    };\n int refprism_2fb_1ec_0v_splitfaces[][4] =\n    {\n      { 1, 2, 3, 15 },\n      { 4, 5, 6, 16 },\n      { 0, 0, 0, 0 },\n    };\n  HPREF_ELEMENT_TYPE refprism_2fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_NONE,\n    };\n  int refprism_2fb_1ec_0v_newels[][8] =\n    {\n      { 15, 8, 10, 16, 12, 14 }, \n      { 13, 5, 2, 9, 16, 12, 8, 15}, \n      { 11, 7, 17, 18, 16, 15, 10, 14 }, \n      { 1, 9, 15, 4, 13, 16 }, \n      { 4, 11, 16, 1,7, 15 }, \n      { 3, 17, 10, 6, 18, 14 } \n    };\n  HPRef_Struct refprism_2fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_2fb_1ec_0v_splitedges, \n      refprism_2fb_1ec_0v_splitfaces,\n      0,\n      refprism_2fb_1ec_0v_newelstypes, \n      refprism_2fb_1ec_0v_newels\n    };\n\n\n\n//  HP_PRISM_2FB    ... quad face 1-2-4-5 and quad face 1-4-6-3 and 3 sing edges\n  int refprism_2fb_3e_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 1, 2, 9 }, \n      { 3, 2, 10 }, \n      { 4, 6, 11 },\n      { 5, 6, 12 },\n      { 4, 5, 13 },\n      { 6, 5, 14 },\n      { 3, 1, 17},\n      { 6, 4, 18}, \n      { 2, 1, 19},\n      { 5, 4, 20}, \n      { 0, 0, 0 }\n    };\n int refprism_2fb_3e_0v_splitfaces[][4] =\n    {\n      { 1, 2, 3, 15 },\n      { 4, 5, 6, 16 },\n      { 0, 0, 0, 0 },\n    };\n  HPREF_ELEMENT_TYPE refprism_2fb_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_NONE,\n    };\n  int refprism_2fb_3e_0v_newels[][8] =\n    {\n      { 15, 8, 10, 16, 12, 14 }, \n      { 13, 20, 19, 9, 16, 12, 8, 15}, \n      { 11, 7, 17, 18, 16, 15, 10, 14 }, \n      { 1, 9, 15, 4, 13, 16 }, \n      { 4, 11, 16, 1,7, 15 }, \n      { 3, 17, 10, 6, 18, 14 }, \n      { 5, 20, 12, 2, 19, 8 }\n    };\n  HPRef_Struct refprism_2fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_2fb_3e_0v_splitedges, \n      refprism_2fb_3e_0v_splitfaces, 0,\n      refprism_2fb_3e_0v_newelstypes, \n      refprism_2fb_3e_0v_newels\n    };\n\n\n\n//  HP_PRISM_1FA_1FB_0E_0V   ... quad face 1-2-4-5 and trig face 1-2-3\n  int refprism_1fa_1fb_0e_0v_splitedges[][3] = \n    {\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {2,3,9},\n      {1,3,12},\n      {5,6,42},\n      {4,6,45},\n      {0,0,0}\n    };\n  int refprism_1fa_1fb_0e_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      { 0, 0, 0, 0 }\n    };\n\nHPREF_ELEMENT_TYPE refprism_1fa_1fb_0e_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_1fb_0e_0v_newels[][8] =\n    {\n      { 24, 21, 18, 45, 42, 6 }, \n      { 4, 5, 17, 16, 45, 42, 21, 24 },\n      { 12, 9, 3, 24, 21, 18 }, \n      { 1, 2, 9, 12, 16, 17, 21, 24 } \n    };\n  HPRef_Struct refprism_1fa_1fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_0e_0v_splitedges, \n\n      refprism_1fa_1fb_0e_0v_splitfaces, 0,\n      refprism_1fa_1fb_0e_0v_newelstypes, \n      refprism_1fa_1fb_0e_0v_newels\n    };\n\n/*\n//  HP_PRISM_1FA_1FB_1EC_0V   ... quad face 1-2-4-5 and trig face 1-2-3\nint refprism_1fa_1fb_1ec_0v_splitedges[][3] =\n    {\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {2,3,9},\n      {1,3,12},\n      {5,6,42},\n      {4,6,45},\n      {6,5,43},\n      {6,4,44},\n      {3,2,10},\n      {3,1,11},\n      {0,0,0}\n    };\n  int refprism_1fa_1fb_1ec_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      { 0, 0, 0, 0 }\n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_1FA_1E_0V, \n      HP_PRISM_\n      HP_NONE,\n    };\n  int refprism_1fa_1fb_0e_0v_newels[][8] =\n    {\n      { 24, 21, 18, 45, 42, 6 }, \n      { 4, 5, 17, 16, 45, 42, 21, 24 },\n      { 12, 9, 3, 24, 21, 18 }, \n      { 1, 2, 9, 12, 16, 17, 21, 24 } \n    };\n  HPRef_Struct refprism_1fa_1fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_1ec_0v_splitedges, \n\n      refprism_1fa_1fb_1ec_0v_splitfaces, 0,\n      refprism_1fa_1fb_1ec_0v_newelstypes, \n      refprism_1fa_1fb_1ec_0v_newels\n    };\n\n\n*/\n\n\n\n\n//  HP_PRISM_2FA_1FB_0E_0V   ... quad face 1-2-4-5 and trig face 1-2-3 \n  int refprism_2fa_1fb_0e_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {4,1,28},\n      {5,2,29},\n      {6,3,30},\n      {0,0,0}\n      \n    };\n  int refprism_2fa_1fb_0e_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {5,6,2,33},\n      {4,1,6,36},\n      {0,0,0,0}\n    };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_0e_0v_newelstypes[] =\n    {  \n      HP_HEX_1F_0E_0V,\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_NONE,\n    };\n  int refprism_2fa_1fb_0e_0v_newels[][8] =\n    {\n      {28,29,17,16,36,33,21,24}, \n      {24,21,18, 36, 33, 30}, \n      {12,9,3,24,21,18},\n      {1,2,9,12,16,17,21,24}, \n      {6,42,45,30,33,36},\n      {4,5,29,28,45,42,33,36}\n    };\n  HPRef_Struct refprism_2fa_1fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_0e_0v_splitedges, \n\n      refprism_2fa_1fb_0e_0v_splitfaces, 0,\n      refprism_2fa_1fb_0e_0v_newelstypes, \n      refprism_2fa_1fb_0e_0v_newels\n    };\n\n\n//  HP_PRISM_1FA_1FB_1EA_0V   ... quad face 1-2-4-5 and trig face 1-2-3 \n  int refprism_1fa_1fb_1ea_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {4,5,40},\n      {1,2,7},\n      {0,0,0}, \n    };\n  int refprism_1fa_1fb_1ea_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {1,2,4,19},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ea_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_NONE\n    };\n  int refprism_1fa_1fb_1ea_0v_newels[][8] =\n    {\n      {40,5,17,19,45,42,21,24}, \n      {24,21,18,45,42,6},\n      {12,9,3,24,21,18},\n      {7,2,9,12,19,17,21,24}, \n      {16,19,24,4,40,45},\n      {1,7,12,16,19,24}\n      \n    };\n  HPRef_Struct refprism_1fa_1fb_1ea_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_1ea_0v_splitedges, \n      refprism_1fa_1fb_1ea_0v_splitfaces, 0,\n      refprism_1fa_1fb_1ea_0v_newelstypes, \n      refprism_1fa_1fb_1ea_0v_newels\n    };\n\n//  HP_PRISM_2FA_1FB_1EA_0V   \n  int refprism_2fa_1fb_1ea_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {4,1,28},\n      {5,2,29},\n      {6,3,30},\n      {4,5,40},\n      {1,2,7},\n      {0,0,0}, \n    };\n  int refprism_2fa_1fb_1ea_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {1,2,4,19},\n      {4,1,6,36},\n      {4,1,5,31},\n      {5,6,2,33},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ea_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_NONE\n    };\n  int refprism_2fa_1fb_1ea_0v_newels[][8] =\n    {\n      { 18, 24, 21, 30, 36, 33}, \n      { 31, 29, 17, 19, 36, 33, 21, 24}, \n      { 16,19, 24, 28, 31, 36 }, \n      { 3, 12, 9, 18, 24, 21 }, \n      { 7, 2, 9, 12, 19, 17, 21, 24},  \n      { 1, 7, 12, 16, 19, 24 }, \n      { 6, 42, 45, 30, 33, 36 }, \n      { 40, 5, 29, 31, 45, 42, 33, 36 },\n      { 40, 4, 45, 31, 28, 36} \n    };\n  HPRef_Struct refprism_2fa_1fb_1ea_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_1ea_0v_splitedges, \n      refprism_2fa_1fb_1ea_0v_splitfaces, 0,\n      refprism_2fa_1fb_1ea_0v_newelstypes, \n      refprism_2fa_1fb_1ea_0v_newels\n    };\n\n\n//  HP_PRISM_2FA_1FB_2EA_0V   \n  int refprism_2fa_1fb_2ea_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {4,1,28},\n      {5,2,29},\n      {6,3,30},\n      {4,5,40},\n      {1,2,7},\n      { 5, 4, 41},\n      { 2, 1, 8},\n      {0,0,0}, \n    };\n  int refprism_2fa_1fb_2ea_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {1,2,4,19},\n      {4,1,6,36},\n      {4,1,5,31},\n      {5,6,2,33},\n      {5,4,2,32},\n      {2,1,5,20},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_2ea_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_NONE\n    };\n  int refprism_2fa_1fb_2ea_0v_newels[][8] =\n    {\n      { 18, 24, 21, 30, 36, 33}, \n      { 31, 32, 20, 19, 36, 33, 21, 24}, \n      { 16,19, 24, 28, 31, 36 }, \n      { 3, 12, 9, 18, 24, 21 }, \n      {7,8,9,12,19,20,21,24},\n      { 1, 7, 12, 16, 19, 24 }, \n      { 6, 42, 45, 30, 33, 36 }, \n      { 40, 41, 32, 31, 45, 42, 33, 36}, \n      { 40, 4, 45, 31, 28, 36}, \n      { 8, 2, 9, 20, 17, 21 },  \n      { 29, 32, 33, 17, 20, 21 }, \n      { 5, 41, 42, 29, 32, 33 }, \n    };\n  HPRef_Struct refprism_2fa_1fb_2ea_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_2ea_0v_splitedges, \n      refprism_2fa_1fb_2ea_0v_splitfaces, 0,\n      refprism_2fa_1fb_2ea_0v_newelstypes, \n      refprism_2fa_1fb_2ea_0v_newels\n    };\n\n//  HP_PRISM_2FA_1FB_3E_0V   \n  int refprism_2fa_1fb_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      {0,0,0}, \n    };\n  int refprism_2fa_1fb_3e_0v_splitfaces[][4] = \n    {\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,1,5,31},\n      {5,4,2,32},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_1fb_3e_0v_newelstypes[] =\n    {\n      HP_HEX,\n      HP_PRISM_SINGEDGE,\n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FB_1EA_0V, \n\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_HEX_1FA_1FB_0E_0V,\n      \n      HP_NONE\n    };\n  int refprism_2fa_1fb_3e_0v_newels[][8] =\n    {\n      {24, 21, 22, 23, 36, 33, 34, 35},\n      {18, 23, 22, 30, 35, 34}, \n      { 31, 32, 20, 19, 36, 33, 21, 24}, \n      { 16,19, 24, 28, 31, 36 }, \n      { 29, 32, 33, 17, 20, 21},\n      \n      \n      { 12, 9,10,11, 24, 21, 22, 23 }, \n      { 3, 11, 10, 18,23,22}, \n      { 1, 7, 12 , 16, 19, 24}, \n      { 8,2,9, 20, 17,21}, \n      { 7,8,9,12,19, 20, 21, 24}, \n      \n      { 44, 43, 42, 45, 35, 34, 33, 36}, \n      { 6, 43, 44, 30, 34, 35}, \n      { 40, 4, 45, 31,28, 36}, \n      { 5, 41,42, 29, 32, 33},  \n      { 40, 41, 32, 31, 45, 42, 33, 36}, \n    };\n  HPRef_Struct refprism_2fa_1fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_1fb_3e_0v_splitedges, \n\n      refprism_2fa_1fb_3e_0v_splitfaces, 0,\n      refprism_2fa_1fb_3e_0v_newelstypes, \n      refprism_2fa_1fb_3e_0v_newels\n    };\n\n\n\n\n//  HP_PRISM_1FA_1FB_1EB_0V   ... quad face 1-2-4-5 and trig face 1-2-3 \n  int refprism_1fa_1fb_1eb_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {5,4,41},\n      {2,1,8},\n      {0,0,0}, \n    };\n  int refprism_1fa_1fb_1eb_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {2,1,5,20},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_1eb_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V ,\n      HP_NONE\n    };\n  int refprism_1fa_1fb_1eb_0v_newels[][8] =\n    {\n      {4,41,20,16,45,42,21,24}, \n      {24,21,18,45,42,6},\n      {12,9,3,24,21,18},\n      {1,8,9,12,16,20,21,24},\n      {5,41,42,17,20,21},\n      {8,2,9,20,17,21}\n    };\n  HPRef_Struct refprism_1fa_1fb_1eb_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_1eb_0v_splitedges, \n\n       refprism_1fa_1fb_1eb_0v_splitfaces, 0,\n      refprism_1fa_1fb_1eb_0v_newelstypes, \n      refprism_1fa_1fb_1eb_0v_newels\n    };\n\n\n//  HP_PRISM_1FA_1FB_2EA_0V   ... quad face 1-2-4-5 and trig face 1-2-3 \n  int refprism_1fa_1fb_2ea_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {5,4,41},\n      {2,1,8},\n      {4,5,40},\n      {1,2,7},\n      {0,0,0},\n\n    };\n  int refprism_1fa_1fb_2ea_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {2,1,5,20},\n      {1,2,4,19},\n      {0,0,0,0},\n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ea_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V ,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_NONE\n    };\n  int refprism_1fa_1fb_2ea_0v_newels[][8] =\n    {\n      {40,41,20,19,45,42,21,24}, \n      {24,21,18,45,42,6},\n      {12,9,3,24,21,18},\n      {7,8,9,12,19,20,21,24},\n      {5,41,42,17,20,21},\n      {8,2,9,20,17,21},\n      {16,19,24,4,40,45},\n      {1,7,12,16,19,24}\n    };\n  HPRef_Struct refprism_1fa_1fb_2ea_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_2ea_0v_splitedges, \n\n      refprism_1fa_1fb_2ea_0v_splitfaces, 0,\n      refprism_1fa_1fb_2ea_0v_newelstypes, \n      refprism_1fa_1fb_2ea_0v_newels\n    };\n\n\n//  HP_PRISM_1FA_1FB_3E_0V   \n  int refprism_1fa_1fb_3e_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {5,4,41},\n      {2,1,8},\n      {4,5,40},\n      {1,2,7},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      {0,0,0},\n\n    };\n  int refprism_1fa_1fb_3e_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {2,1,5,20},\n      {1,2,4,19},\n      {3,2,6,22},\n      {3,1,6,23},\n      {0,0,0,0},\n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_1fb_3e_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_HEX,\n      HP_PRISM_SINGEDGE,\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V ,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_NONE\n    };\n  int refprism_1fa_1fb_3e_0v_newels[][8] =\n    {\n      {40,41,20,19,45,42,21,24}, \n      {24, 21, 22, 23, 45, 42, 43, 44},\n      {18, 23, 22, 6, 44, 43}, \n      {12, 9, 10, 11, 24, 21, 22, 23}, \n      {3, 11, 10, 18, 23, 22}, \n      {7,8,9,12,19,20,21,24},\n      {5,41,42,17,20,21},\n      {8,2,9,20,17,21},\n      {16,19,24,4,40,45},\n      {1,7,12,16,19,24}\n    };\n  HPRef_Struct refprism_1fa_1fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_1fb_3e_0v_splitedges, \n\n      refprism_1fa_1fb_3e_0v_splitfaces, 0,\n      refprism_1fa_1fb_3e_0v_newelstypes, \n      refprism_1fa_1fb_3e_0v_newels\n    };\n\n\n\n\n\n\n\n\n//  HP_PRISM_2FA_0E_0V  singular trig faces\n  int refprism_2fa_0e_0v_splitedges[][3] =\n    {\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {4,1,28},\n      {5,2,29},\n      {6,3,30},\n      {0,0,0}\n    };\n  \nHPREF_ELEMENT_TYPE refprism_2fa_0e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_NONE\n    };\n  int refprism_2fa_0e_0v_newels[][8] =\n    {\n      {16,17,18,28,29,30},\n      {1,2,3,16,17,18},\n      {4,6,5,28,30,29}, \n    };\n\nHPRef_Struct refprism_2fa_0e_0v = \n\n    {\n      HP_PRISM,\n      refprism_2fa_0e_0v_splitedges, \n      0, 0,\n      refprism_2fa_0e_0v_newelstypes, \n      refprism_2fa_0e_0v_newels\n    };\n\n\n\n\n\n//  HP_PRISM_1FA_2FB    ... quad face 1-2-4-5 and quad face 1-4-6-3\nint refprism_1fa_2fb_0e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_1fa_2fb_0e_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,3,5,21},\n      {3,2,6,22},\n      {1,3,4,24},\n      {4,5,6,46},\n      { 0, 0, 0, 0 }\n    };\nint refprism_1fa_2fb_0e_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_1fa_2fb_0e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_NONE,\n    };\n  int refprism_1fa_2fb_0e_0v_newels[][8] =\n    {\n      { 25, 21, 22, 46, 42, 43 }, \n      { 40, 5, 17, 19, 46, 42, 21, 25 }, \n      { 24, 18, 6, 45, 25, 22, 43, 46}, \n      { 16, 19, 25, 4, 40, 46 }, \n      { 4, 45, 46, 16, 24, 25 }, \n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 2, 9, 13, 19, 17, 21, 25 }, \n      { 3, 12, 13, 10, 18, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      { 12, 1, 13, 24, 16, 25 }\n      \n    };\n  HPRef_Struct refprism_1fa_2fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_2fb_0e_0v_splitedges, \n      refprism_1fa_2fb_0e_0v_splitfaces, \n      refprism_1fa_2fb_0e_0v_splitelement, \n      refprism_1fa_2fb_0e_0v_newelstypes, \n      refprism_1fa_2fb_0e_0v_newels\n    };\n\n//  HP_PRISM_1FA_2FB_1EC    ... quad face 1-2-4-5 and quad face 1-4-6-3\nint refprism_1fa_2fb_1ec_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_1fa_2fb_1ec_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},\n      { 0, 0, 0, 0 }\n    };\nint refprism_1fa_2fb_1ec_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_1fa_2fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V, \n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      \n      HP_NONE,\n    };\n  int refprism_1fa_2fb_1ec_0v_newels[][8] =\n    {\n      { 25, 21, 22, 46, 42, 43 }, \n      { 40, 5, 17, 19, 46, 42, 21, 25 }, \n      { 24, 23, 44, 45, 25, 22, 43, 46}, \n      { 16, 19, 25, 4, 40, 46 }, \n      { 4, 45, 46, 16, 24, 25 }, \n      { 18, 23, 22, 6, 44, 43}, \n\n\n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 2, 9, 13, 19, 17, 21, 25 }, \n      { 11, 12, 13, 10, 23, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 10, 18, 23, 22},\n      \n    };\n  HPRef_Struct refprism_1fa_2fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_2fb_1ec_0v_splitedges, \n      refprism_1fa_2fb_1ec_0v_splitfaces, \n      refprism_1fa_2fb_1ec_0v_splitelement, \n      refprism_1fa_2fb_1ec_0v_newelstypes, \n      refprism_1fa_2fb_1ec_0v_newels\n    };\n\n\n//  HP_PRISM_1FA_2FB_3E    ... quad face 1-2-4-5 and quad face 1-4-6-3\nint refprism_1fa_2fb_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_1fa_2fb_3e_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},\n      { 0, 0, 0, 0 }\n    };\nint refprism_1fa_2fb_3e_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_1fa_2fb_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FB_1EA_0V,\n      \n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V,\n      \n      HP_NONE,\n    };\n  int refprism_1fa_2fb_3e_0v_newels[][8] =\n    {\n      { 25, 21, 22, 46, 42, 43 }, \n      { 40, 41, 20, 19, 46, 42, 21, 25 }, \n      { 24, 23, 44, 45, 25, 22, 43, 46}, \n      { 16, 19, 25, 4, 40, 46 }, \n      { 4, 45, 46, 16, 24, 25 }, \n      { 18, 23, 22, 6, 44, 43}, \n      { 5, 41, 42, 17, 20, 21}, \n      \n\n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 8, 9, 13, 19, 20, 21, 25 }, \n      { 11, 12, 13, 10, 23, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 10, 18, 23, 22},\n      { 8, 2, 9, 20, 17, 21}, \n      \n    };\n  HPRef_Struct refprism_1fa_2fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_2fb_3e_0v_splitedges, \n      refprism_1fa_2fb_3e_0v_splitfaces, \n      refprism_1fa_2fb_3e_0v_splitelement, \n      refprism_1fa_2fb_3e_0v_newelstypes, \n      refprism_1fa_2fb_3e_0v_newels\n    };\n\n\n\n\n\n\n\n\n\n//  HP_PRISM_1FA_2FB_1eb    ... quad face 1-2-4-5 and quad face 1-4-6-3\nint refprism_1fa_2fb_1eb_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_1fa_2fb_1eb_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {1,3,4,24},\n      {4,5,6,46},\n      { 0, 0, 0, 0 }\n    };\nint refprism_1fa_2fb_1eb_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {0,0,0,0,0} \n  };\n\n\nHPREF_ELEMENT_TYPE refprism_1fa_2fb_1eb_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V, \n      HP_PRISM_1FB_1EA_0V,\n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EB_0V,\n      \n      HP_NONE,\n    };\n\n  int refprism_1fa_2fb_1eb_0v_newels[][8] =\n    {\n      { 25, 21, 22, 46, 42, 43 }, \n      { 40, 41, 20, 19, 46, 42, 21, 25 }, \n      { 24, 18, 6, 45, 25, 22, 43, 46}, \n      { 16, 19, 25, 4, 40, 46 },\n      { 4, 45, 46, 16, 24, 25 }, \n      { 5, 41, 42, 17, 20, 21 },\n\n\n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 8, 9, 13, 19, 20, 21, 25 }, \n      { 3, 12, 13, 10, 18, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 },  \n      { 12, 1, 13, 24, 16, 25 }, \n      { 8, 2, 9, 20, 17, 21}, \n      \n    };\n  HPRef_Struct refprism_1fa_2fb_1eb_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_2fb_1eb_0v_splitedges, \n      refprism_1fa_2fb_1eb_0v_splitfaces, \n      refprism_1fa_2fb_1eb_0v_splitelement, \n      refprism_1fa_2fb_1eb_0v_newelstypes, \n      refprism_1fa_2fb_1eb_0v_newels\n    };\n\n\n\n\n\n\n//  HP_PRISM_2FA_2FB \nint refprism_2fa_2fb_0e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 4, 6, 45},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 0, 0, 0 }\n    };\nint refprism_2fa_2fb_0e_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,3,5,21},\n      {3,2,6,22},\n      {1,3,4,24},\n      {4,5,6,46},  \n      {4,1,5,31},\n      {5,6,2,33},\n      {6,5,3,34},\n      {4,1,6,36},\n      { 0, 0, 0, 0 }\n    };\nint refprism_2fa_2fb_0e_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {4,1,6,5,37},\n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_2fa_2fb_0e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      \n      HP_NONE,\n    };\n  int refprism_2fa_2fb_0e_0v_newels[][8] =\n    {\n      { 25, 21, 22, 37, 33, 34}, \n      { 31, 29, 17, 19, 37, 33, 21, 25}, \n      { 36, 24, 18, 30, 37, 25, 22, 34}, \n      { 16, 19, 25, 28, 31, 37}, \n      { 28, 36, 37, 16, 24, 25},\n      \n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 2, 9, 13, 19, 17, 21, 25 }, \n      { 3, 12, 13, 10, 18, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      { 12, 1, 13, 24, 16, 25 }, \n\n      {  46, 43, 42 ,37, 34, 33},\n      { 40, 5, 29, 31, 46, 42, 33, 37 }, \n      { 6, 45, 36, 30, 43, 46, 37, 34 }, \n      { 40, 4, 46, 31, 28, 37 }, \n      { 4, 45, 46, 28, 36, 37},  \n      \n    };\n  HPRef_Struct refprism_2fa_2fb_0e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_2fb_0e_0v_splitedges, \n      refprism_2fa_2fb_0e_0v_splitfaces, \n      refprism_2fa_2fb_0e_0v_splitelement, \n      refprism_2fa_2fb_0e_0v_newelstypes, \n      refprism_2fa_2fb_0e_0v_newels\n    };\n\n\n//  HP_PRISM_2FA_2FB_1EC \nint refprism_2fa_2fb_1ec_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_2fa_2fb_1ec_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},  \n      {4,1,5,31},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      { 0, 0, 0, 0 }\n    };\nint refprism_2fa_2fb_1ec_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {4,1,6,5,37},\n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_2fa_2fb_1ec_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V, \n      \n      HP_NONE,\n    };\n  int refprism_2fa_2fb_1ec_0v_newels[][8] =\n    {\n      { 25, 21, 22, 37, 33, 34}, \n      { 31, 29, 17, 19, 37, 33, 21, 25}, \n      { 36, 24, 23, 35, 37, 25, 22, 34}, \n      { 16, 19, 25, 28, 31, 37}, \n      { 28, 36, 37, 16, 24, 25},\n      { 18, 23, 22, 30, 35, 34}, \n            \n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 2, 9, 13, 19, 17, 21, 25 }, \n      { 11, 12, 13, 10, 23, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 10, 18, 23, 22 }, \n\n      { 46, 43, 42 ,37, 34, 33},\n      { 40, 5, 29, 31, 46, 42, 33, 37 }, \n      { 44, 45, 36, 35, 43, 46, 37, 34 }, \n      { 40, 4, 46, 31, 28, 37 }, \n      { 4, 45, 46, 28, 36, 37},  \n      { 44, 6, 43, 35, 30, 34}, \n      \n    };\n  HPRef_Struct refprism_2fa_2fb_1ec_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_2fb_1ec_0v_splitedges, \n      refprism_2fa_2fb_1ec_0v_splitfaces, \n      refprism_2fa_2fb_1ec_0v_splitelement, \n      refprism_2fa_2fb_1ec_0v_newelstypes, \n      refprism_2fa_2fb_1ec_0v_newels\n    };\n\n\n\n//  HP_PRISM_2FA_2FB_3E \nint refprism_2fa_2fb_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0 }\n    };\nint refprism_2fa_2fb_3e_0v_splitfaces[][4] =\n    {\n      {1,2,3,13},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},  \n      {4,1,5,31},\n      {5,4,2,32},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      { 0, 0, 0, 0 }\n    };\nint refprism_2fa_2fb_3e_0v_splitelement[][5] = \n  {\n    {1,2,3,4,25}, \n    {4,1,6,5,37},\n    {0,0,0,0,0} \n  };\n  \nHPREF_ELEMENT_TYPE refprism_2fa_2fb_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V, \n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      \n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EB_0V,\n      HP_PRISM_1FA_1FB_1EA_0V,\n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      \n      HP_NONE,\n    };\n  int refprism_2fa_2fb_3e_0v_newels[][8] =\n    {\n      { 25, 21, 22, 37, 33, 34}, \n      { 31, 32, 20, 19, 37, 33, 21, 25}, \n      { 36, 24, 23, 35, 37, 25, 22, 34}, \n      { 16, 19, 25, 28, 31, 37}, \n      { 28, 36, 37, 16, 24, 25},\n      { 18, 23, 22, 30, 35, 34}, \n      { 29, 32, 33, 17, 20, 21}, \n            \n      { 13, 9, 10, 25, 21, 22 }, \n      { 7, 8, 9, 13, 19, 20, 21, 25 }, \n      { 11, 12, 13, 10, 23, 24, 25, 22 }, \n      { 1, 7, 13, 16, 19, 25 }, \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 10, 18, 23, 22 }, \n      { 8, 2, 9, 20, 17, 21 }, \n\n      { 46, 43, 42 ,37, 34, 33},\n      { 40, 41, 32, 31, 46, 42, 33, 37 }, \n      { 44, 45, 36, 35, 43, 46, 37, 34 }, \n      { 40, 4, 46, 31, 28, 37 }, \n      { 4, 45, 46, 28, 36, 37},  \n      { 44, 6, 43, 35, 30, 34},\n      { 5, 41, 42, 29, 32, 33}, \n      \n    };\n  HPRef_Struct refprism_2fa_2fb_3e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_2fb_3e_0v_splitedges, \n      refprism_2fa_2fb_3e_0v_splitfaces, \n      refprism_2fa_2fb_3e_0v_splitelement, \n      refprism_2fa_2fb_3e_0v_newelstypes, \n      refprism_2fa_2fb_3e_0v_newels\n    };\n\n\n\n\n//  HP_PRISM_1FA_2E_0V  \n  int refprism_1fa_2e_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {5,4,41},\n      {2,1,8},\n      {4,5,40},\n      {1,2,7},\n      {0,0,0},\n\n    };\n  int refprism_1fa_2e_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {2,1,5,20},\n      {1,2,4,19},\n      {0,0,0,0},\n    };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_2e_0v_newelstypes[] =\n    {\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM_1FA_0E_0V, \n      HP_HEX_1F_0E_0V,\n      HP_PRISM_SINGEDGE, \n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_1FA_1E_0V,\n      HP_NONE\n    };\n  int refprism_1fa_2e_0v_newels[][8] =\n    {\n      {40,41,20,19,45,42,21,24}, \n      {24,21,18,45,42,6},\n      {12,9,3,24,21,18},\n      {9, 12, 7, 8, 21, 24, 19, 20}, \n      { 17, 21, 20, 5, 42, 41},\n      {2, 9, 8, 17, 21, 20},\n      {16,19,24,4,40,45},\n      {1,7,12,16,19,24}\n    };\n  HPRef_Struct refprism_1fa_2e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_2e_0v_splitedges, \n\n      refprism_1fa_2e_0v_splitfaces, 0,\n      refprism_1fa_2e_0v_newelstypes, \n      refprism_1fa_2e_0v_newels\n    };\n    \n//  HP_PRISM_2FA_2E_0V   \n  int refprism_2fa_2e_0v_splitedges[][3] =\n    {\n      {2,3,9},\n      {1,3,12},\n      {1,4,16}, \n      {2,5,17},\n      {3,6,18},\n      {5,6,42},\n      {4,6,45},\n      {4,1,28},\n      {5,2,29},\n      {6,3,30},\n      {4,5,40},\n      {1,2,7},\n      { 5, 4, 41},\n      { 2, 1, 8},\n      {0,0,0}, \n    };\n  int refprism_2fa_2e_0v_splitfaces[][4] = \n    {\n      {2,3,5,21},\n      {1,3,4,24},\n      {1,2,4,19},\n      {4,1,6,36},\n      {4,1,5,31},\n      {5,6,2,33},\n      {5,4,2,32},\n      {2,1,5,20},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_2e_0v_newelstypes[] =\n    {\n      HP_PRISM, \n      HP_HEX, \n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE, \n      \n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_1E_0V, \n      HP_PRISM_1FA_1E_0V, \n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_1E_0V, \n      HP_PRISM_1FA_1E_0V, \n      HP_NONE,\n      \n    };\n  int refprism_2fa_2e_0v_newels[][8] =\n    {\n      { 24, 21, 18, 36, 33, 30}, \n      { 19, 20, 21, 24, 31, 32, 33, 36}, \n      { 16, 19, 24, 28, 31, 36}, \n      { 17, 21, 20, 29, 33, 32}, \n      \n      { 12, 9, 3, 24, 21, 18}, \n      { 7, 8, 9, 12, 19, 20, 21, 24}, \n      { 1, 7, 12, 16, 19, 24},\n      { 2, 9, 8, 17, 21, 20}, \n      \n      { 45, 6, 42, 36, 30, 33}, \n      { 40, 45, 42, 41, 31, 36, 33, 32}, \n      { 4, 45, 40, 28, 36, 31 }, \n      { 5, 41, 42, 29, 32, 33 },\n    };\n  HPRef_Struct refprism_2fa_2e_0v =\n    {\n      HP_PRISM,\n      refprism_2fa_2e_0v_splitedges, \n      refprism_2fa_2e_0v_splitfaces, 0,\n      refprism_2fa_2e_0v_newelstypes, \n      refprism_2fa_2e_0v_newels\n    };\n\n\n \n//  HP_PRISM_3E_0V   \n  int refprism_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\n  int refprism_3e_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX,\n      HP_HEX,\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_NONE\n    };\n  int refprism_3e_0v_newels[][8] =\n    {\n      { 13, 14, 15, 46, 47, 48}, \n      { 7, 8, 14, 13, 40, 41, 47, 46}, \n      { 15, 14, 9, 10, 48, 47, 42, 43}, \n      { 12, 13, 15, 11, 45, 46, 48, 44}, \n      { 14, 8, 9, 47, 41, 42 }, \n      { 11, 15, 10, 44, 48, 43 }, \n      { 7, 13, 12, 40, 46, 45}, \n      { 1, 7, 12, 4, 40, 45}, \n      { 2, 9, 8, 5, 42, 41 }, \n      { 3, 11, 10, 6, 44, 43 }\n    };\n  HPRef_Struct refprism_3e_0v =\n    {\n      HP_PRISM,\n      refprism_3e_0v_splitedges, \n      refprism_3e_0v_splitfaces, 0,\n      refprism_3e_0v_newelstypes, \n      refprism_3e_0v_newels\n    };\n\n\n//  HP_PRISM_3E_0V   \nint refprism_1fa_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      \n      { 0, 0, 0}, \n    };\nint refprism_1fa_3e_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nint refprism_1fa_3e_0v_splitelements[][5] = \n  {\n      {1,2,3,4,25},\n      {2,1,3,5,26},\n      {3,1,2,6,27}, \n      {0,0,0,0,0},\n  };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX,\n      HP_HEX,\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_NONE\n    };\nint refprism_1fa_3e_0v_newels[][8] =\n    {\n      { 25, 26, 27, 46, 47, 48}, \n      { 19, 20, 26, 25, 40, 41, 47, 46},  \n      { 27, 26, 21, 22, 48, 47, 42, 43}, \n      { 23, 24, 25, 27, 44, 45, 46, 48}, \n      { 19, 25, 24, 40, 46, 45}, \n      { 26, 20, 21, 47, 41, 42},\n      { 23, 27, 22, 44, 48, 43}, \n      { 16, 19, 24, 4, 40, 45}, \n      { 17, 21, 20, 5, 42, 41}, \n      { 18, 23, 22, 6, 44, 43}, \n\n      { 13, 14, 15, 25, 26, 27}, \n      { 7, 8, 14, 13, 19, 20, 26, 25},\n      { 15, 14, 9, 10, 27, 26, 21, 22}, \n      { 12, 13, 15, 11, 24, 25, 27, 23}, \n      { 14, 8, 9, 26, 20, 21}, \n      { 11, 15, 10, 23, 27, 22}, \n      { 7, 13 , 12, 19, 25, 24}, \n      { 2, 9, 8, 17, 21, 20}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 1, 7, 12, 16, 19, 24}, \n    };\n  HPRef_Struct refprism_1fa_3e_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_3e_0v_splitedges, \n      refprism_1fa_3e_0v_splitfaces, \n      refprism_1fa_3e_0v_splitelements, \n      refprism_1fa_3e_0v_newelstypes, \n      refprism_1fa_3e_0v_newels\n    };\n\n\n\n//  HP_PRISM_2FA_3E_0V   \nint refprism_2fa_3e_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\nint refprism_2fa_3e_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,1,5,31},\n      {5,4,2,32},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nint refprism_2fa_3e_0v_splitelements[][5] = \n  {\n      {1,2,3,4,25},\n      {2,1,3,5,26},\n      {3,1,2,6,27}, \n      {4,1,6,5,37},\n      {5,2,4,6,38},\n      {6,4,5,3,39}, \n      {0,0,0,0,0},\n  };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX,\n      HP_HEX,\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n\n      HP_NONE\n    };\n\n  int refprism_2fa_3e_0v_newels[][8] =\n    {\n      { 25, 26, 27, 37, 38, 39}, \n      { 19, 20, 26, 25, 31, 32, 38, 37},  \n      { 27, 26, 21, 22, 39, 38, 33, 34}, \n      { 23, 24, 25, 27, 35, 36, 37, 39}, \n      { 19, 25, 24, 31, 37, 36}, \n      { 26, 20, 21, 38, 32, 33},\n      { 23, 27, 22, 35, 39, 34}, \n      { 16, 19, 24, 28, 31, 36}, \n      { 17, 21, 20, 29, 33, 32}, \n      { 18, 23, 22, 30, 35, 34}, \n\n      { 13, 14, 15, 25, 26, 27}, \n      { 7, 8, 14, 13, 19, 20, 26, 25},\n      { 15, 14, 9, 10, 27, 26, 21, 22}, \n      { 12, 13, 15, 11, 24, 25, 27, 23}, \n      { 14, 8, 9, 26, 20, 21}, \n      { 11, 15, 10, 23, 27, 22}, \n      { 7, 13 , 12, 19, 25, 24}, \n      { 2, 9, 8, 17, 21, 20}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 1, 7, 12, 16, 19, 24}, \n\n      { 48, 47, 46, 39, 38, 37 }, \n      { 48, 43, 42, 47, 39, 34, 33, 38}, \n      { 45, 44, 48, 46, 36, 35, 39, 37},\n      { 46, 47, 41, 40, 37, 38, 32, 31}, \n      { 47, 42, 41, 38, 33, 32}, \n      { 45, 46, 40, 36, 37, 31}, \n      { 44, 43, 48, 35, 34, 39},\n      { 6, 43, 44, 30, 34, 35}, \n      { 5, 41, 42, 29, 32, 33}, \n      { 4, 45, 40, 28, 36, 31},\n    };\n\nHPRef_Struct refprism_2fa_3e_0v =\n  {\n    HP_PRISM,\n    refprism_2fa_3e_0v_splitedges, \n    refprism_2fa_3e_0v_splitfaces, \n    refprism_2fa_3e_0v_splitelements, \n    refprism_2fa_3e_0v_newelstypes, \n    refprism_2fa_3e_0v_newels\n  };\n\n\n\n//  HP_PRISM_3FB_0V   \n  int refprism_3fb_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\n  int refprism_3fb_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48},\n      {0,0,0,0}, \n    };\n\n  HPREF_ELEMENT_TYPE refprism_3fb_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_NONE\n    };\n  int refprism_3fb_0v_newels[][8] =\n    {\n      { 13, 14, 15, 46, 47, 48}, \n      { 8, 7, 40, 41, 14,13, 46, 47 }, \n      { 10, 9, 42, 43, 15, 14, 47, 48 }, \n      { 44, 45, 12, 11, 48, 46, 13, 15}, \n      { 1, 7, 13, 4, 40, 46 }, \n      { 4, 45, 46, 1, 12, 13}, \n      { 2, 9, 14, 5, 42, 47 }, \n      { 5, 41, 47, 2, 8, 14 }, \n      { 3, 11, 15, 6, 44, 48}, \n      { 6, 43, 48, 3, 10, 15},\n\n    };\n  HPRef_Struct refprism_3fb_0v =\n    {\n      HP_PRISM,\n      refprism_3fb_0v_splitedges, \n      refprism_3fb_0v_splitfaces, 0,\n      refprism_3fb_0v_newelstypes, \n      refprism_3fb_0v_newels\n    };\n\n\n//  HP_PRISM_3FB_0V   \nint refprism_1fa_3fb_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\nint refprism_1fa_3fb_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nint refprism_1fa_3fb_0v_splitelements[][5] = \n  {\n      {1,2,3,4,25},\n      {2,1,3,5,26},\n      {3,1,2,6,27}, \n      {0,0,0,0,0},\n  };\n\n  HPREF_ELEMENT_TYPE refprism_1fa_3fb_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      \n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      \n      HP_NONE\n    };\n  int refprism_1fa_3fb_0v_newels[][8] =\n    {\n      { 25, 26, 27, 46, 47, 48}, \n      { 19, 40, 41, 20, 25, 46, 47, 26}, \n      { 22, 21, 42, 43, 27, 26, 47, 48}, \n      { 24, 23, 44, 45, 25, 27, 48, 46},\n      \n      { 16, 19, 25, 4, 40, 46 }, \n      { 4, 45, 46, 16, 24, 25 }, \n      { 17, 21, 26, 5, 42, 47 }, \n      { 5, 41, 47, 17, 20, 26}, \n      { 18, 23, 27, 6, 44, 48}, \n      { 6, 43, 48, 18, 22, 27},\n\n      { 13, 14, 15, 25, 26, 27}, \n      { 7, 8, 14, 13, 19, 20, 26, 25}, \n      { 9, 10, 15, 14, 21, 22, 27, 26},\n      { 11, 12, 13, 15, 23, 24, 25, 27},\n\n      { 2, 9, 14, 17, 21, 26}, \n      { 8, 2, 14, 20, 17, 26}, \n      { 1, 7, 13, 16, 19, 25}, \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 15, 18, 23, 27 },\n      { 10, 3, 15, 22, 18, 27}, \n      \n      };\n  HPRef_Struct refprism_1fa_3fb_0v =\n    {\n      HP_PRISM,\n      refprism_1fa_3fb_0v_splitedges, \n      refprism_1fa_3fb_0v_splitfaces, \n      refprism_1fa_3fb_0v_splitelements, \n      refprism_1fa_3fb_0v_newelstypes, \n      refprism_1fa_3fb_0v_newels\n    };\n     \n\n\n//  HP_PRISM_2FA_3E_0V   \nint refprism_2fa_3fb_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\nint refprism_2fa_3fb_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,1,5,31},\n      {5,4,2,32},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nint refprism_2fa_3fb_0v_splitelements[][5] = \n  {\n      {1,2,3,4,25},\n      {2,1,3,5,26},\n      {3,1,2,6,27}, \n      {4,1,6,5,37},\n      {5,2,4,6,38},\n      {6,4,5,3,39}, \n      {0,0,0,0,0},\n  };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] =\n    {\n\n      HP_PRISM,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V, \n      HP_HEX_1FA_1FB_0E_0V,\n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n      HP_PRISM_1FA_1FB_1EA_0V, \n      HP_PRISM_1FA_1FB_1EB_0V, \n\n      HP_NONE\n    };\n  int refprism_2fa_3fb_0v_newels[][8] =\n    {\n      { 25, 26, 27, 37, 38, 39}, \n      { 19, 31, 32, 20, 25, 37, 38, 26}, \n      { 33, 34, 22, 21, 38, 39, 27, 26}, \n      { 35, 36, 24, 23, 39, 37, 25, 27}, \n\n      { 16, 19, 25, 28, 31, 37}, \n      { 28, 36, 37, 16, 24, 25 }, \n      { 17, 21, 26, 29, 33, 38 }, \n      { 29, 32, 38, 17, 20, 26}, \n      { 18, 23, 27, 30, 35, 39}, \n      { 30, 34, 39, 18, 22, 27},\n\n \n      { 13, 14, 15, 25, 26, 27}, \n      { 7, 8, 14, 13, 19, 20, 26, 25}, \n      { 9, 10, 15, 14, 21, 22, 27, 26},\n      { 11, 12, 13, 15, 23, 24, 25, 27},\n\n      { 2, 9, 14, 17, 21, 26}, \n      { 8, 2, 14, 20, 17, 26}, \n      { 1, 7, 13, 16, 19, 25}, \n      { 12, 1, 13, 24, 16, 25 }, \n      { 3, 11, 15, 18, 23, 27 },\n      { 10, 3, 15, 22, 18, 27}, \n\n      \n      { 48, 47, 46, 39, 38, 37 }, \n      { 44, 45, 36, 35, 48, 46, 37, 39}, \n      { 40, 41, 32, 31, 46, 47, 38, 37}, \n      { 42, 43, 34, 33, 47, 48, 39, 38}, \n      \n      { 6, 43, 48, 30, 34, 39}, \n      { 44, 6, 48, 35, 30, 39}, \n      { 4, 45, 46, 28, 36, 37}, \n      { 40, 4, 46, 31, 28, 37}, \n      { 5, 41, 47, 29, 32, 38}, \n      { 42, 5, 47, 33, 29, 38},\n    };\n\nHPRef_Struct refprism_2fa_3fb_0v =\n  {\n    HP_PRISM,\n    refprism_2fa_3fb_0v_splitedges, \n    refprism_2fa_3fb_0v_splitfaces, \n    refprism_2fa_3fb_0v_splitelements, \n    refprism_2fa_3fb_0v_newelstypes, \n    refprism_2fa_3fb_0v_newels\n  };\n\n\n/* \n\n\n//  HP_PRISM_3E_4EH\nint refprism_3e_4eh_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0},\n\n    };\nint refprism_3e_4eh_splitfaces[][4] = \n    {\n      {3,1,2,15},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nHPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] =\n  {\n    HP_PRISM, \n    HP_HEX_2EH_0V,\n    HP_HEX_2EH_0V,\n    HP_TET_2E,\n    HP_TET_2E,\n    HP_PRISM_1E_2EH_0V, \n    HP_PRISM_1E_2EH_0V, \n    HP_NONE\n    };\n  int refprism_2fa_3fb_0v_newels[][8] =\n    {\n      {15, 7, 8, 48, 40, 41 }, \n      \n    };\n\nHPRef_Struct refprism_2fa_3fb_0v =\n  {\n    HP_PRISM,\n    refprism_2fa_3fb_0v_splitedges, \n    refprism_2fa_3fb_0v_splitfaces, \n    refprism_2fa_3fb_0v_splitelements, \n    refprism_2fa_3fb_0v_newelstypes, \n    refprism_2fa_3fb_0v_newels\n  };\n*/ \n\n/*\n//  HP_PRISM_2FA_3E_0V   \nint refprism_3e_4_0v_splitedges[][3] =\n    {\n      { 1, 2, 7},\n      { 2, 1, 8},\n      { 2, 3, 9},\n      { 3, 2, 10},\n      { 3, 1, 11},\n      { 1, 3, 12},\n      { 1, 4, 16}, \n      { 2, 5, 17},\n      { 3, 6, 18},\n      { 4, 1, 28},\n      { 5, 2, 29},\n      { 6, 3, 30},\n      { 4, 5, 40},\n      { 5, 4, 41},\n      { 5, 6, 42},\n      { 6, 5, 43},\n      { 6, 4, 44},\n      { 4, 6, 45},\n      { 0, 0, 0}, \n    };\nint refprism_2fa_3e_0v_splitfaces[][4] = \n    {\n      {1,2,3,13},\n      {2,3,1,14},\n      {3,1,2,15},\n      {1,2,4,19},\n      {2,1,5,20},\n      {2,3,5,21},\n      {3,2,6,22},\n      {3,1,6,23},\n      {1,3,4,24},\n      {4,1,5,31},\n      {5,4,2,32},\n      {5,6,2,33},\n      {6,5,3,34},\n      {6,4,3,35},\n      {4,1,6,36},\n      {4,5,6,46},\n      {5,4,6,47},\n      {6,4,5,48}, \n      {0,0,0,0}, \n    };\n\nint refprism_2fa_3e_0v_splitelements[][5] = \n  {\n      {1,2,3,4,25},\n      {2,1,3,5,26},\n      {3,1,2,6,27}, \n      {4,1,6,5,37},\n      {5,2,4,6,38},\n      {6,4,5,3,39}, \n      {0,0,0,0,0},\n  };\n\n  HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] =\n    {\n      HP_PRISM,\n      HP_HEX,\n      HP_HEX,\n      HP_HEX,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n      HP_PRISM_SINGEDGE,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n\n      HP_PRISM_1FA_0E_0V,\n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_HEX_1F_0E_0V, \n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_0E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n      HP_PRISM_1FA_1E_0V,\n\n      HP_NONE\n    };\n\n  int refprism_2fa_3e_0v_newels[][8] =\n    {\n      { 25, 26, 27, 37, 38, 39}, \n      { 19, 20, 26, 25, 31, 32, 38, 37},  \n      { 27, 26, 21, 22, 39, 38, 33, 34}, \n      { 23, 24, 25, 27, 35, 36, 37, 39}, \n      { 19, 25, 24, 31, 37, 36}, \n      { 26, 20, 21, 38, 32, 33},\n      { 23, 27, 22, 35, 39, 34}, \n      { 16, 19, 24, 28, 31, 36}, \n      { 17, 21, 20, 29, 33, 32}, \n      { 18, 23, 22, 30, 35, 34}, \n\n      { 13, 14, 15, 25, 26, 27}, \n      { 7, 8, 14, 13, 19, 20, 26, 25},\n      { 15, 14, 9, 10, 27, 26, 21, 22}, \n      { 12, 13, 15, 11, 24, 25, 27, 23}, \n      { 14, 8, 9, 26, 20, 21}, \n      { 11, 15, 10, 23, 27, 22}, \n      { 7, 13 , 12, 19, 25, 24}, \n      { 2, 9, 8, 17, 21, 20}, \n      { 3, 11, 10, 18, 23, 22}, \n      { 1, 7, 12, 16, 19, 24}, \n\n      { 48, 47, 46, 39, 38, 37 }, \n      { 48, 43, 42, 47, 39, 34, 33, 38}, \n      { 45, 44, 48, 46, 36, 35, 39, 37},\n      { 46, 47, 41, 40, 37, 38, 32, 31}, \n      { 47, 42, 41, 38, 33, 32}, \n      { 45, 46, 40, 36, 37, 31}, \n      { 44, 43, 48, 35, 34, 39},\n      { 6, 43, 44, 30, 34, 35}, \n      { 5, 41, 42, 29, 32, 33}, \n      { 4, 45, 40, 28, 36, 31},\n    };\n\nHPRef_Struct refprism_2fa_3e_0v =\n  {\n    HP_PRISM,\n    refprism_2fa_3e_0v_splitedges, \n    refprism_2fa_3e_0v_splitfaces, \n    refprism_2fa_3e_0v_splitelements, \n    refprism_2fa_3e_0v_newelstypes, \n    refprism_2fa_3e_0v_newels\n  };\n\n*/\n/*\n\n//  HP_PRISM_1FB_1EB_0V   ... quad face 1-2-4-5\n  int refprism_1fb_1eb_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 3, 8 },\n      { 4, 6, 9 },\n      { 5, 6, 10 },\n      { 2, 1, 11 },\n      { 5, 4, 12 },\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refprism_1fb_1eb_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FB_1EB_0V,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_1fb_1eb_0v_newels[][8] =\n    {\n      { 1, 4, 12, 11, 7, 9, 10, 8  },\n      { 11, 2, 8, 12, 5, 10 },\n      { 7, 8, 3, 9, 10, 6 }\n    };\n  HPRef_Struct refprism_1fb_1eb_0v =\n    {\n      HP_PRISM,\n      refprism_1fb_1eb_0v_splitedges, \n      0, 0,\n      refprism_1fb_1eb_0v_newelstypes, \n      refprism_1fb_1eb_0v_newels\n    };\n\n\n\n\n\n\n\n\n\n\n  // HP_PRISM_2F_0E_0V\n  int refprism_2f_0e_0v_splitedges[][3] =\n    {\n      { 1, 3, 7 },\n      { 2, 1, 8 },\n      { 2, 3, 9 },\n      { 3, 1, 10 },\n\n      { 4, 6, 12 },\n      { 5, 4, 13 },\n      { 5, 6, 14 },\n      { 6, 4, 15 },\n\n      { 0, 0, 0 }\n    };\n\n  int refprism_2f_0e_0v_splitfaces[][4] =\n    {\n      { 2, 1, 3, 11 },\n      { 5, 4, 6, 16 },\n      { 0, 0, 0, 0 },\n    };\n\n  HPREF_ELEMENT_TYPE refprism_2f_0e_0v_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_HEX_1F_0E_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM_1FB_1EA_0V,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refprism_2f_0e_0v_newels[][8] =\n    {\n      //{ 1, 8, 11, 7, 4, 13, 16, 12 },\n      // { 9, 3, 10, 11, 14, 6, 15, 16 },\n      { 1, 4, 13, 8, 7, 12, 16, 11 },\n      { 9, 14, 6, 3, 11, 16, 15, 10 },\n      { 2, 9, 11, 5, 14, 16 },\n      // { 8, 2, 11, 13, 5, 16 },\n      { 5, 13, 16, 2, 8, 11 },\n      { 7, 11, 10, 12, 16, 15 }\n    };\n  HPRef_Struct refprism_2f_0e_0v =\n    {\n      HP_PRISM,\n      refprism_2f_0e_0v_splitedges, \n      refprism_2f_0e_0v_splitfaces, \n      0,\n      refprism_2f_0e_0v_newelstypes, \n      refprism_2f_0e_0v_newels\n    };\n\n*/\n"
  },
  {
    "path": "libsrc/meshing/hpref_pyramid.hpp",
    "content": "\n  // HP_PYRAMID\n  int refpyramid_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refpyramid_newelstypes[] =\n    {\n      HP_PYRAMID,\n      HP_NONE,\n    };\n  int refpyramid_newels[][8] =\n    {\n      { 1, 2, 3, 4, 5 }\n    };\n  HPRef_Struct refpyramid =\n    {\n      HP_PYRAMID,\n      refpyramid_splitedges, \n      0, 0,\n      refpyramid_newelstypes, \n      refpyramid_newels\n    };\n\n\n// singular point 1      \n  // HP_PYRAMID_0E_1V\n  int refpyramid_0e_1v_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refpyramid_0e_1v_newelstypes[] =\n    {\n      HP_TET_0E_1V,\n      HP_TET,\n      HP_NONE,\n    };\n  int refpyramid_0e_1v_newels[][8] =\n    {\n      { 1, 2, 4, 5 },\n      { 2, 3, 4, 5 },\n    };\n  HPRef_Struct refpyramid_0e_1v =\n    {\n      HP_PYRAMID,\n      refpyramid_0e_1v_splitedges, \n      0, 0,\n      refpyramid_0e_1v_newelstypes, \n      refpyramid_0e_1v_newels\n    };\n\n\n// singular edges 1-2 1-4 singular point 1 \n  // HP_PYRAMID_EDGES\n  int refpyramid_edges_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  HPREF_ELEMENT_TYPE refpyramid_edges_newelstypes[] =\n    {\n      HP_TET_1E_1VA,\n      HP_TET_1E_1VA,\n      HP_NONE,\n    };\n  int refpyramid_edges_newels[][8] =\n    {\n      { 1, 2, 3, 5 },\n      { 1, 4, 5, 3 },\n    };\n  HPRef_Struct refpyramid_edges =\n    {\n      HP_PYRAMID,\n      refpyramid_edges_splitedges, \n      0, 0,\n      refpyramid_edges_newelstypes, \n      refpyramid_edges_newels\n    };\n\n\n\n// singular face 1-2-5 \n  // HP_PYRAMID_1FB_0E_0V\n  int refpyramid_1fb_0e_0v_splitedges[][3] =\n    {\n      { 1, 4, 6 },\n      { 2, 3, 7 },\n      { 5, 3, 8 },\n      { 5, 4, 9 },\n      { 0, 0, 0 },\n    };\n\n  HPREF_ELEMENT_TYPE refpyramid_1fb_0e_0v_newelstypes[] =\n    {\n      HP_HEX7_1FB,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refpyramid_1fb_0e_0v_newels[][8] =\n    {\n      { 6, 7, 8, 9, 1, 2, 5 },\n      { 3, 7, 8, 4, 6, 9 },\n    };\n  HPRef_Struct refpyramid_1fb_0e_0v =\n    {\n      HP_PYRAMID,\n      refpyramid_1fb_0e_0v_splitedges, \n      0, 0,\n      refpyramid_1fb_0e_0v_newelstypes, \n      refpyramid_1fb_0e_0v_newels\n    };\n\n\n\n\n\n\n// singular face 1-2-5 singular point 5\n  // HP_PYRAMID_1FB_0E_1VA\n  int refpyramid_1fb_0e_1va_splitedges[][3] =\n    {\n      { 1, 4, 6 },\n      { 2, 3, 7 },\n      { 5, 1, 8 },\n      { 5, 2, 9 },\n      { 5, 3, 10 },\n      { 5, 4, 11 },\n      { 0, 0, 0 },\n    };\n\n  HPREF_ELEMENT_TYPE refpyramid_1fb_0e_1va_newelstypes[] =\n    {\n      HP_HEX_1F_0E_0V,\n      HP_PYRAMID_1FB_0E_1VA,\n      HP_PRISM,\n      HP_NONE,\n    };\n  int refpyramid_1fb_0e_1va_newels[][8] =\n    {\n      { 1, 8, 9, 2, 6, 11, 10, 7 },\n      { 8, 9, 10, 11, 5 },\n      { 3, 7, 10, 4, 6, 11 }\n    };\n  HPRef_Struct refpyramid_1fb_0e_1va =\n    {\n      HP_PYRAMID,\n      refpyramid_1fb_0e_1va_splitedges, \n      0, 0,\n      refpyramid_1fb_0e_1va_newelstypes, \n      refpyramid_1fb_0e_1va_newels\n    };\n\n\n\n\n"
  },
  {
    "path": "libsrc/meshing/hpref_quad.hpp",
    "content": "// HP_QUAD\nint refquad_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_newelstypes[] =\n{\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_newels[][8] =\n{\n  { 1, 2, 3, 4 },\n};\nHPRef_Struct refquad =\n{\n  HP_QUAD,\n  refquad_splitedges, \n  0, 0,\n  refquad_newelstypes, \n  refquad_newels\n};\n\n\n\n\n\n\n\n// HP_QUAD_SINGCORNER\nint refquad_singcorner_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_singcorner_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_TRIG,\n  HP_NONE,\n};\nint refquad_singcorner_newels[][8] =\n{\n  { 1, 5, 6 },\n  { 2, 4, 6, 5 },\n  { 2, 3, 4 },\n};\nHPRef_Struct refquad_singcorner =\n{\n  HP_QUAD,\n  refquad_singcorner_splitedges, \n  0, 0,\n  refquad_singcorner_newelstypes, \n  refquad_singcorner_newels\n};\n\n\n\n\n\n// HP_DUMMY_QUAD_SINGCORNER\nint refdummyquad_singcorner_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refdummyquad_singcorner_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG,\n  HP_NONE,\n};\nint refdummyquad_singcorner_newels[][8] =\n{\n  { 1, 2, 4 },\n  { 4, 2, 3 },\n};\nHPRef_Struct refdummyquad_singcorner =\n{\n  HP_QUAD,\n  refdummyquad_singcorner_splitedges, \n  0, 0,\n  refdummyquad_singcorner_newelstypes, \n  refdummyquad_singcorner_newels\n};\n\n\n\n\n\n\n\n// HP_QUAD_SINGEDGE\nint refquad_singedge_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_singedge_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_singedge_newels[][8] =\n{\n  { 1, 2, 6, 5 },\n  { 5, 6, 3, 4 },\n};\nHPRef_Struct refquad_singedge =\n{\n  HP_QUAD,\n  refquad_singedge_splitedges, \n  0, 0,\n  refquad_singedge_newelstypes, \n  refquad_singedge_newels\n};\n\n\n\n\n\n\n// HP_QUAD_0E_2VA\nint refquad_0e_2va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_0e_2va_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_0e_2va_newels[][8] =\n{\n  { 1, 5, 6 },\n  { 2, 8, 7 },\n  { 5, 7, 8, 6 },\n  { 6, 8, 3, 4 },\n};\nHPRef_Struct refquad_0e_2va =\n{\n  HP_QUAD,\n  refquad_0e_2va_splitedges, \n  0, 0,\n  refquad_0e_2va_newelstypes, \n  refquad_0e_2va_newels\n};\n\n\n\n// HP_QUAD_0E_2VB\nint refquad_0e_2vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 3, 4, 7 },\n  { 3, 2, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_0e_2vb_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_0e_2vb_newels[][8] =\n{\n  { 1, 5, 6 },\n  { 3, 7, 8 },\n  { 5, 2, 4, 6 },\n  { 2, 8, 7, 4 },\n};\nHPRef_Struct refquad_0e_2vb =\n{\n  HP_QUAD,\n  refquad_0e_2vb_splitedges, \n  0, 0,\n  refquad_0e_2vb_newelstypes, \n  refquad_0e_2vb_newels\n};\n\n\n\n\n// HP_QUAD_0E_3V\nint refquad_0e_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 0, 0, 0 }\n};\n\nint refquad_0e_3v_splitfaces[][4] =\n{\n  { 2, 3, 1, 14 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_0e_3v_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_0e_3v_newels[][8] =\n{\n  { 1, 5, 6 },\n  { 2, 8, 14, 7 },\n  { 3, 10, 9 },\n  { 5, 7, 14, 6 },\n  { 8, 9, 10, 14 },\n  { 6, 14, 10, 4 },\n};\nHPRef_Struct refquad_0e_3v =\n{\n  HP_QUAD,\n  refquad_0e_3v_splitedges, \n  refquad_0e_3v_splitfaces, \n  0,\n  refquad_0e_3v_newelstypes, \n  refquad_0e_3v_newels\n};\n\n\n\n\n// HP_QUAD_0E_4V\nint refquad_0e_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint refquad_0e_4v_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 3, 4, 2, 15 },\n  { 4, 1, 3, 16 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_0e_4v_newelstypes[] =\n{\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n\n  HP_QUAD,\n  HP_QUAD,\n  HP_QUAD,\n  HP_QUAD,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_0e_4v_newels[][8] =\n{\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 3, 10, 15, 9 },\n  { 4, 11, 16, 12 },\n  { 5, 7, 14, 13 },\n  { 8, 9, 15, 14 },\n  { 10, 12, 16, 15 },\n  { 11, 6, 13, 16 },\n  { 13, 14, 15, 16 }\n};\nHPRef_Struct refquad_0e_4v =\n{\n  HP_QUAD,\n  refquad_0e_4v_splitedges, \n  refquad_0e_4v_splitfaces, \n  0,\n  refquad_0e_4v_newelstypes, \n  refquad_0e_4v_newels\n};\n\n\n\n\n\n\n\n\n// HP_QUAD_1E_1VA\nint refquad_1e_1va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_1va_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_NONE,\n};\nint refquad_1e_1va_newels[][8] =\n{\n  { 7, 2, 6, 5 },\n  { 5, 6, 3, 4 },\n  { 1, 7, 5 },\n};\nHPRef_Struct refquad_1e_1va =\n{\n  HP_QUAD,\n  refquad_1e_1va_splitedges, \n  0, 0,\n  refquad_1e_1va_newelstypes, \n  refquad_1e_1va_newels\n};\n\n\n\n\n// HP_QUAD_1E_1VB\nint refquad_1e_1vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 2, 1, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_1vb_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_1e_1vb_newels[][8] =\n{\n  { 1, 7, 6, 5 },\n  { 5, 6, 3, 4 },\n  { 7, 2, 6 },\n};\nHPRef_Struct refquad_1e_1vb =\n{\n  HP_QUAD,\n  refquad_1e_1vb_splitedges, \n  0, 0,\n  refquad_1e_1vb_newelstypes, \n  refquad_1e_1vb_newels\n};\n\n\n\n// HP_QUAD_1E_1VC\nint refquad_1e_1vc_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 3, 4, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_1vc_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_1vc_newels[][8] =\n{\n  { 1, 2, 6, 5 },\n  { 5, 6, 4 },\n  { 4, 6, 7, 8 },\n  { 3, 8, 7 }\n};\nHPRef_Struct refquad_1e_1vc =\n{\n  HP_QUAD,\n  refquad_1e_1vc_splitedges, \n  0, 0,\n  refquad_1e_1vc_newelstypes, \n  refquad_1e_1vc_newels\n};\n\n\n\n// HP_QUAD_1E_1VD\nint refquad_1e_1vd_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 4, 1, 7 },\n  { 4, 3, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_1vd_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_1vd_newels[][8] =\n{\n  { 1, 2, 6, 5 },\n  { 5, 6, 3 },\n  { 5, 3, 8, 7 },\n  { 4, 7, 8 }\n};\nHPRef_Struct refquad_1e_1vd =\n{\n  HP_QUAD,\n  refquad_1e_1vd_splitedges, \n  0, 0,\n  refquad_1e_1vd_newelstypes, \n  refquad_1e_1vd_newels\n};\n\n\n\n\n\n\n\n// HP_QUAD_1E_2VA\nint refquad_1e_2va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2va_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_1e_2va_newels[][8] =\n{\n  { 7, 8, 6, 5 },\n  { 5, 6, 3, 4 },\n  { 1, 7, 5 },\n  { 8, 2, 6 }\n};\nHPRef_Struct refquad_1e_2va =\n{\n  HP_QUAD,\n  refquad_1e_2va_splitedges, \n  0, 0,\n  refquad_1e_2va_newelstypes, \n  refquad_1e_2va_newels\n};\n\n\n\n\n// HP_QUAD_1E_2VB\nint refquad_1e_2vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 3, 2, 8 },\n  { 3, 4, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2vb_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_2vb_newels[][8] =\n{\n  { 7, 2, 6, 5 },\n  { 1, 7, 5 },\n  { 5, 6, 4 },\n  { 4, 6, 8, 9 },\n  { 3, 9, 8 }\n};\nHPRef_Struct refquad_1e_2vb =\n{\n  HP_QUAD,\n  refquad_1e_2vb_splitedges, \n  0, 0,\n  refquad_1e_2vb_newelstypes, \n  refquad_1e_2vb_newels\n};\n\n\n\n\n// HP_QUAD_1E_2VC\nint refquad_1e_2vc_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 4, 1, 8 },\n  { 4, 3, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2vc_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_2vc_newels[][8] =\n{\n  { 7, 2, 6, 5 },\n  { 1, 7, 5 },\n  { 5, 6, 3 },\n  { 5, 3, 9, 8 },\n  { 4, 8, 9 }\n};\nHPRef_Struct refquad_1e_2vc =\n{\n  HP_QUAD,\n  refquad_1e_2vc_splitedges, \n  0, 0,\n  refquad_1e_2vc_newelstypes, \n  refquad_1e_2vc_newels\n};\n\n\n\n\n// HP_QUAD_1E_2VD\nint refquad_1e_2vd_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 2, 1, 7 },\n  { 3, 2, 8 },\n  { 3, 4, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2vd_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_2vd_newels[][8] =\n{\n  { 1, 7, 6, 5 },\n  { 7, 2, 6 },\n  { 5, 6, 4 },\n  { 4, 6, 8, 9 },\n  { 3, 9, 8 }\n};\nHPRef_Struct refquad_1e_2vd =\n{\n  HP_QUAD,\n  refquad_1e_2vd_splitedges, \n  0, 0,\n  refquad_1e_2vd_newelstypes, \n  refquad_1e_2vd_newels\n};\n\n\n\n\n\n// HP_QUAD_1E_2VE\nint refquad_1e_2ve_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 2, 1, 7 },\n  { 4, 1, 8 },\n  { 4, 3, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2ve_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_2ve_newels[][8] =\n{\n  { 1, 7, 6, 5 },\n  { 7, 2, 6 },\n  { 5, 6, 3 },\n  { 5, 3, 9, 8 },\n  { 4, 8, 9 }\n};\nHPRef_Struct refquad_1e_2ve =\n{\n  HP_QUAD,\n  refquad_1e_2ve_splitedges, \n  0, 0,\n  refquad_1e_2ve_newelstypes, \n  refquad_1e_2ve_newels\n};\n\n\n\n\n\n\n// HP_QUAD_1E_2VF\nint refquad_1e_2vf_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 4, 1, 7 },\n  { 4, 3, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_2vf_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_1e_2vf_newels[][8] =\n{\n  { 1, 2, 6, 5 },\n  { 5, 6, 9, 7 },\n  { 7, 9, 10, 8 },\n  { 4, 7, 8 },\n  { 3, 10, 9 },\n};\nHPRef_Struct refquad_1e_2vf =\n{\n  HP_QUAD,\n  refquad_1e_2vf_splitedges, \n  0, 0,\n  refquad_1e_2vf_newelstypes, \n  refquad_1e_2vf_newels\n};\n\n\n\n\n\n// HP_QUAD_1E_3VA\nint refquad_1e_3va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_3va_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG,\n  HP_NONE,\n};\nint refquad_1e_3va_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 8, 2, 6 },\n  { 3, 10, 9 },\n  { 7, 8, 6, 5 },\n  { 4, 6, 9, 10 },\n  { 5, 6, 4 }\n};\nHPRef_Struct refquad_1e_3va =\n{\n  HP_QUAD,\n  refquad_1e_3va_splitedges, \n  0, 0,\n  refquad_1e_3va_newelstypes, \n  refquad_1e_3va_newels\n};\n\n\n\n\n\n// HP_QUAD_1E_3VB\nint refquad_1e_3vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 4, 1, 9 },\n  { 4, 3, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_3vb_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG,\n  HP_NONE,\n};\nint refquad_1e_3vb_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 8, 2, 6 },\n  { 4, 9, 10 },\n  { 7, 8, 6, 5 },\n  { 5, 3, 10, 9 },\n  { 5, 6, 3 }\n};\nHPRef_Struct refquad_1e_3vb =\n{\n  HP_QUAD,\n  refquad_1e_3vb_splitedges, \n  0, 0,\n  refquad_1e_3vb_newelstypes, \n  refquad_1e_3vb_newels\n};\n\n\n\n\n\n// HP_QUAD_1E_3VC\nint refquad_1e_3vc_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 3, 2, 8 },\n  { 3, 4, 9 },\n  { 4, 3, 10 },\n  { 4, 1, 11 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_3vc_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_1e_3vc_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 3, 9, 8 },\n  { 4, 11, 10 },\n  { 7, 2, 6, 5 },\n  { 5, 6, 8, 11 },\n  { 11, 8, 9, 10 }\n};\nHPRef_Struct refquad_1e_3vc =\n{\n  HP_QUAD,\n  refquad_1e_3vc_splitedges, \n  0, 0,\n  refquad_1e_3vc_newelstypes, \n  refquad_1e_3vc_newels\n};\n\n\n\n\n// HP_QUAD_1E_3VD\nint refquad_1e_3vd_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 2, 1, 7 },\n  { 3, 2, 8 },\n  { 3, 4, 9 },\n  { 4, 3, 10 },\n  { 4, 1, 11 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_3vd_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_1e_3vd_newels[][8] =\n{\n  { 7, 2, 6 },\n  { 3, 9, 8 },\n  { 4, 11, 10 },\n  { 1, 7, 6, 5 },\n  { 5, 6, 8, 11 },\n  { 11, 8, 9, 10 }\n};\nHPRef_Struct refquad_1e_3vd =\n{\n  HP_QUAD,\n  refquad_1e_3vd_splitedges, \n  0, 0,\n  refquad_1e_3vd_newelstypes, \n  refquad_1e_3vd_newels\n};\n\n\n\n\n\n\n// HP_QUAD_1E_4V\nint refquad_1e_4v_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 4, 1, 9 },\n  { 3, 2, 10 },\n  { 4, 3, 11 },\n  { 3, 4, 12 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_1e_4v_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_1e_4v_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 8, 2, 6 },\n  { 3, 12, 10 },\n  { 4, 9, 11 },\n  { 7, 8, 6, 5 },\n  { 5, 6, 10, 9 },\n  { 9, 10, 12, 11 }\n};\nHPRef_Struct refquad_1e_4v =\n{\n  HP_QUAD,\n  refquad_1e_4v_splitedges, \n  0, 0,\n  refquad_1e_4v_newelstypes, \n  refquad_1e_4v_newels\n};\n\n////////////////////////////////////////////////////////////////////////////////\n\n// HP_QUAD_2E\nint refquad_2e_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 0, 0, 0 }\n};\nint refquad_2e_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\n\n\n/* \n   HPREF_ELEMENT_TYPE refquad_2e_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2e_newels[][8] =\n{\n  { 1, 5, 9 },\n  { 6, 1, 9 },\n  { 5, 2, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 9, 7, 3, 8 },\n};\n*/ \n\n// SZ refine to 4 quads \nHPREF_ELEMENT_TYPE refquad_2e_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2e_newels[][8] =\n{\n  { 1, 5, 9, 6 },\n  { 5, 2, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 9, 7, 3, 8 },\n};\n\nHPRef_Struct refquad_2e =\n{\n  HP_QUAD,\n  refquad_2e_splitedges, \n  refquad_2e_splitfaces, \n  0,\n  refquad_2e_newelstypes, \n  refquad_2e_newels\n};\n\n\n// HP_QUAD_2E_1VA\nint refquad_2e_1va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 2, 1, 10 },\n  { 0, 0, 0 }\n};\nint refquad_2e_1va_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\n\n/* \nHPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_2e_1va_newels[][8] =\n{\n  { 1, 5, 9 },\n  { 6, 1, 9 },\n  { 5, 10, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 9, 7, 3, 8 },\n  { 10, 2, 7 },\n};\n*/ \n// SZ Quad_2e refinement \nHPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_2e_1va_newels[][8] =\n{\n  { 1, 5, 9, 6 },\n  { 5, 10, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 9, 7, 3, 8 },\n  { 10, 2, 7 },\n};\n\nHPRef_Struct refquad_2e_1va =\n{\n  HP_QUAD,\n  refquad_2e_1va_splitedges, \n  refquad_2e_1va_splitfaces, \n  0,\n  refquad_2e_1va_newelstypes, \n  refquad_2e_1va_newels\n};\n\n\n\n// HP_QUAD_2E_1VB\nint refquad_2e_1vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 0, 0, 0 }\n};\nint refquad_2e_1vb_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_1vb_newelstypes[] =\n{\n  // HP_TRIG_SINGEDGECORNER1,\n  // HP_TRIG_SINGEDGECORNER2,\n  // SZ QUAD_2E \n  HP_QUAD_2E,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint refquad_2e_1vb_newels[][8] =\n{\n  //{ 1, 5, 9 },\n  //{ 6, 1, 9 },\n  { 1, 5, 9, 6 },\n  { 5, 2, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 7, 8, 9 },\n  { 8, 7, 10, 11 },\n  { 3, 11, 10 }\n};\nHPRef_Struct refquad_2e_1vb =\n{\n  HP_QUAD,\n  refquad_2e_1vb_splitedges, \n  refquad_2e_1vb_splitfaces, \n  0,\n  refquad_2e_1vb_newelstypes, \n  refquad_2e_1vb_newels\n}\n;\n\n// HP_QUAD_2E_1VC\nint refquad_2e_1vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 1, 8 },\n  { 4, 3, 9 },\n  { 0, 0, 0 }\n};\nint refquad_2e_1vc_splitfaces[][4] =\n{\n  { 1, 2, 4, 10 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_1vc_newelstypes[] =\n{\n  //  HP_TRIG_SINGEDGECORNER1,\n  // HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_2E, \n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2e_1vc_newels[][8] =\n{\n  //{ 1, 5, 10 },\n  //{ 6, 1, 10 },\n  { 1, 5, 10, 6}, \n  { 4, 8, 9 },\n  { 5, 2, 7, 10 },\n  { 8, 6, 10, 9 },\n  { 10, 7, 3, 9 },\n};\nHPRef_Struct refquad_2e_1vc =\n{\n  HP_QUAD,\n  refquad_2e_1vc_splitedges, \n  refquad_2e_1vc_splitfaces, \n  0,\n  refquad_2e_1vc_newelstypes, \n  refquad_2e_1vc_newels\n};\n\n// HP_QUAD_2E_2VA\nint refquad_2e_2va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 2, 1, 12 },\n  { 0, 0, 0 }\n};\nint refquad_2e_2va_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_2va_newelstypes[] =\n{\n  //HP_TRIG_SINGEDGECORNER1,\n  //HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_2E,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_2e_2va_newels[][8] =\n{\n  // { 1, 5, 9 },\n  // { 6, 1, 9 },\n  { 1, 5, 9, 6 }, \n  { 5, 12, 7, 9 },\n  { 4, 6, 9, 8 },\n  { 7, 8, 9 },\n  { 8, 7, 10, 11 },\n  { 3, 11, 10 },\n  { 12, 2, 7 }\n};\nHPRef_Struct refquad_2e_2va =\n{\n  HP_QUAD,\n  refquad_2e_2va_splitedges, \n  refquad_2e_2va_splitfaces, \n  0,\n  refquad_2e_2va_newelstypes, \n  refquad_2e_2va_newels\n};\n\n\n\n\n\n\n// HP_QUAD_2E_2VB\nint refquad_2e_2vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 4, 1, 9 },\n  { 4, 3, 10 },\n  { 0, 0, 0 }\n};\nint refquad_2e_2vb_splitfaces[][4] =\n{\n  { 1, 2, 4, 11 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_2vb_newelstypes[] =\n{\n  // HP_TRIG_SINGEDGECORNER1,\n  // HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_2E, \n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2e_2vb_newels[][8] =\n{\n  //{ 1, 5, 11 },\n  //{ 6, 1, 11 },\n  { 1, 5, 11, 6 }, \n  { 4, 9, 10 },\n  { 7, 2, 8 },\n  { 5, 7, 8, 11 },\n  { 9, 6, 11, 10 },\n  { 3, 10, 11, 8 },\n};\nHPRef_Struct refquad_2e_2vb =\n{\n  HP_QUAD,\n  refquad_2e_2vb_splitedges, \n  refquad_2e_2vb_splitfaces, \n  0,\n  refquad_2e_2vb_newelstypes, \n  refquad_2e_2vb_newels\n};\n\n// HP_QUAD_2E_2VC\nint refquad_2e_2vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 1, 12 },\n  { 0, 0, 0 }\n};\nint refquad_2e_2vc_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_2vc_newelstypes[] =\n{\n  // HP_TRIG_SINGEDGECORNER1,\n  // HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_2E, \n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGEDGECORNER1, //SZ (vorher: SINGEDGECORNER2) \n  HP_NONE,\n};\nint refquad_2e_2vc_newels[][8] =\n{\n  { 1, 5, 9 },\n  { 6, 1, 9 },\n  { 5, 2, 7, 9 },\n  { 12, 6, 9, 8 },\n  { 7, 8, 9 },\n  { 8, 7, 10, 11 },\n  { 3, 11, 10 },\n  { 4, 12, 8 }\n};\nHPRef_Struct refquad_2e_2vc =\n{\n  HP_QUAD,\n  refquad_2e_2vc_splitedges, \n  refquad_2e_2vc_splitfaces, \n  0,\n  refquad_2e_2vc_newelstypes, \n  refquad_2e_2vc_newels\n};\n\n// HP_QUAD_2E_3V  \nint refquad_2e_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 4, 3, 8 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 2, 1, 12 },\n  { 4, 1, 13 },\n  { 0, 0, 0 }\n};\nint refquad_2e_3v_splitfaces[][4] =\n{\n  { 1, 2, 4, 9 },\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2e_3v_newelstypes[] =\n{\n  // HP_TRIG_SINGEDGECORNER1,\n  // HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_2E, \n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_NONE,\n};\nint refquad_2e_3v_newels[][8] =\n{\n  //{ 1, 5, 9 },\n  //{ 6, 1, 9 },\n  { 1, 5, 9, 6 }, \n  { 5, 12, 7, 9 },\n  { 13, 6, 9, 8 },\n  { 7, 8, 9 },\n  { 8, 7, 10, 11 },\n  { 3, 11, 10 },\n  { 12, 2, 7 },\n  { 4, 13, 8 }\n};\nHPRef_Struct refquad_2e_3v =\n{\n  HP_QUAD,\n  refquad_2e_3v_splitedges, \n  refquad_2e_3v_splitfaces, \n  0,\n  refquad_2e_3v_newelstypes, \n  refquad_2e_3v_newels\n};\n\n// HP_QUAD_2EB_0V\nint refquad_2eb_0v_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 0, 0, 0 }\n};\nint refquad_2eb_0v_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2eb_0v_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_0v_newels[][8] =\n{\n  { 1, 2, 6, 5 },\n  { 3, 4, 8, 7 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_0v =\n{\n  HP_QUAD,\n  refquad_2eb_0v_splitedges, \n  refquad_2eb_0v_splitfaces, \n  0,\n  refquad_2eb_0v_newelstypes, \n  refquad_2eb_0v_newels\n};\n\n\n// HP_QUAD_2EB_1VA\nint refquad_2eb_1va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 1, 2, 9 },\n  { 0, 0, 0 }\n};\nint refquad_2eb_1va_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2eb_1va_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_1va_newels[][8] =\n{\n  { 9, 2, 6, 5 },\n  { 3, 4, 8, 7 },\n  { 1, 9, 5 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_1va =\n{\n  HP_QUAD,\n  refquad_2eb_1va_splitedges, \n  refquad_2eb_1va_splitfaces, \n  0,\n  refquad_2eb_1va_newelstypes, \n  refquad_2eb_1va_newels\n};\n\n// HP_QUAD_2EB_1VB\nint refquad_2eb_1vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 2, 1, 9 },\n  { 0, 0, 0 }\n};\nint refquad_2eb_1vb_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2eb_1vb_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_1vb_newels[][8] =\n{\n  { 1, 9, 6, 5 },\n  { 3, 4, 8, 7 },\n  { 9, 2, 6 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_1vb =\n{\n  HP_QUAD,\n  refquad_2eb_1vb_splitedges, \n  refquad_2eb_1vb_splitfaces, \n  0,\n  refquad_2eb_1vb_newelstypes, \n  refquad_2eb_1vb_newels\n};\n\n// HP_QUAD_2EB_2VA\nint refquad_2eb_2va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 1, 2, 9 },\n  { 2, 1, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_2eb_2va_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_2va_newels[][8] =\n{\n  { 9, 10, 6, 5 },\n  { 3, 4, 8, 7 },\n  { 1, 9, 5 },\n  { 10, 2, 6 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_2va =\n{\n  HP_QUAD,\n  refquad_2eb_2va_splitedges, \n  0, 0,\n  refquad_2eb_2va_newelstypes, \n  refquad_2eb_2va_newels\n};\n\n\n\n// HP_QUAD_2EB_2VB\nint refquad_2eb_2vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 1, 2, 9 },\n  { 3, 4, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_2eb_2vb_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_2vb_newels[][8] =\n{\n  { 9, 2, 6, 5 },\n  { 10, 4, 8, 7 },\n  { 1, 9, 5 },\n  { 3, 10, 7 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_2vb =\n{\n  HP_QUAD,\n  refquad_2eb_2vb_splitedges, \n  0, 0,\n  refquad_2eb_2vb_newelstypes, \n  refquad_2eb_2vb_newels\n};\n\n\n\n// HP_QUAD_2EB_2VC\nint refquad_2eb_2vc_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 1, 2, 9 },\n  { 4, 3, 10 },\n  { 0, 0, 0 }\n};\nint refquad_2eb_2vc_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2eb_2vc_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_2vc_newels[][8] =\n{\n  { 9, 2, 6, 5 },\n  { 3, 10, 8, 7 },\n  { 1, 9, 5 },\n  { 10, 4, 8 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_2vc =\n{\n  HP_QUAD,\n  refquad_2eb_2vc_splitedges, \n  refquad_2eb_2vc_splitfaces, \n  0,\n  refquad_2eb_2vc_newelstypes, \n  refquad_2eb_2vc_newels\n};\n\n\n// HP_QUAD_2EB_2VD\nint refquad_2eb_2vd_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 2, 1, 9 },\n  { 4, 3, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_2eb_2vd_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_2vd_newels[][8] =\n{\n  { 1, 9, 6, 5 },\n  { 3, 10, 8, 7 },\n  { 9, 2, 6 },\n  { 10, 4, 8 },\n  { 5, 6, 7, 8 }\n};\nHPRef_Struct refquad_2eb_2vd =\n{\n  HP_QUAD,\n  refquad_2eb_2vd_splitedges, \n  0, 0,\n  refquad_2eb_2vd_newelstypes, \n  refquad_2eb_2vd_newels\n};\n\n\n// HP_QUAD_2EB_3VA\nint refquad_2eb_3va_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 3, 2, 9 },\n  { 4, 1, 10 },\n  { 3, 4, 11 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_2eb_3va_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_3va_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 8, 2, 6 },\n  { 3, 11, 9},\n  { 7, 8, 6, 5 },\n  { 11, 4, 10, 9 },\n  { 5, 6, 9, 10 }\n};\nHPRef_Struct refquad_2eb_3va =\n{\n  HP_QUAD,\n  refquad_2eb_3va_splitedges, \n  0, 0,\n  refquad_2eb_3va_newelstypes, \n  refquad_2eb_3va_newels\n};\n\n\n// HP_QUAD_2EB_3VB\nint refquad_2eb_3vb_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 1, 2, 7 },\n  { 2, 1, 8 },\n  { 3, 2, 9 },\n  { 4, 1, 10 },\n  { 4, 3, 11 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refquad_2eb_3vb_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_2eb_3vb_newels[][8] =\n{\n  { 1, 7, 5 },\n  { 8, 2, 6 },\n  { 11, 4, 10 },\n  { 7, 8, 6, 5 },\n  { 3, 11, 10, 9 },\n  { 5, 6, 9, 10 }\n};\nHPRef_Struct refquad_2eb_3vb =\n{\n  HP_QUAD,\n  refquad_2eb_3vb_splitedges, \n  0, 0,\n  refquad_2eb_3vb_newelstypes, \n  refquad_2eb_3vb_newels\n};\n\n\n// HP_QUAD_2EB_4V\nint refquad_2eb_4v_splitedges[][3] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 4, 1, 8 },\n  { 1, 2, 9 },\n  { 2, 1, 10 },\n  { 3, 4, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\nint refquad_2eb_4v_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 },\n};\nHPREF_ELEMENT_TYPE refquad_2eb_4v_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_NONE,\n};\nint refquad_2eb_4v_newels[][8] =\n{\n  { 9, 10, 6, 5 },\n  { 11, 12, 8, 7 },\n  { 5, 6, 7, 8 },\n  { 1, 9, 5 },\n  { 10, 2, 6 },\n  { 3, 11, 7 },\n  { 12, 4, 8 },\n};\nHPRef_Struct refquad_2eb_4v =\n{\n  HP_QUAD,\n  refquad_2eb_4v_splitedges, \n  refquad_2eb_4v_splitfaces, \n  0,\n  refquad_2eb_4v_newelstypes, \n  refquad_2eb_4v_newels\n};\n\n\n\n// HP_QUAD_3E\nint refquad_3e_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 4, 10 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint refquad_3e_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_3e_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n//   HP_TRIG_SINGEDGECORNER1,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER1,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_3e_newels[][8] =\n{\n//   { 1, 5, 13 },\n//   { 6, 1, 13 },\n//   { 7, 2, 14 },\n//   { 2, 8, 14 },\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 5, 7, 14, 13 },\n  { 8, 3, 10, 14 },\n  { 4, 6, 13, 12 },\n  { 13, 14, 10, 12 }\n};\nHPRef_Struct refquad_3e =\n{\n  HP_QUAD,\n  refquad_3e_splitedges, \n  refquad_3e_splitfaces, \n  0,\n  refquad_3e_newelstypes, \n  refquad_3e_newels\n};\n\n\n\n\n\n\n\n// HP_QUAD_3E_3VA\nint refquad_3e_3va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 4, 10 },\n  { 3, 2, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint refquad_3e_3va_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_3e_3va_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n\n//   HP_TRIG_SINGEDGECORNER1,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_3e_3va_newels[][8] =\n{\n//   { 1, 5, 13 },\n//   { 6, 1, 13 },\n//   { 7, 2, 14 },\n//   { 2, 8, 14 },\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 11, 3, 10 },\n  { 5, 7, 14, 13 },\n  { 8, 11, 10, 14 },\n  { 4, 6, 13, 12 },\n  { 13, 14, 10, 12 }\n};\nHPRef_Struct refquad_3e_3va =\n{\n  HP_QUAD,\n  refquad_3e_3va_splitedges, \n  refquad_3e_3va_splitfaces, \n  0,\n  refquad_3e_3va_newelstypes, \n  refquad_3e_3va_newels\n};\n\n// HP_QUAD_3E_3VB\nint refquad_3e_3vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint refquad_3e_3vb_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_3e_3vb_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n\n//   HP_TRIG_SINGEDGECORNER1,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER1,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_3e_3vb_newels[][8] =\n{\n//   { 1, 5, 13 },\n//   { 6, 1, 13 },\n//   { 7, 2, 14 },\n//   { 2, 8, 14 },\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 4, 11, 12 },\n  { 5, 7, 14, 13 },\n  { 8, 3, 10, 14 },\n  { 11, 6, 13, 12 },\n  { 13, 14, 10, 12 }\n};\nHPRef_Struct refquad_3e_3vb =\n{\n  HP_QUAD,\n  refquad_3e_3vb_splitedges, \n  refquad_3e_3vb_splitfaces, \n  0,\n  refquad_3e_3vb_newelstypes, \n  refquad_3e_3vb_newels\n};\n\n\n\n\n\n\n\n\n\n// HP_QUAD_3E_4V\nint refquad_3e_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 4, 10 },\n  { 3, 2, 11 },\n  { 4, 3, 12 },\n  { 4, 1, 15 },\n  { 0, 0, 0 }\n};\n\nint refquad_3e_4v_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_3e_4v_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n\n//   HP_TRIG_SINGEDGECORNER1,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER2,\n//   HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER1,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_3e_4v_newels[][8] =\n{\n//   { 1, 5, 13 },\n//   { 6, 1, 13 },\n//   { 7, 2, 14 },\n//   { 2, 8, 14 },\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 11, 3, 10 },\n  { 4, 15, 12 },\n  { 5, 7, 14, 13 },\n  { 8, 11, 10, 14 },\n  { 15, 6, 13, 12 },\n  { 13, 14, 10, 12 }\n};\nHPRef_Struct refquad_3e_4v =\n{\n  HP_QUAD,\n  refquad_3e_4v_splitedges, \n  refquad_3e_4v_splitfaces, \n  0,\n  refquad_3e_4v_newelstypes, \n  refquad_3e_4v_newels\n};\n\n\n\n\n\n\n\n\n\n// HP_QUAD_4E\nint refquad_4e_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint refquad_4e_splitfaces[][4] =\n{\n  { 1, 2, 4, 13 },\n  { 2, 3, 1, 14 },\n  { 3, 4, 2, 15 },\n  { 4, 1, 3, 16 },\n  { 0, 0, 0, 0 },\n};\n\nHPREF_ELEMENT_TYPE refquad_4e_newelstypes[] =\n{\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n  HP_QUAD_2E,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n\n  HP_QUAD,\n  HP_NONE,\n};\nint refquad_4e_newels[][8] =\n{\n  { 1, 5, 13, 6 },\n  { 2, 8, 14, 7 },\n  { 3, 10, 15, 9 },\n  { 4, 11, 16, 12 },\n  { 5, 7, 14, 13 },\n  { 8, 9, 15, 14 },\n  { 10, 12, 16, 15 },\n  { 11, 6, 13, 16 },\n  { 13, 14, 15, 16 }\n};\nHPRef_Struct refquad_4e =\n{\n  HP_QUAD,\n  refquad_4e_splitedges, \n  refquad_4e_splitfaces, \n  0,\n  refquad_4e_newelstypes, \n  refquad_4e_newels\n};\n"
  },
  {
    "path": "libsrc/meshing/hpref_segm.hpp",
    "content": "  // HP_SEGM\n  int refsegm_splitedges[][3] =\n    {\n      { 0, 0, 0 }\n    };\n  \n  HPREF_ELEMENT_TYPE refsegm_newelstypes[] =\n    {\n      HP_SEGM,\n      HP_NONE,\n    };\n  int refsegm_newels[][8] =\n    {\n      { 1, 2 },\n    };\n  HPRef_Struct refsegm =\n    {\n      HP_SEGM, \n      refsegm_splitedges, \n      0, 0, \n      refsegm_newelstypes, \n      refsegm_newels\n    };\n\n  // HP_SEGM_SINGCORNERL = 2,\n  int refsegm_scl_splitedges[][3] =\n    {\n      { 1, 2, 3 }, \n      { 0, 0, 0 }\n    };\n  \n  HPREF_ELEMENT_TYPE refsegm_scl_newelstypes[] = \n    {\n      HP_SEGM_SINGCORNERL,\n      HP_SEGM,\n      HP_NONE,\n    };\n  \n  int refsegm_scl_newels[][8] =\n    {\n      { 1, 3 },\n      { 3, 2 },\n      { 0, 0 },\n    };\n  HPRef_Struct refsegm_scl =\n    {\n      HP_SEGM,\n      refsegm_scl_splitedges,\n      0, 0,\n      refsegm_scl_newelstypes,\n      refsegm_scl_newels\n    };\n\n\n\n  // HP_SEGM_SINGCORNERR\n  int refsegm_scr_splitedges[][3] =\n    {\n      { 2, 1, 3 },\n      { 0, 0, 0 }\n    };\n\n  HPREF_ELEMENT_TYPE refsegm_scr_newelstypes[] =\n    {\n      HP_SEGM,\n      HP_SEGM_SINGCORNERR,\n      HP_NONE,\n    };\n  int refsegm_scr_newels[][8] =\n    {\n      { 1, 3 },\n      { 3, 2 },\n      { 0, 0 },\n    };\n  HPRef_Struct refsegm_scr =\n    {\n      HP_SEGM,\n      refsegm_scr_splitedges,\n      0, 0,\n      refsegm_scr_newelstypes,\n      refsegm_scr_newels\n    };\n\n\n\n\n\n\n  // HP_SEGM_SINGCORNERS = 3,\n  int refsegm_sc2_splitedges[][3] =\n    {\n      { 1, 2, 3 },\n      { 2, 1, 4 },\n      { 0, 0, 0 }\n    };\n\n  HPREF_ELEMENT_TYPE refsegm_sc2_newelstypes[] =\n    {\n      HP_SEGM_SINGCORNERL,\n      HP_SEGM_SINGCORNERR,\n      HP_SEGM,\n      HP_NONE,\n    };\n  int refsegm_sc2_newels[][8] =\n    {\n      { 1, 3 },\n      { 4, 2 },\n      { 3, 4 },\n      { 0, 0 },\n    };\n  HPRef_Struct refsegm_sc2 =\n    {  \n      HP_SEGM,\n      refsegm_sc2_splitedges,\n      0, 0, \n      refsegm_sc2_newelstypes,\n      refsegm_sc2_newels\n    };\n\n\n\n\n"
  },
  {
    "path": "libsrc/meshing/hpref_tet.hpp",
    "content": "\n\n\n\n\n\n\nenum VNUM { V1, V2, V3, V4,\n            E12, E13, E14,\n            E21, E23, E24,\n            E31, E32, E34,\n            E41, E42, E43,\n            F123, F124, F134,\n            F213, F214, F234,\n            F312, F314, F324,\n            F412, F413, F423\n};\n\nclass El\n{\npublic:\n  HPREF_ELEMENT_TYPE type;\n  std::vector<VNUM> vertices;\n\n  El (HPREF_ELEMENT_TYPE atype,\n      std::vector<VNUM> avertices)\n    : type(atype), vertices(avertices) { } \n};\n\nextern std::map<HPREF_ELEMENT_TYPE, HPRef_Struct*> & GetHPRegistry();\n\ntemplate <HPREF_ELEMENT_TYPE GEOM>\nclass HPRefStruct : public HPRef_Struct\n{\n  typedef int int3[3];\n  typedef int int4[4];\n  typedef int int8[8];  \n  std::vector<std::array<int,3>> refedges;\n  std::vector<std::array<int,4>> reffaces;\n  std::vector<HPREF_ELEMENT_TYPE> neweltypes_vec;\n  std::vector<std::array<int,8>> newelverts;\n\npublic:\n  HPRefStruct(HPREF_ELEMENT_TYPE type,\n              std::vector<El> list)\n  {\n    GetHPRegistry()[type] = this;\n    \n    geom = GEOM;\n    std::map<VNUM, int> mapnums;\n    int ii = 0;\n    for (auto v : { V1, V2, V3, V4})\n      mapnums[v] = ++ii;\n    \n    for (auto el : list)\n      for (auto v : el.vertices)\n        if (mapnums.count(v)==0)\n          mapnums[v] = ++ii;\n\n    int elist[][3] =\n      { { 1, 2, E12 },\n        { 1, 3, E13 },\n        { 1, 4, E14 },\n        { 2, 1, E21 },\n        { 2, 3, E23 },\n        { 2, 4, E24 },\n        { 3, 1, E31 },\n        { 3, 2, E32 },\n        { 3, 4, E34 },\n        { 4, 1, E41 },\n        { 4, 2, E42 },\n        { 4, 3, E43 }\n      };\n    int flist[][4] =\n      { { 1, 2, 3, F123 },\n        { 1, 2, 4, F124 },\n        { 1, 3, 4, F134 },\n        { 2, 1, 3, F213 },\n        { 2, 1, 4, F214 },\n        { 2, 3, 4, F234 },\n        { 3, 1, 2, F312 },\n        { 3, 1, 4, F314 },\n        { 3, 2, 4, F324 },\n        { 4, 1, 2, F412 },\n        { 4, 1, 3, F413 },\n        { 4, 2, 3, F423 }\n      };\n      \n    /*\n      // too advanced ...\n    for (auto [i1,i2,inew] : elist)\n      if (mapnums.count(VNUM(inew)))\n        refedges.push_back( { i1, i2, mapnums[VNUM(inew)] });\n    */\n    for (int i = 0; i < size(elist); i++)\n      {\n        int i1 = elist[i][0];\n        int i2 = elist[i][1];\n        int inew = elist[i][2];\n        if (mapnums.count(VNUM(inew)))\n          refedges.push_back( { i1, i2, mapnums[VNUM(inew)] });\n      }\n    \n    refedges.push_back( { 0, 0, 0 } );\n    splitedges = (int3*) &refedges[0][0];\n\n    /*\n      // too advanced ...\n    for (auto [i1,i2,i3,inew] : flist)\n      if (mapnums.count(VNUM(inew)))\n        reffaces.push_back( { i1, i2, i3, mapnums[VNUM(inew)] });\n    */\n    for (int i = 0; i < size(flist); i++)\n      {\n        int i1 = flist[i][0];\n        int i2 = flist[i][1];\n        int i3 = flist[i][2];\n        int inew = flist[i][3];\n        if (mapnums.count(VNUM(inew)))\n          reffaces.push_back( { i1, i2, i3, mapnums[VNUM(inew)] });\n      }\n\n\n\n    reffaces.push_back( { 0, 0, 0 } );\n    splitfaces = (int4*) &reffaces[0][0];\n    \n\n\n    splitelements = nullptr;\n    \n    for (auto el : list)\n      {\n        neweltypes_vec.push_back (el.type);\n        std::array<int,8> verts;\n        for (int j = 0; j < std::min(verts.size(), el.vertices.size()); j++)\n          verts[j] = mapnums[VNUM(el.vertices[j])];\n        newelverts.push_back(verts);\n      }\n    \n    neweltypes_vec.push_back (HP_NONE);\n\n    neweltypes = &neweltypes_vec[0];\n    newels = (int8*) &newelverts[0][0];    \n\n    /*\n    int ind = 0;\n    cout << \"rule, split edges:\" << endl;\n    while (splitedges[ind][0])\n      {\n        cout << splitedges[ind][0] << \"-\" << splitedges[ind][1] << \": \" << splitedges[ind][2] << endl;\n        ind++;\n      }\n    \n    ind = 0;\n    cout << \"rule, split faces:\" << endl;\n    while (splitfaces[ind][0])\n      {\n        cout << splitfaces[ind][0] << \"-\" << splitfaces[ind][1]\n             << \"-\" << splitfaces[ind][2] << \": \" << splitfaces[ind][3] << endl;\n        ind++;\n      }\n\n    ind = 0;\n    cout << \"rule, new els:\" << endl;\n    while (neweltypes[ind] != HP_NONE)\n      {\n        cout << \"new type \" << neweltypes[ind] << \", verts: \";\n        for (int j = 0; j < 8; j++)\n          cout << newels[ind][j] << \" \";\n        ind++;\n      }\n    */\n  }\n};\n\n\n\n\n\n \n// HP_NONETET\nint refnonetet_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE refnonetet_newelstypes[] =\n{\n  HP_TET,  \n  HP_NONE,\n};\nint refnonetet_newels[][8] =\n{\n  { 1, 1, 1, 1 },\n};\nHPRef_Struct refnonetet =\n{\n  HP_TET,\n  refnonetet_splitedges, \n  0, 0,\n  refnonetet_newelstypes, \n  refnonetet_newels\n};\n\n\n\n\n\n// HP_TET\nint reftet_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_newelstypes[] =\n{\n  HP_TET,\n  HP_NONE,\n};\nint reftet_newels[][8] =\n{\n  { 1, 2, 3, 4 },\n};\nHPRef_Struct reftet =\n{\n  HP_TET,\n  reftet_splitedges, \n  0, 0,\n  reftet_newelstypes, \n  reftet_newels\n};\n\n\n\n/* *********** Tet - Refinement - 0 edges *************** */\n\n// HP_TET_0E_1V\nint reftet_0e_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_0e_1v_newelstypes[] =\n{\n  HP_TET_0E_1V,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_0e_1v_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 5, 6, 7, 2, 3, 4 }\n};\nHPRef_Struct reftet_0e_1v =\n{\n  HP_TET,\n  reftet_0e_1v_splitedges, \n  0, 0,\n  reftet_0e_1v_newelstypes, \n  reftet_0e_1v_newels\n};\n\n/*\n  // new syntax ???\nHPRef_Struct2 str =\n  {\n    HP_TET_0E_1V, HP_TET,\n    El(HP_TET_0E_1V, { V1, V12, V13, V14 })\n  };\n*/  \n\n\n\n\n// HP_TET_0E_2V\nint reftet_0e_2v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_0e_2v_newelstypes[] =\n{\n  HP_TET_0E_1V,\n  HP_TET_0E_1V,\n  HP_PRISM,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_0e_2v_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 2, 10, 9, 8 },\n  { 5, 6, 7, 8, 9, 10 },\n  { 4, 10, 7, 3, 9, 6 },\n};\nHPRef_Struct reftet_0e_2v =\n{\n  HP_TET,\n  reftet_0e_2v_splitedges, \n  0, 0,\n  reftet_0e_2v_newelstypes, \n  reftet_0e_2v_newels\n};\n\n\n\n\n\n// HP_TET_0E_3V\nint reftet_0e_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_0e_3v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 2, 3, 1, 15 },\n    { 3, 1, 2, 16 },\n    { 0, 0, 0, 0 },\n  };\nHPREF_ELEMENT_TYPE reftet_0e_3v_newelstypes[] =\n{\n  HP_PYRAMID_0E_1V,\n  HP_PYRAMID_0E_1V,\n  HP_PYRAMID_0E_1V,\n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_0e_3v_newels[][8] =\n{\n  { 1, 5, 14, 6, 7 },\n  { 2, 9, 15, 8, 10 },\n  { 3, 11, 16, 12, 13 },\n  { 5, 14, 7, 8, 15, 10 },\n  { 9, 15, 10, 12, 16, 13 },\n  { 6, 7, 14, 11, 13, 16 },\n  { 14, 15, 16, 7, 10, 13 },\n  { 7, 10, 13, 4 }\n};\nHPRef_Struct reftet_0e_3v =\n{\n  HP_TET,\n  reftet_0e_3v_splitedges, \n  reftet_0e_3v_splitfaces, \n  0,\n  reftet_0e_3v_newelstypes, \n  reftet_0e_3v_newels\n};\n\n\n\n\n\n// HP_TET_0E_4V\nint reftet_0e_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_0e_4v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 1, 2, 4, 18 },\n    { 1, 3, 4, 19 },\n\n    { 2, 1, 3, 20 },\n    { 2, 1, 4, 21 },\n    { 2, 3, 4, 22 },\n\n    { 3, 1, 2, 23 },\n    { 3, 1, 4, 24 },\n    { 3, 2, 4, 25 },\n\n    { 4, 1, 2, 26 },\n    { 4, 1, 3, 27 },\n    { 4, 2, 3, 28 },\n    { 0, 0, 0, 0 },\n  };\nint reftet_0e_4v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 29 },\n    { 2, 3, 4, 1, 30 },\n    { 3, 4, 1, 2, 31 },\n    { 4, 1, 2, 3, 32 },\n    { 0 },\n  };\nHPREF_ELEMENT_TYPE reftet_0e_4v_newelstypes[] =\n{\n  HP_HEX_0E_1V,\n  HP_HEX_0E_1V,\n  HP_HEX_0E_1V,\n  HP_HEX_0E_1V,\n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_0e_4v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7, 18, 29, 19 },\n  { 2, 9, 20, 8, 10, 22, 30, 21 },\n  { 3, 11, 23, 12, 13, 24, 31, 25 },\n  { 4, 15, 26, 14, 16, 28, 32, 27 },\n  { 5, 17, 18, 8, 20, 21 },\n  { 18, 17, 29, 21, 20, 30 },\n  { 6, 19, 17,  11, 24, 23 },\n  { 17, 19, 29,  23, 24, 31 },\n  { 7, 18, 19, 14, 26, 27 },\n  { 19, 18, 29, 27, 26, 32 },\n  { 9, 20, 22, 12, 23, 25 },\n  { 22, 20, 30, 25, 23, 31 },\n  { 10, 22, 21, 15, 28, 26 },\n  { 21, 22, 30, 26, 28, 32 },\n  { 13, 24, 25, 16, 27, 28 },\n  { 25, 24, 31, 28, 27, 32 },\n  { 17, 20, 23, 29, 30, 31 },\n  { 18, 26, 21, 29, 32, 30 },\n  { 19, 24, 27, 29, 31, 32 },\n  { 22, 28, 25, 30, 32, 31 },\n  { 29, 30, 31, 32 },\n};\nHPRef_Struct reftet_0e_4v =\n{\n  HP_TET,\n  reftet_0e_4v_splitedges, \n  reftet_0e_4v_splitfaces, \n  reftet_0e_4v_splitelements, \n  reftet_0e_4v_newelstypes, \n  reftet_0e_4v_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* *********** Tet - Refinement - 1 edge *************** */\n\n\n\n// HP_TET_1E_0V\nint reftet_1e_0v_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 2, 4, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1e_0v_newelstypes[] =\n{\n  HP_PRISM_SINGEDGE,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_1e_0v_newels[][8] =\n{\n  { 1, 5, 6, 2, 7, 8 },\n  { 7, 3, 5, 8, 4, 6 }\n};\nHPRef_Struct reftet_1e_0v =\n{\n  HP_TET,\n  reftet_1e_0v_splitedges, \n  0, 0,\n  reftet_1e_0v_newelstypes, \n  reftet_1e_0v_newels\n};\n\n\n\n\n\n// HP_TET_1E_1VA\nint reftet_1e_1va_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 2, 4, 8 },\n  { 1, 2, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1e_1va_newelstypes[] =\n{\n  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_1e_1va_newels[][8] =\n{\n  { 1, 9, 5, 6 },\n  { 9, 5, 6, 2, 7, 8 },\n  { 7, 3, 5, 8, 4, 6 }\n};\nHPRef_Struct reftet_1e_1va =\n{\n  HP_TET,\n  reftet_1e_1va_splitedges, \n  0, 0,\n  reftet_1e_1va_newelstypes, \n  reftet_1e_1va_newels\n};\n\n\n\n\n\n\n// HP_TET_1E_1VB\nint reftet_1e_1vb_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 2, 4, 8 },\n  { 4, 1, 9 },\n  { 4, 2, 10 },\n  { 4, 3, 11 },\n  { 0, 0, 0 }\n};\nint reftet_1e_1vb_splitelements[][5] =\n{\n  { 4, 1, 2, 3, 12 },\n  { 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1e_1vb_newelstypes[] =\n{\n  HP_PRISM_SINGEDGE,\n  HP_TET_0E_1V,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID, \n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1e_1vb_newels[][8] =\n{\n  { 1, 5, 6, 2, 7, 8 },\n  { 4, 11, 10, 9 },\n  { 7, 8, 10, 11, 12 },\n  { 3, 7, 11, 12 },\n  { 5, 11, 9, 6, 12 },\n  { 5, 3, 11, 12 },\n  { 6, 9, 10, 8, 12 },\n  { 5, 7, 3, 12 },\n  { 5, 6, 8, 7, 12 },\n  { 9, 11, 10, 12 }\n};\nHPRef_Struct reftet_1e_1vb =\n{\n  HP_TET,\n  reftet_1e_1vb_splitedges, \n  0,\n  reftet_1e_1vb_splitelements, \n  reftet_1e_1vb_newelstypes, \n  reftet_1e_1vb_newels\n};\n\n\n\n\n\n\n\n\n// HP_TET_1E_2VA\nint reftet_1e_2va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1e_2va_newelstypes[] =\n{\n  HP_TET_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_1e_2va_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n  { 5, 6, 7, 8, 9, 10 },\n  { 4, 10, 7, 3, 9, 6 },\n};\nHPRef_Struct reftet_1e_2va =\n{\n  HP_TET,\n  reftet_1e_2va_splitedges, \n  0, 0,\n  reftet_1e_2va_newelstypes, \n  reftet_1e_2va_newels\n};\n\n\n\n\n\n\n\n// HP_TET_1E_2VB\nint reftet_1e_2vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 1, 10 },\n  { 3, 2, 11 },\n  { 3, 4, 12 },\n  { 0, 0, 0 }\n};\nint reftet_1e_2vb_splitelements[][5] =\n{\n  { 3, 4, 1, 2, 13 },\n  { 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1e_2vb_newelstypes[] =\n{\n  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_TET_0E_1V,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID, \n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1e_2vb_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 5, 6, 7, 2, 8, 9 },\n  { 3, 10, 11, 12 },\n\n  { 8, 9, 12, 11, 13 },\n  { 4, 12, 9, 13 },\n  { 6, 10, 12, 7, 13 },\n  { 4, 7, 12, 13 },\n  { 6, 8, 11, 10, 13 },\n  { 4, 9, 7, 13 },\n  { 6, 7, 9, 8, 13 },\n  { 10, 11, 12, 13 },\n};\nHPRef_Struct reftet_1e_2vb =\n{\n  HP_TET,\n  reftet_1e_2vb_splitedges, \n  0,\n  reftet_1e_2vb_splitelements, \n  reftet_1e_2vb_newelstypes, \n  reftet_1e_2vb_newels\n};\n\n\n\n\n\n\n// HP_TET_1E_2VC\nint reftet_1e_2vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 4, 1, 10 },\n  { 4, 2, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\nint reftet_1e_2vc_splitelements[][5] =\n{\n  { 4, 1, 2, 3, 13 },\n  { 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1e_2vc_newelstypes[] =\n{\n  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_TET_0E_1V,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID, \n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1e_2vc_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 5, 6, 7, 2, 8, 9 },\n  { 4, 11, 10, 12 },\n  { 8, 9, 11, 12, 13 },\n  { 3, 8, 12, 13 },\n  { 7, 6, 12, 10, 13 },\n  { 3, 12, 6, 13 },\n  { 9, 7, 10, 11, 13 },\n  { 3, 6, 8, 13 },\n  { 6, 7, 9, 8, 13 },\n  { 10, 12, 11, 13 }\n};\nHPRef_Struct reftet_1e_2vc =\n{\n  HP_TET,\n  reftet_1e_2vc_splitedges, \n  0,\n  reftet_1e_2vc_splitelements, \n  reftet_1e_2vc_newelstypes, \n  reftet_1e_2vc_newels\n};\n\n\n\n\n\n\n\n\n/*\n\n// HP_TET_1E_2VD\nint reftet_1e_2vd_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 2, 4, 8 },\n  { 3, 1, 9 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 1, 12 },\n  { 4, 2, 13 },\n  { 4, 3, 14 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] =\n{\n  HP_PRISM_SINGEDGE,\n  HP_TET_0E_1V,\n  HP_TET_0E_1V,\n  HP_PRISM,\n  HP_HEX,\n  HP_NONE,\n};\nint reftet_1e_2vd_newels[][8] =\n{\n  { 1, 5, 6, 2, 7, 8 },\n  { 4, 13, 12, 14 },\n  { 3, 10, 11, 9 },\n  { 14, 13, 12, 11, 10, 9 },\n  { 6, 12, 13, 8, 5, 9, 10, 7 },\n};\nHPRef_Struct reftet_1e_2vd =\n{\n  HP_TET,\n  reftet_1e_2vd_splitedges, \n  0, 0,\n  reftet_1e_2vd_newelstypes, \n  reftet_1e_2vd_newels\n};\n\n*/\n\n\n\n\n//  HP_TET_1E_2VD,  // 1 v on edge\nint reftet_1e_2vd_splitedges[][3] =\n{\n  // { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  // { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_1e_2vd_splitfaces[][4] =\n  {\n    { 1, 3, 4, 19 },\n    { 2, 3, 4, 22 },\n    { 3, 1, 4, 24 },\n    { 3, 2, 4, 25 },\n    { 4, 1, 3, 27 },\n    { 4, 2, 3, 28 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_TET_0E_1V,\n    HP_TET_0E_1V,\n    HP_PRISM,\n    HP_HEX,\n    HP_PYRAMID,\n    HP_HEX,\n    HP_PYRAMID,\n    HP_PRISM,\n    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_1e_2vd_newels[][8] =\n{\n  { 1, 6, 7, 2, 9, 10 },\n  { 3, 11, 12, 13 },\n  { 4, 16, 15, 14 },\n  { 7, 6, 19, 10, 9, 22 },\n  { 7, 19, 27, 14, 10, 22, 28, 15 },\n  { 14, 15, 28, 27, 16 },\n  { 9, 6, 19, 22, 12, 11, 24, 25 },\n  { 12, 11, 24, 25, 13 },\n  { 19, 24, 27, 22, 25, 28 },\n  { 16, 28, 27, 13, 25, 24 }\n};\nHPRef_Struct reftet_1e_2vd =\n{\n  HP_TET,\n  reftet_1e_2vd_splitedges, \n  reftet_1e_2vd_splitfaces, \n  0,\n  reftet_1e_2vd_newelstypes, \n  reftet_1e_2vd_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// HP_TET_1E_3VA\nint reftet_1e_3va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_1e_3va_splitelements[][5] =\n{\n  { 1, 2, 3, 4, 14 },\n  { 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1e_3va_newelstypes[] =\n{\n  HP_PRISM_SINGEDGE,\n  HP_TET_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_TET_0E_1V,\n\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID, \n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_PYRAMID,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1e_3va_newels[][8] =\n{\n  { 5, 6, 7, 8, 9, 10 },\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n  { 3, 11, 12, 13 },\n\n  { 6, 7, 10, 9, 14 },\n  { 4, 10, 7, 14 },\n  { 9, 10, 13, 12, 14 },\n  { 4, 13, 10, 14 },\n  { 6, 11, 13, 7, 14 },\n  { 4, 7, 13, 14 },\n  { 6, 11, 12, 9, 14 },\n  { 11, 13, 12, 14 },\n};\n\nHPRef_Struct reftet_1e_3va =\n{\n  HP_TET,\n  reftet_1e_3va_splitedges, \n  0,\n  reftet_1e_3va_splitelements, \n  reftet_1e_3va_newelstypes, \n  reftet_1e_3va_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_1E_3VB,  // 1 v on edge\nint reftet_1e_3vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  // { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_1e_3vb_splitfaces[][4] =\n  {\n    { 1, 3, 4, 19 },\n    { 2, 3, 4, 22 },\n    { 3, 1, 4, 24 },\n    { 3, 2, 4, 25 },\n    { 4, 1, 3, 27 },\n    { 4, 2, 3, 28 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_1e_3vb_newelstypes[] =\n  {\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_TET_0E_1V,\n    HP_TET_0E_1V,\n    HP_PRISM,\n    HP_HEX,\n    HP_PYRAMID,\n    HP_HEX,\n    HP_PYRAMID,\n    HP_PRISM,\n    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_1e_3vb_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 5, 6, 7, 2, 9, 10 },\n  { 3, 11, 12, 13 },\n  { 4, 16, 15, 14 },\n  { 7, 6, 19, 10, 9, 22 },\n  { 7, 19, 27, 14, 10, 22, 28, 15 },\n  { 14, 15, 28, 27, 16 },\n  { 9, 6, 19, 22, 12, 11, 24, 25 },\n  { 12, 11, 24, 25, 13 },\n  { 19, 24, 27, 22, 25, 28 },\n  { 16, 28, 27, 13, 25, 24 }\n};\nHPRef_Struct reftet_1e_3vb =\n{\n  HP_TET,\n  reftet_1e_3vb_splitedges, \n  reftet_1e_3vb_splitfaces, \n  0,\n  reftet_1e_3vb_newelstypes, \n  reftet_1e_3vb_newels\n};\n\n\n\n\n\n\n/*\n// HP_TET_1E_4V\nint reftet_1e_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_1e_4v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 1, 2, 4, 18 },\n    { 1, 3, 4, 19 },\n\n    { 2, 1, 3, 20 },\n    { 2, 1, 4, 21 },\n    { 2, 3, 4, 22 },\n\n    { 3, 1, 2, 23 },\n    { 3, 1, 4, 24 },\n    { 3, 2, 4, 25 },\n\n    { 4, 1, 2, 26 },\n    { 4, 1, 3, 27 },\n    { 4, 2, 3, 28 },\n    { 0, 0, 0, 0 },\n  };\nint reftet_1e_4v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 29 },\n    { 2, 3, 4, 1, 30 },\n    { 3, 4, 1, 2, 31 },\n    { 4, 1, 2, 3, 32 },\n    { 0 },\n  };\nHPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] =\n{\n  HP_HEX_1E_1V,\n  HP_HEX_1E_1V,\n  HP_HEX_0E_1V,\n  HP_HEX_0E_1V,\n  HP_PRISM_SINGEDGE, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM, HP_PRISM, \n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_PRISM,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1e_4v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7, 18, 29, 19 },\n  //  { 2, 9, 20, 8, 10, 22, 30, 21 },\n  { 2, 8, 21, 10, 9, 20, 30, 22 },\n  { 3, 11, 23, 12, 13, 24, 31, 25 },\n  { 4, 15, 26, 14, 16, 28, 32, 27 },\n  { 5, 17, 18, 8, 20, 21 },\n  { 18, 17, 29, 21, 20, 30 },\n  { 6, 19, 17,  11, 24, 23 },\n  { 17, 19, 29,  23, 24, 31 },\n  { 7, 18, 19, 14, 26, 27 },\n  { 19, 18, 29, 27, 26, 32 },\n  { 9, 20, 22, 12, 23, 25 },\n  { 22, 20, 30, 25, 23, 31 },\n  { 10, 22, 21, 15, 28, 26 },\n  { 21, 22, 30, 26, 28, 32 },\n  { 13, 24, 25, 16, 27, 28 },\n  { 25, 24, 31, 28, 27, 32 },\n  { 17, 20, 23, 29, 30, 31 },\n  { 18, 26, 21, 29, 32, 30 },\n  { 19, 24, 27, 29, 31, 32 },\n  { 22, 28, 25, 30, 32, 31 },\n\n  { 29, 30, 31, 32 },\n};\nHPRef_Struct reftet_1e_4v =\n{\n  HP_TET,\n  reftet_1e_4v_splitedges, \n  reftet_1e_4v_splitfaces, \n  reftet_1e_4v_splitelements, \n  reftet_1e_4v_newelstypes, \n  reftet_1e_4v_newels\n};\n*/\n\n\n\n\n// HP_TET_1E_4V\nint reftet_1e_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_1e_4v_splitfaces[][4] =\n  {\n    { 1, 3, 4, 17 },\n    { 2, 3, 4, 18 },\n\n    { 3, 1, 4, 19 },\n    { 3, 2, 4, 20 },\n\n    { 4, 1, 3, 21 },\n    { 4, 2, 3, 22 },\n    { 0, 0, 0, 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] =\n{\n  HP_TET_1E_1VA,\n  HP_TET_1E_1VA,\n  //  HP_TET_1E_1VA,\n  //  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM,\n  HP_HEX, \n  HP_HEX, \n  HP_PRISM,\n  HP_PRISM,\n\n  HP_PYRAMID,\n  HP_TET_0E_1V,\n\n  HP_PYRAMID,\n  HP_TET_0E_1V,\n\n  HP_NONE,\n};\n\nint reftet_1e_4v_newels[][8] =\n{\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n\n  { 5, 6, 7, 8, 9, 10 },\n  { 7, 6, 17, 10, 9, 18 },\n\n  { 7, 10, 18, 17, 14, 15, 22, 21 },\n  { 9, 6, 17, 18, 12, 11, 19, 20 },\n\n  { 17, 19, 21, 18, 20, 22 },\n  { 16, 22, 21, 13, 20, 19 },\n\n  { 14, 15, 22, 21, 16 },\n  { 4, 14, 16, 15 },\n  { 12, 11, 19, 20, 13 },\n  { 3, 11, 12, 13 },\n\n\n\n  { 1, 5, 17, 6, 7, 18, 29, 19 },\n  //  { 2, 9, 20, 8, 10, 22, 30, 21 },\n  { 2, 8, 21, 10, 9, 20, 30, 22 },\n  { 3, 11, 23, 12, 13, 24, 31, 25 },\n  { 4, 15, 26, 14, 16, 28, 32, 27 },\n  { 5, 17, 18, 8, 20, 21 },\n  { 18, 17, 29, 21, 20, 30 },\n  { 6, 19, 17,  11, 24, 23 },\n  { 17, 19, 29,  23, 24, 31 },\n  { 7, 18, 19, 14, 26, 27 },\n  { 19, 18, 29, 27, 26, 32 },\n  { 9, 20, 22, 12, 23, 25 },\n  { 22, 20, 30, 25, 23, 31 },\n  { 10, 22, 21, 15, 28, 26 },\n  { 21, 22, 30, 26, 28, 32 },\n  { 13, 24, 25, 16, 27, 28 },\n  { 25, 24, 31, 28, 27, 32 },\n  { 17, 20, 23, 29, 30, 31 },\n  { 18, 26, 21, 29, 32, 30 },\n  { 19, 24, 27, 29, 31, 32 },\n  { 22, 28, 25, 30, 32, 31 },\n\n  { 29, 30, 31, 32 },\n};\nHPRef_Struct reftet_1e_4v =\n{\n  HP_TET,\n  reftet_1e_4v_splitedges, \n  reftet_1e_4v_splitfaces, \n  0, \n  reftet_1e_4v_newelstypes, \n  reftet_1e_4v_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_2EA_0V,  // 2 edges connected\nint reftet_2ea_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_0v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_0v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_2ea_0v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 5, 17, 7, 2, 9, 10 },\n  { 6, 7, 17, 3, 13, 12 },\n  { 17, 9, 12, 7, 10, 13 },\n  { 7, 10, 13, 4 },\n};\nHPRef_Struct reftet_2ea_0v =\n{\n  HP_TET,\n  reftet_2ea_0v_splitedges, \n  reftet_2ea_0v_splitfaces, \n  0,\n  reftet_2ea_0v_newelstypes, \n  reftet_2ea_0v_newels\n};\n\n\n\n\n\n\n//  HP_TET_2EA_1VA,  // 2 edges connected\nint reftet_2ea_1va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_1va_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_1va_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_2ea_1va_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 5, 17, 7, 8, 9, 10 },\n  { 2, 8, 10, 9 },\n  { 6, 7, 17, 3, 13, 12 },\n  { 17, 9, 12, 7, 10, 13 },\n  { 7, 10, 13, 4 },\n};\nHPRef_Struct reftet_2ea_1va =\n{\n  HP_TET,\n  reftet_2ea_1va_splitedges, \n  reftet_2ea_1va_splitfaces, \n  0,\n  reftet_2ea_1va_newelstypes, \n  reftet_2ea_1va_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_2EA_1VB, \nint reftet_2ea_1vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_1vb_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_1vb_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_2ea_1vb_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 3, 11, 12, 13 },\n  { 5, 17, 7, 2, 9, 10 },\n  { 6, 7, 17, 11, 13, 12 },\n  { 17, 9, 12, 7, 10, 13 },\n  { 7, 10, 13, 4 },\n};\nHPRef_Struct reftet_2ea_1vb =\n{\n  HP_TET,\n  reftet_2ea_1vb_splitedges, \n  reftet_2ea_1vb_splitfaces, \n  0,\n  reftet_2ea_1vb_newelstypes, \n  reftet_2ea_1vb_newels\n};\n\n\n\n\n\n\n//  HP_TET_2EA_1VC,  // 2 edges connected\nint reftet_2ea_1vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  //  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_1vc_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 3, 4, 18 },\n    { 3, 4, 2, 19 },\n    { 4, 2, 3, 20 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_2ea_1vc_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 21 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_1vc_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    //    HP_TET_1E_1VA,\n    HP_TET_0E_1V,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n\n    HP_TET, HP_TET, HP_TET, HP_TET, \n    HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, \n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    //     HP_PRISM,\n    //    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_2ea_1vc_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  // { 3, 11, 12, 13 },\n  { 4, 15, 14, 16 }, \n  { 5, 17, 7, 2, 9, 10 },\n  { 6, 7, 17, 3, 13, 12 },\n \n  { 9, 10, 18, 21 },\n  { 13, 12, 19, 21 },\n  { 15, 16, 20, 21 },\n  { 18, 20, 19, 21 },\n  { 10, 15, 20, 18, 21 },\n  { 13, 19, 20, 16, 21 },\n  { 9, 18, 19, 12, 21 },\n  \n  { 7, 13, 16, 14, 21 },\n  { 7, 14, 15, 10, 21 },\n  { 9, 12, 17, 21 },\n  { 7, 10, 9, 17, 21 },\n  { 7, 17, 12, 13, 21 },\n  { 14, 16, 15, 21 },\n  //  { 17, 9, 12, 7, 10, 13 },\n  //  { 7, 10, 13, 14, 15, 16 },\n};\nHPRef_Struct reftet_2ea_1vc =\n{\n  HP_TET,\n  reftet_2ea_1vc_splitedges, \n  reftet_2ea_1vc_splitfaces, \n  reftet_2ea_1vc_splitelements, \n  reftet_2ea_1vc_newelstypes, \n  reftet_2ea_1vc_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n \n//  HP_TET_2EA_2VA, \nint reftet_2ea_2va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_2va_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_2va_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_2ea_2va_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 3, 11, 12, 13 },\n  { 2, 8, 10, 9 },\n  { 5, 17, 7, 8, 9, 10 },\n  { 6, 7, 17, 11, 13, 12 },\n  { 17, 9, 12, 7, 10, 13 },\n  { 7, 10, 13, 4 },\n};\nHPRef_Struct reftet_2ea_2va =\n{\n  HP_TET,\n  reftet_2ea_2va_splitedges, \n  reftet_2ea_2va_splitfaces, \n  0,\n  reftet_2ea_2va_newelstypes, \n  reftet_2ea_2va_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_2EA_2VB,  // 2 edges connected\nint reftet_2ea_2vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  //  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_2vb_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 3, 4, 18 },\n    { 3, 4, 2, 19 },\n    { 4, 2, 3, 20 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_2ea_2vb_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 21 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_2vb_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    //  HP_TET_1E_1VA,\n    HP_TET_0E_1V,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n\n    HP_TET, HP_TET, HP_TET, HP_TET, \n    HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, \n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    //     HP_PRISM,\n    //    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_2ea_2vb_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 2, 8, 10, 9 },\n  //  { 3, 11, 12, 13 },\n  { 4, 15, 14, 16 }, \n  { 5, 17, 7, 8, 9, 10 },\n  { 6, 7, 17, 3, 13, 12 },\n \n  { 9, 10, 18, 21 },\n  { 13, 12, 19, 21 },\n  { 15, 16, 20, 21 },\n  { 18, 20, 19, 21 },\n  { 10, 15, 20, 18, 21 },\n  { 13, 19, 20, 16, 21 },\n  { 9, 18, 19, 12, 21 },\n  \n  { 7, 13, 16, 14, 21 },\n  { 7, 14, 15, 10, 21 },\n  { 9, 12, 17, 21 },\n  { 7, 10, 9, 17, 21 },\n  { 7, 17, 12, 13, 21 },\n  { 14, 16, 15, 21 },\n  //  { 17, 9, 12, 7, 10, 13 },\n  //  { 7, 10, 13, 14, 15, 16 },\n};\nHPRef_Struct reftet_2ea_2vb =\n{\n  HP_TET,\n  reftet_2ea_2vb_splitedges, \n  reftet_2ea_2vb_splitfaces, \n  reftet_2ea_2vb_splitelements, \n  reftet_2ea_2vb_newelstypes, \n  reftet_2ea_2vb_newels\n};\n\n\n\n\n\n\n\n \n\n\n//  HP_TET_2EA_2VC,  // 2 edges connected\nint reftet_2ea_2vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  //  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_2vc_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 3, 4, 18 },\n    { 3, 4, 2, 19 },\n    { 4, 2, 3, 20 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_2ea_2vc_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 21 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_2vc_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_TET_0E_1V,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n\n    HP_TET, HP_TET, HP_TET, HP_TET, \n    HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, \n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    //     HP_PRISM,\n    //    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_2ea_2vc_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  //  { 2, 8, 10, 9 },\n  { 3, 11, 12, 13 },\n  { 4, 15, 14, 16 }, \n  { 5, 17, 7, 2, 9, 10 },\n  { 6, 7, 17, 11, 13, 12 },\n \n  { 9, 10, 18, 21 },\n  { 13, 12, 19, 21 },\n  { 15, 16, 20, 21 },\n  { 18, 20, 19, 21 },\n  { 10, 15, 20, 18, 21 },\n  { 13, 19, 20, 16, 21 },\n  { 9, 18, 19, 12, 21 },\n  \n  { 7, 13, 16, 14, 21 },\n  { 7, 14, 15, 10, 21 },\n  { 9, 12, 17, 21 },\n  { 7, 10, 9, 17, 21 },\n  { 7, 17, 12, 13, 21 },\n  { 14, 16, 15, 21 },\n  //  { 17, 9, 12, 7, 10, 13 },\n  //  { 7, 10, 13, 14, 15, 16 },\n};\nHPRef_Struct reftet_2ea_2vc =\n{\n  HP_TET,\n  reftet_2ea_2vc_splitedges, \n  reftet_2ea_2vc_splitfaces, \n  reftet_2ea_2vc_splitelements, \n  reftet_2ea_2vc_newelstypes, \n  reftet_2ea_2vc_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_2EA_3V,  // 2 edges connected\nint reftet_2ea_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_2ea_3v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 3, 4, 18 },\n    { 3, 4, 2, 19 },\n    { 4, 2, 3, 20 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_2ea_3v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 21 },\n    { 0, 0, 0, 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_2ea_3v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_TET_0E_1V,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n\n    HP_TET, HP_TET, HP_TET, HP_TET, \n    HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, \n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    HP_PYRAMID, HP_PYRAMID, HP_TET,\n    //     HP_PRISM,\n    //    HP_PRISM,\n    HP_NONE,\n  };\nint reftet_2ea_3v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 2, 8, 10, 9 },\n  { 3, 11, 12, 13 },\n  { 4, 15, 14, 16 }, \n  { 5, 17, 7, 8, 9, 10 },\n  { 6, 7, 17, 11, 13, 12 },\n \n  { 9, 10, 18, 21 },\n  { 13, 12, 19, 21 },\n  { 15, 16, 20, 21 },\n  { 18, 20, 19, 21 },\n  { 10, 15, 20, 18, 21 },\n  { 13, 19, 20, 16, 21 },\n  { 9, 18, 19, 12, 21 },\n  \n  { 7, 13, 16, 14, 21 },\n  { 7, 14, 15, 10, 21 },\n  { 9, 12, 17, 21 },\n  { 7, 10, 9, 17, 21 },\n  { 7, 17, 12, 13, 21 },\n  { 14, 16, 15, 21 },\n  //  { 17, 9, 12, 7, 10, 13 },\n  //  { 7, 10, 13, 14, 15, 16 },\n};\nHPRef_Struct reftet_2ea_3v =\n{\n  HP_TET,\n  reftet_2ea_3v_splitedges, \n  reftet_2ea_3v_splitfaces, \n  reftet_2ea_3v_splitelements, \n  reftet_2ea_3v_newelstypes, \n  reftet_2ea_3v_newels\n};\n\n\n\n\n\n\n\n//  HP_TET_2EB_0V,  // 2 opposite edges\nint reftet_2eb_0v_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 3, 7 },\n  { 2, 4, 8 },\n  { 3, 1, 9 },\n  { 3, 2, 10 },\n  { 4, 1, 11 },\n  { 4, 2, 12 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_0v_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_0v_newels[][8] =\n{\n  { 1, 5, 6, 2, 7, 8 },\n  { 3, 9, 10, 4, 11, 12 },\n  { 6, 11, 12, 8, 5, 9, 10, 7 },\n};\nHPRef_Struct reftet_2eb_0v =\n{\n  HP_TET,\n  reftet_2eb_0v_splitedges, \n  0, 0,\n  reftet_2eb_0v_newelstypes, \n  reftet_2eb_0v_newels\n};\n\n\n//  HP_TET_2EB_1V,    // V1\n\n\n//  HP_TET_2EB_1V,  // 2 opposite edges, V1\nint reftet_2eb_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_1v_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_1v_newels[][8] =\n{\n  { 5, 6, 7, 2, 9, 10 },\n  { 4, 15, 14, 3, 12, 11 },\n  { 1, 5, 6, 7 },\n  //  { 2, 8, 10, 9 },\n  //  { 3, 13, 11, 12 },\n  //  { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_1v =\n{\n  HP_TET,\n  reftet_2eb_1v_splitedges, \n  0, 0,\n  reftet_2eb_1v_newelstypes, \n  reftet_2eb_1v_newels\n};\n\n\n\n//  HP_TET_2EB_2VA,  // 2 opposite edges, V1,2\nint reftet_2eb_2va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_2va_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_2va_newels[][8] =\n{\n  { 5, 6, 7, 8, 9, 10 },\n  { 4, 15, 14, 3, 12, 11 },\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n  //  { 3, 13, 11, 12 },\n  //  { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_2va =\n{\n  HP_TET,\n  reftet_2eb_2va_splitedges, \n  0, 0,\n  reftet_2eb_2va_newelstypes, \n  reftet_2eb_2va_newels\n};\n\n\n//  HP_TET_2EB_2VB,   // V1,3\nint reftet_2eb_2vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_2vb_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    // HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    // HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_2vb_newels[][8] =\n{\n  { 5, 6, 7, 2, 9, 10 },\n  { 4, 15, 14, 13, 12, 11 },\n  { 1, 5, 6, 7 },\n  // { 2, 8, 10, 9 },\n  { 3, 13, 11, 12 },\n  // { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_2vb =\n{\n  HP_TET,\n  reftet_2eb_2vb_splitedges, \n  0, 0,\n  reftet_2eb_2vb_newelstypes, \n  reftet_2eb_2vb_newels\n};\n\n\n\n\n//  HP_TET_2EB_2VC,   // V1,4\nint reftet_2eb_2vc_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_2vc_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    // HP_TET_1E_1VA,\n    // HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_2vc_newels[][8] =\n{\n  { 5, 6, 7, 2, 9, 10 },\n  { 16, 15, 14, 3, 12, 11 },\n  { 1, 5, 6, 7 },\n  // { 2, 8, 10, 9 },\n  // { 3, 13, 11, 12 },\n  { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_2vc =\n{\n  HP_TET,\n  reftet_2eb_2vc_splitedges, \n  0, 0,\n  reftet_2eb_2vc_newelstypes, \n  reftet_2eb_2vc_newels\n};\n\n\n\n\n\n\n//  HP_TET_2EB_3V,    // V1,2,3\nint reftet_2eb_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_3v_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    // HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_3v_newels[][8] =\n{\n  { 5, 6, 7, 8, 9, 10 },\n  { 4, 15, 14, 13, 12, 11 },\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n  { 3, 13, 11, 12 },\n  // { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_3v =\n{\n  HP_TET,\n  reftet_2eb_3v_splitedges, \n  0, 0,\n  reftet_2eb_3v_newelstypes, \n  reftet_2eb_3v_newels\n};\n\n\n\n\n\n\n//  HP_TET_2EB_4V,  // 2 opposite edges\nint reftet_2eb_4v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_2eb_4v_newelstypes[] =\n  {\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_HEX,\n    HP_NONE,\n  };\nint reftet_2eb_4v_newels[][8] =\n{\n  { 5, 6, 7, 8, 9, 10 },\n  { 16, 15, 14, 13, 12, 11 },\n  { 1, 5, 6, 7 },\n  { 2, 8, 10, 9 },\n  { 3, 13, 11, 12 },\n  { 4, 16, 15, 14 },\n  { 7, 14, 15, 10, 6, 11, 12, 9 }\n};\nHPRef_Struct reftet_2eb_4v =\n{\n  HP_TET,\n  reftet_2eb_4v_splitedges, \n  0, 0,\n  reftet_2eb_4v_newelstypes, \n  reftet_2eb_4v_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_3EA_0V,  \nint reftet_3ea_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 0, 0, 0 }\n};\nint reftet_3ea_0v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 1, 2, 4, 15 },\n    { 1, 3, 4, 16 },\n    { 2, 3, 4, 17 },\n    { 3, 4, 2, 18 },\n    { 4, 2, 3, 19 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ea_0v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ea_0v_newelstypes[] =\n  {\n    HP_HEX_3E_0V,\n    HP_HEX_1E_0V,\n    HP_HEX_1E_0V,\n    HP_HEX_1E_0V,\n    HP_PRISM,\n    HP_PRISM,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_3ea_0v_newels[][8] =\n{\n  { 1, 5, 14, 6, 7, 15, 20, 16 },\n  { 5, 2, 8, 14, 15, 9, 17, 20 },\n  { 3, 6, 14, 10, 11, 16, 20, 18 },\n  { 7, 4, 12, 15, 16, 13, 19, 20 },\n  { 11, 13, 16, 18, 19, 20 },\n  { 15, 12, 9, 20, 19, 17 },\n  { 8, 10, 14, 17, 18, 20 },\n  { 20, 17, 18, 19 },\n};\nHPRef_Struct reftet_3ea_0v =\n{\n  HP_TET,\n  reftet_3ea_0v_splitedges, \n  reftet_3ea_0v_splitfaces, \n  reftet_3ea_0v_splitelements, \n  reftet_3ea_0v_newelstypes, \n  reftet_3ea_0v_newels\n};\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_3EA_1V,  \nint reftet_3ea_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 2, 1, 21 },\n  { 3, 1, 22 },\n  { 4, 1, 23 },\n  { 0, 0, 0 }\n};\nint reftet_3ea_1v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 1, 2, 4, 15 },\n    { 1, 3, 4, 16 },\n    { 2, 3, 4, 17 },\n    { 3, 4, 2, 18 },\n    { 4, 2, 3, 19 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ea_1v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ea_1v_newelstypes[] =\n  {\n    HP_HEX_3E_0V,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n\n    HP_PRISM,\n    HP_PRISM,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_3ea_1v_newels[][8] =\n{\n  { 1, 5, 14, 6, 7, 15, 20, 16 },\n\n  { 2, 21, 9, 8 },\n  { 5, 14, 15, 21, 8, 9 },\n  { 15, 14, 20, 9, 8, 17 },\n  //  { 3, 22, 10, 11 },\n  //  { 6, 16, 14, 22, 11, 10 },\n  { 6, 16, 14, 3, 11, 10 },\n  { 14, 16, 20, 10, 11, 18 },\n  //  { 4, 23, 13, 12 },\n  //  { 7, 15, 16, 23, 12, 13 },\n  { 7, 15, 16, 4, 12, 13 },\n  { 16, 15, 20, 13, 12, 19 },\n\n  { 11, 13, 16, 18, 19, 20 },\n  { 15, 12, 9, 20, 19, 17 },\n  { 8, 10, 14, 17, 18, 20 },\n  { 20, 17, 18, 19 },\n};\nHPRef_Struct reftet_3ea_1v =\n{\n  HP_TET,\n  reftet_3ea_1v_splitedges, \n  reftet_3ea_1v_splitfaces, \n  reftet_3ea_1v_splitelements, \n  reftet_3ea_1v_newelstypes, \n  reftet_3ea_1v_newels\n};\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_3EA_2V,  \nint reftet_3ea_2v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 2, 1, 21 },\n  { 3, 1, 22 },\n  { 4, 1, 23 },\n  { 0, 0, 0 }\n};\nint reftet_3ea_2v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 1, 2, 4, 15 },\n    { 1, 3, 4, 16 },\n    { 2, 3, 4, 17 },\n    { 3, 4, 2, 18 },\n    { 4, 2, 3, 19 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ea_2v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ea_2v_newelstypes[] =\n  {\n    HP_HEX_3E_0V,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n\n    HP_PRISM,\n    HP_PRISM,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_3ea_2v_newels[][8] =\n{\n  { 1, 5, 14, 6, 7, 15, 20, 16 },\n\n  { 2, 21, 9, 8 },\n  { 5, 14, 15, 21, 8, 9 },\n  { 15, 14, 20, 9, 8, 17 },\n  { 3, 22, 10, 11 },\n  { 6, 16, 14, 22, 11, 10 },\n  { 14, 16, 20, 10, 11, 18 },\n  //  { 4, 23, 13, 12 },\n  { 7, 15, 16, 4, 12, 13 },\n  { 16, 15, 20, 13, 12, 19 },\n\n  { 11, 13, 16, 18, 19, 20 },\n  { 15, 12, 9, 20, 19, 17 },\n  { 8, 10, 14, 17, 18, 20 },\n  { 20, 17, 18, 19 },\n};\nHPRef_Struct reftet_3ea_2v =\n{\n  HP_TET,\n  reftet_3ea_2v_splitedges, \n  reftet_3ea_2v_splitfaces, \n  reftet_3ea_2v_splitelements, \n  reftet_3ea_2v_newelstypes, \n  reftet_3ea_2v_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_3EA_3V,  \nint reftet_3ea_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 2, 10 },\n  { 3, 4, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 2, 1, 21 },\n  { 3, 1, 22 },\n  { 4, 1, 23 },\n  { 0, 0, 0 }\n};\nint reftet_3ea_3v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 1, 2, 4, 15 },\n    { 1, 3, 4, 16 },\n    { 2, 3, 4, 17 },\n    { 3, 4, 2, 18 },\n    { 4, 2, 3, 19 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ea_3v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ea_3v_newelstypes[] =\n  {\n    HP_HEX_3E_0V,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM,\n\n    HP_PRISM,\n    HP_PRISM,\n    HP_PRISM,\n    HP_TET,\n    HP_NONE,\n  };\nint reftet_3ea_3v_newels[][8] =\n{\n  { 1, 5, 14, 6, 7, 15, 20, 16 },\n\n  { 2, 21, 9, 8 },\n  { 5, 14, 15, 21, 8, 9 },\n  { 15, 14, 20, 9, 8, 17 },\n  { 3, 22, 10, 11 },\n  { 6, 16, 14, 22, 11, 10 },\n  { 14, 16, 20, 10, 11, 18 },\n  { 4, 23, 13, 12 },\n  { 7, 15, 16, 23, 12, 13 },\n  { 16, 15, 20, 13, 12, 19 },\n\n  { 11, 13, 16, 18, 19, 20 },\n  { 15, 12, 9, 20, 19, 17 },\n  { 8, 10, 14, 17, 18, 20 },\n  { 20, 17, 18, 19 },\n};\nHPRef_Struct reftet_3ea_3v =\n{\n  HP_TET,\n  reftet_3ea_3v_splitedges, \n  reftet_3ea_3v_splitfaces, \n  reftet_3ea_3v_splitelements, \n  reftet_3ea_3v_newelstypes, \n  reftet_3ea_3v_newels\n};\n\n\n\n\n\n\n\n//  HP_TET_3EV_0V,  \nint reftet_3eb_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  //  { 3, 2, 12 },\n  { 3, 4, 13 },\n  //  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3eb_0v_splitfaces[][4] =\n  {\n    { 1, 2, 4, 17 },\n    { 2, 1, 3, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3eb_0v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3eb_0v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    //    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3eb_0v_newels[][8] =\n{\n  { 1, 7, 17, 5, 6 },\n  { 2, 9, 18, 8, 10 },\n  //  { 3, 12, 13, 11 },\n  //  { 4, 14, 16, 15 },\n  { 5, 6, 17, 8, 18, 10 },\n  { 7, 17, 6, 4, 15, 16 },\n  { 9, 18, 10, 3, 11, 13 },\n  \n  { 10, 15, 16, 13, 20 },\n  { 6, 11, 13, 16, 20 },\n  { 10, 17, 15, 20 },\n  { 6, 18, 11, 20 },\n  { 6, 17, 10, 18, 20 },\n  { 6, 16, 15, 17, 20 },\n  { 18, 10, 13, 11, 20 },\n};\nHPRef_Struct reftet_3eb_0v =\n{\n  HP_TET,\n  reftet_3eb_0v_splitedges, \n  reftet_3eb_0v_splitfaces, \n  reftet_3eb_0v_splitelements, \n  reftet_3eb_0v_newelstypes, \n  reftet_3eb_0v_newels\n};\n\n\n\n\n\n\n\n\n\n//  HP_TET_3EV_1V,  \nint reftet_3eb_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  //  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3eb_1v_splitfaces[][4] =\n  {\n    { 1, 2, 4, 17 },\n    { 2, 1, 3, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3eb_1v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3eb_1v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3eb_1v_newels[][8] =\n{\n  { 1, 7, 17, 5, 6 },\n  { 2, 9, 18, 8, 10 },\n  { 3, 12, 13, 11 },\n  //  { 4, 14, 16, 15 },\n  { 5, 6, 17, 8, 18, 10 },\n  { 7, 17, 6, 4, 15, 16 },\n  { 9, 18, 10, 12, 11, 13 },\n  \n  { 10, 15, 16, 13, 20 },\n  { 6, 11, 13, 16, 20 },\n  { 10, 17, 15, 20 },\n  { 6, 18, 11, 20 },\n  { 6, 17, 10, 18, 20 },\n  { 6, 16, 15, 17, 20 },\n  { 18, 10, 13, 11, 20 },\n};\nHPRef_Struct reftet_3eb_1v =\n{\n  HP_TET,\n  reftet_3eb_1v_splitedges, \n  reftet_3eb_1v_splitfaces, \n  reftet_3eb_1v_splitelements, \n  reftet_3eb_1v_newelstypes, \n  reftet_3eb_1v_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_3EV_2V,  \nint reftet_3eb_2v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3eb_2v_splitfaces[][4] =\n  {\n    { 1, 2, 4, 17 },\n    { 2, 1, 3, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3eb_2v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3eb_2v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3eb_2v_newels[][8] =\n{\n  { 1, 7, 17, 5, 6 },\n  { 2, 9, 18, 8, 10 },\n  { 3, 12, 13, 11 },\n  { 4, 14, 16, 15 },\n  { 5, 6, 17, 8, 18, 10 },\n  { 7, 17, 6, 14, 15, 16 },\n  { 9, 18, 10, 12, 11, 13 },\n  \n  { 10, 15, 16, 13, 20 },\n  { 6, 11, 13, 16, 20 },\n  { 10, 17, 15, 20 },\n  { 6, 18, 11, 20 },\n  { 6, 17, 10, 18, 20 },\n  { 6, 16, 15, 17, 20 },\n  { 18, 10, 13, 11, 20 },\n};\nHPRef_Struct reftet_3eb_2v =\n{\n  HP_TET,\n  reftet_3eb_2v_splitedges, \n  reftet_3eb_2v_splitfaces, \n  reftet_3eb_2v_splitelements, \n  reftet_3eb_2v_newelstypes, \n  reftet_3eb_2v_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n//  HP_TET_3EC_0V,  \nint reftet_3ec_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  //  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  //  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3ec_0v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 1, 4, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ec_0v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ec_0v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    //    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3ec_0v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 2, 8, 18, 10, 9 },\n  //  { 3, 11, 12, 13 },\n  //  { 4, 15, 14, 16 },\n  { 5, 17, 7, 8, 9, 18 },\n  { 6, 7, 17, 3, 13, 12 },\n  { 10, 9, 18, 4, 16, 14 },\n  \n  { 9, 16, 13, 12, 20 },\n  { 7, 13, 16, 14, 20 },\n  { 7, 14, 18, 20 },\n  { 9, 12, 17, 20 },\n  { 17, 7, 18, 9, 20 },\n  { 7, 17, 12, 13, 20 },\n  { 9, 18, 14, 16, 20 },\n};\nHPRef_Struct reftet_3ec_0v =\n{\n  HP_TET,\n  reftet_3ec_0v_splitedges, \n  reftet_3ec_0v_splitfaces, \n  reftet_3ec_0v_splitelements, \n  reftet_3ec_0v_newelstypes, \n  reftet_3ec_0v_newels\n};\n\n\n\n\n\n\n \n\n\n//  HP_TET_3EC_1V,  \nint reftet_3ec_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  // { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3ec_1v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 1, 4, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ec_1v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ec_1v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    //    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3ec_1v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 2, 8, 18, 10, 9 },\n  { 3, 11, 12, 13 },\n  //  { 4, 15, 14, 16 },\n  { 5, 17, 7, 8, 9, 18 },\n  { 6, 7, 17, 11, 13, 12 },\n  { 10, 9, 18, 4, 16, 14 },\n  \n  { 9, 16, 13, 12, 20 },\n  { 7, 13, 16, 14, 20 },\n  { 7, 14, 18, 20 },\n  { 9, 12, 17, 20 },\n  { 17, 7, 18, 9, 20 },\n  { 7, 17, 12, 13, 20 },\n  { 9, 18, 14, 16, 20 },\n};\nHPRef_Struct reftet_3ec_1v =\n{\n  HP_TET,\n  reftet_3ec_1v_splitedges, \n  reftet_3ec_1v_splitfaces, \n  reftet_3ec_1v_splitelements, \n  reftet_3ec_1v_newelstypes, \n  reftet_3ec_1v_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_3EC_2V,  \nint reftet_3ec_2v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 4, 1, 14 },\n  { 4, 2, 15 },\n  { 4, 3, 16 },\n  { 0, 0, 0 }\n};\nint reftet_3ec_2v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 17 },\n    { 2, 1, 4, 18 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ec_2v_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 20 },\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ec_2v_newelstypes[] =\n  {\n    HP_PYRAMID_EDGES,\n    HP_PYRAMID_EDGES,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    \n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_TET,\n    HP_TET,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_PYRAMID,\n    HP_NONE,\n  };\nint reftet_3ec_2v_newels[][8] =\n{\n  { 1, 5, 17, 6, 7 },\n  { 2, 8, 18, 10, 9 },\n  { 3, 11, 12, 13 },\n  { 4, 15, 14, 16 },\n  { 5, 17, 7, 8, 9, 18 },\n  { 6, 7, 17, 11, 13, 12 },\n  { 10, 9, 18, 15, 16, 14 },\n  \n  { 9, 16, 13, 12, 20 },\n  { 7, 13, 16, 14, 20 },\n  { 7, 14, 18, 20 },\n  { 9, 12, 17, 20 },\n  { 17, 7, 18, 9, 20 },\n  { 7, 17, 12, 13, 20 },\n  { 9, 18, 14, 16, 20 },\n};\nHPRef_Struct reftet_3ec_2v =\n{\n  HP_TET,\n  reftet_3ec_2v_splitedges, \n  reftet_3ec_2v_splitfaces, \n  reftet_3ec_2v_splitelements, \n  reftet_3ec_2v_newelstypes, \n  reftet_3ec_2v_newels\n};\n\n\n\n\n\n//  HP_TET_3ED_3V,  \nint reftet_3ed_3v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 2, 3, 9 },\n  { 2, 4, 10 },\n  { 3, 1, 11 },\n  { 3, 2, 12 },\n  { 3, 4, 13 },\n  { 0, 0, 0 }\n};\nint reftet_3ed_3v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 2, 3, 1, 15 },\n    { 3, 1, 2, 16 },\n    { 0, 0, 0, 0 }\n  };\nint reftet_3ed_3v_splitelements[][5] =\n  {\n    { 0 },\n  };\n\nHPREF_ELEMENT_TYPE reftet_3ed_3v_newelstypes[] =\n  {\n    HP_TET,\n    HP_PRISM,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_PRISM_SINGEDGE,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,    \n    HP_TET_1E_1VA,\n    HP_TET_1E_1VA,    \n    HP_TET_1E_1VA,    \n    HP_NONE,\n  };\nint reftet_3ed_3v_newels[][8] =\n{\n  { 7, 10, 13, 4 },\n  { 14, 15, 16, 7, 10, 13 },\n  { 5, 14, 7, 8, 15, 10 },\n  { 9, 15, 10, 12, 16, 13 },  \n  { 11, 16, 13, 6, 14, 7 },\n  { 1, 5, 14, 7 },\n  { 1, 6, 7, 14 },\n  { 2, 8, 10, 15 },\n  { 2, 9, 15, 10 },\n  { 3, 12, 13, 16 },\n  { 3, 11, 16, 13 }\n};\n\nHPRef_Struct reftet_3ed_3v =\n{\n  HP_TET,\n  reftet_3ed_3v_splitedges, \n  reftet_3ed_3v_splitfaces, \n  reftet_3ed_3v_splitelements, \n  reftet_3ed_3v_newelstypes, \n  reftet_3ed_3v_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n/* ************************ 1 singular face ******************** */\n\n\n// HP_TET_1F_0E_0V\nint reftet_1f_0e_0v_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 3, 1, 6 },\n  { 4, 1, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1f_0e_0v_newelstypes[] =\n{\n  HP_PRISM_1FA_0E_0V,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1f_0e_0v_newels[][8] =\n{\n  { 3, 2, 4, 6, 5, 7 },\n  { 5, 7, 6, 1 }\n};\nHPRef_Struct reftet_1f_0e_0v =\n{\n  HP_TET,\n  reftet_1f_0e_0v_splitedges, \n  0, 0,\n  reftet_1f_0e_0v_newelstypes, \n  reftet_1f_0e_0v_newels\n};\n\n\n\n\n/*\n// HP_TET_1F_0E_1VA    ... singular vertex in face\nint reftet_1f_0e_1va_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 2, 3, 6 },\n  { 2, 4, 7 },\n  { 3, 1, 8 },\n  { 4, 1, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1f_0e_1va_newelstypes[] =\n{\n  // HP_HEX_1F_0E_0V,\n  HP_HEX7_1FA,\n  HP_TET_1F_0E_1VA,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1f_0e_1va_newels[][8] =\n{\n  // { 3, 6, 7, 4, 8, 5, 5, 9 },\n  { 4, 3, 6, 7, 9, 8, 5 },  \n  { 5, 2, 6, 7 },\n  { 5, 9, 8, 1 },\n};\nHPRef_Struct reftet_1f_0e_1va =\n{\n  HP_TET,\n  reftet_1f_0e_1va_splitedges, \n  0, 0,\n  reftet_1f_0e_1va_newelstypes, \n  reftet_1f_0e_1va_newels\n};\n*/\n\n\nHPRefStruct<HP_TET> reftet_1f_0e_1va\n  {\n    HP_TET_1F_0E_1VA,\n    {\n      El(HP_HEX7_1FA, { V4, V3, E23, E24, E41, E31, E21 }),\n      El(HP_TET_1F_0E_1VA, { E21, V2, E23, E24 }),\n      El(HP_TET, {  E21, E41, E31, V1 })\n    }\n  };\n\n\n\n// HP_TET_1F_0E_1VB    ... singular vertex not in face\nint reftet_1f_0e_1vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 1, 4, 7 },\n  { 2, 1, 8 },\n  { 3, 1, 9 },\n  { 4, 1, 10 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1f_0e_1vb_newelstypes[] =\n{\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM,\n  HP_TET_0E_1V,\n  HP_NONE,\n};\nint reftet_1f_0e_1vb_newels[][8] =\n{\n  { 2, 4, 3, 8, 10, 9 },\n  { 8, 10, 9, 5, 7, 6 }, \n  { 1, 5, 6, 7 },\n};\nHPRef_Struct reftet_1f_0e_1vb =\n{\n  HP_TET,\n  reftet_1f_0e_1vb_splitedges, \n  0, 0,\n  reftet_1f_0e_1vb_newelstypes, \n  reftet_1f_0e_1vb_newels\n};\n\n\n\n\n\n\n\n// HP_TET_1F_0E_2V    ... face 234, sing verts v2,v3\nint reftet_1f_0e_2v_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 2, 3, 6 },\n  { 2, 4, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftet_1f_0e_2v_newelstypes[] =\n{\n  HP_TET_0E_1V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FB_0E_0V,\n  HP_TET_1F_0E_1VA,\n  HP_TET_1F_0E_1VA,\n  HP_NONE,\n};\nint reftet_1f_0e_2v_newels[][8] =\n{\n  { 1, 5, 8, 11 },\n  { 4, 10, 7, 11, 8, 5 },\n  { 9, 10, 8, 6, 7, 5 },\n  { 5, 2, 6, 7 },\n  { 8, 3, 10, 9 }\n};\nHPRef_Struct reftet_1f_0e_2v =\n{\n  HP_TET,\n  reftet_1f_0e_2v_splitedges, \n  0, 0,\n  reftet_1f_0e_2v_newelstypes, \n  reftet_1f_0e_2v_newels\n};\n\n\n\n\n\n\n\n\nHPRefStruct<HP_TET> reftet_1f_0e_3v\n  {\n    HP_TET_1F_0E_3V,\n    {\n      El(HP_TET,   { V1, E21, E31, E41 }),\n      El(HP_PRISM_1FA_0E_0V, { F234, F423, F324, E21, E41, E31 }),\n      El(HP_PRISM_1FB_1EA_0V, { E32, F324, E31, E23, F234, E21  }),\n      El(HP_PRISM_1FB_1EA_0V, { E43, F423, E41, E34, F324, E31  }),\n      El(HP_PRISM_1FB_1EA_0V, { E24, F234, E21, E42, F423, E41  }),\n      El(HP_TET_1F_0E_0V, { E21, E24, E23, F234 }),\n      El(HP_TET_1F_0E_1VA, { E21, V2, E23, E24 }),            \n      El(HP_TET_1F_0E_0V, { E31, E32, E34, F324 }),\n      El(HP_TET_1F_0E_1VA, { E31, V3, E34, E32 }),            \n      El(HP_TET_1F_0E_0V, { E41, E43, E42, F423 }),\n      El(HP_TET_1F_0E_1VA, { E41, V4, E42, E43 }),            \n    }\n  };\n\n\n\n\n\n\n\n\n\n\n\n// HP_TET_1F_1EA_0V  ... sing edge is 1..2\nint reftet_1f_1ea_0v_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 1, 10 },\n  { 4, 1, 11 },\n  { 0, 0, 0 }\n};\n\nint reftet_1f_1ea_0v_splitfaces[][4] =\n  {\n    { 2, 1, 3, 12 },\n    { 2, 1, 4, 13 },\n    { 0, 0, 0, 0 }\n  };\n\n\nHPREF_ELEMENT_TYPE reftet_1f_1ea_0v_newelstypes[] =\n{\n  HP_HEX_1F_0E_0V,\n  //  HP_PRISM,\n  HP_PYRAMID_1FB_0E_1VA,\n  HP_TET_1E_1VA,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM,\n  HP_NONE,\n};\nint reftet_1f_1ea_0v_newels[][8] =\n{\n  { 3, 8, 9, 4, 10, 12, 13, 11 },\n  // { 2, 9, 8, 7, 13, 12 },\n  { 8, 9, 13, 12, 2 },\n  { 2, 7, 13, 12 },\n  { 7, 13, 12, 1, 6, 5 },\n  { 6, 11, 13, 5, 10, 12 }\n};\nHPRef_Struct reftet_1f_1ea_0v =\n{\n  HP_TET,\n  reftet_1f_1ea_0v_splitedges, \n  reftet_1f_1ea_0v_splitfaces, \n  0, \n  reftet_1f_1ea_0v_newelstypes, \n  reftet_1f_1ea_0v_newels\n};\n\n\n\n\n\n\n\n\n// HP_TET_1F_1EB_0V     singular edge in face, edge is 2-3\nint reftet_1f_1eb_0v_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 2, 4, 6 },\n  { 3, 1, 7 },\n  { 3, 4, 8 },\n  { 4, 1, 9 },\n  { 0, 0, 0 }\n};\n\n\nHPREF_ELEMENT_TYPE reftet_1f_1eb_0v_newelstypes[] =\n{\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_1f_1eb_0v_newels[][8] =\n{\n  // { 2, 5, 6, 3, 7, 8 },\n  { 3, 8, 7, 2, 6, 5 },\n  { 6, 4, 8, 5, 9, 7 },\n  { 5, 9, 7, 1}\n};\nHPRef_Struct reftet_1f_1eb_0v =\n{\n  HP_TET,\n  reftet_1f_1eb_0v_splitedges, \n  0, 0, \n  reftet_1f_1eb_0v_newelstypes, \n  reftet_1f_1eb_0v_newels\n};\n\n\n\n\n\n\n\n// HP_TET_1F_1E_1VA      // 1 sing edge in face e23, sing vert 2\nint reftet_1f_1e_1va_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 2, 3, 10 }, \n  { 2, 4, 6 },\n  { 3, 1, 7 },\n  { 3, 4, 8 },\n  { 4, 1, 9 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1f_1e_1va_newelstypes[] =\n{\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_TET,\n  HP_TET_1F_1E_1VA,\n  HP_NONE,\n};\nint reftet_1f_1e_1va_newels[][8] =\n{\n  { 3, 8, 7, 10, 6, 5 },\n  { 6, 4, 8, 5, 9, 7 },\n  { 5, 9, 7, 1},\n  { 5, 2, 10, 6 }\n};\nHPRef_Struct reftet_1f_1e_1va =\n{\n  HP_TET,\n  reftet_1f_1e_1va_splitedges, \n  0, 0, \n  reftet_1f_1e_1va_newelstypes, \n  reftet_1f_1e_1va_newels\n};\n\n\n\n\n\n\n\n// HP_TET_1F_1E_1VB      // 1 sing edge in face e24, sing vert 2\nint reftet_1f_1e_1vb_splitedges[][3] =\n{\n  { 2, 1, 5 },\n  { 2, 3, 6 },\n  { 2, 4, 7 },\n  { 3, 1, 8 },\n  { 4, 1, 9 },\n  { 4, 3, 10 },\n  { 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1f_1e_1vb_newelstypes[] =\n{\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FA_0E_0V,  \n  HP_TET,\n  HP_TET_1F_1E_1VB,  \n  HP_NONE,\n};\nint reftet_1f_1e_1vb_newels[][8] =\n{\n  { 4, 9, 10, 7, 5, 6 },\n  { 3, 6, 10, 8, 5, 9 },\n  { 5, 9, 8, 1},\n  { 5, 2, 6, 7 }  \n};\nHPRef_Struct reftet_1f_1e_1vb =\n{\n  HP_TET,\n  reftet_1f_1e_1vb_splitedges, \n  0, 0, \n  reftet_1f_1e_1vb_newelstypes, \n  reftet_1f_1e_1vb_newels\n};\n\n\n\n\n\n\n\n\n\n\n\n\n// HP_TET_1F_1E_2VA     //  1 sing edge not in face (e12), sing v2,v3    \nint reftet_1f_1e_2va_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 1, 10 },\n  { 3, 2, 11 },\n  { 3, 4, 12 },\n  { 4, 1, 13 },\n  { 0, 0, 0 }\n};\n\nint reftet_1f_1e_2va_splitfaces[][4] =\n  {\n    { 2, 1, 3, 14 },\n    { 2, 1, 4, 15 },\n    { 0, 0, 0, 0 }\n  };\n\n\nHPREF_ELEMENT_TYPE reftet_1f_1e_2va_newelstypes[] =\n{\n  HP_PRISM,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM_1FB_0E_0V,\n  HP_TET_1F_0E_1VA,\n  HP_TET_1F_0E_1VA,\n  HP_TET_1E_1VA,  \n  HP_TET_1E_1VA,\n  HP_HEX7_1FB,\n  HP_NONE,  \n};\nint reftet_1f_1e_2va_newels[][8] =\n{\n  { 5, 14, 10, 6, 15, 13 },\n  { 1, 5, 6, 7, 14, 15 },\n  { 8, 14, 9, 11, 10, 12 },\n  { 10, 3, 12, 11 },\n  { 14, 2, 8, 9 },\n  { 2, 7, 15, 14 },\n  { 2, 9, 14, 15 },\n  // { 13, 10, 14, 15, 4, 12, 9 }\n  { 10, 13, 15, 14, 12, 4, 9 }\n};\nHPRef_Struct reftet_1f_1e_2va =\n{\n  HP_TET,\n  reftet_1f_1e_2va_splitedges,\n  reftet_1f_1e_2va_splitfaces,   \n  0, \n  reftet_1f_1e_2va_newelstypes, \n  reftet_1f_1e_2va_newels\n};\n\n\n\n\n\n// HP_TET_1F_1E_2VB     //  1 sing edge not in face (e12), sing v2,v4    \nint reftet_1f_1e_2vb_splitedges[][3] =\n{\n  { 1, 3, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 2, 4, 9 },\n  { 3, 1, 10 },\n  { 4, 1, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 0, 0, 0 }\n};\n\nint reftet_1f_1e_2vb_splitfaces[][4] =\n  {\n    { 2, 1, 3, 14 },\n    { 2, 1, 4, 15 },\n    { 0, 0, 0, 0 }\n  };\n\n\nHPREF_ELEMENT_TYPE reftet_1f_1e_2vb_newelstypes[] =\n{\n  HP_PRISM,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM_1FB_0E_0V,\n  HP_TET_1F_0E_1VA,\n  HP_TET_1F_0E_1VA,\n  HP_TET_1E_1VA,  \n  HP_TET_1E_1VA,\n  HP_HEX7_1FB,\n  HP_NONE,\n\n};\nint reftet_1f_1e_2vb_newels[][8] =\n{\n  { 5, 14, 10, 6, 15, 11 },\n  { 1, 5, 6, 7, 14, 15 },\n  { 8, 15, 9, 13, 11, 12 },\n  { 11, 4, 12, 13 },\n  { 15, 2, 8, 9 },\n  { 2, 7, 15, 14 },\n  { 2, 8, 14, 15 },\n  { 10, 11, 15, 14, 3, 13, 8 }\n};\nHPRef_Struct reftet_1f_1e_2vb =\n{\n  HP_TET,\n  reftet_1f_1e_2vb_splitedges,\n  reftet_1f_1e_2vb_splitfaces,   \n  0, \n  reftet_1f_1e_2vb_newelstypes, \n  reftet_1f_1e_2vb_newels\n};\n\n\n\n\n\n\n//  HP_TET_1F_1EA_3V\nHPRefStruct<HP_TET> reftet_1f_1ea_3v\n  {\n    HP_TET_1F_1EA_3V,\n    {\n      El(HP_PRISM,  { E14, E41, F214, E13, E31, F213 }),\n      El(HP_PRISM_SINGEDGE, { V1, E13, E14, E21, F213, F214 }),\n      El(HP_HEX7_1FB, { E31, E41, F214, F213, F324, F423, F234 }),\n      El(HP_PRISM_1FB_0E_0V, { F234, E23, F213, F324, E32, E31 }),\n      El(HP_PRISM_1FB_0E_0V, { F423, E42, E41, F234, E24, F214 }),\n      El(HP_PRISM_1FB_0E_0V, { F324, E34, E31, F423, E43, E41 }),\n      El(HP_TET_1F_0E_0V, { E31, E32, E34, F324 }),\n      El(HP_TET_1F_0E_1VA, { E31, V3, E34, E32 }),\n\n      El(HP_TET_1F_0E_0V, { E41, E43, E42, F423 }),\n      El(HP_TET_1F_0E_1VA, { E41, V4, E42, E43 }),\n      El(HP_PYRAMID_1FB_0E_0V, {  E24, E23, F213, F214, F234 }),  // needs check\n      El(HP_PYRAMID_1FB_0E_1VA, { E23, E24, F214, F213, V2 }),\n      El(HP_TET_1E_1VA, { V2, E21, F214, F213 }),\n    }\n  };\n\n\n\n//  HP_TET_1F_1E_3V     e4 (E23), V2, V3, V4\nHPRefStruct<HP_TET> reftet_1f_1e_3v\n  {\n    HP_TET_1F_1E_3V,\n    {\n      El(HP_TET,  { V1, E21, E31, E41 }),\n      El(HP_HEX7_1FA, { E34, E24, E42, E43, E31, E21, E41 }),\n      El(HP_PRISM_1FB_1EA_0V, { E32, E34, E31, E23, E24, E21 }),\n      El(HP_TET_1F_0E_1VA, { E41, V4, E42, E43 }),\n      El(HP_TET_1F_1E_1VB, { E21, V2, E23, E24 }),\n      El(HP_TET_1F_1E_1VA, { E31, V3, E34, E32 }),\n    }\n  };\n\n\n\nHPRefStruct<HP_TET> reftet_1f_2eoo_3v\n  {\n    HP_TET_1F_2Eoo_3V,\n    {\n      El(HP_TET,  { E14, E41, F214, F314 }),\n      El(HP_PRISM_1FA_0E_0V, { V4, E34, E24, E41, F314, F214 }),\n      El(HP_PRISM, { F123, F213, F312, E14, F214, F314 }),\n      El(HP_PRISM_SINGEDGE, { E12, F123, E14, E21, F213, F214 }), \n      El(HP_PRISM_SINGEDGE, { E13, E14, F123, E31, F314, F312 }),\n      El(HP_HEX_1F_0E_0V, { E32, E23, E24, E34, F312, F213, F214, F314 }),\n      El(HP_TET_1E_1VA, { V1, E12, F123, E14 }),\n      El(HP_TET_1E_1VA, { V1, E13, E14, F123 }),\n      El(HP_PYRAMID_1FB_0E_1VA, { E34, E32, F312, F314, V3 }),\n      El(HP_PYRAMID_1FB_0E_1VA, { E23, E24, F214, F213, V2 }),\n      El(HP_TET_1E_1VA, { V2, E21, F214, F213 }),\n      El(HP_TET_1E_1VA, { V3, E31, F312, F314 }),\n\n    }\n  };\n\n// HP_TET_1F_2E_0VA    singular edge in face 234 is 34, and edge not in face is 14\nint reftet_1f_2e_0va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 2, 1, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 4, 1, 10 },\n  { 4, 2, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint reftet_1f_2e_0va_splitfaces[][4] =\n{\n  { 4, 1, 2, 13 }, \n  { 4, 1, 3, 14 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1f_2e_0va_newelstypes[] =\n{\n  HP_PRISM,\n  HP_PRISM_SINGEDGE,\n  HP_HEX7_1FB,\n  HP_PRISM_1FB_1EA_0V,\n  HP_TET_1F_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_NONE,\n};\nint reftet_1f_2e_0va_newels[][8] =\n{\n  { 6, 8, 14, 5, 7, 13 },\n  { 1, 5, 6, 10, 13, 14 },\n  { 7, 8, 14, 13, 2, 9, 11 },\n  { 3, 8, 9, 12, 14, 11 },\n  { 14, 4, 11, 12 },\n  { 4, 11, 13, 14 },\n  { 4, 10, 14, 13 }\n};\nHPRef_Struct reftet_1f_2e_0va =\n{\n  HP_TET,\n  reftet_1f_2e_0va_splitedges, \n  reftet_1f_2e_0va_splitfaces, \n  0, \n  reftet_1f_2e_0va_newelstypes, \n  reftet_1f_2e_0va_newels\n};\n\n\n\n\n\n// HP_TET_1F_2E_0VB    singular edge in face 234 is 34, and edge not in face is 13\nint reftet_1f_2e_0vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 4, 6 },\n  { 2, 1, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 4, 2, 12 },\n  { 0, 0, 0 }\n};\n\nint reftet_1f_2e_0vb_splitfaces[][4] =\n{\n  { 3, 1, 2, 13 }, \n  { 3, 1, 4, 14 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftet_1f_2e_0vb_newelstypes[] =\n{\n  HP_PRISM,\n  HP_PRISM_SINGEDGE,\n  HP_HEX7_1FB,\n  HP_PRISM_1FB_1EA_0V,\n  HP_TET_1F_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_TET_1E_1VA,\n  HP_NONE,\n};\nint reftet_1f_2e_0vb_newels[][8] =\n{\n  { 6, 14, 11, 5, 13, 7 },\n  { 1, 6, 5, 8, 14, 13 },\n  { 11, 7, 13, 14, 12, 2, 9 },\n  { 4, 12, 11, 10, 9, 14 },\n  { 14, 3, 10, 9 },\n  { 3, 8, 13, 14  },\n  { 3, 9, 14, 13 }\n};\nHPRef_Struct reftet_1f_2e_0vb =\n{\n  HP_TET,\n  reftet_1f_2e_0vb_splitedges, \n  reftet_1f_2e_0vb_splitfaces, \n  0, \n  reftet_1f_2e_0vb_newelstypes, \n  reftet_1f_2e_0vb_newels\n};\n\n\n\n\n\n//  HP_TET_1F_2E_1V     e4,e5 (E23,E24), V2 \nHPRefStruct<HP_TET> reftet_1f_2e_1v\n  {\n    HP_TET_1F_2E_1V,\n    {\n      El(HP_TET,  { V1, E21, E31, E41 }),\n      El(HP_PRISM_1FA_0E_0V, { F234, E43, E34, E21, E41, E31 }),\n      El(HP_PRISM_1FB_1EA_0V, { V3, E34, E31, E23, F234, E21 }),\n      El(HP_PRISM_1FB_1EA_0V, { E24, F234, E21, V4, E43, E41 }),\n      El(HP_TET_1F_1E_1VA, { E21, V2, E23, F234 }),\n      El(HP_TET_1F_1E_1VB, { E21, V2, F234, E24 }),\n    }\n  };\n\n\n\n//  HP_TET_1F_2E_3V     e4,e5 (E23,E24), V2, V3, V4\nHPRefStruct<HP_TET> reftet_1f_2e_3v\n  {\n    HP_TET_1F_2E_3V,\n    {\n      El(HP_TET,  { V1, E21, E31, E41 }),\n      El(HP_PRISM_1FA_0E_0V, { F234, E43, E34, E21, E41, E31 }),\n      El(HP_PRISM_1FB_1EA_0V, { E32, E34, E31, E23, F234, E21 }),\n      El(HP_PRISM_1FB_1EA_0V, { E24, F234, E21, E42, E43, E41 }),\n      El(HP_TET_1F_1E_1VA, { E21, V2, E23, F234 }),\n      El(HP_TET_1F_1E_1VB, { E21, V2, F234, E24 }),\n      El(HP_TET_1F_1E_1VA, { E31, V3, E34, E32 }),\n      El(HP_TET_1F_1E_1VB, { E41, V4, E42, E43 }),\n    }\n  };\n\n\n\n\n\n/* ************************ 2 singular faces ******************** */\n\n\n// HP_TET_2F_0E_0V\nint reftet_2f_0e_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 2, 1, 6 },\n  { 3, 1, 7 },\n  { 3, 2, 8 },\n  { 4, 1, 9 },\n  { 4, 2, 10 },\n  { 0, 0, 0 }\n};\n\nint reftet_2f_0e_0v_splitfaces[][4] =\n  {\n    { 3, 1, 2, 11 },\n    { 4, 1, 2, 12 },\n    { 0, 0, 0, 0 }\n  };\n\n\nHPREF_ELEMENT_TYPE reftet_2f_0e_0v_newelstypes[] =\n{\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_TET,\n  HP_NONE,\n};\nint reftet_2f_0e_0v_newels[][8] =\n{\n  { 2, 10, 8, 6, 12, 11 },\n  { 1, 7, 9, 5, 11, 12 },\n  //   { 3, 11, 8, 4, 12, 10 },\n  { 4, 10, 12, 3, 8, 11 }, \n  { 3, 7, 11, 4, 9, 12 },\n  { 5, 6, 11, 12 }\n};\nHPRef_Struct reftet_2f_0e_0v =\n{\n  HP_TET,\n  reftet_2f_0e_0v_splitedges, \n  reftet_2f_0e_0v_splitfaces, \n  0, \n  reftet_2f_0e_0v_newelstypes, \n  reftet_2f_0e_0v_newels\n};\n\n\n\n\n\n// HP_TET_2F_0E_1V\nint reftet_2f_0e_1v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 2, 1, 6 },\n  { 3, 1, 7 },\n  { 3, 2, 8 },\n  { 4, 1, 9 },\n  { 4, 2, 10 },\n  { 4, 3, 13 },\n  { 0, 0, 0 }\n};\n\nint reftet_2f_0e_1v_splitfaces[][4] =\n  {\n    { 3, 1, 2, 11 },\n    { 4, 1, 2, 12 },\n    { 0, 0, 0, 0 }\n  };\n\n\nHPREF_ELEMENT_TYPE reftet_2f_0e_1v_newelstypes[] =\n{\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_TET,\n  HP_TET_1F_1E_1VB,  \n  HP_TET_1F_1E_1VA,  \n  HP_NONE\n};\nint reftet_2f_0e_1v_newels[][8] =\n{\n  { 2, 10, 8, 6, 12, 11 },\n  { 1, 7, 9, 5, 11, 12 },\n  //   { 3, 11, 8, 4, 12, 10 },\n  { 13, 10, 12, 3, 8, 11 }, \n  { 3, 7, 11, 13, 9, 12 },\n  { 5, 6, 11, 12 },\n  { 12, 4, 10, 13 },\n  { 12, 4, 13, 9 } \n};\nHPRef_Struct reftet_2f_0e_1v =\n{\n  HP_TET,\n  reftet_2f_0e_1v_splitedges, \n  reftet_2f_0e_1v_splitfaces, \n  0, \n  reftet_2f_0e_1v_newelstypes, \n  reftet_2f_0e_1v_newels\n};\n\n\n\n\n\n\n\n\n//  HP_TET_2F_1E_0VA,  // 2 singular faces, sing edge e4\nint reftet_2f_1e_0va_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 2, 1, 6 },\n  { 2, 4, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 3, 4, 10 },\n  { 4, 1, 11 },\n  { 4, 2, 12 },\n  { 0, 0, 0 }\n};\n\nint reftet_2f_1e_0va_splitfaces[][4] =\n  {\n    { 3, 2, 1, 13 },\n    { 3, 2, 4, 14 },\n    { 4, 1, 2, 15 },\n    { 0, 0, 0, 0 }\n  };\n\nHPREF_ELEMENT_TYPE reftet_2f_1e_0va_newelstypes[] =\n{\n  HP_TET,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_SINGEDGE, \n  HP_PRISM_SINGEDGE, \n  HP_PRISM_SINGEDGE,\n  HP_TET_1F_1E_1VA, \n  HP_TET_1F_1E_1VB, \n  HP_TET_1F_1E_1VB, \n  HP_NONE,\n};\nint reftet_2f_1e_0va_newels[][8] =\n{\n  { 5, 6, 13, 15 },\n  { 1, 8, 11, 5, 13, 15 },\n  { 7, 12, 14, 6, 15, 13 },\n  { 2, 6, 7, 9, 13, 14 },\n  { 4, 15, 11,  10, 13, 8 },\n  { 4, 12, 15,  10, 14, 13, },\n  { 13, 3, 10, 14 },\n  { 13, 3, 14, 9 },\n  { 13, 3, 8, 10 },\n};\nHPRef_Struct reftet_2f_1e_0va =\n{\n  HP_TET,\n  reftet_2f_1e_0va_splitedges, \n  reftet_2f_1e_0va_splitfaces, \n  0, \n  reftet_2f_1e_0va_newelstypes, \n  reftet_2f_1e_0va_newels\n};\n\n\n//  HP_TET_2F_1E_0VB = 602,  // 2 singular faces f234,f134, sing edge e5=e24\nint reftet_2f_1e_0vb_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 4, 1, 10 },\n  { 4, 2, 11 },\n  { 4, 3, 12 },\n  { 0, 0, 0 }\n};\n\nint reftet_2f_1e_0vb_splitfaces[][4] =\n  {\n    { 4, 2, 3, 13 },\n    { 4, 1, 2, 14 },\n    { 3, 1, 2, 15 },\n    { 0, 0, 0, 0 }\n  };\n\nHPREF_ELEMENT_TYPE reftet_2f_1e_0vb_newelstypes[] =\n{\n  HP_TET,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_SINGEDGE, \n  HP_PRISM_SINGEDGE, \n  HP_PRISM_SINGEDGE,\n  HP_TET_1F_1E_1VA, \n  HP_TET_1F_1E_1VB, \n  HP_TET_1F_1E_1VB, \n  HP_NONE,\n};\nint reftet_2f_1e_0vb_newels[][8] =\n{\n  { 5, 6, 15, 14 },\n  { 1, 8, 10, 5, 15, 14 },\n  { 7, 13, 9, 6, 14, 15 },\n  { 2, 7, 6, 11, 13, 14 },\n  { 3, 8, 15, 12, 10, 14 },\n  { 3, 15, 9, 12, 14, 13 },\n  { 14, 4, 11, 13 },\n  { 14, 4, 13, 12 },\n  { 14, 4, 12, 10 },\n};\n\nHPRef_Struct reftet_2f_1e_0vb =\n{\n  HP_TET,\n  reftet_2f_1e_0vb_splitedges, \n  reftet_2f_1e_0vb_splitfaces, \n  0, \n  reftet_2f_1e_0vb_newelstypes, \n  reftet_2f_1e_0vb_newels\n};\n\n\n// HP_TET_3F_0E_0V = 610,  // 3 singular faces, no additional points or edges\nint reftet_3f_0e_0v_splitedges[][3] =\n{\n  { 1, 2, 5 },\n  { 1, 3, 6 },\n  { 2, 1, 7 },\n  { 2, 3, 8 },\n  { 3, 1, 9 },\n  { 3, 2, 10 },\n  { 4, 1, 11 },\n  { 4, 2, 12 },\n  { 4, 3, 13 },\n  { 0, 0, 0 }\n};\n\nint reftet_3f_0e_0v_splitfaces[][4] =\n  {\n    { 1, 2, 3, 14 },\n    { 2, 3, 1, 15 },\n    { 3, 1, 2, 16 },\n    { 4, 1, 2, 17 },\n    { 4, 1, 3, 18 },\n    { 4, 2, 3, 19 },\n    { 0, 0, 0, 0 }\n  };\n\nint reftet_3f_0e_0v_splitelements[][5] =\n  {\n    { 4, 1, 2, 3, 20 },\n    { 0 }\n  };\nHPREF_ELEMENT_TYPE reftet_3f_0e_0v_newelstypes[] =\n{\n  HP_TET,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  HP_PRISM_1FA_0E_0V,\n  \n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n  HP_PRISM_1FB_1EA_0V,\n\n  HP_TET_1F_1E_1VA,  // 1E_1VA\n  HP_TET_1F_0E_0V,  \n  HP_TET_1F_0E_0V,  // 1E_1VA\n  HP_TET_1F_0E_0V,  // 1E_1VA\n  HP_TET_1F_0E_0V,  // 1E_1VA\n  HP_TET_1F_0E_0V,  // 1E_1VA\n  HP_NONE,\n};\nint reftet_3f_0e_0v_newels[][8] =\n{\n  { 14, 15, 16, 20 },\n  { 5, 17, 7, 14, 20, 15 },\n  { 6, 9, 18, 14, 16, 20 },\n  { 10, 8, 19, 16, 15, 20 },\n  \n  { 1, 5, 14, 11, 17, 20 },\n  { 11, 18, 20, 1, 6, 14 },\n  { 2, 8, 15, 12, 19, 20 },\n  { 12, 17, 20, 2, 7, 15 },\n  { 3, 9, 16, 13, 18, 20 },\n  { 13, 19, 20, 3, 10, 16 },\n\n  { 20, 4, 11, 17 },\n  { 20, 4, 17, 12 },\n  { 20, 4, 12, 19 },\n  { 20, 4, 19, 13 },\n  { 20, 4, 13, 18 },\n  { 20, 4, 18, 11 }\n};\nHPRef_Struct reftet_3f_0e_0v =\n{\n  HP_TET,\n  reftet_3f_0e_0v_splitedges, \n  reftet_3f_0e_0v_splitfaces, \n  reftet_3f_0e_0v_splitelements, \n  reftet_3f_0e_0v_newelstypes, \n  reftet_3f_0e_0v_newels\n};\n\n\n\n\n\n\n\n\n// HP_TET_ALFELD\nint reftet_Alfeld_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nint reftet_Alfeld_splitfaces[][4] =\n{\n  { 0, 0, 0, 0 }\n};\n\nint reftet_Alfeld_splitelements[][5] =\n  {\n    { 1, 2, 3, 4, 5},\n    { 0 }\n  };\n\nHPREF_ELEMENT_TYPE reftet_Alfeld_newelstypes[] =\n{\n  HP_TET, HP_TET, HP_TET, HP_TET,\n  HP_NONE, \n};\n\nint reftet_Alfeld_newels[][8] =\n{\n  { 1, 2, 3, 5 }, \n  { 1, 4, 2, 5 }, \n  { 1, 3, 4, 5 },\n  { 3, 2, 4, 5 }\n};\nHPRef_Struct reftet_Alfeld =\n{\n  HP_TET,\n  reftet_Alfeld_splitedges, \n  reftet_Alfeld_splitfaces,\n  reftet_Alfeld_splitelements,  \n  reftet_Alfeld_newelstypes,\n  reftet_Alfeld_newels\n};\n\n\n/*\n\n*/\n"
  },
  {
    "path": "libsrc/meshing/hpref_trig.hpp",
    "content": "\n\n// HP_TRIG\nint reftrig_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_newelstypes[] =\n{\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_newels[][8] =\n{\n  { 1, 2, 3 },\n};\nHPRef_Struct reftrig =\n{\n  HP_TRIG, \n  reftrig_splitedges, \n  0, 0, \n  reftrig_newelstypes, \n  reftrig_newels\n};\n\n\n\n// HP_TRIG_SINGCORNER\nint reftrig_singcorner_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_NONE,\n};\nint reftrig_singcorner_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 2, 3, 5, 4 },\n};\nHPRef_Struct reftrig_singcorner =\n{\n  HP_TRIG,\n  reftrig_singcorner_splitedges, \n  0, 0,\n  reftrig_singcorner_newelstypes, \n  reftrig_singcorner_newels\n};\n\n\n/*\n// HP_TRIG_SINGCORNER, trigs only\nint reftrig_singcorner_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singcorner_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 4, 2, 5 },\n  { 5, 2, 3 },\n};\nHPRef_Struct reftrig_singcorner =\n{\n  HP_TRIG,\n  reftrig_singcorner_splitedges, \n  0, 0,\n  reftrig_singcorner_newelstypes, \n  reftrig_singcorner_newels\n};\n*/\n\n\n\n\n\n// HP_TRIG_SINGCORNER12\nint reftrig_singcorner12_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singcorner12_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singcorner12_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 2, 7, 6 },\n  { 4, 6, 7, 5 },\n  { 5, 7, 3 },\n};\nHPRef_Struct reftrig_singcorner12 =\n{\n  HP_TRIG,\n  reftrig_singcorner12_splitedges, \n  0, 0,\n  reftrig_singcorner12_newelstypes, \n  reftrig_singcorner12_newels\n};\n\n\n\n\n// HP_TRIG_SINGCORNER123_2D\nint reftrig_singcorner123_2D_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singcorner123_2D_newelstypes[] =\n{\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER,\n  HP_QUAD,\n  HP_QUAD,\n  HP_NONE,\n};\nint reftrig_singcorner123_2D_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 2, 7, 6 },\n  { 3, 8, 9 },\n  { 4, 6, 8, 5 },\n  { 6, 7, 9, 8 },\n};\nHPRef_Struct reftrig_singcorner123_2D =\n{\n  HP_TRIG,\n  reftrig_singcorner123_2D_splitedges, \n  0, 0,\n  reftrig_singcorner123_2D_newelstypes, \n  reftrig_singcorner123_2D_newels\n};\n\n\n\n\n\n\n// HP_TRIG_SINGCORNER123\nint reftrig_singcorner123_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 0, 0, 0 }\n};\n\nint reftrig_singcorner123_splitfaces[][4] =\n{\n  { 1, 2, 3, 10 },\n  { 2, 3, 1, 11 },\n  { 3, 1, 2, 12 },\n  { 0, 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singcorner123_newelstypes[] =\n{\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  //  HP_TRIG_SINGCORNER,\n  //  HP_TRIG,\n  //  HP_TRIG_SINGCORNER,\n  //  HP_TRIG,\n  //  HP_TRIG_SINGCORNER,\n  //  HP_TRIG,\n  HP_QUAD,\n  HP_QUAD,\n  HP_QUAD,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singcorner123_newels[][8] =\n{\n  { 1, 4, 10, 5 },\n  { 2, 7, 11, 6 },\n  { 3, 8, 12, 9 },\n  //  { 1, 4, 5 },\n  //  { 5, 4, 10 },\n  //  { 2, 7, 6 },\n  //  { 6, 7, 11 },\n  //  { 3, 8, 9 },\n  //  { 8, 12, 9 },\n  { 4, 6, 11, 10 },\n  { 7, 9, 12, 11 },\n  { 8, 5, 10, 12 },\n  { 10, 11, 12 },\n};\nHPRef_Struct reftrig_singcorner123 =\n{\n  HP_TRIG,\n  reftrig_singcorner123_splitedges, \n  reftrig_singcorner123_splitfaces, \n  0, \n  reftrig_singcorner123_newelstypes, \n  reftrig_singcorner123_newels\n};\n\n// HP_TRIG_SINGEDGE\nint reftrig_singedge_splitedges[][3] =\n{\n  { 2, 3, 4 },\n  { 1, 3, 5 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedge_newelstypes[] =\n{\n  HP_TRIG,\n  HP_QUAD_SINGEDGE,\n  HP_NONE,\n};\nint reftrig_singedge_newels[][8] =\n{\n  { 4, 3, 5 },\n  { 1, 2, 4, 5 },\n};\nHPRef_Struct reftrig_singedge =\n{\n  HP_TRIG,\n  reftrig_singedge_splitedges, \n  0, 0,\n  reftrig_singedge_newelstypes, \n  reftrig_singedge_newels\n};\n\n\n\n\n\n\n// HP_TRIG_SINGEDGECORNER1\nint reftrig_singedgecorner1_splitedges[][3] =\n{\n  { 1, 2, 6 },\n  { 1, 3, 5 },\n  { 2, 3, 4 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner1_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedgecorner1_newels[][8] =\n{\n  { 1, 6, 5 },\n  { 6, 2, 4, 5 },\n  { 5, 4, 3 },\n};\nHPRef_Struct reftrig_singedgecorner1 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner1_splitedges, \n  0, 0, \n  reftrig_singedgecorner1_newelstypes, \n  reftrig_singedgecorner1_newels\n};\n\n\n\n\n\n\n\n\n// HP_TRIG_SINGEDGECORNER2\nint reftrig_singedgecorner2_splitedges[][3] =\n{\n  { 2, 1, 6 },\n  { 1, 3, 5 },\n  { 2, 3, 4 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner2_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedgecorner2_newels[][8] =\n{\n  { 6, 2, 4},\n  { 1, 6, 4, 5 },\n  { 5, 4, 3 },\n};\nHPRef_Struct reftrig_singedgecorner2 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner2_splitedges, \n  0, 0,\n  reftrig_singedgecorner2_newelstypes, \n  reftrig_singedgecorner2_newels\n};\n\n\n\n\n// HP_TRIG_SINGEDGECORNER12\nint reftrig_singedgecorner12_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner12_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedgecorner12_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 6, 2, 7 },\n  { 4, 6, 7, 5 },\n  { 5, 7, 3 },\n};\nHPRef_Struct reftrig_singedgecorner12 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner12_splitedges, \n  0, 0,\n  reftrig_singedgecorner12_newelstypes, \n  reftrig_singedgecorner12_newels\n};\n\n\n\n\n\n\n\n// HP_TRIG_SINGEDGECORNER3\nint reftrig_singedgecorner3_splitedges[][3] =\n{\n  { 1, 3, 4 },\n  { 3, 1, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner3_newelstypes[] =\n{\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint reftrig_singedgecorner3_newels[][8] =\n{\n  { 1, 2, 6, 4 },\n  { 4, 6, 7, 5 },\n  { 3, 5, 7 },\n};\nHPRef_Struct reftrig_singedgecorner3 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner3_splitedges, \n  0, 0,\n  reftrig_singedgecorner3_newelstypes, \n  reftrig_singedgecorner3_newels\n};\n\n\n\n\n// HP_TRIG_SINGEDGECORNER13\nint reftrig_singedgecorner13_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 3, 6 },\n  { 3, 1, 7 },\n  { 3, 2, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner13_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint reftrig_singedgecorner13_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 4, 2, 6, 5 },\n  { 5, 6, 8, 7 },\n  { 3, 7, 8 },\n};\nHPRef_Struct reftrig_singedgecorner13 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner13_splitedges, \n  0, 0,\n  reftrig_singedgecorner13_newelstypes, \n  reftrig_singedgecorner13_newels\n};\n\n\n\n\n\n// HP_TRIG_SINGEDGECORNER23\nint reftrig_singedgecorner23_splitedges[][3] =\n{\n  { 1, 3, 4 },\n  { 2, 1, 5 },\n  { 2, 3, 6 },\n  { 3, 1, 7 },\n  { 3, 2, 8 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner23_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint reftrig_singedgecorner23_newels[][8] =\n{\n  { 5, 2, 6 },\n  { 1, 5, 6, 4 },\n  { 4, 6, 8, 7 },\n  { 3, 7, 8 },\n};\nHPRef_Struct reftrig_singedgecorner23 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner23_splitedges, \n  0, 0,\n  reftrig_singedgecorner23_newelstypes, \n  reftrig_singedgecorner23_newels\n};\n\n\n\n// HP_TRIG_SINGEDGECORNER123\nint reftrig_singedgecorner123_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 0, 0, 0 }\n};\nHPREF_ELEMENT_TYPE reftrig_singedgecorner123_newelstypes[] =\n{\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD,\n  HP_TRIG_SINGCORNER,\n  HP_NONE,\n};\nint reftrig_singedgecorner123_newels[][8] =\n{\n  { 1, 4, 5 },\n  { 6, 2, 7 },\n  { 4, 6, 7, 5 },\n  { 5, 7, 9, 8 },\n  { 3, 8, 9 },\n};\nHPRef_Struct reftrig_singedgecorner123 =\n{\n  HP_TRIG,\n  reftrig_singedgecorner123_splitedges, \n  0, 0,\n  reftrig_singedgecorner123_newelstypes, \n  reftrig_singedgecorner123_newels\n};\n\n// HP_TRIG_SINGEDGES\nint reftrig_singedges_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 3, 6 },\n  { 3, 2, 7 },\n  { 0, 0, 0 }\n};\nint reftrig_singedges_splitfaces[][4] =\n{\n  { 1, 2, 3, 8 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_singedges_newelstypes[] =\n{\n  //  HP_QUAD_2E,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedges_newels[][8] =\n{\n  // { 1, 4, 8, 5 },\n  { 1, 4, 8 },\n  { 5, 1, 8 },\n  { 4, 2, 6, 8 },\n  { 3, 5, 8, 7 },\n  { 6, 7, 8 },\n};\nHPRef_Struct reftrig_singedges =\n{\n  HP_TRIG,\n  reftrig_singedges_splitedges, \n  reftrig_singedges_splitfaces, \n  0,\n  reftrig_singedges_newelstypes, \n  reftrig_singedges_newels\n};\n\n\n\n\n\n\n\n\n// HP_TRIG_SINGEDGES2\nint reftrig_singedges2_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 2, 8 },\n  { 0, 0, 0 }\n};\nint reftrig_singedges2_splitfaces[][4] =\n{\n  { 1, 2, 3, 9 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_singedges2_newelstypes[] =\n{\n  //  HP_QUAD_2E,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedges2_newels[][8] =\n{\n  //  { 1, 4, 9, 5 },\n  { 1, 4, 9 },\n  { 5, 1, 9 },\n  { 4, 6, 7, 9 },\n  { 3, 5, 9, 8 },\n  { 6, 2, 7 },\n  { 7, 8, 9 },\n};\nHPRef_Struct reftrig_singedges2 =\n{\n  HP_TRIG,\n  reftrig_singedges2_splitedges, \n  reftrig_singedges2_splitfaces, \n  0,\n  reftrig_singedges2_newelstypes, \n  reftrig_singedges2_newels\n};\n\n\n\n\n// HP_TRIG_SINGEDGES3\nint reftrig_singedges3_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 3, 6 },\n  { 3, 1, 7 },\n  { 3, 2, 8 },\n  { 0, 0, 0 }\n};\nint reftrig_singedges3_splitfaces[][4] =\n{\n  { 1, 2, 3, 9 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_singedges3_newelstypes[] =\n{\n  //  HP_QUAD_2E,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedges3_newels[][8] =\n{\n  //  { 1, 4, 9, 5 },\n  { 1, 4, 9 },\n  { 5, 1, 9 },\n  { 4, 2, 6, 9 },\n  { 7, 5, 9, 8 },\n  { 3, 7, 8 },\n  { 6, 8, 9 },\n};\nHPRef_Struct reftrig_singedges3 =\n{\n  HP_TRIG,\n  reftrig_singedges3_splitedges, \n  reftrig_singedges3_splitfaces, \n  0,\n  reftrig_singedges3_newelstypes, \n  reftrig_singedges3_newels\n};\n\n\n\n\n\n\n// HP_TRIG_SINGEDGES23\nint reftrig_singedges23_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 1, 3, 5 },\n  { 2, 1, 6 },\n  { 2, 3, 7 },\n  { 3, 1, 8 },\n  { 3, 2, 9 },\n  { 0, 0, 0 }\n};\nint reftrig_singedges23_splitfaces[][4] =\n{\n  { 1, 2, 3, 10 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_singedges23_newelstypes[] =\n{\n  //  HP_QUAD_2E,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG_SINGEDGECORNER2,\n\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_SINGEDGE,\n  HP_TRIG_SINGEDGECORNER2,\n  HP_TRIG_SINGEDGECORNER1,\n  HP_TRIG,\n  HP_NONE,\n};\nint reftrig_singedges23_newels[][8] =\n{\n  //  { 1, 4, 10, 5 },\n  { 1 , 4, 10 },\n  { 5, 1, 10 },\n  { 4, 6, 7, 10 },\n  { 8, 5, 10, 9 },\n  { 6, 2, 7 },\n  { 3, 8, 9 },\n  { 7, 9, 10 },\n};\nHPRef_Struct reftrig_singedges23 =\n{\n  HP_TRIG,\n  reftrig_singedges23_splitedges, \n  reftrig_singedges23_splitfaces, \n  0,\n  reftrig_singedges23_newelstypes, \n  reftrig_singedges23_newels\n};\n\n\n// HP_TRIG_3SINGEDGES\nint reftrig_3singedges_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 2, 1, 5 }, \n  { 2, 3, 6 }, \n  { 3, 2, 7 }, \n  { 3, 1, 8 }, \n  { 1, 3, 9 }, \n  { 0, 0, 0 }\n};\nint reftrig_3singedges_splitfaces[][4] =\n{\n  { 1, 2, 3, 10 },\n  { 2, 3, 1, 11 },\n  { 3, 1, 2, 12 }, \n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_3singedges_newelstypes[] =\n{\n  HP_TRIG, \n  HP_QUAD_SINGEDGE, \n  HP_QUAD_SINGEDGE, \n  HP_QUAD_SINGEDGE, \n  HP_TRIG_SINGEDGECORNER1, \n  HP_TRIG_SINGEDGECORNER2, \n  HP_TRIG_SINGEDGECORNER1, \n  HP_TRIG_SINGEDGECORNER2, \n  HP_TRIG_SINGEDGECORNER1, \n  HP_TRIG_SINGEDGECORNER2, \n  HP_NONE, \n};\nint reftrig_3singedges_newels[][8] =\n{\n  { 10, 11, 12 }, \n  { 4, 5, 11, 10 }, \n  { 6, 7, 12, 11 },\n  { 8, 9, 10, 12 }, \n  { 1, 4, 10 }, \n  { 9, 1, 10 }, \n  { 2, 6, 11 }, \n  { 5, 2, 11 }, \n  { 3, 8, 12 }, \n  { 7, 3, 12 }, \n};\nHPRef_Struct reftrig_3singedges =\n{\n  HP_TRIG,\n  reftrig_3singedges_splitedges, \n  reftrig_3singedges_splitfaces, \n  0,\n  reftrig_3singedges_newelstypes, \n  reftrig_3singedges_newels\n};\n\n// HP_TRIG_ALFELD\nint reftrig_Alfeld_splitedges[][3] =\n{\n  { 0, 0, 0 }\n};\nint reftrig_Alfeld_splitfaces[][4] =\n{\n  { 1, 2, 3, 4 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_Alfeld_newelstypes[] =\n{\n  HP_TRIG, HP_TRIG, HP_TRIG,\n  HP_NONE, \n};\nint reftrig_Alfeld_newels[][8] =\n{\n  { 1, 2, 4 }, \n  { 2, 3, 4 }, \n  { 3, 1, 4 },\n};\nHPRef_Struct reftrig_Alfeld =\n{\n  HP_TRIG,\n  reftrig_Alfeld_splitedges, \n  reftrig_Alfeld_splitfaces,\n  0,\n  reftrig_Alfeld_newelstypes,\n  reftrig_Alfeld_newels\n};\n\n\n// HP_TRIG_POWELL\nint reftrig_Powell_splitedges[][3] =\n{\n  { 1, 2, 4 },\n  { 2, 3, 5 },\n  { 3, 1, 6 },\n  { 0, 0, 0 },\n};\nint reftrig_Powell_splitfaces[][4] =\n{\n  { 1, 2, 3, 7 },\n  { 0, 0, 0, 0 }\n};\n\nHPREF_ELEMENT_TYPE reftrig_Powell_newelstypes[] =\n{\n  HP_TRIG, HP_TRIG, HP_TRIG, HP_TRIG, HP_TRIG, HP_TRIG,\n  HP_NONE, \n};\nint reftrig_Powell_newels[][8] =\n{\n  { 1, 4, 7 }, \n  { 4, 2, 7 }, \n  { 2, 5, 7 },\n  { 5, 3, 7 },\n  { 3, 6, 7 },\n  { 6, 1, 7 },\n};\nHPRef_Struct reftrig_Powell =\n{\n  HP_TRIG,\n  reftrig_Powell_splitedges, \n  reftrig_Powell_splitfaces,\n  0,\n  reftrig_Powell_newelstypes,\n  reftrig_Powell_newels\n};\n\n"
  },
  {
    "path": "libsrc/meshing/hprefinement.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n\n#include \"hpref_segm.hpp\"\n#include \"hpref_trig.hpp\"  \n#include \"hpref_quad.hpp\"\n#include \"hpref_tet.hpp\"  \n#include \"hpref_prism.hpp\"\n#include \"hpref_hex.hpp\" \n#include \"hpref_pyramid.hpp\" \n#include \"classifyhpel.hpp\"  \n\n\n  void HPRefElement :: Reset(void)\n  {\n    np = 8; \n    for (int i = 0; i < 8; i++)\n      {\n\tpnums[i] = -1;\n\tparam[i][0] = param[i][1] = param[i][2] = 0;\n      }\n    domin=-1; domout=-1; // he:\n    levelx = 0; levely = 0; levelz = 0;\n  } \n\n  HPRefElement :: HPRefElement () \n  {\n    Reset();\n  }\n\n  HPRefElement :: HPRefElement(Element & el) :\n    type(HP_NONE), index(el.GetIndex()), levelx(0), levely(0), levelz(0), np(el.GetNV()), domin(-1), domout(-1) //domin,out for segments\n  { \n    //Reset();\n    for (int i=0; i<np ; i++) \n      pnums[i] = el[i]; \n    \n    const Point3d * points = \n      MeshTopology :: GetVertices (el.GetType());\n    for(int i=0;i<np;i++)\n      for(int l=0;l<3;l++) \n\tparam[i][l] = points[i].X(l+1); \n  }\n\n  \n  HPRefElement :: HPRefElement(Element2d & el) :\n    type(HP_NONE), index(el.GetIndex()), levelx(0), levely(0), levelz(0), np(el.GetNV()), domin(-1), domout(-1) //domin,out for segments\n  { \n    //Reset();\n    \n    for (int i=0; i<np ; i++) \n      pnums[i] = el[i]; \n    \n    const Point3d * points = \n      MeshTopology :: GetVertices (el.GetType());\n    for(int i=0;i<np;i++)\n      for(int l=0;l<3;l++) \n\tparam[i][l] = points[i].X(l+1); \n  }\n\n  HPRefElement :: HPRefElement(Segment & el) :\n    type(HP_NONE), levelx(0), levely(0), levelz(0), np(2), domin(el.domin), domout(el.domout), singedge_left(el.singedge_left), singedge_right(el.singedge_right)\n  { \n    //Reset();\n    for (int i=0; i<np ; i++) \n      pnums[i] = el[i];\n    const Point3d * points = \n      MeshTopology :: GetVertices (SEGMENT); \n    for(int i=0;i<np;i++)\n      for(int l=0;l<3;l++) \n        param[i][l] = points[i].X(l+1); \n\n    /*\n    for (int i=0; i<np; i++)\n    {\n      param[i][0] = i;   \n      param[i][1] = -1; param[i][2] = -1;\n    }\n    */\n  }\n  \n  HPRefElement :: HPRefElement(HPRefElement & el) :\n    type(el.type), index(el.index), edgenr(el.edgenr), levelx(el.levelx), levely(el.levely), levelz(el.levelz), np(el.np), coarse_elnr(el.coarse_elnr), domin(el.domin), domout(el.domout), singedge_left(el.singedge_left), singedge_right(el.singedge_right)\n    \n  {\n    //Reset();\n    for (int i=0; i<np ; i++) \n      {\n\tpnums[i] = el[i];\n\tfor(int l=0; l<3; l++) param[i][l] = el.param[i][l]; \n      }      \n  }\n\n  void HPRefElement :: SetType (HPREF_ELEMENT_TYPE t) \n  {\n    type = t; \n    switch(type)\n      {\n      case HP_SEGM: np=2; break; \n      case HP_TRIG: np=3; break; \n      case HP_QUAD: np=4; break; \n      case HP_TET: np=4; break; \n      case HP_PRISM: np=6; break; \n      case HP_PYRAMID: np=5; break; \n      case HP_HEX: np=8; break;      \n\n      default:\n        cerr << \"HPRefElement: illegal type \" << type << endl;\n        throw NgException (\"HPRefElement::SetType: illegal type\");\n      } \n\n    for(int k = 0; k < 8;k++)\n      {\n\tpnums[k]=0;\n\tfor(int l = 0; l < 3; l++) \n          param[k][l]=0.;\n      }\n  }\n\n\n  std::map<HPREF_ELEMENT_TYPE, HPRef_Struct*> & GetHPRegistry()\\\n  {\n    static std::map<HPREF_ELEMENT_TYPE, HPRef_Struct*> registry;\n    return registry;\n  }\n\n  HPRef_Struct * Get_HPRef_Struct (HPREF_ELEMENT_TYPE type)\n  {\n    HPRef_Struct * hps = NULL;\n    /*\n    if (type >= 100 && type < 1000)\n      if (type != HP_TET_1F_0E_1VA)\n        type = HP_NONETET;\n    */\n    switch (type)\n      {\n      case HP_SEGM:\n\thps = &refsegm; break;\n      case HP_SEGM_SINGCORNERL:\n\thps = &refsegm_scl; break;\n      case HP_SEGM_SINGCORNERR:\n\thps = &refsegm_scr; break;\n      case HP_SEGM_SINGCORNERS:\n\thps = &refsegm_sc2; break;\n\t\n      case HP_TRIG:\n\thps = &reftrig; break;\n      case HP_TRIG_SINGCORNER:\n\thps = &reftrig_singcorner; break;\n      case HP_TRIG_SINGCORNER12:\n\thps = &reftrig_singcorner12; break; \n      case HP_TRIG_SINGCORNER123:\n\thps = &reftrig_singcorner123; break;\n      case HP_TRIG_SINGCORNER123_2D:\n\thps = &reftrig_singcorner123_2D; break;\n      case HP_TRIG_SINGEDGE:\n\thps = &reftrig_singedge; break;\n      case HP_TRIG_SINGEDGECORNER1:\n\thps = &reftrig_singedgecorner1; break;\n      case HP_TRIG_SINGEDGECORNER2:\n\thps = &reftrig_singedgecorner2; break;\n      case HP_TRIG_SINGEDGECORNER12:\n\thps = &reftrig_singedgecorner12; break;\n      case HP_TRIG_SINGEDGECORNER3:\n\thps = &reftrig_singedgecorner3; break;\n      case HP_TRIG_SINGEDGECORNER13:\n\thps = &reftrig_singedgecorner13; break;\n      case HP_TRIG_SINGEDGECORNER23:\n\thps = &reftrig_singedgecorner23; break;\n      case HP_TRIG_SINGEDGECORNER123:\n\thps = &reftrig_singedgecorner123; break;\n      case HP_TRIG_SINGEDGES:\n\thps = &reftrig_singedges; break; \n      case HP_TRIG_SINGEDGES2: \n\thps = &reftrig_singedges2; break;\n      case HP_TRIG_SINGEDGES3:\n\thps = &reftrig_singedges3; break;\n      case HP_TRIG_SINGEDGES23:  \n\thps = &reftrig_singedges23; break;\n      case HP_TRIG_3SINGEDGES:\n\thps = &reftrig_3singedges; break;\n \n      case HP_TRIG_ALFELD:\n        hps = &reftrig_Alfeld; break;\n      case HP_TRIG_POWELL:\n        hps = &reftrig_Powell; break;\n\n        \n      case HP_QUAD:\n\thps = &refquad; break;\n      case HP_DUMMY_QUAD_SINGCORNER:\n\thps = &refdummyquad_singcorner; break;\n      case HP_QUAD_SINGCORNER:\n\thps = &refquad_singcorner; break;\n      case HP_QUAD_SINGEDGE:\n\thps = &refquad_singedge; break;\n\n      case HP_QUAD_0E_2VA:\n\thps = &refquad_0e_2va; break;\n      case HP_QUAD_0E_2VB:\n\thps = &refquad_0e_2vb; break;\n\n      case HP_QUAD_0E_3V:\n\thps = &refquad_0e_3v; break;\n      case HP_QUAD_0E_4V:\n\thps = &refquad_0e_4v; break;\n\n      case HP_QUAD_1E_1VA:\n\thps = &refquad_1e_1va; break;\n      case HP_QUAD_1E_1VB:\n\thps = &refquad_1e_1vb; break;\n      case HP_QUAD_1E_1VC:\n\thps = &refquad_1e_1vc; break;\n      case HP_QUAD_1E_1VD:\n\thps = &refquad_1e_1vd; break;\n\n      case HP_QUAD_1E_2VA:\n\thps = &refquad_1e_2va; break;\n      case HP_QUAD_1E_2VB:\n\thps = &refquad_1e_2vb; break;\n      case HP_QUAD_1E_2VC:\n\thps = &refquad_1e_2vc; break;\n      case HP_QUAD_1E_2VD:\n\thps = &refquad_1e_2vd; break;\n      case HP_QUAD_1E_2VE:\n\thps = &refquad_1e_2ve; break;\n      case HP_QUAD_1E_2VF:\n\thps = &refquad_1e_2vf; break;\n\n      case HP_QUAD_1E_3VA:\n\thps = &refquad_1e_3va; break;\n      case HP_QUAD_1E_3VB:\n\thps = &refquad_1e_3vb; break;\n      case HP_QUAD_1E_3VC:\n\thps = &refquad_1e_3vc; break;\n      case HP_QUAD_1E_3VD:\n\thps = &refquad_1e_3vd; break;\n      case HP_QUAD_1E_4V:\n\thps = &refquad_1e_4v; break;\n\n\n      case HP_QUAD_2E:\n\thps = &refquad_2e; break;\n      case HP_QUAD_2E_1VA:\n\thps = &refquad_2e_1va; break;\n      case HP_QUAD_2E_1VB:\n\thps = &refquad_2e_1vb; break;\n      case HP_QUAD_2E_1VC:\n\thps = &refquad_2e_1vc; break;\n      case HP_QUAD_2E_2VA:\n\thps = &refquad_2e_2va; break;\n      case HP_QUAD_2E_2VB:\n\thps = &refquad_2e_2vb; break;\n      case HP_QUAD_2E_2VC:\n\thps = &refquad_2e_2vc; break;\n      case HP_QUAD_2E_3V:\n\thps = &refquad_2e_3v; break;\n\n      case HP_QUAD_2EB_0V:\n\thps = &refquad_2eb_0v; break;\n\n      case HP_QUAD_2EB_1VA:\n\thps = &refquad_2eb_1va; break;\n      case HP_QUAD_2EB_1VB:\n\thps = &refquad_2eb_1vb; break;\n\n\n      case HP_QUAD_2EB_2VA:\n\thps = &refquad_2eb_2va; break;\n      case HP_QUAD_2EB_2VB:\n\thps = &refquad_2eb_2vb; break;\n      case HP_QUAD_2EB_2VC:\n\thps = &refquad_2eb_2vc; break;\n      case HP_QUAD_2EB_2VD:\n\thps = &refquad_2eb_2vd; break;\n\n      case HP_QUAD_2EB_3VA:\n\thps = &refquad_2eb_3va; break;\n      case HP_QUAD_2EB_3VB:\n\thps = &refquad_2eb_3vb; break;\n\n      case HP_QUAD_2EB_4V:\n\thps = &refquad_2eb_4v; break;\n\n      case HP_QUAD_3E:\n\thps = &refquad_3e; break;\n      case HP_QUAD_3E_3VA:\n\thps = &refquad_3e_3va; break;\n      case HP_QUAD_3E_3VB:\n\thps = &refquad_3e_3vb; break;\n      case HP_QUAD_3E_4V:\n\thps = &refquad_3e_4v; break;\n\n\n      case HP_QUAD_4E:\n\thps = &refquad_4e; break;\n\n\n      case HP_TET:\n\thps = &reftet; break;\n      case HP_NONETET:\n\thps = &refnonetet; break;\n      case HP_TET_0E_1V:\n\thps = &reftet_0e_1v; break;\n      case HP_TET_0E_2V:\n\thps = &reftet_0e_2v; break;\n      case HP_TET_0E_3V:\n\thps = &reftet_0e_3v; break;\n      case HP_TET_0E_4V:\n\thps = &reftet_0e_4v; break;\n\n      case HP_TET_1E_0V:      \n\thps = &reftet_1e_0v; break;\n      case HP_TET_1E_1VA:\n\thps = &reftet_1e_1va; break;\n      case HP_TET_1E_1VB:\n\thps = &reftet_1e_1vb; break;\n\n      case HP_TET_1E_2VA:\n\thps = &reftet_1e_2va; break;\n      case HP_TET_1E_2VB:\n\thps = &reftet_1e_2vb; break;\n      case HP_TET_1E_2VC:\n\thps = &reftet_1e_2vc; break;\n      case HP_TET_1E_2VD:\n\thps = &reftet_1e_2vd; break;\n\n      case HP_TET_1E_3VA:\n\thps = &reftet_1e_3va; break;\n      case HP_TET_1E_3VB:\n\thps = &reftet_1e_3vb; break;\n      case HP_TET_1E_4V:\n\thps = &reftet_1e_4v; break;\n\n      case HP_TET_2EA_0V:\n\thps = &reftet_2ea_0v; break;\n      case HP_TET_2EA_1VB:\n\thps = &reftet_2ea_1vb; break;\n      case HP_TET_2EA_1VC:\n\thps = &reftet_2ea_1vc; break;\n      case HP_TET_2EA_1VA:\n\thps = &reftet_2ea_1va; break;\n      case HP_TET_2EA_2VA:\n\thps = &reftet_2ea_2va; break;\n      case HP_TET_2EA_2VB:\n\thps = &reftet_2ea_2vb; break;\n      case HP_TET_2EA_2VC:\n\thps = &reftet_2ea_2vc; break;\n      case HP_TET_2EA_3V:\n\thps = &reftet_2ea_3v; break;\n\n      case HP_TET_2EB_0V:\n\thps = &reftet_2eb_0v; break;\n      case HP_TET_2EB_1V:\n\thps = &reftet_2eb_1v; break;\n      case HP_TET_2EB_2VA:\n\thps = &reftet_2eb_2va; break;\n      case HP_TET_2EB_2VB:\n\thps = &reftet_2eb_2vb; break;\n      case HP_TET_2EB_2VC:\n\thps = &reftet_2eb_2vc; break;\n      case HP_TET_2EB_3V:\n\thps = &reftet_2eb_3v; break;\n      case HP_TET_2EB_4V:\n\thps = &reftet_2eb_4v; break;\n\n\n      case HP_TET_3EA_0V:\n\thps = &reftet_3ea_0v; break;\n      case HP_TET_3EA_1V:\n\thps = &reftet_3ea_1v; break;\n      case HP_TET_3EA_2V:\n\thps = &reftet_3ea_2v; break;\n      case HP_TET_3EA_3V:\n\thps = &reftet_3ea_3v; break;\n\n      case HP_TET_3EB_0V:\n\thps = &reftet_3eb_0v; break;\n      case HP_TET_3EB_1V:\n\thps = &reftet_3eb_1v; break;\n      case HP_TET_3EB_2V:\n\thps = &reftet_3eb_2v; break;\n      case HP_TET_3EC_0V:\n\thps = &reftet_3ec_0v; break;\n      case HP_TET_3EC_1V:\n\thps = &reftet_3ec_1v; break;\n      case HP_TET_3EC_2V:\n\thps = &reftet_3ec_2v; break;\n      case HP_TET_3ED_3V:\n\thps = &reftet_3ed_3v; break;\n\n\n      case HP_TET_1F_0E_0V:\n\thps = &reftet_1f_0e_0v; break;\n        // case HP_TET_1F_0E_1VA:\n\t// hps = &reftet_1f_0e_1va; break;\n      case HP_TET_1F_0E_1VB:\n\thps = &reftet_1f_0e_1vb; break;\n      case HP_TET_1F_0E_2V:\n\thps = &reftet_1f_0e_2v; break;\n        // case HP_TET_1F_0E_3V:\n\t// hps = &reftet_1f_0e_3v; break;\n      case HP_TET_1F_1EA_0V:\n\thps = &reftet_1f_1ea_0v; break;\n      case HP_TET_1F_1EB_0V:\n\thps = &reftet_1f_1eb_0v; break;\n      case HP_TET_1F_1E_1VA:\n\thps = &reftet_1f_1e_1va; break;\n      case HP_TET_1F_1E_1VB:\n\thps = &reftet_1f_1e_1vb; break;\n      case HP_TET_1F_1E_2VA:\n\thps = &reftet_1f_1e_2va; break;\n      case HP_TET_1F_1E_2VB:\n\thps = &reftet_1f_1e_2vb; break;\n      case HP_TET_1F_2E_0VA:\n        hps = &reftet_1f_2e_0va; break;\n      case HP_TET_1F_2E_0VB:\n        hps = &reftet_1f_2e_0vb; break;\n      case HP_TET_2F_0E_0V:\n\thps = &reftet_2f_0e_0v; break;\n      case HP_TET_2F_0E_1V:\n\thps = &reftet_2f_0e_1v; break;\n      case HP_TET_2F_1E_0VA:\n        hps = &reftet_2f_1e_0va; break;\n      case HP_TET_2F_1E_0VB:\n        hps = &reftet_2f_1e_0vb; break;\n      case HP_TET_3F_0E_0V:\n        hps = &reftet_3f_0e_0v; break;\n\n      case HP_TET_ALFELD:\n        hps = &reftet_Alfeld; break;\n\n        \n      case HP_PRISM:\n\thps = &refprism; break;\n      case HP_PRISM_SINGEDGE:\n\thps = &refprism_singedge; break;\n\t//      case HP_PRISM_SINGEDGE_H1:\n\t//\thps = &refprism_singedge_h1; break;\n\t// case HP_PRISM_SINGEDGE_H12:\n\t//\thps = &refprism_singedge_h12; break;\n      case HP_PRISM_SINGEDGE_V12:\n\thps = &refprism_singedge_v12; break;\n\t\n\n      case HP_PRISM_1FA_0E_0V:\n\thps = &refprism_1fa_0e_0v; break;\n      case HP_PRISM_2FA_0E_0V:\n\thps = &refprism_2fa_0e_0v; break;\n      case HP_PRISM_1FB_0E_0V:\n\thps = &refprism_1fb_0e_0v; break;\n      case HP_PRISM_1FB_1EA_0V: \n\thps = &refprism_1fb_1ea_0v; break;\n \n      case HP_PRISM_1FA_1E_0V:\n\thps = &refprism_1fa_1e_0v; break;\n      case HP_PRISM_2FA_1E_0V:\n\thps = &refprism_2fa_1e_0v; break; \n      case HP_PRISM_1FA_1FB_0E_0V: \n\thps = &refprism_1fa_1fb_0e_0v; break;\n      case HP_PRISM_2FA_1FB_0E_0V: \n\thps = &refprism_2fa_1fb_0e_0v; break; \n      case HP_PRISM_1FA_1FB_1EA_0V: \n\thps = &refprism_1fa_1fb_1ea_0v; break; \n      case HP_PRISM_1FA_1FB_1EB_0V: \n\thps = &refprism_1fa_1fb_1eb_0v; break; \n      case HP_PRISM_2FA_1FB_1EA_0V:  \n\thps = &refprism_2fa_1fb_1ea_0v; break; \n      case HP_PRISM_1FB_1EC_0V: \n\thps = &refprism_1fb_1ec_0v; break; \n      case HP_PRISM_1FA_1FB_1EC_0V: \n\thps = &refprism_1fa_1fb_1ec_0v; break; \n      case HP_PRISM_2FA_1FB_1EC_0V: \n\thps = &refprism_2fa_1fb_1ec_0v; break;  \n      case HP_PRISM_1FB_2EA_0V: \n\thps = &refprism_1fb_2ea_0v; break; \n      case HP_PRISM_1FA_1FB_2EA_0V:   \n\thps = &refprism_1fa_1fb_2ea_0v; break; \n      case HP_PRISM_2FA_1FB_2EA_0V:  \n\thps = &refprism_2fa_1fb_2ea_0v; break;   \n      case HP_PRISM_1FB_2EB_0V: \n\thps = &refprism_1fb_2eb_0v; break; \n      case HP_PRISM_1FA_1FB_2EB_0V:   \n\thps = &refprism_1fa_1fb_2eb_0v; break;  \n      case HP_PRISM_1FA_1FB_2EC_0V: \n\thps = &refprism_1fa_1fb_2ec_0v; break; \n      case HP_PRISM_2FA_1FB_2EB_0V: \n\thps = &refprism_2fa_1fb_2eb_0v; break;  \n      case HP_PRISM_1FB_3E_0V: \n\thps = &refprism_1fb_3e_0v; break; \n      case HP_PRISM_1FA_1FB_3E_0V:  \n\thps = &refprism_1fa_1fb_3e_0v; break;  \n      case HP_PRISM_2FA_1FB_3E_0V:  \n        hps = &refprism_2fa_1fb_3e_0v; break; \n      case HP_PRISM_2FB_0E_0V: \n\thps = &refprism_2fb_0e_0v; break;  \n      case HP_PRISM_1FA_2FB_0E_0V: \n\thps = &refprism_1fa_2fb_0e_0v; break; \n      case HP_PRISM_2FA_2FB_0E_0V:    \n        hps = &refprism_2fa_2fb_0e_0v; break;  \n      case HP_PRISM_2FB_1EC_0V:  \n\thps = &refprism_2fb_1ec_0v; break;  \n      case HP_PRISM_1FA_2FB_1EC_0V: \n        hps = &refprism_1fa_2fb_1ec_0v; break; \n      case HP_PRISM_2FA_2FB_1EC_0V: \n\thps = &refprism_2fa_2fb_1ec_0v; break; \n      case HP_PRISM_1FA_2FB_1EB_0V: \n\thps = &refprism_1fa_2fb_1eb_0v; break; \n      case HP_PRISM_2FB_3E_0V:    \n\thps = &refprism_2fb_3e_0v; break;\n      case HP_PRISM_1FA_2FB_3E_0V: \n\thps = &refprism_1fa_2fb_3e_0v; break;\n      case HP_PRISM_2FA_2FB_3E_0V:  \n\thps = &refprism_2fa_2fb_3e_0v; break;\n      case HP_PRISM_1FA_2E_0V:   \n\thps = &refprism_1fa_2e_0v; break; \n      case HP_PRISM_2FA_2E_0V:  \n\thps = &refprism_2fa_2e_0v; break;   \n      case HP_PRISM_3E_0V:  \n\thps = &refprism_3e_0v; break;\n      case HP_PRISM_1FA_3E_0V:   \n\thps = &refprism_1fa_3e_0v; break; \n      case HP_PRISM_2FA_3E_0V:  \n\thps = &refprism_2fa_3e_0v; break;   \n      case HP_PRISM_3FB_0V:  \n\thps = &refprism_3fb_0v; break;\n      case HP_PRISM_1FA_3FB_0V:   \n\thps = &refprism_1fa_3fb_0v; break; \n      case HP_PRISM_2FA_3FB_0V:  \n\thps = &refprism_2fa_3fb_0v; break;   \n\t//  case HP_PRISM_3E_4EH:\n\t//  hps = &refprism_3e_4eh; break;   \n\t\n\t\n\t/*case HP_PRISM_1FB_1EB_0V:\n\thps = &refprism_1fb_1eb_0v; break;\n      case HP_PRISM_2F_0E_0V:\n\thps = &refprism_2f_0e_0v; break;\n\t*/\n\t\n\t\n      case HP_PYRAMID:\n\thps = &refpyramid; break;\n      case HP_PYRAMID_0E_1V:\n\thps = &refpyramid_0e_1v; break;\n      case HP_PYRAMID_EDGES:\n\thps = &refpyramid_edges; break;\n      case HP_PYRAMID_1FB_0E_0V:\n\thps = &refpyramid_1fb_0e_0v; break;\n      case HP_PYRAMID_1FB_0E_1VA:\n\thps = &refpyramid_1fb_0e_1va; break;\n\n\t\n      case HP_HEX:\n\thps = &refhex; break;\n      case HP_HEX_0E_1V:\n\thps = &refhex_0e_1v; break;\n      case HP_HEX_1E_1V:\n\thps = &refhex_1e_1v; break;\n      case HP_HEX_1E_0V:\n\thps = &refhex_1e_0v; break;\n      case HP_HEX_3E_0V:\n\thps = &refhex_3e_0v; break;\n\n      case HP_HEX_1F_0E_0V:\n\thps = &refhex_1f_0e_0v; break;\n      case HP_HEX_1FA_1FB_0E_0V: \n\thps = &refhex_1fa_1fb_0e_0v; break; \n\n      case HP_HEX7:\n\thps = &refhex7; break;\n      case HP_HEX7_1FA:\n\thps = &refhex7_1fa; break;\n      case HP_HEX7_1FB:\n\thps = &refhex7_1fb; break;\n       \n\n\n      default:\n        {\n          if (GetHPRegistry().count(type))\n            hps = GetHPRegistry()[type];\n          else\n            hps = NULL;\n        }\n      }\n\n    /*\n    if (type != HP_TET_1E_4V && type != HP_TET_1E_2VD)\n      {\n\tif (hps->geom == HP_TET)\n\t  hps = &reftet;\n\tif (hps->geom == HP_TRIG)\n\t  hps = &reftrig;\n      }\n    */\n\n    if (!hps)\n      {\n\tcout << \"Attention hps : hp-refinement not implemented for case \" << type << endl;\n\tPrintSysError (\"hp-refinement not implemented for case \", type);\n      }\n\n    return hps;\n  }\n\n  template <typename HT_EDGEPOINT_DOM>\n  bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoiclt_dom, \n\t\t       NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n\t\t\tINDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int & levels, int & act_ref); \n\n  bool ClassifyHPElements (Mesh & mesh, NgArray<HPRefElement> & elements, SplittingType split, int & act_ref, int & levels);\n  \n  \n  void  InitHPElements(Mesh & mesh, NgArray<HPRefElement> & elements) \n  { \n    // for(ElementIndex i = 0; i < mesh.GetNE(); i++)\n    for(ElementIndex i : mesh.VolumeElements().Range())\n      {\n\tHPRefElement hpel(mesh[i]); \n\thpel.coarse_elnr = int(i); \n\t\n\tswitch (mesh[i].GetType()) \n\t  { \n\t  case PRISM:   hpel.type = HP_PRISM;   break; \n\t  case HEX:     hpel.type = HP_HEX;     break; \n\t  case TET:     hpel.type = HP_TET;     break; \n\t  case PYRAMID: hpel.type = HP_PYRAMID; break; \n\n          default:\n            cerr << \"HPRefElement: illegal elementtype (1) \" << mesh[i].GetType() << endl;\n            throw NgException (\"HPRefElement: illegal elementtype (1)\");\n\t  } \n\telements.Append(hpel); \n      }\n\t    \n    for(SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)\n      {\n\tHPRefElement hpel(mesh[i]);\n\thpel.coarse_elnr = i; \n\tswitch(mesh[i].GetType())\n\t  { \n\t  case TRIG: hpel.type = HP_TRIG; break; \n\t  case QUAD: hpel.type = HP_QUAD; break; \n\n          default:\n            cerr << \"HPRefElement: illegal elementtype (1b) \" << mesh[i].GetType() << endl;\n            throw NgException (\"HPRefElement: illegal elementtype (1b)\");\n\t  } \n\telements.Append(hpel);\n      } \n        \n    for(SegmentIndex i = 0; i < mesh.GetNSeg(); i++) \n      { \n\tSegment & seg = mesh[i];\n\tHPRefElement hpel(mesh[i]);\n\thpel.coarse_elnr = i; \n\thpel.type = HP_SEGM; \n\t// hpel.index = seg.edgenr + 10000*seg.si;\n        hpel.index = seg.GetIndex();\n        hpel.edgenr = seg.GetEdgeNr();\n        /*\n\tif(seg.edgenr >= 10000)\n\t  {\n\t    throw NgException(\"assumption that seg.edgenr < 10000 is wrong\");\n\t  }\n        */\n\telements.Append(hpel); \n      }\n  }\n\n \n \n  /* *******************************  DoRefinement *************************************** */\n  void DoRefinement (Mesh & mesh, NgArray<HPRefElement> & elements,\n\t\t     Refinement * ref, double fac1) \n  {\n    elements.SetAllocSize (5 * elements.Size());\n    INDEX_2_HASHTABLE<int> newpts(elements.Size()+1);\n    INDEX_3_HASHTABLE<int> newfacepts(elements.Size()+1);\n\n    double fac2 = max(0.001,min(1.0/3,fac1)); // factor for face points\n    PrintMessage(3, \" in HP-REFINEMENT with fac1 \", fac1); \n    *testout << \" in HP-REFINEMENT with fac1 \" << fac1 <<  endl; \n   \n\n    int oldelsize = elements.Size();\n       \n    for (int i = 0; i < oldelsize; i++)\n      {\n\tHPRefElement & el = elements[i]; \n\tHPRef_Struct * hprs = Get_HPRef_Struct (el.type);\n\t\t\n\tif (!hprs) \n\t  {\n\t    cout << \"Refinementstruct not defined for element \" << el.type << endl;\n\t    continue;\n\t  }\n\n\tint j = 0;\n\twhile (hprs->splitedges[j][0])\n\t  {\n\t    INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1],\n\t\t       el.pnums[hprs->splitedges[j][1]-1]);\n            if (fac1 == 0.5) i2.Sort();\n            \n\t    if (!newpts.Used (i2))\n\t      {\n\t\tPoint<3> np; \n\t\tfor( int l=0;l<3;l++)\n\t\t  np(l) = (1-fac1)*mesh.Point(i2.I1())(l) \n\t\t    + fac1 * mesh.Point(i2.I2())(l); \n\t\n\t\tint npi = mesh.AddPoint (np);\n\t\tnewpts.Set (i2, npi);\n\t      }\n\t    j++;\n\t  }\n\t\n\tj = 0;\n\tif (hprs->splitfaces)\n\t  while (hprs->splitfaces[j][0])\n\t    {\n\t      INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1],\n\t\t\t el.pnums[hprs->splitfaces[j][1]-1],\n\t\t\t el.pnums[hprs->splitfaces[j][2]-1]);\n\n\t      if (i3.I2() > i3.I3()) Swap (i3.I2(), i3.I3());\n\t      \n\t      if (!newfacepts.Used (i3))\n\t\t{\n\t\t  Point<3> np; \n\t\t  \tfor( int l=0;l<3;l++)\n\t\t\t  np(l) = (1-2*fac2)*mesh.Point(i3.I1())(l) \n\t\t\t    + fac2*mesh.Point(i3.I2())(l)  + fac2*mesh.Point(i3.I3())(l);  \n\t\t  int npi = mesh.AddPoint (np);\n\t\t  newfacepts.Set (i3, npi);\n\t\t}\n\t      j++;\n\t    }\n      }\n     \n    for (int i = 0; i < oldelsize; i++)\n      {\n\tHPRefElement el = elements[i];\n\tHPRef_Struct * hprs = Get_HPRef_Struct (el.type);\n\tint newlevel = el.levelx;\n\tint oldnp = 0;\n\tswitch (hprs->geom)\n\t  {\n\t  case HP_SEGM: oldnp = 2; break;\n\t  case HP_TRIG: oldnp = 3; break;\n\t  case HP_QUAD: oldnp = 4; break;\n\t  case HP_TET: oldnp = 4; break;\n\t  case HP_PYRAMID: oldnp = 5; break;\n\t  case HP_PRISM: oldnp = 6; break;\n\t  case HP_HEX: oldnp = 8; break;\n\t  case HP_HEX7: oldnp = 7; break;\n            \n          default:\n            cerr << \"HPRefElement: illegal type (3) \" << hprs->geom << endl;\n            throw NgException (\"HPRefElement::SetType: illegal type (3)\");\n\t  }\n\n\n\tif (el.type == HP_SEGM ||\n\t    el.type == HP_TRIG ||\n\t    el.type == HP_QUAD ||\n\t    el.type == HP_TET ||\n\t    el.type == HP_PRISM ||\n\t    el.type == HP_HEX || \n\t    el.type == HP_HEX7 || \n\t    el.type == HP_PYRAMID)\n\t  newlevel = el.levelx;\n\n\tif (!hprs) continue;\n\n\tint newpnums[64];\n\tdouble newparam[64][3];\n\n\tint j;\n\tfor (j = 0; j < oldnp; j++)\n\t  {\n\t    newpnums[j] = el.pnums[j];\n\t    for (int l = 0; l < 3; l++)\n\t      newparam[j][l] = el.param[j][l];\n\t  }\n\n\t// split edges, incl. transferring curvature\n\tj = 0;\n\twhile (hprs->splitedges[j][0])\n\t  {\n\t    INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1],\n\t\t       el.pnums[hprs->splitedges[j][1]-1]);\n            if (fac1 == 0.5) i2.Sort();\n            \n\t    int npi = newpts.Get(i2);\n\t    newpnums[hprs->splitedges[j][2]-1] = npi;\n\n\t    for (int l = 0; l < 3; l++)\n\t      newparam[hprs->splitedges[j][2]-1][l] =\n\t\t(1-fac1) * el.param[hprs->splitedges[j][0]-1][l] + \n\t\tfac1 * el.param[hprs->splitedges[j][1]-1][l];\n\t      \n\t    j++;\n\t  }\n\n\t// split faces\n\tj = 0;\n\tif (hprs->splitfaces)\n\t  while (hprs->splitfaces[j][0])\n\t    {\n\t      INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1],\n\t\t\t el.pnums[hprs->splitfaces[j][1]-1],\n\t\t\t el.pnums[hprs->splitfaces[j][2]-1]);\n\t      if (i3.I2() > i3.I3())\n\t\tSwap (i3.I2(), i3.I3());\n\t      int npi = newfacepts.Get(i3);\n\t      newpnums[hprs->splitfaces[j][3]-1] = npi;\n\t    \n\n\t      for (int l = 0; l < 3; l++)\n\t\tnewparam[hprs->splitfaces[j][3]-1][l] =\n\t\t  (1-2*fac2) * el.param[hprs->splitfaces[j][0]-1][l] + \n\t\t  fac2 * el.param[hprs->splitfaces[j][1]-1][l] + \n\t\t  fac2 * el.param[hprs->splitfaces[j][2]-1][l];\n\t      j++;\n\t    }\n\t// split elements\n\tj = 0;\n\tif (hprs->splitelements)\n\t  while (hprs->splitelements[j][0])\n\t    {\n\t      //int pi1 = el.pnums[hprs->splitelements[j][0]-1];\n\t      Point<3> np; \n\t      \tfor( int l=0;l<3;l++)\n\t\t  np(l) = (1-3*fac1)* mesh.Point(el.pnums[hprs->splitelements[j][0]-1])(l) \n\t\t    + fac1* mesh.Point(el.pnums[hprs->splitelements[j][1]-1])(l)\n\t\t    + fac1* mesh.Point(el.pnums[hprs->splitelements[j][2]-1])(l)\n\t\t    + fac1* mesh.Point(el.pnums[hprs->splitelements[j][3]-1])(l); \n\t      \n\t      int npi = mesh.AddPoint (np);\n\t      \n\t      newpnums[hprs->splitelements[j][4]-1] = npi;\n\t      \n\t  \t    \n\t      for (int l = 0; l  < 3; l++)\n\t\tnewparam[hprs->splitelements[j][4]-1][l] =\n\t\t  (1-3*fac1) * el.param[hprs->splitelements[j][0]-1][l] + \n\t\t  fac1 * el.param[hprs->splitelements[j][1]-1][l] + \n\t\t  fac1 * el.param[hprs->splitelements[j][2]-1][l] + \n\t\t  fac1 * el.param[hprs->splitelements[j][3]-1][l];\n\n\t      j++;\n\t    }\n \n\tj = 0;\n\n\t/*\n\t*testout << \" newpnums = \";\n\tfor (int hi = 0; hi < 64; hi++)\n\t  *testout << newpnums[hi] << \" \";\n\t*testout << endl;\n\t*/\n\n\twhile (hprs->neweltypes[j])\n\t  {\n\t    HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]);\n\t    HPRefElement newel(el);\n\n\t    newel.type = hprs->neweltypes[j]; \n\t    // newel.index = elements[i].index;\n\t    // newel.coarse_elnr = elements[i].coarse_elnr;\n            if (newel.type == HP_SEGM ||\n                newel.type == HP_TRIG ||\n                newel.type == HP_QUAD ||\n                newel.type == HP_TET ||\n                newel.type == HP_PRISM ||\n                newel.type == HP_HEX || \n                newel.type == HP_HEX7 || \n                newel.type == HP_PYRAMID)\n              newel.levelx = newel.levely = newel.levelz = newlevel;\n            else\n              newel.levelx = newel.levely = newel.levelz = newlevel+1;\n\t    \n            switch(hprsnew->geom) \n\t      {\n\t      case HP_SEGM:    newel.np=2; break; \n\t      case HP_QUAD:    newel.np=4; break;\n\t      case HP_TRIG:    newel.np=3; break;\n\t      case HP_HEX:     newel.np=8; break; \n\t      case HP_HEX7:    newel.np=7; break; \n\t      case HP_PRISM:   newel.np=6; break;\n\t      case HP_TET:     newel.np=4; break; \n\t      case HP_PYRAMID: newel.np=5; break; \n              default:\n                throw NgException (string(\"hprefinement.cpp: illegal type\"));\n\t      }\n\n\t    for (int k = 0; k < newel.np; k++)\n\t      newel.pnums[k] = newpnums[hprs->newels[j][k]-1];\n\t    \n\t    /*\n\t    *testout  << \" newel pnums \" ; \n\t    for (int k = 0; k < newel.np; k++)  \n\t      *testout  << newel.pnums[k] << \"\\t\"; \n\t    *testout << endl; \n\t    */\n\n\t    for (int k = 0; k < newel.np; k++)  \n\t      { \n\t\tfor (int l = 0; l < 3; l++)\n\t\t  { \n\t\t    newel.param[k][l] = newparam[hprs->newels[j][k]-1][l];\n\t\t    //    *testout << newel.param[k][l] << \" \\t \";\n\t\t  } \n\t\t// *testout << endl; \n\t      } \n\t    \n\t    if (j == 0) \n\t      elements[i] = newel; // overwrite old element\n\t    else\n\t      elements.Append (newel);\n\t    j++;\n\t  }\n      } \n  }\n\n\n\n\n\n\n  /* ************************** DoRefineDummies ******************************** */\n\n  void DoRefineDummies (Mesh & mesh, NgArray<HPRefElement> & elements,\n\t\t\tRefinement * ref)\n  {\n    int oldelsize = elements.Size();\n\n    for (int i = 0; i < oldelsize; i++)\n      {\n\tHPRefElement el = elements[i];\n\n\tHPRef_Struct * hprs = Get_HPRef_Struct (el.type);\n\tif (!hprs) continue;\n\n\tif (el.type != HP_DUMMY_QUAD_SINGCORNER &&\n\t    el.type != HP_PYRAMID_EDGES &&\n\t    el.type != HP_PYRAMID_0E_1V &&\n\t    el.type != HP_HEX_0E_1V &&\n\t    el.type != HP_HEX_1E_1V &&\n\t    el.type != HP_HEX_1E_0V &&\n\t    el.type != HP_HEX_3E_0V\n\t    ) continue;\n\n\tint newlevel = el.levelx;\n\n\tint newpnums[8];\n\tint j;\n\tfor (j = 0; j < 8; j++)\n\t  newpnums[j] = el.pnums[j];\n\n\tdouble newparam[8][3];\n\tfor (j = 0; j < 8; j++)\n\t  for (int k = 0; k < 3; k++)\n\t    newparam[j][k] = el.param[j][k];\n\n\tj = 0;\n\twhile (hprs->neweltypes[j])\n\t  {\n\t    HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]);\n\t    HPRefElement newel(el);\n\t    switch(hprsnew->geom)\n\t      {\n\t      case HP_SEGM: newel.np=2; break; \n\t      case HP_QUAD: newel.np=4; break; \n\t      case HP_TRIG: newel.np=3; break; \n\t      case HP_HEX: newel.np=8; break; \n\t      case HP_PRISM: newel.np=6; break;\n\t      case HP_TET: newel.np=4; break; \n\t      case HP_PYRAMID: newel.np=5; break; \n\n              default:\n                cerr << \"HPRefElement: illegal type (4) \" << hprsnew->geom << endl;\n                throw NgException (\"HPRefElement: illegal type (4)\");\n                \n\t      }\n\t    newel.type = hprs->neweltypes[j];\n\t    for (int k = 0; k < 8; k++)\n\t      newel.pnums[k] = newpnums[hprs->newels[j][k]-1];\n\t    newel.index = el.index;\n            newel.edgenr = el.edgenr;\n\t    newel.coarse_elnr = el.coarse_elnr;\n\t    newel.levelx = newel.levely = newel.levelz = newlevel;\n\n\t    for (int k = 0; k < 8; k++)\n\t      for (int l = 0; l < 3; l++)\n\t\tnewel.param[k][l] = newparam[hprs->newels[j][k]-1][l];\n\t\t\n\t    if (j == 0)\n\t      elements[i] = newel;\n\t    else\n\t      elements.Append (newel);\n\t    j++;\n\t  }\n      }\n  }\n\n\n\n\n\n\n\n  void SubdivideDegeneratedHexes (Mesh & mesh, NgArray<HPRefElement> & elements, double fac1)\n  {\n    int oldne = elements.Size();\n    for (int i = 0; i < oldne; i++)\n      if (Get_HPRef_Struct (elements[i].type)->geom == HP_HEX)\n\t{\n\t  bool common = 0;\n\t  for (int j = 0; j < 8; j++)\n\t    for (int k = 0; k < j; k++)\n\t      if (elements[i].pnums[j] == elements[i].pnums[k])\n\t\tcommon = 1;\n\t  if (common)\n\t    {\n\n               \n\t      cout << \" Degenerate Hex found \" << endl; \n              *testout << \" Degenerate Hex found \" << endl; \n\t      HPRefElement el = elements[i];\n\t      HPRefElement newel = el;\n\n\t      Point<3> center(0,0,0);\n\t      double newparam[3] = { 0, 0, 0 };\n\n\t      for (int j = 0; j < 8; j++)\n\t\t{\n\t\t  \n\t\t  \n\t\t  center += 0.125 * Vec<3>(mesh[el.pnums[j]]); \n\t\t  // 0.125 originates form 8 points not from fac1;\n                  \n\t\t  for (int l = 0; l < 3; l++)\n\t\t    newparam[l] += 0.125 * el.param[j][l];\n                  \n\t\t}\n\n\t      int npi = mesh.AddPoint (center);\n\n\t      const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (HEX);\n\n\t      for (int j = 0; j < 6; j++)  \n\t\t{\n\t\t  NgArray<int> pts;\n\t\t  for (int k = 0; k < 4; k++)\n\t\t    {\n\t\t      bool same = 0;\n\t\t      for (int l = 0; l < pts.Size(); l++)\n\t\t\tif (el.pnums[pts[l]] == el.pnums[faces[j][k]-1])\n\t\t\t  same = 1;\n\t\t      if (!same)\n\t\t\tpts.Append (faces[j][k]-1);\n\n\t\t    }\n\t\t  \n\t\t  \n\t\t  if (pts.Size() == 3) // TrigFace -> TET \n\t\t    {\n\t\t      \n\t\t      for (int k = 0; k < 3; k++)\n\t\t\t{\n\t\t\t  newel.pnums[k] = el.pnums[pts[2-k]];\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    newel.param[k][l] = el.param[pts[2-k]][l];\n\t\t\t}\n\t\t      newel.pnums[3] = npi;\n\t\t      for (int l = 0; l < 3; l++)\n\t\t\tnewel.param[3][l] = newparam[l];\n\n\t\t      newel.type = HP_TET;\n\t\t      newel.np = 4; \n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      for (int k = 0; k < 4; k++)\n\t\t\t{\n\t\t\t  newel.pnums[k] = el.pnums[pts[3-k]];\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    newel.param[k][l] = el.param[pts[3-k]][l];\n\t\t\t}\n\n\t\t      newel.pnums[4] = npi;\n\t\t      for (int l = 0; l < 3; l++)\n\t\t\tnewel.param[4][l] = newparam[l];\n\n\t\t      newel.type = HP_PYRAMID;\n\t\t      newel.np = 5;\n\t\t    }\n\t\t  \n\t\t  if (j == 0)\n\t\t    elements[i] = newel;\n\t\t  else\n\t\t    elements.Append (newel); \n\n\t\t  \n\t\t}\n\n\t      /*     const ELEMENT_EDGE * edges = MeshTopology::GetEdges (HEX);\n\t       \n\t\tfor(int k=0;k<12;k++) \n\t\t  { \n\t\t    int e[2];  \n\t\t    for(int l=0;l<2;l++) e[l] = edges[k][l]-1; \n\t\t    if(el.PNum(e[0]+1)!=el.PNum(e[1]+1)) \n\t\t      { \n\t\t\tnewel.SetType(HP_SEGM);\n\t\t\tfor(int l=0;l<2;l++) \n\t\t\t  { \n\t\t\t    newel.pnums[0] = el.PNum(e[l]+1); \n\t\t\t    newel.pnums[1] = npi; \n\t\t\t    for(int j=0;j<3;j++) \n\t\t\t      {\n\t\t\t\t//\tnewel.param[0][j] = el.param[e[l]][j]; \n\t\t\t\t//\tnewel.param[1][j] = newparam[j]; \n\t\t\t      } \n\t\t\t    \n\t\t\t    elements.Append(newel);\n\t\t\t  }\n\t\t\tnewel.SetType(HP_TRIG);\n\t\t\tnewel.pnums[0] = el.PNum(e[0]+1); \t\t\t\n\t\t\tnewel.pnums[1] = el.PNum(e[1]+1); \t\t\t\n\t\t\tnewel.pnums[2] = npi; \n\t\t\t\n\t\t\t*testout << \"DEGHEX TRIG :: newpnums \" << newel.pnums[0] << \"\\t\"  << newel.pnums[1] << \"\\t\"  << newel.pnums[2] << endl;  \n\tcout << \"DEGHEX TRIG :: newpnums \" << newel.pnums[0] << \"\\t\"  << newel.pnums[1] << \"\\t\"  << newel.pnums[2] << endl;  \n\t\t\tfor(int j=0;j<3;j++) \n\t\t\t  {\n\t\t\t    // newel.param[0][j] = el.param[e[0]][j]; \n\t\t\t    //   newel.param[1][j] = el.param[e[1]][j]; \n\t\t\t    //   newel.param[2][j] = newparam[j]; \n\t\t\t  } \n\t\t\t\n\t\t\telements.Append(newel);\n\t\t      }\n\t\t\t\n\t\t      }*/\n\t    }\n\t}\n  }\n\n\n  void CalcStatistics (NgArray<HPRefElement> & elements)\n  {\n    return;\n#ifdef ABC    \n    int i, p;\n    int nsegm = 0, ntrig = 0, nquad = 0;\n    int nhex = 0, nprism = 0, npyramid = 0, ntet = 0;\n    int maxlevel = 0;\n\n    for (i = 1; i <= elements.Size(); i++)\n      {\n\tconst HPRefElement & el = elements.Get(i);\n\tmaxlevel = max2 (el.level, maxlevel);\n\tswitch (Get_HPRef_Struct (el.type)->geom)\n\t  {\n\t  case HP_SEGM:\n\n\t    {\n\t      nsegm++;\n\t      break;\n\t    }\n\t  case HP_TRIG:\n\t    {\n\t      ntrig ++;\n\t      break;\n\t    }\n\t  case HP_QUAD:\n\t    {\n\t      nquad++;\n\t      break;\n\t    }\n\t  case HP_TET:\n\t    {\n\t      ntet++;\n\t      break;\n\t    }\n\n\t  case HP_PRISM:\n\t    {\n\t      nprism++;\n\t      break;\n\t    }\n\n\t  case HP_PYRAMID:\n\t    {\n\t      npyramid++;\n\t      break;\n\t    }\n\n\t  case HP_HEX:\n\t    {\t\n\t      nhex++;\n\t      break;\n\t    }\n\n\t  default:\n\t    {\n\t      cerr << \"statistics error, unknown element type\" << endl;\n\t    }\n\t  }\n      }\n\n    cout << \"level = \" << maxlevel << endl;\n    cout << \"nsegm = \" << nsegm << endl;\n    cout << \"ntrig = \" << ntrig << \", nquad = \" << nquad << endl;\n    cout << \"ntet = \" << ntet << \", npyr = \" << npyramid\n\t << \", nprism = \" << nprism << \", nhex = \" << nhex << endl;\n\n    return;\n\n    double memcost = 0, cpucost = 0;\n    for (p = 1; p <= 20; p++)\n      {\n\tmemcost = (ntet + nprism + nhex) * pow (static_cast<double>(p), 6.0);\n\tcpucost = (ntet + nprism + nhex) * pow (static_cast<double>(p), 9.0);\n\tcout << \"costs for p = \" << p << \": mem = \" << memcost << \", cpu = \" << cpucost << endl;\n      }\n\n    double memcosttet = 0;\n    double memcostprism = 0;\n    double memcosthex = 0;\n    double memcostsctet = 0; \n    double memcostscprism = 0;\n    double memcostschex = 0;\n    double cpucosttet = 0;\n    double cpucostprism = 0;\n    double cpucosthex = 0;\n\n    for (i = 1; i <= elements.Size(); i++)\n      {\n\tconst HPRefElement & el = elements.Get(i);\n\tswitch (el.type)\n\t  {\n\t  case HP_TET:\n\t  case HP_TET_0E_1V:\n\t  case HP_TET_1E_0V:\n\t  case HP_TET_1E_1VA:\n\t    {\n\t      int p1 = maxlevel - el.level + 1;\n\t      (*testout) << \"p1 = \" << p1 << \", P1^6 = \" << pow (static_cast<double>(p1), 6.0)\n\t\t\t << \" (p1-3)^6 = \" << pow ( static_cast<double>(max2(p1-3, 0)), 6.0) \n\t\t\t << \" p1^3 = \" << pow ( static_cast<double>(p1), 3.0) \n\t\t\t << \" (p1-3)^3 = \" << pow ( static_cast<double>(p1-3), 3.0) \n\t\t\t << \" [p1^3-(p1-3)^3]^2 = \" << sqr (pow (static_cast<double>(p1),3.0) - pow ( static_cast<double>(p1-3), 3.0))\n\t\t\t << endl;\n\n\t      p1 /= 2 +1;\n\t      memcosttet += pow (static_cast<double>(p1), 6.0);\n\t      memcostsctet += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0);\n\t      cpucosttet += pow (static_cast<double>(p1), 9.0);\n\t      break;\n\t    }\n\t  case HP_PRISM:\n\t  case HP_PRISM_SINGEDGE:\n\t    {\n\t      int p1 = maxlevel - el.level + 1;\n\t      p1 /= 2 +1;\n\t      memcostprism += pow (static_cast<double>(p1), 6.0);\n\t      memcostscprism += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0);\n\t      cpucostprism += pow (static_cast<double>(p1), 9.0);\n\t      break;\n\t    }\n\t  case HP_HEX:\n\t    {\t\n\t      int p1 = maxlevel - el.level + 1;\n\t      int p2 = maxlevel;\n\t      p1 /= 2 +1;\n\t      p2 /= 2 +1;\n\t      memcosthex += pow (static_cast<double>(p1), 4.0) * pow (static_cast<double>(p2), 2.0);\n\t      memcostschex += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-2, 0)), 6.0);\n\t      cpucosthex += pow (static_cast<double>(p1), 6.0) * pow (static_cast<double>(p2), 3.0);\n\t      break;\n\t    }\n\t  default:\n\t    ;\n\t  }\n      }\n    cout << \"TET: hp-memcost = \" << memcosttet \n\t << \", scmemcost = \" << memcostsctet\n\t << \", cpucost = \" << cpucosttet\n\t << endl;\n    cout << \"PRI: hp-memcost = \" << memcostprism\n\t << \", scmemcost = \" << memcostscprism\n\t << \", cpucost = \" << cpucostprism << endl;\n    cout << \"HEX: hp-memcost = \" << memcosthex\n\t << \", scmemcost = \" << memcostschex\n\t << \", cpucost = \" << cpucosthex << endl;\n#endif\n  }\n\n\n\n  void ReorderPoints (Mesh & mesh, NgArray<HPRefElement> & hpelements)\n  {\n    NgArray<int, 1> map (mesh.GetNP());\n    \n    for (int i = 1; i <= mesh.GetNP(); i++)\n      map[i] = i;\n\n    int nwrong(0), nright(0);\n    for (int k = 0; k < 5; k++)\n      {\n        nwrong = nright = 0;\n        for (int i = 0; i < hpelements.Size(); i++)\n          {\n            const HPRefElement & hpel = hpelements[i];\n            \n            if (Get_HPRef_Struct (hpel.type) -> geom == HP_PRISM)\n              {\n                int minbot = 0, mintop = 0;\n                for (int j = 0; j < 3; j++)\n                  {\n                    if (map[hpel.pnums[j]] < map[hpel.pnums[minbot]]) minbot = j;\n                    if (map[hpel.pnums[j+3]] < map[hpel.pnums[mintop+3]]) mintop = j;\n                  }\n                if (minbot != mintop) \n                  nwrong++;\n                else\n                  nright++;\n                \n                if (minbot != mintop)\n                  {\n                    if (map[hpel.pnums[minbot]] < map[hpel.pnums[mintop+3]])\n                      swap (map[hpel.pnums[3+minbot]], map[hpel.pnums[3+mintop]]);\n                    else\n                      swap (map[hpel.pnums[minbot]], map[hpel.pnums[mintop]]);\n                  }\n              }\n          }\n        // cout << nwrong << \" wrong prisms, \" << nright << \" right prisms\" << endl;\n      }\n\n    PrintMessage(3, nwrong, \" wrong prisms, \",  nright, \" right prisms\");\n\n\n    NgArray<MeshPoint, 1> hpts(mesh.GetNP());\n\n    for (int i = 1; i <= mesh.GetNP(); i++)\n      hpts[map[i]] = mesh.Point(i);\n\n    for (int i = 1; i <= mesh.GetNP(); i++)\n      mesh.Point(i) = hpts[i];\n\n    for (int i = 0; i < hpelements.Size(); i++)\n      {\n        HPRefElement & hpel = hpelements[i];\n        for (int j = 0; j < hpel.np; j++)\n          hpel.pnums[j] = map[hpel.pnums[j]];\n      }\n  }\n\n\n\n  /* ***************************** HPRefinement ********************************** */\n\n  void HPRefinement (Mesh & mesh, Refinement * ref, SplittingType split,\n                     int levels, double fac1, bool setorders, bool reflevels)\n  {\n    PrintMessage (1, \"HP Refinement called, levels = \", levels);\n\n \n    // NgLock mem_lock (mem_mutex,1);\n\n    mesh.coarsemesh = make_unique<Mesh>(); \n    *mesh.coarsemesh = mesh;\n    \n    // #ifdef CURVEDELEMS_NEW\n    const_cast<CurvedElements&> (mesh.coarsemesh->GetCurvedElements() ).\n      BuildCurvedElements (ref, mesh.GetCurvedElements().GetOrder());\n    // #endif\n\n\n    // delete mesh.hpelements;\n    mesh.hpelements = make_unique<NgArray<HPRefElement>>();\n        \n    NgArray<HPRefElement> & hpelements = *mesh.hpelements; \n        \n    InitHPElements(mesh,hpelements); \n\n    NgArray<int> nplevel;\n    nplevel.Append (mesh.GetNP());\n    \n    int act_ref=1;\n    bool sing = ClassifyHPElements (mesh,hpelements, split, act_ref, levels); \n\n    sing = true; // iterate at least once\n    while(sing) \n      {\n\tPrintMessage(3, \" Start new hp-refinement: step \", act_ref);\n\t\t\n\tDoRefinement (mesh, hpelements, ref, fac1); \n\tDoRefineDummies (mesh, hpelements, ref);\n\t\n\tnplevel.Append (mesh.GetNP());\n\tCalcStatistics (hpelements);\n\t\n\tSubdivideDegeneratedHexes (mesh, hpelements,fac1);\n\n        ReorderPoints (mesh, hpelements);\n\n\tmesh.ClearSegments();\n\tmesh.ClearSurfaceElements();\n  \tmesh.ClearVolumeElements();\n\n\tfor (int i = 0; i < hpelements.Size(); i++)\n\t  {\n\t    HPRefElement & hpel = hpelements[i];\n\t    if (Get_HPRef_Struct (hpel.type))\n\t      switch (Get_HPRef_Struct (hpel.type) -> geom)\n\t\t{\n\t\tcase HP_SEGM:\n\t\t  {\n\t\t    Segment seg;\n\t\t    seg[0] = hpel.pnums[0];\n\t\t    seg[1] = hpel.pnums[1];\n\t\t    // NOTE: only for less than 10000 elements (HACK) !!!\n\t\t    // seg.edgenr = hpel.index % 10000;\n\t\t    // seg.si     = hpel.index / 10000;\n                    seg.SetEdgeNr (hpel.edgenr);\n                    seg.SetIndex (hpel.index);\n\n                    /*\n                    seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0]\n                    seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0]\n                    */\n                    \n                    const Segment & coarseseg = mesh.coarsemesh->LineSegment(hpel.coarse_elnr+1);\n                    double d1 = coarseseg.epgeominfo[0].dist;\n                    double d2 = coarseseg.epgeominfo[1].dist;\n\n                    // seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0]\n                    // seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0]\n\n                    seg.epgeominfo[0].dist = d1 + hpel.param[0][0] * (d2-d1); // JS, June 08\n                    seg.epgeominfo[1].dist = d1 + hpel.param[1][0] * (d2-d1); \n\n\n\t\t    seg.epgeominfo[0].edgenr = seg.edgenr;\n\t\t    seg.epgeominfo[1].edgenr = seg.edgenr;\n                    seg.domin = hpel.domin; seg.domout=hpel.domout; // he: needed for segments!\n\t\t    seg.hp_elnr = i;\n\t\t    seg.singedge_left = hpel.singedge_left; \n\t\t    seg.singedge_right = hpel.singedge_right;\n                    seg.SetCurved (coarseseg.IsCurved());\n\t\t    mesh.AddSegment (seg); \n\t\t    break;\n\t\t  }\n\t\t  \n\t\tcase HP_TRIG: \n\t\tcase HP_QUAD: \n\t\t  { \n\t\t    Element2d el(hpel.np); \n\t\t    for(int j=0;j<hpel.np;j++) \n\t\t      el.PNum(j+1) = hpel.pnums[j]; \n\t\t    el.SetHpElnr(i);\n\t\t    el.SetIndex(hpel.index);\n\t\t    if(setorders)\n\t\t      el.SetOrder(act_ref+1,act_ref+1,0); \n                    if((*mesh.coarsemesh)[SurfaceElementIndex{hpel.coarse_elnr}].IsCurved())\n                        el.SetCurved(true);\n\t\t    mesh.AddSurfaceElement(el);\n\t\t    break; \n\t\t  } \n\t\tcase HP_HEX:\n\t\tcase HP_HEX7:\n\t\tcase HP_TET:\n\t\tcase HP_PRISM:\n\t\tcase HP_PYRAMID:\n\t\t  { \n\t\t    Element el(hpel.np); \n\t\t    for(int j=0;j<hpel.np;j++) \n\t\t      el.PNum(j+1) = hpel.pnums[j]; \n\t\t    el.SetIndex(hpel.index); \n\t\t    el.SetHpElnr(i);\n\t\t    if(setorders)\n\t\t      el.SetOrder(act_ref+1,act_ref+1,act_ref+1);\n                    if((*mesh.coarsemesh)[ElementIndex{hpel.coarse_elnr}].IsCurved())\n                        el.SetCurved(true);\n\t\t    mesh.AddVolumeElement(el); \n\t\t    break;\n\t\t  } \n\t\t      \n\t\tdefault:\n\t\t  PrintSysError (\"hpref, backconversion failed for element \", \n\t\t\t\t int(Get_HPRef_Struct (hpel.type) -> geom));\n\t\t}\n\t  }\n\tPrintMessage(5, \" Start with Update Topology \");\n\tmesh.UpdateTopology();\n        // mesh.ComputeNVertices();\n\tPrintMessage(5, \" Mesh Update Topology done \");\n\n\tact_ref++; \n\t\n\tsing = ClassifyHPElements(mesh,hpelements, split, act_ref, levels); \n      }\n\n    PrintMessage(3, \" HP-Refinement done with \", --act_ref, \" refinement steps.\");\n\n    if(act_ref>=1)\n      { \n\t// for(ElementIndex i=0;i<mesh.GetNE(); i++)\n        for (ElementIndex i : mesh.VolumeElements().Range())\n\t  { \n\t    // Element el = mesh[i] ;\n\t    HPRefElement & hpel = hpelements[mesh[i].GetHpElnr()];\n\t    const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (mesh[i].GetType());\n\t    double dist[3] = {0,0,0}; \n\t    int ord_dir[3] = {0,0,0}; \n\t    int edge_dir[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; \n\t    int ned = 4; \n\t    \n\t    switch (mesh[i].GetType())\n\t      {\n\t      case TET: \n\t\t/* cout << \" TET \" ; \n\t\tfor(int k=0;k<4;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl; */ \n\t\tbreak; \n\t      case PRISM:\n\t\t/* cout << \" PRISM \" ; \n\t\tfor(int k=0;k<6;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl;  */ \n\t\tfor(int l=6;l<9;l++) edge_dir[l] = 2; \n\t\tord_dir[2] = 2; \n\t\tned = 9; \n\t\tbreak;\n\t      case HEX7:\n                // ????\n                break;\n\t      case HEX: \n\t\t/* cout << \" HEX \" ; \n\t\tfor(int k=0;k<8;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl; */\n\t\tfor(int l=8;l<12; l++) edge_dir[l] = 2; \n\t\tedge_dir[2] = edge_dir[3] = edge_dir[6] = edge_dir[7] = 1;\n\t\tord_dir[1] = 1; \n\t\tord_dir[2] = 2; \n\t\tned = 12; \n\t\tbreak;  \n\t      case PYRAMID: \n\t\t/*\tcout << \" PYRAMID \" ; \n\t\tfor(int k=0;k<5;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl; */ \n\t\tfor(int l=4;l<8;l++) edge_dir[l] = 2; \n\t\tedge_dir[2] = edge_dir[3] = 1; \n\t\tord_dir[1] = 1; \n\t\tord_dir[2] = 2; \n\t\tned = 8;  \n\t\tbreak; \n\n\n              default:\n                cerr << \"HPRefElement: illegal elementtype (2) \" << mesh[i].GetType() << endl;\n                throw NgException (\"HPRefElement: illegal elementtype (2)\");\n                \n\t      }\n\t\n\t    for (int j=0;j<ned;j++) \n\t      { \n\t\t\t\n\t\tVec<3> v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0],\n\t\t\t    hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1],\n\t\t\t    hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]);\n\t\tdist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]);\n\t      }\n\t    \n\t    int refi[3];  \n\t    for(int j=0;j<3;j++) \n\t      refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); \t\n\t    \n\t    // cout << \" ref \" << refi[0] << \"\\t\" << refi[1] << \"\\t\" << refi[2] << endl; \n\t    // cout << \" order \" << act_ref +1 - refi[0] << \"\\t\" << act_ref +1 - refi[1] << \"\\t\" << act_ref +1 - refi[2] << endl; \n\t   \t      \n\t    if(setorders)\n\t      mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); \n\t  }\n\tfor(SurfaceElementIndex i=0;i<mesh.GetNSE(); i++) \n\t  { \n\t    // Element2d el = mesh[i] ;\n\t    HPRefElement & hpel = hpelements[mesh[i].GetHpElnr()];\n\t    const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (mesh[i].GetType());\n\t    double dist[3] = {0,0,0}; \n\t    int ord_dir[3] = {0,0,0}; \n\t    int  edge_dir[4] = {0,0,0,0} ; \n\t    int ned = 3; \n\t   \n\t    if(mesh[i].GetType() == QUAD)\n\t      {\n\t\t/*\tcout << \" QUAD \" ; \n\t\tfor(int k=0;k<4;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl; \t*/ \n \n\t\tedge_dir[2] = edge_dir[3] = 1; \n\t\tord_dir[1] = 1; \n\t\tned = 4; \n\t      }\n\t    /*  else \n\t      { \n\t\tcout << \" TRIG \" ; \n\t\tfor(int k=0;k<3;k++) cout << el[k] << \"\\t\" ; \n\t\tcout << endl; \n\t\t} */ \n\t    \n\t    for (int j=0;j<ned;j++) \n\t      { \n\t\tVec<3> v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0],\n\t\t\t    hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1],\n\t\t\t    hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]);\n\t\tdist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]);\n\t      }\n\t    \n\t    int refi[3]; \n\t    for(int j=0;j<3;j++) \n\t      refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); \t\n\t    \n\t    if(setorders)\n\t      mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); \n\n\t      // cout << \" ref \" << refi[0] << \"\\t\" << refi[1] << endl; \n\t      // cout << \" order \" << act_ref +1 - refi[0] << \"\\t\" << act_ref +1 - refi[1] << endl; \n\t  }\n      }\n  }\n\n  template <typename HT_EDGEPOINT_DOM>\n  bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom, \n\t\t       TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, \n\t\t\tINDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int & levels, int & act_ref)\n{\n  bool sing = 0; \n  if (mesh.GetDimension() == 3)\n    {\n\t/*\n\t// check, if point has as least 3 different surfs:\n\n\tNgArray<INDEX_3, PointIndex::BASE> surfonpoint(mesh.GetNP());\n  \tsurfonpoint = INDEX_3(0,0,0);\n\n\tfor (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t  {\n\t    const Element2d & el = mesh[sei];\n\t    int ind = el.GetIndex();\n\t    for (int j = 0; j < el.GetNP(); j++)\n\t      {\n\t\tINDEX_3 & i3 = surfonpoint[el[j]];\n\t\tif (ind != i3.I1() && ind != i3.I2() && ind != i3.I3())\n\t\t  {\n\t\t    i3.I1() = i3.I2();\n\t\t    i3.I2() = i3.I3();\n\t\t    i3.I3() = ind;\n\t\t  }\n\t      }\n\t  }\n\tfor (int i = 1; i <= mesh.GetNP(); i++)\n\t  if (surfonpoint.Get(i).I1())\n\t    cornerpoint.Set(i);\n\t*/\n\tcornerpoint.Clear();\n\t\n\tfor (int i = 1; i <= mesh.GetNP(); i++)\n\t  {\n\t    if (mesh.Point(i).Singularity() * levels >= act_ref)\n\t      {\n\t\tcornerpoint.SetBit(i);\n\t\tsing = 1; \n\t      } \n\t  }\n\t// cout << endl; \n\n\tfor (int i = 1; i <= mesh.GetNSeg(); i++)\n\t  if (mesh.LineSegment(i).singedge_left * levels >= act_ref)\n\t    {\n\t      INDEX_2 i2 (mesh.LineSegment(i)[0], \n\t\t\t  mesh.LineSegment(i)[1]);\n\n\t      /*\n\t\t// before\n\t      edges.Set (i2, 1);\n\t      i2.Sort();   \n\t      INDEX_2 i2s(i2.I2(), i2.I1());\n\t      edges.Set (i2s, 1);\n\t      */\n\n\t      edges.Set (i2, 1);\n\t      INDEX_2 i2s(i2.I2(), i2.I1());\n\t      edges.Set (i2s, 1);\n\n\n\t      edgepoint.SetBit (i2.I1());\n\t      edgepoint.SetBit (i2.I2());\n\t      sing = 1; \n\t    }\n\n\t// if 2 adjacent edges of an element are singular, the \n\t// common point must be a singular point\n\t// for (int i = 1; i <= mesh.GetNE(); i++)\n        for (auto ei : mesh.VolumeElements().Range())\n\t  {\n\t    const Element & el = mesh[ei]; \n\t    const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (el.GetType());\n\t    int nedges = MeshTopology::GetNEdges (el.GetType());\n\t    for (int j = 0; j < nedges; j++)\n\t      for (int k = 0; k < nedges; k++)\n\t\tif (j != k)\n\t\t  {\n\t\t    INDEX_2 ej(el.PNum(eledges[j][0]), el.PNum(eledges[j][1]));\n\t\t    ej.Sort();\n\t\t    INDEX_2 ek(el.PNum(eledges[k][0]), el.PNum(eledges[k][1]));\n\t\t    ek.Sort();\n\t\t    if (edges.Used(ej) && edges.Used(ek))\n\t\t      {\n\t\t\tif (ej.I1() == ek.I1()) cornerpoint.SetBit (ek.I1());\n\t\t\tif (ej.I1() == ek.I2()) cornerpoint.SetBit (ek.I2());\n\t\t\tif (ej.I2() == ek.I1()) cornerpoint.SetBit (ek.I1());\n\t\t\tif (ej.I2() == ek.I2()) cornerpoint.SetBit (ek.I2());\n\t\t      }\n\t\t  }\n\t  }\n\n\tedgepoint.Or (cornerpoint);\n\t(*testout) << \"cornerpoint = \" << endl << cornerpoint << endl;\n\t(*testout) << \"edgepoint = \" << endl << edgepoint << endl;\n\n\tfacepoint = 0;\n\tfor (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t  {\n\t    const Element2d & el = mesh[sei];\n\t    const FaceDescriptor & fd = mesh.GetFaceDescriptor (el.GetIndex());\n\t  \n\t    int domnr = 0;\n\t    if (fd.DomainInSingular() * levels < act_ref && fd.DomainOutSingular() * levels < act_ref) \n\t      { domnr=0;  continue;}\n\t    \n\t    if (fd.DomainInSingular() * levels >= act_ref) \n\t      {\n\t\tdomnr = fd.DomainIn();\n\t\tsing = 1;\n\t      }\n\t    if (fd.DomainOutSingular() * levels >= act_ref)\n\t      {\n\t\tdomnr = fd.DomainOut();\n\t\tsing = 1; \n\t      } \n\t    if (fd.DomainInSingular() * levels >= act_ref \n\t\t&& fd.DomainOutSingular() * levels >= act_ref) \n\t      {\n\t\tdomnr = -1;\n\t\tsing = 1;\n\t      } \n  \n\t    INDEX_3 i3;\n\t    if (el.GetNP() == 3) \n\t      i3 = INDEX_3::Sort (el[0], el[1], el[2]);\n\t    else\n\t      {\n\t\tINDEX_4 i4 (el[0], el[1], el[2], el[3]);\n\t\ti4.Sort();\n\t\ti3 = INDEX_3(i4.I1(), i4.I2(), i4.I3());\n\t      }\n\t    faces.Set (i3, domnr);\n            *testout << \"set face \" << i3 << \", domnr = \" << domnr << endl;\n\t\n\t    for (int j = 0; j < el.GetNP(); j++)\n\t      {\n\t\tface_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), domnr);\n\t\n\t\tsurf_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), fd.SurfNr()+1);\n\t\t\n\t\tfacepoint[el[j]] = domnr;\n\t      }\n\t   \n\t  }\n\t// (*testout) << \"singular edges = \" << edges << endl;        \n\t// (*testout) << \"singular faces = \" << faces << endl;\n\t// (*testout) << \"singular faces_edges = \" << face_edges << endl;\n      }\n    else\n      {\n\t// 2D case\n\n\t// check, if point has as least 3 different surfs:\n\tNgArray<INDEX_3, PointIndex::BASE> surfonpoint(mesh.GetNP());\n\n\tfor (int i = 1; i <= mesh.GetNP(); i++)\n\t  surfonpoint.Elem(i) = INDEX_3(0,0,0);\n\t\n\tfor (int i = 1; i <= mesh.GetNSeg(); i++)\n\t  {\n\t    const Segment & seg = mesh.LineSegment(i);\n\t    int ind = seg.edgenr;\n\t    \n\t    if (seg.singedge_left * levels >= act_ref)\n\t      {\n\t\tINDEX_2 i2 = INDEX_2::Sort(mesh.LineSegment(i)[0], \n                                           mesh.LineSegment(i)[1]);\n\t\tedges.Set(i2,1); \n\t\tedgepoint.SetBit(i2.I1());\n\t\tedgepoint.SetBit(i2.I2());\n\t\t*testout << \" singleft \" << endl;  \n\t\t*testout << \" mesh.LineSegment(i).domout \" << mesh.LineSegment(i).domout << endl;      \n\t\t*testout << \" mesh.LineSegment(i).domin \" << mesh.LineSegment(i).domin << endl;      \n\t\tedgepoint_dom.Set ( { mesh.LineSegment(i).domin, i2.I1() }, 1);\n\t\tedgepoint_dom.Set ( { mesh.LineSegment(i).domin, i2.I2() }, 1);\n\t\tsing = 1; \n\t\t\n\t      }\n\t    \n\t    if (seg.singedge_right * levels >= act_ref)\n\t      {\n\t\tPointIndices<2> i2 = INDEX_2::Sort(mesh.LineSegment(i)[1], \n                                                   mesh.LineSegment(i)[0]);  \n\t\tedges.Set (i2, 1);\n\t\tedgepoint.SetBit(i2.I1());\n\t\tedgepoint.SetBit(i2.I2());\n\t\t\n\t\t*testout << \" singright \" << endl;  \n\t\t*testout << \" mesh.LineSegment(i).domout \" << mesh.LineSegment(i).domout << endl;      \n\t\t*testout << \" mesh.LineSegment(i).domin \" << mesh.LineSegment(i).domin << endl;      \n\t\t\n\t\tedgepoint_dom.Set ( { mesh.LineSegment(i).domout, i2.I1() }, 1);\n\t\tedgepoint_dom.Set ( { mesh.LineSegment(i).domout, i2.I2() }, 1);\n\t\tsing = 1;\n\t      }\n\t    \n\t    // (*testout) << \"seg = \" << ind << \", \" << seg[0] << \"-\" << seg[1] << endl;\n\t    \n\n\t    if (seg.singedge_left * levels >= act_ref\n\t\t|| seg.singedge_right* levels >= act_ref)\n\t      {\n\t\tfor (int j = 0; j < 2; j++)\n\t\t  {\n\t\t    int pi = (j == 0) ? seg[0] : seg[1];\n\t\t    INDEX_3 & i3 = surfonpoint.Elem(pi);\n\t\t    if (ind != i3.I1() &&\n\t\t\tind != i3.I2())\n\t\t      {\n\t\t\ti3.I1() = i3.I2();\n\t\t\ti3.I2() = ind;\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\n\n\tfor (int i = 1; i <= mesh.GetNP(); i++)\n\t  {\n\t    // mark points for refinement that are in corners between two anisotropic edges \n\t    if (surfonpoint.Get(i).I1())\n\t      {\n\t\t// cornerpoint.Set(i);    // disabled by JS, Aug 2009\n\t\tedgepoint.SetBit(i);\n\t      }\n\t\n\t    // mark points for refinement that are explicitly specified in input file\n\t    if (mesh.Point(i).Singularity()*levels >= act_ref)\n\t      {\n\t\tcornerpoint.SetBit(i);\n\t\tedgepoint.SetBit(i);\n\t\tsing =  1; \n\t      }\n\t  }\n\n\tedgepoint.Or (cornerpoint);\n\n\t(*testout) << \"2d sing edges: \" << endl << edges << endl;\n\t(*testout) << \"2d cornerpoints: \" << endl << cornerpoint << endl\n\t\t   << \"2d edgepoints: \" << endl << edgepoint << endl;\n\t\n\tfacepoint = 0;\n      }\n\n    if (!sing)\n      PrintMessage(3, \"PrepareElements no more to do for actual refinement \", act_ref);\n\n    return(sing); \n}\n\n\n\n  bool ClassifyHPElements (Mesh & mesh, NgArray<HPRefElement> & elements, SplittingType split, int & act_ref, int & levels)\n  {\n    INDEX_2_HASHTABLE<int> edges(mesh.GetNSeg()+1);\n    TBitArray<PointIndex> edgepoint(mesh.GetNP());\n    // INDEX_2_HASHTABLE<int> edgepoint_dom(mesh.GetNSeg()+1);\n\n    HT_EDGEPOINT_DOM edgepoint_dom;\n    \n    edgepoint.Clear();\n    TBitArray<PointIndex> cornerpoint(mesh.GetNP());\n    cornerpoint.Clear();\n\n    // value = nr > 0 ... refine elements in domain nr\n    // value = -1   ..... refine elements in any domain\n    INDEX_3_HASHTABLE<int> faces(mesh.GetNSE()+1);\n    INDEX_2_HASHTABLE<int> face_edges(mesh.GetNSE()+1);\n    INDEX_2_HASHTABLE<int> surf_edges(mesh.GetNSE()+1);\n    Array<int, PointIndex> facepoint(mesh.GetNP());\n\n    bool sing = CheckSingularities(mesh, edges, edgepoint_dom, \n\t\t\t      cornerpoint, edgepoint, faces, face_edges, \n\t\t\t      surf_edges, facepoint, levels, act_ref);\n\n    if (act_ref == 1 && split == SPLIT_ALFELD)\n      sing = true;   \n    if (act_ref == 1 && split == SPLIT_POWELL)\n      sing = true;   \n    if(sing==0) return(sing); \n\n    int cnt_undef = 0, cnt_nonimplement = 0;\n    NgArray<int> misses(10000);\n    misses = 0;\n\n    // (*testout) << \"edgepoint_dom = \" << endl << edgepoint_dom << endl;\n\n    \n    for( int i = 0; i<elements.Size(); i++) \n      {\n\tHPRefElement & hpel = elements[i]; \n\tHPRef_Struct * hprs = Get_HPRef_Struct (hpel.type);\n\tHPRefElement old_el = elements[i]; \n\tint dd=3; \n\n\tif(act_ref !=1 && (hpel.type == HP_HEX || hpel.type == HP_PRISM || hpel.type == HP_TET \n\t\t\t   || hpel.type == HP_PYRAMID || hpel.type == HP_QUAD || hpel.type == HP_TRIG || hpel.type == HP_SEGM)) \n\t  continue; \n\t\n\tsing = 1;\n\tswitch (hprs->geom)\n\t  {\n\t  case HP_TET:\n\t    {\n\t      hpel.type = ClassifyTet(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,face_edges, surf_edges, facepoint);\n              /*\n              // if (i != 182)\n              if ( (!hpel.PNums().Contains(40)) || (!hpel.PNums().Contains(41))  )\n                hpel.type = HP_NONETET;\n              else\n                cout << \"type = \" << hpel.type << endl;\n              */\n              if (split == SPLIT_ALFELD && mesh.GetDimension()==3)\n                hpel.type = HP_TET_ALFELD;\n\n\t      break;\n\t    }\n\t  case HP_PRISM:\n\t    {\n\t      hpel.type = ClassifyPrism(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,\n\t\t\t\t\tface_edges, surf_edges, facepoint); \t    \t    \n\t \n\t    \n\t      break;\n\t    }\n\t  case HP_HEX7:\n\t    { \n\t      hpel.type = ClassifyHex7(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,\n                                       face_edges, surf_edges, facepoint); \t    \t    \n\t      break; \n\t    } \n\t  case HP_HEX:\n\t    { \n\t      hpel.type = ClassifyHex(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,\n                                      face_edges, surf_edges, facepoint); \t    \t    \n\t      break; \n\t    } \n\t  case HP_TRIG: \n\t    {\n\t      int dim = mesh.GetDimension(); \n\t      const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex());\n\n              if (split == SPLIT_HP)\n                hpel.type = ClassifyTrig(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, \n                                         faces, face_edges, surf_edges, facepoint, dim, fd);    \n              else if (split == SPLIT_ALFELD && mesh.GetDimension()==2)\n                hpel.type = HP_TRIG_ALFELD;\n              else if (split == SPLIT_POWELL && mesh.GetDimension()==2)\n                hpel.type = HP_TRIG_POWELL;\n\n\t      dd = 2;\n\t      break; \n\t    } \n\t  case HP_QUAD: \n\t    { \n\t      int dim = mesh.GetDimension(); \n\t      const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex());\n\t      hpel.type = ClassifyQuad(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, \n\t\t\t\t  faces, face_edges, surf_edges, facepoint, dim, fd);    \n\t      dd = 2; \n\t      break; \n\t    }\n\t  case HP_SEGM: \n\t    {\n              if (split == SPLIT_HP)\n                hpel.type = ClassifySegm(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, \n                                         faces, face_edges, surf_edges, facepoint);\n              else if (split == SPLIT_POWELL)\n                hpel.type = HP_SEGM_SINGCORNERL;\n\t      dd = 1; \n\t      break; \n\t    }\n\t  case HP_PYRAMID: \n\t    {\n\t      hpel.type = ClassifyPyramid(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,\n\t\t\t\t\t\t  face_edges, surf_edges, facepoint); \t    \t    \n\t      break; \n\t    }\n\t  default:\n\t    {\n\t      cout << \"illegal element type for hp-prepare elements \" << hpel.type << endl;\n\t      throw NgException (\"hprefinement.cpp: don't know how to set parameters\");\n\t    }\n\t  }\n\n\tif(hpel.type == HP_NONE) \n\t  cnt_undef++; \n\n\t//else \n\t//cout << \"elem \" << i << \" classified type \" << hpel.type << endl; \n\n\tif (!Get_HPRef_Struct (hpel.type)) \n\t  {\n\t    (*testout) << \"hp-element-type \" << hpel.type << \" not implemented   \" << endl;\n\t    (*testout) << \" elType \" << hprs->geom << endl; \n (cout) << \" elType \" << hprs->geom << endl;        \n\t    cnt_nonimplement++;\n\t    misses[hpel.type]++;\n\t  }\n\t\n  \n\tfor(int j=0; j<hpel.np; j++)\n\t  {\n\t    for( int k=0; k<hpel.np; k++) \n\t      if(hpel[j] == old_el.pnums[k]) \n\t\t{ \n\t\t  for(int l=0;l<dd;l++) \n\t\t    hpel.param[j][l] = old_el.param[k][l];\n\t\t  break;\n\t\t}\n\t  } \n\n      }\n\n    PrintMessage(3, \"undefined elements update classification: \", cnt_undef);\n    PrintMessage(3, \"non-implemented in update classification: \", cnt_nonimplement);\n    \n    for (int i = 0; i < misses.Size(); i++)\n      if (misses[i])\n\tcout << \" in update classification missing case \" << i << \" occurred \" << misses[i] << \" times\" << endl;\n    return(sing); \n  }\n}\n  \n"
  },
  {
    "path": "libsrc/meshing/hprefinement.hpp",
    "content": "#ifndef FILE_HPREFINEMENT\n#define FILE_HPREFINEMENT\n\n/**************************************************************************/\n/* File:   hprefinement.hh                                                */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   27. Oct. 2000                                                  */\n/**************************************************************************/\n\n/*\n  HP Refinement\n*/\n\n#include \"bisect.hpp\"\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n\n\nenum HPREF_ELEMENT_TYPE {\n  HP_NONE=0,\n\n  HP_SEGM = 1,\n  HP_SEGM_SINGCORNERL,\n  HP_SEGM_SINGCORNERR,\n  HP_SEGM_SINGCORNERS,\n\n  HP_TRIG = 10,\n  HP_TRIG_SINGCORNER,\n  HP_TRIG_SINGCORNER12,\n  HP_TRIG_SINGCORNER123,\n  HP_TRIG_SINGCORNER123_2D,   // not rotational symmetric\n  HP_TRIG_SINGEDGE = 20,\n  HP_TRIG_SINGEDGECORNER1,   // E = 100, V = 100\n  HP_TRIG_SINGEDGECORNER2,   // E = 100, V = 010\n  HP_TRIG_SINGEDGECORNER12,  // E = 100, V = 110\n  HP_TRIG_SINGEDGECORNER3,\n  HP_TRIG_SINGEDGECORNER13,\n  HP_TRIG_SINGEDGECORNER23,\n  HP_TRIG_SINGEDGECORNER123,\n  HP_TRIG_SINGEDGES = 30,\n  HP_TRIG_SINGEDGES2,\n  HP_TRIG_SINGEDGES3,\n  HP_TRIG_SINGEDGES23,\n  HP_TRIG_3SINGEDGES = 40,\n\n  HP_TRIG_ALFELD,\n  HP_TRIG_POWELL,\n  \n  HP_QUAD = 50,\n  HP_QUAD_SINGCORNER,\n  HP_DUMMY_QUAD_SINGCORNER,\n  HP_QUAD_SINGEDGE,\n  HP_QUAD_0E_2VA,  // V = 1100\n  HP_QUAD_0E_2VB,  // V = 1010\n  HP_QUAD_0E_3V,\n  HP_QUAD_0E_4V,\n\n  // one edge: marked edge is always edge from vertex 1 to vertex 2 (E = 1000)\n  HP_QUAD_1E_1VA,  // vertex on beginning of edge: V = 1000\n  HP_QUAD_1E_1VB,  // vertex on end of edge: V = 0100\n  HP_QUAD_1E_1VC,  // V = 0010\n  HP_QUAD_1E_1VD,  // V = 0001\n\n  HP_QUAD_1E_2VA,  // V = 1100\n  HP_QUAD_1E_2VB,  // V = 1010\n  HP_QUAD_1E_2VC,  // V = 1001\n  HP_QUAD_1E_2VD,  // V = 0110\n  HP_QUAD_1E_2VE,  // V = 0101\n  HP_QUAD_1E_2VF,  // V = 0011\n\n  HP_QUAD_1E_3VA,  // V = 1110\n  HP_QUAD_1E_3VB,  // V = 1101\n  HP_QUAD_1E_3VC,  // V = 1011\n  HP_QUAD_1E_3VD,  // V = 0111\n\n  HP_QUAD_1E_4V,   // V = 1111\n\n\n  HP_QUAD_2E,      // E = 1001, V = 1000\n  HP_QUAD_2E_1VA,  // E = 1001, V = 1100\n  HP_QUAD_2E_1VB,  // E = 1001, V = 1010\n  HP_QUAD_2E_1VC,  // E = 1001, V = 1001\n  HP_QUAD_2E_2VA,  // E = 1001, V = 1110\n  HP_QUAD_2E_2VB,  // E = 1001, V = 1101\n  HP_QUAD_2E_2VC,  // E = 1001, V = 1011\n  HP_QUAD_2E_3V,   // E = 1001, V = 1111\n\n  HP_QUAD_2EB_0V,   // E = 1010, V = 0000\n  HP_QUAD_2EB_1VA,  // E = 1010, V = 1000\n  HP_QUAD_2EB_1VB,  // E = 1010, V = 0100\n  HP_QUAD_2EB_2VA,  // E = 1010, V = 1100\n  HP_QUAD_2EB_2VB,  // E = 1010, V = 1010\n  HP_QUAD_2EB_2VC,  // E = 1010, V = 1001\n  HP_QUAD_2EB_2VD,  // E = 1010, V = 0101\n  HP_QUAD_2EB_3VA,  // E = 1010, V = 1110\n  HP_QUAD_2EB_3VB,  // E = 1010, V = 1101\n\n  HP_QUAD_2EB_4V,\n\n\n  HP_QUAD_3E,      // E = 1101, V = 1100\n  HP_QUAD_3E_3VA,  // E = 1101, V = 1110\n  HP_QUAD_3E_3VB,  // E = 1101, V = 1101\n  HP_QUAD_3E_4V,   // E = 1101, V = 1111\n\n  HP_QUAD_4E,\n\n\n  HP_TET = 100,     // no singular vertex/edge\n  HP_NONETET,       // make void\n  HP_TET_0E_1V,     // V1\n  HP_TET_0E_2V,     // V1,2\n  HP_TET_0E_3V,     // V1,2,3  \n  HP_TET_0E_4V,     // V1,2,3,4\n  HP_TET_1E_0V = 200,   // E1-2\n  HP_TET_1E_1VA,    // V1\n  HP_TET_1E_1VB,    // V3\n  HP_TET_1E_2VA,    // V1,2\n  HP_TET_1E_2VB,    // V1,3\n  HP_TET_1E_2VC,    // V1,4\n  HP_TET_1E_2VD,    // V3,4\n  HP_TET_1E_3VA,    // V1,2,3\n  HP_TET_1E_3VB,    // V1,3,4\n  HP_TET_1E_4V,     // V1,2,3,4\n\n\n  // 2 connected edges, additionally marked Vs\n  HP_TET_2EA_0V = 220,    // E1-2, E1-3\n  HP_TET_2EA_1VA,   // V2\n  HP_TET_2EA_1VB,   // V3\n  HP_TET_2EA_1VC,   // V4\n  HP_TET_2EA_2VA,   // V2,3\n  HP_TET_2EA_2VB,   // V2,4\n  HP_TET_2EA_2VC,   // V3,4\n  HP_TET_2EA_3V,    // V2,3,4\n\n  // 2 opposite edges\n  HP_TET_2EB_0V = 230,    // E1-2, E3-4\n  HP_TET_2EB_1V,    // V1\n  HP_TET_2EB_2VA,   // V1,2\n  HP_TET_2EB_2VB,   // V1,3\n  HP_TET_2EB_2VC,   // V1,4\n  HP_TET_2EB_3V,    // V1,2,3\n  HP_TET_2EB_4V,    // V1,2,3,4\n\n  HP_TET_3EA_0V = 400,  // E1-2, E1-3, E1-4, 3 edges connected\n  HP_TET_3EA_1V,        // V2\n  HP_TET_3EA_2V,        // V2,3\n  HP_TET_3EA_3V,        // V2,3,4\n\n  HP_TET_3EB_0V = 420,  // E1-2, E1-4, E2-3  3 edges chain\n  HP_TET_3EB_1V,        // \n  HP_TET_3EB_2V,        // \n  HP_TET_3EC_0V = 430,  // 3 edges chain, alter\n  HP_TET_3EC_1V,        // 3 edges chain, alter\n  HP_TET_3EC_2V,        // 3 edges chain, alter\n  HP_TET_3ED_3V,        // 3 edges in a loop  e12, e13, e23     NEW .. done\n\n\n  HP_TET_1F_0E_0V = 500,  // 1 singular face\n  HP_TET_1F_0E_1VA,       // 1 sing vertex in face (V2)          FIX ... (needs HEX7)\n  HP_TET_1F_0E_1VB,       // 1 sing vertex not in face (V1)\n  HP_TET_1F_0E_2V,        // 2 sing vertex in face (V2,V3)       NEW .. done\n  HP_TET_1F_0E_3V,        // 3 sing vertex in face (V2,V3,V4)    NEWNEW \n  HP_TET_1F_1EA_0V,       // 1 sing edge not in face\n  HP_TET_1F_1EB_0V,       // 1 sing edge in face\n  HP_TET_1F_1E_1VA,       // 1 sing edge in face e23, sing vert 2        NEW  done\n  HP_TET_1F_1E_1VB,       // 1 sing edge in face e24, sing vert 2        NEW  done\n  HP_TET_1F_1E_2VA,      //  1 sing edge not in face (e12), sing v2,v3      NEW  done\n  HP_TET_1F_1E_2VB,       // 1 sing edge not in face (e12), sing v2,v4      NEW  done\n  HP_TET_1F_1E_2VC,       // 1 sing edge not in face (e12), sing v3,v4      NEW\n  HP_TET_1F_1EA_3V,        // 1 sing edge out of face e12, sing v2, v3, v4    NEWNEW   WIP, need Pyramid with 1 sing trig-face\n  HP_TET_1F_1E_3V,        // 1 sing edge in face e23, sing v2, v3, v4       NEWNEW  done\n  HP_TET_1F_2Eoo_3V,      // 2e out of face: f234, e12, e13, v1,v2,v3       NEWNEW\n  HP_TET_1F_2E_0VA,       // edge6 && fedge3  .. 1 in face, 1 not in face    NEW done\n  HP_TET_1F_2E_0VB,       // edge6 && fedge2  .. 1 in face, 1 not in face    NEW done\n  HP_TET_1F_2E_1V,        // e4,e5 (E23,E24), V2                            NEW NEW         WIP\n  HP_TET_1F_2E_3V,        // e4,e5 (E23,E24), V2,V3,V4                     NEW NEW  done\n\n  HP_TET_2F_0E_0V = 600,  // 2 singular faces\n  HP_TET_2F_0E_1V,      // 2 singular faces f234, f134, sing point V4     NEW\n  HP_TET_2F_1E_0VA,  // 2 singular faces, sing edge e4               NEW  done \n  HP_TET_2F_1E_0VB,  // 2 singular faces, sing edge e5               NEW  done\n\n  HP_TET_2F_1E_3VA,  // 2 singular faces f234,f134, e23, v2,v3,v4        NEW3\n  HP_TET_2F_1E_4VA,  // 2 singular faces f234,f134, e23, v2,v3,v4        NEW3  \n  \n  HP_TET_3F_0E_0V = 700,  // 3 singular faces, no additional points or edges  NEW   done \n\n  HP_TET_ALFELD,\n  \n  HP_PRISM = 1000,\n  HP_PRISM_SINGEDGE,\n  HP_PRISM_SINGEDGE_V12,\n  HP_PRISM_SINGEDGE_H1,\n  HP_PRISM_SINGEDGE_H12,\n\n  HP_PRISM_1FA_0E_0V,     // 1 singular trig face\n  HP_PRISM_2FA_0E_0V,     // 2 singular trig faces\n  HP_PRISM_1FB_0E_0V,     // 1 singular quad face  1-2-4-5\n\n  HP_PRISM_1FB_1EA_0V,     // 1 singular quad face, edge is 1-4\n  HP_PRISM_1FA_1E_0V,       \n  HP_PRISM_2FA_1E_0V, \n  HP_PRISM_1FA_1FB_0E_0V, \n  HP_PRISM_2FA_1FB_0E_0V,\n  HP_PRISM_1FA_1FB_1EA_0V, \n  HP_PRISM_1FA_1FB_1EB_0V, \n  HP_PRISM_2FA_1FB_1EA_0V,\n  HP_PRISM_1FB_1EC_0V, \n  HP_PRISM_1FA_1FB_1EC_0V, \n  HP_PRISM_2FA_1FB_1EC_0V,\n  HP_PRISM_1FB_2EA_0V, \n  HP_PRISM_1FA_1FB_2EA_0V, \n  HP_PRISM_2FA_1FB_2EA_0V,\n  HP_PRISM_1FB_2EB_0V,\n  HP_PRISM_1FA_1FB_2EB_0V,  \n  HP_PRISM_1FA_1FB_2EC_0V, \n  HP_PRISM_2FA_1FB_2EB_0V, \n  HP_PRISM_1FB_3E_0V, \n  HP_PRISM_1FA_1FB_3E_0V, \n  HP_PRISM_2FA_1FB_3E_0V, \n  HP_PRISM_2FB_0E_0V, \n  HP_PRISM_1FA_2FB_0E_0V, \n  HP_PRISM_2FA_2FB_0E_0V,\n  HP_PRISM_2FB_1EC_0V, \n  HP_PRISM_1FA_2FB_1EC_0V,\n  HP_PRISM_1FA_2FB_1EB_0V,\n  HP_PRISM_2FA_2FB_1EC_0V,\n  HP_PRISM_2FB_3E_0V, \n  HP_PRISM_1FA_2FB_3E_0V, \n  HP_PRISM_2FA_2FB_3E_0V, \n  HP_PRISM_1FA_2E_0V, \n  HP_PRISM_2FA_2E_0V,\n  HP_PRISM_3E_0V, \n  HP_PRISM_1FA_3E_0V, \n  HP_PRISM_2FA_3E_0V,  \n  HP_PRISM_3FB_0V, \n  HP_PRISM_1FA_3FB_0V, \n  HP_PRISM_2FA_3FB_0V,  \n  HP_PRISM_3E_4EH,\n  \n \n\n  /*  HP_PRISM_1FB_1EA_0V,     // 1 singular quad face, edge is 1-4\n  HP_PRISM_1FB_1EB_0V,     // 1 singular quad face, edge is 2-5\n  HP_PRISM_2F_0E_0V,      // 2 singular quad faces\n  */\n\n  HP_PYRAMID = 2000,\n  HP_PYRAMID_0E_1V,\n  HP_PYRAMID_EDGES,\n  HP_PYRAMID_1FB_0E_0V,   // 1 trig face F125\n  HP_PYRAMID_1FB_0E_1VA,  // 1 trig face, top vertex\n\n  HP_HEX = 3000,\n  HP_HEX_0E_1V,\n  HP_HEX_1E_1V,\n  HP_HEX_1E_0V,\n  HP_HEX_3E_0V,\n  HP_HEX_1F_0E_0V,\n  HP_HEX_1FA_1FB_0E_0V,\n\n  HP_HEX7 = 3100,\n  HP_HEX7_1FA,      // singular quad face 1,2,3,4\n  HP_HEX7_1FB       // singular trig face 5,6,7\n};\n\n\n\nstruct HPRef_Struct {\n  HPREF_ELEMENT_TYPE geom;\n  int (*splitedges)[3];\n  int (*splitfaces)[4];\n  int (*splitelements)[5];\n  HPREF_ELEMENT_TYPE * neweltypes;\n  int (*newels)[8];\n};\n\n\n\n\nclass HPRefElement\n{\nprivate:\n  void Reset(void);\n\npublic:\n  HPRefElement (); \n  HPRefElement(Element & el);\n  HPRefElement(Element2d & el);\n  HPRefElement(Segment & el);\t\n  HPRefElement(HPRefElement & el);\n\n  void SetType( HPREF_ELEMENT_TYPE t);\n  // HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t); \n\t       \n  /* HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t)\n  { \n    type = t; \n    HPRef_Struct * hprs = Get_HPRef_Struct(t);\n    for (int i=0; i<np ; i++) \n      {\n\tpnums[i] = el[i];\n\tfor(int l=0; l<np; l++) param[i][l] = el.param[i][l]; \n      }\n    switch(hprs->geom)\n      {\n      case HP_SEGM: np=2; sing_edge_left=0; sing_edge_right=0; break; \n      case HP_QUAD: np=4; break; \n      case HP_TRIG: np=3; break; \n      case HP_HEX: np=8; break; \n      case HP_PRISM: np=6; break;\n      case HP_TET: np=4; break; \n      case HP_PYRAMID: np=5; break; \n      }\n    index = el.index; \n    levelx = el.levelx; \n    levely = el.levely; \n    levelz = el.levelz; \n    type = el.type; \n    coarse_elnr = el.coarse_elnr;\n    singedge_left = el.singedge_left; \n    singedge_right = el.singedge_left; \n    } */ \n  \n  HPREF_ELEMENT_TYPE type;\n  PointIndex pnums[8];\n  double param[8][3];\n  int index;\n  // int si;\n  int edgenr;\n  int levelx;\n  int levely;\n  int levelz;\n  int np; \n  int coarse_elnr;  // issue (JS): same class is for ElementIndex, SurfaceElementIndex, SegmentIndex \n  int domin, domout; // he: needed for segment!! in 3d there should be surf1, surf2!!\n  // int coarse_hpelnr; \n  PointIndex & operator[](int i) { return(pnums[i]);}\n  PointIndex & PNumMod(int i) { return pnums[(i-1) % np]; };\n  PointIndex & PNum(int i) {return pnums[(i-1)]; };\n  int GetIndex () const { return index; }; \n  double singedge_left, singedge_right; \n  auto PNums() const { return FlatArray<const PointIndex>(np, &pnums[0]); }\n\n  //  EdgePointGeomInfo epgeominfo[2];\n  \n};\n\n\nenum SplittingType { SPLIT_HP, SPLIT_ALFELD, SPLIT_POWELL};\n\nDLL_HEADER extern void HPRefinement (Mesh & mesh, Refinement * ref, SplittingType split, int levels,\n\t\t\t  double fac1=0.125, bool setorders=true, bool ref_level = false);\n\ninline void HPRefinement (Mesh & mesh, Refinement * ref, int levels,\n\t\t\t  double fac1=0.125, bool setorders=true, bool ref_level = false)\n{\n  HPRefinement (mesh, ref, SPLIT_HP, levels, fac1, setorders, ref_level);\n}\n\n} // namespace netgen\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/improve2.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#include <opti.hpp>\n\n\nnamespace netgen\n{\n\n  class trionedge\n  {\n  public:\n    SurfaceElementIndex tnr;\n    int sidenr;\n\n    trionedge () { tnr = 0; sidenr = 0; }\n    trionedge (SurfaceElementIndex atnr, int asidenr)\n    { tnr = atnr; sidenr = asidenr; }\n  };\n\n  // check if element is quad with at least one surface point -> relevant for optimization\n  // (quads with 4 edge points are not optimized and can be ignored)\n  bool checkMixedElement(const Mesh & mesh, FlatArray<SurfaceElementIndex> seia)\n  {\n      bool mixed = false;\n      ParallelForRange( Range(seia), [&] (auto myrange) NETGEN_LAMBDA_INLINE\n         {\n            for (auto i : myrange)\n            {\n              const auto & sel = mesh[seia[i]];\n\n              if(sel.GetNP() == 3)\n                  continue;\n\n              for(auto pi : Range(sel.GetNP()))\n                  if(mesh[sel[pi]].Type() == SURFACEPOINT)\n                      mixed = true;\n            }\n         });\n      return mixed;\n  }\n\n  bool MeshOptimize2d :: EdgeSwapping (const int usemetric,\n    Array<Neighbour> &neighbors,\n    Array<bool> &swapped,\n    const SurfaceElementIndex t1, const int o1,\n    const int t,\n    Array<int,PointIndex> &pdef,\n    const bool check_only)\n  {\n    bool should;\n    bool do_swap = false;\n\n    SurfaceElementIndex t2 = neighbors[t1].GetNr (o1);\n    int o2 = neighbors[t1].GetOrientation (o1);\n\n    if (t2 == -1) return false;\n    if (swapped[t1] || swapped[t2]) return false;\n    if (mesh[t2].IsDeleted()) return false;\n    if (mesh[t2].GetNP() != 3) return false;\n\n    const int faceindex = mesh[t1].GetIndex();\n    const int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();\n\n    PointIndex pi1 = mesh[t1].PNumMod(o1+1+1);\n    PointIndex pi2 = mesh[t1].PNumMod(o1+1+2);\n    PointIndex pi3 = mesh[t1].PNumMod(o1+1);\n    PointIndex pi4 = mesh[t2].PNumMod(o2+1);\n\n    PointGeomInfo gi1 = mesh[t1].GeomInfoPiMod(o1+1+1);\n    PointGeomInfo gi2 = mesh[t1].GeomInfoPiMod(o1+1+2);\n    PointGeomInfo gi3 = mesh[t1].GeomInfoPiMod(o1+1);\n    PointGeomInfo gi4 = mesh[t2].GeomInfoPiMod(o2+1);\n\n    bool allowswap = true;\n\n    Vec<3> auxvec1 = mesh[pi3]-mesh[pi4];\n    Vec<3> auxvec2 = mesh[pi1]-mesh[pi4];\n\n    allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4;\n\n    if(!allowswap)\n        return false;\n\n    // normal of new\n    Vec<3> nv1 = Cross (auxvec1, auxvec2);\n\n    auxvec1 = mesh.Point(pi4)-mesh.Point(pi3);\n    auxvec2 = mesh.Point(pi2)-mesh.Point(pi3);\n    allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4;\n\n\n    if(!allowswap)\n        return false;\n\n    Vec<3> nv2 = Cross (auxvec1, auxvec2);\n\n\n    // normals of original\n    Vec<3> nv3 = Cross (mesh[pi1]-mesh[pi4], mesh[pi2]-mesh[pi4]);\n    Vec<3> nv4 = Cross (mesh[pi2]-mesh[pi3], mesh[pi1]-mesh[pi3]);\n\n    nv3 *= -1;\n    nv4 *= -1;\n    nv3.Normalize();\n    nv4.Normalize();\n\n    nv1.Normalize();\n    nv2.Normalize();\n\n    auto nvp3 = geo.GetNormal (surfnr, mesh.Point(pi3), &gi3);\n\n    nvp3.Normalize();\n\n    auto nvp4 = geo.GetNormal (surfnr, mesh.Point(pi4), &gi4);\n\n    nvp4.Normalize();\n\n\n\n    double critval = cos (M_PI / 6);  // 30 degree\n    allowswap = allowswap &&\n        (nv1 * nvp3 > critval) &&\n        (nv1 * nvp4 > critval) &&\n        (nv2 * nvp3 > critval) &&\n        (nv2 * nvp4 > critval) &&\n        (nvp3 * nv3 > critval) &&\n        (nvp4 * nv4 > critval);\n\n\n    double horder = Dist (mesh[pi1], mesh[pi2]);\n\n    if ( // nv1 * nv2 >= 0 &&\n            nv1.Length() > 1e-3 * horder * horder &&\n            nv2.Length() > 1e-3 * horder * horder &&\n            allowswap )\n      {\n        if (!usemetric)\n          {\n            int e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4];\n            double d =\n                Dist2 (mesh[pi1], mesh[pi2]) -\n                Dist2 (mesh[pi3], mesh[pi4]);\n\n            should = e >= t && (e > 2 || d > 0);\n          }\n        else\n          {\n            double loch = 0.25*(mesh.GetH(pi1) + mesh.GetH(pi2) + mesh.GetH(pi3) + mesh.GetH(pi4));\n            should =\n                CalcTriangleBadness (mesh[pi4], mesh[pi3], mesh[pi1], metricweight, loch) +\n                CalcTriangleBadness (mesh[pi3], mesh[pi4], mesh[pi2], metricweight, loch) <\n                CalcTriangleBadness (mesh[pi1], mesh[pi2], mesh[pi3], metricweight, loch) +\n                CalcTriangleBadness (mesh[pi2], mesh[pi1], mesh[pi4], metricweight, loch);\n          }\n\n        if (allowswap)\n          {\n            Element2d sw1 (pi4, pi3, pi1);\n            Element2d sw2 (pi3, pi4, pi2);\n\n            int legal1 =\n                mesh.LegalTrig (mesh[t1]) +\n                mesh.LegalTrig (mesh[t2]);\n            int legal2 =\n                mesh.LegalTrig (sw1) + mesh.LegalTrig (sw2);\n\n            if (legal1 < legal2) should = true;\n            if (legal2 < legal1) should = false;\n          }\n\n        do_swap = should;\n        if (should && !check_only)\n          {\n            // do swapping !\n\n            mesh[t1] = { { pi1, gi1 }, { pi4, gi4 }, { pi3, gi3 } };\n            mesh[t2] = { { pi2, gi2 }, { pi3, gi3 }, { pi4, gi4 } };\n\n            pdef[pi1]--;\n            pdef[pi2]--;\n            pdef[pi3]++;\n            pdef[pi4]++;\n\n            swapped[t1] = true;\n            swapped[t2] = true;\n          }\n      }\n    return do_swap;\n  }\n\n \n  void MeshOptimize2d :: EdgeSwapping (int usemetric)\n  {\n    static Timer timer(\"EdgeSwapping (2D)\"); RegionTimer reg(timer);\n    static Timer timer_nb(\"EdgeSwapping-Find neighbors\");\n    if (usemetric)\n      PrintMessage (3, \"Edgeswapping, metric\");\n    else\n      PrintMessage (3, \"Edgeswapping, topological\");\n\n    static Timer timerstart(\"EdgeSwapping 2D start\");\n    timerstart.Start();\n\n    Array<SurfaceElementIndex> seia;\n    mesh.GetSurfaceElementsOfFace (faceindex, seia);\n\n    if(checkMixedElement(mesh, seia))\n    {\n        timerstart.Stop();\n        return GenericImprove();\n    }\n\n    Array<Neighbour> neighbors(mesh.GetNSE());\n    auto elements_on_node = mesh.CreateCompressedPoint2SurfaceElementTable(faceindex);\n\n    Array<bool> swapped(mesh.GetNSE());\n    Array<int,PointIndex> pdef(mesh.GetNP());\n    Array<double,PointIndex> pangle(mesh.GetNP());\n\n    static const double minangle[] = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 };\n\n\n    if(faceindex == 0)\n      {\n        ParallelFor( Range(pangle), [&] (auto i) NETGEN_LAMBDA_INLINE\n            {\n              pangle[i] = 0.0;\n            });\n      }\n    else\n      {\n        ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE\n            {\n              const Element2d & sel = mesh[seia[i]];\n              for (int j = 0; j < 3; j++)\n                  pangle[sel[j]] = 0.0;\n            });\n      }\n\n    ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE\n        {\n          const Element2d & sel = mesh[seia[i]];\n          for (int j = 0; j < 3; j++)\n            {\n              POINTTYPE typ = mesh[sel[j]].Type();\n              if (typ == FIXEDPOINT || typ == EDGEPOINT)\n                {\n                  AtomicAdd(pangle[sel[j]],\n                    Angle (mesh[sel[(j+1)%3]] - mesh[sel[j]],\n                           mesh[sel[(j+2)%3]] - mesh[sel[j]]));\n                }\n            }\n       });\n\n    ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE\n        {\n          const Element2d & sel = mesh[seia[i]];\n          for (int j = 0; j < 3; j++)\n            {\n              PointIndex pi = sel[j];\n              if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT)\n                pdef[pi] = -6;\n              else\n                for (int j = 0; j < 8; j++)\n                  if (pangle[pi] >= minangle[j])\n                    pdef[pi] = -1-j;\n            }\n       });\n\n    ParallelFor( Range(seia), [this, &pdef, &neighbors, &seia, &elements_on_node] (auto i) NETGEN_LAMBDA_INLINE\n        {\n          auto sei = seia[i];\n          for (PointIndex pi : mesh[sei].template PNums<3>())\n              AsAtomic(pdef[pi])++;\n          for (int j = 0; j < 3; j++)\n            {\n              neighbors[sei].SetNr (j, -1);\n              neighbors[sei].SetOrientation (j, 0);\n            }\n\n          const auto sel = mesh[sei];\n          auto index = sel.GetIndex();\n          for (int j = 0; j < 3; j++)\n            {\n              PointIndex pi1 = sel.PNumMod(j+2);\n              PointIndex pi2 = sel.PNumMod(j+3);\n              if(mesh.IsSegment(pi1, pi2))\n                  continue;\n\n              for (auto sei_other : elements_on_node[pi1])\n                {\n                  if(sei_other==sei) continue;\n                  if(mesh[sei_other].GetIndex()!=index) continue;\n                  const auto & other = mesh[sei_other];\n                  int pi1_other = -1;\n                  int pi2_other = -1;\n                  bool common_edge = false;\n                  for (int k = 0; k < 3; k++)\n                    {\n                      if(other[k] == pi1)\n                          pi1_other = k;\n                      if(other[k] == pi2)\n                        {\n                          pi2_other = k;\n                          common_edge = true;\n                        }\n                    }\n\n                  if(common_edge)\n                    {\n                      neighbors[sei].SetNr (j, sei_other);\n                      neighbors[sei].SetOrientation (j, 3-pi1_other-pi2_other);\n                    }\n                }\n            }\n        });\n\n\n    for (SurfaceElementIndex sei : seia)\n      swapped[sei] = false;\n    \n    timerstart.Stop();\n  \n\n\n    Array<std::pair<SurfaceElementIndex,int>> improvement_candidates(3*seia.Size());\n    atomic<int> cnt(0);\n\n    int t = 4;\n    bool done = false;\n    while (!done && t >= 2)\n      {\n        cnt = 0;\n        ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE\n          {\n            SurfaceElementIndex t1 = seia[i];\n\n            if (mesh[t1].IsDeleted())\n              return;\n\n            if (swapped[t1])\n              return;\n\n            if(mesh[t1].GetNP() != 3)\n              return;\n\n            if (multithread.terminate)\n              throw NgException (\"Meshing stopped\");\n\n            for (int o1 = 0; o1 < 3; o1++)\n                if(EdgeSwapping(usemetric, neighbors, swapped, t1, o1, t, pdef, true))\n                    improvement_candidates[cnt++]= std::make_pair(t1,o1);\n          });\n\n        auto elements_with_improvement = improvement_candidates.Range(0, cnt.load());\n        QuickSort(elements_with_improvement);\n\n        for (auto [t1,o1] : elements_with_improvement)\n            done |= EdgeSwapping(usemetric, neighbors, swapped, t1, o1, t, pdef, false);\n\tt--;\n      }\n\n    mesh.SetNextTimeStamp();\n  }\n\n\n\n  template <typename T_PI2SEI>\n  double CombineImproveEdge( Mesh & mesh,\n                           const T_PI2SEI & elementsonnode,\n                           Array<Vec<3>, PointIndex> & normals,\n                           Array<bool, PointIndex> & fixed,\n                           PointIndex pi1, PointIndex pi2,\n                           double metricweight,\n                           bool check_only = true)\n  {\n    Vec<3> nv;\n    ArrayMem<SurfaceElementIndex, 20> hasonepi, hasbothpi;\n\n    if (!pi1.IsValid() || !pi2.IsValid())\n        return 0.0;\n\n    bool debugflag = 0;\n\n    if (debugflag)\n      {\n        (*testout) << \"Combineimprove \"\n            << \"pi1 = \" << pi1 << \" pi2 = \" << pi2 << endl;\n      }\n\n    if (fixed[pi2])\n        return 0.0;\n\n    double loch = 0.5*(mesh.GetH(pi1) + mesh.GetH(pi2));\n    int faceindex = -1;\n\n    for (SurfaceElementIndex sei2 : elementsonnode[pi1])\n      {\n        const Element2d & el2 = mesh[sei2];\n\n        if (el2.IsDeleted()) continue;\n\n        if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2)\n          {\n            faceindex = el2.GetIndex();\n            hasbothpi.Append (sei2);\n          }\n      }\n\n    if(hasbothpi.Size()==0)\n        return 0.0;\n\n\n    nv = normals[pi2];\n\n\n    for (SurfaceElementIndex sei2 :  elementsonnode[pi2])\n      {\n        const Element2d & el2 = mesh[sei2];\n        if (el2.IsDeleted()) continue;\n        if (!el2.PNums<3>().Contains (pi1))\n            hasonepi.Append (sei2);\n      }\n\n    double bad1 = 0;\n    int illegal1 = 0, illegal2 = 0;\n    /*\n       for (SurfaceElementIndex sei : hasonepi)\n       {\n       const Element2d & el = mesh[sei];\n       bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],\n       nv, -1, loch);\n       illegal1 += 1-mesh.LegalTrig(el);\n       }\n       */\n    for (const Element2d & el : mesh.SurfaceElements()[hasonepi])\n      {\n        bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],\n                nv, metricweight, loch);\n        illegal1 += 1-mesh.LegalTrig(el);\n      }\n\n    for (int k = 0; k < hasbothpi.Size(); k++)\n      {\n        const Element2d & el = mesh[hasbothpi[k]];\n        bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],\n                nv, metricweight, loch);\n        illegal1 += 1-mesh.LegalTrig(el);\n      }\n\n    double bad2 = 0;\n    for (int k = 0; k < hasonepi.Size(); k++)\n      {\n        Element2d el = mesh[hasonepi[k]];\n        for (auto i : Range(3))\n            if(el[i]==pi2)\n                el[i] = pi1;\n\n        double err =\n            CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],\n                    nv, metricweight, loch);\n        bad2 += err;\n\n        Vec<3> hnv = Cross (Vec3d (mesh[el[0]],\n                    mesh[el[1]]),\n                Vec3d (mesh[el[0]],\n                    mesh[el[2]]));\n        if (hnv * nv < 0)\n            bad2 += 1e10;\n\n        for (int l = 0; l < 3; l++)\n          {\n            auto normal = normals[el[l]];\n            if(mesh[el[l]].Type() != SURFACEPOINT)\n            {\n                // point possibly on edge -> multiple normal vectors (for each surface), need to calculate it to be sure\n                const int surfnr = mesh.GetFaceDescriptor (el.GetIndex()).SurfNr();\n                normal = mesh.GetGeometry()->GetNormal (surfnr, mesh[el[l]], &el.GeomInfo()[l]);\n            }\n            if ( ( normal * nv) < 0.5)\n                bad2 += 1e10;\n          }\n\n        illegal2 += 1-mesh.LegalTrig(el);\n      }\n\n    if (debugflag)\n      {\n        (*testout) << \"bad1 = \" << bad1 << \", bad2 = \" << bad2 << endl;\n      }\n\n    bool should = (illegal2<=illegal1 && bad2 < bad1 && bad2 < 1e4);\n    if(illegal2 < illegal1)\n      {\n        should = true;\n        bad1 += 1e4;\n      }\n\n    double d_badness = should * (bad2-bad1);\n\n    if(check_only)\n        return d_badness;\n\n    if (should)\n      {\n        /*\n           (*testout) << \"combine !\" << endl;\n           (*testout) << \"bad1 = \" << bad1 << \", bad2 = \" << bad2 << endl;\n           (*testout) << \"illegal1 = \" << illegal1 << \", illegal2 = \" << illegal2 << endl;\n           (*testout) << \"loch = \" << loch << endl;\n           */\n\n        PointGeomInfo gi;\n        // bool gi_set(false);\n\n        /*\n           Element2d *el1p(NULL);\n           int l = 0;\n           while(mesh[elementsonnode[pi1][l]].IsDeleted() && l<elementsonnode[pi1].Size()) l++;\n           if(l<elementsonnode[pi1].Size())\n           el1p = &mesh[elementsonnode[pi1][l]];\n           else\n           cerr << \"OOPS!\" << endl;\n\n           for (l = 0; l < el1p->GetNP(); l++)\n           if ((*el1p)[l] == pi1)\n           {\n           gi = el1p->GeomInfoPi (l+1);\n        // gi_set = true;\n        }\n        */\n        for (auto sei : hasbothpi)\n          {\n            const Element2d & el1p = mesh[sei];\n            if (el1p.IsDeleted()) continue;\n            if(el1p.GetIndex() != faceindex) continue;\n\n            for (int l = 0; l < el1p.GetNP(); l++)\n                if (el1p[l] == pi1)\n                    gi = el1p.GeomInfo()[l];\n            break;\n          }\n\n\n        // (*testout) << \"Connect point \" << pi2 << \" to \" << pi1 << \"\\n\";\n        // for (int k = 0; k < elementsonnode[pi2].Size(); k++)\n        for (SurfaceElementIndex sei2 : elementsonnode[pi2])\n          {\n            Element2d & el = mesh[sei2];\n            if (el.IsDeleted()) continue;\n            if (el.PNums().Contains(pi1)) continue;\n\n            for (auto l : Range(el.GetNP()))\n              {\n                if (el[l] == pi2)\n                  {\n                    el[l] = pi1;\n                    el.GeomInfo()[l] = gi;\n                  }\n\n                fixed[el[l]] = true;\n              }\n          }\n\n        for (auto sei : hasbothpi)\n            mesh[sei].Delete();\n\n      }\n    return d_badness;\n  }\n\n  void MeshOptimize2d :: CombineImprove ()\n  {\n    SplitImprove();\n    PrintMessage (3, \"Combine improve\");\n\n    if (multithread.terminate)\n        throw NgException (\"Meshing stopped\");\n\n    static Timer timer (\"Combineimprove 2D\");\n    RegionTimer reg (timer);\n\n    static Timer timerstart (\"Combineimprove 2D start\");\n    timerstart.Start();\n\n\n    static Timer timerstart1 (\"Combineimprove 2D start1\");\n    timerstart1.Start();\n\n    \n    Array<SurfaceElementIndex> seia;\n    mesh.GetSurfaceElementsOfFace (faceindex, seia);\n\n    if(checkMixedElement(mesh, seia))\n    {\n        timerstart1.Stop();\n        timerstart.Stop();\n        return;\n    }\n\n    int np = mesh.GetNP();\n\n    auto elementsonnode = mesh.CreateCompressedPoint2SurfaceElementTable(faceindex);\n\n    // int ntasks = ngcore::TaskManager::GetMaxThreads();\n    Array<std::tuple<PointIndex, PointIndex>> edges;\n\n    BuildEdgeList( mesh, elementsonnode, edges );\n\n    Array<bool,PointIndex> fixed(np);\n    ParallelFor( fixed.Range(), [&] (auto i) NETGEN_LAMBDA_INLINE\n            { fixed[i] = mesh[i].Type() != SURFACEPOINT; });\n\n    timerstart1.Stop();\n\n    ParallelFor( mesh.LockedPoints().Range(), [&] (auto i) NETGEN_LAMBDA_INLINE\n            {\n              fixed[mesh.LockedPoints()[i]] = true;\n            });\n\n\n    Array<Vec<3>,PointIndex> normals(np);\n\n    ParallelFor( mesh.Points().Range(), [&] (auto pi) NETGEN_LAMBDA_INLINE\n        {\n            if (elementsonnode[pi].Size())\n              {\n                Element2d & hel = mesh[elementsonnode[pi][0]];\n                for (int k = 0; k < 3; k++)\n                  if (hel[k] == pi)\n                    {\n                      const int faceindex = hel.GetIndex();\n                      const int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();\n                      normals[pi] = geo.GetNormal (surfnr, mesh[pi], &hel.GeomInfoPi(k+1));\n                      break;\n                    }\n              }\n        }, TasksPerThread(4));\n\n    timerstart.Stop();\n\n    // Find edges with improvement\n    Array<std::tuple<double, int>> candidate_edges(edges.Size());\n    std::atomic<int> improvement_counter(0);\n\n    ParallelFor( Range(edges), [&] (auto i) NETGEN_LAMBDA_INLINE\n      {\n        auto [pi1, pi2] = edges[i];\n        double d_badness = CombineImproveEdge(mesh, elementsonnode, normals, fixed, pi1, pi2, metricweight, true);\n        if(d_badness < 0.0)\n            candidate_edges[improvement_counter++] = make_tuple(d_badness, i);\n        d_badness = CombineImproveEdge(mesh, elementsonnode, normals, fixed, pi2, pi1, metricweight, true);\n        if(d_badness < 0.0)\n            candidate_edges[improvement_counter++] = make_tuple(d_badness, -i);\n      }, TasksPerThread(4));\n\n    auto edges_with_improvement = candidate_edges.Part(0, improvement_counter.load());\n    QuickSort(edges_with_improvement);\n\n    for(auto [d_badness, ei] : edges_with_improvement)\n      {\n        auto [pi1, pi2] = edges[ei < 0 ? -ei : ei];\n        if(ei<0)\n            Swap(pi1,pi2);\n        CombineImproveEdge(mesh, elementsonnode, normals, fixed, pi1, pi2, metricweight, false);\n      }\n\n    //  mesh.Compress();\n    mesh.SetNextTimeStamp();\n  }\n\n  void MeshOptimize2d :: SplitImprove()\n  {\n    if (!faceindex)\n      {\n        PrintMessage (3, \"Split improve\");\n\n        mesh.CalcSurfacesOfNode(); // TODO: needed?\n        for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)\n          {\n            SplitImprove();\n\n            if (multithread.terminate)\n                throw NgException (\"Meshing stopped\");\n          }\n\n        faceindex = 0;\n        mesh.Compress(); // TODO: needed?\n        return;\n      }\n\n    Array<SurfaceElementIndex> elements;\n    mesh.GetSurfaceElementsOfFace (faceindex, elements);\n\n    // return if we have quads in this surface\n    for (auto & ei : elements)\n        if (mesh[ei].GetNP() != 3)\n            return;\n\n    // maps from edges to adjacent trigs\n    INDEX_2_HASHTABLE<tuple<SurfaceElementIndex, SurfaceElementIndex>> els_on_edge(2*elements.Size() + 2);\n\n    // build els_on_edge table\n    for (SurfaceElementIndex sei : elements)\n      {\n        const Element2d & sel = mesh[sei];\n\n        for (int j = 0; j < 3; j++)\n          {\n            PointIndex pi1 = sel.PNumMod(j+2);\n            PointIndex pi2 = sel.PNumMod(j+3);\n\n            if (mesh.IsSegment (pi1, pi2)) continue;\n\n            PointIndices<2> ii2 (pi1, pi2);\n            ii2.Sort();\n            if (els_on_edge.Used (ii2))\n              {\n                auto els = els_on_edge.Get(ii2);\n                get<1>(els) = sei;\n                els_on_edge.Set(ii2, els);\n              }\n            else\n              {\n                els_on_edge.Set (ii2, make_tuple(sei, sei));\n              }\n          }\n      }\n\n    // split edges of illegal trigs\n    for (SurfaceElementIndex sei : elements)\n      {\n        Element2d & sel = mesh[sei];\n\n        if (sel.IsDeleted()) continue;\n\n        // TODO: split also bad trigs, nut just illegal ones\n        if (mesh.LegalTrig(sel)) continue;\n\n        // find longest edge\n        PointIndices<2> edge;\n        double edge_len = 0;\n        PointIndex pi1, pi2, pi3, pi4;\n        PointGeomInfo gi1, gi2, gi3, gi4;\n        for(auto j : Range(1,4))\n          {\n            auto test_pi1 = sel.PNumMod(j);\n            auto test_pi2 = sel.PNumMod(j+1);\n            if (mesh.IsSegment(test_pi1, test_pi2))\n              continue;\n            auto len = (mesh[test_pi2]-mesh[test_pi1]).Length();\n            if(len > edge_len)\n              {\n                edge = {test_pi1, test_pi2};\n                edge.Sort();\n                edge_len = len;\n                pi1 = test_pi1;\n                pi2 = test_pi2;\n                pi3 = sel.PNumMod(j+2);\n                gi1 = sel.GeomInfoPiMod(j);\n                gi2 = sel.GeomInfoPiMod(j+1);\n                gi3 = sel.GeomInfoPiMod(j+2);\n              }\n          }\n        if(!edge_len)\n          throw Exception(\"Couldn't find edge to split, something is wrong\");\n        // get neighbor element\n        auto els = els_on_edge.Get(edge);\n        SurfaceElementIndex other_i = get<0>(els);\n        if(other_i==sei) other_i = get<1>(els);\n        auto & other = mesh[other_i];\n\n        // find opposite point of neighbor element\n        for (int j = 0; j < 3; j++)\n          if(other[j]!=pi1 && other[j]!=pi2)\n            {\n              pi4 = other[j];\n              gi4 = other.GeomInfoPi(j);\n              break;\n            }\n\n        // split edge pi1,pi2\n        Point<3> p5;\n        PointIndex pi5;\n        PointGeomInfo gi5;\n\n        geo.PointBetween(mesh[pi1], mesh[pi2], 0.5,\n                         faceindex,\n                         gi1, gi2, p5, gi5);\n\n        pi5 = mesh.AddPoint(p5);\n\n        Element2d e1(3);\n        e1.SetIndex(faceindex);\n        e1={ {pi1,gi1}, {pi5,gi5}, {pi3,gi3} };\n        mesh.AddSurfaceElement( e1 );\n\n        Element2d e2(3);\n        e2.SetIndex(faceindex);\n        e2 ={ {pi5,gi5}, {pi2,gi2}, {pi3,gi3} };\n        mesh.AddSurfaceElement( e2 );\n\n        Element2d e3(3);\n        e3.SetIndex(faceindex);\n        e3 ={ {pi1,gi1}, {pi4,gi4}, {pi5,gi5} };\n        mesh.AddSurfaceElement( e3 );\n\n        Element2d e4(3);\n        e4.SetIndex(faceindex);\n        e4 ={ {pi4,gi4}, {pi2,gi2}, {pi5,gi5} };\n        mesh.AddSurfaceElement( e4 );\n\n        sel.Delete();\n        other.Delete();\n      }\n\n    mesh.SetNextTimeStamp();\n  }\n\n  void MeshOptimize2d :: CheckMeshApproximation (Mesh & mesh)\n  {\n    // Check angles between elements and normals at corners\n    /*\n  \n    int i, j;\n    int ne = mesh.GetNSE();\n    int surfnr;\n  \n    Vec3d n, ng;\n    NgArray<Vec3d> ngs(3);\n\n    (*mycout) << \"Check Surface Approximation\" << endl;\n    (*testout) << \"Check Surface Approximation\" << endl;\n\n    for (i = 1; i <= ne; i++)\n    {\n    const Element2d & el = mesh.SurfaceElement(i);\n    surfnr = mesh.GetFaceDescriptor (el.GetIndex()).SurfNr();\n    Vec3d n = Cross (mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(2)),\n    mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(3)));\n    n /= n.Length();\n\n    for (j = 1; j <= el.GetNP(); j++)\n    {\n    SelectSurfaceOfPoint (mesh.Point(el.PNum(j)), el.GeomInfoPi(j));\n    GetNormalVector (surfnr, mesh.Point(el.PNum(j)), ng);\n    ng /= ng.Length();\n    ngs.Elem(j) = ng;\n\n    double angle =  (180.0 / M_PI) * Angle (n, ng);\n    if (angle > 60)\n    {\n    (*testout) << \"el \" << i << \" node \" << el.PNum(j)\n    << \"has angle = \" << angle << endl;\n    }\n    }\t\n\n    for (j = 1; j <= 3; j++)\n    {\n    double angle =  (180.0 / M_PI) * Angle (ngs.Get(j), ngs.Get(j%3+1));\n    if (angle > 60)\n    {\n    (*testout) << \"el \" << i << \" node-node \" \n    << ngs.Get(j) << \" - \" << ngs.Get(j%3+1)\n    << \" has angle = \" << angle << endl;\n    }\n    }\n    }\n    */\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/improve2.hpp",
    "content": "#ifndef NETGEN_IMPROVE2_HPP\n#define NETGEN_IMPROVE2_HPP\n\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n\ninline void AppendEdges( const Element2d & elem, PointIndex pi, Array<std::tuple<PointIndex,PointIndex>> & edges )\n{\n  for (int j = 0; j < 3; j++)\n  {\n      PointIndex pi0 = elem[j];\n      PointIndex pi1 = elem[(j+1)%3];\n      if (pi1 < pi0) Swap(pi0, pi1);\n      if(pi0==pi)\n          edges.Append(std::make_tuple(pi0, pi1));\n  }\n}\n\ninline void AppendEdges( const Element & elem, PointIndex pi, Array<std::tuple<PointIndex,PointIndex>> & edges )\n{\n  static constexpr int tetedges[6][2] =\n  { { 0, 1 }, { 0, 2 }, { 0, 3 },\n      { 1, 2 }, { 1, 3 }, { 2, 3 } };\n\n  if(elem.Flags().fixed)\n      return;\n  for (int j = 0; j < 6; j++)\n  {\n      PointIndex pi0 = elem[tetedges[j][0]];\n      PointIndex pi1 = elem[tetedges[j][1]];\n      if (pi1 < pi0) Swap(pi0, pi1);\n      if(pi0==pi)\n          edges.Append(std::make_tuple(pi0, pi1));\n  }\n}\n\ntemplate<typename T_PI2SEI>\nvoid BuildEdgeList( const Mesh & mesh, const T_PI2SEI & elementsonnode, Array<std::tuple<PointIndex, PointIndex>> & edges )\n{\n  // static_assert(is_same_v<TINDEX, ElementIndex>||is_same_v<TINDEX,SurfaceElementIndex>, \"Invalid type for TINDEX\");\n  static Timer tbuild_edges(\"Build edges\"); RegionTimer reg(tbuild_edges);\n\n  int ntasks = 4*ngcore::TaskManager::GetMaxThreads();\n  Array<Array<std::tuple<PointIndex,PointIndex>>> task_edges(ntasks);\n\n  ParallelFor(IntRange(ntasks), [&] (int ti)\n    {\n      auto myrange = mesh.Points().Range().Split(ti, ntasks);\n      ArrayMem<std::tuple<PointIndex,PointIndex>, 100> local_edges;\n      for (auto pi : myrange)\n      {\n        local_edges.SetSize(0);\n\n        for(auto ei : elementsonnode[pi])\n        {\n            const auto & elem = mesh[ei];\n            if (elem.IsDeleted()) continue;\n\n            AppendEdges(elem, pi, local_edges);\n        }\n        QuickSort(local_edges);\n\n        auto edge_prev = std::make_tuple<PointIndex, PointIndex>(PointIndex::INVALID, PointIndex::INVALID);\n\n        for(auto edge : local_edges)\n            if(edge != edge_prev)\n            {\n                task_edges[ti].Append(edge);\n                edge_prev = edge;\n            }\n      }\n    }, ntasks);\n\n  int num_edges = 0;\n  for (auto & edg : task_edges)\n      num_edges += edg.Size();\n  edges.SetAllocSize(num_edges);\n  for (auto & edg : task_edges)\n      edges.Append(edg);\n}\n\n\nclass Neighbour\n{\n  int nr[3];\n  int orient[3];\n\npublic:\n  Neighbour () { ; }\n\n  void SetNr (int side, int anr) { nr[side] = anr; }\n  int GetNr (int side) { return nr[side]; }\n\n  void SetOrientation (int side, int aorient) { orient[side] = aorient; }\n  int GetOrientation (int side) { return orient[side]; }\n};\n\n///\nclass MeshOptimize2d\n{\n  int faceindex = 0;\n  int improveedges = 0;\n  double metricweight = 0.;\n  int writestatus = 1;\n  Mesh& mesh;\n  const NetgenGeometry& geo;\npublic:\n  ///\n  MeshOptimize2d(Mesh& amesh) : mesh(amesh), geo(*mesh.GetGeometry())\n  {}\n  virtual ~MeshOptimize2d() { ; }\n  ///\n  DLL_HEADER void ImproveMesh (const MeshingParameters & mp);\n  DLL_HEADER void ImproveMeshJacobian (const MeshingParameters & mp);\n  DLL_HEADER void ImproveVolumeMesh ();\n  DLL_HEADER void ProjectBoundaryPoints(NgArray<int> & surfaceindex, \n\t\t\t     const NgArray<Point<3>* > & from, NgArray<Point<3>* > & dest);\n\n  DLL_HEADER bool EdgeSwapping (const int usemetric, Array<Neighbour> &neighbors, Array<bool> &swapped,\n                                const SurfaceElementIndex t1, const int edge, const int t, Array<int,PointIndex> &pdef, const bool check_only=false);\n  DLL_HEADER void EdgeSwapping (int usemetric);\n  DLL_HEADER void CombineImprove ();\n  DLL_HEADER void SplitImprove ();\n\n  DLL_HEADER void GenericImprove ();\n\n\n  void SetFaceIndex (int fi) { faceindex = fi; }\n  void SetImproveEdges (int ie) { improveedges = ie; }\n  void SetMetricWeight (double mw) { metricweight = mw; }\n  void SetWriteStatus (int ws) { writestatus = ws; }\n\n\n  /// liefert zu einem 3d-Punkt die geominfo (Dreieck) und liefert 1, wenn erfolgreich, \n  /// 0, wenn nicht (Punkt ausserhalb von chart)\n  ///\n\n  void CheckMeshApproximation (Mesh & mesh);\n\n\n  ///\n  friend class Opti2SurfaceMinFunction;\n  ///\n  friend class Opti2EdgeMinFunction;\n  ///\n  friend double Opti2FunctionValueGrad (const Vector & x, Vector & grad);\n  ///\n  friend double Opti2EdgeFunctionValueGrad (const Vector & x, Vector & grad);\n\n\n\n};\n\n\nextern void CalcTriangleBadness (double x2, double x3, double y3, \n\t\t\t\t double metricweight,\n\t\t\t\t double h, double & badness, \n\t\t\t\t double & g1x, double & g1y);\n\n\n\n\nextern double CalcTriangleBadness (const Point<3> & p1, \n\t\t\t\t   const Point<3> & p2, \n\t\t\t\t   const Point<3> & p3,\n\t\t\t\t   double metricweight,\n\t\t\t\t   double h);\n\nextern double CalcTriangleBadness (const Point<3> & p1, \n\t\t\t\t   const Point<3> & p2, \n\t\t\t\t   const Point<3> & p3,\n\t\t\t\t   const Vec<3> & n,\n\t\t\t\t   double metricweight,\n\t\t\t\t   double h);\n} // namespace netgen\n#endif // NETGEN_IMPROVE2_HPP\n"
  },
  {
    "path": "libsrc/meshing/improve2gen.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#include <opti.hpp>\n\nnamespace netgen\n{\n\n  class ImprovementRule\n  {\n  public:\n    NgArray<Element2d> oldels;\n    NgArray<Element2d> newels;\n    NgArray<PointIndices<2>> deledges;\n    Array<int,PointIndex> incelsonnode;\n    Array<int,PointIndex> reused;\n    int bonus;\n    int onp;\n  };\n\n\n  void MeshOptimize2d :: GenericImprove ()\n  {\n    static Timer timer(\"MeshOptimize2d::GenericImprove\"); RegionTimer reg(timer);\n    if (!faceindex)\n      {\n\tif (writestatus)\n\t  PrintMessage (3, \"Generic Improve\");\n\n\tfor (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)\n\t  GenericImprove ();\n      \n\tfaceindex = 0;\n        return;\n      }\n\n    // int j, k, l, ri;\n    int np = mesh.GetNP();\n    int ne = mesh.GetNSE();\n    //    SurfaceElementIndex sei;\n\n    \n//     for (SurfaceElementIndex sei = 0; sei < ne; sei++)\n//       {\n// \tconst Element2d & el = mesh[sei];\n// \t(*testout) << \"element \" << sei << \": \" <<flush;\n// \tfor(int j=0; j<el.GetNP(); j++)\n// \t  (*testout) << el[j] << \" \" << flush;\n// \t(*testout) << \"IsDeleted() \" << el.IsDeleted()<< endl;\n//       }\n\n    bool ok;\n    int olddef, newdef;\n\n    NgArray<ImprovementRule*> rules;\n    NgArray<SurfaceElementIndex> elmap;\n    NgArray<int> elrot;\n    Array<PointIndex,PointIndex> pmap;\n    Array<PointGeomInfo,PointIndex> pgi;\n\n    int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();\n  \n    ImprovementRule * r1;\n\n    PointIndex p1 = IndexBASE<PointIndex>();\n    PointIndex p2 = p1+1;\n    PointIndex p3 = p2+1;\n    PointIndex p4 = p3+1;\n    PointIndex p5 = p4+1;\n    PointIndex p6 = p5+1;\n    PointIndex p7 = p6+1;\n    \n    \n    // 2 triangles to quad\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3));\n    r1->oldels.Append (Element2d (p3, p2, p4));\n    r1->newels.Append (Element2d (p1, p2, p4, p3));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 4;\n    r1->bonus = 2;\n    rules.Append (r1);\n\n    // 2 quad to 1 quad\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p4, p3, p2, p5));\n    r1->newels.Append (Element2d (p1, p2, p5, p4));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->deledges.Append ( { p3, p4 } );\n    r1->onp = 5;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    // swap quads\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p3, p2, p5, p6));\n    r1->newels.Append (Element2d (p1, p6, p3, p4));\n    r1->newels.Append (Element2d (p1, p2, p5, p6));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 6;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    // three quads to 2\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p5, p6, p3));\n    r1->oldels.Append (Element2d (p3, p6, p7, p4));\n    r1->newels.Append (Element2d (p1, p2, p5, p4));\n    r1->newels.Append (Element2d (p4, p5, p6, p7));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->deledges.Append ( { p3, p4 } );\n    r1->deledges.Append ( { p3, p6 } );\n    r1->onp = 7;\n    r1->bonus = -1;\n    rules.Append (r1);\n\n    // quad + 2 connected trigs to quad\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p5, p3));\n    r1->oldels.Append (Element2d (p3, p5, p4));\n    r1->newels.Append (Element2d (p1, p2, p5, p4));\n    r1->deledges.Append ( { p2, p3 } ); \n    r1->deledges.Append ( { p3, p4 } );\n    r1->deledges.Append ( { p3, p5 } );\n    r1->onp = 5;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    // quad + 2 non-connected trigs to quad (a and b)\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p6, p3));\n    r1->oldels.Append (Element2d (p1, p4, p5));\n    r1->newels.Append (Element2d (p1, p3, p4, p5));\n    r1->newels.Append (Element2d (p1, p2, p6, p3));\n    r1->deledges.Append ( { p1, p4 } );\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 6;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p6, p3));\n    r1->oldels.Append (Element2d (p1, p4, p5));\n    r1->newels.Append (Element2d (p1, p2, p4, p5));\n    r1->newels.Append (Element2d (p4, p2, p6, p3));\n    r1->deledges.Append ( { p1, p4 } );\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 6;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    // two quad + trig -> one quad + trig\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p5, p6, p3));\n    r1->oldels.Append (Element2d (p4, p3, p6));\n    r1->newels.Append (Element2d (p1, p2, p6, p4));\n    r1->newels.Append (Element2d (p2, p5, p6));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->deledges.Append ( { p3, p4 } );\n    r1->deledges.Append ( { p3, p6 } );\n    r1->onp = 6;\n    r1->bonus = -1;\n    rules.Append (r1);\n\n    // swap quad + trig (a and b)\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p5, p3));\n    r1->newels.Append (Element2d (p2, p5, p3, p4));\n    r1->newels.Append (Element2d (p1, p2, p4));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 5;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p2, p5, p3));\n    r1->newels.Append (Element2d (p1, p2, p5, p3));\n    r1->newels.Append (Element2d (p1, p3, p4));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 5;\n    r1->bonus = 0;\n    rules.Append (r1);\n\n\n    // 2 quads to quad + 2 trigs\n    r1 = new ImprovementRule;\n    r1->oldels.Append (Element2d (p1, p2, p3, p4));\n    r1->oldels.Append (Element2d (p3, p2, p5, p6));\n    r1->newels.Append (Element2d (p1, p5, p6, p4));\n    r1->newels.Append (Element2d (p1, p2, p5));\n    r1->newels.Append (Element2d (p4, p6, p3));\n    r1->deledges.Append ( { p2, p3 } );\n    r1->onp = 6;\n    r1->bonus = 0;\n    //    rules.Append (r1);\n\n\n\n\n    NgArray<int> mapped(rules.Size());\n    NgArray<int> used(rules.Size());\n    used = 0;\n    mapped = 0;\n\n  \n    for (int ri = 0; ri < rules.Size(); ri++)\n      {\n\tImprovementRule & rule = *rules[ri];\n\trule.incelsonnode.SetSize (rule.onp);\n\trule.reused.SetSize (rule.onp);\n\n        /*\n\tfor (int j = 0; j < rule.onp; j++)\n\t  {\n\t    rule.incelsonnode[j] = 0;\n\t    rule.reused[j] = 0;\n\t  }\n        */\n        rule.incelsonnode = 0;\n        rule.reused = 0;\n\n        /*\n\tfor (int j = 1; j <= rule.oldels.Size(); j++)\n\t  {\n\t    const Element2d & el = rule.oldels.Elem(j);\n\t    for (int k = 1; k <= el.GetNP(); k++)\n\t      rule.incelsonnode.Elem(el.PNum(k))--;\n\t  }\n        */\n        for (const Element2d & el : rule.oldels)\n          for (PointIndex pi : el.PNums())\n            rule.incelsonnode[pi]--;\n\n\tfor (int j = 1; j <= rule.newels.Size(); j++)\n\t  {\n\t    const Element2d & el = rule.newels.Elem(j);\n\t    for (int k = 1; k <= el.GetNP(); k++)\n\t      {\n\t\trule.incelsonnode[el.PNum(k)]++;\n\t\trule.reused[el.PNum(k)] = 1;\n\t      }\n\t  }\n      }\n\n\n\n  \n    DynamicTable<int,PointIndex> elonnode(np);\n    Array<int,PointIndex> nelonnode(np);\n    TABLE<SurfaceElementIndex> nbels(ne);\n\n    nelonnode = -4;\n\n    for (SurfaceElementIndex sei = 0; sei < ne; sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\n\tif (el.GetIndex() == faceindex && !el.IsDeleted())\n\t  {\n\t    for (int j = 0; j < el.GetNP(); j++)\n\t      elonnode.Add (el[j], sei);\n\t  }\n\tif(!el.IsDeleted())\n\t  {\n\t    for (int j = 0; j < el.GetNP(); j++)\n\t      nelonnode[el[j]]++;\n\t  }\n      }\n\n    for (SurfaceElementIndex sei = 0; sei < ne; sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\tif (el.GetIndex() == faceindex && !el.IsDeleted())\n\t  {\n\t    for (int j = 0; j < el.GetNP(); j++)\n\t      {\n\t\tfor (int k = 0; k < elonnode[el[j]].Size(); k++)\n\t\t  {\n\t\t    int nbel = elonnode[el[j]] [k];\n\t\t    bool inuse = false;\n\t\t    for (int l = 0; l < nbels[sei].Size(); l++)\n\t\t      if (nbels[sei][l] == nbel)\n\t\t\tinuse = true;\n\t\t    if (!inuse)\n\t\t      nbels.Add (sei, nbel);\n\t\t  }\n\t      }\n\t  }\n      }\n\n\n    for (int ri = 0; ri < rules.Size(); ri++)\n      {\n\tconst ImprovementRule & rule = *rules[ri];\n      \n\telmap.SetSize (rule.oldels.Size());\n\telrot.SetSize (rule.oldels.Size());\n\tpmap.SetSize (rule.onp);\n\tpgi.SetSize (rule.onp);\n\n\n\tfor (SurfaceElementIndex sei = 0; sei < ne; sei++)\n\t  {\n\t    if (multithread.terminate)\n\t      break;\n\t    if (mesh[sei].IsDeleted()) continue;\n\n\t    elmap[0] = sei;\n\t    NgFlatArray<SurfaceElementIndex> neighbours = nbels[sei];\n\t    \n\t    for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++)\n\t      {\n\t\tconst Element2d & el0 = mesh[sei];\n\t\tconst Element2d & rel0 = rule.oldels[0];\n\n\t\tif (el0.GetIndex() != faceindex) continue;\n\t\tif (el0.IsDeleted()) continue;\n\t\tif (el0.GetNP() != rel0.GetNP()) continue;\n\n\t\t// pmap = PointIndex (-1);\n                for (auto & p : pmap) p.Invalidate();\n \n\t\tfor (int k = 0; k < el0.GetNP(); k++)\n\t\t  {\n\t\t    pmap[rel0[k]] = el0.PNumMod(k+elrot[0]+1);\n\t\t    pgi[rel0[k]] = el0.GeomInfoPiMod(k+elrot[0]+1);\n\t\t  }\n\t\t\n\t\tok = 1;\n\t\tfor (int i = 1; i < elmap.Size(); i++)\n\t\t  {\n\t\t    // try to find a mapping for reference-element i\n\n\t\t    const Element2d & rel = rule.oldels[i];\n\t\t    bool possible = 0;\n\n\t\t    for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++)\n\t\t      {\n\t\t\tconst Element2d & el = mesh[neighbours[elmap[i]]];\n\t\t\tif (el.IsDeleted()) continue;\n\t\t\tif (el.GetNP() != rel.GetNP()) continue;\n\n\t\t\tfor (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++)\n\t\t\t  {\n\t\t\t    possible = 1;\n\n\t\t\t    for (int k = 0; k < rel.GetNP(); k++)\n\t\t\t      if (pmap[rel[k]].IsValid() && \n\t\t\t\t  pmap[rel[k]] != el.PNumMod (k+elrot[i]+1))\n\t\t\t\tpossible = 0;\n\n\t\t\t    if (possible) \n\t\t\t      {\n\t\t\t\tfor (int k = 0; k < el.GetNP(); k++)\n\t\t\t\t  {\n\t\t\t\t    pmap[rel[k]] = el.PNumMod(k+elrot[i]+1);\n\t\t\t\t    pgi[rel[k]] = el.GeomInfoPiMod(k+elrot[i]+1);\n\t\t\t\t  }\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\t\t\tif (possible) break;\n\t\t      }\n\n\t\t    if (!possible) \n\t\t      {\n\t\t\tok = 0;\n\t\t\tbreak;\n\t\t      }\n\n\t\t    elmap[i] = neighbours[elmap[i]];\n\t\t  }\n\n\t\tfor(int i=0; ok && i<rule.deledges.Size(); i++)\n\t\t  {\n\t\t    ok = !mesh.IsSegment(pmap[rule.deledges[i][0]],\n\t\t\t\t\t pmap[rule.deledges[i][1]]);\n\t\t  }\n\t\t\t\t\t\t\t\t    \n\t\t\t\t\t\t\t\t    \n\t\t\n\t\t\n\t\tif (!ok) continue;\n\n\t\tmapped[ri]++;\n\n\t\tolddef = 0;\n\t\tfor (auto j : pmap.Range())\n\t\t  olddef += sqr (nelonnode[pmap[j]]);\n\t\tolddef += rule.bonus;\n\n\t\tnewdef = 0;\n\t\tfor (auto j : pmap.Range())\n\t\t  if (rule.reused[j])\n\t\t    newdef += sqr (nelonnode[pmap[j]] + \n\t\t\t\t   rule.incelsonnode[j]); \n\n\t\tif (newdef > olddef)\n\t\t  continue;\n\n\t\t// calc metric badness\n\t\tdouble bad1 = 0, bad2 = 0;\n\t\t// SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1));\n\t\t// auto n = geo.GetNormal(surfnr, mesh.Point(pmap.Get(1)), &pgi.Elem(1));\n                auto n = geo.GetNormal(surfnr, mesh.Point(pmap.First()), pgi.Data());\n\t\t  \n\t\tfor (int j = 0; j < rule.oldels.Size(); j++)\n\t\t  bad1 += mesh[elmap[j]].CalcJacobianBadness (mesh.Points(), n);\n\t\t  \n\t\t// check new element:\n\t\tfor (int j = 1; j <= rule.newels.Size(); j++)\n\t\t  {\n\t\t    const Element2d & rnel = rule.newels.Get(j);\n\t\t    Element2d nel(rnel.GetNP());\n\t\t    for (int k = 1; k <= rnel.GetNP(); k++)\n\t\t      nel.PNum(k) = pmap[rnel.PNum(k)];\n\n\t\t    bad2 += nel.CalcJacobianBadness (mesh.Points(), n);\n\t\t  }\n\n\t\tif (bad2 > 1e3) continue;\n\n\t\tif (newdef == olddef && bad2 > bad1) continue;\n\t\t  \n\n\t\t// generate new element:\n\t\tfor (int j = 1; j <= rule.newels.Size(); j++)\n\t\t  {\n\t\t    const Element2d & rnel = rule.newels.Get(j);\n\t\t    Element2d nel(rnel.GetNP());\n\t\t    nel.SetIndex (faceindex);\n\t\t    for (int k = 1; k <= rnel.GetNP(); k++)\n\t\t      {\n\t\t\tnel.PNum(k) = pmap[rnel.PNum(k)];\n\t\t\tnel.GeomInfoPi(k) = pgi[rnel.PNum(k)];\n\t\t      }\n\t\t      \n\t\t    mesh.AddSurfaceElement(nel);\n\t\t  }\n\t\t  \n\t\tfor (int j = 0; j < rule.oldels.Size(); j++)\n\t\t  mesh.Delete (elmap[j]);\n\n                for (PointIndex j : pmap.Range())\n\t\t  nelonnode[pmap[j]] += rule.incelsonnode[j];\n\n\t\tused[ri]++;\n\t      }\n\t  }\n      }\n\n    mesh.Compress();\n\n    for (int ri = 0; ri < rules.Size(); ri++)\n      {\n\tPrintMessage (5, \"rule \", ri+1, \" \",\n\t\t      mapped[ri], \"/\", used[ri], \" mapped/used\");\n      }\n  }\n\n\n\n\n}\n"
  },
  {
    "path": "libsrc/meshing/improve3.cpp",
    "content": "#include <mystdlib.h>\n#include <algorithm>\n\n#include <core/taskmanager.hpp>\n#include <core/logging.hpp>\n\n#include \"meshing.hpp\"\n\n#ifdef SOLIDGEOM\n#include <csg.hpp>\n#endif\n#include <opti.hpp>\n\nnamespace netgen\n{\n\nbool WrongOrientation(Point<3> p1, Point<3> p2, Point<3> p3, Point<3> p4)\n{\n  Vec<3> v1 = p2 - p1;\n  Vec<3> v2 = p3 - p1;\n  Vec<3> v3 = p4 - p1;\n\n  Vec<3> n = Cross(v1, v2);\n  return n * v3 > 0;\n}\n\nstatic constexpr int tetedges[6][2] =\n  { { 0, 1 }, { 0, 2 }, { 0, 3 },\n    { 1, 2 }, { 1, 3 }, { 2, 3 } };\n\n\nstatic constexpr int IMPROVEMENT_CONFORMING_EDGE = -1e6;\n\nstatic inline bool NotTooBad(double bad1, double bad2)\n{\n  return (bad2 <= bad1) ||\n         (bad2 <= 100 * bad1 && bad2 <= 1e18) ||\n         (bad2 <= 1e8);\n}\n\n// Calc badness of new element where pi1 and pi2 are replaced by pnew\ndouble CalcBadReplacePoints (const Mesh::T_POINTS & points, const MeshingParameters & mp, const Element & elem, double h, PointIndex &pi1, PointIndex &pi2, MeshPoint &pnew)\n  {\n    if (elem.GetType() != TET) return 0;\n\n    MeshPoint* p[] = {&points[elem[0]], &points[elem[1]], &points[elem[2]], &points[elem[3]]};\n\n    for (auto i : Range(4))\n        if(elem[i]==pi1 || elem[i]==pi2) p[i] = &pnew;\n\n    return CalcTetBadness (*p[0], *p[1], *p[2], *p[3], h, mp);\n  }\n\nstatic ArrayMem<Element, 3> SplitElement (Element old, PointIndex pi0, PointIndex pi1, PointIndex pinew)\n{\n  ArrayMem<Element, 3> new_elements;\n  // split element by cutting edge pi0,pi1 at pinew\n  auto np = old.GetNP();\n  old.Touch();\n  if(np == 4)\n  {\n    // Split tet into two tets\n    Element newel0 = old;\n    Element newel1 = old;\n    for (int i : Range(4))\n    {\n      if(newel0[i] == pi0) newel0[i] = pinew;\n      if(newel1[i] == pi1) newel1[i] = pinew;\n    }\n    new_elements.Append(newel0);\n    new_elements.Append(newel1);\n  }\n  else if (np == 5)\n  {\n    // split pyramid into pyramid and two tets\n    Element new_pyramid = old;\n    new_pyramid[4] = pinew;\n    new_elements.Append(new_pyramid);\n\n    auto pibase = (pi0==old[4]) ? pi1 : pi0;\n    auto pitop = (pi0==old[4]) ? pi0 : pi1;\n\n    Element new_tet0 = old;\n    Element new_tet1 = old;\n    new_tet0.SetType(TET);\n    new_tet1.SetType(TET);\n\n    size_t pibase_index=0;\n    for(auto i : Range(4))\n      if(old[i]==pibase)\n        pibase_index = i;\n\n    new_tet0[0] = old[(pibase_index+1)%4];\n    new_tet0[1] = old[(pibase_index+2)%4];\n    new_tet0[2] = pinew;\n    new_tet0[3] = pitop;\n    new_elements.Append(new_tet0);\n\n    new_tet1[0] = old[(pibase_index+2)%4];\n    new_tet1[1] = old[(pibase_index+3)%4];\n    new_tet1[2] = pinew;\n    new_tet1[3] = pitop;\n    new_elements.Append(new_tet1);\n  }\n\n  return new_elements;\n}\n\nstatic double SplitElementBadness (const Mesh::T_POINTS & points, const MeshingParameters & mp, Element old, PointIndex pi0, PointIndex pi1, MeshPoint & pnew)\n{\n  double badness = 0;\n  auto np = old.GetNP();\n  PointIndex dummy{PointIndex::INVALID};\n  if(np == 4)\n  {\n    // Split tet into two tets\n    badness += CalcBadReplacePoints ( points, mp, old, 0, pi0, dummy, pnew );\n    badness += CalcBadReplacePoints ( points, mp, old, 0, pi1, dummy, pnew );\n  }\n  else if (np == 5)\n  {\n    // split pyramid into pyramid and two tets\n    auto pibase = (pi0==old[4]) ? pi1 : pi0;\n    auto pitop = (pi0==old[4]) ? pi0 : pi1;\n\n    badness += CalcBadReplacePoints ( points, mp, old, 0, pitop, dummy, pnew );\n\n    Element tet = old;\n    tet.SetType(TET);\n\n    size_t pibase_index=0;\n    for(auto i : Range(4))\n      if(old[i]==pibase)\n        pibase_index = i;\n\n    MeshPoint p[4];\n    p[0] = points[old[(pibase_index+1)%4]];\n    p[1] = points[old[(pibase_index+2)%4]];\n    p[2] = pnew;\n    p[3] = points[pitop];\n    badness += CalcTetBadness (p[0], p[1], p[2], p[3], 0, mp);\n\n    p[0] = points[old[(pibase_index+2)%4]];\n    p[1] = points[old[(pibase_index+3)%4]];\n    p[2] = pnew;\n    p[3] = points[pitop];\n    badness += CalcTetBadness (p[0], p[1], p[2], p[3], 0, mp);\n  }\n\n  return badness;\n}\n\n\ntuple<double, double, int> MeshOptimize3d :: UpdateBadness()\n{\n  static Timer tbad(\"UpdateBadness\");\n  RegionTimer reg(tbad);\n\n  double totalbad = 0.0;\n  double maxbad = 0.0;\n  atomic<int> bad_elements = 0;\n\n  ParallelForRange(Range(mesh.GetNE()), [&] (auto myrange) {\n    double totalbad_local = 0.0;\n    double maxbad_local = 0.0;\n    int bad_elements_local = 0;\n    for (ElementIndex ei : myrange)\n    {\n      auto & el = mesh[ei];\n      if(mp.only3D_domain_nr && mp.only3D_domain_nr != el.GetIndex()) continue;\n      if(!el.BadnessValid())\n        el.SetBadness(CalcBad(mesh.Points(), el, 0));\n      double bad = el.GetBadness();\n      totalbad_local += bad;\n      maxbad_local = max(maxbad_local, bad);\n      if(bad > min_badness)\n        bad_elements_local++;\n    }\n    AtomicAdd(totalbad, totalbad_local);\n    AtomicMax(maxbad, maxbad_local);\n    bad_elements += bad_elements_local;\n  });\n  return {totalbad, maxbad, bad_elements};\n}\n\nbool MeshOptimize3d :: HasBadElement(FlatArray<ElementIndex> els)\n{\n  for(auto ei : els)\n    if(mesh[ei].GetBadness()>min_badness)\n      return true;\n  return false;\n}\n\nbool MeshOptimize3d :: HasIllegalElement(FlatArray<ElementIndex> els)\n{\n  for(auto ei : els)\n    if(!mesh.LegalTet(mesh[ei]))\n      return true;\n  return false;\n}\n\nbool MeshOptimize3d :: NeedsOptimization(FlatArray<ElementIndex> els)\n{\n  if(goal == OPT_LEGAL) return HasIllegalElement(els);\n  if(goal == OPT_QUALITY) return HasBadElement(els);\n  return true;\n}\n\n\n/*\n  Combine two points to one.\n  Set new point into the center, if both are\n  inner points.\n  Connect inner point to boundary point, if one\n  point is inner point.\n*/\ndouble MeshOptimize3d :: CombineImproveEdge (\n                            Table<ElementIndex, PointIndex> & elements_of_point,\n                            PointIndex pi0, PointIndex pi1,\n                            FlatArray<bool, PointIndex> is_point_removed,\n                            bool check_only)\n{\n  if (pi1 < pi0) Swap (pi0, pi1);\n  if(is_point_removed[pi0] || is_point_removed[pi1]) return false;\n\n  MeshPoint p0 = mesh[pi0];\n  MeshPoint p1 = mesh[pi1];\n\n  if (p1.Type() != INNERPOINT)\n      return false;\n\n  ArrayMem<ElementIndex, 50> has_one_point;\n  ArrayMem<ElementIndex, 50> has_both_points;\n\n  for (auto ei : elements_of_point[pi0] )\n  {\n      Element & elem = mesh[ei];\n      if (elem.IsDeleted()) return false;\n      if(elem.GetType() != TET) return false; // TODO: implement case where pi0 or pi1 is top of a pyramid\n\n      if (elem[0] == pi1 || elem[1] == pi1 || elem[2] == pi1 || elem[3] == pi1)\n      {\n          if(!has_both_points.Contains(ei))\n            has_both_points.Append (ei);\n      }\n      else\n      {\n          if(!has_one_point.Contains(ei))\n              has_one_point.Append (ei);\n      }\n  }\n\n  for (auto ei : elements_of_point[pi1] )\n  {\n      Element & elem = mesh[ei];\n      if (elem.IsDeleted()) return false;\n      if(elem.GetType() != TET) return false; // TODO: implement case where pi0 or pi1 is top of a pyramid\n\n      if (elem[0] == pi0 || elem[1] == pi0 || elem[2] == pi0 || elem[3] == pi0)\n      {\n          ;\n      }\n      else\n      {\n          if(!has_one_point.Contains(ei))\n            has_one_point.Append (ei);\n      }\n  }\n\n  double badness_old = 0.0;\n  for (auto ei : has_one_point)\n      badness_old += mesh[ei].GetBadness();\n  for (auto ei : has_both_points)\n      badness_old += mesh[ei].GetBadness();\n\n  if (goal == OPT_CONFORM && p0.Type() <= EDGEPOINT) {\n    // check if the optimization improves conformity with free segments\n    std::set<PointIndex> edges_before, edges_after;\n\n    for (auto ei : has_one_point) {\n        const auto el = mesh[ei];\n        for(auto i : Range(6)) {\n          auto e0 = el[tetedges[i][0]];\n          auto e1 = el[tetedges[i][1]];\n          if(e0 == pi0 || e1 == pi0) edges_before.insert(e0 == pi0 ? e1 : e0);\n          if(e0 == pi1 || e1 == pi1) edges_after.insert(e0 == pi1 ? e1 : e0);\n        }\n    }\n\n    for(auto new_edge : edges_after) {\n      if (edges_before.count(new_edge) == 0 && mesh[new_edge].Type() <= EDGEPOINT && mesh.BoundaryEdge (new_edge, pi0))\n        badness_old += GetLegalPenalty();\n    }\n  }\n\n  MeshPoint pnew = p0;\n  if (p0.Type() == INNERPOINT)\n      pnew = Center (p0, p1);\n\n  ArrayMem<double, 50> one_point_badness(has_one_point.Size());\n\n  double badness_new = 0;\n  for (auto i : Range(has_one_point))\n  {\n      const Element & elem = mesh[has_one_point[i]];\n      double badness = CalcBadReplacePoints (mesh.Points(), mp, elem, 0, pi0, pi1, pnew);\n      badness_new += badness;\n      one_point_badness[i] = badness;\n  }\n\n  // Check if changed tets are topologically legal\n  if (p0.Type() != INNERPOINT)\n  {\n      for (auto ei : has_one_point)\n      {\n          Element elem = mesh[ei];\n          // int l;\n          for (int l = 0; l < 4; l++)\n              if (elem[l] == pi1)\n              {\n                  elem[l] = pi0;\n                  break;\n              }\n\n          elem.Touch();\n          if (!mesh.LegalTet(elem))\n              badness_new += GetLegalPenalty();\n      }\n  }\n\n  double d_badness = badness_new / has_one_point.Size() - badness_old / (has_one_point.Size()+has_both_points.Size());\n\n  // Do the actual combine operation\n  if (d_badness < 0.0 && !check_only)\n  {\n      is_point_removed[pi1] = true;\n      mesh[pi0] = pnew;\n\n      for (auto ei : elements_of_point[pi1])\n      {\n          Element & elem = mesh[ei];\n          if (elem.IsDeleted()) continue;\n\n          for (int l = 0; l < elem.GetNP(); l++)\n              if (elem[l] == pi1)\n                  elem[l] = pi0;\n\n          elem.Touch();\n          if (!mesh.LegalTet (elem))\n              (*testout) << \"illegal tet \" << ei << endl;\n      }\n\n      for (auto i : Range(has_one_point))\n          mesh[has_one_point[i]].SetBadness(one_point_badness[i]);\n\n      for (auto ei : has_both_points)\n      {\n          mesh[ei].Touch();\n          mesh[ei].Delete();\n      }\n  }\n\n  return d_badness;\n}\n\nvoid MeshOptimize3d :: CombineImprove ()\n{\n  static Timer t(\"MeshOptimize3d::CombineImprove\"); RegionTimer reg(t);\n  static Timer topt(\"Optimize\");\n  static Timer tsearch(\"Search-combine\");\n  static Timer tbuild_elements_table(\"Build elements table\");\n\n  mesh.BuildBoundaryEdges(false);\n  \n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int ntasks = 4*ngcore::TaskManager::GetNumThreads();\n\n  Array<bool, PointIndex> is_point_removed (np);\n  is_point_removed = false;\n\n  PrintMessage (3, \"CombineImprove\");\n  (*testout)  << \"Start CombineImprove\" << \"\\n\";\n\n  //  mesh.CalcSurfacesOfNode ();\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Combine Improve\";\n\n\n  UpdateBadness();\n\n  if (goal == OPT_QUALITY && testout->good())\n    {\n      double totalbad = mesh.CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << totalbad << endl;\n    }\n\n  auto elementsonnode = mesh.CreatePoint2ElementTable(nullopt, mp.only3D_domain_nr);\n\n  Array<std::tuple<PointIndex,PointIndex>> edges;\n  BuildEdgeList(mesh, elementsonnode, edges);\n\n  // Find edges with improvement\n  Array<std::tuple<double, int>> combine_candidate_edges(edges.Size());\n  std::atomic<int> improvement_counter(0);\n\n  tsearch.Start();\n  ParallelForRange(Range(edges), [&] (auto myrange)\n  {\n    for(auto i : myrange)\n    {\n      auto [p0,p1] = edges[i];\n      double d_badness = CombineImproveEdge (elementsonnode, p0, p1, is_point_removed, true);\n      if(d_badness<0.0)\n      {\n        int index = improvement_counter++;\n        combine_candidate_edges[index] = make_tuple(d_badness, i);\n      }\n    }\n  }, ntasks);\n  tsearch.Stop();\n\n  auto edges_with_improvement = combine_candidate_edges.Part(0, improvement_counter.load());\n\n  QuickSort(edges_with_improvement);\n  PrintMessage(5, edges.Size(), \" edges\");\n  PrintMessage(5, edges_with_improvement.Size(), \" edges with improvement\");\n\n  // Apply actual optimizations\n  topt.Start();\n  int cnt = 0;\n  for(auto [d_badness, ei] : edges_with_improvement)\n  {\n      auto [p0,p1] = edges[ei];\n      if (CombineImproveEdge (elementsonnode, p0, p1, is_point_removed, false) < 0.0)\n        cnt++;\n  }\n  topt.Stop();\n\n  mesh.Compress();\n  mesh.MarkIllegalElements();\n\n  PrintMessage (5, cnt, \" elements combined\");\n  (*testout) << \"CombineImprove done\" << \"\\n\";\n\n  if (goal == OPT_QUALITY && testout->good())\n    {\n      double totalbad = mesh.CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << totalbad << endl;\n\n      int cntill = 0;\n      // for (ElementIndex ei = 0; ei < ne; ei++)\n      for (ElementIndex ei : ngcore::T_Range<ElementIndex>(ne))\n\tif(!(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()))\n\t  if (!mesh.LegalTet (mesh[ei]))\n\t    cntill++;\n\n      PrintMessage (5, cntill, \" illegal tets\");\n    }\n  multithread.task = savetask;\n} \n\n\n\ndouble MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<PointIndices<3>> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only)\n{\n  double d_badness = 0.0;\n  // int cnt = 0;\n\n  ArrayMem<ElementIndex, 20> hasbothpoints;\n\n  if (mesh.BoundaryEdge (pi1, pi2)) return 0.0;\n\n  for (ElementIndex ei : elementsonnode[pi1])\n    {\n      Element & el = mesh[ei];\n\n      if(el.IsDeleted()) return 0.0;\n      if (mesh[ei].GetType() != TET) return 0.0;\n\n      bool has1 = el.PNums().Contains(pi1);\n      bool has2 = el.PNums().Contains(pi2);\n\n      if (has1 && has2)\n          if (!hasbothpoints.Contains (ei))\n              hasbothpoints.Append (ei);\n    }\n\n  if(mp.only3D_domain_nr)\n      for(auto ei : hasbothpoints)\n          if(mp.only3D_domain_nr != mesh[ei].GetIndex())\n              return 0.0;\n\n  if (!NeedsOptimization(hasbothpoints))\n    return 0.0;\n\n  double bad1 = 0.0;\n  double bad1_max = 0.0;\n  for (ElementIndex ei : hasbothpoints)\n    {\n      double bad = mesh[ei].GetBadness();\n      bad1 += bad;\n      bad1_max = max(bad1_max, bad);\n    }\n\n  if(bad1_max < 100.0)\n      return 0.0;\n\n  bool puretet = 1;\n  for (ElementIndex ei : hasbothpoints)\n      if (mesh[ei].GetType() != TET)\n          puretet = 0;\n  if (!puretet) return 0.0;\n\n  Point3d p1 = mesh[pi1];\n  Point3d p2 = mesh[pi2];\n\n  locfaces.SetSize(0);\n  for (ElementIndex ei : hasbothpoints)\n    {\n      const Element & el = mesh[ei];\n\n      for (int l = 0; l < 4; l++)\n          if (el[l] == pi1 || el[l] == pi2)\n            {\n              PointIndices<3> i3;\n              Element2d face(TRIG);\n              el.GetFace (l+1, face);\n              for (int kk = 0; kk < 3; kk++)\n                i3[kk] = face[kk];\n              locfaces.Append (i3);\n            }\n    }\n\n  PointFunction1 pf (mesh.Points(), locfaces, mp, -1);\n  OptiParameters par;\n  par.maxit_linsearch = 50;\n  par.maxit_bfgs = 20;\n\n  Point3d pnew = Center (p1, p2);\n  Vector px(3);\n  px(0) = pnew.X();\n  px(1) = pnew.Y();\n  px(2) = pnew.Z();\n\n  if (bad1_max > 0.1 * badmax)\n    {\n      int pok = pf.Func (px) < 1e10;\n      if (!pok)\n        pok = FindInnerPoint (mesh.Points(), locfaces, pnew);\n\n      if(pok)\n        {\n          px(0) = pnew.X();\n          px(1) = pnew.Y();\n          px(2) = pnew.Z();\n          BFGS (px, pf, par);\n          pnew.X() = px(0);\n          pnew.Y() = px(1);\n          pnew.Z() = px(2);\n        }\n    }\n\n  double bad2 = pf.Func (px);\n\n  for (int k = 0; k < hasbothpoints.Size(); k++)\n    {\n      Element & oldel = mesh[hasbothpoints[k]];\n      Element newel1 = oldel;\n      Element newel2 = oldel;\n\n      newel1.Touch();\n      newel2.Touch();\n\n      Point<3> pel1[4];\n      Point<3> pel2[4];\n      for (int l = 0; l < 4; l++)\n        {\n          pel1[l] = pel2[l] = mesh[oldel[l]];\n          if (newel1[l] == pi2) {\n            newel1[l] = ptmp;\n            pel1[l] = pnew;\n          }\n          if (newel2[l] == pi1) {\n            newel2[l] = ptmp;\n            pel2[l] = pnew;\n          }\n        }\n\n      if (!mesh.LegalTet (oldel)) return 0.0;\n      if (!mesh.LegalTet (newel1)) return 0.0;\n      if (!mesh.LegalTet (newel2)) return 0.0;\n\n      if( WrongOrientation(pel1[0], pel1[1], pel1[2], pel1[3]) ||\n          WrongOrientation(pel2[0], pel2[1], pel2[2], pel2[3]) )\n        return 0.0;\n    }\n\n  if(bad2 >= 1e24) return 0.0;\n  d_badness = bad2-bad1;\n  if(check_only)\n      return d_badness;\n\n  if (d_badness<0.0)\n    {\n      // cnt++;\n\n      PointIndex pinew = mesh.AddPoint (pnew);\n\n      for (ElementIndex ei : hasbothpoints)\n        {\n          Element & oldel = mesh[ei];\n          Element newel1 = oldel;\n          Element newel2 = oldel;\n\n          newel1.Touch();\n          newel2.Touch();\n\n          for (int l = 0; l < 4; l++)\n            {\n              if (newel1[l] == pi2) newel1[l] = pinew;\n              if (newel2[l] == pi1) newel2[l] = pinew;\n            }\n\n          oldel.Touch();\n          oldel.Delete();\n\n          mesh.AddVolumeElement (newel1);\n          mesh.AddVolumeElement (newel2);\n        }\n    }\n  return d_badness;\n}\n\nvoid MeshOptimize3d :: SplitImprove ()\n{\n  static Timer t(\"MeshOptimize3d::SplitImprove\"); RegionTimer reg(t);\n  static Timer topt(\"Optimize\");\n  static Timer tsearch(\"Search-split\");\n\n  // int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  double bad = 0.0;\n  double badmax = 0.0;\n\n  auto elementsonnode = mesh.CreatePoint2ElementTable(nullopt, mp.only3D_domain_nr);\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Split Improve\";\n\n  PrintMessage (3, \"SplitImprove\");\n  (*testout)  << \"start SplitImprove\" << \"\\n\";\n  mesh.BuildBoundaryEdges(false);\n\n  UpdateBadness();\n\n  if (goal == OPT_QUALITY && testout->good())\n    {\n      bad = mesh.CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << bad << endl;\n    }\n\n  Array<std::tuple<PointIndex,PointIndex>> edges;\n  BuildEdgeList(mesh, elementsonnode, edges);\n\n  // Find edges with improvement\n  Array<std::tuple<double, int>> candidate_edges(edges.Size());\n  std::atomic<int> improvement_counter(0);\n  auto ptmp = mesh.AddPoint( {0,0,0} );\n\n  tsearch.Start();\n  ParallelForRange(Range(edges), [&] (auto myrange)\n  {\n    NgArray<PointIndices<3>> locfaces;\n\n    for(auto i : myrange)\n    {\n      auto [p0,p1] = edges[i];\n      double d_badness = SplitImproveEdge (elementsonnode, locfaces, badmax, p0, p1, ptmp, true);\n      if(d_badness<0.0)\n      {\n        int index = improvement_counter++;\n        candidate_edges[index] = make_tuple(d_badness, i);\n      }\n    }\n  }, ngcore::TasksPerThread(4));\n  tsearch.Stop();\n\n  auto edges_with_improvement = candidate_edges.Part(0, improvement_counter.load());\n\n  QuickSort(edges_with_improvement);\n  PrintMessage(5, edges.Size(), \" edges\");\n  PrintMessage(5, edges_with_improvement.Size(), \" edges with improvement\");\n\n  // Apply actual optimizations\n  topt.Start();\n  int cnt = 0;\n  NgArray<PointIndices<3>> locfaces;\n  for(auto [d_badness, ei] : edges_with_improvement)\n  {\n      auto [p0,p1] = edges[ei];\n      if (SplitImproveEdge (elementsonnode, locfaces, badmax, p0, p1, ptmp, false) < 0.0)\n        cnt++;\n  }\n  topt.Stop();\n  mesh.Compress();\n  PrintMessage (5, cnt, \" splits performed\");\n  (*testout) << \"Splitt - Improve done\" << \"\\n\";\n\n  if (goal == OPT_QUALITY)\n    {\n      if(testout->good())\n      {\n        bad = mesh.CalcTotalBad (mp);\n        (*testout) << \"Total badness = \" << bad << endl;\n      }\n\n      [[maybe_unused]] int cntill = 0;\n      ne = mesh.GetNE();\n      // for (ElementIndex ei = 0; ei < ne; ei++)\n      for (auto ei : ngcore::T_Range<ElementIndex>(ne))\n        if (!mesh.LegalTet (mesh[ei]))\n          cntill++;\n      //      cout << cntill << \" illegal tets\" << endl;\n    }\n\n  multithread.task = savetask;\n}\n\ndouble MeshOptimize3d :: SwapImproveEdge (\n        const TBitArray<ElementIndex> * working_elements,\n        Table<ElementIndex, PointIndex> & elementsonnode,\n        INDEX_3_HASHTABLE<int> & faces,\n        PointIndex pi1, PointIndex pi2, bool check_only)\n{\n  ArrayMem<ElementIndex, 20> hasbothpoints;\n\n  double d_badness = 0.0;\n  if (pi2 < pi1) Swap (pi1, pi2);\n\n  if (mesh.BoundaryEdge (pi1, pi2)) return 0.0;\n\n\n  hasbothpoints.SetSize (0);\n  for (ElementIndex elnr : elementsonnode[pi1])\n    {\n      bool has1 = 0, has2 = 0;\n      const Element & elem = mesh[elnr];\n\n      if (elem.IsDeleted()) return 0.0;\n\n      for (int l = 0; l < elem.GetNP(); l++)\n        {\n          if (elem[l] == pi1) has1 = 1;\n          if (elem[l] == pi2) has2 = 1;\n        }\n\n      if (has1 && has2)\n        { // only once\n          if (hasbothpoints.Contains (elnr))\n              has1 = false;\n\n          if (has1)\n            {\n              hasbothpoints.Append (elnr);\n            }\n        }\n    }\n\n  for (ElementIndex ei : hasbothpoints)\n    {\n      if (mesh[ei].GetType () != TET)\n          return 0.0;\n\n      if (mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex())\n          return 0.0;\n\n\n      if ((mesh.ElementType(ei)) == FIXEDELEMENT)\n          return 0.0;\n\n      if(working_elements &&\n              ei < working_elements->Size() &&\n         !working_elements->Test(ei))\n          return 0.0;\n\n      if (mesh[ei].IsDeleted())\n          return 0.0;\n\n      if(WrongOrientation(mesh.Points(), mesh[ei]))\n          return 0.0;\n    }\n\n  if(!NeedsOptimization(hasbothpoints))\n    return 0.0;\n\n  int nsuround = hasbothpoints.Size();\n  int mattyp = mesh[hasbothpoints[0]].GetIndex();\n\n  /*\n    // unused ? \n  auto fix_orientation = [&] (Element & el) {\n    if (WrongOrientation (mesh.Points(), el))\n      el.Invert();\n  };\n  */\n  \n  auto El = [&] ( PointIndex pi0, PointIndex pi1, PointIndex pi2, PointIndex pi3) -> Element {\n    Element el(TET);\n    el[0] = pi0;\n    el[1] = pi1;\n    el[2] = pi2;\n    el[3] = pi3;\n    el.SetIndex (mattyp);\n    // fix_orientation(el);\n    return el;\n  };\n\n  auto combined_badness = [&] (std::initializer_list<Element> els, bool apply_illegal_penalty = true) {\n    double bad = 0.0;\n    bool have_illegal = false;\n    for (auto el : els) {\n      bad += CalcBad(mesh.Points(), el, 0);\n      if(apply_illegal_penalty && !have_illegal) {\n        el.Touch();\n        have_illegal = !mesh.LegalTet(el);\n      }\n    }\n    if(have_illegal && apply_illegal_penalty)\n      bad += GetLegalPenalty();\n    return bad;\n  };\n\n  if ( nsuround == 3 )\n    {\n      PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID), pi5(PointIndex::INVALID);\n\n      Element & elem = mesh[hasbothpoints[0]];\n      for (int l = 0; l < 4; l++)\n          if (elem[l] != pi1 && elem[l] != pi2)\n            {\n              pi4 = pi3;\n              pi3 = elem[l];\n            }\n\n      auto el31 = El(pi1, pi2, pi3, pi4);\n      if (WrongOrientation (mesh.Points(), el31))\n        {\n          Swap (pi3, pi4);\n          el31[2] = pi3;\n          el31[3] = pi4;\n        }\n\n      pi5.Invalidate();\n      for (int k = 0; k < 3; k++)   // JS, 201212\n        {\n          const Element & elemk = mesh[hasbothpoints[k]];\n          bool has1 = false;\n          for (int l = 0; l < 4; l++)\n              if (elemk[l] == pi4)\n                  has1 = true;\n          if (has1)\n            {\n              for (int l = 0; l < 4; l++)\n                  if (elemk[l] != pi1 && elemk[l] != pi2 && elemk[l] != pi4)\n                      pi5 = elemk[l];\n            }\n        }\n\n      if (!pi5.IsValid())\n          throw NgException(\"Illegal state observed in SwapImprove\");\n\n\n      auto el32 = El(pi1, pi2, pi4, pi5);\n      auto el33 = El(pi1, pi2, pi5, pi3);\n\n      auto el21 = El(pi3, pi4, pi5, pi2);\n      auto el22 = El(pi5, pi4, pi3, pi1);\n\n      double bad1 = combined_badness({el31, el32, el33});\n      double bad2 = combined_badness({el21, el22});\n\n      if ((goal == OPT_CONFORM) && NotTooBad(bad1, bad2))\n        {\n          PointIndices<3> face(pi3, pi4, pi5);\n          face.Sort();\n          if (faces.Used(face))\n            {\n              // (*testout) << \"3->2 swap, could improve conformity, bad1 = \" << bad1\n              //\t\t\t\t << \", bad2 = \" << bad2 << endl;\n                bad2 = bad1 + IMPROVEMENT_CONFORMING_EDGE;\n            }\n        }\n\n      if (bad2 < bad1)\n        {\n          //\t\t  (*mycout) << \"3->2 \" << flush;\n          //\t\t  (*testout) << \"3->2 conversion\" << endl;\n          d_badness = bad2-bad1;\n          if(check_only)\n              return d_badness;\n\n\n          /*\n             (*testout) << \"3->2 swap, old els = \" << endl\n             << mesh[hasbothpoints[0]] << endl\n             << mesh[hasbothpoints[1]] << endl\n             << mesh[hasbothpoints[2]] << endl\n             << \"new els = \" << endl\n             << el21 << endl\n             << el22 << endl;\n             */\n\n          mesh[hasbothpoints[0]].Delete();\n          mesh[hasbothpoints[1]].Delete();\n          mesh[hasbothpoints[2]].Delete();\n\n          mesh.AddVolumeElement(el21);\n          mesh.AddVolumeElement(el22);\n        }\n    }\n\n  if (nsuround == 4)\n    {\n      PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID);\n      PointIndex pi5(PointIndex::INVALID), pi6(PointIndex::INVALID);\n\n      const Element & elem1 = mesh[hasbothpoints[0]];\n      for (int l = 0; l < 4; l++)\n          if (elem1[l] != pi1 && elem1[l] != pi2)\n            {\n              pi4 = pi3;\n              pi3 = elem1[l];\n            }\n\n      auto el1 = El(pi1, pi2, pi3, pi4);\n\n      if (WrongOrientation (mesh.Points(), el1))\n        {\n          Swap (pi3, pi4);\n          el1[2] = pi3;\n          el1[3] = pi4;\n        }\n\n      pi5.Invalidate();\n      for (int k = 0; k < 4; k++)\n        {\n          const Element & elem = mesh[hasbothpoints[k]];\n          bool has1 = elem.PNums().Contains(pi4);\n          if (has1)\n            {\n              for (int l = 0; l < 4; l++)\n                  if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4)\n                      pi5 = elem[l];\n            }\n        }\n\n      pi6.Invalidate();\n      for (int k = 0; k < 4; k++)\n        {\n          const Element & elem = mesh[hasbothpoints[k]];\n          bool has1 = elem.PNums().Contains(pi3);\n          if (has1)\n            {\n              for (int l = 0; l < 4; l++)\n                  if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi3)\n                      pi6 = elem[l];\n            }\n        }\n\n      el1 = El(pi1, pi2, pi3, pi4);\n      auto el2 = El(pi1, pi2, pi4, pi5);\n      auto el3 = El(pi1, pi2, pi5, pi6);\n      auto el4 = El(pi1, pi2, pi6, pi3);\n      double bad1 = combined_badness({el1, el2, el3, el4}, goal != OPT_CONFORM);\n\n      el1 = El(pi3, pi5, pi2, pi4);\n      el2 = El(pi3, pi5, pi4, pi1);\n      el3 = El(pi3, pi5, pi1, pi6);\n      el4 = El(pi3, pi5, pi6, pi2);\n      double bad2 = combined_badness({el1, el2, el3, el4}, goal != OPT_CONFORM);\n\n      auto el1b = El(pi4, pi6, pi3, pi2);\n      auto el2b = El(pi4, pi6, pi2, pi5);\n      auto el3b = El(pi4, pi6, pi5, pi1);\n      auto el4b = El(pi4, pi6, pi1, pi3);\n      double bad3 = combined_badness({el1b, el2b, el3b, el4b}, goal != OPT_CONFORM);\n\n      bool swap2=false;\n      bool swap3=false;\n\n      if (goal == OPT_CONFORM)\n        {\n          swap2 = mesh.BoundaryEdge (pi3, pi5) && NotTooBad(bad1, bad2);\n          swap3 = mesh.BoundaryEdge (pi4, pi6) && NotTooBad(bad1, bad3);\n\n          if(swap2 || swap3)\n            d_badness = IMPROVEMENT_CONFORMING_EDGE;\n        }\n\n      if (goal != OPT_CONFORM || (!swap2 && !swap3))\n        {\n          swap2 = (bad2 < bad1) && (bad2 < bad3);\n          swap3 = !swap2 && (bad3 < bad1);\n          d_badness = swap2 ? bad2-bad1 : bad3-bad1;\n        }\n\n      if(check_only)\n          return d_badness;\n\n      if (swap2)\n        {\n          for (auto i : IntRange(4))\n              mesh[hasbothpoints[i]].Delete();\n\n          mesh.AddVolumeElement (el1);\n          mesh.AddVolumeElement (el2);\n          mesh.AddVolumeElement (el3);\n          mesh.AddVolumeElement (el4);\n        }\n      else if (swap3)\n        {\n          for (auto i : IntRange(4))\n              mesh[hasbothpoints[i]].Delete();\n\n          mesh.AddVolumeElement (el1b);\n          mesh.AddVolumeElement (el2b);\n          mesh.AddVolumeElement (el3b);\n          mesh.AddVolumeElement (el4b);\n        }\n    }\n\n  // if (goal == OPT_QUALITY)\n  if (nsuround >= 5)\n    {\n      PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID);\n\n      NgArrayMem<PointIndex, 50> suroundpts(nsuround);\n      NgArrayMem<bool, 50> tetused(nsuround);\n\n      Element & elem = mesh[hasbothpoints[0]];\n\n      for (int l = 0; l < 4; l++)\n          if (elem[l] != pi1 && elem[l] != pi2)\n            {\n              pi4 = pi3;\n              pi3 = elem[l];\n            }\n\n      if (WrongOrientation (mesh.Points(), El(pi1, pi2, pi3, pi4)))\n          Swap (pi3, pi4);\n\n      // suroundpts.SetSize (nsuround);\n      suroundpts = PointIndex::INVALID;\n      suroundpts[0] = pi3;\n      suroundpts[1] = pi4;\n\n      tetused = false;\n      tetused[0] = true;\n\n      for (int l = 2; l < nsuround; l++)\n        {\n          PointIndex oldpi = suroundpts[l-1];\n          PointIndex newpi;\n          newpi.Invalidate();\n\n          for (int k = 0; k < nsuround && !newpi.IsValid(); k++)\n              if (!tetused[k])\n                {\n                  const Element & nel = mesh[hasbothpoints[k]];\n                  for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++)\n                      if (nel[k2] == oldpi)\n                        {\n                          newpi = nel[0] - pi1 + nel[1] - pi2 + nel[2] - oldpi + nel[3];\n                          tetused[k] = true;\n                          suroundpts[l] = newpi;\n                        }\n                }\n        }\n\n\n      double bad1 = 0;\n      for (auto k : Range(nsuround))\n          bad1 += CalcBad (mesh.Points(), El(pi1, pi2, suroundpts[k], suroundpts[(k+1) % nsuround]), 0);\n\n      //  (*testout) << \"nsuround = \" << nsuround << \" bad1 = \" << bad1 << endl;\n\n\n      int bestl = -1;\n      int confface = -1;\n      int confedge = -1;\n      double badopt = bad1;\n\n      for (int l = 0; l < nsuround; l++)\n        {\n          double bad2 = 0;\n\n          for (int k = l+1; k <= nsuround + l - 2; k++)\n            {\n              PointIndex pil = suroundpts[l];\n              PointIndex pik0 = suroundpts[k % nsuround];\n              PointIndex pik1 = suroundpts[(k+1) % nsuround];\n\n              bad2 += combined_badness({El(pil, pik0, pik1, pi2)});\n              bad2 += combined_badness({El(pil, pik1, pik0, pi1)});\n            }\n          // (*testout) << \"bad2,\" << l << \" = \" << bad2 << endl;\n\n          if ( bad2 < badopt )\n            {\n              bestl = l;\n              badopt = bad2;\n            }\n\n\n          if (goal == OPT_CONFORM)\n            {\n              bool nottoobad = NotTooBad(bad1, bad2);\n\n              for (int k = l+1; k <= nsuround + l - 2; k++)\n                {\n                  PointIndices<3> hi3(suroundpts[l],\n                                      suroundpts[k % nsuround],\n                                      suroundpts[(k+1) % nsuround]);\n                  hi3.Sort();\n                  if (faces.Used(hi3))\n                    {\n                      // (*testout) << \"could improve face conformity, bad1 = \" << bad1\n                      // << \", bad 2 = \" << bad2 << \", nottoobad = \" << nottoobad << endl;\n                      if (nottoobad)\n                          confface = l;\n                    }\n                }\n\n              for (int k = l+2; k <= nsuround+l-2; k++)\n                {\n                  if (mesh.BoundaryEdge (suroundpts[l],\n                              suroundpts[k % nsuround]))\n                    {\n                      /*\n                       *testout << \"could improve edge conformity, bad1 = \" << bad1\n                       << \", bad 2 = \" << bad2 << \", nottoobad = \" << nottoobad << endl;\n                       */\n                      if (nottoobad)\n                          confedge = l;\n                    }\n                }\n            }\n        }\n\n      if (confedge != -1)\n          bestl = confedge;\n      if (confface != -1)\n          bestl = confface;\n\n      if(confface != -1 || confedge != -1)\n          badopt = bad1 + IMPROVEMENT_CONFORMING_EDGE;\n\n      if (bestl != -1)\n        {\n          // (*mycout) << nsuround << \"->\" << 2 * (nsuround-2) << \" \" << flush;\n          d_badness = badopt-bad1;\n          if(check_only)\n              return d_badness;\n\n          for (int k = bestl+1; k <= nsuround + bestl - 2; k++)\n            {\n              // int k1;\n              PointIndex pi = suroundpts[bestl];\n              PointIndex pik0 = suroundpts[k % nsuround];\n              PointIndex pik1 = suroundpts[(k+1) % nsuround];\n\n              auto el = El(pi, pik0, pik1, pi2);\n              /*\n                 (*testout) << nsuround << \"-swap, new el,top = \"\n                 << el << endl;\n                 */\n              mesh.AddVolumeElement (el);\n\n              el = El(pi, pik1, pik0, pi1);\n              /*\n                 (*testout) << nsuround << \"-swap, new el,bot = \"\n                 << el << endl;\n                 */\n\n              mesh.AddVolumeElement (el);\n            }\n\n          for (int k = 0; k < nsuround; k++)\n            {\n              Element & rel = mesh[hasbothpoints[k]];\n              /*\n                 (*testout) << nsuround << \"-swap, old el = \"\n                 << rel << endl;\n                 */\n              rel.Delete();\n              for (int k1 = 0; k1 < 4; k1++)\n                  rel[k1].Invalidate();\n            }\n        }\n    }\n  return d_badness;\n}\n\nvoid MeshOptimize3d :: SwapImprove (const TBitArray<ElementIndex> * working_elements)\n{\n  static Timer t(\"MeshOptimize3d::SwapImprove\"); RegionTimer reg(t);\n  static Timer tloop(\"MeshOptimize3d::SwapImprove loop\");\n\n  int cnt = 0;\n\n  // int np = mesh.GetNP();\n  // int ne = mesh.GetNE();\n\n  mesh.BuildBoundaryEdges(false);\n  TBitArray<PointIndex> free_points(mesh.GetNP());\n  free_points.Clear();\n\n  ParallelForRange(mesh.VolumeElements().Range(), [&] (auto myrange)\n      {\n        for (ElementIndex eli : myrange)\n          {\n            const auto & el = mesh[eli];\n            if(el.Flags().fixed || el.GetType() != TET)\n              continue;\n\n            if(mp.only3D_domain_nr && mp.only3D_domain_nr != el.GetIndex())\n              continue;\n\n            for (auto pi : el.PNums())\n              if(!free_points[pi])\n                  free_points.SetBitAtomic(pi);\n          }\n      });\n\n  auto elementsonnode = mesh.CreatePoint2ElementTable(free_points, mp.only3D_domain_nr );\n\n  NgArray<ElementIndex> hasbothpoints;\n\n  PrintMessage (3, \"SwapImprove \");\n  (*testout) << \"\\n\" << \"Start SwapImprove\" << endl;\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Swap Improve\";\n\n  INDEX_3_HASHTABLE<int> faces(mesh.GetNOpenElements()/3 + 2);\n  if (goal == OPT_CONFORM)\n    {\n      for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n\t{\n\t  const Element2d & hel = mesh.OpenElement(i);\n\t  PointIndices<3> face(hel[0], hel[1], hel[2]);\n\t  face.Sort();\n\t  faces.Set (face, i);\n\t}\n    }\n\n  // Calculate total badness\n  if (goal == OPT_QUALITY && testout->good())\n    {\n      double bad1 = mesh.CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << bad1 << endl;\n    }\n\n  Array<std::tuple<PointIndex,PointIndex>> edges;\n  BuildEdgeList(mesh, elementsonnode, edges);\n\n  Array<std::tuple<double, int>> candidate_edges(edges.Size());\n  std::atomic<int> improvement_counter(0);\n\n  UpdateBadness();\n\n  tloop.Start();\n\n  auto num_elements_before = mesh.VolumeElements().Range().Next();\n\n  ParallelForRange(Range(edges), [&] (auto myrange)\n  {\n    for(auto i : myrange)\n    {\n      if (multithread.terminate)\n        break;\n\n      auto [pi0, pi1] = edges[i];\n      double d_badness = SwapImproveEdge (working_elements, elementsonnode, faces, pi0, pi1, true);\n      if(d_badness<0.0)\n      {\n        int index = improvement_counter++;\n        candidate_edges[index] = make_tuple(d_badness, i);\n      }\n    }\n  }, TasksPerThread (4));\n\n  auto edges_with_improvement = candidate_edges.Part(0, improvement_counter.load());\n  QuickSort(edges_with_improvement);\n\n  for(auto [d_badness, ei] : edges_with_improvement)\n  {\n      auto [pi0,pi1] = edges[ei];\n      if(SwapImproveEdge (working_elements, elementsonnode, faces, pi0, pi1, false) < 0.0)\n          cnt++;\n  }\n\n  tloop.Stop();\n\n  PrintMessage (5, cnt, \" swaps performed\");\n\n  if(goal == OPT_CONFORM)\n  {\n      // Remove open elements that were closed by new tets\n      auto & open_els = mesh.OpenElements();\n\n      for (auto & el : mesh.VolumeElements().Range( num_elements_before, mesh.VolumeElements().Range().Next() ))\n      {\n          for (auto i : Range(1,5))\n          {\n              Element2d sel;\n              el.GetFace(i, sel);\n              PointIndices<3> face(sel[0], sel[1], sel[2]);\n              face.Sort();\n              if(faces.Used(face))\n                  open_els[faces.Get(face)-1].Delete();\n          }\n      }\n\n      for(int i=open_els.Size()-1; i>=0; i--)\n          if(open_els[i].IsDeleted())\n              open_els.Delete(i);\n\n      mesh.DeleteBoundaryEdges();\n  }\n  mesh.Compress ();\n\n  multithread.task = savetask;\n}\n  \n\n\n\n\n\nvoid MeshOptimize3d :: SwapImproveSurface (\n\t\t\t\t\t   const TBitArray<ElementIndex> * working_elements,\n\t\t\t\t\t   const NgArray< idmap_type* > * idmaps)\n{\n  NgArray< idmap_type* > locidmaps;\n  const NgArray< idmap_type* > * used_idmaps;\n\n  if(idmaps)\n    used_idmaps = idmaps;\n  else\n    {\n      used_idmaps = &locidmaps;\n      \n      for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)\n\t{\n\t  if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)\n\t    {\n\t      locidmaps.Append(new idmap_type);\n\t      mesh.GetIdentifications().GetMap(i,*locidmaps.Last(),true);\n\t    }\n\t}\n    }\n\n\n  PointIndex pi1, pi2; // , pi3, pi4, pi5, pi6;\n  PointIndex pi1other, pi2other;\n  int cnt = 0;\n\n  //double bad1, bad2, bad3, sbad;\n  double bad1, sbad;\n  double h;\n\n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int nse = mesh.GetNSE();\n\n  int mattype, othermattype;\n\n  \n  // contains at least all elements at node\n  DynamicTable<ElementIndex,PointIndex> elementsonnode(np);\n  DynamicTable<SurfaceElementIndex,PointIndex> surfaceelementsonnode(np);\n  DynamicTable<int,PointIndex> surfaceindicesonnode(np);\n\n  NgArray<ElementIndex> hasbothpoints;\n  NgArray<ElementIndex> hasbothpointsother;\n\n  PrintMessage (3, \"SwapImproveSurface \");\n  (*testout) << \"\\n\" << \"Start SwapImproveSurface\" << endl;\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Swap Improve Surface\";\n    \n      \n  \n  // find elements on node\n  for (ElementIndex ei = 0; ei < ne; ei++)\n    for (int j = 0; j < mesh[ei].GetNP(); j++)\n      elementsonnode.Add (mesh[ei][j], ei);\n\n  for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n    for(int j=0; j<mesh[sei].GetNP(); j++)\n      {\n\tsurfaceelementsonnode.Add(mesh[sei][j], sei);\n\tif(!surfaceindicesonnode[mesh[sei][j]].Contains(mesh[sei].GetIndex()))\n\t  surfaceindicesonnode.Add(mesh[sei][j],mesh[sei].GetIndex());\n      }\n\n  bool periodic;\n  int idnum(-1);\n\n  // INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5);\n  INDEX_2_CLOSED_HASHTABLE<int> edgeused(12 * ne + 5);\n\n  for (ElementIndex ei = 0; ei < ne; ei++)\n    {\n      if (multithread.terminate)\n\tbreak;\n      \n      multithread.percent = 100.0 * (ei+1) / ne;\n\n      if (mesh.ElementType(ei) == FIXEDELEMENT)\n\tcontinue;\n      \n      if(working_elements && \n\t ei < working_elements->Size() &&\n\t !working_elements->Test(ei))\n\tcontinue;\n\n      if (mesh[ei].IsDeleted())\n\tcontinue;\n\n      if (goal == OPT_LEGAL && mesh.LegalTet (mesh[ei]))\n\tcontinue;\n\n      const Element & elemi = mesh[ei];\n      //Element elemi = mesh[ei];\n      if (elemi.IsDeleted()) continue;\n\n\n      mattype = elemi.GetIndex();\n\n      bool swapped = false;\n\n      for (int j = 0; !swapped && j < 6; j++)\n\t{\n\t  // loop over edges\n\n\t  \n\t  pi1 = elemi[tetedges[j][0]];\n\t  pi2 = elemi[tetedges[j][1]];\n\n\t  \n\t  if (pi2 < pi1)\n\t    Swap (pi1, pi2);\n\t    \t  \n\t  \n\t  bool found = false;\n\t  for(int k=0; !found && k<used_idmaps->Size(); k++)\n\t    {\n\t      if(pi2 < (*used_idmaps)[k]->Size() + IndexBASE<PointIndex>())\n\t\t{\n\t\t  pi1other = (*(*used_idmaps)[k])[pi1];\n\t\t  pi2other = (*(*used_idmaps)[k])[pi2];\n\t\t  found = (pi1other.IsValid() && pi2other.IsValid() && pi1other != pi1 && pi2other != pi2);\n\t\t  if(found)\n\t\t    idnum = k;\n\t\t}\n\t    }\n\t  if(found)\n\t    periodic = true;\n\t  else\n\t    {\n\t      periodic = false;\n\t      pi1other = pi1; pi2other = pi2;\n\t    }\n\n\n\t \t  \n\t  if (!mesh.BoundaryEdge (pi1, pi2) ||\n\t      mesh.IsSegment(pi1, pi2)) continue;\n\n\t  othermattype = -1;\n\n\t  \n\t  PointIndices<2> i2 (pi1, pi2);\n\t  i2.Sort();\n\t  if (edgeused.Used(i2)) continue;\n\t  edgeused.Set (i2, 1);\n\t  if(periodic)\n\t    {\n\t      i2[0] = pi1other;\n\t      i2[1] = pi2other;\n\t      i2.Sort();\n\t      edgeused.Set(i2,1);\n\t    }\n\t  \n\t  \n\t  hasbothpoints.SetSize (0);\n\t  hasbothpointsother.SetSize (0);\n\t  for (int k = 0; k < elementsonnode[pi1].Size(); k++)\n\t    {\n\t      bool has1 = false, has2 = false;\n\t      ElementIndex elnr = elementsonnode[pi1][k];\n\t      const Element & elem = mesh[elnr];\n\t      \n\t      if (elem.IsDeleted()) continue;\n\t      \n\t      for (int l = 0; l < elem.GetNP(); l++)\n\t\t{\n\t\t  if (elem[l] == pi1) has1 = true;\n\t\t  if (elem[l] == pi2) has2 = true;\n\t\t}\n\n\t      if (has1 && has2) \n\t\t{ \n\t\t  if(othermattype == -1 && elem.GetIndex() != mattype)\n\t\t    othermattype = elem.GetIndex();\n\n\t\t  if(elem.GetIndex() == mattype)\n\t\t    {\n\t\t      // only once\n\t\t      for (int l = 0; l < hasbothpoints.Size(); l++)\n\t\t\tif (hasbothpoints[l] == elnr)\n\t\t\t  has1 = 0;\n\t\t      \n\t\t      if (has1)\n\t\t\thasbothpoints.Append (elnr);\n\t\t    }\n\t\t  else if(elem.GetIndex() == othermattype)\n\t\t    {\n\t\t      // only once\n\t\t      for (int l = 0; l < hasbothpointsother.Size(); l++)\n\t\t\tif (hasbothpointsother[l] == elnr)\n\t\t\t  has1 = 0;\n\t\t      \n\t\t      if (has1)\n\t\t\thasbothpointsother.Append (elnr);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      cout << \"problem with domain indices\" << endl;\n\t\t      (*testout) << \"problem: mattype = \" << mattype << \", othermattype = \" << othermattype \n\t\t\t\t << \" elem \" << elem << \" mt \" << elem.GetIndex() << endl\n\t\t\t\t << \" pi1 \" << pi1 << \" pi2 \" << pi2 << endl;\n\t\t      (*testout) << \"hasbothpoints:\" << endl;\n\t\t      for(int ii=0; ii < hasbothpoints.Size(); ii++)\n\t\t\t(*testout) << mesh[hasbothpoints[ii]] << endl;\n\t\t      (*testout) << \"hasbothpointsother:\" << endl;\n\t\t      for(int ii=0; ii < hasbothpointsother.Size(); ii++)\n\t\t\t(*testout) << mesh[hasbothpointsother[ii]] << endl;\n\t\t    }\n\t\t}\n\t    }\n\n\t  if(hasbothpointsother.Size() > 0 && periodic)\n\t    throw NgException(\"SwapImproveSurface: Assumption about interface/periodicity wrong!\");\n\n\t  if(periodic)\n\t    {\n\t      for (int k = 0; k < elementsonnode[pi1other].Size(); k++)\n\t\t{\n\t\t  bool has1 = false, has2 = false;\n\t\t  ElementIndex elnr = elementsonnode[pi1other][k];\n\t\t  const Element & elem = mesh[elnr];\n\t      \n\t\t  if (elem.IsDeleted()) continue;\n\t      \n\t\t  for (int l = 0; l < elem.GetNP(); l++)\n\t\t    {\n\t\t      if (elem[l] == pi1other) has1 = true;\n\t\t      if (elem[l] == pi2other) has2 = true;\n\t\t    }\n\t\t  \n\t\t  if (has1 && has2) \n\t\t    { \n\t\t      if(othermattype == -1)\n\t\t\tothermattype = elem.GetIndex();\n\n\t\t      // only once\n\t\t      for (int l = 0; l < hasbothpointsother.Size(); l++)\n\t\t\tif (hasbothpointsother[l] == elnr)\n\t\t\t  has1 = 0;\n\t\t      \n\t\t      if (has1)\n\t\t\thasbothpointsother.Append (elnr);\n\t\t    }\n\t\t}\n\t    }\n\n\n\t  //for(k=0; k<hasbothpoints.Size(); k++)\n\t  //  (*testout) << \"hasbothpoints[\"<<k<<\"]: \" << mesh[hasbothpoints[k]] << endl;\n\n\t  \n\t  SurfaceElementIndex sel1=-1,sel2=-1;\n\t  SurfaceElementIndex sel1other=-1,sel2other=-1;\n\t  for(int k = 0; k < surfaceelementsonnode[pi1].Size(); k++)\n\t    {\n\t      bool has1 = false, has2 = false;\n\t      SurfaceElementIndex elnr = surfaceelementsonnode[pi1][k];\n\t      const Element2d & elem = mesh[elnr];\n\n\t      if (elem.IsDeleted()) continue;\n\n\t      for (int l = 0; l < elem.GetNP(); l++)\n\t\t{\n\t\t  if (elem[l] == pi1) has1 = true;\n\t\t  if (elem[l] == pi2) has2 = true;\n\t\t}\n\n\t      if(has1 && has2 && elnr != sel2)\n\t\t{\n\t\t  sel1 = sel2;\n\t\t  sel2 = elnr;\n\t\t}\n\t    }\n\n\t  if(periodic)\n\t    {\n\t      for(int k = 0; k < surfaceelementsonnode[pi1other].Size(); k++)\n\t\t{\n\t\t  bool has1 = false, has2 = false;\n\t\t  SurfaceElementIndex elnr = surfaceelementsonnode[pi1other][k];\n\t\t  const Element2d & elem = mesh[elnr];\n\n\t\t  if (elem.IsDeleted()) continue;\n\n\t\t  for (int l = 0; l < elem.GetNP(); l++)\n\t\t    {\n\t\t      if (elem[l] == pi1other) has1 = true;\n\t\t      if (elem[l] == pi2other) has2 = true;\n\t\t    }\n\n\t\t  if(has1 && has2 && elnr != sel2other)\n\t\t    {\n\t\t      sel1other = sel2other;\n\t\t      sel2other = elnr;\n\t\t    }\n\t\t}\n\t    }\n\t  else\n\t    {\n\t      sel1other = sel1; sel2other = sel2;\n\t    }\n\n\t  //(*testout) << \"sel1 \" << sel1 << \" sel2 \" << sel2 << \" el \" << mesh[sel1] << \" resp. \" << mesh[sel2] << endl;\n\n\t  PointIndex sp1(PointIndex::INVALID), sp2(PointIndex::INVALID);\n\t  PointIndex sp1other, sp2other;\n\t  for(int l=0; l<mesh[sel1].GetNP(); l++)\n\t    if(mesh[sel1][l] != pi1 && mesh[sel1][l] != pi2)\n\t      sp1 = mesh[sel1][l];\n\t  for(int l=0; l<mesh[sel2].GetNP(); l++)\n\t    if(mesh[sel2][l] != pi1 && mesh[sel2][l] != pi2)\n\t      sp2 = mesh[sel2][l];\n\n\t  if(periodic)\n\t    {\n\t      sp1other = (*(*used_idmaps)[idnum])[sp1];\n\t      sp2other = (*(*used_idmaps)[idnum])[sp2];\n\n\t      bool change = false;\n\t      for(int l=0; !change && l<mesh[sel1other].GetNP(); l++)\n\t\tchange = (sp2other == mesh[sel1other][l]);\n\t      \n\t      if(change)\n\t\t{\n\t\t  SurfaceElementIndex aux = sel1other;\n\t\t  sel1other = sel2other;\n\t\t  sel2other = aux;\n\t\t}\n\n\t    }\n\t  else\n\t    {\n\t      sp1other = sp1; sp2other = sp2;\n\t    }\n\t  \n\t  Vec<3> v1 = mesh[sp1]-mesh[pi1],\n\t    v2 = mesh[sp2]-mesh[pi1],\n\t    v3 = mesh[sp1]-mesh[pi2],\n\t    v4 = mesh[sp2]-mesh[pi2];\n\t  double vol = 0.5*(Cross(v1,v2).Length() + Cross(v3,v4).Length());\n\t  h = sqrt(vol);\n\t  h = 0;\n\n\t  sbad = CalcTriangleBadness (mesh[pi1],mesh[pi2],mesh[sp1],0,0) + \n\t    CalcTriangleBadness (mesh[pi2],mesh[pi1],mesh[sp2],0,0);\n\t  \n\n\n\t  bool puretet = true;\n\t  for (int k = 0; puretet && k < hasbothpoints.Size(); k++)\n\t    if (mesh[hasbothpoints[k]].GetType () != TET)\n\t      puretet = false;\n\t  for (int k = 0; puretet && k < hasbothpointsother.Size(); k++)\n\t    if (mesh[hasbothpointsother[k]].GetType () != TET)\n\t      puretet = false;\n\t  if (!puretet)\n\t    continue;\n\n\t  int nsuround = hasbothpoints.Size();\n\t  int nsuroundother = hasbothpointsother.Size();\n\n\t  NgArray < PointIndex > outerpoints(nsuround+1);\n\t  outerpoints[0] = sp1;\n\n\t  for(int i=0; i<nsuround; i++)\n\t    {\n\t      bool done = false;\n\t      for(int jj=i; !done && jj<hasbothpoints.Size(); jj++)\n\t\t{\n\t\t  for(int k=0; !done && k<4; k++)\n\t\t    if(mesh[hasbothpoints[jj]][k] == outerpoints[i])\n\t\t      {\n\t\t\tdone = true;\n\t\t\tfor(int l=0; l<4; l++)\n\t\t\t  if(mesh[hasbothpoints[jj]][l] != pi1 &&\n\t\t\t     mesh[hasbothpoints[jj]][l] != pi2 &&\n\t\t\t     mesh[hasbothpoints[jj]][l] != outerpoints[i])\n\t\t\t    outerpoints[i+1] = mesh[hasbothpoints[jj]][l];\n\t\t      }\n\t\t  if(done)\n\t\t    {\n\t\t      ElementIndex aux = hasbothpoints[i];\n\t\t      hasbothpoints[i] = hasbothpoints[jj];\n\t\t      hasbothpoints[jj] = aux;\n\t\t    }\n\t\t}\n\t    }\n\t  if(outerpoints[nsuround] != sp2)\n\t    {\n\t      cerr << \"OJE OJE OJE\" << endl;\n\t      (*testout) << \"OJE OJE OJE\" << endl;\n\t      (*testout) << \"hasbothpoints: \" << endl;\n\t      for(int ii=0; ii < hasbothpoints.Size(); ii++)\n\t\t{\n\t\t  (*testout) << mesh[hasbothpoints[ii]] << endl;\n\t\t  for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)\n\t\t    if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0].IsValid())\n\t\t      (*testout) << mesh[hasbothpoints[ii]][jj] << \" between \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << \" and \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;\n\t\t}\n\t      (*testout) << \"outerpoints: \" << outerpoints << endl;\n\t      (*testout) << \"sel1 \" << mesh[sel1] << endl\n\t\t\t << \"sel2 \" << mesh[sel2] << endl;\n\t      for(int ii=0; ii<3; ii++)\n\t\t{\n\t\t  if(mesh.mlbetweennodes[mesh[sel1][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel1][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;\n\t\t  if(mesh.mlbetweennodes[mesh[sel2][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel2][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;\n\t\t}\n\t    }\n\n\t  \n\t  NgArray < PointIndex > outerpointsother;\n\n\t  if(nsuroundother > 0)\n\t    {\n\t      outerpointsother.SetSize(nsuroundother+1);\n\t      outerpointsother[0] = sp2other;\n\t    }\n\n\t  for(int i=0; i<nsuroundother; i++)\n\t    {\n\t      bool done = false;\n\t      for(int jj=i; !done && jj<hasbothpointsother.Size(); jj++)\n\t\t{\n\t\t  for(int k=0; !done && k<4; k++)\n\t\t    if(mesh[hasbothpointsother[jj]][k] == outerpointsother[i])\n\t\t      {\n\t\t\tdone = true;\n\t\t\tfor(int l=0; l<4; l++)\n\t\t\t  if(mesh[hasbothpointsother[jj]][l] != pi1other &&\n\t\t\t     mesh[hasbothpointsother[jj]][l] != pi2other &&\n\t\t\t     mesh[hasbothpointsother[jj]][l] != outerpointsother[i])\n\t\t\t    outerpointsother[i+1] = mesh[hasbothpointsother[jj]][l];\n\t\t      }\n\t\t  if(done)\n\t\t    {\n\t\t      ElementIndex aux = hasbothpointsother[i];\n\t\t      hasbothpointsother[i] = hasbothpointsother[jj];\n\t\t      hasbothpointsother[jj] = aux;\n\t\t    }\n\t\t}\n\t    }\n\t  if(nsuroundother > 0 && outerpointsother[nsuroundother] != sp1other)\n\t    {\n\t      cerr << \"OJE OJE OJE (other)\" << endl;\n\t      (*testout) << \"OJE OJE OJE (other)\" << endl;\n\t      (*testout) << \"pi1 \" << pi1 << \" pi2 \" << pi2 << \" sp1 \" << sp1 << \" sp2 \" << sp2 << endl;\n\t      (*testout) << \"hasbothpoints: \" << endl;\n\t      for(int ii=0; ii < hasbothpoints.Size(); ii++)\n\t\t{\n\t\t  (*testout) << mesh[hasbothpoints[ii]] << endl;\n\t\t  for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)\n\t\t    if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0].IsValid())\n\t\t      (*testout) << mesh[hasbothpoints[ii]][jj] << \" between \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << \" and \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;\n\t\t}\n\t      (*testout) << \"outerpoints: \" << outerpoints << endl;\n\t      (*testout) << \"sel1 \" << mesh[sel1] << endl\n\t\t\t << \"sel2 \" << mesh[sel2] << endl;\n\t      for(int ii=0; ii<3; ii++)\n\t\t{\n\t\t  if(mesh.mlbetweennodes[mesh[sel1][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel1][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;\n\t\t  if(mesh.mlbetweennodes[mesh[sel2][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel2][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;\n\t\t}\n\t\t  \n\t      (*testout) << \"pi1other \" << pi1other << \" pi2other \" << pi2other << \" sp1other \" << sp1other << \" sp2other \" << sp2other << endl;\n\t      (*testout) << \"hasbothpointsother: \" << endl;\n\t      for(int ii=0; ii < hasbothpointsother.Size(); ii++)\n\t\t{\n\t\t  (*testout) << mesh[hasbothpointsother[ii]] << endl;\n\t\t  for(int jj=0; jj<mesh[hasbothpointsother[ii]].GetNP(); jj++)\n\t\t    if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0].IsValid())\n\t\t      (*testout) << mesh[hasbothpointsother[ii]][jj] << \" between \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] << \" and \"\n\t\t\t\t << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][1] << endl;\n\t\t}\n\t      (*testout) << \"outerpoints: \" << outerpointsother << endl;\n\t      (*testout) << \"sel1other \" << mesh[sel1other] << endl\n\t\t\t << \"sel2other \" << mesh[sel2other] << endl;\n\t      for(int ii=0; ii<3; ii++)\n\t\t{\n\t\t  if(mesh.mlbetweennodes[mesh[sel1other][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel1other][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1other][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel1other][ii]][1] << endl;\n\t\t  if(mesh.mlbetweennodes[mesh[sel2other][ii]][0].IsValid())\n\t\t    (*testout) << mesh[sel2other][ii] << \" between \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2other][ii]][0] << \" and \"\n\t\t\t       << mesh.mlbetweennodes[mesh[sel2other][ii]][1] << endl;\n\t\t}\n\t    }\n\n\t  bad1=0;\n\t  for(int i=0; i<hasbothpoints.Size(); i++)\n\t    bad1 += CalcBad(mesh.Points(), mesh[hasbothpoints[i]],h);\n\t  for(int i=0; i<hasbothpointsother.Size(); i++)\n\t    bad1 += CalcBad(mesh.Points(), mesh[hasbothpointsother[i]],h);\n\t  bad1 /= double(hasbothpoints.Size() + hasbothpointsother.Size());\n\n\t  \n\t  int startpoints,startpointsother;\n\n\n\t  if(outerpoints.Size() == 3)\n\t    startpoints = 1;\n\t  else if(outerpoints.Size() == 4)\n\t    startpoints = 2;\n\t  else\n\t    startpoints = outerpoints.Size();\n\t  \n\t  if(outerpointsother.Size() == 3)\n\t    startpointsother = 1;\n\t  else if(outerpointsother.Size() == 4)\n\t    startpointsother = 2;\n\t  else\n\t    startpointsother = outerpointsother.Size();\n\t  \n\n\t  NgArray < NgArray < Element* > * > newelts(startpoints);\n\t  NgArray < NgArray < Element* > * > neweltsother(startpointsother);\n\n\t  double minbad = 1e50, minbadother = 1e50, currbad;\n\t  int minpos = -1, minposother = -1;\n\n\t  //(*testout) << \"pi1 \" << pi1 << \" pi2 \" << pi2 << \" outerpoints \" << outerpoints << endl;\n\n\t  for(int i=0; i<startpoints; i++)\n\t    {\n\t      newelts[i] = new NgArray <Element*>(2*(nsuround-1));\n\t      \n\t      for(int jj=0; jj<nsuround-1; jj++)\n\t\t{\n\t\t  (*newelts[i])[2*jj] = new Element(TET);\n\t\t  (*newelts[i])[2*jj+1] = new Element(TET);\n\t\t  Element & newel1 = *((*newelts[i])[2*jj]);\n\t\t  Element & newel2 = *((*newelts[i])[2*jj+1]);\n\n\t\t  newel1[0] = pi1;\n\t\t  newel1[1] = outerpoints[i];\n\t\t  newel1[2] = outerpoints[(i+jj+1)%outerpoints.Size()];\n\t\t  newel1[3] = outerpoints[(i+jj+2)%outerpoints.Size()];\n\n\t\t  newel2[0] = pi2;\n\t\t  newel2[1] = outerpoints[i];\n\t\t  newel2[2] = outerpoints[(i+jj+2)%outerpoints.Size()];\n\t\t  newel2[3] = outerpoints[(i+jj+1)%outerpoints.Size()];\n\t\t  \n\n\t\t  //(*testout) << \"j \" << j << \" newel1 \" << newel1[0] << \" \"<< newel1[1] << \" \"<< newel1[2] << \" \"<< newel1[3] << endl\n\t\t  //     << \" newel2 \" << newel2[0] << \" \"<< newel2[1] << \" \"<< newel2[2] << \" \"<< newel2[3] << endl;\n\t\t  \n\t\t  newel1.SetIndex(mattype);\n\t\t  newel2.SetIndex(mattype);\n\n\t\t}\n\n\t      bool wrongorientation = true;\n\t      for(int jj = 0; wrongorientation && jj<newelts[i]->Size(); jj++)\n\t\twrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*newelts[i])[jj]);\n\t      \n\t      currbad = 0;\n\n\t      for(int jj=0; jj<newelts[i]->Size(); jj++)\n\t\t{\n\t\t  if(wrongorientation)\n\t\t    Swap((*(*newelts[i])[jj])[2],(*(*newelts[i])[jj])[3]);\n\n\n\t\t  // not two new faces on same surface\n\t\t  NgArray<int> face_index;\n\t\t  for(int k = 0; k<surfaceindicesonnode[(*(*newelts[i])[jj])[0]].Size(); k++)\n\t\t    face_index.Append(surfaceindicesonnode[(*(*newelts[i])[jj])[0]][k]);\n\n\t\t  for(int k=1; k<4; k++)\n\t\t    {\n\t\t      for(int l=0; l<face_index.Size(); l++)\n\t\t\t{\n\t\t\t  if(face_index[l] != -1 && \n\t\t\t     !(surfaceindicesonnode[(*(*newelts[i])[jj])[k]].Contains(face_index[l])))\n\t\t\t    face_index[l] = -1;\n\t\t\t}\n\n\t\t    }\n\t\t      \n\t\t  for(int k=0; k<face_index.Size(); k++)\n\t\t    if(face_index[k] != -1)\n\t\t      currbad += 1e12;\n\n\n\t\t  currbad += CalcBad(mesh.Points(),*(*newelts[i])[jj],h);\n\n\n\t\t}  \n\n\t      //currbad /= double(newelts[i]->Size());\n\t\t    \n\n\n\t      if(currbad < minbad)\n\t\t{\n\t\t  minbad = currbad;\n\t\t  minpos = i;\n\t\t}\n\n\t    }\n\n\t  if(startpointsother == 0)\n\t    minbadother = 0;\n\n\t  for(int i=0; i<startpointsother; i++)\n\t    {\n\t      neweltsother[i] = new NgArray <Element*>(2*(nsuroundother));\n\t      \n\t      for(int jj=0; jj<nsuroundother; jj++)\n\t\t{\n\t\t  (*neweltsother[i])[2*jj] = new Element(TET);\n\t\t  (*neweltsother[i])[2*jj+1] = new Element(TET);\n\t\t  Element & newel1 = *((*neweltsother[i])[2*jj]);\n\t\t  Element & newel2 = *((*neweltsother[i])[2*jj+1]);\n\n\t\t  newel1[0] = pi1other;\n\t\t  newel1[1] = outerpointsother[i];\n\t\t  newel1[2] = outerpointsother[(i+jj+1)%outerpointsother.Size()];\n\t\t  newel1[3] = outerpointsother[(i+jj+2)%outerpointsother.Size()];\n\n\t\t  newel2[0] = pi2other;\n\t\t  newel2[1] = outerpointsother[i];\n\t\t  newel2[2] = outerpointsother[(i+jj+2)%outerpointsother.Size()];\n\t\t  newel2[3] = outerpointsother[(i+jj+1)%outerpointsother.Size()];\n\t\t  \n\n\t\t  //(*testout) << \"j \" << j << \" newel1 \" << newel1[0] << \" \"<< newel1[1] << \" \"<< newel1[2] << \" \"<< newel1[3] << endl\n\t\t  //\t     << \" newel2 \" << newel2[0] << \" \"<< newel2[1] << \" \"<< newel2[2] << \" \"<< newel2[3] << endl;\n\t\t  \n\t\t  newel1.SetIndex(othermattype);\n\t\t  newel2.SetIndex(othermattype);\n\n\t\t}\n\n\t      bool wrongorientation = true;\n\t      for(int jj = 0; wrongorientation && jj<neweltsother[i]->Size(); jj++)\n\t\twrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*neweltsother[i])[jj]);\n\t      \n\t      currbad = 0;\n\n\t      for(int jj=0; jj<neweltsother[i]->Size(); jj++)\n\t\t{\n\t\t  if(wrongorientation)\n\t\t    Swap((*(*neweltsother[i])[jj])[2],(*(*neweltsother[i])[jj])[3]);\n\n\t\t  currbad += CalcBad(mesh.Points(),*(*neweltsother[i])[jj],h);\n\t\t}  \n\n\t      //currbad /= double(neweltsother[i]->Size());\n\t\t    \n\n\n\t      if(currbad < minbadother)\n\t\t{\n\t\t  minbadother = currbad;\n\t\t  minposother = i;\n\t\t}\n\n\t    }\n\n\t  //(*testout) << \"minbad \" << minbad << \" bad1 \" << bad1 << endl;\n\n\t  \n\t  double sbadnew = CalcTriangleBadness (mesh[pi1],mesh[sp2],mesh[sp1],0,0) + \n\t    CalcTriangleBadness (mesh[pi2],mesh[sp1],mesh[sp2],0,0);\n\t  \n\n\t  int denom = newelts[minpos]->Size();\n\t  if(minposother >= 0)\n\t    denom += neweltsother[minposother]->Size();\n\t  \n\n\t  if((minbad+minbadother)/double(denom) < bad1 && \n\t     sbadnew < sbad)\n\t    {\n\t      cnt++;\n\n\t      swapped = true;\n\n\n\t      int start1 = -1;\n\t      for(int l=0; l<3; l++)\n\t\tif(mesh[sel1][l] == pi1)\n\t\t  start1 = l;\n\t      if(mesh[sel1][(start1+1)%3] == pi2)\n\t\t{\n\t\t  mesh[sel1][0] = pi1;\n\t\t  mesh[sel1][1] = sp2;\n\t\t  mesh[sel1][2] = sp1;\n\t\t  mesh[sel2][0] = pi2;\n\t\t  mesh[sel2][1] = sp1;\n\t\t  mesh[sel2][2] = sp2;\n\t\t}\n\t      else\n\t\t{\n\t\t  mesh[sel1][0] = pi2;\n\t\t  mesh[sel1][1] = sp2;\n\t\t  mesh[sel1][2] = sp1;\n\t\t  mesh[sel2][0] = pi1;\n\t\t  mesh[sel2][1] = sp1;\n\t\t  mesh[sel2][2] = sp2;\n\t\t}\n\t      //(*testout) << \"changed surface element \" << sel1 << \" to \" << mesh[sel1] << \", \" << sel2 << \" to \" << mesh[sel2] << endl;\n\n\t      for(int l=0; l<3; l++)\n\t\t{\n\t\t  surfaceelementsonnode.Add(mesh[sel1][l],sel1);\n\t\t  surfaceelementsonnode.Add(mesh[sel2][l],sel2);\n\t\t}\n\t      \n\n\n\t      if(periodic)\n\t\t{\n\t\t  start1 = -1;\n\t\t  for(int l=0; l<3; l++)\n\t\t    if(mesh[sel1other][l] == pi1other)\n\t\t      start1 = l;\n\t\t  \n\n\n\t\t  //(*testout) << \"changed surface elements \" << mesh[sel1other] << \" and \" << mesh[sel2other] << endl;\n\t\t  if(mesh[sel1other][(start1+1)%3] == pi2other)\n\t\t    {\n\t\t      mesh[sel1other][0] = pi1other;\n\t\t      mesh[sel1other][1] = sp2other;\n\t\t      mesh[sel1other][2] = sp1other;\n\t\t      mesh[sel2other][0] = pi2other;\n\t\t      mesh[sel2other][1] = sp1other;\n\t\t      mesh[sel2other][2] = sp2other;\n\t\t      //(*testout) << \"       with rule 1\" << endl;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      mesh[sel1other][0] = pi2other;\n\t\t      mesh[sel1other][1] = sp2other;\n\t\t      mesh[sel1other][2] = sp1other;\n\t\t      mesh[sel2other][0] = pi1other;\n\t\t      mesh[sel2other][1] = sp1other;\n\t\t      mesh[sel2other][2] = sp2other;\n\t\t      //(*testout) << \"       with rule 2\" << endl;\n\t\t    }\n\t\t  //(*testout) << \"         to \" << mesh[sel1other] << \" and \" << mesh[sel2other] << endl;\n\t\t  \n\t\t  //(*testout) << \"  and surface element \" << sel1other << \" to \" << mesh[sel1other] << \", \" << sel2other << \" to \" << mesh[sel2other] << endl;\n\n\t\t  for(int l=0; l<3; l++)\n\t\t    {\n\t\t      surfaceelementsonnode.Add(mesh[sel1other][l],sel1other);\n\t\t      surfaceelementsonnode.Add(mesh[sel2other][l],sel2other);\n\t\t    }\n\t\t}\n\n\n\n\n\t      for(int i=0; i<hasbothpoints.Size(); i++)\n\t\t{\n\t\t  mesh[hasbothpoints[i]] = *(*newelts[minpos])[i];\n\n\t\t  for(int l=0; l<4; l++)\n\t\t    elementsonnode.Add((*(*newelts[minpos])[i])[l],hasbothpoints[i]);\n\t\t}\n\n\t      for(int i=hasbothpoints.Size(); i<(*newelts[minpos]).Size(); i++)\n\t\t{\n\t\t  ElementIndex ni = mesh.AddVolumeElement(*(*newelts[minpos])[i]);\n\t\t  \n\t\t  for(int l=0; l<4; l++)\n\t\t    elementsonnode.Add((*(*newelts[minpos])[i])[l],ni);\n\t\t}\n\n\t      if(hasbothpointsother.Size() > 0)\n\t\t{\n\t\t  for(int i=0; i<hasbothpointsother.Size(); i++)\n\t\t    {\n\t\t      mesh[hasbothpointsother[i]] = *(*neweltsother[minposother])[i];\n\t\t      for(int l=0; l<4; l++)\n\t\t\telementsonnode.Add((*(*neweltsother[minposother])[i])[l],hasbothpointsother[i]);\n\t\t    }\n\t\t  \n\t\t  for(int i=hasbothpointsother.Size(); i<(*neweltsother[minposother]).Size(); i++)\n\t\t    {\n\t\t      ElementIndex ni = mesh.AddVolumeElement(*(*neweltsother[minposother])[i]);\n\t\t      for(int l=0; l<4; l++)\n\t\t\telementsonnode.Add((*(*neweltsother[minposother])[i])[l],ni);\n\t\t    }\n\t\t}\n\n\t      \n\n\t    }\n\n\t  for(int i=0; i<newelts.Size(); i++)\n\t    {\n\t      for(int jj=0; jj<newelts[i]->Size(); jj++)\n\t\tdelete (*newelts[i])[jj];\n\t      delete newelts[i];\n\t    }\n\n\t  for(int i=0; i<neweltsother.Size(); i++)\n\t    {\n\t      for(int jj=0; jj<neweltsother[i]->Size(); jj++)\n\t\tdelete (*neweltsother[i])[jj];\n\t      delete neweltsother[i];\n\t    }\n\t\n\t}\n    }\n\n  PrintMessage (5, cnt, \" swaps performed\");\n\n\n  for(int i=0; i<locidmaps.Size(); i++)\n    delete locidmaps[i];\n\n\n  mesh.Compress ();\n\n  multithread.task = savetask;\n}\n  \n\n\n\n\n\n\n\n/*\n  2 -> 3 conversion\n*/\n\ndouble MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,\n                                        Table<ElementIndex, PointIndex> & elementsonnode,\n                                        DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only )\n{\n  PointIndex pi1, pi2, pi3, pi4, pi5;\n  Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);\n  int j = face;\n  double bad1, bad2;\n  double d_badness = 0.0;\n\n  Element & elem = mesh[eli1];\n  if (elem.IsDeleted()) return 0.0;\n\n  int mattyp = elem.GetIndex();\n\n  switch (j)\n  {\n    case 0:\n      pi1 = elem.PNum(1); pi2 = elem.PNum(2);\n      pi3 = elem.PNum(3); pi4 = elem.PNum(4);\n      break;\n    case 1:\n      pi1 = elem.PNum(1); pi2 = elem.PNum(4);\n      pi3 = elem.PNum(2); pi4 = elem.PNum(3);\n      break;\n    case 2:\n      pi1 = elem.PNum(1); pi2 = elem.PNum(3);\n      pi3 = elem.PNum(4); pi4 = elem.PNum(2);\n      break;\n    case 3:\n      pi1 = elem.PNum(2); pi2 = elem.PNum(4);\n      pi3 = elem.PNum(3); pi4 = elem.PNum(1);\n      break;\n  }\n\n\n  if(!conform_segments)\n    {\n      bool bface = 0;\n      for (int k = 0; k < belementsonnode[pi1].Size(); k++)\n      {\n          const Element2d & bel =\n            mesh[belementsonnode[pi1][k]];\n\n          bool bface1 = 1;\n          for (int l = 0; l < 3; l++)\n              if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)\n              {\n                  bface1 = 0;\n                  break;\n              }\n\n          if (bface1)\n          {\n              bface = 1;\n              break;\n          }\n      }\n\n      if (bface) return 0.0;\n    }\n\n\n  FlatArray<ElementIndex> row = elementsonnode[pi1];\n  for(auto ei : row)\n      if (mesh[ei].IsDeleted()) return 0.0;\n\n  for(auto ei : elementsonnode[pi2])\n      if (mesh[ei].IsDeleted()) return 0.0;\n\n  for(auto ei : elementsonnode[pi3])\n      if (mesh[ei].IsDeleted()) return 0.0;\n\n  for(auto ei : elementsonnode[pi4])\n      if (mesh[ei].IsDeleted()) return 0.0;\n\n  for (int k = 0; k < row.Size(); k++)\n  {\n      ElementIndex eli2 = row[k];\n\n      if ( eli1 != eli2 )\n      {\n          Element & elem2 = mesh[eli2];\n          if (elem2.GetType() != TET)\n              continue;\n\n          ArrayMem<ElementIndex, 2> elis = {eli1, eli2};\n          if(!NeedsOptimization(elis))\n            continue;\n\n          int comnodes=0;\n          for (int l = 1; l <= 4; l++)\n              if (elem2.PNum(l) == pi1 || elem2.PNum(l) == pi2 ||\n                  elem2.PNum(l) == pi3)\n              {\n                  comnodes++;\n              }\n              else\n              {\n                  pi5 = elem2.PNum(l);\n              }\n\n          if (comnodes == 3)\n          {\n              bad1 = elem.GetBadness() + elem2.GetBadness();\n\n              if (!mesh.LegalTet(elem) ||\n                  !mesh.LegalTet(elem2))\n                  bad1 += GetLegalPenalty();\n\n              if(mesh.BoundaryEdge (pi4, pi5))\n                  bad1 += GetLegalPenalty();\n\n              el31.PNum(1) = pi1;\n              el31.PNum(2) = pi2;\n              el31.PNum(3) = pi5;\n              el31.PNum(4) = pi4;\n              el31.SetIndex (mattyp);\n\n              el32.PNum(1) = pi2;\n              el32.PNum(2) = pi3;\n              el32.PNum(3) = pi5;\n              el32.PNum(4) = pi4;\n              el32.SetIndex (mattyp);\n\n              el33.PNum(1) = pi3;\n              el33.PNum(2) = pi1;\n              el33.PNum(3) = pi5;\n              el33.PNum(4) = pi4;\n              el33.SetIndex (mattyp);\n\n              bad2 = CalcBad (mesh.Points(), el31, 0) +\n                CalcBad (mesh.Points(), el32, 0) +\n                CalcBad (mesh.Points(), el33, 0);\n\n\n              el31.Touch();\n              el32.Touch();\n              el33.Touch();\n\n              if (!mesh.LegalTet(el31) ||\n                  !mesh.LegalTet(el32) ||\n                  !mesh.LegalTet(el33))\n                  bad2 += GetLegalPenalty();\n\n\n              d_badness = bad2 - bad1;\n\n              if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) &&\n                  mesh.BoundaryEdge (pi4, pi5))\n                  d_badness = -1e4;\n\n              if(check_only)\n                  return d_badness;\n\n              if (d_badness<0.0)\n              {\n                  el31.Touch();\n                  el32.Touch();\n                  el33.Touch();\n\n                  mesh[eli1].Delete();\n                  mesh[eli2].Delete();\n                  mesh.AddVolumeElement (el31);\n                  mesh.AddVolumeElement (el32);\n                  mesh.AddVolumeElement (el33);\n              }\n              return d_badness;\n          }\n      }\n  }\n  return d_badness;\n}\n\n/*\n  2 -> 3 conversion\n*/\n\nvoid MeshOptimize3d :: SwapImprove2 (bool conform_segments)\n{\n  static Timer t(\"MeshOptimize3d::SwapImprove2\"); RegionTimer reg(t);\n\n  if (!conform_segments && goal == OPT_CONFORM) return;\n\n  mesh.BuildBoundaryEdges(false);\n\n  int cnt = 0;\n  // double bad1, bad2;\n\n  int np = mesh.GetNP();\n  int ne = mesh.GetNE();\n  int nse = mesh.GetNSE();\n\n  // contains at least all elements at node\n  DynamicTable<SurfaceElementIndex, PointIndex> belementsonnode(np);\n\n  PrintMessage (3, \"SwapImprove2 \");\n  (*testout) << \"\\n\" << \"Start SwapImprove2\" << \"\\n\";\n\n  if(testout->good())\n  {\n    double bad1 = mesh.CalcTotalBad (mp);\n    (*testout) << \"Total badness = \" << bad1 << endl;\n  }\n\n  // find elements on node\n\n  auto elementsonnode = mesh.CreatePoint2ElementTable(nullopt, mp.only3D_domain_nr);\n  // todo: respect mp.only3D_domain_nr\n  \n  for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n    for (int j = 0; j < 3; j++)\n      belementsonnode.Add (mesh[sei][j], sei);\n\n  int num_threads = ngcore::TaskManager::GetNumThreads();\n\n  Array<std::tuple<double, ElementIndex, int>> faces_with_improvement;\n  Array<Array<std::tuple<double, ElementIndex, int>>> faces_with_improvement_threadlocal(num_threads);\n\n  UpdateBadness();\n\n  ParallelForRange( Range(ne), [&]( auto myrange )\n      {\n        int tid = ngcore::TaskManager::GetThreadId();\n        auto & my_faces_with_improvement = faces_with_improvement_threadlocal[tid];\n        for (ElementIndex eli1 : myrange)\n          {\n            if (multithread.terminate)\n              break;\n\n            if (mesh.ElementType (eli1) == FIXEDELEMENT)\n              continue;\n\n            if (mesh[eli1].GetType() != TET)\n              continue;\n\n            if (goal == OPT_LEGAL && mesh.LegalTet (mesh[eli1]))\n              continue;\n\n            if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(eli1).GetIndex())\n              continue;\n\n            for (int j = 0; j < 4; j++)\n              {\n                double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, conform_segments, true);\n                if(d_badness<0.0)\n                    my_faces_with_improvement.Append( std::make_tuple(d_badness, eli1, j) );\n              }\n          }\n      });\n\n  for (auto & a : faces_with_improvement_threadlocal)\n    faces_with_improvement.Append(a);\n\n  QuickSort(faces_with_improvement);\n\n  for (auto [dummy, eli,j] : faces_with_improvement)\n    {\n      if(mesh[eli].IsDeleted())\n          continue;\n      if(SwapImprove2( eli, j, elementsonnode, belementsonnode, conform_segments, false) < 0.0)\n          cnt++;\n    }\n\n  PrintMessage (5, cnt, \" swaps performed\");\n\n  mesh.Compress();\n  if(testout->good())\n  {\n    double bad1 = mesh.CalcTotalBad (mp);\n    (*testout) << \"Total badness = \" << bad1 << endl;\n    (*testout) << \"swapimprove2 done\" << \"\\n\";\n  }\n}\n\ndouble MeshOptimize3d :: SplitImprove2Element (\n                            ElementIndex ei,\n                            const Table<ElementIndex, PointIndex> & elements_of_point,\n                            bool check_only)\n{\n  auto & el = mesh[ei];\n  if(el.GetType() != TET)\n    return false;\n\n  // Optimize only bad elements\n  if(el.GetBadness() < 100)\n    return false;\n\n  // search for very flat tets, with two disjoint edges nearly crossing, like a rectangle with diagonals\n  int minedge = -1;\n  double mindist = 1e99;\n  double minlam0=0, minlam1=0;\n\n  for (int i : Range(3))\n  {\n    auto pi0 = el[tetedges[i][0]];\n    auto pi1 = el[tetedges[i][1]];\n    auto pi2 = el[tetedges[5-i][0]];\n    auto pi3 = el[tetedges[5-i][1]];\n\n    double lam0, lam1;\n    double dist = MinDistLL2(mesh[pi0], mesh[pi1], mesh[pi2], mesh[pi3], lam0, lam1 );\n    if(dist<mindist)\n    {\n      mindist = dist;\n      minedge = i;\n      minlam0 = lam0;\n      minlam1 = lam1;\n    }\n  }\n\n  if(minedge==-1)\n    return false;\n\n  auto pi0 = el[tetedges[minedge][0]];\n  auto pi1 = el[tetedges[minedge][1]];\n  auto pi2 = el[tetedges[5-minedge][0]];\n  auto pi3 = el[tetedges[5-minedge][1]];\n\n  // we cannot split edges on the boundary\n  if(mesh.BoundaryEdge (pi0,pi1) || mesh.BoundaryEdge(pi2, pi3))\n    return false;\n\n  ArrayMem<ElementIndex, 50> has_both_points0;\n  ArrayMem<ElementIndex, 50> has_both_points1;\n\n  Point3d p[4] = { mesh[el[0]], mesh[el[1]], mesh[el[2]], mesh[el[3]] };\n  auto center = Center(p[0]+minlam0*(p[1]-p[0]), p[2]+minlam1*(p[3]-p[2]));\n  MeshPoint pnew;\n\n  pnew(0) = center.X();\n  pnew(1) = center.Y();\n  pnew(2) = center.Z();\n\n  // find all tets with edge (pi0,pi1) or (pi2,pi3)\n  for (auto ei0 : elements_of_point[pi0] )\n  {\n    Element & elem = mesh[ei0];\n    if (elem.IsDeleted()) return false;\n    if (ei0 == ei) continue;\n    if (elem.GetType() != TET) return false;\n\n    if (elem[0] == pi1 || elem[1] == pi1 || elem[2] == pi1 || elem[3] == pi1 || (elem.GetNP()==5 && elem[4]==pi1) )\n      if(!has_both_points0.Contains(ei0))\n        has_both_points0.Append (ei0);\n  }\n\n  for (auto ei1 : elements_of_point[pi2] )\n  {\n    Element & elem = mesh[ei1];\n    if (elem.IsDeleted()) return false;\n    if (ei1 == ei) continue;\n    if (elem.GetType() != TET) return false;\n\n    if (elem[0] == pi3 || elem[1] == pi3 || elem[2] == pi3 || elem[3] == pi3 || (elem.GetNP()==5 && elem[4]==pi3))\n      if(!has_both_points1.Contains(ei1))\n        has_both_points1.Append (ei1);\n  }\n\n  double badness_before = mesh[ei].GetBadness();\n  double badness_after = 0.0;\n\n  for (auto ei0 : has_both_points0)\n  {\n    if(mesh[ei0].GetType()!=TET)\n      return false;\n    badness_before += mesh[ei0].GetBadness();\n    badness_after += SplitElementBadness (mesh.Points(), mp, mesh[ei0], pi0, pi1, pnew);\n  }\n  for (auto ei1 : has_both_points1)\n  {\n    if(mesh[ei1].GetType()!=TET)\n      return false;\n    badness_before += mesh[ei1].GetBadness();\n    badness_after += SplitElementBadness (mesh.Points(), mp, mesh[ei1], pi2, pi3, pnew);\n  }\n\n  if(check_only)\n    return badness_after-badness_before;\n\n  if(badness_after<badness_before)\n  {\n    PointIndex pinew = mesh.AddPoint (center);\n    el.Touch();\n    el.Delete();\n\n    for (auto ei1 : has_both_points0)\n    {\n      auto new_els = SplitElement(mesh[ei1], pi0, pi1, pinew);\n      for(const auto & el : new_els)\n        mesh.AddVolumeElement(el);\n      mesh[ei1].Delete();\n    }\n    for (auto ei1 : has_both_points1)\n    {\n      auto new_els = SplitElement(mesh[ei1], pi2, pi3, pinew);\n      for(const auto & el : new_els)\n        mesh.AddVolumeElement(el);\n      mesh[ei1].Delete();\n    }\n  }\n  return badness_after-badness_before;\n}\n\n// Split two opposite edges of very flat tet and let all 4 new segments have one common vertex\n// Imagine a square with 2 diagonals -> new point where diagonals cross, remove the flat tet\nvoid MeshOptimize3d :: SplitImprove2 ()\n{\n  static Timer t(\"MeshOptimize3d::SplitImprove2\"); RegionTimer reg(t);\n  static Timer tsearch(\"Search\");\n  static Timer topt(\"Optimize\");\n\n  int ne = mesh.GetNE();\n  auto elements_of_point = mesh.CreatePoint2ElementTable(nullopt, mp.only3D_domain_nr);\n  int ntasks = 4*ngcore::TaskManager::GetNumThreads();\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Split Improve 2\";\n\n  UpdateBadness();\n  mesh.BuildBoundaryEdges(false);\n\n  Array<std::tuple<double, ElementIndex>> split_candidates(ne);\n  std::atomic<int> improvement_counter(0);\n\n  tsearch.Start();\n  ParallelForRange(Range(ne), [&] (auto myrange)\n  {\n    for(ElementIndex ei : myrange)\n    {\n      if(mp.only3D_domain_nr && mp.only3D_domain_nr != mesh[ei].GetIndex())\n        continue;\n      double d_badness = SplitImprove2Element(ei, elements_of_point, true);\n      if(d_badness<0.0)\n      {\n        int index = improvement_counter++;\n        split_candidates[index] = make_tuple(d_badness, ei);\n      }\n    }\n  }, ntasks);\n  tsearch.Stop();\n\n  auto elements_with_improvement = split_candidates.Part(0, improvement_counter.load());\n  QuickSort(elements_with_improvement);\n\n  size_t cnt = 0;\n  topt.Start();\n  for(auto [d_badness, ei] : elements_with_improvement)\n  {\n    if( SplitImprove2Element(ei, elements_of_point, false) < 0.0)\n      cnt++;\n  }\n  topt.Stop();\n\n  PrintMessage (5, cnt, \" elements split\");\n  (*testout) << \"SplitImprove2 done\" << \"\\n\";\n\n  if(cnt>0)\n    mesh.Compress();\n  multithread.task = savetask;\n}\n\n\n/*\n  void Mesh :: SwapImprove2 (OPTIMIZEGOAL goal)\n  {\n  int i, j;\n  int eli1, eli2;\n  int mattyp;\n\n  Element el31(4), el32(4), el33(4);\n  double bad1, bad2;\n\n\n  INDEX_3_HASHTABLE<INDEX_2> elsonface (GetNE());\n\n  (*mycout) << \"SwapImprove2 \" << endl;\n  (*testout) << \"\\n\" << \"Start SwapImprove2\" << \"\\n\";\n\n  // Calculate total badness\n\n  if (goal == OPT_QUALITY)\n  {\n  double bad1 = CalcTotalBad (points, volelements);\n  (*testout) << \"Total badness = \" << bad1 << endl;\n  }\n\n  // find elements on node\n\n\n  Element2d face;\n  for (i = 1; i <= GetNE(); i++)\n  if ( (i > eltyps.Size()) || (eltyps.Get(i) != FIXEDELEMENT) )\n  {\n  const Element & el = VolumeElement(i);\n  if (!el.PNum(1)) continue;\n\n  for (j = 1; j <= 4; j++)\n  {\n  el.GetFace (j, face);\n  INDEX_3 i3 (face.PNum(1), face.PNum(2), face.PNum(3));\n  i3.Sort();\n\n\n  int bnr, posnr;\n  if (!elsonface.PositionCreate (i3, bnr, posnr))\n  {\n  INDEX_2 i2;\n  elsonface.GetData (bnr, posnr, i3, i2);\n  i2.I2() = i;\n  elsonface.SetData (bnr, posnr, i3, i2);\n  }\n  else\n  {\n  INDEX_2 i2 (i, 0);\n  elsonface.SetData (bnr, posnr, i3, i2);\n  }\n\n  //  \t    if (elsonface.Used (i3))\n  //  \t      {\n  //  \t\tINDEX_2 i2 = elsonface.Get(i3);\n  //  \t\ti2.I2() = i;\n  //  \t\telsonface.Set (i3, i2);\n  //  \t      }\n  //  \t    else\n  //  \t      {\n  //  \t\tINDEX_2 i2 (i, 0);\n  //  \t\telsonface.Set (i3, i2);\n  //  \t      }\n\n  }\n  }\n\n  NgBitArray original(GetNE());\n  original.Set();\n\n  for (i = 1; i <= GetNSE(); i++)\n  {\n  const Element2d & sface = SurfaceElement(i);\n  INDEX_3 i3 (sface.PNum(1), sface.PNum(2), sface.PNum(3));\n  i3.Sort();\n  INDEX_2 i2(0,0);\n  elsonface.Set (i3, i2);\n  }\n\n\n  for (i = 1; i <= elsonface.GetNBags(); i++)\n  for (j = 1; j <= elsonface.GetBagSize(i); j++)\n  {\n  INDEX_3 i3;\n  INDEX_2 i2;\n  elsonface.GetData (i, j, i3, i2);\n\n\n  int eli1 = i2.I1();\n  int eli2 = i2.I2();\n\n  if (eli1 && eli2 && original.Test(eli1) && original.Test(eli2) )\n  {\n  Element & elem = volelements.Elem(eli1);\n  Element & elem2 = volelements.Elem(eli2);\n\n  int pi1 = i3.I1();\n  int pi2 = i3.I2();\n  int pi3 = i3.I3();\n\n  int pi4 = elem.PNum(1) + elem.PNum(2) + elem.PNum(3) + elem.PNum(4) - pi1 - pi2 - pi3;\n  int pi5 = elem2.PNum(1) + elem2.PNum(2) + elem2.PNum(3) + elem2.PNum(4) - pi1 - pi2 - pi3;\n\n\n\n\n\n\n  el31.PNum(1) = pi1;\n  el31.PNum(2) = pi2;\n  el31.PNum(3) = pi3;\n  el31.PNum(4) = pi4;\n  el31.SetIndex (mattyp);\n\t    \n  if (WrongOrientation (points, el31))\n  swap (pi1, pi2);\n\n\n  bad1 = CalcBad (points, elem, 0) + \n  CalcBad (points, elem2, 0); \n\t    \n  //\t    if (!LegalTet(elem) || !LegalTet(elem2))\n  //\t      bad1 += 1e4;\n\n\t    \n  el31.PNum(1) = pi1;\n  el31.PNum(2) = pi2;\n  el31.PNum(3) = pi5;\n  el31.PNum(4) = pi4;\n  el31.SetIndex (mattyp);\n\t    \n  el32.PNum(1) = pi2;\n  el32.PNum(2) = pi3;\n  el32.PNum(3) = pi5;\n  el32.PNum(4) = pi4;\n  el32.SetIndex (mattyp);\n\t\t      \n  el33.PNum(1) = pi3;\n  el33.PNum(2) = pi1;\n  el33.PNum(3) = pi5;\n  el33.PNum(4) = pi4;\n  el33.SetIndex (mattyp);\n\t    \n  bad2 = CalcBad (points, el31, 0) + \n  CalcBad (points, el32, 0) +\n  CalcBad (points, el33, 0); \n\t    \n  //\t    if (!LegalTet(el31) || !LegalTet(el32) ||\n  //\t\t!LegalTet(el33))\n  //\t      bad2 += 1e4;\n\t    \n\t    \n  int swap = (bad2 < bad1);\n\n  INDEX_2 hi2b(pi4, pi5);\n  hi2b.Sort();\n\t    \n  if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) &&\n  boundaryedges->Used (hi2b) )\n  swap = 1;\n\t    \n  if (swap)\n  {\n  (*mycout) << \"2->3 \" << flush;\n\t\t\n  volelements.Elem(eli1) = el31;\n  volelements.Elem(eli2) = el32;\n  volelements.Append (el33);\n\t\t\n  original.Clear (eli1);\n  original.Clear (eli2);\n  }\n  }\n  }\n  \n  (*mycout) << endl;\n\n  if (goal == OPT_QUALITY)\n  {\n  bad1 = CalcTotalBad (points, volelements);\n  (*testout) << \"Total badness = \" << bad1 << endl;\n  }\n\n  //  FindOpenElements ();\n\n  (*testout) << \"swapimprove2 done\" << \"\\n\";\n  }\n\n*/\n}\n"
  },
  {
    "path": "libsrc/meshing/improve3.hpp",
    "content": "#ifndef FILE_IMPROVE3\n#define FILE_IMPROVE3\n\nnamespace netgen\n{\n\n\n///\nclass MeshOptimize3d\n{\n  Mesh & mesh;\n  const MeshingParameters & mp;\n  OPTIMIZEGOAL goal = OPT_QUALITY;\n  double min_badness = 0;\n\n  bool HasBadElement(FlatArray<ElementIndex> els);\n  bool HasIllegalElement(FlatArray<ElementIndex> els);\n  bool NeedsOptimization(FlatArray<ElementIndex> els);\n\npublic:\n\n  MeshOptimize3d (Mesh & m, const MeshingParameters & amp, OPTIMIZEGOAL agoal = OPT_QUALITY) :\n      mesh(m), mp(amp), goal(agoal) { ; }\n\n  void SetGoal(OPTIMIZEGOAL agoal) { goal = agoal; }\n  void SetMinBadness(double badness) { min_badness = badness; }\n\n  tuple<double, double, int> UpdateBadness();\n\n  double CombineImproveEdge (\n            Table<ElementIndex, PointIndex> & elements_of_point,\n            PointIndex pi0, PointIndex pi1,\n            FlatArray<bool, PointIndex> is_point_removed, bool check_only=false);\n\n  void CombineImprove ();\n\n  void SplitImprove ();\n  double SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<PointIndices<3>> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only=false);\n\n  void SplitImprove2 ();\n  double SplitImprove2Element (ElementIndex ei, const Table<ElementIndex, PointIndex> & elements_of_point, bool check_only);\n  \n\n  double SwapImproveEdge (const TBitArray<ElementIndex> * working_elements, Table<ElementIndex,PointIndex> & elementsonnode, INDEX_3_HASHTABLE<int> & faces, PointIndex pi1, PointIndex pi2, bool check_only=false);\n  void SwapImprove (const TBitArray<ElementIndex> * working_elements = NULL);\n  void SwapImproveSurface (const TBitArray<ElementIndex> * working_elements = NULL,\n\t\t\t   const NgArray< idmap_type* > * idmaps = NULL);\n  void SwapImprove2 (bool conform_segments = false);\n  double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only=false );\n\n  void ImproveMesh() { mesh.ImproveMesh(mp, goal); }\n\n  double \n  CalcBad (const Mesh::T_POINTS & points, const Element & elem, double h)\n  {\n    if (elem.GetType() == TET)\n      return CalcTetBadness (points[elem[0]], points[elem[1]],  \n\t\t\t     points[elem[2]], points[elem[3]], h, mp);  \n    return 0;\n  }\n\n\n  double GetLegalPenalty()\n  {\n    return goal == OPT_LEGAL ? 1e15 : 1e6;\n  }\n\n};\n\n\ninline double \nCalcBad (const Mesh::T_POINTS & points, const Element & elem, double h, const MeshingParameters & mp)\n{\n  if (elem.GetType() == TET)\n    return CalcTetBadness (points[elem[0]], points[elem[1]],  \n\t\t\t   points[elem[2]], points[elem[3]], h, mp);  \n  return 0;\n}\n\n\n\nextern int WrongOrientation (const Mesh::T_POINTS & points, const Element & el);\n\n\n/* Functional depending of inner point inside triangular surface */\n\n\nclass MinFunctionSum : public MinFunction\n{\nprotected:\n  NgArray<MinFunction*> functions;\n \npublic:\n  \n  virtual double Func (const Vector & x) const;\n  virtual void Grad (const Vector & x, Vector & g) const;\n  virtual double FuncGrad (const Vector & x, Vector & g) const;\n  virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n  virtual double GradStopping (const Vector & x) const;\n\n  void AddFunction(MinFunction & fun);\n  \n  const MinFunction & Function(int i) const;\n  MinFunction & Function(int i);  \n};\n  \n\nclass PointFunction1 : public MinFunction\n{\n  Mesh::T_POINTS & points;\n  const NgArray<PointIndices<3>> & faces;\n  const MeshingParameters & mp;\n  double h;\npublic:\n  PointFunction1 (Mesh::T_POINTS & apoints, \n\t\t  const NgArray<PointIndices<3>> & afaces,\n\t\t  const MeshingParameters & amp,\n\t\t  double ah);\n  \n  virtual double Func (const Vector & x) const;\n  virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n  virtual double FuncGrad (const Vector & x, Vector & g) const;\n  virtual double GradStopping (const Vector & x) const;\n};\n\nclass JacobianPointFunction : public MinFunction\n{\npublic:\n  Mesh::T_POINTS & points;\n  const Array<Element, ElementIndex> & elements;\n  TABLE<INDEX> elementsonpoint;\n  PointIndex actpind;\n\n  bool onplane;\n  Vec<3> nv;\n  \npublic:\n  JacobianPointFunction (Mesh::T_POINTS & apoints, \n\t\t\t const Array<Element, ElementIndex> & aelements);\n  virtual ~JacobianPointFunction () { ; }\n  virtual void SetPointIndex (PointIndex aactpind);\n  virtual double Func (const Vector & x) const;\n  virtual double FuncGrad (const Vector & x, Vector & g) const;\n  virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n\n  inline void SetNV(const Vec<3> & anv) {nv = anv; onplane = true;}\n  inline void UnSetNV(void) {onplane = false;}\n};\n\n} // namespace netgen\n#endif\n"
  },
  {
    "path": "libsrc/meshing/localh.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\nnamespace netgen\n{\n\n  GradingBox :: GradingBox (const double * ax1, const double * ax2)\n  {\n    h2 = 0.5 * (ax2[0] - ax1[0]);\n    for (int i = 0; i < 3; i++)\n      xmid[i] = 0.5 * (ax1[i] + ax2[i]);\n\n    flags.cutboundary = 0;\n    flags.isinner = 0;\n    flags.oldcell = 0;\n    flags.pinner = 0;\n\n    hopt = 2 * h2;\n  }\n\n  void GradingBox :: DoArchive(Archive& ar)\n  {\n    ar & xmid[0] & xmid[1] & xmid[2] & h2 & father & hopt &\n      flags.cutboundary & flags.isinner & flags.oldcell & flags.pinner;\n    for(auto i : Range(8))\n      ar & childs[i];\n  }\n\n  BlockAllocator GradingBox :: ball(sizeof (GradingBox));\n\n  void * GradingBox :: operator new(size_t)\n  {\n    return ball.Alloc();\n  }\n\n  void GradingBox :: operator delete (void * p)\n  {\n    ball.Free (p);\n  }\n\n\n\n\n\n  void GradingBox :: DeleteChilds()\n  {\n    for (int i = 0; i < 8; i++)\n      if (childs[i])\n\t{\n\t  childs[i]->DeleteChilds();\n\t  delete childs[i];\n\t  childs[i] = NULL;\n\t}\n  }\n  \n\n  LocalH :: LocalH (Point<3> pmin, Point<3> pmax, double agrading, int adimension)\n    : dimension(adimension)\n  {\n    double x1[3], x2[3];\n    double hmax;\n\n    boundingbox = Box<3> (pmin, pmax);\n    grading = agrading;\n\n    // a small enlargement, non-regular points \n    double val = 0.0879;\n    for (int i = 0; i < dimension; i++)\n      {\n\tx1[i] = (1 + val * (i+1)) * pmin(i) - val * (i+1) * pmax(i);\n\tx2[i] = 1.1 * pmax(i) - 0.1 * pmin(i);\n      }\n    for (int i = dimension; i < 3; i++)\n      x1[i] = x2[i] = 0;\n\n    hmax = x2[0] - x1[0];\n    for (int i = 1; i < dimension; i++)\n      hmax = max2(x2[i]-x1[i], hmax);\n\n    for (int i = 0; i < dimension; i++)\n      x2[i] = x1[i] + hmax;\n\n    root = new GradingBox (x1, x2);\n    boxes.Append (root);\n  }\n\n  LocalH :: ~LocalH ()\n  {\n    root->DeleteChilds();\n    delete root;\n  }\n\n  unique_ptr<LocalH> LocalH :: Copy ()\n  {\n    static Timer t(\"LocalH::Copy\"); RegionTimer rt(t);\n    auto lh = make_unique<LocalH>(boundingbox, grading, dimension);\n    std::map<GradingBox*, GradingBox*> mapping;\n    lh->boxes.SetSize(boxes.Size());\n\n    for(auto i : boxes.Range())\n    {\n      lh->boxes[i] = new GradingBox();\n      auto & bnew = *lh->boxes[i];\n      auto & b = *boxes[i];\n      bnew.xmid[0] = b.xmid[0];\n      bnew.xmid[1] = b.xmid[1];\n      bnew.xmid[2] = b.xmid[2];\n      bnew.h2 = b.h2;\n      bnew.hopt = b.hopt;\n      bnew.flags = b.flags;\n      mapping[&b] = &bnew;\n    }\n\n    for(auto i : boxes.Range())\n    {\n      auto & bnew = *lh->boxes[i];\n      auto & b = *boxes[i];\n      for(auto k : Range(8))\n      {\n        if(b.childs[k])\n          bnew.childs[k] = mapping[b.childs[k]];\n      }\n\n      if(b.father)\n        bnew.father = mapping[b.father];\n    }\n\n    lh->root = mapping[root];\n    return lh;\n  }\n\n  unique_ptr<LocalH> LocalH :: Copy( const Box<3> & bbox )\n  {\n    static Timer t(\"LocalH::Copy with bounding box\"); RegionTimer rt(t);\n    auto lh = make_unique<LocalH>(boundingbox, grading, dimension);\n    std::map<GradingBox*, GradingBox*> mapping;\n    lh->boxes.SetAllocSize(boxes.Size());\n\n    for(auto i : boxes.Range())\n    {\n      auto & b = *boxes[i];\n      auto h = b.H2();\n      Vec<3> vh = {h,h,h};\n      Box<3> box( b.PMid() - vh, b.PMid() + vh);\n      if(!box.Intersect(bbox))\n          continue;\n      lh->boxes.Append(new GradingBox());\n      auto & bnew = *lh->boxes.Last();\n      bnew.xmid[0] = b.xmid[0];\n      bnew.xmid[1] = b.xmid[1];\n      bnew.xmid[2] = b.xmid[2];\n      bnew.h2 = b.h2;\n      bnew.hopt = b.hopt;\n      bnew.flags = b.flags;\n      mapping[&b] = &bnew;\n    }\n\n    for(auto i : boxes.Range())\n    {\n      auto & b = *boxes[i];\n      if(mapping.count(&b)==0)\n          continue;\n\n      auto & bnew = *mapping[&b];\n      for(auto k : Range(8))\n      {\n        if(b.childs[k] && mapping.count(b.childs[k]))\n          bnew.childs[k] = mapping[b.childs[k]];\n      }\n\n      if(b.father && mapping.count(b.father))\n        bnew.father = mapping[b.father];\n    }\n\n    lh->root = mapping[root];\n    return lh;\n\n  }\n\n  void LocalH :: Delete ()\n  {\n    root->DeleteChilds();\n  }\n\n  void LocalH :: DoArchive(Archive& ar)\n  {\n    ar & root & grading & boxes & boundingbox & dimension;\n  }\n\n  void LocalH :: SetH (Point<3> p, double h)\n  {\n    if (dimension == 2)\n      {\n        if (fabs (p(0) - root->xmid[0]) > root->h2 ||\n            fabs (p(1) - root->xmid[1]) > root->h2)\n          return;\n        \n        GradingBox * box = Find(p);\n        if (box->HOpt() <= 1.2 * h) return;\n        \n        while (2 * box->h2 > h)\n          {\n            int childnr = 0;\n            double x1[3], x2[3];\n        \n            double h2 = box->h2;\n            if (p(0) > box->xmid[0])\n              {\n                childnr += 1;\n                x1[0] = box->xmid[0];\n                x2[0] = x1[0]+h2;\n              }\n            else\n              {\n                x2[0] = box->xmid[0];\n                x1[0] = x2[0]-h2;\n              }\n            \n            if (p(1) > box->xmid[1])\n              {\n                childnr += 2;\n                x1[1] = box->xmid[1];\n                x2[1] = x1[1]+h2;\n              }\n            else\n              {\n                x2[1] = box->xmid[1];\n                x1[1] = x2[1]-h2;\n              }\n            x1[2] = x2[2] = 0;\n\n            auto ngb = new GradingBox (x1, x2);\n            box->childs[childnr] = ngb;\n            ngb->father = box;\n            \n            boxes.Append (ngb);\n            box = box->childs[childnr];\n          }\n\n        box->hopt = h;\n        \n        double hbox = 2 * box->h2;  // box->x2[0] - box->x1[0];\n        double hnp = h + grading * hbox;\n        \n        Point<3> np;\n        for (int i = 0; i < 2; i++)\n          {\n            np = p;\n            np(i) = p(i) + hbox;\n            SetH (np, hnp);\n            \n            np(i) = p(i) - hbox;\n            SetH (np, hnp);\n          }\n\n      }\n\n    else\n      {\n        if (fabs (p(0) - root->xmid[0]) > root->h2 ||\n            fabs (p(1) - root->xmid[1]) > root->h2 ||\n            fabs (p(2) - root->xmid[2]) > root->h2)\n          return;\n        \n        GradingBox * box = Find(p);\n        if (box->HOpt() <= 1.2 * h) return;\n        \n        while (2 * box->h2 > h)\n          {\n            double x1[3], x2[3];\n            int childnr = 0;\n            double h2 = box->h2;\n\n            if (p(0) > box->xmid[0])\n              {\n                childnr += 1;\n                x1[0] = box->xmid[0];\n                x2[0] = x1[0]+h2;\n              }\n            else\n              {\n                x2[0] = box->xmid[0];\n                x1[0] = x2[0]-h2;\n              }\n            \n            if (p(1) > box->xmid[1])\n              {\n                childnr += 2;\n                x1[1] = box->xmid[1];\n                x2[1] = x1[1]+h2;\n              }\n            else\n              {\n                x2[1] = box->xmid[1];\n                x1[1] = x2[1]-h2;\n              }\n            \n            if (p(2) > box->xmid[2])\n              {\n                childnr += 4;\n                x1[2] = box->xmid[2];\n                x2[2] = x1[2]+h2;\n              }\n            else\n              {\n                x2[2] = box->xmid[2];\n                x1[2] = x2[2]-h2;\n              }\n            \n            auto ngb = new GradingBox (x1, x2);\n            box->childs[childnr] = ngb;\n            ngb->father = box;\n            \n            boxes.Append (ngb);\n            box = box->childs[childnr];\n          }\n\n        box->hopt = h;\n        \n        double hbox = 2 * box->h2;  // box->x2[0] - box->x1[0];\n        double hnp = h + grading * hbox;\n        \n        Point<3> np;\n        for (int i = 0; i < 3; i++)\n          {\n            np = p;\n            np(i) = p(i) + hbox;\n            SetH (np, hnp);\n            \n            np(i) = p(i) - hbox;\n            SetH (np, hnp);\n          }\n      }\n  }\n\n\n\n  double LocalH :: GetH (Point<3> x) const\n  {\n    return Find(x)->HOpt();\n  }\n\n\n  /// minimal h in box (pmin, pmax)\n  double LocalH :: GetMinH (Point<3> pmin, Point<3> pmax) const\n  { \n    Point<3> pmin2, pmax2;\n    for (int j = 0; j < 3; j++)\n      if (pmin(j) < pmax(j))\n\t{ pmin2(j) = pmin(j); pmax2(j) = pmax(j); }\n      else\n\t{ pmin2(j) = pmax(j); pmax2(j) = pmin(j); }\n\n    return GetMinHRec (pmin2, pmax2, root); \n  }\n\n\n  double LocalH :: GetMinHRec (const Point3d & pmin, const Point3d & pmax,\n\t\t\t       const GradingBox * box) const\n  {\n    if (dimension == 2)\n      {\n        double h2 = box->h2;\n        if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 ||\n            pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2)\n          return 1e8;\n        \n        double hmin = 2 * box->h2; // box->x2[0] - box->x1[0];\n        \n        for (int i = 0; i < 8; i++)\n          if (box->childs[i])\n            hmin = min2 (hmin, GetMinHRec (pmin, pmax, box->childs[i]));\n        \n        return hmin;\n      }\n    else\n      {\n        double h2 = box->h2;\n        if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 ||\n            pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 ||\n            pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2)\n          return 1e8;\n        \n        double hmin = 2 * box->h2; // box->x2[0] - box->x1[0];\n        \n        for (int i = 0; i < 8; i++)\n          if (box->childs[i])\n            hmin = min2 (hmin, GetMinHRec (pmin, pmax, box->childs[i]));\n        \n        return hmin;\n      }\n  }\n\n\n\n\n\n\n\n\n\n  void LocalH :: CutBoundaryRec (const Point3d & pmin, const Point3d & pmax,\n\t\t\t\t GradingBox * box)\n  {\n    double h2 = box->h2;\n    if (dimension == 2)\n      {\n        if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 ||\n            pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2)\n          return;\n      }\n    else\n      {\n        if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 ||\n            pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 ||\n            pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2)\n          return;\n      }\n\n    if (!box->flags.cutboundary)\n      for (int i = 0; i < 8; i++)\n        if (box->childs[i])\n          box->childs[i]->flags.cutboundary = false;\n    \n    box->flags.cutboundary = true;\n    for (int i = 0; i < 8; i++)\n      if (box->childs[i])\n\tCutBoundaryRec (pmin, pmax, box->childs[i]);\n  }\n\n\n  GradingBox * LocalH :: Find (Point<3> p) const\n  {\n    GradingBox * box = root;\n    if (dimension == 2)\n      {\n        while (1)\n          {\n            int childnr = 0;\n            if (p(0) > box->xmid[0]) childnr += 1;\n            if (p(1) > box->xmid[1]) childnr += 2;\n\n            if (box->childs[childnr])\n              box = box->childs[childnr];\n            else\n              return box;\n          }\n      }\n    else\n      {\n        while (1)\n          {\n            int childnr = 0;\n            if (p(0) > box->xmid[0]) childnr += 1;\n            if (p(1) > box->xmid[1]) childnr += 2;\n            if (p(2) > box->xmid[2]) childnr += 4;\n\n            if (box->childs[childnr])\n              box = box->childs[childnr];\n            else\n              return box;\n          }\n      }\n    return nullptr;\n  }\n\n\n  void LocalH :: FindInnerBoxes (const AdFront3 & adfront,\n\t\t\t\t int (*testinner)(const Point3d & p1))\n  {\n    static Timer timer(\"LocalH::FindInnerBoxes\");\n    RegionTimer reg (timer);\n\n\n    int nf = adfront.GetNF();\n\n    for (int i = 0; i < boxes.Size(); i++)\n      boxes[i] -> flags.isinner = 0;\n\n    root->flags.isinner = 0;\n\n    Point3d rpmid(root->xmid[0], root->xmid[1], root->xmid[2]);\n    Vec3d rv(root->h2, root->h2, root->h2);\n    Point3d rx2 = rpmid + rv;\n    // Point3d rx1 = rpmid - rv;\n\n\n    root->flags.pinner = !adfront.SameSide (rpmid, rx2);\n    \n    if (testinner)\n      (*testout) << \"inner = \" << root->flags.pinner << \" =?= \" \n\t\t << testinner(Point3d(root->xmid[0], root->xmid[1], root->xmid[2])) << endl;\n\n    NgArray<int> faceinds(nf);\n    NgArray<Box3d> faceboxes(nf);\n\n    for (int i = 1; i <= nf; i++)\n      {\n\tfaceinds.Elem(i) = i;\n\tadfront.GetFaceBoundingBox(i, faceboxes.Elem(i));\n      }\n  \n    for (int i = 0; i < 8; i++)\n      FindInnerBoxesRec2 (root->childs[i], adfront, faceboxes, faceinds, nf);\n  }\n\n\n  void LocalH :: \n  FindInnerBoxesRec2 (GradingBox * box,\n\t\t      const AdFront3 & adfront, \n\t\t      NgArray<Box3d> & faceboxes,\n\t\t      NgArray<int> & faceinds, int nfinbox)\n  {\n    if (!box) return;\n  \n    GradingBox * father = box -> father;\n  \n    Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]);\n    Vec3d v(box->h2, box->h2, box->h2);\n    Box3d boxc(c-v, c+v);\n\n    Point3d fc(father->xmid[0], father->xmid[1], father->xmid[2]);\n    Vec3d fv(father->h2, father->h2, father->h2);\n    Box3d fboxc(fc-fv, fc+fv);\n\n    Box3d boxcfc(c,fc);\n\n    NgArrayMem<int, 100> faceused;\n    NgArrayMem<int, 100> faceused2;\n    NgArrayMem<int, 100> facenotused;\n\n    /*\n    faceused.SetSize(0);\n    facenotused.SetSize(0);\n    faceused2.SetSize(0);\n    */\n\n    for (int j = 1; j <= nfinbox; j++)\n      {\n\t//      adfront->GetFaceBoundingBox (faceinds.Get(j), facebox);\n\tconst Box3d & facebox = faceboxes.Get(faceinds.Get(j));\n  \n\tif (boxc.Intersect (facebox))\n\t  faceused.Append(faceinds.Get(j));\n\telse\n\t  facenotused.Append(faceinds.Get(j));\n\n\tif (boxcfc.Intersect (facebox))\n\t  faceused2.Append (faceinds.Get(j));\n      }\n  \n    for (int j = 1; j <= faceused.Size(); j++)\n      faceinds.Elem(j) = faceused.Get(j);\n    for (int j = 1; j <= facenotused.Size(); j++)\n      faceinds.Elem(j+faceused.Size()) = facenotused.Get(j);\n\n  \n    if (!father->flags.cutboundary)\n      {\n\tbox->flags.isinner = father->flags.isinner;\n\tbox->flags.pinner = father->flags.pinner;\n      }\n    else\n      {\n\tPoint3d cf(father->xmid[0], father->xmid[1], father->xmid[2]);\n      \n\tif (father->flags.isinner)\n\t  box->flags.pinner = 1;\n\telse\n\t  {\n\t    if (adfront.SameSide (c, cf, &faceused2))\n\t      box->flags.pinner = father->flags.pinner;\n\t    else\n\t      box->flags.pinner = 1 - father->flags.pinner;\n\t  }\n      \n\tif (box->flags.cutboundary)\n\t  box->flags.isinner = 0;\n\telse\n\t  box->flags.isinner = box->flags.pinner;\n      }\n\n    // cout << \"faceused: \" << faceused.Size() << \", \" << faceused2.Size() << \", \" << facenotused.Size() << endl;\n\n    int nf = faceused.Size();\n    for (int i = 0; i < 8; i++)\n      FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf);\n  }\n\n\n\n  void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point3d & p),\n\t\t\t\t     GradingBox * box)\n  {\n    if (box->flags.cutboundary)\n      {\n\tfor (int i = 0; i < 8; i++)\n\t  if (box->childs[i])\n\t    FindInnerBoxesRec (inner, box->childs[i]);\n      }\n    else\n      {\n\tif (inner (box->PMid()))\n\t  SetInnerBoxesRec (box);\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void LocalH :: FindInnerBoxes (const AdFront2 & adfront,\n\t\t\t\t int (*testinner)(const Point<2> & p1))\n  {\n    static Timer t(\"LocalH::FindInnerBoxes 2d\"); RegionTimer reg (t);\n    static Timer trec(\"LocalH::FindInnerBoxes 2d - rec\");\n    static Timer tinit(\"LocalH::FindInnerBoxes 2d - init\");     \n\n    /*\n    tinit.Start();\n    for (int i = 0; i < boxes.Size(); i++)\n      boxes[i] -> flags.isinner = 0;\n    tinit.Stop();\n    */\n    \n    root->flags.isinner = 0;\n    root->flags.cutboundary = true;\n\n    Point<2> rpmid(root->xmid[0], root->xmid[1]);   // , root->xmid[2]);\n    Vec<2> rv(root->h2, root->h2);\n    Point<2> rx2 = rpmid + rv;\n    // Point<2> rx1 = rpmid - rv;\n\n\n    root->flags.pinner = !adfront.SameSide (rpmid, rx2);\n  \n    if (testinner)\n      (*testout) << \"inner = \" << root->flags.pinner << \" =?= \"\n\t\t << testinner(rpmid) << endl;\n\n\n    int nf = adfront.GetNFL();\n    Array<int> faceinds(nf);\n    Array<Box<2>> faceboxes(nf);\n\n    for (int i = 0; i < nf; i++)\n      {\n\tfaceinds[i] = i;\n\tconst FrontLine & line = adfront.GetLine(i);\n        Point<3> p1 = adfront.GetPoint (line.L().I1());\n        Point<3> p2 = adfront.GetPoint (line.L().I2());\n        \n\tfaceboxes[i].Set (Point<2> (p1(0), p1(1)));\n\tfaceboxes[i].Add (Point<2> (p2(0), p2(1)));\n      }\n\n    RegionTimer regrc(trec);\n    for (int i = 0; i < 8; i++)\n      FindInnerBoxesRec2 (root->childs[i], adfront, faceboxes, faceinds); // , nf);\n  }\n\n\n  void LocalH :: \n  FindInnerBoxesRec2 (GradingBox * box,\n\t\t      const class AdFront2 & adfront, \n\t\t      FlatArray<Box<2>> faceboxes,\n\t\t      FlatArray<int> faceinds) // , int nfinbox)\n  {\n    if (!box) return;\n\n    GradingBox * father = box -> father;    \n    \n    if (!father->flags.cutboundary)\n      {\n\tbox->flags.isinner = father->flags.isinner;\n\tbox->flags.pinner = father->flags.pinner;\n        box->flags.cutboundary = false;\n      }\n    else\n      {        \n\tif (father->flags.isinner)\n          {\n            cout << \"how is this possible ???\" << endl;\n            box->flags.pinner = 1;\n          }\n\telse\n\t  {\n            Point<2> c(box->xmid[0], box->xmid[1]); \n            Point<2> fc(father->xmid[0], father->xmid[1]); \n            Box<2> boxcfc(c,fc);\n\n            // reorder: put faces cutting boxcfc first:\n            int iused = 0;\n            int inotused = faceinds.Size()-1;\n            while (iused <= inotused)\n              {\n                while ( (iused <= inotused) && boxcfc.Intersect (faceboxes[faceinds[iused]]))\n                  iused++;\n                while ( (iused <= inotused) && !boxcfc.Intersect (faceboxes[faceinds[inotused]]))\n                  inotused--;\n                if (iused < inotused)\n                  {\n                    Swap (faceinds[iused], faceinds[inotused]);\n                    iused++;\n                    inotused--;\n                  }\n              }\n\n            // bool sameside = adfront->SameSide (c2d, cf2d, &faceused2);\n            auto sub = faceinds.Range(0, iused);\n            bool sameside = adfront.SameSide (c, fc, &sub);\n            if (sameside)\n\t      box->flags.pinner = father->flags.pinner;\n\t    else\n\t      box->flags.pinner = 1 - father->flags.pinner;\n\t  }\n      \n\tif (box->flags.cutboundary)\n\t  box->flags.isinner = 0;\n\telse\n\t  box->flags.isinner = box->flags.pinner;\n      }\n\n\n    \n    int iused = 0;\n    if (faceinds.Size())\n      {\n        Point<2> c(box->xmid[0], box->xmid[1]); // box->xmid[2]);\n        Vec<2> v(box->h2, box->h2);\n        Box<2> boxc(c-v, c+v);\n        \n        // reorder again: put faces cutting boxc first:    \n        int inotused = faceinds.Size()-1;\n        while (iused <= inotused)\n          {\n            while ( (iused <= inotused) && boxc.Intersect (faceboxes[faceinds[iused]]))\n              iused++;\n            while ( (iused <= inotused) && !boxc.Intersect (faceboxes[faceinds[inotused]]))\n              inotused--;\n            if (iused < inotused)\n              {\n                Swap (faceinds[iused], faceinds[inotused]);\n                iused++;\n                inotused--;\n              }\n          }\n      }\n\n\n    if (box->flags.isinner || box->flags.cutboundary)\n      for (int i = 0; i < 8; i++)\n        FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds.Range(0,iused));\n  }\n\n\n\n  void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point<2> & p),\n\t\t\t\t     GradingBox * box)\n  {\n    if (box->flags.cutboundary)\n      {\n\tfor (int i = 0; i < 8; i++)\n\t  if (box->childs[i])\n\t    FindInnerBoxesRec (inner, box->childs[i]);\n      }\n    else\n      {\n\tPoint<2> p2d(box->PMid()(0), box->PMid()(1)); \n\tif (inner (p2d))\n\t  SetInnerBoxesRec (box);\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void LocalH :: SetInnerBoxesRec (GradingBox * box)\n  {\n    box->flags.isinner = 1;\n    for (int i = 0; i < 8; i++)\n      if (box->childs[i])\n\tClearFlagsRec (box->childs[i]);\n  }\n\n  void LocalH :: ClearRootFlags ()\n  {\n    root->flags.cutboundary = false;\n    root->flags.isinner = false;\n  }\n\n  \n  void LocalH :: ClearFlagsRec (GradingBox * box)\n  {\n    box->flags.cutboundary = 0;\n    box->flags.isinner = 0;\n    for (int i = 0; i < 8; i++)\n      if (box->childs[i])\n\tClearFlagsRec (box->childs[i]);\n  }\n\n\n  void LocalH :: WidenRefinement ()\n  {\n    for (int i = 0; i < boxes.Size(); i++)\n      {\n\tdouble h = boxes[i]->hopt;\n\tPoint3d c = boxes[i]->PMid();\n      \n\tfor (int i1 = -1; i1 <= 1; i1++)\n\t  for (int i2 = -1; i2 <= 1; i2++)\n\t    for (int i3 = -1; i3 <= 1; i3++)\n\t      SetH (Point3d (c.X() + i1 * h, \n\t\t\t     c.Y() + i2 * h,\n\t\t\t     c.Z() + i3 * h), 1.001 * h);     \n      }\n  }\n\n  void LocalH :: GetInnerPoints (NgArray<Point<3> > & points) const\n  {\n    static Timer t(\"GetInnerPoints\"); RegionTimer reg(t);\n    if (dimension == 2)\n      {\n        GetInnerPointsRec (root, points);\n        /*\n        for (int i = 0; i < boxes.Size(); i++)\n          if (boxes[i] -> flags.isinner && boxes[i] -> HasChilds())\n            points.Append ( boxes[i] -> PMid() );\n        */\n      }\n    else\n      {\n        for (int i = 0; i < boxes.Size(); i++)\n          if (boxes[i] -> flags.isinner)\n            points.Append ( boxes[i] -> PMid() );\n      }\n          \n  }\n\n  void LocalH :: GetInnerPointsRec (const GradingBox * box, NgArray<Point<3> > & points) const\n  {\n    if (box -> flags.isinner && box -> HasChilds())\n      points.Append ( box -> PMid() );\n\n    if (box->flags.isinner || box->flags.cutboundary)\n      for (int i = 0; i < 8; i++)\n        if (box->childs[i])\n          GetInnerPointsRec (box->childs[i], points);\n  }\n\n  \n  void LocalH :: GetOuterPoints (NgArray<Point<3> > & points)\n  {\n    static Timer t(\"LocalH::GetOuterPoints\"); RegionTimer rt(t);\n    for (int i = 0; i < boxes.Size(); i++)\n      if (!boxes[i]->flags.isinner && !boxes[i]->flags.cutboundary)\n\tpoints.Append ( boxes[i] -> PMid());\n  }\n\n\n  void LocalH :: Convexify ()\n  {\n    ConvexifyRec (root);\n  }\n\n  void LocalH :: ConvexifyRec (GradingBox * box)\n  {\n    Point<3> center = box -> PMid();\n\n    double size = 2 * box->h2; // box->x2[0] - box->x1[0];\n    double dx = 0.6 * size;\n\n    double maxh = box->hopt;\n  \n    for (int i = 0; i < 3; i++)\n      {\n\tPoint<3> hp = center;\n\thp(i) += dx;\n\tmaxh = max2 (maxh, GetH(hp));\n\thp(i) = center(i)-dx;\n\tmaxh = max2 (maxh, GetH(hp));\n      }\n\n    if (maxh < 0.95 * box->hopt)\n      SetH (center, maxh);\n\n    for (int i = 0; i < 8; i++)\n      if (box->childs[i])\n\tConvexifyRec (box->childs[i]);  \n  }\n\n  void LocalH :: PrintMemInfo (ostream & ost) const\n  {\n    ost << \"LocalH: \" << boxes.Size() << \" boxes of \" << sizeof(GradingBox)\n\t<< \" bytes = \" << boxes.Size()*sizeof(GradingBox) << \" bytes\" << endl;\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/localh.hpp",
    "content": "#ifndef LOCALH\n#define LOCALH\n\n/**************************************************************************/\n/* File:   localh.hh                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   29. Jan. 97                                                    */\n/**************************************************************************/\n\n\nnamespace netgen\n{\n\n\n  /// box for grading\n  class GradingBox\n  {\n    /// xmid\n    float xmid[3];\n    /// half edgelength\n    float h2;\n    ///\n    GradingBox * childs[8] = {nullptr};\n    ///\n    GradingBox * father = nullptr;\n    ///\n    double hopt;\n    ///\n  public:\n\n    struct \n    {\n      /*\n      unsigned int cutboundary:1;\n      unsigned int isinner:1;\n      unsigned int oldcell:1;\n      unsigned int pinner:1;\n      */\n      bool cutboundary;\n      bool isinner;\n      bool oldcell;\n      bool pinner;\n    } flags;\n\n    ///\n    GradingBox (const double * ax1, const double * ax2);\n    /// default constructor for Archive\n    GradingBox() = default;\n    ///\n    void DeleteChilds();\n    ///\n\n    void DoArchive(Archive& ar);\n\n    Point<3> PMid() const { return Point<3> (xmid[0], xmid[1], xmid[2]); }\n    double H2() const { return h2; }\n    double HOpt() const { return hopt; }\n\n    bool HasChilds() const\n    {\n      for (int i = 0; i < 8; i++)\n        if (childs[i]) return true;\n      return false;\n    }\n    \n    friend class LocalH;\n\n    static BlockAllocator ball;\n    void * operator new(size_t);\n    void operator delete (void *);\n  };\n\n\n\n\n  /**\n     Control of 3D mesh grading\n  */\n  class LocalH \n  {\n    ///\n    GradingBox * root;\n    ///\n    double grading;\n    ///\n    Array<GradingBox*> boxes;\n    ///\n    Box<3> boundingbox;\n    /// octree or quadtree\n    int dimension;\n  public:\n    ///\n    DLL_HEADER LocalH (Point<3> pmin, Point<3> pmax, double grading, int adimension = 3);\n    ///\n    LocalH (const Box<3> & box, double grading, int adimension = 3)\n      : LocalH (box.PMin(), box.PMax(), grading, adimension) { ; }\n    /// Default ctor for archive\n    LocalH() = default;\n\n    DLL_HEADER ~LocalH();\n    ///\n    DLL_HEADER unique_ptr<LocalH> Copy();\n    DLL_HEADER unique_ptr<LocalH> Copy( const Box<3> & bbox );\n    ///\n    DLL_HEADER void Delete();\n    ///\n    DLL_HEADER void DoArchive(Archive& ar);\n    ///\n    void SetGrading (double agrading) { grading = agrading; }\n    ///\n    DLL_HEADER void SetH (Point<3> x, double h);\n    ///\n    DLL_HEADER double GetH (Point<3> x) const;\n    /// minimal h in box (pmin, pmax)\n    DLL_HEADER double GetMinH (Point<3> pmin, Point<3> pmax) const;\n\n    /// mark boxes intersecting with boundary-box\n    // void CutBoundary (const Point3d & pmin, const Point3d & pmax)\n    // { CutBoundaryRec (pmin, pmax, root); }\n\n    void CutBoundary (const Box<3> & box)\n    { CutBoundaryRec (box.PMin(), box.PMax(), root); }\n\n    GradingBox * Find(Point<3> p) const;\n  \n    /// find inner boxes\n    void FindInnerBoxes (const class AdFront3 & adfront,\n\t\t\t int (*testinner)(const Point3d & p1));\n\n    void FindInnerBoxes (const class AdFront2 & adfront,\n\t\t\t int (*testinner)(const Point<2> & p1));\n\n\n    /// clears all flags \n    void ClearFlags ()\n    { ClearFlagsRec(root); }\n\n    void ClearRootFlags ();\n\n    /// widen refinement zone\n    void WidenRefinement ();\n\n    /// get points in inner elements\n    void GetInnerPoints (NgArray<Point<3> > & points) const;\n    void GetInnerPointsRec (const GradingBox * box, NgArray<Point<3> > & points) const;\n\n    /// get points in outer closure\n    void GetOuterPoints (NgArray<Point<3> > & points);\n\n    ///\n    void Convexify ();\n    ///\n    int GetNBoxes () { return boxes.Size(); } \n    const Box<3> & GetBoundingBox () const\n    { return boundingbox; }\n    ///\n    void PrintMemInfo (ostream & ost) const;\n  private:\n    /// \n    double GetMinHRec (const Point3d & pmin, const Point3d & pmax,\n\t\t       const GradingBox * box) const;\n    ///\n    void CutBoundaryRec (const Point3d & pmin, const Point3d & pmax,\n\t\t\t GradingBox * box);\n\n    ///\n    void FindInnerBoxesRec ( int (*inner)(const Point3d & p),\n\t\t\t     GradingBox * box);\n\n    ///\n    void FindInnerBoxesRec2 (GradingBox * box,\n\t\t\t     const class AdFront3 & adfront,\n\t\t\t     NgArray<Box3d> & faceboxes,\n\t\t\t     NgArray<int> & finds, int nfinbox);\n\n\n\n    void FindInnerBoxesRec ( int (*inner)(const Point<2> & p),\n\t\t\t     GradingBox * box);\n\n    ///\n    void FindInnerBoxesRec2 (GradingBox * box,\n\t\t\t     const class AdFront2 & adfront,\n\t\t\t     FlatArray<Box<2>> faceboxes,\n\t\t\t     FlatArray<int> finds); // , int nfinbox);\n\n\n\n    ///\n    void SetInnerBoxesRec (GradingBox * box);\n\n    ///\n    void ClearFlagsRec (GradingBox * box);\n  \n    ///\n    void ConvexifyRec (GradingBox * box);\n\n    unique_ptr<LocalH> CopyRec( const Box<3> & bbox, GradingBox * current );\n\n    friend ostream & operator<< (ostream & ost, const LocalH & loch);\n  };\n\n\n\n\n  inline ostream & operator<< (ostream & ost, const GradingBox & box)\n  {\n    ost << \"gradbox, pmid = \" << box.PMid() << \", h2 = \" << box.H2() \n\t<< \" cutbound = \" << box.flags.cutboundary << \" isinner = \" << box.flags.isinner \n\t<< endl;\n    return ost;\n  }\n\n  inline ostream & operator<< (ostream & ost, const LocalH & loch)\n  {\n    for (int i = 0; i < loch.boxes.Size(); i++)\n      ost << \"box[\" << i << \"] = \" << *(loch.boxes[i]);\n    return ost;\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/meshclass.cpp",
    "content": "#include <algorithm>\n#include <mystdlib.h>\n#include <atomic>\n#include <regex>\n#include <set>\n#include \"core/array.hpp\"\n#include \"meshing.hpp\"\n#include \"../general/gzstream.h\"\n\n#include <core/register_archive.hpp>\n#include \"basegeom.hpp\"\n\nnamespace netgen\n{\n  ElementIndex Find3dElement (const Mesh& mesh,\n                              const netgen::Point<3> & p,\n                              double * lami,\n                              optional<FlatArray<int>> indices,\n                              BoxTree<3, ElementIndex> * searchtree,\n                              const bool allowindex,\n                              double tol=1e-4)\n  {\n    int ne = 0;\n    Array<ElementIndex> locels;\n    if (searchtree)\n      {\n        searchtree->GetIntersecting (p, p, locels);\n        ne = locels.Size();\n      }\n    else\n      ne = mesh.GetNE();\n\n    for (auto i : Range(ne))\n      {\n        ElementIndex ei;\n\n        if (searchtree)\n          ei = locels[i];\n        else\n          ei = i;\n\n        if(indices && indices->Size() > 0)\n          {\n            bool contained = indices->Contains(mesh[ei].GetIndex());\n            if((allowindex && !contained) || (!allowindex && contained)) continue;\n          }\n\n        if(mesh.PointContainedIn3DElement(p,lami,ei, tol))\n          return ei;\n      }\n\n    // Not found, try uncurved variant:\n    for (auto i : Range(ne))\n      {\n        ElementIndex ei;\n\n        if (searchtree)\n          ei = locels[i];\n        else\n          ei = i;\n\n        if(indices && indices->Size() > 0)\n          {\n            bool contained = indices->Contains(mesh[ei].GetIndex());\n            if((allowindex && !contained) || (!allowindex && contained)) continue;\n          }\n\n\n        if(mesh.PointContainedIn3DElementOld(p,lami,ei, tol))\n          {\n            (*testout) << \"WARNING: found element of point \" << p <<\" only for uncurved mesh\" << endl;\n            return ei;\n          }\n      }\n    return ElementIndex::INVALID;\n  }\n\n  SurfaceElementIndex\n  Find2dElement (const Mesh& mesh,\n                 const netgen::Point<3> & p,\n                 double * lami,\n                 std::optional<FlatArray<int>> indices,\n                 BoxTree<3, SurfaceElementIndex> * searchtree,\n                 bool allowindex)\n  {\n    double vlam[3];\n    ElementIndex velement = ElementIndex::INVALID;\n\n    if(mesh.GetNE())\n      {\n        if(searchtree)\n          const_cast<Mesh&>(mesh).BuildElementSearchTree(3);\n        velement = Find3dElement(mesh, p,vlam, nullopt,searchtree ? mesh.GetElementSearchTree() : nullptr,allowindex);\n      }\n\n    //(*testout) << \"p \" << p << endl;\n    //(*testout) << \"velement \" << velement << endl;\n\n    // first try to find a volume element containing p and project to face\n    if(velement.IsValid())\n    {\n      auto & topology = mesh.GetTopology();\n      const auto & fnrs = topology.GetFaces(velement);\n      auto faces = ArrayMem<SurfaceElementIndex,4>();\n      for(auto face : fnrs)\n        faces.Append(topology.GetFace2SurfaceElement(face));\n\n      for(int i=0; i<faces.Size(); i++)\n        {\n          if(!faces[i].IsValid())\n            continue;\n          auto sel = mesh.SurfaceElement(faces[i]);\n          if(indices && indices->Size() > 0 && !indices->Contains(sel.GetIndex()))\n            continue;\n\n          auto & el = mesh[velement];\n          if (el.GetType() == TET)\n          {\n            double lam4[4] = { vlam[0], vlam[1], vlam[2], 1.0-vlam[0]-vlam[1]-vlam[2] };\n            double face_lam = lam4[i];\n            if(face_lam < 1e-5)\n            {\n              // found volume point very close to a face -> use barycentric coordinates directly\n              lami[2] = 0.0;\n              for(auto j : Range(1,3))\n                for(auto k : Range(4))\n                  if(sel[j] == el[k])\n                    lami[j-1] = lam4[k]/(1.0-face_lam);\n              return SurfaceElementIndex(faces[i]);\n            }\n          }\n\n          if(mesh.PointContainedIn2DElement(p,lami,faces[i],true))\n            return faces[i];\n        }\n    }\n\n    // Did't find any matching face of a volume element, search 2d elements directly\n    int ne;\n\n    Array<SurfaceElementIndex> locels;\n    if (searchtree)\n      {\n        searchtree->GetIntersecting (p, p, locels);\n        ne = locels.Size();\n      }\n    else\n      ne = mesh.GetNSE();\n\n    for (auto i : Range(ne))\n      {\n        SurfaceElementIndex ii;\n\n        if (locels.Size())\n          ii = locels[i];\n        else\n          ii = i;\n\n        if(indices && indices->Size() > 0)\n          {\n            bool contained = indices->Contains(mesh[ii].GetIndex());\n            if((allowindex && !contained) || (!allowindex && contained)) continue;\n          }\n        if(mesh.PointContainedIn2DElement(p,lami,ii))\n          return ii;\n      }\n    return SurfaceElementIndex::INVALID;\n  }\n\n  SegmentIndex Find1dElement (const Mesh& mesh,\n                              const netgen::Point<3> & p,\n                              double * lami,\n                              std::optional<FlatArray<int>> indices,\n                              BoxTree<3> * searchtree,\n                              const bool allowindex = true)\n  {\n    double vlam[3];\n    if(searchtree)\n      const_cast<Mesh&>(mesh).BuildElementSearchTree(2);\n    auto velement = Find2dElement(mesh, p, vlam, nullopt, searchtree ? mesh.GetSurfaceElementSearchTree() : nullptr, allowindex);\n    if(!velement.IsValid())\n      return 0;\n\n    vlam[2] = 1.-vlam[0] - vlam[1];\n    // NgArray<int> edges;\n    auto & topology = mesh.GetTopology();\n\n    /*\n    topology.GetSurfaceElementEdges(velement, edges);\n    Array<SegmentIndex> segs(edges.Size());\n    for(auto i : Range(edges))\n      segs[i] = topology.GetSegmentOfEdge(edges[i]);\n    */\n    auto hedges = topology.GetEdges(SurfaceElementIndex(velement-1));\n    Array<SegmentIndex> segs(hedges.Size());\n    for(auto i : Range(hedges))\n      segs[i] = topology.GetSegmentOfEdge(hedges[i]+1);\n    \n    \n    for(auto i : Range(segs))\n      {\n        if(IsInvalid(segs[i]))\n          continue;\n        auto& el = mesh.SurfaceElement(velement);\n        if(el.GetType() == TRIG)\n          {\n            double seg_lam=-1;\n            double lam=-1;\n            auto seg = mesh.LineSegment(segs[i]);\n                for(auto k : Range(3))\n                  {\n                    if(seg[0] == el[k])\n                      lam = vlam[k];\n                    if(seg[1] == el[k])\n                      seg_lam = vlam[k];\n                  }\n            if(1.- seg_lam - lam < 1e-5)\n              {\n                // found point close to segment -> use barycentric coordinates directly\n                lami[0] = lam;\n                return int(segs[i])+1;\n              }\n          }\n        else\n          throw NgException(\"Quad not implemented yet!\");\n      }\n\n    return 0;\n  }\n\n  static mutex buildsearchtree_mutex;\n\n  Mesh :: Mesh ()\n    : topology(*this), surfarea(*this)\n  {\n    lochfunc = {nullptr};\n    for(auto i : Range(4))\n      elementsearchtreets[i] = NextTimeStamp();\n    majortimestamp = timestamp = NextTimeStamp();\n    hglob = 1e10;\n    hmin = 0;\n    numvertices = -1;\n    dimension = 3;\n\n    curvedelems = make_unique<CurvedElements> (*this);\n    clusters = make_unique<AnisotropicClusters> (*this);\n    ident = make_unique<Identifications> (*this);\n\n    ps_startelement = 0;\n\n    geomtype = NO_GEOM;\n\n    bcnames.SetSize(0);\n    cd2names.SetSize(0);\n\n#ifdef PARALLEL\n    paralleltop = make_unique<ParallelMeshTopology> (*this);\n#endif\n  }\n\n\n  Mesh :: ~Mesh()\n  {\n    for (int i = 0; i < materials.Size(); i++)\n      delete materials[i];\n    for(int i = 0; i < userdata_int.Size(); i++)\n      delete userdata_int[i];\n    for(int i = 0; i < userdata_double.Size(); i++)\n      delete userdata_double[i];\n\n    for (int i = 0; i < bcnames.Size(); i++ )\n      delete bcnames[i];\n\n    for (int i = 0; i < cd2names.Size(); i++)\n      delete cd2names[i];\n\n    for (int i = 0; i < cd3names.Size(); i++)\n      delete cd3names[i];\n\n    // #ifdef PARALLEL\n    // delete paralleltop;\n    // #endif\n  }\n\n  shared_ptr<NetgenGeometry> Mesh :: GetGeometry() const\n  {\n    static auto global_geometry = make_shared<NetgenGeometry>();\n    return geometry ? geometry : global_geometry;\n  }\n\n  void Mesh :: SetCommunicator(NgMPI_Comm acomm)\n  {\n    this->comm = acomm;\n  }\n\n  Mesh & Mesh :: operator= (const Mesh & mesh2)\n  {\n    geometry = mesh2.geometry;\n    dimension = mesh2.dimension;\n    points = mesh2.points;\n    segments = mesh2.segments;\n    surfelements = mesh2.surfelements;\n    volelements = mesh2.volelements;\n    lockedpoints = mesh2.lockedpoints;\n    facedecoding = mesh2.facedecoding;\n    dimension = mesh2.dimension;\n    hglob = mesh2.hglob;\n    hmin = mesh2.hmin;\n    maxhdomain = mesh2.maxhdomain;\n    pointelements = mesh2.pointelements;\n\n    // Remap string* values to new mesh\n    std::map<const string*, string*> names_map;\n    for (auto fi : Range(facedecoding))\n      names_map[&mesh2.facedecoding[fi].bcname] = &facedecoding[fi].bcname;\n\n    auto get_name = [&](const string *old_name) -> string* {\n      if (!old_name) return nullptr;\n      if (names_map.count(old_name)) return names_map[old_name];\n      return new string(*old_name);\n    };\n\n    materials.SetSize( mesh2.materials.Size() );\n    for ( int i = 0; i < mesh2.materials.Size(); i++ )\n    {\n      const string * old_name = mesh2.materials[i];\n      if ( old_name ) materials[i] = dimension == 2 ? get_name(old_name) : new string ( *old_name );\n      else materials[i] = 0;\n    }\n\n    bcnames.SetSize( mesh2.bcnames.Size() );\n    for ( int i = 0; i < mesh2.bcnames.Size(); i++ )\n    {\n      const string * old_name = mesh2.bcnames[i];\n      if ( old_name ) bcnames[i] = dimension == 3 ? get_name(old_name) : new string ( *old_name );\n      else bcnames[i] = 0;\n    }\n\n    cd2names.SetSize(mesh2.cd2names.Size());\n    for (int i=0; i < mesh2.cd2names.Size(); i++)\n      if (mesh2.cd2names[i]) cd2names[i] = new string(*mesh2.cd2names[i]);\n      else cd2names[i] = 0;\n\n    cd3names.SetSize(mesh2.cd3names.Size());\n    for (int i=0; i < mesh2.cd3names.Size(); i++)\n      if (mesh2.cd3names[i]) cd3names[i] = new string(*mesh2.cd3names[i]);\n      else cd3names[i] = 0;\n\n    numvertices = mesh2.numvertices;\n\n    return *this;\n  }\n\n\n  void Mesh :: DeleteMesh()\n  {\n    NgLock lock(mutex);\n    lock.Lock();\n    points.SetSize(0);\n    segments.SetSize(0);\n    surfelements.SetSize(0);\n    volelements.SetSize(0);\n    lockedpoints.SetSize(0);\n    // surfacesonnode.SetSize(0);\n\n    // delete boundaryedges;\n    boundaryedges = nullptr;\n    segmentht = nullptr;\n    surfelementht = nullptr;\n\n    openelements.SetSize(0);\n    facedecoding.SetSize(0);\n\n    ident = make_unique<Identifications> (*this);\n    topology = MeshTopology (*this);\n    curvedelems = make_unique<CurvedElements> (*this);\n    clusters = make_unique<AnisotropicClusters> (*this);\n\n    for ( int i = 0; i < bcnames.Size(); i++ )\n      if ( bcnames[i] ) delete bcnames[i];\n    for (int i= 0; i< cd2names.Size(); i++)\n      if (cd2names[i]) delete cd2names[i];\n\n#ifdef PARALLEL\n    paralleltop = make_unique<ParallelMeshTopology> (*this);\n#endif\n\n    lock.UnLock();\n\n    timestamp = NextTimeStamp();\n  }\n\n\n  void Mesh :: ClearSurfaceElements()\n  { \n    surfelements.SetSize(0);\n    /*\n    for (int i = 0; i < facedecoding.Size(); i++)\n      facedecoding[i].firstelement = -1;\n    */\n    for (auto & fd : facedecoding)\n      fd.firstelement = -1;\n    \n    timestamp = NextTimeStamp();\n  }\n\n\n\n  PointIndex Mesh :: AddPoint (const Point3d & p, int layer)\n  { \n    return AddPoint (p, layer, INNERPOINT);\n  }\n\n  PointIndex Mesh :: AddPoint (const Point3d & p, int layer, POINTTYPE type)\n  { \n\n    // PointIndex pi = points.End();\n    PointIndex pi = *points.Range().end();\n    if (points.Size() == points.AllocSize())\n      {\n        NgLock lock(mutex);\n        lock.Lock();\n        points.Append ( MeshPoint (p, layer, type) ); \n        lock.UnLock();\n      }\n    else\n      {\n        points.Append ( MeshPoint (p, layer, type) ); \n      }\n\n    timestamp = NextTimeStamp();\n\n    return pi;\n  }\n\n\n  SegmentIndex Mesh :: AddSegment (const Segment & s)\n  { \n    NgLock lock(mutex);\t\n    lock.Lock();\n    timestamp = NextTimeStamp();\n\n    // int maxn = max2 (s[0], s[1]);\n    // maxn += 1-PointIndex::BASE;\n    int maxn = max2 (s[0]-IndexBASE<PointIndex>()+1,\n                     s[1]-IndexBASE<PointIndex>()+1);\n\n    /*\n      if (maxn > ptyps.Size())\n      {\n      int maxo = ptyps.Size();\n      ptyps.SetSize (maxn);\n      for (int i = maxo; i < maxn; i++)\n      ptyps[i] = INNERPOINT;\n      }\n\n      if (ptyps[s[0]] > EDGEPOINT) ptyps[s[0]] = EDGEPOINT;\n      if (ptyps[s[1]] > EDGEPOINT) ptyps[s[1]] = EDGEPOINT;\n    */\n\n    if (maxn <= points.Size())\n      {\n        if (points[s[0]].Type() > EDGEPOINT)\n          points[s[0]].SetType (EDGEPOINT);\n        if (points[s[1]].Type() > EDGEPOINT)\n          points[s[1]].SetType (EDGEPOINT);\n      }\n    /*\n      else\n      {\n      cerr << \"edge points nrs > points.Size\" << endl;\n      }\n    */\n\n    SegmentIndex si = segments.Size();\n    segments.Append (s); \n\n    lock.UnLock();\n    return si;\n  }\n\n  SurfaceElementIndex Mesh :: AddSurfaceElement (const Element2d & el)\n  {     \n    timestamp = NextTimeStamp();\n\n    PointIndex maxn = el[0];\n    for (int i = 1; i < el.GetNP(); i++)\n      if (el[i] > maxn) maxn = el[i];\n\n    /*\n    maxn += 1-PointIndex::BASE;\n    if (maxn <= points.Size())\n      {\n        for (int i = 0; i < el.GetNP(); i++)\n          if (points[el[i]].Type() > SURFACEPOINT)\n            points[el[i]].SetType(SURFACEPOINT);\n      }\n    */\n    // if (maxn < points.End())\n    if (maxn < *points.Range().end())\n      for (PointIndex pi : el.PNums())\n        if (points[pi].Type() > SURFACEPOINT)\n          points[pi].SetType(SURFACEPOINT);\n\n    \n    SurfaceElementIndex si = surfelements.Size();\n    if (surfelements.AllocSize() == surfelements.Size())\n      {\n        NgLock lock(mutex);\n        lock.Lock();\n        surfelements.Append (el);\n        lock.UnLock();\n      }\n    else\n      {\n        surfelements.Append (el);        \n      }\n\n    if (el.index<=0 || el.index > facedecoding.Size())\n      cerr << \"has no facedecoding: fd.size = \" << facedecoding.Size() << \", ind = \" << el.index << endl;\n\n    surfelements.Last().next = facedecoding[el.index-1].firstelement;\n    facedecoding[el.index-1].firstelement = si;\n\n    if (SurfaceArea().Valid())\n      SurfaceArea().Add (el);\n\n    return si;\n  }\n\n  void Mesh :: SetSurfaceElement (SurfaceElementIndex sei, const Element2d & el)\n  {\n    /*\n    int maxn = el[0];\n    for (int i = 1; i < el.GetNP(); i++)\n      if (el[i] > maxn) maxn = el[i];\n\n    maxn += 1-PointIndex::BASE;\n    */\n    PointIndex maxpi = el[0];\n    for (int i = 1; i < el.GetNP(); i++)\n      if (el[i] > maxpi) maxpi = el[i];\n    int maxn = maxpi-IndexBASE<PointIndex>()+1;\n\n    \n    if (maxn <= points.Size())\n      {\n        for (int i = 0; i < el.GetNP(); i++)\n          if (points[el[i]].Type() > SURFACEPOINT)\n            points[el[i]].SetType(SURFACEPOINT);\n      }\n\n    surfelements[sei] = el;\n    if (el.index > facedecoding.Size())\n      cerr << \"has no facedecoding: fd.size = \" << facedecoding.Size() << \", ind = \" << el.index << endl;\n\n    // add lock-free to list ... slow, call RebuildSurfaceElementLists later\n    /*\n    surfelements[sei].next = facedecoding[el.index-1].firstelement;\n    auto & head = reinterpret_cast<atomic<SurfaceElementIndex>&> (facedecoding[el.index-1].firstelement);\n    while (!head.compare_exchange_weak (surfelements[sei].next, sei))\n      ;\n    */\n\n    /*\n    if (SurfaceArea().Valid())\n      SurfaceArea().Add (el);\n    */\n  }\n\n\n  ElementIndex Mesh :: AddVolumeElement (const Element & el)\n  { \n    /*\n    int maxn = el[0];\n    for (int i = 1; i < el.GetNP(); i++)\n      if (el[i] > maxn) maxn = el[i];\n\n    maxn += 1-PointIndex::BASE;\n    */\n    \n    /*\n      if (maxn > ptyps.Size())\n      {\n      int maxo = ptyps.Size();\n      ptyps.SetSize (maxn);\n      for (i = maxo+PointIndex::BASE; \n      i < maxn+PointIndex::BASE; i++)\n      ptyps[i] = INNERPOINT;\n      }\n    */\n    /*\n      if (maxn > points.Size())\n      {\n      cerr << \"add vol element before point\" << endl;\n      }\n    */\n\n    int ve = volelements.Size();\n\n    if (volelements.Size() == volelements.AllocSize())\n      {\n        NgLock lock(mutex);\n        lock.Lock();\n        volelements.Append (el);\n        lock.UnLock();\n      }\n    else\n      {\n        volelements.Append (el);\n      }\n    volelements.Last().Touch();\n    volelements.Last().Flags().fixed = 0;\n    volelements.Last().Flags().deleted = 0;\n\n    // while (volelements.Size() > eltyps.Size())\n    // eltyps.Append (FREEELEMENT);\n\n    timestamp = NextTimeStamp();\n\n    return ve;\n  }\n\n  void Mesh :: SetVolumeElement (ElementIndex ei, const Element & el)\n  {\n    /*\n    int maxn = el[0];\n    for (int i = 1; i < el.GetNP(); i++)\n      if (el[i] > maxn) maxn = el[i];\n\n    maxn += 1-PointIndex::BASE;\n    */\n\n    volelements[ei]  = el;\n    volelements[ei].Touch();\n    volelements[ei].Flags().fixed = 0;\n    volelements[ei].Flags().deleted = 0;\n  }\n\n\n\n\n\n  void Mesh :: Save (const filesystem::path & filename) const\n  {\n    string ext0 = filename.stem().extension().string();\n    string ext = filename.extension().string();\n\n    if (ext0 == \".vol\" && ext == \".bin\")\n    {\n        BinaryOutArchive in(filename);\n        in & const_cast<Mesh&>(*this);\n        return;\n    }\n\n    ostream * outfile;\n    if (ext0 == \".vol\" && ext == \".gz\")\n      outfile = new ogzstream(filename);\n    else if (ext == \".vol\")\n      outfile = new ofstream(filename);\n    else\n      outfile = new ogzstream(filesystem::path(filename).concat(\".vol.gz\"));\n\n    Save(*outfile);\n    delete outfile;\n  }\n\n\n\n  void Mesh :: Save (ostream & outfile) const\n  {\n    static Timer timer(\"Mesh::Save\"); RegionTimer rt(timer);\n    int i, j;\n\n    double scale = 1;  // globflags.GetNumFlag (\"scale\", 1);\n    int inverttets = 0;  // globflags.GetDefineFlag (\"inverttets\");\n    int invertsurf = 0;  // globflags.GetDefineFlag (\"invertsurfacemesh\");\n\n    outfile << \"# Generated by NETGEN \" << GetLibraryVersion(\"netgen\") << endl << endl;\n\n\n    outfile << \"mesh3d\" << \"\\n\";\n\n    outfile << \"dimension\\n\" << GetDimension() << \"\\n\";\n\n    outfile << \"geomtype\\n\" << int(geomtype) << \"\\n\";\n\n    outfile << \"\\n\";\n    outfile << \"# surfnr\\tdomin\\tdomout\\ttlosurf\\tbcprop\\n\";\n    outfile << \"facedescriptors\\n\";\n    outfile << GetNFD() << \"\\n\";\n    for(auto & fd : FaceDescriptors())\n        outfile << fd.SurfNr() << ' ' << fd.DomainIn() << ' ' << fd.DomainOut() << ' ' << fd.TLOSurface() << ' ' << fd.BCProperty() << '\\n';\n\n\n    outfile << \"\\n\";\n    outfile << \"# surfnr    bcnr   domin  domout      np      p1      p2      p3\"\n            << \"\\n\";\n\n\n    switch (geomtype)\n      {\n      case GEOM_STL:\n        outfile << \"surfaceelementsgi\" << \"\\n\";\n        break;\n      case GEOM_OCC: case GEOM_ACIS:\n        outfile << \"surfaceelementsuv\" << \"\\n\";\n        break;\n      default:\n        outfile << \"surfaceelements\" << \"\\n\";\n      }\n\n    outfile << GetNSE() << \"\\n\";\n\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        if ((*this)[sei].GetIndex())\n          {\n            outfile << \" \" << GetFaceDescriptor((*this)[sei].GetIndex ()).SurfNr()+1;\n            outfile << \" \" << GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();\n            outfile << \" \" << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainIn();\n            outfile << \" \" << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainOut();\n          }\n        else\n          outfile << \" 0 0 0\";\n\n        Element2d sel = (*this)[sei];\n        if (invertsurf)\n          sel.Invert();\n\n        outfile << \" \" << sel.GetNP();\n        for (j = 0; j < sel.GetNP(); j++)\n          outfile << \" \" << sel[j];\n\n        switch (geomtype)\n          {\n          case GEOM_STL:\n            for (j = 1; j <= sel.GetNP(); j++)\n              outfile << \" \" << sel.GeomInfoPi(j).trignum;\n            break;\n          case GEOM_OCC: case GEOM_ACIS:\n            for (j = 1; j <= sel.GetNP(); j++)\n              {\n                outfile << \" \" << sel.GeomInfoPi(j).u;\n                outfile << \" \" << sel.GeomInfoPi(j).v;\n              }\n            break;\n          default:\n            ; \n          }\n        outfile << \"\\n\";\n      }\n\n    outfile << \"\\n\" << \"\\n\";\n    outfile << \"#  matnr      np      p1      p2      p3      p4\" << \"\\n\";\n    outfile << \"volumeelements\" << \"\\n\";\n    outfile << GetNE() << \"\\n\";\n\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      {\n        outfile << (*this)[ei].GetIndex();\n        outfile << \" \" << (*this)[ei].GetNP();\n\n        Element el = (*this)[ei];\n        if (inverttets) el.Invert();\n\n        for (j = 0; j < el.GetNP(); j++)\n\t  outfile << \" \" << el[j];\n        outfile << \"\\n\";\n      }\n\n\n    outfile << \"\\n\" << \"\\n\";\n    //     outfile << \"   surf1   surf2      p1      p2\" << \"\\n\";\n    outfile << \"# surfid  0   p1   p2   trignum1    trignum2   domin/surfnr1    domout/surfnr2   ednr1   dist1   ednr2   dist2 \\n\";\n    outfile << \"edgesegmentsgi2\" << \"\\n\";\n    outfile << GetNSeg() << \"\\n\";\n\n    for (i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment (i);\n        outfile.width(8);\n        outfile << seg.si; // 2D: bc number, 3D: wievielte Kante\n        outfile.width(8);\n        outfile << 0;\n        outfile.width(8);\n        outfile << seg[0];\n        outfile.width(8);\n        outfile << seg[1];\n        outfile << \" \";\n        outfile.width(8);\n        outfile << seg.geominfo[0].trignum;  // stl dreiecke\n        outfile << \" \";\n        outfile.width(8);\n        outfile << seg.geominfo[1].trignum; // << endl;  // stl dreieck\n\n        if (dimension == 3)\n          {\n            outfile << \" \";\n            outfile.width(8);\n            outfile << seg.surfnr1+1;\n            outfile << \" \";\n            outfile.width(8);\n            outfile << seg.surfnr2+1;\n          }\n        else\n          {\n            outfile << \" \";\n            outfile.width(8);\n            outfile << seg.domin;\n            outfile << \" \";\n            outfile.width(8);\n            outfile << seg.domout;\n          }\n\n        outfile << \" \";\n        outfile.width(8);\n        outfile << seg.edgenr;\n        outfile << \" \";\n        outfile.width(12);\n        outfile.precision(16);\n        outfile << seg.epgeominfo[0].dist;  // splineparameter (2D)\n        outfile << \" \";\n        outfile.width(8);\n        outfile.precision(16);\n        outfile << seg.epgeominfo[1].edgenr;  // geometry dependent\n        outfile << \" \";\n        outfile.width(12);\n        outfile << seg.epgeominfo[1].dist;\n\n        outfile << \"\\n\";\n      }\n\n\n    outfile << \"\\n\" << \"\\n\";\n    outfile << \"#          X             Y             Z\" << \"\\n\";\n    outfile << \"points\" << \"\\n\";\n    outfile << GetNP() << \"\\n\";\n    outfile.precision(16);\n    outfile.setf (ios::fixed, ios::floatfield);\n    outfile.setf (ios::showpoint);\n\n    /*\n    PointIndex pi;\n    for (pi = PointIndex::BASE; \n         pi < GetNP()+PointIndex::BASE; pi++)\n    */\n    for (PointIndex pi : (*this).Points().Range())\n      {\n        outfile.width(22);\n        outfile << (*this)[pi](0)/scale << \"  \";\n        outfile.width(22);\n        outfile << (*this)[pi](1)/scale << \"  \";\n        outfile.width(22);\n        outfile << (*this)[pi](2)/scale << \"\\n\";\n      }\n\n    outfile << \"\\n\" << \"\\n\";\n    outfile << \"#          pnum             index\" << \"\\n\";\n    outfile << \"pointelements\" << \"\\n\";\n    outfile << pointelements.Size() << \"\\n\";\n\n    for (i = 0; i < pointelements.Size(); i++)\n      {\n        outfile.width(8);\n        outfile << pointelements[i].pnum << \"  \";\n        outfile.width(8);\n        outfile << pointelements[i].index << \"\\n\";\n      }\n\n    if (ident -> GetMaxNr() > 0)\n      {\n        outfile << \"identifications\\n\";\n        NgArray<INDEX_2> identpairs;\n        int cnt = 0;\n        for (i = 1; i <= ident -> GetMaxNr(); i++)\n          {\n            ident -> GetPairs (i, identpairs);\n            cnt += identpairs.Size();\n          }\n        outfile << cnt << \"\\n\";\n        for (i = 1; i <= ident -> GetMaxNr(); i++)\n          {\n            ident -> GetPairs (i, identpairs);\n            for (j = 1; j <= identpairs.Size(); j++)\n              {\n                outfile.width (8);\n                outfile << identpairs.Get(j).I1();\n                outfile.width (8);\n                outfile << identpairs.Get(j).I2();\n                outfile.width (8);\n                outfile << i << \"\\n\";\n              }\n          }\n\n        outfile << \"identificationtypes\\n\";\n        outfile << ident -> GetMaxNr() << \"\\n\";\n        for (i = 1; i <= ident -> GetMaxNr(); i++)\n          {\n            int type = ident -> GetType(i);\n            outfile << \" \" << type;\n          }\n        outfile << \"\\n\";\n        outfile << \"identificationnames\\n\";\n        outfile << ident -> GetMaxNr() << \"\\n\";\n        for (i = 1; i <= ident -> GetMaxNr(); i++)\n          {\n            string name = ident -> GetName(i);\n            if(name == \"\")\n              name = \"default\";\n            outfile << name << \"\\n\";\n          }\n      }\n\n    int cntmat = 0;\n    for (int i = 0; i < materials.Size(); i++)\n      if (materials[i] && materials[i]->length())\n        cntmat++;\n\n    if (cntmat)\n      {\n        outfile << \"materials\" << endl;\n        outfile << cntmat << endl;\n        for (int i = 0; i < materials.Size(); i++)\n          if (materials[i] && materials[i]->length())\n            outfile << i+1 << \" \" << *materials[i] << endl;\n      }\n\n\n    int cntbcnames = 0;\n    for ( int ii = 0; ii < bcnames.Size(); ii++ )\n      if ( bcnames[ii] ) cntbcnames++;\n\n    if ( cntbcnames )\n      {\n        outfile << \"\\n\\nbcnames\" << endl << bcnames.Size() << endl;\n        for ( i = 0; i < bcnames.Size(); i++ )\n          outfile << i+1 << \"\\t\" << GetBCName(i) << endl;\n        outfile << endl << endl;\n      }\n    int cntcd2names = 0;\n    for (int ii = 0; ii<cd2names.Size(); ii++)\n      if(cd2names[ii]) cntcd2names++;\n\n    if(cntcd2names)\n      {\n\toutfile << \"\\n\\ncd2names\" << endl << cd2names.Size() << endl;\n\tfor (i=0; i<cd2names.Size(); i++)\n\t  outfile << i+1 << \"\\t\" << GetCD2Name(i) << endl;\n\toutfile << endl << endl;\n      }\n\n    int cntcd3names = 0;\n    for (int ii = 0; ii<cd3names.Size(); ii++)\n      if(cd3names[ii]) cntcd3names++;\n\n    if(cntcd3names)\n      {\n\toutfile << \"\\n\\ncd3names\" << endl << cd3names.Size() << endl;\n\tfor (i=0; i<cd3names.Size(); i++)\n\t  outfile << i+1 << \"\\t\" << GetCD3Name(i) << endl;\n\toutfile << endl << endl;\n      }\n\n    /*\n      if ( GetDimension() == 2 )\n      {\n      for (i = 1; i <= GetNSeg(); i++)\n      {\n      const Segment & seg = LineSegment (i);\n      if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != \"\" )\n      {\n      bcprops.Append(seg.si);\n      cntbcnames++;\n      }\n      }\n      }\n      else\n      {\n      for (sei = 0; sei < GetNSE(); sei++)\n      {\n      if ((*this)[sei].GetIndex())\n      {\n      int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();\n      string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName();\n      if ( !bcprops.Contains(bcp) &&\n      name != \"\" )\n      {\n      bcprops.Append(bcp);\n      cntbcnames++;\n      }\n      }\n      }\n      }\n\n      bcprops.SetSize(0);\n      if ( cntbcnames )\n      {\n      outfile << \"\\nbcnames\" << endl << cntbcnames << endl;\n      if ( GetDimension() == 2 )\n      {\n      for (i = 1; i <= GetNSeg(); i++)\n      {\n      const Segment & seg = LineSegment (i);\n      if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != \"\" )\n      {\n      bcprops.Append(seg.si);\n      outfile << seg.si << \"\\t\" << seg.GetBCName() << endl;\n      }\n      }\n      }\n      else\n      {\n      for (sei = 0; sei < GetNSE(); sei++)\n      {\n      if ((*this)[sei].GetIndex())\n      {\n      int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();\n      string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName();\n      if ( !bcprops.Contains(bcp) &&\n      name != \"\" )\n      {\n      bcprops.Append(bcp);\n      outfile << bcp << \"\\t\" << name << endl;\n      }\n      }\n      }\n      }\n      outfile << endl << endl;\n      }\n    */\n\n    int cnt_sing = 0;\n    // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n    // if ((*this)[pi].Singularity()>=1.) cnt_sing++;\n    for (auto & p : points)\n      if (p.Singularity() >= 1.) cnt_sing++;\n      \n    if (cnt_sing)\n      {\n        outfile << \"singular_points\" << endl << cnt_sing << endl;\n        // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n        for (PointIndex pi : points.Range())\n          if ((*this)[pi].Singularity()>=1.) \n            outfile << pi << \"\\t\" << (*this)[pi].Singularity() << endl;\n      }\n\n    cnt_sing = 0;\n    for (SegmentIndex si = 0; si < GetNSeg(); si++)\n      if ( segments[si].singedge_left ) cnt_sing++;\n    if (cnt_sing)\n      {\n        outfile << \"singular_edge_left\" << endl << cnt_sing << endl;\n        for (SegmentIndex si = 0; si < GetNSeg(); si++)\n          if ( segments[si].singedge_left )\n            outfile << int(si) << \"\\t\" << segments[si].singedge_left << endl;\n      }\n\n    cnt_sing = 0;\n    for (SegmentIndex si = 0; si < GetNSeg(); si++)\n      if ( segments[si].singedge_right ) cnt_sing++;\n    if (cnt_sing)\n      {\n        outfile << \"singular_edge_right\" << endl << cnt_sing << endl;\n        for (SegmentIndex si = 0; si < GetNSeg(); si++)\n          if ( segments[si].singedge_right  )\n            outfile << int(si) << \"\\t\" << segments[si].singedge_right << endl;\n      }\n\n\n    cnt_sing = 0;\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) \n        cnt_sing++;\n\n    if (cnt_sing)\n      {\n        outfile << \"singular_face_inside\" << endl << cnt_sing << endl;\n        for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n          if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) \n            outfile << int(sei)  << \"\\t\" << \n              GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular  << endl;\n      }\n\n    cnt_sing = 0;\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) cnt_sing++;\n    if (cnt_sing)\n      {\n        outfile << \"singular_face_outside\" << endl << cnt_sing << endl;\n        for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n          if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) \n            outfile << int(sei) << \"\\t\" \n                    << GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular << endl;\n      }\n\n\n    // Philippose - 09/07/2009\n    // Add mesh face colours to Netgen Vol file format\n    // The colours are saved in RGB triplets\n    int cnt_facedesc = GetNFD();\n    if (cnt_facedesc)\n    {\n       outfile << endl << endl << \"#   Surfnr     Red     Green     Blue\" << endl;\n       outfile << \"face_colours\" << endl << cnt_facedesc << endl;\n\n       outfile.precision(8);\n       outfile.setf(ios::fixed, ios::floatfield);\n       outfile.setf(ios::showpoint);\n\n       for(i = 1; i <= cnt_facedesc; i++)\n       {\n          outfile.width(8);\n          outfile << GetFaceDescriptor(i).SurfNr()+1 << \" \";\n          outfile.width(12);\n          outfile << GetFaceDescriptor(i).SurfColour()[0] << \" \";\n          outfile.width(12);\n          outfile << GetFaceDescriptor(i).SurfColour()[1] << \" \";\n          outfile.width(12);\n          outfile << GetFaceDescriptor(i).SurfColour()[2];\n          outfile << endl;\n       }\n\n       outfile << \"face_transparencies\" << endl << cnt_facedesc << endl;\n       for(i = 1; i <= cnt_facedesc; i++)\n         {\n           outfile.width(8);\n           outfile << GetFaceDescriptor(i).SurfNr()+1 << \" \";\n           outfile.width(12);\n           outfile << GetFaceDescriptor(i).SurfColour()[3] << endl;\n         }\n    }\n\n\n    if (curvedelems && curvedelems->IsHighOrder())\n      {\n        if (level_nv.Size() > 1 && (MeshTopology().HasParentEdges() || MeshTopology().HasParentFaces()))\n          cerr << \"Waring: cannot store curvedelements on refined meshes with full hierarchy\" << endl;\n        else\n          {\n            outfile << \"curvedelements\" << endl;\n            shared_ptr<std::ostream> spoutfile(&outfile,  [](void*) noexcept {});\n            TextOutArchive out(std::move(spoutfile));\n            out & (*curvedelems);\n          }\n      }\n\n    \n    outfile << endl << endl << \"endmesh\" << endl << endl;\n    if (geometry)\n      geometry -> SaveToMeshFile (outfile);\n  }\n\n\n\n  void Mesh :: Load (const filesystem::path & filename)\n  {\n    PrintMessage (1, \"filename = \", filename);\n\n    string ext0 = filename.stem().extension().string();\n    string ext = filename.extension().string();\n\n    if (ext0 == \".vol\" && ext == \".bin\")\n    {\n        BinaryInArchive in(filename);\n        in & (*this);\n        return;\n    }\n\n    istream * infile = NULL;\n\n    if (ext0 == \".vol\" && ext == \".gz\")\n      infile = new igzstream (filename);\n    else\n      infile = new ifstream (filename);\n\n    if (! (infile -> good()) )\n      throw NgException (\"mesh file not found\");\n\n    Load(*infile);\n    delete infile;\n  }\n\n\n\n  // Reads mandatory integer and optional string token from input stream\n  // used for parsing bcnames, cd2names etc.\n  void ReadNumberAndName( istream & infile, int & i, string & s )\n  {\n    string line;\n    std::istringstream iline;\n\n    bool empty_line = true;\n\n    while(empty_line && infile)\n      {\n        std::getline(infile, line);\n        iline = std::istringstream{line};\n        iline >> i;\n\n        if(iline)\n            empty_line = false;\n\n        iline >> s;\n      }\n\n    if(!infile)\n        throw Exception(\"Reached end of file while parsing\");\n  }\n\n  void Mesh :: Load (istream & infile)\n  {\n    static Timer timer(\"Mesh::Load\"); RegionTimer rt(timer);\n    if (! (infile.good()) )\n      {\n        cout << \"cannot load mesh\" << endl;\n        throw NgException (\"mesh file not found\");\n      }\n\n    // int rank = GetCommunicator().Rank();\n    int ntasks = GetCommunicator().Size();\n    \n    char str[100];\n    int i, n;\n\n    double scale = 1;  // globflags.GetNumFlag (\"scale\", 1);\n    int inverttets = 0;  // globflags.GetDefineFlag (\"inverttets\");\n    int invertsurf = 0;  // globflags.GetDefineFlag (\"invertsurfacemesh\");\n\n\n    facedecoding.SetSize(0);\n\n    bool endmesh = false;\n\n    bool has_facedescriptors = false;\n    \n\n    while (infile.good() && !endmesh)\n      {\n        infile >> str;\n\n        if (strcmp (str, \"dimension\") == 0)\n          {\n            infile >> dimension;\n          }\n\n        if (strcmp (str, \"geomtype\") == 0)\n          {\n            int hi;\n            infile >> hi;\n            geomtype = GEOM_TYPE(hi);\n          }\n\n        if (strcmp (str, \"facedescriptors\") == 0)\n          {\n            has_facedescriptors = true;\n            int nfd;\n            infile >> nfd;\n            for([[maybe_unused]] auto i : Range(nfd))\n            {\n                int surfnr, domin, domout, tlosurf, bcprop;\n                infile >> surfnr >> domin >> domout >> tlosurf >> bcprop;\n                auto faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, tlosurf));\n                GetFaceDescriptor(faceind).SetBCProperty(bcprop);\n            }\n          }\n\n\n        if (strcmp (str, \"surfaceelements\") == 0 || strcmp (str, \"surfaceelementsgi\")==0 || strcmp (str, \"surfaceelementsuv\") == 0)\n          {\n            static Timer t1(\"read surface elements\"); RegionTimer rt1(t1);\n            infile >> n;\n            PrintMessage (3, n, \" surface elements\");\n\n\t    bool geominfo = strcmp (str, \"surfaceelementsgi\") == 0;\n\t    bool uv = strcmp (str, \"surfaceelementsuv\") == 0;\n\n\n            for (i = 1; i <= n; i++)\n              {\n                int surfnr, bcp, domin, domout, nep, faceind = 0;\n\n                infile >> surfnr >> bcp >> domin >> domout;\n                surfnr--;\n\n\t\tbool invert_el = false;\n\t\t/*\n\t\tif (domin == 0) \n\t\t  {\n\t\t    invert_el = true;\n\t\t    Swap (domin, domout);\n\t\t  }\n\t\t*/\n\t\t\n                for (int j = 1; j <= facedecoding.Size(); j++)\n                  if (GetFaceDescriptor(j).SurfNr() == surfnr &&\n                      GetFaceDescriptor(j).BCProperty() == bcp &&\n                      GetFaceDescriptor(j).DomainIn() == domin &&\n                      GetFaceDescriptor(j).DomainOut() == domout)\n                    faceind = j;\n\n\t\t// if (facedecoding.Size()) faceind = 1;   // for timing \n\n                if (!faceind)\n                  {\n                    faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0));\n                    GetFaceDescriptor(faceind).SetBCProperty (bcp);\n                  }\n\n                infile >> nep;\n                if (!nep) nep = 3;\n\n                Element2d tri(nep);\n                tri.SetIndex(faceind);\n\n                for (int j = 1; j <= nep; j++)\n                  infile >> tri.PNum(j);\n\n                if (geominfo)\n                  for (int j = 1; j <= nep; j++)\n                    infile >> tri.GeomInfoPi(j).trignum;\n\n                if (uv)\n                  for (int j = 1; j <= nep; j++)\n                    infile >> tri.GeomInfoPi(j).u >> tri.GeomInfoPi(j).v;\n\t\t\n                if (invertsurf) tri.Invert();\n\t\tif (invert_el) tri.Invert();\n\n\t\tAddSurfaceElement (tri);\n              }\n          }\n\n        if (strcmp (str, \"volumeelements\") == 0)\n          {\n            static Timer t1(\"read volume elements\"); RegionTimer rt1(t1);\n            infile >> n;\n            PrintMessage (3, n, \" volume elements\");\n            for (i = 1; i <= n; i++)\n              {\n                Element el(TET);\n                int hi, nep;\n                infile >> hi;\n                if (hi == 0) hi = 1;\n                el.SetIndex(hi);\n                infile >> nep;\n                el.SetNP(nep);\n                el.SetCurved (nep != 4);\n                for (int j = 0; j < nep; j++)\n                  infile >> el[j];\n\n                if (inverttets)\n                  el.Invert();\n\n\t\tAddVolumeElement (el);\n              }\n          }\n\n\n        if (strcmp (str, \"edgesegments\") == 0)\n          {\n            static Timer t1(\"read edge segments\"); RegionTimer rt1(t1);\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1];\n                AddSegment (seg);\n              }\n          }\n\n\n\n        if (strcmp (str, \"edgesegmentsgi\") == 0)\n          {\n            static Timer t1(\"read edge segmentsgi\"); RegionTimer rt1(t1);\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1]\n                       >> seg.geominfo[0].trignum\n                       >> seg.geominfo[1].trignum;\n                AddSegment (seg);\n              }\n          }\n\n        if (strcmp (str, \"edgesegmentsgi2\") == 0)\n          {\n            static Timer t1(\"read edge segmentsgi2\"); RegionTimer rt1(t1);\n            int a; \n            infile >> a;\n            n=a; \n\n            PrintMessage (3, n, \" curve elements\");\n\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1]\n                       >> seg.geominfo[0].trignum\n                       >> seg.geominfo[1].trignum\n                       >> seg.surfnr1 >> seg.surfnr2\n                       >> seg.edgenr\n                       >> seg.epgeominfo[0].dist\n                       >> seg.epgeominfo[1].edgenr\n                       >> seg.epgeominfo[1].dist;\n\n                seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr;\n                if (geomtype == GEOM_OCC)\n                  seg.index = seg.epgeominfo[0].edgenr+1;\n                else if (geomtype == GEOM_CSG)\n                  seg.index = seg.edgenr;\n                else\n                  seg.index = seg.si;\n                \n                    \n                seg.domin = seg.surfnr1;\n                seg.domout = seg.surfnr2;\n\n                seg.surfnr1--;\n                seg.surfnr2--;\n\n                AddSegment (seg);\n              }\n          }\n\n        if (strcmp (str, \"points\") == 0)\n          {\n            static Timer t1(\"read points\"); RegionTimer rt1(t1);\n            infile >> n;\n            PrintMessage (3, n, \" points\");\n            for (i = 1; i <= n; i++)\n              {\n                Point3d p;\n                infile >> p.X() >> p.Y() >> p.Z();\n                p.X() *= scale;\n                p.Y() *= scale;\n                p.Z() *= scale;\n                AddPoint (p);\n              }\n\t    PrintMessage (3, n, \" points done\");\n          }\n\n        if (strcmp (str, \"pointelements\") == 0)\n          {\n            static Timer t1(\"read point elements\"); RegionTimer rt1(t1);\n            infile >> n;\n            PrintMessage (3, n, \" pointelements\");\n            for (i = 1; i <= n; i++)\n              {\n                Element0d el;\n                infile >> el.pnum >> el.index;\n                pointelements.Append (el);\n              }\n\t    PrintMessage (3, n, \" pointelements done\");\n          }\n\n        if (strcmp (str, \"identifications\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" identifications\");\n            for (i = 1; i <= n; i++)\n              {\n                PointIndex pi1, pi2;\n                int ind;\n                infile >> pi1 >> pi2 >> ind;\n                ident -> Add (pi1, pi2, ind);\n              }\n          }\n\n        if (strcmp (str, \"identificationtypes\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" identificationtypes\");\n            for (i = 1; i <= n; i++)\n              {\n                int type;\n                infile >> type;\n                ident -> SetType(i,Identifications::ID_TYPE(type));\n              }\n          }\n        if (strcmp (str, \"identificationnames\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" identificationnames\");\n            for (i = 1; i <= n; i++)\n              {\n                string name;\n                infile >> name;\n                ident -> SetName(i,name);\n              }\n          }\n\n        if (strcmp (str, \"materials\") == 0)\n          {\n            infile >> n;\n            for ([[maybe_unused]] auto i : Range(n) )\n              {\n                int nr;\n                string mat;\n                ReadNumberAndName( infile, nr, mat );\n                SetMaterial (nr, mat.c_str());\n              }\n          }\n\n        if ( strcmp (str, \"bcnames\" ) == 0 )\n          {\n            infile >> n;\n            Array<int> bcnrs(n);\n            SetNBCNames(n);\n            for ( auto i : Range(n) )\n              {\n                string nextbcname;\n                ReadNumberAndName( infile, bcnrs[i], nextbcname );\n                bcnames[bcnrs[i]-1] = new string(nextbcname);\n              }\n\n            if ( GetDimension() == 3 )\n              {\n                for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n                  {\n                    if ((*this)[sei].GetIndex())\n                      {\n                        int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();\n                        if ( bcp <= n )\n                          GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(bcnames[bcp-1]);\n                        else\n                          GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(0);\n\n                      }\n                  }\n\n              }\n          }\n\n\tif ( strcmp (str, \"cd2names\" ) == 0)\n\t  {\n\t    infile >> n;\n\t    Array<int> cd2nrs(n);\n\t    SetNCD2Names(n);\n            for ( auto i : Range(n) )\n              {\n                string nextcd2name;\n                ReadNumberAndName( infile, cd2nrs[i], nextcd2name );\n                cd2names[cd2nrs[i]-1] = new string(nextcd2name);\n              }\n\t    if (GetDimension() < 2)\n\t      {\n\t\tthrow NgException(\"co dim 2 elements not implemented for dimension < 2\");\n\t      }\n\t  }\n\n        if ( strcmp (str, \"cd3names\" ) == 0)\n\t  {\n\t    infile >> n;\n\t    Array<int> cd3nrs(n);\n\t    SetNCD3Names(n);\n\t    for( auto i : Range(n) )\n\t      {\n\t\tstring nextcd3name;\n                ReadNumberAndName( infile, cd3nrs[i], nextcd3name );\n                cd3names[cd3nrs[i]-1] = new string(nextcd3name);\n\t      }\n\t    if (GetDimension() < 3)\n\t      {\n\t\tthrow NgException(\"co dim 3 elements not implemented for dimension < 3\");\n\t      }\n\t  }\n\n        if (strcmp (str, \"singular_points\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                PointIndex pi;\n                double s; \n                infile >> pi;\n                infile >> s; \n                (*this)[pi].Singularity (s);\n              }\n          }\n\n        if (strcmp (str, \"singular_edge_left\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                SegmentIndex si;\n                double s; \n                infile >> si;\n                infile >> s; \n                (*this)[si].singedge_left = s;\n              }\n          }\n        if (strcmp (str, \"singular_edge_right\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                SegmentIndex si;\n                double s; \n                infile >> si;\n                infile >> s; \n                (*this)[si].singedge_right = s;\n              }\n          }\n\n        if (strcmp (str, \"singular_face_inside\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                SurfaceElementIndex sei;\n                double s; \n                infile >> sei;\n                infile >> s; \n                GetFaceDescriptor((*this)[sei].GetIndex()).domin_singular = s;\n              }\n          }\n\n        if (strcmp (str, \"singular_face_outside\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                SurfaceElementIndex sei;\n                double s; \n                infile >> sei;\n                infile >> s; \n                GetFaceDescriptor((*this)[sei].GetIndex()).domout_singular = s;\n              }\n          }\n\n        // Philippose - 09/07/2009\n        // Add mesh face colours to Netgen Vol file format\n        // The colours are read in as RGB triplets\n        if (strcmp (str, \"face_colours\") == 0)\n        {\n           int cnt_facedesc = GetNFD();\n           infile >> n;\n           if(n == cnt_facedesc)\n           {\n              for(i = 1; i <= n; i++)\n              {\n                 int surfnr = 0;\n                 Vec<4> surfcolour(0.0,1.0,0.0,1.0);\n\n                 infile >> surfnr \n                        >> surfcolour[0]\n                        >> surfcolour[1]\n                        >> surfcolour[2];\n\n                 surfnr--;\n\n                 if(has_facedescriptors)\n                 {\n                    GetFaceDescriptor(i).SetSurfColour(surfcolour);\n                 }\n                 else if(surfnr > 0)\n                 {\n                    for(int facedesc = 1; facedesc <= cnt_facedesc; facedesc++)\n                    {\n                       if(surfnr == GetFaceDescriptor(facedesc).SurfNr())\n                       {\n                          GetFaceDescriptor(facedesc).SetSurfColour(surfcolour);\n                       }\n                    }\n                 }\n              }\n           }\n        }\n\n        if (strcmp (str, \"face_transparencies\") == 0)\n          {\n            int cnt_facedesc = GetNFD();\n            infile >> n;\n            // int index = 1;\n            if(n == cnt_facedesc)\n              {\n                for(int index = 1; index <= n; index++)\n                  {\n                    int surfnr;\n                    double transp;\n                    infile >> surfnr >> transp;\n                    surfnr--;\n                    if(has_facedescriptors)\n                    {\n                       auto& fd = GetFaceDescriptor(index);\n                       auto scol = fd.SurfColour();\n                       scol[3] = transp;\n                       fd.SetSurfColour(scol);\n                    }\n                    else if(surfnr > 0)\n                      {\n                        for(int facedesc = 1; facedesc <= cnt_facedesc; facedesc++)\n                          {\n                            if(surfnr == GetFaceDescriptor(facedesc).SurfNr())\n                              {\n                                auto& fd = GetFaceDescriptor(facedesc);\n                                auto scol = fd.SurfColour();\n                                scol[3] = transp;\n                                fd.SetSurfColour(scol);\n                              }\n                          }\n                      }\n                  }\n              }\n          }\n        \n        if (strcmp (str, \"curvedelements\") == 0)\t      \n          {\n            topology.Update();\n            shared_ptr<std::istream> spinfile(&infile,  [](void*) noexcept {});\n            TextInArchive in(std::move(spinfile));\n            in & (*curvedelems);\n\n            for (SegmentIndex seg = 0; seg < GetNSeg(); seg++)\n              (*this)[seg].SetCurved (GetCurvedElements().IsSegmentCurved (seg));\n            for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n              (*this)[sei].SetCurved (GetCurvedElements().IsSurfaceElementCurved (sei));\n            for (ElementIndex ei = 0; ei < GetNE(); ei++)\n              (*this)[ei].SetCurved (GetCurvedElements().IsElementCurved (ei));\n          }\n\n        \n        if (strcmp (str, \"endmesh\") == 0)\n          endmesh = true;\n\n\n\n        strcpy (str, \"\");\n      }\n\n\n\n\n    CalcSurfacesOfNode ();\n \n    if (ntasks == 1) // sequential run only\n      {\n\ttopology.Update();\n\tclusters -> Update();\n      }\n\n    SetNextMajorTimeStamp();\n    //  PrintMemInfo (cout);\n  }\n\n\n  void Mesh :: DoArchive (Archive & archive)\n  {\n    static Timer t(\"Mesh::Archive\"); RegionTimer r(t);\n\n#ifdef PARALLEL\n    auto comm = GetCommunicator();\n    if (archive.IsParallel() && comm.Size() > 1)\n      { // parallel pickling supported only for output archives\n        if (comm.Rank() == 0)\n          archive & dimension;\n\n        // auto rank = comm.Rank();\n        \n        auto & partop = GetParallelTopology();\n        \n        // global enumration of points:\n        // not used now, but will be needed for refined meshes\n        // GridFunciton pickling is not compatible, now\n        // should go to paralleltopology\n        \n        \n        \n        // merge points\n        Array<PointIndex, PointIndex> globnum(points.Size());\n        PointIndex maxglob = -1;\n        for (auto pi : Range(points))\n          {\n            globnum[pi] = partop.GetGlobalPNum(pi);\n            // globnum[pi] = global_pnums[pi];\n            maxglob = max(globnum[pi], maxglob);\n          }\n        \n        maxglob = comm.AllReduce (maxglob, NG_MPI_MAX);\n        int numglob = maxglob+1-IndexBASE<PointIndex>();\n        if (comm.Rank() > 0)\n          {\n            comm.Send (globnum, 0, 200);\n            comm.Send (points, 0, 200);\n          }\n        else\n          {\n            Array<PointIndex, PointIndex> globnumi;\n            Array<MeshPoint, PointIndex> pointsi;\n            Array<MeshPoint, PointIndex> globpoints(numglob);\n            for (int j = 1; j < comm.Size(); j++)\n              {\n                comm.Recv (globnumi, j, 200);\n                comm.Recv (pointsi, j, 200);\n                for (auto i : Range(globnumi))\n                  globpoints[globnumi[i]] = pointsi[i];\n              }\n            archive & globpoints;\n          }\n\n        \n        // sending surface elements\n        auto copy_el2d  (surfelements);\n        for (auto & el : copy_el2d)\n          for (auto & pi : el.PNums())\n            pi = globnum[pi];\n\n        if (comm.Rank() > 0)\n          comm.Send(copy_el2d, 0, 200);\n        else\n          {\n            Array<Element2d, SurfaceElementIndex> el2di;\n            for (int j = 1; j < comm.Size(); j++)\n              {\n                comm.Recv(el2di, j, 200);\n                for (auto & el : el2di)\n                  copy_el2d += el;\n              }\n            archive & copy_el2d;\n          }\n\n\n        // sending volume elements\n        auto copy_el3d  (volelements);\n        for (auto & el : copy_el3d)\n          for (auto & pi : el.PNums())\n            pi = globnum[pi];\n\n        if (comm.Rank() > 0)\n          comm.Send(copy_el3d, 0, 200);\n        else\n          {\n            Array<Element, ElementIndex> el3di;\n            for (int j = 1; j < comm.Size(); j++)\n              {\n                comm.Recv(el3di, j, 200);\n                for (auto & el : el3di)\n                  copy_el3d += el;\n              }\n            archive & copy_el3d;\n          }\n\n\n        // sending 1D elements\n        auto copy_el1d  (segments);\n        for (auto & el : copy_el1d)\n          for (auto & pi : el.pnums)\n            if (pi != PointIndex(PointIndex::INVALID))\n              pi = globnum[pi];\n\n        if (comm.Rank() > 0)\n          comm.Send(copy_el1d, 0, 200);\n        else\n          {\n            Array<Segment, SegmentIndex> el1di;\n            for (int j = 1; j < comm.Size(); j++)\n              {\n                comm.Recv(el1di, j, 200);\n                for (auto & el : el1di)\n                  copy_el1d += el;\n              }\n            archive & copy_el1d;\n          }\n\n\n        // sending 0D elements\n        auto copy_el0d  (pointelements);\n        for (auto & el : copy_el0d)\n          {\n            auto & pi = el.pnum;\n            if (pi != PointIndex(PointIndex::INVALID))\n              pi = globnum[pi];\n          }\n        \n        if (comm.Rank() > 0)\n          comm.Send(copy_el0d, 0, 200);\n        else\n          {\n            Array<Element0d> el0di;\n            for (int j = 1; j < comm.Size(); j++)\n              {\n                comm.Recv(el0di, j, 200);\n                for (auto & el : el0di)\n                  copy_el0d += el;\n              }\n            archive & copy_el0d;\n          }\n\n\n\n        \n        if (comm.Rank() == 0)\n          {\n            archive & facedecoding;\n            archive & materials & bcnames & cd2names & cd3names;\n            auto mynv = numglob;\n            archive & mynv;   // numvertices;\n            archive & *ident;\n\n            if(archive.GetVersion(\"netgen\") >= \"v6.2.2103-1\")\n              {\n                archive.NeedsVersion(\"netgen\", \"v6.2.2103-1\");\n                archive & vol_partition & surf_partition & seg_partition;\n              }\n            \n            archive.Shallow(geometry);\n            archive & *curvedelems;\n          }\n        \n        if (comm.Rank() == 0)\n          return;\n      }\n#endif\n    \n    \n    archive & dimension;\n    archive & points;\n    archive & surfelements;\n    archive & volelements;\n    archive & segments;\n    archive & pointelements;\n    archive & facedecoding;\n    archive & materials & bcnames & cd2names & cd3names;\n    archive & numvertices;\n\n    archive & *ident;\n\n    // cout << \"archive, ngsversion = \" << archive.GetVersion(\"netgen\") << endl;\n    if(archive.GetVersion(\"netgen\") >= \"v6.2.2103-1\")\n      {\n        // cout << \"do the partition\" << endl;\n        archive.NeedsVersion(\"netgen\", \"v6.2.2103-1\");\n        archive & vol_partition & surf_partition & seg_partition;\n      }\n    // else\n    // cout << \"no partition\" << endl;\n    \n    archive.Shallow(geometry);\n    archive & *curvedelems;\n    \n    if (archive.Input())\n      {\n\t// int rank = GetCommunicator().Rank();\n\tint ntasks = GetCommunicator().Size();\n\t\n        RebuildSurfaceElementLists();\n        \n        CalcSurfacesOfNode ();\n        if (ntasks == 1) // sequential run only\n          {\n            topology.Update();\n            clusters -> Update();\n          }\n        SetNextMajorTimeStamp();\n      }\n  }\n\n\n  void Mesh :: Merge (const filesystem::path & filename, const int surfindex_offset)\n  {\n    ifstream infile(filename);\n    if (!infile.good())\n      throw NgException (\"mesh file not found\");\n\n    Merge(infile,surfindex_offset);\n\n  }\n\n\n\n  void Mesh :: Merge (istream & infile, const int surfindex_offset)\n  {\n    char str[100];\n    int i, n;\n\n\n    int inverttets = 0;  // globflags.GetDefineFlag (\"inverttets\");\n\n    int oldnp = GetNP();\n    int oldne = GetNSeg();\n    int oldnd = GetNDomains();\n\n    for(SurfaceElementIndex si = 0; si < GetNSE(); si++)\n      for(int j=1; j<=(*this)[si].GetNP(); j++) (*this)[si].GeomInfoPi(j).trignum = -1;\n\n    int max_surfnr = 0;\n    for (i = 1; i <= GetNFD(); i++)\n      max_surfnr = max2 (max_surfnr, GetFaceDescriptor(i).SurfNr());\n    max_surfnr++;\n\n    if(max_surfnr < surfindex_offset) max_surfnr = surfindex_offset;\n\n\n    bool endmesh = false;\n\n    while (infile.good() && !endmesh)\n      {\n        infile >> str;\n\n        if (strcmp (str, \"surfaceelementsgi\") == 0 || strcmp (str, \"surfaceelements\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" surface elements\");\n            for (i = 1; i <= n; i++)\n              {\n                int j;\n                int surfnr, bcp, domin, domout, nep, faceind = 0;\n                infile >> surfnr >> bcp >> domin >> domout;\n\n                surfnr--;\n\n                if(domin > 0) domin += oldnd;\n                if(domout > 0) domout += oldnd;\n                surfnr += max_surfnr;\n\n\n                for (j = 1; j <= facedecoding.Size(); j++)\n                  if (GetFaceDescriptor(j).SurfNr() == surfnr &&\n                      GetFaceDescriptor(j).BCProperty() == bcp &&\n                      GetFaceDescriptor(j).DomainIn() == domin &&\n                      GetFaceDescriptor(j).DomainOut() == domout)\n                    faceind = j;\n\n                if (!faceind)\n                  {\n                    faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0));\n                    if(GetDimension() == 2) bcp++;\n                    GetFaceDescriptor(faceind).SetBCProperty (bcp);\n                  }\n\n                infile >> nep;\n                if (!nep) nep = 3;\n\n                Element2d tri(nep);\n                tri.SetIndex(faceind);\n\n                for (j = 1; j <= nep; j++)\n                  {\n                    infile >> tri.PNum(j);\n                    tri.PNum(j) = tri.PNum(j) + oldnp;\n                  }\n\n\n                if (strcmp (str, \"surfaceelementsgi\") == 0)\n                  for (j = 1; j <= nep; j++)\n                    {\n                      infile >> tri.GeomInfoPi(j).trignum;\n                      tri.GeomInfoPi(j).trignum = -1;\n                    }\n\n                AddSurfaceElement (tri);\n              }\n          }\n\n\n        if (strcmp (str, \"edgesegments\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1];\n                seg[0] = seg[0] + oldnp;\n                seg[1] = seg[1] + oldnp;\n                AddSegment (seg);\n              }\n          }\n\n\n\n        if (strcmp (str, \"edgesegmentsgi\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1]\n                       >> seg.geominfo[0].trignum\n                       >> seg.geominfo[1].trignum;\n                seg[0] = seg[0] + oldnp;\n                seg[1] = seg[1] + oldnp;\n                AddSegment (seg);\n              }\n          }\n        if (strcmp (str, \"edgesegmentsgi2\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" curve elements\");\n\n            for (i = 1; i <= n; i++)\n              {\n                Segment seg;\n                int hi;\n                infile >> seg.si >> hi >> seg[0] >> seg[1]\n                       >> seg.geominfo[0].trignum\n                       >> seg.geominfo[1].trignum\n                       >> seg.surfnr1 >> seg.surfnr2\n                       >> seg.edgenr\n                       >> seg.epgeominfo[0].dist\n                       >> seg.epgeominfo[1].edgenr\n                       >> seg.epgeominfo[1].dist;\n                seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr;\n\n                seg.surfnr1--;\n                seg.surfnr2--;\n\n                if(seg.surfnr1 >= 0)  seg.surfnr1 = seg.surfnr1 + max_surfnr;\n                if(seg.surfnr2 >= 0)  seg.surfnr2 = seg.surfnr2 + max_surfnr;\n                seg[0] = seg[0] +oldnp;\n                seg[1] = seg[1] +oldnp;\n\t\t*testout << \"old edgenr: \" << seg.edgenr << endl;\n                seg.edgenr = seg.edgenr + oldne;\n\t\t*testout << \"new edgenr: \" << seg.edgenr << endl;\n                seg.epgeominfo[1].edgenr = seg.epgeominfo[1].edgenr + oldne;\n\n                AddSegment (seg);\n              }\n          }\n\n        if (strcmp (str, \"volumeelements\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" volume elements\");\n            for (i = 1; i <= n; i++)\n              {\n                Element el(TET);\n                int hi, nep;\n                infile >> hi;\n                if (hi == 0) hi = 1;\n                el.SetIndex(hi+oldnd);\n                infile >> nep;\n                el.SetNP(nep);\n\n                for (int j = 0; j < nep; j++)\n                  {\n                    infile >> el[j];\n                    el[j] = el[j]+oldnp;\n                  }\n\n                if (inverttets)\n                  el.Invert();\n\n                AddVolumeElement (el);\n              }\n          }\n\n\n        if (strcmp (str, \"points\") == 0)\n          {\n            infile >> n;\n            PrintMessage (3, n, \" points\");\n            for (i = 1; i <= n; i++)\n              {\n                Point3d p;\n                infile >> p.X() >> p.Y() >> p.Z();\n                AddPoint (p);\n              }\n          }\n\n\n        if (strcmp (str, \"endmesh\") == 0)\n          {\n            endmesh = true;\n          }\n\n\n        if (strcmp (str, \"materials\") == 0)\n          {\n            infile >> n;\n            for (i = 1; i <= n; i++)\n              {\n                int nr;\n                string mat;\n                infile >> nr >> mat;\n                SetMaterial (nr+oldnd, mat.c_str());\n              }\n          }\n\n\n        strcpy (str, \"\");\n      }\n\n    CalcSurfacesOfNode ();\n\n    topology.Update();\n    clusters -> Update();\n\n    SetNextMajorTimeStamp();\n  }\n\n\n\n\n\n\n\n\n\n\n  bool Mesh :: TestOk () const\n  {\n    for (ElementIndex ei = 0; ei < volelements.Size(); ei++)\n      {\n        for (int j = 0; j < 4; j++)\n          if ( !(*this)[ei][j].IsValid())\n            {\n              (*testout) << \"El \" << ei << \" has 0 nodes: \";\n              for (int k = 0; k < 4; k++)\n                (*testout) << (*this)[ei][k];\n              break;\n            }\n      }\n    CheckMesh3D (*this);\n    return 1;\n  }\n\n  void Mesh :: SetAllocSize(int nnodes, int nsegs, int nsel, int nel)\n  {\n    points.SetAllocSize(nnodes);\n    segments.SetAllocSize(nsegs);\n    surfelements.SetAllocSize(nsel);\n    volelements.SetAllocSize(nel);\n  }\n\n  void Mesh :: BuildBoundaryEdges(bool rebuild)\n  {\n    static Timer t(\"Mesh::BuildBoundaryEdges\"); RegionTimer reg(t);\n    \n    if(!rebuild && boundaryedges)\n      return;\n\n    boundaryedges = make_unique<INDEX_2_CLOSED_HASHTABLE<int>>\n      (3 * (GetNSE() + GetNOpenElements()) + GetNSeg() + 1);\n\n\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        const Element2d & sel = surfelements[sei];\n        if (sel.IsDeleted()) continue;\n\n        // int si = sel.GetIndex();\n\n        if (sel.GetNP() <= 4)\n          for (int j = 0; j < sel.GetNP(); j++)\n            {\n              PointIndices<2> i2;\n              i2[0] = sel.PNumMod(j+1);\n              i2[1] = sel.PNumMod(j+2);\n              i2.Sort();\n              boundaryedges->Set (i2, 1);\n            }\n        else if (sel.GetType()==TRIG6)\n          {\n            for (int j = 0; j < 3; j++)\n              {\n                PointIndices<2> i2;\n                i2[0] = sel[j];\n                i2[1] = sel[(j+1)%3];\n                i2.Sort();\n                boundaryedges->Set (i2, 1);\n              }\n          }\n        else \n          cerr << \"illegal element for buildboundaryedges\" << endl;\n      }\n\n    /*\n    for (int i = 0; i < openelements.Size(); i++)\n      {\n        const Element2d & sel = openelements[i];\n        for (int j = 0; j < sel.GetNP(); j++)\n          {\n            INDEX_2 i2;\n            i2.I1() = sel.PNumMod(j+1);\n            i2.I2() = sel.PNumMod(j+2);\n            i2.Sort();\n            boundaryedges->Set (i2, 1);\n\n            points[sel[j]].SetType(FIXEDPOINT);\n          }\n      }\n    */\n    for (const Element2d & sel : openelements)\n      for (int j = 0; j < sel.GetNP(); j++)\n        {\n          PointIndices<2> i2 { sel.PNumMod(j+1), sel.PNumMod(j+2) };\n          i2.Sort();\n          boundaryedges->Set (i2, 1);\n\n          points[sel[j]].SetType(FIXEDPOINT);\n        }\n\n    /*\n    for (int i = 0; i < GetNSeg(); i++)\n      {\n        const Segment & seg = segments[i];\n        INDEX_2 i2(seg[0], seg[1]);\n        i2.Sort();\n\n        boundaryedges -> Set (i2, 2);\n        //segmentht -> Set (i2, i);\n      }\n    */\n    for (const Segment & seg : segments)\n      {\n        PointIndices<2> i2 { seg[0], seg[1] };\n        i2.Sort();\n\n        boundaryedges -> Set (i2, 2);\n        //segmentht -> Set (i2, i);\n      }\n\n  }\n\n  void Mesh :: CalcSurfacesOfNode ()\n  {\n    static Timer t(\"Mesh::CalcSurfacesOfNode\"); RegionTimer reg (t);\n    static Timer tn2se(\"Mesh::CalcSurfacesOfNode - surf on node\");     \n    static Timer tht(\"Mesh::CalcSurfacesOfNode - surfelementht\"); \n    // surfacesonnode.SetSize (GetNP());\n    DynamicTable<int,PointIndex> surfacesonnode(GetNP());\n\n    // delete boundaryedges;\n    // boundaryedges = NULL;\n    boundaryedges = nullptr;\n\n    // delete surfelementht;\n    // surfelementht = nullptr;\n    surfelementht = nullptr;\n    // delete segmentht;\n\n    /*\n      surfelementht = new INDEX_3_HASHTABLE<int> (GetNSE()/4 + 1);\n      segmentht = new INDEX_2_HASHTABLE<int> (GetNSeg() + 1);\n    */\n\n    if (dimension == 3)\n      surfelementht = make_unique<INDEX_3_CLOSED_HASHTABLE<int>> (3*GetNSE() + 1);\n    segmentht = make_unique<INDEX_2_CLOSED_HASHTABLE<int>> (3*GetNSeg() + 1);\n\n    tn2se.Start();\n    if (dimension == 3)\n      /*\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        const Element2d & sel = surfelements[sei];\n      */\n      for (const Element2d & sel : surfelements)\n        {\n        if (sel.IsDeleted()) continue;\n\n        int si = sel.GetIndex();\n\n        /*\n        for (int j = 0; j < sel.GetNP(); j++)\n          {\n            PointIndex pi = sel[j];\n        */\n        for (PointIndex pi : sel.PNums())\n          {\n            if (!surfacesonnode[pi].Contains(si))\n              surfacesonnode.Add (pi, si);\n            /*\n            bool found = 0;\n            for (int k = 0; k < surfacesonnode[pi].Size(); k++)\n              if (surfacesonnode[pi][k] == si)\n                {\n                  found = 1;\n                  break;\n                }\n\n            if (!found)\n              surfacesonnode.Add (pi, si);\n            */\n          }\n      }\n    /*\n      for (sei = 0; sei < GetNSE(); sei++)\n      {\n      const Element2d & sel = surfelements[sei];\n      if (sel.IsDeleted()) continue;\n\n      INDEX_3 i3;\n      i3.I1() = sel.PNum(1);\n      i3.I2() = sel.PNum(2);\n      i3.I3() = sel.PNum(3);\n      i3.Sort();\n      surfelementht -> PrepareSet (i3);\n      }\n\n      surfelementht -> AllocateElements();\n    */\n    tn2se.Stop();\n    \n    tht.Start();\n    if (dimension==3)\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        const Element2d & sel = surfelements[sei];\n        if (sel.IsDeleted()) continue;\n\n        PointIndices<3> i3;\n        i3[0] = sel.PNum(1);\n        i3[1] = sel.PNum(2);\n        i3[2] = sel.PNum(3);\n        i3.Sort();\n        surfelementht -> Set (i3, sei);   // war das wichtig ???    sel.GetIndex());\n      }\n    tht.Stop();\n    \n    // int np = GetNP();\n\n    if (dimension == 3)\n      {\n        static Timer t(\"Mesh::CalcSurfacesOfNode, pointloop\"); RegionTimer reg (t);            \n        /*\n        for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n          points[pi].SetType (INNERPOINT);\n        */\n        for (auto & p : points)\n          p.SetType (INNERPOINT);\n        \n        if (GetNFD() == 0) \n          {\n            for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n              {\n                const Element2d & sel = surfelements[sei];\n                if (sel.IsDeleted()) continue;\n                for (int j = 0;  j < sel.GetNP(); j++)\n                  {\n                    PointIndex pi = SurfaceElement(sei)[j];\n                    points[pi].SetType(FIXEDPOINT);\n                  }\n              }\n          }\n        else\n          {\n            for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n              {\n                const Element2d & sel = surfelements[sei];\n                if (sel.IsDeleted()) continue;\n                for (int j = 0; j < sel.GetNP(); j++)\n                  {\n                    PointIndex pi = sel[j];\n                    int ns = surfacesonnode[pi].Size();\n                    if (ns == 1)\n                      points[pi].SetType(SURFACEPOINT);\n                    if (ns == 2)\n                      points[pi].SetType(EDGEPOINT);\n                    if (ns >= 3)\n                      points[pi].SetType(FIXEDPOINT);\n                  }      \n              }\n          }\n      }\n\n    /*\n    for (int i = 0; i < segments.Size(); i++)\n      {\n        const Segment & seg = segments[i];\n    */\n    for (const Segment & seg : segments)\n      {\n        for (int j = 1; j <= 2; j++)\n          {\n            PointIndex hi = (j == 1) ? seg[0] : seg[1];\n            if (points[hi].Type() == INNERPOINT ||\n                points[hi].Type() == SURFACEPOINT)\n              points[hi].SetType(EDGEPOINT);\n          }\n      }\n    \n    for (int i = 0; i < lockedpoints.Size(); i++)\n      points[lockedpoints[i]].SetType(FIXEDPOINT);\n\n    for(const auto& pointel : pointelements)\n      points[pointel.pnum].SetType(FIXEDPOINT);\n\n    /*\n      for (i = 0; i < openelements.Size(); i++)\n      {\n      const Element2d & sel = openelements[i];\n      for (j = 0; j < sel.GetNP(); j++)\n      {\n      INDEX_2 i2;\n      i2.I1() = sel.PNumMod(j+1);\n      i2.I2() = sel.PNumMod(j+2);\n      i2.Sort();\n      boundaryedges->Set (i2, 1);\n\n      points[sel[j]].SetType(FIXEDPOINT);\n      }\n      }\n    */\n\n    // eltyps.SetSize (GetNE());\n    // eltyps = FREEELEMENT;\n\n    for (int i = 0; i < GetNSeg(); i++)\n      {\n        const Segment & seg = segments[i];\n        PointIndices<2> i2(seg[0], seg[1]);\n        i2.Sort();\n\n        //boundaryedges -> Set (i2, 2);\n        segmentht -> Set (i2, i);\n      }\n  }\n\n  // NgBitArray base is PointIndex::BASE ... \n  void Mesh :: FixPoints (const TBitArray<PointIndex> & fixpoints)\n  {\n    if (fixpoints.Size() != GetNP())\n      {\n        cerr << \"Mesh::FixPoints: sizes don't fit\" << endl;\n        return;\n      }\n    /*\n    int np = GetNP();\n    for (int i = 1; i <= np; i++)\n      if (fixpoints.Test(i))\n        {\n          points.Elem(i).SetType (FIXEDPOINT);\n        }\n    */\n    for (PointIndex pi : points.Range())\n      if (fixpoints.Test(pi))\n        points[pi].SetType(FIXEDPOINT);\n  }\n\n\n  void Mesh :: FindOpenElements (int dom)\n  {\n    static Timer t(\"Mesh::FindOpenElements\"); RegionTimer reg (t);\n    static Timer t_table(\"Mesh::FindOpenElements - build table\"); \n    static Timer t_pointloop(\"Mesh::FindOpenElements - pointloop\"); \n\n    int np = GetNP();\n    // int ne = GetNE();\n    int nse = GetNSE();\n    \n    t_table.Start();\n\n    auto elsonpoint = ngcore::CreateSortedTable<ElementIndex, PointIndex>( volelements.Range(),\n           [&](auto & table, ElementIndex ei)\n           {\n             const Element & el = (*this)[ei];\n             if(el.IsDeleted()) return;\n             if (dom == 0 || dom == el.GetIndex())\n               {\n                 if (el.GetNP() == 4)\n                   {\n                     PointIndices<4> i4(el[0], el[1], el[2], el[3]);\n                     i4.Sort();\n                     table.Add (i4.I1(), ei);\n                     table.Add (i4.I2(), ei);\n                   }\n                 else\n                   {\n                     for (PointIndex pi : el.PNums())\n                       table.Add(pi, ei);\n                   }\n               }\n           }, GetNP());\n\n\n    NgArray<int,PointIndex::BASE> numonpoint(np);\n    /*\n    numonpoint = 0;\n    for (ElementIndex ei = 0; ei < ne; ei++)\n      {\n        const Element & el = (*this)[ei];\n        if (dom == 0 || dom == el.GetIndex())\n          {\n            if (el.GetNP() == 4)\n              {\n                INDEX_4 i4(el[0], el[1], el[2], el[3]);\n                i4.Sort();\n                numonpoint[i4.I1()]++;\n                numonpoint[i4.I2()]++;\n              }\n            else\n              for (int j = 0; j < el.GetNP(); j++)\n                numonpoint[el[j]]++;\n          }\n      }\n\n    TABLE<ElementIndex,PointIndex::BASE> elsonpoint(numonpoint);\n    for (ElementIndex ei = 0; ei < ne; ei++)\n      {\n        const Element & el = (*this)[ei];\n        if (dom == 0 || dom == el.GetIndex())\n          {\n            if (el.GetNP() == 4)\n              {\n                INDEX_4 i4(el[0], el[1], el[2], el[3]);\n                i4.Sort();\n                elsonpoint.Add (i4.I1(), ei);\n                elsonpoint.Add (i4.I2(), ei);\n              }\n            else\n              for (int j = 0; j < el.GetNP(); j++)\n                elsonpoint.Add (el[j], ei);\n          }\n      }\n    */\n    t_table.Stop();\n\n\n    NgArray<bool, 1> hasface(GetNFD());\n\n    for (int i = 1; i <= GetNFD(); i++)\n      {\n        int domin = GetFaceDescriptor(i).DomainIn();\n        int domout = GetFaceDescriptor(i).DomainOut();\n        hasface[i] = \n          ( dom == 0 && (domin != 0 || domout != 0) ) ||\n          ( dom != 0 && (domin == dom || domout == dom) );\n      }\n\n    numonpoint = 0;\n    for (SurfaceElementIndex sii = 0; sii < nse; sii++)\n      {\n        int ind = surfelements[sii].GetIndex();\n        /*\n          if (\n          GetFaceDescriptor(ind).DomainIn() && \n          (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn())\n          ||\n          GetFaceDescriptor(ind).DomainOut() && \n          (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut())\n          )\n        */\n        if (hasface[ind])\n          {\n            /*\n              Element2d hel = surfelements[i];\n              hel.NormalizeNumbering();\t  \n              numonpoint[hel[0]]++;\n            */\n            const Element2d & hel = surfelements[sii];\n            int mini = 0;\n            for (int j = 1; j < hel.GetNP(); j++)\n              if (hel[j] < hel[mini])\n                mini = j;\n            numonpoint[hel[mini]]++;\n          }\n      }\n\n    TABLE<SurfaceElementIndex,PointIndex::BASE> selsonpoint(numonpoint);\n    for (SurfaceElementIndex sii = 0; sii < nse; sii++)\n      {\n        int ind = surfelements[sii].GetIndex();\n\n        /*\n          if (\n          GetFaceDescriptor(ind).DomainIn() && \n          (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn())\n          ||\n          GetFaceDescriptor(ind).DomainOut() && \n          (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut())\n          )\n        */\n        if (hasface[ind])\n          {\n            /*\n              Element2d hel = surfelements[i];\n              hel.NormalizeNumbering();\t  \n              selsonpoint.Add (hel[0], i);\n            */\n            const Element2d & hel = surfelements[sii];\n            int mini = 0;\n            for (int j = 1; j < hel.GetNP(); j++)\n              if (hel[j] < hel[mini])\n                mini = j;\n            selsonpoint.Add (hel[mini], sii);\n          }\n      }\n\n\n    // PointIndex pi;\n    // SurfaceElementIndex sei;\n    // Element2d hel;\n\n    struct tval { int index; PointIndex p4; };\n    openelements.SetSize(0);\n    \n    t_pointloop.Start();\n\n    /*\n    INDEX_3_CLOSED_HASHTABLE<tval> faceht(100);\n    \n    for (PointIndex pi : points.Range())\n      if (selsonpoint[pi].Size()+elsonpoint[pi].Size())\n        {\n          faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size());\n\n          for (SurfaceElementIndex sei : selsonpoint[pi])\n            {\n              Element2d hel = SurfaceElement(sei);\n              if (hel.GetType() == TRIG6) hel.SetType(TRIG);\n              int ind = hel.GetIndex();\t  \n\n              if (GetFaceDescriptor(ind).DomainIn() && \n                  (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) )\n                {\n                  hel.NormalizeNumbering();\n                  if (hel.PNum(1) == pi)\n                    {\n                      INDEX_3 i3(hel[0], hel[1], hel[2]);\n                      tval i2;\n                      i2.index = GetFaceDescriptor(ind).DomainIn();\n                      i2.p4 = (hel.GetNP() == 3)\n                            ? PointIndex (PointIndex::INVALID)\n                      : hel.PNum(4);\n                      faceht.Set (i3, i2);\n                    }\n                }\n              if (GetFaceDescriptor(ind).DomainOut() &&\n                  (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) )\n                {\n                  hel.Invert();\n                  hel.NormalizeNumbering();\n                  if (hel.PNum(1) == pi)\n                    {\n                      INDEX_3 i3(hel[0], hel[1], hel[2]);\n                      tval i2;\n                      i2.index = GetFaceDescriptor(ind).DomainOut();\n                      i2.p4 = (hel.GetNP() == 3)\n                        ? PointIndex (PointIndex::INVALID)\n                        : hel.PNum(4);\n                      faceht.Set (i3, i2);\n                    }\n                }\n            }\n\n          for (ElementIndex ei : elsonpoint[pi])\n            {\n              const Element & el = VolumeElement(ei);\n\n              if (dom == 0 || el.GetIndex() == dom)\n                {\n                  for (int j = 1; j <= el.GetNFaces(); j++)\n                    {\n                      Element2d hel(TRIG);\n                      el.GetFace (j, hel);\n                      hel.Invert();\n                      hel.NormalizeNumbering();\n\n                      if (hel[0] == pi)\n                        {\n                          INDEX_3 i3(hel[0], hel[1], hel[2]);\n\n                          if (faceht.Used (i3))\n                            {\n                              tval i2 = faceht.Get(i3);\n                              if (i2.index == el.GetIndex())\n                                {\n                                  i2.index = PointIndex::BASE-1;\n                                  faceht.Set (i3, i2);\n                                }\n                              else\n                                {\n                                  if (i2.index == 0)\n                                    {\n                                      PrintSysError (\"more elements on face\");\n                                      (*testout)  << \"more elements on face!!!\" << endl;\n                                      (*testout) << \"el = \" << el << endl;\n                                      (*testout) << \"hel = \" << hel << endl;\n                                      (*testout) << \"face = \" << i3 << endl;\n                                      (*testout) << \"points = \" << endl;\n                                      for (int jj = 1; jj <= 3; jj++)\n                                        (*testout) << \"p = \" << Point(i3.I(jj)) << endl;\n                                    }\n                                }\n                            }\n                          else\n                            {\n                              hel.Invert();\n                              hel.NormalizeNumbering();\n                              INDEX_3 i3(hel[0], hel[1], hel[2]);\n                              \n                              tval i2;\n                              i2.index = el.GetIndex();\n                              i2.p4 = (hel.GetNP() == 3)\n                                ? PointIndex (PointIndex::INVALID)\n                                : hel[3];\n                              faceht.Set (i3, i2);\n                            }\n                        }\n                    }\n                }\n            }\n          \n          for (int i = 0; i < faceht.Size(); i++)\n            if (faceht.UsedPos (i))\n              {\n                INDEX_3 i3;\n                //INDEX_2 i2;\n                tval i2;\n                faceht.GetData (i, i3, i2);\n                if (i2.index != PointIndex::BASE-1)\n                  {\n                    Element2d tri ( (i2.p4 == PointIndex::BASE-1) ? TRIG : QUAD);\n                    for (int l = 0; l < 3; l++)\n                      tri[l] = i3.I(l+1);\n                    tri.PNum(4) = i2.p4;\n                    tri.SetIndex (i2.index);\n                    openelements.Append (tri);\n                  }\n              }\n        }\n\n    */\n\n    size_t numtasks = 4*ngcore::TaskManager::GetNumThreads();\n    Array<Array<Element2d>> thread_openelements(numtasks);\n    ParallelJob\n      ( [&](TaskInfo & ti)\n      {\n        auto myrange = points.Range().Split(ti.task_nr, ti.ntasks);\n        INDEX_3_CLOSED_HASHTABLE<tval> faceht(100);        \n        for (PointIndex pi : myrange)\n          if (selsonpoint[pi].Size()+elsonpoint[pi].Size())\n            {\n              faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size());\n\n              for (SurfaceElementIndex sei : selsonpoint[pi])\n                {\n                  Element2d hel = SurfaceElement(sei);\n                  if (hel.GetType() == TRIG6) hel.SetType(TRIG);\n                  int ind = hel.GetIndex();\t  \n\n                  if (GetFaceDescriptor(ind).DomainIn() && \n                      (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) )\n                    {\n                      hel.NormalizeNumbering();\n                      if (hel.PNum(1) == pi)\n                        {\n                          PointIndices<3> i3(hel[0], hel[1], hel[2]);\n                          tval i2;\n                          i2.index = GetFaceDescriptor(ind).DomainIn();\n                          i2.p4 = (hel.GetNP() == 3)\n                            ? PointIndex (PointIndex::INVALID)\n                            : hel.PNum(4);\n                          faceht.Set (i3, i2);\n                        }\n                    }\n                  if (GetFaceDescriptor(ind).DomainOut() &&\n                      (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) )\n                    {\n                      hel.Invert();\n                      hel.NormalizeNumbering();\n                      if (hel.PNum(1) == pi)\n                        {\n                          PointIndices<3> i3(hel[0], hel[1], hel[2]);\n                          tval i2;\n                          i2.index = GetFaceDescriptor(ind).DomainOut();\n                          i2.p4 = (hel.GetNP() == 3)\n                            ? PointIndex (PointIndex::INVALID)\n                            : hel.PNum(4);\n                          faceht.Set (i3, i2);\n                        }\n                    }\n                }\n              \n              for (ElementIndex ei : elsonpoint[pi])\n                {\n                  const Element & el = VolumeElement(ei);\n                  if(el.IsDeleted()) continue;\n                  \n                  if (dom == 0 || el.GetIndex() == dom)\n                    {\n                      for (int j = 1; j <= el.GetNFaces(); j++)\n                        {\n                          Element2d hel(TRIG);\n                          el.GetFace (j, hel);\n                          hel.Invert();\n                          hel.NormalizeNumbering();\n                          \n                          if (hel[0] == pi)\n                            {\n                              PointIndices<3> i3(hel[0], hel[1], hel[2]);\n                              \n                              if (faceht.Used (i3))\n                                {\n                                  tval i2 = faceht.Get(i3);\n                                  if (i2.index == el.GetIndex())\n                                    {\n                                      i2.index = long(PointIndex::BASE)-1;\n                                      faceht.Set (i3, i2);\n                                    }\n                                  else\n                                    {\n                                      if (i2.index == 0)\n                                        {\n                                          PrintSysError (\"more elements on face\");\n                                          (*testout)  << \"more elements on face!!!\" << endl;\n                                          (*testout) << \"el = \" << el << endl;\n                                          (*testout) << \"hel = \" << hel << endl;\n                                          (*testout) << \"face = \" << i3 << endl;\n                                          (*testout) << \"points = \" << endl;\n                                          for (int jj = 1; jj <= 3; jj++)\n                                            (*testout) << \"p = \" << Point(i3.I(jj)) << endl;\n                                        }\n                                    }\n                                }\n                              else\n                                {\n                                  hel.Invert();\n                                  hel.NormalizeNumbering();\n                                  PointIndices<3> i3(hel[0], hel[1], hel[2]);\n                                  \n                                  tval i2;\n                                  i2.index = el.GetIndex();\n                                  i2.p4 = (hel.GetNP() == 3)\n                                    ? PointIndex (PointIndex::INVALID)\n                                    : hel[3];\n                                  faceht.Set (i3, i2);\n                                }\n                            }\n                        }\n                    }\n                }\n              \n              for (int i = 0; i < faceht.Size(); i++)\n                if (faceht.UsedPos (i))\n                  {\n                    INDEX_3 i3;\n                    tval i2;\n                    faceht.GetData (i, i3, i2);\n                    if (i2.index != PointIndex::BASE-1)\n                      {\n                        Element2d tri ( (!i2.p4.IsValid()) ? TRIG : QUAD);\n                        for (int l = 0; l < 3; l++)\n                          tri[l] = i3.I(l+1);\n                        tri.PNum(4) = i2.p4;\n                        tri.SetIndex (i2.index);\n                        thread_openelements[ti.task_nr].Append (tri);\n                      }\n                  }\n            }}, numtasks);\n\n    for (auto & a : thread_openelements)\n      for (auto & el : a)\n        openelements.Append (el);\n    \n    t_pointloop.Stop();\n    \n    int cnt3 = 0;\n    for (int i = 0; i < openelements.Size(); i++)\n      if (openelements[i].GetNP() == 3)\n        cnt3++;\n\n    int cnt4 = openelements.Size() - cnt3;\n\n\n    MyStr treequad;\n    if (cnt4)\n      treequad = MyStr(\" (\") + MyStr(cnt3) + MyStr (\" + \") + \n        MyStr(cnt4) + MyStr(\")\");\n\n    PrintMessage (5, openelements.Size(), treequad, \" open elements\");\n\n    BuildBoundaryEdges();\n\n\n    for (int i = 1; i <= openelements.Size(); i++)\n      {\n        const Element2d & sel = openelements.Get(i);\n\n        if (boundaryedges)\n          for (int j = 1; j <= sel.GetNP(); j++)\n            {\n              INDEX_2 i2;\n              i2.I1() = sel.PNumMod(j);\n              i2.I2() = sel.PNumMod(j+1);\n              i2.Sort();\n              boundaryedges->Set (i2, 1);\n            }\n\n        for (int j = 1; j <= 3; j++)\n          {\n            PointIndex pi = sel.PNum(j);\n            // if (pi < points.End())\n            if (pi < *points.Range().end())\n              points[pi].SetType (FIXEDPOINT);\n          }\n      }\n\n\n\n    /*\n      for (i = 1; i <= GetNSeg(); i++)\n      {\n      const Segment & seg = LineSegment(i);\n      INDEX_2 i2(seg[0], seg[1]);\n      i2.Sort();\n\n      if (!boundaryedges->Used (i2))\n      cerr << \"WARNING: no boundedge, but seg edge: \" << i2 << endl;\n\n      boundaryedges -> Set (i2, 2);\n      segmentht -> Set (i2, i-1);\n      }\n    */\n  }\n\n  bool Mesh :: HasOpenQuads () const\n  {\n    int no = GetNOpenElements();\n    for (int i = 0; i < no; i++)\n      if (openelements[i].GetNP() == 4)\n        return true;\n    return false;\n  }\n\n\n\n\n\n  void Mesh :: FindOpenSegments (int surfnr)\n  {\n    // int i, j, k;\n\n    // new version, general elements\n    // hash index: pnum1-2, surfnr\n    // hash data : surfel-nr (pos) or segment nr(neg)\n    INDEX_3_HASHTABLE<int> faceht(4 * GetNSE()+GetNSeg()+1);   \n\n    PrintMessage (5, \"Test Opensegments\");\n    for (int i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment (i);\n\n        if (surfnr == 0 || seg.si == surfnr)\n          {\n            INDEX_3 key(seg[0], seg[1], seg.si);\n            int data = -i;\n\n            if (faceht.Used (key))\n              {\n                cerr << \"ERROR: Segment \" << seg << \" already used\" << endl;\n                (*testout) << \"ERROR: Segment \" << seg << \" already used\" << endl;\n              }\n\n            faceht.Set (key, data);\n          }\n      }\n\n\n    /*\n      // not possible with surfnr as hash-index\n    for (int i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment (i);\n\n        if (surfnr == 0 || seg.si == surfnr)\n          {\n            INDEX_2 key(seg[1], seg[0]);\n            if (!faceht.Used(key))\n              {\n                cerr << \"ERROR: Segment \" << seg << \" brother not used\" << endl;\n                (*testout) << \"ERROR: Segment \" << seg << \" brother not used\" << endl;\n              }\n          }\n      }\n    */\n\n    \n    // bool buggy = false;\n    // ofstream bout(\"buggy.out\");\n\n\n    for (int i = 1; i <= GetNSE(); i++)\n      {\n        const Element2d & el = SurfaceElement(i);\n        if (el.IsDeleted()) continue;\n\n        if (surfnr == 0 || el.GetIndex() == surfnr)\n          {\n            for (int j = 1; j <= el.GetNP(); j++)\n              {\n                PointIndices<3> seg (el.PNumMod(j), el.PNumMod(j+1), el.GetIndex());\n                // int data;\n\n                if (!seg.I1().IsValid() || !seg.I2().IsValid())\n                  cerr << \"seg = \" << seg << endl;\n\n                if (faceht.Used(seg))\n                  {\n                    faceht.Set (seg, 0);\n                    /*\n                    data = faceht.Get(seg);\n                    \n                    if (data.I1() == el.GetIndex())\n                      {\n                        data.I1() = 0;\n                        faceht.Set (seg, data);\n                      }\n                    else\n                      {\n\t\t\t// buggy = true;\n                        PrintWarning (\"hash table si not fitting for segment: \",\n                                       seg.I1(), \"-\", seg.I2(), \" other = \",\n                                      data.I2(), \", surfnr = \", surfnr);\n                      }\n                    */\n                  }\n                else\n                  {\n                    Swap (seg.I1(), seg.I2());\n                    // data.I1() = el.GetIndex();\n                    // data.I2() = i;\n                    faceht.Set (seg, i);\n                  }\n              }\n          }\n      }  \n\n    /*\n    if (buggy)\n      {\n\tfor (int i = 1; i <= GetNSeg(); i++)\n\t  bout << \"seg\" << i << \" \" << LineSegment(i) << endl;\n\n\tfor (int i = 1; i <= GetNSE(); i++)\n\t  bout << \"sel\" << i << \" \" << SurfaceElement(i) << \" ind = \" \n\t       << SurfaceElement(i).GetIndex() << endl;\n\n\tbout << \"hashtable: \" << endl;\n\tfor (int j = 1; j <= faceht.GetNBags(); j++)\n\t  {\n\t    bout << \"bag \" << j << \":\" << endl;\n\t    for (int k = 1; k <= faceht.GetBagSize(j); k++)\n\t      {\n\t\tINDEX_2 i2, data;\n\t\tfaceht.GetData (j, k, i2, data);\n\t\tbout << \"key = \" << i2 << \", data = \" << data << endl;\n\t      }\n\t  }\n\texit(1);\n      }\n    */\n\n    (*testout) << \"open segments: \" << endl;\n    opensegments.SetSize(0);\n    for (int i = 1; i <= faceht.GetNBags(); i++)\n      for (int j = 1; j <= faceht.GetBagSize(i); j++)\n        {\n          PointIndices<3> i2;\n          int data;\n          faceht.GetData (i, j, i2, data);\n          if (data)  // surfnr\n            {\n              Segment seg;\n              seg[0] = i2.I1();\n              seg[1] = i2.I2();\n              seg.si = i2.I3();\n\n              // find geomdata:\n              if (data > 0)\n                {\n                  // segment due to triangle\n                  const Element2d & el = SurfaceElement (data);\n                  for (int k = 1; k <= el.GetNP(); k++)\n                    {\n                      if (seg[0] == el.PNum(k))\n                        seg.geominfo[0] = el.GeomInfoPi(k);\n                      if (seg[1] == el.PNum(k))\n                        seg.geominfo[1] = el.GeomInfoPi(k);\n                    }\n\n                  (*testout) << \"trig seg: \";\n                }\n              else\n                {\n                  // segment due to line\n                  const Segment & lseg = LineSegment (-data);\n                  seg.geominfo[0] = lseg.geominfo[0];\n                  seg.geominfo[1] = lseg.geominfo[1];\n\n                  (*testout) << \"line seg: \";\n                }\n\n              (*testout) << seg[0] << \" - \" << seg[1] \n                         << \" len = \" << Dist (Point(seg[0]), Point(seg[1]))\n                         << endl;\n\n              opensegments.Append (seg);\n              if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0)\n                {\n                  (*testout) << \"Problem with open segment: \" << seg << endl;\n                }\n\n            }\n        }\n\n    PrintMessage (3, opensegments.Size(), \" open segments found\");\n    (*testout) << opensegments.Size() << \" open segments found\" << endl;\n\n    /*\n      ptyps.SetSize (GetNP());\n      for (i = 1; i <= ptyps.Size(); i++)\n      ptyps.Elem(i) = SURFACEPOINT;\n\n      for (i = 1; i <= GetNSeg(); i++)\n      {\n      const Segment & seg = LineSegment (i);\n      ptyps.Elem(seg[0]) = EDGEPOINT;\n      ptyps.Elem(seg[1]) = EDGEPOINT;\n      }\n      for (i = 1; i <= GetNOpenSegments(); i++)\n      {\n      const Segment & seg = GetOpenSegment (i);\n      ptyps.Elem(seg[0]) = EDGEPOINT;\n      ptyps.Elem(seg[1]) = EDGEPOINT;\n      }\n    */\n    /*\n    for (int i = 1; i <= points.Size(); i++)\n      points.Elem(i).SetType(SURFACEPOINT);\n    */\n    for (auto & p : points)\n      p.SetType (SURFACEPOINT);\n    \n    for (int i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment (i);\n        points[seg[0]].SetType(EDGEPOINT);\n        points[seg[1]].SetType(EDGEPOINT);\n      }\n    for (int i = 1; i <= GetNOpenSegments(); i++)\n      {\n        const Segment & seg = GetOpenSegment (i);\n        points[seg[0]].SetType (EDGEPOINT);\n        points[seg[1]].SetType (EDGEPOINT);\n      }\n\n\n\n    /*\n\n    for (i = 1; i <= openelements.Size(); i++)\n    {\n    const Element2d & sel = openelements.Get(i);\n\n    if (boundaryedges)\n    for (j = 1; j <= sel.GetNP(); j++)\n    {\n    INDEX_2 i2;\n    i2.I1() = sel.PNumMod(j);\n    i2.I2() = sel.PNumMod(j+1);\n    i2.Sort();\n    boundaryedges->Set (i2, 1);\n    }\n\n    for (j = 1; j <= 3; j++)\n    {\n    int pi = sel.PNum(j);\n    if (pi <= ptyps.Size())\n    ptyps.Elem(pi) = FIXEDPOINT;\n    }\n    }\n    */\n  }\n\n\n  void Mesh :: RemoveOneLayerSurfaceElements ()\n  {\n    int np = GetNP();\n\n    FindOpenSegments();\n    TBitArray<PointIndex> frontpoints(np);  // for 0- and 1-based\n    frontpoints.Clear();\n    \n    for (int i = 1; i <= GetNOpenSegments(); i++)\n      {\n        const Segment & seg = GetOpenSegment(i);\n        frontpoints.SetBit (seg[0]);\n        frontpoints.SetBit (seg[1]);\n      }\n\n    for (int i = 1; i <= GetNSE(); i++)\n      {\n        Element2d & sel = surfelements[i-1];\n        bool remove = false;\n        for (int j = 1; j <= sel.GetNP(); j++)\n          if (frontpoints.Test(sel.PNum(j)))\n            remove = true;\n        if (remove)\n          sel.PNum(1).Invalidate();\n      }\n\n    for (int i = surfelements.Size(); i >= 1; i--)\n      {\n        if (!surfelements[i-1].PNum(1).IsValid())\n          {\n            surfelements[i-1] = surfelements.Last();\n            surfelements.DeleteLast();\n          }\n      }\n\n    RebuildSurfaceElementLists ();\n    /*\n    for (int i = 0; i < facedecoding.Size(); i++)\n      facedecoding[i].firstelement = -1;\n    for (int i = surfelements.Size()-1; i >= 0; i--)\n      {\n        int ind = surfelements[i].GetIndex();\n        surfelements[i].next = facedecoding[ind-1].firstelement;\n        facedecoding[ind-1].firstelement = i;\n      }\n    */\n\n    timestamp = NextTimeStamp();\n    //  Compress();\n  }\n\n\n\n\n\n  void Mesh :: FreeOpenElementsEnvironment (int layers)\n  {\n    static Timer timer(\"FreeOpenElementsEnvironment\"); RegionTimer rt(timer);\n    const int large = 9999;\n    Array<int,PointIndex> dist(GetNP());\n\n    dist = large;\n\n    for (int i = 1; i <= GetNOpenElements(); i++)\n      {\n        const Element2d & face = OpenElement(i);\n        for (int j = 0; j < face.GetNP(); j++)\n          dist[face[j]] = 1;\n      }\n\n    for (int k = 1; k <= layers; k++)\n      /*\n      for (i = 1; i <= GetNE(); i++)\n        {\n          const Element & el = VolumeElement(i);\n      */\n      for (auto & el : VolumeElements())\n        {\n          if (!el[0].IsValid() || el.IsDeleted()) continue;\n\n          int elmin = large;\n          for (int j = 0; j < el.GetNP(); j++)\n            if (dist[el[j]] < elmin)\n              elmin = dist[el[j]];\n          \n          if (elmin < large)\n            {\n              for (int j = 0; j < el.GetNP(); j++)\n                if (dist[el[j]] > elmin+1)\n                  dist[el[j]] = elmin+1;\n            }\n        }\n\n    int cntfree = 0;\n    /*\n    for (int i = 1; i <= GetNE(); i++)\n      {\n        Element & el = VolumeElement(i);\n    */\n    for (auto & el : VolumeElements())\n      {\n        if (!el[0].IsValid() || el.IsDeleted()) continue;\n\n        int elmin = large;\n        for (int j = 0; j < el.GetNP(); j++)\n          if (dist[el[j]] < elmin)\n            elmin = dist[el[j]];\n\n        el.Flags().fixed = elmin > layers;\n        // eltyps.Elem(i) = (elmin <= layers) ? \n        // FREEELEMENT : FIXEDELEMENT;\n        if (elmin <= layers)\n          cntfree++;\n      }\n\n    PrintMessage (5, \"free: \", cntfree, \", fixed: \", GetNE()-cntfree);\n    (*testout) << \"free: \" << cntfree << \", fixed: \" << GetNE()-cntfree << endl;\n\n    for (PointIndex pi = IndexBASE<PointIndex>(); \n         pi < GetNP()+IndexBASE<PointIndex>(); pi++)\n      {\n        if (dist[pi] > layers+1)\n          points[pi].SetType(FIXEDPOINT);\n      }\n  }\n\n\n\n  void Mesh :: SetLocalH (netgen::Point<3> pmin, netgen::Point<3> pmax, double grading, int layer)\n  {\n    using netgen::Point;\n    Point<3> c = Center (pmin, pmax);\n    double d = max3 (pmax(0)-pmin(0),\n                     pmax(1)-pmin(1),\n                     pmax(2)-pmin(2));\n    d /= 2;\n    Point<3> pmin2 = c - Vec<3> (d, d, d);\n    Point<3> pmax2 = c + Vec<3> (d, d, d);\n\n    SetLocalH(make_unique<LocalH> (pmin2, pmax2, grading, dimension), layer);\n  }\n\n  void Mesh :: RestrictLocalH (const Point3d & p, double hloc, int layer)\n  {\n    if(hloc < hmin)\n      hloc = hmin;\n\n    //cout << \"restrict h in \" << p << \" to \" << hloc << endl;\n    if (!lochfunc[layer-1])\n      {\n        PrintWarning(\"RestrictLocalH called, creating mesh-size tree\");\n\n        Point3d boxmin, boxmax;\n        GetBox (boxmin, boxmax);\n        SetLocalH (boxmin, boxmax, 0.8, layer);\n      }\n\n    lochfunc[layer-1] -> SetH (p, hloc);\n  }\n\n  void Mesh :: RestrictLocalHLine (const Point3d & p1, \n                                   const Point3d & p2,\n                                   double hloc, int layer)\n  {\n    if(hloc < hmin)\n      hloc = hmin;\n\n    // cout << \"restrict h along \" << p1 << \" - \" << p2 << \" to \" << hloc << endl;\n    int i;\n    int steps = int (Dist (p1, p2) / hloc) + 2;\n    Vec3d v(p1, p2);\n\n    for (i = 0; i <= steps; i++)\n      {\n        Point3d p = p1 + (double(i)/double(steps) * v);\n        RestrictLocalH (p, hloc, layer);\n      }\n  }\n\n\n  void Mesh :: SetMinimalH (double h)\n  {\n    hmin = h;\n  }\n\n\n  void Mesh :: SetGlobalH (double h)\n  {\n    hglob = h;\n  }\n\n  double Mesh :: MaxHDomain (int dom) const\n  {\n    if (dom >= 0 && dom < maxhdomain.Size())\n      return maxhdomain.Get(dom);\n    else\n      return 1e10;\n  }\n\n  void Mesh :: SetMaxHDomain (const NgArray<double> & mhd)\n  {\n    maxhdomain.SetSize(mhd.Size());\n    for (int i = 1; i <= mhd.Size(); i++)\n      maxhdomain.Elem(i) = mhd.Get(i);\n  }\n\n\n  double Mesh :: GetH (const Point3d & p, int layer) const\n  {\n    const auto& lh = GetLocalH(layer);\n    double hmin = hglob;\n    if (lh)\n      {\n        double hl = lh->GetH (p);\n        if (hl < hglob)\n          hmin = hl;\n      }\n    return hmin;\n  }\n\n  double Mesh :: GetMinH (const Point3d & pmin, const Point3d & pmax, int layer)\n  {\n    const auto& lh = GetLocalH(layer);\n    double hmin = hglob;\n    if (lh)\n      {\n        double hl = lh->GetMinH (pmin, pmax);\n        if (hl < hmin)\n          hmin = hl;\n      }\n    return hmin;\n  }\n\n\n\n\n\n  double Mesh :: AverageH (int surfnr) const\n  {\n    int i, j, n;\n    double hi, hsum;\n    double maxh = 0, minh = 1e10;\n\n    hsum = 0;\n    n = 0;\n    for (i = 1; i <= GetNSE(); i++)\n      {\n        const Element2d & el = SurfaceElement(i);\n        if (surfnr == 0 || el.GetIndex() == surfnr)\n          {\n            for (j = 1; j <= 3; j++)\n              {\n                hi = Dist (Point (el.PNumMod(j)), \n                           Point (el.PNumMod(j+1)));\n\n                hsum += hi;\n\n                if (hi > maxh) maxh = hi;\n                if (hi < minh) minh = hi;\n                n++;\n              }\n          }\n      }\n\n    PrintMessage (5, \"minh = \", minh, \" avh = \", (hsum/n), \" maxh = \", maxh);\n    return (hsum / n);\n  }\n\n\n\n  void Mesh :: CalcLocalH (double grading, int layer)\n  {\n    static Timer t(\"Mesh::CalcLocalH\"); RegionTimer reg(t);\n    \n    if (!lochfunc[layer-1])\n      {\n        Point3d pmin, pmax;\n        GetBox (pmin, pmax);\n        // SetLocalH (pmin, pmax, mparam.grading);\n\tSetLocalH (pmin, pmax, grading, layer);\n      }\n\n    PrintMessage (3,\n                  \"CalcLocalH: \", \n                  GetNP(), \" Points \", \n                  GetNE(), \" Elements \", \n                  GetNSE(), \" Surface Elements\");\n\n\n    for (int i = 0; i < GetNSE(); i++)\n      {\n        const Element2d & el = surfelements[i];\n        int j;\n\n        if (el.GetNP() == 3)\n          {\n            double hel = -1;\n            for (j = 1; j <= 3; j++)\n              {\n                const Point3d & p1 = points[el.PNumMod(j)];\n                const Point3d & p2 = points[el.PNumMod(j+1)];\n\n                /*\n                  INDEX_2 i21(el.PNumMod(j), el.PNumMod(j+1));\n                  INDEX_2 i22(el.PNumMod(j+1), el.PNumMod(j));\n                  if (! identifiedpoints->Used (i21) &&\n                  ! identifiedpoints->Used (i22) )\n                */\n                if (!ident -> UsedSymmetric (el.PNumMod(j),\n                                             el.PNumMod(j+1)))\n                  {\n                    double hedge = Dist (p1, p2);\n                    if (hedge > hel)\n                      hel = hedge;\n                    //\t\t  lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));\n                    //\t\t  (*testout) << \"trigseth, p1,2 = \" << el.PNumMod(j) << \", \" << el.PNumMod(j+1) \n                    //\t\t\t     << \" h = \" << (2 * Dist(p1, p2)) << endl;\n                  }\n              }\n\n            if (hel > 0)\n              {\n                const Point3d & p1 = points[el.PNum(1)];\n                const Point3d & p2 = points[el.PNum(2)];\n                const Point3d & p3 = points[el.PNum(3)];\n                lochfunc[layer-1]->SetH (Center (p1, p2, p3), hel);\n              }\n          }\n        else\n          {\n            {\n              const Point3d & p1 = points[el.PNum(1)];\n              const Point3d & p2 = points[el.PNum(2)];\n              lochfunc[layer-1]->SetH (Center (p1, p2), 2 * Dist (p1, p2));\n            }\n            {\n              const Point3d & p1 = points[el.PNum(3)];\n              const Point3d & p2 = points[el.PNum(4)];\n              lochfunc[layer-1]->SetH (Center (p1, p2), 2 * Dist (p1, p2));\n            }\n          }\n      }\n\n    for (int i = 0; i < GetNSeg(); i++)\n      {\n        const Segment & seg = segments[i];\n        const Point3d & p1 = points[seg[0]];\n        const Point3d & p2 = points[seg[1]];\n        /*\n          INDEX_2 i21(seg[0], seg[1]);\n          INDEX_2 i22(seg[1], seg[0]);\n          if (identifiedpoints)\n          if (!identifiedpoints->Used (i21) && !identifiedpoints->Used (i22))\n        */\n        if (!ident -> UsedSymmetric (seg[0], seg[1]))\n          {\n            lochfunc[layer-1]->SetH (Center (p1, p2), Dist (p1, p2));\n          }\n      }\n    /*\n      cerr << \"do vol\" << endl;\n      for (i = 1; i <= GetNE(); i++)\n      {\n      const Element & el = VolumeElement(i);\n      if (el.GetType() == TET)\n      {\n      int j, k;\n      for (j = 2; j <= 4; j++)\n      for (k = 1; k < j; k++)  \n      {\n      const Point3d & p1 = Point (el.PNum(j));\n      const Point3d & p2 = Point (el.PNum(k));\n      lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));\n      (*testout) << \"set vol h to \" << (2 * Dist (p1, p2)) << endl;\n\n      }\n      }\n      }\n    */\n\n    /*\n      const char * meshsizefilename = \n      globflags.GetStringFlag (\"meshsize\", NULL);\n      if (meshsizefilename)\n      {\n      ifstream msf(meshsizefilename);\n      if (msf)\n      {\n      int nmsp;\n      msf >> nmsp;\n      for (i = 1; i <= nmsp; i++)\n      {\n      Point3d pi;\n      double hi;\n      msf >> pi.X() >> pi.Y() >> pi.Z();\n      msf >> hi;\n      lochfunc->SetH (pi, hi);\n      }\n      }\n      }\n    */\n    //  lochfunc -> Convexify();\n    //  lochfunc -> PrintMemInfo (cout);\n  }\n\n\n  void Mesh :: CalcLocalHFromPointDistances(double grading, int layer)\n  {\n    PrintMessage (3, \"Calculating local h from point distances\");\n\n    if (!lochfunc[layer-1])\n      {\n        Point3d pmin, pmax;\n        GetBox (pmin, pmax);\n\n        // SetLocalH (pmin, pmax, mparam.grading);\n\tSetLocalH (pmin, pmax, grading, layer);\n      }\n\n    // double hl;\n\n    for (PointIndex i = IndexBASE<PointIndex>(); \n         i < GetNP()+IndexBASE<PointIndex>(); i++)\n      {\n        for(PointIndex j=i+1; j<GetNP()+IndexBASE<PointIndex>(); j++)\n          {\n            const Point3d & p1 = points[i];\n            const Point3d & p2 = points[j];\n            double hl = Dist(p1,p2);\n            RestrictLocalH(p1,hl);\n            RestrictLocalH(p2,hl);\n            //cout << \"restricted h at \" << p1 << \" and \" << p2 << \" to \" << hl << endl;\n          }\n      }\n\n\n  }\n\n\n  void Mesh :: CalcLocalHFromSurfaceCurvature (double grading, double elperr, int layer) \n  {\n    PrintMessage (3, \"Calculating local h from surface curvature\");\n\n    if (!lochfunc[layer-1])\n      {\n        Point3d pmin, pmax;\n        GetBox (pmin, pmax);\n\n        // SetLocalH (pmin, pmax, mparam.grading);\n\tSetLocalH (pmin, pmax, grading, layer);\n      }\n\n\n    INDEX_2_HASHTABLE<int> edges(3 * GetNP() + 2);\n    INDEX_2_HASHTABLE<int> bedges(GetNSeg() + 2);\n    int i, j;\n\n    for (i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment(i);\n        PointIndices<2> i2(seg[0], seg[1]);\n        i2.Sort();\n        bedges.Set (i2, 1);\n      }\n    for (i = 1; i <= GetNSE(); i++)\n      {\n        const Element2d & sel = SurfaceElement(i);\n        if (!sel.PNum(1).IsValid())\n          continue;\n        for (j = 1; j <= 3; j++)\n          {\n            PointIndices<2> i2(sel.PNumMod(j), sel.PNumMod(j+1));\n            i2.Sort();\n            if (bedges.Used(i2)) continue;\n\n            if (edges.Used(i2))\n              {\n                int other = edges.Get(i2);\n\n                const Element2d & elother = SurfaceElement(other);\n\n                int pi3_ = 1;\n                while ( (sel.PNum(pi3_) == i2[0]) || \n                        (sel.PNum(pi3_) == i2[1]))\n                  pi3_++;\n                PointIndex pi3 = sel.PNum(pi3_);\n\n                int pi4_ = 1;\n                while ( (elother.PNum(pi4_) == i2[0]) || \n                        (elother.PNum(pi4_) == i2[1]))\n                  pi4_++;\n                PointIndex pi4 = elother.PNum(pi4_);\n\n                double rad = ComputeCylinderRadius (Point (i2[0]),\n                                                    Point (i2[1]),\n                                                    Point (pi3),\n                                                    Point (pi4));\n\n                RestrictLocalHLine (Point(PointIndex(i2.I1())), Point(PointIndex(i2.I2())), rad/elperr);\n\n\n                /*\t      \n                  (*testout) << \"pi1,2, 3, 4 = \" << i2.I1() << \", \" << i2.I2() << \", \" << pi3 << \", \" << pi4\n                  << \" p1 = \" << Point(i2.I1()) \n                  << \", p2 = \" << Point(i2.I2()) \n                  //\t\t\t << \", p3 = \" << Point(pi3) \n                  //\t\t\t << \", p4 = \" << Point(pi4) \n                  << \", rad = \" << rad << endl;\n                */\n              }\n            else\n              edges.Set (i2, i);\n          }\n      }\n\n\n    // Restrict h due to line segments\n\n    for (i = 1; i <= GetNSeg(); i++)\n      {\n        const Segment & seg = LineSegment(i);\n        const Point3d & p1 = Point(seg[0]);\n        const Point3d & p2 = Point(seg[1]);\n        RestrictLocalH (Center (p1, p2),  Dist (p1, p2));\n      }\n\n\n\n    /*\n\n\n    int i, j;\n    int np = GetNP();\n    int nseg = GetNSeg();\n    int nse = GetNSE();\n\n    NgArray<Vec3d> normals(np);\n    NgBitArray linepoint(np);\n\n    linepoint.Clear();\n    for (i = 1; i <= nseg; i++)\n    {\n    linepoint.Set (LineSegment(i)[0]);\n    linepoint.Set (LineSegment(i)[1]);\n    }\n\n    for (i = 1; i <= np; i++)\n    normals.Elem(i) = Vec3d(0,0,0);\n\n    for (i = 1; i <= nse; i++)\n    {\n    Element2d & el = SurfaceElement(i);\n    Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))),\n    Vec3d (Point (el.PNum(1)), Point(el.PNum(3))));\n    for (j = 1; j <= 3; j++)\n    normals.Elem(el.PNum(j)) += nf;\n    }\n\n    for (i = 1; i <= np; i++)\n    normals.Elem(i) /= (1e-12 + normals.Elem(i).Length());\n\n    for (i = 1; i <= nse; i++)\n    {\n    Element2d & el = SurfaceElement(i);\n    Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))),\n    Vec3d (Point (el.PNum(1)), Point(el.PNum(3))));\n    nf /= nf.Length();\n    Point3d c = Center (Point(el.PNum(1)),\n    Point(el.PNum(2)),\n    Point(el.PNum(3)));\n\n    for (j = 1; j <= 3; j++)\n    {\n    if (!linepoint.Test (el.PNum(j)))\n    {\n    double dist = Dist (c, Point(el.PNum(j)));\n    double dn = (nf - normals.Get(el.PNum(j))).Length();\n\n    RestrictLocalH (Point(el.PNum(j)), dist / (dn+1e-12) /elperr);\n    }\n    }\n    }\n    */\n  }\n\n\n  void Mesh :: RestrictLocalH (resthtype rht, int nr, double loch)\n  {\n    int i;\n    switch (rht)\n      {\n      case RESTRICTH_FACE:\n        {\n          for (i = 1; i <= GetNSE(); i++)\n            {\n              const Element2d & sel = SurfaceElement(i);\n              if (sel.GetIndex() == nr)\n                RestrictLocalH (RESTRICTH_SURFACEELEMENT, i, loch);\n            }\n          break;\n        }\n      case RESTRICTH_EDGE:\n        {\n          for (i = 1; i <= GetNSeg(); i++)\n            {\n              const Segment & seg = LineSegment(i);\n              if (seg.edgenr == nr)\n                RestrictLocalH (RESTRICTH_SEGMENT, i, loch);\n            }\n          break;\n        }\n      case RESTRICTH_POINT:\n        {\n          RestrictLocalH (Point (nr), loch);\n          break;\n        }\n\n      case RESTRICTH_SURFACEELEMENT:\n        {\n          const Element2d & sel = SurfaceElement(nr);\n          Point3d p = Center (Point(sel.PNum(1)),\n                              Point(sel.PNum(2)),\n                              Point(sel.PNum(3)));\n          RestrictLocalH (p, loch);\n          break;\n        }\n      case RESTRICTH_SEGMENT:\n        {\n          const Segment & seg = LineSegment(nr);\n          RestrictLocalHLine (Point (seg[0]), Point(seg[1]), loch);\n          break;\n        }\n      }\n  }\n\n\n  void Mesh :: LoadLocalMeshSize (const filesystem::path &  meshsizefilename)\n  {\n    // Philippose - 10/03/2009\n    // Improve error checking when loading and reading\n    // the local mesh size file\n\n    if (meshsizefilename.empty()) return;\n\n    ifstream msf(meshsizefilename);\n\n    // Philippose - 09/03/2009\n    // Adding print message information in case the specified \n    // does not exist, or does not load successfully due to \n    // other reasons such as access rights, etc...\n    if (!msf) \n      {\n        PrintMessage(3, \"Error loading mesh size file: \", meshsizefilename, \"....\",\"Skipping!\");\n        return;\n      }\n\n    PrintMessage (3, \"Load local mesh-size file: \", meshsizefilename);\n\n    int nmsp = 0;\n    int nmsl = 0;\n\n    msf >> nmsp;\n    if(!msf.good())\n      throw NgException (\"Mesh-size file error: No points found\\n\");\n\n    if(nmsp > 0)\n      PrintMessage (4, \"Number of mesh-size restriction points: \", nmsp);\n\n    for (int i = 0; i < nmsp; i++)\n      {\n        Point3d pi;\n        double hi;\n        msf >> pi.X() >> pi.Y() >> pi.Z();\n        msf >> hi;\n        if (!msf.good())\n          throw NgException (\"Mesh-size file error: Number of points don't match specified list size\\n\");\n        RestrictLocalH (pi, hi);\n      }\n\n    msf >> nmsl;\n    if(!msf.good())\n      throw NgException (\"Mesh-size file error: No line definitions found\\n\");\n\n    if(nmsl > 0)\n      PrintMessage (4, \"Number of mesh-size restriction lines: \", nmsl);\n\n    for (int i = 0; i < nmsl; i++)\n      {\n        Point3d p1, p2;\n        double hi;\n        msf >> p1.X() >> p1.Y() >> p1.Z();\n        msf >> p2.X() >> p2.Y() >> p2.Z();\n        msf >> hi;\n        if (!msf.good())\n          throw NgException (\"Mesh-size file error: Number of line definitions don't match specified list size\\n\");\n        RestrictLocalHLine (p1, p2, hi);\n      }\n\n    msf.close();\n  }\n\n\n\n  void Mesh :: SetLocalH(shared_ptr<LocalH> loch, int layer)\n  {\n      if(layer>lochfunc.Size())\n      {\n          auto pre_size = lochfunc.Size();\n          lochfunc.SetSize(layer);\n          for(auto & func : lochfunc.Range(pre_size, layer-1))\n              func = lochfunc[0];\n      }\n      lochfunc[layer-1] = loch;\n  }\n\n  void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, int dom) const\n  {\n    if (points.Size() == 0)\n      {\n        pmin = pmax = Point3d(0,0,0);\n        return;\n      }\n\n    if (dom <= 0)\n      {\n        pmin = Point3d (1e10, 1e10, 1e10);\n        pmax = Point3d (-1e10, -1e10, -1e10); \n\n        // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n        for (PointIndex pi : points.Range())\n          {\n            pmin.SetToMin ( (*this) [pi] );\n            pmax.SetToMax ( (*this) [pi] );\n          }\n      }\n    else\n      {\n        int j, nse = GetNSE();\n        SurfaceElementIndex sei;\n\n        pmin = Point3d (1e10, 1e10, 1e10);\n        pmax = Point3d (-1e10, -1e10, -1e10); \n        for (sei = 0; sei < nse; sei++)\n          {\n            const Element2d & el = (*this)[sei];\n            if (el.IsDeleted() ) continue;\n\n            if (dom == -1 || el.GetIndex() == dom)\n              {\n                for (j = 0; j < 3; j++)\n                  {\n                    pmin.SetToMin ( (*this) [el[j]] );\n                    pmax.SetToMax ( (*this) [el[j]] );\n                  }\n              }\n          }\n      }\n\n    if (pmin.X() > 0.5e10)\n      {\n        pmin = pmax = Point3d(0,0,0);\n      }\n  }\n\n\n\n\n  void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp) const\n  {\n    if (points.Size() == 0)\n      {\n        pmin = pmax = Point3d(0,0,0);\n        return;\n      }\n\n    pmin = Point3d (1e10, 1e10, 1e10);\n    pmax = Point3d (-1e10, -1e10, -1e10); \n\n    // for (PointIndex pi = points.Begin(); pi < points.End(); pi++)\n    for (PointIndex pi : points.Range())\n      if (points[pi].Type() <= ptyp)\n        {\n          pmin.SetToMin ( (*this) [pi] );\n          pmax.SetToMax ( (*this) [pi] );\n        }\n  }\n\n\n\n\n  double Mesh :: ElementError (int eli, const MeshingParameters & mp) const\n  {\n    const Element & el = volelements[eli-1];\n    return CalcTetBadness (points[el[0]], points[el[1]],\n                           points[el[2]], points[el[3]], -1, mp);\n  }\n\n  void Mesh :: AddLockedPoint (PointIndex pi)\n  { \n    lockedpoints.Append (pi); \n  }\n\n  void Mesh :: ClearLockedPoints ()\n  { \n    lockedpoints.SetSize (0); \n  }\n\n\n\n  void Mesh :: Compress ()\n  {\n    static Timer t(\"Mesh::Compress\"); RegionTimer reg(t);\n    NgLock lock(mutex);\n    lock.Lock();\n    \n    Array<PointIndex,PointIndex> op2np(GetNP());\n    Array<bool, PointIndex> pused(GetNP());\n\n    /*\n      (*testout) << \"volels: \" << endl;\n      for (i = 1; i <= volelements.Size(); i++)\n      {\n      for (j = 1; j <= volelements.Get(i).GetNP(); j++)\n      (*testout) << volelements.Get(i).PNum(j) << \" \";\n      (*testout) << endl;\n      }\n      (*testout) << \"np: \" << GetNP() << endl;\n    */\n\n    for (int i = 0; i < volelements.Size(); i++)\n      if (!volelements[i][0].IsValid() ||\n          volelements[i].IsDeleted())\n        {\n          volelements.DeleteElement(i);\n          i--;\n        }\n\n\n    for (int i = 0; i < surfelements.Size(); i++)\n      if (surfelements[i].IsDeleted())\n        {\n          surfelements.DeleteElement(i);\n          i--;\n        }\n\n    for (int i = 0; i < segments.Size(); i++)\n      if (!segments[i][0].IsValid())\n        {\n          segments.DeleteElement(i);\n          i--;\n        }\n\n    for(int i=0; i < segments.Size(); i++)\n      if(segments[i].edgenr < 0)\n          segments.DeleteElement(i--);\n\n    pused = false;\n    /*\n    for (int i = 0; i < volelements.Size(); i++)\n      {\n        const Element & el = volelements[i];\n        for (int j = 0; j < el.GetNP(); j++)\n          pused[el[j]] = true;\n      }\n    */\n    /*\n    for (const Element & el : volelements)\n      for (PointIndex pi : el.PNums())\n        pused[pi] = true;\n    */\n\n    ParallelForRange\n      (volelements.Range(), [&] (auto myrange)\n       {\n         for (const Element & el : volelements.Range(myrange))\n           for (PointIndex pi : el.PNums())\n             pused[pi] = true;\n       });\n\n    /*\n    for (int i = 0; i < surfelements.Size(); i++)\n      {\n        const Element2d & el = surfelements[i];\n        for (int j = 0; j < el.GetNP(); j++)\n          pused[el[j]] = true;\n      }\n    */\n    ParallelForRange\n      (surfelements.Range(), [&] (auto myrange)\n       {\n         for (const Element2d & el : surfelements.Range(myrange))\n           for (PointIndex pi : el.PNums())\n             pused[pi] = true;\n       });\n    \n    for (int i = 0; i < segments.Size(); i++)\n      {\n        const Segment & seg = segments[i];\n        for (int j = 0; j < seg.GetNP(); j++)\n          pused[seg[j]] = true;\n      }\n\n    for(auto& pe : pointelements)\n      pused[pe.pnum] = true;\n\n    for (int i = 0; i < openelements.Size(); i++)\n      {\n        const Element2d & el = openelements[i];\n        for (int j = 0; j < el.GetNP(); j++)\n          pused[el[j]] = true;\n      }\n\n    for (int i = 0; i < lockedpoints.Size(); i++)\n      pused[lockedpoints[i]] = true;\n\n\n    /*\n    // compress points doesn't work for identified points !\n    if (identifiedpoints)\n    {\n    for (i = 1; i <= identifiedpoints->GetNBags(); i++)\n    if (identifiedpoints->GetBagSize(i))\n    {\n    pused.Set ();\n    break;\n    }\n    }\n    */\n    //  pused.Set();\n\n    \n    {\n      Array<MeshPoint> hpoints;\n      PointIndex npi = IndexBASE<PointIndex>();\n      for (PointIndex pi : points.Range())\n        if (pused[pi])\n          {\n            op2np[pi] = npi;\n            npi++;\n            hpoints.Append (points[pi]);\n          }\n        else\n          {\n            op2np[pi].Invalidate(); \n          }\n      \n      points.SetSize(0);\n      for (int i = 0; i < hpoints.Size(); i++)\n        points.Append (hpoints[i]);\n    }\n    \n    /*\n    for (int i = 1; i <= volelements.Size(); i++)\n      {\n        Element & el = VolumeElement(i);\n        for (int j = 0; j < el.GetNP(); j++)\n          el[j] = op2np[el[j]];\n      }\n    */\n    ParallelForRange\n      (volelements.Range(), [&] (auto myrange)\n       {\n         for (Element & el : volelements.Range(myrange))\n           for (PointIndex & pi : el.PNums())\n             pi = op2np[pi];\n       });\n\n    /*\n    for (int i = 1; i <= surfelements.Size(); i++)\n      {\n        Element2d & el = SurfaceElement(i);\n        for (int j = 0; j < el.GetNP(); j++)\n          el[j] = op2np[el[j]];\n      }\n    */\n    ParallelForRange\n      (surfelements.Range(), [&] (auto myrange)\n       {\n         for (Element2d & el : surfelements.Range(myrange))\n           for (PointIndex & pi : el.PNums())\n             pi = op2np[pi];\n       });\n\n    \n    for (int i = 0; i < segments.Size(); i++)\n      {\n        Segment & seg = segments[i];\n        for (int j = 0; j < seg.GetNP(); j++)\n          seg[j] = op2np[seg[j]];\n      }\n\n    for(auto& pe : pointelements)\n      pe.pnum = op2np[pe.pnum];\n\n    for (int i = 1; i <= openelements.Size(); i++)\n      {\n        Element2d & el = openelements.Elem(i);\n        for (int j = 0; j < el.GetNP(); j++)\n          el[j] = op2np[el[j]];\n      }  \n\n\n    for (int i = 0; i < lockedpoints.Size(); i++)\n      lockedpoints[i] = op2np[lockedpoints[i]];\n\n    GetIdentifications().MapPoints(op2np);\n    /*\n    for (int i = 0; i < facedecoding.Size(); i++)\n      facedecoding[i].firstelement = -1;\n    for (int i = surfelements.Size()-1; i >= 0; i--)\n      {\n        int ind = surfelements[i].GetIndex();\n        surfelements[i].next = facedecoding[ind-1].firstelement;\n        facedecoding[ind-1].firstelement = i;\n      }\n    */\n    RebuildSurfaceElementLists ();\n    CalcSurfacesOfNode();\n\n\n    //  FindOpenElements();\n    timestamp = NextTimeStamp();\n    lock.UnLock();\n  }\n\n  void Mesh :: OrderElements()\n  {\n    for (auto & el : surfelements)\n      {\n        if (el.GetType() == TRIG)\n          while (el[0] > el[1] || el[0] > el[2])\n            { // rotate element\n              auto hp = el[0];\n              el[0] = el[1];\n              el[1] = el[2];\n              el[2] = hp;\n              auto hgi = el.GeomInfoPi(1);\n              el.GeomInfoPi(1) = el.GeomInfoPi(2);\n              el.GeomInfoPi(2) = el.GeomInfoPi(3);\n              el.GeomInfoPi(3) = hgi;\n            }\n      }\n\n    for (auto & el : volelements)\n      if (el.GetType() == TET)\n        {\n          // lowest index first ...\n          int mini = 0;\n          for (int i = 1; i < 4; i++)\n            if (el[i] < el[mini]) mini = i;\n          if (mini != 0)\n            { // swap 0 with mini, and the other two ...\n              int i3 = -1, i4 = -1;\n              for (int i = 1; i < 4; i++)\n                if (i != mini)\n                  {\n                    i4 = i3;\n                    i3 = i;\n                  }\n              swap (el[0], el[mini]);\n              swap (el[i3], el[i4]);\n            }\n          \n          while (el[1] > el[2] || el[1] > el[3])\n            { // rotate element to move second index to second position\n              auto hp = el[1];\n              el[1] = el[2];\n              el[2] = el[3];\n              el[3] = hp;\n            }\n        }\n  }\n\n  int Mesh :: CheckConsistentBoundary () const\n  {\n    int nf = GetNOpenElements();\n    INDEX_2_HASHTABLE<int> edges(nf+2);\n    INDEX_2 i2, i2s, edge;\n    int err = 0;\n\n    for (int i = 1; i <= nf; i++)\n      {\n        const Element2d & sel = OpenElement(i);\n\n        for (int j = 1; j <= sel.GetNP(); j++)\n          {\n            i2.I1() = sel.PNumMod(j);\n            i2.I2() = sel.PNumMod(j+1);\n\n            int sign = (i2.I2() > i2.I1()) ? 1 : -1;\n            i2.Sort();\n            if (!edges.Used (i2))\n              edges.Set (i2, 0);\n            edges.Set (i2, edges.Get(i2) + sign);\n          }\n      }\n\n    for (int i = 1; i <= edges.GetNBags(); i++)\n      for (int j = 1; j <= edges.GetBagSize(i); j++)\n        {\n          int cnt = 0;\n          edges.GetData (i, j, i2, cnt);\n          if (cnt)\n            {\n              PrintError (\"Edge \", i2.I1() , \" - \", i2.I2(), \" multiple times in surface mesh\");\n\n              (*testout) << \"Edge \" << i2 << \" multiple times in surface mesh\" << endl;\n              i2s = i2;\n              i2s.Sort();\n              for (int k = 1; k <= nf; k++)\n                {\n                  const Element2d & sel = OpenElement(k);\n                  for (int l = 1; l <= sel.GetNP(); l++)\n                    {\n                      edge.I1() = sel.PNumMod(l);\n                      edge.I2() = sel.PNumMod(l+1);\n                      edge.Sort();\n\n                      if (edge == i2s) \n                        (*testout) << \"edge of element \" << sel << endl;\n                    }\n                }\n\n\n              err = 2;\n            }\n        }\n\n    return err;\n  }\n\n\n\n  int Mesh :: CheckOverlappingBoundary () \n  {\n    static Timer t(\"Mesh::CheckOverlappingBoundary\"); RegionTimer reg(t);\n    \n    Point3d pmin, pmax;\n    GetBox (pmin, pmax);\n    BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);\n    // NgArray<SurfaceElementIndex> inters;\n\n    bool overlap = 0;\n    bool incons_layers = 0;\n\n    for (Element2d & el : SurfaceElements())\n      el.badel = false;\n\n    for (SurfaceElementIndex sei : Range(SurfaceElements()))\n      {\n        const Element2d & tri = SurfaceElement(sei);\n\n        Box<3> box(Box<3>::EMPTY_BOX);\n        for (PointIndex pi : tri.PNums())\n          box.Add (Point(pi));\n\n        box.Increase(1e-3*box.Diam());\n        setree.Insert (box, sei);\n      }\n\n    std::mutex m;\n    // for (SurfaceElementIndex sei : Range(SurfaceElements()))\n    ParallelForRange\n      (Range(SurfaceElements()), [&] (auto myrange)\n       {\n         for (SurfaceElementIndex sei : myrange)\n           {\n             const Element2d & tri = SurfaceElement(sei);\n             \n             Box<3> box(Box<3>::EMPTY_BOX);\n             for (PointIndex pi : tri.PNums())\n               box.Add (Point(pi));\n             \n             setree.GetFirstIntersecting\n               (box.PMin(), box.PMax(),\n                [&] (SurfaceElementIndex sej) \n                {\n                  const Element2d & tri2 = SurfaceElement(sej);\t  \n                  \n                  if ( (*this)[tri[0]].GetLayer() != (*this)[tri2[0]].GetLayer())\n                    return false;\n                  \n                  if ( (*this)[tri[0]].GetLayer() != (*this)[tri[1]].GetLayer() ||\n                       (*this)[tri[0]].GetLayer() != (*this)[tri[2]].GetLayer())\n                    {\n                      incons_layers = 1;\n                      // cout << \"inconsistent layers in triangle\" << endl;\n                    }\n                  \n                  const netgen::Point<3> *trip1[3], *trip2[3];\t  \n                  for (int k = 0; k < 3; k++)\n                    {\n                      trip1[k] = &Point (tri[k]);\n                      trip2[k] = &Point (tri2[k]);\n                    }\n                  \n                  if (IntersectTriangleTriangle (&trip1[0], &trip2[0]))\n                    {\n                      overlap = 1;\n                      lock_guard<std::mutex> guard(m);\n                      if(!incons_layers)\n                        {\n                          PrintWarning (\"Intersecting elements \"\n                                        ,int(sei), \" and \", int(sej));\n                      \n                          (*testout) << \"Intersecting: \" << endl;\n                          (*testout) << \"openelement \" << sei << \" with open element \" << sej << endl;\n                      \n                          cout << \"el1 = \" << tri << endl;\n                          cout << \"el2 = \" << tri2 << endl;\n                          cout << \"layer1 = \" <<  (*this)[tri[0]].GetLayer() << endl;\n                          cout << \"layer2 = \" <<  (*this)[tri2[0]].GetLayer() << endl;\n                        }\n                      \n                      for (int k = 1; k <= 3; k++)\n                        (*testout) << tri.PNum(k) << \"  \";\n                      (*testout) << endl;\n                      for (int k = 1; k <= 3; k++)\n                        (*testout) << tri2.PNum(k) << \"  \";\n                      (*testout) << endl;\n                      \n                      for (int k = 0; k <= 2; k++)\n                        (*testout) << *trip1[k] << \"   \";\n                      (*testout) << endl;\n                      for (int k = 0; k <= 2; k++)\n                        (*testout) << *trip2[k] << \"   \";\n                      (*testout) << endl;\n\n                      (*testout) << \"Face1 = \" << GetFaceDescriptor(tri.GetIndex()) << endl;\n                      (*testout) << \"Face1 = \" << GetFaceDescriptor(tri2.GetIndex()) << endl;\n                      \n                      SurfaceElement(sei).badel = 1;\n                      SurfaceElement(sej).badel = 1;\n                    }\n                  return false;\n                });\n           }\n       });\n    // bug 'fix'\n    if (incons_layers) overlap = 0;\n\n    return overlap;\n  }\n\n\n  int Mesh :: CheckVolumeMesh () const\n  {\n    PrintMessage (3, \"Checking volume mesh\");\n\n    int ne = GetNE();\n    DenseMatrix dtrans(3,3);\n    int i, j;\n\n    PrintMessage (5, \"elements: \", ne);\n    for (i = 1; i <= ne; i++)\n      {\n        Element & el = (Element&) VolumeElement(i);\n        el.Flags().badel = 0;\n        int nip = el.GetNIP();\n        for (j = 1; j <= nip; j++)\n          {\n            el.GetTransformation (j, Points(), dtrans);\n            double det = dtrans.Det();\n            if (det > 0)\n              {\n                PrintError (\"Element \", i , \" has wrong orientation\");\n                el.Flags().badel = 1;\n              }\n          }\n      }\n\n    return 0;\n  }\n\n  // Search for surface trigs with same vertices ( may happen for instance with close surfaces in stl geometies )\n  int Mesh :: FindIllegalTrigs ()\n  {\n    // Temporary table to store the vertex numbers of all triangles\n    INDEX_3_CLOSED_HASHTABLE<int> temp_tab(3*GetNSE() + 1);\n    size_t cnt = 0;\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        const Element2d & sel = surfelements[sei];\n        if (sel.IsDeleted()) continue;\n\n        INDEX_3 i3(sel[0], sel[1], sel[2]);\n        i3.Sort();\n        if(temp_tab.Used(i3))\n          {\n            temp_tab.Set (i3, -1);\n            cnt++;\n          }\n        else\n          {\n            temp_tab.Set (i3, sei);\n          }\n      }\n\n    illegal_trigs = make_unique<INDEX_3_CLOSED_HASHTABLE<int>> (2*cnt+1);\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      {\n        const Element2d & sel = surfelements[sei];\n        if (sel.IsDeleted()) continue;\n\n        INDEX_3 i3(sel[0], sel[1], sel[2]);\n        i3.Sort();\n        if(temp_tab.Get(i3)==-1)\n            illegal_trigs -> Set (i3, 1);\n      }\n    return cnt;\n  }\n\n  bool Mesh :: LegalTrig (const Element2d & el) const\n  {\n      if(illegal_trigs)\n      {\n          INDEX_3 i3 (el[0], el[1], el[2]);\n          i3.Sort();\n          if(illegal_trigs->Used(i3))\n              return false;\n      }\n\n    return 1;\n    // if ( /* hp */ 1)  // needed for old, simple hp-refinement\n    //   { \n    //     // trigs with 2 or more segments are illegal\n    //     int i;\n    //     int nseg = 0;\n\n    //     if (!segmentht)\n    //       {\n    //         cerr << \"no segmentht allocated\" << endl;\n    //         return 0;\n    //       }\n\n    //     //      Point3d cp(0.5, 0.5, 0.5);\n    //     for (i = 1; i <= 3; i++)\n    //       {\n    //         INDEX_2 i2(el.PNumMod (i), el.PNumMod (i+1));\n    //         i2.Sort();\n    //         if (segmentht -> Used (i2))\n    //           nseg++;\n    //       }\n    //     if (nseg >= 2) \n    //       return 0;\n    //   }\n    // return 1;\n  }\n\n  double Mesh :: CalcTotalBad (const MeshingParameters & mp )\n  {\n    static Timer t(\"CalcTotalBad\"); RegionTimer reg(t);\n    static constexpr int n_classes = 20;\n\n    double sum = 0;\n\n    tets_in_qualclass.SetSize(n_classes);\n    tets_in_qualclass = 0;\n\n    ParallelForRange( IntRange(volelements.Size()), [&] (auto myrange)\n       {\n         double local_sum = 0.0;\n         double teterrpow = mp.opterrpow;\n\n         // std::array<int,n_classes> classes_local{};\n         size_t n_classes = tets_in_qualclass.Size();\n         Array<int> classes_local(n_classes);\n         for (int i = 0; i < n_classes; i++)\n           classes_local[i] = 0;\n\n         for (auto i : myrange)\n           {\n             double elbad = pow (max2(CalcBad (points, volelements[i], 0, mp),1e-10), 1/teterrpow);\n\n             int qualclass = int (n_classes / elbad + 1);\n             if (qualclass < 1) qualclass = 1;\n             if (qualclass > n_classes) qualclass = n_classes;\n             classes_local[qualclass-1]++;\n\n             local_sum += elbad;\n           }\n\n         AtomicAdd(sum, local_sum);\n\n         for (auto i : Range(n_classes))\n             AsAtomic(tets_in_qualclass[i]) += classes_local[i];\n    });\n\n    return sum;\n  }\n\n\n\n\n  ///\n  bool Mesh :: LegalTet2 (Element & el) const\n  {\n    // static int timer1 = NgProfiler::CreateTimer (\"Legaltet2\");\n\n    // Test, whether 4 points have a common surface plus\n    // at least 4 edges at the boundary\n\n    if(!boundaryedges)\n      const_cast<Mesh *>(this)->BuildBoundaryEdges();\n\n\n    // non-tets are always legal\n    if (el.GetType() != TET)\n      {\n        el.SetLegal (1);\n        return 1;\n      }\n\n    POINTTYPE pointtype[4];\n    for(int i = 0; i < 4; i++)\n      pointtype[i] = (*this)[el[i]].Type();\n\n\n\n    // element has at least 2 inner points ---> legal\n    int cnti = 0;\n    for (int j = 0; j < 4; j++)\n      if ( pointtype[j] == INNERPOINT)\n        {\n          cnti++;\n          if (cnti >= 2)\n            {\n              el.SetLegal (1);\n              return 1;\n            }\n        }\n\n\n\n    // which faces are boundary faces ?\n    int bface[4];\n    for (int i = 0; i < 4; i++)\n      {\n        bface[i] = surfelementht->Used (INDEX_3::Sort(el[gftetfacesa[i][0]],\n                                                      el[gftetfacesa[i][1]],\n                                                      el[gftetfacesa[i][2]]));\n      }\n\n    int bedge[4][4];\n    int segedge[4][4];\n    static const int pi3map[4][4] = { { -1,  2,  1,  1 },\n                                      {  2, -1,  0,  0 },\n                                      {  1,  0, -1,  0 },\n                                      {  1,  0,  0, -1 } };\n\n    static const int pi4map[4][4] = { { -1,  3,  3,  2 },\n                                      {  3, -1,  3,  2 },\n                                      {  3,  3, -1,  1 },\n                                      {  2,  2,  1, -1 } };\n\n\n    for (int i = 0; i < 4; i++)\n      for (int j = 0; j < i; j++)\n        {\n          bool sege = false, be = false;\n\n          int pos = boundaryedges -> Position0(INDEX_2::Sort(el[i], el[j]));\n          if (pos != -1)\n            {\n              be = true;\n              if (boundaryedges -> GetData0(pos) == 2)\n                sege = true;\n            }\n\n          segedge[j][i] = segedge[i][j] = sege;\n          bedge[j][i] = bedge[i][j] = be;\n        }\n\n    // two boundary faces and no edge is illegal\n    for (int i = 0; i < 3; i++)\n      for (int j = i+1; j < 4; j++)\n        {\n          if (bface[i] && bface[j])\n            if (!segedge[pi3map[i][j]][pi4map[i][j]])\n              {\n                // 2 boundary faces without edge in between\n                el.SetLegal (0);\n                return 0;\n              }\n        }\n\n    // three boundary edges meeting in a Surface point\n    for (int i = 0; i < 4; i++)\n      {\n        if ( pointtype[i] == SURFACEPOINT)\n          {\n            bool alledges = 1;\n            for (int j = 0; j < 4; j++)\n              if (j != i && !bedge[i][j])\n                {\n                  alledges = 0;\n                  break;\n                }\n            if (alledges)\n              {\n                // cout << \"tet illegal due to unmarked node\" << endl;\n                el.SetLegal (0);\n                return 0;\n              }\n          }\n      }\n\n\n\n    for (int fnr = 0; fnr < 4; fnr++)\n      if (!bface[fnr])\n        for (int i = 0; i < 4; i++)\n          if (i != fnr)\n            {\n              int pi1 = pi3map[i][fnr];\n              int pi2 = pi4map[i][fnr];\n\n              if ( pointtype[i] == SURFACEPOINT)\n                {\n                  // two connected edges on surface, but no face\n                  if (bedge[i][pi1] && bedge[i][pi2])\n                    {\n                      el.SetLegal (0);\n                      return 0;\n                    }\n                }\n\n              if ( pointtype[i] == EDGEPOINT)\n                {\n                  // connected surface edge and edge edge, but no face\n                  if ( (bedge[i][pi1] && segedge[i][pi2]) ||\n                       (bedge[i][pi2] && segedge[i][pi1]) )\n                    {\n                      el.SetLegal (0);\n                      return 0;\n                    }\n                }\n\n            }\n\n\n    el.SetLegal (1);\n    return 1;\n\n  }\n\n\n\n  int Mesh :: GetNDomains() const\n  {\n    int ndom = 0;\n\n    for (int k = 0; k < facedecoding.Size(); k++)\n      {\n        if (facedecoding[k].DomainIn() > ndom)\n          ndom = facedecoding[k].DomainIn();\n        if (facedecoding[k].DomainOut() > ndom)\n          ndom = facedecoding[k].DomainOut();\n      }\n\n    return ndom;\n  }\n\n  void Mesh :: SetDimension (int dim)\n  {\n    if (dimension == 3 && dim == 2)\n      {\n        // change mesh-dim from 3 to 2 (currently needed for OCC)\n        for (auto str : materials)\n          delete str;\n        materials.SetSize(0);\n        for (auto str : bcnames)\n          materials.Append(str);\n        bcnames.SetSize(0);\n        for (auto str : cd2names)\n          bcnames.Append(str);\n        cd2names.SetSize(0);\n        for (auto str : cd3names)\n          cd2names.Append(str);\n        cd3names.SetSize(0);\n\n        for (auto & seg : LineSegments())\n          seg.si = seg.edgenr;\n      }\n    if (dimension == 3 && dim == 1)\n      {\n        for(auto str : materials)\n          delete str;\n        materials.SetSize(0);\n        for(auto str : bcnames)\n          delete str;\n        bcnames.SetSize(0);\n        for(auto str: cd2names)\n          materials.Append(str);\n        cd2names.SetSize(0);\n        for(auto str : cd3names)\n          bcnames.Append(str);\n        cd3names.SetSize(0);\n      }\n    dimension = dim;\n  }\n\n  void Mesh :: SurfaceMeshOrientation ()\n  {\n    // int i, j;\n    int nse = GetNSE();\n\n    BitArray used(nse+1);\n    used.Clear();\n    INDEX_2_HASHTABLE<int> edges(nse+1);\n\n    bool haschanged = 0;\n\n\n    const Element2d & tri = SurfaceElement(1);\n    for (int j = 1; j <= 3; j++)\n      {\n        INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1));\n        edges.Set (i2, 1);\n      }\n    used.SetBit(1);\n\n    bool unused;\n    do\n      {\n        bool changed;\n        do\n          {\n            changed = 0;\n            for (int i = 1; i <= nse; i++)\n              if (!used.Test(i))\n                {\n                  Element2d & el = surfelements[i-1];\n                  int found = 0, foundrev = 0;\n                  for (int j = 1; j <= 3; j++)\n                    {\n                      INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1));\n                      if (edges.Used(i2))\n                        foundrev = 1;\n                      swap (i2.I1(), i2.I2());\n                      if (edges.Used(i2))\n                        found = 1;\n                    }\n\n                  if (found || foundrev)\n                    {\n                      if (foundrev)\n                        swap (el.PNum(2), el.PNum(3));\n\n                      changed = 1;\n                      for (int j = 1; j <= 3; j++)\n                        {\n                          INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1));\n                          edges.Set (i2, 1);\n                        }\n                      used.SetBit (i);\n                    }\n                }\n            if (changed)\n              haschanged = 1;\n          }\n        while (changed);\n\n\n        unused = 0;\n        for (int i = 1; i <= nse; i++)\n          if (!used.Test(i))\n            {\n              unused = 1;\n              const Element2d & tri = SurfaceElement(i);\n              for (int j = 1; j <= 3; j++)\n                {\n                  INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1));\n                  edges.Set (i2, 1);\n                }\n              used.SetBit(i);\n              break;\n            }\n      }\n    while (unused);\n\n    if (haschanged)\n      timestamp = NextTimeStamp();\n  }\n\n\n  void Mesh :: Split2Tets()\n  {\n    PrintMessage (1, \"Split To Tets\");\n    bool has_prisms = 0;\n\n    int oldne = GetNE(); \n    for (int i = 1; i <= oldne; i++)\n      {\n        Element el = VolumeElement(i);\n\n        if (el.GetType() == PRISM)\n          {\n            // prism, to 3 tets\n\n            // make minimal node to node 1\n            int minpi=0;\n            PointIndex minpnum = IndexBASE<PointIndex>()+GetNP();\n\n            for (int j = 1; j <= 6; j++)\n              {\n                if (el.PNum(j) < minpnum)\n                  {\n                    minpnum = el.PNum(j);\n                    minpi = j;\n                  }\n              }\n\n            if (minpi >= 4)\n              {\n                for (int j = 1; j <= 3; j++)\n                  swap (el.PNum(j), el.PNum(j+3));\n                minpi -= 3;\n              }\n\n            while (minpi > 1)\n              {\n                for (int j = 0; j <= 3; j+= 3)\n                  {\n                    PointIndex hi = el.PNum(1+j);\n                    el.PNum(1+j) = el.PNum(2+j);\n                    el.PNum(2+j) = el.PNum(3+j);\n                    el.PNum(3+j) = hi;\n                  }\n                minpi--;\n              }\n\n            /*\n              version 1: edge from pi2 to pi6,\n              version 2: edge from pi3 to pi5,\n            */\n\n            static const int ntets[2][12] =\n              { { 1, 4, 5, 6, 1, 2, 3, 6, 1, 2, 5, 6 },\n                { 1, 4, 5, 6, 1, 2, 3, 5, 3, 1, 5, 6 } };\n\n            const int * min2pi;\n\n            if (min2 (el.PNum(2), el.PNum(6)) <\n                min2 (el.PNum(3), el.PNum(5)))\n              {\n                min2pi = &ntets[0][0];\n                // (*testout) << \"version 1 \";\n              }\n            else\n              {\n                min2pi = &ntets[1][0];\n                // (*testout) << \"version 2 \";\n              }\n\n\n            int firsttet = 1;\n            for (int j = 1; j <= 3; j++)\n              {\n                Element nel(TET);\n                for (int k = 1; k <= 4; k++)\n                  nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]);\n                nel.SetIndex (el.GetIndex());\n\n                int legal = 1;\n                for (int k = 1; k <= 3; k++)\n                  for (int l = k+1; l <= 4; l++)\n                    if (nel.PNum(k) == nel.PNum(l))\n                      legal = 0;\n\n                // (*testout) << nel << \" \";\n                if (legal)\n                  {\n                    if (firsttet)\n                      {\n                        VolumeElement(i) = nel;\n                        firsttet = 0;\n                      }\n                    else\n                      {\n                        AddVolumeElement(nel);\n                      }\n                  }\n              }\n            if (firsttet) cout << \"no legal\";\n            (*testout) << endl;\n          }\n\n\n\n        else if (el.GetType() == HEX)\n          {\n            // hex to A) 2 prisms or B) to 5 tets\n\n            // make minimal node to node 1\n            int minpi=0;\n            PointIndex minpnum = GetNP() + IndexBASE<PointIndex>();\n\n            for (int j = 1; j <= 8; j++)\n              {\n                if (el.PNum(j) < minpnum)\n                  {\n                    minpnum = el.PNum(j);\n                    minpi = j;\n                  }\n              }\n\n            if (minpi >= 5)\n              {\n                for (int j = 1; j <= 4; j++)\n                  swap (el.PNum(j), el.PNum(j+4));\n                minpi -= 4;\n              }\n\n            while (minpi > 1)\n              {\n                for (int j = 0; j <= 4; j+= 4)\n                  {\n                    PointIndex hi = el.PNum(1+j);\n                    el.PNum(1+j) = el.PNum(2+j);\n                    el.PNum(2+j) = el.PNum(3+j);\n                    el.PNum(3+j) = el.PNum(4+j);\n                    el.PNum(4+j) = hi;\n                  }\n                minpi--;\n              }\n\n\n\n            static const int to_prisms[3][12] =\n              { { 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 6, 7 },\n                { 0, 1, 5, 3, 2, 6, 0, 5, 4, 3, 6, 7 },\n                { 0, 7, 4, 1, 6, 5, 0, 3, 7, 1, 2, 6 },\n              };\n\n            const int * min2pi = 0;\n            if (min2 (el[4], el[6]) < min2 (el[5], el[7]))\n              min2pi = &to_prisms[0][0];\n            else if (min2 (el[3], el[6]) < min2 (el[2], el[7]))\n              min2pi = &to_prisms[1][0];\n            else if (min2 (el[1], el[6]) < min2 (el[2], el[5]))\n              min2pi = &to_prisms[2][0];\n\n            if (min2pi)\n              {\n                has_prisms = 1;\n                for (int j = 0; j < 2; j++)\n                  {\n                    Element nel(PRISM);\n                    for (int k = 0; k < 6; k++)\n                      nel[k] = el[min2pi[6*j + k]];\n                    nel.SetIndex (el.GetIndex());\n\n                    if (j == 0)\n                      VolumeElement(i) = nel;\n                    else\n                      AddVolumeElement(nel);\n                  }\n              }\n            else\n              {\n                // split to 5 tets\n\n                static const int to_tets[20] =\n                  {\n                    1, 2, 0, 5,\n                    3, 0, 2, 7,\n                    4, 5, 7, 0,\n                    6, 7, 5, 2,\n                    0, 2, 7, 5\n                  };\n\n                for (int j = 0; j < 5; j++)\n                  {\n                    Element nel(TET);\n                    for (int k = 0; k < 4; k++)\n                      nel[k] = el[to_tets[4*j + k]];\n                    nel.SetIndex (el.GetIndex());\n\n                    if (j == 0)\n                      VolumeElement(i) = nel;\n                    else\n                      AddVolumeElement(nel);\n                  }\n\n              }\n          }\n\n\n\n\n\n        else if (el.GetType() == PYRAMID)\n          {\n            // pyramid, to 2 tets\n\n            // cout << \"pyramid: \" << el << endl;\n\n            static const int ntets[2][8] =\n              { { 1, 2, 3, 5, 1, 3, 4, 5 },\n                { 1, 2, 4, 5, 4, 2, 3, 5 }};\n\n            const int * min2pi;\n\n            if (min2 (el[0], el[2]) < min2 (el[1], el[3]))\n              min2pi = &ntets[0][0];\n            else\n              min2pi = &ntets[1][0];\n\n            bool firsttet = 1;\n            for (int j = 0; j < 2; j++)\n              {\n                Element nel(TET);\n                for (int k = 0; k < 4; k++)\n                  nel[k] = el[min2pi[4*j + k]-1];\n                nel.SetIndex (el.GetIndex());\n\n                // cout << \"pyramid-tet: \" << nel << endl;\n\n                bool legal = 1;\n                for (int k = 0; k < 3; k++)\n                  for (int l = k+1; l < 4; l++)\n                    if (nel[k] == nel[l])\n                      legal = 0;\n\n                if (legal)\n                  {\n                    (*testout) << nel << \" \";\n                    if (firsttet)\n                      VolumeElement(i) = nel;\n                    else\n                      AddVolumeElement(nel);\n\n                    firsttet = 0;\n                  }\n              }\n            if (firsttet) cout << \"no legal\";\n            (*testout) << endl;\n          }\n      }\n\n\n    int oldnse = GetNSE(); \n    for (int i = 1; i <= oldnse; i++)\n      {\n        Element2d el = SurfaceElement(i);\n        if (el.GetNP() == 4)\n          {\n            (*testout) << \"split el: \" << el << \" to \";\n\n            static const int ntris[2][6] =\n              { { 1, 2, 3, 1, 3, 4 },\n                { 1, 2, 4, 4, 2, 3 }};\n\n            const int * min2pi;\n\n            if (min2 (el.PNum(1), el.PNum(3)) <\n                min2 (el.PNum(2), el.PNum(4)))\n              min2pi = &ntris[0][0];\n            else\n              min2pi = &ntris[1][0];\n\n            for (int j = 0; j <6; j++)\n              (*testout) << min2pi[j] << \" \";\n\n\n            int firsttri = 1;\n            for (int j = 1; j <= 2; j++)\n              {\n                Element2d nel(3);\n                for (int k = 1; k <= 3; k++)\n                  nel.PNum(k) = el.PNum(min2pi[3 * j + k - 4]);\n                nel.SetIndex (el.GetIndex());\n\n                int legal = 1;\n                for (int k = 1; k <= 2; k++)\n                  for (int l = k+1; l <= 3; l++)\n                    if (nel.PNum(k) == nel.PNum(l))\n                      legal = 0;\n\n                if (legal)\n                  {\n                    (*testout) << nel << \" \";\n                    if (firsttri)\n                      {\n                        SurfaceElement(i) = nel;\n                        firsttri = 0;\n                      }\n                    else\n                      {\n                        AddSurfaceElement(nel);\n                      }\n                  }\n              }\n            (*testout) << endl;\n\n          }\n      }\n\n\n    if (has_prisms)\n\n      Split2Tets();\n\n    else\n      {\n        for (int i = 1; i <= GetNE(); i++)\n          {\n            Element & el = VolumeElement(i);\n            const Point3d & p1 = Point (el.PNum(1));\n            const Point3d & p2 = Point (el.PNum(2));\n            const Point3d & p3 = Point (el.PNum(3));\n            const Point3d & p4 = Point (el.PNum(4));\n\n            double vol = (Vec3d (p1, p2) * \n                          Cross (Vec3d (p1, p3), Vec3d(p1, p4)));\n            if (vol > 0)\n              swap (el.PNum(3), el.PNum(4));\n          }\n\n\n\n        UpdateTopology();\n        timestamp = NextTimeStamp();\n      }\n\n    RebuildSurfaceElementLists();\n  }\n\n  void Mesh :: BuildElementSearchTree (int dim)\n  {\n    if(dim < 2)\n      return;\n    if (elementsearchtreets[dim] == GetTimeStamp())\n      return;\n\n    {\n      std::lock_guard<std::mutex> guard(buildsearchtree_mutex);\n      // check again to see if some other thread built while waiting for lock\n      if (elementsearchtreets[dim] == GetTimeStamp()) return;\n\n      PrintMessage (4, \"Rebuild element searchtree dim \" + ToString(dim));\n          \n\n      Point3d pmin, pmax;\n      GetBox(pmin, pmax);\n      Box<3> box(pmin, pmax);\n      box.Scale(1.2);\n      if (dim == 3)\n        elementsearchtree_vol = make_unique<BoxTree<3, ElementIndex>>(box);\n      else\n        elementsearchtree_surf = make_unique<BoxTree<3, SurfaceElementIndex>>(box);\n\n      if (dim == 3)\n        {\n          for(auto ei : volelements.Range())\n            {\n              const auto& el = volelements[ei];\n              Box<3> box (Box<3>::EMPTY_BOX);\n              for (auto pi : el.PNums())\n                box.Add (points[pi]);\n\n              if(el.IsCurved() && curvedelems->IsElementCurved(ei))\n                {\n                  // add edge/face midpoints to box\n                  auto eltype = el.GetType();\n                  const auto verts = topology.GetVertices(eltype);\n\n                  const auto edges = FlatArray<const ELEMENT_EDGE>(topology.GetNEdges(eltype), topology.GetEdges0(eltype));\n                  for (const auto & edge: edges) {\n                    netgen::Point<3> lam = netgen::Point<3>(0.5* (verts[edge[0]] + verts[edge[1]]));\n                    auto p = netgen::Point<3>(0.0);\n                    curvedelems->CalcElementTransformation(lam,ei,p);\n                    box.Add(p);\n                  }\n\n                  const auto faces = FlatArray<const ELEMENT_FACE>(topology.GetNFaces(eltype), topology.GetFaces0(eltype));\n                  for (const auto & face: faces) {\n                    netgen::Vec<3> lam = netgen::Vec<3>(verts[face[0]] + verts[face[1]] + verts[face[2]]);\n                    if(face[3] != -1) {\n                      lam += netgen::Vec<3>(verts[face[3]]);\n                      lam *= 0.25;\n                    }\n                    else\n                      lam *= 1.0/3;\n                    auto p = netgen::Point<3>(0.0);\n                    curvedelems->CalcElementTransformation(netgen::Point<3>(lam),ei,p);\n                    box.Add(p);\n                  }\n                }\n              box.Scale(1.2);\n              elementsearchtree_vol -> Insert (box, ei);\n            }\n        }\n      else if (dim == 2)\n        {\n          for (auto ei : Range(surfelements))\n            {\n              const auto& el = surfelements[ei];\n              Box<3> box (Box<3>::EMPTY_BOX);\n              for (auto pi : el.PNums())\n                box.Add (points[pi]);\n\n              if(el.IsCurved() && curvedelems->IsSurfaceElementCurved(ei))\n                {\n                  netgen::Point<2>  lami [4] = {netgen::Point<2>(0.5,0), netgen::Point<2>(0,0.5), netgen::Point<2>(0.5,0.5), netgen::Point<2>(1./3,1./3)};\n                  for (auto lam : lami)\n                    {\n                      netgen::Point<3> x;\n                      Mat<3,2> Jac;\n\n                      curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);\n                      box.Add (x);\n                    }\n                  box.Scale(1.2);\n                }\n              elementsearchtree_surf -> Insert (box, ei);\n            }\n        }\n      elementsearchtreets[dim] = GetTimeStamp();\n    }\n  }\n\n  \n  int SolveLinearSystemLS (const Vec3d & col1,\n                           const Vec3d & col2,\n                           const Vec3d & rhs,\n                           Vec2d & sol)\n  {\n    double a11 = col1 * col1;\n    double a12 = col1 * col2;\n    double a22 = col2 * col2;\n    \n    double det = a11 * a22 - a12 * a12;\n    \n    if (det*det <= 1e-24 * a11 * a22)\n      {\n        sol = Vec2d (0, 0);\n        return 1;\n      }\n    \n    Vec2d aTrhs;\n    aTrhs.X() = col1*rhs;\n    aTrhs.Y() = col2*rhs;\n\n    sol.X() = ( a22 * aTrhs.X() - a12 * aTrhs.Y()) / det;\n    sol.Y() = (-a12 * aTrhs.X() + a11 * aTrhs.Y()) / det;\n    return 0;\n  }\n\n  bool ValidBarCoord(double lami[3], double eps=1e-12)\n  {\n    return (lami[0]<=1.+eps && lami[0]>=0.-eps && lami[1]<=1.+eps && lami[1]>=0.-eps && lami[2]<=1.+eps && lami[2]>=0.-eps );\n  }\n\n  bool Mesh :: PointContainedIn2DElement(const Point3d & p,\n                                         double lami[3],\n                                         SurfaceElementIndex ei,\n                                         bool consider3D) const\n  {\n    Vec3d col1, col2, col3;\n    Vec3d rhs, sol;\n    const double eps = 1e-6;\n\n    NgArray<Element2d> loctrigs;\n\n    \n    //SZ \n    if(surfelements[ei].GetType()==QUAD)\n      {\n        const Element2d & el = surfelements[ei];\n\n        const Point3d & p1 = Point(el.PNum(1)); \n        const Point3d & p2 = Point(el.PNum(2));\n        const Point3d & p3 = Point(el.PNum(3));\n        const Point3d & p4 = Point(el.PNum(4));\n\n        if (el.GetOrder() > 1 || el.GetHpElnr() != -1) {\n          netgen::Point<2> lam(0.5,0.5);\n          Vec<3> rhs;\n          Vec<2> deltalam;\n\n          netgen::Point<3> x;\n          Mat<3,2> Jac;\n          double delta = 1.;\n          const int maxits = 30;\n          int i = 0;\n          while(delta > 1e-16 && i < maxits)\n            {\n              curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);\n              rhs = p - x;\n              Jac.Solve(rhs,deltalam);\n              lam += deltalam;\n              delta = deltalam.Length2();\n              i++;\n            }\n          if(i == maxits)\n            return false;\n          lami[0] = lam[0];\n          lami[1] = lam[1];\n          if(lami[0] < -eps || lami[0] > 1+eps || lami[1] < -eps || lami[1] > 1+eps)\n            return false;\n          return true;\n        }\n\n        // Coefficients of Bilinear Mapping from Ref-Elem to global Elem\n        // X = a + b x + c y + d x y \n        Vec3d a = p1; \n        Vec3d b = p2 - a; \n        Vec3d c = p4 - a; \n        Vec3d d = p3 - a - b - c;\n\n        /*cout << \"p = \" << p << endl;\n        cout << \"p1 = \" << p1 << endl;\n        cout << \"p2 = \" << p2 << endl;\n        cout << \"p3 = \" << p3 << endl;\n        cout << \"p4 = \" << p4 << endl;\n\n        cout << \"a = \" << a << endl;\n        cout << \"b = \" << b << endl;\n        cout << \"c = \" << c << endl;\n        cout << \"d = \" << d << endl;*/\n\n\n        Vec3d pa = p-a;\n        double dxb = d.X()*b.Y()-d.Y()*b.X();\n        double dxc = d.X()*c.Y()-d.Y()*c.X();\n        double bxc = b.X()*c.Y()-b.Y()*c.X();\n        double bxpa = b.X()*pa.Y()-b.Y()*pa.X();\n        double cxpa = c.X()*pa.Y()-c.Y()*pa.X();\n        double dxpa = d.X()*pa.Y()-d.Y()*pa.X();\n\n        /*cout << \"dxb = \" << dxb << endl;\n        cout << \"dxc = \" << dxc << endl;\n        cout << \"bxc = \" << bxc << endl;\n        cout << \"bxpa = \" << bxpa << endl;\n        cout << \"cxpa = \" << cxpa << endl;\n        cout << \"dxpa = \" << dxpa << endl;*/\n\n        /*\n          P = a + b x + c y + d x y\n          1) P1 = a1 + b1 x + c1 y + d1 x y\n          2) P2 = a2 + b2 x + c2 y + d2 x y\n          \n          -> det(x,d) = det(a,d) + det(b,d) x + det(c,d) y\n            -> x = 1/det(b,d) *( det(P-a,d)-det(c,d) y )\n            -> y = 1/det(c,d) *( det(P-a,d)-det(b,d) x )\n          \n          -> x = (P1 - a1 - c1 y)/(b1 + d1 y)\n            -> det(c,d) y**2 + [det(d,P-a) + det(c,b)] y + det(b,P-a) = 0\n          ( same if we express x = (P2 - a2 - c2 y)/(b2 + d2 y) )\n\n          -> y = (P1 - a1 - b1 x)/(c1 + d1 x)\n            -> det(b,d) x**2 + [det(d,P-a) + det(b,c)] x + det(c,P-a) = 0\n          ( same if we express y = (P2 - a2 - b2 x)/(c2 + d2 x)\n         */\n\n        lami[2]=0.; \n        // double eps = 1.E-12;\n        double c1,c2,r;\n\n        //First check if point is \"exactly\" a vertex point\n        Vec3d d1 = p-p1;\n        Vec3d d2 = p-p2;\n        Vec3d d3 = p-p3;\n        Vec3d d4 = p-p4;\n\n        //cout << \" d1 = \" << d1 << \", d2 = \" << d2 << \", d3 = \" << d3 << \", d4 = \" << d4 << endl;\n        \n        if (d1.Length2() < sqr(eps)*d2.Length2() && d1.Length2() < sqr(eps)*d3.Length2() && d1.Length2() < sqr(eps)*d4.Length2())\n          {\n            lami[0] = lami[1] = 0.;\n            return true;\n          }\n        else if (d2.Length2() < sqr(eps)*d1.Length2() && d2.Length2() < sqr(eps)*d3.Length2() && d2.Length2() < sqr(eps)*d4.Length2())\n          {\n            lami[0] = 1.;\n            lami[1] = 0.;\n            return true;\n          }\n        else if (d3.Length2() < sqr(eps)*d1.Length2() && d3.Length2() < sqr(eps)*d2.Length2() && d3.Length2() < sqr(eps)*d4.Length2())\n          {\n            lami[0] = lami[1] = 1.;\n            return true;\n          }\n        else if (d4.Length2() < sqr(eps)*d1.Length2() && d4.Length2() < sqr(eps)*d2.Length2() && d4.Length2() < sqr(eps)*d3.Length2())\n          {\n            lami[0] = 0.;\n            lami[1] = 1.;\n            return true;\n          }//if d is nearly 0: solve resulting linear system\n        else if (d.Length2() < sqr(eps)*b.Length2() && d.Length2() < sqr(eps)*c.Length2())\n          {\n            Vec2d sol;\n            SolveLinearSystemLS (b, c, p-a, sol);\n            lami[0] = sol.X();\n            lami[1] = sol.Y();\n\t    return ValidBarCoord(lami, eps);\n          }// if dxc is nearly 0: solve resulting linear equation for y and compute x\n        else if (fabs(dxc) < sqr(eps))\n          {\n            lami[1] = -bxpa/(dxpa-bxc);\n            lami[0] = (dxpa-dxc*lami[1])/dxb;\n            return ValidBarCoord(lami, eps);\n          }// if dxb is nearly 0: solve resulting linear equation for x and compute y\n        else if (fabs(dxb) < sqr(eps))\n          {\n            lami[0] = -cxpa/(dxpa+bxc);\n            lami[1] = (dxpa-dxb*lami[0])/dxc;\n            return ValidBarCoord(lami, eps);\n          }//if dxb >= dxc: solve quadratic equation in y and compute x\n        else if (fabs(dxb) >= fabs(dxc))\n          {\n            c1 = (bxc-dxpa)/dxc;\n            c2 = -bxpa/dxc;\n            r = c1*c1/4.0-c2;\n\n            //quadratic equation has only 1 (unstable) solution\n            if (fabs(r) < eps) //not eps^2!\n              {\n                lami[1] = -c1/2;\n                lami[0] = (dxpa-dxc*lami[1])/dxb;\n                return ValidBarCoord(lami, eps);\n              }\n            if (r < 0) return false;\n\n            lami[1] = -c1/2+sqrt(r);\n            lami[0] = (dxpa-dxc*lami[1])/dxb;\n\n            if (ValidBarCoord(lami, eps))\n                return true;\n            else\n              {\n                lami[1] = -c1/2-sqrt(r);\n                lami[0] = (dxpa-dxc*lami[1])/dxb;\n                return ValidBarCoord(lami, eps);\n              }\n          }//if dxc > dxb: solve quadratic equation in x and compute y\n        else\n          {\n            c1 = (-bxc-dxpa)/dxb;\n            c2 = -cxpa/dxb;\n            r = c1*c1/4.0-c2;\n\n            //quadratic equation has only 1 (unstable) solution\n            if (fabs(r) < eps) //not eps^2!\n              {\n                lami[0] = -c1/2;\n                lami[1] = (dxpa-dxb*lami[0])/dxc;\n                return ValidBarCoord(lami, eps);\n              }\n            if (r < 0) return false;\n\n            lami[0] = -c1/2+sqrt(r);\n            lami[1] = (dxpa-dxb*lami[0])/dxc;\n\n            if (ValidBarCoord(lami, eps))\n                return true;\n            else\n              {\n                lami[0] = -c1/2-sqrt(r);\n                lami[1] = (dxpa-dxb*lami[0])/dxc;\n                return ValidBarCoord(lami, eps);\n              }\n          }\n        \n        /*\n        double dxa = d.X()*a.Y()-d.Y()*a.X(); \n        double dxp = d.X()*p.Y()-d.Y()*p.X();\n\t\n\t\n        double c0,c1,c2; // ,rt; \n        \n\n\tVec3d dp13 = p3-p1;\n\tVec3d dp24 = p4-p2;\n\tdouble d1 = dp13.Length2();\n\tdouble d2 = dp24.Length2();\n\n\t// if(fabs(d.X()) <= eps && fabs(d.Y())<= eps)\n\t//if (d.Length2() < sqr(eps))\n        if (d.Length2() < sqr(eps)*d1 && d.Length2() < sqr(eps)*d2)\n          {\n\t    //Solve Linear System\n\t    Vec2d sol;\n            SolveLinearSystemLS (b, c, p-a, sol);\n            lami[0] = sol.X();\n            lami[1] = sol.Y();\n\n\t    if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t      return true;\n\t    \n            \n              //lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/\n              //(b.X()*c.Y() -b.Y()*c.X()); \n            //lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/\n             // (b.X()*c.Y() -b.Y()*c.X()); \n            \n          } \n        else\n          if(fabs(dxb) <= eps*fabs(dxc))\n            {\n\t      lami[1] = (dxp-dxa)/dxc;\n              if(fabs(b.X()+d.X()*lami[1])>=fabs(b.Y()+d.Y()*lami[1]))\n                lami[0] = (p.X()-a.X() - c.X()*lami[1])/(b.X()+d.X()*lami[1]); \n              else\n                lami[0] = (p.Y()-a.Y() - c.Y()*lami[1])/(b.Y()+d.Y()*lami[1]);\n\n\t      if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\treturn true;\n            }\n          else\n            if(fabs(dxc) <= eps*fabs(dxb))\n              {\n\t\tlami[0] = (dxp-dxa)/dxb;\n                if(fabs(c.X()+d.X()*lami[0])>=fabs(c.Y()+d.Y()*lami[0]))\n                  lami[1] = (p.X()-a.X() - b.X()*lami[0])/(c.X()+d.X()*lami[0]); \n                else\n                  lami[1] = (p.Y()-a.Y() - b.Y()*lami[0])/(c.Y()+d.Y()*lami[0]);\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t  return true;\n              }\n            else //Solve quadratic equation\n              {\n\t\tc2 = -d.X()*dxb;\n\t\tc1 = b.X()*dxc - c.X()*dxb + d.X()*(dxp-dxa);\n\t\tc0 = c.X()*(dxp-dxa) + (a.X()-p.X())*dxc;\n\t\tdouble rt =  c1*c1 - 4*c2*c0;\n\t\t\n\t\tif (rt < 0.) return false; \n\t\tlami[1] = (-c1 + sqrt(rt))/2/c2;\n\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps)\n\t\t  {\n\t\t    lami[0] = (dxp - dxa -dxb*lami[1])/dxc;\n\t\t    \n\t\t    if(lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t      return true;\n\t\t  }\n\t\tlami[1] = (-c1 - sqrt(rt))/2/c2;\n\n\t\tlami[0] = (dxp - dxa -dxb*lami[1])/dxc;\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t  return true;\n\n\t\tc2 = d.Y()*dxb;\n\t\tc1 = b.Y()*dxc - c.Y()*dxb + d.Y()*(dxp-dxa);\n\t\tc0 = c.Y()*(dxp -dxa) + (a.Y()-p.Y())*dxc;\n\t\trt =  c1*c1 - 4*c2*c0;\n\t\t\n\t\tif (rt < 0.) return false; \n\t\tlami[1] = (-c1 + sqrt(rt))/2/c2;\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps)\n\t\t  {\n\t\t    lami[0] = (dxp - dxa -dxb*lami[1])/dxc;\n\n\t\t    if(lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t      return true;\n\t\t  }\n\t\tlami[1] = (-c1 - sqrt(rt))/2/c2;\n\n\t\tlami[0] = (dxp - dxa -dxb*lami[1])/dxc;\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t  return true;\n\n\t\tc2 = -d.X()*dxc;\n\t\tc1 = -b.X()*dxc + c.X()*dxb + d.X()*(dxp-dxa);\n\t\tc0 = b.X()*(dxp -dxa) + (a.X()-p.X())*dxb;\n\t\trt =  c1*c1 - 4*c2*c0;\n\t\t\n\t\tif (rt < 0.) return false; \n\t\tlami[1] = (-c1 + sqrt(rt))/2/c2;\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps)\n\t\t  {\n\t\t    lami[0] = (dxp - dxa -dxc*lami[1])/dxb;\n\n\t\t    if(lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t      return true;\n\t\t  }\n\t\tlami[1] = (-c1 - sqrt(rt))/2/c2;\n\n\t\tlami[0] = (dxp - dxa -dxc*lami[1])/dxb;\n\n\t\tif(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps)\n\t\t  return true;\n                  }*/\n\n      \n        //cout << \"lam0,1 = \" << lami[0] << \", \" << lami[1] << endl;\n        \n        /*if( lami[0] <= 1.+eps  && lami[0] >= -eps && lami[1]<=1.+eps && lami[1]>=-eps)\n          {\n            if(consider3D)\n              {\n                Vec3d n = Cross(b,c);\n                lami[2] = 0;\n                for(int i=1; i<=3; i++)\n                  lami[2] +=(p.X(i)-a.X(i)-lami[0]*b.X(i)-lami[1]*c.X(i)) * n.X(i);\n                if(lami[2] >= -eps && lami[2] <= eps)\n                  return true;\n              }\n            else\n              return true;\n\t      }*/\n\n        return false;\n\n      }\n    else\n      {\n        //\t  SurfaceElement(element).GetTets (loctets);\n        loctrigs.SetSize(1);\n        loctrigs.Elem(1) = surfelements[ei];\n\n\n\n        for (int j = 1; j <= loctrigs.Size(); j++)\n          {\n            const Element2d & el = loctrigs.Get(j);\n\n\n            const Point3d & p1 = Point(el.PNum(1));\n            const Point3d & p2 = Point(el.PNum(2));\n            const Point3d & p3 = Point(el.PNum(3));\n            /*\n              Box3d box;\n              box.SetPoint (p1);\n              box.AddPoint (p2);\n              box.AddPoint (p3);\n              box.AddPoint (p4);\n              if (!box.IsIn (p))\n              continue;\n            */\n            col1 = p2-p1;\n            col2 = p3-p1;\n            col3 = Cross(col1,col2);\n            //col3 = Vec3d(0, 0, 1);\n            rhs = p - p1;\n\n            // int retval = \n            SolveLinearSystem (col1, col2, col3, rhs, sol);\n\n            //(*testout) << \"retval \" << retval << endl;\n\n            //(*testout) << \"col1 \" << col1 << \" col2 \" << col2 << \" col3 \" << col3 << \" rhs \" << rhs << endl;\n            //(*testout) << \"sol \" << sol << endl;\n\n            if (surfelements[ei].GetType() ==TRIG6 || curvedelems->IsSurfaceElementCurved(ei))\n              {\n                // netgen::Point<2> lam(1./3,1./3);\n                netgen::Point<2> lam(sol.X(), sol.Y());\n                if(surfelements[ei].GetType() != TRIG6)\n                  {\n                    lam[0] = 1-sol.X()-sol.Y();\n                    lam[1] = sol.X();\n                  }\n                Vec<3> rhs;\n                Vec<2> deltalam;\n                netgen::Point<3> x;\n                Mat<3,2> Jac,Jact;\n                \n                double delta=1;\n                \n                // bool retval;\n                \n                int i = 0;\n                \n                const int maxits = 30;\n                while(delta > 1e-16 && i<maxits)\n                  {\n                    curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);\n                    rhs = p-x;\n                    Jac.Solve(rhs,deltalam);\n                    \n                    lam += deltalam;\n                    \n                    delta = deltalam.Length2();\n                    \n                    i++;\n                    //(*testout) << \"pcie i \" << i << \" delta \" << delta << \" p \" << p << \" x \" << x << \" lam \" << lam << endl;\n                    //<< \"Jac \" << Jac << endl;\n                  }\n                \n                if(i==maxits)\n                  return false;\n                \n                sol.X() = lam(0);\n                sol.Y() = lam(1);\n\n                if (surfelements[ei].GetType() !=TRIG6 )\n                  {\n                    sol.Z() = sol.X();\n                    sol.X() = sol.Y();\n                    sol.Y() = 1.0 - sol.Z() - sol.X();\n                  }\n\n              }\n            if (sol.X() >= -eps && sol.Y() >= -eps && \n                sol.X() + sol.Y() <= 1+eps)\n              {\n                if(!consider3D || (sol.Z() >= -eps && sol.Z() <= eps))\n                  {\n                    lami[0] = sol.X();\n                    lami[1] = sol.Y();\n                    lami[2] = sol.Z();\n\n                    return true;\n                  }\n              }\n          }\n      }\n\n    return false;\n\n  }\n\n\n\n\n  bool Mesh :: PointContainedIn3DElement(const Point3d & p,\n                                         double lami[3],\n                                         ElementIndex ei,\n                                         double eps) const\n  {\n    //bool oldresult = PointContainedIn3DElementOld(p,lami,element);\n    //(*testout) << \"old result: \" << oldresult\n    //       << \" lam \" << lami[0] << \" \" << lami[1] << \" \" << lami[2] << endl;\n\n    //if(!curvedelems->IsElementCurved(element-1))\n    //  return PointContainedIn3DElementOld(p,lami,element);\n    const Element & el = volelements[ei];\n\n    netgen::Point<3> lam = 0.0;\n\n    if (el.GetType() == TET || el.GetType() == TET10)\n      {\n        lam = 0.25;\n      }\n    else if (el.GetType() == PRISM)\n      {\n        lam(0) = 0.33; lam(1) = 0.33; lam(2) = 0.5;\n      }\n    else if (el.GetType() == PYRAMID)\n      {\n        lam(0) = 0.4; lam(1) = 0.4; lam(2) = 0.2;\n      }\n    else if (el.GetType() == HEX)\n      {\n        lam = 0.5;\n      }\n\n\n    Vec<3> deltalam,rhs;\n    netgen::Point<3> x;\n    Mat<3,3> Jac,Jact;\n\n    double delta=1;\n\n    bool retval;\n\n    int i = 0;\n\n    const int maxits = 30;\n    while(delta > 1e-16 && i<maxits)\n      {\n        curvedelems->CalcElementTransformation(lam,ei,x,Jac);\n        rhs = p-x;\n        Jac.Solve(rhs,deltalam);\n\n        lam += deltalam;\n\n        delta = deltalam.Length2();\n\n        i++;\n        //(*testout) << \"pcie i \" << i << \" delta \" << delta << \" p \" << p << \" x \" << x << \" lam \" << lam << endl;\n        //<< \"Jac \" << Jac << endl;\n      }\n\n    if(i==maxits)\n      return false;\n\n    for(i=0; i<3; i++)\n      lami[i] = lam(i);\n\n\n\n    if (el.GetType() == TET || el.GetType() == TET10)\n      {\n        retval = (lam(0) > -eps && \n                  lam(1) > -eps && \n                  lam(2) > -eps && \n                  lam(0) + lam(1) + lam(2) < 1+eps);\n      }\n    else if (el.GetType() == PRISM || el.GetType() == PRISM15)\n      {\n        retval = (lam(0) > -eps &&\n                  lam(1) > -eps &&\n                  lam(2) > -eps &&\n                  lam(2) < 1+eps &&\n                  lam(0) + lam(1) < 1+eps);\n      }\n    else if (el.GetType() == PYRAMID || el.GetType() == PYRAMID13)\n      {\n        retval = (lam(0) > -eps &&\n                  lam(1) > -eps &&\n                  lam(2) > -eps &&\n                  lam(0) + lam(2) < 1+eps &&\n                  lam(1) + lam(2) < 1+eps);\n      }\n    else if (el.GetType() == HEX || el.GetType() == HEX20)\n      {\n        retval = (lam(0) > -eps && lam(0) < 1+eps &&\n                  lam(1) > -eps && lam(1) < 1+eps &&\n                  lam(2) > -eps && lam(2) < 1+eps);\n      }\n    else\n      throw NgException(\"Da haun i wos vagessn\");\n\n    return retval;\n  }\n\n\n\n  bool Mesh :: PointContainedIn3DElementOld(const Point3d & p,\n                                            double lami[3],\n                                            ElementIndex element,\n                                            double eps) const\n  {\n    Vec3d col1, col2, col3;\n    Vec3d rhs, sol;\n\n    NgArray<Element> loctets;\n\n    VolumeElement(element).GetTets (loctets);\n\n    for (int j = 1; j <= loctets.Size(); j++)\n      {\n        const Element & el = loctets.Get(j);\n\n        const Point3d & p1 = Point(el.PNum(1));\n        const Point3d & p2 = Point(el.PNum(2));\n        const Point3d & p3 = Point(el.PNum(3));\n        const Point3d & p4 = Point(el.PNum(4));\n\n        Box3d box;\n        box.SetPoint (p1);\n        box.AddPoint (p2);\n        box.AddPoint (p3);\n        box.AddPoint (p4);\n        if (!box.IsIn (p))\n          continue;\n\n        col1 = p2-p1;\n        col2 = p3-p1;\n        col3 = p4-p1;\n        rhs = p - p1;\n\n        SolveLinearSystem (col1, col2, col3, rhs, sol);\n\n        if (sol.X() >= -eps && sol.Y() >= -eps && sol.Z() >= -eps &&\n            sol.X() + sol.Y() + sol.Z() <= 1+eps)\n          {\n            NgArray<Element> loctetsloc;\n            NgArray<netgen::Point<3> > pointsloc;\n\n            VolumeElement(element).GetTetsLocal (loctetsloc);\n            VolumeElement(element).GetNodesLocalNew (pointsloc);\n\n            const Element & le = loctetsloc.Get(j);\n\n\n            Point3d pp = \n              pointsloc.Get(le.PNum(1)) \n              + sol.X() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(2))) \n              + sol.Y() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(3))) \n              + sol.Z() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(4))) ;\n\n            lami[0] = pp.X();\n            lami[1] = pp.Y();\n            lami[2] = pp.Z();\n            return true;\n          }\n      }\n    return false;\n  }\n\n\n  ElementIndex Mesh :: GetElementOfPoint (const netgen::Point<3> & p,\n                                          double* lami,\n                                          bool build_searchtree,\n                                          int index,\n                                          bool allowindex,\n                                          double tol) const\n  {\n    if(index != -1) \n      {\n        Array<int> dummy(1);\n        dummy[0] = index;\n        return GetElementOfPoint(p,lami,dummy,build_searchtree,allowindex, tol);\n      }\n    else\n      return GetElementOfPoint(p,lami,nullopt,build_searchtree,allowindex, tol);\n  }\n\n\n\n\n  ElementIndex Mesh :: GetElementOfPoint (const netgen::Point<3> & p,\n                                          double* lami,\n                                          std::optional<FlatArray<int>> indices,\n                                          bool build_searchtree,\n                                          bool allowindex,\n                                          double tol) const\n  {\n    if (build_searchtree)\n      const_cast<Mesh&>(*this).BuildElementSearchTree (3);\n    return Find3dElement(*this, p, lami, indices, elementsearchtree_vol.get(), allowindex, tol);\n  }\n\n\n\n  SurfaceElementIndex Mesh ::\n  GetSurfaceElementOfPoint (const netgen::Point<3> & p,\n                            double* lami,\n                            bool build_searchtree,\n                            int index,\n                            bool allowindex) const\n  {\n    if(index != -1)\n      {\n        Array<int> dummy(1);\n        dummy[0] = index;\n        return GetSurfaceElementOfPoint(p,lami,dummy,build_searchtree,allowindex);\n      }\n    else\n      return GetSurfaceElementOfPoint(p,lami,nullopt,build_searchtree,allowindex);\n  }\n\n  SurfaceElementIndex Mesh ::\n  GetSurfaceElementOfPoint (const netgen::Point<3> & p,\n                            double* lami,\n                            std::optional<FlatArray<int>> indices,\n                            bool build_searchtree,\n                            bool allowindex) const\n  {\n    if (build_searchtree)\n      const_cast<Mesh&>(*this).BuildElementSearchTree(2);\n    return Find2dElement(*this, p, lami, indices, elementsearchtree_surf.get(), allowindex);\n  }\n\n\n  void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, \n                                   Array<ElementIndex> & locels) const\n  {\n    elementsearchtree_vol->GetIntersecting (p1, p2, locels);\n  }\n\n  void Mesh :: SplitIntoParts()\n  {\n    // int i, j, dom;\n    int ne = GetNE();\n    int np = GetNP();\n    int nse = GetNSE();\n\n    BitArray surfused(nse+1);\n    TBitArray<PointIndex> pused (np);\n\n    surfused.Clear();\n\n    int dom = 0;\n\n    while (1)\n      {\n        int cntd = 1;\n\n        dom++;\n\n        pused.Clear();\n\n        int found = 0;\n        for (int i = 1; i <= nse; i++)\n          if (!surfused.Test(i))\n            {\n              SurfaceElement(i).SetIndex (dom);\n              for (int j = 1; j <= 3; j++)\n                pused.SetBit (SurfaceElement(i).PNum(j));\n              found = 1;\n              cntd = 1;\n              surfused.SetBit(i);\n              break;\n            }\n\n        if (!found)\n          break;\n\n        int change;\n        do\n          {\n            change = 0;\n            for (int i = 1; i <= nse; i++)\n              {\n                int is = 0, isnot = 0;\n                for (int j = 1; j <= 3; j++)\n                  if (pused.Test(SurfaceElement(i).PNum(j)))\n                    is = 1;\n                  else\n                    isnot = 1;\n\n                if (is && isnot)\n                  {\n                    change = 1;\n                    for (int j = 1; j <= 3; j++)\n                      pused.SetBit (SurfaceElement(i).PNum(j));\n                  }\n\n                if (is) \n                  {\n                    if (!surfused.Test(i))\n                      {\n                        surfused.SetBit(i);\n                        SurfaceElement(i).SetIndex (dom);\n                        cntd++;\n                      }\n                  }\n              }\n\n\n            for (int i = 1; i <= ne; i++)\n              {\n                int is = 0, isnot = 0;\n                for (int j = 1; j <= 4; j++)\n                  if (pused.Test(VolumeElement(i).PNum(j)))\n                    is = 1;\n                  else\n                    isnot = 1;\n\n                if (is && isnot)\n                  {\n                    change = 1;\n                    for (int j = 1; j <= 4; j++)\n                      pused.SetBit (VolumeElement(i).PNum(j));\n                  }\n\n                if (is)\n                  {\n                    VolumeElement(i).SetIndex (dom);\n                  }\n              }\n          }\n        while (change);\n\n        PrintMessage (3, \"domain \", dom, \" has \", cntd, \" surfaceelements\");\n      }\n\n    /*\n      facedecoding.SetSize (dom);\n      for (i = 1; i <= dom; i++)\n      {\n      facedecoding.Elem(i).surfnr = 0;\n      facedecoding.Elem(i).domin = i;\n      facedecoding.Elem(i).domout = 0;\n      }\n    */\n    ClearFaceDescriptors();\n    for (int i = 1; i <= dom; i++)\n      AddFaceDescriptor (FaceDescriptor (0, i, 0, 0));\n    CalcSurfacesOfNode();\n    timestamp = NextTimeStamp();\n  }\n\n  void Mesh :: SplitSeparatedFaces ()\n  {\n    PrintMessage (3, \"SplitSeparateFaces\");\n    int fdi;\n    int np = GetNP();\n\n    TBitArray<PointIndex> usedp(np);\n    Array<SurfaceElementIndex> els_of_face;\n\n    fdi = 1;\n    while (fdi <= GetNFD())\n      {\n        GetSurfaceElementsOfFace (fdi, els_of_face);\n\n        if (els_of_face.Size() == 0)\n        {\n            fdi++;\n            continue;\n        }\n\n        SurfaceElementIndex firstel = els_of_face[0];\n\n        usedp.Clear();\n        for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++)\n          usedp.SetBit (SurfaceElement(firstel).PNum(j));\n\n        bool changed;\n        do\n          {\n            changed = false;\n\n            for (int i = 0; i < els_of_face.Size(); i++)\n              {\n                const Element2d & el = SurfaceElement(els_of_face[i]);\n\n                bool has = 0;\n                bool hasno = 0;\n                for (int j = 0; j < el.GetNP(); j++)\n                  {\n                    if (usedp.Test(el[j]))\n                      has = true;\n                    else\n                      hasno = true;\n                  }\n\n                if (has && hasno)\n                  changed = true;\n\n                if (has)\n                  for (int j = 0; j < el.GetNP(); j++)\n                    usedp.SetBit (el[j]);\n              }\n          }\n        while (changed);\n\n        int nface = 0;\n        for (int i = 0; i < els_of_face.Size(); i++)\n          {\n            Element2d & el = SurfaceElement(els_of_face[i]);\n\n            int hasno = 0;\n            for (int j = 1; j <= el.GetNP(); j++)\n              if (!usedp.Test(el.PNum(j)))\n                hasno = 1;\n\n            if (hasno)\n              {\n                if (!nface)\n                  {\n                    FaceDescriptor nfd = GetFaceDescriptor(fdi);\n                    nface = AddFaceDescriptor (nfd);\n                  }\n\n                el.SetIndex (nface);\n              }\n          }\n\n        // reconnect list\n        if (nface)\n          {\n            facedecoding[nface-1].firstelement = -1;\n            facedecoding[fdi-1].firstelement = -1;\n\n            for (int i = 0; i < els_of_face.Size(); i++)\n              {\n                int ind = SurfaceElement(els_of_face[i]).GetIndex();\n                SurfaceElement(els_of_face[i]).next = facedecoding[ind-1].firstelement;\n                facedecoding[ind-1].firstelement = els_of_face[i];\n              }\n\n            // map the segments\n            for(auto& seg : segments)\n              if(!usedp.Test(seg[0]) || !usedp.Test(seg[1]))\n                if(seg.si == fdi)\n                  seg.si = nface;\n          }\n\n        fdi++;\n      }\n\n\n    /*\n      fdi = 1;\n      while (fdi <= GetNFD())\n      {\n      int firstel = 0;\n      for (int i = 1; i <= GetNSE(); i++)\n      if (SurfaceElement(i).GetIndex() == fdi)\n      {\n      firstel = i;\n      break;\n      }\n      if (!firstel) continue;\n\n      usedp.Clear();\n      for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++)\n      usedp.Set (SurfaceElement(firstel).PNum(j));\n\n      int changed;\n      do\n      {\n      changed = 0;\n      for (int i = 1; i <= GetNSE(); i++)\n      {\n      const Element2d & el = SurfaceElement(i);\n      if (el.GetIndex() != fdi)\n      continue;\n\n      int has = 0;\n      int hasno = 0;\n      for (int j = 1; j <= el.GetNP(); j++)\n      {\n      if (usedp.Test(el.PNum(j)))\n      has = 1;\n      else\n      hasno = 1;\n      }\n      if (has && hasno)\n      changed = 1;\n\n      if (has)\n      for (int j = 1; j <= el.GetNP(); j++)\n      usedp.Set (el.PNum(j));\n      }\n      }\n      while (changed);\n\n      int nface = 0;\n      for (int i = 1; i <= GetNSE(); i++)\n      {\n      Element2d & el = SurfaceElement(i);\n      if (el.GetIndex() != fdi)\n      continue;\t  \n\n      int hasno = 0;\n      for (int j = 1; j <= el.GetNP(); j++)\n      {\n      if (!usedp.Test(el.PNum(j)))\n      hasno = 1;\n      }\n\n      if (hasno)\n      {\n      if (!nface)\n      {\n      FaceDescriptor nfd = GetFaceDescriptor(fdi);\n      nface = AddFaceDescriptor (nfd);\n      }\n\n      el.SetIndex (nface);\n      }\n      }\n      fdi++;\n      }\n    */\n  }\n\n  void Mesh :: ZRefine(const string& name, const Array<double>& slices)\n  {\n    auto nr = GetIdentifications().GetNr(name);\n    auto& identpts = GetIdentifications().GetIdentifiedPoints();\n\n    UpdateTopology();\n\n    std::map<std::pair<PointIndex, PointIndex>,\n             Array<PointIndex>> inserted_points;\n    BitArray mapped_points(GetNV()+1);\n    mapped_points = false;\n\n    // Add new points\n    for(auto [hash, dummy] : identpts)\n      {\n        auto [hash_pts, hash_nr] = hash;\n        if(hash_nr != nr)\n          continue;\n        // auto& ipts = inserted_points[{p1p2.I1(), p1p2.I2()}];\n        auto& ipts = inserted_points[ { hash_pts[0], hash_pts[1] }];\n        auto p1 = Point(hash_pts.I1());\n        auto p2 = Point(hash_pts.I2());\n        ipts.Append(hash_pts.I1());\n        mapped_points.SetBit(hash_pts.I1());\n        for(auto slice : slices)\n          {\n            auto np = p1 + slice * (p2-p1);\n            auto npi = AddPoint(np);\n            ipts.Append(npi);\n          }\n        ipts.Append(hash_pts.I2());\n      }\n\n    // Split segments\n    for(auto si : Range(segments))\n      {\n        auto& seg = segments[si];\n        // Copy segment, as reference above might get invalidated in AddSegment()\n        auto reference_seg = seg;\n        auto p1 = seg[0];\n        auto p2 = seg[1];\n\n        auto c1 = inserted_points.count({p1, p2});\n        auto c2 = inserted_points.count({p2, p1});\n\n        if(c1 == 0 && c2 == 0)\n          continue;\n\n        if(c2)\n          Swap(p1,p2);\n\n        const auto& ipts = inserted_points[{p1,p2}];\n        if(c2)\n          seg[1] = ipts[ipts.Size()-2];\n        else\n          seg[1] = ipts[1];\n        for(auto i : Range(size_t(1), ipts.Size()-1))\n          {\n            Segment snew = reference_seg;\n            if(c2)\n              {\n                snew[0] = ipts[ipts.Size()-1-i];\n                snew[1] = ipts[ipts.Size()-2-i];\n              }\n            else\n              {\n                snew[0] = ipts[i];\n                snew[1] = ipts[i+1];\n              }\n            AddSegment(snew);\n          }\n      }\n\n    BitArray sel_done(surfelements.Size());\n    sel_done = false;\n\n    // Split surface elements\n    auto p2sel = CreatePoint2SurfaceElementTable();\n    for(const auto& [pair, inserted] : inserted_points)\n      {\n        for(auto si : p2sel[pair.first])\n          {\n            if(sel_done[si])\n              continue;\n            sel_done.SetBit(si);\n            auto sel = surfelements[si];\n            map<PointIndex, Array<PointIndex>> mapped_points;\n            int nmapped = 0;\n            for(auto i : Range(sel.GetNP()))\n              {\n                auto p1 = sel[i];\n                auto p2 = sel[(i+1)%sel.GetNP()];\n                auto c1 = inserted_points.count({p1, p2});\n                auto c2 = inserted_points.count({p2, p1});\n                if(c1 == 0 && c2 == 0)\n                  continue;\n                if(c2)\n                  Swap(p1, p2);\n                auto& ipts = inserted_points[{p1, p2}];\n                auto& a1 = mapped_points[p1];\n                auto& a2 = mapped_points[p2];\n                a1 = ipts.Range(0, ipts.Size()-1);\n                a2 = ipts.Range(1, ipts.Size());\n                nmapped = ipts.Size()-1;\n              }\n            for(auto i : Range(nmapped))\n              {\n                Element2d nsel = sel;\n                for(auto& pi : nsel.PNums())\n                  if(mapped_points.count(pi))\n                    pi = mapped_points[pi][i];\n                AddSurfaceElement(nsel);\n              }\n            if(nmapped)\n              surfelements[si].Delete();\n          }\n      }\n\n    // Split volume elements\n    BitArray vol_done(volelements.Size());\n    vol_done = false;\n    auto p2el = CreatePoint2ElementTable(); // mapped_points);\n    for(const auto& [pair, inserted] : inserted_points)\n      {\n        for(auto ei : p2el[pair.first])\n          {\n            if(vol_done[ei])\n              continue;\n            vol_done.SetBit(ei);\n            auto el = volelements[ei];\n            map<PointIndex, Array<PointIndex>> mapped_points;\n            int nmapped = 0;\n            // NgArray<int> eledges;\n            // topology.GetElementEdges(ei+1, eledges);\n            // for(auto edgei : eledges)\n            for(auto edgei : topology.GetEdges(ElementIndex(ei)))\n              {\n                // int p1, p2;\n                // topology.GetEdgeVertices(edgei+1, p1, p2);\n                auto [p1, p2] = topology.GetEdgeVertices(edgei);\n                auto c1 = inserted_points.count({p1, p2});\n                auto c2 = inserted_points.count({p2, p1});\n                if(c1 == 0 && c2 == 0)\n                  continue;\n                if(c2)\n                  Swap(p1, p2);\n                auto& ipts = inserted_points[{p1, p2}];\n                auto& a1 = mapped_points[p1];\n                auto& a2 = mapped_points[p2];\n                a1 = ipts.Range(0, ipts.Size()-1);\n                a2 = ipts.Range(1, ipts.Size());\n                nmapped = ipts.Size()-1;\n              }\n\n            for(auto i : Range(nmapped))\n              {\n                Element nel = el;\n                for(auto& pi : nel.PNums())\n                  if(mapped_points.count(pi))\n                    pi = mapped_points[pi][i];\n                AddVolumeElement(nel);\n              }\n            if(nmapped)\n              volelements[ei].Delete();\n          }\n      }\n\n    Compress();\n    SetNextMajorTimeStamp();\n  }\n\n  void Mesh :: RebuildSurfaceElementLists ()\n  {\n    static Timer t(\"Mesh::LinkSurfaceElements\"); RegionTimer reg (t);    \n    \n    for (int i = 0; i < facedecoding.Size(); i++)\n      facedecoding[i].firstelement = -1;\n    for (int i = surfelements.Size()-1; i >= 0; i--)\n      {\n        int ind = surfelements[i].GetIndex();\n        surfelements[i].next = facedecoding[ind-1].firstelement;\n        facedecoding[ind-1].firstelement = i;\n      }\n  }\n\n  void Mesh :: GetSurfaceElementsOfFace (int facenr, Array<SurfaceElementIndex> & sei) const\n  {\n    static int timer = NgProfiler::CreateTimer (\"GetSurfaceElementsOfFace\");\n    NgProfiler::RegionTimer reg (timer);\n\n    if(facenr==0)\n    {\n        sei.SetSize(GetNSE());\n        ParallelForRange( IntRange(GetNSE()), [&sei] (auto myrange)\n            {\n                for(auto i : myrange)\n                    sei[i] = i;\n            });\n        return;\n    }\n\n     sei.SetSize(0);\n\n     SurfaceElementIndex si = facedecoding[facenr-1].firstelement;\n     while (si != -1)\n     {\n       if ( (*this)[si].GetIndex () == facenr && (*this)[si][0].IsValid() &&\n            !(*this)[si].IsDeleted() )\n        {\n           sei.Append (si);\n        }\n\n        si = (*this)[si].next;\n     }\n  }\n\n\n\n\n  void Mesh :: CalcMinMaxAngle (double badellimit, double * retvalues) \n  {\n    int lpi1, lpi2, lpi3, lpi4;\n    double phimax = 0, phimin = 10;\n    double facephimax = 0, facephimin = 10;\n    int illegaltets = 0, negativetets = 0, badtets = 0;\n\n    // for (int i = 1; i <= GetNE(); i++)\n    for (ElementIndex ei : Range(VolumeElements()))\n      {\n        int badel = 0;\n\n        Element & el = VolumeElement(ei);\n\n        if (el.GetType() != TET)\n          {\n            VolumeElement(ei).Flags().badel = 0;\n            continue;\n          }\n\n        if (el.Volume(Points()) < 0)\n          {\n            badel = 1;\n            negativetets++;\n          }\n\n\n        if (!LegalTet (el)) \n          {\n            badel = 1;\n            illegaltets++;\n            (*testout) << \"illegal tet: \" << ei << \" \";\n            for (int j = 1; j <= el.GetNP(); j++)\n              (*testout) << el.PNum(j) << \" \";\n            (*testout) << endl;\n          }\n\n\n        // angles between faces\n        for (lpi1 = 1; lpi1 <= 3; lpi1++)\n          for (lpi2 = lpi1+1; lpi2 <= 4; lpi2++)\n            {\n              lpi3 = 1;\n              while (lpi3 == lpi1 || lpi3 == lpi2)\n                lpi3++;\n              lpi4 = 10 - lpi1 - lpi2 - lpi3;\n\n              const Point3d & p1 = Point (el.PNum(lpi1));\n              const Point3d & p2 = Point (el.PNum(lpi2));\n              const Point3d & p3 = Point (el.PNum(lpi3));\n              const Point3d & p4 = Point (el.PNum(lpi4));\n\n              Vec3d n(p1, p2);\n              n /= n.Length();\n              Vec3d v1(p1, p3);\n              Vec3d v2(p1, p4);\n\n              v1 -= (n * v1) * n;\n              v2 -= (n * v2) * n;\n\n              double cosphi = (v1 * v2) / (v1.Length() * v2.Length());\n              double phi = acos (cosphi);\n              if (phi > phimax) phimax = phi;\n              if (phi < phimin) phimin = phi;\n\n              if ((180/M_PI) * phi > badellimit)\n                badel = 1;\n            }\n\n\n        // angles in faces\n        for (int j = 1; j <= 4; j++)\n          {\n            Element2d face(TRIG);\n            el.GetFace (j, face);\n            for (lpi1 = 1; lpi1 <= 3; lpi1++)\n              {\n                lpi2 = lpi1 % 3 + 1;\n                lpi3 = lpi2 % 3 + 1;\n\n                const Point3d & p1 = Point (el.PNum(lpi1));\n                const Point3d & p2 = Point (el.PNum(lpi2));\n                const Point3d & p3 = Point (el.PNum(lpi3));\n\n                Vec3d v1(p1, p2);\n                Vec3d v2(p1, p3);\n                double cosphi = (v1 * v2) / (v1.Length() * v2.Length());\n                double phi = acos (cosphi);\n                if (phi > facephimax) facephimax = phi;\n                if (phi < facephimin) facephimin = phi;\n\n                if ((180/M_PI) * phi > badellimit)\n                  badel = 1;\n\n              }\n          }\n\n\n        VolumeElement(ei).Flags().badel = badel;\n        if (badel) badtets++;\n      }\n\n    if (!GetNE())\n      {\n        phimin = phimax = facephimin = facephimax = 0;\n      }\n\n    if (!retvalues)\n      {\n        PrintMessage (1, \"\");\n        PrintMessage (1, \"between planes:  phimin = \", (180/M_PI) * phimin,\n                      \" phimax = \", (180/M_PI) *phimax);\n        PrintMessage (1, \"inside planes:   phimin = \", (180/M_PI) * facephimin,\n                      \" phimax = \", (180/M_PI) * facephimax);\n        PrintMessage (1, \"\");      \n      }\n    else\n      {\n        retvalues[0] = (180/M_PI) * facephimin;\n        retvalues[1] = (180/M_PI) * facephimax;\n        retvalues[2] = (180/M_PI) * phimin;\n        retvalues[3] = (180/M_PI) * phimax;\n      }\n    PrintMessage (3, \"negative tets: \", negativetets);\n    PrintMessage (3, \"illegal tets:  \", illegaltets);\n    PrintMessage (3, \"bad tets:      \", badtets);\n  }\n\n\n  int Mesh :: MarkIllegalElements (int domain)\n  {\n    if(!boundaryedges)\n      BuildBoundaryEdges();\n\n    atomic<int> cnt = 0;\n    ParallelForRange( Range(volelements), [&] (auto myrange)\n    {\n      int cnt_local = 0;\n      for(auto & el : volelements.Range(myrange))\n        if ((domain==0 || el.GetIndex() == domain) && !LegalTet (el))\n          cnt_local++;\n      cnt += cnt_local;\n    });\n    return cnt;\n  }\n\n  // #ifdef NONE\n  //   void Mesh :: AddIdentification (int pi1, int pi2, int identnr)\n  //   {\n  //     INDEX_2 pair(pi1, pi2);\n  //     //  pair.Sort();\n  //     identifiedpoints->Set (pair, identnr);\n  //     if (identnr > maxidentnr)\n  //       maxidentnr = identnr;\n  //     timestamp = NextTimeStamp();\n  //   }\n\n  //   int Mesh :: GetIdentification (int pi1, int pi2) const\n  //   {\n  //     INDEX_2 pair(pi1, pi2);\n  //     if (identifiedpoints->Used (pair))\n  //       return identifiedpoints->Get(pair);\n  //     else\n  //       return 0;\n  //   }\n\n  //   int Mesh :: GetIdentificationSym (int pi1, int pi2) const\n  //   {\n  //     INDEX_2 pair(pi1, pi2);\n  //     if (identifiedpoints->Used (pair))\n  //       return identifiedpoints->Get(pair);\n\n  //     pair = INDEX_2 (pi2, pi1);\n  //     if (identifiedpoints->Used (pair))\n  //       return identifiedpoints->Get(pair);\n\n  //     return 0;\n  //   }\n\n\n  //   void Mesh :: GetIdentificationMap (int identnr, NgArray<int> & identmap) const\n  //   {\n  //     int i, j;\n\n  //     identmap.SetSize (GetNP());\n  //     for (i = 1; i <= identmap.Size(); i++)\n  //       identmap.Elem(i) = 0;\n\n  //     for (i = 1; i <= identifiedpoints->GetNBags(); i++)\n  //       for (j = 1; j <= identifiedpoints->GetBagSize(i); j++)\n  // \t{\n  // \t  INDEX_2 i2;\n  // \t  int nr;\n  // \t  identifiedpoints->GetData (i, j, i2, nr);\n\n  // \t  if (nr == identnr)\n  // \t    {\n  // \t      identmap.Elem(i2.I1()) = i2.I2();\n  // \t    }\n  // \t}\n  //   }\n\n\n  //   void Mesh :: GetIdentificationPairs (int identnr, NgArray<INDEX_2> & identpairs) const\n  //   {\n  //     int i, j;\n\n  //     identpairs.SetSize(0);\n\n  //     for (i = 1; i <= identifiedpoints->GetNBags(); i++)\n  //       for (j = 1; j <= identifiedpoints->GetBagSize(i); j++)\n  // \t{\n  // \t  INDEX_2 i2;\n  // \t  int nr;\n  // \t  identifiedpoints->GetData (i, j, i2, nr);\n\n  // \t  if (identnr == 0 || nr == identnr)\n  // \t    identpairs.Append (i2);\n  // \t}\n  //   }\n  // #endif\n\n  int Mesh::IdentifyPeriodicBoundaries(const string& id_name,\n                                       const string &s1,\n                                       const Transformation<3> &mapping,\n                                       double pointTolerance)\n  {\n    auto nr = ident->GetNr(id_name);\n    ident->SetType(nr, Identifications::PERIODIC);\n    // double lami[4];\n    set<int> identified_points;\n    if(pointTolerance < 0.)\n      {\n        Point3d pmin, pmax;\n        GetBox(pmin, pmax);\n        pointTolerance = 1e-8 * (pmax-pmin).Length();\n      }\n    size_t nse = GetDimension() == 3 ? surfelements.Size() : segments.Size();\n    for(auto sei : Range(nse))\n      {\n        auto name = GetDimension() == 3 ? GetBCName(surfelements[sei].index-1) :\n          GetBCName(segments[sei].edgenr-1);\n        if(name != s1)\n          continue;\n\n        const auto& pnums = GetDimension() == 3 ? surfelements[sei].PNums() :\n          segments[sei].PNums();\n        for(const auto& pi : pnums)\n          {\n            if(identified_points.find(pi) != identified_points.end())\n              continue;\n            auto pt = (*this)[pi];\n            auto mapped_pt = mapping(pt);\n            bool found = false;\n            for(auto other_pi : Range(points))\n              {\n                if((mapped_pt - (*this)[other_pi]).Length() < pointTolerance)\n                  {\n                    identified_points.insert(pi);\n                    ident->Add(pi, other_pi, nr);\n                    found = true;\n                    break;\n                  }\n              }\n            if(!found)\n              {\n                cout << \"point coordinates = \" << pt << endl;\n                cout << \"mapped coordinates = \" << mapped_pt << endl;\n                throw Exception(\"Did not find mapped point with nr \" + ToString(pi) + \", are you sure your mesh is periodic?\");\n              }\n          }\n      }\n    return nr;\n  }\n\n  void Mesh :: InitPointCurve(double red, double green, double blue) const\n  {\n    pointcurves_startpoint.Append(pointcurves.Size());\n    pointcurves_red.Append(red);\n    pointcurves_green.Append(green);\n    pointcurves_blue.Append(blue);\n  }\n  void Mesh :: AddPointCurvePoint(const Point3d & pt) const\n  {\n    pointcurves.Append(pt);\n  }\n  int Mesh :: GetNumPointCurves(void) const\n  {\n    return pointcurves_startpoint.Size();\n  }\n  int Mesh :: GetNumPointsOfPointCurve(int curve) const\n  {\n    if(curve == pointcurves_startpoint.Size()-1)\n      return (pointcurves.Size() - pointcurves_startpoint.Last());\n    else\n      return (pointcurves_startpoint[curve+1]-pointcurves_startpoint[curve]);\n  }\n\n  Point3d & Mesh :: GetPointCurvePoint(int curve, int n) const\n  {\n    return pointcurves[pointcurves_startpoint[curve]+n];\n  }\n\n  void Mesh :: GetPointCurveColor(int curve, double & red, double & green, double & blue) const\n  {\n    red = pointcurves_red[curve];\n    green = pointcurves_green[curve];\n    blue = pointcurves_blue[curve];\n  }\n\n\n  void Mesh :: ComputeNVertices ()\n  {\n\n    numvertices = 0;\n    /*\n    for (const Element & el : VolumeElements())\n      for (PointIndex v : el.Vertices())\n        if (v > numvertices) numvertices = v;\n        \n    for (const Element2d & el : SurfaceElements())\n      for (PointIndex v : el.Vertices())\n        if (v > numvertices) numvertices = v;\n\n    numvertices += 1-PointIndex::BASE;\n    */\n    numvertices = 0;    \n    numvertices =\n      ParallelReduce (VolumeElements().Size(),\n                      [&](size_t nr)\n                      {\n                        return int(Max(VolumeElements()[nr].Vertices()));\n                      },\n                      [](auto a, auto b) { return a > b ?  a : b; },\n                      numvertices);\n    numvertices =\n      ParallelReduce (SurfaceElements().Size(),\n                      [&](size_t nr)\n                      {\n                        return int(Max(SurfaceElements()[nr].Vertices()));\n                      },\n                      [](auto a, auto b) { return a > b ?  a : b; },\n                      numvertices);\n    numvertices =\n      ParallelReduce (LineSegments().Size(),\n                      [&](size_t nr)\n                      {\n                        return int(Max(LineSegments()[nr].Vertices()));\n                      },\n                      [](auto a, auto b) { return a > b ?  a : b; },\n                      numvertices);\n    numvertices += 1-PointIndex::BASE;    \n  }\n\n  int Mesh :: GetNV () const\n  {\n    if (numvertices < 0)\n      return GetNP();\n    else\n      return numvertices;\n  }\n\n  void Mesh :: SetNP (int np)\n  {\n    points.SetSize(np);\n    //  ptyps.SetSize(np);\n\n    int mlold = mlbetweennodes.Size();\n    mlbetweennodes.SetSize(np);\n    if (np > mlold)\n      for (PointIndex i = mlold+IndexBASE<PointIndex>(); \n           i < np+IndexBASE<PointIndex>(); i++)\n        {\n          mlbetweennodes[i][0].Invalidate();\n          mlbetweennodes[i][1].Invalidate();\n        }\n\n    GetIdentifications().SetMaxPointNr (np + PointIndex::BASE-1);\n  }\n\n\n  Table<ElementIndex, PointIndex> Mesh :: CreatePoint2ElementTable(std::optional<TBitArray<PointIndex>> points, int domain) const\n  {\n    static Timer timer(\"Mesh::CreatePoint2VolumeElementTable\"); RegionTimer rt(timer);\n    \n    if(points)\n      {\n        const auto & free_points = *points;\n        return ngcore::CreateSortedTable<ElementIndex, PointIndex>( volelements.Range(),\n               [&](auto & table, ElementIndex ei)\n               {\n                 const auto & el = (*this)[ei];\n                 if(el.IsDeleted())\n                     return;\n\n                 if(domain && el.GetIndex() != domain)\n                     return;\n\n                 for (PointIndex pi : el.PNums())\n                   if(free_points[pi])\n                     table.Add (pi, ei);\n               }, GetNP());\n      }\n    else\n        return ngcore::CreateSortedTable<ElementIndex, PointIndex>( volelements.Range(),\n               [&](auto & table, ElementIndex ei)\n               {\n                 const auto & el = (*this)[ei];\n                 if(el.IsDeleted())\n                     return;\n\n                 if(domain && el.GetIndex() != domain)\n                     return;\n\n                 for (PointIndex pi : el.PNums())\n                   table.Add (pi, ei);\n               }, GetNP());\n  }\n\n  Table<SurfaceElementIndex, PointIndex> Mesh :: CreatePoint2SurfaceElementTable( int faceindex ) const\n  {\n    static Timer timer(\"Mesh::CreatePoint2SurfaceElementTable\"); RegionTimer rt(timer);\n\n    if(faceindex==0)\n      {\n        return ngcore::CreateSortedTable<SurfaceElementIndex, PointIndex>( surfelements.Range(),\n               [&](auto & table, SurfaceElementIndex ei)\n               {\n                 for (PointIndex pi : (*this)[ei].PNums())\n                   table.Add (pi, ei);\n               }, GetNP());\n      }\n\n    Array<SurfaceElementIndex> face_els;\n    GetSurfaceElementsOfFace(faceindex, face_els);\n    return ngcore::CreateSortedTable<SurfaceElementIndex, PointIndex>( face_els.Range(),\n           [&](auto & table, size_t i)\n           {\n             for (PointIndex pi : (*this)[face_els[i]].PNums())\n               table.Add (pi, face_els[i]);\n           }, GetNP());\n  }\n\n\n  CompressedTable<SurfaceElementIndex, PointIndex> Mesh :: CreateCompressedPoint2SurfaceElementTable( int faceindex ) const\n  {\n    static Timer timer(\"Mesh::CreatePoint2SurfaceElementTable\"); RegionTimer rt(timer);\n\n    CompressedTableCreator<SurfaceElementIndex, PointIndex> creator;\n    \n    if(faceindex==0)\n      {\n        for ( ; !creator.Done(); creator++)\n          for (auto sei : SurfaceElements().Range())\n            for (auto pi : (*this)[sei].PNums())\n              creator.Add(pi, sei);\n      }\n    else\n      {\n        Array<SurfaceElementIndex> face_els;\n        GetSurfaceElementsOfFace(faceindex, face_els);\n\n        for ( ; !creator.Done(); creator++)\n          for (auto sei : face_els)\n            for (auto pi : (*this)[sei].PNums())\n              creator.Add(pi, sei);\n      }\n\n\n    auto compressed_table = creator.MoveTable();\n    \n    for (auto row : compressed_table.GetTable())\n      QuickSort (row);\n    \n    return compressed_table;\n  }\n\n\n\n  \n\n  /*\n    void Mesh :: BuildConnectedNodes ()\n    {\n    if (PureTetMesh())\n    {\n    connectedtonode.SetSize(0);\n    return;\n    }\n\n\n    int i, j, k;\n    int np = GetNP();\n    int ne = GetNE();\n    TABLE<int> conto(np);\n    for (i = 1; i <= ne; i++)\n    {\n    const Element & el = VolumeElement(i);\n\n    if (el.GetType() == PRISM)\n    {\n    for (j = 1; j <= 6; j++)\n    {\n    int n1 = el.PNum (j);\n    int n2 = el.PNum ((j+2)%6+1);\n    //\t    if (n1 != n2)\n    {\n    int found = 0;\n    for (k = 1; k <= conto.EntrySize(n1); k++)\n    if (conto.Get(n1, k) == n2)\n    {\n    found = 1;\n    break;\n    }\n    if (!found)\n    conto.Add (n1, n2);\n    }\n    }\n    }\n    else if (el.GetType() == PYRAMID)\n    {\n    for (j = 1; j <= 4; j++)\n    {\n    int n1, n2;\n    switch (j)\n    {\n    case 1: n1 = 1; n2 = 4; break;\n    case 2: n1 = 4; n2 = 1; break;\n    case 3: n1 = 2; n2 = 3; break;\n    case 4: n1 = 3; n2 = 2; break;\n    }\n\n    int found = 0;\n    for (k = 1; k <= conto.EntrySize(n1); k++)\n    if (conto.Get(n1, k) == n2)\n    {\n    found = 1;\n    break;\n    }\n    if (!found)\n    conto.Add (n1, n2);\n    }\n    }\n    }\n\n    connectedtonode.SetSize(np);\n    for (i = 1; i <= np; i++)\n    connectedtonode.Elem(i) = 0;\n\n    for (i = 1; i <= np; i++)\n    if (connectedtonode.Elem(i) == 0)\n    {\n    connectedtonode.Elem(i) = i;\n    ConnectToNodeRec (i, i, conto);\n    }\n\n\n\n    }\n\n    void Mesh :: ConnectToNodeRec (int node, int tonode, \n    const TABLE<int> & conto)\n    {\n    int i, n2;\n    //  (*testout) << \"connect \" << node << \" to \" << tonode << endl;\n    for (i = 1; i <= conto.EntrySize(node); i++)\n    {\n    n2 = conto.Get(node, i);\n    if (!connectedtonode.Get(n2))\n    {\n    connectedtonode.Elem(n2) = tonode;\n    ConnectToNodeRec (n2, tonode, conto);\n    }\n    }\n    }\n  */\n\n\n  bool Mesh :: PureTrigMesh (int faceindex) const\n  {\n    // if (!faceindex) return !mparam.quad;\n    \n    if (!faceindex)\n      {\n\tfor (int i = 1; i <= GetNSE(); i++)\n\t  if (SurfaceElement(i).GetNP() != 3)\n\t    return false;\n\treturn true;\n      }\n\n    for (int i = 1; i <= GetNSE(); i++)\n      if (SurfaceElement(i).GetIndex() == faceindex &&\n          SurfaceElement(i).GetNP() != 3)\n        return false;\n    return true;\n  }\n\n  bool Mesh :: PureTetMesh () const\n  {\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      if (VolumeElement(ei).GetNP() != 4)\n        return 0;\n    return 1;\n  }\n\n  void Mesh :: UpdateTopology (NgTaskManager tm,\n                               NgTracer tracer)\n  {\n    static Timer t(\"Update Topology\"); RegionTimer reg(t);\n    ComputeNVertices();\n    topology.Update(tm, tracer);\n    (*tracer)(\"call update clusters\", false);\n    clusters->Update();\n    (*tracer)(\"call update clusters\", true);\n#ifdef PARALLEL\n    if (paralleltop)\n      {\n        paralleltop->Reset();\n        paralleltop->UpdateCoarseGrid();\n      }\n#endif\n    updateSignal.Emit();\n  }\n\n  void Mesh :: BuildCurvedElements  (const Refinement * ref, int aorder, bool arational)\n  {\n    GetCurvedElements().BuildCurvedElements (ref, aorder, arational);\n\n    for (SegmentIndex seg = 0; seg < GetNSeg(); seg++)\n      (*this)[seg].SetCurved (GetCurvedElements().IsSegmentCurved (seg));\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      (*this)[sei].SetCurved (GetCurvedElements().IsSurfaceElementCurved (sei));\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      (*this)[ei].SetCurved (GetCurvedElements().IsElementCurved (ei));\n    \n    SetNextMajorTimeStamp();\n  }\n\n  void Mesh :: BuildCurvedElements (int aorder)\n  {\n    if (!GetGeometry())\n      throw NgException (\"don't have a geometry for mesh curving\");\n    \n    GetCurvedElements().BuildCurvedElements (&GetGeometry()->GetRefinement(), aorder, false);\n\n    for (SegmentIndex seg = 0; seg < GetNSeg(); seg++)\n      (*this)[seg].SetCurved (GetCurvedElements().IsSegmentCurved (seg));\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      (*this)[sei].SetCurved (GetCurvedElements().IsSurfaceElementCurved (sei));\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      (*this)[ei].SetCurved (GetCurvedElements().IsElementCurved (ei));\n    \n    SetNextMajorTimeStamp();\n  }\n\n  void Mesh :: SplitFacesByAdjacentDomains ()\n  {\n    UpdateTopology();\n    std::map<std::tuple<int, int, int>, int> face_doms_2_new_face;\n    int nfaces = FaceDescriptors().Size();\n    Array<bool> first_visit(nfaces);\n    first_visit = true;\n\n    for (auto sei : Range(SurfaceElements()))\n      {\n        int eli0, eli1;\n        GetTopology().GetSurface2VolumeElement(sei+1, eli0, eli1);\n        // auto [ei0,ei1] = GetTopology().GetSurface2VolumeElement(sei); // the way to go\n        if(eli0 == 0)\n          continue;\n        auto & sel = (*this)[sei];\n        int face = sel.GetIndex();\n        int domin = VolumeElement(eli0).GetIndex();\n        int domout = eli1 ? VolumeElement(eli1).GetIndex() : 0;\n        if(domin < domout)\n          swap(domin, domout);\n\n        auto key = std::make_tuple(face, domin, domout);\n        if(face_doms_2_new_face.find(key) == face_doms_2_new_face.end())\n          {\n            {\n              auto & fd = FaceDescriptors()[face-1];\n              if(domout == 0 && min(fd.DomainIn(), fd.DomainOut()) > 0)\n                continue;\n            }\n            if(!first_visit[face-1]) {\n              nfaces++;\n              FaceDescriptor new_fd = FaceDescriptors()[face-1];\n              new_fd.bcprop = nfaces;\n              new_fd.domin = domin;\n              new_fd.domout = domout;\n              AddFaceDescriptor(new_fd);\n              SetBCName(nfaces-1, new_fd.GetBCName());\n              face_doms_2_new_face[key] = nfaces;\n            }\n            else {\n              face_doms_2_new_face[key] = face;\n              auto & fd = FaceDescriptors()[face-1];\n              fd.domin = domin;\n              fd.domout = domout;\n            }\n            first_visit[face-1] = false;\n          }\n          sel.SetIndex(face_doms_2_new_face[key]);\n      }\n    SetNextMajorTimeStamp();\n    RebuildSurfaceElementLists ();\n    CalcSurfacesOfNode();\n    UpdateTopology();\n  }\n\n  shared_ptr<Mesh> Mesh :: GetSubMesh(string domains, string faces) const\n  {\n    // Copy the mesh into a new one, then delete unwanted elements\n    // Unused points are deleted by the Compress() function at the end\n    auto mesh_ptr = make_unique<Mesh>();\n    auto & mesh = *mesh_ptr;\n    mesh = (*this);\n\n    auto ndomains = GetNDomains();\n    auto nfaces = GetNFD();\n\n    BitArray keep_point(GetNP()+1);\n    BitArray keep_face(nfaces+1);\n    BitArray keep_domain(ndomains+1);\n    keep_point.Clear();\n    keep_face.Clear();\n    keep_domain.Clear();\n\n    regex regex_faces(faces);\n    regex regex_domains(domains);\n\n    if(dimension == 3) {\n      for(auto dom : Range(ndomains))\n        if(regex_match(mesh.GetMaterial(dom+1), regex_domains))\n          keep_domain.SetBit(dom+1);\n\n      for(auto fi : Range(nfaces))\n      {\n        auto & fd = mesh.FaceDescriptors()[fi];\n        if (regex_match(fd.GetBCName(), regex_faces) \n          || keep_domain[fd.DomainIn()] || keep_domain[fd.DomainOut()])\n            keep_face.SetBit(fd.BCProperty());\n      }\n    }\n    else {\n      for(auto fi : Range(nfaces))\n      {\n        auto & fd = mesh.FaceDescriptors()[fi];\n        auto mat = GetMaterial(fd.BCProperty());\n        if (regex_match(mat, regex_faces))\n            keep_face.SetBit(fd.BCProperty());\n      }\n    }\n\n    auto filter_elements = [&keep_point](auto & elements, auto & keep_region)\n    {\n      for(auto & el : elements)\n      {\n        if(keep_region[el.GetIndex()])\n          for (auto pi : el.PNums())\n            keep_point.SetBit(pi);\n        else\n          el.Delete();\n      }\n    };\n\n    filter_elements(mesh.VolumeElements(), keep_domain);\n    filter_elements(mesh.SurfaceElements(), keep_face);\n\n    // Keep line segments only if all points are kept\n    // Check them in reverse order because they are deleted from the end\n    auto nsegments = mesh.LineSegments().Size();\n    for(auto i : Range(nsegments))\n    {\n      SegmentIndex segi = nsegments-i-1;\n      auto seg = mesh[segi];\n      bool keep = true;\n      for(auto pi : seg.PNums())\n        keep &= keep_point[pi];\n\n      if(!keep)\n        mesh.LineSegments().DeleteElement(segi);\n    }\n\n    // Check in reverse order because they are deleted from the end\n    auto npointelements = mesh.pointelements.Size();\n    for(auto i : Range(npointelements))\n    {\n      auto pel = mesh.pointelements[npointelements-i-1];\n      if(!keep_point[pel.pnum])\n        mesh.pointelements.DeleteElement(npointelements-i-1);\n    }\n\n    mesh.Compress();\n    return mesh_ptr;\n  }\n\n  void Mesh :: SetMaterial (int domnr, const string & mat)\n  {\n    if (domnr > materials.Size())\n      {\n        int olds = materials.Size();\n        materials.SetSize (domnr);\n        for (int i = olds; i < domnr-1; i++)\n          materials[i] = new string(\"default\");\n      }\n    /*\n    materials.Elem(domnr) = new char[strlen(mat)+1];\n    strcpy (materials.Elem(domnr), mat);\n    */\n    materials[domnr-1] = new string(mat);\n  }\n\n  string Mesh :: defaultmat = \"default\";\n  string_view Mesh :: defaultmat_sv = \"default\";  \n  const string & Mesh :: GetMaterial (int domnr) const\n  {\n    if (domnr <= materials.Size() && materials[domnr-1])\n      return *materials[domnr-1];\n    static string emptystring(\"default\");\n    return emptystring;\n  }\n\n  void Mesh ::SetNBCNames ( int nbcn )\n  {\n    if ( bcnames.Size() )\n      for ( int i = 0; i < bcnames.Size(); i++)\n        if ( bcnames[i] ) delete bcnames[i];\n    bcnames.SetSize(nbcn);\n    bcnames = 0;\n  }\n\n  void Mesh ::SetBCName ( int bcnr, const string & abcname )\n  {\n    if (bcnr >= bcnames.Size())\n      {\n        int oldsize = bcnames.Size();\n        bcnames.SetSize (bcnr+1);  // keeps contents\n        for (int i = oldsize; i <= bcnr; i++)\n          bcnames[i] = new string(\"default\");\n      }\n\n    if ( bcnames[bcnr] ) delete bcnames[bcnr];\n    bcnames[bcnr] = new string ( abcname );\n\n    for (auto & fd : facedecoding)\n      if (fd.BCProperty() <= bcnames.Size())\n        fd.SetBCName (bcnames[fd.BCProperty()-1]);\n  }\n\n  const string & Mesh ::GetBCName ( int bcnr ) const\n  {\n    static string defaultstring = \"default\";\n\n    if ( !bcnames.Size() )\n      return defaultstring;\n\n    if (bcnr < 0 || bcnr >= bcnames.Size())\n      throw RangeException(\"Illegal bc number \", bcnr, 0, bcnames.Size());\n\n    if ( bcnames[bcnr] )\n      return *bcnames[bcnr];\n    else\n      return defaultstring;\n  }\n\n  void Mesh :: SetNCD2Names( int ncd2n )\n  {\n    if (cd2names.Size())\n      for(int i=0; i<cd2names.Size(); i++)\n\tif(cd2names[i]) delete cd2names[i];\n    cd2names.SetSize(ncd2n);\n    cd2names = 0;\n  }\n\n  void Mesh :: SetCD2Name ( int cd2nr, const string & abcname )\n  {\n    cd2nr--;\n    (*testout) << \"setCD2Name on edge \" << cd2nr << \" to \" << abcname << endl;\n    if (cd2nr >= cd2names.Size())\n      {\n\tint oldsize = cd2names.Size();\n\tcd2names.SetSize(cd2nr+1);\n\tfor(int i= oldsize; i<= cd2nr; i++)\n\t  cd2names[i] = nullptr;\n      }\n    //if (cd2names[cd2nr]) delete cd2names[cd2nr];\n    if (abcname != \"default\" && abcname != \"\")\n      cd2names[cd2nr] = new string(abcname);\n    else\n      cd2names[cd2nr] = nullptr;\n  }\n\n  string Mesh :: cd2_default_name = \"default\";\n  string Mesh :: default_bc = \"default\";\n  const string & Mesh :: GetCD2Name (int cd2nr) const\n  {\n    static string defaultstring  = \"default\";\n    if (!cd2names.Size())\n      return defaultstring;\n\n    if (cd2nr < 0 || cd2nr >= cd2names.Size())\n      return defaultstring;\n\n    if (cd2names[cd2nr])\n      return *cd2names[cd2nr];\n    else\n      return defaultstring;\n  }\n\n  void Mesh :: SetNCD3Names( int ncd3n )\n  {\n    if (cd3names.Size())\n      for(int i=0; i<cd3names.Size(); i++)\n\tif(cd3names[i]) delete cd3names[i];\n    cd3names.SetSize(ncd3n);\n    cd3names = 0;\n  }\n\n  void Mesh :: SetCD3Name ( int cd3nr, const string & abcname )\n  {\n    cd3nr--;\n    (*testout) << \"setCD3Name on vertex \" << cd3nr << \" to \" << abcname << endl;\n    if (cd3nr >= cd3names.Size())\n      {\n\tint oldsize = cd3names.Size();\n\tcd3names.SetSize(cd3nr+1);\n\tfor(int i= oldsize; i<= cd3nr; i++)\n\t  cd3names[i] = nullptr;\n      }\n    if (abcname != \"default\")\n      cd3names[cd3nr] = new string(abcname);\n    else\n      cd3names[cd3nr] = nullptr;\n  }\n  \n  int Mesh :: AddCD3Name (const string & aname)\n  {\n    for (int i = 0; i < cd3names.Size(); i++)\n      if (*cd3names[i] == aname)\n        return i;\n    cd3names.Append (new string(aname));\n    return cd3names.Size()-1;\n  }\n  \n  string Mesh :: cd3_default_name = \"default\";\n  static string defaultstring  = \"default\";\n  const string & Mesh :: GetCD3Name (int cd3nr) const\n  {\n    if (!cd3names.Size())\n      return defaultstring;\n\n    if (cd3nr < 0 || cd3nr >= cd3names.Size())\n      return defaultstring;\n\n    if (cd3names[cd3nr])\n      return *cd3names[cd3nr];\n    else\n      return defaultstring;\n  }\n\n\n  Array<string*> & Mesh :: GetRegionNamesCD (int codim)\n  {\n    switch (codim)\n      {\n      case 0: return materials;\n      case 1: return bcnames;\n      case 2: return cd2names;\n      case 3: return cd3names;\n      default: throw Exception(\"don't have regions of co-dimension \"+ToString(codim));\n      }\n  }\n  \n  FlatArray<string*> Mesh :: GetRegionNamesCD (int codim) const\n  {\n    switch (codim)\n      {\n      case 0: return materials;\n      case 1: return bcnames;\n      case 2: return cd2names;\n      case 3: return cd3names;\n      default: throw Exception(\"don't have regions of co-dimension \"+ToString(codim));\n      }\n  }\n\n  std::string_view Mesh :: GetRegionName (const Segment & el) const\n  {\n    return *const_cast<Mesh&>(*this).GetRegionNamesCD(GetDimension()-1)[el.edgenr-1];\n  }\n\n  std::string_view Mesh :: GetRegionName (const Element2d & el) const\n  {\n    // return *const_cast<Mesh&>(*this).GetRegionNamesCD(GetDimension()-2)[GetFaceDescriptor(el).BCProperty()-1];\n\n    auto ind = GetFaceDescriptor(el).BCProperty()-1;\n    auto names = this->GetRegionNamesCD(GetDimension()-2);\n\n    if (!names.Range().Contains(ind))\n      return defaultstring;\n    if (!names[ind])\n      return defaultstring;\n    return *names[ind];\n  }\n\n  std::string_view Mesh :: GetRegionName (const Element & el) const\n  {\n    const auto& names = const_cast<Mesh&>(*this).GetRegionNamesCD(GetDimension()-3);\n    if(names.Size() <= el.GetIndex())\n      return defaultstring;\n    return *const_cast<Mesh&>(*this).GetRegionNamesCD(GetDimension()-3)[el.GetIndex()-1];\n  }\n  \n\n  void Mesh :: SetUserData(const char * id, NgArray<int> & data)\n  {\n    if(userdata_int.Used(id))\n      delete userdata_int[id];\n\n    NgArray<int> * newdata = new NgArray<int>(data);\n\n    userdata_int.Set(id,newdata);      \n  }\n  bool Mesh :: GetUserData(const char * id, NgArray<int> & data, int shift) const\n  {\n    if(userdata_int.Used(id))\n      {\n        if(data.Size() < (*userdata_int[id]).Size()+shift)\n          data.SetSize((*userdata_int[id]).Size()+shift);\n        for(int i=0; i<(*userdata_int[id]).Size(); i++)\n          data[i+shift] = (*userdata_int[id])[i];\n        return true;\n      }\n    else\n      {\n        data.SetSize(0);\n        return false;\n      }\n  }\n  void Mesh :: SetUserData(const char * id, NgArray<double> & data)\n  {\n    if(userdata_double.Used(id))\n      delete userdata_double[id];\n\n    NgArray<double> * newdata = new NgArray<double>(data);\n\n    userdata_double.Set(id,newdata);      \n  }\n  bool Mesh :: GetUserData(const char * id, NgArray<double> & data, int shift) const\n  {\n    if(userdata_double.Used(id))\n      {\n        if(data.Size() < (*userdata_double[id]).Size()+shift)\n          data.SetSize((*userdata_double[id]).Size()+shift);\n        for(int i=0; i<(*userdata_double[id]).Size(); i++)\n          data[i+shift] = (*userdata_double[id])[i];\n        return true;\n      }\n    else\n      {\n        data.SetSize(0);\n        return false;\n      }\n  }\n\n\n\n  void Mesh :: PrintMemInfo (ostream & ost) const\n  {\n    ost << \"Mesh Mem:\" << endl;\n\n    ost << GetNP() << \" Points, of size \" \n        << sizeof (Point3d) << \" + \" << sizeof(POINTTYPE) << \" = \"\n        << GetNP() * (sizeof (Point3d) + sizeof(POINTTYPE)) << endl;\n\n    ost << GetNSE() << \" Surface elements, of size \" \n        << sizeof (Element2d) << \" = \" \n        << GetNSE() * sizeof(Element2d) << endl;\n\n    ost << GetNE() << \" Volume elements, of size \" \n        << sizeof (Element) << \" = \" \n        << GetNE() * sizeof(Element) << endl;\n\n    // ost << \"surfs on node:\";\n    // surfacesonnode.PrintMemInfo (cout);\n\n    ost << \"boundaryedges: \";\n    if (boundaryedges)\n      boundaryedges->PrintMemInfo (cout);\n\n    ost << \"surfelementht: \";\n    if (surfelementht)\n      surfelementht->PrintMemInfo (cout);\n  }\n\n  shared_ptr<Mesh> Mesh :: Mirror ( netgen::Point<3> p_plane, Vec<3> n_plane )\n  {\n    Mesh & m = *this;\n    auto nm_ = make_shared<Mesh>();\n    Mesh & nm = *nm_;\n    nm = m;\n\n    Point3d pmin, pmax;\n    GetBox(pmin, pmax);\n    auto v = pmax-pmin;\n    double eps = v.Length()*1e-8;\n\n    /*\n    auto onPlane = [&] (const MeshPoint & p) -> bool\n    {\n      auto v = p_plane-p;\n      auto l = v.Length();\n      if(l<eps) return true;\n\n      // auto ret = fabs(v*n_plane)/l;\n      return fabs(v*n_plane) < eps;\n    };\n    */\n\n    /*\n    auto mirror = [&] (PointIndex pi) -> PointIndex\n    {\n      auto & p = m[pi];\n\n      auto v = p_plane-p;\n      auto l = v.Length();\n      if(l<eps)\n        return pi;\n\n      if(fabs(v*n_plane)/l < eps)\n        return pi;\n\n      auto new_point = p + 2*(v*n_plane)*n_plane;\n      return nm.AddPoint( new_point, p.GetLayer(), p.Type() );\n    };\n\n    Array<PointIndex, PointIndex> point_map;\n    point_map.SetSize(GetNP());\n    point_map = -1;\n\n    for(auto pi : Range(points))\n      point_map[pi] = mirror(pi);\n    */\n\n    Array<PointIndex, PointIndex> point_map(GetNP());\n    Array<PointIndex, PointIndex> point_map1(GetNP());\n\n    nm.Points().SetSize(0);\n    \n    for(auto pi : Range(points))\n      {\n        auto & p = m[pi];\n        \n        auto v = p_plane-p;\n        auto l = v.Length();\n\n        if(l < eps || fabs(v*n_plane)/l < eps)\n          {\n            auto npi = nm.AddPoint(p, p.GetLayer(), p.Type());\n            point_map[pi] = npi;\n            point_map1[pi] = npi;\n          }\n        else\n          {\n            auto new_point = p + 2*(v*n_plane)*n_plane;\n            point_map1[pi] = nm.AddPoint(p, p.GetLayer(), p.Type());\n            point_map[pi] = nm.AddPoint( new_point, p.GetLayer(), p.Type() );\n          }\n      }\n    \n    for(auto & el : nm.VolumeElements())\n      for(auto i : Range(el.GetNP()))\n        el[i] = point_map1[el[i]];\n    for(auto & el : nm.SurfaceElements())\n      for(auto i : Range(el.GetNP()))\n        el[i] = point_map1[el[i]];\n    for(auto & el : nm.LineSegments())\n      for(auto i : Range(el.GetNP()))\n        el[i] = point_map1[el[i]];\n    \n    for(auto & el : VolumeElements())\n      {\n        auto nel = el;\n        for(auto i : Range(el.GetNP()))\n          nel[i] = point_map[el[i]];\n        nm.AddVolumeElement(nel);\n      }\n\n    for (auto ei : Range(SurfaceElements()))\n    {\n      auto & el = m[ei];\n      auto nel = el;\n      for(auto i : Range(el.GetNP()))\n        nel[i] = point_map[el[i]];\n\n      if(!(nel==el))\n        {\n          nel.Invert();\n          nm.AddSurfaceElement(nel);\n        }\n    }\n\n    for (auto ei : Range(LineSegments()))\n    {\n      auto & el = LineSegments()[ei];\n      auto nel = el;\n      bool is_same = true;\n\n      for(auto i : Range(el.GetNP()))\n      {\n        auto pi = el[i];\n        nel[i] = point_map[pi];\n        if(point_map[pi]!=pi)\n          is_same = false;\n      }\n\n      if(!is_same)\n        nm.AddSegment(nel);\n    }\n\n    nm.ComputeNVertices();\n    return nm_;\n  }\n\n  void AddFacesBetweenDomains(Mesh & mesh)\n  {\n    static Timer timer(\"AddFacesBetweenDomains\"); RegionTimer rt(timer);\n    auto & topo = mesh.GetTopology();\n    auto p2el = mesh.CreatePoint2ElementTable();\n\n    Array<size_t> els_per_domain(mesh.GetNDomains()+1);\n    els_per_domain = 0;\n\n    for(const auto & el : mesh.VolumeElements())\n      els_per_domain[el.GetIndex()]++;\n\n    std::map<tuple<int,int>, int> doms_2_new_face;\n\n    for(const auto & [facei, fd]: Enumerate(mesh.FaceDescriptors()))\n    {\n      auto dom0 = fd.DomainIn();\n      auto dom1 = fd.DomainOut();\n      if(dom0 > dom1)\n        swap(dom0, dom1);\n\n      doms_2_new_face[{dom0, dom1}] = facei+1;\n    }\n\n    for(auto dom : Range(1, 1+mesh.GetNDomains()))\n    {\n      if(els_per_domain[dom] == 0)\n        continue;\n\n      mesh.UpdateTopology();\n\n      mesh.FindOpenElements(dom);\n      for(const auto & openel : mesh.OpenElements())\n      {\n        std::set<ElementIndex> has_p1, has_p2, has_p3;\n        for (auto ei: topo.GetVertexElements(openel[0]))\n          has_p1.insert(ei);\n        for (auto ei: topo.GetVertexElements(openel[1]))\n          has_p2.insert(ei);\n        for (auto ei: topo.GetVertexElements(openel[2]))\n          has_p3.insert(ei);\n\n        std::set<ElementIndex> has_p12, has_all;\n        set_intersection(has_p1.begin(), has_p1.end(),\n                         has_p2.begin(), has_p2.end(),\n                         inserter(has_p12, has_p12.begin()));\n        set_intersection(has_p12.begin(), has_p12.end(),\n                         has_p3.begin(), has_p3.end(),\n                         inserter(has_all, has_all.begin()));\n\n        ArrayMem<ElementIndex, 5> els;\n        for(auto ei : has_all)\n          els.Append(ei);\n\n        if(els.Size() == 2 && mesh[els[0]].GetIndex() != mesh[els[1]].GetIndex())\n        {\n          auto dom0 = mesh[els[0]].GetIndex();\n          auto dom1 = mesh[els[1]].GetIndex();\n          ElementIndex ei0 = els[0];\n          if(dom0 > dom1)\n          {\n            Swap(dom0, dom1);\n            ei0 = els[1];\n          }\n\n          if(dom1 == dom)\n            continue;\n\n          if(doms_2_new_face.count({dom0, dom1}) == 0)\n          {\n            auto fd = FaceDescriptor(-1, dom0, dom1, -1);\n            auto new_si = mesh.GetNFD()+1;\n            fd.SetBCProperty(new_si);\n            auto new_face = mesh.AddFaceDescriptor(fd);\n            mesh.SetBCName(new_si - 1, \"default\");\n            doms_2_new_face[{dom0, dom1}] = new_face;\n          }\n          for(auto face : topo.GetFaces(ei0)) {\n            auto verts = topo.GetFaceVertices(face);\n            if(verts.Contains(openel[0]) && verts.Contains(openel[1]) && verts.Contains(openel[2])) {\n              Element2d sel(static_cast<int>(verts.Size()));\n              sel.SetIndex(doms_2_new_face[{dom0, dom1}]);\n\n              for(auto j : Range(verts.Size()))\n                sel[j] = verts[j];\n              auto normal = Cross(mesh[sel[1]]-mesh[sel[0]], mesh[sel[2]]-mesh[sel[0]]);\n              Vec<3> surf_center = Vec<3>(Center(mesh[sel[0]] , mesh[sel[1]] , mesh[sel[2]]));\n              Vec<3> center(0., 0., 0.);\n              for(auto pi : mesh[ei0].PNums())\n                center += Vec<3>(mesh[pi]);\n              center *= 1.0/mesh[ei0].GetNP();\n              if((normal * (center - surf_center)) < 0)\n                sel.Invert();\n              mesh.AddSurfaceElement(sel);\n              break;\n            }\n          }\n        }\n      }\n    }\n\n\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/meshclass.hpp",
    "content": "#ifndef NETGEN_MESHCLASS_HPP\n#define NETGEN_MESHCLASS_HPP\n\n/**************************************************************************/\n/* File:   meshclass.hpp                                                  */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   20. Nov. 99                                                    */\n/**************************************************************************/\n\n/*\n  The mesh class\n*/\n\n#include<filesystem>\n\n#include <gprim/adtree.hpp>\n#include <gprim/transform3d.hpp>\n\n#include \"meshtype.hpp\"\n#include \"localh.hpp\"\n#include \"topology.hpp\"\n#include \"paralleltop.hpp\"\n\nnamespace netgen\n{\n  class NetgenGeometry;\n  using namespace std;\n\n  static constexpr int  NG_MPI_TAG_MESH = 210;\n  \n\n  enum resthtype { RESTRICTH_FACE, RESTRICTH_EDGE, \n\t\t   RESTRICTH_SURFACEELEMENT, RESTRICTH_POINT, RESTRICTH_SEGMENT };\n\n  class HPRefElement;\n  class CurvedElements;\n  class AnisotropicClusters;\n  class ParallelMeshTopology;\n\n  class MarkedTet;\n  class MarkedPrism;\n  class MarkedIdentification;\n  class MarkedTri;\n  class MarkedQuad;\n\n  typedef Array<MarkedTet,ElementIndex> T_MTETS;\n  typedef NgArray<MarkedPrism> T_MPRISMS;\n  typedef NgArray<MarkedIdentification> T_MIDS;\n  typedef NgArray<MarkedTri> T_MTRIS;\n  typedef NgArray<MarkedQuad> T_MQUADS;\n\n  struct BisectionInfo\n  {\n    unique_ptr<T_MTETS> mtets;\n    unique_ptr<T_MPRISMS> mprisms;\n    unique_ptr<T_MIDS> mids;\n    unique_ptr<T_MTRIS> mtris;\n    unique_ptr<T_MQUADS> mquads;\n\n    BisectionInfo();\n    ~BisectionInfo();\n  };\n  \n  /// 2d/3d mesh\n  class Mesh\n  {\n  public:\n    // typedef Array<MeshPoint, PointIndex> T_POINTS;\n    typedef netgen::T_POINTS T_POINTS;\n\n  private:\n    /// point coordinates\n    T_POINTS points;\n\n    // The communicator for this mesh. Just a dummy if compiled without MPI.  \n    NgMPI_Comm comm;\n    \n    /// line-segments at edges\n    Array<Segment, SegmentIndex> segments;\n    /// surface elements, 2d-inner elements\n    Array<Element2d, SurfaceElementIndex> surfelements;\n    /// volume elements\n    Array<Element, ElementIndex> volelements;\n    /// points will be fixed forever\n    Array<PointIndex> lockedpoints;\n\n\n    /// surface indices at boundary nodes\n    // TABLE<int,PointIndex::BASE> surfacesonnode;\n    /// boundary edges  (1..normal bedge, 2..segment)\n    unique_ptr<INDEX_2_CLOSED_HASHTABLE<int>> boundaryedges;\n    ///\n    unique_ptr<INDEX_2_CLOSED_HASHTABLE<int>> segmentht;\n    ///\n    unique_ptr<INDEX_3_CLOSED_HASHTABLE<int>> surfelementht;\n    unique_ptr<INDEX_3_CLOSED_HASHTABLE<int>> illegal_trigs;\n\n    /// faces of rest-solid\n    NgArray<Element2d> openelements;\n    /// open segments for surface meshing\n    NgArray<Segment> opensegments;\n\n    Array<int> tets_in_qualclass;\n\n\n\n    /**\n       Representation of local mesh-size h (one function per mesh layer)\n    */\n    Array<shared_ptr<LocalH>> lochfunc;\n    ///\n    double hglob;\n    ///\n    double hmin;\n    ///\n    NgArray<double> maxhdomain;\n  \n    /**\n       the face-index of the surface element maps into\n       this table.\n    */\n    Array<FaceDescriptor> facedecoding;\n\n  \n    /**\n       the edge-index of the line element maps into\n       this table.\n    */\n    NgArray<EdgeDescriptor> edgedecoding;\n\n    Array<string*> region_name_cd[4];\n    Array<string*> & materials = region_name_cd[0];\n    Array<string*> & bcnames   = region_name_cd[1];\n    Array<string*> & cd2names  = region_name_cd[2];\n    Array<string*> & cd3names  = region_name_cd[3];\n\n    /*\n    /// sub-domain materials \n    Array<string*> materials;\n\n    /// labels for boundary conditions\n    Array<string*> bcnames;\n\n    /// labels for co dim 2 bboundary conditions\n    Array<string*> cd2names;\n\n    /// labels for co dim 3 bbboundary conditions\n    Array<string*> cd3names;\n    */\n    \n    /// Periodic surface, close surface, etc. identifications\n    unique_ptr<Identifications> ident;\n\n\n    /// number of vertices (if < 0, use np)\n    int numvertices;\n\n    /// geometric search tree for interval intersection search\n    unique_ptr<BoxTree<3, ElementIndex>> elementsearchtree_vol;\n    unique_ptr<BoxTree<3, SurfaceElementIndex>> elementsearchtree_surf;\n    /// time stamp for tree\n    mutable size_t elementsearchtreets[4];\n\n    /// element -> face, element -> edge etc ...\n    MeshTopology topology;\n    /// methods for high order elements\n    unique_ptr<CurvedElements> curvedelems;\n\n    /// nodes identified by close points \n    unique_ptr<AnisotropicClusters> clusters;\n\n    /// space dimension (2 or 3)\n    int dimension;\n  \n    /// changed by every minor modification (addpoint, ...)\n    int timestamp;\n    /// changed after finishing global algorithm (improve, ...)\n    int majortimestamp;\n\n    /// mesh access semaphores.\n    NgMutex mutex;\n    /// mesh access semaphores.\n    NgMutex majormutex;\n\n    SymbolTable< NgArray<int>* > userdata_int;\n    SymbolTable< NgArray<double>* > userdata_double;\n\n\n    mutable NgArray< Point3d > pointcurves;\n    mutable NgArray<int> pointcurves_startpoint;\n    mutable NgArray<double> pointcurves_red,pointcurves_green,pointcurves_blue;\n\n\n    /// start element for point search (GetElementOfPoint)\n    mutable int ps_startelement;\n\n\n#ifdef PARALLEL\n    /// connection to parallel meshes\n    unique_ptr<ParallelMeshTopology> paralleltop;\n#endif\n\n    \n    shared_ptr<NetgenGeometry> geometry;\n\n\n  public:\n    DLL_HEADER void BuildBoundaryEdges(bool rebuild=true);\n\n    DLL_HEADER bool PointContainedIn2DElement(const Point3d & p,\n\t\t\t\t   double lami[3],\n\t\t\t\t   SurfaceElementIndex element,\n\t\t\t\t   bool consider3D = false) const;\n    DLL_HEADER bool PointContainedIn3DElement(const Point3d & p,\n\t\t\t\t   double lami[3],\n                                   ElementIndex element,\n                                   double tol=1e-4) const;\n    DLL_HEADER bool PointContainedIn3DElementOld(const Point3d & p,\n\t\t\t\t      double lami[3],\n                                      ElementIndex element,\n                                      double tol=1e-4) const;\n\n  public:\n    Signal<> updateSignal;\n    BisectionInfo bisectioninfo;\n\n    // store coarse mesh before hp-refinement\n    unique_ptr<NgArray<HPRefElement>> hpelements;\n    unique_ptr<Mesh> coarsemesh;\n  \n  \n    /// number of refinement levels\n    // int mglevels;\n    // number of vertices on each refinement level:\n    NgArray<size_t> level_nv;\n    /// refinement hierarchy\n    Array<PointIndices<2>,PointIndex> mlbetweennodes;\n    /// parent element of volume element\n    Array<ElementIndex, ElementIndex> mlparentelement;\n    /// parent element of surface element\n    Array<SurfaceElementIndex, SurfaceElementIndex> mlparentsurfaceelement;\n\n\n\n    ///\n    DLL_HEADER Mesh();\n    ///\n    DLL_HEADER ~Mesh();\n\n    DLL_HEADER Mesh & operator= (const Mesh & mesh2);\n  \n    ///\n    DLL_HEADER void DeleteMesh();\n  \n    ///\n    void ClearSurfaceElements();\n\n    ///\n    DLL_HEADER void ClearVolumeElements()\n    {\n      volelements.SetSize(0); \n      timestamp = NextTimeStamp();\n    }\n\n    ///\n    DLL_HEADER void ClearSegments()\n    { \n      segments.SetSize(0); \n      timestamp = NextTimeStamp();\n    }\n    \n    ///\n    bool TestOk () const;\n\n    void SetAllocSize(int nnodes, int nsegs, int nsel, int nel);\n    \n\n    DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer = 1);\n    DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer, POINTTYPE type);\n\n    auto GetNP () const { return points.Size(); }\n\n    // [[deprecated(\"Use Point(PointIndex) instead of int !\")]]        \n    MeshPoint & Point(int i) // 1-based\n    {\n      // return points.Elem(i);\n      // return Point (PointIndex(i+PointIndex::BASE-1));\n      return Point (PointIndex(IndexBASE<PointIndex>()+i-1)); \n    } \n    MeshPoint & Point(PointIndex pi) { return points[pi]; }\n    // [[deprecated(\"Use Point(PointIndex) instead of int !\")]]            \n    const MeshPoint & Point(int i) const\n    {\n      // return points.Get(i);\n      // return Point (PointIndex(i+PointIndex::BASE-1));\n      return Point (PointIndex(IndexBASE<PointIndex>()+i-1));       \n    }\n    const MeshPoint & Point(PointIndex pi) const { return points[pi]; }\n\n    const MeshPoint & operator[] (PointIndex pi) const { return points[pi]; }\n    MeshPoint & operator[] (PointIndex pi) { return points[pi]; }\n\n    const T_POINTS & Points() const { return points; }\n    T_POINTS & Points() { return points; }\n\n\n    DLL_HEADER SegmentIndex AddSegment (const Segment & s);\n    void DeleteSegment (int segnr)\n    {\n      segments[segnr-1][0].Invalidate();\n      segments[segnr-1][1].Invalidate();\n    }\n    /*\n    void FullDeleteSegment (int segnr)  // von wem ist das ???\n    {\n      segments.Delete(segnr-PointIndex::BASE);\n    }\n    */\n\n    int GetNSeg () const { return segments.Size(); }\n    // [[deprecated(\"Use LineSegment(SegmentIndex) instead of int !\")]]                \n    Segment & LineSegment(int i) { return segments[i-1]; }\n    // [[deprecated(\"Use LineSegment(SegmentIndex) instead of int !\")]]                    \n    const Segment & LineSegment(int i) const { return segments[i-1]; }\n\n    Segment & LineSegment(SegmentIndex si) { return segments[si]; }\n    const Segment & LineSegment(SegmentIndex si) const { return segments[si]; }\n    const Segment & operator[] (SegmentIndex si) const { return segments[si]; }\n    Segment & operator[] (SegmentIndex si) { return segments[si]; }\n\n    const auto & LineSegments() const { return segments; }\n    auto & LineSegments() { return segments; }\n    \n    Array<Element0d> pointelements;  // only via python interface\n\n    DLL_HEADER SurfaceElementIndex AddSurfaceElement (const Element2d & el);\n    // write to pre-allocated container, thread-safe\n    DLL_HEADER void SetSurfaceElement (SurfaceElementIndex sei, const Element2d & el);\n    \n    [[deprecated(\"Use Delete(SurfaceElementIndex) instead of int !\")]]\n    void DeleteSurfaceElement (int eli)\n    {\n      /*\n      surfelements.Elem(eli).Delete();\n      surfelements.Elem(eli).PNum(1).Invalidate();\n      surfelements.Elem(eli).PNum(2).Invalidate();\n      surfelements.Elem(eli).PNum(3).Invalidate();\n      */\n      surfelements[eli-1].Delete();\n      /*\n      surfelements[eli-1].PNum(1).Invalidate();\n      surfelements[eli-1].PNum(2).Invalidate();\n      surfelements[eli-1].PNum(3).Invalidate();\n      */\n      timestamp = NextTimeStamp();\n    }\n\n    [[deprecated(\"Use Delete(SurfaceElementIndex) instead !\")]]        \n    void DeleteSurfaceElement (SurfaceElementIndex eli)\n    {\n      // for (auto & p : surfelements[eli].PNums()) p.Invalidate();\n      surfelements[eli].Delete();\n      timestamp = NextTimeStamp();\n    }\n    \n    void Delete (SurfaceElementIndex eli)\n    {\n      // for (auto & p : surfelements[eli].PNums()) p.Invalidate();\n      surfelements[eli].Delete();\n      timestamp = NextTimeStamp();\n    }\n\n    auto GetNSE () const { return surfelements.Size(); }\n\n    // [[deprecated(\"Use SurfaceElement(SurfaceElementIndex) instead of int !\")]]    \n    Element2d & SurfaceElement(int i) { return surfelements[i-1]; }\n    // [[deprecated(\"Use SurfaceElement(SurfaceElementIndex) instead of int !\")]]        \n    const Element2d & SurfaceElement(int i) const { return surfelements[i-1]; }\n    // [[deprecated(\"Use mesh[](SurfaceElementIndex) instead !\")]]\n    Element2d & SurfaceElement(SurfaceElementIndex i) { return surfelements[i]; }\n    // [[deprecated(\"Use mesh[](SurfaceElementIndex) instead !\")]]\n    const Element2d & SurfaceElement(SurfaceElementIndex i) const { return surfelements[i]; }\n\n    const Element2d & operator[] (SurfaceElementIndex ei) const\n    { return surfelements[ei]; }\n    Element2d & operator[] (SurfaceElementIndex ei)\n    { return surfelements[ei]; }\n\n    const auto & SurfaceElements() const { return surfelements; }\n    auto & SurfaceElements() { return surfelements; }\n\n    \n    DLL_HEADER void RebuildSurfaceElementLists ();\n    DLL_HEADER void GetSurfaceElementsOfFace (int facenr, Array<SurfaceElementIndex> & sei) const;\n\n    DLL_HEADER ElementIndex AddVolumeElement (const Element & el);\n    // write to pre-allocated container, thread-safe\n    DLL_HEADER void SetVolumeElement (ElementIndex sei, const Element & el);\n\n    auto GetNE () const { return volelements.Size(); }\n\n    // [[deprecated(\"Use VolumeElement(ElementIndex) instead of int !\")]]    \n    Element & VolumeElement(int i) { return volelements[IndexBASE<ElementIndex>()+(i-1)]; }\n    // [[deprecated(\"Use VolumeElement(ElementIndex) instead of int !\")]]        \n    const Element & VolumeElement(int i) const { return volelements[IndexBASE<ElementIndex>()+(i-1)]; }\n    // [[deprecated(\"Use mesh[](VolumeElementIndex) instead !\")]]\n    Element & VolumeElement(ElementIndex i) { return volelements[i]; }\n    // [[deprecated(\"Use mesh[](VolumeElementIndex) instead !\")]]\n    const Element & VolumeElement(ElementIndex i) const { return volelements[i]; }\n\n    const Element & operator[] (ElementIndex ei) const { return volelements[ei]; }\n    Element & operator[] (ElementIndex ei) { return volelements[ei]; }\n\n    ELEMENTTYPE ElementType (ElementIndex i) const \n    { return (volelements[i].Flags().fixed) ? FIXEDELEMENT : FREEELEMENT; }\n\n    const auto & VolumeElements() const { return volelements; }\n    auto & VolumeElements() { return volelements; }\n\n    ///\n    DLL_HEADER double ElementError (int eli, const MeshingParameters & mp) const;\n\n    /// \n    DLL_HEADER void AddLockedPoint (PointIndex pi);\n    ///\n    void ClearLockedPoints ();\n\n    const auto & LockedPoints() const { return lockedpoints; }\n\n    /// Returns number of domains\n    DLL_HEADER int GetNDomains() const;\n    ///\n    int GetDimension() const { return dimension; }\n    DLL_HEADER void SetDimension (int dim); //  { dimension = dim; }\n\n    /// sets internal tables\n    DLL_HEADER void CalcSurfacesOfNode ();\n\n    /// additional (temporarily) fix points \n    void FixPoints (const TBitArray<PointIndex> & fixpoints);\n\n    /**\n       finds elements without neighbour and\n       boundary elements without inner element.\n       Results are stored in openelements.\n       if dom == 0, all sub-domains, else subdomain dom */\n    DLL_HEADER void FindOpenElements (int dom = 0);\n\n  \n    /**\n       finds segments without surface element,\n       and surface elements without neighbours.\n       store in opensegmentsy\n    */\n    DLL_HEADER void FindOpenSegments (int surfnr = 0);\n    /**\n       remove one layer of surface elements\n    */\n    DLL_HEADER void RemoveOneLayerSurfaceElements ();\n\n\n    int GetNOpenSegments () { return opensegments.Size(); }\n    const Segment & GetOpenSegment (int nr) { return opensegments.Get(nr); }\n  \n    /**\n       Checks overlap of boundary\n       return == 1, iff overlap\n    */\n    DLL_HEADER int CheckOverlappingBoundary ();\n    /**\n       Checks consistent boundary\n       return == 0, everything ok\n    */\n    DLL_HEADER int CheckConsistentBoundary () const;\n\n    /*\n      checks element orientation\n    */\n    DLL_HEADER int CheckVolumeMesh () const;\n\n\n    /**\n       finds average h of surface surfnr if surfnr > 0,\n       else of all surfaces.\n    */\n    DLL_HEADER double AverageH (int surfnr = 0) const;\n    /// Calculates localh \n    DLL_HEADER void CalcLocalH (double grading, int layer=1);\n    ///\n    DLL_HEADER void SetLocalH (netgen::Point<3> pmin, netgen::Point<3> pmax, double grading, int layer=1);\n    ///\n    DLL_HEADER void RestrictLocalH (const Point3d & p, double hloc, int layer=1);\n    ///\n    DLL_HEADER void RestrictLocalHLine (const Point3d & p1, const Point3d & p2, \n\t\t\t     double hloc, int layer=1);\n    /// number of elements per radius\n    DLL_HEADER void CalcLocalHFromSurfaceCurvature(double grading, double elperr, int layer=1);\n    ///\n    DLL_HEADER void CalcLocalHFromPointDistances(double grading, int layer=1);\n    ///\n    DLL_HEADER void RestrictLocalH (resthtype rht, int nr, double loch);\n    ///\n    DLL_HEADER void LoadLocalMeshSize (const filesystem::path & meshsizefilename);\n    ///\n    DLL_HEADER void SetGlobalH (double h);\n    ///\n\tDLL_HEADER void SetMinimalH (double h);\n    ///\n\tDLL_HEADER double MaxHDomain (int dom) const;\n    ///\n\tDLL_HEADER void SetMaxHDomain (const NgArray<double> & mhd);\n    ///\n    DLL_HEADER double GetH (const Point3d & p, int layer=1) const;\n    DLL_HEADER double GetH (PointIndex pi) const { return GetH(points[pi], points[pi].GetLayer()); }\n    ///\n    double GetMinH (const Point3d & pmin, const Point3d & pmax, int layer=1);\n    ///\n    bool HasLocalHFunction (int layer=1) { return lochfunc[layer-1] != nullptr; }\n    ///\n    LocalH & LocalHFunction (int layer=1) { return * lochfunc[layer-1]; }\n\n    shared_ptr<LocalH> & GetLocalH(int layer=1) const\n    {\n      if(lochfunc.Size() == 1)\n        return lochfunc[0];\n      return lochfunc[layer-1];\n    }\n    DLL_HEADER void SetLocalH(shared_ptr<LocalH> loch, int layer=1);\n\n    ///\n    bool LocalHFunctionGenerated(int layer=1) const { return (lochfunc[layer-1] != NULL); }\n\n    /// Find bounding box\n    DLL_HEADER void GetBox (Point3d & pmin, Point3d & pmax, int dom = -1) const;\n\n    /// Find bounding box of points of typ ptyp or less\n    DLL_HEADER void GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp ) const;\n\n    ///\n    int GetNOpenElements() const\n    { return openelements.Size(); }\n    ///\n    const Element2d & OpenElement(int i) const\n    { return openelements.Get(i); }\n\n    auto & OpenElements() const { return openelements; }\n\n    auto & OpenElements() { return openelements; }\n    \n    /// are also quads open elements\n    bool HasOpenQuads () const;\n\n    /// split into connected pieces\n\tDLL_HEADER void SplitIntoParts ();\n\n    /// \n\tDLL_HEADER void SplitSeparatedFaces ();\n\n    /// Refines mesh and projects points to true surface\n    // void Refine (int levels, const CSGeometry * geom);\n\n    void ZRefine(const string& name, const Array<double>& slices);\n    \n    bool BoundaryEdge (PointIndex pi1, PointIndex pi2) const\n    {\n      if(!boundaryedges)\n\tconst_cast<Mesh *>(this)->BuildBoundaryEdges();\n      \n      PointIndices<2> i2(pi1, pi2);\n      i2.Sort();\n      return boundaryedges->Used (i2);\n    }\n\n    void DeleteBoundaryEdges ()\n    {\n        boundaryedges = nullptr;\n    }\n\n    bool IsSegment (PointIndex pi1, PointIndex pi2) const\n    {\n      PointIndices<2> i2 (pi1, pi2);\n      i2.Sort();\n      return segmentht->Used (i2);\n    }\n\n    SegmentIndex SegmentNr (PointIndex pi1, PointIndex pi2) const\n    {\n      PointIndices<2> i2(pi1, pi2);\n      i2.Sort();\n      return segmentht->Get (i2);\n    }\n\n\n    /**\n       Remove unused points. etc.\n    */\n    DLL_HEADER void Compress ();\n\n    /// first vertex has lowest index\n    void OrderElements(); \n\n    ///\n\tDLL_HEADER void Save (ostream & outfile) const;\n    ///\n\tDLL_HEADER void Load (istream & infile);\n    ///\n\tDLL_HEADER void Merge (istream & infile, const int surfindex_offset = 0);\n    ///\n\tDLL_HEADER void Save (const filesystem::path & filename) const;\n    ///\n\tDLL_HEADER void Load (const filesystem::path & filename);\n    ///\n\tDLL_HEADER void Merge (const filesystem::path & filename, const int surfindex_offset = 0);\n\n\n    DLL_HEADER void DoArchive (Archive & archive);\n    ///\n\tDLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY);\n\n    ///\n    void ImproveMeshJacobian (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY,\n                              const TBitArray<PointIndex> * usepoint = NULL);\n    ///\n    void ImproveMeshJacobianOnSurface (const MeshingParameters & mp,\n\t\t\t\t       const TBitArray<PointIndex> & usepoint, \n\t\t\t\t       const NgArray< Vec<3>* > & nv,\n\t\t\t\t       OPTIMIZEGOAL goal = OPT_QUALITY,\n\t\t\t\t       const NgArray< idmap_type* > * idmaps = NULL);\n    /**\n       free nodes in environment of openelements \n       for optimiztion\n    */\n    void FreeOpenElementsEnvironment (int layers);\n\n\n    DLL_HEADER double CalcTotalBad (const MeshingParameters & mp);\n    FlatArray<int> GetQualityHistogram() { return tets_in_qualclass; }\n\n    ///\n    bool LegalTet (Element & el) const\n    {\n      if (el.IllegalValid())\n\treturn !el.Illegal();\n      return LegalTet2 (el);\n    }\n    ///\n    bool LegalTet2 (Element & el) const;\n\n\n    ///\n    // Find trigs with same vertices\n    // return: number of illegal trigs\n    int FindIllegalTrigs ();\n\n    bool LegalTrig (const Element2d & el) const;\n    /**\n       if values non-null, return values in 4-double array:\n       triangle angles min/max, tetangles min/max\n       if null, output results on cout\n    */\n\tDLL_HEADER void CalcMinMaxAngle (double badellimit, double * retvalues = NULL);\n\n    /*\n      Marks elements which are dangerous to refine\n      return: number of illegal elements\n    */\n\tDLL_HEADER int MarkIllegalElements (int domain=0);\n\n    /// orient surface mesh, for one sub-domain only\n\tDLL_HEADER void SurfaceMeshOrientation ();\n\n    /// convert mixed element mesh to tet-mesh\n\tDLL_HEADER void Split2Tets();\n\n\n    /// build box-search tree\n    DLL_HEADER void BuildElementSearchTree (int dim);\n    BoxTree<3, ElementIndex>* GetElementSearchTree () const\n    {\n        return elementsearchtree_vol.get();\n    }\n\n    BoxTree<3, SurfaceElementIndex>* GetSurfaceElementSearchTree () const\n    {\n      return elementsearchtree_surf.get();\n    }\n\n    void SetPointSearchStartElement(const int el) const {ps_startelement = el;}\n\n    /// gives element of point, barycentric coordinates\n    DLL_HEADER ElementIndex\n    GetElementOfPoint (const netgen::Point<3> & p,\n                       double * lami,\n                       bool build_searchtree = false,\n                       int index = -1,\n                       bool allowindex = true,\n                       double tol=1e-4) const;\n    DLL_HEADER ElementIndex\n    GetElementOfPoint (const netgen::Point<3> & p,\n                       double * lami,\n                       std::optional<FlatArray<int>> indices,\n                       bool build_searchtree = 0,\n                       bool allowindex = true,\n                       double tol=1e-4) const;\n    DLL_HEADER SurfaceElementIndex\n    GetSurfaceElementOfPoint (const netgen::Point<3> & p,\n                              double * lami,\n                              bool build_searchtree = false,\n                              int index = -1,\n                              bool allowindex = true) const;\n    DLL_HEADER SurfaceElementIndex\n    GetSurfaceElementOfPoint (const netgen::Point<3> & p,\n                              double * lami,\n                              std::optional<FlatArray<int>> indices,\n                              bool build_searchtree = false,\n                              bool allowindex = true) const;\n\n    /// give list of vol elements which are int the box(p1,p2)\n    void GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, \n\t\t\t       Array<ElementIndex> & locels) const;\n\n    ///\n    int AddFaceDescriptor(const FaceDescriptor& fd)\n    { facedecoding.Append(fd); return facedecoding.Size(); }\n\n    int AddEdgeDescriptor(const EdgeDescriptor & fd)\n    { edgedecoding.Append(fd); return edgedecoding.Size() - 1; }\n\n    auto & GetCommunicator() const { return this->comm; }\n    void SetCommunicator(NgMPI_Comm acomm);\n    \n    DLL_HEADER void SplitFacesByAdjacentDomains();\n    DLL_HEADER shared_ptr<Mesh> GetSubMesh(string domains=\"\", string faces=\"\") const;\n\n    ///\n    DLL_HEADER void SetMaterial (int domnr, const string & mat);\n    ///\n    DLL_HEADER const string & GetMaterial (int domnr) const;\n    DLL_HEADER static string defaultmat;\n    const string * GetMaterialPtr (int domnr) const // 1-based\n    {\n      return domnr <= materials.Size() ? materials[domnr-1] : &defaultmat;\n    }\n    \n    DLL_HEADER void SetNBCNames ( int nbcn );\n\n    DLL_HEADER void SetBCName ( int bcnr, const string & abcname );\n\n    DLL_HEADER const string & GetBCName ( int bcnr ) const;\n\n    DLL_HEADER void SetNCD2Names (int ncd2n);\n    DLL_HEADER void SetCD2Name (int cd2nr, const string & abcname);\n\n    DLL_HEADER const string & GetCD2Name (int cd2nr ) const;\n    DLL_HEADER static string cd2_default_name;\n    string * GetCD2NamePtr (int cd2nr ) const\n    {\n      if (cd2nr < cd2names.Size() && cd2names[cd2nr]) return cd2names[cd2nr];\n      return &cd2_default_name;\n    }\n    size_t GetNCD2Names() const { return cd2names.Size(); }\n\n    DLL_HEADER void SetNCD3Names (int ncd3n);\n    DLL_HEADER void SetCD3Name (int cd3nr, const string & abcname);\n    DLL_HEADER int AddCD3Name (const string & aname);\n\n    DLL_HEADER const string & GetCD3Name (int cd3nr ) const;\n    DLL_HEADER static string cd3_default_name;\n    string * GetCD3NamePtr (int cd3nr ) const\n    {\n      if (cd3nr < cd3names.Size() && cd3names[cd3nr]) return cd3names[cd3nr];\n      return &cd3_default_name;\n    }\n    size_t GetNCD3Names() const { return cd3names.Size(); }\n\n    DLL_HEADER static string default_bc;\n    string * GetBCNamePtr (int bcnr) const\n    { return (bcnr < bcnames.Size() && bcnames[bcnr]) ? bcnames[bcnr] : &default_bc; }\n\n\n    DLL_HEADER Array<string*> & GetRegionNamesCD (int codim);\n    DLL_HEADER FlatArray<string*> GetRegionNamesCD (int codim) const;\n\n    DLL_HEADER std::string_view GetRegionName(const Segment & el) const;\n    DLL_HEADER std::string_view GetRegionName(const Element2d & el) const;\n    DLL_HEADER std::string_view GetRegionName(const Element & el) const;\n\n    std::string_view GetRegionName(SegmentIndex ei) const { return GetRegionName((*this)[ei]); }\n    std::string_view GetRegionName(SurfaceElementIndex ei) const { return GetRegionName((*this)[ei]); }\n    std::string_view GetRegionName(ElementIndex ei) const { return GetRegionName((*this)[ei]); }\n\n    DLL_HEADER static string_view defaultmat_sv;\n    std::string_view GetRegionName (int dim, int domnr) // 1-based domnr\n    {\n      domnr--;\n      auto & names = region_name_cd[dimension-dim];\n      if (domnr < names.Size() && names[domnr]) return *names[domnr];\n      return defaultmat_sv;\n    }\n    \n    ///\n    void ClearFaceDescriptors()\n    { facedecoding.SetSize(0); }\n\n    void FreeFaceDescriptors()\n    { facedecoding = Array<FaceDescriptor>(); }\n\n    ///\n    int GetNFD () const\n    { return facedecoding.Size(); }\n\n    const FaceDescriptor & GetFaceDescriptor (const Element2d & el) const\n    { return facedecoding[el.GetIndex()-1]; }\n    \n    const FaceDescriptor & GetFaceDescriptor (int i) const\n    { return facedecoding[i-1]; }      \n    // { return facedecoding.Get(i); }\n\n    auto & FaceDescriptors () const { return facedecoding; }\n\n    const EdgeDescriptor & GetEdgeDescriptor (int i) const\n    { return edgedecoding[i]; }\n\n\n    ///\n    FaceDescriptor & GetFaceDescriptor (int i)\n    { return facedecoding[i-1]; }      \n    // { return facedecoding.Elem(i); }\n\n    int IdentifyPeriodicBoundaries(const string& id_name,\n                                   const string& s1,\n                                   const Transformation<3>& mapping,\n                                   double pointTolerance);\n\n    // #ifdef NONE\n    //   /*\n    //     Identify points pi1 and pi2, due to\n    //     identification nr identnr\n    //   */\n    //   void AddIdentification (int pi1, int pi2, int identnr);\n\n    //   int GetIdentification (int pi1, int pi2) const;\n    //   int GetIdentificationSym (int pi1, int pi2) const;\n    //   ///\n    //   INDEX_2_HASHTABLE<int> & GetIdentifiedPoints () \n    //   { \n    //     return *identifiedpoints; \n    //   }\n\n    //   ///\n    //   void GetIdentificationMap (int identnr, NgArray<int> & identmap) const;\n    //   ///\n    //   void GetIdentificationPairs (int identnr, NgArray<INDEX_2> & identpairs) const;\n    //   ///\n    //   int GetMaxIdentificationNr () const\n    //   { \n    //     return maxidentnr; \n    //   }\n    // #endif\n\n    /// return periodic, close surface etc. identifications\n    Identifications & GetIdentifications () { return *ident; }\n    /// return periodic, close surface etc. identifications\n    const Identifications & GetIdentifications () const { return *ident; }\n    ///\n    bool HasIdentifications() const { return ident != nullptr; }\n\n    DLL_HEADER void InitPointCurve(double red = 1, double green = 0, double blue = 0) const;\n    DLL_HEADER void AddPointCurvePoint(const Point3d & pt) const;\n    DLL_HEADER int GetNumPointCurves(void) const;\n    DLL_HEADER int GetNumPointsOfPointCurve(int curve) const;\n    DLL_HEADER Point3d & GetPointCurvePoint(int curve, int n) const;\n    DLL_HEADER void GetPointCurveColor(int curve, double & red, double & green, double & blue) const;\n\n\n\n\n    /// find number of vertices\n    DLL_HEADER void ComputeNVertices ();\n    /// number of vertices (no edge-midpoints)\n    DLL_HEADER int GetNV () const;\n    /// remove edge points\n    DLL_HEADER void SetNP (int np);\n\n  \n\n    DLL_HEADER Table<ElementIndex, PointIndex> CreatePoint2ElementTable(std::optional<TBitArray<PointIndex>> points = std::nullopt, int domain = 0) const;\n    // DLL_HEADER Table<SurfaceElementIndex, PointIndex> CreatePoint2SurfaceElementTable( int faceindex=0 ) const;\n    DLL_HEADER Table<SurfaceElementIndex, PointIndex> CreatePoint2SurfaceElementTable( int faceindex=0 ) const;\n    DLL_HEADER CompressedTable<SurfaceElementIndex, PointIndex> CreateCompressedPoint2SurfaceElementTable( int faceindex=0 ) const;\n\n    DLL_HEADER bool PureTrigMesh (int faceindex = 0) const;\n    DLL_HEADER bool PureTetMesh () const;\n\n\n    const MeshTopology & GetTopology () const { return topology; }\n    MeshTopology & GetTopology () { return topology; }\n\n    DLL_HEADER void UpdateTopology (NgTaskManager tm = &DummyTaskManager,\n                                    NgTracer tracer = &DummyTracer);\n  \n    class CurvedElements & GetCurvedElements () const\n    { return *curvedelems; }\n    \n    DLL_HEADER void BuildCurvedElements  (const class Refinement * ref, int aorder, bool arational = false);\n    DLL_HEADER void BuildCurvedElements  (int aorder);\n\n    const class AnisotropicClusters & GetClusters () const\n    { return *clusters; }\n\n\n    class CSurfaceArea\n    {\n      const Mesh & mesh;\n      bool valid;\n      double area;\n    public:\n      CSurfaceArea (const Mesh & amesh) \n\t: mesh(amesh), valid(false), area(0.) { ; }\n\n      void Add (const Element2d & sel)\n      {\n\tif (sel.GetNP() == 3)\n\t  area += Cross ( mesh[sel[1]]-mesh[sel[0]],\n\t\t\t  mesh[sel[2]]-mesh[sel[0]] ).Length() / 2;\n\telse\n\t  area += Cross (Vec3d (mesh[sel.PNum(1)], mesh[sel.PNum(3)]),\n\t\t\t Vec3d (mesh[sel.PNum(1)], mesh[sel.PNum(4)])).Length() / 2;;\n      }\n      void ReCalc ()\n      {\n\tarea = 0;\n        /*\n\tfor (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t  Add (mesh[sei]);\n        */\n        for (const Element2d & el : mesh.SurfaceElements())\n          Add (el);\n\tvalid = true;\n      }\n\n      operator double () const { return area; }\n      bool Valid() const { return valid; }\n    };\n\n    CSurfaceArea surfarea;\n    CSurfaceArea & SurfaceArea() { return surfarea; }\n    const CSurfaceArea & SurfaceArea() const { return surfarea; }\n\n\n\n    int GetTimeStamp() const { return timestamp; }\n    void SetNextTimeStamp() \n    { timestamp = NextTimeStamp(); }\n\n    int GetMajorTimeStamp() const { return majortimestamp; }\n    void SetNextMajorTimeStamp() \n    { majortimestamp = timestamp = NextTimeStamp(); }\n\n\n    /// return mutex\n    NgMutex & Mutex ()   { return mutex; }\n    NgMutex & MajorMutex ()   { return majormutex; }\n\n\n    DLL_HEADER shared_ptr<NetgenGeometry> GetGeometry() const;\n    void SetGeometry (shared_ptr<NetgenGeometry> geom) \n    {\n      geometry = geom;\n    }\n\n    ///\n    void SetUserData(const char * id, NgArray<int> & data);\n    ///\n    bool GetUserData(const char * id, NgArray<int> & data, int shift = 0) const;\n    ///\n    void SetUserData(const char * id, NgArray<double> & data);\n    ///\n    bool GetUserData(const char * id, NgArray<double> & data, int shift = 0) const;\n\n    ///\n    friend void OptimizeRestart (Mesh & mesh3d);\n    ///\n    void PrintMemInfo (ostream & ost) const;\n    /// \n    friend class Meshing3;\n\n    // only for saving the geometry\n    enum GEOM_TYPE { NO_GEOM = 0, GEOM_2D = 1, GEOM_CSG = 10, GEOM_STL = 11, GEOM_OCC = 12, GEOM_ACIS = 13 };\n    GEOM_TYPE geomtype;\n  \n\n#ifdef PARALLEL\n    /// returns parallel topology\n    class ParallelMeshTopology & GetParallelTopology () const\n    { return *paralleltop; }\n\n    /// distributes the master-mesh to local meshes\n    DLL_HEADER void Distribute ();\n    DLL_HEADER void Distribute (NgArray<int> & volume_weights, NgArray<int> & surface_weights,\n                                NgArray<int> & segment_weights);\n\n\n    /// find connection to parallel meshes\n    //   void FindExchangePoints () ;\n\n    //   void FindExchangeEdges ();\n    //   void FindExchangeFaces ();\n\n    /// use metis to decompose master mesh \n    DLL_HEADER void ParallelMetis (int nproc); \n    DLL_HEADER void ParallelMetis (NgArray<int> & volume_weights, NgArray<int> & surface_weights,\n                                   NgArray<int> & segment_weights); \n\n    void PartHybridMesh (); \n    void PartDualHybridMesh (); \n    void PartDualHybridMesh2D ();\n\n    /// send mesh from master to local procs\n    void SendRecvMesh ();\n\n    /// send mesh to parallel machine, keep global mesh at master \n    void SendMesh ( ) const;   \n    /// loads a mesh sent from master processor\n    void ReceiveParallelMesh ();\n\n    \n#else\n    void ParallelMetis (int /* nproc */) {}\n    void Distribute () {}\n    void SendRecvMesh () {}\n    void Distribute (NgArray<int> & volume_weights, NgArray<int> & surface_weights, \n      NgArray<int> & segment_weights){ }\n#endif\n\n    Array<int, ElementIndex> vol_partition;\n    NgArray<int> surf_partition;\n    NgArray<int> seg_partition;\n\n    shared_ptr<Mesh> Mirror( netgen::Point<3> p, Vec<3> n );\n\n    private:\n    MemoryTracer mem_tracer = {\"Mesh\",\n      points, \"points\",\n      segments, \"segments\",\n      surfelements, \"surfelements\",\n      volelements, \"volelements\"\n    };\n    public:\n    const MemoryTracer & GetMemoryTracer() { return mem_tracer; }\n  };\n\n  inline ostream& operator<<(ostream& ost, const Mesh& mesh)\n  {\n    ost << \"mesh: \" << endl;\n    mesh.Save(ost);\n    return ost;\n  }\n\n\n\n  FlatArray<T_EDGE> MeshTopology :: GetEdges (SurfaceElementIndex elnr) const\n  {\n    return FlatArray<T_EDGE>(GetNEdges ( (*mesh)[elnr].GetType()), &surfedges[elnr][0]);\n  }\n\n  FlatArray<T_EDGE> MeshTopology :: GetEdges (ElementIndex elnr) const\n  {\n    return FlatArray<T_EDGE>(GetNEdges ( (*mesh)[elnr].GetType()), &edges[elnr][0]);\n  }\n  \n  FlatArray<T_FACE> MeshTopology :: GetFaces (ElementIndex elnr) const\n  {\n    return FlatArray<T_FACE>(GetNFaces ( (*mesh)[elnr].GetType()), &faces[elnr][0]);\n  }\n\n  DLL_HEADER void AddFacesBetweenDomains(Mesh & mesh);\n}\n\n#endif // NETGEN_MESHCLASS_HPP\n"
  },
  {
    "path": "libsrc/meshing/meshfunc.cpp",
    "content": "#include <set>\n\n#include <mystdlib.h>\n#include \"meshing.hpp\"\n#include \"debugging.hpp\"\n#include \"boundarylayer.hpp\"\n\nnamespace netgen\n{\n  extern const char * tetrules[];\n  // extern const char * tetrules2[];\n  extern const char * prismrules2[];\n  extern const char * pyramidrules[];\n  extern const char * pyramidrules2[];\n  extern const char * hexrules[];\n\n  struct MeshingData\n  {\n      int domain;\n\n      // mesh for one domain (contains all adjacent surface elements)\n      unique_ptr<Mesh> mesh;\n\n      // maps from local (domain) mesh to global mesh\n      Array<PointIndex, PointIndex> pmap;\n\n      // Array<INDEX_2> connected_pairs;\n\n      MeshingParameters mp;\n\n      unique_ptr<Meshing3> meshing;\n  };\n\n  // extract surface meshes belonging to individual domains\n  Array<MeshingData> DivideMesh(Mesh & mesh, const MeshingParameters & mp)\n  {\n      static Timer timer(\"DivideMesh\"); RegionTimer rt(timer);\n\n      Array<MeshingData> ret;\n      auto num_domains = mesh.GetNDomains();\n\n      if(num_domains==1 || mp.only3D_domain_nr)\n      {\n          ret.SetSize(1);\n          // no need to divide mesh, just fill in meshing data\n          ret[0].domain = 1;\n          if(mp.only3D_domain_nr)\n              ret[0].domain = mp.only3D_domain_nr;\n\n          ret[0].mesh.reset(&mesh); // careful, this unique_ptr must not delete &mesh! (it will be released in MergeMeshes after meshing)\n          ret[0].mp = mp;\n          return ret;\n      }\n      ret.SetSize(num_domains);\n\n      Array<Array<PointIndex, PointIndex>> ipmap;\n      ipmap.SetSize(num_domains);\n      // auto dim = mesh.GetDimension();\n      auto num_points = mesh.GetNP();\n      auto num_facedescriptors = mesh.GetNFD();\n\n\n      constexpr PointIndex state0 = IndexBASE<PointIndex>()-1; \n      constexpr PointIndex state1 = state0+1;\n      constexpr PointIndex state2 = state0+2;\n      \n      for(auto i : Range(ret))\n      {\n          auto & md = ret[i];\n          md.domain = i+1;\n\n          md.mp = mp;\n          md.mp.maxh = min2 (mp.maxh, mesh.MaxHDomain(md.domain));\n\n          ret[i].mesh = make_unique<Mesh>();\n          auto & m = *ret[i].mesh;\n\n          m.SetLocalH(mesh.GetLocalH());\n\n          ipmap[i].SetSize(num_points);\n          ipmap[i] = state0;   // 0; // PointIndex::INVALID;\n          m.SetDimension( mesh.GetDimension() );\n          m.SetGeometry( mesh.GetGeometry() );\n      }\n\n      // mark interior edge points\n      for(const auto& seg : mesh.LineSegments())\n        {\n          if(seg.domin > 0 && seg.domin == seg.domout)\n            {\n              ipmap[seg.domin-1][seg[0]] = state1; // 1;\n              ipmap[seg.domin-1][seg[1]] = state1; // 1;\n            }\n        }\n\n      // mark used points for each domain, add surface elements (with wrong point numbers) to domain mesh\n      for(const auto & sel : mesh.SurfaceElements())\n      {\n        const auto & fd = mesh.GetFaceDescriptor(sel.GetIndex());\n        int dom_in  = fd.DomainIn();\n        int dom_out = fd.DomainOut();\n\n        for( auto dom : {dom_in, dom_out} )\n        {\n            if(dom<=0)\n              continue;\n\n            auto & sels = ret[dom-1].mesh->SurfaceElements();\n            for(auto pi : sel.PNums())\n              ipmap[dom-1][pi] = state1;  // 1;\n            sels.Append(sel);\n        }\n      }\n\n      // mark used points for already existing volume elements, add them (with wrong point numbers) to domain mesh\n      for(const auto & el : mesh.VolumeElements())\n      {\n        auto dom = el.GetIndex();\n        \n        auto & els = ret[dom-1].mesh->VolumeElements();\n        for(auto pi : el.PNums())\n          ipmap[dom-1][pi] = state1; // 1;\n        els.Append(el);\n      }\n\n      // mark locked/fixed points for each domain TODO: domain bounding box to add only relevant points?\n      for(auto pi : mesh.LockedPoints())\n        for(auto i : Range(ret))\n          ipmap[i][pi] = state2; // 2;\n\n      // add used points to domain mesh, build point mapping\n      for(auto i : Range(ret))\n      {\n          auto & m = *ret[i].mesh;\n          auto & pmap = ret[i].pmap;\n\n          for(auto pi : Range(ipmap[i]))\n            if(ipmap[i][pi] != state0)\n            {\n              const auto& mp = mesh[pi];\n              auto pi_new = m.AddPoint( mp, mp.GetLayer(), mp.Type() );\n              if(ipmap[i][pi] == state2) // 2)\n                mesh.AddLockedPoint(pi_new);\n              ipmap[i][pi] = pi_new;\n              pmap.Append( pi );\n            }\n      }\n\n      // add segments\n      for(auto i : Range(ret))\n      {\n          auto & imap = ipmap[i];\n          auto & m = *ret[i].mesh;\n          for(auto seg : mesh.LineSegments())\n            if(imap[seg[0]].IsValid() && imap[seg[1]].IsValid())\n              {\n                  seg[0] = imap[seg[0]];\n                  seg[1] = imap[seg[1]];\n                  m.AddSegment(seg);\n              }\n      }\n\n      auto & identifications = mesh.GetIdentifications();\n\n      for(auto i : Range(ret))\n      {\n          auto & m = *ret[i].mesh;\n          auto & imap = ipmap[i];\n          auto nmax = identifications.GetMaxNr ();\n          auto & m_ident = m.GetIdentifications();\n\n          for (auto & sel : m.SurfaceElements())\n            for(auto & pi : sel.PNums())\n              pi = imap[pi];\n\n          for (auto & el : m.VolumeElements())\n            for(auto & pi : el.PNums())\n              pi = imap[pi];\n\n          for(auto n : Range(1,nmax+1))\n          {\n              NgArray<INDEX_2> pairs;\n              identifications.GetPairs(n, pairs);\n\n              for(auto pair : pairs)\n              {\n                  auto pi0 = imap[pair[0]];\n                  auto pi1 = imap[pair[1]];\n                  if(!pi0.IsValid() || !pi1.IsValid())\n                      continue;\n\n                  m_ident.Add(pi0, pi1, n);\n              }\n              m_ident.SetType( n, identifications.GetType(n) );\n          }\n      }\n      return ret;\n  }\n\n  // Add between identified surface elements (only consider closesurface identifications)\n  void FillCloseSurface( MeshingData & md)\n  {\n      static Timer timer(\"FillCloseSurface\"); RegionTimer rtimer(timer);\n\n      auto & mesh = *md.mesh;\n      auto & identifications = mesh.GetIdentifications();\n      auto nmax = identifications.GetMaxNr();\n\n      bool have_closesurfaces = false;\n      for(auto i : Range(1,nmax+1))\n          if(identifications.GetType(i) == Identifications::CLOSESURFACES)\n              have_closesurfaces = true;\n      if(!have_closesurfaces)\n          return;\n\n      idmap_type map;\n      std::set<std::tuple<PointIndex,PointIndex,PointIndex>> hex_faces;\n      for(auto identnr : Range(1,nmax+1))\n      {\n          if(identifications.GetType(identnr) != Identifications::CLOSESURFACES)\n              continue;\n\n          identifications.GetMap(identnr, map);\n          mesh.FindOpenElements(md.domain);\n\n          for(auto & sel : mesh.OpenElements())\n          {\n              // For quads: check if this open element is already closed by a hex\n              // this happens when we have identifications in two directions\n              if(sel.GetNP() == 4)\n              {\n                  Element2d face = sel;\n                  face.NormalizeNumbering();\n                  if(hex_faces.count({face[0], face[1], face[2]}))\n                      continue;\n              }\n              bool is_mapped = true;\n              for(auto pi : sel.PNums())\n                  if(!PointIndex(map[pi]).IsValid())\n                      is_mapped = false;\n\n              if(!is_mapped)\n                  continue;\n\n              // insert prism/hex\n              auto np = sel.GetNP();\n              Element el(2*np);\n              std::set<PointIndex> pis;\n              for(auto i : Range(np))\n              {\n                  el[i] = sel[i];\n                  el[i+np] = map[sel[i]];\n                  pis.insert(sel[i]);\n                  pis.insert(map[sel[i]]);\n              }\n\n              // degenerate element (mapped element onto itself, might happen for surface elements connecting two identified faces)\n              if(pis.size() < 2*np)\n                  continue;\n\n              // check if new element is inside current domain\n              auto p0 = mesh[sel[0]];\n              Vec<3> n = -Cross(mesh[sel[1]] - p0, mesh[sel[2]] - p0 );\n\n              if(n*(mesh[el[np]]-p0) < 0.0)\n                  continue;\n\n              el.SetIndex(md.domain);\n              mesh.AddVolumeElement(el);\n              if(el.NP()==8)\n              {\n                  // remember all adjacent faces of the new hex (to skip corresponding openelements accordingly)\n                  for(auto facei : Range(1,7))\n                  {\n                      Element2d face;\n                      el.GetFace(facei, face);\n                      face.NormalizeNumbering();\n                      hex_faces.insert({face[0], face[1], face[2]});\n                  }\n              }\n          }\n      }\n  }\n\n  void CloseOpenQuads( MeshingData & md)\n  {\n    static Timer t(\"CloseOpenQuads\"); RegionTimer rt(t);\n    auto & mesh = *md.mesh;\n    auto domain = md.domain;\n    MeshingParameters & mp = md.mp;\n\n    int oldne;\n    if (multithread.terminate)\n      return;\n    \n    mesh.CalcSurfacesOfNode();\n    mesh.FindOpenElements(domain);\n    \n    if (!mesh.GetNOpenElements())\n      return;\n\n    for (int qstep = 0; qstep <= 3; qstep++)\n     {\n       if (qstep == 0 && !mp.try_hexes) continue;\n       \n       if (mesh.HasOpenQuads())\n         {\n           string rulefile = ngdir;\n           \n           const char ** rulep = NULL;\n           switch (qstep)\n             {\n             case 0:\n               rulep = hexrules;\n               break;\n             case 1:\n               rulep = prismrules2;\n               break;\n             case 2: // connect pyramid to triangle\n               rulep = pyramidrules2;\n               break;\n             case 3: // connect to vis-a-vis point\n               rulep = pyramidrules;\n               break;\n             }\n           \n           Meshing3 meshing(rulep); \n           \n           MeshingParameters mpquad = mp;\n           \n           mpquad.giveuptol = mp.giveuptolopenquads;\n           mpquad.baseelnp = 4;\n           mpquad.starshapeclass = 1000;\n           mpquad.check_impossible = qstep == 1;   // for prisms only (air domain in trafo)\n           \n           \n           for (PointIndex pi : mesh.Points().Range())\n             meshing.AddPoint (mesh[pi], pi);\n\n           NgArray<INDEX_2> connectednodes;\n           for (int nr = 1; nr <= mesh.GetIdentifications().GetMaxNr(); nr++)\n             if (mesh.GetIdentifications().GetType(nr) != Identifications::PERIODIC)\n               {\n                 mesh.GetIdentifications().GetPairs (nr, connectednodes);\n                 for (auto pair : connectednodes)\n                 {\n                   meshing.AddConnectedPair (pair);\n                   meshing.AddConnectedPair ({pair[1], pair[0]});\n                 }\n               }\n           \n           for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n             {\n               Element2d hel = mesh.OpenElement(i);\n               meshing.AddBoundaryElement (hel);\n             }\n           \n           oldne = mesh.GetNE();\n           \n           meshing.GenerateMesh (mesh, mpquad);\n           \n           // for (int i = oldne + 1; i <= mesh.GetNE(); i++)\n           for (ElementIndex i : mesh.VolumeElements().Range().Modify(oldne, 0))\n             mesh.VolumeElement(i).SetIndex (domain);\n           \n           (*testout) \n             << \"mesh has \" << mesh.GetNE() << \" prism/pyramid elements\" << endl;\n           \n           mesh.FindOpenElements(domain);\n         }\n     }\n   \n\n   if (mesh.HasOpenQuads())\n   {\n      if(debugparam.write_mesh_on_error) {\n        md.mesh->Save(\"open_quads_starting_mesh_\"+ToString(md.domain)+\".vol.gz\");\n        GetOpenElements(*md.mesh, md.domain)->Save(\"open_quads_rest_\" + ToString(md.domain)+\".vol.gz\");\n        GetOpenElements(*md.mesh, md.domain, true)->Save(\"open_quads_rest_\" + ToString(md.domain)+\"_only_quads.vol.gz\");\n      }\n      PrintSysError (\"mesh has still open quads\");\n      throw NgException (\"Stop meshing since too many attempts\");\n      // return MESHING3_GIVEUP;\n   }\n  }\n\n\n  void MeshDomain( MeshingData & md)\n  {\n    auto & mesh = *md.mesh;\n    auto domain = md.domain;\n    MeshingParameters & mp = md.mp;\n\n    mesh.CalcSurfacesOfNode();\n    mesh.FindOpenElements(md.domain);\n\n    md.meshing = make_unique<Meshing3>(nullptr);\n    for (PointIndex pi : mesh.Points().Range())\n       md.meshing->AddPoint (mesh[pi], pi);\n\n    for (int i = 1; i <= mesh.GetNOpenElements(); i++)\n       md.meshing->AddBoundaryElement (mesh.OpenElement(i));\n\n    if (mp.delaunay && mesh.GetNOpenElements())\n    {\n      int oldne = mesh.GetNE();\n\n      md.meshing->Delaunay (mesh, domain, mp);\n\n      // for (int i = oldne + 1; i <= mesh.GetNE(); i++)\n      for (ElementIndex i : mesh.VolumeElements().Range().Modify(oldne, 0))\n         mesh.VolumeElement(i).SetIndex (domain);\n\n      PrintMessage (3, mesh.GetNP(), \" points, \",\n         mesh.GetNE(), \" elements\");\n      mesh.FindOpenElements(domain);\n    }\n\n    Box<3> domain_bbox( Box<3>::EMPTY_BOX ); \n   \n    for (auto & sel : mesh.SurfaceElements())\n     {\n       if (sel.IsDeleted() ) continue;\n\n       for (auto pi : sel.PNums())\n         domain_bbox.Add (mesh[pi]);\n     }\n    domain_bbox.Increase (0.01 * domain_bbox.Diam());\n\n    int cntsteps = 0;\n    int meshed;\n    if (mesh.GetNOpenElements())\n     do\n       {\n         if (multithread.terminate)\n           break;\n         \n         mesh.FindOpenElements(domain);\n         PrintMessage (5, mesh.GetNOpenElements(), \" open faces\");\n         // GetOpenElements( mesh, domain )->Save(\"open_\"+ToString(domain)+\"_\"+ToString(cntsteps)+\".vol\");\n         cntsteps++;\n\n\n         if (cntsteps > mp.maxoutersteps) \n         {\n           if(debugparam.write_mesh_on_error)\n           {\n             md.mesh->Save(\"meshing_error_domain_\"+ToString(md.domain)+\".vol.gz\");\n             if(mesh.GetNOpenElements())\n               GetOpenElements(*md.mesh, md.domain)->Save(\"meshing_error_rest_\" + ToString(md.domain)+\".vol.gz\");\n           }\n           throw NgException (\"Stop meshing since too many attempts in domain \" + ToString(md.domain));\n         }\n\n         PrintMessage (1, \"start tetmeshing\");\n\n         Meshing3 meshing(tetrules);\n\n         Array<PointIndex, PointIndex> glob2loc(mesh.GetNP());\n         glob2loc = PointIndex::INVALID;\n\n         for (PointIndex pi : mesh.Points().Range())\n           if (domain_bbox.IsIn (mesh[pi]))\n             glob2loc[pi] = meshing.AddPoint (mesh[pi], pi);\n\n         for (auto sel : mesh.OpenElements())\n           {\n             for(auto & pi : sel.PNums())\n               pi = glob2loc[pi];\n             meshing.AddBoundaryElement (sel);\n           }\n\n         int oldne = mesh.GetNE();\n\n         mp.giveuptol = 15 + 10 * cntsteps; \n         mp.sloppy = 5;\n         meshing.GenerateMesh (mesh, mp);\n         \n         for (auto & el : mesh.VolumeElements().Range(oldne, END))\n           el.SetIndex (domain);\n         \n\n         mesh.CalcSurfacesOfNode();\n         mesh.FindOpenElements(domain);\n\n         // teterrpow = 2;\n         if (mesh.GetNOpenElements() != 0)\n         {\n            meshed = 0;\n            PrintMessage (5, mesh.GetNOpenElements(), \" open faces found\");\n\n            MeshOptimize3d optmesh(mesh, mp, OPT_REST);\n\n            const char * optstr = \"mcmstmcmstmcmstmcm\";\n            for (size_t j = 1; j <= strlen(optstr); j++)\n            {\n               mesh.FindOpenElements();\n               mesh.CalcSurfacesOfNode();\n               mesh.FreeOpenElementsEnvironment(2);\n               mesh.CalcSurfacesOfNode();\n\n               switch (optstr[j-1])\n               {\n               case 'c': optmesh.CombineImprove(); break;\n               case 'd': optmesh.SplitImprove(); break;\n               case 's': optmesh.SwapImprove(); break;\n               case 't': optmesh.SwapImprove2(); break;\n               case 'm': optmesh.ImproveMesh(); break;\n               }\t  \n\n            }\n\n            mesh.FindOpenElements(domain);\n            PrintMessage (3, \"Call remove problem\");\n            RemoveProblem (mesh, domain);\n            mesh.FindOpenElements(domain);\n         }\n         else\n           {\n            meshed = 1;\n            PrintMessage (1, \"Success !\");\n           }\n       }\n    while (!meshed);\n\n    PrintMessage (3, \"Check subdomain \", domain, \" / \", mesh.GetNDomains());\n\n    mesh.FindOpenElements(domain);\n\n    bool res = (mesh.CheckConsistentBoundary() != 0);\n    if (res)\n    {\n      if(debugparam.write_mesh_on_error)\n        md.mesh->Save(\"inconsistent_surface_domain_\"+ToString(md.domain)+\".vol.gz\");\n      PrintError (\"Surface mesh not consistent\");\n      throw NgException (\"Stop meshing since surface mesh not consistent\");\n    }\n    RemoveIllegalElements (mesh, domain);\n    ConformToFreeSegments (mesh, domain);\n  }\n\n  void MergeMeshes( Mesh & mesh, Array<MeshingData> & md )\n  {\n     // todo: optimize: count elements, alloc all memory, copy vol elements in parallel\n     static Timer t(\"MergeMeshes\"); RegionTimer rt(t);\n     if(md.Size()==1)\n     {\n         // assume that mesh was never divided, no need to do anything\n         if(&mesh != md[0].mesh.get())\n             throw Exception(\"Illegal Mesh pointer in MeshingData\");\n\n         md[0].mesh.release();\n         return;\n     }\n\n     mesh.VolumeElements().DeleteAll();\n\n     // Keep identifications in the mesh, except the ones containing inner points\n     // Inner points will be renumbered, the identifcations will not be valid anymore\n     // These inner identifications are inserted at boundary layers when\n     // 4 or more faces meet at a vertex -> insert pyramids to fill the gap\n     // But pyramids are only inserted if the quad edges are identified\n     mesh.GetIdentifications().DeleteInnerPointIdentifications();\n\n     for(auto & m_ : md)\n     {\n         auto first_new_pi = m_.pmap.Range().Next();\n         auto & m = *m_.mesh;\n         Array<PointIndex, PointIndex> pmap(m.Points().Size());\n         for(auto pi : Range(IndexBASE<PointIndex>(), first_new_pi))\n             pmap[pi] = m_.pmap[pi];\n\n         for (auto pi : Range(first_new_pi, m.Points().Range().Next()))\n             pmap[pi] = mesh.AddPoint(m[pi]);\n\n\n         for ( auto el : m.VolumeElements() )\n         {\n             for (auto i : Range(el.GetNP()))\n                 el[i] = pmap[el[i]];\n             el.SetIndex(m_.domain);\n             mesh.AddVolumeElement(el);\n         }\n         // for(const auto& [p1p2, dummy] : m.GetIdentifications().GetIdentifiedPoints())\n         // mesh.GetIdentifications().Add(pmap[p1p2[0]], pmap[p1p2[1]], p1p2[2]);\n         for(const auto& [p1p2, dummy] : m.GetIdentifications().GetIdentifiedPoints())         \n           mesh.GetIdentifications().Add( pmap[ get<0>(p1p2)[0] ], pmap[ get<0>(p1p2)[1]] , get<1>(p1p2) );\n         for(auto i : Range(m.GetIdentifications().GetMaxNr()))\n           {\n             mesh.GetIdentifications().SetType(i+1, m.GetIdentifications().GetType(i+1));\n             if(auto name = m.GetIdentifications().GetName(i+1); name != \"\")\n               mesh.GetIdentifications().SetName(i+1, name);\n           }\n     }\n  }\n\n  void MergeMeshes( Mesh & mesh, FlatArray<Mesh> meshes, PointIndex first_new_pi )\n  {\n     // todo: optimize: count elements, alloc all memory, copy vol elements in parallel\n     static Timer t(\"MergeMeshes\"); RegionTimer rt(t);\n     for(auto & m : meshes)\n     {\n         Array<PointIndex, PointIndex> pmap(m.Points().Size());\n         for(auto pi : Range(IndexBASE<PointIndex>(), first_new_pi))\n             pmap[pi] = pi;\n\n         for (auto pi : Range(first_new_pi, m.Points().Range().Next()))\n             pmap[pi] = mesh.AddPoint(m[pi]);\n\n\n         for ( auto el : m.VolumeElements() )\n         {\n             for (auto i : Range(el.GetNP()))\n                 el[i] = pmap[el[i]];\n             mesh.AddVolumeElement(el);\n         }\n     }\n  }\n\n  // extern double teterrpow; \n  MESHING3_RESULT MeshVolume (const MeshingParameters & mp, Mesh& mesh3d)\n  {\n    static Timer t(\"MeshVolume\"); RegionTimer reg(t);\n\n     mesh3d.Compress();\n\n     if(mesh3d.GetNDomains()==0)\n         return MESHING3_OK;\n\n     auto geo = mesh3d.GetGeometry();\n     for (auto i : Range(std::min(geo->GetNSolids(), (size_t)mesh3d.GetNDomains())))\n       if (auto name = geo->GetSolid(i).properties.name)\n         mesh3d.SetMaterial (i+1, *name);\n\n     for (auto bl : mp.boundary_layers)\n       GenerateBoundaryLayer(mesh3d, bl);\n\n     if (!mesh3d.HasLocalHFunction())\n         mesh3d.CalcLocalH(mp.grading);\n\n     auto md = DivideMesh(mesh3d, mp);\n\n     try\n       {\n     ParallelFor( md.Range(), [&](int i)\n       {\n         try {\n             auto & mesh = *md[i].mesh;\n             if(&mesh != &mesh3d)\n             {\n                mesh.ClearFaceDescriptors();\n                for(auto face_descriptor : mesh3d.FaceDescriptors())\n                    mesh.AddFaceDescriptor(face_descriptor);\n             }\n\n           if (mp.checkoverlappingboundary)\n             if (mesh.CheckOverlappingBoundary())\n             {\n               if(debugparam.write_mesh_on_error)\n                 mesh.Save(\"overlapping_mesh_domain_\"+ToString(md[i].domain)+\".vol.gz\");\n               throw NgException (\"Stop meshing since boundary mesh is overlapping\");\n             }\n\n           if(mesh.GetGeometry()->GetGeomType() == Mesh::GEOM_OCC)\n              FillCloseSurface( md[i] );\n           CloseOpenQuads( md[i] );\n           MeshDomain(md[i]);\n           if(&mesh != &mesh3d)\n               mesh.FreeFaceDescriptors();\n         }\n         catch (const Exception & e) {\n           if(debugparam.write_mesh_on_error)\n             md[i].mesh->Save(\"meshing_error_domain_\"+ToString(md[i].domain)+\".vol.gz\");\n           cerr << \"Meshing of domain \" << i+1 << \" failed with error: \" << e.what() << endl;\n           throw e;\n         }\n       }, md.Size());\n       }\n     catch(...)\n       {\n         MergeMeshes(mesh3d, md);\n         return MESHING3_GIVEUP;\n       }\n\n     MergeMeshes(mesh3d, md);\n\n     MeshQuality3d (mesh3d);\n\n     return MESHING3_OK;\n  }  \n\n\n  MESHING3_RESULT OptimizeVolume (const MeshingParameters & mp, \n\t\t\t\t  Mesh & mesh3d)\n    //\t\t\t\t  const CSGeometry * geometry)\n  {\n    static Timer t(\"OptimizeVolume\"); RegionTimer reg(t);\n  #ifndef EMSCRIPTEN\n    RegionTaskManager rtm(mp.parallel_meshing ? mp.nthreads : 0);\n  #endif // EMSCRIPTEN\n    const char* savetask = multithread.task;\n    multithread.task = \"Optimize Volume\";\n    \n    // int i;\n\n    PrintMessage (1, \"Volume Optimization\");\n\n    /*\n      if (!mesh3d.PureTetMesh())\n      return MESHING3_OK;\n    */\n\n    // (*mycout) << \"optstring = \" << mp.optimize3d << endl;\n    /*\n      const char * optstr = globflags.GetStringFlag (\"optimize3d\", \"cmh\");\n      int optsteps = int (globflags.GetNumFlag (\"optsteps3d\", 2));\n    */\n\n    mesh3d.CalcSurfacesOfNode();\n\n    MeshOptimize3d optmesh(mesh3d, mp);\n\n    // optimize only bad elements first\n    optmesh.SetMinBadness(1000.);\n    bool do_split = mp.optimize3d.find('d') != string::npos;\n    bool do_swap = mp.optimize3d.find('s') != string::npos;\n    bool do_swap2 = mp.optimize3d.find('t') != string::npos;\n    for([[maybe_unused]] auto i : Range(mp.optsteps3d))\n      {\n        auto [total_badness, max_badness, bad_els] = optmesh.UpdateBadness();\n        if(bad_els==0) break;\n        if(do_split) optmesh.SplitImprove();\n        if(do_swap) optmesh.SwapImprove();\n        if(do_swap2) optmesh.SwapImprove2();\n      }\n\n    // Now optimize all elements\n    optmesh.SetMinBadness(0);\n\n    for (auto i : Range(mp.optsteps3d))\n      {\n\tif (multithread.terminate)\n\t  break;\n\n\t// teterrpow = mp.opterrpow;\n\t// for (size_t j = 1; j <= strlen(mp.optimize3d); j++)\n        for (auto j : Range(mp.optimize3d.size()))\n\t  {\n            multithread.percent = 100.* (double(j)/mp.optimize3d.size() + i)/mp.optsteps3d;\n\t    if (multithread.terminate)\n\t      break;\n\n\t    switch (mp.optimize3d[j])\n\t      {\n\t      case 'c': \n          optmesh.SetGoal(OPT_REST);\n          optmesh.CombineImprove();\n          optmesh.SetGoal(OPT_QUALITY);\n          break;\n\t      case 'd': optmesh.SplitImprove(); break;\n\t      case 'D': optmesh.SplitImprove2(); break;\n\t      case 's': optmesh.SwapImprove(); break;\n                // case 'u': optmesh.SwapImproveSurface(mesh3d); break;\n\t      case 't': optmesh.SwapImprove2(); break;\n#ifdef SOLIDGEOM\n\t      case 'm': mesh3d.ImproveMesh(*geometry); break;\n\t      case 'M': mesh3d.ImproveMesh(*geometry); break;\n#else\n\t      case 'm': mesh3d.ImproveMesh(mp); break;\n\t      case 'M': mesh3d.ImproveMesh(mp); break;\n#endif\n\t      case 'j': mesh3d.ImproveMeshJacobian(mp); break;\n\t      }\n\t  }\n\t// mesh3d.mglevels = 1;\n\tMeshQuality3d (mesh3d);\n      }\n  \n    multithread.task = savetask;\n    return MESHING3_OK;\n  }\n\n\n  void ConformToFreeSegments (Mesh & mesh, int domain)\n  {\n    auto geo = mesh.GetGeometry();\n    if(!geo) return;\n    auto n_solids = geo->GetNSolids();\n    if(n_solids < domain) return;\n    if(geo->GetSolid(domain-1).free_edges.Size() == 0)\n      return;\n\n    Array<SegmentIndex> free_segs;\n    for (auto segi : Range(mesh.LineSegments()))\n      if(mesh[segi].domin == domain && mesh[segi].domout == domain)\n        free_segs.Append(segi);\n\n    auto get_nonconforming = [&] (const auto & p2el) {\n      Array<SegmentIndex> nonconforming;\n\n      for (auto segi : free_segs) {\n        auto seg = mesh[segi];\n\n        auto has_p0 = p2el[seg[0]];\n        bool has_both = false;\n\n        for(auto ei : has_p0) {\n          if(mesh[ei].PNums().Contains(seg[1]))\n            has_both = true;\n        }\n\n        if(!has_both)\n          nonconforming.Append(segi);\n      }\n      return nonconforming;\n    };\n\n    auto split_segment = [&] (SegmentIndex segi, const auto & p2el) {\n      auto seg = mesh[segi];\n      auto p_new = Center(mesh[seg[0]], mesh[seg[1]]);\n      double lam[3];\n      ElementIndex ei_start = mesh.GetElementOfPoint(p_new, lam, false, domain);\n\n      if(!ei_start.IsValid()) {\n        PrintMessage(1, \"Could not find volume element with new point\");\n        return;\n      }\n\n      if(mesh[ei_start].IsDeleted())\n        return;\n\n      double max_inside = -1.;\n      ElementIndex ei_max_inside = ElementIndex::INVALID;\n\n      // search for adjacent volume element, where the new point is \"most inside\",\n      // i.e. the minimal barycentric coordinate is maximal\n      for(auto pi : mesh[ei_start].PNums()) {\n        for(auto ei1 : p2el[pi]) {\n          double lam[3];\n\n          if(mesh[ei1].IsDeleted())\n            return;\n          if(!mesh.PointContainedIn3DElement(p_new, lam, ei1))\n            continue;\n\n          double inside = min(min(lam[0], lam[1]), min(lam[2], 1.0-lam[0]-lam[1]));\n          if(inside > max_inside) {\n            max_inside = inside;\n            ei_max_inside = ei1;\n          }\n        }\n      }\n\n      if(max_inside < 1e-4) {\n        PrintMessage(3, \"Could not find volume element with new point inside\");\n        return;\n      }\n\n      // split tet into 4 new tests, with new point inside\n      auto el = mesh[ei_max_inside];\n      if(el.GetNP() != 4) {\n        PrintMessage(3, \"Only tet elements are supported to split around free segments\");\n        return;\n      }\n\n      if(el.IsDeleted()) {\n        PrintMessage(3,\"Element to split is already deleted\");\n        return;\n      }\n\n      auto pi_new = mesh.AddPoint(p_new);\n      auto seg_new0 = seg;\n      auto seg_new1 = seg;\n      seg_new0[1] = pi_new;\n      seg_new1[0] = pi_new;\n\n      mesh[segi][0] = PointIndex::INVALID;\n      mesh.AddSegment(seg_new0);\n      mesh.AddSegment(seg_new1);\n\n\n      int pmap[4][4] = {\n        {0,1,2,4},\n        {1,3,2,4},\n        {0,2,3,4},\n        {0,3,1,4}\n      };\n\n      PointIndex pis[5] = {el[0], el[1], el[2], el[3], pi_new};\n\n      for (auto i : Range(4)) {\n        Element el_new;\n        el_new = el;\n        for (auto j : Range(4))\n          el_new[j] = pis[pmap[i][j]];\n        mesh.AddVolumeElement(el_new);\n      }\n      mesh[ei_max_inside].Delete();\n    };\n\n    size_t last_num_bad_segs = -1;\n    for ([[maybe_unused]] auto i : Range(10)) {\n      auto p2el = mesh.CreatePoint2ElementTable();\n\n      auto bad_segs = get_nonconforming(p2el);\n      auto num_bad_segs = bad_segs.Size();\n\n      if(num_bad_segs == 0)\n        return;\n\n      PrintMessage(3, \"Non-conforming free segments in domain \", domain, \": \", num_bad_segs);\n\n      if(i>=5 || num_bad_segs != last_num_bad_segs) {\n        for(auto i : bad_segs)\n          split_segment(i, p2el);\n        mesh.Compress();\n      }\n\n      MeshingParameters dummymp;\n      MeshOptimize3d optmesh(mesh, dummymp, OPT_CONFORM);\n\n      for ([[maybe_unused]] auto i : Range(3)) {\n        optmesh.ImproveMesh();\n        optmesh.SwapImprove2(true);\n        optmesh.ImproveMesh();\n        optmesh.SwapImprove();\n        optmesh.ImproveMesh();\n        optmesh.CombineImprove();\n      }\n      last_num_bad_segs = num_bad_segs;\n    }\n\n    auto p2el = mesh.CreatePoint2ElementTable();\n    auto bad_segs = get_nonconforming(p2el);\n\n    if(bad_segs.Size() > 0) {\n      auto bad_seg = mesh[bad_segs[0]];\n      if(debugparam.write_mesh_on_error)\n        mesh.Save(\"free_segment_not_conformed_dom_\"+ToString(domain)+\"_seg_\"+ToString(bad_seg[0])+\"_\"+ToString(bad_seg[1])+\".vol.gz\");\n      throw Exception(\"Segment not resolved in volume mesh in domain \" + ToString(domain)+ \", seg: \" + ToString(bad_seg));\n    }\n  }\n\n\n  void RemoveIllegalElements (Mesh & mesh3d, int domain)\n  {\n    static Timer t(\"RemoveIllegalElements\"); RegionTimer reg(t);\n    \n    // return, if non-pure tet-mesh\n    /*\n      if (!mesh3d.PureTetMesh())\n      return;\n    */\n    mesh3d.CalcSurfacesOfNode();\n\n    int nillegal = mesh3d.MarkIllegalElements(domain);\n    if(nillegal)\n      PrintMessage (1, \"Remove Illegal Elements\");\n\n    int oldn = nillegal;\n    int nillegal_min = nillegal;\n\n    MeshingParameters dummymp;\n    MeshOptimize3d optmesh(mesh3d, dummymp, OPT_LEGAL);\n    int it = 10;\n    while (nillegal && (it--) > 0)\n      {\n\tif (multithread.terminate)\n\t  break;\n\n\tPrintMessage (5, nillegal, \" illegal tets\");\n        optmesh.SplitImprove ();\n\n\tmesh3d.MarkIllegalElements();  // test\n\toptmesh.SwapImprove ();\n\tmesh3d.MarkIllegalElements();  // test\n\toptmesh.SwapImprove2 ();\n\n\toldn = nillegal;\n\tnillegal = mesh3d.MarkIllegalElements();\n        nillegal_min = min(nillegal_min, nillegal);\n        if(nillegal > nillegal_min)\n          break;\n\n\tif (oldn != nillegal)\n\t  it = 10;\n      }\n    PrintMessage (5, nillegal, \" illegal tets\");\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/meshfunc.hpp",
    "content": "#ifndef FILE_MESHFUNC\n#define FILE_MESHFUNC\n\n/**************************************************************************/\n/* File:   meshfunc.hpp                                                   */\n/* Author: Johannes Gerstmayr, Joachim Schoeberl                          */\n/* Date:   26. Jan. 98                                                    */\n/**************************************************************************/\n\n#include <mydefs.hpp>\n#include \"meshing3.hpp\"\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n/*\n  Functions for mesh-generations strategies\n */\n\nclass Mesh;\n// class CSGeometry;\n\n/// Build tet-mesh\nDLL_HEADER MESHING3_RESULT MeshVolume (const MeshingParameters & mp, Mesh& mesh3d);\n\n/// Build mixed-element mesh\n// MESHING3_RESULT MeshMixedVolume (MeshingParameters & mp, Mesh& mesh3d);\n\n/// Optimize tet-mesh\nDLL_HEADER MESHING3_RESULT OptimizeVolume (const MeshingParameters & mp, Mesh& mesh3d);\n//\t\t\t       const CSGeometry * geometry = NULL);\n\nDLL_HEADER void RemoveIllegalElements (Mesh & mesh3d, int domain = 0);\nDLL_HEADER void ConformToFreeSegments (Mesh & mesh3d, int domain);\n\n\nenum MESHING_STEP { \n  MESHCONST_ANALYSE = 1,\n  MESHCONST_MESHEDGES = 2,\n  MESHCONST_MESHSURFACE = 3,\n  MESHCONST_OPTSURFACE = 4,\n  MESHCONST_MESHVOLUME = 5,\n  MESHCONST_OPTVOLUME = 6\n};\n} // namespace netgen\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/meshfunc2d.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n\n  DLL_HEADER void Optimize2d (Mesh & mesh, MeshingParameters & mp, int faceindex)\n  {\n    static Timer timer(\"optimize2d\"); RegionTimer reg(timer);\n\n    mesh.CalcSurfacesOfNode();\n\n    bool secondorder = mesh.GetNP() > mesh.GetNV();\n\n\n    if (secondorder)\n      {\n      for (SurfaceElementIndex ei = 0; ei < mesh.GetNSE(); ei++)\n        mesh[ei].SetType(TRIG);\n      }\n    mesh.Compress();\n\n    bool optimize_swap_separate_faces = false;\n    if(!mp.quad)\n    {\n      bool mixed = false;\n      ParallelFor( Range(mesh.GetNSE()), [&] (auto i) NETGEN_LAMBDA_INLINE\n          {\n            if (mesh[SurfaceElementIndex(i)].GetNP() != 3)\n                mixed = true;\n          });\n      if(mixed)\n        optimize_swap_separate_faces = true;\n    }\n\n    if(faceindex)\n      optimize_swap_separate_faces = false;\n\n    const char * optstr = mp.optimize2d.c_str();\n    int optsteps = mp.optsteps2d;\n\n    // reset topology\n    mesh.GetTopology() = MeshTopology(mesh);\n    for (int i = 1; i <= optsteps; i++)\n      for (size_t j = 1; j <= strlen(optstr); j++)\n\t{\n\t  if (multithread.terminate) break;\n          MeshOptimize2d meshopt(mesh);\n          meshopt.SetMetricWeight (mp.elsizeweight);\n          meshopt.SetFaceIndex(faceindex);\n\t  switch (optstr[j-1])\n\t    {\n\t    case 's': \n\t      {  // topological swap\n\n                if(optimize_swap_separate_faces)\n                {\n                  for(auto i : Range(1, mesh.GetNFD()+1))\n                  {\n                    meshopt.SetFaceIndex(i);\n                    meshopt.EdgeSwapping (0);\n                  }\n                }\n                else\n                {\n                  meshopt.EdgeSwapping (0);\n                }\n\t\tbreak;\n\t      }\n\t    case 'S': \n\t      {  // metric swap\n                if(optimize_swap_separate_faces)\n                {\n                  for(auto i : Range(1, mesh.GetNFD()+1))\n                  {\n                    meshopt.SetFaceIndex(i);\n                    meshopt.EdgeSwapping (1);\n                  }\n                }\n                else\n                {\n                  meshopt.EdgeSwapping (1);\n                }\n\t\tbreak;\n\t      }\n\t    case 'm': \n\t      {\n\t\tmeshopt.ImproveMesh(mp);\n\t\tbreak;\n\t      }\n\t    case 'c': \n\t      {\n\t\tmeshopt.CombineImprove();\n\t\tbreak;\n\t      }\n\t    default:\n\t      cerr << \"Optimization code \" << optstr[j-1] << \" not defined\" << endl;\n\t    }  \n\t}\n    mesh.Compress(); // better: compress in individual steps, if necessary\n    if (secondorder)\n      {\n        mesh.GetGeometry()->GetRefinement().MakeSecondOrder(mesh);\n      }\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/meshing.hpp",
    "content": "#ifndef FILE_MESHING\n#define FILE_MESHING\n\n#include \"../include/myadt.hpp\"\n#include \"../include/gprim.hpp\"\n#include \"../include/linalg.hpp\"\n#include \"../include/opti.hpp\"\n\n\nnamespace netgen\n{\n  // extern int printmessage_importance;\n\n  // class CSGeometry;\n  using namespace std;\n  class NetgenGeometry;\n}\n  \n  \n// #include \"msghandler.hpp\"\n// #include \"meshtype.hpp\"\n// #include \"localh.hpp\"\n// #include \"topology.hpp\"\n// #include \"meshclass.hpp\"\n// #include \"global.hpp\"\n\n#include \"meshtool.hpp\"\n\n#include \"ruler2.hpp\"\n#include \"adfront2.hpp\"\n\n\n#include \"meshing2.hpp\"\n#include \"improve2.hpp\"\n\n\n#include \"geomsearch.hpp\"\n#include \"adfront3.hpp\"\n#include \"ruler3.hpp\"\n\n#include \"findip.hpp\"\n#include \"findip2.hpp\"\n\n#include \"meshing3.hpp\"\n#include \"improve3.hpp\"\n\n#include \"curvedelems.hpp\"\n#include \"clusters.hpp\"\n#include \"meshfunc.hpp\"\n\n#include \"bisect.hpp\"\n#include \"hprefinement.hpp\"\n\n#include \"specials.hpp\"\n#include \"validate.hpp\"\n#include \"basegeom.hpp\"\n#include \"surfacegeom.hpp\"\n\n#include \"paralleltop.hpp\"\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/meshing2.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing2.hpp\"\n\n#include \"visual_interface.hpp\"\n\nnamespace netgen\n{\n  static void glrender (int wait)\n  {\n    //  cout << \"plot adfront\" << endl;\n\n    if (multithread.drawing)\n      {\n        // vssurfacemeshing.DrawScene();\n\tRender ();\n\n\tif (wait || multithread.testmode)\n\t  {\n\t    multithread.pause = 1;\n\t  }\n\twhile (multithread.pause);\n      }\n  }\n\n  ostream& operator << (ostream& ost, const MultiPointGeomInfo& mpgi)\n  {\n    for(auto i : Range(mpgi.GetNPGI()))\n      {\n        ost << \"gi[\" << i << \"] = \" << mpgi.GetPGI(i+1) << endl;\n      }\n    return ost;\n  }\n\n  static Array<unique_ptr<netrule>> global_trig_rules;\n  static Array<unique_ptr<netrule>> global_quad_rules;\n\n  \n  Meshing2 :: Meshing2 (const NetgenGeometry& ageo,\n                        const MeshingParameters & mp,\n                        const Box<3> & aboundingbox)\n    : adfront(aboundingbox), boundingbox(aboundingbox), geo(ageo)\n  {\n    static Timer t(\"Mesing2::Meshing2\"); RegionTimer r(t);\n\n    auto & globalrules = mp.quad ? global_quad_rules : global_trig_rules;\n\n    {\n      static mutex mut;\n      lock_guard<mutex> guard(mut);\n      if (!globalrules.Size())\n        {\n          LoadRules (NULL, mp.quad);\n          for (auto & rule : rules)\n            globalrules.Append (make_unique<netrule>(*rule));\n          rules.SetSize(0);\n        }\n      /*\n      else\n        {\n          for (auto i : globalrules.Range())\n            rules.Append (globalrules[i].get());\n        }\n      */\n    }\n    for (auto i : globalrules.Range())\n      rules.Append (make_unique<netrule>(*globalrules[i]));\n\n    // LoadRules (\"rules/quad.rls\");\n    // LoadRules (\"rules/triangle.rls\");\n\n\n    \n    // adfront = new AdFront2(boundingbox);\n    starttime = GetTime();\n\n    maxarea = -1;\n  }\n\n\n  Meshing2 :: ~Meshing2 ()\n  { ; } \n\n  int Meshing2 :: AddPoint (const Point3d & p, PointIndex globind,\n                            MultiPointGeomInfo * mgi,\n                            bool pointonsurface)\n  {\n    //(*testout) << \"add point \" << globind << endl;\n    return adfront.AddPoint (p, globind, mgi, pointonsurface);\n  }\n\n  PointIndex Meshing2 :: GetGlobalIndex(int pi) const\n  {\n    return adfront.GetGlobalIndex(pi);\n  }\n\n  void Meshing2 :: AddBoundaryElement (int i1, int i2,\n\t\t\t\t       const PointGeomInfo & gi1, const PointGeomInfo & gi2)\n  {\n    //    (*testout) << \"add line \" << i1 << \" - \" << i2 << endl;\n    if (!gi1.trignum || !gi2.trignum)\n      {\n\tPrintSysError (\"addboundaryelement: illegal geominfo\");\n      }\n    adfront.AddLine (i1-1, i2-1, gi1, gi2);\n  }\n\n\n\n  void Meshing2 :: StartMesh ()\n  {\n    foundmap.SetSize (rules.Size());\n    canuse.SetSize (rules.Size());\n    ruleused.SetSize (rules.Size());\n\n    foundmap = 0;\n    canuse = 0;\n    ruleused = 0;\n\n    // cntelem = 0;\n    // trials = 0;\n  }\n\n  void Meshing2 :: EndMesh ()\n  {\n    for (int i = 0; i < ruleused.Size(); i++)\n      (*testout) << setw(4) << ruleused[i]\n\t\t << \" times used rule \" << rules[i] -> Name() << endl;\n  }\n\n  void Meshing2 :: SetStartTime (double astarttime)\n  {\n    starttime = astarttime;\n  }\n\n  \n  void Meshing2 :: SetMaxArea (double amaxarea)\n  {\n    maxarea = amaxarea;\n  }\n\n\n  double Meshing2 :: CalcLocalH (const Point<3> & /* p */, double gh) const\n  {\n    return gh;\n  }\n\n  // should be class variables !!(?)\n  // static Vec3d ex, ey;\n  // static Point3d globp1;\n\n  void Meshing2 :: DefineTransformation (const Point<3> & ap1,\n                                         const Point<3> & ap2,\n\t\t\t\t\t const PointGeomInfo * gi1,\n\t\t\t\t\t const PointGeomInfo * gi2)\n  {\n    p1 = ap1;\n    p2 = ap2;\n    auto n1 = geo.GetNormal(gi1->trignum, p1, gi1);\n    auto n2 = geo.GetNormal(gi2->trignum, p2, gi2);\n\n    ez = 0.5 * (n1+n2);\n    ez.Normalize();\n    ex = (p2-p1).Normalize();\n    ez -= (ez*ex)*ex;\n    ez.Normalize();\n    ey = Cross(ez, ex);\n  }\n\n  void Meshing2 :: TransformToPlain (const Point<3> & locpoint, \n\t\t\t\t     const MultiPointGeomInfo & geominfo,\n\t\t\t\t     Point<2> & plainpoint, double h, int & zone)\n  {\n    auto& gi = geominfo.GetPGI(1);\n    auto n = geo.GetNormal(gi.trignum, locpoint, &gi);\n    auto p1p = locpoint - p1;\n    plainpoint(0) = (p1p * ex) / h;\n    plainpoint(1) = (p1p * ey) / h;\n\n    if(n*ez < 0)\n      zone = -1;\n    else\n      zone = 0;\n  }\n\n  int Meshing2 :: TransformFromPlain (const Point<2> & plainpoint,\n\t\t\t\t      Point<3> & locpoint, \n\t\t\t\t      PointGeomInfo & gi, \n\t\t\t\t      double h)\n  {\n    locpoint = p1 + (h*plainpoint(0)) * ex + (h* plainpoint(1)) * ey;\n    if (!geo.ProjectPointGI(gi.trignum, locpoint, gi))\n      gi = geo.ProjectPoint(gi.trignum, locpoint);\n    return 0;\n  }\n\n\n  int Meshing2 :: BelongsToActiveChart (const Point3d & p, \n\t\t\t\t\tconst PointGeomInfo & gi)\n  {\n    return 1;\n  }\n\n\n  int Meshing2 :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi)\n  {\n    gi.trignum = 1;\n    return 0;\n  }\n\n\n  int Meshing2 :: ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, \n\t\t\t\t\t    PointGeomInfo & pgi)\n  {\n    pgi = mpgi.GetPGI(1);\n    return 0;\n  }\n\n\n\n  int Meshing2 :: \n  IsLineVertexOnChart (const Point3d & p1, const Point3d & p2,\n\t\t       int endpoint, const PointGeomInfo & geominfo)\n  {\n    return 1;\n  }\n\n  void Meshing2 ::\n  GetChartBoundary (NgArray<Point<2>> & points, \n\t\t    NgArray<Point<3>> & points3d, \n\t\t    NgArray<INDEX_2> & lines, double h) const\n  {\n    points.SetSize (0);\n    points3d.SetSize (0);\n    lines.SetSize (0);\n  }\n\n  double Meshing2 :: Area () const\n  {\n    return -1;\n  }\n\n\n\n\n\n  MESHING2_RESULT Meshing2 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr, int layer)\n  {\n    static Timer timer(\"surface meshing\"); RegionTimer reg(timer);\n\n    static Timer timer1(\"surface meshing1\");\n    static Timer timer2(\"surface meshing2\");\n    static int timer3 = NgProfiler::CreateTimer (\"surface meshing3\");\n\n    static int ts1 = NgProfiler::CreateTimer (\"surface meshing start 1\");\n    static int ts2 = NgProfiler::CreateTimer (\"surface meshing start 2\");\n    static int ts3 = NgProfiler::CreateTimer (\"surface meshing start 3\");\n\n\n    NgProfiler::StartTimer (ts1);\n\n    NgArray<int> pindex, lindex;\n    NgArray<int> delpoints, dellines;\n\n    NgArray<PointGeomInfo> upgeominfo;  // unique info\n    NgArray<MultiPointGeomInfo> mpgeominfo;  // multiple info\n\n    NgArray<Element2d> locelements;\n\n    int z1, z2, oldnp(-1);\n    bool found;\n    int rulenr(-1);\n\n    const PointGeomInfo * blgeominfo1;\n    const PointGeomInfo * blgeominfo2;\n\n    bool morerisc;\n    bool debugflag;\n\n    // double h;\n\n    auto locpointsptr = make_shared<NgArray<Point<3>>>();\n    auto& locpoints = *locpointsptr;\n    NgArray<int> legalpoints;\n    auto plainpointsptr = make_shared<NgArray<Point<2>>>();\n    auto& plainpoints = *plainpointsptr;\n    NgArray<int> plainzones;\n    auto loclinesptr = make_shared<NgArray<INDEX_2>>();\n    auto &loclines = *loclinesptr;\n    int trials = 0, nfaces = 0;\n    int oldnl = 0;\n\n    UpdateVisSurfaceMeshData(oldnl, locpointsptr, loclinesptr, plainpointsptr);\n\n    int qualclass;\n\n\n\n    // test for 3d overlaps\n    BoxTree<3> surfeltree (boundingbox.PMin(),\n                           boundingbox.PMax());\n\n    NgArray<int> intersecttrias;\n    NgArray<Point3d> critpoints;\n\n    // test for doubled edges\n    //INDEX_2_HASHTABLE<int> doubleedge(300000);\n\n\n    testmode = 0;\n\n    StartMesh();\n\n    NgArray<Point<2>> chartboundpoints;\n    NgArray<Point<3>> chartboundpoints3d;\n    NgArray<INDEX_2> chartboundlines;\n\n    // illegal points: points with more then 50 elements per node\n    int maxlegalpoint(-1), maxlegalline(-1);\n    NgArray<int,PointIndex::BASE> trigsonnode;\n    NgArray<int,PointIndex::BASE> illegalpoint;\n\n    trigsonnode.SetSize (mesh.GetNP());\n    illegalpoint.SetSize (mesh.GetNP());\n\n    trigsonnode = 0;\n    illegalpoint = 0;\n  \n    double totalarea = Area ();\n    double meshedarea = 0;\n\n\n    // search tree for surface elements:\n    /*\n    for (sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tconst Element2d & sel = mesh[sei];\n\n\tif (sel.IsDeleted()) continue;\n\n\tif (sel.GetIndex() == facenr)\n\t  {\n\t    Box<3> box;\n\t    box.Set ( mesh[sel[0]] );\n\t    box.Add ( mesh[sel[1]] );\n\t    box.Add ( mesh[sel[2]] );\n\t    surfeltree.Insert (box, sei);\n\t  }\n      }\n    */\n    Array<SurfaceElementIndex> seia;\n    mesh.GetSurfaceElementsOfFace (facenr, seia);\n    for (int i = 0; i < seia.Size(); i++)\n      {\n\tconst Element2d & sel = mesh[seia[i]];\n\n\tif (sel.IsDeleted()) continue;\n\n\tBox<3> box;\n\tbox.Set ( mesh[sel[0]] );\n\tbox.Add ( mesh[sel[1]] );\n\tbox.Add ( mesh[sel[2]] );\n\tsurfeltree.Insert (box, seia[i]);\n      }\n\n    NgProfiler::StopTimer (ts1);\n    NgProfiler::StartTimer (ts2);\n\n    if (totalarea > 0 || maxarea > 0)\n      meshedarea = mesh.SurfaceArea();\n      /*\n      for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t{\n\t  const Element2d & sel = mesh[sei];\n\t  if (sel.IsDeleted()) continue;\n\t\n\t  double trigarea = Cross ( mesh[sel[1]]-mesh[sel[0]],\n\t\t\t\t    mesh[sel[2]]-mesh[sel[0]] ).Length() / 2;\n\t  \n\t  \n\t  if (sel.GetNP() == 4)\n\t    trigarea += Cross (Vec3d (mesh.Point (sel.PNum(1)),\n\t\t\t\t      mesh.Point (sel.PNum(3))),\n\t\t\t       Vec3d (mesh.Point (sel.PNum(1)),\n\t\t\t\t      mesh.Point (sel.PNum(4)))).Length() / 2;;\n\t  meshedarea += trigarea;\n\t}\n      */\n      // cout << \"meshedarea = \" << meshedarea << \" =?= \" \n      // << mesh.SurfaceArea() << endl;\n\n    NgProfiler::StopTimer (ts2);\n    NgProfiler::StartTimer (ts3);\n\n    const char * savetask = multithread.task;\n    multithread.task = \"Surface meshing\";\n\n    adfront.SetStartFront ();\n\n\n    int plotnexttrial = 999;\n\n    double meshedarea_before = meshedarea;\n\n    NgProfiler::StopTimer (ts3);\n\n    static Timer tloop(\"surfacemeshing mainloop\");\n    // static Timer tgetlocals(\"surfacemeshing getlocals\");\n    {\n      RegionTimer rloop(tloop);\n    while (!adfront.Empty() && !multithread.terminate)\n      {\n\t// RegionTimer reg1 (timer1);\n\n\tif (multithread.terminate)\n\t  throw NgException (\"Meshing stopped\");\n\n\t// known for STL meshing\n\tif (totalarea > 0)\n\t  multithread.percent = 100 * meshedarea / totalarea;\n\t/*\n\t  else\n\t  multithread.percent = 0;\n\t*/\n\n\tlocpoints.SetSize0();\n\tloclines.SetSize0();\n\tpindex.SetSize0();\n\tlindex.SetSize0();\n\tdelpoints.SetSize0();\n\tdellines.SetSize0();\n\tlocelements.SetSize0();\n\n\n\n\t// plot statistics\n\tif (trials > plotnexttrial)\n\t  {\n\t    PrintMessage (5, \n\t\t\t  \"faces = \", nfaces,\n\t\t\t  \" trials = \", trials,\n\t\t\t  \" elements = \", mesh.GetNSE(),\n\t\t\t  \" els/sec = \",\n\t\t\t  (mesh.GetNSE() / (GetTime() - starttime + 0.0001)));\n\t    plotnexttrial += 1000;\n\t  }\n\n\n\t// unique-pgi, multi-pgi\n\tupgeominfo.SetSize0();\n\tmpgeominfo.SetSize0();\n\n\n\tnfaces = adfront.GetNFL();\n\ttrials ++;\n    \n\n\tif (trials % 1000 == 0)\n\t  {\n\t    (*testout) << \"\\n\";\n\t    for (int i = 1; i <= canuse.Size(); i++)\n\t      {\n\t\t(*testout) << foundmap.Get(i) << \"/\" \n\t\t\t   << canuse.Get(i) << \"/\"\n\t\t\t   << ruleused.Get(i) << \" map/can/use rule \" << rules[i-1]->Name() << \"\\n\";\n\t      }\n\t    (*testout) << \"\\n\";\n\t  }\n\n        Point<3> p1, p2;\n\tint baselineindex = adfront.SelectBaseLine (p1, p2, blgeominfo1, blgeominfo2, qualclass);\n\n\tfound = 1;\n\n\tdouble his = Dist (p1, p2);\n\n\tPoint<3> pmid = Center (p1, p2);\n\tdouble hshould = CalcLocalH (pmid, mesh.GetH (pmid, layer));\n\tif (gh < hshould) hshould = gh;\n\n\tmesh.RestrictLocalH (pmid, hshould);\n\n\tdouble h = hshould;\n\n\tdouble hinner = (3 + qualclass) * max2 (his, hshould);\n\n        // tgetlocals.Start();\n\tadfront.GetLocals (baselineindex, locpoints, mpgeominfo, loclines, \n\t\t\t     pindex, lindex, 2*hinner);\n        // tgetlocals.Stop();\n\n\t// RegionTimer reg2 (timer2);\n\t//(*testout) << \"h for locals: \" << 2*hinner << endl;\n\t\n\n\t//(*testout) << \"locpoints \" << locpoints << endl;\n\n\tif (qualclass > mp.giveuptol2d)\n\t  {\n\t    PrintMessage (3, \"give up with qualclass \", qualclass);\n\t    PrintMessage (3, \"number of frontlines = \", adfront.GetNFL());\n\t    // throw NgException (\"Give up 2d meshing\");\n\t    break;\n\t  }\n\n\t/*\n\tif (found && qualclass > 60)\n\t  {\n\t    found = 0;\n\t  }\n\t*/\n\t//      morerisc = ((qualclass > 20) && (qualclass % 2 == 1));\n\t//      morerisc = 1;\n\tmorerisc = 0;\n\n\n\tPointIndex gpi1 = adfront.GetGlobalIndex (pindex.Get(loclines[0].I1()));\n\tPointIndex gpi2 = adfront.GetGlobalIndex (pindex.Get(loclines[0].I2()));\n\n\n\tdebugflag = \n\t  ( \n\t   debugparam.haltsegment &&\n\t   ( ((debugparam.haltsegmentp1 == gpi1) && (debugparam.haltsegmentp2 == gpi2)) || \n\t     ((debugparam.haltsegmentp1 == gpi2) && (debugparam.haltsegmentp2 == gpi1))) \n\t   ) \n\t  ||\n\t  (\n\t   debugparam.haltnode &&\n\t   ( (debugparam.haltsegmentp1 == gpi1) || (debugparam.haltsegmentp2 == gpi1))\n\t   );\n\t\n      \n\tif (debugparam.haltface && debugparam.haltfacenr == facenr)\n\t  {\n\t    debugflag = 1;\n\t    cout << \"set debugflag\" << endl;\n\t  }\n\t\n\tif (debugparam.haltlargequalclass && qualclass == 50)\n\t  debugflag = 1;\n\n\t// problem recognition !\n\tif (found && \n\t    (gpi1 < illegalpoint.Size()+IndexBASE<PointIndex>()) && \n\t    (gpi2 < illegalpoint.Size()+IndexBASE<PointIndex>()) )\n\t  {\n\t    if (illegalpoint[gpi1] || illegalpoint[gpi2])\n\t      found = 0;\n\t  }\n\n\n\t// Point2d p12d, p22d;\n\n\tif (found)\n\t  {\n\t    oldnp = locpoints.Size();\n\t    oldnl = loclines.Size();\n\n            UpdateVisSurfaceMeshData(oldnl);\n            \n\t    if (debugflag)\n\t      (*testout) << \"define new transformation\" << endl;\n\n\t    DefineTransformation (p1, p2, blgeominfo1, blgeominfo2);\n\t  \n\t    plainpoints.SetSize (locpoints.Size());\n\t    plainzones.SetSize (locpoints.Size());\n\n\t    // (*testout) << endl;\n\n\t    if (debugflag)\n\t      {\n\t\t*testout << \"3d->2d transformation\" << endl;\n\t\t*testout << \"3d points: \" << endl << locpoints << endl;\n\t      }\n\n            {\n              // RegionTimer reg2 (timer2);\n              for (size_t i = 0; i < locpoints.Size(); i++)\n                {\n                  Point<2> pp;\n                  TransformToPlain (locpoints[i], mpgeominfo[i],\n                                    pp, h, plainzones[i]);\n                  plainpoints[i] = pp;\n                }\n            }\n            /*\n\t    for (int i = 1; i <= locpoints.Size(); i++)\n\t      {\n\t\t// (*testout) << \"pindex(i) = \" << pindex[i-1] << endl;\n\t\tTransformToPlain (locpoints.Get(i), \n\t\t\t\t  mpgeominfo.Get(i),\n\t\t\t\t  plainpoints.Elem(i), h, plainzones.Elem(i));\n\t\t//\t\t(*testout) << mpgeominfo.Get(i).GetPGI(1).u << \" \" << mpgeominfo.Get(i).GetPGI(1).v << \" \";\n\t\t//\t\t(*testout) << plainpoints.Get(i).X() << \" \" << plainpoints.Get(i).Y() << endl;\n\t\t//(*testout) << \"transform \" << locpoints.Get(i) << \" to \" << plainpoints.Get(i).X() << \" \" << plainpoints.Get(i).Y() << endl;\n\t      }\n            */\n\t    //\t    (*testout) << endl << endl << endl;\n\n\n\t    if (debugflag)\n\t      *testout << \"2d points: \" << endl << plainpoints << endl;\n\n\n\t    // p12d = plainpoints.Get(1);\n\t    // p22d = plainpoints.Get(2);\n\n\t    /*\n\t    // last idea on friday\n\t    plainzones.Elem(1) = 0;\n\t    plainzones.Elem(2) = 0;\n\t    */\n\n\n\t    /*\n\t    // old netgen:\n\t    for (i = 2; i <= loclines.Size(); i++)  // don't remove first line\n\t    {\n\t    z1 = plainzones.Get(loclines.Get(i).I1());\n\t    z2 = plainzones.Get(loclines.Get(i).I2());\n\t      \n\t    if (z1 && z2 && (z1 != z2) || (z1 == -1) || (z2 == -1) )\n\t    {\n\t    loclines.DeleteElement(i);\n\t    lindex.DeleteElement(i);\n\t    oldnl--;\n\t    i--;\n\t    }\n\t    }\n\n\t    // \t  for (i = 1; i <= plainpoints.Size(); i++)\n\t    // \t    if (plainzones.Elem(i) == -1)\n\t    // \t      plainpoints.Elem(i) = Point2d (1e4, 1e4);\n\t    */\n\t  \n\t  \n\t    for (int i = 2; i <= loclines.Size(); i++)  // don't remove first line\n\t      {\n\t\t// (*testout) << \"loclines(i) = \" << loclines.Get(i).I1() << \" - \" << loclines.Get(i).I2() << endl;\n\t\tz1 = plainzones.Get(loclines.Get(i).I1());\n\t\tz2 = plainzones.Get(loclines.Get(i).I2());\n\t      \n\t      \n\t\t// one inner point, one outer\n\t\tif ( (z1 >= 0) != (z2 >= 0))\n\t\t  {\n\t\t    int innerp = (z1 >= 0) ? 1 : 2;\n\t\t    if (IsLineVertexOnChart (locpoints.Get(loclines.Get(i).I1()),\n\t\t\t\t\t     locpoints.Get(loclines.Get(i).I2()),\n\t\t\t\t\t     innerp,\n\t\t\t\t\t     adfront.GetLineGeomInfo (lindex.Get(i), innerp)))\n\t\t      // pgeominfo.Get(loclines.Get(i).I(innerp))))\n\t\t      {\t\t\n\n\t\t\tif (!morerisc)\n\t\t\t  {\n\t\t\t    // use one end of line\n\t\t\t    int pini = loclines.Get(i).I(innerp);\n\t\t\t    int pouti = loclines.Get(i).I(3-innerp);\n\t\t\t  \n\t\t\t    const auto& pin = plainpoints.Get(pini);\n\t\t\t    const auto& pout = plainpoints.Get(pouti);\n\t\t\t    auto v = pout - pin;\n\t\t\t    double len = v.Length();\n\t\t\t    if (len <= 1e-6)\n\t\t\t      (*testout) << \"WARNING(js): inner-outer: short vector\" << endl;\n\t\t\t    else\n\t\t\t      v /= len;\n\t\t\t  \n\t\t\t    /*\n\t\t\t    // don't elongate line towards base-line !!\n\t\t\t    if (Vec2d (pin, p12d) * v > 0 && \n\t\t\t    Vec2d (pin, p22d) * v > 0)\n\t\t\t    v *= -1;  \n\t\t\t    */\n\n\t\t\t    Point<2> newpout = pin + 1000. * v;\n\t\t\t    newpout = pout;\n\n\t\t\t  \n\t\t\t    plainpoints.Append (newpout);\n\t\t\t    auto pout3d = locpoints.Get(pouti);\n\t\t\t    locpoints.Append (pout3d);\n\n\t\t\t    plainzones.Append (0);\n\t\t\t    pindex.Append (-1);\n\t\t\t    oldnp++;\n\t\t\t    loclines.Elem(i).I(3-innerp) = oldnp;\n\t\t\t  }\n\t\t\telse\n\t\t\t  plainzones.Elem(loclines.Get(i).I(3-innerp)) = 0;\n\t\t\t\n\n\t\t\t//\t\t  (*testout) << \"inner - outer correction\" << endl;\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\t// remove line\n\t\t\tloclines.DeleteElement(i);\n\t\t\tlindex.DeleteElement(i);\n\t\t\toldnl--;\n\t\t\ti--;\n\t\t      }\t\t\t\n\t\t  }\n\t      \n\t\telse if ( (z1 > 0 && z2 > 0 && (z1 != z2)) || ((z1 < 0) && (z2 < 0)) )\n\t\t  {\n\t\t    loclines.DeleteElement(i);\n\t\t    lindex.DeleteElement(i);\n\t\t    oldnl--;\n\t\t    i--;\n\t\t  }\n\t      }\n\t  \n\n\n\n\n\t    legalpoints.SetSize(plainpoints.Size());\n            legalpoints = 1;\n            /*\n\t    for (int i = 1; i <= legalpoints.Size(); i++)\n\t      legalpoints.Elem(i) = 1;\n            */\n            \n\t    double avy = 0;\n\t    for (size_t i = 0; i < plainpoints.Size(); i++)\n\t      avy += plainpoints[i][1];\n\t    avy *= 1./plainpoints.Size();\n\t\t\n\n\t    for (auto i : Range(plainpoints))\n\t      {\n\t\tif (plainzones[i] < 0)\n\t\t  {\n\t\t    plainpoints[i] = {1e4, 1e4};\n\t\t    legalpoints[i] = 0;\n\t\t  }\n\t\tif (pindex[i] == -1)\n\t\t  {\n\t\t    legalpoints[i] = 0;\n\t\t  }\n\t\t    \n\n\t\tif (plainpoints[i][1] < -1e-10*avy) // changed\n\t\t  {\n\t\t    legalpoints[i] = 0;\n\t\t  }\n\t      }\n\t    /*\n\t      for (i = 3; i <= plainpoints.Size(); i++)\n\t      if (sqr (plainpoints.Get(i).X()) + sqr (plainpoints.Get(i).Y())\n\t      > sqr (2 + 0.2 * qualclass))\n\t      legalpoints.Elem(i) = 0;\n\t    */  \n\n\t    /*\t  \n\t\t int clp = 0;\n\t\t for (i = 1; i <= plainpoints.Size(); i++)\n\t\t if (legalpoints.Get(i))\n\t\t clp++;\n\t\t (*testout) << \"legalpts: \" << clp << \"/\" << plainpoints.Size() << endl; \n\n\t\t // sort legal/illegal lines\n\t\t int lastleg = 2;\n\t\t int firstilleg = oldnl;\n\n\t\t while (lastleg < firstilleg)\n\t\t {\n\t\t while (legalpoints.Get(loclines.Get(lastleg).I1()) &&\n\t\t legalpoints.Get(loclines.Get(lastleg).I2()) &&\n\t\t lastleg < firstilleg)\n\t\t lastleg++;\n\t\t while ( ( !legalpoints.Get(loclines.Get(firstilleg).I1()) ||\n\t\t !legalpoints.Get(loclines.Get(firstilleg).I2())) &&\n\t\t lastleg < firstilleg)\n\t\t firstilleg--;\n\t      \n\t\t if (lastleg < firstilleg)\n\t\t {\n\t\t swap (loclines.Elem(lastleg), loclines.Elem(firstilleg));\n\t\t swap (lindex.Elem(lastleg), lindex.Elem(firstilleg));\n\t\t }\n\t\t }\n\n\t\t (*testout) << \"leglines \" << lastleg << \"/\" << oldnl << endl;\n\t    */\n\t\n\n\t    GetChartBoundary (chartboundpoints, \n\t\t\t      chartboundpoints3d,\n\t\t\t      chartboundlines, h);\n\n\t    oldnp = plainpoints.Size();\n\n\t    maxlegalpoint = locpoints.Size();\n\t    maxlegalline = loclines.Size();\n\n\n\n\t    if (mp.checkchartboundary)\n\t      {\n\t\tfor (int i = 1; i <= chartboundpoints.Size(); i++)\n\t\t  {\n                    pindex.Append(-1);\n\t\t    plainpoints.Append (chartboundpoints.Get(i));\n\t\t    locpoints.Append (chartboundpoints3d.Get(i));\n\t\t    legalpoints.Append (0);\n\t\t  }\n\t      \n\n\t\tfor (int i = 1; i <= chartboundlines.Size(); i++)\n\t\t  {\n\t\t    INDEX_2 line (chartboundlines.Get(i).I1()+oldnp,\n\t\t\t\t  chartboundlines.Get(i).I2()+oldnp);\n\t\t    loclines.Append (line);\n\t\t    //\t      (*testout) << \"line: \" << line.I1() << \"-\" << line.I2() << endl;\n\t\t  }\n\t      }\n\n\t    oldnl = loclines.Size();\n\t    oldnp = plainpoints.Size();\n\t  }\n\n\n\t/*\n\t  if (qualclass > 100)\n\t  {\n\t  multithread.drawing = 1;\n\t  glrender(1);\n\t  cout << \"qualclass 100, nfl = \" << adfront.GetNFL() << endl;\n\t  }\n\t*/\n\n\tif (found)\n\t  {\n            // static Timer t(\"ApplyRules\");\n            // RegionTimer r(t);\n\t    rulenr = ApplyRules (plainpoints, legalpoints, maxlegalpoint,\n\t\t\t\t loclines, maxlegalline, locelements,\n\t\t\t\t dellines, qualclass, mp);\n\n\t    //\t    (*testout) << \"Rule Nr = \" << rulenr << endl;\n\t    if (!rulenr)\n\t      {\n\t\tfound = 0;\n\t\tif ( debugflag || debugparam.haltnosuccess )\n\t\t  PrintWarning (\"no rule found\");\n\t      }\n\t  }\n      \n\tNgProfiler::RegionTimer reg3 (timer3);\n\n\n\tfor (int i = 1; i <= locelements.Size() && found; i++)\n\t  {\n\t    const Element2d & el = locelements.Get(i);\n\n\t    for (int j = 1; j <= el.GetNP(); j++)\n\t      // if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1)\n              if (el.PNum(j) < IndexBASE<PointIndex>()+oldnp && pindex.Get(el.PNum(j)) == -1)\n\t\t{\n\t\t  found = 0;\n\t\t  PrintSysError (\"meshing2, index missing\");\n\t\t}\n\t  }\n\n\n\tif (found)\n\t  {\n\t    locpoints.SetSize (plainpoints.Size());\n\t    upgeominfo.SetSize(locpoints.Size());\n\n\t    for (int i = oldnp+1; i <= plainpoints.Size(); i++)\n\t      {\n                Point<3> locp;\n                upgeominfo.Elem(i) = *blgeominfo1;\n\t\tint err =\n\t\t  TransformFromPlain (plainpoints.Elem(i), locp, \n\t\t\t\t      upgeominfo.Elem(i), h);\n                locpoints.Elem(i) = locp;\n\n\t\tif (err)\n\t\t  {\n\t\t    found = 0;\n\n\t\t    if ( debugflag || debugparam.haltnosuccess )\n\t\t      PrintSysError (\"meshing2, Backtransformation failed\");\n\n\t\t    break;\n\t\t  }\n\t      }\n\t  }\n\t  \n\n\t//      for (i = 1; i <= oldnl; i++)\n\t//        adfront.ResetClass (lindex[i]);\n\n\n\t/*\n\t  double violateminh;\n\t  if (qualclass <= 10)\n\t  violateminh = 3;\n\t  else\n\t  violateminh = 3 * qualclass;\n\n\t  if (uselocalh && found) //  && qualclass <= 10)\n\t  {\n\t  for (i = 1; i <= locelements.Size(); i++)\n\t  {\n\t  Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1));\n\t  Point3d pmax = pmin;\n\t  for (j = 2; j <= 3; j++)\n\t  {\n\t  const Point3d & hp = \n\t  locpoints.Get(locelements.Get(i).PNum(j));\n\t  pmin.SetToMin (hp);\n\t  pmax.SetToMax (hp);\n\t  }\n\t  double minh = mesh.GetMinH (pmin, pmax);\n\t  if (h > violateminh * minh)\n\t  {\n\t  found = 0;\n\t  loclines.SetSize (oldnl);\n\t  locpoints.SetSize (oldnp);\n\t  }\n\t  }\n\t  }\n\t*/\n\n\n\tif (found) \n\t  {\n\t    double violateminh = 3 + 0.1 * sqr (qualclass);\n\t    double minh = 1e8;\n\t    double newedgemaxh = 0;\n\t    for (int i = oldnl+1; i <= loclines.Size(); i++)\n\t      {\n\t\tdouble eh = Dist (locpoints.Get(loclines.Get(i).I1()),\n\t\t\t\t  locpoints.Get(loclines.Get(i).I2()));\n\n\t\t// Markus (brute force method to avoid bad elements on geometries like \\_/ )\n\t\t//if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I1()))) found = 0;\n\t\t//if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I2()))) found = 0;\n\t\t// Markus end\n\n\t\tif (eh > newedgemaxh)\n\t\t  newedgemaxh = eh;\n\t      }\n\n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      {\n\t\tPoint3d pmin = locpoints.Get(locelements.Get(i).PNum(1));\n\t\tPoint3d pmax = pmin;\n\t\tfor (int j = 2; j <= locelements.Get(i).GetNP(); j++)\n\t\t  {\n\t\t    const Point3d & hp = \n\t\t      locpoints.Get(locelements.Get(i).PNum(j));\n\t\t    pmin.SetToMin (hp);\n\t\t    pmax.SetToMax (hp);\n\t\t  }\n\t\tdouble eh = mesh.GetMinH (pmin, pmax);\n\t\tif (eh < minh)\n\t\t  minh = eh;\n\t      }\n\n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      for (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\tif (Dist2 (locpoints.Get(locelements.Get(i).PNum(j)), pmid) > hinner*hinner)\n\t\t  found = 0;\n\n\t    //\t  cout << \"violate = \" << newedgemaxh / minh << endl;\n\t    static double maxviolate = 0;\n\t    if (newedgemaxh / minh > maxviolate)\n\t      {\n\t\tmaxviolate = newedgemaxh / minh;\n\t\t//\t      cout << \"max minhviolate = \" << maxviolate << endl;\n\t      }\n\n\n\t    if (newedgemaxh > violateminh * minh)\n\t      {\n\t\tfound = 0;\n\t\tloclines.SetSize (oldnl);\n\t\tlocpoints.SetSize (oldnp);\n\n\t\tif ( debugflag || debugparam.haltnosuccess )\n\t\t  PrintSysError (\"meshing2, maxh too large\");\n\n\n\t      }\n\t  }\n\n\n\n\t/*\n\t// test good ComputeLineGeoInfo\n\tif (found)\n\t{\n\t// is line on chart ?\n\tfor (i = oldnl+1; i <= loclines.Size(); i++)\n\t{\n\tint gisize;\n\tvoid *geominfo;\n\n\tif (ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()),\n\tlocpoints.Get(loclines.Get(i).I2()),\n\tgisize, geominfo))\n\tfound = 0;\n\t}\n\t}\n\t*/\n\n\n\t// changed for OCC meshing\n\tif (found)\n\t  {\n\t    // take geominfo from dellines\n\t    // upgeominfo.SetSize(locpoints.Size());\n\n\t    /*\n\t      for (i = 1; i <= dellines.Size(); i++)\n\t      for (j = 1; j <= 2; j++)\n\t      {\n\t      upgeominfo.Elem(loclines.Get(dellines.Get(i)).I(j)) =\n\t      adfront.GetLineGeomInfo (lindex.Get(dellines.Get(i)), j);\n\t      }\n\t    */\n\n\n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      for (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\t{\n\t\t  int pi = locelements.Get(i).PNum(j);\n\t\t  if (pi <= oldnp)\n\t\t    {\n\t\t    \n\t\t      if (ChooseChartPointGeomInfo (mpgeominfo.Get(pi), upgeominfo.Elem(pi)))\n\t\t\t{\n\t\t\t  // cannot select, compute new one\n\t\t\t  PrintWarning (\"calc point geominfo instead of using\");\n\t\t\t  if (ComputePointGeomInfo (locpoints.Get(pi), upgeominfo.Elem(pi)))\n\t\t\t    {\n\t\t\t      found = 0;\n\t\t\t      PrintSysError (\"meshing2d, geominfo failed\");\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t    /*\n\t    // use upgeominfo from ProjectFromPlane\n\t    for (i = oldnp+1; i <= locpoints.Size(); i++)\n\t    {\n\t    if (ComputePointGeomInfo (locpoints.Get(i), upgeominfo.Elem(i)))\n\t    {\n\t    found = 0;\n\t    if ( debugflag || debugparam.haltnosuccess )\n\t    PrintSysError (\"meshing2d, compute geominfo failed\");\n\t    }\n\t    }\n\t    */\n\t  }\n\n\n\tif (found && mp.checkoverlap)\n\t  {\n\t    // cout << \"checkoverlap\" << endl;\n\t    // test for overlaps\n\t  \n\t    Point3d hullmin(1e10, 1e10, 1e10);\n\t    Point3d hullmax(-1e10, -1e10, -1e10);\n\t  \n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      for (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\t{\n\t\t  const Point3d & p = locpoints.Get(locelements.Get(i).PNum(j));\n\t\t  hullmin.SetToMin (p);\n\t\t  hullmax.SetToMax (p);\n\t\t}\n\t    hullmin += Vec3d (-his, -his, -his);\n\t    hullmax += Vec3d ( his,  his,  his);\n\n\t    surfeltree.GetIntersecting (hullmin, hullmax, intersecttrias);\n\n\t    critpoints.SetSize (0);\n\t    for (int i = oldnp+1; i <= locpoints.Size(); i++)\n\t      critpoints.Append (locpoints.Get(i));\n\n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      {\n\t\tconst Element2d & tri = locelements.Get(i);\n\t\tif (tri.GetNP() == 3)\n\t\t  {\n\t\t    const Point3d & tp1 = locpoints.Get(tri.PNum(1));\n\t\t    const Point3d & tp2 = locpoints.Get(tri.PNum(2));\n\t\t    const Point3d & tp3 = locpoints.Get(tri.PNum(3));\n\t\t  \n\t\t    Vec3d tv1 (tp1, tp2);\n\t\t    Vec3d tv2 (tp1, tp3);\n\t\t  \n\t\t    double lam1, lam2;\n\t\t    for (lam1 = 0.2; lam1 <= 0.8; lam1 += 0.2)\n\t\t      for (lam2 = 0.2; lam2 + lam1 <= 0.8; lam2 += 0.2)\n\t\t\t{\n\t\t\t  Point3d hp = tp1 + lam1 * tv1 + lam2 * tv2;\n\t\t\t  critpoints.Append (hp);\n\t\t\t}\n\t\t  }\n\t\telse if (tri.GetNP() == 4)\n\t\t  {\n\t\t    const Point3d & tp1 = locpoints.Get(tri.PNum(1));\n\t\t    const Point3d & tp2 = locpoints.Get(tri.PNum(2));\n\t\t    const Point3d & tp3 = locpoints.Get(tri.PNum(3));\n\t\t    const Point3d & tp4 = locpoints.Get(tri.PNum(4));\n\t\t  \n\t\t    double l1, l2;\n\t\t    for (l1 = 0.1; l1 <= 0.9; l1 += 0.1)\n\t\t      for (l2 = 0.1; l2 <= 0.9; l2 += 0.1)\n\t\t\t{\n\t\t\t  Point3d hp;\n\t\t\t  hp.X() = \n\t\t\t    (1-l1)*(1-l2) * tp1.X() +\n\t\t\t    l1*(1-l2) * tp2.X() +\n\t\t\t    l1*l2 * tp3.X() +\n\t\t\t    (1-l1)*l2 * tp4.X();\n\t\t\t  hp.Y() = \n\t\t\t    (1-l1)*(1-l2) * tp1.Y() +\n\t\t\t    l1*(1-l2) * tp2.Y() +\n\t\t\t    l1*l2 * tp3.Y() +\n\t\t\t    (1-l1)*l2 * tp4.Y();\n\t\t\t  hp.Z() = \n\t\t\t    (1-l1)*(1-l2) * tp1.Z() +\n\t\t\t    l1*(1-l2) * tp2.Z() +\n\t\t\t    l1*l2 * tp3.Z() +\n\t\t\t    (1-l1)*l2 * tp4.Z();\n\n\n\t\t\t  critpoints.Append (hp);\n\t\t\t}\n\t\t  }\n\t      }\n\t    /*\n\t      for (i = oldnl+1; i <= loclines.Size(); i++)\n\t      {\n\t      Point3d hp = locpoints.Get(loclines.Get(i).I1());\n\t      Vec3d hv(hp, locpoints.Get(loclines.Get(i).I2()));\n\t      int ncp = 2;\n\t      for (j = 1; j <= ncp; j++)\n\t      critpoints.Append ( hp + (double(j)/(ncp+1)) * hv);\n\t      }\n\t    */\n\n\n\t    /*\n\t      for (i = oldnp+1; i <= locpoints.Size(); i++)\n\t      {\n\t      const Point3d & p = locpoints.Get(i);\n\t    */\n\n\n\t    for (int i = 1; i <= critpoints.Size(); i++)\n\t      {\n\t\tconst Point3d & p = critpoints.Get(i);\n\t\t \n\t\tfor (int jj = 0; jj < intersecttrias.Size(); jj++)\n\t\t  {\n\t\t    // int j = intersecttrias.Get(jj);\n\t\t    // const Element2d & el = mesh.SurfaceElement(j);\n\n\t\t    SurfaceElementIndex j = intersecttrias[jj];\n\t\t    const Element2d & el = mesh[j];\n\n\t\t    int ntrig = (el.GetNP() == 3) ? 1 : 2;\n\n\t\t    int jl;\n\t\t    for (jl = 1; jl <= ntrig; jl++)\n\t\t      {\n\t\t\tPoint3d tp1, tp2, tp3;\n\n\t\t\tif (jl == 1)\n\t\t\t  {\n\t\t\t    tp1 = mesh.Point(el.PNum(1));\n\t\t\t    tp2 = mesh.Point(el.PNum(2));\n\t\t\t    tp3 = mesh.Point(el.PNum(3));\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    tp1 = mesh.Point(el.PNum(1));\n\t\t\t    tp2 = mesh.Point(el.PNum(3));\n\t\t\t    tp3 = mesh.Point(el.PNum(4));\n\t\t\t  }\n\n\t\t\tint onchart = 0;\n\t\t\tfor (int k = 1; k <= el.GetNP(); k++)\n\t\t\t  if (BelongsToActiveChart (mesh.Point(el.PNum(k)),\n\t\t\t\t\t\t    el.GeomInfoPi(k)))\n\t\t\t    onchart = 1;\n\t\t\tif (!onchart)\n\t\t\t  continue;\n\t\t      \n\t\t\tVec3d e1(tp1, tp2);\n\t\t\tVec3d e2(tp1, tp3);\n\t\t\tVec3d n = Cross (e1, e2);\n\t\t\tn /= n.Length();\n\t\t\tdouble lam1, lam2, lam3;\n\t\t\tlam3 = n * Vec3d (tp1, p);\n\t\t\tLocalCoordinates (e1, e2, Vec3d (tp1, p), lam1, lam2);\n\t\t      \n\t\t\tif (fabs (lam3) < 0.1 * hshould && \n\t\t\t    lam1 > 0 && lam2 > 0 && (lam1 + lam2) < 1)\n\t\t\t  {\n#ifdef DEVELOP\n\t\t\t    cout << \"overlap\" << endl;\n\t\t\t    (*testout) << \"overlap:\" << endl\n\t\t\t\t       << \"tri = \" << tp1 << \"-\" << tp2 << \"-\" << tp3 << endl\n\t\t\t\t       << \"point = \" << p << endl\n\t\t\t\t       << \"lam1, 2 = \" << lam1 << \", \" << lam2 << endl\n\t\t\t\t       << \"lam3 = \" << lam3 << endl;\n\t\t\t  \n\t\t\t    //\t\t      cout << \"overlap !!!\" << endl;\n#endif\n\t\t\t    for (int k = 1; k <= 5; k++)\n\t\t\t      adfront.IncrementClass (lindex.Get(1));\n\n\t\t\t    found = 0;\n\t\t\t  \n\t\t\t    if ( debugflag || debugparam.haltnosuccess )\n\t\t\t      PrintWarning (\"overlapping\");\n\t\t\t  \n\t\t\t  \n\t\t\t    if (debugparam.haltoverlap)\n\t\t\t      {\n\t\t\t\tdebugflag = 1;\n\t\t\t      }\n\t\t\t  \n\t\t\t    /*\n\t\t\t      multithread.drawing = 1;\n\t\t\t      glrender(1);\n\t\t\t    */\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\n\n\tif (found)\n\t  {\n\t    // check, whether new front line already exists\n\n\t    for (int i = oldnl+1; i <= loclines.Size(); i++)\n\t      {\n\t\tint nlgpi1 = loclines.Get(i).I1();\n\t\tint nlgpi2 = loclines.Get(i).I2();\n\t\tif (nlgpi1 <= pindex.Size() && nlgpi2 <= pindex.Size())\n\t\t  {\n\t\t    nlgpi1 = adfront.GetGlobalIndex (pindex.Get(nlgpi1));\n\t\t    nlgpi2 = adfront.GetGlobalIndex (pindex.Get(nlgpi2));\n\n\t\t    int exval = adfront.ExistsLine (nlgpi1, nlgpi2);\n\t\t    if (exval)\n\t\t      {\n\t\t\tcout << \"ERROR: new line exits, val = \" << exval << endl;\n\t\t\t(*testout) << \"ERROR: new line exits, val = \" << exval << endl;\n\t\t\tfound = 0;\n\n\n\t\t\tif (debugparam.haltexistingline)\n\t\t\t  debugflag = 1;\n\n\t\t      }\n\t\t  }\n\t      }\n\t  \n\t  }\n\n\n\t/*\n\t  if (found)\n\t  {\n\t  // check, whether new triangles insert edges twice\n\t  for (i = 1; i <= locelements.Size(); i++)\n\t  for (j = 1; j <= 3; j++)\n\t  {\n\t  int tpi1 = locelements.Get(i).PNumMod (j);\n\t  int tpi2 = locelements.Get(i).PNumMod (j+1);\n\t  if (tpi1 <= pindex.Size() && tpi2 <= pindex.Size())\n\t  {\n\t  tpi1 = adfront.GetGlobalIndex (pindex.Get(tpi1));\n\t  tpi2 = adfront.GetGlobalIndex (pindex.Get(tpi2));\n\n\t  if (doubleedge.Used (INDEX_2(tpi1, tpi2)))\n\t  {\n\t  if (debugparam.haltexistingline)\n\t  debugflag = 1;\n\t  cerr << \"ERROR Insert edge \"\n\t  << tpi1 << \" - \" << tpi2 << \" twice !!!\" << endl;\n\t  found = 0;\n\t  }\n\t  doubleedge.Set (INDEX_2(tpi1, tpi2), 1);\n\t  }\n\t  }\n\t  }\n\t*/\n\n\n\tif (found)\n\t  {\n\t    // everything is ok, perform mesh update\n\n\t    ruleused.Elem(rulenr)++;\n\n\n\t    pindex.SetSize(locpoints.Size());\n\t      \n\t    for (int i = oldnp+1; i <= locpoints.Size(); i++)\n\t      {\n\t\tPointIndex globind = mesh.AddPoint (locpoints.Get(i));\n\t\tpindex.Elem(i) = adfront.AddPoint (locpoints.Get(i), globind);\n\t      }\n\t      \n\t    for (int i = oldnl+1; i <= loclines.Size(); i++)\n\t      {\n\t\t/*\n\t\t  for (j = 1; j <= locpoints.Size(); j++)\n\t\t  {\n\t\t  (*testout) << j << \": \" << locpoints.Get(j) << endl;\n\t\t  }\n\t\t*/\n\t      \n\t\t/*\n\t\t  ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()),\n\t\t  locpoints.Get(loclines.Get(i).I2()),\n\t\t  gisize, geominfo);\n\t\t*/\t\t  \n\n\t\tif (pindex.Get(loclines.Get(i).I1()) == -1 || \n\t\t    pindex.Get(loclines.Get(i).I2()) == -1)\n\t\t  {\n\t\t    (*testout) << \"pindex is 0\" << endl;\n\t\t  }\n\n\t\tif (!upgeominfo.Get(loclines.Get(i).I1()).trignum || \n\t\t    !upgeominfo.Get(loclines.Get(i).I2()).trignum)\n\t\t  {\n\t\t    cout << \"new el: illegal geominfo\" << endl;\n\t\t  }\n\n\t\tadfront.AddLine (pindex.Get(loclines.Get(i).I1()),\n\t\t\t\t    pindex.Get(loclines.Get(i).I2()),\n\t\t\t\t    upgeominfo.Get(loclines.Get(i).I1()),\n\t\t\t\t    upgeominfo.Get(loclines.Get(i).I2()));\n\t      }\n\t    for (int i = 1; i <= locelements.Size(); i++)\n\t      {\n\t\tElement2d mtri(locelements.Get(i).GetNP());\n\t\tmtri = locelements.Get(i);\n\t\tmtri.SetIndex (facenr);\n\n\n\t\t// compute triangle geominfo:\n\t\t//\t      (*testout) << \"triggeominfo: \";\n\t\tfor (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\t  {\n\t\t    mtri.GeomInfoPi(j) = upgeominfo.Get(locelements.Get(i).PNum(j));\n\t\t    //\t\t  (*testout) << mtri.GeomInfoPi(j).trignum << \" \";\n\t\t  }\n\t\t//\t      (*testout) << endl;\n\n\t\tfor (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\t  {\n\t\t    mtri.PNum(j) = \n\t\t      locelements.Elem(i).PNum(j) =\n\t\t      adfront.GetGlobalIndex (pindex.Get(locelements.Get(i).PNum(j)));\n\t\t  }\n\t      \n\t\t\n\t      \n\t      \n\t\tmesh.AddSurfaceElement (mtri);\n\t\t// cntelem++;\n\t\t//\t      cout << \"elements: \" << cntelem << endl;\n\n\n\t      \n\t\tBox<3> box;\n\t\tbox.Set (mesh[mtri[0]]);\n\t\tbox.Add (mesh[mtri[1]]);\n\t\tbox.Add (mesh[mtri[2]]);\n\t\tsurfeltree.Insert (box, mesh.GetNSE()-1);\n\n\t\tconst Point3d & sep1 = mesh.Point (mtri.PNum(1));\n\t\tconst Point3d & sep2 = mesh.Point (mtri.PNum(2));\n\t\tconst Point3d & sep3 = mesh.Point (mtri.PNum(3));\n\n\t\tdouble trigarea = Cross (Vec3d (sep1, sep2), \n\t\t\t\t\t Vec3d (sep1, sep3)).Length() / 2;\n\n\t\tif (mtri.GetNP() == 4)\n\t\t  {\n\t\t    const Point3d & sep4 = mesh.Point (mtri.PNum(4));\n\t\t    trigarea += Cross (Vec3d (sep1, sep3), \n\t\t\t\t       Vec3d (sep1, sep4)).Length() / 2;\n\t\t  }\n\n\t\tmeshedarea += trigarea;\n\n\t\tif(maxarea > 0 && meshedarea-meshedarea_before > maxarea)\n\t\t  {\n\t\t    cerr << \"meshed area = \" << meshedarea-meshedarea_before << endl\n\t\t\t << \"maximal area = \" << maxarea << endl\n\t\t\t << \"GIVING UP\" << endl;\n\t\t    return MESHING2_GIVEUP;\n\t\t  }\n\t      \n\n\n\t\tfor (int j = 1; j <= locelements.Get(i).GetNP(); j++)\n\t\t  {\n\t\t    int gpi = locelements.Get(i).PNum(j);\n\n\t\t    int oldts = trigsonnode.Size();\n\t\t    if (gpi >= oldts+PointIndex::BASE)\n\t\t      {\n\t\t\ttrigsonnode.SetSize (gpi+1-PointIndex::BASE);\n\t\t\tillegalpoint.SetSize (gpi+1-PointIndex::BASE);\n\t\t\tfor (int k = oldts+PointIndex::BASE; \n\t\t\t     k <= gpi; k++)\n\t\t\t  {\n\t\t\t    trigsonnode[k] = 0;\n\t\t\t    illegalpoint[k] = 0;\n\t\t\t  }\n\t\t      }\n\n\t\t    trigsonnode[gpi]++;\n\t\t  \n\t\t    if (trigsonnode[gpi] > 20)\n\t\t      {\n\t\t\tillegalpoint[gpi] = 1;\n\t\t\t//\t\t      cout << \"illegal point: \" << gpi << endl;\n\t\t\t(*testout) << \"illegal point: \" << gpi << endl;\n\t\t      }\n\n\t\t    static int mtonnode = 0;\n\t\t    if (trigsonnode[gpi] > mtonnode)\n\t\t      mtonnode = trigsonnode[gpi];\n\t\t  }\n\t\t//\t      cout << \"els = \" << cntelem << \" trials = \" << trials << endl;\n\t\t//\t      if (trials > 100)\t\treturn;\n\t      }\n\t      \n\t    for (int i = 1; i <= dellines.Size(); i++)\n\t      adfront.DeleteLine (lindex.Get(dellines.Get(i)));\n\t      \n\t    //\t  rname = rules.Get(rulenr)->Name();\n#ifdef MYGRAPH\n\t    if (silentflag<3) \n\t      {\n\t\tplotsurf.DrawPnL(locpoints, loclines);\n\t\tplotsurf.Plot(testmode, testmode);\n\t      }\n#endif\n\n\t    if (morerisc)\n\t      {\n\t\tcout << \"generated due to morerisc\" << endl;\n\t\t//\t      multithread.drawing = 1;\n\t\t//\t      glrender(1);\n\t      }\n\n\n\n\t  \n\t    if ( debugparam.haltsuccess || debugflag )\n\t      {\n\t\t// adfront.PrintOpenSegments (*testout);\n\t\tcout << \"success of rule\" << rules[rulenr-1]->Name() << endl;\n\t\tmultithread.drawing = 1;\n\t\tmultithread.testmode = 1;\n\t\tmultithread.pause = 1;\n\n\n\t\t/*\n\t\t  extern STLGeometry * stlgeometry;\n\t\t  stlgeometry->ClearMarkedSegs();\n\t\t  for (i = 1; i <= loclines.Size(); i++)\n\t\t  {\n\t\t  stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()),\n\t\t  locpoints.Get(loclines.Get(i).I2()));\n\t\t  }\n\t\t*/\n\n\t\t(*testout) << \"success of rule\" << rules[rulenr-1]->Name() << endl;\n\t\t(*testout) << \"trials = \" << trials << endl;\n\n\t\t(*testout) << \"locpoints \" << endl;\n\t\tfor (int i = 1; i <= pindex.Size(); i++)\n\t\t  (*testout) << adfront.GetGlobalIndex (pindex.Get(i)) << endl;\n\n\t\t(*testout) << \"old number of lines = \" << oldnl << endl;\n\n                UpdateVisSurfaceMeshData(oldnl);\n\n\t\tfor (int i = 1; i <= loclines.Size(); i++)\n\t\t  {\n\t\t    (*testout) << \"line \";\n\t\t    for (int j = 1; j <= 2; j++)\n\t\t      {\n\t\t\tint hi = 0;\n\t\t\tif (loclines.Get(i).I(j) >= 1 &&\n\t\t\t    loclines.Get(i).I(j) <= pindex.Size())\n\t\t\t  hi = adfront.GetGlobalIndex (pindex.Get(loclines.Get(i).I(j)));\n\n\t\t\t(*testout) << hi << \" \";\n\t\t      }\n\t\t    (*testout) << \" : \" \n\t\t\t       << plainpoints.Get(loclines.Get(i).I1()) << \" - \"\n\t\t\t       << plainpoints.Get(loclines.Get(i).I2()) << \" 3d: \"\n\t\t\t       << locpoints.Get(loclines.Get(i).I1()) << \" - \"\n\t\t\t       << locpoints.Get(loclines.Get(i).I2()) \n\t\t\t       << endl;\n\t\t  }\n\n\n\n\t\tglrender(1);\n\t      }\n\t  }\n\telse\n\t  {\n\t    adfront.IncrementClass (lindex.Get(1));\n\n\t    if ( debugparam.haltnosuccess || debugflag )\n\t      {\n\t\tcout << \"Problem with seg \" << gpi1 << \" - \" << gpi2\n\t\t     << \", class = \" << qualclass << endl;\n\n\t\t(*testout) << \"Problem with seg \" << gpi1 << \" - \" << gpi2\n\t\t\t   << \", class = \" << qualclass << endl;\n\n\t\tmultithread.drawing = 1;\n\t\tmultithread.testmode = 1;\n\t\tmultithread.pause = 1;\n\n\n\t\t/*\n\t\t  extern STLGeometry * stlgeometry;\n\t\t  stlgeometry->ClearMarkedSegs();\n\t\t  for (i = 1; i <= loclines.Size(); i++)\n\t\t  {\n\t\t  stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()),\n\t\t  locpoints.Get(loclines.Get(i).I2()));\n\t\t  }\n\t\t*/\n\n\t\tfor (int i = 1; i <= loclines.Size(); i++)\n\t\t  {\n\t\t    (*testout) << \"line \";\n\t\t    for (int j = 1; j <= 2; j++)\n\t\t      {\n\t\t\tint hi = 0;\n\t\t\tif (loclines.Get(i).I(j) >= 1 &&\n\t\t\t    loclines.Get(i).I(j) <= pindex.Size())\n\t\t\t  hi = adfront.GetGlobalIndex (pindex.Get(loclines.Get(i).I(j)));\n\n\t\t\t(*testout) << hi << \" \";\n\t\t      }\n\t\t    (*testout) << \" : \" \n\t\t\t       << plainpoints.Get(loclines.Get(i).I1()) << \" - \"\n\t\t\t       << plainpoints.Get(loclines.Get(i).I2()) << \" 3d: \"\n\t\t\t       << locpoints.Get(loclines.Get(i).I1()) << \" - \"\n\t\t\t       << locpoints.Get(loclines.Get(i).I2()) \n\t\t\t       << endl;\n\t\t  }\n\n\n\t\t/*\n\t\t  cout << \"p1gi = \" << blgeominfo[0].trignum \n\t\t  << \", p2gi = \" << blgeominfo[1].trignum << endl;\n\t\t*/\n\n\t\tglrender(1);\n\t      }\n\n\t  \n#ifdef MYGRAPH      \n\t    if (silentflag<3)\n\t      {\n\t\tif (testmode || trials%2 == 0)\n\t\t  {\n\t\t    plotsurf.DrawPnL(locpoints, loclines);\n\t\t    plotsurf.Plot(testmode, testmode);\n\t\t  }\n\t      }\n#endif\n\t  }\n\n      }\n    }\n    PrintMessage (3, \"Surface meshing done\");\n\n\n    adfront.PrintOpenSegments (*testout);\n\n    multithread.task = savetask;\n\n\n    EndMesh ();\n\n\n    if (!adfront.Empty())\n      return MESHING2_GIVEUP;\n    \n    return MESHING2_OK;\n  }\n\n\n}\n\n"
  },
  {
    "path": "libsrc/meshing/meshing2.hpp",
    "content": "#ifndef NETGEN_MESHING2_HPP\n#define NETGEN_MESHING2_HPP\n\n/**************************************************************************/\n/* File:   meshing2.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\n\n#include \"adfront2.hpp\"\n#include \"ruler2.hpp\"\n#include \"basegeom.hpp\"\n\nnamespace netgen\n{\n\n\nenum MESHING2_RESULT\n{\n  MESHING2_OK = 0,\n  MESHING2_GIVEUP = 1\n};\n\n\n/*\n   \nThe basis class for 2D mesh generation. \nHas the method GenerateMesh\n\nFor surface mesh generation, or non-Euklidean meshing,\nderive from Meshing2, and replace transformation.\n\n*/\n\nclass Meshing2\n{\n  /// the current advancing front\n  AdFront2 adfront;\n  /// rules for mesh generation\n  Array<unique_ptr<netrule>> rules;\n  /// statistics\n  NgArray<int> ruleused, canuse, foundmap;\n  /// \n  Box<3> boundingbox;\n  ///\n  double starttime;\n  ///\n  double maxarea;\n\n  Vec3d ex, ey, ez;\n  Point<3> p1, p2;\n\n  const NetgenGeometry& geo;\n\npublic:\n  ///\n  DLL_HEADER Meshing2 (const NetgenGeometry& geo,\n                       const MeshingParameters & mp,\n                       const Box<3> & aboundingbox);\n\n  ///\n  DLL_HEADER virtual ~Meshing2 ();\n\n  /// Load rules, either from file, or compiled rules\n  void LoadRules (const char * filename, bool quad);\n\n  /// \n  DLL_HEADER MESHING2_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr, int layer=1);\n\n  DLL_HEADER void Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp);\n  DLL_HEADER void BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp);\n\n\n  ///\n  DLL_HEADER int AddPoint (const Point3d & p, PointIndex globind, MultiPointGeomInfo * mgi = NULL,\n\t\t bool pointonsurface = true);\n  DLL_HEADER PointIndex GetGlobalIndex(int pi) const;\n\n  ///\n  DLL_HEADER void AddBoundaryElement (INDEX i1, INDEX i2,\n\t\t\t   const PointGeomInfo & gi1, const PointGeomInfo & gi2);\n  \n  ///\n  void SetStartTime (double astarttime);\n\n  ///\n  void SetMaxArea (double amaxarea);\n\nprotected:\n  ///\n  virtual void StartMesh ();\n  ///\n  virtual void EndMesh ();\n  ///\n  virtual double CalcLocalH (const Point<3> & p, double gh) const;\n\n  ///\n  virtual void DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n\t\t\t\t     const PointGeomInfo * geominfo1,\n\t\t\t\t     const PointGeomInfo * geominfo2);\n  ///\n  virtual void TransformToPlain (const Point<3> & locpoint, const MultiPointGeomInfo &  geominfo,\n\t\t\t\t Point<2> & plainpoint, double h, int & zone);\n  /// return 0 .. ok\n  /// return >0 .. cannot transform point to true surface\n  virtual int TransformFromPlain (const Point<2>& plainpoint,\n\t\t\t\t  Point<3> & locpoint, \n\t\t\t\t  PointGeomInfo & geominfo, \n\t\t\t\t  double h);\n  \n  /// projects to surface\n  /// return 0 .. ok\n  virtual int BelongsToActiveChart (const Point3d & p, \n\t\t\t\t    const PointGeomInfo & gi);\n\n  /// computes geoinfo data for line with respect to\n  /// selected chart\n  virtual int ComputePointGeomInfo (const Point3d & p, \n\t\t\t\t    PointGeomInfo & gi);\n\n  /// Tries to select unique geominfo on active chart\n  /// return 0: success\n  /// return 1: failed\n  virtual int ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, \n\t\t\t\t\tPointGeomInfo & pgi);\n\n\n\n  /*\n    tests, whether endpoint (= 1 or 2) of line segment p1-p2\n    is inside of the selected chart. The endpoint must be on the\n    chart\n   */\n  virtual int IsLineVertexOnChart (const Point3d & p1, const Point3d & p2,\n\t\t\t\t   int endpoint, const PointGeomInfo & geominfo);\n\n  /*\n    get (projected) boundary of current chart\n   */\n  virtual void GetChartBoundary (NgArray<Point<2>> & points, \n\t\t\t\t NgArray<Point<3>> & points3d,\n\t\t\t\t NgArray<INDEX_2> & lines, double p) const;\n\n  virtual double Area () const;\n\n\n/** Applies 2D rules.\n Tests all 2D rules */\n  int ApplyRules (NgArray<Point<2>> & lpoints, \n\t\t  NgArray<int> & legalpoints,\n\t\t  int maxlegalpoint,\n\t\t  NgArray<INDEX_2> & llines,\n\t\t  int maxlegelline,\n\t\t  NgArray<Element2d> & elements, NgArray<INDEX> & dellines,\n\t\t  int tolerance,\n\t\t  const MeshingParameters & mp);\n  \n\n};\n} // namespace netgen\n\n#endif // NETGEN_MESHING2_HPP\n"
  },
  {
    "path": "libsrc/meshing/meshing3.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing3.hpp\"\n#include \"findip.hpp\"\n#include \"findip2.hpp\"\n\nnamespace netgen\n{\n\ndouble minother;\ndouble minwithoutother;\n\n\n\nMeshingStat3d :: MeshingStat3d ()\n{\n  cntsucc = cnttrials = cntelem = qualclass = 0;\n  vol0 = h = 1;\n  problemindex = 1;\n}  \n  \n\nMeshing3 :: Meshing3 (const string & rulefilename) \n{\n  tolfak = 1;\n\n  LoadRules (rulefilename.c_str(), NULL);\n  adfront = make_unique<AdFront3>();\n\n  problems.SetSize (rules.Size());\n  foundmap.SetSize (rules.Size());\n  canuse.SetSize (rules.Size());\n  ruleused.SetSize (rules.Size());\n\n  /*\n  for (int i = 1; i <= rules.Size(); i++)\n    {\n      problems.Elem(i) = new char[255];\n      foundmap.Elem(i) = 0;\n      canuse.Elem(i) = 0;\n      ruleused.Elem(i) = 0;\n    }\n  */\n\n  foundmap = 0;\n  canuse = 0;\n  ruleused = 0;\n}\n\n\nMeshing3 :: Meshing3 (const char ** rulep)\n{\n  tolfak = 1;\n\n  LoadRules (NULL, rulep);\n  adfront = make_unique<AdFront3>();\n\n  problems.SetSize (rules.Size());\n  foundmap.SetSize (rules.Size());\n  canuse.SetSize (rules.Size());\n  ruleused.SetSize (rules.Size());\n\n  /*\n  for (int i = 0; i < rules.Size(); i++)\n    {\n      problems[i] = new char[255];\n      foundmap[i] = 0;\n      canuse[i]   = 0;\n      ruleused[i] = 0;\n    }\n  */\n  foundmap = 0;\n  canuse = 0;\n  ruleused = 0;\n}\n\nMeshing3 :: ~Meshing3 ()\n{\n  // delete adfront;\n  /*\n  for (int i = 0; i < rules.Size(); i++)\n    {\n      delete [] problems[i];\n      delete rules[i];\n    }\n  */\n}\n\n\n\n/*\n  // was war das ????\nstatic double CalcLocH (const NgArray<Point3d> & locpoints,\n\t\t\tconst NgArray<MiniElement2d> & locfaces,\n\t\t\tdouble h)\n{\n  return h;\n\n  \n  int i, j;\n  double hi, h1, d, dn, sum, weight, wi;\n  Point3d p0, pc;\n  Vec3d n, v1, v2;\n\n  p0.X() = p0.Y() = p0.Z() = 0;\n  for (j = 1; j <= 3; j++)\n    {\n      p0.X() += locpoints.Get(locfaces.Get(1).PNum(j)).X();\n      p0.Y() += locpoints.Get(locfaces.Get(1).PNum(j)).Y();\n      p0.Z() += locpoints.Get(locfaces.Get(1).PNum(j)).Z();\n    }\n  p0.X() /= 3; p0.Y() /= 3; p0.Z() /= 3;\n  \n  v1 = locpoints.Get(locfaces.Get(1).PNum(2)) -\n    locpoints.Get(locfaces.Get(1).PNum(1));\n  v2 = locpoints.Get(locfaces.Get(1).PNum(3)) -\n    locpoints.Get(locfaces.Get(1).PNum(1));\n\n  h1 = v1.Length();\n  n = Cross (v2, v1);\n  n /= n.Length();\n\n  sum = 0;\n  weight = 0;\n\n  for(int i = 1; i <= locfaces.Size(); i++)\n    {\n      pc.X() = pc.Y() = pc.Z() = 0;\n      for (j = 1; j <= 3; j++)\n\t{\n\t  pc.X() += locpoints.Get(locfaces.Get(i).PNum(j)).X();\n\t  pc.Y() += locpoints.Get(locfaces.Get(i).PNum(j)).Y();\n\t  pc.Z() += locpoints.Get(locfaces.Get(i).PNum(j)).Z();\n\t}\n      pc.X() /= 3; pc.Y() /= 3; pc.Z() /= 3;\n\n      d = Dist (p0, pc);\n      dn = n * (pc - p0);\n      hi = Dist (locpoints.Get(locfaces.Get(i).PNum(1)),\n\t\t locpoints.Get(locfaces.Get(i).PNum(2)));\n\t\t \n      if (dn > -0.2 * h1)\n\t{\n\t  wi = 1 / (h1 + d);\n\t  wi *= wi;\n\t}\n      else\n\twi = 0;\n\n      sum += hi * wi;\n      weight += wi;\n    }\n\n  return sum/weight;\n}\n*/\n\nPointIndex Meshing3 :: AddPoint (const Point3d & p, PointIndex globind)\n{\n  return adfront -> AddPoint (p, globind);  \n}  \n\nvoid Meshing3 :: AddBoundaryElement (const Element2d & elem)\n{\n  MiniElement2d mini(elem.GetNP());\n  for (int j = 0; j < elem.GetNP(); j++)\n    mini[j] = elem[j];\n  adfront -> AddFace(mini);\n}  \n\n\nvoid Meshing3 :: AddBoundaryElement (const MiniElement2d & elem)\n{\n  adfront -> AddFace(elem);\n}\n\nint Meshing3 :: AddConnectedPair (const INDEX_2 & apair)\n{\n  return adfront -> AddConnectedPair (apair);\n}\n\nMESHING3_RESULT Meshing3 :: \nGenerateMesh (Mesh & mesh, const MeshingParameters & mp)\n{\n  static Timer t(\"Meshing3::GenerateMesh\"); RegionTimer reg(t);\n  // static Timer meshing3_timer_a(\"Meshing3::GenerateMesh a\", 2);\n  // static Timer meshing3_timer_b(\"Meshing3::GenerateMesh b\", 2);\n  // static Timer meshing3_timer_c(\"Meshing3::GenerateMesh c\", 1);\n  // static Timer meshing3_timer_d(\"Meshing3::GenerateMesh d\", 2);\n  // static int meshing3_timer = NgProfiler::CreateTimer (\"Meshing3::GenerateMesh\");\n  // static int meshing3_timer_a = NgProfiler::CreateTimer (\"Meshing3::GenerateMesh a\");\n  // static int meshing3_timer_b = NgProfiler::CreateTimer (\"Meshing3::GenerateMesh b\");\n  // static int meshing3_timer_c = NgProfiler::CreateTimer (\"Meshing3::GenerateMesh c\");\n  // static int meshing3_timer_d = NgProfiler::CreateTimer (\"Meshing3::GenerateMesh d\");\n  // NgProfiler::RegionTimer reg (meshing3_timer);\n\n\n  Array<Point3d, PointIndex> locpoints;      // local points\n  Array<MiniElement2d> locfaces;                   // local faces\n  Array<PointIndex, PointIndex> pindex;      // mapping from local to front point numbering\n  Array<int, PointIndex> allowpoint;         // point is allowed (0/1/2) ?\n  Array<INDEX> findex;                             // mapping from local to front face numbering\n  //INDEX_2_HASHTABLE<int> connectedpairs(100);    // connecgted pairs for prism meshing\n\n  Array<Point3d, PointIndex> plainpoints;    // points in reference coordinates\n  // NgArray<int> delpoints;   // points to be deleted\n  NgArray<int> delfaces;    // lines to be deleted\n  NgArray<Element> locelements;       // new generated elements\n\n  int j, oldnp, oldnf;\n  int found;\n  referencetransform trans;\n  Point3d inp;\n  float err;\n\n  INDEX locfacesplit;             //index for faces in outer area\n  \n  bool loktestmode = false;\n\n  int uselocalh = mp.uselocalh;\n\n  // int giveuptol = mp.giveuptol; // \n  MeshingStat3d stat;      // statistics\n  int plotstat_oldne = -1;\n\n  \n  // for star-shaped domain meshing\n  Array<MeshPoint, PointIndex> grouppoints;      \n  Array<MiniElement2d> groupfaces;\n  Array<PointIndex, PointIndex> grouppindex;\n  Array<INDEX> groupfindex;\n  \n  \n  float minerr;\n  int hasfound;\n  [[maybe_unused]] double tetvol;\n  // int giveup = 0;\n\n  \n  NgArray<Point3d> tempnewpoints;\n  NgArray<MiniElement2d> tempnewfaces;\n  NgArray<int> tempdelfaces;\n  NgArray<Element> templocelements;\n\n\n  stat.h = mp.maxh;\n\n  adfront->SetStartFront (mp.baseelnp);\n\n\n  found = 0;\n  stat.vol0 = adfront -> Volume();\n  tetvol = 0;\n\n  stat.qualclass = 1;\n\n  while (1)\n    {\n      if (multithread.terminate)\n\tthrow NgException (\"Meshing stopped\");\n\n      // break if advancing front is empty\n      if (!mp.baseelnp && adfront->Empty())\n\tbreak;\n\n      // break, if advancing front has no elements with\n      // mp.baseelnp nodes  \n      if (mp.baseelnp && adfront->Empty (mp.baseelnp))\n\tbreak;\n\n      locpoints.SetSize(0);\n      locfaces.SetSize(0);\n      locelements.SetSize(0);\n      pindex.SetSize(0);\n      findex.SetSize(0);\n\n      INDEX_2_HASHTABLE<int> connectedpairs(100);  // connected pairs for prism meshing\n      \n      // select base-element (will be locface[1])\n      // and get local environment of radius (safety * h)\n\n\n      int baseelem = adfront -> SelectBaseElement ();\n      if (mp.baseelnp && adfront->GetFace (baseelem).GetNP() != mp.baseelnp)\n\t{\n\t  adfront->IncrementClass (baseelem);\t  \n\t  continue;\n\t}\n\n      const MiniElement2d & bel = adfront->GetFace (baseelem);\n      const Point<3> p1 = adfront->GetPoint (bel[0]);\n      const Point<3> p2 = adfront->GetPoint (bel[1]);\n      const Point<3> p3 = adfront->GetPoint (bel[2]);\n      \n\n      Point<3> pmid = Center (p1, p2, p3);\n\n      double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3;\n      double hshould = mesh.GetH (pmid);\n      \n      if (adfront->GetFace (baseelem).GetNP() == 4)\n\thshould = max2 (his, hshould);\n\n      double hmax = (his > hshould) ? his : hshould;\n      \n      // qualclass should come from baseelem !!!!!\n      double hinner = hmax * (1 + stat.qualclass);\n      double houter = hmax * (1 + 2 * stat.qualclass);\n\n      // meshing3_timer_a.Start();\n      stat.qualclass =\n        adfront -> GetLocals (baseelem, locpoints, locfaces, \n\t\t\t      pindex, findex, connectedpairs,\n\t\t\t      houter, hinner,\n\t\t\t      locfacesplit);\n      // meshing3_timer_a.Stop();\n\n      // (*testout) << \"locfaces = \" << endl << locfaces << endl;\n\n\n      //loktestmode = 1;\n      testmode = loktestmode;  //changed \n      // loktestmode = testmode =  (adfront->GetFace (baseelem).GetNP() == 4) && (rules.Size() == 5);\n\n      loktestmode = stat.qualclass > 5;\n      \n\n      if (loktestmode)\n\t{\n\t  (*testout) << \"baseel = \" << baseelem << \", ind = \" << findex[0] << endl;\n          int pi1 = pindex[locfaces[0].PNum(1)];\n          int pi2 = pindex[locfaces[0].PNum(2)];\n          int pi3 = pindex[locfaces[0].PNum(3)];\n\t  (*testout) << \"pi = \" << pi1 << \", \" << pi2 << \", \" << pi3 << endl;\n\t}\n\n\n      if (testmode)\n\t{\n\t  (*testout) << \"baseelem = \" << baseelem << \" qualclass = \" << stat.qualclass << endl;\n\t  (*testout) << \"locpoints = \" << endl << locpoints << endl;\n\t  (*testout) << \"connected = \" << endl << connectedpairs << endl;\n\t}\n\n\n\n      // loch = CalcLocH (locpoints, locfaces, h);\n      \n      stat.nff = adfront->GetNF();\n      stat.vol = adfront->Volume();\n      if (stat.vol < 0) break;\n\n      oldnp = locpoints.Size();\n      oldnf = locfaces.Size();\n\n\n      allowpoint.SetSize(locpoints.Size());\n      if (uselocalh && stat.qualclass <= 3)\n\t//for(int i = 1; i <= allowpoint.Size(); i++)\n        for(auto i : allowpoint.Range())\n\t  {\n\t    allowpoint[i] =\n\t      (mesh.GetH (locpoints[i]) > 0.4 * hshould / mp.sloppy) ? 2 : 1;\n\t  }\n      else\n\tallowpoint = 2;\n\n\n      \n      if (stat.qualclass >= mp.starshapeclass &&\n\t  mp.baseelnp != 4)   \n\t{\n\t  // NgProfiler::RegionTimer reg1 (meshing3_timer_b);\n\t  // star-shaped domain removing\n\n\t  grouppoints.SetSize (0);\n\t  groupfaces.SetSize (0);\n\t  grouppindex.SetSize (0);\n\t  groupfindex.SetSize (0);\n\t  \n\t  adfront -> GetGroup (findex[0], grouppoints, groupfaces, \n\t\t\t       grouppindex, groupfindex);\n\n\t  bool onlytri = 1;\n          for (auto & f : groupfaces)\n            if (f.GetNP() != 3) \n              onlytri = 0;\n            \n              \n\t  if (onlytri && groupfaces.Size() <= 20 + 2*stat.qualclass &&\n\t      FindInnerPoint (grouppoints, groupfaces, inp) &&\n              !adfront->PointInsideGroup(grouppindex, groupfaces))\n\t    {\n\t      (*testout) << \"inner point found\" << endl;\n\n\t      for(int i = 0; i < groupfaces.Size(); i++)\n\t\tadfront -> DeleteFace (groupfindex[i]);\n              \n\t      for(int i = 1; i <= groupfaces.Size(); i++)\n\t\tfor (j = 1; j <= locfaces.Size(); j++)\n\t\t  if (findex[j-1] == groupfindex[i-1])\n\t\t    delfaces.Append (j);\n\t      \n\t      \n\t      delfaces.SetSize (0);\n\t      \n\t      Element newel(TET);\n\t      \n\t      PointIndex npi = mesh.AddPoint (inp);\n\t      newel.SetNP(4);\n\t      newel.PNum(4) = npi;\n\t      \n\t      for(int i = 0; i < groupfaces.Size(); i++)\n\t\t{\n\t\t  for (j = 1; j <= 3; j++)\n\t\t    {\n\t\t      newel.PNum(j) = \n\t\t\tadfront->GetGlobalIndex \n\t\t\t(grouppindex[groupfaces[i].PNum(j)]);\n\t\t    }\n\t\t  mesh.AddVolumeElement (newel);\n\t\t}\n\t      continue;\n\t    }\n\t}\n      \n      found = 0;\n      hasfound = 0;\n      minerr = 1e6;\n\n      //      int optother = 0;\n\n      /*\n      for(int i = 1; i <= locfaces.Size(); i++)\n\t{\n\t  (*testout) << \"Face \" << i << \": \";\n\t  for (j = 1; j <= locfaces.Get(i).GetNP(); j++)\n\t    (*testout) << pindex.Get(locfaces.Get(i).PNum(j)) << \" \";\n\t  (*testout) << endl;\n\t}\n      for(int i = 1; i <= locpoints.Size(); i++)\n\t{\n\t  (*testout) << \"p\" << i \n\t\t     << \", gi = \" << pindex.Get(i) \n\t\t     << \" = \" << locpoints.Get(i) << endl;\n\t}\n\t*/\n\n      minother = 1e10;\n      minwithoutother = 1e10;\n\n      bool impossible = 1;\n\n      for (int rotind = 1; rotind <= locfaces[0].GetNP(); rotind++)\n\t{\n\t  // set transformatino to reference coordinates\n\n\t  if (locfaces[0].GetNP() == 3)\n\t    {\n\t      trans.Set (locpoints[locfaces[0].PNumMod(1+rotind)],\n\t\t\t locpoints[locfaces[0].PNumMod(2+rotind)],\n\t\t\t locpoints[locfaces[0].PNumMod(3+rotind)], hshould);\n\t    }\n\t  else\n\t    {\n\t      trans.Set (locpoints[locfaces[0].PNumMod(1+rotind)],\n\t\t\t locpoints[locfaces[0].PNumMod(2+rotind)],\n\t\t\t locpoints[locfaces[0].PNumMod(4+rotind)], hshould);\n\t    }\n\n\t  // trans.ToPlain (locpoints, plainpoints);\n\n          plainpoints.SetSize (locpoints.Size());\n          for (auto i : locpoints.Range())\n            trans.ToPlain (locpoints[i], plainpoints[i]);\n          \n          for (auto i : allowpoint.Range())\n            if (plainpoints[i].Z() > 0)\n              allowpoint[i] = false;\n\n\t  stat.cnttrials++;\n\n\n\t  if (stat.cnttrials % 100 == 0)\n\t    {\n\t      (*testout) << \"\\n\";\n\t      for(int i : canuse.Range()) \n                {\n                  (*testout) << foundmap[i] << \"/\" \n                             << canuse[i] << \"/\"\n                             << ruleused[i] << \" map/can/use rule \" << rules[i]->Name() << \"\\n\";\n                }\n\t      (*testout) << endl;\n\t    }\n\n\t  // NgProfiler::StartTimer (meshing3_timer_c);\n          // meshing3_timer_c.Start();\n\n\t  found = ApplyRules (plainpoints, allowpoint, \n\t\t\t      locfaces, locfacesplit, connectedpairs,\n\t\t\t      locelements, delfaces, \n\t\t\t      stat.qualclass, mp.sloppy, rotind, err);\n\n\t  if (found >= 0) impossible = 0;\n\t  if (found < 0) found = 0;\n\n          // meshing3_timer_c.Stop();\n\t  // NgProfiler::StopTimer (meshing3_timer_c);\t  \n\n\t  if (!found) loktestmode = 0;\n\n\t  // NgProfiler::RegionTimer reg2 (meshing3_timer_d);\t  \n\t  \n\t  if (loktestmode)\n\t    {\n\t      (*testout) << \"plainpoints = \" << endl << plainpoints << endl;\n\t      (*testout) << \"Applyrules found \" << found << endl;\n\t    }\n\n\t  if (found) stat.cntsucc++;\n\n\t  locpoints.SetSize (plainpoints.Size());\n          /*\n\t  for (int i = oldnp+1; i <= plainpoints.Size(); i++)\n\t    trans.FromPlain (plainpoints.Elem(i), locpoints.Elem(i));\n          */\n\t  for (auto i : plainpoints.Range().Modify(oldnp,0))\n\t    trans.FromPlain (plainpoints[i], locpoints[i]);\n          \n\n\n\t  // avoid meshing from large to small mesh-size\n\t  if (uselocalh && found && stat.qualclass <= 3)\n\t    {\n\t      for (int i = 1; i <= locelements.Size(); i++)\n\t\t{\n\t\t  Point3d pmin = locpoints[locelements.Get(i).PNum(1)];\n\t\t  Point3d pmax = pmin;\n\t\t  for (j = 2; j <= 4; j++)\n\t\t    {\n\t\t      const Point3d & hp = locpoints[locelements.Get(i).PNum(j)];\n\t\t      pmin.SetToMin (hp);\n\t\t      pmax.SetToMax (hp);\n\t\t    }\n\n\t\t  if (mesh.GetMinH (pmin, pmax) < 0.4 * hshould / mp.sloppy)\n\t\t    found = 0;\n\t\t}\n\t    }\n\t  if (found)\n\t    {\n\t      for (int i = 1; i <= locelements.Size(); i++)\n\t\tfor (int j = 1; j <= 4; j++)\n\t\t  {\n\t\t    const Point3d & hp = locpoints[locelements.Get(i).PNum(j)];\n\t\t    if (Dist (hp, pmid) > hinner)\n\t\t      found = 0;\n\t\t  }\n\t    }\n\n\n\t  if (found)\n\t    ruleused[found-1]++;\n          \n\n\t  // plotstat->Plot(stat);\n\t  \n\t  if (stat.cntelem != plotstat_oldne)\n\t    {\n\t      plotstat_oldne = stat.cntelem;\n\n\t      PrintMessageCR (5, \"El: \", stat.cntelem,\n\t\t\t      //\t    << \" trials: \" << stat.cnttrials\n\t\t\t      \" faces: \", stat.nff,\n\t\t\t      \" vol = \", float(100 * stat.vol / stat.vol0));\n  \n\t      multithread.percent = 100 -  100.0 * stat.vol / stat.vol0;\n\t    }\n\n\n\t  if (found && (!hasfound || err < minerr) )\n\t    {\n\t      \n\t      if (testmode)\n\t\t{\n\t\t  (*testout) << \"found is active, 3\" << endl;\n\t\t  //for(int i = 1; i <= plainpoints.Size(); i++)\n                  for(auto i : plainpoints.Range())\n\t\t    {\n\t\t      (*testout) << \"p\";\n\t\t      if (i < pindex.Range().Next())\n\t\t\t(*testout) << pindex[i] << \": \";\n\t\t      else\n\t\t\t(*testout) << \"new: \";\n\t\t      (*testout) << plainpoints[i] << endl;\n\t\t    }\n\t\t}\n\t      \n\t      \n\t      \n\t      hasfound = found;\n\t      minerr = err;\n\t      \n\t      tempnewpoints.SetSize (0);\n\t      // for(int i = oldnp+1; i <= locpoints.Size(); i++)\n              for (auto i : locpoints.Range().Modify(oldnp,0))\n\t\ttempnewpoints.Append (locpoints[i]);\n\t      \n\t      tempnewfaces.SetSize (0);\n\t      // for(int i = oldnf+1; i <= locfaces.Size(); i++)\n              for (auto i : locfaces.Range().Modify(oldnf,0))              \n\t\ttempnewfaces.Append (locfaces[i]);\n\t      \n\t      tempdelfaces.SetSize (0);\n\t      // for(int i = 1; i <= delfaces.Size(); i++)\n              for (auto i : delfaces.Range())\n\t\ttempdelfaces.Append (delfaces[i]);\n\t      \n\t      templocelements.SetSize (0);\n\t      // for(int i = 1; i <= locelements.Size(); i++)\n              for (auto i : locelements.Range())\n\t\ttemplocelements.Append (locelements[i]);\n\n\t      /*\n\t      optother =\n\t\tstrcmp (problems[found], \"other\") == 0;\n\t      */\n\t    }\n\t  \n\t  locpoints.SetSize (oldnp);\n\t  locfaces.SetSize (oldnf);\n\t  delfaces.SetSize (0);\n\t  locelements.SetSize (0);\n\t}\n      \n      \n\n      if (hasfound)\n\t{\n\n\t  /*\n\t  if (optother)\n\t    (*testout) << \"Other is optimal\" << endl;\n\n\t  if (minother < minwithoutother)\n\t    {\n\t      (*testout) << \"Other is better, \" << minother << \" less \" << minwithoutother << endl;\n\t    }\n\t    */\n\n\t  for(int i = 1; i <= tempnewpoints.Size(); i++)\n\t    locpoints.Append (tempnewpoints.Get(i));\n\t  for(int i = 1; i <= tempnewfaces.Size(); i++)\n\t    locfaces.Append (tempnewfaces.Get(i));\n\t  for(int i = 1; i <= tempdelfaces.Size(); i++)\n\t    delfaces.Append (tempdelfaces.Get(i));\n\t  for(int i = 1; i <= templocelements.Size(); i++)\n\t    locelements.Append (templocelements.Get(i));\n\n\n\t  if (loktestmode)\n\t    {\n\t      (*testout) << \"apply rule\" << endl;\n\t      for (auto i : locpoints.Range())\n\t\t{\n\t\t  (*testout) << \"p\";\n\t\t  if (pindex.Range().Contains(i))\n\t\t    (*testout) << pindex[i] << \": \";\n\t\t  else\n\t\t    (*testout) << \"new: \";\n\t\t  (*testout) << locpoints[i] << endl;\n\t\t}\n\t    }\n\n\n\n\t  pindex.SetSize(locpoints.Size());\n\n\t  // for (int i = oldnp+1; i <= locpoints.Size(); i++)\n          for (auto i : locpoints.Range().Modify(oldnp,0))\n\t    {\n\t      PointIndex globind = mesh.AddPoint (locpoints[i]);\n\t      pindex[i] = adfront -> AddPoint (locpoints[i], globind);\n\t    }\n\n\t  for (int i = 1; i <= locelements.Size(); i++)\n\t    {\n\t      Point3d * hp1, * hp2, * hp3, * hp4;\n\t      hp1 = &locpoints[locelements.Get(i).PNum(1)];\n\t      hp2 = &locpoints[locelements.Get(i).PNum(2)];\n\t      hp3 = &locpoints[locelements.Get(i).PNum(3)];\n\t      hp4 = &locpoints[locelements.Get(i).PNum(4)];\n\t      \n\t      tetvol += (1.0 / 6.0) * ( Cross ( *hp2 - *hp1, *hp3 - *hp1) * (*hp4 - *hp1) );\n\n\t      for (j = 1; j <= locelements.Get(i).NP(); j++)\n\t\tlocelements.Elem(i).PNum(j) =\n\t\t  adfront -> GetGlobalIndex (pindex[locelements.Get(i).PNum(j)]);\n\n\t      mesh.AddVolumeElement (locelements.Get(i));\n\t      stat.cntelem++;\n\t    }\n\n\t  for(int i = oldnf; i < locfaces.Size(); i++)\n\t    {\n\t      for (j = 1; j <= locfaces[i].GetNP(); j++)\n\t\tlocfaces[i].PNum(j) = \n\t\t  pindex[locfaces[i].PNum(j)];\n\t      // (*testout) << \"add face \" << locfaces.Get(i) << endl;\n\t      adfront->AddFace (locfaces[i]);\n\t    }\n\t  \n\t  for(int i = 1; i <= delfaces.Size(); i++)\n\t    adfront->DeleteFace (findex[delfaces.Get(i)-1]);\n\t}\n      else\n\t{\n\t  adfront->IncrementClass (findex[0]);\n\t  if (impossible && mp.check_impossible)\n\t    {\n\t      (*testout) << \"skip face since it is impossible\" << endl;\n\t      for (j = 0; j < 100; j++)\n\t\tadfront->IncrementClass (findex[0]);\n\t    }\n\t}\n\n      locelements.SetSize (0);\n      // delpoints.SetSize(0);\n      delfaces.SetSize(0);\n\n      if (stat.qualclass >= mp.giveuptol)\n\tbreak;\n    }\n  \n  PrintMessage (5, \"\");  // line feed after statistics\n\n  for(int i : ruleused.Range())\n    (*testout) << setw(4) << ruleused[i]\n\t       << \" times used rule \" << rules[i] -> Name() << endl;\n\n\n  if (!mp.baseelnp && adfront->Empty())\n    return MESHING3_OK;\n\n  if (mp.baseelnp && adfront->Empty (mp.baseelnp))\n    return MESHING3_OK;\n\n  if (stat.vol < -1e-15)\n    return MESHING3_NEGVOL;\n\n  return MESHING3_NEGVOL;\n}\n\n\n\n\nenum blocktyp { BLOCKUNDEF, BLOCKINNER, BLOCKBOUND, BLOCKOUTER };\n\nvoid Meshing3 :: BlockFill (Mesh & mesh, double gh)\n{\n  static Timer t(\"Mesing3::BlockFill\"); RegionTimer reg(t);\n  \n  PrintMessage (3, \"Block-filling called (obsolete) \");\n\n  int i, j(0), i1, i2, i3, j1, j2, j3;\n  int n1, n2, n3, n, min1, min2, min3, max1, max2, max3;\n  int changed, filled;\n  double xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0);\n  double xminb, xmaxb, yminb, ymaxb, zminb, zmaxb;\n  //double rad = 0.7 * gh;\n  \n  for(int i = 1; i <= adfront->GetNP(); i++)\n    {\n      const Point3d & p = adfront->GetPoint(PointIndex(i));\n      if (i == 1)\n\t{\n\t  xmin = xmax = p.X();\n\t  ymin = ymax = p.Y();\n\t  zmin = zmax = p.Z();\n\t}\n      else\n\t{\n\t  if (p.X() < xmin) xmin = p.X();\n\t  if (p.X() > xmax) xmax = p.X();\n\t  if (p.Y() < ymin) ymin = p.Y();\n\t  if (p.Y() > ymax) ymax = p.Y();\n\t  if (p.Z() < zmin) zmin = p.Z();\n\t  if (p.Z() > zmax) zmax = p.Z();\n\t}\n    }\n  \n  xmin -= 5 * gh;\n  ymin -= 5 * gh;\n  zmin -= 5 * gh;\n  \n  n1 = int ((xmax-xmin) / gh + 5);\n  n2 = int ((ymax-ymin) / gh + 5);\n  n3 = int ((zmax-zmin) / gh + 5);\n  n = n1 * n2 * n3;\n  \n  PrintMessage (5, \"n1 = \", n1, \" n2 = \", n2, \" n3 = \", n3);\n\n  NgArray<blocktyp> inner(n);\n  NgArray<PointIndex> pointnr(n);\n  NgArray<int> frontpointnr(n);\n\n\n  // initialize inner to 1\n\n  for(int i = 1; i <= n; i++)\n    inner.Elem(i) = BLOCKUNDEF;\n\n\n  // set blocks cutting surfaces to 0\n\n  for(int i = 1; i <= adfront->GetNF(); i++)\n    {\n      const MiniElement2d & el = adfront->GetFace(i);\n      xminb = xmax; xmaxb = xmin;\n      yminb = ymax; ymaxb = ymin;\n      zminb = zmax; zmaxb = zmin;\n\n      for (j = 1; j <= 3; j++)\n\t{\n\t  const Point3d & p = adfront->GetPoint (el.PNum(j));\n\t  if (p.X() < xminb) xminb = p.X();\n\t  if (p.X() > xmaxb) xmaxb = p.X();\n\t  if (p.Y() < yminb) yminb = p.Y();\n\t  if (p.Y() > ymaxb) ymaxb = p.Y();\n\t  if (p.Z() < zminb) zminb = p.Z();\n\t  if (p.Z() > zmaxb) zmaxb = p.Z();\n\t}\n\n\t\n\n      double filldist = 0.2; // globflags.GetNumFlag (\"filldist\", 0.4);\n      xminb -= filldist * gh;\n      xmaxb += filldist * gh;\n      yminb -= filldist * gh;\n      ymaxb += filldist * gh;\n      zminb -= filldist * gh;\n      zmaxb += filldist * gh;\n\n      min1 = int ((xminb - xmin) / gh) + 1;\n      max1 = int ((xmaxb - xmin) / gh) + 1;\n      min2 = int ((yminb - ymin) / gh) + 1;\n      max2 = int ((ymaxb - ymin) / gh) + 1;\n      min3 = int ((zminb - zmin) / gh) + 1;\n      max3 = int ((zmaxb - zmin) / gh) + 1;\n\n\n      for (i1 = min1; i1 <= max1; i1++)\n\tfor (i2 = min2; i2 <= max2; i2++)\n\t  for (i3 = min3; i3 <= max3; i3++)\n\t    inner.Elem(i3 + (i2-1) * n3 + (i1-1) * n2 * n3) = BLOCKBOUND;      \n    }\n\n  \n\n\n  while (1)\n    {\n      int undefi = 0;\n      Point3d undefp;\n\n      for (i1 = 1; i1 <= n1 && !undefi; i1++)\n\tfor (i2 = 1; i2 <= n2 && !undefi; i2++)\n\t  for (i3 = 1; i3 <= n3 && !undefi; i3++)\n\t    {\n\t      i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3;\n\t      if (inner.Elem(i) == BLOCKUNDEF)\n\t\t{\n\t\t  undefi = i;\n\t\t  undefp.X() = xmin + (i1-0.5) * gh;\n\t\t  undefp.Y() = ymin + (i2-0.5) * gh;\n\t\t  undefp.Z() = zmin + (i3-0.5) * gh;\n\t\t}\n\t    }\n\t      \n      if (!undefi)\n\tbreak;\n\n      //      PrintMessage (5, \"Test point: \", undefp);\n      \n      if (adfront -> Inside (undefp))\n\t{\n\t  //\t  (*mycout) << \"inner\" << endl;\n\t  inner.Elem(undefi) = BLOCKINNER;\n\t}\n      else\n\t{\n\t  //\t  (*mycout) << \"outer\" << endl;\n\t  inner.Elem(undefi) = BLOCKOUTER;\n\t}\n\n      do\n\t{\n\t  changed = 0;\n\t  for (i1 = 1; i1 <= n1; i1++)\n\t    for (i2 = 1; i2 <= n2; i2++)\n\t      for (i3 = 1; i3 <= n3; i3++)\n\t\t{\n\t\t  i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3;\n\n\t\t  for (int k = 1; k <= 3; k++)\n\t\t    {\n\t\t      switch (k)\n\t\t\t{\n\t\t\tcase 1: j = i + n2 * n3; break;\n\t\t\tcase 2: j = i + n3; break;\n\t\t\tcase 3: j = i + 1; break;\n\t\t\t}\n\t\t  \n\t\t      if (j > n1 * n2 * n3) continue;\n\n\t\t      if (inner.Elem(i) == BLOCKOUTER && inner.Elem(j) == BLOCKUNDEF)\n\t\t\t{\n\t\t\t  changed = 1;\n\t\t\t  inner.Elem(j) = BLOCKOUTER;\n\t\t\t}\n\t\t      if (inner.Elem(j) == BLOCKOUTER && inner.Elem(i) == BLOCKUNDEF)\n\t\t\t{\n\t\t\t  changed = 1;\n\t\t\t  inner.Elem(i) = BLOCKOUTER;\n\t\t\t}\n\t\t      if (inner.Elem(i) == BLOCKINNER && inner.Elem(j) == BLOCKUNDEF)\n\t\t\t{\n\t\t\t  changed = 1;\n\t\t\t  inner.Elem(j) = BLOCKINNER;\n\t\t\t}\n\t\t      if (inner.Elem(j) == BLOCKINNER && inner.Elem(i) == BLOCKUNDEF)\n\t\t\t{\n\t\t\t  changed = 1;\n\t\t\t  inner.Elem(i) = BLOCKINNER;\n\t\t\t}\n\t\t    }\n\t\t}\n\t}\n      while (changed); \n\n    }\n\n\n\n  filled = 0;\n  for(int i = 1; i <= n; i++)\n    if (inner.Elem(i) == BLOCKINNER)\n      {\n\tfilled++;\n      }\n  PrintMessage (5, \"Filled blocks: \", filled);\n\n  for(int i = 1; i <= n; i++)\n    {\n      pointnr.Elem(i) = PointIndex::INVALID;\n      frontpointnr.Elem(i) = 0;\n    }\n  \n  for (i1 = 1; i1 <= n1-1; i1++)\n    for (i2 = 1; i2 <= n2-1; i2++)\n      for (i3 = 1; i3 <= n3-1; i3++)\n\t{\n\t  i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3;\n\t  if (inner.Elem(i) == BLOCKINNER)\n\t    {\n\t      for (j1 = i1; j1 <= i1+1; j1++)\n\t\tfor (j2 = i2; j2 <= i2+1; j2++)\n\t\t  for (j3 = i3; j3 <= i3+1; j3++)\n\t\t    {\n\t\t      j = j3 + (j2-1) * n3 + (j1-1) * n2 * n3;\n\t\t      if (!pointnr.Get(j).IsValid())\n\t\t\t{\n\t\t\t  Point3d hp(xmin + (j1-1) * gh, \n\t\t\t\t     ymin + (j2-1) * gh, \n\t\t\t\t     zmin + (j3-1) * gh);\n\t\t\t  pointnr.Elem(j) = mesh.AddPoint (hp);\n\t\t\t  frontpointnr.Elem(j) =\n\t\t\t    AddPoint (hp, pointnr.Elem(j));\n\n\t\t\t}\n\t\t    }\n\t    }\n\t}\n\n\n  for (i1 = 2; i1 <= n1-1; i1++)\n    for (i2 = 2; i2 <= n2-1; i2++)\n      for (i3 = 2; i3 <= n3-1; i3++)\n\t{\n\t  i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3;\n\t  if (inner.Elem(i) == BLOCKINNER)\n\t    {\n\t      int pn[9];\n\t      pn[1] = pointnr.Get(i);\n\t      pn[2] = pointnr.Get(i+1);\n\t      pn[3] = pointnr.Get(i+n3);\n\t      pn[4] = pointnr.Get(i+n3+1);\n\t      pn[5] = pointnr.Get(i+n2*n3);\n\t      pn[6] = pointnr.Get(i+n2*n3+1);\n\t      pn[7] = pointnr.Get(i+n2*n3+n3);\n\t      pn[8] = pointnr.Get(i+n2*n3+n3+1);\n\t      static int elind[][4] =\n\t      {\n\t\t{ 1, 8, 2, 4 },\n\t\t{ 1, 8, 4, 3 },\n\t\t{ 1, 8, 3, 7 },\n\t\t{ 1, 8, 7, 5 },\n\t\t{ 1, 8, 5, 6 },\n\t\t{ 1, 8, 6, 2 }\n\t      };\n\t      for (j = 1; j <= 6; j++)\n\t\t{\n\t\t  Element el(4);\n\t\t  for (int k = 1; k <= 4;  k++)\n\t\t    el.PNum(k) = pn[elind[j-1][k-1]];\n\n\t\t  mesh.AddVolumeElement (el);\n\t\t}\n\t    }\n\t}\n\n\n\n  for (i1 = 2; i1 <= n1-1; i1++)\n    for (i2 = 2; i2 <= n2-1; i2++)\n      for (i3 = 2; i3 <= n3-1; i3++)\n\t{\n\t  i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3;\n\t  if (inner.Elem(i) == BLOCKINNER)\n\t    {    \n\t      int pi1(0), pi2(0), pi3(0), pi4(0);\n\n\t      int pn1 = frontpointnr.Get(i);\n\t      int pn2 = frontpointnr.Get(i+1);\n\t      int pn3 = frontpointnr.Get(i+n3);\n\t      int pn4 = frontpointnr.Get(i+n3+1);\n\t      int pn5 = frontpointnr.Get(i+n2*n3);\n\t      int pn6 = frontpointnr.Get(i+n2*n3+1);\n\t      int pn7 = frontpointnr.Get(i+n2*n3+n3);\n\t      int pn8 = frontpointnr.Get(i+n2*n3+n3+1);\n\n\t      for (int k = 1; k <= 6; k++)\n\t\t{\n\t\t  switch (k)\n\t\t    {\n\t\t    case 1: // j3 = i3+1\n\t\t      j = i + 1;\n\t\t      pi1 = pn2;\n\t\t      pi2 = pn6;\n\t\t      pi3 = pn4;\n\t\t      pi4 = pn8;\n\t\t      break;\n\t\t    case 2: // j3 = i3-1\n\t\t      j = i - 1;\n\t\t      pi1 = pn1;\n\t\t      pi2 = pn3;\n\t\t      pi3 = pn5;\n\t\t      pi4 = pn7;\n\t\t      break;\n\t\t    case 3: // j2 = i2+1\n\t\t      j = i + n3;\n\t\t      pi1 = pn3;\n\t\t      pi2 = pn4;\n\t\t      pi3 = pn7;\n\t\t      pi4 = pn8;\n\t\t      break;\n\t\t    case 4: // j2 = i2-1\n\t\t      j = i - n3;\n\t\t      pi1 = pn1;\n\t\t      pi2 = pn5;\n\t\t      pi3 = pn2;\n\t\t      pi4 = pn6;\n\t\t      break;\n\t\t    case 5: // j1 = i1+1\n\t\t      j = i + n3*n2;\n\t\t      pi1 = pn5;\n\t\t      pi2 = pn7;\n\t\t      pi3 = pn6;\n\t\t      pi4 = pn8;\n\t\t      break;\n\t\t    case 6: // j1 = i1-1\n\t\t      j = i - n3*n2;\n\t\t      pi1 = pn1;\n\t\t      pi2 = pn2;\n\t\t      pi3 = pn3;\n\t\t      pi4 = pn4;\n\t\t      break;\n\t\t    }\n\n\t\t  if (inner.Get(j) == BLOCKBOUND)\n\t\t    {\n\t\t      MiniElement2d face;\n\t\t      face.PNum(1) = pi4;\n\t\t      face.PNum(2) = pi1;\n\t\t      face.PNum(3) = pi3;\n\t\t      AddBoundaryElement (face);\n\n\t\t      face.PNum(1) = pi1;\n\t\t      face.PNum(2) = pi4;\n\t\t      face.PNum(3) = pi2;\n\t\t      AddBoundaryElement (face);\n\n\t\t    }\n\t\t}\n\t    }\n\t}\n}\n\n\n/*\nstatic const AdFront3 * locadfront;\nstatic int TestInner (const Point3d & p)\n{\n  return locadfront->Inside (p);\n}\nstatic int TestSameSide (const Point3d & p1, const Point3d & p2)\n{\n  return locadfront->SameSide (p1, p2);\n}\n*/\n\n\n\nvoid Meshing3 :: BlockFillLocalH (Mesh & mesh, \n\t\t\t\t  const MeshingParameters & mp)\n{\n  static Timer t(\"Mesing3::BlockFillLocalH\"); RegionTimer reg(t);\n  \n  double filldist = mp.filldist;\n  \n  // (*testout) << \"blockfill local h\" << endl;\n  // (*testout) << \"rel filldist = \" << filldist << endl;\n  PrintMessage (3, \"blockfill local h\");\n\n\n  NgArray<Point<3> > npoints;\n  \n  adfront -> CreateTrees();\n\n  Box<3> bbox ( Box<3>::EMPTY_BOX );\n  double maxh = 0;\n\n  for (int i = 1; i <= adfront->GetNF(); i++)\n    {\n      const MiniElement2d & el = adfront->GetFace(i);\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  const Point3d & p1 = adfront->GetPoint (el.PNumMod(j));\n\t  const Point3d & p2 = adfront->GetPoint (el.PNumMod(j+1));\n\n\t  double hi = Dist (p1, p2);\n\t  if (hi > maxh) maxh = hi;\n\n\t  bbox.Add (p1);\n\t}\n    }\n\n\n  Point3d mpmin = bbox.PMin();\n  Point3d mpmax = bbox.PMax();\n  Point3d mpc = Center (mpmin, mpmax);\n  double d = max3(mpmax.X()-mpmin.X(), \n\t\t  mpmax.Y()-mpmin.Y(), \n\t\t  mpmax.Z()-mpmin.Z()) / 2;\n  mpmin = mpc - Vec3d (d, d, d);\n  mpmax = mpc + Vec3d (d, d, d);\n  Box3d meshbox (mpmin, mpmax);\n\n  LocalH loch2 (mpmin, mpmax, 1);\n\n  if (mp.maxh < maxh) maxh = mp.maxh;\n\n  auto loch_ptr = mesh.LocalHFunction().Copy(bbox);\n  auto & loch = *loch_ptr;\n\n  bool changed;\n  static Timer t1(\"loop1\");\n  t1.Start();\n  do \n    {\n      loch.ClearFlags();\n\n      static Timer tbox(\"adfront-bbox\");\n      tbox.Start();\n      for (int i = 1; i <= adfront->GetNF(); i++)\n\t{\n\t  const MiniElement2d & el = adfront->GetFace(i);\n\t  \n\t  Box<3> bbox (adfront->GetPoint (el[0]));\n\t  bbox.Add (adfront->GetPoint (el[1]));\n\t  bbox.Add (adfront->GetPoint (el[2]));\n\n\n\t  double filld = filldist * bbox.Diam();\n\t  bbox.Increase (filld);\n      \n      \t  loch.CutBoundary (bbox); // .PMin(), bbox.PMax());\n\t}\n      tbox.Stop();\n\n      //      locadfront = adfront;\n      loch.FindInnerBoxes (*adfront, NULL);\n\n      npoints.SetSize(0);\n      loch.GetInnerPoints (npoints);\n\n      changed = false;\n      for (int i = 1; i <= npoints.Size(); i++)\n\t{\n\t  if (loch.GetH(npoints.Get(i)) > 1.5 * maxh)\n\t    {\n\t      loch.SetH (npoints.Get(i), maxh);\n\t      changed = true;\n\t    }\n\t}\n    }\n  while (changed);\n  t1.Stop();\n\n  if (debugparam.slowchecks)\n    (*testout) << \"Blockfill with points: \" << endl;\n  for (int i = 1; i <= npoints.Size(); i++)\n    {\n      if (meshbox.IsIn (npoints.Get(i)))\n\t{\n\t  PointIndex gpnum = mesh.AddPoint (npoints.Get(i));\n\t  adfront->AddPoint (npoints.Get(i), gpnum);\n\n\t  if (debugparam.slowchecks)\n\t    {\n\t      (*testout) << npoints.Get(i) << endl;\n\t      if (!adfront->Inside(npoints.Get(i)))\n\t\t{\n\t\t  cout << \"add outside point\" << endl;\n\t\t  (*testout) << \"outside\" << endl;\n\t\t}\n\t    }\n\n\t}\n    }\n\n  \n\n  // find outer points\n  \n  static Timer tloch2(\"build loch2\");\n  tloch2.Start();\n  loch2.ClearFlags();\n\n  for (int i = 1; i <= adfront->GetNF(); i++)\n    {\n      const MiniElement2d & el = adfront->GetFace(i);\n      Point3d pmin = adfront->GetPoint (el.PNum(1));\n      Point3d pmax = pmin;\n      \n      for (int j = 2; j <= 3; j++)\n\t{\n\t  const Point3d & p = adfront->GetPoint (el.PNum(j));\n\t  pmin.SetToMin (p);\n\t  pmax.SetToMax (p);\n\t}\n      \n      loch2.SetH (Center (pmin, pmax), Dist (pmin, pmax));\n    }\n\n  for (int i = 1; i <= adfront->GetNF(); i++)\n    {\n      const MiniElement2d & el = adfront->GetFace(i);\n      Point3d pmin = adfront->GetPoint (el.PNum(1));\n      Point3d pmax = pmin;\n      \n      for (int j = 2; j <= 3; j++)\n\t{\n\t  const Point3d & p = adfront->GetPoint (el.PNum(j));\n\t  pmin.SetToMin (p);\n\t  pmax.SetToMax (p);\n\t}\n      \n      double filld = filldist * Dist (pmin, pmax);\n      pmin = pmin - Vec3d (filld, filld, filld);\n      pmax = pmax + Vec3d (filld, filld, filld);\n      // loch2.CutBoundary (pmin, pmax);\n      loch2.CutBoundary (Box<3> (pmin, pmax)); // pmin, pmax);\n    }\n  tloch2.Stop();\n\n  // locadfront = adfront;\n  loch2.FindInnerBoxes (*adfront, NULL);\n\n  npoints.SetSize(0);\n  loch2.GetOuterPoints (npoints);\n  \n  for (int i = 1; i <= npoints.Size(); i++)\n    {\n      if (meshbox.IsIn (npoints.Get(i)))\n\t{\n\t  PointIndex gpnum = mesh.AddPoint (npoints.Get(i));\n\t  adfront->AddPoint (npoints.Get(i), gpnum);\n\t}\n    }  \n}\n\n}\n"
  },
  {
    "path": "libsrc/meshing/meshing3.hpp",
    "content": "#ifndef FILE_MESHING3\n#define FILE_MESHING3\n\n#include \"meshclass.hpp\"\n#include \"adfront3.hpp\"\n#include \"ruler3.hpp\"\n\nnamespace netgen\n{\n\nenum MESHING3_RESULT\n{\n  MESHING3_OK = 0,\n  MESHING3_GIVEUP = 1,\n  MESHING3_NEGVOL = 2,\n  MESHING3_OUTERSTEPSEXCEEDED = 3,\n  MESHING3_TERMINATE = 4,\n  MESHING3_BADSURFACEMESH = 5\n};\n\n\n/// 3d volume mesh generation\nclass Meshing3\n{\n  /// current state of front\n  unique_ptr<AdFront3> adfront;\n  /// 3d generation rules\n  Array<unique_ptr<vnetrule>> rules;\n  /// counts how often a rule is used\n  Array<int> ruleused, canuse, foundmap;\n  /// describes, why a rule is not applied\n  Array<string> problems;\n  /// tolerance criterion\n  double tolfak;\npublic:\n  /// \n  Meshing3 (const string & rulefilename); \n  /// \n  Meshing3 (const char ** rulep);\n  ///\n  virtual ~Meshing3 ();\n  \n  ///\n  void LoadRules (const char * filename, const char ** prules);\n  ///\n  MESHING3_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp);\n  \n  ///\n  int ApplyRules (Array<Point3d, PointIndex> & lpoints,\n                  Array<int, PointIndex> & allowpoint,\n\t\t  Array<MiniElement2d> & lfaces, INDEX lfacesplit,\n\t\t  INDEX_2_HASHTABLE<int> & connectedpairs,\n\t\t  NgArray<Element> & elements,\n\t\t  NgArray<INDEX> & delfaces, int tolerance, \n\t\t  double sloppy, int rotind1,\n\t\t  float & retminerr);\n  \n  ///\n  PointIndex AddPoint (const Point3d & p, PointIndex globind);\n  ///\n  void AddBoundaryElement (const Element2d & elem);\n  ///\n  void AddBoundaryElement (const MiniElement2d & elem);\n  ///\n  int AddConnectedPair (const INDEX_2 & pair);\n  \n  ///\n  void BlockFill (Mesh & mesh, double gh);\n  ///\n  void BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp);\n\n  /// uses points of adfront, and puts new elements into mesh\n  void Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp);\n  ///\n  friend class PlotVolMesh;\n  ///\n  friend void TestRules ();\n};\n\n\n\n\n/// status of mesh generation\nclass MeshingStat3d\n{\npublic:\n  ///\n  MeshingStat3d ();\n  ///\n  int cntsucc;\n  ///\n  int cnttrials;\n  ///\n  int cntelem;\n  ///\n  int nff;\n  ///\n  int qualclass;\n  ///\n  double vol0;\n  ///\n  double vol;\n  ///\n  double h;\n  ///\n  int problemindex;\n};\n\n\n\n\n\n/*\ntemplate <typename POINTArray, typename FACEArray>\nextern int FindInnerPoint (POINTArray & grouppoints,\n\t\t\t   FACEArray & groupfaces,\n\t\t\t   Point3d & p);\n\n*/\n\n} // namespace netgen\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/meshtool.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#include <csg.hpp>\n#include <geometry2d.hpp>\n\nnamespace netgen\n{\n\n  int CheckSurfaceMesh (const Mesh & mesh)\n  {\n    PrintMessage (3, \"Check Surface mesh\");\n\n    int nf = mesh.GetNSE();\n    INDEX_2_HASHTABLE<int> edges(nf+2);\n    int i, j;\n    INDEX_2 i2;\n    int cnt1 = 0, cnt2 = 0;\n\n    for (i = 1; i <= nf; i++)\n      for (j = 1; j <= 3; j++)\n\t{\n\t  i2.I1() = mesh.SurfaceElement(i).PNumMod(j);\n\t  i2.I2() = mesh.SurfaceElement(i).PNumMod(j+1);\n\t  if (edges.Used(i2))\n\t    {\n\t      int hi;\n\t      hi = edges.Get(i2);\n\t      if (hi != 1) \n\t\tPrintSysError (\"CheckSurfaceMesh, hi = \", hi);\n\t      edges.Set(i2, 2);\n\t      cnt2++;\n\t    }\n\t  else\n\t    {\n\t      Swap (i2.I1(), i2.I2());\n\t      edges.Set(i2, 1);\n\t      cnt1++;\n\t    }\n\t}\n  \n\n    if (cnt1 != cnt2)\n      {\n\tPrintUserError (\"Surface mesh not consistent\");\n\t//      MyBeep(2);\n\t//      (*mycout) << \"cnt1 = \" << cnt1 << \" cnt2 = \" << cnt2 << endl;\n\treturn 0;\n      }\n    return 1;\n  }\n\n\n\n  int CheckSurfaceMesh2 (const Mesh & mesh)\n  {\n    int i, j, k;\n    const Point<3> *tri1[3], *tri2[3];\n\n    for (i = 1; i <= mesh.GetNOpenElements(); i++)\n      {\n\tPrintDot ();\n\tfor (j = 1; j < i; j++)\n\t  {\n\t    for (k = 1; k <= 3; k++)\n\t      {\n\t\ttri1[k-1] = &mesh.Point (mesh.OpenElement(i).PNum(k));\n\t\ttri2[k-1] = &mesh.Point (mesh.OpenElement(j).PNum(k));\n\t      }\n\t    if (IntersectTriangleTriangle (&tri1[0], &tri2[0]))\n\t      {\n\t\tPrintSysError (\"Surface elements are intersecting\");\n\t\t(*testout) << \"Intersecting: \" << endl;\n\t\tfor (k = 0; k <= 2; k++)\n\t\t  (*testout) << *tri1[k] << \"   \";\n\t\t(*testout) << endl;\n\t\tfor (k = 0; k <= 2; k++)\n\t\t  (*testout) << *tri2[k] << \"   \";\n\t\t(*testout) << endl;\n\t      }\n\n\t  }\n      }\n    return 0;\n  }\n\n\n\n\n\n  static double TriangleQualityInst (const Point3d & p1, const Point3d & p2,\n\t\t\t\t     const Point3d & p3)\n  {\n    // quality 0 (worst) .. 1 (optimal)\n\n    Vec3d v1, v2, v3;\n    double s1, s2, s3;\n    double an1, an2, an3;\n\n    v1 = p2 - p1;\n    v2 = p3 - p1;\n    v3 = p3 - p2;\n\n    an1 = Angle (v1, v2);\n    v1 *= -1;\n    an2 = Angle (v1, v3);\n    an3 = Angle (v2, v3);\n\n    s1 = sin (an1/2);\n    s2 = sin (an2/2);\n    s3 = sin (an3/2);\n\n    return 8 * s1 * s2 * s3;\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void MeshQuality2d (const Mesh & mesh)\n  {\n    int ncl = 20, cl;\n    NgArray<INDEX> incl(ncl);\n    INDEX i;\n    SurfaceElementIndex sei;\n    double qual;\n\n    incl = 0;\n\n    for (sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tqual = TriangleQualityInst (mesh[mesh[sei][0]],\n\t\t\t\t    mesh[mesh[sei][1]],\n\t\t\t\t    mesh[mesh[sei][2]]);\n\n\tcl = int ( (ncl-1e-3) * qual ) + 1;\n\tincl.Elem(cl)++;\n      }\n\n    (*testout) << endl << endl;\n\n    (*testout) << \"Points:           \" << mesh.GetNP() << endl;\n    (*testout) << \"Surface Elements: \" << mesh.GetNSE() << endl;\n\n    (*testout) << endl;\n    (*testout) << \"Elements in qualityclasses:\" << endl;\n    // (*testout).precision(2);\n    (*testout) << setprecision(2);\n    for (i = 1; i <= ncl; i++)\n      {\n\t(*testout) << setw(4) << double (i-1)/ncl << \" - \"\n\t\t   << setw(4) << double (i) / ncl << \": \"\n\t\t   << incl.Get(i) << endl;\n      }\n  }\n\n\n  static double TetElementQuality (const Point3d & p1, const Point3d & p2,\n\t\t\t\t   const Point3d & p3, const Point3d & p4)\n  {\n    double vol, l, l4, l5, l6;\n\n\n    Vec3d v1 = p2 - p1;\n    Vec3d v2 = p3 - p1;\n    Vec3d v3 = p4 - p1;\n\n    vol = fabs ((Cross (v1, v2) * v3)) / 6;\n    l4 = Dist (p2, p3);\n    l5 = Dist (p2, p4);\n    l6 = Dist (p3, p4);\n\n    l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6;\n\n    if (vol <= 1e-8 * l * l * l) return 1e-10;\n\n    return vol/(l*l*l) * 1832.82;    // 6^4 * sqrt(2)\n  }\n\n\n\n\n  // static double teterrpow = 2;\n\n  double CalcTetBadness (const Point3d & p1, const Point3d & p2,\n\t\t\t const Point3d & p3, const Point3d & p4, double h,\n\t\t\t const MeshingParameters & mp)\n  {\n    double vol, l, ll, lll, ll1, ll2, ll3, ll4, ll5, ll6;\n    double err;\n\n    Vec3d v1 (p1, p2);\n    Vec3d v2 (p1, p3);\n    Vec3d v3 (p1, p4);\n\n    vol = Determinant (v1, v2, v3)  * (-0.166666666666666);\n\n    ll1 = v1.Length2();\n    ll2 = v2.Length2();\n    ll3 = v3.Length2();\n    ll4 = Dist2 (p2, p3);\n    ll5 = Dist2 (p2, p4);\n    ll6 = Dist2 (p3, p4);\n\n    ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6;\n    l = sqrt (ll);\n    lll = l * ll;\n\n    if (vol <= 1e-24 * lll)\n      return 1e24;\n\n    err = 0.0080187537 * lll / vol;    // sqrt(216) / (6^4 * sqrt(2))\n\n    if (h > 0)\n      err += ll / (h * h) + \n\th * h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + \n\t\t  1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12;\n    \n    double teterrpow = mp.opterrpow;\n    if(teterrpow < 1) teterrpow = 1;\n    \n    if (teterrpow == 1) return err;\n    if (teterrpow == 2) return err*err;\n    return pow (err, teterrpow);\n  }\n\n\n  double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2,\n\t\t\t     const Point3d & p3, const Point3d & p4, double h,\n\t\t\t     int pi, Vec<3> & grad,\n\t\t\t     const MeshingParameters & mp)\n  {\n    double vol, l, ll, lll;\n    double err;\n\n    const Point3d *pp1, *pp2, *pp3, *pp4;\n\n    pp1 = &p1;\n    pp2 = &p2;\n    pp3 = &p3;\n    pp4 = &p4;\n  \n    switch (pi)\n      {\n      case 2:\n\t{\n\t  swap (pp1, pp2);\n\t  swap (pp3, pp4);\n\t  break;\n\t}\n      case 3:\n\t{\n\t  swap (pp1, pp3);\n\t  swap (pp2, pp4);\n\t  break;\n\t}\n      case 4:\n\t{\n\t  swap (pp1, pp4);\n\t  swap (pp3, pp2);\n\t  break;\n\t}\n      }\n  \n\n    Vec3d v1 (*pp1, *pp2);\n    Vec3d v2 (*pp1, *pp3);\n    Vec3d v3 (*pp1, *pp4);\n\n    Vec3d v4 (*pp2, *pp3);\n    Vec3d v5 (*pp2, *pp4);\n    Vec3d v6 (*pp3, *pp4);\n\n    vol = Determinant (v1, v2, v3) * (-0.166666666666666);\n\n    Vec3d gradvol;\n    Cross (v5, v4, gradvol);\n    gradvol *= (-1.0/6.0);\n\n\n    double ll1 = v1.Length2();\n    double ll2 = v2.Length2();\n    double ll3 = v3.Length2();\n    double ll4 = v4.Length2();\n    double ll5 = v5.Length2();\n    double ll6 = v6.Length2();\n\n    ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6;\n    l = sqrt (ll);\n    lll = l * ll;\n\n    if (vol <= 1e-24 * lll)\n      { \n\tgrad = Vec3d (0, 0, 0);\n\treturn 1e24;\n      }\n\n\n\n    Vec3d gradll1 (*pp2, *pp1);\n    Vec3d gradll2 (*pp3, *pp1);\n    Vec3d gradll3 (*pp4, *pp1);\n    gradll1 *= 2;\n    gradll2 *= 2;\n    gradll3 *= 2;\n\n    Vec3d gradll (gradll1);\n    gradll += gradll2;\n    gradll += gradll3;\n\n    /*\n    Vec3d gradll;\n    gradll = v1+v2+v3;\n    gradll *= -2;\n    */\n\n    err = 0.0080187537 * lll / vol; \n\n\n    gradll *= (0.0080187537 * 1.5 * l / vol);\n    Vec3d graderr(gradll);\n    gradvol *= ( -0.0080187537 * lll / (vol * vol) );\n    graderr += gradvol;\n  \n    if (h > 0)\n      {\n\t/*\n\tVec3d gradll1 (*pp2, *pp1);\n\tVec3d gradll2 (*pp3, *pp1);\n\tVec3d gradll3 (*pp4, *pp1);\n\tgradll1 *= 2;\n\tgradll2 *= 2;\n\tgradll3 *= 2;\n\t*/\n\terr += ll / (h*h) + \n\t  h*h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + \n\t\t  1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12;\n\n\tgraderr += (1/(h*h) - h*h/(ll1*ll1)) * gradll1;\n\tgraderr += (1/(h*h) - h*h/(ll2*ll2)) * gradll2;\n\tgraderr += (1/(h*h) - h*h/(ll3*ll3)) * gradll3;\n      }\n\n    double errpow;\n\n    double teterrpow = mp.opterrpow;\n    if(teterrpow < 1) teterrpow = 1;\n\n    if (teterrpow == 1)\n      {\n        errpow = err;\n        grad = graderr;\n      }\n    else if (teterrpow == 2)\n      {\n        errpow = err*err;   \n        grad = (2 * err) * graderr;\n      }\n    else \n      {\n        errpow = pow (err, teterrpow);\n        grad = (teterrpow * errpow / err) * graderr;\n      }\n    return errpow;\n  }\n  \n\n\n\n\n  /*\n\n  double CalcTetBadness (const Point3d & p1, const Point3d & p2,\n  const Point3d & p3, const Point3d & p4, double h)\n  {\n  double vol, l;\n  double err;\n\n\n  Vec3d v1 (p1, p2);\n  Vec3d v2 (p1, p3);\n  Vec3d v3 (p1, p4);\n\n  vol = -Determinant (v1, v2, v3) / 6;\n\n  double l1 = v1.Length();\n  double l2 = v2.Length();\n  double l3 = v3.Length();\n  double l4 = Dist (p2, p3);\n  double l5 = Dist (p2, p4);\n  double l6 = Dist (p3, p4);\n\n  l = l1 + l2 + l3 + l4 + l5 + l6;\n\n  // just for timing\n  // l += 1e-40 * CalcTetBadnessNew (p1, p2, p3, p4, h);\n\n  if (vol <= 1e-24 * l * l * l)\n  { \n  return 1e24;\n  }\n\n  err = (l*l*l) / (1832.82 * vol);    // 6^4 * sqrt(2)\n  \n  if (h > 0)\n  err += l / h + \n  h * (1 / l1 + 1/l2 + 1/l3 + 1/l4 + 1/l5 + 1/l6) - 12;\n\n  return pow (err, teterrpow);\n  }\n\n\n  \n  double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2,\n  const Point3d & p3, const Point3d & p4, double h,\n  int pi, Vec3d & grad)\n  {\n  double vol, l;\n  double err;\n\n  const Point3d *pp1, *pp2, *pp3, *pp4;\n\n  pp1 = &p1;\n  pp2 = &p2;\n  pp3 = &p3;\n  pp4 = &p4;\n  \n  switch (pi)\n  {\n  case 2:\n  {\n  swap (pp1, pp2);\n  swap (pp3, pp4);\n  break;\n  }\n  case 3:\n  {\n  swap (pp1, pp3);\n  swap (pp2, pp4);\n  break;\n  }\n  case 4:\n  {\n  swap (pp1, pp4);\n  swap (pp3, pp2);\n  break;\n  }\n  }\n  \n\n  Vec3d v1 (*pp1, *pp2);\n  Vec3d v2 (*pp1, *pp3);\n  Vec3d v3 (*pp1, *pp4);\n\n  Vec3d v4 (*pp2, *pp3);\n  Vec3d v5 (*pp2, *pp4);\n  Vec3d v6 (*pp3, *pp4);\n\n\n  //   Vec3d n;\n  //   Cross (v1, v2, n);\n  //   vol = - (n * v3) / 6;\n\n\n  vol = -Determinant (v1, v2, v3) / 6;  \n\n  Vec3d gradvol;\n  Cross (v5, v4, gradvol);\n  gradvol *= (-1.0/6.0);\n\n\n  double l1 = v1.Length();\n  double l2 = v2.Length();\n  double l3 = v3.Length();\n  double l4 = v4.Length();\n  double l5 = v5.Length();\n  double l6 = v6.Length();\n\n  l = l1 + l2 + l3 +l4 + l5 + l6;\n\n  Vec3d gradl1 (*pp2, *pp1);\n  Vec3d gradl2 (*pp3, *pp1);\n  Vec3d gradl3 (*pp4, *pp1);\n  gradl1 /= l1;\n  gradl2 /= l2;\n  gradl3 /= l3;\n\n  Vec3d gradl (gradl1);\n  gradl += gradl2;\n  gradl += gradl3;\n\n\n  if (vol <= 1e-24 * l * l * l)\n  { \n  grad = Vec3d (0, 0, 0);\n  return 1e24;\n  }\n\n\n  double c1 = 1.0 / 1832.82;      // 6^4 * sqrt(2)\n  err = c1 * (l*l*l) / vol; \n\n\n  gradl *= (c1 * 3 * l * l / vol);\n  Vec3d graderr(gradl);\n  gradvol *= ( -c1 * l * l * l / (vol * vol) );\n  graderr+= gradvol;\n  \n  if (h > 0)\n  {\n  err += l / h + \n  h * ( 1 / l1 + 1 / l2 + 1 / l3 + \n  1 / l4 + 1 / l5 + 1 / l6 ) - 12;\n\n  graderr += (1/h - h/(l1*l1)) * gradl1;\n  graderr += (1/h - h/(l2*l2)) * gradl2;\n  graderr += (1/h - h/(l3*l3)) * gradl3;\n  cout << \"?\";\n  }\n\n  double errpow = pow (err, teterrpow);\n  grad = (teterrpow * errpow / err) * graderr;\n  \n  return errpow;\n  }\n  \n  */\n\n\n\n\n  \n  /*\n    double CalcVolume (const NgArray<Point3d> & points,\n    const Element & el)\n    {\n    Vec3d v1 = points.Get(el.PNum(2)) - \n    points.Get(el.PNum(1));\n    Vec3d v2 = points.Get(el.PNum(3)) - \n    points.Get(el.PNum(1));\n    Vec3d v3 = points.Get(el.PNum(4)) - \n    points.Get(el.PNum(1)); \n         \n    return -(Cross (v1, v2) * v3) / 6;\t \n    }  \n  */\n\n  double CalcVolume (const NgArray<Point3d> & points, \n\t\t     const NgArray<Element> & elements)\n  {\n    double vol;\n    Vec3d v1, v2, v3;\n  \n    vol = 0;\n    for (int i = 0; i < elements.Size(); i++)\n      {\n\tv1 = points.Get(elements[i][1]) - points.Get(elements[i][0]);\n\tv2 = points.Get(elements[i][2]) - points.Get(elements[i][0]);\n\tv3 = points.Get(elements[i][3]) - points.Get(elements[i][0]);\n\tvol -= (Cross (v1, v2) * v3) / 6;\t \n      }\n    return vol;\n  }\n\n  \n  \n\n  void MeshQuality3d (const Mesh & mesh, NgArray<int> * inclass)\n  { \n    int ncl = 20;\n    signed int cl;\n    NgArray<INDEX> incl(ncl);\n    INDEX i;\n    double qual;\n    double sum = 0;\n    int nontet  = 0;\n\n    for (i = 1; i <= incl.Size(); i++)\n      incl.Elem(i) = 0;\n\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tif (mesh[ei].GetType() != TET)\n\t  {\n\t    nontet++;\n\t    continue;\n\t  }\n\n\tqual = TetElementQuality (mesh.Point(mesh[ei][0]),\n\t\t\t\t  mesh.Point(mesh[ei][1]),\n\t\t\t\t  mesh.Point(mesh[ei][2]),\n\t\t\t\t  mesh.Point(mesh[ei][3]));\n\n\tif (qual > 1) qual = 1;\n\tcl = int (ncl * qual ) + 1;\n     \n\tif (cl < 1) cl = 1; \n\tif (cl > ncl) cl = ncl;\n\n\tincl.Elem(cl)++;\n\tif (inclass) (*inclass)[ei] = cl;\n\tsum += 1/qual;\n      }\n\n    (*testout) << endl << endl;\n    (*testout) << \"Points:           \" << mesh.GetNP() << endl;\n    (*testout) << \"Volume Elements:  \" << mesh.GetNE() << endl;\n    if (nontet)\n      (*testout) << nontet << \" non tetrahedral elements\" << endl;\n    (*testout) << endl;\n\n    (*testout) << \"Volume elements in qualityclasses:\" << endl;\n    (*testout) << setprecision(2);\n    for (i = 1; i <= ncl; i++)\n      {\n\t(*testout) << setw(4) << double (i-1)/ncl << \" - \"\n\t\t   << setw(4) << double (i) / ncl << \": \"\n\t\t   << incl.Get(i) << endl;\n      }\n    (*testout) << \"total error: \" << sum << endl;\n  }\n\n\n  void SaveEdges (const Mesh & mesh, const char * geomfile, double h, char * filename)\n  {\n    ofstream of (filename);\n    int i;\n    const Segment * seg;\n  \n    of << \"edges\" << endl;\n    of << geomfile << endl;\n    of << h << endl;\n\n    of << mesh.GetNP() << endl;\n    for (i = 1; i <= mesh.GetNP(); i++)\n      of << mesh.Point(i)(0) << \" \"\n\t << mesh.Point(i)(1) << \" \"\n\t << mesh.Point(i)(2) << \"\\n\";\n    \n    of << 2 * mesh.GetNSeg() << endl;\n    for (i = 1; i <= mesh.GetNSeg(); i++)\n      {\n\tseg = &mesh.LineSegment(i);\n\n\tof << (*seg)[1] << \" \" << (*seg)[0] << \" \" << seg->si << \"\\n\";\n      }\n   \n  }\n\n\n  void SaveSurfaceMesh (const Mesh & mesh,\n\t\t\tdouble h,\n\t\t\tchar * filename)\n\n  {\n    INDEX i;\n\n    ofstream outfile(filename);\n\n    outfile << \"surfacemesh\" << endl;\n    outfile << h << endl;\n\n    outfile << mesh.GetNP() << endl;\n    for (i = 1; i <= mesh.GetNP(); i++)\n      outfile << mesh.Point(i)(0) << \" \"\n\t      << mesh.Point(i)(1) << \" \"\n\t      << mesh.Point(i)(2) << endl;\n\n  \n\n    outfile << mesh.GetNSE() << endl;\n    for (i = 1; i <= mesh.GetNSE(); i++)\n      {\n\tconst Element2d & el = mesh.SurfaceElement(i);\n\n\tif (mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0)\n\t  outfile << mesh.SurfaceElement(i).PNum(1) << \" \"\n\t\t  << mesh.SurfaceElement(i).PNum(2) << \" \"\n\t\t  << mesh.SurfaceElement(i).PNum(3) << endl;\n\tif (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0)\n\t  outfile << mesh.SurfaceElement(i).PNum(1) << \" \"\n\t\t  << mesh.SurfaceElement(i).PNum(3) << \" \"\n\t\t  << mesh.SurfaceElement(i).PNum(2) << endl;\n      }\n  }\n\n\n#ifdef OLD\n  void Save2DMesh (\n\t\t   const Mesh & mesh2d,\n\t\t   const NgArray<SplineSegment *> * splines,\n\t\t   ostream & outfile)\n\n  {\n    int i, j;\n    outfile.precision (6);\n  \n    outfile << \"areamesh2\" << endl;\n\n\n    outfile << endl;\n    outfile << mesh2d.GetNSeg() << endl;\n    for (i = 1; i <= mesh2d.GetNSeg(); i++)\n      outfile << mesh2d.LineSegment(i).si << \"        \"\n\t      << mesh2d.LineSegment(i)[0] << \" \"\n\t      << mesh2d.LineSegment(i)[1] << \"  \" << endl;\n  \n\n    outfile << mesh2d.GetNSE() << endl;\n    for (i = 1; i <= mesh2d.GetNSE(); i++)\n      {\n\toutfile << mesh2d.SurfaceElement(i).GetIndex() << \"         \";\n\toutfile << mesh2d.SurfaceElement(i).GetNP() << \" \";\n\tfor (j = 1; j <= mesh2d.SurfaceElement(i).GetNP(); j++)\n\t  outfile << mesh2d.SurfaceElement(i).PNum(j) << \" \";\n\toutfile << endl;\n      }\n\n    outfile << mesh2d.GetNP() << endl;\n    for (i = 1; i <= mesh2d.GetNP(); i++)\n      outfile << mesh2d.Point(i).X() << \" \"\n\t      << mesh2d.Point(i).Y() << endl;\n\n    if (splines)\n      {\n\toutfile << splines->Size() << endl;\n\tfor (i = 1; i <= splines->Size(); i++)\n\t  splines->Get(i) -> PrintCoeff (outfile);\n      }\n    else\n      outfile << \"0\" << endl;\n  }\n#endif\n\n\n\n\n\n\n\n\n  void SaveVolumeMesh (const Mesh & mesh, \n\t\t       const NetgenGeometry & geometry,\n\t\t       char * filename)\n  {\n    INDEX i;\n\n    ofstream outfile(filename);\n    outfile << \"volumemesh\" << endl;\n\n    outfile << mesh.GetNSE() << endl;\n    for (i = 1; i <= mesh.GetNSE(); i++)\n      {\n\tif (mesh.SurfaceElement(i).GetIndex())\n\t  outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).SurfNr()\n\t\t  << \"\\t\";\n\telse\n\t  outfile << \"0\" << \"\\t\";\n\toutfile << mesh.SurfaceElement(i)[0] << \" \"\n\t\t<< mesh.SurfaceElement(i)[1] << \" \"\n\t\t<< mesh.SurfaceElement(i)[2] << endl;\n      }\n    outfile << mesh.GetNE() << endl;\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      outfile << mesh[ei].GetIndex() << \"\\t\"\n\t      << mesh[ei][0] << \" \" << mesh[ei][1] << \" \"\n\t      << mesh[ei][2] << \" \" << mesh[ei][3] << endl;\n\n    outfile << mesh.GetNP() << endl;\n    for (i = 1; i <= mesh.GetNP(); i++)\n      outfile << mesh.Point(i)(0) << \" \"\n\t      << mesh.Point(i)(1) << \" \"\n\t      << mesh.Point(i)(2) << endl;\n\n#ifdef SOLIDGEOM\n    outfile << geometry.GetNSurf() << endl;\n    for (i = 1; i <= geometry.GetNSurf(); i++)\n      geometry.GetSurface(i) -> Print (outfile);\n#endif\n  }\n\n\n\n\n  int CheckCode ()\n  {\n    return 1;\n\n    /*\n      char st[100];\n      ifstream ist(\"pw\");\n\n      if (!ist.good()) return 0;\n      ist >> st;\n      if (strcmp (st, \"JKULinz\") == 0) return 1;\n      return 0;\n    */\n  }\n\n\n\n  /* ******************** CheckMesh ******************************* */\n\n  /// Checks, whether mesh contains a valid 3d mesh\n  int CheckMesh3D (const Mesh & mesh)\n  {\n    INDEX_3_HASHTABLE<int> faceused(mesh.GetNE()/3);\n    INDEX i;\n    int j, k, l;\n    INDEX_3 i3;\n    int ok = 1;\n    ElementIndex ei;\n\n    for (i = 1; i <= mesh.GetNSE(); i++)\n      {\n\tconst Element2d & el = mesh.SurfaceElement(i);\n      \n\tif (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0 ||\n\t    mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0)\n\t  {\n\t    for (j = 1; j <= 3; j++)\n\t      i3.I(j) = el.PNum(j);\n\t  \n\t    i3.Sort();\n\t    faceused.Set (i3, 1);\n\t  }\n      }\n  \n    for (ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tconst Element & el = mesh[ei];\n\n\tfor (j = 1; j <= 4; j++)\n\t  {\n\t    l = 0;\n\t    for (k = 1; k <= 4; k++)\n\t      {\n\t\tif (j != k)\n\t\t  {\n\t\t    l++;\n\t\t    i3.I(l) = el.PNum(k);\n\t\t  }\n\t      }\n\n\t    i3.Sort();\n\t    if (faceused.Used(i3))\n\t      faceused.Set(i3, faceused.Get(i3)+1);\n\t    else\n\t      faceused.Set (i3, 1);\n\t  }\n      }\n\n\n    for (i = 1; i <= mesh.GetNSE(); i++)\n      {\n\tconst Element2d & el = mesh.SurfaceElement(i);\n\n\tfor (j = 1; j <= 3; j++)\n\t  i3.I(j) = el.PNum(j);\n      \n\ti3.Sort();\n\tk = faceused.Get (i3);\n\tif (k != 2)\n\t  {\n\t    ok = 0;\n\t    (*testout) << \"face \" << i << \" with points \" \n\t\t       << i3.I1() << \"-\" << i3.I2() << \"-\" << i3.I3() \n\t\t       << \" has \" << k << \" elements\" << endl;\n\t  }\n      }\n  \n    for (ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tconst Element & el = mesh[ei];\n\n\tfor (j = 1; j <= 4; j++)\n\t  {\n\t    l = 0;\n\t    for (k = 1; k <= 4; k++)\n\t      {\n\t\tif (j != k)\n\t\t  {\n\t\t    l++;\n\t\t    i3.I(l) = el.PNum(k);\n\t\t  }\n\t      }\n\n\t    i3.Sort();\n\t    k = faceused.Get(i3);\n\t    if (k != 2)\n\t      {\n\t\tok = 0;\n\t\t(*testout) << \"element \" << ei << \" with face \" \n\t\t\t   << i3.I1() << \"-\" << i3.I2() << \"-\"\n\t\t\t   << i3.I3() \n\t\t\t   << \" has \" << k << \" elements\" << endl;\n\t      }\n\t  }\n      }\n\n\n\n\n\n    /*\n      for (i = 1; i <= faceused.GetNBags(); i++)\n      for (j = 1; j <= faceused.GetBagSize(i); j++)\n      {\n      faceused.GetData(i, j, i3, k);\n      if (k != 2)\n      {\n      (*testout) << \"Face: \" << i3.I1() << \"-\" \n      << i3.I2() << \"-\" << i3.I3() << \" has \" \n      << k << \" Faces \" << endl;\n      cerr << \"Face Error\" << endl;\n      ok = 0;\n      }\n      }\n    */\n\n\n    if (!ok)\n      {\n\t(*testout) << \"surfelements: \" << endl;\n\tfor (i = 1; i <= mesh.GetNSE(); i++)\n\t  {\n\t    const Element2d & el = mesh.SurfaceElement(i);\n\t    (*testout) << setw(5) << i << \":\" \n\t\t       << setw(6) << el.GetIndex() \n\t\t       << setw(6) << el.PNum(1) \n\t\t       << setw(4) << el.PNum(2) \n\t\t       << setw(4) << el.PNum(3)  << endl;\n\t  }\n\t(*testout) << \"volelements: \" << endl;\n\tfor (ei = 0; ei < mesh.GetNE(); ei++)\n\t  {\n\t    const Element & el = mesh[ei];\n\t    (*testout) << setw(5) << i << \":\" \n\t\t       << setw(6) << el.GetIndex() \n\t\t       << setw(6) << el[0] << setw(4) << el[1]\n\t\t       << setw(4) << el[2] << setw(4) << el[3] << endl;\n\t  }\n      }\n\n\n    return ok;\n  }\n\n\n\n  void RemoveProblem (Mesh & mesh, int domainnr)\n  {\n    int i, j, k;\n  \n    mesh.FindOpenElements(domainnr);\n    int np = mesh.GetNP();\n\n    Array<bool, PointIndex> ppoints(np);\n  \n    // int ndom = mesh.GetNDomains();\n\n    PrintMessage (3, \"Elements before Remove: \", mesh.GetNE());\n    // for (k = 1; k <= ndom; k++)\n    k = domainnr;\n      {\n\tppoints = false;\n      \n\tfor (i = 1; i <= mesh.GetNOpenElements(); i++)\n\t  {\n\t    const Element2d & sel = mesh.OpenElement(i);\n\t    if (sel.GetIndex() == k)\n\t      {\n\t\tfor (j = 1; j <= sel.GetNP(); j++)\n\t\t  ppoints[sel.PNum(j)] = true;\n\t      }\n\t  }\n\n\tfor (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n\t  {\n\t    const Element & el = mesh[ei];\n\t    if (el.GetIndex() == k)\n\t      {\n\t\tint todel = 0;\n\t\tfor (j = 0; j < el.GetNP(); j++)\n\t\t  if (ppoints[el[j]])\n\t\t    todel = 1;\n\t      \n\t\tif (el.GetNP() != 4)\n\t\t  todel = 0;\n\t      \n\t\tif (todel)\n\t\t  {\n\t\t    mesh[ei].Delete();\n\t\t    // ei--;\n\t\t  }\n\t      }\n\t  }\n      }\n  \n    mesh.Compress();\n    PrintMessage (3, \"Elements after Remove: \", mesh.GetNE());\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/meshtool.hpp",
    "content": "#ifndef NETGEN_MESHTOOL_HPP\n#define NETGEN_MESHTOOL_HPP\n\n// #include \"../general/ngarray.hpp\"\n// #include \"../gprim/geom3d.hpp\"\n// #include \"../gprim/geomobjects.hpp\"\n\n#include \"meshtype.hpp\"\n#include \"meshclass.hpp\"\n\nnamespace netgen {\n///\nextern void MeshQuality2d (const Mesh & mesh);\n\n///\nextern void MeshQuality3d (const Mesh & mesh,\n\t\t\t   NgArray<int> * inclass = NULL);\n\n///\nextern void SaveEdges (const Mesh & mesh, \n\t\t       const char * geomfile, \n\t\t       double h, \n\t\t       char * filename);\n\n///\nextern void SaveSurfaceMesh (const Mesh & mesh,\n\t\t\t     double h,\n\t\t\t     char * filename);\n/*\n///\nextern void Save2DMesh (\n         const Mesh & mesh2d,\n\t const NgArray<class SplineSegment*> * splines,\n         ostream & outfile);\n*/\n\nclass Surface;\n///\nextern void SaveVolumeMesh (\n         const NgArray<Point3d> & points,\n         const NgArray<Element> & elements,\n         const NgArray<Element> & volelements,\n         const NgArray<Surface*> & surfaces,\n         char * filename);\n\n///\nvoid SaveVolumeMesh (const Mesh & mesh, \n\t\t     const class NetgenGeometry & geometry,\n\t\t     char * filename);\n\n///\nextern int CheckCode ();\n\n\n///\nextern double CalcTetBadness (const Point3d & p1, const Point3d & p2,\n\t\t\t      const Point3d & p3, const Point3d & p4, \n\t\t\t      double h,\n\t\t\t      const MeshingParameters & mp);\n///\nextern double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2,\n\t\t\t\t  const Point3d & p3, const Point3d & p4, \n\t\t\t\t  double h, int pi,\n\t\t\t\t  Vec<3> & grad,\n\t\t\t\t  const MeshingParameters & mp);\n\n\n/** Calculates volume of an element.\n  The volume of the tetrahedron el is computed\n */\n// extern double CalcVolume (const NgArray<Point3d> & points,\n//        const Element & el);  \n\n/** The total volume of all elements is computed.\n  This function calculates the volume of the mesh */\nextern double CalcVolume (const NgArray<Point3d> & points, \n\tconst NgArray<Element> & elements);\n\n///\nextern int CheckSurfaceMesh (const Mesh & mesh);\n\n///\nextern int CheckSurfaceMesh2 (const Mesh & mesh);\n///\nextern int CheckMesh3D (const Mesh & mesh);\n///\nextern void RemoveProblem (Mesh & mesh, int domainnr);\n\n} // namespace netgen\n#endif // NETGEN_MESHTOOL_HPP\n"
  },
  {
    "path": "libsrc/meshing/meshtype.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"  \n\nnamespace netgen\n{\n  int MultiPointGeomInfo :: \n  AddPointGeomInfo (const PointGeomInfo & gi)\n  {\n    for (auto & pgi : mgi)\n      if (pgi.trignum == gi.trignum)\n\treturn 0;\n  \n    mgi.Append(gi);\n    return 0;\n  }\n  \n\n\n#ifdef PARALLEL\n\n  /*\n    working locally, but not too much at once ...\n     \n  template <int N>\n  NG_MPI_Datatype NgMPI_CommitType ( std::array<int,N> ablocklen,\n                                     std::array<std::ptrdiff_t,N> adispl,\n                                     std::array<NG_MPI_Datatype,N> atypes,\n                                     size_t aext )\n  {\n    std::array<NG_MPI_Aint,N> displ;\n    for (int i = 0; i < N; i++)\n      displ[i] = adispl[i];\n    \n    NG_MPI_Datatype htype, type;\n    NG_MPI_Type_create_struct (N, &ablocklen[0], &displ[0], &atypes[0], &htype);\n    NG_MPI_Type_commit ( &htype );\n\n    NG_MPI_Aint lb, ext;\n    ext = aext;\n    \n    NG_MPI_Type_get_extent (htype, &lb, &ext);\n\n    NG_MPI_Type_create_resized (htype, lb, ext, &type);\n    NG_MPI_Type_commit ( &type );\n\n    return type;\n  }\n                                     \n                                     \n\n  NG_MPI_Datatype MeshPoint :: MyGetMPIType ( )\n  { \n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    if (type != NG_MPI_DATATYPE_NULL) return type;\n\n    MeshPoint hp;\n    \n    array<int,3> ablocklen = { 3, 1, 1 };\n    \n    array<ptrdiff_t,3>  adispl =\n      {\n        (char*)&hp.x[0] - (char*)&hp,\n        (char*)&hp.layer - (char*)&hp,\n        (char*)&hp.singular - (char*)&hp\n      };\n        \n    array<NG_MPI_Datatype,3> atypes = { GetMPIType(hp.x[0]),\n                                        GetMPIType(hp.layer),\n                                        GetMPIType(hp.singular) };\n    \n    type = NgMPI_CommitType<3> ( ablocklen, adispl, atypes, sizeof(MeshPoint) ); \n    return type;\n  }\n  */\n  \n  \n\n  NG_MPI_Datatype MeshPoint :: MyGetMPIType ( )\n  { \n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    static NG_MPI_Datatype htype = NG_MPI_DATATYPE_NULL;\n    if (type == NG_MPI_DATATYPE_NULL)\n      {\n\tMeshPoint hp;\n        \n        int blocklen[] = { 3, 1, 1 };\n\n\tNG_MPI_Aint displ[] = { (char*)&hp.x[0] - (char*)&hp,\n                                (char*)&hp.layer - (char*)&hp,\n                                (char*)&hp.singular - (char*)&hp };\n        \n        NG_MPI_Datatype types[] = { NG_MPI_DOUBLE, NG_MPI_INT, NG_MPI_DOUBLE };\n\n\t// *testout << \"displ = \" << displ[0] << \", \" << displ[1] << \", \" << displ[2] << endl;\n\t// *testout << \"sizeof = \" << sizeof (MeshPoint) << endl;\n\tNG_MPI_Type_create_struct (3, blocklen, displ, types, &htype);\n\tNG_MPI_Type_commit ( &htype );\n\tNG_MPI_Aint lb, ext;\n\tNG_MPI_Type_get_extent (htype, &lb, &ext);\n\t// *testout << \"lb = \" << lb << endl;\n\t// *testout << \"ext = \" << ext << endl;\n\text = sizeof (MeshPoint);\n\tNG_MPI_Type_create_resized (htype, lb, ext, &type);\n\tNG_MPI_Type_commit ( &type );\n      }\n    return type;\n  }\n\n\n  \n  NG_MPI_Datatype Element2d :: MyGetMPIType ( )\n  { \n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    static NG_MPI_Datatype htype = NG_MPI_DATATYPE_NULL;\n    if (type == NG_MPI_DATATYPE_NULL)\n      {\n\tElement2d hel;\n\tint blocklen[] = { ELEMENT2D_MAXPOINTS, 1, 1, 1 };\n\tNG_MPI_Aint displ[] =\n          { (char*)&hel.pnum[0] - (char*)&hel,\n            (char*)&hel.index - (char*)&hel,\n            (char*)&hel.typ - (char*)&hel,\n            (char*)&hel.np - (char*)&hel\n          };\n\tNG_MPI_Datatype types[] = { GetMPIType<PointIndex>(), GetMPIType(hel.index),\n                                 GetMPIType(hel.typ), GetMPIType(hel.np) };\n\t// *testout << \"displ = \" << displ[0] << \", \" << displ[1] << \", \" << displ[2] << endl;\n\t// *testout << \"sizeof = \" << sizeof (MeshPoint) << endl;\n\tNG_MPI_Type_create_struct (4, blocklen, displ, types, &htype);\n\tNG_MPI_Type_commit ( &htype );\n\tNG_MPI_Aint lb, ext;\n\tNG_MPI_Type_get_extent (htype, &lb, &ext);\n\t// *testout << \"lb = \" << lb << endl;\n\t// *testout << \"ext = \" << ext << endl;\n\text = sizeof (Element2d);\n\tNG_MPI_Type_create_resized (htype, lb, ext, &type);\n\tNG_MPI_Type_commit ( &type );\n      }\n    return type;\n  }\n\n  NG_MPI_Datatype Element :: MyGetMPIType ( )\n  {\n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    static NG_MPI_Datatype htype = NG_MPI_DATATYPE_NULL;\n    if (type == NG_MPI_DATATYPE_NULL)\n      {\n\tElement hel;\n\tint blocklen[] = { ELEMENT_MAXPOINTS, 1, 1, 1 };\n\tNG_MPI_Aint displ[] =\n          { (char*)&hel.pnum[0] - (char*)&hel,\n            (char*)&hel.index - (char*)&hel,\n            (char*)&hel.typ - (char*)&hel,\n            (char*)&hel.np - (char*)&hel\n          };\n\tNG_MPI_Datatype types[] = { GetMPIType<PointIndex>(), GetMPIType(hel.index),\n                                 GetMPIType(hel.typ), GetMPIType(hel.np) };\n\t// *testout << \"displ = \" << displ[0] << \", \" << displ[1] << \", \" << displ[2] << endl;\n\t// *testout << \"sizeof = \" << sizeof (MeshPoint) << endl;\n\tNG_MPI_Type_create_struct (4, blocklen, displ, types, &htype);\n\tNG_MPI_Type_commit ( &htype );\n\tNG_MPI_Aint lb, ext;\n\tNG_MPI_Type_get_extent (htype, &lb, &ext);\n\t// *testout << \"lb = \" << lb << endl;\n\t// *testout << \"ext = \" << ext << endl;\n\text = sizeof (Element);\n\tNG_MPI_Type_create_resized (htype, lb, ext, &type);\n\tNG_MPI_Type_commit ( &type );\n      }\n    return type;\n  }\n\n  NG_MPI_Datatype Segment :: MyGetMPIType ( )\n  {\n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    static NG_MPI_Datatype htype = NG_MPI_DATATYPE_NULL;\n    if (type == NG_MPI_DATATYPE_NULL)\n      {\n\tSegment hel;\n\tint blocklen[] = { 3, 1, 1, 1 };\n\tNG_MPI_Aint displ[] =\n          { (char*)&hel.pnums[0] - (char*)&hel,\n            (char*)&hel.edgenr - (char*)&hel,\n            (char*)&hel.index - (char*)&hel,\n            (char*)&hel.si - (char*)&hel\n          };\n\tNG_MPI_Datatype types[] = {\n          GetMPIType<PointIndex>(), GetMPIType(hel.edgenr), GetMPIType(hel.index), GetMPIType(hel.si)\n        };\n\t// *testout << \"displ = \" << displ[0] << \", \" << displ[1] << \", \" << displ[2] << endl;\n\t// *testout << \"sizeof = \" << sizeof (MeshPoint) << endl;\n\tNG_MPI_Type_create_struct (4, blocklen, displ, types, &htype);\n\tNG_MPI_Type_commit ( &htype );\n\tNG_MPI_Aint lb, ext;\n\tNG_MPI_Type_get_extent (htype, &lb, &ext);\n\t// *testout << \"lb = \" << lb << endl;\n\t// *testout << \"ext = \" << ext << endl;\n\text = sizeof (Segment);\n\tNG_MPI_Type_create_resized (htype, lb, ext, &type);\n\tNG_MPI_Type_commit ( &type );\n      }\n    return type;\n  }\n\n#endif\n\n\n#ifdef PARALLEL\n  NG_MPI_Datatype Element0d :: MyGetMPIType()\n  {\n    static NG_MPI_Datatype type = NG_MPI_DATATYPE_NULL;\n    static NG_MPI_Datatype htype = NG_MPI_DATATYPE_NULL;\n    if (type == NG_MPI_DATATYPE_NULL)\n      {\n\tElement0d hel;\n\tint blocklen[] = { 1, 1 };\n\tNG_MPI_Aint displ[] =\n          { (char*)&hel.pnum - (char*)&hel,\n            (char*)&hel.index - (char*)&hel,\n          };\n\tNG_MPI_Datatype types[] = {\n          GetMPIType(hel.pnum), GetMPIType(hel.index)\n        };\n\tNG_MPI_Type_create_struct (2, blocklen, displ, types, &htype);\n\tNG_MPI_Type_commit ( &htype );\n\tNG_MPI_Aint lb, ext;\n\tNG_MPI_Type_get_extent (htype, &lb, &ext);\n\t// *testout << \"lb = \" << lb << endl;\n\t// *testout << \"ext = \" << ext << endl;\n\text = sizeof (Element0d);\n\tNG_MPI_Type_create_resized (htype, lb, ext, &type);\n\tNG_MPI_Type_commit ( &type );\n      }\n    return type;\n  }\n#endif\n\n void Element0d :: DoArchive (Archive & ar)\n {\n   ar & pnum & index;\n }\n\n  Segment :: Segment() \n    : is_curved(false)\n  {\n    pnums[0] = PointIndex::INVALID;\n    pnums[1] = PointIndex::INVALID;\n    edgenr = -1;\n    index = -1;\n    singedge_left = 0.;\n    singedge_right = 0.;\n    seginfo = 0;\n\n    si = -1;\n\n    domin = -1;\n    domout = -1;\n    tlosurf = -1;\n\n    surfnr1 = -1;\n    surfnr2 = -1;\n    pnums[2] = PointIndex::INVALID;\n    meshdocval = 0;\n    geominfo[0].trignum=-1;\n    geominfo[1].trignum=-1;\n\n    epgeominfo[0].edgenr = -1;\n    epgeominfo[0].dist = 0;\n    epgeominfo[1].edgenr = -1;\n    epgeominfo[1].dist = 0;\n  }    \n\n  void Segment :: DoArchive (Archive & ar)\n  {\n    string * bcname_dummy = nullptr;\n    ar & pnums[0] & pnums[1] & pnums[2]\n      & edgenr & singedge_left & singedge_right\n      & si & index & domin & domout & tlosurf\n      & surfnr1 & surfnr2\n      & bcname_dummy // keep this for backward compatibility\n      & epgeominfo[0].edgenr & epgeominfo[1].edgenr;\n  }\n\n\n  ostream & operator<<(ostream  & s, const Segment & seg)\n  {\n    s << seg[0] << \"(gi=\" << seg.geominfo[0].trignum << \") - \"\n      << seg[1] << \"(gi=\" << seg.geominfo[1].trignum << \")\"\n      << \" domin = \" << seg.domin << \", domout = \" << seg.domout \n      << \" si = \" << seg.si << \", edgenr = \" << seg.edgenr;\n    return s;\n  }\n\n  // needed, e.g. for MPI communication\n  Element2d :: Element2d ()\n  {\n    for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++)\n      {\n\tpnum[i].Invalidate();\n\tgeominfo[i].trignum = 0;\n      }\n    np = 3;\n    index = 0;\n    badel = 0;\n    deleted = 0;\n    visible = 1;\n    typ = TRIG;\n    orderx = ordery = 1;\n    refflag = 1;\n    strongrefflag = false;\n    is_curved = 0;\n  } \n\n  Element2d :: Element2d (int anp)\n  { \n    for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++)\n      {\n        pnum[i].Invalidate();\n\tgeominfo[i].trignum = 0;\n      }\n    np = anp;\n    index = 0;\n    badel = 0;\n    deleted = 0;\n    visible = 1;\n    switch (np)\n      {\n      case 3: typ = TRIG; break;\n      case 4: typ = QUAD; break;\n      case 6: typ = TRIG6; break;\n      case 8: typ = QUAD8; break;\n      }\n    orderx = ordery = 1;\n    refflag = 1;\n    strongrefflag = false;\n    is_curved = (np >= 4); // false;\n  } \n\n  Element2d :: Element2d (ELEMENT_TYPE atyp)\n  { \n    for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++)\n      {\n        pnum[i].Invalidate();\n\tgeominfo[i].trignum = 0;\n      }\n\n    SetType (atyp);\n\n    index = 0;\n    badel = 0;\n    deleted = 0;\n    visible = 1;\n    orderx = ordery = 1;\n    refflag = 1;\n    strongrefflag = false;\n    is_curved = (np >= 4); // false;\n  } \n\n\n\n  Element2d :: Element2d (PointIndex pi1, PointIndex pi2, PointIndex pi3)\n  {\n    pnum[0] = pi1;\n    pnum[1] = pi2;\n    pnum[2] = pi3;\n    np = 3;\n    typ = TRIG;\n    \n    for (int i = 3; i < ELEMENT2D_MAXPOINTS; i++)\n      pnum[i].Invalidate();\n  \n    for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++)\n      geominfo[i].trignum = 0;\n    index = 0;\n    badel = 0;\n    refflag = 1;\n    strongrefflag = false;\n    deleted = 0;\n    visible = 1;\n    orderx = ordery = 1;\n    is_curved = false;\n  }\n\n  Element2d :: Element2d (PointIndex pi1, PointIndex pi2, PointIndex pi3, PointIndex pi4)\n  {\n    pnum[0] = pi1;\n    pnum[1] = pi2;\n    pnum[2] = pi3;\n    pnum[3] = pi4;\n    np = 4;\n    typ = QUAD;\n\n    pnum[4].Invalidate();\n    pnum[5].Invalidate();\n  \n    for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++)\n      geominfo[i].trignum = 0;\n    index = 0;\n    badel = 0;\n    refflag = 1;\n    strongrefflag = false;\n    deleted = 0;\n    visible = 1;\n    orderx = ordery = 1;\n    is_curved = true;\n  }\n\n\n  /*\n    void Element2d :: SetType (ELEMENT_TYPE atyp)\n    {\n    typ = atyp;\n    switch (typ)\n    {\n    case TRIG: np = 3; break;\n    case QUAD: np = 4; break;\n    case TRIG6: np = 6; break;\n    case QUAD6: np = 6; break;\n    default:\n    PrintSysError (\"Element2d::SetType, illegal type \", typ);\n    }\n    }\n  */\n\n\n  void Element2d :: GetBox (const T_POINTS & points, Box3d & box) const\n  {\n    box.SetPoint (points[pnum[0]]);\n    for (unsigned i = 1; i < np; i++)\n      box.AddPoint (points[pnum[i]]);\n  }\n\n  bool Element2d :: operator==(const Element2d & el2) const\n  {\n    bool retval = (el2.GetNP() == np);\n    for(int i= 0; retval && i<np; i++)\n      retval = (el2[i] == (*this)[i]);\n\n    return retval;\n  }\n\n\n  void Element2d :: Invert2()\n  {\n    switch (typ)\n      {\n      case TRIG:\n        {\n          Swap (pnum[1], pnum[2]);\n          break;\n        }\n      case TRIG6:\n        {\n          Swap (pnum[1], pnum[2]);\n          Swap (pnum[4], pnum[5]);\n          break;\n        }\n      case QUAD:\n        {\n          Swap (pnum[0], pnum[3]);\n          Swap (pnum[1], pnum[2]);\n          break;\n        }\n      default:\n        {\n          cerr << \"Element2d::Invert2, illegal element type \" << int(typ) << endl;\n        }\n      }\n  }\n\n  int Element2d::HasFace(const Element2d & el) const\n  {\n    //nur für tets!!! hannes\n    for (int i = 1; i <= 3; i++)\n      {\n        if (PNumMod(i)   == el[0] && \n            PNumMod(i+1) == el[1] && \n            PNumMod(i+2) == el[2])\n          {\n            return 1;\n          }\n      }\n    return 0;\n  }\n\n  void Element2d :: NormalizeNumbering2 ()\n  {\n    if (GetNP() == 3)\n      {\n        if (PNum(1) < PNum(2) && PNum(1) < PNum(3))\n          return;\n        else\n          {\n            if (PNum(2) < PNum(3))\n              {\n                PointIndex pi1 = PNum(2);\n                PNum(2) = PNum(3);\n                PNum(3) = PNum(1);\n                PNum(1) = pi1;\n              }\n            else\n              {\n                PointIndex pi1 = PNum(3);\n                PNum(3) = PNum(2);\n                PNum(2) = PNum(1);\n                PNum(1) = pi1;\n              }\n          }\n      }\n    else\n      {\n        int mini = 1;\n        for (int i = 2; i <= GetNP(); i++)\n          if (PNum(i) < PNum(mini)) mini = i;\n      \n        Element2d hel = (*this);\n        for (int i = 1; i <= GetNP(); i++)\n          PNum(i) = hel.PNumMod (i+mini-1);\n      }\n  }\n\n\n\n\n  NgArray<IntegrationPointData*> ipdtrig;\n  NgArray<IntegrationPointData*> ipdquad;\n\n\n  int Element2d :: GetNIP () const\n  {\n    int nip;\n    switch (np)\n      {\n      case 3: nip = 1; break;\n      case 4: nip = 4; break;\n      default: nip = 0; break;\n      }\n    return nip;\n  }\n\n  void Element2d :: \n  GetIntegrationPoint (int ip, Point<2> & p, double & weight) const\n  {\n    static double eltriqp[1][3] =\n      {\n        { 1.0/3.0, 1.0/3.0, 0.5 }\n      };\n\n    static double elquadqp[4][3] =\n      { \n        { 0, 0, 0.25 },\n        { 0, 1, 0.25 },\n        { 1, 0, 0.25 },\n        { 1, 1, 0.25 }\n      };\n  \n    double * pp = 0;\n    switch (typ)\n      {\n      case TRIG: pp = &eltriqp[0][0]; break;\n      case QUAD: pp = &elquadqp[ip-1][0]; break;\n      default:\n        PrintSysError (\"Element2d::GetIntegrationPoint, illegal type \", int(typ));\n      }\n\n    p[0] = pp[0];\n    p[1] = pp[1];\n    weight = pp[2];\n  }\n\n  void Element2d :: \n  GetTransformation (int ip, const NgArray<Point<2>> & points,\n                     DenseMatrix & trans) const\n  {\n    int np = GetNP();\n    DenseMatrix pmat(2, np), dshape(2, np);\n    pmat.SetSize (2, np);\n    dshape.SetSize (2, np);\n\n    Point<2> p;\n    double w;\n\n    GetPointMatrix (points, pmat);\n    GetIntegrationPoint (ip, p, w);\n    GetDShape (p, dshape);\n  \n    CalcABt (pmat, dshape, trans);\n\n    /*\n      (*testout) << \"p = \" << p  << endl\n      << \"pmat = \" << pmat << endl\n      << \"dshape = \" << dshape << endl\n      << \"tans = \" << trans << endl;\n    */\n  }\n\n  void Element2d :: \n  GetTransformation (int ip, class DenseMatrix & pmat,\n                     class DenseMatrix & trans) const\n  {\n    //  int np = GetNP();\n\n#ifdef DEBUG\n    if (pmat.Width() != np || pmat.Height() != 2)\n      {\n        (*testout) << \"GetTransofrmation: pmat doesn't fit\" << endl;\n        return;\n      }\n#endif\n\n    ComputeIntegrationPointData ();\n    DenseMatrix * dshapep = NULL;\n    switch (typ)\n      {\n      case TRIG: dshapep = &ipdtrig.Get(ip)->dshape; break;\n      case QUAD: dshapep = &ipdquad.Get(ip)->dshape; break;\n      default:\n        PrintSysError (\"Element2d::GetTransformation, illegal type \", int(typ));\n      }\n  \n    CalcABt (pmat, *dshapep, trans);\n  }\n\n\n  void Element2d :: GetShape (const Point<2> & p, Vector & shape) const\n  {\n    if (shape.Size() != GetNP())\n      {\n        cerr << \"Element::GetShape: Length not fitting\" << endl;\n        return;\n      }\n\n    switch (typ)\n      {\n      case TRIG:\n        shape(0) = 1 - p[0] - p[1];\n        shape(1) = p[0];\n        shape(2) = p[1];\n        break;\n      case QUAD:\n        shape(0) = (1-p[0]) * (1-p[1]);\n        shape(1) = p[0] * (1-p[1]);\n        shape(2) = p[0] * p[1];\n        shape(3) = (1-p[0]) * p[1];\n        break;\n      default:\n        PrintSysError (\"Element2d::GetShape, illegal type \", int(typ));\n      }\n  }\n\n\n\n  void Element2d :: GetShapeNew (const Point<2> & p, FlatVector & shape) const\n  {\n    switch (typ)\n      {\n      case TRIG:\n        {\n          shape(0) = p(0);\n          shape(1) = p(1);\n          shape(2) = 1-p(0)-p(1);\n          break;\n        }\n\n      case QUAD:\n        {\n          shape(0) = (1-p(0))*(1-p(1));\n          shape(1) =    p(0) *(1-p(1));\n          shape(2) =    p(0) *   p(1) ;\n          shape(3) = (1-p(0))*   p(1) ;\n          break;\n        }\n\n      default:\n        throw NgException (\"illegal element type in GetShapeNew\");\n      }\n  }\n\n  template <typename T>\n  void Element2d :: GetShapeNew (const Point<2,T> & p, TFlatVector<T> shape) const\n  {\n    switch (typ)\n      {\n      case TRIG:\n        {\n          shape(0) = p(0);\n          shape(1) = p(1);\n          shape(2) = 1-p(0)-p(1);\n          break;\n        }\n\n      case QUAD:\n        {\n          shape(0) = (1-p(0))*(1-p(1));\n          shape(1) =    p(0) *(1-p(1));\n          shape(2) =    p(0) *   p(1) ;\n          shape(3) = (1-p(0))*   p(1) ;\n          break;\n        }\n      default:\n        throw NgException (\"illegal element type in GetShapeNew\");\n      }\n  }\n\n\n\n\n\n\n\n\n\n  void Element2d :: \n  GetDShape (const Point<2> & p, DenseMatrix & dshape) const\n  {\n#ifdef DEBUG\n    if (dshape.Height() != 2 || dshape.Width() != np)\n      {\n        PrintSysError (\"Element::DShape: Sizes don't fit\");\n        return;\n      }\n#endif\n\n    switch (typ)\n      {\n      case TRIG:\n        dshape.Elem(1, 1) = -1;\n        dshape.Elem(1, 2) = 1;\n        dshape.Elem(1, 3) = 0;\n        dshape.Elem(2, 1) = -1;\n        dshape.Elem(2, 2) = 0;\n        dshape.Elem(2, 3) = 1;\n        break;\n      case QUAD:\n        dshape.Elem(1, 1) = -(1-p[1]);\n        dshape.Elem(1, 2) = (1-p[1]);\n        dshape.Elem(1, 3) = p[1];\n        dshape.Elem(1, 4) = -p[1];\n        dshape.Elem(2, 1) = -(1-p[0]);\n        dshape.Elem(2, 2) = -p[0];\n        dshape.Elem(2, 3) = p[0];\n        dshape.Elem(2, 4) = (1-p[0]);\n        break;\n\n      default:\n        PrintSysError (\"Element2d::GetDShape, illegal type \", int(typ));\n      }\n  }\n\n\n  template <typename T>\n  void Element2d :: \n  GetDShapeNew (const Point<2,T> & p, MatrixFixWidth<2,T> & dshape) const\n  {\n    switch (typ)\n      {\n      case TRIG:\n        {\n          dshape = T(0.0);\n          dshape(0,0) = 1;\n          dshape(1,1) = 1;\n          dshape(2,0) = -1;\n          dshape(2,1) = -1;\n          break;\n        }\n      case QUAD:\n        {\n          dshape(0,0) = -(1-p(1));\n          dshape(0,1) = -(1-p(0));\n\n          dshape(1,0) =  (1-p(1));\n          dshape(1,1) =  -p(0);\n\n          dshape(2,0) = p(1);\n          dshape(2,1) = p(0);\n\n          dshape(3,0) = -p(1);\n          dshape(3,1) = (1-p(0));\n          break;\n        }\n      default:\n        throw NgException (\"illegal element type in GetDShapeNew\");\n      }\n  }\n\n\n\n\n\n  void Element2d :: \n  GetPointMatrix (const NgArray<Point<2>> & points,\n                  DenseMatrix & pmat) const\n  {\n    int np = GetNP();\n\n#ifdef DEBUG\n    if (pmat.Width() != np || pmat.Height() != 2)\n      {\n        cerr << \"Element::GetPointMatrix: sizes don't fit\" << endl;\n        return;\n      }\n#endif\n  \n    for (int i = 1; i <= np; i++)\n      {\n        const auto& p = points.Get(PNum(i));\n        pmat.Elem(1, i) = p[0];\n        pmat.Elem(2, i) = p[1];\n      }\n  }\n\n\n\n\n\n  double Element2d :: CalcJacobianBadness (const NgArray<Point<2>> & points) const\n  {\n    int i, j;\n    int nip = GetNIP();\n    DenseMatrix trans(2,2);\n    DenseMatrix pmat;\n  \n    pmat.SetSize (2, GetNP());\n    GetPointMatrix (points, pmat);\n\n    double err = 0;\n    for (i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n\n        // Frobenius norm\n        double frob = 0;\n        for (j = 1; j <= 4; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n        frob /= 2;\n\n        double det = trans.Det();\n\n        if (det <= 0)\n          err += 1e12;\n        else\n          err += frob * frob / det;\n      }\n\n    err /= nip;\n    return err;\n  }\n\n\n\n  static const int qip_table[4][4] =\n    { { 0, 1, 0, 3 },\n      { 0, 1, 1, 2 },\n      { 3, 2, 0, 3 },\n      { 3, 2, 1, 2 }\n    };\n\n  double Element2d :: \n  CalcJacobianBadnessDirDeriv (const NgArray<Point<2>> & points,\n                               int pi, Vec<2> & dir, double & dd) const\n  {\n    if (typ == QUAD)\n      {\n        Mat<2,2> trans, dtrans;\n        Mat<2,4> vmat, pmat;\n      \n        for (int j = 0; j < 4; j++)\n          {\n            const auto& p = points.Get( (*this)[j] );\n            pmat(0, j) = p[0];\n            pmat(1, j) = p[1];\n          }\n\n        vmat = 0.0;\n        vmat(0, pi-1) = dir[0];\n        vmat(1, pi-1) = dir[1];\n      \n        double err = 0;\n        dd = 0;\n\n        for (int i = 0; i < 4; i++)\n          {\n            int ix1 = qip_table[i][0];\n            int ix2 = qip_table[i][1];\n            int iy1 = qip_table[i][2];\n            int iy2 = qip_table[i][3];\n\t      \n            trans(0,0) = pmat(0, ix2) - pmat(0,ix1);\n            trans(1,0) = pmat(1, ix2) - pmat(1,ix1);\n            trans(0,1) = pmat(0, iy2) - pmat(0,iy1);\n            trans(1,1) = pmat(1, iy2) - pmat(1,iy1);\n\n            double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1);\n\n            if (det <= 0)\n              {\n                dd = 0;\n                return 1e12;\n              }\n\t  \n            dtrans(0,0) = vmat(0, ix2) - vmat(0,ix1);\n            dtrans(1,0) = vmat(1, ix2) - vmat(1,ix1);\n            dtrans(0,1) = vmat(0, iy2) - vmat(0,iy1);\n            dtrans(1,1) = vmat(1, iy2) - vmat(1,iy1);\n\n\n            // Frobenius norm\n            double frob = 0;\n            for (int j = 0; j < 4; j++) \n              frob += sqr (trans(j));\n            frob = sqrt (frob);\n\t  \n            double dfrob = 0;\n            for (int j = 0; j < 4; j++)\n              dfrob += trans(j) * dtrans(j);\n            dfrob = dfrob / frob;\n\t  \n            frob /= 2;      \n            dfrob /= 2;\n\t  \n\t  \n            // ddet = \\sum_j det (m_j)   with m_j = trans, except col j = dtrans\n            double ddet \n              = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0)\n              + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0);\n\t  \n            err += frob * frob / det;\n            dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det);\n          }\n      \n        err /= 4;\n        dd /= 4;\n        return err;\n      }\n\n    int nip = GetNIP();\n    DenseMatrix trans(2,2), dtrans(2,2);\n    DenseMatrix pmat, vmat;\n  \n    pmat.SetSize (2, GetNP());\n    vmat.SetSize (2, GetNP());\n\n    GetPointMatrix (points, pmat);\n  \n    vmat = 0.0;\n    vmat.Elem(1, pi) = dir[0];\n    vmat.Elem(2, pi) = dir[1];\n\n\n    double err = 0;\n    dd = 0;\n\n    for (int i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n        GetTransformation (i, vmat, dtrans);\n\n        // Frobenius norm\n        double frob = 0;\n        for (int j = 1; j <= 4; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n      \n        double dfrob = 0;\n        for (int j = 1; j <= 4; j++)\n          dfrob += trans.Get(j) * dtrans.Get(j);\n        dfrob = dfrob / frob;\n      \n        frob /= 2;      \n        dfrob /= 2;\n      \n        double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1);\n\n        // ddet = \\sum_j det (m_j)   with m_j = trans, except col j = dtrans\n        double ddet \n          = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0)\n          + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0);\n\n        if (det <= 0)\n          err += 1e12;\n        else\n          {\n            err += frob * frob / det;\n            dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det);\n          }\n      }\n\n    err /= nip;\n    dd /= nip;\n    return err;\n  }\n\n\n\n  double Element2d :: \n  CalcJacobianBadness (const T_POINTS & points, const Vec<3> & n) const\n  {\n    int i, j;\n    int nip = GetNIP();\n    DenseMatrix trans(2,2);\n    DenseMatrix pmat;\n  \n    pmat.SetSize (2, GetNP());\n\n    Vec<3> t1, t2;\n    t1 = n.GetNormal();\n    t2 = Cross (n, t1);\n\n    for (i = 1; i <= GetNP(); i++)\n      {\n        const auto& p = points[PNum(i)];\n        pmat.Elem(1, i) = p[0] * t1(0) + p[1] * t1(1) + p[2] * t1(2);\n        pmat.Elem(2, i) = p[0] * t2(0) + p[1] * t2(1) + p[2] * t2(2);\n      }\n\n    double err = 0;\n    for (i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n\n        // Frobenius norm\n        double frob = 0;\n        for (j = 1; j <= 4; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n        frob /= 2;\n\n        double det = trans.Det();\n        if (det <= 0)\n          err += 1e12;\n        else\n          err += frob * frob / det;\n      }\n\n    err /= nip;\n    return err;\n  }\n\n\n\n\n  void Element2d :: ComputeIntegrationPointData () const\n  {\n    switch (np)\n      {\n      case 3: if (ipdtrig.Size()) return; break;\n      case 4: if (ipdquad.Size()) return; break;\n      }\n\n    for (int i = 1; i <= GetNIP(); i++)\n      {\n        IntegrationPointData * ipd = new IntegrationPointData;\n        Point<2> hp;\n        GetIntegrationPoint (i, hp, ipd->weight);\n        ipd->p(0) = hp[0];\n        ipd->p(1) = hp[1];\n        ipd->p(2) = 0;\n\n        ipd->shape.SetSize(GetNP());\n        ipd->dshape.SetSize(2, GetNP());\n\n        GetShape (hp, ipd->shape);\n        GetDShape (hp, ipd->dshape);\n\n        switch (np)\n          {\n          case 3: ipdtrig.Append (ipd); break;\n          case 4: ipdquad.Append (ipd); break;\n          }\n      }\n  }\n\n\n\n\n\n\n\n  ostream & operator<<(ostream  & s, const Element0d & el)\n  {\n    s << el.pnum << \", index = \" << el.index;\n    return s;\n  }\n\n\n  ostream & operator<<(ostream  & s, const Element2d & el)\n  {\n    s << \"np = \" << el.GetNP();\n    for (int j = 1; j <= el.GetNP(); j++)\n      s << \" \" << el.PNum(j);\n    return s;\n  }\n\n\n  ostream & operator<<(ostream  & s, const Element & el)\n  {\n    s << \"np = \" << el.GetNP();\n    for (int j = 0; j < el.GetNP(); j++)\n      s << \" \" << el[j];\n    return s;\n  }\n\n  /*\n  Element :: Element ()\n  {\n    typ = TET;\n    np = 4;\n    for (int i = 0; i < ELEMENT_MAXPOINTS; i++)\n      pnum[i] = 0;\n    index = 0;\n    flags.marked = 1;\n    flags.badel = 0;\n    flags.reverse = 0;\n    flags.illegal = 0;\n    flags.illegal_valid = 0;\n    flags.badness_valid = 0;\n    flags.refflag = 1;\n    flags.strongrefflag = false;\n    flags.deleted = 0;\n    flags.fixed = 0;\n    orderx = ordery = orderz = 1;\n    is_curved = false;\n#ifdef PARALLEL\n    partitionNumber = -1;\n#endif\n  }\n  */\n\n  Element :: Element (int anp)\n  {\n    np = anp;\n    for (int i = 0; i < ELEMENT_MAXPOINTS; i++)\n        pnum[i].Invalidate();\n    index = 0;\n    flags.marked = 1;\n    flags.badel = 0;\n    flags.reverse = 0;\n    flags.illegal = 0;\n    flags.illegal_valid = 0;\n    flags.badness_valid = 0;\n    flags.refflag = 1;\n    flags.strongrefflag = false;\n    flags.deleted = 0;\n    flags.fixed = 0;\n\n    switch (np)\n      {\n      case 4: typ = TET; break;\n      case 5: typ = PYRAMID; break;\n      case 6: typ = PRISM; break;\n      case 7: typ = HEX7; break;\n      case 8: typ = HEX; break;\n      case 10: typ = TET10; break;\n      case 13: typ = PYRAMID13; break;\n      case 15: typ = PRISM15; break;\n      case 20: typ = HEX20; break;\n      default: cerr << \"Element::Element: unknown element with \" << np << \" points\" << endl;\n      }\n    orderx = ordery = orderz = 1;\n    is_curved = typ != TET; // false;\n  }\n\n  void Element :: SetOrder (const int aorder) \n  { \n    orderx = aorder; \n    ordery = aorder; \n    orderz = aorder;\n  }\n\n\n  void Element :: SetOrder (const int ox, const int oy, const int oz) \n  { \n    orderx = ox; \n    ordery = oy;\n    orderz = oz; \n  }\n\n\n  Element :: Element (ELEMENT_TYPE type)\n  {\n    SetType (type);\n\n    for (int i = 0; i < ELEMENT_MAXPOINTS; i++)\n        pnum[i].Invalidate();\n    index = 0;\n    flags.marked = 1;\n    flags.badel = 0;\n    flags.reverse = 0;\n    flags.illegal = 0;\n    flags.illegal_valid = 0;\n    flags.badness_valid = 0;\n    flags.refflag = 1;\n    flags.strongrefflag = false;\n    flags.deleted = 0;\n    flags.fixed = 0;\n    orderx = ordery = orderz = 1;\n    is_curved =  typ != TET; // false;\n    // #ifdef PARALLEL\n    // partitionNumber = -1;\n    // #endif\n  }\n\n\n\n\n  /*\n  Element & Element :: operator= (const Element & el2)\n  {\n    typ = el2.typ;\n    np = el2.np;\n    for (int i = 0; i < ELEMENT_MAXPOINTS; i++)\n      pnum[i] = el2.pnum[i];\n    index = el2.index;\n    flags = el2.flags;\n    orderx = el2.orderx;\n    ordery = el2.ordery;\n    orderz = el2.orderz;\n    hp_elnr = el2.hp_elnr;\n    flags = el2.flags;\n    is_curved = el2.is_curved;\n    return *this;\n  }\n  */\n\n\n  void Element :: SetNP (int anp)\n  {\n    np = anp; \n    switch (np)\n      {\n      case 4: typ = TET; break;\n      case 5: typ = PYRAMID; break;\n      case 6: typ = PRISM; break;\n      case 7: typ = HEX7; break;\n      case 8: typ = HEX; break;\n      case 10: typ = TET10; break;\n      case 13: typ = PYRAMID13; break;\n      case 15: typ = PRISM15; break;\n      case 20: typ = HEX20; break;\n        // \n      default: break;\n        cerr << \"Element::SetNP unknown element with \" << np << \" points\" << endl;\n      }\n  }\n\n\n\n  void Element :: SetType (ELEMENT_TYPE atyp)\n  {\n    typ = atyp;\n    switch (atyp)\n      {\n      case TET: np = 4; break;\n      case PYRAMID: np = 5; break;\n      case PRISM: np = 6; break;\n      case HEX7: np = 7; break;\n      case HEX: np = 8; break;\n      case TET10: np = 10; break;\n      case PYRAMID13: np = 13; break;\n      case PRISM12: np = 12; break;\n      case PRISM15: np = 15; break;\n      case HEX20: np = 20; break;\n\n      default: break;\n        cerr << \"Element::SetType unknown type  \" << int(typ) << endl;\n      }\n    is_curved = (np > 4); \n  }\n\n\n\n  void Element :: Invert()\n  {\n    switch (GetNP())\n      {\n      case 4:\n        {\n          Swap (PNum(3), PNum(4));\n          break;\n        }\n      case 5:\n        {\n          Swap (PNum(1), PNum(4));\n          Swap (PNum(2), PNum(3));\n          break;\n        }\n      case 6:\n        {\n          Swap (PNum(1), PNum(4));\n          Swap (PNum(2), PNum(5));\n          Swap (PNum(3), PNum(6));\n          break;\n        }\n      }\n  }\n\n\n  void Element :: Print (ostream & ost) const\n  {\n    ost << np << \" Points: \";\n    for (int i = 1; i <= np; i++)\n      ost << pnum[i-1] << \" \" << endl;\n  }\n\n  void Element :: GetBox (const T_POINTS & points, Box3d & box) const\n  {\n    box.SetPoint (points[PNum(1)]);\n    box.AddPoint (points[PNum(2)]);\n    box.AddPoint (points[PNum(3)]);\n    box.AddPoint (points[PNum(4)]);\n  }\n\n  double Element :: Volume (const T_POINTS & points) const\n  {\n    Vec<3> v1 = points[PNum(2)] - points[PNum(1)];\n    Vec<3> v2 = points[PNum(3)] - points[PNum(1)];\n    Vec<3> v3 = points[PNum(4)] - points[PNum(1)]; \n  \n    return -(Cross (v1, v2) * v3) / 6;\t \n  }  \n\n\n  void Element :: GetFace2 (int i, Element2d & face) const\n  {\n    static const int tetfaces[][5] = \n      { { 3, 2, 3, 4, 0 },\n        { 3, 3, 1, 4, 0 },\n        { 3, 1, 2, 4, 0 },\n        { 3, 2, 1, 3, 0 } };\n\n    static const int tet10faces[][7] = \n      { { 3, 2, 3, 4, 10, 9, 8 },\n        { 3, 3, 1, 4, 7, 10, 6 },\n        { 3, 1, 2, 4, 9, 7, 5 },\n        { 3, 2, 1, 3, 6, 8, 5 } };\n\n    static const int pyramidfaces[][5] =\n      { { 4, 1, 4, 3, 2 },\n        { 3, 1, 2, 5, 0 },\n        { 3, 2, 3, 5, 0 },\n        { 3, 3, 4, 5, 0 },\n        { 3, 4, 1, 5, 0 } };\n    \n    static const int prismfaces[][5] =\n      {\n        { 3, 1, 3, 2, 0 },\n        { 3, 4, 5, 6, 0 },\n        { 4, 1, 2, 5, 4 },\n        { 4, 2, 3, 6, 5 },\n        { 4, 3, 1, 4, 6 }\n      };\n    \n    static const int hex7faces[][5] =\n      {\n        { 4, 4, 3, 2, 1 },\n        { 4, 3, 7, 6, 2 },\n        { 3, 7, 5, 6 },\n        { 4, 7, 4, 1, 5 },\n        { 4, 1, 2, 6, 5 },\n        { 3, 3, 4, 7 }\n      };\n    \n    static const int hexfaces[][5] =\n      {\n        { 4, 4, 3, 2, 1 },\n        { 4, 3, 7, 6, 2 },\n        { 4, 7, 8, 5, 6 },\n        { 4, 8, 4, 1, 5 },\n        { 4, 1, 2, 6, 5 },\n        { 4, 3, 4, 8, 7 }\n      };\n\n    switch (np)\n      {\n      case 4: // tet\n        {\n          face.SetType(TRIG);\n          for (int j = 1; j <= 3; j++)\n            face.PNum(j) = PNum(tetfaces[i-1][j]);\n          break;\n        }\n\n      case 10: // tet10\n        {\n          face.SetType(TRIG6);\n          for (int j = 1; j <= 6; j++)\n            face.PNum(j) = PNum(tet10faces[i-1][j]);\n          break;\n        }\n\n      case 5: // pyramid\n        {\n          // face.SetNP(pyramidfaces[i-1][0]);\n          face.SetType ( (i == 1) ? QUAD : TRIG);\n          for (int j = 1; j <= face.GetNP(); j++)\n            face.PNum(j) = PNum(pyramidfaces[i-1][j]);\n          break;\n        }\n      case 6: // prism\n        {\n          //\tface.SetNP(prismfaces[i-1][0]);\n          face.SetType ( (i >= 3) ? QUAD : TRIG);\n          for (int j = 1; j <= face.GetNP(); j++)\n            face.PNum(j) = PNum(prismfaces[i-1][j]);\n          break;\n        }\n      case 7: // hex7\n        {\n          //\tface.SetNP(prismfaces[i-1][0]);\n          face.SetType ( ((i == 3) || (i==6)) ? TRIG : QUAD);\n          for (int j = 1; j <= face.GetNP(); j++)\n            face.PNum(j) = PNum(hex7faces[i-1][j]);\n          break;\n        }\n      case 8:\n        {\n          face.SetType(QUAD);\n          for (int j = 1; j <= 4; j++)\n            face.PNum(j) = PNum(hexfaces[i-1][j]);\n          break;\n        }\n      }\n  }\n\n\n\n  void Element :: GetTets (NgArray<Element> & locels) const\n  {\n    GetTetsLocal (locels);\n    int i, j;\n    for (i = 1; i <= locels.Size(); i++)\n      for (j = 1; j <= 4; j++)\n        locels.Elem(i).PNum(j) = PNum ( locels.Elem(i).PNum(j) );\n  }\n\n  void Element :: GetTetsLocal (NgArray<Element> & locels) const\n  {\n    int i, j;\n    locels.SetSize(0);\n    switch (GetType())\n      {\n      case TET:\n        {\n          int linels[1][4] = \n            { { 1, 2, 3, 4 },\n            };\n          for (i = 0; i < 1; i++)\n            {\n              Element tet(4);\n              for (j = 1; j <= 4; j++)\n                tet.PNum(j) = linels[i][j-1];\n              locels.Append (tet);\n            }\n          break;\n        }\n      case TET10:\n        {\n          int linels[8][4] = \n            { { 1, 5, 6, 7 },\n              { 5, 2, 8, 9 },\n              { 6, 8, 3, 10 },\n              { 7, 9, 10, 4 },\n              { 5, 6, 7, 9 },\n              { 5, 6, 9, 8 },\n              { 6, 7, 9, 10 },\n              { 6, 8, 10, 9 } };\n          for (i = 0; i < 8; i++)\n            {\n              Element tet(4);\n              for (j = 1; j <= 4; j++)\n                tet.PNum(j) = linels[i][j-1];\n              locels.Append (tet);\n            }\n          break;\n        }\n      case PYRAMID:\n        {\n          int linels[2][4] = \n            { { 1, 2, 3, 5 },\n              { 1, 3, 4, 5 } };\n          for (i = 0; i < 2; i++)\n            {\n              Element tet(4);\n              for (j = 1; j <= 4; j++)\n                tet.PNum(j) = linels[i][j-1];\n              locels.Append (tet);\n            }\n          break;\n        }\n      case PRISM:\n      case PRISM12:\n        {\n          int linels[3][4] = \n            { { 1, 2, 3, 4 },\n              { 4, 2, 3, 5 },\n              { 6, 5, 4, 3 }\n            };\n          for (i = 0; i < 3; i++)\n            {\n              Element tet(4);\n              for (j = 0; j < 4; j++)\n                tet[j] = linels[i][j];\n              locels.Append (tet);\n            }\n          break;\n        }\n      case HEX:\n        {\n          int linels[6][4] = \n            { { 1, 7, 2, 3 },\n              { 1, 7, 3, 4 },\n              { 1, 7, 4, 8 },\n              { 1, 7, 8, 5 },\n              { 1, 7, 5, 6 },\n              { 1, 7, 6, 2 }\n            };\n          for (i = 0; i < 6; i++)\n            {\n              Element tet(4);\n              for (j = 0; j < 4; j++)\n                tet[j] = linels[i][j];\n              locels.Append (tet);\n            }\n          break;\n        }\n      default:\n        {\n          cerr << \"GetTetsLocal not implemented for el with \" << GetNP() << \" nodes\" << endl;\n        }\n      }\n  }\n\n  bool Element :: operator==(const Element & el2) const\n  {\n    bool retval = (el2.GetNP() == np);\n    for(int i= 0; retval && i<np; i++)\n      retval = (el2[i] == (*this)[i]);\n\n    return retval;\n  }\n\n\n#ifdef OLD\n  void Element :: GetNodesLocal (NgArray<Point3d> & points) const\n  {\n    const static double tetpoints[4][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 }};\n  \n    const static double prismpoints[6][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 1, 0, 1 },\n        { 0, 1, 1 } };\n  \n    const static double pyramidpoints[6][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 1, 1, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 } };\n  \n    const static double tet10points[10][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 0.5, 0, 0 },\n        { 0, 0.5, 0 },\n        { 0, 0, 0.5 },\n        { 0.5, 0.5, 0 },\n        { 0.5, 0, 0.5 },\n        { 0, 0.5, 0.5 } };\n\n    const static double hexpoints[8][3] =\n      { \n        { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 1, 1, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 1, 0, 1 },\n        { 1, 1, 1 },\n        { 0, 1, 1 }\n      };\n  \n    int np, i;\n    const double (*pp)[3];\n    switch (GetType())\n      {\n      case TET:\n        {\n          np = 4;\n          pp = tetpoints;\n          break;\n        }\n      case PRISM:\n      case PRISM12:\n        {\n          np = 6;\n          pp = prismpoints;\n          break;\n        }\n      case TET10:\n        {\n          np = 10;\n          pp = tet10points;\n          break;\n        }\n      case PYRAMID:\n        {\n          np = 5;\n          pp = pyramidpoints;\n          break;\n        }\n      case HEX:\n        {\n          np = 8;\n          pp = hexpoints;\n          break;\n        }\n      default:\n        {\n          cout << \"GetNodesLocal not implemented for element \" << GetType() << endl;\n          np = 0;\n        }\n      }\n  \n    points.SetSize(0);\n    for (i = 0; i < np; i++)\n      points.Append (Point3d (pp[i][0], pp[i][1], pp[i][2]));\n  }\n#endif\n\n\n\n\n\n\n  void Element :: GetNodesLocalNew (NgArray<Point<3> > & points) const\n  {\n    const static double tetpoints[4][3] =\n      {      \n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 0, 0, 0 }\n      };\n  \n    const static double prismpoints[6][3] =\n      {\n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 0 },\n        { 1, 0, 1 },\n        { 0, 1, 1 },\n        { 0, 0, 1 }\n      };\n  \n    const static double pyramidpoints[6][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 1, 1, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 } };\n  \n    const static double tet10points[10][3] =\n      { { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 0.5, 0, 0 },\n        { 0, 0.5, 0 },\n        { 0, 0, 0.5 },\n        { 0.5, 0.5, 0 },\n        { 0.5, 0, 0.5 },\n        { 0, 0.5, 0.5 } };\n\n    const static double hexpoints[8][3] =\n      { \n        { 0, 0, 0 },\n        { 1, 0, 0 },\n        { 1, 1, 0 },\n        { 0, 1, 0 },\n        { 0, 0, 1 },\n        { 1, 0, 1 },\n        { 1, 1, 1 },\n        { 0, 1, 1 }\n      };\n  \n\n  \n    int np, i;\n    const double (*pp)[3];\n    switch (GetType())\n      {\n      case TET:\n        {\n          np = 4;\n          pp = tetpoints;\n          break;\n        }\n      case PRISM:\n      case PRISM12:\n        {\n          np = 6;\n          pp = prismpoints;\n          break;\n        }\n      case TET10:\n        {\n          np = 10;\n          pp = tet10points;\n          break;\n        }\n      case PYRAMID:\n        {\n          np = 5;\n          pp = pyramidpoints;\n          break;\n        }\n      case HEX:\n        {\n          np = 8;\n          pp = hexpoints;\n          break;\n        }\n      default:\n        {\n          cout << \"GetNodesLocal not implemented for element \" << GetType() << endl;\n          np = 0;\n\t  pp = NULL;\n        }\n      }\n  \n    points.SetSize(0);\n    for (i = 0; i < np; i++)\n      points.Append (Point<3> (pp[i][0], pp[i][1], pp[i][2]));\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void Element :: GetSurfaceTriangles (NgArray<Element2d> & surftrigs) const\n  {\n    static int tet4trigs[][3] = \n      { { 2, 3, 4 },\n        { 3, 1, 4 },\n        { 1, 2, 4 },\n        { 2, 1, 3 } };\n\n    static int tet10trigs[][3] = \n      { { 2, 8, 9 }, { 3, 10, 8}, { 4, 9, 10 }, { 9, 8, 10 },\n        { 3, 6, 10 }, { 1, 7, 6 }, { 4, 10, 7 }, { 6, 7, 10 },\n        { 1, 5, 7 }, { 2, 9, 5 }, { 4, 7, 9 }, { 5, 9, 7 },\n        { 1, 6, 5 }, { 2, 5, 8 }, { 3, 8, 6 }, { 5, 6, 8 }\n      };\n\n    static int pyramidtrigs[][3] =\n      {\n        { 1, 3, 2 },\n        { 1, 4, 3 },\n        { 1, 2, 5 },\n        { 2, 3, 5 },\n        { 3, 4, 5 },\n        { 4, 1, 5 }\n      };\n\n    static int prismtrigs[][3] =\n      {\n        { 1, 3, 2 },\n        { 4, 5, 6 },\n        { 1, 2, 4 },\n        { 4, 2, 5 },\n        { 2, 3, 5 },\n        { 5, 3, 6 },\n        { 3, 1, 6 },\n        { 6, 1, 4 }\n      };\n  \n    static int hex7trigs[][3] = \n      {\n        { 1, 3, 2 },\n        { 1, 4, 3 }, \n        { 5, 6, 7 },\n        { 1, 2, 6 },\n        { 1, 6, 5 },\n        { 2, 3, 7 },\n        { 2, 7, 6 },\n        { 3, 4, 7 },\n        { 4, 1, 7 },\n        { 1, 5, 7 }\n      };\n    \n    static int hextrigs[][3] = \n      {\n        { 1, 3, 2 },\n        { 1, 4, 3 }, \n        { 5, 6, 7 },\n        { 5, 7, 8 },\n        { 1, 2, 6 },\n        { 1, 6, 5 },\n        { 2, 3, 7 },\n        { 2, 7, 6 },\n        { 3, 4, 8 },\n        { 3, 8, 7 },\n        { 4, 1, 8 },\n        { 1, 5, 8 }\n      };\n\n\n    \n    int j;\n\n    int nf;\n    int (*fp)[3];\n\n    switch (GetType())\n      {\n      case TET:\n        {\n          nf = 4;\n          fp = tet4trigs;\n          break;\n        }\n      case PYRAMID:\n        {\n          nf = 6;\n          fp = pyramidtrigs;\n          break;\n        }\n      case PRISM:\n      case PRISM12:\n        {\n          nf = 8;\n          fp = prismtrigs;\n          break;\n        }\n      case TET10:\n        {\n          nf = 16;\n          fp = tet10trigs;\n          break;\n        }\n      case HEX7:\n        {\n          nf = 10;\n          fp = hex7trigs;\n          break;\n        }\n      case HEX:\n        {\n          nf = 12;\n          fp = hextrigs;\n          break;\n        }\n      default:\n        {\n          nf = 0;\n          fp = NULL;\n        }\n      }\n\n  \n    surftrigs.SetSize (nf);\n    for (j = 0; j < nf; j++)\n      {\n        surftrigs.Elem(j+1) = Element2d(TRIG);\n        surftrigs.Elem(j+1).PNum(1) = fp[j][0];\n        surftrigs.Elem(j+1).PNum(2) = fp[j][1];\n        surftrigs.Elem(j+1).PNum(3) = fp[j][2];\n      }\n  }\n\n\n\n\n\n  NgArray< shared_ptr < IntegrationPointData > > ipdtet;\n  NgArray< shared_ptr < IntegrationPointData > > ipdtet10;\n\n\n\n  int Element :: GetNIP () const\n  {\n    int nip;\n    switch (typ)\n      {\n      case TET: nip = 1; break;\n      case TET10: nip = 8; break;\n      default: nip = 0; break;\n      }\n    return nip;\n  }\n\n  void Element :: \n  GetIntegrationPoint (int ip, Point<3> & p, double & weight) const\n  {\n    static double eltetqp[1][4] =\n      {\n        { 0.25, 0.25, 0.25, 1.0/6.0 }\n      };\n\n    static double eltet10qp[8][4] =\n      {\n        { 0.585410196624969, 0.138196601125011, 0.138196601125011, 1.0/24.0 },\n        { 0.138196601125011, 0.585410196624969, 0.138196601125011, 1.0/24.0 },\n        { 0.138196601125011, 0.138196601125011, 0.585410196624969, 1.0/24.0 },\n        { 0.138196601125011, 0.138196601125011, 0.138196601125011, 1.0/24.0 },\n        { 1, 0, 0, 1 },\n        { 0, 1, 0, 1 },\n        { 0, 0, 1, 1 },\n        { 0, 0, 0, 1 },\n      };\n    \n    double * pp = NULL;\n    switch (typ)\n      {\n      case TET: pp = &eltetqp[0][0]; break;\n      case TET10: pp = &eltet10qp[ip-1][0]; break;\n      default:\n        throw NgException (\"illegal element shape in GetIntegrationPoint\");\n      }\n\n    p(0) = pp[0];\n    p(1) = pp[1];\n    p(2) = pp[2];\n    weight = pp[3];\n  }\n\n  void Element :: \n  GetTransformation (int ip, const T_POINTS & points,\n                     DenseMatrix & trans) const\n  {\n    int np = GetNP();\n    DenseMatrix pmat(3, np), dshape(3, np);\n    pmat.SetSize (3, np);\n    dshape.SetSize (3, np);\n\n    Point<3> p;\n    double w;\n\n    GetPointMatrix (points, pmat);\n    GetIntegrationPoint (ip, p, w);\n    GetDShape (p, dshape);\n  \n    CalcABt (pmat, dshape, trans);\n\n    /*\n      (*testout) << \"p = \" << p  << endl\n      << \"pmat = \" << pmat << endl\n      << \"dshape = \" << dshape << endl\n      << \"tans = \" << trans << endl;\n    */\n  }\n\n  void Element :: \n  GetTransformation (int ip, class DenseMatrix & pmat,\n                     class DenseMatrix & trans) const\n  {\n    int np = GetNP();\n\n    if (pmat.Width() != np || pmat.Height() != 3)\n      {\n        (*testout) << \"GetTransofrmation: pmat doesn't fit\" << endl;\n        return;\n      }\n\n    ComputeIntegrationPointData ();\n    DenseMatrix * dshapep = 0;\n    switch (GetType())\n      {\n      case TET: dshapep = &ipdtet.Get(ip)->dshape; break;\n      case TET10: dshapep = &ipdtet10.Get(ip)->dshape; break;\n      default:\n        PrintSysError (\"Element::GetTransformation, illegal type \", int(typ));\n      }\n  \n    CalcABt (pmat, *dshapep, trans);\n  }\n\n\n  void Element :: GetShape (const Point<3> & hp, Vector & shape) const\n  {\n    if (shape.Size() != GetNP())\n      {\n        cerr << \"Element::GetShape: Length not fitting\" << endl;\n        return;\n      }\n\n    switch (typ)\n      {\n      case TET:\n        {\n          shape(0) = 1 - hp[0] - hp[1] - hp[2]; \n          shape(1) = hp[0];\n          shape(2) = hp[1];\n          shape(3) = hp[2];\n          break;\n        }\n      case TET10:\n        {\n          double lam1 = 1 - hp[0] - hp[1] - hp[2];\n          double lam2 = hp[0];\n          double lam3 = hp[1];\n          double lam4 = hp[2];\n\t\n          shape(4) = 4 * lam1 * lam2;\n          shape(5) = 4 * lam1 * lam3;\n          shape(6) = 4 * lam1 * lam4;\n          shape(7) = 4 * lam2 * lam3;\n          shape(8) = 4 * lam2 * lam4;\n          shape(9) = 4 * lam3 * lam4;\n\t\n          shape(0) = lam1 - 0.5 * (shape(4) + shape(5) + shape(6));\n          shape(1) = lam2 - 0.5 * (shape(4) + shape(7) + shape(8));\n          shape(2) = lam3 - 0.5 * (shape(5) + shape(7) + shape(9));\n          shape(3) = lam4 - 0.5 * (shape(6) + shape(8) + shape(9));\n          break;\n        }\n\n      case PRISM:\n        {\n          shape(0) = hp(0) * (1-hp(2));\n          shape(1) = hp(1) * (1-hp(2));\n          shape(2) = (1-hp(0)-hp(1)) * (1-hp(2));\n          shape(3) = hp(0) * hp(2);\n          shape(4) = hp(1) * hp(2);\n          shape(5) = (1-hp(0)-hp(1)) * hp(2);\n          break;\n        }\n      case HEX:\n        {\n          shape(0) = (1-hp(0))*(1-hp(1))*(1-hp(2));\n          shape(1) = (  hp(0))*(1-hp(1))*(1-hp(2));\n          shape(2) = (  hp(0))*(  hp(1))*(1-hp(2));\n          shape(3) = (1-hp(0))*(  hp(1))*(1-hp(2));\n          shape(4) = (1-hp(0))*(1-hp(1))*(  hp(2));\n          shape(5) = (  hp(0))*(1-hp(1))*(  hp(2));\n          shape(6) = (  hp(0))*(  hp(1))*(  hp(2));\n          shape(7) = (1-hp(0))*(  hp(1))*(  hp(2));\n          break;\n        }\n      default:\n        throw NgException(\"Element :: GetShape not implemented for that element\");\n      }\n  }\n\n\n  template <typename T>\n  void Element :: GetShapeNew (const Point<3,T> & p, TFlatVector<T> shape) const\n  {\n    /*\n      if (shape.Size() < GetNP())\n      {\n      cerr << \"Element::GetShape: Length not fitting\" << endl;\n      return;\n      }\n    */\n\n    switch (typ)\n      {\n      case TET:\n        {\n          shape(0) = p(0);\n          shape(1) = p(1);\n          shape(2) = p(2);\n          shape(3) = 1-p(0)-p(1)-p(2);\n          break;\n        }\n\n      case TET10:\n        {\n          T lam1 = p(0);\n          T lam2 = p(1);\n          T lam3 = p(2);\n          T lam4 = 1-p(0)-p(1)-p(2);\n\t\n          shape(0) = 2 * lam1 * (lam1-0.5);\n          shape(1) = 2 * lam2 * (lam2-0.5);\n          shape(2) = 2 * lam3 * (lam3-0.5);\n          shape(3) = 2 * lam4 * (lam4-0.5);\n\n          shape(4) = 4 * lam1 * lam2;\n          shape(5) = 4 * lam1 * lam3;\n          shape(6) = 4 * lam1 * lam4;\n          shape(7) = 4 * lam2 * lam3;\n          shape(8) = 4 * lam2 * lam4;\n          shape(9) = 4 * lam3 * lam4;\n\t\n          break;\n        }\n\n\n      case PYRAMID:\n        {\n          T noz = 1-p(2);\n          // if (noz == 0.0) noz = 1e-10;\n          noz += T(1e-12);\n\n          T xi  = p(0) / noz;\n          T eta = p(1) / noz;\n          shape(0) = (1-xi)*(1-eta) * (noz);\n          shape(1) = (  xi)*(1-eta) * (noz);\n          shape(2) = (  xi)*(  eta) * (noz);\n          shape(3) = (1-xi)*(  eta) * (noz);\n          shape(4) = p(2);\n          break;\n        }\n      case PYRAMID13:\n        {\n\t  T x = p(0);\n\t  T y = p(1);\n\t  T z = p(2);\n          z *= 1-1e-12;\n          shape[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25);\n          shape[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2));\n          shape[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75);\n          shape[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2));\n          shape[4] = z*(2*z - 1);\n          shape[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          shape[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2);\n          shape[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2);\n          shape[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2);\n          shape[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1);\n          shape[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1);\n          shape[11] = 4*x*y*z/(-z + 1);\n          shape[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1);\n          break;\n        }\n      case PRISM:\n        {\n          shape(0) = p(0) * (1-p(2));\n          shape(1) = p(1) * (1-p(2));\n          shape(2) = (1-p(0)-p(1)) * (1-p(2));\n          shape(3) = p(0) * p(2);\n          shape(4) = p(1) * p(2);\n          shape(5) = (1-p(0)-p(1)) * p(2);\n          break;\n        }\n      case PRISM15:\n        {\n\t  T x = p(0);\n\t  T y = p(1);\n\t  T z = p(2);\n          T lam = 1-x-y;\n          T lamz = 1-z;\n          shape[0] = (2*x*x-x) * (2*lamz*lamz-lamz);\n          shape[1] = (2*y*y-y) * (2*lamz*lamz-lamz);\n          shape[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz);\n          shape[3] = (2*x*x-x) * (2*z*z-z);\n          shape[4] = (2*y*y-y) * (2*z*z-z);\n          shape[5] = (2*lam*lam-lam) * (2*z*z-z);\n          shape[6] = 4 * x * y * (2*lamz*lamz-lamz);\n          shape[7] = 4 * x * lam * (2*lamz*lamz-lamz);\n          shape[8] = 4 * y * lam * (2*lamz*lamz-lamz);\n          shape[9] = x * 4 * z * (1-z);\n          shape[10] = y * 4 * z * (1-z);\n          shape[11] = lam * 4 * z * (1-z);\n          shape[12] = 4 * x * y * (2*z*z-z);\n          shape[13] = 4 * x * lam * (2*z*z-z);\n          shape[14] = 4 * y * lam * (2*z*z-z);\n          break;\n        }\n      case HEX7:\n        {\n          T y = p(1);\n          T z = p(2);\n          // T den = (1-y)*(1-z);\n          T den = (1-y*z);\n          den += T(1e-12);\n          \n          T x = p(0) / den;\n\n          shape(0) = (1-x)*(1-y)*(1-z);\n          shape(1) = (  x)*(1-y)*(1-z);\n          shape(2) = (  x)*(  y)*(1-z);\n          shape(3) = (1-x)*(  y)*(1-z);\n          shape(4) = (1-x)*(1-y)*(  z);\n          shape(5) = (  x)*(1-y)*(  z);\n          shape(6) =       (  y)*(  z);\n          break;\n        }\n\n      case HEX:\n        {\n          shape(0) = (1-p(0))*(1-p(1))*(1-p(2));\n          shape(1) = (  p(0))*(1-p(1))*(1-p(2));\n          shape(2) = (  p(0))*(  p(1))*(1-p(2));\n          shape(3) = (1-p(0))*(  p(1))*(1-p(2));\n          shape(4) = (1-p(0))*(1-p(1))*(  p(2));\n          shape(5) = (  p(0))*(1-p(1))*(  p(2));\n          shape(6) = (  p(0))*(  p(1))*(  p(2));\n          shape(7) = (1-p(0))*(  p(1))*(  p(2));\n          break;\n        }\n      case HEX20:\n\t{\n\t  T x = p(0);\n\t  T y = p(1);\n\t  T z = p(2);\n\t  shape[0] = (1-x)*(1-y)*(1-z);\n\t  shape[1] =    x *(1-y)*(1-z);\n\t  shape[2] =    x *   y *(1-z);\n\t  shape[3] = (1-x)*   y *(1-z);\n\t  shape[4] = (1-x)*(1-y)*(z);\n\t  shape[5] =    x *(1-y)*(z);\n\t  shape[6] =    x *   y *(z);\n\t  shape[7] = (1-x)*   y *(z);\n\n          T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z),\n                      (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z};\n\n          static const int e[12][2] =\n            {\n              { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 },\n              { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 },\n              { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 },\n            };\n\n          for (int i = 0; i < 12; i++)\n            {\n              T lame = shape[e[i][0]]+shape[e[i][1]];\n              T xi = sigma[e[i][1]]-sigma[e[i][0]];\n              shape[8+i] = (1-xi*xi)*lame;\n            }\n          for (int i = 0; i < 12; i++)\n            {\n              shape[e[i][0]] -= 0.5 * shape[8+i];\n              shape[e[i][1]] -= 0.5 * shape[8+i];\n            }\n          break;\n\t}\n      default:\n        throw NgException(\"Element :: GetNewShape not implemented for that element\");\n      }\n  }\n\n\n\n  void Element :: \n  GetDShape (const Point<3> & hp, DenseMatrix & dshape) const\n  {\n    int np = GetNP();\n    if (dshape.Height() != 3 || dshape.Width() != np)\n      {\n        cerr << \"Element::DShape: Sizes don't fit\" << endl;\n        return;\n      }\n\n    double eps = 1e-6;\n    Vector shaper(np), shapel(np);\n\n    for (auto i : Range(3))\n      {\n        Point<3> pr(hp), pl(hp);\n        pr[i] += eps;\n        pl[i] -= eps;\n      \n        GetShape (pr, shaper);\n        GetShape (pl, shapel);\n        for (int j = 0; j < np; j++)\n          dshape(i, j) = (shaper(j) - shapel(j)) / (2 * eps);\n      }\n  }\n\n  template <typename T>\n  void Element :: \n  GetDShapeNew (const Point<3,T> & p, MatrixFixWidth<3,T> & dshape) const\n  {\n    switch (typ)\n      {\n      case TET:\n        {\n          dshape = T(0.0);\n          dshape(0,0) = 1;\n          dshape(1,1) = 1;\n          dshape(2,2) = 1;\n          dshape(3,0) = -1;\n          dshape(3,1) = -1;\n          dshape(3,2) = -1;\n          break;\n        }\n      case PRISM:\n        {\n          dshape = T(0.0);\n          dshape(0,0) = 1-p(2);\n          dshape(0,2) = -p(0);\n          dshape(1,1) = 1-p(2);\n          dshape(1,2) = -p(1);\n          dshape(2,0) = -(1-p(2));\n          dshape(2,1) = -(1-p(2));\n          dshape(2,2) = -(1-p(0)-p(1));\n\n          dshape(3,0) = p(2);\n          dshape(3,2) = p(0);\n          dshape(4,1) = p(2);\n          dshape(4,2) = p(1);\n          dshape(5,0) = -p(2);\n          dshape(5,1) = -p(2);\n          dshape(5,2) = 1-p(0)-p(1);\n          break;\n        }\n\n      default:\n        {\n          /*\n          int np = GetNP();\n          double eps = 1e-6;\n          NgArrayMem<T,100> mem(2*np);\n          TFlatVector<T> shaper(np, &mem[0]);\n          TFlatVector<T> shapel(np, &mem[np]);\n          // Vector shaper(np), shapel(np);\n\t\n          for (int i = 0; i < 3; i++)\n            {\n              Point<3,T> pr(p), pl(p);\n              pr(i) += eps;\n              pl(i) -= eps;\n\t    \n              GetShapeNew (pr, shaper);\n              GetShapeNew (pl, shapel);\n              for (int j = 0; j < np; j++)\n                dshape(j, i) = (shaper(j) - shapel(j)) / (2 * eps);\n            }\n          */\n\n          AutoDiff<3,T> adx(p(0), 0);\n          AutoDiff<3,T> ady(p(1), 1);\n          AutoDiff<3,T> adz(p(2), 2);\n          Point<3,AutoDiff<3,T>> adp{adx, ady, adz};\n          NgArrayMem<AutoDiff<3,T>,100> mem(np);\n          TFlatVector<AutoDiff<3,T>> adshape(np, &mem[0]);\n          GetShapeNew (adp, adshape);\n          for (int j = 0; j < np; j++)\n            for (int k = 0; k < 3; k++)\n              dshape(j,k) = adshape(j).DValue(k);\n        }\n      }\n  }\n\n  template void Element2d :: GetShapeNew (const Point<2,double> & p, TFlatVector<double> shape) const;\n  template void Element2d :: GetShapeNew (const Point<2,SIMD<double>> & p, TFlatVector<SIMD<double>> shape) const;\n\n  template void Element2d::GetDShapeNew<double> (const Point<2> &, MatrixFixWidth<2> &) const;\n  template void Element2d::GetDShapeNew<SIMD<double>> (const Point<2,SIMD<double>> &, MatrixFixWidth<2,SIMD<double>> &) const;\n\n\n  template DLL_HEADER void Element :: GetShapeNew (const Point<3,double> & p, TFlatVector<double> shape) const;\n  template DLL_HEADER void Element :: GetShapeNew (const Point<3,SIMD<double>> & p, TFlatVector<SIMD<double>> shape) const;\n  \n  template void Element::GetDShapeNew<double> (const Point<3> &, MatrixFixWidth<3> &) const;\n  template void Element::GetDShapeNew<SIMD<double>> (const Point<3,SIMD<double>> &, MatrixFixWidth<3,SIMD<double>> &) const;\n\n\n  void Element :: \n  GetPointMatrix (const T_POINTS & points,\n                  DenseMatrix & pmat) const\n  {\n    int np = GetNP();\n    for (int i = 1; i <= np; i++)\n      {\n        const auto& p = points[PNum(i)];\n        pmat.Elem(1, i) = p[0];\n        pmat.Elem(2, i) = p[1];\n        pmat.Elem(3, i) = p[2];\n      }\n  }\n\n\n\n\n  double Element :: CalcJacobianBadness (const T_POINTS & points) const\n  {\n    int nip = GetNIP();\n    DenseMatrix trans(3,3);\n    DenseMatrix pmat;\n  \n    pmat.SetSize (3, GetNP());\n    GetPointMatrix (points, pmat);\n\n    double err = 0;\n    for (int i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n\n        // Frobenius norm\n        double frob = 0;\n        for (int j = 1; j <= 9; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n        frob /= 3;\n\n        double det = -trans.Det();\n      \n        if (det <= 0)\n          err += 1e12;\n        else\n          err += frob * frob * frob / det;\n      }\n\n    err /= nip;\n    return err;\n  }\n\n  double Element :: \n  CalcJacobianBadnessDirDeriv (const T_POINTS & points,\n                               int pi, Vec<3> & dir, double & dd) const\n  {\n    int i, j, k;\n    int nip = GetNIP();\n    DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3);\n    DenseMatrix pmat, vmat;\n  \n    pmat.SetSize (3, GetNP());\n    vmat.SetSize (3, GetNP());\n\n    GetPointMatrix (points, pmat);\n  \n    for (i = 1; i <= np; i++)\n      for (j = 1; j <= 3; j++)\n        vmat.Elem(j, i) = 0;\n    for (j = 1; j <= 3; j++)\n      vmat.Elem(j, pi) = dir(j-1);\n\n\n\n    double err = 0;\n    dd = 0;\n\n    for (i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n        GetTransformation (i, vmat, dtrans);\n\n\n        // Frobenius norm\n        double frob = 0;\n        for (j = 1; j <= 9; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n      \n        double dfrob = 0;\n        for (j = 1; j <= 9; j++)\n          dfrob += trans.Get(j) * dtrans.Get(j);\n        dfrob = dfrob / frob;\n      \n        frob /= 3;      \n        dfrob /= 3;\n\n      \n        double det = trans.Det();\n        double ddet = 0;\n      \n        for (j = 1; j <= 3; j++)\n          {\n            hmat = trans;\n            for (k = 1; k <= 3; k++)\n              hmat.Elem(k, j) = dtrans.Get(k, j);\n            ddet += hmat.Det();\n          }\n\n\n        det *= -1;\n        ddet *= -1;\n\n      \n        if (det <= 0)\n          err += 1e12;\n        else\n          {\n            err += frob * frob * frob / det;\n            dd += (3 * frob * frob * dfrob * det - frob * frob * frob * ddet) / (det * det);\n          }\n      }\n\n    err /= nip;\n    dd /= nip;\n    return err;\n  }\n\n  double Element :: \n  CalcJacobianBadnessGradient (const T_POINTS & points,\n                               int pi, Vec<3> & grad) const\n  {\n    int nip = GetNIP();\n    DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3);\n    DenseMatrix pmat, vmat;\n  \n    pmat.SetSize (3, GetNP());\n    vmat.SetSize (3, GetNP());\n\n    GetPointMatrix (points, pmat);\n  \n    for (int i = 1; i <= np; i++)\n      for (int j = 1; j <= 3; j++)\n        vmat.Elem(j, i) = 0;\n    for (int j = 1; j <= 3; j++)\n      vmat.Elem(j, pi) = 1.;\n\n\n    double err = 0;\n\n    double dfrob[3];\n\n    grad = 0;\n\n    for (int i = 1; i <= nip; i++)\n      {\n        GetTransformation (i, pmat, trans);\n        GetTransformation (i, vmat, dtrans);\n \n        // Frobenius norm\n        double frob = 0;\n        for (int j = 1; j <= 9; j++)\n          frob += sqr (trans.Get(j));\n        frob = sqrt (frob);\n\n        for(int k = 0; k<3; k++)\n          {\n            dfrob[k] = 0;\n            for (int j = 1; j <= 3; j++)\n              dfrob[k] += trans.Get(k+1,j) * dtrans.Get(k+1,j);\n            dfrob[k] = dfrob[k] / (3.*frob);\n          }\n\n        frob /= 3;      \n\n        double det = trans.Det();\n        double ddet[3]; // = 0;\n      \n        for(int k=1; k<=3; k++)\n          {\n            int km1 = (k > 1) ? (k-1) : 3;\n            int kp1 = (k < 3) ? (k+1) : 1;\n            ddet[k-1] = 0;\n            for(int j=1; j<=3; j++)\n              {\n                int jm1 = (j > 1) ? (j-1) : 3;\n                int jp1 = (j < 3) ? (j+1) : 1;\n\t      \n                ddet[k-1] += (-1.)* dtrans.Get(k,j) * ( trans.Get(km1,jm1)*trans.Get(kp1,jp1) - \n                                                        trans.Get(km1,jp1)*trans.Get(kp1,jm1) );\n              }\n          }\n\n      \n        det *= -1;\n      \n        if (det <= 0)\n          err += 1e12;\n        else\n          {\n            err += frob * frob * frob / det;\n            double fac = (frob * frob)/(det * det);\n            for(int j=0; j<3; j++)\n              grad(j) += fac * (3 * dfrob[j] * det - frob * ddet[j]);\n          }\n      }\n\n    err /= nip;\n    grad *= 1./nip;\n    return err;\n  }\n\n\n\n\n\n  void Element :: ComputeIntegrationPointData () const\n  {\n    switch (GetType())\n      {\n      case TET: if (ipdtet.Size()) return; break;\n      case TET10: if (ipdtet10.Size()) return; break;\n      default:\n        PrintSysError (\"Element::ComputeIntegrationPoint, illegal type \", int(typ));\n      }\n\n    switch (GetType())\n      {\n      case TET: ipdtet.SetSize(GetNIP()); break;\n      case TET10: ipdtet10.SetSize(GetNIP()); break;\n      default:\n        PrintSysError (\"Element::ComputeIntegrationPoint, illegal type2 \", int(typ));\n      }\n\n\n    for (int i = 1; i <= GetNIP(); i++)\n      {\n        IntegrationPointData * ipd = new IntegrationPointData;\n        GetIntegrationPoint (i, ipd->p, ipd->weight);\n        ipd->shape.SetSize(GetNP());\n        ipd->dshape.SetSize(3, GetNP());\n\n        GetShape (ipd->p, ipd->shape);\n        GetDShape (ipd->p, ipd->dshape);\n\n        switch (GetType())\n          {\n          case TET: ipdtet.Elem(i).reset(ipd); break;\n          case TET10: ipdtet10.Elem(i).reset(ipd); break;\n          default:\n            PrintSysError (\"Element::ComputeIntegrationPoint(2), illegal type \", int(typ));\n          }\n      }\n  }\n\n\n\n\n\n\n\n  FaceDescriptor ::  FaceDescriptor()\n  { \n    surfnr = domin = domout  = bcprop = 0; \n    domin_singular = domout_singular = 0.;\n    // Philippose - 06/07/2009\n    // Initialise surface colour\n    surfcolour = Vec<4>(0.0,1.0,0.0,1.0);\n    tlosurf = -1; \n    // bcname = 0;\n    firstelement = -1;\n  }\n\n  FaceDescriptor ::  FaceDescriptor(const FaceDescriptor& other)\n    : surfnr(other.surfnr), domin(other.domin), domout(other.domout),\n      tlosurf(other.tlosurf), bcprop(other.bcprop), \n      surfcolour(other.surfcolour), bcname(other.bcname),\n      domin_singular(other.domin_singular), domout_singular(other.domout_singular)\n  { \n    firstelement = -1;\n  }\n\n  FaceDescriptor :: \n  FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi)\n  { \n    surfnr = surfnri; \n    domin = domini; \n    domout = domouti;\n    // Philippose - 06/07/2009\n    // Initialise surface colour\n    surfcolour = Vec<4>(0.0,1.0,0.0,1.0);\n    tlosurf = tlosurfi; \n    bcprop = surfnri;\n    domin_singular = domout_singular = 0.;\n    // bcname = 0;\n    firstelement = -1;\n  }\n\n  FaceDescriptor :: FaceDescriptor(const Segment & seg)\n  { \n    surfnr = seg.si; \n    domin = seg.domin+1;\n    domout = seg.domout+1;\n    // Philippose - 06/07/2009\n    // Initialise surface colour\n    surfcolour = Vec<4>(0.0,1.0,0.0,1.0);\n    tlosurf = seg.tlosurf+1;\n    bcprop = 0;\n    domin_singular = domout_singular = 0.;\n    // bcname = 0;\n    firstelement = -1;\n  }\n\n  int FaceDescriptor ::  SegmentFits (const Segment & seg)\n  {\n    return\n      surfnr == seg.si &&\n      domin == seg.domin+1 &&\n      domout == seg.domout+1  &&\n      tlosurf == seg.tlosurf+1;\n  }\n\n  // string FaceDescriptor :: default_bcname = \"default\";\n  /*\n  const string & FaceDescriptor :: GetBCName () const\n  {\n    static string defaultstring = \"default\";\n    if (bcname) return *bcname;\n    return defaultstring;\n  }\n  */\n\n  void FaceDescriptor :: SetBCName (string * bcn)\n  {\n    if (bcn)\n      bcname = *bcn;\n    else\n      bcname = \"default\";\n  }\n  \n  void FaceDescriptor :: DoArchive (Archive & ar)\n  {\n    ar & surfnr & domin & domout & tlosurf & bcprop\n      & surfcolour & bcname   \n      & domin_singular & domout_singular ;\n      // don't need:  firstelement\n  }\n  \n\n  \n  ostream & operator<<(ostream  & s, const FaceDescriptor & fd)\n  {\n    s << \"surfnr = \" << fd.SurfNr() \n      << \", domin = \" << fd.DomainIn()\n      << \", domout = \" << fd.DomainOut()\n      << \", tlosurf = \" << fd.TLOSurface()\n      << \", bcprop = \" << fd.BCProperty()\n      << \", bcname = \" << fd.GetBCName()\n      << \", domin_sing = \" << fd.DomainInSingular()\n      << \", domout_sing = \" << fd.DomainOutSingular()\n      << \", colour = \" << fd.SurfColour();\n    return s;\n  }\n\n\n  Identifications :: Identifications (Mesh & amesh)\n    : mesh(amesh), identifiedpoints(100), identifiedpoints_nr(100)\n  {\n    // identifiedpoints = new INDEX_2_HASHTABLE<int>(100);\n    // identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100);\n    maxidentnr = 0;\n  }\n\n  Identifications :: ~Identifications ()\n  {\n    ;\n    // delete identifiedpoints;\n    // delete identifiedpoints_nr;\n  }\n\n  void Identifications :: Delete ()\n  {\n    identifiedpoints.DeleteData();\n    identifiedpoints_nr.DeleteData();\n    idpoints_table.SetSize(0);\n\n    /*\n    delete identifiedpoints;\n    identifiedpoints = new INDEX_2_HASHTABLE<int>(100);\n    delete identifiedpoints_nr;\n    identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100);\n    */\n    maxidentnr = 0;\n  }\n\n  void Identifications :: DeleteInnerPointIdentifications ()\n  {\n    Array<std::tuple<PointIndex, PointIndex, int>> entries;\n    for(auto [pis, nr]: identifiedpoints)\n      {\n        PointIndex pi0 = pis[0];\n        PointIndex pi1 = pis[1];\n        if(mesh[pi0].Type() != INNERPOINT || mesh[pi1].Type() != INNERPOINT)\n            entries.Append( { pi0, pi1, nr } );\n      }\n\n    identifiedpoints.DeleteData();\n    identifiedpoints_nr.DeleteData();\n    idpoints_table.SetSize(0);\n\n    for (auto [pi0, pi1, nr]: entries)\n        Add(pi0, pi1, nr);\n  }\n\n    void Identifications :: DoArchive (Archive & ar)\n    {\n      ar & maxidentnr;\n      ar & identifiedpoints & identifiedpoints_nr;\n      ar & idpoints_table;\n      \n      if (ar.Output())\n        {\n          size_t s = type.Size();\n          ar & s;\n          for (auto & t : type)\n            ar & (unsigned char&)(t);\n        }\n      else\n        {\n          size_t s;\n          ar & s;\n          type.SetSize(s);\n          for (auto & t : type)\n            ar & (unsigned char&)(t);\n        }\n      if (ar.GetVersion(\"netgen\") > \"v6.2.2404-66\")\n        ar & names;\n    }    \n\n  \n\n  void Identifications :: Add (PointIndex pi1, PointIndex pi2, int identnr)\n  {\n    //  (*testout) << \"Identification::Add, pi1 = \" << pi1 << \", pi2 = \" << pi2 << \", identnr = \" << identnr << endl;\n    PointIndices<2> pair (pi1, pi2);\n    identifiedpoints.Set (pair, identnr);\n\n    // INDEX_3 tripl (pi1, pi2, identnr);\n    identifiedpoints_nr.Set ( { { pi1, pi2 }, identnr }, 1);\n\n    if (identnr > maxidentnr) maxidentnr = identnr;\n    names.SetSize(maxidentnr);\n\n    if (identnr+1 > idpoints_table.Size())\n      idpoints_table.ChangeSize (identnr+1);\n    idpoints_table.Add (identnr, pair);\n  \n    //  timestamp = NextTimeStamp();\n  }\n\n  int Identifications :: Get (PointIndex pi1, PointIndex pi2) const\n  {\n    INDEX_2 pair(pi1, pi2);\n    if (identifiedpoints.Used (pair))\n      return identifiedpoints.Get(pair);\n    else\n      return 0;\n  }\n\n  bool Identifications :: Get (PointIndex pi1, PointIndex pi2, int nr) const\n  {\n    // INDEX_3 tripl(pi1, pi2, nr);\n    // if (identifiedpoints_nr.Used (tripl))\n    if (identifiedpoints_nr.Used ( { { pi1, pi1 }, nr } ) )\n      return 1;\n    else\n      return 0;\n  }\n\n\n\n  int Identifications :: GetSymmetric (PointIndex pi1, PointIndex pi2) const\n  {\n    INDEX_2 pair(pi1, pi2);\n    if (identifiedpoints.Used (pair))\n      return identifiedpoints.Get(pair);\n\n    pair = INDEX_2 (pi2, pi1);\n    if (identifiedpoints.Used (pair))\n      return identifiedpoints.Get(pair);\n\n    return 0;\n  }\n\n\n  void Identifications :: GetMap (int identnr, idmap_type & identmap, bool symmetric) const\n  {\n    identmap.SetSize (mesh.GetNP());\n    identmap = 0;\n\n    if (identnr)\n      for (int i = 0; i < idpoints_table[identnr].Size(); i++)\n        {\n          INDEX_2 pair = idpoints_table[identnr][i];\n          identmap[pair.I1()] = pair.I2();\n          if(symmetric)\n            identmap[pair.I2()] = pair.I1();\n        }\n\n    else\n      {\n        cout << \"getmap, identnr = \" << identnr << endl;\n\n        /*\n        for (int i = 1; i <= identifiedpoints_nr.GetNBags(); i++)\n          for (int j = 1; j <= identifiedpoints_nr.GetBagSize(i); j++)\n        */\n        for (auto [hash, val] : identifiedpoints_nr)\n            {\n              /*\n              INDEX_3 i3;\n              int dummy;\n              identifiedpoints_nr.GetData (i, j, i3, dummy);\n              */\n\n              auto [hash_pts, hash_nr] = hash;\n              \n              if (hash_nr == identnr || !identnr)\n                {\n                  /*\n                  identmap.Elem(i3.I1()) = i3.I2();\n                  if(symmetric)\n                    identmap.Elem(i3.I2()) = i3.I1();\n                  */\n                  identmap[hash_pts.I1()] = hash_pts.I2();\n                  if(symmetric)\n                    identmap[hash_pts.I2()] = hash_pts.I1();\n                }\n            }  \n      }\n\n  }\n\n\n  Array<INDEX_3> Identifications :: GetPairs () const\n  {\n    Array<INDEX_3> pairs;\n    for(auto [hash, dummy] : identifiedpoints_nr)\n      // pairs.Append(i3);\n      {\n        auto [pts,nr] = hash;\n        pairs.Append ( { pts[0], pts[1], nr } );\n      }\n    return pairs;\n  }\n\n  void Identifications :: GetPairs (int identnr, \n                                    NgArray<INDEX_2> & identpairs) const\n  {\n    identpairs.SetSize(0);\n  \n    if (identnr == 0)\n      {\n        /*\n      for (int i = 1; i <= identifiedpoints.GetNBags(); i++)\n        for (int j = 1; j <= identifiedpoints.GetBagSize(i); j++)\n          {\n            INDEX_2 i2;\n            int nr;\n            identifiedpoints.GetData (i, j, i2, nr);\n            identpairs.Append (i2);\n          }\n        */\n        for (auto [hash,val] : identifiedpoints)\n          identpairs.Append (hash);\n      }\n    else\n      {\n        /*\n      for (int i = 1; i <= identifiedpoints_nr.GetNBags(); i++)\n        for (int j = 1; j <= identifiedpoints_nr.GetBagSize(i); j++)\n          {\n            INDEX_3 i3;\n            int dummy;\n            identifiedpoints_nr.GetData (i, j, i3 , dummy);\n\t  \n            if (i3.I3() == identnr)\n              identpairs.Append (INDEX_2(i3.I1(), i3.I2()));\n          }\n        */\n        for (auto [hash,val] : identifiedpoints_nr)\n          {\n            auto [hash_pts, hash_nr] = hash;\n            if (hash_nr == identnr)\n              identpairs.Append (hash_pts);\n          }\n      }\n  }\n\n\n  void Identifications :: SetMaxPointNr (int maxpnum)\n  {\n    /*\n    for (int i = 1; i <= identifiedpoints.GetNBags(); i++)\n      for (int j = 1; j <= identifiedpoints.GetBagSize(i); j++)\n        {\n          INDEX_2 i2;\n          int nr;\n          identifiedpoints.GetData (i, j, i2, nr);\n\t\n          if (i2.I1() > maxpnum || i2.I2() > maxpnum)\n            {\n              i2.I1() = i2.I2() = -1;\n              identifiedpoints.SetData (i, j, i2, -1);\t    \n            }\n        }\n    */\n\n    // can we get data by reference ? \n    for (auto [hash,data] : identifiedpoints)\n      {\n        if (hash.I1() > IndexBASE<PointIndex>()+maxpnum-1 ||\n            hash.I2() > IndexBASE<PointIndex>()+maxpnum-1)\n          {\n            identifiedpoints[hash] = -1;\n          }\n            \n      }\n  }\n\n  // Map points in the identifications to new point numbers\n  // deletes identifications with invalid (mapped) points\n  void Identifications :: MapPoints(FlatArray<PointIndex, PointIndex> op2np)\n  {\n    auto pairs = GetPairs();\n    Delete();\n\n    for(auto pair : pairs)\n      {\n        auto p1 = op2np[pair.I1()];\n        auto p2 = op2np[pair.I2()];\n        if(p1.IsValid() && p2.IsValid())\n          Add(p1, p2, pair.I3());\n      }\n  }\n\n  void Identifications :: Print (ostream & ost) const\n  {\n    ost << \"Identifications:\" << endl;\n    ost << \"pairs: \" << endl << identifiedpoints << endl;\n    // ost << \"pairs and nr: \" << endl << identifiedpoints_nr << endl;\n    ost << \"pairs and nr: \" << endl;\n    for (auto [key,val] : identifiedpoints_nr)\n      ost << get<0>(key) << \",\" << get<1>(key) << \": \" << val << endl;\n    \n    ost << \"table: \" << endl << idpoints_table << endl;\n  }\n\n  ostream & operator<< (ostream & ost, const BoundaryLayerParameters & mp)\n  {\n    auto print_vec = [&ost](auto & v) {\n        ost << \"[\";\n        for (const auto & val : v)\n          ost << val << \" \";\n        ost << \"]\";\n    };\n    ost << \"BoundaryLayerParameters\" << endl;\n    ost << \"  boundary: \";\n    switch(mp.boundary.index())\n      {\n        case 0: ost << std::get<0>(mp.boundary); break;\n        case 1: ost << std::get<1>(mp.boundary); break;\n        case 2: print_vec(std::get<2>(mp.boundary)); break;\n      }\n    ost << \"\\n  thickness: \";\n    switch(mp.thickness.index())\n      {\n        case 0: ost << std::get<0>(mp.thickness); break;\n        case 1: print_vec(std::get<1>(mp.thickness)); break;\n      }\n    ost <<\"\\n  new_material: \";\n    if(!mp.new_material) ost << \"nullopt\";\n    else {\n      switch(mp.new_material->index())\n        {\n          case 0: ost << std::get<0>(*mp.new_material); break;\n          case 1:\n          for (const auto & [key, value] : std::get<1>(*mp.new_material))\n            ost << key << \" -> \" << value << \", \";\n          break;\n        }\n    }\n    ost << \"\\n  domain: \";\n    switch(mp.domain.index())\n      {\n        case 0: ost << std::get<0>(mp.domain); break;\n        case 1: ost << std::get<1>(mp.domain); break;\n        case 2: print_vec(std::get<2>(mp.domain)); break;\n      }\n    ost << \"\\n  outside: \" << mp.outside;\n    ost << \"\\n  project_boundaries: \";\n    if(mp.project_boundaries) {\n      auto & proj_bnd = *mp.project_boundaries;\n      switch(proj_bnd.index())\n        {\n          case 0: ost << std::get<0>(proj_bnd); break;\n          case 1: print_vec(std::get<1>(proj_bnd)); break;\n        }\n    }\n    else\n      ost << \"nullopt\";\n    ost << \"\\n  grow_edges: \" << mp.grow_edges;\n    ost << \"\\n  limit_growth_vectors: \" << mp.limit_growth_vectors;\n    ost << \"\\n  sides_keep_surfaceindex: \" << (mp.sides_keep_surfaceindex ? ToString(*mp.sides_keep_surfaceindex) : \"nullopt\");\n    ost << \"\\n  disable_curving: \" << mp.disable_curving;\n    ost << endl;\n    return ost;\n  }\n\n  MeshingParameters :: MeshingParameters ()\n  {\n    // optimize3d = \"cmdmustm\";\n    //optimize3d = \"cmdmstm\";\n    // optsteps3d = 3;\n    // optimize2d = \"smsmsmSmSmSm\";\n    // optsteps2d = 3;\n    // opterrpow = 2;\n    // blockfill = 1;\n    // filldist = 0.1;\n    // safety = 5;\n    // relinnersafety = 3;\n    // uselocalh = 1;\n    // grading = 0.3;\n    // delaunay = 1;\n    // maxh = 1e10;\n    // minh = 0;\n    // meshsizefilename = NULL;\n    // startinsurface = 0;\n    // checkoverlap = 1;\n    // checkoverlappingboundary = 1;\n    // checkchartboundary = 1;\n    // curvaturesafety = 2;\n    // segmentsperedge = 1;\n    // parthread = 0;\n\n    // elsizeweight = 0.2;\n    // giveuptol2d = 200;\n    // giveuptol = 10;\n    // maxoutersteps = 10;\n    // starshapeclass = 5;\n    // baseelnp = 0;\n    // sloppy = 1;\n\n    // badellimit = 175;\n    // check_impossible = 0;\n    // secondorder = 0;\n  }\n\n  void MeshingParameters :: Print (ostream & ost) const\n  {\n    ost << \"Meshing parameters: \" << endl\n        << \"optimize3d = \" << optimize3d << endl\n        << \"optsteps3d = \" << optsteps3d << endl\n        << \" optimize2d = \" <<  optimize2d << endl\n        << \" optsteps2d = \" <<  optsteps2d << endl\n        << \" opterrpow = \" <<  opterrpow << endl\n        << \" blockfill = \" <<  blockfill << endl\n        << \" filldist = \" <<  filldist << endl\n        << \" safety = \" <<  safety << endl\n        << \" relinnersafety = \" <<  relinnersafety << endl\n        << \" uselocalh = \" <<  uselocalh << endl\n        << \" grading = \" <<  grading << endl\n        << \" delaunay = \" <<  delaunay << endl\n        << \" maxh = \" <<  maxh << endl\n        << \" meshsizefilename = \" <<  meshsizefilename << endl\n        << \" startinsurface = \" <<  startinsurface << endl\n        << \" checkoverlap = \" <<  checkoverlap << endl\n        << \" checkchartboundary = \" <<  checkchartboundary << endl\n        << \" curvaturesafety = \" <<  curvaturesafety << endl\n        << \" segmentsperedge = \" <<  segmentsperedge << endl\n        << \" parthread = \" <<  parthread << endl\n        << \" elsizeweight = \" <<  elsizeweight << endl\n        << \" giveuptol2d = \" <<  giveuptol2d << endl\n        << \" giveuptol = \" <<  giveuptol << endl\n        << \" maxoutersteps = \" <<  maxoutersteps << endl\n        << \" starshapeclass = \" <<  starshapeclass << endl\n        << \" baseelnp        = \" <<  baseelnp        << endl\n        << \" sloppy = \" <<  sloppy << endl\n        << \" badellimit = \" <<  badellimit << endl\n        << \" secondorder = \" <<  secondorder << endl\n        << \" elementorder = \" <<  elementorder << endl\n        << \" quad = \" <<  quad << endl\n        << \" inverttets = \" <<  inverttets << endl\n        << \" inverttrigs = \" <<  inverttrigs << endl\n        << \"closeedge enabled = \" << closeedgefac.has_value() << endl\n        << \"closeedgefac = \" << closeedgefac.value_or(0.) << endl;\n  }\n\n  /*\n  void MeshingParameters :: CopyFrom(const MeshingParameters & other)\n  {\n    //strcpy(optimize3d,other.optimize3d); \n    optimize3d = other.optimize3d;\n    optsteps3d = other.optsteps3d;\n    //strcpy(optimize2d,other.optimize2d); \n    optimize2d = other.optimize2d;\n    optsteps2d = other.optsteps2d;\n    opterrpow = other.opterrpow;\n    blockfill = other.blockfill;\n    filldist = other.filldist;\n    safety = other.safety;\n    relinnersafety = other.relinnersafety;\n    uselocalh = other.uselocalh;\n    grading = other.grading;\n    delaunay = other.delaunay;\n    maxh = other.maxh;\n    //strcpy(const_cast<char*>(meshsizefilename), other.meshsizefilename);\n    //const_cast<char*>(meshsizefilename) = other.meshsizefilename; //???\n    meshsizefilename = other.meshsizefilename;\n    startinsurface = other.startinsurface;\n    checkoverlap = other.checkoverlap;\n    checkoverlappingboundary = other.checkoverlappingboundary;\n    checkchartboundary = other.checkchartboundary;\n    curvaturesafety = other.curvaturesafety;\n    segmentsperedge = other.segmentsperedge;\n    parthread = other.parthread;\n    elsizeweight = other.elsizeweight;\n    giveuptol2d = other.giveuptol2d;\n    giveuptol = other.giveuptol;\n    maxoutersteps = other.maxoutersteps;\n    starshapeclass = other.starshapeclass;\n    baseelnp = other.baseelnp;       \n    sloppy = other.sloppy;\n    badellimit = other.badellimit;\n    secondorder = other.secondorder;\n    elementorder = other.elementorder;\n    quad = other.quad;\n    inverttets = other.inverttets;\n    inverttrigs = other.inverttrigs;\n  }\n  */\n\n  DebugParameters :: DebugParameters ()\n  {\n    slowchecks = 0;\n    haltsuccess = 0;\n    haltnosuccess = 0;\n    haltlargequalclass = 0;\n    haltsegment = 0;\n    haltsegmentp1 = 0;\n    haltsegmentp2 = 0;\n    write_mesh_on_error = getenv(\"NG_WRITE_MESH_ON_ERROR\");\n  };\n\n\n\n}\n\n"
  },
  {
    "path": "libsrc/meshing/meshtype.hpp",
    "content": "#ifndef MESHTYPE\n#define MESHTYPE\n\n\n/**************************************************************************/\n/* File:   meshtype.hpp                                                   */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   01. Okt. 95                                                    */\n/**************************************************************************/\n\n#include <variant>\n\n#include <mydefs.hpp>\n#include <general/template.hpp>\n#include <core/mpi_wrapper.hpp>\n#include <gprim/geom3d.hpp>\n#include <linalg.hpp>\n\n#include \"core/exception.hpp\"\n#include \"msghandler.hpp\"\n\nnamespace netgen\n{\n\n  /*\n    Classes for NETGEN\n  */\n\n\n  enum ELEMENT_TYPE : unsigned char { \n    SEGMENT = 1, SEGMENT3 = 2,\n    TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14,\n    TET = 20, TET10 = 21, \n    PYRAMID = 22, PRISM = 23, PRISM12 = 24, PRISM15 = 27, PYRAMID13 = 28,\n    HEX = 25, HEX20 = 26, HEX7 = 29\n  };\n\n\n  using ELEMENT_EDGE = std::array<int,2>;\n  using ELEMENT_FACE = std::array<int,4>;\n\n\n#define ELEMENT_MAXPOINTS 20\n#define ELEMENT2D_MAXPOINTS 8\n\n\n  enum POINTTYPE : unsigned char { FIXEDPOINT = 1, EDGEPOINT = 2, SURFACEPOINT = 3, INNERPOINT = 4 };\n  enum ELEMENTTYPE { FREEELEMENT, FIXEDELEMENT };\n  enum OPTIMIZEGOAL { OPT_QUALITY, OPT_CONFORM, OPT_REST, OPT_WORSTCASE, OPT_LEGAL };\n\n\n  extern DLL_HEADER size_t timestamp;\n  inline size_t GetTimeStamp() \n  { \n    return timestamp; \n  }\n\n  inline size_t NextTimeStamp()\n  {\n    timestamp++;\n    return timestamp;\n  }\n  \n  class PointGeomInfo\n  {\n  public:\n    int trignum;   // for STL Meshing\n    double u, v;   // for OCC Meshing\n\n    PointGeomInfo () = default;\n    PointGeomInfo (const PointGeomInfo&) = default;\n    PointGeomInfo (PointGeomInfo &&) = default;\n    PointGeomInfo & operator= (const PointGeomInfo&) = default;\n    PointGeomInfo & operator= (PointGeomInfo&&) = default;\n  };\n\n  inline ostream & operator<< (ostream & ost, const PointGeomInfo & gi)\n  {\n    return (ost << gi.trignum << \" \" << gi.u << \" \" << gi.v);\n  }\n\n  inline istream & operator>> (istream & ist, PointGeomInfo & gi)\n  {\n    return (ist >> gi.trignum >> gi.u >> gi.v);\n  }\n\n\n\n  class MultiPointGeomInfo\n  {\n    ArrayMem<PointGeomInfo, 100> mgi;\n  public:\n    int AddPointGeomInfo (const PointGeomInfo & gi);\n    void Init () { mgi.SetSize(0); }\n    void DeleteAll () { mgi.SetSize(0); }\n\n    int GetNPGI () const { return mgi.Size(); }\n    const PointGeomInfo & GetPGI (int i) const { return mgi[i-1]; }\n\n    MultiPointGeomInfo () = default;\n    MultiPointGeomInfo (const MultiPointGeomInfo&) = default;\n    MultiPointGeomInfo (MultiPointGeomInfo &&) = default;\n    MultiPointGeomInfo & operator= (const MultiPointGeomInfo&) = delete;\n    MultiPointGeomInfo & operator= (MultiPointGeomInfo&&) = default;\n  };\n\n\n  class EdgePointGeomInfo\n  {\n  public:\n    int edgenr;\n    int body;    // for ACIS\n    double dist; // for 2d meshing\n    double u, v; // for OCC Meshing\n\n  public:\n    EdgePointGeomInfo ()\n      : edgenr(-1), body(0), dist(0.0), u(0.0), v(0.0) { ; }\n    EdgePointGeomInfo (const EdgePointGeomInfo&) = default;\n    EdgePointGeomInfo & operator= (const EdgePointGeomInfo & gi2) = default;\n  };\n\n  inline ostream & operator<< (ostream & ost, const EdgePointGeomInfo & gi)\n  {\n    ost << \"epgi: edgnr=\" << gi.edgenr << \", dist=\" << gi.dist;\n    return ost;\n  }\n\n\n  template <typename T, typename TIndex, int BASE_>\n  class Index\n  {\n  public:\n    T i;\n\n    static constexpr int BASE = BASE_;\n    static constexpr TIndex Base() { return TIndex(BASE_); } \n\n    class t_invalid { public: constexpr t_invalid() = default; };\n    static constexpr t_invalid INVALID{};\n\n    typedef decltype( declval<T>()-declval<T>() ) T_diff;\n    \n  public:\n    constexpr Index () = default;\n    constexpr Index (const Index& i2) = default;\n    constexpr Index (Index &&) = default;\n    Index & operator= (const Index&) = default;\n    Index & operator= (Index&&) = default;\n\n    // private:\n    constexpr Index (T ai) : i(ai)\n    {\n#ifdef DEBUG\n      if (ai < BASE_)\n        cout << \"illegal Index, use Index::INVALID instead\" << endl;\n#endif\n    }\n\n\n    /*\n      // didn't manage constexpr friend functions so far ???\n    friend auto operator+ (Index, int) -> TIndex;\n    friend TIndex operator+ (Index, size_t);    \n    friend TIndex operator+ (int, Index);\n    friend TIndex operator+ (size_t, Index);\n    friend constexpr TIndex operator- (Index, int);\n    friend int operator- (Index, Index);\n    friend bool operator< (Index a, Index b);\n    friend bool operator> (Index a, Index b);\n    friend bool operator>= (Index a, Index b);\n    friend bool operator<= (Index a, Index b);\n    friend bool operator== (Index a, Index b);\n    friend bool operator!= (Index a, Index b);\n    */\n    \n  public:\n    constexpr Index (t_invalid inv) : i(long(BASE)-1) { ; }\n    // protected:\n    constexpr operator T () const { return i; }\n    explicit constexpr operator T& () { return i; }\n  public:\n    TIndex operator++ (int) { TIndex hi{*this}; i++; return hi; }\n    TIndex operator-- (int) { TIndex hi(*this); i--; return hi; }\n    TIndex & operator++ () { i++; return static_cast<TIndex&>(*this); }\n    TIndex & operator-- () { i--; return static_cast<TIndex&>(*this); }\n\n    /*\n    constexpr TIndex operator+= (int add) { i += add; return TIndex{*this}; }\n    constexpr TIndex operator+= (size_t add) { i += add; return TIndex{*this}; }\n    constexpr TIndex operator-= (int add) { i -= add; return TIndex{*this}; }\n    constexpr TIndex operator-= (size_t add) { i -= add; return TIndex{*this}; }\n    */\n    constexpr TIndex operator+= (T_diff add) { i += add; return TIndex{*this}; }\n    constexpr TIndex operator-= (T_diff add) { i -= add; return TIndex{*this}; }\n    \n    constexpr auto operator- (Index i2) const { return i-i2.i; }\n\n    // bool operator== (Index i2) const { return i==i2.i; }\n    // bool operator!= (Index i2) const { return i!=i2.i; }\n    void Invalidate() { i = long(TIndex::BASE)-1; }\n    bool IsValid() const { return i+1 != TIndex::BASE; }\n    // operator bool() const { return IsValid(); }\n\n    void DoArchive (Archive & ar) { ar & i; }\n  };\n\n\n  template <typename T, typename TIndex, int Base>  \n  constexpr auto operator+ (Index<T,TIndex,Base> ind, int i) { Index<T,TIndex,Base> res(ind); return res += i; }\n  template <typename T, typename TIndex, int Base>\n  constexpr auto operator+ (Index<T,TIndex,Base> ind, size_t i) { Index<T,TIndex,Base> res(ind); return res += i; }\n  template <typename T, typename TIndex, int Base>    \n  constexpr TIndex operator+ (int i, Index<T,TIndex,Base> ind) { return ind+i; } // Indexx<T,TIndex,Base> res(ind); return res += i; \n  template <typename T, typename TIndex, int Base>    \n  inline TIndex operator+ (size_t i, Index<T,TIndex,Base> ind) { return ind+i; } //  TIndex res(ind); res += i; return res; }\n  \n  template <typename T, typename TIndex, int Base>    \n  constexpr inline auto operator- (Index<T,TIndex,Base> ind, int i) { Index<T,TIndex,Base> res(ind); return res -= i; }  \n  // template <typename T, typename TIndex, int Base>    \n  // constexpr inline auto operator- (Index<T,TIndex,Base> pa, Index<T,TIndex,Base> pb) { return pa.i-pb.i; }\n  \n  template <typename T, typename TIndex, int Base>      \n  inline bool operator< (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a-b < 0; }\n  template <typename T, typename TIndex, int Base>      \n  inline bool operator> (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a-b > 0; }\n  template <typename T, typename TIndex, int Base>      \n  inline bool operator>= (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a-b >= 0; }\n  template <typename T, typename TIndex, int Base>      \n  inline bool operator<= (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a-b <= 0; }\n\n  template <typename T, typename TIndex, int Base>      \n  inline bool operator== (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a.i == b.i; }\n  template <typename T, typename TIndex, int Base>      \n  inline bool operator!= (Index<T,TIndex,Base> a, Index<T,TIndex,Base> b) { return a.i != b.i; }\n\n\n  template <typename T, typename TIndex, int Base>      \n  inline void SetInvalid (Index<T,TIndex,Base> & id) { id.Invalidate(); }\n  template <typename T, typename TIndex, int Base>        \n  inline bool IsInvalid (const Index<T,TIndex,Base> & id) { return !id.IsValid(); }\n\n\n  \n  class PointIndex : public Index<int,PointIndex,1>\n  {\n  public:\n    using Index::Index;\n    template <int N> friend class PointIndices;    \n  };\n\n}\n\nnamespace ngcore\n{\n  template<> \n  constexpr netgen::PointIndex IndexBASE<netgen::PointIndex> () { return netgen::PointIndex::Base(); }\n}\n\nnamespace netgen\n{\n\n  // input-output is 1-based\n  inline istream & operator>> (istream & ist, PointIndex & pi)\n  {\n    // int i; ist >> i; pi = PointIndex(i); return ist;\n    int i; ist >> i;\n    pi = IndexBASE<PointIndex>()+i-1;\n    return ist;\n  }\n\n  inline ostream & operator<< (ostream & ost, const PointIndex & pi)\n  {\n    // return (ost << int(pi));\n    int intpi = pi - IndexBASE<PointIndex>() + 1;\n    return (ost << intpi);    \n  }\n\n\n\n  /*\n    PointIndices<2> etc are derived from historic INDEX_2 etc to be useable in old HASHTABLEs.\n    Will change to IVec<2> or std::array when INDEX_2 is not needed anymore\n   */\n  \n  template <int N> class PointIndices;\n  template <> class PointIndices<2> : public INDEX_2\n  {\n  public:\n    PointIndices () = default;\n    constexpr PointIndices (const PointIndices&) = default;\n    constexpr PointIndices (PointIndices&&) = default;\n    PointIndices & operator= (const PointIndices&) = default;\n    PointIndices & operator= (PointIndices&&) = default;\n    \n    constexpr PointIndices (INDEX_2 i2) : INDEX_2(i2) { ; }\n    constexpr PointIndices (PointIndex i1, PointIndex i2) : INDEX_2(i1,i2) { ; } \n    constexpr PointIndex operator[] (int i) const { return PointIndex(INDEX_2::operator[](i)); }\n    PointIndex & operator[] (int i) { return reinterpret_cast<PointIndex&>(INDEX_2::operator[](i)); }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE& ar) { ar.Do(&I1(), 2); }\n    \n    PointIndex & I1 () { return (*this)[0]; }\n    PointIndex & I2 () { return (*this)[1]; }\n    PointIndex I1 () const { return (*this)[0]; }\n    PointIndex I2 () const { return (*this)[1]; }\n    \n    using INDEX_2::Sort;\n    static PointIndices Sort(PointIndex i1, PointIndex i2) { return INDEX_2::Sort(i1, i2); }\n    template <size_t J>\n    PointIndex get() const { return PointIndex(INDEX_2::operator[](J)); }    \n  };\n  \n  template <> class PointIndices<3> : public INDEX_3\n  {\n  public:\n    PointIndices () = default;\n    PointIndices (const PointIndices&) = default;\n    PointIndices (PointIndices&&) = default;\n    PointIndices & operator= (const PointIndices&) = default;\n    PointIndices & operator= (PointIndices&&) = default;\n    constexpr PointIndices (INDEX_3 i3) : INDEX_3(i3) { ; }\n    constexpr PointIndices (PointIndex i1, PointIndex i2, PointIndex i3) : INDEX_3(i1,i2,i3) { ; }\n    PointIndex operator[] (int i) const { return PointIndex(INDEX_3::operator[](i)); }\n    PointIndex & operator[] (int i) { return reinterpret_cast<PointIndex&>(INDEX_3::operator[](i)); }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE& ar) { ar.Do(&I1(), 3); }\n    \n    PointIndex & I1 () { return (*this)[0]; }\n    PointIndex & I2 () { return (*this)[1]; }\n    PointIndex & I3 () { return (*this)[2]; }\n    PointIndex I1 () const { return (*this)[0]; }\n    PointIndex I2 () const { return (*this)[1]; }\n    PointIndex I3 () const { return (*this)[2]; }\n\n    using INDEX_3::Sort;\n    static PointIndices Sort(PointIndex i1, PointIndex i2, PointIndex i3) { return INDEX_3::Sort(i1, i2, i3); }\n    template <size_t J>\n    PointIndex get() const { return PointIndex(INDEX_3::operator[](J)); }    \n  };\n  \n  template <> class PointIndices<4> : public INDEX_4\n  {\n  public:\n    PointIndices () = default;\n    PointIndices (INDEX_4 i4) : INDEX_4(i4) { ; }\n    PointIndices (PointIndex i1, PointIndex i2, PointIndex i3, PointIndex i4) : INDEX_4(i1,i2,i3,i4) { ; } \n    PointIndex operator[] (int i) const { return PointIndex(INDEX_4::operator[](i)); }\n    PointIndex & operator[] (int i) { return reinterpret_cast<PointIndex&>(INDEX_4::operator[](i)); }\n\n    template <typename ARCHIVE>\n    void DoArchive(ARCHIVE& ar) { ar.Do(&I1(), 4); }\n    \n    PointIndex & I1 () { return (*this)[0]; }\n    PointIndex & I2 () { return (*this)[1]; }\n    PointIndex & I3 () { return (*this)[2]; }\n    PointIndex & I4 () { return (*this)[3]; }\n    PointIndex I1 () const { return (*this)[0]; }\n    PointIndex I2 () const { return (*this)[1]; }\n    PointIndex I3 () const { return (*this)[2]; }\n    PointIndex I4 () const { return (*this)[3]; }\n    \n    using INDEX_4::Sort;\n    // static PointIndices Sort(PointIndex i1, PointIndex i2, PointIndex i3, PointIndex i4) { return INDEX_4::Sort(i1, i2, i3, i4); }\n    template <size_t J>\n    PointIndex get() const { return PointIndex(INDEX_4::operator[](J)); }    \n  };\n\n\n  template <int N>\n  class SortedPointIndices : public PointIndices<N>\n  {\n    using PointIndices<N>::Sort;\n  public:\n    constexpr SortedPointIndices (PointIndices<N> pnts)\n      : PointIndices<N>(pnts.Sort()) { } \n    \n      template <typename ...Pnts>\n    constexpr SortedPointIndices (Pnts ...pnts)\n      : PointIndices<N>(pnts...)\n    { Sort(); }\n  };\n  \n}\n\n\n\nnamespace ngcore\n{\n\n  template <>\n  struct CHT_trait<netgen::PointIndex>\n  {\n    constexpr static inline netgen::PointIndex Invalid() { return netgen::PointIndex::INVALID; }\n    constexpr static inline size_t HashValue (const netgen::PointIndex & hash, size_t mask)\n    { return (hash-IndexBASE<netgen::PointIndex>()) & mask; }\n  };\n\n\n  template <>\n  struct CHT_trait<netgen::PointIndices<2>>\n  {\n    constexpr static inline netgen::PointIndices<2> Invalid() { return { netgen::PointIndex::INVALID, netgen::PointIndex::INVALID} ; }\n    constexpr static inline size_t HashValue (const netgen::PointIndices<2> & hash, size_t mask)\n    { return HashValue2(IVec<2>(hash[0]-IndexBASE<netgen::PointIndex>(),\n                                hash[1]-IndexBASE<netgen::PointIndex>()), mask); }\n  };\n  \n\n  template <>\n  struct CHT_trait<netgen::SortedPointIndices<2>>\n  {\n    constexpr static inline netgen::SortedPointIndices<2> Invalid() { return { netgen::PointIndex::INVALID, netgen::PointIndex::INVALID} ; }\n    constexpr static inline size_t HashValue (const netgen::SortedPointIndices<2> & hash, size_t mask)\n    // { return HashValue2(IVec<2,netgen::INDEX>(hash[0], hash[1]), mask); }\n    { return CHT_trait<netgen::PointIndices<2>>::HashValue (hash, mask); }\n  };\n  \n\n  template <>\n  constexpr inline netgen::PointIndices<3> InvalidHash<netgen::PointIndices<3>> ()\n  { return netgen::PointIndices<3>{netgen::PointIndex::INVALID, netgen::PointIndex::INVALID, netgen::PointIndex::INVALID}; }\n\n  /*\n  template <>\n  constexpr inline netgen::SortedPointIndices<2> InvalidHash<netgen::SortedPointIndices<2>> ()\n  //   { return InvalidHash<netgen::PointIndices<2>>(); }\n  { return CHT_trait<netgen::PointIndices<2>>::Invalid(); }    \n  */\n}\n\n\nnamespace std\n{\n  // structured binding support\n  template <auto N>\n  struct tuple_size<netgen::PointIndices<N>> : std::integral_constant<std::size_t, N> {};\n  template<size_t N, auto M> struct tuple_element<N,netgen::PointIndices<M>> { using type = netgen::PointIndex; };\n}\n\nnamespace netgen\n{\n\n  class ElementIndex : public Index<int,ElementIndex,0>\n  {\n  public:\n    using Index::Index; // <int,ElementIndex,0>::Index;\n  };\n  \n  inline istream & operator>> (istream & ist, ElementIndex & ei)\n  {\n    int i; ist >> i; ei = ElementIndex::Base()+i; return ist;\n  }\n\n  inline ostream & operator<< (ostream & ost, const ElementIndex & ei)\n  {\n    return ost << int(ei-ElementIndex::Base());\n  }\n\n\n  /*\n  // these should not be needed soon\n  inline bool operator== (Index<int,ElementIndex,0> ei1, int ei2) { return int(ei1) == int(ei2); };  \n  inline bool operator< (size_t s, Index<int,ElementIndex,0> ei2) { return int(s) < int(ei2); };    \n  inline bool operator< ( Index<int,ElementIndex,0> ei1, size_t s) { return int(ei1) < int(s); };   // should not need\n  inline bool operator< ( Index<int,ElementIndex,0> ei1, int s) { return int(ei1) < int(s); };   // should not need\n  inline bool operator>= (size_t s,  Index<int,ElementIndex,0> ei2) { return int(s) >= int(ei2); };\n  */\n\n  class SurfaceElementIndex : public Index<int,SurfaceElementIndex,0>\n  {\n  public:\n    using Index::Index;\n  };\n\n  \n  // these should not be needed soon\n  /*\n  inline bool operator== (Index<int, SurfaceElementIndex,0> ei1, int ei2) { return int(ei1) == int(ei2); };\n  inline bool operator== (int ei2, Index<int, SurfaceElementIndex,0> ei1) { return int(ei1) == int(ei2); };\n  inline bool operator!= (Index<int, SurfaceElementIndex,0> ei1, int ei2) { return int(ei1) != int(ei2); };    \n  inline bool operator< (size_t s, Index<int, SurfaceElementIndex,0> ei2) { return int(s) < int(ei2); };    \n  inline bool operator< (Index<int, SurfaceElementIndex,0> ei1, size_t s) { return int(ei1) < int(s); };   // should not need\n  inline bool operator< (Index<int, SurfaceElementIndex,0> ei1, int s) { return int(ei1) < int(s); };   // should not need\n  inline bool operator>= (size_t s, Index<int, SurfaceElementIndex,0> ei2) { return int(s) >= int(ei2); };\n  inline bool operator>= (Index<int, SurfaceElementIndex,0> ei1, int s) { return int(ei1) >= int(s); };\n  */\n  \n  // inline void SetInvalid (SurfaceElementIndex & id) { id.Invalidate(); }\n  // inline bool IsInvalid (SurfaceElementIndex & id) { return !id.IsValid(); }\n\n  inline istream & operator>> (istream & ist, SurfaceElementIndex & pi)\n  {\n    int i; ist >> i; pi = i; return ist;\n  }\n\n  inline ostream & operator<< (ostream & ost, const SurfaceElementIndex & si)\n  {\n    return ost << (si-IndexBASE(si));\n  }\n\n\n  class SegmentIndex : public Index<int,SegmentIndex,0>\n  {\n  public:\n    using Index::Index;\n  };\n\n  // these should not be needed soon\n  /*\n  inline bool operator== (Index<int, SegmentIndex,0> ei1, int ei2) { return int(ei1) == int(ei2); };  \n  inline bool operator< (size_t s, Index<int,SegmentIndex,0> ei2) { return int(s) < int(ei2); };\n  inline bool operator< (Index<int, SegmentIndex,0> ei1, size_t s) { return int(ei1) < int(s); };\n  inline bool operator< (Index<int, SegmentIndex,0> ei1, int s) { return int(ei1) < int(s); };   \n  */\n  \n  // inline void SetInvalid (SegmentIndex & id) { id = -1; }\n  // inline bool IsInvalid (SegmentIndex & id) { return id == -1; }\n\n\n  inline istream & operator>> (istream & ist, SegmentIndex & pi)\n  {\n    int i; ist >> i; pi = i; return ist;\n  }\n\n  inline ostream & operator<< (ostream & ost, const SegmentIndex & si)\n  {\n    return ost << (si - IndexBASE(si));\n  } \n\n\n\n\n  /**\n     Point in the mesh.\n     Contains layer (a new feature in 4.3 for overlapping meshes.\n  */\n  class MeshPoint : public Point<3>\n  {\n    double singular; // singular factor for hp-refinement\n    int layer;\n    POINTTYPE type;\n\n\n  public:\n    MeshPoint () \n    { \n      ;\n    }\n\n    MeshPoint (const Point<3> & ap, int alayer = 1, POINTTYPE apt = INNERPOINT)\n      : Point<3> (ap), singular(0.), layer(alayer), type(apt) \n    { \n      ;\n    }\n  \n    void SetPoint (const Point<3> & ap)\n    { \n      Point<3>::operator= (ap); \n      layer = 0; \n      singular = 0; \n    }\n\n    void Scale(double factor) { *testout << \"before: \" << x[0] << endl; x[0] *= factor; x[1] *= factor; x[2] *= factor; *testout << \"after: \" << x[0] << endl;}\n\n    int GetLayer() const { return layer; }\n\n    POINTTYPE Type() const { return type; }\n    void SetType(POINTTYPE at) { type = at; }\n \n    double Singularity() const { return singular; }\n    void Singularity(double s) { singular = s; }\n    bool IsSingular() const { return (singular != 0.0); }\n\n#ifdef PARALLEL\n    static NG_MPI_Datatype MyGetMPIType ( );\n#endif\n\n    void DoArchive (Archive & ar)\n    {\n      // ar & x[0] & x[1] & x[2] & layer & singular;\n      // ar.Do(&x[0], 3);\n      // ar & layer & singular;\n      // ar & (unsigned char&)(type);\n      ar.DoPacked (x[0], x[1], x[2], layer, singular, (unsigned char&)(type));\n    }\n  };\n\n  inline ostream & operator<<(ostream  & s, const MeshPoint & pt)\n  { \n    return (s << Point<3> (pt)); \n  }\n\n\n\n  typedef Array<MeshPoint, PointIndex> T_POINTS;\n\n\n  /**\n     Triangle element for surface mesh generation.\n  */\n  class Element2d\n  { \n    /// point numbers\n    PointIndex pnum[ELEMENT2D_MAXPOINTS];\n    /// geom info of points\n    PointGeomInfo geominfo[ELEMENT2D_MAXPOINTS];\n\n    /// surface nr\n    int index;\n    ///\n    ELEMENT_TYPE typ;\n    /// number of points\n    int8_t np;\n    bool refflag;  // marked for refinement\n    bool badel:1;\n    bool strongrefflag:1;\n    bool deleted:1;  // element is deleted\n\n    // Philippose - 08 August 2010\n    // Set a new property for each element, to \n    // control whether it is visible or not\n    bool visible:1;  // element visible\n    bool is_curved;   // element is (high order) curved\n    int8_t newest_vertex = -1; // from refinement via bisection\n    /// order for hp-FEM\n    unsigned int orderx:6;\n    unsigned int ordery:6;\n\n    /// a linked list for all elements in the same face\n    SurfaceElementIndex next;\n    ///\n    int hp_elnr;\n\n  public:\n    static auto GetDataLayout()\n    {\n      return std::map<string, int>({\n          { \"pnum\", offsetof(Element2d, pnum)},\n          { \"index\", offsetof(Element2d, index) },\n          { \"np\", offsetof(Element2d, np) },\n          { \"refine\", offsetof(Element2d, refflag) },\n          { \"curved\", offsetof(Element2d, is_curved)}\n        });\n    }\n\n    ///\n    DLL_HEADER Element2d ();\n    Element2d (const Element2d &) = default;\n    Element2d (Element2d &&) = default;\n    Element2d & operator= (const Element2d &) = default;\n    Element2d & operator= (Element2d &&) = default;\n    Element2d & operator= (initializer_list<PointIndex> list)\n    {\n      size_t cnt = 0;\n      for (auto val : list)\n        pnum[cnt++] = val;\n      return *this;\n    }\n    Element2d & operator= (initializer_list<std::tuple<PointIndex,PointGeomInfo>> list)\n    {\n      size_t cnt = 0;\n      for (auto val : list)\n        {\n          pnum[cnt] = get<0>(val);\n          geominfo[cnt++] = get<1>(val);\n        }\n      return *this;\n    }\n    ///\n    DLL_HEADER Element2d (int anp);\n    ///\n    DLL_HEADER Element2d (ELEMENT_TYPE type);\n    ///\n    DLL_HEADER Element2d (PointIndex pi1, PointIndex pi2, PointIndex pi3);\n    ///\n    DLL_HEADER Element2d (PointIndex pi1, PointIndex pi2, PointIndex pi3, PointIndex pi4);\n    ///\n    ELEMENT_TYPE GetType () const { return typ; }\n    /// \n    void SetType (ELEMENT_TYPE atyp)\n    {\n      typ = atyp;\n      switch (typ)\n\t{\n\tcase TRIG: np = 3; break;\n\tcase QUAD: np = 4; break;\n\tcase TRIG6: np = 6; break;\n\tcase QUAD6: np = 6; break;\n\tcase QUAD8: np = 8; break;\n\tdefault:\n\t  PrintSysError (\"Element2d::SetType, illegal type \", int(typ));\n\t}\n      is_curved = (np >= 4); \n    }\n    ///\n    int GetNP() const { return np; }\n    ///\n    int GetNV() const\n    {\n      if (typ == TRIG || typ == TRIG6)\n        return 3;\n      else\n        {\n#ifdef DEBUG\n          if (typ != QUAD && typ != QUAD6 && typ != QUAD8)\n            PrintSysError (\"element2d::GetNV not implemented for typ\", int(typ));\n#endif\n          return 4;\n        }\n      /*\n      switch (typ)\n\t{\n\tcase TRIG:\n\tcase TRIG6: return 3;\n          \n\tcase QUAD:\n\tcase QUAD8:\n\tcase QUAD6: return 4;\n\tdefault:\n#ifdef DEBUG\n\t  PrintSysError (\"element2d::GetNV not implemented for typ\", typ)\n#endif\n\t    ;\n\t}\n      return np;\n      */\n    }\n\n    ///\n    PointIndex & operator[] (int i) { return pnum[i]; }\n    ///\n    const PointIndex & operator[] (int i) const { return pnum[i]; }\n\n    auto PNums () const { return FlatArray<const PointIndex> (np, &pnum[0]); }\n    auto PNums ()  { return FlatArray<PointIndex> (np, &pnum[0]); }\n    template <int NP>\n    auto PNums() const { return FlatArray<const PointIndex> (NP, &pnum[0]); }\n    auto Vertices() const { return FlatArray<const PointIndex> (GetNV(), &pnum[0]); }\n\n    auto GeomInfo() const { return FlatArray<const PointGeomInfo> (np, &geominfo[0]); }\n    auto GeomInfo() { return FlatArray<PointGeomInfo> (np, &geominfo[0]); }\n    \n    ///\n    PointIndex & PNum (int i) { return pnum[i-1]; }\n    ///\n    const PointIndex & PNum (int i) const { return pnum[i-1]; }\n    ///\n    PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; }\n    ///\n    const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; }\n    ///\n\n    ///\n    PointGeomInfo & GeomInfoPi (int i) { return geominfo[i-1]; }\n    ///\n    const PointGeomInfo & GeomInfoPi (int i) const { return geominfo[i-1]; }\n    ///\n    PointGeomInfo & GeomInfoPiMod (int i) { return geominfo[(i-1) % np]; }\n    ///\n    const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; }\n\n    auto & NewestVertex() { return newest_vertex; }\n    auto NewestVertex() const { return newest_vertex; }\n\n    void DoArchive (Archive & ar)\n    {\n      short _np, _typ;\n      bool _curved, _vis, _deleted;\n      if (ar.Output())\n        { _np = np; _typ = typ; _curved = is_curved;\n          _vis = visible; _deleted = deleted; }\n      // ar & _np & _typ & index & _curved & _vis & _deleted;\n      ar.DoPacked (_np, _typ, index, _curved, _vis, _deleted);\n      // ar & next; don't need \n      if (ar.Input())\n        { np = _np; typ = ELEMENT_TYPE(_typ); is_curved = _curved;\n          visible = _vis; deleted = _deleted; }\n      /*\n      for (size_t i = 0; i < np; i++)\n        ar & pnum[i];\n      */\n      static_assert(sizeof(int) == sizeof (PointIndex));\n      ar.Do( (int*)&pnum[0], np);\n    }\n\n#ifdef PARALLEL\n    static NG_MPI_Datatype MyGetMPIType();\n#endif\n    \n\n    void SetIndex (int si) { index = si; }\n    ///\n    int GetIndex () const { return index; }\n\n    int GetOrder () const { return orderx; }\n    void SetOrder (int aorder) { orderx = ordery = aorder; }\n\n\n    void GetOrder (int & ox, int & oy) const { ox = orderx, oy =ordery;};\n    void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz=0; }\n    void SetOrder (int ox, int oy, int  /* oz */) { orderx = ox; ordery = oy;}\n    void SetOrder (int ox, int oy) { orderx = ox; ordery = oy;}\n\n    int GetHpElnr() const { return hp_elnr; }\n    void SetHpElnr(int _hp_elnr) { hp_elnr = _hp_elnr; }\n\n    ///\n    void GetBox (const T_POINTS & points, Box3d & box) const;\n    /// invert orientation\n    inline void Invert ();\n    ///\n    DLL_HEADER void Invert2 ();\n    /// first point number is smallest\n    inline void NormalizeNumbering ();\n    ///\n    void NormalizeNumbering2 ();\n\n    bool BadElement() const { return badel; }\n\n    // friend ostream & operator<<(ostream  & s, const Element2d & el);\n    friend class Mesh;\n\n\n    /// get number of 'integration points'\n    int GetNIP () const;\n    void GetIntegrationPoint (int ip, Point<2> & p, double & weight) const;\n\n    void GetTransformation (int ip, const NgArray<Point<2>> & points,\n\t\t\t    class DenseMatrix & trans) const;\n    void GetTransformation (int ip, class DenseMatrix & pmat,\n\t\t\t    class DenseMatrix & trans) const;\n\n    void GetShape (const Point<2> & p, class Vector & shape) const;\n    DLL_HEADER void GetShapeNew (const Point<2> & p, class FlatVector & shape) const;\n    template <typename T>\n    DLL_HEADER void GetShapeNew (const Point<2,T> & p, TFlatVector<T> shape) const;\n    /// matrix 2 * np\n    DLL_HEADER void GetDShape (const Point<2> & p, class DenseMatrix & dshape) const;\n    template <typename T>\n    DLL_HEADER void GetDShapeNew (const Point<2,T> & p, class MatrixFixWidth<2,T> & dshape) const;\n    \n    /// matrix 2 * np\n    void GetPointMatrix (const NgArray<Point<2>> & points,\n\t\t\t class DenseMatrix & pmat) const; \n\n    void ComputeIntegrationPointData () const;\n  \n\n    double CalcJacobianBadness (const NgArray<Point<2>> & points) const;\n    double CalcJacobianBadness (const T_POINTS & points, \n\t\t\t\tconst Vec<3> & n) const;\n    double CalcJacobianBadnessDirDeriv (const NgArray<Point<2>> & points,\n\t\t\t\t\tint pi, Vec<2> & dir, double & dd) const;\n\n\n    \n    void Delete ()\n    {\n      deleted = true;\n      // for (PointIndex & p : pnum) p.Invalidate(); \n    }\n    \n    bool IsDeleted () const \n    {\n#ifdef DEBUG\n      if ((pnum[0]-IndexBASE<PointIndex>() < 0) && !deleted)\n\tcerr << \"Surfelement has illegal pnum, but not marked as deleted\" << endl;\n#endif    \n      return deleted; \n    }\n\n    // Philippose - 08 August 2010\n    // Access functions for the new property: visible\n    void Visible(bool vis = true) \n    { visible = vis; }\n    bool IsVisible () const \n    { return visible; }\n   \n    void SetRefinementFlag (bool rflag = true) \n    { refflag = rflag; }\n    bool TestRefinementFlag () const\n    { return refflag; }\n\n    void SetStrongRefinementFlag (bool rflag = true) \n    { strongrefflag = rflag; }\n    bool TestStrongRefinementFlag () const\n    { return strongrefflag; }\n\n\n    bool IsCurved () const { return is_curved; }\n    void SetCurved (bool acurved) { is_curved = acurved; }\n  \n    SurfaceElementIndex NextElement() { return next; }\n\n    bool operator==(const Element2d & el2) const;\n\n    int HasFace(const Element2d& el) const;\n  };\n\n  DLL_HEADER ostream & operator<<(ostream  & s, const Element2d & el);\n\n\n\n\n\n  class IntegrationPointData\n  {\n  public:\n    Point<3> p;\n    double weight;\n    Vector shape;\n    DenseMatrix dshape;\n  };\n\n\n\n\n\n\n\n\n  /**\n     Volume element\n  */\n  class Element\n  {\n  private:\n    /// point numbers\n    PointIndex pnum[ELEMENT_MAXPOINTS];\n    ///\n    ELEMENT_TYPE typ;\n    /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism)\n    int8_t np;\n    int8_t newest_vertex = -1; // from refinement via bisection\n    \n    /// sub-domain index\n    int index;\n    /// order for hp-FEM\n    unsigned int orderx:6;\n    unsigned int ordery:6;\n    unsigned int orderz:6;\n    /* unsigned int levelx:6;\n       unsigned int levely:6;\n       unsigned int levelz:6; */ \n    /// stored shape-badness of element\n    float badness;\n    bool is_curved;   // element is (high order) curved\n\n    class flagstruct {\n    public:\n      bool refflag;     // mark element for refinement\n      bool marked:1;  // marked for refinement\n      bool badel:1;   // angles worse then limit\n      bool reverse:1; // for refinement a la Bey\n      bool illegal:1; // illegal, will be split or swapped\n      bool illegal_valid:1; // is illegal-flag valid ?\n      bool badness_valid:1; // is badness valid ?\n      bool strongrefflag:1;\n      bool deleted:1;   // element is deleted, will be removed from array\n      bool fixed:1;     // don't change element in optimization\n    };\n\n    flagstruct flags;\n    int hp_elnr;\n  public:\n\n    static auto GetDataLayout()\n    {\n      return std::map<string, int>({\n          { \"pnum\", offsetof(Element, pnum)},\n          { \"index\", offsetof(Element, index) },\n          { \"np\", offsetof(Element, np) },\n          { \"refine\", offsetof(Element, flags.refflag) },\n          { \"curved\", offsetof(Element, is_curved)}\n        });\n    }\n\n    ///\n    DLL_HEADER Element () = default;\n    Element (const Element &) = default;\n    Element (Element &&) = default;\n    Element & operator= (const Element &) = default;\n    Element & operator= (Element &&) = default;\n\n    ///\n    DLL_HEADER Element (int anp);\n    ///\n    DLL_HEADER Element (ELEMENT_TYPE type);\n    ///\n    // Element & operator= (const Element & el2);\n\n    const flagstruct& Flags() const { return flags; }\n    flagstruct& Flags() { return flags; }\n  \n    ///\n    DLL_HEADER void SetNP (int anp);\n    ///\n    DLL_HEADER void SetType (ELEMENT_TYPE atyp);\n    ///\n    int GetNP () const { return np; }\n    ///\n    uint8_t GetNV() const\n    {\n      // __assume(typ >= TET && typ <= PYRAMID13);\n      switch (typ)\n\t{\n        case TET: \n        case TET10: \n          return 4;\n        case PRISM12:\n        case PRISM15:\n        case PRISM:\n\t  return 6; \n\tcase PYRAMID:\n        case PYRAMID13:\n\t  return 5;\n\tcase HEX7:\n\t  return 7;\n\tcase HEX:\n\tcase HEX20:\n\t  return 8;\n        default: // not a 3D element\n#ifdef DEBUG\n          PrintSysError (\"Element3d::GetNV not implemented for typ \", int(typ));\n#endif\n          __assume(false);\n          return -1;\n        }\n    }\n\n    DLL_HEADER bool operator==(const Element & el2) const;\n\n    // old style:\n    int NP () const { return np; }\n\n    ///\n    ELEMENT_TYPE GetType () const { return typ; }\n\n    ///\n    PointIndex & operator[] (int i) { return pnum[i]; }\n    ///\n    const PointIndex & operator[] (int i) const { return pnum[i]; }\n\n    auto PNums () const { return FlatArray<const PointIndex> (np, &pnum[0]); }\n    auto PNums () { return FlatArray<PointIndex> (np, &pnum[0]); }    \n    template <int NP>\n    auto PNums() const { return FlatArray<const PointIndex> (NP, &pnum[0]); }\n\n    FlatArray<const PointIndex> Vertices() const { return { GetNV(), &pnum[0] }; }\n\n    ///\n    PointIndex & PNum (int i) { return pnum[i-1]; }\n    ///\n    const PointIndex & PNum (int i) const { return pnum[i-1]; }\n    ///\n    PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; }\n    ///\n    const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; }\n\n    auto & NewestVertex() { return newest_vertex; }\n    auto NewestVertex() const { return newest_vertex; }\n\n    void DoArchive (Archive & ar)\n    {\n      short _np, _typ;\n      bool _curved;\n      if (ar.Output())\n        { _np = np; _typ = typ; _curved = is_curved; }\n      // ar & _np & _typ & index & _curved;\n      ar.DoPacked (_np, _typ, index, _curved);                \n\n      if (ar.Input())\n        {\n          np = _np;\n          typ = ELEMENT_TYPE(_typ);\n          is_curved = _curved;\n          flags.marked = 1;\n          flags.badel = 0;\n          flags.reverse = 0;\n          flags.illegal = 0;\n          flags.illegal_valid = 0;\n          flags.badness_valid = 0;\n          flags.refflag = 1;\n          flags.strongrefflag = false;\n          flags.deleted = 0;\n          flags.fixed = 0;\n        }\n\n      static_assert(sizeof(int) == sizeof (PointIndex));\n      ar.Do( (int*)&pnum[0], np);\n    }\n    \n#ifdef PARALLEL\n    static NG_MPI_Datatype MyGetMPIType();\n#endif\n\n    ///\n    void SetIndex (int si) { index = si; }\n    ///\n    int GetIndex () const { return index; }\n\n    int GetOrder () const { return orderx; }\n    void SetOrder (const int aorder) ; \n\n    void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz = orderz; }\n    void SetOrder (const int ox, const int oy, const int oz);\n    // void GetLevel (int & ox, int & oy, int & oz) const { ox = levelx; oy = levely; oz = levelz; }\n    // void SetLevel (int ox, int oy, int oz) { levelx = ox; levely = oy; levelz = oz; }\n\n\n    ///\n    void GetBox (const T_POINTS & points, Box3d & box) const;\n    /// Calculates Volume of element\n    double Volume (const T_POINTS & points) const;\n    ///\n    DLL_HEADER void Print (ostream & ost) const;\n    ///\n    int GetNFaces () const\n    {\n      switch (typ)\n\t{\n\tcase TET: \n\tcase TET10: return 4;\n\tcase PYRAMID: case PYRAMID13: return 5;\n\tcase PRISM:\n        case PRISM15:\n\tcase PRISM12: return 5;\n        case HEX7: return 6;\n        case HEX: case HEX20:\n          return 6;\n\tdefault:\n#ifdef DEBUG\n\t  PrintSysError (\"element3d::GetNFaces not implemented for typ\", int(typ))\n#endif\n\t    ;\n\t}\n      return 0;\n    }\n    ///\n    inline void GetFace (int i, Element2d & face) const;\n    ///\n    DLL_HEADER void GetFace2 (int i, Element2d & face) const;\n    ///\n    DLL_HEADER void Invert ();\n\n    int GetHpElnr() const { return hp_elnr; }\n    void SetHpElnr(int _hp_elnr) { hp_elnr = _hp_elnr; }\n\n    /// split into 4 node tets\n    void GetTets (NgArray<Element> & locels) const;\n    /// split into 4 node tets, local point nrs\n    void GetTetsLocal (NgArray<Element> & locels) const;\n    /// returns coordinates of nodes\n    // void GetNodesLocal (NgArray<Point<3> > & points) const;\n    void GetNodesLocalNew (NgArray<Point<3> > & points) const;\n\n    /// split surface into 3 node trigs\n    DLL_HEADER void GetSurfaceTriangles (NgArray<Element2d> & surftrigs) const;\n\n\n    /// get number of 'integration points'\n    int GetNIP () const;\n    void GetIntegrationPoint (int ip, Point<3> & p, double & weight) const;\n\n    void GetTransformation (int ip, const T_POINTS & points,\n\t\t\t    class DenseMatrix & trans) const;\n    void GetTransformation (int ip, class DenseMatrix & pmat,\n\t\t\t    class DenseMatrix & trans) const;\n\n    void GetShape (const Point<3> & p, class Vector & shape) const;\n    // void GetShapeNew (const Point<3> & p, class FlatVector & shape) const;\n    template <typename T>\n    DLL_HEADER void GetShapeNew (const Point<3,T> & p, TFlatVector<T> shape) const;\n    /// matrix 2 * np\n    void GetDShape (const Point<3> & p, class DenseMatrix & dshape) const;\n    template <typename T>\n    void GetDShapeNew (const Point<3,T> & p, class MatrixFixWidth<3,T> & dshape) const;\n    /// matrix 3 * np\n    void GetPointMatrix (const T_POINTS & points,\n\t\t\t class DenseMatrix & pmat) const; \n\n    void ComputeIntegrationPointData () const;\n  \n\n    double CalcJacobianBadness (const T_POINTS & points) const;\n    double CalcJacobianBadnessDirDeriv (const T_POINTS & points,\n\t\t\t\t\tint pi, Vec<3> & dir, double & dd) const;\n    double CalcJacobianBadnessGradient (const T_POINTS & points,\n\t\t\t\t\tint pi, Vec<3> & grad) const;\n\n    ///\n    // friend ostream & operator<<(ostream  & s, const Element & el);\n\n    void SetRefinementFlag (bool rflag = 1) \n    { flags.refflag = rflag; }\n    int TestRefinementFlag () const\n    { return flags.refflag; }\n\n    void SetStrongRefinementFlag (bool rflag = 1) \n    { flags.strongrefflag = rflag; }\n    int TestStrongRefinementFlag () const\n    { return flags.strongrefflag; }\n\n    int Illegal () const\n    {\n      NETGEN_CHECK_SAME(flags.illegal_valid, true);\n      return flags.illegal;\n    }\n    int IllegalValid () const\n    { return flags.illegal_valid; }\n    void SetIllegal (int aillegal)\n    {\n      flags.illegal = aillegal ? 1 : 0;\n      flags.illegal_valid = 1;\n    }\n    void SetLegal (int alegal)\n    {\n      flags.illegal = alegal ? 0 : 1;\n      flags.illegal_valid = 1;\n    }\n\n    bool BadnessValid()\n    { return flags.badness_valid; }\n\n    float GetBadness()\n    {\n      NETGEN_CHECK_SAME(flags.badness_valid, true);\n      return badness;\n    }\n\n    void SetBadness(float value)\n    {\n      badness = value;\n      flags.badness_valid = 1;\n    }\n\n    void Touch() {\n      flags.illegal_valid = 0;\n      flags.badness_valid = 0;\n    }\n  \n    void Delete () { flags.deleted = 1; }\n    bool IsDeleted () const \n    { \n#ifdef DEBUG\n      if (pnum[0]-IndexBASE<PointIndex>() < 0 && !flags.deleted)\n\tcerr << \"Volelement has illegal pnum, but not marked as deleted\" << endl;\n#endif    \n\n      return flags.deleted; \n    }\n\n    bool IsCurved () const { return is_curved; }\n    void SetCurved (bool acurved) { is_curved = acurved; }\n\n  };\n\n  ostream & operator<<(ostream  & s, const Element & el);\n\n\n\n\n\n\n  /**\n     Edge segment.\n\n     How indices are used up to 2026-03-29\n\n     edgenr:\n     OCC: the geometry edge, 1-based\n     Spline2D:  edge-nr, 1-based\n     CSG:  edge counter \n     \n     si:\n     CSG: one surface of the edge\n     Spline2d: bc-number\n     OCC: edgenr, 1-based\n     \n     cd2i:\n     ????\n     \n     epgeominfo:\n     OCC: geometry  edgenr, 0-based\n     Spline2D: edgenr, 1-based\n     \n\n     NGSoleve Interface:\n     GetIndex\n     mesh.dim == 3 ->  edgenr\n     mesh.dim == 2 ->  si\n\n     \n     Python interface:\n     edgenr -> segmnr\n     index -> si\n     \n     Python ctor:\n     index -> si, segmnr\n     edgenr -> epgeominfo DECREMENT 1\n\n\n\n     NEW from 2026-03-29\n     GetEdgeNr()  -> the geometry edge\n     GetIndex()  -> the index for boundary conditions\n  */\n  \n  class Segment\n  {\n  public:\n    ///\n    DLL_HEADER Segment();\n    Segment (const Segment& other) = default;\n\n    // friend ostream & operator<<(ostream  & s, const Segment & seg);\n\n    PointIndex pnums[3];  // p1, p2, pmid\n\n    int edgenr;\n    ///\n    double singedge_left;\n    double singedge_right;\n\n    /// 0.. not first segment of segs, 1..first of class, 2..first of class, inverse\n    unsigned int seginfo:2;\n\n    /// surface decoding index\n    int si;\n    /// co dim 2 decoding index\n    // int cd2i\n    /// index for boundary conditions (1-based)\n    int index; \n    \n    /// domain number inner side\n    int domin;\n    /// domain number outer side\n    int domout;  \n    /// top-level object number of surface\n    int tlosurf;\n    ///\n    PointGeomInfo geominfo[2];\n\n    /// surfaces describing edge\n    int surfnr1, surfnr2;\n    ///\n    EdgePointGeomInfo epgeominfo[2];\n    ///\n    // int pmid; // for second order\n    ///\n    int meshdocval;\n\n    bool is_curved;\n    int hp_elnr;\n    /*\n      PointIndex operator[] (int i) const\n      { return (i == 0) ? p1 : p2; }\n\n      PointIndex & operator[] (int i) \n      { return (i == 0) ? p1 : p2; }\n    */\n\n    Segment& operator=(const Segment & other) = default;\n\n  \n\n    int GetNP() const\n    {\n      return pnums[2].IsValid() ? 3 : 2;\n    }\n\n    auto PNums() const { return FlatArray<const PointIndex> (GetNP(), &pnums[0]); }\n    auto PNums() { return FlatArray<PointIndex> (GetNP(), &pnums[0]); }\n    \n    auto Vertices() const { return FlatArray<const PointIndex> (2, &pnums[0]); }\n    \n    ELEMENT_TYPE GetType() const\n    {\n      return pnums[2].IsValid() ? SEGMENT3 : SEGMENT;\n    }\n  \n    PointIndex & operator[] (int i) { return pnums[i]; }\n    const PointIndex & operator[] (int i) const { return pnums[i]; }\n\n\n    bool IsCurved () const { return is_curved; }\n    void SetCurved (bool acurved) { is_curved = acurved; }\n\n\n    int GetEdgeNr() const { return epgeominfo[0].edgenr; }  // 0 or 1-based (geometry dependent)\n    void SetEdgeNr (int nr) { epgeominfo[0].edgenr=nr; }   \n\n    int GetIndex() const { return index; }   // 1-based\n    void SetIndex (int i) { index=i; }   // 1-based\n    \n    void DoArchive (Archive & ar);\n#ifdef PARALLEL\n    static NG_MPI_Datatype MyGetMPIType();\n#endif\n    \n  };\n\n  ostream & operator<<(ostream  & s, const Segment & seg);\n\n\n  class Element0d\n  {\n  public:\n    PointIndex pnum;\n    string name;\n    int index;\n    Element0d () = default;\n    Element0d (PointIndex _pnum, int _index)\n      : pnum(_pnum), index(_index) { ; }\n\n#ifdef PARALLEL\n    static NG_MPI_Datatype MyGetMPIType();\n#endif\n    \n    void DoArchive (Archive & ar);\n  };\n\n  ostream & operator<<(ostream  & s, const Element0d & el);\n\n  // class Surface;  \n  // class FaceDescriptor;\n\n  ///\n  class FaceDescriptor\n  {\n    /// which surface, 0 if not available\n    int surfnr;\n    /// domain nr inside\n    int domin;\n    /// domain nr outside\n    int domout;\n    /// top level object number of surface\n    int tlosurf;\n    /// boundary condition property\n    int bcprop;\n    // Philippose - 06/07/2009\n    // Add capability to store surface colours along with \n    // other face data\n    /// surface colour (Default: R=0.0 ; G=1.0 ; B=0.0)\n    Vec<4> surfcolour;\n    \n    ///\n    // static string default_bcname;\n    // string * bcname = &default_bcname;\n    string bcname = \"default\";\n    /// root of linked list \n    SurfaceElementIndex firstelement;\n  \n    double domin_singular;\n    double domout_singular;\n\n  public:\n    DLL_HEADER FaceDescriptor();\n    DLL_HEADER FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi);\n    DLL_HEADER FaceDescriptor(const Segment & seg);\n    DLL_HEADER FaceDescriptor(const FaceDescriptor& other);\n    DLL_HEADER ~FaceDescriptor()  { ; }\n\n    DLL_HEADER int SegmentFits (const Segment & seg);\n\n    int SurfNr () const { return surfnr; }\n    int DomainIn () const { return domin; }\n    int DomainOut () const { return domout; }\n    int TLOSurface () const { return tlosurf; }\n    int BCProperty () const { return bcprop; }\n\n\n    double DomainInSingular() const { return domin_singular; }\n    double DomainOutSingular() const { return domout_singular; }\n\n    // Philippose - 06/07/2009\n    // Get Surface colour\n    Vec<4> SurfColour () const { return surfcolour; }\n    /* DLL_HEADER */ const string & GetBCName () const { return bcname; }\n    // string * BCNamePtr () { return bcname; }\n    // const string * BCNamePtr () const  { return bcname; }\n    void SetSurfNr (int sn) { surfnr = sn; }\n    void SetDomainIn (int di) { domin = di; }\n    void SetDomainOut (int dom) { domout = dom; }\n    void SetBCProperty (int bc) { bcprop = bc; }\n    DLL_HEADER void SetBCName (string * bcn); //  { bcname = bcn; }\n    void SetBCName (const string & bcn) { bcname = bcn; }    \n    // Philippose - 06/07/2009\n    // Set the surface colour\n    void SetSurfColour (Vec<4> colour) { surfcolour = colour; }\n\n    void SetDomainInSingular (double v) { domin_singular = v; }\n    void SetDomainOutSingular (double v) { domout_singular = v; }\n\n    SurfaceElementIndex FirstElement() { return firstelement; }\n    // friend ostream & operator<<(ostream  & s, const FaceDescriptor & fd);\n    friend class Mesh;\n\n    void DoArchive (Archive & ar);\n  };\n\n  ostream & operator<< (ostream  & s, const FaceDescriptor & fd);\n\n  \n \n  class EdgeDescriptor\n  {\n    int tlosurf;\n    int surfnr[2];\n  public:\n    EdgeDescriptor ()\n      : tlosurf(-1)\n    { surfnr[0] = surfnr[1] = -1; }\n\n    int SurfNr (int i) const { return surfnr[i]; }\n    void SetSurfNr (int i, int nr) { surfnr[i] = nr; }\n\n    int TLOSurface() const { return tlosurf; }\n    void SetTLOSurface (int nr) { tlosurf = nr; }\n  };\n\n\n  struct BoundaryLayerParameters\n  {\n    std::variant<double, std::vector<double>> thickness;\n    std::variant<string, int, std::vector<int>> domain;\n    std::variant<string, int, std::vector<int>> boundary = \".*\";\n    std::optional<std::variant<string, std::map<string, string>>> new_material = nullopt;\n    std::optional<std::variant<string, std::vector<int>>> project_boundaries = nullopt;\n    bool outside = false;\n    bool grow_edges = true;\n    bool limit_growth_vectors = false; // automatic reduction of layer thickness to avoid intersections\n    std::optional<bool> sides_keep_surfaceindex = nullopt; // !outside by default\n    bool disable_curving = true; // disable curving affected boundaries/edges (could lead to self-intersecting volume elements)\n  };\n\n\n  ostream & operator<< (ostream & ost, const BoundaryLayerParameters & mp);\n\n  class DLL_HEADER MeshingParameters\n  {\n  public:\n    /**\n       3d optimization strategy:\n       // m .. move nodes\n       // M .. move nodes, cheap functional\n       // s .. swap faces\n       // c .. combine elements\n       // d .. divide elements\n       // D .. divide and join opposite edges, remove element\n       // p .. plot, no pause\n       // P .. plot, Pause\n       // h .. Histogramm, no pause\n       // H .. Histogramm, pause\n       */\n    string optimize3d = \"cmdDmustm\";\n    /// number of 3d optimization steps\n    int optsteps3d = 3;\n    /**\n       2d optimization strategy:\n       // s .. swap, opt 6 lines/node\n       // S .. swap, optimal elements\n       // m .. move nodes\n       // p .. plot, no pause\n       // P .. plot, pause\n       // c .. combine\n       **/\n    string optimize2d = \"smcmSmcmSmcm\";\n    /// number of 2d optimization steps\n    int optsteps2d = 3;\n    /// power of error (to approximate max err optimization)\n    double opterrpow = 2;\n    /// do block filling ?  \n    bool blockfill = true;\n    /// block filling up to distance\n    double filldist = 0.1;\n    /// radius of local environment (times h)\n    double safety = 5;\n    /// radius of active environment (times h)\n    double relinnersafety = 3;\n    /// use local h ?\n    bool uselocalh = true;\n    /// grading for local h\n    double grading = 0.3;\n    /// use delaunay for 3d meshing\n    bool delaunay = true;\n    /// use delaunay for 2d meshing\n    bool delaunay2d = false;\n    /// maximal mesh size\n    double maxh = 1e10;\n    /// minimal mesh size\n    double minh = 0.0;\n    /// file for meshsize\n    string meshsizefilename = \"\";\n    /// restrict h based on close edges\n    optional<double> closeedgefac = nullopt;\n    /// start surfacemeshing from everywhere in surface\n    bool startinsurface = false;\n    /// check overlapping surfaces (debug)\n    bool checkoverlap = true;\n    /// check overlapping surface mesh before volume meshing\n    bool checkoverlappingboundary = true;\n    /// check chart boundary (sometimes too restrictive)\n    bool checkchartboundary = true;\n    /// safety factor for curvatures (elements per radius)\n    double curvaturesafety = 2;\n    /// minimal number of segments per edge\n    double segmentsperedge = 1;\n    /// use parallel threads\n    bool parthread = 0;\n    /// weight of element size w.r.t element shape\n    double elsizeweight = 0.2;\n    /// init with default values\n\n    /// start at step\n    int perfstepsstart = 0;\n    /// end at step\n    int perfstepsend = 6;\n\n\n    /// from mp3:\n    /// give up quality class, 2d meshing\n    int giveuptol2d = 200;\n    /// give up quality class, 3d meshing\n    int giveuptol = 10;\n    /// give up quality class for closing open quads, > 100 for\n    /// free pyramids\n    int giveuptolopenquads = 15;\n    /// maximal outer steps\n    int maxoutersteps = 10;\n    /// class starting star-shape filling\n    int starshapeclass = 5;\n    /// if non-zero, baseelement must have baseelnp points\n    int baseelnp = 0;        \n    /// quality tolerances are handled less careful\n    int sloppy = 1;\n  \n    /// limit for max element angle (150-180)\n    double badellimit = 175;\n\n    bool check_impossible = false;\n\n    int only3D_domain_nr = 0;\n  \n    ///\n    bool secondorder = false;\n    /// high order element curvature\n    int elementorder = 1;\n    /// quad-dominated surface meshing\n    bool quad = false;\n    ///\n    bool try_hexes = false;\n    ///\n    bool inverttets = false;\n    ///\n    bool inverttrigs = false;\n    ///\n    bool autozrefine = false;\n\n    bool parallel_meshing = true;\n    int nthreads = 4;\n\n    Flags geometrySpecificParameters;\n\n    Array<BoundaryLayerParameters> boundary_layers;\n    ///\n    MeshingParameters ();\n    ///\n    MeshingParameters (const MeshingParameters & mp2) = default;\n    MeshingParameters (MeshingParameters && mp2) = default;\n    MeshingParameters & operator= (const MeshingParameters & mp2) = default;\n    MeshingParameters & operator= (MeshingParameters && mp2) = default;\n    ///\n    void Print (ostream & ost) const;\n    /// \n    // void CopyFrom(const MeshingParameters & other);\n\n    class MeshSizePoint\n    {\n    public:\n      Point<3> pnt;\n      double h;\n      int layer = 1;\n      MeshSizePoint (Point<3> pnt_, double h_, int layer_ = 1) : pnt(pnt_), h(h_), layer(layer_) { ; }\n      MeshSizePoint () = default;\n      MeshSizePoint (const MeshSizePoint &) = default;\n      MeshSizePoint (MeshSizePoint &&) = default;\n      MeshSizePoint & operator= (const MeshSizePoint &) = default;\n      MeshSizePoint & operator= (MeshSizePoint &&) = default;      \n    };\n    NgArray<MeshSizePoint> meshsize_points;\n    \n    void (*render_function)(bool) = NULL;\n    void Render(bool blocking = false) const\n    {\n      if (render_function) \n        (*render_function)(blocking);\n    }\n  };\n\n  inline ostream & operator<< (ostream & ost, const MeshingParameters & mp)\n  {\n    mp.Print (ost);\n    return ost;\n  }\n\n  class DebugParameters \n  {\n  public:\n    ///\n    int debugoutput;\n    /// use slow checks\n    int slowchecks;\n    ///\n    int haltsuccess;\n    ///\n    int haltnosuccess;\n    ///\n    int haltlargequalclass;\n    ///\n    int haltsegment;\n    ///\n    int haltnode;\n    ///\n    PointIndex haltsegmentp1;\n    ///\n    PointIndex haltsegmentp2;\n    ///\n    int haltexistingline;\n    ///\n    int haltoverlap;\n    ///\n    int haltface;\n    ///\n    int haltfacenr;\n    ///\n    bool write_mesh_on_error;\n    ///\n    DebugParameters ();\n  };\n\n\n\n\n  inline void Element2d :: Invert()\n  {\n    if (typ == TRIG)\n      Swap (PNum(2), PNum(3));\n    else\n      Invert2();\n  }\n\n\n\n\n  inline void Element2d :: NormalizeNumbering ()\n  {\n    if (GetNP() == 3)\n      {\n\tif (PNum(1) < PNum(2) && PNum(1) < PNum(3))\n\t  return;\n\telse\n\t  {\n\t    if (PNum(2) < PNum(3))\n\t      {\n\t\tPointIndex pi1 = PNum(2);\n\t\tPNum(2) = PNum(3);\n\t\tPNum(3) = PNum(1);\n\t\tPNum(1) = pi1;\n\t      }\n\t    else\n\t      {\n\t\tPointIndex pi1 = PNum(3);\n\t\tPNum(3) = PNum(2);\n\t\tPNum(2) = PNum(1);\n\t\tPNum(1) = pi1;\n\t      }\n\t  }\n      }\n    else\n      NormalizeNumbering2();\n  }\n\n\n\n  static const int gftetfacesa[4][3] = \n    { { 1, 2, 3 },\n      { 2, 0, 3 },\n      { 0, 1, 3 },\n      { 1, 0, 2 } };\n\n  inline void Element :: GetFace (int i, Element2d & face) const\n  {\n    if (typ == TET)\n      {\n\tface.SetType(TRIG);\n\tface[0] = pnum[gftetfacesa[i-1][0]];\n\tface[1] = pnum[gftetfacesa[i-1][1]];\n\tface[2] = pnum[gftetfacesa[i-1][2]];\n      }\n    else\n      GetFace2 (i, face);\n  }\n\n\n\n  // typedef NgArray<PointIndex,PointIndex::BASE> idmap_type;\n  typedef Array<PointIndex,PointIndex> idmap_type;\n  \n\n\n  /**\n     Identification of periodic surfaces, close surfaces, etc. \n  */\n  class Identifications\n  {\n  public:\n    enum ID_TYPE : unsigned char { UNDEFINED = 1, PERIODIC = 2, CLOSESURFACES = 3, CLOSEEDGES = 4};\n  \n\n  private:\n    class Mesh & mesh;\n\n    /// identify points (thin layers, periodic b.c.)  \n    // INDEX_2_HASHTABLE<int> identifiedpoints;\n    ClosedHashTable<PointIndices<2>, int> identifiedpoints;\n  \n    /// the same, with info about the id-nr\n    // INDEX_3_HASHTABLE<int> identifiedpoints_nr;\n    ClosedHashTable<std::tuple<PointIndices<2>, int>, int> identifiedpoints_nr;\n\n    /// sorted by identification nr\n    TABLE<PointIndices<2>> idpoints_table;\n\n    NgArray<ID_TYPE> type;\n\n    /// number of identifications (or, actually used identifications ?)\n    int maxidentnr;\n    Array<string> names;\n\n  public:\n    ///\n    DLL_HEADER Identifications (class Mesh & amesh);\n    ///\n    DLL_HEADER ~Identifications ();\n\n    DLL_HEADER void Delete ();\n\n    // Removes identifications if one point is an INNERPOINT\n    DLL_HEADER void DeleteInnerPointIdentifications ();\n\n    /*\n      Identify points pi1 and pi2, due to\n      identification nr identnr\n    */\n    DLL_HEADER void Add (PointIndex pi1, PointIndex pi2, int identnr);\n    void Add (PointIndex pi1, PointIndex pi2, string name, ID_TYPE type)\n    {\n        auto nr = GetNr(name);\n        Add(pi1, pi2, nr);\n        SetType(nr, type);\n    }\n\n    int Get (PointIndex pi1, PointIndex pi2) const;\n    int GetSymmetric (PointIndex pi1, PointIndex pi2) const;\n\n    bool Get (PointIndex pi1, PointIndex pi2, int identnr) const;\n    bool GetSymmetric (PointIndex pi1, PointIndex pi2, int identnr) const;\n\n    // bool HasIdentifiedPoints() const { return identifiedpoints != nullptr; } \n    ///\n    auto & GetIdentifiedPoints ()\n    { \n      return identifiedpoints_nr;\n    }\n\n    bool Used (PointIndex pi1, PointIndex pi2)\n    {\n      // return identifiedpoints.Used (INDEX_2 (pi1, pi2));\n      return identifiedpoints.Used (PointIndices<2>(pi1, pi2));\n    }\n\n    bool UsedSymmetric (PointIndex pi1, PointIndex pi2)\n    {\n      return \n\tidentifiedpoints.Used (PointIndices<2>(pi1, pi2)) ||\n\tidentifiedpoints.Used (PointIndices<2>(pi2, pi1));\n    }\n\n    ///\n    void GetMap (int identnr, idmap_type & identmap, bool symmetric = false) const;\n    ///\n    ID_TYPE GetType(int identnr) const\n    {\n      if(identnr <= type.Size())\n\treturn type[identnr-1];\n      else\n\treturn UNDEFINED;\n    }\n    void SetType(int identnr, ID_TYPE t)\n    {\n      while(type.Size() < identnr)\n\ttype.Append(UNDEFINED);\n      type[identnr-1] = t;\n    }\n    \n    ///\n    DLL_HEADER void GetPairs (int identnr, NgArray<INDEX_2> & identpairs) const;\n    DLL_HEADER Array<INDEX_3> GetPairs () const;\n    ///\n    int GetMaxNr () const { return maxidentnr; }  \n\n    int GetNr(string name)\n    {\n      if(!names.Contains(name))\n         names.Append(name);\n      return names.Pos(name)+1;\n    }\n    string GetName(int nr) const\n    {\n      if (nr <= names.Size())\n        return names[nr - 1];\n      else\n        return \"\";\n    }\n    void SetName(int nr, string name)\n    {\n      while(names.Size() < nr)\n        names.Append(\"\");\n      names[nr-1] = name;\n    }\n\n    /// remove secondorder\n    void SetMaxPointNr (int maxpnum);\n\n    void MapPoints(FlatArray<PointIndex, PointIndex> op2np);\n\n    DLL_HEADER void Print (ostream & ost) const;\n\n    void DoArchive (Archive & ar);\n  };\n}\n\n\n#ifdef PARALLEL\nnamespace ngcore\n{\n  template <> struct MPI_typetrait<netgen::PointIndex> {\n    static NG_MPI_Datatype MPIType ()  { return NG_MPI_INT; }\n  };\n\n  template <> struct MPI_typetrait<netgen::ELEMENT_TYPE> {\n    static NG_MPI_Datatype MPIType ()  { return NG_MPI_CHAR; }\n  };\n\n  template <> struct MPI_typetrait<netgen::MeshPoint> {\n    static NG_MPI_Datatype MPIType ()  { return netgen::MeshPoint::MyGetMPIType(); }\n  };\n\n  template <> struct MPI_typetrait<netgen::Element> {\n    static NG_MPI_Datatype MPIType ()  { return netgen::Element::MyGetMPIType(); }\n  };\n  template <> struct MPI_typetrait<netgen::Element2d> {\n    static NG_MPI_Datatype MPIType ()  { return netgen::Element2d::MyGetMPIType(); }\n  };\n  template <> struct MPI_typetrait<netgen::Segment> {\n    static NG_MPI_Datatype MPIType ()  { return netgen::Segment::MyGetMPIType(); }\n  };\n  template <> struct MPI_typetrait<netgen::Element0d> {\n    static NG_MPI_Datatype MPIType ()  { return netgen::Element0d::MyGetMPIType(); }\n  };\n\n}\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/msghandler.cpp",
    "content": "//File for handling warnings, errors, messages\n#include <meshing.hpp>\n\nnamespace netgen\n{\n  // int printmessage_importance = 3;\nint printwarnings = 1;\nint printerrors = 1;\nint printdots = 1;\nint printfnstart = 0;\n\n// extern void Ng_PrintDest(const MyStr& s);\nextern void Ng_PrintDest(const char * s);\n\n//the dots for progression of program\nvoid PrintDot(char ch)\n{\n  // if (printdots)\n  if (printmessage_importance >= 4)\n    {\n      char st[2];\n      st[0] = ch;\n      st[1] = 0;\n      Ng_PrintDest(st);\n    }\n}\n\nvoid PrintMessage(int importance, \n\t\t  const MyStr& s1, const MyStr& s2)\n{\n  if (importance <= printmessage_importance)\n    {\n      Ng_PrintDest(MyStr(\" \")+s1+s2+MyStr(\"\\n\"));\n    }\n}\n\nvoid PrintMessage(int importance, \n\t\t  const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4)\n{\n  if (importance <= printmessage_importance)\n    {\n      Ng_PrintDest(MyStr(\" \")+s1+s2+s3+s4+MyStr(\"\\n\"));\n    }\n}\n\nvoid PrintMessage(int importance, \n\t\t  const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t  const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (importance <= printmessage_importance)\n    {\n      Ng_PrintDest(MyStr(\" \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n    }\n}\n\nvoid PrintMessageCR(int importance, \n\t\t    const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t    const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (importance <= printmessage_importance)\n    {\n      Ng_PrintDest(MyStr(\" \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\r\"));\n    }\n}\n\nvoid PrintFnStart(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t  const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printfnstart)\n    Ng_PrintDest(MyStr(\" Start Function: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintWarning(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t  const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printwarnings)\n    Ng_PrintDest(MyStr(\" WARNING: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\tconst MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printerrors)\n    Ng_PrintDest(MyStr(\" ERROR: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintFileError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t    const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printerrors)\n    Ng_PrintDest(MyStr(\" FILE ERROR: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintUserError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\tconst MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  Ng_PrintDest(MyStr(\" USER ERROR: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintSysError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\tconst MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printerrors)\n    Ng_PrintDest(MyStr(\" SYSTEM ERROR: \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\nvoid PrintTime(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t       const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8)\n{\n  if (printmessage_importance >= 3)\n    Ng_PrintDest(MyStr(\" Time = \")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr(\"\\n\"));\n}\n\n\n/*\n#ifdef SMALLLIB\n#define SMALLLIBORNOTCL\n#endif\n#ifdef NOTCL\n#define SMALLLIBORNOTCL\n#endif\n\n#ifdef SMALLLIBORNOTCL\nvoid Ng_PrintDest(const char * s){cout << s <<flush;}\ndouble GetTime(){return 0;}\nvoid MyError(const char * ch)\n{\n  cerr << ch << endl;\n}\n#endif\n*/\n\n\n}\n"
  },
  {
    "path": "libsrc/meshing/msghandler.hpp",
    "content": "#ifndef FILE_MSGHANDLER\n#define FILE_MSGHANDLER\n\n/**************************************************************************/\n/* File:   msghandler.hh                                                  */\n/* Author: Johannes Gerstmayr                                             */\n/* Date:   20. Nov. 99                                                    */\n/**************************************************************************/\n\n#include <general/mystring.hpp>\n\n\nnamespace netgen\n{\n\n  extern void PrintDot(char ch = '.');\n\n\n  //Message Pipeline:\n\n  //importance: importance of message: 1=very important, 3=middle, 5=low, 7=unimportant\n  extern DLL_HEADER void PrintMessage(int importance, \n\t\t\t   const MyStr& s1, const MyStr& s2=MyStr());\n  extern DLL_HEADER void PrintMessage(int importance, \n\t\t\t   const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4=MyStr());\n  extern DLL_HEADER void PrintMessage(int importance, \n\t\t\t   const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, \n\t\t\t   const MyStr& s5, const MyStr& s6=MyStr(), const MyStr& s7=MyStr(), const MyStr& s8=MyStr());\n\n  // CR without line-feed\n  extern DLL_HEADER void PrintMessageCR(int importance, \n\t\t\t     const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t     const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintFnStart(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t   const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintWarning(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t   const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintError(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintFileError(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t     const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintSysError(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t    const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintUserError(const MyStr& s1, const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\t     const MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n  extern DLL_HEADER void PrintTime(const MyStr& s1=\"\", const MyStr& s2=\"\", const MyStr& s3=\"\", const MyStr& s4=\"\", \n\t\t\tconst MyStr& s5=\"\", const MyStr& s6=\"\", const MyStr& s7=\"\", const MyStr& s8=\"\");\n\n\n\n\n  inline void PushStatusF(const std::string& s)\n  {\n    PushStatus (s);\n    PrintFnStart(s);\n  }\n\n}\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/netrule2.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n\nnetrule :: netrule ()\n{\n  // name = new char[1];\n  // name[0] = char(0);\n  quality = 0;\n}\n\nnetrule ::  ~netrule()\n{\n  // delete [] name;\n  /*\n  for(int i = 0; i < oldutofreearea_i.Size(); i++)\n    delete oldutofreearea_i[i];\n  for(int i = 0; i < freezone_i.Size(); i++)\n    delete freezone_i[i];\n  */\n}\n\n\n\nvoid netrule :: SetFreeZoneTransformation (const Vector & devp, int tolclass)\n{\n  double lam1 = 1.0/tolclass;\n  double lam2 = 1.-lam1;\n\n  double mem1[100], mem2[100], mem3[100];\n\n  int vs = oldutofreearea.Height();\n  FlatVector devfree(vs, mem1);\n\n  int fzs = freezone.Size();\n  transfreezone.SetSize (fzs);\n\n  if (tolclass <= oldutofreearea_i.Size())\n    {\n      oldutofreearea_i[tolclass-1].Mult (devp, devfree);\n\n      auto& fzi = freezone_i[tolclass-1];\n      for (int i = 0; i < fzs; i++)\n\t{\n\t  transfreezone[i][0] = fzi[i][0] + devfree[2*i];\n\t  transfreezone[i][1] = fzi[i][1] + devfree[2*i+1];\n\t}\n    }\n  else\n    {\n      FlatVector devfree1(vs, mem2);\n      FlatVector devfree2(vs, mem3);\n\n      oldutofreearea.Mult (devp, devfree1);\n      oldutofreearealimit.Mult (devp, devfree2);\n      devfree.Set2 (lam1, devfree1, lam2, devfree2);\n\n      for (int i = 0; i < fzs; i++)\n\t{\n\t  transfreezone[i][0] = lam1 * freezone[i][0] + lam2 * freezonelimit[i][0] + devfree[2*i];\n\t  transfreezone[i][1] = lam1 * freezone[i][1] + lam2 * freezonelimit[i][1] + devfree[2*i+1];\n\t}\n    }\n\n\n  if (fzs > 0)\n    {\n      fzmaxx = fzminx = transfreezone[0][0];\n      fzmaxy = fzminy = transfreezone[0][1];\n    }\n\n  for (int i = 1; i < fzs; i++)\n    {\n      if (transfreezone[i][0] > fzmaxx) fzmaxx = transfreezone[i][0];\n      if (transfreezone[i][0] < fzminx) fzminx = transfreezone[i][0];\n      if (transfreezone[i][1] > fzmaxy) fzmaxy = transfreezone[i][1];\n      if (transfreezone[i][1] < fzminy) fzminy = transfreezone[i][1];\n    }\n\n  for (int i = 0; i < fzs; i++)\n    {\n      const auto& p1 = transfreezone[i];\n      const auto& p2 = transfreezone[(i+1) % fzs];\n\n      Vec<2> vn = { p2[1] - p1[1], p1[0] - p2[0] };\n\n      double len2 = vn.Length2();\n\n      if (len2 < 1e-10)\n\t{\n\t  freesetinequ(i, 0) = 0;\n\t  freesetinequ(i, 1) = 0;\n\t  freesetinequ(i, 2) = -1;\n\t}\n      else\n\t{\n\t  vn /= sqrt (len2);    // scaling necessary ?\n\n\t  freesetinequ(i,0) = vn[0]; \n\t  freesetinequ(i,1) = vn[1]; \n\t  freesetinequ(i,2) = -(p1[0] * vn[0] + p1[1] * vn[1]);\n\t}\n    }\n}\n\n\n/*\nint netrule :: IsInFreeZone2 (const Point2d & p) const\n{\n  for (int i = 0; i < transfreezone.Size(); i++)\n    {\n      if (freesetinequ(i, 0) * p.X() + \n\t  freesetinequ(i, 1) * p[1] +\n\t  freesetinequ(i, 2) > 0) return 0;\n    }\n  return 1;\n}\n*/\n\nint netrule :: IsLineInFreeZone2 (const Point<2> & p1, const Point<2> & p2) const\n{\n  if ( (p1[0] > fzmaxx && p2[0] > fzmaxx) ||\n       (p1[0] < fzminx && p2[0] < fzminx) ||\n       (p1[1] > fzmaxy && p2[1] > fzmaxy) ||\n       (p1[1] < fzminy && p2[1] < fzminy) ) return 0;\n\n  for (int i = 1; i <= transfreezone.Size(); i++)\n    {\n      if (freesetinequ.Get(i, 1) * p1[0] + freesetinequ.Get(i, 2) * p1[1] +\n\t  freesetinequ.Get(i, 3) > -1e-8 &&    // -1e-6\n\t  freesetinequ.Get(i, 1) * p2[0] + freesetinequ.Get(i, 2) * p2[1] +\n\t  freesetinequ.Get(i, 3) > -1e-8       // -1e-6\n\t  ) return 0;\n    }\n\n  double nx =  (p2[1] - p1[1]);\n  double ny = -(p2[0] - p1[0]);\n  double nl = sqrt (nx * nx + ny * ny);\n  if (nl > 1e-8)\n    {\n      nx /= nl;\n      ny /= nl;\n      double c = - (p1[0] * nx + p1[1] * ny);\n\n      bool allleft = true;\n      bool allright = true;\n\n      for (int i = 1; i <= transfreezone.Size(); i++)\n\t{\n\t  bool left  = transfreezone.Get(i)[0] * nx + transfreezone.Get(i)[1] * ny + c <  1e-7;\n          bool right = transfreezone.Get(i)[0] * nx + transfreezone.Get(i)[1] * ny + c > -1e-7;\n\t  if (!left) allleft = false;\n\t  if (!right) allright = false;\n\t}\n      if (allleft || allright) return false;\n    }\n\n  return true;\n}\n\nint netrule :: ConvexFreeZone () const\n{\n  int n = transfreezone.Size();\n  for (int i = 1; i <= n; i++)\n    {\n      const bool counterclockwise = CCW (transfreezone.Get(i), \n\t\t\t\t\t transfreezone.Get(i % n + 1),\n\t\t\t\t\t transfreezone.Get( (i+1) % n + 1 ),\n\t\t\t\t\t 1e-7);\n      //(*testout) << \"ccw \" << counterclockwise << endl << \" p1 \" << transfreezone.Get(i) << \" p2 \" << transfreezone.Get(i % n + 1)\n      //\t\t << \" p3 \" << transfreezone.Get( (i+1) % n + 1 ) << endl;\n      if (!counterclockwise )\n\treturn 0;\n    }\n  return 1;\n}\n\n\n/*\nfloat netrule :: CalcPointDist (int pi, const Point2d & p) const\n{\n  float dx = p.X() - points.Get(pi).X();\n  float dy = p.Y() - points.Get(pi).Y();\n  const threefloat * tf = &tolerances.Get(pi);\n\n  return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy;\n}\n*/\n\nfloat netrule :: CalcLineError (int li, const Vec<2> & v) const\n{\n  float dx = v[0] - linevecs.Get(li)[0];\n  float dy = v[1] - linevecs.Get(li)[1];\n\n  const threefloat * ltf = &linetolerances.Get(li);\n  return ltf->f1 * dx * dx + ltf->f2 * dx * dy + ltf->f3 * dy * dy;\n}\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/meshing/netrule3.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\n\nnamespace netgen\n{\n\n\nvnetrule :: vnetrule ()\n{\n  name = new char[1];\n  name[0] = char(0);\n  quality = 0;\n}\n\nvnetrule :: ~vnetrule ()\n{\n  // if (strlen(name)) \n  delete [] name;\n  for (int i = 1; i <= freefaces.Size(); i++)\n    delete freefaces.Elem(i);\n  for (int i = 1; i <= freesets.Size(); i++)\n    delete freesets.Elem(i);\n  for (int i = 1; i <= freeedges.Size(); i++)\n    delete freeedges.Elem(i);\n  for (int i = 1; i <= freefaceinequ.Size(); i++)\n    delete freefaceinequ.Elem(i);\n  delete oldutofreezone;\n  delete oldutofreezonelimit;\n}\n\nint vnetrule :: TestFlag (char flag) const\n{\n  for (int i = 1; i <= flags.Size(); i++)\n    if (flags.Get(i) == flag) return 1;\n  return 0;\n}\n\n\nvoid vnetrule :: SetFreeZoneTransformation (const Vector & allp, int tolclass)\n{\n  int i, j;\n  // double nx, ny, nz, v1x, v1y, v1z, v2x, v2y, v2z;\n  double nl;\n  const threeint * ti;\n  int fs;\n\n  double lam1 = 1.0/(2 * tolclass - 1);\n  double lam2 = 1-lam1;\n\n  transfreezone.SetSize (freezone.Size());\n  \n  int np = points.Size();\n  int nfp = freezone.Size();\n  Vector vp(np), vfp1(nfp), vfp2(nfp);\n\n\n  for (i = 1; i <= 3; i++)\n    {\n      for (j = 1; j <= np; j++)\n\tvp(j-1) = allp(i+3*j-3-1);\n\n      oldutofreezone->Mult (vp, vfp1);\n      oldutofreezonelimit->Mult (vp, vfp2);\n\n      vfp1 *= lam1;\n      vfp1.Add (lam2, vfp2);\n\n      for (j = 1; j <= nfp; j++)\n\ttransfreezone.Elem(j).X(i) = vfp1(j-1);\n    }\n\n  // MARK(setfz2);\n\n\n  fzbox.SetPoint (transfreezone.Elem(1));\n  for (i = 2; i <= freezone.Size(); i++)\n    fzbox.AddPoint (transfreezone.Elem(i));\n  fzbox.IncreaseRel(1e-8);\n  \n  \n  // MARK(setfz3);\n\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      NgArray<threeint> & freesetfaces = *freefaces.Get(fs);\n      DenseMatrix & freesetinequ = *freefaceinequ.Get(fs);\n      \n      for (i = 1; i <= freesetfaces.Size(); i++)\n\t{\n\t  ti = &freesetfaces.Get(i);\n\t  const Point3d & p1 = transfreezone.Get(ti->i1);\n\t  const Point3d & p2 = transfreezone.Get(ti->i2);\n\t  const Point3d & p3 = transfreezone.Get(ti->i3);\n\n\t  Vec3d v1(p1, p2);   \n\t  Vec3d v2(p1, p3);   \n\t  Vec3d n;\n\t  Cross (v1, v2, n);\n\n\t  nl = n.Length();\n\n\t  if (nl < 1e-10)\n\t    {\n\t      freesetinequ.Set(1, 1, 0);\n\t      freesetinequ.Set(1, 2, 0);\n\t      freesetinequ.Set(1, 3, 0);\n\t      freesetinequ.Set(1, 4, -1);\n\t    }\n\t  else\n\t    {\n\t      //\t      n /= nl;\n\t      \n\t      freesetinequ.Set(i, 1, n.X()/nl);\n\t      freesetinequ.Set(i, 2, n.Y()/nl);\n\t      freesetinequ.Set(i, 3, n.Z()/nl);\n\t      freesetinequ.Set(i, 4,\n\t\t\t       -(p1.X() * n.X() + p1.Y() * n.Y() + p1.Z() * n.Z()) / nl);\n\t    }\n\t}\n    }\n\n  /*\n  (*testout) << \"Transformed freezone: \" << endl;\n  for (i = 1; i <= transfreezone.Size(); i++)\n    (*testout) << transfreezone.Get(i) << \" \";\n  (*testout) << endl;\n  */\n}\n\nint vnetrule :: ConvexFreeZone () const\n{\n  int i, j, k, fs;\n\n  // (*mycout) << \"Convex free zone...\\n\";\n  \n  int ret1=1;\n  // int ret2=1;\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      const DenseMatrix & freesetinequ = *freefaceinequ.Get(fs);\n\n      // const NgArray<int> & freeset = *freesets.Get(fs);\n      const NgArray<twoint> & freesetedges = *freeedges.Get(fs);\n      // const NgArray<threeint> & freesetfaces = *freefaces.Get(fs);\n      \n      for (i = 1; i <= freesetedges.Size(); i++)\n\t{\n\t  j = freesetedges.Get(i).i1;    //triangle j with opposite point k\n\t  k = freesetedges.Get(i).i2;\n\t  \n\t  if ( freesetinequ.Get(j, 1) * transfreezone.Get(k).X() +\n\t       freesetinequ.Get(j, 2) * transfreezone.Get(k).Y() +\n\t       freesetinequ.Get(j, 3) * transfreezone.Get(k).Z() +\n\t       freesetinequ.Get(j, 4) > 0 )\n\t    {\n\t      ret1=0;\n\t    }\n\t}\n      \n    }\n\n  return ret1;\n}\n\n\nint vnetrule :: IsInFreeZone (const Point3d & p) const\n{\n  int i, fs;\n  char inthis;\n  \n  \n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      inthis = 1;\n      NgArray<threeint> & freesetfaces = *freefaces.Get(fs);\n      DenseMatrix & freesetinequ = *freefaceinequ.Get(fs);\n      \n      for (i = 1; i <= freesetfaces.Size() && inthis; i++)\n\t{\n\t  if (freesetinequ.Get(i, 1) * p.X() + freesetinequ.Get(i, 2) * p.Y() +\n\t      freesetinequ.Get(i, 3) * p.Z() + freesetinequ.Get(i, 4) > 0)\n\t    inthis = 0;\n\t}\n      \n      if (inthis) return 1;\n    }\n  \n  return 0;\n}\n\n\nint vnetrule :: IsTriangleInFreeZone (const Point3d & p1, \n\t\t\t\t      const Point3d & p2,\n\t\t\t\t      const Point3d & p3, \n\t\t\t\t      const NgArray<int> & pi, int newone)\n{\n  int fs;\n  int infreeset, cannot = 0;\n\n\n  NgArrayMem<int,3> pfi(3), pfi2(3);\n\n  // convert from local index to freeset index\n  int i, j;\n  for (i = 1; i <= 3; i++)\n    {\n      pfi.Elem(i) = 0;\n      if (pi.Get(i))\n\t{\n\t  for (j = 1; j <= freezonepi.Size(); j++)\n\t    if (freezonepi.Get(j) == pi.Get(i))\n\t      pfi.Elem(i) = j;\n\t}\n    }\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      const NgArray<int> & freeseti = *freesets.Get(fs);\n      for (i = 1; i <= 3; i++)\n\t{\n\t  pfi2.Elem(i) = 0;\n\t  for (j = 1; j <= freeseti.Size(); j++)\n\t    if (pfi.Get(i) == freeseti.Get(j))\n\t      pfi2.Elem(i) = pfi.Get(i);\n\t}\n\n      infreeset = IsTriangleInFreeSet(p1, p2, p3, fs, pfi2, newone);\n      if (infreeset == 1) return 1;\n      if (infreeset == -1) cannot = -1;\n    }\n  \n  return cannot;\n}\n\n\n\nint vnetrule :: IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2,\n                                     const Point3d & p3, int fs,\n\t\t\t\t     const NgArray<int> & pi, int newone)\n{\n  int i, ii;\n  Vec3d n;\n  int allleft, allright;\n  int hos1, hos2, hos3, os1, os2, os3;\n  double hf, lam1, lam2, f, c1, c2, alpha;\n  double v1n, v2n, h11, h12, h22, dflam1, dflam2;\n  double lam1old, lam2old, fold;\n  double hpx, hpy, hpz, v1x, v1y, v1z, v2x, v2y, v2z;\n  int act1, act2, act3, it;\n  int cntout;\n  NgArray<int> activefaces;\n  int isin;\n  \n\n  // MARK(triinfz);\n  \n  NgArray<threeint> & freesetfaces = *freefaces.Get(fs);\n  DenseMatrix & freesetinequ = *freefaceinequ.Get(fs);\n  \n\n  int cnt = 0;\n  for (i = 1; i <= 3; i++)\n    if (pi.Get(i)) cnt++;\n\n  /*\n  (*testout) << \"trig in free set : \" << p1 << \" - \" << p2 << \" - \" << p3 << endl;\n  (*testout) << \"common points: \" << cnt << endl;\n  */\n  if (!newone)\n    cnt = 0;\n\n  if (cnt == 1)\n    {\n      // MARK(triinfz1);\n\n      int upi = 0, lpiu = 0;\n      for (i = 1; i <= 3; i++)\n\tif (pi.Get(i))\n\t  {\n\t    upi = i;\n\t    lpiu = pi.Get(i);\n\t  }\n\n      Vec3d v1, v2;\n      switch (upi)\n\t{\n\tcase 1:\n\t  {\n\t    v1 = p2 - p1;\n\t    v2 = p3 - p1;\n\t    break;\n\t  }\n\tcase 2:\n\t  {\n\t    v1 = p3 - p2;\n\t    v2 = p1 - p2;\n\t    break;\n\t  }\n\tcase 3:\n\t  {\n\t    v1 = p1 - p3;\n\t    v2 = p2 - p3;\n\t    break;\n\t  }\n\t}\n\n      v1 /= v1.Length();\n      v2 /= v2.Length();\n      Cross (v1, v2, n);\n      n /= n.Length();\n\n      //      (*testout) << \"Test new: \" << endl;\n      for (i = 1; i <= freesetfaces.Size(); i++)\n\t{\n\t  if ( (freesetfaces.Get(i).i1 == lpiu) || \n\t       (freesetfaces.Get(i).i2 == lpiu) ||\n\t       (freesetfaces.Get(i).i3 == lpiu) )\n\t    {\n\t      // freeface has point\n\n\n\t      Vec3d a (freesetinequ.Get(i, 1),\n\t\t       freesetinequ.Get(i, 2),\n\t\t       freesetinequ.Get(i, 3));\n\t      \n\t      //\t      if (1 - fabs (a * n) < 1e-8 ) \n\t      //\t\tcontinue;\n\n\t      Vec3d an;\n\t      Cross (a, n, an);\n\t      double lan = an.Length();\n\t      if (lan < 1e-10)\n\t\tcontinue;\n\n\t      an /= lan;\n\t      \n\t      int out1 = (a * v1) > 0;\n\t      int out2 = (a * v2) > 0;\n\t      //\t      (*testout) << \"out1, out2 = \" << out1 << \", \" << out2 << endl;\n\t      if (out1 && out2)\n\t\treturn 0;\n\n\t      if (!out1 && !out2) \n\t\tcontinue;\n\n\n\t      //\t      if ( ( (an * v1) < 0) &&  ( (an * v2) < 0) )   // falsch !!!!\n\t      //\t\tan *= -1;\n\n\t      // solve  an = lam1 v1 + lam2 v2\n\t      double vii11 = v1 * v1;\n\t      double vii12 = v1 * v2;\n\t      double vii22 = v2 * v2;\n\t      double det = vii11 * vii22 - vii12 * vii12;\n\t      if ( fabs (det) < 1e-10 )\n\t\tcontinue;\n\t      double rs1 = an * v1;\n\t      double rs2 = an * v2;\n\t      \n\t      double lambda1 = rs1 * vii22 - rs2 * vii12;\n\t      double lambda2 = rs2 * vii11 - rs1 * vii12;\n\n\t      if (fabs (lambda1) > fabs (lambda2))\n\t\t{\n\t\t  if (lambda1 < 0)\n\t\t    an *= -1;\n\t\t}\n\t      else\n\t\t{\n\t\t  if (lambda2 < 0)\n\t\t    an *= -1;\n\t\t}\n\n\n\t      if (lambda1 * lambda2 < 0 && 0)\n\t\t{\n\t\t  if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14)\n\t\t    {\n\t\t      //\t\t      (*mycout) << \"lambda1 lambda2 < 0\" << endl;\n\t\t      (*testout) << \"lambdai different\" << endl;\n\t\t      (*testout) << \"v1 = \" << v1 << endl;\n\t\t      (*testout) << \"v2 = \" << v2 << endl;\n\t\t      (*testout) << \"n = \" << n << endl;\n\t\t      (*testout) << \"a = \" << a << endl;\n\t\t      (*testout) << \"an = \" << an << endl;\n\t\t      (*testout) << \"a * v1 = \" << (a * v1) << endl;\n\t\t      (*testout) << \"a * v2 = \" << (a * v2) << endl;\n\t\t      (*testout) << \"an * v1 = \" << (an * v1) << endl;\n\t\t      (*testout) << \"an * v2 = \" << (an * v2) << endl;\n\t\t      \n\t\t      (*testout) << \"vii = \" << vii11 << \", \" << vii12 << \", \" << vii22 << endl;\n\t\t      (*testout) << \"lambdai = \" << lambda1 << \", \" << lambda2 << endl;\n\t\t      (*testout) << \"rs = \" << rs1 << \", \" << rs2 << endl;\n\t\t      continue;\n\t\t    }\n\t\t}\n\n\t      if (out1)\n\t\tv1 = an;\n\t      else\n\t\tv2 = an;\n\t    }\n\t}\n      \n      return 1;\n\n      /*\n      (*testout) << \"overlap trig \" << p1 << p2 << p3 << endl;\n      (*testout) << \"upi = \" << upi << endl;\n      (*testout) << \"v1 = \" << v1 << \" v2 = \" << v2 << endl;\n      */\n\n      switch (upi)\n\t{\n\tcase 1:\n\t  {\n\t    v1 = p2 - p1;\n\t    v2 = p3 - p1;\n\t    break;\n\t  }\n\tcase 2:\n\t  {\n\t    v1 = p3 - p2;\n\t    v2 = p1 - p2;\n\t    break;\n\t  }\n\tcase 3:\n\t  {\n\t    v1 = p1 - p3;\n\t    v2 = p2 - p3;\n\t    break;\n\t  }\n\t}\n\n      v1 /= v1.Length();\n      v2 /= v2.Length();\n      Cross (v1, v2, n);\n      n /= n.Length();\n\n      //      (*testout) << \"orig v1, v2 = \" << v1 << \", \" << v2 << endl;\n\n      \n      for (i = 1; i <= freesetfaces.Size(); i++)\n\t{\n\t  if ( (freesetfaces.Get(i).i1 == lpiu) || \n\t       (freesetfaces.Get(i).i2 == lpiu) ||\n\t       (freesetfaces.Get(i).i3 == lpiu) )\n\t    {\n\t      /*\n\t      (*testout) << \"v1, v2, now = \" << v1 << \", \" << v2 << endl;\n\n\t      // freeface has point\n\t      (*testout) << \"freesetface: \"\n\t\t\t << freesetfaces.Get(i).i1 << \" \"\n\t\t\t << freesetfaces.Get(i).i2 << \" \"\n\t\t\t << freesetfaces.Get(i).i3 << \" \";\n\t      */\n\n\t      Vec3d a (freesetinequ.Get(i, 1),\n\t\t       freesetinequ.Get(i, 2),\n\t\t       freesetinequ.Get(i, 3));\n\t      //\t      (*testout) << \"a = \" <<  a << endl;\n\n\n\t      Vec3d an;\n\t      Cross (a, n, an);\n\t      double lan = an.Length();\n\t      \n\t      //\t      (*testout) << \"an = \" << an << endl;\n\n\t      if (lan < 1e-10)\n\t\tcontinue;\n\n\t      an /= lan;\n\n\t      //\t      (*testout) << \"a*v1 = \" << (a*v1) << \" a*v2 = \" << (a*v2) << endl;\n\t      \n\t      int out1 = (a * v1) > 0;\n\t      // int out2 = (a * v2) > 0;\n\n\n\t      //\t      (*testout) << \"out1, 2 = \" << out1 << \", \" << out2 << endl;\n\n\t      \n\t      double vii11 = v1 * v1;\n\t      double vii12 = v1 * v2;\n\t      double vii22 = v2 * v2;\n\t      double det = vii11 * vii22 - vii12 * vii12;\n\t      if ( fabs (det) < 1e-10 )\n\t\tcontinue;\n\t      double rs1 = an * v1;\n\t      double rs2 = an * v2;\n\t      \n\t      double lambda1 = rs1 * vii22 - rs2 * vii12;\n\t      double lambda2 = rs2 * vii11 - rs1 * vii12;\n\n\t      //\t      (*testout) << \"lambda1, lambda2 = \" << lambda1 << \", \" << lambda2 << endl;\n\n\n\t      if (fabs (lambda1) > fabs (lambda2))\n\t\t{\n\t\t  if (lambda1 < 0)\n\t\t    an *= -1;\n\t\t}\n\t      else\n\t\t{\n\t\t  if (lambda2 < 0)\n\t\t    an *= -1;\n\t\t}\n\n\n\t      if (lambda1 * lambda2 < 0)\n\t\t{\n\t\t  if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14)\n\t\t    {\n\t\t      //\t\t      (*mycout) << \"lambda1 lambda2 < 0\" << endl;\n\t\t      (*testout) << \"lambdai different\" << endl;\n\t\t      (*testout) << \"v1 = \" << v1 << endl;\n\t\t      (*testout) << \"v2 = \" << v2 << endl;\n\t\t      (*testout) << \"n = \" << n << endl;\n\t\t      (*testout) << \"a = \" << a << endl;\n\t\t      (*testout) << \"an = \" << an << endl;\n\t\t      (*testout) << \"a * v1 = \" << (a * v1) << endl;\n\t\t      (*testout) << \"a * v2 = \" << (a * v2) << endl;\n\t\t      (*testout) << \"an * v1 = \" << (an * v1) << endl;\n\t\t      (*testout) << \"an * v2 = \" << (an * v2) << endl;\n\t\t      \n\t\t      (*testout) << \"vii = \" << vii11 << \", \" << vii12 << \", \" << vii22 << endl;\n\t\t      (*testout) << \"lambdai = \" << lambda1 << \", \" << lambda2 << endl;\n\t\t      (*testout) << \"rs = \" << rs1 << \", \" << rs2 << endl;\n\t\t      continue;\n\t\t    }\n\t\t}\n\n\t      if (out1)\n\t\tv1 = an;\n\t      else\n\t\tv2 = an;\n\n\n\n\t    }\n\t}\n\n      return 1;\n    }\n\n\n\n  if (cnt == 2)\n    {\n      //      (*testout) << \"tripoitns: \" << p1 << \" \" << p2 << \" \" << p3 << endl;\n\n      // MARK(triinfz2);\n\n      int pi1 = 0, pi2 = 0, pi3 = 0;\n      Vec3d a1, a2;  // outer normals\n      Vec3d trivec;  // vector from common edge to third point of triangle\n      for (i = 1; i <= 3; i++)\n\tif (pi.Get(i))\n\t  {\n\t    pi2 = pi1;\n\t    pi1 = pi.Get(i);\n\t  }\n\telse\n\t  pi3 = i;\n\n      switch (pi3)\n\t{\n\tcase 1: trivec = (p1 - p2); break;\n\tcase 2: trivec = (p2 - p3); break;\n\tcase 3: trivec = (p3 - p2); break;\n\t}\n\n      NgArray<int> lpi(freezonepi.Size());\n      for (i = 1; i <= lpi.Size(); i++)\n\tlpi.Elem(i) = 0;\n      lpi.Elem(pi1) = 1;\n      lpi.Elem(pi2) = 1;\n      \n      int ff1 = 0, ff2 = 0;\n      for (i = 1; i <= freesetfaces.Size(); i++)\n\t{\n\t  if (lpi.Get(freesetfaces.Get(i).i1) + \n\t      lpi.Get(freesetfaces.Get(i).i2) + \n\t      lpi.Get(freesetfaces.Get(i).i3) == 2)\n\t    {\n\t      ff2 = ff1;\n\t      ff1 = i;\n\t    }\n\t}\n\n      if (ff2 == 0)\n\treturn 1;\n\n      a1 = Vec3d (freesetinequ.Get(ff1, 1),\n\t\t  freesetinequ.Get(ff1, 2),\n\t\t  freesetinequ.Get(ff1, 3));\n      a2 = Vec3d (freesetinequ.Get(ff2, 1),\n\t\t  freesetinequ.Get(ff2, 2),\n\t\t  freesetinequ.Get(ff2, 3));\n\n      if ( ( (a1 * trivec) > 0) || ( (a2 * trivec) > 0))\n\treturn 0;\n\n      return 1;\n    }\n\n\n  if (cnt == 3)\n    {\n      // MARK(triinfz3);  \n\n      NgArray<int> lpi(freezonepi.Size());\n      for (i = 1; i <= lpi.Size(); i++)\n\tlpi.Elem(i) = 0;\n\n      for (i = 1; i <= 3; i++)\n\tlpi.Elem(pi.Get(i)) = 1;\n      \n      for (i = 1; i <= freesetfaces.Size(); i++)\n\t{\n\t  if (lpi.Get(freesetfaces.Get(i).i1) + \n\t      lpi.Get(freesetfaces.Get(i).i2) + \n\t      lpi.Get(freesetfaces.Get(i).i3) == 3)\n\t    {\n\t      return 0;\n\t    }\n\t}\n      return 1;\n    }\n\n  // MARK(triinfz0);  \n\n  \n  os1 = os2 = os3 = 0;\n  activefaces.SetSize(0);\n\n  // is point inside ?\n\n  for (i = 1; i <= freesetfaces.Size(); i++)\n    {\n      hos1 = freesetinequ.Get(i, 1) * p1.X() +\n\tfreesetinequ.Get(i, 2) * p1.Y() +\n\tfreesetinequ.Get(i, 3) * p1.Z() +\n\tfreesetinequ.Get(i, 4) > -1E-5;\n      \n      hos2 = freesetinequ.Get(i, 1) * p2.X() +\n\tfreesetinequ.Get(i, 2) * p2.Y() +\n\tfreesetinequ.Get(i, 3) * p2.Z() +\n\tfreesetinequ.Get(i, 4) > -1E-5;\n      \n      hos3 = freesetinequ.Get(i, 1) * p3.X() +\n\tfreesetinequ.Get(i, 2) * p3.Y() +\n\tfreesetinequ.Get(i, 3) * p3.Z() +\n\tfreesetinequ.Get(i, 4) > -1E-5;\n      \n      if (hos1 && hos2 && hos3) return 0;\n      \n      if (hos1) os1 = 1;\n      if (hos2) os2 = 1;\n      if (hos3) os3 = 1;\n      \n      if (hos1 || hos2 || hos3) activefaces.Append (i);\n    }\n  \n  if (!os1 || !os2 || !os3) return 1;\n\n  v1x = p2.X() - p1.X();\n  v1y = p2.Y() - p1.Y();\n  v1z = p2.Z() - p1.Z();\n\n  v2x = p3.X() - p1.X();\n  v2y = p3.Y() - p1.Y();\n  v2z = p3.Z() - p1.Z();\n\n  n.X() = v1y * v2z - v1z * v2y;\n  n.Y() = v1z * v2x - v1x * v2z;\n  n.Z() = v1x * v2y - v1y * v2x;\n  n /= n.Length();\n\n  allleft = allright = 1;\n  for (i = 1; i <= transfreezone.Size() && (allleft || allright); i++)\n    {\n      const Point3d & p = transfreezone.Get(i);\n      float scal = (p.X() - p1.X()) * n.X() +\n\t(p.Y() - p1.Y()) * n.Y() +\n\t(p.Z() - p1.Z()) * n.Z();\n\n      if ( scal >  1E-8 ) allleft = 0;\n      if ( scal < -1E-8 ) allright = 0;\n    }\n\n  if (allleft || allright) return 0;\n\n\n  lam1old = lam2old = lam1 = lam2 = 1.0 / 3.0;\n\n\n  //  testout << endl << endl << \"Start minimizing\" << endl;\n\n  it = 0;\n  int minit;\n  minit = 1000;\n  fold = 1E10;\n\n  \n\n  while (1)\n    {\n      it++;\n\n      if (it > 1000) return -1;\n\n      if (lam1 < 0) lam1 = 0;\n      if (lam2 < 0) lam2 = 0;\n      if (lam1 + lam2 > 1) lam1 = 1 - lam2;\n\n      if (it > minit)\n\t{\n\t  (*testout) << \"it = \" << it << endl;\n\t  (*testout) << \"lam1/2 = \" << lam1 << \"  \" << lam2 << endl;\n\t}\n\n      hpx = p1.X() + lam1 * v1x + lam2 * v2x;\n      hpy = p1.Y() + lam1 * v1y + lam2 * v2y;\n      hpz = p1.Z() + lam1 * v1z + lam2 * v2z;\n\n      f = 0;\n\n      h11 = h12 = h22 = dflam1 = dflam2 = 0;\n      cntout = 0;\n\n      isin = 1;\n\n      for (i = 1; i <= activefaces.Size(); i++)\n\t{\n\t  ii = activefaces.Get(i);\n\n\t  hf = freesetinequ.Get(ii, 1) * hpx +\n\t    freesetinequ.Get(ii, 2) * hpy +\n\t    freesetinequ.Get(ii, 3) * hpz +\n\t    freesetinequ.Get(ii, 4);\n\n\t  if (hf > -1E-7) isin = 0;\n\n\t  hf += 1E-4;\n\t  if (hf > 0)\n\t    {\n\t      f += hf * hf;\n\n\t      v1n = freesetinequ.Get(ii, 1) * v1x +\n\t\tfreesetinequ.Get(ii, 2) * v1y +\n\t\tfreesetinequ.Get(ii, 3) * v1z;\n\t      v2n = freesetinequ.Get(ii, 1) * v2x +\n\t\tfreesetinequ.Get(ii, 2) * v2y +\n\t\tfreesetinequ.Get(ii, 3) * v2z;\n\n\t      h11 += 2 * v1n * v1n;\n\t      h12 += 2 * v1n * v2n;\n\t      h22 += 2 * v2n * v2n;\n\t      dflam1 += 2 * hf * v1n;\n\t      dflam2 += 2 * hf * v2n;\n\t      cntout++;\n\t    }\n\t}\n\n      if (isin) return 1;\n\n      if (it > minit)\n\t{\n\t  (*testout) << \"f = \" << f\n\t\t     << \"  dfdlam = \" << dflam1 << \"  \" << dflam2 << endl;\n\t  (*testout) << \"h = \" << h11 << \"  \" << h12 << \"  \" << h22 << endl;\n\t  (*testout) << \"active: \" << cntout << endl;\n\t  (*testout) << \"lam1-lam1old = \" << (lam1 - lam1old) << endl;\n\t  (*testout) << \"lam2-lam2old = \" << (lam2 - lam2old) << endl;\n\t}\n\n\n      if (f >= fold)\n\t{\n\t  lam1 = 0.100000000000000 * lam1 + 0.9000000000000000 * lam1old;\n\t  lam2 = 0.100000000000000 * lam2 + 0.9000000000000000 * lam2old;\n\t}\n      else\n\t{\n\t  lam1old = lam1;\n\t  lam2old = lam2;\n\t  fold = f;\n\n\n\t  if (f < 1E-9) return 1;\n\n\t  h11 += 1E-10;\n\t  h22 += 1E-10;\n\t  c1 = - ( h22 * dflam1 - h12 * dflam2) / (h11 * h22 - h12 * h12);\n\t  c2 = - (-h12 * dflam1 + h11 * dflam2) / (h11 * h22 - h12 * h12);\n\t  alpha = 1;\n\n\n\t  if (it > minit)\n\t    (*testout) << \"c1/2 = \" << c1 << \"  \" << c2 << endl;\n\n\t  act1 = lam1 <= 1E-6 && c1 <= 0;\n\t  act2 = lam2 <= 1E-6 && c2 <= 0;\n\t  act3 = lam1 + lam2 >= 1 - 1E-6 && c1 + c2 >= 0;\n\n\t  if (it > minit)\n\t    (*testout) << \"act1,2,3 = \" << act1 << act2 << act3 << endl;\n\n\t  if ( (act1 && act2) || (act1 && act3) || (act2 && act3) ) return 0;\n\n\t  if (act1)\n\t    {\n\t      c1 = 0;\n\t      c2 = - dflam2 / h22;\n\t    }\n\n\t  if (act2)\n\t    {\n\t      c1 = - dflam1 / h11;\n\t      c2 = 0;\n\t    }\n\n\t  if (act3)\n\t    {\n\t      c1 = - (dflam1 - dflam2) / (h11 + h22 - 2 * h12);\n\t      c2 = -c1;\n\t    }\n\n\t  if (it > minit)\n\t    (*testout) << \"c1/2 now = \" << c1 << \"  \" << c2 << endl;\n\n\n\t  if (f > 100 * sqrt (sqr (c1) + sqr (c2))) return 0;\n\n\n\t  if (lam1 + alpha * c1 < 0 && !act1)\n\t    alpha = -lam1 / c1;\n\t  if (lam2 + alpha * c2 < 0 && !act2)\n\t    alpha = -lam2 / c2;\n\t  if (lam1 + lam2 + alpha * (c1 + c2) > 1 && !act3)\n\t    alpha = (1 - lam1 - lam2) / (c1 + c2);\n\n\t  if (it > minit)\n\t    (*testout) << \"alpha = \" << alpha << endl;\n\n\t  lam1 += alpha * c1;\n\t  lam2 += alpha * c2;\n\t}\n    }\n}\n\n\n\n\nint vnetrule :: IsQuadInFreeZone (const Point3d & p1, \n\t\t\t\t  const Point3d & p2,\n\t\t\t\t  const Point3d & p3, \n\t\t\t\t  const Point3d & p4, \n\t\t\t\t  const NgArray<int> & pi, int newone)\n{\n  int fs;\n  int infreeset, cannot = 0;\n\n\n  NgArrayMem<int,4> pfi(4), pfi2(4);\n\n  // convert from local index to freeset index\n  int i, j;\n  for (i = 1; i <= 4; i++)\n    {\n      pfi.Elem(i) = 0;\n      if (pi.Get(i))\n\t{\n\t  for (j = 1; j <= freezonepi.Size(); j++)\n\t    if (freezonepi.Get(j) == pi.Get(i))\n\t      pfi.Elem(i) = j;\n\t}\n    }\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      const NgArray<int> & freeseti = *freesets.Get(fs);\n      for (i = 1; i <= 4; i++)\n\t{\n\t  pfi2.Elem(i) = 0;\n\t  for (j = 1; j <= freeseti.Size(); j++)\n\t    if (pfi.Get(i) == freeseti.Get(j))\n\t      pfi2.Elem(i) = pfi.Get(i);\n\t}\n\n      infreeset = IsQuadInFreeSet(p1, p2, p3, p4, fs, pfi2, newone);\n      if (infreeset == 1) return 1;\n      if (infreeset == -1) cannot = -1;\n    }\n  \n  return cannot;\n}\n\n\nint vnetrule :: IsQuadInFreeSet (const Point3d & p1, const Point3d & p2,\n\t\t\t\t const Point3d & p3, const Point3d & p4, \n\t\t\t\t int fs, const NgArray<int> & pi, int newone)\n{\n  int i;\n  \n  int cnt = 0;\n  for (i = 1; i <= 4; i++)\n    if (pi.Get(i)) cnt++;\n  \n  /*\n  (*testout) << \"test quad in freeset: \" << p1 << \" - \" << p2 << \" - \" << p3 << \" - \" << p4 << endl;\n  (*testout) << \"pi = \";\n  for (i = 1; i <= pi.Size(); i++)\n    (*testout) << pi.Get(i) << \" \";\n  (*testout) << endl;\n  (*testout) << \"cnt = \" << cnt  << endl;\n  */\n  if (cnt == 4)\n    {\n      return 1;\n    }\n\n  if (cnt == 3)\n    {\n      return 1;\n    }\n\n  NgArrayMem<int,3> pi3(3);\n  int res;\n\n  pi3.Elem(1) = pi.Get(1);\n  pi3.Elem(2) = pi.Get(2);\n  pi3.Elem(3) = pi.Get(3);\n  res = IsTriangleInFreeSet (p1, p2, p3, fs, pi3, newone);\n  if (res) return res;\n\n\n  pi3.Elem(1) = pi.Get(2);\n  pi3.Elem(2) = pi.Get(3);\n  pi3.Elem(3) = pi.Get(4);\n  res = IsTriangleInFreeSet (p2, p3, p4, fs, pi3, newone);\n  if (res) return res;\n\n  pi3.Elem(1) = pi.Get(3);\n  pi3.Elem(2) = pi.Get(4);\n  pi3.Elem(3) = pi.Get(1);\n  res = IsTriangleInFreeSet (p3, p4, p1, fs, pi3, newone);\n  if (res) return res;\n\n  pi3.Elem(1) = pi.Get(4);\n  pi3.Elem(2) = pi.Get(1);\n  pi3.Elem(3) = pi.Get(2);\n  res = IsTriangleInFreeSet (p4, p1, p2, fs, pi3, newone);\n  return res;\n}\n\n\n\n\n\n\n\n\n\n\n\n\nfloat vnetrule :: CalcPointDist (int pi, const Point3d & p) const\n{\n  float dx = p.X() - points.Get(pi).X();\n  float dy = p.Y() - points.Get(pi).Y();\n  float dz = p.Z() - points.Get(pi).Z();\n  \n  //  const threefloat * tf = &tolerances.Get(pi);\n  //  return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy;\n  return tolerances.Get(pi) * (dx * dx + dy * dy + dz * dz);\n}\n\n\nint vnetrule :: TestOk () const\n{\n  NgArray<int> cntpused(points.Size());\n  NgArray<int> edge1, edge2;\n  NgArray<int> delf(faces.Size());\n  int i, j, k;\n  int pi1, pi2;\n  int found;\n\n  for (i = 1; i <= cntpused.Size(); i++)\n    cntpused.Elem(i) = 0;\n  for (i = 1; i <= faces.Size(); i++)\n    delf.Elem(i) = 0;\n  for (i = 1; i <= delfaces.Size(); i++)\n    delf.Elem(delfaces.Get(i)) = 1;\n\n\n  for (i = 1; i <= faces.Size(); i++)\n    if (delf.Get(i) || i > noldf)\n      for (j = 1; j <= faces.Get(i).GetNP(); j++)\n        cntpused.Elem(faces.Get(i).PNum(j))++;\n\n  for (i = 1; i <= cntpused.Size(); i++)\n    if (cntpused.Get(i) > 0 && cntpused.Get(i) < 2)\n      {\n\treturn 0;\n      }\n\n\n  //  (*testout) << endl;\n  for (i = 1; i <= faces.Size(); i++)\n    {\n      //      (*testout) << \"face \" << i << endl;\n      for (j = 1; j <= faces.Get(i).GetNP(); j++)\n\t{\n\t  pi1 = 0; pi2 = 0;\n\t  if (delf.Get(i))\n\t    {\n\t      pi1 = faces.Get(i).PNumMod(j);\n\t      pi2 = faces.Get(i).PNumMod(j+1);\n\t    }\n\t  if (i > noldf)\n\t    {\n\t      pi1 = faces.Get(i).PNumMod(j+1);\n\t      pi2 = faces.Get(i).PNumMod(j);\n\t    }\n\n\t  found = 0;\n\t  if (pi1)\n\t    {\n\t      for (k = 1; k <= edge1.Size(); k++)\n\t\tif (edge1.Get(k) == pi1 && edge2.Get(k) == pi2)\n\t\t  {\n\t\t    found = 1;\n\t\t    edge1.DeleteElement(k);\n\t\t    edge2.DeleteElement(k);\n\t\t    k--;\n\t\t    //\t\t    (*testout) << \"Del edge \" << pi1 << \"-\" << pi2 << endl;\n\t\t  }\n\t      if (!found)\n\t\t{\n\t\t  edge1.Append (pi2);\n\t\t  edge2.Append (pi1);\n\t\t  //\t\t  (*testout) << \"Add edge \" << pi1 << \"-\" << pi2 << endl;\n\t\t}\n\t    }\n\t}\n    }\n\n\n  if (edge1.Size() > 0)\n    {\n      return 0;\n    }\n\n  /*\n    cntpused.SetSize(freezone.Size());\n    for (i = 1; i <= cntpused.Size(); i++)\n    cntpused[i] = 0;\n\n    for (i = 1; i <= freefaces.Size(); i++)\n    {\n    cntpused[freefaces[i].i1]++;\n    cntpused[freefaces[i].i2]++;\n    cntpused[freefaces[i].i3]++;\n    }\n\n    for (i = 1; i <= cntpused.Size(); i++)\n    if (cntpused[i] < 3)\n    {\n    (*mycout) << \"Fall 3\" << endl;\n    return 0;\n    }\n\n\n\n    for (i = 1; i <= freefaces.Size(); i++)\n    {\n    for (j = 1; j <= 3; j++)\n    {\n    if (j == 1)\n    {\n    pi1 = freefaces[i].i1;\n    pi2 = freefaces[i].i2;\n    }\n    if (j == 2)\n    {\n    pi1 = freefaces[i].i2;\n    pi2 = freefaces[i].i3;\n    }\n    if (j == 3)\n    {\n    pi1 = freefaces[i].i3;\n    pi2 = freefaces[i].i1;\n    }\n\n    found = 0;\n    for (k = 1; k <= edge1.Size(); k++)\n    if (edge1[k] == pi1 && edge2[k] == pi2)\n    {\n    found = 1;\n    edge1.DeleteElement(k);\n    edge2.DeleteElement(k);\n    k--;\n    }\n\n    if (!found)\n    {\n    edge1.Append (pi2);\n    edge2.Append (pi1);\n    }\n    }\n    }\n\n    if (edge1.Size() > 0)\n    {\n    (*mycout) << \"Fall 4\" << endl;\n    return 0;\n    }\n    */\n  return 1;\n}\n\n\nint vnetrule :: IsDelFace (int fn) const\n{\n  int i;\n  for (i = 1; i <= GetNDelF(); i++)\n    if (GetDelFace(i) == fn) return 1;\n  return 0;\n}\n\n}\n"
  },
  {
    "path": "libsrc/meshing/parallelmesh.cpp",
    "content": "#ifdef PARALLEL\n\n#include <meshing.hpp>\n#include \"paralleltop.hpp\"\n\n// #define METIS4\n\n\n#ifdef METIS\nnamespace metis {\n  extern \"C\" {\n\n#include <metis.h>\n\n#if METIS_VER_MAJOR >= 5\n#define METIS5\n    typedef idx_t idxtype;   \n#else\n#define METIS4\n    typedef idxtype idx_t;  \n#endif\n  } \n}\n\nusing namespace metis;\n#endif\n\n/*\nnamespace ngcore {\n  template <> struct MPI_typetrait<netgen::PointIndex> {\n    static MPI_Datatype MPIType () { return MPI_INT; } };  \n}\n*/\n\nnamespace ngcore\n{\n\n  /** An MPI-Package for a Surface element **/\n  class SurfPointPackage\n  {\n  public:\n    int num;     // point number\n    int trignum; // STL geo info\n    double u, v; // OCC geo info\n    SurfPointPackage () { ; }\n    SurfPointPackage & operator = (const SurfPointPackage & other) {\n      num = other.num;\n      trignum = other.trignum;\n      u = other.u;\n      v = other.v;\n      return *this;\n    }\n  }; // class SurfPointPackage\n\n  template<> struct MPI_typetrait<SurfPointPackage> {\n    static NG_MPI_Datatype MPIType () {\n      static NG_MPI_Datatype MPI_T = 0;\n      if (!MPI_T)\n\t{\n\t  int block_len[2] = { 2, 2 };\n\t  NG_MPI_Aint displs[3] = { 0, 2*sizeof(int) };\n\t  NG_MPI_Datatype types[2] = { NG_MPI_INT, NG_MPI_DOUBLE };\n\t  NG_MPI_Type_create_struct(2, block_len, displs, types, &MPI_T);\n\t  NG_MPI_Type_commit(&MPI_T);\n\t}\n      return MPI_T;\n    }\n  }; // struct MPI_typetrait<SurfPointPackage>\n\n\n  class SelPackage\n  {\n  public:\n    int sei;\n    int index;\n    int np;\n    /** we send too much here, especially in 2d! **/\n    SurfPointPackage points[ELEMENT2D_MAXPOINTS];\n    SelPackage () { ; }\n    SelPackage (const netgen::Mesh & mesh, netgen::SurfaceElementIndex _sei)\n    {\n      const netgen::Element2d & el = mesh[_sei];\n      sei = _sei;\n      index = el.GetIndex();\n      np = el.GetNP();\n      for (int k : Range(1, np+1)) {\n\tauto & pnt = points[k-1];;\n\tpnt.num = el.PNum(k);\n\tpnt.trignum = el.GeomInfoPi(k).trignum;\n\tpnt.u = el.GeomInfoPi(k).u;\n\tpnt.v = el.GeomInfoPi(k).v;\n      }\n      /** otherwise, we use uninitialized values **/\n      for (int k : Range(np, ELEMENT2D_MAXPOINTS)) {\n\tpoints[k].num = -1;\n\tpoints[k].trignum = -1;\n\tpoints[k].u = -1;\n\tpoints[k].v = -1;\n      }\n    }\n    void Unpack (netgen::Element2d & el) const {\n      \tel.SetIndex(index);\n\tfor (int k : Range(1, np + 1)) {\n\t  auto & pnt = points[k-1];\n\t  el.PNum(k) = pnt.num;\n\t  el.GeomInfoPi(k).trignum = pnt.trignum;\n\t  el.GeomInfoPi(k).u = pnt.u;\n\t  el.GeomInfoPi(k).v = pnt.v;\n\t}\n    }\n    SelPackage & operator = (const SelPackage & other) {\n      sei = other.sei;\n      index = other.index;\n      np = other.np;\n      for (int k : Range(ELEMENT2D_MAXPOINTS))\n\t{ points[k] = other.points[k]; }\n      return *this;\n    }\n  }; // class SelPackage\n\n  template<> struct MPI_typetrait<SelPackage> {\n    static NG_MPI_Datatype MPIType () {\n      static NG_MPI_Datatype MPI_T = 0;\n      if (!MPI_T)\n\t{\n\t  int block_len[2] = { 3, ELEMENT2D_MAXPOINTS };\n\t  NG_MPI_Aint displs[3] = { 0, 3*sizeof(int) };\n\t  NG_MPI_Datatype types[2] = { NG_MPI_INT, GetMPIType<SurfPointPackage>() };\n\t  NG_MPI_Type_create_struct(2, block_len, displs, types, &MPI_T);\n\t  NG_MPI_Type_commit(&MPI_T);\n\t}\n      return MPI_T;\n    }\n  }; // MPI_typetrait<SelPackage>\n\n\n  class PointElPackage\n  {\n  public:\n    netgen::PointIndex pnum;\n    int index;\n    PointElPackage () { pnum = -1; index = -1; }\n    PointElPackage (const netgen::Element0d & el)\n    { pnum = el.pnum; index = el.index; }\n  }; // class PointElPackage\n\n  template<> struct MPI_typetrait<PointElPackage> {\n    static NG_MPI_Datatype MPIType () {\n      static NG_MPI_Datatype MPI_T = 0;\n      if (!MPI_T)\n\t{\n\t  int block_len[2] = { 1, 1 };\n\t  NG_MPI_Aint displs[3] = { 0, sizeof(netgen::PointIndex) };\n\t  NG_MPI_Datatype types[2] = { GetMPIType<netgen::PointIndex>(), NG_MPI_INT };\n\t  NG_MPI_Type_create_struct(2, block_len, displs, types, &MPI_T);\n\t  NG_MPI_Type_commit(&MPI_T);\n\t}\n      return MPI_T;\n    }\n  }; // MPI_typetrait<Element0d>\n\n\n} // namespace ngcore\n\nnamespace netgen\n{\n  /*\n  template <>\n  inline MPI_Datatype MyGetMPIType<PointIndex> ( )\n  { return MPI_INT; }\n  */\n\n  void Mesh :: SendRecvMesh ()\n  {\n    int id = GetCommunicator().Rank();\n    int np = GetCommunicator().Size();\n\n    if (np == 1) {\n      throw NgException(\"SendRecvMesh called, but only one rank in communicator!!\");\n    }\n    \n    if (id == 0)\n      PrintMessage (1, \"Send/Receive mesh\");\n\n    // Why is this here??\n    if (id == 0)\n      {\n\tparalleltop -> SetNV (GetNV());\n\tparalleltop -> SetNV_Loc2Glob (GetNV());\n\tparalleltop -> SetNE (GetNE());\n\tparalleltop -> SetNSegm (GetNSeg());\n\tparalleltop -> SetNSE (GetNSE());\n      }\n\n    if (id == 0)\n      SendMesh ();\n    else\n      ReceiveParallelMesh();\n\n    paralleltop -> UpdateCoarseGrid();\n  }\n\n\n\n\n\n\n\n  void Mesh :: SendMesh () const   \n  {\n    static Timer tsend(\"SendMesh\"); RegionTimer reg(tsend);\n    static Timer tbuildvertex(\"SendMesh::BuildVertex\");\n    static Timer tbuildvertexa(\"SendMesh::BuildVertex a\");\n    static Timer tbuildvertexb(\"SendMesh::BuildVertex b\");\n    static Timer tbuilddistpnums(\"SendMesh::Build_distpnums\");\n    static Timer tbuildelementtable(\"SendMesh::Build_elementtable\");\n    \n    NgMPI_Comm comm = GetCommunicator();\n    // int id = comm.Rank();\n    int ntasks = comm.Size();\n\n    int dim = GetDimension();\n    comm.Bcast(dim);\n\n    NgMPI_Requests sendrequests;  // (8*(ntasks-1));\n    // sendrequests.SetSize0();\n    \n    // If the topology is not already updated, we do not need to\n    // build edges/faces.\n    auto & top = const_cast<MeshTopology&>(GetTopology());\n    if(top.NeedsUpdate()) {\n      top.SetBuildVertex2Element(false);\n      top.SetBuildEdges(false);\n      top.SetBuildFaces(false);\n      top.Update();\n    }\n    \n    PrintMessage ( 3, \"Sending nr of elements\");\n    \n    Array<int> num_els_on_proc(ntasks);\n    num_els_on_proc = 0;\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      num_els_on_proc[vol_partition[ei]]++;\n\n    comm.ScatterRoot (num_els_on_proc);\n\n    Table<ElementIndex> els_of_proc (num_els_on_proc);\n    num_els_on_proc = 0;\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      {\n        auto nr = vol_partition[ei];\n        els_of_proc[nr][num_els_on_proc[nr]++] = ei;\n      }\n    \n    PrintMessage ( 3, \"Building vertex/proc mapping\");\n\n    Array<int> num_sels_on_proc(ntasks);\n    num_sels_on_proc = 0;\n    for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++)\n      num_sels_on_proc[surf_partition[ei]]++;\n\n    Table<SurfaceElementIndex> sels_of_proc (num_sels_on_proc);\n    num_sels_on_proc = 0;\n    for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++)\n      {\n        auto nr = surf_partition[ei];\n        sels_of_proc[nr][num_sels_on_proc[nr]++] = ei;\n      }\n    \n\n    NgArray<int> num_segs_on_proc(ntasks);\n    num_segs_on_proc = 0;\n    for (SegmentIndex ei = 0; ei < GetNSeg(); ei++)\n      // num_segs_on_proc[(*this)[ei].GetPartition()]++;\n      num_segs_on_proc[seg_partition[ei]]++;\n\n    TABLE<SegmentIndex> segs_of_proc (num_segs_on_proc);\n    for (SegmentIndex ei = 0; ei < GetNSeg(); ei++)\n      segs_of_proc.Add (seg_partition[ei], ei);\n\n\n    /**\n            ----- STRATEGY FOR PERIODIC MESHES -----\n\n       Whenever two vertices are identified by periodicity, any proc \n       that gets one of the vertices actually gets both of them.\n       This has to be transitive, that is, if\n       a <-> b and  b <-> c,\n       then any proc that has vertex a also has vertices b and c!\n\n       Surfaceelements and Segments that are identified by\n       periodicity are treated the same way.\n       \n       We need to duplicate these so we have containers to\n       hold the edges/facets. Afaik, a mesh cannot have nodes \n       that are not part of some sort of element.\n\n     **/\n\n    /** First, we build tables for vertex identification. **/\n    NgArray<INDEX_2> per_pairs;\n    NgArray<INDEX_2> pp2;\n    auto & idents = GetIdentifications();\n    bool has_periodic = false; \n    for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++)\n      {\n\tif(idents.GetType(idnr)!=Identifications::PERIODIC) continue;\n\thas_periodic = true;\n\tidents.GetPairs(idnr, pp2);\n\tper_pairs.Append(pp2);\n      }\n    NgArray<int, PointIndex::BASE> npvs(GetNV());\n    npvs = 0;\n    for (int k = 0; k < per_pairs.Size(); k++) {\n      npvs[per_pairs[k].I1()]++;\n      npvs[per_pairs[k].I2()]++;\n    }\n\n    /** for each vertex, gives us all identified vertices **/\n    TABLE<PointIndex, PointIndex::BASE> per_verts(npvs);\n    for (int k = 0; k < per_pairs.Size(); k++) {\n      per_verts.Add(per_pairs[k].I1(), per_pairs[k].I2());\n      per_verts.Add(per_pairs[k].I2(), per_pairs[k].I1());\n    }\n    for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) {\n      BubbleSort(per_verts[k]);\n    }\n\n    /** The same table as per_verts, but TRANSITIVE!! **/\n    auto iterate_per_verts_trans = [&](auto f){\n      NgArray<int> allvs;\n      // for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++)\n      for (PointIndex k = IndexBASE<PointIndex>();\n           k < GetNV()+IndexBASE<PointIndex>(); k++)      \n\t{\n\t  allvs.SetSize(0);\n\t  allvs.Append(per_verts[k]);\n\t  bool changed = true;\n\t  while(changed) {\n\t    changed = false;\n\t    for (int j = 0; j<allvs.Size(); j++)\n\t      {\n\t\tauto pervs2 = per_verts[allvs[j]];\n\t\tfor (int l = 0; l < pervs2.Size(); l++)\n\t\t  {\n\t\t    auto addv = pervs2[l];\n\t\t    if (allvs.Contains(addv) || addv==k) continue;\n\t\t    changed = true;\n\t\t    allvs.Append(addv);\n\t\t  }\n\t      }\n\t  }\n\t  f(k, allvs);\n\t}\n    };\n    iterate_per_verts_trans([&](auto k, auto & allvs) {\n\tnpvs[k] = allvs.Size();\n      });\n    TABLE<PointIndex, PointIndex::BASE> per_verts_trans(npvs);\n    iterate_per_verts_trans([&](auto k, auto & allvs) {\n\tfor (int j = 0; j<allvs.Size(); j++)\n\t  per_verts_trans.Add(k, allvs[j]);\n      });\n    for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) {\n      BubbleSort(per_verts_trans[k]);\n    }\n\n    /** Now we build the vertex-data to send to the workers. **/\n    tbuildvertex.Start();\n    NgArray<int, PointIndex::BASE> vert_flag (GetNV());\n    NgArray<int, PointIndex::BASE> num_procs_on_vert (GetNV());\n    NgArray<int> num_verts_on_proc (ntasks);\n    num_verts_on_proc = 0;\n    num_procs_on_vert = 0;\n    \n    auto iterate_vertices = [&](auto f) {\n      vert_flag = -1;\n      for (int dest = 1; dest < ntasks; dest++)\n\t{\n          for (auto ei : els_of_proc[dest])\n            for (auto pnum : (*this)[ei].PNums())\n              f(pnum, dest);\n\n          for (auto ei : sels_of_proc[dest])\n            for (auto pnum : (*this)[ei].PNums())\n              f(pnum, dest);\n\n          /*\n\t  NgFlatArray<SegmentIndex> segs = segs_of_proc[dest];\n\t  for (int hi = 0; hi < segs.Size(); hi++)\n\t    {\n\t      const Segment & el = (*this) [segs[hi]];\n\t      for (int i = 0; i < 2; i++)\n\t\tf(el[i], dest);\n\t    }\n          */\n          for (auto segi : segs_of_proc[dest])\n            for (auto pnum : (*this)[segi].PNums())\n              f(pnum, dest);\n\t}\n    };\n    /** count vertices per proc and procs per vertex **/\n    tbuildvertexa.Start();    \n    iterate_vertices([&](auto vertex, auto dest){\n\tauto countit = [&] (auto vertex, auto dest) {\n\t  if (vert_flag[vertex] < dest)\n\t    {\n\t      vert_flag[vertex] = dest;\n\t      num_verts_on_proc[dest]++;\n\t      num_procs_on_vert[vertex]++;\n\t    }\n\t};\n\tcountit(vertex, dest);\n        for (auto v : per_verts_trans[vertex])\n\t  countit(v, dest);\n      });\n    tbuildvertexa.Stop();    \n\n    \n    tbuildvertexb.Start();    \n    \n    TABLE<PointIndex> verts_of_proc (num_verts_on_proc);\n    TABLE<int, PointIndex::BASE> procs_of_vert (num_procs_on_vert);\n    TABLE<int, PointIndex::BASE> loc_num_of_vert (num_procs_on_vert);\n    /** Write vertex/proc mappingfs to tables **/\n    iterate_vertices([&](auto vertex, auto dest) {\n\tauto addit = [&] (auto vertex, auto dest) {\n\t  if (vert_flag[vertex] < dest)\n\t    {\n\t      vert_flag[vertex] = dest;\n\t      procs_of_vert.Add (vertex, dest);\n\t    }\n\t};\n\taddit(vertex, dest);\n        for (auto v : per_verts_trans[vertex])\n\t  addit(v, dest);\n      });\n    tbuildvertexb.Stop();        \n    /** \n\tlocal vertex numbers on distant procs \n\t(I think this was only used for debugging??) \n    **/\n    // for (int vert = 1; vert <= GetNP(); vert++ )\n    for (PointIndex vert : Points().Range())\n      {\n\tNgFlatArray<int> procs = procs_of_vert[vert];\n\tfor (int j = 0; j < procs.Size(); j++)\n\t  {\n\t    int dest = procs[j];\n\t    // !! we also use this as offsets for MPI-type, if this is changed, also change ReceiveParallelMesh\n\t    verts_of_proc.Add (dest, vert - IndexBASE<T_POINTS::index_type>());\n\t    loc_num_of_vert.Add (vert, verts_of_proc[dest].Size() -1+IndexBASE<T_POINTS::index_type>());\n\t  }\n      }\n    tbuildvertex.Stop();    \n    PrintMessage ( 3, \"Sending Vertices - vertices\");\n\n    Array<NG_MPI_Datatype> point_types(ntasks-1);\n    for (int dest = 1; dest < ntasks; dest++)\n      {\n\tNgFlatArray<PointIndex> verts = verts_of_proc[dest];\n\t// sendrequests.Append (MyMPI_ISend (verts, dest, NG_MPI_TAG_MESH+1, comm));\n        sendrequests += comm.ISend (FlatArray<PointIndex>(verts), dest, NG_MPI_TAG_MESH+1);\n\n\tNG_MPI_Datatype mptype = MeshPoint::MyGetMPIType();\n\n\tint numv = verts.Size();\n\n\tNgArray<int> blocklen (numv);  \n\tblocklen = 1;\n\t\n\tNG_MPI_Type_indexed (numv, (numv == 0) ? nullptr : &blocklen[0], \n\t\t\t  (numv == 0) ? nullptr : reinterpret_cast<int*> (&verts[0]), \n\t\t\t  mptype, &point_types[dest-1]);\n\tNG_MPI_Type_commit (&point_types[dest-1]);\n\n\tNG_MPI_Request request;\n\tNG_MPI_Isend( points.Data(), 1, point_types[dest-1], dest, NG_MPI_TAG_MESH+1, comm, &request);\n\tsendrequests += request;\n      }\n\n\n    /**\n       Next, we send the identifications themselves.\n       \n       Info about periodic identifications sent to each proc is an array of\n       integers.\n       - maxidentnr\n       - type for each identification\n       - nr of pairs for each identification (each pair is local!)\n       - pairs for each periodic ident (global numbers)\n    **/\n    PrintMessage ( 3, \"Sending Vertices - identifications\");\n    int maxidentnr = idents.GetMaxNr();\n    NgArray<int> ppd_sizes(ntasks);\n    ppd_sizes = 1 + 2*maxidentnr;\n    for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++)\n      {\n\tif(idents.GetType(idnr)!=Identifications::PERIODIC) continue;\n\tidents.GetPairs(idnr, pp2);\n\tfor(int j = 0; j<pp2.Size(); j++)\n\t  {\n\t    INDEX_2 & pair = pp2[j];\n\t    // both are on same procs!\n\t    auto ps = procs_of_vert[pair.I1()];\n\t    for (int l = 0; l < ps.Size(); l++)\n\t      {\n\t\tppd_sizes[ps[l]] += 2;\n\t      }\n\t  }\n      }\n    TABLE<int> pp_data(ppd_sizes);\n    for(int dest = 0; dest < ntasks; dest++)\n      pp_data.Add(dest, maxidentnr);\n    for (int dest = 0; dest < ntasks; dest++)\n      {\n\tfor (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++)\n\t  pp_data.Add(dest, idents.GetType(idnr));\n\tfor (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++)\n\t  pp_data.Add(dest, 0);\n      }\n    for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++)\n      {\n\tif(idents.GetType(idnr)!=Identifications::PERIODIC) continue;\n\tidents.GetPairs(idnr, pp2);\n\tfor(int j = 0; j<pp2.Size(); j++)\n\t  {\n\t    INDEX_2 & pair = pp2[j];\n\t    auto ps = procs_of_vert[pair.I1()];\n\t    for (int l = 0; l < ps.Size(); l++)\n\t      {\n\t\tauto p = ps[l];\n\t\tpp_data[p][maxidentnr + idnr]++;\n\t\tpp_data.Add(p, pair.I1());\n\t\tpp_data.Add(p, pair.I2());\n\t      }\n\t  }\n      }\n    NgMPI_Requests req_per;\n    for(int dest = 1; dest < ntasks; dest++)\n      // req_per.Append(MyMPI_ISend(pp_data[dest], dest, NG_MPI_TAG_MESH+1, comm));\n      req_per += comm.ISend(FlatArray<int>(pp_data[dest]), dest, NG_MPI_TAG_MESH+1);\n    req_per.WaitAll();\n\n    PrintMessage ( 3, \"Sending Vertices - distprocs\");\n\n    tbuilddistpnums.Start();\n    Array<int> num_distpnums(ntasks);\n    num_distpnums = 0;\n    // for (int vert = 1; vert <= GetNP(); vert++)\n    for (PointIndex vert : Points().Range())\n      {\n\tFlatArray<int> procs = procs_of_vert[vert];\n\tfor (auto p : procs)\n\t  num_distpnums[p] += 3 * (procs.Size()-1);\n      }\n\n    DynamicTable<int> distpnums (num_distpnums);\n    // for (int vert = 1; vert <= GetNP(); vert++)\n    for (PointIndex vert : Points().Range())\n      {\n\tNgFlatArray<int> procs = procs_of_vert[vert];\n\tfor (int j = 0; j < procs.Size(); j++)\n\t  for (int k = 0; k < procs.Size(); k++)\n\t    if (j != k)\n\t      {\n\t\tdistpnums.Add (procs[j], loc_num_of_vert[vert][j]);\n\t\tdistpnums.Add (procs[j], procs_of_vert[vert][k]);\n\t\tdistpnums.Add (procs[j], loc_num_of_vert[vert][k]);\n\t      }\n      }\n\n    tbuilddistpnums.Stop();\n        \n    for ( int dest = 1; dest < ntasks; dest ++ )\n      sendrequests += comm.ISend (distpnums[dest], dest, NG_MPI_TAG_MESH+1);\n\n\n\n    PrintMessage ( 3, \"Sending elements\" );\n\n    tbuildelementtable.Start();\n    Array<int> elarraysize (ntasks);\n    elarraysize = 0;\n    // for (int ei = 1; ei <= GetNE(); ei++)\n    for (ElementIndex ei : VolumeElements().Range())\n      {\n\tconst Element & el = VolumeElement (ei);\n\t// int dest = el.GetPartition();\n        int dest = vol_partition[ei];\n\telarraysize[dest] += 3 + el.GetNP();\n      }\n\n    DynamicTable<int> elementarrays(elarraysize);\n    \n    for (ElementIndex ei : VolumeElements().Range())    \n      {\n\tconst Element & el = VolumeElement (ei);\n        int dest = vol_partition[ei];\n        \n\telementarrays.Add (dest, int(ei+1));\n\telementarrays.Add (dest, el.GetIndex());\n\telementarrays.Add (dest, el.GetNP());\n        for (PointIndex pi : el.PNums())\n\t  elementarrays.Add (dest, pi);\n      }\n    tbuildelementtable.Stop();\n    \n    for (int dest = 1; dest < ntasks; dest ++ )\n      sendrequests += comm.ISend (elementarrays[dest], dest, NG_MPI_TAG_MESH+2);\n\n\n    PrintMessage ( 3, \"Sending Face Descriptors\" );\n\n    Array<double> fddata (6 * GetNFD());\n    for (int fdi = 1; fdi <= GetNFD(); fdi++)\n      {\n\tfddata[6*fdi-6] = GetFaceDescriptor(fdi).SurfNr();\n\tfddata[6*fdi-5] = GetFaceDescriptor(fdi).DomainIn();\t\n\tfddata[6*fdi-4] = GetFaceDescriptor(fdi).DomainOut();\n\tfddata[6*fdi-3] = GetFaceDescriptor(fdi).BCProperty();\n\tfddata[6*fdi-2] = GetFaceDescriptor(fdi).domin_singular;\n\tfddata[6*fdi-1] = GetFaceDescriptor(fdi).domout_singular;\n\t\n      }\n    for (int dest = 1; dest < ntasks; dest++)\n      sendrequests += comm.ISend (fddata, dest, NG_MPI_TAG_MESH+3);\n    \n    /** Surface Elements **/\n\n    PrintMessage ( 3, \"Sending Surface elements\" );\n    // build sel-identification\n    size_t nse = GetNSE();\n    NgArray<SurfaceElementIndex> ided_sel(nse);\n    ided_sel = -1;\n    [[maybe_unused]] bool has_ided_sels = false;\n    if(GetNE() && has_periodic) //we can only have identified surf-els if we have vol-els (right?)\n      {\n\tArray<SurfaceElementIndex> os1, os2;\n\tfor(SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n\t  {\n\t    if(ided_sel[sei]!=-1) continue;\n\t    const Element2d & sel = (*this)[sei];\n\t    auto points = sel.PNums();\n\t    auto ided1 = per_verts[points[0]];\n\t    os1.SetSize(0);\n\t    for (int j = 0; j < ided1.Size(); j++)\n\t      os1.Append(GetTopology().GetVertexSurfaceElements(ided1[j]));\n\t    for (int j = 1; j < points.Size(); j++)\n\t      {\n\t\tos2.SetSize(0);\n\t\tauto p2 = points[j];\n\t\tauto ided2 = per_verts[p2];\n\t\tfor (int l = 0; l < ided2.Size(); l++)\n\t\t  os2.Append(GetTopology().GetVertexSurfaceElements(ided2[l]));\n\t\tfor (int m = 0; m<os1.Size(); m++) {\n\t\t  if(!os2.Contains(os1[m])) {\n\t\t    os1.DeleteElement(m);\n\t\t    m--;\n\t\t  }\n\t\t}\n\t      }\n\t    if(!os1.Size()) continue;\n\t    if(os1.Size()>1) {\n\t      throw NgException(\"SurfaceElement identified with more than one other??\");\n\t    }\n\t    // const Element2d & sel2 = (*this)[sei];\n\t    // auto points2 = sel2.PNums();\n\t    has_ided_sels = true;\n\t    ided_sel[sei] = os1[0];\n\t    ided_sel[os1[0]] = sei;\n\t  }\n      }\n    // build sel data to send\n    auto iterate_sels = [&](auto f) {\n      for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++ )\n\t{\n\t  const Element2d & sel = (*this)[sei];\n\t  // int dest = (*this)[sei].GetPartition();\n          int dest = surf_partition[sei];\n\t  f(sei, sel, dest);\n\t  if(ided_sel[sei]!=-1)\n\t    {\n\t      // int dest2 = (*this)[ided_sel[sei]].GetPartition();\n              int dest2 = surf_partition[ided_sel[sei]];\n\t      f(sei, sel, dest2);\n\t    }\n\t}      \n    };\n    Array <int> nlocsel(ntasks), bufsize(ntasks);\n    nlocsel = 0;\n    bufsize = 0;\n    iterate_sels([&](SurfaceElementIndex sei, const Element2d & sel, int dest){\n\tnlocsel[dest]++;\n\tbufsize[dest]++;\n      });\n    DynamicTable<SelPackage> selbuf(bufsize);\n    iterate_sels([&](SurfaceElementIndex sei, const auto & sel, int dest) {\n\tselbuf.Add (dest, SelPackage(*this, sei));\n      });\n    // distribute sel data\n    for (int dest = 1; dest < ntasks; dest++)\n      sendrequests += comm.ISend(selbuf[dest], dest, NG_MPI_TAG_MESH+4);\n    \n\n    /** Segments **/\n    PrintMessage ( 3, \"Sending Edge Segments\");\n    auto iterate_segs1 = [&](auto f) {\n      NgArray<SegmentIndex> osegs1, osegs2, osegs_both;\n      NgArray<int> type1, type2;\n      for(SegmentIndex segi = 0; segi < GetNSeg(); segi++)\n\t{\n\t  const Segment & seg = (*this)[segi];\n\t  int segnp = seg.GetNP();\n\t  PointIndex pi1 = seg[0];\n\t  auto ided1 = per_verts[pi1];\n\t  PointIndex pi2 = seg[1];\n\t  auto ided2 = per_verts[pi2];\n\t  if (!(ided1.Size() && ided2.Size())) continue;\n\t  osegs1.SetSize(0);\n\t  type1.SetSize(0);\n\t  for (int l = 0; l<ided1.Size(); l++)\n\t    {\n\t      auto ospart = GetTopology().GetVertexSegments(ided1[l]);\n\t      for(int j=0; j<ospart.Size(); j++)\n\t\t{\n\t\t  if(osegs1.Contains(ospart[j]))\n\t\t    throw NgException(\"Periodic Mesh did something weird.\");\n\t\t  osegs1.Append(ospart[j]);\n\t\t  type1.Append(idents.GetSymmetric(pi1, ided1[l]));\n\t\t}\n\t    }\n\t  osegs2.SetSize(0);\n\t  type2.SetSize(0);\n\t  for (int l = 0; l<ided2.Size(); l++)\n\t    {\n\t      auto ospart = GetTopology().GetVertexSegments(ided2[l]);\n\t      for(int j=0; j<ospart.Size(); j++)\n\t\t{\n\t\t  if(osegs2.Contains(ospart[j]))\n\t\t    throw NgException(\"Periodic Mesh did something weird.\");\n\t\t  osegs2.Append(ospart[j]);\n\t\t  type2.Append(idents.GetSymmetric(pi2, ided2[l]));\n\t\t}\n\t    }\n\t  osegs_both.SetSize(0);\n\t  for (int l = 0; l<osegs1.Size(); l++) {\n\t    auto pos = osegs2.Pos(osegs1[l]);\n\t    if (pos == -1) continue;\n\t    if (type1[l] != type2[pos]) continue;\n\t    osegs_both.Append(osegs1[l]);\n\t  }\n\t  for(int l = 0; l<osegs_both.Size(); l++) {\n\t    int segnp2 = (*this)[osegs_both[l]].GetNP();\n\t    if(segnp!=segnp2)\n\t      throw NgException(\"Tried to identify non-curved and curved Segment!\");\n\t  }\n\t  for(int l = 0; l<osegs_both.Size(); l++) {\n\t    f(segi, osegs_both[l]);\n\t  }\n\t}\n    };\n    NgArray<int> per_seg_size(GetNSeg());\n    per_seg_size = 0;\n    iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2)\n\t\t  { per_seg_size[segi1]++; });\n    TABLE<SegmentIndex> per_seg(per_seg_size);\n    iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2)\n\t\t  { per_seg.Add(segi1, segi2); });\n    // make per_seg transitive\n    auto iterate_per_seg_trans = [&](auto f){\n      NgArray<SegmentIndex> allsegs;\n      for (SegmentIndex segi = 0; segi < GetNSeg(); segi++)\n\t{\n\t  allsegs.SetSize(0);\n\t  allsegs.Append(per_seg[segi]);\n\t  bool changed = true;\n\t  while (changed)\n\t    {\n\t      changed = false;\n\t      for (int j = 0; j<allsegs.Size(); j++)\n\t\t{\n\t\t  auto persegs2 = per_seg[allsegs[j]];\n\t\t  for (int l = 0; l<persegs2.Size(); l++)\n\t\t    {\n\t\t      auto addseg = persegs2[l];\n\t\t      if (allsegs.Contains(addseg) || addseg==segi) continue;\n\t\t      allsegs.Append(addseg);\n\t\t      changed = true;\n\t\t    }\n\t\t}\n\t    }\n\t  f(segi, allsegs);\n\t}\n    };\n    iterate_per_seg_trans([&](SegmentIndex segi, NgArray<SegmentIndex> & segs){\n\tfor (int j = 0; j < segs.Size(); j++)\n\t  per_seg_size[segi] = segs.Size();\n      });\n    TABLE<SegmentIndex> per_seg_trans(per_seg_size);\n    iterate_per_seg_trans([&](SegmentIndex segi, NgArray<SegmentIndex> & segs){\n\tfor (int j = 0; j < segs.Size(); j++)\n\t  per_seg_trans.Add(segi, segs[j]);\n      });\n    // build segment data\n    NgArray<int> dests;\n    auto iterate_segs2 = [&](auto f)\n      {\n\tfor (SegmentIndex segi = 0; segi<GetNSeg(); segi++)\n\t  {\n\t    const Segment & seg = (*this)[segi];\n\t    dests.SetSize(0);\n\t    // dests.Append(seg.GetPartition());\n            dests.Append(seg_partition[segi]);\n\t    for (int l = 0; l < per_seg_trans[segi].Size(); l++)\n\t      {\n\t\t// int dest2 = (*this)[per_seg_trans[segi][l]].GetPartition();\n                int dest2 = seg_partition[per_seg_trans[segi][l]];\n\t\tif(!dests.Contains(dest2))\n\t\t  dests.Append(dest2);\n\t      }\n\t    for (int l = 0; l < dests.Size(); l++)\n\t      f(segi, seg, dests[l]);\n\t  }\n      };\n    NgArray<int> nloc_seg(ntasks);\n    // bufsize = 1; //was originally this - why??\n    bufsize = 0;\n    nloc_seg = 0;\n    iterate_segs2([&](auto segi, const auto & seg, int dest)\n\t\t  {\n\t\t    nloc_seg[dest]++;\n\t\t    bufsize[dest] += 15;\n\t\t  });\n    DynamicTable<double> segm_buf(bufsize);\n    iterate_segs2([&](auto segi, const auto & seg, int dest)\n\t\t  {\n\t\t    segm_buf.Add (dest, segi);\n\t\t    segm_buf.Add (dest, seg.si);\n\t\t    segm_buf.Add (dest, seg.pnums[0]);\n\t\t    segm_buf.Add (dest, seg.pnums[1]);\n\t\t    segm_buf.Add (dest, seg.geominfo[0].trignum);\n\t\t    segm_buf.Add (dest, seg.geominfo[1].trignum);\n\t\t    segm_buf.Add (dest, seg.surfnr1);\n\t\t    segm_buf.Add (dest, seg.surfnr2);\n\t\t    segm_buf.Add (dest, seg.edgenr);\n\t\t    segm_buf.Add (dest, seg.index);                    \n\t\t    segm_buf.Add (dest, seg.epgeominfo[0].dist);\n\t\t    segm_buf.Add (dest, seg.epgeominfo[1].edgenr);\n\t\t    segm_buf.Add (dest, seg.epgeominfo[1].dist);\n\t\t    segm_buf.Add (dest, seg.singedge_right);\n\t\t    segm_buf.Add (dest, seg.singedge_left);\n\t\t  });\n    // distribute segment data\n    for (int dest = 1; dest < ntasks; dest++)\n      sendrequests += comm.ISend(segm_buf[dest], dest, NG_MPI_TAG_MESH+5);\n\n    /** Point-Elements **/\n    PrintMessage ( 3, \"Point-Elements ...\");\n\n    auto iterate_zdes = [&](auto f) {\n      for (auto k : Range(pointelements)) {\n\tauto & el = pointelements[k];\n\tPointElPackage pack(el);\n\tauto dests = procs_of_vert[el.pnum];\n\tfor (auto dest : dests)\n\t  { f(pack, dest); }\n      }\n    };\n\n    bufsize = 0;\n    iterate_zdes([&](const auto & pack, auto dest) { bufsize[dest]++; });\n    DynamicTable<PointElPackage> zde_buf(bufsize); // zero dim elements\n    iterate_zdes([&](const auto & pack, auto dest) { zde_buf.Add(dest, pack); });\n\n    for (int dest = 1; dest < ntasks; dest++)\n      sendrequests += comm.ISend(zde_buf[dest], dest, NG_MPI_TAG_MESH+6); \n\n    PrintMessage ( 3, \"now wait ...\");\n\n    sendrequests.WaitAll();\n\n    // clean up MPI-datatypes we allocated earlier\n    for (auto t : point_types)\n      { NG_MPI_Type_free(&t); }\n\n    paralleltop -> SetNV_Loc2Glob (0);\n    paralleltop -> SetNV (0);\n    paralleltop -> EnumeratePointsGlobally();\n    PrintMessage ( 3, \"Sending names\");\n\n    /** Send bc/mat/cd*-names **/\n    // nr of names\n    std::array<int,4> nnames{0,0,0,0};\n    nnames[0] = materials.Size();\n    nnames[1] = bcnames.Size();\n    nnames[2] = GetNCD2Names();\n    nnames[3] = GetNCD3Names();\n    int tot_nn = nnames[0] + nnames[1] + nnames[2] + nnames[3];\n\n    NgMPI_Requests requ;\n    requ += comm.IBcast (nnames);\n    \n    auto iterate_names = [&](auto func) {\n      for (int k = 0; k < nnames[0]; k++) func(materials[k]);\n      for (int k = 0; k < nnames[1]; k++) func(bcnames[k]);\n      for (int k = 0; k < nnames[2]; k++) func(cd2names[k]);\n      for (int k = 0; k < nnames[3]; k++) func(cd3names[k]);\n    };\n    // sizes of names\n    Array<int> name_sizes(tot_nn);\n    tot_nn = 0;\n    iterate_names([&](auto ptr) { name_sizes[tot_nn++] = (ptr==NULL) ? 0 : ptr->size(); });\n\n    requ += comm.IBcast (name_sizes);\n    // names\n    int strs = 0;\n    iterate_names([&](auto ptr) { strs += (ptr==NULL) ? 0 : ptr->size(); });\n    Array<char> compiled_names(strs);\n    strs = 0;\n    iterate_names([&](auto ptr) {\n\tif (ptr==NULL) return;\n\tauto& name = *ptr;\n\tfor (int j=0; j < name.size(); j++) compiled_names[strs++] = name[j];\n      });\n\n\n    requ += comm.IBcast (compiled_names);\n    PrintMessage ( 3, \"wait for names\");\n\n    requ.WaitAll();\n    \n    comm.Barrier();\n\n    PrintMessage( 3, \"Clean up local memory\");\n\n    auto & self = const_cast<Mesh&>(*this);\n    self.points = T_POINTS(0);\n    self.surfelements = Array<Element2d>(0);\n    self.volelements = Array<Element>(0);\n    self.segments = Array<Segment>(0);\n    self.pointelements = Array<Element0d>(0);\n    self.lockedpoints = Array<PointIndex>(0);\n    /*\n    auto cleanup_ptr = [](auto & ptr) {\n      if (ptr != nullptr) {\n\tdelete ptr;\n\tptr = nullptr;\n      }\n    };\n    cleanup_ptr(self.boundaryedges);\n    cleanup_ptr(self.segmentht);\n    cleanup_ptr(self.surfelementht);\n    */\n    self.boundaryedges = nullptr;\n    self.segmentht = nullptr;\n    self.surfelementht = nullptr;\n    \n    self.openelements = NgArray<Element2d>(0);\n    self.opensegments = NgArray<Segment>(0);\n    self.numvertices = 0;\n    self.mlbetweennodes = Array<PointIndices<2>,PointIndex> (0);\n    self.mlparentelement = Array<ElementIndex, ElementIndex>(0);\n    self.mlparentsurfaceelement = Array<SurfaceElementIndex, SurfaceElementIndex>(0);\n    self.curvedelems = make_unique<CurvedElements> (self);\n    self.clusters = make_unique<AnisotropicClusters> (self);\n    self.ident = make_unique<Identifications> (self);\n    self.topology = MeshTopology(*this);\n    self.topology.Update();\n    self.BuildElementSearchTree(3);\n    \n    // const_cast<Mesh&>(*this).DeleteMesh();\n\n    // paralleltop -> SetNV (0);\n    // paralleltop->EnumeratePointsGlobally();\n    \n    PrintMessage( 3, \"send mesh complete\");\n  }\n\n\n\n\n\n\n\n\n  // workers receive the mesh from the master\n  void Mesh :: ReceiveParallelMesh ( )\n  {\n    Timer timer(\"ReceiveParallelMesh\");\n    Timer timer_pts(\"Receive points\");\n    Timer timer_els(\"Receive elements\");\n    Timer timer_sels(\"Receive surface elements\");\n    RegionTimer reg(timer);\n\n    NgMPI_Comm comm = GetCommunicator();\n    int id = comm.Rank();\n    // int ntasks = comm.Size();\n    \n    int dim;\n    comm.Bcast(dim);\n    SetDimension(dim);\n    \n    // Receive number of local elements\n    int nelloc;\n    comm.Scatter (nelloc);\n    paralleltop -> SetNE (nelloc);\n    \n    // receive vertices\n    timer_pts.Start();\n\n    Array<int> verts;\n    comm.Recv (verts, 0, NG_MPI_TAG_MESH+1);\n\n    int numvert = verts.Size();\n    paralleltop -> SetNV (numvert);\n    paralleltop -> SetNV_Loc2Glob (numvert);\n    \n    // INDEX_CLOSED_HASHTABLE<int> glob2loc_vert_ht (3*numvert+1);\n    INDEX_HASHTABLE<int> glob2loc_vert_ht (3*numvert+1);\n\n    for (int vert = 0; vert < numvert; vert++)\n      {\n\tPointIndex globvert = verts[vert] + IndexBASE<T_POINTS::index_type>();\n        // paralleltop->SetLoc2Glob_Vert ( vert+1, globvert  );\n        paralleltop->L2G (PointIndex(vert+PointIndex::BASE)) = globvert;\n\tglob2loc_vert_ht.Set (globvert, vert+PointIndex::BASE);\n      }\n    \n    for (int i = 0; i < numvert; i++)\n      AddPoint (netgen::Point<3> (0,0,0));\n    \n    NG_MPI_Datatype mptype = MeshPoint::MyGetMPIType();\n    NG_MPI_Status status;\n    NG_MPI_Recv( points.Data(), numvert, mptype, 0, NG_MPI_TAG_MESH+1, comm, &status);\n\n    Array<int> pp_data;\n    comm.Recv(pp_data, 0, NG_MPI_TAG_MESH+1);\n\n    int maxidentnr = pp_data[0];\n    auto & idents = GetIdentifications();\n    for (int idnr = 1; idnr < maxidentnr+1; idnr++)\n      idents.SetType(idnr, (Identifications::ID_TYPE)pp_data[idnr]);\n\n    int offset = 2*maxidentnr+1;\n    for(int idnr = 1; idnr < maxidentnr+1; idnr++)\n      {\n    \tint npairs = pp_data[maxidentnr+idnr];\n    \tNgFlatArray<int> pairdata(2*npairs, &pp_data[offset]);\n    \toffset += 2*npairs;\n\tfor (int k = 0; k<npairs; k++) {\n\t  PointIndex loc1 = glob2loc_vert_ht.Get(pairdata[2*k]);\n\t  PointIndex loc2 = glob2loc_vert_ht.Get(pairdata[2*k+1]);\n\t  idents.Add(loc1, loc2, idnr);\n\t}\n      }\n    \n    Array<int> dist_pnums; \n    comm.Recv (dist_pnums, 0, NG_MPI_TAG_MESH+1);\n    \n    for (int hi = 0; hi < dist_pnums.Size(); hi += 3)\n      paralleltop ->\n\t// SetDistantPNum (dist_pnums[hi+1], dist_pnums[hi]); // , dist_pnums[hi+2]);\n        AddDistantProc (PointIndex(dist_pnums[hi]), dist_pnums[hi+1]);\n    \n    timer_pts.Stop();\n    *testout << \"got \" << numvert << \" vertices\" << endl;\n\n    \n    {\n      RegionTimer reg(timer_els);\n\n      Array<int> elarray;\n      comm.Recv (elarray, 0, NG_MPI_TAG_MESH+2);\n\n      for (int ind = 0, elnum = 1; ind < elarray.Size(); elnum++)\n\t{\n\t  paralleltop->SetLoc2Glob_VolEl ( elnum,  elarray[ind++]);\n\n          int index = elarray[ind++];\n          Element el(elarray[ind++]);          \n\t  el.SetIndex(index);\n\t  \n\t  for ( int j = 0; j < el.GetNP(); j++)\n\t    el[j] = glob2loc_vert_ht.Get (elarray[ind++]); \n\t  \n\t  AddVolumeElement (el);\n\t}\n    }\n\n    {\n      Array<double> fddata;\n      comm.Recv (fddata, 0, NG_MPI_TAG_MESH+3);\n      for (int i = 0; i < fddata.Size(); i += 6)\n\t{\n\t  int faceind = AddFaceDescriptor \n\t    (FaceDescriptor(int(fddata[i]), int(fddata[i+1]), int(fddata[i+2]), 0));\n\t  GetFaceDescriptor(faceind).SetBCProperty (int(fddata[i+3]));\n\t  GetFaceDescriptor(faceind).domin_singular = fddata[i+4];\n\t  GetFaceDescriptor(faceind).domout_singular = fddata[i+5];\n\t}\n    }\n\n    {\n      RegionTimer reg(timer_sels);\n      Array<SelPackage> selbuf;\n\n      comm.Recv ( selbuf, 0, NG_MPI_TAG_MESH+4);\n      \n      int nlocsel = selbuf.Size();\n      paralleltop -> SetNSE ( nlocsel );\n      \n      int sel = 0;\n      for (auto k : Range(selbuf)) {\n\tauto & pack = selbuf[k];\n\tElement2d el(pack.np);\n\tpack.Unpack(el);\n\t/** map global point numbers to local ones **/\n\tfor (int k : Range(1, 1+el.GetNP()))\n\t  { el.PNum(k) = glob2loc_vert_ht.Get(el.PNum(k)); }\n\tparalleltop->SetLoc2Glob_SurfEl (sel+1, pack.sei);\n\tAddSurfaceElement (el);\n\tsel++;\n      }\n    }\n    \n\n\n    {\n      // NgArray<double> segmbuf;\n      // MyMPI_Recv ( segmbuf, 0, NG_MPI_TAG_MESH+5, comm);\n      Array<double> segmbuf;\n      comm.Recv (segmbuf, 0, NG_MPI_TAG_MESH+5);\n\n      Segment seg;\n      int globsegi;\n      int ii = 0;\n      int segi = 1;\n      int nsegloc = int ( segmbuf.Size() / 14 ) ;\n      paralleltop -> SetNSegm ( nsegloc );\n\n      while ( ii < segmbuf.Size() )\n\t{\n\t  globsegi = int (segmbuf[ii++]);\n\t  seg.si = int (segmbuf[ii++]);\n\t  \n\t  seg.pnums[0] = glob2loc_vert_ht.Get (int(segmbuf[ii++]));\n\t  seg.pnums[1] = glob2loc_vert_ht.Get (int(segmbuf[ii++]));\n\t  seg.geominfo[0].trignum = int( segmbuf[ii++] );\n\t  seg.geominfo[1].trignum = int ( segmbuf[ii++]);\n\t  seg.surfnr1 = int ( segmbuf[ii++]);\n\t  seg.surfnr2 = int ( segmbuf[ii++]);\n\t  seg.edgenr = int ( segmbuf[ii++]);\n\t  seg.index = int ( segmbuf[ii++]);          \n\t  seg.epgeominfo[0].dist = segmbuf[ii++];\n\t  seg.epgeominfo[1].edgenr = int (segmbuf[ii++]);\n\t  seg.epgeominfo[1].dist = segmbuf[ii++];\n\t  \n\t  seg.singedge_left = segmbuf[ii++];\n\t  seg.singedge_right = segmbuf[ii++];\n\t  \n\t  seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr;\n\t  \n\t  seg.domin = seg.surfnr1;\n\t  seg.domout = seg.surfnr2;\n\t  if ( seg.pnums[0].IsValid() && seg.pnums[1].IsValid() )\n\t    {\n\t      paralleltop-> SetLoc2Glob_Segm ( segi,  globsegi );\n\t      \n\t      AddSegment (seg);\n\t      segi++;\n\t    }\n\t}\n    }\n\n    { /** 0d-Elements **/\n      Array<PointElPackage> zdes;\n      comm.Recv ( zdes, 0, NG_MPI_TAG_MESH+6);\n      pointelements.SetSize(zdes.Size());\n      for (auto k : Range(pointelements)) {\n\tauto & el = pointelements[k];\n\tel.pnum = glob2loc_vert_ht.Get(zdes[k].pnum);\n\tel.index = zdes[k].index;\n      }\n    }\n\n    // paralleltop -> SetNV_Loc2Glob (0);\n    paralleltop -> EnumeratePointsGlobally();\n    /** Recv bc-names **/\n    /*\n    ArrayMem<int,4> nnames{0,0,0,0};\n    // NG_MPI_Recv(nnames, 4, NG_MPI_INT, 0, NG_MPI_TAG_MESH+6, comm, NG_MPI_STATUS_IGNORE);\n    comm.Recv(nnames, 0, NG_MPI_TAG_MESH+7);\n    */\n\n    // Array<NG_MPI_Request> recvrequests(1);\n    std::array<int,4> nnames;\n    /*\n    recvrequests[0] = comm.IBcast (nnames);\n    MyMPI_WaitAll (recvrequests);\n    */\n    comm.IBcast (nnames).Wait();\n    \n    // cout << \"nnames = \" << FlatArray(nnames) << endl;\n    materials.SetSize(nnames[0]);\n    bcnames.SetSize(nnames[1]);\n    cd2names.SetSize(nnames[2]);\n    cd3names.SetSize(nnames[3]);\n\n    int tot_nn = nnames[0] + nnames[1] + nnames[2] + nnames[3];\n    Array<int> name_sizes(tot_nn);\n    // NG_MPI_Recv(&name_sizes[0], tot_nn, NG_MPI_INT, 0, NG_MPI_TAG_MESH+7, comm, NG_MPI_STATUS_IGNORE);\n    /*\n    recvrequests[0] = comm.IBcast (name_sizes);\n    MyMPI_WaitAll (recvrequests);\n    */\n    comm.IBcast (name_sizes).Wait();\n    \n    int tot_size = 0;\n    for (int k = 0; k < tot_nn; k++) tot_size += name_sizes[k];\n    \n    // NgArray<char> compiled_names(tot_size);\n    // NG_MPI_Recv(&(compiled_names[0]), tot_size, NG_MPI_CHAR, 0, NG_MPI_TAG_MESH+7, comm, NG_MPI_STATUS_IGNORE);\n    Array<char> compiled_names(tot_size);\n    // recvrequests[0] = comm.IBcast (compiled_names);\n    // MyMPI_WaitAll (recvrequests);\n    comm.IBcast (compiled_names).Wait();\n    \n    tot_nn = tot_size = 0;\n    auto write_names = [&] (auto & array) {\n      for (int k = 0; k < array.Size(); k++) {\n\tint s = name_sizes[tot_nn];\n\tarray[k] = s ? new string(&compiled_names[tot_size], s) : new string(\"\");\n\ttot_nn++;\n\ttot_size += s;\n      }\n    };\n    write_names(materials);\n    write_names(bcnames);\n    write_names(cd2names);\n    write_names(cd3names);\n    \n    comm.Barrier();\n\n    int timerloc = NgProfiler::CreateTimer (\"Update local mesh\");\n    int timerloc2 = NgProfiler::CreateTimer (\"CalcSurfacesOfNode\");\n\n    NgProfiler::RegionTimer regloc(timerloc);\n    stringstream str;\n    str << \"p\" << id << \": got \" << GetNE() << \" elements and \" \n\t << GetNSE() << \" surface elements\";\n    PrintMessage(2, str.str());\n    // cout << str.str() << endl;\n    // PrintMessage (2, \"Got \", GetNE(), \" elements and \", GetNSE(), \" surface elements\");\n    // PrintMessage (2, \"Got \", GetNSE(), \" surface elements\");\n\n    NgProfiler::StartTimer (timerloc2);\n\n    CalcSurfacesOfNode ();\n\n    NgProfiler::StopTimer (timerloc2);\n\n    topology.Update();\n    clusters -> Update();\n\n    // paralleltop -> UpdateCoarseGrid();\n    // paralleltop->EnumeratePointsGlobally();\n    SetNextMajorTimeStamp();\n  }\n  \n\n\n  \n  \n  // distribute the mesh to the worker processors\n  // call it only for the master !\n  void Mesh :: Distribute ()\n  {\n    NgMPI_Comm comm = GetCommunicator();\n    int id = comm.Rank();\n    int ntasks = comm.Size();\n\n    if (id != 0 || ntasks == 1 ) return;\n\n#ifdef METIS\n    if (vol_partition.Size() < GetNE() || surf_partition.Size() < GetNSE() ||\n        seg_partition.Size() < GetNSeg())\n      ParallelMetis (comm.Size());\n#else\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      (*this)[ei].SetPartition(ntasks * ei/GetNE() + 1);\n#endif\n\n    /*\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      *testout << \"el(\" << ei << \") is in part \" << (*this)[ei].GetPartition() << endl;\n    for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++)\n      *testout << \"sel(\" << int(ei) << \") is in part \" << (*this)[ei].GetPartition() << endl;\n      */\n    \n    // MyMPI_SendCmd (\"mesh\");\n    SendRecvMesh (); \n  }\n  \n\n#ifdef METIS5\n  void Mesh :: ParallelMetis (int nproc)  \n  {\n    PrintMessage (3, \"call metis 5 ...\");\n\n    int timer = NgProfiler::CreateTimer (\"Mesh::Partition\");\n    NgProfiler::RegionTimer reg(timer);\n\n    idx_t ne = GetNE() + GetNSE() + GetNSeg();\n    idx_t nn = GetNP();\n\n    NgArray<idx_t> eptr, eind;\n    for (int i = 0; i < GetNE(); i++)\n      {\n\teptr.Append (eind.Size());\n\tconst Element & el = VolumeElement(i+1);\n\tfor (int j = 0; j < el.GetNP(); j++)\n\t  eind.Append (el[j]-IndexBASE<PointIndex>());\n      }\n    for (int i = 0; i < GetNSE(); i++)\n      {\n\teptr.Append (eind.Size());\n\tconst Element2d & el = SurfaceElement(i+1);\n\tfor (int j = 0; j < el.GetNP(); j++)\n\t  eind.Append (el[j]-IndexBASE<PointIndex>());\n      }\n    for (int i = 0; i < GetNSeg(); i++)\n      {\n\teptr.Append (eind.Size());\n\tconst Segment & el = LineSegment(i+1);\n\teind.Append (el[0]-IndexBASE<PointIndex>());\n\teind.Append (el[1]-IndexBASE<PointIndex>());\n      }\n    eptr.Append (eind.Size());\n    NgArray<idx_t> epart(ne), npart(nn);\n\n    idxtype nparts = nproc-1; // GetCommunicator().Size()-1;\n\n    vol_partition.SetSize(GetNE());\n    surf_partition.SetSize(GetNSE());\n    seg_partition.SetSize(GetNSeg());\n    if (nparts == 1)\n      {\n        for (int i = 0; i < GetNE(); i++)\n          vol_partition[i]= 1;\n        for (int i = 0; i < GetNSE(); i++)\n          surf_partition[i] = 1;\n        for (int i = 0; i < GetNSeg(); i++)\n          seg_partition[i] = 1;\n      }\n\n    else\n      \n      {\n\n        idxtype edgecut;\n        \n        idxtype ncommon = GetDimension();\n        PrintMessage (3, \"metis start\");\n\n        static Timer tm(\"metis library\");\n        tm.Start();\n        METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts,\n                            NULL, NULL,\n                            &edgecut, &epart[0], &npart[0]);\n        tm.Stop();\n\n        PrintMessage (3, \"metis complete\");\n        \n        for (int i = 0; i < GetNE(); i++)\n          vol_partition[i]= epart[i] + 1;\n        for (int i = 0; i < GetNSE(); i++)\n          surf_partition[i] = epart[i+GetNE()] + 1;\n        for (int i = 0; i < GetNSeg(); i++)\n          seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1;\n      }\n    \n        \n    // surface elements attached to volume elements\n    NgArray<bool, PointIndex::BASE> boundarypoints (GetNP());\n    boundarypoints = false;\n\n    if(GetDimension() == 3)\n      for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n\t{\n\t  const Element2d & el = (*this)[sei];\n\t  for (int j = 0; j < el.GetNP(); j++)\n\t    boundarypoints[el[j]] = true;\n\t}\n    else\n      for (SegmentIndex segi = 0; segi < GetNSeg(); segi++)\n\t{\n\t  const Segment & seg = (*this)[segi];\n\t  for (int j = 0; j < 2; j++)\n\t    boundarypoints[seg[j]] = true;\n\t}\n\n    \n    // Build Pnt2Element table, boundary points only\n    NgArray<int, PointIndex::BASE> cnt(GetNP());\n    cnt = 0;\n\n    auto loop_els_2d = [&](auto f) {\n      for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n\t{\n\t  const Element2d & el = (*this)[sei];\n\t  for (int j = 0; j < el.GetNP(); j++) {\n\t    f(el[j], sei);\n\t  }\n\t}\n    };\n    auto loop_els_3d = [&](auto f) {\n      for (ElementIndex ei = 0; ei < GetNE(); ei++)\n\t{\n\t  const Element & el = (*this)[ei];\n\t  for (int j = 0; j < el.GetNP(); j++)\n\t    f(el[j], ei);\n\t}\n    };\n    auto loop_els = [&](auto f)\n      {\n\tif (GetDimension() == 3 ) \n\t  loop_els_3d(f);\n\telse\n\t  loop_els_2d(f);\n      };\n\n    \n    loop_els([&](auto vertex, int index)\n\t{\n\t  if(boundarypoints[vertex])\n\t    cnt[vertex]++;\n\t});\n    TABLE<int, PointIndex::BASE> pnt2el(cnt);\n    loop_els([&](auto vertex, int index)\n\t{\n\t  if(boundarypoints[vertex])\n\t    pnt2el.Add(vertex, index);\n\t});\n\n\n    if (GetDimension() == 3)\n      {\n\tfor (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n\t  {\n\t    Element2d & sel = (*this)[sei];\n\t    PointIndex pi1 = sel[0];\n\t    // NgFlatArray<ElementIndex> els = pnt2el[pi1];\n\t    NgFlatArray<int> els = pnt2el[pi1];\n\t    \n\t    // sel.SetPartition (-1);\n            surf_partition[sei] = -1;\n\t    \n\t    for (int j = 0; j < els.Size(); j++)\n\t      {\n\t\tconst Element & el = (*this)[ElementIndex(els[j])];\n\t\t\n\t\tbool hasall = true;\n\t\t\n\t\tfor (int k = 0; k < sel.GetNP(); k++)\n\t\t  {\n\t\t    bool haspi = false;\n\t\t    for (int l = 0; l < el.GetNP(); l++)\n\t\t      if (sel[k] == el[l])\n\t\t\thaspi = true;\n\n\t\t    if (!haspi) hasall = false;\n\t\t  }\n\t\t\n\t\tif (hasall)\n\t\t  {\n\t\t    // sel.SetPartition (el.GetPartition());\n                    surf_partition[sei] = vol_partition[ElementIndex(els[j])];\n\t\t    break;\n\t\t  }\n\t      }\n\t    // if (sel.GetPartition() == -1)\n            if (surf_partition[sei] == -1)\n\t      cerr << \"no volume element found\" << endl;\n\t  }\n\n\n\tfor (SegmentIndex si = 0; si < GetNSeg(); si++)\n\t  {\n\t    Segment & sel = (*this)[si];\n\t    PointIndex pi1 = sel[0];\n\t    NgFlatArray<int> els = pnt2el[pi1];\n\t    \n\t    // sel.SetPartition (-1);\n            seg_partition[si] = -1;\n\t    \n\t    for (int j = 0; j < els.Size(); j++)\n\t      {\n\t\tconst Element & el = (*this)[ElementIndex(els[j])];\n\t\t\n\t\tbool haspi[9] = { false };  // max surfnp\n\t\t\n\t\tfor (int k = 0; k < 2; k++)\n\t\t  for (int l = 0; l < el.GetNP(); l++)\n\t\t    if (sel[k] == el[l])\n\t\t      haspi[k] = true;\n\t\t\n\t\tbool hasall = true;\n\t\tfor (int k = 0; k < sel.GetNP(); k++)\n\t\t  if (!haspi[k]) hasall = false;\n\t\t\n\t\tif (hasall)\n\t\t  {\n\t\t    // sel.SetPartition (el.GetPartition());\n                    seg_partition[si] = vol_partition[ElementIndex(els[j])];\n\t\t    break;\n\t\t  }\n\t      }\n\t    // if (sel.GetPartition() == -1)\n            if (seg_partition[si] == -1)\n\t      cerr << \"no volume element found\" << endl;\n\t  }\n      }\n    else\n      {\n\tfor (SegmentIndex segi = 0; segi < GetNSeg(); segi++)\n\t  {\n\t    Segment & seg = (*this)[segi];\n\t    // seg.SetPartition(-1);\n            seg_partition[segi] = -1;\n\t    PointIndex pi1 = seg[0];\n\n\t    NgFlatArray<int> sels = pnt2el[pi1];\n\t    for (int j = 0; j < sels.Size(); j++)\n\t      {\n\t\tSurfaceElementIndex sei = sels[j];\n\t\tElement2d & se = (*this)[sei];\n\t\tbool found = false;\n\t\tfor (int l = 0; l < se.GetNP(); l++ && !found)\n\t\t  found |= (se[l]==seg[1]);\n\t\tif(found) {\n\t\t  // seg.SetPartition(se.GetPartition());\n                  seg_partition[segi] = surf_partition[sei];\n\t\t  break;\n\t\t}\n\t      }\n\t    \n\t    // if (seg.GetPartition() == -1) {\n            if (seg_partition[segi] == -1) {\n\t      cout << endl << \"segi: \" << segi << endl;\n\t      cout << \"points: \" << seg[0] << \" \" << seg[1] << endl;\n\t      cout << \"surfels: \" << endl << sels << endl;\n\t      throw NgException(\"no surface element found\");\n\t    }\n\t  }\n\t\n      }\n  }\n\n#endif\n\n\n\n\n\n//========================== weights =================================================================\n\n\n\n  // distribute the mesh to the worker processors\n  // call it only for the master !\n  void Mesh :: Distribute (NgArray<int> & volume_weights , NgArray<int>  & surface_weights, NgArray<int>  & segment_weights)\n  {\n    NgMPI_Comm comm = GetCommunicator();\n    int id = comm.Rank();\n    int ntasks = comm.Size();\n\n    if (id != 0 || ntasks == 1 ) return;\n\n#ifdef METIS\n    ParallelMetis (volume_weights, surface_weights, segment_weights);\n#else\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      (*this)[ei].SetPartition(ntasks * ei/GetNE() + 1);\n#endif\n\n    /*\n    for (ElementIndex ei = 0; ei < GetNE(); ei++)\n      *testout << \"el(\" << ei << \") is in part \" << (*this)[ei].GetPartition() << endl;\n    for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++)\n      *testout << \"sel(\" << int(ei) << \") is in part \" << (*this)[ei].GetPartition() << endl;\n      */\n    \n    // MyMPI_SendCmd (\"mesh\");\n    SendRecvMesh (); \n  }\n  \n\n#ifdef METIS5\n  void Mesh :: ParallelMetis (NgArray<int> & volume_weights , NgArray<int> & surface_weights, NgArray<int> & segment_weights)  \n  {\n    PrintMessage (3, \"call metis 5 with weights ...\");\n    \n    // cout << \"segment_weights \" << segment_weights << endl;\n    // cout << \"surface_weights \" << surface_weights << endl;\n    // cout << \"volume_weights \" << volume_weights << endl;\n\n    int timer = NgProfiler::CreateTimer (\"Mesh::Partition\");\n    NgProfiler::RegionTimer reg(timer);\n\n    idx_t ne = GetNE() + GetNSE() + GetNSeg();\n    idx_t nn = GetNP();\n    \n    NgArray<idx_t> eptr, eind , nwgt;\n    for (int i = 0; i < GetNE(); i++)\n      {\n\teptr.Append (eind.Size());\n\t\n\tconst Element & el = VolumeElement(i+1);\n\t\n\tint ind = el.GetIndex();\t\n\tif (volume_weights.Size()<ind)\n\t    nwgt.Append(0);\n\telse\n\t    nwgt.Append (volume_weights[ind -1]);\n\t\n\tfor (int j = 0; j < el.GetNP(); j++)\n\t  eind.Append (el[j]-1);\n      }\n    for (int i = 0; i < GetNSE(); i++)\n      {\n\teptr.Append (eind.Size());\n\tconst Element2d & el = SurfaceElement(i+1);\n\t\n\t\n\tint ind = el.GetIndex(); \n\tind = GetFaceDescriptor(ind).BCProperty();\n\tif (surface_weights.Size()<ind)\n\t    nwgt.Append(0);\n\telse\n\t    nwgt.Append (surface_weights[ind -1]);\n\n\t\n\tfor (int j = 0; j < el.GetNP(); j++)\n\t  eind.Append (el[j]-1);\n      }\n    for (int i = 0; i < GetNSeg(); i++)\n      {\n\teptr.Append (eind.Size());\n\t\n\tconst Segment & el = LineSegment(i+1);\t\n\t\n\tint ind = el.si;\n\tif (segment_weights.Size()<ind)\n\t    nwgt.Append(0);\n\telse\n\t    nwgt.Append (segment_weights[ind -1]);\n\t\n\teind.Append (el[0]);\n\teind.Append (el[1]);\n      }\n      \n    eptr.Append (eind.Size());\n    NgArray<idx_t> epart(ne), npart(nn);\n\n    idxtype nparts = GetCommunicator().Size()-1;\n    vol_partition.SetSize(GetNE());\n    surf_partition.SetSize(GetNSE());\n    seg_partition.SetSize(GetNSeg());\n    \n    if (nparts == 1)\n      {\n        for (int i = 0; i < GetNE(); i++)\n          // VolumeElement(i+1).SetPartition(1);\n          vol_partition[i] = 1;\n        for (int i = 0; i < GetNSE(); i++)\n          // SurfaceElement(i+1).SetPartition(1);\n          surf_partition[i] = 1;\n        for (int i = 0; i < GetNSeg(); i++)\n          // LineSegment(i+1).SetPartition(1);\n          seg_partition[i] = 1;\n        return;\n      }\n\n    \n    idxtype edgecut;\n\n\n    idxtype ncommon = 3;\n    METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], &nwgt[0], NULL, &ncommon, &nparts,\n\t\t\tNULL, NULL,\n\t\t\t&edgecut, &epart[0], &npart[0]);\n    /*\n    METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts,\n\t\t\t NULL, NULL,\n\t\t\t &edgecut, &epart[0], &npart[0]);\n    */\n    PrintMessage (3, \"metis complete\");\n    // cout << \"done\" << endl;\n\n    for (int i = 0; i < GetNE(); i++)\n      // VolumeElement(i+1).SetPartition(epart[i] + 1);\n      vol_partition[i] = epart[i] + 1;\n    for (int i = 0; i < GetNSE(); i++)\n      // SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1);\n      surf_partition[i] = epart[i+GetNE()] + 1;\n    for (int i = 0; i < GetNSeg(); i++)\n      // LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1);\n      seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1;\n  }\n#endif \n\n\n\n//===========================================================================================\n\n\n\n\n\n\n\n\n\n#ifdef METIS4\n  void Mesh :: ParallelMetis ( )  \n  {\n    int timer = NgProfiler::CreateTimer (\"Mesh::Partition\");\n    NgProfiler::RegionTimer reg(timer);\n\n    PrintMessage (3, \"Metis called\");\n      \n    if (GetDimension() == 2) \n      {\n\tPartDualHybridMesh2D ( ); // neloc );\n\treturn;\n      }\n\n\n    idx_t ne = GetNE();\n    idx_t nn = GetNP();\n\n    if (ntasks <= 2 || ne <= 1)\n      {\n        if (ntasks == 1) return;\n        \n        for (int i=1; i<=ne; i++)\n          VolumeElement(i).SetPartition(1);\n\n        for (int i=1; i<=GetNSE(); i++)\n          SurfaceElement(i).SetPartition(1);\n\n        return;\n      }\n\n\n    bool uniform_els = true;\n\n    ELEMENT_TYPE elementtype = TET; \n    for (int el = 1; el <= GetNE(); el++)\n      if (VolumeElement(el).GetType() != elementtype)\n\t{\n\t  uniform_els = false;\n\t  break;\n\t}\n\n\n    if (!uniform_els)\n      {\n\tPartHybridMesh ();  \n      }\n    else\n      {\n\t\n\t// uniform (TET) mesh,  JS\n\tint npe = VolumeElement(1).GetNP();\n\tNgArray<idxtype> elmnts(ne*npe);\n\t\n\tint etype;\n\tif (elementtype == TET)\n\t  etype = 2;\n\telse if (elementtype == HEX)\n\t  etype = 3;\n\t\n    \n\tfor (int i=1; i<=ne; i++)\n\t  for (int j=1; j<=npe; j++)\n\t    elmnts[(i-1)*npe+(j-1)] = VolumeElement(i).PNum(j)-1;\n\t\n\tint numflag = 0;\n\tint nparts = ntasks-1;\n\tint ncommon = 3;\n\tint edgecut;\n\tNgArray<idxtype> epart(ne), npart(nn);\n\t\n\t//     if ( ntasks == 1 ) \n\t//       {\n\t// \t(*this) = *mastermesh;\n\t// \tnparts = 4;\t   \n\t// \tmetis :: METIS_PartMeshDual (&ne, &nn, elmnts, &etype, &numflag, &nparts,\n\t// \t\t\t\t     &edgecut, epart, npart);\n\t// \tcout << \"done\" << endl;\n\t\n\t// \tcout << \"edge-cut: \" << edgecut << \", balance: \" << metis :: ComputeElementBalance(ne, nparts, epart) << endl;\n\t\n\t// \tfor (int i=1; i<=ne; i++)\n\t// \t  {\n\t// \t    mastermesh->VolumeElement(i).SetPartition(epart[i-1]);\n\t// \t  }\n\t\n\t// \treturn;\n\t//       }\n\t\n\t\n\tint timermetis = NgProfiler::CreateTimer (\"Metis itself\");\n\tNgProfiler::StartTimer (timermetis);\n\t\n#ifdef METIS4\n\tcout << \"call metis(4)_PartMeshDual ... \" << flush;\n\tMETIS_PartMeshDual (&ne, &nn, &elmnts[0], &etype, &numflag, &nparts,\n\t\t\t    &edgecut, &epart[0], &npart[0]);\n#else\n\tcout << \"call metis(5)_PartMeshDual ... \" << endl;\n\t// idx_t options[METIS_NOPTIONS];\n\t\n\tNgArray<idx_t> eptr(ne+1);\n\tfor (int j = 0; j < ne+1; j++)\n\t  eptr[j] = 4*j;\n\t\n\tMETIS_PartMeshDual (&ne, &nn, &eptr[0], &elmnts[0], NULL, NULL, &ncommon, &nparts,\n\t\t\t    NULL, NULL,\n\t\t\t    &edgecut, &epart[0], &npart[0]);\n#endif\n\t\n\tNgProfiler::StopTimer (timermetis);\n\t\n\tcout << \"complete\" << endl;\n#ifdef METIS4\n\tcout << \"edge-cut: \" << edgecut << \", balance: \" \n\t     << ComputeElementBalance(ne, nparts, &epart[0]) << endl;\n#endif\n\t\n\t// partition numbering by metis : 0 ...  ntasks - 1\n\t// we want:                       1 ...  ntasks\n\tfor (int i=1; i<=ne; i++)\n\t  VolumeElement(i).SetPartition(epart[i-1] + 1);\n      }\n    \n\n    for (int sei = 1; sei <= GetNSE(); sei++ )\n      {\n\tint ei1, ei2;\n\tGetTopology().GetSurface2VolumeElement (sei, ei1, ei2);\n\tElement2d & sel = SurfaceElement (sei);\n\n        for (int j = 0; j < 2; j++)\n          {\n            int ei = (j == 0) ? ei1 : ei2;\n            if ( ei > 0 && ei <= GetNE() )\n              {\n\t\tsel.SetPartition (VolumeElement(ei).GetPartition());\n\t\tbreak;\n\t      }\n\t  }\t\n      }\n    \n  }\n#endif\n\n\n  void Mesh :: PartHybridMesh () \n  {\n    throw Exception(\"PartHybridMesh not supported\");    \n#ifdef METISxxx\n    int ne = GetNE();\n    \n    int nn = GetNP();\n    int nedges = topology.GetNEdges();\n\n    idxtype *xadj, * adjacency;\n    // idxtype *v_weights = NULL, *e_weights = NULL;\n\n    int weightflag = 0;\n    int numflag = 0;\n    int nparts = ntasks - 1;\n\n    int options[5];\n    options[0] = 0;\n    int edgecut;\n    idxtype * part;\n\n    xadj = new idxtype[nn+1];\n    part = new idxtype[nn];\n\n    NgArray<int> cnt(nn+1);\n    cnt = 0;\n\n    for ( int edge = 0; edge < nedges; edge++ )\n      {\n\t// int v1, v2;\n\t// topology.GetEdgeVertices ( edge, v1, v2);\n        auto [v1,v2] = topology.GetEdgeVertices(edge);\n\tcnt[v1-1] ++;\n\tcnt[v2-1] ++;\n      }\n\n    xadj[0] = 0;\n    for ( int n = 1; n <= nn; n++ )\n      {\n\txadj[n] = idxtype(xadj[n-1] + cnt[n-1]); \n      }\n\n    adjacency = new idxtype[xadj[nn]];\n    cnt = 0;\n\n    for ( int edge = 0; edge < nedges; edge++ )\n      {\n\t// int v1, v2;\n\t// topology.GetEdgeVertices ( edge, v1, v2);\n        auto [v1,v2] = topology.GetEdgeVertices(edge);        \n\tadjacency[ xadj[v1-1] + cnt[v1-1] ] = v2-1;\n\tadjacency[ xadj[v2-1] + cnt[v2-1] ] = v1-1;\n\tcnt[v1-1]++;\n\tcnt[v2-1]++;\n      }\n\n    for ( int vert = 0; vert < nn; vert++ )\n      {\n\tNgFlatArray<idxtype> array ( cnt[vert], &adjacency[ xadj[vert] ] );\n\tBubbleSort(array);\n      }\n\n#ifdef METIS4\n    METIS_PartGraphKway ( &nn, xadj, adjacency, v_weights, e_weights, &weightflag, \n\t\t\t  &numflag, &nparts, options, &edgecut, part );\n#else\n    cout << \"currently not supported (metis5), A\" << endl;\n#endif\n\n    NgArray<int> nodesinpart(ntasks);\n    vol_partition.SetSize(ne);\n    for ( int el = 1; el <= ne; el++ )\n      {\n\tElement & volel = VolumeElement(el);\n\tnodesinpart = 0;\n\n\t\n\tint el_np = volel.GetNP();\n\tint partition = 0; \n\tfor ( int i = 0; i < el_np; i++ )\n\t  nodesinpart[ part[volel[i]-1]+1 ] ++;\n\n\tfor ( int i = 1; i < ntasks; i++ )\n\t  if ( nodesinpart[i] > nodesinpart[partition] ) \n\t    partition = i;\n\n\t// volel.SetPartition(partition);\n        vol_partition[el-1] = partition;\n      }\n\n    delete [] xadj;\n    delete [] part;\n    delete [] adjacency;\n#else\n    cout << \"parthybridmesh not available\" << endl;\n#endif\n  }\n\n\n  void Mesh :: PartDualHybridMesh ( ) // NgArray<int> & neloc ) \n  {\n    throw Exception(\"PartDualHybridMesh not supported\");\n#ifdef OLD      \n#ifdef METIS\n    int ne = GetNE();\n    \n    // int nn = GetNP();\n    // int nedges = topology->GetNEdges();\n    int nfaces = topology.GetNFaces();\n\n    idxtype  *xadj, * adjacency, *v_weights = NULL, *e_weights = NULL;\n\n    int weightflag = 0;\n    // int numflag = 0;\n    int nparts = ntasks - 1;\n\n    int options[5];\n    options[0] = 0;\n    int edgecut;\n    idxtype * part;\n\n    NgArray<int, 0> facevolels1(nfaces), facevolels2(nfaces);\n    facevolels1 = -1;\n    facevolels2 = -1;\n\n    // NgArray<int, 0> elfaces;\n    xadj = new idxtype[ne+1];\n    part = new idxtype[ne];\n\n    NgArray<int, 0> cnt(ne+1);\n    cnt = 0;\n\n    for ( int el=1; el <= ne; el++ )\n      {\n\tElement volel = VolumeElement(el);\n\t// topology.GetElementFaces(el, elfaces);\n        auto elfaces = topology.GetFaces (ElementIndex(el-1));\n\tfor ( int i = 0; i < elfaces.Size(); i++ )\n\t  {\n\t    if ( facevolels1[elfaces[i]] == -1 )\n\t      facevolels1[elfaces[i]] = el;\n\t    else\n\t      {\n\t\tfacevolels2[elfaces[i]] = el;\n\t\tcnt[facevolels1[elfaces[i]]-1]++;\n\t\tcnt[facevolels2[elfaces[i]]-1]++;\n\t      }\n\t  }\n      }\n\n    xadj[0] = 0;\n    for ( int n = 1; n <= ne; n++ )\n      {\n\txadj[n] = idxtype(xadj[n-1] + cnt[n-1]); \n      }\n\n    adjacency = new idxtype[xadj[ne]];\n    cnt = 0;\n\n    for ( int face = 1; face <= nfaces; face++ )\n      {\n\tint e1, e2;\n\te1 = facevolels1[face-1];\n\te2 = facevolels2[face-1];\n\tif ( e2 == -1 ) continue;\n\tadjacency[ xadj[e1-1] + cnt[e1-1] ] = e2-1;\n\tadjacency[ xadj[e2-1] + cnt[e2-1] ] = e1-1;\n\tcnt[e1-1]++;\n\tcnt[e2-1]++;\n      }\n\n    for ( int el = 0; el < ne; el++ )\n      {\n\tNgFlatArray<idxtype> array ( cnt[el], &adjacency[ xadj[el] ] );\n\tBubbleSort(array);\n      }\n\n    int timermetis = NgProfiler::CreateTimer (\"Metis itself\");\n    NgProfiler::StartTimer (timermetis);\n\n#ifdef METIS4\n    METIS_PartGraphKway ( &ne, xadj, adjacency, v_weights, e_weights, &weightflag, \n\t\t\t  &numflag, &nparts, options, &edgecut, part );\n#else\n    cout << \"currently not supported (metis5), B\" << endl;\n#endif\n\n\n    NgProfiler::StopTimer (timermetis);\n\n    NgArray<int> nodesinpart(ntasks);\n\n    vol_partition.SetSize(ne);\n    for ( int el = 1; el <= ne; el++ )\n      {\n\t// Element & volel = VolumeElement(el);\n\tnodesinpart = 0;\n\n\t// VolumeElement(el).SetPartition(part[el-1 ] + 1);\n\tvol_partition[el-1] = part[el-1 ] + 1;\n      }\n\n    /*    \n    for ( int i=1; i<=ne; i++)\n      {\n\tneloc[ VolumeElement(i).GetPartition() ] ++;\n      }\n    */\n\n    delete [] xadj;\n    delete [] part;\n    delete [] adjacency;\n#else\n    cout << \"partdualmesh not available\" << endl;\n#endif\n#endif\n    \n  }\n\n\n\n\n\n  void Mesh :: PartDualHybridMesh2D ( ) \n  {\n#ifdef METIS\n    idxtype ne = GetNSE();\n    int nv = GetNV();\n\n    NgArray<idxtype> xadj(ne+1);\n    NgArray<idxtype> adjacency(ne*4);\n\n    // first, build the vertex 2 element table:\n    NgArray<int, PointIndex::BASE> cnt(nv);\n    cnt = 0;\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      for (int j = 0; j < (*this)[sei].GetNP(); j++)\n\tcnt[ (*this)[sei][j] ] ++;\n    \n    TABLE<SurfaceElementIndex, PointIndex::BASE> vert2els(cnt);\n    for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)\n      for (int j = 0; j < (*this)[sei].GetNP(); j++)\n\tvert2els.Add ((*this)[sei][j], sei);\n    \n\n    // find all neighbour elements\n    int cntnb = 0;\n    NgArray<int> marks(ne);   // to visit each neighbour just once\n    marks = -1;\n    for (SurfaceElementIndex sei = 0; sei < ne; sei++)\n      {\n\txadj[sei] = cntnb;\n\tfor (int j = 0; j < (*this)[sei].GetNP(); j++)\n\t  {\n\t    PointIndex vnr = (*this)[sei][j];\n\n\t    // all elements with at least one common vertex\n\t    for (int k = 0; k < vert2els[vnr].Size(); k++)   \n\t      {\n\t\tSurfaceElementIndex sei2 = vert2els[vnr][k];\n\t\tif (sei == sei2) continue;\n\t\tif (marks[sei2] == sei) continue;\n\t\t\n\t\t// neighbour, if two common vertices\n\t\tint common = 0;\n\t\tfor (int m1 = 0; m1 < (*this)[sei].GetNP(); m1++)\n\t\t  for (int m2 = 0; m2 < (*this)[sei2].GetNP(); m2++)\n\t\t    if ( (*this)[sei][m1] == (*this)[sei2][m2])\n\t\t      common++;\n\t\t\n\t\tif (common >= 2)\n\t\t  {\n\t\t    marks[sei2] = sei;     // mark as visited\n\t\t    adjacency[cntnb++] = sei2;\n\t\t  }\n\t      }\n\t  }\n      }\n    xadj[ne] = cntnb;\n\n    idxtype *v_weights = NULL, *e_weights = NULL;\n\n    // int numflag = 0;\n    idxtype nparts = ntasks - 1;\n\n    idxtype edgecut;\n    NgArray<idxtype> part(ne);\n\n    for ( int el = 0; el < ne; el++ )\n      BubbleSort (adjacency.Range (xadj[el], xadj[el+1]));\n\n#ifdef METIS4\t\n    idxtype weightflag = 0;\n    int options[5];\n    options[0] = 0;\n    METIS_PartGraphKway ( &ne, &xadj[0], &adjacency[0], v_weights, e_weights, &weightflag, \n\t\t\t  &numflag, &nparts, options, &edgecut, &part[0] );\n#else\n    idx_t ncon = 1;\n    METIS_PartGraphKway ( &ne, &ncon, &xadj[0], &adjacency[0], \n\t\t\t  v_weights, NULL, e_weights, \n\t\t\t  &nparts, \n\t\t\t  NULL, NULL, NULL,\n\t\t\t  &edgecut, &part[0] );\n#endif\n\n\n    surf_partition.SetSize(ne);\n    for (SurfaceElementIndex sei = 0; sei < ne; sei++)\n      // (*this) [sei].SetPartition (part[sei]+1);\n      surf_partition[sei] = part[sei]+1;\n#else\n    cout << \"partdualmesh not available\" << endl;\n#endif\n\n  }\n\n\n\n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/paralleltop.cpp",
    "content": "#include <meshing.hpp>\n#include \"paralleltop.hpp\"\n\n\nnamespace netgen\n{\n\n  ParallelMeshTopology :: ParallelMeshTopology (const Mesh & amesh)\n    : mesh(amesh)\n  {\n    is_updated = false;\n  }\n \n\n  ParallelMeshTopology :: ~ParallelMeshTopology ()\n  {\n    ;\n  }\n\n\n  void ParallelMeshTopology :: Reset ()\n  {\n    *testout << \"ParallelMeshTopology::Reset\" << endl;\n\n    if ( mesh.GetCommunicator().Size() == 1 ) return;\n\n    size_t ned = mesh.GetTopology().GetNEdges();\n    size_t nfa = mesh.GetTopology().GetNFaces();\n\n    if (glob_edge.Size() != ned)\n      {\n\tglob_edge.SetSize(ned);\n\tglob_face.SetSize(nfa);\n\tglob_edge = -1;\n\tglob_face = -1;\n\n\tloc2distedge.ChangeSize (ned);\n\tloc2distface.ChangeSize (nfa);\n      }\n\n    if (glob_vert.Size() != mesh.GetNV())\n      {\n\tSetNV(mesh.GetNV());\n\tSetNE(mesh.GetNE());\n      }\n  }\n\n\n  void ParallelMeshTopology ::  Print() const\n  {\n    ;\n  }\n\n\n  void ParallelMeshTopology :: EnumeratePointsGlobally ()\n  {\n    auto comm = mesh.GetCommunicator();\n    auto rank = comm.Rank();\n\n    size_t oldnv = glob_vert.Size();\n    size_t nv = loc2distvert.Size();\n    *testout << \"enumerate globally, loc2distvert.size = \" << loc2distvert.Size()\n             << \", glob_vert.size = \" << glob_vert.Size() << endl;\n\n    \n    if (rank == 0)\n      nv = 0;\n\n    // IntRange newvr(oldnv, nv); // new vertex range\n    auto new_pir = Range(PointIndex(oldnv+PointIndex::BASE),\n                         PointIndex(nv+PointIndex::BASE));\n    \n    glob_vert.SetSize (nv);\n    for (auto pi : new_pir)\n      L2G(pi) = -1;\n\n    int num_master_points = 0;\n\n    for (auto pi : new_pir)\n      {\n        auto dps = GetDistantProcs(pi);\n        // check sorted:\n        for (int j = 0; j+1 < dps.Size(); j++)\n          if (dps[j+1] < dps[j]) cout << \"wrong sort\" << endl;\n        \n        if (dps.Size() == 0 || dps[0] > comm.Rank())\n          L2G(pi) = num_master_points++;\n      }\n    \n    // *testout << \"nummaster = \" << num_master_points << endl;\n\n    Array<int> first_master_point(comm.Size());\n    comm.AllGather (num_master_points, first_master_point);\n    auto max_oldv = comm.AllReduce (Max (glob_vert.Range(0, oldnv)), NG_MPI_MAX);\n    if (comm.AllReduce (oldnv, NG_MPI_SUM) == 0)\n      max_oldv = long(PointIndex::BASE)-1;\n    \n    size_t num_glob_points = max_oldv+1;\n    for (int i = 0; i < comm.Size(); i++)\n      {\n        int cur = first_master_point[i];\n        first_master_point[i] = num_glob_points;\n        num_glob_points += cur;\n      }\n    \n    for (auto pi : new_pir)\n      if (L2G(pi) != -1)\n        L2G(pi) += first_master_point[comm.Rank()];\n    \n    // ScatterDofData (global_nums); \n    \n    Array<int> nsend(comm.Size()), nrecv(comm.Size());\n    nsend = 0;\n    nrecv = 0;\n\n    /** Count send/recv size **/\n    for (auto pi : new_pir)\n      if (auto dps = GetDistantProcs(pi); dps.Size())\n        {\n          if (rank < dps[0])\n            for (auto p : dps)\n              nsend[p]++;\n          else\n            nrecv[dps[0]]++;\n        }\n    \n    Table<PointIndex> send_data(nsend);\n    Table<PointIndex> recv_data(nrecv);\n    \n    /** Fill send_data **/\n    nsend = 0;\n    for (auto pi : new_pir)\n      if (auto dps = GetDistantProcs(pi); dps.Size())\n        if (rank < dps[0])\n          for (auto p : dps)\n            send_data[p][nsend[p]++] = L2G(pi);\n\n    NgMPI_Requests requests;\n    for (int i = 0; i < comm.Size(); i++)\n      {\n        if (nsend[i])\n          requests += comm.ISend (send_data[i], i, 200);\n        if (nrecv[i])\n          requests += comm.IRecv (recv_data[i], i, 200);\n      }\n    \n    // MyMPI_WaitAll (requests);\n    requests.WaitAll();\n    \n    Array<int> cnt(comm.Size());\n    cnt = 0;\n\n    for (auto pi : new_pir)\n      if (auto dps = GetDistantProcs(pi); dps.Size())\n        if (int master = dps[0]; master < comm.Rank())\n          L2G(pi) = recv_data[master][cnt[master]++];\n    \n    // reorder following global ordering:\n    Array<int> index0(glob_vert.Size());\n    for (int pi : Range(index0))\n      index0[pi] = pi;\n    QuickSortI (glob_vert, index0);\n\n    if (rank != 0)\n      {\n        Array<PointIndex, PointIndex> inv_index(index0.Size());\n        for (int i = 0; i < index0.Size(); i++)\n          inv_index[index0[i]+PointIndex::BASE] = i+PointIndex::BASE;\n        \n        for (auto & el : mesh.VolumeElements())\n          for (PointIndex & pi : el.PNums())\n            pi = inv_index[pi];\n        for (auto & el : mesh.SurfaceElements())\n          for (PointIndex & pi : el.PNums())\n            pi = inv_index[pi];\n        for (auto & el : mesh.LineSegments())\n          for (PointIndex & pi : el.PNums())\n            pi = inv_index[pi];\n        \n        // auto hpoints (mesh.Points());\n        Array<MeshPoint, PointIndex> hpoints { mesh.Points() };\n        for (PointIndex pi : Range(mesh.Points()))\n          mesh.Points()[inv_index[pi]] = hpoints[pi];\n\n        if (mesh.mlbetweennodes.Size() == mesh.Points().Size())\n          {\n            Array<PointIndices<2>,PointIndex> hml { mesh.mlbetweennodes };\n            for (PointIndex pi : Range(mesh.Points()))\n              mesh.mlbetweennodes[inv_index[pi]] = hml[pi];\n          }\n\n        // *testout << \"index0 = \" << endl << index0 << endl;\n        // *testout << \"loc2distvertold = \" << endl;\n        // for (auto i : Range(index0))\n        // *testout << \"l \" << i << \" globi \"<< glob_vert[i]  << \" dist = \" << loc2distvert[i] << endl;\n\n        DynamicTable<int> oldtable = std::move(loc2distvert);        \n        loc2distvert = DynamicTable<int> (oldtable.Size());\n        for (size_t i = 0; i < oldtable.Size(); i++)\n          for (auto val : oldtable[index0[i]])\n            loc2distvert.Add (i, val);\n\n        Array<int> hglob_vert(glob_vert);\n        for (int i = 0; i < index0.Size(); i++)\n          glob_vert[i] = hglob_vert[index0[i]];\n\n        // *testout << \"loc2distvertnew = \" << endl;\n        // for (auto i : Range(index0))\n        // *testout << \"l \" << i << \" globi \"<< glob_vert[i]  << \" dist = \" << loc2distvert[i] << endl;\n      }\n\n    /*\n    for (size_t i = 0; i+1 < glob_vert.Size(); i++)\n      if (glob_vert[i] > glob_vert[i+1])\n        cout << \"wrong ordering of globvert\" << endl;\n    */\n    if (glob_vert.Size() > 1)\n      for (auto i : Range(glob_vert).Modify(0,-1))\n        if (glob_vert[i] > glob_vert[i+1])\n          cout << \"wrong ordering of globvert\" << endl;\n  }\n  \n  /*\n  void ParallelMeshTopology :: SetDistantFaceNum (int dest, int locnum)\n  {\n    for ( int i = 0; i < loc2distface[locnum-1].Size(); i+=1 )\n      if ( loc2distface[locnum-1][i] == dest )\n\treturn;\n    loc2distface.Add(locnum-1, dest);\n  }\n\n  void ParallelMeshTopology :: SetDistantPNum (int dest, int locnum)\n  {\n    for ( int i = 0;  i < loc2distvert[locnum-1].Size(); i+=1 )\n      if ( loc2distvert[locnum-1][i] == dest )\n\treturn;\n    loc2distvert.Add (locnum-1, dest);  \n  }\n\n\n  void ParallelMeshTopology :: SetDistantEdgeNum (int dest, int locnum)\n  {\n    for ( int i = 0; i < loc2distedge[locnum-1].Size(); i+=1 )\n      if ( loc2distedge[locnum-1][i] == dest )\n\treturn;\n    loc2distedge.Add (locnum-1, dest);\n  }\n  */\n  \n  void ParallelMeshTopology :: SetNV_Loc2Glob (int anv)\n  {\n    glob_vert.SetSize(anv);\n    glob_vert = -1;\n  }\n  \n  void ParallelMeshTopology :: SetNV (int anv)\n  {\n    // glob_vert.SetSize(anv);\n    // glob_vert = -1;\n    // loc2distvert.ChangeSize (anv);\n\n    DynamicTable<int> oldtable(loc2distvert.Size());    \n    for (size_t i = 0; i < loc2distvert.Size(); i++)\n      for (auto val : loc2distvert[i])\n        oldtable.Add (i, val);\n    loc2distvert = DynamicTable<int> (anv);\n    for (size_t i = 0; i < min(size_t(anv), oldtable.Size()); i++)\n      for (auto val : oldtable[i])\n        loc2distvert.Add (i, val);\n  }\n\n  void ParallelMeshTopology :: SetNE ( int ane )\n  {\n    glob_el.SetSize (ane);\n    glob_el = -1;\n  }\n\n  void ParallelMeshTopology :: SetNSE ( int anse )\n  {\n    glob_surfel.SetSize(anse);\n    glob_surfel = -1;\n  }\n\n  void ParallelMeshTopology :: SetNSegm ( int anseg )\n  {\n    glob_segm.SetSize (anseg);\n    glob_segm = -1;\n  }\n\n\n\n\n  /*\n\n  void ParallelMeshTopology :: UpdateCoarseGridGlobal ()\n  {\n    // cout << \"updatecoarsegridglobal called\" << endl;\n    if (id == 0)\n      PrintMessage ( 3, \"UPDATE GLOBAL COARSEGRID STARTS\" );      \n\n    int timer = NgProfiler::CreateTimer (\"UpdateCoarseGridGlobal\");\n    NgProfiler::RegionTimer reg(timer);\n\n    *testout << \"ParallelMeshTopology :: UpdateCoarseGridGlobal\" << endl;\n\n    const MeshTopology & topology = mesh.GetTopology();\n    auto comm = mesh.GetCommunicator();\n\n    if ( id == 0 )\n      {\n\tNgArray<NgArray<int>*> sendarrays(ntasks);\n\tfor (int dest = 1; dest < ntasks; dest++)\n\t  sendarrays[dest] = new NgArray<int>;\n\n\tNgArray<int> edges, faces;\n\tfor (int el = 1; el <= mesh.GetNE(); el++)\n\t  {\n\t    topology.GetElementFaces (el, faces);\n\t    topology.GetElementEdges (el, edges);\n\t    // const Element & volel = mesh.VolumeElement (el);\n\n\t    // NgArray<int> & sendarray = *sendarrays[volel.GetPartition()];\n            NgArray<int> & sendarray = *sendarrays[mesh.vol_partition[el-1]];\n\n\t    for ( int i = 0; i < edges.Size(); i++ )\n\t      sendarray.Append (edges[i]);\n\t    for ( int i = 0; i < faces.Size(); i++ )\n\t      sendarray.Append (faces[i]);\n\t  }\n\n\tfor (int el = 1; el <= mesh.GetNSE(); el++)\n\t  {\n\t    topology.GetSurfaceElementEdges (el, edges);\n\t    // const Element2d & surfel = mesh.SurfaceElement (el);\n\t    // NgArray<int> & sendarray = *sendarrays[surfel.GetPartition()];\n            NgArray<int> & sendarray = *sendarrays[mesh.surf_partition[el-1]];\n\n\t    for ( int i = 0; i < edges.Size(); i++ )\n\t      sendarray.Append (edges[i]);\n\t    sendarray.Append (topology.GetSurfaceElementFace (el));\n\t  }\n\n\tArray<NG_MPI_Request> sendrequests;\n\tfor (int dest = 1; dest < ntasks; dest++)\n\t  // sendrequests.Append (MyMPI_ISend (*sendarrays[dest], dest, NG_MPI_TAG_MESH+10, comm));\n          sendrequests.Append (comm.ISend (FlatArray<int>(*sendarrays[dest]), dest, NG_MPI_TAG_MESH+10));\n\tMyMPI_WaitAll (sendrequests);\n\n\tfor (int dest = 1; dest < ntasks; dest++)\n\t  delete sendarrays[dest];\n      }\n\n    else\n\n      {\n\t// NgArray<int> recvarray;\n\t// MyMPI_Recv (recvarray, 0, NG_MPI_TAG_MESH+10, comm);\n\tArray<int> recvarray;\n\tcomm.Recv (recvarray, 0, NG_MPI_TAG_MESH+10); // MyMPI_Recv (recvarray, 0, NG_MPI_TAG_MESH+10, comm);\n\n\tint ii = 0;\n\n\tNgArray<int> faces, edges;\n\n\tfor (int volel = 1; volel <= mesh.GetNE(); volel++)\n\t  {\n\t    topology.GetElementEdges ( volel, edges);\n\t    for ( int i = 0; i  < edges.Size(); i++)\n\t      SetLoc2Glob_Edge ( edges[i], recvarray[ii++]);\n\n\t    topology.GetElementFaces( volel, faces);\n\t    for ( int i = 0; i  < faces.Size(); i++)\n\t      SetLoc2Glob_Face ( faces[i], recvarray[ii++]);\n\t  }\n\n\tfor (int surfel = 1; surfel <= mesh.GetNSE(); surfel++)\n\t  {\n\t    topology.GetSurfaceElementEdges (surfel, edges);\n\t    for (int i = 0; i  < edges.Size(); i++)\n\t      SetLoc2Glob_Edge (edges[i], recvarray[ii++]);\n\t    int face = topology.GetSurfaceElementFace (surfel);\n\t    SetLoc2Glob_Face ( face, recvarray[ii++]);\n\t  }\n      }\n    \n    is_updated = true;\n  }\n  */\n  \n  \n  void ParallelMeshTopology :: IdentifyVerticesAfterRefinement()\n  {\n    static Timer t(\"ParallelTopology::UpdateCoarseGrid\"); RegionTimer r(t);\n\n    NgMPI_Comm comm = mesh.GetCommunicator();\n    int id = comm.Rank();\n    int ntasks = comm.Size();\n\n    if (ntasks == 1) return;\n    \n    Reset();\n    static int timer = NgProfiler::CreateTimer (\"UpdateCoarseGrid\");\n    NgProfiler::RegionTimer reg(timer);\n\n\n    (*testout) << \"UPDATE COARSE GRID PARALLEL TOPOLOGY \" << endl;\n    if (id == 0)\n      PrintMessage (1, \"update parallel topology\");\n    \n    \n    // const MeshTopology & topology = mesh.GetTopology();\n\n    Array<int> cnt_send(ntasks);\n\n    int maxsize = comm.AllReduce (mesh.mlbetweennodes.Size(), NG_MPI_MAX);\n    // update new vertices after mesh-refinement\n    if (maxsize > 0)\n      {\n        int newnv = mesh.mlbetweennodes.Size();\n        \n        loc2distvert.ChangeSize(mesh.mlbetweennodes.Size());\n\n\tbool changed = true;\n\twhile (changed)\n\t  {\n\t    changed = false;\n\n\t    // build exchange vertices\n\t    cnt_send = 0;\n\t    for (PointIndex pi : mesh.Points().Range())\n\t      for (int dist : GetDistantProcs(pi))\n\t\tcnt_send[dist]++;\n            // TABLE<int> dest2vert(cnt_send);    \n\t    DynamicTable<int> dest2vert(cnt_send);    \n\t    for (PointIndex pi : mesh.Points().Range())\n\t      for (int dist : GetDistantProcs(pi))\n\t\tdest2vert.Add (dist, pi);\n            \n\t    for (PointIndex pi = IndexBASE<PointIndex>(); pi < newnv+IndexBASE<PointIndex>(); pi++)\n              if (auto [v1,v2] = mesh.mlbetweennodes[pi]; v1.IsValid())              \n                {\n                  auto procs1 = GetDistantProcs(v1);\n                  auto procs2 = GetDistantProcs(v2);\n                  for (int p : procs1)\n                    if (procs2.Contains(p))\n                      cnt_send[p]++;\n                }\n\n\t    // TABLE<int> dest2pair(cnt_send);\n            DynamicTable<int> dest2pair(cnt_send);            \n            \n            for (PointIndex pi : mesh.mlbetweennodes.Range())\n              if (auto [v1,v2] = mesh.mlbetweennodes[pi]; v1.IsValid())\n                {\n                  auto procs1 = GetDistantProcs(v1);\n                  auto procs2 = GetDistantProcs(v2);\n                  for (int p : procs1)\n                    if (procs2.Contains(p))\n                      dest2pair.Add (p, pi);\n                }\n\n\t    cnt_send = 0;\n\t    for (PointIndex pi : mesh.mlbetweennodes.Range())\n              if (auto [v1,v2] = mesh.mlbetweennodes[pi]; v1.IsValid())\n                {\n                  auto procs1 = GetDistantProcs(v1);\n                  auto procs2 = GetDistantProcs(v2);\n                  \n                  for (int p : procs1)\n                    if (procs2.Contains(p))\n                      cnt_send[p]+=2;\n                }\n\t    \n\t    // TABLE<int> send_verts(cnt_send);\n            DynamicTable<int> send_verts(cnt_send);\n\n\t    NgArray<int, PointIndex::BASE> loc2exchange(mesh.GetNV());\n\n\t    for (int dest = 0; dest < ntasks; dest++)\n\t      if (dest != id)\n\t\t{\n\t\t  loc2exchange = -1;\n\t\t  int cnt = 0;\n\t\t  for (PointIndex pi : dest2vert[dest])\n\t\t    loc2exchange[pi] = cnt++;\n\t\t  \n\t\t  for (PointIndex pi : dest2pair[dest])\n                    if (auto [v1,v2] = mesh.mlbetweennodes[pi]; v1.IsValid())                    \n                      {\n                        auto procs1 = GetDistantProcs(v1);\n                        auto procs2 = GetDistantProcs(v2);\n                        \n                        if (procs1.Contains(dest) && procs2.Contains(dest))\n                          {\n                            send_verts.Add (dest, loc2exchange[v1]);\n                            send_verts.Add (dest, loc2exchange[v2]);\n                          }\n                      }\n\t\t}\n\n\t    DynamicTable<int> recv_verts(ntasks);\n            comm.ExchangeTable (send_verts, recv_verts, NG_MPI_TAG_MESH+9);\n\n\t    for (int dest = 0; dest < ntasks; dest++)\n\t      if (dest != id)\n\t\t{\n\t\t  loc2exchange = -1;\n\t\t  int cnt = 0;\n\n\t\t  for (PointIndex pi : dest2vert[dest])\n\t\t    loc2exchange[pi] = cnt++;\n\t\t  \n\t\t  FlatArray<int> recvarray = recv_verts[dest];\n\t\t  for (int ii = 0; ii < recvarray.Size(); ii+=2)\n\t\t    for (PointIndex pi : dest2pair[dest])\n\t\t      {\n\t\t\tPointIndex v1 = mesh.mlbetweennodes[pi][0];\n\t\t\tPointIndex v2 = mesh.mlbetweennodes[pi][1];\n\t\t\tif (v1.IsValid())\n\t\t\t  {\n\t\t\t    INDEX_2 re(recvarray[ii], recvarray[ii+1]);\n\t\t\t    INDEX_2 es(loc2exchange[v1], loc2exchange[v2]);\n\t\t\t    // if (es == re && !IsExchangeVert(dest, pi))\n                            if (es == re && !GetDistantProcs(pi).Contains(dest))\n\t\t\t      {\n\t\t\t\t// SetDistantPNum(dest, pi);\n                                AddDistantProc (pi, dest);\n\t\t\t\tchanged = true;\n\t\t\t      }\n\t\t\t  }\n\t\t      }\n\t\t}\n\n            changed = comm.AllReduce (changed, NG_MPI_LOR);\n\t  }\n      }\n\n    NgArray<int> sendarray, recvarray;\n    // cout << \"UpdateCoarseGrid - edges\" << endl;\n\n    // static int timerv = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex vertices\");\n    static int timere = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex edges\");\n    // static int timerf = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex faces\");\n\n    \n    NgProfiler::StartTimer (timere);\n\n    // build exchange vertices\n    cnt_send = 0;\n    for (PointIndex pi : mesh.Points().Range())\n      for (int dist : GetDistantProcs(pi))\n\tcnt_send[dist]++;\n    // TABLE<int> dest2vert(cnt_send);\n    DynamicTable<int> dest2vert(cnt_send);    \n    for (PointIndex pi : mesh.Points().Range())\n      for (int dist : GetDistantProcs(pi))\n\tdest2vert.Add (dist, pi);\n    \n    // NG_MPI_Group_free(&NG_MPI_LocalGroup);\n    // NG_MPI_Comm_free(&NG_MPI_LocalComm);\n  }\n\n\n  void ParallelMeshTopology :: UpdateCoarseGrid ()\n  {\n    static Timer t(\"ParallelTopology::UpdateCoarseGrid\"); RegionTimer r(t);\n    // cout << \"UpdateCoarseGrid\" << endl;\n    // if (is_updated) return;\n\n    NgMPI_Comm comm = mesh.GetCommunicator();\n    int id = comm.Rank();\n    int ntasks = comm.Size();\n\n    if (ntasks == 1) return;\n    \n    Reset();\n    static int timer = NgProfiler::CreateTimer (\"UpdateCoarseGrid\");\n    NgProfiler::RegionTimer reg(timer);\n\n\n    (*testout) << \"UPDATE COARSE GRID PARALLEL TOPOLOGY \" << endl;\n    if (id == 0)\n      PrintMessage (1, \"update parallel topology\");\n\n\n    // UpdateCoarseGridGlobal();\n\n\n    /*\n    // MPI_Barrier (MPI_COMM_WORLD);\n\n    MPI_Group MPI_GROUP_comm;\n    MPI_Group MPI_LocalGroup;\n    MPI_Comm MPI_LocalComm;\n\n    int process_ranks[] = { 0 };\n    MPI_Comm_group (comm, &MPI_GROUP_comm);\n    MPI_Group_excl (MPI_GROUP_comm, 1, process_ranks, &MPI_LocalGroup);\n    MPI_Comm_create (comm, MPI_LocalGroup, &MPI_LocalComm);\n\n    if (id == 0)\n      {\n        // SetNV(0);\n        // EnumeratePointsGlobally();\n        return;\n      }\n    */\n    \n    const MeshTopology & topology = mesh.GetTopology();\n\n    Array<int> cnt_send(ntasks);\n\n    // NgArray<int> sendarray, recvarray;\n    // cout << \"UpdateCoarseGrid - edges\" << endl;\n\n    // static int timerv = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex vertices\");\n    static int timere = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex edges\");\n    static int timerf = NgProfiler::CreateTimer (\"UpdateCoarseGrid - ex faces\");\n\n\n    NgProfiler::StartTimer (timere);\n\n\n    int nfa = topology . GetNFaces();\n    int ned = topology . GetNEdges();\n    \n    // build exchange vertices\n    cnt_send = 0;\n    for (PointIndex pi : mesh.Points().Range())\n      for (int dist : GetDistantProcs(pi))\n\tcnt_send[dist]++;\n    // TABLE<int> dest2vert(cnt_send);\n    DynamicTable<int> dest2vert(cnt_send);    \n    for (PointIndex pi : mesh.Points().Range())\n      for (int dist : GetDistantProcs(pi))\n\tdest2vert.Add (dist, pi);\n\n    // exchange edges\n    cnt_send = 0;\n    // int v1, v2;\n    for (int edge = 1; edge <= ned; edge++)\n      {\n\t// topology.GetEdgeVertices (edge, v1, v2);\n        auto [v1,v2] = topology.GetEdgeVertices(edge-1);\n        /*\n\tfor (int dest = 1; dest < ntasks; dest++)\n\t  // if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2))\n          if (GetDistantProcs(v1).Contains(dest) && GetDistantProcs(v2).Contains(dest))\n\t    cnt_send[dest-1]+=1;\n        */\n        for (auto p : GetDistantProcs(v1))\n          if (GetDistantProcs(v2).Contains(p))\n\t    cnt_send[p]+=1;\n      }\n    \n    // TABLE<int> dest2edge(cnt_send);\n    DynamicTable<int> dest2edge(cnt_send);\n    for (int & v : cnt_send) v *= 2;\n    // TABLE<int> send_edges(cnt_send);\n    DynamicTable<int> send_edges(cnt_send);\n\n    for (int edge = 1; edge <= ned; edge++)\n      {\n\t// topology.GetEdgeVertices (edge, v1, v2);\n        auto [v1,v2] = topology.GetEdgeVertices(edge-1);        \n\tfor (int dest = 0; dest < ntasks; dest++)\n\t  // if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2))\n          if (GetDistantProcs(v1).Contains(dest) && GetDistantProcs(v2).Contains(dest))\n\t    dest2edge.Add (dest, edge);\n      }\n\n\n    NgArray<int, PointIndex::BASE> loc2exchange(mesh.GetNV());\n    for (int dest = 0; dest < ntasks; dest++)\n      {\n        loc2exchange = -1;\n        int cnt = 0;\n        for (PointIndex pi : dest2vert[dest])\n\t  loc2exchange[pi] = cnt++;\n\n\tfor (int edge : dest2edge[dest])\n          {\n            // topology.GetEdgeVertices (edge, v1, v2);\n            auto [v1,v2] = topology.GetEdgeVertices(edge-1);            \n            // if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2))\n            if (GetDistantProcs(v1).Contains(dest) && GetDistantProcs(v2).Contains(dest))            \n              {\n                send_edges.Add (dest, loc2exchange[v1]);\n                send_edges.Add (dest, loc2exchange[v2]);\n              }\n          }\n      }\n\n    DynamicTable<int> recv_edges(ntasks);\n    comm.ExchangeTable (send_edges, recv_edges, NG_MPI_TAG_MESH+9);\n\n    for (int dest = 0; dest < ntasks; dest++)\n      {\n\tauto ex2loc = dest2vert[dest];\n\tif (ex2loc.Size() == 0) continue;\n\n\tINDEX_2_CLOSED_HASHTABLE<int> vert2edge(2*dest2edge[dest].Size()+10); \n\tfor (int edge : dest2edge[dest])\n\t  {\n\t    // topology.GetEdgeVertices (edge, v1, v2);\n            auto [v1,v2] = topology.GetEdgeVertices(edge-1);            \n\t    vert2edge.Set(INDEX_2(v1,v2), edge);\n\t  }\n\n\tFlatArray<int> recvarray = recv_edges[dest];\n        for (int ii = 0; ii < recvarray.Size(); ii+=2)\n\t  {\n\t    INDEX_2 re(ex2loc[recvarray[ii]], \n\t\t       ex2loc[recvarray[ii+1]]);\n\t    if (vert2edge.Used(re))\n\t      // SetDistantEdgeNum(dest, vert2edge.Get(re));\n              AddDistantEdgeProc(vert2edge.Get(re)-1, dest);\n\t  }\n      }\n\n\n\n    NgProfiler::StopTimer (timere);\n\n    // cout << \"UpdateCoarseGrid - faces\" << endl;\n    if (mesh.GetDimension() == 3)\n      {\n\tNgProfiler::StartTimer (timerf);\n\tNgArray<int> verts;\n\n\t// exchange faces\n\tcnt_send = 0;\n\tfor (int face = 1; face <= nfa; face++)\n\t  {\n\t    topology.GetFaceVertices (face, verts);\n\t    for (int dest = 0; dest < ntasks; dest++)\n\t      if (dest != id)\n                /*\n\t\tif (IsExchangeVert (dest, verts[0]) && \n\t\t    IsExchangeVert (dest, verts[1]) &&\n\t\t    IsExchangeVert (dest, verts[2]))\n                */\n                if (GetDistantProcs (verts[0]).Contains(dest) &&\n                    GetDistantProcs (verts[1]).Contains(dest) &&\n                    GetDistantProcs (verts[2]).Contains(dest))\n\t\t  cnt_send[dest]++;\n\t  }\n\t\n\t// TABLE<int> dest2face(cnt_send);\n        DynamicTable<int> dest2face(cnt_send);\n\tfor (int face = 1; face <= nfa; face++)\n\t  {\n\t    topology.GetFaceVertices (face, verts);\n\t    for (int dest = 0; dest < ntasks; dest++)\n\t      if (dest != id)\n                /*\n\t\tif (IsExchangeVert (dest, verts[0]) && \n\t\t    IsExchangeVert (dest, verts[1]) &&\n\t\t    IsExchangeVert (dest, verts[2]))\n                */\n                if (GetDistantProcs (verts[0]).Contains(dest) && \n                    GetDistantProcs (verts[1]).Contains(dest) &&\n                    GetDistantProcs (verts[2]).Contains(dest))\n\t\t  dest2face.Add(dest, face);\n\t  }\n\n\tfor (int & c : cnt_send) c*=3;\n\t// TABLE<int> send_faces(cnt_send);\n        DynamicTable<int> send_faces(cnt_send);\n\tNgArray<int, PointIndex::BASE> loc2exchange(mesh.GetNV());\n\tfor (int dest = 0; dest < ntasks; dest++)\n\t  if (dest != id)\n\t    {\n\t      if (dest2vert[dest].Size() == 0) continue;\n\n\t      loc2exchange = -1;\n\t      int cnt = 0;\n\t      for (PointIndex pi : dest2vert[dest])\n\t\tloc2exchange[pi] = cnt++;\n\t      \n\t      for (int face : dest2face[dest])\n\t\t{\n\t\t  topology.GetFaceVertices (face, verts);\n                  /*\n\t\t  if (IsExchangeVert (dest, verts[0]) && \n\t\t      IsExchangeVert (dest, verts[1]) &&\n\t\t      IsExchangeVert (dest, verts[2]))\n                  */\n                  if (GetDistantProcs (verts[0]).Contains(dest) &&\n                      GetDistantProcs (verts[1]).Contains(dest) &&\n                      GetDistantProcs (verts[2]).Contains(dest))\n\t\t    {\n\t\t      send_faces.Add (dest, loc2exchange[verts[0]]);\n\t\t      send_faces.Add (dest, loc2exchange[verts[1]]);\n\t\t      send_faces.Add (dest, loc2exchange[verts[2]]);\n\t\t    }\n\t\t}\n\t    }\n\t\n\tDynamicTable<int> recv_faces(ntasks);\n        comm.ExchangeTable (send_faces, recv_faces, NG_MPI_TAG_MESH+9);\n\t\n\tfor (int dest = 0; dest < ntasks; dest++)\n\t  {\n\t    auto ex2loc = dest2vert[dest];\n\t    if (ex2loc.Size() == 0) continue;\n\t    \n\t    INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*dest2face[dest].Size()+10); \n\t    for (int face : dest2face[dest])\n\t      {\n\t\ttopology.GetFaceVertices (face, verts);\n\t\tvert2face.Set(INDEX_3(verts[0], verts[1], verts[2]), face);\n\t      }\n\t    \n\t    FlatArray<int> recvarray = recv_faces[dest];\n\t    for (int ii = 0; ii < recvarray.Size(); ii+=3)\n\t      {\n\t\tINDEX_3 re(ex2loc[recvarray[ii]], \n\t\t\t   ex2loc[recvarray[ii+1]],\n\t\t\t   ex2loc[recvarray[ii+2]]);\n\t\tif (vert2face.Used(re))\n\t\t  AddDistantFaceProc(vert2face.Get(re)-1, dest);\n\t      }\n\t  }\n\t\n\tNgProfiler::StopTimer (timerf);\n      }\n    // cout << \"UpdateCoarseGrid - done\" << endl;\n    // EnumeratePointsGlobally();\n    is_updated = true;\n\n    // NG_MPI_Group_free(&NG_MPI_LocalGroup);\n    // NG_MPI_Comm_free(&NG_MPI_LocalComm);\n  }\n}\n\n\n"
  },
  {
    "path": "libsrc/meshing/paralleltop.hpp",
    "content": "#ifndef FILE_PARALLELTOP\n#define FILE_PARALLELTOP\n\nnamespace netgen\n{\n\n\n  class ParallelMeshTopology\n  {\n    const Mesh & mesh;\n\n    /**\n       mapping from local to distant vertex number\n       each row of the table corresponds to one vertex\n       each row contains a list of pairs (procnr, dist_vnum)\n    */\n    \n    DynamicTable<int> loc2distvert;\n    DynamicTable<int> loc2distedge, loc2distface;\n\n    Array<int> glob_vert;\n\n    // will get rid of them\n    NgArray<int> glob_edge, glob_face;\n    NgArray<int> glob_el, glob_surfel, glob_segm;\n\n    bool is_updated;\n\n  public:\n\n    ParallelMeshTopology (const Mesh & amesh);\n    ~ParallelMeshTopology ();\n\n    void Reset ();\n    void Print() const;\n\n    \n    void UpdateCoarseGrid();\n    // [[deprecated(\"should not need it anymore\")]]                    \n    // void UpdateCoarseGridGlobal();\n    void IdentifyVerticesAfterRefinement();\n    void EnumeratePointsGlobally ();\n        \n    void AddDistantProc    (PointIndex pi, int proc) { loc2distvert.AddUnique (pi-IndexBASE<PointIndex>(), proc); }\n    void AddDistantFaceProc (int edge, int proc) { loc2distface.AddUnique (edge, proc); }\n    void AddDistantEdgeProc (int face, int proc) { loc2distedge.AddUnique (face, proc); }\n    \n    FlatArray<int> GetDistantProcs (PointIndex pi) const { return loc2distvert[pi-IndexBASE<PointIndex>()]; }\n    FlatArray<int> GetDistantFaceProcs (int locnum) const { return loc2distface[locnum]; }\n    FlatArray<int> GetDistantEdgeProcs (int locnum) const { return loc2distedge[locnum]; }\n\n\n    \n    auto & L2G (PointIndex pi) { return glob_vert[pi-IndexBASE<PointIndex>()]; } \n    auto L2G (PointIndex pi) const { return glob_vert[pi-IndexBASE<PointIndex>()]; } \n\n\n    /// set number of local vertices, reset sizes of loc2dist_vert, isexchangevert...\n    void SetNV (int anv);\n    void SetNV_Loc2Glob (int anv);\n    void SetNE (int ane);\n    void SetNSE (int anse);\n    void SetNSegm (int anseg);\n\n    [[deprecated(\"Use AddDistantFaceProc instead!\")]]                \n    void SetDistantFaceNum (int dest, int locnum) { loc2distface.AddUnique (locnum-1, dest); }\n    [[deprecated(\"Use AddDistantProc instead!\")]]                \n    void SetDistantPNum    (int dest, int locnum) { loc2distvert.AddUnique (locnum-1, dest); }\n    [[deprecated(\"Use AddDistantEdgeProc instead!\")]]                \n    void SetDistantEdgeNum (int dest, int locnum) { loc2distedge.AddUnique (locnum-1, dest); }\n\n    [[deprecated(\"Use GetDistantFaceProcx instead!\")]]                    \n    FlatArray<int> GetDistantFaceNums (int locnum) const { return loc2distface[locnum]; }\n    [[deprecated(\"Use GetDistantEdgeProcx instead!\")]]\n    FlatArray<int> GetDistantEdgeNums (int locnum) const { return loc2distedge[locnum]; }\n\n\n    \n    [[deprecated(\"Use L2G(pi) instead!\")]]                \n    void SetLoc2Glob_Vert   (int locnum, int globnum) { glob_vert[locnum-1] = globnum; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    void SetLoc2Glob_Edge   (int locnum, int globnum) { glob_edge[locnum-1] = globnum; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    void SetLoc2Glob_Face   (int locnum, int globnum) { glob_face[locnum-1] = globnum; }\n    // [[deprecated(\"Try to avoid global enumration!\")]]                \n    void SetLoc2Glob_VolEl  (int locnum, int globnum) { glob_el[locnum-1] = globnum; }\n    // [[deprecated(\"Try to avoid global enumration!\")]]                \n    void SetLoc2Glob_SurfEl (int locnum, int globnum) { glob_surfel[locnum-1] = globnum; }\n    // [[deprecated(\"Try to avoid global enumration!\")]]                \n    void SetLoc2Glob_Segm   (int locnum, int globnum) { glob_segm[locnum-1] = globnum; }\n\n    // [[deprecated(\"Try to avoid global enumration!\")]]                    \n    int GetGlobalPNum    (PointIndex locnum) const { return glob_vert[locnum-IndexBASE<PointIndex>()]; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    int GetGlobalEdgeNum (int locnum) const { return glob_edge[locnum-1]; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    int GetGlobalFaceNum (int locnum) const { return glob_face[locnum-1]; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    int GetGlobalElNum   (int locnum) const { return glob_el[locnum-1]; }\n    [[deprecated(\"Try to avoid global enumration!\")]]                \n    int GetGlobalSElNum  (int locnum) const { return glob_surfel[locnum-1]; }\n\n    \n\n    // [[deprecated(\"Use GetDistantPNums(locnum).Size() instead!\")]]            \n    int GetNDistantPNums (int locpnum) const { return loc2distvert[locpnum-1].Size(); }\n\n    // [[deprecated(\"Use GetDistantFaceNums(locnum).Size() instead!\")]]                \n    int GetNDistantFaceNums (int locfacenum) const { return loc2distface[locfacenum-1].Size(); }\n\n    // [[deprecated(\"Use GetDistantEdgeNums(locnum).Size() instead!\")]]                    \n    int GetNDistantEdgeNums ( int locedgenum) const { return loc2distedge[locedgenum-1].Size(); }\n\n    // [[deprecated(\"Use GetDistantPNums(locnum) -> FlatArray instead!\")]]                \n    void GetDistantPNums (int locpnum, int * distpnums ) const\n    {\n      for (int i = 0; i < loc2distvert[locpnum-1].Size(); i++ )\n\tdistpnums[i] = loc2distvert[locpnum-1][i];\n    } \n\n    // [[deprecated(\"Use GetDistantFaceNums(locnum) -> FlatArray instead!\")]]                    \n    void GetDistantFaceNums (int locfacenum, int * distfacenums ) const\n    {\n      for ( int i = 0; i < loc2distface[locfacenum-1].Size(); i++ )\n\tdistfacenums[i] = loc2distface[locfacenum-1][i];\n    } \n\n    // [[deprecated(\"Use GetDistantFaceNums(locnum) -> FlatArray instead!\")]]                        \n    void GetDistantFaceNums (int locfacenum, NgArray<int> & distfacenums ) const\n    {\n      // distfacenums = loc2distface[locfacenum-1];\n      auto loc = loc2distface[locfacenum-1];\n      distfacenums.SetSize (loc.Size());\n      for (int i = 0; i < loc.Size(); i++)\n        distfacenums[i] = loc[i];\n    }\n\n    // [[deprecated(\"Use GetDistantEdgeNums(locnum) -> FlatArray instead!\")]]                            \n    void GetDistantEdgeNums (int locedgenum, int * distedgenums ) const\n    {\n      for (int i = 0; i < loc2distedge[locedgenum-1].Size(); i++ )\n\tdistedgenums[i] = loc2distedge[locedgenum-1][i];\n    } \n\n    // [[deprecated(\"Use GetDistantEdgeNums(locnum) -> FlatArray instead!\")]]                                \n    void GetDistantEdgeNums (int locedgenum, NgArray<int> & distedgenums ) const\n    {\n      // distedgenums = loc2distedge[locedgenum-1];\n      auto loc = loc2distedge[locedgenum-1];\n      distedgenums.SetSize (loc.Size());\n      for (int i = 0; i < loc.Size(); i++)\n        distedgenums[i] = loc[i];\n    } \n\n    [[deprecated(\"Use GetDistantProcs(..)!\")]]                    \n    FlatArray<int> GetDistantPNums (int locnum) const { return loc2distvert[locnum]; }\n\n\n    \n    [[deprecated(\"Use GetDistantProcs(..).Contains instead!\")]]                \n    bool IsExchangeVert (int dest, int vnum) const\n    {\n      return loc2distvert[vnum-1].Contains (dest);\n    }\n  };\n\n}\n\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/parser2.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n#ifdef WIN32\n#define COMMASIGN ':'\n#else\n#define COMMASIGN ','\n#endif\n\n\nnamespace netgen\n{\n\n\nvoid LoadMatrixLine (istream & ist, DenseMatrix & m, int line)\n{\n  char ch;\n  int pnum;\n  float f;\n\n  ist >> ch;\n  while (ch != '}')\n    {\n      ist.putback (ch);\n      ist >> f;\n      ist >> ch;\n      ist >> pnum;\n\n      if (ch == 'x' || ch == 'X')\n\tm.Elem(line, 2 * pnum - 1) = f;\n      if (ch == 'y' || ch == 'Y')\n\tm.Elem(line, 2 * pnum) = f;\n\n      ist >> ch;\n      if (ch == COMMASIGN)\n\tist >> ch;\n    }\n}\n\n\nvoid netrule :: LoadRule (istream & ist)\n{\n  char buf[256];\n  char ch;\n  Point<2> p;\n  INDEX_2 lin;\n  int i, j;\n  DenseMatrix tempoldutonewu(20, 20), tempoldutofreearea(20, 20),\n    tempoldutofreearealimit(20, 20);\n\n  tempoldutonewu = 0;\n  tempoldutofreearea = 0;\n  tempoldutofreearealimit = 0;\n\n  noldp = 0;\n  noldl = 0;\n\n  ist.get (buf, sizeof(buf), '\"');\n  ist.get (ch);\n  ist.get (buf, sizeof(buf), '\"');\n  ist.get (ch);\n\n  // if(name != NULL)\n  /*\n  delete [] name;\n  name = new char[strlen (buf) + 1];\n  strcpy (name, buf);\n  */\n  name = string(buf);\n  //(*testout) << \"name \" << name << endl;\n  //  (*mycout) << \"Rule \" << name << \" found.\" << endl;\n\n  do\n    {\n      ist >> buf;\n\n      //(*testout) << \"buf \" << buf << endl;\n\n      if (strcmp (buf, \"quality\") == 0)\n\n\t{\n\t  ist >> quality;\n\t}\n\n      else if (strcmp (buf, \"mappoints\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> p[0];\n\t      ist >> ch;    // ','\n\t      ist >> p[1];\n\t      ist >> ch;    // ')'\n\n\t      points.Append (p);\n\t      noldp++;\n\n\t      tolerances.SetSize (noldp);\n\t      tolerances.Elem(noldp).f1 = 1.0;\n\t      tolerances.Elem(noldp).f2 = 0;\n\t      tolerances.Elem(noldp).f3 = 1.0;\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      ist >> tolerances.Elem(noldp).f1;\n\t\t      ist >> ch;  // ','\n\t\t      ist >> tolerances.Elem(noldp).f2;\n\t\t      ist >> ch;  // ','\n\t\t      ist >> tolerances.Elem(noldp).f3;\n\t\t      ist >> ch;  // '}'\n\t\t    }\n\t\t  else if (ch == 'd')\n\t\t    {\n\t\t      //            delpoints.Append (noldp);\n\t\t      ist >> ch; // 'e'\n\t\t      ist >> ch; // 'l'\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n\n      else if (strcmp (buf, \"maplines\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> lin.I1();\n\t      ist >> ch;    // ','\n\t      ist >> lin.I2();\n\t      ist >> ch;    // ')'\n\n\n\t      //(*testout) << \"read line \" << lin.I1() << \" \" << lin.I2() << endl;\n\t      lines.Append (lin);\n\t      linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1()));\n\t      noldl++;\n\t      linetolerances.SetSize (noldl);\n\t      linetolerances.Elem(noldl).f1 = 0;\n\t      linetolerances.Elem(noldl).f2 = 0;\n\t      linetolerances.Elem(noldl).f3 = 0;\n\n\t      //(*testout) << \"mapl1\" << endl; \n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  //(*testout) << \"working on character \\\"\"<<ch<<\"\\\"\"<< endl;\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      ist >> linetolerances.Elem(noldl).f1;\n\t\t      ist >> ch;  // ','\n\t\t      ist >> linetolerances.Elem(noldl).f2;\n\t\t      ist >> ch;  // ','\n\t\t      ist >> linetolerances.Elem(noldl).f3;\n\t\t      ist >> ch;  // '}'\n\t\t    }\n\t\t  else if (ch == 'd')\n\t\t    {\n\t\t      dellines.Append (noldl);\n\t\t      ist >> ch; // 'e'\n\t\t      ist >> ch; // 'l'\n\t\t      //(*testout) << \"read del\" << endl;\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t  //(*testout) << \"read character \\\"\"<<ch<<\"\\\"\"<< endl;\n\t\t}\n\n\t      ist >> ch;\n\t      //(*testout) << \"read next character \\\"\"<<ch<<\"\\\"\"<< endl;\n\t    }\n\t  \n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"newpoints\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> p[0];\n\t      ist >> ch;    // ','\n\t      ist >> p[1];\n\t      ist >> ch;    // ')'\n\n\t      points.Append (p);\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      LoadMatrixLine (ist, tempoldutonewu,\n\t\t\t\t      2 * (points.Size()-noldp) - 1);\n\n\t\t      ist >> ch; // '{'\n\t\t      LoadMatrixLine (ist, tempoldutonewu,\n\t\t\t\t      2 * (points.Size()-noldp));\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"newlines\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> lin.I1();\n\t      ist >> ch;    // ','\n\t      ist >> lin.I2();\n\t      ist >> ch;    // ')'\n\n\t      lines.Append (lin);\n\t      linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1()));\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"freearea\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> p[0];\n\t      ist >> ch;    // ','\n\t      ist >> p[1];\n\t      ist >> ch;    // ')'\n\n\t      freezone.Append (p);\n\t      freezonelimit.Append (p);\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      LoadMatrixLine (ist, tempoldutofreearea,\n\t\t\t\t      2 * freezone.Size() - 1);\n\n\t\t      ist >> ch; // '{'\n\t\t      LoadMatrixLine (ist, tempoldutofreearea,\n\t\t\t\t      2 * freezone.Size());\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  for (i = 1; i <= tempoldutofreearealimit.Height(); i++)\n\t    for (j = 1; j <= tempoldutofreearealimit.Width(); j++)\n\t      tempoldutofreearealimit.Elem(i,j) =\n\t\ttempoldutofreearea.Elem(i,j);\n\n\n\t  ist.putback (ch);\n\t}    \n      else if (strcmp (buf, \"freearea2\") == 0)\n\t{\n\t  ist >> ch;\n\t  int freepi = 0;\n\t  tempoldutofreearealimit = 0;\n\n\t  while (ch == '(')\n\t    {\n\t      freepi++;\n\n\t      ist >> p[0];\n\t      ist >> ch;    // ','\n\t      ist >> p[1];\n\t      ist >> ch;    // ')'\n\n\t      freezonelimit.Elem(freepi) = p;\n\t  \n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      LoadMatrixLine (ist, tempoldutofreearealimit,\n\t\t\t\t      2 * freepi - 1);\n\n\t\t      ist >> ch; // '{'\n\t\t      LoadMatrixLine (ist, tempoldutofreearealimit,\n\t\t\t\t      2 * freepi);\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\t  \n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"elements\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      elements.Append (Element2d(TRIG));\n\n\t      ist >> (int&)elements.Last().PNum(1);\n\t      ist >> ch;    // ','\n\t  \n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  ist >> (int&)elements.Last().PNum(2);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  ist >> (int&)elements.Last().PNum(3);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  elements.Last().SetType (QUAD);\n\t\t  ist >> (int&)elements.Last().PNum(4);\n\t\t  ist >> ch;    // ','\n\t\t  \n\t\t  // const Element2d & el = elements.Last();\n\t\t  /*\n\t\t  orientations.Append (threeint(el.PNum(1), el.PNum(2), el.PNum(3)));\n\t\t  orientations.Append (threeint(el.PNum(2), el.PNum(3), el.PNum(4)));\n\t\t  orientations.Append (threeint(el.PNum(3), el.PNum(4), el.PNum(1)));\n\t\t  orientations.Append (threeint(el.PNum(4), el.PNum(1), el.PNum(2)));\n\t\t  */\n\t\t}\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"orientations\") == 0)\n\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      //        threeint a = threeint();\n\t      orientations.Append (threeint());\n\n\t      ist >> orientations.Last().i1;\n\t      ist >> ch;    // ','\n\t      ist >> orientations.Last().i2;\n\t      ist >> ch;    // ','\n\t      ist >> orientations.Last().i3;\n\t      ist >> ch;    // ','\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"endrule\") != 0)\n\t{\n\t  PrintSysError (\"Parser error, unknown token \", buf);\n\t}\n    }\n  while (!ist.eof() && strcmp (buf, \"endrule\") != 0);\n\n  oldutonewu.SetSize (2 * (points.Size() - noldp), 2 * noldp);\n  oldutofreearea.SetSize (2 * freezone.Size(), 2 * noldp);\n  oldutofreearealimit.SetSize (2 * freezone.Size(), 2 * noldp);\n\n  for (i = 1; i <= oldutonewu.Height(); i++)\n    for (j = 1; j <= oldutonewu.Width(); j++)\n      oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j);\n\n  for (i = 1; i <= oldutofreearea.Height(); i++)\n    for (j = 1; j <= oldutofreearea.Width(); j++)\n      oldutofreearea.Elem(i, j) = tempoldutofreearea.Elem(i, j);\n\n  for (i = 1; i <= oldutofreearea.Height(); i++)\n    for (j = 1; j <= oldutofreearea.Width(); j++)\n      oldutofreearealimit.Elem(i, j) = tempoldutofreearealimit.Elem(i, j);\n\n  freesetinequ.SetSize (freezone.Size());\n\n\n  {\n    char ok;\n    int minn;\n    NgArray<int> pnearness (noldp);\n\n    for (i = 1; i <= pnearness.Size(); i++)\n      pnearness.Elem(i) = 1000;\n\n    for (j = 1; j <= 2; j++)\n      pnearness.Elem(GetPointNr (1, j)) = 0;\n\n    do\n      {\n\tok = 1;\n\n\tfor (i = 1; i <= noldl; i++)\n\t  {\n\t    minn = 1000;\n\t    for (j = 1; j <= 2; j++)\n\t      minn = min2 (minn, pnearness.Get(GetPointNr (i, j)));\n\n\t    for (j = 1; j <= 2; j++)\n\t      if (pnearness.Get(GetPointNr (i, j)) > minn+1)\n\t\t{\n\t\t  ok = 0;\n\t\t  pnearness.Elem(GetPointNr (i, j)) = minn+1;\n\t\t}\n\t  }\n      }\n    while (!ok);\n\n    lnearness.SetSize (noldl);\n\n    for (i = 1; i <= noldl; i++)\n      {\n\tlnearness.Elem(i) = 0;\n\tfor (j = 1; j <= 2; j++)\n\t  lnearness.Elem(i) += pnearness.Get(GetPointNr (i, j));\n      }\n  }\n\n  oldutofreearea_i.SetSize (10);\n  freezone_i.SetSize (10);\n\n  for (i = 0; i < oldutofreearea_i.Size(); i++)\n    {\n      double lam1 = 1.0/(i+1);\n\n      oldutofreearea_i[i] = std::move(DenseMatrix (oldutofreearea.Height(), oldutofreearea.Width()));\n      DenseMatrix & mati = oldutofreearea_i[i];\n      for (j = 0; j < oldutofreearea.Height(); j++)\n\tfor (int k = 0; k < oldutofreearea.Width(); k++)\n\t  mati(j,k) = lam1 * oldutofreearea(j,k) + (1 - lam1) * oldutofreearealimit(j,k);\n\n      freezone_i[i] = NgArray<Point<2>> (freezone.Size());\n      auto& fzi = freezone_i[i];\n      for (int j = 0; j < freezone.Size(); j++)\n\tfzi[j] = freezonelimit[j] + lam1 * (freezone[j] - freezonelimit[j]);\n    }\n}\n\n\n\n\nextern const char * triarules[];\nextern const char * quadrules[];\n\nvoid Meshing2 :: LoadRules (const char * filename, bool quad)\n{\n  char buf[256];\n  istream * ist;\n  //char *tr1 = NULL;\n  string tr1;\n\n  /*\n  ifstream ist (filename);\n  if (!ist.good())\n    {\n      cerr << \"Rule description file \" << filename << \" not found\" << endl;\n      exit (1);\n    }\n  */\n\n\n  if (filename)\n    {\n      //      (*mycout) << \"rule-filename = \" << filename << endl;\n      ist = new ifstream (filename);\n    }\n  else \n    {\n      /* connect tetrules to one string */\n      const char ** hcp;\n\n      // if (!mparam.quad)\n      if (!quad)\n\t{\n\t  hcp = triarules;\n\t  PrintMessage (3, \"load internal triangle rules\");\n\t}\n      else\n\t{\n\t  hcp = quadrules;\n\t  PrintMessage (3, \"load internal quad rules\");\n\t  // LoadRules (\"rules/quad.rls\");\n\t}\n\n      size_t len = 0;\n      while (*hcp)\n\t{\n\t  //\t  (*testout) << \"POS2 *hcp \" << *hcp << endl;\n\t  len += strlen (*hcp);\n\t  hcp++;\n\t}\n      //tr1 = new char[len+1];\n      //tr1[0] = 0;\n      tr1.reserve(len+1);\n\n\n      // if (!mparam.quad)\n      if (!quad)\n\thcp = triarules;\n      else\n\thcp = quadrules;\n\n\n      //char * tt1 = tr1;\n      while (*hcp)\n\t{\n\t  //strcat (tt1, *hcp);\n\t  //tt1 += strlen (*hcp);\n\t  tr1.append(*hcp);\n\t  hcp++;\n\t}\n      \n#ifdef WIN32\n      // VC++ 2005 workaround\n\t  for(string::size_type i=0; i<tr1.size(); i++)\n\tif(tr1[i] == ',')\n\t  tr1[i] = ':';\n#endif\n\n      ist = new istringstream (tr1);\n    }\n\n\n  if (!ist->good())\n    {\n      cerr << \"Rule description file \" << filename << \" not found\" << endl;\n      delete ist;\n      exit (1);\n    }\n\n  Timer t(\"Parsing rules\");\n  t.Start();\n  while (!ist->eof())\n    {\n      buf[0] = 0;\n      (*ist) >> buf;\n\n      if (strcmp (buf, \"rule\") == 0)\n\t{\n\t  //(*testout) << \"found rule\" << endl;\n\t  auto rule = make_unique<netrule>();\n\t  //(*testout) << \"fr1\" << endl;\n\t  rule -> LoadRule(*ist);\n\t  //(*testout) << \"fr2\" << endl;\n\t  \n\t  rules.Append (std::move(rule));\n\t}\n      //(*testout) << \"loop\" << endl;\n    }\n  //(*testout) << \"POS3\" << endl;\n  t.Stop();\n  \n  delete ist;\n  //delete [] tr1;\n}\n\n}\n"
  },
  {
    "path": "libsrc/meshing/parser3.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n#ifdef WIN32\n#define COMMASIGN ':'\n#else\n#define COMMASIGN ','\n#endif\n\n\nnamespace netgen\n{\n\nextern const char * tetrules[];\n\nvoid LoadVMatrixLine (istream & ist, DenseMatrix & m, int line)\n{\n  char ch;\n  int pnum;\n  float f;\n  \n  ist >> ch;\n  while (ch != '}')\n    {\n      ist.putback (ch);\n      ist >> f;\n      ist >> ch;\n      ist >> pnum;\n      \n      if (ch == 'x' || ch == 'X')\n\tm.Elem(line, 3 * pnum - 2) = f;\n      if (ch == 'y' || ch == 'Y')\n\tm.Elem(line, 3 * pnum - 1) = f;\n      if (ch == 'z' || ch == 'Z')\n\tm.Elem(line, 3 * pnum    ) = f;\n\n      if (ch == 'p' || ch == 'P')\n\t{\n\t  m.Elem(line  , 3 * pnum-2) = f;\n\t  m.Elem(line+1, 3 * pnum-1) = f;\n\t  m.Elem(line+2, 3 * pnum  ) = f;\n\t}\n\n      ist >> ch;\n      if (ch == COMMASIGN)\n\tist >> ch;\n    }\n}\n\n\n\n\n\nint vnetrule :: NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const\n{\n  NgArray<int> tr1(3);\n  NgArray<int> tr2(3);\n  tr1.Elem(1)=t1.i1;\n  tr1.Elem(2)=t1.i2;\n  tr1.Elem(3)=t1.i3;\n  tr2.Elem(1)=t2.i1;\n  tr2.Elem(2)=t2.i2;\n  tr2.Elem(3)=t2.i3;\n\n\n  int ret=0;\n\n  for (int i=1; i<=3; i++)\n    {\n      for (int j=1; j<=3; j++)\n\t{\n\t  if ((tr1.Get(i)==tr2.Get(j) && tr1.Get((i%3)+1)==tr2.Get((j%3)+1)) ||\n              (tr1.Get(i)==tr2.Get((j%3)+1) && tr1.Get((i%3)+1)==tr2.Get(j)))\n\t    {ret = tr2.Get((j+1)%3+1);}\n\t}      \n    }\n\n  return ret;\n\n}\n\nvoid vnetrule :: LoadRule (istream & ist)\n{\n  char buf[256];\n  char ch, ok;\n  Point3d p;\n  Element2d face(TRIG);\n  int i, j, i1, i2, i3, fs, ii, ii1, ii2, ii3;\n  twoint edge;\n  DenseMatrix tempoldutonewu(30, 20), \n    tempoldutofreezone(30, 20),\n    tempoldutofreezonelimit(30, 20),\n    tfz(20, 20),\n    tfzl(20, 20);\n\n  tempoldutonewu = 0;\n  tempoldutofreezone = 0;\n  tfz = 0;\n  tfzl = 0;\n\n\n  noldp = 0;\n  noldf = 0;\n\n  ist.get (buf, sizeof(buf), '\"');\n  ist.get (ch);\n  ist.get (buf, sizeof(buf), '\"');\n  ist.get (ch);\n\n  delete [] name;\n  name = new char[strlen (buf) + 1];\n  strcpy (name, buf);\n  //  (*mycout) << \"Rule \" << name << \" found.\" << endl;\n\n  do\n    {\n      ist >> buf;\n\n      if (strcmp (buf, \"quality\") == 0)\n\n\t{\n\t  ist >> quality;\n\t}\n\n      else if (strcmp (buf, \"flags\") == 0)\n\t{\n\t  ist >> ch;\n\t  while (ch != ';')\n\t    {\n\t      flags.Append (ch);\n\t      ist >> ch;\n\t    }\n\t}\n\n      else if (strcmp (buf, \"mappoints\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> p.X();\n\t      ist >> ch;    // ','\n\t      ist >> p.Y();\n\t      ist >> ch;    // ','\n\t      ist >> p.Z();\n\t      ist >> ch;    // ')'\n\n\t      points.Append (p);\n\t      noldp++;\n\n\t      tolerances.SetSize (noldp);\n\t      tolerances.Elem(noldp) = 1;\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      ist >> tolerances.Elem(noldp);\n\t\t      ist >> ch;  // '}'\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n\n      else if (strcmp (buf, \"mapfaces\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      face.SetType(TRIG);\n\t      ist >> (int&)face.PNum(1);\n\t      ist >> ch;    // ','\n\t      ist >> (int&)face.PNum(2);\n\t      ist >> ch;    // ','\n\t      ist >> (int&)face.PNum(3);\n\t      ist >> ch;    // ')' or ','\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  face.SetType(QUAD);\n\t\t  ist >> (int&)face.PNum(4);\n\t\t  ist >> ch;    // ')' \n\t\t}\n\t      faces.Append (face);\n\t      noldf++;\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == 'd')\n\t\t    {\n\t\t      delfaces.Append (noldf);\n\t\t      ist >> ch; // 'e'\n\t\t      ist >> ch; // 'l'\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"mapedges\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> edge.i1;\n\t      ist >> ch;    // ','\n\t      ist >> edge.i2;\n\t      ist >> ch;    // ')'\n\n\t      edges.Append (edge);\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n\n      else if (strcmp (buf, \"newpoints\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      ist >> p.X();\n\t      ist >> ch;    // ','\n\t      ist >> p.Y();\n\t      ist >> ch;    // ','\n\t      ist >> p.Z();\n\t      ist >> ch;    // ')'\n\n\t      points.Append (p);\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      LoadVMatrixLine (ist, tempoldutonewu,\n\t\t\t\t       3 * (points.Size()-noldp) - 2);\n\n\t\t      ist >> ch; // '{'\n\t\t      LoadVMatrixLine (ist, tempoldutonewu,\n\t\t\t\t       3 * (points.Size()-noldp) - 1);\n\n\t\t      ist >> ch; // '{'\n\t\t      LoadVMatrixLine (ist, tempoldutonewu,\n\t\t\t\t       3 * (points.Size()-noldp)    );\n\t\t    }\n\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"newfaces\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      face.SetType(TRIG);\n\t      ist >> (int&)face.PNum(1);\n\t      ist >> ch;    // ','\n\t      ist >> (int&)face.PNum(2);\n\t      ist >> ch;    // ','\n\t      ist >> (int&)face.PNum(3);\n\t      ist >> ch;    // ')' or ','\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  face.SetType(QUAD);\n\t\t  ist >> (int&)face.PNum(4);\n\t\t  ist >> ch;    // ')' \n\t\t}\n\t      faces.Append (face);\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"freezone\") == 0)\n\t{\n\t  ist >> ch;\n\t\n\t  while (ch == '(')\n\t    {\n\t      ist >> p.X();\n\t      ist >> ch;    // ','\n\t      ist >> p.Y();\n\t      ist >> ch;    // ','\n\t      ist >> p.Z();\n\t      ist >> ch;    // ')'\n\t    \n\t      freezone.Append (p);\n\t    \n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  if (ch == '{')\n\t\t    {\n\t\t      LoadVMatrixLine (ist, tempoldutofreezone,\n\t\t\t\t       3 * freezone.Size() - 2);\n\t\t    \n\t\t      ist >> ch; // '{'\n\t\t      LoadVMatrixLine (ist, tempoldutofreezone,\n\t\t\t\t       3 * freezone.Size() - 1);\n\t\t    \n\t\t      ist >> ch; // '{'\n\t\t      LoadVMatrixLine (ist, tempoldutofreezone,\n\t\t\t\t       3 * freezone.Size()    );\n\t\t    }\n\t\t\n\t\t  ist >> ch;\n\t\t}\n\t    \n\t      ist >> ch;\n\t    }\n\t\n\t  ist.putback (ch);\n\t}\n      else if (strcmp (buf, \"freezone2\") == 0)\n\t{\n\t  int k, nfp;\n\n\t  nfp = 0;\n\t  ist >> ch;\n\n\t  DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50);\n\t  hm3 = 0;\n\n\t  while (ch == '{')\n\t    {\n\t      hm1 = 0;\n\t      nfp++;\n\t      LoadVMatrixLine (ist, hm1, 1);\n\n\t      for (i = 1; i <= points.Size(); i++)\n\t\ttfz.Elem(nfp, i) = hm1.Get(1, 3*i-2);\n\n\n\t      p.X() = p.Y() = p.Z() = 0;\n\t      for (i = 1; i <= points.Size(); i++)\n\t\t{\n\t\t  p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X();\n\t\t  p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y();\n\t\t  p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z();\n\t\t}\n\t      freezone.Append (p);\n\t      freezonelimit.Append (p);\n\t    \n\t      hm2 = 0;\n\t      for (i = 1; i <= 3 * noldp; i++)\n\t\thm2.Elem(i, i) = 1;\n\t      for (i = 1; i <= 3 * noldp; i++)\n\t\tfor (j = 1; j <= 3 * (points.Size() - noldp); j++)\n\t\t  hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i);\n\t\t  \n\t      for (i = 1; i <= 3; i++)\n\t\tfor (j = 1; j <= 3 * noldp; j++)\n\t\t  {\n\t\t    double sum = 0;\n\t\t    for (k = 1; k <= 3 * points.Size(); k++)\n\t\t      sum += hm1.Get(i, k) * hm2.Get(k, j);\n\t\t  \n\t\t    hm3.Elem(i + 3 * (nfp-1), j) = sum;\n\t\t  }\n\n\t      //\t    (*testout) << \"freepoint: \" << p << endl;\n\n\t      while (ch != ';')\n\t\tist >> ch; \n\n\t      ist >> ch;\n\t    }\n\n\t  tfzl = tfz;\n\n\t  tempoldutofreezone = hm3;\n\t  tempoldutofreezonelimit = hm3;\n\t  ist.putback(ch);\n\t}\n\n      else if (strcmp (buf, \"freezonelimit\") == 0)\n\t{\n\t  int k, nfp;\n\t  nfp = 0;\n\t  ist >> ch;\n\n\t  DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50);\n\t  hm3 = 0;\n\n\t  while (ch == '{')\n\t    {\n\t      hm1 = 0;\n\t      nfp++;\n\t      LoadVMatrixLine (ist, hm1, 1);\n\n\t      for (i = 1; i <= points.Size(); i++)\n\t\ttfzl.Elem(nfp, i) = hm1.Get(1, 3*i-2);\n\n\n\t      p.X() = p.Y() = p.Z() = 0;\n\t      for (i = 1; i <= points.Size(); i++)\n\t\t{\n\t\t  p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X();\n\t\t  p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y();\n\t\t  p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z();\n\t\t}\n\t      freezonelimit.Elem(nfp) = p;\n\t    \n\t      hm2 = 0;\n\t      for (i = 1; i <= 3 * noldp; i++)\n\t\thm2.Elem(i, i) = 1;\n\t      for (i = 1; i <= 3 * noldp; i++)\n\t\tfor (j = 1; j <= 3 * (points.Size() - noldp); j++)\n\t\t  hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i);\n\t\t  \n\t      for (i = 1; i <= 3; i++)\n\t\tfor (j = 1; j <= 3 * noldp; j++)\n\t\t  {\n\t\t    double sum = 0;\n\t\t    for (k = 1; k <= 3 * points.Size(); k++)\n\t\t      sum += hm1.Get(i, k) * hm2.Get(k, j);\n\t\t  \n\t\t    hm3.Elem(i + 3 * (nfp-1), j) = sum;\n\t\t  }\n\n\t      //\t    (*testout) << \"freepoint: \" << p << endl;\n\n\t      while (ch != ';')\n\t\tist >> ch; \n\n\t      ist >> ch;\n\t    }\n\n\t  tempoldutofreezonelimit = hm3;\n\t  ist.putback(ch);\n\t}\n\n      else if (strcmp (buf, \"freeset\") == 0)\n\t{\n\t  freesets.Append (new NgArray<int>);\n\n\t  ist >> ch;\n\n\t  while (ch != ';')\n\t    {\n\t      ist.putback (ch);\n\t      ist >> i;\n\t      freesets.Last()->Append(i);\n\t      ist >> ch;\n\t    }\n\t}\n\n      else if (strcmp (buf, \"elements\") == 0)\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      elements.Append (Element(TET));\n\n\t      //\t      elements.Last().SetNP(1);\n\t      ist >> (int&)elements.Last().PNum(1);\n\t      ist >> ch;    // ','\n\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(2);\n\t\t  ist >> (int&)elements.Last().PNum(2);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(3);\n\t\t  ist >> (int&)elements.Last().PNum(3);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(4);\n\t\t  elements.Last().SetType(TET);\n\t\t  ist >> (int&)elements.Last().PNum(4);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(5);\n\t\t  elements.Last().SetType(PYRAMID);\n\t\t  ist >> (int&)elements.Last().PNum(5);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(6);\n\t\t  elements.Last().SetType(PRISM);\n\t\t  ist >> (int&)elements.Last().PNum(6);\n\t\t  ist >> ch;    // ','\n\t\t}\n              \n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(6);\n\t\t  elements.Last().SetType(HEX);\n\t\t  ist >> (int&)elements.Last().PNum(7);\n\t\t  ist >> ch;    // ','\n\t\t}\n\t      if (ch == COMMASIGN)\n\t\t{\n\t\t  //\t\t  elements.Last().SetNP(6);\n\t\t  elements.Last().SetType(HEX);\n\t\t  ist >> (int&)elements.Last().PNum(8);\n\t\t  ist >> ch;    // ','\n\t\t}\n\n\t      /*\n\t      orientations.Append (fourint());\n\t      orientations.Last().i1 = elements.Last().PNum(1);\n\t      orientations.Last().i2 = elements.Last().PNum(2);\n\t      orientations.Last().i3 = elements.Last().PNum(3);\n\t      orientations.Last().i4 = elements.Last().PNum(4);\n\t      */\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n      else if (strcmp (buf, \"orientations\") == 0)\n\n\t{\n\t  ist >> ch;\n\n\t  while (ch == '(')\n\t    {\n\t      //        fourint a = fourint();\n\t      orientations.Append (fourint());\n\n\t      ist >> orientations.Last().i1;\n\t      ist >> ch;    // ','\n\t      ist >> orientations.Last().i2;\n\t      ist >> ch;    // ','\n\t      ist >> orientations.Last().i3;\n\t      ist >> ch;    // ','\n\t      ist >> orientations.Last().i4;\n\t      ist >> ch;    // ','\n\n\n\t      ist >> ch;\n\t      while (ch != ';')\n\t\t{\n\t\t  ist >> ch;\n\t\t}\n\n\t      ist >> ch;\n\t    }\n\n\t  ist.putback (ch);\n\t}\n\n\n      else if (strcmp (buf, \"endrule\") != 0)\n\t{\n\t  PrintSysError (\"Parser3d, unknown token \" , buf);\n\t}\n    }\n  while (!ist.eof() && strcmp (buf, \"endrule\") != 0);\n\n\n  //  (*testout) << endl;\n  //  (*testout) << Name() << endl;\n  //  (*testout) << \"no1 = \" << GetNO() << endl;\n\n  oldutonewu.SetSize (3 * (points.Size() - noldp), 3 * noldp);\n  oldutonewu = 0;\n\n  for (i = 1; i <= oldutonewu.Height(); i++)\n    for (j = 1; j <= oldutonewu.Width(); j++)\n      oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j);\n\n\n  /*\n    oldutofreezone = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp);\n    oldutofreezonelimit = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp);\n\n    oldutofreezone -> SetSymmetric(0);\n    oldutofreezonelimit -> SetSymmetric(0);\n    */\n\n  /*\n    oldutofreezone = new DenseMatrix (3 * freezone.Size(), 3 * noldp);\n    oldutofreezonelimit = new DenseMatrix (3 * freezone.Size(), 3 * noldp);\n  \n    for (i = 1; i <= oldutofreezone->Height(); i++)\n    for (j = 1; j <= oldutofreezone->Width(); j++)\n    //      if (j == 4 || j >= 7)\n    {\n    if (tempoldutofreezone.Elem(i, j))\n    (*oldutofreezone)(i, j) = tempoldutofreezone(i, j);\n    if (tempoldutofreezonelimit.Elem(i, j))\n    (*oldutofreezonelimit)(i, j) = tempoldutofreezonelimit(i, j);\n    }\n    */\n\n\n\n\n  oldutofreezone = new DenseMatrix (freezone.Size(), points.Size());\n  oldutofreezonelimit = new DenseMatrix (freezone.Size(), points.Size());\n  //  oldutofreezone = new SparseMatrixFlex (freezone.Size(), points.Size());\n  //  oldutofreezonelimit = new SparseMatrixFlex (freezone.Size(), points.Size());\n\n  for (i = 1; i <= freezone.Size(); i++)\n    for (j = 1; j <= points.Size(); j++)\n      {\n\tif (tfz.Elem(i, j))\n\t  (*oldutofreezone).Elem(i, j) = tfz.Elem(i, j);\n\tif (tfzl.Elem(i, j))\n\t  (*oldutofreezonelimit).Elem(i, j) = tfzl.Elem(i, j);\n      }\n  \n  /*\n  (*testout) << \"Rule \" << Name() << endl;\n  (*testout) << \"oldutofreezone = \" << (*oldutofreezone) << endl;\n  (*testout) << \"oldutofreezonelimit = \" << (*oldutofreezonelimit) << endl;\n  */\n\n  freezonepi.SetSize (freezone.Size());\n  for (i = 1; i <= freezonepi.Size(); i++)\n    freezonepi.Elem(i) = 0;\n  for (i = 1; i <= freezone.Size(); i++)\n    for (j = 1; j <= noldp; j++)\n      if (Dist (freezone.Get(i), points.Get(j)) < 1e-8)\n\tfreezonepi.Elem(i) = j;\n\n\n\n  \n  for (i = 1; i <= elements.Size(); i++)\n    {\n      if (elements.Elem(i).GetNP() == 4)\n\t{\n\t  orientations.Append (fourint());\n\t  orientations.Last().i1 = elements.Get(i).PNum(1);\n\t  orientations.Last().i2 = elements.Get(i).PNum(2);\n\t  orientations.Last().i3 = elements.Get(i).PNum(3);\n\t  orientations.Last().i4 = elements.Get(i).PNum(4);\n\t}\n      if (elements.Elem(i).GetNP() == 5)\n\t{\n\t  orientations.Append (fourint());\n\t  orientations.Last().i1 = elements.Get(i).PNum(1);\n\t  orientations.Last().i2 = elements.Get(i).PNum(2);\n\t  orientations.Last().i3 = elements.Get(i).PNum(3);\n\t  orientations.Last().i4 = elements.Get(i).PNum(5);\n\n\t  orientations.Append (fourint());\n\t  orientations.Last().i1 = elements.Get(i).PNum(1);\n\t  orientations.Last().i2 = elements.Get(i).PNum(3);\n\t  orientations.Last().i3 = elements.Get(i).PNum(4);\n\t  orientations.Last().i4 = elements.Get(i).PNum(5);\n\t}\n    }\n\n\n\n  if (freesets.Size() == 0)\n    {\n      freesets.Append (new NgArray<int>);\n      for (i = 1; i <= freezone.Size(); i++)\n\tfreesets.Elem(1)->Append(i);\n    }\n\n\n  //  testout << \"Freezone: \" << endl;\n\n  //  for (i = 1; i <= freezone.Size(); i++)\n  //    (*testout) << \"freepoint: \" << freezone.Get(i) << endl;\n  Vector vp(points.Size()), vfp(freezone.Size());\n\n\n  if (quality < 100)\n    {\n      for (int i = 1; i <= 3; i++)\n\t{\n\t  for (int j = 1; j <= points.Size(); j++)\n\t    vp(j-1) = points.Get(j).X(i);\n\t  oldutofreezone->Mult(vp, vfp);\n\t  for (int j = 1; j <= freezone.Size(); j++)\n\t    freezone.Elem(j).X(i) = vfp(j-1);\n\t}\n      //      for (i = 1; i <= freezone.Size(); i++)\n      //\t(*testout) << \"freepoint: \" << freezone.Get(i) << endl;\n    }\n\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      freefaces.Append (new NgArray<threeint>);\n\n      NgArray<int> & freeset = *freesets.Elem(fs);\n      NgArray<threeint> & freesetfaces = *freefaces.Last();\n\n      for (ii1 = 1; ii1 <= freeset.Size(); ii1++)\n\tfor (ii2 = 1; ii2 <= freeset.Size(); ii2++)\n\t  for (ii3 = 1; ii3 <= freeset.Size(); ii3++)\n\t    if (ii1 < ii2 && ii1 < ii3 && ii2 != ii3)\n\t      {\n\t\ti1 = freeset.Get(ii1);\n\t\ti2 = freeset.Get(ii2);\n\t\ti3 = freeset.Get(ii3);\n\n\t\tVec3d v1, v2, n;\n\n\t\tv1 = freezone.Get(i3) - freezone.Get(i1);\n\t\tv2 = freezone.Get(i2) - freezone.Get(i1);\n\t\tn = Cross (v1, v2);\n\t\tn /= n.Length();\n\t\t//\t\t(*testout) << \"i1,2,3 = \" << i1 << \", \" << i2 << \", \" << i3 << endl;\n\t\t//\t\t(*testout) << \"v1 = \" << v1 << \" v2 = \" << v2 << \" n = \" << n << endl;\n\t\tok = 1;\n\t\tfor (ii = 1; ii <= freeset.Size(); ii++)\n\t\t  {\n\t\t    i = freeset.Get(ii);\n\t\t    //\t\t    (*testout) << \"i = \" << i << endl;\n\t\t    if (i != i1 && i != i2 && i != i3)\n\t\t      if ( (freezone.Get(i) - freezone.Get(i1)) * n < 0 ) ok = 0;\n\t\t  }\n\n\t\tif (ok)\n\t\t  {\n\t\t    freesetfaces.Append (threeint());\n\t\t    freesetfaces.Last().i1 = i1;\n\t\t    freesetfaces.Last().i2 = i2;\n\t\t    freesetfaces.Last().i3 = i3;\n\t\t  }\n\t      }\n    }\n\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      freefaceinequ.Append (new DenseMatrix (freefaces.Get(fs)->Size(), 4));\n    }\n\n\n  {\n    int minn;\n    //    NgArray<int> pnearness (noldp);\n    pnearness.SetSize (noldp);\n\n    for (i = 1; i <= pnearness.Size(); i++)\n      pnearness.Elem(i) = INT_MAX/10;\n\n    for (j = 1; j <= GetNP(1); j++)\n      pnearness.Elem(GetPointNr (1, j)) = 0;\n\n    do\n      {\n\tok = 1;\n\n\tfor (i = 1; i <= noldf; i++)\n\t  {\n\t    minn = INT_MAX/10;\n\t    for (j = 1; j <= GetNP(i); j++)\n\t      minn = min2 (minn, pnearness.Get(GetPointNr (i, j)));\n\n\t    for (j = 1; j <= GetNP(i); j++)\n\t      if (pnearness.Get(GetPointNr (i, j)) > minn+1)\n\t\t{\n\t\t  ok = 0;\n\t\t  pnearness.Elem(GetPointNr (i, j)) = minn+1;\n\t\t}\n\t  }\n\n\tfor (i = 1; i <= edges.Size(); i++)\n\t  {\n\t    int pi1 = edges.Get(i).i1;\n\t    int pi2 = edges.Get(i).i2;\n\n\t    if (pnearness.Get(pi1) > pnearness.Get(pi2)+1)\n\t      {\n\t\tok = 0;\n\t\tpnearness.Elem(pi1) = pnearness.Get(pi2)+1;\n\t      }\n\t    if (pnearness.Get(pi2) > pnearness.Get(pi1)+1)\n\t      {\n\t\tok = 0;\n\t\tpnearness.Elem(pi2) = pnearness.Get(pi1)+1;\n\t      }\n\t  }\n\t\n\n\tfor (i = 1; i <= elements.Size(); i++)\n\t  if (elements.Get(i).GetNP() == 6)  // prism rule\n\t    {\n\t      for (j = 1; j <= 3; j++)\n\t\t{\n\t\t  int pi1 = elements.Get(i).PNum(j);\n\t\t  int pi2 = elements.Get(i).PNum(j+3);\n\n\t\t  if (pnearness.Get(pi1) > pnearness.Get(pi2)+1)\n\t\t    {\n\t\t      ok = 0;\n\t\t      pnearness.Elem(pi1) = pnearness.Get(pi2)+1;\n\t\t    }\n\t\t  if (pnearness.Get(pi2) > pnearness.Get(pi1)+1)\n\t\t    {\n\t\t      ok = 0;\n\t\t      pnearness.Elem(pi2) = pnearness.Get(pi1)+1;\n\t\t    }\n\t\t}\n\t    }\n      }\n    while (!ok);\n\n    maxpnearness = 0;\n    for (i = 1; i <= pnearness.Size(); i++)\n      maxpnearness = max2 (maxpnearness, pnearness.Get(i));\n\n\n    fnearness.SetSize (noldf);\n\n    for (i = 1; i <= noldf; i++)\n      {\n\tfnearness.Elem(i) = 0;\n\tfor (j = 1; j <= GetNP(i); j++)\n\t  fnearness.Elem(i) += pnearness.Get(GetPointNr (i, j));\n      }\n\n    // (*testout) << \"rule \" << name << \", pnear = \" << pnearness << endl;\n  }\n\n  \n  //Table of edges:\n  for (fs = 1; fs <= freesets.Size(); fs++)\n    {\n      freeedges.Append (new NgArray<twoint>);\n      \n      //      NgArray<int> & freeset = *freesets.Get(fs);\n      NgArray<twoint> & freesetedges = *freeedges.Last();\n      NgArray<threeint> & freesetfaces = *freefaces.Get(fs);\n      // int k,l;\n      // INDEX ind;\n      \n      for (int k = 1; k <= freesetfaces.Size(); k++)\n\t{\n          // threeint tr = freesetfaces.Get(k);\n\n\t  for (int l = k+1; l <= freesetfaces.Size(); l++)\n\t    {\n\t      INDEX ind = NeighbourTrianglePoint(freesetfaces.Get(k), freesetfaces.Get(l));\n\t      if (!ind) continue;\n\n\t      INDEX_3 f1(freesetfaces.Get(k).i1, \n\t\t\t freesetfaces.Get(k).i2, \n\t\t\t freesetfaces.Get(k).i3);\n\t      INDEX_3 f2(freesetfaces.Get(l).i1, \n\t\t\t freesetfaces.Get(l).i2, \n\t\t\t freesetfaces.Get(l).i3);\n\t      PointIndices<2> ed(PointIndex::INVALID, PointIndex::INVALID);\n\t      for (int f11 = 1; f11 <= 3; f11++)\n\t\tfor (int f12 = 1; f12 <= 3; f12++)\n\t\t  if (f11 != f12)\n\t\t    for (int f21 = 1; f21 <= 3; f21++)\n\t\t      for (int f22 = 1; f22 <= 3; f22++)\t\t    \n\t\t\tif (f1.I(f11) == f2.I(f21) && f1.I(f12) == f2.I(f22))\n\t\t\t{\n\t\t\t  ed.I(1) = f1.I(f11);\n\t\t\t  ed.I(2) = f1.I(f12);\n\t\t\t}\n\t      //\t      (*testout) << \"ed = \" << ed.I(1) << \"-\" << ed.I(2) << endl;\n\t      //\t      (*testout) << \"ind = \" << ind << \" ed = \" << ed << endl;\n\t      for (int eli = 1; eli <= GetNOldF(); eli++)\n\t\t{\n\t\t  if (GetNP(eli) == 4)\n\t\t    {\n\t\t      for (int elr = 1; elr <= 4; elr++)\n\t\t\t{\n\t\t\t  if (GetPointNrMod (eli, elr) == ed[0] &&\n\t\t\t      GetPointNrMod (eli, elr+2) == ed[1])\n\t\t\t    {\n\t\t\t      /*\n\t\t\t      (*testout) << \"ed is diagonal of rectangle\" << endl;\n\t\t\t      (*testout) << \"ed = \" << ed.I(1) << \"-\" << ed.I(2) << endl;\n\t\t\t      (*testout) << \"ind = \" << ind << endl;\n\t\t\t      */\n\t\t\t      ind = 0;\n\t\t\t    }\n\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t      if (ind)\n\t\t{\n\t\t  /*\n\t\t  (*testout) << \"new edge from face \" << k \n\t\t\t     << \" = (\" << freesetfaces.Get(k).i1 \n\t\t\t     << \", \" << freesetfaces.Get(k).i2 \n\t\t\t     << \", \" << freesetfaces.Get(k).i3\n\t\t\t     << \"), point \" << ind << endl;\n\t\t\t     */\n\t\t  freesetedges.Append(twoint(k,ind));\n\t\t}\n\t    }\t\n\t}\n    }\n    \n}\n\n\n\n\n\nvoid Meshing3 :: LoadRules (const char * filename, const char ** prules)\n{\n  char buf[256];\n  istream * ist;\n  char *tr1 = NULL;\n\n  if (filename)\n    {\n      PrintMessage (3, \"rule-filename = \", filename);\n      ist = new ifstream (filename);\n    }\n  else \n    {\n      /* connect tetrules to one string */\n      PrintMessage (3, \"Use internal rules\");\n      if (!prules) prules = tetrules;\n\n      const char ** hcp = prules; \n      size_t len = 0;\n      while (*hcp)\n\t{\n\t  len += strlen (*hcp);\n\t  hcp++;\n\t}\n      tr1 = new char[len+1];\n      tr1[0] = 0;\n      hcp = prules; //  tetrules;\n\n\n      char * tt1 = tr1;\n      while (*hcp)\n\t{\n\t  strcat (tt1, *hcp);\n\t  tt1 += strlen (*hcp);\t  \n\t  hcp++;\n\t}\n\n\n#ifdef WIN32\n      // VC++ 2005 workaround\n      for(size_t i=0; i<len; i++)\n\tif(tr1[i] == ',')\n\t  tr1[i] = ':';\n#endif\n\n      ist = new istringstream (tr1);\n    }\n  \n  if (!ist->good())\n    {\n      cerr << \"Rule description file \" << filename << \" not found\" << endl;\n      delete ist;\n      exit (1);\n    }\n    \n  while (!ist->eof())\n    {\n      buf[0] = 0;\n      (*ist) >> buf;\n\t\n      if (strcmp (buf, \"rule\") == 0)\n\t{\n\t  // vnetrule * rule = new vnetrule;\n          auto rule = make_unique<vnetrule>();\n\t  rule -> LoadRule(*ist);\n\t  if (!rule->TestOk())\n\t    {\n\t      PrintSysError (\"Parser3d: Rule \", rules.Size(), \" not ok\");\n\t      exit (1);\n\t    }\n\t  rules.Append (std::move(rule));\n\t}\n      else if (strcmp (buf, \"tolfak\") == 0)\n\t{\n\t  (*ist) >> tolfak;\n\t}\n    }\n  delete ist;\n  delete [] tr1;\n}\n}\n"
  },
  {
    "path": "libsrc/meshing/python_mesh.cpp",
    "content": "#ifdef NG_PYTHON\n\n#include <regex>\n\n#include <../general/ngpython.hpp>\n#include <core/python_ngcore.hpp>\n#include \"python_mesh.hpp\"\n\n#include <mystdlib.h>\n#include \"meshing.hpp\"\n#include \"boundarylayer.hpp\"\n// #include <csg.hpp>\n// #include <geometry2d.hpp>\n#include <../interface/rw_medit.hpp>\n#include <../interface/writeuser.hpp>\n#include <../include/nginterface.h>\n#include <../general/gzstream.h>\n\n\nclass ClearSolutionClass\n{\npublic:\n  ClearSolutionClass() { } \n  ~ClearSolutionClass() { Ng_ClearSolutionData(); }\n};\n\n\n\nusing namespace netgen;\n\nextern const char *ngscript[];\n\nnamespace netgen\n{\n  extern bool netgen_executable_started;\n  extern shared_ptr<NetgenGeometry> ng_geometry;\n  extern void Optimize2d (Mesh & mesh, MeshingParameters & mp, int faceindex=0);\n#ifdef NG_CGNS\n  extern tuple<shared_ptr<Mesh>, vector<string>, vector<Array<double>>, vector<int>> ReadCGNSFile(const filesystem::path & filename, int base);\n  extern void WriteCGNSFile(shared_ptr<Mesh> mesh, const filesystem::path & filename, vector<string> fields, vector<Array<double>> values, vector<int> locations);\n#endif // NG_CGNS\n}\n\n\nvoid TranslateException (const NgException & ex)\n{\n  string err = string(\"Netgen exception: \")+ex.What();\n  PyErr_SetString(PyExc_RuntimeError, err.c_str());\n}\n\nstatic Transformation<3> global_trafo(Vec<3> (0,0,0));\n\n\n\n\n\nDLL_HEADER void ExportNetgenMeshing(py::module &m) \n{\n  py::register_exception<NgException>(m, \"NgException\");\n  m.attr(\"_netgen_executable_started\") = py::cast(netgen::netgen_executable_started);\n  string script;\n  const char ** hcp = ngscript;\n  while (*hcp)\n      script += *hcp++;\n\n  m.attr(\"_ngscript\") = py::cast(script);\n\n  m.def(\"_GetStatus\", []()\n        {\n          std::string s; double percent;\n          GetStatus(s, percent);\n          return py::make_tuple(s.c_str(), percent);\n        });\n  m.def(\"_PushStatus\", [](string s) { PushStatus(s); });\n  m.def(\"_SetThreadPercentage\", [](double percent) { SetThreadPercent(percent); });\n\n  py::enum_<Identifications::ID_TYPE>(m,\"IdentificationType\")\n    .value(\"UNDEFINED\", Identifications::UNDEFINED)\n    .value(\"PERIODIC\", Identifications::PERIODIC)\n    .value(\"CLOSESURFACES\", Identifications::CLOSESURFACES)\n    .value(\"CLOSEEDGES\", Identifications::CLOSEEDGES)\n    ;\n\n  py::implicitly_convertible<int, Identifications::ID_TYPE>();\n\n  \n  py::class_<NGDummyArgument>(m, \"NGDummyArgument\")\n    .def(\"__bool__\", []( NGDummyArgument &self ) { return false; } )\n    ;\n\n  py::class_<LocalH, shared_ptr<LocalH>>(m, \"LocalH\");\n  \n  py::class_<Point<2>> (m, \"Point2d\")\n    .def(py::init<double,double>())\n    .def(py::init( [] (std::pair<double,double> xy)\n            {\n                return Point<2>{xy.first, xy.second};\n            }))\n    .def (\"__str__\", &ToString<Point<2>>)\n    .def(py::self-py::self)\n    .def(py::self+Vec<2>())\n    .def(py::self-Vec<2>())\n    .def(\"__getitem__\", [](Point<2>& self, int index) { return self[index]; })\n    .def(\"__len__\", [](Point<2>& /*unused*/) { return 2; })\n    ;\n\n  py::implicitly_convertible<py::tuple, Point<2>>();\n\n  py::class_<Point<3>> (m, \"Point3d\")\n    .def(py::init<double,double,double>())\n    .def(py::init([](py::tuple p)\n    {\n      return Point<3> { p[0].cast<double>(), p[1].cast<double>(),\n        p[2].cast<double>() };\n    }))\n    .def (\"__str__\", &ToString<Point<3>>)\n    .def(py::self-py::self)\n    .def(py::self+Vec<3>())\n    .def(py::self-Vec<3>())\n    .def(\"__getitem__\", [](Point<3>& self, int index) { return self[index]; })\n    .def(\"__setitem__\", [](Point<3>& self, int index, double value) { self[index] = value; })\n    .def(\"__len__\", [](Point<3>& /*unused*/) { return 3; })\n    ;\n\n  py::implicitly_convertible<py::tuple, Point<3>>();\n\n  m.def(\"Pnt\", [](double x, double y, double z)\n               { return global_trafo(Point<3>(x,y,z)); });\n  m.def(\"Pnt\", [](double x, double y) { return Point<2>(x,y); });\n  m.def(\"Pnt\", [](py::array_t<double> np_array)\n               {\n                 int dim = np_array.size();\n                 if(!(dim == 2 || dim == 3))\n                   throw Exception(\"Invalid dimension of input array!\");\n                 if(dim == 2)\n                   return py::cast(Point<2>(np_array.at(0),\n                                            np_array.at(1)));\n                 return py::cast(global_trafo(Point<3>(np_array.at(0),\n                                                       np_array.at(1),\n                                                       np_array.at(2))));\n               });\n\n  py::class_<Vec<2>> (m, \"Vec2d\")\n    .def(py::init<double,double>())\n    .def(py::init( [] (std::pair<double,double> xy)\n            {\n                return Vec<2>{xy.first, xy.second};\n            }))\n    .def (\"__str__\", &ToString<Vec<3>>)\n    .def(py::self==py::self)\n    .def(py::self+py::self)\n    .def(py::self-py::self)\n    .def(-py::self)\n    .def(double()*py::self)\n    .def(py::self*double())\n    .def(\"Norm\", &Vec<2>::Length)\n    .def(\"__getitem__\", [](Vec<2>& vec, int index) { return vec[index]; })\n    .def(\"__len__\", [](Vec<2>& /*unused*/) { return 2; })\n    ;\n\n  py::implicitly_convertible<py::tuple, Vec<2>>();\n\n  py::class_<Vec<3>> (m, \"Vec3d\")\n    .def(py::init<double,double,double>())\n    .def(py::init([](py::tuple v)\n    {\n      return Vec<3> { v[0].cast<double>(), v[1].cast<double>(),\n        v[2].cast<double>() };\n    }))\n    .def (\"__str__\", &ToString<Vec<3>>)\n    .def(py::self==py::self)\n    .def(py::self+py::self)\n    .def(py::self-py::self)\n    .def(-py::self)\n    .def(double()*py::self)\n    .def(py::self*double())\n    .def(\"Norm\", &Vec<3>::Length)\n    .def(\"__getitem__\", [](Vec<3>& vec, int index) { return vec[index]; })\n    .def(\"__len__\", [](Vec<3>& /*unused*/) { return 3; })\n    ;\n\n  py::implicitly_convertible<py::tuple, Vec<3>>();\n\n  py::class_<Mat<3,3>>(m, \"Mat33\")\n    .def(py::init([](py::tuple m)\n    {\n      if(m.size() != 9)\n        throw std::length_error(\"Invalid dimension of input array!\");\n      Mat<3,3> mat;\n      for(int i = 0; i < 3; i++)\n        for(int j = 0; j < 3; j++)\n          mat(i,j) = m[i*3+j].cast<double>();\n      return mat;\n    }))\n    .def(\"__getitem__\", [](Mat<3,3>& mat, py::tuple index)\n    {\n      if(index.size() != 2)\n        throw std::length_error(\"Invalid dimension of input array!\");\n      return mat(index[0].cast<int>(), index[1].cast<int>());\n    })\n    .def(\"__setitem__\", [](Mat<3,3>& mat, py::tuple index, double val)\n    {\n      if(index.size() != 2)\n        throw std::length_error(\"Invalid dimension of input array!\");\n      mat(index[0].cast<int>(), index[1].cast<int>()) = val;\n    })\n    .def(\"__str__\", &ToString<Mat<3,3>>)\n    ;\n\n  py::implicitly_convertible<py::tuple, Mat<3,3>>();\n\n  m.def (\"Vec\", FunctionPointer\n           ([] (double x, double y, double z) { return global_trafo(Vec<3>(x,y,z)); }));\n  m.def(\"Vec\", [](py::array_t<double> np_array)\n               {\n                 int dim = np_array.size();\n                 if(!(dim == 2 || dim == 3))\n                   throw Exception(\"Invalid dimension of input array!\");\n                 if(dim == 2)\n                   return py::cast(Vec<2>(np_array.at(0),\n                                          np_array.at(1)));\n                 return py::cast(global_trafo(Vec<3>(np_array.at(0),\n                                                     np_array.at(1),\n                                                     np_array.at(2))));\n               });\n\n  m.def (\"Vec\", FunctionPointer\n           ([] (double x, double y) { return Vec<2>(x,y); }));\n\n  py::class_<Transformation<3>> (m, \"Trafo\")\n    .def(py::init<Vec<3>>(), \"a translation\")\n    .def(py::init<Point<3>,Vec<3>,double>(), \"a rotation given by point on axes, direction of axes, angle\")\n    .def(\"__mul__\", [](Transformation<3> a, Transformation<3> b)->Transformation<3>\n         { Transformation<3> res; res.Combine(a,b); return res; })\n    .def(\"__call__\", [] (Transformation<3> trafo, Point<3> p) { return trafo(p); })\n    .def_property(\"mat\", &Transformation<3>::GetMatrix,\n                  [](Transformation<3>& self, const Mat<3,3>& mat)\n                  {\n                    self.GetMatrix() = mat;\n                  })\n    ;\n\n  m.def (\"GetTransformation\", [] () { return global_trafo; });\n  m.def (\"SetTransformation\", [] (Transformation<3> trafo) { global_trafo = trafo; });\n  m.def (\"SetTransformation\", \n         [](int dir, double angle)\n         {\n           if (dir > 0)\n             global_trafo.SetAxisRotation (dir, angle*M_PI/180);\n           else\n             global_trafo = Transformation<3> (Vec<3>(0,0,0));\n         },\n         py::arg(\"dir\")=int(0), py::arg(\"angle\")=int(0));\n  m.def (\"SetTransformation\", \n         [](Point<3> p0, Vec<3> ex, Vec<3> ey, Vec<3> ez)\n            {\n              Point<3> pnts[4];\n              pnts[0] = p0;\n              pnts[1] = p0 + ex;\n              pnts[2] = p0 + ey;\n              pnts[3] = p0 + ez;\n              global_trafo = Transformation<3> (pnts);\n            },\n         py::arg(\"p0\"), py::arg(\"ex\"), py::arg(\"ey\"), py::arg(\"ez\"));\n\n\n  \n  py::class_<PointIndex>(m, \"PointId\")\n    .def(py::init<int>())\n    .def(\"__repr__\", &ToString<PointIndex>)\n    .def(\"__str__\", &ToString<PointIndex>)\n    .def_property_readonly(\"nr\", &PointIndex::operator int)\n    .def(\"__eq__\" , FunctionPointer( [](PointIndex &self, PointIndex &other)\n                  { return static_cast<int>(self)==static_cast<int>(other); }) )\n    .def(\"__hash__\" , FunctionPointer( [](PointIndex &self ) { return static_cast<int>(self); }) )\n    ;\n\n  py::class_<ElementIndex>(m, \"ElementId3D\")\n    .def(py::init<int>())\n    .def(\"__repr__\", &ToString<ElementIndex>)\n    .def(\"__str__\", &ToString<ElementIndex>)\n    .def_property_readonly(\"nr\", &ElementIndex::operator int)\n    .def(\"__eq__\" , FunctionPointer( [](ElementIndex &self, ElementIndex &other)\n                  { return static_cast<int>(self)==static_cast<int>(other); }) )\n    .def(\"__hash__\" , FunctionPointer( [](ElementIndex &self ) { return static_cast<int>(self); }) )\n    ;\n\n\n  py::class_<SurfaceElementIndex>(m, \"ElementId2D\")\n    .def(py::init<int>())\n    .def(\"__repr__\", &ToString<SurfaceElementIndex>)\n    .def(\"__str__\", &ToString<SurfaceElementIndex>)\n    .def_property_readonly(\"nr\", &SurfaceElementIndex::operator int)\n    .def(\"__eq__\" , FunctionPointer( [](SurfaceElementIndex &self, SurfaceElementIndex &other)\n                  { return static_cast<int>(self)==static_cast<int>(other); }) )\n    .def(\"__hash__\" , FunctionPointer( [](SurfaceElementIndex &self ) { return static_cast<int>(self); }) )\n    ;\n\n  py::class_<SegmentIndex>(m, \"ElementId1D\")\n    .def(py::init<int>())\n    .def(\"__repr__\", &ToString<SegmentIndex>)\n    .def(\"__str__\", &ToString<SegmentIndex>)\n    .def_property_readonly(\"nr\", &SegmentIndex::operator int)\n    .def(\"__eq__\" , FunctionPointer( [](SegmentIndex &self, SegmentIndex &other)\n                  { return static_cast<int>(self)==static_cast<int>(other); }) )\n    .def(\"__hash__\" , FunctionPointer( [](SegmentIndex &self ) { return static_cast<int>(self); }) )\n    ;\n\n\n\n  /*  \n  py::class_<Point<3>> (\"Point\")\n    .def(py::init<double,double,double>())\n    ;\n  */\n\n  py::class_<MeshPoint /* ,py::bases<Point<3>> */ >(m, \"MeshPoint\")\n    .def(py::init<Point<3>>())\n    .def(\"__str__\", &ToString<MeshPoint>)\n    .def(\"__repr__\", &ToString<MeshPoint>)\n    .def_property_readonly(\"p\", [](const MeshPoint & self)\n                           {\n                             py::list l;\n                             l.append ( py::cast(self[0]) );\n                             l.append ( py::cast(self[1]) );\n                             l.append ( py::cast(self[2]) );\n                             return py::tuple(l);\n                           })\n    .def(\"__getitem__\", [](const MeshPoint & self, int index) {\n\t  if(index<0 || index>2)\n              throw py::index_error();\n\t  return self[index];\n\t})\n    .def(\"__setitem__\", [](MeshPoint & self, int index, double val) {\n\t  if(index<0 || index>2)\n              throw py::index_error();\n\t  self(index) = val;\n    })\n    .def_property(\"singular\",\n                  [](const MeshPoint & pnt) { return pnt.Singularity(); },\n                  [](MeshPoint & pnt, double sing) { pnt.Singularity(sing); })\n    ;\n\n  py::class_<Element>(m, \"Element3D\")\n    .def(py::init([](int index, std::vector<PointIndex> vertices)\n                  {\n                    int np = vertices.size();\n                    ELEMENT_TYPE et;\n                    switch (np)\n                      {\n                      case 4: et = TET; break;\n                      case 5: et = PYRAMID; break;\n                      case 6: et = PRISM; break;\n                      case 8: et = HEX; break;\n                      case 10: et = TET10; break;\n                      case 13: et = PYRAMID13; break;\n                      case 15: et = PRISM15; break;\n                      case 20: et = HEX20; break;\n                      default:\n                        throw Exception (\"no Element3D with \" + ToString(np) +\n                                         \" points\");\n                      }\n\n                    auto newel = new Element(et);\n                    for(int i=0; i<np; i++)\n                      (*newel)[i] = vertices[i];\n                    newel->SetIndex(index);\n                    return newel;\n                  }),\n          py::arg(\"index\")=1,py::arg(\"vertices\"),\n         \"create volume element\"\n         )\n    .def(\"__repr__\", &ToString<Element>)\n    .def_property(\"index\", &Element::GetIndex, &Element::SetIndex)\n    .def_property(\"curved\", &Element::IsCurved, &Element::SetCurved)\n    .def_property(\"refine\", &Element::TestRefinementFlag, &Element::SetRefinementFlag)\n    .def_property_readonly(\"vertices\", \n                  FunctionPointer ([](const Element & self) -> py::list\n                                   {\n                                     py::list li;\n                                     for (int i = 0; i < self.GetNV(); i++)\n                                       li.append (py::cast(self[i]));\n                                     return li;\n                                   }))\n    .def_property_readonly(\"points\", \n                  FunctionPointer ([](const Element & self) -> py::list\n                                   {\n                                     py::list li;\n                                     for (int i = 0; i < self.GetNP(); i++)\n                                       li.append (py::cast(self[i]));\n                                     return li;\n                                   }))\n    ;\n\n  if(ngcore_have_numpy)\n  {\n    auto data_layout = Element::GetDataLayout();\n\n    py::detail::npy_format_descriptor<Element>::register_dtype({\n        py::detail::field_descriptor {\n          \"nodes\", data_layout[\"pnum\"],\n          ELEMENT_MAXPOINTS * sizeof(PointIndex),\n          py::format_descriptor<int[ELEMENT_MAXPOINTS]>::format(),\n          py::detail::npy_format_descriptor<int[ELEMENT_MAXPOINTS]>::dtype() },\n        py::detail::field_descriptor {\n          \"index\", data_layout[\"index\"], sizeof(int),\n          py::format_descriptor<int>::format(),\n          py::detail::npy_format_descriptor<int>::dtype() },\n        py::detail::field_descriptor {\n          \"np\", data_layout[\"np\"], sizeof(int8_t),\n          py::format_descriptor<signed char>::format(),\n            pybind11::dtype(\"int8\") },\n        py::detail::field_descriptor {\n          \"refine\", data_layout[\"refine\"], sizeof(bool),\n          py::format_descriptor<bool>::format(),\n          py::detail::npy_format_descriptor<bool>::dtype() },            \n        py::detail::field_descriptor {\n          \"curved\", data_layout[\"curved\"], sizeof(bool),\n          py::format_descriptor<bool>::format(),\n          py::detail::npy_format_descriptor<bool>::dtype()}            \n      });\n  }\n\n  py::class_<Element2d>(m, \"Element2D\")\n    .def(py::init ([](int index, std::vector<PointIndex> vertices,\n                      std::optional<std::vector<std::array<double,2>>> uv)\n                   {\n                     Element2d * newel = nullptr;\n                     if (vertices.size() == 3)\n                       {\n                         newel = new Element2d(TRIG);\n                         for (int i = 0; i < 3; i++)\n                           (*newel)[i] = vertices[i];\n                         newel->SetIndex(index);\n                       }\n                     else if (vertices.size() == 4)\n                       {\n                         newel = new Element2d(QUAD);\n                         for (int i = 0; i < 4; i++)\n                           (*newel)[i] = vertices[i];\n                         newel->SetIndex(index);\n                       }\n                     else if (vertices.size() == 6)\n                       {\n                         newel = new Element2d(TRIG6);\n                         for(int i = 0; i<6; i++)\n                           (*newel)[i] = vertices[i];\n                         newel->SetIndex(index);\n                       }\n                     else if (vertices.size() == 8)\n                       {\n                         newel = new Element2d(QUAD8);\n                         for(int i = 0; i<8; i++)\n                           (*newel)[i] = vertices[i];\n                         newel->SetIndex(index);\n                       }\n                     else \n                       throw NgException(\"Inconsistent number of vertices in Element2D\");\n                     if (uv.has_value())\n                       {\n                         auto vecuv = *uv;\n                         if (vecuv.size() != vertices.size())\n                           throw NgException(\"wrong number of uv-parameters\");\n                         for (int i = 0; i < vertices.size(); i++)\n                           {\n                             PointGeomInfo gi;\n                             gi.u = vecuv[i][0];\n                             gi.v = vecuv[i][1];\n                             newel->GeomInfo()[i] = gi;\n                           }\n                       }\n                     return newel;\n                   }),\n         py::arg(\"index\")=1,py::arg(\"vertices\"), py::arg(\"uv\")=std::nullopt,\n         \"create surface element\"\n         )\n    .def_property(\"index\", &Element2d::GetIndex, &Element2d::SetIndex)\n    .def_property(\"curved\", &Element2d::IsCurved, &Element2d::SetCurved)\n    .def_property(\"refine\", &Element2d::TestRefinementFlag, &Element2d::SetRefinementFlag)\n    .def_property(\"uv\",\n                  [](const Element2d & self) {\n                    std::vector<std::array<double,2>> uv(self.GetNP());\n                    for (int i = 0; i < uv.size(); i++)\n                      {\n                        double u = self.GeomInfo()[i].u;\n                        double v = self.GeomInfo()[i].v;\n                        uv[i] = std::array<double,2>{u,v};\n                      }\n                    return uv;\n                  },\n                  [](Element2d & self, const std::vector<std::array<double,2>> & uv) {\n                    if (uv.size() != self.GetNP())\n                      throw NgException(\"wrong number of uv-parameters\");\n                    for (int i = 0; i < uv.size(); i++)\n                      {\n                        PointGeomInfo gi;\n                        gi.u = uv[i][0];\n                        gi.v = uv[i][1];\n                        self.GeomInfo()[i] = gi;\n                      }\n                  })\n    .def_property_readonly(\"geominfo\", [](const Element2d& self) -> py::list\n    {\n      py::list li;\n      for (const auto &pgi : self.GeomInfo())\n        li.append(py::make_tuple(pgi.trignum, pgi.u, pgi.v));\n      return li;\n    })\n    .def_property_readonly(\"vertices\",\n                  FunctionPointer([](const Element2d & self) -> py::list\n                                  {\n                                    py::list li;\n                                    for (int i = 0; i < self.GetNV(); i++)\n                                      li.append(py::cast(self[i]));\n                                    return li;\n                                  }))\n    .def_property_readonly(\"points\", \n                  FunctionPointer ([](const Element2d & self) -> py::list\n                                   {\n                                     py::list li;\n                                     for (int i = 0; i < self.GetNP(); i++)\n                                       li.append (py::cast(self[i]));\n                                     return li;\n                                   }))    \n    ;\n\n  if(ngcore_have_numpy)\n  {\n    auto data_layout = Element2d::GetDataLayout();\n    py::detail::npy_format_descriptor<Element2d>::register_dtype({\n        py::detail::field_descriptor {\n          \"nodes\", data_layout[\"pnum\"],\n          ELEMENT2D_MAXPOINTS * sizeof(PointIndex),\n          py::format_descriptor<int[ELEMENT2D_MAXPOINTS]>::format(),\n          py::detail::npy_format_descriptor<int[ELEMENT2D_MAXPOINTS]>::dtype() },\n        py::detail::field_descriptor {\n          \"index\", data_layout[\"index\"], sizeof(int),\n          py::format_descriptor<int>::format(),\n          py::detail::npy_format_descriptor<int>::dtype() },\n        py::detail::field_descriptor {\n          \"np\", data_layout[\"np\"], sizeof(int8_t),\n          py::format_descriptor<signed char>::format(),\n        pybind11::dtype(\"int8\") },\n        py::detail::field_descriptor {\n          \"refine\", data_layout[\"refine\"], sizeof(bool),\n          py::format_descriptor<bool>::format(),\n          py::detail::npy_format_descriptor<bool>::dtype() },\n        py::detail::field_descriptor {\n          \"curved\", data_layout[\"curved\"], sizeof(bool),\n          py::format_descriptor<bool>::format(),\n          py::detail::npy_format_descriptor<bool>::dtype() }\n      });\n  }\n\n  py::class_<Segment>(m, \"Element1D\")\n    .def(py::init([](py::list vertices, py::list surfaces, int index, int edgenr,\n                     py::list trignums)\n                  {\n                    Segment * newel = new Segment();\n                    for (int i = 0; i < 2; i++)\n                      (*newel)[i] = py::extract<PointIndex>(vertices[i])();\n                    newel -> si = index;\n                    newel -> epgeominfo[0].edgenr = edgenr;\n                    newel -> epgeominfo[1].edgenr = edgenr;\n                    newel -> edgenr = index;\n                    newel -> index = index;\n                    for(auto i : Range(len(trignums)))\n                      newel->geominfo[i].trignum = py::cast<int>(trignums[i]);\n                    if (len(surfaces))\n                      {\n                        newel->surfnr1 = py::extract<int>(surfaces[0])();\n                        newel->surfnr2 = py::extract<int>(surfaces[1])();\n                      }\n                    return newel;\n                  }),\n          py::arg(\"vertices\"),\n           py::arg(\"surfaces\")=py::list(),\n           py::arg(\"index\")=1,\n           py::arg(\"edgenr\")=1,\n           py::arg(\"trignums\")=py::list(), // for stl\n         \"create segment element\"\n         )\n    .def(\"__repr__\", &ToString<Segment>)\n    .def_property_readonly(\"vertices\", \n                  FunctionPointer ([](const Segment & self) -> py::list\n                                   {\n                                     py::list li;\n                                     for (int i = 0; i < 2; i++)\n                                       li.append (py::cast(self[i]));\n                                     return li;\n                                   }))\n    .def_property_readonly(\"points\", \n                  FunctionPointer ([](const Segment & self) -> py::list\n                                   {\n                                     py::list li;\n                                     for (int i = 0; i < self.GetNP(); i++)\n                                       li.append (py::cast(self[i]));\n                                     return li;\n                                   }))\n    .def_property_readonly(\"surfaces\", \n                  FunctionPointer ([](const Segment & self) -> py::list\n                                   {\n                                     py::list li;\n                                     li.append (py::cast(self.surfnr1));\n                                     li.append (py::cast(self.surfnr2));\n                                     return li;\n                                   }))\n    .def_property(\"index\",\n                  [](const Segment &self)\n                  {\n                    return self.GetIndex();\n                  },\n                  [](Segment& self, int index)\n                  {\n                    self.SetIndex(index);\n                  })\n    .def_property(\"edgenr\",\n                  [](const Segment & self)\n                  {\n                    return self.GetEdgeNr();\n                  },\n                  [](Segment& self, int edgenr)\n                  {\n                    self.SetEdgeNr(edgenr); \n                  })\n    .def_property(\"singular\",\n                  [](const Segment & seg) { return seg.singedge_left; },\n                  [](Segment & seg, double sing) { seg.singedge_left = sing; seg.singedge_right=sing; })\n    ;\n\n  if(ngcore_have_numpy)\n  {\n    py::detail::npy_format_descriptor<Segment>::register_dtype({\n        py::detail::field_descriptor {\n          \"nodes\", offsetof(Segment, pnums),\n          3 * sizeof(PointIndex),\n          py::format_descriptor<int[3]>::format(),\n          py::detail::npy_format_descriptor<int[3]>::dtype() },\n        py::detail::field_descriptor {\n          \"index\", offsetof(Segment, si), sizeof(int),\n          py::format_descriptor<int>::format(),\n          py::detail::npy_format_descriptor<int>::dtype() },\n        py::detail::field_descriptor {\n          \"edgenr\", offsetof(Segment, edgenr), sizeof(int),\n          py::format_descriptor<int>::format(),\n          py::detail::npy_format_descriptor<int>::dtype() },\n      });\n  }\n\n  py::class_<Element0d>(m, \"Element0D\")\n    .def(py::init([](PointIndex vertex, int index)\n                  {\n                    Element0d * instance = new Element0d;\n                    instance->pnum = vertex;\n                    instance->index = index;\n                    return instance;\n                  }),\n         py::arg(\"vertex\"),\n         py::arg(\"index\")=1,\n         \"create point element\"\n         )\n    .def(\"__repr__\", &ToString<Element0d>)\n    .def_property_readonly(\"vertices\", \n                  FunctionPointer ([](const Element0d & self) -> py::list\n                                   {\n                                     py::list li;\n                                     li.append (py::cast(self.pnum));\n                                     return li;\n                                   }))\n    ;\n  \n  \n  \n\n\n  py::class_<FaceDescriptor>(m, \"FaceDescriptor\")\n    .def(py::init<const FaceDescriptor&>())\n    .def(py::init([](int surfnr, int domin, int domout, int bc)\n                  {\n                    FaceDescriptor * instance = new FaceDescriptor();\n                    instance->SetSurfNr(surfnr);\n                    instance->SetDomainIn(domin);\n                    instance->SetDomainOut(domout);\n                    instance->SetBCProperty(bc);\n                             return instance;\n                  }),\n         py::arg(\"surfnr\")=1, \n         py::arg(\"domin\")=1,\n         py::arg(\"domout\")=py::int_(0),\n         py::arg(\"bc\")=py::int_(0),\n         \"create facedescriptor\")\n    .def(\"__str__\", &ToString<FaceDescriptor>)\n    .def(\"__repr__\", &ToString<FaceDescriptor>)\n    .def_property(\"surfnr\", &FaceDescriptor::SurfNr, &FaceDescriptor::SetSurfNr)\n    .def_property(\"domin\", &FaceDescriptor::DomainIn, &FaceDescriptor::SetDomainIn)\n    .def_property(\"domout\", &FaceDescriptor::DomainOut, &FaceDescriptor::SetDomainOut)\n    .def_property(\"domin_singular\", &FaceDescriptor::DomainInSingular, &FaceDescriptor::SetDomainInSingular)\n    .def_property(\"domout_singular\", &FaceDescriptor::DomainOutSingular, &FaceDescriptor::SetDomainOutSingular)\n\n    .def_property(\"bc\", &FaceDescriptor::BCProperty, &FaceDescriptor::SetBCProperty)\n    .def_property(\"bcname\",\n                  [](FaceDescriptor & self) -> string { return self.GetBCName(); },\n                  [](FaceDescriptor & self, string name) { self.SetBCName(new string(name)); } // memleak\n                  )\n    .def_property(\"color\",\n                  [](const FaceDescriptor& self)\n                  {\n                    auto sc = self.SurfColour();\n                    return py::make_tuple(sc[0], sc[1], sc[2], sc[3]);\n                  },\n                  [](FaceDescriptor& self, py::tuple col)\n                  {\n                    Vec<4> sc = 1;\n                    sc[0] = py::cast<double>(col[0]);\n                    sc[1] = py::cast<double>(col[1]);\n                    sc[2] = py::cast<double>(col[2]);\n                    if(py::len(col) > 3)\n                      sc[3] = py::cast<double>(col[3]);\n                    self.SetSurfColour(sc);\n                  }\n                  )\n    .def_property(\"transparency\",\n                  [](const FaceDescriptor& self)\n                  {\n                    return self.SurfColour()[3];\n                  },\n                  [](FaceDescriptor& self, double val)\n                  {\n                    auto sc = self.SurfColour();\n                    sc[3] = val;\n                    self.SetSurfColour(sc);\n                  })\n    ;\n\n  py::implicitly_convertible< int, SurfaceElementIndex>();\n  PYBIND11_NUMPY_DTYPE(SurfaceElementIndex, i);\n  ExportArray<SurfaceElementIndex, SurfaceElementIndex>(m);\n  \n  py::implicitly_convertible< int, ElementIndex>();\n  PYBIND11_NUMPY_DTYPE(ElementIndex, i);\n  ExportArray<ElementIndex, ElementIndex>(m);\n  \n  ExportArray<Element,ElementIndex>(m);\n  ExportArray<Element2d,SurfaceElementIndex>(m);\n  ExportArray<Segment,SegmentIndex>(m);\n  ExportArray<Element0d>(m);\n  ExportArray<MeshPoint,PointIndex>(m);\n  ExportArray<FaceDescriptor>(m);\n\n  string export_docu = \"Export mesh to other file format. Supported formats are:\\n\";\n  Array<string> export_formats;\n  for(auto & kv : UserFormatRegister::getFormats()) {\n    const auto e = kv.second;\n    if(e.write) {\n      string s = '\\t'+e.format+\"\\t(\"+e.extensions[0];\n      for(auto & ext : e.extensions.Range(1, e.extensions.Size()))\n        s += \", \"+ext;\n      s += \")\\n\";\n      export_formats.Append(s);\n    }\n  }\n  QuickSort(export_formats);\n  for(const auto & s : export_formats)\n    export_docu += s;\n\n  py::implicitly_convertible< int, PointIndex>();\n\n  py::class_<PointGeomInfo>(m, \"PointGeomInfo\")\n    .def(py::init<>())\n    .def_readwrite(\"trignum\", &PointGeomInfo::trignum)\n    .def_readwrite(\"u\", &PointGeomInfo::u)\n    .def_readwrite(\"v\", &PointGeomInfo::v)\n  ;\n\n  py::class_<EdgePointGeomInfo>(m, \"EdgePointGeomInfo\")\n    .def(py::init<>())\n    .def_readwrite(\"edgenr\", &EdgePointGeomInfo::edgenr)\n    .def_readwrite(\"dist\", &EdgePointGeomInfo::dist)\n    .def_readwrite(\"u\", &EdgePointGeomInfo::u)\n    .def_readwrite(\"v\", &EdgePointGeomInfo::v)\n  ;\n\n  class NetgenGeometryTrampoline : public NetgenGeometry {\n    public:\n      using NetgenGeometry::NetgenGeometry;\n      NetgenGeometryTrampoline() : NetgenGeometry()\n          {\n            static_assert( sizeof(NetgenGeometry)==sizeof(NetgenGeometryTrampoline), \"Size of NetgenGeometry and NetgenGeometryTrampoline differ\");\n          }\n\n      Vec<3> GetNormal (int surfind, const Point<3> &p, const PointGeomInfo *gi) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"GetNormal\"))\n          return py::cast<Vec<3>> (overload(surfind, p, gi));\n        else\n            throw Exception (\"GetNormal not implemented\");\n      }\n      PointGeomInfo ProjectPoint(int surfind, Point<3> & p) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"ProjectPoint\"))\n          return py::cast<PointGeomInfo> (overload(surfind, py::cast(p, py::return_value_policy::reference)));\n        else\n            throw Exception (\"ProjectPoint not implemented\");\n      }\n\n      void ProjectPointEdge(int surfind, int surfind2, Point<3> & p,\n                                    EdgePointGeomInfo* gi = nullptr) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"ProjectPointEdge\"))\n          overload(surfind, surfind2,\n              py::cast(p, py::return_value_policy::reference),\n              py::cast(gi, py::return_value_policy::reference));\n        throw Exception (\"ProjectPointEdge not implemented\");\n      }\n\n      bool ProjectPointGI(int surfind, Point<3> & p,\n                                  PointGeomInfo & gi) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"ProjectPointGI\"))\n          return py::cast<bool> (overload(surfind, p, gi));\n        else if (auto overload = pybind11::get_overload(this, \"ProjectPoint\"))\n            return py::cast<bool> (overload(surfind, py::cast(p, py::return_value_policy::reference)));\n        else\n            throw Exception (\"Neither ProjectPointGI nor ProjectPoint implemented\");\n      }\n\n      bool CalcPointGeomInfo(int surfind, PointGeomInfo& gi,\n                                     const Point<3> & p3) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"CalcPointGeomInfo\"))\n          return py::cast<bool> (overload(surfind, py::cast(gi, py::return_value_policy::reference), p3));\n        else\n            throw Exception (\"CalcPointGeomInfo not implemented\");\n      }\n\n      void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2,\n                                    double secpoint,\n                                    int surfi1, int surfi2,\n                                    const EdgePointGeomInfo & ap1,\n                                    const EdgePointGeomInfo & ap2,\n                                    Point<3> & newp,\n                                    EdgePointGeomInfo & newgi) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"PointBetweenEdge\"))\n          overload(p1, p2, secpoint, surfi1, surfi2, ap1, ap2,\n              py::cast(newp, py::return_value_policy::reference),\n              py::cast(newgi, py::return_value_policy::reference));\n        else\n            throw Exception (\"PointBetweenEdge not implemented\");\n      }\n\n      void PointBetween(const Point<3> & p1, const Point<3> & p2,\n                                double secpoint,\n                                int surfi,\n                                const PointGeomInfo & gi1,\n                                const PointGeomInfo & gi2,\n                                Point<3> & newp,\n                                PointGeomInfo & newgi) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"PointBetween\"))\n          overload(p1, p2, secpoint, surfi, gi1, gi2,\n              py::cast(newp, py::return_value_policy::reference),\n              py::cast(newgi, py::return_value_policy::reference));\n        else\n            throw Exception (\"PointBetween not implemented\");\n      }\n\n      Vec<3> GetTangent(const Point<3> & p, int surfi1,\n                                int surfi2,\n                                const EdgePointGeomInfo & egi) const override {\n        py::gil_scoped_acquire gil;\n        if (auto overload = pybind11::get_overload(this, \"GetTangent\"))\n          return py::cast<Vec<3>> (overload(p, surfi1, surfi2, egi));\n        throw Exception (\"GetTangent not implemented\");\n      }\n\n    };\n\n  py::class_<NetgenGeometry, shared_ptr<NetgenGeometry>, NetgenGeometryTrampoline> (m, \"NetgenGeometry\", py::dynamic_attr())\n    .def(py::init<> ())\n    .def(\"RestrictH\", &NetgenGeometry::RestrictH)\n             ;\n  \n  py::class_<Mesh,shared_ptr<Mesh>>(m, \"Mesh\")\n    // .def(py::init<>(\"create empty mesh\"))\n\n    .def(py::init( [] (int dim, NgMPI_Comm comm)\n                   {\n                     auto mesh = make_shared<Mesh>();\n\t\t     mesh->SetCommunicator(comm);\n                     mesh -> SetDimension(dim);\n                     SetGlobalMesh(mesh);  // for visualization\n                     mesh -> SetGeometry (nullptr);\n                     return mesh;\n                   } ),\n         py::arg(\"dim\")=3, py::arg(\"comm\")=NgMPI_Comm{}\n         )\n    .def(NGSPickle<Mesh>())\n    .def_property_readonly(\"comm\", [](const Mesh & amesh) -> NgMPI_Comm\n\t\t\t   { return amesh.GetCommunicator(); },\n                           \"MPI-communicator the Mesh lives in\")\n    /*\n    .def(\"__init__\",\n         [](Mesh *instance, int dim)\n                           {\n                             new (instance) Mesh();\n                             instance->SetDimension(dim);\n                           },\n           py::arg(\"dim\")=3\n          )\n    */\n    \n    .def_property_readonly(\"_timestamp\", &Mesh::GetTimeStamp)\n    .def_property_readonly(\"ne\", [](Mesh& m) { return m.GetNE(); })\n    .def_property_readonly(\"bounding_box\", [](Mesh& m) {\n          Point3d pmin, pmax;\n          m.GetBox(pmin, pmax);\n          return py::make_tuple( Point<3>(pmin),Point<3>(pmax));\n    })\n    .def(\"Partition\", [](shared_ptr<Mesh> self, int numproc) {\n        self->ParallelMetis(numproc);\n      }, py::arg(\"numproc\"))\n    \n    .def(\"Distribute\", [](shared_ptr<Mesh> self, NgMPI_Comm comm) {\n\tself->SetCommunicator(comm);\n\tif(comm.Size()==1) return self;\n\t// if(MyMPI_GetNTasks(comm)==2) throw NgException(\"Sorry, cannot handle communicators with NP=2!\");\n\t// cout << \" rank \" << MyMPI_GetId(comm) << \" of \" << MyMPI_GetNTasks(comm) << \" called Distribute \" << endl;\n\tif(comm.Rank()==0) self->Distribute();\n\telse self->SendRecvMesh();\n\treturn self;\n      }, py::arg(\"comm\"))\n    .def_static(\"Receive\", [](NgMPI_Comm comm) -> shared_ptr<Mesh> {\n        auto mesh = make_shared<Mesh>();\n        mesh->SetCommunicator(comm);\n        mesh->SendRecvMesh();\n        return mesh;\n      }, py::arg(\"comm\"))\n    .def(\"Load\",  FunctionPointer \n\t ([](shared_ptr<Mesh> self, const string & filename)\n\t  {\n\n\t    auto comm = self->GetCommunicator();\n\t    int id = comm.Rank();\n\t    int ntasks = comm.Size();\n\t    auto & mesh = self;\n\n\t    {\n\t      ifstream infile(filename.c_str());\n\t      if(!infile.good())\n\t\tthrow NgException(string(\"Error opening file \") + filename);\n\t    }\n\n\t    if ( filename.find(\".vol\") == string::npos )\n\t      {\n\t\tif(ntasks>1)\n\t\t  throw NgException(\"Not sure what to do with this?? Does this work with MPI??\");\n\t\tmesh->SetCommunicator(comm);\n\t\tReadFile(*mesh,filename.c_str());\n\t\t//mesh->SetGlobalH (mparam.maxh);\n\t\t//mesh->CalcLocalH();\n\t\treturn;\n\t      }\n\n\t    istream * infile = nullptr;\n\t    Array<char> buf; // for distributing geometry!\n\t    int strs;\n\n\t    if( id == 0) {\n\t      if (filename.length() > 8 && filename.substr (filename.length()-8, 8) == \".vol.bin\")\n                mesh -> Load(filename);\n              else if (filename.substr (filename.length()-3, 3) == \".gz\")\n\t\tinfile = new igzstream (filename.c_str());\n\t      else\n\t\tinfile = new ifstream (filename.c_str());\n\n              if(infile)\n                {\n                  mesh -> Load(*infile);\n                  // make string from rest of file (for geometry info!)\n                  // (this might be empty, in which case we take the global ng_geometry)\n                  stringstream geom_part;\n                  geom_part << infile->rdbuf();\n                  string geom_part_string = geom_part.str();\n                  strs = geom_part_string.size();\n                  // buf = new char[strs];\n                  buf.SetSize(strs);\n                  memcpy(buf.Data(), geom_part_string.c_str(), strs*sizeof(char));\n                  delete infile;\n                }\n\n\n\t      if (ntasks > 1)\n\t\t{\n\n\t\t  char * weightsfilename = new char [filename.size()+1];\n\t\t  strcpy (weightsfilename, filename.c_str());            \n\t\t  weightsfilename[strlen (weightsfilename)-3] = 'w';\n\t\t  weightsfilename[strlen (weightsfilename)-2] = 'e';\n\t\t  weightsfilename[strlen (weightsfilename)-1] = 'i';\n\n\t\t  ifstream weightsfile(weightsfilename);      \n\t\t  delete [] weightsfilename;  \n\t  \n\t\t  if (!(weightsfile.good()))\n\t\t    {\n\t\t      // cout << \"regular distribute\" << endl;\n\t\t      mesh -> Distribute();\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      char str[20];   \n\t\t      bool endfile = false;\n\t\t      int n, dummy;\n\t      \n\t\t      NgArray<int> segment_weights;\n\t\t      NgArray<int> surface_weights;\n\t\t      NgArray<int> volume_weights;\n\t      \n\t\t      while (weightsfile.good() && !endfile)\n\t\t\t{\n\t\t\t  weightsfile >> str;\n\t\t  \n\t\t\t  if (strcmp (str, \"edgeweights\") == 0)\n\t\t\t    {\n\t\t\t      weightsfile >> n;\n\t\t\t      segment_weights.SetSize(n);\n\t\t\t      for (int i = 0; i < n; i++)\n\t\t\t\tweightsfile >> dummy >> segment_weights[i];\n\t\t\t    }\n\t\t  \n\t\t\t  if (strcmp (str, \"surfaceweights\") == 0)\n\t\t\t    {\n\t\t\t      weightsfile >> n;\n\t\t\t      surface_weights.SetSize(n);\n\t\t\t      for (int i=0; i<n; i++)\n\t\t\t\tweightsfile >> dummy >> surface_weights[i];\n\t\t\t    }\n\t\t  \n\t\t\t  if (strcmp (str, \"volumeweights\") == 0)\n\t\t\t    {\n\t\t\t      weightsfile >> n;\n\t\t\t      volume_weights.SetSize(n);\n\t\t\t      for (int i=0; i<n; i++)\n\t\t\t\tweightsfile >> dummy >> volume_weights[i];\n\t\t\t    }\n\t\t  \n\t\t\t  if (strcmp (str, \"endfile\") == 0)\n\t\t\t    endfile = true;  \n\t\t\t}     \n\t      \n\t\t      mesh -> Distribute(volume_weights, surface_weights, segment_weights);\n\t\t    }\n\t\t} // ntasks>1 end\n\t    } // id==0 end\n\t    else {\n\t      mesh->SendRecvMesh();\n\t    }\n\n\t    if(ntasks>1) {\n              // #ifdef PARALLEL\n\t      /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/\n              /*\n\t      int strs = buf.Size();\n\t      MyMPI_Bcast(strs, comm);\n\t      if(strs>0)\n\t\tMyMPI_Bcast(buf, comm);\n              */\n              comm.Bcast(buf);\n              // #endif\n\t    }\n\n\t    shared_ptr<NetgenGeometry> geo;\n\t    if(buf.Size()) { // if we had geom-info in the file, take it\n\t      istringstream geom_infile(string((const char*)buf.Data(), buf.Size()));\n\t      geo = GeometryRegister().LoadFromMeshFile(geom_infile);\n\t    }\n\t    if(geo!=nullptr) mesh->SetGeometry(geo);\n\t    else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry);\n\t  }),py::call_guard<py::gil_scoped_release>())\n    .def(\"Save\", static_cast<void(Mesh::*)(const filesystem::path & name)const>(&Mesh::Save),py::call_guard<py::gil_scoped_release>())\n    .def(\"Export\",\n         [] (Mesh & self, string filename, string format)\n          {\n            if (WriteUserFormat (format, self, filename))\n                throw Exception (\"Nothing known about format\"+format);\n          },\n         py::arg(\"filename\"), py::arg(\"format\"), export_docu.c_str(),\n         py::call_guard<py::gil_scoped_release>())\n    \n    .def_property(\"dim\", &Mesh::GetDimension, &Mesh::SetDimension)\n\n    .def(\"Elements3D\", \n         static_cast<Array<Element,ElementIndex>&(Mesh::*)()> (&Mesh::VolumeElements),\n         py::return_value_policy::reference)\n\n    .def(\"Elements2D\", \n         static_cast<Array<Element2d,SurfaceElementIndex>&(Mesh::*)()> (&Mesh::SurfaceElements),\n         py::return_value_policy::reference)\n\n    .def(\"Elements1D\", \n         static_cast<Array<Segment, SegmentIndex>&(Mesh::*)()> (&Mesh::LineSegments),\n         py::return_value_policy::reference)\n\n    .def(\"Elements0D\", FunctionPointer([] (Mesh & self) -> Array<Element0d>&\n                                       {\n                                         return self.pointelements;\n                                       } ),\n         py::return_value_policy::reference)\n\n    .def(\"Points\", \n         static_cast<Mesh::T_POINTS&(Mesh::*)()> (&Mesh::Points),\n         py::return_value_policy::reference)\n\n    .def(\"Coordinates\", [](Mesh & self) {\n        return py::array\n          (\n           py::memoryview::from_buffer\n           (&self.Points()[PointIndex::BASE](0), sizeof(double),\n            py::format_descriptor<double>::value,\n            { self.Points().Size(), size_t(self.GetDimension())  }, \n            { sizeof(self.Points()[PointIndex::BASE]), sizeof(double) } )\n           );\n      })\n    .def_property_readonly(\"parentelements\", py::cpp_function([](Mesh & self) {\n      return FlatArray(self.mlparentelement);\n    }, py::keep_alive<0,1>()))\n    .def_property_readonly(\"parentsurfaceelements\", py::cpp_function([](Mesh & self) {\n      return FlatArray(self.mlparentsurfaceelement);      \n    }, py::keep_alive<0,1>()))\n    .def_property_readonly(\"macromesh\", [](Mesh & self) {\n      auto coarsemesh = make_shared<Mesh>();\n      *coarsemesh = *self.coarsemesh;\n      return coarsemesh;\n    }, \"mesh before hp-refinement\")\n    .def(\"MacroElementNr\", [](Mesh & self, int elnr, optional<int> dim) {\n      // cout << \"hpels = \" << self.hpelements->Size() << endl;\n      // return self[ElementIndex(elnr)].GetHpElnr();\n      if (!dim) dim = self.GetDimension();\n      switch (*dim)\n        {\n        case 2:\n          return (*self.hpelements)[self[SurfaceElementIndex(elnr)].GetHpElnr()].coarse_elnr;\n        case 3:\n          return (*self.hpelements)[self[ElementIndex(elnr)].GetHpElnr()].coarse_elnr;\n        }\n      throw Exception (\"MacroElementNr not implemented for dim\");\n    }, py::arg(\"elnr\"), py::arg(\"dim\")=nullopt, \"number of macro element of element number elnr\")\n    .def(\"FaceDescriptor\", static_cast<FaceDescriptor&(Mesh::*)(int)> (&Mesh::GetFaceDescriptor),\n         py::return_value_policy::reference)\n    .def(\"GetNFaceDescriptors\", &Mesh::GetNFD)\n    .def(\"RestrictLocalH\", [](Mesh& self, const Point<3>& pnt, double maxh,\n                              int layer)\n    {\n      self.RestrictLocalH(pnt, maxh, layer);\n    }, py::arg(\"p\"), py::arg(\"h\"), py::arg(\"layer\")=1)\n    .def(\"FaceDescriptors\", \n         // static_cast<Array<Element>&(Mesh::*)()> (&Mesh::FaceDescriptors),\n         &Mesh::FaceDescriptors,         \n         py::return_value_policy::reference)\n    \n    \n    .def(\"GetNDomains\", &Mesh::GetNDomains)\n\n    .def(\"GetVolumeNeighboursOfSurfaceElement\", [](Mesh & self, size_t sel)\n                                                {\n                                                  int elnr1, elnr2;\n                                                  self.GetTopology().GetSurface2VolumeElement(sel+1, elnr1, elnr2);\n                                                  return py::make_tuple(elnr1, elnr2);\n                                                }, \"Returns element nrs of volume element connected to surface element, -1 if no volume element\")\n\n    .def(\"GetNCD2Names\", &Mesh::GetNCD2Names)\n    \n\n    .def(\"__getitem__\", [](const Mesh & self, PointIndex id) { return self[id]; })\n    .def(\"__getitem__\", [](const Mesh & self, ElementIndex id) { return self[id]; })\n    .def(\"__getitem__\", [](const Mesh & self, SurfaceElementIndex id) { return self[id]; })\n    .def(\"__getitem__\", [](const Mesh & self, SegmentIndex id) { return self[id]; })\n\n    .def(\"__setitem__\", [](Mesh & self, PointIndex id, const MeshPoint & mp) { return self[id] = mp; })\n    \n    .def (\"Add\", [](Mesh & self, MeshPoint p)\n          {\n            return self.AddPoint (Point3d(p));\n          })\n          \n    .def (\"Add\", [](Mesh & self, const Element & el)\n          {\n            return self.AddVolumeElement (el);\n          })\n          \n    .def (\"Add\", [](Mesh & self, const Element2d & el)\n          {\n            return self.AddSurfaceElement (el);\n          })\n\n    .def (\"Add\", [](Mesh & self, const Segment & el, bool project_geominfo)\n          {\n            if (project_geominfo)\n              {\n                auto &p1 = self[el[0]];\n                auto &p2 = self[el[1]];\n                auto geo = self.GetGeometry();\n                geo->ProjectPointEdge\n                  (0,0,p1,\n                   const_cast<EdgePointGeomInfo*>(&el.epgeominfo[0]));\n                geo->ProjectPointEdge\n                  (0,0,p2,\n                   const_cast<EdgePointGeomInfo*>(&el.epgeominfo[1]));\n              }\n            return self.AddSegment (el);\n          }, py::arg(\"el\"), py::arg(\"project_geominfo\")=false)\n          \n    .def (\"Add\", [](Mesh & self, const Element0d & el)\n          {\n            return self.pointelements.Append (el);\n          })\n\n    .def (\"Add\", [](Mesh & self, const FaceDescriptor & fd)\n          {\n            return self.AddFaceDescriptor (fd);\n          })\n\n    .def (\"AddSingularity\", [](Mesh & self, PointIndex pi, double factor)\n         {\n\t   self[pi].Singularity(factor);\n         })\n\n    .def (\"AddPoints\", [](Mesh & self, py::buffer b1)\n          {\n            static Timer timer(\"Mesh::AddPoints\");\n            static Timer timercast(\"Mesh::AddPoints - casting\");            \n            RegionTimer reg(timer);\n\n            timercast.Start();\n            // casting from here: https://github.com/pybind/pybind11/issues/1908\n            auto b = b1.cast<py::array_t<double_t, py::array::c_style | py::array::forcecast>>();\n            timercast.Stop();\n            \n            py::buffer_info info = b.request();\n            // cout << \"data format = \" << info.format << endl;\n            if (info.ndim != 2)\n              throw std::runtime_error(\"AddPoints needs buffer of dimension 2\");\n            // if (info.format != py::format_descriptor<double>::format())\n            // throw std::runtime_error(\"AddPoints needs buffer of type double\");\n            if (info.strides[0] != sizeof(double)*info.shape[1])\n              throw std::runtime_error(\"AddPoints needs packed array\");              \n            double * ptr = static_cast<double*> (info.ptr);\n            \n            self.Points().SetAllocSize(self.Points().Size()+info.shape[0]);\n            if (info.shape[1]==2)\n              for ([[maybe_unused]] auto i : Range(info.shape[0]))\n                {\n                  self.AddPoint (Point<3>(ptr[0], ptr[1], 0));\n                  ptr += 2;\n                }\n            if (info.shape[1]==3)\n              for ([[maybe_unused]] auto i : Range(info.shape[0]))\n                {\n                  self.AddPoint (Point<3>(ptr[0], ptr[1], ptr[2]));\n                  ptr += 3;\n                }\n          })\n    .def (\"AddElements\", [](Mesh & self, int dim, int index, py::buffer b1, int base,\n                            bool project_geometry)\n          {\n            static Timer timer(\"Mesh::AddElements\");\n            static Timer timercast(\"Mesh::AddElements casting\");\n            RegionTimer reg(timer);\n\n            timercast.Start();\n            auto b = b1.cast<py::array_t<int, py::array::c_style | py::array::forcecast>>();\n            timercast.Stop();\n            \n            py::buffer_info info = b.request();\n            if (info.ndim != 2)\n              throw std::runtime_error(\"AddElements needs buffer of dimension 2\");\n            // if (info.format != py::format_descriptor<int>::format())\n            // throw std::runtime_error(\"AddPoints needs buffer of type int\");\n\n            int * ptr = static_cast<int*> (info.ptr);\n            if (dim == 1)\n              {\n                // ELEMENT_TYPE type;\n                int np = info.shape[1];\n                self.LineSegments().SetAllocSize(self.LineSegments().Size()+info.shape[0]);                \n                for ([[maybe_unused]] auto i : Range(info.shape[0]))\n                  {\n                    Segment el;\n                    for (int j = 0; j < np; j++)\n                      el[j] = ptr[j]+PointIndex::BASE-base;\n                    el.si = index;\n                    self.AddSegment(el);\n                    ptr += info.strides[0]/sizeof(int);\n                  }\n              }\n            if (dim == 2)\n              {\n                ELEMENT_TYPE type;\n                int np = info.shape[1];\n                switch (np)\n                  {\n                  case 3: type = TRIG; break;\n                  case 4: type = QUAD; break;\n                  case 6: type = TRIG6; break;\n                  case 8: type = QUAD8; break;\n                  default:\n                    throw Exception(\"unsupported 2D element with \"+ToString(np)+\" points\");\n                  }\n                self.SurfaceElements().SetAllocSize(self.SurfaceElements().Size()+info.shape[0]);                \n                for ([[maybe_unused]] auto i : Range(info.shape[0]))\n                  {\n                    Element2d el(type);\n                    for (int j = 0; j < np; j++)\n                      el[j] = ptr[j]+PointIndex::BASE-base;\n                    el.SetIndex(index);\n                    if(project_geometry)\n                      {\n                        // find some point in the mid of trig/quad for\n                        // quick + stable uv-projection of all points\n                        auto startp = Center(self[el[0]], self[el[1]], self[el[2]]);\n\t\t\tint surfnr = self.GetFaceDescriptor(index).SurfNr();\n                        PointGeomInfo gi = self.GetGeometry()->ProjectPoint(surfnr,\n                                                                            startp);\n                        for(auto i : Range(np))\n                          {\n                            el.GeomInfo()[i] = gi;\n                            self.GetGeometry()->ProjectPointGI(surfnr,\n                                                               self[el[i]],\n                                                               el.GeomInfo()[i]);\n                          }\n                      }\n                    self.AddSurfaceElement (el);\n                    ptr += info.strides[0]/sizeof(int);\n                  }\n              }\n            if (dim == 3)\n              {\n                ELEMENT_TYPE type;\n                int np = info.shape[1];\n                switch (np)\n                  {\n                  case 4: type = TET; break;\n                  case 5: type = PYRAMID; break;                    \n                  case 6: type = PRISM; break;\n                  case 8: type = HEX; break;\n                  case 10: type = TET10; break;\n                  default:\n                    throw Exception(\"unsupported 3D element with \"+ToString(np)+\" points\");\n                  }\n                self.VolumeElements().SetAllocSize(self.VolumeElements().Size()+info.shape[0]);\n                for ([[maybe_unused]] auto i : Range(info.shape[0]))\n                  {\n                    Element el(type);\n                    for (int j = 0; j < np;j ++)\n                      el[j] = ptr[j]+PointIndex::BASE-base;\n                    el.SetIndex(index);\n                    self.AddVolumeElement (el);\n                    ptr += info.strides[0]/sizeof(int);\n                  }\n              }\n            \n          }, py::arg(\"dim\"), py::arg(\"index\"), py::arg(\"data\"), py::arg(\"base\")=0,\n          py::arg(\"project_geometry\")=false)\n    \n    .def (\"DeleteSurfaceElement\",\n          [](Mesh & self, SurfaceElementIndex i)\n          {\n            return self.Delete(i);\n          })\n          \n    .def (\"Compress\", [](Mesh & self)\n          {\n            return self.Compress ();\n          } ,py::call_guard<py::gil_scoped_release>())\n          \n    .def (\"AddRegion\", [] (Mesh & self, string name, int dim) -> int\n         {\n           auto & regionnames = self.GetRegionNamesCD(self.GetDimension()-dim);\n           regionnames.Append (new string(name));\n           int idx = regionnames.Size();\n           if (dim == 2)\n             {\n               FaceDescriptor fd;\n               fd.SetBCName(regionnames.Last());\n               fd.SetBCProperty(idx);\n               self.AddFaceDescriptor(fd);\n             }\n           return idx;\n         }, py::arg(\"name\"), py::arg(\"dim\"))\n\n    .def (\"GetRegionNames\", [] (Mesh & self, optional<int> optdim, optional<int> optcodim)\n          {\n            int codim;\n            if (optdim)\n              codim = self.GetDimension() - *optdim;\n            else if (optcodim)\n              codim = *optcodim;\n            else\n              throw Exception(\"either 'dim' or 'codim' must be specified\");\n            \n            Array<string*> & codimnames = self.GetRegionNamesCD (codim);\n            \n            std::vector<string> names;\n            for (auto name : codimnames)\n              {\n                if (name)\n                  names.push_back(*name);\n                else\n                  names.push_back(\"\");\n              }\n            return names;               \n          }, py::arg(\"dim\")=nullopt, py::arg(\"codim\")=nullopt)\n    \n    .def (\"SetBCName\", &Mesh::SetBCName)\n    .def (\"GetBCName\", FunctionPointer([](Mesh & self, int bc)->string \n                                       { return self.GetBCName(bc); }))\n    .def (\"SetMaterial\", &Mesh::SetMaterial)\n    .def (\"GetMaterial\", FunctionPointer([](Mesh & self, int domnr)\n                                         { return string(self.GetMaterial(domnr)); }))\n\n    .def (\"GetCD2Name\", &Mesh::GetCD2Name)\n    .def (\"SetCD2Name\", &Mesh::SetCD2Name)\n\n    .def (\"GetCD3Name\", &Mesh::GetCD3Name)\n    .def (\"SetCD3Name\", &Mesh::SetCD3Name)\n    .def (\"SplitFacesByAdjacentDomains\", &Mesh::SplitFacesByAdjacentDomains)\n    .def (\"GetSubMesh\", &Mesh::GetSubMesh, py::arg(\"domains\")=\"\", py::arg(\"faces\")=\"\")\n    .def(\"GetIdentifications\", [](Mesh & self) -> py::list\n         {\n           py::list points;\n           for(const auto& pair : self.GetIdentifications().GetIdentifiedPoints())\n             {\n               // py::tuple pnts = py::make_tuple(pair.first.I1(), pair.first.I2());\n               \n               auto [pi1, pi2] = get<0> (pair.first);\n               py::tuple pnts = py::make_tuple(pi1, pi2);\n               points.append(pnts);\n             }\n           return points;\n         })\n    .def (\"AddPointIdentification\", [](Mesh & self, py::object pindex1, py::object pindex2, int identnr, Identifications::ID_TYPE type)\n                           {\n\t\t\t     if(py::extract<PointIndex>(pindex1).check() && py::extract<PointIndex>(pindex2).check())\n\t\t\t       {\n\t\t\t\t self.GetIdentifications().Add (py::extract<PointIndex>(pindex1)(), py::extract<PointIndex>(pindex2)(), identnr);\n\t\t\t\t self.GetIdentifications().SetType(identnr, type); // type = 2 ... periodic\n\t\t\t       }\n                           },\n          //py::default_call_policies(),\n          py::arg(\"pid1\"),\n           py::arg(\"pid2\"),\n           py::arg(\"identnr\"),\n           py::arg(\"type\")=Identifications::PERIODIC)\n    .def(\"IdentifyPeriodicBoundaries\", &Mesh::IdentifyPeriodicBoundaries,\n         py::arg(\"identification_name\"), py::arg(\"face1\"), py::arg(\"mapping\"),\npy::arg(\"point_tolerance\") = -1.)\n    .def(\"GetCurveOrder\", [] (Mesh & self)\n          {\n            return self.GetCurvedElements().GetOrder();\n          })\n    .def(\"GetNrIdentifications\", [](Mesh& self)\n                                 {\n                                   return self.GetIdentifications().GetMaxNr();\n                                 })\n    .def (\"CalcLocalH\", &Mesh::CalcLocalH)\n    .def (\"SetMaxHDomain\", [] (Mesh& self, py::list maxhlist)\n          {\n            NgArray<double> maxh;\n            for(auto el : maxhlist)\n              maxh.Append(py::cast<double>(el));\n            self.SetMaxHDomain(maxh);\n          })\n    .def (\"GenerateVolumeMesh\", \n          [](Mesh & self, MeshingParameters* pars,\n             py::kwargs kwargs)\n           {\n             MeshingParameters mp;\n             if(pars) mp = *pars;\n             CreateMPfromKwargs(mp, kwargs);\n             py::gil_scoped_release gil_release;\n             MeshVolume (mp, self);\n             OptimizeVolume (mp, self);\n           }, py::arg(\"mp\")=nullptr,\n          meshingparameter_description.c_str())\n\n    .def (\"OptimizeVolumeMesh\", [](Mesh & self, MeshingParameters* pars)\n          {\n            MeshingParameters mp;\n            if(pars) mp = *pars;\n            else mp.optsteps3d = 5;\n            OptimizeVolume (mp, self);\n          }, py::arg(\"mp\"), py::call_guard<py::gil_scoped_release>())\n    .def(\"SetLocalH\",[](Mesh& self, shared_ptr<LocalH> localh, int layer)\n         {\n           self.SetLocalH(localh, layer);\n         }, py::arg(\"localh\"), py::arg(\"layer\")=1)\n    .def(\"GetLocalH\", &Mesh::GetLocalH)\n    .def (\"OptimizeMesh2d\", [](Mesh & self, MeshingParameters* pars, int faceindex)\n          {\n            self.CalcLocalH(0.5);\n            MeshingParameters mp;\n            if(pars) mp = *pars;\n            else mp.optsteps2d = 5;\n            if(!self.GetGeometry())\n              throw Exception(\"Cannot optimize surface mesh without geometry!\");\n            Optimize2d (self, mp, faceindex);\n          }, py::arg(\"mp\")=nullptr, py::arg(\"faceindex\")=0, py::call_guard<py::gil_scoped_release>())\n    \n    .def (\"Refine\", FunctionPointer\n          ([](Mesh & self, bool adaptive)\n           {\n             if (!adaptive)\n               {\n                 self.GetGeometry()->GetRefinement().Refine(self);\n                 self.UpdateTopology();\n               }\n             else\n               {\n                 BisectionOptions biopt;\n                 biopt.usemarkedelements = 1;\n                 biopt.refine_p = 0;\n                 biopt.refine_hp = 0;\n                 /*\n                   biopt.onlyonce = onlyonce;\n                   if (reftype == NG_REFINE_P)\n                   biopt.refine_p = 1;\n                   if (reftype == NG_REFINE_HP)\n                   biopt.refine_hp = 1;\n                 */\n                 self.GetGeometry()->GetRefinement().Bisect (self, biopt);\n                 self.UpdateTopology();\n                 self.GetCurvedElements().SetIsHighOrder (false);\n               }\n           }), py::arg(\"adaptive\")=false, py::call_guard<py::gil_scoped_release>())\n    \n    .def(\"ZRefine\", &Mesh::ZRefine)\n    .def(\"Split2Tets\", &Mesh::Split2Tets)\n    .def (\"SplitAlfeld\", FunctionPointer\n          ([](Mesh & self)\n           {\n            NgLock meshlock (self.MajorMutex(), true);\n            Refinement & ref = const_cast<Refinement&> (self.GetGeometry()->GetRefinement());\n            ::netgen::HPRefinement (self, &ref, SPLIT_ALFELD, 1, 0.5, true, true);\n           }\n           ), py::call_guard<py::gil_scoped_release>())\n    .def (\"SplitPowellSabin\", FunctionPointer\n          ([](Mesh & self)\n           {\n            NgLock meshlock (self.MajorMutex(), true);\n            Refinement & ref = const_cast<Refinement&> (self.GetGeometry()->GetRefinement());\n            ::netgen::HPRefinement (self, &ref, SPLIT_POWELL, 1, 0.5, true, true);\n           }\n           ), py::call_guard<py::gil_scoped_release>())\n    .def (\"SecondOrder\", [](Mesh & self)\n          {\n            self.GetGeometry()->GetRefinement().MakeSecondOrder(self);\n          })\n    \n    .def (\"Curve\", [](Mesh & self, int order)\n          {\n            self.BuildCurvedElements(order);\n          })\n    .def (\"CalcElementMapping\", [](Mesh & self, py::buffer refpts1, py::buffer physpts1)\n          {\n            auto refpts = refpts1.cast<py::array_t<double_t, py::array::c_style | py::array::forcecast>>();\n            auto physpts = physpts1.cast<py::array_t<double_t, py::array::c_style | py::array::forcecast>>();            \n            \n            py::buffer_info ref_info = refpts.request();\n            py::buffer_info phys_info = physpts.request();            \n            double * ref_ptr = static_cast<double*> (ref_info.ptr);\n            double * phys_ptr = static_cast<double*> (phys_info.ptr);\n            \n            if (ref_info.ndim != 2)\n              throw std::runtime_error(\"Reference points need buffer of dimension 2\");\n            if (phys_info.ndim != 3)\n              throw std::runtime_error(\"Physical points need buffer of dimension 3\");\n\n            /*\n            cout << \"ref_info.shape = \" << FlatArray(2, &ref_info.shape[0]) << endl;\n            cout << \"ref_info.stride = \" << FlatArray(2, &ref_info.strides[0]) << endl;\n            cout << \"phys_info.shape = \" << FlatArray(3, &phys_info.shape[0]) << endl;\n            cout << \"phys_info.stride = \" << FlatArray(3, &phys_info.strides[0]) << endl;\n            */\n            \n            size_t npts = ref_info.shape[0];\n            size_t dim = ref_info.shape[1];\n            // size_t nel = phys_info.shape[0];\n            size_t dim_phys = phys_info.shape[2];            \n\n            size_t stride_refpts = ref_info.strides[0]/sizeof(double);\n            size_t stride_physels = phys_info.strides[0]/sizeof(double);\n            size_t stride_physpts = phys_info.strides[1]/sizeof(double);\n            \n            auto & curved = self.GetCurvedElements();\n\n            if (dim == 2)  // mapping of 2D elements\n              {\n                for (SurfaceElementIndex i = 0; i < self.GetNSE(); i++)\n                  for (size_t j = 0; j < npts; j++)\n                    {\n                      Point<2> xref;\n                      Point<3> xphys;\n                      for (size_t k = 0; k < 2; k++)\n                        xref(k) = ref_ptr[j*stride_refpts+k];\n                      curved.CalcSurfaceTransformation(xref, i, xphys);\n                      for (size_t k = 0; k < dim_phys; k++)\n                        phys_ptr[i*stride_physels+j*stride_physpts+k] = xphys(k);\n                    }\n              }\n            \n            if (dim == 3)  // mapping of 3D elements\n              {\n                for (ElementIndex i = 0; i < self.GetNE(); i++)\n                  for (size_t j = 0; j < npts; j++)\n                    {\n                      Point<3> xref;\n                      Point<3> xphys;\n                      for (size_t k = 0; k < 3; k++)\n                        xref(k) = ref_ptr[j*stride_refpts+k];\n                      curved.CalcElementTransformation(xref, i, xphys);\n                      for (size_t k = 0; k < 3; k++)\n                        phys_ptr[i*stride_physels+j*stride_physpts+k] = xphys(k);\n                    }\n              }\n          })\n    \n    .def (\"GetGeometry\", [](Mesh & self) { return self.GetGeometry(); })\n    .def (\"SetGeometry\", [](Mesh & self, shared_ptr<NetgenGeometry> geo)\n           {\n             self.SetGeometry(geo);\n           })\n\n    /*\n    .def (\"SetGeometry\", FunctionPointer\n          ([](Mesh & self, shared_ptr<CSGeometry> geo)\n           {\n             self.SetGeometry(geo);\n           }))\n    */\n    \n    .def (\"BuildSearchTree\", &Mesh::BuildElementSearchTree,py::call_guard<py::gil_scoped_release>(),\n          py::arg(\"dim\")=3)\n\n    .def (\"BoundaryLayer2\", GenerateBoundaryLayer2, py::arg(\"domain\"), py::arg(\"thicknesses\"), py::arg(\"make_new_domain\")=true, py::arg(\"boundaries\")=Array<int>{})\n    .def (\"BoundaryLayer\", [](Mesh & self, variant<string, int, std::vector<int>> boundary,\n                              variant<double, std::vector<double>> thickness,\n                              optional<variant<string, map<string, string>>> material,\n                              variant<string, int, std::vector<int>> domain, bool outside,\n                              optional<variant<string, std::vector<int>>> project_boundaries,\n                              bool grow_edges, bool limit_growth_vectors,\n                              bool sides_keep_surfaceindex,\n                              bool disable_curving)\n           {\n             throw Exception(\"Call syntax has changed! Pass a list of BoundaryLayerParameters to the GenerateMesh call instead: \\ngeo.GenerateMesh(..., boundary_layers=[BoundaryLayerParameters(...), BoundaryLayerParameters(...), ...])\");\n             BoundaryLayerParameters blp;\n             blp.boundary = boundary;\n             blp.thickness = thickness;\n             blp.new_material = material;\n             blp.domain = domain;\n             blp.outside = outside;\n             blp.project_boundaries = project_boundaries;\n             blp.grow_edges = grow_edges;\n             blp.limit_growth_vectors = limit_growth_vectors;\n             blp.sides_keep_surfaceindex = sides_keep_surfaceindex;\n             blp.disable_curving = disable_curving;\n             GenerateBoundaryLayer (self, blp);\n             self.UpdateTopology();\n           }, py::arg(\"boundary\"), py::arg(\"thickness\"), py::arg(\"material\")=nullopt,\n          py::arg(\"domains\") = \".*\", py::arg(\"outside\") = false,\n          py::arg(\"project_boundaries\")=nullopt, py::arg(\"grow_edges\")=true, py::arg(\"limit_growth_vectors\") = false, py::arg(\"sides_keep_surfaceindex\")=false,\n          py::arg(\"disable_curving\")=true, \"Add boundary layer to mesh. see help(BoundaryLayerParameters) for details.\")\n\n    .def_static (\"EnableTableClass\", [] (string name, bool set)\n          {\n            MeshTopology::EnableTableStatic(name, set);\n          },\n          py::arg(\"name\"), py::arg(\"set\")=true)\n    .def (\"EnableTable\", [] (Mesh & self, string name, bool set)\n          {\n            const_cast<MeshTopology&>(self.GetTopology()).EnableTable(name, set);\n          },\n          py::arg(\"name\"), py::arg(\"set\")=true)\n    \n    .def (\"Scale\", [](Mesh & self, double factor)\n          {\n            for(auto & pnt : self.Points())\n\t      pnt.Scale(factor);\n          })\n    .def (\"Copy\", [](Mesh & self)\n          {\n            auto m2 = make_shared<Mesh> ();\n            *m2 = self;\n            return m2;\n          })\n    .def (\"CalcMinMaxAngle\", [](Mesh & self, double badel_limit)\n          {\n            double values[4];\n            self.CalcMinMaxAngle (badel_limit, values);\n            py::dict res;\n            res[\"trig\"] = py::make_tuple( values[0], values[1] );\n            res[\"tet\"] = py::make_tuple( values[2], values[3] );\n            return res;\n          }, py::arg(\"badelement_limit\")=175.0)\n    .def (\"Update\", [](Mesh & self)\n          {\n            self.SetNextTimeStamp();\n          })\n    .def (\"UpdateTopology\", [](Mesh & self) {\n      self.CalcSurfacesOfNode();\n      self.RebuildSurfaceElementLists();\n      self.UpdateTopology();\n    })\n    .def (\"CalcTotalBadness\", &Mesh::CalcTotalBad)\n    .def (\"GetQualityHistogram\", &Mesh::GetQualityHistogram)\n    .def(\"Mirror\", &Mesh::Mirror)\n    .def(\"_getVertices\", [](Mesh & self)\n          {\n            // std::vector<float> verts(3*self.GetNV());\n            Array<float> verts(3*self.GetNV());\n            ParallelForRange( self.GetNV(), [&](auto myrange) {\n                const auto & points = self.Points();\n                for(auto i : myrange)\n                {\n                    auto p = points[PointIndex::BASE+i];\n                    auto * v = &verts[3*i];\n                    for(auto k : Range(3))\n                        v[k] = p[k];\n                } });\n            return verts;\n          })\n    .def(\"_getSegments\", [](Mesh & self)\n          {\n            // std::vector<int> output;\n            // output.resize(2*self.GetNSeg());\n            Array<int> output(2*self.GetNSeg());\n            ParallelForRange( self.GetNSeg(), [&](auto myrange) {\n                const auto & segs = self.LineSegments();\n                for(auto i : myrange)\n                {\n                    const auto & seg = segs[i];\n                    for(auto k : Range(2))\n                      output[2*i+k] = seg[k]-IndexBASE<PointIndex>();\n                } });\n            return output;\n          })\n    .def(\"_getWireframe\", [](Mesh & self)\n          {\n            const auto & topo = self.GetTopology();\n            size_t n = topo.GetNEdges();\n            /*\n            std::vector<int> output;\n            output.resize(2*n);\n            */\n            Array<int> output(2*n);\n            ParallelForRange( n, [&](auto myrange) {\n                for(auto i : myrange)\n                {\n                  // PointIndex p0,p1;\n                  // topo.GetEdgeVertices(i+1, p0, p1);\n                  auto [p0,p1] = topo.GetEdgeVertices(i);\n                    output[2*i] = p0-IndexBASE<PointIndex>();\n                    output[2*i+1] = p1-IndexBASE<PointIndex>();\n                } });\n            return output;\n          })\n    .def(\"_get2dElementsAsTriangles\", [](Mesh & self)\n          {\n            /*\n            std::vector<int> trigs;\n            trigs.resize(3*self.GetNSE());\n            */\n            Array<int> trigs(3*self.GetNSE());\n            ParallelForRange( self.GetNSE(), [&](auto myrange) {\n                const auto & surfels = self.SurfaceElements();\n                for(auto i : myrange)\n                {\n                    const auto & sel = surfels[i];\n                    auto * trig = &trigs[3*i];\n                    for(auto k : Range(3))\n                        trig[k] = sel[k]-IndexBASE<PointIndex>();\n                        // todo: quads (store the second trig in thread-local extra array, merge them at the end (mutex)\n                } });\n            return trigs;\n          })\n    .def(\"_get3dElementsAsTets\", [](Mesh & self)\n        {\n          // std::vector<int> tets;\n          // tets.resize(4*self.GetNE());\n\n            Array<int> tets(4*self.GetNE());\n            ParallelForRange( self.GetNE(), [&](auto myrange) {\n                const auto & els = self.VolumeElements();\n                for(auto i : myrange)\n                {\n                    const auto & el = els[i];\n                    auto * trig = &tets[4*i];\n                    for(auto k : Range(4))\n                        trig[k] = el[k]-IndexBASE<PointIndex>();\n                        // todo: prisms etc (store the extra tets in thread-local extra array, merge them at the end (mutex)\n                } });\n            return tets;\n        })\n    ;\n\n  string import_docu = \"Import mesh from other file format. Leaving format parameter empty guesses based on file extension.\\nSupported formats are:\\n\";\n  UserFormatRegister::IterateFormats([&](auto & e) {\n      string s = '\\t'+e.format+\"\\t(\"+e.extensions[0];\n      for(auto & ext : e.extensions.Range(1, e.extensions.Size()))\n        s += \", \"+ext;\n      s += \")\\n\";\n      import_docu += s;\n  }, true);\n\n  m.def(\"ReadMedit\", [](const string& filename) {\n          map<tuple<int, int>, int> index_map;\n          auto mesh = make_shared<Mesh>();\n          ReadMeditFormat(*mesh, filename, index_map);\n          return py::make_tuple(mesh, index_map);\n  });\n  m.def(\"WriteMedit\", [](const Mesh& mesh, const string& filename) {\n          map<tuple<int,int>, int> index_map;\n          WriteMeditFormat(mesh, filename, index_map);\n          return index_map;\n  });\n  m.def(\"ImportMesh\", [](const string& filename, const string & format)\n                      {\n                        auto mesh = make_shared<Mesh>();\n                        ReadUserFormat(*mesh, filename, format);\n                        return mesh;\n                      }, py::arg(\"filename\"), py::arg(\"format\")=\"\", import_docu.c_str());\n  py::enum_<MESHING_STEP>(m,\"MeshingStep\")\n    .value(\"ANALYSE\", MESHCONST_ANALYSE)\n    .value(\"MESHEDGES\", MESHCONST_MESHEDGES)\n    .value(\"MESHSURFACE\", MESHCONST_OPTSURFACE)\n    .value(\"MESHVOLUME\", MESHCONST_OPTVOLUME)\n    ;\n         \n  typedef MeshingParameters MP;\n  auto mp = py::class_<MP> (m, \"MeshingParameters\")\n    .def(py::init<>())\n            .def(py::init([](MeshingParameters* other, py::kwargs kwargs)\n                  {\n                    MeshingParameters mp;\n                    if(other) mp = *other;\n                    CreateMPfromKwargs(mp, kwargs, false);\n                    return mp;\n                  }), py::arg(\"mp\")=nullptr, meshingparameter_description.c_str())\n    .def(\"__str__\", &ToString<MP>)\n    .def(\"RestrictH\", [](MP & mp, double x, double y, double z, double h, int layer)\n          {\n            mp.meshsize_points.Append ( MeshingParameters::MeshSizePoint(Point<3> (x,y,z), h, layer));\n          }, py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"), py::arg(\"h\"), py::arg(\"layer\")=1\n         )\n    .def(\"RestrictH\", [](MP & mp, const Point<3>& p, double h, int layer)\n    {\n      mp.meshsize_points.Append ({p, h, layer});\n    }, py::arg(\"p\"), py::arg(\"h\"), py::arg(\"layer\")=1)\n    .def(\"RestrictHLine\", [](MP& mp, const Point<3>& p1, const Point<3>& p2,\n                             double maxh, int layer)\n    {\n      int steps = int(Dist(p1, p2) / maxh) + 2;\n      auto v = p2 - p1;\n      for (int i = 0; i <= steps; i++)\n        {\n          mp.meshsize_points.Append({p1 + double(i)/steps * v, maxh, layer});\n        }\n    }, py::arg(\"p1\"), py::arg(\"p2\"), py::arg(\"maxh\"), py::arg(\"layer\")=1)\n    ;\n\n  m.def(\"SetTestoutFile\", FunctionPointer ([] (const string & filename)\n                                             {\n                                               delete testout;\n                                               testout = new ofstream (filename);\n                                             }));\n\n  m.def(\"SetMessageImportance\", FunctionPointer ([] (int importance)\n                                                   {\n                                                     int old = printmessage_importance;\n                                                     printmessage_importance = importance;\n                                                     return old;\n                                                   }));\n\n  py::class_<DebugParameters> (m, \"_DebugParameters\")\n      .def_readwrite(\"debugoutput\", &DebugParameters::debugoutput)\n      .def_readwrite(\"slowchecks\", &DebugParameters::slowchecks)\n      .def_readwrite(\"haltsuccess\", &DebugParameters::haltsuccess)\n      .def_readwrite(\"haltnosuccess\", &DebugParameters::haltnosuccess)\n      .def_readwrite(\"haltlargequalclass\", &DebugParameters::haltlargequalclass)\n      .def_readwrite(\"haltsegment\", &DebugParameters::haltsegment)\n      .def_readwrite(\"haltnode\", &DebugParameters::haltnode)\n      .def_readwrite(\"haltsegmentp1\", &DebugParameters::haltsegmentp1)\n      .def_readwrite(\"haltsegmentp2\", &DebugParameters::haltsegmentp2)\n      .def_readwrite(\"haltexistingline\", &DebugParameters::haltexistingline)\n      .def_readwrite(\"haltoverlap\", &DebugParameters::haltoverlap)\n      .def_readwrite(\"haltface\", &DebugParameters::haltface)\n      .def_readwrite(\"haltfacenr\", &DebugParameters::haltfacenr)\n      .def_readwrite(\"write_mesh_on_error\", &DebugParameters::write_mesh_on_error)\n      ;\n\n  m.attr(\"debugparam\") = py::cast(&debugparam);\n\n  py::class_<BoundaryLayerParameters>(m, \"BoundaryLayerParameters\")\n    .def(py::init([]( \n        std::variant<string, int, std::vector<int>> boundary,\n        std::variant<double, std::vector<double>> thickness,\n        std::optional<std::variant<string, std::map<string, string>>> new_material,\n        std::variant<string, int, std::vector<int>> domain,\n        bool outside,\n        std::optional<std::variant<string, std::vector<int>>> project_boundaries,\n        bool grow_edges,\n        bool limit_growth_vectors,\n        std::optional<bool> sides_keep_surfaceindex,\n        bool disable_curving)\n        {\n          BoundaryLayerParameters blp;\n          blp.boundary = boundary;\n          blp.thickness = thickness;\n          blp.new_material = new_material;\n          blp.domain = domain;\n          blp.outside = outside;\n          blp.project_boundaries = project_boundaries;\n          blp.grow_edges = grow_edges;\n          blp.limit_growth_vectors = limit_growth_vectors;\n          blp.sides_keep_surfaceindex = sides_keep_surfaceindex;\n          blp.disable_curving = disable_curving;\n          return blp;\n        }),\n           py::arg(\"boundary\"), py::arg(\"thickness\"), py::arg(\"new_material\")=nullopt,\n           py::arg(\"domain\") = \".*\", py::arg(\"outside\") = false,\n           py::arg(\"project_boundaries\")=nullopt, py::arg(\"grow_edges\")=true,\n           py::arg(\"limit_growth_vectors\") = false, py::arg(\"sides_keep_surfaceindex\")=nullopt,\n           py::arg(\"disable_curving\")=true,\n           R\"delimiter(\nAdd boundary layer to mesh.\n\nParameters\n----------\n\nboundary : string or int\n  Boundary name or number.\n\nthickness : float or List[float]\n  Thickness of boundary layer(s).\n\nmaterial : str or List[str]\n  Material name of boundary layer(s).\n\ndomain : str or int\n  Regexp for domain boundarylayer is going into.\n\noutside : bool = False\n  If true add the layer on the outside\n\ngrow_edges : bool = False\n  Grow boundary layer over edges.\n\nproject_boundaries : Optional[str] = None\n  Project boundarylayer to these boundaries if they meet them. Set\n  to boundaries that meet boundarylayer at a non-orthogonal edge and\n  layer-ending should be projected to that boundary.\n\n)delimiter\")\n    .def(py::init([]( const py::dict & d ) {\n      try {\n        // Call other constructor with named arguments by unpacking the dictionary\n        py::object cls = py::type::of<BoundaryLayerParameters>();\n        return cls(**d).cast<BoundaryLayerParameters>();\n      }\n      catch (py::error_already_set & e) {\n        cerr << \"Error creating BoundaryLayerParameters from dict:\" << endl;\n        cerr << e.what() << endl;\n        throw;\n      }\n    }))\n    .def_readwrite(\"boundary\", &BoundaryLayerParameters::boundary)\n    .def_readwrite(\"thickness\", &BoundaryLayerParameters::thickness)\n    .def_readwrite(\"new_material\", &BoundaryLayerParameters::new_material)\n    .def_readwrite(\"domain\", &BoundaryLayerParameters::domain)\n    .def_readwrite(\"outside\", &BoundaryLayerParameters::outside)\n    .def_readwrite(\"project_boundaries\", &BoundaryLayerParameters::project_boundaries)\n    .def_readwrite(\"grow_edges\", &BoundaryLayerParameters::grow_edges)\n    .def_readwrite(\"limit_growth_vectors\", &BoundaryLayerParameters::limit_growth_vectors)\n    .def_readwrite(\"sides_keep_surfaceindex\", &BoundaryLayerParameters::sides_keep_surfaceindex)\n    .def_readwrite(\"disable_curving\", &BoundaryLayerParameters::disable_curving)\n    ;\n  py::implicitly_convertible<py::dict, BoundaryLayerParameters>();\n\n#ifdef NG_CGNS\n  m.def(\"ReadCGNSFile\", &ReadCGNSFile, py::arg(\"filename\"), py::arg(\"base\")=1, \"Read mesh and solution vectors from CGNS file\");\n  m.def(\"WriteCGNSFile\", &WriteCGNSFile, py::arg(\"mesh\"), py::arg(\"filename\"), py::arg(\"names\"), py::arg(\"values\"), py::arg(\"locations\"),\n      R\"(Write mesh and solution vectors to CGNS file, possible values for locations:\n      Vertex     = 0\n      EdgeCenter = 1\n      FaceCenter = 2\n      CellCenter = 3\n      )\");\n#endif // NG_CGNS\n\n    py::class_<SurfaceGeometry, NetgenGeometry, shared_ptr<SurfaceGeometry>> (m, \"SurfaceGeometry\")\n    .def(py::init<>())\n    .def(py::init([](py::object pyfunc)\n                  {\n                    std::function<Vec<3> (Point<2>)> func = [pyfunc](Point<2> p)\n                                                    {\n                                                      py::gil_scoped_acquire aq;\n                                                      py::tuple pyres = py::extract<py::tuple>(pyfunc(p[0],p[1],0.0)) ();\n                                                      return Vec<3>(py::extract<double>(pyres[0])(),py::extract<double>(pyres[1])(),py::extract<double>(pyres[2])());\n                                                    };\n                    auto geo = make_shared<SurfaceGeometry>(func);\n                    return geo;\n                  }), py::arg(\"mapping\"))\n    .def(NGSPickle<SurfaceGeometry>())\n    .def(\"GenerateMesh\", [](shared_ptr<SurfaceGeometry> geo,\n                            bool quads, int nx, int ny, bool flip_triangles, py::list py_bbbpts, py::list py_bbbnames, py::list py_hppnts, py::dict/*list*/ py_hpbnd, py::dict py_layers)\n           {\n             if (py::len(py_bbbpts) != py::len(py_bbbnames))\n               throw Exception(\"In SurfaceGeometry::GenerateMesh bbbpts and bbbnames do not have same lengths.\");\n             Array<Point<3>> bbbpts(py::len(py_bbbpts));\n             Array<string> bbbname(py::len(py_bbbpts));\n             Array<Point<3>> hppnts(py::len(py_hppnts));\n             Array<float> hppntsfac(py::len(py_hppnts));\n             Array<string> hpbnd(py::len(py_hpbnd));\n             Array<float> hpbndfac(py::len(py_hpbnd));\n             for(int i = 0; i<py::len(py_bbbpts);i++)\n\t\t {\n                   py::tuple pnt = py::extract<py::tuple>(py_bbbpts[i])();\n                   bbbpts[i] = Point<3>(py::extract<double>(pnt[0])(),py::extract<double>(pnt[1])(),py::extract<double>(pnt[2])());\n                   bbbname[i] = py::extract<string>(py_bbbnames[i])();\n                 }\n             for(int i = 0; i<py::len(py_hppnts);i++)\n\t\t {\n                   py::tuple pnt = py::extract<py::tuple>(py_hppnts[i])();\n                   hppnts[i] = Point<3>(py::extract<double>(pnt[0])(),py::extract<double>(pnt[1])(),py::extract<double>(pnt[2])());\n                   hppntsfac[i] = py::extract<double>(pnt[3])();\n                 }\n\n\t     int ii=0;\n             for(auto val : py_hpbnd)\n               {\n                 hpbnd[ii] = py::cast<string>(val.first);\n\t\t hpbndfac[ii] = py::cast<float>(val.second);\n\t\t ii++;\n\t       }\n\n             \n             Array<double> layer_thickness[4];\n             bool layer_quad = false;\n\n             for(auto val : py_layers)\n               {\n\t\t int index = -1;\n                 if (py::cast<string>(val.first) == \"left\") index = 0;\n                 else if (py::cast<string>(val.first) == \"top\") index = 3;\n                 else if (py::cast<string>(val.first) == \"right\") index = 2;\n                 else if (py::cast<string>(val.first) == \"bottom\") index = 1;\n\t\t else if (py::cast<string>(val.first) == \"quads\") layer_quad = py::cast<bool>(val.second);\n\t\t else throw Exception(\"Unknown parameter \" + string(py::cast<string>(val.first)));\n\t\t if (index < 0) continue;\n\n\t\t auto list = py::cast<py::list>(val.second);\n\t\t layer_thickness[index] = Array<double>(py::len(list));\n\t\t for (size_t i = 0; i < py::len(list); i++)\n\t\t   layer_thickness[index][i] = py::cast<double>(list[i]);\n               }\n                   \n             auto mesh = make_shared<Mesh>();\n             SetGlobalMesh (mesh);\n             mesh->SetGeometry(geo);\n\t     ng_geometry = geo;\n             auto result = geo->GenerateStructuredMesh (mesh, quads, nx, ny, flip_triangles, bbbpts, bbbname, hppnts, hppntsfac, hpbnd, hpbndfac, layer_thickness, layer_quad);\n             if(result != 0)\n               throw Exception(\"SurfaceGeometry: Meshing failed!\");\n             return mesh;\n           }, py::arg(\"quads\")=true, py::arg(\"nx\")=10, py::arg(\"ny\")=10, py::arg(\"flip_triangles\")=false, py::arg(\"bbbpts\")=py::list(), py::arg(\"bbbnames\")=py::list(), py::arg(\"hppnts\")=py::list(), py::arg(\"hpbnd\")=py::dict(), py::arg(\"boundarylayer\")=py::dict());/*, R\"raw_string(\n      Generate a structured 2D surface mesh\n\n    Parameters:\n    \n    quads : bool\n      If True, a quadrilateral mesh is generated. If False, the quads are split to triangles.\n\n    nx : int\n      Number of cells in x-direction.\n\n    ny : int\n      Number of cells in y-direction.\n\n    flip_triangles : bool\n      If set to True together with quads=False the quads are cut the other way round\n\n    bbbpts : list\n      List of points which should be handled as BBBND and are named with bbbnames. The mesh must be constructed in such a way that the bbbpts coincide with generated points.\n\n    bbbnames : list\n      List of bbbnd names as strings. Size must coincide with size of bbbpts.\n\n    hppnts : list\n      If not None it expects a list of the form [ (px1,py1,pz1, hpref1), (px2,py2,pz2, hpref2), ... ] where px,py,pz are the point coordinates which have to be resolved in the mesh and hpref the refinement factor.\n\n    hpbnd : dict\n      If not None it expects a dictionary of the form {\"boundaryname\" : hpref } where boundaryname in [left, right, top, bottom] and hpref the refinement factor.\n\n    boundarylayer : dict\n      If not None it expects a dictionary of the form { \"boundaryname\" : [t1,...,tn], \"quads\" : False } where ti denote the thickness of layer i. The number of layers are included in nx/ny. After the layers are placed the remaining number of cells are used to divide the remaining grid uniformly. If quads are set to True quadrilaterals are used inside the boundarylayer. If set False the value of \"quads\" of the function call is used.\n      )raw_string\");*/\n    ;\n\n    py::class_<ClearSolutionClass> (m, \"ClearSolutionClass\")\n      .def(py::init<>())\n      ;\n    m.def(\"SetParallelPickling\", [](bool par) { parallel_pickling = par; });\n    m.def (\"_Redraw\",\n        ([](bool blocking, double fr)\n          {\n            static auto last_time = std::chrono::system_clock::now()-std::chrono::seconds(10);\n            auto now = std::chrono::system_clock::now();\n            double elapsed = std::chrono::duration<double>(now-last_time).count();\n            if (blocking || elapsed * fr > 1)\n              {\n                Ng_Redraw(blocking);\n                last_time = std::chrono::system_clock::now();\n                return true;\n              }\n            return false;\n          }),\n        py::arg(\"blocking\")=false, py::arg(\"fr\") = 25, R\"raw_string(\n  Redraw all\n\n  Parameters:\n\n  blocking : bool\n    input blocking\n\n  fr : double\n    input framerate\n\n  )raw_string\");\n}\n\nPYBIND11_MODULE(libmesh, m) {\n  ExportNetgenMeshing(m);\n}\n#endif\n\n\n\n\n"
  },
  {
    "path": "libsrc/meshing/python_mesh.hpp",
    "content": "#ifndef NETGEN_MESHING_PYTHON_MESH_HPP\n#define NETGEN_MESHING_PYTHON_MESH_HPP\n\n#include <core/python_ngcore.hpp>\n\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n  // TODO: Clarify a lot of these parameters\n  static string meshingparameter_description = R\"delimiter(\nMeshing Parameters\n-------------------\n\nmaxh: float = 1e10\n  Global upper bound for mesh size.\n\ngrading: float = 0.3\n  Mesh grading how fast the local mesh size can change.\n\nmeshsizefilename: str = None\n  Load meshsize from file. Can set local mesh size for points\n  and along edges. File must have the format:\n\n    nr_points\n    x1, y1, z1, meshsize\n    x2, y2, z2, meshsize\n    ...\n    xn, yn, zn, meshsize\n\n    nr_edges\n    x11, y11, z11, x12, y12, z12, meshsize\n    ...\n    xn1, yn1, zn1, xn2, yn2, zn2, meshsize\n\nsegmentsperedge: float = 1.\n  Minimal number of segments per edge.\n\nquad_dominated: bool = False\n  Quad-dominated surface meshing.\n\nblockfill: bool = True\n  Do fast blockfilling.\n\nfilldist: float = 0.1\n  Block fill up to distance\n\ndelaunay: bool = True\n  Use delaunay meshing.\n\ndelaunay2d : bool = True\n  Use delaunay meshing for 2d geometries.\n\nOptimization Parameters\n-----------------------\n\noptimize3d: str = \"cmdmustm\"\n  3d optimization strategy:\n    m .. move nodes\n    M .. move nodes, cheap functional\n    s .. swap faces\n    c .. combine elements\n    d .. divide elements\n    p .. plot, no pause\n    P .. plot, Pause\n    h .. Histogramm, no pause\n    H .. Histogramm, pause\n\noptsteps3d: int = 3\n  Number of 3d optimization steps.\n\noptimize2d: str = \"smcmSmcmSmcm\"\n  2d optimization strategy:\n    s .. swap, opt 6 lines/node\n    S .. swap, optimal elements\n    m .. move nodes\n    p .. plot, no pause\n    P .. plot, pause\n    c .. combine\n\noptsteps2d: int = 3\n  Number of 2d optimization steps.\n\nelsizeweight: float = 0.2\n  Weight of element size w.r.t. element shape in optimization.\n\n)delimiter\";\n\ninline void CreateMPfromKwargs(MeshingParameters& mp, py::kwargs kwargs, bool throw_if_not_all_parsed=true)\n  {\n    if(kwargs.contains(\"optimize3d\"))\n      mp.optimize3d = py::cast<string>(kwargs.attr(\"pop\")(\"optimize3d\"));\n    if(kwargs.contains(\"optsteps3d\"))\n      mp.optsteps3d = py::cast<int>(kwargs.attr(\"pop\")(\"optsteps3d\"));\n    if(kwargs.contains(\"optimize2d\"))\n      mp.optimize2d = py::cast<string>(kwargs.attr(\"pop\")(\"optimize2d\"));\n    if(kwargs.contains(\"optsteps2d\"))\n      mp.optsteps2d = py::cast<int>(kwargs.attr(\"pop\")(\"optsteps2d\"));\n    if(kwargs.contains(\"opterrpow\"))\n      mp.opterrpow = py::cast<double>(kwargs.attr(\"pop\")(\"opterrpow\"));\n    if(kwargs.contains(\"blockfill\"))\n      mp.blockfill = py::cast<bool>(kwargs.attr(\"pop\")(\"blockfill\"));\n    if(kwargs.contains(\"filldist\"))\n      mp.filldist = py::cast<double>(kwargs.attr(\"pop\")(\"filldist\"));\n    if(kwargs.contains(\"safety\"))\n      mp.safety = py::cast<double>(kwargs.attr(\"pop\")(\"safety\"));\n    if(kwargs.contains(\"relinnersafety\"))\n      mp.relinnersafety = py::cast<double>(kwargs.attr(\"pop\")(\"relinnersafety\"));\n    if(kwargs.contains(\"uselocalh\"))\n      mp.uselocalh = py::cast<bool>(kwargs.attr(\"pop\")(\"uselocalh\"));\n    if(kwargs.contains(\"grading\"))\n      mp.grading = py::cast<double>(kwargs.attr(\"pop\")(\"grading\"));\n    if(kwargs.contains(\"delaunay\"))\n      mp.delaunay = py::cast<bool>(kwargs.attr(\"pop\")(\"delaunay\"));\n    if(kwargs.contains(\"delaunay2d\"))\n      mp.delaunay2d = py::cast<bool>(kwargs.attr(\"pop\")(\"delaunay2d\"));\n    if(kwargs.contains(\"maxh\"))\n      mp.maxh = py::cast<double>(kwargs.attr(\"pop\")(\"maxh\"));\n    if(kwargs.contains(\"minh\"))\n      mp.minh = py::cast<double>(kwargs.attr(\"pop\")(\"minh\"));\n    if(kwargs.contains(\"meshsizefilename\"))\n      mp.meshsizefilename = py::cast<string>(kwargs.attr(\"pop\")(\"meshsizefilename\"));\n    if(kwargs.contains(\"startinsurface\"))\n      mp.startinsurface = py::cast<bool>(kwargs.attr(\"pop\")(\"startinsurface\"));\n    if(kwargs.contains(\"checkoverlap\"))\n      mp.checkoverlap = py::cast<bool>(kwargs.attr(\"pop\")(\"checkoverlap\"));\n    if(kwargs.contains(\"checkoverlappingboundary\"))\n      mp.checkoverlappingboundary = py::cast<bool>(kwargs.attr(\"pop\")(\"checkoverlappingboundary\"));\n    if(kwargs.contains(\"checkchartboundary\"))\n      mp.checkchartboundary = py::cast<bool>(kwargs.attr(\"pop\")(\"checkchartboundary\"));\n    if(kwargs.contains(\"curvaturesafety\"))\n      mp.curvaturesafety = py::cast<double>(kwargs.attr(\"pop\")(\"curvaturesafety\"));\n    if(kwargs.contains(\"segmentsperedge\"))\n      mp.segmentsperedge = py::cast<double>(kwargs.attr(\"pop\")(\"segmentsperedge\"));\n    if(kwargs.contains(\"parthread\"))\n      mp.parthread = py::cast<bool>(kwargs.attr(\"pop\")(\"parthread\"));\n    if(kwargs.contains(\"elsizeweight\"))\n      mp.elsizeweight = py::cast<double>(kwargs.attr(\"pop\")(\"elsizeweight\"));\n    if(kwargs.contains(\"perfstepsstart\"))\n      mp.perfstepsstart = py::cast<int>(kwargs.attr(\"pop\")(\"perfstepsstart\"));\n    if(kwargs.contains(\"perfstepsend\"))\n      mp.perfstepsend = py::cast<int>(kwargs.attr(\"pop\")(\"perfstepsend\"));\n    if(kwargs.contains(\"giveuptol2d\"))\n      mp.giveuptol2d = py::cast<int>(kwargs.attr(\"pop\")(\"giveuptol2d\"));\n    if(kwargs.contains(\"giveuptol\"))\n      mp.giveuptol = py::cast<int>(kwargs.attr(\"pop\")(\"giveuptol\"));\n    if(kwargs.contains(\"giveuptolopenquads\"))\n      mp.giveuptolopenquads = py::cast<int>(kwargs.attr(\"pop\")(\"giveuptolopenquads\"));\n    if(kwargs.contains(\"maxoutersteps\"))\n      mp.maxoutersteps = py::cast<int>(kwargs.attr(\"pop\")(\"maxoutersteps\"));\n    if(kwargs.contains(\"starshapeclass\"))\n      mp.starshapeclass = py::cast<int>(kwargs.attr(\"pop\")(\"starshapeclass\"));\n    if(kwargs.contains(\"baseelnp\"))\n      mp.baseelnp = py::cast<int>(kwargs.attr(\"pop\")(\"baseelnp\"));\n    if(kwargs.contains(\"sloppy\"))\n      mp.sloppy = py::cast<int>(kwargs.attr(\"pop\")(\"sloppy\"));\n    if(kwargs.contains(\"badellimit\"))\n      mp.badellimit = py::cast<double>(kwargs.attr(\"pop\")(\"badellimit\"));\n    if(kwargs.contains(\"check_impossible\"))\n      mp.check_impossible = py::cast<bool>(kwargs.attr(\"pop\")(\"check_impossible\"));\n    if(kwargs.contains(\"only3D_domain_nr\"))\n      mp.only3D_domain_nr = py::cast<int>(kwargs.attr(\"pop\")(\"only3D_domain_nr\"));\n    if(kwargs.contains(\"secondorder\"))\n      mp.secondorder = py::cast<bool>(kwargs.attr(\"pop\")(\"secondorder\"));\n    if(kwargs.contains(\"elementorder\"))\n      mp.elementorder = py::cast<int>(kwargs.attr(\"pop\")(\"elementorder\"));\n    if(kwargs.contains(\"quad\"))\n      {\n        cout << \"WARNING: Meshing parameter 'quad' is deprecated, use 'quad_dominated' instead!\" << endl;\n        mp.quad = py::cast<bool>(kwargs.attr(\"pop\")(\"quad\"));\n      }\n    if(kwargs.contains(\"quad_dominated\"))\n      mp.quad = py::cast<bool>(kwargs.attr(\"pop\")(\"quad_dominated\"));\n    if(kwargs.contains(\"try_hexes\"))\n      mp.try_hexes = py::cast<bool>(kwargs.attr(\"pop\")(\"try_hexes\"));\n    if(kwargs.contains(\"inverttets\"))\n      mp.inverttets = py::cast<bool>(kwargs.attr(\"pop\")(\"inverttets\"));\n    if(kwargs.contains(\"inverttrigs\"))\n      mp.inverttrigs = py::cast<bool>(kwargs.attr(\"pop\")(\"inverttrigs\"));\n    if(kwargs.contains(\"autozrefine\"))\n      mp.autozrefine = py::cast<bool>(kwargs.attr(\"pop\")(\"autozrefine\"));\n    if(kwargs.contains(\"parallel_meshing\"))\n      mp.parallel_meshing = py::cast<bool>(kwargs.attr(\"pop\")(\"parallel_meshing\"));\n    if(kwargs.contains(\"nthreads\"))\n      mp.nthreads = py::cast<int>(kwargs.attr(\"pop\")(\"nthreads\"));\n    if(kwargs.contains(\"closeedgefac\"))\n      mp.closeedgefac = py::cast<optional<double>>(kwargs.attr(\"pop\")(\"closeedgefac\"));\n\n    if(kwargs.contains(\"boundary_layers\"))\n    {\n      auto layers = py::list(kwargs.attr(\"pop\")(\"boundary_layers\"));\n      for(auto layer : layers)\n        mp.boundary_layers.Append(py::cast<BoundaryLayerParameters>(layer));\n    }\n\n    if(kwargs.size())\n    {\n      if(throw_if_not_all_parsed)\n        throw Exception(string(\"Not all kwargs given to GenerateMesh could be parsed:\") + string(py::str(kwargs)));\n      mp.geometrySpecificParameters = CreateFlagsFromKwArgs(kwargs);\n    }\n  }\n} // namespace netgen\n\n#endif // NETGEN_MESHING_PYTHON_MESH_HPP\n \n"
  },
  {
    "path": "libsrc/meshing/refine.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshclass.hpp\"\n#include \"bisect.hpp\"\n#include \"paralleltop.hpp\"\n\n\nnamespace netgen\n{\n\n  void Refinement :: Refine (Mesh & mesh) const\n  {\n    const_cast<Refinement&> (*this).Refine(mesh);\n  }\n\n\n  void Refinement :: Refine (Mesh & mesh)\n  {\n    if (mesh.GetCommunicator().Rank()==0)\n      PrintMessage (3, \"Refine mesh\");\n    Timer t(\"Refine mesh\"); RegionTimer reg(t);\n\n    \n    mesh.SetNextMajorTimeStamp();\n    \n    if (ntasks > 1 && id == 0)\n      return;\n\n\n    // reduce 2nd order\n    mesh.ComputeNVertices();\n    mesh.SetNP(mesh.GetNV());\n\n    if (mesh.mlbetweennodes.Size() < mesh.GetNV())\n      {\n        mesh.mlbetweennodes.SetSize(mesh.GetNV());\n        mesh.mlbetweennodes = PointIndices<2>(PointIndex::INVALID, PointIndex::INVALID);\n      }\n\n    if (mesh.level_nv.Size() == 0)\n      mesh.level_nv.Append (mesh.GetNV());\n    \n    \n    INDEX_2_HASHTABLE<PointIndex> between(mesh.GetNP() + 5);\n\n\n    // new version with consistent ordering across sub-domains\n\n    NgArray<INDEX_2> parents;\n    for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n      {\n\tconst Segment & el = mesh[si];\n\tINDEX_2 i2 = INDEX_2::Sort(el[0], el[1]);\n        if (!between.Used(i2))\n          {\n            between.Set (i2, 0);          \n            parents.Append(i2);\n          }\n      }\n    for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\tswitch (el.GetType())\n\t  {\n\t  case TRIG:\n\t  case TRIG6:\n\t    {\n              static int betw[3][3] =\n\t\t{ { 1, 2, 3 },\n\t\t  { 0, 2, 4 },\n\t\t  { 0, 1, 5 } };\n              for (int j = 0; j < 3; j++)\n                {\n                  auto i2 = PointIndices<2>::Sort(el[betw[j][0]],el[betw[j][1]]);\n                  if (!between.Used(i2))\n                    {\n                      between.Set (i2, 0);          \n                      parents.Append(i2);\n                    }\n                }\n              break;\n            }\n\t  case QUAD:\n\t    {\n              static int betw[5][3] =\n\t\t{ { 0, 1, 4 },\n\t\t  { 1, 2, 5 },\n\t\t  { 2, 3, 6 },\n\t\t  { 0, 3, 7 },\n\t\t  { 0, 2, 8 } };   // one diagonal of the quad. should change later to mid-point of edge mid-points\n              for (int j = 0; j < 5; j++)\n                {\n                  auto i2 = PointIndices<2>::Sort(el[betw[j][0]],el[betw[j][1]]);\n                  if (j == 4)\n                    {\n                      auto i2a = PointIndices<2>::Sort(el[0], el[2]);\n                      auto i2b = PointIndices<2>::Sort(el[1], el[3]);\n                      i2 = i2a[0] < i2b[0] ? i2a : i2b;\n                    }\n                  if (!between.Used(i2))\n                    {\n                      between.Set (i2, 0);\n                      parents.Append(i2);\n                    }\n                }\n              break;\n            }\n            \n          default:\n            throw NgException (\"currently refinement for quad-elements is not supported\");\n          }\n      }\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      {\n\tconst Element & el = mesh[ei];\n\tswitch (el.GetType())\n\t  {\n\t  case TET:\n\t  case TET10:\n\t    {\n\t      static int betw[6][3] =\n                { { 1, 2, 5 },\n                  { 1, 3, 6 },\n                  { 1, 4, 7 },\n                  { 2, 3, 8 },\n                  { 2, 4, 9 },\n                  { 3, 4, 10 } };\n\n              for (int j = 0; j < 6; j++)\n                {\n                  INDEX_2 i2 = INDEX_2::Sort(el.PNum(betw[j][0]),el.PNum(betw[j][1]));\n                  if (!between.Used(i2))\n                    {\n                      between.Set (i2, 0);          \n                      parents.Append(i2);\n                    }\n                }\n              break;\n            }\n          default:\n            throw NgException (\"currently refinement for non-tet elements is not supported\");\n          }\n      }\n\n    PrintMessage (5, \"have points\");\n    \n    NgArray<int> par_nr(parents.Size());\n    for (int i = 0; i < par_nr.Size(); i++)\n      par_nr[i] = i;\n    QuickSort (parents, par_nr);\n    mesh.mlbetweennodes.SetSize(mesh.GetNV()+parents.Size());\n    for (int i = 0; i < parents.Size(); i++)\n      {\n        between.Set (parents[i], mesh.GetNV()+i+PointIndex::BASE);\n        mesh.mlbetweennodes[mesh.GetNV()+i+PointIndex::BASE] = parents[i];\n      }\n\n    mesh.SetNP(mesh.GetNV() + parents.Size());\n    NgArray<bool, PointIndex::BASE> pointset(mesh.GetNP());\n    pointset = false;\n    \n    PrintMessage (5, \"sorting complete\");\n    \n    // refine edges\n    NgArray<EdgePointGeomInfo,PointIndex::BASE> epgi;\n\n    int oldns = mesh.GetNSeg();\n    for (SegmentIndex si = 0; si < oldns; si++)\n      {\n\tconst Segment & el = mesh.LineSegment(si);\n\n\tINDEX_2 i2 = INDEX_2::Sort(el[0], el[1]);\n\tPointIndex pinew = between.Get(i2);\n\tEdgePointGeomInfo ngi;\n\n\tif (pointset[pinew])\n\t  {\n\t    // pinew = between.Get(i2);\n\t    ngi = epgi[pinew]; \n\t  }\n\telse\n\t  {\n            pointset[pinew] = true;\n\t    Point<3> pnew;\n\t    geo.PointBetweenEdge(mesh.Point (el[0]),\n                                 mesh.Point (el[1]), 0.5,\n                                 el.surfnr1, el.surfnr2,\n                                 el.epgeominfo[0], el.epgeominfo[1],\n                                 pnew, ngi);\n\n\t    // pinew = mesh.AddPoint (pnew);\n            mesh.Point(pinew) = pnew;\n\t    // between.Set (i2, pinew);\n\n\t    if (pinew >= epgi.Size()+IndexBASE<PointIndex>())\n\t      epgi.SetSize (pinew+1-IndexBASE<PointIndex>());\n\t    epgi[pinew] = ngi;\n\t  }\n\n\tSegment ns1 = el;\n\tSegment ns2 = el;\n\tns1[1] = pinew;\n\tns1.epgeominfo[1] = ngi;\n\tns2[0] = pinew;\n\tns2.epgeominfo[0] = ngi;\n\n\tmesh.LineSegment(si) = ns1;\n\tmesh.AddSegment (ns2);\n      }\n\n    PrintMessage (5, \"have 1d elements\");\n    \n    // refine surface elements\n    Array<PointGeomInfo,PointIndex> surfgi (8*mesh.GetNP());\n    for (int i = PointIndex::BASE;\n\t i < surfgi.Size()+PointIndex::BASE; i++)\n      surfgi[i].trignum = -1;\n\n\n    int oldnf = mesh.GetNSE();\n    for (SurfaceElementIndex sei = 0; sei < oldnf; sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\n\tswitch (el.GetType())\n\t  {\n\t  case TRIG:\n\t  case TRIG6:\n\t    {\n\t      NgArrayMem<PointIndex,6> pnums(6);\n\t      NgArrayMem<PointGeomInfo,6> pgis(6);\n\n\t      static int betw[3][3] =\n\t\t{ { 2, 3, 4 },\n\t\t  { 1, 3, 5 },\n\t\t  { 1, 2, 6 } };\n\n\t      for (int j = 1; j <= 3; j++)\n\t\t{\n\t\t  pnums.Elem(j) = el.PNum(j);\n\t\t  pgis.Elem(j) = el.GeomInfoPi(j);\n\t\t}\n\n\t      for (int j = 0; j < 3; j++)\n\t\t{\n\t\t  PointIndex pi1 = pnums.Elem(betw[j][0]);\n\t\t  PointIndex pi2 = pnums.Elem(betw[j][1]);\n\n\t\t  INDEX_2 i2 (pi1, pi2);\n\t\t  i2.Sort();\n\n\t\t  Point<3> pb;\n\t\t  PointGeomInfo pgi;\n\t\t  geo.PointBetween(mesh.Point (pi1),\n                                   mesh.Point (pi2), 0.5,\n                                   mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(),\n                                   el.GeomInfoPi (betw[j][0]),\n                                   el.GeomInfoPi (betw[j][1]),\n                                   pb, pgi);\n\n\n\t\t  pgis.Elem(4+j) = pgi;\n                  PointIndex pinew = between.Get(i2); \n                  pnums.Elem(4+j) = pinew;\n                  if (!pointset[pinew])\n                    {\n                      pointset[pinew] = true;\n                      mesh.Point(pinew) = pb;                      \n                    }\n                  /*\n\t\t  if (between.Used(i2))\n\t\t    pnums.Elem(4+j) = between.Get(i2);\n\t\t  else\n\t\t    {\n\t\t      pnums.Elem(4+j) = mesh.AddPoint (pb);\n\t\t      between.Set (i2, pnums.Get(4+j));\n\t\t    }\n                  */\n\t\t  if (surfgi.Size() < pnums.Elem(4+j)-IndexBASE<PointIndex>()+1)\n\t\t    surfgi.SetSize (pnums.Elem(4+j)-IndexBASE<PointIndex>()+1);\n\t\t  surfgi[pnums.Elem(4+j)] = pgis.Elem(4+j);\n\t\t}\n\n\n\t      static int reftab[4][3] =\n\t\t{ { 1, 6, 5 },\n\t\t  { 2, 4, 6 },\n\t\t  { 3, 5, 4 },\n\t\t  { 6, 4, 5 } };\n\n\t      int ind = el.GetIndex();\n\t      for (int j = 0; j < 4; j++)\n\t\t{\n\t\t  Element2d nel(TRIG);\n\t\t  for (int k = 1; k <= 3; k++)\n\t\t    {\n\t\t      nel.PNum(k) = pnums.Get(reftab[j][k-1]);\n\t\t      nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]);\n\t\t    }\n\t\t  nel.SetIndex(ind);\n\n\t\t  if (j == 0)\n\t\t    mesh[sei] = nel;\n\t\t  else\n\t\t    mesh.AddSurfaceElement(nel);\n\t\t}\n\t      break;\n\t    }\n\t  case QUAD:\n\t  case QUAD6:\n\t  case QUAD8:\n\t    {\n\t      PointIndex pnums[9];\n              PointGeomInfo pgis[9];\n\n\t      static int betw[5][3] =\n\t\t{ { 0, 1, 4 },\n\t\t  { 1, 2, 5 },\n\t\t  { 2, 3, 6 },\n\t\t  { 0, 3, 7 },\n\t\t  { 0, 2, 8 } };\n              \n\t      for (int j = 0; j < 4; j++)\n\t\t{\n\t\t  pnums[j] = el[j];\n\t\t  pgis[j] = el.GeomInfoPi(j+1);\n\t\t}\n\n\t      for (int j = 0; j < 5; j++)\n\t\t{\n\t\t  int pi1 = pnums[betw[j][0]];\n\t\t  int pi2 = pnums[betw[j][1]];\n\n\t\t  INDEX_2 i2 (pi1, pi2);\n\t\t  i2.Sort();\n                  \n                  if (j == 4)\n                    {\n                      auto i2a = PointIndices<2>::Sort(el[0], el[2]);\n                      auto i2b = PointIndices<2>::Sort(el[1], el[3]);\n                      i2 = i2a[0] < i2b[0] ? i2a : i2b;\n                    }\n\n                  Point<3> pb;\n\t\t  PointGeomInfo pgi;                  \n                  geo.PointBetween(mesh.Point (pi1), mesh.Point (pi2), 0.5,\n                                   mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(),\n                                   el.GeomInfoPi (betw[j][0]+1 ),\n                                   el.GeomInfoPi (betw[j][1]+1 ),\n                                   pb, pgi); \n\n\t\t  pgis[4+j] = pgi;\n                  PointIndex pinew = between.Get(i2); \n                  pnums[4+j] = pinew; \n\n                  if (!pointset[pinew])\n                    {\n                      pointset[pinew] = true;\n                      mesh.Point(pinew) = pb;                      \n                    }\n                  \n                  if (surfgi.Size() < pnums[4+j]-IndexBASE<PointIndex>()+1)\n                    surfgi.SetSize (pnums[4+j]-IndexBASE<PointIndex>()+1);\n                  surfgi[pnums[4+j]] = pgis[4+j];\n                }\n\n\t      static int reftab[4][4] =\n\t\t{\n\t\t  { 0, 4, 8, 7 },\n\t\t  { 4, 1, 5, 8 },\n\t\t  { 7, 8, 6, 3 },\n\t\t  { 8, 5, 2, 6 } };\n\n              \n\t      int ind = el.GetIndex();\n\t      for (int j = 0; j < 4; j++)\n\t\t{\n\t\t  Element2d nel(QUAD);\n\t\t  for (int k = 0; k < 4; k++)\n\t\t    {\n\t\t      nel[k] = pnums[reftab[j][k]];\n\t\t      nel.GeomInfoPi(k+1) = pgis[reftab[j][k]];\n\t\t    }\n\t\t  nel.SetIndex(ind);\n\n\t\t  if (j == 0)\n\t\t    mesh[sei] = nel;\n\t\t  else\n\t\t    mesh.AddSurfaceElement(nel);\n\t\t}\n\t      break;\n\t    }\n\t  default:\n\t    PrintSysError (\"Refine: undefined surface element type \", int(el.GetType()));\n\t  }\n      }\n\n    PrintMessage (5, \"have 2d elements\");\n    // cout << \"id = \" << id << \", ne = \" << mesh.GetNE() << endl;\n    // refine volume elements\n    int oldne = mesh.GetNE();\n    mesh.VolumeElements().SetAllocSize(8*oldne);\n    for (ElementIndex ei = 0; ei < oldne; ei++)\n      {\n\tconst Element & el = mesh[ei];\n\tswitch (el.GetType())\n\t  {\n\t  case TET:\n\t  case TET10:\n\t    {\n\t     NgArrayMem<PointIndex,10> pnums(10);\n\t     static int betw[6][3] =\n\t     { { 1, 2, 5 },\n\t       { 1, 3, 6 },\n\t       { 1, 4, 7 },\n\t       { 2, 3, 8 },\n\t       { 2, 4, 9 },\n\t       { 3, 4, 10 } };\n\n\t     int elrev = el.Flags().reverse;\n\n\t     for (int j = 1; j <= 4; j++)\n               pnums.Elem(j) = el.PNum(j);\n\t     if (elrev)\n\t     swap (pnums.Elem(3), pnums.Elem(4));\n\n\t     for (int j = 0; j < 6; j++)\n               {\n                 PointIndex pi1 = pnums.Get(betw[j][0]);\n                 PointIndex pi2 = pnums.Get(betw[j][1]);\n                 INDEX_2 i2 (pi1, pi2);\n                 i2.Sort();\n\n\t       /*\n\t       if (between.Used(i2))\n\t          pnums.Elem(5+j) = between.Get(i2);\n\t       else\n\t       {\n\t\t  pnums.Elem(5+j) = mesh.AddPoint\n\t\t  (Center (mesh.Point(i2.I1()),\n\t\t\t   mesh.Point(i2.I2())));\n\t\t  between.Set (i2, pnums.Elem(5+j));\n\t       }\n\t       */\n\t       PointIndex pinew = between.Get(i2);\n\t       pnums.Elem(j+5) = pinew;\n\t       if (!pointset[pinew])\n\t\t {\n\t\t   pointset[pinew] = true;\n\t\t   mesh.Point(pinew) = Center(mesh.Point(pi1),\n\t\t\t\t\t      mesh.Point(pi2));\n\t\t }\n\t    }\n\n\t    static int reftab[8][4] =\n\t    { { 1, 5, 6, 7 },\n\t      { 5, 2, 8, 9 },\n\t      { 6, 8, 3, 10 },\n\t      { 7, 9, 10, 4 },\n\t      { 5, 6, 7, 9 },\n\t      { 5, 6, 9, 8 },\n\t      { 6, 7, 9, 10 },\n\t      { 6, 8, 10, 9 } };\n\t/*\n\t  { { 1, 5, 6, 7 },\n\t  { 5, 2, 8, 9 },\n\t  { 6, 8, 3, 10 },\n\t  { 7, 9, 10, 4 },\n\t  { 5, 6, 7, 9 },\n\t  { 5, 6, 8, 9 },\n\t  { 6, 7, 9, 10 },\n\t  { 6, 8, 9, 10 } };\n\t*/\n\t   static bool reverse[8] =\n\t   {\n\t      false, false, false, false, false, true, false, true\n\t   };\n\n\t   int ind = el.GetIndex();\n\t   for (int j = 0; j < 8; j++)\n\t   {\n             Element nel(TET);\n\t      for (int k = 1; k <= 4; k++)\n\t        nel.PNum(k) = pnums.Get(reftab[j][k-1]);\n\t      nel.SetIndex(ind);\n\t      nel.Flags().reverse = reverse[j];\n\t      if (elrev)\n\t      {\n\t\tnel.Flags().reverse = !nel.Flags().reverse;\n\t\tswap (nel.PNum(3), nel.PNum(4));\n\t      }\n\n\t      if (j == 0)\n\t        mesh.VolumeElement(ei) = nel;\n\t      else\n\t        mesh.AddVolumeElement (nel);\n\t    }\n\t    break;\n          }\n          case HEX:\n          {\n\t     NgArrayMem<PointIndex,27> pnums(27);\n\t     static int betw[13][3] =\n\t     { { 1, 2, 9 },\n\t       { 3, 4, 10 },\n\t       { 4, 1, 11 },\n               { 2, 3, 12 },\n\t       { 5, 6, 13 },\n\t       { 7, 8, 14 },\n\t       { 8, 5, 15 },\n\t       { 6, 7, 16 },\n\t       { 1, 5, 17 },\n\t       { 2, 6, 18 },\n\t       { 3, 7, 19 },\n\t       { 4, 8, 20 },\n\t       { 2, 8, 21 },\n\t       };\n\n             /*\n\t     static int fbetw[12][3] =\n\t     { { 1, 3, 22 },\n\t       { 2, 4, 22 },\n\t       { 5, 7, 23 },\n               { 6, 8, 23 },\n\t       { 1, 6, 24 },\n\t       { 2, 5, 24 },\n\t       { 2, 7, 25 },\n\t       { 3, 6, 25 },\n\t       { 3, 8, 26 },\n\t       { 4, 7, 26 },\n\t       { 1, 8, 27 },\n\t       { 4, 5, 27 },\n\t       };\n             */\n             \n             // updated by anonymous supporter, donations please to Karo W.\n             static int fbetw[12][3] =\n               { { 11, 12, 22 },\n                 { 9, 10, 22 },\n                 { 13, 14, 23 },\n                 { 15, 16, 23 },\n                 { 9, 13, 24 },\n                 { 17, 18, 24 },\n                 { 12, 16, 25 },\n                 { 18, 19, 25 },\n                 { 19, 20, 26 },\n                 { 10, 14, 26 },\n                 { 11, 15, 27 },\n                 { 17, 20, 27 },\n               };\n\n\t     pnums = PointIndex(-1);\n\n\t     for (int j = 1; j <= 8; j++)\n               pnums.Elem(j) = el.PNum(j);\n\n\n\t     for (int j = 0; j < 13; j++)\n\t     {\n\t       INDEX_2 i2;\n\t       i2.I1() = pnums.Get(betw[j][0]);\n\t       i2.I2() = pnums.Get(betw[j][1]);\n\t       i2.Sort();\n\n\t       if (between.Used(i2))\n\t          pnums.Elem(9+j) = between.Get(i2);\n\t       else\n\t       {\n\t\t  pnums.Elem(9+j) = mesh.AddPoint\n\t\t  (Center (mesh.Point(i2.I1()),\n\t\t\t   mesh.Point(i2.I2())));\n\t\t  between.Set (i2, pnums.Elem(9+j));\n\t       }\n\t    }\n\n\t    for (int j = 0; j < 6; j++)\n\t    {\n\t       INDEX_2 i2a, i2b;\n\t       i2a.I1() = pnums.Get(fbetw[2*j][0]);\n\t       i2a.I2() = pnums.Get(fbetw[2*j][1]);\n\t       i2a.Sort();\n\t       i2b.I1() = pnums.Get(fbetw[2*j+1][0]);\n\t       i2b.I2() = pnums.Get(fbetw[2*j+1][1]);\n\t       i2b.Sort();\n\n\t       if (between.Used(i2a))\n\t\t pnums.Elem(22+j) = between.Get(i2a);\n\t       else if (between.Used(i2b))\n\t\t pnums.Elem(22+j) = between.Get(i2b);\n\t       else\n\t\t {\n\t\t   pnums.Elem(22+j) = mesh.AddPoint\n\t\t     (Center (mesh.Point(i2a.I1()),\n\t\t\t      mesh.Point(i2a.I2())));\n\n\t\t   between.Set (i2a, pnums.Elem(22+j));\n\t\t }\n\t    }\n\n\t    static int reftab[8][8] =\n\t    { { 1, 9, 22, 11, 17, 24, 21, 27 },\n\t      { 9, 2, 12, 22, 24, 18, 25, 21 },\n\t      { 11, 22, 10, 4, 27, 21, 26, 20},\n\t      { 22, 12, 3, 10, 21, 25, 19, 26},\n\t      { 17, 24, 21, 27, 5, 13, 23, 15},\n\t      { 24, 18, 25, 21, 13, 6, 16, 23},\n\t      { 27, 21, 26, 20, 15, 23, 14, 8},\n\t      { 21, 25, 19, 26, 23, 16, 7, 14} };\n\n\n\t   int ind = el.GetIndex();\n\t   for (int j = 0; j < 8; j++)\n\t   {\n\t      Element nel(HEX);\n\t      for (int k = 1; k <= 8; k++)\n\t        nel.PNum(k) = pnums.Get(reftab[j][k-1]);\n\t      nel.SetIndex(ind);\n\n              if (j == 0)\n\t        mesh.VolumeElement(ei) = nel;\n\t      else\n\t        mesh.AddVolumeElement (nel);\n           }\n           break;\n\t  }\n\t  case PRISM:\n          {\n\t     NgArrayMem<PointIndex,18> pnums(18);\n\t     static int betw[9][3] =\n\t     { { 3, 1, 7 },\n\t       { 1, 2, 8 },\n\t       { 3, 2, 9 },\n               { 6, 4, 10 },\n\t       { 4, 5, 11 },\n\t       { 6, 5, 12 },\n\t       { 1, 4, 13 },\n\t       { 3, 6, 14 },\n\t       { 2, 5, 15 },\n\t       };\n\n// he: 15.jul 08, old version is wrong\n//                produces double points ad quad faces and inconsistent mesh\n// \t     static int fbetw[6][3] =\n// \t     { { 1, 6, 16 },\n// \t       { 3, 4, 16 },\n// \t       { 1, 5, 17 },\n//                { 2, 4, 17 },\n// \t       { 2, 6, 18 },\n// \t       { 3, 5, 18 },\n// \t       };\n           \n           static int fbetw[6][3] =\n           { { 7, 10, 16 },\n           { 14, 13, 16 },\n           { 11, 8, 17 },\n           { 13, 15, 17 },\n           { 12, 9, 18 },\n           { 14, 15, 18 },\n           };\n\n\t     //int elrev = el.flags.reverse;\n           pnums = PointIndex(-1);\n           \n           for (int j = 1; j <= 6; j++)\n\t     pnums.Elem(j) = el.PNum(j);\n\t    // if (elrev)\n\t    // swap (pnums.Elem(3), pnums.Elem(4));\n\n\t   for (int j = 0; j < 9; j++)\n           {\n\t       INDEX_2 i2;\n\t       i2.I1() = pnums.Get(betw[j][0]);\n\t       i2.I2() = pnums.Get(betw[j][1]);\n\t       i2.Sort();\n\n\t       if (between.Used(i2))\n\t          pnums.Elem(7+j) = between.Get(i2);\n\t       else\n\t       {\n\t\t  pnums.Elem(7+j) = mesh.AddPoint\n\t\t  (Center (mesh.Point(i2.I1()),\n\t\t\t   mesh.Point(i2.I2())));\n\t\t  between.Set (i2, pnums.Elem(7+j));\n\t       }\n           }\n\n           for (int j = 0; j < 3; j++)\n\t   {\n\t       INDEX_2 i2a, i2b;\n\t       i2a.I1() = pnums.Get(fbetw[2*j][0]);\n\t       i2a.I2() = pnums.Get(fbetw[2*j][1]);\n\t       i2a.Sort();\n\t       i2b.I1() = pnums.Get(fbetw[2*j+1][0]);\n\t       i2b.I2() = pnums.Get(fbetw[2*j+1][1]);\n\t       i2b.Sort();\n\n\t       if (between.Used(i2a))\n\t\t pnums.Elem(16+j) = between.Get(i2a);\n\t       else if (between.Used(i2b))\n\t\t pnums.Elem(16+j) = between.Get(i2b);\n\t       else\n\t\t {\n\t\t   pnums.Elem(16+j) = mesh.AddPoint\n\t\t     (Center (mesh.Point(i2a.I1()),\n\t\t\t      mesh.Point(i2a.I2())));\n\n\t\t   between.Set (i2a, pnums.Elem(16+j));\n\t\t }\n\t    }\n\n\n\t    static int reftab[8][6] =\n\t    { { 1, 8, 7, 13, 17, 16 },\n\t      { 7, 8, 9, 16, 17, 18 },\n\t      { 7, 9, 3, 16, 18, 14 },\n\t      { 8, 2, 9, 17, 15, 18 },\n\t      { 13, 17, 16, 4, 11, 10 },\n\t      { 16, 17, 18, 10, 11, 12 },\n\t      { 16, 18, 14, 10, 12, 6 },\n\t      { 17, 15, 18, 11, 5, 12 } };\n\n\n\t   int ind = el.GetIndex();\n\t   for (int j = 0; j < 8; j++)\n\t   {\n\t      Element nel(PRISM);\n\t      for (int k = 1; k <= 6; k++)\n\t        nel.PNum(k) = pnums.Get(reftab[j][k-1]);\n\t      nel.SetIndex(ind);\n\n\n\t      //nel.flags.reverse = reverse[j];\n\t      //if (elrev)\n\t     // {\n\t\t//nel.flags.reverse = 1 - nel.flags.reverse;\n\t\t//swap (nel.PNum(3), nel.PNum(4));\n\n\n\t      if (j == 0)\n\t        mesh.VolumeElement(ei) = nel;\n\t      else\n\t        mesh.AddVolumeElement (nel);\n           }\n           break;\n\t  }\n\t  default:\n\t    PrintSysError (\"Refine: undefined volume element type \", int(el.GetType()));\n        }\n      }\n\n\n    // update identification tables\n    for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tidmap_type identmap;\n\tmesh.GetIdentifications().GetMap (i, identmap);\n\n\tfor (int j = 1; j <= between.GetNBags(); j++)\n\t  for (int k = 1; k <= between.GetBagSize(j); k++)\n\t    {\n\t      PointIndices<2> i2;\n\t      PointIndex newpi;\n\t      between.GetData (j, k, i2, newpi);\n\t      PointIndices<2> oi2(identmap[i2[0]], \n                                  identmap[i2[1]]);\n\t      oi2.Sort();\n\t      if (between.Used (oi2))\n\t\t{\n\t\t  PointIndex onewpi = between.Get(oi2);\n\t\t  mesh.GetIdentifications().Add (newpi, onewpi, i);\n\t\t}\n\t    }\n\n      }\n\n    PrintMessage (5, \"have 3d elements\");\n    mesh.ComputeNVertices();\n    mesh.RebuildSurfaceElementLists();\n\n    mesh.level_nv.Append (mesh.GetNV());\n\n#ifdef PARALLEL\n    if (mesh.GetCommunicator().Size() > 1)\n      {\n        mesh.GetParallelTopology().IdentifyVerticesAfterRefinement();\n        mesh.GetCommunicator().Barrier();\n        mesh.GetParallelTopology().EnumeratePointsGlobally();\n      }\n#endif\n      \n    PrintMessage (5, \"mesh updates complete\");\n    return;\n\n    int cnttrials = 10;\n    int wrongels = 0;\n\n    for (auto & el : mesh.VolumeElements())\n      if (el.Volume(mesh.Points()) < 0)\n\t{\n\t  wrongels++;\n\t  el.Flags().badel = 1;\n\t}\n      else\n\tel.Flags().badel = 0;\n\n    if (wrongels)\n      {\n\tcout << \"WARNING: \" << wrongels << \" with wrong orientation found\" << endl;\n\n\tint np = mesh.GetNP();\n\tNgArray<Point<3> > should(np);\n\tNgArray<Point<3> > can(np);\n\tfor (int i = 1; i <= np; i++)\n\t  {\n\t    should.Elem(i) = can.Elem(i) = mesh.Point(i);\n\t  }\n\tfor (int i = 1; i <= between.GetNBags(); i++)\n\t  for (int j = 1; j <= between.GetBagSize(i); j++)\n\t    {\n\t      INDEX_2 parent;\n\t      PointIndex child;\n\t      between.GetData (i, j, parent, child);\n\t      can.Elem(child) = Center (can.Elem(parent.I1()),\n\t\t\t\t\tcan.Elem(parent.I2()));\n\t    }\n\n\tTBitArray<PointIndex> boundp(np);\n\tboundp.Clear();\n\tfor (auto & sel : mesh.SurfaceElements())\n          for (auto pi : sel.PNums())\n            boundp.SetBit(pi);\n\n\n\tdouble lam = 0.5;\n\n\twhile (lam < 0.9 && cnttrials > 0)\n\t  {\n\t    lam = 2;\n\t    do\n\t      {\n\t\tlam *= 0.5;\n\t\tcnttrials--;\n\n\t\tcout << \"lam = \" << lam << endl;\n\n\t\tfor (int i = 1; i <= np; i++)\n\t\t  if (boundp.Test(i))\n\t\t    {\n\t\t      for (int j = 0; j < 3; j++)\n\t\t\tmesh.Point(i)(j) = \n\t\t\t  lam * should.Get(i)(j) +\n\t\t\t  (1-lam) * can.Get(i)(j);\n\t\t    }\n\t\t  else\n\t\t    mesh.Point(i) = can.Get(i);\n\t      \n\n\t\tTBitArray<PointIndex> free (mesh.GetNP()), fhelp(mesh.GetNP());\n\t\tfree.Clear();\n\t\t// for (int i = 1; i <= mesh.GetNE(); i++)\n                for (ElementIndex ei : mesh.VolumeElements().Range())\n\t\t  {\n\t\t    const Element & el = mesh.VolumeElement(ei);\n\t\t    if (el.Volume(mesh.Points()) < 0)\n\t\t      for (int j = 1; j <= el.GetNP(); j++)\n\t\t\tfree.SetBit (el.PNum(j));\n\t\t  }\n\t\tfor (int k = 1; k <= 3; k++)\n\t\t  {\n\t\t    fhelp.Clear();\n\t\t    // for (int i = 1; i <= mesh.GetNE(); i++) \n                    for (const Element & el : mesh.VolumeElements())\n\t\t      {\n\t\t\t// const Element & el = mesh.VolumeElement(i);\n\t\t\tint freeel = 0;\n\t\t\tfor (int j = 1; j <= el.GetNP(); j++)\n\t\t\t  if (free.Test(el.PNum(j)))\n\t\t\t    freeel = 1;\n\t\t\tif (freeel)\n\t\t\t  for (int j = 1; j <= el.GetNP(); j++)\n\t\t\t    fhelp.SetBit (el.PNum(j));\n\t\t      }\n\t\t    free.Or (fhelp);\n\t\t  }\n\n\t\t(*testout) << \"smooth points: \" << endl;\n\t\tfor (int i = 1; i <= free.Size(); i++)\n\t\t  if (free.Test(i))\n\t\t    (*testout) << \"p \" << i << endl;\n\n\t\t(*testout) << \"surf points: \" << endl;\n\t\tfor (auto & sel : mesh.SurfaceElements())\n\t\t  for (auto pi : sel.PNums())\n\t\t    (*testout) << pi << endl;\n\n\t\tmesh.CalcSurfacesOfNode();\n\t\tfree.Invert();\n\t\tmesh.FixPoints (free);\n\t\tMeshingParameters dummymp;\n\t\tmesh.ImproveMesh (dummymp, OPT_REST);\n\n\n\t\twrongels = 0;\n                for (ElementIndex ei : mesh.VolumeElements().Range())\n\t\t  {\n\t\t    if (mesh.VolumeElement(ei).Volume(mesh.Points()) < 0)\n\t\t      {\n\t\t\twrongels++;\n\t\t\tmesh.VolumeElement(ei).Flags().badel = 1;\n\t\t\t(*testout) << \"wrong el: \";\n\t\t\tfor (int j = 1; j <= 4; j++)\n\t\t\t  (*testout) << mesh.VolumeElement(ei).PNum(j) << \" \";\n\t\t\t(*testout) << endl;\n\t\t      }\n\t\t    else\n\t\t      mesh.VolumeElement(ei).Flags().badel = 0;\n\t\t  }\n\t\tcout << \"wrongels = \" << wrongels << endl;\n\t      }\n\t    while (wrongels && cnttrials > 0);\n\t  \n\t    for (int i = 1; i <= np; i++)\n\t      can.Elem(i) = mesh.Point(i);\n\t  }\n      }\n\n    if (cnttrials <= 0)\n      {\n\tcerr << \"ERROR: Sorry, reverted elements\" << endl;\n      }\n \n    mesh.ComputeNVertices();\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/ruler2.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n\n\n  static double CalcElementBadness (const NgArray<Point<2>> & points,\n\t\t\t\t    const Element2d & elem)\n  {\n    // badness = sqrt(3) /36 * circumference^2 / area - 1 +\n    //           h / li + li / h - 2\n\n    Vec<2> v12, v13, v23;\n    double l12, l13, l23, cir, area;\n    static const double c = sqrt(3.0) / 36;\n\n    v12 = points.Get(elem.PNum(2)) - points.Get(elem.PNum(1));\n    v13 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(1));\n    v23 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(2));\n\n    l12 = v12.Length();\n    l13 = v13.Length();\n    l23 = v23.Length();\n\n    cir = l12 + l13 + l23;\n    area = 0.5 * (v12[0] * v13[1] - v12[1] * v13[0]);\n    if (area < 1e-6)\n      {\n\treturn 1e8;\n      }\n\n    if (testmode)\n      {\n\t(*testout) << \"l = \" << l12 << \" + \" << l13 << \" + \" << l23 << \" = \" \n\t\t   << cir << \", area = \" << area << endl;\n\t(*testout) << \"shapeerr = \" << 10 * (c * cir * cir / area - 1) << endl\n\t\t   << \"sizeerr = \" << 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6\n\t\t   << endl;\n      }\n\n    return 10 * (c * cir * cir / area - 1)\n      + 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6;\n  }\n\n\n\n  int Meshing2 ::ApplyRules (NgArray<Point<2>> & lpoints, \n\t\t\t     NgArray<int> & legalpoints,\n\t\t\t     int maxlegalpoint,\n\t\t\t     NgArray<INDEX_2> & llines1,\n\t\t\t     int maxlegalline,\n\t\t\t     NgArray<Element2d> & elements,\n\t\t\t     NgArray<INDEX> & dellines, int tolerance,\n\t\t\t     const MeshingParameters & mp)\n  {\n    // static Timer timer (\"meshing2::ApplyRules\"); RegionTimer reg (timer);\n\n\n    double maxerr = 0.5 + 0.3 * tolerance;\n    double minelerr = 2 + 0.5 * tolerance * tolerance;\n\n    int noldlp = lpoints.Size();\n    int noldll = llines1.Size();\n\n\n    NgArrayMem<int,100> pused(maxlegalpoint), lused(maxlegalline);\n    NgArrayMem<int,100> pnearness(noldlp), lnearness(llines1.Size());\n\n    NgArrayMem<int, 20> pmap, pfixed, lmap;\n  \n    NgArrayMem<Point<2>,100> tempnewpoints;\n    NgArrayMem<INDEX_2,100> tempnewlines;\n    NgArrayMem<int,100> tempdellines;\n    NgArrayMem<Element2d,100> tempelements;\n\n    // a least 2 * maximal number of old points in rules,\n    // what is actually 4 now\n    double oldumem[20];  \n\n    elements.SetSize (0);\n    dellines.SetSize (0);\n\n    testmode = debugparam.debugoutput;\n\n#ifdef LOCDEBUG\n    int loctestmode = testmode;\n\n    if (loctestmode)\n      {\n\t(*testout) << endl << endl << \"Check new environment\" << endl;\n\t(*testout) << \"tolerance = \" << tolerance << endl;\n\tfor (int i = 1; i <= lpoints.Size(); i++)\n\t  (*testout) << \"P\" << i << \" = \" << lpoints.Get(i) << endl;\n\t(*testout) << endl;\n\tfor (int i = 1; i <= llines1.Size(); i++)\n\t  (*testout) << \"(\" << llines1.Get(i).I1() << \"-\" << llines1.Get(i).I2() << \")\" << endl;\n      }\n#endif\n\n    // check every rule\n\n    int found = 0;   // rule number\n\n    pnearness = 1000;\n  \n    for (int j = 0; j < 2; j++)\n      pnearness.Set(llines1[0][j], 0);\n\n\n\n    enum { MAX_NEARNESS = 3 };\n\n    for (int cnt = 0; cnt < MAX_NEARNESS; cnt++)\n      {\n\tbool ok = true;\n\tfor (int i = 0; i < maxlegalline; i++)\n\t  {\n\t    const INDEX_2 & hline = llines1[i];\n\n\t    int minn = min2 (pnearness.Get(hline[0]),  pnearness.Get(hline[1]));\n\n\t    for (int j = 0; j < 2; j++)\n\t      if (pnearness.Get(hline[j]) > minn+1)\n\t\t{\n\t\t  ok = false;\n\t\t  pnearness.Set(hline[j], minn+1);\n\t\t}\n\t  }\n\tif (!ok) break;\n      }\n\n\n    for (int i = 0; i < maxlegalline; i++)\n      lnearness[i] = pnearness.Get(llines1[i][0]) + pnearness.Get(llines1[i][1]);\n\n\n    // resort lines after lnearness\n    NgArray<INDEX_2> llines(llines1.Size());\n    NgArray<int> sortlines(llines1.Size());\n    int lnearness_class[MAX_NEARNESS];\n\n    for (int j = 0; j < MAX_NEARNESS; j++)\n      lnearness_class[j] = 0;\n    for (int i = 0; i < maxlegalline; i++)\n      if (lnearness[i] < MAX_NEARNESS)\n\tlnearness_class[lnearness[i]]++;\n    \n    int cumm = 0;\n    for (int j = 0; j < MAX_NEARNESS; j++)\n      {\n\tint hcnt = lnearness_class[j];\n\tlnearness_class[j] = cumm;\n\tcumm += hcnt;\n      }\n\n    for (int i = 0; i < maxlegalline; i++)\n      if (lnearness[i] < MAX_NEARNESS)\n\t{\n\t  llines[lnearness_class[lnearness[i]]] = llines1[i];\n\t  sortlines[lnearness_class[lnearness[i]]] = i+1;\n\t  lnearness_class[lnearness[i]]++;\n\t}\n      else\n\t{\n\t  llines[cumm] = llines1[i];\n\t  sortlines[cumm] = i+1;\n\t  cumm++;\n\t}\n\n    for (int i = maxlegalline; i < llines1.Size(); i++)\n      {\n\tllines[cumm] = llines1[i];\n\tsortlines[cumm] = i+1;\n\tcumm++;\n      }\n\n    for (int i = 0; i < maxlegalline; i++)\n      lnearness[i] = pnearness.Get(llines[i][0]) + pnearness.Get(llines[i][1]);\n\n\n\n\n    static bool firsttime = true;\n    // static int timers[100];\n    // static int timers2[100];\n    // static int timers3[100];\n    if (firsttime)\n      {\n\t/*\n\tfor (int ri = 0; ri < rules.Size(); ri++)\n\t  timers[ri] = NgProfiler::CreateTimer (string(\"netrule \")+rules[ri]->Name());\n\tfor (int ri = 0; ri < rules.Size(); ri++)\n\t  timers2[ri] = NgProfiler::CreateTimer (string(\"netrule,mapped \")+rules[ri]->Name());\n\tfor (int ri = 0; ri < rules.Size(); ri++)\n\t  timers3[ri] = NgProfiler::CreateTimer (string(\"netrule,lines mapped \")+rules[ri]->Name());\n\t*/\n\tfirsttime = false;\n      }\n\n    lused = 0;\n    pused = 0;\n\n\n    static int timer1 = NgProfiler::CreateTimer (\"meshing2::ApplyRules 1\");\n    NgProfiler::RegionTimer reg1 (timer1);\n\n\n    for (int ri = 1; ri <= rules.Size(); ri++)\n      {\n\t// NgProfiler::RegionTimer reg(timers[ri-1]);\n\tnetrule * rule = rules[ri-1].get();\n\n#ifdef LOCDEBUG\n\tif (loctestmode)\n\t  (*testout) << \"Rule \" << rule->Name() << endl;\n#endif\n\n\tif (rule->GetQuality() > tolerance) continue;\n\n\tpmap.SetSize (rule->GetNP());\n\tlmap.SetSize (rule->GetNL());\n      \n\tpmap = 0;\n\tlmap = 0;\n\n\tlused[0] = 1; \n\tlmap[0] = 1;  \n\n\tfor (int j = 0; j < 2; j++)\n\t  {\n\t    pmap.Elem(rule->GetLine(1)[j]) = llines[0][j];\n\t    pused.Elem(llines[0][j])++;\n\t  }\n\n\n\n\tint nlok = 2;\n\n\n\tbool ok = false;\n\n\twhile (nlok >= 2)\n\t  {\n\n\t    if (nlok <= rule->GetNOldL())\n\n\t      {\n\t\tok = 0;\n\t\t\n\t\tint maxline = (rule->GetLNearness(nlok) < MAX_NEARNESS) ? lnearness_class[rule->GetLNearness(nlok)] : maxlegalline;\n\t\t// int maxline = maxlegalline;\n\n\t\twhile (!ok && lmap.Get(nlok) < maxline)\n\t\t  {\n\t\t    lmap.Elem(nlok)++;\n\t\t    int locli = lmap.Get(nlok);\n\n\t\t    if (lnearness.Get(locli) > rule->GetLNearness (nlok) ) continue;\n\t\t    if (lused.Get(locli)) continue;\n\n\n\t\t    ok = 1;\n\n\t\t    INDEX_2 loclin = llines.Get(locli);\n\t\t    auto linevec = lpoints.Get(loclin.I2()) - lpoints.Get(loclin.I1());\n\n\t\t    if (rule->CalcLineError (nlok, linevec) > maxerr)\n\t\t      {\n\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\tif(loctestmode)\n\t\t\t  (*testout) << \"not ok pos1\" << endl;\n#endif\n\t\t\tcontinue;\n\t\t      }\n\n\t\t    for (int j = 0; j < 2; j++)\n\t\t      {\n\t\t\tint refpi = rule->GetLine(nlok)[j];\n\n\t\t\tif (pmap.Get(refpi) != 0)\n\t\t\t  {\n\t\t\t    if (pmap.Get(refpi) != loclin[j])\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif(loctestmode)\n\t\t\t\t  (*testout) << \"not ok pos2\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    if (rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr\n\t\t\t\t|| !legalpoints.Get(loclin[j])\n\t\t\t\t|| pused.Get(loclin[j]))\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif(loctestmode)\n\t\t\t\t  {\n\t\t\t\t    (*testout) << \"nok pos3\" << endl;\n\t\t\t\t    //if(rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr)\n\t\t\t\t    //(*testout) << \"r1\" << endl;\n\t\t\t\t    //if(!legalpoints.Get(loclin[j]))\n\t\t\t\t    //(*testout) << \"r2 legalpoints \" << legalpoints << \" loclin \" << loclin << \" j \" << j << endl;\n\t\t\t\t    //if(pused.Get(loclin[j]))\n\t\t\t\t    //(*testout) << \"r3\" << endl;\n\t\t\t\t  }\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\t\t      }\n\t\t  }\n\n\t\tif (ok)\n\t\t  {\n\t\t    int locli = lmap.Get(nlok);\n\t\t    INDEX_2 loclin = llines.Get(locli);\n\n\t\t    lused.Elem (locli) = 1;\n\t\t    for (int j = 0; j < 2; j++)\n\t\t      {\n\t\t\tpmap.Set(rule->GetLine (nlok)[j], loclin[j]);\n\t\t\tpused.Elem(loclin[j])++;\n\t\t      }\n\n\t\t    nlok++;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    lmap.Elem(nlok) = 0;\n\t\t    nlok--;\n\n\t\t    lused.Elem (lmap.Get(nlok)) = 0;\n\t\t    for (int j = 0; j < 2; j++)\n\t\t      {\n\t\t\tpused.Elem(llines.Get(lmap.Get(nlok))[j]) --;\n\t\t\tif (! pused.Get (llines.Get (lmap.Get (nlok))[j]))\n\t\t\t  pmap.Set (rule->GetLine (nlok)[j], 0);\n\t\t      }\n\t\t  }\n\t      }\n\n\t    else\n\n\t      {\n\t\t// NgProfiler::RegionTimer reg(timers3[ri-1]);\n\n\t\t// all lines are mapped !!\n\n\t\t// map also all points:\n\n\t\tint npok = 1;\n\t\tint incnpok = 1;\n\n\t\tpfixed.SetSize (pmap.Size());\n\t\tfor (int i = 0; i < pmap.Size(); i++)\n\t\t  pfixed[i] = (pmap[i] >= 1);\n \n\t\twhile (npok >= 1)\n\t\t  {\n\n\t\t    if (npok <= rule->GetNOldP())\n\n\t\t      {\n\t\t\tif (pfixed.Get(npok))\n\n\t\t\t  {\n\t\t\t    if (incnpok)\n\t\t\t      npok++;\n\t\t\t    else\n\t\t\t      npok--;\n\t\t\t  }\n\n\t\t\telse\n\n\t\t\t  {\n\t\t\t    ok = 0;\n\n\t\t\t    if (pmap.Get(npok))\n\t\t\t      pused.Elem(pmap.Get(npok))--;\n\n\t\t\t    while (!ok && pmap.Get(npok) < maxlegalpoint)\n\t\t\t      {\n\t\t\t\tok = 1;\n\n\t\t\t\tpmap.Elem(npok)++;\n\n\t\t\t\tif (pused.Get(pmap.Get(npok)))\n\t\t\t\t  {\n\t\t\t\t    ok = 0;\n\t\t\t\t  }\n\t\t\t\telse\n\t\t\t\t  {\n\t\t\t\t    if (rule->CalcPointDist (npok, lpoints.Get(pmap.Get(npok))) > maxerr \n\t\t\t\t\t|| !legalpoints.Get(pmap.Get(npok))) \n                                    \n\t\t\t\t      ok = 0;\n\t\t\t\t  }\n\t\t\t      }\n\n\t\t\t    if (ok)\n\t\t\t      {\n\t\t\t\tpused.Elem(pmap.Get(npok))++;\n\t\t\t\tnpok++;\n\t\t\t\tincnpok = 1;\n\t\t\t      }\n\n\t\t\t    else\n\n\t\t\t      {\n\t\t\t\tpmap.Elem(npok) = 0;\n\t\t\t\tnpok--;\n\t\t\t\tincnpok = 0;\n\t\t\t      }\n\t\t\t  }\n\t\t      }\n\n\t\t    else\n\n\t\t      {\n\t\t\t// NgProfiler::RegionTimer reg(timers2[ri-1]);\n\n\t\t\tnpok = rule->GetNOldP();\n\t\t\tincnpok = 0;\n\n\t\t\tif (ok)\n\t\t\t  foundmap.Elem(ri)++; \n\n#ifdef LOCDEBUG\n\t\t\tif (loctestmode)\n\t\t\t  (*testout) << \"lines and points mapped\" << endl;\n#endif\n\n\t\t\tok = 1;\n\n\t\t\t// check orientations\n\n\t\t\tfor (int i = 1; i <= rule->GetNOrientations(); i++)\n\t\t\t  {\n\t\t\t    if (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)),\n\t\t\t\t    lpoints.Get(pmap.Get(rule->GetOrientation(i).i2)),\n\t\t\t\t    lpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) )\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif (loctestmode)\n\t\t\t\t  (*testout) << \"Orientation \" << i << \" not ok\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\n\n\t\t\tif (!ok) continue;\n\n\t\t\t// Vector oldu (2 * rule->GetNOldP());\n                        Vector oldu (2 * rule->GetNOldP(), &oldumem[0]);\n\t\t      \n\t\t\tfor (int i = 1; i <= rule->GetNOldP(); i++)\n\t\t\t  {\n\t\t\t    Vec2d ui(rule->GetPoint(i), lpoints.Get(pmap.Get(i)));\n\t\t\t    oldu (2*i-2) = ui.X();\n\t\t\t    oldu (2*i-1) = ui.Y();\n\t\t\t  }\n\t\t      \n\t\t\trule -> SetFreeZoneTransformation (oldu, tolerance);\n\n\t\t      \n\t\t\tif (!ok) continue;\n\t\t\tif (!rule->ConvexFreeZone())\n\t\t\t  {\n\t\t\t    ok = 0;\n#ifdef LOCDEBUG\n\t\t\t    if (loctestmode) \n\t\t\t      (*testout) << \"freezone not convex\" << endl;\n#endif\n\t\t\t    /*\n\t\t\t      static int cnt = 0;\n\t\t\t      cnt++;\n\t\t\t      if (cnt % 100 == 0)\n\t\t\t      {\n\t\t\t      cout << \"freezone not convex, cnt = \" << cnt << \"; rule = \" << rule->Name() << endl;\n\t\t\t      (*testout) << \"freezone not convex, cnt = \" << cnt << \"; rule = \" << rule->Name() << endl;\n\t\t\t      (*testout) << \"tol = \" << tolerance << endl;\n\t\t\t      (*testout) << \"maxerr = \" << maxerr << \"; minerr = \" << minelerr << endl;\n\t\t\t      (*testout) << \"freezone = \" << rule->GetTransFreeZone() << endl;\n\t\t\t      }\n\t\t\t    */\n\t\t\t  }\n\n\t\t\t// check freezone:\n\t\t\tif (!ok) continue;\n\t\t\tfor (int i = 1; i <= maxlegalpoint && ok; i++)\n\t\t\t  {\n\t\t\t    if ( !pused.Get(i) &&\n\t\t\t\t rule->IsInFreeZone (lpoints.Get(i)) )\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif (loctestmode)\n\t\t\t\t  (*testout) << \"Point \" << i << \" in freezone\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\n\t\t\tif (!ok) continue;\n\t\t\tfor (int i = maxlegalpoint+1; i <= lpoints.Size(); i++)\n\t\t\t  {\n\t\t\t    if ( rule->IsInFreeZone (lpoints.Get(i)) )\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif (loctestmode)\n\t\t\t\t  (*testout) << \"Point \" << i << \" in freezone\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\n\n\t\t\tif (!ok) continue;\n\t\t\tfor (int i = 1; i <= maxlegalline; i++)\n\t\t\t  {\n\t\t\t    if (!lused.Get(i) && \n\t\t\t\trule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()),\n\t\t\t\t\t\t\tlpoints.Get(llines.Get(i).I2())))\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif (loctestmode)\n\t\t\t\t  (*testout) << \"line \" << llines.Get(i).I1() << \"-\"\n\t\t\t\t\t     << llines.Get(i).I2() << \" in freezone\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\n\t\t\tif (!ok) continue;\n\n\t\t\tfor (int i = maxlegalline+1; i <= llines.Size(); i++)\n\t\t\t  {\n\t\t\t    if (rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()),\n\t\t\t\t\t\t\tlpoints.Get(llines.Get(i).I2())))\n\t\t\t      {\n\t\t\t\tok = 0;\n#ifdef LOCDEBUG\n\t\t\t\tif (loctestmode)\n\t\t\t\t  (*testout) << \"line \" << llines.Get(i).I1() << \"-\"\n\t\t\t\t\t     << llines.Get(i).I2() << \" in freezone\" << endl;\n#endif\n\t\t\t\tbreak;\n\t\t\t      }\n\t\t\t  }\n\n\n\t\t\t/*\n\t\t\t// check orientations\n\n\t\t\tfor (i = 1; i <= rule->GetNOrientations() && ok; i++)\n\t\t\t{\n\t\t\tif (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)),\n\t\t\tlpoints.Get(pmap.Get(rule->GetOrientation(i).i2)),\n\t\t\tlpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) )\n\t\t\t{\n\t\t\tok = 0;\n\t\t\tif (loctestmode)\n\t\t\t(*testout) << \"Orientation \" << i << \" not ok\" << endl;\n\t\t\t}\n\t\t\t}\n\t\t\t*/\n\n\n\t\t\tif (!ok) continue;\n\n#ifdef LOCDEBUG\n\t\t\tif (loctestmode)\n\t\t\t  (*testout) << \"rule ok\" << endl;\n#endif\n\n\t\t\t// Setze neue Punkte:\n\t\t\tif (rule->GetNOldP() < rule->GetNP())\n\t\t\t  {\n\t\t\t    Vector newu(rule->GetOldUToNewU().Height());\n\t\t\t    rule->GetOldUToNewU().Mult (oldu, newu);\n\t\t\t    \n\t\t\t    int oldnp = rule->GetNOldP();\n\t\t\t    for (int i = oldnp + 1; i <= rule->GetNP(); i++)\n\t\t\t      {\n\t\t\t\tauto np = rule->GetPoint(i);\n\t\t\t\tnp[0] += newu (2 * (i-oldnp) - 2);\n\t\t\t\tnp[1] += newu (2 * (i-oldnp) - 1);\n\n                                lpoints.Append (np);\n\t\t\t\tpmap.Elem(i) = lpoints.Size();\n\t\t\t      }\n\t\t\t  }\n\n\t\t\t// Setze neue Linien:\n\n\t\t\tfor (int i = rule->GetNOldL() + 1; i <= rule->GetNL(); i++)\n\t\t\t  {\n\t\t\t    llines.Append (INDEX_2 (pmap.Get(rule->GetLine (i)[0]),\n\t\t\t\t\t\t    pmap.Get(rule->GetLine (i)[1])));\n\t\t\t  }\n\n\n\t\t\t// delete old lines:\n\t\t\tfor (int i = 1; i <= rule->GetNDelL(); i++)\n\t\t\t  dellines.Append (sortlines.Elem (lmap.Get(rule->GetDelLine(i))));\n\t\t\t// dellines.Append (lmap.Get(rule->GetDelLine(i))));\n\n\t\t\t// dellines.Append (lmap.Elem(rule->GetDelLines()));\n\t\t\t// lmap[rule->GetDelLines()];\n\n\n\t\t\t// insert new elements:\n\n\t\t\tfor (int i = 1; i <= rule->GetNE(); i++)\n\t\t\t  {\n\t\t\t    elements.Append (rule->GetElement(i));\n\t\t\t    for (int j = 1; j <= elements.Get(i).GetNP(); j++)\n\t\t\t      elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j));\n\t\t\t  }\n\n\n\t\t\tdouble elerr = 0;\n\t\t\tfor (int i = 1; i <= elements.Size(); i++)\n\t\t\t  {\n\t\t\t    double hf;\n\t\t\t    if (!mp.quad)\n\t\t\t      hf = CalcElementBadness (lpoints, elements.Get(i));\n\t\t\t    else\n\t\t\t      hf = elements.Get(i).CalcJacobianBadness (lpoints) * 5;\n#ifdef LOCDEBUG\n\t\t\t    if (loctestmode)\n\t\t\t      (*testout) << \"r \" << rule->Name() << \"bad = \" << hf << endl;\n#endif\n\t\t\t    if (hf > elerr) elerr = hf;\n\t\t\t  }\n\n#ifdef LOCDEBUG\n\t\t\tif (loctestmode)\n\t\t\t  (*testout) << \"error = \" << elerr;\n#endif\n\n\t\t\tcanuse.Elem(ri) ++;\n\n\t\t\tif (elerr < 0.99*minelerr)\n\t\t\t  {\n#ifdef LOCDEBUG\n\t\t\t    if (loctestmode)\n\t\t\t      {\n\t\t\t\t(*testout) << \"rule = \" << rule->Name() << endl;\n\t\t\t\t(*testout) << \"class = \" << tolerance << endl;\n\t\t\t\t(*testout) << \"lpoints: \" << endl;\n\t\t\t\tfor (int i = 1; i <= lpoints.Size(); i++)\n\t\t\t\t  (*testout) << lpoints.Get(i) << endl;\n\t\t\t\t(*testout) << \"llines: \" << endl;\n\t\t\t\tfor (int i = 1; i <= llines.Size(); i++)\n\t\t\t\t  (*testout) << llines.Get(i).I1() << \" \" << llines.Get(i).I2() << endl;\n\n\t\t\t\t(*testout) << \"Freezone: \";\n\t\t\t\tfor (int i = 1; i <= rule -> GetTransFreeZone().Size(); i++)\n\t\t\t\t  (*testout) << rule->GetTransFreeZone().Get(i) << endl;\n\t\t\t      }\n#endif\n\n\t\t\t    minelerr = elerr;\n\t\t\t    found = ri;\n\n\t\t\t    tempnewpoints = lpoints.Range (noldlp, lpoints.Size());\n\t\t\t    tempnewlines = llines.Range (noldll, llines.Size());\n\t\t\t    tempdellines = dellines;\n\t\t\t    tempelements = elements;\n\t\t\t  }\n\n\t\t\tlpoints.SetSize (noldlp);\n\t\t\tllines.SetSize (noldll);\n\t\t\tdellines.SetSize (0);\n\t\t\telements.SetSize (0);\n\t\t\tok = 0;\n\t\t      }\n\t\t  }\n\n\t\tnlok = rule->GetNOldL();\n\n\t\tlused.Set (lmap.Get(nlok), 0);\n\n\t\tfor (int j = 1; j <= 2; j++)\n\t\t  {\n\t\t    int refpi = rule->GetPointNr (nlok, j);\n\t\t    pused.Elem(pmap.Get(refpi))--;\n\n\t\t    if (pused.Get(pmap.Get(refpi)) == 0)\n\t\t      pmap.Set(refpi, 0);\n\t\t  }\n\t      }\n\t  }\n      }\n\n\n    if (found)\n      {\n\tlpoints.Append (tempnewpoints);\n\tllines1.Append (tempnewlines);\n\tdellines.Append (tempdellines);\n\telements.Append (tempelements);\n      }\n\n\n    return found;\n  }\n\n\n\n\n\n}\n"
  },
  {
    "path": "libsrc/meshing/ruler2.hpp",
    "content": "#ifndef FILE_NETRULE\n#define FILE_NETRULE\n\nnamespace netgen\n{\n///\nclass netrule\n{\nprivate:\n  ///\n  typedef struct tf \n  { float f1, f2, f3; }   threefloat;\n  \n  class threeint \n  { \n  public: int i1, i2, i3; \n    threeint() { } \n    threeint(int ai1, int ai2, int ai3) \n    { i1 = ai1; i2 = ai2; i3 = ai3; } \n  };\n\n\n  ///\n  int quality;\n  ///\n  string name;\n  ///\n  NgArray<Point<2>> points;\n  ///\n  NgArray<INDEX_2> lines;\n  ///\n  NgArray<Point<2>> freezone, freezonelimit;\n  ///\n  NgArray<NgArray<Point<2>>> freezone_i;\n  ///\n  NgArray<Point<2>> transfreezone;\n\n  ///\n  NgArray<int> dellines;\n  ///\n  NgArray<Element2d> elements;\n  ///\n  NgArray<threefloat> tolerances, linetolerances;\n  ///\n  NgArray<threeint> orientations;\n  ///\n  DenseMatrix oldutonewu, oldutofreearea, oldutofreearealimit;\n  ///\n  NgArray<DenseMatrix> oldutofreearea_i;\n  ///\n  MatrixFixWidth<3> freesetinequ;\n\n  ///\n  NgArray<Vec<2>> linevecs;\n\n  ///\n  int noldp, noldl;\n  ///\n  float fzminx, fzmaxx, fzminy, fzmaxy;\n\n  /// topological distance of line to base element\n  NgArray<int> lnearness;\n\npublic:\n\n  ///\n  netrule ();\n  ///\n  ~netrule();\n\n  ///\n  int GetNP () const { return points.Size(); }\n  ///\n  int GetNL () const { return lines.Size(); }\n  ///\n  int GetNE () const { return elements.Size(); }\n  ///\n  int GetNOldP () const { return noldp; }\n  ///\n  int GetNOldL () const { return noldl; }\n  ///\n  int GetNDelL () const { return dellines.Size(); }\n  ///\n  int GetNOrientations () const { return orientations.Size(); }\n  ///\n  int GetQuality () const { return quality; }\n  ///\n  int GetLNearness (int li) const { return lnearness.Get(li); }\n\n  ///\n  const Point<2>& GetPoint (int i) const { return points.Get(i); }\n  ///\n  const INDEX_2 & GetLine (int i) const { return lines.Get(i); }\n  ///\n  const Element2d & GetElement (int i) const { return elements.Get(i); }\n  ///\n  const threeint & GetOrientation (int i) const { return orientations.Get(i); }\n  ///\n  int GetDelLine (int i) const { return dellines.Get(i); }\n  ///\n  const NgArray<int> & GetDelLines() const { return dellines; }\n  ///\n  void GetFreeZone (NgArray<Point<2>> & afreearea);\n  ///\n\n  double CalcPointDist (int pi, const Point<2> & p) const\n  {\n    double dx = p[0] - points.Get(pi)[0];\n    double dy = p[1] - points.Get(pi)[1];\n    const threefloat * tfp = &tolerances.Get(pi);\n    return tfp->f1 * dx * dx + tfp->f2 * dx * dy + tfp->f3 * dy * dy;\n  }\n\n  ///\n  float CalcLineError (int li, const Vec<2>& v) const;\n\n  ///\n  void SetFreeZoneTransformation (const Vector & u, int tolclass);\n\n  ///\n  bool IsInFreeZone (const Point<2> & p) const\n  {\n    if (p[0] < fzminx || p[0] > fzmaxx ||\n\tp[1] < fzminy || p[1] > fzmaxy) return 0;\n\n    for (int i = 0; i < transfreezone.Size(); i++)\n      {\n\tif (freesetinequ(i, 0) * p[0] + \n\t    freesetinequ(i, 1) * p[1] +\n\t    freesetinequ(i, 2) > 0) return 0;\n      }\n    return 1;\n  }\n\n  ///\n  int IsLineInFreeZone (const Point<2> & p1, const Point<2> & p2) const\n  {\n    if ( (p1[0] > fzmaxx && p2[0] > fzmaxx) ||\n         (p1[0] < fzminx && p2[0] < fzminx) ||\n         (p1[1] > fzmaxy && p2[1] > fzmaxy) ||\n         (p1[1] < fzminy && p2[1] < fzminy) ) return 0;\n    return IsLineInFreeZone2 (p1, p2);\n  }\n  ///\n  int IsLineInFreeZone2 (const Point<2> & p1, const Point<2> & p2) const;\n  ///\n  int ConvexFreeZone () const;\n  ///\n  const NgArray<Point<2>> & GetTransFreeZone () { return transfreezone; }\n\n  ///\n  int GetPointNr (int ln, int endp) const { return lines.Get(ln).I(endp); }\n\n  ///\n  const DenseMatrix & GetOldUToNewU () const { return oldutonewu; }\n  ///\n  const DenseMatrix & GetOldUToFreeArea () const { return oldutofreearea; }\n  ///\n  const string & Name () const { return name; }\n\n  ///\n  void LoadRule (istream & ist);\n};\n\n\n\n/** Draws 2D rules.\n    Visual testing of 2D meshing rules */\nextern void DrawRules ();\n} // namespace netgen\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/ruler3.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\nnamespace netgen\n{\nextern double minother;\nextern double minwithoutother;\n\n\n  static double TetBadnessFromPoints (const Point3d & p1,\n                                      const Point3d & p2,\n                                      const Point3d & p3,\n                                      const Point3d & p4)\n  {\n    Vec3d v1 = p2 - p1;\n    Vec3d v2 = p3 - p1;\n    Vec3d v3 = p4 - p1;\n\n    double vol = -(Cross(v1, v2) * v3);\n    if (vol < 1e-8) return 1e10;\n\n    double l4 = Dist(p2, p3);\n    double l5 = Dist(p2, p4);\n    double l6 = Dist(p3, p4);\n    double l  = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6;\n\n    return pow(l*l*l/vol, 1.0/3.0) / 12.0;\n  }\n\n  static double CalcElementBadness (const Array<Point3d, PointIndex> & points,\n                                    const Element & elem)\n{\n  if(elem.GetNP() == 4)\n    return TetBadnessFromPoints (points[elem.PNum(1)],\n                                 points[elem.PNum(2)],\n                                 points[elem.PNum(3)],\n                                 points[elem.PNum(4)]);\n  if (elem.GetNP() == 5)\n    {\n      auto p1 = points[elem.PNum(1)];\n      auto p2 = points[elem.PNum(2)];\n      auto p3 = points[elem.PNum(3)];\n      auto p4 = points[elem.PNum(4)];\n      auto p5 = points[elem.PNum(5)];\n      double a1 = TetBadnessFromPoints(p1,p2,p3,p5);\n      double a2 = TetBadnessFromPoints(p1,p3,p4,p5);\n      double splitA = std::max(a1,a2);\n\n      double b1 = TetBadnessFromPoints(p1,p2,p4,p5);\n      double b2 = TetBadnessFromPoints(p2,p3,p4,p5);\n      double splitB = std::max(b1,b2);\n\n      double best = std::min(splitA, splitB);\n\n      return best;\n    }\n  return 0.;\n}\n\n\n\n\n\n\nint Meshing3 :: ApplyRules \n(\n Array<Point3d, PointIndex> & lpoints,     // in: local points, out: old+new local points\n Array<int, PointIndex> & allowpoint,      // in: 2 .. it is allowed to use pointi, 1..will be allowed later, 0..no means\n Array<MiniElement2d> & lfaces,    // in: local faces, out: old+new local faces\n INDEX lfacesplit,\t       // for local faces in outer radius\n INDEX_2_HASHTABLE<int> & connectedpairs,  // connected pairs for prism-meshing\n NgArray<Element> & elements,    // out: new elements\n NgArray<INDEX> & delfaces,      // out: face indices of faces to delete\n int tolerance,                // quality class: 1 best \n double sloppy,                // quality strength\n int rotind1,                  // how to rotate base element\n float & retminerr             // element error \n )\n\n{\n  // static Timer t(\"ruler3 - all\"); RegionTimer reg(t);\n  // static Timer tstart(\"ruler3 - rule start\");   \n  // static Timer tloop(\"ruler3 - rule loop\"); \n\n  // tstart.Start();\n  float err, minerr, teterr, minteterr;\n  char ok, found, hc;\n  // vnetrule * rule;\n  Vector oldu, newu, newu1, newu2, allp;\n  Vec3d ui;\n  Point3d np;\n  const MiniElement2d * locface = NULL;\n  int loktestmode;\n\n\n  NgArray<int, PointIndex::BASE> pused;      // point is already mapped, number of uses\n  NgArrayMem<char,100> fused;                       // face is already mapped\n  NgArrayMem<PointIndex,100> pmap;                  // map of reference point to local point\n  NgArrayMem<bool,100> pfixed;                      // point mapped by face-map\n  NgArrayMem<int,100> fmapi;                        // face in reference is mapped to face nr ...\n  NgArrayMem<int,100> fmapr;                        // face in reference is rotated to map \n  NgArrayMem<Point3d,100> transfreezone;            // transformed free-zone\n  INDEX_2_CLOSED_HASHTABLE<int> ledges(100); // edges in local environment\n  \n  NgArrayMem<Point3d,100> tempnewpoints;\n  NgArray<MiniElement2d> tempnewfaces;\n  NgArrayMem<int,100> tempdelfaces;\n  NgArray<Element> tempelements;\n  NgArrayMem<Box3d,100> triboxes;         // bounding boxes of local faces\n\n  NgArray<int, PointIndex::BASE> pnearness;\n  NgArray<int> fnearness;\n\n  static int cnt = 0;\n  cnt++;\n  \n  delfaces.SetSize (0);\n  elements.SetSize (0);\n\n  // determine topological distance of faces and points to\n  // base element\n\n  pnearness.SetSize (lpoints.Size());\n  fnearness.SetSize (lfacesplit);\n\n  pnearness = INT_MAX/10;\n\n  for (PointIndex pi : lfaces[0].PNums())\n    pnearness[pi] = 0;\n  \n  NgProfiler::RegionTimer reg2(98);\n  \n  NgProfiler::StartTimer (90);\n\n  for (int loop = 0; loop < 2; loop++)\n    {\n\n      for (int i = 0; i < lfacesplit; i++)\n\t{\n\t  const MiniElement2d & hface = lfaces[i];\n\n\t  int minn = INT_MAX-1;\n\t  for (PointIndex pi : hface.PNums())\n\t    {\n\t      int hi = pnearness[pi];\n\t      if (hi < minn) minn = hi;\n\t    }\n\t  if (minn < INT_MAX/10)\n\t    for (PointIndex pi : hface.PNums())\n\t      if (pnearness[pi] > minn+1)\n\t\tpnearness[pi] = minn+1;\n\t}\n\n      for (int i = 1; i <= connectedpairs.GetNBags(); i++)\n\tfor (int j = 1; j <= connectedpairs.GetBagSize(i); j++)\n\t  {\n\t    INDEX_2 edge;\n\t    int val;\n\t    connectedpairs.GetData (i, j, edge, val);\n\n\t    if (pnearness[edge.I1()] > pnearness[edge.I2()] + 1)\n\t      pnearness[edge.I1()] = pnearness[edge.I2()] + 1;\n\n\t    if (pnearness[edge.I2()] > pnearness[edge.I1()] + 1)\n\t      pnearness[edge.I2()] = pnearness[edge.I1()] + 1;\n\t  }\n    }\n\n  for (int i : fnearness.Range())\n    {\n      int sum = 0;\n      for (PointIndex pi : lfaces[i].PNums())\n        sum += pnearness[pi];\n      fnearness[i] = sum;\n    }\n\n  \n  NgProfiler::StopTimer (90);\n  NgProfiler::StartTimer (91);\n\n  // find bounding boxes of faces\n\n  triboxes.SetSize (lfaces.Size());\n  // for (int i = 0; i < lfaces.Size(); i++)\n  for (auto i : lfaces.Range())\n    {\n      const MiniElement2d & face = lfaces[i];\n      triboxes[i].SetPoint (lpoints[face[0]]);\n      for (int j = 1; j < face.GetNP(); j++)\n\ttriboxes[i].AddPoint (lpoints[face[j]]);\n    }\n\n  NgProfiler::StopTimer (91);\n  NgProfiler::StartTimer (92);\n\n  \n  bool useedges = false;\n  for (int ri = 0; ri < rules.Size(); ri++)\n    if (rules[ri]->GetNEd()) useedges = true;\n\n  if (useedges)\n    {\n      ledges.SetSize (5 * lfacesplit);\n      \n      for (int j = 0; j < lfacesplit; j++)\n\t// if (fnearness[j] <= 5) \n\t  {\n\t    const MiniElement2d & face = lfaces[j];\n\t    int newp, oldp;\n\t    \n\t    newp = face[face.GetNP()-1];\n\t    for (int k = 0; k < face.GetNP(); k++)\n\t      {\n\t\toldp = newp;\n\t\tnewp = face[k];\n\t\tledges.Set (INDEX_2::Sort(oldp, newp), 1);\n\t      }\n\t  }\n    }\n\n  NgProfiler::StopTimer (92);\n\n  NgProfiler::RegionTimer reg3(99);\n\n  pused.SetSize (lpoints.Size());\n  fused.SetSize (lfaces.Size());\n\n  found = 0;\n  minerr = tolfak * tolerance * tolerance;\n  minteterr = sloppy * tolerance;\n\n  if (testmode)\n    (*testout) << \"cnt = \" << cnt << \" class = \" << tolerance << endl;\n\n\n\n  // impossible, if no rule can be applied at any tolerance class\n  bool impossible = 1;\n\n\n  // check each rule:\n  // tstart.Stop();\n  // tloop.Start();\n  for (int rim = 0; rim < rules.Size(); rim++)\n    {\n      int base = (lfaces[0].GetNP() == 3) ? 100 : 200;\n      NgProfiler::RegionTimer regx1(base);\n      NgProfiler::RegionTimer regx(base+rim+1);\n\n      // sprintf (problems.Elem(ri), \"\");\n      // *problems.Elem(ri) = '\\0';\n      problems[rim] = \"\";\n\n      vnetrule * rule = rules[rim].get();\n      \n      if (rule->GetNP(1) != lfaces[0].GetNP())\n\tcontinue;\n\n      if (rule->GetQuality() > tolerance)\n\t{\n\t  if (rule->GetQuality() < 100) impossible = 0;\n\n\t  if (testmode)\n\t    problems[rim] = \"Quality not ok\";\n\t  continue;\n\t}\n      \n      if (testmode)\n\tproblems[rim] = \"no mapping found\";\n      \n      loktestmode = testmode || rule->TestFlag ('t') || tolerance > 5;\n\n      if (loktestmode)\n\t(*testout) << \"Rule \" << rim+1 << \" = \" << rule->Name() << endl;\n      \n      pmap.SetSize (rule->GetNP());\n      fmapi.SetSize (rule->GetNF());\n      fmapr.SetSize (rule->GetNF());\n      \n      fused = 0;\n      pused = 0;\n      for (auto & p : pmap) p.Invalidate();\n      fmapi = 0;\n\n      for (int i : fmapr.Range())\n        fmapr[i] = rule->GetNP(i+1);\n      \n      fused[0] = 1;\n      fmapi[0] = 1;\n      fmapr[0] = rotind1;\n\n      for (int j = 1; j <= lfaces[0].GetNP(); j++)\n\t{\n\t  PointIndex locpi = lfaces[0].PNumMod (j+rotind1);\n\t  pmap.Set (rule->GetPointNr (1, j), locpi);\n\t  pused[locpi]++;\n\t}\n\n      /*\n\tmap all faces\n\tnfok .. first nfok-1 faces are mapped properly\n\t*/\n\n      int nfok = 2;\n      NgProfiler::RegionTimer regfa(300);\n      NgProfiler::RegionTimer regx2(base+50+rim+1);\n      while (nfok >= 2)\n\t{\n\t  \n\t  if (nfok <= rule->GetNOldF())\n\t    {\n\t      // not all faces mapped\n\n\t      ok = 0;\n\t      int locfi = fmapi.Get(nfok);\n\t      int locfr = fmapr.Get(nfok);\n\n\t      int actfnp = rule->GetNP(nfok);\n\n\t      while (!ok)\n\t\t{\n\t\t  locfr++;\n\t\t  if (locfr == actfnp + 1)\n\t\t    {\n\t\t      locfr = 1;\n\t\t      locfi++;\n\t\t      if (locfi > lfacesplit) break;\n\t\t    }\n\t\t  \n\t\t  \n\t\t  if (fnearness.Get(locfi) > rule->GetFNearness (nfok) ||\n\t\t      fused.Get(locfi) ||\n\t\t      actfnp != lfaces[locfi-1].GetNP() )\n\t\t    {\n\t\t      // face not feasible in any rotation\n\n\t\t      locfr = actfnp;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      \n\t\t      ok = 1;\n\t\t      \n\t\t      locface = &lfaces[locfi-1];\n\n\t\t      \n\t\t      // reference point already mapped differently ?\n\t\t      for (int j = 1; j <= actfnp && ok; j++)\n\t\t\t{\n\t\t\t  PointIndex locpi = pmap.Get(rule->GetPointNr (nfok, j));\n\t\t\t  if (locpi.IsValid() && locpi != locface->PNumMod(j+locfr))\n\t\t\t    ok = 0;\n\t\t\t}\n\t\t      \n\t\t      // local point already used or point outside tolerance ?\n\t\t      for (int j = 1; j <= actfnp && ok; j++)\n\t\t\t{\n\t\t\t  int refpi = rule->GetPointNr (nfok, j);\n\t\t\t  \n\t\t\t  if (!pmap.Get(refpi).IsValid())\n\t\t\t    {\n\t\t\t      PointIndex locpi = locface->PNumMod (j + locfr);\n\n\t\t\t      if (pused[locpi])\n\t\t\t\tok = 0;\n\t\t\t      else\n\t\t\t\t{\n\t\t\t\t  const Point3d & lp = lpoints[locpi];\n\t\t\t\t  const Point3d & rp = rule->GetPoint(refpi);\n\n\t\t\t\t  if ( Dist2 (lp, rp) * rule->PointDistFactor(refpi) > minerr)\n\t\t\t\t    {\n\t\t\t\t      impossible = 0;\n\t\t\t\t      ok = 0;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t      \n\t      \n\t      if (ok)\n\t\t{\n\t\t  // map face nfok\n\n\t\t  fmapi.Set (nfok, locfi);\n\t\t  fmapr.Set (nfok, locfr);\n\t\t  fused.Set (locfi, 1);\n\t\t  \n\t\t  for (int j = 1; j <= rule->GetNP (nfok); j++)\n\t\t    {\n\t\t      PointIndex locpi = locface->PNumMod(j+locfr);\n\t\t      \n\t\t      if (rule->GetPointNr (nfok, j) < IndexBASE<PointIndex>()+3 &&\n\t\t\t  pmap.Get(rule->GetPointNr(nfok, j)) != locpi)\n\t\t\t(*testout) << \"change face1 point, mark1\" << endl;\n\t\t      \n\t\t      pmap.Set(rule->GetPointNr (nfok, j), locpi);\n\t\t      pused[locpi]++;\n\t\t    }\n\t\t  \n\t\t  nfok++;\n\t\t}\n\t      else\n\t\t{\n\t\t  // backtrack one face\n\t\t  fmapi.Set (nfok, 0);\n\t\t  fmapr.Set (nfok, rule->GetNP(nfok));\n\t\t  nfok--;\n\t\t  \n\t\t  fused.Set (fmapi.Get(nfok), 0);\n\t\t  for (int j = 1; j <= rule->GetNP (nfok); j++)\n\t\t    {\n\t\t      int refpi = rule->GetPointNr (nfok, j);\n\t\t      pused[pmap.Get(refpi)]--;\n                      \n\t\t      if (pused[pmap.Get(refpi)] == 0)\n\t\t\t{\n\t\t\t  // pmap.Set(refpi, 0);\n                          pmap.Elem(refpi).Invalidate();\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t  \n\t  else\n\t    \n\t    { \n\t      NgProfiler::RegionTimer regfb(301);\n\n\t      // all faces are mapped\n\t      // now map all isolated points:\n\t      \n\t      if (loktestmode)\n\t\t{\n\t\t  (*testout) << \"Faces Ok\" << endl;\n\t\t  problems[rim] = \"Faces Ok\";\n\t\t}\n\n\t      int npok = 1;\n\t      int incnpok = 1;\n\t      \n\t      pfixed.SetSize (pmap.Size());\n              /*\n\t      for (int i = 1; i <= pmap.Size(); i++)\n\t\tpfixed.Set(i, (pmap.Get(i) != 0) );\n              */\n              for (int i : pmap.Range())\n                pfixed[i] = pmap[i].IsValid();\n                  \n\t      while (npok >= 1)\n\t\t{\n\t\t  \n\t\t  if (npok <= rule->GetNOldP())\n\t\t    {\n\t\t      \n\t\t      if (pfixed.Get(npok))\n\t\t\t\n\t\t\t{\n\t\t\t  if (incnpok)\n\t\t\t    npok++;\n\t\t\t  else\n\t\t\t    npok--;\n\t\t\t}\n\t\t      \n\t\t      else\n\t\t\t\n\t\t\t{\n\t\t\t  PointIndex locpi = pmap.Elem(npok);\n\t\t\t  ok = 0;\n\t\t\t  \n\t\t\t  if (locpi.IsValid())\n\t\t\t    pused[locpi]--;\n\t\t\t  \n\t\t\t  while (!ok && locpi < lpoints.Size()-1+IndexBASE<PointIndex>())\n\t\t\t    {\n\t\t\t      ok = 1;\n\t\t\t      locpi++;\n\t\t\t      \n\t\t\t      if (pused[locpi] || \n\t\t\t\t  pnearness[locpi] > rule->GetPNearness(npok))\n\t\t\t\t{\n\t\t\t\t  ok = 0;\n\t\t\t\t}\n\t\t\t      else if (allowpoint[locpi] != 2)\n\t\t\t\t{\n\t\t\t\t  ok = 0;\n\t\t\t\t  if (allowpoint[locpi] == 1)\n\t\t\t\t    impossible = 0;\n\t\t\t\t}\n\t\t\t      else\n\t\t\t\t{\n\t\t\t\t  const Point3d & lp = lpoints[locpi];\n\t\t\t\t  const Point3d & rp = rule->GetPoint(npok);\n\n\t\t\t\t  if ( Dist2 (lp, rp) * rule->PointDistFactor(npok) > minerr)\n\t\t\t\t    {\n\t\t\t\t      ok = 0;\n\t\t\t\t      impossible = 0;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\n\t\t\t  \n\t\t\t  \n\t\t\t  if (ok)\n\t\t\t    {\n\t\t\t      pmap.Set (npok, locpi);\n\t\t\t      \n\t\t\t      if (npok <= 3)\n\t\t\t\t(*testout) << \"set face1 point, mark3\" << endl;\n\t\t\t      \n\t\t\t      pused[locpi]++;\n\t\t\t      npok++;\n\t\t\t      incnpok = 1;\n\t\t\t    }\n\t\t\t  \n\t\t\t  else\n\t\t\t    \n\t\t\t    {\n\t\t\t      // pmap.Set (npok, 0);\n                              pmap.Elem(npok).Invalidate();\n\t\t\t      \n\t\t\t      if (npok <= 3)\n\t\t\t\t(*testout) << \"set face1 point, mark4\" << endl;\n\t\t\t      \n\t\t\t      npok--;\n\t\t\t      incnpok = 0;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t  \n\t\t  else\n\t\t    \n\t\t    {\n\t\t      NgProfiler::RegionTimer regfa2(302);\t\t      \n\n\t\t      // all points are mapped\n\t\t      \n\t\t      if (loktestmode)\n\t\t\t{\n\t\t\t  (*testout) << \"Mapping found!!: Rule \" << rule->Name() << endl;\n\t\t\t  for (auto pi : pmap)\n\t\t\t    (*testout) << pi << \" \";\n\t\t\t  (*testout) << endl;\n\t\t\t  problems[rim] = \"mapping found\";\n\t\t\t  (*testout) << rule->GetNP(1) << \" = \" << lfaces[0].GetNP() << endl;\n\t\t\t}\n\t\t      \n\t\t      ok = 1;\n\t\t      \n\t\t      \n\t\t      // check mapedges:\n\t\t      for (int i = 1; i <= rule->GetNEd(); i++)\n\t\t\t{\n\t\t\t  INDEX_2 in2(pmap.Get(rule->GetEdge(i).i1),\n\t\t\t\t      pmap.Get(rule->GetEdge(i).i2));\n\t\t\t  in2.Sort();\n\t\t\t  if (!ledges.Used (in2)) ok = 0;\n\t\t\t}\n\n\n\t\t      // check prism edges:\n\t\t      for (int i = 1; i <= rule->GetNE(); i++)\n\t\t\t{\n\t\t\t  const Element & el = rule->GetElement (i);\n\t\t\t  if (el.GetType() == PRISM) \n\t\t\t    { \n\t\t\t      for (int j = 1; j <= 3; j++)\n\t\t\t\t{\n\t\t\t\t  INDEX_2 in2(pmap.Get(el.PNum(j)),\n\t\t\t\t\t      pmap.Get(el.PNum(j+3)));      \n\t\t\t\t  in2.Sort();\n\t\t\t\t  if (!connectedpairs.Used (in2)) ok = 0;\n\t\t\t\t}\n\t\t\t    }\n\t\t\t  if (el.GetType() == PYRAMID) \n\t\t\t    { \n\t\t\t      if (loktestmode)\n\t\t\t\t(*testout) << \"map pyramid, rule = \" << rule->Name() << endl;\n\t\t\t      for (int j = 1; j <= 2; j++)\n\t\t\t\t{\n\t\t\t\t  INDEX_2 in2;\n\t\t\t\t  if (j == 1)\n\t\t\t\t    {\n\t\t\t\t      in2.I1() = pmap.Get(el.PNum(2));\n\t\t\t\t      in2.I2() = pmap.Get(el.PNum(3));\n\t\t\t\t    }\n\t\t\t\t  else\n\t\t\t\t    {\n\t\t\t\t      in2.I1() = pmap.Get(el.PNum(1));\n\t\t\t\t      in2.I2() = pmap.Get(el.PNum(4));\n\t\t\t\t    }\n\t\t\t\t  in2.Sort();\n\t\t\t\t  if (!connectedpairs.Used (in2)) \n\t\t\t\t    {\n\t\t\t\t      ok = 0;\n\t\t\t\t      if (loktestmode)\n\t\t\t\t\t(*testout) << \"no pair\" << endl;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\n\n\t\t\t}\n\t\t      \n\n\t\t      \n\t\t      for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++)\n\t\t\tfmapi.Set(i, 0);\n\t\t      \n\n\t\t      if (ok)\n                        foundmap[rim]++;\n\t\t      \n\n\n\t\t      // deviation of existing points\n\n\t\t      oldu.SetSize (3 * rule->GetNOldP());\n\t\t      newu.SetSize (3 * (rule->GetNP() - rule->GetNOldP()));\n\t\t      allp.SetSize (3 * rule->GetNP());\n\t\t      \n\t\t      for (int i = 1; i <= rule->GetNOldP(); i++)\n\t\t\t{\n\t\t\t  const Point3d & lp = lpoints[pmap.Get(i)];\n\t\t\t  const Point3d & rp = rule->GetPoint(i);\n\t\t\t  oldu (3*i-3) = lp.X()-rp.X();\n                          oldu (3*i-2) = lp.Y()-rp.Y();\n\t\t\t  oldu (3*i-1) = lp.Z()-rp.Z();\n\t\t\t  \n\t\t\t  allp (3*i-3) = lp.X();\n                          allp (3*i-2) = lp.Y();\n                          allp (3*i-1) = lp.Z();\n\t\t\t}\n\n\t\t      if (rule->GetNP() > rule->GetNOldP())\n\t\t\t{\n\t\t\t  newu.SetSize (rule->GetOldUToNewU().Height());\n\t\t\t  rule->GetOldUToNewU().Mult (oldu, newu);\n\t\t\t}\n\n\t\t      //\t\t      int idiff = 3 * (rule->GetNP()-rule->GetNOldP());\n\t\t      int idiff = 3 * rule->GetNOldP();\n\t\t      for (int i = rule->GetNOldP()+1; i <= rule->GetNP(); i++)\n\t\t\t{\n\t\t\t  const Point3d & rp = rule->GetPoint(i);\n\t\t\t  allp (3*i-3) = rp.X() + newu(3*i-3 - idiff);\n                          allp (3*i-2) = rp.Y() + newu(3*i-2 - idiff);\n                          allp (3*i-1) = rp.Z() + newu(3*i-1 - idiff);\n\t\t\t}\n\t\t      \n\t\t      rule->SetFreeZoneTransformation (allp, \n\t\t\t\t\t\t       tolerance + int(sloppy));\n\n\t\t      if (!rule->ConvexFreeZone())\n\t\t\t{\n\t\t\t  ok = 0;\n\t\t\t  problems[rim] = \"Freezone not convex\";\n\n\t\t\t  if (loktestmode)\n\t\t\t    (*testout) << \"Freezone not convex\" << endl;\n\t\t\t}\n\n\t\t      if (loktestmode)\n\t\t\t{\n\t\t\t  const NgArray<Point3d> & fz = rule->GetTransFreeZone();\n\t\t\t  (*testout) << \"Freezone: \" << endl;\n\t\t\t  for (int i = 1; i <= fz.Size(); i++)\n\t\t\t    (*testout) << fz.Get(i) << endl;\n\t\t\t}\n\t\t      \n\n\t\t      // check freezone:\n\t\t      \n\t\t      // for (int i = 1; i <= lpoints.Size(); i++)\n                      for (auto i : lpoints.Range())\n\t\t\t{\n\t\t\t  if ( !pused[i] )\n\t\t\t    {\n\t\t\t      const Point3d & lp = lpoints[i];\n\n\t\t\t      if (rule->fzbox.IsIn (lp))\n\t\t\t\t{\n\t\t\t\t  if (rule->IsInFreeZone(lp))\n\t\t\t\t    {\n\t\t\t\t      if (loktestmode)\n\t\t\t\t\t{\n\t\t\t\t\t  (*testout) << \"Point \" << i \n\t\t\t\t\t\t     << \" in Freezone\" << endl;\n\t\t\t\t\t  problems[rim] = \"locpoint \" + ToString(i) + \" in Freezone\";\n\t\t\t\t\t}\n\t\t\t\t      ok = 0;\n\t\t\t\t      break;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\n\t\t\t}\n\n\t\t      for (int i = 1; i <= lfaces.Size() && ok; i++)\n\t\t\t{\n\t\t\t  NgArrayMem<int, 10> lpi(4);\n\n\t\t\t  if (!fused.Get(i))\n\t\t\t    { \n\t\t\t      int triin;\n\t\t\t      const MiniElement2d & lfacei = lfaces[i-1];\n\n\t\t\t      if (!triboxes.Elem(i).Intersect (rule->fzbox))\n\t\t\t\ttriin = 0;\n\t\t\t      else\n\t\t\t\t{\n\t\t\t\t  int li, lj;\n\t\t\t\t  for (li = 1; li <= lfacei.GetNP(); li++)\n\t\t\t\t    {\n\t\t\t\t      int lpii = 0;\n\t\t\t\t      PointIndex pi = lfacei.PNum(li);\n\t\t\t\t      for (lj = 1; lj <= rule->GetNOldP(); lj++)\n\t\t\t\t\tif (pmap.Get(lj) == pi)\n\t\t\t\t\t  lpii = lj;\n\t\t\t\t      lpi.Elem(li) = lpii;\n\t\t\t\t    }\n\n\n\t\t\t\t  if (lfacei.GetNP() == 3)\n\t\t\t\t    {\n\t\t\t\t      triin = rule->IsTriangleInFreeZone \n\t\t\t\t\t(\n\t\t\t\t\t lpoints[lfacei.PNum(1)],\n\t\t\t\t\t lpoints[lfacei.PNum(2)],\n\t\t\t\t\t lpoints[lfacei.PNum(3)], lpi, 1\n\t\t\t\t\t );\n\t\t\t\t    }\n\t\t\t\t  else\n\t\t\t\t    {\n\t\t\t\t      triin = rule->IsQuadInFreeZone \n\t\t\t\t\t(\n\t\t\t\t\t lpoints[lfacei.PNum(1)],\n\t\t\t\t\t lpoints[lfacei.PNum(2)],\n\t\t\t\t\t lpoints[lfacei.PNum(3)], \n\t\t\t\t\t lpoints[lfacei.PNum(4)], \n\t\t\t\t\t lpi, 1\n\t\t\t\t\t );\n\t\t\t\t    }\n\t\t\t\t}\n\n\n\t\t\t      if (triin == -1)\n\t\t\t\t{\n\t\t\t\t  ok = 0;\n\t\t\t\t}\n\t\t\t      \n\t\t\t      if (triin == 1)\n\t\t\t\t{\n#ifdef TEST_JS\n\t\t\t\t  ok = 0;\n\n\t\t\t\t  if (loktestmode)\n\t\t\t\t    {\n\t\t\t\t      (*testout) << \"El with \" << lfaces[i-1].GetNP() << \" points in freezone: \"\n\t\t\t\t\t\t << lfaces[i-1].PNum(1) << \" - \" \n\t\t\t\t\t\t << lfaces[i-1].PNum(2) << \" - \"\n\t\t\t\t\t\t << lfaces[i-1].PNum(3) << \" - \"\n\t\t\t\t\t\t << lfaces[i-1].PNum(4) << endl;\n\t\t\t\t      for (int lj = 1; lj <= lfaces[i-1].GetNP(); lj++)\n\t\t\t\t\t(*testout) << lpoints[lfaces[i-1].PNum(lj)] << \" \";\n\n\t\t\t\t      (*testout) << endl;\n\n\t\t\t\t      sprintf (problems.Elem(ri), \"triangle (%d, %d, %d) in Freezone\",\n\t\t\t\t\t       lfaces[i-1].PNum(1), lfaces[i-1].PNum(2),\n\t\t\t\t\t       lfaces[i-1].PNum(3));\n\t\t\t\t    }\n#else\n\t\t\t\t  if (loktestmode)\n\t\t\t\t    {\n\t\t\t\t      if (lfacei.GetNP() == 3)\n\t\t\t\t\t{\n\t\t\t\t\t  (*testout) << \"Triangle in freezone: \"\n\t\t\t\t\t\t     << lfacei.PNum(1) << \" - \" \n\t\t\t\t\t\t     << lfacei.PNum(2) << \" - \"\n\t\t\t\t\t\t     << lfacei.PNum(3) \n\t\t\t\t\t\t     << \", or \"\n\t\t\t\t\t\t     << lpoints[lfacei.PNum(1)] << \" - \" \n\t\t\t\t\t\t     << lpoints[lfacei.PNum(2)] << \" - \"\n\t\t\t\t\t\t     << lpoints[lfacei.PNum(3)] \n\t\t\t\t\t\t     << endl;\n\t\t\t\t\t  (*testout) << \"lpi = \" << lpi.Get(1) << \", \" \n\t\t\t\t\t\t     << lpi.Get(2) << \", \" << lpi.Get(3) << endl;\n\t\t\t\t\t}\n\t\t\t\t      else\n\t\t\t\t\t  (*testout) << \"Quad in freezone: \"\n\t\t\t\t\t\t     << lfacei.PNum(1) << \" - \" \n\t\t\t\t\t\t     << lfacei.PNum(2) << \" - \"\n\t\t\t\t\t\t     << lfacei.PNum(3) << \" - \"\n\t\t\t\t\t\t     << lfacei.PNum(4) \n\t\t\t\t\t\t     << \", or \"\n\t\t\t\t\t\t     << lpoints[lfacei.PNum(1)] << \" - \" \n\t\t\t\t\t\t     << lpoints[lfacei.PNum(2)] << \" - \"\n\t\t\t\t\t\t     << lpoints[lfacei.PNum(3)] << \" - \"\n\t\t\t\t\t\t     << lpoints[lfacei.PNum(4)] \n\t\t\t\t\t\t     << endl;\n\n\t\t\t\t      problems[rim] = \"triangle (\"+ToString(lfaces[i-1].PNum(1))+\", \"\n                                        + ToString(lfaces[i-1].PNum(2)) + \", \"\n                                        + ToString(lfaces[i-1].PNum(3)) + \") in Freezone\";\n\t\t\t\t    }\t\n\n\t\t\t\t  hc = 0;\n\t\t\t\t  for (int k = rule->GetNOldF() + 1; k <= rule->GetNF(); k++)\n\t\t\t\t    {\n\t\t\t\t      if (rule->GetPointNr(k, 1) < IndexBASE<PointIndex>()+rule->GetNOldP() &&\n\t\t\t\t\t  rule->GetPointNr(k, 2) < IndexBASE<PointIndex>()+rule->GetNOldP() &&\n\t\t\t\t\t  rule->GetPointNr(k, 3) < IndexBASE<PointIndex>()+rule->GetNOldP())\n\t\t\t\t\t{\n\t\t\t\t\t  for (int j = 1; j <= 3; j++)\n\t\t\t\t\t    if (lfaces[i-1].PNumMod(j  ) == pmap.Get(rule->GetPointNr(k, 1)) &&\n\t\t\t\t\t\tlfaces[i-1].PNumMod(j+1) == pmap.Get(rule->GetPointNr(k, 3)) &&\n\t\t\t\t\t\tlfaces[i-1].PNumMod(j+2) == pmap.Get(rule->GetPointNr(k, 2)))\n\t\t\t\t\t      {\n\t\t\t\t\t\tfmapi.Elem(k) = i;\n\t\t\t\t\t\thc = 1;\n\n\t\t\t\t\t\t\n // \t\t\t\t\t\t(*testout) << \"found from other side: \" \n//  \t\t\t\t\t\t\t   << rule->Name() \n//  \t\t\t\t\t\t\t   << \" ( \" << pmap.Get (rule->GetPointNr(k, 1))\n//  \t\t\t\t\t\t\t   << \" - \" << pmap.Get (rule->GetPointNr(k, 2))\n//  \t\t\t\t\t\t\t   << \" - \" << pmap.Get (rule->GetPointNr(k, 3)) << \" ) \"\n//  \t\t\t\t\t\t\t   << endl;\n\n\t\t\t\t\t\tproblems[rim] = \"other\";\n\t\t\t\t\t      }\n\t\t\t\t\t}\n\t\t\t\t    }\n\t\t\t\t  \n\t\t\t\t  if (!hc)\n\t\t\t\t    {\n\t\t\t\t      if (loktestmode)\n\t\t\t\t\t{\n\t\t\t\t\t  (*testout) << \"Triangle in freezone: \"\n\t\t\t\t\t\t     << lfaces[i-1].PNum(1) << \" - \" \n\t\t\t\t\t\t     << lfaces[i-1].PNum(2) << \" - \"\n\t\t\t\t\t\t     << lfaces[i-1].PNum(3) << endl;\n\n                                          /*\n\t\t\t\t\t  snprintf (problems.Elem(ri), 255, \"triangle (%d, %d, %d) in Freezone\",\n\t\t\t\t\t\t   int (lfaces[i-1].PNum(1)), \n\t\t\t\t\t\t   int (lfaces[i-1].PNum(2)),\n\t\t\t\t\t\t   int (lfaces[i-1].PNum(3)));\n                                          */\n                                          problems[rim] = \"triangle (\"\n                                            + ToString(lfaces[i-1].PNum(1))+\", \"\n                                            + ToString(lfaces[i-1].PNum(2)) + \", \"\n                                            + ToString(lfaces[i-1].PNum(3)) + \") in Freezone\";\n                                          \n\t\t\t\t\t}\n\t\t\t\t      ok = 0;\n\t\t\t\t    }\n#endif\n\t\t\t\t}\n\t\t\t    }\n\t\t\t   \n\t\t\t}\n\n\t\t      \n\t\t      if (ok)\n\t\t\t{\n\t\t\t  err = 0;\n\t\t\t  for (int i = 1; i <= rule->GetNOldP(); i++)\n\t\t\t    {\n\t\t\t      double hf = rule->CalcPointDist (i, lpoints[pmap.Get(i)]);\n\t\t\t      if (hf > err) err = hf;\n\t\t\t    }\n\t\t\t  \n\t\t\t  \n\t\t\t  if (loktestmode)\n\t\t\t    {\n\t\t\t      (*testout) << \"Rule ok\" << endl;\n\t\t\t      problems[rim] = \"Rule ok, err = \"+ToString(err);\n\t\t\t    }\n\n\n\t\t\t  //\t\t\t  newu = rule->GetOldUToNewU() * oldu;\n\n\t\t\t  // set new points:\n                          int oldnp = rule->GetNOldP();\n\t\t\t  int noldlp = lpoints.Size();\n\t\t\t  int noldlf = lfaces.Size();\n\t\t\t  \n\t\t\t  for (int i = oldnp + 1; i <= rule->GetNP(); i++)\n\t\t\t    {\n\t\t\t      np = rule->GetPoint(i);\n\t\t\t      np.X() += newu (3 * (i-oldnp) - 3);\n\t\t\t      np.Y() += newu (3 * (i-oldnp) - 2);\n\t\t\t      np.Z() += newu (3 * (i-oldnp) - 1);\n\t\t\t      lpoints.Append (np);\n                              pmap.Elem(i) = lpoints.Size()-1+PointIndex::BASE;\n\t\t\t    }\n\t\t\t  \n\t\t\t  // Set new Faces:\n\t\t\t  \n\t\t\t  for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++)\n\t\t\t    if (!fmapi.Get(i))\n\t\t\t      {\n\t\t\t\tMiniElement2d nface(rule->GetNP(i));\n\t\t\t\tfor (int j = 1; j <= nface.GetNP(); j++)\n\t\t\t\t  nface.PNum(j) = pmap.Get(rule->GetPointNr (i, j));\n\t\t\t\t\n\t\t\t\tlfaces.Append (nface);\n\t\t\t      }\n\t\t\t  \n\t\t\t  // Delete old Faces:\n\n\t\t\t  for (int i = 1; i <= rule->GetNDelF(); i++)\n\t\t\t    delfaces.Append (fmapi.Get(rule->GetDelFace(i)));\n\t\t\t  for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++)\n\t\t\t    if (fmapi.Get(i))\n\t\t\t      {\n\t\t\t\tdelfaces.Append (fmapi.Get(i));\n\t\t\t\tfmapi.Elem(i) = 0;\n\t\t\t      }\n\t\t\t  \n\n\t\t\t  // check orientation\n\t\t\t  for (int i = 1; i <= rule->GetNO() && ok; i++)\n\t\t\t    {\n\t\t\t      const fourint * fouri;\n\t\t\t      \n\t\t\t      fouri = &rule->GetOrientation(i);\n\t\t\t      Vec3d v1 (lpoints[pmap.Get(fouri->i1)], \n\t\t\t\t\tlpoints[pmap.Get(fouri->i2)]);\n\t\t\t      Vec3d v2 (lpoints[pmap.Get(fouri->i1)], \n\t\t\t\t\tlpoints[pmap.Get(fouri->i3)]);\n\t\t\t      Vec3d v3 (lpoints[pmap.Get(fouri->i1)], \n\t\t\t\t\tlpoints[pmap.Get(fouri->i4)]);\n\n\t\t\t      Vec3d n;\n\t\t\t      Cross (v1, v2, n);\n\t\t\t      //if (n * v3 >= -1e-7*n.Length()*v3.Length()) // OR -1e-7???\n\t\t\t      if (n * v3 >= -1e-9)\n\t\t\t\t{\n\t\t\t\t  if (loktestmode)\n\t\t\t\t    {\n\t\t\t\t      problems[rim] = \"Orientation wrong\";\n\t\t\t\t      (*testout) << \"Orientation wrong (\"<< n*v3 << \")\" << endl;\n\t\t\t\t    }\n\t\t\t\t  ok = 0;\n\t\t\t\t}\n\t\t\t    }\n\n\t\t\t  \n\n\t\t\t  // new points in free-zone ?\n\t\t\t  for (int i = rule->GetNOldP() + 1; i <= rule->GetNP() && ok; i++)\n\t\t\t    if (!rule->IsInFreeZone (lpoints[pmap.Get(i)]))\n\t\t\t      {\n\t\t\t\tif (loktestmode)\n\t\t\t\t  {\n\t\t\t\t    (*testout) << \"Newpoint \" << lpoints[pmap.Get(i)]\n\t\t\t\t\t       << \" outside convex hull\" << endl;\n\t\t\t\t    problems[rim] = \"newpoint outside convex hull\";\n\t\t\t\t  }\n\t\t\t\tok = 0;\n\t\t\t\t\n\t\t\t      }\n\t\t\t  \n\t\t\t  // insert new elements\n\t\t\t  \n\t\t\t  for (int i = 1; i <= rule->GetNE(); i++)\n\t\t\t    {\n\t\t\t      elements.Append (rule->GetElement(i));\n\t\t\t      for (int j = 1; j <= elements.Get(i).NP(); j++)\n\t\t\t\telements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j));\n\t\t\t    }\n\t\t\t  \n\n\t\t\t  // Calculate Element badness\n\t\t\t  \n\t\t\t  teterr = 0;\n\t\t\t  for (auto i : elements.Range())\n\t\t\t    {\n\t\t\t      double hf = CalcElementBadness (lpoints, elements[i]);\n\t\t\t      if (hf > teterr) teterr = hf;\n\t\t\t    }\n\n\t\t\t  /*\n\t\t\t    // keine gute Erfahrung am 25.1.2000, js\n\t\t\t  if (ok && teterr < 100 &&\n\t\t\t      (rule->TestFlag('b') || tolerance > 10) )\n\t\t\t    {\n\t\t\t      (*mycout) << \"Reset teterr \" \n\t\t\t\t   << rule->Name() \n\t\t\t\t   << \" err = \" << teterr \n\t\t\t\t   << endl;\n\t\t\t      teterr = 1;\n\t\t\t    }\n\t\t\t  */\n\n\t\t\t  // compare edgelength\n\t\t\t  if (rule->TestFlag('l'))\n\t\t\t    {\n\t\t\t      double oldlen = 0;\n\t\t\t      double newlen = 0;\n\n\t\t\t      for (int i = 1; i <= rule->GetNDelF(); i++)\n\t\t\t\t{\n\t\t\t\t  const Element2d & face = \n\t\t\t\t    rule->GetFace (rule->GetDelFace(i));\n\t\t\t\t  for (int j = 1; j <= 3; j++)\n\t\t\t\t    {\n\t\t\t\t      const Point3d & p1 =\n\t\t\t\t\tlpoints[pmap.Get(face.PNumMod(j))];\n\t\t\t\t      const Point3d & p2 =\n\t\t\t\t\tlpoints[pmap.Get(face.PNumMod(j+1))];\n\t\t\t\t      oldlen += Dist(p1, p2);\n\t\t\t\t    }\n\t\t\t\t}\n\n\t\t\t      for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++)\n\t\t\t\t{\n\t\t\t\t  const Element2d & face = rule->GetFace (i);\n\t\t\t\t  for (int j = 1; j <= 3; j++)\n\t\t\t\t    {\n\t\t\t\t      const Point3d & p1 =\n\t\t\t\t\tlpoints[pmap.Get(face.PNumMod(j))];\n\t\t\t\t      const Point3d & p2 =\n\t\t\t\t\tlpoints[pmap.Get(face.PNumMod(j+1))];\n\t\t\t\t      newlen += Dist(p1, p2);\n\t\t\t\t    }\n\t\t\t\t}\n\n\t\t\t      if (oldlen < newlen) \n\t\t\t\t{\n\t\t\t\t  ok = 0;\n\t\t\t\t  if (loktestmode)\n\t\t\t\t    problems[rim] = \"oldlen < newlen\";\n\t\t\t\t}\n\t\t\t    }\n\t\t\t  \n\n\t\t\t  if (loktestmode)\n\t\t\t    (*testout) << \"ok = \" << int(ok) \n\t\t\t\t       << \"teterr = \" << teterr \n\t\t\t\t       << \"minteterr = \" << minteterr << endl;\n\n\n\t\t\t  if (ok && teterr < tolerance)\n\t\t\t    {\n\t\t\t      canuse[rim] ++;\n\t\t\t      /*\n\t\t\t      (*testout) << \"can use rule \" << rule->Name() \n\t\t\t\t\t << \", err = \" << teterr << endl;\n\t\t\t      for (i = 1; i <= pmap.Size(); i++)\n\t\t\t\t(*testout) << pmap.Get(i) << \" \";\n\t\t\t      (*testout) << endl;\n\t\t\t      */\n\n\t\t\t      if (problems[rim] == \"other\")\n\t\t\t\t{\n\t\t\t\t  if (teterr < minother)\n\t\t\t\t    minother = teterr;\n\t\t\t\t}\n\t\t\t      else\n\t\t\t\t{\n\t\t\t\t  if (teterr < minwithoutother)\n\t\t\t\t    minwithoutother = teterr;\n\t\t\t\t}\n\t\t\t    }\n\n\n\t\t\t  if (teterr > minteterr) impossible = 0;\n\n\t\t\t  if (ok && teterr < minteterr)\n\t\t\t    {\n\n\t\t\t      if (loktestmode)\n\t\t\t\t(*testout) << \"use rule\" << endl;\n\n\t\t\t      found = rim+1;\n\t\t\t      minteterr = teterr;\n\t\t\t      \n\t\t\t      if (testmode)\n\t\t\t\t{\n\t\t\t\t  for (int i = 1; i <= rule->GetNOldP(); i++)\n\t\t\t\t    {\n\t\t\t\t      (*testout) << \"P\" << i << \": Ref: \"\n\t\t\t\t\t\t << rule->GetPoint (i) << \"  is: \"\n\t\t\t\t\t\t << lpoints[pmap.Get(i)] << endl;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t      \n\t\t\t      tempnewpoints.SetSize (0);\n\t\t\t      // for (int i = noldlp+1; i <= lpoints.Size(); i++)\n                              for (auto i : lpoints.Range().Modify(noldlp, 0))\n\t\t\t\ttempnewpoints.Append (lpoints[i]);\n\t\t\t      \n\t\t\t      tempnewfaces.SetSize (0);\n\t\t\t      // for (int i = noldlf+1; i <= lfaces.Size(); i++)\n                              for (auto i : lfaces.Range().Modify(noldlf,0))\n\t\t\t\ttempnewfaces.Append (lfaces[i]);\n\n\t\t\t      tempdelfaces.SetSize (0);\n\t\t\t      // for (int i = 1; i <= delfaces.Size(); i++)\n                              for (auto i : delfaces.Range())\n\t\t\t\ttempdelfaces.Append (delfaces[i]);\n\t\t\t      \n\t\t\t      tempelements.SetSize (0);\n\t\t\t      // for (int i = 1; i <= elements.Size(); i++)\n                              for (auto i : elements.Range())\n\t\t\t\ttempelements.Append (elements[i]);\n\t\t\t    }\n\t\t\t  \n\n\t\t\t  lpoints.SetSize (noldlp);\n\t\t\t  lfaces.SetSize (noldlf);\n\t\t\t  delfaces.SetSize (0);\n\t\t\t  elements.SetSize (0);\n\t\t\t}\n\t\t      \n\t\t      npok = rule->GetNOldP();\n\t\t      incnpok = 0;\n\t\t    }\n\t\t}\n\t      \n\t      nfok = rule->GetNOldF();\n\t      \n\t      for (int j = 1; j <= rule->GetNP (nfok); j++)\n\t\t{\n\t\t  int refpi = rule->GetPointNr (nfok, j);\n\t\t  pused[pmap.Get(refpi)]--;\n\t\t  \n\t\t  if (pused[pmap.Get(refpi)] == 0)\n                    pmap.Elem(refpi).Invalidate();\n\t\t}\n\t      \n\t    }\n\t}\n      if (loktestmode)\n\t(*testout) << \"end rule\" << endl;\n    }\n  // tloop.Stop();\n  \n  if (found)\n    {\n      /*\n      for (i = 1; i <= tempnewpoints.Size(); i++)\n\tlpoints.Append (tempnewpoints.Get(i));\n      */\n      for (Point3d p : tempnewpoints)\n        lpoints.Append(p);\n      /*\n      for (i = 1; i <= tempnewfaces.Size(); i++)\n\tif (tempnewfaces.Get(i).PNum(1))\n\t  lfaces.Append (tempnewfaces.Get(i));\n      */\n      for (int i : tempnewfaces.Range())\n\tif (tempnewfaces[i].PNum(1).IsValid())\n\t  lfaces.Append (tempnewfaces[i]);\n      /*\n      for (i = 1; i <= tempdelfaces.Size(); i++)\n\tdelfaces.Append (tempdelfaces.Get(i));\n      */\n      for (int i : tempdelfaces.Range())\n        delfaces.Append (tempdelfaces[i]);\n      /*\n      for (i = 1; i <= tempelements.Size(); i++)\n\telements.Append (tempelements.Get(i));\n      */\n      for (int i : tempelements.Range())\n        elements.Append (tempelements[i]);\n    }\n  \n  retminerr = minerr;\n\n\n  if (impossible && found == 0)\n    return -1;\n\n  return found;\n}\n}\n"
  },
  {
    "path": "libsrc/meshing/ruler3.hpp",
    "content": "#ifndef FILE_RULER3\n#define FILE_RULER3\n\nnamespace netgen\n{\n\n/**\n  3D element generation rule.\n */\nclass vnetrule\n{\nprivate:\n  /// rule is applicable for quality classes above this value\n  int quality;\n  /// name of rule\n  char * name;\n  /// point coordinates in reference position\n  NgArray<Point3d> points;\n  /// old and new faces in reference numbering\n  NgArray<Element2d> faces;\n  /// additional edges of rule\n  NgArray<twoint> edges;\n\n  /// points of freezone in reference coordinates\n  NgArray<Point3d> freezone;\n  /// points of freezone in reference coordinates if tolcalss to infty\n  NgArray<Point3d> freezonelimit;\n  /// point index, if point equal to mappoint, otherwise 0\n  NgArray<int> freezonepi;\n  /// faces of each convex part of freezone\n  NgArray<NgArray<threeint>*> freefaces;\n  /// set of points of each convex part of freezone\n  NgArray<NgArray<int>*> freesets;\n  /// points of transformed freezone\n  NgArray<Point3d> transfreezone;\n  /// edges of each convex part of freezone\n  NgArray<NgArray<twoint>*> freeedges;\n\n  /// face numbers to be deleted\n  NgArray<int> delfaces;\n  /// elements to be generated\n  NgArray<Element> elements;\n  /// tolerances for points and faces (used ??)\n  NgArray<double> tolerances, linetolerances;\n  /// transformation matrix \n  DenseMatrix oldutonewu;\n  /// transformation matrix: deviation old point to dev. freezone\n  DenseMatrix * oldutofreezone;\n  /** transformation matrix: deviation old point to dev. freezone, \n    quality class to infinity */\n  DenseMatrix * oldutofreezonelimit;\n\n  // can be deleted:\n  // BaseMatrix *outf, *outfl;\n\n  /**\n    a point is outside of convex part of freezone, \n    iff mat * (point, 1) >= 0 for each component (correct ?)\n    */\n  NgArray<DenseMatrix*> freefaceinequ;\n  /// \n  NgArray<fourint> orientations;\n  /**\n    flags specified in rule-description file:\n    t .. test rule\n    */\n  NgArray<char> flags;\n\n  /**\n    topological distance of face to base element\n    non-connected: > 100  (??) \n    */\n  NgArray<int> fnearness;\n  NgArray<int> pnearness;\n  int maxpnearness;\n\n  /// number of old points in rule\n  int noldp;\n  /// number of new poitns in rule\n  int noldf;\n  /// box containing free-zone\npublic:  \n  // double fzminx, fzmaxx, fzminy, fzmaxy, fzminz, fzmaxz;\n  Box3d fzbox;\n\npublic:\n  \n  ///\n  vnetrule ();\n  ///\n  ~vnetrule ();\n  ///\n  int GetNP () const { return points.Size(); }\n  ///\n  int GetNF () const { return faces.Size(); }\n  ///\n  int GetNE () const { return elements.Size(); }\n  ///\n  int GetNO () const { return orientations.Size(); }\n  ///\n  int GetNEd () const { return edges.Size(); }\n  ///\n  int GetNOldP () const { return noldp; }\n  ///\n  int GetNOldF () const { return noldf; }\n  ///\n  int GetNDelF () const { return delfaces.Size(); }\n  ///\n  int GetQuality () const { return quality; }\n  ///\n  int GetFNearness (int fi) const { return fnearness.Get(fi); }\n  ///\n  int GetPNearness (int pi) const { return pnearness.Get(pi); }\n  ///\n  int GetMaxPNearness () const { return maxpnearness; }\n\n\n  ///\n  const Point3d & GetPoint (int i) const { return points.Get(i); }\n  ///\n  const Element2d & GetFace (int i) const { return faces.Get(i); }\n  ///\n  const Element & GetElement (int i) const { return elements.Get(i); }\n  ///\n  const twoint & GetEdge (int i) const { return edges.Get(i); }\n  ///\n  int GetDelFace (int i) const { return delfaces.Get(i); }\n  ///\n  int IsDelFace (int fn) const;\n  \n  ///\n  float CalcPointDist (int pi, const Point3d & p) const;\n  ///\n  double PointDistFactor (int pi) const\n    {\n      return tolerances.Get(pi);\n    }\n  ///\n  void SetFreeZoneTransformation (const Vector & allp,\n\t\t\t\t  int tolclass);\n  ///\n  int IsInFreeZone (const Point3d & p) const;\n  /**\n    0 not in free-zone\n    1 in free-zone\n    -1 maybe \n   */\n  int IsTriangleInFreeZone (const Point3d & p1, const Point3d & p2,\n                            const Point3d & p3, const NgArray<int> & pi, int newone);\n  ///\n  int IsQuadInFreeZone (const Point3d & p1, const Point3d & p2,\n\t\t\tconst Point3d & p3, const Point3d & p4,\n\t\t\tconst NgArray<int> & pi, int newone);\n  ///\n  int IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2,\n                           const Point3d & p3, int fs, const NgArray<int> & pi, int newone);\n\n  ///\n  int IsQuadInFreeSet (const Point3d & p1, const Point3d & p2,\n\t\t       const Point3d & p3, const Point3d & p4,\n\t\t       int fs, const NgArray<int> & pi, int newone);\n  \n  ///\n  int ConvexFreeZone () const;\n  \n  /// if t1 and t2 are neighbourtriangles, NTP returns the opposite Point of t1 in t2\n  int NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const;\n  ///\n  const Point3d & GetTransFreeZone (int i) { return transfreezone.Get(i); }\n\n  ///\n  int GetNP (int fn) const\n  { return faces.Get(fn).GetNP(); }\n  ///\n  PointIndex GetPointNr (int fn, int endp) const\n  { return faces.Get(fn).PNum(endp); }\n  ///\n  PointIndex GetPointNrMod (int fn, int endp) const\n  { return faces.Get(fn).PNumMod(endp); }\n  ///\n  const fourint & GetOrientation (int i) { return orientations.Get(i); }\n\n  ///\n  int TestFlag (char flag) const;\n\n  ///\n  const DenseMatrix & GetOldUToNewU () const { return oldutonewu; }\n  //\n  //  const DenseMatrix & GetOldUToFreeZone () const { return oldutofreezone; }\n  //\n  //  const DenseMatrix & GetOldUToFreeZoneLimit () const \n  //    { return oldutofreezonelimit; }\n  ///\n  const char * Name () const { return name; }\n  ///\n  void LoadRule (istream & ist);\n\n  ///\n  const NgArray<Point3d> & GetTransFreeZone () { return transfreezone; }\n  ///\n  int TestOk () const;\n\n  ///\n  friend void TestRules ();\n  ///\n  //  friend void Plot3DRule (const ROT3D & r, char key);\n};\n\n} // namespace netgen\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/secondorder.cpp",
    "content": " #include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\nnamespace netgen\n{\n\n  void Refinement :: MakeSecondOrder (Mesh & mesh) const\n  {\n    const_cast<Refinement&> (*this).MakeSecondOrder(mesh);\n  }\n\n  \n  void Refinement :: MakeSecondOrder (Mesh & mesh)\n  {\n    /*\n      Berlin, 2014: if we have curved surface elements, keep them !\n    */\n\n    mesh.ComputeNVertices();\n    // mesh.SetNP(mesh.GetNV());\n    mesh.SetNP(mesh.GetNP());  // setup multilevel-table\n\n    INDEX_2_HASHTABLE<PointIndex> between(mesh.GetNP() + 5);\n\n    for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)\n      {\n        auto & seg = mesh[si];\n        if (seg.GetType() == SEGMENT3)\n          between.Set(INDEX_2::Sort(seg[0],seg[1]), seg[2]);\n      }\n    \n    \n    for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\n\tstatic int betw_trig[3][3] =\n\t  { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } };\n\tstatic int betw_quad6[2][3] =\n\t  { { 0, 1, 4 }, { 3, 2, 5 } };\n\tstatic int betw_quad8[4][3] =\n\t  { { 0, 1, 4 }, { 3, 2, 5 },\n\t    { 0, 3, 6 }, { 1, 2, 7 } };\n      \n\tint onp = 0;\n\tint (*betw)[3] = NULL;\n\tswitch (el.GetType())\n\t  {\n\t  case TRIG6:\n\t    {\n\t      betw = betw_trig;\n\t      onp = 3;\n\t      break;\n\t    }\n\t  case QUAD6: \n            {\n              betw = betw_quad6;\n              onp = 4;\n              break;\n            }\n\t  case QUAD8: \n            {\n              betw = betw_quad8;\n              onp = 4;\n              break;\n            }\n          default:\n            ;\n          }\n        \n        if (betw)\n          for (int j = 0; j < el.GetNP()-onp; j++)\n            {\n              int pi1 = el[betw[j][0]];\n              int pi2 = el[betw[j][1]];\n              INDEX_2 i2 = INDEX_2::Sort (pi1, pi2);\n              between.Set (i2, el[onp+j]);\n            }\n      }\n      \n\n    bool thinlayers = 0;\n    for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)\n      if (mesh[ei].GetType() == PRISM ||\n\t  mesh[ei].GetType() == PRISM12)\n\tthinlayers = 1;\n    \n\n    int nseg = mesh.GetNSeg();\n    for (SegmentIndex si = 0; si < nseg; si++)\n      {\n\tSegment & el = mesh.LineSegment(si);\n\n\tINDEX_2 i2 = INDEX_2::Sort (el[0], el[1]);\n\n\tif (between.Used(i2))\n\t  el[2] = between.Get(i2);\n\telse\n\t  {\n\t    Point<3> pb;\n\t    EdgePointGeomInfo ngi;\n            geo.PointBetweenEdge(mesh.Point (el[0]),\n                                 mesh.Point (el[1]), 0.5,\n                                 el.surfnr1, el.surfnr2,\n                                 el.epgeominfo[0], el.epgeominfo[1],\n                                 pb, ngi);\n\t  \n\t    el[2] = mesh.AddPoint (pb, mesh.Point(el[0]).GetLayer(), \n\t\t\t\t   EDGEPOINT);\n\t    between.Set (i2, el[2]);\n\t  }\n        el.SetCurved(true);\n      }\n\n    // refine surface elements\n    for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n      {\n\tconst Element2d & el = mesh[sei];\n\n\tint onp = 0;\n      \n\tElement2d newel(TRIG);\n\tnewel.SetIndex (el.GetIndex());\n\n\tstatic int betw_trig[3][3] =\n\t  { { 1, 2, 3 },\n\t    { 0, 2, 4 },\n\t    { 0, 1, 5 } };\n\tstatic int betw_quad6[2][3] =\n\t  { { 0, 1, 4 },\n\t    { 3, 2, 5 } };\n\tstatic int betw_quad8[4][3] =\n\t  { { 0, 1, 4 },\n\t    { 3, 2, 5 },\n\t    { 0, 3, 6 },\n\t    { 1, 2, 7 } };\n\tint (*betw)[3] = NULL;\n      \n\tswitch (el.GetType())\n\t  {\n\t  case TRIG:\n\t  case TRIG6:\n\t    {\n\t      betw = betw_trig;\n\t      newel.SetType (TRIG6);\n\t      onp = 3;\n\t      break;\n\t    }\n\t  case QUAD:\n\t  case QUAD6: \n\t  case QUAD8:\n\t    {\n\t      if (thinlayers)\n\t\t{\n\t\t  betw = betw_quad6;\n\t\t  newel.SetType (QUAD6);\n\t\t}\n\t      else\n\t\t{\n\t\t  betw = betw_quad8;\n\t\t  newel.SetType (QUAD8);\n\t\t}\n\t      onp = 4;\n\t      break;\n\t    }\n\t  default:\n\t    PrintSysError (\"Unhandled element in secondorder:\", int(el.GetType()));\n\t  }\n\n\tfor (int j = 0; j < onp; j++)\n\t  newel[j] = el[j];\n      \n\tint nnp = newel.GetNP();\n\tfor (int j = 0; j < nnp-onp; j++)\n\t  {\n\t    PointIndex pi1 = newel[betw[j][0]];\n\t    PointIndex pi2 = newel[betw[j][1]];\n\t  \n\t    INDEX_2 i2 = INDEX_2::Sort (pi1, pi2);\n\t  \n\t    if (between.Used(i2))\n\t      newel[onp+j] = between.Get(i2);\n\t    else\n\t      {\n\t\tPoint<3> pb;\n\t\tPointGeomInfo newgi;\n\t\tgeo.PointBetween(mesh.Point (pi1),\n                                 mesh.Point (pi2), 0.5, \n                                 mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(),\n                                 el.GeomInfoPi (betw[j][0]+1),\n                                 el.GeomInfoPi (betw[j][1]+1),\n                                 pb, newgi);\n\n\t\tnewel[onp+j] = mesh.AddPoint (pb, mesh.Point(pi1).GetLayer(), \n\t\t\t\t\t      SURFACEPOINT);\n\t\tbetween.Set (i2, newel[onp+j]);\n\t      }\n\t  }\n      \n\tmesh[sei] = newel;\n      }\n\n \n    //    int i, j;\n\n\n\n    // refine volume elements\n    // for (int i = 1; i <= mesh.GetNE(); i++)\n    for (ElementIndex ei : mesh.VolumeElements().Range())\n      {\n\tconst Element & el = mesh.VolumeElement(ei);\n\tint onp = 0;\n\n\tElement newel(TET);\n\tnewel.SetIndex (el.GetIndex());\n\n\tstatic int betw_tet[6][3] =\n\t  { { 0, 1, 4 },\n\t    { 0, 2, 5 },\n\t    { 0, 3, 6 },\n\t    { 1, 2, 7 },\n\t    { 1, 3, 8 },\n\t    { 2, 3, 9 } };\n\tstatic int betw_prism[6][3] =\n\t  {\n\t    { 0, 2, 6 },\n\t    { 0, 1, 7 },\n\t    { 1, 2, 8 },\n\t    { 3, 5, 9 },\n\t    { 3, 4, 10 },\n\t    { 4, 5, 11 },\n\t  };\n        static int betw_prism15[9][3] =\n          {\n           { 0, 1, 6 },\n           { 0, 2, 7 },\n           { 1, 2, 8 },\n           { 0, 3, 9 },\n           { 1, 4, 10 },\n           { 2, 5, 11 },\n           { 3, 4, 12 },\n           { 3, 5, 13 },\n           { 4, 5, 14 }\n          };\n        static int betw_pyramid[8][3] =\n          {\n           { 0, 1, 5 },\n           { 3, 2, 6 },\n           { 3, 0, 7 },\n           { 1, 2, 8 },\n           { 0, 4, 9 },\n           { 1, 4, 10 },\n           { 2, 4, 11 },\n           { 3, 4, 12 }\n          };\n\tstatic int betw_hex[12][3] =\n\t  {\n            { 0, 1, 8 },\n            { 2, 3, 9 },\n            { 3, 0, 10 },\n            { 1, 2, 11 },\n            { 4, 5, 12 },\n            { 6, 7, 13 },\n            { 7, 4, 14 },\n            { 5, 6, 15 },\n            { 0, 4, 16 },\n            { 1, 5, 17 },\n            { 2, 6, 18 },\n            { 3, 7, 19 },\n          };\n        \n\tint (*betw)[3] = NULL;\n\n\tswitch (el.GetType())\n\t  {\n\t  case TET:\n\t  case TET10:\n\t    {\n\t      betw = betw_tet;\n\t      newel.SetType (TET10);\n\t      onp = 4;\n\t      break;\n\t    }\n\t  case PRISM:\n\t  case PRISM12:\n\t    {\n\t      betw = betw_prism;\n\t      newel.SetType (PRISM12);\n\t      onp = 6;\n\t      break;\n\t    }\n          case PRISM15:\n            {\n              betw = betw_prism15;\n              newel.SetType(PRISM15);\n              onp = 6;\n              break;\n            }\n          case PYRAMID:\n          case PYRAMID13:\n            {\n              betw = betw_pyramid;\n              newel.SetType(PYRAMID13);\n              onp = 5;\n              break;\n            }\n          case HEX:\n          case HEX20:\n\t    {\n\t      betw = betw_hex;\n\t      newel.SetType (HEX20);\n\t      onp = 8;\n\t      break;\n\t    }\n\t  default:\n\t    PrintSysError (\"MakeSecondOrder, illegal vol type \", int(el.GetType()));\n\t  }\n\n\n\tfor (int j = 1; j <= onp; j++)\n\t  newel.PNum(j) = el.PNum(j);\n\tint nnp = newel.GetNP();\n\n\tfor (int j = 0; j < nnp-onp; j++)\n\t  {\n\t    INDEX_2 i2(newel[betw[j][0]],\n\t\t       newel[betw[j][1]]);\n\t    i2.Sort();\n\t  \n\t    if (between.Used(i2))\n\t      newel.PNum(onp+1+j) = between.Get(i2);\n\t    else\n\t      {\n\t\tnewel.PNum(onp+1+j) = mesh.AddPoint\n\t\t  (Center (mesh.Point(i2.I1()),\n\t\t\t   mesh.Point(i2.I2())),\n\t\t   mesh.Point(i2.I1()).GetLayer(), \n\t\t   INNERPOINT);\n\n\t\tbetween.Set (i2, newel.PNum(onp+1+j));\n\t      }\n\t  }\n\n\tmesh.VolumeElement (ei) = newel;\n      }\n\n\n    // makes problems after linear mesh refinement, since\n    // 2nd order identifications are not removed\n    // update identification tables\n    for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)\n      {\n\tidmap_type identmap;\n\tmesh.GetIdentifications().GetMap (i, identmap);\n\n\tfor (INDEX_2_HASHTABLE<PointIndex>::Iterator it = between.Begin();\n\t     it != between.End(); it++)\n\t  {\n              PointIndices<2> i2;\n\t      PointIndex newpi;\n\t      between.GetData (it, i2, newpi);\n\t      PointIndices<2> oi2(identmap[i2[0]], \n                                  identmap[i2[1]]);\n\t      oi2.Sort();\n\t      if (between.Used (oi2))\n\t\t{\n\t\t  PointIndex onewpi = between.Get(oi2);\n\t\t  mesh.GetIdentifications().Add (newpi, onewpi, i);\n\t\t}\n\t  }\n\n\t/*\n\tfor (int j = 1; j <= between.GetNBags(); j++)\n\t  for (int k = 1; k <= between.GetBagSize(j); k++)\n\t    {\n\t      INDEX_2 i2;\n\t      int newpi;\n\t      between.GetData (j, k, i2, newpi);\n\t      INDEX_2 oi2(identmap.Get(i2.I1()),\n\t\t\t  identmap.Get(i2.I2()));\n\t      oi2.Sort();\n\t      if (between.Used (oi2))\n\t\t{\n\t\t  int onewpi = between.Get(oi2);\n\t\t  mesh.GetIdentifications().Add (newpi, onewpi, i);\n\t\t}\n\t    }\n\t*/\n      }\n\n\n    //  mesh.mglevels++;\n    int oldsize = mesh.mlbetweennodes.Size();\n    mesh.mlbetweennodes.SetSize(mesh.GetNP());\n    for (int i = oldsize; i < mesh.GetNP(); i++)\n      mesh.mlbetweennodes[i] = INDEX_2(0,0);\n\n    /*\n    for (i = 1; i <= between.GetNBags(); i++)\n      for (j = 1; j <= between.GetBagSize(i); j++)\n\t{\n\t  INDEX_2 oldp;\n\t  int newp;\n\t  between.GetData (i, j, oldp, newp);\n\t  mesh.mlbetweennodes.Elem(newp) = oldp;\n\t}\n    */\n\n    for (INDEX_2_HASHTABLE<PointIndex>::Iterator it = between.Begin();\n\t it != between.End(); it++)\n      {\n\tmesh.mlbetweennodes[between.GetData (it)] = between.GetHash(it);\n      }\n\n    mesh.ComputeNVertices();\n    mesh.RebuildSurfaceElementLists();\n    //  ValidateSecondOrder (mesh);\n  }\n\n\n  void Refinement :: ValidateSecondOrder (Mesh & mesh)\n  {\n    PrintMessage (3, \"Validate mesh\");\n    int np = mesh.GetNP();\n    // int i, j;\n    NgArray<INDEX_2> parents(np);\n  \n    for (int i = 1; i <= np; i++)\n      parents.Elem(i) = INDEX_2(0,0);\n\n    // for (int i = 1; i <= ne; i++)\n    for (ElementIndex ei : mesh.VolumeElements().Range())\n      {\n\tconst Element & el = mesh[ei];\n\tif (el.GetType() == TET10)\n\t  {\n\t    static int betweentab[6][3] =\n\t      { { 1, 2, 5 },\n\t\t{ 1, 3, 6 },\n\t\t{ 1, 4, 7 },\n\t\t{ 2, 3, 8 },\n\t\t{ 2, 4, 9 },\n\t\t{ 3, 4, 10 } };\n\t    for (int j = 0; j < 6; j++)\n\t      {\n\t\tint f1 = el.PNum (betweentab[j][0]);\n\t\tint f2 = el.PNum (betweentab[j][1]);\n\t\tint son = el.PNum (betweentab[j][2]);\n\t\tparents.Elem(son).I1() = f1;\n\t\tparents.Elem(son).I2() = f2;\n\t      }\n\t  }\n      }\n\n    ValidateRefinedMesh (mesh, parents);\n  }\n\n\n  void Refinement ::\n  ValidateRefinedMesh (Mesh & mesh, \n\t\t       NgArray<INDEX_2> & parents)\n  {\n    // int i, j, k;\n  \n    // homotopy method\n\n    int ne = mesh.GetNE();\n\n    int cnttrials = 100;\n    int wrongels = 0;\n    // for (int i = 1; i <= ne; i++)\n    for (ElementIndex ei : mesh.VolumeElements().Range())\n      if (mesh.VolumeElement(ei).CalcJacobianBadness (mesh.Points()) > 1e10)\n\t{\n\t  wrongels++;\n\t  mesh.VolumeElement(ei).Flags().badel = 1;\n\t}\n      else\n\tmesh.VolumeElement(ei).Flags().badel = 0;\n\n    double facok = 0;\n    double factry;\n\n    BitArray illegalels(ne+1);\n    illegalels.Clear();\n\n      \n    if (wrongels)\n      {\n\tcout << \"WARNING: \" << wrongels << \" illegal element(s) found\" << endl;\n\n\tint np = mesh.GetNP();\n\tNgArray<Point<3> > should(np);\n\tNgArray<Point<3> > can(np);\n\n\tfor (int i = 1; i <= np; i++)\n\t  {\n\t    should.Elem(i) = can.Elem(i) = mesh.Point(i);\n\t  }\n\n\tfor (int i = 1; i <= parents.Size(); i++)\n\t  {\n\t    if (parents.Get(i).I1())\n\t      can.Elem(i) = Center (can.Elem(parents.Get(i).I1()),\n\t\t\t\t    can.Elem(parents.Get(i).I2()));\n\t  }\n\n\tTBitArray<PointIndex> boundp(np);\n\tboundp.Clear();\n        /*\n\tfor (int i = 1; i <= mesh.GetNSE(); i++)\n\t  {\n\t    const Element2d & sel = mesh.SurfaceElement(i);\n        */\n        for (auto & sel : mesh.SurfaceElements())\n          for (int j = 1; j <= sel.GetNP(); j++)\n            boundp.SetBit(sel.PNum(j));\n        // }\n\n\n\t(*testout) << \"bpoints:\" << endl;\n\tfor (int i = 1; i <= np; i++)\n\t  if (boundp.Test(i))\n\t    (*testout) << i << endl;\n\n\tdouble lam = 0.5;\n\n\twhile (facok < 1-1e-8 && cnttrials > 0)\n\t  {\n\t    lam *= 4;\n\t    if (lam > 2) lam = 2;\n\n\t    do\n\t      {\n\t\t//\t      cout << \"trials: \" << cnttrials << endl;\n\t\tlam *= 0.5;\n\t\tcnttrials--;\n\n\t\tcout << \"lam = \" << lam << endl;\n\n\t\tfactry = lam + (1-lam) * facok;\n\t\tcout << \"trying: \" << factry << endl;\n\n\t\tfor (int i = 1; i <= np; i++)\n\t\t  if (boundp.Test(i))\n\t\t    {\n\t\t      for (int j = 0; j < 3; j++)\n\t\t\tmesh.Point(i)(j) = \n\t\t\t  lam * should.Get(i)(j) +\n\t\t\t  (1-lam) * can.Get(i)(j);\n\t\t    }\n\t\t  else\n\t\t    mesh.Point(i) = Point<3> (can.Get(i));\n\t      \n\t\t//\t      (*testout) << \"bad els: \" << endl;\n\t\twrongels = 0;\n\t\tfor (int i = 1; i <= ne; i++)\n                  \n\t\t  {\n\t\t    if (!illegalels.Test(i) && \n\t\t\tmesh.VolumeElement(i).\n\t\t\tCalcJacobianBadness(mesh.Points()) > 1e10)\n\t\t      {\n\t\t\twrongels++;\n\t\t\tElement & el = mesh.VolumeElement(i);\n\t\t\tel.Flags().badel = 1;\n\t\t     \n\t\t      \n\t\t\tif (lam < 1e-4)\n\t\t\t  illegalels.SetBit(i);\n \n\n\t\t\t/*\n\t\t\t  (*testout) << i << \": \";\n\t\t\t  for (j = 1; j <= el.GetNP(); j++)\n\t\t\t  (*testout) << el.PNum(j) << \" \";\n\t\t\t  (*testout) << endl;\n\t\t\t*/\n\t\t      }\n\t\t    else\n\t\t      mesh.VolumeElement(i).Flags().badel = 0;\n\t\t  }\n\t\tcout << \"wrongels = \" << wrongels << endl;\n\t      }\n\t    while (wrongels && cnttrials > 0);\n\n\t    mesh.CalcSurfacesOfNode();\n\t    MeshingParameters dummymp;\n\t    mesh.ImproveMeshJacobian (dummymp, OPT_WORSTCASE);\t      \n\t  \n\t    facok = factry;\n\t    for (int i = 1; i <= np; i++)\n\t      can.Elem(i) = mesh.Point(i);\n\t  }\n      }\n\n\n      \n    for (int i = 1; i <= ne; i++)\n      {\n\tif (illegalels.Test(i))\n\t  {\n\t    cout << \"illegal element: \" << i << endl;\n\t    mesh.VolumeElement(i).Flags().badel = 1;\n\t  }\n\telse\n\t  mesh.VolumeElement(i).Flags().badel = 0;\n      }\n  \n    /*\n      if (cnttrials <= 0)\n      {\n      cerr << \"ERROR: Sorry, illegal elements:\" << endl;\n      }\n    */\n  }\n\n}\n"
  },
  {
    "path": "libsrc/meshing/smoothing2.5.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#include <opti.hpp>\n\nnamespace netgen\n{\n\n\n  void MeshOptimize2d :: ProjectBoundaryPoints(NgArray<int> & surfaceindex, \n\t\t\t\t\t       const NgArray<Point<3>* > & from, NgArray<Point<3>* > & dest)\n  {\n    for(int i=0; i<surfaceindex.Size(); i++)\n      {\n\tif(surfaceindex[i] >= 0)\n\t  {\n\t    *dest[i] = *from[i];\n\t    geo.ProjectPoint(surfaceindex[i],*dest[i]);\n\t  }\n      }\n      \n\n  }\n\n  void MeshOptimize2d :: ImproveVolumeMesh ()\n  {\n    \n    if (!faceindex)\n      {\n\tPrintMessage (3, \"Smoothing\");\n\n\tfor (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)\n\t  {\n\t    ImproveVolumeMesh ();\n\t    if (multithread.terminate)\n\t      throw NgException (\"Meshing stopped\");\n\t  }\n\tfaceindex = 0;\n\treturn;\n      }\n      \n\n\n    static int timer = NgProfiler::CreateTimer (\"MeshSmoothing 2D\");\n    NgProfiler::RegionTimer reg (timer);\n\n\n\n    CheckMeshApproximation (mesh);\n\n    int i, j, k;\n    SurfaceElementIndex sei;\n\n    Array<SurfaceElementIndex> seia;\n    mesh.GetSurfaceElementsOfFace (faceindex, seia);\n\n    /*\n    bool mixed = 0;\n    for (i = 0; i < seia.Size(); i++)\n      if (mesh[seia[i]].GetNP() != 3)\n\t{\n\t  mixed = 1;\n\t  break;\n\t}\n    */\n\n    int loci;\n    double fact;\n    bool moveisok;\n\n    PointGeomInfo ngi;\n    Point<3> origp;\n\n    Vector x(3);\n\n    NgArray<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP());\n\n    NgArray<int, PointIndex::BASE> nelementsonpoint(mesh.GetNP());\n    nelementsonpoint = 0;\n\n    for (i = 0; i < seia.Size(); i++)\n      {\n\tconst Element2d & el = mesh[seia[i]];\n\tfor (j = 0; j < el.GetNP(); j++)\n\t  nelementsonpoint[el[j]]++;\n      }\n\n\n    TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonpoint(nelementsonpoint);\n    for (i = 0; i < seia.Size(); i++)\n      {\n\tconst Element2d & el = mesh[seia[i]];\n\tfor (j = 0; j < el.GetNP(); j++)\n\t  elementsonpoint.Add (el[j], seia[i]);\n      }\n    \n\n    JacobianPointFunction pf(mesh.Points(),mesh.VolumeElements());\n\n\n\n//     Opti2SurfaceMinFunction surfminf(mesh);\n//     Opti2EdgeMinFunction edgeminf(mesh);\n//     Opti2SurfaceMinFunctionJacobian surfminfj(mesh);\n\n    OptiParameters par;\n    par.maxit_linsearch = 8;\n    par.maxit_bfgs = 5;\n\n    int np = mesh.GetNP();\n    int ne = mesh.GetNE();\n\n    TBitArray<PointIndex> badnodes(np);\n    badnodes.Clear();\n\n    for (i = 1; i <= ne; i++)\n      {\n\tconst Element & el = mesh.VolumeElement(i);\n\tdouble bad = el.CalcJacobianBadness (mesh.Points());\n\tif (bad > 1)\n\t  for (j = 1; j <= el.GetNP(); j++)\n\t    badnodes.SetBit (el.PNum(j));\n      }\n\n\n    bool printeddot = 0;\n    char plotchar = '.';\n    int modplot = 1;\n    if (mesh.GetNP() > 1000)\n      {\n\tplotchar = '+';\n\tmodplot = 10;\n      }\n    if (mesh.GetNP() > 10000)\n      {\n\tplotchar = 'o';\n\tmodplot = 100;\n      }\n    int cnt = 0;\n\n\n    NgArray<SurfaceElementIndex> locelements(0);\n    NgArray<int> locrots(0);\n\n    // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++)\n    for (PointIndex pi : mesh.Points().Range())\n      {\n\tif (mesh[pi].Type() != SURFACEPOINT)\n\t  continue;\n\n\tif (multithread.terminate)\n\t  throw NgException (\"Meshing stopped\");\n\t\n\tint surfi(-1);\n\n\tif(elementsonpoint[pi].Size() == 0)\n\t  continue;\n\n\tElement2d & hel = mesh[elementsonpoint[pi][0]];\n\n\tif(hel.GetIndex() != faceindex)\n\t  continue;\n\n\tcnt++;\n\tif (cnt % modplot == 0 && writestatus)\n\t  {\n\t    printeddot = 1;\n\t    PrintDot (plotchar);\n\t  }\n\n\t\t\n\tint hpi = 0;\n\tfor (j = 1; j <= hel.GetNP(); j++)\n\t  if (hel.PNum(j) == pi)\n\t    {\n\t      hpi = j;\n\t      break;\n\t    }\n\tPointGeomInfo gi1 = hel.GeomInfoPi(hpi);\n\t\n\tlocelements.SetSize(0);\n\tlocrots.SetSize (0);\n\t\n\tfor (j = 0; j < elementsonpoint[pi].Size(); j++)\n\t  {\n\t    sei = elementsonpoint[pi][j];\n\t    const Element2d & bel = mesh[sei];\n\t    surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr();\n\t    \n\t    locelements.Append (sei);\n\t    \n\t    for (k = 1; k <= bel.GetNP(); k++)\n\t      if (bel.PNum(k) == pi)\n\t\t{\n\t\t  locrots.Append (k);\n\t\t  break;\n\t\t}\n\t  }\n\t \n\n\tdouble lh = mesh.GetH(mesh.Point(pi));\n\tpar.typx = lh;\n\n\tpf.SetPointIndex(pi);\n\t\n\tx = 0;\n\tbool pok = (pf.Func (x) < 1e10); \n\t\n\tif (pok)\n\t  {\n\t    BFGS (x, pf, par);\n\t    \n\t    origp = mesh[pi];\n\t    loci = 1;\n\t    fact = 1;\n\t    moveisok = false;\n\t\n\t    \n\t    //optimizer loop (if whole distance is not possible, move only a bit!!!!)\n\t    while (loci <= 5 && !moveisok)\n\t      {\n\t\tloci ++;\n\t\tmesh[pi](0) = origp(0) + x(0)*fact;\n\t\tmesh[pi](1) = origp(1) + x(1)*fact;\n\t\tmesh[pi](2) = origp(2) + x(2)*fact;\n\t\tfact = fact/2.;\n\t    \n\t    \n\t\t//cout << \"origp \" << origp << \" newp \" << mesh[pi];\n\t    \n\t\tngi = gi1;\n\t\tmoveisok = (geo.ProjectPointGI(surfi, mesh[pi], ngi) != 0);\n\n\t\t//cout << \" projected \" << mesh[pi] << endl;\n\n\t\t// point lies on same chart in stlsurface\n\t\t\n\t\tif (moveisok)\n\t\t  {\n\t\t    for (j = 0; j < locelements.Size(); j++)\n\t\t      mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi;\n\n\t\t    //cout << \"moved \" << origp << \" to \" << mesh[pi] << endl;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    mesh[pi] = origp;\n\t\t  }\n\t    \n\t      }\n\t  }\n\telse\n\t  {\n\t    cout << \"el not ok (point \" << pi << \": \" << mesh[pi] << \")\" << endl;\n\t  }\n      }\n\n    if (printeddot)\n      PrintDot ('\\n');\n  \n    CheckMeshApproximation (mesh);\n    mesh.SetNextTimeStamp();\n  }\n\n  \n}\n"
  },
  {
    "path": "libsrc/meshing/smoothing2.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#include <opti.hpp>\n\nnamespace netgen\n{\n\n  static const double c_trig = 0.14433756;      // sqrt(3.0) / 12\n  static const double c_trig4 = 0.57735026;     // sqrt(3.0) / 3\n\n\n  inline double CalcTriangleBadness (double x2, double x3, double y3, \n\t\t\t\t     double metricweight, double h)\n  {\n    // badness = sqrt(3.0) / 12 * (\\sum l_i^2) / area - 1 \n    // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3);\n\n    double cir_2 = (x2*x2 + x3*x3 + y3*y3 - x2*x3);\n    double area = x2 * y3;\n    \n    if (area <= 1e-24 * cir_2)\n      return 1e10;\n    \n    double badness = c_trig4 * cir_2 / area - 1;\n    \n    if (metricweight > 0)\n      {\n\t// add:  metricweight * (area / h^2 + h^2 / area - 2)\n\n\tdouble areahh = area / (h * h);\n\tbadness += metricweight * (areahh + 1 / areahh - 2);\n      }\n    return badness;\n  }\n  \n  inline void CalcTriangleBadness (double x2, double x3, double y3, double metricweight,\n\t\t\t\t   double h, double & badness, double & g1x, double & g1y)\n  {\n    // old: badness = sqrt(3.0) /36 * circumference^2 / area - 1 \n    // badness = sqrt(3.0) / 12 * (\\sum l_i^2) / area - 1 \n    // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3);\n\n\n    double cir_2 = 2* (x2*x2 + x3*x3 + y3*y3 - x2*x3);\n    double area = 0.5 * x2 * y3;\n\n    if (area <= 1e-24 * cir_2)\n      {\n\tg1x = 0;\n\tg1y = 0;\n\tbadness = 1e10;\n\treturn;\n      }\n\n    badness = c_trig * cir_2 / area - 1;\n\n    double c1 = -2 * c_trig / area;\n    double c2 = 0.5 * c_trig * cir_2 / (area * area);\n    g1x = c1 * (x2 + x3) + c2 * y3;\n    g1y = c1 * (y3)      + c2 * (x2-x3); \n\n    if (metricweight > 0)\n      {\n\t// area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);\n\t// add:  metricweight * (area / h^2 + h^2 / area - 2)\n      \n\tarea = x2 * y3;\n\tdouble dareax1 = -y3; \n\tdouble dareay1 = x3 - x2; \n\n\tdouble areahh = area / (h * h);\n\tdouble fac = metricweight * (areahh - 1 / areahh) / area;\n\n\tbadness += metricweight * (areahh + 1 / areahh - 2);\n\tg1x += fac * dareax1;\n\tg1y += fac * dareay1; \n      }\n  }\n\n\n\n  double CalcTriangleBadness (const Point<3> & p1, \n\t\t\t      const Point<3> & p2, \n\t\t\t      const Point<3> & p3,\n\t\t\t      double metricweight,\n\t\t\t      double h)\n  {\n    // badness = sqrt(3.0) / 12 * (\\sum l_i^2) / area - 1 \n\n    Vec<3> e12 = p2-p1; \n    Vec<3> e13 = p3-p1;\n    Vec<3> e23 = p3-p2;\n\n    double cir_2 = e12.Length2() + e13.Length2() + e23.Length2();\n    double area = 0.5 * Cross (e12, e13).Length();\n\n    if (area <= 1e-24 * cir_2)\n      return 1e10;\n\n    double badness = c_trig * cir_2 / area - 1;\n\n    if (metricweight > 0)\n      {\n\t// add:  metricweight * (area / h^2 + h^2 / area - 2)\n        area *= 2;   // optimum for (2 area) is h^2\n        double areahh = area / (h * h);\n\tbadness += metricweight * (areahh + 1 / areahh - 2);\n      }\n\n    return badness;\n  }\n\n  double CalcTriangleBadnessGrad (const Point<3> & p1, \n                                  const Point<3> & p2, \n                                  const Point<3> & p3,\n                                  Vec<3> & gradp1,\n                                  double metricweight,\n                                  double h)\n  {\n    // badness = sqrt(3.0) / 12 * (\\sum l_i^2) / area - 1 \n\n    Vec<3> e12 = p2-p1; \n    Vec<3> e13 = p3-p1;\n    Vec<3> e23 = p3-p2;\n\n    double cir_2 = e12.Length2() + e13.Length2() + e23.Length2();\n    Vec<3> varea = Cross(e12, e13);\n    double area = 0.5 * varea.Length();\n\n    Vec<3> dcir_2 = (-2) * (e12+e13);\n    Vec<3> darea = (0.25/area) * Cross (p2-p3, varea);\n\n    if (area <= 1e-24 * cir_2)\n      {\n        gradp1 = 0;\n        return 1e10;\n      }\n\n    double badness = c_trig * cir_2 / area - 1;\n    gradp1 = c_trig * (1.0/area * dcir_2 - cir_2 / (area*area) * darea);\n\n    if (metricweight > 0)\n      {\n\t// add:  metricweight * (area / h^2 + h^2 / area - 2)\n        area *= 2;   // optimum for (2 area) is h^2\n\n        double areahh = area / (h * h);\n\tbadness += metricweight * (areahh + 1 / areahh - 2);\n\n        gradp1 += (2*metricweight * (1/(h*h) - (h*h)/(area*area))) * darea;\n      }\n\n    return badness;\n  }\n\n\n\n\n  double CalcTriangleBadness (const Point<3> & p1, \n\t\t\t      const Point<3> & p2, \n\t\t\t      const Point<3> & p3,\n\t\t\t      const Vec<3> & n,\n\t\t\t      double metricweight,\n\t\t\t      double h)\n  {\n    Vec<3> v1 = p2-p1;\n    Vec<3> v2 = p3-p1;\n\n    Vec<3> e1 = v1;\n    Vec<3> e2 = v2;\n\n    e1 -= (e1 * n) * n;\n    e1 /= (e1.Length() + 1e-24);\n    e2 = Cross (n, e1);\n\n    return CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), \n\t\t\t\t metricweight, h);\n  }\n\n\n  class Opti2dLocalData\n  {\n  public:\n    const MeshOptimize2d * meshthis;\n    MeshPoint sp1; \n    PointGeomInfo gi1;\n    Vec<3> normal, t1, t2;\n    NgArray<SurfaceElementIndex> locelements;\n    NgArray<int> locrots;\n    NgArray<double> lochs;\n    NgArray<Point<3> > loc_pnts2, loc_pnts3;\n  // static int locerr2;\n    double locmetricweight;\n    double loch;\n    int surfi, surfi2;\n    int uselocalh;\n  public:\n    Opti2dLocalData ()\n    {\n      locmetricweight = 0;\n    }\n  };\n\n\n  class Opti2SurfaceMinFunction : public MinFunction\n  {\n    Opti2dLocalData & ld;\n    const NetgenGeometry& geo;\n  public:\n    Opti2SurfaceMinFunction (const Mesh & amesh,\n\t\t\t     Opti2dLocalData & ald)\n      : ld(ald), geo(*amesh.GetGeometry())\n    { } ;\n\n\n    virtual double Func (const Vector & x) const override\n    {\n      double badness = 0;\n      \n      auto n = geo.GetNormal(ld.surfi, ld.sp1, &ld.gi1);\n      Point<3> pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n      \n      for (int j = 0; j < ld.locelements.Size(); j++)\n        {\n          Vec<3> e1 = ld.loc_pnts2[j] - pp1;\n          Vec<3> e2 = ld.loc_pnts3[j] - pp1;\n          \n          if (ld.uselocalh) ld.loch = ld.lochs[j];\n          \n          if (Determinant(e1, e2, n) > 1e-8 * ld.loch * ld.loch)\n            {\n              badness += CalcTriangleBadness (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j],\n                                              ld.locmetricweight, ld.loch);\n            }\n          else\n            {\n              badness += 1e8;\n            }\n        }\n      \n      return badness;\n    }\n\n\n    virtual double FuncGrad (const Vector & x, Vector & g) const override\n    {\n      Vec<3> vgrad;\n      Point<3> pp1;\n      \n      vgrad = 0;\n      double badness = 0;\n      \n      pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n      \n      for (int j = 0; j < ld.locelements.Size(); j++)\n        {\n          Vec<3> e1 = ld.loc_pnts2[j] - pp1;\n          Vec<3> e2 = ld.loc_pnts3[j] - pp1;\n          \n          if (ld.uselocalh) ld.loch = ld.lochs[j];\n          \n          if (Determinant(e1, e2, ld.normal) > 1e-8 * ld.loch * ld.loch)\n            {\n              Vec<3> hgrad;\n              badness += \n                CalcTriangleBadnessGrad (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j], hgrad,\n                                         ld.locmetricweight, ld.loch);\n              vgrad += hgrad;\n            }\n          else\n            {\n              badness += 1e8;\n            }\n        }\n      g(0) = ld.t1 * vgrad;\n      g(1) = ld.t2 * vgrad;\n      return badness;\n    }\n\n    virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const override\n    {\n      deriv = 0;\n      double badness = 0;\n      \n      Point<3> pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n      Vec<3> dir3d = dir(0) * ld.t1 + dir(1) * ld.t2;\n      \n      for (int j = 0; j < ld.locelements.Size(); j++)\n        {\n          Vec<3> e1 = ld.loc_pnts2[j] - pp1;\n          Vec<3> e2 = ld.loc_pnts3[j] - pp1;\n          \n          if (ld.uselocalh) ld.loch = ld.lochs[j];\n          \n          if (Determinant(e1, e2, ld.normal) > 1e-8 * ld.loch * ld.loch)\n            {\n              Vec<3> hgrad;\n              badness += \n                CalcTriangleBadnessGrad (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j], hgrad,\n                                         ld.locmetricweight, ld.loch);\n              deriv += dir3d * hgrad;\n            }\n          else\n            {\n              badness += 1e8;\n            }\n        }\n      \n      // cout << \"deriv = \" << deriv << \" =?= \";\n      return badness;\n      /*\n      static int timer = NgProfiler::CreateTimer (\"opti2surface - deriv\");\n      NgProfiler::RegionTimer reg (timer);\n\n      double eps = 1e-6;\n      Vector xr(2), xl(2);\n      xr = x; xl = x;\n      for (int i = 0; i < 2; i++)\n        {\n          xr(i) = x(i) + eps * dir(i);\n          xl(i) = x(i) - eps * dir(i);\n        }\n      deriv = (Func (xr) - Func(xl) ) / (2*eps); \n      cout << deriv << endl;\n      return Func(x);\n      */\n    }\n\n\n\n    virtual double XXFuncGrad (const Vector & x, Vector & g) const;\n    virtual double XXFuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n\n  };\n\n  \n  /*\n  double Opti2SurfaceMinFunction :: \n  Func (const Vector & x) const\n  {\n    static int timer = NgProfiler::CreateTimer (\"opti2surface - func\");\n    NgProfiler::RegionTimer reg (timer);\n\n    Vector g(x.Size());\n    return FuncGrad (x, g);\n  }\n  */\n\n  double Opti2SurfaceMinFunction :: \n  XXFuncGrad (const Vector & x, Vector & grad) const\n  {\n    // static int timer = NgProfiler::CreateTimer (\"opti2surface - funcgrad\");\n    // NgProfiler::RegionTimer reg (timer);\n\n    Vec<3> vgrad;\n    Point<3> pp1;\n\n    vgrad = 0;\n    double badness = 0;\n\n    auto n = geo.GetNormal(ld.surfi, ld.sp1, &ld.gi1);\n    pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n\n    //  meshthis -> ProjectPoint (surfi, pp1);\n    // meshthis -> GetNormalVector (surfi, pp1, n);\n\n    for (int j = 0; j < ld.locelements.Size(); j++)\n      {\n        double g1x, g1y, hbadness;\n\n        Vec<3> e1 = ld.loc_pnts2[j] - pp1;\n        Vec<3> e2 = ld.loc_pnts3[j] - pp1;\n\n\tif (ld.uselocalh) ld.loch = ld.lochs[j];\n\n\tdouble e1l = e1.Length();\n\tif (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length())\n\t  {\n\t    e1 /= e1l;\n\t    double e1e2 = e1 * e2;\n            e2 -= e1e2 * e1;\n\t    double e2l = e2.Length();\n\n            CalcTriangleBadness ( e1l, e1e2, e2l, ld.locmetricweight, ld.loch,\n                                  hbadness, g1x, g1y);\n            \n\t    badness += hbadness;\n            vgrad += g1x * e1 + (g1y/e2l) * e2;\n\t  }\n\telse\n\t  {\n\t    // (*testout) << \"very very bad badness\" << endl;\n\t    badness += 1e8;\n\t  }\n      }\n\n    // vgrad -=  (vgrad * n) * n;\n    grad(0) = vgrad * ld.t1;\n    grad(1) = vgrad * ld.t2;\n    return badness;\n  }\n\n\n  double Opti2SurfaceMinFunction :: \n  XXFuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n  {\n    // static int timer = NgProfiler::CreateTimer (\"opti2surface - funcderiv\");\n    // NgProfiler::RegionTimer reg (timer);\n\n    Vec<3> vgrad;\n    Point<3> pp1;\n\n    vgrad = 0;\n    double badness = 0;\n\n    auto n = geo.GetNormal(ld.surfi, ld.sp1, &ld.gi1);\n    pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n\n    for (int j = 0; j < ld.locelements.Size(); j++)\n      {\n        double g1x, g1y, hbadness;\n\n        /*\n        int roti = ld.locrots[j];\n        const Element2d & bel = mesh[ld.locelements[j]];\n\tVec<3> e1 = mesh[bel.PNumMod(roti + 1)] - pp1;\n\tVec<3> e2 = mesh[bel.PNumMod(roti + 2)] - pp1;\n        */\n        Vec<3> e1 = ld.loc_pnts2[j] - pp1;\n        Vec<3> e2 = ld.loc_pnts3[j] - pp1;\n\tif (ld.uselocalh) ld.loch = ld.lochs[j];\n\n\tdouble e1l = e1.Length();\n\tif (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length())\n\t  {\n\t    e1 /= e1l;\n\t    double e1e2 = e1 * e2;\n\t    e2 -= e1e2 * e1;\n\t    double e2l = e2.Length();\n\t    CalcTriangleBadness ( e1l, e1e2, e2l, ld.locmetricweight, ld.loch,\n\t\t\t\t  hbadness, g1x, g1y);\n\n\t    badness += hbadness;\n            vgrad += g1x * e1 + (g1y / e2l) * e2;\n\t  }\n\telse\n\t  {\n\t    // (*testout) << \"very very bad badness\" << endl;\n\t    badness += 1e8;\n\t  }\n      }\n\n    // vgrad -= (vgrad * n) * n;\n    deriv = dir(0) * (vgrad*ld.t1) + dir(1) * (vgrad*ld.t2);\n\n    return badness;\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  class Opti2EdgeMinFunction : public MinFunction\n  {\n    const Mesh & mesh;\n    Opti2dLocalData & ld;\n    const NetgenGeometry& geo;\n\n  public:\n    Opti2EdgeMinFunction (const Mesh & amesh,\n\t\t\t  Opti2dLocalData & ald)\n      : mesh(amesh), ld(ald), geo(*amesh.GetGeometry()) { } ;\n\n    virtual double FuncGrad (const Vector & x, Vector & g) const override;\n    virtual double Func (const Vector & x) const override;\n  };\n\n  double Opti2EdgeMinFunction :: Func (const Vector & x) const\n  {\n    Vector g(x.Size());\n    return FuncGrad (x, g);\n  }\n\n  double Opti2EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const\n  {\n    int j, rot;\n    Vec<3> v1, v2, e1, e2, vgrad;\n    Point<3> pp1;\n    Vec<2> g1;\n    double badness, hbadness;\n\n    vgrad = 0.0;\n    badness = 0;\n\n    pp1 = ld.sp1 + x(0) * ld.t1;\n    geo.ProjectPointEdge(ld.surfi, ld.surfi2, pp1);\n\n    for (j = 0; j < ld.locelements.Size(); j++)\n      {\n\trot = ld.locrots[j];\n\tconst Element2d & bel = mesh[ld.locelements[j]];\n\n\tv1 = mesh[bel.PNumMod(rot + 1)] - pp1;\n\tv2 = mesh[bel.PNumMod(rot + 2)] - pp1;\n\n\te1 = v1;\n\te2 = v2;\n\te1 /= e1.Length();\n\te2 -= (e1 * e2) * e1;\n\te2 /= e2.Length();\n\n\tif (ld.uselocalh) ld.loch = ld.lochs[j];\n\tCalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), ld.locmetricweight, ld.loch,\n\t\t\t      hbadness, g1(0), g1(1));\n\n\tbadness += hbadness;\n        vgrad += g1(0) * e1 + g1(1) * e2;\n      }\n\n    auto n1 = geo.GetNormal(ld.surfi, pp1);\n    auto n2 = geo.GetNormal(ld.surfi2, pp1);\n\n    v1 = Cross (n1, n2);\n    v1.Normalize();\n\n    grad(0) = (vgrad * v1) * (ld.t1 * v1);\n\n    return badness;\n  }\n\n\n\n\n  class Opti2SurfaceMinFunctionJacobian : public MinFunction\n  {\n    const Mesh & mesh;\n    Opti2dLocalData & ld;\n    const NetgenGeometry& geo;\n\n  public:\n    Opti2SurfaceMinFunctionJacobian (const Mesh & amesh,\n\t\t\t\t     Opti2dLocalData & ald)\n      : mesh(amesh), ld(ald), geo(*amesh.GetGeometry())\n    { } ;\n    virtual double FuncGrad (const Vector & x, Vector & g) const override;\n    virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const override;\n    virtual double Func (const Vector & x) const override;\n  };\n  \n  double Opti2SurfaceMinFunctionJacobian :: \n  Func (const Vector & x) const\n  {\n    Vector g(x.Size());\n    return FuncGrad (x, g);\n  }\n\n\n  double Opti2SurfaceMinFunctionJacobian :: \n  FuncGrad (const Vector & x, Vector & grad) const\n  {\n    // from 2d:\n\n    int lpi, gpi;\n    Vec<3> vgrad;\n    Point<3> pp1;\n    Vec<2> g1, vdir;\n    double badness, hbad, hderiv;\n\n    vgrad = 0;\n    badness = 0;\n\n    // auto n = geo.GetNormal(ld.surfi, ld.sp1, &ld.gi1);\n\n    pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n\n    //  meshthis -> ProjectPoint (surfi, pp1);\n    //  meshthis -> GetNormalVector (surfi, pp1, n);\n\n    static NgArray<Point<2>> pts2d;  // better: use hashtable\n    pts2d.SetSize(mesh.GetNP());\n\n    grad = 0;\n\n    for (int j = 1; j <= ld.locelements.Size(); j++)\n      {\n\tlpi = ld.locrots.Get(j);\n\tconst Element2d & bel = \n\t  mesh[ld.locelements.Get(j)];\n      \n\tgpi = bel.PNum(lpi);\n\n\tfor (int k = 1; k <= bel.GetNP(); k++)\n\t  {\n\t    PointIndex pi = bel.PNum(k);\n\t    pts2d.Elem(pi) = Point2d (ld.t1 * (mesh.Point(pi) - ld.sp1), \n\t\t\t\t      ld.t2 * (mesh.Point(pi) - ld.sp1)); \n\t  }\t\t\t\t    \n\tpts2d.Elem(gpi) = { x(0), x(1) };\n      \n\n\tfor (int k = 1; k <= 2; k++)\n\t  {\n\t    if (k == 1)\n\t      vdir = {1., 0.};\n\t    else\n\t      vdir = {0., 1.};\n\t  \n\t    hbad = bel.\n\t      CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv);\n            \n\t    grad(k-1) += hderiv;\n\t    if (k == 1)\n\t      badness += hbad;\n\t  }\n      }\n\n\n    /*\n      vgrad.Add (-(vgrad * n), n);\n\n      grad.Elem(1) = vgrad * t1;\n      grad.Elem(2) = vgrad * t2;\n    */\n    return badness;\n  }\n\n\n\n\n  double Opti2SurfaceMinFunctionJacobian :: \n  FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n  {\n    // from 2d:\n\n    int j, k, lpi, gpi;\n    Vec<3> vgrad;\n    Point<3> pp1;\n    Vec<2> g1, vdir;\n    double badness, hbad, hderiv;\n\n    vgrad = 0;\n    badness = 0;\n\n    // pp1 = sp1;\n    //    pp1.Add2 (x.Get(1), t1, x.Get(2), t2);\n    pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2;\n\n    static NgArray<Point<2>> pts2d;\n    pts2d.SetSize(mesh.GetNP());\n\n    deriv = 0;\n\n    for (j = 1; j <= ld.locelements.Size(); j++)\n      {\n\tlpi = ld.locrots.Get(j);\n\tconst Element2d & bel = \n\t  mesh[ld.locelements.Get(j)];\n      \n\tgpi = bel.PNum(lpi);\n\n\tfor (k = 1; k <= bel.GetNP(); k++)\n\t  {\n\t    PointIndex pi = bel.PNum(k);\n\t    pts2d.Elem(pi) = Point2d (ld.t1 * (mesh.Point(pi) - ld.sp1), \n\t\t\t\t      ld.t2 * (mesh.Point(pi) - ld.sp1)); \n\t  }\t\t\t\t    \n\tpts2d.Elem(gpi) = Point2d (x(0), x(1));\n      \n\n\tvdir = { dir(0), dir(1) };\n\t  \n\thbad = bel.\n\t  CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv);\n      \n\tderiv += hderiv;\n\tbadness += hbad;\n      }\n\n\n    return badness;\n  }\n\n  void MeshOptimize2d :: ImproveMesh (const MeshingParameters & mp)\n  {\n    static Timer timer(\"MeshSmoothing 2D\"); RegionTimer reg (timer);\n\n    PrintMessage (3, \"Smoothing\");\n\n    CheckMeshApproximation (mesh);\n\n    int ncolors;\n    Array<int> colors;\n    bool mixed = false;\n    // auto elementsonpoint = mesh.CreatePoint2SurfaceElementTable( faceindex );\n    auto elementsonpoint = mesh.CreateCompressedPoint2SurfaceElementTable( faceindex );\n    NgArray<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP());\n\n    Table<PointIndex> color_table;\n    if(faceindex)\n      {\n        Array<SurfaceElementIndex> seia;\n        mesh.GetSurfaceElementsOfFace (faceindex, seia);\n        for (auto sei : seia)\n          if (mesh[sei].GetNP() != 3)\n            {\n              mixed = true;\n              break;\n            }\n\n        Array<int, PointIndex> compress(mesh.GetNP());\n        NgArray<PointIndex> icompress;\n        for (int i = 0; i < seia.Size(); i++)\n          {\n            const Element2d & el = mesh[seia[i]];\n            for (int j = 0; j < el.GetNP(); j++)\n              compress[el[j]] = -1;\n          }\n        for (int i = 0; i < seia.Size(); i++)\n          {\n            const Element2d & el = mesh[seia[i]];\n            for (int j = 0; j < el.GetNP(); j++)\n              if (compress[el[j]] == -1)\n                {\n                  compress[el[j]] = icompress.Size();\n                  icompress.Append(el[j]);\n                }\n          }\n\n        const auto & getDofs = [&] (int i)\n          {\n            return elementsonpoint[icompress[i]];\n          };\n\n        colors.SetSize(icompress.Size());\n\n        ncolors = ngcore::ComputeColoring( colors, mesh.GetNSE(), getDofs );\n\n        TableCreator<PointIndex> creator(ncolors);\n        for ( ; !creator.Done(); creator++)\n            ParallelForRange( Range(colors), [&](auto myrange)\n                    {\n                    for(auto i : myrange)\n                    creator.Add(colors[i], icompress[i]);\n                    });\n\n        color_table = creator.MoveTable();\n      }\n    else\n      {\n        for (auto & se : mesh.SurfaceElements())\n          if (se.GetNP() != 3)\n          {\n              for(auto pi : se.PNums())\n                  if(mesh[pi].Type() == SURFACEPOINT)\n                  {\n                      mixed = true;\n                      break;\n                  }\n              if(mixed)\n                  break;\n          }\n\n        const auto & getDofs = [&] (int i)\n          {\n            return elementsonpoint[i+PointIndex::BASE];\n          };\n\n        colors.SetSize(mesh.GetNP());\n        ncolors = ngcore::ComputeColoring( colors, mesh.GetNSE(), getDofs );\n\n        TableCreator<PointIndex> creator(ncolors);\n        for ( ; !creator.Done(); creator++)\n            ParallelForRange( Range(colors), [&](auto myrange)\n                    {\n                    for(auto i : myrange)\n                    creator.Add(colors[i], PointIndex(i+PointIndex::BASE));\n                    });\n\n        color_table = creator.MoveTable();\n      }\n    \n    /*\n    int i, j, k;\n    Vector xedge(1);\n      if (improveedges)\n      for (i = 1; i <= mesh.GetNP(); i++)\n      if (mesh.PointType(i) == EDGEPOINT)\n      {\n      continue;\n      PrintDot ();\n      sp1 = mesh.Point(i);\n\t  \n      locelements.SetSize(0);\n      locrots.SetSize (0);\n      lochs.SetSize (0);\n      surfi = surfi2 = surfi3 = 0;\n\t  \n      for (j = 0; j < elementsonpoint[i].Size(); j++)\n      {\n      sei = elementsonpoint[i][j];\n      const Element2d * bel = &mesh[sei];\n\t      \n      if (!surfi)\n      surfi = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr();\n      else if (surfi != mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr())\n      {\n      if (surfi2 != 0 && surfi2 != \n      mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr())\n      surfi3 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr();\n      else\n      surfi2 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr();\n      }\n\t      \n      locelements.Append (sei);\n\t      \n      if (bel->PNum(1) == i)\n      locrots.Append (1);\n      else if (bel->PNum(2) == i)\n      locrots.Append (2);\n      else\n      locrots.Append (3);\n\n      if (uselocalh)\n      {\n      Point3d pmid = Center (mesh.Point(bel->PNum(1)),\n      mesh.Point(bel->PNum(2)),\n      mesh.Point(bel->PNum(3)));\n      lochs.Append (mesh.GetH(pmid));\n      }\n      }\n\t  \n      if (surfi2 && !surfi3)\n      {\n      Vec3d n1, n2;\n      GetNormalVector (surfi, sp1, n1);\n      GetNormalVector (surfi2, sp1, n2);\n      t1 = Cross (n1, n2);\n\t      \n      xedge = 0;\n      BFGS (xedge, edgeminf, par, 1e-6);\n\t      \n      mesh.Point(i).X() += xedge.Get(1) * t1.X();\n      mesh.Point(i).Y() += xedge.Get(1) * t1.Y();\n      mesh.Point(i).Z() += xedge.Get(1) * t1.Z();\n      ProjectPoint2 (surfi, surfi2, mesh.Point(i));\n      }\n      }\n    */\n\n\n    // NgProfiler::StopTimer (timer1);\n\n    /*\n    for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++)\n      if (mesh[pi].Type() == SURFACEPOINT)\n    */\n\n    static Timer tloop(\"MeshSmooting 2D - loop\");\n    tloop.Start();\n    for (auto icolor : Range(color_table))\n    {\n     if (multithread.terminate)\n         break;\n     ParallelForRange( Range(color_table[icolor].Size()), [&](auto myrange)\n     {\n      Opti2dLocalData ld;\n      ld.uselocalh = mp.uselocalh;\n      ld.loch = mp.maxh;\n      ld.locmetricweight = metricweight;\n      ld.meshthis = this;\n\n      Opti2SurfaceMinFunction surfminf(mesh, ld);\n      Opti2SurfaceMinFunctionJacobian surfminfj(mesh, ld);\n\n      MinFunction & minfunc = mixed ? static_cast<MinFunction&>(surfminfj) : surfminf;\n\n      OptiParameters par;\n      par.maxit_linsearch = 8;\n      par.maxit_bfgs = 5;\n      for (auto i : myrange)\n        {\n\tPointIndex pi = color_table[icolor][i];\n\tif (mesh[pi].Type() == SURFACEPOINT)\n\t  {\n\t    if (multithread.terminate)\n\t      return;\n\t    \n\t    if (elementsonpoint[pi].Size() == 0) continue;\n            \n\t    ld.sp1 = mesh[pi];\n\t    \n\t    Element2d & hel = mesh[elementsonpoint[pi][0]];\n\t    \n\t    int hpi = 0;\n\t    for (int j = 1; j <= hel.GetNP(); j++)\n\t      if (hel.PNum(j) == pi)\n\t\t{\n\t\t  hpi = j;\n\t\t  break;\n\t\t}\n\n\t    ld.gi1 = hel.GeomInfoPi(hpi);\n\t    // SelectSurfaceOfPoint (ld.sp1, ld.gi1);\n\t  \n\t    ld.locelements.SetSize(0);\n\t    ld.locrots.SetSize (0);\n\t    ld.lochs.SetSize (0);\n            ld.loc_pnts2.SetSize (0);\n            ld.loc_pnts3.SetSize (0);\n\n\t    for (int j = 0; j < elementsonpoint[pi].Size(); j++)\n\t      {\n\t\tSurfaceElementIndex sei = elementsonpoint[pi][j];\n\t\tconst Element2d & bel = mesh[sei];\n\t\tld.surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr();\n\t\t\n\t\tld.locelements.Append (sei);\n\t\t\n\t\tfor (int k = 1; k <= bel.GetNP(); k++)\n\t\t  if (bel.PNum(k) == pi)\n\t\t    {\n\t\t      ld.locrots.Append (k);\n                      ld.loc_pnts2.Append (mesh[bel.PNumMod(k + 1)]);\n                      ld.loc_pnts3.Append (mesh[bel.PNumMod(k + 2)]);\n\t\t      break;\n\t\t    }\n\t\t\n\t\tif (ld.uselocalh)\n\t\t  {\n\t\t    Point3d pmid = Center (mesh[bel[0]], mesh[bel[1]], mesh[bel[2]]);\n\t\t    ld.lochs.Append (mesh.GetH(pmid));\n\t\t  }\n\t      }\n\n\n          ld.normal = geo.GetNormal(ld.surfi, ld.sp1, &ld.gi1);\n\t  ld.t1 = ld.normal.GetNormal ();\n\t  ld.t2 = Cross (ld.normal, ld.t1);\n\t  \n          if(mixed)\n            {\n              // save points, and project to tangential plane (only for optimization with Opti2SurfaceMinFunctionJacobian in mixed element meshes)\n              for (int j = 0; j < ld.locelements.Size(); j++)\n                {\n                  const Element2d & el = mesh[ld.locelements[j]];\n                  for (int k = 0; k < el.GetNP(); k++)\n                    savepoints[el[k]] = mesh[el[k]];\n                }\n\n              for (int j = 0; j < ld.locelements.Size(); j++)\n                {\n                  const Element2d & el = mesh[ld.locelements[j]];\n                  for (int k = 0; k < el.GetNP(); k++)\n                    {\n                      PointIndex hhpi = el[k];\n                      double lam = ld.normal * (mesh[hhpi] - ld.sp1);\n                      mesh[hhpi] -= lam * ld.normal;\n                    }\n                }\n            }\n\t  \n          Vector x(2);\n\t  x = 0;\n\t  par.typx = 0.3*ld.lochs[0];\n\n          // NgProfiler::StartTimer (timer2);\n\n          BFGS (x, minfunc, par, 1e-6);\n\n          // NgProfiler::StopTimer (timer2);\n\n\t  auto origp = mesh[pi];\n\t  int loci = 1;\n\t  double fact = 1;\n\t  int moveisok = 0;\n\n          if(mixed)\n            {\n              // restore other points\n              for (int j = 0; j < ld.locelements.Size(); j++)\n                {\n                  const Element2d & el = mesh[ld.locelements[j]];\n                  for (int k = 0; k < el.GetNP(); k++)\n                    {\n                      PointIndex hhpi = el[k];\n                      if (hhpi != pi) mesh[hhpi] = savepoints[hhpi];\n                    }\n                }\n            }\n\n\t  \n\t  //optimizer loop (if whole distance is not possible, move only a bit!!!!)\n\t  while (loci <= 5 && !moveisok)\n\t    {\n\t      loci ++;\n              /*\n\t      mesh[pi].X() = origp.X() + (x.Get(1) * t1.X() + x.Get(2) * t2.X())*fact;\n\t      mesh[pi].Y() = origp.Y() + (x.Get(1) * t1.Y() + x.Get(2) * t2.Y())*fact;\n\t      mesh[pi].Z() = origp.Z() + (x.Get(1) * t1.Z() + x.Get(2) * t2.Z())*fact;\n              */\n              Vec<3> hv = x(0) * ld.t1 + x(1) * ld.t2;\n              Point3d hnp = origp + Vec3d (hv);\n              mesh[pi](0) = hnp.X();\n              mesh[pi](1) = hnp.Y();\n              mesh[pi](2) = hnp.Z();\n\n\t      fact = fact/2.;\n\n\t      // ProjectPoint (surfi, mesh[pi]);\n\t      // moveisok = CalcPointGeomInfo(surfi, ngi, mesh[pi]); \n\n\t      PointGeomInfo ngi;\n\t      ngi = ld.gi1;\n\t      moveisok = geo.ProjectPointGI(ld.surfi, mesh[pi], ngi);\n\t      // point lies on same chart in stlsurface\n\t    \n\t      if (moveisok)\n\t\t{\n\t\t  for (int j = 0; j < ld.locelements.Size(); j++)\n\t\t    mesh[ld.locelements[j]].GeomInfoPi(ld.locrots[j]) = ngi;\n\t\t}\n\t      else\n\t\t{\n\t\t  mesh[pi] = origp;\n\t\t}\n\t    \n\t    }\n          }\n        }\n      }, mixed ? 1 : ngcore::TasksPerThread(4)); // mixed element smoothing not parallel yet\n    }\n\n    tloop.Stop();\n    CheckMeshApproximation (mesh);\n    mesh.SetNextTimeStamp();\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/smoothing3.cpp",
    "content": "#include <mystdlib.h>\n\n#include \"meshing.hpp\"\n#ifdef SOLIDGEOM\n#include <csg.hpp>\n#endif\n#include <opti.hpp>\n#include <core/array.hpp>\n#include <core/taskmanager.hpp>\n\n\nnamespace netgen\n{\n  using namespace ngcore;\n  \n\n  double MinFunctionSum :: Func (const Vector & x) const\n  {\n    double retval = 0;\n    for(int i=0; i<functions.Size(); i++)\n      retval += functions[i]->Func(x);\n      \n    return retval;\n  }\n\n  void MinFunctionSum :: Grad (const Vector & x, Vector & g) const\n  {\n    g = 0.;\n    VectorMem<3> gi;\n    for(int i=0; i<functions.Size(); i++)\n      {\n\tfunctions[i]->Grad(x,gi);\n\tfor(int j=0; j<g.Size(); j++)\n\t  g[j] += gi[j];\n      }\n  }\n      \n\n  double MinFunctionSum :: FuncGrad (const Vector & x, Vector & g) const\n  {\n    double retval = 0;\n    g = 0.;\n    VectorMem<3> gi;\n    for(int i=0; i<functions.Size(); i++)\n      {\n\tretval += functions[i]->FuncGrad(x,gi);\n\tfor(int j=0; j<g.Size(); j++)\n\t  g[j] += gi[j];\n      }\n    return retval;\n  }\n\n  double MinFunctionSum :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n  {\n    double retval = 0;\n    deriv = 0.;\n    double derivi;\n    for(int i=0; i<functions.Size(); i++)\n      {\n\tretval += functions[i]->FuncDeriv(x,dir,derivi);\n\tderiv += derivi;\n      }\n    return retval;\n  }\n\n  double MinFunctionSum :: GradStopping (const Vector & x) const\n  {\n    double minfs(0), mini;\n    for(int i=0; i<functions.Size(); i++)\n      {\n\tmini = functions[i]->GradStopping(x);\n\tif(i==0 || mini < minfs)\n\t  minfs = mini;\n      }\n    return minfs;\n  }\n\n\n  void MinFunctionSum :: AddFunction(MinFunction & fun)\n  {\n    functions.Append(&fun);\n  }\n  \n  const MinFunction & MinFunctionSum :: Function(int i) const\n  {\n    return *functions[i];\n  }\n  MinFunction & MinFunctionSum :: Function(int i)\n  {\n    return *functions[i];\n  }\n\n  PointFunction1 :: PointFunction1 (Mesh::T_POINTS & apoints, \n\t\t\t\t    const NgArray<PointIndices<3>> & afaces,\n\t\t\t\t    const MeshingParameters & amp,\n\t\t\t\t    double ah)\n    : points(apoints), faces(afaces), mp(amp)\n  {\n    h = ah;\n  }\n  \n\n  double PointFunction1 :: Func (const Vector & vp) const\n  {\n    double badness = 0;\n    Point<3> pp(vp(0), vp(1), vp(2));\n\n    for (int j = 0; j < faces.Size(); j++)\n      {\n\tconst INDEX_3 & el = faces[j];\n\n\tdouble bad = CalcTetBadness (points[PointIndex (el.I1())], \n\t\t\t\t     points[PointIndex (el.I3())], \n\t\t\t\t     points[PointIndex (el.I2())], \n\t\t\t\t     pp, 0, mp);\n\tbadness += bad;\n      }\n \n    return badness;\n  }\n\n\n  double PointFunction1 :: \n  FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n  {\n    VectorMem<3> hx;\n    const double eps = 1e-6;\n\n    double dirlen = dir.L2Norm();\n    if (dirlen < 1e-14)\n      {\n\tderiv = 0;\n\treturn Func(x);\n      }\n\n    hx.Set(1, x);\n    hx.Add(eps * h / dirlen, dir);\n    double fr = Func (hx);\n    hx.Set(1, x);\n    hx.Add(-eps * h / dirlen, dir);\n    double fl = Func (hx);\n\n    deriv = (fr - fl) / (2 * eps * h) * dirlen;\n\n    return Func(x);\n  }\n\n\n  double PointFunction1 :: FuncGrad (const Vector & x, Vector & g) const\n  {\n    VectorMem<3> hx;\n    double eps = 1e-6;\n\n    hx = x;\n    for (int i = 0; i < 3; i++)\n      {\n\thx(i) = x(i) + eps * h;\n\tdouble fr = Func (hx);\n\thx(i) = x(i) - eps * h;\n\tdouble fl = Func (hx);\n\thx(i) = x(i);\n\n\tg(i) = (fr - fl) / (2 * eps * h);\n      }\n\n    return Func(x);\n  }\n\n  double PointFunction1 :: GradStopping (const Vector & x) const\n  {\n    double f = Func(x);\n    return 1e-8 * f * f;\n  }\n\n\n  /* Cheap Functional depending of inner point inside triangular surface */\n\n  // is it used ????\n  class CheapPointFunction1 : public MinFunction\n  {\n    Mesh::T_POINTS & points;\n    const NgArray<INDEX_3> & faces;\n    DenseMatrix m;\n    double h;\n  public:\n    CheapPointFunction1 (Mesh::T_POINTS & apoints, \n\t\t\t const NgArray<INDEX_3> & afaces,\n\t\t\t double ah);\n  \n    virtual double Func (const Vector & x) const;\n    virtual double FuncGrad (const Vector & x, Vector & g) const;\n  };\n\n  CheapPointFunction1 :: CheapPointFunction1 (Mesh::T_POINTS & apoints, \n\t\t\t\t\t      const NgArray<INDEX_3> & afaces,\n\t\t\t\t\t      double ah)\n    : points(apoints), faces(afaces)\n  {\n    h = ah;\n  \n\n    int nf = faces.Size();\n\n    m.SetSize (nf, 4);\n  \n    for (int i = 1; i <= nf; i++)\n      {\n\tconst Point3d & p1 = points[PointIndex(faces.Get(i).I1())];\n\tconst Point3d & p2 = points[PointIndex(faces.Get(i).I2())];\n\tconst Point3d & p3 = points[PointIndex(faces.Get(i).I3())];\n\tVec3d v1 (p1, p2);\n\tVec3d v2 (p1, p3);\n\tVec3d n;\n\tCross (v1, v2, n);\n\tn /= n.Length();\n\n\tm.Elem(i, 1) = n.X();\n\tm.Elem(i, 2) = n.Y();\n\tm.Elem(i, 3) = n.Z();\n\tm.Elem(i, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z());\n      } \n  }\n  \n  double CheapPointFunction1 :: Func (const Vector & vp) const\n  {\n\n    /*\n      int j;\n      double badness = 0;\n      Point3d pp(vp.Get(1), vp.Get(2), vp.Get(3));\n\n      for (j = 1; j <= faces.Size(); j++)\n      {\n      const INDEX_3 & el = faces.Get(j);\n\n      double bad = CalcTetBadness (points.Get(el.I1()), \n      points.Get(el.I3()), \n      points.Get(el.I2()), \n      pp, 0);\n      badness += bad;\n      }\n    */\n\n    int i;\n    double badness = 0;\n    VectorMem<4> hv;\n    Vector res(m.Height());\n\n    for (i = 0;i < 3; i++)\n      hv(i) = vp(i);\n    hv(3) = 1;\n    m.Mult (hv, res);\n\n    for (i = 1; i <= res.Size(); i++)\n      {\n\tif (res(i-1) < 1e-10)\n\t  badness += 1e24;\n\telse\n\t  badness += 1 / res(i-1);\n      }\n \n    return badness;\n  }\n\n\n  double CheapPointFunction1 :: FuncGrad (const Vector & x, Vector & g) const\n  {\n    VectorMem<3> hx;\n    double eps = 1e-6;\n\n    hx = x;\n    for (int i = 0; i < 3; i++)\n      {\n\thx(i) = x(i) + eps * h;\n\tdouble fr = Func (hx);\n\thx(i) = x(i) - eps * h;\n\tdouble fl = Func (hx);\n\thx(i) = x(i);\n\n\tg(i) = (fr - fl) / (2 * eps * h);\n      }\n\n    return Func(x);\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  /* ************* PointFunction **************************** */\n\n\n  class PointFunction \n  {\n  public:\n    Mesh::T_POINTS & points;\n    const Array<Element, ElementIndex> & elements;\n    Table<ElementIndex, PointIndex> &elementsonpoint;\n    bool own_elementsonpoint;\n    const MeshingParameters & mp;\n    PointIndex actpind;\n    double h;\n  \n  public:\n    PointFunction (Mesh & mesh, const MeshingParameters & amp);\n    PointFunction (const PointFunction & pf);\n    virtual ~PointFunction () { if(own_elementsonpoint) delete &elementsonpoint; }\n    virtual void SetPointIndex (PointIndex aactpind);\n    void SetLocalH (double ah) { h = ah; }\n    double GetLocalH () const { return h; }\n    const Table<ElementIndex, PointIndex> & GetPointToElementTable() { return elementsonpoint; };\n    virtual double PointFunctionValue (const Point<3> & pp) const;\n    virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const;\n    virtual double PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir, double & deriv) const;\n\n    int MovePointToInner ();\n  };\n\n\n  PointFunction :: PointFunction (const PointFunction & pf)\n    : points(pf.points), elements(pf.elements), elementsonpoint(pf.elementsonpoint), own_elementsonpoint(false), mp(pf.mp)\n  { }\n\n  PointFunction :: PointFunction (Mesh & mesh, const MeshingParameters & amp)\n    : points(mesh.Points()), elements(mesh.VolumeElements()), elementsonpoint(* new Table<ElementIndex,PointIndex>()), own_elementsonpoint(true), mp(amp)\n  {\n    static Timer tim(\"PointFunction - build elementsonpoint table\"); RegionTimer reg(tim);\n\n    Array<bool, PointIndex> non_tet_points(points.Size());\n    non_tet_points = false;\n    // Don't optimize if point is adjacent to a non-tet element\n    ParallelForRange(elements.Range(), [&] (auto myrange)\n        {\n          for(auto ei : myrange)\n            {\n              const auto & el = elements[ei];\n              if(el.NP()!=4)\n                for(auto pi : el.PNums())\n                  non_tet_points[pi] = true;\n            }\n       });\n\n    elementsonpoint = ngcore::CreateSortedTable<ElementIndex, PointIndex>( elements.Range(),\n               [&](auto & table, ElementIndex ei)\n               {\n                 const auto & el = elements[ei];\n\n                 if(el.NP()!=4 || (mp.only3D_domain_nr && mp.only3D_domain_nr != el.GetIndex()) )\n                   return;\n\n                 for (PointIndex pi : el.PNums())\n                   if(!non_tet_points[pi])\n                     table.Add (pi, ei);\n               }, points.Size());\n  }\n\n  void PointFunction :: SetPointIndex (PointIndex aactpind)\n  {\n    actpind = aactpind; \n  }  \n\n  double PointFunction :: PointFunctionValue (const Point<3> & pp) const\n  {\n    double badness;\n    Point<3> hp;\n\n    badness = 0;\n\n    hp = points[actpind];\n    points[actpind] = Point<3> (pp);\n\n    for (auto ei : elementsonpoint[actpind])\n      {\n        const Element & el = elements[ei];\n\tbadness += CalcTetBadness (points[el[0]], points[el[1]], \n\t\t\t\t   points[el[2]], points[el[3]], -1, mp);\n      }\n  \n    points[actpind] = Point<3> (hp); \n    return badness;\n  }\n\n\n  double PointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const\n  {\n    double f = 0;\n\n    Point<3> hp = points[actpind];\n    Vec<3> vgradi, vgrad(0,0,0);\n    points[actpind] = Point<3> (pp);\n\n    for (auto ei : elementsonpoint[actpind])\n      {\n        const Element & el = elements[ei];\n\tfor (int k = 0; k < 4; k++)\n\t  if (el[k] == actpind)\n\t    {\n\t      f += CalcTetBadnessGrad (points[el[0]], points[el[1]], \n                                       points[el[2]], points[el[3]], \n                                       -1, k+1, vgradi, mp);\n\n              vgrad += vgradi;\n\t    }\n      }\n\n    points[actpind] = Point<3> (hp); \n\n    grad = vgrad;\n    return f;\n  }\n\n\n  double PointFunction :: PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir,\n\t\t\t\t\t\t   double & deriv) const\n  {\n    Vec<3> vgradi, vgrad(0,0,0);\n\n    Point<3> hp = points[actpind];\n    points[actpind] = pp;\n    double f = 0;\n\n    for (auto ei : elementsonpoint[actpind])\n      {\n        const Element & el = elements[ei];\n\n\tfor (int k = 1; k <= 4; k++)\n\t  if (el.PNum(k) == actpind)\n\t    {\n\t      f += CalcTetBadnessGrad (points[el.PNum(1)], \n\t\t\t\t       points[el.PNum(2)], \n\t\t\t\t       points[el.PNum(3)], \n\t\t\t\t       points[el.PNum(4)], -1, k, vgradi, mp);\n\n\t      vgrad += vgradi;\n\t    }\n      }\n\n    points[actpind] = Point<3> (hp); \n    deriv = dir * vgrad;\n    return f;\n  }\n\n  int PointFunction :: MovePointToInner ()\n  {\n    // try point movement \n    NgArray<Element2d> faces;\n  \n    for (auto ei : elementsonpoint[actpind])\n      {\n        const Element & el = elements[ei];\n      \n\tfor (int k = 1; k <= 4; k++)\n\t  if (el.PNum(k) == actpind)\n\t    {\n\t      Element2d face(TRIG);\n\t      el.GetFace (k, face);\n\t      Swap (face.PNum(2), face.PNum(3));\n\t      faces.Append (face);\n\t    }\n      }\n  \n    Point3d hp;\n    int hi = FindInnerPoint (points, faces, hp);\n    if (hi)\n      {\n\t// cout << \"inner point found\" << endl;\n\tpoints[actpind] = Point<3> (hp);\n      }\n    else\n      ;\n    //      cout << \"no inner point found\" << endl;\n\n    /*\n    Point3d hp2;\n    int hi2 = FindInnerPoint (points, faces, hp2);\n    if (hi2)\n      {\n\tcout << \"new: inner point found\" << endl;\n      }\n    else\n      cout << \"new: no inner point found\" << endl;\n  \n    (*testout) << \"hi(orig) = \" << hi << \", hi(new) = \" << hi2;\n    if (hi != hi2) (*testout) << \"hi different\" << endl;\n    */\n\n    return hi;\n  }\n\n\n\n\n\n\n  class CheapPointFunction : public PointFunction\n  {\n    DenseMatrix m;\n  public:\n    CheapPointFunction (Mesh & mesh, const MeshingParameters & amp);\n    virtual void SetPointIndex (PointIndex aactpind);\n    virtual double PointFunctionValue (const Point<3> & pp) const;\n    virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const;\n  };\n\n\n  CheapPointFunction :: CheapPointFunction (Mesh & mesh, const MeshingParameters & amp)\n    : PointFunction (mesh, amp)\n  {\n    ;\n  }\n\n\n  void CheapPointFunction :: SetPointIndex (PointIndex aactpind)\n  {\n    actpind = aactpind; \n\n    int ne = elementsonpoint[actpind].Size();\n    int i, j;\n    PointIndex pi1, pi2, pi3;\n\n    m.SetSize (ne, 4);\n\n    for (i = 0; i < ne; i++)\n      {\n\tpi1 = 0;\n\tpi2 = 0;\n\tpi3 = 0;\n\n\tconst Element & el = elements[elementsonpoint[actpind][i]];\n\tfor (j = 1; j <= 4; j++)\n\t  if (el.PNum(j) != actpind)\n\t    {\n\t      pi3 = pi2;\n\t      pi2 = pi1;\n\t      pi1 = el.PNum(j);\n\t    }\n\n\tconst Point3d & p1 = points[pi1];\n\tVec3d v1 (p1, points[pi2]);\n\tVec3d v2 (p1, points[pi3]);\n\tVec3d n;\n\tCross (v1, v2, n);\n\tn /= n.Length();\n\n\tVec3d v (p1, points[actpind]);\n\tdouble c = v * n;\n      \n\tif (c < 0)\n\t  n *= -1;    \n      \n\t// n is inner normal\n\n\tm.Elem(i+1, 1) = n.X();\n\tm.Elem(i+1, 2) = n.Y();\n\tm.Elem(i+1, 3) = n.Z();\n\tm.Elem(i+1, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z());\n      }\n  }\n\n  double CheapPointFunction :: PointFunctionValue (const Point<3> & pp) const\n  {\n    VectorMem<4> p4;\n    Vector di;\n    int n = m.Height();\n\n    p4(0) = pp(0);\n    p4(1) = pp(1);\n    p4(2) = pp(2);\n    p4(3) = 1;\n\n    di.SetSize (n);\n    m.Mult (p4, di);\n  \n    double sum = 0;\n    for (int i = 0; i < n; i++)\n      {\n\tif (di(i) > 0)\n\t  sum += 1 / di(i);\n\telse\n\t  return 1e16;\n      }\n    return sum;\n  }\n\n\n\n\n  double CheapPointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const\n  {\n    VectorMem<4> p4;\n    Vector di;\n\n    int n = m.Height();\n\n    p4(0) = pp(0);\n    p4(1) = pp(1);\n    p4(2) = pp(2);\n    p4(3) = 1;\n\n    di.SetSize (n);\n    m.Mult (p4, di);\n  \n    double sum = 0;\n    grad = 0;\n    for (int i = 0; i < n; i++)\n      {\n\tif (di(i) > 0)\n\t  {\n\t    double idi = 1 / di(i);\n\t    sum += idi;\n\t    grad(0) -= idi * idi * m(i, 0);\n\t    grad(1) -= idi * idi * m(i, 1);\n\t    grad(2) -= idi * idi * m(i, 2);\n\t  }\n\telse\n\t  {\n\t    return 1e16;\n\t  }\n      }\n    return sum;\n  }\n\n\n\n\n\n\n\n\n  class Opti3FreeMinFunction : public MinFunction\n  { \n    const PointFunction & pf;\n    Point<3> sp1;\n  \n  public:\n    Opti3FreeMinFunction (const PointFunction & apf);\n    void SetPoint (const Point<3> & asp1) { sp1 = asp1; }\n    virtual double Func (const Vector & x) const;\n    virtual double FuncGrad (const Vector & x, Vector & g) const;\n    virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;  \n    virtual double GradStopping (const Vector & x) const;\n    virtual void ApproximateHesse (const Vector & x,\n\t\t\t\t   DenseMatrix & hesse) const;\n  };\n\n  Opti3FreeMinFunction :: Opti3FreeMinFunction (const PointFunction & apf)\n    : pf(apf)\n  {\n    ;\n  }\n\n  double Opti3FreeMinFunction :: Func (const Vector & x) const\n  {\n    Point<3> pp;\n    for (int j = 0; j < 3; j++)\n      pp(j) = sp1(j) + x(j);\n    return pf.PointFunctionValue (pp);\n  }\n  \n  double Opti3FreeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const\n  {\n    Vec<3> vgrad;\n    Point<3> pp;\n\n    for (int j = 0; j < 3; j++)\n      pp(j) = sp1(j) + x(j);\n\n    double val = pf.PointFunctionValueGrad (pp, vgrad);\n\n    for (int j = 0; j < 3; j++)\n      grad(j) = vgrad(j);\n\n    return val;\n  }\n\n  double Opti3FreeMinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n  {\n    Point<3> pp;\n\n    for (int j = 0; j < 3; j++)\n      pp(j) = sp1(j) + x(j);\n\n    Vec<3> vdir;\n    for (int j = 0; j < 3; j++)\n      vdir(j) = dir(j);\n\n    return pf.PointFunctionValueDeriv (pp, vdir, deriv);\n  }\n  \n  double Opti3FreeMinFunction :: GradStopping (const Vector & x) const\n  {\n    double f = Func(x);\n    return 1e-3 * f / pf.GetLocalH();\n  }\n\n\n  void Opti3FreeMinFunction :: ApproximateHesse (const Vector & x,\n\t\t\t\t\t\t DenseMatrix & hesse) const\n  {\n    int n = x.Size();\n\n    Vector hx;\n    hx.SetSize(n);\n\n    double eps = 1e-8;\n    double f, f11, f22; //, f12, f21\n\n    f = Func(x);\n  \n    for (int i = 1; i <= n; i++)\n      {\n\tfor (int j = 1; j < i; j++)\n\t  {\n\t    /*\n\t      hx = x;\n\t      hx.Elem(i) = x.Get(i) + eps;\n\t      hx.Elem(j) = x.Get(j) + eps;\n\t      f11 = Func(hx);\n\t      hx.Elem(i) = x.Get(i) + eps;\n\t      hx.Elem(j) = x.Get(j) - eps;\n\t      f12 = Func(hx);\n\t      hx.Elem(i) = x.Get(i) - eps;\n\t      hx.Elem(j) = x.Get(j) + eps;\n\t      f21 = Func(hx);\n\t      hx.Elem(i) = x.Get(i) - eps;\n\t      hx.Elem(j) = x.Get(j) - eps;\n\t      f22 = Func(hx);\n\t    */\n\t    hesse.Elem(i, j) = hesse.Elem(j, i) = 0;\n\t    //\t    (f11 + f22 - f12 - f21) / (2 * eps * eps);\n\t  }\n\n\thx = x;\n\thx(i-1) = x(i-1) + eps;\n\tf11 = Func(hx);\n\thx(i-1) = x(i-1) - eps;\n\tf22 = Func(hx);\n\n\thesse.Elem(i, i) = (f11 + f22 - 2 * f) / (eps * eps) + 1e-12;\n      }\n  }\n\n\n\n\n\n\n#ifdef SOLIDGEOM\n  class Opti3SurfaceMinFunction : public MinFunction\n  {\n    const PointFunction & pf;\n    Point3d sp1;\n    const Surface * surf;\n    Vec3d t1, t2;\n  \n  public:\n    Opti3SurfaceMinFunction (const PointFunction & apf);\n  \n    void SetPoint (const Surface * asurf, const Point3d & asp1);\n\n    void CalcNewPoint (const Vector & x, Point3d & np) const; \n    virtual double Func (const Vector & x) const;\n    virtual double FuncGrad (const Vector & x, Vector & g) const;\n  };\n\n\n  Opti3SurfaceMinFunction :: Opti3SurfaceMinFunction (const PointFunction & apf)\n    : MinFunction(), pf(apf)\n  {\n    ;\n  }\n\n  void Opti3SurfaceMinFunction :: SetPoint (const Surface * asurf, const Point3d & asp1)\n  { \n    Vec3d n;\n    sp1 = asp1; \n    surf = asurf;\n  \n    Vec<3> hn;\n    surf -> GetNormalVector (sp1, hn);\n    n = hn;\n\n    n.GetNormal (t1);\n    t1 /= t1.Length();\n    t2 = Cross (n, t1);\n  }\n\n  \n  void Opti3SurfaceMinFunction :: CalcNewPoint (const Vector & x, \n\t\t\t\t\t\tPoint3d & np) const\n  {\n    np.X() = sp1.X() + x.Get(1) * t1.X() + x.Get(2) * t2.X();\n    np.Y() = sp1.Y() + x.Get(1) * t1.Y() + x.Get(2) * t2.Y();\n    np.Z() = sp1.Z() + x.Get(1) * t1.Z() + x.Get(2) * t2.Z();\n\n    Point<3> hnp = np;\n    surf -> Project (hnp);\n    np = hnp;\n  }\n\n\n  double Opti3SurfaceMinFunction :: Func (const Vector & x) const\n  {\n    Point3d pp1;\n\n    CalcNewPoint (x, pp1);\n    return pf.PointFunctionValue (pp1);\n  }\n\n\n\n  double Opti3SurfaceMinFunction :: FuncGrad (const Vector & x, Vector & grad) const\n  {\n    Vec3d n, vgrad;\n    Point3d pp1;\n    VectorMem<3> freegrad;\n\n    CalcNewPoint (x, pp1);\n\n    double badness = pf.PointFunctionValueGrad (pp1, freegrad);\n    vgrad.X() = freegrad.Get(1);\n    vgrad.Y() = freegrad.Get(2);\n    vgrad.Z() = freegrad.Get(3);\n\n    Vec<3> hn;\n    surf -> GetNormalVector (pp1, hn);\n    n = hn;\n\n    vgrad -= (vgrad * n) * n;\n\n    grad.Elem(1) = vgrad * t1;\n    grad.Elem(2) = vgrad * t2;\n    \n    return badness;\n  }\n#endif\n  \n  \n  \n\n\n  \n  \n  \n#ifdef SOLIDGEOM\n  class Opti3EdgeMinFunction : public MinFunction\n  {\n    const PointFunction & pf;\n    Point3d sp1;\n    const Surface *surf1, *surf2;\n    Vec3d t1;\n  \n  public:\n    Opti3EdgeMinFunction (const PointFunction & apf);\n  \n    void SetPoint (const Surface * asurf1, const Surface * asurf2,\n\t\t   const Point3d & asp1);\n    void CalcNewPoint (const Vector & x, Point3d & np) const; \n    virtual double FuncGrad (const Vector & x, Vector & g) const;\n    virtual double Func (const Vector & x) const;\n  };\n\n  Opti3EdgeMinFunction :: Opti3EdgeMinFunction (const PointFunction & apf)\n    : MinFunction(), pf(apf)\n  {\n    ;\n  }\n  \n  void Opti3EdgeMinFunction :: SetPoint (const Surface * asurf1, \n\t\t\t\t\t const Surface * asurf2, \n\t\t\t\t\t const Point3d & asp1) \n  { \n    Vec3d n1, n2;\n    sp1 = asp1; \n    surf1 = asurf1;\n    surf2 = asurf2;\n\n    Vec<3> hn1, hn2;\n    surf1 -> GetNormalVector (sp1, hn1);\n    surf2 -> GetNormalVector (sp1, hn2);\n    n1 = hn1;\n    n2 = hn2;\n    t1 = Cross (n1, n2);\n  }\n\n  void Opti3EdgeMinFunction :: CalcNewPoint (const Vector & x,\n\t\t\t\t\t     Point3d & np) const\n{\n  np.X() = sp1.X() + x.Get(1) * t1.X();\n  np.Y() = sp1.Y() + x.Get(1) * t1.Y();\n  np.Z() = sp1.Z() + x.Get(1) * t1.Z();\n  Point<3> hnp = np;\n  ProjectToEdge (surf1, surf2, hnp);\n  np = hnp;\n}   \n\ndouble Opti3EdgeMinFunction :: Func (const Vector & x) const\n{\n  Vector g(x.Size());\n  return FuncGrad (x, g);\n}\n\n\ndouble Opti3EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const\n{\n  Vec3d n1, n2, v1, vgrad;\n  Point3d pp1;\n  double badness;\n  VectorMem<3> freegrad;\n\n  CalcNewPoint (x, pp1);\n\n\n  badness = pf.PointFunctionValueGrad (pp1, freegrad);\n\n  vgrad.X() = freegrad.Get(1);\n  vgrad.Y() = freegrad.Get(2);\n  vgrad.Z() = freegrad.Get(3);\n\n  Vec<3> hn1, hn2;\n  surf1 -> GetNormalVector (pp1, hn1);\n  surf2 -> GetNormalVector (pp1, hn2);\n  n1 = hn1;\n  n2 = hn2;\n\n  v1 = Cross (n1, n2);\n  v1 /= v1.Length();\n\n  grad.Elem(1) = (vgrad * v1) * (t1 * v1);\n  return badness;\n}\n#endif\n\n\n\n\n\nint WrongOrientation (const Mesh::T_POINTS & points, const Element & el)\n{\n  const Point3d & p1 = points[el.PNum(1)];\n  const Point3d & p2 = points[el.PNum(2)];\n  const Point3d & p3 = points[el.PNum(3)];\n  const Point3d & p4 = points[el.PNum(4)];\n\n  Vec3d v1(p1, p2);\n  Vec3d v2(p1, p3);\n  Vec3d v3(p1, p4);\n  Vec3d n;\n\n  Cross (v1, v2, n);\n  double vol = n * v3;\n\n  return (vol > 0);\n}\n\n\n\n\n\n\n\n\n\n\n\n/* ************* JacobianPointFunction **************************** */\n\n\n\n\n// class JacobianPointFunction : public MinFunction\n// {\n// public:\n//   Mesh::T_POINTS & points;\n//   const NgArray<Element> & elements;\n//   TABLE<INDEX> elementsonpoint;\n//   PointIndex actpind;\n  \n// public:\n//   JacobianPointFunction (Mesh::T_POINTS & apoints, \n// \t\t\t const NgArray<Element> & aelements);\n  \n//   virtual void SetPointIndex (PointIndex aactpind);\n//   virtual double Func (const Vector & x) const;\n//   virtual double FuncGrad (const Vector & x, Vector & g) const;\n//   virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const;\n// };\n\n\nJacobianPointFunction :: \nJacobianPointFunction (Mesh::T_POINTS & apoints, \n\t\t       const Array<Element, ElementIndex> & aelements)\n  : points(apoints), elements(aelements), elementsonpoint(apoints.Size())\n{\n  for (int i = 0; i < elements.Size(); i++)\n      for (int j = 1; j <= elements[i].NP(); j++)\n          elementsonpoint.Add1 (elements[i].PNum(j), i+1);\n\n  onplane = false;\n}\n\nvoid JacobianPointFunction :: SetPointIndex (PointIndex aactpind)\n{\n  actpind = aactpind; \n}  \n\n\ndouble JacobianPointFunction :: Func (const Vector & v) const\n{\n  double badness = 0;\n\n  Point<3> hp = points[actpind];\n\n  points[actpind] = hp + Vec<3> (v(0), v(1), v(2));\n\n  if(onplane)\n    points[actpind] -= (v(0)*nv(0)+v(1)*nv(1)+v(2)*nv(2)) * nv;\n\n\n  for (auto eli : elementsonpoint[actpind])\n      badness += elements[eli].CalcJacobianBadness (points);\n  \n  points[actpind] = hp; \n\n  return badness;\n}\n\n\n\n\n\ndouble JacobianPointFunction :: \nFuncGrad (const Vector & x, Vector & g) const\n{\n  int k;\n  int lpi;\n  double badness = 0;//, hbad;\n\n  Point<3> hp = points[actpind];\n  points[actpind] = hp + Vec<3> (x(0), x(1), x(2));\n\n  if(onplane)\n    points[actpind] -= (x(0)*nv(0)+x(1)*nv(1)+x(2)*nv(2)) * nv;\n\n  Vec<3> hderiv;\n  //Vec3d vdir;\n  g.SetSize(3);\n  g = 0;\n\n  for (auto ei : elementsonpoint[actpind])\n    {\n      const Element & el = elements[ei];\n\n      lpi = 0;\n      for (k = 1; k <= el.GetNP(); k++)\n\tif (el.PNum(k) == actpind)\n\t  lpi = k;\n      if (!lpi) cerr << \"loc point not found\" << endl;\n\n      badness += elements[ei].\n\tCalcJacobianBadnessGradient (points, lpi, hderiv);\n\n      for(k=0; k<3; k++)\n\tg(k) += hderiv(k);\n\t\n      /*\n      for (k = 1; k <= 3; k++)\n\t{\n\t  vdir = Vec3d(0,0,0);\n\t  vdir.X(k) = 1;\n\n\t  hbad = elements.Get(eli).\n\t    CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv);\n\t  //(*testout) << \"hderiv \" << k << \": \" << hderiv << endl;\n\t  g.Elem(k) += hderiv;\n\t  if (k == 1)\n\t    badness += hbad;\n\t}\n      */\n    }\n\n  if(onplane)\n    {\n      double scal = nv(0)*g(0) + nv(1)*g(1) + nv(2)*g(2);\n      g(0) -= scal*nv(0);\n      g(1) -= scal*nv(1);\n      g(2) -= scal*nv(2);\n    }\n\n  //(*testout) << \"g = \" << g << endl;\n\n  \n  points[actpind] = hp; \n\n  return badness;\n}\n\n\ndouble JacobianPointFunction :: \nFuncDeriv (const Vector & x, const Vector & dir, double & deriv) const\n{\n  int k;\n  int lpi;\n  double badness = 0;\n\n  Point<3> hp = points[actpind];\n  points[actpind] = Point<3> (hp + Vec3d (x(0), x(1), x(2)));\n\n  if(onplane)\n    points[actpind] -= (Vec3d (x(0), x(1), x(2))*nv) * nv;\n\n  double hderiv;\n  deriv = 0;\n  Vec<3> vdir(dir(0), dir(1), dir(2));\n \n  if(onplane)\n    {\n      double scal = vdir * nv;\n      vdir -= scal*nv;\n    }\n\n  for (auto ei : elementsonpoint[actpind])\n    {\n      const Element & el = elements[ei];\n\n      lpi = 0;\n      for (k = 1; k <= el.GetNP(); k++)\n\tif (el.PNum(k) == actpind)\n\t  lpi = k;\n      if (!lpi) cerr << \"loc point not found\" << endl;\n\n      badness += elements[ei].\n\tCalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv);\n      deriv += hderiv;\n    }\n  \n  points[actpind] = hp; \n\n  return badness;\n  \n}\n\n\n\n\n\n\n\n\n\n\n#ifdef SOLIDGEOMxxxx\nvoid Mesh :: ImproveMesh (const CSG eometry & geometry, OPTIMIZEGOAL goal)\n{\n  INDEX i, eli;\n  int j;\n  int typ = 1;\n\n  if (!&geometry || geometry.GetNSurf() == 0)\n    {\n      ImproveMesh (goal);\n      return;\n    }\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Smooth Mesh\";\n\n\n  TABLE<INDEX> surfelementsonpoint(points.Size());\n  Vector x(3), xsurf(2), xedge(1);\n  int surf, surf1, surf2, surf3;\n\n  int uselocalh = mparam.uselocalh;\n\n  (*testout) << setprecision(8);\n  (*testout) << \"Improve Mesh\" << \"\\n\";\n  PrintMessage (3, \"ImproveMesh\");\n  //  (*mycout) << \"Vol = \" << CalcVolume (points, volelements) << endl;\n\n\n  for (i = 1; i <= surfelements.Size(); i++)\n    for (j = 1; j <= 3; j++)\n      surfelementsonpoint.Add1 (surfelements.Get(i).PNum(j), i);\n\n\n  PointFunction * pf;\n  if (typ == 1)\n    pf = new PointFunction(points, volelements);\n  else\n    pf = new CheapPointFunction(points, volelements);\n\n  //  pf->SetLocalH (h);\n  \n  Opti3FreeMinFunction freeminf(*pf);\n  Opti3SurfaceMinFunction surfminf(*pf);\n  Opti3EdgeMinFunction edgeminf(*pf);\n  \n  OptiParameters par;\n  par.maxit_linsearch = 20;\n  par.maxit_bfgs = 20;\n\n  int printmod = 1;\n  char printdot = '.';\n  if (points.Size() > 1000)\n    {\n      printmod = 10;\n      printdot = '+';\n    }\n  if (points.Size() > 10000)\n    {\n      printmod = 100;\n      printdot = '*';\n    }\n\n  for (i = 1; i <= points.Size(); i++)\n    {\n      //      if (ptyps.Get(i) == FIXEDPOINT) continue;\n      if (ptyps.Get(i) != INNERPOINT) continue;\n\n      if (multithread.terminate)\n\tthrow NgException (\"Meshing stopped\");\n      /*\n      if (multithread.terminate)\n\tbreak;\n      */\n      multithread.percent = 100.0 * i /points.Size();\n\n      /*\n      if (points.Size() < 1000)\n\tPrintDot ();\n      else\n\tif (i % 10 == 0)\n\t  PrintDot ('+');\n      */\n      if (i % printmod == 0) PrintDot (printdot);\n\n      //    (*testout) << \"Now point \" << i << \"\\n\";\n      //    (*testout) << \"Old: \" << points.Get(i) << \"\\n\";\n\n      pf->SetPointIndex (i);\n\n      //      if (uselocalh)\n      {\n\tdouble lh = GetH(points.Get(i), points.Get(i).GetLayer());\n\tpf->SetLocalH (lh);\n\tpar.typx = lh / 10;\n\t//\t  (*testout) << \"lh(\" << points.Get(i) << \") = \" << lh << \"\\n\";\n      }\n\n      surf1 = surf2 = surf3 = 0;\n\n      for (j = 1; j <= surfelementsonpoint.EntrySize(i); j++)\n\t{\n\t  eli = surfelementsonpoint.Get(i, j);\n\t  int surfi = surfelements.Get(eli).GetIndex();\n\n\t  if (surfi)\n\t    {\n\t      surf = GetFaceDescriptor(surfi).SurfNr();\n\t    \n\t      if (!surf1)\n\t\tsurf1 = surf;\n\t      else if (surf1 != surf)\n\t\t{\n\t\t  if (!surf2)\n\t\t    surf2 = surf;\n\t\t  else if (surf2 != surf)\n\t\t    surf3 = surf;\n\t\t}\n\t    }\n\t  else\n\t    {\n\t      surf1 = surf2 = surf3 = 1;   // simulates corner point\n\t    }\n\t}\n\n\n      if (surf2 && !surf3)\n\t{\n\t  //      (*testout) << \"On Edge\" << \"\\n\";\n\t  /*\n\t    xedge = 0;\n\t    edgeminf.SetPoint (geometry.GetSurface(surf1),\n\t    geometry.GetSurface(surf2), \n\t    points.Elem(i));\n\t    BFGS (xedge, edgeminf, par);\n\n\t    edgeminf.CalcNewPoint (xedge, points.Elem(i));\n\t  */\n\t}\n\n      if (surf1 && !surf2)\n\t{\n\t  //      (*testout) << \"In Surface\" << \"\\n\";\n\t  /*\n\t    xsurf = 0;\n\t    surfminf.SetPoint (geometry.GetSurface(surf1),\n\t    points.Get(i));\n\t    BFGS (xsurf, surfminf, par);\n   \n\t    surfminf.CalcNewPoint (xsurf, points.Elem(i));\n\t  */\n\t}\n \n      if (!surf1)\n\t{\n\t  //      (*testout) << \"In Volume\" << \"\\n\";\n\t  x = 0;\n\t  freeminf.SetPoint (points.Elem(i));\n\t  //\t  par.typx = \n\t  BFGS (x, freeminf, par);\n\n\t  points.Elem(i).X() += x.Get(1);\n\t  points.Elem(i).Y() += x.Get(2);\n\t  points.Elem(i).Z() += x.Get(3);\n\t}\n      \n      //    (*testout) << \"New Point: \" << points.Elem(i) << \"\\n\" << \"\\n\";\n    \n    }\n  PrintDot ('\\n');\n  //  (*mycout) << \"Vol = \" << CalcVolume (points, volelements) << endl;\n\n  multithread.task = savetask;\n\n}\n#endif\n\n\n\n  \nvoid Mesh :: ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal)\n{\n  static Timer t(\"Mesh::ImproveMesh\"); RegionTimer reg(t);\n  static Timer tcoloring(\"coloring\");\n  static Timer tcalcbadmax(\"Calc badmax\");\n  static Timer topt(\"optimize\");\n  static Timer trange(\"range\");\n  static Timer tloch(\"loch\");\n\n  BuildBoundaryEdges(false);\n\n  (*testout) << \"Improve Mesh\" << \"\\n\";\n  PrintMessage (3, \"ImproveMesh\");\n\n  // int np = GetNP();\n  int ne = GetNE();\n\n  PointFunction pf_glob(*this, mp);\n\n  auto & elementsonpoint = pf_glob.GetPointToElementTable();\n\n  const auto & getDofs = [&] (int i)\n  {\n      return elementsonpoint[i += PointIndex::BASE];\n  };\n\n  Array<int> colors(points.Size());\n\n  tcoloring.Start();\n  int ncolors = ngcore::ComputeColoring( colors, ne, getDofs );\n  auto color_table = CreateTable<PointIndex, int>( points.Size(),\n         [&] ( auto & table, int i )\n          {\n            PointIndex pi = i+static_cast<int>(PointIndex::BASE);\n            table.Add(colors[i], pi);\n          }, ncolors);\n\n  tcoloring.Stop();\n\n  if (goal == OPT_QUALITY)\n    {\n      double bad1 = CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << bad1 << endl;\n      PrintMessage (5, \"Total badness = \", bad1);\n    }\n\n\n  (*testout) << setprecision(8);\n\n  Array<double, PointIndex> pointh (points.Size());\n\n  if(HasLocalHFunction())\n    {\n      RegionTimer rt(tloch);\n      ParallelForRange(points.Range(), [&] (auto myrange)\n         {\n           for(auto pi : myrange)\n             pointh[pi] = GetH(pi);\n         });\n    }\n  else\n    {\n      pointh = 0;\n      for (Element & el : VolumeElements())\n\t{\n\t  double h = pow(el.Volume(points),1./3.);\n          for (PointIndex pi : el.PNums())\n\t    if (h > pointh[pi])\n              pointh[pi] = h;\n\t}\n    }\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Smooth Mesh\";\n\n  topt.Start();\n  for (auto icolor : Range(ncolors))\n  {\n      if (multithread.terminate)\n          throw NgException (\"Meshing stopped\");\n\n      ParallelForRange( color_table[icolor].Range(), [&](auto myrange)\n      {\n        RegionTracer reg(ngcore::TaskManager::GetThreadId(), trange, myrange.Size());\n        Vector x(3);\n\n        PointFunction pf{pf_glob};\n\n        Opti3FreeMinFunction freeminf(pf);\n\n        OptiParameters par;\n        par.maxit_linsearch = 20;\n        par.maxit_bfgs = 20;\n\n        for (auto i : myrange)\n        {\n          PointIndex pi = color_table[icolor][i];\n          if ( (*this)[pi].Type() == INNERPOINT )\n          {\n            double lh = pointh[pi];\n            pf.SetLocalH (lh);\n            par.typx = lh;\n\n            freeminf.SetPoint (points[pi]);\n            pf.SetPointIndex (pi);\n\n            x = 0;\n            int pok;\n            pok = freeminf.Func (x) < 1e10;\n\n            if (!pok)\n              {\n                pok = pf.MovePointToInner ();\n\n                freeminf.SetPoint (points[pi]);\n                pf.SetPointIndex (pi);\n              }\n\n            if (pok)\n              {\n                //*testout << \"start BFGS, pok\" << endl;\n                BFGS (x, freeminf, par);\n                //*testout << \"BFGS complete, pok\" << endl;\n                points[pi](0) += x(0);\n                points[pi](1) += x(1);\n                points[pi](2) += x(2);\n              }\n          }\n        }\n      }, 4*ngcore::TaskManager::GetNumThreads());\n  }\n  topt.Stop();\n\n  multithread.task = savetask;\n\n  if (goal == OPT_QUALITY)\n    {\n      double bad1 = CalcTotalBad (mp);\n      (*testout) << \"Total badness = \" << bad1 << endl;\n      PrintMessage (5, \"Total badness = \", bad1);\n    }\n}\n\n\n\n// Improve Condition number of Jacobian, any elements  \nvoid Mesh :: ImproveMeshJacobian (const MeshingParameters & mp,\n\t\t\t\t  OPTIMIZEGOAL goal, const TBitArray<PointIndex> * usepoint)\n{\n  // int i, j;\n  \n  (*testout) << \"Improve Mesh Jacobian\" << \"\\n\";\n  PrintMessage (3, \"ImproveMesh Jacobian\");\n\n  int np = GetNP();\n  int ne = GetNE();\n\n  \n  Vector x(3);\n  \n  (*testout) << setprecision(8);\n  \n  JacobianPointFunction pf(points, volelements);\n  \n\n  OptiParameters par;\n  par.maxit_linsearch = 20;\n  par.maxit_bfgs = 20;\n  \n  TBitArray<PointIndex> badnodes(np);\n  badnodes.Clear();\n\n  for (int i = 1; i <= ne; i++)\n    {\n      const Element & el = VolumeElement(i);\n      double bad = el.CalcJacobianBadness (Points());\n      if (bad > 1)\n\tfor (int j = 1; j <= el.GetNP(); j++)\n\t  badnodes.SetBit (el.PNum(j));\n    }\n\n  Array<double, PointIndex> pointh (points.Size());\n\n  if(HasLocalHFunction())\n    {\n      // for(i = 1; i<=points.Size(); i++)\n      for (PointIndex pi : points.Range())\n\tpointh[pi] = GetH(pi);\n    }\n  else\n    {\n      pointh = 0;\n      for (int i=0; i<GetNE(); i++)\n\t{\n\t  const Element & el = VolumeElement(i+1);\n\t  double h = pow(el.Volume(points),1./3.);\n\t  for(int j=1; j<=el.GetNV(); j++)\n\t    if(h > pointh[el.PNum(j)])\n\t      pointh[el.PNum(j)] = h;\n\t}\n    }\n \n\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Smooth Mesh Jacobian\";\n  \n  // for (PointIndex pi = points.Begin(); i < points.End(); pi++)\n  for (PointIndex pi : points.Range())\n    {\n      if ((*this)[pi].Type() != INNERPOINT)\n\tcontinue;\n\n      if(usepoint && !usepoint->Test(pi))\n\tcontinue;\n\n      //(*testout) << \"improvejac, p = \" << i << endl;\n\n      if (goal == OPT_WORSTCASE && !badnodes.Test(pi))\n\tcontinue;\n      //\t(*testout) << \"smooth p \" << i << endl;\n\n      /*\n\tif (multithread.terminate)\n\tbreak;\n      */\n      if (multithread.terminate)\n\tthrow NgException (\"Meshing stopped\");\n\n      multithread.percent = 100.0 * pi / points.Size();\n\n      if (points.Size() < 1000)\n\tPrintDot ();\n      else\n\tif (pi % 10 == 0)\n\t  PrintDot ('+');\n\n      double lh = pointh[pi];\n      par.typx = lh;\n\n      pf.SetPointIndex (pi);\n\n      x = 0;\n      int pok = (pf.Func (x) < 1e10); \n\n      if (pok)\n\t{\n          //*testout << \"start BFGS, Jacobian\" << endl;\n\t  BFGS (x, pf, par);\n          //*testout << \"end BFGS, Jacobian\" << endl;\n\t  points[pi](0) += x(0);\n\t  points[pi](1) += x(1);\n\t  points[pi](2) += x(2);\n\t}\n      else\n\t{\n\t  cout << \"el not ok\" << endl;\n\t}\n    }\n  PrintDot ('\\n');\n  \n\n  multithread.task = savetask;\n}\n\n\n\n\n// Improve Condition number of Jacobian, any elements  \nvoid Mesh :: ImproveMeshJacobianOnSurface (const MeshingParameters & mp,\n\t\t\t\t\t   const TBitArray<PointIndex> & usepoint, \n\t\t\t\t\t   const NgArray< Vec<3>* > & nv,\n\t\t\t\t\t   OPTIMIZEGOAL goal,\n\t\t\t\t\t   const NgArray< idmap_type* > * idmaps)\n{\n  // int i, j;\n  \n  (*testout) << \"Improve Mesh Jacobian\" << \"\\n\";\n  PrintMessage (3, \"ImproveMesh Jacobian\");\n\n  int np = GetNP();\n  int ne = GetNE();\n\n  \n  Vector x(3);\n  \n  (*testout).precision(8);\n  \n  JacobianPointFunction pf(points, volelements);\n\n  NgArray< idmap_type* > locidmaps;\n  const NgArray< idmap_type* > * used_idmaps;\n\n  if(idmaps)\n    used_idmaps = idmaps;\n  else\n    {\n      used_idmaps = &locidmaps;\n      \n      for(int i=1; i<=GetIdentifications().GetMaxNr(); i++)\n\t{\n\t  if(GetIdentifications().GetType(i) == Identifications::PERIODIC)\n\t    {\n\t      locidmaps.Append(new idmap_type);\n\t      GetIdentifications().GetMap(i,*locidmaps.Last(),true);\n\t    }\n\t}\n    }\n\n  \n  bool usesum = (used_idmaps->Size() > 0);\n  MinFunctionSum pf_sum;\n  \n  JacobianPointFunction * pf2ptr = NULL;\n  if(usesum)\n    {\n      pf2ptr = new JacobianPointFunction(points, volelements);\n      pf_sum.AddFunction(pf);\n      pf_sum.AddFunction(*pf2ptr);\n    }\n  \n\n  OptiParameters par;\n  par.maxit_linsearch = 20;\n  par.maxit_bfgs = 20;\n  \n  TBitArray<PointIndex> badnodes(np);\n  badnodes.Clear();\n\n  for (int i = 1; i <= ne; i++)\n    {\n      const Element & el = VolumeElement(i);\n      double bad = el.CalcJacobianBadness (Points());\n      if (bad > 1)\n\tfor (int j = 1; j <= el.GetNP(); j++)\n\t  badnodes.SetBit (el.PNum(j));\n    }\n\n  NgArray<double, PointIndex::BASE> pointh (points.Size());\n \n  if(HasLocalHFunction())\n    {\n      // for(i=1; i<=points.Size(); i++)\n      for (PointIndex pi : points.Range())\n\tpointh[pi] = GetH(pi);\n    }\n  else\n    {\n      pointh = 0;\n      for(int i=0; i<GetNE(); i++)\n\t{\n\t  const Element & el = VolumeElement(i+1);\n\t  double h = pow(el.Volume(points),1./3.);\n\t  for(int j=1; j<=el.GetNV(); j++)\n\t    if(h > pointh[el.PNum(j)])\n\t      pointh[el.PNum(j)] = h;\n\t}\n    }\n\n\n  const char * savetask = multithread.task;\n  multithread.task = \"Optimize Volume: Smooth Mesh Jacobian\";\n  \n  // for (PointIndex pi = points.Begin(); pi <= points.End(); pi++)\n  for (PointIndex pi : points.Range())\n    if ( usepoint.Test(pi) )\n      {\n\t//(*testout) << \"improvejac, p = \" << i << endl;\n\n\tif (goal == OPT_WORSTCASE && !badnodes.Test(pi))\n\t  continue;\n\t//\t(*testout) << \"smooth p \" << i << endl;\n\n\t/*\n\tif (multithread.terminate)\n\t  break;\n\t*/\n\tif (multithread.terminate)\n\t  throw NgException (\"Meshing stopped\");\n\n\tmultithread.percent = 100.0 * pi / points.Size();\n\n\tif (points.Size() < 1000)\n\t  PrintDot ();\n\telse\n\t  if (pi % 10 == 0)\n\t    PrintDot ('+');\n\n\tdouble lh = pointh[pi];//GetH(points.Get(i));\n\tpar.typx = lh;\n\n\tpf.SetPointIndex (pi);\n\n        constexpr PointIndex state0(PointIndex::INVALID);\n        constexpr PointIndex statem1 = state0-1;\n        \n\tPointIndex brother = statem1;\n\tif(usesum)\n\t  {\n\t    for(int j=0; brother == statem1 && j<used_idmaps->Size(); j++)\n\t      {\n\t\tif(pi < (*used_idmaps)[j]->Size() + IndexBASE<PointIndex>())\n\t\t  {\n\t\t    brother = (*(*used_idmaps)[j])[pi];\n\t\t    if(brother == pi || brother == state0)\n\t\t      brother = statem1;\n\t\t  }\n\t      }\n\t    // if(brother >= pi)\n            if(brother-pi >= 0)\n\t      {\n\t\tpf2ptr->SetPointIndex(brother);\n\t\tpf2ptr->SetNV(*nv[brother-1]);\n\t      }\n\t  }\n\n\t// if(usesum && brother < pi)\n        if(usesum && (brother-pi < 0))\n\t  continue;\n\n\t//pf.UnSetNV(); x = 0;\n\t//(*testout) << \"before \" << pf.Func(x);\n\n\tpf.SetNV(*nv[pi-1]);\n\n\tx = 0;\n\tint pok = (brother == statem1) ? (pf.Func (x) < 1e10) : (pf_sum.Func (x) < 1e10);\n\n\tif (pok)\n\t  {\n\t    \n\t    if(brother == statem1)\n\t      BFGS (x, pf, par);\n\t    else\n\t      BFGS (x, pf_sum, par);\n\n\n\t    for(int j=0; j<3; j++)\n\t      points[pi](j) += x(j);// - scal*nv[i-1].X(j);\n\n\t    if(brother != statem1)\n\t      for(int j=0; j<3; j++)\n\t\tpoints[brother](j) += x(j);// - scal*nv[brother-1].X(j);\n\n\n\t  }\n\telse\n\t  {\n\t    cout << \"el not ok\" << endl;\n\t    (*testout) << \"el not ok\" << endl\n\t\t       << \"   func \" << ((brother == statem1) ? pf.Func(x) : pf_sum.Func (x)) << endl;\n\t    if(brother != statem1)\n\t      (*testout) << \"   func1 \" << pf.Func(x) << endl\n\t\t\t << \"   func2 \" << pf2ptr->Func(x) << endl;\n\t  }\n      }\n  \n  PrintDot ('\\n');\n\n  delete pf2ptr;\n  for(int i=0; i<locidmaps.Size(); i++)\n    delete locidmaps[i];\n\n  multithread.task = savetask;\n}\n\n\n\n\n}\n"
  },
  {
    "path": "libsrc/meshing/soldata.hpp",
    "content": "#ifndef FILE_SOLDATA\n#define FILE_SOLDATA\n\n#include <myadt.hpp>  // for tAVX\nnamespace netgen\n{\n\n  using namespace std;\n  \n  class SolutionData\n  {\n  protected:\n\n    string name;\n    int components;\n    bool iscomplex;\n\n    int multidimcomponent;\n\n  public:\n    SolutionData (const string & aname, \n                  int acomponents = 1, bool aiscomplex = 0)\n      : name(aname), components(acomponents), iscomplex(aiscomplex)\n    { ; }\n\n    virtual ~SolutionData ()\n    { ; }\n\n    int GetComponents() \n    { \n      return components; \n    }\n\n    bool IsComplex() \n    {\n      return iscomplex; \n    }\n\n    virtual bool GetValue (int /* elnr */, \n                           double /* lam1 */, double /* lam2 */, double /* lam3 */,\n                           double * /* values */) \n    { \n      return false; \n    }\n\n    virtual bool GetValue (int selnr,\n                           const double xref[], const double x[], const double dxdxref[],\n                           double * values) \n    {\n      return GetValue (selnr, xref[0], xref[1], xref[2], values); \n    }\n\n    virtual bool GetMultiValue (int elnr, int facetnr, int npts,\n\t\t\t\tconst double * xref, int sxref,\n\t\t\t\tconst double * x, int sx,\n\t\t\t\tconst double * dxdxref, int sdxdxref,\n\t\t\t\tdouble * values, int svalues)\n    {\n      bool res = false;\n      for (int i = 0; i < npts; i++)\n\tres = GetValue (elnr, &xref[i*sxref], &x[i*sx], &dxdxref[i*sdxdxref], &values[i*svalues]);\n      return res;\n    }\n\n\n\n    virtual bool GetSurfValue (int /* selnr */, int facetnr, \n                               double /* lam1 */, double /* lam2 */, \n                               double * /* values */)\n    { \n      return false; \n    }\n\n\n    virtual bool GetSurfValue (int selnr, int facetnr, \n                               const double xref[], const double x[], const double dxdxref[],\n                               double * values)\n    { \n      return GetSurfValue (selnr, facetnr, xref[0], xref[1], values); \n    }\n\n\n    virtual bool GetMultiSurfValue (int selnr, int facetnr, int npts,\n                                    const double * xref, int sxref,\n                                    const double * x, int sx,\n                                    const double * dxdxref, int sdxdxref,\n                                    double * values, int svalues)\n    {\n      bool res = false;\n      for (int i = 0; i < npts; i++)\n\tres = GetSurfValue (selnr, facetnr, &xref[i*sxref], &x[i*sx], &dxdxref[i*sdxdxref], &values[i*svalues]);\n      return res;\n    }\n\n    virtual bool GetMultiSurfValue (size_t selnr, size_t facetnr, size_t npts,\n                                    const SIMD<double> * xref,\n                                    const SIMD<double> * x,\n                                    const SIMD<double> * dxdxref,\n                                    SIMD<double> * values)\n    {\n      cerr << \"GetMultiSurfVaue not overloaded for SIMD<double>\" << endl;\n      return false;\n    }\n    \n    virtual bool GetSegmentValue (int segnr, double xref, double * values)\n    { return false; }\n    \n\n    virtual int GetNumMultiDimComponents ()\n    {\n      return 1;\n    }\n\n    virtual void SetMultiDimComponent (int mc)\n    { \n      if (mc >= GetNumMultiDimComponents()) mc = GetNumMultiDimComponents()-1;\n      if (mc < 0) mc = 0;\n      multidimcomponent = mc; \n    }\n  };\n\n\n  class DLL_HEADER MouseEventHandler\n  {\n  public:\n    virtual void DblClick (int elnr, double x, double y, double z) = 0;\n  };\n\n  \n  class DLL_HEADER UserVisualizationObject\n  {\n  public:\n    virtual ~UserVisualizationObject() { ; } \n    virtual void Draw () = 0;\n  };\n\n  \n}\n\n#endif\n\n"
  },
  {
    "path": "libsrc/meshing/specials.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\nnamespace netgen\n{\n\n// A special function for Hermann Landes, Erlangen\n\n\nvoid CutOffAndCombine (Mesh & mesh, const Mesh & othermesh)\n{\n  int i, j;\n  int nse = othermesh.GetNSE();\n  int onp = othermesh.GetNP();\n\n  int ne = mesh.GetNE();\n\n  PrintMessage (1, \"other mesh has \",\n\t\tothermesh.GetNP(), \" points, \",\n\t\tothermesh.GetNSE(), \" surface elements.\");\n\n  NgArray<Box3d> otherbounds(nse);  \n  Box3d otherbox;\n\n  double maxh = 0;\n  for (i = 1; i <= nse; i++)\n    {\n      const Element2d & sel = othermesh.SurfaceElement(i);\n      sel.GetBox(othermesh.Points(), otherbounds.Elem(i));\n\n      double loch = othermesh.GetH (othermesh.Point (sel.PNum(1)));\n      otherbounds.Elem(i).Increase(loch);\n      if (loch > maxh) maxh = loch;\n    }\n\n  otherbox.SetPoint (othermesh.Point(1));\n  for (i = 1; i <= othermesh.GetNP(); i++)\n    otherbox.AddPoint (othermesh.Point(i));\n  otherbox.Increase (maxh);\n\n  for (i = 1; i <= ne; i++)\n    {\n      Box3d box;\n      int remove = 0;\n\n      const Element & el = mesh.VolumeElement(i);\n      el.GetBox(mesh.Points(), box);\n\n      if (i % 10000 == 0)\n\tcout << \"+\" << flush;\n\n      if (box.Intersect(otherbox))\n\t{\n\t  for (j = 1; j <= nse && !remove; j++)\n\t    if (box.Intersect(otherbounds.Get(j)))\n\t      remove = 1;\n\t}\n\n      if (remove)\n\tmesh.VolumeElement(i).Delete();\n    }\n  cout << endl;\n\n  TBitArray<PointIndex> connected(mesh.GetNP());\n  connected.Clear();\n  for (i = 1; i <= mesh.GetNSE(); i++)\n    {\n      const Element2d & el = mesh.SurfaceElement(i);\n      for (j = 1; j <= 3; j++)\n\tconnected.SetBit(el.PNum(j));\n    }\n  \n  bool changed;\n  do\n    {\n      changed = 0;\n      for (i = 1; i <= mesh.GetNE(); i++)\n\t{\n\t  const Element & el = mesh.VolumeElement(i);\n\t  int has = 0, hasnot = 0;\n\t  if (el[0])\n\t    {\n\t      for (j = 0; j < 4; j++)\n\t\t{\n\t\t  if (connected.Test(el[j]))\n\t\t    has = 1;\n\t\t  else\n\t\t    hasnot = 1;\n\t\t}\n\t      if (has && hasnot)\n\t\t{\n\t\t  changed = 1;\n\t\t  for (j = 0; j < 4; j++)\n\t\t    connected.SetBit (el[j]);\n\t\t}\n\t    }\n\t}\n      cout << \".\" << flush;\n    }\n  while (changed);\n  cout << endl;\n\n  for (i = 1; i <= mesh.GetNE(); i++)\n    {\n      const Element & el = mesh.VolumeElement(i);\n      int hasnot = 0;\n      if (el[0])\n\t{\n\t  for (j = 0; j < 4; j++)\n\t    {\n\t      if (!connected.Test(el[j]))\n\t\thasnot = 1;\n\t    }\n\t  if (hasnot)\n\t    mesh.VolumeElement(i).Delete();\n\t}\n    }\n\n  mesh.Compress();\n  \n  mesh.FindOpenElements();\n  TBitArray<PointIndex> locked(mesh.GetNP());\n  locked.Set();\n  for (i = 1; i <= mesh.GetNOpenElements(); i++)\n    for (j = 1; j <= 3; j++)\n      locked.Clear (mesh.OpenElement(i).PNum(j));\n\n  // for (PointIndex i (1); i <= locked.Size(); i++)\n  for (PointIndex i : locked.Range())\n    if (locked.Test(i))\n      {\n\tmesh.AddLockedPoint (i);\n      }\n\n\n\n  \n  NgArray<PointIndex> pmat(onp);\n\n  for (i = 1; i <= onp; i++)\n    pmat.Elem(i) = mesh.AddPoint (othermesh.Point(i));\n\n  int fnum = \n    mesh.AddFaceDescriptor (FaceDescriptor(0,0,1,0));\n\n  for (i = 1; i <= othermesh.GetNSE(); i++)\n    {\n      Element2d tri = othermesh.SurfaceElement(i);\n      for (j = 1; j <= 3; j++)\n\ttri.PNum(j) = pmat.Get(tri.PNum(j));\n      tri.SetIndex(fnum);\n      mesh.AddSurfaceElement (tri);\n    }\n\n  for (i = 1; i <= onp; i++)\n    mesh.AddLockedPoint (pmat.Elem(i));\n\n  mesh.CalcSurfacesOfNode();\n  mesh.CalcLocalH(0.3);\n}\n\n\n\n\nvoid HelmholtzMesh (Mesh & mesh)\n{\n  int i;\n  double ri, ra, rinf;\n\n  cout << \"ri = \";\n  cin >> ri;\n  cout << \"ra = \";\n  cin >> ra;\n  cout << \"rinf = \";\n  cin >> rinf;\n\n  double det = ri * ra * rinf - ri * ri * rinf;\n  double a = (ri - rinf) / det;\n  double b = (ri*ri - ra * rinf) / det;\n  for (i = 1; i <= mesh.GetNP(); i++)\n    {\n      Point<3> & p = mesh.Point(i);\n      double rold = sqrt (sqr(p(0)) + sqr(p(1)) + sqr(p(2)));\n      if (rold < ri) continue;\n\n      double rnew = 1 / (a * rold - b);\n      double fac = rnew / rold;\n      p(0) *= fac;\n      p(1) *= fac;\n      p(2) *= fac;\n    }\n}\n}\n"
  },
  {
    "path": "libsrc/meshing/specials.hpp",
    "content": "#ifndef FILE_SPECIALS\n#define FILE_SPECIALS\n\n/*\n\n  Very special implementations ..\n  \n */\n\nnamespace netgen {\n///\nDLL_HEADER extern void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh);\n\nDLL_HEADER extern void HelmholtzMesh (Mesh & mesh);\n\n} // namespace netgen\n#endif\n"
  },
  {
    "path": "libsrc/meshing/surfacegeom.cpp",
    "content": "/* *************************************************************************/\r\n/* File:   surfacegeom.cpp                                                 */\r\n/* Author: Michael Neunteufel                                              */\r\n/* Date:   Jun. 2020                                                       */\r\n/* *************************************************************************/\r\n\r\n#include <meshing.hpp>\r\n\r\nnamespace netgen\r\n{\r\n  SurfaceGeometry :: SurfaceGeometry()\r\n  {\r\n    //identity\r\n    func = [](Point<2> p) { return Vec<3>(p[0],p[1],0.0); };\r\n  }\r\n\r\n  SurfaceGeometry :: SurfaceGeometry(function<Vec<3>(Point<2>)> _func) : func(_func)\r\n  {\r\n    ;\r\n  }\r\n\r\n  SurfaceGeometry :: SurfaceGeometry(const SurfaceGeometry& geom) : func(geom.func), eps(geom.eps)\r\n  {\r\n    ;\r\n  }\r\n  \r\n  void SurfaceGeometry :: CalcHesse(double u, double v, Vec<3>& f_uu, Vec<3>& f_vv, Vec<3>& f_uv) const\r\n  {\r\n    Point<2> p = Point<2>(u,v);\r\n    double pr  = p[0]+eps;\r\n    double pl  = p[0]-eps;\r\n    double prr = p[0]+2*eps;\r\n    double pll = p[0]-2*eps;\r\n    \r\n    auto dr = GetTangentVectors( pr, v );\r\n    auto dl = GetTangentVectors( pl, v );\r\n    auto drr = GetTangentVectors( prr, v );\r\n    auto dll = GetTangentVectors( pll, v );\r\n    \r\n    f_uu = (1.0/(12.0*eps)) * (8.0*dr[0]-8.0*dl[0]-drr[0]+dll[0]);\r\n    f_uv = (1.0/(12.0*eps)) * (8.0*dr[1]-8.0*dl[1]-drr[1]+dll[1]);\r\n\r\n    pr  = p[1]+eps;\r\n    pl  = p[1]-eps;\r\n    prr = p[1]+2*eps;\r\n    pll = p[1]-2*eps;\r\n\r\n    GetTangentVectors(u, pr, dr);\r\n    GetTangentVectors(u, pl, dl);\r\n    GetTangentVectors(u, prr, drr);\r\n    GetTangentVectors(u, pll, dll);\r\n    \r\n    f_vv = (1.0/(12.0*eps)) * (8.0*dr[1]-8.0*dl[1]-drr[1]+dll[1]);\r\n  }\r\n  \r\n  Array<Vec<3>> SurfaceGeometry :: GetTangentVectors(double u, double v) const\r\n  {\r\n    Array<Vec<3>> tang(2);\r\n    \r\n    Point<2> pru  = Point<2>(u+eps,v);\r\n    Point<2> plu  = Point<2>(u-eps,v);\r\n    Point<2> prru = Point<2>(u+2*eps,v);\r\n    Point<2> pllu = Point<2>(u-2*eps,v);\r\n    \r\n    Point<2> prv  = Point<2>(u,v+eps);\r\n    Point<2> plv  = Point<2>(u,v-eps);\r\n    Point<2> prrv = Point<2>(u,v+2*eps);\r\n    Point<2> pllv = Point<2>(u,v-2*eps);\r\n\r\n    \r\n    tang[0] = 1/(12.0*eps)*( 8.0*func(pru) - 8.0*func(plu) - func(prru) + func(pllu) );\r\n    tang[1] = 1/(12.0*eps)*( 8.0*func(prv) - 8.0*func(plv) - func(prrv) + func(pllv) );\r\n    \r\n    return tang;\r\n  }\r\n\r\n  void SurfaceGeometry :: GetTangentVectors(double u, double v, Array<Vec<3>>& tang) const\r\n  {\r\n    \r\n    Point<2> pru  = Point<2>(u+eps,v);\r\n    Point<2> plu  = Point<2>(u-eps,v);\r\n    Point<2> prru = Point<2>(u+2*eps,v);\r\n    Point<2> pllu = Point<2>(u-2*eps,v);\r\n    \r\n    Point<2> prv  = Point<2>(u,v+eps);\r\n    Point<2> plv  = Point<2>(u,v-eps);\r\n    Point<2> prrv = Point<2>(u,v+2*eps);\r\n    Point<2> pllv = Point<2>(u,v-2*eps);\r\n\r\n    \r\n    tang[0] = 1/(12.0*eps)*( 8.0*func(pru) - 8.0*func(plu) - func(prru) + func(pllu) );\r\n    tang[1] = 1/(12.0*eps)*( 8.0*func(prv) - 8.0*func(plv) - func(prrv) + func(pllv) );\r\n  }\r\n\r\n  \r\n  Vec<3> SurfaceGeometry :: GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi) const\r\n  {\r\n    Array<Vec<3>> tang = GetTangentVectors(gi->u, gi->v);\r\n    auto normal = Cross(tang[0], tang[1]);\r\n    normal.Normalize();\r\n    return normal;\r\n  }\r\n\r\n\r\n  PointGeomInfo SurfaceGeometry :: ProjectPoint(int surfind, Point<3> & p) const\r\n  {\r\n    throw Exception(\"In SurfaceGeometry::ProjectPoint\");\r\n  }\r\n  \r\n  void SurfaceGeometry :: ProjectPointEdge (int surfind, int surfind2, Point<3> & p,\r\n                                            EdgePointGeomInfo* gi) const\r\n  {\r\n    if (gi == nullptr)\r\n      throw Exception(\"In SurfaceGeometry::ProjectPointEdge: gi is nullptr\");\r\n    throw Exception(\"In SurfaceGeometry::ProjectPointEdge: not implemented\");\r\n  }\r\n    \r\n  bool  SurfaceGeometry :: ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const\r\n  {\r\n    Array<Vec<3>> tangs(2);\r\n    Vec<3> diff, f_uu, f_vv, f_uv;\r\n    Vec<2> r, dx;\r\n    double norm_r, energy=0.0, new_energy=0.0, alpha=2.0,u=0.0,v=0.0,maxerr=1e-16;\r\n    Mat<2,2> mat, inv;\r\n    int num=0, maxit=25;\r\n    double damping=0.5;\r\n\r\n    //Solve minimization problem\r\n    //   argmin_(u,v) 0.5*\\| f(u,v)-p\\|^2\r\n    //via Neton's method:\r\n    //  F(u,v) = ( (f(u,v)-p)*f_u(u,v), (f(u,v)-p)*f_v(u,v))^T = (0,0)^T\r\n    //Stiffness matrix\r\n    //  F'(u,v) = ( f_u*f_u + (f-p)*f_uu, f_v*f_u + (f-p)*f_uv, f_v*f_u + (f-p)*f_uv, f_v*f_v + (f-p)*f_vv )\r\n    do\r\n      {\r\n        num++;\r\n        GetTangentVectors(gi.u, gi.v,tangs);\r\n        diff = func(Point<2>(gi.u, gi.v)) - Vec<3>(p);\r\n        energy = diff.Length2();\r\n        r = Vec<2>( diff*tangs[0], diff*tangs[1] );\r\n        norm_r = r.Length2();\r\n\r\n        CalcHesse(gi.u, gi.v, f_uu, f_vv, f_uv);\r\n        \r\n       \r\n        mat(0,0) = tangs[0]*tangs[0] + diff*f_uu;\r\n        mat(1,0) = mat(0,1) = tangs[0]*tangs[1]+diff*f_uv;\r\n        mat(1,1) = tangs[1]*tangs[1]+diff*f_vv;\r\n    \r\n        CalcInverse(mat,inv);\r\n\r\n        dx = inv*r;\r\n\r\n        //Linesearch \r\n        alpha = 2.0;\r\n        do\r\n          {\r\n            alpha /= 2.0;\r\n            u = gi.u - min(1.0,alpha*damping*num)*dx[0];\r\n            v = gi.v - min(1.0,alpha*damping*num)*dx[1];\r\n\r\n            diff = func(Point<2>(u, v)) - Vec<3>(p);\r\n            new_energy = diff.Length2();\r\n          }\r\n        while (alpha > 1e-10 && new_energy > energy+1e-14);\r\n        if (alpha <= 1e-10)\r\n          throw Exception(\"In SurfaceGeometry::ProjectPointGI: Linesearch min alpha reached!\");\r\n\r\n        gi.u = u;\r\n        gi.v = v;\r\n        \r\n\r\n      }\r\n    while ( norm_r > maxerr && num < maxit);\r\n\r\n    //Stay in reference domain [0,1]^2\r\n    if (gi.u < 0 || gi.u > 1 || gi.v < 0 || gi.v > 1)\r\n      {\r\n        cout << \"Warning: Projected point outside [0,1]^2: u=\" << gi.u << \",v=\" << gi.v <<\". Setting back.\" << endl;\r\n        gi.u = min(max(gi.u,0.0),1.0);\r\n        gi.v = min(max(gi.v,0.0),1.0);\r\n      }\r\n\r\n    p = Point<3>(func(Point<2>(gi.u,gi.v)));\r\n\r\n    if (num == maxit)\r\n      {\r\n        //cout << \"In SurfaceGeometry::ProjectPointGI: Newton did not converge\" << endl;\r\n        throw Exception(\"In SurfaceGeometry::ProjectPointGI: Newton did not converge\");\r\n      }\r\n    return true;\r\n  }\r\n\r\n  bool  SurfaceGeometry :: CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const\r\n  {\r\n    throw Exception(\"In SurfaceGeometry::CalcPointGeomInfo: not implemented\");\r\n    return false;\r\n  }\r\n\r\n  \r\n  void  SurfaceGeometry :: PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const\r\n  {\r\n    newgi.u = ap1.u+secpoint*(ap2.u-ap1.u);\r\n    newgi.v = ap1.v+secpoint*(ap2.v-ap1.v);\r\n    newgi.edgenr = ap1.edgenr;\r\n    newgi.body = -1;\r\n    newgi.dist = -1.0;\r\n\r\n    newp = Point<3>(func(Point<2>(newgi.u, newgi.v)));\r\n  }\r\n\r\n    void CheckForBBBPnt(const Array<Point<3>>& bbbpts, const Point<3>& pnt, Array<bool>& found, Array<PointIndex>& indbbbpts, const Array<PointIndex>& pids)\r\n  {\r\n    for (int k = 0; k < bbbpts.Size(); k++)\r\n      {\r\n        auto diff = pnt - bbbpts[k];\r\n        if(diff.Length2() < 1e-14)\r\n          {\r\n            found[k] = true;\r\n            indbbbpts[k] = pids[pids.Size()-1];\r\n          }\r\n      }\r\n  }\r\n\r\n  void CheckForSingularity(const Array<Point<3>>& hppoints, const Point<3>& pnt, const Array<float>& hpptsfac, shared_ptr<Mesh> & mesh, const Array<PointIndex>& pids)\r\n  {\r\n    for (int k = 0; k < hppoints.Size(); k++)\r\n      {\r\n        auto diff = pnt - hppoints[k];\r\n        if(diff.Length2() < 1e-14)\r\n          {\r\n            (*mesh)[pids[pids.Size()-1]].Singularity(hpptsfac[k]);\r\n          }\r\n        \r\n      }\r\n  }\r\n  \r\n  void SurfaceGeometry :: PointBetween(const Point<3> & p1, const Point<3> & p2, double secpoint,\r\n                                       int surfi, \r\n                                       const PointGeomInfo & gi1, \r\n                                       const PointGeomInfo & gi2,\r\n                                       Point<3> & newp, PointGeomInfo & newgi) const\r\n  {\r\n    newgi.u = gi1.u+secpoint*(gi2.u-gi1.u);\r\n    newgi.v = gi1.v+secpoint*(gi2.v-gi1.v);  \r\n    newgi.trignum = -1;\r\n\r\n    newp = Point<3>(func(Point<2>(newgi.u, newgi.v)));\r\n    //newp = p1+secpoint*(p2-p1);\r\n    //ProjectPointGI(surfi, newp, newgi);\r\n  }\r\n\r\n  int SurfaceGeometry :: GenerateStructuredMesh(shared_ptr<Mesh> & mesh, bool quads, int nx, int ny, bool flip_triangles, const Array<Point<3>>& bbbpts, const Array<string>& bbbnames, const Array<Point<3>>& hppoints, const Array<float>& hpptsfac, const Array<string>& hpbnd, const Array<float>& hpbndfac, Array<double> layer_thickness[4], bool layer_quad)\r\n  {\r\n    mesh->SetDimension(3);\r\n\r\n    Array<bool> found(bbbpts.Size());\r\n    found = false;\r\n    Array<PointIndex> indbbbpts(bbbpts.Size());\r\n\r\n    int numx = nx;\r\n    int numy = ny;\r\n\r\n    size_t total_layer_el[4] = {layer_thickness[0].Size(), layer_thickness[1].Size(), layer_thickness[2].Size(), layer_thickness[3].Size()};\r\n    \r\n    double interior_x = 1.0;\r\n    double interior_y = 1.0;\r\n    for(double scale : layer_thickness[0])\r\n      interior_x -= scale;\r\n    for(double scale : layer_thickness[2])\r\n      interior_x -= scale;\r\n    for(double scale : layer_thickness[1])\r\n      interior_y -= scale;\r\n    for(double scale : layer_thickness[3])\r\n      interior_y -= scale;\r\n\r\n    auto AddPoint = [&] (double offsetx, double offsety, Array<PointIndex> & pids, Array<PointGeomInfo> & pgis)\r\n    {\r\n      PointGeomInfo pgi;\r\n      pgi.trignum = -1;\r\n      pgi.u = offsetx;\r\n      pgi.v = offsety;\r\n\r\n      \r\n      Point<3> pnt = Point<3>(func(Point<2>(pgi.u,pgi.v)));\r\n      pids.Append(mesh->AddPoint(pnt));\r\n      pgis.Append(pgi);\r\n      \r\n      CheckForBBBPnt(bbbpts, pnt, found, indbbbpts, pids);\r\n      CheckForSingularity(hppoints, pnt, hpptsfac, mesh, pids);\r\n    };\r\n\r\n    auto InternalLoop = [&] (double offsety, Array<PointIndex> & pids, Array<PointGeomInfo> & pgis)\r\n    {\r\n      int j = 0;\r\n      double offsetx = 0.0;\r\n\r\n      for(int l=0; l < layer_thickness[0].Size(); l++,j++)\r\n        {\r\n\t  AddPoint(offsetx+layer_thickness[0][l]*double(j-l), offsety, pids, pgis);\r\n          offsetx += layer_thickness[0][l];\r\n        }\r\n      \r\n      \r\n      for(;j <= nx-total_layer_el[2]; j++)\r\n        AddPoint(offsetx + interior_x*double(j-total_layer_el[0])/(nx-total_layer_el[0]-total_layer_el[2]), offsety, pids, pgis);\r\n      offsetx += interior_x;\r\n            \r\n      int startj = j;\r\n      for(int l=0; l < layer_thickness[2].Size(); l++, j++)\r\n        {\r\n\t  AddPoint(offsetx+layer_thickness[2][layer_thickness[2].Size()-1-l]*double(j-startj-l+1), offsety, pids, pgis);\r\n\r\n          offsetx += layer_thickness[2][layer_thickness[2].Size()-1-l];\r\n        }\r\n    };\r\n    \r\n    Array<PointIndex> pids;\r\n    Array<PointGeomInfo> pgis;\r\n    \r\n    int i = 0;\r\n    double offsety = 0.0;\r\n\r\n    for(int k=0; k < layer_thickness[1].Size(); k++,i++)\r\n      {\r\n\tInternalLoop(offsety, pids, pgis);\r\n\toffsety += layer_thickness[1][k];\r\n      }\r\n\r\n    for(; i <= ny-total_layer_el[3]; i++)\r\n      {\r\n        InternalLoop(offsety, pids, pgis);        \r\n\toffsety +=  interior_y/(ny-total_layer_el[1]-total_layer_el[3]);\r\n      }\r\n    offsety -=  interior_y/(ny-total_layer_el[1]-total_layer_el[3]);\r\n\r\n    for(int k=0; k < layer_thickness[3].Size(); k++,i++)\r\n      {\r\n\toffsety += layer_thickness[3][layer_thickness[3].Size()-1-k];\r\n\tInternalLoop(offsety, pids, pgis); \r\n      }\r\n\r\n    for (bool f : found)\r\n      if (!f)\r\n        throw Exception(\"In SurfaceGeometry :: GenerateMesh: bbbpts not resolved in mesh.\");\r\n\r\n    FaceDescriptor fd;\r\n    fd.SetSurfNr(1);\r\n    fd.SetDomainIn(1);\r\n    fd.SetDomainOut(0);\r\n    fd.SetBCProperty(1);\r\n    mesh->AddFaceDescriptor(fd);\r\n\r\n\r\n    for(int i=0; i < numy; i++)\r\n      {\r\n        for(int j=0; j < numx; j++)\r\n          {\r\n            int base = i * (numx+1) + j;\r\n            if (quads || (layer_quad && i < total_layer_el[1]) || (layer_quad && i > numy-1-total_layer_el[3]) || (layer_quad && j < total_layer_el[0]) || (layer_quad && j > numx-1-total_layer_el[2]) )\r\n              {\r\n                int pnum[4] = {base,base+1,base+numx+2,base+numx+1};\r\n                Element2d el = Element2d(QUAD);\r\n                for (int i = 0; i < 4; i++)\r\n                  {\r\n                    el[i] = pids[pnum[i]];\r\n                    el.GeomInfoPi(i+1) = pgis[pnum[i]];\r\n                  }\r\n                el.SetIndex(1);\r\n            \r\n                mesh->AddSurfaceElement(el);\r\n              }\r\n            else\r\n              {\r\n                Array<int> pnum1(3);\r\n                Array<int> pnum2(3);\r\n                if (flip_triangles)\r\n                  {\r\n                    pnum1[0] = base;\r\n                    pnum1[1] = base+1;\r\n                    pnum1[2] = base+numx+2;\r\n                    pnum2[0] = base;\r\n                    pnum2[1] = base+numx+2;\r\n                    pnum2[2] = base+numx+1;\r\n                  }\r\n                else\r\n                  {\r\n                    pnum1[0] = base;\r\n                    pnum1[1] = base+1;\r\n                    pnum1[2] = base+numx+1;\r\n                    pnum2[0] = base+1;\r\n                    pnum2[1] = base+numx+2;\r\n                    pnum2[2] = base+numx+1;\r\n                  }\r\n\r\n                Element2d el = Element2d(TRIG);\r\n                for (int i = 0; i < 3; i++)\r\n                  {\r\n                    el[i] = pids[pnum1[i]];\r\n                    el.GeomInfoPi(i+1) = pgis[pnum1[i]];\r\n                  }\r\n                el.SetIndex(1);\r\n            \r\n                mesh->AddSurfaceElement(el);\r\n                for (int i = 0; i < 3; i++)\r\n                  {\r\n                    el[i] = pids[pnum2[i]];\r\n                    el.GeomInfoPi(i+1) = pgis[pnum2[i]];\r\n                  }\r\n                mesh->AddSurfaceElement(el);\r\n              }\r\n          }\r\n      }\r\n\r\n    Segment seg;\r\n    seg.si = 1;\r\n    seg.edgenr = 1;\r\n    seg.epgeominfo[0].edgenr = 0;\r\n    seg.epgeominfo[1].edgenr = 0;\r\n    //for hp refinement\r\n    seg.singedge_left = 0;\r\n    seg.singedge_right = 0;\r\n    for (size_t i=0; i < hpbnd.Size(); i++)\r\n      {\r\n        if (hpbnd[i] == \"bottom\")\r\n          {\r\n            seg.singedge_left = hpbndfac[i];\r\n            seg.singedge_right = hpbndfac[i];\r\n          }\r\n      }\r\n    // needed for codim2 in 3d\r\n    seg.edgenr = 1;\r\n    for(int i=0; i < numx; i++)\r\n      {\r\n        seg[0] = pids[i];\r\n        seg[1] = pids[i+1];\r\n        \r\n        seg.geominfo[0] = pgis[i];\r\n        seg.geominfo[1] = pgis[i+1];\r\n        seg.epgeominfo[0].u = pgis[i].u;\r\n        seg.epgeominfo[0].v = pgis[i].v;\r\n        seg.epgeominfo[0].edgenr = seg.edgenr;\r\n        seg.epgeominfo[1].u = pgis[i+1].u;\r\n        seg.epgeominfo[1].v = pgis[i+1].v;\r\n        seg.epgeominfo[1].edgenr = seg.edgenr;\r\n        \r\n        mesh->AddSegment(seg);\r\n      }\r\n\r\n    seg.si = 2;\r\n    seg.edgenr = 2;\r\n    seg.singedge_left = 0;\r\n    seg.singedge_right = 0;\r\n\r\n    for (size_t i=0; i < hpbnd.Size(); i++)\r\n      {\r\n        if (hpbnd[i] == \"right\")\r\n          {\r\n            seg.singedge_left = hpbndfac[i];\r\n            seg.singedge_right = hpbndfac[i];\r\n          }\r\n      }\r\n\r\n    for(int i=0; i<numy; i++)\r\n      {\r\n        seg[0] = pids[i*(numx+1)+numx];\r\n        seg[1] = pids[(i+1)*(numx+1)+numx];\r\n\r\n        seg.geominfo[0] = pgis[i*(numx+1)+numx];\r\n        seg.geominfo[1] = pgis[(i+1)*(numx+1)+numx];\r\n        seg.epgeominfo[0].u = pgis[i*(numx+1)+numx].u;\r\n        seg.epgeominfo[0].v = pgis[i*(numx+1)+numx].v;\r\n        seg.epgeominfo[0].edgenr = seg.edgenr;\r\n        seg.epgeominfo[1].u = pgis[(i+1)*(numx+1)+numx].u;\r\n        seg.epgeominfo[1].v = pgis[(i+1)*(numx+1)+numx].v;\r\n        seg.epgeominfo[1].edgenr = seg.edgenr;\r\n\r\n        mesh->AddSegment(seg);\r\n      }\r\n\r\n    seg.si = 3;\r\n    seg.edgenr = 3;\r\n    seg.singedge_left = 0;\r\n    seg.singedge_right = 0;\r\n\r\n    for (size_t i=0; i < hpbnd.Size(); i++)\r\n      {\r\n        if (hpbnd[i] == \"top\")\r\n          {\r\n            seg.singedge_left = hpbndfac[i];\r\n            seg.singedge_right = hpbndfac[i];\r\n          }\r\n      }\r\n\r\n    for(int i=0; i<numx; i++)\r\n      {\r\n        seg[0] = pids[numy*(numx+1)+i+1];\r\n        seg[1] = pids[numy*(numx+1)+i];\r\n\r\n        seg.geominfo[0] = pgis[numy*(numx+1)+i+1];\r\n        seg.geominfo[1] = pgis[numy*(numx+1)+i];\r\n        seg.epgeominfo[0].u = pgis[numy*(numx+1)+i+1].u;\r\n        seg.epgeominfo[0].v = pgis[numy*(numx+1)+i+1].v;\r\n        seg.epgeominfo[0].edgenr = seg.edgenr;\r\n        seg.epgeominfo[1].u = pgis[numy*(numx+1)+i].u;\r\n        seg.epgeominfo[1].v = pgis[numy*(numx+1)+i].v;\r\n        seg.epgeominfo[1].edgenr = seg.edgenr;\r\n        \r\n        mesh->AddSegment(seg);\r\n      }\r\n\r\n    seg.si = 4;\r\n    seg.edgenr = 4;\r\n    seg.singedge_left = 0;\r\n    seg.singedge_right = 0;\r\n    for (size_t i=0; i < hpbnd.Size(); i++)\r\n      {\r\n        if (hpbnd[i] == \"left\")\r\n          {\r\n            seg.singedge_left = hpbndfac[i];\r\n            seg.singedge_right = hpbndfac[i];\r\n          }\r\n      }\r\n\r\n\r\n    for(int i=0; i<numy; i++)\r\n      {\r\n        seg[0] = pids[(i+1)*(numx+1)];\r\n        seg[1] = pids[i*(numx+1)];\r\n\r\n        seg.geominfo[0] = pgis[(i+1)*(numx+1)];\r\n        seg.geominfo[1] = pgis[i*(numx+1)];\r\n        seg.epgeominfo[0].u = pgis[(i+1)*(numx+1)].u;\r\n        seg.epgeominfo[0].v = pgis[(i+1)*(numx+1)].v;\r\n        seg.epgeominfo[0].edgenr = seg.edgenr;\r\n        seg.epgeominfo[1].u = pgis[i*(numx+1)].u;\r\n        seg.epgeominfo[1].v = pgis[i*(numx+1)].v;\r\n        seg.epgeominfo[1].edgenr = seg.edgenr;\r\n\r\n        mesh->AddSegment(seg);\r\n      }\r\n\r\n    mesh->SetCD2Name(1, \"bottom\");\r\n    mesh->SetCD2Name(2, \"right\");\r\n    mesh->SetCD2Name(3, \"top\");\r\n    mesh->SetCD2Name(4, \"left\");\r\n\r\n    for (int i = 0; i < bbbpts.Size(); i++)\r\n      {\r\n        Element0d el;\r\n        el.pnum = indbbbpts[i];\r\n        el.index = i+1;\r\n        mesh->pointelements.Append(el);\r\n        mesh->SetCD3Name(i+1, bbbnames[i]);\r\n      }\r\n\r\n    mesh->Compress();\r\n    mesh->UpdateTopology();\r\n\r\n    return 0;\r\n  }\r\n  \r\n};\r\n"
  },
  {
    "path": "libsrc/meshing/surfacegeom.hpp",
    "content": "#ifndef FILE_SURFACEGEOM\r\n#define FILE_SURFACEGEOM\r\n\r\n/* *************************************************************************/\r\n/* File:   surfacegeom.hpp                                                 */\r\n/* Author: Michael Neunteufel                                              */\r\n/* Date:   Jun. 2020                                                       */\r\n/* *************************************************************************/\r\n\r\n\r\n#include <functional>\r\n\r\n\r\nnamespace netgen\r\n{\r\n\r\n  class DLL_HEADER SurfaceGeometry : public NetgenGeometry\r\n  {\r\n    function<Vec<3>(Point<2>)> func;\r\n    double eps=1e-4;\r\n\r\n  private:\r\n\r\n    void CalcHesse(double u, double v, Vec<3>& f_uu, Vec<3>& f_vv, Vec<3>& f_uv) const;\r\n  public:\r\n\r\n    SurfaceGeometry();\r\n    SurfaceGeometry(function<Vec<3>(Point<2>)> func);\r\n    SurfaceGeometry(const SurfaceGeometry& geom);\r\n    SurfaceGeometry& operator =(const SurfaceGeometry& geom)\r\n    {\r\n      func = geom.func;\r\n      eps = geom.eps;\r\n      return *this;\r\n    }\r\n\r\n    Array<Vec<3>> GetTangentVectors(double u, double v) const;\r\n\r\n    void GetTangentVectors(double u, double v, Array<Vec<3>>& tang) const;\r\n\r\n\r\n    virtual Vec<3> GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi) const override;\r\n\r\n    virtual PointGeomInfo ProjectPoint(int surfind, Point<3> & p) const override;\r\n    \r\n    virtual void ProjectPointEdge (int surfind, int surfind2, Point<3> & p,\r\n                           EdgePointGeomInfo* gi = nullptr) const override;\r\n    \r\n    virtual bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const override;\r\n\r\n    virtual bool CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const override;\r\n\r\n    virtual void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\r\n                          int surfi1, int surfi2, \r\n                          const EdgePointGeomInfo & ap1, \r\n                          const EdgePointGeomInfo & ap2,\r\n                          Point<3> & newp, EdgePointGeomInfo & newgi) const override;\r\n    \r\n    virtual void PointBetween(const Point<3> & p1, const Point<3> & p2, double secpoint,\r\n                      int surfi, \r\n                      const PointGeomInfo & gi1, \r\n                      const PointGeomInfo & gi2,\r\n                      Point<3> & newp, PointGeomInfo & newgi) const override;\r\n\r\n    int GenerateStructuredMesh(shared_ptr<Mesh> & mesh, bool quads, int nx, int ny, bool flip_triangles, const Array<Point<3>>& bbbpts, const Array<string>& bbbnames, const Array<Point<3>>& hppoints, const Array<float>& hpptsfac, const Array<string>& hpbnd, const Array<float>& hpbndfac, Array<double> layer_thickness[4], bool layer_quad);\r\n\r\n  };\r\n  \r\n}\r\n   \r\n\r\n\r\n#endif //SURFACEGEOM\r\n"
  },
  {
    "path": "libsrc/meshing/topology.cpp",
    "content": "#include <mystdlib.h>\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n  using ngcore::ParallelForRange;\n  using ngcore::ParallelFor;\n  using ngcore::TasksPerThread;\n\n  /*\n  template <class T>\n  void QuickSortRec (NgFlatArray<T> data,\n\t\t     int left, int right)\n  {\n    int i = left;\n    int j = right;\n    T midval = data[(left+right)/2];\n  \n    do\n      {\n\twhile (data[i] < midval) i++;\n\twhile (midval < data[j]) j--;\n      \n\tif (i <= j)\n\t  {\n\t    Swap (data[i], data[j]);\n\t    i++; j--;\n\t  }\n      }\n    while (i <= j);\n    if (left < j) QuickSortRec (data, left, j);\n    if (i < right) QuickSortRec (data, i, right);\n  }\n\n  template <class T>\n  void QuickSort (NgFlatArray<T> data)\n  {\n    if (data.Size() > 1)\n      QuickSortRec (data, 0, data.Size()-1);\n  }\n  */\n\n\n\n  \n  MeshTopology ::  MeshTopology (const Mesh & amesh)\n    : mesh(&amesh)\n  {\n    buildedges = static_buildedges;\n    buildfaces = static_buildfaces;\n    buildvertex2element = static_buildvertex2element;\n    timestamp = -1;\n  }\n\n  MeshTopology :: ~MeshTopology () { ;  }\n\n  bool MeshTopology :: NeedsUpdate() const\n  { return (timestamp <= mesh->GetTimeStamp()); }\n\n  \n  void MeshTopology :: EnableTable (string name, bool set)\n  {\n    if (name == \"edges\")\n      SetBuildEdges(set);\n    else if (name == \"faces\")\n      SetBuildFaces(set);\n    else if (name == \"parentedges\")\n      SetBuildParentEdges(set);\n    else if (name == \"parentfaces\")\n      SetBuildParentFaces(set);\n    else\n      throw Exception (\"nothing known about table \"+name +\"\\n\"\n                       \"known are 'edges', 'faces', 'parentedges', 'parentfaces'\");\n  }\n\n  bool MeshTopology :: static_buildedges = true; \n  bool MeshTopology :: static_buildfaces = true; \n  bool MeshTopology :: static_buildvertex2element = true; \n  \n  void MeshTopology :: EnableTableStatic (string name, bool set)\n  {\n    if (name == \"edges\")\n      static_buildedges = set;\n    else if (name == \"faces\")\n      static_buildfaces = set;      \n    else if (name == \"vertex2element\")\n      static_buildvertex2element = set;      \n    else\n      throw Exception (\"nothing known about table \"+name +\"\\n\"\n                       \"known are 'edges', 'faces', 'vertex2element'\");\n  }\n\n  \n  template <typename FUNC>\n  void LoopOverEdges (const Mesh & mesh, MeshTopology & top, PointIndex v,\n                      FUNC func)\n  {\n    for (ElementIndex elnr : top.GetVertexElements(v))\n      {\n        const Element & el = mesh[elnr];\n\n        auto eledges = MeshTopology::GetEdges (el.GetType());\n        for (int k = 0; k < eledges.Size(); k++)\n          {\n            PointIndices<2> edge(el[eledges[k][0]], el[eledges[k][1]]);\n\n            bool edgedir = edge[0] > edge[1];\n            if (edgedir) swap (edge[0], edge[1]);\n            if (edge[0] != v) continue;\n\n            func (edge, elnr, k, 3);\n          }      \n      }\n    \n    for (SurfaceElementIndex elnr : top.GetVertexSurfaceElements(v))\n      {\n        const Element2d & el = mesh[elnr];\n\n        auto eledges = MeshTopology::GetEdges (el.GetType());\n        for (int k = 0; k < eledges.Size(); k++)\n          {\n            PointIndices<2> edge(el[eledges[k][0]], el[eledges[k][1]]);\n\n            int edgedir = (edge.I1() > edge.I2());\n            if (edgedir) swap (edge.I1(), edge.I2());\n            \n            if (edge.I1() != v) continue;\n\n            func (edge, elnr, k, 2);\n          }        \n      }\n    \n    for (SegmentIndex elnr : top.GetVertexSegments(v))\n      {\n        const Segment & el = mesh[elnr];\n        PointIndices<2> edge(el[0], el[1]);\n        int edgedir = (edge.I1() > edge.I2());\n        if (edgedir) swap (edge.I1(), edge.I2());\n        \n        edge.Sort();\n        if (edge.I1() != v) continue;\n        \n        func (edge, elnr, 0, 1);\n      }\n  }\n  \n  template <typename FUNC>\n  void LoopOverFaces (const Mesh & mesh, MeshTopology & top, PointIndex v,\n                      FUNC func)\n  {\n    for (ElementIndex elnr : top.GetVertexElements(v))\n      {\n        const Element & el = mesh[elnr];\n\t\n        int nelfaces = MeshTopology::GetNFaces (el.GetType());\n        const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType());\n\t\n        for (int j = 0; j < nelfaces; j++)\n          if (elfaces[j][3] < 0)\n            \n            { // triangle\n              PointIndices<4> face(el[elfaces[j][0]], el[elfaces[j][1]], \n                                   el[elfaces[j][2]], PointIndex(PointIndex::INVALID));\n\n\n              [[maybe_unused]] int facedir = 0;\n              if (face.I1() > face.I2())\n                { swap (face.I1(), face.I2()); facedir += 1; }\n              if (face.I2() > face.I3())\n                { swap (face.I2(), face.I3()); facedir += 2; }\n              if (face.I1() > face.I2())\n                { swap (face.I1(), face.I2()); facedir += 4; }\n\n              if (face.I1() != v) continue;\n\n              func (face, elnr, j, true);\n            }\n        /*\n              if (pass == 1)\n                {\n                  if (!vert2face.Used (face))\n                    {\n                      nfa++;\n                      vert2face.Set (face, nfa);\n                      INDEX_4 hface(face.I1(),face.I2(),face.I3(),0);\n                      face2vert.Append (hface);\n                    }\n                }\n              else\n                {\n                  int facenum = vert2face.Get(face);\n                  faces[elnr][j].fnr = facenum-1;\n                  faces[elnr][j].forient = facedir;\n                }\n        */\n          else\n            {\n              // quad\n              // int facenum;\n              PointIndices<4> face4(el[elfaces[j][0]], el[elfaces[j][1]],\n                                    el[elfaces[j][2]], el[elfaces[j][3]]);\n              \n              // int facedir = 0;\n              if (min2 (face4.I1(), face4.I2()) > \n                  min2 (face4.I4(), face4.I3())) \n                {  // z - flip\n                  // facedir += 1; \n                  swap (face4.I1(), face4.I4());\n                  swap (face4.I2(), face4.I3());\n                }\n              if (min2 (face4.I1(), face4.I4()) >\n                  min2 (face4.I2(), face4.I3())) \n                {  // x - flip\n                  // facedir += 2; \n                  swap (face4.I1(), face4.I2());\n                  swap (face4.I3(), face4.I4());\n                }\n              if (face4.I2() > face4.I4())\n                {  // diagonal flip\n                  // facedir += 4; \n                  swap (face4.I2(), face4.I4());\n                }\n              \n              if (face4.I1() != v) continue;\n              \n              func(face4, elnr, j, true);\n                /*\n              INDEX_3 face(face4.I1(), face4.I2(), face4.I3());\n              \n              \n              if (vert2face.Used (face))\n                {\n                  facenum = vert2face.Get(face);\n                }\n              else\n                {\n                  if (pass == 2) cout << \"hier in pass 2\" << endl;\n                  nfa++;\n                  vert2face.Set (face, nfa);\n                  facenum = nfa;\n                  \n                  INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4());\n                  face2vert.Append (hface);\n                }\n              \n              faces[elnr][j].fnr = facenum-1;\n                          faces[elnr][j].forient = facedir;\n\t\t\t}\n                */\n                }\n      }\n\n    \n    for (SurfaceElementIndex elnr : top.GetVertexSurfaceElements(v))          \n      {\n        const Element2d & el = mesh[elnr];\n        \n        const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (el.GetType());\n\t\n        if (elfaces[0][3] == 0)\n          \n          { // triangle\n            \n            // int facenum;\n            // int facedir;\n            \n            PointIndices<4> face(el.PNum(elfaces[0][0]),\n                                 el.PNum(elfaces[0][1]),\n                                 el.PNum(elfaces[0][2]), PointIndex(PointIndex::INVALID));\n            \n            // facedir = 0;\n            if (face[0] > face[1])\n              {\n                swap (face[0], face[1]);\n                // facedir += 1;\n              }\n            if (face[1] > face[2])\n              {\n                swap (face[1], face[2]);\n                // facedir += 2;\n              }\n            if (face.I1() > face[1])\n              {\n                swap (face.I1(), face[1]);\n                // facedir += 4;\n              }\n            \n            if (face.I1() != v) continue;\n            \n            func(face, elnr, 0, false);\n            /*\n              if (vert2face.Used (face))\n              facenum = vert2face.Get(face);\n              else\n              {\n              nfa++;\n              vert2face.Set (face, nfa);\n              facenum = nfa;\n              \n              INDEX_4 hface(face.I1(),face.I2(),face.I3(),0);\n              face2vert.Append (hface);\n              }\n                \n              surffaces[elnr].fnr = facenum-1;\n              surffaces[elnr].forient = facedir;\n            */\n          }\n        \n        else\n          \n          {\n            // quad\n            // int facenum;\n            // int facedir;\n            \n            PointIndices<4> face4(el.PNum(elfaces[0][0]),\n                                  el.PNum(elfaces[0][1]),\n                                  el.PNum(elfaces[0][2]),\n                                  el.PNum(elfaces[0][3]));\n            \n            // facedir = 0;\n            if (min2 (face4.I1(), face4.I2()) > \n                min2 (face4.I4(), face4.I3())) \n              {  // z - orientation\n                // facedir += 1; \n                swap (face4.I1(), face4.I4());\n                swap (face4.I2(), face4.I3());\n              }\n            if (min2 (face4.I1(), face4.I4()) >\n                min2 (face4.I2(), face4.I3())) \n              {  // x - orientation\n                // facedir += 2; \n                swap (face4.I1(), face4.I2());\n                swap (face4.I3(), face4.I4());\n              }\n            if (face4.I2() > face4.I4())\n              { \n                // facedir += 4; \n                swap (face4.I2(), face4.I4());\n              }\n            \n            if (face4.I1() != v) continue;\n            func(face4, elnr, 0, false);\n            /*\n              INDEX_3 face(face4.I1(), face4.I2(), face4.I3());\n\t\t\n              if (vert2face.Used (face))\n              facenum = vert2face.Get(face);\n              else\n              {\n              nfa++;\n              vert2face.Set (face, nfa);\n              facenum = nfa;\n                    \n              INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4());\n              face2vert.Append (hface);\n              }\n                \n              surffaces[elnr].fnr = facenum-1;\n              surffaces[elnr].forient = facedir;\n              }\n            */\n          }\n            \n      }\n  }\n  \n  \n  void MeshTopology :: Update (NgTaskManager tm_unused, NgTracer tracer)\n  {\n    static Timer timer(\"Topology::Update\");\n    static Timer timer_tables(\"Build vertex to element table\");\n    RegionTimer reg (timer);\n\n#ifdef PARALLEL\n    // ParallelMeshTopology & paralleltop = mesh.GetParallelTopology();\n#endif\n\n    auto id = this->mesh->GetCommunicator().Rank();\n    auto ntasks = this->mesh->GetCommunicator().Size();\n  \n    if (timestamp > mesh->GetTimeStamp()) return;\n  \n    int ne = mesh->GetNE();\n    int nse = mesh->GetNSE();\n    int nseg = mesh->GetNSeg();\n    int np = mesh->GetNP();\n    int nv = mesh->GetNV(); \n\n    if (id == 0)\n      PrintMessage (3, \"Update mesh topology\");\n\n    (*testout) << \" UPDATE MESH TOPOLOGY \" << endl; \n    (*testout) << \"ne   = \" << ne << endl;\n    (*testout) << \"nse  = \" << nse << endl;\n    (*testout) << \"nseg = \" << nseg << endl;\n    (*testout) << \"np   = \" << np << endl;\n    (*testout) << \"nv   = \" << nv << endl;\n\n    (*tracer) (\"Topology::Update setup tables\", false);\n    NgArray<int,PointIndex::BASE> cnt(nv);\n\n    /*\n      generate:\n      vertex to element \n      vertex to surface element\n      vertex to segment \n    */\n\n    if (buildvertex2element)\n      {\n        timer_tables.Start();\n        vert2element = mesh->CreatePoint2ElementTable();\n        vert2surfelement = mesh->CreatePoint2SurfaceElementTable(0);\n\n        vert2segment = ngcore::CreateSortedTable<SegmentIndex, PointIndex>( mesh->LineSegments().Range(),\n                                                                            [&](auto & table, SegmentIndex segi)\n                                                                            {\n                                                                              const Segment & seg = (*mesh)[segi];\n                                                                              table.Add (seg[0], segi);\n                                                                              table.Add (seg[1], segi);\n                                                                            }, np);\n        \n        vert2pointelement = ngcore::CreateSortedTable<int, PointIndex>( mesh->pointelements.Range(),\n                                                                        [&](auto & table, int pei)\n                                                                        {\n                                                                          const Element0d & pointel = mesh->pointelements[pei];\n                                                                          table.Add(pointel.pnum, pei);\n                                                                        }, np);\n        timer_tables.Stop();\n      }\n\n\n    (*tracer) (\"Topology::Update setup tables\", true);\n\n    \n    if (buildedges)\n      {\n        static Timer timer1(\"topology::buildedges\");\n        RegionTimer reg1(timer1);\n\t\n\tif (id == 0)\n\t  PrintMessage (5, \"Update edges \");\n      \n\tedges.SetSize(ne);\n\tsurfedges.SetSize(nse); \n\tsegedges.SetSize(nseg);\n\n        /*\n\tfor (int i = 0; i < ne; i++)\n\t  for (int j = 0; j < 12; j++)\n\t    edges[i][j].nr = -1;\n\tfor (int i = 0; i < nse; i++)\n\t  for (int j = 0; j < 4; j++)\n\t    surfedges[i][j].nr = -1;\n        */\n        ParallelFor (ne, [this](auto i)\n                     {\n                       for (auto & e : edges[i])\n                         e = -1;\n                     });\n\tParallelFor (nse, [this](auto i)\n                     {\n                       for (auto & e : surfedges[i])\n                         e = -1;\n                     });\n\n\n        \n\t// keep existing edges\n\tcnt = 0;\n\tfor (int i = 0; i < edge2vert.Size(); i++)\n\t  cnt[edge2vert[i][0]]++;\n\tTABLE<int,PointIndex::BASE> vert2edge (cnt);\n\tfor (int i = 0; i < edge2vert.Size(); i++)\n\t  vert2edge.AddSave (edge2vert[i][0], i);\n\n\t// ensure all coarse grid and intermediate level edges\n\tcnt = 0;\n\t// for (int i = mesh->mlbetweennodes.Begin(); i < mesh->mlbetweennodes.End(); i++)\n        for (int i : mesh->mlbetweennodes.Range())\n\t  {\n\t    PointIndices<2> parents = Sort (mesh->mlbetweennodes[i]);\n\t    if (parents[0].IsValid()) cnt[parents[0]]++;\n\t  }\n\tTABLE<int,PointIndex::BASE> vert2vertcoarse (cnt);\n\t// for (int i = mesh->mlbetweennodes.Begin(); i < mesh->mlbetweennodes.End(); i++)\n        for (int i : mesh->mlbetweennodes.Range())\n\t  {\n\t    PointIndices<2> parents = Sort (mesh->mlbetweennodes[i]);\n\t    if (parents[0].IsValid()) vert2vertcoarse.AddSave (parents[0], parents[1]);\n\t  }\n\n\n\n\tint max_edge_on_vertex = 0;\n\tfor (int i = PointIndex::BASE; i < nv+PointIndex::BASE; i++)\n\t  {\n\t    int onv = vert2edge[i].Size() + vert2vertcoarse[i].Size() +\n              4*(vert2element)[i].Size() + 2*(vert2surfelement)[i].Size() + (vert2segment)[i].Size();\n\t    max_edge_on_vertex = max (onv, max_edge_on_vertex);\n\t  }\n\n        \n        // count edges associated with vertices\n        cnt = 0;\n\n        ParallelForRange\n          (mesh->GetNV(), // Points().Size(),\n           [&] (IntRange r)\n           {\n             auto begin = r.First();\n             auto end = r.Next();\n             // INDEX_CLOSED_HASHTABLE<int> v2eht(2*max_edge_on_vertex+10);\n             ngcore::ClosedHashTable<int, int> v2eht(2*max_edge_on_vertex+10);\n             for (PointIndex v = begin+IndexBASE<PointIndex>();\n                  v < end+IndexBASE<PointIndex>(); v++)\n               {\n                 v2eht.DeleteData();\n                 for (int ednr : vert2edge[v])\n                   {\n                     int v2 = edge2vert[ednr][1];\n                     v2eht.Set (v2, ednr);\n                   }\n\n                 size_t usedold = v2eht.UsedElements();\n                 \n                 for (int v2 : vert2vertcoarse[v])\n                   v2eht.Set (v2, 33);   // some value                   \n                 \n                 LoopOverEdges (*mesh, *this, v,\n                                [&] (INDEX_2 edge, int elnr, int loc_edge, int element_dim)\n                                {\n                                  v2eht.Set (edge[1], 33); // something                                  \n                                });\n                 \n                 cnt[v] = v2eht.UsedElements()-usedold;\n               }\n           }, TasksPerThread(4) );\n\n        // accumulate number of edges\n        int ned = edge2vert.Size();\n\n        for (size_t v : cnt.Range())\n          {\n            auto hv = cnt[v];\n            cnt[v] = ned;\n            ned += hv;\n          }\n        edge2vert.SetSize(ned);\n        edge2segment.SetSize(ned);\n        edge2segment = -1;\n\n        // INDEX_CLOSED_HASHTABLE<int> v2eht(2*max_edge_on_vertex+10);\n\t// NgArray<int> vertex2;\n\t// for (PointIndex v = IndexBASE<PointIndex>(); v < nv+IndexBASE<PointIndex>(); v++)\n\n        ParallelForRange\n          (mesh->GetNV(), // Points().Size(),\n           [&] (IntRange r)\n           {\n             auto begin = r.First();\n             auto end = r.Next();\n             // INDEX_CLOSED_HASHTABLE<int> v2eht(2*max_edge_on_vertex+10);\n             ngcore::ClosedHashTable<int, int> v2eht(2*max_edge_on_vertex+10);\n\n             Array<int> vertex2;\n             for (PointIndex v = begin+IndexBASE<PointIndex>();\n                  v < end+IndexBASE<PointIndex>(); v++)\n               {\n                 int ned = cnt[v];\n                 v2eht.DeleteData();            \n                 vertex2.SetSize0 ();\n                 \n                 for (int ednr : vert2edge[v])\n                   {\n                     int v2 = edge2vert[ednr][1];\n                     v2eht.Set (v2, ednr);\n                   }\n                 \n                 for (int v2 : vert2vertcoarse[v])\n                   if (!v2eht.Used(v2))\n                     {\n                       v2eht.Set (v2, 33);   // some value\n                       vertex2.Append (v2);\n                     }\n                 \n                 LoopOverEdges (*mesh, *this, v,\n                                [&](INDEX_2 edge, int elnr, int loc_edge, int element_dim)\n                                {\n                                  size_t pos;\n                                  if (v2eht.PositionCreate(edge[1], pos))\n                                    {\n                                      vertex2.Append (edge[1]);\n                                      v2eht.SetData (pos, 33);\n                                    }\n                                  /*\n                                  if (!v2eht.Used(edge.I2()))\n                                    {\n                                      vertex2.Append (edge.I2());\n                                      v2eht.Set (edge.I2(), 33); \n                                    }\n                                  */\n                                });\n                 \n                 QuickSort (vertex2);\n\n                 /*\n                 for (int j = 0; j < vertex2.Size(); j++)\n                   {\n                     v2eht.Set (vertex2[j], ned);\n                     edge2vert[ned] = { v, vertex2[j] };\n                     ned++;\n                   }\n                 */\n                 for (auto v2 : vertex2)\n                   {\n                     v2eht.Set (v2, ned);\n                     edge2vert[ned] = { v, v2 };\n                     ned++;\n                   }\n                 \n                 LoopOverEdges (*mesh, *this, v,\n                                [&](INDEX_2 edge, int elnr, int loc_edge, int element_dim)\n                                {\n                                  int edgenum = v2eht.Get(edge[1]);\n                                  switch (element_dim)\n                                    {\n                                    case 3:\n                                      edges[elnr][loc_edge] = edgenum;\n                                      break;\n                                    case 2:\n                                      surfedges[elnr][loc_edge] = edgenum;\n                                      break;\n                                    case 1:\n                                      segedges[elnr] = edgenum;\n                                      edge2segment[edgenum] = elnr;\n                                      break;\n                                    }\n                                });\n               }\n           }, TasksPerThread(4) );\n\n\n        if (build_parent_edges)\n        {\n          static Timer t(\"build_hierarchy\"); RegionTimer reg(t);\n          cnt = 0;\n          for (auto verts : edge2vert) cnt[verts[0]]++;\n          TABLE<int,PointIndex::BASE> vert2edge (cnt);\n          for (auto i : edge2vert.Range())\n            vert2edge.AddSave (edge2vert[i][0], i);\n\n          // build edge hierarchy:\n          parent_edges.SetSize (ned);\n          parent_edges = { -1, { -1, -1, -1 } };\n\n          for (size_t i = 0; i < ned; i++)\n          {\n            auto verts = edge2vert[i];  // 2 vertices of edge\n\n            if (verts[0] >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>() ||\n                verts[1] >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n              continue;\n\n            auto pa0 = mesh->mlbetweennodes[verts[0]]; // two parent vertices of v0\n            auto pa1 = mesh->mlbetweennodes[verts[1]]; // two parent vertices of v1\n\n            // both vertices are on coarsest mesh\n            if (!pa0[0].IsValid() && !pa1[0].IsValid())\n              continue;\n\n            int issplitedge = 0;\n            if (pa0[0] == verts[1] || pa0[1] == verts[1])\n              issplitedge = 1;\n            if (pa1[0] == verts[0] || pa1[1] == verts[0])\n              issplitedge = 2;\n\n            if (issplitedge)\n            {\n              // cout << \"split edge \" << endl;\n              // edge is obtained by splitting one edge into two parts:\n              auto paedge = issplitedge == 1 ? pa0 : pa1;\n\n              if (paedge[0] > paedge[1]) \n                Swap (paedge[0], paedge[1]);\n\n              for (int ednr : vert2edge[paedge[0]])\n                if (auto cverts = edge2vert[ednr]; cverts[1] == paedge[1])\n                {\n                  int orient = (paedge[0] == verts[0] || paedge[1] == verts[1]) ? 1 : 0;\n                  parent_edges[i] = { orient, { ednr, -1, -1 } };\t\t\t  \n                }\n            }\n            else\n            {\n              bool bisect_edge = false;\n              // edge is splitting edge in middle of triangle:\n              for (int j = 1; j <= 2; j++)\n              {\n                IVec<2,PointIndex> paedge1, paedge2, paedge3;\n                int orient_inner = 0;\n                if (j == 1)\n                {\n                  paedge1 = IVec<2> (pa0[0], verts[1]);\n                  paedge2 = IVec<2> (pa0[1], verts[1]);\n                  paedge3 = IVec<2> (pa0[0], pa0[1]);\n                  orient_inner = 0;\n                }\n                else\n                {\n                  paedge1 = IVec<2> (pa1[0], verts[0]);\n                  paedge2 = IVec<2> (pa1[1], verts[0]);\n                  paedge3 = IVec<2> (pa1[0], pa1[1]);\n                  orient_inner = 1;\n                }\n                if (paedge1[0] > paedge1[1]) \n                  Swap (paedge1[0], paedge1[1]);\n                if (paedge2[0] > paedge2[1]) \n                  Swap (paedge2[0], paedge2[1]);\n                if (paedge3[0] > paedge3[1]) \n                  Swap (paedge3[0], paedge3[1]);\n\n                // if first vertex number is -1, then don't try to find entry in node2edge hash table\n                if ( !paedge1[0].IsValid() || !paedge2[0].IsValid() )\n                  continue;\n\n                int paedgenr1=-1, paedgenr2=-1, paedgenr3=-1, orient1 = 0, orient2 = 0;\n                for (int ednr : vert2edge[paedge1[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge1[1])\n                  {\n                    paedgenr1 = ednr;\n                    orient1 = (paedge1[0] == verts[0] || paedge1[1] == verts[1]) ? 1 : 0;\n                  }\n                for (int ednr : vert2edge[paedge2[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge2[1])\n                  {\n                    paedgenr2 = ednr;\n                    orient2 = (paedge2[0] == verts[0] || paedge2[1] == verts[1]) ? 1 : 0;\n                  }\n\n                for (int ednr : vert2edge[paedge3[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge3[1])\n                    paedgenr3 = ednr;\n\n                if (paedgenr1 != -1 && paedgenr2 != -1){\n                  bisect_edge = true;\n                  parent_edges[i] = { orient1+2*orient2+4*orient_inner, { paedgenr1, paedgenr2, paedgenr3 } };\n                }\n              }\n\n              if (!bisect_edge) // not a bisect edge (then a red edge)\n              {\n                IVec<2,PointIndex> paedge1, paedge2, paedge3;\n                int orient1 = 0, orient2 = 0, orient3=0;\n                // int orient_inner = 0;\n                paedge1 = IVec<2,PointIndex> (pa0[0], pa0[1]);\n                paedge2 = IVec<2,PointIndex> (pa1[0], pa1[1]);\n                // find common vertex and the third pa edge\n                if (pa0[0]==pa1[0]){// 00\n                  //orient1 = 0; \n                  orient2 = 1; \n                  if (pa0[1]<pa1[1]){\n                    orient3 = 1;\n                    paedge3 = IVec<2,PointIndex> (pa0[1], pa1[1]);\n                  }else{\n                    //orient3 = 0;\n                    paedge3 = IVec<2,PointIndex> (pa1[1], pa0[1]);\n                  }\n                }\n                else if (pa0[0]==pa1[1]){//01\n                  //orient1 = 0; \n                  //orient2 = 0; \n                  if (pa0[1]<pa1[0]){\n                    orient3 = 1;\n                    paedge3 = IVec<2,PointIndex> (pa0[1], pa1[0]);\n                  }else{\n                    //orient3 = 0;\n                    paedge3 = IVec<2,PointIndex> (pa1[0], pa0[1]);\n                  }\n                }\n                else if (pa0[1]==pa1[0]){//10\n                  orient1 = 1; \n                  orient2 = 1; \n                  if (pa0[0]<pa1[1]){\n                    orient3 = 1;\n                    paedge3 = IVec<2,PointIndex> (pa0[0], pa1[1]);\n                  }else{\n                    //orient3 = 0;\n                    paedge3 = IVec<2,PointIndex> (pa1[1], pa0[0]);\n                  }\n                }\n                else if (pa0[1]==pa1[1]){//11\n                  orient1 = 1; \n                  //orient2 = 0; \n                  if (pa0[0]<pa1[0]){\n                    orient3 = 1;\n                    paedge3 = IVec<2,PointIndex> (pa0[0], pa1[0]);\n                  }else{\n                    //orient3 = 0;\n                    paedge3 = IVec<2,PointIndex> (pa1[0], pa0[0]);\n                  }\n                }\n\n                int paedgenr1=-1, paedgenr2=-1, paedgenr3=-1;\n                for (int ednr : vert2edge[paedge1[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge1[1])\n                    paedgenr1 = ednr;\n                for (int ednr : vert2edge[paedge2[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge2[1])\n                    paedgenr2 = ednr;\n\n                for (int ednr : vert2edge[paedge3[0]])\n                  if (auto cverts = edge2vert[ednr]; cverts[1] == paedge3[1])\n                    paedgenr3 = ednr;\n\n                parent_edges[i] = { 8+orient1+2*orient2+4*orient3, { paedgenr1, paedgenr2, paedgenr3 } };\n\n                //cout <<8+orient1+2*orient2+4*orient3  <<\":\"<<paedgenr1 <<\", \"<< paedgenr2 << \", \"<< paedgenr3 << endl;\n              }\n\n\n              // TODO: quad edges\n              /*\n                 if (parentedges[i][0] == -1)\n                 {\n              // quad split\n              if (pa1[0] != pa2[0] && \n              pa1[0] != pa2[1] && \n              pa1[1] != pa2[0] && \n              pa1[1] != pa2[1])\n              for (int j = 1; j <= 2; j++)\n              {\n              IVec<2> paedge1, paedge2;\n              if (j == 1)\n              {\n              paedge1 = IVec<2> (pa1[0], pa2[0]);\n              paedge2 = IVec<2> (pa1[1], pa2[1]);\n              }\n              else\n              {\n              paedge1 = IVec<2> (pa1[0], pa2[1]);\n              paedge2 = IVec<2> (pa1[1], pa2[0]);\n              }\n\n              int paedgenr1 = 0, paedgenr2 = 0;\n              int orient1 = 1, orient2 = 1;\n\n              if (paedge1[0] > paedge1[1]) \n              {\n              Swap (paedge1[0], paedge1[1]);\n              orient1 = 0;\n              }\n              if (paedge2[0] > paedge2[1]) \n              {\n              Swap (paedge2[0], paedge2[1]);\n              orient2 = 0;\n              }\n\n              if ( paedge1[0] == -1 || paedge2[0] == -1 )\n              continue;\n\n              if (node2edge.Used (paedge1) && node2edge.Used (paedge2))\n              {\n              paedgenr1 = node2edge.Get (paedge1);\n              paedgenr2 = node2edge.Get (paedge2);\n              parentedges[i][0] = 2 * paedgenr1 + orient1;\t      \n              parentedges[i][1] = 2 * paedgenr2 + orient2;\t      \n              }\n              }\n              }\n\n              if (parentedges[i][0] == -1)\n              {\n              // triangle split into quad+trig (from anisotropic pyramids)\n              for (int j = 0; j < 2; j++)\n              for (int k = 0; k < 2; k++)\n              {\n              IVec<2> paedge (pa1[1-j], pa2[1-k]);\n              int orientpa = 1;\n              if (paedge[0] > paedge[1]) \n              {\n              Swap (paedge[0], paedge[1]);\n              orientpa = 0;\n              }\t\n              if (pa1[j] == pa2[k] && node2edge.Used(paedge))\n              {\n              int paedgenr = node2edge.Get (paedge);\n              parentedges[i][0] = 2 * paedgenr + orientpa;\n              }\n              }\n\n              }\n              */\n            }\n\n          }\n\n          /*\n             for (int i : Range(parent_edges))\n             {\n             auto [info, nrs] = parent_edges[i];\n             cout << \"edge \" << i << \" has \" << info << \", nrs = \" << nrs[0] << \" \" << nrs[1] << endl;\n             }\n             */\n        }\n      }\n    \n\n    // edge hashtable:: needed for getting parent faces\t\n    ngcore::ClosedHashTable<IVec<2>, int> v2e(nv);\n    if (build_parent_faces)\n      for (auto i : Range(edge2vert))\n        {\n          auto edge = edge2vert[i];\n          IVec<2> e2(edge[0], edge[1]);\n          e2.Sort();\n          v2e[e2] = i;\n        }\n\n    \n    // generate faces\n    if (buildfaces) \n      {\n\tstatic Timer timer2(\"topology::buildfaces\");\n\t// static int timer2a = NgProfiler::CreateTimer (\"topology::buildfacesa\");\n\t// static int timer2b = NgProfiler::CreateTimer (\"topology::buildfacesb\");\n        // static int timer2b1 = NgProfiler::CreateTimer (\"topology::buildfacesb1\");\n\t// static int timer2c = NgProfiler::CreateTimer (\"topology::buildfacesc\");\n\tRegionTimer reg2 (timer2);\n\n\tif (id == 0)\n\t  PrintMessage (5, \"Update faces \");\n\n        // NgProfiler::StartTimer (timer2a);\n\n\tfaces.SetSize(ne);\n\tsurffaces.SetSize(nse);\n  \n\n\tcnt = 0;\n\tfor (int i = 0; i < face2vert.Size(); i++)\n\t  cnt[face2vert[i][0]]++;\n\tTABLE<int,PointIndex::BASE> vert2oldface(cnt);\n\tfor (int i = 0; i < face2vert.Size(); i++)\n\t  vert2oldface.AddSave (face2vert[i][0], i);\n\n        // find all potential intermediate faces\n        Array<IVec<3>> intermediate_faces;\n        if (build_parent_faces)\n          {\n            for (ElementIndex ei = 0; ei < ne; ei++)\n              for (int i = 0; i < 4; i++)\n                {\n                  Element2d face;\n                  // cout << \"element: \" << (*mesh)[ei].PNums() << endl;\n                  (*mesh)[ei].GetFace(i+1, face);\n                  // cout << \"face \" << face.PNums() << endl;\n                  IVec<3,PointIndex> f3 = { face[0], face[1], face[2] };\n                  for (int j = 0; j < 3; j++)\n                    {\n                      PointIndex v = f3[j];\n                      if (v >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n                        continue;\n\n                      auto pa = mesh->mlbetweennodes[v];\n                      for (int k = 0; k < 2; k++)\n                        if (f3.Contains(pa[k]))\n                          {\n                            PointIndex v0 = pa[k]; // also in face\n                            PointIndex v1 = pa[1-k];\n                            PointIndex v2 = f3[0]-v+f3[1]-v0+f3[2];\n                            // if there is an edge connecting v1 and v2, accept\n                            // the new face\n                            IVec<2> parentedge(v1, v2);\n                            parentedge.Sort();\n                            if (v2e.Used(parentedge)){ \n                              IVec<3> cf3 = { v0, v1, v2 };\n                              cf3.Sort();\n                              // cout << \"intermediate: \" << cf3 << \" of \" << f3 << endl;\n                              intermediate_faces.Append (cf3);\n                            }\n                          }\n                    }\n                }\n\n            for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n              {\n                const Element2d & sel = (*mesh)[sei];\n                IVec<3,PointIndex> f3 = { sel[0], sel[1], sel[2] };\n                for (int j = 0; j < 3; j++)\n                  {\n                    PointIndex v = f3[j];\n                    if (v >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n                      continue;\n                    \n                    auto pa = mesh->mlbetweennodes[v];\n                    for (int k = 0; k < 2; k++)\n                      if (f3.Contains(pa[k]))\n                        {\n                          PointIndex v0 = pa[k]; // also in face\n                          PointIndex v1 = pa[1-k];\n                          PointIndex v2 = f3[0]-v+f3[1]-v0+f3[2];\n                          // if there is an edge connecting v1 and v2, accept\n                          // the new face\n                          IVec<2> parentedge(v1, v2);\n                          parentedge.Sort();\n                          if (v2e.Used(parentedge)){ \n                            IVec<3> cf3 = { v0, v1, v2 };\n                            cf3.Sort();\n                            // cout << \"intermediate: \" << cf3 << \" of \" << f3 << endl;\n                            intermediate_faces.Append (cf3);\n                          }\n                        }\n                  }\n              }\n\n          }\n\tcnt = 0;\n\tfor (int i = 0; i < intermediate_faces.Size(); i++)\n\t  cnt[intermediate_faces[i][0]]++;\n\tTABLE<int,PointIndex::BASE> vert2intermediate(cnt);\n\tfor (int i = 0; i < intermediate_faces.Size(); i++)\n\t  vert2intermediate.AddSave (intermediate_faces[i][0], i);\n        // cout << \"vert2intermediate = \" << endl << vert2intermediate << endl;\n\n        \n\tfor (int elnr = 0; elnr < ne; elnr++)\n\t  for (int j = 0; j < 6; j++)\n\t    faces[elnr][j] = -1;\n\t\n\n\tint max_face_on_vertex = 0;\n\tfor (PointIndex i = IndexBASE<PointIndex>(); i < nv+IndexBASE<PointIndex>(); i++)\n\t  {\n\t    int onv = vert2oldface[i].Size() + vert2element[i].Size() + vert2surfelement[i].Size();\n\t    max_face_on_vertex = max (onv, max_face_on_vertex);\n\t  }\n\t\n\n\n\n        // NgProfiler::StopTimer (timer2a);\n        // NgProfiler::StartTimer (timer2b);\n\n        // INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*max_face_on_vertex+10);         \n\n\tint oldnfa = face2vert.Size();\n\n        // count faces associated with vertices\n        cnt = 0;\n        // for (auto v : mesh.Points().Range())\n        // NgProfiler::StartTimer (timer2b1);\n        ParallelForRange\n          (mesh->GetNV(), // Points().Size(),\n           [&] (IntRange r)\n            {\n              // auto begin = r.First();\n              // auto end = r.Next();\n              // INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*max_face_on_vertex+10);\n              NgClosedHashTable<INDEX_3, int> vert2face(2*max_face_on_vertex+10);\n              // for (PointIndex v = begin+PointIndex::BASE;\n              // v < end+PointIndex::BASE; v++)\n              for (PointIndex v : r+PointIndex::BASE)                \n                {\n                  vert2face.DeleteData();\n                  \n                  for (int j = 0; j < vert2oldface[v].Size(); j++)\n                    {\n                      int fnr = vert2oldface[v][j];\n                      INDEX_3 face (face2vert[fnr][0],\n                                    face2vert[fnr][1],\n                                    face2vert[fnr][2]);\n                      vert2face.Set (face, 33);  // something\n                    }\n                  int cnti = 0;\n\n                  for (int j = 0; j < vert2intermediate[v].Size(); j++)\n                    {\n                      int fnr = vert2intermediate[v][j];\n                      INDEX_3 face (intermediate_faces[fnr][0],\n                                    intermediate_faces[fnr][1],\n                                    intermediate_faces[fnr][2]);\n                      face.Sort();\n                      if (!vert2face.Used(face))\n                        {\n                          cnti++;\n                          vert2face.Set (face, 33); // something\n                        }\n                    }\n                  LoopOverFaces (*mesh, *this, v,\n                                 [&] (INDEX_4 i4, int elnr, int j, bool volume)\n                                 {\n                                   INDEX_3 face(i4[0], i4[1], i4[2]);\n                                   if (!vert2face.Used (face))\n                                     {\n                                       cnti++;\n                                       vert2face.Set (face, 33); // something\n                                     }\n                                 });\n                  cnt[v] = cnti;\n                }\n            }, TasksPerThread(4) );\n        // NgProfiler::StopTimer (timer2b1);\n        \n        // accumulate number of faces\n        int nfa = oldnfa;\n        // for (auto v : Range(mesh->GetNV())) // Points().Range())\n        // for (size_t v = 0; v < mesh->GetNV(); v++)\n        for (auto v : cnt.Range())\n          {\n            auto hv = cnt[v];\n            cnt[v] = nfa;\n            nfa += hv;\n          }\n        face2vert.SetSize(nfa);\n        \n\n        ParallelForRange\n          (mesh->GetNV(),\n           [&] (IntRange r)\n            {\n              // auto begin = r.First();\n              // auto end = r.Next();\n              // INDEX_3_CLOSED_HASHTABLE<int> vert2face(2*max_face_on_vertex+10);\n              NgClosedHashTable<INDEX_3, int> vert2face(2*max_face_on_vertex+10);\n              /*\n              for (PointIndex v = begin+PointIndex::BASE;\n                   v < end+PointIndex::BASE; v++)\n              */\n              for (PointIndex v : r+PointIndex::BASE)\n                {\n                  int first_fa = cnt[v];\n                  int nfa = first_fa;\n                  vert2face.DeleteData();\n                  \n                  for (int j = 0; j < vert2oldface[v].Size(); j++)\n                    {\n                      int fnr = vert2oldface[v][j];\n                      INDEX_3 face (face2vert[fnr][0], \n                                    face2vert[fnr][1],\n                                    face2vert[fnr][2]);\n                      vert2face.Set (face, fnr);\n                    }\n                  \n                  for (int j = 0; j < vert2intermediate[v].Size(); j++)\n                    {\n                      int fnr = vert2intermediate[v][j];\n                      INDEX_3 face (intermediate_faces[fnr][0],\n                                    intermediate_faces[fnr][1],\n                                    intermediate_faces[fnr][2]);\n                      face.Sort();\n                      /*\n                      if (!vert2face.Used(face))\n                        {\n                          face2vert[nfa] = { face[0], face[1], face[2], 0 }; // i4;\n                          vert2face.Set (face, nfa);\n                          nfa++;\n                        }\n                      */\n                      size_t pos;\n                      if (vert2face.PositionCreate(face, pos))\n                        {\n                          face2vert[nfa] = { face[0], face[1], face[2], PointIndex::BASE-1 }; // i4;\n                          vert2face.SetData (pos, face, nfa);\n                          nfa++;\n                        }\n                      \n                    }\n                  \n                  LoopOverFaces (*mesh, *this, v,\n                                 [&] (INDEX_4 i4, int elnr, int j, bool volume)\n                                 {\n                                   INDEX_3 face(i4.I1(), i4.I2(), i4.I3());\n                                   /*\n                                   if (!vert2face.Used (face))\n                                     {\n                                       face2vert[nfa] = { i4[0], i4[1], i4[2], i4[3] }; // i4;\n                                       vert2face.Set (face, nfa);\n                                       nfa++;\n                                     }\n                                   */\n                                   size_t pos;\n                                   if (vert2face.PositionCreate(face, pos))\n                                     {\n                                       face2vert[nfa] = { i4[0], i4[1], i4[2], i4[3] }; // i4;\n                                       vert2face.SetData (pos, face, nfa);\n                                       nfa++;\n                                     }\n                                 });\n                  \n                  \n                  QuickSort (face2vert.Range(first_fa, nfa));\n                  \n                  for (int j = first_fa; j < nfa; j++)\n                    {\n                      if (face2vert[j][0] == v)\n                        {\n                          INDEX_3 face (face2vert[j][0], \n                                        face2vert[j][1], \n                                        face2vert[j][2]);\n                          vert2face.Set (face, j);\n                        }\n                      else\n                        break;\n                    }\n                  \n                  \n                  LoopOverFaces (*mesh, *this, v,\n                                 [&] (INDEX_4 i4, int elnr, int j, bool volume)\n                                 {\n                                   INDEX_3 face(i4.I1(), i4.I2(), i4.I3());\n                                   int facenum = vert2face.Get(face);\n                                   if (volume)\n                                     faces[elnr][j] = facenum;\n                                   else\n                                     surffaces[elnr] = facenum;\n                                 });\n                }\n            }, TasksPerThread(4) );\n        \n\n\t// *testout << \"face2vert = \" << endl << face2vert << endl;\n\n        // NgProfiler::StopTimer (timer2b);\n        // NgProfiler::StartTimer (timer2c);\n\n\n\tface2surfel.SetSize (nfa);\n\tface2surfel = SurfaceElementIndex::INVALID;\n\tfor (SurfaceElementIndex sei = 0; sei < nse; sei++)\n\t  face2surfel[GetFace(sei)] = sei;\n\n\t/*\n\t  cout << \"build table complete\" << endl;\n\n\t  cout << \"faces = \" << endl;\n\n\t  cout << \"face2vert = \" << endl << face2vert << endl;\n\t  cout << \"surffaces = \" << endl << surffaces << endl;\n\t  cout << \"face2surfel = \" << endl << face2surfel << endl;\n\t*/\n\n\t\n\tsurf2volelement.SetSize (nse);\n        // surf2volelement = INDEX_2(0,0);\n        surf2volelement = { ElementIndex::INVALID, ElementIndex::INVALID };\n\n        (*tracer) (\"Topology::Update build surf2vol\", false);        \n\t// for (int i = 0; i < ne; i++)\n        ParallelFor (ne, [this](auto i)\n                     {\n                       for (int j = 0; j < 6; j++)\n                         {\n                           // int fnum = (faces.Get(i)[j]+7) / 8;\n                           int fnum = faces[i][j];\n                           if (fnum >= 0 && face2surfel[fnum].IsValid())\n                             {\n                               SurfaceElementIndex sel = face2surfel[fnum];\n                               surf2volelement[sel][1] = surf2volelement[sel][0];\n                               surf2volelement[sel][0] = i; // +1;\n                             }\n                         }});\n        (*tracer) (\"Topology::Update build surf2vol\", true);        \n\n\tface2vert.SetAllocSize (face2vert.Size());\n\n\t// face table complete\n\n\n#ifdef PARALLEL\n\t// (*testout) << \" RESET Paralleltop\" << endl;\n\t// paralleltop.Reset ();\n#endif\n\n        (*tracer) (\"Topology::Update count face_els\", false);\n\tNgArray<short int> face_els(nfa), face_surfels(nfa);\n\tface_els = 0;\n\tface_surfels = 0;\n\n        ParallelForRange\n          (ne,\n           [&] (IntRange r)\n            {\n              /*\n              NgArray<int> hfaces;              \n              for (ElementIndex ei : r)\n              {\n                  GetElementFaces (ei+1, hfaces);\n                  for (auto f : hfaces)\n                    AsAtomic(face_els[f-1])++;\n                }\n              */\n              for (ElementIndex ei : r)\n                for (auto f : GetFaces(ei))\n                  AsAtomic(face_els[f])++;\n              \n            }, TasksPerThread(4));\n        /*\n\tfor (int i = 1; i <= nse; i++)\n\t  face_surfels[GetSurfaceElementFace1 (i)-1]++;\n        */\n        for (auto sei : Range(mesh->SurfaceElements()))\n\t  face_surfels[GetFace(sei)]++;          \n        (*tracer) (\"Topology::Update count face_els\", true);\n\n\n\tif (ne)\n\t  {\n\t    int cnt_err = 0;\n\t    for (int i = 0; i < nfa; i++)\n\t      {\n\t\t/*\n\t\t  (*testout) << \"face \" << i << \" has \" << int(face_els[i]) << \" els, \" \n\t\t  << int(face_surfels[i]) << \" surfels, tot = \"\n\t\t  << face_els[i] + face_surfels[i] << endl; \n\t\t*/\n\t\tif (face_els[i] + face_surfels[i] == 1)\n\t\t  {\n\t\t    cnt_err++;\n#ifdef PARALLEL\n\t\t    if ( ntasks > 1 )\n\t\t      {\n\t\t\tcontinue;\n\t\t\t// if ( !paralleltop.DoCoarseUpdate() ) continue;\n\t\t      }\n\t\t    else\n#endif\n\t\t      {\n\t\t\t(*testout) << \"illegal face : \" << i << \", cnt = \" << face_els[i]+face_surfels[i] << endl;\n\t\t\t(*testout) << \"points = \"\n                                   << face2vert[i][0] << \",\"\n                                   << face2vert[i][1] << \",\"\n                                   << face2vert[i][2] << \",\"\n                                   << face2vert[i][3] \n                                   << endl;\n\t\t\t(*testout) << \"pos = \";\n\t\t\tfor (int j = 0; j < 4; j++)\n                          if (face2vert[i][j].IsValid())\n                            (*testout) << (*mesh)[(PointIndex)face2vert[i][j]] << \" \";\n\t\t\t(*testout) << endl;\n\n\t\t\tFlatArray<ElementIndex> vertels = GetVertexElements (face2vert[i][0]);\n\t\t\tfor (int k = 0; k < vertels.Size(); k++)\n\t\t\t  {\n\t\t\t    int elfaces[10], orient[10];\n\t\t\t    int nf = GetElementFaces (vertels[k]+1, elfaces, orient);\n\t\t\t    for (int l = 0; l < nf; l++)\n\t\t\t      if (elfaces[l] == i)\n\t\t\t\t{\n                                  (*testout) << \"is face of element \" << vertels[k] << endl;\n\t\t\t    \n\t\t\t\t  if (mesh->coarsemesh && mesh->hpelements->Size() == mesh->GetNE() )\n\t\t\t\t    {\n\t\t\t\t      const HPRefElement & hpref_el =\n\t\t\t\t\t(*mesh->hpelements) [ (*mesh)[vertels[k]].GetHpElnr()];\n\t\t\t\t      (*testout) << \"coarse eleme = \" << hpref_el.coarse_elnr << endl;\n\t\t\t\t    }\n\n\t\t\t\t}\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\n\t    if (cnt_err && ntasks == 1)\n\t      cout << IM(5) << cnt_err << \" elements are not matching !!!\" << endl;\n\t  }\n        // NgProfiler::StopTimer (timer2c);\n\n\n        if (build_parent_faces)\n          {\n            // tets only\n            if (id == 0)\n              PrintMessage (5, \"build face hierarchy\");\n\n            // cout << \"f2v = \" << face2vert << endl;\n            \n            ngcore::ClosedHashTable<IVec<3>, int> v2f(nv);\n            for (auto i : Range(face2vert))\n              {\n                auto face = face2vert[i];\n                IVec<3> f3(face[0], face[1], face[2]);\n                f3.Sort();\n                v2f[f3] = i;\n              }\n\n            // cout << \"v2f:\" << endl << v2f << endl;\n            \n            parent_faces.SetSize (nfa);\n            parent_faces = { -1, { -1, -1, -1, -1 } };\n\n            for (auto i : Range(nfa))\n              {\n                IVec<3,PointIndex> f3(face2vert[i][0], face2vert[i][1], face2vert[i][2]);\n\n\n                // face on coarses level ?\n                bool all_vert_coarse = true;\n                for (int k = 0; k < 3; k++)\n                  {\n                    PointIndex vb = f3[k]; \n                    if (vb >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n                      continue;\n                    auto parents = mesh->mlbetweennodes[vb];\n                    if (parents[0] >= IndexBASE<PointIndex>())\n                      all_vert_coarse = false;\n                  }\n                if (all_vert_coarse) continue;\n\n                \n                \n                // find a vertex, such that one of its parent is a trig vertex\n                bool issplit = false;\n                for (int k = 0; k < 3; k++)\n                  {\n                    PointIndex vb = f3[k]; // assume vb as the new bisect vert\n                    if (vb >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n                      continue;\n                    auto parents = mesh->mlbetweennodes[vb];\n                    \n                    // is face part of one parent face (boundary-face) ?\n                    for (int j = 0; j < 2; j++)\n                      {\n                        if (f3.Contains(parents[j]))\n                          {\n                            PointIndex v0 = parents[j];\n                            PointIndex v1 = parents[1-j];\n                            \n                            // the third one, on the tip\n                            PointIndex v2 = f3[0]-v0+f3[1]-vb+f3[2];\n                            \n                            // if there is an edge connecting v1 and v2, accept\n                            // the new face\n                            IVec<2> parentedge(v1, v2);\n                            parentedge.Sort();\n                            if (v2e.Used(parentedge)){ \n                              IVec<3> parentverts(v0, v1, v2);\n                              parentverts.Sort();\n\n                              int classnr = 0;\n                              if (v2 > vb) { Swap (v2, vb); classnr += 1; }                            \n                              if (v0 > v1) { Swap (v0, v1); classnr += 2; }\n                              if (v1 > v2) { Swap (v1, v2); classnr += 4; }\n                              if (v0 > v1) { Swap (v0, v1); classnr += 8; }\n\n                              if (v2f.Used(parentverts))\n                              {\n                                int pafacenr = v2f[parentverts];\n                                // cout << \"parent-face = \" << pafacenr << endl;\n                                parent_faces[i] = { classnr, { pafacenr, -1, -1, -1 } };\n                              }\n                              else\n                              {\n                                cout << \"missing parent face: \" << parentverts << endl;\n                              }\n                              issplit=true;\n                              break;\n                            }\n                          }\n                        }\n                  }\n\n                /*\n                // is face a new face (bisect-face) ?\n                if (!issplit)\n                  for (int k = 0; k < 3; k++)\n                    {\n                      PointIndex vb = f3[k]; // assume vb as the new bisect vert\n                      if (vb >= mesh->mlbetweennodes.Size()+PointIndex::BASE)\n                        continue;\n                      auto parents = mesh->mlbetweennodes[vb];\n\n                      PointIndex v0 = parents[0];\n                      PointIndex v1 = parents[1];\n                      PointIndex v2 = f3[(k+1)%3];\n                      PointIndex v3 = f3[(k+2)%3];\n                      IVec<3> parentedge1(v0, v2);\n                      parentedge1.Sort();\n                      IVec<3> parentedge2(v0, v3);\n                      parentedge2.Sort();\n                      IVec<3> parentedge3(v1, v2);\n                      parentedge3.Sort();\n                      IVec<3> parentedge4(v1, v3);\n                      parentedge4.Sort();\n                      // if edges [v0,v2], [v0, v3], [v1,v2], [v1,v3] exists\n                      // then vb is the bisecting edge\n                      if (v2e.Used(parentedge1) && v2e.Used(parentedge2) \n                          && v2e.Used(parentedge3) && v2e.Used(parentedge4) \n                         ){\n                        int classnr;\n                        if (k==2){// vb is the largest vert: 6 cases\n                          // by default v0 < v1, v2 < v3\n                          if (v1 < v2) classnr = 0;\n                          else if (v1 < v3 && v0 < v2) classnr = 1;\n                          else if (v0 < v2) classnr = 2;\n                          else if (v1 < v3) classnr = 3;\n                          else if (v0 < v3) classnr = 4;\n                          else classnr = 5;\n                        }else if (k==1){// vb is the second largest vert: 3 cases\n                          // by default v0 < v1, v3 < v2\n                          if (v1 < v3) classnr = 6;\n                          else if (v0 < v3) classnr = 7;\n                          else classnr = 8;\n                        }else {// vb is the third largest vert: 1 case\n                          // by default v0 < v1 < vb <  v2 < v3\n                          classnr=9;\n                        }\n                        IVec<3> parentverts1(v0, v2, v3);\n                        parentverts1.Sort();\n                        IVec<3> parentverts2(v1, v2, v3);\n                        parentverts2.Sort();\n                        IVec<3> parentverts3(v0, v1, v2);\n                        parentverts3.Sort();\n                        IVec<3> parentverts4(v0, v1, v3);\n                        parentverts4.Sort();\n                        int pafacenr1=-1, pafacenr2=-1, pafacenr3=-1, pafacenr4=-1;\n                        if (v2f.Used(parentverts1))\n                        {\n                          pafacenr1 = v2f[parentverts1];\n                          // cout << \"parent-face1 = \" << pafacenr1<< endl ;\n                        }\n                        if (v2f.Used(parentverts2))\n                        {\n                          pafacenr2 = v2f[parentverts2];\n                          // cout << \"parent-face2 = \" << pafacenr2<< endl  ;\n                        }\n                        if (v2f.Used(parentverts3))\n                        {\n                          pafacenr3 = v2f[parentverts3];\n                          // cout << \"parent-face3 = \" << pafacenr3<< endl  ;\n                        }\n                        if (v2f.Used(parentverts4))\n                        {\n                          pafacenr4 = v2f[parentverts4];\n                          // cout << \"parent-face4 = \" << pafacenr4<< endl  ;\n                        }\n\n                        if (k == 0 || k == 2)\n                          parent_faces[i] = { classnr, { pafacenr2, pafacenr1,\n                                                         pafacenr4, pafacenr3} };\n                        else\n                          parent_faces[i] = { classnr, { pafacenr2, pafacenr1,\n                                                         pafacenr3, pafacenr4} };\n                        break;\n                      }\n                    }\n                */\n\n                // is face a new face (bisect-face) ?\n                if (!issplit)\n                  for (int k = 0; k < 3; k++)\n                    {\n                      PointIndex vb = f3[k]; // assume vb as the new bisect vert\n                      if (vb >= mesh->mlbetweennodes.Size()+IndexBASE<PointIndex>())\n                        continue;\n                      auto parents = mesh->mlbetweennodes[vb];\n\n                      PointIndex v0 = parents[0];\n                      PointIndex v1 = parents[1];\n                      PointIndex v2 = f3[(k+1)%3];\n                      PointIndex v3 = f3[(k+2)%3];\n                      IVec<2> parentedge1(v0, v2);\n                      parentedge1.Sort();\n                      IVec<2> parentedge2(v0, v3);\n                      parentedge2.Sort();\n                      IVec<2> parentedge3(v1, v2);\n                      parentedge3.Sort();\n                      IVec<2> parentedge4(v1, v3);\n                      parentedge4.Sort();\n\n                      // if edges [v0,v2], [v0, v3], [v1,v2], [v1,v3] exists\n                      // then vb is the bisecting edge\n                      if (v2e.Used(parentedge1) && v2e.Used(parentedge2) \n                          && v2e.Used(parentedge3) && v2e.Used(parentedge4))\n                        {\n                          int verts[5] = { v0, v1, v2, v3, vb };\n                          /*\n                          cout << \"verts5: \";\n                          for (int j = 0; j < 5; j++)\n                            cout << verts[j] << \" \";\n                          */\n                          // classify permutation of verts\n                          int classnr = 0;\n                          for (int j = 0; j < 4; j++)\n                            {\n                              int maxk = 0;\n                              for (int k = 0; k < 5-j; k++)\n                                if (verts[k] > verts[maxk]) maxk = k;\n                              // compress\n                              for (int k = maxk; k < 4-j; k++)\n                                verts[k] = verts[k+1];\n                              classnr = maxk + (5-j) * classnr;\n                            }\n                          // cout << \"classnr = \" << classnr << endl;\n\n                          IVec<3> parentverts1(v1, v2, v3);\n                          parentverts1.Sort();\n                          IVec<3> parentverts2(v0, v2, v3);\n                          parentverts2.Sort();\n                          IVec<3> parentverts3(v0, v1, v3);\n                          parentverts3.Sort();\n                          IVec<3> parentverts4(v0, v1, v2);\n                          parentverts4.Sort();\n                          \n                          if (!v2f.Used(parentverts1) || !v2f.Used(parentverts2) ||\n                              !v2f.Used(parentverts3) || !v2f.Used(parentverts4))\n                            {\n                              cout << \"all edges are used, but not faces ????\" << endl;\n                              continue;\n                            }\n                                        \n                          int pafacenr1 = v2f[parentverts1];\n                          int pafacenr2 = v2f[parentverts2];\n                          int pafacenr3 = v2f[parentverts3];\n                          int pafacenr4 = v2f[parentverts4];\n\n                          \n                          parent_faces[i] = { classnr, { pafacenr1, pafacenr2,\n                                                         pafacenr3, pafacenr4} };\n                          \n                          break;\n                        }\n                    }\n\n                auto [info, nrs] = parent_faces[i];\n                if (nrs[0] == -1){\n                  // hacking for tet red refinements\n                  PointIndex v0 = f3[0];\n                  auto pa0 = mesh->mlbetweennodes[v0];\n                  auto pa1 = mesh->mlbetweennodes[f3[1]];\n                  auto pa2 = mesh->mlbetweennodes[f3[2]];\n                  // v0 is a coarse vertex ==> f3 is a boundary face\n                  if (v0==pa1[0] || v0==pa1[1]){\n                    if (pa1[0]==v0){// type 0: bottom left corner\n                      IVec<3> parentverts(v0, pa1[1], pa2[1]);\n                      int pafacenr = v2f[parentverts];\n                      parent_faces[i] = { 16, { pafacenr, -1, -1, -1} };\n                      //cout << \"f \"<<i<<\":pf \"<< pafacenr<< \"A\" <<endl;\n                    }else if (pa2[0]==v0) {// type 1: bottom right corner\n                      IVec<3> parentverts(pa1[0], v0, pa2[1]);\n                      int pafacenr = v2f[parentverts];\n                      parent_faces[i] = { 17, { pafacenr, -1, -1, -1} };\n                      //cout << \"f \"<<i<<\":pf \"<< pafacenr<< \"B\" <<endl;\n                    }else if (pa1[1]==v0){// type 2: top left corner\n                      IVec<3> parentverts(pa1[0], pa2[0], v0);\n                      int pafacenr = v2f[parentverts];\n                      parent_faces[i] = { 18, { pafacenr, -1, -1, -1} };\n                      //cout << \"f \"<<i<<\":pf \"<< pafacenr<< \"C\" <<endl;\n                    }else{\n                      cout << \"************************** unhandled parent-face case **********************\" << endl;\n                    }\n                  }\n                  else{// all vertices are on fine level [fff]\n                    // Here we only work with boundary fff face\n                    if (pa0[0]==pa1[0] && pa0[1]==pa2[0] && pa1[1]==pa2[1]){//type 3 bdry face\n                      IVec<3> parentverts(pa0[0], pa0[1], pa1[1]);\n                      int pafacenr = v2f[parentverts];\n                      parent_faces[i] = { 19, { pafacenr, -1, -1, -1} };\n                      //cout << \"f \"<<i<<\":pf \"<< pafacenr<< \"D\" <<endl;\n                    }else{// this is an interior face FIXME \n                      parent_faces[i] = { 20, { -1, -1, -1, -1} };\n                      //cout << \"face \"<< i << \":\"<< f3 <<\" is an int face\"<< endl;\n                    }\n                  }\n                }\n              }\n          }\n      }\n    \n\n#ifdef PARALLEL\n    if (id != 0)  \n      {\n\t// if ( paralleltop.DoCoarseUpdate() )\n\t// paralleltop.UpdateCoarseGrid();\n      }\n#endif\n \n \n  \n    /* \n       for (i = 1; i <= ne; i++)\n       {\n       (*testout) << \"Element \" << i << endl;\n       (*testout) << \"PNums \" << endl; \n       for( int l=1;l<=8;l++) *testout << mesh.VolumeElement(i).PNum(l) << \"\\t\"; \n       *testout << endl; \n       (*testout) << \"edges: \" << endl;\n       for (j = 0; j < 9; j++)\n       (*testout) << edges.Elem(i)[j] << \" \";\n       (*testout) << \"faces: \" << endl;\n       for (j = 0; j < 6; j++)m\n       (*testout) << faces.Elem(i)[j] << \" \";\n       }\n\n       for (i = 1; i <= nse; i++)\n       {\n       (*testout) << \"SElement \" << i << endl;\n       (*testout) << \"PNums \" << endl; \n       for( int l=1;l<=4;l++) *testout << mesh.SurfaceElement(i).PNum(l) << \"\\t\"; \n       *testout << endl; \n       }\n    */\n    timestamp = NextTimeStamp();\n  }\n\n  \n\n\n\n  const Point3d * MeshTopology :: GetVertices (ELEMENT_TYPE et)\n  {\n    static Point3d segm_points [] = \n      { Point3d (1, 0, 0),\n\tPoint3d (0, 0, 0) };\n  \n    static Point3d trig_points [] = \n      { Point3d ( 1, 0, 0 ),\n\tPoint3d ( 0, 1, 0 ),\n\tPoint3d ( 0, 0, 0 ) };\n\n    static Point3d quad_points [] = \n      { Point3d ( 0, 0, 0 ),\n\tPoint3d ( 1, 0, 0 ),\n\tPoint3d ( 1, 1, 0 ),\n\tPoint3d ( 0, 1, 0 ) };\n\n    static Point3d tet_points [] = \n      { Point3d ( 1, 0, 0 ),\n\tPoint3d ( 0, 1, 0 ),\n\tPoint3d ( 0, 0, 1 ),\n\tPoint3d ( 0, 0, 0 ) };\n\n    static Point3d pyramid_points [] =\n      {\n\tPoint3d ( 0, 0, 0 ),\n\tPoint3d ( 1, 0, 0 ),\n\tPoint3d ( 1, 1, 0 ),\n\tPoint3d ( 0, 1, 0 ),\n\tPoint3d ( 0, 0, 1-1e-7 ),\n      };    \n  \n    static Point3d prism_points[] = \n      {\n\tPoint3d ( 1, 0, 0 ),\n\tPoint3d ( 0, 1, 0 ),\n\tPoint3d ( 0, 0, 0 ),\n\tPoint3d ( 1, 0, 1 ),\n\tPoint3d ( 0, 1, 1 ),\n\tPoint3d ( 0, 0, 1 )\n      };\n\n\n    static Point3d hex_points [] = \n      { Point3d ( 0, 0, 0 ),\n\tPoint3d ( 1, 0, 0 ),\n\tPoint3d ( 1, 1, 0 ),\n\tPoint3d ( 0, 1, 0 ),\n\tPoint3d ( 0, 0, 1 ),\n\tPoint3d ( 1, 0, 1 ),\n\tPoint3d ( 1, 1, 1 ),\n\tPoint3d ( 0, 1, 1 ) };\n\n\n    switch (et)\n      {\n      case SEGMENT:\n      case SEGMENT3:\n\treturn segm_points;\n\n      case TRIG:\n      case TRIG6:\n\treturn trig_points;\n\n      case QUAD:\n      case QUAD6:\n      case QUAD8:\n\treturn quad_points;\n\n      case TET:\n      case TET10:\n\treturn tet_points;\n\n      case PYRAMID:\n\treturn pyramid_points;\n\n      case PRISM:\n      case PRISM12:\n\treturn prism_points;\n\n      case HEX:\n\treturn hex_points;\n      default:\n\tcerr << \"Ng_ME_GetVertices, illegal element type \" << et << endl;\n      }\n    return 0;\n  }\n\n\n\n\n\n\n\n\n  void MeshTopology :: GetElementEdges (int elnr, NgArray<int> & eledges) const\n  {\n    int ned = GetNEdges (mesh->VolumeElement(elnr).GetType());\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);\n    eledges.SetSize (ned);\n    for (int i = 0; i < ned; i++)\n      // eledges[i] = edges.Get(elnr)[i]+1;\n      eledges[i] = edges[ei][i]+1;\n  }\n\n  void MeshTopology :: GetElementFaces (int elnr, NgArray<int> & elfaces) const\n  {\n    int nfa = GetNFaces (mesh->VolumeElement(elnr).GetType());\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);\n    \n    elfaces.SetSize (nfa);\n\n    for (auto i : Range(nfa))\n      // elfaces[i] = faces.Get(elnr)[i]+1;\n      elfaces[i] = faces[ei][i]+1;\n  }\n\n  \n  void MeshTopology :: GetElementFaces (int elnr, NgArray<int> & elfaces, bool withorientation) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);\n    int nfa = GetNFaces (mesh->VolumeElement(ei).GetType());\n    \n    elfaces.SetSize (nfa);\n\n    for (auto i : Range(nfa))\n      // elfaces[i] = faces.Get(elnr)[i]+1;\n      elfaces[i] = faces[ei][i]+1;\n    \n    if(withorientation)\n    {\n        for(auto & face : elfaces)\n        {\n            auto v = face2vert[face-1];\n            if(v[3].IsValid())\n                cerr << \"GetElementFaces with orientation currently not supported for quads\" << endl;\n\n            int classnr = 0;\n            if (v[0] > v[1]) { classnr++; }\n            if (v[1] > v[2]) { classnr++; }\n            if (v[2] > v[0]) { classnr++; }\n\n            if(classnr==1)\n                face = -face;\n        }\n    }\n  }\n\n  void MeshTopology :: GetElementEdgeOrientations (int elnr, NgArray<int> & eorient) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);    \n    int ned = GetNEdges (mesh->VolumeElement(ei).GetType());\n    eorient.SetSize (ned);\n    for (int i = 1; i <= ned; i++)\n      // eorient.Elem(i) = (edges.Get(elnr)[i-1] > 0) ? 1 : -1;\n      // eorient.Elem(i) = (edges.Get(elnr)[i-1].orient) ? -1 : 1;\n      eorient.Elem(i) = GetElementEdgeOrientation (elnr, i-1) ? -1 : 1;\n  }\n\n  void MeshTopology :: GetElementFaceOrientations (int elnr, NgArray<int> & forient) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);    \n    int nfa = GetNFaces (mesh->VolumeElement(ei).GetType());\n    forient.SetSize (nfa);\n    for (int i = 1; i <= nfa; i++)\n      // forient.Elem(i) = faces.Get(elnr)[i-1].forient;\n      // forient.Elem(i) = (faces.Get(elnr)[i-1]-1) % 8;\n      forient.Elem(i) = GetElementFaceOrientation(elnr, i-1);\n  }\n\n\n  \n  int MeshTopology :: GetElementEdges (int elnr, int * eledges, int * orient) const\n  {\n    //  int ned = GetNEdges (mesh.VolumeElement(elnr).GetType());\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);\n    if (mesh->GetDimension()==3 || 1)\n      {\n        if (orient)\n\t  {\n\t    for (int i = 0; i < 12; i++)\n\t      {\n                /*\n\t\tif (!edges.Get(elnr)[i]) return i;\n\t\teledges[i] = abs (edges.Get(elnr)[i]);\n\t\torient[i] = (edges.Get(elnr)[i] > 0 ) ? 1 : -1;\n                */\n                \n                // if (edges.Get(elnr)[i] == -1) return i;\n                // eledges[i] = edges[ei].Get(elnr)[i]+1;\n                if (edges[ei][i] == -1) return i;\n                eledges[i] = edges[ei][i]+1;\n                \n\t\t// orient[i] = edges.Get(elnr)[i].orient ? -1 : 1;\n                orient[i] = GetElementEdgeOrientation(elnr, i) ? -1 : 1;\n\t      }\n\t  }\n\telse\n\t  {\n\t    for (int i = 0; i < 12; i++)\n\t      {\n\t\t// if (!edges.Get(elnr)[i]) return i;\n\t\t// eledges[i] = abs (edges.Get(elnr)[i]);\n                \n                // if (edges.Get(elnr)[i] == -1) return i;\n                //eledges[i] = edges.Get(elnr)[i]+1;\n                if (edges[ei][i] == -1) return i;\n                eledges[i] = edges[ei][i]+1;\n\n\t      }\n\t  }\n\treturn 12;\n      }\n    else\n      {\n\tthrow NgException(\"rethink implementation\");\n\t/*\n\t  if (orient)\n\t  {\n\t  for (i = 0; i < 4; i++)\n\t  {\n\t  if (!surfedges.Get(elnr)[i]) return i;\n\t  eledges[i] = abs (surfedges.Get(elnr)[i]);\n\t  orient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1;\n\t  }\n\t  }\n\t  else\n\t  {\n\t  if (!surfedges.Get(elnr)[i]) return i;\n\t  for (i = 0; i < 4; i++)\n\t  eledges[i] = abs (surfedges.Get(elnr)[i]);\n\t  }\n\t*/\n\treturn 4;\n\t//      return GetSurfaceElementEdges (elnr, eledges, orient);\n      }\n  }\n\n  int MeshTopology :: GetElementFaces (int elnr, int * elfaces, int * orient) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);\n    \n    //  int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType());\n    if (orient)\n      {\n\tfor (int i = 0; i < 6; i++)\n\t  {\n            /*\n\t    if (!faces.Get(elnr)[i]) return i;\n\t    elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1;\n\t    orient[i] = (faces.Get(elnr)[i]-1) % 8;\n            */\n\t    // if (faces.Get(elnr)[i] == -1) return i;\n\t    // elfaces[i] = faces.Get(elnr)[i]+1;\n\t    if (faces[ei][i] == -1) return i;\n\t    elfaces[i] = faces[ei][i]+1;\n\t    // orient[i] = faces.Get(elnr)[i].forient;\n            orient[i] = GetElementFaceOrientation (elnr, i);\n\t  }\n      }\n    else\n      {\n\tfor (int i = 0; i < 6; i++)\n\t  {\n\t    // if (!faces.Get(elnr)[i]) return i;\n\t    // elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1;\n\n\t    // if (faces.Get(elnr)[i] == -1) return i;\n\t    // elfaces[i] = faces.Get(elnr)[i]+1;\n\t    if (faces[ei][i] == -1) return i;\n\t    elfaces[i] = faces[ei][i]+1;\n\t  }\n      }\n    return 6;\n  }\n\n  \n  void MeshTopology :: GetSurfaceElementEdges (int elnr, NgArray<int> & eledges) const\n  {\n    int ned = GetNEdges (mesh->SurfaceElement(elnr).GetType());\n    SurfaceElementIndex sei = IndexBASE<SurfaceElementIndex>() +(elnr-1);    \n    eledges.SetSize (ned);\n    for (int i = 0; i < ned; i++)\n      // eledges[i] = surfedges.Get(elnr)[i]+1;\n      eledges[i] = surfedges[sei][i]+1;\n  }\n\n  void MeshTopology :: GetEdges (SurfaceElementIndex elnr, NgArray<int> & eledges) const\n  {\n    int ned = GetNEdges ( (*mesh)[elnr].GetType());\n    eledges.SetSize (ned);\n    for (int i = 0; i < ned; i++)\n      eledges[i] = surfedges[elnr][i];\n  }\n\n  /*\n  FlatArray<T_EDGE> MeshTopology :: GetEdges (SurfaceElementIndex elnr) const\n  {\n    return FlatArray<T_EDGE>(GetNEdges ( (*mesh)[elnr].GetType()), &surfedges[elnr][0]);\n  }\n\n  FlatArray<T_EDGE> MeshTopology :: GetEdges (ElementIndex elnr) const\n  {\n    return FlatArray<T_EDGE>(GetNEdges ( (*mesh)[elnr].GetType()), &edges[elnr][0]);\n  }\n\n  FlatArray<T_FACE> MeshTopology :: GetFaces (ElementIndex elnr) const\n  {\n    return FlatArray<T_FACE>(GetNFaces ( (*mesh)[elnr].GetType()), &faces[elnr][0]);\n  }\n  */\n  \n  \n  /*\n  int MeshTopology :: GetSurfaceElementFace (int elnr) const\n  {\n    return surffaces[elnr-1]+1;\n  }\n  \n  int MeshTopology :: GetFace (SurfaceElementIndex elnr) const\n  {\n    return surffaces[elnr].fnr;\n  }\n  */\n\n\n  void MeshTopology :: \n  GetSurfaceElementEdgeOrientations (int elnr, NgArray<int> & eorient) const\n  {\n    int ned = GetNEdges (mesh->SurfaceElement(elnr).GetType());\n    eorient.SetSize (ned);\n    for (int i = 0; i < ned; i++)\n      // eorient[i] = (surfedges.Get(elnr)[i] > 0) ? 1 : -1;\n      // eorient[i] = (surfedges.Get(elnr)[i].orient) ? -1 : 1;\n      eorient[i] = GetSurfaceElementEdgeOrientation(elnr, i) ? -1 : 1;\n  }\n\n  int MeshTopology :: GetSurfaceElementFaceOrientation (int elnr) const\n  {\n    // return (surffaces.Get(elnr)-1) % 8;\n    // return surffaces.Get(elnr).forient;\n    return GetSurfaceElementFaceOrientation2(elnr);\n  }\n\n  int MeshTopology :: GetSurfaceElementEdges (int elnr, int * eledges, int * orient) const\n  {\n    SurfaceElementIndex sei = IndexBASE<SurfaceElementIndex>() +(elnr-1);        \n    int i;\n    if (mesh->GetDimension() == 3 || 1)\n      {\n\tif (orient)\n\t  {\n\t    for (i = 0; i < 4; i++)\n\t      {\n                /*\n\t\tif (!surfedges.Get(elnr)[i]) return i;\n\t\teledges[i] = abs (surfedges.Get(elnr)[i]);\n\t\torient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1;\n                */\n\t\t// if (surfedges.Get(elnr)[i] == -1) return i;\n\t\t// eledges[i] = surfedges.Get(elnr)[i]+1;\n\t\tif (surfedges[sei][i] == -1) return i;\n\t\teledges[i] = surfedges[sei][i]+1;\n\t\t// orient[i] = (surfedges.Get(elnr)[i].orient) ? -1 : 1;\n                // orient[i] = GetSurfaceElementEdgeOrientation(elnr, i) ? -1 : 1;\n                orient[i] = 1;\n\n\t      }\n\t  }\n\telse\n\t  {\n\t    for (i = 0; i < 4; i++)\n\t      {\n                /*\n\t\tif (!surfedges.Get(elnr)[i]) return i;\n\t\teledges[i] = abs (surfedges.Get(elnr)[i]);\n                */\n\t\t// if (surfedges.Get(elnr)[i] == -1) return i;\n\t\t// eledges[i] = surfedges.Get(elnr)[i]+1;\n\t\tif (surfedges[sei][i] == -1) return i;\n\t\teledges[i] = surfedges[sei][i]+1;\n\t      }\n\t  }\n\treturn 4;\n      }\n    else\n      {\n        /*\n\teledges[0] = abs (segedges.Get(elnr));\n\tif (orient)\n\t  orient[0] = segedges.Get(elnr) > 0 ? 1 : -1;\n        */\n\teledges[0] = segedges[elnr-1]+1;\n\tif (orient)\n\t  // orient[0] = segedges.Get(elnr).orient ? -1 : 1;\n          // orient[0] = GetSegmentEdgeOrientation(elnr) ? -1 : 1;\n          orient[0] = 1;\n      }\n    return 1;\n  }\n\n\n  int MeshTopology :: GetElementEdgeOrientation (int elnr, int locedgenr) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);        \n    \n    const Element & el = mesh->VolumeElement (ei);\n    const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType());    \n\n    int k = locedgenr;\n    INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]);\n    int edgedir = (edge.I1() > edge.I2());\n    return edgedir;\n  }\n\n  \n  int MeshTopology :: GetElementFaceOrientation (int elnr, int locfacenr) const\n  {\n    ElementIndex ei = IndexBASE<ElementIndex>() +(elnr-1);        \n    const Element & el = mesh->VolumeElement (ei);\n    \n    const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType());\n\n    int j = locfacenr;\n    if (elfaces[j][3] < 0)\n      { // triangle\n        INDEX_4 face(el[elfaces[j][0]], el[elfaces[j][1]], \n                     el[elfaces[j][2]], PointIndex::BASE-1 );\n        \n        int facedir = 0;\n        if (face.I1() > face.I2())\n          { swap (face.I1(), face.I2()); facedir += 1; }\n        if (face.I2() > face.I3())\n          { swap (face.I2(), face.I3()); facedir += 2; }\n        if (face.I1() > face.I2())\n          { swap (face.I1(), face.I2()); facedir += 4; }\n\n        return facedir;\n      }\n    else\n      {\n        // quad\n        // int facenum;\n        INDEX_4 face4(el[elfaces[j][0]], el[elfaces[j][1]],\n                      el[elfaces[j][2]], el[elfaces[j][3]]);\n        \n        int facedir = 0;\n        if (min2 (face4.I1(), face4.I2()) > \n            min2 (face4.I4(), face4.I3())) \n          {  // z - flip\n            facedir += 1; \n            swap (face4.I1(), face4.I4());\n            swap (face4.I2(), face4.I3());\n          }\n        if (min2 (face4.I1(), face4.I4()) >\n            min2 (face4.I2(), face4.I3())) \n          {  // x - flip\n            facedir += 2; \n            swap (face4.I1(), face4.I2());\n            swap (face4.I3(), face4.I4());\n          }\n        if (face4.I2() > face4.I4())\n          {  // diagonal flip\n            facedir += 4; \n            swap (face4.I2(), face4.I4());\n          }\n        \n        return facedir;\n      }\n  }        \n    \n\n  \n  int MeshTopology :: GetSurfaceElementEdgeOrientation (int elnr, int locedgenr) const\n  {\n    const Element2d & el = mesh->SurfaceElement (elnr);\n    const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType());    \n\n    int k = locedgenr;\n    INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]);\n    int edgedir = (edge.I1() > edge.I2());\n    return edgedir;\n  }\n  \n  int MeshTopology :: GetSurfaceElementFaceOrientation2 (int elnr) const\n  {\n    const Element2d & el = mesh->SurfaceElement (elnr);\n    \n    const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType());\n\n    int j = 0;\n    if (elfaces[j][3] < 0)\n      { // triangle\n        INDEX_4 face(el[elfaces[j][0]], el[elfaces[j][1]], \n                     el[elfaces[j][2]], PointIndex(PointIndex::INVALID));\n        \n        int facedir = 0;\n        if (face.I1() > face.I2())\n          { swap (face.I1(), face.I2()); facedir += 1; }\n        if (face.I2() > face.I3())\n          { swap (face.I2(), face.I3()); facedir += 2; }\n        if (face.I1() > face.I2())\n          { swap (face.I1(), face.I2()); facedir += 4; }\n\n        return facedir;\n      }\n    else\n      {\n        // quad\n        // int facenum;\n        INDEX_4 face4(el[elfaces[j][0]], el[elfaces[j][1]],\n                      el[elfaces[j][2]], el[elfaces[j][3]]);\n        \n        int facedir = 0;\n        if (min2 (face4.I1(), face4.I2()) > \n            min2 (face4.I4(), face4.I3())) \n          {  // z - flip\n            facedir += 1; \n            swap (face4.I1(), face4.I4());\n            swap (face4.I2(), face4.I3());\n          }\n        if (min2 (face4.I1(), face4.I4()) >\n            min2 (face4.I2(), face4.I3())) \n          {  // x - flip\n            facedir += 2; \n            swap (face4.I1(), face4.I2());\n            swap (face4.I3(), face4.I4());\n          }\n        if (face4.I2() > face4.I4())\n          {  // diagonal flip\n            facedir += 4; \n            swap (face4.I2(), face4.I4());\n          }\n        \n        return facedir;\n      }\n  }\n\n  void MeshTopology :: GetSegmentEdge (int segnr, int & enr, int & orient) const\n  {\n    enr = segedges[segnr-1]+1;\n    orient = GetSegmentEdgeOrientation(segnr);\n  }\n\n  \n  int MeshTopology :: GetSegmentEdgeOrientation (int elnr) const\n  {\n    const Segment & el = mesh->LineSegment (elnr);\n    const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType());    \n\n    int k = 0;\n    INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]);\n    int edgedir = (edge.I1() > edge.I2());\n    return edgedir;\n  }\n\n\n  \n  void MeshTopology :: GetFaceVertices (int fnr, NgArray<int> & vertices) const\n  {\n    vertices.SetSize(4);\n    for (int i = 0; i < 4; i++)\n      vertices[i] = face2vert[fnr-1][i];\n    if (vertices[3]+1==PointIndex::BASE)\n      vertices.SetSize(3);\n  }\n\n  void MeshTopology :: GetFaceVertices (int fnr, int * vertices) const\n  {\n    for (int i = 0; i <= 3; i++)\n      vertices[i] = face2vert[fnr-1][i];\n  }\n\n\n  void MeshTopology :: GetEdgeVertices (int ednr, int & v1, int & v2) const\n  {\n    // cout << \"id = \" << id << \"getedgevertices, ednr = \" << ednr << \", ned = \" << edge2vert.Size() << \"&v1 = \" << &v1 << endl;\n    if (ednr < 1 || ednr > edge2vert.Size())\n      cerr << \"illegal edge nr: \" << ednr << \", numedges = \" << edge2vert.Size() \n\t   << \" id = \" << id \n\t   << endl;\n    v1 = edge2vert[ednr-1][0];\n    v2 = edge2vert[ednr-1][1];\n  }\n\n  void MeshTopology :: GetEdgeVertices (int ednr, PointIndex & v1, PointIndex & v2) const\n  {\n    v1 = edge2vert[ednr-1][0];\n    v2 = edge2vert[ednr-1][1];\n  }\n\n\n  void MeshTopology :: GetFaceEdges (int fnr, NgArray<int> & fedges, bool withorientation) const\n  {\n    // NgArrayMem<int,4> pi(4);\n    // NgArrayMem<int,12> eledges;\n  \n    fedges.SetSize (0);\n    // GetFaceVertices(fnr, pi);\n    auto pi = GetFaceVertices(fnr-1);\n    \n    // Sort Edges according to global vertex numbers \n    // e1 = fmax, f2 \n    // e2 = fmax, f1 \n    // e3 = op e1(f2,f3) \n    // e4 = op e2(f1,f3) \n\n    /*  NgArrayMem<int,4> fp; \n\tfp[0] = pi[0]; \n\tfor(int k=1;k<pi.Size();k++) \n\tif(fp[k]>fp[0]) swap(fp[k],fp[0]); \n  \n\tfp[1] = fp[0]+ */ \n  \n\n    //  GetVertexElements (pi[0], els);\n    FlatArray<ElementIndex> els = GetVertexElements (pi[0]);\n\n    // find one element having all vertices of the face\n    for (int i = 0; i < els.Size(); i++)\n      {\n\tconst Element & el = (*mesh)[els[i]];\n\tint nref_faces = GetNFaces (el.GetType());\n\tconst ELEMENT_FACE * ref_faces = GetFaces1 (el.GetType());\n\tint nfa_ref_edges = GetNEdges (GetFaceType0(fnr-1));\n      \n\tint cntv = 0,fa=-1; \n\tfor(int m=0;m<nref_faces;m++)\n\t  { \n\t    cntv=0;\n\t    for(int j=0;j<nfa_ref_edges && ref_faces[m][j]>0;j++)\n\t      for(int k=0;k<pi.Size();k++)\n\t\t{\n\t\t  if(el[ref_faces[m][j]-1] == pi[k])\n\t\t    cntv++;\n\t\t}\n\t    if (cntv == pi.Size())\n\t      {\n\t\tfa=m;\n\t\tbreak;\n\t      }\n\t  }\n     \n\tif(fa>=0)\n\t  {\n\t    const ELEMENT_EDGE * fa_ref_edges = GetEdges1 (GetFaceType0(fnr-1)); \n\t    fedges.SetSize(nfa_ref_edges);\n\t    // GetElementEdges (els[i]+1, eledges);\n            auto eledges = GetEdges (els[i]);\n\t  \n\t    for (int j = 0; j < eledges.Size(); j++)\n\t      {\n\t\t// int vi1, vi2;\n\t\t// GetEdgeVertices (eledges[j]+1, vi1, vi2);\n                auto [vi1, vi2] = GetEdgeVertices(eledges[j]);\n\t    \n\t\tbool has1 = 0;\n\t\tbool has2 = 0;\n\t\tfor (int k = 0; k < pi.Size(); k++)\n\t\t  {\n\t\t    if (vi1 == pi[k]) has1 = 1;\n\t\t    if (vi2 == pi[k]) has2 = 1;\n\t\t  \n\t\t  }\n\t      \n\t\tif (has1 && has2) // eledges[j] is on face \n\t\t  {\n\t\t    // fedges.Append (eledges[j]);\n\t\t    for(int k=0;k<nfa_ref_edges;k++)\n\t\t      {\n\t\t\tPointIndex w1 = el[ref_faces[fa][fa_ref_edges[k][0]-1]-1]; \n\t\t\tPointIndex w2 = el[ref_faces[fa][fa_ref_edges[k][1]-1]-1]; \n\n\t\t\tif(withorientation)\n\t\t\t  {\n\t\t\t    if(w1==vi1 && w2==vi2)\n\t\t\t      fedges[k] = eledges[j]+1;\n\t\t\t    if(w1==vi2 && w2==vi1)\n\t\t\t      fedges[k] = -eledges[j]+1;\n\t\t\t  }\n\t\t\telse\n\t\t\t  if((w1==vi1 && w2==vi2) || (w1==vi2 && w2==vi1))\n\t\t\t    fedges[k] = eledges[j]+1;\n\t\t      }\n\t\t  }\n\t      }\n\t  \n\t    // *testout << \" Face \" << fnr << endl; \n\t    // *testout << \" GetFaceEdges \" << fedges << endl;\n\t  \n\t    return;\n\t  }\n      }   \n    SurfaceElementIndex surfel = GetFace2SurfaceElement(fnr-1);\n    \n    if (surfel.IsValid())\n      {\n\t// GetSurfaceElementEdges (surfel, fedges);\n        auto hedges = GetEdges (surfel);\n        fedges.SetSize(hedges.Size());\n        for (int i : Range(hedges))\n          fedges[i]=hedges[i]+1;\n\treturn;\n      }\n  }\n\n\n  void MeshTopology :: GetVertexElements (int vnr, Array<ElementIndex> & elements) const\n  {\n    if (vert2element.Size())\n      elements = vert2element[vnr];\n  }\n\n  void MeshTopology :: GetVertexSurfaceElements( int vnr, \n\t\t\t\t\t\t Array<SurfaceElementIndex> & elements ) const\n  {\n    if (vert2surfelement.Size())\n      elements = vert2surfelement[vnr];\n  }\n\n\n  int MeshTopology :: GetVerticesEdge ( PointIndex v1, PointIndex v2 ) const\n  {\n    /*\n    if (vert2element.Size() > 0)\n      {      \n        auto elements_v1 = GetVertexElements ( v1 );\n        // int edv1, edv2;\n        \n        for ( int i = 0; i < elements_v1.Size(); i++ )\n          {\n            // GetElementEdges( elements_v1[i]+1, elementedges );\n            auto elementedges = GetEdges(ElementIndex(elements_v1[i]));\n            for ( int ed = 0; ed < elementedges.Size(); ed ++)\n              {\n                // GetEdgeVertices( elementedges[ed]+1, edv1, edv2 );\n                auto [edv1,edv2] = GetEdgeVertices (elementedges[ed]);\n                if ( ( edv1 == v1 && edv2 == v2 ) || ( edv1 == v2 && edv2 == v1 ) )\n                  return elementedges[ed];\n              }\n          }\n      }\n    */\n    \n    if (vert2element.Size() > 0)\n      for (auto ei : GetVertexElements ( v1 ))\n        for (auto ed : GetEdges(ei))\n          {\n            auto [edv1,edv2] = GetEdgeVertices (ed);\n            if ( ( edv1 == v1 && edv2 == v2 ) || ( edv1 == v2 && edv2 == v1 ) )\n              return ed;\n          }\n\n \n    if (vert2surfelement.Size() > 0)\n      for (auto sei : GetVertexSurfaceElements ( v1 ))\n        for (auto ed : GetEdges(sei))\n          {\n            auto [edv1,edv2] = GetEdgeVertices (ed);\n            if ( ( edv1 == v1 && edv2 == v2 ) || ( edv1 == v2 && edv2 == v1 ) )\n              return ed;\n          }\n\n    return -1;\n  }\n\n\n\n  void MeshTopology :: \n  GetSegmentVolumeElements ( int segnr, NgArray<ElementIndex> & volels ) const\n  {\n    /*\n    int v1, v2;\n    // GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 );\n    GetEdgeVertices ( GetEdge (segnr-1)+1, v1, v2 );\n    */\n    auto [v1,v2] = GetEdgeVertices ( GetEdge (segnr-1) );\n    auto volels1 = GetVertexElements ( v1 );\n    auto volels2 = GetVertexElements ( v2 );\n    volels.SetSize(0);\n\n    for ( auto volel1 : volels1 )\n      if ( volels2.Contains( volel1 ) )\n\tvolels.Append ( volel1 );\n  }\n\n  void MeshTopology :: \n  GetSegmentSurfaceElements (int segnr, NgArray<SurfaceElementIndex> & els) const\n  {\n    // int v1, v2;\n    // GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 );\n    // GetEdgeVertices ( GetEdge (segnr-1)+1, v1, v2 );\n    auto [v1,v2] = GetEdgeVertices ( GetEdge (segnr-1) );\n    auto els1 = GetVertexSurfaceElements ( v1 );\n    auto els2 = GetVertexSurfaceElements ( v2 );\n    els.SetSize(0);\n\n    for ( auto el1 : els1 )\n      if ( els2.Contains( el1 ) )\n\tels.Append ( el1 );\n  }\n\n\n\n\n}\n"
  },
  {
    "path": "libsrc/meshing/topology.hpp",
    "content": "#ifndef TOPOLOGY\n#define TOPOLOGY\n\n/**************************************************************************/\n/* File:   topology.hh                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   27. Apr. 01                                                    */\n/**************************************************************************/\n\n/*\n    Mesh topology\n    (Elements, Faces, Edges, Vertices\n*/\n\n#include \"meshtype.hpp\"\n\nnamespace netgen\n{\n  // typedef int T_EDGE;\n  // typedef int T_FACE;\n\n  class EdgeIndex : public Index<int,EdgeIndex,0>\n  {\n  public:\n    using Index::Index;\n  };\n\n  class FaceIndex : public Index<int,FaceIndex,0>\n  {\n  public:\n    using Index::Index;\n  };\n\n  typedef EdgeIndex T_EDGE;  \n  typedef FaceIndex T_FACE;  \n  \nclass MeshTopology\n{\n  const Mesh * mesh;\n  bool buildvertex2element;\n  bool buildedges;\n  bool buildfaces;\n  bool build_parent_edges = false; // may be changed to default = false\n  bool build_parent_faces = false; // may be changed to default = false\n  static bool static_buildedges, static_buildfaces, static_buildvertex2element;\n\n  Array<std::array<PointIndex,2>> edge2vert;\n  Array<std::array<PointIndex,4>> face2vert;\n\n  Array<std::array<EdgeIndex,12>, ElementIndex> edges;\n  Array<std::array<FaceIndex,6>, ElementIndex> faces;\n  Array<std::array<EdgeIndex,4>, SurfaceElementIndex> surfedges;\n  \n  Array<EdgeIndex,SegmentIndex> segedges;\n  Array<FaceIndex,SurfaceElementIndex> surffaces;\n  // Array<INDEX_2, SurfaceElementIndex> surf2volelement;\n  Array<std::array<ElementIndex,2>, SurfaceElementIndex> surf2volelement;\n  Array<SurfaceElementIndex> face2surfel;\n  \n  Array<SegmentIndex> edge2segment;\n  Table<ElementIndex, PointIndex> vert2element;\n  Table<SurfaceElementIndex, PointIndex> vert2surfelement;\n  Table<SegmentIndex,PointIndex> vert2segment;\n  Table<int,PointIndex> vert2pointelement;\n  int timestamp;\npublic:\n  MeshTopology () = default;\n  MeshTopology (MeshTopology && top) = default;\n  DLL_HEADER MeshTopology (const Mesh & amesh);\n  DLL_HEADER ~MeshTopology ();\n  MeshTopology & operator= (MeshTopology && top) = default;\n\n  void SetBuildVertex2Element (bool bv2e) { buildvertex2element = bv2e; }  \n  void SetBuildEdges (bool be) { buildedges = be; }\n  void SetBuildFaces (bool bf) { buildfaces = bf; }\n  void SetBuildParentEdges (bool bh) { build_parent_edges = bh; }\n  void SetBuildParentFaces (bool bh) { build_parent_faces = bh; }\n\n  DLL_HEADER void EnableTable (string name, bool set);\n  static void EnableTableStatic (string name, bool set);\n\n  bool HasEdges () const  { return buildedges; }\n  bool HasFaces () const  { return buildfaces; }\n  bool HasParentEdges () const { return build_parent_edges; }\n  bool HasParentFaces () const { return build_parent_faces; }\n\n  void Update(NgTaskManager tm = &DummyTaskManager, NgTracer tracer = &DummyTracer);\n  bool NeedsUpdate() const;\n\n\n  size_t GetNEdges () const { return edge2vert.Size(); }\n  size_t GetNFaces () const { return face2vert.Size(); }\n\n  static inline short int GetNVertices (ELEMENT_TYPE et);\n  static inline short int GetNPoints (ELEMENT_TYPE et);\n  static inline short int GetNEdges (ELEMENT_TYPE et);\n  static inline short int GetNFaces (ELEMENT_TYPE et);\n\n  DLL_HEADER static const Point3d * GetVertices (ELEMENT_TYPE et);\n  inline static const ELEMENT_EDGE * GetEdges1 (ELEMENT_TYPE et);\n  inline static const ELEMENT_EDGE * GetEdges0 (ELEMENT_TYPE et);\n  inline static FlatArray<ELEMENT_EDGE> GetEdges (ELEMENT_TYPE et);\n  inline static const ELEMENT_FACE * GetFaces1 (ELEMENT_TYPE et);\n  inline static const ELEMENT_FACE * GetFaces0 (ELEMENT_TYPE et);\n\n  [[deprecated(\"use GetEdge(SegmentIndex) instead\")]]                    \n  EdgeIndex GetSegmentEdge (int segnr) const { return segedges[segnr-1]+1; }\n  \n  EdgeIndex GetEdge (SegmentIndex segnr) const { return segedges[segnr]; }\n\n  [[deprecated(\"use GetEdge(SegmentIndex) instead\")]]                      \n  void GetSegmentEdge (int segnr, int & enr, int & orient) const;\n\n  [[deprecated(\"use GetEdges (ElementIndex) -> FlatArray\")]]                          \n  void GetElementEdges (int elnr, NgArray<int> & edges) const;\n  [[deprecated(\"use GetFaces (ElementIndex) -> FlatArray\")]]                            \n  void GetElementFaces (int elnr, NgArray<int> & faces) const;\n  void GetElementFaces (int elnr, NgArray<int> & faces, bool withorientation) const;  \n\n  // definition in meshclass.hpp \n  inline FlatArray<EdgeIndex> GetEdges (ElementIndex elnr) const;\n  inline FlatArray<FaceIndex> GetFaces (ElementIndex elnr) const;    \n\n  \n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  void GetElementEdgeOrientations (int elnr, NgArray<int> & eorient) const;\n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  void GetElementFaceOrientations (int elnr, NgArray<int> & forient) const;\n\n  [[deprecated(\"use GetEdges (ElementIndex) -> FlatArray\")]]                            \n  int GetElementEdges (int elnr, int * edges, int * orient) const;\n\n  // [[deprecated(\"use GetFaces (ElementIndex) -> FlatArray\")]]                              \n  int GetElementFaces (int elnr, int * faces, int * orient) const;\n\n  // [[deprecated(\"use GetElementEdge instead\")]]                      \n  int GetElementEdgeOrientation (int elnr, int locedgenr) const; // old style\n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  int GetElementFaceOrientation (int elnr, int locfacenr) const; // old style\n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  int GetSurfaceElementEdgeOrientation (int elnr, int locedgenr) const; // old style\n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  int GetSurfaceElementFaceOrientation2 (int elnr) const; // old style\n  // [[deprecated(\"use GetElementEdge instead\")]]                        \n  int GetSegmentEdgeOrientation (int elnr) const; // old style\n  \n  DLL_HEADER void GetFaceVertices (int fnr, NgArray<int> & vertices) const;\n  DLL_HEADER void GetFaceVertices (int fnr, int * vertices) const;\n  auto GetFaceVertices (int fnr) const\n  { return FlatArray (face2vert[fnr][3].IsValid() ? 4 : 3, &face2vert[fnr][0]); }\n  [[deprecated(\"use GetEdgeVertices -> tupe(v0,v1) instead\")]]                            \n  DLL_HEADER void GetEdgeVertices (int enr, int & v1, int & v2) const;\n  [[deprecated(\"use GetEdgeVertices -> tupe(v0,v1) instead\")]]\n  DLL_HEADER void GetEdgeVertices (int enr, PointIndex & v1, PointIndex & v2) const;\n  auto GetEdgeVertices (int enr) const { return std::array{edge2vert[enr][0], edge2vert[enr][1]}; }\n  auto GetEdgeVerticesPtr (int enr) const { return &edge2vert[enr][0]; }\n  auto GetFaceVerticesPtr (int fnr) const { return &face2vert[fnr][0]; }\n  DLL_HEADER void GetFaceEdges (int fnr, NgArray<int> & edges, bool withorientation = false) const;\n\n  // ELEMENT_TYPE GetFaceType (int fnr) const\n  // { return (!face2vert[fnr-1][3].IsValid()) ? TRIG : QUAD; }    \n  ELEMENT_TYPE GetFaceType0 (SurfaceElementIndex fnr) const\n  { return (!face2vert[fnr][3].IsValid()) ? TRIG : QUAD; }    \n\n  [[deprecated(\"use GetEdges (SurfaceElementIndex) -> FlatArray\")]]  \n  void GetSurfaceElementEdges (int elnr, NgArray<int> & edges) const;\n  [[deprecated(\"use GetFace(SurfaceElementIndex\")]]                            \n  int GetSurfaceElementFace1 (int elnr) const { return surffaces[elnr-1]+1; }    \n  [[deprecated(\"orientation is outdated\")]]                          \n  void GetSurfaceElementEdgeOrientations (int elnr, NgArray<int> & eorient) const;\n  // [[deprecated(\"orientation is outdated\")]]                            \n  int GetSurfaceElementFaceOrientation (int elnr) const;\n\n  [[deprecated(\"use GetEdge -> FlatArray instead\")]]                        \n  void GetEdges (SurfaceElementIndex elnr, NgArray<int> & edges) const;\n\n  inline FlatArray<EdgeIndex> GetEdges (SurfaceElementIndex elnr) const;\n  // { return FlatArray<EdgeIndex>(GetNEdges ( (*mesh)[elnr].GetType()), &surfedges[elnr][0]); }\n  \n  int GetFace (SurfaceElementIndex elnr) const\n  { return surffaces[elnr]; }\n\n  int GetSurfaceElementEdges (int elnr, int * edges, int * orient) const;\n\n  int GetNSurfedges() const {return surfedges.Size();}\n  [[deprecated(\"use GetEdges(ElementIndex) instead\")]]\n  const EdgeIndex * GetElementEdgesPtr (int elnr) const { return &edges[IndexBASE<ElementIndex>()+elnr][0]; }\n  const EdgeIndex * GetSurfaceElementEdgesPtr (int selnr) const { return &surfedges[selnr][0]; }\n  const EdgeIndex * GetSegmentElementEdgesPtr (int selnr) const { return &segedges[selnr]; }\n\n  const FaceIndex * GetElementFacesPtr (int elnr) const { return &faces[IndexBASE<ElementIndex>()+elnr][0]; }\n  const FaceIndex * GetSurfaceElementFacesPtr (int selnr) const { return &surffaces[selnr]; }\n\n\n  void GetSurface2VolumeElement (int selnr, int & elnr1, int & elnr2) const\n  { \n    elnr1 = surf2volelement[SurfaceElementIndex::Base() + selnr-1][0]+1  - ElementIndex::Base(); \n    elnr2 = surf2volelement[SurfaceElementIndex::Base() + selnr-1][1]+1  - ElementIndex::Base();\n  }\n\n  std::array<ElementIndex,2> GetSurface2VolumeElement (SurfaceElementIndex sei) \n  {\n    return surf2volelement[sei];\n  }\n\n  [[deprecated(\"use GetSurfaceEleement -> SurfaceElementIndex\")]]\n  int GetFace2SurfaceElement1 (int fnr) const { return face2surfel[fnr-1]+1 - SurfaceElementIndex::Base(); }\n  SurfaceElementIndex GetFace2SurfaceElement (int fnr) const { return face2surfel[fnr]; }\n\n  SegmentIndex GetSegmentOfEdge(int edgenr) const { return edge2segment[edgenr-1]; }\n\n  [[deprecated(\"use GetVertexElements -> FlatArray instead\")]]                  \n  void GetVertexElements (int vnr, Array<ElementIndex> & elements) const;\n  \n  FlatArray<ElementIndex> GetVertexElements (PointIndex vnr) const\n  { return vert2element[vnr]; }\n\n  [[deprecated(\"use GetVertexSurfaceElements -> FlatArray instead\")]]                    \n  void GetVertexSurfaceElements( int vnr, Array<SurfaceElementIndex>& elements ) const;\n  const auto & GetVertexSurfaceElements( ) const { return vert2surfelement; }\n  \n  FlatArray<SurfaceElementIndex> GetVertexSurfaceElements(PointIndex vnr) const\n  { return vert2surfelement[vnr]; }\n\n  FlatArray<SegmentIndex> GetVertexSegments (PointIndex vnr) const\n  { return vert2segment[vnr]; }\n\n  FlatArray<int> GetVertexPointElements (PointIndex vnr) const\n  { return vert2pointelement[vnr]; }\n  \n  DLL_HEADER int GetVerticesEdge ( PointIndex v1, PointIndex v2) const;\n  void GetSegmentVolumeElements ( int segnr, NgArray<ElementIndex> & els ) const;\n  void GetSegmentSurfaceElements ( int segnr, NgArray<SurfaceElementIndex> & els ) const;\n\n  // Call this before Update() to discard old edges\n  void ClearEdges() { edge2vert.SetSize0(); }\n\nprivate:\n  Array<std::tuple<int, std::array<int,3>>> parent_edges;\n  void BuildParentEdges ();\n\n  Array<std::tuple<int, std::array<int,4>>> parent_faces;\n  void BuildParentFaces ();\npublic:\n  auto GetParentEdges (int enr) const { return parent_edges[enr]; }\n  auto GetParentFaces (int fnr) const { return parent_faces[fnr]; }\n};\n\n\n\n\n\n\n\n\n\n\ninline short int MeshTopology :: GetNVertices (ELEMENT_TYPE et)\n{\n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return 2;\n\n    case TRIG:\n    case TRIG6:\n      return 3;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return 4;\n\n    case TET:\n    case TET10:\n      return 4;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return 5;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return 6;\n\n    case HEX7:\n      return 7;\n      \n    case HEX:\n    case HEX20:\n      return 8;\n\n      // default:\n      // cerr << \"Ng_ME_GetNVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\ninline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et)\n{\n  switch (et)\n    {\n    case SEGMENT:\n      return 2;\n    case SEGMENT3:\n      return 3;\n\n    case TRIG:\n      return 3;\n    case TRIG6:\n      return 6;\n\n    case QUAD:\n    case QUAD6:\n      return 4;\n\n    case QUAD8:\n      return 8;\n\n    case TET:\n      return 4;\n    case TET10:\n      return 10;\n\n    case PYRAMID:\n      return 5;\n    case PYRAMID13:\n      return 13;\n\n    case PRISM:\n      return 6;\n    case PRISM12:\n      return 12;\n    case PRISM15:\n      return 15;\n\n    case HEX7:\n      return 7;\n\n    case HEX:\n      return 8;\n\n    case HEX20:\n      return 20;\n      // default:\n      // cerr << \"Ng_ME_GetNVertices, illegal element type \" << et << endl;\n    }\n  return -99;\n}\n\n\n\ninline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et)\n{\n  // __assume(et >= SEGMENT && et <= PYRAMID13);\n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return 1;\n\n    case TRIG:\n    case TRIG6:\n      return 3;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return 4;\n\n    case TET:\n    case TET10:\n      return 6;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return 8;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return 9;\n\n    case HEX7:\n      return 11;\n      \n    case HEX:\n    case HEX20:\n      return 12;\n      // default:\n      // cerr << \"Ng_ME_GetNEdges, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\ninline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et)\n{\n  // __assume(et >= SEGMENT && et <= PYRAMID13);\n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return 0;\n\n    case TRIG:\n    case TRIG6:\n      return 1;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return 1;\n\n    case TET:\n    case TET10:\n      return 4;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return 5;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return 5;\n\n    case HEX:\n    case HEX20:\n    case HEX7:      \n      return 6;\n\n    default:\n      return 0;\n      // default:\n      // cerr << \"Ng_ME_GetNVertices, illegal element type \" << et << endl;\n    }\n}\n\n\n\n\n\n\nconst ELEMENT_EDGE * MeshTopology :: GetEdges1 (ELEMENT_TYPE et)\n{\n  static ELEMENT_EDGE segm_edges[1] =\n    { { 1, 2 }};\n\n  static ELEMENT_EDGE trig_edges[3] =\n    { { 3, 1 },\n      { 2, 3 },        \n      { 1, 2 }};\n\n  static ELEMENT_EDGE quad_edges[4] =\n    { { 1, 2 },\n      { 3, 4 },\n      { 4, 1 },\n      { 2, 3 }};\n\n\n  static ELEMENT_EDGE tet_edges[6] =\n    { { 4, 1 },\n      { 4, 2 },\n      { 4, 3 }, \n      { 1, 2 },\n      { 1, 3 },\n      { 2, 3 }};\n\n  static ELEMENT_EDGE prism_edges[9] =\n    { { 3, 1 },\n      { 1, 2 },\n      { 3, 2 },\n      { 6, 4 },\n      { 4, 5 },\n      { 6, 5 },\n      { 3, 6 },\n      { 1, 4 },\n      { 2, 5 }};\n\n  static ELEMENT_EDGE pyramid_edges[8] =\n    { { 1, 2 },\n      { 2, 3 },\n      { 1, 4 },\n      { 4, 3 },\n      { 1, 5 },\n      { 2, 5 },\n      { 3, 5 },\n      { 4, 5 }};\n\n  static ELEMENT_EDGE hex7_edges[11] =\n    {\n      { 1, 2 },\n      { 3, 4 },\n      { 4, 1 },\n      { 2, 3 },\n      { 5, 6 },\n      { 7, 5 },\n      { 6, 7 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 7 },\n      { 4, 7 },\n    };\n\n  static ELEMENT_EDGE hex_edges[12] =\n    {\n      { 1, 2 },\n      { 3, 4 },\n      { 4, 1 },\n      { 2, 3 },\n      { 5, 6 },\n      { 7, 8 },\n      { 8, 5 },\n      { 6, 7 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 7 },\n      { 4, 8 },\n    };\n\n  \n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return segm_edges;\n\n    case TRIG:\n    case TRIG6:\n      return trig_edges;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return quad_edges;\n\n    case TET:\n    case TET10:\n      return tet_edges;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return pyramid_edges;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return prism_edges;\n\n    case HEX7:\n      return hex7_edges;\n      \n    case HEX:\n    case HEX20:\n      return hex_edges;\n      // default:\n      // cerr << \"Ng_ME_GetEdges, illegal element type \" << et << endl;\n    }\n   return 0;  \n}\n\n\n\nconst ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et)\n{\n  static ELEMENT_EDGE segm_edges[1] =\n    { { 0, 1 }};\n\n  static ELEMENT_EDGE trig_edges[3] =\n    { { 2, 0 },\n      { 1, 2 },        \n      { 0, 1 }};\n\n  static ELEMENT_EDGE quad_edges[4] =\n    { { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 }};\n\n\n  static ELEMENT_EDGE tet_edges[6] =\n    { { 3, 0 },\n      { 3, 1 },\n      { 3, 2 }, \n      { 0, 1 },\n      { 0, 2 },\n      { 1, 2 }};\n\n  static ELEMENT_EDGE prism_edges[9] =\n    { { 2, 0 },\n      { 0, 1 },\n      { 2, 1 },\n      { 5, 3 },\n      { 3, 4 },\n      { 5, 4 },\n      { 2, 5 },\n      { 0, 3 },\n      { 1, 4 }};\n\n  static ELEMENT_EDGE pyramid_edges[8] =\n    { { 0, 1 },\n      { 1, 2 },\n      { 0, 3 },\n      { 3, 2 },\n      { 0, 4 },\n      { 1, 4 },\n      { 2, 4 },\n      { 3, 4 }};\n\n  static ELEMENT_EDGE hex7_edges[11] =\n    {\n      { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 },\n      { 4, 5 },\n      { 6, 4 },\n      { 5, 6 },\n      { 0, 4 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 6 },\n    };\n\n  static ELEMENT_EDGE hex_edges[12] =\n    {\n      { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 },\n      { 4, 5 },\n      { 6, 7 },\n      { 7, 4 },\n      { 5, 6 },\n      { 0, 4 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 7 },\n    };\n\n  \n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return segm_edges;\n\n    case TRIG:\n    case TRIG6:\n      return trig_edges;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return quad_edges;\n\n    case TET:\n    case TET10:\n      return tet_edges;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return pyramid_edges;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return prism_edges;\n\n    case HEX7:\n      return hex7_edges;\n      \n    case HEX:\n    case HEX20:\n      return hex_edges;\n      // default:\n      // cerr << \"Ng_ME_GetEdges, illegal element type \" << et << endl;\n    }\n   return 0;  \n}\n\n\nFlatArray<ELEMENT_EDGE> MeshTopology :: GetEdges (ELEMENT_TYPE et)\n{\n  static ELEMENT_EDGE segm_edges[1] =\n    { { 0, 1 }};\n\n  static ELEMENT_EDGE trig_edges[3] =\n    { { 2, 0 },\n      { 1, 2 },        \n      { 0, 1 }};\n\n  static ELEMENT_EDGE quad_edges[4] =\n    { { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 }};\n\n\n  static ELEMENT_EDGE tet_edges[6] =\n    { { 3, 0 },\n      { 3, 1 },\n      { 3, 2 }, \n      { 0, 1 },\n      { 0, 2 },\n      { 1, 2 }};\n\n  static ELEMENT_EDGE prism_edges[9] =\n    { { 2, 0 },\n      { 0, 1 },\n      { 2, 1 },\n      { 5, 3 },\n      { 3, 4 },\n      { 5, 4 },\n      { 2, 5 },\n      { 0, 3 },\n      { 1, 4 }};\n\n  static ELEMENT_EDGE pyramid_edges[8] =\n    { { 0, 1 },\n      { 1, 2 },\n      { 0, 3 },\n      { 3, 2 },\n      { 0, 4 },\n      { 1, 4 },\n      { 2, 4 },\n      { 3, 4 }};\n\n  static ELEMENT_EDGE hex7_edges[11] =\n    {\n      { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 },\n      { 4, 5 },\n      { 6, 4 },\n      { 5, 6 },\n      { 0, 4 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 6 },\n    };\n\n  static ELEMENT_EDGE hex_edges[12] =\n    {\n      { 0, 1 },\n      { 2, 3 },\n      { 3, 0 },\n      { 1, 2 },\n      { 4, 5 },\n      { 6, 7 },\n      { 7, 4 },\n      { 5, 6 },\n      { 0, 4 },\n      { 1, 5 },\n      { 2, 6 },\n      { 3, 7 },\n    };\n  \n  switch (et)\n    {\n    case SEGMENT:\n    case SEGMENT3:\n      return { 1, segm_edges };\n\n    case TRIG:\n    case TRIG6:\n      return { 3, trig_edges };\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return { 4, quad_edges };\n\n    case TET:\n    case TET10:\n      return { 6, tet_edges };\n\n    case PYRAMID:\n    case PYRAMID13:\n      return { 8, pyramid_edges };\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return { 9, prism_edges };\n\n    case HEX7:\n      return { 11, hex7_edges };\n\n    case HEX:\n    case HEX20:\n      return { 12, hex_edges };\n      // default:\n      // cerr << \"Ng_ME_GetEdges, illegal element type \" << et << endl;\n    }\n  return { 0, nullptr };  \n}\n\n\n\n\n\n\n\n\ninline const ELEMENT_FACE * MeshTopology :: GetFaces1 (ELEMENT_TYPE et)\n{\n  static const ELEMENT_FACE trig_faces[1] = \n    { { 1, 2, 3, 0 } };\n  static const ELEMENT_FACE quad_faces[1] = \n    { { 1, 2, 3, 4 } };\n\n  static const ELEMENT_FACE tet_faces[4] =\n    { { 4, 2, 3, 0 },\n      { 4, 3, 1, 0 },\n      { 4, 1, 2, 0 },\n      { 1, 3, 2, 0 } };\n  \n  static const ELEMENT_FACE prism_faces[5] =\n    {\n      { 1, 3, 2, 0 },\n      { 4, 5, 6, 0 },\n      { 3, 1, 4, 6 },\n      { 1, 2, 5, 4 },\n      { 2, 3, 6, 5 } \n    };\n\n  static const ELEMENT_FACE pyramid_faces[5] =\n    {\n      { 1, 2, 5, 0 },\n      { 2, 3, 5, 0 },\n      { 3, 4, 5, 0 },\n      { 4, 1, 5, 0 },\n      { 1, 4, 3, 2 } \n    };\n\n  static const ELEMENT_FACE hex7_faces[6] =\n    {\n      { 1, 4, 3, 2 },\n      { 5, 6, 7, 0  },\n      { 1, 2, 6, 5 },\n      { 2, 3, 7, 6 },\n      { 3, 4, 7, 0 },\n      { 4, 1, 5, 7 }\n    };\n\n  \n  static const ELEMENT_FACE hex_faces[6] =\n    {\n      { 1, 4, 3, 2 },\n      { 5, 6, 7, 8 },\n      { 1, 2, 6, 5 },\n      { 2, 3, 7, 6 },\n      { 3, 4, 8, 7 },\n      { 4, 1, 5, 8 }\n    };\n\n\n  \n  switch (et)\n    {\n    case TRIG:\n    case TRIG6:\n      return trig_faces;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return quad_faces;\n\n\n    case TET:\n    case TET10:\n      return tet_faces;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return prism_faces;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return pyramid_faces;\n\n    case SEGMENT:\n    case SEGMENT3:\n\n    case HEX7:\n      return hex7_faces;\n    \n    case HEX:\n    case HEX20:\n      return hex_faces;\n\n      // default:\n      // cerr << \"Ng_ME_GetVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n\n\n\n\ninline const ELEMENT_FACE * MeshTopology :: GetFaces0 (ELEMENT_TYPE et)\n{\n  static const ELEMENT_FACE trig_faces[1] = \n    { { 0, 1, 2, -1 } };\n  static const ELEMENT_FACE quad_faces[1] = \n    { { 0, 1, 2, 3 } };\n\n  static const ELEMENT_FACE tet_faces[4] =\n    { { 3, 1, 2, -1 },\n      { 3, 2, 0, -1 },\n      { 3, 0, 1, -1 },\n      { 0, 2, 1, -1 } };\n  \n  static const ELEMENT_FACE prism_faces[5] =\n    {\n      { 0, 2, 1, -1 },\n      { 3, 4, 5, -1 },\n      { 2, 0, 3, 5 },\n      { 0, 1, 4, 3 },\n      { 1, 2, 5, 4 } \n    };\n\n  static const ELEMENT_FACE pyramid_faces[5] =\n    {\n      { 0, 1, 4, -1 },\n      { 1, 2, 4, -1 },\n      { 2, 3, 4, -1 },\n      { 3, 0, 4, -1 },\n      { 0, 3, 2, 1 } \n    };\n\n  static const ELEMENT_FACE hex7_faces[6] =\n    {\n      { 0, 3, 2, 1 },\n      { 4, 5, 6, -1},\n      { 0, 1, 5, 4 },\n      { 1, 2, 6, 5 },\n      { 2, 3, 6, -1},\n      { 3, 0, 4, 6 }\n    };\n\n  static const ELEMENT_FACE hex_faces[6] =\n    {\n      { 0, 3, 2, 1 },\n      { 4, 5, 6, 7 },\n      { 0, 1, 5, 4 },\n      { 1, 2, 6, 5 },\n      { 2, 3, 7, 6 },\n      { 3, 0, 4, 7 }\n    };\n\n\n  \n  switch (et)\n    {\n    case TRIG:\n    case TRIG6:\n      return trig_faces;\n\n    case QUAD:\n    case QUAD6:\n    case QUAD8:\n      return quad_faces;\n\n\n    case TET:\n    case TET10:\n      return tet_faces;\n\n    case PRISM:\n    case PRISM12:\n    case PRISM15:\n      return prism_faces;\n\n    case PYRAMID:\n    case PYRAMID13:\n      return pyramid_faces;\n\n    case SEGMENT:\n    case SEGMENT3:\n\n    case HEX7:\n      return hex7_faces;\n\n    case HEX:\n    case HEX20:\n      return hex_faces;\n\n      // default:\n      // cerr << \"Ng_ME_GetVertices, illegal element type \" << et << endl;\n    }\n  return 0;\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/meshing/validate.cpp",
    "content": "\n#include <mystdlib.h>\n#include \"meshing.hpp\"\n\n\nnamespace netgen\n{\n  void GetPureBadness(Mesh & mesh, NgArray<double> & pure_badness,\n\t\t      const TBitArray<PointIndex> & isnewpoint)\n  {\n    //const int ne = mesh.GetNE();\n    const int np = mesh.GetNP();\n\n    pure_badness.SetSize(np+PointIndex::BASE+1);\n    pure_badness = -1;\n\n    NgArray< Point<3>* > backup(np);\n\n    for(int i=0; i<np; i++)\n      {\n\tbackup[i] = new Point<3>(mesh.Point(i+1));\n\n\tif(isnewpoint.Test(i+IndexBASE<PointIndex>()) &&\n\t   mesh.mlbetweennodes[i+IndexBASE<PointIndex>()][0].IsValid())\n\t  {\n\t    mesh.Point(i+1) = Center(mesh.Point(mesh.mlbetweennodes[i+IndexBASE<PointIndex>()][0]),\n\t\t\t\t     mesh.Point(mesh.mlbetweennodes[i+IndexBASE<PointIndex>()][1]));\n\t  }\n      }\n    for (ElementIndex i = 0; i < mesh.GetNE(); i++)\n      {\n\tdouble bad = mesh[i].CalcJacobianBadness (mesh.Points());\n\tfor(int j=0; j<mesh[i].GetNP(); j++)\n\t  if(bad > pure_badness[mesh[i][j]])\n\t    pure_badness[mesh[i][j]] = bad;\n\n\t// save maximum\n\tif(bad > pure_badness.Last())\n\t  pure_badness.Last() = bad; \n      }\n    \n    for(int i=0; i<np; i++)\n      {\n\tmesh.Point(i+1) = *backup[i];\n\tdelete backup[i];\n      }\n  }\n\n\n  double Validate(const Mesh & mesh, NgArray<ElementIndex> & bad_elements,\n\t\t  const NgArray<double> & pure_badness,\n\t\t  double max_worsening, const bool uselocalworsening,\n\t\t  NgArray<double> * quality_loss)\n  {\n    PrintMessage(3,\"!!!! Validating !!!!\");\n    //if(max_worsening > 0)\n    //  (*testout) << \"badness \" << counter++ << endl;\n\n    bad_elements.SetSize(0);\n\n    double loc_pure_badness = -1;\n\n    if(!uselocalworsening)\n      loc_pure_badness = pure_badness.Last(); // maximum is saved at last position\n\n\n    double worsening = -1;\n    ElementIndex ind;\n\n    if(quality_loss != NULL)\n      quality_loss->SetSize(mesh.GetNE());\n\n    for (ElementIndex i = 0; i < mesh.GetNE(); i++)\n      {\n\tif(uselocalworsening)\n\t  {\n\t    loc_pure_badness = -1;\n\t    for(int j=0; j<mesh[i].GetNP(); j++)\n\t      if(pure_badness[mesh[i][j]] > loc_pure_badness)\n\t\tloc_pure_badness = pure_badness[mesh[i][j]];\n\t  }\n\n\n\tdouble bad = mesh[i].CalcJacobianBadness (mesh.Points());\n\tif (bad > 1e10 || \n\t    (max_worsening > 0 && bad > loc_pure_badness*max_worsening))\n\t  bad_elements.Append(i);\n\t  \n\n\tif(max_worsening > 0)\n\t  {\n\t    double actw = bad/loc_pure_badness;\n\t    if(quality_loss != NULL)\n\t      (*quality_loss)[i] = actw;\n\n\t    if(actw > worsening)\n\t      {\n\t\tworsening = actw;\n\t\tind = i;\n\t      }\n\t  }\n      }\n    return worsening;\n  }\n\n\n  void GetWorkingArea(BitArray & working_elements, TBitArray<PointIndex> & working_points,\n\t\t      const Mesh & mesh, const NgArray<ElementIndex> & bad_elements,\n\t\t      const int width)\n  {\n    working_elements.Clear();\n    working_points.Clear();\n\n    for(int i=0; i<bad_elements.Size(); i++)\n      {\n\tworking_elements.SetBit(bad_elements[i]);\n\tconst Element & el = mesh[bad_elements[i]];\n\tfor(int j=1; j<=el.GetNP(); j++)\n\t  working_points.SetBit(el.PNum(j));\n      }\n    \n\n    for(int i=0; i<width; i++)\n      {\n\tfor(ElementIndex j=0; j<mesh.GetNE(); j++)\n\t  {\n\t    if(!working_elements.Test(j))\n\t      {  \n\t\tconst Element & el = mesh[j];\n\t\tbool set_active = false;\n\t\t\n\t\tfor(int k=1; !set_active && k<=el.GetNP(); k++)\n\t\t  set_active = working_points.Test(el.PNum(k));\n\t\t\n\t\tif(set_active)\n\t\t  working_elements.SetBit(j);\n\t      }\n\t  }\n\n\tfor(ElementIndex j=0; j<mesh.GetNE(); j++)\n\t  {\n\t    if(working_elements.Test(j))\n\t      {\n\t\tconst Element & el = mesh[j];\n\t\tfor(int k=1; k<=el.GetNP(); k++)\n\t\t  working_points.SetBit(el.PNum(k));\n\t      }\n\t  }\n      }\n  }\n\n\n\n  void RepairBisection(Mesh & mesh, NgArray<ElementIndex> & bad_elements, \n\t\t       const TBitArray<PointIndex> & isnewpoint, const Refinement & refinement,\n\t\t       const NgArray<double> & pure_badness, \n\t\t       double max_worsening, const bool uselocalworsening,\n\t\t       const NgArray< idmap_type* > & idmaps)\n  {\n    ostringstream ostrstr;\n\n    const int maxtrials = 100;\n\n    //bool doit;\n    //cout << \"DOIT: \" << flush;\n    //cin >> doit;\n\n    int ne = mesh.GetNE();\n    int np = mesh.GetNP();\n\n    int numbadneighbours = 3;\n    const int numtopimprove = 3;\n\n    PrintMessage(1,\"repairing\");\n\n    PushStatus(\"Repair Bisection\");\n\n    NgArray<Point<3>* > should(np);\n    NgArray<Point<3>* > can(np);\n    NgArray<Vec<3>* > nv(np);\n    for(int i=0; i<np; i++)\n      {\n\tnv[i] = new Vec<3>;\n\tshould[i] = new Point<3>;\n\tcan[i] = new Point<3>;\n      }\n    \n    TBitArray<PointIndex> isboundarypoint(np),isedgepoint(np);\n    isboundarypoint.Clear();\n    isedgepoint.Clear();\n\n    for(int i = 1; i <= mesh.GetNSeg(); i++)\n      {\n\tconst Segment & seg = mesh.LineSegment(i);\n\tisedgepoint.SetBit(seg[0]);\n\tisedgepoint.SetBit(seg[1]);\n      }\n\n    NgArray<int> surfaceindex(np);\n    surfaceindex = -1;\n\n    /*\n    for (int i = 1; i <= mesh.GetNSE(); i++)\n      {\n\tconst Element2d & sel = mesh.SurfaceElement(i);\n    */\n    for (auto & sel : mesh.SurfaceElements())\n      for (int j = 1; j <= sel.GetNP(); j++)\n        if(!isedgepoint.Test(sel.PNum(j)))\n          {\n            isboundarypoint.SetBit(sel.PNum(j));\n            surfaceindex[sel.PNum(j) - IndexBASE<PointIndex>()] = \n              mesh.GetFaceDescriptor(sel.GetIndex()).SurfNr();\n          }\n    \n\n\n    Validate(mesh,bad_elements,pure_badness,\n\t     ((uselocalworsening) ?  (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)),\n\t     uselocalworsening); // -> larger working area\n    TBitArray<ElementIndex> working_elements(ne+1);\n    TBitArray<PointIndex> working_points(np);\n\n    GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours);\n    //working_elements.Set();\n    //working_points.Set();\n\n    ostrstr.str(\"\");\n    ostrstr << \"worsening: \" <<\n      Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening);\n    PrintMessage(4,ostrstr.str());\n\n    \n\n    int auxnum=0;\n    for(int i=1; i<=np; i++)\n      if(working_points.Test(i))\n\tauxnum++;\n    \n    ostrstr.str(\"\");\n    ostrstr << \"Percentage working points: \" << 100.*double(auxnum)/np;\n    PrintMessage(5,ostrstr.str());\n    \n\n    TBitArray<PointIndex> isworkingboundary(np);\n    for(int i=1; i<=np; i++)\n      if(working_points.Test(i) && isboundarypoint.Test(i))\n\tisworkingboundary.SetBit(i);\n      else\n\tisworkingboundary.Clear(i);\n\n\n    for(int i=0; i<np; i++)\n      *should[i] = mesh.Point(i+1);\n\n    \n    // for(int i=0; i<np; i++)\n    for (PointIndex i = IndexBASE<PointIndex>(); i < IndexBASE<PointIndex>()+np; i++)\n      {\n\tif(isnewpoint.Test(i) && \n\t   //working_points.Test(i+PointIndex::BASE) && \n\t   mesh.mlbetweennodes[i][0].IsValid())\n\t  *can[i-IndexBASE<PointIndex>()] = Center(*can[mesh.mlbetweennodes[i][0]-IndexBASE<PointIndex>()],\n                                                   *can[mesh.mlbetweennodes[i][1]-IndexBASE<PointIndex>()]);\n\telse\n\t  *can[i-IndexBASE<PointIndex>()] = mesh[i];\n      }\n\n\n    int cnttrials = 1;\n    \n    double lamedge = 0.5;\n    double lamface = 0.5;\n    \n    double facokedge = 0;\n    double facokface = 0;\n    double factryedge;\n    double factryface = 0;\n\n    double oldlamedge,oldlamface;\n\n    auto geo = mesh.GetGeometry();\n    if(!geo)\n      {\n\tcerr << \"No 2D Optimizer!\" << endl;\n\treturn;\n      }    \n\n    while ((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && \n\t   cnttrials < maxtrials &&\n\t   multithread.terminate != 1)\n      {\n\t(*testout) << \"   facokedge \" << facokedge << \" facokface \" << facokface << \" cnttrials \" << cnttrials << endl\n\t\t   << \" perc. \" << 95. * max2( min2(facokedge,facokface),\n\t\t\t\t\t       double(cnttrials)/double(maxtrials)) << endl;\n\n\tSetThreadPercent(95. * max2( min2(facokedge,facokface),\n\t\t\t\t     double(cnttrials)/double(maxtrials)));\n\n\tostrstr.str(\"\");\n\tostrstr << \"max. worsening \" << max_worsening;\n\tPrintMessage(5,ostrstr.str());\n\toldlamedge = lamedge;\n\tlamedge *= 6;\n\tif (lamedge > 2)\n\t  lamedge = 2;\n\t   \n\tif(1==1 || facokedge < 1.-1e-8)\n\t  {\n\t    for(int i=0; i<nv.Size(); i++)\n\t      *nv[i] = Vec<3>(0,0,0);\n            /*\n\t    for (int i = 1; i <= mesh.GetNSE(); i++)\n\t      {\n\t\tconst Element2d & sel = mesh.SurfaceElement(i);\n            */\n            for (auto & sel : mesh.SurfaceElements())\n              {\n\t\tVec<3> auxvec = Cross(mesh.Point(sel.PNum(2))-mesh.Point(sel.PNum(1)),\n                                      mesh.Point(sel.PNum(3))-mesh.Point(sel.PNum(1)));\n\t\tauxvec.Normalize();\n\t\tfor (int j = 1; j <= sel.GetNP(); j++)\n\t\t  if(!isedgepoint.Test(sel.PNum(j)))\n\t\t    *nv[sel.PNum(j) - IndexBASE<PointIndex>()] += auxvec;\n\t      }\n\t    for(int i=0; i<nv.Size(); i++)\n\t      nv[i]->Normalize();\n\t    \n\t    \n\t    do  // move edges\n\t      {\n\t\tlamedge *= 0.5;\n\t\tcnttrials++;\n\t\tif(cnttrials % 10 == 0)\n\t\t  max_worsening *= 1.1;\n\t\t\n\t\t\n\t\tfactryedge = lamedge + (1.-lamedge) * facokedge;\n\n\t\tostrstr.str(\"\");\n\t\tostrstr << \"lamedge = \" << lamedge << \", trying: \" << factryedge;\n\t\tPrintMessage(5,ostrstr.str());\n\t\t\n\n\t\tfor (int i = 1; i <= np; i++)\n\t\t  {\n\t\t    if (isedgepoint.Test(i))\n\t\t      {\n\t\t\tfor (int j = 0; j < 3; j++)\n\t\t\t  mesh.Point(i)(j) = \n\t\t\t    lamedge * (*should.Get(i))(j) +\n\t\t\t    (1.-lamedge) * (*can.Get(i))(j);\n\t\t      }\n\t\t    else\n\t\t      mesh.Point(i) = *can.Get(i);\n\t\t  }\n\t\tif(facokedge < 1.-1e-8)\n\t\t  {\n\t\t    ostrstr.str(\"\");\n\t\t    ostrstr << \"worsening: \" <<\n\t\t      Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening);\n\n\t\t    PrintMessage(5,ostrstr.str());\n\t\t  }\n\t\telse\n\t\t  Validate(mesh,bad_elements,pure_badness,-1,uselocalworsening);\n\n\n\t\tostrstr.str(\"\");\n\t\tostrstr << bad_elements.Size() << \" bad elements\";\n\t\tPrintMessage(5,ostrstr.str());\n\t      }\n\t    while (bad_elements.Size() > 0 && \n\t\t   cnttrials < maxtrials &&\n\t\t   multithread.terminate != 1);\n\t  }\n\n\tif(cnttrials < maxtrials &&\n\t   multithread.terminate != 1)\n\t  {\n\t    facokedge = factryedge;\n\t    \n\t    // smooth faces\n\t    mesh.CalcSurfacesOfNode();\n\t    \n\t    MeshingParameters dummymp;\n\t    mesh.ImproveMeshJacobianOnSurface(dummymp,isworkingboundary,nv,OPT_QUALITY, &idmaps);\n\t    \n\t    for (int i = 1; i <= np; i++)\n\t      *can.Elem(i) = mesh.Point(i);\n\t    \n\t    if(geo)\n              for(int i=0; i<surfaceindex.Size(); i++)\n                {\n                  if(surfaceindex[i] >= 0)\n                    {\n                      *should[i] = *can[i];\n                      geo->ProjectPoint(surfaceindex[i],*should[i]);\n                    }\n                }\n\t  }\n\n\n\toldlamface = lamface;\n\tlamface *= 6;\n\tif (lamface > 2)\n\t  lamface = 2;\n\n\n\tif(cnttrials < maxtrials &&\n\t   multithread.terminate != 1)\n\t  {\n\n\t    do  // move faces\n\t      {\n\t\tlamface *= 0.5;\n\t\tcnttrials++;\n\t\tif(cnttrials % 10 == 0)\n\t\t  max_worsening *= 1.1;\n\t\tfactryface = lamface + (1.-lamface) * facokface;\n\n\t\tostrstr.str(\"\");\n\t\tostrstr << \"lamface = \" << lamface << \", trying: \" << factryface;\n\t\tPrintMessage(5,ostrstr.str());\n\t\t\n\t\t\n\t\tfor (int i = 1; i <= np; i++)\n\t\t  {\n\t\t    if (isboundarypoint.Test(i))\n\t\t      {\n\t\t\tfor (int j = 0; j < 3; j++)\n\t\t\t  mesh.Point(i)(j) = \n\t\t\t    lamface * (*should.Get(i))(j) +\n\t\t\t    (1.-lamface) * (*can.Get(i))(j);\n\t\t      }\n\t\t    else\n\t\t      mesh.Point(i) = *can.Get(i);\n\t\t  }\n\n\t\tostrstr.str(\"\");\n\t\tostrstr << \"worsening: \" <<\n\t\t  Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening);\n\t\tPrintMessage(5,ostrstr.str());\n\t\n\n\t\tostrstr.str(\"\");\n\t\tostrstr << bad_elements.Size() << \" bad elements\";\n\t\tPrintMessage(5,ostrstr.str());\n\t      }\n\t    while (bad_elements.Size() > 0 && \n\t\t   cnttrials < maxtrials &&\n\t\t   multithread.terminate != 1);\n\t  }\n\n\n\n\tif(cnttrials < maxtrials &&\n\t   multithread.terminate != 1)\n\t  {\n\t    facokface = factryface;\n\t    // smooth interior\n\t    \n\t    mesh.CalcSurfacesOfNode();\n\t    \n\t    MeshingParameters dummymp;\n\t    mesh.ImproveMeshJacobian (dummymp, OPT_QUALITY,&working_points);\n\t    //mesh.ImproveMeshJacobian (OPT_WORSTCASE,&working_points);\n\t  \n\n\t    for (int i = 1; i <= np; i++)\n\t      *can.Elem(i) = mesh.Point(i);\n\t  }\n\t  \n\t//!\n\tif((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && \n\t   cnttrials < maxtrials &&\n\t   multithread.terminate != 1)\n\t  {\n\t    MeshingParameters dummymp;\n\t    MeshOptimize3d optmesh(mesh, dummymp, OPT_QUALITY);\n\t    for(int i=0; i<numtopimprove; i++)\n\t      {\n\t\toptmesh.SwapImproveSurface(&working_elements,&idmaps);\n\t\toptmesh.SwapImprove(&working_elements);\n\t\t\n\t      }\t    \n\n\t    //\t    mesh.mglevels = 1;\n\t    \n\t\t\n\t    ne = mesh.GetNE();\n\t    working_elements.SetSize(ne);\n\t    \n\t    \n\t    for (int i = 1; i <= np; i++)\n\t      mesh.Point(i) = *should.Elem(i);\n\t    \n\t    Validate(mesh,bad_elements,pure_badness,\n\t\t     ((uselocalworsening) ?  (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)),\n\t\t     uselocalworsening);\n\t    \n\t    if(lamedge < oldlamedge || lamface < oldlamface)\n\t      numbadneighbours++;\n\t    GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours);\n\t    for(int i=1; i<=np; i++)\n\t      if(working_points.Test(i) && isboundarypoint.Test(i))\n\t\tisworkingboundary.SetBit(i);\n\t      else\n\t\tisworkingboundary.Clear(i);\n\t    auxnum=0;\n\t    for(int i=1; i<=np; i++)\n\t      if(working_points.Test(i))\n\t\tauxnum++;\n\n\t    \n\t    ostrstr.str(\"\");\n\t    ostrstr << \"Percentage working points: \" << 100.*double(auxnum)/np;\n\t    PrintMessage(5,ostrstr.str());\n\t    \n\t    for (int i = 1; i <= np; i++)\n\t      mesh.Point(i) = *can.Elem(i);\n\t  }\n\t//!\n\n      }\n\n    MeshingParameters dummymp;\n    MeshOptimize3d optmesh(mesh, dummymp, OPT_QUALITY);\n    for(int i=0; i<numtopimprove && multithread.terminate != 1; i++)\n      {\n\toptmesh.SwapImproveSurface(NULL,&idmaps);\n\toptmesh.SwapImprove();\n\t//mesh.UpdateTopology();\n      }\n    mesh.UpdateTopology();\n    /*\n    if(cnttrials < 100)\n      {\n\tnv = Vec3d(0,0,0);\n\tfor (int i = 1; i <= mesh.GetNSE(); i++)\n\t  {\n\t    const Element2d & sel = mesh.SurfaceElement(i);\n\t    Vec3d auxvec = Cross(mesh.Point(sel.PNum(2))-mesh.Point(sel.PNum(1)),\n\t\t\t\t mesh.Point(sel.PNum(3))-mesh.Point(sel.PNum(1)));\n\t    auxvec.Normalize();\n\t    for (int j = 1; j <= sel.GetNP(); j++)\n\t      if(!isedgepoint.Test(sel.PNum(j)))\n\t\tnv[sel.PNum(j) - PointIndex::BASE] += auxvec;\n\t  }\n\tfor(int i=0; i<nv.Size(); i++)\n\t  nv[i].Normalize();\n\t\n\n\tmesh.ImproveMeshJacobianOnSurface(isboundarypoint,nv,OPT_QUALITY);\n\tmesh.CalcSurfacesOfNode();\n\t    // smooth interior\n\t    \n\t\n\tfor (int i = 1; i <= np; i++)\n\t  if(isboundarypoint.Test(i))\n\t    can.Elem(i) = mesh.Point(i);\n\t    \n\tif(optimizer2d)\n\t  optimizer2d->ProjectBoundaryPoints(surfaceindex,can,should);\n\n\t\n\tfor (int i = 1; i <= np; i++)\n\t  if(isboundarypoint.Test(i))\n\t    for(int j=1; j<=3; j++)\n\t      mesh.Point(i).X(j) = should.Get(i).X(j);\n      }\n    */\n\n\n    if(cnttrials == maxtrials)\n      {\n\tfor (int i = 1; i <= np; i++)\n\t  mesh.Point(i) = *should.Get(i);\n\n\tValidate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening);\n\t\n\tfor(int i=0; i<bad_elements.Size(); i++)\n\t  {\n\t    ostrstr.str(\"\");\n\t    ostrstr << \"bad element:\" << endl\n\t\t    << mesh[bad_elements[i]][0] << \": \" << mesh.Point(mesh[bad_elements[i]][0]) << endl\n\t\t    << mesh[bad_elements[i]][1] << \": \" << mesh.Point(mesh[bad_elements[i]][1]) << endl\n\t\t    << mesh[bad_elements[i]][2] << \": \" << mesh.Point(mesh[bad_elements[i]][2]) << endl\n\t\t    << mesh[bad_elements[i]][3] << \": \" << mesh.Point(mesh[bad_elements[i]][3]);\n\t    PrintMessage(5,ostrstr.str());\n\t  }\n\tfor (int i = 1; i <= np; i++)\n\t  mesh.Point(i) = *can.Get(i);\n      }\n\n    for(int i=0; i<np; i++)\n      {\n\tdelete nv[i];\n\tdelete can[i];\n\tdelete should[i];\n      }\n\n    PopStatus();\n  }\n}\n"
  },
  {
    "path": "libsrc/meshing/validate.hpp",
    "content": "#ifndef VALIDATE_HPP\n#define VALIDATE_HPP\n\nnamespace netgen\n{\n  \n  void GetPureBadness(Mesh & mesh, NgArray<double> & pure_badness,\n\t\t      const TBitArray<PointIndex> & isnewpoint);\n  double Validate(const Mesh & mesh, NgArray<ElementIndex> & bad_elements,\n\t\t  const NgArray<double> & pure_badness, \n\t\t  double max_worsening, const bool uselocalworsening,\n\t\t  NgArray<double> * quality_loss = NULL);\n  void RepairBisection(Mesh & mesh, NgArray<ElementIndex> & bad_elements, \n\t\t       const TBitArray<PointIndex> & isnewpoint, const Refinement & refinement,\n\t\t       const NgArray<double> & pure_badness, \n\t\t       double max_worsening, const bool uselocalworsening,\n\t\t       const NgArray< idmap_type* > & idmaps);\n\n}\n\n#endif // VALIDATE_HPP\n"
  },
  {
    "path": "libsrc/meshing/visual_interface.cpp",
    "content": "#include \"visual_interface.hpp\"\n#include \"../include/nginterface.h\"\n\nvoid (*Ptr_Ng_ClearSolutionData) () = nullptr;\nvoid (*Ptr_Ng_InitSolutionData) (Ng_SolutionData*)  = nullptr;\nvoid (*Ptr_Ng_SetSolutionData) (Ng_SolutionData*) = nullptr;\nvoid (*Ptr_Ng_Redraw) (bool blocking) = nullptr;\n\nvoid Ng_ClearSolutionData () { if(Ptr_Ng_ClearSolutionData) Ptr_Ng_ClearSolutionData(); }\nvoid Ng_InitSolutionData (Ng_SolutionData * soldata) { if(Ptr_Ng_InitSolutionData) Ptr_Ng_InitSolutionData(soldata); }\nvoid Ng_SetSolutionData (Ng_SolutionData * soldata) { if(Ptr_Ng_SetSolutionData) Ptr_Ng_SetSolutionData(soldata); }\nvoid Ng_Redraw (bool blocking) { if(Ptr_Ng_Redraw) Ptr_Ng_Redraw(blocking); }\n\nnamespace netgen\n{\n    void (*Ptr_Ng_Tcl_SetResult)(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc) = nullptr;\n    void (*Ptr_Ng_Tcl_CreateCommand)(Tcl_Interp *interp,\n                                    const char *cmdName, Tcl_CmdProc *proc) = nullptr;\n    void (*Ptr_Render)(bool) = nullptr;\n    void (*Ptr_UpdateVisSurfaceMeshData)(int,\n            shared_ptr<NgArray<Point<3>>>,\n            shared_ptr<NgArray<INDEX_2>>,\n            shared_ptr<NgArray<Point<2>>>\n            ) = nullptr;\n} // namespace netgen\n\n"
  },
  {
    "path": "libsrc/meshing/visual_interface.hpp",
    "content": "#ifndef VISUAL_INTERFACE_HPP_INCLUDED\n#define VISUAL_INTERFACE_HPP_INCLUDED\n\n#include <mystdlib.h>\n#include <meshing.hpp>\n#include <myadt.hpp>\n\nstruct Ng_SolutionData;\n\n// Function pointers for visualization purposed, all set to nullptr by default and initialized correctly when the GUI library is loaded\n\nDLL_HEADER extern void (*Ptr_Ng_ClearSolutionData) ();\nDLL_HEADER extern void (*Ptr_Ng_InitSolutionData) (Ng_SolutionData * soldata);\nDLL_HEADER extern void (*Ptr_Ng_SetSolutionData) (Ng_SolutionData * soldata);\nDLL_HEADER extern void (*Ptr_Ng_Redraw) (bool blocking);\n\n// Tcl wrapper functions\nstruct Tcl_Interp;\ntypedef int (Tcl_CmdProc) (void * clientData, Tcl_Interp *interp,\n        int argc, const char *argv[]);\ntypedef void (Tcl_FreeProc) (char *blockPtr);\n\nnamespace netgen {\n  /*\n  inline constexpr int NG_TCL_VOLATILE = 1;\n  inline constexpr int NG_TCL_STATIC   = 0;\n  inline constexpr int NG_TCL_DYNAMIC  = 3;\n  */\n\n#define NG_TCL_VOLATILE\t\t((Tcl_FreeProc *) 1)\n#define NG_TCL_STATIC\t\t((Tcl_FreeProc *) 0)\n#define NG_TCL_DYNAMIC\t\t((Tcl_FreeProc *) 3)\n\n    inline constexpr int NG_TCL_OK       = 0;\n    inline constexpr int NG_TCL_ERROR    = 1;\n    inline constexpr int NG_TCL_RETURN   = 2;\n    inline constexpr int NG_TCL_BREAK    = 3;\n    inline constexpr int NG_TCL_CONTINUE = 4;\n    DLL_HEADER extern void (*Ptr_Ng_Tcl_SetResult)(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc);\n    DLL_HEADER extern void (*Ptr_Ng_Tcl_CreateCommand)(Tcl_Interp *interp,\n                                    const char *cmdName, Tcl_CmdProc *proc);\n\n    DLL_HEADER extern void (*Ptr_Render)(bool);\n    DLL_HEADER extern void (*Ptr_UpdateVisSurfaceMeshData)(int,\n            shared_ptr<NgArray<Point<3>>>,\n            shared_ptr<NgArray<INDEX_2>>,\n            shared_ptr<NgArray<Point<2>>>\n            );\n\n    inline void Render(bool blocking = false) { if(Ptr_Render) Ptr_Render(blocking); }\n    inline void UpdateVisSurfaceMeshData(int oldnl,\n            shared_ptr<NgArray<Point<3>>> locpointsptr = nullptr,\n            shared_ptr<NgArray<INDEX_2>> loclinesptr = nullptr,\n            shared_ptr<NgArray<Point<2>>> plainpointsptr = nullptr\n            ) {\n        if(Ptr_UpdateVisSurfaceMeshData) Ptr_UpdateVisSurfaceMeshData(oldnl, locpointsptr, loclinesptr, plainpointsptr);\n    }\n\n    inline void Ng_Tcl_SetResult(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc)\n    {\n        if(Ptr_Ng_Tcl_SetResult)\n            Ptr_Ng_Tcl_SetResult(interp, result, freeProc);\n    }\n    inline void Ng_Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc)\n    {\n        if(Ptr_Ng_Tcl_CreateCommand)\n            Ptr_Ng_Tcl_CreateCommand(interp, cmdName, proc);\n    }\n}\n\n#endif // VISUAL_INTERFACE_HPP_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n        Partition_Inter2d.cxx Partition_Inter3d.cxx \n        Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx \n        occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp\n        python_occ_basic.cpp python_occ_shapes.cpp\n        occ_face.cpp occ_edge.cpp occ_vertex.cpp occ_utils.cpp\n        cross_section.cpp\n)\n\nif(USE_GUI)\n    target_sources(nggui PRIVATE vsocc.cpp occpkg.cpp)\nendif(USE_GUI)\n\ninstall(FILES\n  occgeom.hpp occmeshsurf.hpp vsocc.hpp occ_utils.hpp\n  occ_vertex.hpp occ_edge.hpp occ_face.hpp occ_solid.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/occ COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter2d.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R& D, LEG, PRINCIPIA R& D, BUREAU VERITAS\n//\n//  This library is free software; you can redistribute it and/or\n//  modify it under the terms of the GNU Lesser General Public\n//  License as published by the Free Software Foundation; either\n//  version 2.1 of the License.\n//\n//  This library is distributed in the hope that it will be useful,\n//  but WITHOUT ANY WARRANTY; without even the implied warranty of\n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n//  Lesser General Public License for more details.\n//\n//  You should have received a copy of the GNU Lesser General Public\n//  License along with this library; if not, write to the Free Software\n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\n//\n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org\n//\n//\n//\n//  File   : Partition_Inter2d.cxx\n//  Author : Benedicte MARTIN\n//  Module : GEOM\n//  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter2d.cxx,v 1.5 2008/03/31 14:20:28 wabro Exp $\n\n//using namespace std;\n\n#include \"Partition_Inter2d.ixx\"\n\n#include \"utilities.h\"\n\n#include <BRepAdaptor_Curve.hxx>\n#include <BRepAlgo_AsDes.hxx>\n#include <BRepLib_MakeVertex.hxx>\n#include <BRep_Builder.hxx>\n#include <BRep_Tool.hxx>\n#include <Geom_Surface.hxx>\n#include <Precision.hxx>\n#include <TopExp.hxx>\n#include <TopExp_Explorer.hxx>\n#include <TopOpeBRepDS_Transition.hxx>\n#include <TopOpeBRep_EdgesIntersector.hxx>\n#include <TopOpeBRep_Point2d.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopTools_ListOfShape.hxx>\n#include <TopTools_MapIteratorOfMapOfShape.hxx>\n#include <TopTools_MapOfShape.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Edge.hxx>\n#include <TopoDS_Vertex.hxx>\n#include <gp_Pnt.hxx>\n\n#ifdef DEB\nstatic Standard_Boolean TestEdges = 0;\nstatic Standard_Integer NbF2d = 0;\nstatic Standard_Integer NbE2d = 0;\n#endif\n\n//=======================================================================\n//function : getOtherShape\n//purpose  :\n//=======================================================================\n\nstatic TopoDS_Shape getOtherShape(const TopoDS_Shape&         theS,\n                                  const TopTools_ListOfShape& theSList)\n{\n  TopTools_ListIteratorOfListOfShape anIt( theSList );\n  for ( ; anIt.More(); anIt.Next() )\n    if (!theS.IsSame( anIt.Value() ))\n      return anIt.Value();\n\n  return TopoDS_Shape();\n}\n\n//=======================================================================\n//function : findVOnE\n//purpose  : on theE, find a vertex close to theV, such that an edge\n//           passing through it is an itersection of theF1 and theF2.\n//           theE intersects theE2 at theV\n//=======================================================================\n\nstatic Standard_Boolean findVOnE(const TopoDS_Vertex &         theV,\n                                 const TopoDS_Edge&            theE,\n                                 const TopoDS_Edge&            theE2,\n                                 const TopoDS_Shape&           theF1,\n                                 const TopoDS_Shape&           theF2,\n                                 const Handle(BRepAlgo_AsDes)& theAsDes,\n                                 TopoDS_Vertex &               theFoundV)\n{\n  Standard_Real MinDist2 = ::RealLast();\n  gp_Pnt P;\n\n  // check all vertices on theE\n  const TopTools_ListOfShape& aVList = theAsDes->Descendant( theE );\n  TopTools_ListIteratorOfListOfShape anIt( aVList );\n  if (anIt.More())\n    P = BRep_Tool::Pnt( theV );\n  for ( ; anIt.More(); anIt.Next() )\n  {\n    // check by distance\n    TopoDS_Vertex & V = TopoDS::Vertex( anIt.Value() );\n    Standard_Real dist2 = P.SquareDistance( BRep_Tool::Pnt( V ));\n    if (dist2 < MinDist2)\n      MinDist2 = dist2;\n    else\n      continue;\n\n    // V is a candidate if among edges passing through V there is one\n    // which is an intersection of theF1 and theF2\n    TopTools_ListIteratorOfListOfShape anEIt( theAsDes->Ascendant( V ));\n    Standard_Boolean isOk = Standard_False;\n    for (  ; !isOk && anEIt.More(); anEIt.Next() )\n    {\n      const TopoDS_Shape & E2 = anEIt.Value();\n      if ( theE2.IsSame( E2 ))\n        continue;\n      const TopTools_ListOfShape & aFList = theAsDes->Ascendant( E2 );\n      if (aFList.IsEmpty())\n        continue;\n      if ( theF1.IsSame( aFList.First() ))\n        isOk = theF2.IsSame( aFList.Last() );\n      else\n        isOk = theF2.IsSame( aFList.First() ) && theF1.IsSame( aFList.Last() );\n    }\n    if (isOk)\n      theFoundV = V;\n  }\n\n  if (theFoundV.IsNull())\n    return Standard_False;\n\n  // check that MinDist2 is not too large\n  Standard_Real f, l;\n  TopLoc_Location L;\n  Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theE, L, f, l );\n  gp_Pnt P1 = aCurve->Value( f );\n  gp_Pnt P2 = aCurve->Value( 0.3 * f + 0.7 * l );\n  //gp_Pnt P2 = aCurve->Value( 0.5 * ( f + l ));\n  if (MinDist2 > P1.SquareDistance( P2 ))\n    return Standard_False;\n\n#ifdef DEB\n  MESSAGE(\"findVOnE: found MinDist = \" << sqrt (MinDist2));\n#endif\n\n  return Standard_True;\n}\n\n//=======================================================================\n//function : AddVonE\n//purpose  : Put V in AsDes as intersection of E1 and E2.\n//           Check that vertex equal to V already exists on one\n//           of edges, in  such  a  case,  V  is  not added but\n//           existing vertex is updated to  be on E1 and E2 and\n//           is returned instead of V.\n//=======================================================================\n\nTopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV,\n                                         const TopoDS_Edge&   E1,\n                                         const TopoDS_Edge&   E2,\n                                         const Handle(BRepAlgo_AsDes)& AsDes,\n                                         const TopoDS_Face&   theF)\n\n{\n  //-------------------------------------------------------------\n  // test if the points of intersection already exist. If not,\n  // add as descendants of the edges.\n  // nb: these points are only vertices of intersection.\n  //-------------------------------------------------------------\n  const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1);\n  const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2);\n  gp_Pnt                      P1,P2;\n  TopoDS_Vertex               V1,V2;\n  TopTools_ListIteratorOfListOfShape it;\n  BRep_Builder                       B;\n  TopAbs_Orientation                 O1,O2;\n  Standard_Real                      U1,U2;\n  Standard_Real                      Tol,Tol1,Tol2;\n  Standard_Boolean                   OnE1,OnE2;\n\n  TopoDS_Vertex V    = theV;\n\n  U1 = BRep_Tool::Parameter(V,E1);\n  U2 = BRep_Tool::Parameter(V,E2);\n  O1 = V.Orientation();\n  O2 = O1;\n  P1  = BRep_Tool::Pnt(V);\n  Tol = BRep_Tool::Tolerance( V );\n  OnE1 = OnE2 = Standard_False;\n\n  //-----------------------------------------------------------------\n  // Search if the point of intersection is a vertex of E1.\n  //-----------------------------------------------------------------\n  for (it.Initialize(VOnE1); it.More(); it.Next()) {\n    const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );\n    if (V.IsSame( CV )) {\n      V1   = V;\n      OnE1 = Standard_True;\n      break;\n    }\n    P2 = BRep_Tool::Pnt( CV );\n    Tol1 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));\n    if (P1.SquareDistance(P2) <= Tol1*Tol1) {\n      V    = CV;\n      V1   = V;\n      OnE1 = Standard_True;\n      break;\n    }\n  }\n  if (OnE1) {\n    //-----------------------------------------------------------------\n    // Search if the vertex found is still on E2.\n    //-----------------------------------------------------------------\n    for (it.Initialize(VOnE2); it.More(); it.Next()) {\n      if (V.IsSame( it.Value() )) {\n        OnE2 = Standard_True;\n        V2   = V;\n        break;\n      }\n    }\n  }\n  if (!OnE2) {\n    for (it.Initialize(VOnE2); it.More(); it.Next()) {\n      //-----------------------------------------------------------------\n      // Search if the point of intersection is a vertex of E2.\n      //-----------------------------------------------------------------\n      const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );\n      P2 = BRep_Tool::Pnt( CV );\n      Tol2 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));\n      if (P1.SquareDistance(P2) <= Tol2*Tol2) {\n        V  = CV;\n        V2 = V;\n        OnE2 = Standard_True;\n        break;\n      }\n    }\n  }\n\n\n  if (!OnE1 && !OnE2 && !theF.IsNull())\n  {\n    // if 3 faces intersects each others, 3 new edges on them must pass\n    // through one vertex but real intersection points of each\n    // pair of edges are sometimes more far than a tolerance.\n    // Try to analytically find vertices that E1 and E2 must pass through\n\n    TopoDS_Shape F1 = getOtherShape( theF, AsDes->Ascendant( E1 ));\n    TopoDS_Shape F2 = getOtherShape( theF, AsDes->Ascendant( E2 ));\n    if (!F1.IsNull() && !F2.IsNull() && !F1.IsSame( F2 ))\n    {\n      OnE1 = findVOnE ( theV, E1, E2, F1, F2, AsDes, V1 );\n      OnE2 = findVOnE ( theV, E2, E1, F1, F2, AsDes, V2 );\n      if (OnE2) V = V2;\n      if (OnE1) V = V1;\n    }\n  }\n\n  if (OnE1 && OnE2) {\n    if (!V1.IsSame(V2)) {\n      // replace V1 with V2 on all edges V1 is on\n      Standard_Real UV1;\n      TopoDS_Edge   EWE1;\n      TopoDS_Vertex VI;\n      const TopTools_ListOfShape& EdgeWithV1 = AsDes->Ascendant(V1);\n\n      for (it.Initialize(EdgeWithV1); it.More(); it.Next()) {\n        EWE1  = TopoDS::Edge(it.Value());\n        VI = V1;\n        VI.Orientation(TopAbs_INTERNAL);\n        UV1 = BRep_Tool::Parameter(VI,EWE1);\n        VI = V2;\n        VI.Orientation(TopAbs_INTERNAL);\n        B.UpdateVertex( VI, UV1, EWE1, GetTolerance( VI, UV1, EWE1, AsDes));\n      }\n      AsDes->Replace(V1,V2);\n      V = V2;\n    }\n  }\n\n  // add existing vertices instead of new ones\n  if (!OnE1) {\n    if (OnE2) {\n      V.Orientation(TopAbs_INTERNAL);\n      B.UpdateVertex (V, U1, E1, GetTolerance( V, U1, E1, AsDes));\n    }\n    V.Orientation(O1);\n    AsDes->Add(E1,V);\n  }\n  if (!OnE2) {\n    if (OnE1) {\n      V.Orientation(TopAbs_INTERNAL);\n      B.UpdateVertex (V, U2, E2, GetTolerance( V, U2, E2, AsDes ));\n    }\n    V.Orientation(O2);\n    AsDes->Add(E2,V);\n  }\n\n  return V;\n}\n\n//=======================================================================\n//function : FindEndVertex\n//purpose  : Returns a vertex  from  <VertList> having parameter on\n//           <E>  closest  to  <f>  or  <l>.  <isFirst>  is True if\n//           found vertex is closer  to <f>. <DU> returns parameter\n//           difference.\n//=======================================================================\n\nTopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV,\n                                               const Standard_Real f,\n                                               const Standard_Real l,\n                                               const TopoDS_Edge&  E,\n                                               Standard_Boolean&   isFirst,\n                                               Standard_Real&      minDU)\n{\n  TopoDS_Vertex endV;\n  Standard_Real U, endU, min;\n  minDU = 1.e10;\n\n  TopTools_ListIteratorOfListOfShape it;\n  it.Initialize(LV);\n  for (; it.More(); it.Next()) {\n    const TopoDS_Vertex& v = TopoDS::Vertex(it.Value());\n    U = BRep_Tool::Parameter(v, E);\n    min = Min( Abs(U-f), Abs(U-l) );\n    if (min < minDU) {\n      endV = v;\n      endU = U;\n      minDU = min;\n    }\n  }\n  if (Abs(endU-f) < Abs(endU-l))\n    isFirst = Standard_True;\n  else\n    isFirst = Standard_False;\n\n  return endV;\n}\n\n//=======================================================================\n//function : treatClosed\n//purpose  : add second vertex to closed edge. Vertex is one of <LV1>\n//=======================================================================\n\nstatic void treatClosed (const TopoDS_Edge& E1,\n                          const Standard_Real f,\n                          const Standard_Real l,\n                          TopTools_ListOfShape& LV1,\n                          TopTools_ListOfShape& /*LV2*/)\n{\n  Standard_Boolean isFirst=0;\n  Standard_Real    minDU = 1.e10;\n  TopoDS_Vertex endV;\n  endV = Partition_Inter2d::FindEndVertex(LV1, f,l, E1, isFirst,minDU);\n\n  if (minDU > Precision::PConfusion())\n    return; // not end point\n\n  Standard_Real newU;\n  if (isFirst)\n    newU = f + (l - f);\n  else\n    newU = l - (l - f);\n\n  // update end parameter\n  BRep_Builder B;\n  endV.Orientation(TopAbs_INTERNAL);\n  B.UpdateVertex(endV,newU,E1,BRep_Tool::Tolerance(endV));\n}\n\n//=======================================================================\n//function : EdgesPartition\n//purpose  :\n//=======================================================================\n\nstatic void EdgesPartition(const TopoDS_Face&            F,\n                           const TopoDS_Edge&            E1,\n                           const TopoDS_Edge&            E2,\n                           const Handle(BRepAlgo_AsDes)& AsDes,\n                           const TopTools_MapOfShape&    NewEdges,\n                           const Standard_Boolean        WithOri)\n{\n\n  Standard_Real f[3],l[3];\n  Standard_Real MilTol2;\n  Standard_Real Tol = Max (BRep_Tool::Tolerance(E1),\n                           BRep_Tool::Tolerance(E2));\n  MilTol2 = Tol * Tol * 10;\n\n  BRep_Tool::Range(E1, f[1], l[1]);\n  BRep_Tool::Range(E2, f[2], l[2]);\n\n  BRepAdaptor_Curve CE1(E1,F);\n  BRepAdaptor_Curve CE2(E2,F);\n\n  TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;\n  TopTools_ListOfShape        LV1; // new vertices at intersections on E1\n  TopTools_ListOfShape        LV2; // ... on E2\n  BRep_Builder                B;\n\n  // if E1 and E2 are results of intersection of F and two connex faces then\n  // no need to intersect edges, they can contact by vertices only\n  // (encountered an exception in TopOpeBRep_EdgesIntersector in such a case)\n  Standard_Boolean intersect = Standard_True;\n  TopTools_IndexedMapOfShape ME;\n  TopExp::MapShapes(F, TopAbs_EDGE, ME);\n  if (!ME.Contains(E1) && ! ME.Contains(E2)) { // if E1 and E2 are new on F\n    TopoDS_Shape F1, F2;\n    const TopTools_ListOfShape& LF1 = AsDes->Ascendant( E1 );\n    F1 = F.IsSame( LF1.First() ) ? LF1.Last() : LF1.First();\n    const TopTools_ListOfShape& LF2 = AsDes->Ascendant( E2 );\n    F2 = F.IsSame( LF2.First() ) ? LF2.Last() : LF2.First();\n    if (!F.IsSame(F2) && !F.IsSame(F1) ) {\n      TopExp_Explorer exp(F2, TopAbs_EDGE);\n      TopExp::MapShapes(F1, TopAbs_EDGE, ME);\n      for (; exp.More(); exp.Next()) {\n        if (ME.Contains( exp.Current())) {\n          intersect = Standard_False;\n          break;\n        }\n      }\n    }\n  }\n\n  if (intersect) {\n    //------------------------------------------------------\n    // compute the points of Intersection in 2D\n    //-----------------------------------------------------\n    // i.e. fill LV1 and LV2\n    TopOpeBRep_EdgesIntersector EInter;\n    EInter.SetFaces(F,F);\n    Standard_Real TolDub = 1.e-7;\n    EInter.ForceTolerances(TolDub,TolDub);\n    Standard_Boolean reducesegments = Standard_False;\n    EInter.Perform (E1,E2,reducesegments);\n\n    Standard_Boolean rejectreducedsegmentpoints = Standard_False;\n    EInter.InitPoint(rejectreducedsegmentpoints);\n    for ( ; EInter.MorePoint(); EInter.NextPoint() )\n    {\n      const TopOpeBRep_Point2d& P2D = EInter.Point();\n      const gp_Pnt&    P    = P2D.Value();\n      TopoDS_Vertex    V    = BRepLib_MakeVertex(P);\n\n      //-------------------------\n      // control the point found.\n      //-------------------------\n      gp_Pnt P1 = CE1.Value(P2D.Parameter(1));\n      gp_Pnt P2 = CE2.Value(P2D.Parameter(2));\n      Standard_Real sqd1 = P1.SquareDistance(P);\n      Standard_Real sqd2 = P2.SquareDistance(P);\n      if (sqd1 > MilTol2 || sqd2 > MilTol2  )\n        continue;\n\n      // add a new vertex to the both edges\n      Standard_Real toler = Max( Tol, sqrt( Max( sqd1, sqd2 )));\n      Standard_Integer i;\n      for (i = 1; i <= 2; i++) {\n        Standard_Real U = P2D.Parameter(i);\n        V.Orientation(TopAbs_INTERNAL);\n        B.UpdateVertex( V,U,EI[i], toler);\n        TopAbs_Orientation OO = TopAbs_REVERSED;\n        if (WithOri) {\n          if (P2D.IsVertex(i))\n            OO = P2D.Vertex(i).Orientation();\n          else if (P2D.Transition(i).Before() == TopAbs_OUT) {\n            OO = TopAbs_FORWARD;\n          }\n          V.Orientation(OO);\n          if (i == 1) LV1.Append(V);\n          else        LV2.Append(V);\n        }\n      }\n    }\n  } // if (intersect)\n\n  //----------------------------------\n  // Test the extremities of the edges.\n  //----------------------------------\n  // add to LV* vertices for vertex-vertex closeness\n  Standard_Real U1,U2;\n  Standard_Real TolConf2, TolConf;\n  TopoDS_Vertex V1[2],V2[2];\n  TopExp::Vertices(E1,V1[0],V1[1]);\n  TopExp::Vertices(E2,V2[0],V2[1]);\n\n  Standard_Integer i,j,k;\n  for (j = 0; j < 2; j++) {\n    if (V1[j].IsNull()) continue;\n    for ( k = 0; k < 2; k++) {\n      if (V2[k].IsNull()) continue;\n      gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);\n      gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);\n      TolConf = BRep_Tool::Tolerance(V1[j]) + BRep_Tool::Tolerance(V2[k]);\n      TolConf = Max (Tol, TolConf);\n      TolConf2 = TolConf * TolConf;\n      if (!intersect)\n        TolConf2 *= 100;\n      Standard_Real SqDist = P1.SquareDistance(P2);\n\n      if (SqDist <= TolConf2) {\n        TopoDS_Vertex V = BRepLib_MakeVertex(P1);\n        V.Orientation(TopAbs_INTERNAL);\n        U1 = (j == 0) ? f[1] : l[1];\n        U2 = (k == 0) ? f[2] : l[2];\n        B.UpdateVertex(V,U1,E1,TolConf);\n        B.UpdateVertex(V,U2,E2,TolConf);\n        LV1.Prepend(V.Oriented(V1[j].Orientation()));\n        LV2.Prepend(V.Oriented(V2[k].Orientation()));\n      }\n    }\n  }\n\n  // Standard_Boolean AffichPurge = Standard_False;\n\n  if ( LV1.IsEmpty()) return;\n\n  //----------------------------------\n  // Purge of all the vertices.\n  //----------------------------------\n  // remove one of close vertices\n  TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;\n  gp_Pnt P1,P2;\n  Standard_Boolean Purge = Standard_True;\n\n  while (Purge) {\n    i = 1;\n    Purge = Standard_False;\n    for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2);\n         it1LV1.More();\n         it1LV1.Next(),it1LV2.Next()) {\n      j = 1;\n      it2LV1.Initialize(LV1);\n      while (j < i) {\n        const TopoDS_Vertex& VE1 = TopoDS::Vertex(it1LV1.Value());\n        const TopoDS_Vertex& VE2 = TopoDS::Vertex(it2LV1.Value());\n        Standard_Real Tol1 = BRep_Tool::Tolerance( VE1 );\n        Standard_Real Tol2 = BRep_Tool::Tolerance( VE2 );\n        P1 = BRep_Tool::Pnt( VE1 );\n        P2 = BRep_Tool::Pnt( VE2 );\n        if (P1.IsEqual(P2, Tol1 + Tol2)) {\n          LV1.Remove(it1LV1);\n          LV2.Remove(it1LV2);\n          Purge = Standard_True;\n          break;\n        }\n        j++;\n        it2LV1.Next();\n      }\n      if (Purge) break;\n      i++;\n    }\n  }\n\n  // care of new closed edges, they always intersect with seam at end\n  if (V1[0].IsSame( V1[1] ) && NewEdges.Contains(E1) )\n    treatClosed (E1, f[1], l[1], LV1, LV2);\n  if (V2[0].IsSame( V2[1] ) && NewEdges.Contains(E2) )\n    treatClosed (E2, f[2], l[2], LV2, LV1);\n\n  //----------------\n  // Stocking vertex\n  //----------------\n\n  for ( it1LV1.Initialize( LV1 ); it1LV1.More(); it1LV1.Next())\n    Partition_Inter2d::AddVonE (TopoDS::Vertex( it1LV1.Value()),\n                                E1, E2, AsDes, F);\n}\n\n//=======================================================================\n//function : CompletPart2d\n//purpose  : Computes the intersections between the edges stored\n//           is AsDes as descendants of <F> . Intersections is computed\n//           between two edges if one of them is bound in NewEdges.\n//=======================================================================\n\nvoid Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)&   AsDes,\n                                       const TopoDS_Face&              F,\n                                       const TopTools_MapOfShape&      NewEdges)\n{\n\n#ifdef DEB\n  NbF2d++;\n  NbE2d = 0;\n#endif\n\n  //Do not intersect the edges of a face\n  TopTools_IndexedMapOfShape EdgesOfFace;\n  TopExp::MapShapes( F, TopAbs_EDGE , EdgesOfFace);\n\n  //-------------------------------------------------------------------\n  // compute the intersection2D on the faces touched by the intersection3D\n  //-------------------------------------------------------------------\n  TopTools_ListIteratorOfListOfShape it1LE ;\n  TopTools_ListIteratorOfListOfShape it2LE ;\n\n  //-----------------------------------------------\n  // Intersection edge-edge.\n  //-----------------------------------------------\n  const TopTools_ListOfShape&        LE = AsDes->Descendant(F);\n  TopoDS_Vertex                      V1,V2;\n  Standard_Integer                   j, i = 1;\n\n  TopoDS_Face FF = F;\n  FF.Orientation(TopAbs_FORWARD);\n\n  for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) {\n    const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value());\n    j = 1;\n    it2LE.Initialize(LE);\n\n    while (j < i && it2LE.More()) {\n      const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value());\n      //----------------------------------------------------------\n      // Intersections of the new edges obtained by intersection\n      // between them and with the restrictions edges\n      //----------------------------------------------------------\n      if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) &&\n           (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {\n        EdgesPartition(FF,E1,E2,AsDes,NewEdges,Standard_True);\n      }\n      it2LE.Next();\n      j++;\n    }\n    i++;\n  }\n}\n\n//=======================================================================\n//function : GetTolerance\n//purpose  : Returns  tolerance  theV   must   have  atfer  its\n//           addition to theE with  theU parameter. theAsDes is\n//           used to find pcurves of theE\n//=======================================================================\n\nStandard_Real Partition_Inter2d::GetTolerance\n                         (const TopoDS_Vertex &         theV,\n                          const Standard_Real           theU,\n                          const TopoDS_Edge &           theE,\n                          const Handle(BRepAlgo_AsDes)& theAsDes)\n{\n  Standard_Real aTol = BRep_Tool::Tolerance( theV );\n  gp_Pnt aPnt = BRep_Tool::Pnt( theV );\n\n  // check point on 3D curve\n  Standard_Real f,l;\n  Handle(Geom_Curve) C = BRep_Tool::Curve( theE, f, l );\n  if (!C.IsNull())\n    aTol = Max ( aTol, aPnt.Distance( C->Value( theU )));\n\n  // check points on pcurves\n  const TopTools_ListOfShape& aFList = theAsDes->Ascendant( theE );\n  TopTools_ListIteratorOfListOfShape aFIt( aFList );\n  for (  ; aFIt.More(); aFIt.Next() )\n  {\n    const TopoDS_Face& F = TopoDS::Face( aFIt.Value() );\n    Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( theE, F, f, l );\n    if (!pcurve.IsNull())\n    {\n      gp_Pnt2d aPnt2d = pcurve->Value( theU );\n      TopLoc_Location L;\n      Handle(Geom_Surface) S = BRep_Tool::Surface( F, L );\n      gp_Pnt aPntOnS = S->Value( aPnt2d.X(), aPnt2d.Y() );\n      if (!L.IsIdentity())\n        aPntOnS.Transform( L.Transformation() );\n      aTol = Max ( aTol, aPnt.Distance( aPntOnS ));\n    }\n  }\n\n  return aTol;\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter2d.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter2d.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Inter2d_HeaderFile\n#define _Partition_Inter2d_HeaderFile\n\n#ifndef _Standard_Version_HeaderFile\n   #include <Standard_Version.hxx>\n#endif\n\n#if OCC_VERSION_HEX < 0x070000\n   #ifndef _Handle_BRepAlgo_AsDes_HeaderFile\n      #include <Handle_BRepAlgo_AsDes.hxx>\n   #endif\n#else\n   #include <BRepAlgo_AsDes.hxx>\n   #include <TopTools_MapOfShape.hxx>\n#endif\n\n#ifndef _Standard_Real_HeaderFile\n#include <Standard_Real.hxx>\n#endif\n#ifndef _Standard_Boolean_HeaderFile\n#include <Standard_Boolean.hxx>\n#endif\nclass BRepAlgo_AsDes;\nclass TopoDS_Face;\n\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_MapOfShape;\n   class TopTools_ListOfShape;\n#endif\n\nclass TopoDS_Vertex;\nclass TopoDS_Edge;\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Inter2d  {\n\npublic:\n\n   void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   // Methods PUBLIC\n   // \n   static  void CompletPart2d(const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F,const TopTools_MapOfShape& NewEdges) ;\n   static  TopoDS_Vertex FindEndVertex(const TopTools_ListOfShape& VertList,const Standard_Real f,const Standard_Real l,const TopoDS_Edge& E,Standard_Boolean& First,Standard_Real& DU) ;\n   static  TopoDS_Vertex AddVonE(const TopoDS_Vertex& V,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F) ;\n   static  Standard_Real GetTolerance(const TopoDS_Vertex& theV,const Standard_Real theU,const TopoDS_Edge& theE,const Handle(BRepAlgo_AsDes)& theAsDes) ;\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n\n\n   // Fields PRIVATE\n   //\n\n\n};\n\n\n\n\n\n// other Inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter2d.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter2d.ixx\n//  Module : GEOM\n\n#include <climits>\n#include \"Partition_Inter2d.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter2d.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter2d.jxx\n//  Module : GEOM\n\n#include <mystdlib.h>  // netgen headers\n\n\n#ifndef _BRepAlgo_AsDes_HeaderFile\n#include <BRepAlgo_AsDes.hxx>\n#endif\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopTools_MapOfShape_HeaderFile\n#include <TopTools_MapOfShape.hxx>\n#endif\n#ifndef _TopoDS_Vertex_HeaderFile\n#include <TopoDS_Vertex.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _Partition_Inter2d_HeaderFile\n#include \"Partition_Inter2d.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter3d.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter3d.cxx\n//  Author : Benedicte MARTIN\n//  Module : GEOM\n//  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter3d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $\n\n//using namespace std;\n#include <climits>\n\n#include \"Partition_Inter2d.hxx\"\n#include \"Partition_Inter3d.ixx\"\n#include \"utilities.h\"\n\n#include <BRepAlgo_AsDes.hxx>\n#include <BRepAlgo_Image.hxx>\n#include <BRepLib.hxx>\n#include <BRepOffset_Tool.hxx>\n#include <BRep_Builder.hxx>\n#include <BRep_Tool.hxx>\n\n#include <TopExp.hxx>\n#include <TopExp_Explorer.hxx>\n\n#include <TopOpeBRepTool_BoxSort.hxx>\n#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopTools_ListOfShape.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Compound.hxx>\n#include <TopoDS_Edge.hxx>\n#include <TopoDS_Face.hxx>\n#include <TopoDS_Vertex.hxx>\n\n#ifdef DEB\n#include <DBRep.hxx>\n#endif\n\n#include <BRepLib_MakeVertex.hxx>\n#include <BRepTools.hxx>\n#include <Extrema_ExtPS.hxx>\n#include <Extrema_POnSurf.hxx>\n#include <Geom2dAPI_ProjectPointOnCurve.hxx>\n#include <Geom2d_Curve.hxx>\n#include <GeomAPI_ProjectPointOnCurve.hxx>\n#include <GeomAdaptor_Surface.hxx>\n#include <Geom_Curve.hxx>\n#include <Geom_RectangularTrimmedSurface.hxx>\n#include <Geom_SphericalSurface.hxx>\n#include <Geom_Surface.hxx>\n#include <Geom_TrimmedCurve.hxx>\n#include <Precision.hxx>\n#include <TColStd_MapOfInteger.hxx>\n#include <TopOpeBRepBuild_Builder.hxx>\n#include <TopOpeBRepDS_BuildTool.hxx>\n#include <TopOpeBRepDS_CurveExplorer.hxx>\n#include <TopOpeBRepDS_HDataStructure.hxx>\n#include <TopOpeBRepDS_Interference.hxx>\n#include <TopOpeBRepDS_PointIterator.hxx>\n#include <TopOpeBRepDS_Transition.hxx>\n#include <TopOpeBRepTool_CurveTool.hxx>\n#include <TopOpeBRepTool_GeomTool.hxx>\n#include <TopOpeBRepTool_OutCurveType.hxx>\n#include <TopOpeBRep_DSFiller.hxx>\n#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>\n#include <stdio.h>\n\n//=======================================================================\n//function : Partition_Inter3d\n//purpose  : \n//=======================================================================\n\nPartition_Inter3d::Partition_Inter3d()\n{\n}\n//=======================================================================\n//function : Partition_Inter3d\n//purpose  : \n//=======================================================================\n\nPartition_Inter3d::Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes)\n  :myAsDes(AsDes)\n{\n  mySectionEdgesAD = new BRepAlgo_AsDes;\n}\n\n//=======================================================================\n//function : CompletPart3d\n//purpose  : FaceShapeMap is just to know the shape a face belongs to\n//=======================================================================\n\nvoid Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1,\n\t\t\t\t      const TopTools_DataMapOfShapeShape& FaceShapeMap)\n{\n  if (myAsDes.IsNull())\n    myAsDes = new BRepAlgo_AsDes;\n  \n  TopTools_ListIteratorOfListOfShape it;\n\n  //---------------------------------------------------------------\n  // Construction of bounding boxes.\n  //---------------------------------------------------------------\n\n  BRep_Builder B;\n  TopoDS_Compound CompOS;\n  B.MakeCompound(CompOS);\n  for (it.Initialize(SetOfFaces1); it.More(); it.Next())\n    B.Add(CompOS, it.Value());\n    \n  TopOpeBRepTool_BoxSort BOS;\n  BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE);\n\n  for (it.Initialize(SetOfFaces1); it.More(); it.Next()) {\n    TopoDS_Face F1 = TopoDS::Face(it.Value());\n    \n    // avoid intersecting faces of one shape\n    TopoDS_Shape S1;\n    if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1);\n\n    // to filter faces sharing an edge\n    TopTools_IndexedMapOfShape EM;\n    TopExp::MapShapes( F1, TopAbs_EDGE, EM);\n    \n    TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1);\n    for (; itLI.More(); itLI.Next()) {\n      TopoDS_Face F2 = TopoDS::Face(BOS.TouchedShape(itLI));\n      if (F1.IsSame(F2) || IsDone(F1,F2))\n\tcontinue;\n\n      TopoDS_Shape S2;\n      if (FaceShapeMap.IsBound(F2)) S2 = FaceShapeMap.Find(F2);\n      if (!S1.IsNull() && S1.IsSame(S2))\n\tcontinue; // descendants of one shape\n\n      TopExp_Explorer expE (F2, TopAbs_EDGE);\n      for ( ; expE.More(); expE.Next())\n\tif (EM.Contains( expE.Current() ))\n\t  break;\n      if (expE.More())\n      {\n        // faces have a common edge, check if they are a tool and a face\n        // generated by the tool in another shape; in that case they are\n        // to be intersected\n        TopLoc_Location L1, L2;\n        Handle(Geom_Surface) S1 = BRep_Tool::Surface( F1, L1 );\n        Handle(Geom_Surface) S2 = BRep_Tool::Surface( F2, L2 );\n        if ( S1 != S2 || L1 != L2 )\n          continue;\n      }\n\n      F1.Orientation(TopAbs_FORWARD);\n      F2.Orientation(TopAbs_FORWARD);\n      FacesPartition(F1,F2);\t  \n    }\n\n    // mark as modified a face which has at least one new edge\n    if (!myAsDes->HasDescendant( F1 ))\n      continue;\n    TopTools_ListIteratorOfListOfShape itE (myAsDes->Descendant( F1 ));\n    for ( ; itE.More(); itE.Next()) {\n      if (myNewEdges.Contains( itE.Value())) {\n\tmyTouched.Add( F1 );\n\tbreak;\n      }\n    }\n  }\n}\n\n//=======================================================================\n//function : PutInBounds\n//purpose  : \n//=======================================================================\n\nstatic void PutInBounds (const TopoDS_Face&          F,\n\t\t\t const TopoDS_Edge&          E,\n\t\t\t Handle(Geom2d_Curve)&       C2d)\n{\n  Standard_Real   umin,umax,vmin,vmax;\n  Standard_Real   f,l;\n  BRep_Tool::Range(E,f,l);\n\n  TopLoc_Location L; // Recup S avec la location pour eviter la copie.\n  Handle (Geom_Surface) S   = BRep_Tool::Surface(F,L);\n\n  if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {\n    S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();\n  }\n  if (!S->IsUPeriodic() && !S->IsVPeriodic())\n    return;\n\n  BRepTools::UVBounds(F,umin,umax,vmin,vmax);\n\n  gp_Pnt2d Pf = C2d->Value(f);\n  gp_Pnt2d Pl = C2d->Value(l);\n  const Standard_Real Um = 0.34*f + 0.66*l;\n  gp_Pnt2d Pm = C2d->Value( Um );\n\n  // sometimes on sphere, pcurve is out of domain by V though S is\n  // UPeriodic, sometimes it is in domain but nonetheless it has\n  // wrong position.\n  // Check pcurve position by 3D point\n  if (S->IsKind(STANDARD_TYPE( Geom_SphericalSurface )))\n  {\n    // get point on the surface\n    gp_Pnt Ps = S->Value( Pm.X(), Pm.Y() );\n    // get point on the edge\n    Handle(Geom_Curve) C = BRep_Tool::Curve( E, f, l );\n    gp_Pnt Pc = C->Value( Um );\n    // compare points\n    Standard_Real TolE = BRep_Tool::Tolerance( E );\n    if ( Pc.SquareDistance( Ps ) * 0.95 < TolE * TolE )\n      return; // OK\n\n    // find good UV for Pc: project Pc on S\n    GeomAdaptor_Surface  SA (S);\n    Extrema_ExtPS anExtPS (Pc, SA,\n                           SA.UResolution( TolE ), SA.VResolution( TolE ));\n    if (anExtPS.IsDone())\n    {\n      Standard_Integer i, nbExt = anExtPS.NbExt();\n      Extrema_POnSurf aPOnSurf;\n      for (i = 1; i <= nbExt; ++i )\n\t  // if (anExtPS.Value( i ) <= TolE)               // V6.3\n\t  if (anExtPS.SquareDistance( i ) <= TolE)   // V6.5\n\t  {\n          aPOnSurf = anExtPS.Point( i );\n          break;\n        }\n      if (i <= nbExt) {\n        // a point found\n        Standard_Real u, v;\n        aPOnSurf.Parameter( u, v );\n        gp_Pnt2d aGoodPm ( u, v );\n        C2d->Translate( Pm , aGoodPm );\n      }\n    }\n  }\n\n  //---------------\n  // Recadre en U.\n  //---------------\n  if (S->IsUPeriodic()) {\n    Standard_Real period  = S->UPeriod();\n    Standard_Real eps     = period*1.e-6;\n    Standard_Real minC    = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());\n    Standard_Real maxC    = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());\n    Standard_Real du = 0.;\n    if (minC< umin - eps) {\n      du = (int((umin - minC)/period) + 1)*period;\n    }\n    if (minC > umax + eps) {\n      du = -(int((minC - umax)/period) + 1)*period;\n    }\n    if (du != 0) {\n      gp_Vec2d T1(du,0.);\n      C2d->Translate(T1);\n      minC += du; maxC += du;\n    }\n    // Ajuste au mieux la courbe dans le domaine.\n    if (maxC > umax +100*eps) {\n      Standard_Real d1 = maxC - umax;\n      Standard_Real d2 = umin - minC + period;\n      if (d2 < d1) du =-period;\n      if ( du != 0.) {\n\tgp_Vec2d T2(du,0.);\n\tC2d->Translate(T2);\n      }\n    }\n  }\n  //------------------\n  // Recadre en V.\n  //------------------\n  if (S->IsVPeriodic()) {\n    Standard_Real period  = S->VPeriod();\n    Standard_Real eps     = period*1.e-6;\n    Standard_Real minC    = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());\n    Standard_Real maxC    = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());\n    Standard_Real dv = 0.;\n    if (minC< vmin - eps) {\n      dv = (int((vmin - minC)/period) + 1)*period;\n    }\n    if (minC > vmax + eps) {\n      dv = -(int((minC - vmax)/period) + 1)*period;\n    }\n    if (dv != 0) {\n      gp_Vec2d T1(0.,dv);\n      C2d->Translate(T1);\n      minC += dv; maxC += dv;\n    }\n    // Ajuste au mieux la courbe dans le domaine.\n    if (maxC > vmax +100*eps) {\n      Standard_Real d1 = maxC - vmax;\n      Standard_Real d2 = vmin - minC + period;\n      if (d2 < d1) dv =-period;\n      if ( dv != 0.) {\n\tgp_Vec2d T2(0.,dv);\n\tC2d->Translate(T2);\n      }\n    }\n  }\n}\n\n//=======================================================================\n//function : Inter3D\n//purpose  : \n//=======================================================================\n\nvoid Partition_Inter3d::Inter3D(const TopoDS_Face& F1,\n\t\t\t\tconst TopoDS_Face& F2,\n\t\t\t\tTopTools_ListOfShape& L)\n{\n  BRep_Builder B;\n  \n  // fill the data Structure\n  Handle(TopOpeBRepDS_HDataStructure) DatStr = new TopOpeBRepDS_HDataStructure();\n  TopOpeBRep_DSFiller DSFiller;\n  DSFiller.Insert(F1,F2,DatStr);\n\n  // define the GeomTool used by the DSFiller :\n  // compute BSpline of degree 1 on intersection curves.\n  Standard_Real tol3dAPPROX = 1e-7;\n  Standard_Real tol2dAPPROX = 1e-7;\n  TopOpeBRepTool_GeomTool GT2 (TopOpeBRepTool_APPROX);  \n  GT2.SetTolerances(tol3dAPPROX,tol2dAPPROX);\n  TopOpeBRepDS_BuildTool  BT(GT2);\n\n  // Perform Section\n  TopOpeBRepBuild_Builder TopB(BT);\n  TopB.Perform(DatStr);\n\n  // ===============\n  // Store new edges\n  // ===============\n  \n  L.Clear();\n  TopOpeBRepDS_CurveExplorer cex(DatStr->DS());\n  for (; cex.More(); cex.Next()) {\n    const TopOpeBRepDS_Curve& CDS = cex.Curve();\n    Standard_Integer ic = cex.Index();\n    Handle(Geom2d_Curve) pc1 = CDS.Curve1();\n    Handle(Geom2d_Curve) pc2 = CDS.Curve2();\n    \n    TopTools_ListIteratorOfListOfShape itLE = TopB.NewEdges(ic);\n    while (itLE.More()) {\n      TopoDS_Edge E = TopoDS::Edge(itLE.Value());\n      \n      PutInBounds (F1,E,pc1);\n      PutInBounds (F2,E,pc2);\n      \n      B.UpdateEdge (E,pc1,F1,0.);\n      B.UpdateEdge (E,pc2,F2,0.);\n      \n      L.Append (E);\n      \n      itLE.Next();\n      if (itLE.More()) {\n\tpc1 = Handle(Geom2d_Curve)::DownCast(pc1->Copy());\n\tpc2 = Handle(Geom2d_Curve)::DownCast(pc2->Copy());\n      }\n    }\n  }\n\n  // ========================\n  // store same domain faces \n  // ========================\n\n\n  if ( DatStr->HasSameDomain( F1 ))\n  {\n    TopTools_ListOfShape emptyList;\n    if (!mySameDomainFM.IsBound(F1))\n      mySameDomainFM.Bind(F1,emptyList);\n    if (!mySameDomainFM.IsBound(F2))\n      mySameDomainFM.Bind(F2,emptyList);\n    mySameDomainFM(F1).Append(F2);\n    mySameDomainFM(F2).Append(F1);\n  }\n\n  // ====================\n  // Store section edges\n  // ====================\n\n  const TopOpeBRepDS_DataStructure& DS = DatStr->DS();\n  Standard_Integer j,i,nse = DS.NbSectionEdges();\n  if (nse == 0) return;\n\n    \n  TopoDS_Vertex V, sdeV1, sdeV2;\n  TopTools_MapOfShape MV;\n  TopTools_ListOfShape LSE; // list of section edges\n  TopoDS_Face dummyF;\n  \n  for (i = 1; i <= nse; i++)\n  {\n    const TopoDS_Edge & se = DS.SectionEdge(i);\n    if (! TopB.IsSplit(se,TopAbs_ON))\n      continue;\n    LSE.Append( se );\n\n    // add vertices where section edges interferes with other\n    // edges as its descendant in myAsDes\n    \n    TopoDS_Edge sde, oe; // same domain, other edge\n    if (DatStr->HasSameDomain(se)) {\n      sde = TopoDS::Edge( DatStr->SameDomain(se).Value() );\n      TopExp::Vertices( sde, sdeV1, sdeV2);\n    }\n    TColStd_MapOfInteger MIV; // indices of added edges\n    TopOpeBRepDS_PointIterator itP (DS.ShapeInterferences( se ));\n    itP.SupportKind( TopOpeBRepDS_EDGE );\n    // loop on intersections of se\n    for (; itP.More(); itP.Next()) {\n      oe = TopoDS::Edge( DS.Shape( itP.Support()));\n      if (itP.IsVertex()) {\n        // there is a vertex at intersection\n\tif ( !MIV.Add( itP.Current() ))\n\t  continue;\n\tV = TopoDS::Vertex( DS.Shape( itP.Current()));\n\tif ( !sde.IsNull() && (V.IsSame(sdeV1) || V.IsSame(sdeV2)) )\n\t  oe = sde;\n\tV = ReplaceSameDomainV( V , oe );\n\tV.Orientation( TopAbs_INTERNAL);\n\tB.UpdateVertex( V, itP.Parameter(), se, 0.); // AddVonE() sets real U\n      }\n      else {\n        // create a new vertex at the intersection point\n\tconst TopOpeBRepDS_Point& DSP = DS.Point( itP.Current());\n\tV = BRepLib_MakeVertex( DSP.Point() );\n\tV.Orientation( TopAbs_INTERNAL);\n\tB.UpdateVertex( V, itP.Parameter(), se, DSP.Tolerance());\n\t// make V be on the other edge\n\tTopOpeBRepDS_PointIterator itOP (DS.ShapeInterferences( oe ));\n\tfor (; itOP.More(); itOP.Next()) {\n\t  const TopOpeBRepDS_Point& ODSP = DS.Point( itOP.Current());\n\t  if ( DSP.IsEqual (ODSP)) {\n\t    B.UpdateVertex( V, itOP.Parameter(), TopoDS::Edge(oe), ODSP.Tolerance());\n\t    break;\n\t  }\n\t}\n      }\n      // add V on the both intersecting edges\n      TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes,dummyF);\n      if (!addedV.IsSame( V ))\n\tmySameDomainVM.Bind (V, addedV); // equal vertex is already there\n\n      MV.Add( addedV ); // to ease storage of vertices of ON splits\n    }\n  }\n\n  // add section edge to the face it intersects and find\n  // splits ON that do not have same domain pair\n  \n  TopB.SplitSectionEdges(); // let TopB find ON splits\n\n  TopTools_MapOfShape SPM; // map of ON splits\n  TopTools_IndexedMapOfShape ME[2];\n  TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]);\n  TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]);\n\n  TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE);\n  while ( itLSE.More() ) {\n\n    TopoDS_Edge se = TopoDS::Edge( itLSE.Value() );\n\n    // move itLSE to the next se\n    Standard_Integer ancRank = DS.AncestorRank(se);\n    if (ME[ancRank-1].Contains( se ))\n    {\n      LSE.Remove( itLSE ); // se is an edge of face it intersects\n      continue;\n    }\n    else\n    {\n      itLSE.Next();\n    }\n\n    const TopoDS_Face& F = (ancRank == 1) ? F2 : F1;\n\n    // add se to face but don't add twice\n    TopTools_ListIteratorOfListOfShape itE( myAsDes->Descendant( F ));\n    if (myAsDes->HasDescendant( F )) {\n      for ( ; itE.More(); itE.Next())\n\tif (se.IsSame( itE.Value() ))\n\t  break;\n    }\n    if (!itE.More())\n    {\n      myAsDes->Add( F, se );\n\n      // check se pcurve on F\n      Standard_Real tol, f,l, umin=1e100, umax=-1e100;\n      Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( se, F, f,l);\n      if (pc.IsNull()) {\n\titSP.Initialize( TopB.Splits(se,TopAbs_ON) );\n\tfor ( ; itSP.More(); itSP.Next()) {\n\t  const TopoDS_Edge& E = TopoDS::Edge ( itSP.Value());\n\t  BRep_Tool::Range(E, f, l);\n\t  umin = Min( umin, f);\n\t  umax = Max( umax, l);\n\t}\n\tHandle(Geom_Curve) C3d = BRep_Tool::Curve( se, f, l);\n\tif (umin < umax) // sometimes umin == umax for closed edge\n\t  C3d = new Geom_TrimmedCurve( C3d, umin, umax);\n\tpc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol);\n\tif (pc.IsNull()) {\n\t  MESSAGE (\" CANNOT BUILD PCURVE \");\n\t}\n\tB.UpdateEdge( se, pc, F, tol);\n      }\n    }\n\n    // to detect splits that do not have same domain pair\n    // ie which split a face into parts and not pass by its boundary\n    itSP.Initialize( TopB.Splits(se,TopAbs_ON) );\n    for ( ; itSP.More(); itSP.Next()) {\n      const TopoDS_Shape& SP = itSP.Value();\n      if (!SPM.Add( SP ))\n\tSPM.Remove( SP );\n    }\n  }\n\n  // store vertices of ON splits and bind section edges to faces\n  \n  for (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next())\n  {\n    const TopoDS_Shape& se = itLSE.Value();\n\n    Standard_Integer ancRank = DS.AncestorRank(se);\n    TopoDS_Face F = (ancRank == 1) ? F2 : F1;\n\n    // add vertices of ON splits which have no same domain pair\n    Standard_Boolean added = Standard_False;\n    itSP.Initialize( TopB.Splits(se,TopAbs_ON) );\n    for ( ; itSP.More(); itSP.Next())\n    {\n      if (!SPM.Contains( itSP.Value() ))\n\tcontinue;\n      \n      const TopoDS_Edge& S = TopoDS::Edge ( itSP.Value());\n\n      added = Standard_True;\n      mySectionEdgesAD->Add( F, se );\n      \n      TopoDS_Vertex VS[2];\n      TopExp::Vertices (S, VS[0], VS[1]);\n      for (j=0; j<2; ++j)\n      {\n\tif (mySameDomainVM.IsBound( VS[j] ))\n\t  VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] ));\n\tif ( !MV.Contains( VS[j] )) {\n\t  // find equal vertex on se - point interference\n\t  gp_Pnt P1 = BRep_Tool::Pnt( VS[j] );\n\t  TopTools_ListIteratorOfListOfShape itV( myAsDes->Descendant(se) );\n\t  for (; itV.More(); itV.Next()) {\n\t    V = TopoDS::Vertex( itV.Value() );\n            if ( V.IsSame( VS[j] ))\n              break;\n\t    gp_Pnt P2 = BRep_Tool::Pnt( V );\n\t    if (P1.IsEqual( P2, Precision::Confusion())) {\n\t      mySameDomainVM.Bind (VS[j], V);\n\t      VS[j] = V;\n\t      break;\n\t    }\n\t  }\n\t  if (!itV.More())  // no interferences with edges\n\t    myAsDes->Add( se, VS[j]);\n\t}\n\n        // add ends of ON splits to F in order to detect later\n        // if a split is on face in IsSplitOn()\n\tmySectionEdgesAD->Add( F, VS[j]);\n      }\n      // in the descendants of F, first go ends of an ON split and\n      // then a split itself\n      mySectionEdgesAD->Add( F, S );\n    }\n    if (!added)\n      mySectionEdgesAD->Add( F, se );\n    \n    myNewEdges.Add( se );\n  }\n}\n\n//=======================================================================\n//function : FacesPartition\n//purpose  : \n//=======================================================================\n\nvoid Partition_Inter3d::FacesPartition(const TopoDS_Face& F1,\n\t\t\t\t       const TopoDS_Face& F2)\n     //(const TopTools_DataMapOfShapeListOfShape& /*SetOfFaces2*/)\n{\n  TopTools_ListOfShape LInt;\n\n  Inter3D (F1,F2,LInt);\n  \n  StorePart3d (F1,F2,LInt);\n}\n\n//=======================================================================\n//function : SetDone\n//purpose  : \n//=======================================================================\n\nvoid Partition_Inter3d::SetDone(const TopoDS_Face& F1, \n\t\t\t\tconst TopoDS_Face& F2)\n{\n  if (!myDone.IsBound(F1)) {\n    TopTools_ListOfShape emptyList;\n    myDone.Bind(F1,emptyList);\n  }\n  myDone(F1).Append(F2);\n  if (!myDone.IsBound(F2)) {\n    TopTools_ListOfShape emptyList;\n    myDone.Bind(F2,emptyList);\n  }\n  myDone(F2).Append(F1);\n}\n\n//=======================================================================\n//function : IsDone\n//purpose  : \n//=======================================================================\n\nStandard_Boolean Partition_Inter3d::IsDone(const TopoDS_Face& F1, \n\t\t\t\t\t   const TopoDS_Face& F2) \n\n  const \n{\n  if (myDone.IsBound(F1)) {\n    TopTools_ListIteratorOfListOfShape it (myDone(F1));\n    for (; it.More(); it.Next()) {\n      if (it.Value().IsSame(F2)) return Standard_True;\n    }\n  }\n  return Standard_False;\n}\n\n//=======================================================================\n//function : StorePart3d\n//purpose  : \n//=======================================================================\n\nvoid Partition_Inter3d::StorePart3d(const TopoDS_Face& F1, \n\t\t\t\t    const TopoDS_Face& F2, \n\t\t\t\t    const TopTools_ListOfShape& LInt)\n{\n  if (!LInt.IsEmpty()) {\n    myAsDes->Add( F1,LInt);\n    myAsDes->Add( F2,LInt);\n\n    TopTools_ListIteratorOfListOfShape it(LInt);\n    for (; it.More(); it.Next()) {\n\n      TopoDS_Edge E = TopoDS::Edge(it.Value());\n\n      BRep_Builder B;\n      B.SameParameter(E,Standard_False);\n      BRepLib::SameParameter(E,1.0e-7);\n      \n      myNewEdges.Add(E);\n    }\n  }\n  SetDone(F1,F2);\n}\n\n//=======================================================================\n//function : TouchedFaces\n//purpose  : \n//=======================================================================\n\nTopTools_MapOfShape& Partition_Inter3d::TouchedFaces()\n{\n  return myTouched;\n}\n\n//=======================================================================\n//function : AsDes\n//purpose  : \n//=======================================================================\n\nHandle(BRepAlgo_AsDes) Partition_Inter3d::AsDes() const\n{\n  return myAsDes;\n}\n\n//=======================================================================\n//function : NewEdges\n//purpose  : \n//=======================================================================\n\nTopTools_MapOfShape& Partition_Inter3d::NewEdges() \n{\n  return myNewEdges;\n}\n\n//=======================================================================\n//function : Affiche\n//purpose  : \n//=======================================================================\n\nvoid Partition_Inter3d::Affiche(const TopTools_ListOfShape& SetOfFaces) const\n{\n#ifdef DEB\n  char PSection[1024];\n  char *section=PSection;\n  Standard_Integer i = 0;\n  Standard_Real j=1;\n  TopTools_ListOfShape aList;\n  TopTools_ListIteratorOfListOfShape it;\n  for (it.Initialize(SetOfFaces); it.More(); it.Next()) {\n    const TopoDS_Shape& OS = it.Value();\n    aList=myAsDes->Descendant(OS);\n    MESSAGE ( \" the number of items stored in the list \" << j << \" :  \" << aList.Extent() )\n    j++;\n    TopTools_ListIteratorOfListOfShape itaList;\n    for (itaList.Initialize(aList); itaList.More(); itaList.Next()) {\n      const TopoDS_Shape& SS = itaList.Value();\n      i++;\n      sprintf(PSection,\"section_%d\",i);\n      DBRep::Set(section,SS);  \n    }\n  }\n#endif\n}\n\n//=======================================================================\n//function : SameDomain\n//purpose  : \n//=======================================================================\n\nconst TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) const\n{\n  if (mySameDomainFM.IsBound( F ))\n    return mySameDomainFM (F);\n\n  static TopTools_ListOfShape emptyList;\n  return emptyList;\n}\n\n//=======================================================================\n//function : HasSameDomainF\n//purpose  : Return true if F has same domain faces\n//=======================================================================\n\nStandard_Boolean Partition_Inter3d::HasSameDomainF(const TopoDS_Shape& F) const\n{\n  return mySameDomainFM.IsBound( F );\n}\n\n//=======================================================================\n//function : IsSameDomain\n//purpose  : Return true if F1 and F2 are same domain faces\n//=======================================================================\n\nStandard_Boolean Partition_Inter3d::IsSameDomainF(const TopoDS_Shape& F1,\n\t\t\t\t\t\t const TopoDS_Shape& F2) const\n{\n  if (mySameDomainFM.IsBound( F1 )) {\n    TopTools_ListIteratorOfListOfShape it (mySameDomainFM( F1 ));\n    for (; it.More(); it.Next()) \n      if (F2.IsSame( it.Value()))\n\treturn Standard_True;\n  }\n  return F1.IsSame( F2 );\n}\n\n//=======================================================================\n//function : ReplaceSameDomainV\n//purpose  : return same domain vertex of  V if it was replaced\n//           and make this vertex to be on E too, else return V\n//=======================================================================\n\nTopoDS_Vertex Partition_Inter3d::ReplaceSameDomainV(const TopoDS_Vertex& V,\n\t\t\t\t\t\t    const TopoDS_Edge&   E) const\n{\n  TopoDS_Vertex SDV = V;\n  if (mySameDomainVM.IsBound( V )) {\n\n    TopoDS_Vertex V1,V2;\n    TopExp::Vertices(E,V1,V2);\n    Standard_Boolean isClosed = V1.IsSame( V2 ) && V.IsSame(V1);\n\n    SDV = TopoDS::Vertex( mySameDomainVM(V) );\n    Standard_Real tol = BRep_Tool::Tolerance( V );\n    BRep_Builder B;\n    SDV.Orientation( V.Orientation());\n\n    if (isClosed) {\n      Standard_Real f, l;\n      BRep_Tool::Range (E, f, l);\n      Standard_Boolean isFirst = IsEqual( BRep_Tool::Parameter(V,E), f );\n      B.UpdateVertex(SDV, (isFirst ? f : l), E, tol);\n      SDV.Reverse();\n      B.UpdateVertex(SDV, (isFirst ? l : f), E, tol);\n    }\n    else\n      B.UpdateVertex (SDV, BRep_Tool::Parameter(V,E), E, tol);\n      \n  }\n  return SDV;\n}\n\n//=======================================================================\n//function : SectionEdgesAD\n//purpose  : \n//=======================================================================\n\nHandle(BRepAlgo_AsDes) Partition_Inter3d::SectionEdgesAD() const\n{\n  return mySectionEdgesAD;\n}\n\n//=======================================================================\n//function : IsSectionEdge\n//purpose  : return True if  E  is  an  edge  of  a face and it\n//           intersects an other face\n//=======================================================================\n\nStandard_Boolean\n  Partition_Inter3d::IsSectionEdge(const TopoDS_Edge& E) const\n{\n  return mySectionEdgesAD->HasAscendant(E);\n}\n\n//=======================================================================\n//function : HasSectionEdge\n//purpose  : return True if an  edge  of  F intersects an other\n//           face or F is intersected by edge of an other face\n//=======================================================================\n\nStandard_Boolean\n  Partition_Inter3d::HasSectionEdge(const TopoDS_Face& F) const\n{\n  return mySectionEdgesAD->HasDescendant(F);\n}\n\n//=======================================================================\n//function : IsSplitOn\n//purpose  : return True if NewE is split of OldE on F\n//=======================================================================\n\nStandard_Boolean\n  Partition_Inter3d::IsSplitOn(const TopoDS_Edge& NewE,\n\t\t\t       const TopoDS_Edge& OldE,\n\t\t\t       const TopoDS_Face& F) const\n{\n  if (! mySectionEdgesAD->HasDescendant(F))\n    return Standard_False;\n\n  TopTools_ListIteratorOfListOfShape itE ( mySectionEdgesAD->Descendant(F) );\n  for ( ; itE.More(); itE.Next()) {\n    if ( itE.Value().ShapeType() != TopAbs_EDGE ||\n\t! OldE.IsSame ( itE.Value() ))\n      continue;\n    // an edge encountered, its vertices and a split come next\n    itE.Next();\n    if (!itE.More()) break;\n    const TopoDS_Shape& V3 = itE.Value();\n    if (V3.ShapeType() != TopAbs_VERTEX) continue;\n    itE.Next();\n    if (!itE.More()) break;\n    const TopoDS_Shape& V4 = itE.Value();\n    if (V4.ShapeType() != TopAbs_VERTEX) continue;\n\n    TopoDS_Vertex V1, V2;\n    TopExp::Vertices( OldE, V1, V2);\n    \n    if ( V1.IsSame(V2) &&\n\t(V1.IsSame(V3) || V1.IsSame(V4)) ) {\n      // closed old edge; use the split for the test \n      itE.Next();\n      if (!itE.More()) break;\n      const TopoDS_Edge& split = TopoDS::Edge( itE.Value() );\n      // check distance at middle point of NewE\n      Standard_Real f1,l1, f2,l2;\n      Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface( split, F ,f1,l1);\n      if (!PC1.IsNull()) {\n\tHandle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(NewE, F ,f2,l2);\n\tgp_Pnt2d P = PC2->Value( 0.5*(f2+l2) );\n\tGeom2dAPI_ProjectPointOnCurve proj (P, PC1, f1, l1);\n\tif (proj.NbPoints() &&\n\t    proj.LowerDistance() <= Precision::Confusion())\n\t  return Standard_True;\n      }\n      else {\n        Handle(Geom_Curve) C1 = BRep_Tool::Curve( split ,f1,l1);\n\tHandle(Geom_Curve) C2 = BRep_Tool::Curve( NewE  ,f2,l2);\n\tgp_Pnt P = C2->Value( 0.5*(f2+l2) );\n\tGeomAPI_ProjectPointOnCurve proj (P, C1, f1, l1);\n\tif (proj.NbPoints() &&\n\t    proj.LowerDistance() <= Precision::Confusion())\n\t  return Standard_True;\n      }\n    }\n    else {\n      Standard_Real u3 = BRep_Tool::Parameter( TopoDS::Vertex(V3), OldE);\n      Standard_Real u4 = BRep_Tool::Parameter( TopoDS::Vertex(V4), OldE);\n\n      Standard_Real f,l, u;\n      BRep_Tool::Range( NewE, f,l);\n      u = 0.5*(f+l);\n      f = Min(u3,u4);\n      l = Max(u3,u4);\n\n      if (u <= l && u >= f)\n        return Standard_True;\n    }\n  }\n  return Standard_False;\n}\n\n//=======================================================================\n//function : SectionEdgeFaces\n//purpose  : return faces cut by section edge\n//=======================================================================\n\nconst TopTools_ListOfShape&\n  Partition_Inter3d::SectionEdgeFaces(const TopoDS_Edge& SecE) const\n{\n  return mySectionEdgesAD->Ascendant( SecE );\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter3d.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter3d.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Inter3d_HeaderFile\n#define _Partition_Inter3d_HeaderFile\n\n#ifndef _Standard_Version_HeaderFile\n#include <Standard_Version.hxx>\n#endif\n\n#if OCC_VERSION_HEX < 0x070000\n   #ifndef _Handle_BRepAlgo_AsDes_HeaderFile\n      #include <Handle_BRepAlgo_AsDes.hxx>\n   #endif\n#else\n   #include <BRepAlgo_AsDes.hxx>\n   #include <TopTools_DataMapOfShapeShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile\n#include <TopTools_DataMapOfShapeListOfShape.hxx>\n#endif\n#ifndef _TopTools_MapOfShape_HeaderFile\n#include <TopTools_MapOfShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeShape_HeaderFile\n#include <TopTools_DataMapOfShapeShape.hxx>\n#endif\n#ifndef _Standard_Boolean_HeaderFile\n#include <Standard_Boolean.hxx>\n#endif\n\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_ListOfShape;\n   class TopTools_DataMapOfShapeShape;\n   class TopTools_MapOfShape;\n#endif\n\nclass BRepAlgo_AsDes;\nclass TopoDS_Face;\nclass TopoDS_Shape;\nclass TopoDS_Vertex;\nclass TopoDS_Edge;\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Inter3d  {\n\npublic:\n\n   void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   // Methods PUBLIC\n   // \n   Partition_Inter3d();\n   Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes);\n   void CompletPart3d(const TopTools_ListOfShape& SetOfFaces1,const TopTools_DataMapOfShapeShape& FaceShapeMap) ;\n   void FacesPartition(const TopoDS_Face& F1,const TopoDS_Face& F2) ;\n   Standard_Boolean IsDone(const TopoDS_Face& F1,const TopoDS_Face& F2) const;\n   TopTools_MapOfShape& TouchedFaces() ;\n   Handle(BRepAlgo_AsDes) AsDes() const;\n   TopTools_MapOfShape& NewEdges() ;\n   Standard_Boolean HasSameDomainF(const TopoDS_Shape& F) const;\n   Standard_Boolean IsSameDomainF(const TopoDS_Shape& F1,const TopoDS_Shape& F2) const;\n   const TopTools_ListOfShape& SameDomain(const TopoDS_Face& F) const;\n   TopoDS_Vertex ReplaceSameDomainV(const TopoDS_Vertex& V,const TopoDS_Edge& E) const;\n   Handle(BRepAlgo_AsDes) SectionEdgesAD() const;\n   Standard_Boolean IsSectionEdge(const TopoDS_Edge& E) const;\n   Standard_Boolean HasSectionEdge(const TopoDS_Face& F) const;\n   Standard_Boolean IsSplitOn(const TopoDS_Edge& NewE,const TopoDS_Edge& OldE,const TopoDS_Face& F) const;\n   const TopTools_ListOfShape& SectionEdgeFaces(const TopoDS_Edge& SecE) const;\n\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n   void Inter3D(const TopoDS_Face& F1,const TopoDS_Face& F2,TopTools_ListOfShape& LInt) ;\n   void StorePart3d(const TopoDS_Face& F1,const TopoDS_Face& F2,const TopTools_ListOfShape& LInt1) ;\n   void SetDone(const TopoDS_Face& F1,const TopoDS_Face& F2) ;\n   void Affiche(const TopTools_ListOfShape& SetOfFaces) const;\n\n\n   // Fields PRIVATE\n   //\n   Handle(BRepAlgo_AsDes) myAsDes;\n   TopTools_DataMapOfShapeListOfShape myDone;\n   TopTools_MapOfShape myTouched;\n   TopTools_MapOfShape myNewEdges;\n   Handle(BRepAlgo_AsDes) mySectionEdgesAD;\n   TopTools_DataMapOfShapeListOfShape mySameDomainFM;\n   TopTools_DataMapOfShapeShape mySameDomainVM;\n\n\n};\n\n\n\n\n\n// other Inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter3d.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter3d.ixx\n//  Module : GEOM\n\n#include \"Partition_Inter3d.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Inter3d.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Inter3d.jxx\n//  Module : GEOM\n\n#ifndef _BRepAlgo_AsDes_HeaderFile\n#include <BRepAlgo_AsDes.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeShape_HeaderFile\n#include <TopTools_DataMapOfShapeShape.hxx>\n#endif\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopTools_MapOfShape_HeaderFile\n#include <TopTools_MapOfShape.hxx>\n#endif\n#ifndef _TopoDS_Shape_HeaderFile\n#include <TopoDS_Shape.hxx>\n#endif\n#ifndef _TopoDS_Vertex_HeaderFile\n#include <TopoDS_Vertex.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _Partition_Inter3d_HeaderFile\n#include \"Partition_Inter3d.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Loop.cxx\n//  Author : Benedicte MARTIN\n//  Module : GEOM\n//  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $\n\n//using namespace std;\n#include <cstdio>\n#include <climits>\n\n#include \"Partition_Loop.ixx\"\n\n#include \"utilities.h\"\n\n#include <BRep_Builder.hxx>\n#include <BRepAlgo_FaceRestrictor.hxx>\n#include <BRep_Tool.hxx>\n\n#include <Geom2d_Curve.hxx>\n#include <Geom_Surface.hxx>\n\n#include <TopTools_SequenceOfShape.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopTools_MapOfShape.hxx>\n#include <TopTools_MapIteratorOfMapOfShape.hxx>\n#include <TopTools_MapOfOrientedShape.hxx>\n#include <TopTools_DataMapOfShapeShape.hxx>\n#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>\n\n#include <gp_Pnt.hxx>\n#include <gp_Pnt2d.hxx>\n\n#include <TopoDS.hxx>\n#include <TopoDS_Vertex.hxx>\n#include <TopoDS_Wire.hxx>\n#include <TopoDS_Iterator.hxx>\n\n#include <Precision.hxx>\n#include <BRep_TVertex.hxx>\n#include <BRep_TEdge.hxx>\n\n#include <TopExp.hxx>\n#include <TopExp_Explorer.hxx>\n\nstatic char* name = new char[100];\n// static int nbe = 0;\n\n#ifdef WIN32\n#define M_PI 3.14159265358979323846\n#endif \n\n//=======================================================================\n//function : Partition_Loop\n//purpose  : \n//=======================================================================\nPartition_Loop::Partition_Loop()\n{\n}\n\n//=======================================================================\n//function : Init\n//purpose  : \n//=======================================================================\nvoid Partition_Loop::Init(const TopoDS_Face& F)\n{\n  myConstEdges.Clear(); \n  myNewWires  .Clear();\n  myNewFaces  .Clear();\n  myFace = F;\n}\n\n//=======================================================================\n//function : AddConstEdge\n//purpose  : \n//=======================================================================\nvoid Partition_Loop::AddConstEdge (const TopoDS_Edge& E)\n{\n  myConstEdges.Append(E);\n}\n\n\n//=======================================================================\n//function : FindDelta\n//purpose  : \n//=======================================================================\nstatic Standard_Real FindDelta(TopTools_ListOfShape& LE,\n\t\t\t       const TopoDS_Face& F)\n{\n  Standard_Real dist, f, l;\n  Standard_Real d = Precision::Infinite();\n  TopTools_ListIteratorOfListOfShape itl;\n\n  for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n    const TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n    Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l);\n    gp_Pnt2d p = C->Value(f);\n    gp_Pnt2d pp = C->Value(l);\n    Standard_Real d1 = p.Distance(pp);\n    if (d1<d) { d=d1;}\n  }\n  dist = d ;\n  return dist;\n}\n\n//=======================================================================\n//function : SelectEdge\n//purpose  : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>.\n//           <NE> Is erased  of the list. If <CE> is too in the list <LE> \n//\t\t\t with the same orientation, it's erased of the list \n//=======================================================================\nstatic Standard_Boolean  SelectEdge(const TopoDS_Face&    F,\n\t\t\t\t    const TopoDS_Edge&    CE,\n\t\t\t\t    const TopoDS_Vertex&  CV,\n\t\t\t\t    TopoDS_Edge&          NE,\n\t\t\t\t    TopTools_ListOfShape& LE)\n{\n  TopTools_ListIteratorOfListOfShape itl;\n  NE.Nullify();\n  for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n    if (itl.Value().IsEqual(CE)) {\n      LE.Remove(itl);\n      break;\n    }\n  }\n\n  if (LE.Extent() > 1) {\n    //--------------------------------------------------------------\n    // Several possible edges.   \n    // - Test the edge difference of CE \n    //--------------------------------------------------------------\n    Standard_Real   cf, cl, f, l;\n    TopoDS_Face FForward = F;\n    Handle(Geom2d_Curve) Cc, C;\n    FForward.Orientation(TopAbs_FORWARD);\n\t\t\t\n    Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl);\n    Standard_Real dist,distmin  = 100*BRep_Tool::Tolerance(CV);\n    Standard_Real uc,u;\n    if (CE.Orientation () == TopAbs_FORWARD) uc = cl;\n    else                                     uc = cf;\n\n    gp_Pnt2d P2,PV = Cc->Value(uc); \n\n    Standard_Real delta = FindDelta(LE,FForward);\n\n    for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n      const TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n      if (!E.IsSame(CE)) {\n\tC = BRep_Tool::CurveOnSurface(E,FForward,f,l);\n\tif (E.Orientation () == TopAbs_FORWARD) u = f;\n\telse                                    u = l;\n\tP2 = C->Value(u);\n\tdist = PV.Distance(P2);\n\tif (dist <= distmin){\n\t  distmin = dist;\n\t}\n\t\t\t\t\n      }\n    }\n\n    Standard_Real anglemax = - M_PI;\n    TopoDS_Edge   SelectedEdge;\t\n    for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n      const TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n      if (!E.IsSame(CE)) {\n\tC = BRep_Tool::CurveOnSurface(E,FForward,f,l);\n\tif (E.Orientation () == TopAbs_FORWARD) u = f;\n\telse                                    u = l;\n\tP2 = C->Value(u);\n\tdist = PV.Distance(P2);\n\tif (dist <= distmin + (1./3)*delta){ \n\t  gp_Pnt2d PC, P;\n\t  gp_Vec2d CTg1, CTg2, Tg1, Tg2;\n\t  Cc->D2(uc, PC, CTg1, CTg2);\n\t  C->D2(u, P, Tg1, Tg2);\n\n\t  Standard_Real angle = 0.0;\n\n\t  if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) {\n\t    angle = CTg1.Angle(Tg1.Reversed());\n\t  }\n\t  else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) {\n\t    angle = (CTg1.Reversed()).Angle(Tg1);\n\t  }\n\t  else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) {\n\t    angle = CTg1.Angle(Tg1);\n\t  }\n\t  else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) {\n\t    angle = (CTg1.Reversed()).Angle(Tg1.Reversed());\n\t  }\n\t  if (angle >= anglemax) {\n\t    anglemax = angle ;\n\t    SelectedEdge = E;\t\n\t  }\n\t}\n      }\n    }\n    for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n      const TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n      if (E.IsEqual(SelectedEdge)) {\n\tNE = TopoDS::Edge(E);\n\tLE.Remove(itl);\n\tbreak;\n      }\n    }\t\t\t\t\t\n  }\n  else if (LE.Extent() == 1) {\n    NE = TopoDS::Edge(LE.First());\n    LE.RemoveFirst();\n  }\n  else {\n    return Standard_False;\n  }\n  return Standard_True;\n}\n\n//=======================================================================\n//function : SamePnt2d\n//purpose  : \n//=======================================================================\nstatic Standard_Boolean  SamePnt2d(TopoDS_Vertex  V,\n\t\t\t\t   TopoDS_Edge&   E1,\n\t\t\t\t   TopoDS_Edge&   E2,\n\t\t\t\t   TopoDS_Face&   F)\n{\n  Standard_Real   f1,f2,l1,l2;\n  gp_Pnt2d        P1,P2;\n  TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD);\n  TopoDS_Face FF = TopoDS::Face(aLocalF);\n  Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1);  \n  Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2);  \n  if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1);\n  else                                     P1 = C1->Value(l1);\n  \n  if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2);\n  else                                     P2 = C2->Value(f2);\n  Standard_Real Tol  = 100*BRep_Tool::Tolerance(V);\n  Standard_Real Dist = P1.Distance(P2);\n  return Dist < Tol; \n}\n\n//=======================================================================\n//function : PurgeNewEdges\n//purpose  : \n//=======================================================================\nstatic void  PurgeNewEdges(TopTools_ListOfShape& ConstEdges,\n\t\t\t   const TopTools_MapOfOrientedShape&          UsedEdges)\n{\n  TopTools_ListIteratorOfListOfShape it(ConstEdges);\n  while ( it.More()) {\n    const TopoDS_Shape& NE = it.Value();\n    if (!UsedEdges.Contains(NE)) {\n      ConstEdges.Remove(it);\n    }\n    else {\n      it.Next();\n    }\n  }  \n}\n\n//=======================================================================\n//function : StoreInMVE\n//purpose  : \n//=======================================================================\nstatic void StoreInMVE (const TopoDS_Face& F,\n\t\t\tTopoDS_Edge& E,\n\t\t\tTopTools_DataMapOfShapeListOfShape& MVE )\n\n{ \n  TopoDS_Vertex V1, V2;\n  TopTools_ListOfShape Empty;\n\n  TopExp::Vertices(E,V1,V2);\n  if (!MVE.IsBound(V1)) {\n    MVE.Bind(V1,Empty);\n  }\n  MVE(V1).Append(E);\n\t\n  if (!MVE.IsBound(V2)) {\n    MVE.Bind(V2,Empty);\n  }\n  MVE(V2).Append(E);\n}\n\n//=======================================================================\n//function : Perform\n//purpose  : \n//=======================================================================\nvoid Partition_Loop::Perform()\n{\n\n  TopTools_DataMapOfShapeListOfShape MVE;\n  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit, Mapit1;  \n  TopTools_ListIteratorOfListOfShape                  itl;\n  TopoDS_Vertex                                       V1,V2;\n\n  //-----------------------------------\n  // Construction map vertex => edges\n  //-----------------------------------\n  for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {\n    TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n    StoreInMVE(myFace,E,MVE);\n  }\n\n  //----------------------------------------------\n  // Construction of all the wires and of all the new faces. \n  //----------------------------------------------\n  TopTools_MapOfOrientedShape UsedEdges;\n\n  while (!MVE.IsEmpty()) {\n    TopoDS_Vertex    VF,CV;\n    TopoDS_Edge      CE,NE,EF;\n    TopoDS_Wire      NW;\n    BRep_Builder     B;\n    Standard_Boolean End= Standard_False;\n\n    B.MakeWire(NW);\n    //--------------------------------\n    // EF first edge.\n    //--------------------------------\n    Mapit.Initialize(MVE);\n    EF = CE = TopoDS::Edge(Mapit.Value().First());\n\n    TopExp::Vertices(CE,V1,V2);\n    //--------------------------------\n    // VF first vertex \n    //--------------------------------\n    if (CE.Orientation() == TopAbs_FORWARD) { \n      CV = VF = V1;\n    }\n    else  { \n      CV = VF = V2;\n    }\n    if (!MVE.IsBound(CV)) continue;\n    for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) {\n      if (itl.Value().IsEqual(CE)) {\n\tMVE(CV).Remove(itl);\n\tbreak;\n      }\n    }\n\n    // int i = 0;\n    while (!End) { \n      //-------------------------------\n      // Construction of a wire.\n      //-------------------------------\n      TopExp::Vertices(CE,V1,V2);\n      if (!CV.IsSame(V1)) CV = V1; else CV = V2; \n      B.Add (NW,CE);\n      UsedEdges.Add(CE);\n\n      //--------------\n      // stop test\n      //--------------\t\t\t\n      if (!MVE.IsBound(CV) || MVE(CV).IsEmpty() || CV.IsSame(VF) ) {\n\tif (CV.IsSame(VF)) {\n\t  if (MVE(CV).Extent() == 1 ) MVE.UnBind(CV);\n\t  else {\n\t    for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) {\n\t      if (itl.Value().IsEqual(CE)) {\n\t\tMVE(CV).Remove(itl);\n\t\tbreak;\n\t      }\n\t    }\n\t  }\n\t}\n\tEnd=Standard_True;\n      } \n\n      //--------------\n      // select edge\n      //--------------\n      else {\n\tStandard_Boolean find = SelectEdge(myFace,CE,CV,NE,MVE(CV));\n\tif (find) {\n\t  CE=NE;\n\t  if (MVE(CV).IsEmpty()) MVE.UnBind(CV);\n\t  if (CE.IsNull() ) {\n\t    MESSAGE ( \" CE is  NULL !!! \" )\n\t    End=Standard_True;\n\t  }\n\t}\n\telse {\n\t  MESSAGE ( \" edge doesn't exist \" )\n\t  End=Standard_True;\n\t}\n      }\n    }\n\n    //-----------------------------\n    // Test if the wire is closed  \n    //-----------------------------\n    if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace)) {\n    }\n    else{\n      MESSAGE ( \"wire not closed\" )\n    }\n    myNewWires.Append (NW);\t\t\t\n  }\n\n  PurgeNewEdges(myConstEdges,UsedEdges);\n\n}\n\n\n//=======================================================================\n//function : NewWires\n//purpose  : \n//=======================================================================\nconst TopTools_ListOfShape&  Partition_Loop::NewWires() const \n{  \n  return myNewWires;\n}\n\n//=======================================================================\n//function : NewFaces\n//purpose  : \n//=======================================================================\nconst TopTools_ListOfShape&  Partition_Loop::NewFaces() const \n{  \n  return myNewFaces;\n}\n \n//=======================================================================\n//function : WiresToFaces\n//purpose  : \n//=======================================================================\nvoid  Partition_Loop::WiresToFaces() \n{  \n  if (!myNewWires.IsEmpty()) {\n    BRepAlgo_FaceRestrictor FR;\n\n    TopAbs_Orientation OriF = myFace.Orientation();\n    TopoDS_Shape aLocalS = myFace.Oriented(TopAbs_FORWARD);\n\n    FR.Init (TopoDS::Face(aLocalS),Standard_False);\n    TopTools_ListIteratorOfListOfShape it(myNewWires);\n    for (; it.More(); it.Next()) {\n      FR.Add(TopoDS::Wire(it.Value()));\n    }\n\n    FR.Perform();\n    \n    if (FR.IsDone()) {\n      for (; FR.More(); FR.Next()) {\n\tmyNewFaces.Append(FR.Current().Oriented(OriF));\n      }\n    }\n  }\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Loop.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Loop_HeaderFile\n#define _Partition_Loop_HeaderFile\n\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile\n#include <TopTools_DataMapOfShapeListOfShape.hxx>\n#endif\n#ifndef _Standard_Version_HeaderFile\n#include <Standard_Version.hxx>\n#endif\nclass TopoDS_Face;\nclass TopoDS_Edge;\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_ListOfShape;\n#endif\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Loop  {\n\npublic:\n\n   inline void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   inline void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   inline void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   //    inline void  operator delete(void *anAddress, size_t size) \n   //      { \n   //        if (anAddress) Standard::Free((Standard_Address&)anAddress,size); \n   //      }\n   // Methods PUBLIC\n   // \n   Partition_Loop();\n   void Init(const TopoDS_Face& F) ;\n   void AddConstEdge(const TopoDS_Edge& E) ;\n   void Perform() ;\n   const TopTools_ListOfShape& NewWires() const;\n   void WiresToFaces() ;\n   const TopTools_ListOfShape& NewFaces() const;\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n\n\n   // Fields PRIVATE\n   //\n   TopoDS_Face myFace;\n   TopTools_ListOfShape myConstEdges;\n   TopTools_ListOfShape myNewWires;\n   TopTools_ListOfShape myNewFaces;\n\n\n};\n\n\n\n\n\n// other inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Loop.ixx\n//  Module : GEOM\n\n#include \"Partition_Loop.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Loop.jxx\n//  Module : GEOM\n\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeShape_HeaderFile\n#include <TopTools_DataMapOfShapeShape.hxx>\n#endif\n#ifndef _Partition_Loop_HeaderFile\n#include \"Partition_Loop.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop2d.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R& D\n//\n//\n//\n//  File   : Partition_Loop2d.cxx\n//  Author : Benedicte MARTIN\n//  Module : GEOM\n//  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop2d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $\n\n//using namespace std;\n#include <climits>\n#include \"Partition_Loop2d.ixx\"\n\n#include \"utilities.h\"\n#include <stdio.h>\n\n#include <BRepAdaptor_Curve2d.hxx>\n#include <BRepAdaptor_Surface.hxx>\n#include <BRepAlgo_AsDes.hxx>\n#include <BRepAlgo_FaceRestrictor.hxx>\n// #include <BRepOffset_DataMapOfShapeReal.hxx>   // V6.3\n#include <BRepTopAdaptor_FClass2d.hxx>\n#include <BRep_Builder.hxx>\n#include <BRep_Tool.hxx>\n#include <Geom2dInt_GInter.hxx>\n#include <Geom2d_Curve.hxx>\n#include <IntRes2d_IntersectionPoint.hxx>\n#include <Precision.hxx>\n#include <TColStd_MapOfInteger.hxx>\n#include <TColStd_SequenceOfReal.hxx>\n#include <TopExp.hxx>\n#include <TopExp_Explorer.hxx>\n#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>\n#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>\n#include <TopTools_DataMapOfShapeInteger.hxx>\n#include <TopTools_DataMapOfShapeReal.hxx>    // V6.5\n#include <TopTools_DataMapOfShapeShape.hxx>\n#include <TopTools_IndexedMapOfShape.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopTools_MapIteratorOfMapOfShape.hxx>\n#include <TopTools_MapOfOrientedShape.hxx>\n#include <TopTools_MapOfShape.hxx>\n#include <TopTools_SequenceOfShape.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Iterator.hxx>\n#include <TopoDS_Vertex.hxx>\n#include <TopoDS_Wire.hxx>\n#include <gp_Pnt.hxx>\n#include <gp_Pnt2d.hxx>\n\n//=======================================================================\n//function : Partition_Loop2d\n//purpose  :\n//=======================================================================\n\nPartition_Loop2d::Partition_Loop2d()\n{\n}\n\n//=======================================================================\n//function : Init\n//purpose  : Init with <F> the set of edges must have\n//           pcurves on <F>.\n//=======================================================================\n\nvoid Partition_Loop2d::Init(const TopoDS_Face& F)\n{\n  myConstEdges.Clear();\n  myNewWires  .Clear();\n  myNewFaces  .Clear();\n  myFace = F;\n  myFaceOri = myFace.Orientation();\n  myFace.Orientation( TopAbs_FORWARD );\n}\n\n//=======================================================================\n//function : AddConstEdge\n//purpose  : Add <E> as unique edge in the result.\n//=======================================================================\n\nvoid Partition_Loop2d::AddConstEdge (const TopoDS_Edge& E)\n{\n#ifdef DEB\n  Standard_Real f,l;\n  Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);\n  if (pc.IsNull()) {\n    INFOS( \"AddConstEdge(): EDGE W/O PCURVE on FACE\");\n  } else\n#endif\n  {\n    myConstEdges.Append(E);\n  }\n}\n\nvoid Partition_Loop2d::AddSectionEdge (const TopoDS_Edge& E)\n{\n#ifdef DEB\n  Standard_Real f,l;\n  Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);\n  if (pc.IsNull())\n    pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);\n  gp_Vec2d Tg1;\n  gp_Pnt2d PC;\n  pc->D1(0.5*(f+l), PC, Tg1);\n  if (Tg1.Magnitude()  <= gp::Resolution()) {\n    MESSAGE (\"\");\n  }\n  if (pc.IsNull()) {\n    INFOS( \"AddConstEdge(): EDGE W/O PCURVE on FACE\");\n  } else\n#endif\n  {\n    myConstEdges.Append(E);\n    myConstEdges.Append(E.Reversed());\n    mySectionEdges.Add( E );\n  }\n}\n\n//=======================================================================\n//function : preciseU\n//purpose  : find u such that the 3D point on theE is just out of tolerance\n//           of theV\n//=======================================================================\n\nstatic Standard_Real preciseU (const BRepAdaptor_Surface&  theSurf,\n                               const TopoDS_Edge&          theE,\n                               const TopoDS_Vertex&        theV,\n                               const Handle(Geom2d_Curve)& theC,\n                               const Standard_Boolean      theFirstEnd)\n{\n  Standard_Boolean isForward = ( theE.Orientation () == TopAbs_FORWARD );\n  if (theFirstEnd) isForward = !isForward;\n\n  // find the first point in 2d and 3d\n  Standard_Real f,l;\n  BRep_Tool::Range( theE, f, l );\n  Standard_Real u0 = isForward ? l : f;\n  gp_Pnt2d aP2d0 = theC->Value( u0 );\n  gp_Pnt aPnt0 = theSurf.Value( aP2d0.X(), aP2d0.Y() );\n\n  // shift in 2d and 3d\n  Standard_Real du = ( l - f ) / 100, du3d = 0;\n  if (isForward)\n    du = -du;\n\n  // target parameter\n  Standard_Real u;\n\n  while (du3d < ::RealSmall())\n  {\n    // u for test\n    u = u0 + du;\n    du *= 10; // for the next iteration: increase du until du3d is large enough\n\n    // find out how u is far from u0 in 3D\n    gp_Pnt2d aP2d  = theC->Value( u );\n    gp_Pnt aPnt  = theSurf.Value( aP2d.X(), aP2d.Y() );\n    du3d = aPnt0.Distance( aPnt );\n  }\n\n  // find u such that the 3D point is just out of tolerance of theV\n  Standard_Real tolV = BRep_Tool::Tolerance( theV ) + Precision::Confusion();\n  u = u0 + du * tolV / du3d;\n\n  // check that u is within the range\n  if ( isForward ? (u < f) : (u > l) )\n    u = u0 + du;\n\n  return u;\n}\n\n//=======================================================================\n//function : SelectEdge\n//purpose  : Find in the list <LE> the edge <NE> connected with <CE> by\n//           the vertex <CV>.\n//           <NE> is removed from the list. If <CE> is in <LE>\n//           with the same orientation, it's removed from the list\n//=======================================================================\n\nstatic Standard_Boolean  SelectEdge(const BRepAdaptor_Surface& Surf,\n                                    const TopoDS_Edge&    CE,\n                                    const TopoDS_Vertex&  CV,\n                                    TopoDS_Edge&          NE,\n                                    const TopTools_ListOfShape& LE)\n{\n  NE.Nullify();\n\n  if (LE.Extent() > 1) {\n    //--------------------------------------------------------------\n    // Several possible edges.\n    // - Test the edge difference of CE\n    //--------------------------------------------------------------\n    TopoDS_Face FForward = Surf.Face();\n    TopoDS_Edge aPrevNE;\n\n    gp_Vec2d CTg1, Tg1, CTg2, Tg2;\n    gp_Pnt2d PC, P;\n\n    Standard_Real f, l;\n    Handle(Geom2d_Curve) Cc, C;\n    Cc = BRep_Tool::CurveOnSurface(CE,FForward,f,l);\n\n    Standard_Boolean isForward = ( CE.Orientation () == TopAbs_FORWARD );\n    Standard_Real uc, u, du = Precision::PConfusion();\n    uc = isForward ? ( l - du ) : ( f + du );\n    Cc->D1(uc, PC, CTg1);\n    if (!isForward) CTg1.Reverse();\n\n    Standard_Real anglemin = 3 * M_PI, tolAng = 1.e-8;\n\n    // select an edge whose first derivative is most left of CTg1\n    // ie an angle between Tg1 and CTg1 is least\n    TopTools_ListIteratorOfListOfShape itl;\n    for ( itl.Initialize(LE); itl.More(); itl.Next()) {\n      const TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n      if (E.IsSame(CE))\n        continue;\n      if (! CV.IsSame( TopExp::FirstVertex( E, Standard_True )))\n        continue;\n\n      isForward = ( E.Orientation () == TopAbs_FORWARD );\n\n      // get E curve\n      C = BRep_Tool::CurveOnSurface(E,FForward,f,l);\n      // get the first derivative Tg1\n      u = isForward ? ( f + du ) : ( l - du );\n      C->D1(u, P, Tg1);\n      if (!isForward) Tg1.Reverse();\n\n      // -PI < angle < PI\n      Standard_Real angle = Tg1.Angle(CTg1);\n\n      if (M_PI - Abs(angle) <= tolAng)\n      {\n        // an angle is too close to PI; assure that an angle sign really\n        // reflects an edge position: +PI - an edge is worst,\n        // -PI - an edge is best.\n        u = preciseU( Surf, CE, CV, Cc, Standard_False);\n        gp_Vec2d CTg;\n        Cc->D1(u, PC, CTg);\n        if (CE.Orientation() == TopAbs_REVERSED) CTg.Reverse();\n\n        u = preciseU( Surf, E, CV, C, Standard_True);\n        C->D1(u, P, Tg1);\n        if (!isForward) Tg1.Reverse();\n\n        angle = Tg1.Angle(CTg);\n      }\n\n      Standard_Boolean isClose = ( Abs( angle - anglemin ) <= tolAng );\n      if (angle <= anglemin) {\n        if (isClose)\n          aPrevNE = NE;\n        else\n          aPrevNE.Nullify();\n        anglemin = angle ;\n        NE = E;\n      }\n      else\n        if (isClose)\n          aPrevNE = E;\n\n    }\n    if (!aPrevNE.IsNull()) {\n      // select one of close edges, the most left one.\n      Cc = BRep_Tool::CurveOnSurface( NE, FForward, f, l );\n      uc = preciseU( Surf, NE, CV, Cc, Standard_True);\n      Cc->D1(uc, PC, CTg1);\n      if (NE.Orientation() != TopAbs_FORWARD) CTg1.Reverse();\n      \n      u = preciseU( Surf, aPrevNE, CV, C, Standard_True);\n      C->D1(u, P, Tg1);\n      if (aPrevNE.Orientation() != TopAbs_FORWARD) Tg1.Reverse();\n\n      if ( Tg1.Angle(CTg1) < 0)\n        NE = aPrevNE;\n    }\n  }\n  else if (LE.Extent() == 1) {\n    NE = TopoDS::Edge(LE.First());\n  }\n  else {\n    return Standard_False;\n  }\n  return !NE.IsNull();\n}\n\n//=======================================================================\n//function : SamePnt2d\n//purpose  :\n//=======================================================================\n\nstatic Standard_Boolean  SamePnt2d(const TopoDS_Vertex& V1,\n                                   const TopoDS_Edge&   E1,\n                                   const TopoDS_Vertex& V2,\n                                   const TopoDS_Edge&   E2,\n                                   const TopoDS_Face&   F)\n{\n  Standard_Real   f1,f2,l1,l2;\n  Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,F,f1,l1);\n  Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,F,f2,l2);\n\n  gp_Pnt2d P1 = C1->Value( BRep_Tool::Parameter(V1,E1));\n  gp_Pnt2d P2 = C2->Value( BRep_Tool::Parameter(V2,E2));\n\n  Standard_Real Tol  = 100 * BRep_Tool::Tolerance(V1);\n  Standard_Real Dist = P1.Distance(P2);\n  return Dist < Tol;\n}\n\n\n//=======================================================================\n//function : StoreInMVE\n//purpose  :\n//=======================================================================\n\nstatic void StoreInMVE (const TopoDS_Face& /*F*/,\n                        TopoDS_Edge& E,\n                        TopTools_DataMapOfShapeListOfShape& MVE )\n\n{\n  TopoDS_Vertex V1, V2;\n  TopTools_ListOfShape Empty;\n\n  TopExp::Vertices(E,V1,V2);\n  if (!MVE.IsBound(V1)) {\n    MVE.Bind(V1,Empty);\n  }\n  MVE(V1).Append(E);\n\n  if (!MVE.IsBound(V2)) {\n    MVE.Bind(V2,Empty);\n  }\n  MVE(V2).Append(E);\n}\n\n//=======================================================================\n//function : RemoveFromMVE\n//purpose  :\n//=======================================================================\n\nstatic void RemoveFromMVE(const TopoDS_Edge& E,\n                          TopTools_DataMapOfShapeListOfShape& MVE)\n{\n  TopTools_ListIteratorOfListOfShape itl;\n  TopoDS_Vertex  V1,V2;\n  TopExp::Vertices (E,V1,V2);\n  if (MVE.IsBound(V1))\n    for ( itl.Initialize(MVE(V1)); itl.More(); itl.Next()) {\n      if (itl.Value().IsEqual(E)) {\n        MVE(V1).Remove(itl);\n        break;\n      }\n    }\n  if (MVE.IsBound(V2))\n    for ( itl.Initialize(MVE(V2)); itl.More(); itl.Next()) {\n      if (itl.Value().IsEqual(E)) {\n        MVE(V2).Remove(itl);\n        break;\n      }\n    }\n}\n//=======================================================================\n//function : addConnected\n//purpose  : add to <EM> all edges reachable from <E>\n//=======================================================================\n\nstatic void addConnected(const TopoDS_Shape& E,\n                         TopTools_MapOfShape& EM,\n                         TopTools_MapOfShape& VM,\n                         const TopTools_DataMapOfShapeListOfShape& MVE)\n{\n  // Loop on vertices of E\n  TopoDS_Iterator itV ( E );\n  for ( ; itV.More(); itV.Next()) {\n\n    if ( ! VM.Add ( itV.Value() )) continue;\n\n    // Loop on edges sharing V\n    TopTools_ListIteratorOfListOfShape itE( MVE( itV.Value() ) );\n    for (; itE.More(); itE.Next()) {\n      if ( EM.Add( itE.Value() ))\n        addConnected ( itE.Value(), EM, VM, MVE );\n    }\n  }\n}\n//=======================================================================\n//function : canPassToOld\n//purpose  :\n//=======================================================================\n\n// static Standard_Boolean canPassToOld (const TopoDS_Shape& V,\n//                                    TopTools_MapOfShape& UsedShapesMap,\n//                                    const TopTools_DataMapOfShapeListOfShape& MVE,\n//                                    const TopTools_MapOfShape& SectionEdgesMap)\n// {\n//   TopTools_ListIteratorOfListOfShape itE( MVE(V) );\n//   // Loop on edges sharing V\n//   for (; itE.More(); itE.Next()) {\n//     if ( !UsedShapesMap.Add( itE.Value() ))\n//       continue; // already checked\n\n//     if ( !SectionEdgesMap.Contains( itE.Value() ))\n//       return Standard_True; // WE PASSED\n\n//     TopoDS_Iterator itV( itE.Value() );\n//     // Loop on vertices of an edge\n//     for (; itV.More(); itV.Next()) {\n//       if ( !UsedShapesMap.Add( itV.Value() ))\n//      continue; // already checked\n//       else\n//      return canPassToOld( itV.Value(), UsedShapesMap, MVE, SectionEdgesMap);\n//     }\n//   }\n//   return Standard_False;\n// }\n\n//=======================================================================\n//function : MakeDegenAndSelect\n//purpose  : Find parameter of intersection of <CE> with <DE> and\n//           select an edge with its parameter closest to found one.\n//           Return new degenerated edge trimming <DE> by found parameters\n//=======================================================================\n\nstatic TopoDS_Edge MakeDegenAndSelect(const TopoDS_Edge& CE,\n                                      const TopoDS_Vertex& CV,\n                                      TopoDS_Edge& NE,\n                                      TopTools_SequenceOfShape& EdgesSeq,\n                                      TColStd_SequenceOfReal& USeq,\n                                      const TopoDS_Edge& DE)\n{\n  if (EdgesSeq.Length() < 3) {\n    if (CE == EdgesSeq.First())\n      NE = TopoDS::Edge( EdgesSeq.Last() );\n    else\n      NE = TopoDS::Edge( EdgesSeq.First() );\n    return DE;\n  }\n\n  // find parameter on DE where it intersects CE\n\n  Standard_Real U1;\n  Standard_Integer i, nb = EdgesSeq.Length();\n  for (i=1; i<= nb; ++i) {\n    if (CE == EdgesSeq(i)) {\n      U1 = USeq(i);\n      break;\n    }\n  }\n\n  // select NE with param closest to U1 thus finding U2 for a new degen edge\n\n  Standard_Real U2, dU, dUmin = 1.e100;\n  Standard_Boolean isReversed = ( DE.Orientation() == TopAbs_REVERSED );\n  for (i=1; i<= nb; ++i) {\n    dU = USeq(i) - U1;\n    if (isReversed ? (dU > 0) : (dU < 0))\n        continue;\n    dU = Abs( dU );\n    if ( dU  > dUmin || IsEqual( dU, 0.))\n      continue;\n    const TopoDS_Edge& E = TopoDS::Edge ( EdgesSeq(i) );\n    if ( ! CV.IsSame( TopExp::FirstVertex( E , Standard_True )))\n      continue;\n    NE = E;\n    dUmin = dU + Epsilon(dU);\n    U2 = USeq(i);\n  }\n\n  // make a new degenerated edge\n  TopoDS_Edge NewDegen = TopoDS::Edge ( DE.EmptyCopied() );\n\n  Standard_Real Tol = BRep_Tool::Tolerance( CV );\n  TopoDS_Vertex V = CV;\n\n  BRep_Builder B;\n  V.Orientation( NewDegen.Orientation() );\n  B.UpdateVertex( V, U1, NewDegen, Tol);\n  B.Add ( NewDegen , V );\n\n  V.Reverse();\n  B.UpdateVertex( V, U2, NewDegen, Tol);\n  B.Add ( NewDegen , V );\n\n  return NewDegen;\n}\n\n//=======================================================================\n//function : prepareDegen\n//purpose  : Intersect <DegEdge> with edges bound to its vertex in <MVE>\n//           and store intersection parameter on <DegEdge> in\n//           <USeq> as well as the edges them-self in <EdgesSeq>.\n//           Bind <DegEdgeIndex> to vertex of <DegEdge> in <MVDEI>\n//=======================================================================\n\nstatic void prepareDegen (const TopoDS_Edge&                        DegEdge,\n                          const TopoDS_Face&                        F,\n                          const TopTools_DataMapOfShapeListOfShape& MVE,\n                          TopTools_SequenceOfShape&                 EdgesSeq,\n                          TColStd_SequenceOfReal&                   USeq,\n                          TopTools_DataMapOfShapeInteger&           MVDEI,\n                          const Standard_Integer                    DegEdgeIndex)\n{\n  const TopoDS_Vertex& V = TopExp::FirstVertex ( DegEdge );\n  MVDEI.Bind ( V, DegEdgeIndex );\n\n  const TopTools_ListOfShape& EdgesList = MVE ( V );\n  // if only 2 edges come to degenerated one, no pb in selection and\n  // no need to intersect them, just simulate asked data\n  Standard_Boolean doIntersect =  ( EdgesList.Extent() > 2 );\n\n  BRepAdaptor_Curve2d DC, C;\n  Geom2dInt_GInter InterCC;\n  Standard_Real Tol = Precision::PConfusion();\n  if ( doIntersect )\n    DC.Initialize( DegEdge, F );\n\n  // avoid intersecting twice the same edge\n  // BRepOffset_DataMapOfShapeReal EUMap ( EdgesList.Extent() );  // V6.3\n  TopTools_DataMapOfShapeReal EUMap ( EdgesList.Extent() );   // V6.5\n\n  Standard_Real U, f, l;\n  BRep_Tool::Range (DegEdge, f, l);\n\n  TopTools_ListIteratorOfListOfShape itE (EdgesList);\n  for (; itE.More(); itE.Next()) {\n\n    const TopoDS_Edge& E = TopoDS::Edge ( itE.Value() );\n\n    if ( !doIntersect) {\n      U = 0.; // it won't be used\n    }\n    else if ( BRep_Tool::IsClosed( E, F )) {\n      // seam edge: select U among f and l\n      Standard_Boolean first = Standard_True;\n      if ( V.IsSame ( TopExp::FirstVertex( E, Standard_True ) ))\n        first = Standard_False;\n      if ( DegEdge.Orientation() == TopAbs_REVERSED )\n        first = !first;\n      U = first ? f : l;\n    }\n    else if ( EUMap.IsBound( E ) ) {\n      // same edge already bound\n      U = EUMap( E );\n    }\n    else {\n      // intersect 2d curves\n      C.Initialize( E, F );\n      InterCC.Perform ( DC, C , Tol, Tol );\n      if (! InterCC.IsDone() || InterCC.NbPoints() == 0) {\n        MESSAGE ( \"NO 2d INTERSECTION ON DEGENERATED EDGE\" );\n        continue;\n      }\n      // hope there is only one point of intersection\n      U = InterCC.Point( 1 ).ParamOnFirst();\n    }\n    USeq.Append ( U );\n    EdgesSeq.Append ( E );\n  }\n}\n//=======================================================================\n//function : Perform\n//purpose  : Make loops.\n//=======================================================================\n\nvoid Partition_Loop2d::Perform()\n{\n\n  Standard_Integer NbConstEdges = myConstEdges.Extent();\n  TopTools_DataMapOfShapeListOfShape MVE(NbConstEdges) , MVE2(NbConstEdges);\n  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;\n  TopTools_ListIteratorOfListOfShape itl;\n  TopoDS_Vertex V1,V2;\n  BRepAdaptor_Surface Surface ( myFace, Standard_False );\n\n  // degenerated edges and parameters of their 2d intersection with other edges\n  TopoDS_Edge                    DE [2];\n  TopTools_SequenceOfShape       SEID [2]; // seq of edges intersecting degenerated\n  TColStd_SequenceOfReal         SeqU [2]; // n-th U corresponds to n-th edge in SEID\n  TopTools_DataMapOfShapeInteger MVDEI(2); // map vertex - degenerated edge index\n  Standard_Integer               iDeg = 0; // index of degenerated edge [0,1]\n\n  //---------------------------------------------------------\n  // Construction map vertex => edges, find degenerated edges\n  //---------------------------------------------------------\n  for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {\n    TopoDS_Edge& E = TopoDS::Edge(itl.Value());\n    if ( BRep_Tool::Degenerated( E )) {\n      if (DE[0].IsNull()) DE[0] = E;\n      else                DE[1] = E;\n    }\n    else\n      StoreInMVE(myFace,E,MVE);\n  }\n\n  // fill data for degenerated edges\n  if ( ! DE[0].IsNull() )\n    prepareDegen ( DE[0], myFace, MVE, SEID[0], SeqU[0], MVDEI, 0);\n  if ( ! DE[1].IsNull() )\n    prepareDegen ( DE[1], myFace, MVE, SEID[1], SeqU[1], MVDEI, 1);\n\n\n  // to detect internal wires\n  Standard_Boolean isInternCW = 0;\n  MVE2 = MVE;\n\n\n  //------------------------------\n  // Construction of all the wires\n  //------------------------------\n  // first, we collect wire edges in WEL list looking for same edges that\n  // will be then removed possibly exploding a wire into parts;\n  // second, build wire(s)\n\n  while (!MVE.IsEmpty()) {\n\n    TopoDS_Vertex    VF,CV;\n    TopoDS_Edge      CE,NE,EF;\n    TopoDS_Wire      NW;\n    BRep_Builder     B;\n    Standard_Boolean End = Standard_False;\n    TopTools_ListOfShape WEL;\n\n    Mapit.Initialize(MVE);\n    if (Mapit.Value().IsEmpty()) {\n      MVE.UnBind(Mapit.Key());\n      continue;\n    }\n\n    // EF first edge.\n    EF = CE = TopoDS::Edge(Mapit.Value().First());\n    // VF first vertex\n    VF = TopExp::FirstVertex( CE, Standard_True);\n\n    isInternCW = Standard_True;\n\n    TopTools_MapOfShape addedEM  (NbConstEdges); // map of edges added to WEL\n    TopTools_MapOfShape doubleEM (NbConstEdges); // edges encountered twice in WEL\n\n    //-------------------------------\n    // Construction of a wire.\n    //-------------------------------\n    while (!End) {\n\n      // only a seam is allowed twice in a wire, the others should be removed\n      if (addedEM.Add ( CE ) || BRep_Tool::IsClosed( CE, myFace ) )\n        WEL.Append( CE );\n      else {\n        doubleEM.Add( CE );\n        RemoveFromMVE (CE,MVE2);\n        TopoDS_Edge CERev = CE;\n        CERev.Reverse();\n        RemoveFromMVE (CERev,MVE2);\n      }\n\n      RemoveFromMVE (CE,MVE);\n\n      CV = TopExp::LastVertex( CE, Standard_True);\n\n      if (isInternCW && !mySectionEdges.Contains(CE))\n        // wire is internal if all edges are section ones\n        isInternCW = Standard_False;\n\n      if (MVDEI.IsBound( CV )) { // CE comes to the degeneration\n        iDeg = MVDEI( CV );\n        TopoDS_Edge NewDegen;\n        NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]);\n        WEL.Append( NewDegen );\n        CE = NE;\n        End = CV.IsSame( VF );\n        continue;\n      }\n\n      //--------------\n      // stop test\n      //--------------\n      if (MVE(CV).IsEmpty()) {\n        End=Standard_True;\n        MVE.UnBind(CV);\n      }\n      else if (CV.IsSame(VF) && SamePnt2d(CV,CE, VF,EF, myFace) ) {\n        End = Standard_True;\n      }\n      else {\n        //----------------------------\n        // select new current edge\n        //----------------------------\n        if (! SelectEdge (Surface,CE,CV,NE,MVE(CV))) {\n          MESSAGE ( \" NOT CLOSED WIRE \" );\n          End=Standard_True;\n        }\n        else\n          CE = NE;\n      }\n    } // while ( !End )\n\n\n    // WEL is built, built wire(s)\n\n\n    itl.Initialize( WEL );\n    if ( doubleEM.IsEmpty()) { // no double edges\n      B.MakeWire( NW );\n      for (; itl.More(); itl.Next())\n        B.Add ( NW, itl.Value());\n      if (isInternCW) myInternalWL.Append(NW);\n      else            myNewWires.Append  (NW);\n    }\n\n    else {\n      // remove double and degenerated edges from WEL\n      while (itl.More()) {\n        const TopoDS_Edge& E = TopoDS::Edge ( itl.Value() );\n        if ( doubleEM.Contains( E ) || BRep_Tool::Degenerated( E ))\n          WEL.Remove( itl );\n        else\n           itl.Next();\n      }\n      if ( WEL.IsEmpty())\n        continue;\n      // remove double edges from SEID and SeqU\n      Standard_Integer i,j;\n      for (j=0; j<2; ++j) {\n        for (i=1; i<=SEID[j].Length(); ++i) {\n          if (doubleEM.Contains( SEID[j].Value(i))) {\n            SEID[j].Remove( i );\n            SeqU[j].Remove( i-- );\n          }\n        }\n      }\n      // removal of double edges can explode a wire into parts,\n      // make new wires of them.\n      // A Loop like previous one but without 2d check\n      while ( !WEL.IsEmpty() ) {\n        CE = TopoDS::Edge( WEL.First() );\n        WEL.RemoveFirst();\n        B.MakeWire( NW );\n        VF = TopExp::FirstVertex ( CE, Standard_True);\n\n        End = Standard_False;\n        while ( !End) {\n          B.Add( NW, CE );\n          CV = TopExp::LastVertex  ( CE, Standard_True);\n\n          if (MVDEI.IsBound( CV )) {   // CE comes to the degeneration\n            iDeg = MVDEI( CV );\n            TopoDS_Edge NewDegen;\n            NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]);\n            B.Add( NW, NewDegen );\n            End = CV.IsSame( VF );\n            CE = NE;\n            if (!NE.IsNull()) { // remove NE from WEL\n              for (itl.Initialize( WEL ); itl.More(); itl.Next())\n                if ( NE == itl.Value()) {\n                  WEL.Remove( itl );\n                  break;\n                }\n            }\n          }  // end degeneration\n\n          else {\n            if (CV.IsSame( VF )) {\n              End = Standard_True;\n              continue;\n            }\n            // edges in WEL most often are well ordered\n            // so try to iterate until the End\n            Standard_Boolean add = Standard_False;\n            itl.Initialize(WEL);\n            while ( itl.More() && !End) {\n              NE = TopoDS::Edge( itl.Value() );\n              if ( CV.IsSame( TopExp::FirstVertex( NE, Standard_True ))) {\n                WEL.Remove( itl );\n                if (add)\n                  B.Add( NW, CE );\n                CE = NE;\n                add = Standard_True;\n                CV = TopExp::LastVertex( CE, Standard_True);\n                if (MVDEI.IsBound( CV ) || CV.IsSame( VF ))\n                  break;\n              }\n              else\n                itl.Next();\n            }\n            if (!add)\n              End = Standard_True;\n          }\n        } // !End\n\n        myInternalWL.Append( NW );\n      }\n    } // end building new wire(s) from WEL\n\n  } // end Loop on MVE\n\n  // all wires are built\n\n\n  // ============================================================\n  // select really internal wires i.e. those from which we can`t\n  // pass to an old (not section) edge\n  // ============================================================\n\n  Standard_Integer nbIW = myInternalWL.Extent();\n  if (nbIW == 0)\n    return;\n\n  if ( myNewWires.Extent() != 1 && nbIW > 1) {\n    TopTools_MapOfShape outerEM (NbConstEdges); // edges connected to non-section ones\n    TopTools_MapOfShape visitedVM (NbConstEdges);\n    for ( itl.Initialize( myConstEdges ); itl.More(); itl.Next()) {\n      if ( ! mySectionEdges.Contains( itl.Value() ))\n        addConnected (itl.Value(), outerEM, visitedVM, MVE2);\n    }\n    // if an edge of a wire is in <outerEM>, the wire is not internal\n    TopExp_Explorer expIWE;\n    TopTools_ListIteratorOfListOfShape itIW ( myInternalWL );\n    while (itIW.More()) {\n      expIWE.Init ( itIW.Value() , TopAbs_EDGE );\n      if ( outerEM.Contains( expIWE.Current() )) {\n        myNewWires.Append ( itIW.Value() );\n        myInternalWL.Remove( itIW ); // == itIW.Next()\n      }\n      else\n        itIW.Next();\n    }\n  }\n}\n//=======================================================================\n//function : isHole\n//purpose  :\n//=======================================================================\n\nstatic Standard_Boolean isHole (const TopoDS_Wire& W,\n                                const TopoDS_Face& F)\n{\n  BRep_Builder B;\n  TopoDS_Shape newFace = F.EmptyCopied();\n  B.Add(newFace,W.Oriented(TopAbs_FORWARD));\n  BRepTopAdaptor_FClass2d classif (TopoDS::Face(newFace),\n                                   Precision::PConfusion());\n  return (classif.PerformInfinitePoint() == TopAbs_IN);\n}\n\n//=======================================================================\n//function : IsInside\n//purpose  : check if W1 is inside W2. Suppose W2 is not a hole !!!!\n//=======================================================================\n\nstatic Standard_Boolean isInside(const TopoDS_Face& F,\n                                 const TopoDS_Wire& W1,\n                                 const TopoDS_Wire& W2)\n{\n  // make a face with wire W2\n  BRep_Builder B;\n  TopoDS_Shape aLocalShape = F.EmptyCopied();\n  TopoDS_Face newFace = TopoDS::Face(aLocalShape);\n  B.Add(newFace,W2);\n\n  // get any 2d point of W1\n  TopExp_Explorer exp(W1,TopAbs_EDGE);\n  if (BRep_Tool::Degenerated( TopoDS::Edge( exp.Current() )))\n    exp.Next();\n  const TopoDS_Edge& e = TopoDS::Edge(exp.Current());\n  Standard_Real f,l;\n  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(e,F,f,l);\n  gp_Pnt2d pt2d(C2d->Value( 0.5 * ( f + l )));\n\n  BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());\n  return (classif.Perform(pt2d) == TopAbs_IN);\n}\n\n//=======================================================================\n//function : NewWires\n//purpose  : Returns the list of wires performed.\n//           can be an empty list.\n//=======================================================================\n\nconst TopTools_ListOfShape&  Partition_Loop2d::NewWires() const\n{\n  return myNewWires;\n}\n\n//=======================================================================\n//function : NewFaces\n//purpose  : Returns the list of faces.\n//Warning  : The method <WiresToFaces> as to be called before.\n//           can be an empty list.\n//=======================================================================\n\nconst TopTools_ListOfShape&  Partition_Loop2d::NewFaces() const\n{\n  return myNewFaces;\n}\n\n//=======================================================================\n//function : findEqual\n//purpose  : move wires form <WL> to <EqWL> pairs of wires build of the\n//           same edges\n//=======================================================================\n\nstatic void findEqual (TopTools_ListOfShape& WL,\n                       TopTools_DataMapOfShapeShape& EqWM,\n                       const TopoDS_Face& F)\n{\n  TopTools_ListIteratorOfListOfShape it1, it2;\n  Standard_Integer i,j;\n  TColStd_MapOfInteger IndMap;\n  for (it1.Initialize(WL), i=1;  it1.More();  it1.Next(), i++) {\n\n    if (IndMap.Contains(i)) continue;\n    const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value());\n\n    for (it2.Initialize(WL), j=1;  it2.More();  it2.Next(), j++) {\n\n      if (j <= i || IndMap.Contains(j)) continue;\n\n      TopTools_IndexedMapOfShape EdgesMap;\n      TopExp::MapShapes (Wire1, TopAbs_EDGE, EdgesMap);\n\n      const TopoDS_Shape& Wire2 = it2.Value();\n      TopoDS_Iterator itE ( Wire2);\n      for (; itE.More(); itE.Next()) {\n        if ( !EdgesMap.Contains( itE.Value()) )\n          break;\n      }\n      if (!itE.More()) { // all edges are same\n        if (isHole( Wire1, F)) {\n          EqWM.Bind ( Wire1, Wire2 );\n        }\n        else {\n          EqWM.Bind ( Wire2, Wire1 );\n        }\n        IndMap.Add(i);\n        IndMap.Add(j);\n        break;\n      }\n    }\n  }\n  // clear WL\n  it1.Initialize(WL);\n  i=1;\n  while (it1.More()) {\n    if (IndMap.Contains(i))\n      WL.Remove(it1); // next node becomes current and with Next() we would miss it\n    else\n      it1.Next();\n    i++;\n  }\n}\n\n//=======================================================================\n//function : classify\n//purpose  : bind to a wire a list of internal wires\n//=======================================================================\n\nstatic void classify(const TopTools_DataMapOfShapeShape& EqWM,\n                     BRepAlgo_AsDes& OuterInner,\n                     const TopoDS_Face& F)\n{\n  TopTools_DataMapIteratorOfDataMapOfShapeShape it1, it2;\n\n  for (it1.Initialize(EqWM);  it1.More();  it1.Next()) {\n    // find next after it1.Value()\n    for (it2.Initialize(EqWM);  it2.More();  it2.Next())\n      if (it1.Value().IsSame( it2.Value() ))\n      {\n        it2.Next();\n        break;\n      }\n    for ( ;  it2.More();  it2.Next()) {\n      const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value() );\n      const TopoDS_Wire& Wire2 = TopoDS::Wire( it2.Value() );\n      if (isInside(F, Wire1, Wire2))\n        OuterInner.Add (Wire2, Wire1);\n      else if (isInside(F, Wire2, Wire1))\n        OuterInner.Add (Wire1, Wire2);\n    }\n  }\n}\n//=======================================================================\n//function : WiresToFaces\n//purpose  : Build faces from the wires result.\n//           <EdgeImage> serves to  find  original edge by new\n//           one. <Section> contains edges resulting from face\n//           intersections\n//=======================================================================\n\nvoid  Partition_Loop2d::WiresToFaces(const BRepAlgo_Image& )\n{\n  Standard_Integer nbW = myNewWires.Extent() + myInternalWL.Extent();\n  if (nbW==0)\n    return;\n\n  BRepAlgo_FaceRestrictor FR;\n  FR.Init (myFace,Standard_False);\n\n  // FaceRestrictor is instable in rather simple cases\n  // (ex. a single face of bellecoque.brep splited by 10 planes:\n  // sometimes 1-2 faces are missing ).\n  // So we use it as less as possible: no holes -> make faces by hands\n\n\n  // are there holes in myFace ?\n  Standard_Boolean hasOldHoles = Standard_False;\n  TopoDS_Iterator itOldW (myFace);\n  if ( itOldW.More()) {\n    const TopoDS_Wire& FirstOldWire = TopoDS::Wire( itOldW.Value() );\n    itOldW.Next();\n    hasOldHoles = itOldW.More() || isHole( FirstOldWire, myFace);\n  }\n  if (myInternalWL.IsEmpty() && !hasOldHoles) {\n    // each wire bounds one face\n    BRep_Builder B;\n    TopTools_ListIteratorOfListOfShape itNW (myNewWires);\n    for (; itNW.More(); itNW.Next()) {\n      TopoDS_Face NF = TopoDS::Face ( myFace.EmptyCopied() );\n      B.Add ( NF, itNW.Value() );\n      NF.Orientation( myFaceOri);\n      myNewFaces.Append ( NF );\n    }\n    return;\n  }\n\n  // FaceRestrictor can't classify wires build on all the same edges\n  // and gives incorrect result in such cases (ex. a plane cut into 2 parts by cylinder)\n  // We must make faces of equal wires separately. One of equal wires makes a\n  // hole in a face and should come together with outer wires of face.\n  // The other of a wires pair bounds a face that may have holes in turn.\n\n  // Find equal wires among internal wires\n  TopTools_DataMapOfShapeShape EqWM; // key is a hole part of a pair of equal wires\n  findEqual (myInternalWL, EqWM, myFace);\n\n  if (!EqWM.IsEmpty()) { // there are equal wires\n\n    if (hasOldHoles)\n      myInternalWL.Append( myNewWires ); // an old wire can be inside an equal wire\n\n    // classify equal wire pairs\n    BRepAlgo_AsDes OuterInner;\n    classify (EqWM,OuterInner,myFace);\n\n    // make face of most internal of equal wires and its inner wires\n    while ( !EqWM.IsEmpty()) {\n\n      TopTools_ListOfShape prevHolesL; // list of hole-part of previous most internal equal wires\n\n      // find most internal wires among pairs (key - hole, value - outer part)\n      TopTools_DataMapIteratorOfDataMapOfShapeShape it(EqWM);\n      Standard_Integer nbEqW = EqWM.Extent(); // protection against infinite loop\n      for ( ; it.More(); it.Next()) {\n\n        TopoDS_Wire outerW = TopoDS::Wire ( it.Value() );\n        if (  OuterInner.HasDescendant( outerW ) && // has internal\n             ! OuterInner.Descendant( outerW ).IsEmpty() )\n          continue;\n\n        FR.Add( outerW );\n\n        // add internal wires that are inside of outerW\n        TopTools_ListIteratorOfListOfShape itIW (myInternalWL);\n        while ( itIW.More()) {\n          TopoDS_Wire IW = TopoDS::Wire ( itIW.Value() );\n          if ( isInside (myFace, IW, outerW)) {\n            FR.Add (IW);\n            myInternalWL.Remove( itIW ); // == itIW.Next() !!!\n          }\n          else\n            itIW.Next();\n        }\n\n        // the hole-part of current pair of equal wires will be in the next new face\n        prevHolesL.Append ( it.Key() );\n\n      } // Loop on map of equal pairs searching for innermost wires\n\n      // make faces\n      FR.Perform();\n      if (FR.IsDone()) {\n        for (; FR.More(); FR.Next())\n          myNewFaces.Append(FR.Current());\n      }\n\n      FR.Clear();\n\n      // add hole-parts to FaceRestrictor,\n      // remove them from the EqWM,\n      // remove found wires as internal of resting classified wires\n      Standard_Boolean clearOuterInner =  ( prevHolesL.Extent() < EqWM.Extent() );\n      TopTools_ListIteratorOfListOfShape itPrev (prevHolesL);\n      for (; itPrev.More(); itPrev.Next()) {\n        TopoDS_Wire& Hole = TopoDS::Wire ( itPrev.Value() );\n        FR.Add ( Hole );\n        if (clearOuterInner) {\n          const TopoDS_Wire& outerW = TopoDS::Wire ( EqWM.Find( Hole ) );\n          // Loop on wires including outerW\n          TopTools_ListIteratorOfListOfShape itO( OuterInner.Ascendant( outerW ));\n          for (; itO.More(); itO.Next()) {\n            TopTools_ListOfShape& innerL = OuterInner.ChangeDescendant( itO.Value() );\n            TopTools_ListIteratorOfListOfShape itI (innerL);\n            // Loop on internal wires of current including wire\n            for (; itI.More(); itI.Next())\n              if ( outerW.IsSame( itI.Value() )) {\n                innerL.Remove( itI );   break;\n              }\n          }\n        }\n        EqWM.UnBind ( Hole );\n      }\n\n      if (nbEqW == EqWM.Extent())\n      {\n        // error: pb with wires classification\n#ifdef DEB\n        MESSAGE(\"Partition_Loop2d::WiresToFaces(), pb with wires classification\");\n#endif\n        break;\n      }\n\n    } // while (!EqWM.IsEmpty)\n\n  } //  if !EqWM.IsEmpty()\n\n  myNewWires.Append ( myInternalWL );\n\n  TopTools_ListIteratorOfListOfShape itW (myNewWires);\n  for (; itW.More(); itW.Next()) {\n    TopoDS_Wire& W = TopoDS::Wire ( itW.Value() );\n    FR.Add(W);\n  }\n  FR.Perform();\n  for (; FR.IsDone() && FR.More(); FR.Next())\n    myNewFaces.Append(FR.Current());\n\n\n  TopTools_ListIteratorOfListOfShape itNF (myNewFaces);\n  for (; itNF.More(); itNF.Next())\n    itNF.Value().Orientation( myFaceOri );\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop2d.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop2d.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Loop2d_HeaderFile\n#define _Partition_Loop2d_HeaderFile\n\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopAbs_Orientation_HeaderFile\n#include <TopAbs_Orientation.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_MapOfShape_HeaderFile\n#include <TopTools_MapOfShape.hxx>\n#endif\n#ifndef _Standard_Version_HeaderFile\n#include <Standard_Version.hxx>\n#endif\n\n\nclass TopoDS_Face;\nclass TopoDS_Edge;\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_ListOfShape;\n#endif\nclass BRepAlgo_Image;\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Loop2d  {\n\npublic:\n\n   void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   // Methods PUBLIC\n   // \n   Partition_Loop2d();\n   void Init(const TopoDS_Face& F) ;\n   void AddConstEdge(const TopoDS_Edge& E) ;\n   void AddSectionEdge(const TopoDS_Edge& E) ;\n   void Perform() ;\n   const TopTools_ListOfShape& NewWires() const;\n   void WiresToFaces(const BRepAlgo_Image& EdgeImage) ;\n   const TopTools_ListOfShape& NewFaces() const;\n\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n\n\n   // Fields PRIVATE\n   //\n   TopoDS_Face myFace;\n   TopAbs_Orientation myFaceOri;\n   TopTools_ListOfShape myConstEdges;\n   TopTools_ListOfShape myNewWires;\n   TopTools_ListOfShape myNewFaces;\n   TopTools_ListOfShape myInternalWL;\n   TopTools_MapOfShape mySectionEdges;\n\n\n};\n\n\n\n\n\n// other Inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop2d.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop2d.ixx\n//  Module : GEOM\n\n#include \"Partition_Loop2d.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop2d.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop2d.jxx\n//  Module : GEOM\n\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _BRepAlgo_Image_HeaderFile\n#include <BRepAlgo_Image.hxx>\n#endif\n#ifndef _Partition_Loop2d_HeaderFile\n#include \"Partition_Loop2d.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop3d.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop3d.cxx\n//  Module : GEOM\n\n//using namespace std;\n#include <climits>\n#include \"Partition_Loop3d.ixx\"\n\n#include <TopExp_Explorer.hxx>\n#include <TopExp.hxx>\n#include <BRep_Builder.hxx>\n#include <TopTools_MapOfShape.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopoDS_Shell.hxx>\n#include <TopoDS_Iterator.hxx>\n#include <TopoDS.hxx>\n#include <TopTools_MapIteratorOfMapOfShape.hxx>\n#include <gp_Vec.hxx>\n#include <gp_Pnt.hxx>\n#include <Geom2d_Curve.hxx>\n#include <BRep_Tool.hxx>\n#include <Geom_Surface.hxx>\n#include <gp_Pnt2d.hxx>\n#include <gp_Vec2d.hxx>\n#include <gp_Dir2d.hxx>\n#include <Geom_Curve.hxx>\n\n//=======================================================================\n//function : Partition_Loop3d\n//purpose  : \n//=======================================================================\n\nPartition_Loop3d::Partition_Loop3d()\n{\n}\n\n//=======================================================================\n//function : AddConstFaces\n//purpose  : Add faces of <S> as unique faces in the result.\n//=======================================================================\n\nvoid Partition_Loop3d::AddConstFaces(const TopoDS_Shape& S) \n{\n  TopExp_Explorer FaceExp(S, TopAbs_FACE);\n  for (; FaceExp.More(); FaceExp.Next())\n    myFaces.Append( FaceExp.Current() );\n\n  TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, myEFMap);\n}\n\n//=======================================================================\n//function : AddSectionFaces\n//purpose  : Add faces of <S> as double faces in the result.\n//=======================================================================\n\nvoid Partition_Loop3d::AddSectionFaces(const TopoDS_Shape& S) \n{\n  AddConstFaces( S );\n  AddConstFaces( S.Reversed() );\n}\n\n//=======================================================================\n//function : MakeShells\n//purpose  : Make and return shells. \n//           <AvoidFacesMap> can contain faces that must not be\n//           added to result shells.\n//=======================================================================\n\nconst TopTools_ListOfShape&\n  Partition_Loop3d::MakeShells (const TopTools_MapOfOrientedShape& AvoidFacesMap)\n{\n  myNewShells.Clear();\n  \n  BRep_Builder Builder;\n  TopTools_MapOfShape CheckedEdgesMap;\n  TopTools_MapOfOrientedShape AddedFacesMap;\n  \n  TopTools_ListIteratorOfListOfShape itF (myFaces);\n  for (; itF.More(); itF.Next())\n  {\n    const TopoDS_Shape& FF = itF.Value();\n    if (AvoidFacesMap.Contains( FF ) ||\n\t! AddedFacesMap.Add( FF ) )\n      continue;\n\n    // make a new shell\n    TopoDS_Shell Shell;\n    Builder.MakeShell(Shell);\n    Builder.Add(Shell,FF);\n\n    // clear the maps from shapes added to previous Shell\n    TopTools_MapIteratorOfMapOfShape itEM (CheckedEdgesMap);\n    for (; itEM.More(); itEM.Next()) {\n      TopTools_ListOfShape& FL = myEFMap.ChangeFromKey( itEM.Key());\n      TopTools_ListIteratorOfListOfShape it (FL);\n      while ( it.More()) {\n        if (AddedFacesMap.Contains( it.Value()))\n          FL.Remove( it );\n        else\n          it.Next();\n      }\n    }\n    CheckedEdgesMap.Clear();\n\n    \n    // loop on faces added to Shell; add their neighbor faces to Shell and so on\n    TopoDS_Iterator itAddedF (Shell);\n    for (; itAddedF.More(); itAddedF.Next())\n    {\n      const TopoDS_Face& F = TopoDS::Face (itAddedF.Value());\n\n      // loop on edges of F; find a good neighbor face of F by E\n      TopExp_Explorer EdgeExp(F, TopAbs_EDGE);\n      for (; EdgeExp.More(); EdgeExp.Next())\n      {\n        const TopoDS_Edge& E = TopoDS::Edge( EdgeExp.Current());\n\tif (! CheckedEdgesMap.Add( E ))\n\t  continue;\n\n\t// candidate faces list\n        const TopTools_ListOfShape& FL = myEFMap.ChangeFromKey(E);\n        if (FL.IsEmpty())\n          continue;\n\t// select one of neighbors\n        TopoDS_Face SelF;\n        if (FL.Extent() == 2) {\n          if (! F.IsSame( FL.First() ))\n            SelF = TopoDS::Face( FL.First() );\n          else if (!F.IsSame( FL.Last() ))\n            SelF = TopoDS::Face( FL.Last() );\n        }\n        else {\n          // check if a face already added to Shell shares E\n\t  TopTools_ListIteratorOfListOfShape it (FL);\n          Standard_Boolean found = Standard_False;\n          for (; !found && it.More(); it.Next())\n            if (F != it.Value())\n              found = AddedFacesMap.Contains( it.Value() );\n          if (found)\n            continue;\n          // select basing on geometrical check\n          Standard_Boolean GoodOri, inside;\n          Standard_Real dot, MaxDot = -100;\n          TopTools_ListOfShape TangFL; // tangent faces\n          for ( it.Initialize( FL ) ; it.More(); it.Next()) {\n            const TopoDS_Face& NeighborF = TopoDS::Face( it.Value());\n            if (NeighborF.IsSame( F ))\n              continue;\n            inside = Partition_Loop3d::IsInside( E, F, NeighborF, 1, dot, GoodOri);\n            if (!GoodOri)\n              continue;\n            if (!inside)\n              dot = -dot - 3;\n            if (dot < MaxDot)\n              continue;\n            if ( IsEqual( dot, MaxDot))\n              TangFL.Append(SelF);\n            else\n              TangFL.Clear();\n            MaxDot = dot;\n            SelF = NeighborF;\n          }\n          if (!TangFL.IsEmpty()) {\n            for (it.Initialize( TangFL ); it.More(); it.Next()) {\n              const TopoDS_Face& NeighborF = TopoDS::Face( it.Value());\n              if (Partition_Loop3d:: IsInside( E, SelF , NeighborF, 0, dot, GoodOri))\n                SelF = NeighborF;\n            }\n          }\n        }\n        if (!SelF.IsNull() &&\n\t    AddedFacesMap.Add( SelF ) &&\n\t    !AvoidFacesMap.Contains( SelF )) \n          Builder.Add( Shell, SelF);\n\n      } // loop on edges of F\n      \n    } // loop on the faces added to Shell\n\n    // Shell is complete\n    myNewShells.Append( Shell );\n\n  } // loop on myFaces\n\n\n  // prepare to the next call\n  myFaces.Clear();\n  myEFMap.Clear();\n\n  return myNewShells;\n}\n\n\n\n//=======================================================================\n//function : Normal\n//purpose  : \n//=======================================================================\n\ngp_Vec Partition_Loop3d::Normal(const TopoDS_Edge& E,\n\t\t\t\tconst TopoDS_Face& F)\n{\n  gp_Vec Norm, V1, V2;\n  Standard_Real First, Last;\n  gp_Pnt Ps;\n\n  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last);\n  Handle(Geom_Surface) Sf = BRep_Tool::Surface(F);\n\n  gp_Pnt2d p = C2d->Value( 0.5*(First+Last) );\n  Sf->D1(p.X(), p.Y(), Ps, V1, V2);\n  Norm = V1.Crossed(V2);\n\n  if (F.Orientation() == TopAbs_REVERSED ) \n    Norm.Reverse();\n\n  return Norm;\n}\n\n//=======================================================================\n//function : NextNormal\n//purpose  : find normal to F at point a little inside F near the middle of E\n//warning  : E must be properly oriented in F.\n//=======================================================================\n\nstatic gp_Vec NextNormal(const TopoDS_Edge& E,\n\t\t\t const TopoDS_Face& F)\n{\n  Standard_Real First, Last;\n\n  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last);\n  Handle(Geom_Surface) Sf = BRep_Tool::Surface(F);\n\n  gp_Pnt2d p;\n  gp_Vec2d v;\n  C2d->D1( 0.5*(First+Last), p, v);\n  if (E.Orientation() != F.Orientation())\n    v.Reverse();\n  gp_Dir2d dir( -v.Y(), v.X() ); // dir inside F\n  \n  Standard_Real duv = 1e-6; // this is not Ok and may give incorrect result if\n  // resolutionUV of compared faces is very different. To have a good result,\n  //it is necessary to get normal to faces at points equidistant from E in 3D\n  \n  p.SetX( p.X() + dir.X()*duv );\n  p.SetY( p.Y() + dir.Y()*duv );\n  \n  gp_Pnt Ps;\n  gp_Vec Norm, V1, V2, VV1, VV2;\n  Sf->D1( p.X(), p.Y(), Ps, V1, V2);\n  Norm = V1.Crossed(V2);\n\n  if (F.Orientation() == TopAbs_REVERSED ) \n    Norm.Reverse();\n\n  return Norm;\n}\n\n\n//=======================================================================\n//function : FindEinF\n//purpose  : find E in F\n//=======================================================================\n\nstatic TopoDS_Edge FindEinF(const TopoDS_Edge& E,\n\t\t\t    const TopoDS_Face& F)\n{\n  TopExp_Explorer expl (F, TopAbs_EDGE);\n  for (; expl.More(); expl.Next()) \n    if( E.IsSame( expl.Current() ))\n      return TopoDS::Edge(expl.Current());\n  TopoDS_Edge nullE;\n  return nullE;\n}\n\n//=======================================================================\n//function : IsInside\n//purpose  : check if <F2> is inside <F1> by edge <E>.\n//           if <CountDot>, compute <Dot>: scalar production of\n//           normalized  vectors  pointing  inside  faces,  and\n//           check if faces are oriented well for sewing\n//=======================================================================\n\nStandard_Boolean Partition_Loop3d::IsInside(const TopoDS_Edge& E,\n\t\t\t\t\t    const TopoDS_Face& F1,\n\t\t\t\t\t    const TopoDS_Face& F2,\n\t\t\t\t\t    const Standard_Boolean CountDot,\n\t\t\t\t\t    Standard_Real& Dot,\n\t\t\t\t\t    Standard_Boolean& GoodOri) \n{\n  Standard_Real f, l;\n  gp_Pnt P;\n  gp_Vec Vc1, Vc2, Vin1, Vin2, Nf1, Nf2;\n  Handle(Geom_Curve) Curve = BRep_Tool::Curve(E,f,l);\n  Curve->D1( 0.5*(f + l), P, Vc2);\n  TopoDS_Edge E1, E2 = FindEinF (E, F2);\n  if (E2.Orientation() == TopAbs_REVERSED ) Vc2.Reverse();\n\n  Nf1 = Normal(E,F1);\n  Nf2 = Normal(E,F2);\n\n  Standard_Real sin =\n    Nf1.CrossSquareMagnitude(Nf2) / Nf1.SquareMagnitude() / Nf2.SquareMagnitude();\n  Standard_Boolean tangent = sin < 0.001;\n\n  Standard_Boolean inside = 0;\n  if (tangent) {\n    E1 = FindEinF (E, F1);\n    gp_Vec NNf1 = NextNormal(E1,F1);\n    gp_Vec NNf2 = NextNormal(E2,F2);\n    Vin2 = NNf2.Crossed(Vc2);\n    inside = Vin2 * NNf1 < 0;\n  }\n  else {\n    Vin2 = Nf2.Crossed(Vc2);\n    inside = Vin2 * Nf1 < 0;\n  }\n  \n  if (!CountDot) return inside;\n\n  if (tangent)\n    Vin2 = Nf2.Crossed(Vc2);\n  else\n    E1 = FindEinF (E, F1);\n    \n  Vc1 = Vc2;\n  if (E1.Orientation() != E2.Orientation()) \n    Vc1.Reverse();\n  Vin1 = Nf1.Crossed(Vc1);\n\n  if (tangent) {\n    Standard_Real N1N2 = Nf1 * Nf2;\n    GoodOri = (Vin2 * Vin1 < 0) ? N1N2 > 0 : N1N2 < 0;\n  }\n  else {\n    Standard_Real V1N2 = Vin1 * Nf2;\n    GoodOri = ( inside ? V1N2 <= 0 : V1N2 >= 0);\n  }\n\n  Vin1.Normalize();\n  Vin2.Normalize();\n  \n  Dot = Vin2 * Vin1;\n  \n  return inside;\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop3d.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop3d.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Loop3d_HeaderFile\n#define _Partition_Loop3d_HeaderFile\n\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_IndexedDataMapOfShapeListOfShape_HeaderFile\n#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>\n#endif\n#ifndef _Standard_Boolean_HeaderFile\n#include <Standard_Boolean.hxx>\n#endif\n#ifndef _Standard_Real_HeaderFile\n#include <Standard_Real.hxx>\n#endif\n#ifndef _Standard_Version_HeaderFile\n#include <Standard_Version.hxx>\n#endif\n\n#if OCC_VERSION_HEX < 0x070000\n#else\n   #include <TopTools_ShapeMapHasher.hxx>\n   #include <TopTools_MapOfOrientedShape.hxx>\n#endif\n\nclass TopoDS_Shape;\n\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_ListOfShape;\n   class TopTools_MapOfOrientedShape;\n#endif\n\nclass TopoDS_Edge;\nclass TopoDS_Face;\nclass gp_Vec;\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Loop3d  {\n\npublic:\n\n   void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   // Methods PUBLIC\n   // \n   Partition_Loop3d();\n   void AddConstFaces(const TopoDS_Shape& S) ;\n   void AddSectionFaces(const TopoDS_Shape& S) ;\n   const TopTools_ListOfShape& MakeShells(const TopTools_MapOfOrientedShape& AvoidFacesMap) ;\n   static  Standard_Boolean IsInside(const TopoDS_Edge& E,const TopoDS_Face& F1,const TopoDS_Face& F2,const Standard_Boolean CountDot,Standard_Real& Dot,Standard_Boolean& GoodOri) ;\n   static  gp_Vec Normal(const TopoDS_Edge& E,const TopoDS_Face& F) ;\n\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n\n\n   // Fields PRIVATE\n   //\n   TopTools_ListOfShape myNewShells;\n   TopTools_ListOfShape myFaces;\n   TopTools_IndexedDataMapOfShapeListOfShape myEFMap;\n\n\n};\n\n\n\n\n\n// other Inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop3d.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop3d.ixx\n//  Module : GEOM\n\n#include \"Partition_Loop3d.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Loop3d.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Loop3d.jxx\n//  Module : GEOM\n\n#ifndef _TopoDS_Shape_HeaderFile\n#include <TopoDS_Shape.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_MapOfOrientedShape_HeaderFile\n#include <TopTools_MapOfOrientedShape.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _TopoDS_Face_HeaderFile\n#include <TopoDS_Face.hxx>\n#endif\n#ifndef _gp_Vec_HeaderFile\n#include <gp_Vec.hxx>\n#endif\n#ifndef _Partition_Loop3d_HeaderFile\n#include \"Partition_Loop3d.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Spliter.cxx",
    "content": "#ifdef OCCGEOMETRY\n\n//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Spliter.cxx\n//  Author : Benedicte MARTIN\n//  Module : GEOM\n//  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Spliter.cxx,v 1.7 2008/03/31 14:20:28 wabro Exp $\n\n//using namespace std;\n#include <climits>\n#include \"Partition_Inter2d.hxx\"\n#include \"Partition_Inter3d.hxx\"\n#include \"Partition_Loop2d.hxx\"\n#include \"Partition_Loop3d.hxx\"\n#include \"Partition_Spliter.ixx\"\n\n#include \"utilities.h\"\n\n#include <Precision.hxx>\n#include <TopAbs_Orientation.hxx>\n#include <TopExp.hxx>\n#include <TopExp_Explorer.hxx>\n\n#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>\n#include <TopTools_DataMapOfShapeListOfShape.hxx>\n#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>\n#include <TopTools_IndexedMapOfShape.hxx>\n#include <TopTools_ListIteratorOfListOfShape.hxx>\n#include <TopTools_ListOfShape.hxx>\n#include <TopTools_MapIteratorOfMapOfShape.hxx>\n#include <TopTools_SequenceOfShape.hxx>\n\n#include <Geom2d_Curve.hxx>\n#include <Geom_Curve.hxx>\n#include <Geom_Surface.hxx>\n#include <Geom_TrimmedCurve.hxx>\n#include <gp_Pnt.hxx>\n#include <gp_Pnt2d.hxx>\n#include <gp_Vec.hxx>\n\n#include <TopoDS.hxx>\n#include <TopoDS_Compound.hxx>\n#include <TopoDS_Edge.hxx>\n#include <TopoDS_Face.hxx>\n#include <TopoDS_Iterator.hxx>\n#include <TopoDS_Shell.hxx>\n#include <TopoDS_Solid.hxx>\n#include <TopoDS_Vertex.hxx>\n#include <TopoDS_Wire.hxx>\n\n#include <BRepBndLib.hxx>\n#include <BRepClass3d_SolidClassifier.hxx>\n#include <BRepLib.hxx>\n#include <BRep_Tool.hxx>\n\n#include <Extrema_ExtPC.hxx>\n#include <GeomAdaptor_Curve.hxx>\n#include <TopOpeBRepTool_CurveTool.hxx>\n\n#ifdef DEB\n//# define PART_PERF\n#endif\n\n#ifdef PART_PERF\n# include <OSD_Chronometer.hxx>\n#endif\n\n//=======================================================================\n//function : isClosed\n//purpose  : check id a shape is closed, ie is a solid or a closed shell\n//=======================================================================\n\nstatic Standard_Boolean isClosed(const TopoDS_Shape& theShape)\n{\n  Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);\n\n  if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {\n    TopTools_IndexedDataMapOfShapeListOfShape MEF;\n    TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);\n    for (Standard_Integer i=1;  isClosed && i<=MEF.Extent();  ++i)\n      isClosed = ( MEF(i).Extent() != 1 );\n  }\n  \n  return isClosed;\n}\n\n//=======================================================================\n//function : Partition_Spliter\n//purpose  : constructor\n//=======================================================================\n\nPartition_Spliter::Partition_Spliter()\n{\n  myAsDes = new BRepAlgo_AsDes;\n  Clear();\n}\n\n//=======================================================================\n//function : AddTool\n//purpose  : add cutting tool that will _NOT_ be in result\n//=======================================================================\n\nvoid Partition_Spliter::AddTool(const TopoDS_Shape& S)\n{\n  if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid\n    TopoDS_Iterator it (S);\n    for (; it.More(); it.Next())\n    {\n      AddTool( it.Value());\n      myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape\n    }\n    return;\n  }\n\n  for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next())\n  {\n    myMapTools.Add(exp.Current());\n    myFaceShapeMap.Bind( exp.Current(), S );\n  }\n  if (isClosed( S ))\n    myClosedShapes.Add( S );\n}\n\n//=======================================================================\n//function : AddShape\n//purpose  : add object Shape to be splited\n//=======================================================================\n\nvoid Partition_Spliter::AddShape(const TopoDS_Shape& S)\n{\n  if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid\n    TopoDS_Iterator it (S);\n    for (; it.More(); it.Next())\n    {\n      AddShape( it.Value());\n      myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape\n    }\n    return;\n  }\n\n  TopExp_Explorer exp(S,TopAbs_FACE);\n  if (!exp.More()) { // do not split edges and vertices\n    //myBuilder.Add( myShape, S );\n    return;\n  }\n\n  Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S\n  for (; exp.More(); exp.Next()) {\n    const TopoDS_Shape & aFace = exp.Current();\n    if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object\n      myFaceShapeMap.Bind( aFace, S );\n    if (myMapFaces.Add( aFace ))\n      myImagesFaces.SetRoot( aFace );\n  }\n\n  if (nbFacesBefore == myMapFaces.Extent())\n    return;\n\n  // solids must be processed before all\n  if (S.ShapeType() == TopAbs_SOLID)\n    myListShapes.Prepend(S);\n  else\n    myListShapes.Append(S);\n\n  if (isClosed( S ))\n    myClosedShapes.Add( S );\n\n}\n\n//=======================================================================\n//function : Shape\n//purpose  : return resulting compound\n//=======================================================================\n\nTopoDS_Shape Partition_Spliter::Shape() const\n{\n  return myShape;\n}\n\n//=======================================================================\n//function : Clear\n//purpose  : clear fields\n//=======================================================================\n\nvoid Partition_Spliter::Clear()\n{\n  myDoneStep = TopAbs_SHAPE;\n  \n  myListShapes.Clear();\n  myMapFaces.Clear();\n  myMapTools.Clear();\n  myEqualEdges.Clear();\n  myNewSection.Clear();\n  myClosedShapes.Clear();\n  mySharedFaces.Clear();\n  myWrappingSolid.Clear();\n  myFaceShapeMap.Clear();\n  \n  myInternalFaces.Clear();\n  myIntNotClFaces.Clear();\n  \n  myAsDes->Clear();\n  myImagesFaces.Clear();\n  myImagesEdges.Clear();\n  myImageShape.Clear();\n  \n  //  myInter3d = Partition_Inter3d(myAsDes);\n  Partition_Inter3d hinter3d (myAsDes);\n  myInter3d = hinter3d;\n  \n  myAddedFacesMap.Clear();\n\n}\n\n//=======================================================================\n//function : Compute\n//purpose  : produce a result\n//=======================================================================\n\nvoid Partition_Spliter::Compute(const TopAbs_ShapeEnum Limit)\n{\n  if ((Limit != TopAbs_SHAPE && myDoneStep == Limit) ||\n      (Limit == TopAbs_SHAPE && myDoneStep == TopAbs_SOLID))\n    return;\n  \n  myBuilder.MakeCompound( myShape );\n  \n  TopTools_MapIteratorOfMapOfShape it;\n  TopTools_ListIteratorOfListOfShape itl;\n  TopExp_Explorer exp;\n\n#ifdef PART_PERF\n  OSD_Chronometer aCron;\n#endif\n\n  if (myDoneStep > TopAbs_VERTEX) {\n\n    TopTools_ListOfShape aListFaces;\n    aListFaces = myImagesFaces.Roots();\n    for (it.Initialize(myMapTools); it.More(); it.Next())\n      aListFaces.Append(it.Key());\n\n#ifdef PART_PERF\n    aCron.Start();\n#endif\n\n    //-----------------------------------------------\n    // Intersection between faces\n    //-----------------------------------------------\n    // result is in myAsDes as a map Face - list of new edges;\n    // special care is done for section edges, same domain faces and vertices:\n    // data about them is inside myInter3d\n    myInter3d.CompletPart3d(aListFaces, myFaceShapeMap);\n\n#ifdef PART_PERF\n    MESSAGE(\"+++ CompletPart3d()\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n    //-----------------------------------------------\n    // Intersection of edges\n    //-----------------------------------------------\n\n    // add tool faces which must be reconstructed to myMapFaces too\n    FindToolsToReconstruct();\n\n#ifdef PART_PERF\n    MESSAGE(\"+++ FindToolsToReconstruct()\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n\n    // add existing vertices to edges of object faces in myAsDes\n    TopTools_MapOfShape DoneEM;\n    for ( it.Initialize(myMapFaces); it.More(); it.Next()) {\n      const TopoDS_Shape& F  = it.Key();\n      TopoDS_Face FForward = TopoDS::Face(F.Oriented(TopAbs_FORWARD));\n      for (exp.Init(FForward,TopAbs_EDGE); exp.More(); exp.Next()) {\n        const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );\n        myAsDes->Add(FForward,E);\n        if (DoneEM.Add(E)) {\n          TopoDS_Iterator itV(E);\n          for (; itV.More(); itV.Next()) {\n            const TopoDS_Vertex& V = TopoDS::Vertex( itV.Value());\n            myAsDes->Add(E, myInter3d.ReplaceSameDomainV( V, E ));\n          }\n        }\n      }\n    }\n\n    // intersect edges that are descendants of a face in myAsDes\n    TopTools_MapOfShape& Modif = myInter3d.TouchedFaces();\n    for ( it.Initialize(Modif); it.More(); it.Next()) {\n      const TopoDS_Face& F  = TopoDS::Face(it.Key());\n      Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges());\n    }\n    // now myAsDes contains also new vertices made at edge intersection as\n    // descendant of edges both new and old\n\n    myDoneStep = TopAbs_VERTEX;\n    \n#ifdef PART_PERF\n    MESSAGE(\"+++ CompletPart2d()\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n  } //   if (myDoneStep > TopAbs_VERTEX)\n  \n  if (Limit == TopAbs_VERTEX) {\n    // add new vertices to myShape\n    for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {\n      if (! myAsDes->HasDescendant( it.Key() ))\n        continue;\n      itl.Initialize( myAsDes->Descendant( it.Key() ));\n      for (; itl.More(); itl.Next()) \n        myBuilder.Add ( myShape, itl.Value() );\n    }\n    return;\n  }\n  \n\n  if (myDoneStep > TopAbs_EDGE) {\n\n    //-----------------------------------------------\n    //-----------------------------------------------\n    // ------- Reconstruction of all the edges.------\n    //-----------------------------------------------\n    //-----------------------------------------------\n\n    // ==============\n    // cut new edges\n    // ==============\n    TopTools_ListOfShape LSE; // all edge splits\n    for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) {\n\n      TopoDS_Vertex V1,V2;\n      TopoDS_Edge EE = TopoDS::Edge(it.Key());\n\n      TopTools_ListOfShape aListV, aListF;\n      aListV = myAsDes->Descendant(EE); // intersection vertices\n      aListF = myAsDes->Ascendant(EE);  // intersected faces\n\n      if (aListV.IsEmpty())\n        continue;  // new edge does not intersect any other edge\n\n      // Add end vertices to new edges only if \n      // one face is Tool and the other is Shape\n      Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() );\n      Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() );\n      if (isTool1 || isTool2)\n      {\n        TopExp::Vertices(EE,V1,V2);\n\tStandard_Real Tol = Max (BRep_Tool::Tolerance( V1 ),\n\t\t\t\t BRep_Tool::Tolerance( V2 ));\n\n        gp_Pnt P1 = BRep_Tool::Pnt(V1);\n        gp_Pnt P2 = BRep_Tool::Pnt(V2);\n        Standard_Boolean AddV1 = Standard_True;\n        Standard_Boolean AddV2 = Standard_True;\n\n        // add only if there is no intersection at end vertex\n        for (itl.Initialize(aListV); itl.More(); itl.Next()) {\n          const TopoDS_Vertex& Ve = TopoDS::Vertex(itl.Value()) ;\n          Standard_Real Tol2 = Max ( Tol, BRep_Tool::Tolerance( Ve ));\n          Tol2 *= Tol2;\n          gp_Pnt P = BRep_Tool::Pnt(Ve);\n          if (AddV1 && P.SquareDistance(P1) <= Tol2)\n            AddV1 = Standard_False;\n\n          if (AddV2 && P.SquareDistance(P2) <= Tol2) \n            AddV2 = Standard_False;\n        }\n\n        if (AddV1) {\n          aListV.Append(V1);\n          myAsDes->Add(EE,V1);\n        }\n\n        if (AddV2) {\n          aListV.Append(V2);\n          myAsDes->Add(EE,V2);\n        }\n      }\n\n      // cut new edges\n      Standard_Integer NbV=aListV.Extent() ;\n      if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) {\n        TopTools_ListOfShape LNE;\n        MakeEdges (EE,aListV, LNE);\n        myImagesEdges.Bind(EE,LNE);\n\tLSE.Append( LNE );\n      }\n    }\n\n    // ==============\n    // cut old edges\n    // ==============\n    for ( it.Initialize(myMapFaces); it.More(); it.Next()) {\n      for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) {\n        const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() );\n        if ( myImagesEdges.HasImage( EE ))\n          continue;\n        TopTools_ListOfShape  LNE;\n        const TopTools_ListOfShape& aListVV = myAsDes->Descendant(EE);\n        MakeEdges (EE, aListVV, LNE);\n        myImagesEdges.Bind(EE,LNE);\n\tLSE.Append( LNE );\n      }\n    }\n#ifdef PART_PERF\n    MESSAGE(\"+++ Cut Edges\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n\n    // process same domain section edges\n    MergeEqualEdges( LSE );\n    \n    myDoneStep = TopAbs_EDGE;\n    \n#ifdef PART_PERF\n    MESSAGE(\"+++ MergeEqualEdges()\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n  }  //   if (myDoneStep > TopAbs_EDGE) \n\n  if (Limit == TopAbs_EDGE) {\n    // add splits of old edges\n    TopTools_ListIteratorOfListOfShape itNE;\n    for (itl.Initialize( myListShapes );itl.More();itl.Next()) {\n      if (myMapTools.Contains( itl.Value() ))\n        continue; // skip tool faces\n      for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) {\n\titNE.Initialize( myImagesEdges.Image( exp.Current() ));\n\tfor ( ; itNE.More(); itNE.Next())\n\t  myBuilder.Add ( myShape, itNE.Value() );\n      }\n    }\n    // add splits of new edges\n    for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {\n      itNE.Initialize( myImagesEdges.Image( it.Key() ));\n      for (; itNE.More(); itNE.Next())\n        myBuilder.Add ( myShape, itNE.Value() );\n    }\n    return;\n  }\n  \n  \n  //-----------------------------------------------\n  // split faces\n  //-----------------------------------------------\n\n  if (myDoneStep > TopAbs_FACE) {\n    \n    for (itl.Initialize(myListShapes);itl.More();itl.Next()) {\n      TopoDS_Shape FacesComp = MakeFaces ( itl.Value());\n      // there is a cunning here: myImagesFaces keeps faces made by Loop2d\n      // but some of them may be replaced with splits of same domain face\n      // and myImageShape keeps ultimate result\n      myImageShape.Bind( itl.Value(), FacesComp );\n    }\n    \n    myDoneStep = TopAbs_FACE;\n#ifdef PART_PERF\n    MESSAGE(\"+++ MakeFaces()\");\n    aCron.Show( cout );\n    aCron.Reset();\n    aCron.Start();\n#endif\n  }\n  \n  if (Limit == TopAbs_WIRE ||\n      Limit == TopAbs_FACE)   {\n    for (itl.Initialize(myListShapes);itl.More();itl.Next()) {\n      if ( myMapTools.Contains( itl.Value() ))\n\tcontinue; // no result needed for a tool face\n      const TopoDS_Shape& FacesComp = myImageShape.Image( itl.Value() ).First();\n      for ( exp.Init( FacesComp, Limit); exp.More(); exp.Next())\n\tmyBuilder.Add ( myShape, exp.Current());\n    }\n    return;\n  }\n\n  \n  //-----------------------------------------------\n  // split and add solids and shells\n  //-----------------------------------------------\n\n  Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE ||\n\t\t\t\t Limit < TopAbs_SHELL);\n  for (itl.Initialize(myListShapes);itl.More();itl.Next())\n  {\n    const TopoDS_Shape & S = itl.Value();\n    if (S.ShapeType() > TopAbs_SHELL)\n      continue;\n\n    TopTools_ListOfShape NSL; // new shape list\n    MakeShells (S , NSL);\n    if (makeSolids && S.ShapeType() == TopAbs_SOLID )\n      MakeSolids( S, NSL );\n\n    // store new shells or solids\n    TopTools_ListIteratorOfListOfShape itNSL (NSL);\n    for ( ; itNSL.More(); itNSL.Next()) \n      myBuilder.Add (myShape, itNSL.Value());\n  }\n#ifdef PART_PERF\n    MESSAGE(\"+++ MakeShells()\");\n    aCron.Show( cout );\n#endif\n\n  //-----------------------------------------------\n  // add split faces\n  //-----------------------------------------------\n\n  for (itl.Initialize(myListShapes);itl.More();itl.Next())\n  {\n    const TopoDS_Shape & S = itl.Value();\n    if (S.ShapeType() != TopAbs_FACE ||\n        myMapTools.Contains( S ))\n      continue; \n    TopoDS_Iterator itS( myImageShape.Image(S).First() );\n    for (; itS.More(); itS.Next())\n      if (! myAddedFacesMap.Contains( itS.Value() ))\n        myBuilder.Add (myShape, itS.Value());\n  }\n\n  myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL;\n  \n}\n\n//=======================================================================\n//function : MakeSolids\n//purpose  : make solids out of Shells\n//=======================================================================\n\nvoid Partition_Spliter::MakeSolids(const TopoDS_Shape &   theSolid,\n                                   TopTools_ListOfShape & theShellList)\n{\n  // for a solid wrapping other shells or solids without intersection,\n  // it is necessary to find shells making holes in it\n\n  TopTools_ListOfShape aNewSolids; // result\n  TopTools_ListOfShape aHoleShells;\n  TopoDS_Shape anInfinitePointShape;\n\n  Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid );\n  if (!isWrapping && !theShellList.IsEmpty())\n  {\n    // check if theSolid initially has internal shells\n    TopoDS_Iterator aShellExp (theSolid);\n    aShellExp.Next();\n    isWrapping = aShellExp.More();\n  }\n  \n  TopTools_ListIteratorOfListOfShape aShellIt(theShellList);\n  for ( ; aShellIt.More(); aShellIt.Next())\n  {\n    const TopoDS_Shape & aShell = aShellIt.Value();\n\n    // check if a shell is a hole\n    if (isWrapping && IsInside (anInfinitePointShape, aShell))\n      aHoleShells.Append( aShell );\n    else\n    {\n      // make a solid from a shell\n      TopoDS_Solid Solid;\n      myBuilder.MakeSolid( Solid );\n      myBuilder.Add (Solid, aShell);\n\n      aNewSolids.Append (Solid);\n    }\n  }\n\n  // find an outer shell most close to each hole shell\n  TopTools_DataMapOfShapeShape aInOutMap;\n  for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next())\n  {\n    const TopoDS_Shape & aHole = aShellIt.Value();\n    TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids);\n    for ( ; aSolisIt.More(); aSolisIt.Next())\n    {\n      const TopoDS_Shape & aSolid = aSolisIt.Value();\n      if (! IsInside( aHole, aSolid ))\n        continue;\n\n      if ( aInOutMap.IsBound (aHole))\n      {\n        const TopoDS_Shape & aSolid2 = aInOutMap( aHole );\n        if ( IsInside( aSolid, aSolid2 ))\n        {\n          aInOutMap.UnBind( aHole );\n          aInOutMap.Bind ( aHole, aSolid );\n        }\n      }\n      else\n        aInOutMap.Bind ( aHole, aSolid );\n    }\n\n    // add aHole to a solid\n    if (aInOutMap.IsBound( aHole ))\n      myBuilder.Add ( aInOutMap( aHole ), aHole );\n  }\n\n  theShellList.Clear();\n  theShellList.Append( aNewSolids );\n}\n \n//=======================================================================\n//function : FindFacesInside\n//purpose  : return compound of faces  of other shapes that are\n//           inside <theShape>. \n//           <theShape> is an object shape.\n//           <CheckClosed> makes avoid faces that do not form a\n//           closed shell\n//           <All> makes return already added faces\n//=======================================================================\n\nTopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape,\n\t\t\t\t\t\tconst Standard_Boolean CheckClosed,\n\t\t\t\t\t\tconst Standard_Boolean All)\n{\n  // ================================================\n  // check if internal faces have been already found\n  // ================================================\n  TopExp_Explorer expl;\n  if (myInternalFaces.IsBound( theShape ))\n  {\n    TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape );\n    TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape );\n\n    expl.Init( aIntRemFComp, TopAbs_FACE);\n    if (CheckClosed || !expl.More())\n      return aIntFComp;\n\n    TopoDS_Compound C;\n    myBuilder.MakeCompound( C );\n    // add removed faces\n    for (; expl.More(); expl.Next())\n      myBuilder.Add( C, expl.Current() );\n    // add good internal faces\n    for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next())\n      myBuilder.Add( C, expl.Current() );\n    return C;\n  }\n\n  // ===================================\n  // get data for internal faces search\n  // ===================================\n\n  // compound of split faces of theShape \n  const TopoDS_Shape& CSF = myImageShape.Image(theShape).First();\n\n  TopTools_MapOfShape MSE, MFP;\n  TopTools_DataMapOfShapeListOfShape DMSEFP;\n  TopTools_MapIteratorOfMapOfShape itm;\n  TopTools_ListOfShape EmptyL;\n\n  // MSE filling: map of new section edges of CSF\n  for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) {\n    const TopoDS_Shape & resE = expl.Current() ;\n    if (myNewSection.Contains( resE )) // only new edges\n      MSE.Add(resE);\n  }\n\n  // DMEF: map edge of CSF - faces of CSF\n  TopTools_IndexedDataMapOfShapeListOfShape DMEF;\n  TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF);\n\n  // Fill\n  // 1.  MFP - a map of faces to process: map of resulting faces except\n  // those of theShape; we`ll add to C those of them which are inside CSF\n  // 2.  DMSEFP - edge of MSE => faces of MFP\n  TopTools_ListIteratorOfListOfShape itl;\n  for (itl.Initialize(myListShapes);itl.More();itl.Next()) {\n    const TopoDS_Shape& aShape = itl.Value();\n    if ( theShape.IsSame( aShape )) continue;\n    // fill maps\n    // iterate on split faces of aShape\n    TopoDS_Iterator itF ( myImageShape.Image(aShape).First() );\n    for ( ; itF.More(); itF.Next()) {\n      const TopoDS_Shape& sf = itF.Value();\n      MFP.Add(sf);\n      // iterate on edges of split faces of aShape,\n      // add to DMSEFP edges that are new\n      for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) {\n\tTopoDS_Shape se = expl.Current();\n\tif ( MSE.Contains(se)) {// section edge\n\t  if (!DMSEFP.IsBound(se)) \n\t    DMSEFP.Bind(se,EmptyL);\n\t  DMSEFP(se).Append(sf);\n\t}\n      }\n    }\n  }\n\n  // add tool faces having section edges on faces of theShape to MFP and DMSEFP;\n  // such tool faces need not to be reconstructed and so they are not in myListShapes\n  for (itm.Initialize(myMapTools); itm.More(); itm.Next())\n  {\n    const TopoDS_Shape & aToolFace = itm.Key();\n    if (myMapFaces.Contains( aToolFace ))\n      continue;\n    MFP.Add(aToolFace);\n    for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) {\n      TopoDS_Shape se = expl.Current();\n      if ( MSE.Contains( se )) {// section edge\n        if (!DMSEFP.IsBound( se )) \n          DMSEFP.Bind( se, EmptyL );\n        DMSEFP( se ).Append( aToolFace );\n      }\n    }\n  }\n  \n\n  // ===========================\n  // find faces inside theShape\n  // ===========================\n\n  Standard_Boolean skipAlreadyAdded = Standard_False;\n  Standard_Boolean GoodOri, inside;\n  Standard_Real dot;\n  TopTools_ListOfShape KeepFaces;\n  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;\n\n  // iterate on section edges, check faces of other shapes\n  // sharing section edges and put internal faces to KeepFaces\n  for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) {\n    // a new edge of theShape\n    const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key());\n    // an original edge of which E is a split\n    const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E ));\n    // does OrigE itself splits a face\n    Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE );\n\n    // split faces of other shapes sharing E\n    TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E);\n    itl.Initialize( LSF );\n    while (itl.More()) {\n      // a split faces of other shape\n      TopoDS_Face aFace1 = TopoDS::Face(itl.Value());\n      // remove aFace1 form DMSEFP and MFP\n      LSF.Remove( itl ); // == itl.Next();\n      if (!MFP.Remove( aFace1 ))\n\tcontinue; // was not is MFP ( i.e already checked)\n      // check if aFace1 was already added to 2 shells\n      if (!All &&\n\t  myAddedFacesMap.Contains( aFace1 ) &&\n\t  myAddedFacesMap.Contains( aFace1.Reversed() )) {\n\tskipAlreadyAdded = Standard_True;\n\tcontinue;\n      }\n\n      // find another face which originates from the same face as aFace1:\n      // usually aFace2 is internal if aFace1 is not and vice versa\n\n      TopoDS_Shape anOrigFace = aFace1;\n      if (myImagesFaces.IsImage(aFace1))\n        anOrigFace = myImagesFaces.Root(aFace1);\n      TopoDS_Shape aFace2;\n      if ( !isSectionE ) {\n        while (itl.More()) {\n          aFace2 = itl.Value();\n          if (!MFP.Contains( aFace2 )) {\n            LSF.Remove( itl );\n            continue;\n          }\n          if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 )))\n            break;\n          itl.Next();\n        }\n        if (itl.More()) { // aFace2 found, remove it from maps\n          LSF.Remove( itl );\n          MFP.Remove(aFace2);\n        }\n        else\n          aFace2.Nullify();\n        itl.Initialize( LSF );\n      }\n\n      // check that anOrigFace is not same domain with CSF faces it intersects\n\n      const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E\n      const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First());\n      const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last());\n      Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 );\n      Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 );\n      if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) {\n\tsameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1);\n        if (origF1 == origF2)\n          sameDom2 = sameDom1;\n        else\n          myInter3d.IsSameDomainF( anOrigFace, origF2);\n      }\n      if (sameDom1 && sameDom2)\n\tcontinue;\n      if ((sameDom1 || sameDom2)) {\n\tinside = Partition_Loop3d::IsInside (E,\n\t\t\t\t\t     TopoDS::Face(FL.First()),\n\t\t\t\t\t     TopoDS::Face(FL.Last()),\n\t\t\t\t\t     1, dot, GoodOri);\n\tif (inside || (dot + Precision::Angular() >= 1.0))\n\t  continue; // E is convex between origF1 and origF2 or they are tangent\n      }\n\n\n      // keep one of found faces\n\n      //face of CSF sharing E\n      const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First();\n      // analyse aFace1 state\n      inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1,\n\t\t\t\t\t   1, dot, GoodOri);\n      if (inside && isSectionE)\n      {\n        // aFace1 must be tested with both adjacent faces of CSF\n        const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last();\n        if (aShapeFace2 != aShapeFace)\n          inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1,\n                                               1, dot, GoodOri);\n      }\n\n      // store internal face\n      if (inside)\n        KeepFaces.Append(aFace1);\n\n      else if (!aFace2.IsNull())\n      {\n        if (dot + Precision::Angular() >= 1.0)\n        {\n          // aFace2 state is not clear, it will be analysed alone,\n          // put it back to the maps\n          MFP.Add( aFace2 );\n          LSF.Append( aFace2 );\n        }\n        else\n          KeepFaces.Append(aFace2);\n      }\n    }\n  }\n\n  // ===================================================\n  // add not distributed faces connected with KeepFaces\n  // ===================================================\n\n  // ultimate list of internal faces\n  TopTools_ListOfShape KeptFaces;\n\n  // add to MFP unsplit tool faces as well, they may be connected with\n  // tool faces interfering with theShape\n  for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) {\n    const TopoDS_Shape& aToolFace = itm.Key();\n    if (!myImageShape.HasImage(aToolFace))\n      MFP.Add (aToolFace);\n  }\n\n  if (MFP.IsEmpty())\n    KeptFaces.Append (KeepFaces);\n\n  while (!KeepFaces.IsEmpty())\n  {\n    // KeepEdges : map of edges of faces kept last time\n    TopTools_IndexedMapOfShape KeepEdges;\n    for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) {\n      TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges);\n      KeptFaces.Append( itl.Value() );\n    }\n\n    KeepFaces.Clear();\n\n    // keep faces connected with already kept faces by KeepEdges\n    for ( itm.Initialize(MFP); itm.More(); itm.Next() ) {\n      const TopoDS_Shape& FP = itm.Key();\n      for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) {\n        const TopoDS_Shape& se = expl.Current();\n        if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {\n          KeepFaces.Append(FP);\n          MFP.Remove(FP);\n          break;\n        }\n      }\n    }\n  }\n\n  // ===============================================================\n  // here MFP contains faces outer of theShape and those of shapes\n  // which do not interfere with theShape at all and between which\n  // there may be those wrapped by theShape and whose faces may be\n  // needed to be returned as well\n  // ===============================================================\n\n  Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID);\n  if (All || isSolid)  // All is for sub-result removal\n  {\n    // loop on not used faces; checked faces will be removed from MFP\n    // during the loop\n    for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) {\n      const TopoDS_Shape & aFace = itm.Key();\n\n      // a shape which aFace originates from\n      TopoDS_Shape anOrigShape = GetOriginalShape( aFace );\n\n      // find out if all split faces of anOrigShape are not in MFP\n      // and by the way remove them from MFP\n      Standard_Boolean isAllOut = Standard_True;\n      TopoDS_Shape aSplitFaces = anOrigShape;\n      if (myImageShape.HasImage(anOrigShape))\n        aSplitFaces = myImageShape.Image(anOrigShape).First();\n\n      TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept\n      for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next())\n      {\n        const TopoDS_Shape & aSpFace = expl.Current();\n        // a tool face which became object has image but the whole tool shape has not\n        if (myImageShape.HasImage( aSpFace ))\n        {\n          TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE );\n          for ( ; exF.More(); exF.Next() )\n          {\n            aSplitFaceL.Append( exF.Current() );\n            if ( ! MFP.Remove( exF.Current() ) && isAllOut )\n              // a shared face might be removed from MFP during a prev loop\n              isAllOut = mySharedFaces.Contains( exF.Current() );\n          }\n        }\n        else\n        {\n          aSplitFaceL.Append( aSpFace );\n          if ( ! MFP.Remove( aSpFace ) && isAllOut)\n            // a shared face might be removed from MFP during a prev loop\n            isAllOut = mySharedFaces.Contains( aSpFace );\n        }\n      }\n      itm.Initialize( MFP ); // iterate remaining faces\n      if ( !isAllOut )\n        continue;\n\n      // classify anOrigShape against theShape\n      if (IsInside (anOrigShape, theShape))\n      {\n        if (isSolid && myClosedShapes.Contains( anOrigShape ))\n          // to make a special care at solid reconstruction\n          myWrappingSolid.Add ( theShape );\n\n        // keep faces of an internal shape anOrigShape\n        KeptFaces.Append( aSplitFaceL );\n      }\n    }\n  }\n\n  // ====================================================\n  // check if kept faces form a shell without free edges\n  // ====================================================\n\n  DMEF.Clear();  // edge - kept faces\n  MFP.Clear(); // reuse it for wrong faces\n  if (CheckClosed) {\n    for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) \n      TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF);\n\n    Standard_Integer i, nb = DMEF.Extent();\n    Standard_Boolean isClosed = Standard_False;\n    while (!isClosed) {\n      isClosed = Standard_True;\n      for (i=1;  isClosed && i<=nb;  ++i) {\n        const TopoDS_Shape& E = DMEF.FindKey( i );\n        if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) &&\n            ! MSE.Contains( E ))\n          isClosed = ( DMEF(i).Extent() != 1 );\n      }\n      if (!isClosed) {\n        const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face\n        MFP.Add( F ); \n        // remove bad face from DMEF\n        for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {\n\t  const TopoDS_Shape& E = expl.Current();\n          TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E );\n          for (itl.Initialize( FL ); itl.More(); itl.Next() ) {\n            if ( F.IsSame( itl.Value() )) {\n              FL.Remove( itl );\n              break;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  // ==============\n  // make a result\n  // ==============\n\n  TopoDS_Compound C;\n  // compound of removed internal faces\n  TopoDS_Compound CNotCl;\n\n  myBuilder.MakeCompound(C);\n  myBuilder.MakeCompound(CNotCl);\n\n  // add to compounds\n  for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )\n  {\n    TopoDS_Shape & aIntFace = itl.Value();\n    if (! MFP.Contains( aIntFace ))\n      myBuilder.Add( C, aIntFace);\n    else\n      myBuilder.Add( CNotCl, aIntFace);\n  }\n\n  if (!skipAlreadyAdded && CheckClosed)\n  {\n    myInternalFaces.Bind( theShape, C );\n    myIntNotClFaces.Bind( theShape, CNotCl );\n  }\n\n  return C;\n}\n\n//=======================================================================\n//function : MakeShell\n//purpose  : split S into compound of shells\n//=======================================================================\n\nvoid Partition_Spliter::MakeShells(const TopoDS_Shape& S,\n                                   TopTools_ListOfShape& NS)\n{\n  Partition_Loop3d ShellMaker;\n  // get compound of split faces of S\n  const TopoDS_Shape& FacesComp = myImageShape.Image(S).First();\n  ShellMaker.AddConstFaces( FacesComp );\n  // add split faces inside S\n  if (myClosedShapes.Contains( S )) {\n    TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True);\n    ShellMaker.AddSectionFaces( InternalFacesComp );\n  }\n  \n  NS = ShellMaker.MakeShells( myAddedFacesMap );\n\n  // Add faces added to new shell to myAddedFacesMap:\n  // avoid rebuilding twice common part of 2 solids.\n  TopTools_ListIteratorOfListOfShape itS(NS);\n  while ( itS.More()) {\n    TopExp_Explorer expF (itS.Value(), TopAbs_FACE);\n    for (; expF.More(); expF.Next())\n      myAddedFacesMap.Add (expF.Current());\n    \n    itS.Next();\n  }\n}\n\n//=======================================================================\n//function : findEqual\n//purpose  : compare edges of EL1 against edges of EL2,\n//           Result is in EMM binding EL1 edges to list of equal edges.\n//           Edges are considered equal only if they have same vertices.\n//           <addSame>==True makes consider same edges as equal\n//           Put in <AllEqMap> all equal edges\n//=======================================================================\n\nstatic void findEqual (const TopTools_ListOfShape& EL1,\n\t\t       const TopTools_ListOfShape& EL2,\n\t\t       const Standard_Boolean addSame,\n\t\t       TopTools_DataMapOfShapeListOfShape& EEM,\n\t\t       TopTools_MapOfShape& AllEqMap)\n{\n  // map vertices to edges for EL2\n  TopTools_DataMapOfShapeListOfShape VEM;\n  TopTools_ListIteratorOfListOfShape itE1, itE2(EL2);\n  TopoDS_Iterator itV;\n  TopTools_ListOfShape emptyL;\n  for (; itE2.More(); itE2.Next()) {\n    for (itV.Initialize( itE2.Value() ); itV.More(); itV.Next()) {\n      const TopoDS_Shape& V = itV.Value(); \n      if (! VEM.IsBound( V ) )\n\tVEM.Bind( V, emptyL);\n      VEM( V ).Append( itE2.Value());\n    }\n  }\n\n  gp_Vec D1, D2;\n  gp_Pnt P;\n  Standard_Real f,l,u,tol;\n  Handle(Geom_Curve) C1, C2;\n  Extrema_ExtPC Extrema;\n  TopoDS_Vertex V1, V2, V3, V4;\n\n  AllEqMap.Clear();\n  \n  for (itE1.Initialize(EL1); itE1.More(); itE1.Next()) {\n    const TopoDS_Edge& E1 = TopoDS::Edge( itE1.Value());\n    if (BRep_Tool::Degenerated( E1 ) || AllEqMap.Contains (E1))\n      continue;\n    TopExp::Vertices( E1, V1, V2 );\n\n    if (VEM.IsBound(V1))\n      itE2.Initialize( VEM(V1) );\n    for (; itE2.More(); itE2.Next()) {\n      const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value());\n      if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2))\n        continue;\n\n      if (E1.IsSame(E2)) {\n\tif (!addSame)\n\t  continue;\n      }\n      else {\n\tTopExp::Vertices( E2, V3, V4);\n\tif (!V2.IsSame(V4) && !V2.IsSame(V3))\n\t  continue;\n\t// E1 and E2 have same vertices\n\t// check D1 at end points.\n        C2 = BRep_Tool::Curve( E2, f,l);\n        C1 = BRep_Tool::Curve( E1, f,l);\n\tu = BRep_Tool::Parameter(V1,E1);\n        C1->D1(u, P, D1);\n\tu = BRep_Tool::Parameter(V1.IsSame(V3) ? V3 : V4, E2);\n\tC2->D1(u, P, D2);\n        D1.Normalize(); D2.Normalize();\n        if (Abs(D1*D2) + Precision::Angular() < 1.0)\n          continue;\n\tif (! V1.IsSame(V2)) {\n\t  u = BRep_Tool::Parameter(V2,E1);\n\t  C1->D1(u, P, D1);\n\t  u = BRep_Tool::Parameter(V2.IsSame(V3) ? V3 : V4, E2);\n\t  C2->D1(u, P, D2);\n\t  D1.Normalize(); D2.Normalize();\n\t  if (Abs(D1*D2) + Precision::Angular() < 1.0)\n\t    continue;\n\t}\n        // check distance at a couple of internal points\n        tol = Max(BRep_Tool::Tolerance(E1),\n                  BRep_Tool::Tolerance(E2));\n        GeomAdaptor_Curve AC1(C1);\n        Extrema.Initialize(AC1,f,l);\n\tStandard_Boolean ok = Standard_True, hasMin = Standard_False;\n\tBRep_Tool::Range( E2, f, l);\n        Standard_Integer i=1, nbi=3;\n        for (; i<nbi && ok; ++i) {\n          Extrema.Perform( C2->Value( f+(l-f)*i/nbi ));\n          Standard_Integer j=1, nbj=Extrema.NbExt();\n          for (; j<=nbj && ok; ++j) {\n            if (Extrema.IsMin(j)) {\n\t      hasMin = Standard_True;\n\t      // ok = Extrema.Value(j) <= tol;  // V6.3\n\t      ok = Extrema.SquareDistance(j) <= tol;  // V6.5\n\t    }\n          }\n        }\n        if ( !hasMin || !ok)\n          continue;\n      }\n      // bind E2 to E1 in EEM\n      if (!EEM.IsBound(E1)) {\n        EEM.Bind (E1, emptyL);\n\tAllEqMap.Add (E1);\n      }\n      EEM(E1).Append(E2);\n      AllEqMap.Add (E2);\n    }\n  }\n}\n\n//=======================================================================\n//function : MakeFaces\n//purpose  : split faces of S, return compound of new faces\n//=======================================================================\n\nTopoDS_Shape Partition_Spliter::MakeFaces (const TopoDS_Shape& S)\n{\n  TopoDS_Compound C;\n  myBuilder.MakeCompound(C);\n  \n  TopTools_ListIteratorOfListOfShape itl, itNE;\n  \n  TopExp_Explorer exp(S,TopAbs_FACE);\n  for (; exp.More(); exp.Next()) {\n\n    const TopoDS_Face& F = TopoDS::Face(exp.Current());\n\n    TopTools_ListOfShape LNF;\n    \n    if (myImagesFaces.HasImage( F )) {\n      myImagesFaces.LastImage( F, LNF );\n      TopAbs_Orientation oriF = F.Orientation();\n      for ( itl.Initialize( LNF ); itl.More(); itl.Next())\n\titl.Value().Orientation( oriF );\n    }\n    else {\n\n      Partition_Loop2d loops;\n      loops.Init(F);\n\n      TopTools_IndexedMapOfShape EM;\n      TopExp::MapShapes( F, TopAbs_EDGE, EM);\n\n      TopTools_MapOfShape AddedEqualM, EqualSeamM;\n      Standard_Boolean needRebuild = Standard_False;\n\n      // add splits to loops\n\n      // LE: old edges + new unsplit edges\n      const TopTools_ListOfShape& LE = myAsDes->Descendant(F);\n      for (itl.Initialize(LE); itl.More(); itl.Next()) {\n\tconst TopoDS_Edge& E = TopoDS::Edge( itl.Value() );\n\n\tStandard_Boolean isSectionE = myInter3d.IsSectionEdge(E);\n\tStandard_Boolean isNewE = !EM.Contains( E );\n\n\t// LSE: list of split edges\n\tTopTools_ListOfShape LSE;\n\tmyImagesEdges.LastImage(E,LSE); // splits of E or E itself\n\n\tfor (itNE.Initialize(LSE); itNE.More(); itNE.Next()) {\n\n\t  TopoDS_Edge NE = TopoDS::Edge( itNE.Value() );\n\t  Standard_Boolean isSameE = NE.IsSame ( E );\n\t  \n\t  if ( isNewE || isSectionE || !isSameE) {\n\t    if (AddedEqualM.Contains( NE )) {\n              // a seam must be twice in a loop\n              if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE ))\n                continue;\n            }\n\n\t    if (isNewE) {\n\t      if (isSectionE) {\n\t\tif ( ! myInter3d.IsSplitOn( NE, E, F) )\n\t\t  continue;\n\t      }\n\t      else {\n\t\tTopoDS_Vertex V1,V2;\n\t\tTopExp::Vertices(NE,V1,V2);\n\t\tconst TopTools_ListOfShape& EL1 = myAsDes->Ascendant(V1);\n\t\tconst TopTools_ListOfShape& EL2 = myAsDes->Ascendant(V2);\n\t\tif ( EL1.Extent() < 2 && EL2.Extent() < 2 )\n\t\t  continue;\n\t      }\n\t    }\n\t    else {\n\t      NE.Orientation( E.Orientation());\n\t      if (!isSameE) {\n\t\t// orient NE because it may be a split of other edge\n\t\tStandard_Real f,l,u;\n\t\tHandle(Geom_Curve) C3d  = BRep_Tool::Curve( E,f,l );\n\t\tHandle(Geom_Curve) NC3d = BRep_Tool::Curve( NE,f,l);\n\t\tif ( C3d != NC3d) {\n\t\t  gp_Vec D1, ND1;  gp_Pnt P;\n\t\t  TopoDS_Vertex V = TopExp::FirstVertex(NE);\n\t\t  u = BRep_Tool::Parameter(V,NE);\n\t\t  NC3d->D1 (u, P, ND1);\n\t\t  u = BRep_Tool::Parameter(V,E);\n\t\t  C3d ->D1 (u, P, D1);\n\t\t  if (ND1.Dot(D1) < 0)\n\t\t    NE.Reverse();\n\t\t}\n\t      }\n\t    }\n\t    if (myEqualEdges.Contains( NE ))\n              AddedEqualM.Add( NE );\n\n\t    needRebuild = Standard_True;\n\t  }\n\n\t  if (isNewE || isSectionE)\n\t    myNewSection.Add( NE );\n\n\t  if (isNewE) \n\t    loops.AddSectionEdge(NE);\n\t  else\n\t    loops.AddConstEdge(NE);\n\t}\n      }\n\n      //-------------------\n      // Build the faces.\n      //-------------------\n      \n      if (needRebuild) {\n\t\n        loops.Perform();\n        loops.WiresToFaces(myImagesEdges);\n\n        LNF = loops.NewFaces();\n\n        myImagesFaces.Bind(F,LNF);\n\n        // replace the result faces that have already been built\n        // during same domain faces reconstruction done earlier\n        if (myInter3d.HasSameDomainF( F ))\n        {\n          // build map edge to same domain faces: EFM\n          TopTools_IndexedDataMapOfShapeListOfShape EFM;\n          TopTools_MapOfShape SDFM; // avoid doubling\n          itl.Initialize( myInter3d.SameDomain( F ));\n          for (; itl.More(); itl.Next()) {\n            if ( !myImagesFaces.HasImage( itl.Value() ))\n              continue;\n            // loop on splits of a SD face\n            TopTools_ListIteratorOfListOfShape itNF;\n            itNF.Initialize (myImagesFaces.Image( itl.Value() ));\n            for ( ; itNF.More(); itNF.Next()) {\n              TopoDS_Shape SDF = itNF.Value();\n              if (myImagesFaces.HasImage( SDF )) // already replaced\n                SDF = myImagesFaces.Image( SDF ).First();\n              if (SDFM.Add (SDF))\n                TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM);\n            }\n          }\n          // do replace faces in the LNF\n          TopTools_ListOfShape LOF;\n          if ( !EFM.IsEmpty() )\n            itl.Initialize( LNF );\n          while (itl.More()) {\n            const TopoDS_Shape& NF = itl.Value();\n            TopExp_Explorer expE ( NF, TopAbs_EDGE );\n            const TopoDS_Edge& E  = TopoDS::Edge (expE.Current());\n            if (EFM.Contains( E )) {\n              const TopTools_ListOfShape& SDFL = EFM.FindFromKey( E );\n              TopoDS_Shape SDF = SDFL.First();\n              Standard_Boolean GoodOri;\n              Standard_Real dot;\n              Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF),\n                                          1, dot, GoodOri);\n              if (dot < 0)\n              {\n                // NF and SDF are on different side of E\n                if (SDFL.Extent() == 1) {\n                  itl.Next();\n                  continue;\n                }\n                else\n                  SDF = SDFL.Last(); // next face must be on the same side\n              }\n              gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF ));\n              gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF ));\n              if (V1*V2 < 0)\n                SDF.Reverse();\n\n              if (!myImagesFaces.HasImage( NF ))\n                myImagesFaces.Bind( NF, SDF );\n\n              // mySharedFaces is used in FindFacesInside()\n              mySharedFaces.Add( SDF );\n\n              LOF.Prepend ( SDF );\n              LNF.Remove (itl);\n            }\n            else\n              itl.Next();\n          }\n\n          LNF.Append (LOF);\n        }\n      } // if (needRebuild)\n      \n      else {\n\tLNF.Append( F );\n\tmyImagesFaces.Bind(F,LNF);\n      }\n    } // if (myImagesFaces.HasImage( F ))\n\n    // fill the resulting compound\n    for (itl.Initialize(LNF); itl.More(); itl.Next())\n      myBuilder.Add ( C, itl.Value());\n    \n  } // loop on faces of S\n\n  return C;\n}\n\n\n//=======================================================================\n//function : Tri\n//purpose  : \n//=======================================================================\n\nstatic void Tri(const TopoDS_Edge&        E,\n\t\tTopTools_SequenceOfShape& Seq,\n                const Partition_Inter3d & theInter3d)\n{\n  Standard_Boolean Invert   = Standard_True;\n  Standard_Real    U1,U2;\n  TopoDS_Vertex    V1,V2;\n\n  while (Invert) {\n    Invert = Standard_False;\n    for ( Standard_Integer i = 1; i < Seq.Length(); i++) {\n      \n      V1 = TopoDS::Vertex(Seq.Value(i));\n      V2 = TopoDS::Vertex(Seq.Value(i+1));\n      \n      V1.Orientation(TopAbs_INTERNAL);\n      V2.Orientation(TopAbs_INTERNAL);\n      \n      U1 = BRep_Tool::Parameter(V1,E);\n      U2 = BRep_Tool::Parameter(V2,E);\n      \n      if (IsEqual(U1,U2)) {\n        if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 ))\n          Seq.Remove(i+1); // remove V2\n        else\n          Seq.Remove(i);\n\ti--;\n\tcontinue;\n      }\n      if (U2 < U1) {\n\tSeq.Exchange(i,i+1);\n\tInvert = Standard_True;\n      }\n    }\n  }\n}\n\n//=======================================================================\n//function : MakeEdges\n//purpose  : cut E by vertices VOnE, return list of new edges NE\n//=======================================================================\n\nvoid Partition_Spliter::MakeEdges (const TopoDS_Edge& E,\n                                   const TopTools_ListOfShape& VOnE,\n                                   TopTools_ListOfShape& NE   ) const\n{\n  TopoDS_Edge WE = E;\n  WE.Orientation(TopAbs_FORWARD);\n\n  Standard_Real    U1,U2, f, l;\n  TopoDS_Vertex    V1,V2,VF,VL;\n\n  BRep_Tool::Range(WE,f,l);\n  TopExp::Vertices(WE,VF,VL);\n\n  if (VOnE.Extent() < 3) { // do not rebuild not cut edge\n    if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) ||\n        (VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ))  ) {\n      NE.Append( E );\n      return;\n    }\n  }\n\n  TopTools_SequenceOfShape SV;\n  TopTools_ListIteratorOfListOfShape itv(VOnE);\n  TopTools_MapOfOrientedShape VM( VOnE.Extent() );\n  for (; itv.More(); itv.Next())\n    if ( VM.Add( itv.Value() ))\n      SV.Append(itv.Value());\n\n  Tri( WE, SV, myInter3d );\n\n  if (SV.Length() < 3) { // do not rebuild not cut edge\n    if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) ||\n\t( VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() ))  ) {\n      NE.Append( E );\n      return;\n    }\n  }\n\n  Standard_Integer iVer, NbVer = SV.Length();\n\n\n  //----------------------------------------------------------------\n  // Construction of the new edges.\n  //----------------------------------------------------------------\n\n  if (VF.IsSame(VL)) { // closed edge\n    if (NbVer==1) \n      SV.Append( SV.First() );\n    else if (!SV.First().IsSame(SV.Last())) {\n      Standard_Boolean isFirst=0;\n      Standard_Real    minDU = 1.e10;\n      TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU);\n      if (endV.IsSame(SV.First()))\n\tSV.Append(endV);\n      else if (endV.IsSame(SV.Last()))\n\tSV.Prepend(endV);\n      else\n\tMESSAGE (\"END VERTEX IS IN SEQUENCE MIDDLE\");\n    }\n    NbVer = SV.Length();\n  }\n\n  for (iVer=1; iVer < NbVer; iVer++) {\n    V1  = TopoDS::Vertex(SV(iVer));\n    V2  = TopoDS::Vertex(SV(iVer+1));\n    \n    TopoDS_Shape NewEdge = WE.EmptyCopied();\n    V1.Orientation(TopAbs_FORWARD);\n    myBuilder.Add  (NewEdge,V1);\n    V2.Orientation(TopAbs_REVERSED);\n    myBuilder.Add  (NewEdge,V2);\n    \n    if (iVer==1)\n      U1 = f;\n    else \t{\n      V1.Orientation(TopAbs_INTERNAL);\n      U1=BRep_Tool::Parameter(V1,WE);\n    }\n    if (iVer+1 == NbVer)\n      U2 = l;\n    else\t{\n      V2.Orientation(TopAbs_INTERNAL);\n      U2=BRep_Tool::Parameter(V2,WE);\n    }\n    if (Abs(U1-U2) <= Precision::PConfusion()) {\n      MESSAGE( \"MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES\");\n      continue;\n    }\n    TopoDS_Edge EE=TopoDS::Edge(NewEdge);\n    myBuilder.Range (EE,U1,U2);\n\n    TopoDS_Edge NEdge = TopoDS::Edge(NewEdge);\n    myBuilder.SameParameter(NEdge,Standard_False);\n\n    Standard_Real tol = 1.0e-2;\n    Standard_Boolean flag = BRep_Tool::SameParameter(NEdge);\n    if (!flag) {\n      BRepLib::SameParameter(NEdge,tol);\n    }\n    NE.Append(NEdge.Oriented(E.Orientation()));\n  }\n}\n\n//=======================================================================\n//function : MergeEqualEdges\n//purpose  : find equal edges,  choose  ones  to  keep and make\n//           them have pcurves on all faces they are shared by\n//=======================================================================\n\nvoid Partition_Spliter::MergeEqualEdges (const TopTools_ListOfShape& LSE)\n{\n  // find equal edges\n  // map: edge - equal edges\n  TopTools_DataMapOfShapeListOfShape EEM( LSE.Extent() );\n  findEqual (LSE, LSE, 0, EEM, myEqualEdges);\n\n  TopTools_ListOfShape EEL; // list of equal edges\n  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itM (EEM);\n  for ( ; itM.More(); itM.Next()) {\n    EEL = itM.Value();\n    EEL.Append( itM.Key() );\n\n    // choose an edge to keep, section edges have priority\n    TopoDS_Edge EKeep;\n    TopTools_ListIteratorOfListOfShape itEE (EEL);\n    for (; itEE.More(); itEE.Next()) {\n      EKeep = TopoDS::Edge( itEE.Value() );\n      const TopoDS_Edge& EKeepOrig = TopoDS::Edge( myImagesEdges.Root( EKeep ));\n      if (myInter3d.IsSectionEdge( EKeepOrig ))\n        break;\n    }\n\n    // update edge images and build pcurves\n    Standard_Real f,l, tol;\n    for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) {\n      const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() );\n      if ( E.IsSame( EKeep )) \n        continue;\n\n      // 1. build pcurves of the kept edge on faces where replaced edges exist\n      const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E ));\n      TopTools_ListOfShape FL;\n      FL = myAsDes->Ascendant( EReplOrig );\n      Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1;\n      // add faces where the replaced edge is a section edge\n      if (myInter3d.IsSectionEdge( EReplOrig )) {\n        TopTools_ListIteratorOfListOfShape seIt;\n        seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig ));\n        for ( ; seIt.More(); seIt.Next())\n          FL.Append( seIt.Value() );\n      }\n      // loop on faces\n      TopTools_ListIteratorOfListOfShape itF (FL);\n      for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) {\n        const TopoDS_Face& F = TopoDS::Face( itF.Value());\n\n        Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l);\n        if (pc.IsNull()) {\n          Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l);\n          C3d = new Geom_TrimmedCurve( C3d, f,l);\n          pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol);\n          if (pc.IsNull()) {\n            MESSAGE (\" CANNOT BUILD PCURVE \");\n          }\n          myBuilder.UpdateEdge( EKeep, pc, F, tol);\n        }\n\n        if (iFace >= iFirstSectionFace ||\n            !BRep_Tool::IsClosed( EReplOrig, F ))\n          continue;\n\n        // build the second pcurve for a seam\n        TopoDS_Vertex V = TopExp::FirstVertex( EKeep );\n        Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep );\n        Standard_Real Urepl = BRep_Tool::Parameter( V, E );\n\n        TopoDS_Edge EReplRev = E;\n        EReplRev.Reverse();\n        Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l);\n        Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l);\n\n        gp_Pnt2d p1r, p2r, pk;\n        p1r = pcRepl1->Value( Urepl );\n        p2r = pcRepl2->Value( Urepl );\n        pk  = pc->Value( Ukeep );\n\n        // suppose that pk is equal to either p1r or p2r\n        Standard_Boolean isUPeriod =\n          ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() ));\n        Standard_Boolean is1Equal;\n        if (isUPeriod)\n          is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() ));\n        else\n          is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() ));\n\n        Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast\n          ( pc->Translated( pk, is1Equal ? p2r : p1r ) );\n\n        if (E.Orientation() == TopAbs_REVERSED)\n          is1Equal = !is1Equal;\n\n        if (is1Equal)\n          myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol);\n        else\n          myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol);\n\n      } // loop on a Faces where a replaced edge exists\n\n\n      // 2. update edge images according to replacement\n      if (myImagesEdges.HasImage( E ))\n        myImagesEdges.Remove( E );\n      myImagesEdges.Bind( E, EKeep );\n\n    } // loop on a list of equal edges EEL\n  } // loop on a map of equal edges EEM\n}\n\n//=======================================================================\n//function : KeepShapesInside\n//purpose  : remove shapes that are outside of S from result\n//=======================================================================\n\nvoid Partition_Spliter::KeepShapesInside (const TopoDS_Shape& S)\n{\n  TopoDS_Iterator it;\n  if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid\n    for (it.Initialize( S ); it.More(); it.Next())\n      KeepShapesInside( it.Value());\n    return;\n  }\n\n  Standard_Boolean isTool = Standard_False;\n  if (!myImageShape.HasImage( S )) {\n    isTool = CheckTool( S );\n    if (!isTool) return;\n  }\n\n  // build map of internal faces\n  TopTools_IndexedMapOfShape MIF;\n  TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);\n  TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF );\n\n  TopoDS_Compound C;\n  myBuilder.MakeCompound(C);\n\n  TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE;\n  if (!MIF.IsEmpty())\n  {\n    // leave in the result only those shapes having a face in MIF\n    for (it.Initialize( myShape ); it.More(); it.Next()) {\n      const TopoDS_Shape & aResShape = it.Value();\n      TopExp_Explorer expResF( aResShape, TopAbs_FACE );\n      for (; expResF.More(); expResF.Next()) {\n        if ( MIF.Contains( expResF.Current())) {\n          myBuilder.Add( C, aResShape );\n          if (aResShape.ShapeType() < anInternalShapeType)\n            anInternalShapeType = aResShape.ShapeType();\n          break;\n        }\n      }\n    }\n  }\n\n  // may be S was not split by internal faces then it is missing\n  // in myShape, add it\n  if (!isTool &&\n      (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID))\n  {\n    TopTools_IndexedMapOfShape MSF; // map of split faces of S\n    TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF);\n\n    // find a shape having all faces in MSF\n    for (it.Initialize( myShape ); it.More(); it.Next()) {\n      TopExp_Explorer expResF( it.Value(), TopAbs_FACE );\n      for (; expResF.More(); expResF.Next()) {\n        if (! MSF.Contains( expResF.Current())) \n          break;\n      }\n      if (! expResF.More()) {\n        myBuilder.Add( C, it.Value() );\n        break;\n      }\n    }\n  }\n\n  myShape = C;\n}\n\n//=======================================================================\n//function : RemoveShapesInside\n//purpose  : remove shapes that are inside S from result\n//=======================================================================\n\nvoid Partition_Spliter::RemoveShapesInside (const TopoDS_Shape& S)\n{\n  TopoDS_Iterator it;\n  if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid\n    for (it.Initialize( S ); it.More(); it.Next())\n      RemoveShapesInside( it.Value());\n    return;\n  }\n  Standard_Boolean isTool = Standard_False;\n  if (!myImageShape.HasImage( S )) {\n    isTool = CheckTool( S );\n    if (!isTool) return;\n  }\n\n  TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);\n  TopTools_IndexedMapOfShape MIF; // map of internal faces\n  TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF);\n\n  if (MIF.IsEmpty()) return;\n\n  // add to MIF split faces of S\n  if (myImageShape.HasImage(S))\n    TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF);\n\n  // leave in the result only those shapes not having all face in MIF\n  \n  TopoDS_Compound C;\n  myBuilder.MakeCompound(C);\n\n  // RMF : faces of removed shapes that encounter once\n  TopTools_MapOfShape RFM;\n  \n  for (it.Initialize( myShape ); it.More(); it.Next()) {\n    \n    TopExp_Explorer expResF( it.Value(), TopAbs_FACE );\n    for (; expResF.More(); expResF.Next())\n      if (!MIF.Contains( expResF.Current()))\n\tbreak;\n\n    if (expResF.More())\n      // add shape to result\n      myBuilder.Add( C, it.Value() );\n    else \n      // add faces of a removed shape to RFM\n      for (expResF.ReInit(); expResF.More(); expResF.Next()) {\n\tconst TopoDS_Shape& F = expResF.Current();\n\tif ( ! RFM.Remove ( F ))\n\t  RFM.Add( F );\n      }\n  }\n\n  if (!isTool) {\n\n    // rebuild S, it must remain in the result\n\n    Standard_Boolean isClosed = Standard_False;\n    switch (S.ShapeType()) {\n    case TopAbs_SOLID :\n      isClosed = Standard_True; break;\n    case TopAbs_SHELL: {\n      TopTools_IndexedDataMapOfShapeListOfShape MEF;\n      TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF);\n      Standard_Integer i;\n      for (i=1;  isClosed && i<=MEF.Extent();  ++i) \n        isClosed = ( MEF(i).Extent() != 1 );\n      break;\n    }\n    default:\n      isClosed = Standard_False;\n    }\n    if (isClosed) {\n\n      // add to a new shape external faces of removed shapes, ie those in RFM\n\n      TopoDS_Shell Shell;\n      myBuilder.MakeShell( Shell );\n\n      // exclude redundant internal face with edges encountered only once\n      TopTools_IndexedDataMapOfShapeListOfShape MEF;\n      TopTools_MapIteratorOfMapOfShape itF (RFM);\n      for ( ; itF.More(); itF.Next()) \n        TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF);\n\n      // add only faces forming a closed shell\n      for (itF.Reset() ; itF.More(); itF.Next())\n      {\n        TopExp_Explorer expE (itF.Key(), TopAbs_EDGE);\n        for (; expE.More(); expE.Next())\n          if (MEF.FindFromKey(expE.Current()).Extent() == 1)\n            break;\n        if (!expE.More())\n          myBuilder.Add( Shell, itF.Key());\n      }\n\n      if (S.ShapeType() == TopAbs_SOLID) {\n        TopoDS_Solid Solid;\n        myBuilder.MakeSolid( Solid );\n        myBuilder.Add (Solid, Shell);\n        myBuilder.Add (C, Solid);\n      }\n      else\n        myBuilder.Add (C, Shell);\n    }\n    else {\n      if (myImageShape.HasImage( S )) {\n        for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next())\n          myBuilder.Add (C, it.Value());\n      }\n    }\n  }\n  \n  myShape = C;\n}\n\n//=======================================================================\n//function : CheckTool\n//purpose  : Return True if <S>  is  a tool shape. Prepare tool\n//           faces of <S> for the search of internal faces.\n//=======================================================================\n\nStandard_Boolean Partition_Spliter::CheckTool(const TopoDS_Shape& S)\n{\n  // suppose S has not an image\n  \n  Standard_Boolean isTool = Standard_False;\n  TopoDS_Compound C;\n  myBuilder.MakeCompound( C );\n\n  TopExp_Explorer expF( S, TopAbs_FACE);\n  for (; expF.More(); expF.Next()) {\n\n    const TopoDS_Face& F = TopoDS::Face( expF.Current() );\n    if (myMapTools.Contains( F ))\n      isTool = Standard_True;\n    else\n      continue;\n\n    if (myImagesFaces.HasImage( F )) {\n      // F has been reconstructed\n      TopAbs_Orientation Fori = F.Orientation();\n      TopTools_ListOfShape LNF;\n      myImagesFaces.LastImage( F, LNF);\n      TopTools_ListIteratorOfListOfShape itF (LNF);\n      for ( ; itF.More(); itF.Next())\n\tmyBuilder.Add( C, itF.Value().Oriented(Fori) );\n      continue;\n    }\n    \n    Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F );\n    Standard_Boolean hasNewE     = myAsDes->HasDescendant( F );\n    if (!hasSectionE && !hasNewE)\n    {\n      // F intersects nothing\n      myBuilder.Add( C, F );\n      continue;\n    }\n    \n    // make an image for F\n    \n    TopoDS_Face NF = F;\n    NF.Orientation(TopAbs_FORWARD);\n    NF = TopoDS::Face( NF.EmptyCopied() ); // make a copy\n    TopoDS_Wire NW;\n    myBuilder.MakeWire( NW );\n\n    // add edges, as less as possible\n    TopTools_ListOfShape NEL;\n    TopTools_ListIteratorOfListOfShape itNE;\n    if (hasSectionE) {\n      // add section edges\n      TopExp_Explorer expE;\n      for ( ; expE.More(); expE.Next()) {\n\tif (! myImagesEdges.HasImage( expE.Current() ))\n\t  continue;\n\tmyImagesEdges.LastImage( expE.Current(), NEL );\n\tfor ( itNE.Initialize( NEL ); itNE.More(); itNE.Next())\n\t  myBuilder.Add ( NW, itNE.Value());\n      }\n    }\n    if (hasNewE) {\n      // add new edges\n      NEL = myAsDes->Descendant( F );\n      for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) {\n\tTopTools_ListOfShape SEL; // splits\n\tmyImagesEdges.LastImage( itNE.Value(), SEL );\n\tTopTools_ListIteratorOfListOfShape itSE (SEL);\n\tfor ( ; itSE.More(); itSE.Next()) \n\t  myBuilder.Add ( NW, itSE.Value());\n      }\n    }\n    myBuilder.Add( NF, NW );\n    myBuilder.Add (C, NF);\n    \n    NF.Orientation( F.Orientation() ); // NF is most probably invalid\n    myImagesFaces.Bind (F, NF);\n  }\n  if (isTool)\n    myImageShape.Bind (S, C);\n\n  return isTool;\n}\n\n//=======================================================================\n//function : IsInside\n//purpose  : Return True if the first vertex of S1 inside S2.\n//           If S1.IsNull(), check infinite point against S2.\n//=======================================================================\n\nStandard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1,\n                                              const TopoDS_Shape& theS2)\n{\n  BRepClass3d_SolidClassifier aClassifier( theS2 );\n\n  TopExp_Explorer expl( theS1, TopAbs_VERTEX );\n  if (!expl.More())\n    aClassifier.PerformInfinitePoint( ::RealSmall());\n  else\n  {\n    const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );\n    aClassifier.Perform (BRep_Tool::Pnt( aVertex ),\n                         BRep_Tool::Tolerance( aVertex ));\n  }\n\n  return ( aClassifier.State() == TopAbs_IN );\n}\n\n//=======================================================================\n//function : GetOriginalShape\n//purpose  : Return the  shape  aShape  originates from. aShape\n//           should be a face or more complex result shape\n//=======================================================================\n\nTopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const\n{\n  TopoDS_Shape anOrigShape;\n\n  TopExp_Explorer expl( theShape, TopAbs_FACE);\n  if (expl.More())\n  {\n\n    TopoDS_Shape aFace = expl.Current();\n    if (myImagesFaces.IsImage( aFace ))\n      aFace = myImagesFaces.Root( aFace );\n    anOrigShape = myFaceShapeMap.Find( aFace );\n  }\n  return anOrigShape;\n}\n\n//=======================================================================\n//function : FindToolsToReconstruct\n//purpose  : find and store  as  objects  tools which interfere\n//           with  solids   or   are   inside   solids  without\n//           an interference\n//=======================================================================\n\nvoid Partition_Spliter::FindToolsToReconstruct()\n{\n  if (myMapTools.IsEmpty())\n    return;\n\n  Standard_Integer nbFoundTools = 0;\n\n  // build edge - face map in order to detect interference with section edges\n  TopTools_IndexedDataMapOfShapeListOfShape EFM;\n  TopTools_MapIteratorOfMapOfShape aMapIt;\n  for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next())\n    TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);\n  for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next())\n    TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);\n\n  TopTools_MapOfShape aCurrentSolids, aCheckedShapes;\n\n  // faces cut by new edges\n  TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces();\n\n  // keep solids interfering with each other in aCurrentSolids map\n  // and add tool faces intersecting solids as object shapes\n\n  TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE;\n  for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) {\n    TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID);\n    for (; expSo.More(); expSo.Next()) {\n\n      // check if a solid has been already processed\n      const TopoDS_Shape & aSo = expSo.Current();\n      if (!aCheckedShapes.Add( aSo ))\n        continue;\n      aCurrentSolids.Add( aSo );\n\n      // faces to check\n      TopTools_ListOfShape aFacesToCheck;\n      TopExp_Explorer exp( aSo, TopAbs_FACE );\n      for ( ; exp.More(); exp.Next())\n        aFacesToCheck.Append ( exp.Current());\n\n      // add other shapes interefering with a solid.\n      // iterate faces to check while appending new ones\n      for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next())\n      {\n        const TopoDS_Shape& aCheckFace = itCF.Value();\n//         if (!aCheckedShapes.Add( aCheckFace ))\n//           continue;\n\n        // find faces interfering with aCheckFace\n        TopTools_ListOfShape anIntFaces;\n\n        // ** 1. faces intersecting aCheckFace with creation of new edges on it\n        if ( myAsDes->HasDescendant( aCheckFace ))\n        {\n          // new edges on aCheckFace\n          const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace );\n          for (itE.Initialize( NEL); itE.More(); itE.Next())\n          {\n            const TopoDS_Shape & aNewEdge = itE.Value();\n            if (!aCheckedShapes.Add( aNewEdge ))\n              continue;\n\n            // faces interfering by aNewEdge\n            itF.Initialize (myAsDes->Ascendant( aNewEdge ));\n            for (; itF.More(); itF.Next())\n              if (aCheckFace != itF.Value())\n                anIntFaces.Append( itF.Value() );\n\n            // ** 2. faces having section edge aNewEdge on aFacesToCheck\n            if (EFM.Contains( aNewEdge))\n            {\n              itF.Initialize ( EFM.FindFromKey (itE.Value()));\n              for (; itF.More(); itF.Next())\n                if (aCheckFace != itF.Value())\n                  anIntFaces.Append( itF.Value() );\n            }\n          }\n        }\n\n        // ** 3. faces cut by edges of aCheckFace\n        TopExp_Explorer expE (aCheckFace, TopAbs_EDGE);\n        for ( ; expE.More(); expE.Next())\n        {\n          const TopoDS_Shape & aCheckEdge = expE.Current();\n          if (aCheckedShapes.Add( aCheckEdge ) &&\n              myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge )))\n          {\n            itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge )));\n            for (; itF.More(); itF.Next()) \n              if (aCheckFace != itF.Value())\n                anIntFaces.Append( itF.Value() );\n          }\n        }\n\n        // process faces interfering with aCheckFace and shapes they\n        // belong to\n        for (itF.Initialize (anIntFaces); itF.More(); itF.Next())\n        {\n          const TopoDS_Shape & F = itF.Value();\n          if (! aCheckedShapes.Add( F ))\n            continue;\n\n          Standard_Boolean isTool = myMapTools.Contains( F );\n          if (isTool && \n              myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID )\n          {\n            // a tool interfering with a solid\n            if (aSectionFaces.Contains( F ))\n              AddShape( F );\n            ++ nbFoundTools;\n            if (nbFoundTools == myMapTools.Extent())\n              return;\n          }\n\n          const TopoDS_Shape & S = myFaceShapeMap( F );\n          if (aCheckedShapes.Add( S ))\n          {\n            // a new shape interefering with aCurrentSolids is found\n            if (!isTool && S.ShapeType() == TopAbs_SOLID)\n              aCurrentSolids.Add ( S );\n            // add faces to aFacesToCheck list\n            for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next())\n              aFacesToCheck.Append ( exp.Current() );\n          }\n        }\n      } // loop on aFacesToCheck\n\n      // Here aCurrentSolids contains all solids interfering with each other.\n      // aCheckedShapes contains all faces belonging to shapes included\n      // in or interfering with aCurrentSolids or previously checked solids.\n      // Test if tool faces that do not interefere with other shapes are\n      // wrapped by any of aCurrentSolids\n\n      TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids);\n      for ( ; aSolidIt.More(); aSolidIt.Next())\n      {\n        const TopoDS_Shape & aSolid = aSolidIt.Key();\n        TopTools_MapOfShape aCheckedTools( myMapTools.Extent() );\n\n        TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools);\n        for ( ; aToolIt.More(); aToolIt.Next())\n        {\n          const TopoDS_Shape & aToolFace = aToolIt.Key();\n          if (aCheckedShapes.Contains( aToolFace ) || // already found\n              aCheckedTools.Contains( aToolFace ))    // checked against aSolid\n            continue;\n\n          const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace );\n          TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE );\n          \n          Standard_Boolean isInside = IsInside( aToolShape, aSolid );\n          for ( ; aToolFaceIt.More(); aToolFaceIt.Next() )\n          {\n            const TopoDS_Shape & aTool = aToolFaceIt.Current();\n            aCheckedTools.Add( aTool );\n            if (isInside)\n            {\n              if (aSectionFaces.Contains( aTool ))\n                AddShape( aTool );\n              ++ nbFoundTools;\n              if (nbFoundTools == myMapTools.Extent())\n                return;\n              aCheckedShapes.Add( aTool );\n            }\n          }\n        }\n      }\n      \n    } // loop on solid shapes\n  }\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Spliter.hxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  CEA/DEN, EDF R&D\n//\n//\n//\n//  File   : Partition_Spliter.hxx\n//  Module : GEOM\n\n#ifndef _Partition_Spliter_HeaderFile\n#define _Partition_Spliter_HeaderFile\n\n#ifndef _Standard_Version_HeaderFile\n#include <Standard_Version.hxx>\n#endif\n\n#ifndef _TopAbs_ShapeEnum_HeaderFile\n#include <TopAbs_ShapeEnum.hxx>\n#endif\n#ifndef _TopoDS_Compound_HeaderFile\n#include <TopoDS_Compound.hxx>\n#endif\n#ifndef _BRep_Builder_HeaderFile\n#include <BRep_Builder.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopTools_MapOfShape_HeaderFile\n#include <TopTools_MapOfShape.hxx>\n#endif\n#ifndef _TopTools_DataMapOfShapeShape_HeaderFile\n#include <TopTools_DataMapOfShapeShape.hxx>\n#endif\n\n#if OCC_VERSION_HEX < 0x070000\n   #ifndef _Handle_BRepAlgo_AsDes_HeaderFile\n      #include <Handle_BRepAlgo_AsDes.hxx>\n   #endif\n#else\n   #include <BRepAlgo_AsDes.hxx>\n   #include <TopTools_MapOfShape.hxx>\n#endif\n\n#ifndef _BRepAlgo_Image_HeaderFile\n#include <BRepAlgo_Image.hxx>\n#endif\n#ifndef _Partition_Inter3d_HeaderFile\n#include \"Partition_Inter3d.hxx\"\n#endif\n#ifndef _TopTools_MapOfOrientedShape_HeaderFile\n#include <TopTools_MapOfOrientedShape.hxx>\n#endif\n#ifndef _Standard_Boolean_HeaderFile\n#include <Standard_Boolean.hxx>\n#endif\nclass BRepAlgo_AsDes;\nclass TopoDS_Shape;\n\n#if OCC_VERSION_HEX < 0x070000\n   class TopTools_ListOfShape;\n#endif\nclass TopoDS_Edge;\n\n\n#ifndef _Standard_HeaderFile\n#include <Standard.hxx>\n#endif\n#ifndef _Standard_Macro_HeaderFile\n#include <Standard_Macro.hxx>\n#endif\n\nclass Partition_Spliter  {\n\npublic:\n\n   void* operator new(size_t,void* anAddress) \n   {\n      return anAddress;\n   }\n   void* operator new(size_t size) \n   { \n      return Standard::Allocate(size); \n   }\n   void  operator delete(void *anAddress) \n   { \n      if (anAddress) Standard::Free((Standard_Address&)anAddress); \n   }\n   // Methods PUBLIC\n   // \n   Partition_Spliter();\n   void AddShape(const TopoDS_Shape& S) ;\n   void AddTool(const TopoDS_Shape& S) ;\n   void Compute(const TopAbs_ShapeEnum Limit = TopAbs_SHAPE) ;\n   void KeepShapesInside(const TopoDS_Shape& S) ;\n   void RemoveShapesInside(const TopoDS_Shape& S) ;\n   TopoDS_Shape Shape() const;\n   void Clear() ;\n\n\n\n\n\nprotected:\n\n   // Methods PROTECTED\n   // \n\n\n   // Fields PROTECTED\n   //\n\n\nprivate: \n\n   // Methods PRIVATE\n   // \n   void MakeSolids(const TopoDS_Shape& Solid,TopTools_ListOfShape& Shells) ;\n   void MakeShells(const TopoDS_Shape& S,TopTools_ListOfShape& NS) ;\n   TopoDS_Shape MakeFaces(const TopoDS_Shape& S) ;\n   void MakeEdges(const TopoDS_Edge& E,const TopTools_ListOfShape& VOnE,TopTools_ListOfShape& NE) const;\n   TopoDS_Shape FindFacesInside(const TopoDS_Shape& S,const Standard_Boolean CheckClosed = Standard_False,const Standard_Boolean All = Standard_False) ;\n   Standard_Boolean CheckTool(const TopoDS_Shape& S) ;\n   void MergeEqualEdges(const TopTools_ListOfShape& LE) ;\n   static  Standard_Boolean IsInside(const TopoDS_Shape& S1,const TopoDS_Shape& S2) ;\n   TopoDS_Shape GetOriginalShape(const TopoDS_Shape& aShape) const;\n   void FindToolsToReconstruct() ;\n\n\n   // Fields PRIVATE\n   //\n   TopAbs_ShapeEnum myDoneStep;\n   TopoDS_Compound myShape;\n   BRep_Builder myBuilder;\n   TopTools_ListOfShape myListShapes;\n   TopTools_MapOfShape myMapFaces;\n   TopTools_MapOfShape myMapTools;\n   TopTools_MapOfShape myEqualEdges;\n   TopTools_MapOfShape myNewSection;\n   TopTools_MapOfShape myClosedShapes;\n   TopTools_MapOfShape mySharedFaces;\n   TopTools_MapOfShape myWrappingSolid;\n   TopTools_DataMapOfShapeShape myFaceShapeMap;\n   TopTools_DataMapOfShapeShape myInternalFaces;\n   TopTools_DataMapOfShapeShape myIntNotClFaces;\n   Handle(BRepAlgo_AsDes) myAsDes;\n   BRepAlgo_Image myImagesFaces;\n   BRepAlgo_Image myImagesEdges;\n   BRepAlgo_Image myImageShape;\n   Partition_Inter3d myInter3d;\n   TopTools_MapOfOrientedShape myAddedFacesMap;\n\n\n};\n\n\n\n\n\n// other Inline functions and methods (like \"C++: function call\" methods)\n//\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/Partition_Spliter.ixx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Spliter.ixx\n//  Module : GEOM\n\n#include \"Partition_Spliter.jxx\"\n\n \n\n\n"
  },
  {
    "path": "libsrc/occ/Partition_Spliter.jxx",
    "content": "//  GEOM PARTITION : partition algorithm\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : Partition_Spliter.jxx\n//  Module : GEOM\n\n#ifndef _BRepAlgo_AsDes_HeaderFile\n#include <BRepAlgo_AsDes.hxx>\n#endif\n#ifndef _TopoDS_Shape_HeaderFile\n#include <TopoDS_Shape.hxx>\n#endif\n#ifndef _TopTools_ListOfShape_HeaderFile\n#include <TopTools_ListOfShape.hxx>\n#endif\n#ifndef _TopoDS_Edge_HeaderFile\n#include <TopoDS_Edge.hxx>\n#endif\n#ifndef _Partition_Spliter_HeaderFile\n#include \"Partition_Spliter.hxx\"\n#endif\n"
  },
  {
    "path": "libsrc/occ/cross_section.cpp",
    "content": "\n#include <BOPAlgo_Builder.hxx>\n#include <BRepAlgoAPI_Splitter.hxx>\n#include <BRepBndLib.hxx>\n#include <BRepBuilderAPI_Copy.hxx>\n#include <BRepBuilderAPI_MakeFace.hxx>\n#include <BRepBuilderAPI_Sewing.hxx>\n#include <BRepBuilderAPI_Transform.hxx>\n#include <BRep_Builder.hxx>\n#include <BRep_Tool.hxx>\n#include <Bnd_Box.hxx>\n#include <Geom_Plane.hxx>\n#include <Geom_Surface.hxx>\n#include <Precision.hxx>\n#include <ShapeBuild_ReShape.hxx>\n#include <ShapeFix_Shape.hxx>\n#include <Standard_Handle.hxx>\n#include <Standard_TypeDef.hxx>\n#include <TopAbs_ShapeEnum.hxx>\n#include <TopExp_Explorer.hxx>\n#include <TopTools_ListOfShape.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Face.hxx>\n#include <TopoDS_Face.hxx>\n#include <TopoDS_Shape.hxx>\n#include <algorithm>\n#include <gp.hxx>\n#include <gp_Ax3.hxx>\n#include <gp_Pln.hxx>\n#include <gp_Trsf.hxx>\n#include <limits>\n\n#include \"core/array.hpp\"\n#include \"occ_utils.hpp\"\n#include \"occgeom.hpp\"\n\nnamespace netgen\n{\n  TopoDS_Face MakePlaneFaceCoveringShape\n  (const TopoDS_Shape& shape,\n   const gp_Pln& pln,\n   double rel_margin = 0.05,\n   double abs_margin = 0.0)\n  {\n    Bnd_Box b;\n    BRepBndLib::Add(shape, b);\n    b.SetGap(0.0);\n\n    Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;\n    b.Get(xmin, ymin, zmin, xmax, ymax, zmax);\n\n    gp_Trsf w2l;\n    w2l.SetTransformation(pln.Position());\n\n    auto upd = [&] (double x, double y, double z, double& umin, double& umax, double& vmin, double& vmax) {\n      gp_Pnt p(x, y, z);\n      p.Transform(w2l);\n      umin = std::min(umin, p.X());\n      umax = std::max(umax, p.X());\n      vmin = std::min(vmin, p.Y());\n      vmax = std::max(vmax, p.Y());\n    };\n\n    double umin = std::numeric_limits<double>::infinity();\n    double umax = -std::numeric_limits<double>::infinity();\n    double vmin = std::numeric_limits<double>::infinity();\n    double vmax = -std::numeric_limits<double>::infinity();\n\n    upd(xmin, ymin, zmin, umin, umax, vmin, vmax);\n    upd(xmin, ymin, zmax, umin, umax, vmin, vmax);\n    upd(xmin, ymax, zmin, umin, umax, vmin, vmax);\n    upd(xmin, ymax, zmax, umin, umax, vmin, vmax);\n    upd(xmax, ymin, zmin, umin, umax, vmin, vmax);\n    upd(xmax, ymin, zmax, umin, umax, vmin, vmax);\n    upd(xmax, ymax, zmin, umin, umax, vmin, vmax);\n    upd(xmax, ymax, zmax, umin, umax, vmin, vmax);\n\n    double du = umax - umin;\n    double dv = vmax - vmin;\n    double pad = std::max(abs_margin, rel_margin * std::max(du, dv));\n\n    umin -= pad;\n    umax += pad;\n    vmin -= pad;\n    vmax += pad;\n\n    double eps = std::max(Precision::Confusion(), 1e-9);\n    if (umax - umin < eps)\n      {\n        umin -= 1.0;\n        umax += 1.0;\n      }\n    if (vmax - vmin < eps)\n      {\n        vmin -= 1.0;\n        vmax += 1.0;\n      }\n    return BRepBuilderAPI_MakeFace(pln, umin, umax, vmin, vmax).Face();\n  }\n\n  TopoDS_Shape CrossSection (const TopoDS_Shape& shape,\n                             const gp_Ax3& axes)\n  {\n    gp_Pln pln(axes);\n    TopoDS_Face planeFace = MakePlaneFaceCoveringShape(shape, axes);\n\n    auto bb = GetBoundingBox(shape);\n    auto diam = bb.Diam();\n\n    // Heal / unify the input\n    //  - especially if shape comes from STEP/IGES\n    ShapeFix_Shape fix(shape);\n    fix.Perform();\n    TopoDS_Shape fixed = fix.Shape();\n\n    BRepAlgoAPI_Splitter splitter;\n    splitter.SetNonDestructive(true);\n    splitter.SetFuzzyValue(1e-7 * diam);\n\n    TopTools_ListOfShape args;\n    args.Append(shape);\n\n    TopTools_ListOfShape tools;\n    tools.Append(planeFace);\n\n    splitter.SetArguments(args);\n    splitter.SetTools(tools);\n    splitter.Build();\n    if (!splitter.IsDone())\n      return TopoDS_Shape();\n\n    // for each input face/edge propagate properties to generated sub-shapes\n    for (auto typ : {TopAbs_FACE, TopAbs_EDGE})\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n        {\n          if (!OCCGeometry::HaveProperties(e.Current()))\n            continue;\n          auto prop = OCCGeometry::GetProperties(e.Current());\n          for (auto mods : splitter.Generated(e.Current()))\n            OCCGeometry::GetProperties(mods).Merge(prop);\n        }\n    // for each input solid, find the cut faces and propagate properties\n    for (auto solid : GetSolids(shape))\n      {\n        if (!OCCGeometry::HaveProperties(solid))\n          continue;\n        auto prop = OCCGeometry::GetProperties(solid);\n        for (auto mods : splitter.Modified(solid))\n          {\n            if (mods.ShapeType() != TopAbs_SOLID)\n              continue;\n            for (TopExp_Explorer ef(mods, TopAbs_FACE); ef.More(); ef.Next())\n              OCCGeometry::GetProperties(ef.Current()).Merge(prop);\n          }\n      }\n    TopoDS_Shape res = splitter.Shape();\n    const gp_Ax1 ax = axes.Axis();\n    const gp_Dir n = ax.Direction();\n    const gp_Pnt p0 = axes.Location();\n    Array<TopoDS_Shape> out_shapes;\n    for (auto f : GetFaces(res))\n      {\n        Handle(Geom_Surface) s = BRep_Tool::Surface(TopoDS::Face(f));\n        Handle(Geom_Plane) gp = Handle(Geom_Plane)::DownCast(s);\n        if (gp.IsNull())\n          continue;\n\n        // Check coplanarity (orientation can flip)\n        gp_Pln fpln = gp->Pln();\n        auto my_n = fpln.Position().Axis().Direction();\n        if (!my_n.IsParallel(n, 1e-10))\n          continue;\n\n        // Check distance of face plane to our plane\n        Standard_Real dist = fpln.Distance(p0);\n        if (dist > 1e-7 * diam)\n          continue;\n        if (my_n.Dot(n) > 0)\n          f.Reverse();\n        out_shapes.Append(f);\n      }\n    BRepBuilderAPI_Sewing sew(1e-7 * diam);\n    for (auto s : out_shapes)\n      sew.Add(TopoDS::Face(s));\n    sew.Perform();\n    for (auto s : out_shapes)\n      PropagateProperties(sew, s);\n    auto out = sew.SewedShape();\n    gp_Ax3 xy(gp::XOY());\n\n    gp_Trsf T;\n    T.SetTransformation(axes, xy);\n    BRepBuilderAPI_Transform btransf(out, T, Standard_True);\n    PropagateProperties(btransf, out);\n    return btransf.Shape();\n  }\n} // namespace netgen\n"
  },
  {
    "path": "libsrc/occ/occ_edge.cpp",
    "content": "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <BRepGProp.hxx>\n#include <BRep_Tool.hxx>\n#include <GeomAPI_ProjectPointOnCurve.hxx>\n\n#pragma clang diagnostic pop\n\n#include \"occ_edge.hpp\"\n#include \"occgeom.hpp\"\n\nnamespace netgen\n{\n    OCCEdge::OCCEdge(TopoDS_Shape edge_, GeometryVertex & start_, GeometryVertex & end_)\n        : GeometryEdge(start_, end_),\n          edge(TopoDS::Edge(edge_))\n    {\n        curve = BRep_Tool::Curve(edge, s0, s1);\n        BRepGProp::LinearProperties(edge, props);\n\n        auto verts = GetVertices(edge);\n        if(verts.size() != 2)\n            throw Exception(\"OCC edge does not have 2 vertices\");\n\n        if(start != end)\n        {\n            // swap start/end if necessary\n            double d00 = Dist(GetPoint(0), start->GetPoint());\n            double d01 = Dist(GetPoint(0), end->GetPoint());\n            if(d01 < d00)\n                swap(start, end);\n        }\n    }\n\n    double OCCEdge::GetLength() const\n    {\n        return props.Mass();\n    }\n\n    Point<3> OCCEdge::GetCenter() const\n    {\n        return occ2ng( props.CentreOfMass() );\n    }\n\n    Point<3> OCCEdge::GetPoint(double t) const\n    {\n        return occ2ng( curve->Value(s0+t*(s1-s0)) );\n    }\n\n    double OCCEdge::CalcStep(double t, double sag) const\n    {\n        throw Exception(ToString(\"not implemented\") + __FILE__ + \":\" + ToString(__LINE__));\n    }\n\n    void OCCEdge::ProjectPoint(Point<3>& p, EdgePointGeomInfo* gi) const\n    {\n        auto pnt = ng2occ(p);\n        // extend the projection parameter range, else projection might fail\n        // for an endpoint\n        // see discussion here: https://forum.ngsolve.org/t/how-to-apply-occidentification-correctly/2555\n        // I do not see a better way using occ tolerances?\n        double eps = 1e-7 * (s1-s0);\n        GeomAPI_ProjectPointOnCurve proj(pnt, curve, s0-eps, s1+eps);\n        pnt = proj.NearestPoint();\n        if(gi)\n            gi->dist = (proj.LowerDistanceParameter() - s0)/(s1-s0);\n        p = occ2ng(pnt);\n    }\n\n    Vec<3> OCCEdge::GetTangent(double t) const\n    {\n        t = s0 + t*(s1-s0);\n        gp_Pnt p;\n        gp_Vec v;\n        curve->D1(t, p, v);\n        return occ2ng(v) * (s1-s0);\n    }\n\n}\n"
  },
  {
    "path": "libsrc/occ/occ_edge.hpp",
    "content": "#ifndef FILE_OCC_EDGE_INCLUDED\n#define FILE_OCC_EDGE_INCLUDED\n\n\n// #pragma clang diagnostic push\n// #pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <GProp_GProps.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Edge.hxx>\n#include <Geom_Curve.hxx>\n#include <BRep_TEdge.hxx>\n#include <BRep_Tool.hxx>\n\n// #pragma clang diagnostic pop\n\n#include \"occ_vertex.hpp\"\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n    class OCCEdge : public GeometryEdge \n    {\n        public:\n        TopoDS_Edge edge;\n        Handle(Geom_Curve) curve;\n        double s0, s1;\n        GProp_GProps props;\n\n        public:\n        OCCEdge(TopoDS_Shape edge_, GeometryVertex & start_, GeometryVertex & end_);\n\n        auto Shape() const { return edge; }\n\n        double GetLength() const override;\n        Point<3> GetCenter() const override;\n        Point<3> GetPoint(double t) const override;\n        double CalcStep(double t, double sag) const override;\n        void ProjectPoint(Point<3>& p, EdgePointGeomInfo* gi) const override;\n        Vec<3> GetTangent(double t) const override;\n        bool IsDegenerated(double) const override {\n          return BRep_Tool::Degenerated(edge);\n        }\n    };\n}\n\n#endif // FILE_OCCEDGE_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/occ_face.cpp",
    "content": "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <BRepGProp.hxx>\n#include <BRep_Tool.hxx>\n#include <GeomAPI_ProjectPointOnCurve.hxx>\n#include <BRepLProp_SLProps.hxx>\n\n#pragma clang diagnostic pop\n\n#include \"occ_edge.hpp\"\n#include \"occ_face.hpp\"\n#include \"occgeom.hpp\"\n\nnamespace netgen\n{\n    OCCFace::OCCFace(TopoDS_Shape dshape)\n        : face(TopoDS::Face(dshape))\n    {\n        BRepGProp::SurfaceProperties (dshape, props);\n        bbox = ::netgen::GetBoundingBox(face);\n\n        surface = BRep_Tool::Surface(face);\n        shape_analysis = new ShapeAnalysis_Surface( surface );\n        tolerance = BRep_Tool::Tolerance( face );\n    }\n\n    size_t OCCFace::GetNBoundaries() const\n    {\n        return 0;\n    }\n\n    Point<3> OCCFace::GetCenter() const\n    {\n        return occ2ng( props.CentreOfMass() );\n    }\n\n    Array<Segment> OCCFace::GetBoundary(const Mesh& mesh) const\n    {\n        auto & geom = dynamic_cast<OCCGeometry&>(*mesh.GetGeometry());\n\n        auto n_edges = geom.GetNEdges();\n        constexpr int UNUSED = 0;\n        constexpr int FORWARD = 1;\n        constexpr int REVERSED = 2;\n        constexpr int BOTH = 3;\n\n        Array<int> edge_orientation(n_edges);\n        edge_orientation = UNUSED;\n\n        Array<Handle(Geom2d_Curve)> curve_on_face[BOTH];\n        curve_on_face[FORWARD].SetSize(n_edges);\n        curve_on_face[REVERSED].SetSize(n_edges);\n\n        Array<TopoDS_Edge> edge_on_face[BOTH];\n        edge_on_face[FORWARD].SetSize(n_edges);\n        edge_on_face[REVERSED].SetSize(n_edges);\n\n        // In case the face is INTERNAL, we need to orient it to FORWARD to get proper orientation for the edges\n        // (relative to the face) otherwise, all edges are also INTERNAL\n        auto oriented_face = TopoDS_Face(face);\n        if(oriented_face.Orientation() == TopAbs_INTERNAL)\n          oriented_face.Orientation(TopAbs_FORWARD);\n\n        for(auto edge_ : GetEdges(oriented_face))\n        {\n            auto edge = TopoDS::Edge(edge_);\n            auto edgenr = geom.GetEdge(edge).nr;\n            auto & orientation = edge_orientation[edgenr];\n            double s0, s1;\n            auto cof = BRep_Tool::CurveOnSurface (edge, oriented_face, s0, s1);\n            if(edge.Orientation() == TopAbs_FORWARD || edge.Orientation() == TopAbs_INTERNAL)\n            {\n                curve_on_face[FORWARD][edgenr] = cof;\n                orientation += FORWARD;\n                edge_on_face[FORWARD][edgenr] = edge;\n            }\n            if(edge.Orientation() == TopAbs_REVERSED)\n            {\n                curve_on_face[REVERSED][edgenr] = cof;\n                orientation += REVERSED;\n                edge_on_face[REVERSED][edgenr] = edge;\n            }\n            if(edge.Orientation() == TopAbs_INTERNAL)\n            {\n              // add reversed edge\n              auto r_edge = TopoDS::Edge(edge.Reversed());\n              auto cof = BRep_Tool::CurveOnSurface (r_edge, oriented_face, s0, s1);\n              curve_on_face[REVERSED][edgenr] = cof;\n              orientation += REVERSED;\n              edge_on_face[REVERSED][edgenr] = r_edge;\n            }\n\n            if(orientation > BOTH)\n                throw Exception(\"have edge more than twice in face \" + ToString(nr) + \" \" + properties.GetName() + \", orientation: \" + ToString(orientation));\n        }\n\n        Array<Segment> boundary;\n        for (auto seg : mesh.LineSegments())\n        {\n            auto edgenr = seg.epgeominfo[0].edgenr;\n            auto orientation = edge_orientation[edgenr];\n\n            if(orientation == UNUSED)\n                continue;\n\n            for(const auto ORIENTATION : {FORWARD, REVERSED})\n            {\n                if((orientation & ORIENTATION) == 0)\n                    continue;\n\n                // auto cof = curve_on_face[ORIENTATION][edgenr];\n                auto edge = edge_on_face[ORIENTATION][edgenr];\n                double s0, s1;\n                auto cof = BRep_Tool::CurveOnSurface (edge, face, s0, s1);\n\n                double s[2] = { seg.epgeominfo[0].dist, seg.epgeominfo[1].dist };\n\n                // dist is in [0,1], map parametrization to [s0, s1]\n                s[0] = s0 + s[0]*(s1-s0);\n                s[1] = s0 + s[1]*(s1-s0);\n\n                // fixes normal-vector roundoff problem when endpoint is cone-tip\n                double delta = s[1]-s[0];\n                s[0] += 1e-10*delta;\n                s[1] -= 1e-10*delta;\n\n                for(auto i : Range(2))\n                {\n                    // take uv from CurveOnSurface as start value but project again for better accuracy\n                    // (cof->Value yields wrong values (outside of surface) for complicated faces\n                    auto uv = cof->Value(s[i]);\n                    PointGeomInfo gi;\n                    gi.u = uv.X();\n                    gi.v = uv.Y();\n                    Point<3> pproject = mesh[seg[i]];\n                    ProjectPointGI(pproject, gi);\n                    seg.epgeominfo[i].u = gi.u;\n                    seg.epgeominfo[i].v = gi.v;\n                }\n\n                bool do_swap = ORIENTATION == REVERSED;\n                if(seg.epgeominfo[1].dist < seg.epgeominfo[0].dist)\n                  do_swap = !do_swap;\n\n                if(do_swap)\n                {\n                    swap(seg[0], seg[1]);\n                    swap(seg.epgeominfo[0].dist, seg.epgeominfo[1].dist);\n                    swap(seg.epgeominfo[0].u, seg.epgeominfo[1].u);\n                    swap(seg.epgeominfo[0].v, seg.epgeominfo[1].v);\n                }\n\n                boundary.Append(seg);\n            }\n        }\n        return boundary;\n    }\n\n    PointGeomInfo OCCFace::Project(Point<3>& p) const\n    {\n        auto suval = shape_analysis->ValueOfUV(ng2occ(p), tolerance);\n        double u,v;\n        suval.Coord(u, v);\n        p = occ2ng(surface->Value( u, v ));\n\n        PointGeomInfo gi;\n        gi.trignum = nr+1;\n        gi.u = u;\n        gi.v = v;\n        return gi;\n    }\n\n    bool OCCFace::ProjectPointGI(Point<3>& p_, PointGeomInfo& gi) const\n    {\n      /*\n        static Timer t(\"OCCFace::ProjectPointGI\");\n        RegionTimer rt(t);\n        // *testout << \"input, uv = \" << gi.u << \", \" << gi.v << endl;\n        auto suval = shape_analysis->NextValueOfUV({gi.u, gi.v}, ng2occ(p_), tolerance);\n        gi.trignum = nr+1;\n        suval.Coord(gi.u, gi.v);\n        // *testout << \"result, uv = \" << gi.u << \", \" << gi.v << endl;\n        p_ = occ2ng(surface->Value( gi.u, gi.v ));        \n        return true;\n      */\n        // Old code: do newton iterations manually\n        double u = gi.u;\n        double v = gi.v;\n        auto p = ng2occ(p_);\n        auto x = surface->Value (u,v);\n      \n        if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return true;\n      \n        gp_Vec du, dv;\n        surface->D1(u,v,x,du,dv);\n      \n        int count = 0;\n        gp_Pnt xold;\n        gp_Vec n;\n        double det, lambda, mu;\n      \n        do {\n           count++;\n\n           n = du^dv;\n\n           det = Det3 (n.X(), du.X(), dv.X(),\n              n.Y(), du.Y(), dv.Y(),\n              n.Z(), du.Z(), dv.Z());\n\n           if (det < 1e-15) return false;\n\n           lambda = Det3 (n.X(), p.X()-x.X(), dv.X(),\n              n.Y(), p.Y()-x.Y(), dv.Y(),\n              n.Z(), p.Z()-x.Z(), dv.Z())/det;\n\n           mu     = Det3 (n.X(), du.X(), p.X()-x.X(),\n              n.Y(), du.Y(), p.Y()-x.Y(),\n              n.Z(), du.Z(), p.Z()-x.Z())/det;\n\n           u += lambda;\n           v += mu;\n\n           xold = x;\n           surface->D1(u,v,x,du,dv);\n\n        } while (xold.SquareDistance(x) > sqr(PROJECTION_TOLERANCE) && count < 50);\n\n        //    (*testout) << \"FastProject count: \" << count << endl;\n\n        if (count == 50) return false;\n\n        p_ = occ2ng(x);\n        gi.u = u; gi.v = v;\n\n        return true;\n    }\n\n    Point<3> OCCFace::GetPoint(const PointGeomInfo& gi) const\n    {\n        return occ2ng(surface->Value( gi.u, gi.v ));\n    }\n\n    void OCCFace::CalcEdgePointGI(const GeometryEdge& edge,\n            double t,\n            EdgePointGeomInfo& egi) const\n    {\n        throw Exception(ToString(\"not implemented\") + __FILE__ + \":\" + ToString(__LINE__));\n    }\n\n    Box<3> OCCFace::GetBoundingBox() const\n    {\n        return bbox;\n    }\n\n\n    double OCCFace::GetCurvature(const PointGeomInfo& gi) const\n    {\n        BRepAdaptor_Surface sf(face, Standard_True);\n        BRepLProp_SLProps prop2(sf, 2, 1e-5);\n        prop2.SetParameters (gi.u, gi.v);\n        return max(fabs(prop2.MinCurvature()),\n                   fabs(prop2.MaxCurvature()));\n    }\n\n    void OCCFace::RestrictH(Mesh& mesh, const MeshingParameters& mparam) const\n    {\n        throw Exception(ToString(\"not implemented\") + __FILE__ + \":\" + ToString(__LINE__));\n    }\n\n    Vec<3> OCCFace::GetNormal(const Point<3>& p, const PointGeomInfo* gi) const\n    {\n        PointGeomInfo gi_;\n        if(gi==nullptr)\n        {\n            auto p_ = p;\n            gi_ = Project(p_);\n            gi = &gi_;\n        }\n\n        gp_Pnt pnt;\n        gp_Vec du, dv;\n        surface->D1(gi->u,gi->v,pnt,du,dv);\n        auto n = Cross (occ2ng(du), occ2ng(dv));\n        n.Normalize();\n        if (face.Orientation() == TopAbs_REVERSED)\n            n *= -1;\n        return n;\n    }\n\n\n}\n"
  },
  {
    "path": "libsrc/occ/occ_face.hpp",
    "content": "#ifndef FILE_OCC_FACE_INCLUDED\n#define FILE_OCC_FACE_INCLUDED\n\n// #pragma clang diagnostic push\n// #pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <GProp_GProps.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Face.hxx>\n#include <ShapeAnalysis_Surface.hxx>\n\n// #pragma clang diagnostic pop\n\n#include \"occ_vertex.hpp\"\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n    class OCCFace : public GeometryFace \n    {\n        TopoDS_Face face;\n        GProp_GProps props;\n        Box<3> bbox;\n\n        Handle( Geom_Surface ) surface;\n        Handle( ShapeAnalysis_Surface ) shape_analysis;\n        double tolerance;\n\n        public:\n        OCCFace(TopoDS_Shape dshape);\n\n        const TopoDS_Face Shape() const { return face; }\n\n        Point<3> GetCenter() const override;\n        virtual size_t GetNBoundaries() const override;\n        virtual Array<Segment> GetBoundary(const Mesh& mesh) const override;\n        virtual PointGeomInfo Project(Point<3>& p) const override;\n        virtual bool ProjectPointGI(Point<3>& p, PointGeomInfo& gi) const override;\n        virtual Point<3> GetPoint(const PointGeomInfo& gi) const override;\n        virtual void CalcEdgePointGI(const GeometryEdge& edge,\n                double t,\n                EdgePointGeomInfo& egi) const override;\n        virtual Box<3> GetBoundingBox() const override;\n\n        virtual double GetCurvature(const PointGeomInfo& gi) const override;\n\n        virtual void RestrictH(Mesh& mesh, const MeshingParameters& mparam) const override;\n        virtual Vec<3> GetNormal(const Point<3>& p, const PointGeomInfo* gi = nullptr) const override;\n    };\n}\n\n#endif // FILE_OCC_FACE_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/occ_solid.hpp",
    "content": "#ifndef FILE_OCC_SOLID_INCLUDED\n#define FILE_OCC_SOLID_INCLUDED\n\n#include <TopoDS.hxx>\n#include <TopoDS_Solid.hxx>\n\n#include \"meshing.hpp\"\n\nnamespace netgen\n{\n    class OCCSolid : public GeometrySolid \n    {\n        TopoDS_Solid solid;\n\n        public:\n        OCCSolid(TopoDS_Shape dshape)\n            : solid(TopoDS::Solid(dshape))\n        { }\n        TopoDS_Solid& GetShape() { return solid; }\n    };\n}\n\n#endif // FILE_OCC_SOLID_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/occ_utils.cpp",
    "content": "#include <Bnd_Box.hxx>\n#include <BRepBndLib.hxx>\n#include <BRep_TVertex.hxx>\n#include <BRepMesh_IncrementalMesh.hxx>\n#include <BRepTools.hxx>\n\n#include \"occ_utils.hpp\"\n#include \"occgeom.hpp\"\n\nnamespace netgen\n{\n    Point<3> occ2ng (const TopoDS_Shape& shape)\n    {\n      if(shape.ShapeType() != TopAbs_VERTEX)\n        throw Exception(\"Try to convert non vertex to point!\");\n      return occ2ng( BRep_Tool::Pnt(TopoDS::Vertex(shape)) );\n    }\n\n    Transformation<3> occ2ng (const gp_Trsf & occ_trafo)\n    {\n        Transformation<3> trafo;\n        auto v = occ_trafo.TranslationPart();\n        auto m = occ_trafo.VectorialPart();\n        auto & tv = trafo.GetVector();\n        auto & tm = trafo.GetMatrix();\n        for(auto i : Range(3))\n        {\n            tv[i] = v.Coord(i+1);\n            for(auto k : Range(3))\n                tm(i,k) = m(i+1,k+1);\n        }\n        return trafo;\n    }\n\n  Transformation<3> occ2ng (const gp_GTrsf & occ_trafo)\n    {\n        Transformation<3> trafo;\n        auto v = occ_trafo.TranslationPart();\n        auto m = occ_trafo.VectorialPart();\n        auto & tv = trafo.GetVector();\n        auto & tm = trafo.GetMatrix();\n        for(auto i : Range(3))\n        {\n            tv[i] = v.Coord(i+1);\n            for(auto k : Range(3))\n                tm(i,k) = m(i+1,k+1);\n        }\n        return trafo;\n    }\n\n    Box<3> GetBoundingBox( const TopoDS_Shape & shape )\n    {\n        Bnd_Box bb;\n#if OCC_VERSION_HEX < 0x070000\n        BRepBndLib::Add (shape, bb);\n#else\n        BRepBndLib::Add (shape, bb, true);\n#endif\n        return {occ2ng(bb.CornerMin()), occ2ng(bb.CornerMax())};\n    }\n\n    Standard_Integer BuildTriangulation( const TopoDS_Shape & shape )\n    {\n       BRepTools::Clean (shape);\n       // double deflection = 0.01;\n\n       // https://dev.opencascade.org/doc/overview/html/occt_user_guides__mesh.html\n       // from Standard_Boolean meshing_imeshtools_parameters()\n       IMeshTools_Parameters aMeshParams;\n       aMeshParams.Deflection               = 0.01;\n       aMeshParams.Angle                    = 0.5;\n       aMeshParams.Relative                 = Standard_True;\n       aMeshParams.InParallel               = Standard_True;\n       aMeshParams.MinSize                  = Precision::Confusion();\n       aMeshParams.InternalVerticesMode     = Standard_True;\n       aMeshParams.ControlSurfaceDeflection = Standard_True;\n\n       BRepMesh_IncrementalMesh aMesher (shape, aMeshParams);\n       return  aMesher.GetStatusFlags();\n    }\n}\n"
  },
  {
    "path": "libsrc/occ/occ_utils.hpp",
    "content": "#ifndef FILE_OCC_UTILS_INCLUDED\n#define FILE_OCC_UTILS_INCLUDED\n\n\n\n#include <variant>\n\n// #pragma clang diagnostic push\n// #pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <Standard_Version.hxx>\n#include <BRepGProp.hxx>\n#include <BRep_Tool.hxx>\n#include <GProp_GProps.hxx>\n#include <TopExp_Explorer.hxx>\n#include <TopTools_IndexedMapOfShape.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Vertex.hxx>\n#include <gp_Trsf.hxx>\n#include <gp_GTrsf.hxx>\n\n#define NETGEN_OCC_VERSION_AT_LEAST(MAJOR, MINOR) \\\n  ((OCC_VERSION_MAJOR > MAJOR) ||                               \\\n   ((OCC_VERSION_MAJOR == MAJOR) && (OCC_VERSION_MINOR >= MINOR)))\n#define NETGEN_OCC_VERSION_AT_LEAST_MAJOR(MAJOR) \\\n  (NETGEN_OCC_VERSION_AT_LEAST(MAJOR, 0))\n\n// #pragma clang diagnostic pop\n\n#include \"meshing.hpp\"\n\n#if NETGEN_OCC_VERSION_AT_LEAST(7, 4)\n#define OCC_HAVE_DUMP_JSON\n#endif\n\nnamespace netgen\n{\n    inline Point<3> occ2ng (const gp_Pnt & p)\n    {\n        return Point<3> (p.X(), p.Y(), p.Z());\n    }\n\n    inline Point<2> occ2ng (const gp_Pnt2d & p)\n    {\n        return Point<2> (p.X(), p.Y());\n    }\n\n    inline Vec<3> occ2ng (const gp_Vec & v)\n    {\n        return Vec<3> (v.X(), v.Y(), v.Z());\n    }\n\n    DLL_HEADER Point<3> occ2ng (const TopoDS_Shape & s);\n\n    inline Point<3> occ2ng (const TopoDS_Vertex & v)\n    {\n        return occ2ng (BRep_Tool::Pnt (v));\n    }\n\n    DLL_HEADER Transformation<3> occ2ng (const gp_Trsf & t);\n    DLL_HEADER Transformation<3> occ2ng (const gp_GTrsf & t);\n    inline Transformation<3> occ2ng (const variant<gp_Trsf, gp_GTrsf> & t)\n    {\n      if(auto t1 = get_if<gp_Trsf>(&t))\n        return occ2ng(*t1);\n      return occ2ng(get<gp_GTrsf>(t));\n    }\n\n    inline gp_Pnt ng2occ (const Point<3> & p)\n    {\n        return gp_Pnt(p(0), p(1), p(2));\n    }\n\n    inline void CheckValidPropertyType(const TopoDS_Shape & shape)\n    {\n        switch (shape.ShapeType())\n        {\n          case TopAbs_SOLID:\n          case TopAbs_FACE:\n          case TopAbs_EDGE:\n          case TopAbs_VERTEX:\n            break;\n          default:\n            throw Exception(\"Cannot query properties of compound shapes - setting properties sets property on all highest dimension subshape type\");\n        }\n    }\n\n    DLL_HEADER Box<3> GetBoundingBox( const TopoDS_Shape & shape );\n\n    struct OCCIdentification\n    {\n      TopoDS_Shape from;\n      TopoDS_Shape to;\n      optional<Transformation<3>> trafo = nullopt;\n      string name;\n      Identifications::ID_TYPE type;\n      bool opposite_direction = false;\n    };\n\n    Standard_Integer BuildTriangulation( const TopoDS_Shape & shape );\n\n\n    class MyExplorer\n    {\n      class Iterator\n      {\n        TopExp_Explorer exp;\n      public:\n        Iterator (TopoDS_Shape ashape, TopAbs_ShapeEnum atoFind, TopAbs_ShapeEnum atoAvoid)\n          : exp(ashape, atoFind, atoAvoid) { }\n        auto operator*() { return exp.Current(); }\n        Iterator & operator++() { exp.Next(); return *this; }\n        bool operator!= (nullptr_t nu) { return exp.More(); }\n      };\n\n    public:\n      TopoDS_Shape shape;\n      TopAbs_ShapeEnum toFind;\n      TopAbs_ShapeEnum toAvoid;\n      MyExplorer (TopoDS_Shape ashape, TopAbs_ShapeEnum atoFind, TopAbs_ShapeEnum atoAvoid = TopAbs_SHAPE)\n        : shape(ashape), toFind(atoFind), toAvoid(atoAvoid) { ; }\n      Iterator begin() { return Iterator(shape, toFind, toAvoid); }\n      auto end() { return nullptr; }\n    };\n\n    inline auto Explore (TopoDS_Shape shape, TopAbs_ShapeEnum toFind, TopAbs_ShapeEnum toAvoid = TopAbs_SHAPE)\n    {\n      return MyExplorer (shape, toFind, toAvoid);\n    }\n\n\n    class IndexMapIterator\n    {\n      class Iterator\n      {\n        const TopTools_IndexedMapOfShape & indmap;\n        int i;\n      public:\n        Iterator (const TopTools_IndexedMapOfShape & aindmap, int ai)\n          : indmap(aindmap), i(ai) { ; }\n        auto operator*() { return tuple(i, indmap(i)); }\n        Iterator & operator++() { i++; return *this; }\n        bool operator!= (const Iterator & i2) { return i != i2.i; }\n      };\n\n    public:\n      const TopTools_IndexedMapOfShape & indmap;\n      IndexMapIterator (const TopTools_IndexedMapOfShape & aindmap) : indmap(aindmap) { }\n      Iterator begin() { return Iterator(indmap, 1); }\n      Iterator end() { return Iterator(indmap, indmap.Extent()+1); }\n    };\n\n    inline auto Enumerate (const TopTools_IndexedMapOfShape & indmap)\n    {\n      return IndexMapIterator(indmap);\n    }\n\n    class ListOfShapes : public std::vector<TopoDS_Shape>\n    {\n    public:\n      DLL_HEADER TopoDS_Shape Max(gp_Vec dir);\n      DLL_HEADER TopoDS_Shape Nearest(gp_Pnt pnt);\n      DLL_HEADER ListOfShapes SubShapes(TopAbs_ShapeEnum type) const;\n\n      ListOfShapes Solids() const\n      {\n        return SubShapes(TopAbs_SOLID);\n      }\n      ListOfShapes Shells() const\n      {\n        return SubShapes(TopAbs_SHELL);\n      }\n      ListOfShapes Faces() const\n      {\n        return SubShapes(TopAbs_FACE);\n      }\n      ListOfShapes Wires() const\n      {\n        return SubShapes(TopAbs_WIRE);\n      }\n      ListOfShapes Edges() const\n      {\n        return SubShapes(TopAbs_EDGE);\n      }\n      ListOfShapes Vertices() const\n      {\n        return SubShapes(TopAbs_VERTEX);\n      }\n\n      ListOfShapes operator*(const ListOfShapes& other) const\n      {\n        ListOfShapes common;\n        for(const auto& shape : (*this))\n          for(const auto& shape_o : other)\n            if(shape.IsSame(shape_o))\n              common.push_back(shape);\n        return common;\n      }\n\n      ListOfShapes GetHighestDimShapes() const\n      {\n        for (auto type : {TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX})\n        {\n          auto ret = SubShapes(type);\n          if (ret.size() > 0)\n            return ret;\n        }\n        return ListOfShapes();\n      }\n    };\n\n    inline ListOfShapes GetSolids(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetShells(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_SHELL); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetFaces(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetWires(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_WIRE); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetEdges(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_EDGE); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetVertices(const TopoDS_Shape & shape)\n    {\n      ListOfShapes sub;\n      for (TopExp_Explorer e(shape, TopAbs_VERTEX); e.More(); e.Next())\n        sub.push_back(e.Current());\n      return sub;\n    }\n\n    inline ListOfShapes GetHighestDimShapes(const TopoDS_Shape & shape)\n    {\n      auto ret = GetSolids(shape); if(ret.size() > 0) return ret;\n      ret = GetFaces(shape); if(ret.size() > 0) return ret;\n      ret = GetEdges(shape); if(ret.size() > 0) return ret;\n      ret = GetVertices(shape); if(ret.size() > 0) return ret;\n      return ListOfShapes();\n    }\n\n\n  class DirectionalInterval\n  {\n  public:\n    gp_Vec dir;\n    double minval = -1e99;\n    double maxval = 1e99;\n    bool openmin = false, openmax = false;\n\n    DirectionalInterval (gp_Vec adir) : dir(adir) { ; }\n    DirectionalInterval (const DirectionalInterval & i2) = default;\n\n    DirectionalInterval operator< (double val) const\n    {\n      DirectionalInterval i2 = *this;\n      i2.maxval = val;\n      i2.openmax = true;\n      return i2;\n    }\n\n    DirectionalInterval operator> (double val) const\n    {\n      DirectionalInterval i2 = *this;\n      i2.minval = val;\n      i2.openmin = true;\n      return i2;\n    }\n\n    DirectionalInterval operator<= (double val) const\n    {\n      DirectionalInterval i2 = *this;\n      i2.maxval = val;\n      i2.openmax = false;\n      return i2;\n    }\n\n    DirectionalInterval operator>= (double val) const\n    {\n      DirectionalInterval i2 = *this;\n      i2.minval = val;\n      i2.openmin = false;\n      return i2;\n    }\n\n    DirectionalInterval Intersect (const DirectionalInterval & i2)\n    {\n      DirectionalInterval res = *this;\n      res.minval = max(res.minval, i2.minval);\n      res.maxval = min(res.maxval, i2.maxval);\n      return res;\n    }\n\n    bool Contains (gp_Pnt p, double eps = 1e-8)\n    {\n      // cout << \"Contains point \" << p.X() << \",\" << p.Y() << \",\" << p.Z() << \" ? \" << endl;\n      double val = dir.X()*p.X() + dir.Y()*p.Y() + dir.Z() * p.Z();\n      // cout << \"minval = \" << minval << \", val = \" << val << \" maxval = \" << maxval << endl;\n      if (openmin) {\n        if (val < minval+eps) return false;\n      } else {\n        if (val < minval-eps) return false;\n      }\n      if (openmax) {\n        if (val > maxval-eps) return false;\n      } else {\n        if (val > maxval+eps) return false;\n      }\n      return true;\n    }\n  };\n\n  inline auto Properties (TopoDS_Shape shape)\n  {\n    GProp_GProps props;\n    double tol;\n    switch (shape.ShapeType())\n    {\n      case TopAbs_SOLID:\n      case TopAbs_COMPOUND:\n      case TopAbs_COMPSOLID:\n        tol = 1e-2 * BRep_Tool::MaxTolerance(shape, TopAbs_FACE);\n        BRepGProp::VolumeProperties (shape, props, tol); break;\n      case TopAbs_FACE:\n      case TopAbs_SHELL:\n        tol = 1e-2 * BRep_Tool::MaxTolerance(shape, TopAbs_FACE);\n        BRepGProp::SurfaceProperties (shape, props, tol); break;\n      case TopAbs_WIRE:\n      case TopAbs_EDGE:\n        tol = 1e-2 * BRep_Tool::MaxTolerance(shape, TopAbs_EDGE);\n        BRepGProp::LinearProperties(shape, props, tol); break;\n      default:\n        BRepGProp::LinearProperties(shape, props);\n    }\n    return props;\n  }\n\n  inline gp_Pnt Center (TopoDS_Shape shape)\n  {\n    return Properties(shape).CentreOfMass();\n  }\n\n  inline double Mass (TopoDS_Shape shape)\n  {\n    return Properties(shape).Mass();\n  }\n  \n}\n#endif // FILE_OCC_UTILS_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/occ_vertex.cpp",
    "content": "#include <BRepGProp.hxx>\n#include <BRep_Tool.hxx>\n\n#include \"occ_vertex.hpp\"\n\nnamespace netgen\n{\n\n    OCCVertex::OCCVertex( TopoDS_Shape s )\n        : vertex(TopoDS::Vertex(s))\n    {\n        p = occ2ng(vertex);\n    }\n\n    Point<3> OCCVertex::GetPoint() const\n    {\n        return p;\n    }\n}\n"
  },
  {
    "path": "libsrc/occ/occ_vertex.hpp",
    "content": "#ifndef FILE_OCC_VERTEX_INCLUDED\n#define FILE_OCC_VERTEX_INCLUDED\n\n// #pragma clang diagnostic push\n// #pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <TopoDS.hxx>\n#include <BRep_TVertex.hxx>\n\n// #pragma clang diagnostic pop\n\n#include \"meshing.hpp\"\n#include \"occ_utils.hpp\"\n\nnamespace netgen\n{\n    class OCCVertex : public GeometryVertex\n    {\n        TopoDS_Vertex vertex;\n        Point<3> p;\n\n        public:\n        OCCVertex( ) = default;\n        OCCVertex( TopoDS_Shape s );\n        ~OCCVertex() {}\n        Point<3> GetPoint() const override;\n    };\n}\n\n#endif // FILE_OCC_VERTEX_INCLUDED\n"
  },
  {
    "path": "libsrc/occ/occconstruction.cpp",
    "content": "\n#ifdef OCCGEOMETRY\n\n#include <mystdlib.h>\n#include <occgeom.hpp>  \n#include \"ShapeAnalysis_ShapeTolerance.hxx\"\n#include \"ShapeAnalysis_ShapeContents.hxx\"\n#include \"ShapeAnalysis_CheckSmallFace.hxx\"\n#include \"ShapeAnalysis_DataMapOfShapeListOfReal.hxx\"\n#include \"BRepAlgoAPI_Fuse.hxx\"\n#include \"BRepCheck_Analyzer.hxx\"\n#include \"BRepLib.hxx\"\n#include \"ShapeBuild_ReShape.hxx\"\n#include \"ShapeFix.hxx\"\n#include \"ShapeFix_FixSmallFace.hxx\"\n#include \"Partition_Spliter.hxx\"\n//#include \"VrmlAPI.hxx\"\n//#include \"StlAPI.hxx\"\n\n\n#include <GC_MakeSegment.hxx>\n#include <BRepBuilderAPI_MakeEdge.hxx>\n#include <BRepBuilderAPI_MakeWire.hxx>\n#include <BRepPrimAPI_MakeBox.hxx>\n// #include <BRep_Builder.hxx>\n#include <TopoDS_Builder.hxx>\n#include <BRepAlgoAPI_Cut.hxx>\n#include <BRepAlgoAPI_Common.hxx>\n#include <BRepAlgoAPI_Fuse.hxx>\n#include <BRepAlgoAPI_Section.hxx>\n#include <BRepOffsetAPI_Sewing.hxx>\n//#include <BRepAlgo_Sewing.hxx>\n#include <BRepOffsetAPI_MakeOffsetShape.hxx>\n#include <ShapeFix_Shape.hxx>\nnamespace netgen\n{\n\n  void OCCConstructGeometry (OCCGeometry & geom)\n  {\n#ifdef NOTHING\n    cout << \"OCC construction\" << endl;\n\n    BRep_Builder builder;\n    BRepPrimAPI_MakeBox mbox(gp_Pnt(-10e5, -15e5, 0), gp_Pnt(20e5, 15e5, 10e5));\n\n\n    /*\n    TopoDS_Shape air = TopoDS_Solid (mbox);\n    air = BRepAlgoAPI_Cut (air, geom.somap(1));\n    air = BRepAlgoAPI_Cut (air, geom.somap(2));\n    air = BRepAlgoAPI_Cut (air, geom.somap(3));\n    air = BRepAlgoAPI_Cut (air, geom.somap(4));\n    air = BRepAlgoAPI_Cut (air, geom.somap(5));\n    air = BRepAlgoAPI_Cut (air, geom.somap(6));\n    air = BRepAlgoAPI_Cut (air, geom.somap(7));\n    // air = BRepAlgoAPI_Cut (air, geom.somap(8));\n    air = BRepAlgoAPI_Cut (air, geom.somap(9));\n    // air = BRepAlgoAPI_Cut (air, geom.somap(10));\n    */\n\n    /*\n    BRepOffsetAPI_MakeOffsetShape dom8plus (geom.somap(8), 1e4, 1e-6);\n    BRepOffsetAPI_MakeOffsetShape dom6plus (geom.somap(6), 1e4, 1e-6);\n    dom8plus.Build();\n    ShapeFix_Shape fixshape(dom8plus.Shape());\n    fixshape.Perform();\n    \n    ShapeFix_Shape fix_dom2(geom.somap(2));\n    fix_dom2.Perform();\n\n\n    BRepAlgoAPI_Cut dom2m8(fix_dom2.Shape(), fixshape.Shape());\n    ShapeFix_Shape fix_dom2m8 (dom2m8);\n    fix_dom2m8.Perform();\n\n    builder.Add (geom.shape, \n\t\t BRepAlgoAPI_Cut \n\t\t (BRepAlgoAPI_Cut (geom.somap(2), dom6plus),\n\t\t  dom8plus));\n    // builder.Add (geom.shape, fix_dom2m8.Shape());\n    //     builder.Add (geom.shape, fixshape.Shape());\n    */\n\n    TopoDS_Shape my_fuse;\n    int cnt = 0;\n    for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next())\n      {\n\tif (cnt == 0)\n\t  my_fuse = exp_solid.Current();\n\telse\n\t  {\n\t    cout << \"fuse, cnt = \" << cnt << endl;\n\t    if (cnt != 7 && cnt != 9)\n\t      my_fuse = BRepAlgoAPI_Fuse (my_fuse, exp_solid.Current());\n\t  }\n\tcnt++;\n      }\n    builder.Add (geom.shape, my_fuse);\n\n    /*\n    ShapeUpgrade_ShellSewing ss;\n    ss.ApplySewing(geom.shape,1e5);\n    */\n\n    /*\n    BRepAlgo_Sewing sewing(1.e5);\n    \n    int cnt = 0;\n    for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next())\n      {\n\tcout << \"swe, cnt = \" << cnt << endl;\n\tif (cnt != 7 && cnt != 9)\n\t  sewing.Add (exp_solid.Current());\n\tcnt++;\n      }\n\n    sewing.Perform();\n    builder.Add (geom.shape, sewing.SewedShape());\n    */\n\n\n    /*\n    cout << \"build air domain\" << endl;\n    TopoDS_Shape air = BRepAlgoAPI_Cut (TopoDS_Solid (mbox), my_fuse);\n\n    cnt = 0;\n    for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next())\n      {\n\tcout << \"section, cnt = \" << cnt << endl;\n\tif (cnt == 7)\n\t  {\n\t    builder.Add (geom.shape, \n\t\t\t BRepAlgoAPI_Section (air, exp_solid.Current()));\n\t  }\n\tcnt++;\n      }\n    */\n\n\n\n    //    builder.Add (geom.shape, air);\n    for (int i = 1; i <= 10; i++)\n      builder.Remove (geom.shape, geom.somap(i));\n\n\n\n\n    geom.BuildFMap();\n    geom.BuildVisualizationMesh();\n    geom.changed = 1;\n#endif\n\n  }\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/occgenmesh.cpp",
    "content": "#ifdef OCCGEOMETRY\r\n\r\n#include <mystdlib.h>\r\n#include <meshing.hpp>\r\n\r\n#include \"occgeom.hpp\"\r\n#include \"occ_face.hpp\"\r\n#include \"occmeshsurf.hpp\"\r\n\r\n#include <BRepAdaptor_Curve.hxx>\r\n#include <BRepGProp.hxx>\r\n#include <BRepLProp_CLProps.hxx>\r\n#include <BRepLProp_SLProps.hxx>\r\n#include <BRepTools.hxx>\r\n#include <GProp_GProps.hxx>\r\n#include <Quantity_Color.hxx>\r\n#include <ShapeAnalysis.hxx>\r\n#include <TopExp.hxx>\r\n#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>\r\n#include <TopoDS_Edge.hxx>\r\n\r\nnamespace netgen\r\n{\r\n\r\n\r\n#define TCL_OK 0\r\n#define TCL_ERROR 1\r\n\r\n#define DIVIDEEDGESECTIONS 10000   // better solution to come soon\r\n#define IGNORECURVELENGTH 0\r\n#define VSMALL 1e-10\r\n\r\n\r\n  DLL_HEADER bool merge_solids = false;\r\n\r\n\r\n  // can you please explain what you intend to compute here (JS) !!!\r\n  double Line :: Dist (Line l)\r\n  {\r\n    Vec<3> n = p1-p0;\r\n    Vec<3> q = l.p1-l.p0;\r\n    double nq = n*q;\r\n\r\n    Point<3> p = p0 + 0.5*n;\r\n    double lambda = (p-l.p0)*n / (nq + VSMALL);\r\n\r\n    if (lambda >= 0 && lambda <= 1)\r\n      {\r\n        double d = (p-l.p0-lambda*q).Length();\r\n        //        if (d < 1e-3) d = 1e99;\r\n        return d;\r\n      }\r\n    else\r\n      return 1e99;\r\n  }\r\n\r\n\r\n  double ComputeH (double kappa, const MeshingParameters & mparam)\r\n  {\r\n    kappa *= mparam.curvaturesafety;\r\n    /*\r\n    double hret;\r\n\r\n    if (mparam.maxh * kappa < 1)\r\n      hret = mparam.maxh;\r\n    else\r\n      hret = 1 / (kappa + VSMALL);\r\n\r\n    if (mparam.maxh < hret)\r\n      hret = mparam.maxh;\r\n\r\n    return hret;\r\n    */\r\n    // return min(mparam.maxh, 1/kappa);\r\n    return (mparam.maxh*kappa < 1) ? mparam.maxh : 1/kappa;\r\n  }\r\n\r\n\r\n\r\n  void RestrictHTriangle (gp_Pnt2d & par0, gp_Pnt2d & par1, gp_Pnt2d & par2,\r\n                          BRepLProp_SLProps * prop, BRepLProp_SLProps * prop2, Mesh & mesh, int depth, double h, int layer, const MeshingParameters & mparam)\r\n  {\r\n    int ls = -1;\r\n\r\n    gp_Pnt pnt0,pnt1,pnt2;\r\n\r\n    prop->SetParameters (par0.X(), par0.Y());\r\n    pnt0 = prop->Value();\r\n\r\n    prop->SetParameters (par1.X(), par1.Y());\r\n    pnt1 = prop->Value();\r\n\r\n    prop->SetParameters (par2.X(), par2.Y());\r\n    pnt2 = prop->Value();\r\n\r\n    double aux;\r\n    double maxside = pnt0.Distance(pnt1);\r\n    ls = 2;\r\n    aux = pnt1.Distance(pnt2);\r\n    if(aux > maxside)\r\n      {\r\n        maxside = aux;\r\n        ls = 0;\r\n      }\r\n    aux = pnt2.Distance(pnt0);\r\n    if(aux > maxside)\r\n      {\r\n        maxside = aux;\r\n        ls = 1;\r\n      }\r\n\r\n\r\n\r\n    gp_Pnt2d parmid;\r\n\r\n    parmid.SetX( (par0.X()+par1.X()+par2.X()) / 3 );\r\n    parmid.SetY( (par0.Y()+par1.Y()+par2.Y()) / 3 );\r\n\r\n    if (depth%3 == 0)\r\n      {\r\n        double curvature = 0;\r\n\r\n        prop2->SetParameters (parmid.X(), parmid.Y());\r\n        if (!prop2->IsCurvatureDefined())\r\n          {\r\n            (*testout) << \"curvature not defined!\" << endl;\r\n            return;\r\n          }\r\n        curvature = max(fabs(prop2->MinCurvature()),\r\n                        fabs(prop2->MaxCurvature()));\r\n\r\n        prop2->SetParameters (par0.X(), par0.Y());\r\n        if (!prop2->IsCurvatureDefined())\r\n          {\r\n            (*testout) << \"curvature not defined!\" << endl;\r\n            return;\r\n          }\r\n        curvature = max(curvature,max(fabs(prop2->MinCurvature()),\r\n                                      fabs(prop2->MaxCurvature())));\r\n\r\n        prop2->SetParameters (par1.X(), par1.Y());\r\n        if (!prop2->IsCurvatureDefined())\r\n          {\r\n            (*testout) << \"curvature not defined!\" << endl;\r\n            return;\r\n          }\r\n        curvature = max(curvature,max(fabs(prop2->MinCurvature()),\r\n                                      fabs(prop2->MaxCurvature())));\r\n\r\n        prop2->SetParameters (par2.X(), par2.Y());\r\n        if (!prop2->IsCurvatureDefined())\r\n          {\r\n            (*testout) << \"curvature not defined!\" << endl;\r\n            return;\r\n          }\r\n        curvature = max(curvature,max(fabs(prop2->MinCurvature()),\r\n                                      fabs(prop2->MaxCurvature())));\r\n\r\n        //(*testout) << \"curvature \" << curvature << endl;\r\n\r\n        if (curvature < 1e-3)\r\n          {\r\n            //(*testout) << \"curvature too small (\" << curvature << \")!\" << endl;\r\n            return;\r\n            // return war bis 10.2.05 auskommentiert\r\n          }\r\n\r\n\r\n\r\n        h = ComputeH (curvature+1e-10, mparam);\r\n\r\n        if(h < 1e-4*maxside)\r\n          return;\r\n\r\n\r\n        // if (h > 30) return;\r\n      }\r\n\r\n    if (h < maxside && depth < 10)\r\n      {\r\n        //cout << \"\\r h \" << h << flush;\r\n        gp_Pnt2d pm;\r\n\r\n        //cout << \"h \" << h << \" maxside \" << maxside << \" depth \" << depth << endl;\r\n        //cout << \"par0 \" << par0.X() << \" \" << par0.Y()\r\n        //<< \" par1 \" << par1.X() << \" \" << par1.Y()\r\n        //   << \" par2 \" << par2.X() << \" \" << par2.Y()<< endl;\r\n\r\n        if(ls == 0)\r\n          {\r\n            pm.SetX(0.5*(par1.X()+par2.X())); pm.SetY(0.5*(par1.Y()+par2.Y()));\r\n            RestrictHTriangle(pm, par2, par0, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n            RestrictHTriangle(pm, par0, par1, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n          }\r\n        else if(ls == 1)\r\n          {\r\n            pm.SetX(0.5*(par0.X()+par2.X())); pm.SetY(0.5*(par0.Y()+par2.Y()));\r\n            RestrictHTriangle(pm, par1, par2, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n            RestrictHTriangle(pm, par0, par1, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n          }\r\n        else if(ls == 2)\r\n          {\r\n            pm.SetX(0.5*(par0.X()+par1.X())); pm.SetY(0.5*(par0.Y()+par1.Y()));\r\n            RestrictHTriangle(pm, par1, par2, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n            RestrictHTriangle(pm, par2, par0, prop, prop2, mesh, depth+1, h, layer, mparam);\r\n          }\r\n\r\n      }\r\n    else\r\n      {\r\n        gp_Pnt pnt;\r\n        Point3d p3d;\r\n\r\n        prop->SetParameters (parmid.X(), parmid.Y());\r\n        pnt = prop->Value();\r\n        p3d = Point3d(pnt.X(), pnt.Y(), pnt.Z());\r\n        mesh.RestrictLocalH (p3d, h, layer);\r\n\r\n        p3d = Point3d(pnt0.X(), pnt0.Y(), pnt0.Z());\r\n        mesh.RestrictLocalH (p3d, h, layer);\r\n\r\n        p3d = Point3d(pnt1.X(), pnt1.Y(), pnt1.Z());\r\n        mesh.RestrictLocalH (p3d, h, layer);\r\n\r\n        p3d = Point3d(pnt2.X(), pnt2.Y(), pnt2.Z());\r\n        mesh.RestrictLocalH (p3d, h, layer);\r\n\r\n        //(*testout) << \"p = \" << p3d << \", h = \" << h << \", maxside = \" << maxside << endl;\r\n\r\n      }\r\n  }\r\n\r\n  bool OCCMeshFace (const OCCGeometry & geom, Mesh & mesh, FlatArray<int, PointIndex> glob2loc,\r\n                       const MeshingParameters & mparam, int nr, int projecttype, bool delete_on_failure)\r\n  {\r\n    auto k = nr+1;\r\n    if(1==0 && !geom.fvispar[k-1].IsDrawable())\r\n      {\r\n        (*testout) << \"ignoring face \" << k << endl;\r\n        cout << \"ignoring face \" << k << endl;\r\n        return true;\r\n      }\r\n\r\n    // if(master_faces[k]!=k)\r\n    //     continue;\r\n\r\n    (*testout) << \"mesh face \" << k << endl;\r\n    multithread.percent = 100 * k / (mesh.GetNFD() + VSMALL);\r\n    geom.facemeshstatus[k-1] = -1;\r\n\r\n    // FaceDescriptor & fd = mesh.GetFaceDescriptor(k);\r\n    auto face = TopoDS::Face(geom.fmap(k));\r\n    const auto& occface = dynamic_cast<const OCCFace&>(geom.GetFace(k-1));\r\n\r\n    int oldnf = mesh.GetNSE();\r\n\r\n    Box<3> bb = geom.GetBoundingBox();\r\n\r\n    // int projecttype = PLANESPACE;\r\n    // int projecttype = PARAMETERSPACE;\r\n    \r\n    static Timer tinit(\"init\");\r\n    tinit.Start();\r\n    Meshing2OCCSurfaces meshing(geom, face, bb, projecttype, mparam);\r\n    tinit.Stop();\r\n\r\n\r\n    static Timer tprint(\"print\");\r\n    tprint.Start();\r\n    if (meshing.GetProjectionType() == PLANESPACE)\r\n      PrintMessage (2, \"Face \", k, \" / \", geom.GetNFaces(), \" (plane space projection)\");\r\n    else\r\n      PrintMessage (2, \"Face \", k, \" / \", geom.GetNFaces(), \" (parameter space projection)\");\r\n    tprint.Stop();\r\n\r\n    //      Meshing2OCCSurfaces meshing(f2, bb);\r\n    // meshing.SetStartTime (starttime);\r\n    //(*testout) << \"Face \" << k << endl << endl;\r\n    \r\n\r\n    auto segments = geom.GetFace(k-1).GetBoundary(mesh);\r\n\r\n    if (meshing.GetProjectionType() == PLANESPACE)\r\n      {\r\n        static Timer t(\"MeshSurface: Find edges and points - Physical\"); RegionTimer r(t);\r\n        int cntp = 0;\r\n        glob2loc = 0;\r\n\r\n        for (Segment & seg : segments)\r\n          // if (seg.si == k)\r\n            for (int j = 0; j < 2; j++)\r\n              {\r\n                PointIndex pi = seg[j];\r\n                if (glob2loc[pi] == 0)\r\n                  {\r\n                    meshing.AddPoint (mesh.Point(pi), pi);\r\n                    cntp++;\r\n                    glob2loc[pi] = cntp;\r\n                  }\r\n              }\r\n        for(const auto& vert : geom.GetFaceVertices(geom.GetFace(k-1)))\r\n          {\r\n            PointIndex pi = vert->nr + IndexBASE<PointIndex>();\r\n            if(glob2loc[pi] == 0)\r\n              {\r\n                auto gi = occface.Project(mesh[pi]);\r\n                MultiPointGeomInfo mgi;\r\n                mgi.AddPointGeomInfo(gi);\r\n                meshing.AddPoint(mesh[pi], pi, &mgi);\r\n                cntp++;\r\n                glob2loc[pi] = cntp;\r\n              }\r\n          }\r\n\r\n\r\n        /*\r\n        for (int i = 1; i <= mesh.GetNSeg(); i++)\r\n          {\r\n            Segment & seg = mesh.LineSegment(i);\r\n        */\r\n        // for (Segment & seg : mesh.LineSegments())                \r\n        for (Segment & seg : segments)\r\n          //if (seg.si == k)\r\n            {\r\n              PointGeomInfo gi0, gi1;\r\n              gi0.trignum = gi1.trignum = k;\r\n              gi0.u = seg.epgeominfo[0].u;\r\n              gi0.v = seg.epgeominfo[0].v;\r\n              gi1.u = seg.epgeominfo[1].u;\r\n              gi1.v = seg.epgeominfo[1].v;\r\n              \r\n              //if(orientation & 1)\r\n              meshing.AddBoundaryElement (glob2loc[seg[0]], glob2loc[seg[1]], gi0, gi1);\r\n\r\n            }\r\n      }\r\n    else\r\n      {\r\n        static Timer t(\"MeshSurface: Find edges and points - Parameter\"); RegionTimer r(t);\r\n\r\n        Array<PointGeomInfo> gis(2*segments.Size());\r\n        gis.SetSize (0);\r\n        glob2loc = 0;\r\n        // int cntpt = 0;\r\n\r\n        Box<2> uv_box(Box<2>::EMPTY_BOX);\r\n        for(auto & seg : segments)\r\n            for(auto i : Range(2))\r\n                uv_box.Add( {seg.epgeominfo[i].u, seg.epgeominfo[i].v } );\r\n\r\n        BoxTree<2> uv_tree(uv_box);\r\n        double tol = 1e99;\r\n        for(auto& seg : segments)\r\n          {\r\n            Point<2> p1 = { seg.epgeominfo[0].u, seg.epgeominfo[0].v };\r\n            Point<2> p2 = { seg.epgeominfo[1].u, seg.epgeominfo[1].v };\r\n            tol = min2(tol, Dist(p1, p2));\r\n          }\r\n        uv_tree.SetTolerance(0.9 * tol);\r\n        Array<int> found_points;\r\n\r\n        for(auto & seg : segments)\r\n        {\r\n            PointGeomInfo gi[2];\r\n            gi[0].trignum = gi[1].trignum = k;\r\n            gi[0].u = seg.epgeominfo[0].u;\r\n            gi[0].v = seg.epgeominfo[0].v;\r\n            gi[1].u = seg.epgeominfo[1].u;\r\n            gi[1].v = seg.epgeominfo[1].v;\r\n\r\n            int locpnum[2] = {0, 0};\r\n\r\n            for (int j = 0; j < 2; j++)\r\n            {\r\n                Point<2> uv = {gi[j].u, gi[j].v};\r\n                uv_tree.GetIntersecting(uv, uv, found_points);\r\n\r\n                bool found = false;\r\n                for(auto& fp : found_points)\r\n                  {\r\n                    if(meshing.GetGlobalIndex(fp - 1) == seg[j])\r\n                      {\r\n                        locpnum[j] = fp;\r\n                        found = true;\r\n                      }\r\n                  }\r\n                if(!found)\r\n                {\r\n                    PointIndex pi = seg[j];\r\n                    locpnum[j] = meshing.AddPoint (mesh.Point(pi), pi) + 1;\r\n                    glob2loc[pi] = locpnum[j];\r\n                    gis.Append (gi[j]);\r\n                    uv_tree.Insert(uv, locpnum[j]);\r\n                }\r\n            }\r\n\r\n            meshing.AddBoundaryElement (locpnum[0], locpnum[1], gi[0], gi[1]);\r\n        }\r\n        for(const auto& vert : geom.GetFaceVertices(geom.GetFace(k-1)))\r\n          {\r\n            PointIndex pi = vert->nr + IndexBASE<PointIndex>();\r\n            if(glob2loc[pi] == 0)\r\n              {\r\n                auto gi = occface.Project(mesh[pi]);\r\n                MultiPointGeomInfo mgi;\r\n                mgi.AddPointGeomInfo(gi);\r\n                glob2loc[pi] = meshing.AddPoint(mesh[pi], pi, &mgi) + 1;\r\n                gis.Append(gi);\r\n                Point<2> uv = { gi.u, gi.v };\r\n                uv_tree.Insert(uv, glob2loc[pi]);\r\n              }\r\n          }\r\n      }\r\n\r\n\r\n    // Philippose - 15/01/2009\r\n    auto& props = occface.properties;\r\n    double maxh = min2(geom.face_maxh[k-1], props.maxh);\r\n    //double maxh = mparam.maxh;\r\n    //      int noldpoints = mesh->GetNP();\r\n    int noldsurfel = mesh.GetNSE();\r\n    int layer = props.layer;\r\n\r\n    static Timer tsurfprop(\"surfprop\");\r\n    tsurfprop.Start();\r\n    GProp_GProps sprops;\r\n    BRepGProp::SurfaceProperties(TopoDS::Face(geom.fmap(k)),sprops);\r\n    tsurfprop.Stop();\r\n    meshing.SetMaxArea(2.*sprops.Mass());\r\n\r\n    MESHING2_RESULT res;\r\n\r\n    // TODO: check overlap not correctly working here\r\n    MeshingParameters mparam_without_overlap = mparam;\r\n    mparam_without_overlap.checkoverlap = false;\r\n    \r\n    try {\r\n      static Timer t(\"GenerateMesh\"); RegionTimer reg(t);\r\n      res = meshing.GenerateMesh (mesh, mparam_without_overlap, maxh, k, layer);\r\n    }\r\n\r\n    catch (SingularMatrixException)\r\n      {\r\n        // (*myerr) << \"Singular Matrix\" << endl;\r\n        res = MESHING2_GIVEUP;\r\n      }\r\n\r\n    catch (UVBoundsException)\r\n      {\r\n        // (*myerr) << \"UV bounds exceeded\" << endl;\r\n        res = MESHING2_GIVEUP;\r\n      }\r\n\r\n    static Timer t1(\"rest of loop\"); RegionTimer reg1(t1);\r\n      \r\n    bool meshing_failed = res != MESHING2_OK;\r\n    if(meshing_failed && delete_on_failure)\r\n    {\r\n        for (SurfaceElementIndex sei = noldsurfel; sei < mesh.GetNSE(); sei++)\r\n            mesh.Delete(sei);\r\n\r\n        mesh.Compress();\r\n    }\r\n\r\n    for (SurfaceElementIndex sei = oldnf; sei < mesh.GetNSE(); sei++)\r\n      mesh[sei].SetIndex (k);\r\n\r\n    auto n_illegal_trigs = mesh.FindIllegalTrigs();\r\n    PrintMessage (3, n_illegal_trigs, \" illegal triangles\");\r\n    return meshing_failed;\r\n  }\r\n\r\n\r\n  void OCCSetLocalMeshSize(const OCCGeometry & geom, Mesh & mesh,\r\n                           const MeshingParameters & mparam, const OCCParameters& occparam)\r\n  {\r\n    static Timer t1(\"OCCSetLocalMeshSize\");\r\n    RegionTimer regt(t1);\r\n    mesh.SetGlobalH (mparam.maxh);\r\n    mesh.SetMinimalH (mparam.minh);\r\n\r\n    NgArray<double> maxhdom;\r\n    maxhdom.SetSize (geom.NrSolids());\r\n    maxhdom = mparam.maxh;\r\n    int maxlayer = 1;\r\n\r\n    for(auto dom : Range(geom.GetNSolids()))\r\n    {\r\n      auto & props = geom.GetSolid(dom).properties;\r\n      maxhdom[dom] = min2(maxhdom[dom], props.maxh);\r\n      maxlayer = max2(maxlayer, props.layer);\r\n    }\r\n\r\n    for(auto & f : geom.Faces())\r\n      maxlayer = max2(maxlayer, f->properties.layer);\r\n\r\n    for(auto & e : geom.Edges())\r\n      maxlayer = max2(maxlayer, e->properties.layer);\r\n\r\n    mesh.SetMaxHDomain (maxhdom);\r\n\r\n    Box<3> bb = geom.GetBoundingBox();\r\n    bb.Increase (bb.Diam()/10);\r\n\r\n    if (mparam.uselocalh)\r\n      {\r\n        const char * savetask = multithread.task;\r\n        multithread.percent = 0;\r\n\r\n        for(auto layer : Range(1, maxlayer+1))\r\n            mesh.SetLocalH (bb.PMin(), bb.PMax(), mparam.grading, layer);\r\n\r\n        for(auto& v : geom.Vertices())\r\n          {\r\n            auto& props = v->properties;\r\n            if(props.maxh < 1e99)\r\n                mesh.GetLocalH(props.layer)->SetH(v->GetPoint(), props.maxh);\r\n          }\r\n\r\n        int nedges = geom.emap.Extent();\r\n\r\n        double mincurvelength = IGNORECURVELENGTH;\r\n        double maxedgelen = 0;\r\n        double minedgelen = 1e99;\r\n\r\n        if(occparam.resthminedgelenenable) \r\n          {\r\n            mincurvelength = occparam.resthminedgelen;\r\n            if(mincurvelength < IGNORECURVELENGTH) mincurvelength = IGNORECURVELENGTH;\r\n          }\r\n\r\n        multithread.task = \"Setting local mesh size (elements per edge)\";\r\n\r\n        // setting elements per edge\r\n        for (int i = 1; i <= nedges && !multithread.terminate; i++)\r\n          {\r\n            TopoDS_Edge e = TopoDS::Edge (geom.emap(i));\r\n            multithread.percent = 100 * (i-1)/double(nedges);\r\n            if (BRep_Tool::Degenerated(e)) continue;\r\n\r\n            double len = Mass(e);\r\n\r\n            if (len < mincurvelength)\r\n              {\r\n                (*testout) << \"ignored\" << endl;\r\n                continue;\r\n              }\r\n\r\n            bool is_identified_edge = false;\r\n            // TODO: change to use hash value\r\n            const auto& gedge = geom.GetEdge(e);\r\n            auto& v0 = gedge.GetStartVertex();\r\n            auto& v1 = gedge.GetEndVertex();\r\n            for(auto & ident : v0.identifications)\r\n            {\r\n                auto other = ident.from == &v0 ? ident.to : ident.from;\r\n                if(other->nr == v1.nr && ident.type == Identifications::CLOSESURFACES)\r\n                {\r\n                    is_identified_edge = true;\r\n                    break;\r\n                }\r\n            }\r\n\r\n            if(is_identified_edge)\r\n              continue;\r\n\r\n            double localh = len/mparam.segmentsperedge;\r\n            double s0, s1;\r\n\r\n            Handle(Geom_Curve) c = BRep_Tool::Curve(e, s0, s1);\r\n\r\n            const auto & props = gedge.properties;\r\n            localh = min2(localh, props.maxh);\r\n            maxedgelen = max (maxedgelen, len);\r\n            minedgelen = min (minedgelen, len);\r\n            int maxj = max((int) ceil(len/localh)*2, 2);\r\n\r\n            for (int j = 0; j <= maxj; j++)\r\n              {\r\n                gp_Pnt pnt = c->Value (s0+double(j)/maxj*(s1-s0));\r\n                mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), localh, props.layer);\r\n              }\r\n          }\r\n\r\n        multithread.task = \"Setting local mesh size (edge curvature)\";\r\n\r\n        // setting edge curvature\r\n\r\n        int nsections = 20;\r\n\r\n        for (int i = 1; i <= nedges && !multithread.terminate; i++)\r\n          {\r\n            double maxcur = 0;\r\n            multithread.percent = 100 * (i-1)/double(nedges);\r\n            TopoDS_Edge edge = TopoDS::Edge (geom.emap(i));\r\n            if (BRep_Tool::Degenerated(edge)) continue;\r\n            double s0, s1;\r\n            Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);\r\n            BRepAdaptor_Curve brepc(edge);\r\n            BRepLProp_CLProps prop(brepc, 2, 1e-5);\r\n            auto layer = geom.GetEdge(edge).properties.layer;\r\n\r\n            for (int j = 1; j <= nsections; j++)\r\n              {\r\n                double s = s0 + j/(double) nsections * (s1-s0);\r\n                prop.SetParameter (s);\r\n                double curvature = 0;\r\n                if(prop.IsTangentDefined())\r\n                  curvature = prop.Curvature();\r\n                if(curvature> maxcur) maxcur = curvature;\r\n\r\n                if (curvature >= 1e99)\r\n                  continue;\r\n\r\n                gp_Pnt pnt = c->Value (s);\r\n\r\n                mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), ComputeH (fabs(curvature), mparam), layer);\r\n              }\r\n          }\r\n\r\n        multithread.task = \"Setting local mesh size (face curvature)\";\r\n\r\n        // setting face curvature\r\n\r\n        int nfaces = geom.fmap.Extent();\r\n\r\n        BuildTriangulation(geom.shape);\r\n        for (int i = 1; i <= nfaces && !multithread.terminate; i++)\r\n          {\r\n            multithread.percent = 100 * (i-1)/double(nfaces);\r\n            TopoDS_Face face = TopoDS::Face(geom.fmap(i));\r\n            TopLoc_Location loc;\r\n            Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\r\n            Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\r\n\r\n            if(triangulation.IsNull())\r\n              {\r\n                if (geom.shape.Infinite())\r\n                  throw Exception(\"Cannot generate mesh for an infinite geometry\");\r\n                else\r\n                  throw Exception(\"OCC-Triangulation could not be built\");\r\n              }\r\n            \r\n            BRepAdaptor_Surface sf(face, Standard_True);\r\n            // one prop for evaluating and one for derivatives\r\n            BRepLProp_SLProps prop(sf, 0, 1e-5);\r\n            BRepLProp_SLProps prop2(sf, 2, 1e-5);\r\n            auto layer = geom.GetFace(face).properties.layer;\r\n\r\n            int ntriangles = triangulation -> NbTriangles();\r\n            for (int j = 1; j <= ntriangles; j++)\r\n              {\r\n                gp_Pnt p[3];\r\n                gp_Pnt2d par[3];\r\n\r\n                for (int k = 1; k <=3; k++)\r\n                  {\r\n                    // int n = triangulation->Triangles()(j)(k);\r\n                    // p[k-1] = triangulation->Nodes()(n).Transformed(loc);\r\n                    // par[k-1] = triangulation->UVNodes()(n);\r\n                    // fix for OCC7.6.0-dev\r\n                    int n = triangulation->Triangle(j)(k);\r\n                    p[k-1] = triangulation->Node(n).Transformed(loc);\r\n                    par[k-1] = triangulation->UVNode(n);\r\n                  }\r\n\r\n                //double maxside = 0;\r\n                //maxside = max (maxside, p[0].Distance(p[1]));\r\n                //maxside = max (maxside, p[0].Distance(p[2]));\r\n                //maxside = max (maxside, p[1].Distance(p[2]));\r\n                //cout << \"\\rFace \" << i << \" pos11 ntriangles \" << ntriangles << \" maxside \" << maxside << flush;\r\n\r\n                RestrictHTriangle (par[0], par[1], par[2], &prop, &prop2, mesh, 0, 0, layer, mparam);\r\n                //cout << \"\\rFace \" << i << \" pos12 ntriangles \" << ntriangles << flush;\r\n              }\r\n          }\r\n\r\n        // setting close edges\r\n\r\n        if (mparam.closeedgefac.has_value())\r\n          {\r\n            multithread.task = \"Setting local mesh size (close edges)\";\r\n\r\n            int sections = 100;\r\n\r\n            NgArray<Line> lines(sections*nedges);\r\n\r\n            /*\r\n            BoxTree<3> * searchtree =\r\n              new BoxTree<3> (bb.PMin(), bb.PMax());\r\n            */\r\n            BoxTree<3> searchtree(bb.PMin(), bb.PMax());\r\n            \r\n            int nlines = 0;\r\n            Array<int> edgenumber;\r\n            for (int i = 1; i <= nedges && !multithread.terminate; i++)\r\n              {\r\n                TopoDS_Edge edge = TopoDS::Edge (geom.emap(i));\r\n                int layer = geom.GetEdge(edge).properties.layer;\r\n                if (BRep_Tool::Degenerated(edge)) continue;\r\n\r\n                double s0, s1;\r\n                Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);\r\n                BRepAdaptor_Curve brepc(edge);\r\n                BRepLProp_CLProps prop(brepc, 1, 1e-5);\r\n                prop.SetParameter (s0);\r\n\r\n                gp_Vec d0 = prop.D1().Normalized();\r\n                double s_start = s0;\r\n                // int count = 0;\r\n                for (int j = 1; j <= sections; j++)\r\n                  {\r\n                    double s = s0 + (s1-s0)*(double)j/(double)sections;\r\n                    prop.SetParameter (s);\r\n                    gp_Vec d1 = prop.D1().Normalized();\r\n                    double cosalpha = fabs(d0*d1);\r\n                    if ((j == sections) || (cosalpha < cos(10.0/180.0*M_PI)))\r\n                      {\r\n                        // count++;\r\n                        gp_Pnt p0 = c->Value (s_start);\r\n                        gp_Pnt p1 = c->Value (s);\r\n                        lines[nlines].p0 = Point<3> (p0.X(), p0.Y(), p0.Z());\r\n                        lines[nlines].p1 = Point<3> (p1.X(), p1.Y(), p1.Z());\r\n                        lines[nlines].layer = layer;\r\n\r\n                        Box3d box;\r\n                        box.SetPoint (Point3d(lines[nlines].p0));\r\n                        box.AddPoint (Point3d(lines[nlines].p1));\r\n\r\n                        searchtree.Insert (box.PMin(), box.PMax(), nlines+1);\r\n                        nlines++;\r\n                        edgenumber.Append(i);\r\n\r\n                        s_start = s;\r\n                        d0 = d1;\r\n                      }\r\n                  }\r\n              }\r\n\r\n            NgArray<int> linenums;\r\n            auto is_identified_edge = [&](int e0, int e1) {\r\n                const auto& edge0 = geom.GetEdge(e0-1);\r\n                const auto& edge1 = geom.GetEdge(e1-1);\r\n\r\n                if(edge0.primary == edge1.primary)\r\n                    return true;\r\n\r\n                Array<const GeometryVertex *> v0 = { &edge0.GetStartVertex(), &edge0.GetEndVertex() };\r\n                Array<const GeometryVertex *> v1 = { &edge1.GetStartVertex(), &edge1.GetEndVertex() };\r\n                for(auto i : Range(2))\r\n                    for(auto j : Range(2))\r\n                        if(v0[i]->primary == v1[j]->primary)\r\n                            return true;\r\n\r\n                return false;\r\n            };\r\n\r\n            for (int i = 0; i < nlines; i++)\r\n              {\r\n                multithread.percent = (100*i)/double(nlines);\r\n                Line & line = lines[i];\r\n\r\n                Box3d box;\r\n                box.SetPoint (Point3d(line.p0));\r\n                box.AddPoint (Point3d(line.p1));\r\n                double maxhline = max (mesh.GetH(box.PMin(), line.layer),\r\n                                       mesh.GetH(box.PMax(), line.layer));\r\n                box.Increase(maxhline);\r\n\r\n                double mindist = 1e99;\r\n                linenums.SetSize(0);\r\n                searchtree.GetIntersecting(box.PMin(),box.PMax(),linenums);\r\n\r\n                for (int j = 0; j < linenums.Size(); j++)\r\n                  {\r\n                    int num = linenums[j]-1;\r\n                    if (i == num) continue;\r\n                    if (line.layer != lines[num].layer) continue;\r\n                    if( is_identified_edge(edgenumber[i], edgenumber[num]) ) continue;\r\n                    if ((line.p0-lines[num].p0).Length2() < 1e-15) continue;\r\n                    if ((line.p0-lines[num].p1).Length2() < 1e-15) continue;\r\n                    if ((line.p1-lines[num].p0).Length2() < 1e-15) continue;\r\n                    if ((line.p1-lines[num].p1).Length2() < 1e-15) continue;\r\n                    mindist = min (mindist, line.Dist(lines[num]));\r\n                  }\r\n\r\n                mindist /= (*mparam.closeedgefac + VSMALL);\r\n\r\n                if (mindist < 1e-3 * bb.Diam())\r\n                  {\r\n                    (*testout) << \"extremely small local h: \" << mindist\r\n                               << \" --> setting to \" << 1e-3 * bb.Diam() << endl;\r\n                    (*testout) << \"somewhere near \" << line.p0 << \" - \" << line.p1 << endl;\r\n                    mindist = 1e-3 * bb.Diam();\r\n                  }\r\n\r\n                mesh.RestrictLocalHLine(line.p0, line.p1, mindist, line.layer);\r\n              }\r\n          }\r\n\r\n        for (auto mspnt : mparam.meshsize_points)\r\n          mesh.RestrictLocalH(mspnt.pnt, mspnt.h, mspnt.layer);\r\n\r\n        multithread.task = savetask;\r\n\r\n      }\r\n\r\n    mesh.LoadLocalMeshSize (mparam.meshsizefilename);\r\n  }\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "libsrc/occ/occgeom.cpp",
    "content": "\r\n#ifdef OCCGEOMETRY\r\n\r\n#include <cstdio>\r\n#include <set>\r\n\r\n#include <mystdlib.h>\r\n#include <core/register_archive.hpp>\r\n\r\n#include \"occ_vertex.hpp\"\r\n#include \"occ_edge.hpp\"\r\n#include \"occ_face.hpp\"\r\n#include \"occ_solid.hpp\"\r\n#include \"occgeom.hpp\"\r\n#include \"Partition_Spliter.hxx\"\r\n\r\n#include <BinTools.hxx>\r\n#include <BOPAlgo_Builder.hxx>\r\n#include <BRepBndLib.hxx>\r\n#include <BRepBuilderAPI_Copy.hxx>\r\n#include <BRepBuilderAPI_MakeSolid.hxx>\r\n#include <BRepBuilderAPI_MakeVertex.hxx>\r\n#include <BRepCheck_Analyzer.hxx>\r\n#include <BRepExtrema_DistShapeShape.hxx>\r\n#include <BRepGProp.hxx>\r\n#include <BRepLib.hxx>\r\n#include <BRepOffsetAPI_Sewing.hxx>\r\n#include <BRepTools.hxx>\r\n#include <IGESCAFControl_Reader.hxx>\r\n#include <IGESControl_Writer.hxx>\r\n#include <Interface_InterfaceModel.hxx>\r\n#include <Interface_Static.hxx>\r\n#include <STEPCAFControl_Writer.hxx>\r\n#include <STEPConstruct.hxx>\r\n#include <STEPControl_Writer.hxx>\r\n#include <ShapeAnalysis_CheckSmallFace.hxx>\r\n#include <ShapeAnalysis_DataMapOfShapeListOfReal.hxx>\r\n#include <ShapeAnalysis_ShapeContents.hxx>\r\n#include <ShapeBuild_ReShape.hxx>\r\n#include <ShapeFix_Face.hxx>\r\n#include <ShapeFix_FixSmallFace.hxx>\r\n#include <ShapeFix_Shape.hxx>\r\n#include <ShapeFix_Wire.hxx>\r\n#include <ShapeFix_Wireframe.hxx>\r\n#include <StepBasic_ProductDefinitionRelationship.hxx>\r\n#include <StepRepr_RepresentationItem.hxx>\r\n#include <StlAPI_Writer.hxx>\r\n#include <TopoDS_Shape.hxx>\r\n#include <TransferBRep.hxx>\r\n#include <Transfer_FinderProcess.hxx>\r\n#include <Transfer_TransientProcess.hxx>\r\n#include <XCAFApp_Application.hxx>\r\n#include <XCAFDoc_ColorTool.hxx>\r\n#include <XCAFDoc_DocumentTool.hxx>\r\n#include <XCAFDoc_ShapeTool.hxx>\r\n#include <XCAFPrs.hxx>\r\n#include <XCAFPrs_Style.hxx>\r\n#include <XSControl_TransferReader.hxx>\r\n#include <XSControl_WorkSession.hxx>\r\n\r\n#if OCC_VERSION_HEX < 0x070000\r\n// pass\r\n#elif OCC_VERSION_HEX < 0x070200\r\n   #include <StlTransfer.hxx>\r\n   #include <TopoDS_Iterator.hxx>\r\n#else\r\n   #include <TopoDS_Iterator.hxx>\r\n#endif\r\n\r\nnamespace netgen\r\n{\r\n  void LoadOCCInto(OCCGeometry* occgeo, const filesystem::path & filename);\r\n  void PrintContents (OCCGeometry * geom);\r\n\r\n  // Utility function to apply builder and propagate properties\r\n  template <typename T>\r\n  static TopoDS_Shape Apply(T & builder, TopoDS_Shape & shape) {\r\n    auto newshape = builder->Apply(shape);\r\n    PropagateProperties(*builder, newshape);\r\n    return newshape;\r\n  };\r\n\r\n\r\n  TopTools_IndexedMapOfShape OCCGeometry::global_shape_property_indices;\r\n  std::vector<ShapeProperties> OCCGeometry::global_shape_properties;\r\n  TopTools_IndexedMapOfShape OCCGeometry::global_identification_indices;\r\n  std::vector<std::vector<OCCIdentification>> OCCGeometry::global_identifications;\r\n\r\n  TopoDS_Shape ListOfShapes::Max(gp_Vec dir)\r\n  {\r\n    double maxval = -1e99;\r\n    TopoDS_Shape maxshape;\r\n    for (auto shape : *this)\r\n      {\r\n        GProp_GProps props;\r\n        gp_Pnt center;\r\n\r\n        switch (shape.ShapeType())\r\n          {\r\n          case TopAbs_VERTEX:\r\n            center = BRep_Tool::Pnt (TopoDS::Vertex(shape)); break;\r\n          case TopAbs_FACE:\r\n            BRepGProp::SurfaceProperties (shape, props);\r\n            center = props.CentreOfMass();\r\n            break;\r\n          default:\r\n            BRepGProp::LinearProperties(shape, props);\r\n            center = props.CentreOfMass();\r\n          }\r\n\r\n        double val = center.X()*dir.X() + center.Y()*dir.Y() + center.Z() * dir.Z();\r\n        if (val > maxval)\r\n          {\r\n            maxval = val;\r\n            maxshape = shape;\r\n          }\r\n      }\r\n    return maxshape;\r\n  }\r\n  TopoDS_Shape ListOfShapes::Nearest(gp_Pnt pnt)\r\n  {\r\n    double mindist = 1e99;\r\n    TopoDS_Shape nearestshape;\r\n    auto vertex = BRepBuilderAPI_MakeVertex (pnt).Vertex();\r\n    \r\n    for (auto shape : *this)\r\n      {\r\n        double dist = BRepExtrema_DistShapeShape(shape, vertex).Value();\r\n        if (dist < mindist)\r\n          {\r\n            nearestshape = shape;\r\n            mindist = dist;\r\n          }\r\n      }\r\n    return nearestshape;\r\n  }\r\n\r\n  ListOfShapes ListOfShapes::SubShapes(TopAbs_ShapeEnum type) const\r\n  {\r\n    TopTools_MapOfShape check_unique;\r\n    ListOfShapes sub;\r\n    for(const auto& shape : *this)\r\n      for(TopExp_Explorer e(shape, type); e.More(); e.Next())\r\n        if(const auto& s = e.Current(); !check_unique.Contains(s))\r\n          {\r\n            check_unique.Add(s);\r\n            sub.push_back(s);\r\n          }\r\n    return sub;\r\n  }\r\n\r\n  OCCGeometry::OCCGeometry(const TopoDS_Shape& _shape, int aoccdim, bool copy)\r\n  {\r\n    if(copy)\r\n      {\r\n        auto filename = GetTempFilename();\r\n        step_utils::WriteSTEP(_shape, filename);\r\n        LoadOCCInto(this, filename);\r\n        dimension = aoccdim;\r\n        filesystem::remove(filename);\r\n      }\r\n    else\r\n      {\r\n        shape = _shape;\r\n        changed = 1;\r\n        dimension = aoccdim;\r\n        BuildFMap();\r\n        CalcBoundingBox();\r\n        PrintContents (this);\r\n      }\r\n  }\r\n\r\n  const GeometryShape & OCCGeometry :: GetShape(const TopoDS_Shape & shape) const\r\n  {\r\n    switch (shape.ShapeType())\r\n    {\r\n      case TopAbs_VERTEX:\r\n        return GetVertex(shape);\r\n      case TopAbs_EDGE:\r\n        return GetEdge(shape);\r\n      case TopAbs_FACE:\r\n        return GetFace(shape);\r\n      default:\r\n        throw Exception(\"unknown shape type\");\r\n    }\r\n  }\r\n\r\n  const GeometryVertex & OCCGeometry :: GetVertex(const TopoDS_Shape & shape) const\r\n  {\r\n      return *vertices[vmap.FindIndex(shape)-1];\r\n  }\r\n\r\n  const GeometryEdge & OCCGeometry :: GetEdge(const TopoDS_Shape & shape) const\r\n  {\r\n      return *edges[emap.FindIndex(shape)-1];\r\n  }\r\n\r\n  const GeometryFace & OCCGeometry :: GetFace(const TopoDS_Shape & shape) const\r\n  {\r\n      return *faces[fmap.FindIndex(shape)-1];\r\n  }\r\n\r\n  const GeometrySolid & OCCGeometry :: GetSolid(const TopoDS_Shape & shape) const\r\n  {\r\n      return *solids[somap.FindIndex(shape)-1];\r\n  }\r\n\r\n\r\n  string STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * aReader)\r\n  {\r\n    const Handle(XSControl_WorkSession)& theSession = aReader->Reader().WS();\r\n    const Handle(XSControl_TransferReader)& aTransferReader =\r\n        theSession->TransferReader();\r\n\r\n    Handle(Standard_Transient) anEntity =\r\n        aTransferReader->EntityFromShapeResult(theShape, 1);\r\n\r\n    if (anEntity.IsNull()) // as just mapped\r\n        anEntity = aTransferReader->EntityFromShapeResult (theShape,-1);\r\n\r\n    if (anEntity.IsNull()) // as anything\r\n        anEntity = aTransferReader->EntityFromShapeResult (theShape,4);\r\n\r\n    if (anEntity.IsNull())\r\n      {\r\n        cout<<\"Warning: cannot get entity from shape\" <<endl;\r\n        return \"none\";\r\n      }\r\n\r\n    auto aReprItem = Handle(StepRepr_RepresentationItem)::DownCast(anEntity);\r\n    if(!aReprItem.IsNull())\r\n        return aReprItem->Name()->ToCString();;\r\n\r\n    auto bReprItem = Handle(StepBasic_ProductDefinitionRelationship)::DownCast(anEntity);\r\n    if (!bReprItem.IsNull())\r\n        return bReprItem->Description()->ToCString();\r\n\r\n    cout<<\"Warning: unknown entity type \" << anEntity->DynamicType() << endl;\r\n    return \"none\";\r\n  }\r\n\r\n  void OCCGeometry :: Analyse(Mesh& mesh,\r\n                              const MeshingParameters& mparam) const\r\n  {\r\n    OCCSetLocalMeshSize(*this, mesh, mparam, occparam);\r\n  }\r\n\r\n  bool OCCGeometry :: MeshFace(Mesh& mesh,\r\n                                  const MeshingParameters& mparam, int nr, FlatArray<int, PointIndex> glob2loc) const\r\n  {\r\n    MeshingParameters local_mp = mparam;\r\n    auto face = TopoDS::Face(fmap(nr+1));\r\n    if(auto quad_dominated = OCCGeometry::GetProperties(face).quad_dominated; quad_dominated.has_value())\r\n      local_mp.quad = *quad_dominated;\r\n\r\n    bool failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PARAMETERSPACE, true);\r\n    if(failed)\r\n        failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PLANESPACE, false);\r\n\r\n    if(failed)\r\n    {\r\n        facemeshstatus[nr] = -1;\r\n        PrintError (\"Problem in Surface mesh generation\");\r\n    }\r\n    else\r\n    {\r\n        facemeshstatus[nr] = 1;\r\n    }\r\n    return failed;\r\n  }\r\n\r\n   void OCCGeometry :: PrintNrShapes ()\r\n   {\r\n      TopExp_Explorer e;\r\n      int count = 0;\r\n      for (e.Init(shape, TopAbs_COMPSOLID); e.More(); e.Next()) count++;\r\n      cout << \"CompSolids: \" << count << endl;\r\n\r\n      cout << \"Solids    : \" << somap.Extent() << endl;\r\n      cout << \"Shells    : \" << shmap.Extent() << endl;\r\n      cout << \"Faces     : \" << fmap.Extent() << endl;\r\n      cout << \"Edges     : \" << emap.Extent() << endl;\r\n      cout << \"Vertices  : \" << vmap.Extent() << endl;\r\n   }\r\n\r\n\r\n\r\n\r\n   void PrintContents (OCCGeometry * geom)\r\n   {\r\n      ShapeAnalysis_ShapeContents cont;\r\n      cont.Clear();\r\n      cont.Perform(geom->shape);\r\n\r\n      (*testout) << \"OCC CONTENTS\" << endl;\r\n      (*testout) << \"============\" << endl;\r\n      (*testout) << \"SOLIDS   : \" << cont.NbSolids() << endl;\r\n      (*testout) << \"SHELLS   : \" << cont.NbShells() << endl;\r\n      (*testout) << \"FACES    : \" << cont.NbFaces() << endl;\r\n      (*testout) << \"WIRES    : \" << cont.NbWires() << endl;\r\n      (*testout) << \"EDGES    : \" << cont.NbEdges() << endl;\r\n      (*testout) << \"VERTICES : \" << cont.NbVertices() << endl;\r\n\r\n      TopExp_Explorer e;\r\n      int count = 0;\r\n      for (e.Init(geom->shape, TopAbs_COMPOUND); e.More(); e.Next())\r\n         count++;\r\n      (*testout) << \"Compounds: \" << count << endl;\r\n\r\n      count = 0;\r\n      for (e.Init(geom->shape, TopAbs_COMPSOLID); e.More(); e.Next())\r\n         count++;\r\n      (*testout) << \"CompSolids: \" << count << endl;\r\n\r\n      (*testout) << endl;\r\n\r\n      cout << IM(3) << \"Highest entry in topology hierarchy: \" << endl;\r\n      if (count)\r\n         cout << IM(3) << count << \" composite solid(s)\" << endl;\r\n      else\r\n         if (geom->somap.Extent())\r\n            cout << IM(3) << geom->somap.Extent() << \" solid(s)\" << endl;\r\n         else\r\n            if (geom->shmap.Extent())\r\n               cout << IM(3) << geom->shmap.Extent() << \" shells(s)\" << endl;\r\n            else\r\n               if (geom->fmap.Extent())\r\n                  cout << IM(3) << geom->fmap.Extent() << \" face(s)\" << endl;\r\n               else\r\n                  if (geom->wmap.Extent())\r\n                     cout << IM(3) << geom->wmap.Extent() << \" wire(s)\" << endl;\r\n                  else\r\n                     if (geom->emap.Extent())\r\n                        cout << IM(3) << geom->emap.Extent() << \" edge(s)\" << endl;\r\n                     else\r\n                        if (geom->vmap.Extent())\r\n                           cout << IM(3) << geom->vmap.Extent() << \" vertices(s)\" << endl;\r\n                        else\r\n                           cout << IM(3) << \"no entities\" << endl;\r\n\r\n   }\r\n\r\n  void OCCGeometry :: GlueGeometry()\r\n  {\r\n    PrintMessage(1, \"OCC Glue Geometry\");\r\n    /*\r\n      // \r\n    BRep_Builder builder;\r\n    TopoDS_Shape my_fuse;\r\n    int cnt = 0;\r\n    for (TopExp_Explorer exp_solid(shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next())\r\n      {\r\n        cout << \"cnt = \" << cnt << endl;\r\n\tif (cnt == 0)\r\n\t  my_fuse = exp_solid.Current();\r\n\telse\r\n          // my_fuse = BRepAlgoAPI_Fuse (my_fuse, exp_solid.Current());\r\n          my_fuse = QANewModTopOpe_Glue::QANewModTopOpe_Glue(my_fuse, exp_solid.Current());\r\n\tcnt++;\r\n      }\r\n    cout << \"remove\" << endl;\r\n    // for (int i = 1; i <= somap.Size(); i++)\r\n    // builder.Remove (shape, somap(i));\r\n    cout << \"now add\" << endl;\r\n    // builder.Add (shape, my_fuse);\r\n    shape = my_fuse;\r\n    cout << \"build fmap\" << endl;\r\n    BuildFMap();\r\n    */\r\n\r\n\r\n    // from \r\n    // https://www.opencascade.com/doc/occt-7.4.0/overview/html/occt_user_guides__boolean_operations.html\r\n    BOPAlgo_Builder aBuilder;\r\n\r\n    // Setting arguments\r\n    TopTools_ListOfShape aLSObjects; \r\n    for (TopExp_Explorer exp_solid(shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next())\r\n      aLSObjects.Append (exp_solid.Current());\r\n    aBuilder.SetArguments(aLSObjects);\r\n\r\n    // Setting options for GF\r\n    // Set parallel processing mode (default is false)\r\n    // Standard_Boolean bRunParallel = Standard_True;\r\n    // aBuilder.SetRunParallel(bRunParallel);\r\n    \r\n    // Set Fuzzy value (default is Precision::Confusion())\r\n    // Standard_Real aFuzzyValue = 1.e-5;\r\n    // aBuilder.SetFuzzyValue(aFuzzyValue);\r\n    \r\n    // Set safe processing mode (default is false)\r\n    // Standard_Boolean bSafeMode = Standard_True;\r\n    // aBuilder.SetNonDestructive(bSafeMode);\r\n    \r\n    // Set Gluing mode for coinciding arguments (default is off)\r\n    // BOPAlgo_GlueEnum aGlue = BOPAlgo_GlueShift;\r\n    // aBuilder.SetGlue(aGlue);\r\n    \r\n    // Disabling/Enabling the check for inverted solids (default is true)\r\n    // Standard Boolean bCheckInverted = Standard_False;\r\n    // aBuilder.SetCheckInverted(bCheckInverted);\r\n    \r\n    // Set OBB usage (default is false)\r\n    // Standard_Boolean bUseOBB = Standard_True;\r\n    // aBuilder.SetUseOBB(buseobb);\r\n    \r\n    // Perform the operation\r\n    aBuilder.Perform();\r\n    // Check for the errors\r\n#if OCC_VERSION_HEX >= 0x070200\r\n    if (aBuilder.HasErrors())\r\n      {\r\n        cout << \"builder has errors\" << endl;\r\n        return;\r\n      }\r\n    // Check for the warnings\r\n    if (aBuilder.HasWarnings())\r\n      {\r\n        // treatment of the warnings\r\n        ;\r\n      }\r\n#endif\r\n\r\n    PropagateProperties(aBuilder, shape);\r\n    \r\n    // result of the operation\r\n    shape = aBuilder.Shape();\r\n    BuildFMap();\r\n  }\r\n\r\n   void OCCGeometry :: HealGeometry ()\r\n   {\r\n      int nrc = 0, nrcs = 0,\r\n         nrso = somap.Extent(),\r\n         nrsh = shmap.Extent(),\r\n         nrf = fmap.Extent(),\r\n         nrw = wmap.Extent(),\r\n         nre = emap.Extent(),\r\n         nrv = vmap.Extent();\r\n\r\n      TopExp_Explorer exp0;\r\n      TopExp_Explorer exp1;\r\n\r\n\r\n      for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nrc++;\r\n      for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nrcs++;\r\n\r\n      double surfacecont = 0;\r\n      \r\n      {\r\n         Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n         Apply(rebuild, shape);\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               rebuild->Remove(edge);\r\n         }\r\n         shape = Apply(rebuild, shape);\r\n      }\r\n\r\n      BuildFMap();\r\n\r\n\r\n      for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next())\r\n      {\r\n         TopoDS_Face face = TopoDS::Face(exp0.Current());\r\n\r\n         GProp_GProps system;\r\n         BRepGProp::SurfaceProperties(face, system);\r\n         surfacecont += system.Mass();\r\n      }\r\n\r\n\r\n      cout << \"Starting geometry healing procedure (tolerance: \" << tolerance << \")\" << endl\r\n         << \"-----------------------------------\" << endl;\r\n\r\n      {\r\n         cout << endl << \"- repairing faces\" << endl;\r\n\r\n         Handle(ShapeFix_Face) sff;\r\n         Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n         Apply(rebuild, shape);\r\n\r\n         for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next())\r\n         {\r\n            TopoDS_Face face = TopoDS::Face (exp0.Current());\r\n            auto props = GetProperties(face);\r\n\r\n            sff = new ShapeFix_Face (face);\r\n            sff->FixAddNaturalBoundMode() = Standard_True;\r\n            sff->FixSmallAreaWireMode() = Standard_True;\r\n            sff->Perform();\r\n\r\n            if(sff->Status(ShapeExtend_DONE1) ||\r\n               sff->Status(ShapeExtend_DONE2) ||\r\n               sff->Status(ShapeExtend_DONE3) ||\r\n               sff->Status(ShapeExtend_DONE4) ||\r\n               sff->Status(ShapeExtend_DONE5))\r\n            {\r\n               cout << \"repaired face \" << fmap.FindIndex(face) << \" \";\r\n               if(sff->Status(ShapeExtend_DONE1))\r\n                  cout << \"(some wires are fixed)\" <<endl;\r\n               else if(sff->Status(ShapeExtend_DONE2))\r\n                  cout << \"(orientation of wires fixed)\" <<endl;\r\n               else if(sff->Status(ShapeExtend_DONE3))\r\n                  cout << \"(missing seam added)\" <<endl;\r\n               else if(sff->Status(ShapeExtend_DONE4))\r\n                  cout << \"(small area wire removed)\" <<endl;\r\n               else if(sff->Status(ShapeExtend_DONE5))\r\n                  cout << \"(natural bounds added)\" <<endl;\r\n               TopoDS_Face newface = sff->Face();\r\n\r\n               rebuild->Replace(face, newface);\r\n            }\r\n\r\n            // Set the original properties of the face to the newly created \r\n            // face (after the healing process)\r\n            // GetProperties(face);\r\n         }\r\n         shape = Apply(rebuild, shape);\r\n      }\r\n\r\n\r\n      {\r\n         Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n         Apply(rebuild, shape);\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               rebuild->Remove(edge);\r\n         }\r\n         shape = Apply(rebuild, shape);\r\n      }\r\n\r\n\r\n      if (fixsmalledges)\r\n      {\r\n         cout << endl << \"- fixing small edges\" << endl;\r\n\r\n         Handle(ShapeFix_Wire) sfw;\r\n         Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n         Apply(rebuild, shape);\r\n\r\n\r\n         for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next())\r\n         {\r\n            TopoDS_Face face = TopoDS::Face(exp0.Current());\r\n\r\n            for (exp1.Init (face, TopAbs_WIRE); exp1.More(); exp1.Next())\r\n            {\r\n               TopoDS_Wire oldwire = TopoDS::Wire(exp1.Current());\r\n               sfw = new ShapeFix_Wire (oldwire, face ,tolerance);\r\n               sfw->ModifyTopologyMode() = Standard_True;\r\n\r\n               sfw->ClosedWireMode() = Standard_True;\r\n\r\n               bool replace = false;\r\n\r\n               replace = sfw->FixReorder() || replace;\r\n\r\n               replace = sfw->FixConnected() || replace;\r\n\r\n\r\n\r\n               if (sfw->FixSmall (Standard_False, tolerance) && ! (sfw->StatusSmall(ShapeExtend_FAIL1) ||\r\n                  sfw->StatusSmall(ShapeExtend_FAIL2) ||\r\n                  sfw->StatusSmall(ShapeExtend_FAIL3)))\r\n               {\r\n                  cout << \"Fixed small edge in wire \" << wmap.FindIndex (oldwire) << endl;\r\n                  replace = true;\r\n\r\n               }\r\n               else if (sfw->StatusSmall(ShapeExtend_FAIL1))\r\n                  cerr << \"Failed to fix small edge in wire \" << wmap.FindIndex (oldwire)\r\n                  << \", edge cannot be checked (no 3d curve and no pcurve)\" << endl;\r\n               else if (sfw->StatusSmall(ShapeExtend_FAIL2))\r\n                  cerr << \"Failed to fix small edge in wire \" << wmap.FindIndex (oldwire)\r\n                  << \", edge is null-length and has different vertives at begin and end, and lockvtx is True or ModifiyTopologyMode is False\" << endl;\r\n               else if (sfw->StatusSmall(ShapeExtend_FAIL3))\r\n                  cerr << \"Failed to fix small edge in wire \" << wmap.FindIndex (oldwire)\r\n                  << \", CheckConnected has failed\" << endl;\r\n\r\n               replace = sfw->FixEdgeCurves() || replace;\r\n\r\n               replace = sfw->FixDegenerated() || replace;\r\n\r\n               replace = sfw->FixSelfIntersection() || replace;\r\n\r\n               replace = sfw->FixLacking(Standard_True) || replace;\r\n\r\n               if(replace)\r\n               {\r\n                  TopoDS_Wire newwire = sfw->Wire();\r\n                  rebuild->Replace(oldwire, newwire);\r\n               }\r\n\r\n               //delete sfw; sfw = NULL;\r\n\r\n            }\r\n         }\r\n\r\n         shape = Apply(rebuild, shape);\r\n\r\n\r\n\r\n         {\r\n            BuildFMap();\r\n            Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n            Apply(rebuild, shape);\r\n\r\n            for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n            {\r\n               TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n               if (vmap.FindIndex(TopExp::FirstVertex (edge)) ==\r\n                  vmap.FindIndex(TopExp::LastVertex (edge)))\r\n               {\r\n                  GProp_GProps system;\r\n                  BRepGProp::LinearProperties(edge, system);\r\n                  if (system.Mass() < tolerance)\r\n                  {\r\n                     cout << \"removing degenerated edge \" << emap.FindIndex(edge)\r\n                        << \" from vertex \" << vmap.FindIndex(TopExp::FirstVertex (edge))\r\n                        << \" to vertex \" << vmap.FindIndex(TopExp::LastVertex (edge)) << endl;\r\n                     rebuild->Remove(edge);\r\n                  }\r\n               }\r\n            }\r\n            shape = Apply(rebuild, shape);\r\n\r\n            //delete rebuild; rebuild = NULL;\r\n         }\r\n\r\n\r\n\r\n         {\r\n            Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n            Apply(rebuild, shape);\r\n            for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n            {\r\n               TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n               if ( BRep_Tool::Degenerated(edge) )\r\n                  rebuild->Remove(edge);\r\n            }\r\n            shape = Apply(rebuild, shape);\r\n         }\r\n\r\n\r\n\r\n\r\n         Handle(ShapeFix_Wireframe) sfwf = new ShapeFix_Wireframe;\r\n         sfwf->SetPrecision(tolerance);\r\n         sfwf->Load (shape);\r\n         sfwf->ModeDropSmallEdges() = Standard_True;\r\n\r\n         if (sfwf->FixWireGaps())\r\n         {\r\n            cout << endl << \"- fixing wire gaps\" << endl;\r\n            if (sfwf->StatusWireGaps(ShapeExtend_OK)) cout << \"no gaps found\" << endl;\r\n            if (sfwf->StatusWireGaps(ShapeExtend_DONE1)) cout << \"some 2D gaps fixed\" << endl;\r\n            if (sfwf->StatusWireGaps(ShapeExtend_DONE2)) cout << \"some 3D gaps fixed\" << endl;\r\n            if (sfwf->StatusWireGaps(ShapeExtend_FAIL1)) cout << \"failed to fix some 2D gaps\" << endl;\r\n            if (sfwf->StatusWireGaps(ShapeExtend_FAIL2)) cout << \"failed to fix some 3D gaps\" << endl;\r\n         }\r\n\r\n         {\r\n            for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n            {\r\n               TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n               if ( BRep_Tool::Degenerated(edge) )\r\n                  cout << \"degenerated edge at position 4\" << endl;\r\n            }\r\n         }\r\n\r\n\r\n\r\n         if (sfwf->FixSmallEdges())\r\n         {\r\n            cout << endl << \"- fixing wire frames\" << endl;\r\n            if (sfwf->StatusSmallEdges(ShapeExtend_OK)) cout << \"no small edges found\" << endl;\r\n            if (sfwf->StatusSmallEdges(ShapeExtend_DONE1)) cout << \"some small edges fixed\" << endl;\r\n            if (sfwf->StatusSmallEdges(ShapeExtend_FAIL1)) cout << \"failed to fix some small edges\" << endl;\r\n         }\r\n\r\n\r\n\r\n         auto newshape = sfwf->Shape();\r\n         PropagateProperties(*sfwf->Context(), newshape);\r\n         shape = newshape;\r\n\r\n         //delete sfwf; sfwf = NULL;\r\n         //delete rebuild; rebuild = NULL;\r\n\r\n      }\r\n\r\n\r\n\r\n\r\n\r\n      {\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               cout << \"degenerated edge at position 5\" << endl;\r\n         }\r\n      }\r\n\r\n\r\n\r\n\r\n      if (fixspotstripfaces)\r\n      {\r\n\r\n         cout << endl << \"- fixing spot and strip faces\" << endl;\r\n         Handle(ShapeFix_FixSmallFace) sffsm = new ShapeFix_FixSmallFace();\r\n         sffsm -> Init (shape);\r\n         sffsm -> SetPrecision (tolerance);\r\n         sffsm -> Perform();\r\n\r\n         auto newshape = sffsm -> FixShape();\r\n         PropagateProperties(*sffsm->Context(), newshape);\r\n         shape = newshape;\r\n         //delete sffsm; sffsm = NULL;\r\n      }\r\n\r\n\r\n      {\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               cout << \"degenerated edge at position 6\" << endl;\r\n         }\r\n      }\r\n\r\n\r\n\r\n      if (sewfaces)\r\n      {\r\n         cout << endl << \"- sewing faces\" << endl;\r\n\r\n         BRepOffsetAPI_Sewing sewedObj(tolerance);\r\n\r\n         for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next())\r\n         {\r\n            TopoDS_Face face = TopoDS::Face (exp0.Current());\r\n            sewedObj.Add (face);\r\n         }\r\n\r\n         sewedObj.Perform();\r\n         PropagateProperties(sewedObj, shape);\r\n\r\n         if (!sewedObj.SewedShape().IsNull())\r\n            shape = sewedObj.SewedShape();\r\n         else\r\n            cout << \" not possible\";\r\n      }\r\n\r\n\r\n\r\n      {\r\n         Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n         rebuild->Apply(shape);\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               rebuild->Remove(edge);\r\n         }\r\n         shape = Apply(rebuild, shape);\r\n      }\r\n\r\n\r\n      if (makesolids)\r\n      {\r\n         cout << endl << \"- making solids\" << endl;\r\n\r\n         BRepBuilderAPI_MakeSolid ms;\r\n         int count = 0;\r\n         for (exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next())\r\n         {\r\n            count++;\r\n            ms.Add (TopoDS::Shell(exp0.Current()));\r\n         }\r\n\r\n         if (!count)\r\n         {\r\n            cout << \" not possible (no shells)\" << endl;\r\n         }\r\n         else\r\n         {\r\n            BRepCheck_Analyzer ba(ms);\r\n            if (ba.IsValid ())\r\n            {\r\n               Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;\r\n               sfs->Init (ms);\r\n               sfs->SetPrecision(tolerance);\r\n               sfs->SetMaxTolerance(tolerance);\r\n               sfs->Perform();\r\n               shape = sfs->Shape();\r\n\r\n               for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next())\r\n               {\r\n                  TopoDS_Solid solid = TopoDS::Solid(exp0.Current());\r\n                  TopoDS_Solid newsolid = solid;\r\n                  BRepLib::OrientClosedSolid (newsolid);\r\n                  Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n                  //\t\t  rebuild->Apply(shape);\r\n                  rebuild->Replace(solid, newsolid);\r\n                  TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_COMPSOLID);//, 1);\r\n                  //\t\t  TopoDS_Shape newshape = rebuild->Apply(shape);\r\n                  shape = newshape;\r\n               }\r\n\r\n               //delete sfs; sfs = NULL;\r\n            }\r\n            else\r\n               cout << \" not possible\" << endl;\r\n         }\r\n      }\r\n\r\n\r\n\r\n      if (splitpartitions)\r\n      {\r\n         cout << \"- running SALOME partition splitter\" << endl;\r\n\r\n         TopExp_Explorer e2;\r\n         Partition_Spliter ps;\r\n         int count = 0;\r\n\r\n         for (e2.Init (shape, TopAbs_SOLID);\r\n            e2.More(); e2.Next())\r\n         {\r\n            count++;\r\n            ps.AddShape (e2.Current());\r\n         }\r\n\r\n         ps.Compute();\r\n         shape = ps.Shape();\r\n\r\n         cout << \" before: \" << count << \" solids\" << endl;\r\n\r\n         count = 0;\r\n         for (e2.Init (shape, TopAbs_SOLID);\r\n            e2.More(); e2.Next()) count++;\r\n\r\n            cout << \" after : \" << count << \" solids\" << endl;\r\n      }\r\n\r\n      BuildFMap();\r\n\r\n\r\n\r\n      {\r\n         for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next())\r\n         {\r\n            TopoDS_Edge edge = TopoDS::Edge(exp1.Current());\r\n            if ( BRep_Tool::Degenerated(edge) )\r\n               cout << \"degenerated edge at position 8\" << endl;\r\n         }\r\n      }\r\n\r\n\r\n      double newsurfacecont = 0;\r\n\r\n\r\n      for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next())\r\n      {\r\n         TopoDS_Face face = TopoDS::Face(exp0.Current());\r\n         GProp_GProps system;\r\n         BRepGProp::SurfaceProperties(face, system);\r\n         newsurfacecont += system.Mass();\r\n      }\r\n\r\n\r\n      int nnrc = 0, nnrcs = 0,\r\n         nnrso = somap.Extent(),\r\n         nnrsh = shmap.Extent(),\r\n         nnrf = fmap.Extent(),\r\n         nnrw = wmap.Extent(),\r\n         nnre = emap.Extent(),\r\n         nnrv = vmap.Extent();\r\n\r\n      for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nnrc++;\r\n      for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nnrcs++;\r\n\r\n      cout << \"-----------------------------------\" << endl;\r\n      cout << \"Compounds       : \" << nnrc << \" (\" << nrc << \")\" << endl;\r\n      cout << \"Composite solids: \" << nnrcs << \" (\" << nrcs << \")\" << endl;\r\n      cout << \"Solids          : \" << nnrso << \" (\" << nrso << \")\" << endl;\r\n      cout << \"Shells          : \" << nnrsh << \" (\" << nrsh << \")\" << endl;\r\n      cout << \"Wires           : \" << nnrw << \" (\" << nrw << \")\" << endl;\r\n      cout << \"Faces           : \" << nnrf << \" (\" << nrf << \")\" << endl;\r\n      cout << \"Edges           : \" << nnre << \" (\" << nre << \")\" << endl;\r\n      cout << \"Vertices        : \" << nnrv << \" (\" << nrv << \")\" << endl;\r\n      cout << endl;\r\n      cout << \"Total surface area : \" << newsurfacecont << \" (\" << surfacecont << \")\" << endl;\r\n      cout << endl;\r\n   }\r\n\r\n\r\n   // For 2d geometries, make sure all faces have a normal vector with positive z-component\r\n   void OCCGeometry :: FixFaceOrientation()\r\n   {\r\n     if(dimension!=2) return;\r\n\r\n     bool needs_fix = false;\r\n     Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n     for (auto face : GetFaces(shape))\r\n     {\r\n       auto occface = OCCFace(face);\r\n       auto normal = occface.GetNormal(occ2ng(GetVertices(face)[0]));\r\n       if(normal[2] < 0) {\r\n         needs_fix = true;\r\n         // Need do copy the face, otherwise replace is ignored\r\n         BRepBuilderAPI_Copy copy(face);\r\n         auto newface = copy.Shape().Reversed();\r\n         PropagateProperties(copy, face);\r\n         rebuild->Replace(face, newface);\r\n       }\r\n     }\r\n\r\n     if(needs_fix )\r\n       shape = Apply(rebuild, shape);\r\n   }\r\n\r\n   void OCCGeometry :: BuildFMap()\r\n   {\r\n      somap.Clear();\r\n      shmap.Clear();\r\n      fmap.Clear();\r\n      wmap.Clear();\r\n      emap.Clear();\r\n      vmap.Clear();\r\n\r\n      TopExp_Explorer exp0, exp1, exp2, exp3, exp4, exp5;\r\n\r\n      // Check face orientation in 2d geometries\r\n      FixFaceOrientation();\r\n\r\n      for (exp0.Init(shape, TopAbs_COMPOUND);\r\n         exp0.More(); exp0.Next())\r\n      {\r\n         TopoDS_Compound compound = TopoDS::Compound (exp0.Current());\r\n         (*testout) << \"compound\" << endl;\r\n         int i = 0;\r\n         for (exp1.Init(compound, TopAbs_SHELL);\r\n            exp1.More(); exp1.Next())\r\n         {\r\n            (*testout) << \"shell \" << ++i << endl;\r\n         }\r\n      }\r\n\r\n      for (exp0.Init(shape, TopAbs_SOLID);\r\n         exp0.More(); exp0.Next())\r\n      {\r\n         TopoDS_Solid solid = TopoDS::Solid (exp0.Current());\r\n\r\n         if (somap.FindIndex(solid) < 1)\r\n         {\r\n            somap.Add (solid);\r\n\r\n            for (exp1.Init(solid, TopAbs_SHELL);\r\n               exp1.More(); exp1.Next())\r\n            {\r\n               TopoDS_Shell shell = TopoDS::Shell (exp1.Current());\r\n               if (shmap.FindIndex(shell) < 1)\r\n               {\r\n                  shmap.Add (shell);\r\n\r\n                  for (exp2.Init(shell, TopAbs_FACE);\r\n                     exp2.More(); exp2.Next())\r\n                  {\r\n                     TopoDS_Face face = TopoDS::Face(exp2.Current());\r\n                     if (fmap.FindIndex(face) < 1)\r\n                     {\r\n                        fmap.Add (face);\r\n                        (*testout) << \"face \" << fmap.FindIndex(face) << \" \";\r\n                        (*testout) << ((face.Orientation() == TopAbs_REVERSED) ? \"-\" : \"+\") << \", \";\r\n                        (*testout) << ((exp2.Current().Orientation() == TopAbs_REVERSED) ? \"-\" : \"+\") << endl;\r\n                        for (exp3.Init(exp2.Current(), TopAbs_WIRE);\r\n                           exp3.More(); exp3.Next())\r\n                        {\r\n                           TopoDS_Wire wire = TopoDS::Wire (exp3.Current());\r\n                           if (wmap.FindIndex(wire) < 1)\r\n                           {\r\n                              wmap.Add (wire);\r\n\r\n                              for (exp4.Init(exp3.Current(), TopAbs_EDGE);\r\n                                 exp4.More(); exp4.Next())\r\n                              {\r\n                                 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());\r\n                                 if (emap.FindIndex(edge) < 1)\r\n                                 {\r\n                                    emap.Add (edge);\r\n                                    for (exp5.Init(exp4.Current(), TopAbs_VERTEX);\r\n                                       exp5.More(); exp5.Next())\r\n                                    {\r\n                                       TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());\r\n                                       if (vmap.FindIndex(vertex) < 1)\r\n                                          vmap.Add (vertex);\r\n                                    }\r\n                                 }\r\n                              }\r\n                           }\r\n                        }\r\n                     }\r\n                  }\r\n               }\r\n            }\r\n         }\r\n      }\r\n\r\n      // Free Shells\r\n      for (exp1.Init(shape, TopAbs_SHELL, TopAbs_SOLID); exp1.More(); exp1.Next())\r\n      {\r\n         TopoDS_Shell shell = TopoDS::Shell(exp1.Current());\r\n         if (shmap.FindIndex(shell) < 1)\r\n         {\r\n            shmap.Add (shell);\r\n\r\n            (*testout) << \"shell \" << shmap.FindIndex(shell) << \" \";\r\n            (*testout) << ((shell.Orientation() == TopAbs_REVERSED) ? \"-\" : \"+\") << \", \";\r\n            (*testout) << ((exp1.Current().Orientation() == TopAbs_REVERSED) ? \"-\" : \"+\") << endl;\r\n\r\n            for (exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next())\r\n            {\r\n               TopoDS_Face face = TopoDS::Face(exp2.Current());\r\n               if (fmap.FindIndex(face) < 1)\r\n               {\r\n                 fmap.Add (face);\r\n\r\n                  for (exp3.Init(face, TopAbs_WIRE); exp3.More(); exp3.Next())\r\n                  {\r\n                     TopoDS_Wire wire = TopoDS::Wire (exp3.Current());\r\n                     if (wmap.FindIndex(wire) < 1)\r\n                     {\r\n                        wmap.Add (wire);\r\n\r\n                        for (exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next())\r\n                        {\r\n                           TopoDS_Edge edge = TopoDS::Edge(exp4.Current());\r\n                           if (emap.FindIndex(edge) < 1)\r\n                           {\r\n                              emap.Add (edge);\r\n                              for (exp5.Init(edge, TopAbs_VERTEX); exp5.More(); exp5.Next())\r\n                              {\r\n                                 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());\r\n                                 if (vmap.FindIndex(vertex) < 1)\r\n                                    vmap.Add (vertex);\r\n                              }\r\n                           }\r\n                        }\r\n                     }\r\n                  }\r\n               }\r\n            }\r\n         }\r\n      }\r\n\r\n\r\n      // Free Faces\r\n      for (auto face : MyExplorer(shape, TopAbs_FACE, TopAbs_SHELL))\r\n        if (!fmap.Contains(face))\r\n          {\r\n            fmap.Add (face);\r\n            for (auto wire : MyExplorer(face, TopAbs_WIRE))\r\n              if (!wmap.Contains(wire))\r\n                {\r\n                  wmap.Add (wire);\r\n                  for (auto edge : MyExplorer(wire, TopAbs_EDGE))\r\n                    if (!emap.Contains(edge))\r\n                      {\r\n                        emap.Add (edge);\r\n                        for (auto vertex : MyExplorer(edge, TopAbs_VERTEX))\r\n                          if (!vmap.Contains(vertex))\r\n                            vmap.Add (vertex);\r\n                      }\r\n                }\r\n          }\r\n\r\n\r\n      // Free Wires\r\n\r\n      for (exp3.Init(shape, TopAbs_WIRE, TopAbs_FACE); exp3.More(); exp3.Next())\r\n      {\r\n         TopoDS_Wire wire = TopoDS::Wire (exp3.Current());\r\n         if (wmap.FindIndex(wire) < 1)\r\n         {\r\n            wmap.Add (wire);\r\n\r\n            for (exp4.Init(exp3.Current(), TopAbs_EDGE); exp4.More(); exp4.Next())\r\n            {\r\n               TopoDS_Edge edge = TopoDS::Edge(exp4.Current());\r\n               if (emap.FindIndex(edge) < 1)\r\n               {\r\n                  emap.Add (edge);\r\n                  for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next())\r\n                  {\r\n                     TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());\r\n                     if (vmap.FindIndex(vertex) < 1)\r\n                        vmap.Add (vertex);\r\n                  }\r\n               }\r\n            }\r\n         }\r\n      }\r\n\r\n\r\n      // Free Edges\r\n      /*\r\n      for (exp4.Init(shape, TopAbs_EDGE, TopAbs_WIRE); exp4.More(); exp4.Next())\r\n      {\r\n         TopoDS_Edge edge = TopoDS::Edge(exp4.Current());\r\n         if (emap.FindIndex(edge) < 1)\r\n         {\r\n            emap.Add (edge);\r\n            for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next())\r\n            {\r\n               TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());\r\n               if (vmap.FindIndex(vertex) < 1)\r\n                  vmap.Add (vertex);\r\n            }\r\n         }\r\n      }\r\n      */\r\n\r\n      std::map<int, ArrayMem<int, 10>> free_edges_in_solid;\r\n      for(auto i1 : Range(1, somap.Extent()+1))\r\n      {\r\n          auto s = somap(i1);\r\n          for (auto edge : MyExplorer(s, TopAbs_EDGE, TopAbs_WIRE))\r\n            if (!emap.Contains(edge))\r\n              {\r\n                free_edges_in_solid[i1].Append(emap.Add (edge));\r\n                for (auto vertex : MyExplorer(edge, TopAbs_VERTEX))\r\n                  if (!vmap.Contains(vertex))\r\n                    vmap.Add (vertex);\r\n              }\r\n      }\r\n\r\n      for (auto edge : MyExplorer(shape, TopAbs_EDGE, TopAbs_WIRE))\r\n        if (!emap.Contains(edge))\r\n          {\r\n            emap.Add (edge);\r\n            for (auto vertex : MyExplorer(edge, TopAbs_VERTEX))\r\n              if (!vmap.Contains(vertex))\r\n                vmap.Add (vertex);\r\n          }\r\n\r\n      \r\n      // Free Vertices\r\n      /*\r\n      for (exp5.Init(shape, TopAbs_VERTEX, TopAbs_EDGE); exp5.More(); exp5.Next())\r\n      {\r\n         TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());\r\n         if (vmap.FindIndex(vertex) < 1)\r\n            vmap.Add (vertex);\r\n      }\r\n      */\r\n      for (auto vertex : MyExplorer(shape, TopAbs_VERTEX, TopAbs_EDGE))\r\n        if (!vmap.Contains(vertex))\r\n          vmap.Add (vertex);\r\n\r\n      facemeshstatus.DeleteAll();\r\n      facemeshstatus.SetSize (fmap.Extent());\r\n      facemeshstatus = 0;\r\n\r\n      // Philippose - 15/01/2009\r\n      face_maxh.DeleteAll();\r\n      face_maxh.SetSize (fmap.Extent());\r\n      face_maxh = 1e99; // mparam.maxh;\r\n\r\n      // Philippose - 15/01/2010      \r\n      face_maxh_modified.DeleteAll();      \r\n      face_maxh_modified.SetSize(fmap.Extent());      \r\n      face_maxh_modified = 0;\r\n      \r\n\r\n      // Philippose - 17/01/2009\r\n      face_sel_status.DeleteAll();\r\n      face_sel_status.SetSize (fmap.Extent());\r\n      face_sel_status = 0;\r\n\r\n      fvispar.SetSize (fmap.Extent());\r\n      evispar.SetSize (emap.Extent());\r\n      vvispar.SetSize (vmap.Extent());\r\n\r\n      fsingular.SetSize (fmap.Extent());\r\n      esingular.SetSize (emap.Extent());\r\n      vsingular.SetSize (vmap.Extent());\r\n\r\n      fsingular = esingular = vsingular = false;\r\n\r\n      NetgenGeometry::Clear();\r\n\r\n      // Add shapes\r\n      for(auto i1 : Range(1, vmap.Extent()+1))\r\n      {\r\n          auto v = vmap(i1);\r\n          auto occ_vertex = make_unique<OCCVertex>(TopoDS::Vertex(v));\r\n          occ_vertex->nr = vertices.Size();\r\n\r\n          if(HaveProperties(v))\r\n            occ_vertex->properties = GetProperties(v);\r\n          vertices.Append(std::move(occ_vertex));\r\n      }\r\n\r\n      for(auto i1 : Range(1, emap.Extent()+1))\r\n      {\r\n          auto e = emap(i1);\r\n          auto edge = TopoDS::Edge(e);\r\n          auto verts = GetVertices(e);\r\n          if(verts.size() == 0)\r\n            continue;\r\n          auto occ_edge = make_unique<OCCEdge>(edge, GetVertex(verts[0]), GetVertex(verts[1]) );\r\n          if(HaveProperties(edge))\r\n            occ_edge->properties = GetProperties(e);\r\n          edges.Append(std::move(occ_edge));\r\n      }\r\n\r\n      for(auto i1 : Range(1, fmap.Extent()+1))\r\n      {\r\n          auto f = fmap(i1);\r\n\r\n          auto k = faces.Size();\r\n          auto occ_face = make_unique<OCCFace>(f);\r\n\r\n          for(auto e : GetEdges(f))\r\n              occ_face->edges.Append( &GetEdge(e) );\r\n\r\n          if(HaveProperties(f))\r\n            occ_face->properties = GetProperties(f);\r\n          faces.Append(std::move(occ_face));\r\n\r\n          if(dimension==2)\r\n              for(auto e : GetEdges(f))\r\n              {\r\n                  auto & edge = GetEdge(e);\r\n                  if(e.Orientation() == TopAbs_REVERSED)\r\n                      edge.domout = k;\r\n                  else\r\n                      edge.domin = k;\r\n              }\r\n      }\r\n\r\n\r\n      for(auto i1 : Range(1, somap.Extent()+1))\r\n      {\r\n          auto s = somap(i1);\r\n          int k = solids.Size();\r\n          auto occ_solid = make_unique<OCCSolid>(s);\r\n          if(HaveProperties(s))\r\n            occ_solid->properties = GetProperties(s);\r\n          for(auto f : GetFaces(s))\r\n          {\r\n              auto & face = static_cast<OCCFace&>(GetFace(f));\r\n              face.properties.maxh = min2(face.properties.maxh, occ_solid->properties.maxh);\r\n\r\n              if(face.domin==-1)\r\n                  face.domin = k;\r\n              else\r\n                  face.domout = k;\r\n              if(face.Shape().Orientation() == TopAbs_INTERNAL)\r\n                  face.domout = k;\r\n          }\r\n\r\n          if(free_edges_in_solid.count(i1))\r\n            for(auto ei : free_edges_in_solid[i1])\r\n            {\r\n              auto & edge = GetEdge(emap(ei));\r\n              edge.properties.maxh = min(edge.properties.maxh, occ_solid->properties.maxh);\r\n              edge.domin = k;\r\n              edge.domout = k;\r\n              occ_solid->free_edges.Append(&GetEdge(emap(ei)));\r\n            }\r\n          solids.Append(std::move(occ_solid));\r\n      }\r\n\r\n      // Propagate maxh to children\r\n      for(auto& face : faces)\r\n        for(auto& edge : face->edges)\r\n          edge->properties.maxh = min2(edge->properties.maxh,\r\n                                       face->properties.maxh);\r\n\r\n      // Add identifications\r\n      auto add_identifications = [&](auto & shapes, auto & shape_map)\r\n      {\r\n          for(auto i1 : Range(1, shape_map.Extent()+1))\r\n          {\r\n            auto shape = shape_map(i1);\r\n            if(HaveIdentifications(shape))\r\n              for(auto & ident : GetIdentifications(shape))\r\n                {\r\n                    if(!shape_map.Contains(ident.from) || !shape_map.Contains(ident.to))\r\n                        continue;\r\n                    ShapeIdentification si{\r\n                        &GetShape(ident.from),\r\n                        &GetShape(ident.to),\r\n                        ident.trafo,\r\n                        ident.type,\r\n                        ident.name\r\n                    };\r\n                    shapes[i1-1]->identifications.Append(si);\r\n                }\r\n          }\r\n      };\r\n      add_identifications( vertices, vmap );\r\n      add_identifications( edges, emap );\r\n      add_identifications( faces, fmap );\r\n\r\n      bounding_box = ::netgen::GetBoundingBox( shape );\r\n      ProcessIdentifications();\r\n   }\r\n\r\n\r\n\r\n   void OCCGeometry :: SewFaces ()\r\n   {\r\n      (*testout) << \"Trying to sew faces ...\" << endl;\r\n      cout << \"Trying to sew faces ...\" << flush;\r\n\r\n      BRepOffsetAPI_Sewing sewedObj(1);\r\n \r\n      for (int i = 1; i <= fmap.Extent(); i++)\r\n      {\r\n         TopoDS_Face face = TopoDS::Face (fmap(i));\r\n         sewedObj.Add (face);\r\n      }\r\n\r\n      sewedObj.Perform();\r\n\r\n      if (!sewedObj.SewedShape().IsNull())\r\n      {\r\n         shape = sewedObj.SewedShape();\r\n         cout << \" done\" << endl;\r\n      }\r\n      else\r\n         cout << \" not possible\";\r\n   }\r\n\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: MakeSolid ()\r\n   {\r\n      TopExp_Explorer exp0;\r\n\r\n      (*testout) << \"Trying to build solids ...\" << endl;\r\n      cout << \"Trying to build solids ...\" << flush;\r\n\r\n      BRepBuilderAPI_MakeSolid ms;\r\n      int count = 0;\r\n      for (exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next())\r\n      {\r\n         count++;\r\n         ms.Add (TopoDS::Shell(exp0.Current()));\r\n      }\r\n\r\n      if (!count)\r\n      {\r\n         cout << \" not possible (no shells)\" << endl;\r\n         return;\r\n      }\r\n\r\n      BRepCheck_Analyzer ba(ms);\r\n      if (ba.IsValid ())\r\n      {\r\n         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;\r\n         sfs->Init (ms);\r\n\r\n         sfs->SetPrecision(1e-5);\r\n         sfs->SetMaxTolerance(1e-5);\r\n\r\n         sfs->Perform();\r\n\r\n         shape = sfs->Shape();\r\n\r\n         for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next())\r\n         {\r\n            TopoDS_Solid solid = TopoDS::Solid(exp0.Current());\r\n            TopoDS_Solid newsolid = solid;\r\n            BRepLib::OrientClosedSolid (newsolid);\r\n            Handle(ShapeBuild_ReShape) rebuild = new ShapeBuild_ReShape;\r\n            rebuild->Replace(solid, newsolid);\r\n\r\n            TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_SHAPE, 1);\r\n            shape = newshape;\r\n         }\r\n\r\n         cout << \" done\" << endl;\r\n      }\r\n      else\r\n         cout << \" not possible\" << endl;\r\n   }\r\n\r\n\r\n  Array<const GeometryVertex*> OCCGeometry :: GetFaceVertices(const GeometryFace& face) const\r\n  {\r\n    Array<const GeometryVertex*> verts;\r\n    const auto& occface = dynamic_cast<const OCCFace&>(face);\r\n    for(auto& vert : GetVertices(occface.Shape()))\r\n      verts.Append(&GetVertex(vert));\r\n    return verts;\r\n  }\r\n\r\n\r\n   void OCCGeometry :: BuildVisualizationMesh (double deflection)\r\n   {\r\n      // cout << IM(5) << \"Preparing visualization (deflection = \" << deflection << \") ... \" << flush;\r\n      BuildTriangulation(shape);\r\n      // cout << IM(5) << \"done\" << endl;\r\n   }\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: CalcBoundingBox ()\r\n   {\r\n      boundingbox = ::netgen::GetBoundingBox(shape);\r\n      (*testout) << \"Bounding Box = [\" << boundingbox.PMin() << \" - \" << boundingbox.PMax() << \"]\" << endl;\r\n      SetCenter();\r\n   }\r\n\r\n\r\n//    void OCCGeometry :: WriteOCC_STL(char * filename)\r\n//    {\r\n//       cout << \"writing stl...\"; cout.flush();\r\n//       StlAPI_Writer writer;\r\n//       writer.RelativeMode() = Standard_False;\r\n// \r\n//       writer.SetDeflection(0.02);\r\n//       writer.Write(shape,filename);\r\n// \r\n//       cout << \"done\" << endl;\r\n//    }\r\n\r\n\r\n  void LoadOCCInto(OCCGeometry* occgeo, const filesystem::path & filename)\r\n  {\r\n      static Timer timer_all(\"LoadOCC\"); RegionTimer rtall(timer_all);\r\n      static Timer timer_readfile(\"LoadOCC-ReadFile\");\r\n      static Timer timer_transfer(\"LoadOCC-Transfer\");\r\n      static Timer timer_getnames(\"LoadOCC-get names\");\r\n\r\n      // Initiate a dummy XCAF Application to handle the STEP XCAF Document\r\n      static Handle(XCAFApp_Application) dummy_app = XCAFApp_Application::GetApplication();\r\n\r\n      // Create an XCAF Document to contain the STEP file itself\r\n      Handle(TDocStd_Document) step_doc;\r\n\r\n      // Check if a STEP File is already open under this handle, if so, close it to prevent\r\n      // Segmentation Faults when trying to create a new document\r\n      if(dummy_app->NbDocuments() > 0)\r\n      {\r\n         dummy_app->GetDocument(1,step_doc);\r\n         dummy_app->Close(step_doc);\r\n      }\r\n      dummy_app->NewDocument (\"STEP-XCAF\",step_doc);\r\n\r\n      timer_readfile.Start();\r\n      STEPCAFControl_Reader reader;\r\n\r\n      // Enable transfer of colours\r\n      reader.SetColorMode(Standard_True);\r\n      reader.SetNameMode(Standard_True);\r\n      Standard_Integer stat = reader.ReadFile(filename.string().c_str());\r\n      timer_readfile.Stop();\r\n\r\n      timer_transfer.Start();\r\n      if(stat != IFSelect_RetDone)\r\n      {\r\n        throw NgException(\"Couldn't load OCC geometry\");\r\n      }\r\n\r\n      reader.Transfer(step_doc);\r\n      timer_transfer.Stop();\r\n\r\n      // Read in the shape(s) and the colours present in the STEP File\r\n      auto step_shape_contents = XCAFDoc_DocumentTool::ShapeTool(step_doc->Main());\r\n\r\n      TDF_LabelSequence step_shapes;\r\n      step_shape_contents->GetShapes(step_shapes);\r\n\r\n      // For the STEP File Reader in OCC, the 1st Shape contains the entire \r\n      // compound geometry as one shape\r\n      auto main_shape = step_shape_contents->GetShape(step_shapes.Value(1)); \r\n\r\n      step_utils::LoadProperties(main_shape, reader, step_doc);\r\n\r\n      occgeo->shape = main_shape;\r\n      occgeo->changed = 1;\r\n      occgeo->BuildFMap();\r\n      occgeo->CalcBoundingBox();\r\n      PrintContents (occgeo);\r\n  }\r\n\r\n   // Philippose - 23/02/2009\r\n   /* Special IGES File load function including the ability\r\n   to extract individual surface colours via the extended\r\n   OpenCascade XDE and XCAF Feature set.\r\n   */\r\n   OCCGeometry *LoadOCC_IGES(const filesystem::path & filename)\r\n   {\r\n      OCCGeometry *occgeo;\r\n      occgeo = new OCCGeometry;\r\n      // Initiate a dummy XCAF Application to handle the IGES XCAF Document\r\n      static Handle(XCAFApp_Application) dummy_app = XCAFApp_Application::GetApplication();\r\n\r\n      // Create an XCAF Document to contain the IGES file itself\r\n      Handle(TDocStd_Document) iges_doc;\r\n\r\n      // Check if a IGES File is already open under this handle, if so, close it to prevent\r\n      // Segmentation Faults when trying to create a new document\r\n      if(dummy_app->NbDocuments() > 0)\r\n      {\r\n         dummy_app->GetDocument(1,iges_doc);\r\n         dummy_app->Close(iges_doc);\r\n      }\r\n      dummy_app->NewDocument (\"IGES-XCAF\",iges_doc);\r\n\r\n      IGESCAFControl_Reader reader;\r\n\r\n      Standard_Integer stat = reader.ReadFile(filename.string().c_str());\r\n\r\n      if(stat != IFSelect_RetDone)\r\n      {\r\n        throw NgException(\"Couldn't load occ\");\r\n      }\r\n\r\n      // Enable transfer of colours\r\n      reader.SetColorMode(Standard_True);\r\n      reader.SetNameMode(Standard_True);\r\n\r\n      reader.Transfer(iges_doc);\r\n\r\n      // Read in the shape(s) and the colours present in the IGES File\r\n      Handle(XCAFDoc_ShapeTool) iges_shape_contents = XCAFDoc_DocumentTool::ShapeTool(iges_doc->Main());\r\n      Handle(XCAFDoc_ColorTool) iges_colour_contents = XCAFDoc_DocumentTool::ColorTool(iges_doc->Main());\r\n\r\n      TDF_LabelSequence iges_shapes;\r\n      iges_shape_contents->GetShapes(iges_shapes);\r\n\r\n      // List out the available colours in the IGES File as Colour Names\r\n      // TDF_LabelSequence all_colours;\r\n      // iges_colour_contents->GetColors(all_colours);\r\n      // PrintMessage(1,\"Number of colours in IGES File: \",all_colours.Length());\r\n      // for(int i = 1; i <= all_colours.Length(); i++)\r\n      // {\r\n      //    Quantity_Color col;\r\n      //    stringstream col_rgb;\r\n      //    iges_colour_contents->GetColor(all_colours.Value(i),col);\r\n      //    col_rgb << \" : (\" << col.Red() << \",\" << col.Green() << \",\" << col.Blue() << \")\";\r\n      //    PrintMessage(1, \"Colour [\", i, \"] = \",col.StringName(col.Name()),col_rgb.str());\r\n      // }\r\n\r\n\r\n      // For the IGES Reader, all the shapes can be exported as one compound shape\r\n      // using the \"OneShape\" member\r\n      auto shape = reader.OneShape();\r\n      auto shapeTool = XCAFDoc_DocumentTool::ShapeTool(iges_doc->Main());\r\n      // load colors\r\n      for (auto typ : {TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\r\n        for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n          {\r\n            TDF_Label label;\r\n            shapeTool->Search(e.Current(), label);\r\n\r\n            if(label.IsNull())\r\n              continue;\r\n\r\n            XCAFPrs_IndexedDataMapOfShapeStyle set;\r\n            TopLoc_Location loc;\r\n            XCAFPrs::CollectStyleSettings(label, loc, set);\r\n            XCAFPrs_Style aStyle;\r\n            set.FindFromKey(e.Current(), aStyle);\r\n\r\n            auto & prop = OCCGeometry::GetProperties(e.Current());\r\n            if(aStyle.IsSetColorSurf())\r\n              prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());\r\n          }\r\n\r\n      // load names\r\n      auto workSession = reader.WS();\r\n      auto model = workSession->Model();\r\n      auto transProc = workSession->TransferReader()->TransientProcess();\r\n      Standard_Integer nb = model->NbEntities();\r\n      for (Standard_Integer i = 1; i <= nb; i++)\r\n        {\r\n          Handle(Standard_Transient) entity = model->Value(i);\r\n          auto item = Handle(StepRepr_RepresentationItem)::DownCast(entity);\r\n\r\n          if(item.IsNull())\r\n            continue;\r\n\r\n          TopoDS_Shape shape = TransferBRep::ShapeResult(transProc->Find(item));\r\n          string name = item->Name()->ToCString();\r\n          if (!transProc->IsBound(item))\r\n            continue;\r\n\r\n          OCCGeometry::GetProperties(shape).name = name;\r\n        }\r\n\r\n      occgeo->shape = shape;\r\n      occgeo->changed = 1;\r\n      occgeo->BuildFMap();\r\n\r\n      occgeo->CalcBoundingBox();\r\n      PrintContents (occgeo);\r\n      return occgeo;\r\n   }\r\n\r\n\r\n\r\n\r\n\r\n   // Philippose - 29/01/2009\r\n   /* Special STEP File load function including the ability\r\n   to extract individual surface colours via the extended\r\n   OpenCascade XDE and XCAF Feature set.\r\n   */\r\n   OCCGeometry * LoadOCC_STEP (const filesystem::path & filename)\r\n   {\r\n      OCCGeometry * occgeo;\r\n      occgeo = new OCCGeometry;\r\n\r\n      LoadOCCInto(occgeo, filename);\r\n      return occgeo;\r\n   }\r\n\r\n\r\n\r\n\r\n   OCCGeometry *LoadOCC_BREP (const filesystem::path & filename)\r\n   {\r\n      OCCGeometry * occgeo;\r\n      occgeo = new OCCGeometry;\r\n\r\n      BRep_Builder aBuilder;\r\n      Standard_Boolean result = BRepTools::Read(occgeo->shape, filename.string().c_str(), aBuilder);\r\n\r\n      if(!result)\r\n      {\r\n        result = BinTools::Read(occgeo->shape, filename.string().c_str());\r\n        if (!result)\r\n          {\r\n            delete occgeo;\r\n            throw Exception(\"Could not read BREP file \" + filename.string());\r\n          }\r\n      }\r\n\r\n      occgeo->changed = 1;\r\n      occgeo->BuildFMap();\r\n\r\n      occgeo->CalcBoundingBox();\r\n      PrintContents (occgeo);\r\n\r\n      return occgeo;\r\n   }\r\n\r\n\r\n  void OCCGeometry :: Save (const filesystem::path & filename) const\r\n  {\r\n    string ext = ToLower(filename.extension());\r\n    auto s_filename = filename.string();\r\n    auto c_filename = s_filename.c_str();\r\n\r\n    if (ext == \".igs\")\r\n      {\r\n\tIGESControl_Writer writer(\"millimeters\", 1);\r\n\twriter.AddShape (shape);\r\n\twriter.Write (c_filename);\r\n      }\r\n    else if (ext == \".stp\")\r\n      {\r\n          step_utils::WriteSTEP(*this, filename);\r\n      }\r\n    else if (ext == \".stl\")\r\n      {\r\n\tStlAPI_Writer writer;\r\n\twriter.ASCIIMode() = Standard_True;\r\n\twriter.Write (shape, c_filename);\r\n      }\r\n    else if (ext == \".stlb\")\r\n      {\r\n\tStlAPI_Writer writer;\r\n\twriter.ASCIIMode() = Standard_False;\r\n\twriter.Write (shape, c_filename);\r\n      }\r\n\r\n    throw NgException (\"Unknown target format: \" + filename);\r\n  }\r\n\r\n  void OCCGeometry :: SaveToMeshFile (ostream & ost) const\r\n  {\r\n    auto ss = make_shared<stringstream>();\r\n    TextOutArchive out(ss);\r\n    NetgenGeometry *geo = const_cast<OCCGeometry*>(this);\r\n    out & geo;\r\n\r\n    ost << \"TextOutArchive\" << endl;\r\n    ost << ss->str().size() << endl;\r\n    ost << ss->str();\r\n  }\r\n\r\n  void OCCGeometry :: DoArchive(Archive& ar)\r\n  {\r\n    constexpr int current_format_version = 0;\r\n\r\n    int format_version = current_format_version;\r\n    auto netgen_version = GetLibraryVersion(\"netgen\");\r\n    ar & netgen_version & format_version;\r\n\r\n    if(ar.Output())\r\n      {\r\n        std::stringstream ss;\r\n#if OCC_VERSION_HEX < 0x070600\r\n        BRepTools::Write(shape, ss);\r\n#else\r\n        BRepTools::Write(shape, ss, false, false, TopTools_FormatVersion_VERSION_1);\r\n#endif\r\n        ar << ss.str();\r\n      }\r\n    else\r\n      {\r\n        if(format_version>current_format_version)\r\n            throw Exception(\"Loading OCCGeometry from archive: unknown format version \"\r\n                    + ToString(format_version)\r\n                    + \", written by netgen version \"\r\n                    + ToString(netgen_version));\r\n        std::string str;\r\n        ar & str;\r\n        stringstream ss(str);\r\n        BRep_Builder builder;\r\n        BRepTools::Read(shape, ss, builder);\r\n      }\r\n\r\n    TopTools_IndexedMapOfShape shape_map;\r\n    Array<TopoDS_Shape> shape_list;\r\n\r\n    ar & dimension;\r\n    auto types = Array<TopAbs_ShapeEnum>{ TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE };\r\n    if(ar.GetVersion(\"netgen\") >= \"v6.2.2406-22\")\r\n      types.Append(TopAbs_VERTEX);\r\n    for (auto typ : types)\r\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n        {\r\n          auto ds = e.Current();\r\n          if(shape_map.FindIndex(ds) == 0)\r\n            {\r\n              shape_map.Add(ds);\r\n              shape_list.Append(ds);\r\n            }\r\n        }\r\n\r\n    for (auto s : shape_list)\r\n      {\r\n        bool has_properties = HaveProperties(s);\r\n        ar & has_properties;\r\n        if(has_properties)\r\n          ar & GetProperties(s);\r\n\r\n        bool has_identifications = HaveIdentifications(s);\r\n        ar & has_identifications;\r\n        if(has_identifications)\r\n          {\r\n            int n_idents;\r\n            std::vector<OCCIdentification> used_idents;\r\n            if(ar.Output())\r\n              {\r\n                // only use identifications that are used within the geometry\r\n                for(auto& id : GetIdentifications(s))\r\n                  {\r\n                    if(shape_map.Contains(id.from) && shape_map.Contains(id.to))\r\n                      used_idents.push_back(id);\r\n                  }\r\n                n_idents = used_idents.size();\r\n              }\r\n            auto & idents = ar.Output() ? used_idents : GetIdentifications(s);\r\n            ar & n_idents;\r\n            idents.resize(n_idents);\r\n            for(auto i : Range(n_idents))\r\n              {\r\n                auto & id = idents[i];\r\n                int id_from, id_to;\r\n                if(ar.Output())\r\n                {\r\n                  id_from = shape_map.FindIndex(id.from)-1;\r\n                  id_to = shape_map.FindIndex(id.to)-1;\r\n                }\r\n                ar & id_from & id_to;\r\n\r\n                // trafo is now optional -> special treatment necessary for backward compatibility\r\n                if(ar.Output() || netgen_version >= \"v6.2.2403-34-g571cbbe4\")\r\n                  ar & id.trafo;\r\n                else\r\n                {\r\n                  auto trafo = Transformation<3>();\r\n                  ar & trafo;\r\n                  id.trafo = trafo;\r\n                }\r\n                ar & id.name;\r\n                if(ar.Input())\r\n                {\r\n                    id.from = shape_list[id_from];\r\n                    id.to = shape_list[id_to];\r\n                }\r\n              }\r\n          }\r\n      }\r\n\r\n    if(ar.Input())\r\n      {\r\n        changed = 1;\r\n        BuildFMap();\r\n        CalcBoundingBox();\r\n      }\r\n  }\r\n  \r\n  const char * shapesname[] =\r\n   {\" \", \"CompSolids\", \"Solids\", \"Shells\",\r\n\r\n   \"Faces\", \"Wires\", \"Edges\", \"Vertices\"};\r\n\r\n  const char * shapename[] =\r\n   {\" \", \"CompSolid\", \"Solid\", \"Shell\",\r\n   \"Face\", \"Wire\", \"Edge\", \"Vertex\"};\r\n\r\n  const char * orientationstring[] =\r\n    {\"+\", \"-\", \"i\", \"e\"};\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: RecursiveTopologyTree (const TopoDS_Shape & sh,\r\n      stringstream & str,\r\n      TopAbs_ShapeEnum l,\r\n      bool isfree,\r\n      const char * lname)\r\n   {\r\n      if (l > TopAbs_VERTEX) return;\r\n\r\n      TopExp_Explorer e;\r\n      int count = 0;\r\n      int count2 = 0;\r\n\r\n      if (isfree)\r\n         e.Init(sh, l, TopAbs_ShapeEnum(l-1));\r\n      else\r\n         e.Init(sh, l);\r\n\r\n      for (; e.More(); e.Next())\r\n      {\r\n         count++;\r\n\r\n         stringstream lname2;\r\n         lname2 << lname << \"/\" << shapename[l] << count;\r\n         str << lname2.str() << \" \";\r\n\r\n         switch (e.Current().ShapeType())\r\n\t   {\r\n\t   case TopAbs_SOLID:\r\n\t     count2 = somap.FindIndex(TopoDS::Solid(e.Current())); break;\r\n\t   case TopAbs_SHELL:\r\n\t     count2 = shmap.FindIndex(TopoDS::Shell(e.Current())); break;\r\n\t   case TopAbs_FACE:\r\n\t     count2 = fmap.FindIndex(TopoDS::Face(e.Current())); break;\r\n\t   case TopAbs_WIRE:\r\n\t     count2 = wmap.FindIndex(TopoDS::Wire(e.Current())); break;\r\n\t   case TopAbs_EDGE:\r\n\t     count2 = emap.FindIndex(TopoDS::Edge(e.Current())); break;\r\n\t   case TopAbs_VERTEX:\r\n\t     count2 = vmap.FindIndex(TopoDS::Vertex(e.Current())); break;\r\n\t   default:\r\n\t     cout << \"RecursiveTopologyTree: Case \" << e.Current().ShapeType() << \" not handled\" << endl;\r\n         }\r\n\r\n         int nrsubshapes = 0;\r\n\r\n         if (l <= TopAbs_WIRE)\r\n         {\r\n            TopExp_Explorer e2;\r\n            for (e2.Init (e.Current(), TopAbs_ShapeEnum (l+1));\r\n               e2.More(); e2.Next())\r\n               nrsubshapes++;\r\n         }\r\n\r\n         str << \"{\" << shapename[l] << \" \" << count2;\r\n         if(HaveProperties(e.Current()))\r\n           {\r\n             const auto& props = GetProperties(e.Current());\r\n             if(props.name || props.maxh < 1e99)\r\n               str << \" - \";\r\n             if(props.name)\r\n               str << props.GetName();\r\n             if(props.maxh < 1e99)\r\n               str << \" maxh(\" << props.maxh << \")\";\r\n           }\r\n\r\n         if (l <= TopAbs_EDGE)\r\n         {\r\n            str << \" (\" << orientationstring[e.Current().Orientation()];\r\n            if (nrsubshapes != 0) str << \", \" << nrsubshapes;\r\n            str << \") } \";\r\n         }\r\n         else\r\n            str << \" } \";\r\n\r\n         RecursiveTopologyTree (e.Current(), str, TopAbs_ShapeEnum (l+1),\r\n            false, (char*)lname2.str().c_str());\r\n\r\n      }\r\n   }\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: GetTopologyTree (stringstream & str)\r\n   {\r\n      cout << \"Building topology tree ... \" << flush;\r\n      RecursiveTopologyTree (shape, str, TopAbs_COMPSOLID, false, \"CompSolids\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_SOLID, true, \"FreeSolids\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_SHELL, true, \"FreeShells\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_FACE, true, \"FreeFaces\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_WIRE, true, \"FreeWires\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_EDGE, true, \"FreeEdges\");\r\n      RecursiveTopologyTree (shape, str, TopAbs_VERTEX, true, \"FreeVertices\");\r\n      str << flush;\r\n      //  cout << \"done\" << endl;\r\n   }\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: CheckIrregularEntities(stringstream & str)\r\n   {\r\n      ShapeAnalysis_CheckSmallFace csm;\r\n\r\n      csm.SetTolerance (1e-6);\r\n\r\n      TopTools_DataMapOfShapeListOfShape mapEdges;\r\n      ShapeAnalysis_DataMapOfShapeListOfReal mapParam;\r\n      TopoDS_Compound theAllVert;\r\n\r\n      int spotfaces = 0;\r\n      int stripsupportfaces = 0;\r\n      int singlestripfaces = 0;\r\n      int stripfaces = 0;\r\n      int facessplitbyvertices = 0;\r\n      int stretchedpinfaces = 0;\r\n      int smoothpinfaces = 0;\r\n      int twistedfaces = 0;\r\n      // int edgessamebutnotidentified = 0;\r\n\r\n      cout << \"checking faces ... \" << flush;\r\n\r\n      int i;\r\n      for (i = 1; i <= fmap.Extent(); i++)\r\n      {\r\n         TopoDS_Face face = TopoDS::Face (fmap(i));\r\n         TopoDS_Edge e1, e2;\r\n\r\n         if (csm.CheckSpotFace (face))\r\n         {\r\n            if (!spotfaces++)\r\n               str << \"SpotFace {Spot face} \";\r\n\r\n            (*testout) << \"Face \" << i << \" is a spot face\" << endl;\r\n            str << \"SpotFace/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" } \";\r\n         }\r\n\r\n         if (csm.IsStripSupport (face))\r\n         {\r\n            if (!stripsupportfaces++)\r\n               str << \"StripSupportFace {Strip support face} \";\r\n\r\n            (*testout) << \"Face \" << i << \" has strip support\" << endl;\r\n            str << \"StripSupportFace/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" } \";\r\n         }\r\n\r\n         if (csm.CheckSingleStrip(face, e1, e2))\r\n         {\r\n            if (!singlestripfaces++)\r\n               str << \"SingleStripFace {Single strip face} \";\r\n\r\n            (*testout) << \"Face \" << i << \" is a single strip (edge \" << emap.FindIndex(e1)\r\n               << \" and edge \" << emap.FindIndex(e2) << \" are identical)\" << endl;\r\n            str << \"SingleStripFace/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" (edge \" << emap.FindIndex(e1)\r\n               << \" and edge \" << emap.FindIndex(e2) << \" are identical)} \";\r\n         }\r\n\r\n         if (csm.CheckStripFace(face, e1, e2))\r\n         {\r\n            if (!stripfaces++)\r\n               str << \"StripFace {Strip face} \";\r\n\r\n            (*testout) << \"Face \" << i << \" is a strip (edge \" << emap.FindIndex(e1)\r\n               << \" and edge \" << emap.FindIndex(e2)\r\n               << \" are identical)\" << endl;\r\n            str << \"StripFace/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" (edge \" << emap.FindIndex(e1)\r\n               << \" and edge \" << emap.FindIndex(e2) << \" are identical)} \";\r\n         }\r\n\r\n         if (int count = csm.CheckSplittingVertices(face, mapEdges, mapParam, theAllVert))\r\n         {\r\n            if (!facessplitbyvertices++)\r\n               str << \"FaceSplitByVertices {Face split by vertices} \";\r\n\r\n            (*testout) << \"Face \" << i << \" is split by \" << count\r\n               << \" vertex/vertices \" << endl;\r\n            str << \"FaceSplitByVertices/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" (split by \" << count << \"vertex/vertices)} \";\r\n         }\r\n\r\n         int whatrow, sens;\r\n         if (int type = csm.CheckPin (face, whatrow, sens))\r\n         {\r\n            if (type == 1)\r\n            {\r\n               if (!smoothpinfaces++)\r\n                  str << \"SmoothPinFace {Smooth pin face} \";\r\n\r\n               (*testout) << \"Face \" << i << \" is a smooth pin\" << endl;\r\n               str << \"SmoothPinFace/Face\" << i << \" \";\r\n               str << \"{Face \" << i << \" } \";\r\n            }\r\n            else\r\n            {\r\n               if (!stretchedpinfaces++)\r\n                  str << \"StretchedPinFace {Stretched pin face} \";\r\n\r\n               (*testout) << \"Face \" << i << \" is a stretched pin\" << endl;\r\n               str << \"StretchedPinFace/Face\" << i << \" \";\r\n               str << \"{Face \" << i << \" } \";\r\n            }\r\n         }\r\n\r\n         double paramu, paramv;\r\n         if (csm.CheckTwisted (face, paramu, paramv))\r\n         {\r\n            if (!twistedfaces++)\r\n               str << \"TwistedFace {Twisted face} \";\r\n\r\n            (*testout) << \"Face \" << i << \" is twisted\" << endl;\r\n            str << \"TwistedFace/Face\" << i << \" \";\r\n            str << \"{Face \" << i << \" } \";\r\n         }\r\n      }\r\n\r\n      cout << \"done\" << endl;\r\n      cout << \"checking edges ... \" << flush;\r\n\r\n      // double dmax;\r\n      // int cnt = 0;\r\n      NgArray <double> edgeLengths;\r\n      NgArray <int> order;\r\n      edgeLengths.SetSize (emap.Extent());\r\n      order.SetSize (emap.Extent());\r\n\r\n      for (i = 1; i <= emap.Extent(); i++)\r\n      {\r\n         TopoDS_Edge edge1 = TopoDS::Edge (emap(i));\r\n         GProp_GProps system;\r\n         BRepGProp::LinearProperties(edge1, system);\r\n         edgeLengths[i-1] = system.Mass();\r\n      }\r\n\r\n      Sort (edgeLengths, order);\r\n\r\n      str << \"ShortestEdges {Shortest edges} \";\r\n      for (i = 1; i <= min(20, emap.Extent()); i++)\r\n      {\r\n         str << \"ShortestEdges/Edge\" << i;\r\n         str << \" {Edge \" << order[i-1] << \" (L=\" << edgeLengths[order[i-1]-1] << \")} \";\r\n      }\r\n\r\n      str << flush;\r\n\r\n      cout << \"done\" << endl;\r\n   }\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: GetUnmeshedFaceInfo (stringstream & str)\r\n   {\r\n      for (int i = 1; i <= fmap.Extent(); i++)\r\n      {\r\n         if (facemeshstatus[i-1] == -1)\r\n            str << \"Face\" << i << \" {Face \" << i << \" } \";\r\n      }\r\n      str << flush;\r\n   }\r\n\r\n\r\n\r\n\r\n   void OCCGeometry :: GetNotDrawableFaces (stringstream & str)\r\n   {\r\n      for (int i = 1; i <= fmap.Extent(); i++)\r\n      {\r\n         if (!fvispar[i-1].IsDrawable())\r\n            str << \"Face\" << i << \" {Face \" << i << \" } \";\r\n      }\r\n      str << flush;\r\n   }\r\n\r\n\r\n\r\n\r\n   bool OCCGeometry :: ErrorInSurfaceMeshing ()\r\n   {\r\n      for (int i = 1; i <= fmap.Extent(); i++)\r\n         if (facemeshstatus[i-1] == -1)\r\n            return true;\r\n\r\n      return false;\r\n   }\r\n\r\n  bool IsMappedShape(const Transformation<3> & trafo, const TopoDS_Shape & me, const TopoDS_Shape & you)\r\n  {\r\n      if(me.ShapeType() != you.ShapeType()) return false;\r\n\r\n      Bnd_Box bbox;\r\n      BRepBndLib::Add(me, bbox);\r\n      BRepBndLib::Add(you, bbox);\r\n      BoxTree<3> tree( occ2ng(bbox.CornerMin()), occ2ng(bbox.CornerMax()) );\r\n\r\n      Point<3> c_me = occ2ng(Center(me));\r\n      Point<3> c_you = occ2ng(Center(you));\r\n      if(tree.GetTolerance() < Dist(trafo(c_me), c_you))\r\n          return false;\r\n\r\n      TopTools_IndexedMapOfShape vmap;\r\n      std::vector<optional<TopoDS_Shape>> verts;\r\n\r\n      auto verts_me = GetVertices(me);\r\n      auto verts_you = GetVertices(you);\r\n\r\n      if(verts_me.size() != verts_you.size())\r\n          return false;\r\n\r\n      for (auto i : Range(verts_me.size()))\r\n      {\r\n          auto s = verts_me[i];\r\n          if(vmap.FindIndex(s) > 0)\r\n              continue;\r\n          auto p = trafo(occ2ng(s));\r\n          tree.Insert( p, i );\r\n          vmap.Add(s);\r\n          verts.push_back(nullopt);\r\n      }\r\n          \r\n      for (auto vert : verts_you)\r\n      {\r\n          auto s = vert;\r\n          auto p = occ2ng(s);\r\n          bool vert_mapped = false;\r\n          tree.GetFirstIntersecting( p, p, [&](size_t i ) {\r\n            vmap.Add(verts_me[i]);\r\n            verts[vmap.FindIndex(verts_me[i])-1] = s;\r\n            vert_mapped = true;\r\n            return true;\r\n          });\r\n          if(!vert_mapped)\r\n              return false;\r\n      }\r\n      return true;\r\n  }\r\n\r\n  void Identify(const TopoDS_Shape & me, const TopoDS_Shape & you, string name, Identifications::ID_TYPE type, std::optional<std::variant<gp_Trsf, gp_GTrsf>> opt_trafo) \r\n  {\r\n    Transformation<3> trafo;\r\n    if(opt_trafo)\r\n    {\r\n        trafo = occ2ng(*opt_trafo);\r\n    }\r\n    else\r\n    {\r\n        auto v = occ2ng(Center(you)) - occ2ng(Center(me));\r\n        trafo = Transformation<3>(v);\r\n    }\r\n\r\n    ListOfShapes list_me, list_you;\r\n    list_me.push_back(me);\r\n    list_you.push_back(you);\r\n    Identify(list_me, list_you, name, type, trafo);\r\n  }\r\n\r\n  void Identify(const ListOfShapes & me, const ListOfShapes & you, string name, Identifications::ID_TYPE type, Transformation<3> trafo) \r\n  {\r\n    ListOfShapes id_me;\r\n    ListOfShapes id_you;\r\n\r\n    if(auto faces_me = me.Faces(); faces_me.size()>0)\r\n    {\r\n        id_me = faces_me;\r\n        id_you = you.Faces();\r\n    }\r\n    else if(auto edges_me = me.Edges(); edges_me.size()>0)\r\n    {\r\n        id_me = edges_me;\r\n        id_you = you.Edges();\r\n    }\r\n    else\r\n    {\r\n        id_me = me.Vertices();\r\n        id_you = you.Vertices();\r\n    }\r\n\r\n    for(auto shape_me : id_me)\r\n        for(auto shape_you : id_you)\r\n        {\r\n            if(!IsMappedShape(trafo, shape_me, shape_you))\r\n                continue;\r\n\r\n            OCCGeometry::GetIdentifications(shape_me).push_back\r\n                (OCCIdentification { shape_me, shape_you, trafo, name, type });\r\n        }\r\n  }\r\n\r\n  void OCCParameters :: Print(ostream & ost) const\r\n   {\r\n      ost << \"OCC Parameters:\" << endl\r\n\t\t << \"minimum edge length: \" << resthminedgelenenable\r\n\t\t << \", min len = \" << resthminedgelen << endl;\r\n   }\r\n\r\n  DLL_HEADER extern OCCParameters occparam;\r\n  OCCParameters occparam;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n  // int OCCGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)\r\n  //  {\r\n  //    return OCCGenerateMesh (*this, mesh, mparam, occparam);\r\n  //  }\r\n  static RegisterClassForArchive<OCCGeometry, NetgenGeometry> regnggeo;\r\n\r\n  namespace step_utils\r\n  {\r\n      void LoadProperties(const TopoDS_Shape & shape,\r\n                          const STEPCAFControl_Reader & reader,\r\n                          const Handle(TDocStd_Document) step_doc)\r\n      {\r\n        static Timer t(\"step_utils::LoadProperties\"); RegionTimer rt(t);\r\n\r\n        auto workSession = reader.Reader().WS();\r\n        auto model = workSession->Model();\r\n        auto transferReader = workSession->TransferReader();\r\n        auto transProc = transferReader->TransientProcess();\r\n        auto shapeTool = XCAFDoc_DocumentTool::ShapeTool(step_doc->Main());\r\n\r\n        // load colors\r\n        for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\r\n          for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n          {\r\n            TDF_Label label;\r\n            shapeTool->Search(e.Current(), label);\r\n\r\n            if(label.IsNull())\r\n                continue;\r\n\r\n            XCAFPrs_IndexedDataMapOfShapeStyle set;\r\n            TopLoc_Location loc;\r\n            XCAFPrs::CollectStyleSettings(label, loc, set);\r\n            XCAFPrs_Style aStyle;\r\n            set.FindFromKey(e.Current(), aStyle);\r\n            if(aStyle.IsSetColorSurf())\r\n              {\r\n                for(TopExp_Explorer e2(e.Current(), TopAbs_FACE); e2.More(); e2.Next())\r\n                  {\r\n                    auto & prop = OCCGeometry::GetProperties(e2.Current());\r\n                    prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());\r\n                  }\r\n              }\r\n            if(aStyle.IsSetColorCurv())\r\n              {\r\n                for(TopExp_Explorer e2(e.Current(), TopAbs_EDGE); e2.More(); e2.Next())\r\n                  {\r\n                    auto & prop = OCCGeometry::GetProperties(e2.Current());\r\n                    prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());\r\n                  }\r\n              }\r\n          }\r\n\r\n        // load names\r\n        Standard_Integer nb = model->NbEntities();\r\n        for (Standard_Integer i = 1; i <= nb; i++)\r\n          {\r\n            Handle(Standard_Transient) entity = model->Value(i);\r\n            auto item = Handle(StepRepr_RepresentationItem)::DownCast(entity);\r\n\r\n            if(item.IsNull())\r\n                continue;\r\n\r\n            TopoDS_Shape shape = TransferBRep::ShapeResult(transProc->Find(item));\r\n            string name = item->Name()->ToCString();\r\n            if (!transProc->IsBound(item) || name == \"\")\r\n              continue;\r\n\r\n            // we only allow names on SOLIDS, FACES, EDGES, VERTICES.\r\n            // if name is given on a compound, assume it should be on all subshapes\r\n            // of highest dimension\r\n            for(auto & s : GetHighestDimShapes(shape))\r\n              OCCGeometry::GetProperties(s).name = name;\r\n          }\r\n\r\n\r\n        // load custom data (maxh etc.)\r\n        for (Standard_Integer i = 1; i <= nb; i++)\r\n          {\r\n            Handle(Standard_Transient) entity = model->Value(i);\r\n\r\n            auto item = Handle(StepRepr_CompoundRepresentationItem)::DownCast(entity);\r\n\r\n            if(item.IsNull())\r\n                continue;\r\n\r\n            auto shape_item = item->ItemElementValue(1);\r\n            TopoDS_Shape shape = TransferBRep::ShapeResult(transProc->Find(shape_item));\r\n            string name = item->Name()->ToCString();\r\n\r\n            if(name == \"netgen_geometry_identification\")\r\n                ReadIdentifications(item, transProc);\r\n\r\n            if(name != \"netgen_geometry_properties\")\r\n                continue;\r\n\r\n            auto & prop = OCCGeometry::GetProperties(shape);\r\n\r\n            auto nprops = item->NbItemElement();\r\n\r\n            for(auto i : Range(2, nprops+1))\r\n            {\r\n                auto prop_item = item->ItemElementValue(i);\r\n                string prop_name = prop_item->Name()->ToCString();\r\n\r\n                if(prop_name==\"maxh\")\r\n                    prop.maxh = Handle(StepRepr_ValueRepresentationItem)::DownCast(prop_item)\r\n                        ->ValueComponentMember()->Real();\r\n\r\n                if(prop_name==\"hpref\")\r\n                    prop.hpref = Handle(StepRepr_ValueRepresentationItem)::DownCast(prop_item)\r\n                        ->ValueComponentMember()->Real();\r\n            }\r\n          }\r\n      }\r\n\r\n      void WriteProperties(const Handle(Interface_InterfaceModel) model, const Handle(Transfer_FinderProcess) finder, const TopoDS_Shape & shape)\r\n      {\r\n          static const ShapeProperties default_props;\r\n          Handle(StepRepr_RepresentationItem) item = STEPConstruct::FindEntity(finder, shape);\r\n          if(!item)\r\n              return;\r\n          auto prop = OCCGeometry::GetProperties(shape);\r\n\r\n          if(auto n = prop.name)\r\n              item->SetName(MakeName(*n));\r\n\r\n          Array<Handle(StepRepr_RepresentationItem)> props;\r\n          props.Append(item);\r\n\r\n          if(auto maxh = prop.maxh; maxh != default_props.maxh)\r\n              props.Append( MakeReal(maxh, \"maxh\") );\r\n\r\n          if(auto hpref = prop.hpref; hpref != default_props.hpref)\r\n              props.Append( MakeReal(hpref, \"hpref\") );\r\n\r\n          if(props.Size()>1)\r\n          {\r\n              for(auto & item : props.Range(1, props.Size()))\r\n                  model->AddEntity(item);\r\n\r\n              auto compound = MakeCompound(props, \"netgen_geometry_properties\");\r\n              model->AddEntity(compound);\r\n          }\r\n\r\n          WriteIdentifications(model, shape, finder);\r\n      }\r\n\r\n      void WriteIdentifications(const Handle(Interface_InterfaceModel) model, const TopoDS_Shape & shape, const Handle(Transfer_FinderProcess) finder)\r\n      {\r\n          Handle(StepRepr_RepresentationItem) item = STEPConstruct::FindEntity(finder, shape);\r\n          if(!OCCGeometry::HaveIdentifications(shape))\r\n            return;\r\n          auto & identifications = OCCGeometry::GetIdentifications(shape);\r\n          if(identifications.size()==0)\r\n              return;\r\n          // auto n = identifications.size();\r\n          Array<Handle(StepRepr_RepresentationItem)> ident_items;\r\n          ident_items.Append(item);\r\n\r\n          for(auto & ident : identifications)\r\n          {\r\n              const auto& to = STEPConstruct::FindEntity(finder, ident.from == shape ? ident.to : ident.from);\r\n              if(to.IsNull())\r\n                  continue;\r\n              Array<Handle(StepRepr_RepresentationItem)> items;\r\n              items.Append(MakeReal(ident.from == shape ? 1 : 0));\r\n              items.Append(to);\r\n              Transformation<3> trafo;\r\n              if(ident.trafo) trafo = *ident.trafo;\r\n              auto & m = trafo.GetMatrix();\r\n              for(auto i : Range(9))\r\n                  items.Append(MakeReal(m(i)));\r\n              auto & v = trafo.GetVector();\r\n              for(auto i : Range(3))\r\n                  items.Append(MakeReal(v(i)));\r\n              items.Append(MakeInt(ident.type));\r\n              for(auto & item : items.Range(0, items.Size()))\r\n                  model->AddEntity(item);\r\n              ident_items.Append(MakeCompound(items, ident.name));\r\n          }\r\n          for(auto & item : ident_items.Range(1, ident_items.Size()))\r\n            model->AddEntity(item);\r\n          auto comp = MakeCompound(ident_items, \"netgen_geometry_identification\");\r\n          model->AddEntity(comp);\r\n      }\r\n\r\n      void ReadIdentifications(Handle(StepRepr_RepresentationItem) item, Handle(Transfer_TransientProcess) transProc)\r\n      {\r\n          auto idents = Handle(StepRepr_CompoundRepresentationItem)::DownCast(item);\r\n          auto n = idents->NbItemElement();\r\n          std::vector<OCCIdentification> result;\r\n          auto shape_origin = TransferBRep::ShapeResult(transProc->Find(idents->ItemElementValue(1)));\r\n\r\n          for(auto i : Range(2,n+1))\r\n          {\r\n              auto id_item = Handle(StepRepr_CompoundRepresentationItem)::DownCast(idents->ItemElementValue(i));\r\n              OCCIdentification ident;\r\n              ident.name = id_item->Name()->ToCString();\r\n              auto is_from = ReadReal(id_item->ItemElementValue(1));\r\n              if(is_from)\r\n                {\r\n                  ident.from = shape_origin;\r\n                  ident.to = TransferBRep::ShapeResult(transProc->Find(id_item->ItemElementValue(2)));\r\n                }\r\n              else\r\n                {\r\n                  ident.from = TransferBRep::ShapeResult(\r\n                      transProc->Find(id_item->ItemElementValue(2)));\r\n                  ident.to = shape_origin;\r\n                }\r\n\r\n              Transformation<3> trafo;\r\n              auto & m = trafo.GetMatrix();\r\n              for(auto i : Range(9))\r\n                  m(i) = ReadReal(id_item->ItemElementValue(3+i));\r\n              auto & v = trafo.GetVector();\r\n              for(auto i : Range(3))\r\n                  v(i) = ReadReal(id_item->ItemElementValue(12+i));\r\n              if(FlatVector(9, &trafo.GetMatrix()(0,0)).L2Norm() != .0 && trafo.GetVector().Length2() != .0)\r\n                  ident.trafo = trafo;\r\n              ident.type = Identifications::ID_TYPE(ReadInt(id_item->ItemElementValue(15)));\r\n              result.push_back(ident);\r\n          }\r\n          OCCGeometry::GetIdentifications(shape_origin) = result;\r\n      }\r\n\r\n      void WriteSTEP(const TopoDS_Shape & shape, const filesystem::path & filename)\r\n      {\r\n          Interface_Static::SetCVal(\"write.step.schema\", \"AP242IS\");\r\n          Interface_Static::SetIVal(\"write.step.assembly\",1);\r\n          Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication();\r\n          Handle(TDocStd_Document) doc;\r\n\r\n          app->NewDocument(\"STEP-XCAF\", doc);\r\n          Handle(XCAFDoc_ShapeTool) shapetool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());\r\n          Handle(XCAFDoc_ColorTool) colortool = XCAFDoc_DocumentTool::ColorTool(doc->Main());\r\n          TDF_Label label = shapetool->NewShape();\r\n          shapetool->SetShape(label, shape);\r\n\r\n          Handle(XSControl_WorkSession) session = new XSControl_WorkSession;\r\n          STEPCAFControl_Writer writer(session);\r\n          const Handle(Interface_InterfaceModel) model = session->Model();\r\n\r\n          // Set colors (BEFORE transferring shape into step data structures)\r\n          for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\r\n            for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n              {\r\n                auto prop = OCCGeometry::GetProperties(e.Current());\r\n                if(auto col = prop.col)\r\n                    colortool->SetColor(e.Current(), step_utils::MakeColor(*col), XCAFDoc_ColorGen);\r\n              }\r\n\r\n          // Transfer shape into step data structures -> now we can manipulate/add step representation items\r\n          writer.Transfer(doc, STEPControl_AsIs);\r\n\r\n          // Write all other properties\r\n          auto finder = session->TransferWriter()->FinderProcess();\r\n\r\n          for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\r\n            for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n                WriteProperties(model, finder, e.Current());\r\n\r\n          writer.Write(filename.string().c_str());\r\n      }\r\n\r\n  } // namespace step_utils\r\n}\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "libsrc/occ/occgeom.hpp",
    "content": "#ifndef FILE_OCCGEOM\r\n#define FILE_OCCGEOM\r\n\r\n/* *************************************************************************/\r\n/* File:   occgeom.hpp                                                     */\r\n/* Author: Robert Gaisbauer                                                */\r\n/* Date:   26. May  03                                                     */\r\n/* *************************************************************************/\r\n\r\n#ifdef OCCGEOMETRY\r\n\r\n#include <set>\r\n\r\n#include <meshing.hpp>\r\n#include \"occ_utils.hpp\"\r\n#include \"occmeshsurf.hpp\"\r\n\r\n#include <BOPAlgo_BuilderShape.hxx>\r\n#include <BRepTools_ReShape.hxx>\r\n#include <BRepBuilderAPI_MakeShape.hxx>\r\n#include <BRepBuilderAPI_Sewing.hxx>\r\n#include <Quantity_ColorRGBA.hxx>\r\n#include <STEPCAFControl_Reader.hxx>\r\n#include <StepBasic_MeasureValueMember.hxx>\r\n#include <StepRepr_CompoundRepresentationItem.hxx>\r\n#include <StepRepr_IntegerRepresentationItem.hxx>\r\n#include <StepRepr_ValueRepresentationItem.hxx>\r\n#include <TCollection_HAsciiString.hxx>\r\n#include <TDocStd_Document.hxx>\r\n#include <TopoDS.hxx>\r\n#include <TopoDS_Shape.hxx>\r\n#include <Transfer_FinderProcess.hxx>\r\n\r\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4\r\n#define OCC_HAVE_HISTORY\r\n#endif\r\n\r\nnamespace netgen\r\n{\r\n\r\n  // extern DLL_HEADER MeshingParameters mparam;\r\n\r\n#define PROJECTION_TOLERANCE 1e-10\r\n\r\n#define ENTITYISVISIBLE 1\r\n#define ENTITYISHIGHLIGHTED 2\r\n#define ENTITYISDRAWABLE 4\r\n\r\n#define OCCGEOMETRYVISUALIZATIONNOCHANGE   0\r\n#define OCCGEOMETRYVISUALIZATIONFULLCHANGE 1  // Compute transformation matrices and redraw\r\n#define OCCGEOMETRYVISUALIZATIONHALFCHANGE 2  // Redraw\r\n\r\n  bool IsMappedShape(const Transformation<3> & trafo, const TopoDS_Shape & me, const TopoDS_Shape & you);\r\n\r\n  class EntityVisualizationCode\r\n  {\r\n    int code;\r\n\r\n  public:\r\n\r\n    EntityVisualizationCode()\r\n    {  code = ENTITYISVISIBLE + !ENTITYISHIGHLIGHTED + ENTITYISDRAWABLE;}\r\n\r\n    int IsVisible ()\r\n    {  return code & ENTITYISVISIBLE;}\r\n\r\n    int IsHighlighted ()\r\n    {  return code & ENTITYISHIGHLIGHTED;}\r\n\r\n    int IsDrawable ()\r\n    {  return code & ENTITYISDRAWABLE;}\r\n\r\n    void Show ()\r\n    {  code |= ENTITYISVISIBLE;}\r\n\r\n    void Hide ()\r\n    {  code &= ~ENTITYISVISIBLE;}\r\n\r\n    void Highlight ()\r\n    {  code |= ENTITYISHIGHLIGHTED;}\r\n\r\n    void Lowlight ()\r\n    {  code &= ~ENTITYISHIGHLIGHTED;}\r\n\r\n    void SetDrawable ()\r\n    {  code |= ENTITYISDRAWABLE;}\r\n\r\n    void SetNotDrawable ()\r\n    {  code &= ~ENTITYISDRAWABLE;}\r\n  };\r\n\r\n\r\n\r\n  class Line\r\n  {\r\n  public:\r\n    Point<3> p0, p1;\r\n    int layer = 1;\r\n    double Dist (Line l);\r\n    double Length () { return (p1-p0).Length(); }\r\n  };\r\n  \r\n\r\n\r\n  inline double Det3 (double a00, double a01, double a02,\r\n                      double a10, double a11, double a12,\r\n                      double a20, double a21, double a22)\r\n  {\r\n    return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00;\r\n  }\r\n  \r\n  class DLL_HEADER OCCParameters\r\n  {\r\n  public:\r\n\r\n    /// Factor for meshing close edges, moved to meshingparameters\r\n    // double resthcloseedgefac = 2.;\r\n\r\n    /// Enable / Disable detection of close edges\r\n    // int resthcloseedgeenable = true;\r\n\r\n    /// Minimum edge length to be used for dividing edges to mesh points\r\n    // double resthminedgelen = 0.001;\r\n    double resthminedgelen = 1e-4;\r\n\r\n    /// Enable / Disable use of the minimum edge length (by default use 1e-4)\r\n    int resthminedgelenenable = false;\r\n\r\n    /*!\r\n      Dump all the OpenCascade specific meshing parameters \r\n      to console\r\n    */\r\n    void Print (ostream & ost) const;\r\n  };\r\n\r\n\r\n  class DLL_HEADER OCCGeometry : public NetgenGeometry\r\n  {\r\n    Point<3> center;\r\n    OCCParameters occparam;\r\n  public:\r\n    static TopTools_IndexedMapOfShape global_shape_property_indices;\r\n    static std::vector<ShapeProperties> global_shape_properties;\r\n    static TopTools_IndexedMapOfShape global_identification_indices;\r\n    static std::vector<std::vector<OCCIdentification>> global_identifications;\r\n\r\n    static ShapeProperties& GetProperties(const TopoDS_Shape& shape)\r\n    {\r\n      try\r\n        {\r\n          CheckValidPropertyType(shape);\r\n        }\r\n      catch(Exception& e)\r\n        {\r\n          cerr << \"WARNING: \" << e.what() << endl;\r\n        }\r\n      auto index = OCCGeometry::global_shape_property_indices.FindIndex(shape);\r\n      if(index > 0)\r\n        return OCCGeometry::global_shape_properties\r\n          [index-1];\r\n      OCCGeometry::global_shape_property_indices.Add(shape);\r\n      OCCGeometry::global_shape_properties.push_back({});\r\n      return OCCGeometry::global_shape_properties.back();\r\n    }\r\n    static bool HaveProperties(const TopoDS_Shape& shape)\r\n    {\r\n      return OCCGeometry::global_shape_property_indices.FindIndex(shape) > 0;\r\n    }\r\n    static std::vector<OCCIdentification>& GetIdentifications(const TopoDS_Shape& shape)\r\n    {\r\n      auto index = OCCGeometry::global_identification_indices.FindIndex(shape);\r\n      if(index > 0)\r\n        return OCCGeometry::global_identifications[index-1];\r\n      OCCGeometry::global_identification_indices.Add(shape);\r\n      OCCGeometry::global_identifications.push_back({});\r\n      return OCCGeometry::global_identifications.back();\r\n    }\r\n    static bool HaveIdentifications(const TopoDS_Shape& shape)\r\n    {\r\n      return OCCGeometry::global_identification_indices.FindIndex(shape) > 0;\r\n    }\r\n\r\n    TopoDS_Shape shape;\r\n    TopTools_IndexedMapOfShape fmap, emap, vmap, somap, shmap, wmap;\r\n    NgArray<bool> fsingular, esingular, vsingular;\r\n    Box<3> boundingbox;\r\n\r\n    mutable int changed;\r\n    mutable NgArray<int> facemeshstatus;\r\n\r\n    // Philippose - 15/01/2009\r\n    // Maximum mesh size for a given face\r\n    // (Used to explicitly define mesh size limits on individual faces)\r\n    NgArray<double> face_maxh;\r\n     \r\n    // Philippose - 14/01/2010\r\n    // Boolean array to detect whether a face has been explicitly modified \r\n    // by the user or not\r\n    NgArray<bool> face_maxh_modified;\r\n     \r\n    // Philippose - 15/01/2009\r\n    // Indicates which faces have been selected by the user in geometry mode\r\n    // (Currently handles only selection of one face at a time, but an array would\r\n    //  help to extend this to multiple faces)\r\n    NgArray<bool> face_sel_status;\r\n     \r\n    NgArray<EntityVisualizationCode> fvispar, evispar, vvispar;\r\n     \r\n    double tolerance;\r\n    bool fixsmalledges;\r\n    bool fixspotstripfaces;\r\n    bool sewfaces;\r\n    bool makesolids;\r\n    bool splitpartitions;\r\n\r\n    OCCGeometry()\r\n    {\r\n      somap.Clear();\r\n      shmap.Clear();\r\n      fmap.Clear();\r\n      wmap.Clear();\r\n      emap.Clear();\r\n      vmap.Clear();\r\n    }\r\n\r\n    OCCGeometry(const TopoDS_Shape& _shape, int aoccdim = 3, bool copy = false);\r\n\r\n    Mesh::GEOM_TYPE GetGeomType() const override\r\n    { return Mesh::GEOM_OCC; }\r\n\r\n    void SetDimension(int dim)\r\n    {\r\n        dimension = dim;\r\n        BuildFMap();\r\n    }\r\n\r\n    void SetOCCParameters(const OCCParameters& par)\r\n    { occparam = par; }\r\n\r\n    using NetgenGeometry::GetVertex;\r\n    using NetgenGeometry::GetEdge;\r\n    using NetgenGeometry::GetFace;\r\n    using NetgenGeometry::GetSolid;\r\n\r\n    GeometryShape & GetShape(const TopoDS_Shape & shape)\r\n    {\r\n        return const_cast<GeometryShape&>(as_const(*this).GetShape(shape));\r\n    }\r\n    GeometryVertex & GetVertex(const TopoDS_Shape & shape)\r\n    {\r\n        return const_cast<GeometryVertex&>(as_const(*this).GetVertex(shape));\r\n    }\r\n\r\n    GeometryEdge & GetEdge(const TopoDS_Shape & shape)\r\n    {\r\n        return const_cast<GeometryEdge&>(as_const(*this).GetEdge(shape));\r\n    }\r\n\r\n    GeometryFace & GetFace(const TopoDS_Shape & shape)\r\n    {\r\n        return const_cast<GeometryFace&>(as_const(*this).GetFace(shape));\r\n    }\r\n\r\n    GeometrySolid & GetSolid(const TopoDS_Shape & shape)\r\n    {\r\n        return const_cast<GeometrySolid&>(as_const(*this).GetSolid(shape));\r\n    }\r\n\r\n    const GeometryShape & GetShape(const TopoDS_Shape & shape) const;\r\n    const GeometryVertex & GetVertex(const TopoDS_Shape & shape) const;\r\n    const GeometryEdge & GetEdge(const TopoDS_Shape & shape) const;\r\n    const GeometryFace & GetFace(const TopoDS_Shape & shape) const;\r\n    const GeometrySolid & GetSolid(const TopoDS_Shape & shape) const;\r\n\r\n    void Analyse(Mesh& mesh,\r\n                 const MeshingParameters& mparam) const override;\r\n    bool MeshFace(Mesh& mesh, const MeshingParameters& mparam,\r\n                     int nr, FlatArray<int, PointIndex> glob2loc) const override;\r\n    // void OptimizeSurface(Mesh& mesh, const MeshingParameters& mparam) const override {}\r\n \r\n    void Save (const filesystem::path & filename) const override;\r\n    void SaveToMeshFile (ostream & /* ost */) const override;\r\n     \r\n    void DoArchive(Archive& ar) override;\r\n\r\n    void BuildFMap();\r\n\r\n    auto GetShape() const { return shape; }\r\n    Box<3> GetBoundingBox() const\r\n    { return boundingbox; }\r\n\r\n    int NrSolids() const\r\n    { return somap.Extent(); }\r\n\r\n    // Philippose - 17/01/2009\r\n    // Total number of faces in the geometry\r\n    int NrFaces() const\r\n    { return fmap.Extent(); }\r\n\r\n    void SetCenter()\r\n    { center = boundingbox.Center(); }\r\n\r\n    Point<3> Center() const\r\n    { return center; }\r\n\r\n    OCCSurface GetSurface (int surfi)\r\n    {\r\n      cout << \"OCCGeometry::GetSurface using PLANESPACE\" << endl;\r\n      return OCCSurface (TopoDS::Face(fmap(surfi)), PLANESPACE);\r\n    }\r\n\r\n    void CalcBoundingBox ();\r\n    void BuildVisualizationMesh (double deflection);\r\n    \r\n    void RecursiveTopologyTree (const TopoDS_Shape & sh,\r\n                                stringstream & str,\r\n                                TopAbs_ShapeEnum l,\r\n                                bool free,\r\n                                const char * lname);\r\n\r\n    void GetTopologyTree (stringstream & str);\r\n\r\n    void PrintNrShapes ();\r\n\r\n    void CheckIrregularEntities (stringstream & str);\r\n\r\n    void SewFaces();\r\n\r\n    void MakeSolid();\r\n\r\n    Array<const GeometryVertex*> GetFaceVertices(const GeometryFace& face) const override;\r\n\r\n    void FixFaceOrientation();\r\n    void HealGeometry();\r\n    void GlueGeometry();\r\n\r\n    // Philippose - 15/01/2009\r\n    // Sets the maximum mesh size for a given face\r\n    // (Note: Local mesh size limited by the global max mesh size)\r\n    void SetFaceMaxH(int facenr, double faceh, const MeshingParameters & mparam)\r\n    {\r\n      if((facenr> 0) && (facenr <= fmap.Extent()))\r\n        {\r\n          face_maxh[facenr-1] = min(mparam.maxh,faceh);\r\n            \r\n          // Philippose - 14/01/2010\r\n          // If the face maxh is greater than or equal to the \r\n          // current global maximum, then identify the face as \r\n          // not explicitly controlled by the user any more\r\n          if(faceh >= mparam.maxh)\r\n            {\r\n              face_maxh_modified[facenr-1] = 0;\r\n            }\r\n          else\r\n            {\r\n              face_maxh_modified[facenr-1] = 1;\r\n            }\r\n        }\r\n    }\r\n\r\n    void SetFaceMaxH(size_t facenr, double faceh)\r\n    {\r\n      if(facenr >= fmap.Extent())\r\n        throw RangeException(\"OCCGeometry faces\", facenr, 0, fmap.Extent());\r\n      face_maxh[facenr] = faceh;\r\n      face_maxh_modified[facenr] = true;\r\n    }\r\n\r\n    // Philippose - 15/01/2009\r\n    // Returns the local mesh size of a given face\r\n    double GetFaceMaxH(int facenr)\r\n    {\r\n      if((facenr> 0) && (facenr <= fmap.Extent()))\r\n        {\r\n          return face_maxh[facenr-1];\r\n        }\r\n      else\r\n        {\r\n          return 0.0;\r\n        }\r\n    }\r\n      \r\n    // Philippose - 14/01/2010\r\n    // Returns the flag whether the given face \r\n    // has a mesh size controlled by the user or not\r\n    bool GetFaceMaxhModified(int facenr)\r\n    {\r\n      return face_maxh_modified[facenr-1];\r\n    }\r\n      \r\n    // Philippose - 17/01/2009\r\n    // Returns the index of the currently selected face\r\n    int SelectedFace()\r\n    {\r\n      for(int i = 1; i <= fmap.Extent(); i++)\r\n        {\r\n          if(face_sel_status[i-1])\r\n            {\r\n              return i;\r\n            }\r\n        }\r\n\r\n      return 0;\r\n    }\r\n\r\n    // Philippose - 17/01/2009\r\n    // Sets the currently selected face\r\n    void SetSelectedFace(int facenr)\r\n    {\r\n      face_sel_status = 0;\r\n\r\n      if((facenr >= 1) && (facenr <= fmap.Extent()))\r\n        {\r\n          face_sel_status[facenr-1] = 1;\r\n        }\r\n    }\r\n\r\n    void LowLightAll()\r\n    {\r\n      for (int i = 1; i <= fmap.Extent(); i++)\r\n        fvispar[i-1].Lowlight();\r\n      for (int i = 1; i <= emap.Extent(); i++)\r\n        evispar[i-1].Lowlight();\r\n      for (int i = 1; i <= vmap.Extent(); i++)\r\n        vvispar[i-1].Lowlight();\r\n    }\r\n\r\n    void GetUnmeshedFaceInfo (stringstream & str);\r\n    void GetNotDrawableFaces (stringstream & str);\r\n    bool ErrorInSurfaceMeshing ();\r\n\r\n    //      void WriteOCC_STL(char * filename);\r\n\r\n  private:\r\n    //bool FastProject (int surfi, Point<3> & ap, double& u, double& v) const;\r\n  };\r\n\r\n  DLL_HEADER void Identify(const ListOfShapes & me, const ListOfShapes & you, string name, Identifications::ID_TYPE type, Transformation<3> trafo);\r\n  DLL_HEADER void Identify(const TopoDS_Shape & me, const TopoDS_Shape & you, string name, Identifications::ID_TYPE type, std::optional<std::variant<gp_Trsf, gp_GTrsf>> opt_trafo);\r\n   \r\n\r\n  void PrintContents (OCCGeometry * geom);\r\n\r\n  DLL_HEADER OCCGeometry * LoadOCC_IGES (const filesystem::path & filename);\r\n  DLL_HEADER OCCGeometry * LoadOCC_STEP (const filesystem::path & filename);\r\n  DLL_HEADER OCCGeometry * LoadOCC_BREP (const filesystem::path & filename);\r\n\r\n  // Philippose - 31.09.2009\r\n  // External access to the mesh generation functions within the OCC\r\n  // subsystem (Not sure if this is the best way to implement this....!!)\r\n  DLL_HEADER extern void OCCSetLocalMeshSize(const OCCGeometry & geom, Mesh & mesh, const MeshingParameters & mparam,\r\n                                             const OCCParameters& occparam);\r\n\r\n  DLL_HEADER extern bool OCCMeshFace (const OCCGeometry & geom, Mesh & mesh, FlatArray<int, PointIndex> glob2loc,\r\n                       const MeshingParameters & mparam, int nr, int projecttype, bool delete_on_failure);\r\n\r\n  inline auto GetModified(BRepBuilderAPI_MakeShape & builder, TopoDS_Shape shape) { return builder.Modified(shape); }\r\n  inline auto GetModified(BRepTools_History & history, TopoDS_Shape shape) { return history.Modified(shape); }\r\n  inline auto GetModified(BOPAlgo_BuilderShape & builder, TopoDS_Shape shape) { return builder.Modified(shape); }\r\n  inline ArrayMem<TopoDS_Shape, 1> GetModified(BRepBuilderAPI_Sewing& builder, TopoDS_Shape shape) { return {builder.Modified(shape)}; }\r\n  inline auto GetModified(BRepTools_ReShape& reshape, TopoDS_Shape shape) {\r\n    auto history = reshape.History();\r\n    return history->Modified(shape);\r\n  }\r\n\r\n  template <class TBuilder>\r\n  void PropagateIdentifications (TBuilder & builder, TopoDS_Shape shape, std::optional<Transformation<3>> trafo = nullopt)\r\n  {\r\n    TopTools_IndexedMapOfShape mod_indices;\r\n    Array<TopTools_IndexedMapOfShape> modifications;\r\n    TopTools_MapOfShape shape_handled;\r\n\r\n    Transformation<3> trafo_inv;\r\n    if(trafo)\r\n        trafo_inv = trafo->CalcInverse();\r\n  \r\n    for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE, TopAbs_VERTEX })\r\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n      {\r\n          auto s = e.Current();\r\n          mod_indices.Add(s);\r\n          modifications.Append(TopTools_IndexedMapOfShape());\r\n          modifications.Last().Add(s);\r\n      }\r\n  \r\n    for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE, TopAbs_VERTEX })\r\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n        {\r\n          auto s = e.Current();\r\n            for (auto mods : GetModified(builder, s))\r\n              {\r\n                auto index = mod_indices.FindIndex(s)-1;\r\n                modifications[index].Add(mods);\r\n              }\r\n        }\r\n  \r\n    for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE, TopAbs_VERTEX })\r\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n      {\r\n          auto s = e.Current();\r\n  \r\n          if(shape_handled.Contains(s))\r\n              continue;\r\n          shape_handled.Add(s);\r\n\r\n          if(!OCCGeometry::HaveIdentifications(s))\r\n            continue;\r\n          auto& identifications = OCCGeometry::GetIdentifications(s);\r\n\r\n          // auto& shape_mapped = modifications[mod_indices.FindIndex(s)-1];\r\n  \r\n          for(auto ident : identifications)\r\n          {\r\n              auto i1 = mod_indices.FindIndex(ident.to);\r\n              auto i2 = mod_indices.FindIndex(ident.from);\r\n              if(i1 == 0 || i2 == 0) // not in geometry\r\n                continue;\r\n              auto& mods_to = modifications[i1-1];\r\n              auto& mods_from = modifications[i2-1];\r\n              if(mods_to.Extent()==1 && mods_from.Extent() ==1)\r\n                continue;\r\n  \r\n              auto from = ident.from;\r\n              auto to = ident.to;\r\n  \r\n              for(auto it = mods_from.cbegin(); it != mods_from.cend(); it++)\r\n                for(auto it2 = mods_to.cbegin(); it2 != mods_to.cend(); it2++)\r\n                  {\r\n                      auto& from_mapped = it.Iterator().Value();\r\n                      auto& to_mapped = it2.Iterator().Value();\r\n                      if(from.IsSame(from_mapped) && to.IsSame(to_mapped))\r\n                        continue;\r\n  \r\n                      if(!ident.trafo) continue;\r\n                      Transformation<3> trafo_mapped = *ident.trafo;\r\n\r\n                      if(trafo)\r\n                      {\r\n                          Transformation<3> trafo_temp;\r\n                          trafo_temp.Combine(*ident.trafo, trafo_inv);\r\n                          trafo_mapped.Combine(*trafo, trafo_temp);\r\n                      }\r\n  \r\n                      if(!IsMappedShape(trafo_mapped, from_mapped, to_mapped))\r\n                          continue;\r\n  \r\n                      OCCIdentification id_new = ident;\r\n                      id_new.to = to_mapped;\r\n                      id_new.from = from_mapped;\r\n                      id_new.trafo = trafo_mapped;\r\n                      auto id_owner = from.IsSame(s) ? from_mapped : to_mapped;\r\n                      OCCGeometry::GetIdentifications(id_owner).push_back(id_new);\r\n                  }\r\n          }\r\n      }\r\n  }\r\n  \r\n  template <class TBuilder>\r\n  void PropagateProperties (TBuilder & builder, TopoDS_Shape shape, std::optional<Transformation<3>> trafo = nullopt)\r\n  {\r\n    bool have_identifications = false;\r\n  \r\n    for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE, TopAbs_VERTEX })\r\n      for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\r\n        {\r\n          auto s = e.Current();\r\n          have_identifications |= OCCGeometry::HaveIdentifications(s);\r\n          if(!OCCGeometry::HaveProperties(s))\r\n            continue;\r\n          auto prop = OCCGeometry::GetProperties(s);\r\n          for (auto mods : GetModified(builder, s))\r\n            OCCGeometry::GetProperties(mods).Merge(prop);\r\n        }\r\n    if(have_identifications)\r\n        PropagateIdentifications(builder, shape, trafo);\r\n  }\r\n\r\n  namespace step_utils\r\n  {\r\n      inline Handle(TCollection_HAsciiString) MakeName (string s)\r\n      {\r\n          return new TCollection_HAsciiString(s.c_str());\r\n      };\r\n\r\n      inline Handle(StepRepr_RepresentationItem) MakeInt (int n, string name = \"\")\r\n      {\r\n          Handle(StepRepr_IntegerRepresentationItem) int_obj = new StepRepr_IntegerRepresentationItem;\r\n          int_obj->Init(MakeName(name), n);\r\n          return int_obj;\r\n      }\r\n\r\n      inline int ReadInt (Handle(StepRepr_RepresentationItem) item)\r\n      {\r\n          return Handle(StepRepr_IntegerRepresentationItem)::DownCast(item)->Value();\r\n      }\r\n\r\n      inline Handle(StepRepr_RepresentationItem) MakeReal (double val, string name = \"\")\r\n      {\r\n            Handle(StepBasic_MeasureValueMember) value_member = new StepBasic_MeasureValueMember;\r\n            value_member->SetReal(val);\r\n            Handle(StepRepr_ValueRepresentationItem) value_repr = new StepRepr_ValueRepresentationItem;\r\n            value_repr->Init(MakeName(name), value_member);\r\n            return value_repr;\r\n      }\r\n\r\n      inline double ReadReal (Handle(StepRepr_RepresentationItem) item)\r\n      {\r\n          return Handle(StepRepr_ValueRepresentationItem)::DownCast(item)\r\n              ->ValueComponentMember()->Real();\r\n      }\r\n\r\n\r\n      inline Handle(StepRepr_RepresentationItem) MakeCompound( FlatArray<Handle(StepRepr_RepresentationItem)> items, string name = \"\" )\r\n      {\r\n            Handle(StepRepr_HArray1OfRepresentationItem) array_repr = new StepRepr_HArray1OfRepresentationItem(1,items.Size());\r\n\r\n            for(auto i : Range(items))\r\n                array_repr->SetValue(i+1, items[i]);\r\n\r\n            Handle(StepRepr_CompoundRepresentationItem) comp = new StepRepr_CompoundRepresentationItem;\r\n            comp->Init( MakeName(name), array_repr );\r\n            return comp;\r\n      }\r\n\r\n      void WriteIdentifications(const Handle(Interface_InterfaceModel) model, const TopoDS_Shape & shape, const Handle(Transfer_FinderProcess) finder);\r\n      void ReadIdentifications(Handle(StepRepr_RepresentationItem) item, Handle(Transfer_TransientProcess) transProc);\r\n\r\n      inline Quantity_ColorRGBA MakeColor(const Vec<4> & c)\r\n      {\r\n          return Quantity_ColorRGBA (c[0], c[1], c[2], c[3]);\r\n      }\r\n\r\n      inline Vec<4> ReadColor (const Quantity_ColorRGBA & c)\r\n      {\r\n          auto rgb = c.GetRGB();\r\n          return {rgb.Red(), rgb.Green(), rgb.Blue(), c.Alpha()};\r\n      }\r\n\r\n\r\n      void LoadProperties(const TopoDS_Shape & shape,\r\n                          const STEPCAFControl_Reader & reader,\r\n                          const Handle(TDocStd_Document) step_doc);\r\n      void WriteProperties(const Handle(Interface_InterfaceModel) model, const Handle(Transfer_FinderProcess) finder, const TopoDS_Shape & shape);\r\n\r\n      void WriteSTEP(const TopoDS_Shape & shape, const filesystem::path & filename);\r\n\r\n      inline void WriteSTEP(const OCCGeometry & geo, const filesystem::path & filename)\r\n      {\r\n          WriteSTEP(geo.GetShape(), filename);\r\n      }\r\n\r\n      // deep copy, also ensures consistent shape ordering (face numbers etc.)\r\n      TopoDS_Shape WriteAndRead(const TopoDS_Shape shape);\r\n  } // namespace step_utils\r\n}\r\n\r\n#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "libsrc/occ/occmeshsurf.cpp",
    "content": "#ifdef OCCGEOMETRY\n\n#include <mystdlib.h>\n\n#include <meshing.hpp>\n#include \"occgeom.hpp\"\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#include <GeomLProp_SLProps.hxx>\n#include <ShapeAnalysis_Surface.hxx>\n\n#pragma clang diagnostic pop\n\n#include \"occmeshsurf.hpp\"\n\nnamespace netgen\n{\n\n  bool glob_testout(false);\n\n  void OCCSurface :: GetNormalVector (const Point<3> & p, \n\t\t\t\t      const PointGeomInfo & geominfo,\n\t\t\t\t      Vec<3> & n) const\n  {\n    GeomLProp_SLProps lprop(occface,geominfo.u,geominfo.v,1,1e-8);\n\n    if (lprop.IsNormalDefined())\n      {\n        n = occ2ng(lprop.Normal());\n      }\n    else\n      {\n        gp_Pnt pnt;\n        gp_Vec du, dv;\n\n        double setu=geominfo.u,setv=geominfo.v;\n\tdouble ustep = 0.01*(umax-umin);\n\t// double vstep = 0.01*(vmax-vmin);\n\n\tn=0;\n\n\twhile(setu < umax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))\n\t  setu += ustep;\n\tif(setu < umax)\n\t  {\n\t    lprop.SetParameters(setu,setv);\n            /*\n\t    n(0)+=lprop.Normal().X();\n\t    n(1)+=lprop.Normal().Y();\n\t    n(2)+=lprop.Normal().Z();\n            */\n            n += occ2ng(lprop.Normal());\n\t  }\n\tsetu = geominfo.u;\n\twhile(setu > umin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))\n\t  setu -= ustep;\n\tif(setu > umin)\n\t  {\n\t    lprop.SetParameters(setu,setv);\n            /*\n\t    n(0)+=lprop.Normal().X();\n\t    n(1)+=lprop.Normal().Y();\n\t    n(2)+=lprop.Normal().Z();\n            */\n            n += occ2ng(lprop.Normal());            \n\t  }\n\tsetu = geominfo.u;\n\n\twhile(setv < vmax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))\n\t  setv += ustep;\n\tif(setv < vmax)\n\t  {\n\t    lprop.SetParameters(setu,setv);\n            /*\n\t    n(0)+=lprop.Normal().X();\n\t    n(1)+=lprop.Normal().Y();\n\t    n(2)+=lprop.Normal().Z();\n            */\n            n += occ2ng(lprop.Normal());\n\t  }\n\tsetv = geominfo.v;\n\twhile(setv > vmin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))\n\t  setv -= ustep;\n\tif(setv > vmin)\n\t  {\n\t    lprop.SetParameters(setu,setv);\n            /*\n\t    n(0)+=lprop.Normal().X();\n\t    n(1)+=lprop.Normal().Y();\n\t    n(2)+=lprop.Normal().Z();\n            */\n            n += occ2ng(lprop.Normal());            \n\t  }\n\tsetv = geominfo.v;\n\n\tn.Normalize();\n      }\n\n    if(glob_testout)\n      {\n\t(*testout) << \"u \" << geominfo.u << \" v \" << geominfo.v \n\t\t   << \" du \" << lprop.D1U().X() << \" \"<< lprop.D1U().Y() << \" \"<< lprop.D1U().Z()\n\t\t   << \" dv \" << lprop.D1V().X() << \" \"<< lprop.D1V().Y() << \" \"<< lprop.D1V().Z() << endl;\n      }\n\n\n\n    if (orient == TopAbs_REVERSED) n = -n;\n    //  (*testout) << \"GetNormalVector\" << endl;\n  }\n\n\n  void OCCSurface :: DefineTangentialPlane (const Point<3> & ap1,\n\t\t\t\t\t    const PointGeomInfo & geominfo1,\n\t\t\t\t\t    const Point<3> & ap2,\n\t\t\t\t\t    const PointGeomInfo & geominfo2)\n  {\n    if (projecttype == PLANESPACE)\n      {\n\tp1 = ap1; p2 = ap2;\n\n\t//cout << \"p1 = \" << p1 << endl;\n\t//cout << \"p2 = \" << p2 << endl;\n      \n\tGetNormalVector (p1, geominfo1, ez);\n      \n\tex = p2 - p1;\n\tex -= (ex * ez) * ez;\n\tex.Normalize();\n\tey = Cross (ez, ex); \n\n\tGetNormalVector (p2, geominfo2, n2);\n  \n\tnmid = 0.5*(n2+ez);\n      \n\tez = nmid;\n\tez.Normalize(); \n      \n\tex = (p2 - p1).Normalize();\n\tez -= (ez * ex) * ex;\n\tez.Normalize();\n\tey = Cross (ez, ex);\n\tnmid = ez;\n\t//cout << \"ex \" << ex << \" ey \" << ey << \" ez \" << ez << endl;\n      }\n    else\n      {\n\tif ( (geominfo1.u < umin) ||\n\t     (geominfo1.u > umax) ||\n\t     (geominfo2.u < umin) ||\n\t     (geominfo2.u > umax) ||\n\t     (geominfo1.v < vmin) ||\n\t     (geominfo1.v > vmax) ||\n\t     (geominfo2.v < vmin) ||\n\t     (geominfo2.v > vmax) ) throw UVBoundsException();\n\t  \n\n\tp1 = ap1; p2 = ap2;\n\tpsp1 = Point<2>(geominfo1.u, geominfo1.v);\n\tpsp2 = Point<2>(geominfo2.u, geominfo2.v);\n      \n\tVec<3> n;\n\tGetNormalVector (p1, geominfo1, n);\n\n\tgp_Pnt pnt;\n\tgp_Vec du, dv;\n\toccface->D1 (geominfo1.u, geominfo1.v, pnt, du, dv);\n\n        // static Timer t(\"occ-defintangplane calculations\");\n        // RegionTimer reg(t);\n\n        Mat<3,2> D1_;\n\tD1_(0,0) = du.X(); D1_(1,0) = du.Y(); D1_(2,0) = du.Z();\n\tD1_(0,1) = dv.X(); D1_(1,1) = dv.Y(); D1_(2,1) = dv.Z();\n        auto D1T_ = Trans(D1_);\n\tauto D1TD1_ = D1T_*D1_;\n\tif (Det (D1TD1_) == 0) throw SingularMatrixException();\n        Mat<2,2> DDTinv_;\n        CalcInverse (D1TD1_, DDTinv_);\n\n        Mat<3,2> Y_;\n\tVec<3> y1_ = (ap2-ap1).Normalize();\n\tVec<3> y2_ = Cross(n, y1_).Normalize();\n\tfor (int i = 0; i < 3; i++)\n\t  {\n\t    Y_(i,0) = y1_(i);\n\t    Y_(i,1) = y2_(i);\n\t  }\n\n        auto A_ = DDTinv_ * D1T_ * Y_;\n\tMat<2,2> Ainv_;\n\tif (Det(A_) == 0) throw SingularMatrixException();\n\tCalcInverse (A_, Ainv_);\n\n\tVec<2> temp_ = Ainv_ * (psp2-psp1);\n\tdouble r_ = temp_.Length();\n        Mat<2,2> R_;\n        R_(0,0) = temp_(0)/r_;\n        R_(1,0) = temp_(1)/r_;\n        R_(0,1) = -R_(1,0);\n        R_(1,1) = R_(0,0);\n\n        A_ = A_ * R_;\n        Ainv_ = Trans(R_) * Ainv_;\n\n        Amat = A_;\n        Amatinv = Ainv_;\n        \n\t// temp = Amatinv * (psp2-psp1);\n        \n\n#ifdef OLD\n\tDenseMatrix D1(3,2), D1T(2,3), DDTinv(2,2);\n\tD1(0,0) = du.X(); D1(1,0) = du.Y(); D1(2,0) = du.Z();\n\tD1(0,1) = dv.X(); D1(1,1) = dv.Y(); D1(2,1) = dv.Z();\n\n\t/*\n\t  (*testout) << \"DefineTangentialPlane\" << endl\n\t  << \"---------------------\" << endl;\n\t  (*testout) << \"D1 = \" << endl << D1 << endl;\n\t*/\n\n\tTranspose (D1, D1T);\n\tDenseMatrix D1TD1(3,3);\n\n\tD1TD1 = D1T*D1;\n\tif (D1TD1.Det() == 0) throw SingularMatrixException();\n      \n\tCalcInverse (D1TD1, DDTinv);\n        // cout << \" =?= inv = \" << DDTinv << endl;\n        \n\tDenseMatrix Y(3,2);\n\tVec<3> y1 = (ap2-ap1).Normalize();\n\tVec<3> y2 = Cross(n, y1).Normalize();\n\tfor (int i = 0; i < 3; i++)\n\t  {\n\t    Y(i,0) = y1(i);\n\t    Y(i,1) = y2(i);\n\t  }\n\n\tDenseMatrix A(2,2);\n\tA = DDTinv * D1T * Y;\n\tDenseMatrix Ainv(2,2);\n\n\tif (A.Det() == 0) throw SingularMatrixException();\n\n\tCalcInverse (A, Ainv);\n\n\tfor (int i = 0; i < 2; i++)\n\t  for (int j = 0; j < 2; j++)\n\t    {\n\t      Amat(i,j) = A(i,j);\n\t      Amatinv(i,j) = Ainv(i,j);\n\t    }\n\n\tVec<2> temp = Amatinv * (psp2-psp1);\n      \n\n\tdouble r = temp.Length();\n\t//      double alpha = -acos (temp(0)/r);\n\tdouble alpha = -atan2 (temp(1),temp(0));\n\tDenseMatrix R(2,2);\n\tR(0,0) = cos (alpha);\n\tR(1,0) = -sin (alpha);\n\tR(0,1) = sin (alpha);\n\tR(1,1) = cos (alpha);\n\n        // cout << \"=?= R = \" << R << endl;\n\n\tA = A*R;\n\n\tif (A.Det() == 0) throw SingularMatrixException();\n\n\tCalcInverse (A, Ainv);\n    \n\n\tfor (int i = 0; i < 2; i++)\n\t  for (int j = 0; j < 2; j++)\n\t    {\n\t      Amat(i,j) = A(i,j);\n\t      Amatinv(i,j) = Ainv(i,j);\n\t    }\n        // cout << \"=?= Ainv = \" << endl << Ainv << endl;\n\ttemp = Amatinv * (psp2-psp1);\n        cout << \" =?= Amatinv = \" << Amatinv << endl;        \n#endif\n      };\n \n  }\n\n\n  void OCCSurface :: ToPlane (const Point<3> & p3d,\n\t\t\t      const PointGeomInfo & geominfo,\n\t\t\t      Point<2> & pplane, \n\t\t\t      double h, int & zone) const\n  {\n    // static Timer t(\"ToPlane\"); RegionTimer reg(t);\n    \n    if (projecttype == PLANESPACE)\n      {\n\tVec<3> p1p, n;\n\tGetNormalVector (p3d, geominfo, n);\n      \n\tp1p = p3d - p1;\n\tpplane(0) = (p1p * ex) / h;\n\tpplane(1) = (p1p * ey) / h;\n      \n\tif (n * nmid < 0)\n\t  zone = -1;\n\telse\n\t  zone = 0;\n\n\t/*\n\t  if(zone == -1)\n\t  {\n\t  (*testout) << \"zone = -1 for \" << p3d << \" 2D: \" << pplane << \" n \" << n << \" nmid \" << nmid << endl;\n\t  glob_testout = true;\n\t  GetNormalVector (p3d, geominfo, n);\n\t  glob_testout = false;\n\t  }\n\t*/\n      }\n    else\n      {\n\tpplane = Point<2>(geominfo.u, geominfo.v);\n\t//      (*testout) << \"(u,v) = \" << geominfo.u << \", \" << geominfo.v << endl;\n\tpplane = Point<2> (1/h * (Amatinv * (pplane-psp1)));\n\t//      pplane = Point<2> (h * (Amatinv * (pplane-psp1)));\n\t//      pplane = Point<2> (1/h * ((pplane-psp1)));\n\n\tzone = 0;\n      };\n  }\t\n\n\n  void OCCSurface :: FromPlane (const Point<2> & pplane, \n\t\t\t\tPoint<3> & p3d,\n\t\t\t\tPointGeomInfo & gi,\n\t\t\t\tdouble h) \n  {\n    // static Timer t(\"FromPlane\"); RegionTimer reg(t);\n    \n    if (projecttype == PLANESPACE)\n      {\n\t//      cout << \"2d   : \" << pplane << endl;\n\tp3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey;\n\t//      cout << \"3d   : \" << p3d << endl;\n\tProject (p3d, gi);  \n\t//      cout << \"proj : \" << p3d << endl;\n      }\n    else\n      {\n\t//      Point<2> pspnew = Point<2>(1/h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1));\n\tPoint<2> pspnew = Point<2>(h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1));\n\t//      Point<2> pspnew = Point<2>(h * (Vec<2>(pplane)) + Vec<2>(psp1));\n\tgi.u = pspnew(0);\n\tgi.v = pspnew(1);\n\tgi.trignum = 1;\n        p3d = occ2ng(occface->Value (gi.u, gi.v));\n      };\n  }\n\n\n\n  void OCCSurface :: Project (Point<3> & ap, PointGeomInfo & gi)\n  {\n    static Timer t(\"OccSurface::Project\"); RegionTimer reg(t);\n    static Timer tanal(\"OccSurface::Project analysis\"); \n    static Timer ttol(\"OccSurface::Project approximation\"); \n\n    static Timer t2(\"OccSurface::Project actual\"); \n\n\n    // try Newton's method ...\n    \n    gp_Pnt p = ng2occ(ap);\n\n    double u = gi.u;\n    double v = gi.v;\n#ifdef OLD\n    // was a problem for pheres: got u-v parameters outside range of definition\n    \n    gp_Pnt x = occface->Value (u,v);\n\n    if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return;\n\n    gp_Vec du, dv;\n    occface->D1(u,v,x,du,dv);\n\n    int count = 0;\n    \n    gp_Pnt xold;\n    gp_Vec n;\n    double det, lambda, mu;\n    \n    do\n      {\n        count++;\n        \n        n = du^dv;\n        \n        det = Det3 (n.X(), du.X(), dv.X(),\n                    n.Y(), du.Y(), dv.Y(),\n                    n.Z(), du.Z(), dv.Z());\n        \n        if (det < 1e-15)\n          break;\n        \n        lambda = Det3 (n.X(), p.X()-x.X(), dv.X(),\n                       n.Y(), p.Y()-x.Y(), dv.Y(),\n                       n.Z(), p.Z()-x.Z(), dv.Z())/det;\n        \n        mu     = Det3 (n.X(), du.X(), p.X()-x.X(),\n                       n.Y(), du.Y(), p.Y()-x.Y(),\n                       n.Z(), du.Z(), p.Z()-x.Z())/det;\n        \n        u += lambda;\n        v += mu;\n        \n        xold = x;\n        occface->D1(u,v,x,du,dv);\n        \n        if (xold.SquareDistance(x) < sqr(PROJECTION_TOLERANCE))\n          {\n            ap = Point<3> (x.X(), x.Y(), x.Z());\n            gi.u = u;\n            gi.v = v;\n            return;\n          }\n      }\n    while (count < 20);\n#endif\n\n    // Newton did not converge, use OCC projection\n\n    \n    //   static int cnt = 0;\n    //  if (cnt++ % 1000 == 0) cout << \"********************************************** OCCSurfce :: Project, cnt = \" << cnt << endl;\n  \n    gp_Pnt pnt = p;  // (p(0), p(1), p(2));\n\n    //(*testout) << \"pnt = \" << pnt.X() << \", \" << pnt.Y() << \", \" << pnt.Z() << endl;\n\n\n    /*\n    GeomAPI_ProjectPointOnSurf proj(pnt, occface, umin, umax, vmin, vmax);\n\n    if (!proj.NbPoints())\n      {\n\tcout << \"Project Point on Surface FAIL\" << endl;\n\tthrow UVBoundsException();\n      }\n    */\n\n    \n\n\n\n    /*\n      cout << \"NP = \" << proj.NbPoints() << endl;\n\n      for (int i = 1; i <= proj.NbPoints(); i++)\n      {\n      gp_Pnt pnt2 = proj.Point(i);\n      Point<3> p2 = Point<3> (pnt2.X(), pnt2.Y(), pnt2.Z());\n      cout << i << \". p = \" << p2 << \", dist = \" << (p2-p).Length() << endl;\n      }\n    */\n\n    /*\n    pnt = proj.NearestPoint();\n    proj.LowerDistanceParameters (gi.u, gi.v);\n    */\n\n    // double u,v;\n    // JS : shouldn't we move these 2 lines to the constructor ?\n    // tanal.Start();\n    Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface );\n    // ShapeAnalysis_Surface su( occface );    \n    // tanal.Stop();\n    ttol.Start();\n    auto toltool =  BRep_Tool::Tolerance( topods_face );\n    ttol.Stop();\n    // gp_Pnt2d suval = su->ValueOfUV ( pnt, toltool);\n    t2.Start();\n    gp_Pnt2d suval = su->NextValueOfUV (gp_Pnt2d(u,v), pnt, toltool);\n    t2.Stop();\n    suval.Coord( u, v);\n    pnt = occface->Value( u, v );\n    \n    //(*testout) << \"pnt(proj) = \" << pnt.X() << \", \" << pnt.Y() << \", \" << pnt.Z() << endl;\n    gi.u = u;\n    gi.v = v;\n    gi.trignum = 1;\n\n    ap = occ2ng(pnt); // Point<3> (pnt.X(), pnt.Y(), pnt.Z());\n  } \n\n\n  Meshing2OCCSurfaces :: Meshing2OCCSurfaces (const NetgenGeometry& geo,\n                                              const TopoDS_Shape & asurf,\n\t\t\t\t\t      const Box<3> & abb, int aprojecttype,\n                                              const MeshingParameters & mparam)\n    : Meshing2(geo, mparam, Box<3>(abb.PMin(), abb.PMax())),\n      surface(TopoDS::Face(asurf), aprojecttype)\n  {\n    ;\n  }\n\n\n  void Meshing2OCCSurfaces :: DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n\t\t\t\t\t\t    const PointGeomInfo * geominfo1,\n\t\t\t\t\t\t    const PointGeomInfo * geominfo2)\n  {\n    ((OCCSurface&)surface).DefineTangentialPlane (p1, *geominfo1, p2, *geominfo2);\n  }\n \n  void Meshing2OCCSurfaces :: TransformToPlain (const Point<3>& locpoint, \n\t\t\t\t\t\tconst MultiPointGeomInfo & geominfo,\n\t\t\t\t\t\tPoint<2> & planepoint, \n\t\t\t\t\t\tdouble h, int & zone)\n  {\n    surface.ToPlane (locpoint, geominfo.GetPGI(1), planepoint, h, zone);\n  }\n\n  int Meshing2OCCSurfaces :: TransformFromPlain (const Point<2> & planepoint,\n\t\t\t\t\t\t Point<3> & locpoint,\n\t\t\t\t\t\t PointGeomInfo & gi,\n\t\t\t\t\t\t double h)\n  {\n    surface.FromPlane (planepoint, locpoint, gi, h);\n    return 0;\n  }\n\n\n\n  double Meshing2OCCSurfaces :: CalcLocalH (const Point<3> & p, double gh) const\n  {\n    return gh;\n  }\n\n  /*\n    inline double Det3 (double a00, double a01, double a02,\n    double a10, double a11, double a12,\n    double a20, double a21, double a22)\n    {\n    return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00;\n    }\n\n    bool ProjectToSurface (gp_Pnt & p, Handle(Geom_Surface) surface, double& u, double& v)\n    {\n    gp_Pnt x = surface->Value (u,v);\n\n    if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return true;\n\n    gp_Vec du, dv;\n\n    surface->D1(u,v,x,du,dv);\n\n    int count = 0;\n\n    gp_Pnt xold;\n    gp_Vec n;\n    double det, lambda, mu;\n\n    do {\n    count++;\n\n    n = du^dv;\n\n    det = Det3 (n.X(), du.X(), dv.X(),\n    n.Y(), du.Y(), dv.Y(),\n    n.Z(), du.Z(), dv.Z());\n\n    if (det < 1e-15) return false; \n\n    lambda = Det3 (n.X(), p.X()-x.X(), dv.X(),\n    n.Y(), p.Y()-x.Y(), dv.Y(),\n    n.Z(), p.Z()-x.Z(), dv.Z())/det;\n\n    mu     = Det3 (n.X(), du.X(), p.X()-x.X(),\n    n.Y(), du.Y(), p.Y()-x.Y(),\n    n.Z(), du.Z(), p.Z()-x.Z())/det;\n  \n    u += lambda;\n    v += mu;\n\n    xold = x;\n    surface->D1(u,v,x,du,dv);\n\n    } while (xold.SquareDistance(x) > sqr(PROJECTION_TOLERANCE) || count > 50);\n\n    if (count > 50) return false;\n\n    p = x;\n\n    return true;\n    }\n  */\n}\n\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/occmeshsurf.hpp",
    "content": "#ifdef OCCGEOMETRY\n\n#ifndef FILE_OCCMESHSURF\n#define FILE_OCCMESHSURF\n\n#include \"occgeom.hpp\"\n#include \"mydefs.hpp\"\n#include <BRep_Tool.hxx>\n#include <TopoDS_Face.hxx>\n#include <Geom_Surface.hxx>\n#include <ShapeAnalysis.hxx>\n#include <ShapeAnalysis_Surface.hxx>\n#include <GeomLProp_SLProps.hxx>\n\n\n#define PARAMETERSPACE -1\n#define PLANESPACE     1\n\nnamespace netgen\n{\nclass OCCGeometry;\n\nclass SingularMatrixException\n{};\n\nclass UVBoundsException\n{};\n\nclass OCCSurface\n{\npublic:\n  TopoDS_Face topods_face;\n  Handle(Geom_Surface) occface;\n  TopAbs_Orientation orient;\n  int projecttype;\n  ShapeAnalysis_Surface su;\n  Standard_Real toltool;\nprotected:\n  Point<3> p1;\n  Point<3> p2;\n\n  /// in plane, directed p1->p2\n  Vec<3> ex;\n  /// in plane\n  Vec<3> ey;\n  /// outer normal direction\n  Vec<3> ez;\n\n  /// normal vector in p2\n  Vec<3> n2;\n\n  /// average normal vector\n  Vec<3> nmid;\n\n  // for transformation to parameter space\n  Point<2> psp1;\n  Point<2> psp2;\n  Vec<2> psex;\n  Vec<2> psey;\n  Mat<2,2> Amat, Amatinv;\n\n  // UV Bounds\n  double umin, umax, vmin, vmax;\n\npublic:\n  OCCSurface (const TopoDS_Face & aface, int aprojecttype)\n    : topods_face(aface),\n      occface(BRep_Tool::Surface(topods_face)),\n      su( occface ),\n      toltool(BRep_Tool::Tolerance(topods_face))\n      \n  {\n    static Timer t(\"occurface ctor\"); RegionTimer r(t);\n    topods_face = aface;\n    // occface = BRep_Tool::Surface(topods_face);\n    orient = topods_face.Orientation();\n    projecttype = aprojecttype;\n    ShapeAnalysis::GetFaceUVBounds (topods_face, umin, umax, vmin, vmax);\n    umin -= fabs(umax-umin)/100.0;\n    vmin -= fabs(vmax-vmin)/100.0;\n    umax += fabs(umax-umin)/100.0;\n    vmax += fabs(vmax-vmin)/100.0;\n    // projecttype = PLANESPACE;\n\n    // su = ShapeAnalysis_Surface( occface );        \n    /*\n    TopExp_Explorer exp1;\n    exp1.Init (topods_face, TopAbs_WIRE);\n    orient = TopAbs::Compose (orient, exp1.Current().Orientation());\n    */\n  };\n  \n  ~OCCSurface()\n  {};\n\n  void Project (Point<3> & p, PointGeomInfo & gi);\n\n  void GetNormalVector (const Point<3> & p,\n\t\t\tconst PointGeomInfo & geominfo,\n\t\t\tVec<3> & n) const;\n\n  /**\n    Defines tangential plane in ap1.\n    The local x-coordinate axis point to the direction of ap2 */\n  void DefineTangentialPlane (const Point<3> & ap1, \n\t\t\t      const PointGeomInfo & geominfo1,\n\t\t\t      const Point<3> & ap2,\n\t\t\t      const PointGeomInfo & geominfo2);\n\n\n  /// Transforms 3d point p3d to local coordinates pplane\n  void ToPlane (const Point<3> & p3d, const PointGeomInfo & geominfo,\n\t\tPoint<2> & pplane, double h, int & zone) const;\n  \n  /// Transforms point pplane in local coordinates to 3d point\n  void FromPlane (const Point<2> & pplane, \n\t\t  Point<3> & p3d,\n\t\t  PointGeomInfo & gi,\n\t\t  double h);\n};\n\n\n\n///\nclass Meshing2OCCSurfaces : public Meshing2\n{\n  ///\n  OCCSurface surface;\n \n\npublic:\n  ///\n  Meshing2OCCSurfaces (const NetgenGeometry& geo,\n                       const TopoDS_Shape & asurf, const Box<3> & aboundingbox,\n                       int aprojecttype, const MeshingParameters & mparam);\n\n  ///\n  int GetProjectionType ()\n  { return surface.projecttype; }\n\nprotected:\n  ///\n  void DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n                             const PointGeomInfo * geominfo1,\n                             const PointGeomInfo * geominfo2) override;\n  ///\n  void TransformToPlain (const Point<3> & locpoint, \n                         const MultiPointGeomInfo & geominfo,\n                         Point<2> & plainpoint, \n                         double h, int & zone) override;\n  ///\n\n  int TransformFromPlain (const Point<2> & plainpoint,\n                          Point<3> & locpoint,\n                          PointGeomInfo & gi,\n                          double h) override;\n  ///\n  double CalcLocalH (const Point<3> & p, double gh) const override;\n  \n};\n\nclass OCCGeometry;\n\n} // namespace netgen\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libsrc/occ/occpkg.cpp",
    "content": "#ifdef OCCGEOMETRY\r\n\r\n#include <mystdlib.h>\r\n#include <myadt.hpp>\r\n#include <linalg.hpp>\r\n#include <csg.hpp>\r\n#include <occgeom.hpp>\r\n\r\n\r\n#include <inctcl.hpp>\r\n#include <visual.hpp>\r\n\r\n#include <meshing.hpp>\r\n#include \"../meshing/bcfunctions.hpp\"\r\n\r\n#include \"vsocc.hpp\"\r\n\r\n#include <TopoDS_Edge.hxx>\r\n#include <IGESControl_Writer.hxx>\r\n\r\n// __declspec(dllimport) void AutoColourBcProps(Mesh & mesh, const char *bccolourfile);\r\n// __declspec(dllimport) void GetFaceColours(Mesh & mesh, NgArray<Vec3d> & face_colours);\r\n// __declspec(dllimport) bool ColourMatch(Vec3d col1, Vec3d col2, double eps = 2.5e-05);\r\n\r\nextern \"C\" int Ng_occ_Init (Tcl_Interp * interp);\r\n\r\n\r\n\r\nnamespace netgen\r\n{\r\n  extern DLL_HEADER shared_ptr<NetgenGeometry> ng_geometry;\r\n  extern DLL_HEADER shared_ptr<Mesh> mesh;\r\n  extern DLL_HEADER MeshingParameters mparam;\r\n  extern DLL_HEADER OCCParameters occparam;\r\n \r\n  char * err_needsoccgeometry = (char*) \"This operation needs an OCC geometry\";\r\n  extern char * err_needsmesh;\r\n  extern char * err_jobrunning;\r\n\r\n\r\n\r\n                          \r\n  class OCCGeometryRegister : public GeometryRegister\r\n  {\r\n  public:\r\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const;\r\n    virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;\r\n\r\n    virtual void SetParameters (Tcl_Interp * interp) \r\n    {\r\n      // occparam.resthminedgelen = \r\n      //   atof (Tcl_GetVar (interp, \"::stloptions.resthminedgelen\", 0));\r\n      //     occparam.resthminedgelenenable = \r\n      //   atoi (Tcl_GetVar (interp, \"::stloptions.resthminedgelenenable\", 0));\r\n      if(auto geo = dynamic_pointer_cast<OCCGeometry>(ng_geometry); geo)\r\n        geo->SetOCCParameters(occparam);\r\n    }\r\n  };\r\n\r\n\r\n\r\n\r\n  int Ng_SetOCCVisParameters  (ClientData clientData,\r\n\t\t\t       Tcl_Interp * interp,\r\n\t\t\t       int argc, tcl_const char *argv[])\r\n  {\r\n#ifdef OCCGEOMETRY\r\n    int showvolume;\r\n    OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry.get());\r\n\r\n    showvolume = atoi (Tcl_GetVar (interp, \"::occoptions.showvolumenr\", 0));\r\n\r\n    if (occgeometry)\r\n      if (showvolume != vispar.occshowvolumenr)\r\n\t{\r\n\t  if (showvolume < 0 || showvolume > occgeometry->NrSolids())\r\n\t    {\r\n\t      char buf[20];\r\n\t      snprintf (buf, size(buf),  \"%5i\", vispar.occshowvolumenr);\r\n\t      Tcl_SetVar (interp, \"::occoptions.showvolumenr\", buf, 0);\r\n\t    }\r\n\t  else\r\n\t    {\r\n\t      vispar.occshowvolumenr = showvolume;\r\n\t      if (occgeometry)\r\n\t\toccgeometry -> changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t    }\r\n\t}\r\n    \r\n    int temp;\r\n\r\n    temp = atoi (Tcl_GetVar (interp, \"::occoptions.visproblemfaces\", 0));\r\n\r\n    if ((bool) temp != vispar.occvisproblemfaces)\r\n      {\r\n\tvispar.occvisproblemfaces = temp;\r\n\tif (occgeometry)\r\n\t  occgeometry -> changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n      }\r\n\r\n    vispar.occshowsurfaces = atoi (Tcl_GetVar (interp, \"::occoptions.showsurfaces\", 0));\r\n    vispar.occshowedges = atoi (Tcl_GetVar (interp, \"::occoptions.showedges\", 0));\r\n    vispar.occzoomtohighlightedentity = atoi (Tcl_GetVar (interp, \"::occoptions.zoomtohighlightedentity\", 0));\r\n    vispar.occdeflection = pow(10.0,-1-atof (Tcl_GetVar (interp, \"::occoptions.deflection\", 0)));\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n#ifdef ACIS\r\n    vispar.ACISshowfaces = atoi (Tcl_GetVar (interp, \"::occoptions.showsurfaces\", 0));\r\n    vispar.ACISshowedges = atoi (Tcl_GetVar (interp, \"::occoptions.showedges\", 0));\r\n    vispar.ACISshowsolidnr = atoi (Tcl_GetVar (interp, \"::occoptions.showsolidnr\", 0));\r\n    vispar.ACISshowsolidnr2 = atoi (Tcl_GetVar (interp, \"::occoptions.showsolidnr2\", 0));\r\n\r\n#endif\r\n\r\n\r\n\r\n    return TCL_OK;\r\n  }  \r\n\r\n\r\n\r\n\r\n  int Ng_GetOCCData (ClientData clientData,\r\n\t\t     Tcl_Interp * interp,\r\n\t\t     int argc, tcl_const char *argv[])\r\n  {\r\n#ifdef OCCGEOMETRY\r\n    OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry.get());\r\n\r\n    // static char buf[1000];\r\n    // buf[0] = 0;\r\n    stringstream str;\r\n\r\n    if (argc >= 2)\r\n      {\r\n\tif (strcmp (argv[1], \"getentities\") == 0)\r\n\t  {\r\n\t    if (occgeometry)\r\n\t      {\r\n\t\toccgeometry->GetTopologyTree(str);\r\n\t      }\r\n\t  }\r\n      }\r\n\r\n    Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\r\n\r\n#endif\r\n    return TCL_OK;\r\n  }\r\n\r\n  \r\n\r\n  int Ng_OCCCommand (ClientData clientData,\r\n\t\t     Tcl_Interp * interp,\r\n\t\t     int argc, tcl_const char *argv[])\r\n  {\r\n#ifdef OCCGEOMETRY\r\n    OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry.get());\r\n\r\n    stringstream str;\r\n    if (argc >= 2)\r\n      {\r\n\tif (strcmp (argv[1], \"isoccgeometryloaded\") == 0)\r\n\t  {\r\n\t    if (occgeometry)\r\n\t      str << \"1 \" << flush;\r\n\t    else str << \"0 \" << flush;\r\n\r\n\t    Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\r\n\t  }\r\n\tif (occgeometry)\r\n\t  {\r\n\t    if (strcmp (argv[1], \"buildvisualizationmesh\") == 0)\r\n\t      {\r\n\t\toccgeometry->BuildVisualizationMesh(vispar.occdeflection);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"mesherror\") == 0)\r\n\t      {\r\n\t\tif (occgeometry->ErrorInSurfaceMeshing())\r\n\t\t  str << 1;\r\n\t\telse\r\n\t\t  str << 0;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"sewfaces\") == 0)\r\n\t      {\r\n\t\tcout << \"Before operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->SewFaces();\r\n\t\toccgeometry->BuildFMap();\r\n\t\tcout << endl << \"After operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->BuildVisualizationMesh(vispar.occdeflection);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"makesolid\") == 0)\r\n\t      {\r\n\t\tcout << \"Before operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->MakeSolid();\r\n\t\toccgeometry->BuildFMap();\r\n\t\tcout << endl << \"After operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->BuildVisualizationMesh(vispar.occdeflection);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"upgradetopology\") == 0)\r\n\t      {\r\n\t\tcout << \"Before operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->SewFaces();\r\n\t\toccgeometry->MakeSolid();\r\n\t\toccgeometry->BuildFMap();\r\n\t\tcout << endl << \"After operation:\" << endl;\r\n\t\toccgeometry->PrintNrShapes();\r\n\t\toccgeometry->BuildVisualizationMesh(vispar.occdeflection);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"shapehealing\") == 0)\r\n\t      {\r\n\t\toccgeometry->tolerance =\r\n\t\t  atof (Tcl_GetVar (interp, \"::occoptions.tolerance\", 0));\r\n\t\toccgeometry->fixsmalledges =\r\n\t\t  atoi (Tcl_GetVar (interp, \"::occoptions.fixsmalledges\", 0));\r\n\t\toccgeometry->fixspotstripfaces =\r\n\t\t  atoi (Tcl_GetVar (interp, \"::occoptions.fixspotstripfaces\", 0));\r\n\t\toccgeometry->sewfaces =\r\n\t\t  atoi (Tcl_GetVar (interp, \"::occoptions.sewfaces\", 0));\r\n\t\toccgeometry->makesolids =\r\n\t\t  atoi (Tcl_GetVar (interp, \"::occoptions.makesolids\", 0));\r\n\t\toccgeometry->splitpartitions =\r\n\t\t  atoi (Tcl_GetVar (interp, \"::occoptions.splitpartitions\", 0));\r\n\r\n\t\t//\t      cout << \"Before operation:\" << endl;\r\n\t\t//\t      occgeometry->PrintNrShapes();\r\n\t\toccgeometry->HealGeometry();\r\n\t\toccgeometry->BuildFMap();\r\n\t\t//\t      cout << endl << \"After operation:\" << endl;\r\n\t\t//\t      occgeometry->PrintNrShapes();\r\n\t\toccgeometry->BuildVisualizationMesh(vispar.occdeflection);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t      }\r\n\r\n\r\n\t    if (strcmp (argv[1], \"highlightentity\") == 0)\r\n\t      {\r\n\t\tif (strcmp (argv[2], \"Face\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    occgeometry->fvispar[nr-1].Highlight();\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Shell\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Highlight();\r\n\t\t      }\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Solid\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->somap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Highlight();\r\n\t\t      }\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\t\t/*\r\n\t\t  if (strcmp (argv[2], \"CompSolid\") == 0)\r\n\t\t  {\r\n\t\t  int nr = atoi (argv[3]);\r\n\t\t  occgeometry->LowLightAll();\r\n\r\n\t\t  TopExp_Explorer exp;\r\n\t\t  for (exp.Init (occgeometry->cmap(nr), TopAbs_FACE);\r\n\t\t  exp.More(); exp.Next())\r\n\t\t  {\r\n\t\t  int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t  occgeometry->fvispar[i-1].Highlight();\r\n\t\t  }\r\n\t\t  occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\t\t*/\r\n\r\n\t\tif (strcmp (argv[2], \"Edge\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    occgeometry->evispar[nr-1].Highlight();\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Wire\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current()));\r\n\t\t\toccgeometry->evispar[i-1].Highlight();\r\n\t\t      }\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\r\n\t\tif (strcmp (argv[2], \"Vertex\") == 0)\r\n\t\t  {\r\n\t\t    int nr = atoi (argv[3]);\r\n\t\t    occgeometry->LowLightAll();\r\n\r\n\t\t    occgeometry->vvispar[nr-1].Highlight();\r\n\t\t    if (vispar.occzoomtohighlightedentity)\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\r\n\t\t    else\r\n\t\t      occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t  }\r\n\r\n\t      }\r\n\r\n\r\n\r\n\t    if (strcmp (argv[1], \"show\") == 0)\r\n\t      {\r\n\t\tint nr = atoi (argv[3]);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\r\n\t\tif (strcmp (argv[2], \"Face\") == 0)\r\n\t\t  {\r\n\t\t    occgeometry->fvispar[nr-1].Show();\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Shell\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Show();\r\n\t\t      }\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Solid\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->somap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Show();\r\n\t\t      }\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Edge\") == 0)\r\n\t\t  {\r\n\t\t    occgeometry->evispar[nr-1].Show();\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Wire\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current()));\r\n\t\t\toccgeometry->evispar[i-1].Show();\r\n\t\t      }\r\n\t\t  }\r\n\t      }\r\n\r\n\r\n\t    if (strcmp (argv[1], \"hide\") == 0)\r\n\t      {\r\n\t\tint nr = atoi (argv[3]);\r\n\t\toccgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\r\n\t\tif (strcmp (argv[2], \"Face\") == 0)\r\n\t\t  {\r\n\t\t    occgeometry->fvispar[nr-1].Hide();\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Shell\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Hide();\r\n\t\t      }\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Solid\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->somap(nr), TopAbs_FACE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current()));\r\n\t\t\toccgeometry->fvispar[i-1].Hide();\r\n\t\t      }\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Edge\") == 0)\r\n\t\t  {\r\n\t\t    occgeometry->evispar[nr-1].Hide();\r\n\t\t  }\r\n\t\tif (strcmp (argv[2], \"Wire\") == 0)\r\n\t\t  {\r\n\t\t    TopExp_Explorer exp;\r\n\t\t    for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE);\r\n\t\t\t exp.More(); exp.Next())\r\n\t\t      {\r\n\t\t\tint i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current()));\r\n\t\t\toccgeometry->evispar[i-1].Hide();\r\n\t\t      }\r\n\t\t  }\r\n\t      }\r\n\r\n\r\n\r\n\t    if (strcmp (argv[1], \"findsmallentities\") == 0)\r\n\t      {\r\n\t\tstringstream str(\"\");\r\n\t\toccgeometry->CheckIrregularEntities(str);\r\n\t\tTcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\r\n\t      }\r\n\t    if (strcmp (argv[1], \"getunmeshedfaceinfo\") == 0)\r\n\t      {\r\n\t\toccgeometry->GetUnmeshedFaceInfo(str);\r\n\t\tTcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\r\n\t      }\r\n\t    if (strcmp (argv[1], \"getnotdrawablefaces\") == 0)\r\n\t      {\r\n\t\toccgeometry->GetNotDrawableFaces(str);\r\n\t\tTcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\r\n\t      }\r\n\t    if (strcmp (argv[1], \"redrawstatus\") == 0)\r\n\t      {\r\n\t\tint i = atoi (argv[2]);\r\n\t\toccgeometry->changed = i;\r\n\t      }\r\n\t    if (strcmp (argv[1], \"swaporientation\") == 0)\r\n\t      {\r\n\t\tIGESControl_Writer writer(\"millimeters\", 1);\r\n\t\twriter.AddShape (occgeometry->shape);\r\n\t\twriter.Write (\"1.igs\");\r\n\t\t/*\r\n\t\t  int nr = atoi (argv[3]);\r\n\r\n\t\t  //\t      const_cast<TopoDS_Shape&> (occgeometry->fmap(nr)).Reverse();\r\n\r\n\t\t  Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;\r\n\t\t  rebuild->Apply(occgeometry->shape);\r\n\r\n\t\t  TopoDS_Shape sh;\r\n\r\n\t\t  //\t      if (strcmp (argv[2], \"CompSolid\") == 0) sh = occgeometry->cmap(nr);\r\n\t\t  if (strcmp (argv[2], \"Solid\") == 0) sh = occgeometry->somap(nr);\r\n\t\t  if (strcmp (argv[2], \"Shell\") == 0) sh = occgeometry->shmap(nr);\r\n\t\t  if (strcmp (argv[2], \"Face\") == 0) sh = occgeometry->fmap(nr);\r\n\t\t  if (strcmp (argv[2], \"Wire\") == 0) sh = occgeometry->wmap(nr);\r\n\t\t  if (strcmp (argv[2], \"Edge\") == 0) sh = occgeometry->emap(nr);\r\n\r\n\t\t  rebuild->Replace(sh, sh.Reversed(), Standard_False);\r\n\r\n\t\t  TopoDS_Shape newshape = rebuild->Apply(occgeometry->shape, TopAbs_SHELL, 1);\r\n\t\t  occgeometry->shape = newshape;\r\n\r\n\t\t  occgeometry->BuildFMap();\r\n\t\t  occgeometry->BuildVisualizationMesh();\r\n\t\t  occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t\t*/\r\n\t      }\r\n\t    if (strcmp (argv[1], \"marksingular\") == 0)\r\n\t      {\r\n\t\tint nr = atoi (argv[3]);\r\n\t\tcout << \"marking \" << argv[2] << \" \" << nr << endl;\r\n\t\tchar buf[2]; buf[0] = '0'; buf[1] = 0;\r\n\t\tbool sing = false;\r\n\t\tif (strcmp (argv[2], \"Face\") == 0)\r\n\t\t  sing = occgeometry->fsingular[nr-1] = !occgeometry->fsingular[nr-1];\r\n\t\tif (strcmp (argv[2], \"Edge\") == 0)\r\n\t\t  sing = occgeometry->esingular[nr-1] = !occgeometry->esingular[nr-1];\r\n\t\tif (strcmp (argv[2], \"Vertex\") == 0)\r\n\t\t  sing = occgeometry->vsingular[nr-1] = !occgeometry->vsingular[nr-1];\r\n\r\n\t\tif (sing) buf[0] = '1';\r\n\r\n                Tcl_SetVar (interp, \"::ismarkedsingular\", buf, 0);\r\n\r\n\t\tstringstream str;\r\n\t\toccgeometry->GetTopologyTree (str);\r\n\r\n                auto txt = str.str();\r\n\t\tchar* cstr = (char*) txt.c_str();\r\n\r\n\t\t(*testout) << cstr << endl;\r\n\r\n\t\tchar helpstr[1000];\r\n\r\n\t\twhile (strchr (cstr, '}'))\r\n\t\t  {\r\n\t\t    strncpy (helpstr, cstr+2, strlen(strchr(cstr+2, '}')));\r\n\t\t    (*testout) << \"***\" << cstr << \"***\" << endl;\r\n\t\t    cstr = strchr (cstr, '}');\r\n\t\t  } \r\n\t      }\r\n\t  }\r\n      }\r\n\r\n#endif\r\n    return TCL_OK;\r\n  }\r\n\r\n\r\n\r\n#ifdef OCCGEOMETRY\r\n  /*\r\n  void OCCConstructGeometry (OCCGeometry & geom);\r\n\r\n  int Ng_OCCConstruction (ClientData clientData,\r\n\t\t\t  Tcl_Interp * interp,\r\n\t\t\t  int argc, tcl_const char *argv[])\r\n  {\r\n    if (occgeometry)\r\n      OCCConstructGeometry (*occgeometry);\r\n    return TCL_OK;\r\n  }\r\n  */\r\n#endif\r\n\r\n\r\n\r\n\r\n  // Philippose - 30/01/2009\r\n  // TCL interface function for the Local Face Mesh size\r\n  // definition functionality\r\n  int Ng_SurfaceMeshSize (ClientData clientData,\r\n\t\t                    Tcl_Interp * interp,\r\n\t\t                    int argc, tcl_const char *argv[])\r\n  {\r\n#ifdef OCCGEOMETRY\r\n\r\n    static char buf[100];\r\n\r\n    if (argc < 2)\r\n    {\r\n\t   Tcl_SetResult (interp, (char *)\"Ng_SurfaceMeshSize needs arguments\", TCL_STATIC);\r\n\t   return TCL_ERROR;\r\n    }\r\n\r\n    OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry.get());\r\n    if (!occgeometry)\r\n    {\r\n      Tcl_SetResult (interp, (char *)\"Ng_SurfaceMeshSize currently supports only OCC (STEP/IGES) Files\", TCL_STATIC);\r\n\t   return TCL_ERROR;\r\n    }\r\n\r\n    // Update the face mesh sizes to reflect the global maximum mesh size\r\n    for(int i = 1; i <= occgeometry->NrFaces(); i++)\r\n    {\r\n           if(!occgeometry->GetFaceMaxhModified(i))\r\n           {\r\n             occgeometry->SetFaceMaxH(i, mparam.maxh, mparam);\r\n           }   \r\n    }\r\n\r\n    if (strcmp (argv[1], \"setsurfms\") == 0)\r\n    {\r\n\t   int facenr = atoi (argv[2]);\r\n\t   double surfms = atof (argv[3]);\r\n\t   if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces())\r\n\t     occgeometry->SetFaceMaxH(facenr, surfms, mparam);\r\n\r\n    }\r\n\r\n    if (strcmp (argv[1], \"setall\") == 0)\r\n    {\r\n\t   double surfms = atof (argv[2]);\r\n\t   if (occgeometry)\r\n\t   {\r\n\t     int nrFaces = occgeometry->NrFaces();\r\n\t     for (int i = 1; i <= nrFaces; i++)\r\n               occgeometry->SetFaceMaxH(i, surfms, mparam);\r\n\t   }\r\n    }\r\n\r\n    if (strcmp (argv[1], \"getsurfms\") == 0)\r\n    {\r\n\t   int facenr = atoi (argv[2]);\r\n\t   if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces())\r\n\t   {\r\n\t     snprintf (buf, size(buf),  \"%5.2f\", occgeometry->GetFaceMaxH(facenr));\r\n\t   }\r\n\t   else\r\n\t   {\r\n\t     snprintf (buf, size(buf),  \"%5.2f\", mparam.maxh);\r\n\t   }\r\n\t   Tcl_SetResult (interp, buf, TCL_STATIC);\r\n    }\r\n\r\n    if (strcmp (argv[1], \"getactive\") == 0)\r\n    {\r\n\t   snprintf (buf, size(buf),  \"%d\", occgeometry->SelectedFace());\r\n\t   Tcl_SetResult (interp, buf, TCL_STATIC);\r\n    }\r\n\r\n    if (strcmp (argv[1], \"setactive\") == 0)\r\n    {\r\n\t   int facenr = atoi (argv[2]);\r\n\t   if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces())\r\n\t   {\r\n\t     occgeometry->SetSelectedFace (facenr);\r\n\r\n        occgeometry->LowLightAll();\r\n        occgeometry->fvispar[facenr-1].Highlight();\r\n        occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\r\n\t   }\r\n    }\r\n\r\n    if (strcmp (argv[1], \"getnfd\") == 0)\r\n    {\r\n\t   if (occgeometry)\r\n\t     snprintf (buf, size(buf),  \"%d\", occgeometry->NrFaces());\r\n\t   else\r\n\t     snprintf (buf, size(buf),  \"0\");\r\n\t   Tcl_SetResult (interp, buf, TCL_STATIC);\r\n    }\r\n    return TCL_OK;\r\n#else // No OCCGEOMETRY \r\n\r\n    Tcl_SetResult (interp, (char *)\"Ng_SurfaceMeshSize currently supports only OCC (STEP/IGES) Files\", TCL_STATIC);\r\n    return TCL_ERROR;\r\n    \r\n#endif // OCCGEOMETRY\r\n  }\r\n\r\n\r\n\r\n  // Philippose - 25/07/2010\r\n  // TCL interface function for extracting and eventually \r\n  // setting or editing the current colours present in the mesh\r\n  int Ng_CurrentFaceColours (ClientData clientData,\r\n                             Tcl_Interp * interp,\r\n                             int argc, tcl_const char *argv[])\r\n  {\r\n     if(argc < 1)\r\n     {\r\n        Tcl_SetResult (interp, (char *)\"Ng_GetCurrentFaceColours needs arguments\", TCL_STATIC);\r\n        return TCL_ERROR;\r\n     }\r\n\r\n     if(!mesh)\r\n     {\r\n        Tcl_SetResult (interp, (char *)\"Ng_GetCurrentFaceColours: Valid netgen mesh required...please mesh the Geometry first\", TCL_STATIC);\r\n\t     return TCL_ERROR;\r\n     }\r\n\r\n     if(strcmp(argv[1], \"getcolours\") == 0)\r\n     {\r\n        stringstream outVar;\r\n        NgArray<Vec<4>> face_colours;\r\n        GetFaceColours(*mesh, face_colours);\r\n\r\n        for(int i = 0; i < face_colours.Size();i++)\r\n        {\r\n           outVar << \"{ \" << face_colours[i][0]\r\n                  << \" \"  << face_colours[i][1]\r\n                  << \" \"  << face_colours[i][2]\r\n                  << \" } \";\r\n        }\r\n\r\n        tcl_const char * valuevar = argv[2];\r\n        Tcl_SetVar  (interp, valuevar, (char*)outVar.str().c_str(), 0);\r\n     }\r\n\r\n     if(strcmp(argv[1], \"showalso\") == 0)\r\n     {\r\n        NgArray<Vec<4>> face_colours;\r\n        GetFaceColours(*mesh,face_colours);\r\n\r\n        int colourind = atoi (argv[2]);\r\n\r\n        for(int i = 1; i <= mesh->GetNFD(); i++)\r\n        {\r\n          Array<SurfaceElementIndex> surfElems;\r\n           mesh->GetSurfaceElementsOfFace(i,surfElems);\r\n\r\n           if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour()))\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(1);\r\n              }\r\n           }\r\n        }\r\n\r\n        mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     if(strcmp(argv[1], \"hidealso\") == 0)\r\n     {\r\n       NgArray<Vec<4>> face_colours;\r\n        GetFaceColours(*mesh,face_colours);\r\n\r\n        int colourind = atoi (argv[2]);\r\n\r\n        for(int i = 1; i <= mesh->GetNFD(); i++)\r\n        {\r\n           Array<SurfaceElementIndex> surfElems;\r\n           mesh->GetSurfaceElementsOfFace(i,surfElems);\r\n\r\n           if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour()))\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(0);\r\n              }\r\n           }\r\n        }\r\n\r\n        mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     if(strcmp(argv[1], \"showonly\") == 0)\r\n     {\r\n        NgArray<Vec<4>> face_colours;\r\n        GetFaceColours(*mesh,face_colours);\r\n\r\n        int colourind = atoi (argv[2]);\r\n\r\n        for(int i = 1; i <= mesh->GetNFD(); i++)\r\n        {\r\n           Array<SurfaceElementIndex> surfElems;\r\n           mesh->GetSurfaceElementsOfFace(i,surfElems);\r\n\r\n           if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour()))\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(1);\r\n              }\r\n           }\r\n           else\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(0);\r\n              }\r\n           }\r\n        }\r\n\r\n        mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     if(strcmp(argv[1], \"hideonly\") == 0)\r\n     {\r\n       NgArray<Vec<4>> face_colours;\r\n        GetFaceColours(*mesh,face_colours);\r\n\r\n        int colourind = atoi (argv[2]);\r\n\r\n        for(int i = 1; i <= mesh->GetNFD(); i++)\r\n        {\r\n           Array<SurfaceElementIndex> surfElems;\r\n           mesh->GetSurfaceElementsOfFace(i,surfElems);\r\n\r\n           if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour()))\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(0);\r\n              }\r\n           }\r\n           else\r\n           {\r\n              for(int j = 0; j < surfElems.Size(); j++)\r\n              {\r\n                 mesh->SurfaceElement(surfElems[j]).Visible(1);\r\n              }\r\n           }\r\n        }\r\n\r\n        mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     if(strcmp(argv[1], \"showall\") == 0)\r\n     {\r\n       /*\r\n        for(int i = 1; i <= mesh->GetNSE(); i++)\r\n        {\r\n          mesh->SurfaceElement(i).Visible(1);\r\n        }\r\n       */\r\n       for (auto & el : mesh->SurfaceElements())\r\n         el.Visible(1);\r\n       \r\n       mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     if(strcmp(argv[1], \"hideall\") == 0)\r\n     {\r\n       /*\r\n        for(int i = 1; i <= mesh->GetNSE(); i++)\r\n        {\r\n          mesh->SurfaceElement(i).Visible(0);\r\n        }\r\n       */\r\n       for (auto & el : mesh->SurfaceElements())\r\n         el.Visible(0);\r\n       \r\n        mesh->SetNextTimeStamp();\r\n     }\r\n\r\n     return TCL_OK;\r\n  }\r\n\r\n\r\n\r\n\r\n  // Philippose - 10/03/2009\r\n  // TCL interface function for the Automatic Colour-based\r\n  // definition of boundary conditions for OCC Geometry\r\n  int Ng_AutoColourBcProps (ClientData clientData,\r\n\t\t                      Tcl_Interp * interp,\r\n\t\t                      int argc, tcl_const char *argv[])\r\n  {\r\n     if(argc < 1)\r\n     {\r\n        Tcl_SetResult (interp, (char *)\"Ng_AutoColourBcProps needs arguments\", TCL_STATIC);\r\n        return TCL_ERROR;\r\n     }\r\n\r\n     if(!mesh)\r\n     {\r\n        Tcl_SetResult (interp, (char *)\"Ng_AutoColourBcProps: Valid netgen mesh required...please mesh the Geometry first\", TCL_STATIC);\r\n\t     return TCL_ERROR;\r\n     }\r\n\r\n     if(strcmp(argv[1], \"auto\") == 0)\r\n     {\r\n        AutoColourBcProps(*mesh, 0);\r\n     }\r\n\r\n     if(strcmp(argv[1], \"profile\") == 0)\r\n     {\r\n        AutoColourBcProps(*mesh, argv[2]);\r\n     }\r\n\r\n     return TCL_OK;\r\n  }\r\n\r\n\r\n  int Ng_SetOCCParameters  (ClientData clientData,\r\n\t\t\t    Tcl_Interp * interp,\r\n\t\t\t    int argc, tcl_const char *argv[])\r\n  {\r\n    OCCGeometryRegister reg;\r\n    reg.SetParameters (interp);\r\n    /*\r\n    occparam.resthcloseedgefac =\r\n      atof (Tcl_GetVar (interp, \"::stloptions.resthcloseedgefac\", 0));\r\n\r\n    occparam.resthcloseedgeenable =\r\n      atoi (Tcl_GetVar (interp, \"::stloptions.resthcloseedgeenable\", 0));\r\n    */\r\n    return TCL_OK;\r\n  }\r\n\r\n\r\n\r\n\r\n  NetgenGeometry *  OCCGeometryRegister :: Load (const filesystem::path & filename) const\r\n  {\r\n    string ext = ToLower(filename.extension());\r\n\r\n    if (ext == \".iges\" || ext == \".igs\")\r\n      {\r\n\tPrintMessage (1, \"Load IGES geometry file \", filename);\r\n\tOCCGeometry * occgeometry = LoadOCC_IGES (filename);\r\n\treturn occgeometry;\r\n      }\r\n\r\n    else if (ext == \".stp\" || ext == \".step\")\r\n      {\r\n\tPrintMessage (1, \"Load STEP geometry file \", filename);\r\n\tOCCGeometry * occgeometry = LoadOCC_STEP (filename);\r\n\treturn occgeometry;    \r\n      }\r\n    else if (ext == \".brep\")\r\n      {\r\n\tPrintMessage (1, \"Load BREP geometry file \", filename);\r\n\tOCCGeometry * occgeometry = LoadOCC_BREP (filename);\r\n\treturn occgeometry;\r\n      }\r\n    \r\n    return NULL;\r\n  }\r\n\r\n\r\n  static VisualSceneOCCGeometry vsoccgeom;\r\n\r\n  VisualScene * OCCGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const\r\n  {\r\n    OCCGeometry * geometry = dynamic_cast<OCCGeometry*> (ng_geometry.get());\r\n    if (geometry)\r\n      {\r\n\tvsoccgeom.SetGeometry (geometry);\r\n\treturn &vsoccgeom;\r\n      }\r\n    return NULL;\r\n  }\r\n\r\n\r\n\r\n}\r\n\r\n\r\n\r\nusing namespace netgen;\r\n\r\nint Ng_occ_Init (Tcl_Interp * interp)\r\n{\r\n  GeometryRegister().Append (new OCCGeometryRegister);\r\n\r\n\r\n    Tcl_CreateCommand (interp, \"Ng_SetOCCVisParameters\",\r\n\t\t       Ng_SetOCCVisParameters,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n    Tcl_CreateCommand (interp, \"Ng_GetOCCData\",\r\n\t\t       Ng_GetOCCData,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n    /*\r\n#ifdef OCCGEOMETRY\r\n    Tcl_CreateCommand (interp, \"Ng_OCCConstruction\",\r\n\t\t       Ng_OCCConstruction,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n#endif\r\n    */\r\n\r\n    Tcl_CreateCommand (interp, \"Ng_OCCCommand\",\r\n\t\t       Ng_OCCCommand,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n\r\n    Tcl_CreateCommand (interp, \"Ng_SetOCCParameters\", Ng_SetOCCParameters,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n\r\n\r\n    // Philippose - 30/01/2009\r\n    // Register the TCL Interface Command for local face mesh size\r\n    // definition\r\n    Tcl_CreateCommand (interp, \"Ng_SurfaceMeshSize\", Ng_SurfaceMeshSize,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n    Tcl_CreateCommand (interp, \"Ng_AutoColourBcProps\", Ng_AutoColourBcProps,\r\n\t\t       (ClientData)NULL,\r\n\t\t       (Tcl_CmdDeleteProc*) NULL);\r\n\r\n    // Philippose - 25/07/2010\r\n    // Register the TCL Interface Command for handling the face colours \r\n    // present in the mesh\r\n    Tcl_CreateCommand(interp, \"Ng_CurrentFaceColours\", Ng_CurrentFaceColours,\r\n                      (ClientData)NULL,\r\n                      (Tcl_CmdDeleteProc*) NULL);\r\n\r\n\r\n  return TCL_OK;\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "libsrc/occ/python_occ.cpp",
    "content": "#ifdef NG_PYTHON\n#ifdef OCCGEOMETRY\n\n\n#include <memory>\n\n#include <general/ngpython.hpp>\n#include <core/python_ngcore.hpp>\n#include <meshing/python_mesh.hpp>\n#include <meshing.hpp>\n\n#include \"occgeom.hpp\"\n\n#include <BOPAlgo_Builder.hxx>\n#include <BRepLProp_SLProps.hxx>\n#include <Message.hxx>\n#include <Standard_GUID.hxx>\n#include <Standard_Version.hxx>\n#include <TDF_Attribute.hxx>\n#include <XCAFApp_Application.hxx>\n#include <XCAFDoc_DocumentTool.hxx>\n#include <XCAFDoc_MaterialTool.hxx>\n#include <XCAFDoc_ShapeTool.hxx>\n#include <TopoDS_Edge.hxx>\n#include <BRepAdaptor_Curve.hxx>\n#include <GCPnts_TangentialDeflection.hxx>\n\nusing namespace netgen;\n\nnamespace netgen\n{\n  extern std::shared_ptr<NetgenGeometry> ng_geometry;\n  extern std::shared_ptr<Mesh> mesh;\n}\n\nstatic string occparameter_description = R\"delimiter(\nOCC Specific Meshing Parameters\n-------------------------------\n\ncloseedgefac: Optional[float] = 2.\n  Factor for meshing close edges, if None it is disabled.\n\nminedgelen: Optional[float] = 0.001\n  Minimum edge length to be used for dividing edges to mesh points. If\n  None this is disabled.\n\n)delimiter\";\n\nvoid CreateOCCParametersFromKwargs(OCCParameters& occparam, py::dict kwargs)\n{\n  if(kwargs.contains(\"minedgelen\"))\n    {\n      auto val = kwargs.attr(\"pop\")(\"minedgelen\");\n      if(val.is_none())\n        occparam.resthminedgelenenable = false;\n      else\n        {\n          occparam.resthminedgelen = py::cast<double>(val);\n          occparam.resthminedgelenenable = true;\n        }\n    }\n}\n\nextern py::object CastShape(const TopoDS_Shape & s);\n\nDLL_HEADER void ExportNgOCCBasic(py::module &m);\nDLL_HEADER void ExportNgOCCShapes(py::module &m);\n\n\n\nDLL_HEADER void ExportNgOCC(py::module &m) \n{\n  m.attr(\"occ_version\") = OCC_VERSION_COMPLETE;\n\n  // suppress info messages from occ (like statistics on Transfer)\n  Message_Gravity aGravity = Message_Alarm;\n  for (Message_SequenceOfPrinters::Iterator aPrinterIter (Message::DefaultMessenger()->Printers());\n       aPrinterIter.More(); aPrinterIter.Next())\n  {\n    aPrinterIter.Value()->SetTraceLevel (aGravity);\n  }\n\n  ExportNgOCCBasic(m);\n  ExportNgOCCShapes(m);\n\n  static py::exception<Standard_Failure> exc(m, \"OCCException\");\n  py::register_exception_translator([](std::exception_ptr p)\n  {\n    try {\n      if(p) std::rethrow_exception(p);\n    } catch (const Standard_Failure& e) {\n#if (PYBIND11_VERSION_MAJOR == 2 && PYBIND11_VERSION_MINOR < 12)\n      exc((string(e.DynamicType()->Name()) + \": \" + e.GetMessageString()).c_str());\n#else\n      py::set_error(PyExc_RuntimeError, (string(e.DynamicType()->Name()) + \": \" + e.GetMessageString()).c_str());\n#endif\n    }\n  });\n  \n  py::class_<OCCGeometry, shared_ptr<OCCGeometry>, NetgenGeometry> (m, \"OCCGeometry\", R\"raw_string(Use LoadOCCGeometry to load the geometry from a *.step file.)raw_string\")\n    /*\n    .def(py::init<const TopoDS_Shape&>(), py::arg(\"shape\"),\n         \"Create Netgen OCCGeometry from existing TopoDS_Shape\")\n    */\n    .def(py::init([] (const TopoDS_Shape& shape, int occdim, bool copy)\n                  {\n                    auto geo = make_shared<OCCGeometry> (shape, occdim, copy);\n                    // ng_geometry = geo;\n                    \n                    // geo->BuildFMap();\n                    // geo->CalcBoundingBox();\n                    return geo;\n                  }), py::arg(\"shape\"), py::arg(\"dim\")=3, py::arg(\"copy\")=false,\n         \"Create Netgen OCCGeometry from existing TopoDS_Shape\")\n    \n    .def(py::init([] (const std::vector<TopoDS_Shape> shapes)\n                  {\n                    BOPAlgo_Builder builder;\n                    for (auto & s : shapes)\n                      builder.AddArgument(s);                    \n                    builder.Perform();\n                    for(auto& s : shapes)\n                      PropagateProperties(builder, s);\n                    auto geo = make_shared<OCCGeometry> (builder.Shape());\n                    ng_geometry = geo;\n                    // geo->BuildFMap();\n                    // geo->CalcBoundingBox();\n                    return geo;\n                  }), py::arg(\"shape\"),\n         \"Create Netgen OCCGeometry from existing TopoDS_Shape\")\n    \n    .def(py::init([] (const string& filename, int dim)\n                  {\n                    shared_ptr<OCCGeometry> geo;\n                    if(EndsWith(filename, \".step\") || EndsWith(filename, \".stp\"))\n                      geo.reset(LoadOCC_STEP(filename));\n                    else if(EndsWith(filename, \".brep\"))\n                      geo.reset(LoadOCC_BREP(filename));\n                    else if(EndsWith(filename, \".iges\"))\n                      geo.reset(LoadOCC_IGES(filename));\n                    else\n                      throw Exception(\"Cannot load file \" + filename + \"\\nValid formats are: step, stp, brep, iges\");\n                    if(dim<3)\n                      geo->SetDimension(dim);\n                    ng_geometry = geo;\n                    return geo;\n                  }), py::arg(\"filename\"), py::arg(\"dim\")=3,\n        \"Load OCC geometry from step, brep or iges file\")\n    .def(NGSPickle<OCCGeometry>())\n    .def(\"Glue\", &OCCGeometry::GlueGeometry)\n    .def(\"Heal\",[](OCCGeometry & self, double tolerance, bool fixsmalledges, bool fixspotstripfaces, bool sewfaces, bool makesolids, bool splitpartitions)\n         {\n           self.tolerance = tolerance;\n           self.fixsmalledges = fixsmalledges;\n           self.fixspotstripfaces = fixspotstripfaces;\n           self.sewfaces = sewfaces;\n           self.makesolids = makesolids;\n           self.splitpartitions = splitpartitions;\n\n           self.HealGeometry();\n           self.BuildFMap();\n         },py::arg(\"tolerance\")=1e-3, py::arg(\"fixsmalledges\")=true, py::arg(\"fixspotstripfaces\")=true, py::arg(\"sewfaces\")=true, py::arg(\"makesolids\")=true, py::arg(\"splitpartitions\")=false,R\"raw_string(Heal the OCCGeometry.)raw_string\",py::call_guard<py::gil_scoped_release>())\n    .def(\"SetFaceMeshsize\", [](OCCGeometry& self, size_t fnr, double meshsize)\n                            {\n                              self.SetFaceMaxH(fnr, meshsize);\n                            }, \"Set maximum meshsize for face fnr. Face numbers are 0 based.\")\n    .def(\"Draw\", [](shared_ptr<OCCGeometry> geo)\n    {\n      ng_geometry = geo;\n    })\n    .def_property_readonly(\"solids\", [](shared_ptr<OCCGeometry> geo)\n         {\n           ListOfShapes solids;\n           for (int i = 1; i <= geo->somap.Extent(); i++)\n             solids.push_back(geo->somap(i));\n           return solids;\n         }, \"Get solids in order that they will be in the mesh\")\n    .def_property_readonly(\"faces\", [](shared_ptr<OCCGeometry> geo)\n         {\n           ListOfShapes faces;\n           for (int i = 1; i <= geo->fmap.Extent(); i++)\n             faces.push_back(geo->fmap(i));\n           return faces;\n         }, \"Get faces in order that they will be in the mesh\")\n    .def_property_readonly(\"edges\", [](shared_ptr<OCCGeometry> geo)\n         {\n           ListOfShapes edges;\n           for (int i = 1; i <= geo->emap.Extent(); i++)\n             edges.push_back(geo->emap(i));\n           return edges;\n         }, \"Get edges in order that they will be in the mesh\")\n    .def_property_readonly(\"vertices\", [](shared_ptr<OCCGeometry> geo)\n         {\n           ListOfShapes vertices;\n           for (int i = 1; i <= geo->vmap.Extent(); i++)\n             vertices.push_back(geo->vmap(i));\n           return vertices;\n         }, \"Get vertices in order that they will be in the mesh\")\n    .def(\"_visualizationData\", [] (shared_ptr<OCCGeometry> occ_geo)\n         {\n           std::vector<float> vertices;\n           std::vector<uint32_t> indices;\n           std::vector<float> edges;\n           std::vector<uint32_t> edge_indices;\n           std::vector<float> normals;\n           std::vector<float> min = {std::numeric_limits<float>::max(),\n                               std::numeric_limits<float>::max(),\n                               std::numeric_limits<float>::max()};\n           std::vector<float> max = {std::numeric_limits<float>::lowest(),\n                               std::numeric_limits<float>::lowest(),\n                               std::numeric_limits<float>::lowest()};\n           std::vector<float> face_colors;\n           std::vector<float> edge_colors;\n           auto box = occ_geo->GetBoundingBox();\n           for(int i = 0; i < 3; i++)\n             {\n               min[i] = box.PMin()[i];\n               max[i] = box.PMax()[i];\n             }\n           occ_geo->BuildVisualizationMesh(0.01);\n           gp_Pnt2d uv;\n           gp_Pnt pnt;\n           gp_Vec n;\n           gp_Pnt p[3];\n           for(int edge_index = 1; edge_index <= occ_geo->emap.Extent();\n               edge_index++)\n             {\n               auto edge = TopoDS::Edge(occ_geo->emap(edge_index));\n               if(OCCGeometry::HaveProperties(edge))\n                 {\n                   const auto& props = OCCGeometry::GetProperties(edge);\n                   if(props.col)\n                     edge_colors.insert(edge_colors.end(),\n                                        {float((*props.col)[0]),\n                                         float((*props.col)[1]),\n                                         float((*props.col)[2]),\n                                         float((*props.col)[3])});\n                   else\n                     edge_colors.insert(edge_colors.end(),{0.f,0.f,0.f,1.f});\n                 }\n               else\n                 {\n                   edge_colors.insert(edge_colors.end(),{0.f,0.f,0.f,1.f});\n                 }\n\n               Handle(Poly_PolygonOnTriangulation) poly;\n               Handle(Poly_Triangulation) T;\n               TopLoc_Location loc;\n               BRep_Tool::PolygonOnTriangulation(edge, poly, T, loc);\n               if(poly.IsNull())\n                 {\n                   cout << IM(2) << \"No polygon on triangulation for edge \" << edge_index << endl;\n                   BRepAdaptor_Curve adapt_crv = BRepAdaptor_Curve(edge);\n                   GCPnts_TangentialDeflection discretizer;\n                   discretizer.Initialize(adapt_crv, 0.09, 0.01);\n                   if (discretizer.NbPoints() > 1)\n                     {\n                       for (int j = 1; j <= discretizer.NbPoints()-1; ++j)\n                         {\n                           gp_Pnt p_0 = discretizer.Value(j);\n                           gp_Pnt p_1 = discretizer.Value(j+1);\n                           edges.insert(edges.end(),\n                                        {float(p_0.X()),\n                                         float(p_0.Y()),\n                                         float(p_0.Z()),\n                                         float(p_1.X()),\n                                         float(p_1.Y()),\n                                         float(p_1.Z())});\n                           edge_indices.push_back(uint32_t(edge_index-1));\n                         }\n                     }\n                 }\n               else\n                 {\n                   int nbnodes = poly -> NbNodes();\n                   for (int j = 1; j < nbnodes; j++)\n                     {\n                       auto p0 = occ2ng((T -> Node(poly->Nodes()(j))).Transformed(loc));\n                       auto p1 = occ2ng((T -> Node(poly->Nodes()(j+1))).Transformed(loc));\n                       for(auto k : Range(3))\n                         edges.push_back(p0[k]);\n                       for(auto k : Range(3))\n                         edges.push_back(p1[k]);\n                       edge_indices.push_back(uint32_t(edge_index-1));\n                       box.Add(p0);\n                       box.Add(p1);\n                     }\n                 }\n             }\n           for (int i = 1; i <= occ_geo->fmap.Extent(); i++)\n             {\n               auto face = TopoDS::Face(occ_geo->fmap(i));\n               if (OCCGeometry::HaveProperties(face))\n                 {\n                   const auto& props = OCCGeometry::GetProperties(face);\n                   if(props.col)\n                     face_colors.insert(face_colors.end(),\n                                        {float((*props.col)[0]),\n                                         float((*props.col)[1]),\n                                         float((*props.col)[2]),\n                                         float((*props.col)[3])});\n                    else\n                      {\n                        face_colors.insert(face_colors.end(),{0.7,0.7,0.7,1.});\n                      }\n                 }\n               else\n                 {\n                   face_colors.insert(face_colors.end(),{0.7,0.7,0.7,1.});\n                 }\n               auto surf = BRep_Tool::Surface(face);\n               TopLoc_Location loc;\n               BRepAdaptor_Surface sf(face, Standard_False);\n               BRepLProp_SLProps prop(sf, 1, 1e-5);\n               Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\n               if (triangulation.IsNull())\n                 cout << \"cannot visualize face \" << i << endl;\n               indices.reserve(indices.size() + triangulation->NbTriangles());\n               vertices.reserve(vertices.size() + triangulation->NbTriangles()*3*3);\n               normals.reserve(normals.size() + triangulation->NbTriangles()*3*3);\n               for (int j = 1; j < triangulation->NbTriangles()+1; j++)\n                 {\n                   auto triangle = triangulation->Triangle(j);\n                   for (int k = 1; k < 4; k++)\n                     p[k-1] = triangulation->Node(triangle(k)).Transformed(loc);\n                   indices.push_back(uint32_t(i-1));\n                   for (int k = 1; k < 4; k++)\n                     {\n                       vertices.insert(vertices.end(),{\n                           float(p[k-1].X()),\n                           float(p[k-1].Y()),\n                           float(p[k-1].Z())});\n                       uv = triangulation->UVNode(triangle(k));\n                       prop.SetParameters(uv.X(), uv.Y());\n                       if (prop.IsNormalDefined())\n                         n = prop.Normal();\n                       else\n                         {\n                           gp_Vec a(p[0], p[1]);\n                           gp_Vec b(p[0], p[2]);\n                           n = b^a;\n                         }\n                       if (face.Orientation() == TopAbs_REVERSED) n*= -1;\n                       normals.insert(normals.end(),{float(n.X()), float(n.Y()), float(n.Z())});\n                     }\n                 }\n             }\n            py::gil_scoped_acquire ac;\n            py::dict res;\n            py::list snames;\n            res[\"vertices\"] = MoveToNumpy(vertices);\n            res[\"edges\"] = MoveToNumpy(edges);\n            res[\"edge_indices\"] = MoveToNumpy(edge_indices);\n            res[\"edge_colors\"] = MoveToNumpy(edge_colors);\n            res[\"indices\"] = MoveToNumpy(indices);\n            res[\"normals\"] = MoveToNumpy(normals);\n            res[\"face_colors\"] = MoveToNumpy(face_colors);\n            res[\"min\"] = MoveToNumpy(min);\n            res[\"max\"] = MoveToNumpy(max);\n            return res;\n         }, py::call_guard<py::gil_scoped_release>())\n    .def(\"GenerateMesh\", [](shared_ptr<OCCGeometry> geo,\n                            MeshingParameters* pars, NgMPI_Comm comm,\n                            shared_ptr<Mesh> mesh, py::kwargs kwargs)\n                         {\n                           MeshingParameters mp;\n                           OCCParameters occparam;\n                           if(pars)\n                             {\n                               auto mp_kwargs = CreateDictFromFlags(pars->geometrySpecificParameters);\n                               CreateOCCParametersFromKwargs(occparam, mp_kwargs);\n                               mp = *pars;\n                             }\n                           CreateOCCParametersFromKwargs(occparam, kwargs);\n                           CreateMPfromKwargs(mp, kwargs);\n                           py::gil_scoped_release gil_release;\n                           geo->SetOCCParameters(occparam);\n                           if(!mesh)\n                             mesh = make_shared<Mesh>();\n                           mesh->SetCommunicator(comm);\n                           mesh->SetGeometry(geo);\n\n                           if (comm.Rank()==0)\n                             {\n                               SetGlobalMesh(mesh);\n                               auto result = geo->GenerateMesh(mesh, mp);\n                               if(result != 0)\n                                 {\n                                   netgen::mesh = mesh;   // keep mesh for debugging\n                                   throw Exception(\"Meshing failed!\");\n                                 }\n                               ng_geometry = geo;\n                               if (comm.Size() > 1)\n                                 mesh->Distribute();\n                             }\n                           else\n                             {\n                               mesh->SendRecvMesh();\n                             }\n                           return mesh;\n                         }, py::arg(\"mp\") = nullptr, py::arg(\"comm\")=NgMPI_Comm{},\n         py::arg(\"mesh\")=nullptr,\n         (meshingparameter_description + occparameter_description).c_str())\n    .def_property_readonly(\"shape\", [](const OCCGeometry & self) { return self.GetShape(); })\n    ;\n\n  \n  \n  m.def(\"LoadOCCGeometry\",[] (filesystem::path filename)\n        {\n          cout << \"WARNING: LoadOCCGeometry is deprecated! Just use the OCCGeometry(filename) constructor. It is able to read brep and iges files as well!\" << endl;\n          ifstream ist(filename);\n          OCCGeometry * instance = new OCCGeometry();\n          instance = LoadOCC_STEP(filename.c_str());\n          ng_geometry = shared_ptr<OCCGeometry>(instance, NOOP_Deleter);\n          return ng_geometry;\n        },py::call_guard<py::gil_scoped_release>());\n\n\n  m.def(\"TestXCAF\", [] (TopoDS_Shape shape) {\n\n      /*static*/ Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication();\n      cout << endl << endl << endl;\n      cout << \"app = \" << *reinterpret_cast<void**>(&app) << endl;\n      Handle(TDocStd_Document) doc;\n      cout << \"nbdocs = \" << app->NbDocuments() << endl;\n      if(app->NbDocuments() > 0)\n      {\n         app->GetDocument(1,doc);\n         // app->Close(doc);\n      }\n      else\n        app->NewDocument (\"STEP-XCAF\",doc);\n      Handle(XCAFDoc_ShapeTool) shape_tool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());\n      Handle(XCAFDoc_MaterialTool) material_tool = XCAFDoc_DocumentTool::MaterialTool(doc->Main());\n      // Handle(XCAFDoc_VisMaterialTool) vismaterial_tool = XCAFDoc_DocumentTool::VisMaterialTool(doc->Main());\n\n      // TDF_LabelSequence doc_shapes;\n      // shape_tool->GetShapes(doc_shapes);\n      // cout << \"shape tool nbentities: \" << doc_shapes.Size() << endl;\n      TDF_Label label = shape_tool -> FindShape(shape);\n      cout << \"shape label = \" << endl << label << endl;\n      if (label.IsNull()) return;\n      cout << \"nbattr = \" << label.NbAttributes() << endl;\n                                                     \n                                                     \n      if (!label.IsNull())\n        {\n          Handle(TDF_Attribute) attribute;\n          cout << \"create guid\" << endl;\n          // Standard_GUID guid(\"c4ef4200-568f-11d1-8940-080009dc3333\");\n          Standard_GUID guid(\"2a96b608-ec8b-11d0-bee7-080009dc3333\");      \n          cout << \"have guid\" << endl;\n          cout << \"find attrib \" << label.FindAttribute(guid, attribute) << endl;\n          cout << \"attrib = \" << attribute << endl;\n          cout << \"tag = \" << label.Tag() << endl;\n          cout << \"father.tag = \" << label.Father().Tag() << endl;\n          cout << \"Data = \" << label.Data() << endl;\n          \n          cout << \"nbchild = \" << label.NbChildren() << endl;\n          for (auto i : Range(label.NbChildren()))\n            {\n              TDF_Label child = label.FindChild(i+1);\n              cout << \"child[\" << i << \"] = \" << child << endl;\n              cout << \"find attrib \" << child.FindAttribute(guid, attribute) << endl;\n              cout << \"attrib = \" << attribute << endl;\n            }\n          \n          // cout << \"findshape = \" << shape_tool -> FindShape(shape) << endl;\n          cout << \"IsMaterial = \" << material_tool->IsMaterial(label) << endl;\n          // cout << \"IsVisMaterial = \" << vismaterial_tool->IsMaterial(label) << endl;\n        }\n    }, py::arg(\"shape\")=TopoDS_Shape());\n        \n}\n\nPYBIND11_MODULE(libNgOCC, m) {\n  ExportNgOCC(m);\n}\n\n#endif // OCCGEOMETRY\n#endif // NG_PYTHON\n"
  },
  {
    "path": "libsrc/occ/python_occ_basic.cpp",
    "content": "#ifdef NG_PYTHON\n#ifdef OCCGEOMETRY\n\n#include <general/ngpython.hpp>\n#include <core/python_ngcore.hpp>\n#include <meshing/python_mesh.hpp>\n#include <meshing.hpp>\n\n#include \"occgeom.hpp\"\n\n#include <BRepBuilderAPI_Transform.hxx>\n#include <BRepBuilderAPI_GTransform.hxx>\n#include <gp_Ax1.hxx>\n#include <gp_Ax2.hxx>\n#include <gp_Ax2d.hxx>\n#include <gp_Ax3.hxx>\n#include <gp_Trsf.hxx>\n#include <gp_GTrsf.hxx>\n\nusing namespace netgen;\n\nDLL_HEADER void ExportNgOCCBasic(py::module &m) \n{\n  py::class_<gp_Pnt>(m, \"gp_Pnt\", \"3d OCC point\")\n    .def(py::init([] (py::tuple pnt)\n                  {\n                    if (py::len(pnt) != 3)\n                      throw std::length_error(\"need 3-tuple to create gp_Pnt\");\n                    \n                    return gp_Pnt(py::cast<double>(pnt[0]),\n                                  py::cast<double>(pnt[1]),\n                                  py::cast<double>(pnt[2]));\n                  }))\n    .def(py::init([] (double x, double y, double z) {\n          return gp_Pnt(x, y, z);\n        }), py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"))\n    .def_property(\"x\", [](gp_Pnt&p) { return p.X(); }, [](gp_Pnt&p,double x) { p.SetX(x); })\n    .def_property(\"y\", [](gp_Pnt&p) { return p.Y(); }, [](gp_Pnt&p,double y) { p.SetY(y); })\n    .def_property(\"z\", [](gp_Pnt&p) { return p.Z(); }, [](gp_Pnt&p,double z) { p.SetZ(z); })\n    .def(\"__str__\", [] (const gp_Pnt & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \", \" << p.Z() << \")\";\n        return str.str();\n      })\n    .def(\"__repr__\", [] (const gp_Pnt & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \", \" << p.Z() << \")\";\n        return str.str();\n      })\n\n    .def(\"__sub__\", [](gp_Pnt p1, gp_Pnt p2) { return gp_Vec(p2, p1); }) \n    .def(\"__add__\", [](gp_Pnt p, gp_Vec v) { return p.Translated(v); }) // gp_Pnt(p.X()+v.X(), p.Y()+v.Y(), p.Z()+v.Z()); })\n    .def(\"__sub__\", [](gp_Pnt p, gp_Vec v) { return p.Translated(-v); }) // gp_Pnt(p.X()-v.X(), p.Y()-v.Y(), p.Z()-v.Z()); })\n    .def(\"__getitem__\", [](const gp_Pnt& p, int index)\n    {\n      if(index == 0)\n        return p.X();\n      if(index == 1)\n        return p.Y();\n      if(index == 2)\n        return p.Z();\n      throw std::out_of_range(\"Point index must be in range [0,3)!\");\n    })\n    ;\n  \n  py::class_<gp_Vec>(m, \"gp_Vec\", \"3d OCC vector\")\n    .def(py::init([] (py::tuple vec)\n                  {\n                    return gp_Vec(py::cast<double>(vec[0]),\n                                  py::cast<double>(vec[1]),\n                                  py::cast<double>(vec[2]));\n                  }))\n    .def(py::init([] (double x, double y, double z) {\n          return gp_Vec(x, y, z);\n        }), py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"))\n    .def(py::init([](gp_Dir d) { return gp_Vec(d); }))\n    .def_property(\"x\", [](gp_Vec&p) { return p.X(); }, [](gp_Vec&p,double x) { p.SetX(x); })\n    .def_property(\"y\", [](gp_Vec&p) { return p.Y(); }, [](gp_Vec&p,double y) { p.SetY(y); })\n    .def_property(\"z\", [](gp_Vec&p) { return p.Z(); }, [](gp_Vec&p,double z) { p.SetZ(z); })\n    .def(\"Norm\", [](const gp_Vec& v)\n    { return v.Magnitude(); })\n    .def(\"__str__\", [] (const gp_Vec & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \", \" << p.Z() << \")\";\n        return str.str();\n      })\n    .def(\"__repr__\", [] (const gp_Vec & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \", \" << p.Z() << \")\";\n        return str.str();\n      })\n    .def(\"__add__\", [](gp_Vec v1, gp_Vec v2) { return v1+v2; }) \n    .def(\"__sub__\", [](gp_Vec v1, gp_Vec v2) { return v1-v2; }) \n    .def(\"__rmul__\", [](gp_Vec v, double s) { return s*v; }) \n    .def(\"__mul__\", [](gp_Vec v1, gp_Vec v2) { return v1*v2; })\n    .def(\"__neg__\", [](gp_Vec v) { return -v; }) \n    .def(\"__xor__\", [](gp_Vec v1, gp_Vec v2) { return v1^v2; })\n    \n    .def(\"__lt__\", [](gp_Vec v, double val)\n         {\n           cout << IM(6) << \"vec, lt v - \" << netgen::occ2ng(v) << \", val = \" << val << endl;\n           return DirectionalInterval(v) < val;\n         })\n    .def(\"__gt__\", [](gp_Vec v, double val)\n         {\n           cout << IM(6) << \"vec, gt v - \" << netgen::occ2ng(v) << \", val = \" << val << endl;           \n           return DirectionalInterval(v) > val;\n         })\n    .def(\"__le__\", [](gp_Vec v, double val)\n        {\n          return DirectionalInterval(v) <= val;\n        })\n    .def(\"__ge__\", [](gp_Vec v, double val)\n        {\n          return DirectionalInterval(v) >= val;\n        })\n    ;\n\n  py::class_<gp_Dir>(m, \"gp_Dir\", \"3d OCC direction\")\n    .def(py::init([] (py::tuple dir)\n                  {\n                    return gp_Dir(py::cast<double>(dir[0]),\n                                  py::cast<double>(dir[1]),\n                                  py::cast<double>(dir[2]));\n                  }))\n    .def(py::init([] (double x, double y, double z) {\n          return gp_Dir(x, y, z);\n        }), py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"))\n    .def(py::init<gp_Vec>())\n    .def(\"__str__\", [] (const gp_Dir & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \", \" << p.Z() << \")\";\n        return str.str();\n      })\n    .def(\"__getitem__\", [](const gp_Dir& d, int index)\n    {\n      if(index == 0)\n        return d.X();\n      if(index == 1)\n        return d.Y();\n      if(index == 2)\n        return d.Z();\n      throw std::out_of_range(\"Direction index must be in range [0,3)!\");\n    })\n    ;\n\n\n  py::class_<gp_Mat>(m, \"gp_Mat\", \"3d OCC matrix\")\n    .def(\"__getitem__\", [](const gp_Mat& mat, tuple<int,int> index)\n    { return mat.Row(get<0>(index)+1).Coord(get<1>(index)+1); })\n    ;\n  \n  py::class_<gp_Ax1>(m, \"Axis\", \"an OCC axis in 3d\") \n    .def(py::init([](gp_Pnt p, gp_Dir d) {\n          return gp_Ax1(p,d);\n        }), py::arg(\"p\"), py::arg(\"d\"))\n    ;\n  py::class_<gp_Ax2>(m, \"gp_Ax2\")\n    .def(py::init([](gp_Pnt p, gp_Dir d) {\n          return gp_Ax2(p,d);\n        }))\n    .def(py::init([](const gp_Ax3 & ax3) {\n          return gp_Ax2(ax3.Ax2());\n        }))\n    ;\n\n  py::class_<gp_Ax3>(m, \"Axes\", \"an OCC coordinate system in 3d\")\n    .def(py::init([](gp_Pnt p, gp_Dir N, gp_Dir Vx) {\n          return gp_Ax3(p,N, Vx);\n        }), py::arg(\"p\")=gp_Pnt(0,0,0), py::arg(\"n\")=gp_Vec(0,0,1), py::arg(\"h\")=gp_Vec(1,0,0))\n    .def(py::init([](gp_Ax1 ax1) {\n          return gp_Ax3(ax1.Location(), ax1.Direction());\n        }), py::arg(\"axis\"))\n    .def(py::init<gp_Ax2>())\n    .def_property(\"p\", [](gp_Ax3 & ax) { return ax.Location(); }, [](gp_Ax3&ax, gp_Pnt p) { ax.SetLocation(p); })\n    ;\n\n\n  py::class_<gp_Pnt2d>(m, \"gp_Pnt2d\", \"2d OCC point\")\n    .def(py::init([] (std::tuple<double,double> pnt)\n                  {\n                    return gp_Pnt2d(get<0>(pnt), get<1>(pnt));\n                  }))\n    .def(py::init([] (double x, double y) {\n          return gp_Pnt2d(x, y);\n        }), py::arg(\"x\"), py::arg(\"y\"))\n    .def_property(\"x\", [](gp_Pnt2d&p) { return p.X(); }, [](gp_Pnt2d&p,double x) { p.SetX(x); })\n    .def_property(\"y\", [](gp_Pnt2d&p) { return p.Y(); }, [](gp_Pnt2d&p,double y) { p.SetY(y); })\n    .def(\"__str__\", [] (const gp_Pnt2d & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \")\";\n        return str.str();\n      })\n    .def(\"__repr__\", [] (const gp_Pnt2d & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \")\";\n        return str.str();\n      })\n\n    .def(\"__sub__\", [](gp_Pnt2d p1, gp_Pnt2d p2) { return gp_Vec2d(p1.X()-p2.X(), p1.Y()-p2.Y()); })\n    .def(\"__add__\", [](gp_Pnt2d p, gp_Vec2d v) { return p.Translated(v); })\n    .def(\"__sub__\", [](gp_Pnt2d p, gp_Vec2d v) { return p.Translated(-v); })\n    ;\n  \n  py::class_<gp_Vec2d>(m, \"gp_Vec2d\", \"2d OCC vector\")\n    .def(py::init([] (py::tuple vec)\n                  {\n                    if (py::len(vec) != 2)\n                      throw Exception(\"need 2-tuple to create gp_Vec2d\");                    \n                    return gp_Vec2d(py::cast<double>(vec[0]),\n                                    py::cast<double>(vec[1]));\n                  }))\n    .def(py::init([] (double x, double y) {\n          return gp_Vec2d(x, y);\n        }), py::arg(\"x\"), py::arg(\"y\"))\n    .def_property(\"x\", [](gp_Vec2d&p) { return p.X(); }, [](gp_Vec2d&p,double x) { p.SetX(x); })\n    .def_property(\"y\", [](gp_Vec2d&p) { return p.Y(); }, [](gp_Vec2d&p,double y) { p.SetY(y); })\n    .def(\"__str__\", [] (const gp_Vec & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \")\";\n        return str.str();\n      })\n    .def(\"__repr__\", [] (const gp_Vec & p) {\n        stringstream str;\n        str << \"(\" << p.X() << \", \" << p.Y() << \")\";\n        return str.str();\n      })\n    .def(\"__add__\", [](gp_Vec2d v1, gp_Vec2d v2) { return v1+v2; }) \n    .def(\"__sub__\", [](gp_Vec2d v1, gp_Vec2d v2) { return v1-v2; })\n    .def(\"__rmul__\", [](gp_Vec2d v, double s) { return s*v; })\n    .def(\"__neg__\", [](gp_Vec2d v) { return -v; }) \n    .def(\"__xor__\", [](gp_Vec2d v1, gp_Vec2d v2) { return v1^v2; }) \n    ;\n\n  py::class_<gp_Dir2d>(m, \"gp_Dir2d\", \"2d OCC direction\")\n    .def(py::init([] (py::tuple dir)\n                  {\n                    if (py::len(dir) != 2)\n                      throw Exception(\"need 2-tuple to create gp_Dir2d\");                    \n                    return gp_Dir2d(py::cast<double>(dir[0]),\n                                    py::cast<double>(dir[1]));\n                  }))\n    .def(py::init([] (double x, double y) {\n          return gp_Dir2d(x, y);\n        }), py::arg(\"x\"), py::arg(\"y\"))\n    ;\n\n  m.def(\"Pnt\", [](double x, double y) { return gp_Pnt2d(x,y); },\n        py::arg(\"x\"), py::arg(\"y\"), \"create 2d OCC point\");\n  m.def(\"Pnt\", [](double x, double y, double z) { return gp_Pnt(x,y,z); },\n        py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"), \"create 3d OCC point\");\n  m.def(\"Pnt\", [](std::vector<double> p)\n        {\n          if (p.size() == 2)\n            return py::cast(gp_Pnt2d(p[0], p[1]));\n          if (p.size() == 3)\n            return py::cast(gp_Pnt(p[0], p[1], p[2]));\n          throw Exception(\"OCC-Points only in 2D or 3D\");\n        }, py::arg(\"p\"), \"create 2d or 3d OCC point\");\n\n  m.def(\"Vec\", [](double x, double y) { return gp_Vec2d(x,y); },\n        py::arg(\"x\"), py::arg(\"y\"), \"create 2d OCC point\");\n  m.def(\"Vec\", [](double x, double y, double z) { return gp_Vec(x,y,z); },\n        py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"), \"create 3d OCC point\");        \n  m.def(\"Vec\", [](std::vector<double> p)\n        {\n          if (p.size() == 2)\n            return py::cast(gp_Vec2d(p[0], p[1]));\n          if (p.size() == 3)\n            return py::cast(gp_Vec(p[0], p[1], p[2]));\n          throw Exception(\"OCC-Vecs only in 2D or 3D\");\n        }, py::arg(\"v\"), \"create 2d or 3d OCC vector\");          \n\n  m.def(\"Dir\", [](double x, double y) { return gp_Dir2d(x,y); },\n        py::arg(\"x\"), py::arg(\"y\"), \"create 2d OCC direction\");\n  m.def(\"Dir\", [](double x, double y, double z) { return gp_Dir(x,y,z); },\n        py::arg(\"x\"), py::arg(\"y\"), py::arg(\"z\"), \"create 3d OCC direction\");        \n  m.def(\"Dir\", [](std::vector<double> p)\n        {\n          if (p.size() == 2)\n            return py::cast(gp_Dir2d(p[0], p[1]));\n          if (p.size() == 3)\n            return py::cast(gp_Dir(p[0], p[1], p[2]));\n          throw Exception(\"OCC-Dirs only in 2D or 3D\");\n        }, py::arg(\"d\"), \"create 2d or 3d OCC direction\");                    \n\n\n\n  \n  py::class_<gp_Ax2d>(m, \"gp_Ax2d\", \"2d OCC coordinate system\")\n    .def(py::init([](gp_Pnt2d p, gp_Dir2d d) {\n          return gp_Ax2d(p,d);\n        }), py::arg(\"p\")=gp_Pnt2d(0,0), py::arg(\"d\")=gp_Dir2d(1,0))\n    ;\n\n  py::class_<gp_GTrsf>(m, \"gp_GTrsf\")\n    .def(py::init([](const std::vector<double>& mat,\n                     const std::vector<double>& vec)\n         {\n           if(mat.size() != 9)\n             throw Exception(\"Need 9 matrix values for construction of gp_GTrsf\");\n           if(vec.size() != 3)\n             throw Exception(\"Need 3 vector values for construction of gp_GTrsf\");\n           gp_GTrsf trafo;\n           trafo.SetVectorialPart({ mat[0], mat[1], mat[2],\n               mat[3], mat[4], mat[5],\n               mat[6], mat[7], mat[8] });\n           trafo.SetTranslationPart( { vec[0], vec[1], vec[2] });\n           return trafo;\n         }), py::arg(\"mat\"), py::arg(\"vec\") = std::vector<double>{ 0., 0., 0. })\n    .def(\"__call__\", [] (gp_GTrsf & trafo, const TopoDS_Shape & shape) {\n        BRepBuilderAPI_GTransform builder(shape, trafo, true);\n        PropagateProperties(builder, shape, occ2ng(trafo));\n        return builder.Shape();\n      })\n    ;\n  \n  py::class_<gp_Trsf>(m, \"gp_Trsf\")\n    .def(py::init<>())    \n    .def(\"SetMirror\", [] (gp_Trsf & trafo, const gp_Ax1 & ax) { trafo.SetMirror(ax); return trafo; })\n    .def(\"Inverted\", &gp_Trsf::Inverted)\n    .def_static(\"Translation\", [] (const gp_Vec & v) { gp_Trsf trafo; trafo.SetTranslation(v); return trafo; })\n    .def_static(\"Scale\", [] (const gp_Pnt & p, double s) { gp_Trsf trafo; trafo.SetScale(p,s); return trafo; })    \n    .def_static(\"Mirror\", [] (const gp_Ax1 & ax) { gp_Trsf trafo; trafo.SetMirror(ax); return trafo; })\n    .def_static(\"Rotation\", [] (const gp_Ax1 & ax, double ang) { gp_Trsf trafo; trafo.SetRotation(ax, ang*M_PI/180); return trafo; })\n    .def_static(\"Rotation\", [] (const gp_Pnt & p, const gp_Dir & d, double ang)\n                { gp_Trsf trafo; trafo.SetRotation(gp_Ax1(p,d), ang*M_PI/180); return trafo; })    \n    .def_static(\"Transformation\", [] (const gp_Ax3 & ax) { gp_Trsf trafo; trafo.SetTransformation(ax); return trafo; })\n    .def_static(\"Transformation\", [] (const gp_Ax3 & from, const gp_Ax3 to)\n                { gp_Trsf trafo; trafo.SetTransformation(from, to); return trafo; })\n    .def(py::self * py::self)\n    .def(\"__call__\", [] (gp_Trsf & trafo, const TopoDS_Shape & shape) {\n        BRepBuilderAPI_Transform builder(shape, trafo, true);\n        PropagateProperties(builder, shape, occ2ng(trafo));\n        return builder.Shape();\n      })\n    .def(\"__str__\", [](gp_Trsf & trafo)\n    {\n      stringstream str;\n      gp_XYZ xyz = trafo.TranslationPart();\n      str << xyz.X() << \", \" << xyz.Y() << \", \" << xyz.Z();\n      return str.str();\n    })\n    ;\n\n  py::class_<TopLoc_Location>(m, \"TopLoc_Location\")\n    .def(py::init<gp_Trsf>())\n    .def(\"Transformation\", [](const TopLoc_Location & loc) { return loc.Transformation(); })\n    ;\n\n\n  py::class_<DirectionalInterval> (m, \"DirectionalInterval\")\n    .def(\"__str__\", [](DirectionalInterval self)\n         {\n           stringstream str;\n           str << \"(\" << self.minval << \", \" << self.maxval << \")\";\n           return str.str();\n         })\n         \n    .def(\"__lt__\", [](DirectionalInterval i, double val)\n         {\n           cout << \"directionalinterval, lt, imin/max = \" << i.minval << \" / \" << i.maxval << endl;\n           return i < val;\n         })\n    .def(\"__gt__\", [](DirectionalInterval i, double val)\n         {\n           cout << \"directionalinterval, gt, imin/max = \" << i.minval << \" / \" << i.maxval << endl;\n           return i > val;\n         })\n    .def(\"__and__\", [](DirectionalInterval self, DirectionalInterval other) {\n        cout << \"and of intervals\" << endl;\n        return self.Intersect(other);\n      })\n    ;    \n  \n  py::implicitly_convertible<py::tuple, gp_Pnt>();\n  py::implicitly_convertible<py::tuple, gp_Vec>();\n  py::implicitly_convertible<py::tuple, gp_Dir>();\n  py::implicitly_convertible<gp_Vec, gp_Dir>();\n  py::implicitly_convertible<gp_Dir, gp_Vec>();\n  py::implicitly_convertible<py::tuple, gp_Pnt2d>();  \n  py::implicitly_convertible<py::tuple, gp_Vec2d>();  \n  py::implicitly_convertible<py::tuple, gp_Dir2d>();\n  \n  py::implicitly_convertible<gp_Ax1, gp_Ax3>();  \n  py::implicitly_convertible<gp_Ax3, gp_Ax1>();  \n\n\n  py::implicitly_convertible<gp_Ax3, gp_Ax2>();\n\n  m.attr(\"X\") = py::cast(gp_Vec(1,0,0));\n  m.attr(\"Y\") = py::cast(gp_Vec(0,1,0));\n  m.attr(\"Z\") = py::cast(gp_Vec(0,0,1));\n}\n\n\n#endif // OCCGEOMETRY\n#endif // NG_PYTHON\n \n"
  },
  {
    "path": "libsrc/occ/python_occ_shapes.cpp",
    "content": "#include <Geom_Curve.hxx>\n#ifdef NG_PYTHON\n#ifdef OCCGEOMETRY\n\n#include <regex>\n\n#include <general/ngpython.hpp>\n#include <core/python_ngcore.hpp>\n#include <meshing/python_mesh.hpp>\n#include <meshing.hpp>\n\n#include \"occgeom.hpp\"\n#include \"occ_utils.hpp\"\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n#if NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n#include <BinTools_ShapeWriter.hxx>\n#endif // NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n#include <BOPAlgo_Builder.hxx>\n#include <BOPTools_AlgoTools.hxx>\n#include <BRepAlgoAPI_Common.hxx>\n#include <BRepAlgoAPI_Cut.hxx>\n#include <BRepAlgoAPI_Fuse.hxx>\n#include <BRepAlgoAPI_Section.hxx>\n#include <BRepAlgo_NormalProjection.hxx>\n#include <BRepBndLib.hxx>\n#include <BRepBuilderAPI_MakeEdge.hxx>\n#include <BRepBuilderAPI_MakeFace.hxx>\n#include <BRepBuilderAPI_MakePolygon.hxx>\n#include <BRepBuilderAPI_MakeVertex.hxx>\n#include <BRepBuilderAPI_MakeWire.hxx>\n#include <BRepBuilderAPI_Transform.hxx>\n#include <BRepBuilderAPI_GTransform.hxx>\n#include <BRepExtrema_DistShapeShape.hxx>\n#include <BRepFilletAPI_MakeChamfer.hxx>\n#include <BRepFilletAPI_MakeFillet.hxx>\n#include <BRepFilletAPI_MakeFillet2d.hxx>\n#include <BRepGProp.hxx>\n#include <BRepLProp_SLProps.hxx>\n#include <BRepLib.hxx>\n#include <BRepOffsetAPI_MakeOffset.hxx>\n#include <BRepOffsetAPI_MakePipe.hxx>\n#include <BRepOffsetAPI_MakePipeShell.hxx>\n#include <BRepOffsetAPI_MakeThickSolid.hxx>\n#include <BRepOffsetAPI_ThruSections.hxx>\n#include <BRepPrimAPI_MakeBox.hxx>\n#include <BRepPrimAPI_MakeCylinder.hxx>\n#include <BRepPrimAPI_MakeCone.hxx>\n#include <BRepPrimAPI_MakeHalfSpace.hxx>\n#include <BRepPrimAPI_MakePrism.hxx>\n#include <BRepPrimAPI_MakeRevol.hxx>\n#include <BRepPrimAPI_MakeSphere.hxx>\n#include <BRepTools.hxx>\n#include <GCE2d_MakeArcOfCircle.hxx>\n#include <GCE2d_MakeCircle.hxx>\n#include <GCE2d_MakeEllipse.hxx>\n#include <GCE2d_MakeSegment.hxx>\n#include <GC_MakeArcOfCircle.hxx>\n#include <GC_MakeCircle.hxx>\n#include <GC_MakeSegment.hxx>\n#include <GProp_GProps.hxx>\n#include <Geom2d_BSplineCurve.hxx>\n#include <Geom2d_Curve.hxx>\n#include <Geom2d_Ellipse.hxx>\n#include <Geom2d_TrimmedCurve.hxx>\n#include <Geom2dAPI_Interpolate.hxx>\n#include <Geom2dAPI_PointsToBSpline.hxx>\n#include <GeomAPI_Interpolate.hxx>\n#include <GeomAPI_PointsToBSpline.hxx>\n#include <GeomAPI_PointsToBSplineSurface.hxx>\n#include <GeomLProp_SLProps.hxx>\n#include <Geom_BezierCurve.hxx>\n#include <Geom_BezierSurface.hxx>\n#include <Geom_BSplineCurve.hxx>\n#include <Geom_BSplineSurface.hxx>\n#include <Geom_Plane.hxx>\n#include <Geom_TrimmedCurve.hxx>\n#include <IntTools_Context.hxx>\n#include <ShapeAnalysis_FreeBounds.hxx>\n#include <ShapeUpgrade_UnifySameDomain.hxx>\n#include <ShapeFix_ShapeTolerance.hxx>\n#include <gp_Ax1.hxx>\n#include <gp_Ax2.hxx>\n#include <gp_Ax2d.hxx>\n#include <gp_Pln.hxx>\n#include <gp_Trsf.hxx>\n#include <GeomLib.hxx>\n#include <Geom_BoundedCurve.hxx>\n\n#pragma clang diagnostic pop\n\nusing namespace netgen;\n\nvoid ExtractEdgeData( const TopoDS_Edge & edge, int index, std::vector<double> * p, Box<3> & box )\n{\n    if (BRep_Tool::Degenerated(edge)) return;\n\n    Handle(Poly_PolygonOnTriangulation) poly;\n    Handle(Poly_Triangulation) T;\n    TopLoc_Location loc;\n    BRep_Tool::PolygonOnTriangulation(edge, poly, T, loc);\n\n    if (poly.IsNull())\n      {\n        cout << IM(2) << \"no edge mesh, do my own sampling\" << endl;\n\n        double s0, s1;\n        Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);\n\n        constexpr int num = 100;\n        for (int i = 0; i < num; i++)\n          {\n            auto p0 = occ2ng(c->Value (s0 + i*(s1-s0)/num));\n            auto p1 = occ2ng(c->Value (s0 + (i+1)*(s1-s0)/num));\n            for(auto k : Range(3))\n              {\n                p[0].push_back(p0[k]);\n                p[1].push_back(p1[k]);\n              }\n            p[0].push_back(index);\n            p[1].push_back(index);\n            box.Add(p0);\n            box.Add(p1);\n          }\n        return;\n      }        \n\n    int nbnodes = poly -> NbNodes();\n    for (int j = 1; j < nbnodes; j++)\n      {\n        auto p0 = occ2ng((T -> Node(poly->Nodes()(j))).Transformed(loc));\n        auto p1 = occ2ng((T -> Node(poly->Nodes()(j+1))).Transformed(loc));\n        for(auto k : Range(3))\n          {\n            p[0].push_back(p0[k]);\n            p[1].push_back(p1[k]);\n          }\n        p[0].push_back(index);\n        p[1].push_back(index);\n        box.Add(p0);\n        box.Add(p1);\n    }\n}\n\nvoid ExtractFaceData( const TopoDS_Face & face, int index, std::vector<double> * p, std::vector<double> * n, Box<3> & box )\n{\n    TopLoc_Location loc;\n    Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\n    Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n    BRepAdaptor_Surface sf(face, Standard_False);\n    BRepLProp_SLProps prop(sf, 1, 1e-5);\n\n    bool flip = TopAbs_REVERSED == face.Orientation();\n\n    if (triangulation.IsNull())\n      {\n        cout << \"pls build face triangulation before\" << endl;\n        return;\n      }\n\n    int ntriangles = triangulation -> NbTriangles();\n    for (int j = 1; j <= ntriangles; j++)\n    {\n      Poly_Triangle triangle = triangulation -> Triangle(j);\n        std::array<Point<3>,3> pts;\n        std::array<Vec<3>,3> normals;\n        for (int k = 0; k < 3; k++)\n          pts[k] = occ2ng( (triangulation -> Node(triangle(k+1))).Transformed(loc) );\n\n        for (int k = 0; k < 3; k++)\n          {\n            auto uv = triangulation -> UVNode(triangle(k+1));\n            prop.SetParameters (uv.X(), uv.Y());\n            if (prop.IsNormalDefined())\n              normals[k] = occ2ng (prop.Normal());\n            else\n              normals[k] = Cross(pts[1]-pts[0], pts[2]-pts[0]);\n          }\n\n        if(flip)\n        {\n            Swap(pts[1], pts[2]);\n            Swap(normals[1], normals[2]);\n            for (int k = 0; k < 3; k++)\n                normals[k] = -normals[k];\n        }\n\n        for (int k = 0; k < 3; k++)\n        {\n            box.Add(pts[k]);\n            for (int d = 0; d < 3; d++)\n            {\n                p[k].push_back( pts[k][d] );\n                n[k].push_back( normals[k][d] );\n            }\n            p[k].push_back( index );\n        }\n    }\n}\n\npy::object CastShape(const TopoDS_Shape & s)\n{\n  switch (s.ShapeType())\n    {\n    case TopAbs_VERTEX:\n      return py::cast(TopoDS::Vertex(s));\n    case TopAbs_FACE:\n      return py::cast(TopoDS::Face(s));      \n    case TopAbs_EDGE:\n      return py::cast(TopoDS::Edge(s));      \n    case TopAbs_WIRE:\n      return py::cast(TopoDS::Wire(s));      \n\n    case TopAbs_COMPOUND:\n    case TopAbs_COMPSOLID:\n    case TopAbs_SOLID:\n    case TopAbs_SHELL:\n    case TopAbs_SHAPE:\n      return py::cast(s);\n    }\n    throw Exception(\"Invalid Shape type\");\n};\n\nnamespace netgen {\nTopoDS_Shape CrossSection(const TopoDS_Shape & shape,\n                          const gp_Ax3 & axis);\n}\n\n\nclass WorkPlane : public enable_shared_from_this<WorkPlane>\n{\n  gp_Ax3 axes;\n  gp_Ax2d localpos;\n  gp_Pnt2d startpnt;\n  TopoDS_Vertex lastvertex, startvertex;\n  Handle(Geom_Surface) surf;\n  // Geom_Plane surf;\n\n  BRepBuilderAPI_MakeWire wire_builder;\n  std::vector<TopoDS_Wire> wires;\n  \npublic:\n  \n  WorkPlane (const gp_Ax3 & _axes, const gp_Ax2d _localpos = gp_Ax2d())\n    : axes(_axes), localpos(_localpos) // , surf(_axis) \n  {\n    // surf = GC_MakePlane (gp_Ax1(axis.Location(), axis.Direction()));\n    surf = new Geom_Plane(axes);\n  }\n\n\n  auto Finish()\n  {\n    if (!startvertex.IsNull())\n      {\n        wires.push_back (wire_builder.Wire());\n        wire_builder = BRepBuilderAPI_MakeWire();\n        startvertex.Nullify();\n      }\n    return shared_from_this();            \n  }\n\n  auto StartPnt() const {\n      return startpnt;\n  }\n\n  auto CurrentLocation() const\n  {\n    return localpos.Location();\n  }\n\n  auto CurrentDirection() const\n  {\n      return gp_Vec2d(localpos.Direction());\n  }\n\n  auto MoveTo (double h, double v)\n  {\n    startpnt = gp_Pnt2d(h,v);\n    localpos.SetLocation(startpnt);\n    startvertex.Nullify();\n    return shared_from_this();\n  }\n\n  auto Move(double len)\n  {\n    gp_Dir2d dir = localpos.Direction();\n    gp_Pnt2d oldp = localpos.Location();\n    auto newp = oldp.Translated(len*dir);\n    return MoveTo(newp.X(), newp.Y());\n  }\n  \n  auto Direction (double h, double v)\n  {\n    localpos.SetDirection(gp_Dir2d(h,v));\n    return shared_from_this();\n  }\n  \n  auto LineTo (double h, double v, optional<string> name = nullopt)\n  {\n    gp_Pnt2d old2d = localpos.Location();\n    gp_Pnt oldp = axes.Location() . Translated(old2d.X() * axes.XDirection() + old2d.Y() * axes.YDirection());\n\n    // localpos.Translate (gp_Vec2d(h,v));\n    localpos.SetLocation (gp_Pnt2d(h,v));\n    gp_Pnt2d new2d = localpos.Location();\n    gp_Pnt newp = axes.Location() . Translated(new2d.X() * axes.XDirection() + new2d.Y() * axes.YDirection());\n\n    if (new2d.Distance(old2d) < 1e-10) return shared_from_this();    \n    bool closing = new2d.Distance(startpnt) < 1e-10;\n\n      \n    cout << IM(6) << \"lineto, oldp = \" << occ2ng(oldp) << endl;\n    cout << IM(6) << \"lineto, newp = \" << occ2ng(newp) << endl;\n    gp_Pnt pfromsurf = surf->Value(new2d.X(), new2d.Y());\n    cout << IM(6) << \"p from plane = \" << occ2ng(pfromsurf) << endl;\n    \n    Handle(Geom_TrimmedCurve) curve = GC_MakeSegment(oldp, newp);\n\n    if (startvertex.IsNull())\n      startvertex = lastvertex = BRepBuilderAPI_MakeVertex(oldp);\n    auto endv = closing ? startvertex : BRepBuilderAPI_MakeVertex(newp);\n    // liefert noch Fehler bei close\n    auto edge = BRepBuilderAPI_MakeEdge(curve, lastvertex, endv).Edge();\n    lastvertex = endv;\n\n    // auto edge = BRepBuilderAPI_MakeEdge(curve).Edge();\n    if (name)\n      OCCGeometry::GetProperties(edge).name = name;\n    wire_builder.Add(edge);\n\n    if (closing) Finish();\n    return shared_from_this();    \n  }\n\n  auto Line(double h, double v, optional<string> name = nullopt)\n  {\n    gp_Pnt2d oldp = localpos.Location();\n    oldp.Translate(gp_Vec2d(h,v));\n    return LineTo (oldp.X(), oldp.Y(), name);\n  }\n  \n  auto Line(double len, optional<string> name = nullopt)\n  {\n    gp_Dir2d dir = localpos.Direction();\n    cout << IM(6) << \"dir = \" << dir.X() << \", \" << dir.Y() << endl;\n    gp_Pnt2d oldp = localpos.Location();\n    oldp.Translate(len*dir);\n    return LineTo (oldp.X(), oldp.Y(), name);\n  }\n\n  auto Rotate (double angle)\n  {\n    localpos.Rotate(localpos.Location(), angle*M_PI/180);\n    return shared_from_this();\n  }\n\n  auto Spline(const std::vector<gp_Pnt2d> &points, bool periodic, double tol, const std::map<int, gp_Vec2d> &tangents,\n              bool start_from_localpos, std::optional<string> name)\n  {\n    gp_Pnt2d P1 = start_from_localpos ? localpos.Location() : points.front();\n    gp_Pnt P13d = surf->Value(P1.X(), P1.Y());\n\n    gp_Pnt2d PLast = points.back();\n    gp_Pnt PLast3d = surf->Value(PLast.X(), PLast.Y());\n\n    Handle(TColgp_HArray1OfPnt2d) allpoints;\n    if (start_from_localpos)\n      {\n        if (points.front().Distance(P1) <= tol)\n          throw Exception(\"First item of given list of points is too close to current position (distance <= tol).\");\n        allpoints = new TColgp_HArray1OfPnt2d(1, points.size() + 1);\n        allpoints->SetValue(1, P1);\n        for (int i = 0; i < points.size(); i++)\n          allpoints->SetValue(i + 2, points[i]);\n      }\n    else\n      {\n        allpoints = new TColgp_HArray1OfPnt2d(1, points.size());\n        for (int i = 0; i < points.size(); i++)\n          allpoints->SetValue(i + 1, points[i]);\n      }\n\n    Geom2dAPI_Interpolate builder(allpoints, periodic, tol);\n\n    if (tangents.size() > 0)\n      {\n        const gp_Vec2d dummy_vec = tangents.begin()->second;\n        TColgp_Array1OfVec2d tangent_vecs(1, allpoints->Length());\n        Handle(TColStd_HArray1OfBoolean) tangent_flags = new TColStd_HArray1OfBoolean(1, allpoints->Length());\n        for (int i : Range(allpoints->Length()))\n          {\n            if (tangents.count(i) > 0)\n              {\n                tangent_vecs.SetValue(i+1, tangents.at(i));\n                tangent_flags->SetValue(i+1, true);\n              }\n            else\n              {\n                tangent_vecs.SetValue(i+1, dummy_vec);\n                tangent_flags->SetValue(i+1, false);\n              }\n          }\n        builder.Load(tangent_vecs, tangent_flags);\n      }\n\n\n    builder.Perform();\n    auto curve2d = builder.Curve();\n\n    const bool closing = periodic || PLast.Distance(startpnt) < 1e-10;\n    if (startvertex.IsNull())\n        startvertex = lastvertex = BRepBuilderAPI_MakeVertex(P13d).Vertex();\n    auto endv = closing ? startvertex : BRepBuilderAPI_MakeVertex(PLast3d).Vertex();\n\n    //create 3d edge from 2d curve using surf\n    auto edge = BRepBuilderAPI_MakeEdge(curve2d, surf, lastvertex, endv).Edge();\n    lastvertex = endv;\n    BRepLib::BuildCurves3d(edge);\n    wire_builder.Add(edge);\n    if(name.has_value())\n      OCCGeometry::GetProperties(edge).name = name;\n\n    // update localpos\n    localpos.SetLocation(PLast);\n\n    //compute angle of rotation\n    //compute tangent t2 in PLast\n    const auto dir = localpos.Direction();\n    gp_Vec2d t = gp_Vec2d(dir.X(), dir.Y());\n    gp_Vec2d t2 = curve2d->DN(curve2d->LastParameter(), 1);\n\n    double angle = t.Angle(t2);    //angle \\in [-pi,pi]\n    \n    //update localpos.Direction()\n    Rotate(angle*180/M_PI);\n\n    if (closing)\n        Finish();\n\n    return shared_from_this();\n  }\n\n  auto ArcTo (double h, double v, const gp_Vec2d t, optional<string> name=nullopt,\n              optional<double> maxh=nullopt)\n  {\n    gp_Pnt2d P1 = localpos.Location();\n\n    //check input\n    if(P1.X() == h && P1.Y() == v)\n        throw Exception(\"points P1 and P2 must not be congruent\");\n\n    localpos.SetLocation (gp_Pnt2d(h,v));\n    gp_Pnt2d P2 = localpos.Location();\n\n    cout << IM(6) << \"ArcTo:\" << endl;\n    cout << IM(6) << \"P1 = (\" << P1.X() <<\", \" << P1.Y() << \")\"<<endl;\n    cout << IM(6) << \"P2 = (\" << P2.X() <<\", \" << P2.Y() << \")\"<<endl;\n    cout << IM(6) << \"t = (\" << t.X() << \", \" << t.Y() << \")\" << endl;\n\n    //compute circle center point M\n    //point midway between p1 and p2\n    gp_Pnt2d P12 = gp_Pnt2d((P1.X() + h) / 2, (P1.Y() + v) / 2);\n    //vector normal to vector from P1 to P12\n    gp_Vec2d p12n = gp_Vec2d( - (P12.Y() - P1.Y()), (P12.X() - P1.X()));\n    //M is intersection of p12n and tn (tn ... normalvector to t)\n    double k = ((P12.Y()- P1.Y())*p12n.X() + (P1.X() - P12.X())*p12n.Y() )/ (t.X()*p12n.X() + t.Y()*p12n.Y());\n    gp_Pnt2d M = gp_Pnt2d(P1.X()-k*t.Y(), P1.Y() + k*t.X());\n\n    cout << IM(6) << \"P12 = (\" << P12.X() <<\", \" << P12.Y() << \")\"<<endl;\n    cout << IM(6) << \"p12n = (\" << p12n.X() <<\", \" << p12n.Y() << \")\"<<endl;\n    cout << IM(6) << \"k = \" << k <<endl;\n    cout << IM(6) << \"M = (\" << M.X() <<\", \" << M.Y() << \")\"<<endl;\n\n    //radius\n    double r = P1.Distance(M);\n\n    //compute point P3 on circle between P1 and P2\n    p12n.Normalize();   //docu: reverses direction of p12n ??\n    cout << IM(6) << \"p12n = (\" << p12n.X() <<\", \" << p12n.Y() << \")\"<<endl;\n\n    gp_Pnt2d P3;\n\n    double angletp12n = t.Angle(p12n);\n    if(angletp12n > -M_PI/2 && angletp12n < M_PI/2)\n        P3 = gp_Pnt2d(M.X() + r * p12n.X() , M.Y() + r * p12n.Y());\n    else\n        P3 = gp_Pnt2d(M.X() - r * p12n.X() , M.Y() - r * p12n.Y());\n\n    cout << IM(6) << \"r = \" << r <<endl;\n    cout << IM(6) << \"angle t,p12n = \" << t.Angle(p12n)<<endl;\n    cout << IM(6) << \"P3 = (\" << P3.X() <<\", \" << P3.Y() << \")\"<<endl;\n    cout << IM(6) << \"dist(M,P3) = \" << P3.Distance(M) <<endl;\n\n    //Draw 2d arc of circle from P1 to P2 through P3\n    Handle(Geom2d_TrimmedCurve) curve2d = GCE2d_MakeArcOfCircle(P1, P3, P2).Value();\n\n    gp_Pnt P13d = surf->Value(P1.X(), P1.Y());\n    gp_Pnt P23d = surf->Value(P2.X(), P2.Y());\n    cout << IM(6) << \"p13d = \" << occ2ng(P13d) << \", p23d = \" << occ2ng(P23d) << endl;\n    bool closing = P2.Distance(startpnt) < 1e-10;\n    if (startvertex.IsNull())\n      startvertex = lastvertex = BRepBuilderAPI_MakeVertex(P13d);\n    auto endv = closing ? startvertex : BRepBuilderAPI_MakeVertex(P23d);\n\n    //create 3d edge from 2d curve using surf\n    auto edge = BRepBuilderAPI_MakeEdge(curve2d, surf, lastvertex, endv).Edge();\n    lastvertex = endv;\n    BRepLib::BuildCurves3d(edge);\n    if(name.has_value())\n      OCCGeometry::GetProperties(edge).name = name;\n    if(maxh.has_value())\n      OCCGeometry::GetProperties(edge).maxh = maxh.value();\n    wire_builder.Add(edge);\n\n    //compute angle of rotation\n    //compute tangent t2 in P2\n    gp_Vec2d p2 = gp_Vec2d(P1.X()-P2.X(),P1.Y()-P2.Y());\n    gp_Vec2d t2;\n    if(t.Angle(p2) >=0)\n        t2 = gp_Vec2d((P2.Y()-M.Y()),-(P2.X()-M.X()));\n    else\n        t2 = gp_Vec2d(-(P2.Y()-M.Y()),(P2.X()-M.X()));\n    double angle = -t2.Angle(t);    //angle \\in [-pi,pi]\n\n    //update localpos.Direction()\n    Rotate(angle*180/M_PI);\n    if (closing)\n      Finish();\n\n    return shared_from_this();\n  }\n\n  auto Arc(double radius, double angle, optional<string> name,\n           optional<double> maxh)\n  {\n    double newAngle = fmod(angle,360)*M_PI/180;\n\n    //check input\n    if(newAngle<1e-16 && newAngle>-1e-16)\n        throw Exception(\"angle must not be an integer multiple of 360\");\n\n    gp_Dir2d dir = localpos.Direction();\n    gp_Dir2d dirn;\n    //compute center point of arc\n    if(newAngle>=0)\n        dirn = gp_Dir2d(-dir.Y(),dir.X());\n    else\n        dirn = gp_Dir2d(dir.Y(),-dir.X());\n\n    gp_Pnt2d oldp = localpos.Location();\n\n    oldp.Translate(radius*dirn);\n\n    cout << IM(6) << \"M = (\" << oldp.X() << \", \" << oldp.Y() << \")\" << endl;\n\n    dirn.Rotate(newAngle-M_PI);\n    oldp.Translate(radius*dirn);\n\n    //compute tangent vector in P1\n    gp_Vec2d t = gp_Vec2d(dir.X(),dir.Y());\n\n    cout << IM(6) << \"t = (\" << t.X() << \", \" << t.Y() << \")\" << endl;\n\n    //add arc\n    return ArcTo (oldp.X(), oldp.Y(), t, name, maxh);\n  }\n\n  auto Rectangle (double l, double w, optional<string> name)\n  {\n    Line (l, name);\n    Rotate (90);\n    Line(w, name);\n    Rotate (90);\n    Line (l, name);\n    Rotate (90);\n    Line(w, name);\n    Rotate (90);\n    return shared_from_this();            \n  }\n\n  auto RectangleCentered (double l, double w, optional<string> name)\n  {\n    Move(-l/2);\n    Rotate(-90);\n    Move(w/2);\n    Rotate(90);\n    Rectangle(l,w, name);\n    Rotate(-90);\n    Move(-w/2);\n    Rotate(90);\n    Move(l/2);\n    return shared_from_this();                \n  }\n\n  \n  auto Circle(double x, double y,  double r)\n  {\n    /*\n    MoveTo(x+r, y);\n    Direction (0, 1);\n    Arc(r, 180);\n    Arc(r, 180);\n    // wires.push_back (wire_builder.Wire());\n    // wire_builder = BRepBuilderAPI_MakeWire();\n    return shared_from_this();            \n    */\n    \n    gp_Pnt2d p(x,y);\n    Handle(Geom2d_Circle) circ_curve = GCE2d_MakeCircle(p, r).Value();\n    \n    auto edge = BRepBuilderAPI_MakeEdge(circ_curve, surf).Edge();\n    BRepLib::BuildCurves3d(edge);\n\n    wire_builder.Add(edge);\n    wires.push_back (wire_builder.Wire());\n    wire_builder = BRepBuilderAPI_MakeWire();\n    return shared_from_this();    \n  }\n\n  auto Ellipse(double major, double minor)\n  {\n    Handle(Geom2d_Ellipse) ell_curve = GCE2d_MakeEllipse(localpos, major, minor).Value();\n\n    auto edge = BRepBuilderAPI_MakeEdge(ell_curve, surf).Edge();\n    BRepLib::BuildCurves3d(edge);\n\n    wire_builder.Add(edge);\n    wires.push_back (wire_builder.Wire());\n    wire_builder = BRepBuilderAPI_MakeWire();\n    return shared_from_this();\n  }\n\n  auto NameVertex (string name)\n  {\n    if (!lastvertex.IsNull())\n      OCCGeometry::GetProperties(lastvertex).name = name;\n    return shared_from_this();\n  }\n\n  auto Circle (double r)\n  {\n    gp_Pnt2d pos = localpos.Location();\n    return Circle (pos.X(), pos.Y(), r);\n  }\n  \n  shared_ptr<WorkPlane> Close (optional<string> name = nullopt)\n  {\n    if (startpnt.Distance(localpos.Location()) > 1e-10)\n      {\n        LineTo (startpnt.X(), startpnt.Y(), name);\n        return shared_from_this();                    \n      }\n\n    if (!startvertex.IsNull())\n      Finish();\n    return shared_from_this();            \n  }\n  \n  auto Reverse()\n  {\n    wires.back().Reverse();\n    return shared_from_this();                \n  }\n  \n  auto Offset(double d)\n  {\n    Finish();\n    TopoDS_Wire wire = wires.back();\n    wires.pop_back();\n\n    // handle wires containing a single edge correctly, see\n    // https://dev.opencascade.org/content/brepoffsetapimakeoffset-open-topodswire\n    BRepBuilderAPI_MakeFace makeFace{gp_Pln{axes}};\n    makeFace.Add(wire);\n    BRepOffsetAPI_MakeOffset builder(makeFace.Face());\n    builder.Perform(d);\n    auto shape = builder.Shape();\n    wires.push_back (TopoDS::Wire(shape));\n    return shared_from_this();\n  }\n  \n  optional<TopoDS_Wire> Last()\n  {\n    return wires.empty() ?\n                         optional<TopoDS_Wire>{} :\n                         optional<TopoDS_Wire>{wires.back()};\n  }\n\n  TopoDS_Face Face()\n  {\n    BRepBuilderAPI_MakeFace builder(surf, 1e-8);\n    for (auto w : wires)\n      builder.Add(w);\n    wires.clear();\n    return builder.Face();\n  }\n\n  auto Wires()\n  {\n    ListOfShapes ws;\n    for (auto w : wires)\n      ws.push_back(w);\n    return ws;\n  }\n};\n\n\n\nDLL_HEADER void ExportNgOCCShapes(py::module &m) \n{\n  py::enum_<TopAbs_ShapeEnum>(m, \"TopAbs_ShapeEnum\", \"Enumeration of all supported TopoDS_Shapes\")\n    .value(\"COMPOUND\", TopAbs_COMPOUND)   .value(\"COMPSOLID\", TopAbs_COMPSOLID)\n    .value(\"SOLID\", TopAbs_SOLID)       .value(\"SHELL\", TopAbs_SHELL)\n    .value(\"FACE\", TopAbs_FACE)         .value(\"WIRE\", TopAbs_WIRE)\n    .value(\"EDGE\", TopAbs_EDGE) .value(\"VERTEX\", TopAbs_VERTEX)\n    .value(\"SHAPE\", TopAbs_SHAPE)\n    .export_values()\n    ;\n  \n  m.def(\"ResetGlobalShapeProperties\", [] () {\n    OCCGeometry::global_shape_properties.clear();\n    OCCGeometry::global_shape_property_indices.Clear();\n  }, \"Clear cached OpenCascade shape property metadata stored by Netgen.\");\n\n  struct SwigTypeInfo\n  {\n    const char* name;  // SWIG's type name string\n    // Other fields...\n  };\n\n  struct SwigPyObject{\n    PyObject_HEAD\n    void *ptr;\n    SwigTypeInfo* ty; // SWIG type information\n    int own; // ownership flag\n  };\n\n  m.def(\"From_PyOCC\", [](py::object shape)\n  {\n    py::object py_this = shape.attr(\"this\");\n    PyObject* obj = py_this.ptr();\n    SwigPyObject* swig_obj = reinterpret_cast<SwigPyObject*>(obj);\n    if (!swig_obj->ptr || !swig_obj->ty || !swig_obj->ty->name) {\n        throw std::runtime_error(\"SWIG object does not contain a valid pointer\");\n    }\n    if(strcmp(swig_obj->ty->name, \"_p_TopoDS_Shape\") != 0)\n      throw std::runtime_error(\"Does not contain TopoDS_Shape from pyocc!\");\n    return py::cast(static_cast<TopoDS_Shape*>(swig_obj->ptr));\n  }, py::return_value_policy::reference, py::keep_alive<0,1>(),\n  \"Convert a PyOCC SWIG-wrapped TopoDS_Shape into a Netgen TopoDS_Shape view without copying.\");\n  \n  py::class_<TopoDS_Shape> (m, \"TopoDS_Shape\")\n    .def(\"__str__\", [] (const TopoDS_Shape & shape)\n         {\n           stringstream str;\n#ifdef OCC_HAVE_DUMP_JSON\n           shape.DumpJson(str);\n#endif // OCC_HAVE_DUMP_JSON\n           return str.str();\n         })\n    .def(\"GenerateMesh\", [](TopoDS_Shape & shape,\n                            MeshingParameters* pars, int dim,\n                            bool ngs_mesh, py::kwargs kwargs)\n    {\n      auto geo = py::cast(make_shared<OCCGeometry>(shape, dim));\n      auto mesh = geo.attr(\"GenerateMesh\")(**kwargs);\n      if(!ngs_mesh)\n        return mesh;\n      try\n        {\n          auto ngsolve = py::module::import(\"ngsolve\");\n          return ngsolve.attr(\"Mesh\")(mesh);\n        }\n      catch (py::import_error &)\n        {\n          throw Exception(\"ngsolve module not found, cannot convert to ngsolve mesh, you can use 'ngs_mesh=False' to return a Netgen mesh instead\");\n        }\n    }, py::arg(\"mp\")=nullptr, py::arg(\"dim\")=3, py::arg(\"ngs_mesh\")=true,\n       \"Generate a mesh for the shape. Returns an NGSolve mesh if ngs_mesh=True, \"\n       \"otherwise a Netgen mesh. Extra keyword arguments are forwarded to OCCGeometry.GenerateMesh.\")\n    .def(\"ShapeType\", [] (const TopoDS_Shape & shape)\n         {\n           throw Exception (\"use 'shape.type' instead of 'shape.ShapeType()'\");\n         }, \"deprecated, use 'shape.type' instead\")\n    \n    .def_property_readonly(\"type\", [](const TopoDS_Shape & shape)\n                           { return shape.ShapeType(); }, \"returns type of shape, i.e. 'EDGE', 'FACE', ...\")    \n    \n    .def(\"SubShapes\", [] (const TopoDS_Shape & shape, TopAbs_ShapeEnum & type)\n         {\n           ListOfShapes sub;\n           for (TopExp_Explorer e(shape, type); e.More(); e.Next())\n             sub.push_back(e.Current());\n           return sub;\n         }, py::arg(\"type\"), \"returns list of sub-shapes of type 'type'\")\n    \n    .def_property_readonly(\"solids\", GetSolids,\n            \"returns all sub-shapes of type 'SOLID'\")\n    .def_property_readonly(\"shells\", GetShells,\n            \"returns all sub-shapes of type 'SHELL'\")\n    .def_property_readonly(\"faces\", GetFaces,\n            \"returns all sub-shapes of type 'FACE'\")\n    .def_property_readonly(\"edges\", GetEdges,\n            \"returns all sub-shapes of type 'EDGE'\")\n    .def_property_readonly(\"wires\", GetWires,\n                           \"returns all sub-shapes of type 'WIRE'\")\n    .def_property_readonly(\"vertices\", GetVertices,\n            \"returns all sub-shapes of type 'VERTEX'\")\n    .def_property_readonly(\"bounding_box\", [] ( const TopoDS_Shape &shape )\n            {\n               auto box = GetBoundingBox(shape);\n               return py::make_tuple( ng2occ(box.PMin()), ng2occ(box.PMax()) );\n            }, \"returns bounding box (pmin, pmax)\")\n\n    .def(\"LimitTolerance\", [](TopoDS_Shape& self, double tmin,\n                              double tmax, TopAbs_ShapeEnum type)\n    {\n      ShapeFix_ShapeTolerance fix;\n      fix.LimitTolerance(self, tmin, tmax, type);\n    }, py::arg(\"tmin\"), py::arg(\"tmax\")=0., py::arg(\"type\")=TopAbs_SHAPE,\n         \"limit tolerance of shape to range [tmin, tmax]\")\n    .def(\"SetTolerance\", [](TopoDS_Shape& self, double tol,\n                            TopAbs_ShapeEnum stype)\n    {\n      ShapeFix_ShapeTolerance fix;\n      fix.SetTolerance(self, tol, stype);\n    }, py::arg(\"tol\"), py::arg(\"stype\")=TopAbs_SHAPE, \"set (enforce) tolerance of shape to 't'\")\n\n    .def(\"Properties\", [] (const TopoDS_Shape & shape)\n         {\n           auto props = Properties(shape);\n           return tuple( py::cast(props.Mass()), py::cast(props.CentreOfMass()) );\n         }, \"returns tuple of shape properties, currently ('mass', 'center'\")\n    \n    .def_property_readonly(\"center\", [](const TopoDS_Shape & shape) {\n           return Center(shape);\n      }, \"returns center of gravity of shape\")\n    \n    .def_property_readonly(\"mass\", [](const TopoDS_Shape & shape) {\n           return Mass(shape);\n      }, \"returns mass of shape, what is length, face, or volume\")\n\n    .def_property_readonly(\"inertia\", [](const TopoDS_Shape & shape) {\n           return Properties(shape).MatrixOfInertia();           \n      }, \"returns matrix of inertia of shape\")\n    \n    .def(\"Move\", [](const TopoDS_Shape & shape, const gp_Vec v)\n         {\n           // which one to choose ? \n           // version 1: Transoformation\n           gp_Trsf trafo;\n           trafo.SetTranslation(v);\n           BRepBuilderAPI_Transform builder(shape, trafo, true);\n           PropagateProperties(builder, shape, occ2ng(trafo));\n           return CastShape(builder.Shape());\n           // version 2: change location\n           // ...\n         }, py::arg(\"v\"), \"copy shape, and translate copy by vector 'v'\")\n\n\n    .def(\"Rotate\", [](const TopoDS_Shape & shape, const gp_Ax1 ax, double ang)\n         {\n           gp_Trsf trafo;\n           trafo.SetRotation(ax, ang*M_PI/180);            \n           BRepBuilderAPI_Transform builder(shape, trafo, true);\n           PropagateProperties(builder, shape, occ2ng(trafo));\n           return builder.Shape();\n         }, py::arg(\"axis\"), py::arg(\"ang\"),\n         \"copy shape, and rotet copy by 'ang' degrees around 'axis'\")\n\n    .def(\"Mirror\", [] (const TopoDS_Shape & shape, const gp_Ax3 & ax)\n         {\n           gp_Trsf trafo;\n           trafo.SetMirror(ax.Ax2());\n           BRepBuilderAPI_Transform builder(shape, trafo, true);\n           PropagateProperties(builder, shape, occ2ng(trafo));\n           return builder.Shape();\n         }, py::arg(\"axes\"),\n         \"copy shape, and mirror over XY - plane defined by 'axes'\")\n    \n    .def(\"Mirror\", [] (const TopoDS_Shape & shape, const gp_Ax1 & ax)\n         {\n           gp_Trsf trafo;\n           trafo.SetMirror(ax);\n           BRepBuilderAPI_Transform builder(shape, trafo, true);\n           PropagateProperties(builder, shape, occ2ng(trafo));\n           return builder.Shape();\n         }, py::arg(\"axes\"),\n         \"copy shape, and rotate by 180 deg around axis 'axis'\")\n    \n    .def(\"Scale\", [](const TopoDS_Shape & shape, const gp_Pnt p, double s)\n         {\n           gp_Trsf trafo;\n           trafo.SetScale(p, s);\n           BRepBuilderAPI_Transform builder(shape, trafo, true);\n           PropagateProperties(builder, shape, occ2ng(trafo));\n           return builder.Shape();\n         }, py::arg(\"p\"), py::arg(\"s\"),\n         \"copy shape, and scale copy by factor 's'\")\n\n    .def(\"WriteStep\", [](const TopoDS_Shape & shape, string & filename)\n            { step_utils::WriteSTEP(shape, filename); }\n         , py::arg(\"filename\"), \"export shape in STEP - format\")\n    .def(\"WriteBrep\", [](const TopoDS_Shape & shape, const string& filename,\n                         bool withTriangles, bool withNormals,\n                         optional<int> version, bool binary)\n    {\n      if(binary)\n        {\n#if NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n          BinTools_FormatVersion v = version ? BinTools_FormatVersion(*version) : BinTools_FormatVersion_CURRENT;\n          BinTools::Write(shape, filename.c_str(), withTriangles, withNormals, v);\n# else // NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n          throw Exception(\"Binary BREP export not supported in this version of OpenCascade\");\n#endif // NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n        }\n      else\n        {\n#if NETGEN_OCC_VERSION_AT_LEAST(7, 6)\n          TopTools_FormatVersion v = version ? (TopTools_FormatVersion)(*version) : TopTools_FormatVersion_CURRENT;\n          BRepTools::Write(shape, filename.c_str(), withTriangles, withNormals, v);\n#else // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6\n          BRepTools::Write(shape, filename.c_str());\n#endif // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6\n        }\n    }, py::arg(\"filename\"), py::arg(\"withTriangles\")=true,\n       py::arg(\"withNormals\")=false,\n         py::arg(\"version\")=py::none(),\n         py::arg(\"binary\")=false,\n       \"export shape in BREP - format\")\n    .def(\"bc\", [](const TopoDS_Shape & shape, const string & name)\n         {\n           for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())\n             OCCGeometry::GetProperties(e.Current()).name = name;\n           return shape;\n         }, py::arg(\"name\"), \"sets 'name' property for all faces of shape\")\n\n    .def(\"mat\", [](const TopoDS_Shape & shape, const string & name)\n         {\n           for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next())\n             OCCGeometry::GetProperties(e.Current()).name = name;\n           return shape;\n         }, py::arg(\"name\"), \"sets 'name' property to all solids of shape\")\n    \n    .def_property(\"name\", [](const TopoDS_Shape & self) -> optional<string> {\n        CheckValidPropertyType(self);\n        if (auto name = OCCGeometry::GetProperties(self).name)\n          return *name;\n        else\n          return nullopt;\n      }, [](const TopoDS_Shape & self, optional<string> name) {\n        for (auto & s : GetHighestDimShapes(self))\n          OCCGeometry::GetProperties(s).name = name;\n      }, \"'name' of shape\")\n    \n    .def_property(\"maxh\",\n                  [](const TopoDS_Shape& self)\n                  {\n                    CheckValidPropertyType(self);\n                    return OCCGeometry::GetProperties(self).maxh;\n                  },\n                  [](TopoDS_Shape& self, double val)\n                  {\n                    for(auto & s : GetHighestDimShapes(self))\n                      OCCGeometry::GetProperties(s).maxh = val;\n                  }, \"maximal mesh-size for shape\")\n    \n    .def_property(\"hpref\",\n                  [](const TopoDS_Shape& self)\n                  {\n                    CheckValidPropertyType(self);\n                    return OCCGeometry::GetProperties(self).hpref;\n                  },\n                  [](TopoDS_Shape& self, double val)\n                  {\n                    for(auto & s : GetHighestDimShapes(self))\n                      OCCGeometry::GetProperties(s).hpref = val;\n                  }, \"number of refinement levels for geometric refinement\")\n    \n    .def_property(\"col\", [](const TopoDS_Shape & self) -> py::object {\n      CheckValidPropertyType(self);\n      if(!OCCGeometry::HaveProperties(self) || !OCCGeometry::GetProperties(self).col)\n        return py::none();\n      auto col = *OCCGeometry::GetProperties(self).col;\n      return py::cast(std::vector<double>({ col(0), col(1), col(2), col(3) }));\n    }, [](const TopoDS_Shape & self, std::optional<std::vector<double>> c) {\n      if(c.has_value())\n        {\n          Vec<4> col((*c)[0], (*c)[1], (*c)[2], 1.0);\n          if(c->size() == 4)\n            col[3] = (*c)[3];\n          for(auto & s : GetHighestDimShapes(self))\n            OCCGeometry::GetProperties(s).col = col;\n        }\n      else\n        for(auto & s : GetHighestDimShapes(self))\n          OCCGeometry::GetProperties(s).col = nullopt;\n      }, \"color of shape as RGB or RGBA - tuple\")\n    .def_property(\"layer\", [](const TopoDS_Shape& self) {\n    if (!OCCGeometry::HaveProperties(self))\n      return 1;\n    return OCCGeometry::GetProperties(self).layer;\n    }, [](const TopoDS_Shape& self, int layer) {\n    OCCGeometry::GetProperties(self).layer = layer;\n    for(auto & s : GetHighestDimShapes(self))\n      OCCGeometry::GetProperties(s).layer = layer;\n    }, \"layer of shape\")\n    .def(\"UnifySameDomain\", [](const TopoDS_Shape& shape,\n                               bool edges, bool faces,\n                               bool concatBSplines)\n    {\n      ShapeUpgrade_UnifySameDomain unify(shape, edges, faces,\n                                         concatBSplines);\n      unify.Build();\n      Handle(BRepTools_History) history = unify.History ();\n      for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n        for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n          {\n            auto prop = OCCGeometry::GetProperties(e.Current());\n            for (auto mods : history->Modified(e.Current()))\n              OCCGeometry::GetProperties(mods).Merge(prop);\n          }\n      return unify.Shape();\n    }, py::arg(\"unifyEdges\")=true, py::arg(\"unifyFaces\")=true,\n         py::arg(\"concatBSplines\")=true,\n         \"Unify edges and/or faces that lie on the same geometric domain \"\n         \"(ShapeUpgrade_UnifySameDomain) and propagate shape properties.\")\n    \n    .def_property(\"location\",\n                  [](const TopoDS_Shape & shape) { return shape.Location(); },\n                  [](TopoDS_Shape & shape, const TopLoc_Location & loc)\n                  { shape.Location(loc); }, \"Location of shape\")\n    .def(\"Located\", [](const TopoDS_Shape & shape, const TopLoc_Location & loc)\n         { return shape.Located(loc); }, py::arg(\"loc\"), \"copy shape and sets location of copy\")\n\n    .def(\"__add__\", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) {\n\n        BRepAlgoAPI_Fuse builder(shape1, shape2);\n        PropagateProperties (builder, shape1);\n        PropagateProperties (builder, shape2);\n        /*\n#ifdef OCC_HAVE_HISTORY\n        Handle(BRepTools_History) history = builder.History ();\n        \n        for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n          for (auto & s : { shape1, shape2 })\n            for (TopExp_Explorer e(s, typ); e.More(); e.Next())\n              {\n                auto prop = OCCGeometry::GetProperties(e.Current());\n                for (auto mods : history->Modified(e.Current()))\n                  OCCGeometry::GetProperties(mods).Merge(prop);\n              }\n#endif        \n        */\n        auto fused = builder.Shape();        \n        \n        // make one face when fusing in 2D\n        // from https://gitlab.onelab.info/gmsh/gmsh/-/issues/627\n        // int cntsolid = 0;\n        // for (TopExp_Explorer e(shape1, TopAbs_SOLID); e.More(); e.Next())\n        //   cntsolid++;\n        // for (TopExp_Explorer e(shape2, TopAbs_SOLID); e.More(); e.Next())\n        //   cntsolid++;\n        // if (cntsolid == 0)\n        //   {\n            ShapeUpgrade_UnifySameDomain unify(fused, true, true, true);\n            unify.Build();\n\n            // #ifdef OCC_HAVE_HISTORY\n            Handle(BRepTools_History) history = unify.History ();\n            \n            for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n              for (TopExp_Explorer e(fused, typ); e.More(); e.Next())\n                {\n                  auto prop = OCCGeometry::GetProperties(e.Current());\n                  for (auto mods : history->Modified(e.Current()))\n                    OCCGeometry::GetProperties(mods).Merge(prop);\n                }\n            // #endif        \n            // PropagateProperties (unify, fused);\n            \n            return unify.Shape();\n        //   }\n        // else\n        //   return fused;\n      }, \"fuses shapes\")\n    .def(\"__radd__\", [] (const TopoDS_Shape & shape, int i) // for sum([shapes])\n         { return shape; }, \"needed for Sum([shapes])\")\n    .def(\"__mul__\", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) {\n        \n        BRepAlgoAPI_Common builder(shape1, shape2);\n        /*\n#ifdef OCC_HAVE_HISTORY\n        Handle(BRepTools_History) history = builder.History ();\n\n        \n        for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n          for (auto & s : { shape1, shape2 })\n            for (TopExp_Explorer e(s, typ); e.More(); e.Next())\n              {\n                auto prop = OCCGeometry::GetProperties(e.Current());\n                for (auto mods : history->Modified(e.Current()))\n                  OCCGeometry::GetProperties(mods).Merge(prop);\n              }\n#endif // OCC_HAVE_HISTORY\n        */\n        PropagateProperties (builder, shape1);\n        PropagateProperties (builder, shape2);\n        \n        return builder.Shape();\n      }, \"common of shapes\")\n    \n    .def(\"__sub__\", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) {\n        \n        BRepAlgoAPI_Cut builder(shape1, shape2);\n        /*\n#ifdef OCC_HAVE_HISTORY        \n        Handle(BRepTools_History) history = builder.History ();\n        \n        for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n          for (auto & s : { shape1, shape2 })\n            for (TopExp_Explorer e(s, typ); e.More(); e.Next())\n              {\n                auto prop = OCCGeometry::GetProperties(e.Current());\n                for (auto mods : history->Modified(e.Current()))\n                  OCCGeometry::GetProperties(mods).Merge(prop);\n              }\n#endif // OCC_HAVE_HISTORY\n        */\n        PropagateProperties (builder, shape1);\n        PropagateProperties (builder, shape2);\n        \n        return builder.Shape();        \n      }, \"cut of shapes\")\n    .def(\"__eq__\", [] (const TopoDS_Shape& shape1, const TopoDS_Shape& shape2) {\n      return shape1.IsSame(shape2);\n    })\n    .def(\"__hash__\", [] (const TopoDS_Shape& shape) {\n      OCCGeometry::GetProperties(shape); // make sure it is in global properties\n      return OCCGeometry::global_shape_property_indices.FindIndex(shape);\n    })\n\n    .def(\"Reversed\", [](const TopoDS_Shape & shape) {\n        return CastShape(shape.Reversed()); }, \"Return a copy with the orientation reversed (TopoDS_Shape::Reversed).\")\n\n    .def(\"Extrude\", [](const TopoDS_Shape & shape, double h,\n                       optional<gp_Vec> dir, bool identify,\n                       Identifications::ID_TYPE idtype,\n                       string idname)\n    {\n        for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())\n          {\n            Handle(Geom_Surface) surf = BRep_Tool::Surface (TopoDS::Face(e.Current()));\n            gp_Vec edir;\n            if(dir.has_value())\n              edir = *dir;\n            else\n              {\n                gp_Vec du, dv;\n                gp_Pnt p;\n                surf->D1 (0,0,p,du,dv);\n                edir = du^dv;\n              }\n            BRepPrimAPI_MakePrism builder(shape, h*edir, false);\n            for (auto typ : { TopAbs_SOLID, TopAbs_FACE,\n                              TopAbs_EDGE, TopAbs_VERTEX })\n              for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n                {\n                  auto prop = OCCGeometry::GetProperties(e.Current());\n                  for (auto mods : builder.Generated(e.Current()))\n                    OCCGeometry::GetProperties(mods).Merge(prop);\n                }\n            if(identify)\n              {\n                Transformation<3> trsf(h * occ2ng(edir));\n                Identify(GetFaces(shape), GetFaces(builder.LastShape()),\n                         idname, idtype, trsf);\n            }\n            return builder.Shape();\n          }\n        if (!dir.has_value())\n          throw Exception(\"shape does not contain a face to determine extrusion direction, please provide 'dir' argument\");\n        gp_Vec edir = h * (*dir);\n        BRepPrimAPI_MakePrism builder(shape, edir, false);\n        for (auto typ : { TopAbs_SOLID, TopAbs_FACE,\n                          TopAbs_EDGE, TopAbs_VERTEX })\n          for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n            {\n              auto prop = OCCGeometry::GetProperties(e.Current());\n              for (auto mods : builder.Generated(e.Current()))\n                OCCGeometry::GetProperties(mods).Merge(prop);\n            }\n        return builder.Shape();\n    }, py::arg(\"h\"), py::arg(\"dir\")=nullopt, py::arg(\"identify\")=false,\n         py::arg(\"idtype\")=Identifications::CLOSESURFACES,\n         py::arg(\"idname\") = \"extrusion\",\n         \"extrude shape to thickness 'h', shape must contain a plane surface, optionally give an extrusion direction\")\n    \n    .def(\"Extrude\", [] (const TopoDS_Shape & face, gp_Vec vec) {\n      BRepPrimAPI_MakePrism builder(face, vec);\n      for (auto typ : { TopAbs_SOLID, TopAbs_FACE,\n                        TopAbs_EDGE, TopAbs_VERTEX })\n        for (TopExp_Explorer e(face, typ); e.More(); e.Next())\n          {\n            auto prop = OCCGeometry::GetProperties(e.Current());\n            for (auto mods : builder.Generated(e.Current()))\n              OCCGeometry::GetProperties(mods).Merge(prop);\n          }\n      return builder.Shape();\n      }, py::arg(\"v\"), \"extrude shape by vector 'v'\")\n\n  .def(\"Revolve\", [](const TopoDS_Shape & shape, const gp_Ax1 &A, const double D) {\n      // for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())\n        {\n          // return BRepPrimAPI_MakeRevol (shape, A, D*M_PI/180).Shape();\n          BRepPrimAPI_MakeRevol builder(shape, A, D*M_PI/180, true);\n            \n          for (auto typ : { TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX})\n            for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n              {\n                auto prop = OCCGeometry::GetProperties(e.Current());\n                for (auto mods : builder.Generated(e.Current()))\n                  OCCGeometry::GetProperties(mods).Merge(prop);\n              }\n\n          return builder.Shape();          \n        }\n        // throw Exception(\"no face found for revolve\");\n    }, py::arg(\"axis\"), py::arg(\"ang\"), \"revolve shape around 'axis' by 'ang' degrees\")\n    .def(\"CrossSection\", &CrossSection, py::arg(\"plane_axes\"),\n         \"Create cross section of shape with plane defined by 'plane_axes' and transfer properties to dim-1 entities\")\n    .def(\"MakeFillet\", [](const TopoDS_Shape& shape, const std::vector<std::pair<TopoDS_Shape, double>>& fillets) -> TopoDS_Shape\n    {\n      if (shape.ShapeType() == TopAbs_FACE) {\n        BRepFilletAPI_MakeFillet2d mkFillet2d(TopoDS::Face(shape));\n        for (auto [v, r] : fillets)\n          mkFillet2d.AddFillet(TopoDS::Vertex(v), r);\n        mkFillet2d.Build();\n        // TODO: CL I think we shouldn't do this here but, double check\n        // PropagateProperties (mkFillet2d, shape);\n        return mkFillet2d.Shape();\n      }\n        BRepFilletAPI_MakeFillet mkFillet(shape);\n        for (auto [e, r] : fillets)\n          mkFillet.Add(r, TopoDS::Edge(e));\n        mkFillet.Build();\n        PropagateProperties (mkFillet, shape);\n        for (auto [e, r] : fillets)\n          for (auto gen : mkFillet.Generated(e))\n            OCCGeometry::GetProperties(gen).name = \"fillet\";\n        return mkFillet.Shape();\n      }, py::arg(\"fillets\"), \"make fillets for shapes of radius 'r'\")\n    .def(\"MakeFillet\", [](const TopoDS_Shape & shape, std::vector<TopoDS_Shape> edges, double r) -> TopoDS_Shape {\n        if(shape.ShapeType() == TopAbs_FACE)\n        {\n          BRepFilletAPI_MakeFillet2d mkFillet(TopoDS::Face(shape));\n          for (auto e : edges)\n            mkFillet.AddFillet (TopoDS::Vertex(e), r);\n          mkFillet.Build();\n          // TODO: CL I think we shouldn't do this here but, double check\n          // PropagateProperties (mkFillet, shape);\n          return mkFillet.Shape();\n        }\n        BRepFilletAPI_MakeFillet mkFillet(shape);\n        for (auto e : edges)\n          mkFillet.Add (r, TopoDS::Edge(e));\n        mkFillet.Build();\n        PropagateProperties (mkFillet, shape);\n        for (auto e : edges)\n          for (auto gen : mkFillet.Generated(e))\n            OCCGeometry::GetProperties(gen).name = \"fillet\";\n        return mkFillet.Shape();\n      }, py::arg(\"edges\"), py::arg(\"r\"), \"make fillets for edges 'edges' of radius 'r'\")\n  \n    .def(\"MakeChamfer\", [](const TopoDS_Shape & shape, std::vector<TopoDS_Shape> edges, double d) {\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4        \n        BRepFilletAPI_MakeChamfer mkChamfer(shape);\n        for (auto e : edges)\n          mkChamfer.Add (d, TopoDS::Edge(e));\n        mkChamfer.Build();\n        PropagateProperties (mkChamfer, shape);\n        for (auto e : edges)\n          for (auto gen : mkChamfer.Generated(e))\n            OCCGeometry::GetProperties(gen).name = \"chamfer\";\n        return mkChamfer.Shape();\n#else\n        throw Exception(\"MakeChamfer not available for occ-version < 7.4\");\n#endif        \n      }, py::arg(\"edges\"), py::arg(\"d\"), \"make symmetric chamfer for edges 'edges' of distrance 'd'\")\n  \n    .def(\"MakeThickSolid\", [](const TopoDS_Shape & body, std::vector<TopoDS_Shape> facestoremove,\n                              double offset, double tol, bool intersection,\n                              string joinT, bool removeIntEdges) {\n           TopTools_ListOfShape faces;\n           for (auto f : facestoremove)\n             faces.Append(f);\n           \n           BRepOffsetAPI_MakeThickSolid maker;\n           GeomAbs_JoinType joinType;\n           if(joinT == \"arc\")\n             joinType = GeomAbs_Arc;\n           else if(joinT == \"intersection\")\n             joinType = GeomAbs_Intersection;\n           else\n             throw Exception(\"Only joinTypes 'arc' and 'intersection' exist!\");\n           maker.MakeThickSolidByJoin(body, faces, offset, tol,\n                                      BRepOffset_Skin, intersection,\n                                      false, joinType, removeIntEdges);\n           return maker.Shape();\n       }, py::arg(\"facestoremove\"), py::arg(\"offset\"), py::arg(\"tol\"),\n         py::arg(\"intersection\") = false,py::arg(\"joinType\")=\"arc\",\n         py::arg(\"removeIntersectingEdges\") = false,\n         \"makes shell-like solid from faces\")\n\n    .def(\"Offset\", [](const TopoDS_Shape & shape, \n                      double offset, double tol, bool intersection,\n                      string joinT, bool removeIntEdges, optional<string> identification_name) {\n           BRepOffsetAPI_MakeOffsetShape maker;\n           GeomAbs_JoinType joinType;\n           if(joinT == \"arc\")\n             joinType = GeomAbs_Arc;\n           else if(joinT == \"intersection\")\n             joinType = GeomAbs_Intersection;\n           else if(joinT == \"tangent\")\n            joinType = GeomAbs_Tangent;\n           else\n             throw Exception(\"Only joinTypes 'arc', 'intersection' and 'tangent' exist!\");\n           \n           maker.PerformByJoin(shape, offset, tol,\n                               BRepOffset_Skin, intersection,\n                               false, joinType, removeIntEdges);\n\n           // PropagateProperties (maker, shape);\n           for (auto typ : { TopAbs_FACE,  TopAbs_EDGE, TopAbs_VERTEX })\n             for (TopExp_Explorer e(shape, typ); e.More(); e.Next())\n               {\n                 auto s = e.Current();\n                 auto prop = OCCGeometry::GetProperties(s);\n                 for (auto mods : maker.Generated(s))\n                   {\n                     if(OCCGeometry::HaveProperties(s))\n                       {\n                         auto & new_props = OCCGeometry::GetProperties(mods);\n                         new_props.Merge(prop);\n                         if (prop.name) new_props.name = string(\"offset_\")+(*prop.name);\n                       }\n                     if(identification_name)\n                       {\n                         OCCIdentification ident;\n                         ident.from = s;\n                         ident.to = mods;\n                         ident.name = *identification_name;\n                         ident.type = Identifications::CLOSESURFACES;\n                         OCCGeometry::GetIdentifications(s).push_back(ident);\n                       }\n                   }\n               }\n           \n           return maker.Shape();\n       }, py::arg(\"offset\"), py::arg(\"tol\"),\n         py::arg(\"intersection\") = false,py::arg(\"joinType\")=\"arc\",\n         py::arg(\"removeIntersectingEdges\") = false,\n         py::arg(\"identification_name\") = nullopt,\n         \"makes shell-like solid from faces\")\n\n\n    \n    .def(\"MakeTriangulation\", [](const TopoDS_Shape & shape)\n         {\n           BuildTriangulation(shape);\n         }, \"Ensure all faces of the shape have an OpenCascade triangulation \"\n            \"(typically via BRepMesh). Useful before querying Poly_Triangulation \"\n            \"or exporting to viewers. See https://dev.opencascade.org/doc/refman/html/class_b_rep_mesh___incremental_mesh.html\")\n\n\n    .def(\"Identify\", py::overload_cast<const TopoDS_Shape &, const TopoDS_Shape &, string, Identifications::ID_TYPE, std::optional<std::variant<gp_Trsf, gp_GTrsf>>>(&Identify),\n            py::arg(\"other\"), py::arg(\"name\"),\n            py::arg(\"type\")=Identifications::PERIODIC, py::arg(\"trafo\")=nullopt,\n            \"Identify shapes for periodic meshing\")\n\n    .def(\"Distance\", [](const TopoDS_Shape& self,\n                        const TopoDS_Shape& other)\n    {\n      return BRepExtrema_DistShapeShape(self, other).Value();\n    }, \"Compute the minimum distance between two shapes using \"\n       \"BRepExtrema_DistShapeShape. See https://dev.opencascade.org/doc/refman/html/class_b_rep_extrema___dist_shape_shape.html\")\n    \n    .def(\"Triangulation\", [](const TopoDS_Shape & shape)\n         {\n           // extracted from vsocc.cpp\n           TopoDS_Face face;\n           try\n             {\n               face = TopoDS::Face(shape);\n             }\n           catch (Standard_Failure & e)\n             {\n               e.Print (cout);\n               throw NgException (\"Triangulation: shape is not a face\");\n             }\n\n           Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n\n           TopLoc_Location loc;\n           Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\n           \n           if (triangulation.IsNull())\n             {\n               BuildTriangulation(shape);\n               triangulation = BRep_Tool::Triangulation (face, loc);               \n             }\n           // throw Exception(\"Don't have a triangulation, call 'MakeTriangulation' first\");\n\n           int ntriangles = triangulation -> NbTriangles();\n           Array< std::array<Point<3>,3> > triangles;\n           for (int j = 1; j <= ntriangles; j++)\n             {\n               Poly_Triangle triangle = triangulation -> Triangle(j);\n               std::array<Point<3>,3> pts;\n               for (int k = 0; k < 3; k++)\n                 pts[k] = occ2ng( (triangulation -> Node(triangle(k+1))).Transformed(loc) );\n               triangles.Append ( pts );\n             }\n           \n           // return MoveToNumpyArray(triangles);\n           return triangles;\n         }, \"Extract the face triangulation (Poly_Triangulation) from OpenCascade. If missing, builds it first, then returns the triangle vertex coordinates.\")\n    .def(\"_webgui_data\", [](const TopoDS_Shape & shape)\n         {\n           [[maybe_unused]] auto status = BuildTriangulation(shape);\n           // cout << \"status = \" << aStatus << endl;\n           \n           std::vector<double> p[3];\n           std::vector<double> n[3];\n           py::list names, colors, solid_names;\n           std::vector<std::vector<int>> solid_face_map;\n\n           int index = 0;\n\n           Box<3> box(Box<3>::EMPTY_BOX);\n           TopTools_IndexedMapOfShape fmap;\n           for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())\n           {\n               TopoDS_Face face = TopoDS::Face(e.Current());\n               if(fmap.Contains(face)) continue;\n               // Handle(TopoDS_Face) face = e.Current();\n               fmap.Add(face);\n               ExtractFaceData(face, index, p, n, box);\n\n               ShapeProperties props;\n               if(OCCGeometry::HaveProperties(face))\n                 props = OCCGeometry::GetProperties(face);\n\n               auto c = props.GetColor();\n               colors.append(py::make_tuple(c[0], c[1], c[2], c[3]));\n               names.append(props.GetName());\n               index++;\n           }\n\n           for(auto& solid : GetSolids(shape))\n             {\n               std::vector<int> faces;\n               for(auto& face : GetFaces(solid))\n                 faces.push_back(fmap.FindIndex(face)-1);\n               solid_face_map.push_back(std::move(faces));\n               auto& props = OCCGeometry::GetProperties(solid);\n               if(props.name)\n                 solid_names.append(*props.name);\n               else\n                 solid_names.append(\"\");\n             }\n\n           std::vector<double> edge_p[2];\n           py::list edge_names, edge_colors;\n           index = 0;\n           for (TopExp_Explorer e(shape, TopAbs_EDGE); e.More(); e.Next())\n           {\n               TopoDS_Edge edge = TopoDS::Edge(e.Current());\n               ExtractEdgeData(edge, index, edge_p, box);\n               auto & props = OCCGeometry::GetProperties(edge);\n               if(props.col)\n               {\n                 auto & c = *props.col;\n                 edge_colors.append(py::make_tuple(c[0], c[1], c[2]));\n               }\n               else\n                   edge_colors.append(py::make_tuple(0.0, 0.0, 0.0));\n               if(props.name)\n               {\n                 edge_names.append(*props.name);\n               }\n               else\n                   edge_names.append(\"\");\n               index++;\n           }\n           \n           \n           auto center = box.Center();\n\n           py::list mesh_center;\n           mesh_center.append(center[0]);\n           mesh_center.append(center[1]);\n           mesh_center.append(center[2]);\n           py::dict data;\n           data[\"ngsolve_version\"] = \"Netgen x.x\"; // TODO\n           data[\"mesh_dim\"] = 3; // TODO\n           data[\"mesh_center\"] = mesh_center;\n           data[\"mesh_radius\"] = box.Diam()/2;\n           data[\"order2d\"] = 1;\n           data[\"order3d\"] = 0;\n           data[\"draw_vol\"] = false;\n           data[\"draw_surf\"] = true;\n           data[\"funcdim\"] = 0;\n           data[\"have_normals\"] = true;\n           data[\"show_wireframe\"] = true;\n           data[\"show_mesh\"] = true;\n           data[\"Bezier_points\"] = py::list{};\n           py::list points;\n           points.append(p[0]);\n           points.append(p[1]);\n           points.append(p[2]);\n           points.append(n[0]);\n           points.append(n[1]);\n           points.append(n[2]);\n           data[\"Bezier_trig_points\"] = points;\n           data[\"funcmin\"] = 0;\n           data[\"funcmax\"] = 1;\n           data[\"mesh_regions_2d\"] = index;\n           data[\"autoscale\"] = false;\n           data[\"colors\"] = colors;\n           data[\"names\"] = names;\n           data[\"solid_names\"] = solid_names;\n\n           py::list edges;\n           edges.append(edge_p[0]);\n           edges.append(edge_p[1]);\n           data[\"edges\"] = edges;\n           data[\"edge_names\"] = edge_names;\n           data[\"edge_colors\"] = edge_colors;\n           data[\"solid_face_map\"] = solid_face_map;\n           return data;\n         }, \"Return triangulated face/edge data and metadata for web visualization.\")\n    ;\n  \n  py::class_<TopoDS_Vertex, TopoDS_Shape> (m, \"Vertex\")\n    .def(py::init([] (const TopoDS_Shape & shape) {\n          return TopoDS::Vertex(shape);\n        }), \"Create a vertex from a TopoDS_Shape (must be a vertex).\")\n    .def(py::init([] (const gp_Pnt & p) {\n          return BRepBuilderAPI_MakeVertex (p).Vertex();\n        }), \"Create a vertex at the given point.\")\n    .def_property_readonly(\"p\", [] (const TopoDS_Vertex & v) -> gp_Pnt {\n        return BRep_Tool::Pnt (v); }, \"coordinates of vertex\")\n    ;\n  \n  py::class_<TopoDS_Edge, TopoDS_Shape> (m, \"Edge\")\n    .def(py::init([] (const TopoDS_Shape & shape) {\n          return TopoDS::Edge(shape);\n        }), \"Create an edge from a TopoDS_Shape (must be an edge).\")\n    .def(py::init([] (Handle(Geom2d_Curve) curve2d, TopoDS_Face face) {\n          auto edge = BRepBuilderAPI_MakeEdge(curve2d, BRep_Tool::Surface (face)).Edge();\n          BRepLib::BuildCurves3d(edge);\n          return edge;\n        }),\n        \"Construct an edge from a 2D parametric curve on a face by lifting it to the face's surface.\")\n    .def(py::init([] (const TopoDS_Vertex & v1, const TopoDS_Vertex & v2) {\n      return BRepBuilderAPI_MakeEdge(v1, v2).Edge();\n    }), \"Create a straight edge between two vertices.\")\n    .def(\"Value\", [](const TopoDS_Edge & e, double s) {\n        double s0, s1;\n        auto curve = BRep_Tool::Curve(e, s0, s1);\n        return curve->Value(s);        \n      }, py::arg(\"s\"), \"evaluate curve for parameters 's'\")\n    \n    .def(\"Tangent\", [](const TopoDS_Edge & e, double s) {\n        gp_Pnt p; gp_Vec v;\n        double s0, s1;\n        auto curve = BRep_Tool::Curve(e, s0, s1);\n        curve->D1(s, p, v);\n        return v;\n      }, py::arg(\"s\"), \"tangent vector to curve at parameter 's'\")\n    \n    .def_property_readonly(\"start\",\n                           [](const TopoDS_Edge & e) {\n                           double s0, s1;\n                           auto curve = BRep_Tool::Curve(e, s0, s1);\n                           return curve->Value(s0);\n                           },\n                           \"start-point of curve\")\n    .def_property_readonly(\"end\",\n                           [](const TopoDS_Edge & e) {\n                           double s0, s1;\n                           auto curve = BRep_Tool::Curve(e, s0, s1);\n                           return curve->Value(s1);\n                           },\n                           \"end-point of curve\")\n    .def_property_readonly(\"start_tangent\",\n                           [](const TopoDS_Edge & e) {\n                           double s0, s1;\n                           auto curve = BRep_Tool::Curve(e, s0, s1);\n                           gp_Pnt p; gp_Vec v;\n                           curve->D1(s0, p, v);\n                           return v;\n                           },\n                           \"tangent at start-point\")\n    .def_property_readonly(\"end_tangent\",\n                           [](const TopoDS_Edge & e) {\n                           double s0, s1;\n                           auto curve = BRep_Tool::Curve(e, s0, s1);\n                           gp_Pnt p; gp_Vec v;\n                           curve->D1(s1, p, v);\n                           return v;\n                           },\n                           \"tangent at end-point\")\n    .def_property_readonly(\"parameter_interval\",\n                           [](const TopoDS_Edge & e) {\n                             double s0, s1;\n                             auto curve = BRep_Tool::Curve(e, s0, s1);\n                             return tuple(s0, s1);\n                           },\n                           \"parameter interval of curve\")\n    .def_property(\"partition\",\n       [](TopoDS_Shape & self) -> optional<Array<double>>\n       {\n         if (OCCGeometry::HaveProperties(self))\n           return OCCGeometry::GetProperties(self).partition;\n         return nullopt;\n       },\n       [](TopoDS_Shape &self, py::array_t<double> val)\n       {\n         Array<double> partition(val.size());\n         for(auto i : Range(partition))\n           partition[i] = val.at(i);\n         OCCGeometry::GetProperties(self).partition = std::move(partition);\n       }, \"Optional edge partition parameters for meshing (array of curve parameters).\")\n    \n    .def(\"Split\", [](const TopoDS_Edge& self, py::args args)\n    {\n      ListOfShapes new_edges;\n      double s0, s1;\n      auto curve = BRep_Tool::Curve(self, s0, s1);\n      double tstart, t, dist;\n      TopoDS_Vertex vstart, vend;\n      vstart = TopExp::FirstVertex(self);\n      IntTools_Context context;\n      tstart = s0;\n      for(auto arg : args)\n        {\n          if(py::isinstance<py::float_>(arg))\n            t = s0 + py::cast<double>(arg) * (s1-s0);\n          else\n            {\n              auto p = py::cast<gp_Pnt>(arg);\n              auto result = context.ComputePE(p, 0., self, t, dist);\n              if(result != 0)\n                throw Exception(\"Error in finding splitting points on edge!\");\n            }\n          auto p = curve->Value(t);\n          vend = BRepBuilderAPI_MakeVertex(p);\n          auto newE = TopoDS::Edge(self.EmptyCopied());\n          BOPTools_AlgoTools::MakeSplitEdge(self, vstart, tstart, vend, t, newE);\n          new_edges.push_back(newE);\n          vstart = vend;\n          tstart = t;\n        }\n      auto newE = TopoDS::Edge(self.EmptyCopied());\n      t = s1;\n      vend = TopExp::LastVertex(self);\n      BOPTools_AlgoTools::MakeSplitEdge(self, vstart, tstart, vend, t, newE);\n      new_edges.push_back(newE);\n      return new_edges;\n    }, \"Splits edge at given parameters. Parameters can either be floating values in (0,1), then edge parametrization is used. Or it can be points, then the projection of these points are used for splitting the edge.\")\n    .def(\"Extend\", [](const TopoDS_Edge & edge, gp_Pnt pnt, int continuity, bool after)\n    {\n      double s0, s1;\n      auto curve = BRep_Tool::Curve(edge, s0, s1);\n      if (continuity < 0 || continuity > 2)\n        throw Exception(\"continuity must be 0, 1 or 2\");\n\n      auto bounded_curve = opencascade::handle<Geom_BoundedCurve>::DownCast(curve);\n      GeomLib::ExtendCurveToPoint(bounded_curve, pnt, continuity, after);\n      return BRepBuilderAPI_MakeEdge(bounded_curve).Edge();\n\n    }, py::arg(\"point\"), py::arg(\"continuity\") = 1, py::arg(\"after\") = true,\n       \"Extend the edge's underlying curve to a target point with G0/G1/G2 continuity.\")\n    ;\n  \n  py::class_<TopoDS_Wire, TopoDS_Shape> (m, \"Wire\")\n    .def(py::init([](const TopoDS_Edge & edge) {\n          BRepBuilderAPI_MakeWire builder;\n          builder.Add(edge); \n          return builder.Wire();\n        }), \"Create a wire from a single edge.\")\n    .def(py::init([](std::vector<TopoDS_Shape> edges) {\n          BRepBuilderAPI_MakeWire builder;\n          try\n            {\n              for (auto s : edges)\n                switch (s.ShapeType())\n                  {\n                  case TopAbs_EDGE:\n                    builder.Add(TopoDS::Edge(s)); break;\n                  case TopAbs_WIRE:\n                    builder.Add(TopoDS::Wire(s)); break;\n                  default:\n                    throw Exception(\"can make wire only from edges and wires\");\n                  }\n              return builder.Wire();\n            }\n          catch (Standard_Failure & e)\n            {\n              stringstream errstr;\n              e.Print(errstr);\n              throw NgException(\"error in wire builder: \"+errstr.str());\n            }\n        }), \"Create a wire from a list of edges and/or wires.\")\n    .def(\"Offset\", [](const TopoDS_Wire & wire, const TopoDS_Face & face, double dist,\n                      string joinT, bool openresult)\n    {\n      GeomAbs_JoinType joinType;\n      if(joinT == \"arc\")\n        joinType = GeomAbs_Arc;\n      else if(joinT == \"intersection\")\n        joinType = GeomAbs_Intersection;\n      else if(joinT == \"tangent\")\n        joinType = GeomAbs_Tangent;\n      else\n        throw Exception(\"Only joinTypes 'arc', 'tangent', and 'intersection' exist!\");\n      BRepOffsetAPI_MakeOffset builder(face, joinType, openresult);\n      builder.AddWire(wire);\n      builder.Perform(dist);\n      auto shape = builder.Shape();    \n      return shape;\n    }, \"Offset a wire on a supporting face by distance 'dist' with a chosen join type: \"\n       \"'arc' rounds corners with circular arcs, 'tangent' blends with tangent continuity, \"\n       \"and 'intersection' keeps sharp corners by intersecting offset segments.\")\n    ;\n\n  py::class_<TopoDS_Face, TopoDS_Shape> (m, \"Face\")\n    .def(py::init([](TopoDS_Wire wire) {\n          return BRepBuilderAPI_MakeFace(wire).Face();\n        }), py::arg(\"w\"), \"Create a planar face bounded by a wire.\")\n    .def(py::init([](const TopoDS_Face & face, const TopoDS_Wire & wire) {\n          return BRepBuilderAPI_MakeFace(BRep_Tool::Surface (face), wire).Face();\n        }), py::arg(\"f\"), py::arg(\"w\"), \"Create a face on the surface of another face, bounded by a wire.\")\n    .def(py::init([](const TopoDS_Face & face, std::vector<TopoDS_Wire> wires) {\n          auto surf = BRep_Tool::Surface (face);\n          BRepBuilderAPI_MakeFace builder(surf, 1e-8);\n          for (auto w : wires)\n            builder.Add(w);\n          return builder.Face();\n        }), py::arg(\"f\"), py::arg(\"w\"), \"Create a face on a reference surface and add one or more bounding wires.\")\n    .def(py::init([] (const TopoDS_Shape & shape) {\n          return TopoDS::Face(shape);\n        }), \"Create a face from a TopoDS_Shape (must be a face).\")\n    .def_property(\"quad_dominated\", [](const TopoDS_Face& self) -> optional<bool>\n                  {\n                    return OCCGeometry::GetProperties(self).quad_dominated;\n                  },\n                  [](TopoDS_Face& self, optional<bool> quad_dominated)\n                  {\n                    OCCGeometry::GetProperties(self).quad_dominated = quad_dominated;\n                  }, \"Hint that the face should be meshed with quad-dominated elements.\")\n    .def_property_readonly(\"surf\", [] (TopoDS_Face face) -> Handle(Geom_Surface)\n         {\n           Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n           return surf;\n         }, \"Return the underlying OpenCascade surface of the face.\")\n    .def(\"WorkPlane\",[] (const TopoDS_Face & face) {\n        Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n        gp_Vec du, dv;\n        gp_Pnt p;\n        surf->D1 (0,0,p,du,dv);\n        auto ax = gp_Ax3(p, du^dv, du);\n        return make_shared<WorkPlane> (ax);\n      }, \"Create a 2D work plane aligned with the face's surface at (u,v)=(0,0), using the surface normal as the plane normal.\")\n    .def(\"ProjectWire\", [](const TopoDS_Face& face,\n                           const TopoDS_Wire& wire)\n    {\n      BRepAlgo_NormalProjection builder(face);\n      builder.Add(wire);\n      builder.Build();\n      return builder.Projection();\n    }, \"Project a wire onto a face along the local surface normals \"\n       \"using BRepAlgo_NormalProjection. See https://dev.opencascade.org/doc/refman/html/class_b_rep_algo___normal_projection.html\")\n    .def(\"Extend\", [](const TopoDS_Face & face, double length, int continuity, bool inU, bool after)\n    {\n      if (continuity < 0 || continuity > 2)\n        throw Exception(\"continuity must be 0, 1 or 2\");\n\n      auto surf = BRep_Tool::Surface (face);\n      auto bounded_surface = opencascade::handle<Geom_BoundedSurface>::DownCast(surf);\n      GeomLib::ExtendSurfByLength(bounded_surface, length, continuity, inU, after);\n      return BRepBuilderAPI_MakeFace(bounded_surface, 1e-7).Face();\n\n    }, py::arg(\"length\"), py::arg(\"continuity\") = 1, py::arg(\"u_direction\") = true, py::arg(\"after\") = true,\n    \"Extend a bounded face in U or V by a given length with a requested continuity \"\n    \"using GeomLib::ExtendSurfByLength. See https://dev.opencascade.org/doc/refman/html/class_geom_lib.html\")\n    ;\n  py::class_<TopoDS_Solid, TopoDS_Shape> (m, \"Solid\")\n    .def(py::init([](const TopoDS_Shape& faces)\n    {\n      BRep_Builder builder;\n      TopoDS_Shell shell;\n      builder.MakeShell(shell);\n      for(auto& face : GetFaces(faces))\n        builder.Add(shell, face);\n      TopoDS_Solid solid;\n      builder.MakeSolid(solid);\n      builder.Add(solid, shell);\n      return solid;\n    }), \"Create solid from shell. Shell must consist of topologically closed faces (share vertices and edges).\")\n    ;\n  \n  py::class_<TopoDS_Compound, TopoDS_Shape> (m, \"Compound\")\n    .def(py::init([](std::vector<TopoDS_Shape> shapes, bool separate_layers) {\n          BRep_Builder builder;\n          TopoDS_Compound comp;\n          builder.MakeCompound(comp);\n          for(auto i : Range(shapes.size()))\n          {\n            builder.Add(comp, shapes[i]);\n            if(separate_layers)\n            {\n                for(auto & s : GetSolids(shapes[i]))\n                  OCCGeometry::GetProperties(s).layer = i+1;\n                for(auto & s : GetFaces(shapes[i]))\n                  OCCGeometry::GetProperties(s).layer = i+1;\n                for(auto & s : GetEdges(shapes[i]))\n                  OCCGeometry::GetProperties(s).layer = i+1;\n                for(auto & s : GetVertices(shapes[i]))\n                  OCCGeometry::GetProperties(s).layer = i+1;\n            }\n          }\n\n          return comp;\n        }), py::arg(\"shapes\"), py::arg(\"separate_layers\")=false,\n        \"Create a compound from a list of shapes. If separate_layers is true, assigns layer indices per input shape.\")\n    ;\n\n\n  \n  py::class_<Handle(Geom_Surface)> (m, \"Geom_Surface\")\n    .def(\"Value\", [] (const Handle(Geom_Surface) & surf, double u, double v) {\n        return surf->Value(u, v); }, \"Evaluate the surface point at parameters (u, v).\")\n    .def(\"D1\", [] (const Handle(Geom_Surface) & surf, double u, double v) {\n        gp_Vec du, dv;\n        gp_Pnt p;\n        surf->D1 (u,v,p,du,dv);\n        return tuple(p,du,dv);\n      }, \"Evaluate point and first derivatives (du, dv) at parameters (u, v).\")\n    \n    .def(\"Normal\", [] (const Handle(Geom_Surface) & surf, double u, double v) {\n        GeomLProp_SLProps lprop(surf,u,v,1,1e-8);\n        if (lprop.IsNormalDefined())\n          return lprop.Normal();\n        throw Exception(\"normal not defined\");\n      }, \"Compute the surface normal at parameters (u, v) if defined.\")\n    ;\n  \n  \n  py::implicitly_convertible<TopoDS_Shape, TopoDS_Face>();\n  py::implicitly_convertible<TopoDS_Edge, TopoDS_Wire>();\n\n  m.def(\"MakePolygon\", [](std::vector<TopoDS_Vertex> verts)\n  {\n    BRepBuilderAPI_MakePolygon builder;\n    for(auto& v : verts)\n      builder.Add(v);\n    return builder.Wire();\n  }, py::arg(\"verts\"), \"Create a polygonal wire by connecting vertices in order.\");\n\n  class ListOfShapesIterator \n  {\n    TopoDS_Shape * ptr;\n  public:\n    ListOfShapesIterator (TopoDS_Shape * aptr) : ptr(aptr) { }\n    ListOfShapesIterator operator++ () { return ListOfShapesIterator(++ptr); }\n    auto operator*() const { return CastShape(*ptr); }\n    bool operator!=(ListOfShapesIterator it2) const { return ptr != it2.ptr; }\n    bool operator==(ListOfShapesIterator it2) const { return ptr == it2.ptr; }\n  };\n  \n  py::class_<ListOfShapes> (m, \"ListOfShapes\")\n    .def(py::init<vector<TopoDS_Shape>>(), \"Create a list of shapes from a Python list.\")\n    .def(\"__iter__\", [](ListOfShapes &s) {\n        return py::make_iterator(ListOfShapesIterator(&*s.begin()),\n                                 ListOfShapesIterator(&*s.end()));\n      },\n      py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */,\n      \"Iterate over shapes in the list.\")\n    .def(\"__getitem__\", [](const ListOfShapes & list, size_t i) {\n        return CastShape(list.at(i)); },\n      \"Return the i-th shape from the list.\")\n    \n    .def(\"__getitem__\", [](const ListOfShapes & self, py::slice inds) {\n        size_t start, step, n, stop;\n        if (!inds.compute(self.size(), &start, &stop, &step, &n))                                          \n          throw py::error_already_set();\n        ListOfShapes sub;\n        sub.reserve(n);\n        for (size_t i = 0; i < n; i++)\n          sub.push_back (self[start+i*step]);\n        return sub;\n      }, \"Return a sub-list of shapes using Python slice semantics.\")\n    \n    .def(\"__add__\", [](const ListOfShapes & l1, const ListOfShapes & l2) {\n        ListOfShapes l = l1;\n        for (auto s : l2) l.push_back(s);\n        return l;\n      }, \"Concatenate two ListOfShapes instances.\")\n    .def(\"__add__\", [](const ListOfShapes & l1, py::list l2) {\n        ListOfShapes l = l1;\n        for (auto s : l2) l.push_back(py::cast<TopoDS_Shape>(s));\n        return l;\n      }, \"Concatenate a ListOfShapes with a Python list of shapes.\")\n    .def(\"__len__\", [](const ListOfShapes & self) { return self.size(); },\n         \"Return the number of shapes in the list.\")\n    .def(\"__getitem__\",[](const ListOfShapes & self, string name)\n         {\n           ListOfShapes selected;\n           std::regex pattern(name);\n           for (auto s : self)\n             if (auto sname = OCCGeometry::GetProperties(s).name)\n               if (std::regex_match(*sname, pattern))\n                 selected.push_back(s);\n           return selected;\n         }, \"returns list of all shapes named 'name'\")\n\n    .def(\"__getitem__\",[](const ListOfShapes & self, DirectionalInterval interval)\n         {\n           ListOfShapes selected;\n           for (auto s : self)\n             if (interval.Contains(Center(s), GetBoundingBox(s).Diam() * 1e-7))\n               selected.push_back(s);\n           return selected;\n         }, \"Return shapes whose centers lie inside the given directional interval.\")\n    .def_property_readonly(\"solids\", &ListOfShapes::Solids, \"Return only solid sub-shapes.\")\n    .def_property_readonly(\"shells\", &ListOfShapes::Shells, \"Return only shell sub-shapes.\")\n    .def_property_readonly(\"faces\", &ListOfShapes::Faces, \"Return only face sub-shapes.\")\n    .def_property_readonly(\"wires\", &ListOfShapes::Wires, \"Return only wire sub-shapes.\")\n    .def_property_readonly(\"edges\", &ListOfShapes::Edges, \"Return only edge sub-shapes.\")\n    .def_property_readonly(\"vertices\", &ListOfShapes::Vertices, \"Return only vertex sub-shapes.\")\n    .def(py::self * py::self)\n\n    .def(\"Sorted\",[](ListOfShapes self, gp_Vec dir)\n         {\n           TopTools_IndexedMapOfShape indices;\n           std::vector<double> sortval;\n\n           for (auto shape : self)\n             {\n               if(indices.FindIndex(shape) > 0)\n                 continue;\n               GProp_GProps props;\n               gp_Pnt center;\n               \n               switch (shape.ShapeType())\n                 {\n                 case TopAbs_VERTEX:\n                   center = BRep_Tool::Pnt (TopoDS::Vertex(shape)); break;\n                 case TopAbs_FACE:\n                   BRepGProp::SurfaceProperties (shape, props);\n                   center = props.CentreOfMass();\n                   break;\n                 default:\n                   BRepGProp::LinearProperties(shape, props);\n                   center = props.CentreOfMass();\n                 }\n               \n               double val = center.X()*dir.X() + center.Y()*dir.Y() + center.Z() * dir.Z();\n               indices.Add(shape);\n               sortval.push_back(val);\n             }\n\n           std::sort (std::begin(self), std::end(self),\n                      [&](const TopoDS_Shape& a, const TopoDS_Shape& b)\n                      { return sortval[indices.FindIndex(a)-1] <\n                          sortval[indices.FindIndex(b)-1]; });\n           return self;\n         }, py::arg(\"dir\"), \"returns list of shapes, where center of gravity is sorted in direction of 'dir'\")\n    \n    .def(\"Max\", [] (ListOfShapes & shapes, gp_Vec dir)\n         { return CastShape(shapes.Max(dir)); },\n         py::arg(\"dir\"), \"returns shape where center of gravity is maximal in the direction 'dir'\")\n    \n    .def(\"Min\", [] (ListOfShapes & shapes, gp_Vec dir) \n         { return CastShape(shapes.Max(-dir)); },\n         py::arg(\"dir\"), \"returns shape where center of gravity is minimal in the direction 'dir'\")\n\n    .def(\"Nearest\", [] (ListOfShapes & shapes, gp_Pnt pnt) \n         { return CastShape(shapes.Nearest(pnt)); },\n         py::arg(\"p\"), \"returns shape nearest to point 'p'\")\n    .def(\"Nearest\", [] (ListOfShapes & shapes, gp_Pnt2d pnt) \n         { return CastShape(shapes.Nearest( { pnt.X(), pnt.Y(), 0 })); },\n         py::arg(\"p\"), \"returns shape nearest to point 'p'\")\n    \n    .def_property(\"name\", [](ListOfShapes& shapes)\n    {\n      throw Exception(\"Cannot get property of ListOfShapes, get the property from individual shapes!\");\n    },\n      [](ListOfShapes& shapes, optional<std::string> name)\n      {\n        for(auto& shape : shapes)\n          {\n            OCCGeometry::GetProperties(shape).name = name;\n          }\n      }, \"set name for all elements of list\")\n    .def_property(\"col\", [](ListOfShapes& shapes) {\n        throw Exception(\"Cannot get property of ListOfShapes, get the property from individual shapes!\");\n      }, [](ListOfShapes& shapes, std::vector<double> c) {\n        Vec<4> col(c[0], c[1], c[2], 1.0);\n        if(c.size() == 4)\n          col[3] = c[3];\n        for(auto& shape : shapes)\n          OCCGeometry::GetProperties(shape).col = col;\n      }, \"set col for all elements of list\")\n    \n    .def_property(\"maxh\", [](ListOfShapes& shapes)\n    {\n      throw Exception(\"Cannot get property of ListOfShapes, get the property from individual shapes!\");\n    },\n      [](ListOfShapes& shapes, double maxh)\n      {\n        for(auto & s : shapes)\n          OCCGeometry::GetProperties(s).maxh = maxh;\n      }, \"set maxh for all elements of list\")\n    .def_property(\"hpref\", [](ListOfShapes& shapes)\n    {\n      throw Exception(\"Cannot get property of ListOfShapes, get the property from individual shapes!\");\n    },\n      [](ListOfShapes& shapes, double hpref)\n      {\n        for(auto& shape : shapes)\n          OCCGeometry::GetProperties(shape).hpref = hpref;\n      }, \"set hpref for all elements of list\")\n    .def_property(\"quad_dominated\", [](ListOfShapes& shapes)\n                  {\n                    throw Exception(\"Cannot get property of ListOfShapes, get the property from individual shapes!\");\n                  },\n                  [](ListOfShapes& shapes, optional<bool> quad_dominated)\n                  {\n                    for(auto& shape : shapes)\n                      OCCGeometry::GetProperties(shape).quad_dominated = quad_dominated;\n                  }, \"Set the quad-dominated meshing hint for all shapes in the list.\")\n    \n    .def(\"Identify\", [](const ListOfShapes& me,\n                        const ListOfShapes& other,\n                        string name,\n                        Identifications::ID_TYPE type,\n                        std::variant<gp_Trsf, gp_GTrsf> trafo)\n    {\n      Identify(me, other, name, type, occ2ng(trafo));\n    }, py::arg(\"other\"), py::arg(\"name\"),\n         py::arg(\"type\")=Identifications::PERIODIC, py::arg(\"trafo\"),\n         \"Identify shapes for periodic meshing\")\n\n    ;\n         \n\n\n\n\n\n\n\n\n\n\n  \n  py::class_<Handle(Geom2d_Curve)> (m, \"Geom2d_Curve\")\n    .def(\"Trim\", [](Handle(Geom2d_Curve) curve, double u1, double u2) -> Handle(Geom2d_Curve)\n         {\n           return new Geom2d_TrimmedCurve (curve, u1, u2);\n         }, \"Return a trimmed 2D curve on the parameter interval [u1, u2].\")\n    .def(\"Value\", [](Handle(Geom2d_Curve) curve, double s) {\n        return curve->Value(s);\n      }, \"Evaluate the 2D curve at parameter s.\")\n    .def_property_readonly(\"start\", [](Handle(Geom2d_Curve) curve) {\n        return curve->Value(curve->FirstParameter());\n      }, \"Start point of the curve in parameter space.\")\n    .def_property_readonly(\"end\", [](Handle(Geom2d_Curve) curve) {\n        return curve->Value(curve->LastParameter());\n      }, \"End point of the curve in parameter space.\")\n    .def(\"Edge\", [](Handle(Geom2d_Curve) curve) {\n        // static Geom_Plane surf{gp_Ax3()}; // crashes in nbconvert ???\n        static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});\n        auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();\n        BRepLib::BuildCurves3d(edge);\n        return edge;\n      }, \"Lift the 2D curve to the default plane and return a 3D edge.\")\n    .def(\"Wire\", [](Handle(Geom2d_Curve) curve) {\n        // static Geom_Plane surf{gp_Ax3()}; // crashes in nbconvert ???\n        static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});\n        auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();\n        BRepLib::BuildCurves3d(edge);\n        return BRepBuilderAPI_MakeWire(edge).Wire();                \n      }, \"Create a wire from the lifted 2D curve on the default plane.\")\n    .def(\"Face\", [](Handle(Geom2d_Curve) curve) {\n        // static Geom_Plane surf{gp_Ax3()};  // crashes in nbconvert ???\n        static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});\n        auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();\n        BRepLib::BuildCurves3d(edge);        \n        auto wire = BRepBuilderAPI_MakeWire(edge).Wire();        \n        return BRepBuilderAPI_MakeFace(wire).Face();\n      }, \"Create a planar face bounded by the lifted 2D curve.\")\n    ;\n\n\n  py::enum_<GeomAbs_Shape>(m, \"ShapeContinuity\", \"Wrapper for OCC enum GeomAbs_Shape\")\n    .value(\"C0\", GeomAbs_Shape::GeomAbs_C0)\n    .value(\"C1\", GeomAbs_Shape::GeomAbs_C1)\n    .value(\"C2\", GeomAbs_Shape::GeomAbs_C2)\n    .value(\"C3\", GeomAbs_Shape::GeomAbs_C3)\n    .value(\"CN\", GeomAbs_Shape::GeomAbs_CN)\n    .value(\"G1\", GeomAbs_Shape::GeomAbs_G1)\n    .value(\"G2\", GeomAbs_Shape::GeomAbs_G2);\n\n  py::enum_<Approx_ParametrizationType>(m, \"ApproxParamType\", \"Wrapper for Approx_ParametrizationType\")\n    .value(\"Centripetal\", Approx_ParametrizationType::Approx_Centripetal)\n    .value(\"ChordLength\", Approx_ParametrizationType::Approx_ChordLength)\n    .value(\"IsoParametric\", Approx_ParametrizationType::Approx_IsoParametric);\n\n\n  m.def(\"HalfSpace\", [] (gp_Pnt p, gp_Vec n)\n  {\n    gp_Pln plane(p, n);\n    BRepBuilderAPI_MakeFace bface(plane);\n    auto face = bface.Face();\n    auto refpnt = p.Translated(-n);\n    BRepPrimAPI_MakeHalfSpace builder(face, refpnt);\n    return builder.Shape();\n  }, py::arg(\"p\"), py::arg(\"n\"), \"Create a half-space bounded by a plane through point p with normal n.\");\n\n  m.def(\"Sphere\", [] (gp_Pnt cc, double r) {\n      return BRepPrimAPI_MakeSphere (cc, r).Solid();\n    }, py::arg(\"c\"), py::arg(\"r\"), \"Create a sphere with center c and radius r.\");\n\n  m.def(\"Ellipsoid\", [] (gp_Ax3 ax, double r1, double r2, optional<double> hr3) {\n      auto sp = BRepPrimAPI_MakeSphere (gp_Pnt(0,0,0), 1).Solid();\n\n      gp_GTrsf gtrafo;\n      double r3 = hr3.value_or(r2);\n      gtrafo.SetVectorialPart({ r2, 0, 0,  0, r3, 0,  0, 0, r1 });\n      gtrafo.SetTranslationPart( { 0.0, 0.0, 0.0 } );\n\n      BRepBuilderAPI_GTransform gbuilder(sp, gtrafo, true);\n      PropagateProperties(gbuilder, sp, occ2ng(gtrafo));\n\n      auto gsp = gbuilder.Shape();      \n      \n      gp_Trsf trafo;\n      trafo.SetTransformation(ax, gp_Ax3());\n      BRepBuilderAPI_Transform builder(gsp, trafo, true);\n      PropagateProperties(builder, gsp, occ2ng(trafo));\n      return builder.Shape();\n    }, py::arg(\"axes\"), py::arg(\"r1\"), py::arg(\"r2\"), py::arg(\"r3\")=std::nullopt,\n    \"Create an ellipsoid aligned with axes, with radii r1, r2, and optional r3 (defaults to r2).\");\n\n  \n  m.def(\"Cylinder\", [] (gp_Pnt cpnt, gp_Dir cdir, double r, double h,\n                        optional<string> bot, optional<string> top, optional<string> mantle) {\n    auto builder = BRepPrimAPI_MakeCylinder (gp_Ax2(cpnt, cdir), r, h);\n    if(mantle)\n      OCCGeometry::GetProperties(builder.Face()).name = *mantle;\n    auto pyshape = py::cast(builder.Solid());\n    gp_Vec v = cdir;\n    if(bot)\n      pyshape.attr(\"faces\").attr(\"Min\")(v).attr(\"name\") = *bot;\n    if(top)\n      pyshape.attr(\"faces\").attr(\"Max\")(v).attr(\"name\") = *top;\n    return pyshape;\n    }, py::arg(\"p\"), py::arg(\"d\"), py::arg(\"r\"), py::arg(\"h\"),\n        py::arg(\"bottom\") = nullopt, py::arg(\"top\") = nullopt,\n        py::arg(\"mantle\") = nullopt,\n    \"Create a cylinder at base point p with axis direction d, radius r, and height h. Optional face names: bottom/top/mantle.\");\n  \n  m.def(\"Cylinder\", [] (gp_Ax2 ax, double r, double h) {\n      return BRepPrimAPI_MakeCylinder (ax, r, h).Solid();\n    }, py::arg(\"axis\"), py::arg(\"r\"), py::arg(\"h\"),\n    \"Create a cylinder defined by axis, radius, and height.\");\n  \n  m.def(\"Cone\", [] (gp_Ax2 ax, double r1, double r2, double h, double angle) {\n     return BRepPrimAPI_MakeCone (ax, r1, r2, h, angle).Solid();\n    }, py::arg(\"axis\"), py::arg(\"r1\"), py::arg(\"r2\"), py::arg(\"h\"), py::arg(\"angle\"),\n    \"Create a cone defined by axis, bottom radius r1, top radius r2, height h, and semi-angle.\");\n\n  m.def(\"Box\", [] (gp_Pnt cp1, gp_Pnt cp2) {\n      return BRepPrimAPI_MakeBox (cp1, cp2).Solid();\n    }, py::arg(\"p1\"), py::arg(\"p2\"),\n    \"Create a box defined by two opposite corner points p1 and p2.\");\n\n  m.def(\"Prism\", [] (const TopoDS_Shape & face, gp_Vec vec) {\n      return BRepPrimAPI_MakePrism (face, vec, true).Shape();\n    }, py::arg(\"face\"), py::arg(\"v\"),\n    \"Extrude a face (or shape) along the vector v to create a prism.\");\n\n  m.def(\"Revolve\", [] (const TopoDS_Shape & face,const gp_Ax1 &A, const double D) {\n      //convert angle from deg to rad\n      return BRepPrimAPI_MakeRevol (face, A, D*M_PI/180, true).Shape();\n    }, \"Revolve a shape around an axis by an angle in degrees.\");\n\n  m.def(\"Pipe\", [] (const TopoDS_Wire & spine, const TopoDS_Shape & profile,\n                    optional<tuple<gp_Pnt, double>> twist,\n                    optional<TopoDS_Wire> auxspine) {\n          if (twist)\n            {\n              // auto [pnt, angle] = *twist;\n\n              /*\n                cyl = Cylinder((0,0,0), Z, r=1, h=1).faces[0]\n                heli = Edge(Segment((0,0), (2*math.pi, 1)), cyl)\n                auxspine = Wire( [heli] )\n                \n                Handle(Geom_Surface) cyl = new Geom_CylindricalSurface (gp_Ax3(pnt, gp_Vec(0,0,1)), 1);\n                auto edge = BRepBuilderAPI_MakeEdge(curve2d, cyl).Edge();\n                BRepLib::BuildCurves3d(edge);\n              */              \n              throw Exception(\"twist not implemented\");\n            }\n          if (auxspine)\n            {\n              BRepOffsetAPI_MakePipeShell builder(spine);\n              builder.SetMode (*auxspine, Standard_True);\n              for (TopExp_Explorer e(profile, TopAbs_WIRE); e.More(); e.Next())\n                builder.Add (TopoDS::Wire(e.Current()));\n              builder.Build();\n              builder.MakeSolid();\n              return builder.Shape();\n            }\n          \n          return BRepOffsetAPI_MakePipe (spine, profile).Shape();\n        }, py::arg(\"spine\"), py::arg(\"profile\"), py::arg(\"twist\")=nullopt, py::arg(\"auxspine\")=nullopt,\n        \"Create a pipe by sweeping a profile along a spine wire. \"\n        \"If auxspine is provided, uses a pipe shell with the auxiliary spine for orientation.\");\n  \n  m.def(\"PipeShell\", [] (const TopoDS_Wire & spine, variant<TopoDS_Shape, std::vector<TopoDS_Shape>> profile, std::optional<TopoDS_Wire> auxspine) {\n      try\n        {\n          BRepOffsetAPI_MakePipeShell builder(spine);\n          if(auxspine)\n            builder.SetMode (*auxspine, Standard_True);\n          if(std::holds_alternative<TopoDS_Shape>(profile))\n            builder.Add (std::get<TopoDS_Shape>(profile));\n          else\n            {\n              for(auto s : std::get<std::vector<TopoDS_Shape>>(profile))\n                builder.Add(s);\n            }\n          return builder.Shape();\n        }\n      catch (Standard_Failure & e)\n        {\n          stringstream errstr;\n          e.Print(errstr);\n          throw NgException(\"cannot create PipeShell: \"+errstr.str());\n        }\n    }, py::arg(\"spine\"), py::arg(\"profile\"), py::arg(\"auxspine\")=nullopt,\n    \"Create a pipe shell by sweeping one or more profiles along a spine wire. \"\n    \"Optionally uses an auxiliary spine to control orientation.\");\n\n\n  // Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);\n  m.def(\"Ellipse\", [] (const gp_Ax2d & ax, double major, double minor) -> Handle(Geom2d_Curve)\n        {\n          return Handle(Geom2d_Ellipse) (GCE2d_MakeEllipse(ax, major, minor));\n        }, py::arg(\"axes\"), py::arg(\"major\"), py::arg(\"minor\"),\n        \"Create a 2D ellipse curve defined by axes and major/minor radii.\");\n  \n  m.def(\"Segment\", [](gp_Pnt2d p1, gp_Pnt2d p2) -> Handle(Geom2d_Curve) {\n      return Handle(Geom2d_TrimmedCurve)(GCE2d_MakeSegment(p1, p2));   \n      /*\n      Handle(Geom2d_TrimmedCurve) curve = GCE2d_MakeSegment(p1, p2);\n      return curve;\n      */\n    }, py::arg(\"p1\"), py::arg(\"p2\"), \"Create a 2D line segment curve from p1 to p2.\");\n  \n  m.def(\"Circle\", [](gp_Pnt2d p1, double r) -> Handle(Geom2d_Curve) {\n      return Handle(Geom2d_Circle)(GCE2d_MakeCircle(p1, r));\n      /*\n      Handle(Geom2d_Circle) curve = GCE2d_MakeCircle(p1, r);\n      return curve;\n      */\n    }, py::arg(\"c\"), py::arg(\"r\"), \"Create a 2D circle curve with center c and radius r.\");\n\n  m.def(\"SplineApproximation\", [](const std::vector<gp_Pnt2d> &points, Approx_ParametrizationType approx_type, int deg_min,\n                                    int deg_max, GeomAbs_Shape continuity, double tol) -> Handle(Geom2d_Curve) {\n      TColgp_Array1OfPnt2d hpoints(0, 0);\n      hpoints.Resize(0, points.size() - 1, true);\n      for (int i = 0; i < points.size(); i++)\n          hpoints.SetValue(i, points[i]);\n\n      Geom2dAPI_PointsToBSpline builder(hpoints, approx_type, deg_min, deg_max, continuity, tol);\n      return Handle(Geom2d_BSplineCurve)(builder.Curve());\n    },\n    py::arg(\"points\"),\n    py::arg(\"approx_type\") = Approx_ParametrizationType::Approx_ChordLength,\n    py::arg(\"deg_min\") = 3,\n    py::arg(\"deg_max\") = 8,\n    py::arg(\"continuity\") = GeomAbs_Shape::GeomAbs_C2,\n    py::arg(\"tol\")=1e-8,\n    R\"delimiter(\nGenerate a piecewise continuous spline-curve approximating a list of points in 2d.\n\nParameters\n----------\n\npoints : List|Tuple[gp_Pnt2d]\n  List (or tuple) of gp_Pnt.\n\napprox_type : ApproxParamType\n  Assumption on location of parameters wrt points.\n\ndeg_min : int\n  Minimum polynomial degree of splines\n\ndeg_max : int\n  Maximum polynomial degree of splines\n\ncontinuity : ShapeContinuity\n  Continuity requirement on the approximating surface\n\ntol : float\n  Tolerance for the distance from individual points to the approximating curve.\n\n)delimiter\");\n\n  m.def(\"SplineInterpolation\", [](const std::vector<gp_Pnt2d> &points, bool periodic, double tol, const std::map<int, gp_Vec2d> &tangents) -> Handle(Geom2d_Curve) {\n      Handle(TColgp_HArray1OfPnt2d) hpoints = new TColgp_HArray1OfPnt2d(1, points.size());\n      for (int i = 0; i < points.size(); i++)\n          hpoints->SetValue(i+1, points[i]);\n      Geom2dAPI_Interpolate builder(hpoints, periodic, tol);\n\n      if (tangents.size() > 0)\n      {\n        const gp_Vec2d dummy_vec = tangents.begin()->second;\n        TColgp_Array1OfVec2d tangent_vecs(1, points.size());\n        Handle(TColStd_HArray1OfBoolean) tangent_flags = new TColStd_HArray1OfBoolean(1, points.size());\n        for (int i : Range(points.size()))\n        {\n          if (tangents.count(i) > 0)\n          {\n              tangent_vecs.SetValue(i+1, tangents.at(i));\n              tangent_flags->SetValue(i+1, true);\n          } else{\n              tangent_vecs.SetValue(i+1, dummy_vec);\n              tangent_flags->SetValue(i+1, false);\n          }\n        }\n        builder.Load(tangent_vecs, tangent_flags);\n      }\n\n      builder.Perform();\n      return Handle(Geom2d_BSplineCurve)(builder.Curve());\n    },\n    py::arg(\"points\"),\n    py::arg(\"periodic\")=false,\n    py::arg(\"tol\")=1e-8,\n    py::arg(\"tangents\")=std::map<int, gp_Vec2d>{},\n    R\"delimiter(\nGenerate a piecewise continuous spline-curve interpolating a list of points in 2d.\n\nParameters\n----------\n\npoints : List|Tuple[gp_Pnt2d]\n  List (or tuple) of gp_Pnt2d.\n\nperiodic : bool\n  Whether the result should be periodic\n\ntol : float\n  Tolerance for the distance between points.\n\ntangents : Dict[int, gp_Vec2d]\n  Tangent vectors for the points indicated by the key value (0-based).\n\n)delimiter\");\n\n  m.def(\"Sew\", [] (const std::vector<TopoDS_Shape> & faces, double tol,\n                   bool non_manifold) -> TopoDS_Shape\n        {\n          if(faces.size() == 1)\n            return faces[0];\n          BRepBuilderAPI_Sewing sewer(tol);\n          sewer.SetNonManifoldMode(non_manifold);\n          for (auto & s : faces)\n            sewer.Add(s);\n          sewer.Perform();\n          for (auto & s : faces)\n            PropagateProperties (sewer, s);\n          auto sewn = sewer.SewedShape();\n          return sewn;\n        }, py::arg(\"faces\"), py::arg(\"tolerance\")=1e-6,\n        py::arg(\"non_manifold\")=false,\n        R\"doc(\nStitch a list of faces into one or more connected shells.\n\nParameters\n----------\nfaces : list[TopoDS_Shape]\n    Faces or other shapes to sew together.\ntolerance : float, default=1e-6\n    Geometric tolerance for merging edges and vertices.\nnon_manifold : bool, default=False\n    If True, allows edges shared by more than two faces (may produce\n    multiple shells). If False, creates only manifold shells suitable\n    for solids.\n\nReturns\n-------\nTopoDS_Shape\n    The sewed shape containing one or more shells.\n)doc\");\n\n  \n  m.def(\"Glue\", [] (const std::vector<TopoDS_Shape> shapes) -> TopoDS_Shape\n        {\n          if(shapes.size() == 1)\n            return shapes[0];\n          BOPAlgo_Builder builder;\n          for (auto & s : shapes)\n            {\n              bool has_solid = false;\n              for (TopExp_Explorer e(s, TopAbs_SOLID); e.More(); e.Next())\n                {\n                  builder.AddArgument(e.Current());\n                  has_solid = true;\n                }\n              if (has_solid) continue;\n              \n              bool has_face = false;\n              for (TopExp_Explorer e(s, TopAbs_FACE); e.More(); e.Next())\n                {\n                  builder.AddArgument(e.Current());\n                  has_face = true;\n                }\n              if (has_face) continue;\n\n              bool has_edge = false;\n              for (TopExp_Explorer e(s, TopAbs_EDGE); e.More(); e.Next())\n                {\n                  builder.AddArgument(e.Current());\n                  has_edge = true;\n                }\n              if (has_edge) continue;\n\n              \n              for (TopExp_Explorer e(s, TopAbs_VERTEX); e.More(); e.Next())\n                {\n                  builder.AddArgument(e.Current());\n                }\n            }\n\n          builder.Perform();\n          \n          /*\n#ifdef OCC_HAVE_HISTORY          \n          Handle(BRepTools_History) history = builder.History ();\n\n          for (auto typ : { TopAbs_SOLID, TopAbs_FACE,  TopAbs_EDGE })\n            for (auto & s : shapes)\n              for (TopExp_Explorer e(s, typ); e.More(); e.Next())\n                {\n                  auto prop = OCCGeometry::GetProperties(e.Current());\n                  for (auto mods : history->Modified(e.Current()))\n                    OCCGeometry::GetProperties(mods).Merge(prop);\n                }\n#endif // OCC_HAVE_HISTORY\n          */\n          for (auto & s : shapes)\n            PropagateProperties (builder, s);          \n          return builder.Shape();\n        }, py::arg(\"shapes\"), \"glue together shapes of list\");\n\n  m.def(\"Glue\", [] (TopoDS_Shape shape) -> TopoDS_Shape\n        {\n          BOPAlgo_Builder builder;\n          \n          for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next())\n            builder.AddArgument(e.Current());\n          \n          builder.Perform();\n          \n          if (builder.HasErrors())\n            builder.DumpErrors(cout);\n          if (builder.HasWarnings())\n            builder.DumpWarnings(cout);\n\n          /*\n#ifdef OCC_HAVE_HISTORY\n          Handle(BRepTools_History) history = builder.History ();\n\n          for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next())\n            {\n              auto prop = OCCGeometry::GetProperties(e.Current());\n              for (auto mods : history->Modified(e.Current()))\n                OCCGeometry::GetProperties(mods).Merge(prop);\n            }\n#endif // OCC_HAVE_HISTORY\n          */\n          PropagateProperties (builder, shape);\n          \n          return builder.Shape();\n        }, py::arg(\"shape\"), \"glue together shapes from shape, typically a compound\");\n  m.def(\"Fuse\", [](const vector<TopoDS_Shape>& shapes) -> TopoDS_Shape\n  {\n    auto s = shapes[0];\n    for(auto i : Range(size_t(1), shapes.size()))\n      {\n        BRepAlgoAPI_Fuse builder(s, shapes[i]);\n        PropagateProperties(builder, s);\n        PropagateProperties(builder, shapes[i]);\n        s = builder.Shape();\n      }\n    return s;\n  }, \"Fuse a list of shapes sequentially (pairwise) using BRepAlgoAPI_Fuse.\");\n\n\n  // py::class_<Handle(Geom_TrimmedCurve)> (m, \"Geom_TrimmedCurve\")\n  // ;\n  \n  m.def(\"Segment\", [](gp_Pnt p1, gp_Pnt p2) { \n      Handle(Geom_TrimmedCurve) curve = GC_MakeSegment(p1, p2);\n      return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"p1\"), py::arg(\"p2\"), \"Create a straight edge between two points.\");\n  m.def(\"Circle\", [](gp_Pnt c, gp_Dir n, double r) {\n\tHandle(Geom_Circle) curve = GC_MakeCircle (c, n, r);\n        return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"center\"), py::arg(\"normal\"), py::arg(\"radius\"),\n    \"Create a circular edge defined by center, normal, and radius.\");\n\n  m.def(\"ArcOfCircle\", [](gp_Pnt p1, gp_Pnt p2, gp_Pnt p3) { \n      Handle(Geom_TrimmedCurve) curve = GC_MakeArcOfCircle(p1, p2, p3);\n      return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"p1\"), py::arg(\"p2\"), py::arg(\"p3\"),\n    \"Create a circular arc from p1 through p2 to p3.\");\n  \n  m.def(\"ArcOfCircle\", [](gp_Pnt p1, gp_Vec v, gp_Pnt p2) { \n      Handle(Geom_TrimmedCurve) curve = GC_MakeArcOfCircle(p1, v, p2);\n      return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"p1\"), py::arg(\"v\"), py::arg(\"p2\"),\n    \"Create a circular arc from p1 to p2 with tangent vector v at p1.\");\n\n\n  m.def(\"BSplineCurve\", [](std::vector<gp_Pnt> vpoles, int degree) {\n      // not yet working ????\n      TColgp_Array1OfPnt poles(0, vpoles.size()-1);\n      TColStd_Array1OfReal knots(0, vpoles.size()+degree);\n      TColStd_Array1OfInteger mult(0, vpoles.size()+degree);\n      // int cnt = 0;\n\n      for (int i = 0; i < vpoles.size(); i++)\n        {\n          poles.SetValue(i, vpoles[i]);\n          knots.SetValue(i, i);\n          mult.SetValue(i,1);\n        }\n      for (int i = vpoles.size(); i < vpoles.size()+degree+1; i++)\n        {\n              knots.SetValue(i, i);\n              mult.SetValue(i, 1);\n        }\n      \n      Handle(Geom_Curve) curve = new Geom_BSplineCurve(poles, knots, mult, degree);\n      return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"poles\"), py::arg(\"degree\"),\n    \"Create a B-spline edge from control points and degree (experimental).\");\n  \n  m.def(\"BezierCurve\", [](std::vector<gp_Pnt> vpoles) {\n      TColgp_Array1OfPnt poles(0, vpoles.size()-1);\n\n      for (int i = 0; i < vpoles.size(); i++)\n        poles.SetValue(i, vpoles[i]);\n      \n      Handle(Geom_Curve) curve = new Geom_BezierCurve(poles);\n      return BRepBuilderAPI_MakeEdge(curve).Edge();\n    }, py::arg(\"points\"), \"Create a Bezier curve from control points.\");\n\n  m.def(\"BezierSurface\", [](py::array_t<double> nppoles,\n                            optional<py::array_t<double>> npweights,\n                            double tol)\n  {\n    if(nppoles.ndim() != 3)\n      throw std::length_error(\"`poles` array must have dimension 3.\");\n    if(nppoles.shape(2) != 3)\n      throw std::length_error(\"The third dimension must have size 3.\");\n    if(npweights && npweights->ndim() != 2)\n      throw std::length_error(\"`weights` array must have dimension 2.\");\n\n    auto deg_u = nppoles.shape(0) - 1;\n    auto deg_v = nppoles.shape(1) - 1;\n    TColgp_Array2OfPnt poles(1, deg_u + 1, 1, deg_v + 1);\n    TColStd_Array2OfReal weights(1, deg_u + 1, 1, deg_v + 1);\n    for(int i = 0; i < nppoles.shape(0); ++i)\n      for(int j = 0; j < nppoles.shape(1); ++j)\n        {\n          poles.SetValue(i + 1, j + 1, gp_Pnt(nppoles.at(i, j, 0), nppoles.at(i, j, 1), nppoles.at(i, j, 2)));\n          if(npweights)\n            weights.SetValue(i + 1, j + 1, npweights->at(i, j));\n          else\n            weights.SetValue(i + 1, j + 1, 1.0);\n        }\n    Handle(Geom_Surface) surface = new Geom_BezierSurface(poles, weights);\n    return BRepBuilderAPI_MakeFace(surface, tol).Face();\n  }, py::arg(\"poles\"), py::arg(\"weights\")=std::nullopt,\n        py::arg(\"tol\")=1e-7,\n        \"Creates a rational Bezier surface with the set of poles and the set of weights. The weights are defaulted to all being 1. If all the weights are identical the surface is considered as non rational. Raises ConstructionError if the number of poles in any direction is greater than MaxDegree + 1 or lower than 2 or CurvePoles and CurveWeights have not the same length or one weight value is lower or equal to Resolution. Returns an occ face with the given tolerance.\");\n\n\n  m.def(\"SplineApproximation\", [](const std::vector<gp_Pnt> &points, Approx_ParametrizationType approx_type, int deg_min,\n          int deg_max, GeomAbs_Shape continuity, double tol) {\n      TColgp_Array1OfPnt hpoints(0, 0);\n      hpoints.Resize(0, points.size() - 1, true);\n      for (int i = 0; i < points.size(); i++)\n        hpoints.SetValue(i, points[i]);\n\n      GeomAPI_PointsToBSpline builder(hpoints, approx_type, deg_min, deg_max, continuity, tol);\n      return BRepBuilderAPI_MakeEdge(builder.Curve()).Edge();\n    },\n    py::arg(\"points\"),\n    py::arg(\"approx_type\") = Approx_ParametrizationType::Approx_ChordLength,\n    py::arg(\"deg_min\") = 3,\n    py::arg(\"deg_max\") = 8,\n    py::arg(\"continuity\") = GeomAbs_Shape::GeomAbs_C2,\n    py::arg(\"tol\")=1e-8,\n    R\"delimiter(\nGenerate a piecewise continuous spline-curve approximating a list of points in 3d.\n\nParameters\n----------\n\npoints : List[gp_Pnt] or Tuple[gp_Pnt]\n  List (or tuple) of gp_Pnt.\n\napprox_type : ApproxParamType\n  Assumption on location of parameters wrt points.\n\ndeg_min : int\n  Minimum polynomial degree of splines\n\ndeg_max : int\n  Maximum polynomial degree of splines\n\ncontinuity : ShapeContinuity\n  Continuity requirement on the approximating surface\n\ntol : float\n  Tolerance for the distance from individual points to the approximating curve.\n\n)delimiter\");\n\n    m.def(\"SplineInterpolation\", [](const std::vector<gp_Pnt> &points, bool periodic, double tol, const std::map<int, gp_Vec> &tangents) {\n        Handle(TColgp_HArray1OfPnt) hpoints = new TColgp_HArray1OfPnt(1, points.size());\n        for (int i = 0; i < points.size(); i++)\n          hpoints->SetValue(i+1, points[i]);\n\n        GeomAPI_Interpolate builder(hpoints, periodic, tol);\n\n        if (tangents.size() > 0)\n        {\n          const gp_Vec dummy_vec = tangents.begin()->second;\n          TColgp_Array1OfVec tangent_vecs(1, points.size());\n          Handle(TColStd_HArray1OfBoolean) tangent_flags = new TColStd_HArray1OfBoolean(1, points.size());\n          for (int i : Range(points.size()))\n          {\n            if (tangents.count(i) > 0)\n            {\n              tangent_vecs.SetValue(i+1, tangents.at(i));\n              tangent_flags->SetValue(i+1, true);\n            } else{\n              tangent_vecs.SetValue(i+1, dummy_vec);\n              tangent_flags->SetValue(i+1, false);\n            }\n          }\n          builder.Load(tangent_vecs, tangent_flags);\n        }\n\n        builder.Perform();\n        return BRepBuilderAPI_MakeEdge(builder.Curve()).Edge();\n      },\n      py::arg(\"points\"),\n      py::arg(\"periodic\")=false,\n      py::arg(\"tol\")=1e-8,\n      py::arg(\"tangents\")=std::map<int, gp_Vec>{},\n      R\"delimiter(\nGenerate a piecewise continuous spline-curve interpolating a list of points in 3d.\n\nParameters\n----------\n\npoints : List|Tuple[gp_Pnt]\n  List (or tuple) of gp_Pnt\n\nperiodic : bool\n  Whether the result should be periodic\n\ntol : float\n  Tolerance for the distance between points.\n\ntangents : Dict[int, gp_Vec]\n  Tangent vectors for the points indicated by the key value (0-based).\n\n)delimiter\");\n\n\n  m.def(\"SplineSurfaceApproximation\", [](py::array_t<double> pnt_array,\n          Approx_ParametrizationType approx_type, int deg_min, int deg_max, GeomAbs_Shape continuity, double tol,\n          bool periodic, double degen_tol) {\n      if (pnt_array.ndim() != 3)\n        throw Exception(\"`points` array must have dimension 3.\");\n      if (pnt_array.shape(2) != 3)\n        throw Exception(\"The third dimension must have size 3.\");\n\n      auto array = py::extract<py::array_t<double>>(pnt_array)();\n      TColgp_Array2OfPnt points(1, pnt_array.shape(0), 1, pnt_array.shape(1));\n      auto pnts_unchecked = pnt_array.unchecked<3>();\n      for (int i = 0; i < pnt_array.shape(0); ++i)\n        for (int j = 0; j < pnt_array.shape(1); ++j)\n          points.SetValue(i+1, j+1, gp_Pnt(pnts_unchecked(i, j, 0), pnts_unchecked(i, j, 1), pnts_unchecked(i, j, 2)));\n\n      GeomAPI_PointsToBSplineSurface builder;\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4\n      builder.Init(points, approx_type, deg_min, deg_max, continuity, tol, periodic);\n#else\n      if(periodic)\n          throw Exception(\"periodic not supported\");\n      builder.Init(points, approx_type, deg_min, deg_max, continuity, tol);\n#endif\n      return BRepBuilderAPI_MakeFace(builder.Surface(), tol).Face();\n    },\n    py::arg(\"points\"),\n    py::arg(\"approx_type\") = Approx_ParametrizationType::Approx_ChordLength,\n    py::arg(\"deg_min\") = 3,\n    py::arg(\"deg_max\") = 8,\n    py::arg(\"continuity\") = GeomAbs_Shape::GeomAbs_C2,\n    py::arg(\"tol\") = 1e-3,\n    py::arg(\"periodic\") = false,\n    py::arg(\"degen_tol\") = 1e-8,\n    R\"delimiter(\nGenerate a piecewise continuous spline-surface approximating an array of points.\n\nParameters\n----------\n\npoints : np.ndarray\n  Array of points coordinates. The first dimension corresponds to the first surface coordinate point\n  index, the second dimension to the second surface coordinate point index. The third dimension refers to physical\n  coordinates. Such an array can be generated with code like::\n\n      px, py = np.meshgrid(*[np.linspace(0, 1, N)]*2)\n      points = np.array([[(px[i,j], py[i,j], px[i,j]*py[i,j]**2) for j in range(N)] for i in range(N)])\n\napprox_type : ApproxParamType\n  Assumption on location of parameters wrt points.\n\ndeg_min : int\n  Minimum polynomial degree of splines\n\ndeg_max : int\n  Maximum polynomial degree of splines\n\ncontinuity : ShapeContinuity\n  Continuity requirement on the approximating surface\n\ntol : float\n  Tolerance for the distance from individual points to the approximating surface.\n\nperiodic : bool\n  Whether the result should be periodic in the first surface parameter\n\ndegen_tol : double\n  Tolerance for resolution of degenerate edges\n\n)delimiter\");\n\n    m.def(\"SplineSurfaceInterpolation\", [](\n            py::array_t<double> pnt_array, Approx_ParametrizationType approx_type, bool periodic, double degen_tol) {\n\n          if (pnt_array.ndim() != 3)\n              throw Exception(\"`points` array must have dimension 3.\");\n          if (pnt_array.shape(2) != 3)\n              throw Exception(\"The third dimension must have size 3.\");\n\n          auto array = py::extract<py::array_t<double>>(pnt_array)();\n          TColgp_Array2OfPnt points(1, pnt_array.shape(0), 1, pnt_array.shape(1));\n          auto pnts_unchecked = pnt_array.unchecked<3>();\n          for (int i = 0; i < pnt_array.shape(0); ++i)\n              for (int j = 0; j < pnt_array.shape(1); ++j)\n                  points.SetValue(i+1, j+1, gp_Pnt(pnts_unchecked(i, j, 0), pnts_unchecked(i, j, 1), pnts_unchecked(i, j, 2)));\n\n          GeomAPI_PointsToBSplineSurface builder;\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4\n          builder.Interpolate(points, approx_type, periodic);\n#else\n          if(periodic)\n              throw Exception(\"periodic not supported\");\n          builder.Interpolate(points, approx_type);\n#endif\n          return BRepBuilderAPI_MakeFace(builder.Surface(), degen_tol).Face();\n      },\n      py::arg(\"points\"),\n      py::arg(\"approx_type\") = Approx_ParametrizationType::Approx_ChordLength,\n      py::arg(\"periodic\") = false,\n      py::arg(\"degen_tol\") = 1e-8,\n      R\"delimiter(\nGenerate a piecewise continuous spline-surface interpolating an array of points.\n\nParameters\n----------\n\npoints : np.ndarray\n  Array of points coordinates. The first dimension corresponds to the first surface coordinate point\n  index, the second dimension to the second surface coordinate point index. The third dimension refers to physical\n  coordinates. Such an array can be generated with code like::\n\n      px, py = np.meshgrid(*[np.linspace(0, 1, N)]*2)\n      points = np.array([[(px[i,j], py[i,j], px[i,j]*py[i,j]**2) for j in range(N)] for i in range(N)])\n\napprox_type : ApproxParamType\n  Assumption on location of parameters wrt points.\n\nperiodic : bool\n  Whether the result should be periodic in the first surface parameter\n\ndegen_tol : double\n  Tolerance for resolution of degenerate edges\n\n)delimiter\");\n\n\n  m.def(\"MakeFillet\", [](TopoDS_Shape shape, std::vector<TopoDS_Shape> edges, double r) {\n      throw Exception(\"call 'shape.MakeFilled'\");\n      BRepFilletAPI_MakeFillet mkFillet(shape);\n      for (auto e : edges)\n        mkFillet.Add (r, TopoDS::Edge(e));\n      return mkFillet.Shape();\n    }, \"deprecated, use 'shape.MakeFillet'\");\n\n  m.def(\"MakeThickSolid\", [](TopoDS_Shape body, std::vector<TopoDS_Shape> facestoremove,\n                             double offset, double tol) {\n          throw Exception(\"call 'shape.MakeThickSolid'\");\n          TopTools_ListOfShape faces;\n          for (auto f : facestoremove)\n            faces.Append(f);\n          \n          BRepOffsetAPI_MakeThickSolid maker;\n          maker.MakeThickSolidByJoin(body, faces, offset, tol);\n          return maker.Shape();\n        }, \"deprecated, use 'shape.MakeThickSolid'\");\n\n  m.def(\"ThruSections\", [](std::vector<TopoDS_Shape> wires, bool solid)\n        {\n          BRepOffsetAPI_ThruSections aTool(solid); // Standard_True);\n          for (auto shape : wires)\n            aTool.AddWire(TopoDS::Wire(shape));\n          aTool.CheckCompatibility(Standard_False);\n          return aTool.Shape();\n        }, py::arg(\"wires\"), py::arg(\"solid\")=true,\n        \"Building a loft. This is a shell or solid passing through a set of sections (wires). \"\n        \"First and last sections may be vertices. See https://dev.opencascade.org/doc/refman/html/class_b_rep_offset_a_p_i___thru_sections.html#details\");\n\n  m.def(\"ConnectEdgesToWires\", [](const vector<TopoDS_Shape>& edges,\n                                  double tol, bool shared)\n  {\n    Handle(TopTools_HSequenceOfShape) sedges = new TopTools_HSequenceOfShape;\n    Handle(TopTools_HSequenceOfShape) swires = new TopTools_HSequenceOfShape;\n    for(auto& e : edges)\n      sedges->Append(e);\n    ShapeAnalysis_FreeBounds::ConnectEdgesToWires(sedges, tol, shared, swires);\n    vector<TopoDS_Wire> wires;\n    for(auto& w : *swires)\n      wires.push_back(TopoDS::Wire(w));\n    return wires;\n  }, py::arg(\"edges\"), py::arg(\"tol\")=1e-8, py::arg(\"shared\")=true,\n  \"Connect edges into one or more wires using ShapeAnalysis_FreeBounds::ConnectEdgesToWires.\");\n\n  py::class_<WorkPlane, shared_ptr<WorkPlane>> (m, \"WorkPlane\")\n    .def(py::init<gp_Ax3, gp_Ax2d>(), py::arg(\"axes\")=gp_Ax3(), py::arg(\"pos\")=gp_Ax2d())\n    .def_property_readonly(\"cur_loc\", &WorkPlane::CurrentLocation)\n    .def_property_readonly(\"cur_dir\", &WorkPlane::CurrentDirection)\n    .def_property_readonly(\"start_pnt\", &WorkPlane::StartPnt)\n    .def(\"MoveTo\", &WorkPlane::MoveTo, py::arg(\"h\"), py::arg(\"v\"), \"moveto (h,v), and start new wire\")\n    .def(\"Move\", &WorkPlane::Move, py::arg(\"l\"), \"move 'l' from current position and direction, start new wire\")\n    .def(\"Direction\", &WorkPlane::Direction, py::arg(\"dirh\"), py::arg(\"dirv\"), \"reset direction to (dirh, dirv)\")    \n    // .def(\"LineTo\", &WorkPlane::LineTo)\n    .def(\"LineTo\", [](WorkPlane&wp, double x, double y, optional<string> name) { return wp.LineTo(x, y, name); },\n         py::arg(\"h\"), py::arg(\"v\"), py::arg(\"name\")=nullopt, \"draw line to position (h,v)\")\n    .def(\"ArcTo\", &WorkPlane::ArcTo, py::arg(\"h\"), py::arg(\"v\"),\n         py::arg(\"t\"), py::arg(\"name\")=nullopt, py::arg(\"maxh\")=nullopt)\n    .def(\"Arc\", &WorkPlane::Arc, py::arg(\"r\"), py::arg(\"ang\"), py::arg(\"name\")=nullopt, py::arg(\"maxh\")=nullopt, \"draw arc tangential to current pos/dir, of radius 'r' and angle 'ang', draw to the left/right if ang is positive/negative\")\n    .def(\"Rotate\", &WorkPlane::Rotate, py::arg(\"ang\"), \"rotate current direction by 'ang' degrees\")\n    .def(\"Line\", [](WorkPlane&wp,double l, optional<string> name) { return wp.Line(l, name); },\n         py::arg(\"l\"), py::arg(\"name\")=nullopt)\n    .def(\"Line\", [](WorkPlane&wp,double h,double v, optional<string> name) { return wp.Line(h,v,name); },\n         py::arg(\"dx\"), py::arg(\"dy\"), py::arg(\"name\")=nullopt)\n    .def(\"Spline\", &WorkPlane::Spline, py::arg(\"points\"), py::arg(\"periodic\")=false, py::arg(\"tol\")=1e-8,\n         py::arg(\"tangents\")=std::map<int, gp_Vec2d>{}, py::arg(\"start_from_localpos\")=true, py::arg(\"name\")=nullopt,\n         \"draw spline (default: starting from current position, which is implicitly added to given list of points), tangents can be specified for each point (0 refers to starting point)\")\n    .def(\"Rectangle\", &WorkPlane::Rectangle, py::arg(\"l\"), py::arg(\"w\"), py::arg(\"name\")=nullopt, \"draw rectangle, with current position as corner, use current direction\")\n    .def(\"RectangleC\", &WorkPlane::RectangleCentered, py::arg(\"l\"), py::arg(\"w\"), py::arg(\"name\")=nullopt, \"draw rectangle, with current position as center, use current direction\")\n    .def(\"Circle\", [](WorkPlane&wp, double x, double y, double r) {\n        return wp.Circle(x,y,r); }, py::arg(\"h\"), py::arg(\"v\"), py::arg(\"r\"), \"draw circle with center (h,v) and radius 'r'\")\n    .def(\"Circle\", [](WorkPlane&wp, double r) { return wp.Circle(r); }, py::arg(\"r\"), \"draw circle with center in current position\")\n    .def(\"Ellipse\", [](WorkPlane& wp, double major, double minor)\n    { return wp.Ellipse(major, minor); }, py::arg(\"major\"), py::arg(\"minor\"), \"draw ellipse with current position as center\")\n    .def(\"NameVertex\", &WorkPlane::NameVertex, py::arg(\"name\"), \"name vertex at current position\")\n    .def(\"Offset\", &WorkPlane::Offset, py::arg(\"d\"), \"replace current wire by offset curve of distance 'd'\")\n    .def(\"Reverse\", &WorkPlane::Reverse, \"revert orientation of current wire\")\n    .def(\"Close\", &WorkPlane::Close, py::arg(\"name\")=nullopt,\n         \"draw line to start point of wire, and finish wire\")\n    .def(\"Finish\", &WorkPlane::Finish, \"finish current wire without closing\")\n    .def(\"Last\", &WorkPlane::Last, \"(deprecated) returns current wire\")\n    .def(\"Wire\", &WorkPlane::Last, \"returns current wire\")\n    .def(\"Face\", &WorkPlane::Face, \"generate and return face of all wires, resets list of wires\")\n    .def(\"Wires\", &WorkPlane::Wires, \"returns all wires\")\n    ;\n}\n\n#endif // OCCGEOMETRY\n#endif // NG_PYTHON\n"
  },
  {
    "path": "libsrc/occ/utilities.h",
    "content": "//  SALOME Utils : general SALOME's definitions and tools\n//\n//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\n//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS \n// \n//  This library is free software; you can redistribute it and/or \n//  modify it under the terms of the GNU Lesser General Public \n//  License as published by the Free Software Foundation; either \n//  version 2.1 of the License. \n// \n//  This library is distributed in the hope that it will be useful, \n//  but WITHOUT ANY WARRANTY; without even the implied warranty of \n//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU \n//  Lesser General Public License for more details. \n// \n//  You should have received a copy of the GNU Lesser General Public \n//  License along with this library; if not, write to the Free Software \n//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA \n// \n//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org \n//\n//\n//\n//  File   : utilities.h\n//  Author : Antoine YESSAYAN, Paul RASCLE, EDF\n//  Module : SALOME\n//  $Header: /cvs/netgen/netgen/libsrc/occ/utilities.h,v 1.3 2008/03/31 14:20:28 wabro Exp $\n\n/* ---  Definition macros file to print information if _DEBUG_ is defined --- */\n\n#ifndef UTILITIES_H\n#define UTILITIES_H\n\n#include <string>\n#include <iostream>\n#include <cstdlib>\n// #include \"SALOME_Log.hxx\"\n\n/* ---  INFOS is always defined (without _DEBUG_): to be used for warnings, with release version --- */\n\n#define INFOS(msg)    {SLog->putMessage(*SLog<<__FILE__<<\" [\"<<__LINE__<<\"] : \"<<msg<<endl);}\n#define PYSCRIPT(msg) {SLog->putMessage(*SLog<<\"---PYSCRIPT--- \"<<msg<<endl);}\n\n/* --- To print date and time of compilation of current source --- */\n\n#if defined ( __GNUC__ )\n#define COMPILER\t\t\"g++\" \n#elif defined ( __sun )\n#define COMPILER\t\t\"CC\" \n#elif defined ( __KCC )\n#define COMPILER\t\t\"KCC\" \n#elif defined ( __PGI )\n#define COMPILER\t\t\"pgCC\" \n#elif defined ( __alpha )\n#define COMPILER\t\t\"cxx\" \n#else\n#define COMPILER\t\t\"undefined\" \n#endif\n\n#ifdef INFOS_COMPILATION\n#error INFOS_COMPILATION already defined\n#endif\n\n#define INFOS_COMPILATION { \\\n\t\t\t   SLog->putMessage(\\\n\t\t\t\t\t   *SLog<<__FILE__<<\" [\"<< __LINE__<<\"] : \"\\\n\t\t\t\t\t   << \"COMPILED with \" << COMPILER \\\n\t\t\t\t\t   << \", \" << __DATE__ \\\n\t\t\t\t\t   << \" at \" << __TIME__ <<endl); }\n\n#ifdef _DEBUG_\n\n/* --- the following MACROS are useful at debug time --- */\n\n#define MYTRACE *SLog << \"- Trace \" << __FILE__ << \" [\" << __LINE__ << \"] : \" \n\n#define MESSAGE(msg) {SLog->putMessage( MYTRACE <<msg<<endl<<ends); }\n#define SCRUTE(var)  {SLog->putMessage( MYTRACE << #var << \"=\" << var <<endl<<ends); }\n\n#define REPERE *SLog << \"   --------------\" << endl \n#define BEGIN_OF(msg) {REPERE;MYTRACE<<\"Begin of: \"     <<msg<<endl;REPERE;} \n#define END_OF(msg)   {REPERE;MYTRACE<<\"Normal end of: \"<<msg<<endl;REPERE;} \n\n#define HERE {cout<<flush ;cerr<<\"- Trace \"<<__FILE__<<\" [\"<<__LINE__<<\"] : \"<<flush ;}\n\n#define INTERRUPTION(code) {HERE;cerr<<\"INTERRUPTION return code= \"<<code<< endl;std::exit(code);}\n\n#ifndef ASSERT\n#define ASSERT(condition) \\\n        if (!(condition)){HERE;cerr<<\"CONDITION \"<<#condition<<\" NOT VERIFIED\"<<endl;INTERRUPTION(1);}\n#endif /* ASSERT */\n\n\n#else /* ifdef _DEBUG_*/\n\n#define HERE \n#define SCRUTE(var) {}\n#define MESSAGE(msg) {}\n#define REPERE\n#define BEGIN_OF(msg) {}\n#define END_OF(msg) {}\n\n#define INTERRUPTION(code) {}\n\n#ifndef ASSERT\n#define ASSERT(condition) {}\n#endif /* ASSERT */\n\n\n#endif /* ifdef _DEBUG_*/\n\n#endif /* ifndef UTILITIES_H */\n"
  },
  {
    "path": "libsrc/occ/vsocc.cpp",
    "content": "#ifndef NOTCL\n\n#ifdef OCCGEOMETRY\n\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n#include <meshing.hpp>\n\n#include <occgeom.hpp>\n\n#include <BRepAdaptor_Surface.hxx>\n#include <BRepBndLib.hxx>\n#include <BRepLProp_SLProps.hxx>\n#include <BRep_Tool.hxx>\n#include <Bnd_Box.hxx>\n#include <Geom_Curve.hxx>\n#include <Poly_PolygonOnTriangulation.hxx>\n#include <Poly_Triangle.hxx>\n#include <Poly_Triangulation.hxx>\n#include <TopoDS.hxx>\n#include <TopoDS_Edge.hxx>\n#include <gp_Pnt.hxx>\n\n#include <visual.hpp>\n\n#include \"vsocc.hpp\"\n\nnamespace netgen\n{\n  // extern OCCGeometry * occgeometry;\n\n   /* *********************** Draw OCC Geometry **************** */\n\n   VisualSceneOCCGeometry :: VisualSceneOCCGeometry ()\n   : VisualScene()\n   {\n      trilists.SetSize(0);\n      linelists.SetSize(1);\n\n   }\n\n   VisualSceneOCCGeometry :: ~VisualSceneOCCGeometry ()\n   {\n      ;\n   }\n\n   void VisualSceneOCCGeometry :: DrawScene ()\n   {\n      if ( occgeometry->changed )\n      {\n         BuildScene();\n         occgeometry -> changed = 0;\n      }\n      glDisable(GL_TEXTURE_2D);\n\n      glClearColor(backcolor, backcolor, backcolor, 1.0);\n      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n      SetLight();\n\n      glPushMatrix();\n      glMultMatrixd (transformationmat);\n\n      glShadeModel (GL_SMOOTH);\n      glDisable (GL_COLOR_MATERIAL);\n      glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n      glEnable (GL_BLEND);\n      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n      \n      //  glEnable (GL_LIGHTING);\n\n      double shine = vispar.shininess;\n      // double transp = vispar.transp;\n\n      glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);\n      glLogicOp (GL_COPY);\n\n      glEnable (GL_NORMALIZE);\n\n      float mat_col[] = {  0.2f, 0.2f, 0.8f, 1.0f};\n      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n      glPolygonOffset (1, 1);\n      glEnable (GL_POLYGON_OFFSET_FILL);\n\n      // Philippose - 30/01/2009\n      // Added clipping planes to Geometry view\n      SetClippingPlane();\n\n      GLfloat matcoledge[] = {  0, 0, 0, 1};\n      GLfloat matcolhiedge[] = {  1, 0, 0, 1};\n\n      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcoledge);\n      glLineWidth (1.0f);\n\n      if (vispar.occshowedges) glCallList (linelists.Get(1));\n      if (vispar.occshowsurfaces) glCallList (trilists.Get(1));\n\n      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge);\n      glLineWidth (5.0f);\n\n      if (vispar.occshowedges) glCallList (linelists.Get(2));\n\n      for (int i = 1; i <= occgeometry->vmap.Extent(); i++)\n      if (occgeometry->vvispar[i-1].IsHighlighted())\n      {\n         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge);\n         glLineWidth (5.0f);\n\n         glBegin (GL_LINES);\n\n         gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(occgeometry->vmap(i)));\n         double d = rad/100;\n         glVertex3f (p.X()-d, p.Y(), p.Z());\n         glVertex3f (p.X()+d, p.Y(), p.Z());\n         glVertex3f (p.X(), p.Y()-d, p.Z());\n         glVertex3f (p.X(), p.Y()+d, p.Z());\n         glVertex3f (p.X(), p.Y(), p.Z()-d);\n         glVertex3f (p.X(), p.Y(), p.Z()+d);\n         glEnd();\n      }\n\n      glDisable (GL_POLYGON_OFFSET_FILL);\n\n      glPopMatrix();\n      //  DrawCoordinateCross ();\n      //  DrawNetgenLogo ();\n      glFinish();\n\n      glDisable (GL_POLYGON_OFFSET_FILL);\n   }\n\n   /*\n    void VisualSceneOCCGeometry :: BuildScene (int zoomall)\n    {\n    int i = 0, j, k;\n\n    TopExp_Explorer ex, ex_edge;\n\n    if (vispar.occvisproblemfaces || (occgeometry -> changed != 2))\n    {\n    Box<3> bb = occgeometry -> GetBoundingBox();\n\n    center = bb.Center();\n    rad = bb.Diam() / 2;\n\n\n\n    if (vispar.occvisproblemfaces)\n    {\n    for (i = 1; i <= occgeometry->fmap.Extent(); i++)\n    if (occgeometry->facemeshstatus[i-1] == -1)\n    {\n    GProp_GProps system;\n    BRepGProp::LinearProperties(occgeometry->fmap(i), system);\n    gp_Pnt pnt = system.CentreOfMass();\n    center = Point<3> (pnt.X(), pnt.Y(), pnt.Z());\n    cout << \"Setting center to mid of face \" << i << \" = \" << center << endl;\n    }\n    }\n\n\n    CalcTransformationMatrices();\n    }\n\n\n    for (i = 1; i <= linelists.Size(); i++)\n    glDeleteLists (linelists.Elem(i), 1);\n    linelists.SetSize(0);\n\n    linelists.Append (glGenLists (1));\n    glNewList (linelists.Last(), GL_COMPILE);\n\n    i = 0;\n    for (ex_edge.Init(occgeometry -> shape, TopAbs_EDGE);\n    ex_edge.More(); ex_edge.Next())\n    {\n    if (BRep_Tool::Degenerated(TopoDS::Edge(ex_edge.Current()))) continue;\n    i++;\n\n\n    TopoDS_Edge edge = TopoDS::Edge(ex_edge.Current());\n\n    Handle(Poly_PolygonOnTriangulation) aEdgePoly;\n    Handle(Poly_Triangulation) T;\n    TopLoc_Location aEdgeLoc;\n    BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc);\n\n    if(aEdgePoly.IsNull())\n    {\n    cout << \"cannot visualize edge \" << i << endl;\n    continue;\n    }\n\n    glBegin (GL_LINE_STRIP);\n\n    int nbnodes = aEdgePoly -> NbNodes();\n    for (j = 1; j <= nbnodes; j++)\n    {\n    gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);\n    glVertex3f (p.X(), p.Y(), p.Z());\n    }\n\n    glEnd ();\n\n\n    }\n\n    glEndList ();\n\n    for (i = 1; i <= trilists.Size(); i++)\n    glDeleteLists (trilists.Elem(i), 1);\n    trilists.SetSize(0);\n\n\n    trilists.Append (glGenLists (1));\n    glNewList (trilists.Last(), GL_COMPILE);\n\n    i = 0;\n\n    TopExp_Explorer exp0, exp1, exp2, exp3;\n    int shapenr = 0;\n    for (exp0.Init(occgeometry -> shape, TopAbs_SOLID); exp0.More(); exp0.Next())\n    {\n    shapenr++;\n\n    if (vispar.occshowvolumenr != 0 &&\n    vispar.occshowvolumenr != shapenr) continue;\n\n    float mat_col[4];\n    mat_col[3] = 1;\n    switch (shapenr)\n    {\n    case 1:\n    mat_col[0] = 0.2;\n    mat_col[1] = 0.2;\n    mat_col[2] = 0.8;\n    break;\n    case 2:\n    mat_col[0] = 0.8;\n    mat_col[1] = 0.2;\n    mat_col[2] = 0.8;\n    break;\n    case 3:\n    mat_col[0] = 0.2;\n    mat_col[1] = 0.8;\n    mat_col[2] = 0.8;\n    break;\n    case 4:\n    mat_col[0] = 0.8;\n    mat_col[1] = 0.2;\n    mat_col[2] = 0.2;\n    break;\n    case 5:\n    mat_col[0] = 0.8;\n    mat_col[1] = 0.8;\n    mat_col[2] = 0.8;\n    break;\n    case 6:\n    mat_col[0] = 0.6;\n    mat_col[1] = 0.6;\n    mat_col[2] = 0.6;\n    break;\n    case 7:\n    mat_col[0] = 0.2;\n    mat_col[1] = 0.8;\n    mat_col[2] = 0.2;\n    break;\n    case 8:\n    mat_col[0] = 0.8;\n    mat_col[1] = 0.8;\n    mat_col[2] = 0.2;\n    break;\n    default:\n    //\t  mat_col[0] = 1-(1.0/double(shapenr));\n    //\t  mat_col[1] = 0.5;\n    mat_col[0] = 0.5+double((shapenr*shapenr*shapenr*shapenr) % 10)/20.0;\n    mat_col[1] = 0.5+double(int(shapenr*shapenr*shapenr*shapenr*sin(double(shapenr))) % 10)/20.0;\n    mat_col[2] = 0.5+double((shapenr*shapenr*shapenr) % 10)/20.0;\n    }\n\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n    for (exp1.Init(exp0.Current(), TopAbs_SHELL); exp1.More(); exp1.Next())\n    for (exp2.Init(exp1.Current().Composed(exp0.Current().Orientation()), TopAbs_FACE); exp2.More(); exp2.Next())\n    {\n    TopoDS_Face face = TopoDS::Face (exp2.Current().Composed(exp1.Current().Orientation()));\n\n    i = occgeometry->fmap.FindIndex(face);\n\n    TopLoc_Location loc;\n    Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n    BRepAdaptor_Surface sf(face, Standard_False);\n    BRepLProp_SLProps prop(sf, 1, 1e-5);\n    Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\n\n    if (triangulation.IsNull())\n    {\n    cout << \"cannot visualize face \" << i << endl;\n    continue;\n    }\n\n    if (vispar.occvisproblemfaces)\n    {\n    switch (occgeometry->facemeshstatus[i-1])\n    {\n    case 0:\n    mat_col[0] = 0.2;\n    mat_col[1] = 0.2;\n    mat_col[2] = 0.8;\n    break;\n    case 1:\n    mat_col[0] = 0.2;\n    mat_col[1] = 0.8;\n    mat_col[2] = 0.2;\n    break;\n    case -1:\n    mat_col[0] = 0.8;\n    mat_col[1] = 0.2;\n    mat_col[2] = 0.2;\n    break;\n    }\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n    }\n    glBegin (GL_TRIANGLES);\n\n    int ntriangles = triangulation -> NbTriangles();\n    for (j = 1; j <= ntriangles; j++)\n    {\n    Poly_Triangle triangle = (triangulation -> Triangles())(j);\n    for (k = 1; k <= 3; k++)\n    {\n    gp_Pnt2d uv = (triangulation -> UVNodes())(triangle(k));\n    gp_Pnt pnt;\n    gp_Vec du, dv;\n    prop.SetParameters (uv.X(), uv.Y());\n    surf->D0 (uv.X(), uv.Y(), pnt);\n    gp_Vec n;\n\n    if (prop.IsNormalDefined())\n    n = prop.Normal();\n    else\n    n = gp_Vec (0,0,0);\n\n    if (face.Orientation() == TopAbs_REVERSED) n *= -1;\n    glNormal3f (n.X(), n.Y(), n.Z());\n    glVertex3f (pnt.X(), pnt.Y(), pnt.Z());\n    }\n    }\n    glEnd ();\n\n    }\n    }\n\n\n    glEndList ();\n\n    }\n    */\n\n   void VisualSceneOCCGeometry :: BuildScene (int zoomall)\n   {\n     if (occgeometry -> changed == OCCGEOMETRYVISUALIZATIONFULLCHANGE)\n       {\n         occgeometry -> BuildVisualizationMesh (vispar.occdeflection);\n\n         center = occgeometry -> Center();\n         rad = occgeometry -> GetBoundingBox().Diam() / 2;\n\n         if (vispar.occzoomtohighlightedentity)\n         {\n            bool hilite = false;\n            bool hiliteonepoint = false;\n            Bnd_Box bb;\n\n            for (int i = 1; i <= occgeometry->fmap.Extent(); i++)\n            if (occgeometry->fvispar[i-1].IsHighlighted())\n            {\n               hilite = true;\n               BRepBndLib::Add (occgeometry->fmap(i), bb);\n            }\n\n            for (int i = 1; i <= occgeometry->emap.Extent(); i++)\n            if (occgeometry->evispar[i-1].IsHighlighted())\n            {\n               hilite = true;\n               BRepBndLib::Add (occgeometry->emap(i), bb);\n            }\n\n            for (int i = 1; i <= occgeometry->vmap.Extent(); i++)\n            if (occgeometry->vvispar[i-1].IsHighlighted())\n            {\n               hiliteonepoint = true;\n               BRepBndLib::Add (occgeometry->vmap(i), bb);\n            }\n\n            if (hilite || hiliteonepoint)\n            {\n               double x1,y1,z1,x2,y2,z2;\n               bb.Get (x1,y1,z1,x2,y2,z2);\n               Point<3> p1 = Point<3> (x1,y1,z1);\n               Point<3> p2 = Point<3> (x2,y2,z2);\n               Box<3> boundingbox(p1,p2);\n\n               center = boundingbox.Center();\n               if (hiliteonepoint)\n               rad = occgeometry -> GetBoundingBox().Diam() / 100;\n               else\n               rad = boundingbox.Diam() / 2;\n            }\n         }\n\n      }\n\n      // Clear lists\n\n      for (int i = 1; i <= linelists.Size(); i++)\n      glDeleteLists (linelists.Elem(i), 1);\n      linelists.SetSize(0);\n\n      for (int i = 1; i <= trilists.Size(); i++)\n      glDeleteLists (trilists.Elem(i), 1);\n      trilists.SetSize(0);\n\n      // Total wireframe\n\n      linelists.Append (glGenLists (1));\n      glNewList (linelists.Last(), GL_COMPILE);\n\n      for (int i = 1; i <= occgeometry->emap.Extent(); i++)\n      {\n         TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i));\n         if (BRep_Tool::Degenerated(edge)) continue;\n         if (occgeometry->evispar[i-1].IsHighlighted()) continue;\n\n         Handle(Poly_PolygonOnTriangulation) aEdgePoly;\n         Handle(Poly_Triangulation) T;\n         TopLoc_Location aEdgeLoc;\n         BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc);\n\n         if(aEdgePoly.IsNull())\n         {\n            (*testout) << \"visualizing edge \" << occgeometry->emap.FindIndex (edge)\n            << \" without using the occ visualization triangulation\" << endl;\n\n            double s0, s1;\n            Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);\n\n            glBegin (GL_LINE_STRIP);\n            for (int i = 0; i<=50; i++)\n            {\n               gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0);\n               glVertex3f (p.X(),p.Y(),p.Z());\n            }\n            glEnd ();\n\n            continue;\n         }\n\n         int nbnodes = aEdgePoly -> NbNodes();\n         glBegin (GL_LINE_STRIP);\n         for (int j = 1; j <= nbnodes; j++)\n         {\n           /*\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=5           \n           gp_Pnt p = T -> Node(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);\n#else           \n           gp_Pnt p = T -> Nodes()(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);\n#endif           \n           */\n           gp_Pnt p = T -> Node(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);           \n           glVertex3f (p.X(), p.Y(), p.Z());\n         }\n         glEnd ();\n      }\n\n      glEndList ();\n\n      // Highlighted edge list\n\n      linelists.Append (glGenLists (1));\n      glNewList (linelists.Last(), GL_COMPILE);\n\n      for (int i = 1; i <= occgeometry->emap.Extent(); i++)\n      if (occgeometry->evispar[i-1].IsHighlighted())\n      {\n         TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i));\n         if (BRep_Tool::Degenerated(edge)) continue;\n\n         Handle(Poly_PolygonOnTriangulation) aEdgePoly;\n         Handle(Poly_Triangulation) T;\n         TopLoc_Location aEdgeLoc;\n         BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc);\n\n         if(aEdgePoly.IsNull())\n         {\n            (*testout) << \"visualizing edge \" << occgeometry->emap.FindIndex (edge)\n            << \" without using the occ visualization triangulation\" << endl;\n\n            double s0, s1;\n            Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);\n\n            glBegin (GL_LINE_STRIP);\n            for (int i = 0; i<=50; i++)\n            {\n               gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0);\n               glVertex3f (p.X(),p.Y(),p.Z());\n            }\n            glEnd ();\n\n            continue;\n         }\n\n         int nbnodes = aEdgePoly -> NbNodes();\n         glBegin (GL_LINE_STRIP);\n         for (int j = 1; j <= nbnodes; j++)\n           {\n             /*\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=5\n             gp_Pnt p = T -> Node(aEdgePoly->Node(j)).Transformed(aEdgeLoc);\n#else             \n             gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);\n#endif             \n             */\n             gp_Pnt p = T -> Node(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);             \n             glVertex3f (p.X(), p.Y(), p.Z());\n           }\n         glEnd ();\n      }\n\n      glEndList ();\n\n      // display faces\n\n      trilists.Append (glGenLists (1));\n      glNewList (trilists.Last(), GL_COMPILE);\n\n      for (int i = 1; i <= occgeometry->fmap.Extent(); i++)\n      {\n         if (!occgeometry->fvispar[i-1].IsVisible()) continue;\n\n         glLoadName (i);\n         float mat_col[4];\n         mat_col[3] = 1;\n\n         TopoDS_Face face = TopoDS::Face(occgeometry->fmap(i));\n\n         if (!occgeometry->fvispar[i-1].IsHighlighted())\n         {\n           auto c = OCCGeometry::GetProperties(face).col.value_or(Vec<4>(0,1,0,1) );\n            for(auto j : Range(4))\n               mat_col[j] = c[j];\n         }\n         else\n         {\n            mat_col[0] = 0.8;\n            mat_col[1] = 0.2;\n            mat_col[2] = 0.2;\n         }\n\n         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n         TopLoc_Location loc;\n         Handle(Geom_Surface) surf = BRep_Tool::Surface (face);\n         BRepAdaptor_Surface sf(face, Standard_False);\n         BRepLProp_SLProps prop(sf, 1, 1e-5);\n         Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);\n\n         if (triangulation.IsNull())\n         {\n            cout << \"cannot visualize face \" << i << endl;\n            occgeometry->fvispar[i-1].SetNotDrawable();\n            continue;\n         }\n\n         gp_Pnt2d uv;\n         gp_Pnt pnt;\n         gp_Vec n;\n\n         glBegin (GL_TRIANGLES);\n         int ntriangles = triangulation -> NbTriangles();\n         for (int j = 1; j <= ntriangles; j++)\n         {\n           /*\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=5           \n           Poly_Triangle triangle = triangulation -> Triangle(j);\n#else\n           Poly_Triangle triangle = triangulation -> Triangles()(j);           \n#endif\n           */\n           Poly_Triangle triangle = triangulation -> Triangle(j);           \n           \n            gp_Pnt p[3];\n            for (int k = 1; k <= 3; k++)\n              p[k-1] = (triangulation -> Node(triangle(k))).Transformed(loc);\n\n            for (int k = 1; k <= 3; k++)\n            {\n#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=5              \n              uv = triangulation -> UVNode(triangle(k));\n#else              \n              uv = triangulation -> UVNodes()(triangle(k));\n#endif\n               prop.SetParameters (uv.X(), uv.Y());\n\n               //\t      surf->D0 (uv.X(), uv.Y(), pnt);\n\n               if (prop.IsNormalDefined())\n               n = prop.Normal();\n               else\n               {\n                  (*testout) << \"Visualization of face \" << i\n                  << \": Normal vector not defined\" << endl;\n                  //\t\t  n = gp_Vec (0,0,0);\n                  gp_Vec a(p[0],p[1]);\n                  gp_Vec b(p[0],p[2]);\n                  n = b^a;\n               }\n\n               if (face.Orientation() == TopAbs_REVERSED) n *= -1;\n               glNormal3f (n.X(), n.Y(), n.Z());\n               glVertex3f (p[k-1].X(), p[k-1].Y(), p[k-1].Z());\n            }\n         }\n         glEnd ();\n\n      }\n      glEndList ();\n\n      if(zoomall)\n         CalcTransformationMatrices();\n   }\n\n   void SelectFaceInOCCDialogTree (int facenr);\n\n   void VisualSceneOCCGeometry :: MouseDblClick (int px, int py)\n   {\n      int hits;\n\n      // select surface triangle by mouse click\n\n      GLuint selbuf[10000];\n      glSelectBuffer (10000, selbuf);\n\n      glRenderMode (GL_SELECT);\n\n      GLint viewport[4];\n      glGetIntegerv (GL_VIEWPORT, viewport);\n\n      glMatrixMode (GL_PROJECTION);\n      glPushMatrix();\n\n      GLdouble projmat[16];\n      glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n\n      glLoadIdentity();\n      gluPickMatrix (px, viewport[3] - py, 1, 1, viewport);\n      glMultMatrixd (projmat);\n\n      glClearColor(backcolor, backcolor, backcolor, 1.0);\n      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n      glMatrixMode (GL_MODELVIEW);\n\n      glPushMatrix();\n      glMultMatrixd (transformationmat);\n\n      glInitNames();\n      glPushName (1);\n\n      glPolygonOffset (1, 1);\n      glEnable (GL_POLYGON_OFFSET_FILL);\n\n      glDisable(GL_CLIP_PLANE0);\n\n      // Philippose - 30/01/2009\n      // Enable clipping planes for Selection mode in OCC Geometry\n      if (vispar.clipping.enable)\n      {\n         Vec<3> n(clipplane[0], clipplane[1], clipplane[2]);\n         double len = Abs(n);\n         double mu = -clipplane[3] / (len*len);\n         Point<3> p (mu * n);\n         n /= len;\n         Vec<3> t1 = n.GetNormal ();\n         Vec<3> t2 = Cross (n, t1);\n\n         double xi1mid = (center - p) * t1;\n         double xi2mid = (center - p) * t2;\n\n         glLoadName (0);\n         glBegin (GL_QUADS);\n         glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2);\n         glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2);\n         glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2);\n         glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2);\n         glEnd ();\n      }\n\n      glCallList (trilists.Get(1));\n\n      glDisable (GL_POLYGON_OFFSET_FILL);\n\n      glPopName();\n\n      glMatrixMode (GL_PROJECTION);\n      glPopMatrix();\n\n      glMatrixMode (GL_MODELVIEW);\n      glPopMatrix();\n\n      glFlush();\n\n      hits = glRenderMode (GL_RENDER);\n\n      int minname = 0;\n      GLuint mindepth = 0;\n\n      // find clippingplane\n      GLuint clipdepth = 0; // GLuint(-1);\n\n      for (int i = 0; i < hits; i++)\n      {\n         int curname = selbuf[4*i+3];\n         if (!curname) clipdepth = selbuf[4*i+1];\n      }\n\n      for (int i = 0; i < hits; i++)\n      {\n         int curname = selbuf[4*i+3];\n         GLuint curdepth = selbuf[4*i+1];\n         if (curname && (curdepth> clipdepth) &&\n               (curdepth < mindepth || !minname))\n         {\n            mindepth = curdepth;\n            minname = curname;\n         }\n      }\n\n      occgeometry->LowLightAll();\n\n      if (minname)\n      {\n         occgeometry->fvispar[minname-1].Highlight();\n\n         if (vispar.occzoomtohighlightedentity)\n         occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE;\n         else\n         occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\n         cout << \"Selected face: \" << minname << endl;\n      }\n      else\n      {\n         occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE;\n      }\n\n      glDisable(GL_CLIP_PLANE0);\n\n      SelectFaceInOCCDialogTree (minname);\n\n      // Philippose - 30/01/2009\n      // Set the currently selected face in the array\n      // for local face mesh size definition\n      occgeometry->SetSelectedFace(minname);\n\n      //  selecttimestamp = NextTimeStamp();\n   }\n\n}\n\n#endif\n\n#endif // NOTCL\n"
  },
  {
    "path": "libsrc/occ/vsocc.hpp",
    "content": "#ifndef FILE_VSOCC\n#define FILE_VSOCC\n\n/**************************************************************************/\n/* File:   vsocc.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   05. Jan. 2011                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n  class VisualSceneOCCGeometry : public VisualScene\n  {\n    NgArray<int> trilists;\n    NgArray<int> linelists;\n    // int selsurf;\n    class OCCGeometry * occgeometry;\n  public:\n    VisualSceneOCCGeometry ();\n    virtual ~VisualSceneOCCGeometry ();\n    void SetGeometry (class OCCGeometry * ageom) { occgeometry = ageom; }\n\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n    virtual void MouseDblClick (int px, int py);\n  };\n\n\n\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE\n        meshstlsurface.cpp stlgeom.cpp stlgeomchart.cpp \n        stlgeommesh.cpp stlline.cpp stltool.cpp stltopology.cpp python_stl.cpp\n)\n\nif(USE_GUI)\n    target_sources(nggui PRIVATE vsstl.cpp stlpkg.cpp)\nendif(USE_GUI)\n\ninstall(FILES\n  meshstlsurface.hpp stlgeom.hpp stlline.hpp\n  stltool.hpp stltopology.hpp vsstl.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/stlgeom COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/stlgeom/meshstlsurface.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n\n#include \"stlgeom.hpp\"\n\n\nnamespace netgen\n{\n\nstatic void STLFindEdges (STLGeometry & geom, Mesh & mesh,\n                          const MeshingParameters& mparam,\n                          const STLParameters& stlparam)\n{\n  double h = mparam.maxh;\n\n  // mark edge points:\n  //int ngp = geom.GetNP();\n\n  geom.RestrictLocalH(mesh, h, stlparam, mparam);\n  \n  PushStatusF(\"Mesh Lines\");\n\n  NgArray<STLLine*> meshlines;\n  NgArray<Point3d> meshpoints;\n\n  PrintMessage(3,\"Mesh Lines\");\n\n  /*\n  cout << geom.GetNLines() << \" lines\" << endl;\n  double totnp = 0;\n  for (int i = 1; i <= geom.GetNLines(); i++)\n    totnp += geom.GetLine(i)->NP();\n  cout << \"avg np per line \" << totnp/geom.GetNLines() << endl;\n  */\n\n  for (int i = 1; i <= geom.GetNLines(); i++)\n    {\n      meshlines.Append(geom.GetLine(i)->Mesh(geom.GetPoints(), meshpoints, h, mesh)); \n      SetThreadPercent(100.0 * (double)i/(double)geom.GetNLines());\n    }\n\n  geom.meshpoints.SetSize(0); //testing\n  geom.meshlines.SetSize(0);  //testing\n  for (int i = 1; i <= meshpoints.Size(); i++)\n    {\n      geom.meshpoints.Append(meshpoints.Get(i)); //testing\n      mesh.AddPoint(meshpoints.Get(i));\n    }\n  //(++++++++++++++testing\n  for (int i = 1; i <= geom.GetNLines(); i++)\n    {\n      geom.meshlines.Append(meshlines.Get(i));\n    }\n  //++++++++++++++testing)\n\n  PrintMessage(7,\"feed with edges\");\n\n  for (int i = 1; i <= meshlines.Size(); i++)\n    {\n      STLLine* line = meshlines.Get(i);\n      (*testout) << \"store line \" << i << endl;\n      for (int j = 1; j <= line->GetNS(); j++)\n\t{\n\t  int p1, p2;\n\t  \n\t  line->GetSeg(j, p1, p2);\n\t  int trig1, trig2, trig1b, trig2b;\n\n\t  if (p1 == p2) \n\t    cout << \"Add Segment, p1 == p2 == \" << p1 << endl;\n\n\t  // Test auf geschlossener Rand mit 2 Segmenten \n\t      \n\t  if ((j == 2) && (line->GetNS() == 2))\n\t    {\n\t      int oldp1, oldp2;\n\t      line->GetSeg (1, oldp1, oldp2);\n\t      if (oldp1 == p2 && oldp2 == p1)\n\t\t{\n\t\t  PrintMessage(7,\"MESSAGE: don't use second segment\");\n\t\t  continue;\n\t\t}\n\t    }\n\n\n\t  //mesh point number\n\t  //p1 = geom2meshnum.Get(p1); // for unmeshed lines!!!\n\t  //p2 = geom2meshnum.Get(p2); // for unmeshed lines!!!\n\t  \n\t  //left and right trigs\n\t  trig1 = line->GetLeftTrig(j);\n\t  trig2 = line->GetRightTrig(j);\n\t  trig1b = line->GetLeftTrig(j+1);\n\t  trig2b = line->GetRightTrig(j+1);\n\t  \n\t  (*testout) << \"j = \" << j << \", p1 = \" << p1 << \", p2 = \" << p2 << endl;\n\t  (*testout) << \"segm-trigs: \"\n\t\t   << \"trig1 = \" << trig1\n\t\t   << \", trig1b = \" << trig1b\n\t\t   << \", trig2 = \" << trig2\n\t\t   << \", trig2b = \" << trig2b << endl;\n\n\t  if (trig1 <= 0 || trig2 < 0 || trig1b <= 0 || trig2b < 0)\n\t    {\n\t      cout << \"negative trigs, \"\n\t\t   << \", trig1 = \" << trig1\n\t\t   << \", trig1b = \" << trig1b\n\t\t   << \", trig2 = \" << trig2\n\t\t   << \", trig2b = \" << trig2b << endl;\n\t    }\n\t  /*\n\t  (*testout) << \"   trigs p1: \" << trig1 << \" - \" << trig2 << endl;\n\t  (*testout) << \"   trigs p2: \" << trig1b << \" - \" << trig2b << endl;\n\t  (*testout) << \"   charts p1: \" << geom.GetChartNr(trig1) << \" - \" << geom.GetChartNr(trig2) << endl;\n\t  (*testout) << \"   charts p2: \" << geom.GetChartNr(trig1b) << \" - \" << geom.GetChartNr(trig2b) << endl;\n\t  */\n\t  Point3d hp, hp2;\n\t  Segment seg;\n\t  seg[0] = p1 + PointIndex::BASE-1;\n\t  seg[1] = p2 + PointIndex::BASE-1;\n\t  seg.si = geom.GetTriangle(trig1).GetFaceNum();\n\t  seg.edgenr = i;\n\n\t  seg.epgeominfo[0].edgenr = i;\n\t  seg.epgeominfo[0].dist = line->GetDist(j);\n\t  seg.epgeominfo[1].edgenr = i;\n\t  seg.epgeominfo[1].dist = line->GetDist(j+1);\n\t  /*\n\t  (*testout) << \"seg = \" \n\t\t     << \"edgenr \" << seg.epgeominfo[0].edgenr\n\t\t     << \" dist \" << seg.epgeominfo[0].dist\n\t\t     << \" edgenr \" << seg.epgeominfo[1].edgenr\n\t\t     << \" dist \" << seg.epgeominfo[1].dist << endl;\n\t  */\n\t  \n\t  seg.geominfo[0].trignum = trig1;\n\t  seg.geominfo[1].trignum = trig1b;\n\n\t  /*\n\t  geom.SelectChartOfTriangle (trig1);\n\t  hp = hp2 = mesh.Point (seg[0]);\n\t  seg.geominfo[0].trignum = geom.Project (hp);\n\n\t  (*testout) << \"hp = \" << hp2 << \", hp proj = \" << hp << \", trignum = \" << seg.geominfo[0].trignum << endl;\n\t  if (Dist (hp, hp2) > 1e-5 || seg.geominfo[0].trignum == 0) \n\t    {\n\t      (*testout) << \"PROBLEM\" << endl;\n\t    }\n\n\t  geom.SelectChartOfTriangle (trig1b);\n\t  hp = hp2 = mesh.Point (seg[1]);\n\t  seg.geominfo[1].trignum = geom.Project (hp);\n\n\t  (*testout) << \"hp = \" << hp2 << \", hp proj = \" << hp << \", trignum = \" << seg.geominfo[1].trignum << endl;\n\t  if (Dist (hp, hp2) > 1e-5 || seg.geominfo[1].trignum == 0) \n\t    {\n\t      (*testout) << \"PROBLEM\" << endl;\n\t    }\n\t  */\n\n\n\t  if (Dist (mesh.Point(seg[0]), mesh.Point(seg[1])) < 1e-10)\n\t    {\n\t      (*testout) << \"ERROR: Line segment of length 0\" << endl;\n\t      (*testout) << \"pi1, 2 = \" << seg[0] << \", \" << seg[1] << endl;\n\t      (*testout) << \"p1, 2 = \" << mesh.Point(seg[0])\n\t\t\t << \", \" << mesh.Point(seg[1]) << endl;\n\t      throw NgException (\"Line segment of length 0\");\n\t    }\n\t  \n\t  mesh.AddSegment (seg);\n\n\n          if(trig2 != 0)\n            {\n\t  Segment seg2;\n\t  seg2[0] = p2 + PointIndex::BASE-1;;\n\t  seg2[1] = p1 + PointIndex::BASE-1;;\n\t  seg2.si = geom.GetTriangle(trig2).GetFaceNum();\n\n\t  seg2.edgenr = i;\n\n\t  seg2.epgeominfo[0].edgenr = i;\n\t  seg2.epgeominfo[0].dist = line->GetDist(j+1);\n\t  seg2.epgeominfo[1].edgenr = i;\n\t  seg2.epgeominfo[1].dist = line->GetDist(j);\n\t  /*\n\t  (*testout) << \"seg = \" \n\t\t     << \"edgenr \" << seg2.epgeominfo[0].edgenr\n\t\t     << \" dist \" << seg2.epgeominfo[0].dist\n\t\t     << \" edgenr \" << seg2.epgeominfo[1].edgenr\n\t\t     << \" dist \" << seg2.epgeominfo[1].dist << endl;\n\t  */\n\t  \n\t  seg2.geominfo[0].trignum = trig2b;\n\t  seg2.geominfo[1].trignum = trig2;\n\t  \n\t  /*\n\t  geom.SelectChartOfTriangle (trig2);\n\t  hp = hp2 = mesh.Point (seg[0]);\n\t  seg2.geominfo[0].trignum = geom.Project (hp);\n\n\t  (*testout) << \"hp = \" << hp2 << \", hp proj = \" << hp << \", trignum = \" << seg.geominfo[0].trignum << endl;\n\t  if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[0].trignum == 0) \n\t    {\n\t      (*testout) << \"Get GeomInfo PROBLEM\" << endl;\n\t    }\n\n\n\t  geom.SelectChartOfTriangle (trig2b);\n\t  hp = hp2 = mesh.Point (seg[1]);\n\t  seg2.geominfo[1].trignum = geom.Project (hp);\n\t  (*testout) << \"hp = \" << hp2 << \", hp proj = \" << hp << \", trignum = \" << seg.geominfo[1].trignum << endl;\n\t  if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[1].trignum == 0) \n\t    {\n\t      (*testout) << \"Get GeomInfo PROBLEM\" << endl;\n\t    }\n\t  */\t  \n\t  mesh.AddSegment (seg2);\n            }\n\t}\n    }\n\n  PopStatus();\n}\n\n\n\n\nvoid STLSurfaceMeshing1 (STLGeometry & geom, class Mesh & mesh, const MeshingParameters& mparam,\n\t\t\t int retrynr, const STLParameters& stlparam);\n\n\nint STLSurfaceMeshing (STLGeometry & geom, class Mesh & mesh, const MeshingParameters& mparam,\n                       const STLParameters& stlparam)\n{\n  PrintFnStart(\"Do Surface Meshing\");\n\n  geom.PrepareSurfaceMeshing();\n\n  if (mesh.GetNSeg() == 0)\n    STLFindEdges (geom, mesh, mparam, stlparam);\n\n  int nopen;\n  int outercnt = 20;\n\n  for (int i = 1; i <= mesh.GetNSeg(); i++)\n    {\n      const Segment & seg = mesh.LineSegment (i);\n      if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0)\n\t(*testout) << \"Problem with segment \" << i << \": \" << seg << endl;\n    }\n\n\n  do\n    {\n      outercnt--;\n      if (outercnt <= 0)\n\treturn MESHING3_OUTERSTEPSEXCEEDED;\n      \n      if (multithread.terminate) return MESHING3_TERMINATE;\n\n      mesh.FindOpenSegments();\n      nopen = mesh.GetNOpenSegments();\n\n      if (nopen)\n\t{\n\t  int trialcnt = 0;\n\t  while (nopen && trialcnt <= 5)\n\t    {\n\t      if (multithread.terminate) { return MESHING3_TERMINATE; }\n\n\t      trialcnt++;\n\t      STLSurfaceMeshing1 (geom, mesh, mparam, trialcnt, stlparam);\n\n\t      mesh.FindOpenSegments();\n\t      nopen = mesh.GetNOpenSegments();\n\n              auto n_illegal_trigs = mesh.FindIllegalTrigs();\n              PrintMessage (3, n_illegal_trigs, \" illegal triangles\");\n\n\t      if (nopen)\n\t\t{\n\t\t  geom.ClearMarkedSegs();\n\t\t  for (int i = 1; i <= nopen; i++)\n\t\t    {\n\t\t      const Segment & seg = mesh.GetOpenSegment (i);\n\t\t      geom.AddMarkedSeg(mesh.Point(seg[0]),mesh.Point(seg[1]));\n\t\t    }\n\n\t\t  geom.InitMarkedTrigs();\n\t\t  for (int i = 1; i <= nopen; i++)\n\t\t    {\n\t\t      const Segment & seg = mesh.GetOpenSegment (i);\n\t\t      geom.SetMarkedTrig(seg.geominfo[0].trignum,1);\n\t\t      geom.SetMarkedTrig(seg.geominfo[1].trignum,1);\n\t\t    }\n\n\t\t  MeshOptimize2d optmesh(mesh);\n\t\t  optmesh.SetFaceIndex (0);\n\t\t  optmesh.SetImproveEdges (0);\n\t\t  optmesh.SetMetricWeight (0);\n\t\t  \n\t\t  mesh.CalcSurfacesOfNode();\n\t\t  optmesh.EdgeSwapping (0);\n\t\t  optmesh.ImproveMesh (mparam);\n\t\t}\n\n\t      mesh.Compress();\n\t      mesh.FindOpenSegments();\n\t      nopen = mesh.GetNOpenSegments();\n\n\t      if (trialcnt <= 5 && nopen)\n\t\t{\n\t\t  mesh.RemoveOneLayerSurfaceElements();\n\n\t\t  if (trialcnt >= 4)\n\t\t    {\n\t\t      mesh.FindOpenSegments();\n\t\t      mesh.RemoveOneLayerSurfaceElements();\n\n\t\t      mesh.FindOpenSegments ();\t\t  \n\t\t      nopen = mesh.GetNOpenSegments();\n\t\t    }\n\t\t}\n\t    }\n\n\n\t  if (multithread.terminate)\n\t    return MESHING3_TERMINATE;\n\n\t  if (nopen)\n\t    {\n\t      \n\t      PrintMessage(3,\"Meshing failed, trying to refine\");\n\n\t      mesh.FindOpenSegments ();\n\t      nopen = mesh.GetNOpenSegments();\n\t\t\t  \n\t      mesh.FindOpenSegments ();\n\t      mesh.RemoveOneLayerSurfaceElements();\n\t      mesh.FindOpenSegments ();\n\t      mesh.RemoveOneLayerSurfaceElements();\n\n\t      // Open edge-segments will be refined !\n\t      INDEX_2_HASHTABLE<int> openseght (nopen+1);\n\t      for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n\t\t{\n\t\t  const Segment & seg = mesh.GetOpenSegment (i);\n\t\t  INDEX_2 i2(seg[0], seg[1]);\n\t\t  i2.Sort();\n\t\t  openseght.Set (i2, 1);\n\t\t}\n\n\t      \n\t      mesh.FindOpenSegments ();\n\t      mesh.RemoveOneLayerSurfaceElements();\n\t      mesh.FindOpenSegments ();\n\t      mesh.RemoveOneLayerSurfaceElements();\n\t      \n\n\t      INDEX_2_HASHTABLE<int> newpht(100);\n\n\t      int nsegold = mesh.GetNSeg();\n\t      for (int i = 1; i <= nsegold; i++)\n\t\t{\n\t\t  Segment seg = mesh.LineSegment(i);\n\t\t  INDEX_2 i2(seg[0], seg[1]);\n\t\t  i2.Sort();\n\t\t  if (openseght.Used (i2))\n\t\t    {\n\t\t      // segment will be split\n\t\t      PrintMessage(7,\"Split segment \", int(seg[0]), \"-\", int(seg[1]));\n\t      \n\t\t      Segment nseg1, nseg2;\n\t\t      EdgePointGeomInfo newgi;\n\t\t      \n\t\t      const EdgePointGeomInfo & gi1 = seg.epgeominfo[0];\n\t\t      const EdgePointGeomInfo & gi2 = seg.epgeominfo[1];\n\t\t      \n\t\t      newgi.dist = 0.5 * (gi1.dist + gi2.dist);\n\t\t      newgi.edgenr = gi1.edgenr;\n\n\t\t      int hi;\n\t\t      \n\t\t      Point3d newp;\n\t\t      int newpi;\n\t\t      \n\t\t      if (!newpht.Used (i2))\n\t\t\t{\n\t\t\t  newp = geom.GetLine (gi1.edgenr)->\n\t\t\t    GetPointInDist (geom.GetPoints(), newgi.dist, hi);\n\t\t\t  newpi = mesh.AddPoint (newp);\n\t\t\t  newpht.Set (i2, newpi);\n\t\t\t}\n\t\t      else\n\t\t\t{\n\t\t\t  newpi = newpht.Get (i2);\n\t\t\t  newp = mesh.Point (newpi);\n\t\t\t}\n\n\t\t      nseg1 = seg;\n\t\t      nseg2 = seg;\n\t\t      nseg1[1] = newpi;\n\t\t      nseg1.epgeominfo[1] = newgi;\n\t\t      \n\t\t      nseg2[0] = newpi;\n\t\t      nseg2.epgeominfo[0] = newgi;\n\t\t      \n\t\t      mesh.LineSegment(i) = nseg1;\n\t\t      mesh.AddSegment (nseg2);\n\t\t      \n\t\t      mesh.RestrictLocalH (Center (mesh.Point(nseg1[0]),\n\t\t\t\t\t\t   mesh.Point(nseg1[1])),\n\t\t\t\t\t   Dist (mesh.Point(nseg1[0]),\n\t\t\t\t\t\t mesh.Point(nseg1[1])));\n\t\t      mesh.RestrictLocalH (Center (mesh.Point(nseg2[0]),\n\t\t\t\t\t\t   mesh.Point(nseg2[1])),\n\t\t\t\t\t   Dist (mesh.Point(nseg2[0]),\n\t\t\t\t\t\t mesh.Point(nseg2[1])));\n\t\t    }\n\t\t}\n\n\t    }\n\n\t  nopen = -1;\n\t}\n    \n      else\n\n\t{\n\t  PrintMessage(5,\"mesh is closed, verifying ...\");\n\n\t  // no open elements, check wrong elements (intersecting..)\n\n\n\n\t  PrintMessage(5,\"check overlapping\");\n\t  // \t  mesh.FindOpenElements(); // would leed to locked points\n          mesh.CheckOverlappingBoundary();\n\t  // if(mesh.CheckOverlappingBoundary()) ;\n          // return MESHING3_BADSURFACEMESH;\n\n\t  geom.InitMarkedTrigs();\n\n\t  for (int i = 1; i <= mesh.GetNSE(); i++)\n\t    if (mesh.SurfaceElement(i).BadElement())\n\t      {\n\t\tint trig = mesh.SurfaceElement(i).PNum(1);\n\t\tgeom.SetMarkedTrig(trig,1);\n\t\tPrintMessage(7, \"overlapping element, will be removed\");\n\t      }\n\t  \n\t  \n\n\t  NgArray<Point3d> refpts;\n\t  NgArray<double> refh;\n\n\t  // was commented:\n\n\t  for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t    if (mesh[sei].BadElement())\n\t      {\n\t\tfor (int j = 1; j <= 3; j++)\n\t\t  {\n\t\t    refpts.Append (mesh.Point (mesh[sei].PNum(j)));\n\t\t    refh.Append (mesh.GetH (refpts.Last()) / 2);\n\t\t  }\n\t\tmesh.Delete(sei);\n\t      }\n\t  \t  \n\t  // delete wrong oriented element\n\t  for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)\n\t    {\n\t      const Element2d & el = mesh[sei];\n              if (el.IsDeleted()) continue;\n\t      if (!el.PNum(1).IsValid()) continue;\n\n\t      Vec3d n = Cross (Vec3d (mesh.Point(el.PNum(1)), \n\t\t\t\t      mesh.Point(el.PNum(2))),\n\t\t\t       Vec3d (mesh.Point(el.PNum(1)), \n\t\t\t\t      mesh.Point(el.PNum(3))));\n\t      Vec3d ng = geom.GetTriangle(el.GeomInfoPi(1).trignum).Normal();\n\t      if (n * ng < 0)\n\t\t{\n\t\t  refpts.Append (mesh.Point (mesh[sei].PNum(1)));\n\t\t  refh.Append (mesh.GetH (refpts.Last()) / 2);\n\t\t  mesh.Delete(sei);\n\t\t}\n\t    }\n\t  // end comments\n\n\t  for (int i = 1; i <= refpts.Size(); i++)\n\t    mesh.RestrictLocalH (refpts.Get(i), refh.Get(i));\n\n\t  mesh.RemoveOneLayerSurfaceElements();\n          // Open edge-segments will be refined !\n\t      INDEX_2_HASHTABLE<int> openseght (nopen+1);\n\t      for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n\t\t{\n\t\t  const Segment & seg = mesh.GetOpenSegment (i);\n\t\t  INDEX_2 i2(seg[0], seg[1]);\n\t\t  i2.Sort();\n\t\t  openseght.Set (i2, 1);\n\t\t}\n          mesh.FindOpenSegments ();\n          mesh.RemoveOneLayerSurfaceElements();\n          mesh.FindOpenSegments ();\n          int nsegold = mesh.GetNSeg();\n          INDEX_2_HASHTABLE<int> newpht(100);\n          for (int i = 1; i <= nsegold; i++)\n            {\n              Segment seg = mesh.LineSegment(i);\n              INDEX_2 i2(seg[0], seg[1]);\n              i2.Sort();\n              if (openseght.Used (i2))\n                {\n                  // segment will be split\n                  PrintMessage(7,\"Split segment \", int(seg[0]), \"-\", int(seg[1]));\n\t      \n                  Segment nseg1, nseg2;\n                  EdgePointGeomInfo newgi;\n\t\t      \n                  const EdgePointGeomInfo & gi1 = seg.epgeominfo[0];\n                  const EdgePointGeomInfo & gi2 = seg.epgeominfo[1];\n\t\t      \n                  newgi.dist = 0.5 * (gi1.dist + gi2.dist);\n                  newgi.edgenr = gi1.edgenr;\n\n                  int hi;\n\t\t      \n                  Point3d newp;\n                  int newpi;\n\t\t      \n                  if (!newpht.Used (i2))\n                    {\n                      newp = geom.GetLine (gi1.edgenr)->\n                        GetPointInDist (geom.GetPoints(), newgi.dist, hi);\n                      newpi = mesh.AddPoint (newp);\n                      newpht.Set (i2, newpi);\n                    }\n                  else\n                    {\n                      newpi = newpht.Get (i2);\n                      newp = mesh.Point (newpi);\n                    }\n\n                  nseg1 = seg;\n                  nseg2 = seg;\n                  nseg1[1] = newpi;\n                  nseg1.epgeominfo[1] = newgi;\n\t\t      \n                  nseg2[0] = newpi;\n                  nseg2.epgeominfo[0] = newgi;\n\t\t      \n                  mesh.LineSegment(i) = nseg1;\n                  mesh.AddSegment (nseg2);\n\t\t      \n                  mesh.RestrictLocalH (Center (mesh.Point(nseg1[0]),\n                                               mesh.Point(nseg1[1])),\n                                       Dist (mesh.Point(nseg1[0]),\n                                             mesh.Point(nseg1[1])));\n                  mesh.RestrictLocalH (Center (mesh.Point(nseg2[0]),\n                                               mesh.Point(nseg2[1])),\n                                       Dist (mesh.Point(nseg2[0]),\n                                             mesh.Point(nseg2[1])));\n                }\n            }\n\t  mesh.Compress();\n\t  \n\t  mesh.FindOpenSegments ();\n\t  nopen = mesh.GetNOpenSegments();\n\n\t  /*\n\t  if (!nopen)\n\t    {\n\t      // mesh is still ok\n\n\t      void STLSurfaceOptimization (STLGeometry & geom,\n\t\t\t\t\t   class Mesh & mesh,\n\t\t\t\t\t   MeshingParameters & mparam)\n\t      \n\t    }\n\t  */\n\t}\n      \n    }\n  while (nopen);\n\n  if(mesh.CheckOverlappingBoundary())\n    return MESHING3_BADSURFACEMESH;\n\n  mesh.Compress();\n  mesh.CalcSurfacesOfNode();\n\n  return MESHING3_OK;\n}\n\n\n\n\n\n\nvoid STLSurfaceMeshing1 (STLGeometry & geom,\n\t\t\t Mesh & mesh,\n                         const MeshingParameters& mparam,\n\t\t\t int retrynr,\n                         const STLParameters& stlparam)\n{\n  static int timer1 = NgProfiler::CreateTimer (\"STL surface meshing1\");\n  static int timer1a = NgProfiler::CreateTimer (\"STL surface meshing1a\");\n  static int timer1b = NgProfiler::CreateTimer (\"STL surface meshing1b\");\n  static int timer1c = NgProfiler::CreateTimer (\"STL surface meshing1c\");\n  static int timer1d = NgProfiler::CreateTimer (\"STL surface meshing1d\");\n\n  double h = mparam.maxh;\n\n  mesh.FindOpenSegments();\n  \n  NgArray<int> spiralps(0);\n  spiralps.SetSize(0);\n  for (int i = 1; i <= geom.GetNP(); i++)\n    if (geom.GetSpiralPoint(i)) \n      spiralps.Append(i);\n  \n  PrintMessage(7,\"NO spiralpoints = \", spiralps.Size());\n  //int spfound;\n\n  /*\n  NgArray<int> meshsp(mesh.GetNP());\n  meshsp = 0;\n  for (int i = 1; i <= mesh.GetNP(); i++)\n    for (int j = 1; j <= spiralps.Size(); j++)\n      if (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20) \n\tmeshsp.Elem(i) = spiralps.Get(j);\n  NgArray<PointIndex> imeshsp;\n  for (int i = 1; i <= meshsp.Size(); i++)\n    if (meshsp.Elem(i)) imeshsp.Append(i);\n  */\n  NgArray<PointIndex> imeshsp;\n  NgArray<int> ispiral_point;\n  for (int i = 1; i <= mesh.GetNP(); i++)\n    {\n      for (int j = 1; j <= spiralps.Size(); j++)\n\tif (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20) \n\t  {\n\t    imeshsp.Append(i);\n\t    ispiral_point.Append(spiralps.Get(j));\n\t    break;\n\t  }\n    }\n\n  double starttime = GetTime ();\n  mesh.SurfaceArea().ReCalc();\n\n  // int oldnp = mesh.GetNP();\n\n  NgArray<int,PointIndex::BASE> compress(mesh.GetNP());\n  compress = 0;\n  NgArray<PointIndex> icompress; \n\n  NgArray<int, 1> opensegsperface(mesh.GetNFD());\n  opensegsperface = 0;\n  for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n    opensegsperface[mesh.GetOpenSegment(i).si]++;\n  \n  TABLE<int, 1> opensegments(mesh.GetNFD());\n  for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n    {\n      const Segment & seg = mesh.GetOpenSegment (i);\n      if (seg.si < 1 || seg.si > mesh.GetNFD())\n\tcerr << \"segment index \" << seg.si << \" out of range [1, \" << mesh.GetNFD() << \"]\" << endl;\n      opensegments.Add (seg.si, i);\n    }\n  \n\n  for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++)\n    {\n      if (!opensegsperface[fnr]) continue;\n      if (multithread.terminate) return;\n\n      NgProfiler::StartTimer (timer1);\n      NgProfiler::StartTimer (timer1a);\n\n\n      PrintMessage(5,\"Meshing surface \", fnr, \"/\", mesh.GetNFD());\n      MeshingSTLSurface meshing (geom, mparam);\n      meshing.SetStartTime (starttime);\n      \n      // compress = 0;\n      icompress.SetSize(0); \n      int cntused = 0;\n\n      for (int i = 0; i < imeshsp.Size(); i++)\n\t{\n\t  compress[imeshsp[i]] = ++cntused;\n\t  icompress.Append(imeshsp[i]);\n\t}\n\n      NgProfiler::StopTimer (timer1a);\n      NgProfiler::StartTimer (timer1b);\n\n\n\n      /*\n      for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n\t{\n\t  const Segment & seg = mesh.GetOpenSegment (i);\n\t  if (seg.si == fnr)\n\t    for (int j = 0; j < 2; j++)\n\t      if (compress[seg[j]] == 0)\n\t\t{\n\t\t  compress[seg[j]] = ++cntused;\n\t\t  icompress.Append(seg[j]);\n\t\t}\n\t}\n      */\n      NgFlatArray<int> segs = opensegments[fnr];\n      for (int hi = 0; hi < segs.Size(); hi++)\n\t{\n\t  int i = segs[hi];\n\t  const Segment & seg = mesh.GetOpenSegment (i);\n\t  for (int j = 0; j < 2; j++)\n\t    if (compress[seg[j]] == 0)\n\t      {\n\t\tcompress[seg[j]] = ++cntused;\n\t\ticompress.Append(seg[j]);\n\t      }\n\t}\n\n      NgProfiler::StopTimer (timer1b);\n      NgProfiler::StartTimer (timer1c);\n\n\n      for (int hi = 0; hi < icompress.Size(); hi++)\n\t{\n\t  PointIndex pi = icompress[hi];\n\t  \n\t  /*\n\t  // int sppointnum = meshsp.Get(i);\n\t  int sppointnum = 0;\n\t  if (hi < ispiral_point.Size())\n\t    sppointnum = ispiral_point[hi];\n\n\t  if (sppointnum)\n\t    {\n\t  */\n\t  if (hi < ispiral_point.Size())\n\t    {\n\t      int sppointnum = ispiral_point[hi];\n\n\t      MultiPointGeomInfo mgi;\n\t      \n\t      int ntrigs = geom.NOTrigsPerPoint(sppointnum);\n\t      for (int j = 0; j < ntrigs; j++)\n\t\t{\n\t\t  PointGeomInfo gi;\n\t\t  gi.trignum = geom.TrigPerPoint(sppointnum, j+1);\n\t\t  mgi.AddPointGeomInfo (gi);\n\t\t}\n\t      \n\t      // Einfuegen von ConePoint: Point bekommt alle\n\t      // Dreiecke (werden dann intern kopiert)\n\t      // Ein Segment zum ConePoint muss vorhanden sein !!!\n\t      \n\t      // meshing.AddPoint (mesh.Point(i), i, &mgi);\n\t      meshing.AddPoint (mesh[pi], pi, &mgi);\n\t    }\n\t  else\n\t    meshing.AddPoint (mesh[pi], pi);\n\t}\n\n      NgProfiler::StopTimer (timer1c);\n      NgProfiler::StartTimer (timer1d);\n\n      /*\n        for (int i = 1; i <= mesh.GetNOpenSegments(); i++)\n\t  {\n\t    const Segment & seg = mesh.GetOpenSegment (i);\n\t    if (seg.si == fnr)\n\t      meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]], \n\t\t\t\t\t  seg.geominfo[0], seg.geominfo[1]);\n\t  }\n      */\n\n\n      // NgFlatArray<int> segs = opensegments[fnr];\n      for (int hi = 0; hi < segs.Size(); hi++)\n\t{\n\t  int i = segs[hi];\n\t  const Segment & seg = mesh.GetOpenSegment (i);\n\t  meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]], \n\t\t\t\t      seg.geominfo[0], seg.geominfo[1]);\n\t}\n\n\n\n      NgProfiler::StopTimer (timer1d);\n\n      NgProfiler::StopTimer (timer1);\n      \n      PrintMessage(3,\"start meshing, trialcnt = \", retrynr);\n      \n      meshing.GenerateMesh (mesh, mparam, h, fnr);  \n      \n      for (int i = 0; i < icompress.Size(); i++)\n\tcompress[icompress[i]] = 0;\n      \n      \n      mparam.Render();\n    }     \n  \n  // NgProfiler::Print(stdout);\n  \n  mesh.CalcSurfacesOfNode();\n}\n\n\n\nvoid STLSurfaceOptimization (STLGeometry & geom,\n\t\t\t     Mesh & mesh,\n\t\t\t     const MeshingParameters & mparam)\n{\n  PrintFnStart(\"optimize STL Surface\");\n\n  MeshOptimize2d optmesh(mesh);\n\n  optmesh.SetFaceIndex (0);\n  optmesh.SetImproveEdges (0);\n  optmesh.SetMetricWeight (mparam.elsizeweight);\n\n  PrintMessage(5,\"optimize string = \", mparam.optimize2d, \" elsizew = \", mparam.elsizeweight);\n\n  for (int i = 1; i <= mparam.optsteps2d; i++)\n    for (size_t j = 1; j <= mparam.optimize2d.length(); j++)\n      {\n\tif (multithread.terminate)\n\t  break;\n\n\t//(*testout) << \"optimize, before, step = \" << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl;\n\n\tmesh.CalcSurfacesOfNode();\n\tswitch (mparam.optimize2d[j-1])\n\t  {\n\t  case 's': \n\t    {\n\t      optmesh.EdgeSwapping(0);\n\t      break;\n\t    }\n\t  case 'S': \n\t    {\n\t      optmesh.EdgeSwapping(1);\n\t      break;\n\t    }\n\t  case 'm': \n\t    {\n\t      optmesh.ImproveMesh(mparam);\n\t      break;\n\t    }\n\t  case 'c': \n\t    {\n\t      optmesh.CombineImprove();\n\t      break;\n\t    }\n\t  }\n        // while(mesh.CheckOverlappingBoundary())\n        //   {\n        //     for(const auto & el : mesh.SurfaceElements())\n        //       {\n        //         if(el.BadElement())\n        //           {\n        //             cout << \"Restrict localh at el nr \" << el << endl;\n        //             for(const auto& p : el.PNums())\n        //               {\n        //                 const auto& pnt = mesh[p];\n        //                 mesh.RestrictLocalH(pnt, 0.5*mesh.GetH(pnt));\n        //               }\n        //           }\n        //       }\n        //     optmesh.SplitImprove();\n        //   }\n\t//(*testout) << \"optimize, after, step = \" << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl;\n      }\n\n  geom.surfaceoptimized = 1;\n\n  mesh.Compress();\n  mesh.CalcSurfacesOfNode();\n\n\n}\n\n\n\nMeshingSTLSurface :: MeshingSTLSurface (STLGeometry & ageom,\n\t\t\t\t\tconst MeshingParameters & mp)\n  : Meshing2(ageom, mp, ageom.GetBoundingBox()), geom(ageom)\n{\n  ;\n}\n\nvoid MeshingSTLSurface :: DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n\t\t\t\t\t\tconst PointGeomInfo * geominfo,\n\t\t\t\t\t\tconst PointGeomInfo * geominfo2)\n{\n  transformationtrig = geominfo[0].trignum;\n  \n  geom.DefineTangentialPlane(p1, p2, transformationtrig);\n}\n\nvoid MeshingSTLSurface :: TransformToPlain (const Point<3> & locpoint, const MultiPointGeomInfo & gi,\n\t\t\t\t\t    Point<2> & plainpoint, double h, int & zone)\n{\n  int trigs[10000];\n\n  if (gi.GetNPGI() >= 9999) \n    {\n      PrintError(\"In Transform to plane: increase size of trigs!!!\");\n    }\n\n  for (int i = 1; i <= gi.GetNPGI(); i++)\n    trigs[i-1] = gi.GetPGI(i).trignum;\n  trigs[gi.GetNPGI()] = 0;\n\n  //  int trig = gi.trignum;\n  //   (*testout) << \"locpoint = \" << locpoint;\n\n  geom.ToPlane (locpoint, trigs, plainpoint, h, zone, 1);\n\n  //  geom.ToPlane (locpoint, NULL, plainpoint, h, zone, 1);\n  /*\n  (*testout) << \" plainpoint = \" << plainpoint\n\t     << \" h = \" << h \n\t     << endl;\n  */\n}\n\n/*\nint MeshingSTLSurface :: ComputeLineGeoInfo (const Point3d & p1, const Point3d & p2,\n\t\t\t\t\t      int & geoinfosize, void *& geoinfo)\n{\n  static int geomtrig[2] = { 0, 0 };\n\n  Point3d hp;\n  hp = p1;\n  geomtrig[0] = geom.Project (hp);\n\n  hp = p2;\n  geomtrig[1] = geom.Project (hp);\n  \n  geoinfosize = sizeof (geomtrig);\n  geoinfo = &geomtrig;\n\n  if (geomtrig[0] == 0)\n    {\n      return 1;\n    }\n  return 0;\n}\n*/\n\n\nint MeshingSTLSurface :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi)\n{\n  // compute triangle of point,\n  // if non-unique: 0\n\n  Point<3> hp = p;\n  gi.trignum = geom.Project (hp);\n\n  if (!gi.trignum)\n    {\n      return 1;\n    }\n\n  return 0;\n}\n\n\nint MeshingSTLSurface :: \nChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, \n\t\t\t  PointGeomInfo & pgi)\n{\n  for (int i = 1; i <= mpgi.GetNPGI(); i++)\n    if (geom.TrigIsInOC (mpgi.GetPGI(i).trignum, geom.meshchart))\n      {\n\tpgi = mpgi.GetPGI(i);\n\treturn 0;\n      }\n  /*\n  for (i = 0; i < mpgi.cnt; i++)\n    {\n      //      (*testout) << \"d\" << endl;\n      if (geom.TrigIsInOC (mpgi.mgi[i].trignum, geom.meshchart))\n\t{\n\t  pgi = mpgi.mgi[i];\n\t  return 0;\n\t}\n    }\n  */\n  PrintMessage(7,\"INFORM: no gi on chart\");\n  pgi.trignum = 1;\n  return 1;\n}\n\n\n\nint MeshingSTLSurface :: \nIsLineVertexOnChart (const Point3d & p1, const Point3d & p2,\n\t\t     int endpoint, const PointGeomInfo & gi)\n{\n  int lineendtrig = gi.trignum;\n  return geom.TrigIsInOC (lineendtrig, geom.meshchart);\n\n  // Vec3d baselinenormal = geom.meshtrignv;\n  //  Vec3d linenormal = geom.GetTriangleNormal (lineendtrig);\n  //  return ( (baselinenormal * linenormal) > cos (30 * (M_PI/180)) );\n}\n\nvoid MeshingSTLSurface :: \nGetChartBoundary (NgArray<Point<2>> & points, \n\t\t  NgArray<Point<3>> & points3d,\n\t\t  NgArray<INDEX_2> & lines, double h) const\n{\n  points.SetSize (0);\n  points3d.SetSize (0);\n  lines.SetSize (0);\n  geom.GetMeshChartBoundary (points, points3d, lines, h);\n}\n\n\n\n\nint MeshingSTLSurface :: TransformFromPlain (const Point<2> & plainpoint,\n\t\t\t\t\t     Point<3> & locpoint, \n\t\t\t\t\t     PointGeomInfo & gi, \n\t\t\t\t\t     double h)\n{\n  //return 0, wenn alles OK\n  Point<3> hp3d;\n  int res = geom.FromPlane (plainpoint, hp3d, h);\n  locpoint = hp3d;\n  ComputePointGeomInfo (locpoint, gi);\n  return res;\n}\n\n\nint MeshingSTLSurface :: \nBelongsToActiveChart (const Point3d & p, \n\t\t      const PointGeomInfo & gi)\n{\n  return (geom.TrigIsInOC(gi.trignum, geom.meshchart) != 0);\n}\n\n\n\ndouble MeshingSTLSurface :: CalcLocalH (const Point<3> & p, double gh) const\n{\n  return gh;\n}\n\ndouble MeshingSTLSurface :: Area () const\n{\n  return geom.Area();\n}\n\n}\n"
  },
  {
    "path": "libsrc/stlgeom/meshstlsurface.hpp",
    "content": "#ifndef FILE_MESHSTLSURF\n#define FILE_MESHSTLSURF\n\n/* *************************************************************************/\n/* File:   meshstlsurf.hpp                                                 */\n/* Author: Johannes Gerstmayr, Joachim Schoeberl                           */\n/* Date:   01. Aug. 99                                                     */\n/* *************************************************************************/\n\n/*\n\nThe interface between mesh generation and stl geometry\n\n*/\n\n\n/// \nclass MeshingSTLSurface : public Meshing2\n{\n  ///\n  STLGeometry & geom;\n  ///\n  int transformationtrig;\npublic:\n  ///\n  MeshingSTLSurface (STLGeometry & ageom, const MeshingParameters & mp);\n\nprotected:\n  ///\n  void DefineTransformation (const Point<3> & p1, const Point<3> & p2,\n                             const PointGeomInfo * geominfo1,\n                             const PointGeomInfo * geominfo2) override;\n  ///\n  void TransformToPlain (const Point<3> & locpoint, const MultiPointGeomInfo & geominfo,\n                         Point<2> & plainpoint, double h, int & zone) override;\n  ///\n  int TransformFromPlain (const Point<2>& plainpoint,\n                          Point<3> & locpoint, \n                          PointGeomInfo & gi,\n                          double h) override;\n  ///\n  int BelongsToActiveChart (const Point3d & p, \n                            const PointGeomInfo & gi) override;\n\n  ///\n  int ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi) override;\n  ///\n  int ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, \n                                PointGeomInfo & pgi) override;\n\n  ///\n  int IsLineVertexOnChart (const Point3d & p1, const Point3d & p2,\n                           int endpoint, const PointGeomInfo & gi) override;\n\n  void GetChartBoundary (NgArray<Point<2>> & points, \n                         NgArray<Point<3>> & poitns3d,\n                         NgArray<INDEX_2> & lines, double h) const override;\n\n  ///\n  double CalcLocalH (const Point<3> & p, double gh) const override;\n\n  ///\n  double Area () const override;\n};\n\n#endif\n\n"
  },
  {
    "path": "libsrc/stlgeom/python_stl.cpp",
    "content": "\n#ifdef NG_PYTHON\n\n#include <../general/ngpython.hpp>\n#include <core/python_ngcore.hpp>\n#include <stlgeom.hpp>\n#include \"../meshing/python_mesh.hpp\"\n\nusing namespace netgen;\nnamespace netgen\n{\n  extern shared_ptr<Mesh> mesh;\n  extern shared_ptr<NetgenGeometry> ng_geometry;\n}\n\nstatic string stlparameter_description = R\"delimiter(\nSTL Specific Meshing Parameters\n-------------------------------\n\nyangle: float = 30.\n  Angle for edge detection\n\ncontyangle: float = 20.\n  Edges continue if angle > contyangle\n\nedgecornerangle: float = 60.\n  Angle of geometry edge at which the mesher should set a point.\n\ncloseedgefac: Optional[float] = 1.\n  Factor for meshing close edges, if None it is disabled.\n\nminedgelen: Optional[float] = 0.001\n  Minimum edge length to be used for dividing edges to mesh points. If\n  None this is disabled.\n)delimiter\";\n\nvoid CreateSTLParametersFromKwargs(STLParameters& stlparam, py::dict kwargs)\n{\n  if(kwargs.contains(\"yangle\"))\n    stlparam.yangle = py::cast<double>(kwargs.attr(\"pop\")(\"yangle\"));\n  if(kwargs.contains(\"contyangle\"))\n    stlparam.contyangle = py::cast<double>(kwargs.attr(\"pop\")(\"contyangle\"));\n  if(kwargs.contains(\"edgecornerangle\"))\n    stlparam.edgecornerangle = py::cast<double>(kwargs.attr(\"pop\")(\"edgecornerangle\"));\n  if(kwargs.contains(\"chartangle\"))\n    stlparam.chartangle = py::cast<double>(kwargs.attr(\"pop\")(\"chartangle\"));\n  if(kwargs.contains(\"outerchartangle\"))\n    stlparam.outerchartangle = py::cast<double>(kwargs.attr(\"pop\")(\"outerchartangle\"));\n  if(kwargs.contains(\"usesearchtree\"))\n    stlparam.usesearchtree = py::cast<int>(kwargs.attr(\"pop\")(\"usesearchtree\"));\n  if(kwargs.contains(\"atlasfac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"resthatlasfac\");\n    if(val.is_none())\n      stlparam.resthatlasenable = false;\n    else\n    {\n      stlparam.resthatlasenable = true;\n      stlparam.resthatlasfac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"atlasminh\"))\n    stlparam.atlasminh = py::cast<double>(kwargs.attr(\"pop\")(\"atlasminh\"));\n  if(kwargs.contains(\"surfcurvfac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"surfcurvfac\");\n    if(val.is_none())\n      stlparam.resthsurfcurvenable = false;\n    else\n    {\n      stlparam.resthsurfcurvenable = true;\n      stlparam.resthsurfcurvfac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"chartdistfac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"chartdistfac\");\n    if(val.is_none())\n      stlparam.resthchartdistenable = false;\n    else\n    {\n      stlparam.resthchartdistenable = true;\n      stlparam.resthchartdistfac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"edgeanglefac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"edgeanglefac\");\n    if(val.is_none())\n      stlparam.resthedgeangleenable = false;\n    else\n    {\n      stlparam.resthedgeangleenable = true;\n      stlparam.resthedgeanglefac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"surfmeshcurvfac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"surfmeshcurvfac\");\n    if(val.is_none())\n      stlparam.resthsurfmeshcurvenable = false;\n    else\n    {\n      stlparam.resthsurfmeshcurvenable = true;\n      stlparam.resthsurfmeshcurvfac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"linelengthfac\"))\n  {\n    auto val = kwargs.attr(\"pop\")(\"linelengthfac\");\n    if(val.is_none())\n      stlparam.resthlinelengthenable = false;\n    else\n    {\n      stlparam.resthlinelengthenable = true;\n      stlparam.resthlinelengthfac = py::cast<double>(val);\n    }\n  }\n  if(kwargs.contains(\"recalc_h_opt\"))\n    stlparam.recalc_h_opt = py::cast<bool>(kwargs.attr(\"pop\")(\"recalc_h_opt\"));\n}\n\n\nNGCORE_API_EXPORT void ExportSTL(py::module & m)\n{\n  py::class_<STLGeometry,shared_ptr<STLGeometry>, NetgenGeometry> (m,\"STLGeometry\")\n    .def(py::init<>())\n    .def(py::init<>([](const string& filename, bool surface)\n                    {\n                      ifstream ist(filename);\n                      return shared_ptr<STLGeometry>(STLGeometry::Load(ist,\n                                                                       surface));\n                    }), py::arg(\"filename\"), py::arg(\"surface\")=false,\n      py::call_guard<py::gil_scoped_release>())\n    .def(NGSPickle<STLGeometry>())\n    .def(\"_visualizationData\", [](shared_ptr<STLGeometry> stl_geo)\n         {\n           std::vector<float> vertices;\n           std::vector<int> trigs;\n           std::vector<float> normals;\n           std::vector<float> min = {std::numeric_limits<float>::max(),\n                               std::numeric_limits<float>::max(),\n                               std::numeric_limits<float>::max()};\n           std::vector<float> max = {std::numeric_limits<float>::lowest(),\n                               std::numeric_limits<float>::lowest(),\n                               std::numeric_limits<float>::lowest()};\n           std::vector<string> surfnames;\n\n           surfnames.push_back(\"stl\");\n           vertices.reserve(stl_geo->GetNT()*3*3);\n           trigs.reserve(stl_geo->GetNT()*4);\n           normals.reserve(stl_geo->GetNT()*3*3);\n           size_t ii = 0;\n           for(int i = 0; i < stl_geo->GetNT(); i++)\n             {\n               auto& trig = stl_geo->GetTriangle(i+1);\n               for(int k = 0; k < 3; k++)\n                 {\n                   trigs.push_back(ii++);\n                   auto& pnt = stl_geo->GetPoint(trig[k]);\n                   for (int l = 0; l < 3; l++)\n                     {\n                       float val = pnt[l];\n                       vertices.push_back(val);\n                       min[l] = min2(min[l], val);\n                       max[l] = max2(max[l], val);\n                       normals.push_back(trig.Normal()[l]);\n                     }\n                 }\n               trigs.push_back(0);\n             }\n            py::gil_scoped_acquire ac;\n            py::dict res;\n            py::list snames;\n            for(auto name : surfnames)\n              snames.append(py::cast(name));\n            res[\"vertices\"] = MoveToNumpy(vertices);\n            res[\"triangles\"] = MoveToNumpy(trigs);\n            res[\"normals\"] = MoveToNumpy(normals);\n            res[\"surfnames\"] = snames;\n            res[\"min\"] = MoveToNumpy(min);\n            res[\"max\"] = MoveToNumpy(max);\n            return res;\n         }, py::call_guard<py::gil_scoped_release>())\n    .def(\"GenerateMesh\", [] (shared_ptr<STLGeometry> geo,\n                             MeshingParameters* pars,\n                             shared_ptr<Mesh> mesh, py::kwargs kwargs)\n                         {\n                           MeshingParameters mp;\n                           STLParameters stlparam;\n                           if(pars)\n                           {\n                             auto mp_flags = pars->geometrySpecificParameters;\n                             auto mp_kwargs = CreateDictFromFlags(mp_flags);\n                             CreateSTLParametersFromKwargs(stlparam, mp_kwargs);\n                             mp = *pars;\n                           }\n                           CreateSTLParametersFromKwargs(stlparam, kwargs);\n                           CreateMPfromKwargs(mp, kwargs); // this will throw if any kwargs are not passed\n                           py::gil_scoped_release gil_release;\n                           if(!mesh)\n                             {\n                               mesh = make_shared<Mesh>();\n                             }\n                           mesh->SetGeometry(geo);\n                           ng_geometry = geo;\n                           SetGlobalMesh(mesh);\n                           auto result = STLMeshingDummy(geo.get(), mesh, mp, stlparam);\n                           if(result != 0)\n                             {\n                               netgen::mesh = mesh;\n                               throw Exception(\"Meshing failed!\");\n                             }\n\n                           return mesh;\n                         }, py::arg(\"mp\") = nullptr, py::arg(\"mesh\") = nullptr,\n         (meshingparameter_description + stlparameter_description).c_str())\n    .def(\"Draw\", FunctionPointer\n         ([] (shared_ptr<STLGeometry> self)\n          {\n             ng_geometry = self;\n          })\n         )\n    .def(\"GetVicinity\", [] (shared_ptr<STLGeometry> self, int node, int size, string type) {\n      NgArray<int> vic;\n\n      int trig=-1;\n      if(type == \"trig\")\n        trig = node;\n\n      if(type == \"point\")\n        trig = self->TrigPerPoint(node, 1);\n\n      self->GetVicinity(trig, size, vic);\n      auto geo = make_shared<STLGeometry>();\n      NgArray<STLReadTriangle> trigs;\n\n      for(auto i : Range(vic.Size())) {\n        int trigi = vic[i];\n        STLReadTriangle t;\n        Vec<3> normal  = self->GetTriangle(trigi).Normal();\n        Point<3> pts[3];\n        auto trig = self->GetTriangle(trigi);\n        for(auto pi : Range(3))\n          pts[pi] = self->GetPoint(trig[pi]);\n        trigs.Append(STLReadTriangle(pts, normal));\n      }\n\n      geo->SetSurfaceSTL(true);\n      geo->InitSTLGeometry(trigs);\n      return geo;\n    }, py::arg(\"node\"), py::arg(\"size\"), py::arg(\"node_type\") = \"trig\")\n    .def(\"SmoothDirtyTrigs\", [] (shared_ptr<STLGeometry> self, py::kwargs kwargs) {\n      STLParameters stlparam;\n      CreateSTLParametersFromKwargs(stlparam, kwargs);\n      self->SmoothDirtyTrigs(stlparam);\n    })\n    .def(\"GetDirtyTrigs\", [] (shared_ptr<STLGeometry> self, py::kwargs kwargs) {\n      STLParameters stlparam;\n      CreateSTLParametersFromKwargs(stlparam, kwargs);\n      self->MarkDirtyTrigs(stlparam);\n      py::list dirty;\n      for(auto i : Range(self->GetNT()))\n        if(self->IsMarkedTrig(i+1))\n          dirty.append(i);\n    })\n    .def(\"MovePointToMiddle\", [] (shared_ptr<STLGeometry> self, int node, int count) {\n      auto trignr = self->TrigPerPoint(node, 1);\n      auto trig = self->GetTriangle(trignr);\n      int point_in_trig = -1;\n      for(auto i : Range(3))\n        if(trig[i] == node)\n          point_in_trig = i;\n\n      if(point_in_trig == -1)\n        throw Exception(\"Point not found in triangle\");\n      self->SetSelectTrig(trignr);\n      self->SetNodeOfSelTrig(point_in_trig);\n      for([[maybe_unused]] auto i : Range(count))\n        self->MoveSelectedPointToMiddle();\n    })\n    .def(\"Save\", &STLGeometry::Save)\n    ;\n  m.def(\"LoadSTLGeometry\", [] (const string & filename)\n                           {\n                             cout << \"WARNING: LoadSTLGeometry is deprecated, use the STLGeometry(filename) constructor instead!\" << endl;\n                             ifstream ist(filename);\n                             return shared_ptr<STLGeometry>(STLGeometry::Load(ist));\n                           },py::call_guard<py::gil_scoped_release>());\n}\n\nPYBIND11_MODULE(libstl, m) {\n  ExportSTL(m);\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/stlgeom.cpp",
    "content": "#include <meshing.hpp>\n#include <core/register_archive.hpp>\n\n#include \"stlgeom.hpp\"\n\nnamespace netgen\n{\n\n//globalen searchtree fuer gesamte geometry aktivieren\nint geomsearchtreeon = 0;\n\nint usechartnormal = 1;  \n\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nvoid STLMeshing (STLGeometry & geom,\n\t\t Mesh & mesh,\n                 const MeshingParameters& mparam,\n                 const STLParameters& stlpar)\n{\n  geom.Clear();\n  geom.BuildEdges(stlpar);\n  geom.MakeAtlas(mesh, mparam, stlpar);\n  if (multithread.terminate) { return; }\n  geom.CalcFaceNums();\n  geom.AddFaceEdges();\n  geom.LinkEdges(stlpar);\n\n  mesh.ClearFaceDescriptors();\n  for (int i = 1; i <= geom.GetNOFaces(); i++)\n    mesh.AddFaceDescriptor (FaceDescriptor (i, 1, 0, 0));\n}\n\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n//+++++++++++++++++++   STL GEOMETRY   ++++++++++++++++++++++++++++\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n  STLGeometry :: STLGeometry()\n  /*\n  : edges(), edgesperpoint(),\n    normals(),  externaledges(),\n    atlas(), chartmark(), \n    lines(), outerchartspertrig(), vicinity(), markedtrigs(), markedsegs(),\n    lineendpoints(), spiralpoints(), selectedmultiedge()\n  */\n{\n  edgedata = make_unique<STLEdgeDataList>(*this);\n  externaledges.SetSize(0);\n  Clear();\n  meshchart = 0; // initialize all ?? JS\n\n  if (geomsearchtreeon)\n    searchtree = new BoxTree<3> (GetBoundingBox().PMin() - Vec3d(1,1,1),\n                                 GetBoundingBox().PMax() + Vec3d(1,1,1));\n  else\n    searchtree = NULL;\n\n  status = STL_GOOD;\n  statustext = \"Good Geometry\";\n  smoothedges = NULL;\n  area = -1;\n}\n\nSTLGeometry :: ~STLGeometry()\n{\n  // for (auto p : atlas) delete p;\n  // delete edgedata;\n}\n\nvoid STLGeometry :: Save (const filesystem::path & filename) const\n{\n  string ext = ToLower(filename.extension());\n\n  if (ext == \".stl\")\n    {\n      STLTopology::Save (filename);\n      return;\n    }\n  else if (ext == \".stlb\")\n    {\n      SaveBinary (filename,\"Binary STL Geometry\");\n      return;\n    }\n  else if (ext == \".stle\")\n    {\n      SaveSTLE (filename);\n      return;\n    }\n\n  throw Exception (\"Unknown target format: \" + filename.string());\n}\n\n\n\nDLL_HEADER extern STLParameters stlparam;\nint STLGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)\n{\n  STLParameters stlpar = stlparam;\n  return STLMeshingDummy (this, mesh, mparam, stlpar);\n}\n\nVec<3> STLGeometry :: GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi) const\n{\n  if(!gi)\n    throw Exception(\"STLGeometry::GetNormal without PointGeomInfo called\");\n  return GetChart(GetChartNr(gi->trignum)).GetNormal();\n}\n\nbool STLGeometry :: CalcPointGeomInfo(int /*surfind*/, PointGeomInfo& gi, const Point<3> & p3) const\n{\n  Point<3> hp = p3;\n  SelectChartOfTriangle(gi.trignum);\n\n  gi.trignum = Project (hp);\n\n  if (gi.trignum) return true;\n\n  return false;\n}\n\nbool STLGeometry :: ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const\n{\n  static std::mutex mutex_project_whole_surface;\n  int meshchart = GetChartNr(gi.trignum);\n  const STLChart& chart = GetChart(meshchart);\n  int trignum = chart.ProjectNormal(p);\n  if(trignum==0)\n    {\n      // non-thread-safe implementation\n      std::lock_guard<std::mutex> guard(mutex_project_whole_surface);\n      PrintMessage(7,\"project failed\");\n      SelectChartOfTriangle (gi.trignum); // needed because ProjectOnWholeSurface uses meshchartnv (the normal vector of selected chart)\n      trignum = ProjectOnWholeSurface(p);\n      if(trignum==0)\n        {\n\t  PrintMessage(7, \"project on whole surface failed\");\n          return false;\n        }\n    }\n  return true;\n}\n\nPointGeomInfo STLGeometry :: ProjectPoint (INDEX surfind, Point<3> & p) const\n{\n  throw Exception(\"ProjectPoint without PointGeomInfo not implemented\");\n}\n\nvoid STLGeometry ::\nPointBetween  (const Point<3> & p1, const Point<3> & p2, double secpoint,\n\t       int surfi,\n\t       const PointGeomInfo & gi1,\n\t       const PointGeomInfo & gi2,\n\t       Point<3> & newp, PointGeomInfo & newgi) const\n{\n  newp = p1+secpoint*(p2-p1);\n\n  /*\n  (*testout) << \"surf-between: p1 = \" << p1 << \", p2 = \" << p2\n\t     << \", gi = \" << gi1 << \" - \" << gi2 << endl;\n  */\n\n  if (gi1.trignum > 0)\n    {\n      //      ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum);\n\n      Point<3> np1 = newp;\n      Point<3> np2 = newp;\n      auto ngi1 = gi1;\n      auto ngi2 = gi2;\n      // SelectChartOfTriangle (gi1.trignum);\n      int tn1 = ProjectPointGI (surfi, np1, ngi1);\n\n      // SelectChartOfTriangle (gi2.trignum);\n      int tn2 = ProjectPointGI (surfi, np2, ngi2);\n\n      newgi.trignum = tn1; //urspruengliche version\n      newp = np1;          //urspruengliche version\n\n      if (!newgi.trignum)\n\t{ newgi.trignum = tn2; newp = np2; }\n      if (!newgi.trignum) newgi.trignum = gi1.trignum;\n    }\n  else\n    {\n      //      (*testout) << \"WARNING: PointBetween got geominfo = 0\" << endl;\n      newp =  p1+secpoint*(p2-p1);\n      newgi.trignum = 0;\n    }\n}\n\nvoid STLGeometry ::\nPointBetweenEdge (const Point<3> & p1, const Point<3> & p2, double secpoint,\n\t      int surfi1, int surfi2,\n\t      const EdgePointGeomInfo & gi1,\n\t      const EdgePointGeomInfo & gi2,\n\t      Point<3> & newp, EdgePointGeomInfo & newgi) const\n{\n  /*\n  (*testout) << \"edge-between: p1 = \" << p1 << \", p2 = \" << p2\n\t     << \", gi1,2 = \" << gi1 << \", \" << gi2 << endl;\n  */\n  /*\n  newp = Center (p1, p2);\n  ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum);\n  newgi.trignum = geom.Project (newp);\n  */\n  int hi;\n  newgi.dist = (1.0-secpoint) * gi1.dist + secpoint*gi2.dist;\n  newgi.edgenr = gi1.edgenr;\n\n  /*\n  (*testout) << \"p1 = \" << p1 << \", p2 = \" << p2 << endl;\n  (*testout) << \"refedge: \" << gi1.edgenr\n\t     << \" d1 = \" << gi1.dist << \", d2 = \" << gi2.dist << endl;\n  */\n  newp = GetLine (gi1.edgenr)->GetPointInDist (GetPoints(), newgi.dist, hi);\n\n  //  (*testout) << \"newp = \" << newp << endl;\n}\n\nvoid STLGeometry :: STLInfo(double* data)\n{\n  data[0] = GetNT();\n\n  Box<3> b = GetBoundingBox();\n  data[1] = b.PMin()(0);\n  data[2] = b.PMax()(0);\n  data[3] = b.PMin()(1);\n  data[4] = b.PMax()(1);\n  data[5] = b.PMin()(2);\n  data[6] = b.PMax()(2);\n\n  int i;\n \n  int cons = 1;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      if (NONeighbourTrigs(i) != 3) {cons = 0;}\n    }\n  data[7] = cons;\n}\n\nvoid STLGeometry :: MarkNonSmoothNormals(const STLParameters& stlparam)\n{\n\n  PrintFnStart(\"Mark Non-Smooth Normals\");\n\n  int i,j;\n\n  markedtrigs.SetSize(GetNT());\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      SetMarkedTrig(i, 0);\n    }\n\n  double dirtyangle = stlparam.yangle/180.*M_PI;\n\n  int cnt = 0;\n  STLPointId lp1,lp2;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      for (j = 1; j <= NONeighbourTrigs(i); j++)\n\t{\n\t  if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)\n\t    {\n\t      GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), lp1, lp2);\n\t      if (!IsEdge(lp1,lp2))\n\t\t{\n\t\t  if (!IsMarkedTrig(i)) {SetMarkedTrig(i,1); cnt++;}\n\t\t}\n\t    }\n\t}\n    }\n\n  PrintMessage(5,\"marked \",cnt,\" non-smooth trig-normals\");\n\n}\n\nvoid STLGeometry :: SmoothNormals(const STLParameters& stlparam)\n{\n  multithread.terminate = 0;\n\n  //  UseExternalEdges();\n\n  BuildEdges(stlparam);\n\n\n  DenseMatrix m(3), hm(3);\n  Vector rhs(3), sol(3), hv(3), hv2(3);\n\n  Vec<3> ri;\n\n  double wnb = stldoctor.smoothnormalsweight;   // neighbour normal weight\n  double wgeom = 1-wnb;   // geometry normal weight\n\n\n  // minimize \n  //  wgeom sum_T  \\sum ri  \\| ri^T (n - n_geom) \\|^2  \n  //  + wnb sum_SE  \\| ri x (n - n_nb) \\|^2\n  \n  int i, j, k, l;\n  int nt = GetNT();\n  \n  PushStatusF(\"Smooth Normals\");\n    \n  //int testmode;\n\n  for (i = 1; i <= nt; i++)\n    {\n\n      SetThreadPercent( 100.0 * (double)i / (double)nt);\n\n      const STLTriangle & trig = GetTriangle (i);\n      \n      m = 0;\n      rhs = 0;\n\n      // normal of geometry:\n      Vec<3> ngeom = trig.GeomNormal(points);\n      ngeom.Normalize();\n\n      for (j = 1; j <= 3; j++)\n\t{ \n\t  int pi1 = trig.PNumMod (j);\n\t  int pi2 = trig.PNumMod (j+1);\n\n\t  // edge vector\n\t  ri = GetPoint (pi2) - GetPoint (pi1);\n\t  \n\t  for (k = 0; k < 3; k++)\n\t    for (l = 0; l < 3; l++)\n\t      hm.Elem(k+1, l+1) = wgeom * ri(k) * ri(l);\n\t  \n\t  \n\t  for (k = 0; k < 3; k++)\n\t    hv(k) = ngeom(k);\n\t  \n\t  hm.Mult (hv, hv2);\n\t  /*\n\t  if (testmode)\n\t    (*testout) << \"add vec \" << hv2 << endl \n\t\t       << \" add m \" << hm << endl;\n\t  */\n\t  rhs.Add (1, hv2);\n\t  m += hm;\n\n\n\t  int nbt = 0;\n\t  STLPointId fp1,fp2;\n\t  for (k = 1; k <= NONeighbourTrigs(i); k++)\n\t    {\n\t      trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);\n\t      if (fp1 == pi1 && fp2 == pi2)\n\t\t{\n\t\t  nbt = NeighbourTrig(i, k);\n\t\t}\n\t    }\n\n\t  if (!nbt)\n\t    {\n\t      cerr << \"ERROR: stlgeom::Smoothnormals, nbt = 0\" << endl;\n\t    }\n\n\t  // smoothed normal\n\t  Vec<3> nnb = GetTriangle(nbt).Normal();   // neighbour normal\n\t  nnb.Normalize();\n\n\t  if (!IsEdge(pi1,pi2)) \n\t    {\n\t      double lr2 = ri * ri;\n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  for (l = 0; l < k; l++)\n\t\t    {\n\t\t      hm.Elem(k+1, l+1) = -wnb * ri(k) * ri(l);\n\t\t      hm.Elem(l+1, k+1) = -wnb * ri(k) * ri(l);\n\t\t    }\n\t\t  \n\t\t  hm.Elem(k+1, k+1) = wnb * (lr2 - ri(k) * ri(k));\n\t\t}\n\t      \n\t      for (k = 0; k < 3; k++)\n\t\thv(k) = nnb(k);\n\t      \n\t      hm.Mult (hv, hv2);\n\t      /*\n\t      if (testmode)\n\t\t(*testout) << \"add nb vec \" << hv2 << endl \n\t\t\t   << \" add nb m \" << hm << endl;\n\t      */\n\n\t      rhs.Add (1, hv2);\n\t      m += hm;\n\t    }\n\t}\n\n      m.Solve (rhs, sol);\n      Vec3d newn(sol(0), sol(1), sol(2));\n      newn /= (newn.Length() + 1e-24);      \n\n      GetTriangle(i).SetNormal(newn);\n      // setnormal (sol);\n    }\n\n  /*\n  for (i = 1; i <= nt; i++)\n    SetMarkedTrig(i, 0);      \t\t\n\n\n\n  int crloop;\n  for (crloop = 1; crloop <= 3; crloop++)\n    {\n\n  // find critical:\n\n  NgArray<INDEX_2> critpairs;\n  for (i = 1; i <= nt; i++)\n    {\n      const STLTriangle & trig = GetTriangle (i);\n      \n      Vec3d ngeom = GetTriangleNormal (i); // trig.Normal(points);\n      ngeom /= (ngeom.Length() + 1e-24);\n\n      for (j = 1; j <= 3; j++)\n\t{ \n\t  int pi1 = trig.PNumMod (j);\n\t  int pi2 = trig.PNumMod (j+1);\n\n\t  int nbt = 0;\n\t  int fp1,fp2;\n\t  for (k = 1; k <= NONeighbourTrigs(i); k++)\n\t    {\n\t      trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);\n\t      if (fp1 == pi1 && fp2 == pi2)\n\t\t{\n\t\t  nbt = NeighbourTrig(i, k);\n\t\t}\n\t    }\n\t  \n\t  if (!nbt)\n\t    {\n\t      cerr << \"ERROR: stlgeom::Smoothnormals, nbt = 0\" << endl;\n\t    }\n\n\t  Vec3d nnb = GetTriangleNormal(nbt);   // neighbour normal\n\t  nnb /= (nnb.Length() + 1e-24);\n\n\t  if (!IsEdge(pi1,pi2)) \n\t    {\n\t      if (Angle (nnb, ngeom) > 150 * M_PI/180)\n\t\t{\n\t\t  SetMarkedTrig(i, 1);      \t\t\n\t\t  SetMarkedTrig(nbt, 1);      \t\t\n\t\t  critpairs.Append (INDEX_2 (i, nbt));\n\t\t}\n\t    }\n\n\t}\n    }\n\n  if (!critpairs.Size())\n    {\n      break;\n    }\n\n  if (critpairs.Size())\n    {\n\n      NgArray<int> friends;\n      double area1 = 0, area2 = 0;\n\n      for (i = 1; i <= critpairs.Size(); i++)\n\t{\n\t  int tnr1 = critpairs.Get(i).I1();\n\t  int tnr2 = critpairs.Get(i).I2();\n\t  (*testout) << \"t1 = \" << tnr1 << \", t2 = \" << tnr2\n\t\t     << \" angle = \" << Angle (GetTriangleNormal (tnr1),\n\t\t\t\t\t      GetTriangleNormal (tnr2))\n\t\t     << endl;\n\n\t  // who has more friends ?\n\t  int side;\n\t  area1 = 0;\n\t  area2 = 0;\n\t  for (side = 1; side <= 2; side++)\n\t    {\n\t      friends.SetSize (0);\n\t      friends.Append ( (side == 1) ? tnr1 : tnr2);\n\n\t      for (j = 1; j <= 3; j++)\n\t\t{\n\t\t  int fsize = friends.Size();\n\t\t  for (k = 1; k <= fsize; k++)\n\t\t    {\n\t\t      int testtnr = friends.Get(k);\n\t\t      Vec3d ntt = GetTriangleNormal(testtnr);\n\t\t      ntt /= (ntt.Length() + 1e-24);\n\t\t      \n\t\t      for (l = 1; l <= NONeighbourTrigs(testtnr); l++)\n\t\t\t{\n\t\t\t  int testnbnr = NeighbourTrig(testtnr, l);\n\t\t\t  Vec3d nbt = GetTriangleNormal(testnbnr);\n\t\t\t  nbt /= (nbt.Length() + 1e-24);\n\n\t\t\t  if (Angle (nbt, ntt) < 15 * M_PI/180)\n\t\t\t    {\n\t\t\t      int ii;\n\t\t\t      int found = 0;\n\t\t\t      for (ii = 1; ii <= friends.Size(); ii++)\n\t\t\t\t{\n\t\t\t\t  if (friends.Get(ii) == testnbnr)\n\t\t\t\t    {\n\t\t\t\t      found = 1;\n\t\t\t\t      break;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t      if (!found)\n\t\t\t\tfriends.Append (testnbnr);\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t      // compute area:\n\t      for (k = 1; k <= friends.Size(); k++)\n\t\t{\n\t\t  double area = \n\t\t    GetTriangle (friends.Get(k)).Area(points);\n\n\t\t  if (side == 1)\n\t\t    area1 += area;\n\t\t  else\n\t\t    area2 += area;\n\t\t}\n\t      \n                }\n\n\t  (*testout) << \"area1 = \" << area1 << \" area2 = \" << area2 << endl;\n\t  if (area1 < 0.1 * area2)\n\t    {\n\t      Vec3d n = GetTriangleNormal (tnr1);\n\t      n *= -1;\n\t      SetTriangleNormal(tnr1, n);\n\t    }\n\t  if (area2 < 0.1 * area1)\n\t    {\n\t      Vec3d n = GetTriangleNormal (tnr2);\n\t      n *= -1;\n\t      SetTriangleNormal(tnr2, n);\n\t    }\n\t}\n    }\n    }\n  */\n\n  calcedgedataanglesnew = 1;\n  PopStatus();\n}\n\n\nint STLGeometry :: AddEdge(int ap1, int ap2)\n{\n  STLEdge e(ap1,ap2);\n  e.SetLeftTrig(GetLeftTrig(ap1,ap2));\n  e.SetRightTrig(GetRightTrig(ap1,ap2));\n  edges.Append(e);\n  return edges.Size();\n}\n\nvoid STLGeometry :: STLDoctorConfirmEdge()\n{\n  StoreEdgeData();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())\n    {\n      if (stldoctor.selectmode == 1)\n\t{\n\t  int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n\t  int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n\t  edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);\n\t}\n      else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)\n\t{\n\t  int i;\n\t  for (i = 1; i <= selectedmultiedge.Size(); i++)\n\t    {\n\t      int ap1 = selectedmultiedge.Get(i).i1;\n\t      int ap2 = selectedmultiedge.Get(i).i2;\n\t      edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);\n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: STLDoctorCandidateEdge()\n{\n  StoreEdgeData();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())\n    {\n      if (stldoctor.selectmode == 1)\n\t{\n\t  int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n\t  int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n\t  edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);\n\t}\n      else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)\n\t{\n\t  int i;\n\t  for (i = 1; i <= selectedmultiedge.Size(); i++)\n\t    {\n\t      int ap1 = selectedmultiedge.Get(i).i1;\n\t      int ap2 = selectedmultiedge.Get(i).i2;\n\t      edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);\n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: STLDoctorExcludeEdge()\n{\n  StoreEdgeData();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())\n    {\n      if (stldoctor.selectmode == 1)\n\t{\n\t  int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n\t  int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n\t  edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);\n\t}\n      else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)\n\t{\n\t  int i;\n\t  for (i = 1; i <= selectedmultiedge.Size(); i++)\n\t    {\n\t      int ap1 = selectedmultiedge.Get(i).i1;\n\t      int ap2 = selectedmultiedge.Get(i).i2;\n\t      edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);\n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: STLDoctorUndefinedEdge()\n{\n  StoreEdgeData();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())\n    {\n      if (stldoctor.selectmode == 1)\n\t{\n\t  int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n\t  int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n\t  edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);\n\t}\n      else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)\n\t{\n\t  int i;\n\t  for (i = 1; i <= selectedmultiedge.Size(); i++)\n\t    {\n\t      int ap1 = selectedmultiedge.Get(i).i1;\n\t      int ap2 = selectedmultiedge.Get(i).i2;\n\t      edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);\n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: STLDoctorSetAllUndefinedEdges()\n{\n  edgedata->ResetAll();\n}\n\nvoid STLGeometry :: STLDoctorEraseCandidateEdges()\n{\n  StoreEdgeData();\n  edgedata->ChangeStatus(ED_CANDIDATE, ED_UNDEFINED);\n}\n\nvoid STLGeometry :: STLDoctorConfirmCandidateEdges()\n{\n  StoreEdgeData();\n  edgedata->ChangeStatus(ED_CANDIDATE, ED_CONFIRMED);\n}\n\nvoid STLGeometry :: STLDoctorConfirmedToCandidateEdges()\n{\n  StoreEdgeData();\n  edgedata->ChangeStatus(ED_CONFIRMED, ED_CANDIDATE);\n}\n\nvoid STLGeometry :: STLDoctorDirtyEdgesToCandidates()\n{\n  StoreEdgeData();\n}\n\nvoid STLGeometry :: STLDoctorLongLinesToCandidates()\n{\n  StoreEdgeData();\n}\n\ntwoint STLGeometry :: GetNearestSelectedDefinedEdge()\n{\n  Point<3> pestimate = Center(GetTriangle(GetSelectTrig()).center,\n  \t\t\t     GetPoint(GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig())));\n    //Point3d pestimate = GetTriangle(GetSelectTrig()).center;\n\n  int i, j, en;\n  NgArray<int> vic;\n  GetVicinity(GetSelectTrig(),4,vic);\n  \n\n  twoint fedg;\n  fedg.i1 = 0;\n  fedg.i2 = 0;\n  double mindist = 1E50;\n  double dist;\n  Point<3> p;\n\n  for (i = 1; i <= vic.Size(); i++)\n  {\n    const STLTriangle& t = GetTriangle(vic.Get(i));\n    for (j = 1; j <= 3; j++)\n      {\n\ten = edgedata->GetEdgeNum(t.PNum(j),t.PNumMod(j+1));\n\tif (edgedata->Get(en).GetStatus() != ED_UNDEFINED)\n\t  {\n\t    p = pestimate;\n\t    dist = GetDistFromLine(GetPoint(t.PNum(j)),GetPoint(t.PNumMod(j+1)),p);\n\t    if (dist < mindist)\n\t      {\n\t\tmindist = dist;\n\t\tfedg.i1 = t.PNum(j);\n\t\tfedg.i2 = t.PNumMod(j+1);\n\t      }\n\t  }\n      }\n  }\n  return fedg;\n}\n \nvoid STLGeometry :: BuildSelectedMultiEdge(twoint ep)\n{\n  if (edgedata->Size() == 0 || \n      !GetEPPSize()) \n    {\n      return; \n    }\n\n  selectedmultiedge.SetSize(0);\n  int tenum = GetTopEdgeNum (ep.i1, ep.i2);\n\n  if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)\n    {\n      twoint epnew = GetNearestSelectedDefinedEdge();\n      if (epnew.i1) \n\t{\n\t  ep = epnew;\n\t  tenum = GetTopEdgeNum (ep.i1, ep.i2);\n\t}\n    }\n\n  selectedmultiedge.Append(twoint(ep));\n\n  if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)\n    {\n      return;\n    }\n\n  edgedata->BuildLineWithEdge(ep.i1,ep.i2,selectedmultiedge);\n}\n\nvoid STLGeometry :: BuildSelectedEdge(twoint ep)\n{\n  if (edgedata->Size() == 0 || \n      !GetEPPSize()) \n    {\n      return; \n    }\n\n  selectedmultiedge.SetSize(0);\n\n  selectedmultiedge.Append(twoint(ep));\n}\n\nvoid STLGeometry :: BuildSelectedCluster(twoint ep)\n{\n  if (edgedata->Size() == 0 || \n      !GetEPPSize()) \n    {\n      return; \n    }\n\n  selectedmultiedge.SetSize(0);\n\n  int tenum = GetTopEdgeNum (ep.i1, ep.i2);\n\n  if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)\n    {\n      twoint epnew = GetNearestSelectedDefinedEdge();\n      if (epnew.i1) \n\t{\n\t  ep = epnew;\n\t  tenum = GetTopEdgeNum (ep.i1, ep.i2);\n\t}\n    }\n\n  selectedmultiedge.Append(twoint(ep));\n\n  if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)\n    {\n      return;\n    }\n\n  edgedata->BuildClusterWithEdge(ep.i1,ep.i2,selectedmultiedge);\n}\n\nvoid STLGeometry :: ImportEdges()\n{\n  StoreEdgeData();\n\n  PrintMessage(5, \"import edges from file 'edges.ng'\");\n  ifstream fin(\"edges.ng\");\n\n  int ne;\n  fin >> ne;\n\n  NgArray<Point<3> > eps;\n\n  int i;\n  Point<3> p;\n  for (i = 1; i <= 2*ne; i++)\n    {\n      fin >> p(0); \n      fin >> p(1); \n      fin >> p(2);\n      eps.Append(p);\n    }\n  AddEdges(eps);\n}\n\nvoid STLGeometry :: AddEdges(const NgArray<Point<3> >& eps)\n{\n  int i;\n  int ne = eps.Size()/2;\n  \n  NgArray<int> epsi;\n  Box<3> bb = GetBoundingBox();\n  bb.Increase(1);\n\n  Point3dTree ptree (bb.PMin(), \n\t\t\t bb.PMax());\n  NgArray<int> pintersect;\n\n  double gtol = GetBoundingBox().Diam()/1.E10;\n  Point<3> p;\n\n  for (i = 1; i <= GetNP(); i++)\n    {\n      p = GetPoint(i);\n      ptree.Insert (p, i);\n    }\n  \n  int error = 0;\n  for (i = 1; i <= 2*ne; i++)\n    {\n      p = eps.Get(i);\n      Point3d pmin = p - Vec3d (gtol, gtol, gtol);\n      Point3d pmax = p + Vec3d (gtol, gtol, gtol);\n\t  \n      ptree.GetIntersecting (pmin, pmax, pintersect);\n      if (pintersect.Size() > 1)\n\t{\n\t  PrintError(\"Found too much points in epsilon-dist\");\n\t  error = 1;\n\t}\n      else if (pintersect.Size() == 0)\n\t{\n\t  error = 1;\n\t  PrintError(\"edgepoint does not exist!\");\n\t  PrintMessage(5,\"p=\",Point3d(eps.Get(i)));\n\t}\n      else\n\t{\n\t  epsi.Append(pintersect.Get(1));\n\t}\n    }\n\n  if (error) return;\n\n  int en;\n  for (i = 1; i <= ne; i++)\n    {\n      if (epsi.Get(2*i-1) == epsi.Get(2*i)) {PrintError(\"Edge with zero length!\");}\n      else \n\t{\n\t  en = edgedata->GetEdgeNum(epsi.Get(2*i-1),epsi.Get(2*i));\n\t  edgedata->Elem(en).SetStatus (ED_CONFIRMED);\n\t}\n    }\n\n}\n\n\n\nvoid STLGeometry :: ImportExternalEdges(const char * filename)\n{\n  //AVL edges!!!!!!\n\n  ifstream inf (filename);\n  char ch;\n  //int cnt = 0;\n  int records, units, i, j;\n  PrintFnStart(\"Import edges from \",filename);\n  \n  const int flen=30;\n  char filter[flen+1];\n  filter[flen] = 0;\n  char buf[20];\n\n  NgArray<Point3d> importpoints;\n  NgArray<int> importlines;\n  NgArray<int> importpnums;\n\n  while (inf.good())\n    {\n      inf.get(ch);\n      //      (*testout) << cnt << \": \" << ch << endl;\n      \n      for (i = 0; i < flen; i++)\n\tfilter[i] = filter[i+1];\n      filter[flen-1] = ch;\n      //      (*testout) << filter << endl;\n\n      if (strcmp (filter+flen-7, \"RECORDS\") == 0)\n\t{\n\t  inf.get(ch);  // '='\n\t  inf >> records;\n\t}\n      if (strcmp (filter+flen-5, \"UNITS\") == 0)\n\t{\n\t  inf.get(ch);  // '='\n\t  inf >> units;\n\t}\n\n      if (strcmp (filter+flen-17, \"EDGE NODE NUMBERS\") == 0)\n\t{\n\t  int nodenr;\n\t  importlines.SetSize (units);\n\t  for (i = 1; i <= units; i++)\n\t    {\n\t      inf >> nodenr;\n\t      importlines.Elem(i) = nodenr;\n\t      //\t      (*testout) << nodenr << endl;\n\t    }\n\t}\n\n      if (strcmp (filter+flen-23, \"EDGE POINT COORD IN DIR\") == 0)\n\t{\n\t  int coord;\n\n\t  inf >> coord;\n\t  \n\t  importpoints.SetSize (units);\n\n\t  inf >> ch;\n\t  inf.putback (ch);\n\n\t  for (i = 1; i <= units; i++)\n\t    {\n\t      for (j = 0; j < 12; j++)\n\t\tinf.get (buf[j]);\n\t      buf[12] = 0;\n\n\t      importpoints.Elem(i).X(coord) = 1000 * atof (buf);\n\t    }\n\t}\n    }\n\n  /*\n  (*testout) << \"lines: \" << endl;\n  for (i = 1; i <= importlines.Size(); i++)\n    (*testout) << importlines.Get(i) << endl;\n  (*testout) << \"points: \" << endl;\n  for (i = 1; i <= importpoints.Size(); i++)\n    (*testout) << importpoints.Get(i) << endl;\n  */\n\n\n\n  importpnums.SetSize (importpoints.Size());\n  \n\n  Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),\n\t    GetBoundingBox().PMax() + Vec3d (1, 1, 1));\n\n  Point3dTree ptree (bb.PMin(), \n\t\t\t bb.PMax());\n\n\n  PrintMessage(7,\"stl - bb: \",bb.PMin(), \" - \", bb.PMax());\n  \n  Box3d ebb;\n  ebb.SetPoint (importpoints.Get(1));\n  for (i = 1; i <= importpoints.Size(); i++)\n    ebb.AddPoint (importpoints.Get(i));\n  PrintMessage(7,\"edgep - bb: \", ebb.PMin(), \" - \", ebb.PMax());\n\n  NgArray<int> pintersect;\n\n  double gtol = GetBoundingBox().Diam()/1.E6;\n\n  for (i = 1; i <= GetNP(); i++)\n    {\n      Point3d p = GetPoint(i);\n      //      (*testout) << \"stlpt: \" << p << endl;\n      ptree.Insert (p, i);\n    }\n  \n\n  for (i = 1; i <= importpoints.Size(); i++)\n    {\n      Point3d p = importpoints.Get(i);\n      Point3d pmin = p - Vec3d (gtol, gtol, gtol);\n      Point3d pmax = p + Vec3d (gtol, gtol, gtol);\n\t  \n      ptree.GetIntersecting (pmin, pmax, pintersect);\n      if (pintersect.Size() > 1)\n\t{\n\t  importpnums.Elem(i) = 0;\n\t  PrintError(\"Found too many points in epsilon-dist\");\n\t}\n      else if (pintersect.Size() == 0)\n\t{\n\t  importpnums.Elem(i) = 0;\n\t  PrintError(\"Edgepoint does not exist!\");\n\t}\n      else\n\t{\n\t  importpnums.Elem(i) = pintersect.Get(1);\n\t}\n    }\n\n  //  if (!error) \n    {\n      PrintMessage(7,\"found all edge points in stl file\");\n\n\n      StoreEdgeData();\n\n      int oldp = 0;\n\n      for (i = 1; i <= importlines.Size(); i++)\n\t{\n\t  int newp = importlines.Get(i);\n\t  if (!importpnums.Get(abs(newp)))\n\t    newp = 0;\n\n\t  if (oldp && newp)\n\t    {\n\t      int en = edgedata->GetEdgeNum(importpnums.Get(oldp), \n\t\t\t\t\t   importpnums.Get(abs(newp)));\n\t      edgedata->Elem(en).SetStatus (ED_CONFIRMED);\n\t    }\n\t  \n\t  if (newp < 0)\n\t    oldp = 0;\n\t  else\n\t    oldp = newp;\n\t}\n    }\n\n\n}\n\n\n\nvoid STLGeometry :: ExportEdges()\n{\n  PrintFnStart(\"Save edges to file 'edges.ng'\");\n\n  ofstream fout(\"edges.ng\");\n  fout.precision(16);\n\n  int n = edgedata->GetNConfEdges();\n  \n  fout << n << endl;\n\n  int i;\n  for (i = 1; i <= edgedata->Size(); i++)\n    {\n      if (edgedata->Get(i).GetStatus() == ED_CONFIRMED)\n\t{\n\t  const STLTopEdge & e = edgedata->Get(i);\n\t  fout << GetPoint(e.PNum(1))(0) << \" \" << GetPoint(e.PNum(1))(1) << \" \" << GetPoint(e.PNum(1))(2) << endl;\n\t  fout << GetPoint(e.PNum(2))(0) << \" \" << GetPoint(e.PNum(2))(1) << \" \" << GetPoint(e.PNum(2))(2) << endl;\n\t}\n    }\n\n}\n\nvoid STLGeometry :: LoadEdgeData(const filesystem::path & filename)\n{\n  StoreEdgeData();\n\n  PrintFnStart(\"Load edges from file '\", filename, \"'\");\n  ifstream fin(filename);\n\n  edgedata->Read(fin);\n\n  //  calcedgedataanglesnew = 1;\n}\n\nvoid STLGeometry :: SaveEdgeData(const filesystem::path & filename)\n{\n  PrintFnStart(\"save edges to file '\", filename, \"'\");\n  ofstream fout(filename);\n\n  edgedata->Write(fout);\n}\n\n\n\n\n\n\n\n/*\nvoid STLGeometry :: SaveExternalEdges()\n{\n  ofstream fout(\"externaledgesp3.ng\");\n  fout.precision(16);\n\n  int n = NOExternalEdges();\n  fout << n << endl;\n\n  int i;\n  for (i = 1; i <= n; i++)\n    {\n      twoint e = GetExternalEdge(i);\n      fout << GetPoint(e.i1)(0) << \" \" << GetPoint(e.i1)(1) << \" \" << GetPoint(e.i1)(2) << endl;\n      fout << GetPoint(e.i2)(0) << \" \" << GetPoint(e.i2)(1) << \" \" << GetPoint(e.i2)(2) << endl;\n    }\n\n}\n*/\nvoid STLGeometry :: StoreExternalEdges()\n{\n  storedexternaledges.SetSize(0);\n  undoexternaledges = 1;\n  int i;\n  for (i = 1; i <= externaledges.Size(); i++)\n    {\n      storedexternaledges.Append(externaledges.Get(i));      \n    }\n\n}\n\nvoid STLGeometry :: UndoExternalEdges()\n{\n  if (!undoexternaledges) \n    {\n      PrintMessage(1, \"undo not further possible!\");\n      return;\n    }\n  RestoreExternalEdges();\n  undoexternaledges = 0;\n}\n\nvoid STLGeometry :: RestoreExternalEdges()\n{\n  externaledges.SetSize(0);\n  int i;\n  for (i = 1; i <= storedexternaledges.Size(); i++)\n    {\n      externaledges.Append(storedexternaledges.Get(i));      \n    }\n\n}\n\n\nvoid STLGeometry :: AddExternalEdgeAtSelected()\n{\n  StoreExternalEdges();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())\n    {\n      int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n      int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n      if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}\n    }\n}\n\nvoid STLGeometry :: AddClosedLinesToExternalEdges()\n{\n  StoreExternalEdges();\n\n  int i, j;\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      STLLine* l = GetLine(i);\n      if (l->StartP() == l->EndP()) \n\t{\n\t  for (j = 1; j < l->NP(); j++)\n\t    {\n\t      int ap1 = l->PNum(j);\n\t      int ap2 = l->PNum(j+1);\n\n\t      if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}\t      \n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: AddLongLinesToExternalEdges()\n{\n  StoreExternalEdges();\n\n  double diamfact = stldoctor.dirtytrigfact;\n  double diam = GetBoundingBox().Diam();\n\n  int i, j;\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      STLLine* l = GetLine(i);\n      if (l->GetLength(points) >= diamfact*diam) \n\t{\n\t  for (j = 1; j < l->NP(); j++)\n\t    {\n\t      int ap1 = l->PNum(j);\n\t      int ap2 = l->PNum(j+1);\n\n\t      if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}\t      \n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: AddAllNotSingleLinesToExternalEdges()\n{\n  StoreExternalEdges();\n\n  int i, j;\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      STLLine* l = GetLine(i);\n      if (GetNEPP(l->StartP()) > 1 || GetNEPP(l->EndP()) > 1) \n\t{\n\t  for (j = 1; j < l->NP(); j++)\n\t    {\n\t      int ap1 = l->PNum(j);\n\t      int ap2 = l->PNum(j+1);\n\n\t      if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}\t      \n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: DeleteDirtyExternalEdges()\n{\n  //delete single triangle edges and single edge-lines in clusters\"\n  StoreExternalEdges();\n\n  int i, j;\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      STLLine* l = GetLine(i);\n      if (l->NP() <= 3 || (l->StartP() == l->EndP() && l->NP() == 4))\n\t{\n\t  for (j = 1; j < l->NP(); j++)\n\t    {\n\t      int ap1 = l->PNum(j);\n\t      int ap2 = l->PNum(j+1);\n\n\t      if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}\t      \n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: AddExternalEdgesFromGeomLine()\n{\n  StoreExternalEdges();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())\n    {\n      int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n      int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n\n      if (IsEdge(ap1,ap2))\n\t{\n\t  int edgenum = IsEdgeNum(ap1,ap2);\n\t  if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}\n\t  \n\t  int noend = 1;\n\t  int startp = ap1;\n\t  int laste = edgenum;\n\t  int np1, np2;\n\t  while (noend)\n\t    {\n\t      if (GetNEPP(startp) == 2)\n\t\t{\n\t\t  if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}\n\t\t  else {laste = GetEdgePP(startp,2);}\n\t\t  np1 = GetEdge(laste).PNum(1);\n\t\t  np2 = GetEdge(laste).PNum(2);\n\t\t  \n\t\t  if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}\n\t\t  else {noend = 0;}\n\t\t  if (np1 != startp) {startp = np1;}\n\t\t  else {startp = np2;}\n\t\t}\n\t      else {noend = 0;}\n\t    }\n\n\t  startp = ap2;\n\t  laste = edgenum;\n\t  noend = 1;\n\t  while (noend)\n\t    {\n\t      if (GetNEPP(startp) == 2)\n\t\t{\n\t\t  if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}\n\t\t  else {laste = GetEdgePP(startp,2);}\n\t\t  np1 = GetEdge(laste).PNum(1);\n\t\t  np2 = GetEdge(laste).PNum(2);\n\t\t  \n\t\t  if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}\n\t\t  else {noend = 0;}\n\t\t  if (np1 != startp) {startp = np1;}\n\t\t  else {startp = np2;}\n\t\t}\n\t      else {noend = 0;}\n\t    }\n\t  \n\t}\n\n    }\n  \n}\n\nvoid STLGeometry :: ClearEdges()\n{\n  edgesfound = 0;\n  edges.SetSize(0);\n  //edgedata->SetSize(0);\n  // externaledges.SetSize(0);\n  edgesperpoint.SetSize(0);\n  undoexternaledges = 0;\n\n}\n\nvoid STLGeometry :: STLDoctorBuildEdges(const STLParameters& stlparam)\n{\n  //  if (!trigsconverted) {return;}\n  ClearEdges();\n\n  meshlines.SetSize(0);\n  FindEdgesFromAngles(stlparam);\n}\n\nvoid STLGeometry :: DeleteExternalEdgeAtSelected()\n{\n  StoreExternalEdges();\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())\n    {\n      int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n      int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);\n      if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}\n    }\n}\n\nvoid STLGeometry :: DeleteExternalEdgeInVicinity()\n{\n  StoreExternalEdges();\n  if (!stldoctor.showvicinity || vicinity.Size() != GetNT()) {return;}\n\n  int i, j, ap1, ap2;\n  \n  for (i = 1; i <= GetNT(); i++)\n    {\n      if (vicinity.Elem(i))\n\t{\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      ap1 = GetTriangle(i).PNum(j);\n\t      ap2 = GetTriangle(i).PNumMod(j+1);\n\n\t      if (IsExternalEdge(ap1,ap2))\n\t\t{\n\t\t  DeleteExternalEdge(ap1,ap2);\n\t\t}\n\t    }\n\t}\n    }\n}\n\nvoid STLGeometry :: BuildExternalEdgesFromEdges()\n{\n  StoreExternalEdges();\n\n  if (GetNE() == 0) {PrintWarning(\"Edges possibly not generated!\");}\n\n  int i;\n  externaledges.SetSize(0);\n\n  for (i = 1; i <= GetNE(); i++)\n    {\n      STLEdge e = GetEdge(i);\n      AddExternalEdge(e.PNum(1), e.PNum(2));\n    }\n\n}\n\n\nvoid STLGeometry :: AddExternalEdge(int ap1, int ap2)\n{\n  externaledges.Append(twoint(ap1,ap2));\n}\n\nvoid STLGeometry :: DeleteExternalEdge(int ap1, int ap2)\n{\n\n  int i;\n  int found = 0;\n  for (i = 1; i <= NOExternalEdges(); i++)\n    {\n      if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||\n\t  (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {found = 1;};\n      if (found && i < NOExternalEdges())\n\t{\n\t  externaledges.Elem(i) = externaledges.Get(i+1);\n\t}\n    }\n  if (!found) {PrintWarning(\"edge not found\");}\n  else\n    {\n      externaledges.SetSize(externaledges.Size()-1);\n    }\n\n}\n\nint STLGeometry :: IsExternalEdge(int ap1, int ap2)\n{\n  int i;\n  for (i = 1; i <= NOExternalEdges(); i++)\n    {\n      if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||\n\t  (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {return 1;};\n    }\n  return 0;\n}\n\nvoid STLGeometry :: DestroyDirtyTrigs()\n{\n\n  PrintFnStart(\"Destroy dirty triangles\");\n  PrintMessage(5,\"original number of triangles=\", GetNT());\n\n  //destroy every triangle with other than 3 neighbours;\n  int changed = 1;\n  int i, j, k;\n  while (changed)\n    {\n      changed = 0;\n      Clear();\n\n      for (i = 1; i <= GetNT(); i++)\n\t{\n\t  int dirty = NONeighbourTrigs(i) < 3;\n\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      int pnum = GetTriangle(i).PNum(j);\n\t      /*\n\t      if (pnum == 1546)\n\t\t{\n\t\t// for (k = 1; k <=  NOTrigsPerPoint(pnum); k++)\n\t\t}\n\t      */\n\t      if (NOTrigsPerPoint(pnum) <= 2) \n\t\tdirty = 1;\n\t    }\n\t  \n\t  int pi1 = GetTriangle(i).PNum(1);\n\t  int pi2 = GetTriangle(i).PNum(2);\n\t  int pi3 = GetTriangle(i).PNum(3);\n\t  if (pi1 == pi2 || pi1 == pi3 || pi2 == pi3)\n\t    {\n\t      PrintMessage(5,\"triangle with Volume 0: \", i, \"  nodes: \", pi1, \", \", pi2, \", \", pi3);\n\t      dirty = 1;\n\t    }\n\n\t  if (dirty)\n\t    {\n\t      for (k = i+1; k <= GetNT(); k++)\n\t\t{\n\t\t  trias[k-1] = trias[k];\n\t\t  // readtrias: not longer permanent, JS\n\t\t  //\t\t  readtrias.Elem(k-1) = readtrias.Get(k); \n\t\t}\n\t      int size = GetNT();\n\t      trias.SetSize(size-1);\n\t      //\t      readtrias.SetSize(size-1);\n\t      changed = 1;\n\t      break;\n\t    }\n\t}\n    }  \n\n  FindNeighbourTrigs();\n  PrintMessage(5,\"final number of triangles=\", GetNT());\n}\n\nvoid STLGeometry :: CalcNormalsFromGeometry()\n{\n  int i;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & tr = GetTriangle(i);\n      const Point3d& ap1 = GetPoint(tr.PNum(1));\n      const Point3d& ap2 = GetPoint(tr.PNum(2));\n      const Point3d& ap3 = GetPoint(tr.PNum(3));\n\n      Vec3d normal = Cross (ap2-ap1, ap3-ap1);\n      \n      if (normal.Length() != 0)\n\t{\n\t  normal /= (normal.Length());\t\t  \n\t}\n      GetTriangle(i).SetNormal(normal);\n    }\n  PrintMessage(5,\"Normals calculated from geometry!!!\");\n\n  calcedgedataanglesnew = 1;\n}\n\nvoid STLGeometry :: SetSelectTrig(int trig)\n{\n  stldoctor.selecttrig = trig;\n}\n\nint STLGeometry :: GetSelectTrig() const\n{\n  return stldoctor.selecttrig;\n}\n\nvoid STLGeometry :: SetNodeOfSelTrig(int n)\n{\n  stldoctor.nodeofseltrig = n;\n}\n\nint STLGeometry :: GetNodeOfSelTrig() const\n{\n  return stldoctor.nodeofseltrig;\n}\n\nvoid STLGeometry :: MoveSelectedPointToMiddle()\n{\n  if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())\n    {\n      int p = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());\n      Point<3> pm(0.,0.,0.); //Middlevector;\n      Point<3> p0(0.,0.,0.);\n      PrintMessage(5,\"original point=\", Point3d(GetPoint(p)));\n\n      int i;\n      int cnt = 0;\n      for (i = 1; i <= trigsperpoint.EntrySize(p); i++)\n\t{\n\t  const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,i));\n\t  int j;\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      if (tr.PNum(j) != p)\n\t\t{\n\t\t  cnt++;\n\t\t  pm(0) += GetPoint(tr.PNum(j))(0);\n\t\t  pm(1) += GetPoint(tr.PNum(j))(1);\n\t\t  pm(2) += GetPoint(tr.PNum(j))(2);\n\t\t}\n\t    }\n\t}\n\n      Point<3> origp = GetPoint(p);\n      double fact = 0.2;\n\n      SetPoint(p, p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0));\n\n      PrintMessage(5,\"middle point=\", Point3d (GetPoint(p)));\n      \n      PrintMessage(5,\"moved point \", Point3d (p));\n\n    }\n}\n\nvoid STLGeometry :: PrintSelectInfo()\n{\n\n  //int trig = GetSelectTrig();\n  //int p = GetTriangle(trig).PNum(GetNodeOfSelTrig());\n  \n  PrintMessage(1,\"touch triangle \", GetSelectTrig()\n               , \", local node \", GetNodeOfSelTrig()\n               , \" (=\", int(GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig())), \")\");\n  if (AtlasMade() && GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())\n    {\n      PrintMessage(1,\"           chartnum=\", int(GetChartNr(GetSelectTrig())));\n      /*      \n      PointBetween(Center(Center(GetPoint(GetTriangle(270).PNum(1)),\n\t\t\t\t GetPoint(GetTriangle(270).PNum(2))),\n\t\t\t  GetPoint(GetTriangle(270).PNum(3))),270,\n\t\t   Center(Center(GetPoint(GetTriangle(trig).PNum(1)),\n\t\t\t\t GetPoint(GetTriangle(trig).PNum(2))),\n\t\t\t  GetPoint(GetTriangle(trig).PNum(3))),trig);\n      */\n      //PointBetween(Point3d(5.7818, 7.52768, 4.14879),260,Point3d(6.80292, 6.55392, 4.70184),233);\n    }\n}\n\nvoid STLGeometry :: ShowSelectedTrigChartnum()\n{\n  int st = GetSelectTrig();\n\n  if (st >= 1 && st <= GetNT() && AtlasMade())\n    PrintMessage(1,\"selected trig \", st, \" has chartnumber \", int(GetChartNr(st)));\n}\n\nvoid STLGeometry :: ShowSelectedTrigCoords()\n{\n  int st = GetSelectTrig();\n\n  /*\n  //testing!!!!\n  NgArray<int> trigs;\n  GetSortedTrianglesAroundPoint(GetTriangle(st).PNum(GetNodeOfSelTrig()),st,trigs);\n  */\n\n  if (st >= 1 && st <= GetNT())\n    {\n      PrintMessage(1, \"coordinates of selected trig \", st, \":\");\n      PrintMessage(1, \"   p1 = \", int(GetTriangle(st).PNum(1)), \" = \", \n\t\t   Point3d (GetPoint(GetTriangle(st).PNum(1))));\n      PrintMessage(1, \"   p2 = \", int(GetTriangle(st).PNum(2)), \" = \", \n\t\t   Point3d (GetPoint(GetTriangle(st).PNum(2))));\n      PrintMessage(1, \"   p3 = \", int(GetTriangle(st).PNum(3)), \" = \", \n\t\t   Point3d (GetPoint(GetTriangle(st).PNum(3))));\n    }\n}\n\nvoid STLGeometry :: LoadMarkedTrigs()\n{\n  PrintFnStart(\"load marked trigs from file 'markedtrigs.ng'\");\n  ifstream fin(\"markedtrigs.ng\");\n\n  int n;\n  fin >> n;\n  if (n != GetNT() || n == 0) {PrintError(\"Not a suitable marked-trig-file!\"); return;}\n\n  int i, m;\n  for (i = 1; i <= n; i++)\n    {\n      fin >> m;\n      SetMarkedTrig(i, m);      \n    }\n\n  fin >> n;\n  if (n != 0) \n    {\n \n      Point<3> ap1, ap2;\n      for (i = 1; i <= n; i++)\n\t{\n\t  fin >> ap1(0); fin >> ap1(1); fin >> ap1(2);\n\t  fin >> ap2(0); fin >> ap2(1); fin >> ap2(2);\n\t  AddMarkedSeg(ap1,ap2);      \n\t}\n    }\n}\n\nvoid STLGeometry :: SaveMarkedTrigs()\n{\n  PrintFnStart(\"save marked trigs to file 'markedtrigs.ng'\");\n  ofstream fout(\"markedtrigs.ng\");\n\n  int n = GetNT();\n  fout << n << endl;\n\n  int i;\n  for (i = 1; i <= n; i++)\n    {\n      fout << IsMarkedTrig(i) << \"\\n\";\n    }\n\n  n = GetNMarkedSegs();\n  fout << n << endl;\n\n  Point<3> ap1,ap2;\n  for (i = 1; i <= n; i++)\n    {\n      GetMarkedSeg(i,ap1,ap2);\n      fout << ap1(0) << \" \" << ap1(1) << \" \" << ap1(2) << \"  \";\n      fout << ap2(0) << \" \" << ap2(1) << \" \" << ap2(2) << \" \" << \"\\n\";\n    }\n\n}\n\nvoid STLGeometry :: NeighbourAnglesOfSelectedTrig()\n{\n  int st = GetSelectTrig();\n\n  if (st >= 1 && st <= GetNT())\n    {\n      int i;\n      PrintMessage(1,\"Angle to triangle \", st, \":\");\n      for (i = 1; i <= NONeighbourTrigs(st); i++)\n\t{\n\t  PrintMessage(1,\"   triangle \", int(NeighbourTrig(st,i)), \": angle = \", \n\t\t       180./M_PI*GetAngle(st, NeighbourTrig(st,i)), \"°\",\n\t\t       \", calculated = \", 180./M_PI*Angle(GetTriangle(st).GeomNormal(points), \n\t\t\t\t\t\t\t  GetTriangle(NeighbourTrig(st,i)).GeomNormal(points)), \"°\");\n\t}\n    }\n}\n\nvoid STLGeometry :: GetVicinity(int starttrig, int size, NgArray<int>& vic)\n{\n  if (starttrig == 0 || starttrig > GetNT()) {return;} \n\n  NgArray<int> vicarray;\n  vicarray.SetSize(GetNT());\n\n  int i;\n  for (i = 1; i <= vicarray.Size(); i++)\n    {\n      vicarray.Elem(i) = 0;\n    }\n \n  vicarray.Elem(starttrig) = 1;\n  \n  int j = 0,k;\n\n  NgArray <int> list1;\n  list1.SetSize(0);\n  NgArray <int> list2;\n  list2.SetSize(0);\n  list1.Append(starttrig);\n\n  while (j < size)\n    {\n      j++;\n      for (i = 1; i <= list1.Size(); i++)\n\t{\n\t  for (k = 1; k <= NONeighbourTrigs(i); k++)\n\t    {\n\t      int nbtrig = NeighbourTrig(list1.Get(i),k);\n\t      if (nbtrig && vicarray.Get(nbtrig) == 0)\n\t\t{\n\t\t  list2.Append(nbtrig);\n\t\t  vicarray.Elem(nbtrig) = 1;\n\t\t}\n\t    }\n\t}\n      list1.SetSize(0);\n      for (i = 1; i <= list2.Size(); i++)\n\t{\n\t  list1.Append(list2.Get(i));\n\t}\n      list2.SetSize(0);\n    }\n\n  vic.SetSize(0);\n  for (i = 1; i <= vicarray.Size(); i++)\n    {\n      if (vicarray.Get(i)) {vic.Append(i);}\n    }\n}\n\nvoid STLGeometry :: CalcVicinity(int starttrig)\n{\n  if (starttrig == 0 || starttrig > GetNT()) {return;} \n\n  vicinity.SetSize(GetNT());\n\n  if (!stldoctor.showvicinity) {return;}\n\n  int i;\n  for (i = 1; i <= vicinity.Size(); i++)\n    {\n      vicinity.Elem(i) = 0;\n    }\n \n  vicinity.Elem(starttrig) = 1;\n  \n  int j = 0,k;\n\n  NgArray <int> list1;\n  list1.SetSize(0);\n  NgArray <int> list2;\n  list2.SetSize(0);\n  list1.Append(starttrig);\n\n  //  int cnt = 1;\n  while (j < stldoctor.vicinity)\n    {\n      j++;\n      for (i = 1; i <= list1.Size(); i++)\n\t{\n\t  for (k = 1; k <= NONeighbourTrigs(i); k++)\n\t    {\n\t      int nbtrig = NeighbourTrig(list1.Get(i),k);\n\t      if (nbtrig && vicinity.Get(nbtrig) == 0)\n\t\t{\n\t\t  list2.Append(nbtrig);\n\t\t  vicinity.Elem(nbtrig) = 1;\n\t\t  //cnt++;\n\t\t}\n\t    }\n\t}\n      list1.SetSize(0);\n      for (i = 1; i <= list2.Size(); i++)\n\t{\n\t  list1.Append(list2.Get(i));\n\t}\n      list2.SetSize(0);\n    }\n\n}\n\nint STLGeometry :: Vicinity(int trig) const \n{\n  if (trig <= vicinity.Size() && trig >=1)\n    {\n      return vicinity.Get(trig);\n    }\n  else {PrintSysError(\"In STLGeometry::Vicinity\");}\n  return 0;\n}\n\nvoid STLGeometry :: InitMarkedTrigs()\n{\n  markedtrigs.SetSize(GetNT());\n  int i;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      SetMarkedTrig(i, 0);\n    }\n}\n\nvoid STLGeometry :: MarkDirtyTrigs(const STLParameters& stlparam)\n{\n  PrintFnStart(\"mark dirty trigs\");\n  int i,j;\n\n  markedtrigs.SetSize(GetNT());\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      SetMarkedTrig(i, 0);\n    }\n\n  int found;\n  double dirtyangle = stlparam.yangle/2./180.*M_PI;\n  int cnt = 0;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      found = 0;\n      for (j = 1; j <= NONeighbourTrigs(i); j++)\n\t{\n\t  if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)\n\t    {\n\t      found++;\n\t    }\n\t}\n      if (found && GetTriangle(i).MinHeight(points) < \n\t  stldoctor.dirtytrigfact*GetTriangle(i).MaxLength(points))\n\t{\n\t  SetMarkedTrig(i, 1); cnt++;\n\t}\n      /*\n      else if (found == 3)\n\t{\n\t  SetMarkedTrig(i, 1); cnt++;\t  \n\t}\n      */\n    }\n\n  PrintMessage(1, \"marked \", cnt, \" dirty trigs\");\n}\n\n\nvoid STLGeometry :: MarkTopErrorTrigs()\n{\n  int cnt = 0;\n  markedtrigs.SetSize(GetNT());\n  for (int i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & trig = GetTriangle(i);\n\n      SetMarkedTrig(i, trig.flags.toperror);\n      if (trig.flags.toperror) cnt++;\n    }\n  PrintMessage(1,\"marked \", cnt, \" inconsistent triangles\");\n}\n\n\n\ndouble STLGeometry :: CalcTrigBadness(int i)\n{\n  int j;\n  double maxbadness = 0;\n  STLPointId ap1, ap2;\n  for (j = 1; j <= NONeighbourTrigs(i); j++)\n    {\n      GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);\n      \n      if (!IsEdge(ap1,ap2) && GetGeomAngle(i, NeighbourTrig(i,j)) > maxbadness)\n\t{\n\t  maxbadness = GetGeomAngle(i, NeighbourTrig(i,j));\n\t}\n    }\n  return maxbadness;\n\n}\n\nvoid STLGeometry :: GeomSmoothRevertedTrigs(const STLParameters& stlparam)\n{\n  //double revertedangle = stldoctor.smoothangle/180.*M_PI;\n  double fact = stldoctor.dirtytrigfact;\n\n  MarkRevertedTrigs(stlparam);\n\n  int i, j, k, l, p;\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      if (IsMarkedTrig(i)) \n\t{\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      double origbadness = CalcTrigBadness(i);\n\n\t      p = GetTriangle(i).PNum(j);\n\t      Point<3> pm(0.,0.,0.); //Middlevector;\n\t      Point<3> p0(0.,0.,0.);\n\n\t      int cnt = 0;\n\n\t      for (k = 1; k <= trigsperpoint.EntrySize(p); k++)\n\t\t{\n\t\t  const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,k));\n\t\t  for (l = 1; l <= 3; l++)\n\t\t    {\n\t\t      if (tr.PNum(l) != p)\n\t\t\t{\n\t\t\t  cnt++;\n\t\t\t  pm(0) += GetPoint(tr.PNum(l))(0);\n\t\t\t  pm(1) += GetPoint(tr.PNum(l))(1);\n\t\t\t  pm(2) += GetPoint(tr.PNum(l))(2);\n\t\t\t}\n\t\t    }\n\t\t}\n\t      Point3d origp = GetPoint(p);\n\t      Point3d newp = p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0);\n\n\t      SetPoint(p, newp);\n\n\t      if (CalcTrigBadness(i) > 0.9*origbadness) {SetPoint(p,origp); PrintDot('f');}\n\t      else {PrintDot('s');}\n\t    }\n\t}\n    }\n  MarkRevertedTrigs(stlparam);\n}\n\nvoid STLGeometry :: MarkRevertedTrigs(const STLParameters& stlparam)\n{\n  int i,j;\n  if (edgesperpoint.Size() != GetNP()) {BuildEdges(stlparam);}\n\n  PrintFnStart(\"mark reverted trigs\");\n\n  InitMarkedTrigs();\n\n  int found;\n  double revertedangle = stldoctor.smoothangle/180.*M_PI;\n\n  int cnt = 0;\n  STLPointId ap1, ap2;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      found = 0;\n      for (j = 1; j <= NONeighbourTrigs(i); j++)\n\t{\n\t  GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);\n\n\t  if (!IsEdge(ap1,ap2))\n\t    {\n              if (GetGeomAngle(i, NeighbourTrig(i,j)) > revertedangle)\n\t\t{\n\t\t  found = 1;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n      \n      if (found)\n\t{\n\t  SetMarkedTrig(i, 1); cnt++;\n\t}\n      \n    }\n\n  PrintMessage(5, \"found \", cnt, \" reverted trigs\");\n\n\n}\n\nvoid STLGeometry :: SmoothDirtyTrigs(const STLParameters& stlparam)\n{\n  PrintFnStart(\"smooth dirty trigs\");\n\n  MarkDirtyTrigs(stlparam);\n\n  int i,j;\n  int changed = 1;\n  STLPointId ap1, ap2;\n  \n  while (changed)\n    {\n      changed = 0;\n      for (i = 1; i <= GetNT(); i++)\n\t{\n\t  if (IsMarkedTrig(i))\n\t    {\n\t      int foundtrig = 0;\n\t      double maxlen = 0;\n\t      // JS: darf normalvector nicht ueber kurze Seite erben\n\t      maxlen = GetTriangle(i).MaxLength(GetPoints()) / 2.1; //JG: bei flachem dreieck auch kurze Seite\n\n\t      for (j = 1; j <= NONeighbourTrigs(i); j++)\n\t\t{\n\t\t  if (!IsMarkedTrig(NeighbourTrig(i,j)))\n\t\t    {\n\t\t      GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)),ap1,ap2);\n\t\t      if (Dist(GetPoint(ap1),GetPoint(ap2)) >= maxlen)\n\t\t\t{\n\t\t\t  foundtrig = NeighbourTrig(i,j);\n\t\t\t  maxlen = Dist(GetPoint(ap1),GetPoint(ap2));\n\t\t\t}\n\t\t    }\n\t\t}\n\t      if (foundtrig)\n\t\t{\n\t\t  GetTriangle(i).SetNormal(GetTriangle(foundtrig).Normal());\n\t\t  changed = 1;\n\t\t  SetMarkedTrig(i,0);\n\t\t}\n\t    }\n\t}\n    }\n\n  calcedgedataanglesnew = 1;\n\n\n  MarkDirtyTrigs(stlparam);\n\n  int cnt = 0;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      if (IsMarkedTrig(i)) {cnt++;}\n    }\n\n  PrintMessage(5,\"NO marked dirty trigs=\", cnt);\n\n}\n\nint STLGeometry :: IsMarkedTrig(int trig) const \n{\n  if (trig <= markedtrigs.Size() && trig >=1)\n    {\n      return markedtrigs.Get(trig);\n    }\n  else {PrintSysError(\"In STLGeometry::IsMarkedTrig\");}\n\n  return 0;  \n}\n\nvoid STLGeometry :: SetMarkedTrig(int trig, int num)\n{\n  if (trig <= markedtrigs.Size() && trig >=1)\n    {\n      markedtrigs.Elem(trig) = num;\n    }\n  else {PrintSysError(\"In STLGeometry::SetMarkedTrig\");}\n}\n\nvoid STLGeometry :: Clear()\n{\n  PrintFnStart(\"Clear\");\n\n  surfacemeshed = 0;\n  surfaceoptimized = 0;\n  volumemeshed = 0;\n\n  selectedmultiedge.SetSize(0);\n  meshlines.SetSize(0);\n  // neighbourtrigs.SetSize(0);\n  outerchartspertrig.SetSize(0);\n  atlas.SetSize(0);\n  ClearMarkedSegs();\n  ClearSpiralPoints();\n  ClearLineEndPoints();\n\n  SetSelectTrig(0);\n  SetNodeOfSelTrig(1);\n  facecnt = 0;\n\n  SetThreadPercent(100.);\n\n  ClearEdges();\n}\n\ndouble STLGeometry :: Area()\n{\n  if (area >= 0) return area;\n  area = 0;\n  for (int i = 1; i <= GetNT(); i++)\n    area += GetTriangle(i).Area(points);\n  return area;\n}\n\ndouble STLGeometry :: GetAngle(int t1, int t2)\n{\n  return Angle(GetTriangle(t1).Normal(),GetTriangle(t2).Normal());\n}\n\ndouble STLGeometry :: GetGeomAngle(int t1, int t2)\n{\n  Vec3d n1 = GetTriangle(t1).GeomNormal(points);\n  Vec3d n2 = GetTriangle(t2).GeomNormal(points);\n  return Angle(n1,n2);\n}\n\n\nvoid STLGeometry :: InitSTLGeometry(const NgArray<STLReadTriangle> & readtrias)\n{\n  PrintFnStart(\"Init STL Geometry\");\n  STLTopology::InitSTLGeometry(readtrias);\n\n  int i, k;\n\n  //const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored\n\n  int np = GetNP();\n  PrintMessage(5,\"NO points= \", GetNP());\n  normals.SetSize(GetNP());\n  NgArray<int> normal_cnt(GetNP()); // counts number of added normals in a point\n\n  for (i = 1; i <= np; i++)\n    {\n      normal_cnt.Elem(i) = 0;\n      normals.Elem(i) = Vec3d (0,0,0);\n    }\n\n  for(i = 1; i <= GetNT(); i++)\n    {\n      //      STLReadTriangle t = GetReadTriangle(i);\n      //      STLTriangle st;\n\n      Vec<3> n = GetTriangle(i).Normal ();\n\n      for (k = 1; k <= 3; k++)\n\t{\n\t  int pi = GetTriangle(i).PNum(k);\n\t  \n\t  normal_cnt.Elem(pi)++;\n\t  SetNormal(pi, GetNormal(pi) + n);\n\t}\n    } \n\n  //normalize the normals\n  for (i = 1; i <= GetNP(); i++)\n    {\n      SetNormal(i,1./(double)normal_cnt.Get(i)*GetNormal(i));\n    }\n\n  trigsconverted = 1;\n\n  vicinity.SetSize(GetNT());\n  markedtrigs.SetSize(GetNT());\n  for (i = 1; i <= GetNT(); i++)\n    {\n      markedtrigs.Elem(i) = 0;\n      vicinity.Elem(i) = 1;\n    }\n\n  ha_points.SetSize(GetNP());\n  for (i = 1; i <= GetNP(); i++)\n    ha_points.Elem(i) = 0;\n\n  calcedgedataanglesnew = 0;\n  edgedatastored = 0;\n  edgedata->Clear();\n\n\n  if (GetStatus() == STL_ERROR) return;\n\n  CalcEdgeData();\n  CalcEdgeDataAngles();\n\n  ClearLineEndPoints();\n\n  CheckGeometryOverlapping();\n}\n\nvoid STLGeometry :: TopologyChanged()\n{\n  calcedgedataanglesnew = 1;\n}\n\nint STLGeometry :: CheckGeometryOverlapping()\n{\n  PrintMessageCR(3,\"Check overlapping geometry ...\");\n\n  Box<3> geombox = GetBoundingBox();\n  Point<3> pmin = geombox.PMin();\n  Point<3> pmax = geombox.PMax();\n\n  BoxTree<3> setree(pmin, pmax);\n\n  int oltrigs = 0;\n  markedtrigs.SetSize(GetNT());\n\n  for (int i = 1; i <= GetNT(); i++)\n    SetMarkedTrig(i, 0);\n\n  for (int i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & tri = GetTriangle(i);\n      \n      Point<3> tpmin = tri.box.PMin();\n      Point<3> tpmax = tri.box.PMax();\n      Vec<3> diag = tpmax - tpmin;\n\n      tpmax = tpmax + 0.001 * diag;\n      tpmin = tpmin - 0.001 * diag;\n\n      setree.Insert (tpmin, tpmax, i);\n    }\n\n\n  {\n    mutex inters_mutex;\n    \n    ParallelFor( 1, GetNT()+1, [&] (int first, int next)\n                 {\n                   NgArray<int> inters;\n                   for (int i=first; i<next; i++) {\n                     const STLTriangle & tri = GetTriangle(i);\n\t\n                     Point<3> tpmin = tri.box.PMin();\n                     Point<3> tpmax = tri.box.PMax();\n\t\n                     setree.GetIntersecting (tpmin, tpmax, inters);\n\t\n                     for (int j = 1; j <= inters.Size(); j++)\n                       {\n                         const STLTriangle & tri2 = GetTriangle(inters.Get(j));\n\t    \n                         const Point<3> *trip1[3], *trip2[3];\t\n                         Point<3> hptri1[3], hptri2[3];\n                         /*\n                           for (k = 1; k <= 3; k++)\n                           {\n                           trip1[k-1] = &GetPoint (tri.PNum(k));\n                           trip2[k-1] = &GetPoint (tri2.PNum(k));\n                           }\n                         */\n\t    \n                         for (int k = 0; k < 3; k++)\n                           {\n                             hptri1[k] = GetPoint (tri[k]);\n                             hptri2[k] = GetPoint (tri2[k]);\n                             trip1[k] = &hptri1[k];\n                             trip2[k] = &hptri2[k];\n                           }\n\n                         if (IntersectTriangleTriangle (&trip1[0], &trip2[0]))\n                           {\n                             lock_guard<mutex> guard(inters_mutex);\n                             {\n                               oltrigs++;\n                               PrintMessage(5,\"Intersecting Triangles: trig \",i,\" with \",inters.Get(j),\"!\");\n                               SetMarkedTrig(i, 1);\n                               SetMarkedTrig(inters.Get(j), 1);\n                             }\n                           }\n                       }\n                   }\n                 });\n  }\n  PrintMessage(3,\"Check overlapping geometry ... \", oltrigs, \" triangles overlap\");\n  return oltrigs;\n}\n\n/*\n  void STLGeometry :: InitSTLGeometry()\n  {\n  STLTopology::InitSTLGeometry();\n\n  int i, j, k;\n\n  const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored\n\n\n  trias.SetSize(0);\n  points.SetSize(0);\n  normals.SetSize(0);\n\n  NgArray<int> normal_cnt; // counts number of added normals in a point\n\n  Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),\n  GetBoundingBox().PMax() + Vec3d (1, 1, 1));\n\n  Point3dTree pointtree (bb.PMin(), \n  bb.PMax());\n  NgArray<int> pintersect;\n\n  double gtol = GetBoundingBox().CalcDiam()/geometry_tol_fact;\n\n  for(i = 1; i <= GetReadNT(); i++)\n  {\n  //if (i%500==499) {(*mycout) << (double)i/(double)GetReadNT()*100. << \"%\" << endl;}\n\n  STLReadTriangle t = GetReadTriangle(i);\n  STLTriangle st;\n  Vec3d n = t.normal;\n\n  for (k = 0; k < 3; k++)\n  {\n  Point3d p = t.pts[k];\n\n  Point3d pmin = p - Vec3d (gtol, gtol, gtol);\n  Point3d pmax = p + Vec3d (gtol, gtol, gtol);\n\t  \n  pointtree.GetIntersecting (pmin, pmax, pintersect);\n\t  \n  if (pintersect.Size() > 1)\n  (*mycout) << \"found too much  \" << char(7) << endl;\n  int foundpos = 0;\n  if (pintersect.Size())\n  foundpos = pintersect.Get(1);\n\n  if (foundpos) \n  {\n  normal_cnt[foundpos]++;\n  SetNormal(foundpos,GetNormal(foundpos)+n);\n  //\t      (*testout) << \"found p \" << p << endl;\n  }\n  else\n  {\n  foundpos = AddPoint(p);\n  AddNormal(n);\n  normal_cnt.Append(1);\n\n  pointtree.Insert (p, foundpos);\n  }\n  //(*mycout) << \"foundpos=\" << foundpos << endl;\n  st.pts[k] = foundpos;\n  }\n\n  if ( (st.pts[0] == st.pts[1]) || \n  (st.pts[0] == st.pts[2]) || \n  (st.pts[1] == st.pts[2]) )\n  {\n  (*mycout) << \"ERROR: STL Triangle degenerated\" << endl;\n  }\n  else\n  {\n  // do not add ? js\n  AddTriangle(st);\n  }\n  //(*mycout) << \"TRIG\" << i << \" = \" << st << endl;\n      \n  } \n  //normal the normals\n  for (i = 1; i <= GetNP(); i++)\n  {\n  SetNormal(i,1./(double)normal_cnt[i]*GetNormal(i));\n  }\n\n  trigsconverted = 1;\n\n  vicinity.SetSize(GetNT());\n  markedtrigs.SetSize(GetNT());\n  for (i = 1; i <= GetNT(); i++)\n  {\n  markedtrigs.Elem(i) = 0;\n  vicinity.Elem(i) = 1;\n  }\n\n  ha_points.SetSize(GetNP());\n  for (i = 1; i <= GetNP(); i++)\n  ha_points.Elem(i) = 0;\n\n  calcedgedataanglesnew = 0;\n  edgedatastored = 0;\n  edgedata->Clear();\n\n  CalcEdgeData();\n  CalcEdgeDataAngles();\n\n  ClearLineEndPoints();\n\n  (*mycout) << \"done\" << endl;\n  }\n*/\n\n\n\nvoid STLGeometry :: SetLineEndPoint(int pn) \n{\n  if (pn <1 || pn > lineendpoints.Size()) {PrintSysError(\"Illegal pnum in SetLineEndPoint!!!\"); return; }\n  lineendpoints.Elem(pn) = 1;\n}\n\nint STLGeometry :: IsLineEndPoint(int pn) \n{\n  //  return 0;\n  if (pn <1 || pn > lineendpoints.Size()) \n    {PrintSysError(\"Illegal pnum in IsLineEndPoint!!!\"); return 0;}\n  return lineendpoints.Get(pn);\n}\n\nvoid STLGeometry :: ClearLineEndPoints()\n{\n  lineendpoints.SetSize(GetNP());\n  int i;\n  for (i = 1; i <= GetNP(); i++)\n    {\n      lineendpoints.Elem(i) = 0;\n    }\n}\n\nint STLGeometry :: IsEdge(int ap1, int ap2)\n{\n  int i,j;\n  for (i = 1; i <= GetNEPP(ap1); i++)\n    {\n      for (j = 1; j <= GetNEPP(ap2); j++)\n\t{\n\t  if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return 1;}\n\t}\n    }\n  return 0;\n}\n\nint STLGeometry :: IsEdgeNum(int ap1, int ap2)\n{\n  int i,j;\n  for (i = 1; i <= GetNEPP(ap1); i++)\n    {\n      for (j = 1; j <= GetNEPP(ap2); j++)\n\t{\n\t  if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return GetEdgePP(ap1,i);}\n\t}\n    }\n  return 0;\n}\n\n\nvoid STLGeometry :: BuildEdges(const STLParameters& stlparam)\n{\n  //PrintFnStart(\"build edges\");\n  edges.SetSize(0);\n  meshlines.SetSize(0);\n  FindEdgesFromAngles(stlparam);\n}\n\nvoid STLGeometry :: UseExternalEdges()\n{\n  for (int i = 1; i <= NOExternalEdges(); i++)\n    AddEdge(GetExternalEdge(i).i1,GetExternalEdge(i).i2);\n  //BuildEdgesPerPointy();\n}\n\nvoid STLGeometry :: UndoEdgeChange()\n{\n  if (edgedatastored) \n    {\n      RestoreEdgeData();\n    }\n  else\n    {\n      PrintWarning(\"no edge undo possible\");\n    }\n}\n\n\nvoid STLGeometry :: StoreEdgeData()\n{\n  //  edgedata_store = *edgedata;\n  \n  edgedata->Store();\n  edgedatastored = 1;\n\n  // put stlgeom-edgedata to stltopology edgedata \n  /*\n    int i;\n    for (i = 1; i <= GetNTE(); i++)\n    {\n    const STLTopEdge & topedge = GetTopEdge (i);\n    int ednum = edgedata->GetEdgeNum (topedge.PNum(1),\n    topedge.PNum(2));\n    topedges.Elem(i).SetStatus (edgedata->Get (ednum).status);\n    }\n  */\n}\n\nvoid STLGeometry :: RestoreEdgeData()\n{\n  //  *edgedata = edgedata_store;\n  edgedata->Restore();\n  edgedatastored=0;\n}\n\n\nvoid STLGeometry :: CalcEdgeData()\n{\n  PushStatus(\"Calc Edge Data\");\n\n  STLPointId np1, np2;\n  \n  int ecnt = 0;\n  edgedata->SetSize(GetNT()/2*3);\n\n  for (int i = 1; i <= GetNT(); i++)\n    {\n      SetThreadPercent((double)i/(double)GetNT()*100.);\n      \n      const STLTriangle & t1 = GetTriangle(i);\n\n      for (int j = 1; j <= NONeighbourTrigs(i); j++)\n\t{\n\t  int nbti = NeighbourTrig(i,j);\n\t  if (nbti > i)\n\t    {\n\t      const STLTriangle & t2 = GetTriangle(nbti);\n\n\t      if (t1.IsNeighbourFrom(t2))\n\t\t{\n\t\t  ecnt++; if (ecnt > edgedata->Size()) {PrintError(\"In Calc edge data, illegal geometry\");}\n\n\t\t  t1.GetNeighbourPoints(t2,np1,np2);\n\n\t\t  /* ang = GetAngle(i,nbti);\n\t\t     if (ang < -M_PI) {ang += 2*M_PI;}*/\n\n\n\t\t  // edgedata->Add(STLEdgeData(0, np1, np2, i, nbti),ecnt);\n\t\t  edgedata->Elem(ecnt).SetStatus(ED_UNDEFINED);\n\n\t\t  // edgedata->Elem(ecnt).top = this;\n\t\t  // edgedata->Elem(ecnt).topedgenr = GetTopEdgeNum (np1, np2);\n\t\t}\n\t    }\n\t}      \n    }\n  \n  //BuildEdgesPerPoint();\n  PopStatus();  \n}\n\nvoid STLGeometry :: CalcEdgeDataAngles()\n{\n  PrintMessageCR (5,\"calc edge data angles ... \");\n\n  for (int i = 1; i <= GetNTE(); i++)\n    {\n      STLTopEdge & edge = GetTopEdge (i);\n      double cosang = edge.TrigNum(2) == 0 ? 1. :\n\tGetTriangle(edge.TrigNum(1)).Normal() *\n\tGetTriangle(edge.TrigNum(2)).Normal();\n      edge.SetCosAngle (cosang);\n    }\n\n  for (int i = 1; i <= edgedata->Size(); i++)\n    {\n      /*\n      const STLEdgeData& e = edgedata->Get(i);\n      ang = GetAngle(e.lt,e.rt);\n      if (ang < -M_PI) {ang += 2*M_PI;}\n      edgedata->Elem(i).angle = fabs(ang);\n      */\n    }\n  PrintMessage (5,\"calc edge data angles ... done\");\n}\n\nvoid STLGeometry :: FindEdgesFromAngles(const STLParameters& stlparam)\n{\n  //  PrintFnStart(\"find edges from angles\");\n\n  double min_edge_angle = stlparam.yangle/180.*M_PI;\n  double cont_min_edge_angle = stlparam.contyangle/180.*M_PI;\n\n  double cos_min_edge_angle = cos (min_edge_angle);\n  double cos_cont_min_edge_angle = cos (cont_min_edge_angle);\n\n  if (calcedgedataanglesnew) {CalcEdgeDataAngles(); calcedgedataanglesnew = 0;}\n\n  for (int i = 1; i <= edgedata->Size(); i++)\n    {\n      STLTopEdge & sed = edgedata->Elem(i);\n      if(sed.TrigNum(2) == 0)\n        sed.SetStatus(ED_CONFIRMED);\n      if (sed.GetStatus() == ED_CANDIDATE || \n\t  sed.GetStatus() == ED_UNDEFINED)\n\t{\n\t  if (sed.CosAngle() <= cos_min_edge_angle)\n\t    {\n\t      sed.SetStatus (ED_CANDIDATE);\n\t    }\n\t  else\n\t    {\n\t      sed.SetStatus(ED_UNDEFINED);\n\t    }\n\t} \n    }\n\n  if (stlparam.contyangle < stlparam.yangle)\n    {\n      int changed = 1;\n      [[maybe_unused]] int its = 0;\n      while (changed && stlparam.contyangle < stlparam.yangle)\n\t{\n          its++;\n\t  //(*mycout) << \".\" << flush;\n\t  changed = 0;\n\t  for (int i = 1; i <= edgedata->Size(); i++)\n\t    {\n\t      STLTopEdge & sed = edgedata->Elem(i);\n\t      if (sed.CosAngle() <= cos_cont_min_edge_angle \n\t\t  && sed.GetStatus() == ED_UNDEFINED && \n\t\t  (edgedata->GetNConfCandEPP(sed.PNum(1)) == 1 || \n\t\t   edgedata->GetNConfCandEPP(sed.PNum(2)) == 1))\n\t\t{\n\t\t  changed = 1;\n\t\t  sed.SetStatus (ED_CANDIDATE);\n\t\t}\n\t    }\n\t}\n    }\n  \n  int confcand = 0;\n  if (edgedata->GetNConfEdges() == 0) \n    {\n      confcand = 1;\n    }\n  \n  for (int i = 1; i <= edgedata->Size(); i++)\n    {\n      STLTopEdge & sed = edgedata->Elem(i);\n      if (sed.GetStatus() == ED_CONFIRMED || \n\t  (sed.GetStatus() == ED_CANDIDATE && confcand))\n\t{\n\t  STLEdge se(sed.PNum(1),sed.PNum(2));\n\t  se.SetLeftTrig(sed.TrigNum(1));\n\t  se.SetRightTrig(sed.TrigNum(2));\n\t  AddEdge(se);\n\t}\n    }\n  BuildEdgesPerPoint();\n\n  \n\n  //(*mycout) << \"its for continued angle = \" << its << endl;\n  PrintMessage(5,\"built \", GetNE(), \" edges with yellow angle = \", stlparam.yangle, \" degree\");\n  \n}\n\n/*\nvoid STLGeometry :: FindEdgesFromAngles()\n{\n  double yangle = stlparam.yangle;\n  char * savetask = multithread.task;\n  multithread.task = \"find edges\";\n\n  const double min_edge_angle = yangle/180.*M_PI;\n\n  int np1, np2;\n  double ang;\n  int i;\n\n  //(*mycout) << \"area=\" << Area() << endl;\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      multithread.percent = (double)i/(double)GetReadNT()*100.;\n      \n      const STLTriangle & t1 = GetTriangle(i);\n      //NeighbourTrigs(nt,i);\n\n      for (int j = 1; j <= NONeighbourTrigs(i); j++)\n\t{\n\t  int nbti = NeighbourTrig(i,j);\n\t  if (nbti > i)\n\t    {\n\t      const STLTriangle & t2 = GetTriangle(nbti);\n\n\t      if (t1.IsNeighbourFrom(t2))\n\t\t{\n\t\t  ang = GetAngle(i,nbti);\n\t\t  if (ang < -M_PI*0.5) {ang += 2*M_PI;}\n\n\t\t  t1.GetNeighbourPoints(t2,np1,np2);\n\t\t  \n\t\t  if (fabs(ang) >= min_edge_angle)\n\t\t    {\n\t\t      STLEdge se(np1,np2);\n\t\t      se.SetLeftTrig(i);\n\t\t      se.SetRightTrig(nbti);\n\t\t      AddEdge(se);\n\t\t    }\n\t\t}\n\t    }\n\t}      \n    }\n  \n  (*mycout) << \"added \" << GetNE() << \" edges\" << endl;\n\n  //BuildEdgesPerPoint();\n\n  multithread.percent = 100.;\n  multithread.task = savetask;\n  \n}\n*/\nvoid STLGeometry :: BuildEdgesPerPoint()\n{\n  //cout << \"*** build edges per point\" << endl;\n  edgesperpoint.SetSize(GetNP());\n\n  //add edges to points\n  for (int i = 1; i <= GetNE(); i++)\n    {\n      //(*mycout) << \"EDGE \" << GetEdge(i).PNum(1) << \" - \" << GetEdge(i).PNum(2) << endl;\n      for (int j = 1; j <= 2; j++)\n\t{\n\t  AddEdgePP(GetEdge(i).PNum(j),i);\n\t}\n    }\n}\n\nvoid STLGeometry :: AddFaceEdges()\n{\n  PrintFnStart(\"Add starting edges for faces\");\n\n  //für Kugel eine STLLine hinzufügen (Vorteil: verfeinerbar, unabhängig von Auflösung der Geometrie!!!):\n  //Grenze von 1. gefundener chart\n\n  NgArray<int> edgecnt;\n  NgArray<int> chartindex;\n  edgecnt.SetSize(GetNOFaces());\n  chartindex.SetSize(GetNOFaces());\n\n  for (int i = 1; i <= GetNOFaces(); i++)\n    {\n      edgecnt.Elem(i) = 0;\n      chartindex.Elem(i) = 0;\n    }\n\n  for (int i = 1; i <= GetNT(); i++)\n    {\n      int fn = GetTriangle(i).GetFaceNum();\n      if (!chartindex.Get(fn)) {chartindex.Elem(fn) = GetChartNr(i);}\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  edgecnt.Elem(fn) += GetNEPP(GetTriangle(i).PNum(j));\n\t}\n    }\n\n  for (int i = 1; i <= GetNOFaces(); i++)\n    {\n      if (!edgecnt.Get(i)) {PrintMessage(5,\"Face\", i, \" has no edge!\");}\n    }\n  \n  int changed = 0;\n  STLPointId ap1, ap2;\n  for (int i = 1; i <= GetNOFaces(); i++)\n    {\n      if (!edgecnt.Get(i))\n      {\n\tconst STLChart& c = GetChart(chartindex.Get(i));\n        // bool foundone = false;\n        int longest_ap1 = -1, longest_ap2 = -1;\n        double maxlen = -1;\n\tfor (int j = 1; j <= c.GetNChartT(); j++)\n\t  {\n\t    const STLTriangle& t1 = GetTriangle(c.GetChartTrig1(j));\n\t    for (int k = 1; k <= 3; k++)\n\t      {\n\t\tint nt = NeighbourTrig(c.GetChartTrig1(j),k);\n\t\tif (GetChartNr(nt) != chartindex.Get(i))\n\t\t  {\n\t\t    t1.GetNeighbourPoints(GetTriangle(nt),ap1,ap2);\n                    // AddEdge(ap1,ap2);\n                    double len = Dist(GetPoint(ap1), GetPoint(ap2));\n                    if (len > maxlen) \n                      {\n                        maxlen = len;\n                        longest_ap1 = ap1;\n                        longest_ap2 = ap2;\n                      }\n\t\t    changed = 1;\n\t\t  }\n\t      }\n\t  }\n        if (maxlen > 0)\n          AddEdge(longest_ap1,longest_ap2);\n      }\n      \n    }\n  \n  if (changed) BuildEdgesPerPoint();\n  \n}\n\nvoid STLGeometry :: LinkEdges(const STLParameters& stlparam)\n{\n  PushStatusF(\"Link Edges\");\n  PrintMessage(5,\"have now \", GetNE(), \" edges with yellow angle = \", stlparam.yangle, \" degree\");\n\n  int i;\n\n  lines.SetSize(0);\n  int starte(0);\n  int edgecnt = 0;\n  int found;\n  int rev(0); //indicates, that edge is inserted reverse\n\n  //worked edges\n  NgArray<int> we(GetNE());\n\n  //setlineendpoints; wenn 180°, dann keine endpunkte\n  //nur punkte mit 2 edges kommen in frage, da bei mehr oder weniger punkten ohnehin ein meshpoint hinkommt\n\n  Vec3d v1,v2;\n  double cos_eca = cos(stlparam.edgecornerangle/180.*M_PI);\n  int ecnt = 0;\n  int lp1, lp2;\n  if (stlparam.edgecornerangle < 180)\n    {\n      for (i = 1; i <= GetNP(); i++)\n\t{\n\t  if (GetNEPP(i) == 2)\n\t    {\n\t      if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) ||\n\t\t  GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2))\n\t\t{\n\t\t  lp1 = 1; lp2 = 2;\n\t\t}\n\t      else\n\t\t{\n\t\t  lp1 = 2; lp2 = 1;\n\t\t}\n\n\t      v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)),\n\t\t\t GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2)));\n\t      v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)),\n\t\t\t GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2)));\n\t      if ((v1*v2)/sqrt(v1.Length2()*v2.Length2()) < cos_eca) \n\t\t{\n\t\t  //(*testout) << \"add edgepoint \" << i << endl;\n\t\t  SetLineEndPoint(i);\n\t\t  ecnt++;\n\t\t}\n\t    }\t  \n\t}\n    }\n  PrintMessage(5, \"added \", ecnt, \" mesh_points due to edge corner angle (\", \n\t       stlparam.edgecornerangle, \" degree)\");\n\n  for (i = 1; i <= GetNE(); i++) {we.Elem(i) = 0;}\n\n  while(edgecnt < GetNE())\n    {\n      SetThreadPercent((double)edgecnt/(double)GetNE()*100.);\n\n      STLLine* line = new STLLine(this);\n\n      //find start edge\n      int j = 1;\n      found = 0;\n      //try second time, if only rings are left!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      int second = 0;\n\n      //find a starting edge at point with 1 or more than 2 edges or at lineendpoint\n      while (!found && j<=GetNE())\n\t{\n\t  if (!we.Get(j))\n\t    {\n\t      if (GetNEPP(GetEdge(j).PNum(1)) != 2 || IsLineEndPoint(GetEdge(j).PNum(1)))\n\t\t{\n\t\t  starte = j;\n\t\t  found = 1;\n\t\t  rev = 0;\n\t\t}\n\t      else \n\t      if (GetNEPP(GetEdge(j).PNum(2)) != 2 || IsLineEndPoint(GetEdge(j).PNum(2)))\n\t\t{\n\t\t  starte = j;\n\t\t  found = 1;\n\t\t  rev = 1;\n\t\t}\n\t      else if (second)\n\t\t{\n\t\t  starte = j;\n\t\t  found = 1;\n\t\t  rev = 0; //0 or 1 are possible\n\t\t}\n\t    }\n\t  j++;\n\t  if (!second && j == GetNE()) {second = 1; j = 1;}\n\t}\n\n      if (!found) {PrintSysError(\"No starting edge found, edgecnt=\", edgecnt, \", GETNE=\", GetNE());}\n\n      line->AddPoint(GetEdge(starte).PNum(1+rev));\n      line->AddPoint(GetEdge(starte).PNum(2-rev));\n      if (!rev)\n\t{\n\t  line->AddLeftTrig(GetEdge(starte).LeftTrig());\n\t  line->AddRightTrig(GetEdge(starte).RightTrig());\n\t}\n      else\n\t{\n\t  line->AddLeftTrig(GetEdge(starte).RightTrig());\n\t  line->AddRightTrig(GetEdge(starte).LeftTrig());\n\t}\n      edgecnt++; we.Elem(starte) = 1;\n\n      //add segments to line as long as segments other than starting edge are found or lineendpoint is reached \n      found = 1;\n      int other;\n      while(found)\n\t{\n\t  found = 0;\n\t  int fp = GetEdge(starte).PNum(2-rev);\n\t  if (GetNEPP(fp) == 2 && !IsLineEndPoint(fp))\n\t    {\n\t      //find the \"other\" edge of point fp\n\t      other = 0;\n\t      if (GetEdgePP(fp,1) == starte) {other = 1;}\n\n\t      starte = GetEdgePP(fp,1+other);\n\n\t      //falls ring -> aufhoeren !!!!!!!!!!!\n\t      if (!we.Elem(starte))\n\t\t{\n\t\t  found = 1;\n\t\t  rev = 0;\n\t\t  if (GetEdge(starte).PNum(2) == fp) {rev = 1;}\n\t\t  else if (GetEdge(starte).PNum(1) != fp) {PrintSysError(\"In Link Edges!\");}\n\n\t\t  line->AddPoint(GetEdge(starte).PNum(2-rev));\n\t\t  if (!rev) \n\t\t    {\n\t\t      line->AddLeftTrig(GetEdge(starte).LeftTrig());\n\t\t      line->AddRightTrig(GetEdge(starte).RightTrig());\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      line->AddLeftTrig(GetEdge(starte).RightTrig());\n\t\t      line->AddRightTrig(GetEdge(starte).LeftTrig());\n\t\t    }\n\t\t  edgecnt++; we.Elem(starte) = 1;\n\t\t}\n\t    }     \n\t}\n      AddLine(line);      \n    }\n  PrintMessage(5,\"number of lines generated = \", GetNLines());\n\n  //check, which lines must have at least one midpoint\n  INDEX_2_HASHTABLE<int> lineht(GetNLines()+1);\n\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      if (GetLine(i)->StartP() == GetLine(i)->EndP())\n\t{\n\t  GetLine(i)->DoSplit();\t  \n\t}\n    }\n\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      INDEX_2 lineep (GetLine(i)->StartP(),GetLine(i)->EndP());\n      lineep.Sort();\n\n      if (lineht.Used (lineep))\n\t{\n\t  GetLine(i)->DoSplit();\n\t  int other = lineht.Get(lineep);\n\t  GetLine(other)->DoSplit();\n\t}\n      else\n\t{\n\t  lineht.Set (lineep, i);\n\t}\n    }\n\n  for (i = 1; i <= GetNLines(); i++)\n    {\n      STLLine* line = GetLine(i);\n      for (int ii = 1; ii <= line->GetNS(); ii++)\n\t{\n\t  int ap1, ap2;\n\t  line->GetSeg(ii,ap1,ap2);\n\t  //\t  (*mycout) << \"SEG \" << p1 << \" - \" << p2 << endl;\n\t}\n    }\n\n  PopStatus();\n}\n\nint STLGeometry :: GetNOBodys()\n{\n  int markedtrigs1 = 0;\n  int starttrig = 1;\n  int i, k, nnt;\n  int bodycnt = 0;\n\n  NgArray<int> bodynum(GetNT());\n\n  for (i = 1; i <= GetNT(); i++)\n    bodynum.Elem(i)=0;\n\n\n  while (markedtrigs1 < GetNT())\n    {\n      for (i = starttrig; i <= GetNT(); i++)\n\t{\n\t  if (!bodynum.Get(i))\n\t    {\n\t      starttrig = i;\n\t      break;\n\t    }\n\t} \n      //add all triangles around starttriangle, which is reachable without going over an edge\n      NgArray<int> todolist;\n      NgArray<int> nextlist;\n      bodycnt++;\n      markedtrigs1++;\n      bodynum.Elem(starttrig) = bodycnt;\n      todolist.Append(starttrig);\n\n      while(todolist.Size())\n\t{\n\t  for (i = 1; i <= todolist.Size(); i++)\n\t    {\n\t      //const STLTriangle& tt = GetTriangle(todolist.Get(i));\n\t      for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)\n\t\t{\n\t\t  nnt = NeighbourTrig(todolist.Get(i),k);\n\t\t  if (!bodynum.Get(nnt))\n\t\t    {\n\t\t      nextlist.Append(nnt);\n\t\t      bodynum.Elem(nnt) = bodycnt;\n\t\t      markedtrigs1++;\n\t\t    }\n\t\t}\n\t    }\n\t  \n\t  todolist.SetSize(0);\n\t  for (i = 1; i <= nextlist.Size(); i++)\n\t    {\n\t      todolist.Append(nextlist.Get(i));\n\t    }\n\t  nextlist.SetSize(0);\t  \n\t}\n    }\n  PrintMessage(3, \"Geometry has \", bodycnt, \" separated bodys\");\n\n  return bodycnt;\n}\n\nvoid STLGeometry :: CalcFaceNums()\n{\n  int markedtrigs1 = 0;\n  int starttrig(0);\n  int laststarttrig = 1;\n  int i, k, nnt;\n  facecnt = 0;\n\n\n  for (i = 1; i <= GetNT(); i++)\n    GetTriangle(i).SetFaceNum(0);\n\n\n  while (markedtrigs1 < GetNT())\n    {\n      for (i = laststarttrig; i <= GetNT(); i++)\n\t{\n\t  if (!GetTriangle(i).GetFaceNum()) \n\t    {\n\t      starttrig = i;\n\t      laststarttrig = i;\n\t      break;\n\t    }\n\t} \n      //add all triangles around starttriangle, which is reachable without going over an edge\n      NgArray<int> todolist;\n      NgArray<int> nextlist;\n      facecnt++;\n      markedtrigs1++;\n      GetTriangle(starttrig).SetFaceNum(facecnt);\n      todolist.Append(starttrig);\n      STLPointId ap1, ap2;\n\n      while(todolist.Size())\n\t{\n\t  for (i = 1; i <= todolist.Size(); i++)\n\t    {\n\t      const STLTriangle& tt = GetTriangle(todolist.Get(i));\n\t      for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)\n\t\t{\n\t\t  nnt = NeighbourTrig(todolist.Get(i),k);\n\t\t  STLTriangle& nt = GetTriangle(nnt);\n\t\t  if (!nt.GetFaceNum())\n\t\t    {\n\t\t      tt.GetNeighbourPoints(nt,ap1,ap2);\n\t\t      if (!IsEdge(ap1,ap2))\n\t\t\t{\n\t\t\t  nextlist.Append(nnt);\n\t\t\t  nt.SetFaceNum(facecnt);\n\t\t\t  markedtrigs1++;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t  \n\t  todolist.SetSize(0);\n\t  for (i = 1; i <= nextlist.Size(); i++)\n\t    {\n\t      todolist.Append(nextlist.Get(i));\n\t    }\n\t  nextlist.SetSize(0);\t  \n\t}\n    }\n  GetNOBodys();\n  PrintMessage(3,\"generated \", facecnt, \" faces\");\n}\n \nvoid STLGeometry :: ClearSpiralPoints()\n{\n  spiralpoints.SetSize(GetNP());\n  int i;\n  for (i = 1; i <= spiralpoints.Size(); i++)\n    {\n      spiralpoints.Elem(i) = 0;\n    }\n}\n\n\nvoid STLGeometry :: BuildSmoothEdges ()\n{\n  if (smoothedges) delete smoothedges;\n\n  smoothedges = new INDEX_2_HASHTABLE<int> (GetNE()/10 + 1);\n\n\n  // Jack: Ok ?\n  //  UseExternalEdges();\n\n  PushStatusF(\"Build Smooth Edges\");\n\n  int nt = GetNT();\n  Vec3d ng1, ng2;\n\n  for (int i = 1; i <= nt; i++)\n    {\n      if (multithread.terminate)\n\t{PopStatus();return;}\n\n      SetThreadPercent(100.0 * (double)i / (double)nt);\n\n      const STLTriangle & trig = GetTriangle (i);\n      \n      ng1 = trig.GeomNormal(points);\n      ng1 /= (ng1.Length() + 1e-24);\n\n      for (int j = 1; j <= NONeighbourTrigs(i); j++)\n\t{ \n\t  int nbt = NeighbourTrig (i, j);\n\n\t  ng2 = GetTriangle(nbt).GeomNormal(points);\n\t  ng2 /= (ng2.Length() + 1e-24);\n\t  \n\t  STLPointId pi1, pi2;\n\t  trig.GetNeighbourPoints(GetTriangle(nbt), pi1, pi2);\n\n\t  if (!IsEdge(pi1,pi2)) \n\t    {\n\t      if (ng1 * ng2 < 0)\n\t\t{\n\t\t  PrintMessage(7,\"smoothedge found\");\n\t\t  INDEX_2 i2(pi1, pi2);\n\t\t  i2.Sort();\n\t\t  smoothedges->Set (i2, 1);\n\t\t}\n\t    }\n\t}\n    }\n  PopStatus();\n}\n\n\n\n\n\nbool STLGeometry :: IsSmoothEdge (int pi1, int pi2) const\n{\n  if (!smoothedges)\n    return false;\n  INDEX_2 i2(pi1, pi2);\n  i2.Sort();\n  return smoothedges->Used (i2);\n}\n\n\n\n/*\n//function is not used now\nint IsInArray(int n, const NgArray<int>& ia)\n{\n  int i;\n  for (i = 1; i <= ia.Size(); i++)\n    {\n      if (ia.Get(i) == n) {return 1;}\n    }\n  return 0;\n}\n*/\n\nvoid STLGeometry :: AddConeAndSpiralEdges(const STLParameters& stlparam)\n{\n  PrintMessage(5,\"have now \", GetNE(), \" edges with yellow angle = \", stlparam.yangle, \" degree\");\n  \n  PrintFnStart(\"AddConeAndSpiralEdges\");\n\n  // int i,j,k,n;\n  //  int changed = 0;\n\n  //check edges, where inner chart and no outer chart come together without an edge\n  STLPointId np1, np2;\n  int cnt = 0;\n\n  for (ChartId i = 1; i <= GetNOCharts(); i++)\n    {\n      STLChart& chart = GetChart(i);\n      for (int j = 1; j <= chart.GetNChartT(); j++)\n\t{\n\t  STLTrigId t = chart.GetChartTrig1(j); \n\t  const STLTriangle& tt = GetTriangle(t);\n\n\t  for (int k = 1; k <= NONeighbourTrigs(t); k++)\n\t    {\n\t      STLTrigId nt = NeighbourTrig(t,k); \n\t      if (GetChartNr(nt) != i && !TrigIsInOC(nt,i))\n\t\t{\t      \n\t\t  tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t\t  if (!IsEdge(np1,np2))\n\t\t    {\n\t\t      STLEdge se(np1,np2);\n\t\t      se.SetLeftTrig(t);\n\t\t      se.SetRightTrig(nt);\n\t\t      int edgenum = AddEdge(se);\n\t\t      AddEdgePP(np1,edgenum);\n\t\t      AddEdgePP(np2,edgenum);\n\t\t      //changed = 1;\n\t\t      PrintWarning(\"Found a spiral like structure: chart=\", int(i),\n\t\t\t\t   \", trig=\", int(t), \", p1=\", int(np1), \", p2=\", int(np2));\n\t\t      cnt++;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\t  \n    }\n\n  PrintMessage(5, \"found \", cnt, \" spiral like structures\");\n  PrintMessage(5, \"added \", cnt, \" edges due to spiral like structures\");\n  \n  cnt = 0;\n  int edgecnt = 0;\n\n  Array<STLTrigId> trigsaroundp;\n  NgArray<int> chartpointchecked(GetNP()); //gets number of chart, if in this chart already checked\n  chartpointchecked = 0;\n\n\n  int onoc, notonoc, tpp, pn;\n  STLPointId ap1, ap2;\n  int tn1, tn2, l, problem;\n\n  if (!stldoctor.conecheck) {PrintWarning(\"++++++++++++ \\ncone checking deactivated by user!!!!!\\n+++++++++++++++\"); return ;}\n\n  PushStatus(\"Find Critical Points\");\n\n  int addedges = 0;\n\n  for (ChartId i = 1; i <= GetNOCharts(); i++)\n    {\n      SetThreadPercent((double)i/(double)GetNOCharts()*100.);\n      if (multithread.terminate)\n\t{PopStatus();return;}\n\n      STLChart& chart = GetChart(i);\n      for (int j = 1; j <= chart.GetNChartT(); j++)\n\t{\n\t  STLTrigId t = chart.GetChartTrig1(j); \n\t  const STLTriangle& tt = GetTriangle(t);\n\n\t  for (int k = 1; k <= 3; k++)\n\t    {\n\t      pn = tt.PNum(k);\n\t      if (chartpointchecked.Get(pn) == i)\n\t\t{continue;}\n\t      \n\t      int checkpoint = 0;\n\t      for (int n = 1; n <= trigsperpoint.EntrySize(pn); n++)\n\t\t{\n\t\t  if (trigsperpoint.Get(pn,n) != t && \n\t\t      GetChartNr(trigsperpoint.Get(pn,n)) != i &&\n\t\t      !TrigIsInOC(trigsperpoint.Get(pn,n),i)) {checkpoint = 1;};\n\t\t}\n\t      if (checkpoint)\n\t\t{\n\t\t  chartpointchecked.Elem(pn) = i;\n\n\t\t  int worked = 0;\n\t\t  int spworked = 0;\n\t\t  GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);\n\t\t  trigsaroundp.Append(t);\n\t\t      \n\t\t  problem = 0;\n\t\t  for (int l = 2; l <= trigsaroundp.Size()-1; l++)\n\t\t    {\n\t\t      tn1 = trigsaroundp[l-2];\n\t\t      tn2 = trigsaroundp[l-1];\n\t\t      const STLTriangle& t1 = GetTriangle(tn1);\n\t\t      const STLTriangle& t2 = GetTriangle(tn2);\n\t\t      t1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t      if (IsEdge(ap1,ap2)) break;\n\t\t      \n\t\t      if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}\n\t\t    }\n\n\t\t  if (problem)\n\t\t    {\n\t\t      for (int l = 2; l <= trigsaroundp.Size()-1; l++)\n\t\t\t{\n\t\t\t  tn1 = trigsaroundp[l-2];\n\t\t\t  tn2 = trigsaroundp[l-1];\n\t\t\t  const STLTriangle& t1 = GetTriangle(tn1);\n\t\t\t  const STLTriangle& t2 = GetTriangle(tn2);\n\t\t\t  t1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t\t  if (IsEdge(ap1,ap2)) break;\n\t\t\t  \n\t\t\t  if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||\n\t\t\t      (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i))) \t\t\t\t \n\t\t\t    {\n\t\t\t      if (addedges || !GetNEPP(pn))\n\t\t\t\t{\n\t\t\t\t  STLEdge se(ap1,ap2);\n\t\t\t\t  se.SetLeftTrig(tn1);\n\t\t\t\t  se.SetRightTrig(tn2);\n\t\t\t\t  int edgenum = AddEdge(se);\n\t\t\t\t  AddEdgePP(ap1,edgenum);\n\t\t\t\t  AddEdgePP(ap2,edgenum);\n\t\t\t\t  edgecnt++;\n\t\t\t\t}\n\t\t\t      if (!addedges && !GetSpiralPoint(pn))\n\t\t\t\t{\n\t\t\t\t  SetSpiralPoint(pn);\n\t\t\t\t  spworked = 1;\n\t\t\t\t}\n\t\t\t      worked = 1;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t  //backwards:\n\t\t  problem = 0;\n\t\t  for (int l = trigsaroundp.Size()-1; l >= 2; l--)\n\t\t    {\n\t\t      tn1 = trigsaroundp[l];\n\t\t      tn2 = trigsaroundp[l-1];\n\t\t      const STLTriangle& t1 = GetTriangle(tn1);\n\t\t      const STLTriangle& t2 = GetTriangle(tn2);\n\t\t      t1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t      if (IsEdge(ap1,ap2)) break;\n\t\t      \n\t\t      if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}\n\t\t    }\n\t\t  if (problem)\n\t\t    for (int l = trigsaroundp.Size()-1; l >= 2; l--)\n\t\t      {\n\t\t\ttn1 = trigsaroundp[l];\n\t\t\ttn2 = trigsaroundp[l-1];\n\t\t\tconst STLTriangle& t1 = GetTriangle(tn1);\n\t\t\tconst STLTriangle& t2 = GetTriangle(tn2);\n\t\t\tt1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t\tif (IsEdge(ap1,ap2)) break;\n\t\t\t\n\t\t\tif ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||\n\t\t\t    (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i))) \t\t\t\t \n\t\t\t  {\n\t\t\t    if (addedges || !GetNEPP(pn))\n\t\t\t      {\n\t\t\t\tSTLEdge se(ap1,ap2);\n\t\t\t\tse.SetLeftTrig(tn1);\n\t\t\t\tse.SetRightTrig(tn2);\n\t\t\t\tint edgenum = AddEdge(se);\n\t\t\t\tAddEdgePP(ap1,edgenum);\n\t\t\t\tAddEdgePP(ap2,edgenum);\n\t\t\t\tedgecnt++;\n\t\t\t      }\n\t\t\t    if (!addedges && !GetSpiralPoint(pn))\n\t\t\t      {\n\t\t\t\tSetSpiralPoint(pn);\n\t\t\t\tspworked = 1;\n\t\t\t\t//if (GetNEPP(pn) == 0) {(*mycout) << \"ERROR: spiralpoint with no edge found!\" << endl;}\n\t\t\t      }\n\t\t\t    worked = 1;\n\t\t\t  }\n\t\t      }\n\n\t\t  if (worked)\n\t\t    {\t\t      \n\t\t      //(*testout) << \"set edgepoint due to spirals: pn=\" << i << endl;\n\t\t      SetLineEndPoint(pn);\n\t\t    }\n\t\t  if (spworked)\n\t\t    {\t\t\n\t\t      /*      \n\t\t      (*mycout) << \"Warning: Critical Point \" << tt.PNum(k) \n\t\t\t   << \"( chart \" << i << \", trig \" << t\n\t\t\t   << \") has been neutralized!!!\" << endl;\n\t\t      */\n\t\t      cnt++;\n\t\t    }\n\t\t  //\t\t  markedpoints.Elem(tt.PNum(k)) = 1;\n\t\t}\n\t    }\n\t}\n    }\n  PrintMessage(5, \"found \", cnt, \" critical points!\");\n  PrintMessage(5, \"added \", edgecnt, \" edges due to critical points!\");\n\n  PopStatus();\n\n  //search points where inner chart and outer chart and \"no chart\" trig come together at edge-point\n\n  PrintMessage(7,\"search for special chart points\");\n  for (ChartId i = 1; i <= GetNOCharts(); i++)\n    {\n      STLChart& chart = GetChart(i);\n      for (int j = 1; j <= chart.GetNChartT(); j++)\n\t{\n\t  STLTrigId t = chart.GetChartTrig1(j); \n\t  const STLTriangle& tt = GetTriangle(t);\n\n\t  for (int k = 1; k <= 3; k++)\n\t    {\n\t      pn = tt.PNum(k);\n\t      if (GetNEPP(pn) == 2)\n\t\t{\n\t\t  onoc = 0;\n\t\t  notonoc = 0;\n\t\t  for (int n = 1; n <= trigsperpoint.EntrySize(pn); n++)\n\t\t    {\n\t\t      tpp = trigsperpoint.Get(pn,n);\n\t\t      if (tpp != t && GetChartNr(tpp) != i)\n\t\t\t{\n\t\t\t  if (TrigIsInOC(tpp,i)) {onoc = 1;}\n\t\t\t  if (!TrigIsInOC(tpp,i)) {notonoc = 1;}\n\t\t\t}\n\t\t    }\n\t\t  if (onoc && notonoc && !IsLineEndPoint(pn)) \n\t\t    {\n\t\t      GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);\n\t\t      int here = 1; //we start on this side of edge, !here = there\n\t\t      int thereOC = 0;\n\t\t      int thereNotOC = 0;\n\t\t      for (l = 2; l <= trigsaroundp.Size(); l++)\n\t\t\t{\n\t\t\t  GetTriangle(trigsaroundp[l-2]).\n\t\t\t    GetNeighbourPoints(GetTriangle(trigsaroundp[l-1]), ap1, ap2);\n\t\t\t  if (IsEdge(ap1,ap2)) {here = (here+1)%2;}\n\t\t\t  if (!here && TrigIsInOC(trigsaroundp[l-1],i)) {thereOC = 1;}\n\t\t\t  if (!here && !TrigIsInOC(trigsaroundp[l-1],i)) {thereNotOC = 1;}\n\t\t\t}\n\t\t      if (thereOC && thereNotOC)\n\t\t\t{\n\t\t\t  //(*mycout) << \"Special OCICnotC - point \" << pn << \" found!\" << endl;\n\t\t\t  //(*testout) << \"set edgepoint due to spirals: pn=\" << i << endl;\n\t\t\t  SetLineEndPoint(pn);\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n  PrintMessage(5,\"have now \", GetNE(), \" edges with yellow angle = \", stlparam.yangle, \" degree\");\n}\n\n//get trigs at a point, started with starttrig, then every left\nvoid STLGeometry :: GetSortedTrianglesAroundPoint(STLPointId p, STLTrigId starttrig, Array<STLTrigId>& trigs)\n{\n  STLTrigId acttrig = starttrig;\n  trigs.SetAllocSize(trigsperpoint.EntrySize(p));\n  trigs.SetSize(0);\n  trigs.Append(acttrig);\n  int locindex1(0), locindex2(0);\n  //(*mycout) << \"trigs around point \" << p << endl;\n\n  int end = 0;\n  while (!end)\n    {\n      const STLTriangle& at = GetTriangle(acttrig);\n      for (int i = 1; i <= trigsperpoint.EntrySize(p); i++)\n\t{\n\t  STLTrigId t = trigsperpoint.Get(p,i);\n\t  const STLTriangle& nt = GetTriangle(t);\n\t  if (at.IsNeighbourFrom(nt))\n\t    {\n              STLPointId ap1, ap2;\n\t      at.GetNeighbourPoints(nt, ap1, ap2);\n\t      if (ap2 == p) {Swap(ap1,ap2);}\n\t      if (ap1 != p) {PrintSysError(\"In GetSortedTrianglesAroundPoint!!!\");}\n\t      \n\t      for (int j = 1; j <= 3; j++) \n\t\t{\n\t\t  if (at.PNum(j) == ap1) {locindex1 = j;};\n\t\t  if (at.PNum(j) == ap2) {locindex2 = j;};\n\t\t}\n\t      if ((locindex2+1)%3+1 == locindex1) \n\t\t{\n\t\t  if (t != starttrig)\n\t\t    {\n\t\t      trigs.Append(t);\n\t\t      //\t\t      (*mycout) << \"trig \" << t << endl;\n\t\t      acttrig = t;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      end = 1;\n\t\t    }\n\t\t  break;\n\t\t}\n\t    }\n\t}\n    }\n  \n}\n\n/*\nint STLGeometry :: NeighbourTrig(int trig, int nr) const\n{\n  return neighbourtrigs.Get(trig,nr);\n}\n*/\n\n\n\nvoid STLGeometry :: SmoothGeometry ()\n{\n  int i, j, k;\n  \n  double maxerr0, maxerr;\n\n  for (i = 1; i <= GetNP(); i++)\n    {\n      if (GetNEPP(i)) continue;\n      \n      maxerr0 = 0;\n      for (j = 1; j <= NOTrigsPerPoint(i); j++)\n\t{\n\t  int tnum = TrigPerPoint(i, j);\n\t  double err = Angle (GetTriangle(tnum).Normal (), \n\t\t\t      GetTriangle(tnum).GeomNormal(GetPoints()));\n\t  if (err > maxerr0)\n\t    maxerr0 = err;\n\t}\n\n      Point3d pi = GetPoint (i);\n      if (maxerr0 < 1.1) continue;    // about 60 degree\n\n      maxerr0 /= 2;  // should be at least halfen\n      \n      for (k = 1; k <= NOTrigsPerPoint(i); k++)\n\t{\n\t  const STLTriangle & trig = GetTriangle (TrigPerPoint (i, k));\n\t  Point3d c = Center(GetPoint (trig.PNum(1)),\n\t\t\t     GetPoint (trig.PNum(2)),\n\t\t\t     GetPoint (trig.PNum(3)));\n\n\t  Point3d np = pi + 0.1 * (c - pi);\n\t  SetPoint (i, np);\n\t  \n\t  maxerr = 0;\n\t  for (j = 1; j <= NOTrigsPerPoint(i); j++)\n\t    {\n\t      int tnum = TrigPerPoint(i, j);\n\t      double err = Angle (GetTriangle(tnum).Normal (), \n\t\t\t\t  GetTriangle(tnum).GeomNormal(GetPoints()));\n\t      if (err > maxerr)\n\t\tmaxerr = err;\n\t    }\n\t  \n\t  if (maxerr < maxerr0)\n\t    {\n\t      pi = np;\n\t    }\n\t}\n\n      SetPoint (i, pi);\n    }\n}\n\nvoid STLGeometry :: WriteChartToFile( ChartId chartnumber, filesystem::path filename )\n{\n  PrintMessage(1,\"write chart \", int(chartnumber), \" to \", filename);\n  Array<int> trignums;\n\n  if (chartnumber >= 1 && chartnumber <= GetNOCharts())\n  {\n    const STLChart& chart = GetChart(chartnumber);\n\n    for (int j = 1; j <= chart.GetNChartT(); j++)\n      trignums.Append(chart.GetChartTrig1(j));\n\n    for (int j = 1; j <= chart.GetNOuterT(); j++)\n      trignums.Append(chart.GetOuterTrig1(j));\n\n    QuickSort(trignums);\n    STLGeometry geo;\n    NgArray<STLReadTriangle> readtrigs;\n    const auto & first_trig = GetTriangle(chart.GetChartTrig1(1));\n    auto normal = first_trig.Normal();\n    Box<3> box{Box<3>::EMPTY_BOX};\n\n    for(auto j : trignums)\n    {\n      const auto& trig = GetTriangle(j);\n      Point<3> pts[3];\n      for(auto k : Range(3))\n      {\n        pts[k] = GetPoint(trig[k]);\n        box.Add(pts[k]);\n      }\n      // Vec3d normal = Cross( pts[1]-pts[0], pts[2]-pts[0] );\n      readtrigs.Append(STLReadTriangle(pts, trig.Normal()));\n    }\n    auto dist = box.PMax() - box.PMin();\n    auto extra_point = GetPoint(first_trig[0]) - dist.Length()*normal;\n\n    NgArray<int> acttrigs(GetNT());\n    acttrigs = -1;\n    for (int j = 1; j <= chart.GetNT(); j++)\n      acttrigs.Elem(chart.GetTrig1(j)) = chartnumber;\n\n    for (int j = 1; j <= chart.GetNT(); j++)\n    {\n      auto t = chart.GetTrig1(j);\n      const auto & tt = GetTriangle(t);\n      for (int k = 1; k <= 3; k++)\n      {\n        int nt = NeighbourTrig(t,k);\n        if (acttrigs.Get(nt) != chartnumber)\n        {\n          STLPointId np1, np2;\n          tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\n          Point<3> pts[3];\n          pts[0] = GetPoint(np2);\n          pts[1] = GetPoint(np1);\n          pts[2] = extra_point;\n          Vec3d normal = -Cross( pts[2]-pts[0], pts[1]-pts[0] );\n          readtrigs.Append(STLReadTriangle(pts, normal));\n        }\n      }\n    }\n\n    geo.InitSTLGeometry(readtrigs);\n    geo.Save(filename);\n  }\n}\n\n\n\n  class STLGeometryRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const;\n  };\n\n  NetgenGeometry *  STLGeometryRegister :: Load (const filesystem::path & filename) const\n  {\n    string ext = ToLower(filename.extension());\n\n    if (ext == \".stl\")\n      {\n\tPrintMessage (1, \"Load STL geometry file \", filename);\n\n\tifstream infile(filename);\n\n\tSTLGeometry * hgeom = STLGeometry :: Load (infile);\n\thgeom -> edgesfound = 0;\n\treturn hgeom;\n      }\n    else if (ext == \".stlb\")\n      {\n\tPrintMessage (1, \"Load STL binary geometry file \", filename);\n\n\tifstream infile(filename);\n\n\tSTLGeometry * hgeom = STLGeometry :: LoadBinary (infile);\n\thgeom -> edgesfound = 0;\n\treturn hgeom;\n      }\n    else if (ext == \".nao\")\n      {\n\tPrintMessage (1, \"Load naomi (F. Kickinger) geometry file \", filename);\n\n\tifstream infile(filename);\n\n\tSTLGeometry * hgeom = STLGeometry :: LoadNaomi (infile);\n\thgeom -> edgesfound = 0;\n\treturn hgeom;\n      }\n\n    \n    return NULL;\n  }\n\n\n  class STLInit\n  {\n  public:\n    STLInit()\n    {\n      GeometryRegister().Append (new STLGeometryRegister);\n    }\n  };\n\n  STLInit stlinit;\n\nstatic RegisterClassForArchive<STLGeometry, std::tuple<NetgenGeometry, STLTopology>> stlgeo;\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stlgeom.hpp",
    "content": "#ifndef FILE_STLGEOM\n#define FILE_STLGEOM\n\n/**************************************************************************/\n/* File:   stlgeom.hpp                                                    */\n/* Author: Joachim Schoeberl                                              */\n/* Author2: Johannes Gerstmayr                                            */\n/* Date:   26. Jul. 99                                                    */\n/**************************************************************************/\n\n/**\n   STL Geometry\n\n\n   Terminology:\n   \n   Point ... coordinates of STL triangles\n   Triangle  (short Trig)  STL triangle\n   TopEdge .... edge in topology, boundary of STL triangles (many)\n   Edge .... Edges which will occur in the mesh (confirmed edges, less)\n*/\n\n\n#include <meshing.hpp>\n\n#include \"stltopology.hpp\"\n#include \"stltool.hpp\"\n#include \"stlline.hpp\"\n \n\n\nnamespace netgen\n{\n  /*\n  inline int IsInArray(int n, const NgArray<int>& ia)\n  {\n    return ia.Contains(n); \n  }\n\n  inline bool AddIfNotExists(NgArray<int>& list, int x)\n  {\n    if (list.Contains(x)) return false;\n    list.Append(x);\n    return true;\n  }\n  */\n  \n// extern DLL_HEADER MeshingParameters mparam;\n  \n\n\n\n\n\n\n\n\n  class STLEdgeDataList\n  {\n    NgArray<int> storedstatus;\n    STLTopology & geom;\n  public:\n  \n    STLEdgeDataList(STLTopology & ageom);\n    ~STLEdgeDataList();\n\n    void Store ();\n    void Restore ();\n\n    void SetSize(int /* size */) { };\n    void Clear() { };\n    int Size() const { return geom.GetNTE(); }\n    const STLTopEdge & Get(int i) const { return geom.GetTopEdge(i); }\n    STLTopEdge & Elem(int i) { return geom.GetTopEdge(i); }\n\n    int GetNEPP(int pn) const {return geom.NTopEdgesPerPoint(pn); }\n    int GetEdgePP(int pn, int vi) const {return geom.TopEdgePerPoint(pn, vi);};\n\n    //void AddEdgePP(int pn, int vn) { } ;\n\n    void ResetAll();\n    void ChangeStatus(int status1, int status2);\n\n    int GetEdgeNum(int np1, int np2) const\n    { return geom.GetTopEdgeNum (np1, np2); }\n\n    int GetNConfEdges() const;\n\n    void Write(ofstream& of) const;\n    void Read(ifstream& ifs);\n\n    void BuildLineWithEdge(int ep1, int ep2, NgArray<twoint>& line);\n    void BuildClusterWithEdge(int ep1, int ep2, NgArray<twoint>& line);\n\n    int GetNEPPStat(int p, int status) const;\n    int GetNConfCandEPP(int p) const;\n  };\n\n\n\n\n\n\n  class DLL_HEADER STLGeometry : public NetgenGeometry, public STLTopology\n  {\n    // edges to be meshed:\n    NgArray<STLEdge> edges;\n    //edges per point\n    TABLE<int> edgesperpoint;\n\n    // line: a connection of edges\n    NgArray<STLLine*> lines;\n    NgArray<int> lineendpoints; //per geometrypoint, 1 = is endpoint; 0 = no endpoint,\n\n    NgArray<Vec3d> normals; //normals belong to points!\n\n    NgArray<twoint> externaledges;\n\n    int undoexternaledges;\n    NgArray<twoint> storedexternaledges;\n\n    unique_ptr<STLEdgeDataList> edgedata;\n    //  STLEdgeDataList edgedata_store;\n    int calcedgedataanglesnew;\n\n    int edgedatastored;\n\n\n\n    int facecnt; \n    //meshpoint is only set, if an edge is at this point!!!\n\n    NgArray<int> vicinity; //is one, if a triangle belongs to vicinity (eg. of selecttrig)\n    NgArray<int> markedtrigs; //is one, if a triangle belongs to marked triangles (calcdirtystrigs)\n    NgArray<Point3d> markedsegs; //every pointpair is a segment!!!  \n    NgArray<twoint> selectedmultiedge;\n\n\n    //spiralpoints:\n    NgArray<int> spiralpoints;\n    //\n    Array<unique_ptr<STLChart>, ChartId> atlas;\n    //marks all already charted trigs with chartnumber\n    Array<ChartId, STLTrigId> chartmark; \n    //outerchartspertrig, ascending sorted\n    TABLE<int> outerchartspertrig;\n\n\n    //for meshing and project:\n    NgArray<int> meshcharttrigs; //per trig: 1=belong to chart, 0 not\n    mutable int meshchart;\n\n    NgArray<int> ha_points;  // help array, np long, filled with 0 \n\n\n    // sharp geometric edges not declared as edges\n    // (not considered for spiral check)\n    INDEX_2_HASHTABLE<int> * smoothedges;\n\n\n    //transformation:\n    mutable Vec<3> meshtrignv;\n    Vec<3> ex, ey, ez;\n    Point<3> p1;\n\n  public:\n    int edgesfound;\n    int surfacemeshed;\n    int surfaceoptimized;\n    int volumemeshed;\n\n    int trigsconverted; //when STLTriangles exist -> 1\n\n    //for selecting nodes\n    //int selecttrig, nodeofseltrig;\n\n    //only for testing;\n    NgArray<STLLine*> meshlines;\n    NgArray<Point3d> meshpoints;\n\n    double area;\n  public:\n    STLGeometry();\n    virtual ~STLGeometry();\n\n    void DoArchive(Archive& ar) override\n    {\n      STLTopology::DoArchive(ar);\n    }\n\n    void Clear();\n\n    virtual void Save (const filesystem::path & filename) const override;\n\n    bool CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const override;\n    PointGeomInfo ProjectPoint(INDEX surfind, Point<3> & p) const override;\n    bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const override;\n    Vec<3> GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi = nullptr) const override;\n    void PointBetween(const Point<3> & p1, const Point<3> & p2,\n                      double secpoint, int surfi,\n                      const PointGeomInfo & gi1,\n                      const PointGeomInfo & gi2,\n                      Point<3> & newp, PointGeomInfo & newgi) const override;\n\n    void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,\n                          int surfi1, int surfi2,\n                          const EdgePointGeomInfo & ap1,\n                          const EdgePointGeomInfo & ap2,\n                          Point<3> & newp, EdgePointGeomInfo & newgi) const override;\n\n\n\n\tvoid STLInfo(double* data);\n    //stldoctor:\n\tvoid SmoothNormals(const STLParameters& stlparam);\n\tvoid MarkNonSmoothNormals(const STLParameters& stlparam);\n\n\tvoid CalcEdgeData();\n\tvoid CalcEdgeDataAngles();\n\n    const STLEdgeDataList& EdgeDataList() const {return *edgedata;}\n\n\tvoid UndoEdgeChange();\n\tvoid StoreEdgeData();\n\tvoid RestoreEdgeData();\n\n    //void ClearSelectedMultiEdge() {selectedmultiedge.SetSize(0);}\n    //void AddSelectedMultiEdge(twoint ep) {selectedmultiedge.Append(ep);}\n    //int SelectedMultiEdgeSize() {return selectedmultiedge.Size();}\n    const NgArray<twoint>& SelectedMultiEdge() {return selectedmultiedge;}\n    twoint GetNearestSelectedDefinedEdge();\n    void BuildSelectedMultiEdge(twoint ep);\n    void BuildSelectedEdge(twoint ep);\n    void BuildSelectedCluster(twoint ep);\n\n\tvoid ImportEdges();\n\tvoid AddEdges(const NgArray<Point<3> >& eps);\n\tvoid ExportEdges();\n\tvoid LoadEdgeData(const filesystem::path & file);\n\tvoid SaveEdgeData(const filesystem::path & file);\n    //  void SetEdgeAtSelected(int mode);\n  \n\n\tvoid STLDoctorConfirmEdge();\n\tvoid STLDoctorCandidateEdge();\n\tvoid STLDoctorExcludeEdge();\n\tvoid STLDoctorUndefinedEdge();\n\n\tvoid STLDoctorSetAllUndefinedEdges();\n\tvoid STLDoctorEraseCandidateEdges();\n\tvoid STLDoctorConfirmCandidateEdges();\n\tvoid STLDoctorConfirmedToCandidateEdges();\n\n\tvoid STLDoctorDirtyEdgesToCandidates();\n\tvoid STLDoctorLongLinesToCandidates();\n\n\tvoid UndoExternalEdges();\n\tvoid StoreExternalEdges();\n\tvoid RestoreExternalEdges();\n\n\tvoid ImportExternalEdges(const char * filename);  // Flame edges, JS\n    //  void LoadExternalEdges();\n\n\tvoid BuildExternalEdgesFromEdges();\n\tvoid SaveExternalEdges();\n\tvoid AddExternalEdgeAtSelected();\n\tvoid AddClosedLinesToExternalEdges();\n\tvoid AddLongLinesToExternalEdges();\n\tvoid AddAllNotSingleLinesToExternalEdges();\n\tvoid STLDoctorBuildEdges(const STLParameters& stlparam);\n\tvoid AddExternalEdgesFromGeomLine();\n\tvoid DeleteDirtyExternalEdges();\n\tvoid DeleteExternalEdgeAtSelected();\n\tvoid DeleteExternalEdgeInVicinity();\n    void AddExternalEdge(int p1, int p2);\n    void DeleteExternalEdge(int p1, int p2);\n    int IsExternalEdge(int p1, int p2);\n    int NOExternalEdges() const {return externaledges.Size();}\n    twoint GetExternalEdge(int i) const {return externaledges.Get(i);}\n\n\tvoid DestroyDirtyTrigs();\n\tvoid CalcNormalsFromGeometry();\n\tvoid MoveSelectedPointToMiddle();\n\tvoid NeighbourAnglesOfSelectedTrig();\n\tvoid PrintSelectInfo();\n\tvoid ShowSelectedTrigChartnum();\n\tvoid ShowSelectedTrigCoords();\n\tvoid SmoothGeometry ();\n\n\n\tvoid LoadMarkedTrigs();\n\tvoid SaveMarkedTrigs();\n\tvoid ClearMarkedSegs() {markedsegs.SetSize(0);}\n    void AddMarkedSeg(const Point<3> & ap1, const Point<3> & ap2) \n    {\n      markedsegs.Append(ap1);markedsegs.Append(ap2);\n    }\n\n    void GetMarkedSeg(int i, Point<3> & ap1, Point<3> & ap2) \n    {\n      ap1=markedsegs.Get(i*2-1); \n      ap2=markedsegs.Get(i*2);\n    }\n    int GetNMarkedSegs() {return markedsegs.Size()/2;}\n\tvoid CalcVicinity(int starttrig);\n\tvoid GetVicinity(int starttrig, int size, NgArray<int>& vic);\n\n\tint Vicinity(int trig) const;\n\n\tvoid InitMarkedTrigs();\n\tvoid MarkDirtyTrigs(const STLParameters& stlparam);\n\tvoid SmoothDirtyTrigs(const STLParameters& stlparam);\n\tvoid GeomSmoothRevertedTrigs(const STLParameters& stlparam);\n\tvoid MarkRevertedTrigs(const STLParameters& stlparam);\n\tdouble CalcTrigBadness(int i);\n\tint IsMarkedTrig(int trig) const;\n\tvoid SetMarkedTrig(int trig, int num);\n\tvoid MarkTopErrorTrigs ();\n\n    //Selected triangle\n\tvoid SetSelectTrig(int trig);\n\tint GetSelectTrig() const;\n\tvoid SetNodeOfSelTrig(int n);\n\tint GetNodeOfSelTrig() const;\n\n\n    int AddNormal(const Vec3d& n) { normals.Append(n); return normals.Size(); }\n    const Vec3d & GetNormal(int nr) const {return normals.Get(nr);}\n    void SetNormal(int nr, const Vec3d& n) {normals.Elem(nr) = n;}\n\n    int AddEdge(const STLEdge& v) { edges.Append(v); return edges.Size(); }\n    int AddEdge(int p1, int p2);\n\n    STLEdge GetEdge(int nr) {return edges.Get(nr);}\n    int GetNE() {return edges.Size();}\n\n    double Area();\n\n    double GetAngle(int t1, int t2);\n    double GetGeomAngle(int t1, int t2);\n    //if triangles t1 and t2 touch, return 1 and in p1, p2 the touching points\n    //int TrigsTouch(int t1, int t2, int& p1, int& p2);\n\n\n  \n    ///\n\n    ///ReadTriangle->STLTriangle, initialise some important variables, always after load!!!\n    virtual void InitSTLGeometry (const NgArray<STLReadTriangle> & readtrigs) override;\n    virtual void TopologyChanged() override; //do some things, if topology changed!\n    int CheckGeometryOverlapping();\n\n    //get NO edges per point\n    int GetEPPSize() const {return edgesperpoint.Size();};\n    int GetNEPP(int pn) \n    {\n      if (edgesperpoint.Size() == 0) {BuildEdgesPerPoint();}\n      return edgesperpoint.EntrySize(pn);\n    };\n    int GetEdgePP(int pn, int vi)\n    {\n      if (edgesperpoint.Size() == 0) {BuildEdgesPerPoint();}\n      return edgesperpoint.Get(pn,vi);\n    };\n    void AddEdgePP(int pn, int vn) {edgesperpoint.Add1(pn,vn);};\n    //von 2 punkten ermitteln, ob sie eine Kante sind\n    int IsEdge(int p1, int p2);\n    int IsEdgeNum(int p1, int p2);\n\n    ///Build EdgeSegments\n    void ClearEdges();\n    void BuildEdges(const STLParameters& stlparam);\n    void BuildEdgesPerPoint();\n    void UseExternalEdges();\n\n\n    void FindEdgesFromAngles(const STLParameters& stlparam);\n    void CalcFaceNums();\n    int GetNOBodys();\n    int GetNOFaces() {return facecnt;}\n    void LinkEdges(const STLParameters& stlparam);\n\n    void AddConeAndSpiralEdges(const STLParameters& stlparam);\n    void AddFaceEdges(); //each face should have at least one starting edge (outherwise it won't be meshed)\n\n    void GetDirtyChartTrigs(int chartnum, STLChart& chart, const Array<ChartId, STLTrigId>& outercharttrigs, \n\t\t\t    NgArray<ChartId>& chartpointchecked, NgArray<int>& dirtytrigs);\n\n    void ClearSpiralPoints();\n    void SetSpiralPoint(int pn) {spiralpoints.Elem(pn) = 1;};\n    int GetSpiralPoint(int pn) const {return spiralpoints.Get(pn);};\n\n    void GetSortedTrianglesAroundPoint(STLPointId p, STLTrigId starttrig, Array<STLTrigId>& trigs);\n\n    // smooth edges: sharp geometric edges not declared as edges\n    void BuildSmoothEdges ();\n    bool IsSmoothEdge (int pi1, int pi2) const;\n\n\n    //make charts with regions of a max. angle\n    void MakeAtlas(class Mesh & mesh, const MeshingParameters& mparam, const STLParameters& stlparam);\n\n    //outerchartspertrig, sorted!\n    int GetOCPTSize() const {return outerchartspertrig.Size();};\n    int GetNOCPT(int tn) const {return outerchartspertrig.EntrySize(tn);};\n    int GetOCPT(int tn, int vi) const {return outerchartspertrig.Get(tn,vi);};\n    void SetOCPT(int tn, int vi, int ocn) {outerchartspertrig.Set(tn,vi,ocn);};\n    void AddOCPT(int tn, int ocn) {outerchartspertrig.Add1(tn, ocn);};\n    int TrigIsInOC(int tn, int ocn) const;\n \n    //get chart number of a trig or 0 if unmarked\n    ChartId GetChartNr(STLTrigId i) const;\n    ChartId GetMarker(STLTrigId i) const  { return chartmark[i]; }\n    void SetMarker(STLTrigId nr, ChartId m);\n    size_t GetNOCharts() const { return atlas.Size(); }\n    //get a chart from atlas\n    const STLChart& GetChart(ChartId nr) const { return *atlas[nr];};\n    STLChart & GetChart(ChartId nr) { return *atlas[nr];};\n    int AtlasMade() const;\n  \n    void GetInnerChartLimes(NgArray<twoint>& limes, ChartId chartnum);\n\n    //FOR MESHING\n    int GetMeshChartNr () { return meshchart; }\n    void GetMeshChartBoundary (NgArray<Point<2>> & points,\n\t\t\t       NgArray<Point<3>> & points3d,\n\t\t\t       NgArray<INDEX_2> & lines, double h);\n\n\n    Point<3> PointBetween(const Point<3> & p1, int t1, const Point<3> & p2, int t2);\n\n    //select triangles in meshcharttrigs of actual (defined by trig) whole chart\n    void PrepareSurfaceMeshing();\n    //\n    void DefineTangentialPlane(const Point<3> & ap1, const Point<3> & ap2, int trig);\n    //\n    void SelectChartOfTriangle (int trignum) const;\n    //\n    void SelectChartOfPoint (const Point<3> & p);\n    //\n    const Vec<3> & GetChartNormalVector () const { return meshtrignv; }\n\n    // list of trigs\n    void ToPlane (const Point<3> & locpoint, int * trigs, Point<2> & plainpoint, \n\t\t  double h, int& zone, int checkchart);\n    //return 0, wenn alles OK, 1 sonst\n    int FromPlane (const Point<2> & plainpoint, Point<3> & locpoint, double h);\n  \n    //get nearest point in actual chart and return any triangle where it lies on\n    int ProjectNearest(Point<3> & p3d) const;\n    //project point with normal nv from last define tangential plane\n\n    int LastTrig() const;\n    int Project(Point<3> & p3d) const;\n    int ProjectOnWholeSurface (Point<3> & p3d) const;\n\n    int GetNLines() const {return lines.Size();}\n    int AddLine(STLLine* line) { lines.Append(line); return lines.Size(); }\n    STLLine* GetLine(int nr) const {return lines.Get(nr);}\n    int GetLineP(int lnr, int pnr) const {return lines.Get(lnr)->PNum(pnr);}\n    int GetLineNP(int nr) const {return lines.Get(nr)->NP();}\n\n    void SetLineEndPoint(int pn);\n    int IsLineEndPoint(int pn);\n    int LineEndPointsSet() const {return lineendpoints.Size() == GetNP();}\n    void ClearLineEndPoints();\n\n    void RestrictLocalH(class Mesh & mesh, double gh, const STLParameters& stlparam, const MeshingParameters& mparam);\n    void RestrictLocalHCurv(class Mesh & mesh, double gh, const STLParameters& stlparam);\n    void RestrictHChartDistOneChart(ChartId chartnum, NgArray<int>& acttrigs, class Mesh & mesh, \n\t\t\t\t    double gh, double fact, double minh, const STLParameters& stlparam);\n\n    friend class MeshingSTLSurface;\n\n    int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam) override;\n    \n    // Add additional Point to chart to close the surface and write the resulting stl to a file\n    void WriteChartToFile( ChartId chartnumber, filesystem::path filename=\"chart.slb\" );\n  };\n \n\n#include \"meshstlsurface.hpp\"\n\n\n\nextern int STLMeshingDummy (STLGeometry* stlgeometry, shared_ptr<Mesh> & mesh, const MeshingParameters & mparam,\n                            const STLParameters& stlpar);\n\n\n}\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/stlgeomchart.cpp",
    "content": "//20.11.1999 third part of stlgeom.cc, functions with chart and atlas\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n#include \"stlgeom.hpp\"\n\nnamespace netgen\n{\n\nint chartdebug = 0;\n\n\n\nvoid STLGeometry :: MakeAtlas(Mesh & mesh, const MeshingParameters& mparam, const STLParameters& stlparam)\n{\n  static Timer t(\"makeatlas\"); RegionTimer reg(t);\n  static Timer tinner(\"find innner chart\");\n  static Timer touter(\"find outer chart\");\n  // int timer1 = NgProfiler::CreateTimer (\"makeatlas\");\n  /*\n  int timerb = NgProfiler::CreateTimer (\"makeatlas - begin\");\n  int timere = NgProfiler::CreateTimer (\"makeatlas - end\");  \n  int timere1 = NgProfiler::CreateTimer (\"makeatlas - end1\");  \n  int timere2 = NgProfiler::CreateTimer (\"makeatlas - end2\");  \n  int timer2 = NgProfiler::CreateTimer (\"makeatlas - part 2\");\n  int timer3 = NgProfiler::CreateTimer (\"makeatlas - part 3\");\n  int timer4 = NgProfiler::CreateTimer (\"makeatlas - part 4\");\n  int timer4a = NgProfiler::CreateTimer (\"makeatlas - part 4a\");\n  int timer4b = NgProfiler::CreateTimer (\"makeatlas - part 4b\");\n  int timer4c = NgProfiler::CreateTimer (\"makeatlas - part 4c\");\n  int timer4d = NgProfiler::CreateTimer (\"makeatlas - part 4d\");\n  int timer4e = NgProfiler::CreateTimer (\"makeatlas - part 4e\");\n  int timer5 = NgProfiler::CreateTimer (\"makeatlas - part 5\");\n  int timer5a = NgProfiler::CreateTimer (\"makeatlas - part 5a\");\n  int timer5b = NgProfiler::CreateTimer (\"makeatlas - part 5b\");\n  int timer5cs = NgProfiler::CreateTimer (\"makeatlas - part 5cs\");\n  int timer5cl = NgProfiler::CreateTimer (\"makeatlas - part 5cl\");\n  */\n  PushStatusF(\"Make Atlas\");\n\n  double h = mparam.maxh;\n   \n  double atlasminh = 5e-3 * Dist (boundingbox.PMin(), boundingbox.PMax());\n  PrintMessage(5, \"atlasminh = \", atlasminh);\n\n  //speedup for make atlas\n  if (GetNT() > 50000)\n    mesh.SetGlobalH(min2 (0.05*Dist (boundingbox.PMin(), boundingbox.PMax()),\n\t\t\t  mparam.maxh));\n\n  atlas.SetSize(0);\n  ClearSpiralPoints();\n  BuildSmoothEdges();\n  \n  // NgProfiler::StartTimer (timer1);\n\n  double chartangle = stlparam.chartangle;\n  double outerchartangle = stlparam.outerchartangle;\n\n  chartangle = chartangle/180.*M_PI;\n  outerchartangle = outerchartangle/180.*M_PI;\n\n  double coschartangle = cos(chartangle);\n  double cosouterchartangle = cos(outerchartangle);\n  double cosouterchartanglehalf = cos(0.5*outerchartangle);\n  double sinchartangle = sin(chartangle);\n  double sinouterchartangle = sin(outerchartangle);\n\n  Array<ChartId,STLTrigId> outermark(GetNT());     //marks all trigs form actual outer region\n  Array<ChartId,STLTrigId> outertested(GetNT());   //marks tested trigs for outer region\n  Array<ChartId,STLPointId> pointstochart(GetNP()); //point in chart becomes chartnum\n  Array<ChartId,STLPointId> innerpointstochart(GetNP()); //point in chart becomes chartnum\n  Array<STLPointId> chartpoints;             //point in chart becomes chartnum\n  Array<STLPointId> innerchartpoints;\n  Array<Point<3>> innerchartpts;\n  NgArray<int> dirtycharttrigs;\n\n  NgArray<int> chartdistacttrigs (GetNT());   //outercharttrigs\n  chartdistacttrigs = 0;\n\n\n  STLBoundary chartbound(this); //knows the actual chart boundary\n  //int chartboundarydivisions = 10;\n  markedsegs.SetSize(0); //for testing!!!\n\n  NgArray<ChartId> chartpointchecked(GetNP()); //for dirty-chart-trigs\n\n  chartmark.SetSize(GetNT());\n\n  innerpointstochart = ChartId::INVALID;\n  pointstochart = ChartId::INVALID;\n  chartpointchecked = ChartId::INVALID;\n\n  double eps = 1e-12 * Dist (boundingbox.PMin(), boundingbox.PMax());\n\n  int spiralcheckon = stldoctor.spiralcheck;\n  if (!spiralcheckon) {PrintWarning(\"++++++++++++\\nspiral deactivated by user!!!!\\n+++++++++++++++\"); }\n\n  chartmark = ChartId::INVALID;\n  outermark = ChartId::INVALID;\n  outertested = ChartId::INVALID;\n\n  double atlasarea = Area();\n  double workedarea = 0;\n  double showinc = 100.*5000./(double)GetNT();\n  double nextshow = 0;\n  STLTrigId lastunmarked = 1;\n\n  PrintMessage(5,\"one dot per 5000 triangles: \");\n\n  size_t markedtrigcnt = 0;\n  while (markedtrigcnt < GetNT())\n    {\n      if (multithread.terminate) { PopStatus(); return; }\n\n      // NgProfiler::StartTimer (timerb);      \n      if (workedarea / atlasarea*100. >= nextshow) \n      \t{PrintDot(); nextshow+=showinc;}\n\n      SetThreadPercent(100.0 * workedarea / atlasarea);\n\n      atlas.Append (make_unique<STLChart> (this, stlparam));\n      STLChart & chart = *atlas.Last();\n      \n      //find unmarked trig\n      STLTrigId prelastunmarked = lastunmarked;\n\n      bool found = false;\n      for (STLTrigId j = lastunmarked; j <= GetNT(); j++)\n\tif (!GetMarker(j))\n\t  {\n\t    found = true;\n\t    lastunmarked = j;\n\t    break;\n\t  }\n\n      chartpoints.SetSize(0);  \n      innerchartpoints.SetSize(0);\n      innerchartpts.SetSize(0);\n      chartbound.Clear();\n      chartbound.SetChart(&chart);\n      \n      if (!found) throw Exception(\"Make Atlas, no starttrig found\"); \n\n      //find surrounding trigs\n      // int starttrig = j;\n      STLTrigId starttrig = lastunmarked;\n\n      Point<3> startp = GetPoint(GetTriangle(starttrig)[0]);\n\n      bool accepted;\n      ChartId chartnum = GetNOCharts();\n\t  \n      Vec<3> sn = GetTriangle(starttrig).Normal();\n      chart.SetNormal (startp, sn);\n      \n      // *testout << \"first trig \" << starttrig << \", n = \" << sn << endl;\n\n      SetMarker(starttrig, chartnum);\n      markedtrigcnt++;\n      chart.AddChartTrig(starttrig);\n      chartbound.AddTriangle(GetTriangle(starttrig));\n\n      workedarea += GetTriangle(starttrig).Area(points);\n\n      for (int i = 0; i < 3; i++)\n\t{\n          STLPointId pi = GetTriangle(starttrig)[i];\n\t  innerpointstochart[pi] = chartnum;\n\t  pointstochart[pi] = chartnum;\n\t  chartpoints.Append(pi);\n\t  innerchartpoints.Append(pi);\n\t}\n\n      bool changed = true;\n      int oldstartic = 1;\n      int oldstartic2;\n      // NgProfiler::StopTimer (timerb);      \n      // NgProfiler::StartTimer (timer2);\n\n      tinner.Start();\n      while (changed)\n\t{   \n\t  changed = false;\n\t  oldstartic2 = oldstartic;\n\t  oldstartic = chart.GetNT();\n\t  //\t      for (ic = oldstartic2; ic <= chart->GetNT(); ic++)\n\t  for (int ic = oldstartic2; ic <= oldstartic; ic++)\n\t    {\n\t      STLTrigId i = chart.GetTrig1(ic);\n\t      if (GetMarker(i) == chartnum)\n\t\t{\n\t\t  for (int j = 1; j <= NONeighbourTrigs(i); j++)\n\t\t    {\n\t\t      STLTrigId nt = NeighbourTrig(i,j);\n                      // *testout << \"check trig \" << nt << endl;\n\t\t      STLPointId np1, np2;\n\t\t      GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t\t      if (GetMarker(nt) == 0 && !IsEdge(np1,np2))\n\t\t\t{\n\t\t\t  Vec<3> n2 = GetTriangle(nt).Normal();\n                          // *testout << \"acos = \" << 180/M_PI*acos (n2*sn) << endl;\n\t\t\t  if ( (n2 * sn) >= coschartangle )\n\t\t\t    {\n                              // *testout << \"good angle \" << endl;\n\t\t\t      accepted = true;\n\t\t\t      /*\n\t\t\t\t//alter spiralentest, schnell, aber ungenau\n\t\t\t      for (k = 1; k <= 3; k++)\n\t\t\t\t{\n\t\t\t\t  //find overlapping charts:\n\t\t\t\t  Point3d pt = GetPoint(GetTriangle(nt).PNum(k));\n\t\t\t\t  if (innerpointstochart.Get(GetTriangle(nt).PNum(k)) != chartnum)\n\t\t\t\t    {\n\t\t\t\t      for (l = 1; l <= chartpoints.Size(); l++)\n\t\t\t\t\t{\n\t\t\t\t\t  Vec3d vptpl(GetPoint(chartpoints.Get(l)), pt);\n\t\t\t\t\t  double vlen = vptpl.Length();\n\t\t\t\t\t  if (vlen > 0)\n\t\t\t\t\t    {\n\t\t\t\t\t      vptpl /= vlen;\n\t\t\t\t\t      if ( fabs( vptpl * sn) > sinchartangle )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t  accepted = 0;\n\t\t\t\t\t\t  break;\n\t\t\t\t\t\t}\n\t\t\t\t\t    } \n\t\t\t\t\t}\n\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t      */\n\t\t\t      \n\t\t\t      //find overlapping charts exacter (fast, too): \n\t\t\t      for (int k = 1; k <= NONeighbourTrigs(nt); k++)\n\t\t\t\t{ \n\t\t\t\t  int nnt = NeighbourTrig(nt,k);\n\t\t\t\t  if (GetMarker(nnt) != chartnum)\n\t\t\t\t    {\n\t\t\t\t      STLPointId nnp1, nnp2; \n\t\t\t\t      GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2);\n\n\t\t\t\t      accepted = chartbound.TestSeg(GetPoint(nnp1),\n\t\t\t\t\t\t\t\t    GetPoint(nnp2),\n\t\t\t\t\t\t\t\t    sn,sinchartangle,1 /*chartboundarydivisions*/ ,points, eps);\n                                      \n                                      // if (!accepted) *testout << \"not acc due to testseg\" << endl;\n\n\t\t\t\t      Vec<3> n3 = GetTriangle(nnt).Normal();\n\t\t\t\t      if ( (n3 * sn) >= coschartangle  &&\n\t\t\t\t\t   IsSmoothEdge (nnp1, nnp2) )\n\t\t\t\t\taccepted = true;\n\t\t\t\t    }\n\t\t\t\t  if (!accepted) \n                                    break;\n\t\t\t\t}\n\n                              /*\n                              // new check 2019-09-22 \n                              if (accepted)\n                              {\n                                auto & trig = GetTriangle(nt);\n                                Point<3> p0 = GetPoint(trig[0]);\n                                Point<3> p1 = GetPoint(trig[1]);\n                                Point<3> p2 = GetPoint(trig[2]);\n                                Point<3> p01 = Center(p0,p1);\n                                Point<3> p02 = Center(p0,p2);\n                                Point<3> p12 = Center(p1,p2);\n                                Point<3> p012 = Center(p0,p1,p2);\n                                p01 += 1e-5 * (p012-p01);\n                                p02 += 1e-5 * (p012-p02);\n                                p12 += 1e-5 * (p012-p12);\n                                bool test1 = chartbound.TestSegChartNV(p01,p012,sn);\n                                bool test2 = chartbound.TestSegChartNV(p02,p012,sn);\n                                bool test3 = chartbound.TestSegChartNV(p12,p012,sn);\n                                if (!test1 || !test2 || !test3)\n                                  {\n                                    cout << \"more stringent\" << endl;\n                                    accepted = false;\n                                  }\n                              }\n                              */\n\n                              \n\t\t\t      if (accepted)\n\t\t\t\t{\n                                  // *testout << \"trig accepted\" << endl;\n\t\t\t\t  SetMarker(nt, chartnum); \n\t\t\t\t  changed = true;\n\t\t\t\t  markedtrigcnt++;\n\t\t\t\t  workedarea += GetTriangle(nt).Area(points);\n\t\t\t\t  chart.AddChartTrig(nt);\n\n\t\t\t\t  chartbound.AddTriangle(GetTriangle(nt));\n\n\t\t\t\t  for (int k = 1; k <= 3; k++)\n\t\t\t\t    {\n                                      STLPointId pi = GetTriangle(nt).PNum(k);\n\t\t\t\t      if (innerpointstochart[pi] != chartnum) \n\t\t\t\t\t{\n\t\t\t\t\t  innerpointstochart[pi] = chartnum;\n\t\t\t\t\t  pointstochart[pi] = chartnum;\n\t\t\t\t\t  chartpoints.Append(pi);\n\t\t\t\t\t  innerchartpoints.Append(pi);\n\t\t\t\t\t}\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\t       \n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n      tinner.Stop();\n      \n      innerchartpts.SetSize(innerchartpoints.Size());\n      for (size_t i = 0; i < innerchartpoints.Size(); i++)\n        innerchartpts[i] = GetPoint(innerchartpoints[i]);\n      \n      // NgProfiler::StopTimer (timer2);\n      // NgProfiler::StartTimer (timer3);\n      \n      //find outertrigs\n\n      //      chartbound.Clear(); \n      // warum, ic-bound auf edge macht Probleme js ???\n      \n      touter.Start();\n      outermark[starttrig] = chartnum;\n      //chart->AddOuterTrig(starttrig);\n      changed = true;\n      oldstartic = 1;\n      while (changed)\n\t{   \n\t  changed = false;\n\t  oldstartic2 = oldstartic;\n\t  oldstartic = chart.GetNT();\n\n\t  for (int ic = oldstartic2; ic <= oldstartic; ic++)\n\t    {\n\t      STLTrigId i = chart.GetTrig1(ic);\n\t      if (outermark[i] != chartnum) continue;\n\t      \n\t      for (int j = 1; j <= NONeighbourTrigs(i); j++)\n\t\t{\n\t\t  STLTrigId nt = NeighbourTrig(i,j);\n\t\t  if (outermark[nt] == chartnum) continue;\n\t\t  \n\t\t  const STLTriangle & ntrig = GetTriangle(nt);\n\t\t  STLPointId np1, np2;\n\t\t  GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t\t  \n\t\t  if (IsEdge (np1, np2)) continue;\n\t\t  \n\t\t  \n\t\t  /*\n\t\t    if (outertested.Get(nt) == chartnum)\n\t\t    continue;\n\t\t  */\n\t\t  outertested[nt] = chartnum;\n\t\t  \n\t\t  Vec<3> n2 = GetTriangle(nt).Normal();\n\n\t\t  //abfragen, ob noch im tolerierten Winkel\n\t\t  if ( (n2 * sn) >= cosouterchartangle )\n\t\t    {\n\t\t      accepted = true;\n\t\t      \n                      // NgProfiler::StartTimer (timer4);\n\t\t      bool isdirtytrig = false;\n\t\t      Vec<3> gn = GetTriangle(nt).GeomNormal(points);\n\t\t      double gnlen = gn.Length();\n\t\t      \n\t\t      if (n2 * gn <= cosouterchartanglehalf * gnlen)\n\t\t\tisdirtytrig = true;\n\t\t      \n\t\t      //zurueckweisen, falls eine Spiralartige outerchart entsteht\n\t\t      \n\t\t      //find overlapping charts exacter: \n\t\t      //do not check dirty trigs!\n                      // NgProfiler::StartTimer (timer4a);\n                      \n\t\t      if (spiralcheckon && !isdirtytrig)\n\t\t\tfor (int k = 1; k <= NONeighbourTrigs(nt); k++)\n\t\t\t  {\n                            // NgProfiler::StartTimer (timer4b);                            \n\t\t\t    STLTrigId nnt = NeighbourTrig(nt,k);\n\t\t\t    \n\t\t\t    if (outermark[nnt] != chartnum)\n\t\t\t      {\n                                // NgProfiler::StartTimer (timer4c);\n\t\t\t\tSTLPointId nnp1, nnp2; \n\t\t\t\tGetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2);\n                                // NgProfiler::StopTimer (timer4c);\n\t\t\t\t\n                                // NgProfiler::StartTimer (timer4d);\n\n\t\t\t\taccepted = \n\t\t\t\t  chartbound.TestSeg(GetPoint(nnp1),GetPoint(nnp2),\n\t\t\t\t\t\t     sn,sinouterchartangle, 0 /*chartboundarydivisions*/ ,points, eps);\n\t\t\t\t\n                                // NgProfiler::StopTimer (timer4d);\t\t\t\t\n\n                                // NgProfiler::StartTimer (timer4e);\n\n\t\t\t\tVec<3> n3 = GetTriangle(nnt).Normal();\n\t\t\t\tif ( (n3 * sn) >= cosouterchartangle  &&\n\t\t\t\t     IsSmoothEdge (nnp1, nnp2) )\n\t\t\t\t  accepted = true;\n                                // NgProfiler::StopTimer (timer4e);                                \n\t\t\t      }\n                            // NgProfiler::StopTimer (timer4b);                            \n\t\t\t    if (!accepted) break;\n\t\t\t  }\n                      // NgProfiler::StopTimer (timer4a);\n\t\t      \n                      //  NgProfiler::StopTimer (timer4);\t\t      \n\n                      // NgProfiler::RegionTimer reg5(timer5);\t\t      \n\n                      \n\t\t      // outer chart is only small environment of\n\t\t      //    inner chart:\n\t\t      \n\t\t      if (accepted)\n\t\t\t{\n                          // NgProfiler::StartTimer (timer5a);\n\t\t\t  accepted = false;\n\t\t\t  \n\t\t\t  for (int k = 1; k <= 3; k++)\n\t\t\t    if (innerpointstochart[ntrig.PNum(k)] == chartnum)\n\t\t\t      {\n\t\t\t\taccepted = true; \n\t\t\t\tbreak;\n\t\t\t      }\n\n                          // NgProfiler::StopTimer (timer5a);\n                          // int timer5csl = (innerchartpts.Size() < 100) ? timer5cs : timer5cl;\n                          // NgProfiler::StartTimer (timer5csl);\n\t\t\t  \n\t\t\t  if (!accepted)\n\t\t\t    for (int k = 1; k <= 3; k++)\n\t\t\t      {\n\t\t\t\tPoint<3> pt = GetPoint(ntrig.PNum(k));\t\t\t\t\t  \n\t\t\t\tdouble h2 = sqr(mesh.GetH(pt));\n                                /*\n                                for (int l = 1; l <= innerchartpoints.Size(); l++)\n\t\t\t\t  {\n\t\t\t\t    double tdist = Dist2(pt, GetPoint (innerchartpoints.Get(l)));\n\t\t\t\t    if (tdist < 4 * h2)\n\t\t\t\t      {\n\t\t\t\t\taccepted = 1; \n\t\t\t\t\tbreak;\n\t\t\t\t      }\n\t\t\t\t  }\n                                */\n                                for (int l = 0; l < innerchartpts.Size(); l++)\n\t\t\t\t  {\n\t\t\t\t    double tdist = Dist2(pt, innerchartpts[l]);\n\t\t\t\t    if (tdist < 4 * h2)\n\t\t\t\t      {\n\t\t\t\t\taccepted = true; \n\t\t\t\t\tbreak;\n\t\t\t\t      }\n\t\t\t\t  }\n\t\t\t\tif (accepted) break;\n\t\t\t      }\n                          \n                          // NgProfiler::StopTimer (timer5csl);\n\t\t\t}\n                      // NgProfiler::StartTimer (timer5b);\n\t\t      \n\t\t      if (accepted)\n\t\t\t{\n\t\t\t  changed = true;\n\t\t\t  outermark[nt] = chartnum;\n\t\t\t  \n\t\t\t  if (GetMarker(nt) != chartnum)\n\t\t\t    {\n\t\t\t      chartbound.AddTriangle(GetTriangle(nt));\n\t\t\t      chart.AddOuterTrig(nt);\n\t\t\t      for (int k = 1; k <= 3; k++)\n\t\t\t\t{\n\t\t\t\t  if (pointstochart[GetTriangle(nt).PNum(k)]\n\t\t\t\t      != chartnum) \n\t\t\t\t    {\n\t\t\t\t      pointstochart[GetTriangle(nt).PNum(k)] = chartnum;\n\t\t\t\t      chartpoints.Append(GetTriangle(nt).PNum(k));\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    }\n\t\t\t}\n                      // NgProfiler::StopTimer (timer5b);\n\t\t    }\t       \n\t\t}\n\t    }\n\t}            \n      touter.Stop();\n      // NgProfiler::StopTimer (timer3);\n      // NgProfiler::StartTimer (timere);      \n      // NgProfiler::StartTimer (timere1);      \n      //end of while loop for outer chart\n      GetDirtyChartTrigs(chartnum, chart, outermark, chartpointchecked, dirtycharttrigs);\n      //dirtycharttrigs are local (chart) point numbers!!!!!!!!!!!!!!!!\n\n      if (dirtycharttrigs.Size() != 0 && \n\t  (dirtycharttrigs.Size() != chart.GetNChartT() || dirtycharttrigs.Size() != 1))\n\t{\n\t  if (dirtycharttrigs.Size() == chart.GetNChartT() && dirtycharttrigs.Size() != 1)\n\t    {\n\t      //if all trigs would be eliminated -> leave 1 trig!\n\t      dirtycharttrigs.SetSize(dirtycharttrigs.Size() - 1);\n\t    }\n\t  for (int k = 1; k <= dirtycharttrigs.Size(); k++)\n\t    {\n\t      STLTrigId tn = chart.GetChartTrig1(dirtycharttrigs.Get(k));\n\t      outermark[tn] = 0; //not necessary, for later use\n\t      SetMarker(tn, 0); \n\t      markedtrigcnt--;\n\t      workedarea -= GetTriangle(tn).Area(points);\n\t    }\n\t  chart.MoveToOuterChart(dirtycharttrigs);\n\t  lastunmarked = 1;\n\t  lastunmarked = prelastunmarked;\n\t}\n\n      chartbound.DeleteSearchTree();\n\n      // NgProfiler::StopTimer (timere1);      \n      // NgProfiler::StartTimer (timere2);      \n\n      \n      // cout << \"key\" << endl;\n      // char key;\n      // cin >> key;\n      //calculate an estimate meshsize, not to produce too large outercharts, with factor 2 larger!\n      RestrictHChartDistOneChart(chartnum, chartdistacttrigs, mesh, h, 0.5, atlasminh, stlparam);\n      // NgProfiler::Print(stdout);\n      // NgProfiler::StopTimer (timere2);      \n      \n      // NgProfiler::StopTimer (timere);      \n      \n    }\n  \n  // NgProfiler::StopTimer (timer1);\n  // NgProfiler::Print(stdout);\n\n\n  PrintMessage(5,\"\");\n  PrintMessage(5,\"NO charts=\", atlas.Size());\n\n  int cnttrias = 0;\n  outerchartspertrig.SetSize(GetNT());\n  // for (int i = 1; i <= atlas.Size(); i++)\n  for (ChartId i : atlas.Range())\n    {\n      for (int j = 1; j <= GetChart(i).GetNT(); j++)\n\t{\n\t  STLTrigId tn = GetChart(i).GetTrig1(j);\n\t  AddOCPT(tn,i);\n\t}\n      \n      cnttrias += GetChart(i).GetNT();\n    }\n  PrintMessage(5, \"NO outer chart trias=\", cnttrias);\n\n  //sort outerchartspertrig\n  for (int i = 1; i <= GetNT(); i++)\n    {\n      for (int k = 1; k < GetNOCPT(i); k++)\n\tfor (int j = 1; j < GetNOCPT(i); j++)\n\t  {\n\t    int swap = GetOCPT(i,j);\n\t    if (GetOCPT(i,j+1) < swap)\n\t      {\n\t\tSetOCPT(i,j,GetOCPT(i,j+1));\n\t\tSetOCPT(i,j+1,swap);\n\t      }\n\t  }\n      \n      // check make atlas\n      if (GetChartNr(i) <= 0 || GetChartNr(i) > GetNOCharts()) \n\tPrintSysError(\"Make Atlas: chartnr(\", i, \")=0!!\");\n    }\n\n  mesh.SetGlobalH(mparam.maxh);\n  mesh.SetMinimalH(mparam.minh);\n  \n  \n  AddConeAndSpiralEdges(stlparam);\n  \n  PrintMessage(5,\"Make Atlas finished\");\n\n  \n  for (auto & chart : atlas)\n    chart->BuildInnerSearchTree();\n\n  PopStatus();\n}\n\n\nint STLGeometry::TrigIsInOC(int tn, int ocn) const\n{\n  if (tn < 1 || tn > GetNT())\n    {\n      // assert (1);\n      abort ();\n      PrintSysError(\"STLGeometry::TrigIsInOC illegal tn: \", tn);\n      \n      return 0;\n    }\n\n  /*\n  int firstval = 0;\n  int i;\n  for (i = 1; i <= GetNOCPT(tn); i++)\n    {\n      if (GetOCPT(tn, i) == ocn) {firstval = 1;}\n    }\n  */\n\n  int found = 0;\n\n  int inc = 1;\n  while (inc <= GetNOCPT(tn)) {inc *= 2;}\n  inc /= 2;\n\n  int start = inc;\n\n  while (!found && inc > 0)\n    {\n      if (GetOCPT(tn,start) > ocn) {inc = inc/2; start -= inc;}\n      else if (GetOCPT(tn,start) < ocn) {inc = inc/2; if (start+inc <= GetNOCPT(tn)) {start += inc;}}\n      else {found = 1;}\n    }\n\n  return GetOCPT(tn, start) == ocn;\n}\n\nChartId STLGeometry :: GetChartNr(STLTrigId i) const\n{\n  if (i > chartmark.Size()) \n    {\n      PrintSysError(\"GetChartNr(\", int(i), \") not possible!!!\");\n      i = 1;\n    }\n  return chartmark[i];\n}\n/*\nint STLGeometry :: GetMarker(int i) const\n{\n  return chartmark.Get(i);\n}\n*/\nvoid STLGeometry :: SetMarker(STLTrigId nr, ChartId m) \n{\n  chartmark[nr] = m;\n}\n\nint STLGeometry :: AtlasMade() const\n{\n  return chartmark.Size() != 0;\n}\n\n\n/*\n//return 1 if not exists\nint AddIfNotExists(NgArray<int>& list, int x)\n{\n  int i;\n  for (i = 1; i <= list.Size(); i++)\n    {\n      if (list.Get(i) == x) {return 0;} \n    }\n  list.Append(x);\n  return 1;\n}\n*/\n\nvoid STLGeometry :: GetInnerChartLimes(NgArray<twoint>& limes, ChartId chartnum)\n{\n  STLPointId np1, np2;\n  \n  limes.SetSize(0);\n\n  STLChart& chart = GetChart(chartnum);\n\n  for (int j = 1; j <= chart.GetNChartT(); j++)\n    {\n      STLTrigId t = chart.GetChartTrig1(j); \n      const STLTriangle& tt = GetTriangle(t);\n      for (int k = 1; k <= NONeighbourTrigs(t); k++)\n\t{\n\t  STLTrigId nt = NeighbourTrig(t,k); \n\t  if (GetChartNr(nt) != chartnum)\n\t    {\t      \n\t      tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t      if (!IsEdge(np1,np2))\n\t\t{\n\t\t  limes.Append(twoint(np1,np2));\n\t\t  /*\n\t\t  p3p1 = GetPoint(np1);\n\t\t  p3p2 = GetPoint(np2);\n\t\t  if (AddIfNotExists(limes,np1)) \n\t\t    {\n\t\t      plimes1.Append(p3p1); \n\t\t      //plimes1trigs.Append(t);\n\t\t      //plimes1origin.Append(np1);\n\t\t    }\n\t\t  if (AddIfNotExists(limes1,np2)) \n\t\t    {\n\t\t      plimes1.Append(p3p2); \n\t\t      //plimes1trigs.Append(t);\n\t\t      //plimes1origin.Append(np2); \t\t\t      \n\t\t    }\n\t\t  //chart.AddILimit(twoint(np1,np2));\n\t\t  \n\t\t  for (int di = 1; di <= divisions; di++)\n\t\t    {\n\t\t      double f1 = (double)di/(double)(divisions+1.);\n\t\t      double f2 = (divisions+1.-(double)di)/(double)(divisions+1.);\n\t\t      \n\t\t      plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,\n\t\t\t\t\t     p3p1.Y()*f1+p3p2.Y()*f2,\n\t\t\t\t\t     p3p1.Z()*f1+p3p2.Z()*f2));\n\t\t      //plimes1trigs.Append(t);\n\t\t      //plimes1origin.Append(0); \t\t\t      \n\t\t    }\n\t\t  */\n\t\t}\n\t    }\n\t}\n    }\n}\n\t \n\n\nvoid STLGeometry :: GetDirtyChartTrigs(int chartnum, STLChart& chart,\n\t\t\t\t       const Array<ChartId,STLTrigId>& outercharttrigs,\n\t\t\t\t       NgArray<ChartId>& chartpointchecked,\n\t\t\t\t       NgArray<int>& dirtytrigs)\n{\n  dirtytrigs.SetSize(0);\n\n\n  // int cnt = 0;\n\n  for (int j = 1; j <= chart.GetNChartT(); j++)\n    {\n      STLTrigId t = chart.GetChartTrig1(j); \n      const STLTriangle& tt = GetTriangle(t);\n      \n      for (int k = 1; k <= NONeighbourTrigs(t); k++)\n\t{\n\t  STLTrigId nt = NeighbourTrig(t,k); \n\t  if (GetChartNr(nt) != chartnum && outercharttrigs[nt] != chartnum)\n\t    {\n              STLPointId np1, np2;              \n\t      tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t      if (!IsEdge(np1,np2))\n\t\t{\n\t\t  dirtytrigs.Append(j); //local numbers!!!\n\t\t  // cnt++;\n\t\t  break; //only once per trig!!!\n\t\t}\n\t    }\n\t}\n    }\n  // cnt = 0;\n\n  STLPointId ap1, ap2, pn;\n  Array<STLTrigId> trigsaroundp;\n\n  for (int j = chart.GetNChartT(); j >= 1; j--)\n    {\n      STLTrigId t = chart.GetChartTrig1(j); \n      const STLTriangle& tt = GetTriangle(t);\n      \n      for (int k = 1; k <= 3; k++)\n\t{\n\t  pn = tt.PNum(k);\n\t  //if (chartpointchecked.Get(pn) == chartnum)\n\t  //{continue;}\n\t  \n\t  int checkpoint = 0;\n\t  for (int n = 1; n <= trigsperpoint.EntrySize(pn); n++)\n\t    {\n\t      if (trigsperpoint.Get(pn,n) != t && //ueberfluessig???\n\t\t  GetChartNr(trigsperpoint.Get(pn,n)) != chartnum &&\n\t\t  outercharttrigs[trigsperpoint.Get(pn,n)] != chartnum) {checkpoint = 1;};\n\t    }\n\t  if (checkpoint)\n\t    {\n\t      chartpointchecked.Elem(pn) = chartnum;\n\n\t      GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);\n\t      trigsaroundp.Append(t); //ring\n\t      \n\t      bool problem = false;\n\t      //forward:\n\t      for (int l = 2; l <= trigsaroundp.Size()-1; l++)\n\t\t{\n\t\t  STLTrigId tn1 = trigsaroundp[l-2];\n\t\t  STLTrigId tn2 = trigsaroundp[l-1];\n\t\t  const STLTriangle& t1 = GetTriangle(tn1);\n\t\t  const STLTriangle& t2 = GetTriangle(tn2);\n\t\t  t1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t  if (IsEdge(ap1,ap2)) break;\n\t\t  \n\t\t  if (GetChartNr(tn2) != chartnum && outercharttrigs[tn2] != chartnum) {problem = true;}\n\t\t}\n\n\t      //backwards:\n\t      for (int l = trigsaroundp.Size()-1; l >= 2; l--)\n\t\t{\n\t\t  STLTrigId tn1 = trigsaroundp[l];\n\t\t  STLTrigId tn2 = trigsaroundp[l-1];\n\t\t  const STLTriangle& t1 = GetTriangle(tn1);\n\t\t  const STLTriangle& t2 = GetTriangle(tn2);\n\t\t  t1.GetNeighbourPoints(t2, ap1, ap2);\n\t\t  if (IsEdge(ap1,ap2)) break;\n\t\t  \n\t\t  if (GetChartNr(tn2) != chartnum && outercharttrigs[tn2] != chartnum) {problem = true;}\n\t\t}\n\t      // if (problem && !IsInArray(j,dirtytrigs))\n              if (problem && !dirtytrigs.Contains(j))\n\t\t{\n\t\t  dirtytrigs.Append(j);\n\t\t  // cnt++;\n\t\t  break; //only once per triangle\n\t\t}\n\t    }\n\t}\n    }\n  \n}\n\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stlgeommesh.cpp",
    "content": "//20.11.1999 second part of stlgeom.cc, mainly mesh functions\n\n#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n#include \"stlgeom.hpp\"\n\nnamespace netgen\n{\nint EdgeUsed(int p1, int p2, NgArray<INDEX_2>& edges, INDEX_2_HASHTABLE<int>& hashtab)\n{\n  if (p1 > p2) {swap (p1,p2);}\n\n  if (hashtab.Used(INDEX_2(p1,p2))) \n    {return hashtab.Get(INDEX_2(p1,p2));}\n\n  return 0;\n}\n\nPoint<3> STLGeometry :: PointBetween(const Point<3> & ap1, int t1, \n\t\t\t\t     const Point<3> & ap2, int t2)\n{\n  //funktioniert nicht in allen Fällen!\n\n  PrintWarning(\"Point between\");\n\n\n  ClearMarkedSegs();\n\n  InitMarkedTrigs();\n  SetMarkedTrig(t1,1);\n  SetMarkedTrig(t2,1);\n\n  TABLE<Point3d> edgepoints;\n  TABLE<double> edgepointdists;\n  TABLE<int> edgepointorigines;\n  TABLE<int> edgepointoriginps;\n\n  NgArray<int> edgetrigs;\n  NgArray<INDEX_2> edgepointnums;\n  NgArray<int> edgetriglocinds;\n\n  int size = 3*GetNT();\n  INDEX_2_HASHTABLE<int> hashtab(size);\n\n  int divisions = 10;\n\n  edgepoints.SetSize(size);\n  edgepointdists.SetSize(size);\n  edgepointorigines.SetSize(size);\n  edgepointoriginps.SetSize(size);\n\n  edgetrigs.SetSize(size);\n  edgepointnums.SetSize(size);\n  edgetriglocinds.SetSize(size);\n\n  NgArray<int> edgelist1;\n  NgArray<int> edgelist2;\n\n  edgelist1.SetSize(0);\n  edgelist2.SetSize(0);\n\n\n  int i, j, k, l, m;\n  int edgecnt = 0;\n\n  //first triangle:\n  for (i = 1; i <= 3; i++)\n    {\n      int ptn1 = GetTriangle(t1).PNum(i);\n      int ptn2 = GetTriangle(t1).PNumMod(i+1);\n\n      if (ptn1 > ptn2) {swap(ptn1,ptn2);}\n\n      Point3d pt1 = GetPoint(ptn1);\n      Point3d pt2 = GetPoint(ptn2);\n\n      edgecnt++;\n      edgetrigs.Elem(edgecnt) = t1;\n      edgepointnums.Elem(edgecnt) = INDEX_2(ptn1,ptn2);\n      hashtab.Set(edgepointnums.Get(edgecnt),edgecnt);\n\n      edgetriglocinds.Elem(edgecnt) = i;\n      edgelist1.Append(edgecnt);\n\n      for (j = 1; j <= divisions; j++)\n\t{\n\t  double lfact = (double)j/(double)divisions;\n\t  Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(),\n\t\t       lfact*pt1.Y()+(1.-lfact)*pt2.Y(),\n\t\t       lfact*pt1.Z()+(1.-lfact)*pt2.Z());\n\n\t  //AddMarkedSeg(ap1,pbtw);\n\t\n\t  edgepoints.Add1(edgecnt,pbtw);\n\t  edgepointdists.Add1(edgecnt,Dist(pbtw,ap1));\n\t  edgepointorigines.Add1(edgecnt,0);\n\t  edgepointoriginps.Add1(edgecnt,0);\n\t}\n    }\n\n  int finished = 0;\n  int endpointorigine = 0;\n  int endpointoriginp = 0;\n  double endpointmindist = 1E50;\n\n  int maxsize = 0;\n  while (!finished)\n    {\n      finished = 1;\n      \n      if (edgelist1.Size() > maxsize) {maxsize = edgelist1.Size();}\n\n      for (i = 1; i <= edgelist1.Size(); i++)\n\t{\n\t  int en = edgelist1.Get(i);\n\t  int trig = edgetrigs.Get(en);\n\t  int edgenum = edgetriglocinds.Get(en);\n\t  int tn = NeighbourTrigSorted(trig,edgenum);\n\n\t  if (tn != t2)\n\t    {\n\t      for (k = 1; k <= 3; k++)\n\t\t{\n\t\t  int pnt1 = GetTriangle(tn).PNum(k);\n\t\t  int pnt2 = GetTriangle(tn).PNumMod(k+1);\n\t\t      \n\t\t  if (pnt1 > pnt2) {swap(pnt1,pnt2);}\n\n\t\t  Point3d pt1 = GetPoint(pnt1);\n\t\t  Point3d pt2 = GetPoint(pnt2);\n\t\t      \n\t\t  //AddMarkedSeg(pt1,pt2);\n\t\t  \n\t\t  //if (!(pnt1 == ep1 && pnt2 == ep2))\n\t\t  //  {\n\t\t  int edgeused = 0;\n\t\t  edgenum = EdgeUsed(pnt1, pnt2, edgepointnums, hashtab);\n\t\t  if (edgenum != en)\n\t\t    {\n\t\t      if (edgenum != 0) \n\t\t\t{edgeused = 1;}\n\t\t      else \n\t\t\t{\n\t\t\t  edgecnt++; \n\t\t\t  edgenum = edgecnt;\n\t\t\t  \n\t\t\t  edgetrigs.Elem(edgenum) = tn;\n\t\t\t  edgepointnums.Elem(edgenum) = INDEX_2(pnt1,pnt2);\n\t\t\t  hashtab.Set(edgepointnums.Get(edgenum),edgenum);\n\t\t\t  edgetriglocinds.Elem(edgenum) = k;\n\t\t\t}\n\t\t      \n\t\t      if (edgenum > size || edgenum == 0) {PrintSysError(\"edgenum = \", edgenum);}\n\t\t\t  \n\t\t      double minofmindist = 1E50;\n\t\t      int changed = 0;\n\t\t      \n\t\t      for (l = 1; l <= divisions; l++)\n\t\t\t{\n\t\t\t  double lfact = (double)l/(double)divisions;\n\t\t\t  Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(),\n\t\t\t\t       lfact*pt1.Y()+(1.-lfact)*pt2.Y(),\n\t\t\t\t       lfact*pt1.Z()+(1.-lfact)*pt2.Z());\n\t\t\t  \n\t\t\t  double mindist = 1E50;\n\t\t\t  int index=0;\n\t\t\t  \n\t\t\t  for (m = 1; m <= divisions; m++)\n\t\t\t    {\n\t\t\t      const Point3d& p = edgepoints.Get(en,m);\n\t\t\t      if (Dist(pbtw,p) + edgepointdists.Get(en,m) < mindist)\n\t\t\t\t{mindist = Dist(pbtw,p) + edgepointdists.Get(en,m); index = m;}\n\t\t\t    }\n\t\t\t  \n\t\t\t  //if (mindist < endpointmindist) {finished = 0;}\n\t\t\t  if (mindist < minofmindist) {minofmindist = mindist;}\n\t\t\t  \n\t\t\t  \n\t\t\t  if (!edgeused)\n\t\t\t    {\n\t\t\t      //AddMarkedSeg(pbtw,edgepoints.Get(en,index));\n\n\t\t\t      edgepoints.Add1(edgenum,pbtw);\n\t\t\t      edgepointdists.Add1(edgenum,mindist);\n\t\t\t      edgepointorigines.Add1(edgenum,en);\n\t\t\t      edgepointoriginps.Add1(edgenum,index);\n\t\t\t      changed = 1;\n\t\t\t    }\n\t\t\t  else\n\t\t\t    {\n\t\t\t      if (mindist < edgepointdists.Get(edgenum,l))\n\t\t\t\t{\n\t\t\t\t  edgepointdists.Set(edgenum,l,mindist);\n\t\t\t\t  edgepointorigines.Set(edgenum,l,en);\n\t\t\t\t  edgepointoriginps.Set(edgenum,l,index);\n\t\t\t\t  changed = 1;\n\t\t\t\t}\t\t\t      \n\t\t\t    }\n\t\t\t}\n\t\t      if (minofmindist < endpointmindist-1E-10 && changed)\n\t\t\t{\n\t\t\t  finished = 0;\n\t\t\t  edgelist2.Append(edgenum);\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t  else\n\t    {\n\t      double mindist = 1E50;\n\t      int index(0);\n\t      for (m = 1; m <= divisions; m++)\n\t\t{\n\t\t  const Point3d& p = edgepoints.Get(en,m);\n\t\t  if (Dist(ap2,p) + edgepointdists.Get(en,m) < mindist)\n\t\t    {mindist = Dist(ap2,p) + edgepointdists.Get(en,m); index = m;}\n\t\t}\n\t      if (mindist < endpointmindist)\n\t\t{\n\t\t  endpointorigine = en;\n\t\t  endpointoriginp = index;\n\t\t  endpointmindist = mindist;\n\t\t}\n\t    }\n\t}\n      edgelist1.SetSize(0);\n      for (i = 1; i <= edgelist2.Size(); i++)\n\t{\n\t  edgelist1.Append(edgelist2.Get(i));\n\t}\n    }\n\n  if (!endpointorigine) {PrintSysError(\"No connection found!\");}\n\n  NgArray<Point3d> plist;\n\n  plist.Append(ap2);\n  int laste = endpointorigine;\n  int lastp = endpointoriginp;\n  int lle, llp;\n\n\n  while (laste)\n    {\n      plist.Append(edgepoints.Get(laste,lastp));\n\n      lle = laste;\n      llp = lastp; \n      laste = edgepointorigines.Get(lle,llp);\n      lastp = edgepointoriginps.Get(lle,llp);\n    }\n\n  plist.Append(ap1);\n\n  for (i = 1; i <= plist.Size()-1; i++)\n    {\n      AddMarkedSeg(plist.Get(i),plist.Get(i+1));\n    }\n\n  PrintMessage(5,\"PointBetween: complexity=\", maxsize);\n\n\n  Point3d pm;\n  double dist = 0;\n  int found = 0;\n  \n  for (i = 1; i <= plist.Size()-1; i++)\n    {\n      dist += Dist(plist.Get(i),plist.Get(i+1));\n      if (dist > endpointmindist*0.5) \n\t{\n\t  double segl = Dist(plist.Get(i), plist.Get(i+1));\n\t  double d = dist - endpointmindist * 0.5;\n\t  pm = Point3d(d/segl*plist.Get(i).X() + (1.-d/segl)*plist.Get(i+1).X(),\n\t\t       d/segl*plist.Get(i).Y() + (1.-d/segl)*plist.Get(i+1).Y(),\n\t\t       d/segl*plist.Get(i).Z() + (1.-d/segl)*plist.Get(i+1).Z());\n\t  found = 1;\n\t  break;\n\t}\n    }\n  if (!found) {PrintWarning(\"Problem in PointBetween\"); pm = Center(ap1,ap2);}\n\n  AddMarkedSeg(pm, Point3d(0.,0.,0.));\n  \n  return pm;\n  \n}\n\n\nvoid STLGeometry :: PrepareSurfaceMeshing()\n{\n  meshchart = -1; //clear no old chart\n  meshcharttrigs.SetSize(GetNT());\n  meshcharttrigs = 0;\n}\n\nvoid STLGeometry::GetMeshChartBoundary (NgArray<Point<2>> & apoints,\n\t\t\t\t\tNgArray<Point<3>> & points3d,\n\t\t\t\t\tNgArray<INDEX_2> & alines, double h)\n{\n  twoint seg, newseg;\n  int zone;\n  Point<2> p2;\n\n  const STLChart& chart = GetChart(meshchart);\n\n\n  for (int i = 1; i <= chart.GetNOLimit(); i++)\n    {\n      seg = chart.GetOLimit(i);\n      INDEX_2 i2;\n      for (int j = 1; j <= 2; j++)\n\t{\n\t  int pi = (j == 1) ? seg.i1 : seg.i2;\n\t  int lpi;\n\t  if (ha_points.Get(pi) == 0)\n\t    {\n\t      const Point<3> & p3d = GetPoint (pi);\n\t      Point<2> p2d;\n\n\t      points3d.Append (p3d);\n\t      ToPlane(p3d, 0, p2d, h, zone, 0);\n\t      apoints.Append (p2d);\n\t      \n\t      lpi = apoints.Size();\n\t      ha_points.Elem(pi) = lpi;\n\t    }\n\t  else\n\t    lpi = ha_points.Get(pi);\n\n\t  i2.I(j) = lpi;\n\t}\n      alines.Append (i2);\n\n      /*\n      seg = chart.GetOLimit(i);\n      psize = points.Size();\n\n      newseg.i1 = psize+1;\n      newseg.i2 = psize+2;\n\n      ToPlane(GetPoint(seg.i1), 0, p2, h, zone, 0);\n      points.Append(p2);\n      points3d.Append (GetPoint(seg.i1));\n      ToPlane(GetPoint(seg.i2), 0, p2, h, zone, 0);\n      points.Append(p2);\n      points3d.Append (GetPoint(seg.i2));\n      lines.Append (INDEX_2 (points.Size()-1, points.Size()));\n      */\n    }\n\n  for (int i = 1; i <= chart.GetNOLimit(); i++)\n    {\n      seg = chart.GetOLimit(i);\n      ha_points.Elem(seg.i1) = 0;\n      ha_points.Elem(seg.i2) = 0;\n    }\n}\n\nvoid STLGeometry :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2, int trig)\n{\n  p1 = ap1; //save for ToPlane, in data of STLGeometry class\n  Point<3> p2 = ap2; //only locally used\n\n  meshchart = GetChartNr(trig);\n\n  if (usechartnormal)\n    meshtrignv = GetChart(meshchart).GetNormal();\n  else\n    meshtrignv = GetTriangle(trig).Normal();\n\n  //meshtrignv = GetTriangle(trig).Normal(points);\n\n  meshtrignv /= meshtrignv.Length();\n\n  GetTriangle(trig).ProjectInPlain(points, meshtrignv, p2);\n\n\n  ez = meshtrignv;\n  ez /= ez.Length();\n  ex = p2 - p1;\n  ex -= (ex * ez) * ez;\n  ex /= ex.Length();\n  ey = Cross (ez, ex);\n\n}\n\n\nvoid STLGeometry :: SelectChartOfTriangle (int trignum) const\n{\n  meshchart = GetChartNr(trignum);\n  meshtrignv = GetTriangle(trignum).Normal();\t\n}\n\n\nvoid STLGeometry :: SelectChartOfPoint (const Point<3> & p)\n{\n  int i, ii;\n\n  NgArray<int> trigsinbox;\n  \n  Box<3> box(p,p);\n  box.Increase (1e-6);\n  GetTrianglesInBox (box, trigsinbox);\n  \n\n  //  for (i = 1; i <= GetNT(); i++)\n  for (ii = 1; ii <= trigsinbox.Size(); ii++)\n    {\n      i = trigsinbox.Get(ii);\n      Point<3> hp = p;\n      if (GetTriangle(i).GetNearestPoint(points, hp) <= 1E-8)\n\t{\n\t  SelectChartOfTriangle (i);\n\t  break;\n      }\n    }\n  return;\n}\n\n\n\nvoid STLGeometry :: ToPlane (const Point<3> & locpoint, int * trigs,\n\t\t\t     Point<2> & plainpoint, double h, int& zone,\n\t\t\t     int checkchart)\n{\n  if (checkchart)\n    {\n\n      //check if locpoint lies on actual chart:\n      zone = 0;\n      \n      \n      //  Point3d p;\n      int i = 1;\n      const STLChart& chart = GetChart(meshchart);\n      int foundinchart = 0;\n      const double range = 1e-6; //1e-4 old\n      \n      \n      \n      \n      if (trigs)\n\t{\n\t  int * htrigs = trigs;\n\t  while (*htrigs)\n\t    {\n\t      if (TrigIsInOC (*htrigs, meshchart))\n\t\t{\n\t\t  foundinchart = 1;\n\t\t  break;\n\t\t}\n\t      htrigs++;\n\t    }\n\t}\n      \n      else\n\t{\n\t  NgArray<STLTrigId> trigsinbox;\n\n\t  if (!geomsearchtreeon)\n\t    {\n\t      //alter chart-tree\n\t      Box<3> box(locpoint, locpoint);\n\t      box.Increase (range);\n\t      chart.GetTrianglesInBox (box.PMin(), box.PMax(), trigsinbox);\n\t    }\n\t  else\n\t    {\n\t      NgArray<int> trigsinbox2;\n\t      Box<3> box(locpoint, locpoint);\n\t      box.Increase (range);\n\t      GetTrianglesInBox (box, trigsinbox2);\n\t      for (i = 1; i <= trigsinbox2.Size(); i++)\n\t\t{\n\t\t  if (TrigIsInOC(trigsinbox2.Get(i),meshchart)) {trigsinbox.Append(trigsinbox2.Get(i));}\n\t\t}\n\t      \n\t    }\n\t  \n\t  \n\t  for (i = 1; i <= trigsinbox.Size(); i++)\n\t    {\n\t      Point<3> p = locpoint;\n\t      if (GetTriangle(trigsinbox.Get(i)).GetNearestPoint(points, p) \n\t\t  <= 1E-8)\n\t\t{\n\t\t  foundinchart = 1;\n\t\t  break;\n\t\t}\n\t      \n\t    }\n\t}\n      \n  //do not use this point (but do correct projection (joachim)\n      if (!foundinchart) \n\t{\n\t  zone = -1; // plainpoint.X() = 11111; plainpoint.Y() = 11111; return; \n\t}\n    }\n  \n  else\n    {\n      zone = 0;\n    }\n  \n  //transform in plane\n  Vec<3> p1p = locpoint - p1;\n  plainpoint(0) = (p1p * ex) / h;\n  plainpoint(1) = (p1p * ey) / h;\n\n}\n\nint STLGeometry :: FromPlane (const Point<2> & plainpoint, \n\t\t\t      Point<3> & locpoint, double h)\n{\n  Vec<3> p1p = h * plainpoint[0] * ex + h * plainpoint[1] * ey;\n  locpoint = p1 + p1p;\n\n  int rv = Project(locpoint);\n  if (!rv) {return 1;} //project nicht gegangen\n  return 0;\n}\n\nint lasttrig;\nint STLGeometry :: LastTrig() const {return lasttrig;};\n\n//project normal to tangential plane\nint STLGeometry :: Project(Point<3> & p3d) const\n{\n  Point<3> p, pf;\n\n  // int j;\n  int fi = 0;\n  // int cnt = 0;\n  int different = 0;\n  // const double lamtol = 1e-6;\n\n  const STLChart& chart = GetChart(meshchart);\n\n  STLTrigId trig = chart.ProjectNormal(p3d);\n  return trig;\n  // cout << \"new, trig = \" << trig << endl;\n\n  // #define MOVEDTOCHART\n#ifdef MOVEDTOCHART\n  \n  int nt = chart.GetNT();\n\n   QuadraticFunction3d quadfun(p3d, meshtrignv);\n \n   /*\n     Vec3d hv = meshtrignv;\n     hv /= hv.Length();\n     Vec3d t1, t2;\n     hv.GetNormal (t1);\n     Cross (hv, t1, t2);\n   */\n  \n  for (j = 1; j <= nt; j++)\n    {\n      STLTrigId i = chart.GetTrig1(j);\n\n      const Point<3> & c = GetTriangle(i).center;\n      /*\n      double d1 = t1 * (c-p3d);\n      double d2 = t2 * (c-p3d);\n      */\n      /*\n      if (d1 * d1 + d2 * d2 > sqr (GetTriangle(i).rad))\n\tcontinue;\n      */\n      if (quadfun.Eval(c) > sqr (GetTriangle(i).rad))\n\tcontinue;\n\n      p = p3d;\n      Vec<3> lam;\n      int err = GetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam);      \n      int inside = (err == 0 && lam(0) > -lamtol && \n\t\t    lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);\n\n\n      /*\n      p = p3d;\n      GetTriangle(i).ProjectInPlain(points, meshtrignv, p);\n      if (GetTriangle(i).PointInside(points, p)) \n      */\n      if (inside)\n\t{\n\t  if (cnt != 0) \n\t    {\n\t      if (Dist2(p,pf)>=1E-16) \n\t\t{\n\t\t  //\t\t  (*testout) << \"ERROR: found two points to project which are different\" << endl;\n\t\t  //(*testout) << \"p=\" << p << \", pf=\" << pf << endl;\n\t\t  different = 1;\n\t\t}\n\t    }\n\t  pf = p; fi = i; cnt++;\n\t}\n\n      if (inside)\n        break;\n    }\n#endif\n\n  // cout << \"oldtrig = \" << fi << endl;\n  \n  //  if (cnt == 2) {(*testout) << \"WARNING: found 2 triangles to project\" << endl;}\n  //if (cnt == 3) {(*testout) << \"WARNING: found 3 triangles to project\" << endl;}\n  //if (cnt > 3) {(*testout) << \"WARNING: found more than 3 triangles to project\" << endl;}\n\n  if (fi != 0) {lasttrig = fi;}\n  if (fi != 0 && !different) {p3d = pf; return fi;}\n\n  //  (*testout) << \"WARNING: Project failed\" << endl;\n  return 0;\n  \n}\n\n//project normal to tangential plane\nint STLGeometry :: ProjectOnWholeSurface(Point<3> & p3d) const\n{\n  Point<3> p, pf;\n\n  int i;\n  int fi = 0;\n  int cnt = 0;\n  int different = 0;\n  const double lamtol = 1e-6;\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      p = p3d;\n      Vec<3> lam;\n      int err =\n\tGetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam);      \n      int inside = (err == 0 && lam(0) > -lamtol && \n\t\t    lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);\n\n      /*\n      p = p3d;\n      GetTriangle(i).ProjectInPlain(points, meshtrignv, p);\n      if (GetTriangle(i).PointInside(points, p)) \n      */\n      if (inside)\n\t{\n\t  if (cnt != 0) \n\t    {\n\t      if (Dist2(p,pf)>=1E-16) \n\t\t{\n\t\t  //\t\t  (*testout) << \"ERROR: found two points to project which are different\" << endl;\n\t\t  //\t\t  (*testout) << \"p=\" << p << \", pf=\" << pf << endl;\n\t\t  different = 1;\n\t\t}\n\t    }\n\t  pf = p; fi = i; cnt++;\n\t}\n    }\n  /*\n  if (cnt == 2) {(*testout) << \"WARNING: found 2 triangles to project\" << endl;}\n  if (cnt == 3) {(*testout) << \"WARNING: found 3 triangles to project\" << endl;}\n  if (cnt > 3) {(*testout) << \"WARNING: found more than 3 triangles to project\" << endl;}\n  */\n  if (fi != 0) {lasttrig = fi;}\n  if (fi != 0 && !different) {p3d = pf; return fi;}\n\n  //  (*testout) << \"WARNING: Project failed\" << endl;\n  return 0;\n  \n}\n\n\nint STLGeometry :: ProjectNearest(Point<3> & p3d) const\n{\n  Point<3> p, pf = 0.0;\n\n  //set new chart\n  const STLChart& chart = GetChart(meshchart);\n  int i;\n  double nearest = 1E50;\n  double dist;\n  int ft = 0;\n\n  for (i = 1; i <= chart.GetNT(); i++)\n    {\n      p = p3d;\n      dist  = GetTriangle(chart.GetTrig1(i)).GetNearestPoint(points, p);\n      if (dist < nearest)\n\t{\n\t  pf = p;\n\t  nearest = dist;\n\t  ft = chart.GetTrig1(i);\n\t}      \n    }\n  p3d = pf;\n  //if (!ft) {(*testout) << \"ERROR: ProjectNearest failed\" << endl;}\n  \n  return ft;\n}\n\n\n\n\t\n//Restrict local h due to curvature for make atlas\nvoid STLGeometry :: RestrictLocalHCurv(class Mesh & mesh, double gh, const STLParameters& stlparam)\n{\n  PushStatusF(\"Restrict H due to surface curvature\");\n\n  //bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen,\n  //die Meshsize auf ein bestimmtes Mass limitieren\n  int i,j;\n\n  STLPointId ap1,ap2,p3,p4;\n  Point<3> p1p, p2p, p3p, p4p;\n  Vec<3> n, ntn;\n  double rzyl, localh;\n\n  //  double localhfact = 0.5;\n  // double geometryignorelength = 1E-4;\n  double minlocalh = stlparam.atlasminh;\n\n  Box<3> bb = GetBoundingBox();\n  //  mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10),\n  //\t\t mparam.grading);\n\n  //  mesh.SetGlobalH(gh);\n\n  double mincalch = 1E10;\n  double maxcalch = -1E10\n;\n  double objectsize = bb.Diam();\n  double geometryignoreedgelength = objectsize * 1e-5;\n\n\n  if (stlparam.resthatlasenable)\n    {\n      NgArray<double> minh; //minimales h pro punkt\n      minh.SetSize(GetNP());\n      for (i = 1; i <= GetNP(); i++)\n\t{\n\t  minh.Elem(i) = gh;\n\t}\n      \n      for (i = 1; i <= GetNT(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNT()*100.);\n\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\n\t  const STLTriangle& trig = GetTriangle(i);\n\t  n = GetTriangle(i).Normal();\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j));\n\t      \n\t      trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3);\t    \t    \n\t      \n\t      //checken, ob ap1-ap2 eine Kante sind\n\t      if (IsEdge(ap1,ap2)) continue;\n\t      \n\t      p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2;\n\t      \n\t      p1p = GetPoint(ap1); p2p = GetPoint(ap2); \n\t      p3p = GetPoint(p3); p4p = GetPoint(p4);\n\t      \n\t      double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p);\n\t      double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p);\n\t      double diaglen = Dist (p1p, p2p);\n\t      \n\t      if (diaglen < geometryignoreedgelength)\n\t\tcontinue;\n\t      rzyl = ComputeCylinderRadius \n\t\t(n, GetTriangle(NeighbourTrig(i,j)).Normal(), \n\t\t h1, h2);\n\t      \n\t      \n\t      if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen)\n\t\tcontinue;\n\t      if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize)\n\t\tcontinue;\n\t      \n\t      \n\t      //\t      rzyl = mindist/(2*sinang);\n\t      localh = 10.*rzyl / stlparam.resthatlasfac;\n\t      if (localh < mincalch) {mincalch = localh;}\n\t      if (localh > maxcalch) {maxcalch = localh;}\n\n\t      if (localh < minlocalh) {localh = minlocalh;}\n\t      if (localh < gh)\n\t\t{\n\t\t  minh.Elem(ap1) = min2(minh.Elem(ap1),localh);\n\t\t  minh.Elem(ap2) = min2(minh.Elem(ap2),localh);\n\t\t}\n\t      \n\t      mesh.RestrictLocalHLine(p1p, p2p, localh);\n\t    }\n\t  \n\t}\n    }\n  PrintMessage(5, \"done\\nATLAS H: nmin local h=\", mincalch);\n  PrintMessage(5, \"ATLAS H: max local h=\", maxcalch);\n  PrintMessage(5, \"Local h tree has \", mesh.LocalHFunction().GetNBoxes(), \" boxes of size \",\n\t       (int)sizeof(GradingBox));\n\n  PopStatus();\n\n}\n  //restrict local h due to near edges and due to outer chart distance\nvoid STLGeometry :: RestrictLocalH(class Mesh & mesh, double gh, const STLParameters& stlparam, const MeshingParameters& mparam)\n{\n  \n  //bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen,\n  //die Meshsize auf ein bestimmtes Mass limitieren\n  int i,j;\n\n  STLPointId ap1,ap2,p3,p4;\n  Point3d p1p, p2p, p3p, p4p;\n  Vec3d n, ntn;\n  double rzyl, localh;\n\n  //  double localhfact = 0.5;\n  // double geometryignorelength = 1E-4;\n\n  Box<3> bb = GetBoundingBox();\n  //mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10),\n  //\t\t mparam.grading);\n\n  //mesh.SetGlobalH(gh);\n\n  double mincalch = 1E10;\n  double maxcalch = -1E10;\n\n  double objectsize = bb.Diam();\n  double geometryignoreedgelength = objectsize * 1e-5;\n\n  if (stlparam.resthsurfcurvenable)\n    {\n      PushStatusF(\"Restrict H due to surface curvature\");\n\n      NgArray<double> minh; //minimales h pro punkt\n      minh.SetSize(GetNP());\n      for (i = 1; i <= GetNP(); i++)\n\t{\n\t  minh.Elem(i) = gh;\n\t}\n\n      for (i = 1; i <= GetNT(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNT()*100.);\n\t  if (i%20000==19999) {PrintMessage(7, (double)i/(double)GetNT()*100. , \"%\");}\n\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\t  \n\t  const STLTriangle& trig = GetTriangle(i);\n\t  n = GetTriangle(i).Normal();\n\t  for (j = 1; j <= 3; j++)\n\t    {\n\t      const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j));\n\t      \n\t      trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3);\t    \t    \n\t      \n\t      //checken, ob ap1-ap2 eine Kante sind\n\t      if (IsEdge(ap1,ap2)) continue;\n\t      \n\t      p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2;\n\t      \n\t      p1p = GetPoint(ap1); p2p = GetPoint(ap2); \n\t      p3p = GetPoint(p3); p4p = GetPoint(p4);\n\t      \n\t      double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p);\n\t      double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p);\n\t      double diaglen = Dist (p1p, p2p);\n\t      \n\t      if (diaglen < geometryignoreedgelength)\n\t\tcontinue;\n\t      rzyl = ComputeCylinderRadius \n\t\t(n, GetTriangle (NeighbourTrig(i,j)).Normal(), \n\t\t h1, h2);\n\t      \n\t      \n\t      if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen)\n\t\tcontinue;\n\t      \n\t      if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize)\n\t\tcontinue;\n\t      \n\t      \n\t      //\t      rzyl = mindist/(2*sinang);\n\t      localh = rzyl / stlparam.resthsurfcurvfac;\n\t      if (localh < mincalch) {mincalch = localh;}\n\t      if (localh > maxcalch) {maxcalch = localh;}\n\t      if (localh < gh) \n\t\t{\n\t\t  minh.Elem(ap1) = min2(minh.Elem(ap1),localh);\n\t\t  minh.Elem(ap2) = min2(minh.Elem(ap2),localh);\n\t\t}\n\t      \n\t      //if (localh < 0.2) {localh = 0.2;}\n\n\t      if(localh < objectsize)\n\t\tmesh.RestrictLocalHLine(p1p, p2p, localh);\n\t      (*testout) << \"restrict h along \" << p1p << \" - \" << p2p << \" to \" << localh << endl;\n\t      \n\t      if (localh < 0.1)\n\t\t{\n\t\t  localh = 0.1;\n\t\t}\n\t      \n\t    }\n\t}\n      PrintMessage(7, \"done\\nmin local h=\", mincalch, \"\\nmax local h=\", maxcalch);\n      PopStatus();\n    }\n\n  if (mparam.closeedgefac.has_value())\n    {\n      PushStatusF(\"Restrict H due to close edges\");\n      //geht nicht für spiralen!!!!!!!!!!!!!!!!!!\n      \n      double disttohfact = sqr(10.0 / *mparam.closeedgefac);\n      int k,l;\n      double h1, h2, dist;\n      int rc = 0;\n      Point3d p3p1;\n      double mindist = 1E50;\n      \n      PrintMessage(7,\"build search tree...\");\n      BoxTree<3> * lsearchtree = new BoxTree<3> (GetBoundingBox().PMin() - Vec3d(1,1,1),\n                                                 GetBoundingBox().PMax() + Vec3d(1,1,1));\n      \n      NgArray<Point3d> pmins(GetNLines());\n      NgArray<Point3d> pmaxs(GetNLines());\n\n      double maxhline;\n      for (i = 1; i <= GetNLines(); i++)\n\t{\n\t  maxhline = 0;\n\t  STLLine* l1 = GetLine(i);\n\t  Point3d pmin(GetPoint(l1->StartP())), pmax(GetPoint(l1->StartP())), px;\n\n\t  for (j = 2; j <= l1->NP(); j++)\n\t    {\n\t      px = GetPoint(l1->PNum(j));\n\t      maxhline = max2(maxhline,mesh.GetH(px));\n\t      pmin.SetToMin (px);\n\t      pmax.SetToMax (px);\n\t    }\n\t  Box3d box(pmin,pmax);\n\t  box.Increase(maxhline);\n\n\t  lsearchtree->Insert (box.PMin(), box.PMax(), i);\n\t  pmins.Elem(i) = box.PMin();\n\t  pmaxs.Elem(i) = box.PMax();\n\t}\n\n      NgArray<int> linenums;\n      int k2;\n\n      for (i = 1; i <= GetNLines(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNLines()*100.);\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\n\t  linenums.SetSize(0);\n\t  lsearchtree->GetIntersecting(pmins.Get(i),pmaxs.Get(i),linenums);\n\t      \n\t  STLLine* l1 = GetLine(i);\n\t  for (j = 1; j <= l1->NP(); j++)\n\t    {\n\t      p3p1 = GetPoint(l1->PNum(j));\n\t      h1 = sqr(mesh.GetH(p3p1));\n\t      \n\t      for (k2 = 1; k2 <= linenums.Size(); k2++)\n\t\t{\n\t\t  k = linenums.Get(k2);\n\t\t  if (k <= i) {continue;} \n\t\t  /*  \n\t\t   //old, without searchtrees\n\t\t     for (k = i+1; k <= GetNLines(); k++)\n\t\t     {\n\t\t  */\n\t\t  STLLine* l2 = GetLine(k);\n\t\t  for (l = 1; l <= l2->NP(); l++)\n\t\t    {\n\t\t      const Point3d& p3p2 = GetPoint(l2->PNum(l));\n\t\t      h2 = sqr(mesh.GetH(p3p2));\n\t\t      dist = Dist2(p3p1,p3p2)*disttohfact;\t\t  \n\t\t      if (dist > 1E-12)\n\t\t\t{\n\t\t\t  if (dist < h1) \n\t\t\t    {\n\t\t\t      mesh.RestrictLocalH(p3p1,sqrt(dist)); \n\t\t\t      rc++;\n\t\t\t      mindist = min2(mindist,sqrt(dist));\n\t\t\t    }\n\t\t\t  if (dist < h2) \n\t\t\t    {\n\t\t\t      mesh.RestrictLocalH(p3p2,sqrt(dist)); \n\t\t\t      rc++;\n\t\t\t      mindist = min2(mindist,sqrt(dist));\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\t  \n\t    }\n\t}\n      PrintMessage(5, \"done\\n Restricted h in \", rc, \" points due to near edges!\");\n      PopStatus(); \n    }\n\n  if (stlparam.resthedgeangleenable)\n    {\n      PushStatusF(\"Restrict h due to close edges\");\n\n      int lp1, lp2;\n      Vec3d v1,v2;\n      mincalch = 1E50;\n      maxcalch = -1E50;\n\n      for (i = 1; i <= GetNP(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNP()*100.);\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\n\t  if (GetNEPP(i) == 2 && !IsLineEndPoint(i))\n\t    {\n\t      if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) ||\n\t\t  GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2))\n\t\t{\n\t\t  lp1 = 1; lp2 = 2;\n\t\t}\n\t      else\n\t\t{\n\t\t  lp1 = 2; lp2 = 1;\n\t\t}\n\n\t      v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)),\n\t\t\t GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2)));\n\t      v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)),\n\t\t\t GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2)));\n\n\t      rzyl = ComputeCylinderRadius(v1, v2, v1.Length(), v2.Length());\n\t      \t      \n\t      localh = rzyl / stlparam.resthedgeanglefac;\n\t      if (localh < mincalch) {mincalch = localh;}\n\t      if (localh > maxcalch) {maxcalch = localh;}\n\t      \n\t      if (localh != 0)\n\t\tmesh.RestrictLocalH(GetPoint(i), localh);\n\t    }\t  \n\t}\n      PrintMessage(7,\"edge-angle min local h=\", mincalch, \"\\nedge-angle max local h=\", maxcalch);\n      PopStatus();\n    }\n\n  if (stlparam.resthchartdistenable)\n    {\n      PushStatusF(\"Restrict H due to outer chart distance\");\n      \n      // mesh.LocalHFunction().Delete();\n\n      //berechne minimale distanz von chart zu einem nicht-outerchart-punkt in jedem randpunkt einer chart\n      \n      NgArray<int> acttrigs(GetNT()); //outercharttrigs\n      acttrigs = 0;\n\n      for (i = 1; i <= GetNOCharts(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNOCharts()*100.);\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\n\t  RestrictHChartDistOneChart(i, acttrigs, mesh, gh, 1., 0., stlparam);\n\t}\n      \n      PopStatus();\n      // NgProfiler::Print(stdout);\n    }\n\n  if (stlparam.resthlinelengthenable)\n    {\n      //restrict h due to short lines\n      PushStatusF(\"Restrict H due to line-length\");\n      \n      double minhl = 1E50;\n      double linefact = 1./stlparam.resthlinelengthfac;\n      double l;\n      for (i = 1; i <= GetNLines(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNLines()*100.);\n\t  if (multithread.terminate)\n\t    {PopStatus(); return;}\n\t  \n\t  l = GetLine(i)->GetLength(points);\n\t  \n\t  const Point3d& pp1 = GetPoint(GetLine(i)->StartP());\n\t  const Point3d& pp2 = GetPoint(GetLine(i)->EndP());\n\t  \n\t  if (l != 0)\n\t    {\n\t      minhl = min2(minhl,l*linefact);\n\t      \n\t      mesh.RestrictLocalH(pp1, l*linefact);\n\t      mesh.RestrictLocalH(pp2, l*linefact);      \n\t    }\n\t}\n      PopStatus();\n      PrintMessage(5, \"minh due to line length=\", minhl);\n  }\n}\n\nvoid STLGeometry :: RestrictHChartDistOneChart(ChartId chartnum, NgArray<int>& acttrigs, \n\t\t\t\t\t       class Mesh & mesh, double gh, double fact, double minh,\n                                               const STLParameters& stlparam)\n{\n  static int timer1 = NgProfiler::CreateTimer (\"restrictH OneChart 1\");\n  static int timer2 = NgProfiler::CreateTimer (\"restrictH OneChart 2\");\n  static int timer3 = NgProfiler::CreateTimer (\"restrictH OneChart 3\");\n  static int timer3a = NgProfiler::CreateTimer (\"restrictH OneChart 3a\");\n  static int timer3b = NgProfiler::CreateTimer (\"restrictH OneChart 3b\");\n\n  NgProfiler::StartTimer (timer1);\n  double limessafety = stlparam.resthchartdistfac*fact;  // original: 2\n  double localh;\n\n  //  mincalch = 1E10;\n  //maxcalch = -1E10;  \n  NgArray<int> limes1;\n  NgArray<int> limes2;\n\t  \n  NgArray<Point3d> plimes1;\n  NgArray<Point3d> plimes2;\n\t  \n  NgArray<int> plimes1trigs; //check from which trig the points come\n  NgArray<int> plimes2trigs;\n\t  \n  NgArray<int> plimes1origin; //either the original pointnumber or zero, if new point\n\n  int divisions = 10;\n\t  \n  STLPointId np1, np2;\n  // Point3d p3p1, p3p2;\n  STLTriangle tt;\n      \n  limes1.SetSize(0);\n  limes2.SetSize(0);\n  plimes1.SetSize(0);\n  plimes2.SetSize(0);\n  plimes1trigs.SetSize(0);\n  plimes2trigs.SetSize(0);\n  plimes1origin.SetSize(0);\n\n  STLChart& chart = GetChart(chartnum);\n  chart.ClearOLimit();\n  chart.ClearILimit();\n\n  for (int j = 1; j <= chart.GetNChartT(); j++)\n    {\n      int t = chart.GetChartTrig1(j); \n      tt = GetTriangle(t);\n      for (int k = 1; k <= NONeighbourTrigs(t); k++)\n\t{\n\t  int nt = NeighbourTrig(t,k); \n\t  if (GetChartNr(nt) != chartnum)\n\t    {\t      \n\t      tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t      if (!IsEdge(np1,np2) && !GetSpiralPoint(np1) && !GetSpiralPoint(np2))\n\t\t{\n\t\t  Point3d p3p1 = GetPoint(np1);\n\t\t  Point3d p3p2 = GetPoint(np2);\n\t\t  // if (AddIfNotExists(limes1,np1))\n                  if (!limes1.Contains(np1))\n\t\t    {\n                      limes1.Append(np1);\n\t\t      plimes1.Append(p3p1); \n\t\t      plimes1trigs.Append(t);\n\t\t      plimes1origin.Append(np1); \t\t\t      \n\t\t    }\n\t\t  // if (AddIfNotExists(limes1,np2))\n                  if (!limes1.Contains(np2))                  \n\t\t    {\n                      limes1.Append(np2);                      \n\t\t      plimes1.Append(p3p2); \n\t\t      plimes1trigs.Append(t);\n\t\t      plimes1origin.Append(np2); \t\t\t      \n\t\t    }\n\t\t  chart.AddILimit(twoint(np1,np2));\n\n\t\t  for (int di = 1; di <= divisions; di++)\n\t\t    {\n\t\t      double f1 = (double)di/(double)(divisions+1.);\n\t\t      double f2 = (divisions+1.-(double)di)/(double)(divisions+1.);\n\t\t\t      \n\t\t      plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,\n\t\t\t\t\t     p3p1.Y()*f1+p3p2.Y()*f2,\n\t\t\t\t\t     p3p1.Z()*f1+p3p2.Z()*f2));\n\t\t      plimes1trigs.Append(t);\n\t\t      plimes1origin.Append(0); \t\t\t      \n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\t  \n  NgProfiler::StopTimer (timer1);\t \n\n  NgProfiler::StartTimer (timer2);\t \n  for (int j = 1; j <= chart.GetNT(); j++)\n    acttrigs.Elem(chart.GetTrig1(j)) = chartnum;\n\n  for (int j = 1; j <= chart.GetNOuterT(); j++)\n    {\n      int t = chart.GetOuterTrig1(j); \n      tt = GetTriangle(t);\n      for (int k = 1; k <= 3; k++)\n\t{\n\t  int nt = NeighbourTrig(t,k);\n\t  if (acttrigs.Get(nt) != chartnum)\n\t    {\n\t      tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);\n\t\t      \n\t      if (!IsEdge(np1,np2))\n\t\t{\n\t\t  Point3d p3p1 = GetPoint(np1);\n\t\t  Point3d p3p2 = GetPoint(np2);\n\t\t\t  \n\t\t  // if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);}\n\t\t  // if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);}\n\t\t  if (!limes2.Contains(np1))\n                    {\n                      limes2.Append(np1);\n                      plimes2.Append(p3p1);\n                      plimes2trigs.Append(t);\n                    }\n\t\t  if (!limes2.Contains(np2))\n                    {\n                      limes2.Append(np2);\n                      plimes2.Append(p3p2);\n                      plimes2trigs.Append(t);\n                    }\n\t\t  chart.AddOLimit(twoint(np1,np2));\n\n\t\t  for (int di = 1; di <= divisions; di++)\n\t\t    {\n\t\t      double f1 = (double)di/(double)(divisions+1.);\n\t\t      double f2 = (divisions+1.-(double)di)/(double)(divisions+1.);\n\t\t\t      \n\t\t      plimes2.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,\n\t\t\t\t\t     p3p1.Y()*f1+p3p2.Y()*f2,\n\t\t\t\t\t     p3p1.Z()*f1+p3p2.Z()*f2));\n\t\t      plimes2trigs.Append(t);\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\t  \n  NgProfiler::StopTimer (timer2);\t \n  NgProfiler::StartTimer (timer3);\t \t  \n\n  double chartmindist = 1E50;\n\n  if (plimes2.Size())\n    {\n      NgProfiler::StartTimer (timer3a);\n      Box3d bbox;\n      bbox.SetPoint (plimes2.Get(1));\n      for (int j = 2; j <= plimes2.Size(); j++)\n\tbbox.AddPoint (plimes2.Get(j));\n      Point3dTree stree(bbox.PMin(), bbox.PMax());\n      for (int j = 1; j <= plimes2.Size(); j++)\n\tstree.Insert (plimes2.Get(j), j);\n      NgArray<int> foundpts;\n\t  \n      NgProfiler::StopTimer (timer3a);\n      NgProfiler::StartTimer (timer3b);\n\n      for (int j = 1; j <= plimes1.Size(); j++) \n\t{\n\t  double mindist = 1E50;\n\n\t  const Point3d & ap1 = plimes1.Get(j);\n\t  double boxs = mesh.GetH (plimes1.Get(j)) * limessafety;\n\n\t  Point3d pmin = ap1 - Vec3d (boxs, boxs, boxs);\n\t  Point3d pmax = ap1 + Vec3d (boxs, boxs, boxs);\n\n\t  stree.GetIntersecting (pmin, pmax, foundpts);\n\n\n\t  for (int kk = 1; kk <= foundpts.Size(); kk++)\n\t    {\n\t      int k = foundpts.Get(kk);\n\t      double dist = Dist2(plimes1.Get(j),plimes2.Get(k));\n\t      if (dist < mindist) mindist = dist;\n\t    }\n\n\t  /*\n\t    const Point3d & ap1 = plimes1.Get(j);\n\t    double his = mesh.GetH (plimes1.Get(j));\n\n\t    double xmin = ap1.X() - his * limessafety;\n\t    double xmax = ap1.X() + his * limessafety;\t      \n\t    double ymin = ap1.Y() - his * limessafety;\n\t    double ymax = ap1.Y() + his * limessafety;\t      \n\t    double zmin = ap1.Z() - his * limessafety;\n\t    double zmax = ap1.Z() + his * limessafety;\t      \n\n\t    for (k = 1; k <= plimes2.Size(); k++)\n\t    {\n\t    const Point3d & ap2 = plimes2.Get(k);\n\t    if (ap2.X() >= xmin && ap2.X() <= xmax &&\n\t    ap2.Y() >= ymin && ap2.Y() <= ymax &&\n\t    ap2.Z() >= zmin && ap2.Z() <= zmax)\n\t    {\n\t    dist = Dist2(plimes1.Get(j),plimes2.Get(k));\n\t    if (dist < mindist) \n\t    {\n\t    mindist = dist;\n\t    }\n\t    }\n\t    }\n\t  */\n\t  mindist = sqrt(mindist);\n\t  localh = mindist/limessafety;\n\n\t  if (localh < minh && localh != 0) {localh = minh;} //minh is generally 0! (except make atlas)\n\t  if (localh < gh && localh > 0)\n\t    {\n\t      mesh.RestrictLocalH(plimes1.Get(j), localh);\n\t      //\t      if (mindist < mincalch) {mincalch = mindist;}\n\t      //\t      if (mindist > maxcalch) {maxcalch = mindist;}\n\t      if (mindist < chartmindist) {chartmindist = mindist;}\n\t    }\n\t}\n      NgProfiler::StopTimer (timer3b);\n    }\n  NgProfiler::StopTimer (timer3);\t \n}\n\n\nint STLMeshingDummy (STLGeometry* stlgeometry, shared_ptr<Mesh> & mesh, const MeshingParameters & mparam,\n                     const STLParameters& stlparam)\n{\n  if (mparam.perfstepsstart > mparam.perfstepsend) return 0;\n\n  multithread.terminate = 0;\n  int success = 1;\n  //int trialcntouter = 0;\n\n  if (mparam.perfstepsstart <= MESHCONST_MESHEDGES)\n    {\n      if (mesh)\n        mesh -> DeleteMesh();\n      else\n        mesh = make_shared<Mesh>();\n\n      mesh->geomtype = Mesh::GEOM_STL;\n\n      mesh -> SetGlobalH (mparam.maxh);\n      mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\n\t\t\t stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\n\t\t\t mparam.grading);\n      mesh -> LoadLocalMeshSize (mparam.meshsizefilename);\n\n      if (mparam.uselocalh)\n        for (auto mspnt : mparam.meshsize_points)\n          mesh->RestrictLocalH(mspnt.pnt, mspnt.h);\n      \n      success = 0;\n  \n      //mesh->DeleteMesh();\n \n      STLMeshing (*stlgeometry, *mesh, mparam, stlparam);\n\n      stlgeometry->edgesfound = 1;\n      stlgeometry->surfacemeshed = 0;\n      stlgeometry->surfaceoptimized = 0;\n      stlgeometry->volumemeshed = 0;\n    }\n\n  if (multithread.terminate)\n    return 0;\n\n  if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE && \n      mparam.perfstepsend >= MESHCONST_MESHSURFACE)\n    {\n\n      if (!stlgeometry->edgesfound) \n\t{\n\t  PrintUserError(\"You have to do 'analyse geometry' first!!!\");\n\t  return 0; \n\t}\n      if (stlgeometry->surfacemeshed || stlgeometry->surfacemeshed) \n\t{\n\t  PrintUserError(\"Already meshed. Please start again with 'Analyse Geometry'!!!\"); \n\t  return 0; \n\t}\n\n      success = 0;\n      int retval = STLSurfaceMeshing (*stlgeometry, *mesh, mparam, stlparam);\n      if (retval == MESHING3_OK)\n\t{\n\t  PrintMessage(3,\"Success !!!!\");\n\t  stlgeometry->surfacemeshed = 1;\n\t  stlgeometry->surfaceoptimized = 0;\n\t  stlgeometry->volumemeshed = 0;\n\t  success = 1;\n\t} \n      else if (retval == MESHING3_OUTERSTEPSEXCEEDED)\n\t{\n\t  PrintError(\"Give up because of too many trials. Meshing aborted!\");\n\t}\n      else if (retval == MESHING3_TERMINATE)\n\t{\n\t  PrintWarning(\"Meshing Stopped by user!\");\n\t}\n      else\n\t{\n\t  PrintError(\"Surface meshing not successful. Meshing aborted!\");\n\t}\n      \n#ifdef STAT_STREAM\n      (*statout) << mesh->GetNSeg() << \" & \" << endl\n\t\t << mesh->GetNSE() << \" & \" << endl\n\t\t << GetTime() << \" & \";\n#endif\n    }\n  if (multithread.terminate)\n    return 0;\n\n  if (success)\n    {\n      if (mparam.perfstepsstart <= MESHCONST_OPTSURFACE && \n\t  mparam.perfstepsend >= MESHCONST_OPTSURFACE)\n\t{\n\t  if (!stlgeometry->edgesfound) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->analyse geometry' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (!stlgeometry->surfacemeshed) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->mesh surface' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (stlgeometry->volumemeshed) \n\t    {\n\t      PrintWarning(\"Surface optimization with meshed volume is dangerous!!!\"); \n\t    }\n\n\t  /*\n\t  if (!optstring || strlen(optstring) == 0)\n\t    {\n\t      mparam.optimize2d = \"smcm\";\n\t    }\n\t  else\n\t    {\n\t      mparam.optimize2d = optstring;\n\t    }\n\t  */\n\n\t  STLSurfaceOptimization (*stlgeometry, *mesh, mparam);\n\t  \n\t  if (stlparam.recalc_h_opt)\n\t    {\n\t      mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\n\t\t\t\t stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\n\t\t\t\t mparam.grading);\n\t      mesh -> LoadLocalMeshSize (mparam.meshsizefilename);\t      \n\t      mesh -> CalcLocalHFromSurfaceCurvature (mparam.grading, \n\t\t\t\t\t\t      stlparam.resthsurfmeshcurvfac);\n              MeshingParameters mpar = mparam;\n\t      mpar.optimize2d = \"cmsmSm\";\n\t      STLSurfaceOptimization (*stlgeometry, *mesh, mpar);\n#ifdef STAT_STREAM\n\t      (*statout) << GetTime() << \" & \";\n#endif\n\n\t      mpar.Render();\n\t    }\n\t  stlgeometry->surfaceoptimized = 1;\n\t}\n      if (multithread.terminate)\n\treturn 0;\n\n      if(stlgeometry->IsSurfaceSTL())\n        return 0;\n\n      if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME && \n\t  mparam.perfstepsend >= MESHCONST_MESHVOLUME)\n\t{\n\t  if (stlgeometry->volumemeshed) \n\t    {\n\t      PrintUserError(\"Volume already meshed!\"); return 0;\n\t    }\n\n\t  if (!stlgeometry->edgesfound) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->analyse geometry' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (!stlgeometry->surfacemeshed) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->mesh surface' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (!stlgeometry->surfaceoptimized) \n\t    {\n\t      PrintWarning(\"You should do 'meshing->optimize surface' first!!!\"); \n\t    }\n\n\n\t  PrintMessage(5,\"Check Overlapping boundary: \");\n\t  mesh->FindOpenElements();\n\t  mesh->CheckOverlappingBoundary();\n\t  PrintMessage(5,\"\");\n\n\n\t  if (stlparam.recalc_h_opt)\n\t    {\n\t      mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\n\t\t\t\t stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\n\t\t\t\t mparam.grading);\t  \n\t      mesh -> LoadLocalMeshSize (mparam.meshsizefilename);\n\t      mesh -> CalcLocalH (mparam.grading);\n\t    }\n\t  \n\t  \n\t  PrintMessage(5,\"Volume meshing\");\n\t  int retval = MeshVolume (mparam, *mesh);\n\t  if (retval == MESHING3_OK)\n\t    {\n\t      RemoveIllegalElements(*mesh);\n\t      stlgeometry->volumemeshed = 1;\n\t    } \n\t  else if (retval == MESHING3_OUTERSTEPSEXCEEDED)\n\t    {\n\t      PrintError(\"Give up because of too many trials. Meshing aborted!\");\n\t      return 0;\n\t    }\n\t  else if (retval == MESHING3_TERMINATE)\n\t    {\n\t      PrintWarning(\"Meshing Stopped by user!\");\n\t    }\n\t  else\n\t    {\n\t      PrintError(\"Volume meshing not successful. Meshing aborted!\");\n\t      return 0;\n\t    }\n\n#ifdef STAT_STREAM\n\t  (*statout) << GetTime() << \" & \" << endl;\n#endif\n\t  MeshQuality3d (*mesh);\n\t}\n\n      if (multithread.terminate)\n\treturn 0;\n\n      if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME && \n\t  mparam.perfstepsend >= MESHCONST_OPTVOLUME)\n\t{\n\t  if (!stlgeometry->edgesfound) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->analyse geometry' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (!stlgeometry->surfacemeshed) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->mesh surface' first!!!\"); \n\t      return 0; \n\t    }\n\t  if (!stlgeometry->volumemeshed) \n\t    {\n\t      PrintUserError(\"You have to do 'meshing->mesh volume' first!!!\"); \n\t      return 0; \n\t    }\n\n\t  /*\n\t  if (!optstring || strlen(optstring) == 0)\n\t    {\n\t      mparam.optimize3d = \"cmdmstm\";\n\t    }\n\t  else\n\t    {\n\t      mparam.optimize3d = optstring;\n\t    }\n\t  */\n\n\t  OptimizeVolume (mparam, *mesh);\n\t  \n#ifdef STAT_STREAM\n\t  (*statout) << GetTime() << \" & \" << endl;\n\t  (*statout) << mesh->GetNE() << \" & \" << endl\n\t\t     << mesh->GetNP() << \" \" << '\\\\' << '\\\\' << \" \\\\\" << \"hline\" << endl;\n#endif\n\n\t  mparam.Render();\n\t}\n    }\n  \n\n  return 0;\n}\n\n\n\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stlline.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n#include \"stlgeom.hpp\"\n\nnamespace netgen\n{\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n//++++++++++++++  EDGE DATA     ++++++++++++++++++++++++++++++++++++++++++\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n/*\nvoid STLEdgeData :: Write(ofstream& of) const\n{\n  of // << angle << \" \"\n     << p1 << \" \"\n     << p2 << \" \"\n     << lt << \" \"\n     << rt << \" \"\n    //     << status\n     << endl;\n}\n\nvoid STLEdgeData :: Read(ifstream& ifs)\n{\n  // ifs >> angle;\n  ifs >> p1;\n  ifs >> p2;\n  ifs >> lt;\n  ifs >> rt;\n  //  ifs >> status;\n}\n\n\nint STLEdgeData :: GetStatus () const\n{\n  if (topedgenr <= 0 || topedgenr > top->GetNTE()) return 0;\n  return top->GetTopEdge (topedgenr).GetStatus(); \n}\n\nvoid STLEdgeData ::SetStatus (int stat)\n{\n  if (topedgenr >= 1 && topedgenr <= top->GetNTE())\n    top->GetTopEdge (topedgenr).SetStatus(stat); \n}\n\n\nfloat STLEdgeData :: CosAngle() const\n{\n  return top->GetTopEdge (topedgenr).CosAngle(); \n}\n\n\n\nvoid STLEdgeDataList :: ResetAll()\n{\n  int i;\n  for (i = 1; i <= edgedata.Size(); i++)\n    {\n      edgedata.Elem(i).SetUndefined();\n    }\n}\n\nvoid STLEdgeDataList :: ResetCandidates()\n{\n  int i;\n  for (i = 1; i <= edgedata.Size(); i++)\n    {\n      if (edgedata.Get(i).Candidate())\n\t{edgedata.Elem(i).SetUndefined();}\n    }\n}\n\nint STLEdgeDataList :: GetNConfEdges() const\n{\n  int i;\n  int cnt = 0;\n  for (i = 1; i <= edgedata.Size(); i++)\n    {\n      if (edgedata.Get(i).Confirmed()) {cnt++;}\n    }\n  return cnt;\n}\n\nvoid STLEdgeDataList :: ConfirmCandidates()\n{\n  int i;\n  for (i = 1; i <= edgedata.Size(); i++)\n    {\n      if (edgedata.Get(i).Candidate())\n\t{edgedata.Elem(i).SetConfirmed();}\n    }\n}\n\nint STLEdgeDataList :: GetEdgeNum(int np1, int np2) const\n{\n  INDEX_2 ed(np1,np2);\n  ed.Sort();\n  if (hashtab.Used(ed))\n    {\n      return hashtab.Get(ed);\n    }\n\n//   int i;\n//   for (i = 1; i <= Size(); i++)\n//     {\n//       if ((Get(i).p1 == np1 && Get(i).p2 == np2) ||\n// \t  (Get(i).p2 == np1 && Get(i).p1 == np2))\n// \t{\n// \t  return i;\n// \t}\n//     }\n\n  return 0;\n}\n\nconst STLEdgeDataList& STLEdgeDataList :: operator=(const STLEdgeDataList& edl)\n{\n  int i;\n  SetSize(edl.Size());\n  for (i = 1; i <= Size(); i++)\n    {\n      Add(edl.Get(i), i);\n    }\n  return *this;\n} \n\nvoid STLEdgeDataList :: Add(const STLEdgeData& ed, int i)\n{\n  INDEX_2 edge(ed.p1,ed.p2);\n  edge.Sort();\n  hashtab.Set(edge, i);\n  Elem(i) = ed;\n  AddEdgePP(ed.p1,i);\n  AddEdgePP(ed.p2,i);\n}\n\nvoid STLEdgeDataList :: Write(ofstream& of) const\n{\n  of.precision(16);\n  int i;\n  of << Size() << endl;\n  \n  for (i = 1; i <= Size(); i++)\n    {\n      Get(i).Write(of);\n    }\n}\n\nvoid STLEdgeDataList :: Read(ifstream& ifs)\n{\n  int i,n;\n  ifs >> n;\n\n  SetSize(n);\n  STLEdgeData ed;\n  for (i = 1; i <= n; i++)\n    {\n      ed.Read(ifs);\n      Add(ed,i);\n    }\n}\n\nint STLEdgeDataList :: GetNEPPStat(int p, int status) const\n{\n  int i;\n  int cnt = 0;\n  for (i = 1; i <= GetNEPP(p); i++)\n    {\n      if (Get(GetEdgePP(p,i)).GetStatus() == status)\n\t{\n\t  cnt++;\n\t}\n    }\n  return cnt;\n}\n\nint STLEdgeDataList :: GetNConfCandEPP(int p) const\n{\n  int i;\n  int cnt = 0;\n  for (i = 1; i <= GetNEPP(p); i++)\n    {\n      if (Get(GetEdgePP(p,i)).ConfCand())\n\t{\n\t  cnt++;\n\t}\n    }\n  return cnt;\n}\n\n\nvoid STLEdgeDataList :: BuildLineWithEdge(int ep1, int ep2, NgArray<twoint>& line)\n{\n  int status = Get(GetEdgeNum(ep1,ep2)).GetStatus();\n\n  int found, pstart, p, en, pnew, ennew;\n  int closed = 0;\n  int j, i;\n  for (j = 1; j <= 2; j++)\n    {\n      if (j == 1) {p = ep1;}\n      if (j == 2) {p = ep2;}\n\n      pstart = p;\n      en = GetEdgeNum(ep1,ep2);\n\n      found = 1;\n      while (found && !closed)\n\t{\n\t  found = 0;\n\t  \n\t  if (GetNEPPStat(p,status) == 2)\n\t    {\n\t      for (i = 1; i <= GetNEPP(p); i++)\n\t\t{\t\t\n\t\t  const STLEdgeData& e = Get(GetEdgePP(p,i));\n\t\t  if (GetEdgePP(p,i) != en && e.GetStatus() == status) \n\t\t    {\n\t\t      if (e.p1 == p) \n\t\t\t{pnew = e.p2;}\n\t\t      else \n\t\t\t{pnew = e.p1;}\n\n\t\t      ennew = GetEdgePP(p,i);\n\t\t    }\n\t\t}\n\t      if (pnew == pstart) {closed = 1;}\n\t      else\n\t\t{\n\t\t  line.Append(twoint(p,pnew));\n\t\t  p = pnew;\n\t\t  en = ennew;\n\t\t  found = 1;\n\t\t}\n\t    }\n\t}\n    }\n  \n}\n*/\n\n\n\n\nSTLEdgeDataList :: STLEdgeDataList (STLTopology & ageom)\n  : geom(ageom)\n{\n  ;\n}\n\nSTLEdgeDataList :: ~STLEdgeDataList()\n{\n  ;\n}\n\n\nvoid STLEdgeDataList :: Store ()\n{\n  int i, ne = geom.GetNTE();\n  storedstatus.SetSize(ne);\n  for (i = 1; i <= ne; i++)\n    {\n      storedstatus.Elem(i) = Get(i).GetStatus();\n    }\n}\n\nvoid STLEdgeDataList :: Restore ()\n{\n  int i, ne = geom.GetNTE();\n  if (storedstatus.Size() == ne)\n    for (i = 1; i <= ne; i++)\n      geom.GetTopEdge(i).SetStatus (storedstatus.Elem(i));\n}\n\n\nvoid STLEdgeDataList :: ResetAll()\n{\n  int i, ne = geom.GetNTE();\n  for (i = 1; i <= ne; i++)\n    geom.GetTopEdge (i).SetStatus (ED_UNDEFINED);\n}\n\nint STLEdgeDataList :: GetNConfEdges() const\n{\n  int i, ne = geom.GetNTE();\n  int cnt = 0;\n  for (i = 1; i <= ne; i++)\n    if (geom.GetTopEdge (i).GetStatus() == ED_CONFIRMED)\n      cnt++;\n  return cnt; \n}\n\nvoid STLEdgeDataList :: ChangeStatus(int status1, int status2)\n{\n  int i, ne = geom.GetNTE();\n  for (i = 1; i <= ne; i++)\n    if (geom.GetTopEdge (i).GetStatus() == status1)\n      geom.GetTopEdge (i).SetStatus (status2);\n}\n\n/*\nvoid STLEdgeDataList :: Add(const STLEdgeData& ed, int i)\n{\n  INDEX_2 edge(ed.p1,ed.p2);\n  edge.Sort();\n  hashtab.Set(edge, i);\n  Elem(i) = ed;\n  AddEdgePP(ed.p1,i);\n  AddEdgePP(ed.p2,i);\n}\n*/\n\nvoid STLEdgeDataList :: Write(ofstream& of) const\n{\n  \n  /*\n  of.precision(16);\n  int i;\n  of << Size() << endl;\n  \n  for (i = 1; i <= Size(); i++)\n    {\n      Get(i).Write(of);\n    }\n\n  */\n  of.precision(16);\n  int i, ne = geom.GetNTE();\n  //of << GetNConfEdges() << endl;\n  of << geom.GetNTE() << endl;\n\n  for (i = 1; i <= ne; i++)\n    {\n      const STLTopEdge & edge = geom.GetTopEdge(i);\n      //if (edge.GetStatus() == ED_CONFIRMED)\n      of << edge.GetStatus() << \" \";\n\n      const Point3d & p1 = geom.GetPoint (edge.PNum(1));\n      const Point3d & p2 = geom.GetPoint (edge.PNum(2));\n      of << p1.X() << \" \"\n\t << p1.Y() << \" \"\n\t << p1.Z() << \" \"\n\t << p2.X() << \" \"\n\t << p2.Y() << \" \"\n\t << p2.Z() << endl;\n    }\n  \n}\n\nvoid STLEdgeDataList :: Read(ifstream& ifs)\n{\n  int i, nce;\n  Point3d p1, p2;\n  int pi1, pi2;\n  int status, ednum;\n\n  ifs >> nce;\n  for (i = 1; i <= nce; i++)\n    {\n      ifs >> status;\n      ifs >> p1.X() >> p1.Y() >> p1.Z();\n      ifs >> p2.X() >> p2.Y() >> p2.Z();\n\n      pi1 = geom.GetPointNum (p1);\n      pi2 = geom.GetPointNum (p2);\n      ednum = geom.GetTopEdgeNum (pi1, pi2);\n\n\n      if (ednum)\n\t{ \n\t  geom.GetTopEdge(ednum).SetStatus (status);\n\t//\tgeom.GetTopEdge (ednum).SetStatus (ED_CONFIRMED);\n\t}\n    }\n    /*\n  int i,n;\n  ifs >> n;\n\n  SetSize(n);\n  STLEdgeData ed;\n  for (i = 1; i <= n; i++)\n    {\n      ed.Read(ifs);\n      Add(ed,i);\n    }\n  */\n}\n\nint STLEdgeDataList :: GetNEPPStat(int p, int status) const\n{\n  int i;\n  int cnt = 0;\n  for (i = 1; i <= GetNEPP(p); i++)\n    {\n      if (Get(GetEdgePP(p,i)).GetStatus() == status)\n\t{\n\t  cnt++;\n\t}\n    }\n  return cnt;\n}\n\nint STLEdgeDataList :: GetNConfCandEPP(int p) const\n{\n  int i;\n  int cnt = 0;\n  for (i = 1; i <= GetNEPP(p); i++)\n    {\n      if (Get(GetEdgePP(p,i)).GetStatus() == ED_CANDIDATE || \n\t  Get(GetEdgePP(p,i)).GetStatus() == ED_CONFIRMED)\n\t{\n\t  cnt++;\n\t}\n    }\n  return cnt;\n}\n\n\nvoid STLEdgeDataList :: BuildLineWithEdge(int ep1, int ep2, NgArray<twoint>& line)\n{\n  int status = Get(GetEdgeNum(ep1,ep2)).GetStatus();\n\n  int found, pstart, p(0), en, pnew(0), ennew(0);\n  int closed = 0;\n  int j, i;\n  for (j = 1; j <= 2; j++)\n    {\n      if (j == 1) {p = ep1;}\n      if (j == 2) {p = ep2;}\n\n      pstart = p;\n      en = GetEdgeNum(ep1,ep2);\n\n      found = 1;\n      while (found && !closed)\n\t{\n\t  found = 0;\n\t  \n\t  if (GetNEPPStat(p,status) == 2)\n\t    {\n\t      for (i = 1; i <= GetNEPP(p); i++)\n\t\t{\t\t\n\t\t  const STLTopEdge & e = Get(GetEdgePP(p,i));\n\t\t  if (GetEdgePP(p,i) != en && e.GetStatus() == status) \n\t\t    {\n\t\t      if (e.PNum(1) == p) \n\t\t\t{pnew = e.PNum(2);}\n\t\t      else \n\t\t\t{pnew = e.PNum(1);}\n\n\t\t      ennew = GetEdgePP(p,i);\n\t\t    }\n\t\t}\n\t      if (pnew == pstart) {closed = 1;}\n\t      else\n\t\t{\n\t\t  line.Append(twoint(p,pnew));\n\t\t  p = pnew;\n\t\t  en = ennew;\n\t\t  found = 1;\n\t\t}\n\t    }\n\t}\n    }\n  \n}\n\nint Exists(int p1, int p2, const NgArray<twoint>& line)\n{\n  int i;\n  for (i = 1; i <= line.Size(); i++)\n    {\n      if ( (line.Get(i).i1 == p1 && line.Get(i).i2 == p2) ||\n\t   (line.Get(i).i1 == p2 && line.Get(i).i2 == p1) )\n\t{return 1;}\n    }\n  return 0;\n}\n\nvoid STLEdgeDataList :: BuildClusterWithEdge(int ep1, int ep2, NgArray<twoint>& line)\n{\n  int status = Get(GetEdgeNum(ep1,ep2)).GetStatus();\n\n  int p(0), en;\n  int j, i, k;\n  int oldend;\n  int newend = 1;\n  STLPointId pnew;\n  int ennew(0);\n\n  int changed = 1;\n  while (changed)\n    {\n      changed = 0;\n      for (j = 1; j <= 2; j++)\n\t{\n\t  oldend = newend;\n\t  newend = line.Size();\n\t  for (k = oldend; k <= line.Size(); k++)\n\t    {\n\t      if (j == 1) p = line.Get(k).i1;\n\t      if (j == 2) p = line.Get(k).i2;\n\t      en = GetEdgeNum(line.Get(k).i1, line.Get(k).i2);\n\n\t      for (i = 1; i <= GetNEPP(p); i++)\n\t\t{\t\t\n\t\t  pnew = 0;\n\t\t  const STLTopEdge & e = Get(GetEdgePP(p,i));\n\t\t  if (GetEdgePP(p,i) != en && e.GetStatus() == status) \n\t\t    {\n\t\t      if (e.PNum(1) == p) \n\t\t\t{pnew = e.PNum(2);}\n\t\t      else \n\t\t\t{pnew = e.PNum(1);}\n\n\t\t      ennew = GetEdgePP(p,i);\n\t\t    }\n\t\t  if (pnew && !Exists(p,pnew,line))\n\t\t    {\n\t\t      changed = 1;\n\t\t      line.Append(twoint(p,pnew));\n\t\t      p = pnew;\n\t\t      en = ennew;\n\t\t    }\n\t\t}\n\t      \n\t    }\n\t}\n\n    }\n\n}\n\n\n\n\n\n\n\n\n\n\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n//+++++++++++++++++++   STL LINE    +++++++++++++++++++++++++++++++\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nSTLLine :: STLLine(const STLGeometry * ageometry)\n  : pts(), lefttrigs(), righttrigs()\n{\n  geometry = ageometry;\n  split = 0;\n};\n\nint STLLine :: GetNS() const\n{\n  if (pts.Size() <= 1) {return 0;}\n  return pts.Size()-1;\n}\nvoid STLLine :: GetSeg(int nr, int& p1, int& p2) const\n{\n  p1 = pts.Get(nr);\n  p2 = pts.Get(nr+1);\n}\n\nint STLLine :: GetLeftTrig(int nr) const \n{\n  if (nr > lefttrigs.Size()) {PrintSysError(\"In STLLine::GetLeftTrig!!!\"); return 0;}\n  return lefttrigs.Get(nr);\n};\n\nint STLLine :: GetRightTrig(int nr) const \n{\n  if (nr > righttrigs.Size()) {PrintSysError(\"In STLLine::GetRightTrig!!!\"); return 0;}\n  return righttrigs.Get(nr);\n};\n\ndouble STLLine :: GetSegLen(const Array<Point<3>,STLPointId>& ap, int nr) const\n{\n  return Dist(ap[PNum(nr)],ap[PNum(nr+1)]);\n}\n\ndouble STLLine :: GetLength(const Array<Point<3>,STLPointId>& ap) const\n{\n  double len = 0;\n  for (int i = 2; i <= pts.Size(); i++)\n    len += (ap[pts.Get(i)] - ap[pts.Get(i-1)]).Length();\n  return len;\n}\n\nvoid STLLine :: GetBoundingBox (const Array<Point<3>,STLPointId> & ap, Box<3> & box) const\n{\n  box.Set (ap[pts[0]]);\n  for (int i = 1; i < pts.Size(); i++)\n    box.Add (ap[pts[i]]);\n}\n\n\n\nPoint<3> STLLine :: \nGetPointInDist(const Array<Point<3>,STLPointId>& ap, double dist, int& index) const\n{\n  if (dist <= 0)\n    {\n      index = 1;\n      return ap[StartP()];\n    }\n  \n  double len = 0;\n  int i;\n  for (i = 1; i < pts.Size(); i++)\n    {\n      double seglen = Dist (ap[pts.Get(i)],\n\t\t\t    ap[pts.Get(i+1)]);\n\n      if (len + seglen > dist)\n\t{\n\t  index = i;\n\t  double relval = (dist - len) / (seglen + 1e-16);\n\t  Vec3d v (ap[pts.Get(i)], ap[pts.Get(i+1)]);\n\t  return ap[pts.Get(i)] + relval * v;\n\t}\n\n      len += seglen;\n    }\n\n  index = pts.Size() - 1;\n  return ap[EndP()];\n}\n\n\n/*\ndouble stlgh;\ndouble GetH(const Point3d& p, double x) \n{\n  return stlgh;//+0.5)*(x+0.5);\n}\n*/\nSTLLine* STLLine :: Mesh(const Array<Point<3>,STLPointId>& ap, \n\t\t\t NgArray<Point3d>& mp, double ghi,\n\t\t\t class Mesh& mesh) const\n{\n  static int timer1a = NgProfiler::CreateTimer (\"mesh stl-line 1a\");\n  static int timer1b = NgProfiler::CreateTimer (\"mesh stl-line 1b\");\n  static int timer2 = NgProfiler::CreateTimer (\"mesh stl-line 2\");\n  static int timer3 = NgProfiler::CreateTimer (\"mesh stl-line 3\");\n\n  NgProfiler::StartTimer (timer1a);\n\n  STLLine* line = new STLLine(geometry);\n\n  //stlgh = ghi; //uebergangsloesung!!!!\n  \n  double len = GetLength(ap);\n  double inthl = 0; //integral of 1/h\n  double dist = 0;\n  double h;\n  int ind;\n  Point3d p;\n\n  Box<3> bbox;\n  GetBoundingBox (ap, bbox);\n  double diam = bbox.Diam();\n\n  double minh = mesh.LocalHFunction().GetMinH (bbox.PMin(), bbox.PMax());\n\n  double maxseglen = 0;\n  for (int i = 1; i <= GetNS(); i++)\n    maxseglen = max2 (maxseglen, GetSegLen (ap, i));\n  \n  int nph = 10+int(maxseglen / minh); //anzahl der integralauswertungen pro segment\n\n  NgArray<double> inthi(GetNS()*nph);\n  NgArray<double> curvelen(GetNS()*nph);\n\n  NgProfiler::StopTimer (timer1a);\n  NgProfiler::StartTimer (timer1b);\n\n\n  for (int i = 1; i <= GetNS(); i++)\n    {\n      //double seglen = GetSegLen(ap,i);\n      for (int j = 1; j <= nph; j++)\n\t{\n\t  p = GetPointInDist(ap,dist,ind);\n\t  //h = GetH(p,dist/len);\n\t  h = mesh.GetH(p);\n\n\t  \n\t  dist += GetSegLen(ap,i)/(double)nph;\n\t  \n\t  inthl += GetSegLen(ap,i)/nph/(h);\n\t  inthi.Elem((i-1)*nph+j) = GetSegLen(ap,i)/nph/h;\n\t  curvelen.Elem((i-1)*nph+j) = GetSegLen(ap,i)/nph;\n\t}\n    }\n\n\n  int inthlint = int(inthl+1);\n\n  if ( (inthlint < 3) && (StartP() == EndP()))\n    {\n      inthlint = 3;\n    }\n  if ( (inthlint == 1) && ShouldSplit())\n    {\n      inthlint = 2; \n    }\n     \n  double fact = inthl/(double)inthlint;\n  dist = 0;\n  int j = 1;\n\n\n  p = ap[StartP()];\n  int pn = AddPointIfNotExists(mp, p, 1e-10*diam);\n\n  int segn = 1;\n  line->AddPoint(pn);\n  line->AddLeftTrig(GetLeftTrig(segn));\n  line->AddRightTrig(GetRightTrig(segn));\n  line->AddDist(dist);\n\n  NgProfiler::StopTimer (timer1b);\n  NgProfiler::StartTimer (timer2);\n\n  inthl = 0; //restart each meshseg\n  for (int i = 1; i <= inthlint; i++)\n    {\n      while (inthl < 1.000000001 && j <= inthi.Size())\n\t{\n\t  inthl += inthi.Get(j)/fact;\n\t  dist += curvelen.Get(j);\n\t  j++;\n\t}\n\n      //went too far:\n      j--;\n      double tofar = (inthl - 1)/inthi.Get(j);\n      inthl -= tofar*inthi.Get(j);\n      dist -= tofar*curvelen.Get(j)*fact;\n\n      if (i == inthlint && fabs(dist - len) >= 1E-8) \n\t{\n\t  PrintSysError(\"meshline failed!!!\"); \n\t}\n\n      if (i != inthlint) \n\t{\n\t  p = GetPointInDist(ap,dist,ind);\n\t  pn = AddPointIfNotExists(mp, p, 1e-10*diam);\n\t  segn = ind;\n\t  line->AddPoint(pn);\n\t  line->AddLeftTrig(GetLeftTrig(segn));\n\t  line->AddRightTrig(GetRightTrig(segn));\n\t  line->AddDist(dist);\n\t}\n\n      inthl = tofar*inthi.Get(j);\n      dist += tofar*curvelen.Get(j)*fact;\n      j++;\n    }\n\n  NgProfiler::StopTimer (timer2);\n  NgProfiler::StartTimer (timer3);\n\n\n  p = ap[EndP()];\n  pn = AddPointIfNotExists(mp, p, 1e-10*diam);\n  segn = GetNS();\n  line->AddPoint(pn);\n  line->AddLeftTrig(GetLeftTrig(segn));\n  line->AddRightTrig(GetRightTrig(segn));\n  line->AddDist(dist);\n  \n  for (int ii = 1; ii <= line->GetNS(); ii++)\n    {\n      int p1, p2;\n      line->GetSeg(ii,p1,p2);\n    }\n  /*  \n  (*testout) << \"line, \" << ap.Get(StartP()) << \"-\" << ap.Get(EndP())\n\t     << \" len = \" << Dist (ap.Get(StartP()), ap.Get(EndP())) << endl;\n  */\n\n  NgProfiler::StopTimer (timer3);\n\n  return line;\n}\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stlline.hpp",
    "content": "#ifndef FILE_STLLINE\n#define FILE_STLLINE\n\n\n/**************************************************************************/\n/* File:   stlline.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Author2: Johannes Gerstmayr                                            */\n/* Date:   20. Nov. 99                                                    */\n/**************************************************************************/\n\nnamespace netgen {\n\nclass STLGeometry;\nclass STLTopology;\n\nclass STLEdge\n{\npublic:\n  int pts[2];\n  int trigs[2]; //left and right trig\n\n  STLEdge (const int * apts) {pts[0] = apts[0]; pts[1] = apts[1];}\n  STLEdge (int v1, int v2) {pts[0] = v1; pts[1] = v2;}\n  STLEdge () {pts[0]=0;pts[1]=0;}\n  int PNum(int i) const {return pts[(i-1)];}\n\n  int LeftTrig() const {return trigs[0];}\n  int RightTrig() const {return trigs[1];}\n  void SetLeftTrig(int i) {trigs[0] = i;}\n  void SetRightTrig(int i) {trigs[1] = i;}\n};\n\nenum STL_ED_STATUS { ED_EXCLUDED, ED_CONFIRMED, ED_CANDIDATE, ED_UNDEFINED };\n                       \n\n/*\n\nclass STLEdgeData\n{\npublic:\n  //  float angle;\n  int p1;\n  int p2;\n  int lt; //left trig\n  int rt; //right trig\n  //  int status;\n\n  STLTopology * top;  // pointer to stl topology\n  int topedgenr;  // number of corresponding topology edge\n\n  STLEdgeData() {}; \n  STLEdgeData(float anglei, int p1i, int p2i, int lti, int rti) \n{\n//     angle = anglei; \np1 = p1i; p2 = p2i;\n      lt = lti; rt = rti;\n    }\n\n  int GetStatus () const;\n  void SetStatus (int stat);\n\n  void SetExcluded() { SetStatus (ED_EXCLUDED); }\n  void SetConfirmed() { SetStatus (ED_CONFIRMED); }\n  void SetCandidate() { SetStatus (ED_CANDIDATE); }\n  void SetUndefined() { SetStatus (ED_UNDEFINED); }\n\n  int Excluded() const {return GetStatus() == ED_EXCLUDED;}\n  int Confirmed() const {return GetStatus() == ED_CONFIRMED;}\n  int Candidate() const {return GetStatus() == ED_CANDIDATE;}\n  int Undefined() const {return GetStatus() == ED_UNDEFINED;}\n  int ConfCand() const {return GetStatus() == ED_CONFIRMED || GetStatus() == ED_CANDIDATE;}\n\n  float CosAngle() const; \n\n  void Write(ofstream& of) const;\n  void Read(ifstream& ifs);\n};\n\nclass STLEdgeDataList\n{\nprivate:\n  INDEX_2_HASHTABLE<int> hashtab;\n  NgArray<STLEdgeData> edgedata;\n  TABLE<int> edgesperpoint;\n  \npublic:\n\n  STLEdgeDataList():edgedata(),hashtab(1),edgesperpoint() {};\n  const STLEdgeDataList& operator=(const STLEdgeDataList& edl); \n  void SetSize(int size) \n    {\n      edgedata.SetSize(size);\n      hashtab.SetSize(size);\n      edgesperpoint.SetSize(size);\n    }\n  void Clear() {SetSize(0);}\n  int Size() const {return edgedata.Size();}\n  const STLEdgeData& Get(int i) const {return edgedata.Get(i);}\n  STLEdgeData& Elem(int i) {return edgedata.Elem(i);}\n  void Add(const STLEdgeData& ed, int i);\n\n  int GetNEPP(int pn) const \n    {\n      return edgesperpoint.EntrySize(pn);\n    };\n  int GetEdgePP(int pn, int vi) const\n    {\n      return edgesperpoint.Get(pn,vi);\n    };\n  void AddEdgePP(int pn, int vn) {edgesperpoint.Add(pn,vn);};\n\n  void ResetAll();\n  void ResetCandidates();\n  void ConfirmCandidates();\n  int GetEdgeNum(int np1, int np2) const;\n\n  int GetNConfEdges() const;\n\n  void Write(ofstream& of) const;\n  void Read(ifstream& ifs);\n\n  void BuildLineWithEdge(int ep1, int ep2, NgArray<twoint>& line);\n\n  int GetNEPPStat(int p, int status) const;\n  int GetNConfCandEPP(int p) const;\n};\n*/\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//a line defined by several points (polyline)\nclass STLLine\n{\nprivate:\n  const STLGeometry * geometry;\n  NgArray<int> pts;\n  NgArray<int> lefttrigs;\n  NgArray<int> righttrigs;\n  NgArray<double> dists;\n  int split;\n\npublic:\n  STLLine(const STLGeometry * ageometry);\n  void AddPoint(int i) {pts.Append(i);}\n  int PNum(int i) const {return pts.Get(i);}\n  int NP() const {return pts.Size();}\n  int GetNS() const;\n  void GetSeg(int nr, int& p1, int& p2) const;\n  double GetSegLen(const Array<Point<3>,STLPointId>& ap, int nr) const;\n  int GetLeftTrig(int nr) const;\n  int GetRightTrig(int nr) const;\n  double GetDist(int nr) const { return dists.Get(nr);};\n  void GetBoundingBox (const Array<Point<3>,STLPointId> & ap, Box<3> & box) const;\n\n  void AddLeftTrig(int nr) {lefttrigs.Append(nr);}\n  void AddRightTrig(int nr) {righttrigs.Append(nr);}\n  void AddDist (double dist) {dists.Append(dist); }\n  int StartP() const {return pts.Get(1);}\n  int EndP() const {return pts.Get(pts.Size());}\n    \n  double GetLength(const Array<Point<3>,STLPointId>& ap) const;\n\n  //suche punkt in entfernung (in linienkoordinaten) dist\n  //in index ist letzter punkt VOR dist (d.h. max pts.Size()-1)\n  Point<3> GetPointInDist(const Array<Point<3>,STLPointId>& ap, double dist, int& index) const;\n\n  //return a meshed polyline\n  STLLine* Mesh(const Array<Point<3>,STLPointId>& ap, \n\t\tNgArray<Point3d>& mp, double ghi,\n\t\tclass Mesh& mesh) const;\n\n  void DoSplit() {split = 1;}\n  int ShouldSplit() const {return split;}\n};\n\n\n} // namespace netgen\n\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/stlpkg.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n\n#include <meshing.hpp>\n\n\n\n#include <inctcl.hpp>\n\n\n\n#include <visual.hpp>\n\n#include <stlgeom.hpp>\n\n#include \"vsstl.hpp\"\n\nextern \"C\" int Ng_STL_Init (Tcl_Interp * interp);\n\n\n\nnamespace netgen\n{\n  DLL_HEADER extern shared_ptr<NetgenGeometry>  ng_geometry;\n  DLL_HEADER extern shared_ptr<Mesh> mesh;\n  DLL_HEADER extern MeshingParameters mparam;\n  DLL_HEADER extern STLParameters stlparam;\n\n  static VisualSceneSTLGeometry vsstlgeom;\n  static VisualSceneSTLMeshing vsstlmeshing;\n\n  char * err_needsstlgeometry = (char*) \"This operation needs an STL geometry\";\n\n\n\n\n\n  class STLGeometryVisRegister : public GeometryRegister\n  {\n  public:\n    virtual NetgenGeometry * Load (const filesystem::path & filename) const { return NULL; }\n    virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;\n    virtual void SetParameters (Tcl_Interp * interp) \n    {\n      stlparam.yangle =\n\tatof (Tcl_GetVar (interp, \"::stloptions.yangle\", 0));\n      stlparam.contyangle =\n\tatof (Tcl_GetVar (interp, \"::stloptions.contyangle\", 0));\n      stlparam.edgecornerangle =\n\tatof (Tcl_GetVar (interp, \"::stloptions.edgecornerangle\", 0));\n      stlparam.chartangle =\n\tatof (Tcl_GetVar (interp, \"::stloptions.chartangle\", 0));\n      stlparam.outerchartangle =\n\tatof (Tcl_GetVar (interp, \"::stloptions.outerchartangle\", 0));\n\n      stlparam.usesearchtree =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.usesearchtree\", 0));\n\n\n      stlparam.atlasminh =\n\tatof (Tcl_GetVar (interp, \"::stloptions.atlasminh\", 0));\n\n      stlparam.resthsurfcurvfac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthsurfcurvfac\", 0));\n      stlparam.resthsurfcurvenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthsurfcurvenable\", 0));\n\n      stlparam.resthatlasfac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthatlasfac\", 0));\n      stlparam.resthatlasenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthatlasenable\", 0));\n\n      stlparam.resthchartdistfac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthchartdistfac\", 0));\n      stlparam.resthchartdistenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthchartdistenable\", 0));\n\n      stlparam.resthlinelengthfac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthlinelengthfac\", 0));\n      stlparam.resthlinelengthenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthlinelengthenable\", 0));\n\n      stlparam.resthedgeanglefac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthedgeanglefac\", 0));\n      stlparam.resthedgeangleenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthedgeangleenable\", 0));\n\n      stlparam.resthsurfmeshcurvfac =\n\tatof (Tcl_GetVar (interp, \"::stloptions.resthsurfmeshcurvfac\", 0));\n      stlparam.resthsurfmeshcurvenable =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.resthsurfmeshcurvenable\", 0));\n\n      stlparam.recalc_h_opt =\n\tatoi (Tcl_GetVar (interp, \"::stloptions.recalchopt\", 0));\n      //  stlparam.Print (cout);      \n    }\n  };\n\n\n\n  int Ng_SetSTLParameters  (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argc, tcl_const char *argv[])\n  {\n    STLGeometryVisRegister reg;\n    reg.SetParameters (interp);\n\n    return TCL_OK;\n  }\n\n  \n\n\n\n\n\n\n  int Ng_STLDoctor (ClientData clientData,\n\t\t    Tcl_Interp * interp,\n\t\t    int argc, tcl_const char *argv[])\n  {\n    //cout << \"STL doctor\" << endl;\n    STLGeometry * stlgeometry = \n          dynamic_cast<STLGeometry*> (ng_geometry.get());\n      \n\n    stldoctor.drawmeshededges =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.drawmeshededges\", 0));\n\n    stldoctor.geom_tol_fact =\n      atof (Tcl_GetVar (interp, \"::stldoctor.geom_tol_fact\", 0));\n\n\n    stldoctor.useexternaledges =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.useexternaledges\", 0));\n\n    stldoctor.showfaces =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showfaces\", 0));\n\n    stldoctor.conecheck =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.conecheck\", 0));\n\n    stldoctor.spiralcheck =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.spiralcheck\", 0));\n\n    stldoctor.selectwithmouse =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.selectwithmouse\", 0));\n\n    stldoctor.showedgecornerpoints =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showedgecornerpoints\", 0));\n\n    stldoctor.showmarkedtrigs =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showmarkedtrigs\", 0));\n\n    stldoctor.showtouchedtrigchart =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showtouchedtrigchart\", 0));\n\n    //cout << \"smt=\" << stldoctor.showmarkedtrigs << endl;\n\n    stldoctor.dirtytrigfact =\n      atof (Tcl_GetVar (interp, \"::stldoctor.dirtytrigfact\", 0));\n\n    stldoctor.smoothnormalsweight =\n      atof (Tcl_GetVar (interp, \"::stldoctor.smoothnormalsweight\", 0));\n\n    stldoctor.smoothangle =\n      atof (Tcl_GetVar (interp, \"::stldoctor.smoothangle\", 0));\n\n    stldoctor.selectmode =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.selectmode\", 0));\n\n    stldoctor.edgeselectmode =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.edgeselectmode\", 0));\n\n    stldoctor.longlinefact =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.longlinefact\", 0));\n\n    stldoctor.showexcluded =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showexcluded\", 0));\n\n\n\n    if (!stldoctor.selectwithmouse)\n      {\n\tstldoctor.selecttrig =\n\t  atoi (Tcl_GetVar (interp, \"::stldoctor.selecttrig\", 0));\n\n\tstldoctor.nodeofseltrig =\n\t  atoi (Tcl_GetVar (interp, \"::stldoctor.nodeofseltrig\", 0));\n      }\n\n    stldoctor.showvicinity =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.showvicinity\", 0));\n\n    stldoctor.vicinity =\n      atoi (Tcl_GetVar (interp, \"::stldoctor.vicinity\", 0));\n\n\n    if (argc >= 2)\n      {\n\tif (!stlgeometry)\n\t  {\n\t    Tcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC);\n\t    return TCL_ERROR;\n\t  }\n\n\tif (strcmp (argv[1], \"destroy0trigs\") == 0)\n\t  {\n\t    stlgeometry->DestroyDirtyTrigs();\n\t  }\n\telse if (strcmp (argv[1], \"movepointtomiddle\") == 0)\n\t  {\n\t    stlgeometry->MoveSelectedPointToMiddle();\n\t  }\n\telse if (strcmp (argv[1], \"calcnormals\") == 0)\n\t  {\n\t    stlgeometry->CalcNormalsFromGeometry();\n\t  }\n\telse if (strcmp (argv[1], \"showchartnum\") == 0)\n\t  {\n\t    stlgeometry->ShowSelectedTrigChartnum();\n\t  }\n\telse if (strcmp (argv[1], \"showcoords\") == 0)\n\t  {\n\t    stlgeometry->ShowSelectedTrigCoords();\n\t  }\n\telse if (strcmp (argv[1], \"loadmarkedtrigs\") == 0)\n\t  {\n\t    stlgeometry->LoadMarkedTrigs();\n\t  }\n\telse if (strcmp (argv[1], \"savemarkedtrigs\") == 0)\n\t  {\n\t    stlgeometry->SaveMarkedTrigs();\n\t  }\n\telse if (strcmp (argv[1], \"neighbourangles\") == 0)\n\t  {\n\t    stlgeometry->NeighbourAnglesOfSelectedTrig();\n\t  }\n\telse if (strcmp (argv[1], \"vicinity\") == 0)\n\t  {\n\t    stlgeometry->CalcVicinity(stldoctor.selecttrig);\n\t  }\n\telse if (strcmp (argv[1], \"markdirtytrigs\") == 0)\n\t  {\n\t    stlgeometry->MarkDirtyTrigs(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"smoothdirtytrigs\") == 0)\n\t  {\n\t    stlgeometry->SmoothDirtyTrigs(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"smoothrevertedtrigs\") == 0)\n\t  {\n\t    stlgeometry->GeomSmoothRevertedTrigs(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"invertselectedtrig\") == 0)\n\t  {\n\t    stlgeometry->InvertTrig(stlgeometry->GetSelectTrig());\n\t  }\n\telse if (strcmp (argv[1], \"deleteselectedtrig\") == 0)\n\t  {\n\t    stlgeometry->DeleteTrig(stlgeometry->GetSelectTrig());\n\t  }\n\telse if (strcmp (argv[1], \"smoothgeometry\") == 0)\n\t  {\n\t    stlgeometry->SmoothGeometry();\n\t  }\n\telse if (strcmp (argv[1], \"orientafterselectedtrig\") == 0)\n\t  {\n\t    stlgeometry->OrientAfterTrig(stlgeometry->GetSelectTrig());\n\t  }\n\telse if (strcmp (argv[1], \"marktoperrortrigs\") == 0)\n\t  {\n\t    stlgeometry->MarkTopErrorTrigs();\n\t  }\n\telse if (strcmp (argv[1], \"exportedges\") == 0)\n\t  {\n\t    stlgeometry->ExportEdges();\n\t  }\n\telse if (strcmp (argv[1], \"importedges\") == 0)\n\t  {\n\t    stlgeometry->ImportEdges();\n\t  }\n\telse if (strcmp (argv[1], \"importexternaledges\") == 0)\n\t  {\n\t    stlgeometry->ImportExternalEdges(argv[2]);\n\t  }\n\telse if (strcmp (argv[1], \"loadedgedata\") == 0)\n\t  {\n\t    if (argc >= 3)\n\t      {\n\t\tstlgeometry->LoadEdgeData(argv[2]);\n\t      }\n\t  }\n\telse if (strcmp (argv[1], \"saveedgedata\") == 0)\n\t  {\n\t    if (argc >= 3)\n\t      {\n\t\tstlgeometry->SaveEdgeData(argv[2]);\n\t      }\n\t  }\n\n\telse if (strcmp (argv[1], \"buildexternaledges\") == 0)\n\t  {\n\t    stlgeometry->BuildExternalEdgesFromEdges();\n\t  }\n\telse if (strcmp (argv[1], \"smoothnormals\") == 0)\n\t  {\n\t    stlgeometry->SmoothNormals(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"marknonsmoothnormals\") == 0)\n\t  {\n\t    stlgeometry->MarkNonSmoothNormals(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"addexternaledge\") == 0)\n\t  {\n\t    stlgeometry->AddExternalEdgeAtSelected();\n\t  }\n\telse if (strcmp (argv[1], \"addgeomline\") == 0)\n\t  {\n\t    stlgeometry->AddExternalEdgesFromGeomLine();\n\t  }\n\telse if (strcmp (argv[1], \"addlonglines\") == 0)\n\t  {\n\t    stlgeometry->AddLongLinesToExternalEdges();\n\t  }\n\telse if (strcmp (argv[1], \"addclosedlines\") == 0)\n\t  {\n\t    stlgeometry->AddClosedLinesToExternalEdges();\n\t  }\n\telse if (strcmp (argv[1], \"addnotsinglelines\") == 0)\n\t  {\n\t    stlgeometry->AddAllNotSingleLinesToExternalEdges();\n\t  }\n\telse if (strcmp (argv[1], \"deletedirtyexternaledges\") == 0)\n\t  {\n\t    stlgeometry->DeleteDirtyExternalEdges();\n\t  }\n\telse if (strcmp (argv[1], \"deleteexternaledge\") == 0)\n\t  {\n\t    stlgeometry->DeleteExternalEdgeAtSelected();\n\t  }\n\telse if (strcmp (argv[1], \"deletevicexternaledge\") == 0)\n\t  {\n\t    stlgeometry->DeleteExternalEdgeInVicinity();\n\t  }\n\n\telse if (strcmp (argv[1], \"addlonglines\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorLongLinesToCandidates();\n\t  }\n\telse if (strcmp (argv[1], \"deletedirtyedges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorDirtyEdgesToCandidates();\n\t  }\n\telse if (strcmp (argv[1], \"undoedgechange\") == 0)\n\t  {\n\t    stlgeometry->UndoEdgeChange();\n\t  }\n\telse if (strcmp (argv[1], \"buildedges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorBuildEdges(stlparam);\n\t  }\n\telse if (strcmp (argv[1], \"confirmedge\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorConfirmEdge();\n\t  }\n\telse if (strcmp (argv[1], \"candidateedge\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorCandidateEdge();\n\t  }\n\telse if (strcmp (argv[1], \"excludeedge\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorExcludeEdge();\n\t  }\n\telse if (strcmp (argv[1], \"undefinededge\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorUndefinedEdge();\n\t  }\n\telse if (strcmp (argv[1], \"setallundefinededges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorSetAllUndefinedEdges();\n\t  }\n\telse if (strcmp (argv[1], \"erasecandidateedges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorEraseCandidateEdges();\n\t  }\n\telse if (strcmp (argv[1], \"confirmcandidateedges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorConfirmCandidateEdges();\n\t  }\n\telse if (strcmp (argv[1], \"confirmedtocandidateedges\") == 0)\n\t  {\n\t    stlgeometry->STLDoctorConfirmedToCandidateEdges();\n\t  }\n\telse if (strcmp (argv[1], \"writechart\") == 0)\n\t  {\n            int st = stlgeometry->GetSelectTrig();\n\n            if (st >= 1 && st <= stlgeometry->GetNT() && stlgeometry->AtlasMade())\n            {\n              auto chartnumber = stlgeometry->GetChartNr(st);\n              stlgeometry->WriteChartToFile(chartnumber, \"chart.stlb\");\n            }\n\t  }\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  int Ng_STLInfo  (ClientData clientData,\n\t\t   Tcl_Interp * interp,\n\t\t   int argc, tcl_const char *argv[])\n  {\n    double data[10];\n    static char buf[20];\n\n    STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry.get());\n\n    if (!stlgeometry)\n      {\n\tTcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n\n    if (stlgeometry)\n      {\n\tstlgeometry->STLInfo(data);\n\t//      cout << \"NT=\" << data[0] << endl;\n\n\tif (argc == 2)\n\t  {\n\t    if (strcmp (argv[1], \"status\") == 0)\n\t      {\n\t\tswitch (stlgeometry->GetStatus())\n\t\t  {\n\t\t  case STLGeometry::STL_GOOD:\n\t\t    strcpy (buf, \"GOOD\"); break;\n\t\t  case STLGeometry::STL_WARNING:\n\t\t    strcpy (buf, \"WARNING\"); break;\n\t\t  case STLGeometry::STL_ERROR:\n\t\t    strcpy (buf, \"ERROR\"); break;\n\t\t  }\n\t\tTcl_SetResult (interp, buf, TCL_STATIC);\n\t\treturn TCL_OK;\n\t      }\n\t    if (strcmp (argv[1], \"statustext\") == 0)\n\t      {\n\t\tTcl_SetResult (interp, (char*)stlgeometry->GetStatusText().c_str(), TCL_STATIC);\n\t\treturn TCL_OK;\n\t      }\n\t    if (strcmp (argv[1], \"topology_ok\") == 0)\n\t      {\n\t\tsnprintf (buf, size(buf), \"%d\", stlgeometry->Topology_Ok());\n\t\tTcl_SetResult (interp, buf, TCL_STATIC);\n\t      }\n\t    if (strcmp (argv[1], \"orientation_ok\") == 0)\n\t      {\n\t\tsnprintf (buf, size(buf), \"%d\", stlgeometry->Orientation_Ok());\n\t\tTcl_SetResult (interp, buf, TCL_STATIC);\n\t      }\n\t  }\n      }\n    else\n      {\n\tdata[0] = 0;\n\tdata[1] = 0;\n\tdata[2] = 0;\n\tdata[3] = 0;\n\tdata[4] = 0;\n\tdata[5] = 0;\n\tdata[6] = 0;\n\tdata[7] = 0;\n      }\n\n\n\n\n    snprintf (buf, size(buf), \"%i\", (int)data[0]);\n    Tcl_SetVar (interp, argv[1], buf, 0);\n\n    snprintf (buf, size(buf), \"%5.3g\", data[1]);\n    Tcl_SetVar (interp, argv[2], buf, 0);\n    snprintf (buf, size(buf), \"%5.3g\", data[2]);\n    Tcl_SetVar (interp, argv[3], buf, 0);\n    snprintf (buf, size(buf), \"%5.3g\", data[3]);\n    Tcl_SetVar (interp, argv[4], buf, 0);\n\n    snprintf (buf, size(buf), \"%5.3g\", data[4]);\n    Tcl_SetVar (interp, argv[5], buf, 0);\n    snprintf (buf, size(buf), \"%5.3g\", data[5]);\n    Tcl_SetVar (interp, argv[6], buf, 0);\n    snprintf (buf, size(buf), \"%5.3g\", data[6]);\n    Tcl_SetVar (interp, argv[7], buf, 0);\n\n    snprintf (buf, size(buf), \"%i\", (int)data[7]);\n    Tcl_SetVar (interp, argv[8], buf, 0);\n\n    return TCL_OK;\n  }\n\n\n\n  extern int Ng_SetMeshingParameters  (ClientData clientData,\n\t\t\t\t       Tcl_Interp * interp,\n\t\t\t\t       int argc, tcl_const char *argv[]);\n\n  int Ng_STLCalcLocalH  (ClientData clientData,    \n\t\t\t Tcl_Interp * interp,\n\t\t\t int argc, tcl_const char *argv[])\n  {\n    for (auto loader : GeometryRegister())\n      loader -> SetParameters (interp);\n\n\n    Ng_SetMeshingParameters (clientData, interp, argc, argv);\n\n    STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry.get());\n    if (mesh && stlgeometry)\n      {\n\tmesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\n\t\t\t   stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\n\t\t\t   mparam.grading);\n\tstlgeometry -> RestrictLocalH(*mesh, mparam.maxh, stlparam, mparam);\n\n\tif (stlparam.resthsurfmeshcurvenable)\n\t  mesh -> CalcLocalHFromSurfaceCurvature (mparam.grading, \n\t\t\t\t\t\t  stlparam.resthsurfmeshcurvfac);\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n  VisualScene * STLGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const\n  {\n    const STLGeometry * geometry = dynamic_cast<const STLGeometry*> (geom);\n    if (geometry)\n      {\n\tvsstlmeshing.SetGeometry (const_cast<STLGeometry*> (geometry));\n\treturn &vsstlmeshing;\n      }\n    return NULL;\n  }\n}\n\n\nusing namespace netgen;\n\nextern \"C\" int Ng_stl_Init (Tcl_Interp * interp);\nint Ng_stl_Init (Tcl_Interp * interp)\n{\n  GeometryRegister().Append (new STLGeometryVisRegister);\n\n  Tcl_CreateCommand (interp, \"Ng_SetSTLParameters\", Ng_SetSTLParameters,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n  \n  Tcl_CreateCommand (interp, \"Ng_STLDoctor\", Ng_STLDoctor,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  Tcl_CreateCommand (interp, \"Ng_STLInfo\", Ng_STLInfo,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n  \n  Tcl_CreateCommand (interp, \"Ng_STLCalcLocalH\", Ng_STLCalcLocalH,\n\t\t     (ClientData)NULL,\n\t\t     (Tcl_CmdDeleteProc*) NULL);\n\n  \n  return TCL_OK;\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stltool.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n#include \"stlgeom.hpp\"\n\nnamespace netgen\n{\n\n\n//add a point into a pointlist, return pointnumber\nint AddPointIfNotExists(NgArray<Point3d>& ap, const Point3d& p, double eps)\n{\n  double eps2 = sqr(eps);\n  for (int i = 1; i <= ap.Size(); i++)\n    if (Dist2(ap.Get(i),p) <= eps2 ) \n      return i;\n  ap.Append(p);\n  return ap.Size();\n}\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\ndouble GetDistFromLine(const Point<3> & lp1, const Point<3> & lp2, \n\t\t       Point<3> & p)\n{\n  Vec3d vn = lp2 - lp1;\n  Vec3d v1 = p - lp1;\n  Vec3d v2 = lp2 - p;\n\n  Point3d pold = p;\n\n  if (v2 * vn <= 0) {p = lp2; return (pold - p).Length();}\n  if (v1 * vn <= 0) {p = lp1; return (pold - p).Length();}\n    \n  double vnl = vn.Length();\n  if (vnl == 0) {return Dist(lp1,p);}\n\n  vn /= vnl;\n  p = lp1 + (v1 * vn) * vn;\n  return (pold - p).Length();\n};\n\ndouble GetDistFromInfiniteLine(const Point<3>& lp1, const Point<3>& lp2, const Point<3>& p)\n{\n  Vec3d vn(lp1, lp2);\n  Vec3d v1(lp1, p);\n\n  double vnl = vn.Length();\n\n  if (vnl == 0)\n    {\n      return Dist (lp1, p);\n    }\n  else\n    {\n      return Cross (vn, v1).Length() / vnl;\n    }\n};\n\n\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n//Binary IO-Manipulation\n\n\n\nvoid FIOReadInt(istream& ios, int& i)\n{\n  const int ilen = sizeof(int);\n  \n  char buf[ilen];\n  for (int j = 0; j < ilen; j++)\n    ios.get(buf[j]);\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteInt(ostream& ios, const int& i)\n{\n  const int ilen = sizeof(int);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  for (int j = 0; j < ilen; j++)\n    ios << buf[j];\n}\n\nvoid FIOReadDouble(istream& ios, double& i)\n{\n  const int ilen = sizeof(double);\n  \n  char buf[ilen];\n  for (int j = 0; j < ilen; j++)\n    ios.get(buf[j]);\n\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteDouble(ostream& ios, const double& i)\n{\n  const int ilen = sizeof(double);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  for (int j = 0; j < ilen; j++)\n    ios << buf[j];\n}\n\nvoid FIOReadFloat(istream& ios, float& i)\n{\n  const int ilen = sizeof(float);\n  \n  char buf[ilen];\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios.get(buf[j]);\n    }\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteFloat(ostream& ios, const float& i)\n{\n  const int ilen = sizeof(float);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  for (int j = 0; j < ilen; j++)\n    ios << buf[j];\n}\n\nvoid FIOReadString(istream& ios, char* str, int len)\n{\n  for (int j = 0; j < len; j++)\n    ios.get(str[j]);\n}\n\n//read string and add terminating 0\nvoid FIOReadStringE(istream& ios, char* str, int len)\n{\n  for (int j = 0; j < len; j++)\n    ios.get(str[j]);\n  str[len] = 0;\n}\n\nvoid FIOWriteString(ostream& ios, char* str, int len)\n{\n  for (int j = 0; j < len; j++)\n    ios << str[j];\n}\n\n\n/*\nvoid FIOReadInt(istream& ios, int& i)\n{\n  const int ilen = sizeof(int);\n  \n  char buf[ilen];\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios.get(buf[ilen-j-1]);\n    }\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteInt(ostream& ios, const int& i)\n{\n  const int ilen = sizeof(int);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios << buf[ilen-j-1];\n    }\n}\n\nvoid FIOReadDouble(istream& ios, double& i)\n{\n  const int ilen = sizeof(double);\n  \n  char buf[ilen];\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios.get(buf[ilen-j-1]);\n    }\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteDouble(ostream& ios, const double& i)\n{\n  const int ilen = sizeof(double);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios << buf[ilen-j-1];\n    }\n}\n\nvoid FIOReadFloat(istream& ios, float& i)\n{\n  const int ilen = sizeof(float);\n  \n  char buf[ilen];\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios.get(buf[ilen-j-1]);\n    }\n  memcpy(&i, &buf, ilen);\n}\n\nvoid FIOWriteFloat(ostream& ios, const float& i)\n{\n  const int ilen = sizeof(float);\n  \n  char buf[ilen];\n  memcpy(&buf, &i, ilen);\n\n  int j;\n  for (j = 0; j < ilen; j++)\n    {\n      ios << buf[ilen-j-1];\n    }\n}\n\nvoid FIOReadString(istream& ios, char* str, int len)\n{\n  int j;\n  for (j = 0; j < len; j++)\n    {\n      ios.get(str[j]);\n    }\n}\n\n//read string and add terminating 0\nvoid FIOReadStringE(istream& ios, char* str, int len)\n{\n  int j;\n  for (j = 0; j < len; j++)\n    {\n      ios.get(str[j]);\n    }\n  str[len] = 0;\n}\n\nvoid FIOWriteString(ostream& ios, char* str, int len)\n{\n  int j;\n  for (j = 0; j < len; j++)\n    {\n      ios << str[j];\n    }\n}\n*/\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nSTLReadTriangle :: STLReadTriangle (const Point<3> * apts,\n\t\t\t\t    const Vec<3> & anormal)\n{\n  pts[0] = apts[0];\n  pts[1] = apts[1];\n  pts[2] = apts[2]; \n  normal = anormal;\n}\n\n\n\nSTLTriangle :: STLTriangle(const STLPointId * apts)\n{\n  pts[0] = apts[0];\n  pts[1] = apts[1];\n  pts[2] = apts[2];\n\n  facenum = 0;\n}\n\nint STLTriangle :: IsNeighbourFrom(const STLTriangle& t) const\n{\n  //triangles must have same orientation!!!\n\n  for(int i = 0; i <= 2; i++)\n    for(int j = 0; j <= 2; j++)\n      if (t.pts[(i+1)%3] == pts[j] && \n\t  t.pts[i] == pts[(j+1)%3])\n\n\treturn 1;\n\n  return 0;      \n}\n\nint STLTriangle :: IsWrongNeighbourFrom(const STLTriangle& t) const\n{\n  //triangles have not same orientation!!!\n  for(int i = 0; i <= 2; i++)\n    for(int j = 0; j <= 2; j++)\n      if (t.pts[(i+1)%3] == pts[(j+1)%3] &&\n\t  t.pts[i] == pts[j])\n\t\n\treturn 1;\n\n  return 0;      \n}\n\nvoid STLTriangle :: GetNeighbourPoints(const STLTriangle& t, STLPointId & p1, STLPointId & p2) const\n{\n  for(int i = 1; i <= 3; i++)\n    for(int j = 1; j <= 3; j++)\n      if (t.PNumMod(i+1) == PNumMod(j) &&\n\t  t.PNumMod(i) == PNumMod(j+1))\n\t{\n\t  p1 = PNumMod(j); \n\t  p2 = PNumMod(j+1); \n\t  return;\n\t}\n\n  PrintSysError(\"Get neighbourpoints failed!\");\n}\n\nint STLTriangle :: GetNeighbourPointsAndOpposite(const STLTriangle& t, STLPointId & p1,\n                                                 STLPointId & p2, STLPointId & po) const\n{\n  for(int i = 1; i <= 3; i++)\n    for(int j = 1; j <= 3; j++)\n      if (t.PNumMod(i+1) == PNumMod(j) &&\n\t  t.PNumMod(i) == PNumMod(j+1))\n\t{\n\t  p1 = PNumMod(j); \n\t  p2 = PNumMod(j+1); \n\t  po = PNumMod(j+2); \n\t  return 1;\n\t}\n  \n  return 0;\n}\n\nVec<3> STLTriangle :: GeomNormal(const Array<Point<3>,STLPointId>& ap) const\n{\n  const Point<3> & p1 = ap[PNum(1)];\n  const Point<3> & p2 = ap[PNum(2)];\n  const Point<3> & p3 = ap[PNum(3)];\n  \n  return Cross(p2-p1, p3-p1);\n}\n\n\nvoid STLTriangle :: SetNormal (const Vec<3> & n)\n{\n  double len = n.Length();\n  if (len > 0)\n    {\n      normal = n;\n      normal.Normalize();\n    }\n  else\n    {\n      normal = Vec<3> (1, 0, 0);\n    }\n}\n\n\nvoid STLTriangle :: ChangeOrientation()\n{ \n  normal *= -1;\n  Swap(pts[0],pts[1]); \n}\n\n\n\ndouble STLTriangle :: Area(const Array<Point<3>,STLPointId>& ap) const\n{\n  return 0.5 * Cross(ap[PNum(2)]-ap[PNum(1)], \n\t\t     ap[PNum(3)]-ap[PNum(1)]).Length();\n}\n\ndouble STLTriangle :: MinHeight(const Array<Point<3>,STLPointId>& ap) const\n{\n  double ml = MaxLength(ap);\n  if (ml != 0) {return 2.*Area(ap)/ml;}\n  PrintWarning(\"max Side Length of a triangle = 0!!!\");\n  return 0;\n}\n\ndouble STLTriangle :: MaxLength(const Array<Point<3>,STLPointId>& ap) const\n{\n  return max3(Dist(ap[PNum(1)],ap[PNum(2)]),\n\t      Dist(ap[PNum(2)],ap[PNum(3)]),\n\t      Dist(ap[PNum(3)],ap[PNum(1)]));\n}\n\nvoid STLTriangle :: ProjectInPlain(const Array<Point<3>,STLPointId>& ap, \n\t\t\t\t   const Vec<3> & n, Point<3> & pp) const\n{\n  const Point<3> & p1 = ap[PNum(1)];\n  const Point<3> & p2 = ap[PNum(2)];\n  const Point<3> & p3 = ap[PNum(3)];\n  \n  Vec<3> v1 = p2 - p1;\n  Vec<3> v2 = p3 - p1;\n  Vec<3> nt = Cross(v1, v2);\n\n  double c = - (p1(0)*nt(0) + p1(1)*nt(1) + p1(2)*nt(2));\n\n  double prod = n * nt;  \n\n  if (fabs(prod) == 0) \n    {\n      pp = Point<3>(1.E20,1.E20,1.E20); \n      return; \n    }\n\n  double nfact = -(pp(0)*nt(0) + pp(1)*nt(1) + pp(2)*nt(2) + c) / (prod);\n  pp = pp + (nfact) * n;\n\n}\n\n\nint STLTriangle :: ProjectInPlain (const Array<Point<3>,STLPointId>& ap, \n\t\t\t\t   const Vec<3> & nproj, \n\t\t\t\t   Point<3> & pp, Vec<3> & lam) const\n{\n  const Point<3> & p1 = ap[PNum(1)];\n  const Point<3> & p2 = ap[PNum(2)];\n  const Point<3> & p3 = ap[PNum(3)];\n  \n  Vec<3> v1 = p2-p1;\n  Vec<3> v2 = p3-p1;\n\n  Mat<3> mat;\n  for (int i = 0; i < 3; i++)\n    {\n      mat(i,0) = v1(i);\n      mat(i,1) = v2(i);\n      mat(i,2) = nproj(i);\n    }\n\n  int err = 0;\n  mat.Solve (pp-p1, lam);\n  //  int err = SolveLinearSystem (v1, v2, nproj, pp-p1, lam);\n\n  if (!err)\n    {\n      //      pp = p1 + lam(0) * v1 + lam(1) * v2;\n\n      pp(0) = p1(0) + lam(0) * v1(0) + lam(1) * v2(0);\n      pp(1) = p1(1) + lam(0) * v1(1) + lam(1) * v2(1);\n      pp(2) = p1(2) + lam(0) * v1(2) + lam(1) * v2(2);\n    }\n  return err;\n}\n\n\n\n\n\nvoid STLTriangle :: ProjectInPlain(const Array<Point<3>,STLPointId>& ap, \n\t\t\t\t   Point<3> & pp) const\n{\n  const Point<3> & p1 = ap[PNum(1)];\n  const Point<3> & p2 = ap[PNum(2)];\n  const Point<3> & p3 = ap[PNum(3)];\n  \n  Vec<3> v1 = p2 - p1;\n  Vec<3> v2 = p3 - p1;\n  Vec<3> nt = Cross(v1, v2);\n\n  double c = - (p1(0)*nt(0) + p1(1)*nt(1) + p1(2)*nt(2));\n  \n  double prod = nt * nt;  \n\n  double nfact = -(pp(0)*nt(0) + pp(1)*nt(1) + pp(2)*nt(2) + c) / (prod);\n\n  pp = pp + (nfact) * nt;\n}\n\nbool STLTriangle :: PointInside(const Array<Point<3>,STLPointId> & ap, \n\t\t\t       const Point<3> & pp) const\n{\n  const Point<3> & p1 = ap[PNum(1)];\n  const Point<3> & p2 = ap[PNum(2)];\n  const Point<3> & p3 = ap[PNum(3)];\n  \n  Vec<3> v1 = p2 - p1;\n  Vec<3> v2 = p3 - p1;\n  Vec<3> v  = pp - p1;\n  double det, l1, l2;\n  Vec<3> ex, ey, ez;\n\n\n  ez = GeomNormal(ap);\n  ez /= ez.Length();\n  ex = v1;\n  ex /= ex.Length();\n  ey = Cross (ez, ex);\n  \n  Vec<2> v1p(v1*ex, v1*ey);\n  Vec<2> v2p(v2*ex, v2*ey);\n  Vec<2> vp(v*ex, v*ey);\n\n  det = v2p(1) * v1p(0) - v2p(0) * v1p(1);\n\n  if (fabs(det) == 0) {return 0;}\n  \n  l2 = (vp(1) * v1p(0) - vp(0) * v1p(1)) / det;\n  \n  if (v1p(0) != 0.)\n    {\n      l1 = (vp(0) - l2 * v2p(0)) / v1p(0);\n    }\n  else if (v1p(1) != 0.)\n    {\n      l1 = (vp(1) - l2 * v2p(1)) / v1p(1);\n    }\n  else {return 0;}\n  \n  if (l1 >= -1E-10 && l2 >= -1E-10 && l1 + l2 <= 1.+1E-10) {return 1;}\n  return 0; \n}\n\ndouble STLTriangle :: GetNearestPoint(const Array<Point<3>,STLPointId>& ap, \n\t\t\t\t      Point<3> & p3d) const\n{\n  Point<3> p = p3d;\n  ProjectInPlain(ap, p);\n  double dist = (p - p3d).Length();\n\n  if (PointInside(ap, p)) {p3d = p; return dist;}\n  else\n    {\n      Point<3> pf = 0.0;\n      double nearest = 1E50;\n      //int fi = 0;\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  p = p3d;\n\t  dist = GetDistFromLine(ap[PNum(j)], ap[PNumMod(j+1)], p);\n\t  if (dist < nearest)\n\t    {\n\t      nearest = dist; \n\t      pf = p;\n\t    }\n\t}\n      p3d = pf;\n      return nearest;\n    }\n}\n\nbool STLTriangle :: HasEdge(STLPointId p1, STLPointId p2) const\n{\n  for (int i = 1; i <= 3; i++)\n    if (p1 == PNum(i) && p2 == PNumMod(i+1))\n      return true;\n  return false;\n}\n\nostream& operator<<(ostream& os, const STLTriangle& t)\n{\n  os << \"[\";\n  os << t[0] << \",\";\n  os << t[1] << \",\";\n  os << t[2] << \"]\";\n\n  return os;\n};\n\n\n\nSTLTopEdge :: STLTopEdge ()\n{\n  pts[0] = pts[1] = 0;\n  trigs[0] = trigs[1] = 0;\n  cosangle = 1;\n  status = ED_UNDEFINED;\n}\n\nSTLTopEdge :: STLTopEdge (STLPointId p1, STLPointId p2, int trig1, int trig2)\n{ \n  pts[0] = p1; \n  pts[1] = p2; \n  trigs[0] = trig1; \n  trigs[1] = trig2; \n  cosangle = 1;\n  status = ED_UNDEFINED;\n}\n\n\n\n\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n//+++++++++++++++++++   STL CHART   +++++++++++++++++++++++++++++++\n//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nSTLChart :: STLChart(STLGeometry * ageometry, const STLParameters& astlparam)\n    : geometry(ageometry), stlparam(astlparam)\n{\n  // charttrigs = new NgArray<int> (0,0);\n  // outertrigs = new NgArray<int> (0,0);\n  // ilimit = new NgArray<twoint> (0,0);\n  // olimit = new NgArray<twoint> (0,0);\n\n  geometry = ageometry;\n\n  if ( stlparam.usesearchtree == 1)\n    {\n      Box<3> box = geometry->GetBoundingBox();\n      box.Increase (0.2*box.Diam()+1e-12);\n      searchtree = new BoxTree<3,STLTrigId> (box);\n      /*\n      searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),\n                                   geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));\n      */\n    }\n  else\n    searchtree = NULL;\n}\n\nSTLChart :: ~STLChart()\n{\n  delete searchtree;\n}\n\nvoid STLChart :: AddChartTrig(STLTrigId i)\n{\n  // static int timer = NgProfiler::CreateTimer (\"STLChart::AddChartTrig\");\n  // NgProfiler::RegionTimer reg(timer);\n  \n  charttrigs.Append(i);\n  \n  const STLTriangle & trig = geometry->GetTriangle(i);\n  const Point<3> & p1 = geometry->GetPoint (trig.PNum(1));\n  const Point<3> & p2 = geometry->GetPoint (trig.PNum(2));\n  const Point<3> & p3 = geometry->GetPoint (trig.PNum(3));\n\n  /*\n  Point3d pmin(p1), pmax(p1);\n  pmin.SetToMin (p2);\n  pmin.SetToMin (p3);\n  pmax.SetToMax (p2);\n  pmax.SetToMax (p3);\n  */\n  /*\n  Box<3> box(p1);\n  box.Add(p2);\n  box.Add(p3);\n  */\n  Box<3> box(p1,p2,p3);\n  if (!geomsearchtreeon && (stlparam.usesearchtree == 1))\n    // {searchtree->Insert (pmin, pmax, i);}\n    {\n      searchtree->Insert (box, i);\n    }\n}\n\nvoid STLChart :: AddOuterTrig(STLTrigId i)\n{\n  // static int timer = NgProfiler::CreateTimer (\"STLChart::AddOuterTrig\");\n  // NgProfiler::RegionTimer reg(timer);\n  \n  outertrigs.Append(i);\n\n  const STLTriangle & trig = geometry->GetTriangle(i);\n  const Point3d & p1 = geometry->GetPoint (trig.PNum(1));\n  const Point3d & p2 = geometry->GetPoint (trig.PNum(2));\n  const Point3d & p3 = geometry->GetPoint (trig.PNum(3));\n\n  Point3d pmin(p1), pmax(p1);\n  pmin.SetToMin (p2);\n  pmin.SetToMin (p3);\n  pmax.SetToMax (p2);\n  pmax.SetToMax (p3);\n  \n  if (!geomsearchtreeon && (stlparam.usesearchtree==1))\n    {searchtree->Insert (pmin, pmax, i);}\n}\n\nbool STLChart :: IsInWholeChart(int nr) const\n{\n  return charttrigs.Contains(nr) || outertrigs.Contains(nr);\n}\n\nvoid STLChart :: GetTrianglesInBox (const Point3d & pmin,\n\t\t\t\t    const Point3d & pmax,\n\t\t\t\t    NgArray<STLTrigId> & trias) const\n{\n  if (geomsearchtreeon) {PrintMessage(5,\"geomsearchtreeon is set!!!\");}\n\n  if (searchtree)\n    searchtree -> GetIntersecting (pmin, pmax, trias);\n  else\n    {\n      Box<3> box1(pmin, pmax);\n      box1.Increase (1e-2*box1.Diam());\n\n      trias.SetSize(0);\n      \n      int nt = GetNT();\n      for (int i = 1; i <= nt; i++)\n\t{\n\t  STLTrigId trignum = GetTrig1(i);\n\t  const STLTriangle & trig = geometry->GetTriangle(trignum);\n          Box<3> box2(geometry->GetPoint (trig.PNum(1)),\n                      geometry->GetPoint (trig.PNum(2)),\n                      geometry->GetPoint (trig.PNum(3)));\n\t  \n\t  if (box1.Intersect (box2))\n\t    trias.Append (trignum);\n\t}\n    }\n}\n\n//trigs may contain the same triangle double\nvoid STLChart :: MoveToOuterChart(const NgArray<int>& trigs)\n{\n  if (!trigs.Size()) return;\n  for (int i = 1; i <= trigs.Size(); i++)\n    {\n      if (charttrigs[trigs.Get(i)-1] != -1) \n\tAddOuterTrig(charttrigs[trigs.Get(i)-1]);\n      charttrigs[trigs.Get(i)-1] = -1;\n    }\n  DelChartTrigs(trigs);\n}\n\n//trigs may contain the same triangle double\nvoid STLChart :: DelChartTrigs(const NgArray<int>& trigs)\n{\n  if (!trigs.Size()) return;\n\n  for (int i = 1; i <= trigs.Size(); i++)\n    charttrigs[trigs.Get(i)-1] = -1;\n\n  int cnt = 0;\n  for (int i = 1; i <= charttrigs.Size(); i++)\n    {\n      if (charttrigs[i-1] == -1)\n        cnt++;\n      if (cnt != 0 && i < charttrigs.Size())\n        charttrigs[i-cnt] = charttrigs[i];\n    }\n  \n  int i = charttrigs.Size() - trigs.Size();\n  charttrigs.SetSize(i);\n\n  if (!geomsearchtreeon && stlparam.usesearchtree == 1)\n    {\n      PrintMessage(7, \"Warning: unsecure routine due to first use of searchtrees!!!\");\n      //bould new searchtree!!!\n      searchtree = new BoxTree<3,STLTrigId> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),\n                                             geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));\n\n      for (int i = 1; i <= charttrigs.Size(); i++)\n\t{\n\t  const STLTriangle & trig = geometry->GetTriangle(i);\n\t  const Point3d & p1 = geometry->GetPoint (trig.PNum(1));\n\t  const Point3d & p2 = geometry->GetPoint (trig.PNum(2));\n\t  const Point3d & p3 = geometry->GetPoint (trig.PNum(3));\n\t  \n\t  Point3d pmin(p1), pmax(p1);\n\t  pmin.SetToMin (p2);\n\t  pmin.SetToMin (p3);\n\t  pmax.SetToMax (p2);\n\t  pmax.SetToMax (p3);\n\t  \n\t  searchtree->Insert (pmin, pmax, i);\n\t}\n    }\n}\n\n\nvoid STLChart :: SetNormal (const Point<3> & apref, const Vec<3> & anormal)\n{\n  pref = apref;\n  normal = anormal;\n  double len = normal.Length();\n  if (len) normal /= len;\n  else normal = Vec<3> (1, 0, 0);\n\n  t1 = normal.GetNormal ();\n  t2 = Cross (normal, t1);\n}\n\nvoid STLChart :: BuildInnerSearchTree()\n{\n  Box<2> chart_bbox(Box<2>::EMPTY_BOX);\n  for (STLTrigId trigid : charttrigs)\n    {\n      for (STLPointId pi : (*geometry)[trigid].PNums())\n        {\n          Point<3> p = (*geometry)[pi];\n          Point<2> p2d = Project2d(p);\n          chart_bbox.Add(p2d);\n        }\n    }\n  chart_bbox.Increase (1e-2*chart_bbox.Diam());\n  inner_searchtree = make_unique<BoxTree<2,STLTrigId>> (chart_bbox);\n  for (STLTrigId trigid : charttrigs)\n    {\n      Box<2> bbox(Box<2>::EMPTY_BOX);      \n      for (STLPointId pi : (*geometry)[trigid].PNums())\n        {\n          Point<3> p = (*geometry)[pi];\n          Point<2> p2d = Project2d(p);\n          bbox.Add(p2d);\n        }\n      inner_searchtree->Insert (bbox, trigid);\n    }\n}\n\nSTLTrigId STLChart :: ProjectNormal (Point<3> & p3d) const\n{\n  \n  int nt = GetNT();\n  double lamtol = 1e-6;\n  QuadraticFunction3d quadfun(p3d, GetNormal());\n\n  int starttrig = 1;\n  if (inner_searchtree)\n    {\n      starttrig = GetNChartT()+1;\n      Point<2> p2d = Project2d (p3d);\n\n\n      bool inside = false;\n      STLTrigId trignum;\n      inner_searchtree->GetFirstIntersecting(p2d, p2d, [&](auto i)\n        {\n          auto & trig = geometry->GetTriangle(i);\n          const Point<3> & c = trig.center;\n          \n          if (quadfun.Eval(c) > sqr (trig.rad))\n            return false;\n          \n          Point<3> p = p3d;\n          Vec<3> lam;\n          int err = trig.ProjectInPlain(geometry->GetPoints(), GetNormal(), p, lam);\n          inside = (err == 0 && lam(0) > -lamtol &&\n                         lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);\n          \n          if (inside)\n            {\n              trignum=i;\n              p3d = p;\n              return true;\n            }\n          return false;\n        });\n\n      if(inside)\n          return trignum;\n    }\n  \n  \n  for (int j = starttrig; j <= nt; j++)\n    {\n      STLTrigId i = GetTrig1(j);\n      auto & trig = geometry->GetTriangle(i);\n      const Point<3> & c = trig.center;\n\n      if (quadfun.Eval(c) > sqr (trig.rad))\n\tcontinue;\n\n      Point<3> p = p3d;\n      Vec<3> lam;\n      int err = trig.ProjectInPlain(geometry->GetPoints(), GetNormal(), p, lam);      \n      bool inside = (err == 0 && lam(0) > -lamtol && \n                     lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);\n\n      if (inside)\n        {\n          p3d = p;\n          return i;\n        }\n    }\n\n  return 0;\n}\n\n\n\n/*\nPoint<2> STLChart :: Project2d (const Point<3> & p3d) const\n{\n  Vec<3> v = p3d-pref;\n  return Point<2> (t1 * v, t2 * v);\n}\n*/\n\n\n\n/*\n  Point3d p1, p2, center;\n  double rad;\n  int i1, i2;\npublic:\n*/\n\n/*\nSTLBoundarySeg :: \nSTLBoundarySeg (int ai1, int ai2, const NgArray<Point<3> > & points,\n\t\tconst STLChart * chart)\n{\n  i1 = ai1;\n  i2 = ai2; \n  p1 = points.Get(i1);\n  p2 = points.Get(i2);\n  center = ::netgen::Center (p1, p2);\n  rad = Dist (p1, center);\n\n  p2d1 = chart->Project2d (p1);\n  p2d2 = chart->Project2d (p2);\n  \n  boundingbox.Set (p2d1);\n  boundingbox.Add (p2d2);\n}\n*/\n\nvoid STLBoundarySeg :: Swap ()\n{\n  ::netgen::Swap (i1, i2);\n  ::netgen::Swap (p1, p2);\n}\n\n\n\nSTLBoundary :: STLBoundary (STLGeometry * ageometry)\n  : geometry(ageometry)\n{ ; }\n\n\n/*\nvoid STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg)\n{\n  bool found = false;\n  for (int i = 1; i <= boundary.Size(); i++)\n    {\n      if (found) { boundary.Elem(i-1) = boundary.Get(i); }\n      if (boundary.Get(i) == seg) { found = true; }\n    }\n  if (!found) \n    {\n      boundary.Append(seg);\n    }\n  else \n    {\n      boundary.SetSize(boundary.Size()-1);\n    }\n}\n*/\n\nvoid STLBoundary ::AddTriangle(const STLTriangle & t)\n{\n  // static Timer timer(\"STLBoundary::AddTriangle\"); RegionTimer reg(timer);\n  // static int timer_old = NgProfiler::CreateTimer (\"STLChart::AddTriangle_old\");\n  // static int timer_new = NgProfiler::CreateTimer (\"STLChart::AddTriangle_new\");\n\n  // NgProfiler::StartTimer (timer_old);\n\n#ifdef ADDTRIGOLD\n  int i;\n  int found1 = 0;\n  int found2 = 0;\n  int found3 = 0;\n  //int offset = 0;\n  \n\n  STLBoundarySeg seg1(t[0],t[1], geometry->GetPoints(), chart);\n  STLBoundarySeg seg2(t[1],t[2], geometry->GetPoints(), chart);\n  STLBoundarySeg seg3(t[2],t[0], geometry->GetPoints(), chart);\n\n  seg1.SetSmoothEdge (geometry->IsSmoothEdge (seg1.I1(), seg1.I2()));\n  seg2.SetSmoothEdge (geometry->IsSmoothEdge (seg2.I1(), seg2.I2()));\n  seg3.SetSmoothEdge (geometry->IsSmoothEdge (seg3.I1(), seg3.I2()));\n\n  /*\n  for (i = 1; i <= boundary.Size(); i++)\n    {\n      if (offset) {boundary.Elem(i-offset) = boundary.Get(i);}\n      if (boundary.Get(i) == seg1) {found1 = 1; offset++;}\n      if (boundary.Get(i) == seg2) {found2 = 1; offset++;}\n      if (boundary.Get(i) == seg3) {found3 = 1; offset++;}\n    }\n\n  if (offset)\n    {\n      boundary.SetSize(boundary.Size()-offset);\n    }    \n  */\n  for (i = boundary.Size(); i >= 1; i--)\n    {\n      if (boundary.Get(i) == seg1) \n\t{ boundary.DeleteElement (i); found1 = 1; } \n      else if (boundary.Get(i) == seg2) \n\t{ boundary.DeleteElement (i); found2 = 1; } \n      else if (boundary.Get(i) == seg3) \n\t{ boundary.DeleteElement (i); found3 = 1; } \n    }\n\n  if (!found1)\n    {\n      seg1.Swap();\n      boundary.Append(seg1);      \n      /*\n      int newnr;\n      if (freelist.Size())\n        {\n          newnr = freelist.Last();\n          freelist.DeleteLast();\n          boundary[newnr] = seg1;\n        }\n      else\n        {\n          boundary.Append(seg1);\n          newnr = boundary.Size();\n        }\n      // cout << \"tree add el \" << boundary.Size() << endl;\n      if (searchtree)\n        {\n          // cout << \"add \" << boundary.Size() << endl;\n          searchtree->Insert (seg1.BoundingBox(), newnr);\n        }\n      */\n    }\n  \n  if (!found2)\n    {\n      seg2.Swap();\n      boundary.Append(seg2);\n      /*\n      int newnr;\n      if (freelist.Size())\n        {\n          newnr = freelist.Last();\n          freelist.DeleteLast();\n          boundary[newnr] = seg2;\n        }\n      else\n        {\n          boundary.Append(seg2);\n          newnr = boundary.Size();\n        }\n      \n      // boundary.Append(seg2);\n      // cout << \"tree add el \" << boundary.Size() << endl;\n      if (searchtree)\n        {\n          // cout << \"add \" << boundary.Size() << endl;\n          searchtree->Insert (seg2.BoundingBox(), newnr);\n        }\n      */\n    }\n  if (!found3)\n    {\n      seg3.Swap();\n      boundary.Append(seg3);      \n      /*\n      int newnr;\n      if (freelist.Size())\n        {\n          newnr = freelist.Last();\n          freelist.DeleteLast();\n          boundary[newnr] = seg3;\n        }\n      else\n        {\n          boundary.Append(seg3);\n          newnr = boundary.Size();\n        }\n      \n      // cout << \"tree add el \" << boundary.Size() << endl;\n      if (searchtree)                            \n        {\n          // cout << \"add \" << boundary.Size() << endl;\n          searchtree->Insert (seg3.BoundingBox(), newnr);\n        }\n      */\n    }\n#endif\n  \n  // NgProfiler::StopTimer (timer_old);  \n\n  // NgProfiler::StartTimer (timer_new);\n\n  INDEX_2 segs[3];\n  segs[0] = INDEX_2(t[0], t[1]);\n  segs[1] = INDEX_2(t[1], t[2]);\n  segs[2] = INDEX_2(t[2], t[0]);\n\n  if(!searchtree)\n      BuildSearchTree();\n\n  for (auto seg : segs)\n    {\n      STLBoundarySeg bseg(seg[0], seg[1], geometry->GetPoints(), chart);\n      bseg.SetSmoothEdge (geometry->IsSmoothEdge (seg[0],seg[1]));\n      \n      INDEX_2 op(seg[1], seg[0]);\n      if (boundary_ht.Used(op))\n        {\n          boundary_ht.Delete(op);\n          if (searchtree)\n            searchtree->DeleteElement(op);\n        }\n      else\n        {\n          boundary_ht[seg] = bseg;\n          if (searchtree)          \n            searchtree->Insert (bseg.BoundingBox(), seg);\n        }\n    }\n}\n\nbool STLBoundary :: TestSeg(const Point<3>& p1, const Point<3> & p2, const Vec<3> & sn, \n                            double sinchartangle, int divisions, Array<Point<3>,STLPointId>& points, double eps)\n{\n  if (usechartnormal)\n    return TestSegChartNV (p1, p2, sn);\n\n#ifdef NONE\n  // for statistics\n  {\n    int i;\n    static NgArray<int> cntclass;\n    static int cnt = 0;\n    static int cnti = 0, cnto = 0;\n    static long int cntsegs = 0;\n    if (cntclass.Size() == 0)\n      {\n\tcntclass.SetSize (20);\n\tfor (i = 1; i <= cntclass.Size(); i++)\n\t  cntclass.Elem(i) = 0;\n      }\n    \n    cntsegs += NOSegments();\n    int cla = int (log (double(NOSegments()+1)) / log(2.0));\n    if (cla < 1) cla = 1;\n    if (cla > cntclass.Size()) cla = cntclass.Size();\n    cntclass.Elem(cla)++;\n    cnt++;\n    if (divisions)\n      cnti++;\n    else\n      cnto++;\n    if (cnt > 100000) \n      {\n\tcnt = 0;\n\t/*\n\t(*testout) << \"TestSeg-calls for classes:\" << endl;\n\t(*testout) << cnti << \" inner calls, \" << cnto << \" outercalls\" << endl;\n\t(*testout) << \"total tested segments: \" << cntsegs << endl;\n\tfor (i = 1; i <= cntclass.Size(); i++)\n\t  {\n\t    (*testout) << int (exp (i * log(2.0))) << \" bnd segs: \" << cntclass.Get(i) << endl;\n\t  }\n\t*/\n      }\n  }\n#endif\n\n  int i,k;\n  Point<3> seg1p/*, seg2p*/;\n  Point<3> sp1,sp2;\n  double lambda1, lambda2, vlen2;\n  Vec<3> vptpl;\n  double sinchartangle2 = sqr(sinchartangle);\n  double scal;\n  int possible;\n\n  //double maxval = -1;\n  //double maxvalnew = -1;\n\n\n\n  double scalp1 = p1(0) * sn(0) + p1(1) * sn(1) + p1(2) * sn(2);\n  double scalp2 = p2(0) * sn(0) + p2(1) * sn(1) + p2(2) * sn(2);\n  double minl = min2(scalp1, scalp2);\n  double maxl = max2(scalp1, scalp2);\n  Point<3> c = Center (p1, p2);\n  double dist1 = Dist (c, p1);\n\n  /*\n  int nseg = NOSegments();\n  for (j = 1; j <= nseg; j++)\n    {\n      const STLBoundarySeg & seg = GetSegment(j);\n  */\n  for(auto [i2, seg] : boundary_ht)\n    { \n\n      if (seg.IsSmoothEdge())\n\tcontinue;\n\n\n      sp1 = seg.P1();\n      sp2 = seg.P2();\n\n      // Test, ob Spiral Konfikt moeglich\n      \n      possible = 1;\n\n      double scalsp1 = sp1(0) * sn(0) + sp1(1) * sn(1) + sp1(2) * sn(2);\n      double scalsp2 = sp2(0) * sn(0) + sp2(1) * sn(1) + sp2(2) * sn(2);\n\n      double minsl = min2(scalsp1, scalsp2);\n      double maxsl = max2(scalsp1, scalsp2);\n      \n      double maxdiff = max2 (maxsl - minl, maxl - minsl);\n      \n      /*\n      Point3d sc = Center (sp1, sp2);\n      double mindist = Dist(c, sc) - dist1 - GetSegment(j).Radius();\n      if (maxdiff < sinchartangle * mindist)\n\t{\n\t  possible = 0;\n\t}\n      */\n       \n      double hscal = maxdiff + sinchartangle * (dist1 + seg.Radius());\n      if (hscal * hscal < sinchartangle * Dist2(c, seg.center ))\n\tpossible = 0;\n\n\n      /*      \n      if (possible)\n\t{\n\t  double mindist2ex = MinDistLL2 (p1, p2, sp1, sp2);\n\t  if (maxdiff * maxdiff < sinchartangle2 * mindist2ex)\n\t    possible = 0;\n\t}\n      */\n\n      if (possible)\n      \t{\n\t  LinearPolynomial2V lp (scalp1 - scalsp1,\n\t\t\t\t scalp2 - scalp1,\n\t\t\t\t -(scalsp2 - scalsp1));\n\t  QuadraticPolynomial2V slp;\n\t  slp.Square (lp);\n\t  \n      \n\t  Vec3d v (p1, sp1);\n\t  Vec3d vl (p1, p2);\n\t  Vec3d vsl (sp1, sp2);\n      \n\t  QuadraticPolynomial2V qp (v.Length2(),\n\t\t\t\t    -2 * (v * vl),\n\t\t\t\t    2 * (v * vsl),\n\t\t\t\t    vl.Length2(),\n\t\t\t\t    -2 * (vl * vsl),\n\t\t\t\t    vsl.Length2());\n\t  \n\t  slp.Add (-sinchartangle2, qp);\n\n\t  double hv = slp.MaxUnitSquare();\n\n\t  if (hv > eps) return 0;\n\t  /*\n\t  if (hv > maxvalnew)\n\t    maxvalnew = hv;\n\t  */\n\t}\n      \n\n      // if (possible && 0)\n      if (false)\n\n\tfor (i = 0; i <= divisions; i++)\n\t  {\n\t    \n\t    lambda1 = (double)i/(double)divisions;\n\t    seg1p = Point3d(p1(0)*lambda1+p2(0)*(1.-lambda1),\n\t\t\t    p1(1)*lambda1+p2(1)*(1.-lambda1),\n\t\t\t    p1(2)*lambda1+p2(2)*(1.-lambda1));\n\t    \n\n\t    \n\t    for (k = 0; k <= divisions; k++)\n\t      {\n\t\tlambda2 = (double)k/(double)divisions;\n\t\tvptpl = Vec3d(sp1(0)*lambda2+sp2(0)*(1.-lambda2)-seg1p(0),\n\t\t\t      sp1(1)*lambda2+sp2(1)*(1.-lambda2)-seg1p(1),\n\t\t\t      sp1(2)*lambda2+sp2(2)*(1.-lambda2)-seg1p(2));\n\t\t\n\t\tvlen2 = vptpl.Length2();\n\n\t\t//\t\tif (vlen2 > 0)\n\t\t  {\n\t\t    scal = vptpl * sn;\n\t\t    double hv = scal*scal - sinchartangle2*vlen2;\n\n\n\n\t\t    /*\n\t\t    if (hv > maxval)\n\t\t      maxval = hv;\n\t\t    */\n\t\t    if (hv > eps) return 0;\n\t\t  }\n\t      } \n\t  }\n    }\n  \n  return 1;\n  //  return (maxvalnew < eps);\n}\n\nvoid STLBoundary :: BuildSearchTree()\n{\n  Box<2> box2d(Box<2>::EMPTY_BOX);\n  Box<3> box3d = geometry->GetBoundingBox();\n\n  for (size_t i = 0; i < 8; i++)\n    box2d.Add ( chart->Project2d (box3d.GetPointNr(i)));\n\n  searchtree = make_unique<BoxTree<2,INDEX_2>> (box2d);\n//   searchtree = nullptr;\n}\n\nvoid STLBoundary :: DeleteSearchTree()\n{\n  searchtree = nullptr;\n}\n\n\n// checks, whether 2d projection intersects\nbool STLBoundary :: TestSegChartNV(const Point3d & p1, const Point3d& p2, \n\t\t\t\t  const Vec3d& sn)\n{\n  //  static int timerquick = NgProfiler::CreateTimer (\"TestSegChartNV-searchtree\");\n  // static Timer timer(\"TestSegChartNV\");  RegionTimer reg(timer);      \n  \n\n  Point<2> p2d1 = chart->Project2d (p1);\n  Point<2> p2d2 = chart->Project2d (p2);\n\n  Box<2> box2d;\n  box2d.Set (p2d1);\n  box2d.Add (p2d2);\n\n  Line2d l1 (p2d1, p2d2);\n\n  double eps = 1e-6;\n\n  auto hasIntersection = [&] (auto i2) NETGEN_LAMBDA_INLINE\n    {\n      const STLBoundarySeg & seg = boundary_ht[i2];\n\n      if (seg.IsSmoothEdge()) return false;\n      if (!box2d.Intersect (seg.BoundingBox())) return false;\n\n      const Point<2> & sp1 = seg.P2D1();\n      const Point<2> & sp2 = seg.P2D2();\n\n      Line2d l2 (sp1, sp2);\n      double lam1, lam2;\n\n      int err = CrossPointBarycentric (l1, l2, lam1, lam2, eps);\n      bool in1 = (lam1 > eps) && (lam1 < 1-eps);\n      bool on1 = (lam1 > -eps) && (lam1 < 1 + eps);\n      bool in2 = (lam2 > eps) && (lam2 < 1-eps);\n      bool on2 = (lam2 > -eps) && (lam2 < 1 + eps);\n\n      if(!err && ((on1 && in2) || (on2 && in1)))\n          return true;\n      return false;\n    };\n\n  if (searchtree)\n    {\n      bool has_intersection = false;\n      searchtree -> GetFirstIntersecting (box2d.PMin(), box2d.PMax(),\n              [&] (auto i2) NETGEN_LAMBDA_INLINE\n              {\n                  has_intersection = hasIntersection(i2);\n                  return has_intersection;\n              });\n      return !has_intersection;\n    }\n  else\n    {\n      for(auto [i2, seg] : boundary_ht)\n        if(hasIntersection(i2))\n              return false;\n      return true;\n    }\n}\n\n\n\nSTLDoctorParams :: STLDoctorParams()\n{\n  drawmeshededges = 1;\n  geom_tol_fact = 1E-6;\n  longlinefact = 0;\n  showexcluded = 1;\n\n  selectmode = 0;\n  edgeselectmode = 0;\n  useexternaledges = 0;\n  showfaces = 0;\n  showtouchedtrigchart = 1;\n  showedgecornerpoints = 1;\n  conecheck = 1;\n  spiralcheck = 1;\n  selecttrig = 0;\n  nodeofseltrig = 1;\n  selectwithmouse = 1;\n  showmarkedtrigs = 1;\n  dirtytrigfact = 0.001;\n  smoothangle = 90;\n  smoothnormalsweight = 0.2;\n  vicinity = 0;\n  showvicinity = 0;\n}\n\n\n\nSTLDoctorParams stldoctor;\n\nvoid STLDoctorParams :: Print (ostream & ost) const\n{\n  ost << \"STL doctor parameters:\" << endl\n      << \"selecttrig = \" << selecttrig << endl\n      << \"selectlocalpoint = \" << nodeofseltrig << endl\n      << \"selectwithmouse = \" << selectwithmouse << endl\n      << \"showmarkedtrigs = \" << showmarkedtrigs << endl\n      << \"dirtytrigfact = \" << dirtytrigfact << endl\n      << \"smoothangle = \" << smoothangle << endl;\n}\n\n\nSTLParameters ::   STLParameters()\n{\n  yangle = 30;\n  contyangle = 20;\n  edgecornerangle = 60;\n  chartangle = 15;\n  outerchartangle = 70;\n     \n  usesearchtree = 0;\n  atlasminh = 1E-4;\n  resthsurfcurvfac = 2;\n  resthsurfcurvenable = 0;\n  resthatlasfac = 2;\n  resthatlasenable = 1;\n  resthchartdistfac = 1.2;\n  resthchartdistenable = 1;\n  resthlinelengthfac = 0.5;\n  resthlinelengthenable = 1;\n  // resthcloseedgefac = 1;\n  // resthcloseedgeenable = 1;\n  resthedgeanglefac = 1;\n  resthedgeangleenable = 0;\n  resthsurfmeshcurvfac = 1;\n  resthsurfmeshcurvenable = 0;\n  recalc_h_opt = 1;\n}\n\nvoid STLParameters :: Print (ostream & ost) const\n{\n  ost << \"STL parameters:\" << endl\n      << \"yellow angle = \" << yangle << endl\n      << \"continued yellow angle = \" << contyangle << endl\n      << \"edgecornerangle = \" << edgecornerangle << endl\n      << \"chartangle = \" << chartangle << endl\n      << \"outerchartangle = \" << outerchartangle << endl\n      << \"restrict h due to ..., enable and safety factor: \" << endl\n      << \"surface curvature: \" << resthsurfcurvenable\n      << \", fac = \" << resthsurfcurvfac << endl\n      << \"atlas surface curvature: \" << resthatlasenable\n      << \", fac = \" << resthatlasfac << endl\n      << \"chart distance: \" << resthchartdistenable\n      << \", fac = \" << resthchartdistfac << endl\n      << \"line length: \" << resthlinelengthenable\n      << \", fac = \" << resthlinelengthfac << endl\n      // << \"close edges: \" << resthcloseedgeenable\n      // << \", fac = \" << resthcloseedgefac << endl\n      << \"edge angle: \" << resthedgeangleenable\n      << \", fac = \" << resthedgeanglefac << endl;\n}\n\n\nDLL_HEADER extern STLParameters stlparam;\nSTLParameters stlparam;\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stltool.hpp",
    "content": "#ifndef FILE_STLTOOL\n#define FILE_STLTOOL\n\n//#include \"gprim/gprim.hh\"\n\n/**************************************************************************/\n/* File:   stlgeom.hh                                                     */\n/* Author: Joachim Schoeberl                                              */\n/* Author2: Johannes Gerstmayr                                            */\n/* Date:   20. Nov. 99                                                    */\n/**************************************************************************/\n\nnamespace netgen {\n\n// use one normal vector for whole chart\nextern int usechartnormal;\nextern int chartdebug;\n\nextern int geomsearchtreeon;\nextern int AddPointIfNotExists(NgArray<Point3d>& ap, const Point3d& p, double eps = 1e-8);\n//get distance from line lp1-lp2 to point p\nextern double GetDistFromLine(const Point<3>& lp1, const Point<3>& lp2, Point<3>& p);\nextern double GetDistFromInfiniteLine(const Point<3>& lp1, const Point<3>& lp2, const Point<3>& p);\n\n\nextern void FIOReadInt(istream& ios, int& i);\nextern void FIOWriteInt(ostream& ios, const int& i);\nextern void FIOReadDouble(istream& ios, double& i);\nextern void FIOWriteDouble(ostream& ios, const double& i);\nextern void FIOReadFloat(istream& ios, float& i);\nextern void FIOWriteFloat(ostream& ios, const float& i);\nextern void FIOReadString(istream& ios, char* str, int len);\nextern void FIOReadStringE(istream& ios, char* str, int len);\nextern void FIOWriteString(ostream& ios, char* str, int len);\n\n\ntypedef NgArray <int> * ArrayINTPTR;\n\nclass STLGeometry;\nclass STLParameters;\n\n// typedef int ChartId\nclass ChartId\n{\n  int i;\npublic:\n  class t_invalid { public: constexpr t_invalid() = default; };\n  static constexpr t_invalid INVALID{};\n  \n  ChartId() { }\n  constexpr ChartId(t_invalid inv) : i(0) { ; }\n  constexpr ChartId(int ai) : i(ai) { } \n  operator int() const { return i; }\n  ChartId operator++ (int) { ChartId hi(*this); i++; return hi; }\n  ChartId & operator++ () { i++; return *this; }\n};\n}\n\nnamespace ngcore\n{\n  template<> \n  constexpr netgen::ChartId IndexBASE<netgen::ChartId> () { return netgen::ChartId(1); }\n}\n\n\nnamespace netgen  {\n  \nclass STLChart\n{\nprivate:\n  STLGeometry * geometry;\n  Array<STLTrigId> charttrigs; // trigs which only belong to this chart\n  Array<STLTrigId> outertrigs; // trigs which belong to other charts\n  BoxTree<3,STLTrigId> * searchtree; // ADT containing outer trigs\n\n  NgArray<twoint> olimit; //outer limit of outer chart\n  NgArray<twoint> ilimit; //outer limit of inner chart\n  const STLParameters& stlparam;\n\n\npublic:\n  \n  STLChart(STLGeometry * ageometry, const STLParameters& astlparam);\n  ~STLChart();\n  void AddChartTrig(STLTrigId i);\n  void AddOuterTrig(STLTrigId i);\n  \n  bool IsInWholeChart(int nr) const;\n\n  STLTrigId GetChartTrig1(int i) const {return charttrigs[i-1];}\n  STLTrigId GetOuterTrig1(int i) const {return outertrigs[i-1];}\n  //get all trigs:\n  STLTrigId GetTrig1(int i) const\n    {\n      if (i <= charttrigs.Size()) {return charttrigs[i-1];}\n      else {return outertrigs[i-charttrigs.Size()-1];}\n    }\n  \n  size_t GetNChartT() const {return charttrigs.Size();}\n  size_t GetNOuterT() const {return outertrigs.Size();}\n  size_t GetNT() const {return charttrigs.Size()+outertrigs.Size(); }\n\n  void GetTrianglesInBox (const Point3d & pmin,\n\t\t\t  const Point3d & pmax,\n\t\t\t  NgArray<STLTrigId> & trias) const;\n  void AddOLimit(twoint l) {olimit.Append(l);}\n  void AddILimit(twoint l) {ilimit.Append(l);}\n\n  void ClearOLimit() {olimit.SetSize(0);}\n  void ClearILimit() {ilimit.SetSize(0);}\n\n  size_t GetNOLimit() const {return olimit.Size();}\n  size_t GetNILimit() const {return ilimit.Size();}\n\n  twoint GetOLimit(int i) const {return olimit.Get(i);}\n  twoint GetILimit(int i) const {return ilimit.Get(i);}\n\n  //move triangles trigs (local chart-trig numbers) to outer chart\n  void MoveToOuterChart(const NgArray<int>& trigs);\n  void DelChartTrigs(const NgArray<int>& trigs);\n\n\n  // define local coordinate system, JS:\nprivate:\n  Vec<3> normal;\n  Point<3> pref;\n  Vec<3> t1, t2;\n  unique_ptr<BoxTree<2,STLTrigId>> inner_searchtree;\npublic:\n  void SetNormal (const Point<3> & apref, const Vec<3> & anormal);\n  const Vec<3> & GetNormal () const { return normal; }\n  Point<2> Project2d (const Point<3> & p3d) const\n  {\n    Vec<3> v = p3d-pref;\n    return Point<2> (t1 * v, t2 * v);\n  }\n  void BuildInnerSearchTree();\n  STLTrigId ProjectNormal (Point<3> & p) const;\n};\n\nclass STLBoundarySeg\n{\n  Point<3> p1, p2, center;\n  Point<2> p2d1, p2d2;\n  Box<2> boundingbox;\n\n  double rad;\n  STLPointId i1, i2;\n  bool smoothedge;\npublic:\n  STLBoundarySeg () { ; }\n  STLBoundarySeg (STLPointId ai1, STLPointId ai2, const Array<Point<3>,STLPointId> & points,\n\t\t  const STLChart * chart)\n    : p1(points[ai1]), p2(points[ai2]),\n      i1(ai1), i2(ai2)\n  {\n    center = ::netgen::Center (p1, p2);\n    rad = Dist (p1, center);\n    \n    p2d1 = chart->Project2d (p1);\n    p2d2 = chart->Project2d (p2);\n    \n    boundingbox.Set (p2d1);\n    boundingbox.Add (p2d2);\n  }\n\n  int operator== (const STLBoundarySeg & s2) const\n    { return i1 == s2.i1 && i2 == s2.i2; }\n  void Swap ();\n  STLPointId I1() const { return i1; }\n  STLPointId I2() const { return i2; }\n  const Point<3> & P1() const { return p1; }\n  const Point<3> & P2() const { return p2; }\n  const Point<2> & P2D1() const { return p2d1; }\n  const Point<2> & P2D2() const { return p2d2; }\n  const Point<2> & P2DMin() const { return boundingbox.PMin(); }\n  const Point<2> & P2DMax() const { return boundingbox.PMax(); }\n  const Point<3> & Center() const { return center; }\n  const Box<2> & BoundingBox() const { return boundingbox; }\n  double Radius () const { return rad; }\n\n  void SetSmoothEdge (bool se) { smoothedge = se; }\n  bool IsSmoothEdge () const { return smoothedge; }\n  friend class STLBoundary;\n};\n\nclass STLBoundary\n{\nprivate:\n  STLGeometry * geometry;\n  const STLChart * chart;\n  // NgArray<STLBoundarySeg> boundary;\n  NgClosedHashTable<INDEX_2, STLBoundarySeg> boundary_ht;\n  unique_ptr<BoxTree<2,INDEX_2>> searchtree;\npublic:\n  STLBoundary(STLGeometry * ageometry);\n  ~STLBoundary() {}\n\n  void Clear() { /* boundary.SetSize(0); */ boundary_ht = NgClosedHashTable<INDEX_2,STLBoundarySeg>(); }\n  void SetChart (const STLChart * achart) { chart = achart; }\n  //don't check, if already exists!\n  // void AddNewSegment(const STLBoundarySeg & seg) {boundary.Append(seg);};\n  //check if segment exists\n  // void AddOrDelSegment(const STLBoundarySeg & seg);\n  //addordelsegment for all 3 triangle segments!\n  void AddTriangle(const STLTriangle & t);\n  int NOSegments() {return boundary_ht.UsedElements();};\n  // const STLBoundarySeg & GetSegment(int i) {return boundary.Get(i);}\n\n  void BuildSearchTree();\n  void DeleteSearchTree();\n  bool TestSeg(const Point<3> & p1, const Point<3> & p2, const Vec<3> & sn, \n               double sinchartangle, int divisions, Array<Point<3>,STLPointId>& points,\n               double eps);\n  \n  bool TestSegChartNV(const Point3d& p1, const Point3d& p2, const Vec3d& sn);\n};\n\n\nclass STLDoctorParams\n{\npublic:\n  int drawmeshededges;\n  double geom_tol_fact;\n\n  double longlinefact;\n  int showexcluded;\n\n  int selectmode; //0==trig, 1==edge, 2==point, 3==multiedge, 4==line cluster\n  int edgeselectmode;\n\n  int useexternaledges;\n  int showfaces;\n  int showedgecornerpoints;\n  int showtouchedtrigchart;\n  int conecheck;\n  int spiralcheck;\n  int selecttrig;\n  int nodeofseltrig;\n  int selectwithmouse;\n  int showmarkedtrigs;\n  double dirtytrigfact;\n  double smoothangle;\n\n  double smoothnormalsweight;\n\n  int showvicinity;\n  int vicinity;\n  ///\n  STLDoctorParams();\n  ///\n  void Print (ostream & ost) const;\n};\n\nDLL_HEADER extern STLDoctorParams stldoctor;\n\n\n\n// TODO change enable flag to optional parameters\nclass DLL_HEADER STLParameters\n{\npublic:\n  /// angle for edge detection\n  double yangle = 30.;\n  double contyangle = 20.; //edges continued with contyangle\n  /// angle of geometry edge at which the mesher should set a point\n  double edgecornerangle = 60.;\n  /// angle inside on chart\n  double chartangle = 15.;\n  /// angle for overlapping parts of char\n  double outerchartangle = 70.;\n  /// 0 .. no, 1 .. local, (2 .. global)\n  int usesearchtree = 0;\n  ///\n  double resthatlasfac = 2.; \n  bool resthatlasenable = true;\n  double atlasminh = 0.1;\n\n  double resthsurfcurvfac = 2.; \n  bool resthsurfcurvenable = false;\n\n  double resthchartdistfac = 1.2;\n  bool resthchartdistenable = true;\n\n  // double resthcloseedgefac = 1.;\n  // bool resthcloseedgeenable = true;\n  \n  double resthedgeanglefac = 1.;\n  bool resthedgeangleenable = false;\n  \n  double resthsurfmeshcurvfac = 1.;\n  bool resthsurfmeshcurvenable = false;\n  \n  double resthlinelengthfac = 0.5;\n  bool resthlinelengthenable = true;\n\n  ///\n  bool recalc_h_opt = true;\n  ///\n  STLParameters();\n  ///\n  void Print (ostream & ost) const;\n};\n\ninline ostream & operator<< (ostream & ost, const STLParameters & stlparam)\n  {\n    stlparam.Print (ost);\n    return ost;\n  }\n\n\n\nvoid STLMeshing (STLGeometry & geom,\n\t\t Mesh & mesh,\n                 const MeshingParameters& mparam,\n                 const STLParameters& stlpar);\n\n\nint STLSurfaceMeshing (STLGeometry & geom,\n                       Mesh & mesh,\n                       const MeshingParameters& mparam,\n                       const STLParameters& stlpar);\n\nvoid STLSurfaceOptimization (STLGeometry & geom,\n\t\t\t     Mesh & mesh,\n\t\t\t     const MeshingParameters & mparam);\n\n\n} // namespace netgen\n\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/stltopology.cpp",
    "content": "#include <mystdlib.h>\n#include <core/register_archive.hpp>\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n\n#include <meshing.hpp>\n\n#include \"stlgeom.hpp\"\n#include <vector>\n#include <cctype>\n\nnamespace netgen\n{\n\n\n  STLTopology :: STLTopology()\n  : trias(), topedges(), points(), ht_topedges(NULL), \n    trigsperpoint(), neighbourtrigs()\n{\n  ;\n}\n\nSTLTopology :: ~STLTopology()\n{\n  ;\n}\n\n\n\n\nSTLGeometry *  STLTopology :: LoadBinary (istream & ist)\n{\n  STLGeometry * geom = new STLGeometry();\n  NgArray<STLReadTriangle> readtrigs;\n\n  PrintMessage(1,\"Read STL binary file\");\n  \n  if (sizeof(int) != 4 || sizeof(float) != 4) \n    {\n      PrintWarning(\"for stl-binary compatibility only use 32 bit compilation!!!\");\n    }\n\n  //specific settings for stl-binary format\n  const int namelen = 80; //length of name of header in file\n  const int nospaces = 2; //number of spaces after a triangle\n\n  //read header: name\n  char buf[namelen+1];\n  FIOReadStringE(ist,buf,namelen);\n  PrintMessage(5,\"header = \",buf);\n\n  //Read Number of facets\n  int nofacets;\n  FIOReadInt(ist,nofacets);\n  PrintMessage(5,\"NO facets = \",nofacets);\n\n  Point<3> pts[3];\n  Vec<3> normal;\n\n  char spaces[nospaces+1];\n\n  for (int cntface = 0; cntface < nofacets; cntface++)\n    {\n      if (cntface % 10000 == 0)\n\t// { PrintDot(); } \n\tPrintMessageCR (3, cntface, \" triangles loaded\\r\");\n\n      float f;\n      FIOReadFloat(ist,f); normal(0) = f;\n      FIOReadFloat(ist,f); normal(1) = f;\n      FIOReadFloat(ist,f); normal(2) = f;\n      \n      for (int j = 0; j < 3; j++)\n\t{\n\t  FIOReadFloat(ist,f); pts[j](0) = f;\n\t  FIOReadFloat(ist,f); pts[j](1) = f;\n\t  FIOReadFloat(ist,f); pts[j](2) = f;\t  \n\t} \n\n      readtrigs.Append (STLReadTriangle (pts, normal));\n      FIOReadString(ist,spaces,nospaces);\n    }\t    \n  PrintMessage (3, nofacets, \" triangles loaded\\r\");  \n\n  geom->InitSTLGeometry(readtrigs);\n\n  return geom;\n}\n\n\nvoid STLTopology :: SaveBinary (const filesystem::path & filename, const char* aname) const\n{\n  ofstream ost(filename);\n  PrintFnStart(\"Write STL binary file '\",filename,\"'\");\n\n  if (sizeof(int) != 4 || sizeof(float) != 4) \n    {PrintWarning(\"for stl-binary compatibility only use 32 bit compilation!!!\");}\n\n  //specific settings for stl-binary format\n  const int namelen = 80; //length of name of header in file\n  const int nospaces = 2; //number of spaces after a triangle\n\n  //write header: aname\n  int i, j;\n  char buf[namelen+1];\n  int strend = 0;\n  for(i = 0; i <= namelen; i++) \n    {\n      if (aname[i] == 0) {strend = 1;}\n      if (!strend) {buf[i] = aname[i];}\n      else {buf[i] = 0;}\n    }\n\n  FIOWriteString(ost,buf,namelen);\n  PrintMessage(5,\"header = \",buf);\n\n  //RWrite Number of facets\n  int nofacets = GetNT();\n  FIOWriteInt(ost,nofacets);\n  PrintMessage(5,\"NO facets = \", nofacets);\n\n  float f;\n  char spaces[nospaces+1];\n  for (i = 0; i < nospaces; i++) {spaces[i] = ' ';}\n  spaces[nospaces] = 0;\n\n  for (i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & t = GetTriangle(i);\n\n      const Vec<3> & n = t.Normal();\n      f = n(0); FIOWriteFloat(ost,f);\n      f = n(1); FIOWriteFloat(ost,f);\n      f = n(2); FIOWriteFloat(ost,f);\n\n      for (j = 1; j <= 3; j++)\n\t{\n\t  const Point3d p = GetPoint(t.PNum(j));\n\t  \n\t  f = p.X(); FIOWriteFloat(ost,f);\n\t  f = p.Y(); FIOWriteFloat(ost,f);\n\t  f = p.Z(); FIOWriteFloat(ost,f);\n\t}\n      FIOWriteString(ost,spaces,nospaces);\n    }\n  PrintMessage(5,\"done\");\n}\n\n\nvoid STLTopology :: SaveSTLE (const filesystem::path & filename) const\n{\n  ofstream outf (filename);\n  int i, j;\n  \n  outf << GetNT() << endl;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & t = GetTriangle(i);\n      for (j = 1; j <= 3; j++)\n\t{\n\t  const Point3d p = GetPoint(t.PNum(j));\n\t  outf << p.X() << \" \" << p.Y() << \" \" << p.Z() << endl;\n\t}\n    }\n\n\n  int ned = 0;\n  for (i = 1; i <= GetNTE(); i++)\n    {\n      if (GetTopEdge (i).GetStatus() == ED_CONFIRMED)\n\tned++;\n    }\n  \n  outf << ned << endl;\n\n  for (i = 1; i <= GetNTE(); i++)\n    {\n      const STLTopEdge & edge = GetTopEdge (i);\n      if (edge.GetStatus() == ED_CONFIRMED)\n\tfor (j = 1; j <= 2; j++)\n\t  {\n\t    const Point3d p = GetPoint(edge.PNum(j));\n\t    outf << p.X() << \" \" << p.Y() << \" \" << p.Z() << endl;\n\t  }\n    }      \n}\n\n\n\nSTLGeometry *  STLTopology :: LoadNaomi (istream & ist)\n{\n  int i;\n  STLGeometry * geom = new STLGeometry();\n  NgArray<STLReadTriangle> readtrigs;\n\n  PrintFnStart(\"read NAOMI file format\");\n  \n  char buf[100];\n  Vec<3> normal;\n\n  //int cntface = 0;\n  //int cntvertex = 0;\n  double px, py, pz;\n    \n\n  int noface, novertex;\n  NgArray<Point<3> > readpoints;\n\n  ist >> buf;\n  if (strcmp (buf, \"NODES\") == 0)\n    {\n      ist >> novertex;\n      PrintMessage(5,\"number of vertices = \", novertex);\n      for (i = 0; i < novertex; i++)\n\t{\n\t  ist >> px;\n\t  ist >> py;\n\t  ist >> pz;\n\t  readpoints.Append(Point<3> (px,py,pz));\n\t}\n    }\n  else\n    {\n      PrintFileError(\"no node information\");\n    }\n\n\n  ist >> buf;\n  if (strcmp (buf, \"2D_EDGES\") == 0)\n    {\n      ist >> noface;\n      PrintMessage(5,\"number of faces=\",noface);\n      int dummy, p1, p2, p3;\n      Point<3> pts[3];\n\n      for (i = 0; i < noface; i++)\n\t{\n\t  ist >> dummy; //2\n\t  ist >> dummy; //1\n\t  ist >> p1;\n\t  ist >> p2;\n\t  ist >> p3;\n\t  ist >> dummy; //0\n\n\t  pts[0] = readpoints.Get(p1);\n\t  pts[1] = readpoints.Get(p2);\n\t  pts[2] = readpoints.Get(p3);\n\t  \n\t  normal = Cross (pts[1]-pts[0], pts[2]-pts[0]) . Normalize();\n\n\t  readtrigs.Append (STLReadTriangle (pts, normal));\n\n\t}\n      PrintMessage(5,\"read \", readtrigs.Size(), \" triangles\");\n    }\n  else\n    {\n      PrintMessage(5,\"read='\",buf,\"'\\n\");\n      PrintFileError(\"ERROR: no Triangle information\");\n    }\n\n  geom->InitSTLGeometry(readtrigs);\n\n  return geom;\n}\n\nvoid STLTopology :: Save (const filesystem::path & filename) const\n{ \n  PrintFnStart(\"Write stl-file '\",filename, \"'\");\n\n  ofstream fout(filename);\n  fout << \"solid\\n\";\n\n  char buf1[50];\n  char buf2[50];\n  char buf3[50];\n\n  int i, j;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & t = GetTriangle(i);\n\n      fout << \"facet normal \";\n      const Vec3d& n = GetTriangle(i).Normal();\n\n      snprintf(buf1, size(buf1), \"%1.9g\",n.X());\n      snprintf(buf2, size(buf2), \"%1.9g\",n.Y());\n      snprintf(buf3, size(buf3), \"%1.9g\",n.Z());\n\n      fout << buf1 << \" \" << buf2 << \" \" << buf3 << \"\\n\";\n      fout << \"outer loop\\n\";\n\n      for (j = 1; j <= 3; j++)\n\t{\n\t  const Point3d p = GetPoint(t.PNum(j));\n\t  \n\t  snprintf(buf1, size(buf1), \"%1.9g\",p.X());\n\t  snprintf(buf2, size(buf2), \"%1.9g\",p.Y());\n\t  snprintf(buf3, size(buf3), \"%1.9g\",p.Z());\n\n\t  fout << \"vertex \" << buf1 << \" \" << buf2 << \" \" << buf3 << \"\\n\";\n\t}\n\n      fout << \"endloop\\n\";\n      fout << \"endfacet\\n\"; \n    }\n  fout << \"endsolid\\n\";\n\n  \n  // write also NETGEN surface mesh:\n  ofstream fout2(\"geom.surf\");\n  fout2 << \"surfacemesh\" << endl;\n  fout2 << GetNP() << endl;\n  for (i = 1; i <= GetNP(); i++)\n    {\n      for (j = 0; j < 3; j++)\n\t{\n\t  fout2.width(8);\n\t  fout2 << GetPoint(i)(j);\n\t}\n\n      fout2 << endl;\n    }\n\n  fout2 << GetNT() << endl;\n  for (i = 1; i <= GetNT(); i++)\n    {\n      const STLTriangle & t = GetTriangle(i);  \n      for (j = 1; j <= 3; j++)\n\t{\n\t  fout2.width(8);\n\t  fout2 << t.PNum(j);\n\t}\n      fout2 << endl;\n    }\n}\n\n\nSTLGeometry *  STLTopology ::Load (istream & ist, bool surface)\n{\n  // Check if the file starts with \"solid\". If not, the file is binary\n  {\n    // binary header is 80 bytes, so don't load more than that\n    constexpr int buflen = 80;\n    char buf[buflen+1];\n    FIOReadStringE(ist,buf,buflen);\n\n    // ignore whitespaces at start of line\n    int istart;\n    for (istart=0; istart<buflen-5; istart++)\n       if(std::isblank(buf[istart])==0)\n            break;\n\n    for ([[maybe_unused]] auto i : Range(buflen))\n        ist.unget();\n\n    // does not start with \"solid\" -> binary file\n    if (strncmp(buf+istart, \"solid\", 5) != 0)\n      return LoadBinary(ist);\n\n    // Check if there is a non-printable character in first 80 bytes\n    for (auto i : Range(istart, buflen))\n       if(std::isprint(buf[i])==0 && std::isspace(buf[i])==0)\n           return LoadBinary(ist);\n  }\n\n  STLGeometry * geom = new STLGeometry();\n\n  NgArray<STLReadTriangle> readtrigs;\n\n  char buf[100];\n  Point<3> pts[3];\n  Vec<3> normal;\n\n  [[maybe_unused]] int cntface = 0;\n  int vertex = 0;\n  bool badnormals = false;\n  ist >> buf; // skip first line\n  \n  while (ist.good())\n    {\n      ist >> buf;\n\n      int n = strlen (buf);\n      for (int i = 0; i < n; i++)\n\tbuf[i] = tolower (buf[i]);\n\n      if (strcmp (buf, \"facet\") == 0)\n\t{\n\t  cntface++;\n\t}\n\n      if (strcmp (buf, \"normal\") == 0)\n\t{\n\t  ist >> normal(0)\n\t      >> normal(1)\n\t      >> normal(2);\n\t  normal.Normalize();\n\t}\n\n      if (strcmp (buf, \"vertex\") == 0)\n\t{\n\t  ist >> pts[vertex](0)\n\t      >> pts[vertex](1)\n\t      >> pts[vertex](2);\n\n\t  vertex++;\n\n\t  if (vertex == 3)\n\t    {\n\t      if (normal.Length() <= 1e-5)\n\n\t\t{\n\t\t  normal = Cross (pts[1]-pts[0], pts[2]-pts[0]);\n\t\t  normal.Normalize();\n\t\t}\n\n\t      else\n\n\t\t{\n\t\t  Vec<3> hnormal = Cross (pts[1]-pts[0], pts[2]-pts[0]);\n\t\t  hnormal.Normalize();\n\n\t\t  if (normal * hnormal < 0.5)\n\t\t    badnormals = true;\n\t\t}\n\n\t      vertex = 0;\n\n\t      if ( (Dist2 (pts[0], pts[1]) > 1e-16) &&\n\t\t   (Dist2 (pts[0], pts[2]) > 1e-16) &&\n\t\t   (Dist2 (pts[1], pts[2]) > 1e-16) )\n\t\t\n\t\t{\n                  readtrigs.Append (STLReadTriangle (pts, normal));\n\n\t\t  if (readtrigs.Size() % 100000 == 0)\n\t\t    PrintMessageCR (3, readtrigs.Size(), \" triangles loaded\\r\");\n\t\t}\n              else\n                {\n                  cout << \"Skipping flat triangle \" \n                       << \"l1 = \" << Dist(pts[0], pts[1])\n                       << \", l2 = \" << Dist(pts[0], pts[2])\n                       << \", l3 = \" << Dist(pts[2], pts[1]) << endl;\n                }\n\n\t    }\n\t}\n    }\n  PrintMessage (3, readtrigs.Size(), \" triangles loaded\");\n\n  if (badnormals) \n    {\n      PrintWarning(\"File has normal vectors which differ extremely from geometry->correct with stldoctor!!!\");\n    }\n\n  geom->surface = surface;\n  geom->InitSTLGeometry(readtrigs);\n  return geom;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid STLTopology :: InitSTLGeometry(const NgArray<STLReadTriangle> & readtrigs)\n{\n  // const double geometry_tol_fact = 1E6; \n  // distances lower than max_box_size/tol are ignored\n\n  trias.SetSize(0);\n  points.SetSize(0);\n\n  PrintMessage(3,\"number of triangles = \", readtrigs.Size());\n\n  if (!readtrigs.Size()) return;\n  \n\n  boundingbox.Set (readtrigs[0][0]);\n  for (int i = 0; i < readtrigs.Size(); i++)\n    for (int k = 0; k < 3; k++)\n      boundingbox.Add (readtrigs[i][k]);\n  \n  PrintMessage(5,\"boundingbox: \", Point3d(boundingbox.PMin()), \" - \", \n\t       Point3d(boundingbox.PMax()));\n\n  Box<3> bb = boundingbox;\n  bb.Increase (1);\n\n  pointtree = new Point3dTree (bb.PMin(), bb.PMax());\n\n  NgArray<int> pintersect;\n\n  pointtol = boundingbox.Diam() * stldoctor.geom_tol_fact;\n  PrintMessage(5,\"point tolerance = \", pointtol);\n  PrintMessageCR(5,\"identify points ...\");  \n\n  for(int i = 0; i < readtrigs.Size(); i++)\n    {\n      const STLReadTriangle & t = readtrigs[i];\n\n      STLTriangle st;\n      st.SetNormal (t.Normal());\n\n      for (int k = 0; k < 3; k++)\n\t{\n\t  Point<3> p = t[k];\n\n\t  Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol);\n\t  Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol);\n\t  \n\t  pointtree->GetIntersecting (pmin, pmax, pintersect);\n\t  \n\t  if (pintersect.Size() > 1)\n            PrintError(\"too many close points\");\n\t  int foundpos = -1;\n\t  if (pintersect.Size())\n\t    foundpos = pintersect[0];\n\t  \n\t  if (foundpos == -1)\n\t    {\n\t      foundpos = AddPoint(p);\n\t      pointtree->Insert (p, foundpos);\n\t    }\n          if (Dist(p, points[foundpos]) > 1e-10)\n            cout << \"identify close points: \" << p << \" \" << points[foundpos]\n                 << \", dist = \" << Dist(p, points[foundpos])\n                 << endl;\n\t  st[k] = foundpos;\n\t}\n\n      if ( (st[0] == st[1]) ||\n\t   (st[0] == st[2]) || \n\t   (st[1] == st[2]) )\n\t{\n\t  PrintError(\"STL Triangle degenerated\");\n\t}\n      else\n\t{\n\t  AddTriangle(st);\n\t}\n      \n    } \n  PrintMessage(5,\"identify points ... done\");  \n  FindNeighbourTrigs();\n}\n\n\n\n\nint STLTopology :: GetPointNum (const Point<3> & p)\n{\n  Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol);\n  Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol);\n  \n  NgArray<int> pintersect;\n\n  pointtree->GetIntersecting (pmin, pmax, pintersect);\n  if (pintersect.Size() == 1)\n    return pintersect[0];\n  else \n    return 0;\n}\n\n\n\nvoid STLTopology :: FindNeighbourTrigs()\n{\n  //  if (topedges.Size()) return;\n\n  PushStatusF(\"Find Neighbour Triangles\");\n\n  PrintMessage(5,\"build topology ...\");\n\n  // build up topology tables\n\n  int nt = GetNT();\n\n  INDEX_2_HASHTABLE<int> * oldedges = ht_topedges;\n  ht_topedges = new INDEX_2_HASHTABLE<int> (GetNP()+1);\n  topedges.SetSize(0);\n  \n  for (int i = 1; i <= nt; i++)\n    {\n      STLTriangle & trig = GetTriangle(i);\n\n\n      for (int j = 1; j <= 3; j++)\n\t{\n\t  int pi1 = trig.PNumMod (j+1);\n\t  int pi2 = trig.PNumMod (j+2);\n\t  \n\t  INDEX_2 i2(pi1, pi2);\n\t  i2.Sort();\n\n\t  int enr;\n\t  int othertn;\n\n\t  if (ht_topedges->Used(i2))\n\t    {\n\t      enr = ht_topedges->Get(i2);\n\t      topedges.Elem(enr).TrigNum(2) = i;\n\n\t      othertn = topedges.Get(enr).TrigNum(1);\n\t      STLTriangle & othertrig = GetTriangle(othertn);\n\n\t      trig.NBTrigNum(j) = othertn;\n\t      trig.EdgeNum(j) = enr;\n\t      for (int k = 1; k <= 3; k++)\n\t\tif (othertrig.EdgeNum(k) == enr)\n\t\t  othertrig.NBTrigNum(k) = i;\n\t    }\n\t  else\n\t    {\n\t      topedges.Append (STLTopEdge (pi1, pi2, i, 0));\n              enr = topedges.Size();\n\t      ht_topedges->Set (i2, enr);\n\t      trig.EdgeNum(j) = enr;\n\t    }\n\t}\n    }\n\n  \n  PrintMessage(5,\"topology built, checking\");\n\n  topology_ok = 1;\n  int ne = GetNTE();\n\n  for (int i = 1; i <= nt; i++)\n    GetTriangle(i).flags.toperror = 0;\n\n  for (int i = 1; i <= nt; i++)\n    for (int j = 1; j <= 3; j++)\n      {\n\tconst STLTopEdge & edge = GetTopEdge (GetTriangle(i).EdgeNum(j));\n\tif (edge.TrigNum(1) != i && edge.TrigNum(2) != i)\n\t  {\n\t    topology_ok = 0;\n\t    GetTriangle(i).flags.toperror = 1;\n\t  }\n      }\n\n  if(!surface)\n  for (int i = 1; i <= ne; i++)\n    {\n      const STLTopEdge & edge = GetTopEdge (i);\n      if (!edge.TrigNum(2))\n\t{\n\t  topology_ok = 0;\n\t  GetTriangle(edge.TrigNum(1)).flags.toperror = 1;\n\t}\n    }\n \n  if (topology_ok)\n    {\n      orientation_ok = 1;\n      for (int i = 1; i <= nt; i++)\n\t{\n\t  const STLTriangle & t = GetTriangle (i);\n\t  for (int j = 1; j <= 3; j++)\n\t    {\n              if(t.NBTrigNum(j) != 0)\n                {\n                  const STLTriangle & nbt = GetTriangle (t.NBTrigNum(j));\n                  if (!t.IsNeighbourFrom (nbt))\n                    orientation_ok = 0;\n                }\n\t    }\n\t}\n    }\n  else\n    orientation_ok = 0;\n  \n\n\n  status = STL_GOOD;\n  statustext = \"\";\n  if (!topology_ok || !orientation_ok)\n    {\n      status = STL_ERROR;\n      if (!topology_ok)\n\tstatustext = \"Topology not ok\";\n      else\n\tstatustext = \"Orientation not ok\";\n    }\n\n\n  PrintMessage(3,\"topology_ok = \",topology_ok);\n  PrintMessage(3,\"orientation_ok = \",orientation_ok);\n  PrintMessage(3,\"topology found\");\n\n  // generate point -> trig table\n\n  trigsperpoint.SetSize(GetNP());\n  for (int i = 1; i <= GetNT(); i++)\n    for (int j = 1; j <= 3; j++)\n      trigsperpoint.Add1(GetTriangle(i).PNum(j),i);\n\n\n  //check trigs per point:\n  /*\n  for (i = 1; i <= GetNP(); i++)\n    {\n      if (trigsperpoint.EntrySize(i) < 3)\n\t{\n\t  (*testout) << \"ERROR: Point \" << i << \" has \" << trigsperpoint.EntrySize(i) << \" triangles!!!\" << endl;\n\t}\n    }\n  */\n  topedgesperpoint.SetSize (GetNP());\n  for (int i = 1; i <= ne; i++)\n    for (int j = 1; j <= 2; j++)\n      topedgesperpoint.Add1 (GetTopEdge (i).PNum(j), i);\n\n  PrintMessage(5,\"point -> trig table generated\");\n\n\n\n  // transfer edge data:\n  // .. to be done\n  delete oldedges;\n\n\n\n  // for (STLTrigId ti = 0; ti < GetNT(); ti++)\n  for (STLTrigId ti : Range(trias))\n    {\n      STLTriangle & trig = trias[ti];\n      for (int k = 0; k < 3; k++)\n\t{\n\t  STLPointId pi = trig[k]; //  - STLBASE;\n\t  STLPointId pi2 = trig[(k+1)%3]; //  - STLBASE;\n\t  STLPointId pi3 = trig[(k+2)%3]; // - STLBASE;\n\t  \n\t  // vector along edge\n\t  Vec<3> ve = points[pi2] - points[pi];\n\t  ve.Normalize();\n\n\t  // vector along third point\n\t  Vec<3> vt = points[pi3] - points[pi];\n\t  vt -= (vt * ve) * ve;\n\t  vt.Normalize();\n\n\t  Vec<3> vn = trig.GeomNormal (points);\n\t  vn.Normalize();\n\n\t  double phimin = 10, phimax = -1; // out of (0, 2 pi)\n\n\t  for (int j = 0; j < trigsperpoint[pi].Size(); j++)\n\t    {\n\t      STLTrigId ti2 = trigsperpoint[pi][j]; //  - STLBASE;\n\t      const STLTriangle & trig2 = trias[ti2];\n\n\t      if (ti == ti2) continue;\n\t      \n\t      bool hasboth = 0;\n\t      for (int l = 0; l < 3; l++)\n\t\tif (trig2[l] /* - STLBASE */ == pi2)\n\t\t  {\n\t\t    hasboth = 1;\n\t\t    break;\n\t\t  }\n\t      if (!hasboth) continue;\n\n\t      STLPointId pi4(0);\n\t      for (int l = 0; l < 3; l++)\n\t\tif (trig2[l] /* - STLBASE */ != pi && trig2[l] /* - STLBASE */ != pi2)\n\t\t  pi4 = trig2[l] /* - STLBASE */;\n\n\t      Vec<3> vt2 = points[pi4] - points[pi];\n\t      \n\t      double phi = atan2 (vt2 * vn, vt2 * vt);\n\t      if (phi < 0) phi += 2 * M_PI;\n\t      \n\t      if (phi < phimin)\n\t\t{\n\t\t  phimin = phi;\n\t\t  trig.NBTrig (0, (k+2)%3) = ti2; //  + STLBASE;\n\t\t}\n\t      if (phi > phimax)\n\t\t{\n\t\t  phimax = phi;\n\t\t  trig.NBTrig (1, (k+2)%3) = ti2; //  + STLBASE;\n\t\t}\n\t    }\n\t}\n    }\n\n\n\n\n  if (status == STL_GOOD)\n    {\n      // for compatibility:\n      neighbourtrigs.SetSize(GetNT());\n      for (int i = 1; i <= GetNT(); i++)\n\tfor (int k = 1; k <= 3; k++)\n          if(GetTriangle(i).NBTrigNum(k) != 0)\n            AddNeighbourTrig (i, GetTriangle(i).NBTrigNum(k));\n    }\n  else\n    {\n      // assemble neighbourtrigs (should be done only for illegal topology):\n      \n      neighbourtrigs.SetSize(GetNT());\n\n      int tr, found;\n      int wrongneighbourfound = 0;\n      for (int i = 1; i <= GetNT(); i++)\n\t{\n\t  SetThreadPercent((double)i/(double)GetNT()*100.);\n\t  if (multithread.terminate)\n\t    {\n\t      PopStatus();\n\t      return;\n\t    }\n\t  \n\t  for (int k = 1; k <= 3; k++)\n\t    {\n\t      for (int j = 1; j <= trigsperpoint.EntrySize(GetTriangle(i).PNum(k)); j++)\n\t\t{\n\t\t  tr = trigsperpoint.Get(GetTriangle(i).PNum(k),j);\n\t\t  if (i != tr && (GetTriangle(i).IsNeighbourFrom(GetTriangle(tr))\n\t\t\t\t  || GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr))))\n\t\t    {\n\t\t      if (GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr)))\n\t\t\t{\n\t\t\t  /*(*testout) << \"ERROR: triangle \" << i << \" has a wrong neighbour triangle!!!\" << endl;*/\n\t\t\t  wrongneighbourfound ++;\n\t\t\t}\n\t\t      \n\t\t      found = 0;\n\t\t      for (int ii = 1; ii <= NONeighbourTrigs(i); ii++) \n\t\t\t{if (NeighbourTrig(i,ii) == tr) {found = 1;break;};}\n\t\t      if (! found) {AddNeighbourTrig(i,tr);}\n\t\t    }\n\t\t}\n\t    }\n\t  if (NONeighbourTrigs(i) != 3) \n\t    {\n\t      PrintError(\"TRIG \",i,\" has \",NONeighbourTrigs(i),\" neighbours!!!!\");\n\t      for (int kk=1; kk <= NONeighbourTrigs(i); kk++)\n\t\t{\n\t\t  PrintMessage(5,\"neighbour-trig\",kk,\" = \",int(NeighbourTrig(i,kk)));\n\t\t}\n\t    };\n\t}\n      if (wrongneighbourfound)\n\t{\n\t  PrintError(\"++++++++++++++++++++\\n\");\n\t  PrintError(wrongneighbourfound, \" wrong oriented neighbourtriangles found!\");\n\t  PrintError(\"try to correct it (with stldoctor)!\");\n\t  PrintError(\"++++++++++++++++++++\\n\");\n\t  \n\t  status = STL_ERROR;\n\t  statustext = \"STL Mesh not consistent\";\n\n\t  multithread.terminate = 1;\n#ifdef STAT_STREAM\n\t  (*statout) << \"non-conform stl geometry \\\\hline\" << endl;\n#endif\n\t}\n    }\n\n  TopologyChanged();\n\n  PopStatus();\n}\n\n\n\n\n\n\n\nvoid STLTopology :: GetTrianglesInBox (/* \n\t\t\t\t\t  const Point<3> & pmin,\n\t\t\t\t\t  const Point<3> & pmax,\n\t\t\t\t       */\n\t\t\t\t       const Box<3> & box,\n\t\t\t\t       NgArray<int> & btrias) const\n{\n  if (searchtree)\n\n    searchtree -> GetIntersecting (box.PMin(), box.PMax(), btrias);\n  \n  else\n    {    \n      int i;\n      Box<3> box1 = box;\n      box1.Increase (1e-4);\n\n      btrias.SetSize(0);\n   \n      int nt = GetNT();\n      for (i = 1; i <= nt; i++)\n\t{\n\t  if (box1.Intersect (GetTriangle(i).box))\n\t    {\n\t      btrias.Append (i);\n\t    }\n\t}    \n    }\n}\n\n\n\nvoid STLTopology :: AddTriangle(const STLTriangle& t)\n{\n  trias.Append(t);\n  \n  const Point<3> & p1 = GetPoint (t.PNum(1));\n  const Point<3> & p2 = GetPoint (t.PNum(2));\n  const Point<3> & p3 = GetPoint (t.PNum(3));\n\n  Box<3> box;\n  box.Set (p1);\n  box.Add (p2);\n  box.Add (p3);\n  /*\n  //  Point<3> pmin(p1), pmax(p1);\n  pmin.SetToMin (p2);\n  pmin.SetToMin (p3);\n  pmax.SetToMax (p2);\n  pmax.SetToMax (p3);\n  */\n\n  trias.Last().box = box; \n  trias.Last().center = Center (p1, p2, p3);\n  double r1 = Dist (p1, trias.Last().center);\n  double r2 = Dist (p2, trias.Last().center);\n  double r3 = Dist (p3, trias.Last().center);\n  trias.Last().rad = max2 (max2 (r1, r2), r3);\n\n  if (geomsearchtreeon)\n    {searchtree->Insert (box.PMin(), box.PMax(), trias.Size());}\n}\n\n\n\n\nint STLTopology :: GetLeftTrig(int p1, int p2) const\n{\n  int i;\n  for (i = 1; i <= trigsperpoint.EntrySize(p1); i++)\n    {\n      if (GetTriangle(trigsperpoint.Get(p1,i)).HasEdge(p1,p2)) {return trigsperpoint.Get(p1,i);}\n    }\n  PrintSysError(\"ERROR in GetLeftTrig !!!\");\n\n  return 0;\n}\n\nint STLTopology :: GetRightTrig(int p1, int p2) const\n{\n  return GetLeftTrig(p2,p1);\n}\n\n\nint STLTopology :: NeighbourTrigSorted(int trig, int edgenum) const\n{\n  STLPointId p1, p2;\n  STLPointId psearch = GetTriangle(trig).PNum(edgenum);\n\n  for (int i = 1; i <= 3; i++)\n    {\n      GetTriangle(trig).GetNeighbourPoints(GetTriangle(NeighbourTrig(trig,i)),p1,p2);\n      if (p1 == psearch) {return NeighbourTrig(trig,i);}\n    }\n\n  PrintSysError(\"ERROR in NeighbourTrigSorted\");\n  return 0;\n}\n\n\n\n\n\n\nint STLTopology :: GetTopEdgeNum (int pi1, int pi2) const\n{\n  if (!ht_topedges) return 0;\n\n  INDEX_2 i2(pi1, pi2);\n  i2.Sort();\n\n  if (!ht_topedges->Used(i2)) return 0;\n  return ht_topedges->Get(i2);\n}\n\n\n\n\nvoid STLTopology :: InvertTrig (int trig)\n{\n  if (trig >= 1 && trig <= GetNT())\n    {\n      GetTriangle(trig).ChangeOrientation();\n      FindNeighbourTrigs();\n    }\n  else\n    {\n      PrintUserError(\"no triangle selected!\");\n    }\n}\n\n\n\n\nvoid STLTopology :: DeleteTrig (int trig)\n{\n  if (trig >= 1 && trig <= GetNT())\n    {\n      trias.DeleteElement(trig);\n      FindNeighbourTrigs();\n    }\n  else\n    {\n      PrintUserError(\"no triangle selected!\");\n    }\n}\n\n\n\nvoid STLTopology :: OrientAfterTrig (int trig)\n{\n  int starttrig = trig;\n\n  if (starttrig >= 1 && starttrig <= GetNT())\n    {\n\n      NgArray <int> oriented;\n      oriented.SetSize(GetNT());\n      int i;\n      for (i = 1; i <= oriented.Size(); i++)\n\t{\n\t  oriented.Elem(i) = 0;\n\t}\n \n      oriented.Elem(starttrig) = 1;\n  \n      int k;\n      \n      NgArray <int> list1;\n      list1.SetSize(0);\n      NgArray <int> list2;\n      list2.SetSize(0);\n      list1.Append(starttrig);\n\n      int cnt = 1;\n      int end = 0;\n      int nt;\n      while (!end)\n\t{\n\t  end = 1;\n\t  for (i = 1; i <= list1.Size(); i++)\n\t    {\n\t      const STLTriangle& tt = GetTriangle(list1.Get(i));\n\t      for (k = 1; k <= 3; k++)\n\t\t{\n\t\t  nt = tt.NBTrigNum (k); // NeighbourTrig(list1.Get(i),k);\n\t\t  if (oriented.Get(nt) == 0)\n\t\t    {\n\t\t      if (tt.IsWrongNeighbourFrom(GetTriangle(nt)))\n\t\t\t{\n\t\t\t  GetTriangle(nt).ChangeOrientation();\n\t\t\t}\n\t\t      oriented.Elem(nt) = 1;\n\t\t      list2.Append(nt);\n\t\t      cnt++;\n\t\t      end = 0;\n\t\t    }\n\t\t}\n\t    }\n\t  list1.SetSize(0);\n\t  for (i = 1; i <= list2.Size(); i++)\n\t    {\n\t      list1.Append(list2.Get(i));\n\t    }\n\t  list2.SetSize(0);\n\t}\n\n      PrintMessage(5,\"NO corrected triangles = \",cnt);\n      if (cnt == GetNT()) \n\t{\n\t  PrintMessage(5,\"ALL triangles oriented in same way!\");\n\t}\n      else\n\t{\n\t  PrintWarning(\"NOT ALL triangles oriented in same way!\");\n\t}\n\n      //      topedges.SetSize(0);\n      FindNeighbourTrigs();\n    }\n  else\n    {\n      PrintUserError(\"no triangle selected!\");\n    }\n}\n\nstatic RegisterClassForArchive<STLTopology> stltop;\n}\n"
  },
  {
    "path": "libsrc/stlgeom/stltopology.hpp",
    "content": "#ifndef FILE_STLTOPOLOGY\n#define FILE_STLTOPOLOGY\n\n/**************************************************************************/\n/* File:   stltopology.hpp                                                */\n/* Author: Joachim Schoeberl                                              */\n/* Author2: Johannes Gerstmayr                                            */\n/* Date:   26. Jul. 99                                                    */\n/**************************************************************************/\n\n/*\n  The STLTopology contains topologic information as\n  triangle->point, point->triangles, triangle->edge, 2-points->edge,...\n*/\n\n\nnamespace netgen {\n\nclass STLGeometry;\n\n  // #define STLBASE 1\n\nclass STLPointId\n{\n  int i;\npublic:\n  STLPointId () { ; }\n  constexpr STLPointId (int ai) : i(ai) { ; }\n  STLPointId & operator= (const STLPointId & ai) { i = ai.i; return *this; }\n  STLPointId & operator= (int ai) { i = ai; return *this; }\n  constexpr operator int () const { return i; }\n  STLPointId operator++ (int) { return STLPointId(i++); }    \n  STLPointId operator-- (int) { return STLPointId(i--); }\n  STLPointId & operator++ () { ++i; return *this; }\n  STLPointId & operator-- () { --i; return *this; }\n  \n  void DoArchive(Archive& ar) { ar & i; }\n};\n\n\n\nclass STLTrigId\n{\n  int i;\npublic:\n  STLTrigId () { ; }\n  constexpr STLTrigId (int ai) : i(ai) { ; }\n  STLTrigId & operator= (const STLTrigId & ai) { i = ai.i; return *this; }\n  STLTrigId & operator= (int ai) { i = ai; return *this; }\n  constexpr operator int () const { return i; }\n\n  STLTrigId operator++ (int) { return STLTrigId(i++); }    \n  STLTrigId operator-- (int) { return STLTrigId(i--); }\n  STLTrigId & operator++ () { ++i; return *this; }\n  STLTrigId & operator-- () { --i; return *this; }\n\n  int operator- (STLTrigId i2) const { return i-i2.i; }\n};\n\n  inline void SetInvalid (STLTrigId & id) { id = 0; }\n  inline bool IsInvalid (STLTrigId & id) { return id == 0; }\n\n}\n\n\nnamespace ngcore\n{\n  template<> \n  constexpr netgen::STLPointId IndexBASE<netgen::STLPointId> () { return netgen::STLPointId(1); }\n  template<> \n  constexpr netgen::STLTrigId IndexBASE<netgen::STLTrigId> () { return netgen::STLTrigId(1); }\n}\n\n\n\nnamespace netgen {\n\n\n// triangle structure for loading stl files\nclass STLReadTriangle\n{\n  Vec<3> normal;\n  Point<3> pts[3];\npublic:\n  STLReadTriangle (const Point<3> * apts, const Vec<3> & anormal);\n  STLReadTriangle () {};\n  const Point<3> & operator[] (int i) const { return pts[i]; }\n  const Vec<3> & Normal() const { return normal; }\n};\n\n\n\nclass STLTriangle\n{\n  // topology edges of triangle, edge[i] opposite to point[i]\n  int topedges[3];\n  // neighbour triangles, trig[i] opposite to point[i]\n  int nbtrigs[2][3]; \n  // normalized stored normal vector ??\n  Vec<3> normal;\n  // point numbers of triangle\n  STLPointId pts[3];\n  // front-side and back-side domains\n  int domains[2];\n\n\npublic:\n\n  Box<3> box;\n  Point<3> center;\n  double rad;\n  int facenum;\n\n  struct \n  {\n    unsigned int toperror : 1;\n  } flags;\n\n\n\n\n  STLTriangle (const STLPointId * apts);\n  STLTriangle ()\n  {\n    pts[0]=0;pts[1]=0;pts[2]=0;\n    nbtrigs[0][0] = nbtrigs[0][1] = nbtrigs[0][2] = 0.;\n    nbtrigs[1][0] = nbtrigs[1][1] = nbtrigs[1][2] = 0.;\n  }\n\n  void DoArchive(Archive& ar)\n  {\n    ar.Do(&topedges[0],3);\n    ar.Do(&nbtrigs[0][0], 6);\n    // ar.Do(&pts[0],3);\n    ar & pts[0] & pts[1] & pts[2];\n    ar.Do(&domains[0],2);\n    size_t i = flags.toperror;\n    ar & normal & box & center & rad & facenum & i;\n    flags.toperror = i;\n  }\n\n  STLPointId operator[] (int i) const { return pts[i]; }\n  STLPointId & operator[] (int i) { return pts[i]; }\n\n  int EdgeNum(int i) const { return topedges[(i-1)]; }\n  int & EdgeNum(int i) { return topedges[(i-1)]; }\n\n  int NBTrig (bool side, int i) const { return nbtrigs[side][i]; }\n  int & NBTrig (bool side, int i) { return nbtrigs[side][i]; }\n\n  \n  int Domain (bool side) const { return domains[side]; }\n  int & Domain (bool side) { return domains[side]; }\n\n\n\n  // obsolete:\n  STLPointId PNum(int i) const { return pts[(i-1)]; }\n  STLPointId & PNum(int i) { return pts[(i-1)]; }\n  STLPointId PNumMod(int i) const { return pts[(i-1)%3]; }\n  STLPointId & PNumMod(int i)  { return pts[(i-1)%3]; }\n  FlatArray<const STLPointId> PNums() const { return { 3, pts }; }\n\n  \n  int EdgeNumMod(int i) const { return topedges[(i-1)%3]; }\n  int & EdgeNumMod(int i)  { return topedges[(i-1)%3]; }\n\n  int NBTrigNum(int i) const { return nbtrigs[0][(i-1)]; }\n  int & NBTrigNum(int i) { return nbtrigs[0][(i-1)]; }\n  int NBTrigNumMod(int i) const { return nbtrigs[0][(i-1)%3]; }\n  int & NBTrigNumMod(int i)  { return nbtrigs[0][(i-1)%3]; }\n  \n\n  // consistently oriented neighbour:\n  int IsNeighbourFrom(const STLTriangle& t) const;\n  // opposite to consistently oriented neighbour:\n  int IsWrongNeighbourFrom(const STLTriangle& t) const;\n\n  ///Get the two points of neighbour-Triangles in orientation of this-Triangle\n  void GetNeighbourPoints(const STLTriangle& t, STLPointId & p1, STLPointId & p2) const;\n  int GetNeighbourPointsAndOpposite(const STLTriangle& t, STLPointId & p1, STLPointId & p2, STLPointId & po) const;\n\n\n\n  // NON-normalized geometry - normal vector\n  Vec<3> GeomNormal(const Array<Point<3>,STLPointId>& ap) const;\n  \n  // Stored normal vector, normalized\n  void SetNormal (const Vec<3> & n);\n  const Vec<3> & Normal () const { return normal; }\n\n\n  void ChangeOrientation(); \n\n  //project with a certain normal vector in plane\n  void ProjectInPlain(const Array<Point<3>, STLPointId>& ap, \n\t\t      const Vec<3> & n, Point<3> & pp) const;\n  //project with the triangle's normal vector in plane\n  void ProjectInPlain(const Array<Point<3>, STLPointId> & ap, Point<3> & pp) const;\n\n\n  /*\n    Project the point pp along the nproj into the plane of\n    the triangle. The triangle normal is given by ntrig to \n    avoid numerical instabilities.\n    The local coordinates lam are defined by\n\n    pp(input) = P1 + lam1 v1 + lam2 v2 + lam3 n\n\n    the result is\n    \n    pp(output) = P1 + lam1 v1 + lam2 v2\n  */\n  int ProjectInPlain (const Array<Point<3>,STLPointId>& ap, \n\t\t      const Vec<3> & nproj, \n\t\t      Point<3> & pp, Vec<3> & lam) const;\n\n  bool PointInside(const Array<Point<3>,STLPointId>& ap, const Point<3> & pp) const;\n\n  //get nearest point on triangle and distance to it\n  double GetNearestPoint(const Array<Point<3>,STLPointId>& ap, \n\t\t\t Point<3> & p3d) const;\n\n  double Area(const Array<Point<3>,STLPointId>& ap) const;\n\n  double MinHeight(const Array<Point<3>,STLPointId>& ap) const;\n  double MaxLength(const Array<Point<3>,STLPointId>& ap) const; \n  //max length of a side of triangle\n\n  int GetFaceNum() {return facenum;}\n  void SetFaceNum(int i) {facenum = i;}\n\n  bool HasEdge(STLPointId p1, STLPointId p2) const;\n};\n\n\n/**\n   Topology Edge:\n   Useful unside a face.\n   A edges sharing more than 2 faces: trigs are undefined \n */\nclass STLTopEdge \n{\n  STLPointId pts[2];  \n  int trigs[2];  \n  double cosangle;\n  int status;  // excluded, confirmed, candidate, undefined\npublic:\n  STLTopEdge ();\n  STLTopEdge (STLPointId p1, STLPointId p2, int trig1, int trig2);\n\n  STLPointId operator[] (int i) const { return pts[i]; }\n  STLPointId & operator[] (int i) { return pts[i]; }\n\n\n  STLPointId PNum(int i) const { return pts[(i-1)]; }\n  STLPointId & PNum(int i) { return pts[(i-1)]; }\n  STLPointId PNumMod(int i) const { return pts[(i-1)%2]; }\n  STLPointId & PNumMod(int i)  { return pts[(i-1)%2]; }\n\n  int TrigNum(int i) const { return trigs[(i-1)]; }\n  int & TrigNum(int i) { return trigs[(i-1)]; }\n  int TrigNumMod(int i) const { return trigs[(i-1)%2]; }\n  int & TrigNumMod(int i)  { return trigs[(i-1)%2]; }\n\n  void SetCosAngle (double ca) { cosangle = ca; }\n  double CosAngle () const { return cosangle; }\n  double Angle () const { return acos (cosangle); }\n\n  void SetStatus (int stat) { status = stat; }\n  int GetStatus () const { return status; }\n};\n\n\n\nostream& operator<<(ostream& os, const STLTriangle& t);\n\n\n\n\n\n\n\nclass STLTopology\n{\nprotected:\n  Array<STLTriangle, STLTrigId> trias;\n  NgArray<STLTopEdge> topedges;\n  Array<Point<3>, STLPointId> points;\n  bool surface = false;\n\n  // mapping of sorted pair of points to topedge\n  INDEX_2_HASHTABLE<int> * ht_topedges;\n  // mapping of node to trigs\n  TABLE<int, IndexBASE<STLPointId>()> trigsperpoint; \n  // mapping of node to edges\n  TABLE<int> topedgesperpoint; \n  \n  // searchtree for trigs and points\n\n  BoxTree<3> * searchtree; // ADT\n  Point3dTree * pointtree;\n\n  Box<3> boundingbox;\n  double pointtol;\n\npublic:\n  enum STL_GEOM_STATUS { STL_GOOD, STL_WARNING, STL_ERROR };\n\nprotected:\n  STL_GEOM_STATUS status;\n  string statustext;\n  \n  bool topology_ok;\n  bool orientation_ok;\n\npublic:\n  STLTopology();\n  virtual ~STLTopology();\n\n  static STLGeometry * LoadNaomi (istream & ist);\n  DLL_HEADER static STLGeometry * Load (istream & ist, bool surface=false);\n  static STLGeometry * LoadBinary (istream & ist);\n\n  void Save (const filesystem::path & filename) const;\n  void SaveBinary (const filesystem::path & filename, const char* aname) const;\n  void SaveSTLE (const filesystem::path & filename) const; // stores trigs and edges\n\n  bool IsSurfaceSTL() const { return surface; }\n  void SetSurfaceSTL( bool surface_ ) { surface = surface_; }\n\n  virtual void DoArchive(Archive& ar)\n  {\n    ar & trias & points & boundingbox & pointtol;\n    if(ar.Input())\n      FindNeighbourTrigs();\n  }\n  \n  virtual void InitSTLGeometry (const NgArray<STLReadTriangle> & readtrigs);\n\n  virtual void TopologyChanged() {}; //do some things, if topology changed!\n\n  /// Generate topology tables\n  void FindNeighbourTrigs();\n\n  \n  void GetTrianglesInBox (const Box<3> & box,\n\t\t\t  NgArray<int> & trias) const;\n\n\n  int GetNP() const { return points.Size(); }\n  int AddPoint(const Point<3> & p) { points.Append(p); return points.Size(); }\n  const Point<3> & GetPoint(STLPointId nr) const { return points[nr]; } // .Get(nr); }\n  int GetPointNum (const Point<3> & p);\n  void SetPoint(STLPointId nr, const Point<3> & p) { points[nr] = p; } // { points.Elem(nr) = p; }\n  auto & GetPoints() const { return points; }\n\n  const Point<3> & operator[] (STLPointId i) const { return points[i]; }\n  Point<3> & operator[] (STLPointId i) { return points[i]; }\n\n\n\n\n  int GetNT() const { return trias.Size(); }\n  void AddTriangle(const STLTriangle& t);\n  const STLTriangle & GetTriangle (STLTrigId nr) const { return trias[nr]; } // .Get(nr); }\n  STLTriangle & GetTriangle (STLTrigId nr) { return trias[nr]; } // .Elem(nr); }\n  \n  const STLTriangle & operator[] (STLTrigId i) const { return trias[i]; }\n  STLTriangle & operator[] (STLTrigId i) { return trias[i]; }\n\n\n  int GetNTE() const { return topedges.Size(); }\n  const STLTopEdge & GetTopEdge (int nr) const { return topedges.Get(nr); }\n  STLTopEdge & GetTopEdge (int nr)  { return topedges.Elem(nr); }\n  DLL_HEADER int GetTopEdgeNum (int pi1, int pi2) const;\n\n\n  int NOTrigsPerPoint(int pn) { return trigsperpoint.EntrySize(pn); }\n  int TrigPerPoint(int pn, int i) { return trigsperpoint.Get(pn, i); }\n\n\n  int NTopEdgesPerPoint (int pn) const { return topedgesperpoint.EntrySize(pn); }\n  int TopEdgePerPoint (int pn, int ei) const { return topedgesperpoint.Get(pn, ei); }\n\n  \n  bool Topology_Ok() const { return topology_ok; }\n  bool Orientation_Ok() const { return orientation_ok; }\n\n  STL_GEOM_STATUS GetStatus () const { return status; }\n  const string & GetStatusText () const { return statustext; }\n\n  DLL_HEADER void InvertTrig (int trig);\n  DLL_HEADER void DeleteTrig (int trig);\n  DLL_HEADER void OrientAfterTrig (int trig);\n\n\n  // Table will be constructed, if topology is not ok\n  /// neighbourtrigs for surfacetrigs\n  TABLE<STLTrigId> neighbourtrigs;\n\n  /// get nr-th neighbour Triangle for triangle trig\n  int NONeighbourTrigs(STLTrigId trig) const { return neighbourtrigs.EntrySize(int(trig)); }\n  STLTrigId NeighbourTrig(STLTrigId trig, int nr) const { return neighbourtrigs.Get(int(trig),nr); }\n  int NeighbourTrigSorted(int trig, int nr) const;\n  void AddNeighbourTrig(STLTrigId i, STLTrigId nt) { neighbourtrigs.Add1(int(i), nt); }\n\n\n\n\n  int GetLeftTrig (int p1, int p2) const;\n  int GetRightTrig (int p1, int p2) const;\n\n  const Box<3> & GetBoundingBox () const { return boundingbox; }\n};\n\n} // namespace netgen\n\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/vsstl.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n\n#include <linalg.hpp>\n#include <stlgeom.hpp>\n\n#include <meshing.hpp>\n#include <visual.hpp>\n\n\n#include \"vsstl.hpp\"\n\n\nnamespace netgen\n{\n\n/*\n//mmm\n#include \"stlgeom/modeller.hpp\"\n*/\n\n/* *********************** Draw STL Geometry **************** */\n\nDLL_HEADER extern shared_ptr<Mesh> mesh;\n\n\n// #include \"../../ngtcltk/mvdraw.hpp\"\n\n\nVisualSceneSTLMeshing :: VisualSceneSTLMeshing ()\n  : VisualScene()\n{\n  selecttrig = 0;\n  nodeofseltrig = 1;\n}\n\nVisualSceneSTLMeshing :: ~VisualSceneSTLMeshing ()\n{\n  ;\n}\n\nvoid VisualSceneSTLMeshing :: DrawScene ()\n{\n  int i, j, k;\n\n  if (changeval != stlgeometry->GetNT())\n    BuildScene();\n  changeval = stlgeometry->GetNT();\n\n  int colormeshsize = vispar.colormeshsize;\n  \n  double hmin = 0.0, hmax = 1.0;\n\n  if (colormeshsize)\n    {\n      hmax = -1E50;\n      hmin = +1E50;\n      double ms;\n\n      for (i = 1; i <= stlgeometry->GetNP(); i++)\n\t{\n\t  ms = mesh->GetH (stlgeometry->GetPoint(i));\n\t  hmin = min2(hmin,ms);\n\t  hmax = max2(hmax,ms);\n\t}\n\n      //hmax = mparam.maxh;\n      //hmin = mesh->GetMinH (stlgeometry->GetBoundingBox().PMin(),\n      //\t\t\t    stlgeometry->GetBoundingBox().PMax());\n  \n      if (hmin == 0) hmin = 0.1 * hmax;\n      //hmax *= 1.1;\n    }\n  \n\n\n  glClearColor(backcolor, backcolor, backcolor, 1.0);\n  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n\n  SetLight();\n\n  glPushMatrix();\n  glMultMatrixd (transformationmat);\n\n  SetClippingPlane ();\n\n  glShadeModel (GL_SMOOTH);\n  glDisable (GL_COLOR_MATERIAL);\n  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n  glEnable (GL_BLEND);\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n  float mat_spec_col[] = { 1, 1, 1, 1 };\n  glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col);\n\n  double shine = vispar.shininess;\n  // double transp = vispar.transp;\n\n  glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);\n  glLogicOp (GL_COPY);\n\n  float mat_colred[]    = { 0.9f, 0.0f, 0.0f, 1.0f };\n  float mat_colgreen[]  = { 0.0f, 0.9f, 0.0f, 1.0f };\n  float mat_colblue[]   = { 0.1f, 0.1f, 1.0f, 1.0f };\n\n  float mat_colbluegreen[] = { 0.1f, 0.5f, 0.9f, 1.0f };\n  // float mat_colpink[]      = { 1.0f, 0.1f, 0.5f, 1.0f };\n  float mat_colviolet[]    = { 1.0f, 0.1f, 1.0f, 1.0f };\n  float mat_colbrown[]     = { 0.8f, 0.6f, 0.1f, 1.0f };\n  // float mat_colorange[]    = { 0.9f, 0.7f, 0.1f, 1.0f };\n  // float mat_colturquis[]   = { 0.0f, 1.0f, 0.8f, 1.0f };\n\n  float mat_colgrey[] = { 0.3f, 0.3f, 0.3f, 1.0f };\n\n  float mat_collred[]   = { 1.0f, 0.5f, 0.5f, 1.0f };\n  float mat_collgreen[] = { 0.2f, 1.9f, 0.2f, 1.0f };\n  float mat_collbrown[] = { 1.0f, 0.8f, 0.3f, 1.0f };\n\n  float mat_collgrey[] = { 0.8f, 0.8f, 0.8f, 1.0f };\n  // float mat_colmgrey[] = { 0.4f, 0.4f, 0.4f, 1.0f };\n\n  float mat_colstlbody[] = { 0.0f, 0.0f, 0.8f, 1.0f };\n  float mat_colseltrig[] = { 0.7f, 0.7f, 0.3f, 1.0f };\n  float mat_colseledge[] = { 0.7f, 0.7f, 1.0f, 1.0f };\n\n  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue);\n\n  float pgoff = 0.5f;\n\n  glPolygonOffset (pgoff*1, pgoff*1);\n  glEnable (GL_POLYGON_OFFSET_FILL);\n\n  glEnable (GL_NORMALIZE);\n\n  /*\n  {\n    //mmm\n    //test modeller\n    Modeller model;\n    \n    //MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01);\n    //model.Add(&z1);\n    //MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01);\n    //model.Add(&z2);\n    \n    MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01);\n    MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01);\n    MoCombine cb1(&z1,&z2);\n    model.Add(&cb1);\n    \n    NgArray<MoTriangle> trigs;\n    model.GetTriangles(trigs);\n    int i, k;\n    glBegin (GL_TRIANGLES);\n    for (i = 1; i <= trigs.Size(); i++)\n      {\n\tconst MoTriangle & tria = trigs.Get(i);\n\tglNormal3f (tria.normal.X(),\n\t\t    tria.normal.Y(),\n\t\t    tria.normal.Z());\n\t\n\tfor (k = 0; k < 3; k++)\n\t  {\n\t    glVertex3f (tria.pts[k].X(),\n\t\t\ttria.pts[k].Y(),\n\t\t\ttria.pts[k].Z());\n\t  }\n      }    \n    glEnd ();\n    \n\n  }\n\n*/\n\n\n\n  \n  if (!stlgeometry->trigsconverted)\n    {\n      glBegin (GL_TRIANGLES);\n      for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t{\n\t  /*\n\t  if (j % 10 == seltria)\n\t    glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t  GL_AMBIENT_AND_DIFFUSE, mat_colred);\n\t  */\n\n\t  const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t  glNormal3f (n.X(), n.Y(), n.Z());\n\t  /*\n\t  const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j);\n\t  glNormal3f (tria.normal.X(),\n\t\t      tria.normal.Y(),\n\t\t      tria.normal.Z());\n\t  */\n\n\t  \n\t  for (k = 1; k <= 3; k++)\n\t    {\n\t      const Point3d & tp = stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k));\n\t      glVertex3f (tp.X(), tp.Y(), tp.Z());\n\n\t    }\n\t  /*\n\t  if (j%10 == seltria)\n\t    glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t  GL_AMBIENT_AND_DIFFUSE, mat_colblue);\n\t  */\n\t}    \n      glEnd ();\n  \n      glDisable (GL_POLYGON_OFFSET_FILL);\n\n      int showtrias = vispar.stlshowtrias;\n\n      if (showtrias)\n\t{\n\t  float mat_coll[] = { 0.2f, 0.2f, 0.2f, 1.f };\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll);\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n      \n\t  glEnable (GL_NORMALIZE);\n      \n\t  glBegin (GL_TRIANGLES);\n\t  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t    {\n\t      const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t      glNormal3f (n.X(), n.Y(), n.Z());\n\t      /*\n\t      const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j);\n\t      glNormal3f (tria.normal.X(),\n\t\t\t  tria.normal.Y(),\n\t\t\t  tria.normal.Z());\n\t      */  \n\n\t      for (k = 1; k <= 3; k++)\n\t\t{\n\t\t  const Point3d & tp = \n\t\t    stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k));\n\t\t  glVertex3f (tp.X(), tp.Y(), tp.Z());\n\t\t  \n\t\t}\n\t      \n\t      /*\n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  glVertex3f (tria.pts[k].X(),\n\t\t\t      tria.pts[k].Y(),\n\t\t\t      tria.pts[k].Z());\n\t\t}\n\t      */\n\t    }    \n\t  glEnd ();\n\t}\n    }\n  else\n    {\n      int showfilledtrias = vispar.stlshowfilledtrias;\n\n      //(*mycout) << \"in \" << showfilledtrias << \", NT=\" << stlgeometry -> GetNT() << endl;\n\n      int chartnumber;\n      if (vispar.stlshowmarktrias)\n\tchartnumber = vispar.stlchartnumber + vispar.stlchartnumberoffset;\n      else\n\tchartnumber = stlgeometry->GetMeshChartNr();\n\n      if (showfilledtrias)\n\t{\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\t  if (colormeshsize)\n\t    glEnable (GL_COLOR_MATERIAL);\n\t  \n\t  glPolygonOffset (pgoff*4, pgoff*4);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\t  glEnable (GL_NORMALIZE);\n\n\n\t  glBegin (GL_TRIANGLES);\n\n\t  int selt = stlgeometry -> GetSelectTrig();\n\t  if (stldoctor.selectmode != 0) \n\t    {selt = 0; } //do not show selected triangle!!!!\n\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody);\n\n\t  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t    {\n\t      if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;}\n\n\t      if (j == selt)\n\t\t{\n\t\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseltrig);\n\t\t}\n\t      else if (j == selt+1)\n\t\t{\n\t\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody);\n\t\t}\n\t      \n\t      const STLTriangle& st = stlgeometry -> GetTriangle(j);\n\n\t      const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t      glNormal3f (n.X(), n.Y(), n.Z());\n\t  \n\t      /*\n\t      const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j);\n\t      glNormal3f (tria.normal.X(),\n\t\t\t  tria.normal.Y(),\n\t\t\t  tria.normal.Z());\n\t      */\n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  const Point3d & p = stlgeometry->GetPoint(st[k]);\n\t\t  if (colormeshsize)\n\t\t    {\n\t\t      SetOpenGlColor (mesh->GetH (p), hmin, hmax, 1);\n\t\t    }\n\n\t\t  glVertex3f (p.X(), p.Y(), p.Z());\n\t\t}\n\t    } \n   \n\t  glEnd ();\n\t}\n      \n      int foundseltrig = stlgeometry -> GetSelectTrig();\n      if (foundseltrig == 0 || foundseltrig > stlgeometry->GetNT() ||\n\t  (stldoctor.showvicinity && !stlgeometry->Vicinity(foundseltrig)))\n\t{foundseltrig = 0;}\n\n      if (foundseltrig)\n\t{\n\n\t  glPolygonOffset (pgoff*0, 0);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\n\t  //glDisable (GL_POLYGON_OFFSET_FILL);      \n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseledge);\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n\t  \n\t  glEnable (GL_NORMALIZE);\n\n\t  if (stldoctor.selectmode == 2)\n\t    {\n\t      //point\n\t      const STLTriangle& st = stlgeometry -> GetTriangle(foundseltrig);\n\t      const Point3d & p1 = stlgeometry->GetPoint(st[0]);\n\t      const Point3d & p2 = stlgeometry->GetPoint(st[1]);\n\t      const Point3d & p3 = stlgeometry->GetPoint(st[2]);\n\n\t      double cs = (Dist(p1,p2)+Dist(p2,p3)+Dist(p3,p1))/100.;\n\n\t      const Point3d & p = stlgeometry->GetPoint(st[nodeofseltrig-1]);\n\t      \n\t      glLineWidth (4);\n\t      glBegin (GL_LINES);\n\t      glVertex3f(p.X()+cs, p.Y()+cs, p.Z()+cs);\n\t      glVertex3f(p.X()-cs, p.Y()-cs, p.Z()-cs);\n\t      \n\t      glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs);\n\t      glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs);\n\n\t      glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs);\n\t      glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs);\n\t      \n\t      glVertex3f(p.X()+cs, p.Y()-cs, p.Z()+cs);\n\t      glVertex3f(p.X()-cs, p.Y()+cs, p.Z()-cs);\n\t      \n\t      glEnd ();\t  \n\t      glLineWidth (1);\n\t    }\n\t  else if (stldoctor.selectmode == 1 || \n\t\t   stldoctor.selectmode == 3 || \n\t\t   stldoctor.selectmode == 4)\n\t    {\n\t      //multiedge\n\t      \n\t      const NgArray<twoint>& me = stlgeometry->SelectedMultiEdge();\n\t      if (stlgeometry->GetSelectTrig() > 0 && \n\t\t  stlgeometry->GetSelectTrig() <= stlgeometry->GetNT() &&\n\t\t  me.Size())\n\t\t{\n\n\t\t  int en = stlgeometry->EdgeDataList().GetEdgeNum(me.Get(1).i1,me.Get(1).i2);\n\t\t  int status = stlgeometry->EdgeDataList().Get(en).GetStatus();\n\t\t  \n\t\t  switch (status)\n\t\t    {\n\t\t    case ED_CONFIRMED:\n\t\t      glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t\t    GL_AMBIENT_AND_DIFFUSE, mat_collgreen);\n\t\t      break;\n\t\t    case ED_CANDIDATE:\n\t\t      glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t\t    GL_AMBIENT_AND_DIFFUSE, mat_collbrown);\n\t\t      break;\n\t\t    case ED_EXCLUDED:\n\t\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collred);\n\t\t      break;\n\t\t    }\n\n\t\t  glLineWidth (2);\n\t\t  glBegin (GL_LINES);\n\t\t  for (j = 1; j <= me.Size(); j++)\n\t\t    { \n\t\t      Point3d p1 = stlgeometry->GetPoint(me.Get(j).i1);\n\t\t      Point3d p2 = stlgeometry->GetPoint(me.Get(j).i2);\n\t\t      \n\t\t      glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t      glVertex3f(p2.X(), p2.Y(), p2.Z());\n\t\t    }\n\t\t  glEnd ();\n\t\t  glLineWidth (1);\n\t\t}\n\t    }\n\t}\n\n      int showmarktrias = vispar.stlshowmarktrias || vispar.stlshowactivechart;\n \n      if (stldoctor.showmarkedtrigs)\n\t{\n\t  //(*mycout) << \"marked\" << endl;\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); //GL_LINE\n\t  glPolygonOffset (pgoff*1, pgoff*1);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbluegreen);\n\t  glEnable (GL_NORMALIZE);\n\n\t  glBegin (GL_TRIANGLES);\n\n\t  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t    {\n\t      if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) \n\t\t{continue;}\n\n\t      if (!stlgeometry->IsMarkedTrig(j)) \n\t\t{continue;}\n\t      \n\t      const STLTriangle& st = stlgeometry -> GetTriangle(j);\n\n\t      const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t      glNormal3f (n.X(), n.Y(), n.Z());\n\t      /*\n\t      const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j);\n\t      glNormal3f (tria.normal.X(),\n\t\t\t  tria.normal.Y(),\n\t\t\t  tria.normal.Z());\n\t      */\n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  const Point3d & p = stlgeometry->GetPoint(st[k]);\n\t\t  glVertex3f (p.X(), p.Y(), p.Z());\n\t\t}\n\t    }    \n\t  glEnd ();\n\n\t  //show OpenSegments on original geometry\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colviolet);\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n\t  glPolygonOffset (pgoff*1, 1);\n      \n\t  glEnable (GL_NORMALIZE);\n      \n\t  glBegin (GL_LINES);\n\n\t  if (stlgeometry->GetNMarkedSegs())\n\t    {\n\t      Point<3> p1,p2;\t      \n\t      for (j = 1; j <= stlgeometry -> GetNMarkedSegs(); j++)\n\t\t{\n\t\t  stlgeometry->GetMarkedSeg(j,p1,p2);\n\t\t  glVertex3dv(&p1(0));\n\t\t  glVertex3dv(&p2(0));\n\t\t}\n\t    }\n\t  glEnd ();\n\t}\n\n\n      if (stldoctor.showfaces)\n\t{\n\t  int facenumber = vispar.stlchartnumber + vispar.stlchartnumberoffset;\n\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\t  glPolygonOffset (pgoff*3, 3);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collgrey);\n\t  glEnable (GL_NORMALIZE);\n\n\t  glBegin (GL_TRIANGLES);\n\n\t  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t    {\n\t      if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) \n\t\t{continue;}\n\n\t      //(*mycout) << \" facenum = \" << stlgeometry->GetTriangle(j).GetFaceNum() << \" \";\n\t      if (stlgeometry->GetTriangle(j).GetFaceNum() != facenumber) \n\t\t{continue;}\n\t      \n\t      const STLTriangle& st = stlgeometry -> GetTriangle(j);\n\n\t      const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t      glNormal3f (n.X(), n.Y(), n.Z());\n\t      /*\n\t      const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j);\n\t      glNormal3f (tria.normal.X(),\n\t\t\t  tria.normal.Y(),\n\t\t\t  tria.normal.Z());\n\t      */\n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  Point3d p = stlgeometry->GetPoint(st[k]);\n\t\t  glVertex3f (p.X(), p.Y(), p.Z());\n\t\t}\n\t    }    \n\t  glEnd ();\n\t}\n\n      if (showmarktrias && stlgeometry->AtlasMade())\n\t{\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\t  glPolygonOffset (pgoff*3, 3);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\n\t  glBegin (GL_TRIANGLES);\n\t  \n\t  if (chartnumber >= 1 && chartnumber <= stlgeometry->GetNOCharts())\n\t    {\n\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown);\n\t      const STLChart& chart = stlgeometry->GetChart(chartnumber);\n\t      for (j = 1; j <= chart.GetNChartT(); j++)\n\t\t{\n\t\t  /*\n\t\t  if (j == charttrignumber) \n\t\t    {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);}\n\t\t  else\n\t\t    {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown);}\n\t\t  */\n\t\t  const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetChartTrig1(j));\n\n\t\t  \n\t\t  const Vec3d & n = stlgeometry->GetTriangle(chart.GetChartTrig1(j)).Normal();\n\t\t  glNormal3f (n.X(), n.Y(), n.Z());\n\t\t  /*\n\t\t  const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetChartTrig(j));\n\t\t  glNormal3f (tria.normal.X(),\n\t\t\t      tria.normal.Y(),\n\t\t\t      tria.normal.Z());\n\t\t  */\n\t\t  for (k = 0; k < 3; k++)\n\t\t    {\n\t\t      glVertex3f (stlgeometry->GetPoint(st[k])(0),\n\t\t\t\t  stlgeometry->GetPoint(st[k])(1),\n\t\t\t\t  stlgeometry->GetPoint(st[k])(2));\n\t\t    }\n\t\t}\n\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen);\n\t      \n\t      for (j = 1; j <= chart.GetNOuterT(); j++)\n\t\t{\n\t\t  \n\t\t  const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetOuterTrig1(j));\n\n\t\t  const Vec3d & n = stlgeometry->GetTriangle(chart.GetOuterTrig1(j)).Normal();\n\t\t  glNormal3f (n.X(), n.Y(), n.Z());\n\n\n\t\t  /*\n\t\t  const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetOuterTrig(j));\n\t\t  glNormal3f (tria.normal.X(),\n\t\t\t      tria.normal.Y(),\n\t\t\t      tria.normal.Z());\n\t\t  */\n\t\t  for (k = 0; k < 3; k++)\n\t\t    {\n\t\t      glVertex3f (stlgeometry->GetPoint(st[k])(0),\n\t\t\t\t  stlgeometry->GetPoint(st[k])(1),\n\t\t\t\t  stlgeometry->GetPoint(st[k])(2));\n\t\t    }\n\t\t}\n\t    }\n\t  glEnd ();\n\t}\n\n      int showtrias = vispar.stlshowtrias;\n\n      if (showtrias)\n\t{\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgrey);\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n\t  glPolygonOffset (pgoff*2, 2);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\t  glEnable (GL_NORMALIZE);\n\n\t  glBegin (GL_TRIANGLES);\n\t  \n\t  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n\t    {\t  \n\t      if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;}\n\n\t      const STLTriangle& st = stlgeometry -> GetTriangle(j);\n\n\t      const Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\t      glNormal3f (n.X(), n.Y(), n.Z());\n\t      /*\n\t      const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j);\n\t      glNormal3f (tria.normal.X(),\n\t\t\t  tria.normal.Y(),\n\t\t\t  tria.normal.Z());\n\t      */\t  \n\t      for (k = 0; k < 3; k++)\n\t\t{\n\t\t  glVertex3f (stlgeometry->GetPoint(st[k])(0),\n\t\t\t      stlgeometry->GetPoint(st[k])(1),\n\t\t\t      stlgeometry->GetPoint(st[k])(2));\n\t\t}\n\t    }    \n\t  glEnd ();\n\t} \n\n      int showedges = vispar.stlshowedges;\n      \n      if (showedges)\n\t{\n\t  glPolygonOffset (pgoff*1, 1);\n\t  glEnable (GL_POLYGON_OFFSET_FILL);\n\t  //glDisable (GL_POLYGON_OFFSET_FILL);      \n\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen);\n\t  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n      \n\t  glEnable (GL_NORMALIZE);\n      \n\t  glBegin (GL_LINES);\n\n\t  /*\n\t  if (stldoctor.useexternaledges)\n\t    {\n\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colorange);\n\t      for (j = 1; j <= stlgeometry -> NOExternalEdges(); j++)\n\t\t{\n\t\t  twoint v = stlgeometry->GetExternalEdge(j);\n\t\t  Point3d p1 = stlgeometry->GetPoint(v.i1);\n\t\t  Point3d p2 = stlgeometry->GetPoint(v.i2);\n\t\t  \n\t\t  Vec3d n1 = stlgeometry->GetNormal(v.i1);\n\t\t  Vec3d n2 = stlgeometry->GetNormal(v.i2);\n\t\t  \n\t\t  glNormal3f(n1.X(), n1.Y(), n1.Z());\n\t\t  glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t  glNormal3f(n2.X(), n2.Y(), n2.Z());\n\t\t  glVertex3f(p2.X(), p2.Y(), p2.Z());\n\t\t}\n\t    }\n\t  */\n\n\t  \n\t  if (!stlgeometry->meshlines.Size() || !stldoctor.drawmeshededges)\n\t    {\n\t      /*\n\t      for (j = 1; j <= stlgeometry -> GetNE(); j++)\n\t\t{\n\t\t  STLEdge v = stlgeometry->GetEdge(j);\n\t\t  Point3d p1 = stlgeometry->GetPoint(v.pts[0]);\n\t\t  Point3d p2 = stlgeometry->GetPoint(v.pts[1]);\n\t\t  \n\t\t  Vec3d n1 = stlgeometry->GetNormal(v.pts[0]);\n\t\t  Vec3d n2 = stlgeometry->GetNormal(v.pts[1]);\n\t\t  \n\t\t  glNormal3f(n1.X(), n1.Y(), n1.Z());\n\t\t  glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t  glNormal3f(n2.X(), n2.Y(), n2.Z());\n\t\t  glVertex3f(p2.X(), p2.Y(), p2.Z());\n\t\t}\n\t      */\n\t      const STLEdgeDataList& ed = stlgeometry->EdgeDataList();\n\t      for (i = 1; i <= ed.Size(); i++)\n\t\t{\n\t\t  if (ed.Get(i).GetStatus() != ED_UNDEFINED)\n\t\t    {\n\t\t      switch (ed.Get(i).GetStatus())\n\t\t\t{\n\t\t\tcase ED_CONFIRMED:\n\t\t\t  glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t\t\tGL_AMBIENT_AND_DIFFUSE, mat_colgreen);\n\t\t\t  break;\n\t\t\tcase ED_CANDIDATE:\n\t\t\t  glMaterialfv (GL_FRONT_AND_BACK, \n\t\t\t\t\tGL_AMBIENT_AND_DIFFUSE, mat_colbrown);\n\t\t\t  break;\n\t\t\tcase ED_EXCLUDED:\n\t\t\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);\n\t\t\t  break;\n\t\t\t}\n\n\t\t      if (ed.Get(i).GetStatus() == ED_EXCLUDED && !stldoctor.showexcluded) continue;\n\n\t\t      Point3d p1 = stlgeometry->GetPoint(ed.Get(i).PNum(1));\n\t\t      Point3d p2 = stlgeometry->GetPoint(ed.Get(i).PNum(2));\n\t\t      glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t      glVertex3f(p2.X(), p2.Y(), p2.Z());\t\t   \n\t\t    }\n\t\t}\n\t    }\n\n\t  /*\n\t  else     \n\t  if (stlgeometry->meshlines.Size() == 0)\n\t    {\n\t      for (j = 1; j <= stlgeometry->GetNLines(); j++)\n\t\t{\n\t\t  STLLine* line = stlgeometry->GetLine(j);\n\t\t  int pn1, pn2;\n\t\t  for (int k = 1; k <= line->NP()-1; k++)\n\t\t    {\n\t\t      pn1 = line->PNum(k);\n\t\t      pn2 = line->PNum(k+1);\n\n\t\t      Point3d p1 = stlgeometry->GetPoint(pn1);\n\t\t      Point3d p2 = stlgeometry->GetPoint(pn2);\n\t\t  \n\t\t      Vec3d n1 = stlgeometry->GetNormal(pn1);\n\t\t      Vec3d n2 = stlgeometry->GetNormal(pn2);\n\t\t  \n\t\t      glNormal3f(n1.X(), n1.Y(), n1.Z());\n\t\t      glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t      glNormal3f(n2.X(), n2.Y(), n2.Z());\n\t\t      glVertex3f(p2.X(), p2.Y(), p2.Z());\n\t\t    }\n\t\t}    \n\t    }\n\t  */\n\t    \n\t  else if (stlgeometry->meshlines.Size() != 0)\n\t    {\n\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen);\n\t      for (j = 1; j <= stlgeometry->meshlines.Size(); j++)\n\t\t{\n\t\t  STLLine* line = stlgeometry->meshlines.Get(j);\n\t\t  int pn1, pn2;\n\t\t  for (int k = 1; k <= line->NP()-1; k++)\n\t\t    {\n\t\t      pn1 = line->PNum(k);\n\t\t      pn2 = line->PNum(k+1);\n\n\t\t      Point3d p1 = stlgeometry->meshpoints.Get(pn1);\n\t\t      Point3d p2 = stlgeometry->meshpoints.Get(pn2);\n\t\t  \t\t  \n\t\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen);\n\t\t      glVertex3f(p1.X(), p1.Y(), p1.Z());\n\t\t      glVertex3f(p2.X(), p2.Y(), p2.Z());\n\n\t\t      \n\t\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);\n\t\t      double cs = 0.02*Dist(p1,p2);\n\t\t      glVertex3f(p1.X()+cs, p1.Y()+cs, p1.Z()+cs);\n\t\t      glVertex3f(p1.X()-cs, p1.Y()-cs, p1.Z()-cs);\n\t\t      glVertex3f(p2.X()+cs, p2.Y()+cs, p2.Z()+cs);\n\t\t      glVertex3f(p2.X()-cs, p2.Y()-cs, p2.Z()-cs);\n\n\t\t      glVertex3f(p1.X()-cs, p1.Y()+cs, p1.Z()+cs);\n\t\t      glVertex3f(p1.X()+cs, p1.Y()-cs, p1.Z()-cs);\n\t\t      glVertex3f(p2.X()-cs, p2.Y()+cs, p2.Z()+cs);\n\t\t      glVertex3f(p2.X()+cs, p2.Y()-cs, p2.Z()-cs);\n\t\t      \n\t\t    }\n\t\t}\n\t    }\n\t    \n\n\t  glEnd ();\n\t}\n\n      if (stldoctor.showedgecornerpoints && stlgeometry->LineEndPointsSet())\n\t{\n\t  glPointSize (5);\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);\n\t  glBegin (GL_POINTS);\n\t  for (i = 1; i <= stlgeometry->GetNP(); i++)\n\t    {\n\t      if (stlgeometry->IsLineEndPoint(i))\n\t\t{\n\t\t  const Point3d p = stlgeometry->GetPoint(i);\n\t\t  glVertex3f (p.X(), p.Y(), p.Z());\n\t\t}\n\t    }\n\t  glEnd();\n\t  \n\t}\n\n\n    }\n\n \n  glPopMatrix();\n\n  if (vispar.colormeshsize)\n    DrawColorBar (hmin, hmax, 1);\n\n  glFinish();  \n}\n\n\nvoid VisualSceneSTLMeshing :: BuildScene (int zoomall)\n{\n  if (selecttrig && zoomall == 2)\n    center = stlgeometry -> GetPoint ( stlgeometry->GetTriangle(selecttrig).PNum(nodeofseltrig));\n  else\n    center = stlgeometry -> GetBoundingBox().Center();\n\n  rad = stlgeometry -> GetBoundingBox().Diam() / 2;\n\n  CalcTransformationMatrices();\n}\n\n\n\nvoid VisualSceneSTLMeshing :: MouseDblClick (int px, int py)\n{\n  //  (*mycout) << \"dblclick: \" << px << \" - \" << py << endl;\n  \n\n  int i, j, k, hits;\n\n  // select surface triangle by mouse click\n\n  GLuint selbuf[10000];\n  glSelectBuffer (10000, selbuf);\n\n\n  glRenderMode (GL_SELECT);\n\n  GLint viewport[4];\n  glGetIntegerv (GL_VIEWPORT, viewport);\n\n  /*  \n  (*mycout) << \"viewport = \" << viewport[0] << \" \" \n       << viewport[1] << \" \" << viewport[2] << \" \" << viewport[3] << endl;\n  */\n\n  glMatrixMode (GL_PROJECTION); \n  glPushMatrix();\n\n\n  GLdouble projmat[16];\n  glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n\n  glLoadIdentity(); \n  gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); \n  glMultMatrixd (projmat);\n  \n\n\n  glClearColor(backcolor, backcolor, backcolor, 1.0);\n  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n  glMatrixMode (GL_MODELVIEW); \n\n  glPushMatrix();\n  glMultMatrixd (transformationmat);\n\n\n  glInitNames();\n  glPushName (1);\n\n\n  glEnable (GL_POLYGON_OFFSET_FILL);\n  for (j = 1; j <= stlgeometry -> GetNT(); j++)\n    {\n      if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;}\n\n      const STLTriangle& st = stlgeometry -> GetTriangle(j);\n\t\t\t\n      //const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j);\n      //glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z());\n      \n      if (stldoctor.selectmode == 0)\n\t{\n\t  glLoadName (j);\n\t  glBegin (GL_TRIANGLES);\n\t  for (k = 0; k < 3; k++)\n\t    {\n\t      Point3d p = stlgeometry->GetPoint(st[k]);\n\t      glVertex3f (p.X(), p.Y(), p.Z());\n\t    }\n\t  glEnd ();\n\t} \n      else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3\n\t        || stldoctor.selectmode == 4)\n\t{\n\t  Point3d pm = Center(stlgeometry->GetPoint(st[0]),\n\t\t\t      stlgeometry->GetPoint(st[1]),\n\t\t\t      stlgeometry->GetPoint(st[2]));\n\n\t  for (k = 0; k < 3; k++)\n\t    {\n\t      glLoadName (j*3+k-2);\n\t      glBegin (GL_TRIANGLES);\n\n\t      Point3d p1 = stlgeometry->GetPoint(st[k]);\n\t      Point3d p2 = stlgeometry->GetPoint(st[(k+1)%3]);\n\t      glVertex3f (p1.X(), p1.Y(), p1.Z());\n\t      glVertex3f (p2.X(), p2.Y(), p2.Z());\n\t      glVertex3f (pm.X(), pm.Y(), pm.Z());\n\n\t      glEnd ();\n\t    }\n\t}\n      else\n\t{\n\t  Point3d pm1 = Center(stlgeometry->GetPoint(st[0]),\n\t\t\t       stlgeometry->GetPoint(st[1]));\n\t  Point3d pm2 = Center(stlgeometry->GetPoint(st[1]),\n\t\t\t       stlgeometry->GetPoint(st[2]));\n\t  Point3d pm3 = Center(stlgeometry->GetPoint(st[2]),\n\t\t\t       stlgeometry->GetPoint(st[0]));\n\n\t  Point3d p1 = stlgeometry->GetPoint(st[0]);\n\t  Point3d p2 = stlgeometry->GetPoint(st[1]);\n\t  Point3d p3 = stlgeometry->GetPoint(st[2]);\n\n\t  glLoadName (j*4-3);\n\t  glBegin (GL_TRIANGLES);\n\t  glVertex3f (p1.X(), p1.Y(), p1.Z());\n\t  glVertex3f (pm1.X(), pm1.Y(), pm1.Z());\n\t  glVertex3f (pm3.X(), pm3.Y(), pm3.Z());\n\t  glEnd ();\n\n\t  glLoadName (j*4-2);\n\t  glBegin (GL_TRIANGLES);\n\t  glVertex3f (p2.X(), p2.Y(), p2.Z());\n\t  glVertex3f (pm2.X(), pm2.Y(), pm2.Z());\n\t  glVertex3f (pm1.X(), pm1.Y(), pm1.Z());\n\t  glEnd ();\n\n\t  glLoadName (j*4-1);\n\t  glBegin (GL_TRIANGLES);\n\t  glVertex3f (p3.X(), p3.Y(), p3.Z());\n\t  glVertex3f (pm3.X(), pm3.Y(), pm3.Z());\n\t  glVertex3f (pm2.X(), pm2.Y(), pm2.Z());\n\t  glEnd ();\n\n\t  glLoadName (j*4);\n\t  glBegin (GL_TRIANGLES);\n\t  glVertex3f (pm1.X(), pm1.Y(), pm1.Z());\n\t  glVertex3f (pm2.X(), pm2.Y(), pm2.Z());\n\t  glVertex3f (pm3.X(), pm3.Y(), pm3.Z());\n\t  glEnd ();\n\t}\n    }    \n\n  glPopName();\n\n  glMatrixMode (GL_PROJECTION); \n  glPopMatrix();\n\n  glMatrixMode (GL_MODELVIEW); \n  glPopMatrix();\n\n  glFlush();  \n\n\t\n  hits = glRenderMode (GL_RENDER);\n\n  //  (*mycout) << \"hits = \" << hits << endl;\n\n  //int minrec = -1;\n  int minname = 0;\n  GLuint mindepth = 0;\n  for (i = 0; i < hits; i++)\n    {\n      int curname = selbuf[4*i+3];\n      GLuint curdepth = selbuf[4*i+1];\n\n      /*      \n      (*mycout) << selbuf[4*i] << \" \" << selbuf[4*i+1] << \" \" \n\t   << selbuf[4*i+2] << \" \" << selbuf[4*i+3] << endl;\n      */\n      if (curname &&\n\t  (curdepth < mindepth || !minname))\n\t{\n\t  //minrec = i;\n\t  mindepth = curdepth;\n\t  minname = curname;\n\t}\n    }\n\n  if (!minname) {return;}\n  \n  if (stldoctor.selectmode == 0)\n    {\n      int oldtrig = selecttrig;\n      selecttrig = minname;\n      if (selecttrig == oldtrig)\n\tnodeofseltrig = (nodeofseltrig % 3) + 1;\n      else\n\tnodeofseltrig = 1;\n\n      stlgeometry->SetSelectTrig(selecttrig);\n      stlgeometry->SetNodeOfSelTrig(nodeofseltrig);\n      stlgeometry->PrintSelectInfo();\n      \n    }\n  else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4)\n    {\n      selecttrig = (minname-1) / 3 + 1;\n      nodeofseltrig = minname-selecttrig*3+3;\n\n      stlgeometry->SetSelectTrig(selecttrig);\n      stlgeometry->SetNodeOfSelTrig(nodeofseltrig);\n      stlgeometry->PrintSelectInfo();\n\n      if (stldoctor.selectmode == 1)\n\t{\n\t  stlgeometry->BuildSelectedEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig),\n\t\t\t\t\t\tstlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1)));\n\t}\n      if (stldoctor.selectmode == 3)\n\t{\n\t  stlgeometry->BuildSelectedMultiEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig),\n\t\t\t\t\t\t     stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1)));\n\t}\n      else if (stldoctor.selectmode == 4)\n\t{\n\t  stlgeometry->BuildSelectedCluster(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig),\n\t\t\t\t\t\t   stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1)));\n\t}\n \n      switch (stldoctor.edgeselectmode)\n\t{\n\tcase 1: stlgeometry->STLDoctorUndefinedEdge(); break;\n\tcase 2: stlgeometry->STLDoctorConfirmEdge(); break;\n\tcase 3: stlgeometry->STLDoctorCandidateEdge(); break;\n\tcase 4: stlgeometry->STLDoctorExcludeEdge(); break;\n\tdefault: break;\n\t}\n    }\n  else if (stldoctor.selectmode == 2)\n    {\n      selecttrig = (minname-1) / 4 + 1;\n      nodeofseltrig = minname-selecttrig*4+4;\n      if (nodeofseltrig == 4) {nodeofseltrig = 1;}\n\n      stlgeometry->SetSelectTrig(selecttrig);\n      stlgeometry->SetNodeOfSelTrig(nodeofseltrig);\n      stlgeometry->PrintSelectInfo();\n\n    }\n\n  if (stldoctor.showtouchedtrigchart && stlgeometry->AtlasMade() && stlgeometry->GetSelectTrig())\n    {\n      vispar.stlchartnumber =  stlgeometry->GetChartNr(stlgeometry->GetSelectTrig());\n      vispar.stlchartnumberoffset = 0;\n    }\n  \n}\n\n\n\n\n// VisualSceneSTLMeshing vsstlmeshing;\n\n\n\n\n\n  /* *********************** Draw STL Geometry **************** */\n\n\n  VisualSceneSTLGeometry :: VisualSceneSTLGeometry ()\n    : VisualScene()\n  {\n    ;\n  }\n\n  VisualSceneSTLGeometry :: ~VisualSceneSTLGeometry ()\n  {\n    ;\n  }\n\n  void VisualSceneSTLGeometry :: DrawScene ()\n  {\n    if (changeval != stlgeometry->GetNT())\n      BuildScene();\n\n    changeval = stlgeometry->GetNT();\n\n\n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    SetLight();\n\n\n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n\n\n\n    glShadeModel (GL_SMOOTH);\n    glDisable (GL_COLOR_MATERIAL);\n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n    glEnable (GL_BLEND);\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n\n    double shine = vispar.shininess;\n    // double transp = vispar.transp;\n\n    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);\n    glLogicOp (GL_COPY);\n\n\n    float mat_col[] = { 0.2f, 0.2f, 0.8f, 1.0f};\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n    glPolygonOffset (1, 1);\n    glEnable (GL_POLYGON_OFFSET_FILL);\n\n    glCallList (trilists.Get(1));\n\n    glDisable (GL_POLYGON_OFFSET_FILL);\n\n\n    int showtrias = vispar.showstltrias;\n\n    if (showtrias)\n      {\n\tfloat mat_coll[] = { 0.2f, 0.2f, 0.2f, 1.0f };\n\tglMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll);\n\tglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n      \n\tglCallList (trilists.Get(1));\n      }\n\n    /*\n\n    glBegin (GL_TRIANGLES);\n    for (j = 1; j <= stlgeometry -> GetNT(); j++)\n    {\n    const STLTriangle & tria = stlgeometry -> GetTriangle(j);\n    glNormal3f (tria.normal.X(),\n    tria.normal.Y(),\n    tria.normal.Z());\n\t\t  \n    for (k = 0; k < 3; k++)\n    {\n    glVertex3f (tria.pts[k].X(),\n    tria.pts[k].Y(),\n    tria.pts[k].Z());\n    }\n    }    \n    glEnd ();\n    */  \n\n\n\n \n    glPopMatrix();\n    glFinish();  \n  }\n\n\n  void VisualSceneSTLGeometry :: BuildScene (int zoomall)\n  {\n    //  cout << \"rebuild stl geometry scene\" << endl;\n\n    center = stlgeometry -> GetBoundingBox().Center();\n    rad = stlgeometry -> GetBoundingBox().Diam() / 2;\n\n\n    CalcTransformationMatrices();\n\n    for (int i = 1; i <= trilists.Size(); i++)\n      glDeleteLists (trilists.Elem(i), 1);\n    trilists.SetSize(0);\n\n\n    trilists.Append (glGenLists (1));\n    glNewList (trilists.Last(), GL_COMPILE);\n\n    glEnable (GL_NORMALIZE);\n\n    glBegin (GL_TRIANGLES);\n    for (int j = 1; j <= stlgeometry -> GetNT(); j++)\n      {\n\tconst Vec3d & n = stlgeometry->GetTriangle(j).Normal();\n\tglNormal3f (n.X(), n.Y(), n.Z());\n      \n\tfor (int k = 1; k <= 3; k++)\n\t  {\n\t    const Point3d & p = \n\t      stlgeometry->GetPoint (stlgeometry -> GetTriangle(j).PNum(k));\n\t    glVertex3f (p.X(),p.Y(), p.Z());\n\t  }\n      }    \n    glEnd ();\n      \n    glEndList ();\n  }\n \n}\n\n\n\n#ifdef NG_PYTHON\n\n\n#include <../general/ngpython.hpp>\n#include <core/ngcore_api.hpp>\n\nNGCORE_API_EXPORT void ExportSTLVis(py::module &m)\n{\n\tusing namespace netgen;\n\n\tpy::class_<VisualSceneSTLGeometry, shared_ptr<VisualSceneSTLGeometry>>\n\t\t(m, \"VisualSceneSTLGeometry\")\n\t\t.def(\"Draw\", &VisualSceneSTLGeometry::DrawScene)\n\t\t;\n\n    m.def(\"SetBackGroundColor\", &VisualSceneSTLGeometry::SetBackGroundColor);\n\n\tm.def(\"VS\",\n\t\t[](STLGeometry & geom)\n\t{\n\t\tauto vs = make_shared<VisualSceneSTLGeometry>();\n\n\t\tvs->SetGeometry(&geom);\n\t\treturn vs;\n\t});\n}\n\nPYBIND11_MODULE(libstlvis, m) {\n  ExportSTLVis(m);\n}\n#endif\n"
  },
  {
    "path": "libsrc/stlgeom/vsstl.hpp",
    "content": "#ifndef FILE_VSSTL\n#define FILE_VSSTL\n\n/**************************************************************************/\n/* File:   vsstl.hpp                                                      */\n/* Author: Joachim Schoeberl                                              */\n/* Date:   05. Jan. 2011                                                  */\n/**************************************************************************/\n\nnamespace netgen\n{\n\n class NGGUI_API VisualSceneSTLGeometry : public VisualScene\n  {\n    NgArray<int> trilists;\n    class STLGeometry * stlgeometry;\n\n  public:\n    VisualSceneSTLGeometry ();\n    virtual ~VisualSceneSTLGeometry ();\n    void SetGeometry (class STLGeometry * astlgeometry) { stlgeometry = astlgeometry; }\n\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n  };\n\n\n  class NGGUI_API VisualSceneSTLMeshing : public VisualScene\n  {\n    NgArray<int> trilists;\n    int selecttrig, nodeofseltrig;\n    class STLGeometry * stlgeometry;\n\n  public:\n    VisualSceneSTLMeshing ();\n    virtual ~VisualSceneSTLMeshing ();\n\n    void SetGeometry (class STLGeometry * astlgeometry)\n    {\n      stlgeometry = astlgeometry;\n      stlgeometry->SetSelectTrig(selecttrig);\n      stlgeometry->SetNodeOfSelTrig(nodeofseltrig);\n    }\n\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n    virtual void MouseDblClick (int px, int py);\n\n    int seltria;\n  };\n\n\n\n}\n\n\n\n#endif\n"
  },
  {
    "path": "libsrc/visualization/CMakeLists.txt",
    "content": "target_sources(nggui PRIVATE\n    importsolution.cpp\n    meshdoc.cpp\n    mvdraw.cpp\n    vsfieldlines.cpp\n    vsmesh.cpp\n    vssolution.cpp\n    visualpkg.cpp\n)\ntarget_link_libraries( nggui PUBLIC \"$<BUILD_INTERFACE:netgen_python>\" ${OPENGL_LIBRARIES} nglib)\n\ninstall(FILES\n  meshdoc.hpp mvdraw.hpp visual_api.hpp\n  vispar.hpp visual.hpp vssolution.hpp\n  DESTINATION ${NG_INSTALL_DIR_INCLUDE}/visualization COMPONENT netgen_devel\n)\n"
  },
  {
    "path": "libsrc/visualization/importsolution.cpp",
    "content": "//\n//  Read solution file\n//\n\n#include \"visual_api.hpp\"\n\n#include <mystdlib.h>\n\n\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <csg.hpp>\n#include <meshing.hpp>\n\n#include <nginterface.h>\n\nnamespace netgen\n{\n\n  DLL_HEADER extern shared_ptr<Mesh> mesh;\n\nNGGUI_API void ImportSolution2 (const char * filename)\n{\n  ifstream inf (filename);\n  char buf[100], name[1000];\n  int i, size, comps, order;\n  bool iscomplex;\n  std::string type;\n  Flags flags;\n\n  while (1)\n    {\n      buf[0] = 0;\n      inf >> buf;\n      if (strcmp (buf, \"solution\") == 0)\n\t{\n\t  inf >> name;\n\t  \n\t  inf >> buf[0];\n\t  flags.DeleteFlags ();\n\t  while (buf[0] == '-')\n\t    {\n\t      inf >> buf[1];\n\t      inf.putback (buf[1]);\n\t      if (!isalpha (buf[1]))\n\t\t{\n\t\t  break;\n\t\t}\n\t      inf >> (buf+1);\n\t      flags.SetCommandLineFlag (buf);\n\t      buf[0] = 0;\n\t      inf >> buf[0];\n\t    }\n\t  inf.putback (buf[0]);\n\n\t  (*testout) << \"Flags: \" << endl;\n\t  flags.PrintFlags (*testout);\n\t  (*testout) << \"done\" << endl;\n\n\t  size = int(flags.GetNumFlag (\"size\", mesh->GetNP())); // Ng_GetNP()));\n\t  comps = int(flags.GetNumFlag (\"components\", 1));\n\t  type = flags.GetStringFlag (\"type\", \"nodal\");\n\t  order = int(flags.GetNumFlag (\"order\", 1));\n\t  iscomplex = flags.GetDefineFlag (\"complex\");\n\n\t  double * sol = new double[size*comps];\n\t  \n\t  (*testout) << \"import solution \" << name << \" size = \" << size << \" comps = \" << comps << \" order = \" << order << endl;\n\n\t  for (i = 0; i < size*comps; i++)\n\t    {\n\t      inf >> sol[i];\n\t      //\t      (*testout) << \"sol: \" << sol[i] << endl;\n\t    }\n\t  \n\t  Ng_SolutionData soldata;\n\t  Ng_InitSolutionData (&soldata);\n\t  soldata.name = name;\n\t  soldata.data = sol;\n\t  soldata.dist = comps;\n\t  soldata.components = comps;\n\t  soldata.order = order;\n\t  soldata.iscomplex = iscomplex;\n\t  soldata.soltype = NG_SOLUTION_NODAL;\n          soldata.draw_surface = 1;\n          soldata.draw_volume = 1;\n\t  if (type == \"element\")\n            {\n              soldata.soltype = NG_SOLUTION_ELEMENT;\n              soldata.draw_surface = 0;\n            }\n\t  if (type == \"surfaceelement\")\n            {\n              soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT;\n              soldata.draw_volume = 0;\n            }\n\t  if (type == \"noncontinuous\")\n\t    soldata.soltype = NG_SOLUTION_NONCONTINUOUS;\n\t  if (type == \"surfacenoncontinuous\")\n\t    soldata.soltype = NG_SOLUTION_SURFACE_NONCONTINUOUS;\n\n\t  Ng_SetSolutionData (&soldata);\n\t  }\n      else\n\t{\n\t  //\t  cout << \"kw = (\" << buf << \")\" << endl;\n\t  (*testout) << \"kw = (\" << buf << \")\" << endl;\n\t  break;\n\t}\n    }\n  /*\n  struct Ng_SolutionData\n    {\n      char * name;      // name of gridfunction\n      double * data;    // solution values\n      int components;   // used components in solution vector\n      int dist;         // num of doubles per entry (alignment!)\n      Ng_SolutionType soltype;  // type of solution function\n  };\n\n  // initialize solution data with default arguments\n  void Ng_InitSolutionData (Ng_SolutionData * soldata);\n  // set solution data\n  void Ng_SetSolutionData (Ng_SolutionData * soldata);\n  */\n}\n\n\n\n}\n"
  },
  {
    "path": "libsrc/visualization/meshdoc.cpp",
    "content": "#ifndef NOTCL\n\n#include <mystdlib.h>\n\n#include <meshing.hpp>\n\n// #include \"incvis.hpp\"\n\n\n#include <visual.hpp>\n#include <inctcl.hpp>\n\nnamespace netgen\n{\n  // #include \"meshdoc.hpp\"\n\n\nMeshDoctorParameters meshdoctor;\n\nDLL_HEADER extern shared_ptr<Mesh> mesh;\n\n\n\nVisualSceneMeshDoctor :: VisualSceneMeshDoctor ()\n  : VisualScene()\n{\n  filledlist = 0;\n  outlinelist = 0;\n  edgelist = 0;\n  selelement = 0;\n  locpi = 1;\n  selpoint = 0;\n  selpoint2 = 0;\n  markedgedist = 1;\n\n  UpdateTables ();\n}\n\nVisualSceneMeshDoctor :: ~VisualSceneMeshDoctor ()\n{\n  ;\n}\n\nvoid VisualSceneMeshDoctor :: DrawScene ()\n{\n  if (!mesh) return;\n\n  int hchval = mesh->GetNP() + mesh->GetNE() + mesh->GetNSE();\n  if (changeval != hchval)\n    {\n      changeval = hchval;\n      BuildScene();\n    }\n\n\n  glClearColor(backcolor, backcolor, backcolor, 1.0);\n  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n  glEnable (GL_COLOR_MATERIAL);\n  glColor3f (1.0f, 1.0f, 1.0f);\n  glLineWidth (1.0f);\n\n  SetLight();\n\n  glPushMatrix();\n  glMultMatrixd (transformationmat);\n  \n  glInitNames ();\n  glPushName (0);\n  \n  glPolygonOffset (1, 1);\n  glEnable (GL_POLYGON_OFFSET_FILL);\n\n  SetClippingPlane ();\n\n  if (vispar.drawfilledtrigs)\n    glCallList (filledlist);\n\n  glDisable (GL_POLYGON_OFFSET_FILL);\n  \n  if (vispar.drawoutline)\n    glCallList (outlinelist);\n  \n  glPolygonOffset (-1, -1);\n  glEnable (GL_POLYGON_OFFSET_LINE);\n\n  if (vispar.drawedges)\n    glCallList (edgelist);\n  \n\n  glDisable (GL_POLYGON_OFFSET_LINE);\n\n  \n  \n  glPopName();\n\n  if (selpoint-IndexBASE<PointIndex>() >= 0 && selpoint-IndexBASE<PointIndex>() < mesh->GetNP())\n    {\n      GLfloat matcolblue[] = { 0, 0, 1, 1 };\n\n      glPointSize (10);\n      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolblue);\n      glBegin (GL_POINTS);\n      \n      const Point3d p = mesh->Point(selpoint);\n      glVertex3f (p.X(), p.Y(), p.Z());\n      glEnd();\n    }\n\n  glDisable(GL_CLIP_PLANE0);\n\n\n  glPopMatrix();\n  glFinish();  \n}\n\n\n\n\nvoid VisualSceneMeshDoctor :: BuildScene (int zoomall)\n{\n  if (zoomall)\n    {\n      Point3d pmin, pmax;\n      mesh->GetBox (pmin, pmax, -1);\n\n      if (vispar.centerpoint)\n\tcenter = mesh->Point (vispar.centerpoint);\n      else\n\tcenter = Center (pmin, pmax);\n  \n      rad = 0.5 * Dist (pmin, pmax);\n\n      glEnable (GL_NORMALIZE);\n  \n      CalcTransformationMatrices();\n    }\n\n\n\n\n  if (filledlist)\n    {\n      glDeleteLists (filledlist, 1);\n      glDeleteLists (outlinelist, 1);\n      glDeleteLists (edgelist, 1);\n    }\n\n  \n  filledlist = glGenLists (1);\n  glNewList (filledlist, GL_COMPILE);\n\n  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n  \n  glLineWidth (1.0f);\n  \n  glDisable (GL_COLOR_MATERIAL);\n    \n  for (int i = 1; i <= mesh->GetNSE(); i++)\n    {\n      glLoadName (i);\n\n      // copy to be thread-safe\n      // Element2d el = mesh->SurfaceElement (i);\n      Element2d el = (*mesh)[SurfaceElementIndex(i-1)];\n\n      int drawel = 1;\n      for (int j = 1; j <= el.GetNP(); j++)\n\t{\n\t  if (!el.PNum(j))\n\t    drawel = 0;\n\t}\n\n      if (!drawel)\n\tcontinue;\n\n      GLfloat matcol[] = { 0, 1, 0, 1 };\n      GLfloat matcolsel[] = { 1, 0, 0, 1 };\n\n      if (i == selelement)\n\tglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcolsel);\n      else\n\tglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcol);\n\n      if (el.GetNP() == 3)\n\t{\n\t  glBegin (GL_TRIANGLES);\n\t  \n\t  const Point3d & lp1 = mesh->Point (el.PNum(1));\n\t  const Point3d & lp2 = mesh->Point (el.PNum(2));\n\t  const Point3d & lp3 = mesh->Point (el.PNum(3));\n\t  Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t  n /= (n.Length()+1e-12);\n\t  glNormal3d (n.X(), n.Y(), n.Z());\n\n\t  if (!vispar.colormeshsize)\n\t    {\n\t      glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t      glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t      glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t    }\n\t  else\n\t    {\n\t      double h1 = mesh->GetH (lp1);\n\t      double h2 = mesh->GetH (lp2);\n\t      double h3 = mesh->GetH (lp3);\n\t      \n\t      SetOpenGlColor  (h1, 0.1, 10);\n\t      glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\n\t      SetOpenGlColor  (h2, 0.1, 10);\n\t      glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\n\t      SetOpenGlColor  (h3, 0.1, 10);\n\t      glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t    }\t    \n\t  glEnd();\n\t}\n      else if (el.GetNP() == 4)\n\t{\n\t  glBegin (GL_QUADS);\n\t  \n\t  const Point3d & lp1 = mesh->Point (el.PNum(1));\n\t  const Point3d & lp2 = mesh->Point (el.PNum(2));\n\t  const Point3d & lp3 = mesh->Point (el.PNum(4));\n\t  const Point3d & lp4 = mesh->Point (el.PNum(3));\n\t  Vec3d n = Cross (Vec3d (lp1, lp2), \n\t\t\t   Vec3d (lp1, Center (lp3, lp4)));\n\t  n /= (n.Length()+1e-12);\n\t  glNormal3d (n.X(), n.Y(), n.Z()); \n\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t  glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n\t  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t  glEnd();\n\t}\n      else if (el.GetNP() == 6)\n\t{\n\t  glBegin (GL_TRIANGLES);\n\t  static int trigs[4][3] = {\n\t    { 1, 6, 5 },\n\t    { 2, 4, 6 },\n\t    { 3, 5, 4 },\n\t    { 4, 5, 6 } };\n\n\t  for (int j = 0; j < 4; j++)\n\t    {\n\t      const Point3d & lp1 = mesh->Point (el.PNum(trigs[j][0]));\n\t      const Point3d & lp2 = mesh->Point (el.PNum(trigs[j][1]));\n\t      const Point3d & lp3 = mesh->Point (el.PNum(trigs[j][2]));\n\t      Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t      n /= (n.Length() + 1e-12);\n\t      glNormal3d (n.X(), n.Y(), n.Z());\n\t      glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t      glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t      glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t    }\n\t  glEnd();\n\t}\n    }\n  glLoadName (0);\n  \n  glEndList ();\n\n  \n  \n  outlinelist = glGenLists (1);\n  glNewList (outlinelist, GL_COMPILE);\n\n  glLineWidth (1.0f);\n  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n\n  glColor3f (0.0f, 0.0f, 0.0f);\n  glEnable (GL_COLOR_MATERIAL);\n  \n  for (int i = 1; i <= mesh->GetNSE(); i++)\n    {\n      Element2d el = (*mesh)[SurfaceElementIndex(i-1)];\n\n      int drawel = 1;\n      for (int j = 1; j <= el.GetNP(); j++)\n\t{\n\t  if (!el.PNum(j))\n\t    drawel = 0;\n\t}\n\n      if (!drawel)\n\tcontinue;\n\n\n      if (el.GetNP() == 3)\n\t{\n\t  glBegin (GL_TRIANGLES);\n\t  \n\t  const Point3d & lp1 = mesh->Point (el.PNum(1));\n\t  const Point3d & lp2 = mesh->Point (el.PNum(2));\n\t  const Point3d & lp3 = mesh->Point (el.PNum(3));\n\t  Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t  n /= (n.Length() + 1e-12);\n\t  glNormal3d (n.X(), n.Y(), n.Z());\n\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t  glEnd();\n\t}\n      else if (el.GetNP() == 4)\n\t{\n\t  glBegin (GL_QUADS);\n\t  \n\t  const Point3d & lp1 = mesh->Point (el.PNum(1));\n\t  const Point3d & lp2 = mesh->Point (el.PNum(2));\n\t  const Point3d & lp3 = mesh->Point (el.PNum(4));\n\t  const Point3d & lp4 = mesh->Point (el.PNum(3));\n\t  Vec3d n = Cross (Vec3d (lp1, lp2), \n\t\t\t   Vec3d (lp1, Center (lp3, lp4)));\n\t  n /= (n.Length() + 1e-12);\n\t  glNormal3d (n.X(), n.Y(), n.Z());\n\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t  glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n\t  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t  glEnd();\n\t}\n      else if (el.GetNP() == 6)\n\t{\n\t  glBegin (GL_LINES);\n\t  \n\t  const Point3d & lp1 = mesh->Point (el.PNum(1));\n\t  const Point3d & lp2 = mesh->Point (el.PNum(2));\n\t  const Point3d & lp3 = mesh->Point (el.PNum(3));\n\t  const Point3d & lp4 = mesh->Point (el.PNum(4));\n\t  const Point3d & lp5 = mesh->Point (el.PNum(5));\n\t  const Point3d & lp6 = mesh->Point (el.PNum(6));\n\n\t  Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t  n /= (n.Length()+1e-12);\n\t  glNormal3d (n.X(), n.Y(), n.Z());\n\n\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t  glVertex3d (lp6.X(), lp6.Y(), lp6.Z());\n\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t  glVertex3d (lp6.X(), lp6.Y(), lp6.Z());\n\n\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t  glVertex3d (lp5.X(), lp5.Y(), lp5.Z());\n\t  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t  glVertex3d (lp5.X(), lp5.Y(), lp5.Z());\n\n\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t  glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n\t  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t  glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n\t  glEnd();\n\t}\n    }\n  glLoadName (0);  \n  glEndList ();\n\n\n\n\n\n  edgelist = glGenLists (1);\n  glNewList (edgelist, GL_COMPILE);\n\n  glDisable (GL_COLOR_MATERIAL);\n\n  GLfloat matcoledge[] = { 0, 0, 1, 1 };\n  GLfloat matcolseledge[] = { 1, 0, 1, 1 };\n\n  glLineWidth (2.0f);\n\n  for (int i = 1; i <= mesh->GetNSeg(); i++)\n    {\n      const Segment & seg = mesh->LineSegment(i);\n      const Point3d & p1 = mesh->Point(seg[0]);\n      const Point3d & p2 = mesh->Point(seg[1]);\n\n      if (edgedist[seg[0]] <= markedgedist &&\n\t  edgedist[seg[1]] <= markedgedist)\n\t{\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, \n\t\t\tmatcolseledge);\n\t  glLineWidth (4.0f);\n\t}\n      else\n\t{\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, \n\t\t\tmatcoledge);\n\t  glLineWidth (2.0f);\n\t}\n      glBegin (GL_LINES);\n      glVertex3f (p1.X(), p1.Y(), p1.Z());\n      glVertex3f (p2.X(), p2.Y(), p2.Z());\n      glEnd(); \n    }\n\n  glLineWidth (1.0f);\n  glEndList ();\n}\n\n\n\n\nvoid VisualSceneMeshDoctor :: MouseDblClick (int px, int py)\n{\n  cout << \"dblclick: \" << px << \" - \" << py << endl;\n  \n  int i, hits;\n\n  // select surface triangle by mouse click\n  GLuint selbuf[10000];\n  glSelectBuffer (10000, selbuf);\n\n\n  glRenderMode (GL_SELECT);\n\n  GLint viewport[4];\n  glGetIntegerv (GL_VIEWPORT, viewport);\n\n  glMatrixMode (GL_PROJECTION); \n  glPushMatrix();\n\n  GLdouble projmat[16];\n  glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n\n  glLoadIdentity(); \n  gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); \n  glMultMatrixd (projmat);\n  \n\n  glClearColor(backcolor, backcolor, backcolor, 1.0);\n  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n  glMatrixMode (GL_MODELVIEW); \n\n  glPushMatrix();\n  glMultMatrixd (transformationmat);\n\n  glInitNames();\n  glPushName (1);\n\n  glPolygonOffset (1, 1);\n  glEnable (GL_POLYGON_OFFSET_FILL);\n\n  glCallList (filledlist);\n\n  glDisable (GL_POLYGON_OFFSET_FILL);\n  \n  glPopName();\n\n  glMatrixMode (GL_PROJECTION); \n  glPopMatrix();\n\n  glMatrixMode (GL_MODELVIEW); \n  glPopMatrix();\n\n  glFlush();  \n\n\t\n  hits = glRenderMode (GL_RENDER);\n\n  cout << \"hits = \" << hits << endl;\n\n  int minname = 0;\n  GLuint mindepth = 0;\n  for (i = 0; i < hits; i++)\n    {\n      int curname = selbuf[4*i+3];\n      GLuint curdepth = selbuf[4*i+1];\n\n      if (curname &&\n\t  (curdepth < mindepth || !minname))\n\t{\n\t  mindepth = curdepth;\n\t  minname = curname;\n\t}\n    }\n\n  cout << \"clicked element: \" << minname << endl;\n\n  ClickElement (minname);\n\n  BuildScene ();\n}\n\n\n\n\nvoid VisualSceneMeshDoctor :: SetMarkEdgeDist (int dist)\n{\n  markedgedist = dist;\n  BuildScene();\n}\n\nvoid VisualSceneMeshDoctor :: ClickElement (int elnr)\n{\n  selelement = elnr;\n  int oldlocpi = locpi;\n  locpi = locpi % 3 + 1;\n  \n  if (selelement > 0 && selelement <= mesh->GetNSE())\n    {\n      SurfaceElementIndex sei(elnr-1);\n      selpoint = (*mesh)[sei].PNum(locpi);\n      selpoint2 = (*mesh)[sei].PNum(oldlocpi);\n      cout << \"selpts = \" << selpoint << \", \" << selpoint2 << endl;\n    }\n\n  UpdateTables();\n}\n\n\nvoid VisualSceneMeshDoctor :: UpdateTables ()\n{\n  if (!mesh) return;\n\n  edgedist.SetSize(mesh->GetNP());\n  int i, changed;\n\n  edgedist = 10000;\n\n  for (i = 1; i <= mesh->GetNSeg(); i++)\n    {\n      const Segment & seg = mesh->LineSegment(i);\n      if ( (seg[0] == selpoint && seg[1] == selpoint2) ||\n           (seg[1] == selpoint && seg[0] == selpoint2) )\n\t{\n\t  edgedist[selpoint] = 1;\n\t  edgedist[selpoint2] = 1;\n\t}\n    }\n\n  do\n    {\n      changed = 0;\n\n      for (i = 1; i <= mesh->GetNSeg(); i++)\n\t{\n\t  const Segment & seg = mesh->LineSegment(i);\n\t  \n\t  int edist = min2 (edgedist[seg[0]], edgedist[seg[1]]);\n\t  edist++;\n\n\t  if (edgedist[seg[0]] > edist)\n\t    {\n\t      edgedist[seg[0]] = edist;\n\t      changed = 1;\n\t    }\n\t  if (edgedist[seg[1]] > edist)\n\t    {\n\t      edgedist[seg[1]] = edist;\n\t      changed = 1;\n\t    }\n\t}\t    \n    }\n  while (changed);\n}\n\nint VisualSceneMeshDoctor :: IsSegmentMarked (int segnr) const\n{\n  const Segment & seg = mesh->LineSegment(segnr);\n  return (edgedist[seg[0]] <= markedgedist &&\n\t  edgedist[seg[1]] <= markedgedist);\n}\n}\n\n\n#endif // NOTCL\n"
  },
  {
    "path": "libsrc/visualization/meshdoc.hpp",
    "content": "namespace netgen\n\n{\n\nclass VisualSceneMeshDoctor : public VisualScene\n{\n  int filledlist;\n  int outlinelist;\n  int edgelist;\n\n  int selelement, locpi;\n  PointIndex selpoint, selpoint2;\n\n  // for edgemarking:\n  Array<int,PointIndex> edgedist;\n  int markedgedist;\n  \n\npublic:\n  NGGUI_API VisualSceneMeshDoctor ();\n  NGGUI_API virtual ~VisualSceneMeshDoctor ();\n\n  NGGUI_API virtual void BuildScene (int zoomall = 0);\n  NGGUI_API virtual void DrawScene ();\n  NGGUI_API virtual void MouseDblClick (int px, int py);\n\n  NGGUI_API void SetMarkEdgeDist (int dist);\n  NGGUI_API void ClickElement (int elnr);\n  NGGUI_API void UpdateTables ();\n  NGGUI_API int IsSegmentMarked (int segnr) const;\n};\n\nclass MeshDoctorParameters \n{\npublic:\n  int active;\n};\n\n\nNGGUI_API extern MeshDoctorParameters meshdoctor;\n\n}\n"
  },
  {
    "path": "libsrc/visualization/mvdraw.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n#include <meshing.hpp>\n\n#include <visual.hpp>\n// #include <parallel.hpp>\n\n\n\n#ifndef WIN32\n#define GLX_GLXEXT_LEGACY\n\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xatom.h>  /* for XA_RGB_DEFAULT_MAP atom */\n// #include <GL/glx.h>    // for parallel GL ???\n#endif\n\n\n\n\n\nnamespace netgen\n{\n  NGGUI_API Point3d VisualScene :: center;\n  NGGUI_API double VisualScene :: rad;\n  NGGUI_API GLdouble VisualScene :: backcolor;\n  NGGUI_API VisualScene visual_scene_cross;\n  NGGUI_API VisualScene *visual_scene = &visual_scene_cross;\n\n  /*\n#if TOGL_MAJOR_VERSION!=2\n  GLuint VisualScene :: fontbase = 0;\n#else\n  Tcl_Obj * VisualScene :: fontbase = NULL;\n  Togl * VisualScene :: globtogl;\n#endif\n  */\n\n  void (*opengl_text_function)(const char * text) = NULL;\n  int opengl_text_width = 0;\n  void Set_OpenGLText_Callback ( void (*fun) (const char * text), int width )\n  {\n    opengl_text_function = fun;\n    opengl_text_width = width;\n  }\n\n  void MyOpenGLText (const char * text)\n  {\n    if (opengl_text_function)\n      (*opengl_text_function) (text);\n    // cout << \"MyOpenGLText: \" << text << endl;\n  }\n\n  int MyOpenGLTextWidth ()\n  {\n      return opengl_text_width;\n  }\n\n  void MyOpenGLLines(FlatArray<Point<3>> points)\n  {\n    glBegin(GL_LINES);\n    for (auto p : points)\n      glVertex3dv(&p[0]);\n    glEnd();\n  }\n\n  // texture for color decoding\n  // GLubyte * VisualScene :: colortexture = NULL;\n  GLuint VisualScene :: coltexname = 1;\n  int VisualScene :: ntexcols = -1;\n\n\n  double VisualScene :: lookatmat[16];\n  double VisualScene :: transmat[16];\n  double VisualScene :: rotmat[16];\n  double VisualScene :: centermat[16];\n  double VisualScene :: transformationmat[16];\n\n  int VisualScene :: selface;\n  int VisualScene :: selelement;\n  PointIndex VisualScene :: selpoint;\n  PointIndex VisualScene :: selpoint2;\n  int VisualScene :: locpi;\n  int VisualScene :: seledge;\n\n  optional<Point<3>> VisualScene :: marker = nullopt;\n\n  int VisualScene :: subdivision_timestamp = -1;\n  int VisualScene :: subdivisions = 2;\n\n  int VisualScene :: viewport[4];\n\n  VisualizationParameters :: VisualizationParameters()\n  {\n    lightamb = 0.3;\n    lightdiff = 0.7;\n    lightspec = 1;\n    shininess = 50;\n    transp = 0.3;\n    locviewer = 0;\n    showstltrias = 0;\n    centerpoint = PointIndex::INVALID;\n    usedispllists = 1;\n    strcpy (selectvisual, \"cross\");\n\n    use_center_coords = false;\n  };\n  VisualizationParameters vispar;\n\n\n\n  double dist = 0;\n  // double dist = 6;\n  // vorher: pnear = 2;\n  // double pnear = 0.1;\n  // double pfar = 10;\n\n\n\n  VisualScene :: VisualScene ()\n  {\n    changeval = -1;\n    backcolor = 0;\n  }\n\n\n  VisualScene :: ~VisualScene()\n  {\n    ;\n  }\n\n\n\n  void VisualScene :: BuildScene (int zoomall)\n  {\n    center = Point3d (0,0,0);\n    rad = 1;\n\n    if(zoomall)\n        CalcTransformationMatrices();\n\n    glEnable(GL_DEPTH_TEST);\n    glDisable (GL_DITHER);\n  \n    GLfloat ambvals[] = { 0.4f, 0.4f, 0.4f, 1.0f };\n    GLfloat diffvals[] = { 0.5f, 0.5f, 0.5f, 1.0f };\n    GLfloat specvals[] =  { 0.7f, 0.7f, 0.7f, 1.0f };\n    glLightfv(GL_LIGHT0, GL_AMBIENT, ambvals);\n    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffvals);\n    glLightfv(GL_LIGHT0, GL_SPECULAR, specvals);\n  \n    GLfloat light_position[] = { 1, 3, 3, 0 };\n    glLightfv(GL_LIGHT0, GL_POSITION, light_position);\n  \n    glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, 0);\n    glEnable(GL_LIGHTING);\n    glEnable(GL_LIGHT0);\n  }\n\n\n  void VisualScene :: DrawScene ()\n  {\n    if (changeval == -1)\n      BuildScene();\n    changeval = 0;\n\n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glColor3f (1.0f, 1.0f, 1.0f);\n    glLineWidth (1.0f);\n\n    DrawCoordinateCross ();\n    DrawNetgenLogo ();\n    glFinish();  \n  }\n\n\n  void VisualScene :: CalcTransformationMatrices()\n  {\n    // prepare model view matrix\n  \n    glPushMatrix();\n\n    glLoadIdentity();\n    gluLookAt (0, 0, 6, 0, 0, 0, 0, 1, 0);\n    glGetDoublev (GL_MODELVIEW_MATRIX, lookatmat);\n\n    glLoadIdentity();\n    glTranslatef(0.0f, 0.0f, -dist);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transmat);\n  \n    glLoadIdentity();\n    glGetDoublev (GL_MODELVIEW_MATRIX, rotmat);\n\n    glScaled (1/rad, 1/rad, 1/rad);\n    glTranslated (-center.X(), -center.Y(), -center.Z());\n    glGetDoublev (GL_MODELVIEW_MATRIX, centermat);\n\n    glLoadIdentity();\n    glMultMatrixd (lookatmat);\n    glMultMatrixd (transmat);\n    glMultMatrixd (rotmat);\n    glMultMatrixd (centermat);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat);\n\n    glPopMatrix();\n  }\n\n\n  void VisualScene :: ArbitraryRotation (const NgArray<double> & alpha, const NgArray<Vec3d> & vec)\n  {\n    glPushMatrix();\n\n    glLoadIdentity();\n\n    for(int i=0; i<alpha.Size() && i<vec.Size(); i++)\n      {\n\tglRotatef(alpha[i], vec[i].X(), vec[i].Y(), vec[i].Z());\n      }\n\n    glGetDoublev (GL_MODELVIEW_MATRIX, rotmat);\n\n    glLoadIdentity();\n    glMultMatrixd (lookatmat);\n    glMultMatrixd (transmat);\n    glMultMatrixd (rotmat);\n    glMultMatrixd (centermat);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat);\n  \n    glPopMatrix();\n  } \n\n\n\n  void VisualScene :: ArbitraryRotation (const double alpha, const Vec3d & vec)\n  {\n    NgArray<double> a(1); a[0] = alpha;\n    NgArray<Vec3d> v(1); v[0] = vec;\n\n    ArbitraryRotation(a,v);\n  } \n\n  void VisualScene :: StandardRotation (const char * dir)\n  {\n    glPushMatrix();\n\n    glLoadIdentity();\n  \n    if (strcmp (dir, \"xy\") == 0)\n      ;\n    else if (strcmp (dir, \"yx\") == 0)\n      glRotatef(180.0, 1.0f, 1.0f, 0.0f);    \n    else if (strcmp (dir, \"xz\") == 0)\n      glRotatef(-90.0, 1.0f, 0.0f, 0.0f);    \n    else if (strcmp (dir, \"zx\") == 0)\n      {\n\tglRotatef(180.0, 1.0f, 1.0f, 0.0f);    \n\tglRotatef(-90.0, 1.0f, 0.0f, 0.0f);    \n      }\n    else if (strcmp (dir, \"yz\") == 0)\n      {\n\tglRotatef(-90.0, 0.0f, 0.0f, 1.0f);    \n\tglRotatef(-90.0, 0.0f, 1.0f, 0.0f);    \n      }\n    else if (strcmp (dir, \"zy\") == 0)\n      glRotatef(90.0, 0.0f, 1.0f, 0.0f);    \n\n\n    glGetDoublev (GL_MODELVIEW_MATRIX, rotmat);\n\n    glLoadIdentity();\n    glMultMatrixd (lookatmat);\n    glMultMatrixd (transmat);\n    glMultMatrixd (rotmat);\n    glMultMatrixd (centermat);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat);\n  \n    glPopMatrix();\n  }\n\n  void VisualScene :: MouseMove(int oldx, int oldy,\n\t\t\t\tint newx, int newy,\n\t\t\t\tchar mode)\n  {\n    int deltax = newx - oldx;\n    int deltay = newy - oldy;\n  \n    glPushMatrix();\n    glLoadIdentity ();\n  \n    switch (mode)\n      {\n      case 'r':\n\t{\t\n\t  glRotatef(float(deltax)/2, 0.0f, 1.0f, 0.0f);\n\t  glRotatef(float(deltay)/2, 1.0f, 0.0f, 0.0f);\n\t  glMultMatrixd (rotmat);\n\t  glGetDoublev (GL_MODELVIEW_MATRIX, rotmat);\n\t  break;\n\t}\n      case 'm':\n\t{\n\t  GLdouble projmat[16], modelviewmat[16];\n\t  GLint viewport[4];\n\t  glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n\t  glGetDoublev (GL_MODELVIEW_MATRIX, modelviewmat);\n\t  glGetIntegerv (GL_VIEWPORT, viewport);\n\t\n\t  // vorher pvz1/2 = 0\n\t  GLdouble pvx1 = 0, pvy1 = 0, pvz1 = 0.99; //  0.95;\n\t  GLdouble pvx2 = deltax, pvy2 = -deltay, pvz2 = 0.99; // 0.95;\n\n\t  GLdouble px1, py1, pz1;\n\t  GLdouble px2, py2, pz2;\n\t\n\t  gluUnProject (pvx1, pvy1, pvz1, \n\t\t\tmodelviewmat, projmat, viewport,\n\t\t\t&px1, &py1, &pz1);\n\t  gluUnProject (pvx2, pvy2, pvz2, \n\t\t\tmodelviewmat, projmat, viewport,\n\t\t\t&px2, &py2, &pz2);\n\t  /*\n\t    gluUnProject (oldx, oldy, 1, \n\t    modelviewmat, projmat, viewport,\n\t    &px1, &py1, &pz1);\n\t    gluUnProject (newx, newy, 1, \n\t    modelviewmat, projmat, viewport,\n\t    &px2, &py2, &pz2);\n\t  */\n\n\t  /*\t\n\t    cout << \"pv1 = \" << pvx1 << \", \" << pvy1 << \", \" << pvz1 << endl;\n\t    cout << \"p1 = \" << px1 << \", \" << py1 << \", \" << pz1 << endl;\n\t  */\n\n\t  glTranslated (px2-px1, py2-py1, pz2-pz1);\n\t\n\t  glMultMatrixd (transmat);\n\t  glGetDoublev (GL_MODELVIEW_MATRIX, transmat);\n\t  break;\n\t}\n      case 'z':\n\t{\n\t  // glTranslatef(0.0f, 0.0f, -dist);\n\n\t  // cout << \"deltay = \" << deltay << endl;\n\t  // cout << \"float_bug = \" << (float(deltay)/100) << endl;   gives wrong result with icc 9.0.021\n\t  glScaled (exp (double (-deltay)/100), \n\t\t    exp (double (-deltay)/100), \n\t\t    exp (double (-deltay)/100));\n\t  // glTranslatef(0.0f, 0.0f, dist);\n\t  glMultMatrixd (transmat);\n\t  glGetDoublev (GL_MODELVIEW_MATRIX, transmat);\n\t  break;\n\t}\n      }\n\n    glLoadIdentity();\n    glMultMatrixd (lookatmat);\n    glMultMatrixd (transmat);\n    glMultMatrixd (rotmat);\n    glMultMatrixd (centermat);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat);\n  \n    glPopMatrix();\n  }\n\n\n  void VisualScene :: LookAt (const Point<3> & cam, const Point<3> & obj,\n\t\t\t      const Point<3> & camup)\n  {\n    glPushMatrix();\n    glLoadIdentity ();\n    gluLookAt (cam(0), cam(1), cam(2), \n\t       obj(0), obj(1), obj(2),\n\t       camup(0), camup(1), camup(2));\n    glMultMatrixd (centermat);\n    glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat);\n    glPopMatrix();\n  }\n\n  \n  void VisualScene :: SetClippingPlane ()\n  {\n    if (vispar.clipping.enable)\n      {\n\tVec3d n = vispar.clipping.normal;\n\tn /= (n.Length()+1e-10);\n\tclipplane[0] = n.X();\n\tclipplane[1] = n.Y();\n\tclipplane[2] = n.Z();\n\tclipplane[3] = -(Vec3d(center) * n) + rad * vispar.clipping.dist;\n\n\tdouble clipplane2[4];\n\tclipplane2[0] = n.X();\n\tclipplane2[1] = n.Y();\n\tclipplane2[2] = n.Z();\n\tclipplane2[3] = -(Vec3d(center) * n) + \n\t  rad * (vispar.clipping.dist + vispar.clipping.dist2);\n\n\tglClipPlane(GL_CLIP_PLANE0, clipplane2);\n\tglEnable(GL_CLIP_PLANE0);\n      }\n    else\n      glDisable (GL_CLIP_PLANE0);\n  }\n\n\n\n\n  void VisualScene :: MouseDblClick (int /* px */, int /* py */)\n  {\n    ;\n  }\n\n\n\n  void VisualScene :: SetLight()\n  {\n    GLfloat vals[3];\n    double lightamb = vispar.lightamb;\n    vals[0] = vals[1] = vals[2] = lightamb;\n    glLightfv(GL_LIGHT0, GL_AMBIENT, vals);\n\n    double lightdiff = vispar.lightdiff;\n    vals[0] = vals[1] = vals[2] = lightdiff;\n    glLightfv(GL_LIGHT0, GL_DIFFUSE, vals);\n\n    double lightspec = vispar.lightspec;\n    vals[0] = vals[1] = vals[2] = lightspec;\n    glLightfv(GL_LIGHT0, GL_SPECULAR, vals);\n\n    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, vispar.shininess);\n    glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, vispar.locviewer);\n\n    float mat_spec_col[] = { 1, 1, 1, 1 };\n    glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col);\n\n    glEnable (GL_LIGHTING);\n    glEnable (GL_LIGHT0);\n  }\n\n\n\n\n  void VisualScene :: SetOpenGlColor(double val, double valmin, double valmax,\n\t\t\t\t     int logscale)\n  {\n    double value;\n\n    if (!logscale)\n      value = (val - valmin) / (valmax - valmin);\n    else\n      {\n\tif (valmax <= 0) valmax = 1;\n\tif (valmin <= 0) valmin = 1e-4 * valmax;\n\tvalue = (log(fabs(val)) - log(valmin)) / (log(valmax) - log(valmin));\n      }\n\n    if (!invcolor)\n      value = 1 - value;\n\n    glTexCoord1f ( 0.998 * value + 0.001);\n    // glTexCoord1f ( val ); \n\n    glTexCoord2f ( 0.998 * value + 0.001, 1.5);\n    // glTexCoord1f ( value ); \n\n    if (value > 1) value = 1;\n    if (value < 0) value = 0;\n\n    value *= 4;\n\n    static const double colp[][3] =\n      {\n\t{ 1, 0, 0 },\n\t{ 1, 1, 0 },\n\t{ 0, 1, 0 },\n\t{ 0, 1, 1 },\n\t{ 0, 0, 1 },\n\t//\t{ 1, 0, 1 },\n\t//\t{ 1, 0, 0 },\n      };\n  \n    int i = int(value);\n    double r = value - i;\n\n    GLdouble col[3];\n    for (int j = 0; j < 3; j++)\n      col[j] = (1-r) * colp[i][j] + r * colp[i+1][j];\n  \n    glColor3d (col[0], col[1], col[2]);\n  }\n\n\n\n  void VisualScene :: CreateTexture (int ncols, int linear, double alpha, int typ)\n  {\n    if (linear) ncols = 32;\n\n    if (ntexcols != ncols) \n      {\n\tntexcols = ncols;\n      \n\tArrayMem<GLubyte, 4*32> colortexture;\n\tcolortexture.SetSize(4*ncols);\n\n\tconst double colp[][3] =\n\t  {\n\t    { 1, 0, 0 },\n\t    { 1, 1, 0 },\n\t    { 0, 1, 0 },\n\t    { 0, 1, 1 },\n\t    { 0, 0, 1 },\n\t  };\n  \n\tfor (int i = 0; i < ncols; i++)\n\t  {\n\t    double value = 4.0 * i / (ncols-1);\n\n\t    int iv = int(value);\n\t    double r = value - iv;\n\n\t    GLdouble col[3];\n\n\t    if(r > 1e-3)\n\t      for (int j = 0; j < 3; j++)\n\t\tcol[j] = (1.-r) * colp[iv][j] + r * colp[iv+1][j];\n\t    else\n\t      for (int j = 0; j < 3; j++)\n\t\tcol[j] = colp[iv][j];\n\n\t    colortexture[4*i] = GLubyte (255 * col[0]);\n\t    colortexture[4*i+1] = GLubyte (255 * col[1]);\n\t    colortexture[4*i+2] = GLubyte (255 * col[2]);\n\t    colortexture[4*i+3] = GLubyte(255*alpha);\n\t  }\n\n\t// glPixelStorei (GL_UNPACK_ALIGNMENT, 1);\n\n\tglTexImage1D (GL_TEXTURE_1D, 0, 4, ncols, 0, GL_RGBA, GL_UNSIGNED_BYTE, colortexture.Data());\n\tglTexImage2D (GL_TEXTURE_2D, 0, 4, ncols, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colortexture.Data());\n\n\tglTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, typ);  // DECAL or MODULATE\n\t\n\tGLfloat bcol[] = { 1, 1, 1, 1.0 };\n\tglTexParameterfv (GL_TEXTURE_1D, GL_TEXTURE_BORDER_COLOR, bcol);\n\tglTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\n\tglTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bcol);\n\tglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\tglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n\n\t\n\tif (linear)\n\t  {\n\t    glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\t    glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n\n\t    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\t    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n\t  }\n\telse\n\t  {\n\t    glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\t    glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);\n\n\t    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\t    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);\n\t  }\n      }\n  }\n  \n\n\n\n  void VisualScene :: DrawColorBar (double minval, double maxval, int logscale, bool linear, string format, string unit)\n  {\n    if (!vispar.drawcolorbar) return;\n\n    CreateTexture (GetVSSolution().numtexturecols, linear, 1, GL_DECAL);\n\n    if (logscale && maxval <= 0) maxval = 1;\n    if (logscale && minval <= 0) minval = 1e-4 * maxval;\n\n    double minx = -1;\n    double maxx = 1;\n    double miny = 0.75;\n    double maxy = 0.8;\n\n    glDisable (GL_LIGHTING);\n    glEnable (GL_COLOR_MATERIAL);\n    glEnable (GL_TEXTURE_1D);\n    glNormal3d (0, 0, 1);\n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n    \n    glDisable (GL_DEPTH_TEST);\n    glBegin (GL_QUAD_STRIP);\n\n    for (auto i : Range(50))\n      {\n        double x = minx + i*1.0/49*(maxx-minx);\n\tSetOpenGlColor (x, minx, maxx);\n\tglVertex3d (x, miny, -5);\n\tglVertex3d (x, maxy, -5);\n      }\n    glEnd();\n\n    glDisable (GL_TEXTURE_1D);\n    \n    glEnable (GL_COLOR_MATERIAL);\n    GLfloat textcol[3] = { GLfloat(1 - backcolor), \n                           GLfloat(1 - backcolor), \n                           GLfloat(1 - backcolor) };\n    glColor3fv (textcol);\n    \n    glPushAttrib (GL_LIST_BIT);\n    // glListBase (fontbase);\n\n    constexpr size_t buf_size = 20;\n    char buf[buf_size];\n    GLint viewport[4];\n    glGetIntegerv (GL_VIEWPORT, viewport);\n    double char_width = 2.0*MyOpenGLTextWidth()/(viewport[3]);\n    for (int i = 0; i <= 4; i++)\n      {\n\tdouble val;\n\tif (logscale)\n\t  val = minval * pow (maxval / minval, i / 4.0);\n\telse\n\t  val = minval + i * (maxval-minval) / 4;\n\n\tsnprintf (buf, buf_size, format.c_str(), val);\n        auto n = strlen(buf);\n\tdouble x = minx + i * (maxx-minx) / 4;\n        x -= 0.5*char_width * n; // center text\n\tglRasterPos3d (x, 0.7,-5);\n\n\tMyOpenGLText (buf);\n      }\n\n    if(unit != \"\")\n        MyOpenGLText (unit.c_str());\n\n    glPopAttrib ();\n    glEnable (GL_DEPTH_TEST);\n  }\n\n  void VisualScene :: DrawTitle (string title)\n  {\n    if(title==\"\")\n      return;\n    glDisable (GL_LIGHTING);\n    glDisable (GL_DEPTH_TEST);\n\n    glEnable (GL_COLOR_MATERIAL);\n    GLfloat textcol[3] = { GLfloat(1 - backcolor),\n                           GLfloat(1 - backcolor),\n                           GLfloat(1 - backcolor) };\n    glColor3fv (textcol);\n\n    glPushAttrib (GL_LIST_BIT);\n\n    GLint viewport[4];\n    glGetIntegerv (GL_VIEWPORT, viewport);\n    double char_width = 2.0*MyOpenGLTextWidth()/(viewport[3]);\n    double x = -0.5*char_width * title.size(); // center text\n    glRasterPos3d (x, 0.82,-5);\n    MyOpenGLText (title.c_str());\n    glPopAttrib ();\n    glEnable (GL_DEPTH_TEST);\n  }\n\n\n  void VisualScene :: DrawCoordinateCross ()\n  {\n    if (!vispar.drawcoordinatecross) return;\n\n    glDisable (GL_DEPTH_TEST);\n    glMatrixMode (GL_PROJECTION); \n    glPushMatrix();\n    glLoadIdentity();\n\n    glMatrixMode (GL_MODELVIEW); \n    glPushMatrix();\n    glLoadIdentity();\n\n    GLint viewport[4];\n    glGetIntegerv (GL_VIEWPORT, viewport);\n\n    glTranslatef (-1, -1, 0.0);\n    glScalef (40.0 / viewport[2], 40.0 / viewport[3], 1);\n    glTranslatef (2.0, 2.0, 0.0);\n    glMultMatrixd (rotmat);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glDisable (GL_LIGHTING);\n\n    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n\n    GLfloat textcol[3] = { GLfloat(1 - backcolor),\n\t\t\t   GLfloat(1 - backcolor),\n\t\t\t   GLfloat(1 - backcolor) };\n    glColor3fv (textcol);\n\n    glLineWidth (1.0f);\n\n    double len = 1;\n\n    glBegin(GL_LINES);\n    glVertex3d (0, 0, 0);\n    glVertex3d (len, 0, 0);\n    glVertex3d (0.0f, 0.0f, 0.0f);\n    glVertex3d (0.0f, len, 0.0f);\n    glVertex3d (0.0f, 0.0f, 0.0f);\n    glVertex3d (0.0f, 0.0f, len);\n    glEnd ();\n\n    glPushAttrib (GL_LIST_BIT);\n    // glListBase (fontbase);\n\n    char buf[20];\n\n    glRasterPos3d (len, 0.0f, 0.0f);\n    snprintf (buf, size(buf), \"x\");\n    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n    MyOpenGLText (buf);\n    glRasterPos3d (0.0f, len, 0.0f);\n    snprintf (buf, size(buf), \"y\");\n    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n    MyOpenGLText (buf);\n    glRasterPos3d (0.0f, 0.0f, len);\n    snprintf (buf, size(buf), \"z\");\n    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n    MyOpenGLText (buf);\n\n    glPopAttrib ();\n\n    glEnable (GL_LIGHTING);\n\n    glMatrixMode (GL_PROJECTION); \n    glPopMatrix();\n    glMatrixMode (GL_MODELVIEW); \n    glPopMatrix();\n    glEnable (GL_DEPTH_TEST);\n  }\n\n\n  void VisualScene :: DrawMarker()\n  {\n    static constexpr GLubyte cross[] = { 0xc6, 0xee, 0x7c, 0x38, 0x7c, 0xee, 0xc6 };\n\n    if(!marker)\n        return;\n\n    glColor3d (0, 0, 1);\n\n    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n\n    glDisable (GL_COLOR_MATERIAL);\n    glDisable (GL_LIGHTING);\n    glDisable (GL_CLIP_PLANE0);\n\n    auto & p = *marker;\n    glRasterPos3d (p[0], p[1], p[2]);\n    glBitmap (7, 7, 3, 3, 0, 0, &cross[0]);\n  }\n\n\n  void VisualScene :: DrawNetgenLogo ()\n  {\n    if (!vispar.drawnetgenlogo) return;\n\n    glDisable (GL_DEPTH_TEST);\n    glMatrixMode (GL_PROJECTION); \n    glPushMatrix();\n    glLoadIdentity();\n\n    glMatrixMode (GL_MODELVIEW); \n    glPushMatrix();\n    glLoadIdentity();\n\n    GLint viewport[4];\n    glGetIntegerv (GL_VIEWPORT, viewport);\n\n    glTranslatef (1, -1, 0.0);\n    glScalef (40.0 / viewport[2], 40.0 / viewport[3], 1);\n    glTranslatef (-7.0, 2.0, 0.0);\n\n    glDisable (GL_CLIP_PLANE0);\n    glDisable (GL_LIGHTING);\n\n    glEnable (GL_COLOR_MATERIAL);\n    GLfloat textcol[3] = { GLfloat(1 - backcolor),\n\t\t\t   GLfloat(1 - backcolor),\n\t\t\t   GLfloat(1 - backcolor) };\n    glColor3fv (textcol);\n    glLineWidth (1.0f);\n\n    glPushAttrib (GL_LIST_BIT);\n    // glListBase (fontbase);\n\n    char buf[] = \"Netgen \" PACKAGE_VERSION;\n\n    glRasterPos3d (0.0f, 0.0f, 0.0f);\n    // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);\n    MyOpenGLText (buf);\n\n    glPopAttrib ();\n\n    glEnable (GL_LIGHTING);\n    glMatrixMode (GL_PROJECTION); \n    glPopMatrix();\n    glMatrixMode (GL_MODELVIEW); \n    glPopMatrix();\n    glEnable (GL_DEPTH_TEST);\n  }\n\n\n  void VisualSceneSurfaceMeshing::MouseMove(int oldx, int oldy,\n                                            int newx, int newy,\n                                            char mode)\n  {\n    double fac = 0.001;\n    if(mode == 'M')\n      {\n        shiftx += fac * (newx - oldx);\n        shifty += fac * (oldy - newy);\n        return;\n      }\n    else if(mode == 'Z')\n      {\n        scalex *= (1 - fac * (newy - oldy));\n        scaley *= (1 - fac * (newy - oldy));\n        return;\n      }\n    \n    VisualScene::MouseMove(oldx, oldy, newx, newy, mode);\n  }\n\n  std::vector<unsigned char> Snapshot( int w, int h )\n  {\n    // save current settings\n    GLint viewport[4];\n    glGetIntegerv (GL_VIEWPORT, viewport);\n\n    glMatrixMode (GL_PROJECTION);\n    glPushMatrix();\n    glLoadIdentity();\n\n    double pnear = 0.1;\n    double pfar = 10;\n\n    gluPerspective(20.0f, double(w) / h, pnear, pfar);\n\n    glMatrixMode (GL_MODELVIEW);\n    glPushMatrix();\n    glLoadIdentity();\n    glViewport(0,0,w,h);\n\n    GLuint fb = 0;\n    glGenFramebuffers(1, &fb);\n    glBindFramebuffer(GL_FRAMEBUFFER, fb);\n\n    // create, reserve and attach color and depth renderbuffer\n    GLuint rbs[2];\n    glGenRenderbuffers(2, rbs);\n    glBindRenderbuffer(GL_RENDERBUFFER, rbs[0]);\n    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);\n    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbs[0]);\n\n    glBindRenderbuffer(GL_RENDERBUFFER, rbs[1]);\n    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);\n    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbs[1]);\n\n    // check if framebuffer status is complete\n    if(int fbstatus; (fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)\n        cerr << \"no frame buffer \" << fbstatus << endl;\n\n    visual_scene->DrawScene();\n    glFinish();\n\n    std::vector<unsigned char> buffer(w*h*3);\n    glPixelStorei(GL_UNPACK_ALIGNMENT,1);\n    glPixelStorei(GL_PACK_ALIGNMENT,1);\n    glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &buffer[0]);\n\n    glDeleteRenderbuffers(2, rbs);\n    glDeleteFramebuffers(1, &fb);\n    glBindFramebuffer(GL_FRAMEBUFFER, 0);\n\n    // restore previous settings\n    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);\n    glMatrixMode (GL_PROJECTION);\n    glPopMatrix();\n    glMatrixMode (GL_MODELVIEW);\n    glPopMatrix();\n    return buffer;\n  }\n\n  VisualSceneSurfaceMeshing :: VisualSceneSurfaceMeshing ()\n    : VisualScene()\n  {\n    ;\n  }\n\n  VisualSceneSurfaceMeshing :: ~VisualSceneSurfaceMeshing ()\n  {\n    ;\n  }\n\n  void VisualSceneSurfaceMeshing :: DrawScene ()\n  {\n    // int i, j, k;\n    if(!locpointsptr)\n      return;\n    auto& locpoints = *locpointsptr;\n    auto& loclines = *loclinesptr;\n    auto& plainpoints = *plainpointsptr;\n\n    if (loclines.Size() != changeval)\n      {\n\tcenter = Point<3>(0,0,-5);\n\trad = 0.1;\n\n\t// CalcTransformationMatrices();\n\tchangeval = loclines.Size();\n      }\n\n  glClearColor(backcolor, backcolor, backcolor, 1.0);\n  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n  SetLight();\n\n  //  glEnable (GL_COLOR_MATERIAL);\n\n  //  glDisable (GL_SHADING);\n  //  glColor3f (0.0f, 1.0f, 1.0f);\n  //  glLineWidth (1.0f);\n  //  glShadeModel (GL_SMOOTH);\n\n  //  glCallList (linelists.Get(1));\n\n  //  SetLight();\n\n  glPushMatrix();\n  glMultMatrixd (transformationmat);\n\n  glShadeModel (GL_SMOOTH);\n  // glDisable (GL_COLOR_MATERIAL);\n  glEnable (GL_COLOR_MATERIAL);\n  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n  glEnable (GL_BLEND);\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n  //  glEnable (GL_LIGHTING);\n\n  double shine = vispar.shininess;\n  // double transp = vispar.transp;\n\n  glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);\n  glLogicOp (GL_COPY);\n\n\n\n\n\n  float mat_col[] = { 0.2, 0.2, 0.8, 1 };\n  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);\n\n  glPolygonOffset (1, 1);\n  glEnable (GL_POLYGON_OFFSET_FILL);\n\n    float mat_colbl[] = { 0.8, 0.2, 0.2, 1 };\n    float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 };\n    float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 };\n\n\n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n    glPolygonOffset (1, -1);\n    glLineWidth (3);\n\n    for (int i = 1; i <= loclines.Size(); i++)\n      {\n\tif (i == 1)\n\t  {\n\t    glEnable (GL_POLYGON_OFFSET_FILL);\n\t    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl);\n\t  }\n\telse if (i <= oldnl)\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl);\n\telse\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl);\n\n\tint pi1 = loclines.Get(i).I1();\n\tint pi2 = loclines.Get(i).I2();\n\n\tif (pi1 >= 1 && pi2 >= 1)\n\t  {\n\t    Point3d p1 = locpoints.Get(pi1);\n\t    Point3d p2 = locpoints.Get(pi2);\n\n\t    glBegin (GL_LINES);\n\t    glVertex3f (p1.X(), p1.Y(), p1.Z());\n\t    glVertex3f (p2.X(), p2.Y(), p2.Z());\n\t    glEnd();\n\t  }\n\n\tglDisable (GL_POLYGON_OFFSET_FILL);\n      }\n\n\n    glLineWidth (1);\n\n\n    glPointSize (5);\n    float mat_colp[] = { 1, 0, 0, 1 };\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);\n    glBegin (GL_POINTS);\n    for (int i = 1; i <= locpoints.Size(); i++)\n      {\n\tPoint3d p = locpoints.Get(i);\n\tglVertex3f (p.X(), p.Y(), p.Z());\n      }\n    glEnd();\n\n\n    glPopMatrix();\n\n\n    // float mat_colp[] = { 1, 0, 0, 1 };\n\n    float mat_col2d1[] = { 1, 0.5, 0.5, 1 };\n    float mat_col2d[] = { 1, 1, 1, 1 };\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);\n\n    glBegin (GL_LINES);\n    for (int i = 1; i <= loclines.Size(); i++)\n      {\n\tglMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);\n\tif (i == 1)\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1);\n\n\tint pi1 = loclines.Get(i).I1();\n\tint pi2 = loclines.Get(i).I2();\n\n\tif (pi1 >= 1 && pi2 >= 1)\n\t  {\n\t    const auto& p1 = plainpoints.Get(pi1);\n\t    const auto& p2 = plainpoints.Get(pi2);\n\n\t    glBegin (GL_LINES);\n\t    glVertex3f (scalex * p1[0] + shiftx, scaley * p1[1] + shifty, -5);\n\t    glVertex3f (scalex * p2[0] + shiftx, scaley * p2[1] + shifty, -5);\n\t    glEnd();\n\t  }\n      }\n    glEnd ();\n\n\n    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);\n    glBegin (GL_POINTS);\n    for (int i = 1; i <= plainpoints.Size(); i++)\n      {\n\tconst auto& p = plainpoints.Get(i);\n\tglVertex3f (scalex * p[0] + shiftx, scaley * p[1] + shifty, -5);\n      }\n    glEnd();\n\n\n\n\n\n\n  glDisable (GL_POLYGON_OFFSET_FILL);\n\n  glPopMatrix();\n  DrawCoordinateCross ();\n  DrawNetgenLogo ();\n  glFinish();\n\n  }\n\n\n  void VisualSceneSurfaceMeshing :: BuildScene (int zoomall)\n  {\n  }\n\n  VisualSceneSurfaceMeshing vssurfacemeshing;\n\n  void Impl_Render (bool blocking)\n  {\n    if (blocking && multithread.running)\n      {\n        multithread.redraw = 2;\n        while (multithread.redraw == 2) ;\n      }\n    else\n      multithread.redraw = 1;\n  }\n\n  void Impl_UpdateVisSurfaceMeshData(int oldnl,\n            shared_ptr<NgArray<Point<3>>> locpointsptr,\n            shared_ptr<NgArray<INDEX_2>> loclinesptr,\n            shared_ptr<NgArray<Point<2>>> plainpointsptr)\n  {\n      vssurfacemeshing.oldnl = oldnl;\n      if(locpointsptr) vssurfacemeshing.locpointsptr = locpointsptr;\n      if(loclinesptr) vssurfacemeshing.loclinesptr = loclinesptr;\n      if(plainpointsptr) vssurfacemeshing.plainpointsptr = plainpointsptr;\n  }\n\n  static bool set_function_pointers = []()\n  {\n      Ptr_Render = Impl_Render;\n      Ptr_UpdateVisSurfaceMeshData = Impl_UpdateVisSurfaceMeshData;\n      return true;\n  }();\n\n\n\n#ifdef PARALLELGL\n  void VisualScene :: InitParallelGL ()\n  {\n    static int init = 0;\n\n    if (!init)\n      {\n\tinit = 1;\n\n\tif (id == 0)\n\t  {\n\t    string displname;\n\t    \n\t    Display * dpy = glXGetCurrentDisplay();\n\t    GLXDrawable drawable = glXGetCurrentDrawable();\n\t    GLXContext ctx = glXGetCurrentContext();\n\t    GLXContextID xid = glXGetContextIDEXT (ctx);\n\t    \n\t    displname = XDisplayName (0);\n\n\t    if( glXIsDirect ( dpy, ctx ) )\n\t      cout << \"WARNING: direct rendering enabled; this might break mpi-parallel netgen (especially if X-forwarding is used! (to disable, change -indirect to true in ng/drawing.tcl)\" << endl;\n\t      \n\t    /*\n\t    cout << \"Init Parallel GL\" << endl;\n\t    cout << \"DisplayName = \" << displname << endl;\n\t    cout << \"current display = \" << dpy << endl;\n\t    cout << \"current drawable = \" << drawable << endl;                  \n\t    cout << \"current context = \" << ctx << endl;                  \n\t    \n\t    cout << \"contextid = \" << xid << endl;\n\t    cout << \"isdirect = \" << glXIsDirect ( dpy, ctx ) << endl;                  \n\t    cout << \"extensionstring = \" << glXQueryExtensionsString( dpy, 0 ) << endl;\n\t    */\n\n\t    MyMPI_SendCmd (\"redraw\");\n\t    MyMPI_SendCmd (\"init\");\n\t\t\n\t    for (int dest = 1; dest < ntasks; dest++)\n\t      {\n\t\tMyMPI_Send (displname, dest, MPI_TAG_VIS);\n\t\tMyMPI_Send (int (drawable), dest, MPI_TAG_VIS);\n\t\tMyMPI_Send (int (xid), dest, MPI_TAG_VIS);\n\t      } \n\t  }\n      }\n  }\n\n\n  void VisualScene :: Broadcast ()\n  {\n    if (ntasks == 1) return;\n\n    if (id == 0)\n      {\n\t/*\n\tfor (int dest = 1; dest < ntasks; dest++)\n\t  {\n\t    MyMPI_Send (\"redraw\", dest, MPI_TAG_CMD);\n\t    MyMPI_Send (\"broadcast\", dest, MPI_TAG_VIS);\n\t  }\n\t*/\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"broadcast\");\n      }\n\n    MyMPI_Bcast (selface);\n\n    netgen::GetVSSolution().Broadcast ();\n  }\n#endif \n\n}\n"
  },
  {
    "path": "libsrc/visualization/mvdraw.hpp",
    "content": "#ifndef FILE_MVDRAW\n#define FILE_MVDRAW\n\n\n#include \"meshing/global.hpp\"\nnamespace netgen\n{\n\n\n  class VisualScene\n  {\n  protected:\n    static NGGUI_API Point3d center;\n    static NGGUI_API double rad;\n\n    static double lookatmat[16];\n    static double transmat[16];\n    static double rotmat[16];\n    static double centermat[16];\n\t\n    static NGGUI_API double transformationmat[16];\n\n    GLdouble clipplane[4];\n\n    int changeval;\n    static NGGUI_API GLdouble backcolor;\n\n    static int NGGUI_API selface;\n    static int selelement;\n    static PointIndex NGGUI_API selpoint;\n    static PointIndex selpoint2;\n    static int locpi;\n    static int NGGUI_API seledge;\n\n    static optional<Point<3>> marker;\n\n    static int subdivision_timestamp;\n    static int subdivisions;\n  public:\n    static int viewport[4];\n    static GLuint coltexname;\n    static int ntexcols;\n    int invcolor;\n\n\n  public:\n    NGGUI_API VisualScene ();\n    NGGUI_API virtual ~VisualScene();\n\n    NGGUI_API virtual void BuildScene (int zoomall = 0);\n    NGGUI_API virtual void DrawScene ();\n  \n    NGGUI_API void CalcTransformationMatrices();\n    NGGUI_API void StandardRotation (const char * dir);\n    NGGUI_API void ArbitraryRotation (const NgArray<double> & alpha, const NgArray<Vec3d> & vec);\n    NGGUI_API void ArbitraryRotation (const double alpha, const Vec3d & vec);\n\n    NGGUI_API virtual void MouseMove(int oldx, int oldy,\n                                      int newx, int newy,\n                                      char mode);\n\n    NGGUI_API void LookAt (const Point<3> & cam, const Point<3> & obj,\n                 const Point<3> & camup);\n\n    NGGUI_API void SetClippingPlane ();\n\n    NGGUI_API virtual void MouseDblClick (int px, int py);\n\n    NGGUI_API void SetLight ();\n    static void SetBackGroundColor (double col)\n    { backcolor = col; }\n\n    NGGUI_API void CreateTexture (int ncols, int linear, double alpha, int typ);\n    NGGUI_API void DrawColorBar (double minval, double maxval, int logscale = 0, bool linear = 1, string format=\"%8.3e\", string unit=\"\");\n    NGGUI_API void DrawTitle (string title);\n    NGGUI_API void DrawCoordinateCross ();\n    NGGUI_API void DrawMarker();\n    NGGUI_API void DrawNetgenLogo ();\n    NGGUI_API void SetOpenGlColor(double val, double valmin, double valmax, int logscale = 0);\n\t\n\n#ifdef PARALLELGL\n    NGGUI_API void InitParallelGL ();\n    NGGUI_API void Broadcast ();\n#endif \n  };\n\n\n  NGGUI_API extern void MyOpenGLText (const char * text);\n  NGGUI_API extern int MyOpenGLTextWidth ();\n  NGGUI_API extern void Set_OpenGLText_Callback ( void (*fun) (const char * text), int width );\n  NGGUI_API extern VisualScene visual_scene_cross;\n  NGGUI_API extern VisualScene *visual_scene;\n  NGGUI_API extern void MyOpenGLLines (FlatArray<Point<3>> points);\n\n\n\n\n\n\n\n\n\n\n  class VisualSceneSurfaceMeshing : public VisualScene\n  {\n    double scalex = 1., scaley = 1., shiftx = 0., shifty = 0.;\n  public:\n    shared_ptr<NgArray<Point<3>>> locpointsptr;\n    shared_ptr<NgArray<INDEX_2>> loclinesptr;\n    shared_ptr<NgArray<Point<2>>> plainpointsptr;\n    int oldnl;\n    bool clearptr;\n    VisualSceneSurfaceMeshing ();\n    virtual ~VisualSceneSurfaceMeshing ();\n\n    void BuildScene (int zoomall = 0) override;\n    void DrawScene () override;\n    NGGUI_API void MouseMove(int oldx, int oldy, int newx, int newy,\n                   char mode) override;\n  };\n\n  NGGUI_API extern VisualSceneSurfaceMeshing vssurfacemeshing;\n\n\n\n  struct VisualSelect\n  {\n    unsigned framebuffer = 0;\n    unsigned render_buffers[2];\n    unsigned width = 0;\n    unsigned height = 0;\n    unsigned x = 0;\n    unsigned y = 0;\n    int list = 0;\n    int list_timestamp = -1;\n    double projmat[16];\n    double transformationmat[16]; // todo: set\n    double clipplane[4]; // todo: set\n    int viewport[4];\n    int selelement = -1;\n    Point<3> center; // todo: set\n    double rad = 0.0; // todo: set\n    bool enable_clipping_plane = true; // todo: set\n\n    bool Unproject(int px, int py, Point<3> &p)\n    {\n      auto hy = viewport[3] - py;\n      float pz;\n      glReadPixels (px, hy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pz);\n      if(pz<1 && pz>0)\n        gluUnProject(px, hy, pz, transformationmat, projmat, viewport,\n            &p[0], &p[1], &p[2]);\n      return pz<1 && pz>0;\n    }\n\n    ngcore::IVec<2> Project(Point<3> p)\n    {\n      Point<3> pwin;\n      gluProject(p[0], p[1], p[2], transformationmat, projmat, viewport,\n          &pwin[0], &pwin[1], &pwin[2]);\n\n      return ngcore::IVec<2>(pwin[0]+0.5, viewport[3]-pwin[1]+0.5);\n    }\n\n    bool SelectSurfaceElement (shared_ptr<Mesh> mesh, int px, int py, Point<3> &p, bool select_on_clipping_plane);\n  };\n\n\n\n\n  class VisualSceneMesh : public VisualScene\n  {\n    int filledlist = 0;\n    int linelist = 0;\n    int edgelist = 0;\n    int pointnumberlist = 0;\n\n    int tetlist = 0;\n    int prismlist = 0;\n    int pyramidlist = 0;\n    int hexlist = 0;\n\n    int badellist = 0;\n    int identifiedlist = 0;\n    int domainsurflist = 0;\n\n    int vstimestamp = -1;\n    int filledtimestamp = -1;\n    int linetimestamp = -1;\n    int edgetimestamp = -1;\n    // int pointnumbertimestamp = -1;\n\n    int tettimestamp = -1;\n    int prismtimestamp = -1;\n    int pyramidtimestamp = -1;\n    int hextimestamp = -1;\n\n    // int badeltimestamp = -1;\n    // int identifiedtimestamp = -1;\n    // int domainsurftimestamp = -1;\n\n    struct {\n      unsigned texture = -1;\n      int width = 0;\n      int height = 0;\n      int size = 0;\n    } colors;\n\n    VisualSelect select;\n\n#ifdef PARALLELGL\n    NgArray<int> par_linelists;\n    NgArray<int> par_filledlists;\n#endif\n\n    MouseEventHandler * user_me_handler;\n\n    NgLock *lock;\n\n    //  int selface, selelement;\n    //  int selpoint, selpoint2, locpi;\n    //  int seledge;\n\n    double minh, maxh; // for meshsize coloring\n    mutable shared_ptr<Mesh> mesh;\n\n  public:\n    NGGUI_API VisualSceneMesh ();\n\tNGGUI_API virtual ~VisualSceneMesh ();\n\n\tNGGUI_API virtual void BuildScene (int zoomall = 0);\n\tNGGUI_API virtual void DrawScene ();\n\tNGGUI_API virtual void MouseDblClick (int px, int py);\n\n    NGGUI_API void SetMesh (shared_ptr<Mesh> m) { mesh = m; }\n    NGGUI_API shared_ptr<Mesh> GetMesh () const { return mesh; }\n\n    void SetMouseEventHandler (MouseEventHandler * handler)\n    { user_me_handler = handler; }\n\n\n\tNGGUI_API int SelectedFace () const\n    { return selface; }\n\tNGGUI_API void SetSelectedFace (int asf);\n    //    { selface = asf; selecttimestamp = GetTimeStamp(); }\n\n\tNGGUI_API int SelectedEdge () const\n    { return seledge; }\n\tNGGUI_API int SelectedElement () const\n    { return selelement; }\n\tNGGUI_API int SelectedPoint () const\n    { return selpoint; }\n    void BuildFilledList (bool select);\n    void BuildColorTexture();\n    void SelectCenter(int zoomall);\n    // private:\n    void BuildLineList();\n    void BuildEdgeList();\n    void BuildPointNumberList();\n\n    void BuildTetList(const BitArray & shownode);\n    void BuildPrismList(const BitArray & shownode);\n    void BuildPyramidList(const BitArray & shownode);\n    void BuildHexList(const BitArray & shownode);\n\n    void BuildBadelList();\n    void BuildIdentifiedList();\n    void BuildDomainSurfList();\n\n    bool SelectSurfaceElement (int px, int py, Point<3> &p, bool select_on_clipping_plane);\n    bool Unproject(int px, int py, Point<3> &p);\n    ngcore::IVec<2> Project(Point<3> p);\n  };\n\n  NGGUI_API extern VisualSceneMesh vsmesh;\n  \n\n  class NGGUI_API VisualSceneSpecPoints : public VisualScene\n  {\n  public:\n    VisualSceneSpecPoints ();\n    virtual ~VisualSceneSpecPoints ();\n\n    virtual void BuildScene (int zoomall = 0);\n    virtual void DrawScene ();\n\n    double len;\n  };\n\n\n\n  \n  \n\n\n  // extern struct Tcl_Interp * hinterp;\n\n\n  extern void AddVisualizationScene (const string & name, \n                                     VisualScene * vs);\n\n\n  void MouseDblClickSelect (const int px, const int py,\n                            const GLdouble * clipplane, const GLdouble backcolor,\n                            const double * transformationmat,\n                            const Point3d & center,\n                            const double rad,\n                            const int displaylist,\n                            int & selelement, int & selface, int & seledge, PointIndex & selpoint,\n                            PointIndex & selpoint2, int & locpi);\n\n  void RenderSurfaceElements (shared_ptr<Mesh> mesh,\n      int subdivisions,\n      std::function<bool(int)> face_init,\n      std::function<bool(SurfaceElementIndex)> sel_init\n  );\n\n  NGGUI_API std::vector<unsigned char> Snapshot( int w, int h );\n}\n\n\n#endif\n\n"
  },
  {
    "path": "libsrc/visualization/vispar.hpp",
    "content": "#ifndef FILE_VISPAR\n#define FILE_VISPAR\n\nnamespace netgen\n{\n\nclass VisualizationParameters\n{\npublic:\n  double lightamb;\n  double lightdiff;\n  double lightspec;\n  double shininess;\n  double transp;\n  int locviewer;\n  char selectvisual[20];\n  int showstltrias;\n  \n  /*\n  Vec3d clipnormal;\n  double clipdist;\n  int clipenable;\n  int clipplanetimestamp;\n  */\n  class Clipping\n  {\n  public:\n    Vec3d normal;\n    double dist;\n    double dist2;\n    int enable;\n    int timestamp;\n    bool operator== (Clipping & clip2)\n    {\n      return \n\t(normal == clip2.normal) && \n\t(dist == clip2.dist) && \n\t// (dist2 == clip2.dist2) && \n\t(enable == clip2.enable);\n    }\n  };\n  Clipping clipping;\n\n  int colormeshsize;\n\n  int drawfilledtrigs;\n  int drawbadels;\n  int drawoutline;\n  int drawedges;\n  int subdivisions;\n\n  int drawprisms;\n  int drawpyramids;\n  int drawhexes;\n  double shrink;\n  int drawidentified;\n  int drawpointnumbers;\n  int drawedgenumbers;\n  int drawfacenumbers;\n  int drawelementnumbers;\n  int drawsurfaceelementnumbers;\n  int drawsegmentnumbers;\n  int drawdomainsurf;\n  int drawtets;\n  int drawtetsdomain;\n\n  int clipdomain;\n  int donotclipdomain;\n\n  int drawededges;\n  int drawedpoints;\n  int drawedpointnrs;\n  int drawedtangents;\n  int drawededgenrs;\n  int drawmetispartition;\n\n  int drawcurveproj;\n  int drawcurveprojedge;\n  \n\n  PointIndex centerpoint;\n  int drawelement;\n\n  // stl:\n  int stlshowtrias;\n  int stlshowfilledtrias;\n  int stlshowedges;\n  int stlshowmarktrias;\n  int stlshowactivechart;\n  int stlchartnumber;\n  int stlchartnumberoffset;\n\n  // occ:\n  int occshowvolumenr;\n  bool occshowsurfaces;\n  bool occshowedges;\n  bool occvisproblemfaces;\n  bool occzoomtohighlightedentity;\n  double occdeflection;\n\n  // ACIS\n\n  bool ACISshowfaces;\n  bool ACISshowedges;\n  int ACISshowsolidnr;\n  int ACISshowsolidnr2;\n\n  bool whitebackground;\n  int stereo;\n  bool usedispllists;\n  bool drawcoordinatecross;\n  bool drawcolorbar;\n  bool drawnetgenlogo;\n\n  bool use_center_coords;\n  double centerx,centery,centerz;\n\n  bool drawspecpoint;\n  double specpointx,specpointy,specpointz;\n\n  \npublic:\n  VisualizationParameters();\n};\nNGGUI_API extern VisualizationParameters vispar;\n}\n\n#endif\n"
  },
  {
    "path": "libsrc/visualization/visual.hpp",
    "content": "#ifndef FILE_VISUAL\n#define FILE_VISUAL\n\n/* *************************************************************************/\n/* File:   visual.hpp                                                       */\n/* Author: Joachim Schoeberl                                               */\n/* Date:   02. Dec. 01                                                     */\n/* *************************************************************************/\n\n/* \n\nVisualization\n\n*/\n\n#include \"visual_api.hpp\"\n#include \"../include/incopengl.hpp\"\n\n#include \"../meshing/visual_interface.hpp\"\n#include \"../meshing/soldata.hpp\"\n#include \"vispar.hpp\"\n#include \"mvdraw.hpp\"\n\n#include <complex>\n#include \"vssolution.hpp\"\n#include \"meshdoc.hpp\"\n\n#endif\n"
  },
  {
    "path": "libsrc/visualization/visual_api.hpp",
    "content": "#ifndef VISUAL_API_HPP_INCLUDED\n#define VISUAL_API_HPP_INCLUDED\n\n#ifdef nggui_EXPORTS\n#define NGGUI_API NGCORE_API_EXPORT\n#else\n#define NGGUI_API NGCORE_API_IMPORT\n#endif\n\n#endif // VISUAL_API_HPP_INCLUDED\n"
  },
  {
    "path": "libsrc/visualization/visualpkg.cpp",
    "content": "#include <mystdlib.h>\n// #include <incopengl.hpp>\n\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n\n#include <inctcl.hpp>\n// #include <parallel.hpp>\n#include <visual.hpp>\n\n#include <limits>\n\n\n\n\n\n\nnamespace netgen\n\n{\n\n  /*\n  */\n\n\n\n\n\n\n\n\n  int Ng_Vis_Set (ClientData clientData,\n                  Tcl_Interp * interp,\n                  int argc, tcl_const char *argv[])\n\n  {\n    auto & vssolution = netgen::GetVSSolution();\n    if (argc >= 2)\n      {\n        if (strcmp (argv[1], \"parameters\") == 0)\n          {\n            vssolution.imag_part = \n              atoi (Tcl_GetVar (interp, \"::visoptions.imaginary\", TCL_GLOBAL_ONLY));      \n            vssolution.usetexture = \n              atoi (Tcl_GetVar (interp, \"::visoptions.usetexture\", TCL_GLOBAL_ONLY));\n            if (atoi (Tcl_GetVar (interp, \"::visoptions.redrawperiodic\", TCL_GLOBAL_ONLY)))\n              vssolution.usetexture = 2;\n                \n            vssolution.invcolor = \n              atoi (Tcl_GetVar (interp, \"::visoptions.invcolor\", TCL_GLOBAL_ONLY));       \n\n            vssolution.clipsolution = 0;\n\n            if (strcmp (Tcl_GetVar (interp, \"::visoptions.clipsolution\", TCL_GLOBAL_ONLY), \n                        \"scal\") == 0)\n              vssolution.clipsolution = 1;\n            if (strcmp (Tcl_GetVar (interp, \"::visoptions.clipsolution\", TCL_GLOBAL_ONLY), \n                        \"vec\") == 0)\n              vssolution.clipsolution = 2;\n            \n            tcl_const char * scalname =  \n              Tcl_GetVar (interp, \"::visoptions.scalfunction\", TCL_GLOBAL_ONLY);\n            tcl_const char * vecname = \n              Tcl_GetVar (interp, \"::visoptions.vecfunction\", TCL_GLOBAL_ONLY);\n            tcl_const char * fieldlines_vecname = \n              Tcl_GetVar (interp, \"::visoptions.fieldlinesvecfunction\", TCL_GLOBAL_ONLY);\n                \n          \n            vssolution.scalfunction = -1;\n            vssolution.vecfunction = -1;\n            vssolution.fieldlines_vecfunction = -1;\n\n            int pointpos; // SZ \n            const char * pch = strchr(scalname,':');\n            pointpos = int(pch-scalname+1);\n\t    \n            for (int i = 0; i < vssolution.soldata.Size(); i++)\n              {\n                if ( (strlen (vssolution.soldata[i]->name.c_str()) == size_t(pointpos-1)) &&\n                     (strncmp (vssolution.soldata[i]->name.c_str(), scalname, pointpos-1) == 0) )\n                  {\n                    vssolution.SetScalfunction(i);\n                    vssolution.scalcomp = atoi (scalname + pointpos);\n\t\t    if ( vssolution.scalcomp > vssolution.soldata[i]->components )\n                      vssolution.scalcomp = 1;\n\t\t    char newscalname[100];\n\t\t    for ( int ii = 0; ii < pointpos; ii++ )\n\t\t      newscalname[ii] = scalname[ii];\n\t\t    newscalname[pointpos] = ':';\n\t\t    snprintf (newscalname+pointpos, sizeof(newscalname)-pointpos, \"%i\", vssolution.scalcomp);\n\n                    if (strcmp (scalname, newscalname) != 0)\n                      Tcl_SetVar ( interp, \"::visoptions.scalfunction\", newscalname, TCL_GLOBAL_ONLY );\n\t\t    scalname = Tcl_GetVar (interp, \"::visoptions.scalfunction\", TCL_GLOBAL_ONLY);\n                  }\n                if (strcmp (vssolution.soldata[i]->name.c_str(), vecname) == 0)\n\t\t  vssolution.SetVecfunction(i);\n\n                if (strcmp (vssolution.soldata[i]->name.c_str(), fieldlines_vecname) == 0)\n\t\t  vssolution.fieldlines_vecfunction = i;\n              }\n\n            if(vssolution.fieldlines_vecfunction != -1 &&\n               vssolution.vecfunction == -1)\n              {\n                //cout << \"WARNING: Setting vector function in Visualization toolbox to value from Fieldlines toolbox!\" << endl;\n                vssolution.vecfunction = vssolution.fieldlines_vecfunction;\n              }\n               \n\t    // reset visoptions.scalfunction and visoptions.vecfunction if not available \n\t    if ( vssolution.scalfunction == -1 && strcmp (scalname, \"none\") != 0)\n              Tcl_SetVar ( interp, \"::visoptions.scalfunction\", \"none\", TCL_GLOBAL_ONLY );\n\t    if ( vssolution.vecfunction == -1  && strcmp (vecname, \"none\") != 0)\n              Tcl_SetVar ( interp, \"::visoptions.vecfunction\", \"none\", TCL_GLOBAL_ONLY );\n\n            tcl_const char * evalname = \n              Tcl_GetVar (interp, \"::visoptions.evaluate\", TCL_GLOBAL_ONLY);\n          \n            if (strcmp(evalname, \"abs\") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_ABS;\n            if (strcmp(evalname, \"abstens\") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_ABS_TENSOR;\n            if (strcmp(evalname, \"mises\") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_MISES;\n            if (strcmp(evalname, \"main\") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_MAIN;\n\n            vssolution.gridsize = \n              atoi (Tcl_GetVar (interp, \"::visoptions.gridsize\", TCL_GLOBAL_ONLY));\n\n            vssolution.xoffset = \n              atof (Tcl_GetVar (interp, \"::visoptions.xoffset\", TCL_GLOBAL_ONLY));\n\n            //    cout << \"x-offset:\" << vssolution.xoffset << endl;\n\n            vssolution.yoffset = \n              atof (Tcl_GetVar (interp, \"::visoptions.yoffset\", TCL_GLOBAL_ONLY));\n\n            vssolution.autoscale = \n              atoi (Tcl_GetVar (interp, \"::visoptions.autoscale\", TCL_GLOBAL_ONLY));\n\n\n            /*\n              vssolution.linear_colors = \n              atoi (Tcl_GetVar (interp, \"::visoptions.lineartexture\", TCL_GLOBAL_ONLY));\n            */\n            vssolution.logscale = \n              atoi (Tcl_GetVar (interp, \"::visoptions.logscale\", TCL_GLOBAL_ONLY));\n\n            vssolution.mminval = \n              atof (Tcl_GetVar (interp, \"::visoptions.mminval\", TCL_GLOBAL_ONLY));\n            vssolution.mmaxval = \n              atof (Tcl_GetVar (interp, \"::visoptions.mmaxval\", TCL_GLOBAL_ONLY));\n\n            vssolution.showclipsolution = \n              atoi (Tcl_GetVar (interp, \"::visoptions.showclipsolution\", TCL_GLOBAL_ONLY));\n            vssolution.showsurfacesolution = \n              atoi (Tcl_GetVar (interp, \"::visoptions.showsurfacesolution\", TCL_GLOBAL_ONLY));\n            vssolution.lineartexture = \n              atoi (Tcl_GetVar (interp, \"::visoptions.lineartexture\", TCL_GLOBAL_ONLY));\n            vssolution.numtexturecols = \n              atoi (Tcl_GetVar (interp, \"::visoptions.numtexturecols\", TCL_GLOBAL_ONLY));\n\n            vssolution.multidimcomponent = \n              atoi (Tcl_GetVar (interp, \"::visoptions.multidimcomponent\", TCL_GLOBAL_ONLY));\n\n\t    vssolution.drawpointcurves = \n\t      atoi (Tcl_GetVar (interp, \"::visoptions.drawpointcurves\", TCL_GLOBAL_ONLY));\t      \n\n            vssolution.draw_fieldlines = \n\t      atoi (Tcl_GetVar (interp, \"::visoptions.drawfieldlines\", TCL_GLOBAL_ONLY));\n            vssolution.num_fieldlines = \n              atoi (Tcl_GetVar (interp, \"::visoptions.numfieldlines\", TCL_GLOBAL_ONLY));\n            vssolution.fieldlines_randomstart =\n              atoi (Tcl_GetVar (interp, \"::visoptions.fieldlinesrandomstart\", TCL_GLOBAL_ONLY));\n\n            vssolution.fieldlines_reltolerance =\n              atof (Tcl_GetVar (interp, \"::visoptions.fieldlinestolerance\", TCL_GLOBAL_ONLY));\n\n            if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesrktype\", TCL_GLOBAL_ONLY), \n                        \"euler\") == 0)\n              vssolution.fieldlines_rktype = 0;\n            else if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesrktype\", TCL_GLOBAL_ONLY), \n                             \"eulercauchy\") == 0)\n              vssolution.fieldlines_rktype = 1;\n            else if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesrktype\", TCL_GLOBAL_ONLY), \n                             \"simpson\") == 0)\n              vssolution.fieldlines_rktype = 2;\n            else if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesrktype\", TCL_GLOBAL_ONLY), \n                             \"crungekutta\") == 0)\n              vssolution.fieldlines_rktype = 3;\n\n\n            vssolution.fieldlines_rellength =\n              atof (Tcl_GetVar (interp, \"::visoptions.fieldlineslength\", TCL_GLOBAL_ONLY));\n\n            vssolution.fieldlines_maxpoints = \n              atoi (Tcl_GetVar (interp, \"::visoptions.fieldlinesmaxpoints\", TCL_GLOBAL_ONLY));\n\n            vssolution.fieldlines_relthickness =\n              atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesthickness\", TCL_GLOBAL_ONLY));\n\n\n            vssolution.fieldlines_fixedphase = \n              (atoi (Tcl_GetVar (interp, \"::visoptions.fieldlinesonlyonephase\", TCL_GLOBAL_ONLY)) != 0);\n\n            if(vssolution.fieldlines_fixedphase)\n              vssolution.fieldlines_phase =\n                atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesphase\", TCL_GLOBAL_ONLY));\n\n\n            if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartarea\", TCL_GLOBAL_ONLY), \n                        \"box\") == 0)\n              vssolution.fieldlines_startarea  = 0;\n            else if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartarea\", TCL_GLOBAL_ONLY), \n                             \"file\") == 0)\n              vssolution.fieldlines_startarea  = 1;\n            else if (strcmp (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartarea\", TCL_GLOBAL_ONLY), \n                             \"face\") == 0)\n              vssolution.fieldlines_startarea  = 2;\n\n                \n            if (vssolution.fieldlines_startarea == 0)\n              {\n                vssolution.fieldlines_startarea_parameter.SetSize(6);\n                vssolution.fieldlines_startarea_parameter[0] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap1x\", TCL_GLOBAL_ONLY));\n                vssolution.fieldlines_startarea_parameter[1] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap1y\", TCL_GLOBAL_ONLY));\n                vssolution.fieldlines_startarea_parameter[2] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap1z\", TCL_GLOBAL_ONLY));\n                vssolution.fieldlines_startarea_parameter[3] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap2x\", TCL_GLOBAL_ONLY));\n                vssolution.fieldlines_startarea_parameter[4] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap2y\", TCL_GLOBAL_ONLY));\n                vssolution.fieldlines_startarea_parameter[5] = atof (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartareap2z\", TCL_GLOBAL_ONLY));\n              }\n            else if (vssolution.fieldlines_startarea == 1)\n              {\n                vssolution.fieldlines_filename = Tcl_GetVar (interp, \"::visoptions.fieldlinesfilename\", TCL_GLOBAL_ONLY);\n              }\n            else if (vssolution.fieldlines_startarea == 2)\n              {\n                vssolution.fieldlines_startface = atoi (Tcl_GetVar (interp, \"::visoptions.fieldlinesstartface\", TCL_GLOBAL_ONLY));\n              }\n\n          \n            vssolution.deform =\n              atoi (Tcl_GetVar (interp, \"::visoptions.deformation\", TCL_GLOBAL_ONLY));\n            vssolution.scaledeform =\n              atof (Tcl_GetVar (interp, \"::visoptions.scaledeform1\", TCL_GLOBAL_ONLY)) *\n              atof (Tcl_GetVar (interp, \"::visoptions.scaledeform2\", TCL_GLOBAL_ONLY));\n\n\n            if (atoi (Tcl_GetVar (interp, \"::visoptions.isolines\", TCL_GLOBAL_ONLY)))\n              vssolution.numisolines = atoi (Tcl_GetVar (interp, \"::visoptions.numiso\", TCL_GLOBAL_ONLY));\n            else\n              vssolution.numisolines = 0;\n            vssolution.draw_isosurface = \n              atoi (Tcl_GetVar (interp, \"::visoptions.isosurf\", TCL_GLOBAL_ONLY));\n\n            vssolution.SetSubdivision(atoi (Tcl_GetVar (interp, \"::visoptions.subdivisions\", TCL_GLOBAL_ONLY)));\n\n            vssolution.UpdateSolutionTimeStamp();\n          }\n      \n        if (strcmp (argv[1], \"parametersrange\") == 0)\n          {\n            vssolution.invcolor = \n              atoi (Tcl_GetVar (interp, \"::visoptions.invcolor\", TCL_GLOBAL_ONLY));       \n            vssolution.mminval = \n              atof (Tcl_GetVar (interp, \"::visoptions.mminval\", TCL_GLOBAL_ONLY));\n            vssolution.mmaxval = \n              atof (Tcl_GetVar (interp, \"::visoptions.mmaxval\", TCL_GLOBAL_ONLY));\n            vssolution.lineartexture = \n              atoi (Tcl_GetVar (interp, \"::visoptions.lineartexture\", TCL_GLOBAL_ONLY));\n            vssolution.numtexturecols = \n              atoi (Tcl_GetVar (interp, \"::visoptions.numtexturecols\", TCL_GLOBAL_ONLY));\n\n            if (vssolution.usetexture == 0 || vssolution.logscale)\n              vssolution.UpdateSolutionTimeStamp();\n          }\n\n\n        if (argc >= 3 && strcmp (argv[1], \"time\") == 0)\n          {\n            vssolution.time = double (atoi (argv[2])) / 1000;\n         \n            vssolution.timetimestamp = NextTimeStamp();\n            cout << \"\\rtime = \" << vssolution.time << \"    \" << flush;\n          }\n\n      }\n\n    \n    vsmesh.SetClippingPlane ();  // for computing parameters\n    vssolution.SetClippingPlane ();  // for computing parameters\n    glDisable(GL_CLIP_PLANE0);\n\n#ifdef PARALLELGL\n    vsmesh.Broadcast ();\n#endif    \n\n\n    return TCL_OK;\n  }\n\n  int Ng_Vis_Field (ClientData clientData,\n                    Tcl_Interp * interp,\n                    int argc, tcl_const char *argv[])\n  {\n    int i;\n    char buf[1000];\n    buf[0] = 0;\n    auto & vssolution = netgen::GetVSSolution();\n\n    if (argc >= 2)\n      {\n        if (strcmp (argv[1], \"setfield\") == 0)\n          {\n            if (argc < 3)\n              return TCL_ERROR;\n\n            for (i = 0; i < vssolution.GetNSolData(); i++)\n              if (strcmp (vssolution.GetSolData(i)->name.c_str(), argv[2]) == 0)\n                {\n                  cout << \"found soldata \" << i << endl;\n                }\n          }\n\n        if (strcmp (argv[1], \"getnfieldnames\") == 0)\n          {\n            snprintf (buf, size(buf),  \"%d\", vssolution.GetNSolData());\n          }\n      \n        if (strcmp (argv[1], \"getfieldname\") == 0)\n          {\n            snprintf (buf, size(buf),  \"%s\", vssolution.GetSolData(atoi(argv[2])-1)->name.c_str());\n          }\n\n        if (strcmp (argv[1], \"iscomplex\") == 0)\n          {\n            snprintf (buf, size(buf),  \"%d\", vssolution.GetSolData(atoi(argv[2])-1)->iscomplex);\n          }\n\n        if (strcmp (argv[1], \"getfieldcomponents\") == 0)\n          {\n            snprintf (buf, size(buf),  \"%d\", vssolution.GetSolData(atoi(argv[2])-1)->components);\n          }\n\n      \n        if (strcmp (argv[1], \"getfieldnames\") == 0)\n          {\n            for (i = 0; i < vssolution.GetNSolData(); i++)\n              {\n                strcat (buf, vssolution.GetSolData(i)->name.c_str());\n                strcat (buf, \" \");\n              }\n            strcat (buf, \"var1 var2 var3\");\n            Tcl_SetResult (interp, buf, TCL_STATIC);\n          }\n\n        if (strcmp (argv[1], \"setcomponent\") == 0)\n          {\n            cout << \"set component \" << argv[2] << endl;\n          }\n\n        if (strcmp (argv[1], \"getactivefield\") == 0)\n          {\n            snprintf (buf, size(buf),  \"1\");\n          }\n\n        if (strcmp (argv[1], \"getdimension\") == 0)\n          {\n            auto mesh = vssolution.GetMesh();\n            snprintf (buf, size(buf),  \"%d\", mesh->GetDimension());\n          }\n      }\n\n    Tcl_SetResult (interp, buf, TCL_STATIC);\n    return TCL_OK;\n  }\n\n  VisualSceneMeshDoctor vsmeshdoc;\n  DLL_HEADER extern shared_ptr<Mesh> mesh;\n\n  int Ng_MeshDoctor(ClientData clientData,\n\t  Tcl_Interp * interp,\n\t  int argc, tcl_const char *argv[])\n  {\n\t  cout << \"Mesh Doctor:\" << endl;\n\t  int i;\n\t  for (i = 0; i < argc; i++)\n\t\t  cout << argv[i] << \" \";\n\t  cout << endl;\n\n\t  meshdoctor.active =\n\t\t  atoi(Tcl_GetVar(interp, \"::meshdoctor.active\", 0));\n\n\n\t  if (argc >= 2)\n\t  {\n\t\t  if (strcmp(argv[1], \"markedgedist\") == 0)\n\t\t  {\n\t\t\t  vsmeshdoc.SetMarkEdgeDist(atoi(argv[2]));\n\t\t  }\n\n\t\t  if (strcmp(argv[1], \"deletemarkedsegments\") == 0)\n\t\t  {\n\t\t\t  for (i = 1; i <= mesh->GetNSeg(); i++)\n\t\t\t\t  if (vsmeshdoc.IsSegmentMarked(i))\n\t\t\t\t\t  mesh->DeleteSegment(i);\n\n\t\t\t  //\t  for (i = 1; i <= mesh->GetNSE(); i++)\n\t\t\t  //\t    mesh->SurfaceElement(i).SetIndex (1);\n\t\t\t  mesh->Compress();\n\t\t  }\n\t  }\n\n\n\t  vsmeshdoc.UpdateTables();\n\t  vsmeshdoc.BuildScene();\n\t  return TCL_OK;\n  }\n\n\n  extern \"C\" int Ng_Vis_Init (Tcl_Interp * interp);\n\n  int Ng_Vis_Init (Tcl_Interp * interp)\n  {\n    Tcl_CreateCommand (interp, \"Ng_Vis_Set\", Ng_Vis_Set,\n                       (ClientData)NULL,\n                       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Vis_Field\", Ng_Vis_Field,\n                       (ClientData)NULL,\n                       (Tcl_CmdDeleteProc*) NULL);\n\n\n    return TCL_OK;\n  }\n\n\n\n\n}\n\n"
  },
  {
    "path": "libsrc/visualization/vsfieldlines.cpp",
    "content": "#ifndef NOTCL\n\n#include <mystdlib.h>\n#include <incopengl.hpp>\n\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n\n#include <visual.hpp>\n#include <meshing/fieldlines.hpp>\n\n\nnamespace netgen\n{\n\n  // extern shared_ptr<Mesh> mesh;\n\n  void VisualSceneSolution :: BuildFieldLinesFromBox(Array<Point<3>> & startpoints)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (!mesh) return;\n\n    if(fieldlines_startarea_parameter[0] > fieldlines_startarea_parameter[3] ||\n       fieldlines_startarea_parameter[1] > fieldlines_startarea_parameter[4] ||\n       fieldlines_startarea_parameter[2] > fieldlines_startarea_parameter[5])\n      {\n\tPoint3d pmin, pmax;\n\tmesh->GetBox (pmin, pmax);\n\t\n\tfieldlines_startarea_parameter[0] = pmin.X();\t\n\tfieldlines_startarea_parameter[1] = pmin.Y();\n\tfieldlines_startarea_parameter[2] = pmin.Z();\n\tfieldlines_startarea_parameter[3] = pmax.X();\t\n\tfieldlines_startarea_parameter[4] = pmax.Y();\n\tfieldlines_startarea_parameter[5] = pmax.Z();\n      }\n    \n    for (int i = 1; i <= startpoints.Size(); i++)\n      {\n\tPoint<3> p (fieldlines_startarea_parameter[0] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[3]-fieldlines_startarea_parameter[0]),\n\t\t   fieldlines_startarea_parameter[1] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[4]-fieldlines_startarea_parameter[1]),\n\t\t   fieldlines_startarea_parameter[2] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[5]-fieldlines_startarea_parameter[2]));\n\t\n\tstartpoints[i-1] = p;\n      }\n  }\n\n  void VisualSceneSolution :: BuildFieldLinesFromLine(Array<Point<3>> & startpoints)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (!mesh) return;\n\n\n    for (int i = 1; i <= startpoints.Size(); i++)\n      {\n\tdouble s = double (rand()) / RAND_MAX;\n\n\tPoint<3> p (fieldlines_startarea_parameter[0] + s * (fieldlines_startarea_parameter[3]-fieldlines_startarea_parameter[0]),\n\t\t   fieldlines_startarea_parameter[1] + s * (fieldlines_startarea_parameter[4]-fieldlines_startarea_parameter[1]),\n\t\t   fieldlines_startarea_parameter[2] + s * (fieldlines_startarea_parameter[5]-fieldlines_startarea_parameter[2]));\n\t\n\tstartpoints[i-1] = p;\n      }\n  }\n\n\n  void VisualSceneSolution :: BuildFieldLinesFromFile(Array<Point<3>> & startpoints)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (!mesh) return;\n\n    ifstream * infile;\n\n    infile = new ifstream(fieldlines_filename.c_str());\n\n    //cout << \"reading from file \" << fieldlines_filename << endl;\n\n    int numpoints = 0;\n\n    string keyword;\n\n    \n    double dparam;\n    int iparam;\n\n    while(infile->good())\n      {\n\t(*infile) >> keyword;\n\n\tif(keyword == \"point\") numpoints++;\n\telse if(keyword == \"line\" || keyword == \"box\")\n\t  {\n\t    for(int i=0; i<6; i++) (*infile) >> dparam;\n\t    (*infile) >> iparam;\n\t    numpoints += iparam;\n\t  }\n      }\n\n    delete infile;\n\n\n    //cout << numpoints << \" startpoints\" << endl;\n\n    startpoints.SetSize(numpoints);\n    \n    infile = new ifstream(fieldlines_filename.c_str());\n\n    numpoints = 0;\n\n    while(infile->good())\n      {\n\t(*infile) >> keyword;\n\n\tif (keyword == \"point\")\n\t  {\n\t    (*infile) >> startpoints[numpoints][0];\n            (*infile) >> startpoints[numpoints][1];\n            (*infile) >> startpoints[numpoints][2];\n\t    numpoints++;\n\t  }\n\telse if (keyword == \"line\" || keyword == \"box\")\n\t  {\n\t    for(int i=0; i<6; i++) (*infile) >> fieldlines_startarea_parameter[i];\n\t    (*infile) >> iparam;\n\n\t    Array<Point<3>> auxpoints(iparam);\n\t    \n\t    if (keyword == \"box\")\n\t      BuildFieldLinesFromBox(auxpoints);\n\t    else if (keyword == \"line\")\n\t      BuildFieldLinesFromLine(auxpoints);\n\t    \n\t    for(int i=0; i<iparam; i++)\n\t      {\n\t\tstartpoints[numpoints] = auxpoints[i];\n\t\tnumpoints++;\n\t      }\n\t  }\n\n\t//cout << \"startpoints \" << startpoints << endl;\n      }\n\n    delete infile;\n    \n    \n\n    \n  }\n\n  \n  void VisualSceneSolution :: BuildFieldLinesFromFace(Array<Point<3>> & startpoints)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (!mesh) return;\n\n    Array<SurfaceElementIndex> elements_2d;\n    \n    //cout << \"fieldlines_startface \" << fieldlines_startface << endl;\n    mesh->GetSurfaceElementsOfFace(fieldlines_startface,elements_2d);\n    if(elements_2d.Size() == 0)\n      {\n\tcerr << \"No Elements on selected face (?)\" << endl;\n\treturn;\n      }\n    Vec3d v1,v2,cross;\n    \n    double area = 0;\n\n\tint i;\n    for(i=0; i<elements_2d.Size(); i++)\n      {\n\tconst Element2d & elem = (*mesh)[elements_2d[i]];\n\t\n\tv1 = mesh->Point(elem[1]) - mesh->Point(elem[0]);\n\tv2 = mesh->Point(elem[2]) - mesh->Point(elem[0]);\n\tcross = Cross(v1,v2);\n\tarea += cross.Length();\n\t\n\tif(elem.GetNV() == 4)\n\t  {\n\t    v1 = mesh->Point(elem[2]) - mesh->Point(elem[0]);\n\t    v2 = mesh->Point(elem[3]) - mesh->Point(elem[0]);\n\t    cross = Cross(v1,v2);\n\t    area += cross.Length();\n\t  }\n      }\n    \n    int startpointsp = 0;\n    i = 0;\n    \n    while(startpointsp < startpoints.Size())\n      {\n\tconst Element2d & elem = (*mesh)[elements_2d[i]];\n\t\n\tint numtri = (elem.GetNV() == 3) ? 1 : 2;\n\t\n\tfor(int tri = 0; startpointsp < startpoints.Size() && tri<numtri; tri++)\n\t  {\n\t    \n\t    if(tri == 0)\n\t      {\n\t\tv1 = mesh->Point(elem[1]) - mesh->Point(elem[0]);\n\t\tv2 = mesh->Point(elem[2]) - mesh->Point(elem[0]);\n\t\tcross = Cross(v1,v2);\n\t      }\n\t    else if(tri == 1)\n\t      {\n\t\tv1 = mesh->Point(elem[2]) - mesh->Point(elem[0]);\n\t\tv2 = mesh->Point(elem[3]) - mesh->Point(elem[0]);\n\t\tcross = Cross(v1,v2);\n\t      }\n\t    \n\t    double thisarea = cross.Length();\n\t    \n\t    int numloc = int(startpoints.Size()*thisarea/area);\n\t    if(double (rand()) / RAND_MAX < startpoints.Size()*thisarea/area - numloc)\n\t      numloc++;\n\t    \n\t    for(int j=0; startpointsp < startpoints.Size() && j<numloc; j++)\n\t      {\n\t\tdouble s = double (rand()) / RAND_MAX;\n\t\tdouble t = double (rand()) / RAND_MAX;\n\t\tif(s+t > 1)\n\t\t  {\n\t\t    s = 1.-s; t = 1.-t;\n\t\t  }\n\t\tstartpoints[startpointsp] = mesh->Point(elem[0]) + s*v1 +t*v2;\n\t\tstartpointsp++;\n\t      }\n\t  }\n\ti++;\n\tif(i == elements_2d.Size()) i = 0;\n      } \n    \n  }\n\n\n  void VisualSceneSolution :: BuildFieldLinesPlot ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (!mesh) return;\n\n    if (fieldlinestimestamp >= solutiontimestamp) \n      return;\n    fieldlinestimestamp = solutiontimestamp;\n    \n\n    if (fieldlineslist)\n      glDeleteLists (fieldlineslist, num_fieldlineslists);\n\n    if (vecfunction == -1)\n      return;\n\n    const SolData * vsol = soldata[fieldlines_vecfunction];\n\n    num_fieldlineslists = (vsol -> iscomplex && !fieldlines_fixedphase) ? 100 : 1;\n   \n    double phaser=1.0;\n    double phasei=0.0;\n    std::function<bool(int, const double *, Vec<3> &)> eval_func = [&](int elnr, const double * lami, Vec<3> & vec)\n    {\n        double values[6] = {0., 0., 0., 0., 0., 0.};\n        bool drawelem;\n        auto mesh = GetMesh();\n        if (mesh->GetDimension()==3)\n            drawelem = GetValues (vsol, elnr, lami[0], lami[1], lami[2], values);\n        else\n            drawelem = GetSurfValues (vsol, elnr, -1, lami[0], lami[1], values);\n\n        Vec3d v;\n        RealVec3d (values, v, vsol->iscomplex, phaser, phasei);\n        vec = v;\n        return drawelem;\n    };\n\n    FieldLineCalc linecalc(*mesh, eval_func,\n\t\t\t   fieldlines_rellength,fieldlines_maxpoints,fieldlines_relthickness,fieldlines_reltolerance,fieldlines_rktype);\n\n    if(fieldlines_randomstart) \n      linecalc.Randomized();\n\n    fieldlineslist = glGenLists (num_fieldlineslists);\n\n    int num_startpoints = num_fieldlines / num_fieldlineslists;\n    if (num_fieldlines % num_fieldlineslists != 0) num_startpoints++;\n\n    if(fieldlines_randomstart)\n      num_startpoints *= 10;\n\n    \n    Array<Point<3>> startpoints(num_startpoints);\n    \n\n    for (int ln = 0; ln < num_fieldlineslists; ln++)\n      {\n\tif(fieldlines_startarea == 0)\n\t  BuildFieldLinesFromBox(startpoints);\n\telse if(fieldlines_startarea == 1)\n\t  BuildFieldLinesFromFile(startpoints);\n\telse if(fieldlines_startarea == 2)\n\t  BuildFieldLinesFromFace(startpoints);\n\n\n\t    \n\tdouble phi;\n\t\n\tif(vsol -> iscomplex)\n\t  {\n\t    if(fieldlines_fixedphase)\n\t      phi = fieldlines_phase;\n\t    else\n\t      phi = 2*M_PI*ln / num_fieldlineslists;\n\t  }\n\telse\n\t  phi = 0;\n\n\tcout << \"phi = \" << phi << endl;\n\n\tphaser = cos(phi);\n        phasei = sin(phi);\n\t\n\n\tlinecalc.GenerateFieldLines(startpoints,num_fieldlines / num_fieldlineslists+1);\n\n        auto & pstart = linecalc.GetPStart();\n        auto & pend = linecalc.GetPEnd();\n        auto & values = linecalc.GetValues();\n        auto nlines = values.Size();\n\n        glNewList(fieldlineslist+ln, GL_COMPILE);\n        SetTextureMode (usetexture);\n\n        for(auto i : Range(nlines))\n          {\n            SetOpenGlColor  (values[i]);\n            DrawCylinder (pstart[i], pend[i], fieldlines_relthickness);\n          }\n\n        glEndList ();\n      }\n  }\n\n\n\n  \n}\n\n\n#endif // NOTCL\n"
  },
  {
    "path": "libsrc/visualization/vsmesh.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include \"../meshing/global.hpp\"\n// #include <csg.hpp>\n\n#ifdef STLGEOM\n#include <stlgeom.hpp>\n#endif\n\n\n// #include <parallel.hpp>\n\n#include <visual.hpp>\n\nnamespace netgen\n{\n  // extern shared_ptr<Mesh> mesh;\n  extern NetgenGeometry * ng_geometry;\n\n  VisualSceneMesh vsmesh;\n\n  VisualSceneMesh :: VisualSceneMesh ()\n    : VisualScene()\n  {\n    selface = -1;\n    selelement = -1;\n    locpi = -2;\n    selpoint = PointIndex::INVALID;\n    selpoint2 = PointIndex::INVALID;\n    seledge = -1;\n\n    minh = 0.0;\n    maxh = 0.0;\n    user_me_handler = NULL;\n    mesh = nullptr;\n  }\n\n  VisualSceneMesh :: ~VisualSceneMesh ()\n  {\n    ;\n  }\n\n\n  void VisualSceneMesh :: DrawScene ()\n  {\n    try\n      {\n        shared_ptr<Mesh> mesh = GetMesh();\n\n    if (!mesh)\n      {\n\tVisualScene::DrawScene();\n\treturn;\n      }\n\n    lock = NULL;\n\n    static int timer = NgProfiler::CreateTimer (\"VSMesh::DrawScene\");\n\n    NgProfiler::RegionTimer reg (timer);\n\n    BuildScene();\n\n    glEnable(GL_DEPTH_TEST);\n    glClearColor(backcolor, backcolor, backcolor, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glColor3f (1.0f, 1.0f, 1.0f);\n    glLineWidth (1.0f);\n\n    SetLight();\n\n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n    GLdouble projmat[16];                 // brauchen wir das ?\n    glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n\n\n    glEnable (GL_BLEND);\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n\n    glInitNames ();\n    glPushName (0);\n\n    //    glEnable (GL_LINE_SMOOTH);\n    //         glEnable (GL_BLEND);\n    //         glEnable (GL_POLYGON_SMOOTH);\n    //         glDisable (GL_DEPTH_TEST);\n    //         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n    //    glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);\n\n    glDisable (GL_COLOR_MATERIAL);\n\n    GLfloat matcol0[] = { 0, 0, 0, 1 };\n    GLfloat matcol1[] = { 1, 1, 1, 1 };\n    GLfloat matcolf[] = { 0, 1, 0, 1 };\n    GLfloat matcolb[] = { 0.5, 0, 0, 1 };\n    // GLfloat matcolblue[] = { 0, 0, 1, 1 };\n\n    glMatrixMode (GL_MODELVIEW);\n\n    glMaterialfv(GL_FRONT, GL_EMISSION, matcol0);\n    glMaterialfv(GL_BACK, GL_EMISSION, matcol0);\n    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol1);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcolf);\n    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, matcolb);\n\n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n    // glPolygonOffset (1,10);\n    glPolygonOffset (2,2);\n    glEnable (GL_POLYGON_OFFSET_FILL);\n\n    SetClippingPlane ();\n\n    if (vispar.drawfilledtrigs)\n      {\n        BuildFilledList (false);\n\n\n#ifdef PARALLELGL\n\tif (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks)\n\t  glCallList (par_filledlists[vispar.drawtetsdomain]);\n\telse\n#endif\n\t  glCallList (filledlist);\n      }\n\n    if (vispar.drawbadels)\n      glCallList (badellist);\n\n    BitArray shownode(mesh->GetNP()+1);\n    if (vispar.clipping.enable)\n      {\n\tshownode.Clear();\n\tfor (PointIndex pi : mesh->Points().Range())\n\t  {\n            Point<3> p = (*mesh)[pi];\n\n            double val =\n\t      p[0] * clipplane[0] +\n\t      p[1] * clipplane[1] +\n\t      p[2] * clipplane[2] +\n\t      clipplane[3];\n\n            if (val > 0) shownode.SetBit (pi);\n\t  }\n      }\n    else\n      shownode.Set();\n    if (vispar.drawprisms)\n      {\n\tBuildPrismList (shownode);\n\tglCallList (prismlist);\n      }\n\n    if (vispar.drawpyramids)\n      {\n\tBuildPyramidList (shownode);\n\tglCallList (pyramidlist);\n      }\n\n    if (vispar.drawhexes)\n      {\n\tBuildHexList (shownode);\n\tglCallList (hexlist);\n      }\n\n    if (vispar.drawtets)\n      {\n\tBuildTetList (shownode);\n\tglCallList (tetlist);\n      }\n\n    if (vispar.drawdomainsurf)\n      {\n\tBuildDomainSurfList();\n\tglCallList (domainsurflist);\n      }\n\n    glDisable (GL_POLYGON_OFFSET_FILL);\n\n    // draw lines\n\n    glMatrixMode (GL_MODELVIEW);\n\n    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol0);\n    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matcol0);\n    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol0);\n\n    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n    glLineWidth (1.0f);\n    glColor3f (0.0f, 0.0f, 0.0f);\n    glDisable (GL_LINE_SMOOTH);\n\n    glDisable(GL_BLEND);\n\n\n    if (vispar.drawoutline)\n      {\n\tglPolygonOffset (1, 1);\n\tglEnable (GL_POLYGON_OFFSET_LINE);\n\n        BuildLineList ();\n\n#ifdef PARALLELGL\n\tif (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks)\n\t  glCallList (par_linelists[vispar.drawtetsdomain]);\n\telse\n#endif\n\t  glCallList (linelist);\n\n\n\tglDisable (GL_POLYGON_OFFSET_LINE);\n      }\n\n    if (vispar.drawidentified)\n      {\n\tglPolygonOffset (1, -1);\n\tglEnable (GL_POLYGON_OFFSET_LINE);\n\tglCallList (identifiedlist);\n\tglDisable (GL_POLYGON_OFFSET_LINE);\n      }\n\n    if (vispar.drawpointnumbers ||\n\tvispar.drawedgenumbers ||\n\tvispar.drawfacenumbers ||\n        vispar.drawsegmentnumbers ||\n        vispar.drawsurfaceelementnumbers ||\n\tvispar.drawelementnumbers)\n      glCallList (pointnumberlist);\n\n\n    glPopName();\n\n    if (vispar.drawedges)\n      {\n\tBuildEdgeList();\n\tglCallList (edgelist);\n      }\n\n    DrawMarker();\n\n    glDisable(GL_CLIP_PLANE0);\n\n    glPopMatrix();\n\n    if (vispar.colormeshsize)\n      DrawColorBar (minh, maxh, 1);\n\n    DrawCoordinateCross ();\n    DrawNetgenLogo ();\n\n\n    if (lock)\n      {\n\tlock -> UnLock();\n\tdelete lock;\n\tlock = NULL;\n      }\n    \n    glFinish();\n\n    \n      }\n    catch (const bad_weak_ptr & e)\n      {\n        // cout << \"don't have a mesh to visualize\" << endl;\n        VisualScene::DrawScene();      \n      }\n\n  }\n\n  void VisualSceneMesh :: SelectCenter (int zoomall)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    Point3d pmin, pmax;\n    mesh->GetBox (pmin, pmax, -1);\n\n    // works in NGSolve, mesh view\n    if (mesh->GetDimension() == 2)\n      mesh->GetBox (pmin, pmax);\n    else // otherwise strange zooms during mesh generation\n      mesh->GetBox (pmin, pmax, SURFACEPOINT);\n\n    if (vispar.use_center_coords && zoomall==2)\n    {\n      center.X() = vispar.centerx;\n      center.Y() = vispar.centery;\n      center.Z() = vispar.centerz;\n    }\n    else if (selpoint-IndexBASE<PointIndex>() >= 1 && zoomall==2)\n      center = mesh->Point (selpoint);\n    else if (marker && zoomall==2)\n      center = *marker;\n    else if (vispar.centerpoint-IndexBASE<PointIndex>() >= 0 && zoomall==2)\n      center = mesh->Point (vispar.centerpoint);\n    else\n      center = Center (pmin, pmax);\n\n    double oldrad = rad;\n    rad = 0.5 * Dist (pmin, pmax);\n    if(rad == 0) rad = 1e-6;\n\n    if (rad > 1.2 * oldrad ||\n        mesh->GetMajorTimeStamp() > vstimestamp ||\n        zoomall)\n    {\n      CalcTransformationMatrices();\n    }\n\n    glEnable (GL_NORMALIZE);\n\n  }\n\n  void VisualSceneMesh :: BuildScene (int zoomall)\n  {\n        auto mesh = GetGlobalMesh();\n        \n        if (!mesh)\n      {\n        PrintMessage (3, \"vsmesh::buildscene: don't have a mesh to visualize\");\n\tVisualScene::BuildScene (zoomall);\n\treturn;\n      }\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    static int timer = NgProfiler::CreateTimer (\"VSMesh::BuildScene\");\n    NgProfiler::RegionTimer reg (timer);\n\n\n\n    NgArray<Element2d> faces;\n\n    int meshtimestamp = mesh->GetTimeStamp();\n    if (meshtimestamp > vstimestamp || zoomall)\n        SelectCenter(zoomall);\n\n    if (pointnumberlist)\n      {\n\tglDeleteLists (pointnumberlist, 1);\n\tpointnumberlist = 0;\n      }\n\n    if (badellist)\n      {\n\tglDeleteLists (badellist, 1);\n\tbadellist = 0;\n      }\n    /*\n      if (prismlist)\n      {\n      glDeleteLists (prismlist, 1);\n      prismlist = 0;\n      }\n\n      if (pyramidlist)\n      {\n      glDeleteLists (pyramidlist, 1);\n      pyramidlist = 0;\n      }\n\n      if (hexlist)\n      {\n      glDeleteLists (hexlist, 1);\n      hexlist = 0;\n      }\n    */\n    if (identifiedlist)\n      {\n\tglDeleteLists (identifiedlist, 1);\n\tidentifiedlist = 0;\n      }\n\n    pointnumberlist = glGenLists (1);\n    glNewList (pointnumberlist, GL_COMPILE);\n\n    if (vispar.drawpointnumbers ||\n\tvispar.drawedgenumbers ||\n\tvispar.drawfacenumbers ||\n        vispar.drawsegmentnumbers ||\n        vispar.drawsurfaceelementnumbers ||\n\tvispar.drawelementnumbers)\n      {\n\t//     \tglEnable (GL_COLOR_MATERIAL);\n\tGLfloat textcol[3] = { float(1-backcolor),\n                               float(1-backcolor),\n                               float(1-backcolor) };\n\tglColor3fv (textcol);\n\tglNormal3d (0, 0, 1);\n\tglPushAttrib (GL_LIST_BIT);\n\t// glListBase (fontbase);\n\n\tchar buf[30];\n\n\tif (vispar.drawpointnumbers)\n\t  for (PointIndex pi : mesh->Points().Range())\n            {\n\t      const Point3d & p = mesh->Point(pi);\n\t      glRasterPos3d (p.X(), p.Y(), p.Z());\n\n\t      snprintf (buf, size(buf),  \"%d\", int(pi));\n\n\t      // glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf);\n\t      MyOpenGLText (buf);\n            }\n\n\tif (vispar.drawedgenumbers)\n\t  {\n\t    /*\n\t      for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++)\n\t      {\n\t      const Segment & seg = (*mesh)[i];\n\n\t      const Point3d & p1 = mesh->Point(seg[0]);\n\t      const Point3d & p2 = mesh->Point(seg[1]);\n\t      const Point3d p = Center (p1, p2);\n\t      glRasterPos3d (p.X(), p.Y(), p.Z());\n\n\t      snprintf (buf, size(buf),  \"%d\", seg.edgenr);\n\t      glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf);\n\t      }\n\t    */\n\n\t    const MeshTopology & top = mesh->GetTopology();\n\t    for (int i = 1; i <= top.GetNEdges(); i++)\n\t      {\n\t\t// int v1, v2;\n\t\t// top.GetEdgeVertices (i, v1, v2);\n                auto [v1,v2] = top.GetEdgeVertices(i-1);\n\t\tconst Point3d & p1 = mesh->Point(v1);\n\t\tconst Point3d & p2 = mesh->Point(v2);\n\t\tconst Point3d p = Center (p1, p2);\n\t\tglRasterPos3d (p.X(), p.Y(), p.Z());\n\n\t\tsnprintf (buf, size(buf),  \"%d\", i);\n\t\t// glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf);\n\t\tMyOpenGLText (buf);\n\n\t      }\n\n\t  }\n\n          if (vispar.drawsegmentnumbers)\n            {\n              for (auto si : Range(mesh->LineSegments())) {\n                const auto& seg = (*mesh)[si];\n                Point<3> c = Center((*mesh)[seg[0]], (*mesh)[seg[1]]);\n\t\tglRasterPos3d (c[0], c[1], c[2]);\n\t\tsnprintf (buf, size(buf),  \"%d\", int(si));\n\t\tMyOpenGLText (buf);\n              }\n            }\n\n          if (vispar.drawfacenumbers)\n\t  {\n\t    const MeshTopology & top = mesh->GetTopology();\n\t    NgArray<int> v;\n\t    for (int i = 1; i <= top.GetNFaces(); i++)\n\t      {\n\t\ttop.GetFaceVertices (i, v);\n\t\tconst Point3d & p1 = mesh->Point(v.Elem(1));\n\t\tconst Point3d & p2 = mesh->Point(v.Elem(2));\n\t\tconst Point3d & p3 = mesh->Point(v.Elem(3));\n\t\tPoint3d p;\n\t\tif (v.Size() == 3)\n                  {\n\t\t    p = Center (p1, p2, p3);\n                  }\n\t\telse\n                  {\n\t\t    const Point3d & p4 = mesh->Point(v.Elem(4));\n\t\t    Point3d hp1 = Center (p1, p2);\n\t\t    Point3d hp2 = Center (p3, p4);\n\t\t    p = Center (hp1, hp2);\n                  }\n\n\t\tglRasterPos3d (p.X(), p.Y(), p.Z());\n\t\tsnprintf (buf, size(buf),  \"%d\", i);\n\t\t// glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf);\n\t\tMyOpenGLText (buf);\n\t      }\n\t  }\n\n          if (vispar.drawsurfaceelementnumbers)\n            {\n              for (auto sei : Range(mesh->SurfaceElements()))\n                {\n                  const auto & sel = (*mesh)[sei];\n                  Point<3> c;\n                  if(sel.GetNV() == 3)\n                    c = Center((*mesh)[sel[0]],\n                               (*mesh)[sel[1]],\n                               (*mesh)[sel[2]]);\n                  else\n                    c = Center((*mesh)[sel[0]],\n                               (*mesh)[sel[1]],\n                               (*mesh)[sel[2]],\n                               (*mesh)[sel[3]]);\n                  glRasterPos3d (c[0], c[1], c[2]);\n                  snprintf (buf, size(buf),  \"%d\", int(sei));\n                  MyOpenGLText (buf);\n                }\n            }\n\n        if (vispar.drawelementnumbers)\n\t  {\n\t    NgArray<int> v;\n\t    // for (int i = 1; i <= mesh->GetNE(); i++)\n            for (ElementIndex ei : Range(mesh->VolumeElements()))\n\t      {\n\t\t// const ELEMENTTYPE & eltype = mesh->ElementType(i);\n\t\tNgArray<int> pnums;\n\n\t\tPoint3d p;\n\t\tconst Element & el = mesh->VolumeElement (ei);\n\n\t\tif ( ! el.PNum(5)) //  eltype == TET )\n                  {\n\n\t\t    pnums.SetSize(4);\n\t\t    for( int j = 0; j < pnums.Size(); j++)\n\t\t      pnums[j] = mesh->VolumeElement(ei).PNum(j+1);\n\n\n\t\t    const Point3d & p1 = mesh->Point(pnums[0]);\n\t\t    const Point3d & p2 = mesh->Point(pnums[1]);\n\t\t    const Point3d & p3 = mesh->Point(pnums[2]);\n\t\t    const Point3d & p4 = mesh->Point(pnums[3]);\n\t\t    p = Center (p1, p2, p3, p4);\n                  }\n\t\telse if ( ! el.PNum(6)) // eltype == PYRAMID\n                  {\n\t\t    pnums.SetSize(5);\n\t\t    for( int j = 0; j < pnums.Size(); j++)\n\t\t      pnums[j] = mesh->VolumeElement(ei).PNum(j+1);\n\n\n\t\t    const Point3d & p1 = mesh->Point(pnums[0]);\n\t\t    const Point3d & p2 = mesh->Point(pnums[1]);\n\t\t    const Point3d & p3 = mesh->Point(pnums[2]);\n\t\t    const Point3d & p4 = mesh->Point(pnums[3]);\n\t\t    const Point3d & p5 = mesh->Point(pnums[4]);\n\n\t\t    p.X()  = 0.3 * p5.X() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . X();\n\t\t    p.Y()  = 0.3 * p5.Y() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . Y();\n\t\t    p.Z()  = 0.3 * p5.Z() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . Z();\n\n                  }\n\t\telse if ( ! el.PNum(7) ) // eltype == PRISM\n                  {\n\t\t    pnums.SetSize(6);\n\t\t    for( int j = 0; j < pnums.Size(); j++)\n\t\t      pnums[j] = mesh->VolumeElement(ei).PNum(j+1);\n\n\t\t    const Point3d & p1 = mesh->Point(pnums[0]);\n\t\t    const Point3d & p2 = mesh->Point(pnums[1]);\n\t\t    const Point3d & p3 = mesh->Point(pnums[2]);\n\t\t    const Point3d & p11 = mesh->Point(pnums[3]);\n\t\t    const Point3d & p12 = mesh->Point(pnums[4]);\n\t\t    const Point3d & p13 = mesh->Point(pnums[5]);\n\t\t    p = Center (  Center (p1, p2, p3) , Center(p11, p12, p13) )  ;\n\n                  }\n\t\telse if (! el.PNum(9) ) // eltype == HEX\n                  {\n\t\t    pnums.SetSize(8);\n\t\t    for( int j = 0; j < pnums.Size(); j++)\n\t\t      pnums[j] = mesh->VolumeElement(ei).PNum(j+1);\n\n\t\t    const Point3d & p1 = mesh->Point(pnums[0]);\n\t\t    const Point3d & p2 = mesh->Point(pnums[1]);\n\t\t    const Point3d & p3 = mesh->Point(pnums[2]);\n\t\t    const Point3d & p4 = mesh->Point(pnums[3]);\n\t\t    const Point3d & p5 = mesh->Point(pnums[4]);\n\t\t    const Point3d & p6 = mesh->Point(pnums[5]);\n\t\t    const Point3d & p7 = mesh->Point(pnums[6]);\n\t\t    const Point3d & p8 = mesh->Point(pnums[7]);\n\n\t\t    p = Center ( Center ( Center(p1, p3), Center(p2, p4) ) , Center( Center(p5, p7) , Center(p6, p8 ) ) );\n                  }\n\n\t\tglRasterPos3d (p.X(), p.Y(), p.Z());\n\t\tsnprintf (buf, size(buf),  \"%d\", ei-IndexBASE(ei));\n\t\t// glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf);\n\t\tMyOpenGLText (buf);\n\n\t      }\n\t  }\n\n\n\tglPopAttrib ();\n\t//      \tglDisable (GL_COLOR_MATERIAL);\n      }\n    glEndList ();\n\n\n\n\n\n\n    badellist = glGenLists (1);\n    glNewList (badellist, GL_COMPILE);\n\n    if (vispar.drawbadels)\n      {\n\t//  SetClippingPlane ();\n\n\tstatic float badelcol[] = { 1.0f, 0.0f, 1.0f, 1.0f };\n\tglLineWidth (1.0f);\n\n\t//for (int i = 1; i <= mesh->GetNE(); i++)\n        for (ElementIndex ei : Range(mesh->VolumeElements()))\n\t  {\n            if (mesh->VolumeElement(ei).Flags().badel ||\n\t\tmesh->VolumeElement(ei).Flags().illegal ||\n\t\t(ei-IndexBASE(ei) == vispar.drawelement))\n\t      {\n\t\t// copy to be thread-safe\n\t\tElement el = mesh->VolumeElement (ei);\n\t\tel.GetSurfaceTriangles (faces);\n\n\t\tglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, badelcol);\n\n\n\t\t//\t  if ( (el.GetNP() == 4) || (el.GetNP() == 10))\n\t\tif (el.PNum(1))\n\t\t  {\n\t\t    glBegin (GL_TRIANGLES);\n\n\t\t    for (int j = 1; j <= faces.Size(); j++)\n\t\t      {\n\t\t\tElement2d & face = faces.Elem(j);\n\t\t\tconst Point3d & lp1 = mesh->Point (el.PNum(face.PNum(1)));\n\t\t\tconst Point3d & lp2 = mesh->Point (el.PNum(face.PNum(2)));\n\t\t\tconst Point3d & lp3 = mesh->Point (el.PNum(face.PNum(3)));\n\t\t\tVec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t\t\tn /= (n.Length()+1e-12);\n\t\t\tglNormal3d (n.X(), n.Y(), n.Z());\n\t\t\tglVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t\tglVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t\tglVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t\t      }\n\n\t\t    glEnd();\n\t\t  }\n\t      }\n\t  }\n\n\n\n\tfor (ElementIndex ei : mesh->VolumeElements().Range())\n\t  {\n            if ((*mesh)[ei].Flags().badel)\n\t      {\n\t\t// copy to be thread-safe\n\t\tElement el = (*mesh)[ei];\n\t\tif ( (el.GetNP() == 4) || (el.GetNP() == 10))\n\t\t  {\n\t\t    glBegin (GL_LINES);\n\t\t    glVertex3d (0,0,0);\n\t\t    const Point3d & p = mesh->Point(el.PNum(1));\n\t\t    glVertex3d (p.X(), p.Y(), p.Z());\n\t\t    glEnd();\n\t\t  }\n\t      }\n\t  }\n\n\n        for (ElementIndex ei : Range(mesh->VolumeElements()))\n\t  {\n            Element el = mesh->VolumeElement (ei);\n            int hascp = 0;\n            for (int j = 1; j <= el.GetNP(); j++)\n\t      if (el.PNum(j) == vispar.centerpoint)\n\t\thascp = 1;\n\n            if (hascp)\n\t      {\n\t\t(*testout) << \"draw el \" << ei << \" : \";\n\t\tfor (int j = 1; j <= el.GetNP(); j++)\n                  (*testout) << el.PNum(j) << \" \";\n\t\t(*testout) << endl;\n\n\t\tif (el.GetNP() == 4)\n\t\t  {\n\t\t    int et[6][2] =\n\t\t      { { 1, 2 },\n\t\t\t{ 1, 3 },\n\t\t\t{ 1, 4 },\n\t\t\t{ 2, 3 },\n\t\t\t{ 2, 4 },\n\t\t\t{ 3, 4 } } ;\n\n\t\t    for (int j = 0; j < 6; j++)\n\t\t      {\n\t\t\tglBegin (GL_LINES);\n\t\t\tconst Point3d & p1 = mesh->Point (el.PNum(et[j][0]));\n\t\t\tconst Point3d & p2 = mesh->Point (el.PNum(et[j][1]));\n\t\t\tglVertex3d (p1.X(), p1.Y(), p1.Z());\n\t\t\tglVertex3d (p2.X(), p2.Y(), p2.Z());\n\t\t\tglEnd ();\n\t\t      }\n\t\t  }\n\n\n\t\tif (el.GetNP() == 10)\n\t\t  {\n\t\t    int et[12][2] =\n\t\t      { { 1, 5 },\n\t\t\t{ 2, 5 },\n\t\t\t{ 1, 6 },\n\t\t\t{ 3, 6 },\n\t\t\t{ 1, 7 },\n\t\t\t{ 4, 7 },\n\t\t\t{ 2, 8 },\n\t\t\t{ 3, 8 },\n\t\t\t{ 2, 9 },\n\t\t\t{ 4, 9 },\n\t\t\t{ 3, 10 },\n\t\t\t{ 4, 10 } };\n\n\t\t    for (int j = 0; j < 12; j++)\n\t\t      {\n\t\t\tglBegin (GL_LINES);\n\t\t\tconst Point3d & p1 = mesh->Point (el.PNum(et[j][0]));\n\t\t\tconst Point3d & p2 = mesh->Point (el.PNum(et[j][1]));\n\t\t\tglVertex3d (p1.X(), p1.Y(), p1.Z());\n\t\t\tglVertex3d (p2.X(), p2.Y(), p2.Z());\n\t\t\tglEnd ();\n\t\t      }\n\t\t  }\n\t      }\n\t  }\n\n        for (SurfaceElementIndex sei : mesh->SurfaceElements().Range())\n\t  {\n            Element2d el = (*mesh)[sei]; // copy to be thread-safe\n            if (!el.BadElement())\n\t      continue;\n\n            if (el.IsDeleted()) continue;\n            \n            bool drawel = true;\n            for (int j = 1; j <= el.GetNP(); j++)\n\t      if (!el.PNum(j).IsValid())\n\t\tdrawel = false;\n\n            if (!drawel)\n\t      continue;\n\n            // cout << int (el.GetType()) << \" \" << flush;\n            switch (el.GetType())\n\t      {\n\t      case TRIG:\n\t\t{\n                  glBegin (GL_TRIANGLES);\n\n                  Point3d lp1 = mesh->Point (el.PNum(1));\n                  Point3d lp2 = mesh->Point (el.PNum(2));\n                  Point3d lp3 = mesh->Point (el.PNum(3));\n                  Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n                  n /= (n.Length() + 1e-12);\n                  glNormal3dv (&n.X());\n                  glVertex3dv (&lp1.X());\n                  glVertex3dv (&lp2.X());\n                  glVertex3dv (&lp3.X());\n                  glEnd();\n                  break;\n\t\t}\n\t      case QUAD:\n\t\t{\n                  glBegin (GL_QUADS);\n\n                  const Point3d & lp1 = mesh->Point (el.PNum(1));\n                  const Point3d & lp2 = mesh->Point (el.PNum(2));\n                  const Point3d & lp3 = mesh->Point (el.PNum(4));\n                  const Point3d & lp4 = mesh->Point (el.PNum(3));\n                  Vec3d n = Cross (Vec3d (lp1, lp2),\n\t\t\t\t   Vec3d (lp1, Center (lp3, lp4)));\n                  n /= (n.Length() + 1e-12);\n                  glNormal3d (n.X(), n.Y(), n.Z());\n                  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n                  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n                  glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n                  glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n                  glEnd();\n                  break;\n\t\t}\n\t      case TRIG6:\n\t\t{\n                  int lines[6][2] = {\n\t\t    { 1, 6 }, { 2, 6 },\n\t\t    { 1, 5 }, { 3, 5 },\n\t\t    { 2, 4 }, { 3, 4 } };\n\n\t\t  glBegin (GL_LINES);\n\t\t  for (int j = 0; j < 6; j++)\n\t\t    {\n\t\t      glVertex3dv ( mesh->Point (el.PNum(lines[j][0])) );\n\t\t      glVertex3dv ( mesh->Point (el.PNum(lines[j][0])) );\n\t\t    }\n\t\t  glEnd();\n\t\t  break;\n\t\t}\n\n\t      case QUAD6:\n\t\t{\n                  int lines[6][2] = {\n\t\t    { 1, 5 }, { 2, 5 },\n\t\t    { 3, 6 }, { 4, 6 },\n\t\t    { 1, 4 }, { 2, 3 } };\n\n\t\t  glBegin (GL_LINES);\n\n\t\t  for (int j = 0; j < 6; j++)\n\t\t    {\n\t\t      const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0]));\n\t\t      const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1]));\n\n\t\t      glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t      glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t    }\n\t\t  glEnd ();\n\t\t  break;\n\t\t}\n\t      default:\n\t\tPrintSysError (\"Cannot draw surface element of type \",\n\t\t\t       int(el.GetType()));\n\t      }\n\t  }\n\tglLoadName (0);\n\n      }\n    glEndList ();\n\n\n    if (1)\n      {\n\n\tidentifiedlist = glGenLists (1);\n\tglNewList (identifiedlist, GL_COMPILE);\n\n\tGLfloat identifiedcol[] = { 1, 0, 1, 1 };\n\n\tglLineWidth (3);\n        glEnable (GL_COLOR_MATERIAL);\n        glDisable (GL_LIGHTING);\n\n\tif (mesh -> HasIdentifications() )\n\t  {\n\t      {\n                auto & idpts =\n                  mesh->GetIdentifications().GetIdentifiedPoints();\n                for (auto [hash, val] : idpts)\n                  {\n                    auto [hash_pts, hash_nr] = hash;\n                    auto [pi1, pi2] = hash_pts;\n                      // val = pts[2];   \n\t\t      Point<3> p1 = mesh->Point(pi1);\n\t\t      Point<3> p2 = mesh->Point(pi2);\n                      Point<3> c = Center(p1, p2);\n                      if (vispar.shrink < 1)\n                        {\n                          p1 = c + vispar.shrink * (p1 - c);\n                          p2 = c + vispar.shrink * (p2 - c);\n                        }\n\n                      glColor3fv (identifiedcol);\n\t\t      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,\n\t\t\t\t    identifiedcol);\n\n\t\t      glBegin (GL_LINES);\n\t\t      glVertex3dv(p1);\n\t\t      glVertex3dv(p2);\n\t\t      glEnd();\n\t\t    }\n\t      }\n\t  }\n\n        glDisable (GL_COLOR_MATERIAL);\n        glEnable (GL_LIGHTING);\n\tglEndList ();\n      }\n\n    if (lock)\n      {\n\tlock -> UnLock();\n\tdelete lock;\n\tlock = NULL;\n      }\n\n    vstimestamp = meshtimestamp;\n\n  }\n\n\n\n  void VisualSceneMesh :: BuildColorTexture ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if(colors.texture == -1)\n      glGenTextures(1, &colors.texture);\n\n    // build color texture\n    glBindTexture(GL_TEXTURE_2D, colors.texture);\n    Array<float> data;\n    for(auto fdi : Range(1, mesh->GetNFD()+1))\n    {\n      auto c = mesh->GetFaceDescriptor(fdi).SurfColour();\n      ArrayMem<float, 4> cf{float(c[0]), float(c[1]), float(c[2]), float(c[3])};\n      if(fdi==selface)\n        cf = {1.0f, 0.0f, 0.0f, 1.0f};\n      data.Append(cf);\n    }\n    int n = data.Size()/4;\n    colors.width = max2(1,min2(n, 1024));\n    colors.height = (n+colors.width-1)/colors.width;\n    for([[maybe_unused]] auto i: Range(n, colors.width*colors.height))\n      data.Append({0.0f, 0.0f, 0.0f, 0.0f});\n    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, colors.width, colors.height, 0, GL_RGBA, GL_FLOAT, data.Data());\n    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);\n  }\n\n  void RenderSurfaceElements (shared_ptr<Mesh> mesh,\n      int subdivisions,\n      std::function<bool(int)> face_init,\n      std::function<bool(SurfaceElementIndex)> sel_init\n    )\n  {\n    CurvedElements & curv = mesh->GetCurvedElements();\n\n    int hoplotn = 1 << subdivisions;\n    \n    Array<SurfaceElementIndex> seia;\n\n    for (int faceindex = 1; faceindex <= mesh->GetNFD(); faceindex++)\n      {\n        if(!face_init(faceindex-1))\n          continue;\n\n\tmesh->GetSurfaceElementsOfFace (faceindex, seia);\n\n        static Point<3> xa[129];\n        static Vec<3> na[129];\n        \n\tfor (int hi = 0; hi < seia.Size(); hi++)\n\t  {\n\t    SurfaceElementIndex sei = seia[hi];\n            const Element2d & el = (*mesh)[sei];\n\n            bool drawel = (!el.IsDeleted() && el.IsVisible());\n\n#ifdef STLGEOM\n            if (checkvicinity)\n\t      for (int j = 0; j < el.GetNP(); j++)\n\t\tif (!stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum))\n\t\t  drawel = 0;\n#endif\n\n            if (!drawel)\n\t      continue;\n\t    \n            if (!sel_init(sei))\n              continue;\n\n            switch (el.GetType())\n\t      {\n\t      case TRIG:\n\t\t{\n                  if (curv.IsHighOrder()) //  && curv.IsSurfaceElementCurved(sei))\n\t\t    {\n\t\t      if (hoplotn > 128) hoplotn = 128;\n\n\t\t      for (int i = 0; i < hoplotn; i++)\n\t\t\t{\n\t\t\t  glBegin (GL_TRIANGLE_STRIP);\n\n\t\t\t  for (int j = 0; j <= hoplotn-i; j++)\n\t\t\t    for (int k = 0; k < 2; k++)\n\t\t\t      {\n\t\t\t\tif (j == hoplotn-i && k == 1) continue;\n\n\t\t\t\tif (i > 0 && k == 0)\n\t\t\t\t  {\n\t\t\t\t    glNormal3dv (na[j]);\n\t\t\t\t    glVertex3dv (xa[j]);\n\t\t\t\t    continue;\n\t\t\t\t  }\n\n\t\t\t\tPoint<2> xref (double(j) / hoplotn, double(i+k) / hoplotn);\n\t\t\t\tPoint<3> xglob;\n\t\t\t\tMat<3,2> dxdxi;\n\t\t\t\tVec<3> dx, dy, n;\n\n\t\t\t\tcurv.CalcSurfaceTransformation (xref, sei, xglob, dxdxi);\n\t\t\t\tfor (int i = 0; i < 3; i++)\n\t\t\t\t  {\n\t\t\t\t    dx(i) = dxdxi(i,0);\n\t\t\t\t    dy(i) = dxdxi(i,1);\n\t\t\t\t  }\n\t\t\t\tn = Cross (dx, dy);\n\t\t\t\tglNormal3dv (n);\n\t\t\t\tglVertex3dv (xglob);\n\n\t\t\t\tif (k == 1)\n\t\t\t\t  {\n\t\t\t\t    na[j] = n;\n\t\t\t\t    xa[j] = xglob;\n\t\t\t\t  }\n\t\t\t      }\n\t\t\t  glEnd();\n\t\t\t}\n\t\t    }\n                  else // not high order\n\t\t    {\n\t\t      glBegin (GL_TRIANGLES);\n\t\t      \n\t\t      const Point<3> & lp0 = (*mesh) [el[0]];\n\t\t      const Point<3> & lp1 = (*mesh) [el[1]];\n\t\t      const Point<3> & lp2 = (*mesh) [el[2]];\n\n\t\t      Vec<3> n = Cross (lp1-lp0, lp2-lp0).Normalize();\n\t\t      glNormal3dv (n);\n\n\t\t      for (int j = 0; j < 3; j++)\n\t\t\t  glVertex3dv ( (*mesh)[el[j]] );\n\t\t      \n\t\t      glEnd();\n\t\t    }\n\t\t  \n                  break;\n\t\t}\n\t      case QUAD:\n\t\t{\n                  if (curv.IsHighOrder()) //  && curv.IsSurfaceElementCurved(sei))\n\t\t    {\n\t\t      Point<2> xr[4];\n\t\t      Point<3> xg;\n\t\t      Vec<3> dx, dy, n;\n\n\t\t      glBegin (GL_QUADS);\n\n\t\t      for (int i = 0; i < hoplotn; i++)\n                        for (int j = 0; j < hoplotn; j++)\n\t\t\t  {\n\t\t\t    xr[0](0) = (double)    i/hoplotn; xr[0](1) = (double)    j/hoplotn;\n\t\t\t    xr[1](0) = (double)(i+1)/hoplotn; xr[1](1) = (double)    j/hoplotn;\n\t\t\t    xr[2](0) = (double)(i+1)/hoplotn; xr[2](1) = (double)(j+1)/hoplotn;\n\t\t\t    xr[3](0) = (double)    i/hoplotn; xr[3](1) = (double)(j+1)/hoplotn;\n\n\t\t\t    for (int l=0; l<4; l++)\n\t\t\t      {\n\t\t\t\tMat<3,2> dxdxi;\n\n\t\t\t\tcurv.CalcSurfaceTransformation (xr[l], sei, xg, dxdxi);\n\t\t\t\tfor (int i = 0; i < 3; i++)\n\t\t\t\t  {\n\t\t\t\t    dx(i) = dxdxi(i,0);\n\t\t\t\t    dy(i) = dxdxi(i,1);\n\t\t\t\t  }\n\n\t\t\t\tn = Cross (dx, dy);\n\t\t\t\tn.Normalize();\n\t\t\t\tglNormal3d (n(0), n(1), n(2));\n\t\t\t\tglVertex3d (xg(0), xg(1), xg(2));\n\t\t\t      }\n\n\t\t\t  }\n\n\t\t      glEnd();\n\t\t    }\n\n                  else // not high order\n\n\t\t    {\n\t\t      glBegin (GL_QUADS);\n\n\t\t      const Point<3> & lp1 = mesh->Point (el.PNum(1));\n\t\t      const Point<3> & lp2 = mesh->Point (el.PNum(2));\n\t\t      const Point<3> & lp3 = mesh->Point (el.PNum(4));\n\t\t      const Point<3> & lp4 = mesh->Point (el.PNum(3));\n\n\t\t      Vec<3> n = Cross (lp2-lp1,  Center (lp3, lp4)-lp1);\n\t\t      n.Normalize();\n\t\t      glNormal3dv (n);\n\n\t\t      glVertex3dv (lp1);\n\t\t      glVertex3dv (lp2);\n\t\t      glVertex3dv (lp4);\n\t\t      glVertex3dv (lp3);\n\n\t\t      glEnd ();\n\t\t    }\n                  break;\n\t\t}\n\n\t      case TRIG6:\n\t\t{\n                  glBegin (GL_TRIANGLES);\n\n                  static int trigs[4][3] = {\n\t\t    { 1, 6, 5 },\n\t\t    { 2, 4, 6 },\n\t\t    { 3, 5, 4 },\n\t\t    { 4, 5, 6 } };\n\n\t\t  for (int j = 0; j < 4; j++)\n\t\t    {\n\t\t      const Point<3> & lp1 = mesh->Point (el.PNum(trigs[j][0]));\n\t\t      const Point<3> & lp2 = mesh->Point (el.PNum(trigs[j][1]));\n\t\t      const Point<3> & lp3 = mesh->Point (el.PNum(trigs[j][2]));\n\t\t      // Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t\t      Vec<3> n = Cross (lp2-lp1, lp3-lp1);\n\t\t      glNormal3dv (n);\n\n\t\t      glVertex3dv (lp1);\n\t\t      glVertex3dv (lp2);\n\t\t      glVertex3dv (lp3);\n\t\t    }\n\t\t  glEnd();\n\t\t  break;\n\t\t}\n\n\t      case QUAD6:\n\t\t{\n                  glBegin (GL_QUADS);\n                  static int quads[2][4] = {\n\t\t    { 1, 5, 6, 4 },\n\t\t    { 5, 2, 3, 6 } };\n\n\t\t  for (int j = 0; j < 2; j++)\n\t\t    {\n\t\t      Point3d lp1 = mesh->Point (el.PNum(quads[j][0]));\n\t\t      Point3d lp2 = mesh->Point (el.PNum(quads[j][1]));\n\t\t      Point3d lp3 = mesh->Point (el.PNum(quads[j][2]));\n\t\t      Point3d lp4 = mesh->Point (el.PNum(quads[j][3]));\n\t\t      Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t\t      n /= (n.Length() + 1e-12);\n\t\t      glNormal3dv (&n.X());\n\t\t      glVertex3dv (&lp1.X());\n\t\t      glVertex3dv (&lp2.X());\n\t\t      glVertex3dv (&lp3.X());\n\t\t      glVertex3dv (&lp4.X());\n\t\t    }\n\t\t  glEnd();\n\t\t  break;\n\t\t}\n\n\t      case QUAD8:\n\t\t{\n                  glBegin (GL_TRIANGLES);\n                  static int boundary[] =\n\t\t    { 1, 5, 2, 8, 3, 6, 4, 7, 1 };\n\n                  Point3d c(0,0,0);\n                  for (int j = 0; j < 4; j++)\n\t\t    {\n\t\t      const Point3d & hp = mesh->Point (el[j]);\n\t\t      c.X() -= 0.25 * hp.X();\n\t\t      c.Y() -= 0.25 * hp.Y();\n\t\t      c.Z() -= 0.25 * hp.Z();\n\t\t    }\n                  for (int j = 4; j < 8; j++)\n\t\t    {\n\t\t      const Point3d & hp = mesh->Point (el[j]);\n\t\t      c.X() += 0.5 * hp.X();\n\t\t      c.Y() += 0.5 * hp.Y();\n\t\t      c.Z() += 0.5 * hp.Z();\n\t\t    }\n\n                  for (int j = 0; j < 8; j++)\n\t\t    {\n\t\t      Point3d lp1 = mesh->Point (el.PNum(boundary[j]));\n\t\t      Point3d lp2 = mesh->Point (el.PNum(boundary[j+1]));\n\n\t\t      Vec3d n = Cross (Vec3d (c, lp1), Vec3d (c, lp2));\n\t\t      n /= (n.Length() + 1e-12);\n\t\t      glNormal3dv (&n.X());\n\t\t      glVertex3dv (&lp1.X());\n\t\t      glVertex3dv (&lp2.X());\n\t\t      glVertex3dv (&c.X());\n\t\t    }\n                  glEnd();\n                  break;\n\t\t}\n\n\n\t      default:\n\t\tPrintSysError (\"Cannot draw (2) surface element of type \",\n\t\t\t       int(el.GetType()));\n\t      }\n\t  }\n      }\n  }\n\n  void VisualSceneMesh :: BuildFilledList (bool build_select)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    \n    static int timer = NgProfiler::CreateTimer (\"Mesh::BuildFilledList\");\n    NgProfiler::RegionTimer reg (timer);\n    auto & list = build_select ? select.list : filledlist;\n    auto & timestamp = build_select ? select.list_timestamp : filledtimestamp;\n    if (list && timestamp > max(mesh->GetTimeStamp(), subdivision_timestamp))\n      return;\n\n\n#ifdef PARALLELGL\n    if (id == 0 && ntasks > 1)\n      {\n\tInitParallelGL();\n\tpar_filledlists.SetSize (ntasks);\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"filledlist\");\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  MyMPI_Recv (par_filledlists[dest], dest, MPI_TAG_VIS);\n\n\tif (list)\n\t  glDeleteLists (list, 1);\n\n\tlist = glGenLists (1);\n\tglNewList (list, GL_COMPILE);\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  glCallList (par_filledlists[dest]);\n\n\tglEndList();\n\n\ttimestamp = NextTimeStamp();\n\treturn;\n      }\n\n#endif\n\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    timestamp = NextTimeStamp();\n\n    if(!build_select && !vispar.colormeshsize)\n      BuildColorTexture();\n\n    if (list)\n      glDeleteLists (list, 1);\n\n    list = glGenLists (1);\n    glNewList (list, GL_COMPILE);\n\n    glBindTexture(GL_TEXTURE_2D, colors.texture);\n      \n#ifdef STLGEOM\n    STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry);\n    bool checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity;\n#endif\n    glEnable (GL_NORMALIZE);\n\n    glLineWidth (1.0f);\n\n    Vector locms;\n\n    if (vispar.colormeshsize)\n      {\n\tglEnable (GL_COLOR_MATERIAL);\n\tglShadeModel (GL_SMOOTH);\n\tlocms.SetSize (mesh->GetNP());\n\tmaxh = -1;\n\tminh = 1e99;\n\tfor (int i = 1; i <= locms.Size(); i++)\n\t  {\n            Point3d p = mesh->Point(i);\n            locms(i-1) = mesh->GetH (p);\n            if (locms(i-1) > maxh) maxh = locms(i-1);\n            if (locms(i-1) < minh) minh = locms(i-1);\n\t  }\n\tif (!locms.Size())\n\t  { \n            minh = 1; \n            maxh = 10; \n\t  }\n      }\n    else if (build_select)\n    {\n      glDisable(GL_TEXTURE_1D);\n      glDisable(GL_TEXTURE_2D);\n      glDisable(GL_FOG);\n      glDisable(GL_LIGHTING);\n      glDisable (GL_COLOR_MATERIAL);\n    }\n    else\n    {\n      glDisable(GL_TEXTURE_1D);\n      glEnable(GL_TEXTURE_2D);\n      glEnable (GL_COLOR_MATERIAL);\n      glBindTexture(GL_TEXTURE_2D, colors.texture);\n    }\n\n    // GLfloat matcol[] = { 0, 1, 0, 1 };\n    // GLfloat matcolsel[] = { 1, 0, 0, 1 };\n\n    GLint rendermode;\n    glGetIntegerv (GL_RENDER_MODE, &rendermode);\n\n    auto face_init = [&](int i)\n      {\n        if(!build_select && !vispar.colormeshsize)\n        {\n          float x = (0.5+i%colors.width)/colors.width;\n          float y = (0.5+i/colors.width)/colors.height;\n          glTexCoord2f(x,y);\n        }\n        return true;\n      };\n\n    CurvedElements & curv = mesh->GetCurvedElements();\n\n    auto sel_init = [&](SurfaceElementIndex sei)\n      {\n        if (build_select)\n          {\n            GLushort r,g,b;\n            r = (sei+1) % (1<<16);\n            g = (sei+1) >> 16;\n            b = 0;\n            glColor3us(r,g,b);\n          }\n            \n        if (vispar.colormeshsize)\n        {\n          auto & el = (*mesh)[sei];\n          if(el.GetType() == TRIG && !curv.IsHighOrder()) {\n            if (vispar.colormeshsize)\n              SetOpenGlColor  (locms(el[0]-1), minh, maxh, 0);\n          }\n        }\n        return true;\n      };\n\n    RenderSurfaceElements(mesh, subdivisions, face_init, sel_init);\n\n    glLoadName (0);\n    glBindTexture(GL_TEXTURE_2D, 0);\n    glEndList ();\n\n\n#ifdef PARALLELGL\n    glFinish();\n    if (id > 0)\n      MyMPI_Send (list, 0, MPI_TAG_VIS);\n#endif\n    if(lock)\n      {\n        lock->UnLock();\n        delete lock;\n        lock = NULL;\n      }\n\n  }\n\n\n  void VisualSceneMesh :: BuildLineList()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    if (linetimestamp > max(mesh->GetTimeStamp (), subdivision_timestamp))\n      return;\n\n    static int timer = NgProfiler::CreateTimer (\"Mesh::BuildLineList\");\n    NgProfiler::RegionTimer reg (timer);\n\n#ifdef PARALLELGL\n\n    if (id == 0 && ntasks > 1)\n      {\n\tInitParallelGL();\n\n\tpar_linelists.SetSize (ntasks);\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"linelist\");\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  MyMPI_Recv (par_linelists[dest], dest, MPI_TAG_VIS);\n\n\tif (linelist)\n\t  glDeleteLists (linelist, 1);\n\n\tlinelist = glGenLists (1);\n\tglNewList (linelist, GL_COMPILE);\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  glCallList (par_linelists[dest]);\n\n\tglEndList();\n\n\n\tlinetimestamp = NextTimeStamp();\n\treturn;\n      }\n\n#endif\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    linetimestamp = NextTimeStamp();\n\n#ifdef STLGEOM\n    STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry);\n    bool checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity;\n#endif\n\n    if (linelist)\n      glDeleteLists (linelist, 1);\n\n    linelist = glGenLists (1);\n    glNewList (linelist, GL_COMPILE);\n\n    // cout << \"linelist = \" << linelist << endl;\n\n    glLineWidth (1.0f);\n\n\n    int hoplotn = 1 << subdivisions;\n\n    // PrintMessage (3, \"nse = \", mesh->GetNSE());\n    for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++)\n      {\n\tconst Element2d & el = (*mesh)[sei];\n\n\tbool drawel = (!el.IsDeleted() && el.IsVisible());\n\n#ifdef STLGEOM\n\tif (checkvicinity)\n\t  for (int j = 0; j < el.GetNP(); j++)\n\t    if (!stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum))\n\t      drawel = 0;\n#endif\n\n\tif (!drawel)\n\t  continue;\n\n\tswitch (el.GetType())\n\t  {\n\t  case TRIG:\n            {\n\t      CurvedElements & curv = mesh->GetCurvedElements();\n\t      if (curv.IsHighOrder()) //  && curv.IsSurfaceElementCurved(sei))\n\t\t{\n                  Point<3> xg;\n                  glBegin (GL_LINE_LOOP);\n                  for (int i = 0; i < hoplotn; i++)\n\t\t    {\n\t\t      Point<2> xr (double(i) / hoplotn, 0);\n\t\t      curv.CalcSurfaceTransformation (xr, sei, xg);\n\t\t      glVertex3dv (xg);\n\t\t    }\n                  for (int i = 0; i < hoplotn; i++)\n\t\t    {\n\t\t      Point<2> xr (double(hoplotn-i) / hoplotn, double(i)/hoplotn);\n\t\t      curv.CalcSurfaceTransformation (xr, sei, xg);\n\t\t      glVertex3dv (xg);\n\t\t    }\n                  for (int i = 0; i < hoplotn; i++)\n\t\t    {\n\t\t      Point<2> xr (0, double(hoplotn-i) / hoplotn);\n\t\t      curv.CalcSurfaceTransformation (xr, sei, xg);\n\t\t      glVertex3dv (xg);\n\t\t    }\n\n                  glEnd();\n\t\t}\n\t      else\n\t\t{\n                  glBegin (GL_TRIANGLES);\n\n\t\t  for (int j = 0; j < 3; j++)\n\t\t    glVertex3dv ( (*mesh) [el[j]] );\n\t\t  /*\n                  const Point<3> & lp0 = (*mesh) [el[0]];\n                  const Point<3> & lp1 = (*mesh) [el[1]];\n                  const Point<3> & lp2 = (*mesh) [el[2]];\n\n                  glVertex3dv (lp0);\n                  glVertex3dv (lp1);\n                  glVertex3dv (lp2);\n\t\t  */\n                  glEnd();\n\t\t}\n\n\t      break;\n\n            }\n\n\t  case QUAD:\n            {\n\t      CurvedElements & curv = mesh->GetCurvedElements();\n\t      if (curv.IsHighOrder()) //  && curv.IsSurfaceElementCurved(sei))\n\t\t{\n                  Point<2> xr;\n                  Point<3> xg;\n\n                  glBegin (GL_LINE_STRIP);\n\n                  for (int side = 0; side < 4; side++)\n\t\t    {\n\t\t      for (int i = 0; i <= hoplotn; i++)\n\t\t\t{\n\t\t\t  switch (side)\n\t\t\t    {\n\t\t\t    case 0:\n\t\t\t      xr(0) = (double) i/hoplotn;\n\t\t\t      xr(1) = 0.;\n\t\t\t      break;\n\t\t\t    case 1:\n\t\t\t      xr(0) = 1.;\n\t\t\t      xr(1) = (double) i/hoplotn;\n\t\t\t      break;\n\t\t\t    case 2:\n\t\t\t      xr(0) = (double) (hoplotn-i)/hoplotn;\n\t\t\t      xr(1) = 1.;\n\t\t\t      break;\n\t\t\t    case 3:\n\t\t\t      xr(0) = 0.;\n\t\t\t      xr(1) = (double) (hoplotn-i)/hoplotn;\n\t\t\t      break;\n\t\t\t    }\n\n\t\t\t  curv.CalcSurfaceTransformation (xr, sei, xg);\n\t\t\t  glVertex3d (xg(0), xg(1), xg(2));\n\n\t\t\t}\n\n\t\t    }\n                  glEnd();\n\n\t\t} else {\n\n\t\tglBegin (GL_QUADS);\n\n\t\tconst Point3d & lp1 = mesh->Point (el.PNum(1));\n\t\tconst Point3d & lp2 = mesh->Point (el.PNum(2));\n\t\tconst Point3d & lp3 = mesh->Point (el.PNum(4));\n\t\tconst Point3d & lp4 = mesh->Point (el.PNum(3));\n\t\tVec3d n = Cross (Vec3d (lp1, lp2),\n\t\t\t\t Vec3d (lp1, Center (lp3, lp4)));\n\t\tglNormal3d (n.X(), n.Y(), n.Z());\n\t\tglVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\tglVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\tglVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n\t\tglVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t\tglEnd();\n\n\t      }\n\n\t      break;\n\n            }\n\n\t  case TRIG6:\n            {\n\t      int lines[6][2] = {\n\t\t{ 1, 6 }, { 2, 6 },\n\t\t{ 1, 5 }, { 3, 5 },\n\t\t{ 2, 4 }, { 3, 4 } };\n\n\t      glBegin (GL_LINES);\n\t      for (int j = 0; j < 6; j++)\n\t\t{\n\t\t  const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0]));\n\t\t  const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1]));\n\n\t\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t}\n\n\t      glEnd();\n\t      break;\n            }\n\n\t  case QUAD6:\n            {\n\t      int lines[6][2] = {\n\t\t{ 1, 5 }, { 2, 5 },\n\t\t{ 3, 6 }, { 4, 6 },\n\t\t{ 1, 4 }, { 2, 3 } };\n\n\t      glBegin (GL_LINES);\n\n\t      for (int j = 0; j < 6; j++)\n\t\t{\n\t\t  const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0]));\n\t\t  const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1]));\n\n\t\t  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t}\n\t      glEnd ();\n\t      break;\n            }\n\n\t  case QUAD8:\n            {\n\t      int lines[8][2] = {\n\t\t{ 1, 5 }, { 2, 5 }, { 3, 6 }, { 4, 6 },\n\t\t{ 1, 7 }, { 4, 7 }, { 2, 8 }, { 3, 8 }\n\t      };\n\n\t      glBegin (GL_LINES);\n\n\t      for (int j = 0; j < 8; j++)\n\t\t{\n                  const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0]));\n                  const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1]));\n\n                  glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n                  glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t}\n\t      glEnd ();\n\t      break;\n            }\n\n\n\n\t  default:\n            PrintSysError (\"Cannot draw (4) surface element of type \",\n\t\t\t   int(el.GetType()));\n\t  }\n      }\n\n    glEndList ();\n\n\n#ifdef PARALLELGL\n    glFinish();\n    if (id > 0)\n      MyMPI_Send (linelist, 0, MPI_TAG_VIS);\n#endif\n  }\n\n\n\n  void VisualSceneMesh :: BuildEdgeList()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    if (edgetimestamp > max(mesh->GetTimeStamp(), subdivision_timestamp) && vispar.drawtetsdomain == 0\n\t&& vispar.shrink == 1)\n      return;\n\n    edgetimestamp = NextTimeStamp();\n\n    if (edgelist)\n      glDeleteLists (edgelist, 1);\n\n    edgelist = glGenLists (1);\n    glNewList (edgelist, GL_COMPILE);\n\n\n    GLfloat matcoledge[] = { 0, 0, 1, 1 };\n    GLfloat matcolsingedge[] = { 1, 0, 1, 1 };\n\n    glEnable (GL_POLYGON_OFFSET_LINE);\n    glPolygonOffset (1, -1);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glDisable (GL_LIGHTING);\n\n    for (int i = 1; i <= mesh->GetNSeg(); i++)\n      {\n\tconst Segment & seg = mesh->LineSegment(i);\n\n        /*\n#ifdef PARALLEL\n\tif (ntasks > 1 && \n\t    vispar.drawtetsdomain && \n\t    // (vispar.drawtetsdomain != seg.GetPartition())) continue;\n            (vispar.drawtetsdomain != mesh->seg_partition[i-1]) continue;\n#endif\n        */\n        \n\tconst Point3d & p1 = (*mesh)[seg[0]];\n\tconst Point3d & p2 = (*mesh)[seg[1]];\n\n\tif (seg.singedge_left || seg.singedge_right)\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,\n\t\t\tmatcolsingedge);\n\telse\n\t  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,\n\t\t\tmatcoledge);\n\n\tif (seg.singedge_left || seg.singedge_right)\n\t  glColor3fv (matcolsingedge);\n\telse\n\t  glColor3fv (matcoledge);\n\n\tif (seg.edgenr == seledge)\n\t  glLineWidth(5);\n\telse\n\t  glLineWidth(2);\n\n\tif (mesh->GetCurvedElements().IsHighOrder())\n\t  {\n            int hoplotn = 1 << subdivisions;\n            // mesh->GetCurvedElements().GetNVisualSubsecs();\n\n            Point<3> x;\n            glBegin (GL_LINE_STRIP);\n\n            for (int j = 0; j <= hoplotn; j++)\n\t      {\n\t\tmesh->GetCurvedElements().CalcSegmentTransformation ((double) j/hoplotn, i-1, x);\n\t\tglVertex3d (x(0), x(1), x(2));\n\t\t/*\n\t\t  cout << \"x = \" << x(0) << \", \" << x(1) << \", \" << x(2)\n\t\t  << \", norm = 1+\" << sqrt(x(0)*x(0)+x(1)*x(1))-1\n\t\t  << \", phi = \" << atan2(x(1), x(0))/M_PI << endl;\n\t\t*/\n\t      }\n\n            glEnd();\n\n\t  }\n\telse\n\t  {\n            glBegin (GL_LINES);\n            Point<3> hp1 = p1;\n            Point<3> hp2 = p2;\n            Point<3> c = Center(p1, p2);\n            if (vispar.shrink < 1)\n\t      {\n\t\thp1 = c + vispar.shrink * (hp1 - c);\n\t\thp2 = c + vispar.shrink * (hp2 - c);\n\t      }\n            glVertex3dv (hp1);\n            glVertex3dv (hp2); // p2.X(), p2.Y(), p2.Z());\n            glEnd();\n\t  }\n      }\n\n    glLineWidth (2);\n    glDisable (GL_POLYGON_OFFSET_LINE);\n\n    glDisable (GL_COLOR_MATERIAL);\n    glEnable (GL_LIGHTING);\n\n    glEndList();\n  }\n\n\n\n\n  void VisualSceneMesh :: BuildPointNumberList()\n  {\n    ;\n  }\n\n\n\n  // Bernstein Pol B_{n,i}(x) = n! / i! / (n-i)! (1-x)^{n-i} x^i\n  static inline double Bernstein (int n, int i, double x)\n  {\n    double val = 1;\n    for (int j = 1; j <= i; j++)\n      val *= x;\n    for (int j = 1; j <= n-i; j++)\n      val *= (1-x) * (j+i) / j;\n    return val;\n  }\n\n  void ToBernstein (int order, Point<3> * pts, int stride)\n  {\n    static DenseMatrix mat, inv;\n    static Vector vec1, vec2;\n\n    if (mat.Height () != order+1)\n      {\n\tmat.SetSize (order+1);\n\tinv.SetSize (order+1);\n\tvec1.SetSize (order+1);\n\tvec2.SetSize (order+1);\n\tfor (int i = 0; i <= order; i++)\n\t  {\n            double x = double(i) / order;\n            for (int j = 0; j <= order; j++)\n\t      mat(i,j) = Bernstein (order, j, x);\n\t  }\n\n\tCalcInverse (mat, inv);\n      }\n\n    for (int i = 0; i < 3; i++)\n      {\n\tfor (int j = 0; j <= order; j++)\n\t  vec1(j) = pts[j*stride](i);\n\n\tinv.Mult (vec1, vec2);\n\n\tfor (int j = 0; j <= order; j++)\n\t  pts[j*stride](i) = vec2(j);\n      }\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  void VisualSceneMesh :: BuildTetList(const BitArray & shownode)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (tettimestamp > mesh->GetTimeStamp () &&\n\ttettimestamp > vispar.clipping.timestamp )\n      return;\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    tettimestamp = NextTimeStamp();\n\n    if (tetlist)\n      glDeleteLists (tetlist, 1);\n\n\n    tetlist = glGenLists (1);\n    glNewList (tetlist, GL_COMPILE);\n\n\n    Vector locms;\n\n    // Philippose - 16/02/2010\n    // Add Mesh size based coloring of \n    // meshes also for the volume elements\n    if (vispar.colormeshsize)\n      {\n\tglEnable (GL_COLOR_MATERIAL);\n\tlocms.SetSize (mesh->GetNP());\n\tmaxh = -1;\n\tminh = 1e99;\n\tfor (int i = 1; i <= locms.Size(); i++)\n\t  {\n            Point3d p = mesh->Point(i);\n            locms(i-1) = mesh->GetH (p);\n            if (locms(i-1) > maxh) maxh = locms(i-1);\n            if (locms(i-1) < minh) minh = locms(i-1);\n\t  }\n\tif (!locms.Size())\n\t  { \n            minh = 1; \n            maxh = 10; \n\t  }\n      }\n    else\n      glDisable (GL_COLOR_MATERIAL);\n\n\n\n    NgArray<Element2d> faces;\n\n    static float tetcols[][4] =\n      {\n\t{ 1.0f, 1.0f, 0.0f, 1.0f },\n\t{ 1.0f, 0.0f, 0.0f, 1.0f },\n\t{ 0.0f, 1.0f, 0.0f, 1.0f },\n\t{ 0.0f, 0.0f, 1.0f, 1.0f }\n\t/*\n\t{ 1.0f, 1.0f, 0.0f, 0.3f },\n\t{ 1.0f, 0.0f, 0.0f, 0.3f },\n\t{ 0.0f, 1.0f, 0.0f, 0.3f },\n\t{ 0.0f, 0.0f, 1.0f, 0.3f }\n\t*/\n      };\n\n    CurvedElements & curv = mesh->GetCurvedElements();\n\n\n    if (!curv.IsHighOrder())\n      glShadeModel (GL_FLAT);\n    else\n      glShadeModel (GL_SMOOTH);\n\n    int hoplotn = max (2, 1 << subdivisions);\n\n\n\n    for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n      {\n\tif (vispar.drawtetsdomain > 0)\n\t  {\n            /*\n\t    int tetid = vispar.drawmetispartition ? \n              (*mesh)[ei].GetPartition() : (*mesh)[ei].GetIndex();\n            */\n            int tetid =  (*mesh)[ei].GetIndex();\n\t    if (vispar.drawtetsdomain != tetid) continue;\n\t  }\n\n\tconst Element & el = (*mesh)[ei];\n\n\tif ((el.GetType() == TET || el.GetType() == TET10) && !el.IsDeleted())\n\t  {\n            bool visible = true;\n            for (auto pi: el.PNums())\n              if (!shownode[pi])\n                visible = false;\n            if(!visible) continue;\n\n            int ind = el.GetIndex() % 4;\n\n            // if (vispar.drawmetispartition && el.GetPartition()!=-1)\n            // ind = el.GetPartition() % 4;\n\n\t    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcols[ind]);\n\n\n            if (curv.IsHighOrder()) //  && curv.IsElementCurved(ei))\n\t      {\n\t\tconst ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (TET);\n\t\tconst Point3d * vertices = MeshTopology :: GetVertices (TET);\n\n\t\t/*\n\t\t  Point<3> grid[11][11];\n\t\t  Point<3> fpts[3];\n\t\t  int order = vispar.subdivisions+1;\n\n\t\t  for (int trig = 0; trig < 4; trig++)\n\t\t  {\n\t\t  for (int j = 0; j < 3; j++)\n\t\t  fpts[j] = vertices[faces[trig][j]-1];\n\n\t\t  static Point<3> c(0.25, 0.25, 0.25);\n\t\t  if (vispar.shrink < 1)\n\t\t  for (int j = 0; j < 3; j++)\n\t\t  fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t  for (int ix = 0; ix <= order; ix++)\n\t\t  for (int iy = 0; iy <= order; iy++)\n\t\t  {\n\t\t  double lami[3] =\n\t\t  { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t  (  double(ix)/order) * (1-double(iy)/order),\n\t\t  double(iy)/order };\n\n\t\t  Point<3> xl;\n\t\t  for (int l = 0; l < 3; l++)\n\t\t  xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t  lami[2] * fpts[2](l);\n\n\t\t  curv.CalcElementTransformation (xl, i-1, grid[ix][iy]);\n\t\t  }\n\n\t\t  for (int j = 0; j <= order; j++)\n\t\t  ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t  for (int j = 0; j <= order; j++)\n\t\t  ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t  glMap2d(GL_MAP2_VERTEX_3,\n\t\t  0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t  0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t  &grid[0][0](0));\n\t\t  glEnable(GL_MAP2_VERTEX_3);\n\t\t  glEnable(GL_AUTO_NORMAL);\n\n\t\t  glMapGrid2f(8, 0.0, 0.999, 8, 0.0, 1.0);\n\t\t  glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t  glDisable (GL_AUTO_NORMAL);\n\t\t  glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\t\t*/\n\n\n\n\t\tint order = curv.GetOrder();\n\n\t\tNgArray<Point<3> > ploc ( (order+1)*(order+1) );\n\t\tNgArray<Point<3> > pglob ( (order+1)*(order+1) );\n\t\tPoint<3> fpts[3];\n\n\t\tfor (int trig = 0; trig < 4; trig++)\n\t\t  {\n\t\t    for (int j = 0; j < 3; j++)\n\t\t      fpts[j] = vertices[faces[trig][j]-1];\n\n\t\t    static Point<3> c(0.25, 0.25, 0.25);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 3; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0, ii = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++, ii++)\n\t\t\t{\n\t\t\t  double lami[3] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      double(iy)/order };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l);\n\n\t\t\t  ploc[ii] = xl;\n\t\t\t}\n\n\t\t    curv.CalcMultiPointElementTransformation (&ploc, ei, &pglob, 0);\n\n\t\t    Point<3> grid[11][11];\n\t\t    for (int ix = 0, ii = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++, ii++)\n\t\t\tgrid[ix][iy] = pglob[ii];\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(hoplotn, 0.0, 0.9999f, hoplotn, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, hoplotn, 0, hoplotn);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\t      }\n\n            else // Not High Order\n\n\t      {\n\t\tPoint<3> pts[4];\n\t\tfor (int j = 0; j < 4; j++)\n                  pts[j] = (*mesh)[el[j]];\n\n\t\tif (vispar.shrink < 1)\n\t\t  {\n\t\t    Point<3> c = Center (pts[0], pts[1], pts[2], pts[3]);\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      pts[j] = c + vispar.shrink * (pts[j]-c);\n\t\t  }\n\n\n\t\tVec<3> n;\n\n\n\t\t// Philippose - 16/02/2010\n\t\t// Add Mesh size based coloring of \n\t\t// meshes also for the volume elements\n\t\tif(vispar.colormeshsize)\n\t\t  {\n\t\t    glBegin (GL_TRIANGLE_STRIP);\n\t\t    n = Cross (pts[1]-pts[0], pts[2]-pts[0]);\n\t\t    glNormal3dv (n);\n\n\t\t    SetOpenGlColor (locms(el[0]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[0]);\n\n\t\t    SetOpenGlColor (locms(el[1]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[1]);\n\n\t\t    SetOpenGlColor (locms(el[2]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[2]);\n\n\t\t    n = Cross (pts[3]-pts[1], pts[2]-pts[1]);\n\t\t    glNormal3dv (n);\n\n\t\t    SetOpenGlColor (locms(el[3]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[3]);\n\n\t\t    n = Cross (pts[3]-pts[2], pts[0]-pts[2]);\n\t\t    glNormal3dv (n);\n\n\t\t    SetOpenGlColor (locms(el[0]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[0]);\n\n\t\t    n = Cross (pts[1]-pts[3], pts[0]-pts[3]);\n\t\t    glNormal3dv (n);\n\n\t\t    SetOpenGlColor (locms(el[1]-1), minh, maxh, 0);\n\t\t    glVertex3dv (pts[1]);\n\t\t    glEnd();\n\t\t  }\n\t\telse // Do not color mesh based on mesh size\n\t\t  {\n\t\t    GLubyte ind[4][3] = { { 0,1,2 }, { 3,1,0 },\n\t\t\t\t\t  { 1,3,2 }, { 2,3,0 } };\n\t\t    \n\t\t    glEnableClientState(GL_VERTEX_ARRAY);\n\t\t    glVertexPointer(3, GL_DOUBLE, 0, &pts[0](0));\n\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      { \n\t\t\tglNormal3dv (Cross (pts[ind[j][1]]-pts[ind[j][0]],\n\t\t\t\t\t    pts[ind[j][2]]-pts[ind[j][0]]));\n\n\t\t\tglDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &ind[j][0]);\n\t\t      }\n\t\t    glDisableClientState(GL_VERTEX_ARRAY);\n\n\t\t    /*\n\t\t    glBegin (GL_TRIANGLE_STRIP);\n\t\t    glNormal3dv (Cross (pts[1]-pts[0], pts[2]-pts[0]));\n\n\t\t    glVertex3dv (pts[0]);\n\t\t    glVertex3dv (pts[1]);\n\t\t    glVertex3dv (pts[2]);\n\n\t\t    glNormal3dv (Cross (pts[3]-pts[1], pts[2]-pts[1]));\n\t\t    glVertex3dv (pts[3]);\n\n\t\t    glNormal3dv (Cross (pts[3]-pts[2], pts[0]-pts[2]));\n\t\t    glVertex3dv (pts[0]);\n\n\t\t    glNormal3dv (Cross (pts[1]-pts[3], pts[0]-pts[3]));\n\t\t    glVertex3dv (pts[1]);\n\t\t    glEnd();\n\t\t    */\n\t\t  }\n\n\t      }\n\t  }\n      }\n\n    glEndList ();\n  }\n\n\n\n\n  void VisualSceneMesh :: BuildPrismList(const BitArray & shownode)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    \n    if (prismtimestamp > mesh->GetTimeStamp () &&\n\tprismtimestamp > vispar.clipping.timestamp )\n      return;\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    prismtimestamp = NextTimeStamp();\n\n\n\n    if (prismlist)\n      glDeleteLists (prismlist, 1);\n\n    prismlist = glGenLists (1);\n    glNewList (prismlist, GL_COMPILE);\n\n    static float prismcol[] = { 0.0f, 1.0f, 1.0f, 1.0f };\n    glLineWidth (1.0f);\n\n    NgArray<Element2d> faces;\n\n\n    glDisable (GL_COLOR_MATERIAL);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, prismcol);\n\n    for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n      {\n\tconst Element & el = (*mesh)[ei];\n\tif (el.GetType() == PRISM && !el.IsDeleted())\n\t  {\n            bool visible = true;\n            for (auto pi: el.PNums())\n              if (!shownode[pi])\n                visible = false;\n            if(!visible) continue;\n\n            int j;\n            int i = ei + 1;\n\n            CurvedElements & curv = mesh->GetCurvedElements();\n            if (curv.IsHighOrder()) //  && curv.IsElementCurved(ei))\n\t      {\n\t\tconst ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (PRISM);\n\t\tconst Point3d * vertices = MeshTopology :: GetVertices (PRISM);\n\n\t\tPoint<3> grid[11][11];\n\t\tPoint<3> fpts[4];\n\t\tint order = subdivisions+1;\n\n\t\tfor (int trig = 0; trig < 2; trig++)\n\t\t  {\n\t\t    for (int j = 0; j < 3; j++)\n\t\t      fpts[j] = vertices[faces[trig][j]-1];\n\n\t\t    static Point<3> c(1.0/3.0, 1.0/3.0, 0.5);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 3; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[3] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      double(iy)/order };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, i-1, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 0.999f, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\n\t\tfor (int quad = 2; quad < 5; quad++)\n\t\t  {\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      fpts[j] = vertices[faces[quad][j]-1];\n\n\t\t    static Point<3> c(1.0/3.0, 1.0/3.0, 0.5);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 4; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[4] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (  double(iy)/order),\n\t\t\t      (1-double(ix)/order) * (  double(iy)/order) };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) =\n\t\t\t      lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l) + lami[3] * fpts[3](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, ei, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\n\n\n\n\n\t\t/*\n\t\t  int hoplotn = 1 << subdivisions;\n\t\t  // int hoplotn = curv.GetNVisualSubsecs();\n\n\t\t  const Point3d * facepoint = MeshTopology :: GetVertices (TRIG);\n\t\t  const ELEMENT_FACE * elface = MeshTopology :: GetFaces(TRIG);\n\n\t\t  glBegin (GL_TRIANGLES);\n\n\t\t  for (int trig = 0; trig<2; trig++)\n\t\t  {\n\n\t\t  Vec<3> x0,x1,d0,d1;\n\t\t  x0 = facepoint[1] - facepoint[2];\n\t\t  x1 = facepoint[0] - facepoint[2];\n\t\t  x0.Normalize();\n\t\t  x1.Normalize();\n\t\t  if (trig == 1) swap (x0,x1);\n\n\t\t  Point<3> xr[3];\n\t\t  Point<3> xg;\n\t\t  Vec<3> dx, dy, dz, n;\n\n\t\t  for (int i1 = 0; i1 < hoplotn; i1++)\n\t\t  for (int j1 = 0; j1 < hoplotn-i1; j1++)\n\t\t  for (int k = 0; k < 2; k++)\n\t\t  {\n\t\t  if (k == 0)\n\t\t  {\n\t\t  xr[0](0) = (double)    i1/hoplotn; xr[0](1) = (double)    j1/hoplotn;\n\t\t  xr[1](0) = (double)(i1+1)/hoplotn; xr[1](1) = (double)    j1/hoplotn;\n\t\t  xr[2](0) = (double)    i1/hoplotn; xr[2](1) = (double)(j1+1)/hoplotn;\n\t\t  } else\n\t\t  {\n\t\t  if (j1 == hoplotn-i1-1) continue;\n\t\t  xr[0](0) = (double)(i1+1)/hoplotn; xr[0](1) = (double)    j1/hoplotn;\n\t\t  xr[1](0) = (double)(i1+1)/hoplotn; xr[1](1) = (double)(j1+1)/hoplotn;\n\t\t  xr[2](0) = (double)    i1/hoplotn; xr[2](1) = (double)(j1+1)/hoplotn;\n\t\t  };\n\n\t\t  for (int l=0; l<3; l++)\n\t\t  {\n\t\t  Mat<3,3> dxdxi;\n\t\t  xr[l](2) = (double) trig;\n\t\t  curv.CalcElementTransformation (xr[l], i-1, xg, dxdxi);\n\t\t  for (int i = 0; i < 3; i++)\n\t\t  {\n\t\t  dx(i) = dxdxi(i,0);\n\t\t  dy(i) = dxdxi(i,1);\n\t\t  dz(i) = dxdxi(i,2);\n\t\t  }\n\n\t\t  Vec<3> d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz;\n\t\t  Vec<3> d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz;\n\t\t  n = Cross (d1, d0);\n\t\t  glNormal3d (n(0), n(1), n(2));\n\t\t  glVertex3d (xg(0), xg(1), xg(2));\n\t\t  }\n\t\t  }\n\n\t\t  }\n\n\t\t  glEnd ();\n\n\t\t  glBegin (GL_QUADS);\n\n\t\t  for (int quad = 0; quad<3; quad++)\n\t\t  {\n\t\t  const Point3d * facepoint = MeshTopology :: GetVertices (PRISM);\n\n\t\t  Vec<3> x0,x1;\n\t\t  int xyz;\n\n\t\t  switch (quad)\n\t\t  {\n\t\t  case 0:\n\t\t  x0 = facepoint[5] - facepoint[2];\n\t\t  x1 = facepoint[0] - facepoint[2];\n\t\t  xyz = 0;\n\t\t  break;\n\t\t  case 1:\n\t\t  x0 = facepoint[4] - facepoint[0];\n\t\t  x1 = facepoint[1] - facepoint[0];\n\t\t  xyz = 0;\n\t\t  break;\n\t\t  case 2:\n\t\t  x0 = facepoint[1] - facepoint[2];\n\t\t  x1 = facepoint[5] - facepoint[2];\n\t\t  xyz = 1;\n\t\t  break;\n\t\t  }\n\n\t\t  x0.Normalize();\n\t\t  x1.Normalize();\n\n\t\t  swap (x0,x1);\n\n\t\t  Point<3> xr[4];\n\t\t  Point<3> xg;\n\t\t  Vec<3> dx, dy, dz, n;\n\n\t\t  for (int i1 = 0; i1 < hoplotn; i1++)\n\t\t  for (int j1 = 0; j1 < hoplotn; j1++)\n\t\t  {\n\t\t  xr[0](xyz) = (double)    i1/hoplotn; xr[0](2) = (double)    j1/hoplotn;\n\t\t  xr[1](xyz) = (double)(i1+1)/hoplotn; xr[1](2) = (double)    j1/hoplotn;\n\t\t  xr[2](xyz) = (double)(i1+1)/hoplotn; xr[2](2) = (double)(j1+1)/hoplotn;\n\t\t  xr[3](xyz) = (double)    i1/hoplotn; xr[3](2) = (double)(j1+1)/hoplotn;\n\n\t\t  for (int l=0; l<4; l++)\n\t\t  {\n\t\t  switch (quad)\n\t\t  {\n\t\t  case 0: xr[l](1) = 0; break;\n\t\t  case 1: xr[l](1) = 1-xr[l](0); break;\n\t\t  case 2: xr[l](0) = 0; break;\n\t\t  }\n\n\t\t  Mat<3,3> dxdxi;\n\t\t  curv.CalcElementTransformation (xr[l], i-1, xg, dxdxi);\n\t\t  for (int i = 0; i < 3; i++)\n\t\t  {\n\t\t  dx(i) = dxdxi(i,0);\n\t\t  dy(i) = dxdxi(i,1);\n\t\t  dz(i) = dxdxi(i,2);\n\t\t  }\n\n\t\t  Vec<3> d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz;\n\t\t  Vec<3> d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz;\n\t\t  n = Cross (d1, d0);\n\t\t  glNormal3d (n(0), n(1), n(2));\n\t\t  glVertex3d (xg(0), xg(1), xg(2));\n\t\t  }\n\t\t  }\n\t\t  }\n\t\t  glEnd ();\n\t\t*/\n\t      }\n            else\n\t      {\n\t\tPoint3d c(0,0,0);\n\t\tif (vispar.shrink < 1)\n\t\t  {\n\t\t    for (j = 1; j <= 6; j++)\n\t\t      {\n\t\t\tPoint3d p = mesh->Point(el.PNum(j));\n\t\t\tc.X() += p.X() / 6;\n\t\t\tc.Y() += p.Y() / 6;\n\t\t\tc.Z() += p.Z() / 6;\n\t\t      }\n\t\t  }\n\n\t\tel.GetSurfaceTriangles (faces);\n\t\tglBegin (GL_TRIANGLES);\n\t\tfor (j = 1; j <= faces.Size(); j++)\n\t\t  {\n\t\t    Element2d & face = faces.Elem(j);\n\t\t    Point3d lp1 = mesh->Point (el.PNum(face.PNum(1)));\n\t\t    Point3d lp2 = mesh->Point (el.PNum(face.PNum(2)));\n\t\t    Point3d lp3 = mesh->Point (el.PNum(face.PNum(3)));\n\t\t    Vec3d n = Cross (Vec3d (lp1, lp3), Vec3d (lp1, lp2));\n\t\t    n /= (n.Length()+1e-12);\n\t\t    glNormal3d (n.X(), n.Y(), n.Z());\n\t\t    if (vispar.shrink < 1)\n\t\t      {\n\t\t\tlp1 = c + vispar.shrink * (lp1 - c);\n\t\t\tlp2 = c + vispar.shrink * (lp2 - c);\n\t\t\tlp3 = c + vispar.shrink * (lp3 - c);\n\t\t      }\n\t\t    glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t    glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t    glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t\t  }\n\n\t\tglEnd();\n\t      }\n\t  }\n      }\n    glEndList ();\n  }\n\n\n\n\n  void VisualSceneMesh :: BuildHexList(const BitArray & shownode)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    \n    if (hextimestamp > mesh->GetTimeStamp () &&\n\thextimestamp > vispar.clipping.timestamp )\n      return;\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    hextimestamp = NextTimeStamp();\n\n    if (hexlist) glDeleteLists (hexlist, 1);\n\n    hexlist = glGenLists (1);\n    glNewList (hexlist, GL_COMPILE);\n\n\n    static float hexcol[] = { 1.0f, 1.0f, 0.0f, 1.0f };\n    glLineWidth (1.0f);\n    glDisable (GL_COLOR_MATERIAL);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, hexcol);\n\n    NgArray<Element2d> faces;\n    // int hoplotn = 1 << vispar.subdivisions;\n\n    for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n      {\n\tconst Element & el = (*mesh)[ei];\n\tif (el.GetType() == HEX && !el.IsDeleted())\n\t  {\n            bool visible = true;\n            for (auto pi: el.PNums())\n              if (!shownode[pi])\n                visible = false;\n            if(!visible) continue;\n            CurvedElements & curv = mesh->GetCurvedElements();\n            if (curv.IsHighOrder()) //  && curv.IsElementCurved(ei))\n\t      {\n\t\t/* // classical\n\t\t   glBegin (GL_QUADS);\n\n\t\t   const ELEMENT_FACE * faces = MeshTopology :: GetFaces (HEX);\n\t\t   const Point3d * vertices = MeshTopology :: GetVertices (HEX);\n\n\t\t   Point<3> grid[33][33];\n\t\t   Vec<3> gridn[33][33];\n\t\t   Point<3> fpts[4];\n\t\t   for (int quad = 0; quad<6; quad++)\n\t\t   {\n\t\t   for (int j = 0; j < 4; j++)\n\t\t   fpts[j] = vertices[faces[quad][j]-1];\n\n\t\t   static Point<3> c(0.5, 0.5, 0.5);\n\t\t   if (vispar.shrink < 1)\n\t\t   for (int j = 0; j < 4; j++)\n\t\t   fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t   Vec<3> taux = fpts[1]-fpts[0];\n\t\t   Vec<3> tauy = fpts[3]-fpts[0];\n\n\t\t   for (int ix = 0; ix <= hoplotn; ix++)\n\t\t   for (int iy = 0; iy <= hoplotn; iy++)\n\t\t   {\n\t\t   Point<3> xl;\n\t\t   Mat<3,3> dxdxi;\n\t\t   double lami[4] =\n\t\t   { (1-double(ix)/hoplotn) * (1-double(iy)/hoplotn),\n\t\t   (  double(ix)/hoplotn) * (1-double(iy)/hoplotn),\n\t\t   (  double(ix)/hoplotn) * (  double(iy)/hoplotn),\n\t\t   (1-double(ix)/hoplotn) * (  double(iy)/hoplotn) };\n\t\t   for (int l = 0; l < 3; l++)\n\t\t   xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t   lami[2] * fpts[2](l) + lami[3] * fpts[3](l);\n\n\t\t   curv.CalcElementTransformation (xl, ei, grid[ix][iy], dxdxi);\n\n\t\t   Vec<3> gtaux = dxdxi * taux;\n\t\t   Vec<3> gtauy = dxdxi * tauy;\n\t\t   gridn[ix][iy] = Cross (gtauy, gtaux).Normalize();\n\t\t   }\n\n\t\t   for (int ix = 0; ix < hoplotn; ix++)\n\t\t   for (int iy = 0; iy < hoplotn; iy++)\n\t\t   {\n\t\t   glNormal3dv (gridn[ix][iy]);\n\t\t   glVertex3dv (grid[ix][iy]);\n\n\t\t   glNormal3dv (gridn[ix+1][iy]);\n\t\t   glVertex3dv (grid[ix+1][iy]);\n\n\t\t   glNormal3dv (gridn[ix+1][iy+1]);\n\t\t   glVertex3dv (grid[ix+1][iy+1]);\n\n\t\t   glNormal3dv (gridn[ix][iy+1]);\n\t\t   glVertex3dv (grid[ix][iy+1]);\n\t\t   }\n\t\t   }\n\n\t\t   glEnd ();\n\t\t*/\n\n\t\tconst ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (HEX);\n\t\tconst Point3d * vertices = MeshTopology :: GetVertices (HEX);\n\n\t\tPoint<3> grid[11][11];\n\t\tPoint<3> fpts[4];\n\t\tint order = subdivisions+1;\n\n\t\tfor (int quad = 0; quad<6; quad++)\n\t\t  {\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      fpts[j] = vertices[faces[quad][j]-1];\n\n\t\t    static Point<3> c(0.5, 0.5, 0.5);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 4; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[4] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (  double(iy)/order),\n\t\t\t      (1-double(ix)/order) * (  double(iy)/order) };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l) + lami[3] * fpts[3](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, ei, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\t      }\n            else\n\t      {\n\t\tPoint3d c(0,0,0);\n\t\tif (vispar.shrink < 1)\n\t\t  {\n\t\t    for (int j = 1; j <= 8; j++)\n\t\t      {\n\t\t\tPoint3d p = mesh->Point(el.PNum(j));\n\t\t\tc.X() += p.X();\n\t\t\tc.Y() += p.Y();\n\t\t\tc.Z() += p.Z();\n\t\t      }\n\t\t    c.X() /= 8;\n\t\t    c.Y() /= 8;\n\t\t    c.Z() /= 8;\n\t\t  }\n\n\t\tglBegin (GL_TRIANGLES);\n\n\t\tel.GetSurfaceTriangles (faces);\n\t\tfor (int j = 1; j <= faces.Size(); j++)\n\t\t  {\n\t\t    Element2d & face = faces.Elem(j);\n\t\t    Point<3> lp1 = mesh->Point (el.PNum(face.PNum(1)));\n\t\t    Point<3> lp2 = mesh->Point (el.PNum(face.PNum(2)));\n\t\t    Point<3> lp3 = mesh->Point (el.PNum(face.PNum(3)));\n\t\t    Vec<3> n = Cross (lp3-lp1, lp2-lp1);\n\t\t    n.Normalize();\n\t\t    glNormal3dv (n);\n\n\t\t    if (vispar.shrink < 1)\n\t\t      {\n\t\t\tlp1 = c + vispar.shrink * (lp1 - c);\n\t\t\tlp2 = c + vispar.shrink * (lp2 - c);\n\t\t\tlp3 = c + vispar.shrink * (lp3 - c);\n\t\t      }\n\n\t\t    glVertex3dv (lp1);\n\t\t    glVertex3dv (lp2);\n\t\t    glVertex3dv (lp3);\n\t\t  }\n\n\t\tglEnd();\n\t      }\n\t  }\n      }\n\n    static float hex7col[] = { 1.0f, 0.65f, 0.0f, 1.0f };\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, hex7col);\n\n    for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n      {\n\tconst Element & el = (*mesh)[ei];\n\tif (el.GetType() == HEX7 && !el.IsDeleted())\n\t  {\n            /*\n            CurvedElements & curv = mesh->GetCurvedElements();\n            if (curv.IsHighOrder()) \n\t      {\n\t\tconst ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (HEX);\n\t\tconst Point3d * vertices = MeshTopology :: GetVertices (HEX);\n\n\t\tPoint<3> grid[11][11];\n\t\tPoint<3> fpts[4];\n\t\tint order = subdivisions+1;\n\n\t\tfor (int quad = 0; quad<6; quad++)\n\t\t  {\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      fpts[j] = vertices[faces[quad][j]-1];\n\n\t\t    static Point<3> c(0.5, 0.5, 0.5);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 4; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[4] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (  double(iy)/order),\n\t\t\t      (1-double(ix)/order) * (  double(iy)/order) };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l) + lami[3] * fpts[3](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, ei, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\t      }\n            else\n            */\n\t      {\n\t\tPoint3d c(0,0,0);\n\t\tif (vispar.shrink < 1)\n\t\t  {\n\t\t    for (int j = 1; j <= 7; j++)\n\t\t      {\n\t\t\tPoint3d p = mesh->Point(el.PNum(j));\n\t\t\tc.X() += p.X();\n\t\t\tc.Y() += p.Y();\n\t\t\tc.Z() += p.Z();\n\t\t      }\n\t\t    c.X() /= 7;\n\t\t    c.Y() /= 7;\n\t\t    c.Z() /= 7;\n\t\t  }\n\n\t\tglBegin (GL_TRIANGLES);\n\n\t\tel.GetSurfaceTriangles (faces);\n\t\tfor (int j = 1; j <= faces.Size(); j++)\n\t\t  {\n\t\t    Element2d & face = faces.Elem(j);\n\t\t    Point<3> lp1 = mesh->Point (el.PNum(face.PNum(1)));\n\t\t    Point<3> lp2 = mesh->Point (el.PNum(face.PNum(2)));\n\t\t    Point<3> lp3 = mesh->Point (el.PNum(face.PNum(3)));\n\t\t    Vec<3> n = Cross (lp3-lp1, lp2-lp1);\n\t\t    n.Normalize();\n\t\t    glNormal3dv (n);\n\n\t\t    if (vispar.shrink < 1)\n\t\t      {\n\t\t\tlp1 = c + vispar.shrink * (lp1 - c);\n\t\t\tlp2 = c + vispar.shrink * (lp2 - c);\n\t\t\tlp3 = c + vispar.shrink * (lp3 - c);\n\t\t      }\n\n\t\t    glVertex3dv (lp1);\n\t\t    glVertex3dv (lp2);\n\t\t    glVertex3dv (lp3);\n\t\t  }\n\n\t\tglEnd();\n\t      }\n\t  }\n      }\n\n    \n    glEndList ();\n  }\n\n\n\n\n\n\n\n\n\n  void VisualSceneMesh :: BuildPyramidList(const BitArray & shownode)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    \n    if (pyramidtimestamp > mesh->GetTimeStamp () &&\n\tpyramidtimestamp > vispar.clipping.timestamp )\n      return;\n\n    if (!lock)\n      {\n\tlock = new NgLock (mesh->Mutex());\n\tlock -> Lock();\n      }\n\n    pyramidtimestamp = NextTimeStamp();\n\n\n    if (pyramidlist)\n      glDeleteLists (pyramidlist, 1);\n\n\n    pyramidlist = glGenLists (1);\n    glNewList (pyramidlist, GL_COMPILE);\n\n    static float pyramidcol[] = { 1.0f, 0.0f, 1.0f, 1.0f };\n    glDisable (GL_COLOR_MATERIAL);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pyramidcol);\n\n    glLineWidth (1.0f);\n    NgArray<Element2d> faces;\n\n    for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n      {\n\tconst Element & el = (*mesh)[ei];\n\tif ((el.GetType() == PYRAMID || el.GetType() == PYRAMID13) && !el.IsDeleted())\n\t  {\n            bool visible = true;\n            for (auto pi: el.PNums())\n              if (!shownode[pi])\n                visible = false;\n            if(!visible) continue;\n\n            int i = ei + 1;\n\n            CurvedElements & curv = mesh->GetCurvedElements();\n            if (curv.IsHighOrder()) //  && curv.IsElementCurved(ei))\n\t      {\n\n\t\tconst ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (PYRAMID);\n\t\tconst Point3d * vertices = MeshTopology :: GetVertices (PYRAMID);\n\n\t\tPoint<3> grid[11][11];\n\t\tPoint<3> fpts[4];\n\t\tint order = subdivisions+1;\n\n\t\tfor (int trig = 0; trig < 4; trig++)\n\t\t  {\n\t\t    for (int j = 0; j < 3; j++)\n\t\t      fpts[j] = vertices[faces[trig][j]-1];\n\n\t\t    static Point<3> c(0.375, 0.375, 0.25);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 3; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[3] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      double(iy)/order };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, i-1, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 0.999f, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\n\t\tfor (int quad = 4; quad < 5; quad++)\n\t\t  {\n\t\t    for (int j = 0; j < 4; j++)\n\t\t      fpts[j] = vertices[faces[quad][j]-1];\n\n\t\t    static Point<3> c(0.375, 0.375, 0.25);\n\t\t    if (vispar.shrink < 1)\n\t\t      for (int j = 0; j < 4; j++)\n                        fpts[j] += (1-vispar.shrink) * (c-fpts[j]);\n\n\t\t    for (int ix = 0; ix <= order; ix++)\n\t\t      for (int iy = 0; iy <= order; iy++)\n\t\t\t{\n\t\t\t  double lami[4] =\n\t\t\t    { (1-double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (1-double(iy)/order),\n\t\t\t      (  double(ix)/order) * (  double(iy)/order),\n\t\t\t      (1-double(ix)/order) * (  double(iy)/order) };\n\n\t\t\t  Point<3> xl;\n\t\t\t  for (int l = 0; l < 3; l++)\n\t\t\t    xl(l) =\n\t\t\t      lami[0] * fpts[0](l) + lami[1] * fpts[1](l) +\n\t\t\t      lami[2] * fpts[2](l) + lami[3] * fpts[3](l);\n\n\t\t\t  curv.CalcElementTransformation (xl, ei, grid[ix][iy]);\n\t\t\t}\n\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]);\n\t\t    for (int j = 0; j <= order; j++)\n\t\t      ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]);\n\n\t\t    glMap2d(GL_MAP2_VERTEX_3,\n\t\t\t    0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1,\n\t\t\t    0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1,\n\t\t\t    &grid[0][0](0));\n\t\t    glEnable(GL_MAP2_VERTEX_3);\n\t\t    glEnable(GL_AUTO_NORMAL);\n\n\t\t    glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0);\n\t\t    glEvalMesh2(GL_FILL, 0, 8, 0, 8);\n\n\t\t    glDisable (GL_AUTO_NORMAL);\n\t\t    glDisable (GL_MAP2_VERTEX_3);\n\t\t  }\n\n\n\n\n\n\n\t\t/*\n\t\t  int hoplotn = 1 << vispar.subdivisions;\n\n\t\t  const ELEMENT_FACE * faces = MeshTopology :: GetFaces (PYRAMID);\n\t\t  const Point3d * vertices = MeshTopology :: GetVertices (PYRAMID);\n\n\t\t  Point<3> grid[33][33];\n\t\t  Vec<3> gridn[33][33];\n\n\n\t\t  glBegin (GL_TRIANGLES);\n\n\t\t  for (int trig = 0; trig < 4; trig++)\n\t\t  {\n\t\t  Point<3> p0 = vertices[faces[trig][0]-1];\n\t\t  Point<3> p1 = vertices[faces[trig][1]-1];\n\t\t  Point<3> p2 = vertices[faces[trig][2]-1];\n\n\t\t  if (vispar.shrink < 1)\n\t\t  {\n\t\t  static Point<3> c(0.375, 0.375, 0.25);\n\t\t  p0 = c + vispar.shrink * (p0 - c);\n\t\t  p1 = c + vispar.shrink * (p1 - c);\n\t\t  p2 = c + vispar.shrink * (p2 - c);\n\t\t  }\n\n\n\t\t  Vec<3> taux = p0-p2;\n\t\t  Vec<3> tauy = p1-p2;\n\t\t  Vec<3> gtaux, gtauy;\n\n\t\t  Point<3> xl;\n\t\t  Mat<3,3> dxdxi;\n\n\t\t  for (int ix = 0; ix <= hoplotn; ix++)\n\t\t  for (int iy = 0; iy <= hoplotn-ix; iy++)\n\t\t  {\n\t\t  for (int l = 0; l < 3; l++)\n\t\t  xl(l) =\n\t\t  (1-double(ix+iy)/hoplotn) * p2(l) +\n\t\t  (double(ix)/hoplotn) * p0(l) +\n\t\t  (double(iy)/hoplotn) * p1(l);\n\n\t\t  curv.CalcElementTransformation (xl, i-1, grid[ix][iy], dxdxi);\n\n\t\t  gtaux = dxdxi * taux;\n\t\t  gtauy = dxdxi * tauy;\n\t\t  gridn[ix][iy] = Cross (gtauy, gtaux).Normalize();\n\t\t  }\n\n\t\t  for (int ix = 0; ix < hoplotn; ix++)\n\t\t  for (int iy = 0; iy < hoplotn-ix; iy++)\n\t\t  {\n\t\t  glNormal3dv (gridn[ix][iy]);\n\t\t  glVertex3dv (grid[ix][iy]);\n\n\t\t  glNormal3dv (gridn[ix+1][iy]);\n\t\t  glVertex3dv (grid[ix+1][iy]);\n\n\t\t  glNormal3dv (gridn[ix][iy+1]);\n\t\t  glVertex3dv (grid[ix][iy+1]);\n\n\t\t  if (iy < hoplotn-ix-1)\n\t\t  {\n\t\t  glNormal3dv (gridn[ix][iy+1]);\n\t\t  glVertex3dv (grid[ix][iy+1]);\n\n\t\t  glNormal3dv (gridn[ix+1][iy]);\n\t\t  glVertex3dv (grid[ix+1][iy]);\n\n\t\t  glNormal3dv (gridn[ix+1][iy+1]);\n\t\t  glVertex3dv (grid[ix+1][iy+1]);\n\t\t  }\n\t\t  }\n\t\t  }\n\n\t\t  glEnd ();\n\n\n\n\n\t\t  glBegin (GL_QUADS);\n\n\t\t  for (int quad = 4; quad < 5; quad++)\n\t\t  {\n\t\t  Point<3> p0 = vertices[faces[quad][0]-1];\n\t\t  Point<3> p1 = vertices[faces[quad][1]-1];\n\t\t  Point<3> p2 = vertices[faces[quad][2]-1];\n\t\t  Point<3> p3 = vertices[faces[quad][3]-1];\n\n\t\t  if (vispar.shrink < 1)\n\t\t  {\n\t\t  static Point<3> c(0.375, 0.375, 0.25);\n\t\t  p0 = c + vispar.shrink * (p0 - c);\n\t\t  p1 = c + vispar.shrink * (p1 - c);\n\t\t  p2 = c + vispar.shrink * (p2 - c);\n\t\t  p3 = c + vispar.shrink * (p3 - c);\n\t\t  }\n\n\t\t  Vec<3> taux = p1-p0;\n\t\t  Vec<3> tauy = p3-p0;\n\t\t  Vec<3> gtaux, gtauy;\n\n\t\t  Point<3> xl, xg;\n\t\t  Mat<3,3> dxdxi;\n\n\t\t  for (int ix = 0; ix <= hoplotn; ix++)\n\t\t  for (int iy = 0; iy <= hoplotn; iy++)\n\t\t  {\n\t\t  Point<3> xl;\n\t\t  for (int l = 0; l < 3; l++)\n\t\t  xl(l) =\n\t\t  (1-double(ix)/hoplotn)*(1-double(iy)/hoplotn) * p0(l) +\n\t\t  (  double(ix)/hoplotn)*(1-double(iy)/hoplotn) * p1(l) +\n\t\t  (  double(ix)/hoplotn)*(  double(iy)/hoplotn) * p2(l) +\n\t\t  (1-double(ix)/hoplotn)*(  double(iy)/hoplotn) * p3(l);\n\n\t\t  curv.CalcElementTransformation (xl, i-1, grid[ix][iy], dxdxi);\n\n\t\t  gtaux = dxdxi * taux;\n\t\t  gtauy = dxdxi * tauy;\n\t\t  gridn[ix][iy] = Cross (gtauy, gtaux).Normalize();\n\t\t  }\n\n\t\t  for (int ix = 0; ix < hoplotn; ix++)\n\t\t  for (int iy = 0; iy < hoplotn; iy++)\n\t\t  {\n\t\t  glNormal3dv (gridn[ix][iy]);\n\t\t  glVertex3dv (grid[ix][iy]);\n\n\t\t  glNormal3dv (gridn[ix+1][iy]);\n\t\t  glVertex3dv (grid[ix+1][iy]);\n\n\t\t  glNormal3dv (gridn[ix+1][iy+1]);\n\t\t  glVertex3dv (grid[ix+1][iy+1]);\n\n\t\t  glNormal3dv (gridn[ix][iy+1]);\n\t\t  glVertex3dv (grid[ix][iy+1]);\n\t\t  }\n\t\t  }\n\n\t\t  glEnd ();\n\t\t*/\n\n\n\t      }\n            else\n\t      {\n\n\n\n\t\tPoint3d c(0,0,0);\n\t\tif (vispar.shrink < 1)\n\t\t  {\n\t\t    for (int j = 1; j <= 5; j++)\n\t\t      {\n\t\t\tPoint3d p = mesh->Point(el.PNum(j));\n\t\t\tc.X() += p.X() / 5;\n\t\t\tc.Y() += p.Y() / 5;\n\t\t\tc.Z() += p.Z() / 5;\n\t\t      }\n\t\t  }\n\n\n\t\tel.GetSurfaceTriangles (faces);\n\n\t\tif (el.PNum(1))\n\t\t  {\n\t\t    glBegin (GL_TRIANGLES);\n\n\t\t    for (int j = 1; j <= faces.Size(); j++)\n\t\t      {\n\t\t\tElement2d & face = faces.Elem(j);\n\t\t\tPoint3d lp1 = mesh->Point (el.PNum(face.PNum(1)));\n\t\t\tPoint3d lp2 = mesh->Point (el.PNum(face.PNum(2)));\n\t\t\tPoint3d lp3 = mesh->Point (el.PNum(face.PNum(3)));\n\t\t\tVec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t\t\tn /= (n.Length()+1e-12);\n\t\t\tn *= -1;\n\t\t\tglNormal3d (n.X(), n.Y(), n.Z());\n\n\t\t\tif (vispar.shrink < 1)\n\t\t\t  {\n\t\t\t    lp1 = c + vispar.shrink * (lp1 - c);\n\t\t\t    lp2 = c + vispar.shrink * (lp2 - c);\n\t\t\t    lp3 = c + vispar.shrink * (lp3 - c);\n\t\t\t  }\n\n\t\t\tglVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\t\tglVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\t\tglVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t\t      }\n\n\t\t    glEnd();\n\t\t  }\n\t      }\n\t  }\n      }\n    glEndList ();\n  }\n\n  void VisualSceneMesh :: BuildBadelList()\n  {\n    ;\n  }\n\n  void VisualSceneMesh :: BuildIdentifiedList()\n  {\n    ;\n  }\n\n  void VisualSceneMesh :: BuildDomainSurfList()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    \n    if (domainsurflist)\n      glDeleteLists (domainsurflist, 1);\n\n    domainsurflist = glGenLists (1);\n    glNewList (domainsurflist, GL_COMPILE);\n\n    int i, j;\n    glLineWidth (1.0f);\n\n    glDisable (GL_COLOR_MATERIAL);\n\n    for (i = 1; i <= mesh->GetNSE(); i++)\n      {\n\tElement2d el = mesh->SurfaceElement (i);\n\n\tint drawel = 1;\n\tfor (j = 1; j <= el.GetNP(); j++)\n\t  {\n            if (!el.PNum(j))\n\t      drawel = 0;\n\t  }\n\n\tif (!drawel)\n\t  continue;\n\n\tif (el.GetIndex() < 1 || el.GetIndex() > mesh->GetNFD())\n\t  continue;\n\tint domin = mesh->GetFaceDescriptor(el.GetIndex()).DomainIn();\n\tint domout = mesh->GetFaceDescriptor(el.GetIndex()).DomainOut();\n\n\tint fac;\n\tif (domin == vispar.drawdomainsurf)\n\t  fac = 1;\n\telse if (domout == vispar.drawdomainsurf)\n\t  fac = -1;\n\telse\n\t  continue;\n\n\n\tGLfloat matcol[] = { 1, 0, 0, 1 };\n\tglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcol);\n\n\n\tif (el.GetNP() == 3)\n\t  {\n            glBegin (GL_TRIANGLES);\n\n            const Point3d & lp1 = mesh->Point (el.PNum(1));\n            const Point3d & lp2 = mesh->Point (el.PNum(2));\n            const Point3d & lp3 = mesh->Point (el.PNum(3));\n            Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n            n /= ( fac * (n.Length()+1e-12));\n            glNormal3d (n.X(), n.Y(), n.Z());\n\n            if (!vispar.colormeshsize)\n\t      {\n\t\tglVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\tglVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\tglVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t      }\n            glEnd();\n\t  }\n\telse if (el.GetNP() == 4)\n\t  {\n            glBegin (GL_QUADS);\n\n            const Point3d & lp1 = mesh->Point (el.PNum(1));\n            const Point3d & lp2 = mesh->Point (el.PNum(2));\n            const Point3d & lp3 = mesh->Point (el.PNum(4));\n            const Point3d & lp4 = mesh->Point (el.PNum(3));\n            Vec3d n = Cross (Vec3d (lp1, lp2),\n\t\t\t     Vec3d (lp1, Center (lp3, lp4)));\n            n /= (fac * (n.Length()+1e-12));\n            glNormal3d (n.X(), n.Y(), n.Z());\n            glVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n            glVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n            glVertex3d (lp4.X(), lp4.Y(), lp4.Z());\n            glVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n            glEnd();\n\t  }\n\telse if (el.GetNP() == 6)\n\t  {\n            glBegin (GL_TRIANGLES);\n            static int trigs[4][3] = {\n\t      { 1, 6, 5 },\n\t      { 2, 4, 6 },\n\t      { 3, 5, 4 },\n\t      { 4, 5, 6 } };\n\n\t    for (j = 0; j < 4; j++)\n\t      {\n\t\tconst Point3d & lp1 = mesh->Point (el.PNum(trigs[j][0]));\n\t\tconst Point3d & lp2 = mesh->Point (el.PNum(trigs[j][1]));\n\t\tconst Point3d & lp3 = mesh->Point (el.PNum(trigs[j][2]));\n\t\tVec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3));\n\t\tn /= (fac * (n.Length() + 1e-12));\n\t\tglNormal3d (n.X(), n.Y(), n.Z());\n\t\tglVertex3d (lp1.X(), lp1.Y(), lp1.Z());\n\t\tglVertex3d (lp2.X(), lp2.Y(), lp2.Z());\n\t\tglVertex3d (lp3.X(), lp3.Y(), lp3.Z());\n\t      }\n\t    glEnd();\n\t  }\n      }\n    glEndList ();\n  }\n\n\n\n\n\n  bool VisualSelect :: SelectSurfaceElement (shared_ptr<Mesh> mesh, int px, int py, Point<3> &p, bool select_on_clipping_plane)\n  {\n    selelement = -1;\n    // marker = nullopt;\n    if(px != x || py != y)\n    {\n      x = px;\n      y = py;\n    }\n\n    glGetIntegerv (GL_VIEWPORT, viewport);\n    // GLenum err;\n    if(framebuffer == 0 || viewport[2] != width || viewport[3] != height)\n    {\n      width = viewport[2];\n      height = viewport[3];\n      if(framebuffer != 0)\n      {\n        glDeleteRenderbuffers(2, render_buffers);\n        glDeleteFramebuffers(1, &framebuffer);\n      }\n\n      glGenFramebuffers(1, &framebuffer);\n      glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);\n\n      // create, reserve and attach color and depth renderbuffer\n      glGenRenderbuffers(2, render_buffers);\n      glBindRenderbuffer(GL_RENDERBUFFER, render_buffers[0]);\n      glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB16, width, height);\n      glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buffers[0]);\n\n      glBindRenderbuffer(GL_RENDERBUFFER, render_buffers[1]);\n      glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);\n      glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_buffers[1]);\n\n      // check if framebuffer status is complete\n      if(int fbstatus; (fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)\n        cerr << \"no frame buffer \" << fbstatus << endl;\n\n    }\n      glFlush();\n\n      glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);\n\n      glEnable(GL_DEPTH_TEST);\n      glClearColor(0, 0, 0, 1.0);\n      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n      glMatrixMode (GL_MODELVIEW);\n      glPushMatrix();\n      glLoadIdentity();\n      glMultMatrixd (transformationmat);\n\n      glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n      auto hy = viewport[3] - py;\n\n      if (enable_clipping_plane)\n      {\n        glClipPlane(GL_CLIP_PLANE0, clipplane);\n        glEnable(GL_CLIP_PLANE0);\n        Vec<3> n(clipplane[0], clipplane[1], clipplane[2]);\n        double len = Abs(n);\n        double mu = -clipplane[3] / (len*len);\n        Point<3> p (mu * n);\n        n /= len;\n        Vec<3> t1 = n.GetNormal ();\n        Vec<3> t2 = Cross (n, t1);\n\n        double xi1mid = (center - p) * t1;\n        double xi2mid = (center - p) * t2;\n\n        if(select_on_clipping_plane)\n        {\n          glColor3us(0,0,0);\n          glBegin (GL_QUADS);\n          glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2);\n          glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2);\n          glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2);\n          glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2);\n          glEnd ();\n        }\n      }\n      glCallList (list);\n      glFinish();\n\n      glGetDoublev (GL_PROJECTION_MATRIX, projmat);\n      auto found = Unproject(px, py, p);\n      if(found)\n      {\n        // marker = p;\n        GLushort numbers[3];\n        glReadPixels (px, hy, 1, 1, GL_RGB, GL_UNSIGNED_SHORT, numbers);\n        selelement = numbers[0] + numbers[1]*(1<<16);\n      }\n      glBindFramebuffer(GL_FRAMEBUFFER, 0);\n      glPopMatrix();\n\n    return found;\n  }\n\n  bool VisualSceneMesh :: Unproject(int px, int py, Point<3> &p)\n  {\n    return select.Unproject(px, py, p);\n  }\n\n  ngcore::IVec<2> VisualSceneMesh :: Project(Point<3> p)\n  {\n    Point<3> pwin;\n    gluProject(p[0], p[1], p[2], transformationmat, select.projmat, select.viewport,\n        &pwin[0], &pwin[1], &pwin[2]);\n\n    return ngcore::IVec<2>(pwin[0]+0.5, select.viewport[3]-pwin[1]+0.5);\n  }\n\n\n  bool VisualSceneMesh :: SelectSurfaceElement(int px, int py, Point<3> &p, bool select_on_clipping_plane) {\n    BuildFilledList(true);\n    memcpy(select.transformationmat, transformationmat, sizeof(transformationmat));\n    memcpy(select.clipplane, clipplane, sizeof(clipplane));\n    select.center = center;\n    select.rad = rad;\n    select.enable_clipping_plane = vispar.clipping.enable;\n    bool found = select.SelectSurfaceElement(GetMesh(), px, py, p, select_on_clipping_plane);\n    selelement = select.selelement;\n    return found;\n  }\n\n  void VisualSceneMesh :: MouseDblClick (int px, int py)\n  {\n    Point<3> p;\n    bool found_point = SelectSurfaceElement(px, py, p, false);\n\n    if(selelement>0)\n      {\n        const Element2d & sel = GetMesh()->SurfaceElement(selelement);\n        SetSelectedFace(sel.GetIndex());\n\n        auto pi_nearest = sel[0];\n        double min_dist = 1e99;\n        for(auto pi : sel.PNums())\n          if(Dist2(GetMesh()->Point(pi), p) < min_dist)\n          {\n            min_dist = Dist2(GetMesh()->Point(pi), p);\n            pi_nearest = pi;\n          }\n        auto p_win = Project(GetMesh()->Point(pi_nearest));\n        if(abs(p_win[0]-px) < 5 && abs(p_win[1]-py) < 5)\n        {\n          marker = GetMesh()->Point(pi_nearest);\n          selpoint = pi_nearest;\n          cout << \"select point \" << pi_nearest << \" at \" << *marker << endl;\n        }\n        else\n        {\n            marker = p;\n            cout << endl << \"select element \" << selelement\n              << \" on face \" << sel.GetIndex();\n            // output face name\n            auto mesh = GetMesh();\n            string name;\n            if(mesh->GetDimension() == 3)\n              name = mesh->GetFaceDescriptor(sel.GetIndex()).GetBCName();\n            else\n              name = mesh->GetMaterial(sel.GetIndex());\n\n            if(name != \"\")\n              cout << \" with name \" << name;\n            cout << endl;\n            if(mesh->GetDimension() == 3) {\n              auto & fd = mesh->GetFaceDescriptor(sel.GetIndex());\n              auto domin = fd.DomainIn();\n              auto domout = fd.DomainOut();\n              string name_in = domin >0 ? mesh->GetMaterial(domin) : \"\";\n              string name_out = domout >0 ? mesh->GetMaterial(domout) : \"\";\n              cout << \"\\tadjacent domains \" << domin << \": \" << name_in << \", \" << domout << \": \" << name_out << endl;\n            }\n            cout << \"\\tpoint: \" << p << endl;;\n            cout << \"\\tnodes: \";\n            for (int i = 1; i <= sel.GetNP(); i++)\n              cout << sel.PNum(i) << \" \";\n            cout << endl;\n        }\n      }\n\n    if(found_point && user_me_handler)\n    {\n      if (selelement != -1)\n        user_me_handler -> DblClick (selelement-1, p[0], p[1], p[2]);\n    }\n\n    if(lock)\n      {\n\tlock->UnLock();\n\tdelete lock;\n\tlock = NULL;\n      }\n  }\n\n\n\n  void VisualSceneMesh :: SetSelectedFace (int asf)\n  {\n    if(selface != asf)\n    {\n      selface = asf;\n      BuildColorTexture();\n    }\n  }\n\n\n  static bool dummy_init_var = [] () {\n    on_set_global_mesh = [](shared_ptr<Mesh> mesh) {\n      vsmesh.SetMesh(mesh);\n    };\n    return true;\n  }();\n}\n\n\n\n\n#ifdef NG_PYTHON\n#include <../general/ngpython.hpp>\n#include \"../include/nginterface.h\"\n\nNGGUI_API void ExportMeshVis(py::module &m)\n{\n  using namespace netgen;\n  vispar.drawcolorbar = true;\n  vispar.drawnetgenlogo = true;\n  vispar.drawcoordinatecross = true;\n  vispar.drawfilledtrigs = true;\n  vispar.drawdomainsurf = true;\n  vispar.drawhexes = true;\n  vispar.drawtets = true;\n  vispar.drawprisms = true;\n  vispar.drawoutline = true;\n  py::class_<VisualSceneMesh, shared_ptr<VisualSceneMesh>>\n    (m, \"VisualSceneMesh\")\n    .def(\"Draw\", &VisualSceneMesh::DrawScene)\n    ;\n\n  m.def(\"VS\", FunctionPointer\n          ([](shared_ptr<Mesh> mesh)\n           {\n             auto vs = make_shared<VisualSceneMesh>();\n             // vs->SetMesh(mesh);\n             SetGlobalMesh (mesh);\n             return vs;\n           }));\n\n  m.def(\"MouseMove\", FunctionPointer\n          ([](VisualSceneMesh &vsmesh, int oldx, int oldy, int newx, int \n              newy, char mode)\n           {\n             vsmesh.MouseMove(oldx, oldy, newx, newy, mode);\n           }));\n  m.def(\"SelectFace\", FunctionPointer\n      ([] (int facenr) {\n       vsmesh.SetSelectedFace(facenr);\n       }));\n  m.def(\"GetGlobalMesh\", FunctionPointer\n      ([] () {\n       return vsmesh.GetMesh();\n       }));\n}\n// BOOST_PYTHON_MODULE(libvisual)\n// {\n//   ExportMeshVis();\n// }\n#endif\n"
  },
  {
    "path": "libsrc/visualization/vssolution.cpp",
    "content": "#include <mystdlib.h>\n\n#include <myadt.hpp>\n#include <meshing.hpp>\n#include <csg.hpp>\n#include <stlgeom.hpp>\n\n\n// #include <parallel.hpp>\n#include <visual.hpp>\n#include <limits>\n\nnamespace netgen\n{\n\n\n  VisualSceneSolution & GetVSSolution()\n  {\n    static VisualSceneSolution vssolution;\n    return vssolution;\n  }\n\n  \n  // extern shared_ptr<Mesh> mesh;\n  extern VisualSceneMesh vsmesh;\n\n  VisualSceneSolution :: SolData :: SolData ()\n    : data{nullptr}, solclass{nullptr}\n  { ; }\n\n  VisualSceneSolution :: SolData :: ~SolData ()\n  {\n    // delete [] name;\n    delete data;\n    delete solclass;\n  }\n\n  \n  VisualSceneSolution :: VisualSceneSolution ()\n    : VisualScene()\n  {\n    // cout << \"init VisualSceneSolution\" << endl;\n    surfellist = 0;\n    linelist = 0;\n    element1dlist = 0;\n    clipplanelist_scal = 0;\n    clipplanelist_vec = 0;\n    isolinelist = 0;\n    clipplane_isolinelist = 0;\n    surface_vector_list = 0;\n    isosurface_list = 0;\n    select_sel_list = 0;\n    numtexturecols = 8;\n\n    fieldlineslist = 0;\n    pointcurvelist = 0;\n\n    num_fieldlineslists = 0;\n\n\n    surfeltimestamp = GetTimeStamp();\n    surfellinetimestamp = GetTimeStamp();\n    clipplanetimestamp = GetTimeStamp();\n    solutiontimestamp = GetTimeStamp();\n    fieldlinestimestamp = GetTimeStamp();\n    pointcurve_timestamp = GetTimeStamp();\n    surface_vector_timestamp = GetTimeStamp();\n    isosurface_timestamp = GetTimeStamp();\n    timetimestamp = GetTimeStamp();\n    // AddVisualizationScene (\"solution\", &vssolution);\n  }\n  \n  VisualSceneSolution :: ~VisualSceneSolution ()\n  {\n    // cout << \"exit VisualSceneSolution\" << endl;    \n    ClearSolutionData();\n  }\n\n  /*\n  void VisualSceneSolution :: SetMesh (shared_ptr<Mesh> amesh)\n  { \n    wp_mesh = amesh; \n  }\n  */\n\n  void VisualSceneSolution :: AddSolutionData (SolData * sd)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    NgLock meshlock1 (mesh->MajorMutex(), 1);\n    int funcnr = -1;\n    for (int i = 0; i < soldata.Size(); i++)\n      {\n        // if (strcmp (soldata[i]->name, sd->name) == 0)\n        if (soldata[i]->name == sd->name)\n          {\n            delete soldata[i];\n            soldata[i] = sd;\n            funcnr = i;\n            break;\n          }\n      }\n\n    if (funcnr == -1)\n      {\n        soldata.Append (sd);\n        funcnr = soldata.Size()-1;\n      }\n    \n    SolData * nsd = soldata[funcnr]; \n\n    nsd->size = 0;\n    if (mesh)\n      {\n        switch (nsd->soltype)\n          {\n          case SOL_NODAL: nsd->size = mesh->GetNV(); break;\n          case SOL_ELEMENT: nsd->size = mesh->GetNE(); break;\n          case SOL_SURFACE_ELEMENT: nsd->size = mesh->GetNSE(); break;\n          case SOL_NONCONTINUOUS: \n            {\n              switch (nsd->order)\n                {\n                case 0: nsd->size =      mesh->GetNE(); break;\n                case 1: nsd->size =  6 * mesh->GetNE(); break;\n                case 2: nsd->size = 18 * mesh->GetNE(); break;\n                }\n              break;\n            }\n          case SOL_SURFACE_NONCONTINUOUS: \n            {\n              switch (nsd->order)\n                {\n                case 0: nsd->size =     mesh->GetNSE(); break;\n                case 1: nsd->size = 4 * mesh->GetNSE(); break;\n                case 2: nsd->size = 9 * mesh->GetNSE(); break;\n                }\n              break;\n            }\n          default:\n            nsd->size = 0;\n          }\n        solutiontimestamp = NextTimeStamp();\n      }\n  }\n\n  \n  void VisualSceneSolution :: ClearSolutionData ()\n  {\n    for (int i = 0; i < soldata.Size(); i++)\n      delete soldata[i];\n    soldata.SetSize (0);\n  }\n\n  void VisualSceneSolution :: UpdateSolutionTimeStamp ()\n  {\n    solutiontimestamp = NextTimeStamp();\n  }\n    \n  VisualSceneSolution::SolData * VisualSceneSolution :: GetSolData (int i)\n  { \n    if (i >= 0 && i < soldata.Size())\n      return soldata[i];\n    else \n      return NULL;\n  }\n  \n\n\n\n  void VisualSceneSolution :: SaveSolutionData (const char * filename) \n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    PrintMessage (1, \"Write solution data to file \", filename);\n\n\n    if (strcmp (&filename[strlen(filename)-3], \"sol\") == 0)\n      {\n        ofstream ost(filename);\n        for (int i = 0; i < soldata.Size(); i++)\n          {\n            const SolData & sol = *soldata[i];\n      \n            ost << \"solution \" \n                << sol.name\n                << \" -size=\" << sol.size \n                << \" -components=\" << sol.components\n                << \" -order=\" << sol.order;\n            if (sol.iscomplex)\n              ost << \" -complex\";\n      \n            switch (sol.soltype)\n              {\n              case SOL_NODAL:\n                ost << \" -type=nodal\"; break;\n              case SOL_ELEMENT:\n                ost << \" -type=element\"; break;\n              case SOL_SURFACE_ELEMENT:\n                ost << \" -type=surfaceelement\"; break;\n              case SOL_NONCONTINUOUS:\n                ost << \" -type=noncontinuous\"; break;\n              case SOL_SURFACE_NONCONTINUOUS:\n                ost << \" -type=surfacenoncontinuous\"; break;\n              default:\n                cerr << \"save solution data, case not handled\" << endl;\n              }\n      \n            ost << endl;\n            for (int j = 0; j < sol.size; j++)\n              {\n                for (int k = 0; k < sol.components; k++)\n                  ost << sol.data[j*sol.dist+k] << \" \";\n                ost << \"\\n\";\n              }\n          }\n      }\n\n\n    if (strcmp (&filename[strlen(filename)-3], \"vtk\") == 0)\n      {\n        string surf_fn = filename;\n        surf_fn.erase (strlen(filename)-4);\n        surf_fn += \"_surf.vtk\";\n\n        cout << \"surface mesh = \" << surf_fn << endl;\n        \n        ofstream surf_ost(surf_fn.c_str());\n\n        surf_ost << \"# vtk DataFile Version 1.0\\n\"\n\t\t << \"NGSolve surface mesh\\n\"\n\t\t << \"ASCII\\n\"\n\t\t << \"DATASET UNSTRUCTURED_GRID\\n\\n\";\n\n        surf_ost << \"POINTS \" << mesh->GetNP() << \" float\\n\";\n        for (PointIndex pi = IndexBASE<PointIndex>(); pi < mesh->GetNP()+IndexBASE<PointIndex>(); pi++)\n          {\n            const MeshPoint & mp = (*mesh)[pi];\n            surf_ost << mp(0) << \" \" << mp(1) << \" \" << mp(2) << \"\\n\";\n          }\n\n        int cntverts = 0;\n        for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++)\n          cntverts += 1 + (*mesh)[sei].GetNP();\n\n        surf_ost << \"\\nCELLS \" << mesh->GetNSE() << \" \" << cntverts << \"\\n\";\n        for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++)\n          {\n            const Element2d & el = (*mesh)[sei];\n            surf_ost << el.GetNP();\n            for (int j = 0; j < el.GetNP(); j++)\n              surf_ost << \" \" << el[j] - IndexBASE<PointIndex>();\n            surf_ost << \"\\n\";\n          }\n        surf_ost << \"\\nCELL_TYPES \" << mesh->GetNSE() << \"\\n\";\n        for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++)\n          {\n            const Element2d & el = (*mesh)[sei];\n            switch (el.GetType())\n              {\n              case QUAD: surf_ost << 9; break;\n              case TRIG: surf_ost << 5; break;\n              default:\n                cerr << \"not implemented 2378\" << endl;\n              }\n            surf_ost << \"\\n\";\n          }\n\n\n       \n        ofstream ost(filename);\n\n        ost << \"# vtk DataFile Version 1.0\\n\"\n            << \"NGSolve solution\\n\"\n            << \"ASCII\\n\"\n            << \"DATASET UNSTRUCTURED_GRID\\n\\n\";\n\n        ost << \"POINTS \" << mesh->GetNP() << \" float\\n\";\n        for (PointIndex pi = IndexBASE<PointIndex>(); pi < mesh->GetNP()+IndexBASE<PointIndex>(); pi++)\n          {\n            const MeshPoint & mp = (*mesh)[pi];\n            ost << mp(0) << \" \" << mp(1) << \" \" << mp(2) << \"\\n\";\n          }\n\n        cntverts = 0;\n        for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n          cntverts += 1 + (*mesh)[ei].GetNP();\n\n        ost << \"\\nCELLS \" << mesh->GetNE() << \" \" << cntverts << \"\\n\";\n        for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n          {\n            const Element & el = (*mesh)[ei];\n            ost << el.GetNP();\n            for (int j = 0; j < el.GetNP(); j++)\n              ost << \" \" << el[j] - IndexBASE<PointIndex>();\n            ost << \"\\n\";\n          }\n        ost << \"\\nCELL_TYPES \" << mesh->GetNE() << \"\\n\";\n        for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n          {\n            const Element & el = (*mesh)[ei];\n            switch (el.GetType())\n              {\n              case TET: ost << 10; break;\n              default:\n                cerr << \"not implemented 67324\" << endl;\n              }\n            ost << \"\\n\";\n          }\n\n\n        ost << \"CELL_DATA \" << mesh->GetNE() << \"\\n\";\n        for (int i = 0; i < soldata.Size(); i++)\n          {\n            ost << \"VECTORS bfield float\\n\";\n            SolutionData & sol = *(soldata[i] -> solclass);\n            double values[3];\n\n            for (int elnr = 0; elnr < mesh->GetNE(); elnr++)\n              {\n                sol.GetValue (elnr, 0.25, 0.25, 0.25, values);\n                ost << values[0] << \" \"  << values[1] << \" \"  << values[2] << \"\\n\";\n              }\n          }\n\n        /*\n\t  ost << \"POINT_DATA \" << mesh->GetNP() << \"\\n\";\n\t  for (int i = 0; i < soldata.Size(); i++)\n          {\n\t  ost << \"VECTORS bfield float\\n\";\n\t  SolutionData & sol = *(soldata[i] -> solclass);\n            \n\t  for (PointIndex pi = PointIndex::BASE; \n\t  pi < mesh->GetNP()+PointIndex::BASE; pi++)\n\t  {\n\t  double values[3], sumvalues[3] = { 0, 0, 0 };\n\n\t  NgFlatArray<int> els = mesh->GetTopology().GetVertexElements(pi);\n\n\t  for (int j = 0; j < els.Size(); j++)\n\t  {\n\t  sol.GetValue (els[j]-1, 0.25, 0.25, 0.25, values);\n\t  for (int k = 0; k < 3; k++)\n\t  sumvalues[k] += values[k];\n\t  }\n\t  for (int k = 0; k < 3; k++)\n\t  sumvalues[k] /= els.Size();\n                \n\t  ost << sumvalues[0] << \" \"  << sumvalues[1] << \" \"  << sumvalues[2] << \"\\n\";\n\t  }\n          }\n        */\n      } \n    \n  }\n  \n\n\n\n  void VisualSceneSolution :: DrawScene ()\n  {\n    try\n      {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (!mesh) \n      {\n        VisualScene::DrawScene();      \n        return;\n      }\n\n    // static NgLock mem_lock(mem_mutex);\n    // mem_lock.Lock();\n\n    NgLock meshlock1 (mesh->MajorMutex(), true);\n    NgLock meshlock (mesh->Mutex(), true);\n\n    BuildScene();\n\n    CreateTexture (GetVSSolution().numtexturecols, lineartexture, 0.5, GL_MODULATE);\n\n    glClearColor(backcolor, backcolor, backcolor, 1);\n    // glClearColor(backcolor, backcolor, backcolor, 0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    SetLight();\n    \n    glPushMatrix();\n    glMultMatrixd (transformationmat);\n\n    glMatrixMode (GL_MODELVIEW); \n    \n    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n    \n    glPolygonOffset (1, 1);\n\n    glEnable (GL_POLYGON_OFFSET_FILL);\n\n    glEnable (GL_COLOR_MATERIAL);\n    glDisable(GL_BLEND);\n\n    if (usetexture)\n      {\n        SetTextureMode (usetexture);\n\n        glMatrixMode (GL_TEXTURE);\n        glLoadIdentity();\n        \n        if (usetexture == 1)\n          {\n            double hmax = maxval;\n            double hmin = minval;\n            if (invcolor) Swap (hmax, hmin);\n\n            if (fabs (hmax - hmin) > 1e-30) \n              glScaled (1.0 / (hmin - hmax), 0, 0);\n            else\n              glScaled (1e30, 0, 0);\n            \n            glTranslatef (-hmax, 0, 0);\n          }\n        else\n          {\n            glTranslatef (0.5, 0, 0);\n            glRotatef(360 * netgen::GetVSSolution().time, 0, 0, -1);\n            if (fabs (maxval) > 1e-10)\n              glScalef(0.5/maxval, 0.5/maxval, 0.5/maxval);\n            else\n              glScalef (1e10, 1e10, 1e10);\n          }\n        glMatrixMode (GL_MODELVIEW);\n      }\n\n\n\n\n    if (vispar.drawfilledtrigs || vispar.drawtetsdomain > 0 || vispar.drawdomainsurf > 0)\n      {\n\t// Change for Martin:\n\n\t// orig:\n\tSetClippingPlane ();  \n\n\tglCallList (surfellist);\n        \n#ifdef USE_BUFFERS\n        // static int timer = NgProfiler::CreateTimer (\"Solution::drawing - DrawSurfaceElements VBO\");\n        // NgProfiler::StartTimer(timer);\n        glEnableClientState(GL_VERTEX_ARRAY);\n        glEnableClientState(GL_NORMAL_ARRAY);\n        glEnableClientState(GL_TEXTURE_COORD_ARRAY);\n        glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0);\n        glDisableClientState(GL_VERTEX_ARRAY);\n        glDisableClientState(GL_NORMAL_ARRAY);\n        glDisableClientState(GL_TEXTURE_COORD_ARRAY);\n        // NgProfiler::StopTimer(timer);\n#endif\n        \n\t/*\n\t// transparent test ...\n\tglColor4f (1, 0, 0, 0.1);\n\tglEnable (GL_COLOR_MATERIAL);\n\n\tglDepthFunc(GL_GREATER); \n\tglDepthMask(GL_FALSE); \n\t// glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA); \n\tglBlendFunc(GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA); \n\n\tglCallList (surfellist);\n\n\tglDisable(GL_BLEND);\n\tglDepthFunc(GL_LEQUAL); \n\tglDepthMask(GL_TRUE); \n\n\tglCallList (surfellist);\n\t// end test ...\n\t*/\n\t\n\n        glCallList (surface_vector_list);\n        glDisable(GL_CLIP_PLANE0);\n      }\n\n\n    if (showclipsolution)\n      {\n\tif (clipsolution == 1)\n\t  {\n\t    // Martin \n\t    // orig:\n\t    glCallList (clipplanelist_scal);\n\n\t    // transparent experiments\n\t    // see http://wiki.delphigl.com/index.php/Blenden\n\n\t    /*\n\t    glColor4f (1, 1, 1, 0.5);\n\t    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);   \n\t    glEnable(GL_BLEND); \n\t    glEnable(GL_COLOR);\n\t    glDepthFunc(GL_GREATER); \n\t    glDepthMask(GL_FALSE); \n\n\t    glCallList (clipplanelist_scal); \n\t    glDepthFunc(GL_LEQUAL); \n\t    glDepthMask(GL_TRUE); \n\n\t    glCallList (clipplanelist_scal);\n\t    glDisable(GL_BLEND); \n\t    */\n\n\n\t    /*\n\t      // latest transparent version ...\n\t    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);   \n\t    glEnable(GL_BLEND); \n\t    glEnable(GL_DEPTH_TEST);\n\n\t    // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE);\n\t    // glCallList (clipplanelist_scal); \n\n\t    glEnable(GL_BLEND); \n\t    // glDisable(GL_DEPTH_TEST);\n\t    \n\t    // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE);\n\t    glCallList (clipplanelist_scal); \n\n\n\t    // glDepthFunc(GL_LEQUAL); \n\t    // glDepthMask(GL_TRUE); \n\t    // glCallList (clipplanelist_scal);\n\t    glEnable(GL_DEPTH_TEST);\n\t    glDisable(GL_BLEND); \n\t    */\n\t    // end test\n\t  } \n\tif (clipsolution == 2)\n\t  {\n\t    // glDisable(GL_DEPTH_TEST);\n\t    glCallList (clipplanelist_vec);\n\t    // glEnable(GL_DEPTH_TEST);\n\t  }\n      }\n\n\n\n    if (draw_fieldlines)\n      {\n\tSetClippingPlane();\n        if (num_fieldlineslists <= 1)\n          glCallList (fieldlineslist);\n        else\n          {  // animated\n            int start = int (time / 10 * num_fieldlineslists);\n            for (int ln = 0; ln < 10; ln++)\n              {\n                int nr = fieldlineslist + (start + ln) % num_fieldlineslists;\n                glCallList (nr);\n              }\n          }\n        glDisable(GL_CLIP_PLANE0);\n      }\n\n    if(drawpointcurves)\n      {\n        SetClippingPlane();\n        glCallList(pointcurvelist);\n        glDisable(GL_CLIP_PLANE0);\n      }\n\n\n    glMatrixMode (GL_TEXTURE);\n    glLoadIdentity();\n    glMatrixMode (GL_MODELVIEW);\n\n    glDisable (GL_TEXTURE_1D);\n    glDisable (GL_TEXTURE_2D);\n\n    glDisable (GL_POLYGON_OFFSET_FILL);\n    glDisable (GL_COLOR_MATERIAL);\n\n    if (draw_isosurface)\n      glCallList (isosurface_list);\n    \n    \n    GLfloat matcol0[] = { 0, 0, 0, 1 };\n    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol0);\n    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matcol0);\n    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol0);\n    \n    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n    glLineWidth (1.0f);\n    glColor3f (0.0f, 0.0f, 0.0f);\n    glDisable (GL_LINE_SMOOTH);\n\n    if (vispar.drawedges)\n      {\n        SetClippingPlane ();\n        glCallList (element1dlist);\n      }\n\n    if (vispar.drawoutline && !numisolines)\n      {\n\tSetClippingPlane ();\n\tglDepthMask(GL_FALSE); \n        glCallList (linelist);\n\tglDepthMask(GL_TRUE); \n\n        glDisable(GL_CLIP_PLANE0);\n      }\n\n    if (numisolines)\n      {\n        SetClippingPlane ();\n        glCallList (isolinelist);\n\n        glDisable(GL_CLIP_PLANE0);\n        glCallList (clipplane_isolinelist);\n      }\n\n\n    // user visualization\n    \n    for (int i = 0; i < user_vis.Size(); i++)\n      user_vis[i] -> Draw();\n\n    DrawMarker();\n\n    glPopMatrix();\n    \n    glDisable(GL_CLIP_PLANE0);\n    DrawColorBar (minval, maxval, logscale, lineartexture, number_format, unit);\n    DrawTitle (title);\n    \n    if (vispar.drawcoordinatecross)\n      DrawCoordinateCross ();\n    DrawNetgenLogo ();\n    \n    glFinish();  \n\n    \n    // delete lock;\n    // mem_lock.UnLock();\n      }\n    catch (const bad_weak_ptr & e)\n      {\n        // cout << \"don't have a mesh to visualize\" << endl;\n        VisualScene::DrawScene();      \n      }\n  }\n  \n\n  \n  /*\n  void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, \n                                         bool iscomplex, bool imag)\n  {\n    if (!iscomplex)\n      {\n        v.X() = values[0];\n        v.Y() = values[1];\n        v.Z() = values[2];\n      }\n    else\n      {\n        if (!imag)\n          {\n            v.X() = values[0];\n            v.Y() = values[2];\n            v.Z() = values[4];\n          }\n        else\n          {\n            v.X() = values[1];\n            v.Y() = values[3];\n            v.Z() = values[5];\n          }\n      }\n  }\n  */\n  Vec<3>  VisualSceneSolution :: RealVec3d (const double * values, \n\t\t\t\t\t    bool iscomplex, bool imag)\n  {\n    Vec<3> v;\n    if (!iscomplex)\n      {\n\tfor (int j = 0; j < 3; j++)\n\t  v(j) = values[j];\n      }\n    else\n      {\n        if (!imag)\n          {\n\t    for (int j = 0; j < 3; j++)\n\t      v(j) = values[2*j];\n          }\n        else\n          {\n\t    for (int j = 0; j < 3; j++)\n\t      v(j) = values[2*j+1];\n          }\n      }\n    return v;\n  }\n  \n\n  void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, \n                                         bool iscomplex, double phaser, double phasei)\n  {\n    if (!iscomplex)\n      {\n        v.X() = values[0];\n        v.Y() = values[1];\n        v.Z() = values[2];\n      }\n    else\n      {\n        for (int i = 0; i < 3; i++)\n          v.X(i+1) = phaser * values[2*i] + phasei * values[2*i+1];\n      }\n  }\n\n\n  \n\n  void VisualSceneSolution :: BuildScene (int zoomall)\n  {\n    try\n      {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (!mesh)\n      {\n        VisualScene::BuildScene (zoomall);\n        return;\n      }\n\n    /*\n      if (!cone_list)\n      {\n      cone_list = glGenLists (1);\n      glNewList (cone_list, GL_COMPILE);\n      DrawCone (Point<3> (0,0,0), Point<3> (0,0,1), 0.4);\n      glEndList();\n      }\n    */\n    \n    // vispar.colormeshsize = 1;\n    \n    // recalc clipping plane\n    SetClippingPlane ();\n    glDisable(GL_CLIP_PLANE0);\n    \n    \n    SolData * sol = GetScalFunction();\n    SolData * vsol = GetVecFunction();\n  \n    if (mesh->GetTimeStamp () > solutiontimestamp)\n      {\n        sol = NULL;\n        vsol = NULL;\n      }\n \n\n    if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent);\n    if (vsol && vsol->solclass) vsol->solclass->SetMultiDimComponent (multidimcomponent);\n\n    if (!autoscale || (!sol && !vsol) )\n      {\n        minval = mminval;\n        maxval = mmaxval;\n      }\n    else\n      {\n        if (mesh->GetTimeStamp () > surfeltimestamp ||\n            vispar.clipping.timestamp > clipplanetimestamp ||\n            solutiontimestamp > surfeltimestamp)\n          {\n            GetMinMax (scalfunction, scalcomp, minval, maxval);\n          }\n      }\n\n    if (mesh->GetTimeStamp() > surfeltimestamp ||\n        solutiontimestamp > surfeltimestamp || \n        zoomall)\n      {\n        if (mesh->GetTimeStamp() > surfeltimestamp || zoomall)\n          {\n            // mesh has changed\n            vsmesh.SelectCenter(zoomall);\n          }\n      \n        DrawSurfaceElements();\n      \n        surfeltimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp());\n      }\n\n    if (mesh->GetTimeStamp() > surfellinetimestamp ||\n        subdivision_timestamp > surfellinetimestamp ||\n        (solutiontimestamp > surfellinetimestamp) ||\n        zoomall)\n      {      \n        DrawSurfaceElementLines();      \n        surfellinetimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp());\n      }\n\n\n    if (vispar.drawedges)\n      Draw1DElements();\n\n\n\n    if (mesh->GetTimeStamp() > surface_vector_timestamp ||\n        solutiontimestamp > surface_vector_timestamp ||\n        zoomall)\n      {\n        if (surface_vector_list)\n          glDeleteLists (surface_vector_list, 1);\n      \n        surface_vector_list = glGenLists (1);\n        glNewList (surface_vector_list, GL_COMPILE);\n\n        glEnable (GL_NORMALIZE);\n        DrawSurfaceVectors();\n\n        glEndList ();\n\n        surface_vector_timestamp = \n          max2 (mesh->GetTimeStamp(), solutiontimestamp);\n      }\n\n    if (clipplanetimestamp < vispar.clipping.timestamp ||\n        clipplanetimestamp < solutiontimestamp)\n      {\n\n        //      cout << \"clipsolution = \" << clipsolution << endl;\n        if (vispar.clipping.enable && clipsolution == 2)      \n          {\n            mesh->Mutex().unlock();\n            mesh->BuildElementSearchTree(3);\n            mesh->Mutex().lock();\n          }\n\n      \n        if (vispar.clipping.enable && clipsolution == 1 && sol)\n\t  DrawClipPlaneTrigs (); \n\n        if (clipplanelist_vec)\n          glDeleteLists (clipplanelist_vec, 1);\n      \n        clipplanelist_vec = glGenLists (1);\n        glNewList (clipplanelist_vec, GL_COMPILE);\n\n        if (vispar.clipping.enable && clipsolution == 2 && vsol)\n          {\n            SetTextureMode (usetexture);\n\n            if (autoscale)\n              GetMinMax (vecfunction, 0, minval, maxval);\n\n            NgArray<ClipPlanePoint> cpp;\n            GetClippingPlaneGrid (cpp);\n\n            for (int i = 0; i < cpp.Size(); i++)\n              {\n                const ClipPlanePoint & p = cpp[i];\n                double values[6];\n                Vec3d v;\n\n                bool drawelem = \n                  GetValues (vsol, p.elnr, p.lami(0), p.lami(1), p.lami(2), values);\n                // RealVec3d (values, v, vsol->iscomplex, imag_part);\n\t\tv = RealVec3d (values, vsol->iscomplex, imag_part);\n\n                double val = v.Length();\n\n                if (drawelem && val > 1e-10 * maxval)\n                  {\n                    v *= (rad / val / gridsize * 0.5);\n                  \n                    SetOpenGlColor  (val);\n                    DrawCone (p.p, p.p+v, rad / gridsize * 0.2);\n                  }\n              }\n          }\n\n        glEndList ();\n      }\n\n\n    if (mesh->GetTimeStamp() > isosurface_timestamp ||\n        solutiontimestamp > isosurface_timestamp ||\n        zoomall)\n      {\n        if (isosurface_list)\n          glDeleteLists (isosurface_list, 1);\n      \n        isosurface_list = glGenLists (1);\n        glNewList (isosurface_list, GL_COMPILE);\n\n        glEnable (GL_NORMALIZE);\n        DrawIsoSurface(sol, vsol, scalcomp);\n\n        glEndList ();\n\n        isosurface_timestamp = \n          max2 (mesh->GetTimeStamp(), solutiontimestamp);\n      }\n\n    if(mesh->GetTimeStamp() > pointcurve_timestamp ||\n       solutiontimestamp > pointcurve_timestamp)\n      {\n\tif(pointcurvelist)\n\t  glDeleteLists(pointcurvelist,1);\n\t\n\t\t\n\tif(mesh->GetNumPointCurves() > 0)\n\t  {\n\t    pointcurvelist = glGenLists(1);\n\t    glNewList(pointcurvelist,GL_COMPILE);\n            SetTextureMode(0); // disable all textures\n\t    \n\t    for(int i=0; i<mesh->GetNumPointCurves(); i++)\n\t      {\n\t\tBox3d box;\n\t\tbox.SetPoint(mesh->GetPointCurvePoint(i,0));\n\t\tfor(int j=1; j<mesh->GetNumPointsOfPointCurve(i); j++)\n\t\t  box.AddPoint(mesh->GetPointCurvePoint(i,j));\n\t\tdouble diam = box.CalcDiam();\n\t\t\t     \n\t\tdouble thick = min2(0.1*diam, 0.001*rad);\n\n\t\tdouble red,green,blue;\n\t\tmesh->GetPointCurveColor(i,red,green,blue);\n\t\tglColor3f (red, green, blue);\n\t\tfor(int j=0; j<mesh->GetNumPointsOfPointCurve(i)-1; j++)\n\t\t  {\n\t\t    DrawCylinder(mesh->GetPointCurvePoint(i,j),\n\t\t\t\t mesh->GetPointCurvePoint(i,j+1),\n\t\t\t\t thick);\n\t\t  }\n\t      }\n\t    glEndList();\n\t  }\n\t\n      }\n\n\n    if (\n        numisolines && \n        (clipplanetimestamp < vispar.clipping.timestamp ||\n         clipplanetimestamp < solutiontimestamp) \n        )\n      {\n        if (isolinelist) glDeleteLists (isolinelist, 1);\n      \n        isolinelist = glGenLists (1);\n        glNewList (isolinelist, GL_COMPILE);\n\n        Point<3> points[1100];\n        double values[1100];\n      \n        int nse = mesh->GetNSE();\n\n        CurvedElements & curv = mesh->GetCurvedElements();\n\n        auto sol_active = GetScalOrVecFunction();\n\n        if (sol)\n          {\n            glBegin (GL_LINES);\n          \n            for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n              {\n                const Element2d & el = (*mesh)[sei];\n\n                if(!SurfaceElementActive(sol_active, *mesh, el))\n                  continue;\n\n                bool curved = curv.IsHighOrder(); //  && curv.IsSurfaceElementCurved(sei);\n              \n                if (el.GetType() == TRIG || el.GetType() == TRIG6)\n                  {\n                    Point<3> lp1, lp2, lp3;\n                    if (!curved)\n                      {\n                        GetPointDeformation (el[0]-1, lp1);\n                        GetPointDeformation (el[1]-1, lp2);\n                        GetPointDeformation (el[2]-1, lp3);\n                      }\n                  \n                    int n = 1 << subdivisions;\n                    int ii = 0;\n                    int ix, iy;\n                    for (iy = 0; iy <= n; iy++)\n                      for (ix = 0; ix <= n-iy; ix++)\n                        {\n                          double x = double(ix) / n;\n                          double y = double(iy) / n;\n                        \n                          // TODO: consider return value (bool: draw/don't draw element)\n                          GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]);\n                          Point<2> xref(x,y);\n                        \n                          if (curved)\n                            mesh->GetCurvedElements().\n                              CalcSurfaceTransformation (xref, sei, points[ii]);\n                          else\n                            points[ii] = lp3 + x * (lp1-lp3) + y * (lp2-lp3);\n                        \n                          if (deform)\n                            {\n                              points[ii] += GetSurfDeformation (sei, -1, x, y);\n                            }\n                          ii++;\n                        }\n                  \n                    ii = 0;\n                    for (iy = 0; iy < n; iy++, ii++)\n                      for (ix = 0; ix < n-iy; ix++, ii++)\n                        {\n                          int index[] = { ii, ii+1, ii+n-iy+1,\n                                          ii+1, ii+n-iy+2, ii+n-iy+1 };\n                        \n                          DrawIsoLines (points[index[0]], points[index[1]], points[index[2]],\n                                        values[index[0]], values[index[1]], values[index[2]]);\n\n                          if (ix < n-iy-1) \n                            DrawIsoLines (points[index[3]], points[index[4]], points[index[5]],\n                                          values[index[3]], values[index[4]], values[index[5]]);\n                        }    \n                  }\n              \n              \n                if (el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 )\n                  {\n                    Point<3> lpi[4];\n                    Vec<3> vx = 0.0, vy = 0.0, vtwist = 0.0, def;\n                    if (!curved)\n                      {\n                        for (int j = 0; j < 4; j++)\n                          GetPointDeformation (el[j]-1, lpi[j]);\n                        vx = lpi[1]-lpi[0];\n                        vy = lpi[3]-lpi[0];\n                        vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]);\n                      }\n\n                    int n = 1 << subdivisions;\n                    int ix, iy, ii = 0;\n                    for (iy = 0; iy <= n; iy++)\n                      for (ix = 0; ix <= n; ix++, ii++)\n                        {\n                          double x = double(ix) / n;\n                          double y = double(iy) / n;\n                        \n                          // TODO: consider return value (bool: draw/don't draw element)\n                          GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]);\n                          Point<2> xref(x,y);\n                        \n                          if (curved)\n                            mesh->GetCurvedElements().\n                              CalcSurfaceTransformation (xref, sei, points[ii]);\n                          else\n                            points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist;\n                        \n                          if (deform)\n                            points[ii] += GetSurfDeformation (sei, -1, x, y);\n                        }\n                  \n                    ii = 0;\n                    for (iy = 0; iy < n; iy++, ii++)\n                      for (ix = 0; ix < n; ix++, ii++)\n                        {\n                          DrawIsoLines (points[ii], points[ii+1], points[ii+n+1],\n                                        values[ii], values[ii+1], values[ii+n+1]);\n                          DrawIsoLines (points[ii+1], points[ii+n+2], points[ii+n+1],\n                                        values[ii+1], values[ii+n+2], values[ii+n+1]);\n                        }       \n                  }\n              }\n            glEnd();\n          }\n        glEndList ();\n\n        if (clipplane_isolinelist) glDeleteLists (clipplane_isolinelist, 1);\n\n        if (vispar.clipping.enable && clipsolution == 1 && sol)\n          {\n            clipplane_isolinelist = glGenLists (1);\n            glNewList (clipplane_isolinelist, GL_COMPILE);\n\n            NgArray<ClipPlaneTrig> cpt;\n            NgArray<ClipPlanePoint> pts;\n            GetClippingPlaneTrigs (sol, cpt, pts);\n            bool drawelem;\n          \n            glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]);\n            glBegin (GL_LINES);\n            \n            if (numisolines)\n              for (int i = 0; i < cpt.Size(); i++)\n                {\n                  const ClipPlaneTrig & trig = cpt[i];\n                  double vali[3];\n                  for (int j = 0; j < 3; j++)\n                    {\n                      Point<3> lami = pts[trig.points[j].pnr].lami;\n                      drawelem = GetValue (sol, trig.elnr, lami(0), lami(1), lami(2),\n                                           scalcomp, vali[j]);\n                    }\n                  if ( drawelem )\n                    DrawIsoLines (pts[trig.points[0].pnr].p,\n                                  pts[trig.points[1].pnr].p,\n                                  pts[trig.points[2].pnr].p,\n                                  vali[0], vali[1], vali[2]);\n                }\n            glEnd();\n            glEndList ();\n          }\n      }\n  \n    clipplanetimestamp = max2 (vispar.clipping.timestamp, solutiontimestamp);\n      }\n    catch (const bad_weak_ptr & e)\n      {\n        PrintMessage (3, \"vssolution::buildscene: don't have a mesh to visualize\");\n        VisualScene::BuildScene (zoomall);\n      }\n  }\n  \n  void  VisualSceneSolution :: Draw1DElements ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (element1dlist)\n      glDeleteLists (element1dlist, 1);\n \n    element1dlist = glGenLists (1);\n    glNewList (element1dlist, GL_COMPILE);\n\n    int npt = (1 << subdivisions) + 1;\n    NgArray<double> pref(npt), values(npt);\n    NgArray<Point<3> > points(npt);\n\n    const SolData * sol = NULL;\n    if (scalfunction != -1) sol = soldata[scalfunction];\n\n    const SolData * vsol = NULL;\n    if (deform && vecfunction != -1) vsol = soldata[vecfunction];\n\n    int ncomp = 0;\n    if (sol) ncomp = sol->components;\n    if (vsol) ncomp = vsol->components;\n    NgArray<double> mvalues(ncomp);\n\n\n    for (int i = 0; i < npt; i++)\n      pref[i] = double(i) / (npt-1);\n    int meshdim = mesh->GetDimension();\n    for (SegmentIndex i = 0; i < mesh -> GetNSeg(); i++)\n      {\n        // mesh->GetCurvedElements().\n        // CalcMultiPointSegmentTransformation (&pref, i, &points, NULL);\n        // const Segment & seg = mesh -> LineSegment(i);\n        for (int j = 0; j < npt; j++)\n          mesh->GetCurvedElements().\n            CalcSegmentTransformation (pref[j], i, points[j]);\n        if (vsol)\n          {\n            for (int j = 0; j < npt; j++)\n              {\n                vsol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]);\n                // values[j] = ExtractValue (sol, scalcomp, &mvalues[0]);\n                for (int k = 0; k < min(ncomp, 3); k++)\n                  points[j](k) += scaledeform * mvalues[k];\n                // points[j](0) += scaledeform * mvalues[0];\n                // points[j](1) += scaledeform * mvalues[1];\n              }\n          }\n        else if (sol && meshdim <= 2)\n          {\n            for (int j = 0; j < npt; j++)\n              {\n                sol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]);\n                values[j] = ExtractValue (sol, scalcomp, &mvalues[0]);\n                points[j](meshdim) += scaledeform * values[j];\n              }\n          }\n\n        glBegin (GL_LINE_STRIP);\n        for (int i = 0; i < npt; i++)\n          glVertex3dv (points[i]);\n        glEnd();\n      }\n\n    glEndList ();\n  }\n  \n  void  VisualSceneSolution :: DrawSurfaceElements ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    static int timer = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements\");\n    /*\n    static int timerstart = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements start\");\n    static int timerloops = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements loops\");\n    static int timerlist = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements list\");\n    static int timerbuffer = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements buffer\");\n    static int timer1 = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 1\");\n    static int timer1a = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 1a\");\n    static int timer1b = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 1b\");\n    static int timer1c = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 1c\");\n    static int timer2 = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 2\");\n    static int timer2a = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 2a\");\n    static int timer2b = NgProfiler::CreateTimer (\"Solution::DrawSurfaceElements 2b\");\n    */\n    NgProfiler::RegionTimer reg (timer);\n  \n    \n#ifdef PARALLELGL\n\n    if (id == 0 && ntasks > 1)\n      {\n\tInitParallelGL();\n\n\tpar_surfellists.SetSize (ntasks);\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"solsurfellist\");\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  MyMPI_Recv (par_surfellists[dest], dest, NG_MPI_TAG_VIS);\n\n\tif (surfellist)\n\t  glDeleteLists (surfellist, 1);\n\n\tsurfellist = glGenLists (1);\n\tglNewList (surfellist, GL_COMPILE);\n\t\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  glCallList (par_surfellists[dest]);\n\t\n\tglEndList();\n\treturn;\n      }\n#endif\n\n    // NgProfiler::StartTimer(timerstart);\n\n    if (surfellist)\n      glDeleteLists (surfellist, 1);\n    \n    surfellist = glGenLists (1);\n    glNewList (surfellist, GL_COMPILE);\n\n    \n    const SolData * sol = NULL;\n    \n    if (scalfunction != -1)\n      sol = soldata[scalfunction];\n    \n    if (mesh->GetTimeStamp () > solutiontimestamp)\n      sol = NULL;\n\n    if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent);\n\n\n\n    glLineWidth (1.0f);\n\n    GLfloat col_grey[] = { 0.6f, 0.6f, 0.6f, 1.0f };\n    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col_grey);\n        \n\n    int nse = mesh->GetNSE();\n\n    SetTextureMode (usetexture);\n\n    CurvedElements & curv = mesh->GetCurvedElements();\n\n    int n = 1 << subdivisions;\n    int npt = sqr(n+1);\n\n    NgArray<Point<2> > pref (npt);\n    NgArray<Point<3> > points (npt);\n    NgArray<Mat<3,2> > dxdxis (npt);\n    NgArray<Vec<3> > nvs(npt);\n    NgArray<double> values(npt);\n\n    NgArray<double> mvalues(npt);\n    int sol_comp = (sol && sol->draw_surface) ? sol->components : 0;\n    NgArray<Point<2,SIMD<double>> > simd_pref ( (npt+SIMD<double>::Size()-1)/SIMD<double>::Size() );\n    NgArray<Point<3,SIMD<double>> > simd_points ( (npt+SIMD<double>::Size()-1)/SIMD<double>::Size() );\n    NgArray<Mat<3,2,SIMD<double>> > simd_dxdxis ( (npt+SIMD<double>::Size()-1)/SIMD<double>::Size() );\n    NgArray<Vec<3,SIMD<double>> > simd_nvs( (npt+SIMD<double>::Size()-1)/SIMD<double>::Size() );\n    NgArray<SIMD<double>> simd_values( (npt+SIMD<double>::Size()-1)/SIMD<double>::Size() * sol_comp);\n\n    \n    \n    // NgArray<Point<3,float>> glob_pnts;\n    // NgArray<Vec<3,float>> glob_nvs;\n    // NgArray<double> glob_values;\n    \n    if (sol && sol->draw_surface) mvalues.SetSize (npt * sol->components);\n      \n    NgArray<complex<double> > valuesc(npt);\n    \n#ifdef USE_BUFFERS\n    if (has_surfel_vbo)\n      glDeleteBuffers (4, &surfel_vbo[0]);\n    glGenBuffers (4, &surfel_vbo[0]);\n\n    has_surfel_vbo = true;\n    glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]);\n    glBufferData (GL_ARRAY_BUFFER,\n                  nse*npt*sizeof(Point<3,double>),\n                  NULL, GL_STATIC_DRAW);\n    glVertexPointer(3, GL_DOUBLE, 0, 0); \n    // glEnableClientState(GL_VERTEX_ARRAY);\n    \n    glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]);\n    glBufferData (GL_ARRAY_BUFFER,\n                  nse*npt*sizeof(Vec<3,double>),\n                  NULL, GL_STATIC_DRAW);\n    // glEnableClientState(GL_NORMAL_ARRAY);\n    glNormalPointer(GL_DOUBLE, 0, 0);  \n\n    // glEnableClientState(GL_TEXTURE_COORD_ARRAY);\n    glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]);\n    glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(double), NULL, GL_STATIC_DRAW);\n    glTexCoordPointer(1, GL_DOUBLE, 0, 0);\n    \n    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]);\n    glBufferData(GL_ELEMENT_ARRAY_BUFFER, nse*npt*6*sizeof(int), NULL, GL_STATIC_DRAW);\n    surfel_vbo_size = 0;\n#endif\n    \n    \n    // NgProfiler::StopTimer(timerstart);\n    auto sol_active = GetScalOrVecFunction();\n    \n    for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n      {\n        const Element2d & el = (*mesh)[sei];\n\n        if(!SurfaceElementActive(sol_active, *mesh, el))\n          continue;\n\n        if ( el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 )\n          {\n            bool curved = curv.IsSurfaceElementCurved (sei);\n\n\n            for (int iy = 0, ii = 0; iy <= n; iy++)\n              for (int ix = 0; ix <= n; ix++, ii++)\n                pref[ii] = Point<2> (double(ix)/n, double(iy)/n);\n\n            int npt = (n+1)*(n+1);\n            if (curved)\n              {\n                for (int ii = 0; ii < npt; ii++)\n                  {\n                    Point<2> xref = pref[ii];\n                    \n                    mesh->GetCurvedElements().\n                      CalcSurfaceTransformation (xref, sei, points[ii], dxdxis[ii]);\n                    nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1));\n                    nvs[ii].Normalize();\n                  }\n              }\n            else\n              {\n\t\tPoint<3> lpi[4];\n\t\tVec<3> vx, vy, vtwist;\n\t\t\n\t\tfor (int k = 0; k < 4; k++)\n\t\t  GetPointDeformation (el[k]-1, lpi[k]);\n\t\t\n\t\tvx = lpi[1]-lpi[0];\n\t\tvy = lpi[3]-lpi[0];\n\t\tvtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]);\n\n                for (int ii = 0; ii < npt; ii++)\n                  {\n                    double x = pref[ii](0);\n                    double y = pref[ii](1);\n                    points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist;\n                    for (int j = 0; j < 3; j++)\n                      {\n                        dxdxis[ii](j,0) = vx(j) + y*vtwist(j);\n                        dxdxis[ii](j,1) = vy(j) + x*vtwist(j);\n                      }\n                  }\n\n                Vec<3> nv = Cross (vx, vy);\n                nv.Normalize();\n                for (int ii = 0; ii < npt; ii++)\n                  nvs[ii] = nv;\n              }\n\n\n            bool drawelem = false;\n\t    /*\n            if (sol && sol->draw_surface) \n              {\n                if (usetexture == 2)\n                  for (int ii = 0; ii < npt; ii++)\n                    drawelem = GetSurfValueComplex (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, valuesc[ii]);\n                else\n                  for (int ii = 0; ii < npt; ii++)\n                    drawelem = GetSurfValue (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, values[ii]);\n              }\n\t    */\n            if (sol && sol->draw_surface) \n              {\n\t\tdrawelem = GetMultiSurfValues (sol, sei, -1, npt, \n\t\t\t\t\t       &pref[0](0), &pref[1](0)-&pref[0](0),\n\t\t\t\t\t       &points[0](0), &points[1](0)-&points[0](0),\n\t\t\t\t\t       &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0),\n\t\t\t\t\t       &mvalues[0], sol->components);\n                if (usetexture == 2)\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]);\n                else\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]);\n              }\n\n            \n            if (deform)\n              for (int ii = 0; ii < npt; ii++)\n                points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1));\n\n\n            int save_usetexture = usetexture;\n            if (!drawelem)\n              {\n                usetexture = 0;\n                SetTextureMode (0);\n              }\n\n            int ii = 0;\n\n            glBegin (GL_QUADS);\n\n            for (int iy = 0; iy < n; iy++, ii++)\n              for (int ix = 0; ix < n; ix++, ii++)\n                {\n                  int index[] = { ii, ii+1, ii+n+2, ii+n+1 };\n                  \n                  for (int j = 0; j < 4; j++)\n                    {\n                      if (drawelem)\n                        {\n                          if (usetexture != 2)\n                            SetOpenGlColor  (values[index[j]]);\n                          else\n                            glTexCoord2f ( valuesc[index[j]].real(),\n                                           valuesc[index[j]].imag() );\n                        }\n                      else\n                        glColor4fv (col_grey);\n                      \n                      glNormal3dv (nvs[index[j]]);\n                      glVertex3dv (points[index[j]]);\n                    }\n                }\n            glEnd();\n\n            if (!drawelem && (usetexture != save_usetexture))\n              {\n                usetexture = save_usetexture;\n                SetTextureMode (usetexture);\n              }\n\n          }\n      }\n\n    n = 1 << subdivisions;\n    double invn = 1.0 / n;\n    npt = (n+1)*(n+2)/2;\n    // NgProfiler::StartTimer(timerloops);\n    size_t base_pi = 0;\n\n    for (int iy = 0, ii = 0; iy <= n; iy++)\n      for (int ix = 0; ix <= n-iy; ix++, ii++)\n        pref[ii] = Point<2> (ix*invn, iy*invn);\n    \n    constexpr size_t simd_size = SIMD<double>::Size();\n    size_t simd_npt = (npt+simd_size-1)/simd_size;\n    \n    for (size_t i = 0; i < simd_npt; i++)\n      {\n        simd_pref[i](0) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](0) : 0; };\n        simd_pref[i](1) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](1) : 0; };\n      }\n\n    NgArray<int> ind_reftrig;\n    for (int iy = 0, ii = 0; iy < n; iy++,ii++)\n      for (int ix = 0; ix < n-iy; ix++, ii++)\n        {\n          int nv = (ix+iy+1 < n) ? 6 : 3;\n          int ind[] = { ii, ii+1, ii+n-iy+1,  \n                        ii+n-iy+1, ii+1, ii+n-iy+2 };\n          for (int j = 0; j < nv; j++)\n            ind_reftrig.Append (ind[j]);\n        }\n    NgArray<int> glob_ind;\n    glob_ind.SetSize(ind_reftrig.Size());    \n\n    \n    for(SurfaceElementIndex sei = 0; sei < nse; sei++)\n      {\n        const Element2d & el = (*mesh)[sei];\n\t// if (el.GetIndex() <= 1) continue;\n\n        if(!SurfaceElementActive(sol_active, *mesh, el))\n          continue;\n        \n        if ( el.GetType() == TRIG || el.GetType() == TRIG6 )\n          {\n            // NgProfiler::StartTimer(timer1);\n#ifdef __AVX_try_it_out__\n            // NgProfiler::StartTimer(timer1a);            \n\t    bool curved = curv.IsSurfaceElementCurved(sei);\n            \n            if (curved)\n              {\n                mesh->GetCurvedElements().\n                  CalcMultiPointSurfaceTransformation<3> (sei, simd_npt,\n                                                          &simd_pref[0](0), 2,\n                                                          &simd_points[0](0), 3,\n                                                          &simd_dxdxis[0](0,0), 6);\n                \n                for (size_t ii = 0; ii < simd_npt; ii++)\n                  simd_nvs[ii] = Cross (simd_dxdxis[ii].Col(0), simd_dxdxis[ii].Col(1)).Normalize();\n              }\n            else\n              {\n\t\tPoint<3,SIMD<double>> p1 = mesh->Point (el[0]);\n\t\tPoint<3,SIMD<double>> p2 = mesh->Point (el[1]);\n\t\tPoint<3,SIMD<double>> p3 = mesh->Point (el[2]);\n\n                Vec<3,SIMD<double>> vx = p1-p3;\n                Vec<3,SIMD<double>> vy = p2-p3;\n                for (size_t ii = 0; ii < simd_npt; ii++)\n                  {\n                    simd_points[ii] = p3 + simd_pref[ii](0) * vx + simd_pref[ii](1) * vy;\n                    for (size_t j = 0; j < 3; j++)\n                      {\n                        simd_dxdxis[ii](j,0) = vx(j);\n                        simd_dxdxis[ii](j,1) = vy(j);\n                      }\n                  }\n\n                Vec<3,SIMD<double>> nv = Cross (vx, vy).Normalize();\n                for (size_t ii = 0; ii < simd_npt; ii++)\n                  simd_nvs[ii] = nv;\n              }\n\n\n            bool drawelem = false;\n            if (sol && sol->draw_surface) \n              {\n                // NgProfiler::StopTimer(timer1a);\n                // NgProfiler::StartTimer(timer1b);            \n\t\tdrawelem = sol->solclass->GetMultiSurfValue (sei, -1, simd_npt, \n                                                             &simd_pref[0](0).Data(),\n                                                             &simd_points[0](0).Data(),\n                                                             &simd_dxdxis[0](0).Data(),\n                                                             &simd_values[0].Data());\n                // NgProfiler::StopTimer(timer1b);\n                // NgProfiler::StartTimer(timer1c);            \n\n                for (size_t j = 0; j < sol->components; j++)\n                  for (size_t i = 0; i < npt; i++)\n                    mvalues[i*sol->components+j] = ((double*)&simd_values[j*simd_npt])[i];\n\n                if (usetexture == 2)\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]);\n                else\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]);\n              }\n\n            for (size_t i = 0; i < npt; i++)\n              {\n                size_t ii = i/4;\n                size_t r = i%4;\n                for (int j = 0; j < 2; j++)\n                  pref[i](j) = simd_pref[ii](j)[r];\n                for (int j = 0; j < 3; j++)\n                  points[i](j) = simd_points[ii](j)[r];\n                for (int j = 0; j < 3; j++)\n                  nvs[i](j) = simd_nvs[ii](j)[r];\n              }\n\n            if (deform)\n              for (int ii = 0; ii < npt; ii++)\n                points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1));\n\n            // NgProfiler::StopTimer(timer1c);\n            \n#else\n\t    bool curved = (*mesh)[sei].IsCurved();\n\n            for (int iy = 0, ii = 0; iy <= n; iy++)\n              for (int ix = 0; ix <= n-iy; ix++, ii++)\n                pref[ii] = Point<2> (ix*invn, iy*invn);\n\n            if (curved)\n              {\n                mesh->GetCurvedElements().\n                  CalcMultiPointSurfaceTransformation (&pref, sei, &points, &dxdxis);\n\n                for (int ii = 0; ii < npt; ii++)\n                  nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1)).Normalize();\n              }\n            else\n              {\n\t\tPoint<3> p1 = mesh->Point (el[0]);\n\t\tPoint<3> p2 = mesh->Point (el[1]);\n\t\tPoint<3> p3 = mesh->Point (el[2]);\n\n                Vec<3> vx = p1-p3;\n                Vec<3> vy = p2-p3;\n                for (int ii = 0; ii < npt; ii++)\n                  {\n                    points[ii] = p3 + pref[ii](0) * vx + pref[ii](1) * vy;\n                    for (int j = 0; j < 3; j++)\n                      {\n                        dxdxis[ii](j,0) = vx(j);\n                        dxdxis[ii](j,1) = vy(j);\n                      }\n                  }\n\n                Vec<3> nv = Cross (vx, vy).Normalize();\n                for (int ii = 0; ii < npt; ii++)\n                  nvs[ii] = nv;\n              }\n\n            bool drawelem = false;\n            if (sol && sol->draw_surface) \n              {\n\t\tdrawelem = GetMultiSurfValues (sol, sei, -1, npt, \n\t\t\t\t\t       &pref[0](0), &pref[1](0)-&pref[0](0),\n\t\t\t\t\t       &points[0](0), &points[1](0)-&points[0](0),\n\t\t\t\t\t       &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0),\n\t\t\t\t\t       &mvalues[0], sol->components);\n                if (usetexture == 2)\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]);\n                else\n\t\t  for (int ii = 0; ii < npt; ii++)\n\t\t    values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]);\n              }\n            \n            if (deform)\n              for (int ii = 0; ii < npt; ii++)\n                points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1));\n#endif\n            // NgProfiler::StopTimer(timer1);\n\n            int save_usetexture = usetexture;\n            if (!drawelem)\n              {\n                usetexture = 0;\n                SetTextureMode (usetexture);\n              }\n\n            // NgProfiler::StartTimer(timer2);\n\n#ifdef USE_BUFFERS\n            if (drawelem && usetexture == 1 && !logscale)\n              {\n                glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]);            \n                glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Point<3,double>),\n                                 npt*sizeof(Point<3,double>), &points[0][0]);\n                glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]);            \n                glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Vec<3,double>),\n                                 npt*sizeof(Vec<3,double>), &nvs[0][0]);\n                glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]);            \n                glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(double),\n                                 npt*sizeof(double), &values[0]);\n                \n                for (size_t i = 0; i < ind_reftrig.Size(); i++)\n                  glob_ind[i] = base_pi+ind_reftrig[i];\n                \n                glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]);            \n                glBufferSubData (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo_size*sizeof(int),\n                                 ind_reftrig.Size()*sizeof(int), &glob_ind[0]);\n                surfel_vbo_size += ind_reftrig.Size();\n                base_pi += npt;\n              }\n              \n            else\n#endif\n              for (int iy = 0, ii = 0; iy < n; iy++)\n                {\n                  glBegin (GL_TRIANGLE_STRIP);\n                  for (int ix = 0; ix <= n-iy; ix++, ii++)\n                    for (int k = 0; k < 2; k++)\n                      {\n                        if (ix+iy+k > n) continue;\n                        int hi = (k == 0) ? ii : ii+n-iy+1;\n                        if (drawelem)\n                          {\n                            if (usetexture != 2)\n                              SetOpenGlColor (values[hi]); \n                            else\n                              glTexCoord2f ( valuesc[hi].real(), valuesc[hi].imag() );\n                          }\n                        else\n                          glColor4fv (col_grey);\n                        \n                        glNormal3dv (nvs[hi]);\n                        glVertex3dv (points[hi]);\n                      }\n                  glEnd();\n                }\n            \n            // NgProfiler::StopTimer(timer2);            \n\n\n\n            \n            if (!drawelem && (usetexture != save_usetexture))\n              {\n                usetexture = save_usetexture;\n                SetTextureMode (usetexture);\n              }\n\t  }\n      }\n    // NgProfiler::StopTimer(timerloops);\n\n    // NgProfiler::StartTimer(timerbuffer);\n\n    // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]);\n    // glBufferData(GL_ELEMENT_ARRAY_BUFFER, glob_ind.Size()*sizeof(int), &glob_ind[0], GL_STATIC_DRAW);\n    // surfel_vbo_size = glob_ind.Size();\n \n    // NgProfiler::StopTimer(timerbuffer);        \n\n    // glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0);\n\n    // glDrawElements(GL_TRIANGLES, glob_ind.Size(), GL_UNSIGNED_INT, &glob_ind[0]);\n    \n    // glDisableClientState(GL_VERTEX_ARRAY);\n    // glDisableClientState(GL_NORMAL_ARRAY);\n    // glDisableClientState(GL_TEXTURE_COORD_ARRAY);\n\n    // glDeleteBuffers (1, &IndexVBOID);    \n    // glDeleteBuffers (4, &vboId[0]);\n\n    \n    // NgProfiler::StartTimer(timerlist);\n    glEndList ();\n    // NgProfiler::StopTimer(timerlist);\n    \n#ifdef PARALLELGL\n    glFinish();\n    if (id > 0)\n      MyMPI_Send (surfellist, 0, NG_MPI_TAG_VIS);\n#endif\n  }\n\n\n  void  VisualSceneSolution :: DrawSurfaceElementLines ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n#ifdef PARALLELGL\n    if (id == 0 && ntasks > 1)\n      {\n\tInitParallelGL();\n\n\tpar_surfellists.SetSize (ntasks);\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"solsurfellinelist\");\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  MyMPI_Recv (par_surfellists[dest], dest, NG_MPI_TAG_VIS);\n\n\tif (linelist)\n\t  glDeleteLists (linelist, 1);\n\n\tlinelist = glGenLists (1);\n\tglNewList (linelist, GL_COMPILE);\n\t\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  glCallList (par_surfellists[dest]);\n\t\n\tglEndList();\n\treturn;\n      }\n#endif\n\n    if (linelist)\n      glDeleteLists (linelist, 1);\n    \n    linelist = glGenLists (1);\n    glNewList (linelist, GL_COMPILE);\n\n    glLineWidth (1.0f);\n\n    int nse = mesh->GetNSE();\n    CurvedElements & curv = mesh->GetCurvedElements();\n\n    int n = 1 << subdivisions;\n    NgArrayMem<Point<2>, 65> ptsloc(n+1);\n    NgArrayMem<Point<3>, 65> ptsglob(n+1);\n\n    double trigpts[3][2]  = { { 0, 0 }, { 0, 1 }, { 1, 0} };\n    double trigvecs[3][2] = { { 1, 0 }, { 0, -1 }, { -1, 1} };\n\n    double quadpts[4][2]  = { { 0, 0 },  { 1, 1 }, { 0, 1}, { 1, 0 } };\n    double quadvecs[4][2] = { { 1, 0 },  { -1, 0}, { 0, -1}, { 0, 1 } };\n\n    auto sol_active = GetScalOrVecFunction();\n\n    for (SurfaceElementIndex sei = 0; sei < nse; sei++)\n      {\n        Element2d & el = (*mesh)[sei];\n\n        if(!SurfaceElementActive(sol_active, *mesh, el))\n            continue;\n\n        int nv = (el.GetType() == TRIG || el.GetType() == TRIG6) ? 3 : 4;\n        for (int k = 0; k < nv; k++)\n          {\n            Point<2> p0;\n            Vec<2> vtau;\n            if (nv == 3)\n\t      {\n\t\tp0 = Point<2>(trigpts[k][0], trigpts[k][1]);\n\t\tvtau = Vec<2>(trigvecs[k][0], trigvecs[k][1]);\n\t      }\n            else\n\t      {\n\t\tp0 = Point<2>(quadpts[k][0], quadpts[k][1]);\n\t\tvtau = Vec<2>(quadvecs[k][0], quadvecs[k][1]);\n\t      }\n\n            glBegin (GL_LINE_STRIP);\n\n\t    for (int ix = 0; ix <= n; ix++)\n\t      ptsloc[ix] = p0 + (double(ix) / n) * vtau;\n\t    \n\t    curv.CalcMultiPointSurfaceTransformation (&ptsloc, sei, &ptsglob, 0);\n\t    \n\t    for (int ix = 0; ix <= n; ix++)\n\t      {\n\t\tif (deform)\n\t\t  ptsglob[ix] += GetSurfDeformation (sei, k, ptsloc[ix](0), ptsloc[ix](1));\n\t\tglVertex3dv (ptsglob[ix]);\n\t      }\n\t    \n            glEnd ();\n          }\n      }\n    glEndList ();\n\n\n#ifdef PARALLELGL\n    glFinish();\n    if (id > 0)\n      MyMPI_Send (linelist, 0, NG_MPI_TAG_VIS);\n#endif\n  }\n\n\n\n\n\n\n\n\n\n  void VisualSceneSolution :: DrawIsoSurface(const SolData * sol, \n                                             const SolData * vsol,\n                                             int comp)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if (!draw_isosurface) return;\n    if (!sol) return;\n\n   \n    SetTextureMode (0);\n    glColor3d (1.0, 0, 0);\n    glEnable (GL_COLOR_MATERIAL);\n\n\n    glBegin (GL_TRIANGLES);\n\n    int ne = mesh->GetNE();\n\n    const int edgei[6][2] =\n      { { 0, 1 }, { 0, 2 }, { 0, 3 },\n        { 1, 2 }, { 1, 3 }, { 2, 3 } };\n    \n    double edgelam[6];\n    Point<3> edgep[6];\n    Vec<3> normp[6];\n    double nodevali[4];\n    \n    int cntce;\n    int cpe1 = 0, cpe2 = 0, cpe3 = 0;\n    \n    int n = 1 << subdivisions;\n    int n3 = (n+1)*(n+1)*(n+1);\n    \n    NgArray<Point<3> > grid(n3);\n    NgArray<Point<3> > locgrid(n3);\n    NgArray<Mat<3,3> > trans(n3);\n    NgArray<double> val1(n3*sol->components);\n    NgArray<Vec<3> > grads1(n3);\n    NgArray<int> compress(n3);\n    \n    MatrixFixWidth<3> pointmat(8);\n    grads1 = Vec<3> (0.0);\n\n    for (ElementIndex ei = 0; ei < ne; ei++)\n      {\n        // if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue;\n        // if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue;\n\n        const Element & el = (*mesh)[ei];\n        if(!VolumeElementActive(sol, *mesh, el))\n          continue;\n\n        ELEMENT_TYPE type = el.GetType();\n        if (type == HEX || type == PRISM || type == TET || type == PYRAMID)\n          {\n            int ii = 0;\n            int cnt_valid = 0;\n            \n            for (int ix = 0; ix <= n; ix++)\n              for (int iy = 0; iy <= n; iy++)\n                for (int iz = 0; iz <= n; iz++, ii++)\n                  {\n                    Point<3> ploc;\n                    compress[ii] = ii;\n                    \n                    switch (type)\n                      {\n                      case PRISM:\n                        if (ix+iy <= n)\n                          {\n                            ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                            compress[ii] = cnt_valid;\n                            cnt_valid++;\n                          }\n                        else\n                          compress[ii] = -1;\n                        break;\n                      case TET:\n                        if (ix+iy+iz <= n)\n                          {\n                            ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                            compress[ii] = cnt_valid;\n                            cnt_valid++;\n                          }\n                        else\n                          compress[ii] = -1;\n                        break;\n                      case HEX:\n                        ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                        break;\n                      case PYRAMID:\n                        ploc = Point<3> (double(ix) / n * (1-double(iz)/n),\n                                         double(iy) / n * (1-double(iz)/n),\n                                         double(iz)/n);\n                        break;\n                      default:\n                        cerr << \"case not implemented 878234\" << endl;\n                        ploc = 0.0;\n                      }\n                    if (compress[ii] != -1)\n                      locgrid[compress[ii]] = ploc;\n                  }\n            \n            if (type != TET && type != PRISM) cnt_valid = n3;\n            \n            \n            if (mesh->GetCurvedElements().IsHighOrder() || 1)\n              {\n                mesh->GetCurvedElements().\n                  CalcMultiPointElementTransformation (&locgrid, ei, &grid, &trans);\n              }\n            else\n              {\n                Vector shape(el.GetNP());\n                for (int k = 0; k < el.GetNP(); k++)\n                  for (int j = 0; j < 3; j++)\n                    pointmat(k,j) = (*mesh)[el[k]](j);\n                \n                for (int i = 0; i < cnt_valid; i++)\n                  {\n                    el.GetShapeNew<double> (locgrid[i], shape);\n                    Point<3> pglob;\n                    for (int j = 0; j < 3; j++)\n                      {\n                        pglob(j) = 0;\n                        for (int k = 0; k < el.GetNP(); k++)\n                          pglob(j) += shape(k) * pointmat(k,j);\n                      }\n                    grid[i] = pglob;\n                  }\n              }\n\n            bool has_pos = 0, has_neg = 0;\n            GetMultiValues( sol, ei, -1, n3, \n                            &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0),\n                            &grid[0](0), &grid[1](0)-&grid[0](0),\n                            &trans[0](0), &trans[1](0)-&trans[0](0),\n                            &val1[0], sol->components);\n            for (int i = 0; i < cnt_valid; i++)\n              {\n                // GetValue (sol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), comp, val[i]);\n\n                // val[i] -= minval;\n                val1[sol->components*i+comp-1] -= minval;\n\n\n                // if (vsol)\n                  // GetValues (vsol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), &grads[i](0));\n                // grads[i] *= -1;\n\n                if (val1[i*sol->components+comp-1] > 0)\n                  has_pos = 1;\n                else\n                  has_neg = 1;\n                // if (val[i] > 0)\n                  // has_pos = 1;\n                // else\n                  // has_neg = 1;\n              }\n\n            if (!has_pos || !has_neg) continue;\n            if (vsol)\n            {\n              GetMultiValues(vsol, ei, -1, n3,\n                           &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0),\n                           &grid[0](0), &grid[1](0)-&grid[0](0),\n                           &trans[0](0), &trans[1](0)-&trans[0](0),\n                           &grads1[0](0), vsol->components);\n              // for (int i = 0; i < cnt_valid; i++)\n                // grads1[i*sol->components+comp-1] *= -1;\n              for (int i = 0; i < cnt_valid; i++)\n                grads1[i] *= -1;\n                \n            }\n            for (int ix = 0; ix < n; ix++)\n              for (int iy = 0; iy < n; iy++)\n                for (int iz = 0; iz < n; iz++)\n                  {\n                    int base = iz + (n+1)*iy + (n+1)*(n+1)*ix;\n                    int pi[8] = \n                      { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1),\n                        base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 };\n                    \n                    for (int j = 0; j < 8; j++)\n                      pi[j] = compress[pi[j]];\n                    \n                    int tets[6][4] = \n                      { { 1, 2, 4, 5 },\n                        { 4, 5, 2, 8 },\n                        { 2, 8, 5, 6 },\n                        { 2, 3, 4, 8 },\n                        { 2, 3, 8, 6 },\n                        { 3, 8, 6, 7 } };\n                    \n                    for (int ii = 0; ii < 6; ii++)\n                      {\n                        int teti[4];\n                        for (int k = 0; k < 4; k++)\n                          teti[k] = pi[tets[ii][k]-1];\n                        \n                        bool is_valid = 1;\n                        for (int j = 0; j < 4; j++)\n                          if (teti[j] == -1) is_valid = 0;\n                        \n                        if (!is_valid) continue;\n                        \n                        // for (int j = 0; j < 4; j++)\n                          // nodevali[j] = val[teti[j]];\n                        for (int j = 0; j < 4; j++)\n                          nodevali[j] = val1[sol->components*teti[j]+comp-1];\n                        \n                        cntce = 0;\n                        for (int j = 0; j < 6; j++)\n                          {\n                            int lpi1 = edgei[j][0];\n                            int lpi2 = edgei[j][1];\n                            if ( (nodevali[lpi1] > 0) !=\n                                 (nodevali[lpi2] > 0) )\n                              {\n                                Point<3> p1 = grid[teti[lpi1]];\n                                Point<3> p2 = grid[teti[lpi2]];\n\n                                edgelam[j] = nodevali[lpi2] / (nodevali[lpi2] - nodevali[lpi1]);\n                                edgep[j] = grid[teti[lpi1]] + (1-edgelam[j]) * (grid[teti[lpi2]]-grid[teti[lpi1]]);\n                                // normp[j] = grads[teti[lpi1]] + (1-edgelam[j]) * (grads[teti[lpi2]]-grads[teti[lpi1]]);\n                                normp[j] = grads1[teti[lpi1]] + (1-edgelam[j]) * (grads1[teti[lpi2]]-grads1[teti[lpi1]]);\n                                // normp[j] = grads1[sol->components*teti[lpi1]+comp-1] + (1-edgelam[j]) * (grads1[sol->components*teti[lpi2]+comp-1]-grads1[sol->components*teti[lpi1]+comp-1]);\n                                cntce++;\n                                cpe3 = cpe2;\n                                cpe2 = cpe1;\n                                cpe1 = j;\n                                if (cntce >= 3)\n                                  {\n                                    if (!vsol)\n                                      {\n                                        Point<3> points[3];\n                                        \n                                        points[0] = edgep[cpe1];\n                                        points[1] = edgep[cpe2];\n                                        points[2] = edgep[cpe3];\n\n                                        Vec<3> normal = Cross (points[2]-points[0], points[1]-points[0]);\n                                        if ( ( (normal * (p2-p1)) > 0 ) == ( nodevali[lpi1] < 0) )\n                                          normal *= -1;\n                                        glNormal3dv (normal);\n\n                                        glVertex3dv (points[0]);\n                                        glVertex3dv (points[1]);\n                                        glVertex3dv (points[2]);\n                                      }\n                                    else\n                                      {\n                                        glNormal3dv (normp[cpe1]);\n                                        glVertex3dv (edgep[cpe1]);\n                                        glNormal3dv (normp[cpe2]);\n                                        glVertex3dv (edgep[cpe2]);\n                                        glNormal3dv (normp[cpe3]);\n                                        glVertex3dv (edgep[cpe3]);\n                                      }\n                                  }\n                              }\n                          }\n                      }\n                  }\n          }\n      }\n    glEnd();\n  }\n    \n\n\n\n\n\n\n\n  void  VisualSceneSolution :: DrawTrigSurfaceVectors(const NgArray< Point<3> > & lp, \n                                                      const Point<3> & pmin, const Point<3> & pmax,\n                                                      const int sei, const SolData * vsol, bool swap_lam)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    int dir,dir1,dir2;\n    double s,t;\n\n    Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]);\n    Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2)));\n    if (na(0) > na(1) && na(0) > na(2))\n      dir = 1;\n    else if (na(1) > na(2))\n      dir = 2;\n    else \n      dir = 3;\n    \n    dir1 = (dir % 3) + 1;\n    dir2 = (dir1 % 3) + 1;\n\n    Point<2> p2d[3];\n\n    int k;\n\n    for (k = 0; k < 3; k++)\n      {\n        p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad),\n                           (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad));\n      }\n\n    \n    double minx2d, maxx2d, miny2d, maxy2d;\n    minx2d = maxx2d = p2d[0](0);\n    miny2d = maxy2d = p2d[0](1);\n    for (k = 1; k < 3; k++)\n      {\n        minx2d = min2 (minx2d, p2d[k](0));\n        maxx2d = max2 (maxx2d, p2d[k](0));\n        miny2d = min2 (miny2d, p2d[k](1));\n        maxy2d = max2 (maxy2d, p2d[k](1));\n      }\n    \n    double mat11 = p2d[1](0) - p2d[0](0);\n    double mat21 = p2d[1](1) - p2d[0](1);\n    double mat12 = p2d[2](0) - p2d[0](0);\n    double mat22 = p2d[2](1) - p2d[0](1);\n    \n    double det = mat11*mat22-mat21*mat12;\n    double inv11 = mat22/det;\n    double inv21 = -mat21/det;\n    double inv12 = -mat12/det;\n    double inv22 = mat11/det;\n          \n    //    cout << \"drawsurfacevectors. xoffset = \" << xoffset << \", yoffset = \";\n    //    cout << yoffset << endl;\n    \n    for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize)\n      if (s >= minx2d && s <= maxx2d)\n        for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize)\n          if (t >= miny2d && t <= maxy2d)\n            {\n              double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1));\n              double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1));\n              \n              if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1)\n                {\n                  if(swap_lam)\n                  {\n                    Swap(lam1, lam2);\n                    lam1 = 1.0-lam1;\n                    lam2 = 1.0-lam2;\n                  }\n                  Point<3> cp;\n                  for (k = 0; k < 3; k++)\n                    cp(k) = lp[0](k) + \n                      lam1 * (lp[1](k)-lp[0](k)) + \n                      lam2 * (lp[2](k)-lp[0](k));\n                  Point<2> xref(lam1, lam2);\n                  if (mesh->GetCurvedElements().IsHighOrder())\n                    mesh->GetCurvedElements().\n                      CalcSurfaceTransformation (xref, sei, cp);\n                  \n                  Vec<3> v;\n                  double values[6];\n                  bool drawelem = \n                    GetSurfValues (vsol, sei, -1, lam1, lam2, values);\n                  \n                  if (!vsol->iscomplex)\n                    for (k = 0; k < 3; k++)\n                      v(k) = values[k];\n                  else\n                    {\n                      if (!imag_part)\n                        for (k = 0; k < 3; k++)\n                          v(k) = values[2*k];\n                      else\n                        for (k = 0; k < 3; k++)\n                          v(k) = values[2*k+1];\n                    }\n                  \n                  if (mesh->GetDimension() == 2)\n                    if ( (!vsol->iscomplex && vsol->components != 3) ||\n                         (vsol->iscomplex && vsol->components != 6) )\n                      v(2) = 0;\n                  \n                  double val = v.Length();\n\n                  SetOpenGlColor  (val); // (val, minval, maxval, logscale);  // change JS\n\n                  if (val > 1e-10 * maxval)\n                    v *= (rad / val / gridsize * 0.5);\n                  else \n                    drawelem = 0;\n\n                  if ( drawelem ) \n                    DrawCone (cp, cp+4*v, 0.8*rad / gridsize);\n                }\n            }\n    \n  }\n\n\n\n  void  VisualSceneSolution :: DrawSurfaceVectors ()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    SurfaceElementIndex sei;\n\n    const SolData * vsol = NULL;\n    // bool drawelem;\n\n    if (vecfunction != -1)\n      vsol = soldata[vecfunction];\n\n    if (mesh->GetTimeStamp () > solutiontimestamp)\n      vsol = NULL;\n     \n    if (!vsol) return;\n\n\n    Point<3> pmin = center - Vec3d (rad, rad, rad);\n    Point<3> pmax = center - Vec3d (rad, rad, rad);\n\n\n    // glColor3d (1.0, 1.0, 1.0);\n    // glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n\n    if (vsol->draw_surface && showsurfacesolution)\n      {\n        int nse = mesh->GetNSE();\n        for (sei = 0; sei < nse; sei++)\n          {\n            const Element2d & el = (*mesh)[sei];\n            if(!SurfaceElementActive(vsol, *mesh, el))\n              continue;\n          \n            if (el.GetType() == TRIG || el.GetType() == TRIG6)\n              {\n          \n                NgArray< Point<3> > lp(3);\n\n                lp[0] = mesh->Point(el[2]);\n                lp[1] = mesh->Point(el[0]);\n                lp[2] = mesh->Point(el[1]);\n\n                DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol);\n                \n                /*\n                  Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]);\n                  Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2)));\n                  if (na(0) > na(1) && na(0) > na(2))\n                  dir = 1;\n                  else if (na(1) > na(2))\n                  dir = 2;\n                  else \n                  dir = 3;\n\n                  dir1 = (dir % 3) + 1;\n                  dir2 = (dir1 % 3) + 1;\n          \n                  for (k = 0; k < 3; k++)\n                  {\n                  p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad),\n                  (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad));\n                  }\n          \n                  double minx2d, maxx2d, miny2d, maxy2d;\n                  minx2d = maxx2d = p2d[0](0);\n                  miny2d = maxy2d = p2d[0](1);\n                  for (k = 1; k < 3; k++)\n                  {\n                  minx2d = min2 (minx2d, p2d[k](0));\n                  maxx2d = max2 (maxx2d, p2d[k](0));\n                  miny2d = min2 (miny2d, p2d[k](1));\n                  maxy2d = max2 (maxy2d, p2d[k](1));\n                  }\n\n                  double mat11 = p2d[1](0) - p2d[0](0);\n                  double mat21 = p2d[1](1) - p2d[0](1);\n                  double mat12 = p2d[2](0) - p2d[0](0);\n                  double mat22 = p2d[2](1) - p2d[0](1);\n\n                  double det = mat11*mat22-mat21*mat12;\n                  double inv11 = mat22/det;\n                  double inv21 = -mat21/det;\n                  double inv12 = -mat12/det;\n                  double inv22 = mat11/det;\n          \n                  //      cout << \"drawsurfacevectors. xoffset = \" << xoffset << \", yoffset = \";\n                  //      cout << yoffset << endl;\n          \n                  for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize)\n                  if (s >= minx2d && s <= maxx2d)\n                  for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize)\n                  if (t >= miny2d && t <= maxy2d)\n                  {\n                  double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1));\n                  double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1));\n                    \n                  if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1)\n                  {\n                  Point<3> cp;\n                  for (k = 0; k < 3; k++)\n                  cp(k) = lp[0](k) + \n                  lam1 * (lp[1](k)-lp[0](k)) + \n                  lam2 * (lp[2](k)-lp[0](k));\n\n                  Vec<3> v;\n                  double values[6];\n                  drawelem = GetSurfValues (vsol, sei, lam1, lam2, values);\n\n                  if (!vsol->iscomplex)\n                  for (k = 0; k < 3; k++)\n                  v(k) = values[k];\n                  else\n                  {\n                  if (!imag_part)\n                  for (k = 0; k < 3; k++)\n                  v(k) = values[2*k];\n                  else\n                  for (k = 0; k < 3; k++)\n                  v(k) = values[2*k+1];\n                  }\n                        \n                  if (mesh->GetDimension() == 2)\n                  if ( (!vsol->iscomplex && vsol->components != 3) ||\n                  (vsol->iscomplex && vsol->components != 6) )\n                  v(2) = 0;\n                        \n                  double val = v.Length();\n                  SetOpenGlColor  (val, minval, maxval, logscale);\n\n                  if (val > 1e-10 * maxval)\n                  v *= (rad / val / gridsize * 0.5);\n                  else drawelem = 0;\n                  // \"drawelem\": added 07.04.2004 (FB)\n                  if ( drawelem ) DrawCone (cp, cp+4*v, 0.8*rad / gridsize);\n\n\n                  }\n                  }\n                */\n              }\n            else if (el.GetType() == QUAD)\n              {\n\t\t  NgArray < Point<3> > lp(3);\n\n\t\t  lp[0] = mesh->Point(el[0]);\n\t\t  lp[1] = mesh->Point(el[1]);\n\t\t  lp[2] = mesh->Point(el[3]);\n\n\t\t  DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol);\n\n\t\t  lp[0] = mesh->Point(el[2]);\n\t\t  lp[1] = mesh->Point(el[1]);\n\t\t  lp[2] = mesh->Point(el[3]);\n\n\t\t  DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol, true);\n                \n                /*\n                Point<3> lp[4];\n                Point<2> p2d[4];\n                \n                for (int k = 0; k < 4; k++)\n                  lp[k] = mesh->Point (el[k]);\n                \n                \n                Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]);\n                Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2)));\n                int dir, dir1, dir2;\n                if (na(0) > na(1) && na(0) > na(2))\n                  dir = 1;\n                else if (na(1) > na(2))\n                  dir = 2;\n                else \n                  dir = 3;\n                \n                dir1 = (dir % 3) + 1;\n                dir2 = (dir1 % 3) + 1;\n                \n                for (int k = 0; k < 4; k++)\n                  {\n                    p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad),\n                                       (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad));\n                  }\n                \n                double minx2d, maxx2d, miny2d, maxy2d;\n                minx2d = maxx2d = p2d[0](0);\n                miny2d = maxy2d = p2d[0](1);\n                for (int k = 1; k < 4; k++)\n                  {\n                    minx2d = min2 (minx2d, p2d[k](0));\n                    maxx2d = max2 (maxx2d, p2d[k](0));\n                    miny2d = min2 (miny2d, p2d[k](1));\n                    maxy2d = max2 (maxy2d, p2d[k](1));\n                  }\n                \n                for (double s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize)\n                  if (s >= minx2d && s <= maxx2d)\n                    for (double t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize)\n                      if (t >= miny2d && t <= maxy2d)\n                        {\n                          double lami[3];\n                          Point3d p3d(2*rad*s+pmin(0), 2*rad*t+pmin(1),0);\n                          \n                          if (mesh->PointContainedIn2DElement (p3d, lami, sei+1))\n                            {\n                              Point<3> cp = p3d;\n                              double lam1 = lami[0];\n                              double lam2 = lami[1];\n                              \n                              //for (k = 0; k < 3; k++)\n                              //cp(k) = lp[0](k) + \n                              //lam1 * (lp[1](k)-lp[0](k)) + \n                              //lam2 * (lp[2](k)-lp[0](k));\n                              \n                              \n                              Vec<3> v;\n                              double values[6];\n                              bool drawelem = GetSurfValues (vsol, sei, -1, lam1, lam2, values);\n                              (*testout) << \"sei \" << sei << \" lam1 \" << lam1 << \" lam2 \" << lam2 << \" drawelem \" << drawelem << endl;\n                              \n                              if (!vsol->iscomplex)\n                                for (int k = 0; k < 3; k++)\n                                  v(k) = values[k];\n                              else\n                                {\n                                  if (!imag_part)\n                                    for (int k = 0; k < 3; k++)\n                                      v(k) = values[2*k];\n                                  else\n                                    for (int k = 0; k < 3; k++)\n                                      v(k) = values[2*k+1];\n                                }\n                              \n                              if (mesh->GetDimension() == 2)\n                                if ( (!vsol->iscomplex && vsol->components != 3) ||\n                                     (vsol->iscomplex && vsol->components != 6) )\n                                  v(2) = 0;\n                              \n                              double val = v.Length();\n                              SetOpenGlColor  (val); // , minval, maxval, logscale); july 09\n                              \n                              (*testout) << \"v \" << v << endl;\n                              \n                              if (val > 1e-10 * maxval)\n                                v *= (rad / val / gridsize * 0.5);\n                              \n                              (*testout) << \"v \" << v << endl;\n                              \n                              if ( drawelem )\n                                {\n                                  DrawCone (cp, cp+4*v, 0.8*rad / gridsize);\n                                  (*testout) << \"cp \" << cp << \" rad \" << rad << \" gridsize \" << gridsize << endl;\n                                }\n                              \n                            }\n                        }\n              */\n              }\n          }\n      }\n  }\n  \n  \n  \n  \n  void VisualSceneSolution :: \n  DrawIsoLines (const Point<3> & p1, \n                const Point<3> & p2, \n                const Point<3> & p3,\n                double val1, double val2, double val3)\n  {\n    DrawIsoLines2 (p1, p2, p1, p3, val1, val2, val1, val3); // , minval, maxval, n);\n    DrawIsoLines2 (p2, p1, p2, p3, val2, val1, val2, val3); // , minval, maxval, n);\n    DrawIsoLines2 (p3, p1, p3, p2, val3, val1, val3, val2); // , minval, maxval, n);\n  }\n\n\n  void VisualSceneSolution :: \n  DrawIsoLines2 (const Point<3> & hp1, \n                 const Point<3> & hp2, \n                 const Point<3> & hp3,\n                 const Point<3> & hp4,\n                 double val1, double val2, double val3, double val4)\n  {\n    int n = numisolines;\n    Point<3> p1, p2, p3, p4;\n    if (val1 < val2)\n      {\n        p1 = hp1; p2 = hp2;\n      }\n    else\n      {\n        p1 = hp2; p2 = hp1;\n        swap (val1, val2);\n      }\n\n    if (val3 < val4)\n      {\n        p3 = hp3; p4 = hp4;\n      }\n    else\n      {\n        p3 = hp4; p4 = hp3;\n        swap (val3, val4);\n      }\n\n    val2 += 1e-10;\n    val4 += 1e-10;\n\n    double fac = (maxval-minval) / n;\n    double idelta1 = 1.0 / (val2 - val1);\n    double idelta2 = 1.0 / (val4 - val3);\n\n    int mini = int ((max2 (val1, val3) - minval) / fac);\n    int maxi = int ((min2 (val2, val4) - minval) / fac);\n    if (mini < 0) mini = 0;\n    if (maxi > n-1) maxi = n-1;\n\n    for (int i = mini; i <= maxi; i++)\n      {\n        double val = minval + i * fac;\n        double lam1 = (val - val1) * idelta1;\n        double lam2 = (val - val3) * idelta2;\n        if (lam1 >= 0 && lam1 <= 1 && lam2 >= 0 && lam2 <= 1)\n          {\n            Point<3> lp1 = p1 + lam1 * (p2-p1);\n            Point<3> lp2 = p3 + lam2 * (p4-p3);\n            glVertex3dv (lp1 );\n            glVertex3dv (lp2 );\n            // glVertex3dv (lp2 );  // better ?\n            // glVertex3dv (lp1 );  \n          }\n      }\n  }\n\n\n\n  void VisualSceneSolution :: \n  GetMinMax (int funcnr, int comp, double & minv, double & maxv) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    // static int timer1 = NgProfiler::CreateTimer (\"getminmax, vol\");\n    // static int timer2 = NgProfiler::CreateTimer (\"getminmax, surf\");\n\n#ifdef PARALLELGL\n    auto comm = mesh->GetCommunicator();\n    if (comm.Size() > 1)\n      {\n        if (id == 0)\n          {\n            MyMPI_SendCmd (\"redraw\");\n            MyMPI_SendCmd (\"getminmax\");\n          }\n        MyMPI_Bcast (funcnr, mesh->GetCommunicator());\n        MyMPI_Bcast (comp, mesh->GetCommunicator());\n      }\n#endif\n\n    // double val;\n    // bool considerElem;\n\n    bool hasit = false;\n#ifdef max\n      #undef max\n#endif\n    minv = numeric_limits<double>::max();\n    maxv = -numeric_limits<double>::max();\n\n    if ((ntasks == 1) || (id > 0))\n      if (funcnr != -1)\n        {\n          const SolData * sol = soldata[funcnr];\n\n          if (sol->draw_volume)\n            {\n              // NgProfiler::RegionTimer reg1 (timer1);\n              \n              int ne = mesh->GetNE();\n\n              mutex min_mutex;\n              mutex max_mutex;\n\n              ParallelFor(0, ne, [&] (int first, int next)\n                {\n                  double minv_local = numeric_limits<double>::max();\n                  double maxv_local = -numeric_limits<double>::max();\n                  for (int i=first; i<next; i++)\n                    {\n                      double val;\n                      if(!VolumeElementActive(sol, *mesh, (*mesh)[ElementIndex(i)]))\n                        continue;\n                      bool considerElem = GetValue (sol, i, 0.333, 0.333, 0.333, comp, val);\n                      if (considerElem)\n                        {\n                          if (val > maxv_local) maxv_local = val;\n                          if (val < minv_local) minv_local = val;\n                          hasit = true;\n                        }\n                    }\n                  if(minv_local < minv)\n                    {\n                      lock_guard<mutex> guard(min_mutex);\n                      if(minv_local < minv)                      \n                        minv = minv_local;\n                    }\n                  if(maxv_local > maxv)\n                    {\n                      lock_guard<mutex> guard(max_mutex);\n                      if(maxv_local > maxv)                      \n                        maxv = maxv_local;\n                    }\n                });\n            }\n          \n          if (sol->draw_surface)\n            {\n              // NgProfiler::RegionTimer reg2 (timer2);\n              \n              // int nse = mesh->GetNSE();\n              // for (int i = 0; i < nse; i++)\n              auto sol_active = GetScalOrVecFunction();\n              for (SurfaceElementIndex i : mesh->SurfaceElements().Range())\n                {\n                  if(!SurfaceElementActive(sol_active, *mesh, (*mesh)[i]))\n                    continue;\n                  ELEMENT_TYPE type = (*mesh)[i].GetType();\n                  double val;\n                  bool considerElem = (type == QUAD) \n                    ? GetSurfValue (sol, i, -1, 0.5, 0.5, comp, val)\n                    : GetSurfValue (sol, i, -1, 0.3333333, 0.3333333, comp, val);\n                  \n                  if (considerElem)\n                    {\n                      if (val > maxv) maxv = val;\n                      if (val < minv) minv = val;\n                      hasit = true;\n                    }\n                }\n            }\n        }\n    if (minv == maxv) maxv = minv+1e-6;\n    if (!hasit) { minv = 0; maxv = 1; }\n    \n#ifdef PARALLEL\n    if ((ntasks > 1) && (id == 0))\n      {\n\tminv = 1e99;\n\tmaxv = -1e99;\n      }\n    if (ntasks > 1)\n      {\n        double hmin, hmax;\n        NG_MPI_Reduce (&minv, &hmin, 1, NG_MPI_DOUBLE, NG_MPI_MIN, 0, NG_MPI_COMM_WORLD);\n        NG_MPI_Reduce (&maxv, &hmax, 1, NG_MPI_DOUBLE, NG_MPI_MAX, 0, NG_MPI_COMM_WORLD);\n        minv = hmin;\n        maxv = hmax;\n      }\n#endif\n  }\n\n\n\n\n\n  bool VisualSceneSolution :: \n  GetValues (const SolData * data, ElementIndex elnr, \n             double lam1, double lam2, double lam3,\n             double * values) const\n  {\n    bool ok = false;\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values);\n          break;\n        }\n      default:\n        {\n          for (int i = 0; i < data->components; i++)\n            ok = GetValue (data, elnr, lam1, lam2, lam3, i+1, values[i]);\n        }\n      }\n    return ok;\n  }\n\n  bool VisualSceneSolution :: \n  GetValues (const SolData * data, ElementIndex elnr, \n             const double xref[], const double x[], const double dxdxref[], \n             double * values) const\n  {\n    bool ok = false;\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values);\n          break;\n        }\n      default:\n        {\n          for (int i = 0; i < data->components; i++)\n            ok = GetValue (data, elnr, xref[0], xref[1], xref[2], i+1, values[i]);\n        }\n      }\n    return ok;\n  }\n\n\n  bool VisualSceneSolution :: \n  GetValue (const SolData * data, ElementIndex elnr, \n            const double xref[], const double x[], const double dxdxref[], \n            int comp, double & val) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    double lam1 = xref[0];\n    double lam2 = xref[1];\n    double lam3 = xref[2];\n        \n    val = 0;\n    bool ok = 0;\n\n\n    if (comp == 0)\n      {\n        NgArrayMem<double,20> values(data->components);\n        ok = GetValues (data, elnr, xref, x, dxdxref, &values[0]);\n\n\tval = ExtractValue (data, 0, &values[0]);\n\treturn ok;\n      }\n\n\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          double values[20];\n          ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values);\n\n          val = values[comp-1];\n          return ok;\n        }\n      case SOL_NODAL:\n        {\n          const Element & el = (*mesh)[elnr];\n\n          double lami[8] = { 0.0 };\n          int np = 0;\n        \n          switch (el.GetType())\n            {\n            case TET:\n            case TET10:\n              {\n                lami[1] = lam1;\n                lami[2] = lam2;\n                lami[3] = lam3;\n                lami[0] = 1-lam1-lam2-lam3;\n                np = 4;\n                break;\n              }\n            case PRISM:\n            case PRISM12:\n            case PRISM15:\n              {\n                lami[0] = (1-lam3) * (1-lam1-lam2);\n                lami[1] = (1-lam3) * lam1;\n                lami[2] = (1-lam3) * lam2;\n                lami[3] = (lam3) * (1-lam1-lam2);\n                lami[4] = (lam3) * lam1;\n                lami[5] = (lam3) * lam2;\n                np = 6;\n                break;\n              }     \n            default:\n              cerr << \"case not implemented 23523\" << endl;\n            }\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_ELEMENT:\n        {\n          val = data->data[elnr * data->dist + comp-1];\n          return 1;\n        }\n\n      case SOL_SURFACE_ELEMENT:\n        return 0;\n\n      case SOL_NONCONTINUOUS:\n        {\n          const Element & el = (*mesh)[elnr];\n\n          double lami[8] = { 0.0 };\n          int np = 0;\n\n          switch (el.GetType())\n            {\n            case TET:\n            case TET10:\n              {\n                lami[1] = lam1;\n                lami[2] = lam2;\n                lami[3] = lam3;\n                lami[0] = 1-lam1-lam2-lam3;\n                np = 4;\n                break;\n              }\n            case PRISM:\n            case PRISM12:\n            case PRISM15:\n              {\n                lami[0] = (1-lam3) * (1-lam1-lam2);\n                lami[1] = (1-lam3) * lam1;\n                lami[2] = (1-lam3) * lam2;\n                lami[3] = (lam3) * (1-lam1-lam2);\n                lami[4] = (lam3) * lam1;\n                lami[5] = (lam3) * lam2;\n                np = 6;\n                break;\n              }\n            case PYRAMID:\n            case PYRAMID13:\n              {\n                if (lam3 > 1-1e-5)\n                  {\n                    lami[0] = lami[1] = lami[2] = lami[3] = 0;\n                    lami[4] = 1;\n                  }\n                else\n                  {\n                    double x0 = lam1 / (1-lam3);\n                    double y0 = lam2 / (1-lam3);\n                    lami[0] = (1-x0) * (1-y0) * (1-lam3);\n                    lami[1] = (  x0) * (1-y0) * (1-lam3);\n                    lami[2] = (  x0) * (  y0) * (1-lam3);\n                    lami[3] = (1-x0) * (  y0) * (1-lam3);\n                    lami[4] = lam3;\n                    np = 5;\n                  }\n                break;\n              }\n            default:\n              np = 0;\n            }\n\n          int base;\n          if (data->order == 1)\n            base = 6 * elnr;\n          else\n            base = 10 * elnr;\n\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(base+i) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_MARKED_ELEMENTS:\n        {\n          val = (*mesh)[elnr].TestRefinementFlag();\n          return 1;\n        }\n      \n      case SOL_ELEMENT_ORDER:\n        {\n          val = (*mesh)[elnr].GetOrder();\n          return 1;\n        }\n\n      default:\n        cerr << \"case not handled 7234\" << endl;\n      }\n    return 0;\n  }\n\n\n\n  bool VisualSceneSolution :: \n  GetValue (const SolData * data, ElementIndex elnr, \n            double lam1, double lam2, double lam3,\n            int comp, double & val) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    val = 0;\n    bool ok = 0;\n\n    if (comp == 0)\n      {\n        NgArrayMem<double,20> values(data->components);\n        ok = GetValues (data, elnr, lam1, lam2, lam3, &values[0]);\n\tval = ExtractValue (data, 0, &values[0]);\n\treturn ok;\n      }\n\n\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n\t  val = 0.0;\n          double values[20];\n\t  ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values);\n\n          val = values[comp-1];\n          return ok;\n        }\n      case SOL_NODAL:\n        {\n          const Element & el = (*mesh)[elnr];\n\n          double lami[8] = { 0.0 };\n          int np = 0;\n        \n          switch (el.GetType())\n            {\n            case TET:\n            case TET10:\n              {\n                lami[1] = lam1;\n                lami[2] = lam2;\n                lami[3] = lam3;\n                lami[0] = 1-lam1-lam2-lam3;\n                np = 4;\n                break;\n              }\n            case PRISM:\n            case PRISM12:\n              {\n                lami[0] = (1-lam3) * (1-lam1-lam2);\n                lami[1] = (1-lam3) * lam1;\n                lami[2] = (1-lam3) * lam2;\n                lami[3] = (lam3) * (1-lam1-lam2);\n                lami[4] = (lam3) * lam1;\n                lami[5] = (lam3) * lam2;\n                np = 6;\n                break;\n              }     \n            default:\n              cerr << \"case not implemented 234324\" << endl;\n            }\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_ELEMENT:\n        {\n          val = data->data[elnr * data->dist + comp-1];\n          return 1;\n        }\n\n      case SOL_SURFACE_ELEMENT:\n        return 0;\n\n      case SOL_NONCONTINUOUS:\n        {\n          const Element & el = (*mesh)[elnr];\n\n          double lami[8] = { 0.0 };\n          int np = 0;\n\n          switch (el.GetType())\n            {\n            case TET:\n            case TET10:\n              {\n                lami[1] = lam1;\n                lami[2] = lam2;\n                lami[3] = lam3;\n                lami[0] = 1-lam1-lam2-lam3;\n                np = 4;\n                break;\n              }\n            case PRISM:\n            case PRISM12:\n              {\n                lami[0] = (1-lam3) * (1-lam1-lam2);\n                lami[1] = (1-lam3) * lam1;\n                lami[2] = (1-lam3) * lam2;\n                lami[3] = (lam3) * (1-lam1-lam2);\n                lami[4] = (lam3) * lam1;\n                lami[5] = (lam3) * lam2;\n                np = 6;\n                break;\n              }\n            case PYRAMID:\n              {\n                if (lam3 > 1-1e-5)\n                  {\n                    lami[0] = lami[1] = lami[2] = lami[3] = 0;\n                    lami[4] = 1;\n                  }\n                else\n                  {\n                    double x0 = lam1 / (1-lam3);\n                    double y0 = lam2 / (1-lam3);\n                    lami[0] = (1-x0) * (1-y0) * (1-lam3);\n                    lami[1] = (  x0) * (1-y0) * (1-lam3);\n                    lami[2] = (  x0) * (  y0) * (1-lam3);\n                    lami[3] = (1-x0) * (  y0) * (1-lam3);\n                    lami[4] = lam3;\n                    np = 5;\n                  }\n                break;\n              }\n            default:\n              np = 0;\n            }\n\n          int base;\n          if (data->order == 1)\n            base = 6 * elnr;\n          else\n            base = 10 * elnr;\n\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(base+i) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_MARKED_ELEMENTS:\n        {\n          val = (*mesh)[elnr].TestRefinementFlag();\n          return 1;\n        }\n      \n      case SOL_ELEMENT_ORDER:\n        {\n          val = (*mesh)[elnr].GetOrder();\n          return 1;\n        }\n      default:\n        cerr << \"case not implemented 234234\" << endl;\n      }\n    return 0;\n  }\n\n\n\n\n\n\n\n  bool VisualSceneSolution :: \n  GetValueComplex (const SolData * data, ElementIndex elnr, \n                   double lam1, double lam2, double lam3,\n                   int comp, complex<double> & val) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    val = 0.0;\n    bool ok = 0;\n\n           \n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          double values[20];\n          ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values);\n          val = complex<double> (values[comp-1], values[comp]);\n          return ok;\n        }\n      default:\n        cerr << \"case not handled 234234\" << endl;\n      } \n    return 0;\n  }\n  \n\n  bool VisualSceneSolution :: \n  GetMultiValues (const SolData * data, ElementIndex elnr, int facetnr, int npt,\n\t\t  const double * xref, int sxref,\n\t\t  const double * x, int sx,\n\t\t  const double * dxdxref, int sdxdxref,\n\t\t  double * val, int sval) const\n  {\n    bool drawelem = false;\n    if (data->soltype == SOL_VIRTUALFUNCTION)\n      drawelem = data->solclass->GetMultiValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval);\n    else\n      for (int i = 0; i < npt; i++)\n        drawelem = GetValues (data, elnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval);\n    return drawelem;\n  }\n\n\n\n\n\n\n  bool VisualSceneSolution :: \n  GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, \n                 double lam1, double lam2, \n                 double * values) const\n  {\n    bool ok = false;\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, values);\n          // ok = 1;\n          // values[0] = 1.0;\n          break;\n        }\n      default:\n        {\n          for (int i = 0; i < data->components; i++)\n            ok = GetSurfValue (data, selnr, facetnr, lam1, lam2, i+1, values[i]);\n        }\n      }\n    return ok;\n  }\n\n\n  bool VisualSceneSolution :: \n  GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, \n                 const double xref[], const double x[], const double dxdxref[], \n                 double * values) const\n  {\n    bool ok = false;\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, values);\n          break;\n        }\n      default:\n        {\n          for (int i = 0; i < data->components; i++)\n            ok = GetSurfValue (data, selnr, facetnr, xref[0], xref[1], i+1, values[i]);\n        }\n      }\n    return ok;\n  }\n\n  bool VisualSceneSolution :: \n  GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, int npt,\n                      const double * xref, int sxref,\n                      const double * x, int sx,\n                      const double * dxdxref, int sdxdxref,\n                      double * val, int sval) const\n  {\n    bool drawelem = false;\n    if (data->soltype == SOL_VIRTUALFUNCTION)\n      drawelem = data->solclass->GetMultiSurfValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval);\n    else\n      for (int i = 0; i < npt; i++)\n        drawelem = GetSurfValues (data, elnr, facetnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval);\n    return drawelem;\n  }\n  \n  double VisualSceneSolution ::  ExtractValue (const SolData * data, int comp, double * values) const\n  {\n    double val = 0;\n    if (comp == 0)\n      {\n        switch (evalfunc)\n          {\n          case FUNC_ABS:\n            {\n              for (int ci = 0; ci < data->components; ci++)\n                val += sqr (values[ci]);\n              val = sqrt (val);\n              break;\n            }\n          case FUNC_ABS_TENSOR:\n            {\n              int d = 0;\n              switch (data->components)\n                {\n                case 1: d = 1; break;\n                case 3: d = 2; break;\n                case 6: d = 3; break;\n                }\n              for (int ci = 0; ci < d; ci++)\n                val += sqr (values[ci]);\n              for (int ci = d; ci < data->components; ci++)\n                val += 2*sqr (values[ci]);\n              val = sqrt (val);\n              break;\n            }\n\n          case FUNC_MISES:\n            {\n              int d = 0;\n              switch(data->components)\n                {\n                case 1: d = 1; break;\n                case 3: d = 2; break;\n                case 6: d = 3; break;\n                }\n              int ci;\n              double trace = 0.;\n              for (ci = 0; ci < d; ci++)\n                trace += 1./3.*(values[ci]);\n              for (ci = 0; ci < d; ci++)\n                val += sqr (values[ci]-trace);\n              for (ci = d; ci < data->components; ci++)\n                val += 2.*sqr (values[ci]);\n              val = sqrt (val);\n              break;\n            }\n          case FUNC_MAIN:\n            {\n              int d = 0;\n              switch(data->components)\n                {\n                case 1: d = 1; break;\n                case 3: d = 2; break;\n                case 6: d = 3; break;\n                }\n              Mat<3,3> m ;\n              Vec<3> ev;\n              int ci;\n              for (ci = 0; ci < d; ci++)\n                m(ci,ci) = (values[ci]);\n              m(0,1) = m(1,0) = values[3];\n              m(0,2) = m(2,0) = values[4];\n              m(1,2) = m(2,1) = values[5];\n\n              EigenValues (m, ev);\n              double help;\n              for (int i=0; i<d; i++)\n                {\n                  for (int j=d-1; i<j; j--)\n                    {\n                      if ( abs(ev(j)) > abs(ev(j-1)) )\n                        {\n                          help = ev(j);\n                          ev(j) = ev(j-1);\n                          ev(j-1) = help;\n                        }\n                    }\n                }\n              val = (ev(0));\n              break;\n            }\n          }\n        return val;\n      }\n\n    return values[comp-1];\n  }\n\n  complex<double> VisualSceneSolution ::  ExtractValueComplex (const SolData * data, int comp, double * values) const\n  {\n    if (!data->iscomplex)\n      return values[comp-1];\n    else\n      return complex<double> (values[comp-1], values[comp]);\n  }\n\n\n\n\n  bool VisualSceneSolution :: \n  GetSurfValueComplex (const SolData * data, SurfaceElementIndex selnr, int facetnr, \n                       double lam1, double lam2, \n                       int comp, complex<double> & val) const\n  {\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          NgArrayMem<double,20> values(data->components);\n          bool ok;\n          \n          ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]);\n          \n          if (ok)\n            {\n              if (!data->iscomplex)\n                val = values[comp-1];\n              else\n                val = complex<double> (values[comp-1], values[comp]);\n            }\n          \n          return ok;\n        }\n      default:\n        cerr << \"case not implemented 6565\" << endl;\n      }\n    return 0;\n  }\n  \n  bool VisualSceneSolution :: \n  GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, \n                double lam1, double lam2, \n                int comp, double & val) const\n  {\n    bool ok;\n    if (comp == 0)\n      {\n        val = 0;\n        NgArrayMem<double,20> values(data->components);\n        ok = GetSurfValues (data, selnr, facetnr, lam1, lam2, &values[0]);\n\tval = ExtractValue (data, 0, &values[0]);\n\treturn ok;\n      }\n\n\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n  \n          NgArrayMem<double,20> values(data->components);\n          bool ok;\n\n          ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]);\n\n          if (ok)\n            {\n              if (!data->iscomplex)\n                val =  values[comp-1];\n              else\n                {\n                  // cout << \"time = \" << time << \", cos = \" << cos(time) << endl;\n     \n                  // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time);\n                  // SZ: Sept 06 \n                  if(comp%2==0) \n                    val =  values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time);\n                  else\n                    val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time);\n         \n         \n         \n                }\n            }\n\n          return ok;\n        }\n\n\n      case SOL_NODAL:\n        {\n          shared_ptr<Mesh> mesh = GetMesh();\n          const Element2d & el = (*mesh)[selnr];\n\n          double lami[8];\n          int np, i;\n          val = 0;\n          double lam3 = 1-lam1-lam2;\n\n          switch (el.GetType())\n            {\n            case TRIG:\n              /*\n                lami[0] = lam3;\n                lami[1] = lam1;\n                lami[2] = lam2;\n              */\n              lami[0] = lam1;\n              lami[1] = lam2;\n              lami[2] = lam3;\n              np = 3;\n              break;\n\n            case TRIG6:\n              /*\n                lami[0] = lam3*(2*lam3-1);\n                lami[1] = lam1*(2*lam1-1);\n                lami[2] = lam2*(2*lam2-1);\n              */\n              // hierarchical basis:\n              lami[0] = lam3;\n              lami[1] = lam1;\n              lami[2] = lam2;\n              lami[3] = 4*lam1*lam2;\n              lami[4] = 4*lam2*lam3;\n              lami[5] = 4*lam1*lam3;\n              np = 6;\n              break;\n\n            case QUAD:\n            case QUAD6:\n            case QUAD8:\n              lami[0] = (1-lam1)*(1-lam2);\n              lami[1] = lam1 * (1-lam2);\n              lami[2] = lam1 * lam2;\n              lami[3] = (1-lam1) * lam2;\n              np = 4;\n              break;\n\n            default:\n              np = 0;\n            }\n\n          for (i = 0; i < np; i++)\n            val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_ELEMENT:\n        {\n          shared_ptr<Mesh> mesh = GetMesh();          \n          int el1, el2;\n          mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2);\n          el1--;\n\n          val = data->data[el1 * data->dist+comp-1];\n          return 1;\n        }\n\n      case SOL_NONCONTINUOUS:\n        {\n          val = 0;\n          // ?????\n          return 0;\n        }\n\n      case SOL_SURFACE_ELEMENT:\n        {\n          val = data->data[selnr * data->dist + comp-1];\n          return 1;\n        }\n\n      case SOL_SURFACE_NONCONTINUOUS:\n        {\n          shared_ptr<Mesh> mesh = GetMesh();          \n          const Element2d & el = (*mesh)[selnr];\n\n          double lami[8];\n          int np = 0;\n          val = 0;\n          int order = data->order;\n\n          switch (order)\n            {\n            case 0:\n              return data->data[selnr * data->dist + comp-1];\n            case 1:\n              {\n                switch (el.GetType())\n                  {\n                  case TRIG:\n                  case TRIG6:\n                    {\n                      lami[1] = lam1;\n                      lami[2] = lam2;\n                      lami[0] = 1-lam1-lam2;\n                      np = 3;\n                      break;\n                    }\n                  default:\n                    cerr << \"case not implemented 2342\" << endl;\n                  }\n                break;\n              }\n            case 2:\n              {\n                switch (el.GetType())\n                  {\n                  case TRIG:\n                    {\n                      lami[1] = lam1;\n                      lami[2] = lam2;\n                      lami[0] = 1-lam1-lam2;\n                      np = 3;\n                      break;\n                    }\n                  case TRIG6:\n                    {\n                      double lam3 = 1-lam1-lam2;\n                      lami[1] = 2*lam1 * (lam1-0.5);\n                      lami[2] = 2*lam2 * (lam2-0.5);\n                      lami[0] = 2*lam3 * (lam3-0.5);\n                      lami[3] = 4*lam1*lam2;\n                      lami[4] = 4*lam2*lam3;\n                      lami[5] = 4*lam1*lam3;\n                      np = 6;\n                      break;\n                    }\n                  default:\n                    cerr << \"case not implemented 8712\" << endl;\n                  }\n                break;\n              }\n            }\n        \n          int base;\n          if (order == 1)\n            base = 4 * selnr;\n          else \n            base = 9 * selnr;\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(base+i) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_MARKED_ELEMENTS:\n        {\n          shared_ptr<Mesh> mesh = GetMesh();          \n          val = (*mesh)[selnr].TestRefinementFlag();\n          return 1;\n        }\n      \n      case SOL_ELEMENT_ORDER:\n        {\n          shared_ptr<Mesh> mesh = GetMesh();          \n          val = (*mesh)[selnr].GetOrder();\n          return 1;\n        }\n\n      }\n    return 0;\n  }\n\n\n\n\n\n\n\n\n\n\n\n\n  bool VisualSceneSolution :: \n  GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, \n                const double xref[], const double x[], const double dxdxref[], \n                int comp, double & val) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    double lam1 = xref[0], lam2 = xref[1];\n\n    bool ok;\n    if (comp == 0)\n      {\n        val = 0;\n        NgArrayMem<double,20> values(data->components);\n        ok = GetSurfValues (data, selnr, facetnr, xref, x, dxdxref, &values[0]);\n\tval = ExtractValue (data, 0, &values[0]);\n\treturn ok;\n      }\n\n\n    switch (data->soltype)\n      {\n      case SOL_VIRTUALFUNCTION:\n        {\n          NgArrayMem<double,20> values(data->components);\n          bool ok;\n\n          // ok = data->solclass->GetSurfValue (selnr, lam1, lam2, &values[0]);\n          // cout << \"data->solclass = \" << flush << data->solclass << endl;\n          ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, &values[0]);\n          // ok = 1;\n          // values[0] = 1.0;\n\n          if (ok)\n            {\n              if (!data->iscomplex)\n                val =  values[comp-1];\n              else\n                {\n                  // cout << \"time = \" << time << \", cos = \" << cos(time) << endl;\n     \n                  // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time);\n                  // SZ: Sept 06 \n                  if(comp%2==0) \n                    val =  values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time);\n                  else\n                    val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time);\n                  \n                }\n            }\n\n          return ok;\n        }\n\n\n      case SOL_NODAL:\n        {\n          const Element2d & el = (*mesh)[selnr];\n\n          double lami[8];\n          int np, i;\n          val = 0;\n          double lam3 = 1-lam1-lam2;\n\n          switch (el.GetType())\n            {\n            case TRIG:\n              /*\n                lami[0] = lam3;\n                lami[1] = lam1;\n                lami[2] = lam2;\n              */\n              lami[0] = lam1;\n              lami[1] = lam2;\n              lami[2] = lam3;\n              np = 3;\n              break;\n\n            case TRIG6:\n              /*\n                lami[0] = lam3*(2*lam3-1);\n                lami[1] = lam1*(2*lam1-1);\n                lami[2] = lam2*(2*lam2-1);\n              */\n              // hierarchical basis:\n              lami[0] = lam3;\n              lami[1] = lam1;\n              lami[2] = lam2;\n              lami[3] = 4*lam1*lam2;\n              lami[4] = 4*lam2*lam3;\n              lami[5] = 4*lam1*lam3;\n              np = 6;\n              break;\n\n            case QUAD:\n            case QUAD6:\n            case QUAD8:\n              lami[0] = (1-lam1)*(1-lam2);\n              lami[1] = lam1 * (1-lam2);\n              lami[2] = lam1 * lam2;\n              lami[3] = (1-lam1) * lam2;\n              np = 4;\n              break;\n\n            default:\n              np = 0;\n            }\n\n          for (i = 0; i < np; i++)\n            val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_ELEMENT:\n        {\n          int el1, el2;\n          mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2);\n          el1--;\n\n          val = data->data[el1 * data->dist+comp-1];\n          return 1;\n        }\n\n      case SOL_NONCONTINUOUS:\n        {\n          val = 0;\n          // ?????\n          return 0;\n        }\n\n      case SOL_SURFACE_ELEMENT:\n        {\n          val = data->data[selnr * data->dist + comp-1];\n          return 1;\n        }\n\n      case SOL_SURFACE_NONCONTINUOUS:\n        {\n          const Element2d & el = (*mesh)[selnr];\n\n          double lami[8] = { 0.0 };\n          int np = 0;\n          val = 0;\n          int order = data->order;\n\n          switch (order)\n            {\n            case 0:\n              return data->data[selnr * data->dist + comp-1];\n            case 1:\n              {\n                switch (el.GetType())\n                  {\n                  case TRIG:\n                  case TRIG6:\n                    {\n                      lami[1] = lam1;\n                      lami[2] = lam2;\n                      lami[0] = 1-lam1-lam2;\n                      np = 3;\n                      break;\n                    }\n                  default:\n                    cerr << \"case not impl 234234\" << endl;\n                  }\n                break;\n              }\n            case 2:\n              {\n                switch (el.GetType())\n                  {\n                  case TRIG:\n                    {\n                      lami[1] = lam1;\n                      lami[2] = lam2;\n                      lami[0] = 1-lam1-lam2;\n                      np = 3;\n                      break;\n                    }\n                  case TRIG6:\n                    {\n                      double lam3 = 1-lam1-lam2;\n                      lami[1] = 2*lam1 * (lam1-0.5);\n                      lami[2] = 2*lam2 * (lam2-0.5);\n                      lami[0] = 2*lam3 * (lam3-0.5);\n                      lami[3] = 4*lam1*lam2;\n                      lami[4] = 4*lam2*lam3;\n                      lami[5] = 4*lam1*lam3;\n                      np = 6;\n                      break;\n                    }\n                  default:\n                    cerr << \"case not implemented 3234\" << endl;\n                  }\n                break;\n              }\n            }\n        \n          int base;\n          if (order == 1)\n            base = 4 * selnr;\n          else \n            base = 9 * selnr;\n\n          for (int i = 0; i < np; i++)\n            val += lami[i] * data->data[(base+i) * data->dist + comp-1];\n\n          return 1;\n        }\n\n      case SOL_MARKED_ELEMENTS:\n        {\n          val = (*mesh)[selnr].TestRefinementFlag();\n          return 1;\n        }\n      \n      case SOL_ELEMENT_ORDER:\n        {       \n          val = (*mesh)[selnr].GetOrder();\n          return 1;\n        }\n\n      }\n    return 0;\n  }\n\n\n\n\n\n\n\n\n\n  Vec<3> VisualSceneSolution :: \n  GetDeformation (ElementIndex elnr, const Point<3> & p) const\n  {\n    Vec<3> def;\n    if (deform && vecfunction != -1)\n      {\n        GetValues (soldata[vecfunction], elnr, p(0), p(1), p(2), &def(0));\n        def *= scaledeform;\n\n        if (soldata[vecfunction]->components == 2) def(2) = 0;\n      }\n    else\n      def = 0;\n    return def;\n  }\n\n\n  Vec<3> VisualSceneSolution :: \n  GetSurfDeformation (SurfaceElementIndex elnr, int facetnr, double lam1, double lam2) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    Vec<3> def;\n    if (deform && vecfunction != -1)\n      {\n        // GetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2,  &def(0));\n\tdouble values[6];\n\tGetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2,  values);\n\tdef = RealVec3d (values, soldata[vecfunction]->iscomplex, imag_part);\n        def *= scaledeform;\n\n        if (soldata[vecfunction]->components == 2) def(2) = 0;\n      }\n    else if (deform && scalfunction != -1 && mesh->GetDimension()==2)\n      { // he: allow for 3d plots of 2d surfaces: usage: turn deformation on\n        def = 0;\n        GetSurfValue (soldata[scalfunction], elnr, facetnr, lam1, lam2, scalcomp, def(2));\n        def *= scaledeform;\n      }\n    else\n      def = 0;\n    return def;\n  }\n\n  void VisualSceneSolution :: GetPointDeformation (PointIndex pnum, Point<3> & p, \n                                                   SurfaceElementIndex elnr) const\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n    auto pnum_ = pnum-IndexBASE<PointIndex>();\n    \n    p = mesh->Point (pnum);\n    if (deform && vecfunction != -1)\n      {\n        const SolData * vsol = soldata[vecfunction];\n      \n        Vec<3> v(0,0,0);\n        if (vsol->soltype == SOL_NODAL)\n          {\n            v = Vec3d(vsol->data[pnum_ * vsol->dist],\n                      vsol->data[pnum_ * vsol->dist+1],\n                      vsol->data[pnum_ * vsol->dist+2]);\n          }\n        else if (vsol->soltype == SOL_SURFACE_NONCONTINUOUS)\n          {\n            const Element2d & el = (*mesh)[elnr];\n            for (int j = 0; j < el.GetNP(); j++)\n              if (el[j] == pnum)\n                {\n                  int base = (4*elnr+j-1) * vsol->dist;\n                  v = Vec3d(vsol->data[base],\n                            vsol->data[base+1],\n                            vsol->data[base+2]);\n                }\n          }\n\n        if (vsol->dist == 2) v(2) = 0;\n      \n        v *= scaledeform;\n        p += v;\n      }\n  }\n\n\n\n\n  void VisualSceneSolution :: GetClippingPlaneTrigs (SolData * sol,\n                                                     NgArray<ClipPlaneTrig> & trigs,\n                                                     NgArray<ClipPlanePoint> & pts)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    // static int timer_vals = NgProfiler::CreateTimer (\"ClipPlaneTrigs - vertex values\");\n    static int timer1 = NgProfiler::CreateTimer (\"ClipPlaneTrigs1\");\n    // static int timer1a = NgProfiler::CreateTimer (\"ClipPlaneTrigs1a\");\n    // static int timer2 = NgProfiler::CreateTimer (\"ClipPlaneTrigs2\");\n    // static int timer3 = NgProfiler::CreateTimer (\"ClipPlaneTrigs3\");\n    // static int timer4 = NgProfiler::CreateTimer (\"ClipPlaneTrigs4\");\n    // static int timer4b = NgProfiler::CreateTimer (\"ClipPlaneTrigs4b\");\n\n\n    NgProfiler::RegionTimer reg1 (timer1);\n\n    \n    int ne = mesh->GetNE();\n\n    const int edgei[6][2] =\n      { { 0, 1 }, { 0, 2 }, { 0, 3 },\n        { 1, 2 }, { 1, 3 }, { 2, 3 } };\n\n    double edgelam[6];\n    // Point<3> edgep[6];\n    double nodevali[4];\n\n    int cntce;\n    int cpe1 = 0, cpe2 = 0, cpe3 = 0;\n\n    // NgArray<Element> loctets;\n    // NgArray<Element> loctetsloc;\n    // NgArray<Point<3> > pointsloc;\n\n    int n = 1 << subdivisions;\n    int n3 = (n+1)*(n+1)*(n+1);\n\n    NgArray<Point<3> > grid(n3);\n    NgArray<Point<3> > locgrid(n3);\n    NgArray<Mat<3,3> > trans(n3);\n    NgArray<double> val(n3);\n    NgArray<bool> locposval(n3);\n    NgArray<int> compress(n3);\n\n    // NgProfiler::StartTimer (timer_vals);\n    NgArray<double,PointIndex::BASE> vertval(mesh->GetNP());\n    NgArray<bool,PointIndex::BASE> posval(mesh->GetNP());\n    // for (PointIndex pi = vertval.Begin(); pi < vertval.End(); pi++)\n    for (PointIndex pi : vertval.Range())\n      {\n        Point<3> vert = (*mesh)[pi];\n        vertval[pi] = \n          vert(0) * clipplane[0] + \n          vert(1) * clipplane[1] + \n          vert(2) * clipplane[2] + \n          clipplane[3]; \n        posval[pi] = vertval[pi] > 0;\n      }\n    // NgProfiler::StopTimer (timer_vals);\n\n    INDEX_2_CLOSED_HASHTABLE<int> edges(8*n3);  // point nr of edge\n    \n\n    for (ElementIndex ei = 0; ei < ne; ei++)\n      {\n        // NgProfiler::RegionTimer reg1a (timer1a);\n\n        const Element & el = (*mesh)[ei];\n        if(!VolumeElementActive(sol, *mesh, el))\n          continue;\n\n        int first_point_of_element = pts.Size();\n\n\tlocgrid.SetSize(n3);\n        if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue;\n        if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue;\n\n        ELEMENT_TYPE type = (*mesh)[ei].GetType();\n        if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID || type == PYRAMID13 || type == PRISM15 || type == HEX20 || type == HEX7)\n          {\n            int ii = 0;\n            int cnt_valid = 0;\n\n            // NgProfiler::StartTimer (timer2);\n\n            \n            if (!mesh->GetCurvedElements().IsElementHighOrder(ei))\n              {\n                bool has_pos = 0, has_neg = 0;\n                \n                for (int i = 0; i < el.GetNP(); i++)\n                  if (posval[el[i]])\n                    has_pos = 1;\n                  else\n                    has_neg = 1;\n                \n                if (!has_pos || !has_neg) \n                  {\n                    // NgProfiler::StopTimer (timer2);\n                    continue;\n                  }\n              }\n            \n\n\n            if (type == TET || type == TET10)\n              {\n                for (int ix = 0; ix <= n; ix++)\n                  for (int iy = 0; iy <= n; iy++)\n                    for (int iz = 0; iz <= n; iz++, ii++)\n                      {\n                        if (ix+iy+iz <= n)\n                          {\n                            compress[ii] = cnt_valid;\n                            locgrid[cnt_valid] = \n                              Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                            cnt_valid++;\n                          }\n                        else\n                          compress[ii] = -1;\n                      }\n              }\n            \n            else\n              \n              for (int ix = 0; ix <= n; ix++)\n                for (int iy = 0; iy <= n; iy++)\n                  for (int iz = 0; iz <= n; iz++, ii++)\n                    {\n                      double x = double(ix)/n;\n                      double y = double(iy)/n;\n                      double z = double(iz)/n;\n                      \n                      Point<3> ploc;\n                      compress[ii] = ii;\n                      \n                      switch (type)\n                        {\n                        case PRISM:\n                        case PRISM12:\n                        case PRISM15:\n                          if (ix+iy <= n)\n                            {\n                              ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                              compress[ii] = cnt_valid;\n                              cnt_valid++;\n                            }\n                          else\n                            compress[ii] = -1;\n                          break;\n                        case HEX:\n                        case HEX20:\n                          ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n);\n                          break;\n                        case PYRAMID:\n                        case PYRAMID13:\n                          ploc = Point<3> (double(ix) / n * (1-double(iz)/n),\n                                           double(iy) / n * (1-double(iz)/n),\n                                           double(iz)/n);\n                          if (iz == n) ploc = Point<3> (0,0,1-1e-8);\n                          break;\n                        case HEX7:\n                          {\n                            if (iz == n && iy==n)\n                              { y -= 1e-7, z -= 1e-7; }\n                            ploc = Point<3> (x * (1-y*z), y, z);\n                            // if (iz == n && iy==n) ploc = Point<3> (0,1-1e-8,1-1e-8);\n                            break;\n                          }\n                        default:\n                          cerr << \"clip plane trigs not implemented\" << endl;\n                          ploc = Point<3> (0,0,0);\n                        }\n                      if (compress[ii] != -1)\n                        locgrid[compress[ii]] = ploc;\n                    }\n\n            if (type != TET && type != TET10 && type != PRISM && type != PRISM12 && type != PRISM15) cnt_valid = n3;\n\n\t    locgrid.SetSize(cnt_valid);\n\n            // NgProfiler::StopTimer (timer2);\n            // NgProfiler::RegionTimer reg4(timer4);\n\n            if (mesh->GetCurvedElements().IsHighOrder())\n              {\n                // NgProfiler::RegionTimer reg4(timer4);\n                mesh->GetCurvedElements().\n                  CalcMultiPointElementTransformation (&locgrid, ei, &grid, 0);\n              }\n            else\n              {\n                // NgProfiler::RegionTimer reg4(timer4b);\n                Vector shape(el.GetNP());\n                MatrixFixWidth<3> pointmat(el.GetNP());\n\n                for (int k = 0; k < el.GetNP(); k++)\n                  for (int j = 0; j < 3; j++)\n                    pointmat(k,j) = (*mesh)[el[k]](j);\n                \n                for (int i = 0; i < cnt_valid; i++)\n                  {\n                    el.GetShapeNew<double> (locgrid[i], shape);\n                    Point<3> pglob;\n                    for (int j = 0; j < 3; j++)\n                      {\n                        pglob(j) = 0;\n                        for (int k = 0; k < el.GetNP(); k++)\n                          pglob(j) += shape(k) * pointmat(k,j);\n                      }\n                    grid[i] = pglob;\n                  }\n              }\n\n            // NgProfiler::RegionTimer reg3(timer3);\n\n            bool has_pos = false, all_pos = true;\n\n            for (int i = 0; i < cnt_valid; i++)\n              {\n                val[i] = \n                  grid[i](0) * clipplane[0] + \n                  grid[i](1) * clipplane[1] + \n                  grid[i](2) * clipplane[2] + \n                  clipplane[3];\n                \n                locposval[i] = val[i] > 0;\n                has_pos |= locposval[i];\n                all_pos &= locposval[i];\n                \n                // if (val[i] > 0) has_pos = 1; else has_neg = 1;\n              }\n                \n            // if (!has_pos || !has_neg) continue;\n            if (!has_pos || all_pos) continue;\n            \n            edges.DeleteData();\n            \n            for (int ix = 0; ix < n; ix++)\n              for (int iy = 0; iy < n; iy++)\n                for (int iz = 0; iz < n; iz++)\n                  {\n                    int base = iz + (n+1)*iy + (n+1)*(n+1)*ix;\n                    int pi[8] = \n                      { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1),\n                        base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 };\n\n                    for (int j = 0; j < 8; j++)\n                      pi[j] = compress[pi[j]];\n\n                    bool has_pos = false, all_pos = true;\n                    for (int j = 0; j < 8; j++)\n                      if (pi[j] != -1)\n                        {\n                          has_pos |= locposval[pi[j]];\n                          all_pos &= locposval[pi[j]];\n                        }\n                    if (!has_pos || all_pos) continue;\n\n\n                    const int tets[6][4] = \n                      { { 1, 2, 4, 5 },\n                        { 4, 5, 2, 8 },\n                        { 2, 8, 5, 6 },\n                        { 2, 3, 4, 8 },\n                        { 2, 3, 8, 6 },\n                        { 3, 8, 6, 7 } };\n                    \n                    for (int ii = 0; ii < 6; ii++)\n                      {\n                        int teti[4];\n                        for (int k = 0; k < 4; k++)\n                          teti[k] = pi[tets[ii][k]-1];\n\n                        bool is_valid = true;\n                        for (int j = 0; j < 4; j++)\n                          is_valid &= (teti[j] != -1);\n                        if (!is_valid) continue;\n                        \n                        bool has_pos = false, all_pos = true;\n                        for (int j = 0; j < 4; j++)\n                          {\n                            has_pos |= locposval[teti[j]];\n                            all_pos &= locposval[teti[j]];\n                          }\n                        if (!has_pos || all_pos) continue;\n\n                        for (int j = 0; j < 4; j++)\n                          nodevali[j] = val[teti[j]];\n          \n                        cntce = 0;\n                        for (int j = 0; j < 6; j++)\n                          {\n                            int lpi1 = edgei[j][0];\n                            int lpi2 = edgei[j][1];\n                            if ( (nodevali[lpi1] > 0) != (nodevali[lpi2] > 0) )\n                              {\n                                cntce++;\n                                cpe3 = cpe2;\n                                cpe2 = cpe1;\n                                cpe1 = j;\n                                if (cntce >= 3)\n                                  {\n                                    ClipPlaneTrig cpt;\n                                    cpt.elnr = ei;\n                                  \n                                    for (int k = 0; k < 3; k++)\n                                      {\n                                        int ednr;\n                                        switch (k)\n                                          {\n                                          case 0: ednr = cpe1; break;\n                                          case 1: ednr = cpe2; break;\n                                          case 2: ednr = cpe3; break;\n                                          }\n\n                                        int pi1 = edgei[ednr][0];\n                                        int pi2 = edgei[ednr][1];\n                                        int pnr = -1;\n                                        \n                                        INDEX_2 pair (teti[pi1], teti[pi2]);\n                                        pair.Sort();\n                                        if (edges.Used(pair))\n                                          pnr = edges.Get(pair);\n                                        else\n                                          {\n                                            ClipPlanePoint cppt;\n                                            cppt.elnr = ei;\n                                            \n                                            edgelam[ednr] = nodevali[pi2] / (nodevali[pi2] - nodevali[pi1]);\n\n                                            Point<3> gp1 = grid[teti[pi1]];\n                                            Point<3> gp2 = grid[teti[pi2]];\n                                            cppt.p = gp2 + edgelam[ednr] * (gp1-gp2);\n                                            \n                                            Point<3> p1 = locgrid[teti[pi1]];\n                                            Point<3> p2 = locgrid[teti[pi2]];\n                                            cppt.lami =  p2 + edgelam[ednr] * (p1-p2);\n                                           \n                                            pts.Append (cppt);\n                                            pnr = pts.Size()-1;\n                                            edges.Set (pair, pnr);\n                                          }\n\n                                        cpt.points[k].pnr = pnr;\n                                        cpt.points[k].locpnr = pnr-first_point_of_element;\n                                      }\n                                  \n                                    trigs.Append (cpt);\n                                  }\n                              }\n                          }\n                      }\n                  }\n          }\n\n        else\n          {  // other elements not supported (JS, June 2007)\n            continue; // return;\n          }\n      \n      }\n  }\n\n  void VisualSceneSolution :: GetClippingPlaneGrid (NgArray<ClipPlanePoint> & pts)\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    Vec3d n(clipplane[0], clipplane[1], clipplane[2]);\n\n    double mu = -clipplane[3] / n.Length2();\n    Point3d p(mu*n.X(), mu * n.Y(), mu * n.Z());\n\n    // n /= n.Length();\n    n.Normalize();\n    Vec3d t1, t2;\n    n.GetNormal (t1);\n    t2 = Cross (n, t1);\n\n    double xi1, xi2;\n\n    double xi1mid = (center - p) * t1;\n    double xi2mid = (center - p) * t2;\n\n    pts.SetSize(0);\n\n    for (xi1 = xi1mid-rad+xoffset/gridsize; xi1 <= xi1mid+rad+xoffset/gridsize; xi1 += rad / gridsize)\n      for (xi2 = xi2mid-rad+yoffset/gridsize; xi2 <= xi2mid+rad+yoffset/gridsize; xi2 += rad / gridsize)\n        {\n          Point3d hp = p + xi1 * t1 + xi2 * t2;\n        \n          int cindex(-1);\n          bool allowindex(true);\n          if(vispar.clipdomain > 0)\n            {\n              cindex = vispar.clipdomain;\n            }\n          else if(vispar.donotclipdomain > 0)\n            {\n              allowindex = false;\n              cindex = vispar.donotclipdomain;\n            }\n\n          double lami[3];\n          int elnr = mesh->GetElementOfPoint (hp, lami,0,cindex,allowindex);\n\n          if (elnr != -1)\n            {\n              ClipPlanePoint cpp;\n              cpp.p = hp;\n              cpp.elnr = elnr;\n              cpp.lami(0) = lami[0];\n              cpp.lami(1) = lami[1];\n              cpp.lami(2) = lami[2];\n              pts.Append (cpp);\n            }\n        }\n  };\n\n\n\n\n  void VisualSceneSolution :: DrawClipPlaneTrigs () \n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n#ifdef PARALLELGL\n\n    if (id == 0 && ntasks > 1)\n      {\n\tInitParallelGL();\n\n\tNgArray<int> parlists (ntasks);\n\n\tMyMPI_SendCmd (\"redraw\");\n\tMyMPI_SendCmd (\"clipplanetrigs\");\n\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  MyMPI_Recv (parlists[dest], dest, NG_MPI_TAG_VIS);\n\n\tif (clipplanelist_scal)\n\t  glDeleteLists (clipplanelist_scal, 1);\n\n\tclipplanelist_scal = glGenLists (1);\n\tglNewList (clipplanelist_scal, GL_COMPILE);\n\t\n\tfor ( int dest = 1; dest < ntasks; dest++ )\n\t  glCallList (parlists[dest]);\n\t\n\tglEndList();\n\treturn;\n      }\n#endif\n\n\n\n\n\n    if (clipplanelist_scal)\n      glDeleteLists (clipplanelist_scal, 1);\n    \n    clipplanelist_scal = glGenLists (1);\n    glNewList (clipplanelist_scal, GL_COMPILE);\n\n\n    NgArray<ClipPlaneTrig> trigs;\n    NgArray<ClipPlanePoint> points;\n\t    \n    glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]);\n    glColor3d (1.0, 1.0, 1.0);\n    \n    SetTextureMode (usetexture);\n\n    SolData * sol = NULL;\n\n    if (scalfunction != -1) \n      sol = soldata[scalfunction];\n\n    GetClippingPlaneTrigs (sol, trigs, points);\n    if (sol -> draw_volume)\n      {\n\tglBegin (GL_TRIANGLES);\n\n    int maxlpnr = 0;\n    for (int i = 0; i < trigs.Size(); i++)\n      for (int j = 0; j < 3; j++)\n        maxlpnr = max2 (maxlpnr, trigs[i].points[j].locpnr);\n\n    NgArray<double> vals(maxlpnr+1);\n    NgArray<complex<double> > valsc(maxlpnr+1);\n    NgArray<int> elnrs(maxlpnr+1);\n    NgArray<bool> trigok(maxlpnr+1);\n    NgArray<Point<3> > locpoints(maxlpnr+1);\n    NgArray<Point<3> > globpoints(maxlpnr+1);\n    NgArray<Mat<3> > jacobi(maxlpnr+1);\n    NgArray<double> mvalues( (maxlpnr+1) * sol->components);\n    trigok = false;\n    elnrs = -1;\n\n    Point<3> p[3];\n    // double val[3];\n    // complex<double> valc[3];\n    int lastelnr = -1;\n    int nlp = -1;\n    bool ok = false;\n\n    for (int i = 0; i < trigs.Size(); i++)\n      {\n        const ClipPlaneTrig & trig = trigs[i];\n\tif (trig.elnr != ElementIndex(lastelnr))\n\t  {\n\t    lastelnr = trig.elnr;\n\t    nlp = -1;\n\n\t    for (int ii = i; ii < trigs.Size(); ii++)\n\t      {\n\t\tif (trigs[ii].elnr != trig.elnr) break;\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  nlp = max (nlp, trigs[ii].points[j].locpnr);\n\t      }\n\t    nlp++;\n\t    locpoints.SetSize (nlp);\n\n\t    for (int ii = i; ii < trigs.Size(); ii++)\n\t      {\n\t\tif (trigs[ii].elnr != trig.elnr) break;\n\t\tfor (int j = 0; j < 3; j++)\n\t\t  locpoints[trigs[ii].points[j].locpnr] = points[trigs[ii].points[j].pnr].lami;\n\t      }\n\n\t    mesh->GetCurvedElements().\n\t      CalcMultiPointElementTransformation (&locpoints, trig.elnr, \n\t\t\t\t\t\t   &globpoints, &jacobi);\n\n\t    bool\n\t      drawelem = GetMultiValues (sol, trig.elnr, -1, nlp, \n\t\t\t\t\t &locpoints[0](0), &locpoints[1](0)-&locpoints[0](0),\n\t\t\t\t\t &globpoints[0](0), &globpoints[1](0)-&globpoints[0](0),\n\t\t\t\t\t &jacobi[0](0), &jacobi[1](0)-&jacobi[0](0),\n\t\t\t\t\t &mvalues[0], sol->components);\n\t    \n\t    // cout << \"have multivalues, comps = \" << sol->components << endl;\n\n\t    // if (!drawelem) ok = false;\n\t    ok = drawelem;\n\t    if (usetexture != 2 || !sol->iscomplex)\n\t      for (int ii = 0; ii < nlp; ii++)\n\t\tvals[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]);\n\t    else\n\t      for (int ii = 0; ii < nlp; ii++)\n\t\tvalsc[ii] = complex<double> (mvalues[ii*sol->components + scalcomp-1],\n\t\t\t\t\t     mvalues[ii*sol->components + scalcomp]);\n\t  }\n\t\n\tif(ok)\n\t  for(int j=0; j<3; j++)\n\t    {\n\t      if (usetexture != 2 || !sol->iscomplex)\n\t\tSetOpenGlColor (vals[trig.points[j].locpnr]);\n\t      else\n\t\tglTexCoord2f ( valsc[trig.points[j].locpnr].real(), \n\t\t\t       valsc[trig.points[j].locpnr].imag() );\n\n\t      p[j] = points[trig.points[j].pnr].p;\n\n\t      if (deform)\n\t\t{\n\t\t  Point<3> ploc = points[trig.points[j].pnr].lami;\n\t\t  p[j] += GetDeformation (trig.elnr, ploc);\n\t\t}\n\n\t      glVertex3dv (p[j]);\n\t    }\n\n      }\n    glEnd();\n      }\n    glEndList ();\n\n\n#ifdef PARALLELGLGL\n    glFinish();\n    if (id > 0)\n      MyMPI_Send (clipplanelist_scal, 0, NG_MPI_TAG_VIS);\n#endif\n  }\n\n\n\n\n\n\n\n\n\n\n  void VisualSceneSolution ::\n  SetOpenGlColor(double val)\n  {\n    if (usetexture == 1 && !logscale)\n      {\n        glTexCoord1f ( val );\n        return;\n      }\n\n    double valmin = minval;\n    double valmax = maxval;\n\n    double value;\n\n    if (!logscale)\n      value = (val - valmin) / (valmax - valmin);\n    else\n      {\n        if (valmax <= 0) valmax = 1;\n        if (valmin <= 0) valmin = 1e-4 * valmax;\n        value = (log(fabs(val)) - log(valmin)) / (log(valmax) - log(valmin));\n      }\n\n    if (!invcolor)\n      value = 1 - value;\n\n\n    if (value > 1) value = 1;\n    if (value < 0) value = 0;\n\n    value *= 4;\n\n    static const double colp[][3] =\n      {\n        { 1, 0, 0 },\n        { 1, 1, 0 },\n        { 0, 1, 0 },\n        { 0, 1, 1 },\n        { 0, 0, 1 },\n        { 1, 0, 1 },\n        { 1, 0, 0 },\n      };\n  \n    int i = int(value);\n    double r = value - i;\n\n    GLdouble col[3];\n    for (int j = 0; j < 3; j++)\n      col[j] = (1-r) * colp[i][j] + r * colp[i+1][j];\n  \n    glColor3dv (col);\n  }\n\n\n\n  void VisualSceneSolution ::\n  SetTextureMode (int texturemode) const\n  {\n    switch (texturemode)\n      {\n      case 0:\n        glDisable (GL_TEXTURE_1D);\n        glDisable (GL_TEXTURE_2D);\n        break;\n      case 1:\n        glEnable (GL_TEXTURE_1D);\n        glDisable (GL_TEXTURE_2D);\n        glColor3d (1.0, 1.0, 1.0);   \n        break;\n      case 2:\n        glDisable (GL_TEXTURE_1D);\n        glEnable (GL_TEXTURE_2D);\n        glColor3d (1.0, 1.0, 1.0);   \n        break;\n      }\n  }\n\n\n\n\n  void VisualSceneSolution ::\n  DrawCone (const Point<3> & p1, const Point<3> & p2, double r)\n  {\n    int n = 10, i;\n    Vec<3> p1p2 = p2 - p1;\n\n    p1p2.Normalize();\n    Vec<3> p2p1 = -p1p2;\n\n    Vec<3> t1 = p1p2.GetNormal();\n    Vec<3> t2 = Cross (p1p2, t1);\n\n    Point<3> oldp = p1 + r * t1;\n    Vec<3> oldn = t1;\n\n    Point<3> p;\n    Vec<3> normal;\n\n    Mat<2> rotmat;\n    Vec<2> cs, newcs;\n    cs(0) = 1;\n    cs(1) = 0;\n    rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n);\n    rotmat(1,0) = sin(2*M_PI/n);\n    rotmat(0,1) = -rotmat(1,0);\n\n    glBegin (GL_TRIANGLES);\n    for (i = 1; i <= n; i++)\n      {\n        /*\n          phi = 2 * M_PI * i / n;\n          normal = cos(phi) * t1 + sin(phi) * t2;\n        */\n        newcs = rotmat * cs;\n        cs = newcs;\n        normal = cs(0) * t1 + cs(1) * t2;\n\n        p = p1 + r * normal;\n\n        // cone\n        glNormal3dv (normal);\n        glVertex3dv (p);\n        glVertex3dv (p2);\n        glNormal3dv (oldn);\n        glVertex3dv (oldp);\n\n        // base-circle\n        glNormal3dv (p2p1);\n        glVertex3dv (p);\n        glVertex3dv (p1);\n        glVertex3dv (oldp);\n\n        oldp = p;\n        oldn = normal;\n      }\n    glEnd ();\n  }\n\n\n\n  void VisualSceneSolution ::\n  DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r)\n  {\n    int n = 10, i;\n    Vec<3> p1p2 = p2 - p1;\n\n    p1p2.Normalize();\n    // Vec<3> p2p1 = -p1p2;\n\n    Vec<3> t1 = p1p2.GetNormal();\n    Vec<3> t2 = Cross (p1p2, t1);\n\n    Point<3> oldhp1 = p1 + r * t1;\n    Point<3> oldhp2 = p2 + r * t1;\n    Vec<3> oldn = t1;\n\n    Point<3> hp1, hp2;\n    Vec<3> normal;\n\n    Mat<2> rotmat;\n    Vec<2> cs, newcs;\n    cs(0) = 1;\n    cs(1) = 0;\n    rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n);\n    rotmat(1,0) = sin(2*M_PI/n);\n    rotmat(0,1) = -rotmat(1,0);\n\n    glBegin (GL_QUADS);\n    for (i = 1; i <= n; i++)\n      {\n        newcs = rotmat * cs;\n        cs = newcs;\n        normal = cs(0) * t1 + cs(1) * t2;\n\n        hp1 = p1 + r * normal;\n        hp2 = p2 + r * normal;\n\n        // cylinder\n        glNormal3dv (normal);\n\n        glVertex3dv (hp1);\n        glVertex3dv (hp2);\n        glVertex3dv (oldhp2);\n        glVertex3dv (oldhp1);\n\n        oldhp1 = hp1;\n        oldhp2 = hp2;\n        oldn = normal;\n      }\n    glEnd ();\n  }\n\n\n  bool VisualSceneSolution ::\n  SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & el) const\n  {\n    if(data == nullptr) return true;\n    bool is_active = true;\n    if (vispar.drawdomainsurf > 0)\n      {\n        if (mesh.GetDimension() == 3)\n          {\n            if (vispar.drawdomainsurf != mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() &&\n                vispar.drawdomainsurf != mesh.GetFaceDescriptor(el.GetIndex()).DomainOut())\n              is_active = false;\n          }\n        else\n          {\n            if (el.GetIndex() != vispar.drawdomainsurf)\n              is_active = false;\n          }\n      }\n\n    if(data->draw_surfaces) {\n      is_active = is_active && (*data->draw_surfaces)[el.GetIndex()-1];\n    }\n\n    return is_active;\n  }\n\n  bool VisualSceneSolution ::\n  VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & el) const\n  {\n    bool is_active = true;\n    if(data->draw_volumes)\n      is_active = is_active && (*data->draw_volumes)[el.GetIndex()-1];\n    return is_active;\n  }\n\n\n\n\n\n\n\n  void VisualSceneSolution :: BuildSelectionList()\n  {\n    shared_ptr<Mesh> mesh = GetMesh();\n\n    if(select.list_timestamp == GetTimeStamp())\n      return;\n\n    if(select.list)\n      glDeleteLists(select.list, 1);\n\n    select.list = glGenLists(1);\n    glNewList(select.list, GL_COMPILE);\n\n    SolData *sol = nullptr;\n    if (scalfunction != -1)\n      sol = soldata[scalfunction];\n\n    auto face_init = [](int i) {return true;};\n    auto sel_init = [&](SurfaceElementIndex sei) {\n        if(!SurfaceElementActive(sol, *mesh, (*mesh)[sei]))\n          return false;\n        GLushort r,g,b;\n        r = (sei+1) % (1<<16);\n        g = (sei+1) >> 16;\n        b = 0;\n        glColor3us(r,g,b);\n        return true;\n    };\n\n    glDisable(GL_TEXTURE_1D);\n    glDisable(GL_TEXTURE_2D);\n    glDisable(GL_FOG);\n    glDisable(GL_LIGHTING);\n    glDisable (GL_COLOR_MATERIAL);\n\n    RenderSurfaceElements(mesh, subdivisions, face_init, sel_init);\n\n    glEndList();\n  }\n\n\n\n  void VisualSceneSolution :: MouseDblClick (int px, int py)\n  {\n    BuildSelectionList();\n    auto mesh = GetMesh();\n    // auto dim = mesh->GetDimension();\n    marker = nullopt;\n\n    auto formatComplex = [](double real, double imag)\n    {\n      return ToString(real) + (imag < 0 ? \"\" : \"+\") + ToString(imag) + \"j\";\n    };\n\n    auto printScalValue = [&formatComplex]\n      (SolData & sol, int comp, double value, double imag=0., bool iscomplex=false)\n      {\n        cout << '\\t';\n        if(sol.components>1)\n          {\n            if(comp==0)\n                cout << \"func(\" << sol.name << \")\";\n            else\n                cout << sol.name << \"[\"+ToString(comp)+\"]\";\n          }\n        else\n            cout << sol.name;\n        cout << \" = \" << (iscomplex ? formatComplex(value, imag) : ToString(value)) << endl;\n      };\n\n    auto printVecValue = [&formatComplex]\n      (SolData & sol, FlatArray<double> values)\n      {\n        if(sol.iscomplex)\n          {\n            cout << sol.name << \" = ( \" << formatComplex(values[0], values[1]);\n            for(int i = 2; i < values.Size(); i+=2)\n              cout << \", \" << formatComplex(values[i], values[i+1]);\n            cout << \" )\" << endl;\n          }\n        else\n          {\n            cout << sol.name << \" = ( \" << values[0];\n            for(int i = 1; i < values.Size(); i++)\n              cout << \", \" << values[i];\n            cout << \" )\" << endl;\n          }\n      };\n\n    Point<3> p;\n\n    memcpy(select.transformationmat, transformationmat, sizeof(transformationmat));\n    memcpy(select.clipplane, clipplane, sizeof(clipplane));\n    select.center = center;\n    select.rad = rad;\n    select.enable_clipping_plane = vispar.clipping.enable;\n    bool found_point = select.SelectSurfaceElement(GetMesh(), px, py, p, showclipsolution && clipsolution);\n    selelement = select.selelement;\n\n    if(!found_point)\n        return;\n\n    marker = p;\n\n    // found point on clipping plane\n    if(selelement==0)\n    {\n      GLint viewport[4];\n      GLdouble projection[16];\n      glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); \n\n      glGetIntegerv(GL_VIEWPORT, &viewport[0]);\n\n      Point<3> eye;\n      gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2,\n          0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]);\n\n      Vec<3> n{vispar.clipping.normal};\n      n.Normalize();\n      Vec<3> view = p-eye;\n\n      // check if we look at the clipping plane from the right direction\n      if(n*view > 1e-8)\n      {\n        double lami[3];\n        if(auto el3d = mesh->GetElementOfPoint( p, lami ))\n        {\n          cout << endl << \"Selected point \" << p << \" on clipping plane\" << endl;\n          // marker = p;\n\n          bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume;\n          // bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume;\n\n          if(have_scal_func)\n          {\n            auto & sol = *soldata[scalfunction];\n            double val;\n            double imag = 0;\n            int rcomponent = scalcomp;\n            int comp = scalcomp;\n            if(sol.iscomplex && rcomponent != 0)\n            {\n              rcomponent = 2 * ((rcomponent-1)/2) + 1;\n              GetValue(&sol, el3d,  lami[0], lami[1], lami[2], rcomponent+1,\n                  imag);\n              comp = (scalcomp-1)/2 + 1;\n            }\n            GetValue(&sol, el3d,  lami[0], lami[1], lami[2], rcomponent, val);\n            printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0);\n          }\n          if(vecfunction!=-1 && soldata[vecfunction]->draw_volume)\n          {\n            auto & sol = *soldata[vecfunction];\n            ArrayMem<double, 10> values(sol.components);\n            GetValues(&sol, el3d,  lami[0], lami[1], lami[2], &values[0]);\n            printVecValue(sol, values);\n          }\n          return;\n        }\n      }\n    }\n\n    double lami[3] = {0.0, 0.0, 0.0};\n    // Check if unprojected Point is close to surface element (eps of 1e-3 due to z-Buffer accuracy)\n    bool found_2del = false;\n    if(selelement>0 && mesh->PointContainedIn2DElement(p, lami, selelement-1, false && fabs(lami[2])<1e-3))\n      {\n        // Found it, use coordinates of point projected to surface element\n        mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p);\n        found_2del = true;\n      }\n    cout << endl << \"Selected point \" << p << \" on surface\" << endl;\n\n    if(!found_2del)\n        return;\n\n    bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_surface;\n    bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_surface;\n\n    if(have_scal_func)\n      {\n        auto & sol = *soldata[scalfunction];\n        double val;\n        double imag = 0;\n        int rcomponent = scalcomp;\n        int comp = scalcomp;\n        if(sol.iscomplex && rcomponent != 0)\n          {\n            rcomponent = 2 * ((rcomponent-1)/2) + 1;\n            GetSurfValue(&sol, selelement-1, -1,  1.0-lami[0]-lami[1], lami[0], rcomponent+1, imag);\n            comp = (scalcomp-1)/2 + 1;\n          }\n        GetSurfValue(&sol, selelement-1, -1,  1.0-lami[0]-lami[1], lami[0], rcomponent, val);\n        printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0);\n      }\n    if(have_vec_func)\n      {\n        auto & sol = *soldata[vecfunction];\n        ArrayMem<double, 10> values(sol.components);\n        GetSurfValues(&sol, selelement-1, -1,  1.0-lami[0]-lami[1], lami[0], &values[0]);\n        printVecValue(sol, values);\n      }\n  }\n\n\n\n#ifdef PARALLELGL\n\n  void VisualSceneSolution :: Broadcast ()\n  {\n    NG_MPI_Datatype type;\n    int blocklen[] = \n      { \n\t1, 1, 1, 1,\n\t1, 1, 1, 1, \n\t1, 1, 1, 1, \n\t1, 4, 1, 1, \n\t1\n      };\n    NG_MPI_Aint displ[] = { (char*)&usetexture - (char*)this,\n\t\t\t (char*)&clipsolution - (char*)this,\n\t\t\t (char*)&scalfunction - (char*)this,\n\t\t\t (char*)&scalcomp - (char*)this,\n\n\t\t\t (char*)&vecfunction - (char*)this,\n\t\t\t (char*)&gridsize - (char*)this,\n\t\t\t (char*)&autoscale - (char*)this,\n\t\t\t (char*)&logscale - (char*)this,\n\n\t\t\t (char*)&minval - (char*)this,\n\t\t\t (char*)&maxval - (char*)this,\n\t\t\t (char*)&numisolines - (char*)this,\n\t\t\t (char*)&subdivisions - (char*)this,\n\n\t\t\t (char*)&evalfunc - (char*)this,\n\t\t\t (char*)&clipplane[0] - (char*)this,\n\t\t\t (char*)&multidimcomponent - (char*)this, \n\t\t\t (char*)&deform - (char*)this,\n\n\t\t\t (char*)&scaledeform - (char*)this \n    };\n\n\n    NG_MPI_Datatype types[] = { \n      NG_MPI_INT, NG_MPI_INT, NG_MPI_INT, NG_MPI_INT,\n      NG_MPI_INT, NG_MPI_INT, NG_MPI_INT, NG_MPI_INT,\n      NG_MPI_DOUBLE, NG_MPI_DOUBLE, NG_MPI_INT, NG_MPI_INT,\n      NG_MPI_INT, NG_MPI_DOUBLE, NG_MPI_INT, NG_MPI_INT,\n      NG_MPI_DOUBLE\n    };\n\n    NG_MPI_Type_create_struct (17, blocklen, displ, types, &type);\n    NG_MPI_Type_commit ( &type );\n\n    NG_MPI_Bcast (this, 1, type, 0, NG_MPI_COMM_WORLD);\n    NG_MPI_Type_free (&type);\n  }\n  \n#endif\n\n}\n\n\n#include \"../include/nginterface.h\"\n\nvoid Impl_Ng_ClearSolutionData ()\n{\n#ifdef OPENGL\n  // if (nodisplay) return;\n  // netgen::vssolution.ClearSolutionData();\n  netgen::GetVSSolution().ClearSolutionData();\n#endif\n}\n\nvoid Impl_Ng_InitSolutionData (Ng_SolutionData * soldata)\n{\n  // soldata -> name = NULL;\n  soldata -> data = NULL;\n  soldata -> components = 1;\n  soldata -> dist = 1;\n  soldata -> order = 1;\n  soldata -> iscomplex = 0;\n  soldata -> draw_surface = 1;\n  soldata -> draw_volume = 1;\n  soldata -> draw_surfaces = nullptr;\n  soldata -> draw_volumes = nullptr;\n  soldata -> soltype = NG_SOLUTION_NODAL;\n  soldata -> solclass = 0;\n}\n\nvoid Impl_Ng_SetSolutionData (Ng_SolutionData * soldata)\n{\n#ifdef OPENGL\n  // if (nodisplay) return;\n  //   vssolution.ClearSolutionData ();\n  netgen::VisualSceneSolution::SolData * vss = new netgen::VisualSceneSolution::SolData;\n\n  // vss->name = new char[strlen (soldata->name)+1];\n  // strcpy (vss->name, soldata->name);\n  vss->name = soldata->name;\n  vss->title = soldata->title;\n  vss->number_format = soldata->number_format;\n  vss->unit = soldata->unit;\n  vss->data = soldata->data;\n  vss->components = soldata->components;\n  vss->dist = soldata->dist;\n  vss->order = soldata->order;\n  vss->iscomplex = bool(soldata->iscomplex);\n  vss->draw_surface = soldata->draw_surface;\n  vss->draw_volume = soldata->draw_volume;\n  vss->draw_surfaces = soldata->draw_surfaces;\n  vss->draw_volumes = soldata->draw_volumes;\n  vss->soltype = netgen::VisualSceneSolution::SolType (soldata->soltype);\n  vss->solclass = soldata->solclass;\n  // netgen::vssolution.AddSolutionData (vss);\n  netgen::GetVSSolution().AddSolutionData (vss);\n#endif\n}\n\n\n\nvoid Impl_Ng_Redraw (bool blocking)\n{\n#ifdef OPENGL\n  //netgen::vssolution.UpdateSolutionTimeStamp();\n  netgen::GetVSSolution().UpdateSolutionTimeStamp();\n  netgen::Render(blocking);\n#endif\n}\n\n#ifdef OPENGL\n#ifdef WIN32\nvoid (*glBindBuffer) (GLenum a, GLuint b);\nvoid (*glDeleteBuffers) (GLsizei a, const GLuint *b);\nvoid (*glGenBuffers) (GLsizei a, GLuint *b);\nvoid (*glBufferData) (GLenum a, GLsizeiptr b, const GLvoid *c, GLenum d);\nvoid (*glBufferSubData) (GLenum a, GLintptr b, GLsizeiptr c, const GLvoid *d);\n\nGLenum (*glCheckFramebufferStatus) (GLenum target);\nvoid (*glBindFramebuffer) (GLenum target, GLuint framebuffer);\nvoid (*glBindRenderbuffer) (GLenum target, GLuint renderbuffer);\nvoid (*glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers);\nvoid (*glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers);\nvoid (*glGenFramebuffers) (GLsizei n, GLuint *framebuffers);\nvoid (*glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers);\nvoid (*glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);\nvoid (*glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\n\nNGGUI_API void LoadOpenGLFunctionPointers() {\n#ifdef USE_BUFFERS\n  glBindBuffer = (decltype(glBindBuffer)) wglGetProcAddress(\"glBindBuffer\");\n  glBufferSubData = (decltype(glBufferSubData)) wglGetProcAddress(\"glBufferSubData\");\n  glBufferData = (decltype(glBufferData)) wglGetProcAddress(\"glBufferData\");\n  glDeleteBuffers = (decltype(glDeleteBuffers)) wglGetProcAddress(\"glDeleteBuffers\");\n  glGenBuffers = (decltype(glGenBuffers)) wglGetProcAddress(\"glGenBuffers\");\n  if(!glBindBuffer) throw std::runtime_error(\"Could not load OpenGL functions!\");\n#endif\n\n  glCheckFramebufferStatus = (decltype(glCheckFramebufferStatus )) wglGetProcAddress(\"glCheckFramebufferStatus\");\n  glBindFramebuffer = (decltype(glBindFramebuffer )) wglGetProcAddress(\"glBindFramebuffer\");\n  glBindRenderbuffer = (decltype(glBindRenderbuffer )) wglGetProcAddress(\"glBindRenderbuffer\");\n  glDeleteFramebuffers = (decltype(glDeleteFramebuffers )) wglGetProcAddress(\"glDeleteFramebuffers\");\n  glDeleteRenderbuffers = (decltype(glDeleteRenderbuffers )) wglGetProcAddress(\"glDeleteRenderbuffers\");\n  glGenFramebuffers = (decltype(glGenFramebuffers )) wglGetProcAddress(\"glGenFramebuffers\");\n  glGenRenderbuffers = (decltype(glGenRenderbuffers )) wglGetProcAddress(\"glGenRenderbuffers\");\n  glRenderbufferStorage = (decltype(glRenderbufferStorage )) wglGetProcAddress(\"glRenderbufferStorage\");\n  glFramebufferRenderbuffer = (decltype(glFramebufferRenderbuffer )) wglGetProcAddress(\"glFramebufferRenderbuffer\");\n}\n#else  // WIN32\nNGGUI_API void LoadOpenGLFunctionPointers() { }\n#endif // WIN32\n#endif // OPENGL\n\n// set function pointers\nstatic bool dummy_init = [](){\n    Ptr_Ng_ClearSolutionData = Impl_Ng_ClearSolutionData;\n    Ptr_Ng_InitSolutionData = Impl_Ng_InitSolutionData;\n    Ptr_Ng_SetSolutionData = Impl_Ng_SetSolutionData;\n    Ptr_Ng_Redraw = Impl_Ng_Redraw;\n    return true;\n}();\n"
  },
  {
    "path": "libsrc/visualization/vssolution.hpp",
    "content": "#ifndef FILE_VSSOLUTION\n#define FILE_VSSOLUTION\n\n#include \"visual_api.hpp\"\n#include \"mvdraw.hpp\"\n\ntypedef void * ClientData;\nstruct Tcl_Interp;\n\n\nnamespace netgen\n{\n\nNGGUI_API extern void ImportSolution (const char * filename);\n\n\n  extern int Ng_Vis_Set (ClientData clientData,\n                         Tcl_Interp * interp,\n                         int argc, const char *argv[]);\n\n\n\nclass NGGUI_API VisualSceneSolution : public VisualScene\n{\n  friend class FieldLineCalc;\n  \n  class ClipPlaneTrig\n  {\n  public:\n    struct ps \n    {\n      int pnr, locpnr;\n    };\n    ps points[3];\n    ElementIndex elnr;\n  };\n\n  class ClipPlanePoint\n  {\n  public:\n    ElementIndex elnr;\n    Point<3> lami;\n    Point<3> p;\n  };\n\n#ifndef WIN32\n  // use OpenGL vertex buffers from OpenGL 2.x\n  // not supported by some drivers on windows\n  // try on your own responsibility \n#define USE_BUFFERS\n#endif\n  \n#ifdef USE_BUFFERS\n  bool has_surfel_vbo = false;\n  GLuint surfel_vbo[4]; //\n  size_t surfel_vbo_size;\n#endif\n  int surfellist;\n  int linelist;\n  int element1dlist;\n  int clipplanelist_scal;\n  int clipplanelist_vec;\n  int isolinelist;\n  int clipplane_isolinelist;\n  int surface_vector_list;\n  // int cone_list;\n  int isosurface_list;\n  int select_sel_list;\n\n  int pointcurvelist;\n\n  bool draw_fieldlines;\n  bool drawpointcurves;\n  bool draw_isosurface;\n  int num_fieldlines;\n  bool fieldlines_randomstart;\n  int fieldlineslist;\n  int num_fieldlineslists;\n  int fieldlines_startarea;\n  NgArray<double> fieldlines_startarea_parameter;\n  int fieldlines_startface;\n  string fieldlines_filename;\n  double fieldlines_reltolerance;\n  int fieldlines_rktype;\n  double fieldlines_rellength;\n  double fieldlines_relthickness;\n  int fieldlines_vecfunction;\n  bool fieldlines_fixedphase;\n  float fieldlines_phase;\n  int fieldlines_maxpoints;\n\n\n  int surfeltimestamp, clipplanetimestamp, solutiontimestamp;\n  int surfellinetimestamp;\n  int fieldlinestimestamp, surface_vector_timestamp;\n  int pointcurve_timestamp;\n  int isosurface_timestamp;\n  int timetimestamp;\n  double minval, maxval;\n\n  int scalfunction, vecfunction;\n  string number_format = \"%8.3e\";\n  string unit = \"\";\n  string title = \"\";\n\n  NgLock *lock;\n\n  VisualSelect select;\n#ifdef PARALLELGL\n  NgArray<int> par_linelists;\n  NgArray<int> par_surfellists;\n#endif\n\n  NgArray<UserVisualizationObject*> user_vis;\n\npublic:\n\n  enum EvalFunc { \n    FUNC_ABS = 1, \n    FUNC_ABS_TENSOR = 2,\n    FUNC_MISES = 3, \n    FUNC_MAIN = 4\n  };\n  int evalfunc;\n\n  enum SolType\n    { \n      SOL_NODAL = 1, \n      SOL_ELEMENT = 2, \n      SOL_SURFACE_ELEMENT = 3, \n      SOL_NONCONTINUOUS = 4, \n      SOL_SURFACE_NONCONTINUOUS = 5,\n      SOL_VIRTUALFUNCTION = 6,\n      SOL_MARKED_ELEMENTS = 10,\n      SOL_ELEMENT_ORDER = 11,\n    };\n\n  class SolData\n  {\n  public:\n    SolData ();\n    ~SolData ();\n    \n    string name;\n    string number_format = \"%8.3e\";\n    string unit = \"\";\n    string title = \"\";\n    double * data;\n    int components;\n    int dist;\n    int order;\n    bool iscomplex;\n    bool draw_volume;\n    bool draw_surface;\n    std::shared_ptr<BitArray> draw_volumes, draw_surfaces;\n    SolType soltype;\n    SolutionData * solclass;\n\n    // internal variables:\n    int size;\n  };\n\n  \n\n\n  NgArray<SolData*> soldata;\n\n\n  int usetexture;    // 0..no, 1..1D texture (standard), 2..2D-texture (complex)\n  int clipsolution;  // 0..no, 1..scal, 2..vec\n  int scalcomp;\n  int gridsize;\n  double xoffset, yoffset;\n\n  int autoscale, logscale;\n  double mminval, mmaxval;\n  int numisolines;\n\n  bool showclipsolution;\n  bool showsurfacesolution;\n  bool lineartexture;\n  int numtexturecols;\n\n  int multidimcomponent;\n\n  // bool fieldlineplot;\n  double time;\n\n  int deform;\n  double scaledeform;\n  bool imag_part;\n\nprivate:\n  void BuildFieldLinesFromFile(Array<Point<3>> & startpoints);\n  void BuildFieldLinesFromFace(Array<Point<3>> & startpoints);\n  void BuildFieldLinesFromBox(Array<Point<3>> & startpoints);\n  void BuildFieldLinesFromLine(Array<Point<3>> & startpoints);\n  // weak_ptr<Mesh> wp_mesh;\npublic:\n  VisualSceneSolution ();\n  virtual ~VisualSceneSolution ();\n\n  virtual void BuildScene (int zoomall = 0);\n  virtual void DrawScene ();\n  void BuildSelectionList();\n  virtual void MouseDblClick (int px, int py);\n\n  // void SetMesh (shared_ptr<Mesh> amesh);\n  // shared_ptr<Mesh> GetMesh () { return shared_ptr<Mesh>(wp_mesh); }\n  shared_ptr<Mesh> GetMesh () const { return GetGlobalMesh(); }\n\n  void BuildFieldLinesPlot ();\n\n  void AddSolutionData (SolData * soldata);\n  void ClearSolutionData ();\n  void UpdateSolutionTimeStamp ();\n  SolData * GetSolData (int i);\n  int GetNSolData () { return soldata.Size(); }\n\n  void SaveSolutionData (const char * filename);\n\n  /*\n  static void RealVec3d (const double * values, Vec3d & v, \n\t\t\t bool iscomplex, bool imag);\n  */\n  static Vec<3> RealVec3d (const double * values, \n\t\t\t   bool iscomplex, bool imag);\n\n  static void RealVec3d (const double * values, Vec3d & v, \n\t\t\t bool iscomplex, double phaser, double phasei);\n\n\n  void SetSubdivision (int sd)\n  {\n    subdivisions = sd;\n    subdivision_timestamp = solutiontimestamp = NextTimeStamp();\n  }\n\n  void GetMinMax (int funcnr, int comp, double & minv, double & maxv) const;\n\n  void AddUserVisualizationObject (UserVisualizationObject * vis)\n  {\n    user_vis.Append (vis);\n  }\n  void DeleteUserVisualizationObject (UserVisualizationObject * vis)\n  {\n    int pos = user_vis.Pos(vis);\n    if (pos >= 0)\n      user_vis.Delete(pos);\n  }\n\nprivate:\n  void GetClippingPlaneTrigs (SolData * sol, NgArray<ClipPlaneTrig> & trigs, NgArray<ClipPlanePoint> & pts);\n  void GetClippingPlaneGrid (NgArray<ClipPlanePoint> & pts);\n  void DrawCone (const Point<3> & p1, const Point<3> & p2, double r);\n  void DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r);\n\n  bool SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & sei) const;\n  bool VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & ei) const;\n\n  // Get Function Value, local coordinates lam1, lam2, lam3, \n  bool GetValue (const SolData * data, ElementIndex elnr, \n\t\t   double lam1, double lam2, double lam3,\n\t\t   int comp, double & val) const;\n\n  bool GetValue (const SolData * data, ElementIndex elnr,\n\t\t const double xref[], const double x[], const double dxdxref[], \n\t\t int comp, double & val) const;\n\n  bool GetValueComplex (const SolData * data, ElementIndex elnr, \n\t\t\tdouble lam1, double lam2, double lam3,\n\t\t\tint comp, complex<double> & val) const;\n\n  bool GetValues (const SolData * data, ElementIndex elnr, \n\t\t  double lam1, double lam2, double lam3,\n\t\t  double * values) const;\n\n  bool GetValues (const SolData * data, ElementIndex elnr, \n\t\t  const double xref[], const double x[], const double dxdxref[], \n\t\t  double * values) const;\n\n  bool GetMultiValues (const SolData * data, ElementIndex elnr, int facetnr, int npt,\n\t\t       const double * xref, int sxref,\n\t\t       const double * x, int sx,\n\t\t       const double * dxdxref, int sdxdxref,\n\t\t       double * val, int sval) const;\n\n\n  bool GetSurfValue (const SolData * data, SurfaceElementIndex elnr, int facetnr,\n\t\t     double lam1, double lam2, \n\t\t     int comp, double & val) const;\n\n  bool GetSurfValue (const SolData * data, SurfaceElementIndex elnr, int facetnr, \n\t\t     const double xref[], const double x[], const double dxdxref[], \n\t\t     int comp, double & val) const;\n\n  \n  bool GetSurfValueComplex (const SolData * data, SurfaceElementIndex elnr, int facetnr, \n\t\t\t    double lam1, double lam2, \n\t\t\t    int comp, complex<double> & val) const;\n\n  bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, \n\t\t      double lam1, double lam2, \n\t\t      double * values) const;\n\n  bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, \n\t\t      const double xref[], const double x[], const double dxdxref[], \n\t\t      double * values) const;\n\n  bool GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, \n\t\t\t   int npt,\n                           const double * xref, int sxref,\n                           const double * x, int sx,\n                           const double * dxdxref, int sdxdxref,\n                           double * val, int sval) const;\n  \n  double ExtractValue (const SolData * data, int comp, double * values) const;\n  complex<double> ExtractValueComplex (const SolData * data, int comp, double * values) const;\n\n\n  Vec<3> GetDeformation (ElementIndex elnr, const Point<3> & p) const;\n  Vec<3> GetSurfDeformation (SurfaceElementIndex selnr, int facetnr, double lam1, double lam2) const;\n\n  void GetPointDeformation (PointIndex pnum, Point<3> & p, SurfaceElementIndex elnr = -1) const;\n\npublic:\n  /// draw elements (build lists)\n  void DrawSurfaceElements ();\n  void DrawSurfaceElementLines ();\n  void Draw1DElements();\n\n  void DrawSurfaceVectors ();\n  void DrawTrigSurfaceVectors(const NgArray< Point<3> > & lp, const Point<3> & pmin, const Point<3> & pmax,\n\t\t\t      const int sei, const SolData * vsol, bool swap_lam=false);\n  void DrawIsoSurface(const SolData * sol, const SolData * grad, int comp);\n  \n  void DrawIsoLines (const Point<3> & p1, \n\t\t     const Point<3> & p2, \n\t\t     const Point<3> & p3,\n\t\t     double val1, double val2, double val3);\n\n  // draw isolines between lines (p1,p2) and (p3,p4)\n  void DrawIsoLines2 (const Point<3> & p1, \n\t\t      const Point<3> & p2, \n\t\t      const Point<3> & p3,\n\t\t      const Point<3> & p4,\n\t\t      double val1, double val2, double val3, double val4);\n\n\n  void DrawClipPlaneTrigs (); // const SolData * sol, int comp);\n\t\t  \n  void SetOpenGlColor(double val);\n\n  // 0 .. non, 1 .. scalar, 2 .. complex\n  void SetTextureMode (int texturemode) const;\n\n\n  friend int Ng_Vis_Set (ClientData clientData,\n                         Tcl_Interp * interp,\n\t\t\t int argc, const char *argv[]);\n\n  void SetScalfunction( int i ) {\n      scalfunction = i;\n      title = soldata[i]->title;\n      number_format = soldata[i]->number_format;\n      unit = soldata[i]->unit;\n  }\n\n  void SetVecfunction( int i ) {\n      vecfunction = i;\n      title = soldata[i]->title;\n      number_format = soldata[i]->number_format;\n      unit = soldata[i]->unit;\n  }\n\n  SolData* GetScalFunction() const { return scalfunction == -1 ? nullptr : soldata[scalfunction]; }\n  SolData* GetVecFunction() const { return vecfunction == -1 ? nullptr : soldata[vecfunction]; }\n  SolData* GetScalOrVecFunction() const { auto sol = GetScalFunction(); return sol ? sol : GetVecFunction(); }\n\n#ifdef PARALLELGL\n  void Broadcast ();\n#endif\n\n\n};\n\nNGGUI_API VisualSceneSolution & GetVSSolution();\n\ninline void AddUserVisualizationObject (UserVisualizationObject * vis)\n{\n    GetVSSolution().AddUserVisualizationObject (vis);\n}\n\ninline void DeleteUserVisualizationObject (UserVisualizationObject * vis)\n{\n    GetVSSolution().DeleteUserVisualizationObject (vis);\n}\n\n\n}\n\n#endif\n\n"
  },
  {
    "path": "mkinstalldirs",
    "content": "#! /bin/sh\n# mkinstalldirs --- make directory hierarchy\n# Author: Noah Friedman <friedman@prep.ai.mit.edu>\n# Created: 1993-05-16\n# Public domain\n\nerrstatus=0\ndirmode=\"\"\n\nusage=\"\\\nUsage: mkinstalldirs [-h] [--help] [-m mode] dir ...\"\n\n# process command line arguments\nwhile test $# -gt 0 ; do\n  case $1 in\n    -h | --help | --h*)         # -h for help\n      echo \"$usage\" 1>&2\n      exit 0\n      ;;\n    -m)                         # -m PERM arg\n      shift\n      test $# -eq 0 && { echo \"$usage\" 1>&2; exit 1; }\n      dirmode=$1\n      shift\n      ;;\n    --)                         # stop option processing\n      shift\n      break\n      ;;\n    -*)                         # unknown option\n      echo \"$usage\" 1>&2\n      exit 1\n      ;;\n    *)                          # first non-opt arg\n      break\n      ;;\n  esac\ndone\n\nfor file\ndo\n  if test -d \"$file\"; then\n    shift\n  else\n    break\n  fi\ndone\n\ncase $# in\n  0) exit 0 ;;\nesac\n\ncase $dirmode in\n  '')\n    if mkdir -p -- . 2>/dev/null; then\n      echo \"mkdir -p -- $*\"\n      exec mkdir -p -- \"$@\"\n    fi\n    ;;\n  *)\n    if mkdir -m \"$dirmode\" -p -- . 2>/dev/null; then\n      echo \"mkdir -m $dirmode -p -- $*\"\n      exec mkdir -m \"$dirmode\" -p -- \"$@\"\n    fi\n    ;;\nesac\n\nfor file\ndo\n  set fnord `echo \":$file\" | sed -ne 's/^:\\//#/;s/^://;s/\\// /g;s/^#/\\//;p'`\n  shift\n\n  pathcomp=\n  for d\n  do\n    pathcomp=\"$pathcomp$d\"\n    case $pathcomp in\n      -*) pathcomp=./$pathcomp ;;\n    esac\n\n    if test ! -d \"$pathcomp\"; then\n      echo \"mkdir $pathcomp\"\n\n      mkdir \"$pathcomp\" || lasterr=$?\n\n      if test ! -d \"$pathcomp\"; then\n  \terrstatus=$lasterr\n      else\n  \tif test ! -z \"$dirmode\"; then\n\t  echo \"chmod $dirmode $pathcomp\"\n    \t  lasterr=\"\"\n  \t  chmod \"$dirmode\" \"$pathcomp\" || lasterr=$?\n\n  \t  if test ! -z \"$lasterr\"; then\n  \t    errstatus=$lasterr\n  \t  fi\n  \tfi\n      fi\n    fi\n\n    pathcomp=\"$pathcomp/\"\n  done\ndone\n\nexit $errstatus\n\n# Local Variables:\n# mode: shell-script\n# sh-indentation: 2\n# End:\n# mkinstalldirs ends here\n"
  },
  {
    "path": "ng/CMakeLists.txt",
    "content": "if(USE_INTERNAL_TCL)\n  add_definitions(-DINTERNAL_TCL_DEFAULT=1)\nelse()\n  add_definitions(-DINTERNAL_TCL_DEFAULT=0)\nendif()\n\nif(WIN32)\n  # add icon and version info to netgen executable\n  enable_language(RC)\n  # Don't use ccache here due to incompatibility with the resource compiler\n  set_directory_properties(PROPERTIES RULE_LAUNCH_COMPILE \"\")\nendif(WIN32)\n\ntarget_sources(nglib PRIVATE onetcl.cpp)\n\nif(USE_GUI)\n    target_sources(nggui PRIVATE\n        gui.cpp ngpkg.cpp demoview.cpp parallelfunc.cpp ngtcl.cpp\n    )\n\n    if(NOT BUILD_FOR_CONDA)\n      add_executable(netgen ngappinit.cpp)\n    if(WIN32)\n      target_sources(netgen PRIVATE ../windows/netgen.rc)\n    endif(WIN32)\n    target_link_libraries( netgen nglib nggui netgen_python netgen_gui)\n    install(TARGETS netgen ${NG_INSTALL_DIR})\n    if(APPLE)\n        set_target_properties(netgen PROPERTIES OUTPUT_NAME netgen)\n    endif(APPLE)\n    target_link_libraries( netgen ${Python3_LIBRARIES} ${TCL_LIBRARY} ${TK_LIBRARY})\n    endif(NOT BUILD_FOR_CONDA)\n\n    install(TARGETS nggui ${NG_INSTALL_DIR})\nendif(USE_GUI)\n\nif(USE_PYTHON)\n    add_library(ngpy SHARED netgenpy.cpp)\n    target_link_libraries( ngpy PUBLIC nglib PRIVATE \"$<BUILD_INTERFACE:netgen_python>\" )\n    target_link_libraries( ngpy PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} occ_libs netgen_cgns )\n    if(EMSCRIPTEN)\n        target_link_options(ngpy PUBLIC -sALLOW_MEMORY_GROWTH -sENVIRONMENT=web -sWASM_BIGINT -fwasm-exceptions)\n    endif()\n    if(APPLE)\n        set_target_properties( ngpy PROPERTIES SUFFIX \".so\")\n    elseif(WIN32)\n        set_target_properties( ngpy PROPERTIES SUFFIX \".pyd\")\n        set_target_properties( ngpy PROPERTIES OUTPUT_NAME \"libngpy\")\n    endif()\n    set_target_properties(ngpy PROPERTIES INSTALL_RPATH \"${NG_RPATH_TOKEN}/../${NETGEN_PYTHON_RPATH}\")\n    install(TARGETS ngpy DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX} COMPONENT netgen EXPORT netgen-targets)\n\n    if(USE_GUI)\n        add_library(ngguipy SHARED ngguipy.cpp)\n        target_link_libraries( ngguipy PUBLIC nglib nggui PRIVATE \"$<BUILD_INTERFACE:netgen_python>\" $<BUILD_INTERFACE:netgen_gui>)\n        if(APPLE)\n            set_target_properties( ngguipy PROPERTIES SUFFIX \".so\")\n        elseif(WIN32)\n            set_target_properties( ngguipy PROPERTIES SUFFIX \".pyd\")\n            set_target_properties( ngguipy PROPERTIES OUTPUT_NAME \"libngguipy\")\n        endif()\n        set_target_properties(ngguipy PROPERTIES INSTALL_RPATH \"${NG_RPATH_TOKEN}/../${NETGEN_PYTHON_RPATH}\")\n        install(TARGETS ngguipy DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX} COMPONENT netgen EXPORT netgen-targets)\n    endif(USE_GUI)\nendif(USE_PYTHON)\n\nif(USE_GUI)\n  if(NOT USE_INTERNAL_TCL)\n    install(FILES\n        dialog.tcl menustat.tcl ngicon.tcl ng.tcl\n        ngvisual.tcl sockets.tcl nghelp.tcl ngshell.tcl\n        ngtesting.tcl parameters.tcl variables.tcl csgeom.tcl stlgeom.tcl\n        occgeom.tcl acisgeom.tcl netgen.ocf drawing.tcl\n        DESTINATION ${NG_INSTALL_DIR_BIN} COMPONENT netgen)\n  endif()\n\n  add_subdirectory(Togl2.1)\nendif(USE_GUI)\n\n"
  },
  {
    "path": "ng/Togl2.1/CMakeLists.txt",
    "content": "\nif(APPLE)\n    set(CMAKE_C_COMPILER \"/usr/bin/gcc\")\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -x objective-c\")\nendif(APPLE)\n\nif(WIN32)\n    set(TOGL_LIBRARY_TYPE SHARED)\nelse(WIN32)\n    set(TOGL_LIBRARY_TYPE STATIC)\nendif(WIN32)\n\nadd_library(togl ${TOGL_LIBRARY_TYPE} togl.c toglProcAddr.c toglStubInit.c)\ntarget_link_libraries( togl PUBLIC $<BUILD_INTERFACE:netgen_gui>)\n\ntarget_compile_definitions(togl PRIVATE -DBUILD_togl=1 -DSTDC_HEADERS=1)\n\nif(WIN32)\n  target_compile_definitions(togl PRIVATE -DUNICODE -D_UNICODE -DTOGL_USE_FONTS=0 -DSTDC_HEADER)\nelse(WIN32)\n  target_compile_options(togl PRIVATE -fomit-frame-pointer -Wno-implicit-int)\n  target_compile_definitions(togl PRIVATE -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=0 -DHAVE_LIMITS_H=1 -DHAVE_SYS_PARAM_H=1 -DUSE_THREAD_ALLOC=1 -D_REENTRANT=1 -D_THREAD_SAFE=1 -DTCL_THREADS=1 -D_LARGEFILE64_SOURCE=1 -DTCL_WIDE_INT_IS_LONG=1) \n\n  include_directories(BEFORE \"${TCL_INCLUDE_PATH}/tcl-private/generic\" \"${TCL_INCLUDE_PATH}/tcl-private/unix\")\n  include_directories(BEFORE \"${TK_INCLUDE_PATH}/tk-private/generic\" \"${TK_INCLUDE_PATH}/tk-private/unix\" \"${TK_INCLUDE_PATH}/tk-private\")\n  include_directories(BEFORE \"${TCL_INCLUDE_PATH}/tk-private/generic/ttk\") \n  include_directories(BEFORE \"${TK_INCLUDE_PATH}/../PrivateHeaders\") \n  include_directories(BEFORE \"${TCL_INCLUDE_PATH}\") \n  include_directories(BEFORE \"${TK_INCLUDE_PATH}\") \n\nendif(WIN32)\n\ntarget_include_directories(togl PUBLIC ${OPENGL_INCLUDE_DIR})\ntarget_link_libraries(togl PUBLIC ${OPENGL_LIBRARY})\nset_target_properties(togl PROPERTIES POSITION_INDEPENDENT_CODE ON )\ninstall(TARGETS togl DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)\n"
  },
  {
    "path": "ng/Togl2.1/LICENSE",
    "content": "This software is copyrighted by Brian Paul (brian@mesa3d.org),\nBenjamin Bederson (bederson@cs.umd.edu), and Greg Couch\n(gregcouch@users.sourceforge.net).  The following terms apply to all\nfiles associated with the software unless explicitly disclaimed in\nindividual files.\n\nThe authors hereby grant permission to use, copy, modify, distribute,\nand license this software and its documentation for any purpose, provided\nthat existing copyright notices are retained in all copies and that this\nnotice is included verbatim in any distributions.  No written agreement,\nlicense, or royalty fee is required for any of the authorized uses.\nModifications to this software may be copyrighted by their authors\nand need not follow the licensing terms described here, provided that\nthe new terms are clearly indicated on the first page of each file where\nthey apply.\n\nIN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY\nFOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\nARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY\nDERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\nTHE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE\nIS PROVIDED ON AN \"AS IS\" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE\nNO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR\nMODIFICATIONS.\n"
  },
  {
    "path": "ng/Togl2.1/Makefile.in",
    "content": "# Makefile.in --\n#\n#\tThis file is a Makefile for Sample TEA Extension.  If it has the name\n#\t\"Makefile.in\" then it is a template for a Makefile;  to generate the\n#\tactual Makefile, run \"./configure\", which is a configuration script\n#\tgenerated by the \"autoconf\" program (constructs like \"@foo@\" will get\n#\treplaced in the actual Makefile.\n#\n# Copyright (c) 1999 Scriptics Corporation.\n# Copyright (c) 2002-2005 ActiveState Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n# RCS: @(#) $Id: Makefile.in,v 1.26 2009/12/23 21:46:16 gregcouch Exp $\n\n#========================================================================\n# Add additional lines to handle any additional AC_SUBST cases that\n# have been added in a customized configure script.\n#========================================================================\n\n#SAMPLE_NEW_VAR\t= @SAMPLE_NEW_VAR@\nSHLIB_SUFFIX\t= @SHLIB_SUFFIX@\nMATH_LIBS\t= @MATH_LIBS@\nLIBGLU\t\t= @LIBGLU@\n\nEXAMPLE_SRCS\t= double.c gears.c index.c overlay.c stereo.c texture.c pbuffer.c\nEXAMPLE_OBJS\t= $(EXAMPLE_SRCS:.c=.$(OBJEXT))\nEXAMPLE_SHLIBS\t= $(EXAMPLE_SRCS:.c=$(SHLIB_SUFFIX))\n\n#========================================================================\n# Nothing of the variables below this line should need to be changed.\n# Please check the TARGETS section below to make sure the make targets\n# are correct.\n#========================================================================\n\n#========================================================================\n# The names of the source files is defined in the configure script.\n# The object files are used for linking into the final library.\n# This will be used when a dist target is added to the Makefile.\n# It is not important to specify the directory, as long as it is the\n# $(srcdir) or in the generic, win or unix subdirectory.\n#========================================================================\n\nPKG_SOURCES\t= @PKG_SOURCES@\nPKG_OBJECTS\t= @PKG_OBJECTS@\n\nPKG_STUB_SOURCES = @PKG_STUB_SOURCES@\nPKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@\n\n#========================================================================\n# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with\n# this package that need to be installed, if any.\n#========================================================================\n\nPKG_TCL_SOURCES = @PKG_TCL_SOURCES@\n\n#========================================================================\n# This is a list of public header files to be installed, if any.\n#========================================================================\n\nPKG_HEADERS\t= @PKG_HEADERS@ togl_ws.h\n\n#========================================================================\n# \"PKG_LIB_FILE\" refers to the library (dynamic or static as per\n# configuration options) composed of the named objects.\n#========================================================================\n\nPKG_LIB_FILE\t= @PKG_LIB_FILE@\nPKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@\n\npkglib_BINARIES\t= $(PKG_LIB_FILE)\nlib_BINARIES\t= $(PKG_STUB_LIB_FILE)\nBINARIES\t= $(pkglib_BINARIES) $(lib_BINARIES)\n\nSHELL\t\t= @SHELL@\n\nsrcdir\t\t= @srcdir@\nprefix\t\t= @prefix@\nexec_prefix\t= @exec_prefix@\n\nbindir\t\t= @bindir@\nlibdir\t\t= @libdir@\nincludedir\t= @includedir@\ndatarootdir\t= @datarootdir@\ndatadir\t\t= @datadir@\nmandir\t\t= @mandir@\n\nDESTDIR\t\t=\n\nPKG_DIR\t\t= $(PACKAGE_NAME)$(PACKAGE_VERSION)\npkgdatadir\t= $(datadir)/$(PKG_DIR)\npkglibdir\t= $(libdir)/$(PKG_DIR)\npkgincludedir\t= $(includedir)/$(PKG_DIR)\n\ntop_builddir\t= .\n\nINSTALL\t\t= @INSTALL@\nINSTALL_PROGRAM\t= @INSTALL_PROGRAM@\nINSTALL_DATA\t= @INSTALL_DATA@\nINSTALL_SCRIPT\t= @INSTALL_SCRIPT@\n\nPACKAGE_NAME\t= @PACKAGE_NAME@\nPACKAGE_VERSION\t= @PACKAGE_VERSION@\nCC\t\t= @CC@\nCFLAGS_DEFAULT\t= @CFLAGS_DEFAULT@\nCFLAGS_WARNING\t= @CFLAGS_WARNING@\nEXEEXT\t\t= @EXEEXT@\nLDFLAGS_DEFAULT\t= @LDFLAGS_DEFAULT@\nMAKE_LIB\t= @MAKE_LIB@\nMAKE_SHARED_LIB\t= @MAKE_SHARED_LIB@\nMAKE_STATIC_LIB\t= @MAKE_STATIC_LIB@\nMAKE_STUB_LIB\t= @MAKE_STUB_LIB@\nOBJEXT\t\t= @OBJEXT@\nRANLIB\t\t= @RANLIB@\nRANLIB_STUB\t= @RANLIB_STUB@\nSHLIB_CFLAGS\t= @SHLIB_CFLAGS@\nSHLIB_LD\t= @SHLIB_LD@\nSHLIB_LD_LIBS\t= @SHLIB_LD_LIBS@\nSTLIB_LD\t= @STLIB_LD@\n#TCL_DEFS\t= @TCL_DEFS@\nTCL_BIN_DIR\t= @TCL_BIN_DIR@\nTCL_SRC_DIR\t= @TCL_SRC_DIR@\n#TK_BIN_DIR\t= @TK_BIN_DIR@\n#TK_SRC_DIR\t= @TK_SRC_DIR@\n\n# Not used, but retained for reference of what libs Tcl required\n#TCL_LIBS\t= @TCL_LIBS@\n\n#========================================================================\n# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our\n# package without installing.  The other environment variables allow us\n# to test against an uninstalled Tcl.  Add special env vars that you\n# require for testing here (like TCLX_LIBRARY).\n#========================================================================\n\n#EXTRA_PATH\t= $(top_builddir):$(TCL_BIN_DIR)\nEXTRA_PATH\t= $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)\nTCLLIBPATH\t= $(top_builddir)\nTCLSH_ENV\t= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \\\n\t\t  @LD_LIBRARY_PATH_VAR@=\"$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)\" \\\n\t\t  PATH=\"$(EXTRA_PATH):$(PATH)\" \\\n\t\t  TCLLIBPATH=\"$(TCLLIBPATH)\"\n#\t\t  TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`\n\nTCLSH_PROG\t= @TCLSH_PROG@\nTCLSH\t= $(TCLSH_ENV) $(TCLSH_PROG)\n\nWISH_PROG\t= @WISH_PROG@\nWISH\t= $(TCLSH_ENV) $(WISH_PROG)\n\n\nSHARED_BUILD\t= @SHARED_BUILD@\n\nINCLUDES\t= -I. @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@\n\nPKG_CFLAGS\t= @PKG_CFLAGS@\n\n# TCL_DEFS is not strictly need here, but if you remove it, then you\n# must make sure that configure.in checks for the necessary components\n# that your library may use.  TCL_DEFS can actually be a problem if\n# you do not compile with a similar machine setup as the Tcl core was\n# compiled with.\n#DEFS\t\t= $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)\nDEFS\t\t= @DEFS@ -DAUTOSTEREOD=\\\"@AUTOSTEREOD@\\\" $(PKG_CFLAGS)\n\nCONFIG_CLEAN_FILES = Makefile pkgIndex.tcl togl_ws.h\nCLEANFILES\t= @CLEANFILES@ $(EXAMPLE_OBJS) $(EXAMPLE_SHLIBS)\n\nCPPFLAGS\t= @CPPFLAGS@\nLIBS\t\t= @PKG_LIBS@ @LIBS@\nAR\t\t= @AR@\nCFLAGS\t\t= @CFLAGS@\nCOMPILE\t\t= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)\n\n#========================================================================\n# Start of user-definable TARGETS section\n#========================================================================\n\n#========================================================================\n# TEA TARGETS.  Please note that the \"libraries:\" target refers to platform\n# independent files, and the \"binaries:\" target includes executable programs and\n# platform-dependent libraries.  Modify these targets so that they install\n# the various pieces of your package.  The make and install rules\n# for the BINARIES that you specified above have already been done.\n#========================================================================\n\nall: binaries libraries doc\n\n#========================================================================\n# The binaries target builds executable programs, Windows .dll's, unix\n# shared/static libraries, and any other platform-dependent files.\n# The list of targets to build for \"binaries:\" is specified at the top\n# of the Makefile, in the \"BINARIES\" variable.\n#========================================================================\n\nbinaries: $(BINARIES)\n\nlibraries:\n\n#========================================================================\n# Example section.  These are examples because we don't want to install them.\n# And they're not tests because we currently have no automatic way to see\n# if they work.\n#========================================================================\n\nexamples: $(EXAMPLE_SHLIBS)\n\ndouble$(SHLIB_SUFFIX): double.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"double.$(OBJEXT) $(PKG_STUB_LIB_FILE)\" $@ ; \\\n\tfi\n\ngears$(SHLIB_SUFFIX): gears.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"gears.$(OBJEXT) $(PKG_STUB_LIB_FILE)\" $@ ; \\\n\tfi\n\nindex$(SHLIB_SUFFIX): index.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"index.$(OBJEXT) $(PKG_STUB_LIB_FILE)\" $@ ; \\\n\tfi\n\noverlay$(SHLIB_SUFFIX): overlay.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"overlay.$(OBJEXT) $(PKG_STUB_LIB_FILE)\" $@ ; \\\n\tfi\n\nstereo$(SHLIB_SUFFIX): stereo.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"stereo.$(OBJEXT) $(PKG_STUB_LIB_FILE)\" $@ ; \\\n\tfi\n\ntexture$(SHLIB_SUFFIX): texture.$(OBJEXT) image.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"texture.$(OBJEXT) image.$(OBJEXT) $(PKG_STUB_LIB_FILE) $(LIBGLU)\" $@ ; \\\n\tfi\n\npbuffer$(SHLIB_SUFFIX): pbuffer.$(OBJEXT) $(PKG_STUB_LIB_FILE)\n\t-match=`expr 'x$(PKG_OBJECTS)' : '.*togl.*'`; \\\n\tif [ $$match -eq 0 ]; then \\\n\t\t$(MAKE_SHARED_LIB) ; \\\n\telse \\\n\t\t$(MAKE) PKG_OBJECTS=\"pbuffer.$(OBJEXT) $(PKG_STUB_LIB_FILE) $(LIBGLU)\" $@ ; \\\n\tfi\n\n#========================================================================\n# Stub section.\n#========================================================================\n\ntoglDecls.h toglStubInit.c: togl.decls\n\t$(TCLSH) `@CYGPATH@ $(TCL_SRC_DIR)/tools/genStubs.tcl` . togl.decls\n\n#========================================================================\n# Your doc target should differentiate from doc builds (by the developer)\n# and doc installs (see install-doc), which just install the docs on the\n# end user machine when building from source.\n#========================================================================\n\ndoc:\n#\t@echo \"If you have documentation to create, place the commands to\"\n#\t@echo \"build the docs in the 'doc:' target.  For example:\"\n#\t@echo \"        xml2nroff sample.xml > sample.n\"\n#\t@echo \"        xml2html sample.xml > sample.html\"\n\ninstall: all install-binaries install-libraries install-doc\n\ninstall-binaries: binaries install-lib-binaries install-bin-binaries\n\n#========================================================================\n# This rule installs platform-independent files, such as header files.\n# The list=...; for p in $$list handles the empty list case x-platform.\n#========================================================================\n\ninstall-libraries: libraries\n\t@mkdir -p $(DESTDIR)$(includedir)\n\t@echo \"Installing header files in $(DESTDIR)$(includedir)\"\n\t@list='$(PKG_HEADERS)'; for i in $$list; do \\\n\t    echo \"Installing $(srcdir)/$$i\" ; \\\n\t    $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \\\n\tdone\n\n#========================================================================\n# Install documentation.  Unix manpages should go in the $(mandir)\n# directory.\n#========================================================================\n\ninstall-doc: doc\n#\t@mkdir -p $(DESTDIR)$(mandir)/mann\n#\t@echo \"Installing documentation in $(DESTDIR)$(mandir)\"\n#\t@list='$(srcdir)/doc/*.n'; for i in $$list; do \\\n#\t    echo \"Installing $$i\"; \\\n#\t    rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \\\n#\t    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \\\n#\tdone\n\ntest: binaries libraries\n\t$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)\n\nshell: binaries libraries\n\t@$(TCLSH) $(SCRIPT)\n\ngdb:\n\t$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)\n\ndepend:\n\n#========================================================================\n# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable\n# mentioned above.  That will ensure that this target is built when you\n# run \"make binaries\".\n#\n# The $(PKG_OBJECTS) objects are created and linked into the final\n# library.  In most cases these object files will correspond to the\n# source files above.\n#========================================================================\n\n$(PKG_LIB_FILE): $(PKG_OBJECTS)\n\t-rm -f $(PKG_LIB_FILE)\n\t${MAKE_LIB}\n\t$(RANLIB) $(PKG_LIB_FILE)\n\n$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)\n\t-rm -f $(PKG_STUB_LIB_FILE)\n\t${MAKE_STUB_LIB}\n\t$(RANLIB_STUB) $(PKG_STUB_LIB_FILE)\n\n#========================================================================\n# We need to enumerate the list of .c to .o lines here.\n#\n# In the following lines, $(srcdir) refers to the toplevel directory\n# containing your extension.  If your sources are in a subdirectory,\n# you will have to modify the paths to reflect this:\n#\n# sample.$(OBJEXT): $(srcdir)/generic/sample.c\n# \t$(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@\n#\n# Setting the VPATH variable to a list of paths will cause the makefile\n# to look into these paths when resolving .c to .obj dependencies.\n# As necessary, add $(srcdir):$(srcdir)/compat:....\n#========================================================================\n\nVPATH = $(srcdir):Xmu\n\n.c.@OBJEXT@:\n\t$(COMPILE) -c `@CYGPATH@ $<` -o $@\n\n#========================================================================\n# Distribution creation\n# You may need to tweak this target to make it work correctly.\n#========================================================================\n\nCOMPRESS\t= tar zcvf $(PKG_DIR)-src.tar.gz $(PKG_DIR)\nDIST_ROOT\t= /tmp/togl-dist\nDIST_DIR\t= $(DIST_ROOT)/$(PKG_DIR)\nBINPKG_DIR\t= $(PKG_DIR)-@TCL_VERSION@-$(subst Darwin,MacOSX,$(subst CYGWIN,Windows,$(shell uname -s | sed -e 's/[-_].*//')))\nBINDIST_DIR\t= $(DIST_ROOT)/$(BINPKG_DIR)\n\ndist-clean:\n\trm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR)*\n\ndist: dist-clean\n\tmkdir -p $(DIST_DIR)\n\tcp -p $(srcdir)/README* $(srcdir)/LICENSE* $(srcdir)/togl.decls \\\n\t\t$(srcdir)/*.py $(srcdir)/*.tcl \\\n\t\t$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \\\n\t\tben.rgb tree2.rgba \\\n\t\t$(DIST_DIR)/\n\tchmod 664 $(DIST_DIR)/*\n\tchmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in\n\n\tfor i in $(srcdir)/*.[ch]; do \\\n\t    if [ -f $$i ]; then \\\n\t\tcp -p $$i $(DIST_DIR)/ ; \\\n\t    fi; \\\n\tdone\n\tcd $(DIST_DIR); rm -f $(CONFIG_CLEAN_FILES)\n\n\tmkdir $(DIST_DIR)/tclconfig\n\tcp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \\\n\t\t$(DIST_DIR)/tclconfig/\n\tchmod 664 $(DIST_DIR)/tclconfig/tcl.m4\n\tchmod +x $(DIST_DIR)/tclconfig/install-sh\n\n\tlist='examples doc tests Xmu GL'; \\\n\tfor p in $$list; do \\\n\t    if test -d $(srcdir)/$$p ; then \\\n\t\tmkdir $(DIST_DIR)/$$p; \\\n\t\tcp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \\\n\t    fi; \\\n\tdone\n\n\t(cd $(DIST_ROOT); $(COMPRESS);)\n\nbindist-clean:\n\trm -rf $(BINDIST_DIR) $(DIST_ROOT)/$(PKG_DIR)*\n\nbindist: all bindist-clean\n\tmkdir -p $(BINDIST_DIR)\n\t$(MAKE) prefix=$(BINDIST_DIR) exec_prefix=$(BINDIST_DIR) install\n\t$(INSTALL_DATA) README.bin $(BINDIST_DIR)/README.txt\n\tmkdir -p $(BINDIST_DIR)/doc\n\t@list='doc/*.html doc/*.js'; for i in $$list; do \\\n\t    echo \"Installing $$i\"; \\\n\t    rm -f $(BINDIST_DIR)/doc/`basename $$i`; \\\n\t    $(INSTALL_DATA) $$i $(BINDIST_DIR)/doc ; \\\n\tdone\n\tif [ @TOGL_WINDOWINGSYSTEM@ == TOGL_WGL ]; then \\\n\t\t(cd $(DIST_ROOT); zip -rDX9 $(BINPKG_DIR).zip $(BINPKG_DIR)); \\\n\telse \\\n\t\t(cd $(DIST_ROOT); tar zcvf $(BINPKG_DIR).tar.gz $(BINPKG_DIR)); \\\n\tfi\n\n#========================================================================\n# End of user-definable section\n#========================================================================\n\n#========================================================================\n# Don't modify the file to clean here.  Instead, set the \"CLEANFILES\"\n# variable in configure.in\n#========================================================================\n\nclean:  \n\t-test -z \"$(BINARIES)\" || rm -f $(BINARIES)\n\t-rm -f *.$(OBJEXT) core *.core\n\t-test -z \"$(CLEANFILES)\" || rm -f $(CLEANFILES)\n\ndistclean: clean\n\t-rm -f *.tab.c\n\t-rm -f $(CONFIG_CLEAN_FILES)\n\t-rm -f config.cache config.log config.status\n\n#========================================================================\n# Install binary object libraries.  On Windows this includes both .dll and\n# .lib files.  Because the .lib files are not explicitly listed anywhere,\n# we need to deduce their existence from the .dll file of the same name.\n# Library files go into the lib directory.\n# In addition, this will generate the pkgIndex.tcl\n# file in the install location (assuming it can find a usable tclsh shell)\n#\n# You should not have to modify this target.\n#========================================================================\n\ninstall-lib-binaries: binaries\n\t@mkdir -p $(DESTDIR)$(libdir)\n\t@list='$(lib_BINARIES)'; for p in $$list; do \\\n\t  if test -f $$p; then \\\n\t    echo \" $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libdir)/$$p\"; \\\n\t    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libdir)/$$p; \\\n\t    stub=`echo $$p|sed -e \"s/.*\\(stub\\).*/\\1/\"`; \\\n\t    if test \"x$$stub\" = \"xstub\"; then \\\n\t\techo \" $(RANLIB_STUB) $(DESTDIR)$(libdir)/$$p\"; \\\n\t\t$(RANLIB_STUB) $(DESTDIR)$(libdir)/$$p; \\\n\t    else \\\n\t\techo \" $(RANLIB) $(DESTDIR)$(libdir)/$$p\"; \\\n\t\t$(RANLIB) $(DESTDIR)$(libdir)/$$p; \\\n\t    fi; \\\n\t    ext=`echo $$p|sed -e \"s/.*\\.//\"`; \\\n\t    if test \"x$$ext\" = \"xdll\"; then \\\n\t\tlib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \\\n\t\tif test -f $$lib; then \\\n\t\t    echo \" $(INSTALL_DATA) $$lib $(DESTDIR)$(libdir)/$$lib\"; \\\n\t            $(INSTALL_DATA) $$lib $(DESTDIR)$(libdir)/$$lib; \\\n\t\tfi; \\\n\t    fi; \\\n\t  fi; \\\n\tdone\n\t@mkdir -p $(DESTDIR)$(pkglibdir)\n\t@list='$(pkglib_BINARIES)'; for p in $$list; do \\\n\t  if test -f $$p; then \\\n\t    echo \" $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p\"; \\\n\t    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \\\n\t    stub=`echo $$p|sed -e \"s/.*\\(stub\\).*/\\1/\"`; \\\n\t    if test \"x$$stub\" = \"xstub\"; then \\\n\t\techo \" $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p\"; \\\n\t\t$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \\\n\t    else \\\n\t\techo \" $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p\"; \\\n\t\t$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \\\n\t    fi; \\\n\t    ext=`echo $$p|sed -e \"s/.*\\.//\"`; \\\n\t    if test \"x$$ext\" = \"xdll\"; then \\\n\t\tlib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \\\n\t\tif test -f $$lib; then \\\n\t\t    echo \" $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib\"; \\\n\t            $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \\\n\t\tfi; \\\n\t    fi; \\\n\t  fi; \\\n\tdone\n\t@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \\\n\t  if test -f $(srcdir)/$$p; then \\\n\t    destp=`basename $$p`; \\\n\t    echo \" Install $$destp $(DESTDIR)$(pkglibdir)/$$destp\"; \\\n\t    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \\\n\t  fi; \\\n\tdone\n\t@if test \"x$(SHARED_BUILD)\" = \"x1\"; then \\\n\t    echo \" Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)\"; \\\n\t    $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \\\n\t    echo \" Install LICENSE $(DESTDIR)$(pkglibdir)\"; \\\n\t    $(INSTALL_DATA) LICENSE $(DESTDIR)$(pkglibdir); \\\n\telse \\\n\t    echo \" Install LICENSE.togl $(DESTDIR)$(libdir)\"; \\\n\t    $(INSTALL_DATA) LICENSE $(DESTDIR)$(libdir)/LICENSE.togl; \\\n\tfi\n\n#========================================================================\n# Install binary executables (e.g. .exe files and dependent .dll files)\n# This is for files that must go in the bin directory (located next to\n# wish and tclsh), like dependent .dll files on Windows.\n#\n# You should not have to modify this target, except to define bin_BINARIES\n# above if necessary.\n#========================================================================\n\ninstall-bin-binaries: binaries\n\t@mkdir -p $(DESTDIR)$(bindir)\n\t@list='$(bin_BINARIES)'; for p in $$list; do \\\n\t  if test -f $$p; then \\\n\t    echo \" $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p\"; \\\n\t    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \\\n\t  fi; \\\n\tdone\n\n.SUFFIXES: .c .$(OBJEXT)\n\nMakefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status\n\tcd $(top_builddir) \\\n\t  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status\n\nuninstall-binaries:\n\tlist='$(pkglib_BINARIES)'; for p in $$list; do \\\n\t  rm -f $(DESTDIR)$(pkglibdir)/$$p; \\\n\tdone\n\tlist='$(lib_BINARIES)'; for p in $$list; do \\\n\t  rm -f $(DESTDIR)$(libdir)/$$p; \\\n\tdone\n\tlist='$(PKG_TCL_SOURCES)'; for p in $$list; do \\\n\t  p=`basename $$p`; \\\n\t  rm -f $(DESTDIR)$(pkglibdir)/$$p; \\\n\tdone\n\tlist='$(bin_BINARIES)'; for p in $$list; do \\\n\t  rm -f $(DESTDIR)$(bindir)/$$p; \\\n\tdone\n\n.PHONY: all binaries clean depend distclean doc install libraries test\n\n# Tell versions [3.59,3.63) of GNU make to not export all variables.\n# Otherwise a system limit (for SysV at least) may be exceeded.\n.NOEXPORT:\n\n# Additional dependencies\ntogl.$(OBJEXT): toglFont.c toglAGL.c toglGLX.c toglWGL.c\n"
  },
  {
    "path": "ng/Togl2.1/README.stubs",
    "content": "This version of Togl is entirely free from\ndependencies on Tcl/Tk's internal functions. It uses the public stubs\ninterface, witch means that the same binary works with any stubs-aware\nwish (i.e. version >= 8.1)\n\nIt has been tested on Windows NT/2000 and Linux for several Tcl/Tk versions up\nto 8.4a3. I haven't been able to test the Mac port, it probably needs mending \nbut I can't see why it shouldn't work in principle.\n\nImplementation wise, what differs from Togl 1.5 is that Togl_MakeWindowExist()\nis replaced by Togl_CreateWindow(), a function that gets registered in Tk as a callback for window creation. In Tk/Tk 8.4a3, there is a new public API call \nTk_SetClassProcs() to register this callback, but for earlier versions of Tk \none needs to do this using some pointer magic.\nThere is a run-time check to determine which method to use, hence the \nsame binary runs on all versions of Wish from 8.1 and up. For this to \nwork you need to compile against the headers from Tcl/Tk 8.4a3 or later, or\nthe binary will only work for Tcl/Tk 8.1-8.4a2.\nThe tk8.4a3 public headers (tk8.4a3.h + tkDecls.h) are included for\nconvenience, and they are used if the flag -DUSE_LOCAL_TK_H is specified.\n\nJonas Beskow, December 2001"
  },
  {
    "path": "ng/Togl2.1/Togl.py",
    "content": "\n\"\"\"\nTkinter support for the Togl 2.X Tk OpenGL widget.\n\nCopyright (C) 2006-2007  Greg Couch\nSee the LICENSE file for copyright details.\n\"\"\"\n__all__ = ['Togl', 'NORMAL', 'OVERLAY']\n\nimport Tkinter\nimport weakref, atexit\n\n# Overlay constants\nNORMAL = 1\nOVERLAY = 2\n\nclass Togl(Tkinter.Widget):\n\t\"\"\"Tk OpenGL Widget\"\"\"\n\t_instances = weakref.WeakKeyDictionary()\n\n\tdef __init__(self, master=None, cnf={}, **kw):\n\t\t\"\"\"Return new Togl widget\"\"\"\n\t\tif master is None:\n\t\t\tmaster = Tkinter._default_root\n\t\tmaster.tk.call('package', 'require', 'Togl', '2.0')\n\t\ttry:\n\t\t\tTkinter.Widget.__init__(self, master, \"togl\", cnf, kw)\n\t\texcept:\n\t\t\tTkinter.Widget.destroy(self)\n\t\t\traise\n\t\tTogl._instances[self] = True\n\n\tdef _cbsubst(self, *args):\n\t\t\"\"\"callback command argument substitution\"\"\"\n\t\tif len(args) != 1:\n\t\t\treturn args\n\t\treturn (self._nametowidget(args[0]),)\n\n\tdef _options(self, cnf, kw = None):\n\t\t\"\"\"Internal function.\"\"\"\n\t\tif kw:\n\t\t\tcnf = Tkinter._cnfmerge((cnf, kw))\n\t\telse:\n\t\t\tcnf = Tkinter._cnfmerge(cnf)\n\t\tres = ()\n\t\tfor k, v in cnf.items():\n\t\t\tif v is not None:\n\t\t\t\tif k[-1] == '_': k = k[:-1]\n\t\t\t\tif callable(v):\n\t\t\t\t\tif k.endswith('command'):\n\t\t\t\t\t\tv = self._register(v, self._cbsubst)\n\t\t\t\t\telse:\n\t\t\t\t\t\tv = self._register(v)\n\t\t\t\tres = res + ('-'+k, v)\n\t\treturn res\n\n\t# cget, configure are inherited\n\n\tdef extensions(self):\n\t\t\"\"\"Return list of supported OpenGL extensions\"\"\"\n\t\treturn self.tk.call(self._w, 'extensions')\n\n\tdef postredisplay(self):\n\t\t\"\"\"Cause the displaycommand callback to be called\n\t\tthe next time the event loop is idle.\"\"\"\n\t\tself.tk.call(self._w, 'postredisplay')\n\n\tdef render(self):\n\t\t\"\"\"Call the displaycommand callback immediately.\"\"\"\n\t\tself.tk.call(self._w, 'render')\n\n\tdef swapbuffers(self):\n\t\t\"\"\"If single-buffred, just flush OpenGL command buffer.  If\n\t\tdouble-buffered, swap front and back buffers.  (So this is\n\t\tappropriate to call after every frame is drawn.)\"\"\"\n\t\tself.tk.call(self._w, 'swapbuffers')\n\n\tdef makecurrent(self):\n\t\t\"\"\"Make widget the current OpenGL context\"\"\"\n\t\tself.tk.call(self._w, 'makecurrent')\n\n\tdef takephoto(self, imageName):\n\t\t\"\"\"Copy current contents of widget into the given photo image\n\t\t\"\"\"\n\t\tself.tk.call(self._w, 'takephoto', imageName)\n\n\tdef loadbitmapfont(self, name):\n\t\treturn self.tk.call(self._w, 'loadbitmapfont', name)\n\n\tdef unloadbitmapfont(self, fontbase):\n\t\tself.tk.call(self._w, 'unloadbitmapfont', fontbase)\n\n\tdef uselayer(self, layer):\n\t\tself.tk.call(self._w, 'uselayer', layer)\n\n\tdef showoverlay(self):\n\t\tself.tk.call(self._w, 'showoverlay')\n\n\tdef hideoverlay(self):\n\t\tself.tk.call(self._w, 'hideoverlay')\n\n\tdef postredisplayoverlay(self):\n\t\tself.tk.call(self._w, 'postredisplayoverlay')\n\n\tdef renderoverlay(self):\n\t\tself.tk.call(self._w, 'renderoverlay')\n\n\tdef existsoverlay(self):\n\t\treturn self.tk.call(self._w, 'existsoverlay')\n\n\tdef ismappedoverlay(self):\n\t\treturn self.tk.call(self._w, 'ismappedoverlay')\n\n\tdef getoverlaytransparentvalue(self):\n\t\treturn self.tk.call(self._w, 'getoverlaytransparentvalue')\n\n\tdef destroy(self):\n\t\tdel Togl._instances[self]\n\t\tTkinter.Widget.destroy(self)\n\ndef _cleanup():\n\t# destroy OpenGL contexts early, so destroycommand's don't\n\t# try to make any OpenGL calls during exit.\n\tfor t in Togl._instances.keys():\n\t\ttry:\n\t\t\tt.destroy()\n\t\texcept Tkinter.TclError:\n\t\t\tpass\natexit.register(_cleanup)\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/CmapAlloc.c",
    "content": "/* $XConsortium: CmapAlloc.c,v 1.9 94/04/17 20:15:52 rws Exp $ */\n\n/* \n\nCopyright (c) 1989, 1994  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * Author:  Donna Converse, MIT X Consortium\n */\n\n#include <X11/Xlib.h>\n#include <X11/Xatom.h>\n#include <X11/Xutil.h>\n#include <stdio.h>\n\n#define lowbit(x) ((x) & (~(x) + 1))\n\nstatic int default_allocation();\nstatic void best_allocation();\nstatic void gray_allocation();\nstatic int icbrt();\nstatic int icbrt_with_bits();\nstatic int icbrt_with_guess();\n\n/* To determine the best allocation of reds, greens, and blues in a \n * standard colormap, use XmuGetColormapAllocation.\n * \tvinfo\t\tspecifies visual information for a chosen visual\n *\tproperty\tspecifies one of the standard colormap property names\n * \tred_max\t\treturns maximum red value \n *      green_max\treturns maximum green value\n * \tblue_max\treturns maximum blue value\n *\n * XmuGetColormapAllocation returns 0 on failure, non-zero on success.\n * It is assumed that the visual is appropriate for the colormap property.\n */\n\nStatus XmuGetColormapAllocation(vinfo, property, red_max, green_max, blue_max)\n    XVisualInfo\t\t*vinfo;\n    Atom\t\tproperty;\n    unsigned long\t*red_max, *green_max, *blue_max;\n{\n    Status \tstatus = 1;\n\n    if (vinfo->colormap_size <= 2)\n\treturn 0;\n\n    switch (property)\n    {\n      case XA_RGB_DEFAULT_MAP:\n\tstatus = default_allocation(vinfo, red_max, green_max, blue_max);\n\tbreak;\n      case XA_RGB_BEST_MAP:\n\tbest_allocation(vinfo, red_max, green_max, blue_max);\n\tbreak;\n      case XA_RGB_GRAY_MAP:\n\tgray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);\n\tbreak;\n      case XA_RGB_RED_MAP:\n\t*red_max = vinfo->colormap_size - 1;\n\t*green_max = *blue_max = 0;\n\tbreak;\n      case XA_RGB_GREEN_MAP:\n\t*green_max = vinfo->colormap_size - 1;\n\t*red_max = *blue_max = 0;\n\tbreak;\n      case XA_RGB_BLUE_MAP:\n\t*blue_max = vinfo->colormap_size - 1;\n\t*red_max = *green_max = 0;\n\tbreak;\n      default:\n\tstatus = 0;\n    }\n    return status;\n}\n\n/****************************************************************************/\n/* Determine the appropriate color allocations of a gray scale.\n *\n * Keith Packard, MIT X Consortium\n */\n\nstatic void gray_allocation(n, red_max, green_max, blue_max)\n    int\t\tn;\t/* the number of cells of the gray scale */\n    unsigned long *red_max, *green_max, *blue_max;\n{\n    *red_max = (n * 30) / 100;\n    *green_max = (n * 59) / 100; \n    *blue_max = (n * 11) / 100; \n    *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));\n}\n\n/****************************************************************************/\n/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.\n * If a map has less than a minimum number of definable entries, we do not\n * produce an allocation for an RGB_DEFAULT_MAP.  \n *\n * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,\n * 12 each.  For 8 planes, let n = the number of colormap entries, which may\n * be 256 or 254.  Then, maximum red value = floor(cube_root(n - 125)) - 1.\n * Maximum green and maximum blue values are identical to maximum red.\n * This leaves at least 125 cells which clients can allocate.\n *\n * Return 0 if an allocation has been determined, non-zero otherwise.\n */\n\nstatic int default_allocation(vinfo, red, green, blue)\n    XVisualInfo\t\t*vinfo;\n    unsigned long\t*red, *green, *blue;\n{\n    int\t\t\tngrays;\t\t/* number of gray cells */\n\n    switch (vinfo->class) {\n      case PseudoColor:\n\n\tif (vinfo->colormap_size > 65000)\n\t    /* intended for displays with 16 planes */\n\t    *red = *green = *blue = (unsigned long) 27;\n\telse if (vinfo->colormap_size > 4000)\n\t    /* intended for displays with 12 planes */\n\t    *red = *green = *blue = (unsigned long) 12;\n\telse if (vinfo->colormap_size < 250)\n\t    return 0;\n\telse\n\t    /* intended for displays with 8 planes */\n\t    *red = *green = *blue = (unsigned long)\n\t\t(icbrt(vinfo->colormap_size - 125) - 1);\n\tbreak;\n\n      case DirectColor:\n\n\tif (vinfo->colormap_size < 10)\n\t    return 0;\n\t*red = *green = *blue = vinfo->colormap_size / 2 - 1;\n\tbreak;\n\n      case TrueColor:\n\n\t*red = vinfo->red_mask / lowbit(vinfo->red_mask);\n\t*green = vinfo->green_mask / lowbit(vinfo->green_mask);\n\t*blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);\n\tbreak;\n\n      case GrayScale:\n\n\tif (vinfo->colormap_size > 65000)\n\t    ngrays = 4096;\n\telse if (vinfo->colormap_size > 4000)\n\t    ngrays = 512;\n\telse if (vinfo->colormap_size < 250)\n\t    return 0;\n\telse\n\t    ngrays = 12;\n\tgray_allocation(ngrays, red, green, blue);\n\tbreak;\n\t\n      default:\n\treturn 0;\n    }\n    return 1;\n}\n\n/****************************************************************************/\n/* Determine an appropriate color allocation for the RGB_BEST_MAP.\n *\n * For a DirectColor or TrueColor visual, the allocation is determined\n * by the red_mask, green_mask, and blue_mask members of the visual info.\n *\n * Otherwise, if the colormap size is an integral power of 2, determine\n * the allocation according to the number of bits given to each color,\n * with green getting more than red, and red more than blue, if there\n * are to be inequities in the distribution.  If the colormap size is\n * not an integral power of 2, let n = the number of colormap entries.\n * Then maximum red value = floor(cube_root(n)) - 1;\n * \tmaximum blue value = floor(cube_root(n)) - 1;\n *\tmaximum green value = n / ((# red values) * (# blue values)) - 1;\n * Which, on a GPX, allows for 252 entries in the best map, out of 254\n * defineable colormap entries.\n */\n \nstatic void best_allocation(vinfo, red, green, blue)\n    XVisualInfo\t\t*vinfo;\n    unsigned long\t*red, *green, *blue;\n{\n\n    if (vinfo->class == DirectColor ||\tvinfo->class == TrueColor)\n    {\n\t*red = vinfo->red_mask;\n\twhile ((*red & 01) == 0)\n\t    *red >>= 1;\n\t*green = vinfo->green_mask;\n\twhile ((*green & 01) == 0)\n\t    *green >>=1;\n\t*blue = vinfo->blue_mask;\n\twhile ((*blue & 01) == 0)\n\t    *blue >>= 1;\n    }\n    else\n    {\n\tregister int bits, n;\n\t\n\t/* Determine n such that n is the least integral power of 2 which is\n\t * greater than or equal to the number of entries in the colormap.\n         */\n\tn = 1;\n\tbits = 0;\n\twhile (vinfo->colormap_size > n)\n\t{\n\t    n = n << 1;\n\t    bits++;\n\t}\n\t\n\t/* If the number of entries in the colormap is a power of 2, determine\n\t * the allocation by \"dealing\" the bits, first to green, then red, then\n\t * blue.  If not, find the maximum integral red, green, and blue values\n\t * which, when multiplied together, do not exceed the number of \n\n\t * colormap entries.\n\t */\n\tif (n == vinfo->colormap_size)\n\t{\n\t    register int r, g, b;\n\t    b = bits / 3;\n\t    g = b + ((bits % 3) ? 1 : 0);\n\t    r = b + (((bits % 3) == 2) ? 1 : 0);\n\t    *red = 1 << r;\n\t    *green = 1 << g;\n\t    *blue = 1 << b;\n\t}\n\telse\n\t{\n\t    *red = icbrt_with_bits(vinfo->colormap_size, bits);\n\t    *blue = *red;\t\n\t    *green = (vinfo->colormap_size / ((*red) * (*blue)));\n\t}\n\t(*red)--;\n\t(*green)--;\n\t(*blue)--;\n    }\n    return;\n}\n\n/*\n * integer cube roots by Newton's method\n *\n * Stephen Gildea, MIT X Consortium, July 1991\n */\n\nstatic int icbrt(a)\t\t/* integer cube root */\n    int a;\n{\n    register int bits = 0;\n    register unsigned n = a;\n\n    while (n)\n    {\n\tbits++;\n\tn >>= 1;\n    }\n    return icbrt_with_bits(a, bits);\n}\n\n\nstatic int icbrt_with_bits(a, bits)\n    int a;\n    int bits;\t\t\t/* log 2 of a */\n{\n    return icbrt_with_guess(a, a>>2*bits/3);\n}\n\n#ifdef _X_ROOT_STATS\nint icbrt_loopcount;\n#endif\n\n/* Newton's Method:  x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */\n\n/* for cube roots, x^3 - a = 0,  x_new = x - 1/3 (x - a/x^2) */\n\n/*\n * Quick and dirty cube roots.  Nothing fancy here, just Newton's method.\n * Only works for positive integers (since that's all we need).\n * We actually return floor(cbrt(a)) because that's what we need here, too.\n */\n\nstatic int icbrt_with_guess(a, guess)\n    int a, guess;\n{\n    register int delta;\n\n#ifdef _X_ROOT_STATS\n    icbrt_loopcount = 0;\n#endif\n    if (a <= 0)\n\treturn 0;\n    if (guess < 1)\n\tguess = 1;\n\n    do {\n#ifdef _X_ROOT_STATS\n\ticbrt_loopcount++;\n#endif\n\tdelta = (guess - a/(guess*guess))/3;\n#ifdef DEBUG\n\tprintf(\"pass %d: guess=%d, delta=%d\\n\", icbrt_loopcount, guess, delta);\n#endif\n\tguess -= delta;\n    } while (delta != 0);\n\n    if (guess*guess*guess > a)\n\tguess--;\n\n    return guess;\n}\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/CrCmap.c",
    "content": "/* $XConsortium: CrCmap.c,v 1.6 94/04/17 20:15:53 rws Exp $ */\n\n/* \n\nCopyright (c) 1989  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * Author:  Donna Converse, MIT X Consortium\n */\n\n/*\n * CreateCmap.c - given a standard colormap description, make the map.\n */\n\n#include <stdio.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <stdlib.h>\n\nstatic int\tROmap();\t\t/* allocate entire map Read Only */\nstatic Status\tROorRWcell();\t\t/* allocate a cell, prefer Read Only */\nstatic Status\tRWcell();\t\t/* allocate a cell Read Write */\nstatic int\tcompare();\t\t/* for quicksort */\nstatic Status \tcontiguous();\t\t/* find contiguous sequence of cells */\nstatic void\tfree_cells();\t\t/* frees resources before quitting */\nstatic Status\treadonly_map();\t\t/* create a map in a RO visual type */\nstatic Status\treadwrite_map();\t/* create a map in a RW visual type */\n\n#define lowbit(x) ((x) & (~(x) + 1))\n#define TRUEMATCH(mult,max,mask) \\\n    (colormap->max * colormap->mult <= vinfo->mask && \\\n     lowbit(vinfo->mask) == colormap->mult)\n\n/*\n * To create any one colormap which is described by an XStandardColormap\n * structure, use XmuCreateColormap().\n *\n * Return 0 on failure, non-zero on success.\n * Resources created by this function are not made permanent.\n * No argument error checking is provided.  Use at your own risk.\n *\n * All colormaps are created with read only allocations, with the exception\n * of read only allocations of colors in the default map or otherwise\n * which fail to return the expected pixel value, and these are individually \n * defined as read/write allocations.  This is done so that all the cells\n * defined in the default map are contiguous, for use in image processing.\n * This typically happens with White and Black in the default map.\n *\n * Colormaps of static visuals are considered to be successfully created if\n * the map of the static visual matches the definition given in the\n * standard colormap structure.\n */\n   \nStatus XmuCreateColormap(dpy, colormap)\n    Display\t\t*dpy;\t\t/* specifies the connection under \n\t\t\t\t\t * which the map is created */\n    XStandardColormap\t*colormap;\t/* specifies the map to be created,\n\t\t\t\t\t * and returns, particularly if the\n\t\t\t\t\t * map is created as a subset of the\n\t\t\t\t\t * default colormap of the screen,\n\t\t\t\t\t * the base_pixel of the map.\n\t\t\t\t\t */\n{\n    XVisualInfo\t\tvinfo_template;\t/* template visual information */\n    XVisualInfo\t\t*vinfo;\t\t/* matching visual information */\n    XVisualInfo\t\t*vpointer;\t/* for freeing the entire list */\n    long\t\tvinfo_mask;\t/* specifies the visual mask value */\n    int \t\tn;\t\t/* number of matching visuals */\n    int\t\t\tstatus;\t\t\n\n    vinfo_template.visualid = colormap->visualid;\n    vinfo_mask = VisualIDMask;\n    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)\n\treturn 0;\n\n    /* A visual id may be valid on multiple screens.  Also, there may \n     * be multiple visuals with identical visual ids at different depths.  \n     * If the colormap is the Default Colormap, use the Default Visual.\n     * Otherwise, arbitrarily, use the deepest visual.\n     */\n    vpointer = vinfo;\n    if (n > 1)\n    {\n\tregister int\ti;\n\tregister int\tscreen_number;\n\tBool \t\tdef_cmap;\n\n\tdef_cmap = False;\n\tfor (screen_number = ScreenCount(dpy); --screen_number >= 0; )\n\t    if (colormap->colormap == DefaultColormap(dpy, screen_number)) {\n\t\tdef_cmap = True;\n\t\tbreak;\n\t    }\n\n\tif (def_cmap) {\n\t    for (i=0; i < n; i++, vinfo++) {\n\t\tif (vinfo->visual == DefaultVisual(dpy, screen_number))\n\t\t\tbreak;\n\t    }\n\t} else {\n\t    unsigned int\tmaxdepth = 0;\n\t    XVisualInfo\t\t*v;\n\n\t    for (i=0; i < n; i++, vinfo++)\n\t\tif (vinfo->depth > maxdepth) {\n\t\t    maxdepth = vinfo->depth;\n\t\t    v = vinfo;\n\t\t}\n\t    vinfo = v;\n\t}\n    }\n\n    if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||\n\tvinfo->class == GrayScale)\n\tstatus = readwrite_map(dpy, vinfo, colormap);\n    else if (vinfo->class == TrueColor)\n\tstatus = TRUEMATCH(red_mult, red_max, red_mask) &&\n\t         TRUEMATCH(green_mult, green_max, green_mask) &&\n\t\t TRUEMATCH(blue_mult, blue_max, blue_mask);\n    else \n\tstatus = readonly_map(dpy, vinfo, colormap);\n    \n    XFree((char *) vpointer);\n    return status;\n}\n\n/****************************************************************************/\nstatic Status readwrite_map(dpy, vinfo, colormap)\n    Display\t\t*dpy;\n    XVisualInfo\t\t*vinfo;\n    XStandardColormap\t*colormap;\n{\n    register unsigned long i, n;\t/* index counters */\n    int\t\t\tncolors;\t/* number of colors to be defined */\n    int\t\t\tnpixels;\t/* number of pixels allocated R/W */\n    int\t\t\tfirst_index;\t/* first index of pixels to use */\n    int\t\t\tremainder;\t/* first index of remainder */\n    XColor\t\tcolor;\t\t/* the definition of a color */\n    unsigned long\t*pixels;\t/* array of colormap pixels */\n    unsigned long\tdelta;\n\n    \n    /* Determine ncolors, the number of colors to be defined.\n     * Insure that 1 < ncolors <= the colormap size.\n     */\n    if (vinfo->class == DirectColor) {\n\tncolors = colormap->red_max;\n\tif (colormap->green_max > ncolors)\n\t    ncolors = colormap->green_max;\n\tif (colormap->blue_max > ncolors)\n\t    ncolors = colormap->blue_max;\n\tncolors++;\n\tdelta = lowbit(vinfo->red_mask) +\n\t        lowbit(vinfo->green_mask) +\n\t\tlowbit(vinfo->blue_mask);\n    } else {\n\tncolors = colormap->red_max * colormap->red_mult +\n\t\t  colormap->green_max * colormap->green_mult +\n\t\t  colormap->blue_max * colormap->blue_mult + 1;\n\tdelta = 1;\n    }\n    if (ncolors <= 1 || ncolors > vinfo->colormap_size)\treturn 0;\n\n    /* Allocate Read/Write as much of the colormap as we can possibly get.\n     * Then insure that the pixels we were allocated are given in \n     * monotonically increasing order, using a quicksort.  Next, insure\n     * that our allocation includes a subset of contiguous pixels at least\n     * as long as the number of colors to be defined.  Now we know that \n     * these conditions are met:\n     *\t1) There are no free cells in the colormap.\n     *  2) We have a contiguous sequence of pixels, monotonically \n     *     increasing, of length >= the number of colors requested.\n     *\n     * One cell at a time, we will free, compute the next color value, \n     * then allocate read only.  This takes a long time.\n     * This is done to insure that cells are allocated read only in the\n     * contiguous order which we prefer.  If the server has a choice of\n     * cells to grant to an allocation request, the server may give us any\n     * cell, so that is why we do these slow gymnastics.\n     */\n\n    if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,\n\t\t\t\t      sizeof(unsigned long))) == NULL)\n\treturn 0;\n\n    if ((npixels = ROmap(dpy, colormap->colormap, pixels,\n\t\t\t   vinfo->colormap_size, ncolors)) == 0) {\n\tfree((char *) pixels);\n\treturn 0;\n    }\n\n    qsort((char *) pixels, npixels, sizeof(unsigned long), compare);\n\n    if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))\n    {\n\t/* can't find enough contiguous cells, give up */\n\tXFreeColors(dpy, colormap->colormap, pixels, npixels,\n\t\t    (unsigned long) 0);\n\tfree((char *) pixels);\n\treturn 0;\n    }\n    colormap->base_pixel = pixels[first_index];\n\n    /* construct a gray map */\n    if (colormap->red_mult == 1 && colormap->green_mult == 1 &&\n\tcolormap->blue_mult == 1)\n\tfor (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)\n\t{\n\t    color.pixel = n;\n\t    color.blue = color.green = color.red =\n\t\t(unsigned short) ((i * 65535) / (colormap->red_max +\n\t\t\t\t\t\t colormap->green_max +\n\t\t\t\t\t\t colormap->blue_max));\n\n\t    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,\n\t\t\t     first_index + i))\n\t\treturn 0;\n\t}\n\n    /* construct a red ramp map */\n    else if (colormap->green_max == 0 && colormap->blue_max == 0)\n    \tfor (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)\n\t{\n\t    color.pixel = n;\n\t    color.red = (unsigned short) ((i * 65535) / colormap->red_max);\n\t    color.green = color.blue = 0;\n\n\t    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,\n\t\t\t     first_index + i))\n\t\treturn 0;\n\t}\n\n    /* construct a green ramp map */\n    else if (colormap->red_max == 0 && colormap->blue_max == 0)\n    \tfor (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)\n\t{\n\t    color.pixel = n;\n\t    color.green = (unsigned short) ((i * 65535) / colormap->green_max);\n\t    color.red = color.blue = 0;\n\n\t    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,\n\t\t\t     first_index + i))\n\t\treturn 0;\n\t}\n\n    /* construct a blue ramp map */\n    else if (colormap->red_max == 0 && colormap->green_max == 0)\n    \tfor (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)\n\t{\n\t    color.pixel = n;\n\t    color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);\n\t    color.red = color.green = 0;\n\n\t    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,\n\t\t\t     first_index + i))\n\t\treturn 0;\n\t}\n\n    /* construct a standard red green blue cube map */\n    else\n    {\n#define calc(max,mult) (((n / colormap->mult) % \\\n\t\t\t (colormap->max + 1)) * 65535) / colormap->max\n\n    \tfor (n=0, i=0; i < ncolors; i++, n += delta)\n\t{\n\t    color.pixel = n + colormap->base_pixel;\n\t    color.red = calc(red_max, red_mult);\n\t    color.green = calc(green_max, green_mult);\n\t    color.blue = calc(blue_max, blue_mult);\n\t    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,\n\t\t\t     first_index + i))\n\t\treturn 0;\n\t}\n#undef calc\n    }\n    /* We have a read-only map defined.  Now free unused cells,\n     * first those occurring before the contiguous sequence begins,\n     * then any following the contiguous sequence.\n     */\n\n    if (first_index)\n\tXFreeColors(dpy, colormap->colormap, pixels, first_index, \n\t\t    (unsigned long) 0);\n    if (remainder)\n\tXFreeColors(dpy, colormap->colormap,\n\t\t    &(pixels[first_index + ncolors]), remainder,\n\t\t    (unsigned long) 0);\n\n    free((char *) pixels);\n    return 1;\n}\n\n\n/****************************************************************************/\nstatic int ROmap(dpy, cmap, pixels, m, n)\n    Display\t\t*dpy;\t\t/* the X server connection */\n    Colormap\t\tcmap;\t\t/* specifies colormap ID */\n    unsigned long\tpixels[];\t/* returns pixel allocations */\n    int\t\t\tm;\t\t/* specifies colormap size */\n    int\t\t\tn;\t\t/* specifies number of colors */\n{\n    register int\tp;\n\n    /* first try to allocate the entire colormap */\n    if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, \n\t\t\t (unsigned) 0, pixels, (unsigned) m))\n\treturn m;\n\n    /* Allocate all available cells in the colormap, using a binary\n     * algorithm to discover how many cells we can allocate in the colormap.\n     */\n    m--;\n    while (n <= m) {\n\tp = n + ((m - n + 1) / 2);\n\tif (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,\n\t\t\t     (unsigned) 0, pixels, (unsigned) p)) {\n\t    if (p == m)\n\t\treturn p;\n\t    else {\n\t\tXFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);\n\t\tn = p;\n\t    }\n\t}\n\telse\n\t    m = p - 1;\n    }\n    return 0;\n}\n      \n\n/****************************************************************************/\nstatic Status contiguous(pixels, npixels, ncolors, delta, first, rem)\n    unsigned long\tpixels[];\t/* specifies allocated pixels */\n    int\t\t\tnpixels;\t/* specifies count of alloc'd pixels */\n    int\t\t\tncolors;\t/* specifies needed sequence length */\n    unsigned long\tdelta;\t\t/* between pixels */\n    int\t\t\t*first;\t\t/* returns first index of sequence */\n    int\t\t\t*rem;\t\t/* returns first index after sequence,\n\t\t\t\t\t * or 0, if none follow */\n{\n    register int i = 1;\t\t/* walking index into the pixel array */\n    register int count = 1;\t/* length of sequence discovered so far */\n\n    *first = 0;\n    if (npixels == ncolors) {\n\t*rem = 0;\n\treturn 1;\n    }\n    *rem = npixels - 1;\n    while (count < ncolors && ncolors - count <= *rem)\n    {\n\tif (pixels[i-1] + delta == pixels[i])\n\t    count++;\n\telse {\n\t    count = 1;\n\t    *first = i;\n\t}\n\ti++;\n\t(*rem)--;\n    }\n    if (count != ncolors)\n\treturn 0;\n    return 1;\n}\n\n\n/****************************************************************************/\nstatic Status ROorRWcell(dpy, cmap, pixels, npixels, color, p)\n    Display\t\t*dpy;\n    Colormap\t\tcmap;\n    unsigned long\tpixels[];\n    int\t\t\tnpixels;\n    XColor\t\t*color;\n    unsigned long\tp;\n{\n    unsigned long\tpixel;\n    XColor\t\trequest;\n\n    /* Free the read/write allocation of one cell in the colormap.\n     * Request a read only allocation of one cell in the colormap.\n     * If the read only allocation cannot be granted, give up, because\n     * there must be no free cells in the colormap.\n     * If the read only allocation is granted, but gives us a cell which\n     * is not the one that we just freed, it is probably the case that\n     * we are trying allocate White or Black or some other color which\n     * already has a read-only allocation in the map.  So we try to \n     * allocate the previously freed cell with a read/write allocation,\n     * because we want contiguous cells for image processing algorithms.\n     */\n     \n    pixel = color->pixel;\n    request.red = color->red;\n    request.green = color->green;\n    request.blue = color->blue;\n\n    XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);\n    if (! XAllocColor(dpy, cmap, color) \n\t|| (color->pixel != pixel &&\n\t    (!RWcell(dpy, cmap, color, &request, &pixel)))) \n    {\n\tfree_cells(dpy, cmap, pixels, npixels, (int)p);\n\treturn 0;\n    }\n    return 1;\n}\n\n\n/****************************************************************************/\nstatic void free_cells(dpy, cmap, pixels, npixels,  p)\n    Display\t\t*dpy;\n    Colormap\t\tcmap;\n    unsigned long\tpixels[];\t/* to be freed */\n    int\t\t\tnpixels;        /* original number allocated */\n    int\t\t\tp;\t  \n{\n    /* One of the npixels allocated has already been freed.\n     * p is the index of the freed pixel.\n     * First free the pixels preceding p, and there are p of them;\n     * then free the pixels following p, there are npixels - p - 1 of them.\n     */\n    XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);\n    XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);\n    free((char *) pixels);\n}\n\n\n/****************************************************************************/\nstatic Status RWcell(dpy, cmap, color, request, pixel)\n    Display\t\t*dpy;\n    Colormap\t\tcmap;\n    XColor\t\t*color;\n    XColor\t\t*request;\n    unsigned long\t*pixel;\n{\n    unsigned long\tn = *pixel;\n\n    XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);\n    if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,\n\t\t\t   (unsigned) 0, pixel, (unsigned) 1))\n\treturn 0;\n    if (*pixel != n)\n    {\n\tXFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);\n\treturn 0;\n    }\n    color->pixel = *pixel;\n    color->flags = DoRed | DoGreen | DoBlue;\n    color->red = request->red;\n    color->green = request->green;\n    color->blue = request->blue;\n    XStoreColors(dpy, cmap, color, 1);\n    return 1;\n}\n\n\n/****************************************************************************/\nstatic int compare(e1, e2)\n    unsigned long\t*e1, *e2;\n{\n    if (*e1 < *e2)\treturn -1;\n    if (*e1 > *e2)\treturn 1;\n    return 0;\n}\n\n\n/****************************************************************************/\nstatic Status readonly_map(dpy, vinfo, colormap)\n    Display\t\t*dpy;\n    XVisualInfo\t\t*vinfo;\n    XStandardColormap\t*colormap;\n{\n    int\t\t\ti, last_pixel;\n    XColor\t\tcolor;\n\n    last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * \n\t(colormap->blue_max + 1) + colormap->base_pixel - 1;\n\n    for(i=colormap->base_pixel; i <= last_pixel; i++) {\n\n\tcolor.pixel = (unsigned long) i;\n\tcolor.red = (unsigned short)\n\t    (((i/colormap->red_mult) * 65535) / colormap->red_max);\n\n\tif (vinfo->class == StaticColor) {\n\t    color.green = (unsigned short)\n\t\t((((i/colormap->green_mult) % (colormap->green_max + 1)) *\n\t\t  65535) / colormap->green_max);\n\t    color.blue = (unsigned short)\n\t\t(((i%colormap->green_mult) * 65535) / colormap->blue_max);\n\t}\n\telse\t/* vinfo->class == GrayScale, old style allocation XXX */\n\t    color.green = color.blue = color.red;\n\n\tXAllocColor(dpy, colormap->colormap, &color);\n\tif (color.pixel != (unsigned long) i)\n\t    return 0;\n    }\n    return 1;\n}\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/DelCmap.c",
    "content": "/* $XConsortium: DelCmap.c,v 1.2 94/04/17 20:15:58 converse Exp $ */\n\n/* \n \nCopyright (c) 1989  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * Author:  Donna Converse, MIT X Consortium\n */\n\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n\n/* To remove any standard colormap property, use XmuDeleteStandardColormap().\n * XmuDeleteStandardColormap() will remove the specified property from the\n * specified screen, releasing any resources used by the colormap(s) of the\n * property if possible.\n */\n\nvoid XmuDeleteStandardColormap(dpy, screen, property)\n    Display\t*dpy;\t\t/* specifies the X server to connect to */\n    int\t\tscreen;\t\t/* specifies the screen of the display */\n    Atom\tproperty;\t/* specifies the standard colormap property */\n{\n    XStandardColormap\t*stdcmaps, *s;\n    int\t\t\tcount = 0;\n\n    if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,\n\t\t\t property))\n    {\n\tfor (s=stdcmaps; count > 0; count--, s++) {\n\t    if ((s->killid == ReleaseByFreeingColormap) &&\n\t\t(s->colormap != None) &&\n\t\t(s->colormap != DefaultColormap(dpy, screen)))\n\t\tXFreeColormap(dpy, s->colormap);\n\t    else if (s->killid != None)\n\t\tXKillClient(dpy, s->killid);\n\t}\n\tXDeleteProperty(dpy, RootWindow(dpy, screen), property);\n\tXFree((char *) stdcmaps);\n\tXSync(dpy, False);\n    }\n}\n\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/LookupCmap.c",
    "content": "/* $XConsortium: LookupCmap.c,v 1.10 94/04/17 20:16:11 rws Exp $ */\n\n/* \n \nCopyright (c) 1989  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * Author:  Donna Converse, MIT X Consortium\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <X11/Xlib.h>\n#include <X11/Xatom.h>\n#include <X11/Xutil.h>\n#include <X11/Xmu/StdCmap.h>\n\nstatic Status lookup();\n\n/*\n * To create a standard colormap if one does not currently exist, or\n * replace the currently existing standard colormap, use \n * XmuLookupStandardColormap().\n *\n * Given a screen, a visual, and a property, XmuLookupStandardColormap()\n * will determine the best allocation for the property under the specified\n * visual, and determine the whether to create a new colormap or to use\n * the default colormap of the screen.  It will call XmuStandardColormap()\n * to create the standard colormap.\n *\n * If replace is true, any previous definition of the property will be \n * replaced.  If retain is true, the property and the colormap will be\n * made permanent for the duration of the server session.  However,\n * pre-existing property definitions which are not replaced cannot be made\n * permanent by a call to XmuLookupStandardColormap(); a request to retain \n * resources pertains to newly created resources.\n *\n * Returns 0 on failure, non-zero on success.  A request to create a \n * standard colormap upon a visual which cannot support such a map is\n * considered a failure.  An example of this would be requesting any\n * standard colormap property on a monochrome visual, or, requesting an\n * RGB_BEST_MAP on a display whose colormap size is 16.\n */\n\nStatus XmuLookupStandardColormap(dpy, screen, visualid, depth, property,\n\t\t\t\t replace, retain)\n    Display\t\t*dpy;\t\t/* specifies X server connection */\n    int\t\t\tscreen; \t/* specifies screen of display */\n    VisualID\t\tvisualid;\t/* specifies the visual type */\n    unsigned int\tdepth;\t\t/* specifies  the visual type */\n    Atom\t\tproperty;\t/* a standard colormap property */\n    Bool\t\treplace;\t/* specifies whether to replace */\n    Bool\t\tretain;\t\t/* specifies whether to retain */\n{\n    Display\t\t*odpy;\t\t/* original display connection */\n    XStandardColormap\t*colormap;\t\n    XVisualInfo\t\tvinfo_template, *vinfo;\t/* visual */\n    long\t\tvinfo_mask;\n    unsigned long\tr_max, g_max, b_max;\t/* allocation */\n    int\t\t\tcount;\t\n    Colormap\t\tcmap;\t\t\t/* colormap ID */\n    Status\t\tstatus = 0;\n\n\n    /* Match the requested visual */\n\n    vinfo_template.visualid = visualid;\t\n    vinfo_template.screen = screen;\n    vinfo_template.depth = depth;\n    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;\n    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==\n\tNULL)\n\treturn 0;\n\n    /* Monochrome visuals have no standard maps */\n\n    if (vinfo->colormap_size <= 2) {\n\tXFree((char *) vinfo);\n\treturn 0;\t\n    }\n\n    /* If the requested property already exists on this screen, and, \n     * if the replace flag has not been set to true, return success.\n     * lookup() will remove a pre-existing map if replace is true.\n     */\n\n    if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,\n\t       replace) && !replace) {\n\tXFree((char *) vinfo);\n\treturn 1;\n    }\n\n    /* Determine the best allocation for this property under the requested\n     * visualid and depth, and determine whether or not to use the default\n     * colormap of the screen.\n     */\n\n    if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {\n\tXFree((char *) vinfo);\n\treturn 0;\n    }\n\n    cmap = (property == XA_RGB_DEFAULT_MAP &&\n\t    visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))\n\t? DefaultColormap(dpy, screen) : None;\n\n    /* If retaining resources, open a new connection to the same server */\n\n    if (retain) {\n\todpy = dpy;\n\tif ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {\n\t    XFree((char *) vinfo);\n\t    return 0;\n\t}\n    }\n\n    /* Create the standard colormap */\n\n    colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,\n\t\t\t\t   cmap, r_max, g_max, b_max);\n\n    /* Set the standard colormap property */\n\n    if (colormap) {\n\tXGrabServer(dpy);\n\n\tif (lookup(dpy, screen, visualid, property, colormap, replace) &&\n\t    !replace) {\n\t    /* Someone has defined the property since we last looked.\n\t     * Since we will not replace it, release our own resources.\n\t     * If this is the default map, our allocations will be freed \n\t     * when this connection closes.\n\t     */\n\t    if (colormap->killid == ReleaseByFreeingColormap)\n\t\tXFreeColormap(dpy, colormap->colormap);\n\t}\n\telse if (retain) {\n\t\tXSetCloseDownMode(dpy, RetainPermanent);\n\t}\n\tXUngrabServer(dpy);\n\tXFree((char *) colormap);\n\tstatus = 1;\n    }\n\n    if (retain)\n\tXCloseDisplay(dpy);\n    XFree((char *) vinfo);\n    return status;\n}\n\n/***************************************************************************/\n\n/* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,\n * the visualid is used to determine whether the indicated standard colormap\n * exists.  If the map exists and replace is true, delete the resources used\n * by the map and remove the property.  Return true if the map exists,\n * or did exist and was deleted; return false if the map was not found.\n *\n * Note that this is not the way that a Status return is normally used.\n *\n * If new is not NULL, new points to an XStandardColormap structure which\n * describes a standard colormap of the specified property.  It will be made\n * a standard colormap of the screen if none already exists, or if replace \n * is true.\n */\n\nstatic Status lookup(dpy, screen, visualid, property, new, replace)\n    Display\t\t*dpy;\t\t/* specifies display connection */\n    int\t\t\tscreen;\t\t/* specifies screen number */\n    VisualID\t\tvisualid;\t/* specifies visualid for std map */\n    Atom\t\tproperty;\t/* specifies colormap property name */\n    XStandardColormap\t*new;\t\t/* specifies a standard colormap */\n    Bool\t\treplace;\t/* specifies whether to replace */\n{\n    register int\ti;\n    int\t\t\tcount;\n    XStandardColormap\t*stdcmaps, *s;\n    Window\t\twin = RootWindow(dpy, screen);\n\n    /* The property does not already exist */\n\n    if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {\n\tif (new)\n\t    XSetRGBColormaps(dpy, win, new, 1, property);\n\treturn 0;\n    }\n\n    /* The property exists and is not describing the RGB_DEFAULT_MAP */\n\n    if (property != XA_RGB_DEFAULT_MAP) {\n\tif (replace) {\n\t    XmuDeleteStandardColormap(dpy, screen, property);\n\t    if (new)\n\t\tXSetRGBColormaps(dpy, win, new, 1, property);\n\t}\n\tXFree((char *)stdcmaps);\n\treturn 1;\n    }\n\n    /* The property exists and is RGB_DEFAULT_MAP */\n    \n    for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)\n\t;\n\n    /* No RGB_DEFAULT_MAP property matches the given visualid */\n\n    if (i == count) {\n\tif (new) {\n\t    XStandardColormap\t*m, *maps;\n\n\t    s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof\n\t\t\t\t\t      (XStandardColormap)));\n\n\t    for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {\n\t\tm->colormap   = maps->colormap;\n\t\tm->red_max    = maps->red_max;\n\t\tm->red_mult   = maps->red_mult;\n\t\tm->green_max  = maps->green_max;\n\t\tm->green_mult = maps->green_mult;\n\t\tm->blue_max   = maps->blue_max;\n\t\tm->blue_mult  = maps->blue_mult;\n\t\tm->base_pixel = maps->base_pixel;\n\t\tm->visualid   = maps->visualid;\n\t\tm->killid     = maps->killid;\n\t    }\n\t    m->colormap   = new->colormap;\n\t    m->red_max    = new->red_max;\n\t    m->red_mult   = new->red_mult;\n\t    m->green_max  = new->green_max;\n\t    m->green_mult = new->green_mult;\n\t    m->blue_max   = new->blue_max;\n\t    m->blue_mult  = new->blue_mult;\n\t    m->base_pixel = new->base_pixel;\n\t    m->visualid   = new->visualid;\n\t    m->killid     = new->killid;\n\n\t    XSetRGBColormaps(dpy, win, s, ++count, property);\n\t    free((char *) s);\n\t}\n\tXFree((char *) stdcmaps);\n\treturn 0;\n    }\n\n    /* Found an RGB_DEFAULT_MAP property with a matching visualid */\n\n    if (replace) {\n\t/* Free old resources first - we may need them, particularly in \n\t * the default colormap of the screen.  However, because of this,\n\t * it is possible that we will destroy the old resource and fail \n\t * to create a new one if XmuStandardColormap() fails.\n\t */\n\n\tif (count == 1) {\n\t    XmuDeleteStandardColormap(dpy, screen, property);\n\t    if (new)\n\t\tXSetRGBColormaps(dpy, win, new, 1, property);\n\t}\n\telse {\n\t    XStandardColormap\t*map;\n\n\t    /* s still points to the matching standard colormap */\n\n\t    if (s->killid == ReleaseByFreeingColormap) {\n\t\tif ((s->colormap != None) &&\n\t\t    (s->colormap != DefaultColormap(dpy, screen)))\n\t\t    XFreeColormap(dpy, s->colormap);\n\t    }\n\t    else if (s->killid != None)\n\t\tXKillClient(dpy, s->killid);\n\n\t    map = (new) ? new : stdcmaps + --count;\n\n\t    s->colormap   = map->colormap;\n\t    s->red_max    = map->red_max;\n\t    s->red_mult   = map->red_mult;\n\t    s->green_max  = map->green_max;\n\t    s->green_mult = map->green_mult;\n\t    s->blue_max   = map->blue_max;\n\t    s->blue_mult  = map->blue_mult;\n\t    s->visualid   = map->visualid;\n\t    s->killid     = map->killid;\n\n\t    XSetRGBColormaps(dpy, win, stdcmaps, count, property);\n\t}\n    }\n    XFree((char *) stdcmaps);\n    return 1;\n}\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/README.togl",
    "content": "The source code in this directory is a subset of the Jun 12, 1995 X11R6 Xmu\nlibrary that is needed for the Togl widget.  The Xmu library is no longer\ninstalled by default on many Linux systems.\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/StdCmap.c",
    "content": "/* $XConsortium: StdCmap.c,v 1.14 94/04/17 20:16:14 rws Exp $ */\n\n/* \n\nCopyright (c) 1989  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * Author:  Donna Converse, MIT X Consortium\n */\n\n#include <stdio.h>\n#include <X11/Xlib.h>\n#include <X11/Xatom.h>\n#include <X11/Xutil.h>\n#include <X11/Xmu/StdCmap.h>\n\n#define lowbit(x) ((x) & (~(x) + 1))\n\nstatic Status valid_args();\t\t/* argument restrictions */\n\n/*\n * To create any one standard colormap, use XmuStandardColormap().\n *\n * Create a standard colormap for the given screen, visualid, and visual\n * depth, with the given red, green, and blue maximum values, with the\n * given standard property name.  Return a pointer to an XStandardColormap\n * structure which describes the newly created colormap, upon success.\n * Upon failure, return NULL.\n * \n * XmuStandardColormap() calls XmuCreateColormap() to create the map.\n *\n * Resources created by this function are not made permanent; that is the\n * caller's responsibility.\n */\n\nXStandardColormap *XmuStandardColormap(dpy, screen, visualid, depth, property,\n\t\t\t\t       cmap, red_max, green_max, blue_max)\n    Display\t\t*dpy;\t\t/* specifies X server connection */\n    int\t\t\tscreen; \t/* specifies display screen */\n    VisualID\t\tvisualid;\t/* identifies the visual type */\n    unsigned int\tdepth;\t\t/* identifies the visual type */\n    Atom\t\tproperty;\t/* a standard colormap property */\n    Colormap\t\tcmap;\t\t/* specifies colormap ID or None */\n    unsigned long\tred_max, green_max, blue_max;\t/* allocations */\n{\n    XStandardColormap\t*stdcmap;\n    Status\t\tstatus;\n    XVisualInfo\t\tvinfo_template, *vinfo;\n    long\t\tvinfo_mask;\n    int\t\t\tn;\n\n    /* Match the required visual information to an actual visual */\n    vinfo_template.visualid = visualid;\t\n    vinfo_template.screen = screen;\n    vinfo_template.depth = depth;\n    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;\n    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)\n\treturn 0;\n\n    /* Check the validity of the combination of visual characteristics,\n     * allocation, and colormap property.  Create an XStandardColormap\n     * structure.\n     */\n\n    if (! valid_args(vinfo, red_max, green_max, blue_max, property)\n\t|| ((stdcmap = XAllocStandardColormap()) == NULL)) {\n\tXFree((char *) vinfo);\n\treturn 0;\n    }\n\n    /* Fill in the XStandardColormap structure */\n\n    if (cmap == DefaultColormap(dpy, screen)) {\n\t/* Allocating out of the default map, cannot use XFreeColormap() */\n\tWindow win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,\n\t\t\t\t   0, 0, InputOnly, vinfo->visual,\n\t\t\t\t   (unsigned long) 0,\n\t\t\t\t   (XSetWindowAttributes *)NULL);\n\tstdcmap->killid  = (XID) XCreatePixmap(dpy, win, 1, 1, depth);\n\tXDestroyWindow(dpy, win);\n\tstdcmap->colormap = cmap;\n    } else {\n\tstdcmap->killid = ReleaseByFreeingColormap;\n\tstdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),\n\t\t\t\t\t    vinfo->visual, AllocNone);\n    }\n    stdcmap->red_max = red_max;\n    stdcmap->green_max = green_max;\n    stdcmap->blue_max = blue_max;\n    if (property == XA_RGB_GRAY_MAP) \n\tstdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;\n    else if (vinfo->class == TrueColor || vinfo->class == DirectColor) {\n\tstdcmap->red_mult = lowbit(vinfo->red_mask);\n\tstdcmap->green_mult = lowbit(vinfo->green_mask);\n\tstdcmap->blue_mult = lowbit(vinfo->blue_mask);\n    } else {\n\tstdcmap->red_mult = (red_max > 0)\n\t    ? (green_max + 1) * (blue_max + 1) : 0;\n\tstdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;\n\tstdcmap->blue_mult = (blue_max > 0) ? 1 : 0;\n    }\n    stdcmap->base_pixel = 0;\t\t\t/* base pixel may change */\n    stdcmap->visualid = vinfo->visualid;\n\n    /* Make the colormap */\n\n    status = XmuCreateColormap(dpy, stdcmap);\n\n    /* Clean up */\n\n    XFree((char *) vinfo);\n    if (!status) {\n\n\t/* Free the colormap or the pixmap, if we created one */\n\tif (stdcmap->killid == ReleaseByFreeingColormap)\n\t    XFreeColormap(dpy, stdcmap->colormap);\n\telse if (stdcmap->killid != None)\n\t    XFreePixmap(dpy, stdcmap->killid);\n\t\n\tXFree((char *) stdcmap);\n\treturn (XStandardColormap *) NULL;\n    }\n    return stdcmap;\n}\n\n/****************************************************************************/\nstatic Status valid_args(vinfo, red_max, green_max, blue_max, property)\n    XVisualInfo\t\t*vinfo;\t\t/* specifies visual */\n    unsigned long\tred_max, green_max, blue_max;\t/* specifies alloc */\n    Atom\t\tproperty;\t/* specifies property name */\n{\n    unsigned long\tncolors;\t/* number of colors requested */\n\n    /* Determine that the number of colors requested is <= map size */\n\n    if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) {\n\tunsigned long mask;\n\n\tmask = vinfo->red_mask;\n\twhile (!(mask & 1))\n\t    mask >>= 1;\n\tif (red_max > mask)\n\t    return 0;\n\tmask = vinfo->green_mask;\n\twhile (!(mask & 1))\n\t    mask >>= 1;\n\tif (green_max > mask)\n\t    return 0;\n\tmask = vinfo->blue_mask;\n\twhile (!(mask & 1))\n\t    mask >>= 1;\n\tif (blue_max > mask)\n\t    return 0;\n    } else if (property == XA_RGB_GRAY_MAP) {\n\tncolors = red_max + green_max + blue_max + 1;\n\tif (ncolors > vinfo->colormap_size)\n\t    return 0;\n    } else {\n\tncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);\n\tif (ncolors > vinfo->colormap_size)\n\t    return 0;\n    }\n    \n    /* Determine that the allocation and visual make sense for the property */\n\n    switch (property)\n    {\n      case XA_RGB_DEFAULT_MAP:\n\tif (red_max == 0 || green_max == 0 || blue_max == 0)\n\t    return 0;\n\tbreak;\n      case XA_RGB_RED_MAP:\n\tif (red_max == 0)\n\t    return 0;\n\tbreak;\n      case XA_RGB_GREEN_MAP:\n\tif (green_max == 0)\n\t    return 0;\n\tbreak;\n      case XA_RGB_BLUE_MAP:\t\n\tif (blue_max == 0)\n\t    return 0;\n\tbreak;\n      case XA_RGB_BEST_MAP:\n\tif (red_max == 0 || green_max == 0 || blue_max == 0)\n\t    return 0;\n\tbreak;\n      case XA_RGB_GRAY_MAP:\n\tif (red_max == 0 || blue_max == 0 || green_max == 0)\n\t    return 0;\n\tbreak;\n      default:\n\treturn 0;\n    }\n    return 1;\n}\n"
  },
  {
    "path": "ng/Togl2.1/Xmu/StdCmap.h",
    "content": "/* $XConsortium: StdCmap.h,v 1.4 94/04/17 20:16:15 converse Exp $ */\n\n/*\n \nCopyright (c) 1988  X Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from the X Consortium.\n\n*/\n\n/*\n * The interfaces described by this header file are for miscellaneous utilities\n * and are not part of the Xlib standard.\n */\n\n#ifndef _XMU_STDCMAP_H_\n#define _XMU_STDCMAP_H_\n\n#include <X11/Xfuncproto.h>\n\n_XFUNCPROTOBEGIN\n\nStatus XmuAllStandardColormaps(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */\n#endif\n);\n\nStatus XmuCreateColormap(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */,\n    XStandardColormap*\t/* colormap */\n#endif\n);\n\nvoid   XmuDeleteStandardColormap(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */,\n    int\t\t\t/* screen */,\n    Atom\t\t/* property */\n#endif\n);\n\nStatus XmuGetColormapAllocation(\n#if NeedFunctionPrototypes\n    XVisualInfo*\t/* vinfo */,\n    Atom\t\t/* property */,\n    unsigned long*\t/* red_max_return */,\n    unsigned long*\t/* green_max_return */,\n    unsigned long*\t/* blue_max_return */\n#endif\n);\n\nStatus XmuLookupStandardColormap(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */,\n    int\t\t\t/* screen */,\n    VisualID\t\t/* visualid */,\n    unsigned int\t/* depth */,\n    Atom\t\t/* property */,\n    Bool\t\t/* replace */,\n    Bool\t\t/* retain */\n#endif\n);\n\nXStandardColormap *XmuStandardColormap(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */,\n    int\t\t\t/* screen */,\n    VisualID\t\t/* visualid */,\n    unsigned int\t/* depth */,\n    Atom\t\t/* property */,\n    Colormap\t\t/* cmap */,\n    unsigned long\t/* red_max */,\n    unsigned long\t/* green_max */,\n    unsigned long\t/* blue_max */\n#endif\n);\n\nStatus XmuVisualStandardColormaps(\n#if NeedFunctionPrototypes\n    Display*\t\t/* dpy */,\n    int\t\t\t/* screen */,\n    VisualID\t\t/* visualid */,\n    unsigned int\t/* depth */,\n    Bool\t\t/* replace */,\n    Bool\t\t/* retain */\n#endif\n);\n\n_XFUNCPROTOEND\n\n#endif /* _XMU_STDCMAP_H_ */\n"
  },
  {
    "path": "ng/Togl2.1/aclocal.m4",
    "content": "#\n# Include the TEA standard macro set\n#\n\nbuiltin(include,tclconfig/tcl.m4)\n\n#\n# Add here whatever m4 macros you want to define for your package\n#\n\n#------------------------------------------------------------------------\n# TOGL_ENABLE_STUBS --\n#\n#\tSpecify if stubs should be used.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-stubs\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN(TOGL_ENABLE_STUBS, [\n    AC_MSG_CHECKING([whether to link with stubs library])\n    AC_ARG_ENABLE(stubs,\n\t[  --enable-stubs          build and link with stub libraries (--enable-stubs)],\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n\n    if test \"${enable_stubs+set}\" = set; then\n\tenableval=\"$enable_stubs\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\tAC_MSG_RESULT([stubs])\n\tUSE_STUBS=1\n    else\n\tAC_MSG_RESULT([no stubs])\n\tUSE_STUBS=0\n    fi\n])\n\n#------------------------------------------------------------------------\n# TOGL_UNDEF_GET_PROC_ADDRESS --\n#\n#\tDoes defining GLX_GLXEXT_LEGACY interfere with including GL/glxext.h?\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tdefines TOGL_UNDEF_GET_PROC_ADDRESS\n#\n#------------------------------------------------------------------------\nAC_DEFUN(TOGL_UNDEF_GET_PROC_ADDRESS, [\n    AC_MSG_CHECKING([if GLX_GLXEXT_LEGACY interferes with including GL/glxext.h])\n    AC_LANG_PUSH(C)\n    ac_save_CFLAGS=$CFLAGS\n    CFLAGS=$TK_XINCLUDES\n    AC_COMPILE_IFELSE(\n\t[AC_LANG_SOURCE([[\n#define GLX_GLXEXT_LEGACY\n#include <GL/glx.h>\n#undef GLX_VERSION_1_3\n#undef GLX_VERSION_1_4\n#include <GL/glxext.h>\nint main() { return 0; }\n]])],\n\t[AC_MSG_RESULT([no])],\n\t[AC_MSG_RESULT([yes])\n\t AC_DEFINE(UNDEF_GET_PROC_ADDRESS, 1)])\n    CFLAGS=$ac_save_CFLAGS\n    AC_LANG_POP()\n])\n"
  },
  {
    "path": "ng/Togl2.1/configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.65 for Togl 2.1.\n#\n#\n# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,\n# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,\n# Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test -n \\\"\\${ZSH_VERSION+set}\\\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse\n  case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" ); then :\n\nelse\n  exitcode=1; echo positional parameters were not saved.\nfi\ntest x\\$exitcode = x0 || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null; then :\n  as_have_required=yes\nelse\n  as_have_required=no\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null; then :\n\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir/$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if { $as_echo \"$as_bourne_compatible\"\"$as_suggested\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\n$as_found || { if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$SHELL\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi; }\nIFS=$as_save_IFS\n\n\n      if test \"x$CONFIG_SHELL\" != x; then :\n  # We cannot yet assume a decent shell, so we have to provide a\n\t# neutralization value for shells without unset; and this also\n\t# works around shells that cannot unset nonexistent variables.\n\tBASH_ENV=/dev/null\n\tENV=/dev/null\n\t(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\n\texport CONFIG_SHELL\n\texec \"$CONFIG_SHELL\" \"$as_myself\" ${1+\"$@\"}\nfi\n\n    if test x$as_have_required = xno; then :\n  $as_echo \"$0: This script requires a shell more modern than all\"\n  $as_echo \"$0: the shells that I found on your system.\"\n  if test x${ZSH_VERSION+set} = xset ; then\n    $as_echo \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    $as_echo \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    $as_echo \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\n# as_fn_error ERROR [LINENO LOG_FD]\n# ---------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with status $?, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$?; test $as_status -eq 0 && as_status=1\n  if test \"$3\"; then\n    as_lineno=${as_lineno-\"$2\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $1\" >&$3\n  fi\n  $as_echo \"$as_me: error: $1\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { $as_echo \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -p'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -p'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -p'\n  fi\nelse\n  as_ln_s='cp -p'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nif test -x / >/dev/null 2>&1; then\n  as_test_x='test -x'\nelse\n  if ls -dL / >/dev/null 2>&1; then\n    as_ls_L_option=L\n  else\n    as_ls_L_option=\n  fi\n  as_test_x='\n    eval sh -c '\\''\n      if test -d \"$1\"; then\n\ttest -d \"$1/.\";\n      else\n\tcase $1 in #(\n\t-*)set \"./$1\";;\n\tesac;\n\tcase `ls -ld'$as_ls_L_option' \"$1\" 2>/dev/null` in #((\n\t???[sx]*):;;*)false;;esac;fi\n    '\\'' sh\n  '\nfi\nas_executable_p=$as_test_x\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME='Togl'\nPACKAGE_TARNAME='togl'\nPACKAGE_VERSION='2.1'\nPACKAGE_STRING='Togl 2.1'\nPACKAGE_BUGREPORT=''\nPACKAGE_URL=''\n\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stdio.h>\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef STDC_HEADERS\n# include <stdlib.h>\n# include <stddef.h>\n#else\n# ifdef HAVE_STDLIB_H\n#  include <stdlib.h>\n# endif\n#endif\n#ifdef HAVE_STRING_H\n# if !defined STDC_HEADERS && defined HAVE_MEMORY_H\n#  include <memory.h>\n# endif\n# include <string.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_subst_vars='LTLIBOBJS\nTCLSH_PROG\nRANLIB_STUB\nMAKE_STUB_LIB\nMAKE_STATIC_LIB\nMAKE_SHARED_LIB\nMAKE_LIB\nTCL_DBGX\nLDFLAGS_DEFAULT\nCFLAGS_DEFAULT\nSHLIB_SUFFIX\nLD_LIBRARY_PATH_VAR\nSHLIB_CFLAGS\nSHLIB_LD_LIBS\nSHLIB_LD\nSTLIB_LD\nCFLAGS_WARNING\nCFLAGS_OPTIMIZE\nCFLAGS_DEBUG\nDL_LIBS\nLIBOBJS\nCELIB_DIR\nAR\nSHARED_BUILD\nTCL_THREADS\nTEA_WINDOWINGSYSTEM\nLIBGLU\nTOGL_WINDOWINGSYSTEM\nAUTOSTEREOD\nXMKMF\nTK_XLIB_DIR_NATIVE\nTK_TOP_DIR_NATIVE\nTK_INCLUDES\nTCL_TOP_DIR_NATIVE\nTCL_INCLUDES\nCLEANFILES\nPKG_OBJECTS\nPKG_SOURCES\nMATH_LIBS\nEGREP\nGREP\nRANLIB\nSET_MAKE\nINSTALL_DATA\nINSTALL_SCRIPT\nINSTALL_PROGRAM\nCPP\nOBJEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nTK_XINCLUDES\nTK_LIBS\nTK_STUB_LIB_SPEC\nTK_STUB_LIB_FLAG\nTK_STUB_LIB_FILE\nTK_LIB_SPEC\nTK_LIB_FLAG\nTK_LIB_FILE\nTK_SRC_DIR\nTK_BIN_DIR\nTK_VERSION\nTCL_SHLIB_LD_LIBS\nTCL_LD_FLAGS\nTCL_EXTRA_CFLAGS\nTCL_DEFS\nTCL_LIBS\nTCL_STUB_LIB_SPEC\nTCL_STUB_LIB_FLAG\nTCL_STUB_LIB_FILE\nTCL_LIB_SPEC\nTCL_LIB_FLAG\nTCL_LIB_FILE\nTCL_SRC_DIR\nTCL_BIN_DIR\nTCL_VERSION\nPKG_CFLAGS\nPKG_LIBS\nPKG_INCLUDES\nPKG_HEADERS\nPKG_TCL_SOURCES\nPKG_STUB_OBJECTS\nPKG_STUB_SOURCES\nPKG_STUB_LIB_FILE\nPKG_LIB_FILE\nEXEEXT\nCYGPATH\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nECHO_T\nECHO_N\nECHO_C\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nwith_tcl\nwith_tk\nenable_stubs\nwith_tclinclude\nwith_tkinclude\nwith_x\nwith_autostereo\nwith_autostereod\nwith_Xmu\nenable_threads\nenable_shared\nenable_64bit\nenable_64bit_vis\nenable_rpath\nenable_wince\nwith_celib\nenable_load\nenable_symbols\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP\nXMKMF\nAUTOSTEREOD'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE_TARNAME}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=*)\tac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *)\tac_optarg=yes ;;\n  esac\n\n  # Accept the important Cygnus configure options, so we can diagnose typos.\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error \"unrecognized option: \\`$ac_option'\nTry \\`$0 --help' for more information.\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error \"invalid variable name: \\`$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    $as_echo \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      $as_echo \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`echo $ac_prev | sed 's/_/-/g'`\n  as_fn_error \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     $as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: `$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n    $as_echo \"$as_me: WARNING: If you wanted to set the --build type, don't use --host.\n    If a cross compiler is detected then cross compile mode will be used.\" >&2\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but \\`cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n\\`configure' configures Togl 2.1 to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print \\`checking...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for \\`--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or \\`..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, \\`make install' will install all the files in\n\\`$ac_default_prefix/bin', \\`$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than \\`$ac_default_prefix' using \\`--prefix',\nfor instance \\`--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/togl]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n\nX features:\n  --x-includes=DIR    X include files are in DIR\n  --x-libraries=DIR   X library files are in DIR\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n  case $ac_init_help in\n     short | recursive ) echo \"Configuration of Togl 2.1:\";;\n   esac\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n  --enable-stubs          build and link with stub libraries (--enable-stubs)\n  --enable-threads        build with threads\n  --enable-shared         build and link with shared libraries (default: on)\n  --enable-64bit          enable 64bit support (default: off)\n  --enable-64bit-vis      enable 64bit Sparc VIS support (default: off)\n  --disable-rpath         disable rpath support (default: on)\n  --enable-wince          enable Win/CE support (where applicable)\n  --enable-load           allow dynamic loading and \"load\" command (default:\n                          on)\n  --enable-symbols        build with debugging symbols (default: off)\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-tcl              directory containing tcl configuration\n                          (tclConfig.sh)\n  --with-tk               directory containing tk configuration (tkConfig.sh)\n  --with-tclinclude       directory containing the public Tcl header files\n  --with-tkinclude        directory containing the public Tk header files\n  --with-x                use the X Window System\n  --with-autostereo       directory with autostereo source (for SGI)\n  --with-autostereod      path to autostereod daemon (for SGI)\n  --with-Xmu              use system's shared Xmu library\n  --with-celib=DIR        use Windows/CE support library from DIR\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n  XMKMF       Path to xmkmf, Makefile generator for X Window System\n  AUTOSTEREOD Path to autostereod for SGI IRIX computers\n\nUse these variables to override the choices made by `configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for guested configure.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      $as_echo \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\nTogl configure 2.1\ngenerated by GNU Autoconf 2.65\n\nCopyright (C) 2009 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } >/dev/null && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1\nfi\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\n\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes\n# that executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: program exited with status $ac_status\" >&5\n       $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif { as_var=$3; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t $as_test_x conftest$ac_exeext\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_check_func LINENO FUNC VAR\n# ----------------------------------\n# Tests whether FUNC exists, setting the cache variable VAR accordingly\nac_fn_c_check_func ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif { as_var=$3; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n/* Define $2 to an innocuous variant, in case <limits.h> declares $2.\n   For example, HP-UX 11i <limits.h> declares gettimeofday.  */\n#define $2 innocuous_$2\n\n/* System header to define __stub macros and hopefully few prototypes,\n    which can conflict with char $2 (); below.\n    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n    <limits.h> exists even on freestanding compilers.  */\n\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\n#undef $2\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar $2 ();\n/* The GNU C library defines this for functions which it implements\n    to always fail with ENOSYS.  Some functions are actually named\n    something starting with __ and the normal name is an alias.  */\n#if defined __stub_$2 || defined __stub___$2\nchoke me\n#endif\n\nint\nmain ()\n{\nreturn $2 ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n\n} # ac_fn_c_check_func\n\n# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists, giving a warning if it cannot be compiled using\n# the include files in INCLUDES and setting the cache variable VAR\n# accordingly.\nac_fn_c_check_header_mongrel ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { as_var=$3; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif { as_var=$3; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  $as_echo_n \"(cached) \" >&6\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nelse\n  # Is the header compilable?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 usability\" >&5\n$as_echo_n \"checking $2 usability... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_header_compiler=yes\nelse\n  ac_header_compiler=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler\" >&5\n$as_echo \"$ac_header_compiler\" >&6; }\n\n# Is the header present?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 presence\" >&5\n$as_echo_n \"checking $2 presence... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <$2>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  ac_header_preproc=yes\nelse\n  ac_header_preproc=no\nfi\nrm -f conftest.err conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc\" >&5\n$as_echo \"$ac_header_preproc\" >&6; }\n\n# So?  What about this header?\ncase $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((\n  yes:no: )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&5\n$as_echo \"$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\n  no:yes:* )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled\" >&5\n$as_echo \"$as_me: WARNING: $2: present but cannot be compiled\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?\" >&5\n$as_echo \"$as_me: WARNING: $2:     check for missing prerequisite headers?\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation\" >&5\n$as_echo \"$as_me: WARNING: $2: see the Autoconf documentation\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&5\n$as_echo \"$as_me: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\nesac\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif { as_var=$3; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  eval \"$3=\\$ac_header_compiler\"\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nfi\n  eval $as_lineno_stack; test \"x$as_lineno_stack\" = x && { as_lineno=; unset as_lineno;}\n\n} # ac_fn_c_check_header_mongrel\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by Togl $as_me 2.1, which was\ngenerated by GNU Autoconf 2.65.  Invocation command line was\n\n  $ $0 $@\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    $as_echo \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`$as_echo \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.  We remove comments because anyway the quotes in there\n# would cause problems or look ugly.\n# WARNING: Use '\\'' to represent an apostrophe within the trap.\n# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.\ntrap 'exit_status=$?\n  # Save into config.log some information that might help in debugging.\n  {\n    echo\n\n    cat <<\\_ASBOX\n## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\n_ASBOX\n    echo\n    # The following way of writing the cache mishandles newlines in values,\n(\n  for ac_var in `(set) 2>&1 | sed -n '\\''s/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'\\''`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n  (set) 2>&1 |\n    case $as_nl`(ac_space='\\'' '\\''; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      sed -n \\\n\t\"s/'\\''/'\\''\\\\\\\\'\\'''\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\''\\\\2'\\''/p\"\n      ;; #(\n    *)\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n    echo\n\n    cat <<\\_ASBOX\n## ----------------- ##\n## Output variables. ##\n## ----------------- ##\n_ASBOX\n    echo\n    for ac_var in $ac_subst_vars\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n      esac\n      $as_echo \"$ac_var='\\''$ac_val'\\''\"\n    done | sort\n    echo\n\n    if test -n \"$ac_subst_files\"; then\n      cat <<\\_ASBOX\n## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\n_ASBOX\n      echo\n      for ac_var in $ac_subst_files\n      do\n\teval ac_val=\\$$ac_var\n\tcase $ac_val in\n\t*\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n\tesac\n\t$as_echo \"$ac_var='\\''$ac_val'\\''\"\n      done | sort\n      echo\n    fi\n\n    if test -s confdefs.h; then\n      cat <<\\_ASBOX\n## ----------- ##\n## confdefs.h. ##\n## ----------- ##\n_ASBOX\n      echo\n      cat confdefs.h\n      echo\n    fi\n    test \"$ac_signal\" != 0 &&\n      $as_echo \"$as_me: caught signal $ac_signal\"\n    $as_echo \"$as_me: exit $exit_status\"\n  } >&5\n  rm -f core *.core core.conftest.* &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\n$as_echo \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_NAME \"$PACKAGE_NAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_VERSION \"$PACKAGE_VERSION\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_STRING \"$PACKAGE_STRING\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_URL \"$PACKAGE_URL\"\n_ACEOF\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nac_site_file1=NONE\nac_site_file2=NONE\nif test -n \"$CONFIG_SITE\"; then\n  ac_site_file1=$CONFIG_SITE\nelif test \"x$prefix\" != xNONE; then\n  ac_site_file1=$prefix/share/config.site\n  ac_site_file2=$prefix/etc/config.site\nelse\n  ac_site_file1=$ac_default_prefix/share/config.site\n  ac_site_file2=$ac_default_prefix/etc/config.site\nfi\nfor ac_site_file in \"$ac_site_file1\" \"$ac_site_file2\"\ndo\n  test \"x$ac_site_file\" = xNONE && continue\n  if test /dev/null != \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\n$as_echo \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\"\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\n$as_echo \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\n$as_echo \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was not set in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=`echo x $ac_old_val`\n\tac_new_val_w=`echo x $ac_new_val`\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' has changed since the previous run:\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&5\n$as_echo \"$as_me: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   former value:  \\`$ac_old_val'\" >&5\n$as_echo \"$as_me:   former value:  \\`$ac_old_val'\" >&2;}\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   current value: \\`$ac_new_val'\" >&5\n$as_echo \"$as_me:   current value: \\`$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`$as_echo \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\n$as_echo \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error \"run \\`make distclean' and/or \\`rm $cache_file' and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n#--------------------------------------------------------------------\n# Call TEA_INIT as the first TEA_ macro to set up initial vars.\n# This will define a ${TEA_PLATFORM} variable == \"unix\" or \"windows\"\n# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.\n#--------------------------------------------------------------------\n\n\n    # TEA extensions pass this us the version of TEA they think they\n    # are compatible with.\n    TEA_VERSION=\"3.7\"\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration\" >&5\n$as_echo_n \"checking for correct TEA configuration... \" >&6; }\n    if test x\"${PACKAGE_NAME}\" = x ; then\n\tas_fn_error \"\nThe PACKAGE_NAME variable must be defined by your TEA configure.in\" \"$LINENO\" 5\n    fi\n    if test x\"3.7\" = x ; then\n\tas_fn_error \"\nTEA version not specified.\" \"$LINENO\" 5\n    elif test \"3.7\" != \"${TEA_VERSION}\" ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \\\"3.7\\\", have \\\"${TEA_VERSION}\\\"\" >&5\n$as_echo \"warning: requested TEA version \\\"3.7\\\", have \\\"${TEA_VERSION}\\\"\" >&6; }\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})\" >&5\n$as_echo \"ok (TEA ${TEA_VERSION})\" >&6; }\n    fi\n    case \"`uname -s`\" in\n\t*win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*)\n\t    # Extract the first word of \"cygpath\", so it can be a program name with args.\nset dummy cygpath; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_CYGPATH+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CYGPATH\"; then\n  ac_cv_prog_CYGPATH=\"$CYGPATH\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_CYGPATH=\"cygpath -w\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_prog_CYGPATH\" && ac_cv_prog_CYGPATH=\"echo\"\nfi\nfi\nCYGPATH=$ac_cv_prog_CYGPATH\nif test -n \"$CYGPATH\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CYGPATH\" >&5\n$as_echo \"$CYGPATH\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n\t    EXEEXT=\".exe\"\n\t    TEA_PLATFORM=\"windows\"\n\t    ;;\n\t*)\n\t    CYGPATH=echo\n\t    EXEEXT=\"\"\n\t    TEA_PLATFORM=\"unix\"\n\t    ;;\n    esac\n\n    # Check if exec_prefix is set. If not use fall back to prefix.\n    # Note when adjusted, so that TEA_PREFIX can correct for this.\n    # This is needed for recursive configures, since autoconf propagates\n    # $prefix, but not $exec_prefix (doh!).\n    if test x$exec_prefix = xNONE ; then\n\texec_prefix_default=yes\n\texec_prefix=$prefix\n    fi\n\n\n\n\n    # This package name must be replaced statically for AC_SUBST to work\n\n    # Substitute STUB_LIB_FILE in case package creates a stub library too.\n\n\n    # We AC_SUBST these here to ensure they are subst'ed,\n    # in case the user doesn't call TEA_ADD_...\n\n\n\n\n\n\n\n\n\nac_aux_dir=\nfor ac_dir in tclconfig \"$srcdir\"/tclconfig; do\n  for ac_t in install-sh install.sh shtool; do\n    if test -f \"$ac_dir/$ac_t\"; then\n      ac_aux_dir=$ac_dir\n      ac_install_sh=\"$ac_aux_dir/$ac_t -c\"\n      break 2\n    fi\n  done\ndone\nif test -z \"$ac_aux_dir\"; then\n  as_fn_error \"cannot find install-sh, install.sh, or shtool in tclconfig \\\"$srcdir\\\"/tclconfig\" \"$LINENO\" 5\nfi\n\n# These three variables are undocumented and unsupported,\n# and are intended to be withdrawn in a future Autoconf release.\n# They can cause serious problems if a builder's source tree is in a directory\n# whose full name contains unusual characters.\nac_config_guess=\"$SHELL $ac_aux_dir/config.guess\"  # Please don't use this var.\nac_config_sub=\"$SHELL $ac_aux_dir/config.sub\"  # Please don't use this var.\nac_configure=\"$SHELL $ac_aux_dir/configure\"  # Please don't use this var.\n\n\n\n#--------------------------------------------------------------------\n# Load the tclConfig.sh file\n#--------------------------------------------------------------------\n\n\n\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\n# Check whether --with-tcl was given.\nif test \"${with_tcl+set}\" = set; then :\n  withval=$with_tcl; with_tclconfig=${withval}\nfi\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tcl configuration\" >&5\n$as_echo_n \"checking for Tcl configuration... \" >&6; }\n\tif test \"${ac_cv_c_tclconfig+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase ${with_tclconfig} in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f ${with_tclconfig}; then\n\t\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&5\n$as_echo \"$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&2;}\n\t\t\t    with_tclconfig=`echo ${with_tclconfig} | sed 's!/tclConfig\\.sh$!!'`\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`\n\t\telse\n\t\t    as_fn_error \"${with_tclconfig} directory doesn't contain tclConfig.sh\" \"$LINENO\" 5\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /System/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tcl.framework/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # TEA specific: on Windows, check in common installation locations\n\t    if test \"${TEA_PLATFORM}\" = \"windows\" \\\n\t\t-a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=`(cd $i/unix; pwd)`\n\t\t    break\n\t\tfi\n\t\tdone\n\t    fi\n\nfi\n\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    as_fn_error \"Can't find Tcl configuration definitions\" \"$LINENO\" 5\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=${ac_cv_c_tclconfig}\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh\" >&5\n$as_echo \"found ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n\tfi\n    fi\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh\" >&5\n$as_echo_n \"checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... \" >&6; }\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n        { $as_echo \"$as_me:${as_lineno-$LINENO}: result: loading\" >&5\n$as_echo \"loading\" >&6; }\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n        { $as_echo \"$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&5\n$as_echo \"could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n    fi\n\n    # eval is required to do the TCL_DBGX substitution\n    eval \"TCL_LIB_FILE=\\\"${TCL_LIB_FILE}\\\"\"\n    eval \"TCL_STUB_LIB_FILE=\\\"${TCL_STUB_LIB_FILE}\\\"\"\n\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}\n        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}\n        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tcl was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tcl.framework installed in an arbitrary location.\n\tcase ${TCL_DEFS} in\n\t    *TCL_FRAMEWORK*)\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_LIB_FILE}\"; then\n\t\t    for i in \"`cd ${TCL_BIN_DIR}; pwd`\" \\\n\t\t\t     \"`cd ${TCL_BIN_DIR}/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TCL_LIB_FILE}.framework\"; then\n\t\t\t    TCL_LIB_SPEC=\"-F`dirname \"$i\"` -framework ${TCL_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"; then\n\t\t    TCL_STUB_LIB_SPEC=\"-L${TCL_BIN_DIR} ${TCL_STUB_LIB_FLAG}\"\n\t\t    TCL_STUB_LIB_PATH=\"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    # eval is required to do the TCL_DBGX substitution\n    eval \"TCL_LIB_FLAG=\\\"${TCL_LIB_FLAG}\\\"\"\n    eval \"TCL_LIB_SPEC=\\\"${TCL_LIB_SPEC}\\\"\"\n    eval \"TCL_STUB_LIB_FLAG=\\\"${TCL_STUB_LIB_FLAG}\\\"\"\n    eval \"TCL_STUB_LIB_SPEC=\\\"${TCL_STUB_LIB_SPEC}\\\"\"\n\n\n\n\n\n\n\n\n\n\n\n\n\n    # TEA specific:\n\n\n\n\n\n\n\n#--------------------------------------------------------------------\n# Load the tkConfig.sh file if necessary (Tk extension)\n#--------------------------------------------------------------------\n\n\n    #\n    # Ok, lets find the tk configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tk\n    #\n\n    if test x\"${no_tk}\" = x ; then\n\t# we reset no_tk in case something fails here\n\tno_tk=true\n\n# Check whether --with-tk was given.\nif test \"${with_tk+set}\" = set; then :\n  withval=$with_tk; with_tkconfig=${withval}\nfi\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tk configuration\" >&5\n$as_echo_n \"checking for Tk configuration... \" >&6; }\n\tif test \"${ac_cv_c_tkconfig+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\n\t    # First check to see if --with-tkconfig was specified.\n\t    if test x\"${with_tkconfig}\" != x ; then\n\t\tcase ${with_tkconfig} in\n\t\t    */tkConfig.sh )\n\t\t\tif test -f ${with_tkconfig}; then\n\t\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself\" >&5\n$as_echo \"$as_me: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself\" >&2;}\n\t\t\t    with_tkconfig=`echo ${with_tkconfig} | sed 's!/tkConfig\\.sh$!!'`\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tkconfig}/tkConfig.sh\" ; then\n\t\t    ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`\n\t\telse\n\t\t    as_fn_error \"${with_tkconfig} directory doesn't contain tkConfig.sh\" \"$LINENO\" 5\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tk library\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tk \\\n\t\t\t`ls -dr ../tk[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../tk \\\n\t\t\t`ls -dr ../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../../tk \\\n\t\t\t`ls -dr ../../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /System/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tk.framework/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/Tk.framework; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # TEA specific: on Windows, check in common installation locations\n\t    if test \"${TEA_PLATFORM}\" = \"windows\" \\\n\t\t-a x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tk \\\n\t\t\t`ls -dr ${srcdir}/../tk[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\nfi\n\n\n\tif test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t    TK_BIN_DIR=\"# no Tk configs found\"\n\t    as_fn_error \"Can't find Tk configuration definitions\" \"$LINENO\" 5\n\telse\n\t    no_tk=\n\t    TK_BIN_DIR=${ac_cv_c_tkconfig}\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: found ${TK_BIN_DIR}/tkConfig.sh\" >&5\n$as_echo \"found ${TK_BIN_DIR}/tkConfig.sh\" >&6; }\n\tfi\n    fi\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for existence of ${TK_BIN_DIR}/tkConfig.sh\" >&5\n$as_echo_n \"checking for existence of ${TK_BIN_DIR}/tkConfig.sh... \" >&6; }\n\n    if test -f \"${TK_BIN_DIR}/tkConfig.sh\" ; then\n        { $as_echo \"$as_me:${as_lineno-$LINENO}: result: loading\" >&5\n$as_echo \"loading\" >&6; }\n\t. \"${TK_BIN_DIR}/tkConfig.sh\"\n    else\n        { $as_echo \"$as_me:${as_lineno-$LINENO}: result: could not find ${TK_BIN_DIR}/tkConfig.sh\" >&5\n$as_echo \"could not find ${TK_BIN_DIR}/tkConfig.sh\" >&6; }\n    fi\n\n    # eval is required to do the TK_DBGX substitution\n    eval \"TK_LIB_FILE=\\\"${TK_LIB_FILE}\\\"\"\n    eval \"TK_STUB_LIB_FILE=\\\"${TK_STUB_LIB_FILE}\\\"\"\n\n    # If the TK_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TK_LIB_SPEC will be set to the value\n    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC\n    # instead of TK_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n        TK_LIB_SPEC=${TK_BUILD_LIB_SPEC}\n        TK_STUB_LIB_SPEC=${TK_BUILD_STUB_LIB_SPEC}\n        TK_STUB_LIB_PATH=${TK_BUILD_STUB_LIB_PATH}\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tk was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tk.framework installed in an arbitrary location.\n\tcase ${TK_DEFS} in\n\t    *TK_FRAMEWORK*)\n\t\tif test -f \"${TK_BIN_DIR}/${TK_LIB_FILE}\"; then\n\t\t    for i in \"`cd ${TK_BIN_DIR}; pwd`\" \\\n\t\t\t     \"`cd ${TK_BIN_DIR}/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TK_LIB_FILE}.framework\"; then\n\t\t\t    TK_LIB_SPEC=\"-F`dirname \"$i\"` -framework ${TK_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"; then\n\t\t    TK_STUB_LIB_SPEC=\"-L${TK_BIN_DIR} ${TK_STUB_LIB_FLAG}\"\n\t\t    TK_STUB_LIB_PATH=\"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    # eval is required to do the TK_DBGX substitution\n    eval \"TK_LIB_FLAG=\\\"${TK_LIB_FLAG}\\\"\"\n    eval \"TK_LIB_SPEC=\\\"${TK_LIB_SPEC}\\\"\"\n    eval \"TK_STUB_LIB_FLAG=\\\"${TK_STUB_LIB_FLAG}\\\"\"\n    eval \"TK_STUB_LIB_SPEC=\\\"${TK_STUB_LIB_SPEC}\\\"\"\n\n    # TEA specific: Ensure windowingsystem is defined\n    if test \"${TEA_PLATFORM}\" = \"unix\" ; then\n\tcase ${TK_DEFS} in\n\t    *MAC_OSX_TK*)\n\n$as_echo \"#define MAC_OSX_TK 1\" >>confdefs.h\n\n\t\tTEA_WINDOWINGSYSTEM=\"aqua\"\n\t\t;;\n\t    *)\n\t\tTEA_WINDOWINGSYSTEM=\"x11\"\n\t\t;;\n\tesac\n    elif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\tTEA_WINDOWINGSYSTEM=\"win32\"\n    fi\n\n\n\n\n\n\n\n\n\n\n\n\n\n    # TEA specific:\n\n\n\n\n#-----------------------------------------------------------------------\n# Handle the --prefix=... option by defaulting to what Tcl gave.\n# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.\n#-----------------------------------------------------------------------\n\n\n    if test \"${prefix}\" = \"NONE\"; then\n\tprefix_default=yes\n\tif test x\"${TCL_PREFIX}\" != x; then\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}\" >&5\n$as_echo \"$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}\" >&6;}\n\t    prefix=${TCL_PREFIX}\n\telse\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local\" >&5\n$as_echo \"$as_me: --prefix defaulting to /usr/local\" >&6;}\n\t    prefix=/usr/local\n\tfi\n    fi\n    if test \"${exec_prefix}\" = \"NONE\" -a x\"${prefix_default}\" = x\"yes\" \\\n\t-o x\"${exec_prefix_default}\" = x\"yes\" ; then\n\tif test x\"${TCL_EXEC_PREFIX}\" != x; then\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}\" >&5\n$as_echo \"$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}\" >&6;}\n\t    exec_prefix=${TCL_EXEC_PREFIX}\n\telse\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}\" >&5\n$as_echo \"$as_me: --exec-prefix defaulting to ${prefix}\" >&6;}\n\t    exec_prefix=$prefix\n\tfi\n    fi\n\n\n#-----------------------------------------------------------------------\n# Standard compiler checks.\n# This sets up CC by using the CC env var, or looks for gcc otherwise.\n# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create\n# the basic setup necessary to compile executables.\n#-----------------------------------------------------------------------\n\n# Find a good install program.  We prefer a C program (faster),\n# so one script is as good as another.  But avoid the broken or\n# incompatible versions:\n# SysV /etc/install, /usr/sbin/install\n# SunOS /usr/etc/install\n# IRIX /sbin/install\n# AIX /bin/install\n# AmigaOS /C/install, which installs bootblocks on floppy discs\n# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag\n# AFS /usr/afsws/bin/install, which mishandles nonexistent args\n# SVR4 /usr/ucb/install, which tries to use the nonexistent group \"staff\"\n# OS/2's system install, which has a completely different semantic\n# ./install, which can be erroneously created by make from ./install.sh.\n# Reject install programs that cannot install multiple files.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install\" >&5\n$as_echo_n \"checking for a BSD-compatible install... \" >&6; }\nif test -z \"$INSTALL\"; then\nif test \"${ac_cv_path_install+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    # Account for people who put trailing slashes in PATH elements.\ncase $as_dir/ in #((\n  ./ | .// | /[cC]/* | \\\n  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \\\n  ?:[\\\\/]os2[\\\\/]install[\\\\/]* | ?:[\\\\/]OS2[\\\\/]INSTALL[\\\\/]* | \\\n  /usr/ucb/* ) ;;\n  *)\n    # OSF1 and SCO ODT 3.0 have their own names for install.\n    # Don't use installbsd from OSF since it installs stuff as root\n    # by default.\n    for ac_prog in ginstall scoinst install; do\n      for ac_exec_ext in '' $ac_executable_extensions; do\n\tif { test -f \"$as_dir/$ac_prog$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_prog$ac_exec_ext\"; }; then\n\t  if test $ac_prog = install &&\n\t    grep dspmsg \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # AIX install.  It has an incompatible calling convention.\n\t    :\n\t  elif test $ac_prog = install &&\n\t    grep pwplus \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # program-specific install script used by HP pwplus--don't use.\n\t    :\n\t  else\n\t    rm -rf conftest.one conftest.two conftest.dir\n\t    echo one > conftest.one\n\t    echo two > conftest.two\n\t    mkdir conftest.dir\n\t    if \"$as_dir/$ac_prog$ac_exec_ext\" -c conftest.one conftest.two \"`pwd`/conftest.dir\" &&\n\t      test -s conftest.one && test -s conftest.two &&\n\t      test -s conftest.dir/conftest.one &&\n\t      test -s conftest.dir/conftest.two\n\t    then\n\t      ac_cv_path_install=\"$as_dir/$ac_prog$ac_exec_ext -c\"\n\t      break 3\n\t    fi\n\t  fi\n\tfi\n      done\n    done\n    ;;\nesac\n\n  done\nIFS=$as_save_IFS\n\nrm -rf conftest.one conftest.two conftest.dir\n\nfi\n  if test \"${ac_cv_path_install+set}\" = set; then\n    INSTALL=$ac_cv_path_install\n  else\n    # As a last resort, use the slow shell script.  Don't cache a\n    # value for INSTALL within a source directory, because that will\n    # break other packages using the cache if that directory is\n    # removed, or if the value is a relative name.\n    INSTALL=$ac_install_sh\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $INSTALL\" >&5\n$as_echo \"$INSTALL\" >&6; }\n\n# Use test -z because SunOS4 sh mishandles braces in ${var-val}.\n# It thinks the first close brace ends the variable substitution.\ntest -z \"$INSTALL_PROGRAM\" && INSTALL_PROGRAM='${INSTALL}'\n\ntest -z \"$INSTALL_SCRIPT\" && INSTALL_SCRIPT='${INSTALL}'\n\ntest -z \"$INSTALL_DATA\" && INSTALL_DATA='${INSTALL} -m 644'\n\n\n    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)\n    # in this macro, they need to go into TEA_SETUP_COMPILER instead.\n\n    # If the user did not set CFLAGS, set it now to keep\n    # the AC_PROG_CC macro from adding \"-g -O2\".\n    if test \"${CFLAGS+set}\" != \"set\" ; then\n\tCFLAGS=\"\"\n    fi\n\n    ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_ac_ct_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_ac_ct_CC+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\n$as_echo_n \"checking whether the C compiler works... \" >&6; }\nac_link_default=`$as_echo \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.\n# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test \"${ac_cv_exeext+set}\" = set && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an `-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse\n  ac_file=''\nfi\nif test -z \"$ac_file\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n$as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n{ as_fn_set_status 77\nas_fn_error \"C compiler cannot create executables\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\n$as_echo_n \"checking for C compiler default output file name... \" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\n$as_echo \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\n$as_echo_n \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # If both `conftest.exe' and `conftest' are `present' (well, observable)\n# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will\n# work properly (i.e., refer to `conftest.exe'), while it won't with\n# `rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error \"cannot compute suffix of executables: cannot compile and link\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\n$as_echo \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain ()\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\n$as_echo_n \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error \"cannot run C compiled programs.\nIf you meant to cross compile, use \\`--host'.\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\n$as_echo \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\n$as_echo_n \"checking for suffix of object files... \" >&6; }\nif test \"${ac_cv_objext+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error \"cannot compute suffix of object files: cannot compile\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\n$as_echo \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif test \"${ac_cv_c_compiler_gnu+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif test \"${ac_cv_prog_cc_g+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif test \"${ac_cv_prog_cc_c89+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n    ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\n$as_echo_n \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if test \"${ac_cv_prog_CPP+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n      # Double quotes because CPP needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" \"/lib/cpp\"\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\n$as_echo \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee \\`config.log' for more details.\" \"$LINENO\" 5; }\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n    #--------------------------------------------------------------------\n    # Checks to see if the make program sets the $MAKE variable.\n    #--------------------------------------------------------------------\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \\$(MAKE)\" >&5\n$as_echo_n \"checking whether ${MAKE-make} sets \\$(MAKE)... \" >&6; }\nset x ${MAKE-make}\nac_make=`$as_echo \"$2\" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`\nif { as_var=ac_cv_prog_make_${ac_make}_set; eval \"test \\\"\\${$as_var+set}\\\" = set\"; }; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat >conftest.make <<\\_ACEOF\nSHELL = /bin/sh\nall:\n\t@echo '@@@%%%=$(MAKE)=@@@%%%'\n_ACEOF\n# GNU make sometimes prints \"make[1]: Entering...\", which would confuse us.\ncase `${MAKE-make} -f conftest.make 2>/dev/null` in\n  *@@@%%%=?*=@@@%%%*)\n    eval ac_cv_prog_make_${ac_make}_set=yes;;\n  *)\n    eval ac_cv_prog_make_${ac_make}_set=no;;\nesac\nrm -f conftest.make\nfi\nif eval test \\$ac_cv_prog_make_${ac_make}_set = yes; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n  SET_MAKE=\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n  SET_MAKE=\"MAKE=${MAKE-make}\"\nfi\n\n\n    #--------------------------------------------------------------------\n    # Find ranlib\n    #--------------------------------------------------------------------\n\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_RANLIB+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\n$as_echo \"$RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_ac_ct_RANLIB+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\n$as_echo \"$ac_ct_RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\n\n    #--------------------------------------------------------------------\n    # Determines the correct binary file extension (.o, .obj, .exe etc.)\n    #--------------------------------------------------------------------\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e\" >&5\n$as_echo_n \"checking for grep that handles long lines and -e... \" >&6; }\nif test \"${ac_cv_path_GREP+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -z \"$GREP\"; then\n  ac_path_GREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in grep ggrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_GREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      { test -f \"$ac_path_GREP\" && $as_test_x \"$ac_path_GREP\"; } || continue\n# Check for GNU ac_path_GREP and select it if it is found.\n  # Check for GNU $ac_path_GREP\ncase `\"$ac_path_GREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_GREP=\"$ac_path_GREP\" ac_path_GREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'GREP' >> \"conftest.nl\"\n    \"$ac_path_GREP\" -e 'GREP$' -e '-(cannot match)-' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_GREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_GREP=\"$ac_path_GREP\"\n      ac_path_GREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_GREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_GREP\"; then\n    as_fn_error \"no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_GREP=$GREP\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP\" >&5\n$as_echo \"$ac_cv_path_GREP\" >&6; }\n GREP=\"$ac_cv_path_GREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for egrep\" >&5\n$as_echo_n \"checking for egrep... \" >&6; }\nif test \"${ac_cv_path_EGREP+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1\n   then ac_cv_path_EGREP=\"$GREP -E\"\n   else\n     if test -z \"$EGREP\"; then\n  ac_path_EGREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in egrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      { test -f \"$ac_path_EGREP\" && $as_test_x \"$ac_path_EGREP\"; } || continue\n# Check for GNU ac_path_EGREP and select it if it is found.\n  # Check for GNU $ac_path_EGREP\ncase `\"$ac_path_EGREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_EGREP=\"$ac_path_EGREP\" ac_path_EGREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'EGREP' >> \"conftest.nl\"\n    \"$ac_path_EGREP\" 'EGREP$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP=\"$ac_path_EGREP\"\n      ac_path_EGREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP\"; then\n    as_fn_error \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP=$EGREP\nfi\n\n   fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP\" >&5\n$as_echo \"$ac_cv_path_EGREP\" >&6; }\n EGREP=\"$ac_cv_path_EGREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ANSI C header files\" >&5\n$as_echo_n \"checking for ANSI C header files... \" >&6; }\nif test \"${ac_cv_header_stdc+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n#include <float.h>\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_header_stdc=yes\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nif test $ac_cv_header_stdc = yes; then\n  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"memchr\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"free\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.\n  if test \"$cross_compiling\" = yes; then :\n  :\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ctype.h>\n#include <stdlib.h>\n#if ((' ' & 0x0FF) == 0x020)\n# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')\n# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))\n#else\n# define ISLOWER(c) \\\n\t\t   (('a' <= (c) && (c) <= 'i') \\\n\t\t     || ('j' <= (c) && (c) <= 'r') \\\n\t\t     || ('s' <= (c) && (c) <= 'z'))\n# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))\n#endif\n\n#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))\nint\nmain ()\n{\n  int i;\n  for (i = 0; i < 256; i++)\n    if (XOR (islower (i), ISLOWER (i))\n\t|| toupper (i) != TOUPPER (i))\n      return 2;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc\" >&5\n$as_echo \"$ac_cv_header_stdc\" >&6; }\nif test $ac_cv_header_stdc = yes; then\n\n$as_echo \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\n# On IRIX 5.3, sys/types and inttypes.h are conflicting.\nfor ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \\\n\t\t  inttypes.h stdint.h unistd.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_compile \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\n\"\neval as_val=\\$$as_ac_Header\n   if test \"x$as_val\" = x\"\"yes; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\n\n\n    # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.\n\n\n    #------------------------------------------------------------------------\n    # If we're using GCC, see if the compiler understands -pipe. If so, use it.\n    # It makes compiling go faster.  (This is only a performance feature.)\n    #------------------------------------------------------------------------\n\n    if test -z \"$no_pipe\" -a -n \"$GCC\"; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe\" >&5\n$as_echo_n \"checking if the compiler understands -pipe... \" >&6; }\nif test \"${tcl_cv_cc_pipe+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -pipe\"\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_cc_pipe=yes\nelse\n  tcl_cv_cc_pipe=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\t    CFLAGS=$hold_cflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe\" >&5\n$as_echo \"$tcl_cv_cc_pipe\" >&6; }\n\tif test $tcl_cv_cc_pipe = yes; then\n\t    CFLAGS=\"$CFLAGS -pipe\"\n\tfi\n    fi\n\n    #--------------------------------------------------------------------\n    # Common compiler flag setup\n    #--------------------------------------------------------------------\n\n     { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian\" >&5\n$as_echo_n \"checking whether byte ordering is bigendian... \" >&6; }\nif test \"${ac_cv_c_bigendian+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_c_bigendian=unknown\n    # See if we're dealing with a universal compiler.\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __APPLE_CC__\n\t       not a universal capable compiler\n\t     #endif\n\t     typedef int dummy;\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\n\t# Check for potential -arch flags.  It is not universal unless\n\t# there are at least two -arch flags with different values.\n\tac_arch=\n\tac_prev=\n\tfor ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do\n\t if test -n \"$ac_prev\"; then\n\t   case $ac_word in\n\t     i?86 | x86_64 | ppc | ppc64)\n\t       if test -z \"$ac_arch\" || test \"$ac_arch\" = \"$ac_word\"; then\n\t\t ac_arch=$ac_word\n\t       else\n\t\t ac_cv_c_bigendian=universal\n\t\t break\n\t       fi\n\t       ;;\n\t   esac\n\t   ac_prev=\n\t elif test \"x$ac_word\" = \"x-arch\"; then\n\t   ac_prev=arch\n\t fi\n       done\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if sys/param.h defines the BYTE_ORDER macro.\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t     #include <sys/param.h>\n\nint\nmain ()\n{\n#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\\n\t\t     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\\n\t\t     && LITTLE_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  # It does; now see whether it defined to BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t\t#include <sys/param.h>\n\nint\nmain ()\n{\n#if BYTE_ORDER != BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_bigendian=yes\nelse\n  ac_cv_c_bigendian=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain ()\n{\n#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  # It does; now see whether it defined to _BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain ()\n{\n#ifndef _BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_bigendian=yes\nelse\n  ac_cv_c_bigendian=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # Compile a test program.\n      if test \"$cross_compiling\" = yes; then :\n  # Try to guess by grepping values from an object file.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nshort int ascii_mm[] =\n\t\t  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };\n\t\tshort int ascii_ii[] =\n\t\t  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };\n\t\tint use_ascii (int i) {\n\t\t  return ascii_mm[i] + ascii_ii[i];\n\t\t}\n\t\tshort int ebcdic_ii[] =\n\t\t  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };\n\t\tshort int ebcdic_mm[] =\n\t\t  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };\n\t\tint use_ebcdic (int i) {\n\t\t  return ebcdic_mm[i] + ebcdic_ii[i];\n\t\t}\n\t\textern int foo;\n\nint\nmain ()\n{\nreturn use_ascii (foo) == use_ebcdic (foo);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then\n\t      ac_cv_c_bigendian=yes\n\t    fi\n\t    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then\n\t      if test \"$ac_cv_c_bigendian\" = unknown; then\n\t\tac_cv_c_bigendian=no\n\t      else\n\t\t# finding both strings is unlikely to happen, but who knows?\n\t\tac_cv_c_bigendian=unknown\n\t      fi\n\t    fi\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain ()\n{\n\n\t     /* Are we little or big endian?  From Harbison&Steele.  */\n\t     union\n\t     {\n\t       long int l;\n\t       char c[sizeof (long int)];\n\t     } u;\n\t     u.l = 1;\n\t     return u.c[sizeof (long int) - 1] == 1;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n  ac_cv_c_bigendian=no\nelse\n  ac_cv_c_bigendian=yes\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\n    fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian\" >&5\n$as_echo \"$ac_cv_c_bigendian\" >&6; }\n case $ac_cv_c_bigendian in #(\n   yes)\n     $as_echo \"#define WORDS_BIGENDIAN 1\" >>confdefs.h\n;; #(\n   no)\n      ;; #(\n   universal)\n\n$as_echo \"#define AC_APPLE_UNIVERSAL_BUILD 1\" >>confdefs.h\n\n     ;; #(\n   *)\n     as_fn_error \"unknown endianness\n presetting ac_cv_c_bigendian=no (or yes) will help\" \"$LINENO\" 5 ;;\n esac\n\n    if test \"${TEA_PLATFORM}\" = \"unix\" ; then\n\n    #--------------------------------------------------------------------\n    # On a few very rare systems, all of the libm.a stuff is\n    # already in libc.a.  Set compiler flags accordingly.\n    # Also, Linux requires the \"ieee\" library for math to work\n    # right (and it must appear before \"-lm\").\n    #--------------------------------------------------------------------\n\n    ac_fn_c_check_func \"$LINENO\" \"sin\" \"ac_cv_func_sin\"\nif test \"x$ac_cv_func_sin\" = x\"\"yes; then :\n  MATH_LIBS=\"\"\nelse\n  MATH_LIBS=\"-lm\"\nfi\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for main in -lieee\" >&5\n$as_echo_n \"checking for main in -lieee... \" >&6; }\nif test \"${ac_cv_lib_ieee_main+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lieee  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\nreturn main ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_ieee_main=yes\nelse\n  ac_cv_lib_ieee_main=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main\" >&5\n$as_echo \"$ac_cv_lib_ieee_main\" >&6; }\nif test \"x$ac_cv_lib_ieee_main\" = x\"\"yes; then :\n  MATH_LIBS=\"-lieee $MATH_LIBS\"\nfi\n\n\n    #--------------------------------------------------------------------\n    # Interactive UNIX requires -linet instead of -lsocket, plus it\n    # needs net/errno.h to define the socket-related error codes.\n    #--------------------------------------------------------------------\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for main in -linet\" >&5\n$as_echo_n \"checking for main in -linet... \" >&6; }\nif test \"${ac_cv_lib_inet_main+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-linet  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\nreturn main ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_inet_main=yes\nelse\n  ac_cv_lib_inet_main=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main\" >&5\n$as_echo \"$ac_cv_lib_inet_main\" >&6; }\nif test \"x$ac_cv_lib_inet_main\" = x\"\"yes; then :\n  LIBS=\"$LIBS -linet\"\nfi\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"net/errno.h\" \"ac_cv_header_net_errno_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_net_errno_h\" = x\"\"yes; then :\n\n\n$as_echo \"#define HAVE_NET_ERRNO_H 1\" >>confdefs.h\n\nfi\n\n\n\n    #--------------------------------------------------------------------\n    #\tCheck for the existence of the -lsocket and -lnsl libraries.\n    #\tThe order here is important, so that they end up in the right\n    #\torder in the command line generated by make.  Here are some\n    #\tspecial considerations:\n    #\t1. Use \"connect\" and \"accept\" to check for -lsocket, and\n    #\t   \"gethostbyname\" to check for -lnsl.\n    #\t2. Use each function name only once:  can't redo a check because\n    #\t   autoconf caches the results of the last check and won't redo it.\n    #\t3. Use -lnsl and -lsocket only if they supply procedures that\n    #\t   aren't already present in the normal libraries.  This is because\n    #\t   IRIX 5.2 has libraries, but they aren't needed and they're\n    #\t   bogus:  they goof up name resolution if used.\n    #\t4. On some SVR4 systems, can't use -lsocket without -lnsl too.\n    #\t   To get around this problem, check for both libraries together\n    #\t   if -lsocket doesn't work by itself.\n    #--------------------------------------------------------------------\n\n    tcl_checkBoth=0\n    ac_fn_c_check_func \"$LINENO\" \"connect\" \"ac_cv_func_connect\"\nif test \"x$ac_cv_func_connect\" = x\"\"yes; then :\n  tcl_checkSocket=0\nelse\n  tcl_checkSocket=1\nfi\n\n    if test \"$tcl_checkSocket\" = 1; then\n\tac_fn_c_check_func \"$LINENO\" \"setsockopt\" \"ac_cv_func_setsockopt\"\nif test \"x$ac_cv_func_setsockopt\" = x\"\"yes; then :\n\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket\" >&5\n$as_echo_n \"checking for setsockopt in -lsocket... \" >&6; }\nif test \"${ac_cv_lib_socket_setsockopt+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lsocket  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar setsockopt ();\nint\nmain ()\n{\nreturn setsockopt ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_socket_setsockopt=yes\nelse\n  ac_cv_lib_socket_setsockopt=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt\" >&5\n$as_echo \"$ac_cv_lib_socket_setsockopt\" >&6; }\nif test \"x$ac_cv_lib_socket_setsockopt\" = x\"\"yes; then :\n  LIBS=\"$LIBS -lsocket\"\nelse\n  tcl_checkBoth=1\nfi\n\nfi\n\n    fi\n    if test \"$tcl_checkBoth\" = 1; then\n\ttk_oldLibs=$LIBS\n\tLIBS=\"$LIBS -lsocket -lnsl\"\n\tac_fn_c_check_func \"$LINENO\" \"accept\" \"ac_cv_func_accept\"\nif test \"x$ac_cv_func_accept\" = x\"\"yes; then :\n  tcl_checkNsl=0\nelse\n  LIBS=$tk_oldLibs\nfi\n\n    fi\n    ac_fn_c_check_func \"$LINENO\" \"gethostbyname\" \"ac_cv_func_gethostbyname\"\nif test \"x$ac_cv_func_gethostbyname\" = x\"\"yes; then :\n\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl\" >&5\n$as_echo_n \"checking for gethostbyname in -lnsl... \" >&6; }\nif test \"${ac_cv_lib_nsl_gethostbyname+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lnsl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar gethostbyname ();\nint\nmain ()\n{\nreturn gethostbyname ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_nsl_gethostbyname=yes\nelse\n  ac_cv_lib_nsl_gethostbyname=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname\" >&5\n$as_echo \"$ac_cv_lib_nsl_gethostbyname\" >&6; }\nif test \"x$ac_cv_lib_nsl_gethostbyname\" = x\"\"yes; then :\n  LIBS=\"$LIBS -lnsl\"\nfi\n\nfi\n\n\n    # TEA specific: Don't perform the eval of the libraries here because\n    # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS\n\n    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'\n\n\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking dirent.h\" >&5\n$as_echo_n \"checking dirent.h... \" >&6; }\nif test \"${tcl_cv_dirent_h+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n#include <dirent.h>\nint\nmain ()\n{\n\n#ifndef _POSIX_SOURCE\n#   ifdef __Lynx__\n\t/*\n\t * Generate compilation error to make the test fail:  Lynx headers\n\t * are only valid if really in the POSIX environment.\n\t */\n\n\tmissing_procedure();\n#   endif\n#endif\nDIR *d;\nstruct dirent *entryPtr;\nchar *p;\nd = opendir(\"foobar\");\nentryPtr = readdir(d);\np = entryPtr->d_name;\nclosedir(d);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_dirent_h=yes\nelse\n  tcl_cv_dirent_h=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h\" >&5\n$as_echo \"$tcl_cv_dirent_h\" >&6; }\n\n    if test $tcl_cv_dirent_h = no; then\n\n$as_echo \"#define NO_DIRENT_H 1\" >>confdefs.h\n\n    fi\n\n    # TEA specific:\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"errno.h\" \"ac_cv_header_errno_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_errno_h\" = x\"\"yes; then :\n\nelse\n\n$as_echo \"#define NO_ERRNO_H 1\" >>confdefs.h\n\nfi\n\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"float.h\" \"ac_cv_header_float_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_float_h\" = x\"\"yes; then :\n\nelse\n\n$as_echo \"#define NO_FLOAT_H 1\" >>confdefs.h\n\nfi\n\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"values.h\" \"ac_cv_header_values_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_values_h\" = x\"\"yes; then :\n\nelse\n\n$as_echo \"#define NO_VALUES_H 1\" >>confdefs.h\n\nfi\n\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"limits.h\" \"ac_cv_header_limits_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_limits_h\" = x\"\"yes; then :\n\n$as_echo \"#define HAVE_LIMITS_H 1\" >>confdefs.h\n\nelse\n\n$as_echo \"#define NO_LIMITS_H 1\" >>confdefs.h\n\nfi\n\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"stdlib.h\" \"ac_cv_header_stdlib_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_stdlib_h\" = x\"\"yes; then :\n  tcl_ok=1\nelse\n  tcl_ok=0\nfi\n\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"strtol\" >/dev/null 2>&1; then :\n\nelse\n  tcl_ok=0\nfi\nrm -f conftest*\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"strtoul\" >/dev/null 2>&1; then :\n\nelse\n  tcl_ok=0\nfi\nrm -f conftest*\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"strtod\" >/dev/null 2>&1; then :\n\nelse\n  tcl_ok=0\nfi\nrm -f conftest*\n\n    if test $tcl_ok = 0; then\n\n$as_echo \"#define NO_STDLIB_H 1\" >>confdefs.h\n\n    fi\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"string.h\" \"ac_cv_header_string_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_string_h\" = x\"\"yes; then :\n  tcl_ok=1\nelse\n  tcl_ok=0\nfi\n\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"strstr\" >/dev/null 2>&1; then :\n\nelse\n  tcl_ok=0\nfi\nrm -f conftest*\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"strerror\" >/dev/null 2>&1; then :\n\nelse\n  tcl_ok=0\nfi\nrm -f conftest*\n\n\n    # See also memmove check below for a place where NO_STRING_H can be\n    # set and why.\n\n    if test $tcl_ok = 0; then\n\n$as_echo \"#define NO_STRING_H 1\" >>confdefs.h\n\n    fi\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"sys/wait.h\" \"ac_cv_header_sys_wait_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_sys_wait_h\" = x\"\"yes; then :\n\nelse\n\n$as_echo \"#define NO_SYS_WAIT_H 1\" >>confdefs.h\n\nfi\n\n\n    ac_fn_c_check_header_mongrel \"$LINENO\" \"dlfcn.h\" \"ac_cv_header_dlfcn_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_dlfcn_h\" = x\"\"yes; then :\n\nelse\n\n$as_echo \"#define NO_DLFCN_H 1\" >>confdefs.h\n\nfi\n\n\n\n    # OS/390 lacks sys/param.h (and doesn't need it, by chance).\n    for ac_header in sys/param.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"sys/param.h\" \"ac_cv_header_sys_param_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_sys_param_h\" = x\"\"yes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_SYS_PARAM_H 1\n_ACEOF\n\nfi\n\ndone\n\n\n\t# Let the user call this, because if it triggers, they will\n\t# need a compat/strtod.c that is correct.  Users can also\n\t# use Tcl_GetDouble(FromObj) instead.\n\t#TEA_BUGGY_STRTOD\n    fi\n\n\n#-----------------------------------------------------------------------\n# __CHANGE__\n# Specify the C source files to compile in TEA_ADD_SOURCES,\n# public headers that need to be installed in TEA_ADD_HEADERS,\n# stub library C source files to compile in TEA_ADD_STUB_SOURCES,\n# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.\n# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS\n# and PKG_TCL_SOURCES.\n#-----------------------------------------------------------------------\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to link with stubs library\" >&5\n$as_echo_n \"checking whether to link with stubs library... \" >&6; }\n    # Check whether --enable-stubs was given.\nif test \"${enable_stubs+set}\" = set; then :\n  enableval=$enable_stubs; tcl_ok=$enableval\nelse\n  tcl_ok=yes\nfi\n\n\n    if test \"${enable_stubs+set}\" = set; then\n\tenableval=\"$enable_stubs\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: stubs\" >&5\n$as_echo \"stubs\" >&6; }\n\tUSE_STUBS=1\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: no stubs\" >&5\n$as_echo \"no stubs\" >&6; }\n\tUSE_STUBS=0\n    fi\n\n\n\n    vars=\"togl.c toglProcAddr.c toglStubInit.c\"\n    for i in $vars; do\n\tcase $i in\n\t    \\$*)\n\t\t# allow $-var names\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $i\"\n\t\t;;\n\t    *)\n\t\t# check for existence - allows for generic/win/unix VPATH\n\t\t# To add more dirs here (like 'src'), you have to update VPATH\n\t\t# in Makefile.in as well\n\t\tif test ! -f \"${srcdir}/$i\" -a ! -f \"${srcdir}/generic/$i\" \\\n\t\t    -a ! -f \"${srcdir}/win/$i\" -a ! -f \"${srcdir}/unix/$i\" \\\n\t\t    ; then\n\t\t    as_fn_error \"could not find source file '$i'\" \"$LINENO\" 5\n\t\tfi\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\t# this assumes it is in a VPATH dir\n\t\ti=`basename $i`\n\t\t# handle user calling this before or after TEA_SETUP_COMPILER\n\t\tif test x\"${OBJEXT}\" != x ; then\n\t\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.${OBJEXT}\"\n\t\telse\n\t\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.\\${OBJEXT}\"\n\t\tfi\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $j\"\n\t\t;;\n\tesac\n    done\n\n\n\n# togl_ws.h is added in Makefile.in because it is generated\n\n    vars=\"togl.h toglDecls.h\"\n    for i in $vars; do\n\t# check for existence, be strict because it is installed\n\tif test ! -f \"${srcdir}/$i\" ; then\n\t    as_fn_error \"could not find header file '${srcdir}/$i'\" \"$LINENO\" 5\n\tfi\n\tPKG_HEADERS=\"$PKG_HEADERS $i\"\n    done\n\n\n\n    vars=\"\"\n    for i in $vars; do\n\tPKG_INCLUDES=\"$PKG_INCLUDES $i\"\n    done\n\n\n\n    vars=\"\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\n    PKG_CFLAGS=\"$PKG_CFLAGS \"\n\n\nif test \"${USE_STUBS}\" = \"1\" ; then\n\n    vars=\"toglStubLib.c\"\n    for i in $vars; do\n\t# check for existence - allows for generic/win/unix VPATH\n\tif test ! -f \"${srcdir}/$i\" -a ! -f \"${srcdir}/generic/$i\" \\\n\t    -a ! -f \"${srcdir}/win/$i\" -a ! -f \"${srcdir}/unix/$i\" \\\n\t    ; then\n\t    as_fn_error \"could not find stub source file '$i'\" \"$LINENO\" 5\n\tfi\n\tPKG_STUB_SOURCES=\"$PKG_STUB_SOURCES $i\"\n\t# this assumes it is in a VPATH dir\n\ti=`basename $i`\n\t# handle user calling this before or after TEA_SETUP_COMPILER\n\tif test x\"${OBJEXT}\" != x ; then\n\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.${OBJEXT}\"\n\telse\n\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.\\${OBJEXT}\"\n\tfi\n\tPKG_STUB_OBJECTS=\"$PKG_STUB_OBJECTS $j\"\n    done\n\n\n\nfi\n\n    vars=\"\"\n    for i in $vars; do\n\t# check for existence, be strict because it is installed\n\tif test ! -f \"${srcdir}/$i\" ; then\n\t    as_fn_error \"could not find tcl source file '${srcdir}/$i'\" \"$LINENO\" 5\n\tfi\n\tPKG_TCL_SOURCES=\"$PKG_TCL_SOURCES $i\"\n    done\n\n\n\n#--------------------------------------------------------------------\n# __CHANGE__\n# A few miscellaneous platform-specific items:\n#\n# Define a special symbol for Windows (BUILD_sample in this case) so\n# that we create the export library with the dll.\n#\n# Windows creates a few extra files that need to be cleaned up.\n# You can add more files to clean if your extension creates any extra\n# files.\n#\n# TEA_ADD_* any platform specific compiler/build info here.\n#--------------------------------------------------------------------\n\n# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure\n# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.\n#CLEANFILES=\"pkgIndex.tcl\"\nif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\n$as_echo \"#define BUILD_togl 1\" >>confdefs.h\n\n    CLEANFILES=\"$CLEANFILES *.lib *.dll *.exp *.ilk *.pdb vc*.pch *.manifest\"\n    #TEA_ADD_SOURCES([win/winFile.c])\n    #TEA_ADD_INCLUDES([-I\\\"$(${CYGPATH} ${srcdir}/win)\\\"])\nelse\n    # Ensure no empty else clauses\n    :\n    CLEANFILES=\"so_locations\"\n    #TEA_ADD_SOURCES([unix/unixFile.c])\n    #TEA_ADD_LIBS([-lsuperfly])\nfi\n\n\n#--------------------------------------------------------------------\n# __CHANGE__\n# Choose which headers you need.  Extension authors should try very\n# hard to only rely on the Tcl public header files.  Internal headers\n# contain private data structures and are subject to change without\n# notice.\n# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG\n#--------------------------------------------------------------------\n\n# find Tcl, Tk, and X11 headers\n#TEA_PUBLIC_TCL_HEADERS\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tcl public headers\" >&5\n$as_echo_n \"checking for Tcl public headers... \" >&6; }\n\n\n# Check whether --with-tclinclude was given.\nif test \"${with_tclinclude+set}\" = set; then :\n  withval=$with_tclinclude; with_tclinclude=${withval}\nfi\n\n\n    if test \"${ac_cv_c_tclh+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t# Use the value from --with-tclinclude, if it was given\n\n\tif test x\"${with_tclinclude}\" != x ; then\n\t    if test -f \"${with_tclinclude}/tcl.h\" ; then\n\t\tac_cv_c_tclh=${with_tclinclude}\n\t    else\n\t\tas_fn_error \"${with_tclinclude} directory does not contain tcl.h\" \"$LINENO\" 5\n\t    fi\n\telse\n\t    if test \"`uname -s`\" = \"Darwin\"; then\n\t\t# If Tcl was built as a framework, attempt to use\n\t\t# the framework's Headers directory\n\t\tcase ${TCL_DEFS} in\n\t\t    *TCL_FRAMEWORK*)\n\t\t\tlist=\"`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`\"\n\t\t\t;;\n\t\tesac\n\t    fi\n\n\t    # Look in the source dir only if Tcl is not installed,\n\t    # and in that situation, look there before installed locations.\n\t    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n\t\tlist=\"$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`\"\n\t    fi\n\n\t    # Check order: pkg --prefix location, Tcl's --prefix location,\n\t    # relative to directory of tclConfig.sh.\n\n\t    eval \"temp_includedir=${includedir}\"\n\t    list=\"$list \\\n\t\t`ls -d ${temp_includedir}        2>/dev/null` \\\n\t\t`ls -d ${TCL_PREFIX}/include     2>/dev/null` \\\n\t\t`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`\"\n\t    if test \"${TEA_PLATFORM}\" != \"windows\" -o \"$GCC\" = \"yes\"; then\n\t\tlist=\"$list /usr/local/include /usr/include\"\n\t\tif test x\"${TCL_INCLUDE_SPEC}\" != x ; then\n\t\t    d=`echo \"${TCL_INCLUDE_SPEC}\" | sed -e 's/^-I//'`\n\t\t    list=\"$list `ls -d ${d} 2>/dev/null`\"\n\t\tfi\n\t    fi\n\t    for i in $list ; do\n\t\tif test -f \"$i/tcl.h\" ; then\n\t\t    ac_cv_c_tclh=$i\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n\nfi\n\n\n    # Print a message based on how we determined the include path\n\n    if test x\"${ac_cv_c_tclh}\" = x ; then\n\tas_fn_error \"tcl.h not found.  Please specify its location with --with-tclinclude\" \"$LINENO\" 5\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}\" >&5\n$as_echo \"${ac_cv_c_tclh}\" >&6; }\n    fi\n\n    # Convert to a native path and substitute into the output files.\n\n    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`\n\n    TCL_INCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\n\n\n\n    # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tcl private include files\" >&5\n$as_echo_n \"checking for Tcl private include files... \" >&6; }\n\n    TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`\n    TCL_TOP_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}\\\"\n\n    # Check to see if tcl<Plat>Port.h isn't already with the public headers\n    # Don't look for tclInt.h because that resides with tcl.h in the core\n    # sources, but the <plat>Port headers are in a different directory\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \\\n\t-f \"${ac_cv_c_tclh}/tclWinPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    elif test \"${TEA_PLATFORM}\" = \"unix\" -a \\\n\t-f \"${ac_cv_c_tclh}/tclUnixPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    else\n\tTCL_GENERIC_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/generic\\\"\n\tif test \"${TEA_PLATFORM}\" = \"windows\"; then\n\t    TCL_PLATFORM_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/win\\\"\n\telse\n\t    TCL_PLATFORM_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/unix\\\"\n\tfi\n\t# Overwrite the previous TCL_INCLUDES as this should capture both\n\t# public and private headers in the same set.\n\t# We want to ensure these are substituted so as not to require\n\t# any *_NATIVE vars be defined in the Makefile\n\tTCL_INCLUDES=\"-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}\"\n\tif test \"`uname -s`\" = \"Darwin\"; then\n            # If Tcl was built as a framework, attempt to use\n            # the framework's Headers and PrivateHeaders directories\n            case ${TCL_DEFS} in\n\t    \t*TCL_FRAMEWORK*)\n\t\t    if test -d \"${TCL_BIN_DIR}/Headers\" -a \\\n\t\t\t    -d \"${TCL_BIN_DIR}/PrivateHeaders\"; then\n\t\t\tTCL_INCLUDES=\"-I\\\"${TCL_BIN_DIR}/Headers\\\" -I\\\"${TCL_BIN_DIR}/PrivateHeaders\\\" ${TCL_INCLUDES}\"\n\t\t    else\n\t\t\tTCL_INCLUDES=\"${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo \"${TCL_INCLUDE_SPEC}\" | sed -e 's/Headers/PrivateHeaders/'`\"\n\t\t    fi\n\t            ;;\n\t    esac\n\t    result=\"Using ${TCL_INCLUDES}\"\n\telse\n\t    if test ! -f \"${TCL_SRC_DIR}/generic/tclInt.h\" ; then\n\t\tas_fn_error \"Cannot find private header tclInt.h in ${TCL_SRC_DIR}\" \"$LINENO\" 5\n\t    fi\n\t    result=\"Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}\"\n\tfi\n    fi\n\n\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${result}\" >&5\n$as_echo \"${result}\" >&6; }\n\n\n#TEA_PUBLIC_TK_HEADERS\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tk public headers\" >&5\n$as_echo_n \"checking for Tk public headers... \" >&6; }\n\n\n# Check whether --with-tkinclude was given.\nif test \"${with_tkinclude+set}\" = set; then :\n  withval=$with_tkinclude; with_tkinclude=${withval}\nfi\n\n\n    if test \"${ac_cv_c_tkh+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t# Use the value from --with-tkinclude, if it was given\n\n\tif test x\"${with_tkinclude}\" != x ; then\n\t    if test -f \"${with_tkinclude}/tk.h\" ; then\n\t\tac_cv_c_tkh=${with_tkinclude}\n\t    else\n\t\tas_fn_error \"${with_tkinclude} directory does not contain tk.h\" \"$LINENO\" 5\n\t    fi\n\telse\n\t    if test \"`uname -s`\" = \"Darwin\"; then\n\t\t# If Tk was built as a framework, attempt to use\n\t\t# the framework's Headers directory.\n\t\tcase ${TK_DEFS} in\n\t\t    *TK_FRAMEWORK*)\n\t\t\tlist=\"`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`\"\n\t\t\t;;\n\t\tesac\n\t    fi\n\n\t    # Look in the source dir only if Tk is not installed,\n\t    # and in that situation, look there before installed locations.\n\t    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n\t\tlist=\"$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`\"\n\t    fi\n\n\t    # Check order: pkg --prefix location, Tk's --prefix location,\n\t    # relative to directory of tkConfig.sh, Tcl's --prefix location,\n\t    # relative to directory of tclConfig.sh.\n\n\t    eval \"temp_includedir=${includedir}\"\n\t    list=\"$list \\\n\t\t`ls -d ${temp_includedir}        2>/dev/null` \\\n\t\t`ls -d ${TK_PREFIX}/include      2>/dev/null` \\\n\t\t`ls -d ${TK_BIN_DIR}/../include  2>/dev/null` \\\n\t\t`ls -d ${TCL_PREFIX}/include     2>/dev/null` \\\n\t\t`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`\"\n\t    if test \"${TEA_PLATFORM}\" != \"windows\" -o \"$GCC\" = \"yes\"; then\n\t\tlist=\"$list /usr/local/include /usr/include\"\n\t    fi\n\t    for i in $list ; do\n\t\tif test -f \"$i/tk.h\" ; then\n\t\t    ac_cv_c_tkh=$i\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n\nfi\n\n\n    # Print a message based on how we determined the include path\n\n    if test x\"${ac_cv_c_tkh}\" = x ; then\n\tas_fn_error \"tk.h not found.  Please specify its location with --with-tkinclude\" \"$LINENO\" 5\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tkh}\" >&5\n$as_echo \"${ac_cv_c_tkh}\" >&6; }\n    fi\n\n    # Convert to a native path and substitute into the output files.\n\n    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`\n\n    TK_INCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\n\n\n    if test \"${TEA_WINDOWINGSYSTEM}\" != \"x11\"; then\n\t# On Windows and Aqua, we need the X compat headers\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for X11 header files\" >&5\n$as_echo_n \"checking for X11 header files... \" >&6; }\n\tif test ! -r \"${INCLUDE_DIR_NATIVE}/X11/Xlib.h\"; then\n\t    INCLUDE_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/xlib`\"\n\t    TK_XINCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\n\tfi\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${INCLUDE_DIR_NATIVE}\" >&5\n$as_echo \"${INCLUDE_DIR_NATIVE}\" >&6; }\n    fi\n\n\n    # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Tk private include files\" >&5\n$as_echo_n \"checking for Tk private include files... \" >&6; }\n\n    TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`\n    TK_TOP_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}\\\"\n\n    # Check to see if tk<Plat>Port.h isn't already with the public headers\n    # Don't look for tkInt.h because that resides with tk.h in the core\n    # sources, but the <plat>Port headers are in a different directory\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \\\n\t-f \"${ac_cv_c_tkh}/tkWinPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    elif test \"${TEA_PLATFORM}\" = \"unix\" -a \\\n\t-f \"${ac_cv_c_tkh}/tkUnixPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    else\n\tTK_GENERIC_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/generic\\\"\n\tTK_XLIB_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/xlib\\\"\n\tif test \"${TEA_PLATFORM}\" = \"windows\"; then\n\t    TK_PLATFORM_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/win\\\"\n\telse\n\t    TK_PLATFORM_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/unix\\\"\n\tfi\n\t# Overwrite the previous TK_INCLUDES as this should capture both\n\t# public and private headers in the same set.\n\t# We want to ensure these are substituted so as not to require\n\t# any *_NATIVE vars be defined in the Makefile\n\tTK_INCLUDES=\"-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}\"\n\t# Detect and add ttk subdir\n\tif test -d \"${TK_SRC_DIR}/generic/ttk\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I\\\"${TK_SRC_DIR_NATIVE}/generic/ttk\\\"\"\n\tfi\n\tif test \"${TEA_WINDOWINGSYSTEM}\" != \"x11\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I${TK_XLIB_DIR_NATIVE}\"\n\tfi\n\tif test \"${TEA_WINDOWINGSYSTEM}\" = \"aqua\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I\\\"${TK_SRC_DIR_NATIVE}/macosx\\\"\"\n\tfi\n\tif test \"`uname -s`\" = \"Darwin\"; then\n\t    # If Tk was built as a framework, attempt to use\n\t    # the framework's Headers and PrivateHeaders directories\n\t    case ${TK_DEFS} in\n\t\t*TK_FRAMEWORK*)\n\t\t\tif test -d \"${TK_BIN_DIR}/Headers\" -a \\\n\t\t\t\t-d \"${TK_BIN_DIR}/PrivateHeaders\"; then\n\t\t\t    TK_INCLUDES=\"-I\\\"${TK_BIN_DIR}/Headers\\\" -I\\\"${TK_BIN_DIR}/PrivateHeaders\\\" ${TK_INCLUDES}\"\n\t\t\telse\n\t\t\t    TK_INCLUDES=\"${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo \"${TK_INCLUDE_SPEC}\" | sed -e 's/Headers/PrivateHeaders/'`\"\n\t\t\tfi\n\t\t\t;;\n\t    esac\n\t    result=\"Using ${TK_INCLUDES}\"\n\telse\n\t    if test ! -f \"${TK_SRC_DIR}/generic/tkInt.h\" ; then\n\t       as_fn_error \"Cannot find private header tkInt.h in ${TK_SRC_DIR}\" \"$LINENO\" 5\n\t    fi\n\t    result=\"Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}\"\n\tfi\n    fi\n\n\n\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${result}\" >&5\n$as_echo \"${result}\" >&6; }\n\n\n    if test \"${TEA_WINDOWINGSYSTEM}\" = \"x11\" ; then\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for X\" >&5\n$as_echo_n \"checking for X... \" >&6; }\n\n\n# Check whether --with-x was given.\nif test \"${with_x+set}\" = set; then :\n  withval=$with_x;\nfi\n\n# $have_x is `yes', `no', `disabled', or empty when we do not yet know.\nif test \"x$with_x\" = xno; then\n  # The user explicitly disabled X.\n  have_x=disabled\nelse\n  case $x_includes,$x_libraries in #(\n    *\\'*) as_fn_error \"cannot use X directory names containing '\" \"$LINENO\" 5;; #(\n    *,NONE | NONE,*) if test \"${ac_cv_have_x+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  # One or both of the vars are not set, and there is no cached value.\nac_x_includes=no ac_x_libraries=no\nrm -f -r conftest.dir\nif mkdir conftest.dir; then\n  cd conftest.dir\n  cat >Imakefile <<'_ACEOF'\nincroot:\n\t@echo incroot='${INCROOT}'\nusrlibdir:\n\t@echo usrlibdir='${USRLIBDIR}'\nlibdir:\n\t@echo libdir='${LIBDIR}'\n_ACEOF\n  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then\n    # GNU make sometimes prints \"make[1]: Entering...\", which would confuse us.\n    for ac_var in incroot usrlibdir libdir; do\n      eval \"ac_im_$ac_var=\\`\\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\\`\"\n    done\n    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.\n    for ac_extension in a so sl dylib la dll; do\n      if test ! -f \"$ac_im_usrlibdir/libX11.$ac_extension\" &&\n\t test -f \"$ac_im_libdir/libX11.$ac_extension\"; then\n\tac_im_usrlibdir=$ac_im_libdir; break\n      fi\n    done\n    # Screen out bogus values from the imake configuration.  They are\n    # bogus both because they are the default anyway, and because\n    # using them would break gcc on systems where it needs fixed includes.\n    case $ac_im_incroot in\n\t/usr/include) ac_x_includes= ;;\n\t*) test -f \"$ac_im_incroot/X11/Xos.h\" && ac_x_includes=$ac_im_incroot;;\n    esac\n    case $ac_im_usrlibdir in\n\t/usr/lib | /usr/lib64 | /lib | /lib64) ;;\n\t*) test -d \"$ac_im_usrlibdir\" && ac_x_libraries=$ac_im_usrlibdir ;;\n    esac\n  fi\n  cd ..\n  rm -f -r conftest.dir\nfi\n\n# Standard set of common directories for X headers.\n# Check X11 before X11Rn because it is often a symlink to the current release.\nac_x_header_dirs='\n/usr/X11/include\n/usr/X11R7/include\n/usr/X11R6/include\n/usr/X11R5/include\n/usr/X11R4/include\n\n/usr/include/X11\n/usr/include/X11R7\n/usr/include/X11R6\n/usr/include/X11R5\n/usr/include/X11R4\n\n/usr/local/X11/include\n/usr/local/X11R7/include\n/usr/local/X11R6/include\n/usr/local/X11R5/include\n/usr/local/X11R4/include\n\n/usr/local/include/X11\n/usr/local/include/X11R7\n/usr/local/include/X11R6\n/usr/local/include/X11R5\n/usr/local/include/X11R4\n\n/usr/X386/include\n/usr/x386/include\n/usr/XFree86/include/X11\n\n/usr/include\n/usr/local/include\n/usr/unsupported/include\n/usr/athena/include\n/usr/local/x11r5/include\n/usr/lpp/Xamples/include\n\n/usr/openwin/include\n/usr/openwin/share/include'\n\nif test \"$ac_x_includes\" = no; then\n  # Guess where to find include files, by looking for Xlib.h.\n  # First, try using that file with no special directory specified.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # We can compile using X headers with no special include directory.\nac_x_includes=\nelse\n  for ac_dir in $ac_x_header_dirs; do\n  if test -r \"$ac_dir/X11/Xlib.h\"; then\n    ac_x_includes=$ac_dir\n    break\n  fi\ndone\nfi\nrm -f conftest.err conftest.$ac_ext\nfi # $ac_x_includes = no\n\nif test \"$ac_x_libraries\" = no; then\n  # Check for the libraries.\n  # See if we find them without any special options.\n  # Don't add to $LIBS permanently.\n  ac_save_LIBS=$LIBS\n  LIBS=\"-lX11 $LIBS\"\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\nint\nmain ()\n{\nXrmInitialize ()\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  LIBS=$ac_save_LIBS\n# We can link X programs with no special library path.\nac_x_libraries=\nelse\n  LIBS=$ac_save_LIBS\nfor ac_dir in `$as_echo \"$ac_x_includes $ac_x_header_dirs\" | sed s/include/lib/g`\ndo\n  # Don't even attempt the hair of trying to link an X program!\n  for ac_extension in a so sl dylib la dll; do\n    if test -r \"$ac_dir/libX11.$ac_extension\"; then\n      ac_x_libraries=$ac_dir\n      break 2\n    fi\n  done\ndone\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi # $ac_x_libraries = no\n\ncase $ac_x_includes,$ac_x_libraries in #(\n  no,* | *,no | *\\'*)\n    # Didn't find X, or a directory has \"'\" in its name.\n    ac_cv_have_x=\"have_x=no\";; #(\n  *)\n    # Record where we found X for the cache.\n    ac_cv_have_x=\"have_x=yes\\\n\tac_x_includes='$ac_x_includes'\\\n\tac_x_libraries='$ac_x_libraries'\"\nesac\nfi\n;; #(\n    *) have_x=yes;;\n  esac\n  eval \"$ac_cv_have_x\"\nfi # $with_x != no\n\nif test \"$have_x\" != yes; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $have_x\" >&5\n$as_echo \"$have_x\" >&6; }\n  no_x=yes\nelse\n  # If each of the values was on the command line, it overrides each guess.\n  test \"x$x_includes\" = xNONE && x_includes=$ac_x_includes\n  test \"x$x_libraries\" = xNONE && x_libraries=$ac_x_libraries\n  # Update the cache value to reflect the command line values.\n  ac_cv_have_x=\"have_x=yes\\\n\tac_x_includes='$x_includes'\\\n\tac_x_libraries='$x_libraries'\"\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes\" >&5\n$as_echo \"libraries $x_libraries, headers $x_includes\" >&6; }\nfi\n\n    not_really_there=\"\"\n    if test \"$no_x\" = \"\"; then\n\tif test \"$x_includes\" = \"\"; then\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/XIntrinsic.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  not_really_there=\"yes\"\nfi\nrm -f conftest.err conftest.$ac_ext\n\telse\n\t    if test ! -r $x_includes/X11/Intrinsic.h; then\n\t\tnot_really_there=\"yes\"\n\t    fi\n\tfi\n    fi\n    if test \"$no_x\" = \"yes\" -o \"$not_really_there\" = \"yes\"; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for X11 header files\" >&5\n$as_echo_n \"checking for X11 header files... \" >&6; }\n\tfound_xincludes=\"no\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Intrinsic.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  found_xincludes=\"yes\"\nelse\n  found_xincludes=\"no\"\nfi\nrm -f conftest.err conftest.$ac_ext\n\tif test \"$found_xincludes\" = \"no\"; then\n\t    dirs=\"/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include\"\n\t    for i in $dirs ; do\n\t\tif test -r $i/X11/Intrinsic.h; then\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $i\" >&5\n$as_echo \"$i\" >&6; }\n\t\t    XINCLUDES=\" -I$i\"\n\t\t    found_xincludes=\"yes\"\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    else\n\tif test \"$x_includes\" != \"\"; then\n\t    XINCLUDES=\"-I$x_includes\"\n\t    found_xincludes=\"yes\"\n\tfi\n    fi\n    if test found_xincludes = \"no\"; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: couldn't find any!\" >&5\n$as_echo \"couldn't find any!\" >&6; }\n    fi\n\n    if test \"$no_x\" = yes; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for X11 libraries\" >&5\n$as_echo_n \"checking for X11 libraries... \" >&6; }\n\tXLIBSW=nope\n\tdirs=\"/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib\"\n\tfor i in $dirs ; do\n\t    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $i\" >&5\n$as_echo \"$i\" >&6; }\n\t\tXLIBSW=\"-L$i -lX11\"\n\t\tx_libraries=\"$i\"\n\t\tbreak\n\t    fi\n\tdone\n    else\n\tif test \"$x_libraries\" = \"\"; then\n\t    XLIBSW=-lX11\n\telse\n\t    XLIBSW=\"-L$x_libraries -lX11\"\n\tfi\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for XCreateWindow in -lXwindow\" >&5\n$as_echo_n \"checking for XCreateWindow in -lXwindow... \" >&6; }\nif test \"${ac_cv_lib_Xwindow_XCreateWindow+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXwindow  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XCreateWindow ();\nint\nmain ()\n{\nreturn XCreateWindow ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_Xwindow_XCreateWindow=yes\nelse\n  ac_cv_lib_Xwindow_XCreateWindow=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xwindow_XCreateWindow\" >&5\n$as_echo \"$ac_cv_lib_Xwindow_XCreateWindow\" >&6; }\nif test \"x$ac_cv_lib_Xwindow_XCreateWindow\" = x\"\"yes; then :\n  XLIBSW=-lXwindow\nfi\n\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: could not find any!  Using -lX11.\" >&5\n$as_echo \"could not find any!  Using -lX11.\" >&6; }\n\tXLIBSW=-lX11\n    fi\n    # TEA specific:\n    if test x\"${XLIBSW}\" != x ; then\n\tPKG_LIBS=\"${PKG_LIBS} ${XLIBSW}\"\n    fi\n\n    fi\n\n\n# find autostereo header, lib, and daemon\n\n# Check whether --with-autostereo was given.\nif test \"${with_autostereo+set}\" = set; then :\n  withval=$with_autostereo; with_autostereo=${withval}\nfi\n\n\n# Check whether --with-autostereod was given.\nif test \"${with_autostereod+set}\" = set; then :\n  withval=$with_autostereod; with_autostereod=${withval}\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for autostereo directory\" >&5\n$as_echo_n \"checking for autostereo directory... \" >&6; }\nif test x\"${with_autostereo}\" != x ; then\n\tif test -f \"${with_autostereo}/lib/autostereo.h\" ; then\n\t\twith_autostereo=`(cd ${with_autostereo}; pwd)`\n\n    vars=\"-I${with_autostereo}/lib\"\n    for i in $vars; do\n\tPKG_INCLUDES=\"$PKG_INCLUDES $i\"\n    done\n\n\n\n    vars=\"-L${with_autostereo}/lib -lautostereo\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define HAVE_AUTOSTEREO 1\n_ACEOF\n\n\telse\n\t\tas_fn_error \"${with_autostereo} directory doesn't contain lib/autostereo.h\" \"$LINENO\" 5\n\tfi\nfi\n\n# Extract the first word of \"autostereod\", so it can be a program name with args.\nset dummy autostereod; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_path_AUTOSTEREOD+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $AUTOSTEREOD in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_AUTOSTEREOD=\"$AUTOSTEREOD\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_dummy=\"`eval \\\"echo $sbindir\\\"`:$PATH:/sbin:/usr/sbin\"\nfor as_dir in $as_dummy\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_path_AUTOSTEREOD=\"$as_dir/$ac_word$ac_exec_ext\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  ;;\nesac\nfi\nAUTOSTEREOD=$ac_cv_path_AUTOSTEREOD\nif test -n \"$AUTOSTEREOD\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AUTOSTEREOD\" >&5\n$as_echo \"$AUTOSTEREOD\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n\n\n# Choose OpenGL platform\ncase \"${TEA_WINDOWINGSYSTEM}\" in\n\taqua)\n\t\tTOGL_WINDOWINGSYSTEM=TOGL_NSOPENGL\n\t\tCFLAGS=\"-ObjC\"\n\n\n#    vars=\"-framework AGL -framework OpenGL -framework ApplicationServices\"\n    vars=\"-framework OpenGL -framework AppKit -framework ApplicationServices\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\t\t# libGLU is implicit in OpenGL framework\n\t\tLIBGLU=\n\t\t;;\n\n\tx11)\n\t\tTOGL_WINDOWINGSYSTEM=TOGL_X11\n\n\n# Check whether --with-Xmu was given.\nif test \"${with_Xmu+set}\" = set; then :\n  withval=$with_Xmu;\nelse\n  with_Xmu=no\nfi\n\n\t\tif test \"x$with_Xmu\" != xno; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for XmuLookupStandardColormap in -lXmu\" >&5\n$as_echo_n \"checking for XmuLookupStandardColormap in -lXmu... \" >&6; }\nif test \"${ac_cv_lib_Xmu_XmuLookupStandardColormap+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXmu -lXt -lX11\n\t\t     $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XmuLookupStandardColormap ();\nint\nmain ()\n{\nreturn XmuLookupStandardColormap ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_Xmu_XmuLookupStandardColormap=yes\nelse\n  ac_cv_lib_Xmu_XmuLookupStandardColormap=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xmu_XmuLookupStandardColormap\" >&5\n$as_echo \"$ac_cv_lib_Xmu_XmuLookupStandardColormap\" >&6; }\nif test \"x$ac_cv_lib_Xmu_XmuLookupStandardColormap\" = x\"\"yes; then :\n\n    vars=\"-lXmu\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\n$as_echo \"#define USE_SYSTEM_LIBXMU 1\" >>confdefs.h\n\n\nelse\n  with_Xmu=no\nfi\n\nfi\n\t\tif test \"x$with_Xmu\" = xno; then :\n\n    vars=\"Xmu/CmapAlloc.c Xmu/CrCmap.c Xmu/DelCmap.c Xmu/LookupCmap.c Xmu/StdCmap.c\"\n    for i in $vars; do\n\tcase $i in\n\t    \\$*)\n\t\t# allow $-var names\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $i\"\n\t\t;;\n\t    *)\n\t\t# check for existence - allows for generic/win/unix VPATH\n\t\t# To add more dirs here (like 'src'), you have to update VPATH\n\t\t# in Makefile.in as well\n\t\tif test ! -f \"${srcdir}/$i\" -a ! -f \"${srcdir}/generic/$i\" \\\n\t\t    -a ! -f \"${srcdir}/win/$i\" -a ! -f \"${srcdir}/unix/$i\" \\\n\t\t    ; then\n\t\t    as_fn_error \"could not find source file '$i'\" \"$LINENO\" 5\n\t\tfi\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\t# this assumes it is in a VPATH dir\n\t\ti=`basename $i`\n\t\t# handle user calling this before or after TEA_SETUP_COMPILER\n\t\tif test x\"${OBJEXT}\" != x ; then\n\t\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.${OBJEXT}\"\n\t\telse\n\t\t    j=\"`echo $i | sed -e 's/\\.[^.]*$//'`.\\${OBJEXT}\"\n\t\tfi\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $j\"\n\t\t;;\n\tesac\n    done\n\n\n\nfi\n\n    vars=\"-lGL\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\t\tLIBGLU=-lGLU\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if GLX_GLXEXT_LEGACY interferes with including GL/glxext.h\" >&5\n$as_echo_n \"checking if GLX_GLXEXT_LEGACY interferes with including GL/glxext.h... \" >&6; }\n    ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n    ac_save_CFLAGS=$CFLAGS\n    CFLAGS=$TK_XINCLUDES\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#define GLX_GLXEXT_LEGACY\n#include <GL/glx.h>\n#undef GLX_VERSION_1_3\n#undef GLX_VERSION_1_4\n#include <GL/glxext.h>\nint main() { return 0; }\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n\t $as_echo \"#define UNDEF_GET_PROC_ADDRESS 1\" >>confdefs.h\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    CFLAGS=$ac_save_CFLAGS\n    ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\t\t;;\n\twin32)\n\t\tTOGL_WINDOWINGSYSTEM=TOGL_WGL\n\n\n    vars=\"opengl32.lib user32.lib gdi32.lib\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\t\tif test \"$GCC\" = \"yes\" ; then\n\t\t\tLIBGLU=-lglu32\n\t\telse\n\t\t\t# assume Microsoft compiler\n\t\t\tLIBGLU=glu32.lib\n\t\tfi\n\t\t;;\n\t*)\n\t\tas_fn_error \"Unsupported windowing system: ${TEA_WINDOWINGSYSTEM}\" \"$LINENO\" 5\n\t\t;;\nesac\n\n\n\n#--------------------------------------------------------------------\n# Check whether --enable-threads or --disable-threads was given.\n# This auto-enables if Tcl was compiled threaded.\n#--------------------------------------------------------------------\n\n\n    # Check whether --enable-threads was given.\nif test \"${enable_threads+set}\" = set; then :\n  enableval=$enable_threads; tcl_ok=$enableval\nelse\n  tcl_ok=yes\nfi\n\n\n    if test \"${enable_threads+set}\" = set; then\n\tenableval=\"$enable_threads\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" -o \"${TCL_THREADS}\" = 1; then\n\tTCL_THREADS=1\n\n\tif test \"${TEA_PLATFORM}\" != \"windows\" ; then\n\t    # We are always OK on Windows, so check what this platform wants:\n\n\t    # USE_THREAD_ALLOC tells us to try the special thread-based\n\t    # allocator that significantly reduces lock contention\n\n$as_echo \"#define USE_THREAD_ALLOC 1\" >>confdefs.h\n\n\n$as_echo \"#define _REENTRANT 1\" >>confdefs.h\n\n\t    if test \"`uname -s`\" = \"SunOS\" ; then\n\n$as_echo \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n\t    fi\n\n$as_echo \"#define _THREAD_SAFE 1\" >>confdefs.h\n\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread\" >&5\n$as_echo_n \"checking for pthread_mutex_init in -lpthread... \" >&6; }\nif test \"${ac_cv_lib_pthread_pthread_mutex_init+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lpthread  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_mutex_init ();\nint\nmain ()\n{\nreturn pthread_mutex_init ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_pthread_pthread_mutex_init=yes\nelse\n  ac_cv_lib_pthread_pthread_mutex_init=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init\" >&5\n$as_echo \"$ac_cv_lib_pthread_pthread_mutex_init\" >&6; }\nif test \"x$ac_cv_lib_pthread_pthread_mutex_init\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t    if test \"$tcl_ok\" = \"no\"; then\n\t\t# Check a little harder for __pthread_mutex_init in the same\n\t\t# library, as some systems hide it there until pthread.h is\n\t\t# defined.  We could alternatively do an AC_TRY_COMPILE with\n\t\t# pthread.h, but that will work with libpthread really doesn't\n\t\t# exist, like AIX 4.2.  [Bug: 4359]\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread\" >&5\n$as_echo_n \"checking for __pthread_mutex_init in -lpthread... \" >&6; }\nif test \"${ac_cv_lib_pthread___pthread_mutex_init+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lpthread  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar __pthread_mutex_init ();\nint\nmain ()\n{\nreturn __pthread_mutex_init ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_pthread___pthread_mutex_init=yes\nelse\n  ac_cv_lib_pthread___pthread_mutex_init=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init\" >&5\n$as_echo \"$ac_cv_lib_pthread___pthread_mutex_init\" >&6; }\nif test \"x$ac_cv_lib_pthread___pthread_mutex_init\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t    fi\n\n\t    if test \"$tcl_ok\" = \"yes\"; then\n\t\t# The space is needed\n\t\tTHREADS_LIBS=\" -lpthread\"\n\t    else\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads\" >&5\n$as_echo_n \"checking for pthread_mutex_init in -lpthreads... \" >&6; }\nif test \"${ac_cv_lib_pthreads_pthread_mutex_init+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lpthreads  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_mutex_init ();\nint\nmain ()\n{\nreturn pthread_mutex_init ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_pthreads_pthread_mutex_init=yes\nelse\n  ac_cv_lib_pthreads_pthread_mutex_init=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init\" >&5\n$as_echo \"$ac_cv_lib_pthreads_pthread_mutex_init\" >&6; }\nif test \"x$ac_cv_lib_pthreads_pthread_mutex_init\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t\tif test \"$tcl_ok\" = \"yes\"; then\n\t\t    # The space is needed\n\t\t    THREADS_LIBS=\" -lpthreads\"\n\t\telse\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc\" >&5\n$as_echo_n \"checking for pthread_mutex_init in -lc... \" >&6; }\nif test \"${ac_cv_lib_c_pthread_mutex_init+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lc  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_mutex_init ();\nint\nmain ()\n{\nreturn pthread_mutex_init ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_c_pthread_mutex_init=yes\nelse\n  ac_cv_lib_c_pthread_mutex_init=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init\" >&5\n$as_echo \"$ac_cv_lib_c_pthread_mutex_init\" >&6; }\nif test \"x$ac_cv_lib_c_pthread_mutex_init\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t\t    if test \"$tcl_ok\" = \"no\"; then\n\t\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r\" >&5\n$as_echo_n \"checking for pthread_mutex_init in -lc_r... \" >&6; }\nif test \"${ac_cv_lib_c_r_pthread_mutex_init+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lc_r  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_mutex_init ();\nint\nmain ()\n{\nreturn pthread_mutex_init ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_c_r_pthread_mutex_init=yes\nelse\n  ac_cv_lib_c_r_pthread_mutex_init=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init\" >&5\n$as_echo \"$ac_cv_lib_c_r_pthread_mutex_init\" >&6; }\nif test \"x$ac_cv_lib_c_r_pthread_mutex_init\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t\t\tif test \"$tcl_ok\" = \"yes\"; then\n\t\t\t    # The space is needed\n\t\t\t    THREADS_LIBS=\" -pthread\"\n\t\t\telse\n\t\t\t    TCL_THREADS=0\n\t\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled\" >&5\n$as_echo \"$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled\" >&2;}\n\t\t\tfi\n\t\t    fi\n\t\tfi\n\t    fi\n\tfi\n    else\n\tTCL_THREADS=0\n    fi\n    # Do checking message here to not mess up interleaved configure output\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for building with threads\" >&5\n$as_echo_n \"checking for building with threads... \" >&6; }\n    if test \"${TCL_THREADS}\" = 1; then\n\n$as_echo \"#define TCL_THREADS 1\" >>confdefs.h\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes (default)\" >&5\n$as_echo \"yes (default)\" >&6; }\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n    fi\n    # TCL_THREADS sanity checking.  See if our request for building with\n    # threads is the same as the way Tcl was built.  If not, warn the user.\n    case ${TCL_DEFS} in\n\t*THREADS=1*)\n\t    if test \"${TCL_THREADS}\" = \"0\"; then\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING:\n    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl\n    that IS thread-enabled.  It is recommended to use --enable-threads.\" >&5\n$as_echo \"$as_me: WARNING:\n    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl\n    that IS thread-enabled.  It is recommended to use --enable-threads.\" >&2;}\n\t    fi\n\t    ;;\n\t*)\n\t    if test \"${TCL_THREADS}\" = \"1\"; then\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING:\n    --enable-threads requested, but building against a Tcl that is NOT\n    thread-enabled.  This is an OK configuration that will also run in\n    a thread-enabled core.\" >&5\n$as_echo \"$as_me: WARNING:\n    --enable-threads requested, but building against a Tcl that is NOT\n    thread-enabled.  This is an OK configuration that will also run in\n    a thread-enabled core.\" >&2;}\n\t    fi\n\t    ;;\n    esac\n\n\n\n#--------------------------------------------------------------------\n# The statement below defines a collection of symbols related to\n# building as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to build libraries\" >&5\n$as_echo_n \"checking how to build libraries... \" >&6; }\n    # Check whether --enable-shared was given.\nif test \"${enable_shared+set}\" = set; then :\n  enableval=$enable_shared; tcl_ok=$enableval\nelse\n  tcl_ok=yes\nfi\n\n\n    if test \"${enable_shared+set}\" = set; then\n\tenableval=\"$enable_shared\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: shared\" >&5\n$as_echo \"shared\" >&6; }\n\tSHARED_BUILD=1\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: static\" >&5\n$as_echo \"static\" >&6; }\n\tSHARED_BUILD=0\n\n$as_echo \"#define STATIC_BUILD 1\" >>confdefs.h\n\n    fi\n\n\n\n#--------------------------------------------------------------------\n# This macro figures out what flags to use with the compiler/linker\n# when building shared/static debug/optimized objects.  This information\n# can be taken from the tclConfig.sh file, but this figures it all out.\n#--------------------------------------------------------------------\n\n\n\n\n    # Step 0.a: Enable 64 bit support?\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested\" >&5\n$as_echo_n \"checking if 64bit support is requested... \" >&6; }\n    # Check whether --enable-64bit was given.\nif test \"${enable_64bit+set}\" = set; then :\n  enableval=$enable_64bit; do64bit=$enableval\nelse\n  do64bit=no\nfi\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $do64bit\" >&5\n$as_echo \"$do64bit\" >&6; }\n\n    # Step 0.b: Enable Solaris 64 bit VIS support?\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested\" >&5\n$as_echo_n \"checking if 64bit Sparc VIS support is requested... \" >&6; }\n    # Check whether --enable-64bit-vis was given.\nif test \"${enable_64bit_vis+set}\" = set; then :\n  enableval=$enable_64bit_vis; do64bitVIS=$enableval\nelse\n  do64bitVIS=no\nfi\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $do64bitVIS\" >&5\n$as_echo \"$do64bitVIS\" >&6; }\n    # Force 64bit on with VIS\n    if test \"$do64bitVIS\" = \"yes\"; then :\n  do64bit=yes\nfi\n\n    # Step 0.c: Check if visibility support is available. Do this here so\n    # that platform specific alternatives can be used below if this fails.\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \\\"hidden\\\"\" >&5\n$as_echo_n \"checking if compiler supports visibility \\\"hidden\\\"... \" >&6; }\nif test \"${tcl_cv_cc_visibility_hidden+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Werror\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t    extern __attribute__((__visibility__(\"hidden\"))) void f(void);\n\t    void f(void) {}\nint\nmain ()\n{\nf();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_cc_visibility_hidden=yes\nelse\n  tcl_cv_cc_visibility_hidden=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\tCFLAGS=$hold_cflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden\" >&5\n$as_echo \"$tcl_cv_cc_visibility_hidden\" >&6; }\n    if test $tcl_cv_cc_visibility_hidden = yes; then :\n\n\n$as_echo \"#define MODULE_SCOPE extern __attribute__((__visibility__(\\\"hidden\\\")))\" >>confdefs.h\n\n\nfi\n\n    # Step 0.d: Disable -rpath support?\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if rpath support is requested\" >&5\n$as_echo_n \"checking if rpath support is requested... \" >&6; }\n    # Check whether --enable-rpath was given.\nif test \"${enable_rpath+set}\" = set; then :\n  enableval=$enable_rpath; doRpath=$enableval\nelse\n  doRpath=yes\nfi\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $doRpath\" >&5\n$as_echo \"$doRpath\" >&6; }\n\n    # TEA specific: Cross-compiling options for Windows/CE builds?\n\n    if test \"${TEA_PLATFORM}\" = windows; then :\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested\" >&5\n$as_echo_n \"checking if Windows/CE build is requested... \" >&6; }\n\t# Check whether --enable-wince was given.\nif test \"${enable_wince+set}\" = set; then :\n  enableval=$enable_wince; doWince=$enableval\nelse\n  doWince=no\nfi\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $doWince\" >&5\n$as_echo \"$doWince\" >&6; }\n\nfi\n\n    # Step 1: set the variable \"system\" to hold the name and version number\n    # for the system.\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking system version\" >&5\n$as_echo_n \"checking system version... \" >&6; }\nif test \"${tcl_cv_sys_version+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t# TEA specific:\n\tif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t    tcl_cv_sys_version=windows\n\telif test -f /usr/lib/NextStep/software_version; then\n\t    tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`\n\telse\n\t    tcl_cv_sys_version=`uname -s`-`uname -r`\n\t    if test \"$?\" -ne 0 ; then\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command\" >&5\n$as_echo \"$as_me: WARNING: can't find uname command\" >&2;}\n\t\ttcl_cv_sys_version=unknown\n\t    else\n\t\t# Special check for weird MP-RAS system (uname returns weird\n\t\t# results, and the version is kept in special file).\n\n\t\tif test -r /etc/.relid -a \"X`uname -n`\" = \"X`uname -s`\" ; then\n\t\t    tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid`\n\t\tfi\n\t\tif test \"`uname -s`\" = \"AIX\" ; then\n\t\t    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`\n\t\tfi\n\t    fi\n\tfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version\" >&5\n$as_echo \"$tcl_cv_sys_version\" >&6; }\n    system=$tcl_cv_sys_version\n\n\n    # Step 2: check for existence of -ldl library.  This is needed because\n    # Linux can use either -ldl or -ldld for dynamic loading.\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl\" >&5\n$as_echo_n \"checking for dlopen in -ldl... \" >&6; }\nif test \"${ac_cv_lib_dl_dlopen+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlopen ();\nint\nmain ()\n{\nreturn dlopen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dl_dlopen=yes\nelse\n  ac_cv_lib_dl_dlopen=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen\" >&5\n$as_echo \"$ac_cv_lib_dl_dlopen\" >&6; }\nif test \"x$ac_cv_lib_dl_dlopen\" = x\"\"yes; then :\n  have_dl=yes\nelse\n  have_dl=no\nfi\n\n\n    # Require ranlib early so we can override it in special cases below.\n\n\n\n    # Step 3: set configuration options based on system name and version.\n    # This is similar to Tcl's unix/tcl.m4 except that we've added a\n    # \"windows\" case.\n\n    do64bit_ok=no\n    LDFLAGS_ORIG=\"$LDFLAGS\"\n    # When ld needs options to work in 64-bit mode, put them in\n    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]\n    # is disabled by the user. [Bug 1016796]\n    LDFLAGS_ARCH=\"\"\n    TCL_EXPORT_FILE_SUFFIX=\"\"\n    UNSHARED_LIB_SUFFIX=\"\"\n    # TEA specific: use PACKAGE_VERSION instead of VERSION\n    TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'\n    ECHO_VERSION='`echo ${PACKAGE_VERSION}`'\n    TCL_LIB_VERSIONS_OK=ok\n    CFLAGS_DEBUG=-g\n    CFLAGS_OPTIMIZE=-O\n    if test \"$GCC\" = yes; then :\n\n\t# TEA specific:\n\tCFLAGS_OPTIMIZE=-O2\n\tCFLAGS_WARNING=\"-Wall -Wno-implicit-int\"\n\nelse\n  CFLAGS_WARNING=\"\"\nfi\n    TCL_NEEDS_EXP_FILE=0\n    TCL_BUILD_EXP_FILE=\"\"\n    TCL_EXP_FILE=\"\"\n    # Extract the first word of \"ar\", so it can be a program name with args.\nset dummy ar; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif test \"${ac_cv_prog_AR+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$AR\"; then\n  ac_cv_prog_AR=\"$AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if { test -f \"$as_dir/$ac_word$ac_exec_ext\" && $as_test_x \"$as_dir/$ac_word$ac_exec_ext\"; }; then\n    ac_cv_prog_AR=\"ar\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nAR=$ac_cv_prog_AR\nif test -n \"$AR\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AR\" >&5\n$as_echo \"$AR\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    STLIB_LD='${AR} cr'\n    LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH\"\n    case $system in\n\t# TEA specific:\n\twindows)\n\t    # This is a 2-stage check to make sure we have the 64-bit SDK\n\t    # We have to know where the SDK is installed.\n\t    # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs\n\t    # MACHINE is IX86 for LINK, but this is used by the manifest,\n\t    # which requires x86|amd64|ia64.\n\t    MACHINE=\"X86\"\n\t    if test \"$do64bit\" != \"no\" ; then\n\t\tif test \"x${MSSDK}x\" = \"xx\" ; then\n\t\t    MSSDK=\"C:/Progra~1/Microsoft Platform SDK\"\n\t\tfi\n\t\tMSSDK=`echo \"$MSSDK\" | sed -e  's!\\\\\\!/!g'`\n\t\tPATH64=\"\"\n\t\tcase \"$do64bit\" in\n\t\t    amd64|x64|yes)\n\t\t\tMACHINE=\"AMD64\" ; # default to AMD64 64-bit build\n\t\t\tPATH64=\"${MSSDK}/Bin/Win64/x86/AMD64\"\n\t\t\t;;\n\t\t    ia64)\n\t\t\tMACHINE=\"IA64\"\n\t\t\tPATH64=\"${MSSDK}/Bin/Win64\"\n\t\t\t;;\n\t\tesac\n\t\tif test ! -d \"${PATH64}\" ; then\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode\" >&5\n$as_echo \"$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode\" >&2;}\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed\" >&5\n$as_echo \"$as_me: WARNING: Ensure latest Platform SDK is installed\" >&2;}\n\t\t    do64bit=\"no\"\n\t\telse\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode\" >&5\n$as_echo \"   Using 64-bit $MACHINE mode\" >&6; }\n\t\t    do64bit_ok=\"yes\"\n\t\tfi\n\t    fi\n\n\t    if test \"$doWince\" != \"no\" ; then\n\t\tif test \"$do64bit\" != \"no\" ; then\n\t\t    as_fn_error \"Windows/CE and 64-bit builds incompatible\" \"$LINENO\" 5\n\t\tfi\n\t\tif test \"$GCC\" = \"yes\" ; then\n\t\t    as_fn_error \"Windows/CE and GCC builds incompatible\" \"$LINENO\" 5\n\t\tfi\n\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-celib\n\n    if test x\"${no_celib}\" = x ; then\n\t# we reset no_celib in case something fails here\n\tno_celib=true\n\n# Check whether --with-celib was given.\nif test \"${with_celib+set}\" = set; then :\n  withval=$with_celib; with_celibconfig=${withval}\nfi\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory\" >&5\n$as_echo_n \"checking for Windows/CE celib directory... \" >&6; }\n\tif test \"${ac_cv_c_celibconfig+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t    # First check to see if --with-celibconfig was specified.\n\t    if test x\"${with_celibconfig}\" != x ; then\n\t\tif test -d \"${with_celibconfig}/inc\" ; then\n\t\t    ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`\n\t\telse\n\t\t    as_fn_error \"${with_celibconfig} directory doesn't contain inc directory\" \"$LINENO\" 5\n\t\tfi\n\t    fi\n\n\t    # then check for a celib library\n\t    if test x\"${ac_cv_c_celibconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../celib-palm-3.0 \\\n\t\t\t../celib \\\n\t\t\t../../celib-palm-3.0 \\\n\t\t\t../../celib \\\n\t\t\t`ls -dr ../celib-*3.[0-9]* 2>/dev/null` \\\n\t\t\t${srcdir}/../celib-palm-3.0 \\\n\t\t\t${srcdir}/../celib \\\n\t\t\t`ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -d \"$i/inc\" ; then\n\t\t\tac_cv_c_celibconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\nfi\n\n\tif test x\"${ac_cv_c_celibconfig}\" = x ; then\n\t    as_fn_error \"Cannot find celib support library directory\" \"$LINENO\" 5\n\telse\n\t    no_celib=\n\t    CELIB_DIR=${ac_cv_c_celibconfig}\n\t    CELIB_DIR=`echo \"$CELIB_DIR\" | sed -e 's!\\\\\\!/!g'`\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: found $CELIB_DIR\" >&5\n$as_echo \"found $CELIB_DIR\" >&6; }\n\tfi\n    fi\n\n\t\t# Set defaults for common evc4/PPC2003 setup\n\t\t# Currently Tcl requires 300+, possibly 420+ for sockets\n\t\tCEVERSION=420; \t\t# could be 211 300 301 400 420 ...\n\t\tTARGETCPU=ARMV4;\t# could be ARMV4 ARM MIPS SH3 X86 ...\n\t\tARCH=ARM;\t\t# could be ARM MIPS X86EM ...\n\t\tPLATFORM=\"Pocket PC 2003\"; # or \"Pocket PC 2002\"\n\t\tif test \"$doWince\" != \"yes\"; then\n\t\t    # If !yes then the user specified something\n\t\t    # Reset ARCH to allow user to skip specifying it\n\t\t    ARCH=\n\t\t    eval `echo $doWince | awk -F, '{ \\\n\t    if (length($1)) { printf \"CEVERSION=\\\"%s\\\"\\n\", $1; \\\n\t    if ($1 < 400)   { printf \"PLATFORM=\\\"Pocket PC 2002\\\"\\n\" } }; \\\n\t    if (length($2)) { printf \"TARGETCPU=\\\"%s\\\"\\n\", toupper($2) }; \\\n\t    if (length($3)) { printf \"ARCH=\\\"%s\\\"\\n\", toupper($3) }; \\\n\t    if (length($4)) { printf \"PLATFORM=\\\"%s\\\"\\n\", $4 }; \\\n\t\t    }'`\n\t\t    if test \"x${ARCH}\" = \"x\" ; then\n\t\t\tARCH=$TARGETCPU;\n\t\t    fi\n\t\tfi\n\t\tOSVERSION=WCE$CEVERSION;\n\t    \tif test \"x${WCEROOT}\" = \"x\" ; then\n\t\t\tWCEROOT=\"C:/Program Files/Microsoft eMbedded C++ 4.0\"\n\t\t    if test ! -d \"${WCEROOT}\" ; then\n\t\t\tWCEROOT=\"C:/Program Files/Microsoft eMbedded Tools\"\n\t\t    fi\n\t\tfi\n\t\tif test \"x${SDKROOT}\" = \"x\" ; then\n\t\t    SDKROOT=\"C:/Program Files/Windows CE Tools\"\n\t\t    if test ! -d \"${SDKROOT}\" ; then\n\t\t\tSDKROOT=\"C:/Windows CE Tools\"\n\t\t    fi\n\t\tfi\n\t\tWCEROOT=`echo \"$WCEROOT\" | sed -e 's!\\\\\\!/!g'`\n\t\tSDKROOT=`echo \"$SDKROOT\" | sed -e 's!\\\\\\!/!g'`\n\t\tif test ! -d \"${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}\" \\\n\t\t    -o ! -d \"${WCEROOT}/EVC/${OSVERSION}/bin\"; then\n\t\t    as_fn_error \"could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM\" \"$LINENO\" 5\n\t\t    doWince=\"no\"\n\t\telse\n\t\t    # We could PATH_NOSPACE these, but that's not important,\n\t\t    # as long as we quote them when used.\n\t\t    CEINCLUDE=\"${SDKROOT}/${OSVERSION}/${PLATFORM}/include\"\n\t\t    if test -d \"${CEINCLUDE}/${TARGETCPU}\" ; then\n\t\t\tCEINCLUDE=\"${CEINCLUDE}/${TARGETCPU}\"\n\t\t    fi\n\t\t    CELIBPATH=\"${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}\"\n    \t\tfi\n\t    fi\n\n\t    if test \"$GCC\" != \"yes\" ; then\n\t        if test \"${SHARED_BUILD}\" = \"0\" ; then\n\t\t    runtime=-MT\n\t        else\n\t\t    runtime=-MD\n\t        fi\n\n                if test \"$do64bit\" != \"no\" ; then\n\t\t    # All this magic is necessary for the Win64 SDK RC1 - hobbs\n\t\t    CC=\"\\\"${PATH64}/cl.exe\\\"\"\n\t\t    CFLAGS=\"${CFLAGS} -I\\\"${MSSDK}/Include\\\" -I\\\"${MSSDK}/Include/crt\\\" -I\\\"${MSSDK}/Include/crt/sys\\\"\"\n\t\t    RC=\"\\\"${MSSDK}/bin/rc.exe\\\"\"\n\t\t    lflags=\"-nologo -MACHINE:${MACHINE} -LIBPATH:\\\"${MSSDK}/Lib/${MACHINE}\\\"\"\n\t\t    LINKBIN=\"\\\"${PATH64}/link.exe\\\"\"\n\t\t    CFLAGS_DEBUG=\"-nologo -Zi -Od -W3 ${runtime}d\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -O2 -W2 ${runtime}\"\n\t\t    # Avoid 'unresolved external symbol __security_cookie'\n\t\t    # errors, c.f. http://support.microsoft.com/?id=894573\n\n    vars=\"bufferoverflowU.lib\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([^-].*\\)\\.lib$/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n\n\n\t\telif test \"$doWince\" != \"no\" ; then\n\t\t    CEBINROOT=\"${WCEROOT}/EVC/${OSVERSION}/bin\"\n\t\t    if test \"${TARGETCPU}\" = \"X86\"; then\n\t\t\tCC=\"\\\"${CEBINROOT}/cl.exe\\\"\"\n\t\t    else\n\t\t\tCC=\"\\\"${CEBINROOT}/cl${ARCH}.exe\\\"\"\n\t\t    fi\n\t\t    CFLAGS=\"$CFLAGS -I\\\"${CELIB_DIR}/inc\\\" -I\\\"${CEINCLUDE}\\\"\"\n\t\t    RC=\"\\\"${WCEROOT}/Common/EVC/bin/rc.exe\\\"\"\n\t\t    arch=`echo ${ARCH} | awk '{print tolower($0)}'`\n\t\t    defs=\"${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS\"\n\t\t    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\t\t\t# Static CE builds require static celib as well\n\t\t    \tdefs=\"${defs} _DLL\"\n\t\t    fi\n\t\t    for i in $defs ; do\n\ncat >>confdefs.h <<_ACEOF\n#define $i 1\n_ACEOF\n\n\t\t    done\n\ncat >>confdefs.h <<_ACEOF\n#define _WIN32_WCE $CEVERSION\n_ACEOF\n\n\ncat >>confdefs.h <<_ACEOF\n#define UNDER_CE $CEVERSION\n_ACEOF\n\n\t\t    CFLAGS_DEBUG=\"-nologo -Zi -Od\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -Ox\"\n\t\t    lversion=`echo ${CEVERSION} | sed -e 's/\\(.\\)\\(..\\)/\\1\\.\\2/'`\n\t\t    lflags=\"-MACHINE:${ARCH} -LIBPATH:\\\"${CELIBPATH}\\\" -subsystem:windowsce,${lversion} -nologo\"\n\t\t    LINKBIN=\"\\\"${CEBINROOT}/link.exe\\\"\"\n\n\t\telse\n\t\t    RC=\"rc\"\n\t\t    lflags=\"-nologo\"\n    \t\t    LINKBIN=\"link\"\n\t\t    CFLAGS_DEBUG=\"-nologo -Z7 -Od -W3 -WX ${runtime}d\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -O2 -W2 ${runtime}\"\n\t\tfi\n\t    fi\n\n\t    if test \"$GCC\" = \"yes\"; then\n\t\t# mingw gcc mode\n\t\tRC=\"windres\"\n\t\tCFLAGS_DEBUG=\"-g\"\n\t\tCFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\t\tSHLIB_LD=\"$CC -shared\"\n\t\tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t\tLDFLAGS_CONSOLE=\"-wl,--subsystem,console ${lflags}\"\n\t\tLDFLAGS_WINDOW=\"-wl,--subsystem,windows ${lflags}\"\n\t    else\n\t\tSHLIB_LD=\"${LINKBIN} -dll ${lflags}\"\n\t\t# link -lib only works when -lib is the first arg\n\t\tSTLIB_LD=\"${LINKBIN} -lib ${lflags}\"\n\t\tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'\n\t\tPATHTYPE=-w\n\t\t# For information on what debugtype is most useful, see:\n\t\t# http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp\n\t\t# and also\n\t\t# http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx\n\t\t# This essentially turns it all on.\n\t\tLDFLAGS_DEBUG=\"-debug -debugtype:cv\"\n\t\tLDFLAGS_OPTIMIZE=\"-release\"\n\t\tif test \"$doWince\" != \"no\" ; then\n\t\t    LDFLAGS_CONSOLE=\"-link ${lflags}\"\n\t\t    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}\n\t\telse\n\t\t    LDFLAGS_CONSOLE=\"-link -subsystem:console ${lflags}\"\n\t\t    LDFLAGS_WINDOW=\"-link -subsystem:windows ${lflags}\"\n\t\tfi\n\t    fi\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".dll\"\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'\n\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    # Bogus to avoid getting this turned off\n\t    DL_OBJS=\"tclLoadNone.obj\"\n    \t    ;;\n\tAIX-*)\n\t    if test \"${TCL_THREADS}\" = \"1\" -a \"$GCC\" != \"yes\"; then :\n\n\t\t# AIX requires the _r compiler when gcc isn't being used\n\t\tcase \"${CC}\" in\n\t\t    *_r)\n\t\t\t# ok ...\n\t\t\t;;\n\t\t    *)\n\t\t\tCC=${CC}_r\n\t\t\t;;\n\t\tesac\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads\" >&5\n$as_echo \"Using $CC for compiling with threads\" >&6; }\n\nfi\n\t    LIBS=\"$LIBS -lc\"\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    LD_LIBRARY_PATH_VAR=\"LIBPATH\"\n\n\t    # Check to enable 64-bit flags for compiler/linker on AIX 4+\n\t    if test \"$do64bit\" = yes -a \"`uname -v`\" -gt 3; then :\n\n\t\tif test \"$GCC\" = yes; then :\n\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;}\n\nelse\n\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS -q64\"\n\t\t    LDFLAGS_ARCH=\"-q64\"\n\t\t    RANLIB=\"${RANLIB} -X64\"\n\t\t    AR=\"${AR} -X64\"\n\t\t    SHLIB_LD_FLAGS=\"-b64\"\n\nfi\n\nfi\n\n\t    if test \"`uname -m`\" = ia64; then :\n\n\t\t# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\t# AIX-5 has dl* in libc.so\n\t\tDL_LIBS=\"\"\n\t\tif test \"$GCC\" = yes; then :\n\n\t\t    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\nelse\n\n\t\t    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'\n\nfi\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\nelse\n\n\t\tif test \"$GCC\" = yes; then :\n  SHLIB_LD='${CC} -shared'\nelse\n\n\t\t    SHLIB_LD=\"/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry\"\n\nfi\n\t\tSHLIB_LD=\"${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}\"\n\t\tDL_LIBS=\"-ldl\"\n\t\tCC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tTCL_NEEDS_EXP_FILE=1\n\t\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\t\tTCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp'\n\nfi\n\n\t    # AIX v<=4.1 has some different flags than 4.2+\n\t    if test \"$system\" = \"AIX-4.1\" -o \"`uname -v`\" -lt 4; then :\n\n\t\tcase \" $LIBOBJS \" in\n  *\" tclLoadAix.$ac_objext \"* ) ;;\n  *) LIBOBJS=\"$LIBOBJS tclLoadAix.$ac_objext\"\n ;;\nesac\n\n\t\tDL_LIBS=\"-lld\"\n\nfi\n\n\t    # On AIX <=v4 systems, libbsd.a has to be linked in to support\n\t    # non-blocking file IO.  This library has to be linked in after\n\t    # the MATH_LIBS or it breaks the pow() function.  The way to\n\t    # insure proper sequencing, is to add it to the tail of MATH_LIBS.\n\t    # This library also supplies gettimeofday.\n\t    #\n\t    # AIX does not have a timezone field in struct tm. When the AIX\n\t    # bsd library is used, the timezone global and the gettimeofday\n\t    # methods are to be avoided for timezone deduction instead, we\n\t    # deduce the timezone by comparing the localtime result on a\n\t    # known GMT value.\n\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for gettimeofday in -lbsd\" >&5\n$as_echo_n \"checking for gettimeofday in -lbsd... \" >&6; }\nif test \"${ac_cv_lib_bsd_gettimeofday+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lbsd  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar gettimeofday ();\nint\nmain ()\n{\nreturn gettimeofday ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_bsd_gettimeofday=yes\nelse\n  ac_cv_lib_bsd_gettimeofday=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gettimeofday\" >&5\n$as_echo \"$ac_cv_lib_bsd_gettimeofday\" >&6; }\nif test \"x$ac_cv_lib_bsd_gettimeofday\" = x\"\"yes; then :\n  libbsd=yes\nelse\n  libbsd=no\nfi\n\n\t    if test $libbsd = yes; then :\n\n\t    \tMATH_LIBS=\"$MATH_LIBS -lbsd\"\n\n$as_echo \"#define USE_DELTA_FOR_TZ 1\" >>confdefs.h\n\n\nfi\n\t    ;;\n\tBeOS*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -nostart'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\n\t    #-----------------------------------------------------------\n\t    # Check for inet_ntoa in -lbind, for BeOS (which also needs\n\t    # -lsocket, even if the network functions are in -lnet which\n\t    # is always linked to, for compatibility.\n\t    #-----------------------------------------------------------\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind\" >&5\n$as_echo_n \"checking for inet_ntoa in -lbind... \" >&6; }\nif test \"${ac_cv_lib_bind_inet_ntoa+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lbind  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar inet_ntoa ();\nint\nmain ()\n{\nreturn inet_ntoa ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_bind_inet_ntoa=yes\nelse\n  ac_cv_lib_bind_inet_ntoa=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa\" >&5\n$as_echo \"$ac_cv_lib_bind_inet_ntoa\" >&6; }\nif test \"x$ac_cv_lib_bind_inet_ntoa\" = x\"\"yes; then :\n  LIBS=\"$LIBS -lbind -lsocket\"\nfi\n\n\t    ;;\n\tBSD/OS-2.1*|BSD/OS-3*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"shlicc -r\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tBSD/OS-4.*)\n\t    SHLIB_CFLAGS=\"-export-dynamic -fPIC\"\n\t    SHLIB_LD='${CC} -shared'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tdgux*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tHP-UX-*.11.*)\n\t    # Use updated header definitions where possible\n\n$as_echo \"#define _XOPEN_SOURCE_EXTENDED 1\" >>confdefs.h\n\n\t    # TEA specific: Needed by Tcl, but not most extensions\n\t    #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])\n\t    #LIBS=\"$LIBS -lxnet\"               # Use the XOPEN network library\n\n\t    if test \"`uname -m`\" = ia64; then :\n\n\t\tSHLIB_SUFFIX=\".so\"\n\t\t# Use newer C++ library for C++ extensions\n\t\t#if test \"$GCC\" != \"yes\" ; then\n\t\t#   CPPFLAGS=\"-AA\"\n\t\t#fi\n\nelse\n\n\t\tSHLIB_SUFFIX=\".sl\"\n\nfi\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld\" >&5\n$as_echo_n \"checking for shl_load in -ldld... \" >&6; }\nif test \"${ac_cv_lib_dld_shl_load+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar shl_load ();\nint\nmain ()\n{\nreturn shl_load ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dld_shl_load=yes\nelse\n  ac_cv_lib_dld_shl_load=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load\" >&5\n$as_echo \"$ac_cv_lib_dld_shl_load\" >&6; }\nif test \"x$ac_cv_lib_dld_shl_load\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t    if test \"$tcl_ok\" = yes; then :\n\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS='${LIBS}'\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\nfi\n\t    if test \"$GCC\" = yes; then :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tSHLIB_LD_LIBS='${LIBS}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\nfi\n\n\t    # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc\n\t    #CFLAGS=\"$CFLAGS +DAportable\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    if test \"$do64bit\" = \"yes\"; then :\n\n\t\tif test \"$GCC\" = yes; then :\n\n\t\t    case `${CC} -dumpmachine` in\n\t\t\thppa64*)\n\t\t\t    # 64-bit gcc in use.  Fix flags for GNU ld.\n\t\t\t    do64bit_ok=yes\n\t\t\t    SHLIB_LD='${CC} -shared'\n\t\t\t    SHLIB_LD_LIBS='${LIBS}'\n\t\t\t    if test $doRpath = yes; then :\n\n\t\t\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\nfi\n\t\t\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\t\t    ;;\n\t\t\t*)\n\t\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;}\n\t\t\t    ;;\n\t\t    esac\n\nelse\n\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS +DD64\"\n\t\t    LDFLAGS_ARCH=\"+DD64\"\n\nfi\n\nfi ;;\n\tHP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)\n\t    SHLIB_SUFFIX=\".sl\"\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld\" >&5\n$as_echo_n \"checking for shl_load in -ldld... \" >&6; }\nif test \"${ac_cv_lib_dld_shl_load+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar shl_load ();\nint\nmain ()\n{\nreturn shl_load ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dld_shl_load=yes\nelse\n  ac_cv_lib_dld_shl_load=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load\" >&5\n$as_echo \"$ac_cv_lib_dld_shl_load\" >&6; }\nif test \"x$ac_cv_lib_dld_shl_load\" = x\"\"yes; then :\n  tcl_ok=yes\nelse\n  tcl_ok=no\nfi\n\n\t    if test \"$tcl_ok\" = yes; then :\n\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS=\"\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\nfi ;;\n\tIRIX-5.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    ;;\n\tIRIX-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    if test \"$GCC\" = yes; then :\n\n\t\tCFLAGS=\"$CFLAGS -mabi=n32\"\n\t\tLDFLAGS=\"$LDFLAGS -mabi=n32\"\n\nelse\n\n\t\tcase $system in\n\t\t    IRIX-6.3)\n\t\t\t# Use to build 6.2 compatible binaries on 6.3.\n\t\t\tCFLAGS=\"$CFLAGS -n32 -D_OLD_TERMIOS\"\n\t\t\t;;\n\t\t    *)\n\t\t\tCFLAGS=\"$CFLAGS -n32\"\n\t\t\t;;\n\t\tesac\n\t\tLDFLAGS=\"$LDFLAGS -n32\"\n\nfi\n\t    ;;\n\tIRIX64-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\n\t    if test \"$do64bit\" = yes; then :\n\n\t        if test \"$GCC\" = yes; then :\n\n\t            { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported by gcc\" >&2;}\n\nelse\n\n\t            do64bit_ok=yes\n\t            SHLIB_LD=\"ld -64 -shared -rdata_shared\"\n\t            CFLAGS=\"$CFLAGS -64\"\n\t            LDFLAGS_ARCH=\"-64\"\n\nfi\n\nfi\n\t    ;;\n\tLinux*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    # TEA specific:\n\t    CFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\t    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings\n\t    # when you inline the string and math operations.  Turn this off to\n\t    # get rid of the warnings.\n\t    #CFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES\"\n\n\t    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS\n\t    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    if test \"`uname -m`\" = \"alpha\"; then :\n  CFLAGS=\"$CFLAGS -mieee\"\nfi\n\t    if test $do64bit = yes; then :\n\n\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag\" >&5\n$as_echo_n \"checking if compiler accepts -m64 flag... \" >&6; }\nif test \"${tcl_cv_cc_m64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\t    hold_cflags=$CFLAGS\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_cc_m64=yes\nelse\n  tcl_cv_cc_m64=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t    CFLAGS=$hold_cflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64\" >&5\n$as_echo \"$tcl_cv_cc_m64\" >&6; }\n\t\tif test $tcl_cv_cc_m64 = yes; then :\n\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    do64bit_ok=yes\n\nfi\n\nfi\n\n\t    # The combo of gcc + glibc has a bug related to inlining of\n\t    # functions like strtod(). The -fno-builtin flag should address\n\t    # this problem but it does not work. The -fno-inline flag is kind\n\t    # of overkill but it works. Disable inlining only when one of the\n\t    # files in compat/*.c is being linked in.\n\n\t    if test x\"${USE_COMPAT}\" != x; then :\n  CFLAGS=\"$CFLAGS -fno-inline\"\nfi\n\n\t    ;;\n\tGNU*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    if test \"`uname -m`\" = \"alpha\"; then :\n  CFLAGS=\"$CFLAGS -mieee\"\nfi\n\t    ;;\n\tLynx*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    CFLAGS_OPTIMIZE=-02\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-mshared -ldl\"\n\t    LD_FLAGS=\"-Wl,--export-dynamic\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\nfi\n\t    ;;\n\tMP-RAS-02*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tMP-RAS-*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tNetBSD-1.*|FreeBSD-[1-2].*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ELF\" >&5\n$as_echo_n \"checking for ELF... \" >&6; }\nif test \"${tcl_cv_ld_elf+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#ifdef __ELF__\n\tyes\n#endif\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"yes\" >/dev/null 2>&1; then :\n  tcl_cv_ld_elf=yes\nelse\n  tcl_cv_ld_elf=no\nfi\nrm -f conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_elf\" >&5\n$as_echo \"$tcl_cv_ld_elf\" >&6; }\n\t    if test $tcl_cv_ld_elf = yes; then :\n\n\t\tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'\n\nelse\n\n\t\tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\nfi\n\n\t    # Ancient FreeBSD doesn't handle version numbers with dots.\n\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tOpenBSD-*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ELF\" >&5\n$as_echo_n \"checking for ELF... \" >&6; }\nif test \"${tcl_cv_ld_elf+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#ifdef __ELF__\n\tyes\n#endif\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"yes\" >/dev/null 2>&1; then :\n  tcl_cv_ld_elf=yes\nelse\n  tcl_cv_ld_elf=no\nfi\nrm -f conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_elf\" >&5\n$as_echo \"$tcl_cv_ld_elf\" >&6; }\n\t    if test $tcl_cv_ld_elf = yes; then :\n\n\t\tLDFLAGS=-Wl,-export-dynamic\n\nelse\n  LDFLAGS=\"\"\nfi\n\n\t    # OpenBSD doesn't do version numbers with dots.\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tNetBSD-*|FreeBSD-*)\n\t    # FreeBSD 3.* and greater have ELF.\n\t    # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    if test \"${TCL_THREADS}\" = \"1\"; then :\n\n\t\t# The -pthread needs to go in the CFLAGS, not LIBS\n\t\tLIBS=`echo $LIBS | sed s/-pthread//`\n\t\tCFLAGS=\"$CFLAGS -pthread\"\n\t    \tLDFLAGS=\"$LDFLAGS -pthread\"\n\nfi\n\t    case $system in\n\t    FreeBSD-3.*)\n\t    \t# FreeBSD-3 doesn't handle version numbers with dots.\n\t    \tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    \tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'\n\t    \tTCL_LIB_VERSIONS_OK=nodots\n\t\t;;\n\t    esac\n\t    ;;\n\tDarwin-*)\n\t    CFLAGS_OPTIMIZE=\"-Os\"\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    # To avoid discrepancies between what headers configure sees during\n\t    # preprocessing tests and compiling tests, move any -isysroot and\n\t    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:\n\t    CPPFLAGS=\"${CPPFLAGS} `echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif ($i~/^(isysroot|mmacosx-version-min)/) print \"-\"$i}'`\"\n\t    CFLAGS=\"`echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif (!($i~/^(isysroot|mmacosx-version-min)/)) print \"-\"$i}'`\"\n\t    if test $do64bit = yes; then :\n\n\t\tcase `arch` in\n\t\t    ppc)\n\t\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag\" >&5\n$as_echo_n \"checking if compiler accepts -arch ppc64 flag... \" >&6; }\nif test \"${tcl_cv_cc_arch_ppc64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_cc_arch_ppc64=yes\nelse\n  tcl_cv_cc_arch_ppc64=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\t    CFLAGS=$hold_cflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64\" >&5\n$as_echo \"$tcl_cv_cc_arch_ppc64\" >&6; }\n\t\t\tif test $tcl_cv_cc_arch_ppc64 = yes; then :\n\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    do64bit_ok=yes\n\nfi;;\n\t\t    i386)\n\t\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag\" >&5\n$as_echo_n \"checking if compiler accepts -arch x86_64 flag... \" >&6; }\nif test \"${tcl_cv_cc_arch_x86_64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_cc_arch_x86_64=yes\nelse\n  tcl_cv_cc_arch_x86_64=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\t    CFLAGS=$hold_cflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64\" >&5\n$as_echo \"$tcl_cv_cc_arch_x86_64\" >&6; }\n\t\t\tif test $tcl_cv_cc_arch_x86_64 = yes; then :\n\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    do64bit_ok=yes\n\nfi;;\n\t\t    *)\n\t\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \\`arch\\`\" >&5\n$as_echo \"$as_me: WARNING: Don't know how enable 64-bit on architecture \\`arch\\`\" >&2;};;\n\t\tesac\n\nelse\n\n\t\t# Check for combined 32-bit and 64-bit fat build\n\t\tif echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc64|x86_64) ' \\\n\t\t    && echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc|i386) '; then :\n\n\t\t    fat_32_64=yes\nfi\n\nfi\n\t    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS\n\t    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag\" >&5\n$as_echo_n \"checking if ld accepts -single_module flag... \" >&6; }\nif test \"${tcl_cv_ld_single_module+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -dynamiclib -Wl,-single_module\"\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nint i;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_ld_single_module=yes\nelse\n  tcl_cv_ld_single_module=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\tLDFLAGS=$hold_ldflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module\" >&5\n$as_echo \"$tcl_cv_ld_single_module\" >&6; }\n\t    if test $tcl_cv_ld_single_module = yes; then :\n\n\t\tSHLIB_LD=\"${SHLIB_LD} -Wl,-single_module\"\n\nfi\n\t    # TEA specific: link shlib with current and compatibility version flags\n\t    vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\\([0-9]\\{1,5\\}\\)\\(\\(\\.[0-9]\\{1,3\\}\\)\\{0,2\\}\\).*$/\\1\\2/p' -e d`\n\t    SHLIB_LD=\"${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".dylib\"\n\t    DL_OBJS=\"tclLoadDyld.o\"\n\t    DL_LIBS=\"\"\n\t    # Don't use -prebind when building for Mac OS X 10.4 or later only:\n\t    if test \"`echo \"${MACOSX_DEPLOYMENT_TARGET}\" | awk -F '10\\\\.' '{print int($2)}'`\" -lt 4 -a \\\n\t\t\"`echo \"${CPPFLAGS}\" | awk -F '-mmacosx-version-min=10\\\\.' '{print int($2)}'`\" -lt 4; then :\n\n\t\tLDFLAGS=\"$LDFLAGS -prebind\"\nfi\n\t    LDFLAGS=\"$LDFLAGS -headerpad_max_install_names\"\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag\" >&5\n$as_echo_n \"checking if ld accepts -search_paths_first flag... \" >&6; }\nif test \"${tcl_cv_ld_search_paths_first+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nint i;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_ld_search_paths_first=yes\nelse\n  tcl_cv_ld_search_paths_first=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\tLDFLAGS=$hold_ldflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first\" >&5\n$as_echo \"$tcl_cv_ld_search_paths_first\" >&6; }\n\t    if test $tcl_cv_ld_search_paths_first = yes; then :\n\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\nfi\n\t    if test \"$tcl_cv_cc_visibility_hidden\" != yes; then :\n\n\n$as_echo \"#define MODULE_SCOPE __private_extern__\" >>confdefs.h\n\n\nfi\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    LD_LIBRARY_PATH_VAR=\"DYLD_LIBRARY_PATH\"\n\t    # TEA specific: for combined 32 & 64 bit fat builds of Tk\n\t    # extensions, verify that 64-bit build is possible.\n\t    if test \"$fat_32_64\" = yes && test -n \"${TK_BIN_DIR}\"; then :\n\n\t\tif test \"${TEA_WINDOWINGSYSTEM}\" = x11; then :\n\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for 64-bit X11\" >&5\n$as_echo_n \"checking for 64-bit X11... \" >&6; }\nif test \"${tcl_cv_lib_x11_64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc / /g\" -e \"s/-arch i386 / /g\"`\"'\n\t\t\tdone\n\t\t\tCPPFLAGS=\"$CPPFLAGS -I/usr/X11R6/include\"\n\t\t\tLDFLAGS=\"$LDFLAGS -L/usr/X11R6/lib -lX11\"\n\t\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\nint\nmain ()\n{\nXrmInitialize();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_lib_x11_64=yes\nelse\n  tcl_cv_lib_x11_64=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64\" >&5\n$as_echo \"$tcl_cv_lib_x11_64\" >&6; }\n\nfi\n\t\t# remove 64-bit arch flags from CFLAGS et al. if configuration\n\t\t# does not support 64-bit.\n\t\tif test \"${TEA_WINDOWINGSYSTEM}\" = aqua -o \"$tcl_cv_lib_x11_64\" = no; then :\n\n\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags\" >&5\n$as_echo \"$as_me: Removing 64-bit architectures from compiler & linker flags\" >&6;}\n\t\t    for v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\teval $v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc64 / /g\" -e \"s/-arch x86_64 / /g\"`\"'\n\t\t    done\nfi\n\nfi\n\t    ;;\n\tNEXTSTEP-*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD='${CC} -nostdlib -r'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadNext.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOS/390-*)\n\t    CFLAGS_OPTIMIZE=\"\"\t\t# Optimizer is buggy\n\n$as_echo \"#define _OE_SOCKETS 1\" >>confdefs.h\n\n\t    ;;\n\tOSF1-1.0|OSF1-1.1|OSF1-1.2)\n\t    # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    # Hack: make package name same as library name\n\t    SHLIB_LD='ld -R -export :'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadOSF.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOSF1-1.*)\n\t    # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    if test \"$SHARED_BUILD\" = 1; then :\n  SHLIB_LD=\"ld -shared\"\nelse\n\n\t        SHLIB_LD=\"ld -non_shared\"\n\nfi\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOSF1-V*)\n\t    # Digital OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    if test \"$SHARED_BUILD\" = 1; then :\n\n\t        SHLIB_LD='${CC} -shared'\n\nelse\n\n\t        SHLIB_LD='${CC} -non_shared'\n\nfi\n\t    SHLIB_LD_LIBS=\"${LIBS}\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes; then :\n\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    if test \"$GCC\" = yes; then :\n  CFLAGS=\"$CFLAGS -mieee\"\nelse\n\n\t\tCFLAGS=\"$CFLAGS -DHAVE_TZSET -std1 -ieee\"\nfi\n\t    # see pthread_intro(3) for pthread support on osf1, k.furukawa\n\t    if test \"${TCL_THREADS}\" = 1; then :\n\n\t\tCFLAGS=\"$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE\"\n\t\tCFLAGS=\"$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64\"\n\t\tLIBS=`echo $LIBS | sed s/-lpthreads//`\n\t\tif test \"$GCC\" = yes; then :\n\n\t\t    LIBS=\"$LIBS -lpthread -lmach -lexc\"\n\nelse\n\n\t\t    CFLAGS=\"$CFLAGS -pthread\"\n\t\t    LDFLAGS=\"$LDFLAGS -pthread\"\n\nfi\n\nfi\n\t    ;;\n\tQNX-6*)\n\t    # QNX RTP\n\t    # This may work for all QNX, but it was only reported for v6.\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    # dlopen is in -lc on QNX\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSCO_SV-3.2*)\n\t    # Note, dlopen is available only on SCO 3.2.5 and greater. However,\n\t    # this test works, since \"uname -s\" was non-standard in 3.2.4 and\n\t    # below.\n\t    if test \"$GCC\" = yes; then :\n\n\t    \tSHLIB_CFLAGS=\"-fPIC -melf\"\n\t    \tLDFLAGS=\"$LDFLAGS -melf -Wl,-Bexport\"\n\nelse\n\n\t    \tSHLIB_CFLAGS=\"-Kpic -belf\"\n\t    \tLDFLAGS=\"$LDFLAGS -belf -Wl,-Bexport\"\n\nfi\n\t    SHLIB_LD=\"ld -G\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSINIX*5.4*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSunOS-4*)\n\t    SHLIB_CFLAGS=\"-PIC\"\n\t    SHLIB_LD=\"ld\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\n\t    # SunOS can't handle version numbers with dots in them in library\n\t    # specs, like -ltcl7.5, so use -ltcl75 instead.  Also, it\n\t    # requires an extra version number at the end of .so file names.\n\t    # So, the library has to have a name like libtcl75.so.1.0\n\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tSunOS-5.[0-6])\n\t    # Careful to not let 5.10+ fall into this case\n\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\n$as_echo \"#define _REENTRANT 1\" >>confdefs.h\n\n\n$as_echo \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Note: need the LIBS below, otherwise Tk won't find Tcl's\n\t    # symbols when dynamically loaded into tclsh.\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    if test \"$GCC\" = yes; then :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\nelse\n\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\tCC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\nfi\n\t    ;;\n\tSunOS-5*)\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\n$as_echo \"#define _REENTRANT 1\" >>confdefs.h\n\n\n$as_echo \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    if test \"$do64bit\" = yes; then :\n\n\t\tarch=`isainfo`\n\t\tif test \"$arch\" = \"sparcv9 sparc\"; then :\n\n\t\t    if test \"$GCC\" = yes; then :\n\n\t\t\tif test \"`${CC} -dumpversion | awk -F. '{print $1}'`\" -lt 3; then :\n\n\t\t\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system\" >&2;}\n\nelse\n\n\t\t\t    do64bit_ok=yes\n\t\t\t    CFLAGS=\"$CFLAGS -m64 -mcpu=v9\"\n\t\t\t    LDFLAGS=\"$LDFLAGS -m64 -mcpu=v9\"\n\t\t\t    SHLIB_CFLAGS=\"-fPIC\"\n\nfi\n\nelse\n\n\t\t\tdo64bit_ok=yes\n\t\t\tif test \"$do64bitVIS\" = yes; then :\n\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9a\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9a\"\n\nelse\n\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9\"\n\nfi\n\t\t\t# Solaris 64 uses this as well\n\t\t\t#LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH_64\"\n\nfi\n\nelse\n  if test \"$arch\" = \"amd64 i386\"; then :\n\n\t\t    if test \"$GCC\" = yes; then :\n\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)\n\t\t\t\tdo64bit_ok=yes\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;};;\n\t\t\tesac\n\nelse\n\n\t\t\tdo64bit_ok=yes\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tCFLAGS=\"$CFLAGS -xarch=amd64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -xarch=amd64\";;\n\t\t\tesac\n\nfi\n\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch\" >&5\n$as_echo \"$as_me: WARNING: 64bit mode not supported for $arch\" >&2;}\nfi\nfi\n\nfi\n\n\t    # Note: need the LIBS below, otherwise Tk won't find Tcl's\n\t    # symbols when dynamically loaded into tclsh.\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    if test \"$GCC\" = yes; then :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tif test \"$do64bit_ok\" = yes; then :\n\n\t\t    if test \"$arch\" = \"sparcv9 sparc\"; then :\n\n\t\t\t# We need to specify -static-libgcc or we need to\n\t\t\t# add the path to the sparv9 libgcc.\n\t\t\t# JH: static-libgcc is necessary for core Tcl, but may\n\t\t\t# not be necessary for extensions.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -mcpu=v9 -static-libgcc\"\n\t\t\t# for finding sparcv9 libgcc, get the regular libgcc\n\t\t\t# path, remove so name and append 'sparcv9'\n\t\t\t#v9gcclibdir=\"`gcc -print-file-name=libgcc_s.so` | ...\"\n\t\t\t#CC_SEARCH_FLAGS=\"${CC_SEARCH_FLAGS},-R,$v9gcclibdir\"\n\nelse\n  if test \"$arch\" = \"amd64 i386\"; then :\n\n\t\t\t# JH: static-libgcc is necessary for core Tcl, but may\n\t\t\t# not be necessary for extensions.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -static-libgcc\"\n\nfi\nfi\n\nfi\n\nelse\n\n\t\tcase $system in\n\t\t    SunOS-5.[1-9][0-9]*)\n\t\t\tSHLIB_LD='${CC} -G -z text ${LDFLAGS}';;\n\t\t    *)\n\t\t\tSHLIB_LD='/usr/ccs/bin/ld -G -z text';;\n\t\tesac\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\nfi\n\t    ;;\n\tUNIX_SV* | UnixWare-5*)\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers\n\t    # that don't grok the -Bexport option.  Test that it does.\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag\" >&5\n$as_echo_n \"checking for ld accepts -Bexport flag... \" >&6; }\nif test \"${tcl_cv_ld_Bexport+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nint i;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  tcl_cv_ld_Bexport=yes\nelse\n  tcl_cv_ld_Bexport=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\t        LDFLAGS=$hold_ldflags\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport\" >&5\n$as_echo \"$tcl_cv_ld_Bexport\" >&6; }\n\t    if test $tcl_cv_ld_Bexport = yes; then :\n\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\nfi\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n    esac\n\n    if test \"$do64bit\" = yes -a \"$do64bit_ok\" = no; then :\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform\" >&5\n$as_echo \"$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform\" >&2;}\n\nfi\n\n\n\n    # Step 4: disable dynamic loading if requested via a command-line switch.\n\n    # Check whether --enable-load was given.\nif test \"${enable_load+set}\" = set; then :\n  enableval=$enable_load; tcl_ok=$enableval\nelse\n  tcl_ok=yes\nfi\n\n    if test \"$tcl_ok\" = no; then :\n  DL_OBJS=\"\"\nfi\n\n    if test \"x$DL_OBJS\" != x; then :\n  BUILD_DLTEST=\"\\$(DLTEST_TARGETS)\"\nelse\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system.\" >&5\n$as_echo \"$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system.\" >&2;}\n\tSHLIB_CFLAGS=\"\"\n\tSHLIB_LD=\"\"\n\tSHLIB_SUFFIX=\"\"\n\tDL_OBJS=\"tclLoadNone.o\"\n\tDL_LIBS=\"\"\n\tLDFLAGS=\"$LDFLAGS_ORIG\"\n\tCC_SEARCH_FLAGS=\"\"\n\tLD_SEARCH_FLAGS=\"\"\n\tBUILD_DLTEST=\"\"\n\nfi\n    LDFLAGS=\"$LDFLAGS $LDFLAGS_ARCH\"\n\n    # If we're running gcc, then change the C flags for compiling shared\n    # libraries to the right flags for gcc, instead of those for the\n    # standard manufacturer compiler.\n\n    if test \"$DL_OBJS\" != \"tclLoadNone.o\" -a \"$GCC\" = yes; then :\n\n\tcase $system in\n\t    AIX-*) ;;\n\t    BSD/OS*) ;;\n\t    IRIX*) ;;\n\t    NetBSD-*|FreeBSD-*) ;;\n\t    Darwin-*) ;;\n\t    SCO_SV-3.2*) ;;\n\t    *) SHLIB_CFLAGS=\"-fPIC\" ;;\n\tesac\nfi\n\n    if test \"$SHARED_LIB_SUFFIX\" = \"\"; then :\n\n\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\tSHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'\nfi\n    if test \"$UNSHARED_LIB_SUFFIX\" = \"\"; then :\n\n\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\tUNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    # These must be called after we do the basic CFLAGS checks and\n    # verify any possible 64-bit or similar switches are necessary\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for required early compiler flags\" >&5\n$as_echo_n \"checking for required early compiler flags... \" >&6; }\n    tcl_flags=\"\"\n\n    if test \"${tcl_cv_flag__isoc99_source+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain ()\n{\nchar *p = (char *)strtoll; char *q = (char *)strtoull;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__isoc99_source=no\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _ISOC99_SOURCE 1\n#include <stdlib.h>\nint\nmain ()\n{\nchar *p = (char *)strtoll; char *q = (char *)strtoull;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__isoc99_source=yes\nelse\n  tcl_cv_flag__isoc99_source=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n\n    if test \"x${tcl_cv_flag__isoc99_source}\" = \"xyes\" ; then\n\n$as_echo \"#define _ISOC99_SOURCE 1\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _ISOC99_SOURCE\"\n    fi\n\n\n    if test \"${tcl_cv_flag__largefile64_source+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/stat.h>\nint\nmain ()\n{\nstruct stat64 buf; int i = stat64(\"/\", &buf);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__largefile64_source=no\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _LARGEFILE64_SOURCE 1\n#include <sys/stat.h>\nint\nmain ()\n{\nstruct stat64 buf; int i = stat64(\"/\", &buf);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__largefile64_source=yes\nelse\n  tcl_cv_flag__largefile64_source=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n\n    if test \"x${tcl_cv_flag__largefile64_source}\" = \"xyes\" ; then\n\n$as_echo \"#define _LARGEFILE64_SOURCE 1\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _LARGEFILE64_SOURCE\"\n    fi\n\n\n    if test \"${tcl_cv_flag__largefile_source64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/stat.h>\nint\nmain ()\n{\nchar *p = (char *)open64;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__largefile_source64=no\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _LARGEFILE_SOURCE64 1\n#include <sys/stat.h>\nint\nmain ()\n{\nchar *p = (char *)open64;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_flag__largefile_source64=yes\nelse\n  tcl_cv_flag__largefile_source64=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n\n    if test \"x${tcl_cv_flag__largefile_source64}\" = \"xyes\" ; then\n\n$as_echo \"#define _LARGEFILE_SOURCE64 1\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _LARGEFILE_SOURCE64\"\n    fi\n\n    if test \"x${tcl_flags}\" = \"x\" ; then\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: none\" >&5\n$as_echo \"none\" >&6; }\n    else\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}\" >&5\n$as_echo \"${tcl_flags}\" >&6; }\n    fi\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type\" >&5\n$as_echo_n \"checking for 64-bit integer type... \" >&6; }\n    if test \"${tcl_cv_type_64bit+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\ttcl_cv_type_64bit=none\n\t# See if the compiler knows natively about __int64\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n__int64 value = (__int64) 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_type_64bit=__int64\nelse\n  tcl_type_64bit=\"long long\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\t# See if we should use long anyway  Note that we substitute in the\n\t# type that is our current guess for a 64-bit type inside this check\n\t# program, so it should be modified only carefully...\n        cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nswitch (0) {\n            case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;\n        }\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_type_64bit=${tcl_type_64bit}\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n\n    if test \"${tcl_cv_type_64bit}\" = none ; then\n\n$as_echo \"#define TCL_WIDE_INT_IS_LONG 1\" >>confdefs.h\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: using long\" >&5\n$as_echo \"using long\" >&6; }\n    elif test \"${tcl_cv_type_64bit}\" = \"__int64\" \\\n\t\t-a \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t# TEA specific: We actually want to use the default tcl.h checks in\n\t# this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults\" >&5\n$as_echo \"using Tcl header defaults\" >&6; }\n    else\n\ncat >>confdefs.h <<_ACEOF\n#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}\n_ACEOF\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}\" >&5\n$as_echo \"${tcl_cv_type_64bit}\" >&6; }\n\n\t# Now check for auxiliary declarations\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for struct dirent64\" >&5\n$as_echo_n \"checking for struct dirent64... \" >&6; }\nif test \"${tcl_cv_struct_dirent64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n#include <sys/dirent.h>\nint\nmain ()\n{\nstruct dirent64 p;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_struct_dirent64=yes\nelse\n  tcl_cv_struct_dirent64=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64\" >&5\n$as_echo \"$tcl_cv_struct_dirent64\" >&6; }\n\tif test \"x${tcl_cv_struct_dirent64}\" = \"xyes\" ; then\n\n$as_echo \"#define HAVE_STRUCT_DIRENT64 1\" >>confdefs.h\n\n\tfi\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for struct stat64\" >&5\n$as_echo_n \"checking for struct stat64... \" >&6; }\nif test \"${tcl_cv_struct_stat64+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/stat.h>\nint\nmain ()\n{\nstruct stat64 p;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_struct_stat64=yes\nelse\n  tcl_cv_struct_stat64=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64\" >&5\n$as_echo \"$tcl_cv_struct_stat64\" >&6; }\n\tif test \"x${tcl_cv_struct_stat64}\" = \"xyes\" ; then\n\n$as_echo \"#define HAVE_STRUCT_STAT64 1\" >>confdefs.h\n\n\tfi\n\n\tfor ac_func in open64 lseek64\ndo :\n  as_ac_var=`$as_echo \"ac_cv_func_$ac_func\" | $as_tr_sh`\nac_fn_c_check_func \"$LINENO\" \"$ac_func\" \"$as_ac_var\"\neval as_val=\\$$as_ac_var\n   if test \"x$as_val\" = x\"\"yes; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_func\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\ndone\n\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for off64_t\" >&5\n$as_echo_n \"checking for off64_t... \" >&6; }\n\tif test \"${tcl_cv_type_off64_t+set}\" = set; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\nint\nmain ()\n{\noff64_t offset;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  tcl_cv_type_off64_t=yes\nelse\n  tcl_cv_type_off64_t=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n\n\t\t\tif test \"x${tcl_cv_type_off64_t}\" = \"xyes\" && \\\n\t        test \"x${ac_cv_func_lseek64}\" = \"xyes\" && \\\n\t        test \"x${ac_cv_func_open64}\" = \"xyes\" ; then\n\n$as_echo \"#define HAVE_TYPE_OFF64_T 1\" >>confdefs.h\n\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n\telse\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n\tfi\n    fi\n\n\n# should be part of TEA_CONFIG_CFLAGS, but more visible modification here\n\n\n#--------------------------------------------------------------------\n# Set the default compiler switches based on the --enable-symbols option.\n#--------------------------------------------------------------------\n\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for build with symbols\" >&5\n$as_echo_n \"checking for build with symbols... \" >&6; }\n    # Check whether --enable-symbols was given.\nif test \"${enable_symbols+set}\" = set; then :\n  enableval=$enable_symbols; tcl_ok=$enableval\nelse\n  tcl_ok=no\nfi\n\n    DBGX=\"\"\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT=\"${CFLAGS_OPTIMIZE}\"\n\tLDFLAGS_DEFAULT=\"${LDFLAGS_OPTIMIZE}\"\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n    else\n\tCFLAGS_DEFAULT=\"${CFLAGS_DEBUG}\"\n\tLDFLAGS_DEFAULT=\"${LDFLAGS_DEBUG}\"\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)\" >&5\n$as_echo \"yes (standard debugging)\" >&6; }\n\tfi\n    fi\n    # TEA specific:\n    if test \"${TEA_PLATFORM}\" != \"windows\" ; then\n\tLDFLAGS_DEFAULT=\"${LDFLAGS}\"\n    fi\n\n\n\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\n$as_echo \"#define TCL_MEM_DEBUG 1\" >>confdefs.h\n\n    fi\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging\" >&5\n$as_echo \"enabled symbols mem debugging\" >&6; }\n\telse\n\t    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging\" >&5\n$as_echo \"enabled $tcl_ok debugging\" >&6; }\n\tfi\n    fi\n\n\n#--------------------------------------------------------------------\n# Everyone should be linking against the Tcl stub library.  If you\n# can't for some reason, remove this definition.  If you aren't using\n# stubs, you also need to modify the SHLIB_LD_LIBS setting below to\n# link against the non-stubbed Tcl library.  Add Tk too if necessary.\n#--------------------------------------------------------------------\n\nif test \"${USE_STUBS}\" = \"1\" ; then\n\n$as_echo \"#define USE_TCL_STUBS 1\" >>confdefs.h\n\n\n$as_echo \"#define USE_TK_STUBS 1\" >>confdefs.h\n\nfi\n\n#--------------------------------------------------------------------\n# This macro generates a line to use when building a library.  It\n# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,\n# and TEA_LOAD_TCLCONFIG macros above.\n#--------------------------------------------------------------------\n\n\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" != \"yes\"; then\n\tMAKE_STATIC_LIB=\"\\${STLIB_LD} -out:\\$@ \\$(PKG_OBJECTS)\"\n\tMAKE_SHARED_LIB=\"\\${SHLIB_LD} \\${SHLIB_LD_LIBS} \\${LDFLAGS_DEFAULT} -out:\\$@ \\$(PKG_OBJECTS)\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} -out:\\$@ \\$(PKG_STUB_OBJECTS)\"\n    else\n\tMAKE_STATIC_LIB=\"\\${STLIB_LD} \\$@ \\$(PKG_OBJECTS)\"\n\tMAKE_SHARED_LIB=\"\\${SHLIB_LD} -o \\$@ \\$(PKG_OBJECTS) \\${SHLIB_LD_LIBS}\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} \\$@ \\$(PKG_STUB_OBJECTS)\"\n    fi\n\n    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\tMAKE_LIB=\"${MAKE_SHARED_LIB} \"\n    else\n\tMAKE_LIB=\"${MAKE_STATIC_LIB} \"\n    fi\n\n    #--------------------------------------------------------------------\n    # Shared libraries and static libraries have different names.\n    # Use the double eval to make sure any variables in the suffix is\n    # substituted. (@@@ Might not be necessary anymore)\n    #--------------------------------------------------------------------\n\n    if test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\tif test \"${SHARED_BUILD}\" = \"1\" ; then\n\t    # We force the unresolved linking of symbols that are really in\n\t    # the private libraries of Tcl and Tk.\n\t    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\\"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\\\"\"\n\t    if test x\"${TK_BIN_DIR}\" != x ; then\n\t\tSHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\\"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\\\"\"\n\t    fi\n\t    eval eval \"PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}\"\n\telse\n\t    eval eval \"PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}\"\n\tfi\n\t# Some packages build their own stubs libraries\n\teval eval \"PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}\"\n\tif test \"$GCC\" = \"yes\"; then\n\t    PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}\n\tfi\n\t# These aren't needed on Windows (either MSVC or gcc)\n\tRANLIB=:\n\tRANLIB_STUB=:\n    else\n\tRANLIB_STUB=\"${RANLIB}\"\n\tif test \"${SHARED_BUILD}\" = \"1\" ; then\n\t    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}\"\n\t    if test x\"${TK_BIN_DIR}\" != x ; then\n\t\tSHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}\"\n\t    fi\n\t    eval eval \"PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}\"\n\t    RANLIB=:\n\telse\n\t    eval eval \"PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}\"\n\tfi\n\t# Some packages build their own stubs libraries\n\teval eval \"PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}\"\n    fi\n\n    # These are escaped so that only CFLAGS is picked up at configure time.\n    # The other values will be substituted at make time.\n    CFLAGS=\"${CFLAGS} \\${CFLAGS_DEFAULT} \\${CFLAGS_WARNING}\"\n    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\tCFLAGS=\"${CFLAGS} \\${SHLIB_CFLAGS}\"\n    fi\n\n\n\n\n\n\n\n\nif test \"${USE_STUBS}\" = \"0\" ; then\n\tSHLIB_LD_LIBS=`echo \"$SHLIB_LD_LIBS\" | sed -e 's!stub!!g'`\nfi\n\n#--------------------------------------------------------------------\n# Determine the name of the tclsh and/or wish executables in the\n# Tcl and Tk build directories or the location they were installed\n# into. These paths are used to support running test cases only,\n# the Makefile should not be making use of these paths to generate\n# a pkgIndex.tcl file or anything else at extension build time.\n#--------------------------------------------------------------------\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for tclsh\" >&5\n$as_echo_n \"checking for tclsh... \" >&6; }\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n        # tclConfig.sh is in Tcl build directory\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            TCLSH_PROG=\"${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}\"\n        else\n            TCLSH_PROG=\"${TCL_BIN_DIR}/tclsh\"\n        fi\n    else\n        # tclConfig.sh is in install location\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            TCLSH_PROG=\"tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}\"\n        else\n            TCLSH_PROG=\"tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}\"\n        fi\n        list=\"`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \\\n              `ls -d ${TCL_BIN_DIR}/..     2>/dev/null` \\\n              `ls -d ${TCL_PREFIX}/bin     2>/dev/null`\"\n        for i in $list ; do\n            if test -f \"$i/${TCLSH_PROG}\" ; then\n                REAL_TCL_BIN_DIR=\"`cd \"$i\"; pwd`/\"\n                break\n            fi\n        done\n        TCLSH_PROG=\"${REAL_TCL_BIN_DIR}${TCLSH_PROG}\"\n    fi\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}\" >&5\n$as_echo \"${TCLSH_PROG}\" >&6; }\n\n\n#TEA_PROG_WISH\n\n#--------------------------------------------------------------------\n# Finally, substitute all of the various values into the Makefile.\n# You may alternatively have a special pkgIndex.tcl.in or other files\n# which require substituting th AC variables in.  Include these here.\n#--------------------------------------------------------------------\n\nac_config_files=\"$ac_config_files Makefile pkgIndex.tcl togl_ws.h\"\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# `ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* `ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\n# The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # `set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # `set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n) |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test \"${\\1+set}\" = set || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    test \"x$cache_file\" != \"x/dev/null\" &&\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\n$as_echo \"$as_me: updating cache $cache_file\" >&6;}\n    cat confcache >$cache_file\n  else\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\n$as_echo \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\n# Transform confdefs.h into DEFS.\n# Protect against shell expansion while executing Makefile rules.\n# Protect against Makefile macro expansion.\n#\n# If the first sed substitution is executed (which looks for macros that\n# take arguments), then branch to the quote section.  Otherwise,\n# look for a macro that doesn't take arguments.\nac_script='\n:mline\n/\\\\$/{\n N\n s,\\\\\\n,,\n b mline\n}\nt clear\n:clear\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t (][^\t (]*([^)]*)\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t ][^\t ]*\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\nb any\n:quote\ns/[\t `~#$^&*(){}\\\\|;'\\''\"<>?]/\\\\&/g\ns/\\[/\\\\&/g\ns/\\]/\\\\&/g\ns/\\$/$$/g\nH\n:any\n${\n\tg\n\ts/^\\n//\n\ts/\\n/ /g\n\tp\n}\n'\nDEFS=`sed -n \"$ac_script\" confdefs.h`\n\n\nac_libobjs=\nac_ltlibobjs=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`$as_echo \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n\nCFLAGS=\"${CFLAGS} ${CPPFLAGS}\"; CPPFLAGS=\"\"\n\n: ${CONFIG_STATUS=./config.status}\nac_write_fail=0\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files $CONFIG_STATUS\"\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\n$as_echo \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$CONFIG_STATUS <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n\n# as_fn_error ERROR [LINENO LOG_FD]\n# ---------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with status $?, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$?; test $as_status -eq 0 && as_status=1\n  if test \"$3\"; then\n    as_lineno=${as_lineno-\"$2\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $1\" >&$3\n  fi\n  $as_echo \"$as_me: error: $1\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -p'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -p'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -p'\n  fi\nelse\n  as_ln_s='cp -p'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nif test -x / >/dev/null 2>&1; then\n  as_test_x='test -x'\nelse\n  if ls -dL / >/dev/null 2>&1; then\n    as_ls_L_option=L\n  else\n    as_ls_L_option=\n  fi\n  as_test_x='\n    eval sh -c '\\''\n      if test -d \"$1\"; then\n\ttest -d \"$1/.\";\n      else\n\tcase $1 in #(\n\t-*)set \"./$1\";;\n\tesac;\n\tcase `ls -ld'$as_ls_L_option' \"$1\" 2>/dev/null` in #((\n\t???[sx]*):;;*)false;;esac;fi\n    '\\'' sh\n  '\nfi\nas_executable_p=$as_test_x\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\nexec 6>&1\n## ----------------------------------- ##\n## Main body of $CONFIG_STATUS script. ##\n## ----------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by Togl $as_me 2.1, which was\ngenerated by GNU Autoconf 2.65.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\n\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n\\`$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n\nConfiguration files:\n$config_files\n\nReport bugs to the package provider.\"\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_cs_config=\"`$as_echo \"$ac_configure_args\" | sed 's/^ //; s/[\\\\\"\"\\`\\$]/\\\\\\\\&/g'`\"\nac_cs_version=\"\\\\\nTogl config.status 2.1\nconfigured by $0, generated by GNU Autoconf 2.65,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2009 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\nINSTALL='$INSTALL'\ntest -n \"\\$AWK\" || AWK=awk\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    $as_echo \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    $as_echo \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h |  --help | --hel | -h )\n    $as_echo \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error \"unrecognized option: \\`$1'\nTry \\`$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X '$SHELL' '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\$as_echo \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  $as_echo \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"Makefile\") CONFIG_FILES=\"$CONFIG_FILES Makefile\" ;;\n    \"pkgIndex.tcl\") CONFIG_FILES=\"$CONFIG_FILES pkgIndex.tcl\" ;;\n    \"togl_ws.h\") CONFIG_FILES=\"$CONFIG_FILES togl_ws.h\" ;;\n\n  *) as_fn_error \"invalid argument: \\`$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test \"${CONFIG_FILES+set}\" = set || CONFIG_FILES=$config_files\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to `$tmp'.\n$debug ||\n{\n  tmp=\n  trap 'exit_status=$?\n  { test -z \"$tmp\" || test ! -d \"$tmp\" || rm -fr \"$tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -n \"$tmp\" && test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error \"cannot create a temporary directory in .\" \"$LINENO\" 5\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with `./config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | grep -c '$'`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | grep -c X`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\ncat >>\"\\$tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>$CONFIG_STATUS || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$tmp/subs1.awk\" > \"$tmp/subs.awk\" \\\n  || as_fn_error \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove $(srcdir),\n# ${srcdir} and @srcdir@ from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=/{\ns/:*\\$(srcdir):*/:/\ns/:*\\${srcdir}:*/:/\ns/:*@srcdir@:*/:/\ns/^\\([^=]*=[\t ]*\\):*/\\1/\ns/:*$//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n\neval set X \"  :F $CONFIG_FILES      \"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error \"invalid tag \\`$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain `:'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error \"cannot find input file: \\`$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`$as_echo \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is `configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  $as_echo \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\n$as_echo \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`$as_echo \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$tmp/stdin\" \\\n      || as_fn_error \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n  case $INSTALL in\n  [\\\\/$]* | ?:[\\\\/]* ) ac_INSTALL=$INSTALL ;;\n  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;\n  esac\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\n$as_echo \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when `$srcdir' = `.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\ns&@INSTALL@&$ac_INSTALL&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$tmp/subs.awk\" >$tmp/out \\\n  || as_fn_error \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \"$tmp/out\"`; test -z \"$ac_out\"; } &&\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined.\" >&5\n$as_echo \"$as_me: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined.\" >&2;}\n\n  rm -f \"$tmp/stdin\"\n  case $ac_file in\n  -) cat \"$tmp/out\" && rm -f \"$tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n\n\n\n  esac\n\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_files=$ac_clean_files_save\n\ntest $ac_write_fail = 0 ||\n  as_fn_error \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit $?\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\n$as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n"
  },
  {
    "path": "ng/Togl2.1/configure.in",
    "content": "#!/bin/bash -norc\ndnl\tThis file is an input file used by the GNU \"autoconf\" program to\ndnl\tgenerate the file \"configure\", which is run during Tcl installation\ndnl\tto configure the system for the local environment.\n#\n# RCS: @(#) $Id: configure.in,v 1.17 2009/03/03 21:49:56 gregcouch Exp $\n\n#-----------------------------------------------------------------------\n# Sample configure.in for Tcl Extensions.  The only places you should\n# need to modify this file are marked by the string __CHANGE__\n#-----------------------------------------------------------------------\n\n#-----------------------------------------------------------------------\n# __CHANGE__\n# Set your package name and version numbers here.\n#\n# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION\n# set as provided.  These will also be added as -D defs in your Makefile\n# so you can encode the package version directly into the source files.\n#-----------------------------------------------------------------------\n\nAC_INIT([Togl], [2.1])\n\n#--------------------------------------------------------------------\n# Call TEA_INIT as the first TEA_ macro to set up initial vars.\n# This will define a ${TEA_PLATFORM} variable == \"unix\" or \"windows\"\n# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.\n#--------------------------------------------------------------------\n\nTEA_INIT([3.7])\n\nAC_CONFIG_AUX_DIR(tclconfig)\n\n#--------------------------------------------------------------------\n# Load the tclConfig.sh file\n#--------------------------------------------------------------------\n\nTEA_PATH_TCLCONFIG\nTEA_LOAD_TCLCONFIG\n\n#--------------------------------------------------------------------\n# Load the tkConfig.sh file if necessary (Tk extension)\n#--------------------------------------------------------------------\n\nTEA_PATH_TKCONFIG\nTEA_LOAD_TKCONFIG\n\n#-----------------------------------------------------------------------\n# Handle the --prefix=... option by defaulting to what Tcl gave.\n# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.\n#-----------------------------------------------------------------------\n\nTEA_PREFIX\n\n#-----------------------------------------------------------------------\n# Standard compiler checks.\n# This sets up CC by using the CC env var, or looks for gcc otherwise.\n# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create\n# the basic setup necessary to compile executables.\n#-----------------------------------------------------------------------\n\nTEA_SETUP_COMPILER\n\n#-----------------------------------------------------------------------\n# __CHANGE__\n# Specify the C source files to compile in TEA_ADD_SOURCES,\n# public headers that need to be installed in TEA_ADD_HEADERS,\n# stub library C source files to compile in TEA_ADD_STUB_SOURCES,\n# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.\n# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS\n# and PKG_TCL_SOURCES.\n#-----------------------------------------------------------------------\n\nTOGL_ENABLE_STUBS\n\nTEA_ADD_SOURCES([togl.c toglProcAddr.c toglStubInit.c])\n# togl_ws.h is added in Makefile.in because it is generated\nTEA_ADD_HEADERS([togl.h toglDecls.h])\nTEA_ADD_INCLUDES([])\nTEA_ADD_LIBS([])\nTEA_ADD_CFLAGS([])\nif test \"${USE_STUBS}\" = \"1\" ; then\n\tTEA_ADD_STUB_SOURCES([toglStubLib.c])\nfi\nTEA_ADD_TCL_SOURCES([])\n\n#--------------------------------------------------------------------\n# __CHANGE__\n# A few miscellaneous platform-specific items:\n#\n# Define a special symbol for Windows (BUILD_sample in this case) so\n# that we create the export library with the dll.\n#\n# Windows creates a few extra files that need to be cleaned up.\n# You can add more files to clean if your extension creates any extra\n# files.\n#\n# TEA_ADD_* any platform specific compiler/build info here.\n#--------------------------------------------------------------------\n\n# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure\n# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.\n#CLEANFILES=\"pkgIndex.tcl\"\nif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n    AC_DEFINE(BUILD_togl, 1, [Build windows export dll])\n    CLEANFILES=\"$CLEANFILES *.lib *.dll *.exp *.ilk *.pdb vc*.pch *.manifest\"\n    #TEA_ADD_SOURCES([win/winFile.c])\n    #TEA_ADD_INCLUDES([-I\\\"$(${CYGPATH} ${srcdir}/win)\\\"])\nelse\n    # Ensure no empty else clauses\n    :\n    CLEANFILES=\"so_locations\"\n    #TEA_ADD_SOURCES([unix/unixFile.c])\n    #TEA_ADD_LIBS([-lsuperfly])\nfi\nAC_SUBST(CLEANFILES)\n\n#--------------------------------------------------------------------\n# __CHANGE__\n# Choose which headers you need.  Extension authors should try very\n# hard to only rely on the Tcl public header files.  Internal headers\n# contain private data structures and are subject to change without\n# notice.\n# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG\n#--------------------------------------------------------------------\n\n# find Tcl, Tk, and X11 headers\n#TEA_PUBLIC_TCL_HEADERS\nTEA_PRIVATE_TCL_HEADERS\n\n#TEA_PUBLIC_TK_HEADERS\nTEA_PRIVATE_TK_HEADERS\nTEA_PATH_X\n\n# find autostereo header, lib, and daemon\nAC_ARG_WITH([autostereo],\n\t[AS_HELP_STRING([--with-autostereo],\n\t\t[directory with autostereo source (for SGI)])],\n\t[with_autostereo=${withval}])\nAC_ARG_WITH([autostereod],\n\t[AS_HELP_STRING([--with-autostereod],\n\t\t[path to autostereod daemon (for SGI)])],\n\t[with_autostereod=${withval}])\nAC_ARG_VAR([AUTOSTEREOD], [Path to autostereod for SGI IRIX computers])\n\nAC_MSG_CHECKING([for autostereo directory])\nif test x\"${with_autostereo}\" != x ; then\n\tif test -f \"${with_autostereo}/lib/autostereo.h\" ; then\n\t\twith_autostereo=`(cd ${with_autostereo}; pwd)`\n\t\tTEA_ADD_INCLUDES([-I${with_autostereo}/lib])\n\t\tTEA_ADD_LIBS([-L${with_autostereo}/lib -lautostereo])\n\t\tAC_DEFINE_UNQUOTED(HAVE_AUTOSTEREO, 1,\n\t\t\t[Define this if you have the autostereo header])\n\telse\n\t\tAC_MSG_ERROR([${with_autostereo} directory doesn't contain lib/autostereo.h])\n\tfi\nfi\n\nAC_PATH_PROG([AUTOSTEREOD], [autostereod], [],\n\t\t\t[`eval \\\"echo $sbindir\\\"`:$PATH:/sbin:/usr/sbin])\n\n\n# Choose OpenGL platform\ncase \"${TEA_WINDOWINGSYSTEM}\" in\n\taqua)\n\t\tAC_SUBST(TOGL_WINDOWINGSYSTEM,TOGL_AGL)\n\t\tTEA_ADD_LIBS([-framework AGL -framework OpenGL -framework ApplicationServices])\n\t\t# libGLU is implicit in OpenGL framework\n\t\tLIBGLU=\n\t\t;;\n\tx11)\n\t\tAC_SUBST(TOGL_WINDOWINGSYSTEM,TOGL_X11)\n\t\tAC_ARG_WITH([Xmu],\n\t\t    [AS_HELP_STRING([--with-Xmu],\n\t\t        [use system's shared Xmu library])],\n\t\t    [],\n\t\t    [with_Xmu=no])\n\t\tAS_IF([test \"x$with_Xmu\" != xno],\n\t\t    [AC_CHECK_LIB([Xmu], [XmuLookupStandardColormap],\n\t\t\t[TEA_ADD_LIBS([-lXmu])\n\t\t\t AC_DEFINE(USE_SYSTEM_LIBXMU, 1,\n\t\t\t\t   [Define to use system Xmu library])\n\t\t\t],\n\t\t\t[with_Xmu=no],\n\t\t\t[-lXt -lX11]\n\t\t    )])\n\t\tAS_IF([test \"x$with_Xmu\" = xno],\n\t\t\t[TEA_ADD_SOURCES([Xmu/CmapAlloc.c Xmu/CrCmap.c Xmu/DelCmap.c Xmu/LookupCmap.c Xmu/StdCmap.c])])\n\t\tTEA_ADD_LIBS([-lGL])\n\t\tLIBGLU=-lGLU\n\t\tTOGL_UNDEF_GET_PROC_ADDRESS\n\t\t;;\n\twin32)\n\t\tAC_SUBST(TOGL_WINDOWINGSYSTEM,TOGL_WGL)\n\t\tTEA_ADD_LIBS([opengl32.lib user32.lib gdi32.lib])\n\t\tif test \"$GCC\" = \"yes\" ; then\n\t\t\tLIBGLU=-lglu32\n\t\telse\n\t\t\t# assume Microsoft compiler\n\t\t\tLIBGLU=glu32.lib\n\t\tfi\n\t\t;;\n\t*)\n\t\tAC_MSG_ERROR([Unsupported windowing system: ${TEA_WINDOWINGSYSTEM}])\n\t\t;;\nesac\nAC_SUBST(LIBGLU)\nAC_SUBST(TEA_WINDOWINGSYSTEM)\n\n#--------------------------------------------------------------------\n# Check whether --enable-threads or --disable-threads was given.\n# This auto-enables if Tcl was compiled threaded.\n#--------------------------------------------------------------------\n\nTEA_ENABLE_THREADS\n\n#--------------------------------------------------------------------\n# The statement below defines a collection of symbols related to\n# building as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\nTEA_ENABLE_SHARED\n\n#--------------------------------------------------------------------\n# This macro figures out what flags to use with the compiler/linker\n# when building shared/static debug/optimized objects.  This information\n# can be taken from the tclConfig.sh file, but this figures it all out.\n#--------------------------------------------------------------------\n\nTEA_CONFIG_CFLAGS\n# should be part of TEA_CONFIG_CFLAGS, but more visible modification here\nAC_SUBST(SHLIB_SUFFIX)\n\n#--------------------------------------------------------------------\n# Set the default compiler switches based on the --enable-symbols option.\n#--------------------------------------------------------------------\n\nTEA_ENABLE_SYMBOLS\n\n#--------------------------------------------------------------------\n# Everyone should be linking against the Tcl stub library.  If you\n# can't for some reason, remove this definition.  If you aren't using\n# stubs, you also need to modify the SHLIB_LD_LIBS setting below to\n# link against the non-stubbed Tcl library.  Add Tk too if necessary.\n#--------------------------------------------------------------------\n\nif test \"${USE_STUBS}\" = \"1\" ; then\n\tAC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])\n\tAC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])\nfi\n\n#--------------------------------------------------------------------\n# This macro generates a line to use when building a library.  It\n# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,\n# and TEA_LOAD_TCLCONFIG macros above.\n#--------------------------------------------------------------------\n\nTEA_MAKE_LIB\n\nif test \"${USE_STUBS}\" = \"0\" ; then\n\tSHLIB_LD_LIBS=`echo \"$SHLIB_LD_LIBS\" | sed -e 's!stub!!g'`\nfi\n\n#--------------------------------------------------------------------\n# Determine the name of the tclsh and/or wish executables in the\n# Tcl and Tk build directories or the location they were installed\n# into. These paths are used to support running test cases only,\n# the Makefile should not be making use of these paths to generate\n# a pkgIndex.tcl file or anything else at extension build time.\n#--------------------------------------------------------------------\n\nTEA_PROG_TCLSH\n#TEA_PROG_WISH\n\n#--------------------------------------------------------------------\n# Finally, substitute all of the various values into the Makefile.\n# You may alternatively have a special pkgIndex.tcl.in or other files\n# which require substituting th AC variables in.  Include these here.\n#--------------------------------------------------------------------\n\nAC_OUTPUT([Makefile pkgIndex.tcl togl_ws.h])\n"
  },
  {
    "path": "ng/Togl2.1/doc/README.txt",
    "content": "This directory contains the documentation of Togl, the Tk OpenGL widget.\nThe documentation also doubles as the contents of the Togl home page.\n"
  },
  {
    "path": "ng/Togl2.1/doc/capi.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Togl C API</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Togl C API</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#compile\">Compiling and linking C Togl Functions</a>\n      <li><a href=\"#setup\">Setup and Initialization Functions</a>\n      <ul>\n\t<li><code>Togl_Init</code>,\n\t<code>Togl_InitStubs</code>\n      </ul>\n      <li><a href=\"#drawing\">Drawing-related Commands</a>\n      <ul>\n\t<li><code>Togl_PostRedisplay</code>,\n\t<code>Togl_SwapBuffers</code>,\n\t<code>Togl_MakeCurrent</code>,\n\t<code>Togl_SwapInterval</code>\n\t<code>Togl_CopyContext</code>\n      </ul>\n      <li><a href=\"#query\">Query Functions</a>\n      <ul>\n\t<li><code>Togl_Ident</code>,\n\t<code>Togl_Width</code>,\n\t<code>Togl_Height</code>,\n\t<code>Togl_Interp</code>,\n\t<code>Togl_TkWin</code>,\n\t<code>Togl_GetProcAddr</code>,\n\t<code>Togl_ContextTag</code>\n\t<code>Togl_UpdatePending</code>\n\t<code>Togl_HasRGBA</code>\n\t<code>Togl_IsDoubleBuffered</code>\n\t<code>Togl_HasDepthBuffer</code>\n\t<code>Togl_HasAccumulationBuffer</code>\n\t<code>Togl_HasDestinationAlpha</code>\n\t<code>Togl_HasStencilBuffer</code>\n\t<code>Togl_StereoMode</code>\n\t<code>Togl_HasMultisample</code>\n      </ul>\n      <li><a href=\"#index\">Color Index Mode Functions</a>\n      <ul>\n\t<li><code>Togl_AllocColor</code>,\n\t<code>Togl_FreeColor</code>,\n\t<code>Togl_SetColor</code>\n      </ul>\n      <li><a href=\"#font\">Font Functions</a>\n      <ul>\n\t<li><code>Togl_LoadBitmapFont</code>,\n\t<code>Togl_UnloadBitmapFont</code>,\n\t<code>Togl_WriteObj</code>,\n\t<code>Togl_WriteChars</code>\n      </ul>\n      <li><a href=\"#client\">Client Data Functions</a>\n      <ul>\n\t<li><code>Togl_SetClientData</code>,\n\t<code>Togl_GetClientData</code>\n      </ul>\n      <li><a href=\"#overlay\">Overlay Functions</a>\n      <ul>\n\t<li><code>Togl_UseLayer</code>,\n\t<code>Togl_ShowOverlay</code>,\n\t<code>Togl_HideOverlay</code>,\n\t<code>Togl_PostOveralyRedisplay</code>,\n\t<code>Togl_ExistsOverlay</code>,\n\t<code>Togl_GetOverlayTransparentValue</code>,\n\t<code>Togl_IsMappedOverlay</code>,\n\t<code>Togl_AllocColorOverlay</code>,\n\t<code>Togl_FreeColorOverlay</code>\n      </ul>\n      <li><a href=\"#stereo\">Stereo Functions</a>\n      <ul>\n\t<li><code>Togl_Drawbuffer</code>,\n\t<li><code>Togl_Clear</code>\n\t<li><code>Togl_Frustum</code>\n\t<li><code>Togl_Ortho</code>\n\t<li><code>Togl_NumEyes</code>\n      </ul>\n      <li><a href=\"#image\">Image Functions</a>\n      <ul>\n\t<li><code>Togl_TakePhoto</code>\n      </ul>\n      <li><a href=\"#convert\">Conversion Functions</a>\n      <ul>\n\t<li><code>Togl_GetToglFromObj</code>,\n\t<li><code>Togl_GetToglFromName</code>\n      </ul>\n    </ul>\n\n    <hr>\n\n    <h2><a name=\"compile\">Compiling and linking C Togl Functions</a></h2>\n\n    <p>\n    All Togl functions are found in the Togl header file.\n\n    <blockquote>\n      <code>\n\t#include \"togl.h\"\n      </code>\n    </blockquote>\n\n    <p>\n    For portability, you should include the <code>togl.h</code> header\n    before any other OpenGL headers\n    so it will compile on Microsoft Windows.\n\n    <p>\n    Before calling any Togl functions, you need to initialize it.\n    Regardless if you're using stubs (by defining <code>USE_TOGL_STUBS</code>)\n    or not, the following code will properly initialize togl:\n\n    <blockquote><pre>\nif (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n|| Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n    /* fail */\n}\n</pre></blockquote>\n\n    <p>\n    If you are using a prebuilt binary distribution,\n    you should be sure to define <code>USE_TOGL_STUBS</code> beforehand.\n\n    <p>\n    See the source for the demo programs in the Togl source distribution\n    for working examples.\n\n    <h3>Linking</h3>\n\n    <p>\n    If you are using a prebuilt binary,\n    be sure to link against the stub library.\n    On Microsoft Windows,\n    link against <code>Toglstub21.lib opengl32.lib user32.lib gdi32.lib</code>,\n    on Mac OS X,\n    link against <code>-lToglstub2.1 -framework OpenGL</code>,\n    on other platforms,\n    link against <code>-lToglstub2.1 -lGLU -lGL -lm</code>.\n\n    <p>\n    If building your own Togl package,\n    you can use the stubs interface or link in the Tcl and Tk libraries as well.\n    If using the stubs interface, link as shown above.\n    Otherwise:\n    on Microsoft Windows,\n    link against <code>Togl21.lib tk84.lib tcl84.lib opengl32.lib user32.lib gdi32.lib</code>,\n    on Mac OS X,\n    link against <code>-lTogl2.1 -framework Tk -framework Tcl -framework OpenGL</code>,\n    on other platforms,\n    link against <code>-lTogl2.1 -ltk8.4 -ltcl8.4 -lGLU -lGL -lm</code>.\n\n    <h2><a name=\"setup\">Setup and Initialization Functions</a></h2>\n\n    <dl>\n      <dt><code>int Togl_Init(Tcl_Interp *interp)</code>\n      <dd>\n      Initializes the Togl module.  This is typically called from the\n      Tk_Main() function\n      or other Tcl package initialization function that is directly linked\n      to the Togl (shared) library.\n      It is also indirectly called via\n      Tcl's <code>package require Togl</code> command.\n      If successful, the return value is TCL_OK.\n    </dl>\n\n    <dl>\n      <dt>\n      <code>const char *Togl_InitStubs(Tcl_Interp *interp, const char *version, int exact)</code>\n      <dd>\n      Loads the Togl package into the given <code>interp</code>reter\n      and initializes it.\n      <code>version</code> should be <code>\"2.0\"</code> or higher.\n      This is typically called from C/C++ code that accesses Togl's C API\n      and has installed Togl into the standard TCL hierarchy.\n      See the Tcl InitStubs(3) or the Tk TkInitStubs(3) manual pages for\n      more information.\n    </dl>\n\n    <h2><a name=\"drawing\">Drawing-related Commands</a></h2>\n\n    <dl>\n      <dt><code>void Togl_PostRedisplay(Togl *togl)</code>\n      <dd>\n      Signals that the widget should be redrawn.  When Tk is next idle,\n      the <code>displaycommand</code> callback will be invoked.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_SwapBuffers(const Togl *togl)</code>\n      <dd>\n      Swaps the front and back color buffers for a double-buffered widget.\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml\">\n\tglFlush</a> is executed if the window is single-buffered.  So this call\n      works for both single- and double-buffered contexts.  This is\n      typically called in the <code>displaycommand</code> callback function.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_MakeCurrent(const Togl *togl)</code>\n      <dd>\n      Sets the current rendering context to the given widget.  This is done\n      automatically before any Togl callback functions is called.  So the\n      call is only needed if you have multiple widgets with separate OpenGL\n      contexts.  If the argument is NULL, then the rendering context is cleared\n      and subsequent OpenGL commands will fail.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_SwapInterval(const Togl *togl, int interval)</code>\n      <dd>\n      Returns True if successful.\n      Attempts to change the maximum refresh rate\n      by setting the minimum number of cycles between successive swap buffers.\n      For benchmarking purposes, you should set the swap interval to 0.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_CopyContext(const Togl *from, const Togl *to, unsigned int mask)</code>\n      <dd>\n      Copy a subset of the OpenGL context state from from one context\n      to another using the mask parameter who values are the same as\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml\">\n\tglPushAttrib</a>.\n      The return value is TCL_OK if the context was copied.\n    </dl>\n\n    <h2><a name=\"query\">Query Functions</a></h2>\n\n    <dl>\n      <dt><code>char *Togl_Ident(const Togl *togl)</code>\n      <dd>\n      Returns a pointer to the identification string associated with a Togl\n      widget or NULL if there's no identifier string.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_Width(const Togl *togl)</code>\n      <dd>\n      Returns the width of the given Togl widget.  Typically called in the\n      <code>reshapecommand</code> callback function.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_Height(const Togl *togl)</code>\n      <dd>\n      Returns the height of the given Togl widget.  Typically called in the\n      <code>reshapecommand</code> callback function.\n    </dl>\n\n    <dl>\n      <dt><code>Tcl_Interp *Togl_Interp(const Togl *togl)</code>\n      <dd>\n      Returns the Tcl interpreter associated with the given Togl widget.\n    </dl>\n    <dl>\n      <dt>\n      <code>Tk_Window Togl_TkWin(const Togl *togl)</code>\n      <dd>\n      Returns the Tk window associated with the given Togl widget.\n    </dl>\n\n    <dl>\n      <dt><code>Togl_FuncPtr Togl_GetProcAddr(const char *funcname)</code>\n      <dd>\n      Platform-independent way to get OpenGL function pointers from a\n      function name.\n      Note that in Microsoft Windows (WGL) versions that\n      \"the extension function addresses are unique for each pixel format.\n      All rendering contexts of a given pixel format\n      share the same extension function addresses.\"\n      And on *nix (GLX/X11) platforms, \n      \"the function pointers returned are context independent\"\n      (Linux ABI documentation).\n      The Mac OS X (AGL) platform acts like a *nix platform.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_ContextTag(const Togl *t)</code>\n      <dd>\n      Returns an integer that represents the context tag.\n      All Togl widgets with the same context tag share display lists.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_UpdatePending(const Togl *t)</code>\n      <dd>\n      Returns True if the window should be redrawn.  See Togl_PostRedisplay.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasRGBA(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget has a RBGA color buffer.\n      False means that the widget is using a color index buffer.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_IsDoubleBuffered(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget is double buffered.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasDepthBuffer(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget is has a depth buffer.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasAccumulationBuffer(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget has an accumulation buffer.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasDestinationAlpha(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget has a destination alpha buffer.\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasStencilBuffer(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget has a stencil buffer.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_StereoMode(const Togl *t)</code>\n      <dd>\n      Return current stereo mode.  See ??\n    </dl>\n\n    <dl>\n      <dt><code>Bool Togl_HasMultisample(const Togl *t)</code>\n      <dd>\n      Return True if Togl widget has a multisample buffer.\n    </dl>\n\n    <h2><a name=\"index\">Color Index Mode Functions</a></h2>\n\n    <p>\n    These functions are only used for color index mode.\n\n    <dl>\n      <dt><code>unsigned long Togl_AllocColor(Togl *togl, float red, float green, float blue)</code>\n      <dd>\n      Allocate a color from a read-only colormap.  Given a color specified\n      by red, green, and blue return a colormap index (aka pixel value)\n      whose entry most closely matches the red, green, blue color.  Red,\n      green, and blue are values in [0,1].  This function is only used in\n      color index mode when the <code>-privatecmap</code> option is false.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_FreeColor(Togl *togl, unsigned long index)</code>\n      <dd>\n      Free a color in a read-only colormap.  Index is a value which was\n      returned by the Togl_AllocColor() function.  This function is only\n      used in color index mode when the <code>-privatecmap</code> option\n      is false.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_SetColor(Togl *togl,\n\tint index, float red, float green, float blue)</code>\n      <dd>\n      Load the colormap entry specified by index with the given red, green\n      and blue values.  Red, green, and blue are values in [0,1].  This\n      function is only used in color index mode when the\n      <code>-privatecmap</code> option is true.\n    </dl>\n\n\n    <h2><a name=\"font\">Font Functions</a></h2>\n\n    <p>\n    These functions provide an interface to the simple bitmap font capabilities\n    that every OpenGL implementation provides.\n    Better font support is found in other C APIs, <i>e.g.</i>,\n    <a href=\"http://quesoglc.sourceforge.net/\">QuesoGLC</a>\n    or <a href=\"http://sourceforge.net/projects/ftgl\">FTGL</a>.\n\n    <dl>\n      <dt><code>Tcl_Obj *Togl_LoadBitmapFont(Togl *togl,\n\tconst char *fontname)</code>\n      <dd>\n      Load the named font as a set of\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml\">\n\tglBitmap</a> display lists.\n      <var>fontname</var> may be any of the font description styles\n      accepted by the Tk font command.\n      For maximum portability, one of the standard Tk fonts,\n      <b>Courier</b>, <b>Times</b>, and <b>Helvetica</b>, should be used.\n      Unicode fonts are treated as if they have only have an 8-bit index\n      (so poorly).\n      If successful, a Togl BitmapFont object is returned.\n      NULL is returned on failure.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_UnloadBitmapFont(Togl *togl, Tcl_Obj *toglfont)\n      </code>\n      <dd>\n      Destroys the bitmap display lists created by by Togl_LoadBitmapFont().\n      If successful, the return value is TCL_OK.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_WriteChars(const Togl *togl, const Tcl_Obj *toglfont, const char *string, int length)\n      </code>\n      Draw the given <em>string</em>.\n      If the given <em>length</em> is zero, then it is computed using strlen.\n      Returns the length of the drawn string.\n      <dd>\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_WriteObj(const Togl *togl, const Tcl_Obj *toglfont, Tcl_Obj *obj)\n      </code>\n      <dd>\n      Tcl_Obj interface to <code>Tcl_WriteChars</code>.\n    </dl>\n\n    <h2><a name=\"client\">Client Data Functions</a></h2>\n\n    <p>\n    Each Togl structure has a pointer to an arbitrary client data structure.\n\n    <dl>\n      <dt><code>void Togl_SetClientData(Togl *togl, ClientData clientData)</code>\n      <dd>\n      Set the Togl widget's client data pointer to <em>clientData</em>.\n    </dl>\n\n    <dl>\n      <dt><code>ClientData Togl_GetClientData(const Togl *togl)</code>\n      <dd>\n      Return the Togl widget's client data pointer.\n    </dl>\n\n\n    <h2><a name=\"overlay\">Overlay Functions</a></h2>\n\n    <p>\n    These functions are modeled after GLUT's overlay sub-API.\n\n    <dl>\n      <dt><code>void Togl_UseLayer(Togl *togl, int layer)</code>\n      <dd>\n      Select the layer into which subsequent OpenGL rendering will be\n      directed.  <em>layer</em> may be either <em>TOGL_OVERLAY</em> or\n      <em>TOGL_NORMAL</em>.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_ShowOverlay(Togl *togl)</code>\n      <dd>\n      Display the overlay planes, if any.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_HideOverlay(Togl *togl)</code>\n      <dd>\n      Hide the overlay planes, if any.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_PostOverlayRedisplay(Togl *togl)</code>\n      <dd>\n      Signal that the overlay planes should be redraw.  \n      When Tk is next idle,\n      the <code>overlaydisplaycommand</code> callback will be invoked.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_ExistsOverlay(Togl *togl)</code>\n      <dd>\n      Returns 1 if overlay planes exist, 0 otherwise.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_GetOverlayTransparentValue(const Togl *togl)</code>\n      <dd>\n      Returns the color index of the overlay's transparent pixel value.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_IsMappedOverlay(const Togl *togl)</code>\n      <dd>\n      Returns 1 if the overlay planes are currently displayed, 0 otherwise.\n    </dl>\n\n    <dl>\n      <dt><code>unsigned long Togl_AllocColorOverlay(const Togl *togl,\n\tfloat red, float green, float blue)</code>\n      <dd>\n      Allocate a color in the overlay planes.  Red, green, and blue are\n      values in [0,1].  Return the color index or -1 if the allocation\n      fails.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_FreeColorOverlay(const Togl *togl, unsigned long index)</code>\n      <dd>\n      Free a color which was allocated with Togl_AllocColorOverlay().\n    </dl>\n\n    <h2><a name=\"stereo\">Stereo Functions</a></h2>\n\n    <p>\n    Togl abstracts part of the stereo drawing process to seamlessly\n    support quad-buffered stereo as well as various alternative stereo\n    formats.  The stereo viewing parameters, <code>eyeseparation</code>\n    and <code>convergence</code> need to be set with the Togl's\n    <a href=\"tclapi.html#stereo options\">stereo options</a>.\n\n    <dl>\n      <dt><code>void Togl_DrawBuffer(Togl *togl, GLenum mode)</code>\n      <dd>\n      Switch to OpenGL draw buffer.\n      Should be one of GL_BACK_LEFT, GL_BACK_RIGHT, GL_FRONT_LEFT, or\n      GL_FRONT_RIGHT.\n      It is not possible to draw in the left and right buffers at the same\n      time in the alternate stereo modes.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_Clear(const Togl *togl, GLbitfield mask)</code>\n      <dd>\n      Replacement for OpenGL's\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml\">\n\tglClear</a> that takes into account the alternate stereo mode.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_Frustum(const Togl *togl, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)</code>\n      <dd>\n      Replacement for OpenGL's\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml\">\n\tglFrustum</a> that takes into account the alternate stereo mode.\n    </dl>\n\n    <dl>\n      <dt><code>void Togl_Ortho(const Togl *togl, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)</code>\n      <dd>\n      Replacement for OpenGL's\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml\">\n\tglOrtho</a> that takes into account the alternate stereo mode.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_NumEyes(const Togl *togl)</code>\n      <dd>\n    </dl>\n\n    <h3>Stereo Example</h3>\n\n    <p>\n    This code works for quad-buffered stereo,\n    as well as the other stereo modes.\n\n    <blockquote><pre>\nif (Togl_NumEyes(togl) == 1) {\n    Togl_DrawBuffer(togl, GL_BACK);\n    Togl_Clear(togl);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    Togl_Frustum(togl, left, right, bottom, top, near, far);\n    glMatrixMode(GL_MODELVIEW);\n    <b><i>draw image</i></b>\n} else {\n    Togl_DrawBuffer(togl, GL_BACK_LEFT);\n    Togl_Clear(togl);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    Togl_Frustum(togl, left, right, bottom, top, near, far);\n    glMatrixMode(GL_MODELVIEW);\n    <b><i>draw left-eye image</i></b>\n    Togl_DrawBuffer(togl, GL_BACK_RIGHT);\n    Togl_Clear(togl);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    Togl_Frustum(togl, left, right, bottom, top, near, far);\n    glMatrixMode(GL_MODELVIEW);\n    <b><i>draw right-eye image</i></b>\n}\nTogl_SwapBuffers(togl);\n</pre></blockquote>\n\n    <h2><a name=\"image\">Image Functions</a></h2>\n\n    <p>\n    <!--description-->\n\n    <dl>\n      <dt><code>int Togl_TakePhoto(Togl *togl, Tk_PhotoHandle photo)</code>\n      <dd>\n      Take a photo image of the current Togl window and place it in the\n      given <code>photo</code> object.\n      If the window is partially obscured,\n      either by other windows or by the edges of the display,\n      the results are undefined in the obscured region. \n      If successful, the return value is TCL_OK.\n    </dl>\n\n    <h2><a name=\"convert\">Conversion Functions</a></h2>\n\n    <p>\n    These functions aid the programmer when writing Togl callback functions.\n\n    <dl>\n      <dt><code>int Togl_GetToglFromObj(Tcl_Interp *interp, Tcl_Obj *obj, Togl **toglPtr)</code>\n      <dd>\n      Attempt to return a Togl structure \"toglPtr\" from the Tcl object \"obj\".\n      If successful, the return value is TCL_OK.\n    </dl>\n\n    <dl>\n      <dt><code>int Togl_GetToglFromName(Tcl_Interp *interp, const char *cmdName, Togl **toglPtr)</code>\n      <dd>\n      Attempt to return a Togl structure \"toglPtr\" from the Tcl command name \"cmdName\".\n      If successful, the return value is TCL_OK.\n    </dl>\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/download.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Downloading and Installing Togl</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Downloading and Installing Togl</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#prereq\">Prerequisites</a>\n      <li><a href=\"#getting\">Downloading</a>\n      <li><a href=\"#building\">Installing</a>\n      <ul>\n\t<li><a href=\"#x11\">X11 usage</a>\n\t<li><a href=\"#windows\">Microsoft Windows usage</a>\n\t<li><a href=\"#macosx\">Mac OS X usage</a>\n      </ul>\n      <li><a href=\"#version\">Version History</a>\n    </ul>\n\n    <hr>\n\n    <h2><a name=\"prereq\">Prerequisites</a></h2>\n\n    <p>\n    You should have\n    <a href=\"http://www.tcl.tk/\">Tcl and Tk</a>\n    installed on your computer.\n    Togl works with Tcl/Tk version 8.1 and up\n    (all recent testing has been with version 8.4).\n    The Mac OS X version requires version 8.4\n    (note: versions 8.4.12 and 8.4.13 have a bug when unmapping Togl widgets).\n\n    <p>\n    You must also have\n    <a href=\"http://www.opengl.org\">OpenGL</a> or\n    <a href=\"http://www.mesa3d.org\">Mesa</a>\n    (a free alternative to OpenGL with the same API)\n    installed on your computer.\n\n    <p>\n    And one should be familiar with Tcl, Tk, OpenGL,\n    and C programming to use Togl effectively.\n\n    <br>\n    <h2><a name=\"getting\">Downloading Togl</a></h2>\n\n    <p>\n    Togl can be downloaded from the\n    <a href=\"http://sourceforge.net/project/showfiles.php?group_id=519\">\n      SourceForge</a> Files page.\n\n    <p>\n    Several prebuilt binary distributions are available\n    as well as a source distribution.\n\n    <h2><a name=\"building\">Installing Togl</a></h2>\n\n    <h3>Installing prebuild binaries</h3>\n\n    <p>\n    Prebuilt binaries provide a Togl2.1 directory,\n    the togl.h, togl_ws.h and toglDecls.h include files,\n    and the togl stub library\n    (libToglstub2.1.a or Toglstub20.lib, <i>etc</i>).\n    The Togl2.1 directory needs to copied\n    into one of the directories on Tcl's package path\n    (type <code>puts $auto_path</code> in the Tcl interpreter to see\n    the list of directories).\n    If you have C code that needs to access Togl's subroutines directly,\n    place the include file in the same place as Tcl's include file and\n    the stub library in the same place as Tcl's stub library.\n\n    <h3>Installing from source</h3>\n\n    <p>\n    Togl uses the Tcl Extension Architecture to be able to build on the\n    same platforms Tcl can be built on.\n    In addition to the Togl source,\n    you will need to have the Tcl and Tk source distributions\n    because not all installations have the needed Tcl and Tk internal header files.\n\n    <p>\n    How you link with Togl depends on how you're planning to use it.\n    There are basically three ways of using Togl with your application:\n    <ul>\n      <li>\n      Install the Togl shared library and pkgIndex.tcl file\n      (using <code>make install</code>)\n      and link to the Togl stubs library with your executable or shared library.\n      In this case you must call Togl_InitStubs() (and probably Tcl_InitStubs()\n      &mdash; Tk_InitStubs is only needed if you call Tk functions).\n      This is the way the included Togl examples are built.\n\n      <li>\n      Link to the Togl shared library\n      or &quot;compile in&quot; the Togl object files\n      with your executable or shared library.\n      In this case you must call Togl_Init() from your C code\n      to initialize Togl.\n\n      <li>\n      Install the Togl shared library and pkgIndex.tcl file\n      (using <code>make install</code>)\n      and then load it using Tcl commands or Tcl_PkgRequire().\n      Then use Tcl commands to create and manipulate the Togl widget.\n    </ul>\n\n    Since Togl is compiled into a shared library using the Tcl/Tk stubs-interface,\n    the same binary can be used with any version of Tck/Tk from 8.1 and up.\n    See <code>README.stubs</code> for more info.\n\n    <p>\n    Specific platform notes follow:\n\n    <h4><a name=\"x11\">Unix/X11 usage</a></h4>\n\n    <p>\n    Unix/X systems only need the public Tcl/Tk include files.\n    Just <code>configure</code>, <code>make</code>,\n    and optionally <code>make install</code>.\n\n    <h4><a name=\"windows\">Microsoft Windows usage</a></h4>\n\n    <p>\n    Microsoft Windows platforms need <code>tkWinInt.h</code>\n    and other internal Tk header files.  So you need a Tcl/Tk\n    source distribution in addition to the Togl distribution\n    (or copy over the various include files).\n    <p>\n    Here's the minimal way to build Togl with Tcl/Tk\n    using the <a href=\"http://gcc.gnu.org\">gcc</a> that is distributed\n    as part of the <a href=\"http://cygwin.com/\">cygwin</a> tools\n    (<a href=\"www.microsoft.com\">Microsoft</a>'s compilers work too):\n    <blockquote><pre><code>\nVER=8.4.12\nSRCDIR=`pwd`\n\ncd $SRCDIR/tcl$VER/win\nenv 'CC=gcc -mno-cygwin' ./configure --enable-threads\nmake libtclstub84.a\n\ncd $SRCDIR/tk$VER/win\nenv 'CC=gcc -mno-cygwin' ./configure --enable-threads\nmake libtkstub84.a\n\ncd $SRCDIR/Togl2.1\nenv 'CC=gcc -mno-cygwin' ./configure --with-tcl=../tcl$VER/win --with-tk=../tk$VER/win\n\nmake\n</code></pre></blockquote>\n    The resulting <code>Togl21.dll</code> and <code>pkgIndex.tcl</code>\n    should be installed into your Tcl installation just like any other package.\n\n    <p>\n    If you change all of the above <code>make</code>'s\n    to <code>make install</code> instead,\n    then the Togl package is installed correctly.\n\n    <h4><a name=\"macosx\">Mac OS X usage</a></h4>\n\n    <p>\n    These special instructions are for building the Aqua version of Togl.\n    Mac OS X needs <code>tkMacOSXInt.h</code>\n    and other internal Tk header files.\n    Unfortunately, the Tcl and Tk frameworks that Apple distributes\n    are missing the internal headers.\n    So you need a Tcl/Tk source distribution in addition to the Togl\n    distribution (or copy over the various include files).\n    You would probably want a newer version of Tcl and Tk anyway\n    because each minor revision of 8.4 has many Aqua bug fixes.\n    <p>\n    Here's one way to build Tcl, Tk, and Togl on Mac OS X\n    (assuming they are all in the same directory)\n    to install in your home directory:\n    <blockquote><pre><code>\nVER=8.4.12\n\nmkdir -p ~/bin\nmake -C tcl$VER/macosx install PREFIX=\"${HOME}\" INSTALL_PATH=\"${HOME}/Library/Frameworks\"\nmake -C tk$VER/macosx install PREFIX=\"${HOME}\" INSTALL_PATH=\"${HOME}/Library/Frameworks\" APPLICATION_INSTALL_PATH=\"${HOME}/Applications\"\n\ncd Togl2.1\n./configure --prefix=\"${HOME}\"\nmake install\n</code></pre></blockquote>\n\n    <br>\n    <h2><a name=\"version\">Version History</a></h2>\n\n    <h3>Version 1.0 &mdash; March, 1996</h3>\n    <ul>\n      <li>Initial version\n    </ul>\n\n    <h3>Version 1.1 (never officially released)</h3>\n    <ul>\n      <li>Added Togl_LoadBitmapFont function\n      <li>Fixed a few bugs\n    </ul>\n\n    <h3>Version 1.2 &mdash; November, 1996</h3>\n    <ul>\n      <li>added swapbuffers and makecurrent Tcl commands\n      <li>more bug fixes\n      <li>upgraded to support Tcl 7.6 and Tk 4.2\n      <li>added stereo and overlay plane support\n      <li>added Togl_Get/SetClientData() functions\n      <li>added Togl_DestroyFunc()\n    </ul>\n\n    <h3>Version 1.3 &mdash; May 2, 1997</h3>\n    <ul>\n      <li>fixed a bug in Togl_Configure()\n      <li>fixed a compilation problem in using Tcl_PkgProvide() with Tcl < 7.4\n      <li>new overlay functions: Togl_ExistsOverlay, Togl_GetOverlayTransparentValue,\n      Togl_IsMappedOverlay, Togl_AllocColorOverlay, Togl_FreeColorOverlay\n      <li>added X11 functions: Togl_Display, Togl_Screen, Togl_ScreenNumber,\n      Togl_Colormap\n      <li>added Togl_DumpToEpsFile function\n      <li>fixed a C++ compilation problem\n      <li>more robust overlay code\n      <li>added timers (Togl_TimerFunc) from Peter Dern and Elmar Gerwalin\n    </ul>\n\n    <h3>Version 1.4 &mdash; September 17, 1997</h3>\n    <ul>\n      <li>ported to Microsoft Windows NT (Robert Casto)\n      <li>updated for Tcl/Tk 8.0\n      <li>added many config flags (-redsize, -depthsize, etc) (Matthias Ott)\n      <li>added Togl_Set*Func() functions to reassign callback functions (Matthias Ott)\n      <li>added Togl_ResetDefaultCallbacks() and Togl_ClientData() functions (Greg Couch)\n    </ul>\n\n    <h3>Version 1.5 &mdash; September 18, 1998</h3>\n    <ul>\n      <li>fixed a few Unix and Microsoft Windows compilation bugs\n      <li>added Ben Evan's SGI stereo functions\n      <li>multiple expose events now reduced to one redraw\n      <li>destroying Togl widgets caused problems, patched by Adrian J. Chung\n      <li>added Togl_TkWin() function\n      <li>updated for Tcl/Tk 8.0p2\n      <li>added gears demo from Philip Quaife\n      <li>added <code>-sharelist</code> and <code>-sharecontext</code> config flags\n      <li>fixed a few overlay update bugs\n      <li>added <code>-indirect</code> config flag\n    </ul>\n\n    <h3>Version 1.6 &mdash; May 7, 2003</h3>\n    <ul>\n      <li>added Togl_SetTimerFunc function\n      <li>updated for Tcl/Tk 8.0.5 and 8.1\n      <li>context sharing added for Microsoft Windows\n      <li>Macintosh support (by Paul Thiessen)\n      <li>Tcl/Tk stubs support &mdash; see README.tcl (by Jonas Beskow)\n    </ul>\n\n    <h3>Version 1.7 &mdash; January 6, 2006</h3>\n    <ul>\n      <li>added Mac OS X support\n      <li>enabled asking for quad-buffered stereo pixel formats on all platforms\n      (use -oldstereo on SGIs for splitscreen stereo &mdash; C API changed too)\n      <li>configuring the cursor is no longer slow\n      <li>added <code>-pixelformat</code> config flag\n      <li>added setgrid support (unfortunately many window managers can't cope with 1x1 pixel grid)\n      <li>only free context when last reference is gone\n      <li>switched to TEA-based configure (instead of editing make files)\n    </ul>\n\n    <h3>Version 2.0 &mdash; April 22, 2008</h3>\n    <ul>\n      <li>stubified C API\n      <li>replaced EPS support with TK photo image support\n      <li>simplified C API by requiring callback command options\n      <li>Added command arguments for create, destroy, etc. callbacks,\n      so there is a -createcommand option to the togl command (etc.).\n      (and removed Togl_*Func from the C API)\n      <li>added togl instance commands that call C API &mdash;\n      see <a href=\"tclapi.html\">documentation</a>\n      <li>use Tcl objects internally\n      <li>use Tcl object interface for callbacks\n      <li>vertical sync control\n      <li>fix thread safety in anticipation that OpenGL drivers may someday be thread safe\n      <li>added simple stereo rendering interface\n      <li>revised font C API\n      <li>updated font support for Tk 8.4 on all platforms\n      <li>updated documentation\n      <li>prebuilt binaries\n    </ul>\n\n    <h3>Version 2.1 &mdash; December 2009 </h3>\n    <ul>\n      <li>incorporate the part of the X11R6 Xmu library that Togl uses\n      so it will work on (Linux) systems that don't have the Xmu shared library\n      <li>Mac OS X Aqua delete context bug fix\n      <li>multisampling support\n      <li>pbuffer support (Unix/X11, Microsoft Windows, Mac OS X)\n      <li>Ability to copy context state\n      <li>row interleaved stereo support\n    </ul>\n\n    <br>\n    <h3>Future plans</h3>\n    Patches for the following are especially welcome:\n    <ul>\n      <li>Tk 8.5 fonts\n      <li>Aqua Cocoa support (Tk 8.6b2)\n      <li>OpenGL 3 contexts\n      <li>EGL support\n      <li>RGB overlays\n      <li>Tcl access to colormap manipulation\n      <li>NVidia consumer stereo support\n    </ul>\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/faq.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Togl Frequently Asked Questions</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Togl Frequently Asked Questions</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#badmatch\">Bad Match X errors on Sun systems</a>\n      <li><a href=\"#stereo\">Is stereo rendering supported?</a>\n      <li><a href=\"#fullscreen stereo\">Is fullscreen stereo rendering supported?</a>\n      <li><a href=\"#dc\">How do I get the Microsoft Windows device context?</a>\n      <li><a href=\"#python\">How do I use Togl from Python?</a>\n      <li><a href=\"#tile\">Is Togl compatible with Tile and Tk 8.5?</a>\n    </ul>\n    <h2>Frequently Asked Questions (and Problems)</h2>\n\n    <hr>\n\n    <p>\n    If you have something to add to this section please let us know.\n\n    <dl>\n      <dt>\n      <a name=\"badmatch\"><b>Bad Match X errors on Sun systems</b></a>\n      <dd>\n      There is(was?) a bug in Sun's XmuLookupStandardColormap\n      X library function.\n      If you compile togl.c with the SOLARIS_BUG symbol defined (-DSOLARIS_BUG)\n      this function call will be omitted.\n\n      <p>\n      <dt>\n      <a name=\"stereo\"><b>Is stereo rendering supported?</b></a>\n      <dd>\n      Several different <a href=\"stereo.html\">stereo modes</a> are supported.\n\n      <p>\n      <dt>\n      <a name=\"fullscreen stereo\"><b>Is fullscreen stereo rendering supported?</b></a>\n      <dd>\n      Before Tk 8.5,\n      Tk does not support true fullscreen windows.\n      Consequenly the full-screen stereo,\n      that gaming graphics cards support (ATI Radeon, NVidia GeForce),\n      won't be added until sometime after Tk 8.5 is available.\n      Fullscreen stereo on workstation graphics cards\n      (ATI FireGL, NVidia Quadro, Matrix Parhelia, 3Dlabs Wildcat)\n      does work.\n      <p>\n      <dt>\n      <a name=\"dc\"><b>How do I get the Microsoft Windows device context?</b></a>\n      <dd>\n      First call <code>Togl_MakeCurrent</code> to make sure you have the\n      right OpenGL context and device context set,\n      then call <code>wglGetCurrentDC</code>.\n\n      <p>\n      <dt>\n      <a name=\"python\"><b>How do I use Togl from Python?</b></a>\n      <dd>\n      The Togl source distribution comes with a <code>Togl.py</code> file\n      that provides a Tkinter-style Togl widget.\n      And for Togl callbacks that are C functions,\n      there is a <code>toglpy.h</code> file that provides a function\n      that converts a Python object into its corresponding Togl widget:\n      <blockquote>\n\t<code>Togl *getToglFromWidget(PyObject *widget)</code>\n      </blockquote>\n\n      <p>\n      <dt>\n      <a name=\"tile\"><b>Is Togl compatible with Tile and Tk 8.5?</b></a>\n      <dd>\n      Yes, Togl works as is (except for the bitmap font support for X11 and Aqua).\n      From <a href=\"http://wiki.tcl.tk/1218\">Joe English</a>:\n      <blockquote>\n\tComplex &quot;owner-draw&quot; widgets like tkZinc,\n\tor the text and canvas widgets,\n\treally don't benefit much from themability,\n\tso there's no reason to rewrite them.\n\t(<a href=\"http://wiki.tcl.tk/13373\">http://wiki.tcl.tk/13373</a>)\n      </blockquote>\n    </dl>\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/header.js",
    "content": "function displayHeader(pageTitle)\n{\n\tdocument.write(\"<center><h1>\" + pageTitle + \"</h1></center>\");\n}\n\nfunction NavigationBar()\n{\n\tdocument.write(\"<table rules='cols' cellpadding='4'>\");\n\tdocument.write(\" <tr>\");\n\tdocument.write(\" <td><a href='index.html'>Index</a></td>\");\n\tdocument.write(\" <td><a href='index.html#intro'>Intro</a></td>\");\n\tdocument.write(\" <td><a href='download.html'>Download/Install</a></td>\");\n\tdocument.write(\" <td><a href='using.html'>Using Togl</a></td>\");\n\tdocument.write(\" <td><a href='tclapi.html'>Tcl API</a></td>\");\n\tdocument.write(\" <td><a href='capi.html'>C API</a></td>\");\n\tdocument.write(\" <td><a href='faq.html'>FAQ</a></td>\");\n\tdocument.write(\" </tr>\");\n\tdocument.write(\"</table>\");\n\tdocument.write(\"<hr>\");\n}\n"
  },
  {
    "path": "ng/Togl2.1/doc/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Togl, a Tk OpenGL widget</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n\n    <h1 align=\"center\">Togl &mdash; a Tk OpenGL widget</h1>\n    <h3 align=\"center\">Copyright &copy; 1996-2009 Brian Paul, Ben Bederson, and Greg Couch</h3>\n\n    <h2>Index</h2>\n\n    <ul>\n      <li><a href=\"#intro\">Introduction</a>\n      <li><a href=\"download.html\">Download/Installation</a>\n      <li><a href=\"using.html\">Using the togl widget</a>\n      <ul>\n\t<li><a href=\"tclapi.html\">Tcl API</a>\n\t<li><a href=\"capi.html\">C API</a>\n\t<li><a href=\"upgrading.html\">Upgrading to version 2</a>\n      </ul>\n      <li><a href=\"faq.html\">Frequently Asked Questions (FAQ)</a>\n      <li><a href=\"#mailing\">Mailing List</a>\n      <li><a href=\"#bugs\">Reporting Bugs</a>\n      <li><a href=\"#contrib\">Contributors</a>\n    </ul>\n\n    <hr>\n\n    <h2><a name=\"intro\">Introduction</a></h2>\n\n    Togl is a <a href=\"http://www.tcl.tk/\">Tk</a> widget for\n    <a href=\"http://www.opengl.org/\">OpenGL</a> rendering.\n    Togl was originally based on OGLTK, written by Benjamin Bederson at\n    the University of New Mexico.\n\n    Togl's main features are:\n\n    <ul>\n      <li>unifies Microsoft Windows, X11 (Linux/IRIX/...), and Mac OS X Aqua support\n      <li>support for requesting stencil, accumulation, alpha buffers, <i>etc</i>.\n      <li>multiple OpenGL drawing windows\n      <li>simple stereo rendering support\n      <li>simple, portable font support\n      <li>color-index mode support including color allocation functions\n      <li>overlay plane support\n      <li>OpenGL extension testing from Tcl\n      <li>Tcl Extension Architecture (TEA) 3 compliant\n    </ul>\n\n    <p>\n    Togl does almost no OpenGL drawing itself,\n    instead it manages OpenGL drawing by calling various Tcl commands\n    (<i>a.k.a.</i>, callback functions).\n    Those commands can be C functions that call OpenGL (in)directly\n    or another Tcl package\n    (<i>e.g.</i>, <a href=\"http://www.tcl3d.org/\">Tcl3D</a>).\n\n    <p>\n    Togl is copyrighted by\n    <a href=\"http://www.mesa3d.org/brianp/home.html\">Brian Paul</a>\n    (brian_e_paulATyahooDOTcom),\n    <a href=\"http://www.cs.umd.edu/~bederson/\">Benjamin Bederson</a>\n    (bedersonATcsDOTumdDOTedu), and\n    <a href=\"http://www.cgl.ucsf.edu/chimera/\">Greg Couch</a>\n    (gregcouchATusersDOTsourceforgeDOTnet).\n    See the LICENSE file for details.\n\n    <p>\n    The <a href=\"http://www.sourceforge.net/projects/togl/\">\n      Togl project</a> and\n    <a href=\"http://togl.sourceforge.net\">home page</a> are\n    hosted by <a href=\"http://www.sourceforge.net\">SourceForge</a>.\n\n    <br>\n    <h2><a name=\"mailing\">Mailing list</a></h2>\n\n    <p>\n    See the <a href=\"http://www.sourceforge.net/projects/togl/\">\n      Togl project at SourceForge</a> for mailing list information.\n\n    <br>\n    <h2><a name=\"bugs\">Reporting Bugs</a></h2>\n\n    <p>\n    There is a bug database on the\n    <a href=\"http://sourceforge.net/projects/togl/\">Togl Project Page</a>.\n    You may also discuss bugs on the mailing list.\n    <p>\n    It may be worth upgrading your graphics driver and retesting\n    before reporting a bug,\n    as, historically,\n    many Togl &quot;bugs&quot; have been fixed by a graphics driver upgrade,\n    especially on Microsoft Windows.\n    <p>\n    When reporting bugs please provide as much information as possible.\n    Such as the version of Togl, which operating system\n    (<i>e,g.</i>, Microsoft Windows, Red Hat Linux, Mac OS X, <i>etc.</i>),\n    the version of the operating system,\n    and the version of the graphics driver.\n    Also, it's very helpful to us if you can provide an example program\n    which demonstrates the problem.\n\n    <br>\n    <h2><a name=\"contrib\">Contributors</a></h2>\n\n    <p>\n    Several people have contributed new features to Togl.  Among them are:\n\n    <ul>\n      <li>Ramon Ramsan &mdash; overlay plane support\n      <li>Miguel A. De Riera Pasenau &mdash; more overlay functions, X11 functions\n      and EPS output\n      <li>Peter Dern and Elmar Gerwalin &mdash; Togl_TimerFunc and related code\n      <li>Robert Casto &mdash; Microsoft Windows NT port\n      <li>Geza Groma &mdash; Microsoft Windows 95/NT patches\n      <li>Ben Evans &mdash; SGI stereo support\n      <li>Paul Thiessen &mdash; Macintosh support\n      <li>Jonas Beskow &mdash; Tcl/Tk stubs support\n      <li>Paul Kienzle &mdash; TEA debugging and patches\n      <li>Greg Couch &mdash; version 1.7, 2.0, 2.1\n    </ul>\n\n    Many others have contributed bug fixes.  Thanks for your contributions!\n\n    <br>\n    <hr>\n    Last edited on 4 February 2009 by Greg Couch.\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/stereo.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Togl Stereo Modes</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Togl Stereo Modes</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#none\">none</a>\n      <li><a href=\"#native\">native</a>\n      <li><a href=\"#anaglyph\">anaglyph</a>\n      <li><a href=\"#cross\">cross-eye</a>\n      <li><a href=\"#wall\">wall-eye</a>\n      <li><a href=\"#dti\">dti</a>\n      <li><a href=\"#row\">row interleaved</a>\n      <li><a href=\"#left\">left eye</a>\n      <li><a href=\"#right\">right eye</a>\n      <li><a href=\"#sgioldstyle\">sgioldstyle</a>\n      <!--\n      <li><a href=\"#nvidia\">nvidia consumer stereo</a>\n      -->\n    </ul>\n\n    <hr>\n\n    <p>\n    There are lots of stereo modes in Togl because there are many ways to\n    draw stereo with different tradeoffs.\n    All of the stereo modes are chosen with the\n    <a href=\"tclapi.html#pixelformat\">\n      <code>-stereo</code> configuration option</a>.\n    All of the non-native stereo techniques\n    are software-only and can be changed at anytime.\n    <p>\n    When using a non-native stereo mode, the OpenGL\n    <code>glDrawBuffer</code>, <code>glClear</code>,\n    <code>glFrustum</code>, and <code>glOrtho</code> calls\n    should be replaced with the Togl\n    <a href=\"tclapi.html#stereo cmds\">Tcl</a> or\n    <a href=\"capi.html#stereo\">C</a> versions\n    for seamless stereo rendering.\n    <p>\n    The various stereo modes are:\n    <dl>\n      <dt>\n      <a name=\"none\"></a><code>none</code> <i>or</i> &quot;&quot <i>or any false boolean value</i>\n      <dd>\n      Turn off stereo.\n      <dt><code>native</code> <i>or any true boolean value</i>\n      <dd>\n      Use native OpenGL hardware accelerated stereo\n      (single- or double-buffered for both the left and the right eyes).\n      Each eye is drawn at full window resolution\n      which gives the best stereo image.\n      This mode requires support from the graphics driver and is\n      typically only supported on workstation-class graphics cards, <i>e.g.</i>,\n      <a href=\"http://www.nvidia.com/page/workstation.html\">NVidia Quadro</a>,\n      <a href=\"http://ati.amd.com/products/workstation.html\">ATI FireGL</a>,\n      <a href=\"http://www.matrox.com/graphics/\">Matrix Parhelia</a>,\n      <a href=\"http://www.3dlabs.com/content/wildcat.asp\">3DLabs Wildcat</a>\n      graphics cards\n      and <a href=\"http://www.sgi.com/\">SGI</a> workstations.\n      The video refresh rate is changed automatically by the windowing system\n      except on SGI workstations.\n      Developers for SGI workstations can either switch the video manually with\n      <code>/usr/gfx/setmon</code> or <code>/usr/bin/X11/xsetmon</code>, or use the\n      <a href=\"http://www.cgl.ucsf.edu/Overview/software.html#autostereo\">\n\tautostereo</a> package.\n      <p>\n      Currently, there is a limitation that a togl widget can not be\n      reconfigured in or out of the native stereo mode.\n      And if/when it is supported,\n      some graphics drivers might not allow it.\n      <dt>\n      <a name=\"anaglyph\"></a><code>anaglyph</code>\n      <dd>\n      Draw the left eye in the red part of the color buffer\n      and the right eye in the blue and green parts.\n      Designed to be viewed with inexpensive red-blue or red-cyan glasses.\n      Works best with gray scale and non-saturated color images.\n      <dt>\n      <a name=\"cross\"></a><code>cross-eye</code>\n      <dd>\n      Draw right eye image on the left half of screen,\n      and draw left eye image on the right half of screen.\n      So each eye is drawn at less than half of the window resolution.\n      <dt>\n      <a name=\"wall\"></a><code>wall-eye</code>\n      <dd>\n      Draw left eye image on the left half of the screen,\n      and draw right eye image on the right half of the screen.\n      So each eye is drawn at less than half of the window resolution.\n      <dt>\n      <a name=\"dti\"></a><code>dti</code>\n      <dd>\n      Designed for <a href=\"http://www.dti3d.com/\">DTI</a> displays.\n      If you look at the window unassisted,\n      you'll see horizonally squished images\n      with the left eye image on the left,\n      and right eye image on the right.\n      So each eye is drawn at half of the window resolution.\n      <dt>\n      <a name=\"row\"></a><code>row interleaved</code>\n      <dd>\n      Designed for\n      <a href=\"http://www.vrex.com/\">VRex</a>,\n      <a href=\"http://www.zalman.co.kr/\">Zalman</a>, and\n      <a href=\"http://www.hyundaiq.com/\">Hyundai</a> displays.\n      Where the right eye is on the even scanlines\n      and the left is on the odd ones.\n      Requires that there be a stencil buffer\n      and uses the most significant stencil bit.\n      Changes to the stencil state should be placed within \n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml\">\n\tglPushAttrib</a>(GL_STENCIL_BUFFER_BIT) and glPopAttrib() calls.\n      <dt>\n      <a name=\"left\"></a><code>left eye</code>\n      <dd>\n      Only draw left eye view at full resolution.\n      <dt>\n      <a name=\"right\"></a><code>right eye</code>\n      <dd>\n      Only draw right eye view at full resolution.\n      <dt>\n      <a name=\"sgioldstyle\"></a><code>sgioldstyle</code>\n      <dd>\n      Support older-style SGI stereo where you lose half of the vertical resolution.\n      This uses the SGIStereo X extension,\n      that is only available on SGI workstations,\n      to tell the X server to duplicate non-stereo windows into both eyes.\n      This option only works when the monitor has been changed to the one\n      of the <code>str_top</code>, <code>str_bot</code>, or <code>str_rect</code> video output modes.\n      <!--\n      <dt>\n      <a name=\"nvidia\"></a><code>nvidia consumer stereo</code>\n      <dd>\n      Use the\n      <a href=\"http://www.nvidia.com/drivers\">NVidia Consumer 3D Stereo</a> driver.\n      This only works with NVidia consumer graphics cards on Microsoft Windows\n      and when the Togl window covers the full screen.\n      NVidia Quadro users should use the <code>native</code> stereo mode.\n      -->\n    </dl>\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/tclapi.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Togl Tcl API</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Togl Tcl API</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#tclfuncs\">Togl Tcl command</a>\n      <li><a href=\"#toglfuncs\">Togl widget commands</a>\n      <ul>\n\t<li><a href=\"#configuration\">Configuration Commands</a>\n\t<li><a href=\"#extensions\">Extensions Command</a>\n\t<li><a href=\"#rendering\">Rendering Commands</a>\n\t<li><a href=\"#image\">Image Commands</a>\n\t<li><a href=\"#font\">Font Commands</a>\n\t<li><a href=\"#overlay\">Overlay Commands</a>\n\t<li><a href=\"#stereo cmds\">OpenGL (Stereo) Commands</a>\n      </ul>\n      <li><a href=\"#options\">Togl configuration options</a>\n      <ul>\n\t<li><a href=\"#drawing\">Drawing callbacks</a>\n\t<li><a href=\"#geometry\">Geometry Options</a>\n\t<li><a href=\"#timer\">Timer Options</a>\n\t<li><a href=\"#stereo options\">Stereo Options</a>\n\t<li><a href=\"#miscellaneous\">Miscellaneous Options</a>\n\t<li><a href=\"#pixelformat\">Pixel Format Options</a>\n      </ul>\n    </ul>\n\n    <hr>\n\n    <h2><a name=\"tclfuncs\">Togl Tcl command</a></h2>\n\n    <p>\n    The togl command creates a new Tk widget, a Tcl command,\n    whose name is <var>pathName</var>.\n    This command may be used to invoke various operations on the widget.\n    <blockquote>\n      <code>togl <var>pathName</var> [<a href=\"#options\">options</a>]</code>\n    </blockquote>\n    If no options are given, a 400 by 400 pixel RGB window is created.\n    This command may be used to invoke various operations on the widget.\n\n    <h2><a name=\"toglfuncs\">Togl widget commands</a></h2>\n\n    The following commands are possible for an existing togl widget:\n\n    <h3><a name=\"configuration\">Configuration commands</a></h3>\n\n    <dl>\n      <dt><code><var>pathName</var> cget <var>-option</var></code>\n      <dd>\n      Return current value of given configuration option.\n    </dl>\n\n    <dl>\n      <dt>\n      <code><var>pathName</var> configure</code><br>\n      <code><var>pathName</var> configure <var>-option</var></code>\n      <dd>\n      If no <var>option</var> is given,\n      then return information about\n      all configuration <a href=\"#options\">options</a>.\n      Otherwise,\n      return configuration information for given <var>option</var>.\n      All configuration information consists of five values:\n      the configuration option name,\n      the option database name,\n      the option database class,\n      the default value,\n      and the current value.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> configure <var>-option</var> <var>value</var></code>\n      <dd>\n      Reconfigure a Togl widget.\n      <var>option</var> may be any one of the options listed below.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> contexttag</code>\n      <dd>\n      Returns an integer that represents the context tag.\n      All Togl widgets with the same context tag share display lists.\n    </dl>\n\n    <h3><a name=\"extensions\">Extensions command</a></h3>\n\n    <dl>\n      <dt><code><var>pathName</var> extensions</code>\n      <dd>\n      Returns a list of OpenGL extensions available.  For example:\n      <blockquote><pre><code>\nif {[lsearch [<i>pathName</i> extensions] GL_EXT_bgra] != -1]} {\n    ....\n}\n</code></pre></blockquote>\n      would check if the GL_EXT_bgra extension were supported.\n    </dl>\n\n    <h3><a name=\"rendering\">Rendering commands</a></h3>\n\n    <dl>\n      <dt><code><var>pathName</var> postredisplay</code>\n      <dd>\n      Cause the displaycommand callback to be called\n      the next time the event loop is idle.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> render</code>\n      <dd>\n      Causes the displaycommand callback to be called for <var>pathName</var>.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> swapbuffers</code>\n      <dd>\n      Causes front/back buffers to be swapped if in double buffer mode.\n      And flushes the OpenGL command buffer if in single buffer mode.\n      (So this is appropriate to call after every frame is drawn.)\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> makecurrent</code>\n      <dd>\n      Make the widget specified by <var>pathName</var> and its OpenGL context\n      the current ones.\n      This is implicitly called before any callback command is invoked.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> copycontextto <var>toPathName</var> <var>mask</var></code>\n      <dd>\n      Copy a subset of the OpenGL context state from <var>pathName</var> to\n      <var>toPathName</var> according the given mask.\n      The mask is an integer corresponding to the same values as\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml\">\n\tglPushAttrib</a>.\n    </dl>\n\n    <h3><a name=\"image\">Image commands</a></h3>\n\n    <dl>\n      <dt><code><var>pathName</var> takephoto <var>imagename</var></code>\n      <dd>\n      Copy the contents of the togl window into the given Tk photo image.\n      Transparency values are copied and should be fully opaque for windows\n      without alpha bitplanes.\n    </dl>\n\n    <h3><a name=\"font\">Font commands</a></h3>\n\n    <p>\n    These functions provide an interface to the simple bitmap font capabilities\n    that every OpenGL implementation provides.\n    Better font support is found in other packages, <i>e.g.</i>,\n    <a href=\"http://www.tcl3d.org/\">Tcl3D</a>\n    or with different <a href=\"capi.html#font\">C APIs</a>.\n\n    <dl>\n      <dt><code><var>pathName</var> loadbitmapfont <var>font</var></code>\n      <dd>\n      <var>font</var> can be any of font descriptions listed in the Tk\n      <a href=\"http://www.tcl.tk/man/tcl8.4/TkCmd/font.htm#M13\">font</a> command.\n      It returns a togl font object.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> unloadbitmapfont <var>toglfont</var></code>\n      <dd>\n      Releases the OpenGL resources needed by the <var>toglfont</var>.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> write <var>toglfont</var> [-pos <var>xyzw</var>] [-color <var>rgba</var>] <var>string</var></code>\n      <dd>\n      Write the given <var>string</var> in the given <var>toglfont</var>,\n      optionally at a particular position, <var>xyzw</var>\n      and color, <var>rgba</var>.\n      <var>xyzw</var> is either a 2, 3, or 4 element list of numbers.\n      <var>rgba</var> is either a 3 or 4 element list of numbers.\n    </dl>\n\n    <h3><a name=\"overlay\">Overlay Commands</a></h3>\n\n    <dl>\n      <dt><code><var>pathName</var> uselayer <var>layer</var></code>\n      <dd>\n      This is a variation on the <code>makecurrent</code> command\n      that makes the overlay OpenGL context current\n      if <var>layer</var> is 2\n      and makes the normal OpenGL context current\n      if <var>layer</var> is 1.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> showoverlay</code>\n      <dd>\n      Turn on drawing in the overlay planes.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> hideoverlay</code>\n      <dd>\n      Turn off drawing in the overlay planes.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> postredisplayoverlay</code>\n      <dd>\n      Cause the overlay OpenGL context to be redrawn the next time\n      the Tcl event loop is idle.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> renderoverlay</code>\n      <dd>\n      Causes the overlaydisplaycommand callback to be called for <var>pathName</var>.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> existsoverlay</code>\n      <dd>\n      Return true if togl widget has overlay planes.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> ismappedoverlay</code>\n      <dd>\n      Return true if overlay planes are shown.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> getoverlaytransparentvalue</code>\n      <dd>\n      Return overlay plane's transparent pixel value.\n    </dl>\n\n    <h3><a name=\"stereo cmds\">OpenGL (Stereo) Commands</a></h3>\n    These commands exist to support stereo rendering.\n    Just replace select OpenGL calls with the Togl versions\n    and stereo rendering will magically work.  And don't forget\n    to update the <a href=\"#stereo options\">stereo options</a>.\n\n    <dl>\n      <dt><code><var>pathName</var> drawbuffer <var>mode</var></code>\n      <dd>\n      Replaces calls to\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml\">\n\tglDrawBuffer</a>.\n      The mode is an integer.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> clear <var>mask</var></code>\n      <dd>\n      Replaces calls to\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml\">\n\tglClear</a>.\n      The mask is an integer.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> frustum <var>left right bottom top near far</var></code>\n      <dd>\n      Replaces calls to\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml\">\n\tglFrustum</a>.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> ortho <var>left right bottom top near far</var></code>\n      <dd>\n      Replaces calls to\n      <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml\">\n\tglOrtho</a>.\n    </dl>\n\n    <dl>\n      <dt><code><var>pathName</var> numeyes</code>\n      <dd>\n      Returns numbers of eyes &mdash; basically,\n      2 for stereo views and 1 for all others,\n      except some stereo views only need one eye from OpenGL.\n    </dl>\n\n    <h2><a name=\"options\">Togl configuration options</a></h2>\n\n    Togl's configuration options can be separated into several categories:\n    geometry, pixel format, and other.\n    The pixel format related options can only be set at widget creation time.\n    The other options can be changed dynamically\n    by the <code><var>pathName</var> configure</code> command (see above).\n\n    <h3><a name=\"drawing\">Drawing callbacks</a></h3>\n\n    <table border=\"0\">\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-createcommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-create</code>.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-displaycommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-display</code>.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-reshapecommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-reshape</code>.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-destroycommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-destroy</code>.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-overlaydisplaycommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-overlaydisplay</code>.\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <h3><a name=\"geometry\">Geometry Options</a></h3>\n\n    <table border=\"0\">\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-width</code></td>\n\t  <td align=\"center\">400</td>\n\t  <td>\n\t    Set width of widget in pixels.\n\t    It may have any of the forms accepted by <b>Tk_GetPixels</b>.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-height</code></td>\n\t  <td align=\"center\">400</td>\n\t  <td>\n\t    Set height of widget in pixels.\n\t    It may have any of the forms accepted by <b>Tk_GetPixels</b>(3).\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-setgrid</code></td>\n\t  <td align=\"center\">0</td>\n\t  <td>\n\t    Turn on gridded geometry management for togl widget's toplevel\n\t    window and specify the geometry of the grid.\n\t    See the manual pages for Tk's <b>wm</b>(n) and <b>Tk_SetGrid</b>(3)\n\t    for more information.\n\t    Unlike the <b>text</b> widget,\n\t    the same value is used for both width and height increments.\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <h3><a name=\"timer\">Timer Options</a></h3>\n\n    <table>\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-time</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>\n\t    Specifies the interval, in milliseconds, for\n\t    calling the timer callback function which\n\t    was registered with -timercommand.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-timercommand</code></td>\n\t  <td align=\"center\">{}</td>\n\t  <td>\n\t    Can be abbreviated <code>-timer</code>.\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <h3><a name=\"stereo options\">Stereo Options</a></h3>\n\n    <table>\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-eyeseparation</code></td>\n\t  <td align=\"center\">2.0</td>\n\t  <td>\n\t    Set the distance between the eyes in viewing coordinates.\n\t  </td>\n\t</tr>\n\n\t<tr valign=\"top\">\n\t  <td><code>-convergence</code></td>\n\t  <td align=\"center\">30.0</td>\n\t  <td>\n\t    Set the distance to the screen from the eye in viewing coordinates\n\t    (the distance at which the eyes converge).\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <blockquote>\n      You'd think these values would be given in physical units,\n      but there's no single right way to convert to viewing coordinates\n      from physical units.\n      So if you're willing to use Tk's idea of the horizontal size of a\n      window in millimeters (not always correct),\n      you could convert the average eye separation of 63 mm\n      to your viewing coordinates, and use that value as the eye separation.\n    </blockquote>\n\n    <h3><a name=\"miscellaneous\">Miscellaneous Options</a></h3>\n\n    <table>\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-cursor</code></td>\n\t  <td align=\"center\">\"\"</td>\n\t  <td>\n\t    Set the cursor in the widget window.\n\t  </td>\n\t</tr>\n\n\t<tr valign=\"top\">\n\t  <td><code>-swapinterval</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>\n\t    Set the minimum swap interval measure in video frame periods.\n\t    The default is 1 for for non-tearing artifacts\n\t    when swapping buffers.\n\t    Use a value of 0 when benchmarking frame rates.\n\t  </td>\n\t</tr>\n\n\t<tr valign=\"top\">\n\t  <td><code>-ident</code></td>\n\t  <td align=\"center\">\"\"</td>\n\t  <td>\n\t    A user identification string.  This is used match widgets\n\t    for the <code>-sharecontext</code>\n\t    and the <code>-sharelist</code> options (see below).\n\t    This is also useful in your callback functions\n\t    to determine which Togl widget is the caller.\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <h3><a name=\"pixelformat\">Pixel Format Options</a></h3>\n\n    The following options can only be given when the togl widget is created\n    &mdash; that is, unlike other options,\n    the togl widget can not be reconfigured with different values\n    for the following options after it is created.\n\n    <table border=\"0\">\n      <thead>\n\t<tr valign=\"top\">\n\t  <th>Option</th>\n\t  <th>Default</th>\n\t  <th>Comments</th>\n\t</tr>\n      </thead>\n      <tbody>\n\t<tr valign=\"top\">\n\t  <td><code>-rgba</code></td>\n\t  <td align=\"center\">true</td>\n\t  <td>If true, use RGB(A) mode, otherwise use Color Index mode.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-redsize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in red component.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td nowrap=\"nowrap\"><code>-greensize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in green component.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-bluesize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in blue component.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-alpha</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>\n\t    If true and <code>-rgba</code> is true, request an alpha channel.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-alphasize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in alpha component.</td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-double</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If true, request a double-buffered window, otherwise\n\t    request a single-buffered window.\n\t  </td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-depth</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>If true, request a depth buffer.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-depthsize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in depth buffer.</td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-accum</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>If true, request an accumulation buffer.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-accumredsize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in accumulation buffer red component.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td nowrap=\"nowrap\"><code>-accumgreensize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>\n\t    Minimum number of bits in accumulation buffer green component.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-accumbluesize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in accumulation buffer blue component.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-accumalphasize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>\n\t    Minimum number of bits in accumulation buffer alpha component.\n\t  </td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-stencil</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>If true, request a stencil buffer.</td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-stencilsize</code></td>\n\t  <td align=\"center\">1</td>\n\t  <td>Minimum number of bits in stencil component.</td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-auxbuffers</code></td>\n\t  <td align=\"center\">0</td>\n\t  <td>Desired number of auxiliary buffers.</td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-privatecmap</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    Only applicable in color index mode.\n\t    If false, use a shared read-only colormap.\n\t    If true, use a private read/write colormap.\n\t  </td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-overlay</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>If true, request overlay planes.</td>\n\t</tr>\n\n\t<tr><td colspan=\"3\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-stereo</code></td>\n\t  <td align=\"center\">mode</td>\n\t  <td>\n\t    See the <a href=\"stereo.html\">stereo</a> information\n\t    for details about the various modes.\n\t    Stereo parameters are changed with the\n\t    <a href=\"#stereo options\">stereo options</a>.\n\t    <p>\n\t    When using a non-native stereo mode, the OpenGL\n\t    <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml\">\n\t      glDrawBuffer</a>,\n\t    <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml\">\n\t      glClear</a>,\n\t    <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml\">\n\t      glFrustum</a>, and\n\t    <a href=\"http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml\">\n\t      glOrtho</a> calls\n\t    must be replaced with the Togl\n\t    <a href=\"#stereo cmds\">Tcl</a> or\n\t    <a href=\"capi.html#stereo\">C</a> versions.\n\t  </td>\n\t</tr>\n\n\t<tr><td colspan=\"3\" height=\"0\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-pbuffer</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If true, request off-screen framebuffer memory for the graphics.\n\t    The resulting togl widget should not be managed.\n\t  </td>\n\t</tr>\n\t<tr>\n\t  <td><code>-largestpbuffer</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If true, when asking for a pbuffer of a given size\n\t    and there isn't enough framebuffer memory available,\n\t    fallback to the largest size available.\n\t  </td>\n\t</tr>\n\n\t<tr><td colspan=\"3\" height=\"0\">&nbsp;</td></tr>\n\t<tr valign=\"top\">\n\t  <td><code>-multisample</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If true, request an multisampled rendering context.\n\t  </td>\n\t</tr>\n\n\t<!--\n\t<tr valign=\"top\">\n\t  <td><code>-fullscreen</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If true, request an multisampled rendering context.\n\t    <em>Requires Tcl/Tk 8.5 or newer on UNIX and Microsoft Windows platforms.</em>\n\t  </td>\n\t</tr>\n\t-->\n\n\t<tr valign=\"top\">\n\t  <td><code>-indirect</code></td>\n\t  <td align=\"center\">false</td>\n\t  <td>\n\t    If present, request an indirect rendering context.\n\t    A direct rendering context is normally requested.\n\t    <em>Only significant on Unix/X11.</em>\n\t  </td>\n\t</tr>\n\n\t<tr valign=\"top\">\n\t  <td><code>-sharelist</code></td>\n\t  <td align=\"center\">\"\"</td>\n\t  <td>\n\t    Togl identification string or window path name\n\t    of an existing Togl widget with which to share display lists.\n\t    If it is not possible to share display lists\n\t    between the two togl widgets\n\t    (depends on the graphics driver and the particular formats),\n\t    it fails.\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-sharecontext</code></td>\n\t  <td align=\"center\">\"\"</td>\n\t  <td>\n\t    Togl identification string or window path name\n\t    of an existing Togl widget with which to share the OpenGL context.\n\t    <i>Note:  all other pixel format options are ignored.</i>\n\t  </td>\n\t</tr>\n\t<tr valign=\"top\">\n\t  <td><code>-pixelformat</code></td>\n\t  <td align=\"center\">0</td>\n\t  <td>\n\t    Set the pixel format to the (platform-dependent) given value.\n\t    This is a backdoor into choosing a particular pixel format\n\t    that was determined by other means.\n\t  </td>\n\t</tr>\n      </tbody>\n    </table>\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/upgrading.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Upgrading to Version 2</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Upgrading to Version 2</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#callbacks\">Widget callback changes</a>\n      <li><a href=\"#subcommands\">Widget subcommand changes</a>\n      <li><a href=\"#stereo\">Stereo changes</a>\n      <li><a href=\"#fonts\">Font API changes</a>\n    </ul>\n\n    <hr>\n\n    <p>\n    Internally, Togl version 2 isn't very different from version 1,\n    and much of the C interface is the same.\n    The main difference is that the focus of the Togl API has changed\n    from being a C API to being a Tcl API.\n    Which means that the full power of Togl is accessible from Tcl\n    (the few exceptions are considered bugs).\n\n    <h2><a name=\"callbacks\">Widget callback changes</a></h2>\n\n    The biggest change is how the various callback are initialized.\n    In version 1,\n    the C API Togl_Set*Func functions had to be used\n    to setup the callback functions before creating the Togl widget.\n    And once the callbacks were set for a particular Togl widget,\n    they could not be changed.\n    If more than once Togl widget was needed,\n    the callback functions would need to be reset before each widget creation.\n    In version 2,\n    the callbacks are configuration arguments to the widget\n    and can be updated like any other standard widget configuration option.\n    See the <a href=\"tclapi.html\">Tcl API</a> for details.\n\n    <h2><a name=\"subcommands\">Widget subcommand changes</a></h2>\n\n    Version 1 also allowed new subcommands to be added\n    to the togl widget command via the C API.\n    This was dropped for a variety of reasons:\n    there is no exact Tcl equivalent,\n    there is no standard object-oriented technique\n    currently in the Tcl core (8.4.13),\n    it is unclear how to make the API thread safe,\n    and the internal Tcl C API doesn't support\n    dynamically changing sets of subcommands.\n    That said, this functionality might come back, especially when\n    <a href=\"http://www.tcl.tk/cgi-bin/tct/tip/\">TIP #257</a> is implemented.\n    Instead, in version 2,\n    create a Tcl function that takes the Togl widget as an argument.\n    Functions written in C can get the underlying Togl structure handle\n    with either the <code>Togl_GetToglFromObj</code>\n    or the <code>Togl_GetToglFromName</code> function,\n    as appropriate.\n    This means that there are no special Togl commands, only Tcl commands.\n    See the <a href=\"tclapi.html\">C API</a> for details.\n\n    <h2><a name=\"stereo\">Stereo changes</a></h2>\n\n    The stereo support has been totally revamped.\n    Some <a href=\"stereo.html\">form of stereo</a> is available all of the time.\n\n    <h2><a name=\"fonts\">Font changes</a></h2>\n\n    Tcl support for writing strings has been added.\n    <p>\n\n    The <a href=\"capi.html#font\">font C API</a> has been revised\n    so that Togl_LoadBitmapFont returns a font object instead an integer\n    (likewise for Togl_UnloadBitmapFont).\n    So instead of calling glListBase and glCallLists directly,\n    use Togl_WriteObj or Togl_WriteChars.\n    <p>\n    The TOGL_BITMAP_* constants remain for limited backwards\n    source compatibility and are deprecated.\n    The acceptable font names are now the same as Tk_GetFont\n    and the Tk font command on all platforms.\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/doc/using.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <!-- vi:set sw=2: -->\n  <!--\n  Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n  Copyright (C) 2005-2009  Greg Couch\n  See the LICENSE file for copyright details.\n  -->\n\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <title>Using the Togl Widget</title>\n  </head>\n\n  <body>\n    <script type=\"text/javascript\" src=\"header.js\"></script>\n    <script type=\"text/javascript\">\n      NavigationBar();\n    </script>\n\n    <h1 align=\"center\">Using the Togl Widget</h1>\n\n    <h2>Contents</h2>\n    <ul>\n      <li><a href=\"#using\">Using Togl With Your Application</a>\n      <li><a href=\"#examples\">Examples</a>\n      <li><a href=\"tclapi.html\">Tcl API</a>\n      <li><a href=\"capi.html\">C API</a>\n    </ul>\n\n    <hr>\n\n    <h2><a name=\"using\">Using Togl With Your Application</a></h2>\n\n    <p>\n    First, double check that you have all of the\n    <a href=\"download.html#prereq\">prerequisites</a>\n    and that you have\n    <a href=\"download.html#building\">compiled and installed</a> Togl.\n    <p>\n    Then, Togl acts like any other extension package &mdash;\n    to load it, you use the Tcl <code>package</code> command:\n    <blockquote>\n      <code>package require Togl 2.0</code>\n    </blockquote>\n    After that, you can create a Togl widget just like any other Tk widget.\n\n    <h2><a name=\"examples\">Examples</a></h2>\n\n    <p>\n    There are eight working examples:\n\n    <blockquote>\n      <table border=\"0\">\n\t<tr>\n\t  <td>double.tcl</td>\n\t  <td>&mdash; compares single vs double buffering with two Togl widgets</td>\n\t</tr>\n\t<tr>\n\t  <td>texture.tcl</td>\n\t  <td>&mdash; lets you play with texture mapping options</td>\n\t</tr>\n\t<tr>\n\t  <td>index.tcl</td>\n\t  <td>&mdash; example of using color index mode</td>\n\t</tr>\n\t<tr>\n\t  <td>overlay.tcl</td>\n\t  <td>&mdash; example of using overlay planes (requires overlay hardware)</td>\n\t</tr>\n\t<tr>\n\t  <td>stereo.tcl</td>\n\t  <td>&mdash; stereo example</td>\n\t</tr>\n\t<tr>\n\t  <td>gears.tcl</td>\n\t  <td>&mdash; spinning gears example</td>\n\t</tr>\n\t<tr>\n\t  <td>multisample.tcl</td>\n\t  <td>&mdash; multisampling example</td>\n\t</tr>\n\t<tr>\n\t  <td>pbuffer.tcl</td>\n\t  <td>&mdash; pbuffer (off-screen rendering) example</td>\n\t</tr>\n      </table>\n    </blockquote>\n\n    <p>\n    Each example consists of two files: a Tcl script for the user interface,\n    and a Tcl C package that does the OpenGL drawing.\n    To compile the examples, type <code>make examples</code>\n    in the Togl source directory.\n    The C packages are compiled into shared libraries\n    that are loaded into the Tcl interpreter as Tcl/Tk-extensions.\n    The examples are started by running the corresponding Tcl script:\n    just type <code>./double.tcl</code>\n    (or <code>./texture.tcl</code> <i>etc.</i>)\n    or run under one of the Tcl interpreters, <i>i.e.</i>,\n    <code>tclsh</code> or <code>wish</code>.\n    For example:\n    <blockquote>\n      <code>tclsh84 double.tcl</code>\n    </blockquote>\n\n    <p>\n    Other examples that use Tcl for OpenGL drawing can be found in the\n    <a href=\"http://tcl3d.org/html/demos.html\">Tcl3D demos</a>.\n\n    <h3><a name=\"callbacks\">Togl callbacks</a></h3>\n    <p>\n    All of the examples have similar structure.\n    First they create the user interface with one or more Togl widgets.\n    Each Togl widget is configured with the desired pixel format\n    and several callback commands (not all are needed):\n    <table>\n      <tr>\n\t<td><code>-createcommand</code></td>\n\t<td>\n\t  Called when Togl widget is mapped &mdash;\n\t  when it is safe to initialize the OpenGL context.\n\t</td>\n      </tr>\n      <tr>\n\t<td><code>-reshapecommand</code></td>\n\t<td>\n\t  Called when the Togl widget is resized &mdash;\n\t  when the OpenGL context's viewport needs to be changed.\n\t</td>\n      </tr>\n      <tr>\n\t<td><code>-displaycommand</code></td>\n\t<td>\n\t  Called when the contents of the Togl widget needs to be redrawn.\n\t  Redraws are normally delayed to be when the Tcl event loop is idle\n\t  (see the togl widget's <code>postredisplay</code> command),\n\t  or as the result of an explicit call to the togl's widgets\n\t  <code>render</code> command.\n\t</td>\n      </tr>\n      <tr>\n\t<td><code>-destroycommand</code></td>\n\t<td>\n\t  Called when the Togl widget is destroyed.\n\t  While OpenGL frees display lists and other resources,\n\t  sometimes there's some associated state that is no longer needed.\n\t</td>\n      </tr>\n      <tr>\n\t<td><code>-timercommand</code></td>\n\t<td>\n\t  Called every <i>n</i> milliseconds\n\t  as given by the <code>-time</code> option.\n\t</td>\n      </tr>\n      <tr>\n\t<td><code>-overlaydisplaycommand</code></td>\n\t<td>\n\t  Called when the overlay planes needs to be redrawn.\n\t  The overlay planes are created and reshaped\n\t  at the same time as the main OpenGL context.\n\t</td>\n      </tr>\n    </table>\n\n    Typically, only <code>-createcommand</code>, <code>-reshapecommand</code>\n    and <code>-displaycommand</code> are used.\n\n    <hr>\n    <a href=\"http://sourceforge.net/projects/togl\">\n      <img src=\"http://sflogo.sourceforge.net/sflogo.php?group_id=519&amp;type=13\" width=\"120\" height=\"30\" border=\"0\" alt=\"Get Togl at SourceForge.net. Fast, secure and Free Open Source software downloads\">\n    </a>\n    <a href=\"http://validator.w3.org/check?uri=referer\">\n      <img src=\"http://www.w3.org/Icons/valid-html401-blue\"\n      alt=\"Valid HTML 4.01 Transitional\" height=\"31\" width=\"88\" border=\"0\">\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "ng/Togl2.1/double.c",
    "content": "/* $Id: double.c,v 1.22 2009/03/12 23:59:35 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2007  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <math.h>\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\nstatic Tcl_Obj *toglFont;\nstatic double xAngle = 0, yAngle = 0, zAngle = 0;\nstatic GLdouble CornerX, CornerY, CornerZ;      /* where to print strings */\n\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (!toglFont)\n        toglFont = Togl_LoadBitmapFont(togl, \"Helvetica\");\n    if (!toglFont) {\n        static int shown;\n\n        if (!shown) {\n            fprintf(stderr, \"Couldn't load font!\\n\");\n            shown = 1;\n        }\n    }\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    double  aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (double) width / (double) height;\n\n    glViewport(0, 0, width, height);\n\n    /* Set up projection transform */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glFrustum(-aspect, aspect, -1, 1, 1, 10);\n\n    CornerX = -aspect;\n    CornerY = -1;\n    CornerZ = -1.1;\n\n    /* Change back to model view transform for rendering */\n    glMatrixMode(GL_MODELVIEW);\n\n    return TCL_OK;\n}\n\n\n\nstatic void\nprint_string(Togl *togl, const char *s)\n{\n    if (toglFont)\n        Togl_WriteChars(togl, toglFont, s, 0);\n}\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static GLuint cubeList = 0;\n    const char *ident;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK)\n        return TCL_ERROR;\n\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    glLoadIdentity();           /* Reset modelview matrix to the identity\n                                 * matrix */\n    glTranslatef(0, 0, -3);     /* Move the camera back three units */\n    glRotated(xAngle, 1, 0, 0); /* Rotate by X, Y, and Z angles */\n    glRotated(yAngle, 0, 1, 0);\n    glRotated(zAngle, 0, 0, 1);\n\n    glEnable(GL_DEPTH_TEST);\n\n    if (!cubeList) {\n        cubeList = glGenLists(1);\n        glNewList(cubeList, GL_COMPILE);\n\n        /* Front face */\n        glBegin(GL_QUADS);\n        glColor3f(0, 0.7f, 0.1f);       /* Green */\n        glVertex3f(-1, 1, 1);\n        glVertex3f(1, 1, 1);\n        glVertex3f(1, -1, 1);\n        glVertex3f(-1, -1, 1);\n        /* Back face */\n        glColor3f(0.9f, 1, 0);  /* Yellow */\n        glVertex3f(-1, 1, -1);\n        glVertex3f(1, 1, -1);\n        glVertex3f(1, -1, -1);\n        glVertex3f(-1, -1, -1);\n        /* Top side face */\n        glColor3f(0.2f, 0.2f, 1);       /* Blue */\n        glVertex3f(-1, 1, 1);\n        glVertex3f(1, 1, 1);\n        glVertex3f(1, 1, -1);\n        glVertex3f(-1, 1, -1);\n        /* Bottom side face */\n        glColor3f(0.7f, 0, 0.1f);       /* Red */\n        glVertex3f(-1, -1, 1);\n        glVertex3f(1, -1, 1);\n        glVertex3f(1, -1, -1);\n        glVertex3f(-1, -1, -1);\n        glEnd();\n\n        glEndList();\n\n    }\n    glCallList(cubeList);\n\n    glDisable(GL_DEPTH_TEST);\n    glLoadIdentity();\n    glColor3f(1, 1, 1);\n    glRasterPos3d(CornerX, CornerY, CornerZ);\n    ident = Togl_Ident(togl);\n    if (ident)\n        print_string(togl, ident);\n    Togl_SwapBuffers(togl);\n    return TCL_OK;\n}\n\n\n\n\nstatic int\nsetXrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"angle\");\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[1], &xAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* printf( \"before %f \", xAngle ); */\n\n    xAngle = fmod(xAngle, 360.0);\n    if (xAngle < 0)\n        xAngle += 360.0;\n\n    /* printf( \"after %f \\n\", xAngle ); */\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[1]);\n    return TCL_OK;\n}\n\n\nstatic int\nsetYrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName angle\");\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[1], &yAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    yAngle = fmod(yAngle, 360.0);\n    if (yAngle < 0)\n        yAngle += 360.0;\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[1]);\n    return TCL_OK;\n}\n\n/* \n * Called by Tcl to let me initialize the modules (Togl) I will need.\n */\nEXTERN int\nDouble_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"double::create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"double::display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"double::reshape_cb\", reshape_cb, NULL, NULL);\n\n    /* \n     * Make a new Togl widget command so the Tcl code can set a C variable.\n     */\n\n    Tcl_CreateObjCommand(interp, \"double::setXrot\", setXrot_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"double::setYrot\", setYrot_cb, NULL, NULL);\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/double.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: double.tcl,v 1.11 2009/03/12 23:59:35 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# An Tk/OpenGL widget demo with two windows, one single buffered and the\n# other double buffered.\n\npackage provide double 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/double[info sharedlibextension]\n\n# create ::double namespace\nnamespace eval ::double {\n}\n\nproc double::setup {} {\n    wm title . \"Single vs Double Buffering\"\n\n    # create first Togl widget\n    togl .o1 -width 200 -height 200 -rgba true -double false -depth true -ident \"Single Buffered\" -create double::create_cb -display double::display_cb -reshape double::reshape_cb\n\n    # create second Togl widget, share display lists with first widget\n    togl .o2 -width 200 -height 200 -rgba true -double true -depth true -ident \"Double Buffered\" -sharelist \"Single Buffered\" -create double::create_cb -display double::display_cb -reshape double::reshape_cb\n\n    scale .sx -label {X Axis} -from 0 -to 360 -command {::double::setAngle x} -orient horizontal\n    scale .sy -label {Y Axis} -from 0 -to 360 -command {::double::setAngle y} -orient horizontal\n    button .btn -text Quit -command exit\n\n    bind .o1 <B1-Motion> {\n\t::double::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    bind .o2 <B1-Motion> {\n\t::double::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    grid rowconfigure . 0 -weight 1\n    grid columnconfigure . 0 -weight 1 -uniform same\n    grid columnconfigure . 1 -weight 1 -uniform same\n    grid .o1 -row 0 -column 0 -sticky nesw -padx 3 -pady 3\n    grid .o2 -row 0 -column 1 -sticky nesw -padx 3 -pady 3\n    #grid .l1 -row 1 -column 0 -sticky ew -padx 3 -pady 3\n    #grid .l2 -row 1 -column 1 -sticky ew -padx 3 -pady 3\n    grid .sx -row 2 -column 0 -columnspan 2 -sticky ew\n    grid .sy -row 3 -column 0 -columnspan 2 -sticky ew\n    grid .btn -row 4 -column 0 -columnspan 2 -sticky ew\n}\n\n\n\n# This is called when mouse button 1 is pressed and moved in either of\n# the OpenGL windows.\nproc double::motion_event { width height x y } {\n    .sx set [double::setXrot [expr 360.0 * $y / $height]]\n    .sy set [double::setYrot [expr 360.0 * ($width - $x) / $width]]\n\n    .o1 postredisplay\n    .o2 postredisplay\n}\n\n# This is called when a slider is changed.\nproc double::setAngle {axis value} {\n    global xAngle yAngle zAngle\n\n    switch -exact $axis {\n\tx {double::setXrot $value\n\t   double::setXrot $value}\n\ty {double::setYrot $value\n\t   double::setYrot $value}\n    }\n\n    .o1 postredisplay\n    .o2 postredisplay\n}\n\n# Execution starts here!\nif { [info script] == $argv0 } {\n\t::double::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/gears.c",
    "content": "/* gears.c */\n\n/* \n * 3-D gear wheels.  This program is in the public domain.\n *\n * Brian Paul\n *\n *\n * Modified to work under Togl as a widget for TK 1997\n *\n * Philip Quaife\n *\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n#ifndef M_PI\n#  define M_PI 3.14159265\n#endif\n#define FM_PI ((float) M_PI)\n\n#ifdef _MSC_VER\n__inline float\nsinf(double a)\n{\n    return (float) sin(a);\n}\n__inline float\ncosf(double a)\n{\n    return (float) cos(a);\n}\n__inline float\nsqrtf(double a)\n{\n    return (float) sqrt(a);\n}\n\n#  define sin sinf\n#  define cos cosf\n#  define sqrt sqrtf\n#endif\n\nstruct WHIRLYGIZMO\n{\n    int     Gear1, Gear2, Gear3;\n    double  Rotx, Roty, Rotz;\n    double  Angle;\n    int     Height, Width;\n};\n\ntypedef struct WHIRLYGIZMO WHIRLYGIZMO;\n\n/* \n * Draw a gear wheel.  You'll probably want to call this function when\n * building a display list since we do a lot of trig here.\n *\n * Input:  inner_radius - radius of hole at center\n *         outer_radius - radius at center of teeth\n *         width - width of gear\n *         teeth - number of teeth\n *         tooth_depth - depth of tooth\n */\nstatic void\ngear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,\n        GLint teeth, GLfloat tooth_depth)\n{\n    GLint   i;\n    GLfloat r0, r1, r2;\n    GLfloat angle, da;\n    GLfloat u, v, len;\n\n    r0 = inner_radius;\n    r1 = outer_radius - tooth_depth / 2;\n    r2 = outer_radius + tooth_depth / 2;\n\n    da = 2 * FM_PI / teeth / 4;\n\n    glShadeModel(GL_FLAT);\n\n    glNormal3f(0, 0, 1);\n\n    /* draw front face */\n    glBegin(GL_QUAD_STRIP);\n    for (i = 0; i <= teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                width * 0.5f);\n    }\n    glEnd();\n\n    /* draw front sides of teeth */\n    glBegin(GL_QUADS);\n    da = 2 * FM_PI / teeth / 4;\n    for (i = 0; i < teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);\n        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5f);\n        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),\n                width * 0.5f);\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                width * 0.5f);\n    }\n    glEnd();\n\n\n    glNormal3f(0, 0, -1);\n\n    /* draw back face */\n    glBegin(GL_QUAD_STRIP);\n    for (i = 0; i <= teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                -width * 0.5f);\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);\n    }\n    glEnd();\n\n    /* draw back sides of teeth */\n    glBegin(GL_QUADS);\n    da = 2 * FM_PI / teeth / 4;\n    for (i = 0; i < teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                -width * 0.5f);\n        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),\n                -width * 0.5f);\n        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5f);\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);\n    }\n    glEnd();\n\n\n    /* draw outward faces of teeth */\n    glBegin(GL_QUAD_STRIP);\n    for (i = 0; i < teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);\n        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);\n        u = r2 * cos(angle + da) - r1 * cos(angle);\n        v = r2 * sin(angle + da) - r1 * sin(angle);\n        len = sqrt(u * u + v * v);\n        u /= len;\n        v /= len;\n        glNormal3f(v, -u, 0);\n        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5f);\n        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5f);\n        glNormal3f(cos(angle), sin(angle), 0);\n        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),\n                width * 0.5f);\n        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),\n                -width * 0.5f);\n        u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);\n        v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);\n        glNormal3f(v, -u, 0);\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                width * 0.5f);\n        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),\n                -width * 0.5f);\n        glNormal3f(cos(angle), sin(angle), 0);\n    }\n\n    glVertex3f(r1 /* * cos(0) */ , /* r1 * sin(0) */ 0, width * 0.5f);\n    glVertex3f(r1 /* * cos(0) */ , /* r1 * sin(0) */ 0, -width * 0.5f);\n\n    glEnd();\n\n\n    glShadeModel(GL_SMOOTH);\n\n    /* draw inside radius cylinder */\n    glBegin(GL_QUAD_STRIP);\n    for (i = 0; i <= teeth; i++) {\n        angle = i * 2 * FM_PI / teeth;\n        glNormal3f(-cos(angle), -sin(angle), 0);\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);\n        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);\n    }\n    glEnd();\n\n}\n\n/* \n * static GLfloat view_rotx=20, view_roty=30, view_rotz=0; static GLint\n * gear1, gear2, gear3; static GLfloat angle = 0; */\nstatic GLuint limit;\nstatic GLuint count = 1;\n\nstatic GLubyte polycolor[4] = { 255, 255, 255, 255 };\n\nstatic int\ndraw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    Wg = (WHIRLYGIZMO *) Togl_GetClientData(togl);\n    glDisable(GL_TEXTURE_2D);\n    glPushMatrix();\n    glRotatef((float) Wg->Rotx, 1, 0, 0);\n    glRotatef((float) Wg->Roty, 0, 1, 0);\n    glRotatef((float) Wg->Rotz, 0, 0, 1);\n\n    glPushMatrix();\n    glTranslatef(-3, -2, 0);\n    glRotatef((float) Wg->Angle, 0, 0, 1);\n    glEnable(GL_DEPTH_TEST);\n    glCallList(Wg->Gear1);\n    glEnable(GL_DEPTH_TEST);\n    glPopMatrix();\n\n    glPushMatrix();\n    glTranslatef(3.1f, -2, 0);\n    glRotatef(-2 * (float) Wg->Angle - 9, 0, 0, 1);\n    glCallList(Wg->Gear2);\n    glPopMatrix();\n\n    glPushMatrix();\n    glTranslatef(-3.1f, 4.2f, 0);\n    glRotatef(-2 * (float) Wg->Angle - 25, 0, 0, 1);\n    glCallList(Wg->Gear3);\n    glPopMatrix();\n\n    glPopMatrix();\n\n    Togl_SwapBuffers(togl);\n\n    return TCL_OK;\n}\n\n\nstatic int\nzap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Wg = (WHIRLYGIZMO *) Togl_GetClientData(togl);\n    free(Wg);\n\n    return TCL_OK;\n}\n\n\nstatic int\nidle(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Wg = (WHIRLYGIZMO *) Togl_GetClientData(togl);\n    Wg->Angle += 2;\n    Togl_PostRedisplay(togl);\n\n    return TCL_OK;\n}\n\n\n/* change view angle, exit upon ESC */\n/* \n * static GLenum key(int k, GLenum mask) { switch (k) { case TK_UP: view_rotx\n * += 5; return GL_TRUE; case TK_DOWN: view_rotx -= 5; return GL_TRUE; case \n * TK_LEFT: view_roty += 5; return GL_TRUE; case TK_RIGHT: view_roty -= 5;\n * return GL_TRUE; case TK_z: view_rotz += 5; return GL_TRUE; case TK_Z:\n * view_rotz -= 5; return GL_TRUE; } return GL_FALSE; } */\n\n/* new window size or exposure */\nstatic int\nreshape(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width, height;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    glViewport(0, 0, (GLint) width, (GLint) height);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    if (width > height) {\n        GLfloat w = (GLfloat) width / (GLfloat) height;\n\n        glFrustum(-w, w, -1, 1, 5, 60);\n    } else {\n        GLfloat h = (GLfloat) height / (GLfloat) width;\n\n        glFrustum(-1, 1, -h, h, 5, 60);\n    }\n\n    glMatrixMode(GL_MODELVIEW);\n    glLoadIdentity();\n    glTranslatef(0, 0, -40);\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    return TCL_OK;\n}\n\n\nstatic int\ninit(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    static GLfloat red[4] = { 0.8f, 0.1f, 0, 1 };\n    static GLfloat green[4] = { 0, 0.8f, 0.2f, 1 };\n    static GLfloat blue[4] = { 0.2f, 0.2f, 1, 1 };\n    static GLfloat pos[4] = { 5, 5, 10, 0 };\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    glLightfv(GL_LIGHT0, GL_POSITION, pos);\n    glEnable(GL_CULL_FACE);\n    glEnable(GL_LIGHTING);\n    glEnable(GL_LIGHT0);\n    glEnable(GL_DEPTH_TEST);\n    /* make the gears */\n    Wg = (WHIRLYGIZMO *) malloc(sizeof (WHIRLYGIZMO));\n    if (!Wg) {\n        Tcl_SetResult(Togl_Interp(togl),\n                \"\\\"Cannot allocate client data for widget\\\"\", TCL_STATIC);\n    }\n    Wg->Gear1 = glGenLists(1);\n    glNewList(Wg->Gear1, GL_COMPILE);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);\n    gear(1, 4, 1, 20, 0.7f);\n    glEndList();\n\n    Wg->Gear2 = glGenLists(1);\n    glNewList(Wg->Gear2, GL_COMPILE);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);\n    gear(0.5f, 2, 2, 10, 0.7f);\n    glEndList();\n\n    Wg->Gear3 = glGenLists(1);\n    glNewList(Wg->Gear3, GL_COMPILE);\n    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);\n    gear(1.3f, 2, 0.5f, 10, 0.7f);\n    glEndList();\n\n    glEnable(GL_NORMALIZE);\n    Wg->Height = Togl_Height(togl);\n    Wg->Width = Togl_Width(togl);\n    Wg->Angle = 0;\n    Wg->Rotx = 0;\n    Wg->Roty = 0;\n    Wg->Rotz = 0;\n    Togl_SetClientData(togl, (ClientData) Wg);\n\n    return TCL_OK;\n}\n\nstatic int\nposition(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    char    Result[100];\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Wg = (WHIRLYGIZMO *) Togl_GetClientData(togl);\n\n    /* Let result string equal value */\n    sprintf(Result, \"%g %g\", Wg->Roty, Wg->Rotx);\n\n    Tcl_SetResult(interp, Result, TCL_VOLATILE);\n    return TCL_OK;\n}\n\nstatic int\nrotate(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    WHIRLYGIZMO *Wg;\n    Togl   *togl;\n\n    if (objc != 4) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName yrot xrot\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Wg = (WHIRLYGIZMO *) Togl_GetClientData(togl);\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &Wg->Roty) != TCL_OK) {\n        return TCL_ERROR;\n    }\n    if (Tcl_GetDoubleFromObj(interp, objv[3], &Wg->Rotx) != TCL_OK) {\n        return TCL_ERROR;\n    }\n    Togl_PostRedisplay(togl);\n\n    return TCL_OK;\n}\n\nEXTERN int\nGears_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"init\", init, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"zap\", zap, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"draw\", draw, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape\", reshape, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"idle\", idle, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"rotate\", rotate, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"position\", position, NULL, NULL);\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/gears.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n#\n# Test Togl using GL Gears Demo\n#\n# Copyright (C) 1997 Philip Quaife\n#\n\npackage provide gears 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/gears[info sharedlibextension]\n\n# create ::gears namespace\nnamespace eval ::gears {\n}\n\nproc ::gears::setup {} {\n    global startx starty xangle0 yangle0 xangle yangle RotCnt\n    global vTime\n    set RotCnt 1\n    set xangle 0.0\n    set yangle 0.0\n    set vTime 100\n    wm title . \"Rotating Gear Widget Test\"\n\n    label .t -text \"Click and drag to rotate image\"\n    pack .t -side top -padx 2 -pady 10\n    frame .f\n    pack .f -side top\n    button .f.n1 -text \"  Add \" -command ::gears::AutoRot\n    button .f.r1 -text \"Remove\" -command ::gears::DelRot\n    button .f.b1 -text \" Quit \" -command exit \n    entry .f.t -width 4 -textvariable vTime\n    pack .f.n1 .f.t .f.r1 .f.b1 -side left -anchor w -padx 5\n    newRot .w0 10\n\n}\nproc ::gears::AutoRot {} {\n    global RotCnt vTime\n    newRot .w$RotCnt $vTime\n    set RotCnt [expr $RotCnt + 1]\n}\n\nproc ::gears::DelRot {} {\n    global RotCnt vTime\n    if { $RotCnt != 0 } {\n      set RotCnt [expr $RotCnt - 1]\n      destroy .w$RotCnt\n    }\n}\n\nproc ::gears::newRot {win {tick 100} } {\n    togl $win -width 200 -height 200 -rgba true -double true -depth true -privatecmap false -time $tick -create init -destroy zap -display draw -reshape reshape -timer idle\n    bind $win <ButtonPress-1> {::gears::RotStart %x %y %W}\n    bind $win <B1-Motion> {::gears::RotMove %x %y %W}\n    pack $win -expand true -fill both\n}\n\nproc ::gears::RotStart {x y W} {\n    global startx starty xangle0 yangle0 xangle yangle\n    set startx $x\n    set starty $y\n    set vPos [position $W]\n    set xangle0 [lindex $vPos 0]\n    set yangle0 [lindex $vPos 1]\n}\n\nproc ::gears::RotMove {x y W} {\n    global startx starty xangle0 yangle0 xangle yangle\n    set xangle [expr $xangle0 + ($x - $startx)]\n    set yangle [expr $yangle0 + ($y - $starty)]\n    rotate $W $xangle $yangle\n}\n\nif { [info script] == $argv0 } {\n\t::gears::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/gl/glext.h",
    "content": "#ifndef __glext_h_\n#define __glext_h_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n** Copyright (c) 2007 The Khronos Group Inc.\n** \n** Permission is hereby granted, free of charge, to any person obtaining a\n** copy of this software and/or associated documentation files (the\n** \"Materials\"), to deal in the Materials without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Materials, and to\n** permit persons to whom the Materials are furnished to do so, subject to\n** the following conditions:\n** \n** The above copyright notice and this permission notice shall be included\n** in all copies or substantial portions of the Materials.\n** \n** THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n*/\n\n#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)\n#define WIN32_LEAN_AND_MEAN 1\n#include <windows.h>\n#endif\n\n#ifndef APIENTRY\n#define APIENTRY\n#endif\n#ifndef APIENTRYP\n#define APIENTRYP APIENTRY *\n#endif\n#ifndef GLAPI\n#define GLAPI extern\n#endif\n\n/*************************************************************/\n\n/* Header file version number, required by OpenGL ABI for Linux */\n/* glext.h last updated 2008/11/14 */\n/* Current version at http://www.opengl.org/registry/ */\n#define GL_GLEXT_VERSION 44\n\n#ifndef GL_VERSION_1_2\n#define GL_UNSIGNED_BYTE_3_3_2            0x8032\n#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033\n#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034\n#define GL_UNSIGNED_INT_8_8_8_8           0x8035\n#define GL_UNSIGNED_INT_10_10_10_2        0x8036\n#define GL_RESCALE_NORMAL                 0x803A\n#define GL_TEXTURE_BINDING_3D             0x806A\n#define GL_PACK_SKIP_IMAGES               0x806B\n#define GL_PACK_IMAGE_HEIGHT              0x806C\n#define GL_UNPACK_SKIP_IMAGES             0x806D\n#define GL_UNPACK_IMAGE_HEIGHT            0x806E\n#define GL_TEXTURE_3D                     0x806F\n#define GL_PROXY_TEXTURE_3D               0x8070\n#define GL_TEXTURE_DEPTH                  0x8071\n#define GL_TEXTURE_WRAP_R                 0x8072\n#define GL_MAX_3D_TEXTURE_SIZE            0x8073\n#define GL_UNSIGNED_BYTE_2_3_3_REV        0x8362\n#define GL_UNSIGNED_SHORT_5_6_5           0x8363\n#define GL_UNSIGNED_SHORT_5_6_5_REV       0x8364\n#define GL_UNSIGNED_SHORT_4_4_4_4_REV     0x8365\n#define GL_UNSIGNED_SHORT_1_5_5_5_REV     0x8366\n#define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367\n#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368\n#define GL_BGR                            0x80E0\n#define GL_BGRA                           0x80E1\n#define GL_MAX_ELEMENTS_VERTICES          0x80E8\n#define GL_MAX_ELEMENTS_INDICES           0x80E9\n#define GL_CLAMP_TO_EDGE                  0x812F\n#define GL_TEXTURE_MIN_LOD                0x813A\n#define GL_TEXTURE_MAX_LOD                0x813B\n#define GL_TEXTURE_BASE_LEVEL             0x813C\n#define GL_TEXTURE_MAX_LEVEL              0x813D\n#define GL_LIGHT_MODEL_COLOR_CONTROL      0x81F8\n#define GL_SINGLE_COLOR                   0x81F9\n#define GL_SEPARATE_SPECULAR_COLOR        0x81FA\n#define GL_SMOOTH_POINT_SIZE_RANGE        0x0B12\n#define GL_SMOOTH_POINT_SIZE_GRANULARITY  0x0B13\n#define GL_SMOOTH_LINE_WIDTH_RANGE        0x0B22\n#define GL_SMOOTH_LINE_WIDTH_GRANULARITY  0x0B23\n#define GL_ALIASED_POINT_SIZE_RANGE       0x846D\n#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E\n#endif\n\n#ifndef GL_ARB_imaging\n#define GL_CONSTANT_COLOR                 0x8001\n#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002\n#define GL_CONSTANT_ALPHA                 0x8003\n#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004\n#define GL_BLEND_COLOR                    0x8005\n#define GL_FUNC_ADD                       0x8006\n#define GL_MIN                            0x8007\n#define GL_MAX                            0x8008\n#define GL_BLEND_EQUATION                 0x8009\n#define GL_FUNC_SUBTRACT                  0x800A\n#define GL_FUNC_REVERSE_SUBTRACT          0x800B\n#define GL_CONVOLUTION_1D                 0x8010\n#define GL_CONVOLUTION_2D                 0x8011\n#define GL_SEPARABLE_2D                   0x8012\n#define GL_CONVOLUTION_BORDER_MODE        0x8013\n#define GL_CONVOLUTION_FILTER_SCALE       0x8014\n#define GL_CONVOLUTION_FILTER_BIAS        0x8015\n#define GL_REDUCE                         0x8016\n#define GL_CONVOLUTION_FORMAT             0x8017\n#define GL_CONVOLUTION_WIDTH              0x8018\n#define GL_CONVOLUTION_HEIGHT             0x8019\n#define GL_MAX_CONVOLUTION_WIDTH          0x801A\n#define GL_MAX_CONVOLUTION_HEIGHT         0x801B\n#define GL_POST_CONVOLUTION_RED_SCALE     0x801C\n#define GL_POST_CONVOLUTION_GREEN_SCALE   0x801D\n#define GL_POST_CONVOLUTION_BLUE_SCALE    0x801E\n#define GL_POST_CONVOLUTION_ALPHA_SCALE   0x801F\n#define GL_POST_CONVOLUTION_RED_BIAS      0x8020\n#define GL_POST_CONVOLUTION_GREEN_BIAS    0x8021\n#define GL_POST_CONVOLUTION_BLUE_BIAS     0x8022\n#define GL_POST_CONVOLUTION_ALPHA_BIAS    0x8023\n#define GL_HISTOGRAM                      0x8024\n#define GL_PROXY_HISTOGRAM                0x8025\n#define GL_HISTOGRAM_WIDTH                0x8026\n#define GL_HISTOGRAM_FORMAT               0x8027\n#define GL_HISTOGRAM_RED_SIZE             0x8028\n#define GL_HISTOGRAM_GREEN_SIZE           0x8029\n#define GL_HISTOGRAM_BLUE_SIZE            0x802A\n#define GL_HISTOGRAM_ALPHA_SIZE           0x802B\n#define GL_HISTOGRAM_LUMINANCE_SIZE       0x802C\n#define GL_HISTOGRAM_SINK                 0x802D\n#define GL_MINMAX                         0x802E\n#define GL_MINMAX_FORMAT                  0x802F\n#define GL_MINMAX_SINK                    0x8030\n#define GL_TABLE_TOO_LARGE                0x8031\n#define GL_COLOR_MATRIX                   0x80B1\n#define GL_COLOR_MATRIX_STACK_DEPTH       0x80B2\n#define GL_MAX_COLOR_MATRIX_STACK_DEPTH   0x80B3\n#define GL_POST_COLOR_MATRIX_RED_SCALE    0x80B4\n#define GL_POST_COLOR_MATRIX_GREEN_SCALE  0x80B5\n#define GL_POST_COLOR_MATRIX_BLUE_SCALE   0x80B6\n#define GL_POST_COLOR_MATRIX_ALPHA_SCALE  0x80B7\n#define GL_POST_COLOR_MATRIX_RED_BIAS     0x80B8\n#define GL_POST_COLOR_MATRIX_GREEN_BIAS   0x80B9\n#define GL_POST_COLOR_MATRIX_BLUE_BIAS    0x80BA\n#define GL_POST_COLOR_MATRIX_ALPHA_BIAS   0x80BB\n#define GL_COLOR_TABLE                    0x80D0\n#define GL_POST_CONVOLUTION_COLOR_TABLE   0x80D1\n#define GL_POST_COLOR_MATRIX_COLOR_TABLE  0x80D2\n#define GL_PROXY_COLOR_TABLE              0x80D3\n#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4\n#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5\n#define GL_COLOR_TABLE_SCALE              0x80D6\n#define GL_COLOR_TABLE_BIAS               0x80D7\n#define GL_COLOR_TABLE_FORMAT             0x80D8\n#define GL_COLOR_TABLE_WIDTH              0x80D9\n#define GL_COLOR_TABLE_RED_SIZE           0x80DA\n#define GL_COLOR_TABLE_GREEN_SIZE         0x80DB\n#define GL_COLOR_TABLE_BLUE_SIZE          0x80DC\n#define GL_COLOR_TABLE_ALPHA_SIZE         0x80DD\n#define GL_COLOR_TABLE_LUMINANCE_SIZE     0x80DE\n#define GL_COLOR_TABLE_INTENSITY_SIZE     0x80DF\n#define GL_CONSTANT_BORDER                0x8151\n#define GL_REPLICATE_BORDER               0x8153\n#define GL_CONVOLUTION_BORDER_COLOR       0x8154\n#endif\n\n#ifndef GL_VERSION_1_3\n#define GL_TEXTURE0                       0x84C0\n#define GL_TEXTURE1                       0x84C1\n#define GL_TEXTURE2                       0x84C2\n#define GL_TEXTURE3                       0x84C3\n#define GL_TEXTURE4                       0x84C4\n#define GL_TEXTURE5                       0x84C5\n#define GL_TEXTURE6                       0x84C6\n#define GL_TEXTURE7                       0x84C7\n#define GL_TEXTURE8                       0x84C8\n#define GL_TEXTURE9                       0x84C9\n#define GL_TEXTURE10                      0x84CA\n#define GL_TEXTURE11                      0x84CB\n#define GL_TEXTURE12                      0x84CC\n#define GL_TEXTURE13                      0x84CD\n#define GL_TEXTURE14                      0x84CE\n#define GL_TEXTURE15                      0x84CF\n#define GL_TEXTURE16                      0x84D0\n#define GL_TEXTURE17                      0x84D1\n#define GL_TEXTURE18                      0x84D2\n#define GL_TEXTURE19                      0x84D3\n#define GL_TEXTURE20                      0x84D4\n#define GL_TEXTURE21                      0x84D5\n#define GL_TEXTURE22                      0x84D6\n#define GL_TEXTURE23                      0x84D7\n#define GL_TEXTURE24                      0x84D8\n#define GL_TEXTURE25                      0x84D9\n#define GL_TEXTURE26                      0x84DA\n#define GL_TEXTURE27                      0x84DB\n#define GL_TEXTURE28                      0x84DC\n#define GL_TEXTURE29                      0x84DD\n#define GL_TEXTURE30                      0x84DE\n#define GL_TEXTURE31                      0x84DF\n#define GL_ACTIVE_TEXTURE                 0x84E0\n#define GL_CLIENT_ACTIVE_TEXTURE          0x84E1\n#define GL_MAX_TEXTURE_UNITS              0x84E2\n#define GL_TRANSPOSE_MODELVIEW_MATRIX     0x84E3\n#define GL_TRANSPOSE_PROJECTION_MATRIX    0x84E4\n#define GL_TRANSPOSE_TEXTURE_MATRIX       0x84E5\n#define GL_TRANSPOSE_COLOR_MATRIX         0x84E6\n#define GL_MULTISAMPLE                    0x809D\n#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE            0x809F\n#define GL_SAMPLE_COVERAGE                0x80A0\n#define GL_SAMPLE_BUFFERS                 0x80A8\n#define GL_SAMPLES                        0x80A9\n#define GL_SAMPLE_COVERAGE_VALUE          0x80AA\n#define GL_SAMPLE_COVERAGE_INVERT         0x80AB\n#define GL_MULTISAMPLE_BIT                0x20000000\n#define GL_NORMAL_MAP                     0x8511\n#define GL_REFLECTION_MAP                 0x8512\n#define GL_TEXTURE_CUBE_MAP               0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP         0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C\n#define GL_COMPRESSED_ALPHA               0x84E9\n#define GL_COMPRESSED_LUMINANCE           0x84EA\n#define GL_COMPRESSED_LUMINANCE_ALPHA     0x84EB\n#define GL_COMPRESSED_INTENSITY           0x84EC\n#define GL_COMPRESSED_RGB                 0x84ED\n#define GL_COMPRESSED_RGBA                0x84EE\n#define GL_TEXTURE_COMPRESSION_HINT       0x84EF\n#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE  0x86A0\n#define GL_TEXTURE_COMPRESSED             0x86A1\n#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2\n#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3\n#define GL_CLAMP_TO_BORDER                0x812D\n#define GL_COMBINE                        0x8570\n#define GL_COMBINE_RGB                    0x8571\n#define GL_COMBINE_ALPHA                  0x8572\n#define GL_SOURCE0_RGB                    0x8580\n#define GL_SOURCE1_RGB                    0x8581\n#define GL_SOURCE2_RGB                    0x8582\n#define GL_SOURCE0_ALPHA                  0x8588\n#define GL_SOURCE1_ALPHA                  0x8589\n#define GL_SOURCE2_ALPHA                  0x858A\n#define GL_OPERAND0_RGB                   0x8590\n#define GL_OPERAND1_RGB                   0x8591\n#define GL_OPERAND2_RGB                   0x8592\n#define GL_OPERAND0_ALPHA                 0x8598\n#define GL_OPERAND1_ALPHA                 0x8599\n#define GL_OPERAND2_ALPHA                 0x859A\n#define GL_RGB_SCALE                      0x8573\n#define GL_ADD_SIGNED                     0x8574\n#define GL_INTERPOLATE                    0x8575\n#define GL_SUBTRACT                       0x84E7\n#define GL_CONSTANT                       0x8576\n#define GL_PRIMARY_COLOR                  0x8577\n#define GL_PREVIOUS                       0x8578\n#define GL_DOT3_RGB                       0x86AE\n#define GL_DOT3_RGBA                      0x86AF\n#endif\n\n#ifndef GL_VERSION_1_4\n#define GL_BLEND_DST_RGB                  0x80C8\n#define GL_BLEND_SRC_RGB                  0x80C9\n#define GL_BLEND_DST_ALPHA                0x80CA\n#define GL_BLEND_SRC_ALPHA                0x80CB\n#define GL_POINT_SIZE_MIN                 0x8126\n#define GL_POINT_SIZE_MAX                 0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE      0x8128\n#define GL_POINT_DISTANCE_ATTENUATION     0x8129\n#define GL_GENERATE_MIPMAP                0x8191\n#define GL_GENERATE_MIPMAP_HINT           0x8192\n#define GL_DEPTH_COMPONENT16              0x81A5\n#define GL_DEPTH_COMPONENT24              0x81A6\n#define GL_DEPTH_COMPONENT32              0x81A7\n#define GL_MIRRORED_REPEAT                0x8370\n#define GL_FOG_COORDINATE_SOURCE          0x8450\n#define GL_FOG_COORDINATE                 0x8451\n#define GL_FRAGMENT_DEPTH                 0x8452\n#define GL_CURRENT_FOG_COORDINATE         0x8453\n#define GL_FOG_COORDINATE_ARRAY_TYPE      0x8454\n#define GL_FOG_COORDINATE_ARRAY_STRIDE    0x8455\n#define GL_FOG_COORDINATE_ARRAY_POINTER   0x8456\n#define GL_FOG_COORDINATE_ARRAY           0x8457\n#define GL_COLOR_SUM                      0x8458\n#define GL_CURRENT_SECONDARY_COLOR        0x8459\n#define GL_SECONDARY_COLOR_ARRAY_SIZE     0x845A\n#define GL_SECONDARY_COLOR_ARRAY_TYPE     0x845B\n#define GL_SECONDARY_COLOR_ARRAY_STRIDE   0x845C\n#define GL_SECONDARY_COLOR_ARRAY_POINTER  0x845D\n#define GL_SECONDARY_COLOR_ARRAY          0x845E\n#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD\n#define GL_TEXTURE_FILTER_CONTROL         0x8500\n#define GL_TEXTURE_LOD_BIAS               0x8501\n#define GL_INCR_WRAP                      0x8507\n#define GL_DECR_WRAP                      0x8508\n#define GL_TEXTURE_DEPTH_SIZE             0x884A\n#define GL_DEPTH_TEXTURE_MODE             0x884B\n#define GL_TEXTURE_COMPARE_MODE           0x884C\n#define GL_TEXTURE_COMPARE_FUNC           0x884D\n#define GL_COMPARE_R_TO_TEXTURE           0x884E\n#endif\n\n#ifndef GL_VERSION_1_5\n#define GL_BUFFER_SIZE                    0x8764\n#define GL_BUFFER_USAGE                   0x8765\n#define GL_QUERY_COUNTER_BITS             0x8864\n#define GL_CURRENT_QUERY                  0x8865\n#define GL_QUERY_RESULT                   0x8866\n#define GL_QUERY_RESULT_AVAILABLE         0x8867\n#define GL_ARRAY_BUFFER                   0x8892\n#define GL_ELEMENT_ARRAY_BUFFER           0x8893\n#define GL_ARRAY_BUFFER_BINDING           0x8894\n#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895\n#define GL_VERTEX_ARRAY_BUFFER_BINDING    0x8896\n#define GL_NORMAL_ARRAY_BUFFER_BINDING    0x8897\n#define GL_COLOR_ARRAY_BUFFER_BINDING     0x8898\n#define GL_INDEX_ARRAY_BUFFER_BINDING     0x8899\n#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A\n#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B\n#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C\n#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D\n#define GL_WEIGHT_ARRAY_BUFFER_BINDING    0x889E\n#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F\n#define GL_READ_ONLY                      0x88B8\n#define GL_WRITE_ONLY                     0x88B9\n#define GL_READ_WRITE                     0x88BA\n#define GL_BUFFER_ACCESS                  0x88BB\n#define GL_BUFFER_MAPPED                  0x88BC\n#define GL_BUFFER_MAP_POINTER             0x88BD\n#define GL_STREAM_DRAW                    0x88E0\n#define GL_STREAM_READ                    0x88E1\n#define GL_STREAM_COPY                    0x88E2\n#define GL_STATIC_DRAW                    0x88E4\n#define GL_STATIC_READ                    0x88E5\n#define GL_STATIC_COPY                    0x88E6\n#define GL_DYNAMIC_DRAW                   0x88E8\n#define GL_DYNAMIC_READ                   0x88E9\n#define GL_DYNAMIC_COPY                   0x88EA\n#define GL_SAMPLES_PASSED                 0x8914\n#define GL_FOG_COORD_SRC                  GL_FOG_COORDINATE_SOURCE\n#define GL_FOG_COORD                      GL_FOG_COORDINATE\n#define GL_CURRENT_FOG_COORD              GL_CURRENT_FOG_COORDINATE\n#define GL_FOG_COORD_ARRAY_TYPE           GL_FOG_COORDINATE_ARRAY_TYPE\n#define GL_FOG_COORD_ARRAY_STRIDE         GL_FOG_COORDINATE_ARRAY_STRIDE\n#define GL_FOG_COORD_ARRAY_POINTER        GL_FOG_COORDINATE_ARRAY_POINTER\n#define GL_FOG_COORD_ARRAY                GL_FOG_COORDINATE_ARRAY\n#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING\n#define GL_SRC0_RGB                       GL_SOURCE0_RGB\n#define GL_SRC1_RGB                       GL_SOURCE1_RGB\n#define GL_SRC2_RGB                       GL_SOURCE2_RGB\n#define GL_SRC0_ALPHA                     GL_SOURCE0_ALPHA\n#define GL_SRC1_ALPHA                     GL_SOURCE1_ALPHA\n#define GL_SRC2_ALPHA                     GL_SOURCE2_ALPHA\n#endif\n\n#ifndef GL_VERSION_2_0\n#define GL_BLEND_EQUATION_RGB             GL_BLEND_EQUATION\n#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622\n#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623\n#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624\n#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625\n#define GL_CURRENT_VERTEX_ATTRIB          0x8626\n#define GL_VERTEX_PROGRAM_POINT_SIZE      0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE        0x8643\n#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645\n#define GL_STENCIL_BACK_FUNC              0x8800\n#define GL_STENCIL_BACK_FAIL              0x8801\n#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802\n#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803\n#define GL_MAX_DRAW_BUFFERS               0x8824\n#define GL_DRAW_BUFFER0                   0x8825\n#define GL_DRAW_BUFFER1                   0x8826\n#define GL_DRAW_BUFFER2                   0x8827\n#define GL_DRAW_BUFFER3                   0x8828\n#define GL_DRAW_BUFFER4                   0x8829\n#define GL_DRAW_BUFFER5                   0x882A\n#define GL_DRAW_BUFFER6                   0x882B\n#define GL_DRAW_BUFFER7                   0x882C\n#define GL_DRAW_BUFFER8                   0x882D\n#define GL_DRAW_BUFFER9                   0x882E\n#define GL_DRAW_BUFFER10                  0x882F\n#define GL_DRAW_BUFFER11                  0x8830\n#define GL_DRAW_BUFFER12                  0x8831\n#define GL_DRAW_BUFFER13                  0x8832\n#define GL_DRAW_BUFFER14                  0x8833\n#define GL_DRAW_BUFFER15                  0x8834\n#define GL_BLEND_EQUATION_ALPHA           0x883D\n#define GL_POINT_SPRITE                   0x8861\n#define GL_COORD_REPLACE                  0x8862\n#define GL_MAX_VERTEX_ATTRIBS             0x8869\n#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A\n#define GL_MAX_TEXTURE_COORDS             0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872\n#define GL_FRAGMENT_SHADER                0x8B30\n#define GL_VERTEX_SHADER                  0x8B31\n#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49\n#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A\n#define GL_MAX_VARYING_FLOATS             0x8B4B\n#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C\n#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D\n#define GL_SHADER_TYPE                    0x8B4F\n#define GL_FLOAT_VEC2                     0x8B50\n#define GL_FLOAT_VEC3                     0x8B51\n#define GL_FLOAT_VEC4                     0x8B52\n#define GL_INT_VEC2                       0x8B53\n#define GL_INT_VEC3                       0x8B54\n#define GL_INT_VEC4                       0x8B55\n#define GL_BOOL                           0x8B56\n#define GL_BOOL_VEC2                      0x8B57\n#define GL_BOOL_VEC3                      0x8B58\n#define GL_BOOL_VEC4                      0x8B59\n#define GL_FLOAT_MAT2                     0x8B5A\n#define GL_FLOAT_MAT3                     0x8B5B\n#define GL_FLOAT_MAT4                     0x8B5C\n#define GL_SAMPLER_1D                     0x8B5D\n#define GL_SAMPLER_2D                     0x8B5E\n#define GL_SAMPLER_3D                     0x8B5F\n#define GL_SAMPLER_CUBE                   0x8B60\n#define GL_SAMPLER_1D_SHADOW              0x8B61\n#define GL_SAMPLER_2D_SHADOW              0x8B62\n#define GL_DELETE_STATUS                  0x8B80\n#define GL_COMPILE_STATUS                 0x8B81\n#define GL_LINK_STATUS                    0x8B82\n#define GL_VALIDATE_STATUS                0x8B83\n#define GL_INFO_LOG_LENGTH                0x8B84\n#define GL_ATTACHED_SHADERS               0x8B85\n#define GL_ACTIVE_UNIFORMS                0x8B86\n#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87\n#define GL_SHADER_SOURCE_LENGTH           0x8B88\n#define GL_ACTIVE_ATTRIBUTES              0x8B89\n#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A\n#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B\n#define GL_SHADING_LANGUAGE_VERSION       0x8B8C\n#define GL_CURRENT_PROGRAM                0x8B8D\n#define GL_POINT_SPRITE_COORD_ORIGIN      0x8CA0\n#define GL_LOWER_LEFT                     0x8CA1\n#define GL_UPPER_LEFT                     0x8CA2\n#define GL_STENCIL_BACK_REF               0x8CA3\n#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4\n#define GL_STENCIL_BACK_WRITEMASK         0x8CA5\n#endif\n\n#ifndef GL_VERSION_2_1\n#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F\n#define GL_PIXEL_PACK_BUFFER              0x88EB\n#define GL_PIXEL_UNPACK_BUFFER            0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF\n#define GL_FLOAT_MAT2x3                   0x8B65\n#define GL_FLOAT_MAT2x4                   0x8B66\n#define GL_FLOAT_MAT3x2                   0x8B67\n#define GL_FLOAT_MAT3x4                   0x8B68\n#define GL_FLOAT_MAT4x2                   0x8B69\n#define GL_FLOAT_MAT4x3                   0x8B6A\n#define GL_SRGB                           0x8C40\n#define GL_SRGB8                          0x8C41\n#define GL_SRGB_ALPHA                     0x8C42\n#define GL_SRGB8_ALPHA8                   0x8C43\n#define GL_SLUMINANCE_ALPHA               0x8C44\n#define GL_SLUMINANCE8_ALPHA8             0x8C45\n#define GL_SLUMINANCE                     0x8C46\n#define GL_SLUMINANCE8                    0x8C47\n#define GL_COMPRESSED_SRGB                0x8C48\n#define GL_COMPRESSED_SRGB_ALPHA          0x8C49\n#define GL_COMPRESSED_SLUMINANCE          0x8C4A\n#define GL_COMPRESSED_SLUMINANCE_ALPHA    0x8C4B\n#endif\n\n#ifndef GL_VERSION_3_0\n#define GL_COMPARE_REF_TO_TEXTURE         GL_COMPARE_R_TO_TEXTURE_ARB\n#define GL_CLIP_DISTANCE0                 GL_CLIP_PLANE0\n#define GL_CLIP_DISTANCE1                 GL_CLIP_PLANE1\n#define GL_CLIP_DISTANCE2                 GL_CLIP_PLANE2\n#define GL_CLIP_DISTANCE3                 GL_CLIP_PLANE3\n#define GL_CLIP_DISTANCE4                 GL_CLIP_PLANE4\n#define GL_CLIP_DISTANCE5                 GL_CLIP_PLANE5\n#define GL_MAX_CLIP_DISTANCES             GL_MAX_CLIP_PLANES\n#define GL_MAJOR_VERSION                  0x821B\n#define GL_MINOR_VERSION                  0x821C\n#define GL_NUM_EXTENSIONS                 0x821D\n#define GL_CONTEXT_FLAGS                  0x821E\n#define GL_DEPTH_BUFFER                   0x8223\n#define GL_STENCIL_BUFFER                 0x8224\n#define GL_COMPRESSED_RED                 0x8225\n#define GL_COMPRESSED_RG                  0x8226\n#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001\n#define GL_RGBA32F                        0x8814\n#define GL_RGB32F                         0x8815\n#define GL_RGBA16F                        0x881A\n#define GL_RGB16F                         0x881B\n#define GL_VERTEX_ATTRIB_ARRAY_INTEGER    0x88FD\n#define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF\n#define GL_MIN_PROGRAM_TEXEL_OFFSET       0x8904\n#define GL_MAX_PROGRAM_TEXEL_OFFSET       0x8905\n#define GL_CLAMP_VERTEX_COLOR             0x891A\n#define GL_CLAMP_FRAGMENT_COLOR           0x891B\n#define GL_CLAMP_READ_COLOR               0x891C\n#define GL_FIXED_ONLY                     0x891D\n#define GL_MAX_VARYING_COMPONENTS         GL_MAX_VARYING_FLOATS\n#define GL_TEXTURE_RED_TYPE               0x8C10\n#define GL_TEXTURE_GREEN_TYPE             0x8C11\n#define GL_TEXTURE_BLUE_TYPE              0x8C12\n#define GL_TEXTURE_ALPHA_TYPE             0x8C13\n#define GL_TEXTURE_LUMINANCE_TYPE         0x8C14\n#define GL_TEXTURE_INTENSITY_TYPE         0x8C15\n#define GL_TEXTURE_DEPTH_TYPE             0x8C16\n#define GL_UNSIGNED_NORMALIZED            0x8C17\n#define GL_TEXTURE_1D_ARRAY               0x8C18\n#define GL_PROXY_TEXTURE_1D_ARRAY         0x8C19\n#define GL_TEXTURE_2D_ARRAY               0x8C1A\n#define GL_PROXY_TEXTURE_2D_ARRAY         0x8C1B\n#define GL_TEXTURE_BINDING_1D_ARRAY       0x8C1C\n#define GL_TEXTURE_BINDING_2D_ARRAY       0x8C1D\n#define GL_R11F_G11F_B10F                 0x8C3A\n#define GL_UNSIGNED_INT_10F_11F_11F_REV   0x8C3B\n#define GL_RGB9_E5                        0x8C3D\n#define GL_UNSIGNED_INT_5_9_9_9_REV       0x8C3E\n#define GL_TEXTURE_SHARED_SIZE            0x8C3F\n#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76\n#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80\n#define GL_TRANSFORM_FEEDBACK_VARYINGS    0x8C83\n#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84\n#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85\n#define GL_PRIMITIVES_GENERATED           0x8C87\n#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88\n#define GL_RASTERIZER_DISCARD             0x8C89\n#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B\n#define GL_INTERLEAVED_ATTRIBS            0x8C8C\n#define GL_SEPARATE_ATTRIBS               0x8C8D\n#define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F\n#define GL_RGBA32UI                       0x8D70\n#define GL_RGB32UI                        0x8D71\n#define GL_RGBA16UI                       0x8D76\n#define GL_RGB16UI                        0x8D77\n#define GL_RGBA8UI                        0x8D7C\n#define GL_RGB8UI                         0x8D7D\n#define GL_RGBA32I                        0x8D82\n#define GL_RGB32I                         0x8D83\n#define GL_RGBA16I                        0x8D88\n#define GL_RGB16I                         0x8D89\n#define GL_RGBA8I                         0x8D8E\n#define GL_RGB8I                          0x8D8F\n#define GL_RED_INTEGER                    0x8D94\n#define GL_GREEN_INTEGER                  0x8D95\n#define GL_BLUE_INTEGER                   0x8D96\n#define GL_ALPHA_INTEGER                  0x8D97\n#define GL_RGB_INTEGER                    0x8D98\n#define GL_RGBA_INTEGER                   0x8D99\n#define GL_BGR_INTEGER                    0x8D9A\n#define GL_BGRA_INTEGER                   0x8D9B\n#define GL_SAMPLER_1D_ARRAY               0x8DC0\n#define GL_SAMPLER_2D_ARRAY               0x8DC1\n#define GL_SAMPLER_1D_ARRAY_SHADOW        0x8DC3\n#define GL_SAMPLER_2D_ARRAY_SHADOW        0x8DC4\n#define GL_SAMPLER_CUBE_SHADOW            0x8DC5\n#define GL_UNSIGNED_INT_VEC2              0x8DC6\n#define GL_UNSIGNED_INT_VEC3              0x8DC7\n#define GL_UNSIGNED_INT_VEC4              0x8DC8\n#define GL_INT_SAMPLER_1D                 0x8DC9\n#define GL_INT_SAMPLER_2D                 0x8DCA\n#define GL_INT_SAMPLER_3D                 0x8DCB\n#define GL_INT_SAMPLER_CUBE               0x8DCC\n#define GL_INT_SAMPLER_1D_ARRAY           0x8DCE\n#define GL_INT_SAMPLER_2D_ARRAY           0x8DCF\n#define GL_UNSIGNED_INT_SAMPLER_1D        0x8DD1\n#define GL_UNSIGNED_INT_SAMPLER_2D        0x8DD2\n#define GL_UNSIGNED_INT_SAMPLER_3D        0x8DD3\n#define GL_UNSIGNED_INT_SAMPLER_CUBE      0x8DD4\n#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY  0x8DD6\n#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY  0x8DD7\n#define GL_QUERY_WAIT                     0x8E13\n#define GL_QUERY_NO_WAIT                  0x8E14\n#define GL_QUERY_BY_REGION_WAIT           0x8E15\n#define GL_QUERY_BY_REGION_NO_WAIT        0x8E16\n/* Reuse tokens from ARB_depth_buffer_float */\n/* reuse GL_DEPTH_COMPONENT32F */\n/* reuse GL_DEPTH32F_STENCIL8 */\n/* reuse GL_FLOAT_32_UNSIGNED_INT_24_8_REV */\n/* Reuse tokens from ARB_framebuffer_object */\n/* reuse GL_INVALID_FRAMEBUFFER_OPERATION */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */\n/* reuse GL_FRAMEBUFFER_DEFAULT */\n/* reuse GL_FRAMEBUFFER_UNDEFINED */\n/* reuse GL_DEPTH_STENCIL_ATTACHMENT */\n/* reuse GL_INDEX */\n/* reuse GL_MAX_RENDERBUFFER_SIZE */\n/* reuse GL_DEPTH_STENCIL */\n/* reuse GL_UNSIGNED_INT_24_8 */\n/* reuse GL_DEPTH24_STENCIL8 */\n/* reuse GL_TEXTURE_STENCIL_SIZE */\n/* reuse GL_TEXTURE_RED_TYPE */\n/* reuse GL_TEXTURE_GREEN_TYPE */\n/* reuse GL_TEXTURE_BLUE_TYPE */\n/* reuse GL_TEXTURE_ALPHA_TYPE */\n/* reuse GL_TEXTURE_LUMINANCE_TYPE */\n/* reuse GL_TEXTURE_INTENSITY_TYPE */\n/* reuse GL_TEXTURE_DEPTH_TYPE */\n/* reuse GL_UNSIGNED_NORMALIZED */\n/* reuse GL_FRAMEBUFFER_BINDING */\n/* reuse GL_DRAW_FRAMEBUFFER_BINDING */\n/* reuse GL_RENDERBUFFER_BINDING */\n/* reuse GL_READ_FRAMEBUFFER */\n/* reuse GL_DRAW_FRAMEBUFFER */\n/* reuse GL_READ_FRAMEBUFFER_BINDING */\n/* reuse GL_RENDERBUFFER_SAMPLES */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */\n/* reuse GL_FRAMEBUFFER_COMPLETE */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER */\n/* reuse GL_FRAMEBUFFER_UNSUPPORTED */\n/* reuse GL_MAX_COLOR_ATTACHMENTS */\n/* reuse GL_COLOR_ATTACHMENT0 */\n/* reuse GL_COLOR_ATTACHMENT1 */\n/* reuse GL_COLOR_ATTACHMENT2 */\n/* reuse GL_COLOR_ATTACHMENT3 */\n/* reuse GL_COLOR_ATTACHMENT4 */\n/* reuse GL_COLOR_ATTACHMENT5 */\n/* reuse GL_COLOR_ATTACHMENT6 */\n/* reuse GL_COLOR_ATTACHMENT7 */\n/* reuse GL_COLOR_ATTACHMENT8 */\n/* reuse GL_COLOR_ATTACHMENT9 */\n/* reuse GL_COLOR_ATTACHMENT10 */\n/* reuse GL_COLOR_ATTACHMENT11 */\n/* reuse GL_COLOR_ATTACHMENT12 */\n/* reuse GL_COLOR_ATTACHMENT13 */\n/* reuse GL_COLOR_ATTACHMENT14 */\n/* reuse GL_COLOR_ATTACHMENT15 */\n/* reuse GL_DEPTH_ATTACHMENT */\n/* reuse GL_STENCIL_ATTACHMENT */\n/* reuse GL_FRAMEBUFFER */\n/* reuse GL_RENDERBUFFER */\n/* reuse GL_RENDERBUFFER_WIDTH */\n/* reuse GL_RENDERBUFFER_HEIGHT */\n/* reuse GL_RENDERBUFFER_INTERNAL_FORMAT */\n/* reuse GL_STENCIL_INDEX1 */\n/* reuse GL_STENCIL_INDEX4 */\n/* reuse GL_STENCIL_INDEX8 */\n/* reuse GL_STENCIL_INDEX16 */\n/* reuse GL_RENDERBUFFER_RED_SIZE */\n/* reuse GL_RENDERBUFFER_GREEN_SIZE */\n/* reuse GL_RENDERBUFFER_BLUE_SIZE */\n/* reuse GL_RENDERBUFFER_ALPHA_SIZE */\n/* reuse GL_RENDERBUFFER_DEPTH_SIZE */\n/* reuse GL_RENDERBUFFER_STENCIL_SIZE */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */\n/* reuse GL_MAX_SAMPLES */\n/* Reuse tokens from ARB_framebuffer_sRGB */\n/* reuse GL_FRAMEBUFFER_SRGB */\n/* Reuse tokens from ARB_half_float_vertex */\n/* reuse GL_HALF_FLOAT */\n/* Reuse tokens from ARB_map_buffer_range */\n/* reuse GL_MAP_READ_BIT */\n/* reuse GL_MAP_WRITE_BIT */\n/* reuse GL_MAP_INVALIDATE_RANGE_BIT */\n/* reuse GL_MAP_INVALIDATE_BUFFER_BIT */\n/* reuse GL_MAP_FLUSH_EXPLICIT_BIT */\n/* reuse GL_MAP_UNSYNCHRONIZED_BIT */\n/* Reuse tokens from ARB_texture_compression_rgtc */\n/* reuse GL_COMPRESSED_RED_RGTC1 */\n/* reuse GL_COMPRESSED_SIGNED_RED_RGTC1 */\n/* reuse GL_COMPRESSED_RG_RGTC2 */\n/* reuse GL_COMPRESSED_SIGNED_RG_RGTC2 */\n/* Reuse tokens from ARB_texture_rg */\n/* reuse GL_RG */\n/* reuse GL_RG_INTEGER */\n/* reuse GL_R8 */\n/* reuse GL_R16 */\n/* reuse GL_RG8 */\n/* reuse GL_RG16 */\n/* reuse GL_R16F */\n/* reuse GL_R32F */\n/* reuse GL_RG16F */\n/* reuse GL_RG32F */\n/* reuse GL_R8I */\n/* reuse GL_R8UI */\n/* reuse GL_R16I */\n/* reuse GL_R16UI */\n/* reuse GL_R32I */\n/* reuse GL_R32UI */\n/* reuse GL_RG8I */\n/* reuse GL_RG8UI */\n/* reuse GL_RG16I */\n/* reuse GL_RG16UI */\n/* reuse GL_RG32I */\n/* reuse GL_RG32UI */\n/* Reuse tokens from ARB_vertex_array_object */\n/* reuse GL_VERTEX_ARRAY_BINDING */\n#endif\n\n#ifndef GL_ARB_multitexture\n#define GL_TEXTURE0_ARB                   0x84C0\n#define GL_TEXTURE1_ARB                   0x84C1\n#define GL_TEXTURE2_ARB                   0x84C2\n#define GL_TEXTURE3_ARB                   0x84C3\n#define GL_TEXTURE4_ARB                   0x84C4\n#define GL_TEXTURE5_ARB                   0x84C5\n#define GL_TEXTURE6_ARB                   0x84C6\n#define GL_TEXTURE7_ARB                   0x84C7\n#define GL_TEXTURE8_ARB                   0x84C8\n#define GL_TEXTURE9_ARB                   0x84C9\n#define GL_TEXTURE10_ARB                  0x84CA\n#define GL_TEXTURE11_ARB                  0x84CB\n#define GL_TEXTURE12_ARB                  0x84CC\n#define GL_TEXTURE13_ARB                  0x84CD\n#define GL_TEXTURE14_ARB                  0x84CE\n#define GL_TEXTURE15_ARB                  0x84CF\n#define GL_TEXTURE16_ARB                  0x84D0\n#define GL_TEXTURE17_ARB                  0x84D1\n#define GL_TEXTURE18_ARB                  0x84D2\n#define GL_TEXTURE19_ARB                  0x84D3\n#define GL_TEXTURE20_ARB                  0x84D4\n#define GL_TEXTURE21_ARB                  0x84D5\n#define GL_TEXTURE22_ARB                  0x84D6\n#define GL_TEXTURE23_ARB                  0x84D7\n#define GL_TEXTURE24_ARB                  0x84D8\n#define GL_TEXTURE25_ARB                  0x84D9\n#define GL_TEXTURE26_ARB                  0x84DA\n#define GL_TEXTURE27_ARB                  0x84DB\n#define GL_TEXTURE28_ARB                  0x84DC\n#define GL_TEXTURE29_ARB                  0x84DD\n#define GL_TEXTURE30_ARB                  0x84DE\n#define GL_TEXTURE31_ARB                  0x84DF\n#define GL_ACTIVE_TEXTURE_ARB             0x84E0\n#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1\n#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2\n#endif\n\n#ifndef GL_ARB_transpose_matrix\n#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3\n#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4\n#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB   0x84E5\n#define GL_TRANSPOSE_COLOR_MATRIX_ARB     0x84E6\n#endif\n\n#ifndef GL_ARB_multisample\n#define GL_MULTISAMPLE_ARB                0x809D\n#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB   0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_ARB        0x809F\n#define GL_SAMPLE_COVERAGE_ARB            0x80A0\n#define GL_SAMPLE_BUFFERS_ARB             0x80A8\n#define GL_SAMPLES_ARB                    0x80A9\n#define GL_SAMPLE_COVERAGE_VALUE_ARB      0x80AA\n#define GL_SAMPLE_COVERAGE_INVERT_ARB     0x80AB\n#define GL_MULTISAMPLE_BIT_ARB            0x20000000\n#endif\n\n#ifndef GL_ARB_texture_env_add\n#endif\n\n#ifndef GL_ARB_texture_cube_map\n#define GL_NORMAL_MAP_ARB                 0x8511\n#define GL_REFLECTION_MAP_ARB             0x8512\n#define GL_TEXTURE_CUBE_MAP_ARB           0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP_ARB   0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP_ARB     0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB  0x851C\n#endif\n\n#ifndef GL_ARB_texture_compression\n#define GL_COMPRESSED_ALPHA_ARB           0x84E9\n#define GL_COMPRESSED_LUMINANCE_ARB       0x84EA\n#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB\n#define GL_COMPRESSED_INTENSITY_ARB       0x84EC\n#define GL_COMPRESSED_RGB_ARB             0x84ED\n#define GL_COMPRESSED_RGBA_ARB            0x84EE\n#define GL_TEXTURE_COMPRESSION_HINT_ARB   0x84EF\n#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0\n#define GL_TEXTURE_COMPRESSED_ARB         0x86A1\n#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2\n#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3\n#endif\n\n#ifndef GL_ARB_texture_border_clamp\n#define GL_CLAMP_TO_BORDER_ARB            0x812D\n#endif\n\n#ifndef GL_ARB_point_parameters\n#define GL_POINT_SIZE_MIN_ARB             0x8126\n#define GL_POINT_SIZE_MAX_ARB             0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_ARB  0x8128\n#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129\n#endif\n\n#ifndef GL_ARB_vertex_blend\n#define GL_MAX_VERTEX_UNITS_ARB           0x86A4\n#define GL_ACTIVE_VERTEX_UNITS_ARB        0x86A5\n#define GL_WEIGHT_SUM_UNITY_ARB           0x86A6\n#define GL_VERTEX_BLEND_ARB               0x86A7\n#define GL_CURRENT_WEIGHT_ARB             0x86A8\n#define GL_WEIGHT_ARRAY_TYPE_ARB          0x86A9\n#define GL_WEIGHT_ARRAY_STRIDE_ARB        0x86AA\n#define GL_WEIGHT_ARRAY_SIZE_ARB          0x86AB\n#define GL_WEIGHT_ARRAY_POINTER_ARB       0x86AC\n#define GL_WEIGHT_ARRAY_ARB               0x86AD\n#define GL_MODELVIEW0_ARB                 0x1700\n#define GL_MODELVIEW1_ARB                 0x850A\n#define GL_MODELVIEW2_ARB                 0x8722\n#define GL_MODELVIEW3_ARB                 0x8723\n#define GL_MODELVIEW4_ARB                 0x8724\n#define GL_MODELVIEW5_ARB                 0x8725\n#define GL_MODELVIEW6_ARB                 0x8726\n#define GL_MODELVIEW7_ARB                 0x8727\n#define GL_MODELVIEW8_ARB                 0x8728\n#define GL_MODELVIEW9_ARB                 0x8729\n#define GL_MODELVIEW10_ARB                0x872A\n#define GL_MODELVIEW11_ARB                0x872B\n#define GL_MODELVIEW12_ARB                0x872C\n#define GL_MODELVIEW13_ARB                0x872D\n#define GL_MODELVIEW14_ARB                0x872E\n#define GL_MODELVIEW15_ARB                0x872F\n#define GL_MODELVIEW16_ARB                0x8730\n#define GL_MODELVIEW17_ARB                0x8731\n#define GL_MODELVIEW18_ARB                0x8732\n#define GL_MODELVIEW19_ARB                0x8733\n#define GL_MODELVIEW20_ARB                0x8734\n#define GL_MODELVIEW21_ARB                0x8735\n#define GL_MODELVIEW22_ARB                0x8736\n#define GL_MODELVIEW23_ARB                0x8737\n#define GL_MODELVIEW24_ARB                0x8738\n#define GL_MODELVIEW25_ARB                0x8739\n#define GL_MODELVIEW26_ARB                0x873A\n#define GL_MODELVIEW27_ARB                0x873B\n#define GL_MODELVIEW28_ARB                0x873C\n#define GL_MODELVIEW29_ARB                0x873D\n#define GL_MODELVIEW30_ARB                0x873E\n#define GL_MODELVIEW31_ARB                0x873F\n#endif\n\n#ifndef GL_ARB_matrix_palette\n#define GL_MATRIX_PALETTE_ARB             0x8840\n#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841\n#define GL_MAX_PALETTE_MATRICES_ARB       0x8842\n#define GL_CURRENT_PALETTE_MATRIX_ARB     0x8843\n#define GL_MATRIX_INDEX_ARRAY_ARB         0x8844\n#define GL_CURRENT_MATRIX_INDEX_ARB       0x8845\n#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB    0x8846\n#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB    0x8847\n#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB  0x8848\n#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849\n#endif\n\n#ifndef GL_ARB_texture_env_combine\n#define GL_COMBINE_ARB                    0x8570\n#define GL_COMBINE_RGB_ARB                0x8571\n#define GL_COMBINE_ALPHA_ARB              0x8572\n#define GL_SOURCE0_RGB_ARB                0x8580\n#define GL_SOURCE1_RGB_ARB                0x8581\n#define GL_SOURCE2_RGB_ARB                0x8582\n#define GL_SOURCE0_ALPHA_ARB              0x8588\n#define GL_SOURCE1_ALPHA_ARB              0x8589\n#define GL_SOURCE2_ALPHA_ARB              0x858A\n#define GL_OPERAND0_RGB_ARB               0x8590\n#define GL_OPERAND1_RGB_ARB               0x8591\n#define GL_OPERAND2_RGB_ARB               0x8592\n#define GL_OPERAND0_ALPHA_ARB             0x8598\n#define GL_OPERAND1_ALPHA_ARB             0x8599\n#define GL_OPERAND2_ALPHA_ARB             0x859A\n#define GL_RGB_SCALE_ARB                  0x8573\n#define GL_ADD_SIGNED_ARB                 0x8574\n#define GL_INTERPOLATE_ARB                0x8575\n#define GL_SUBTRACT_ARB                   0x84E7\n#define GL_CONSTANT_ARB                   0x8576\n#define GL_PRIMARY_COLOR_ARB              0x8577\n#define GL_PREVIOUS_ARB                   0x8578\n#endif\n\n#ifndef GL_ARB_texture_env_crossbar\n#endif\n\n#ifndef GL_ARB_texture_env_dot3\n#define GL_DOT3_RGB_ARB                   0x86AE\n#define GL_DOT3_RGBA_ARB                  0x86AF\n#endif\n\n#ifndef GL_ARB_texture_mirrored_repeat\n#define GL_MIRRORED_REPEAT_ARB            0x8370\n#endif\n\n#ifndef GL_ARB_depth_texture\n#define GL_DEPTH_COMPONENT16_ARB          0x81A5\n#define GL_DEPTH_COMPONENT24_ARB          0x81A6\n#define GL_DEPTH_COMPONENT32_ARB          0x81A7\n#define GL_TEXTURE_DEPTH_SIZE_ARB         0x884A\n#define GL_DEPTH_TEXTURE_MODE_ARB         0x884B\n#endif\n\n#ifndef GL_ARB_shadow\n#define GL_TEXTURE_COMPARE_MODE_ARB       0x884C\n#define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D\n#define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E\n#endif\n\n#ifndef GL_ARB_shadow_ambient\n#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF\n#endif\n\n#ifndef GL_ARB_window_pos\n#endif\n\n#ifndef GL_ARB_vertex_program\n#define GL_COLOR_SUM_ARB                  0x8458\n#define GL_VERTEX_PROGRAM_ARB             0x8620\n#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622\n#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB   0x8623\n#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624\n#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB   0x8625\n#define GL_CURRENT_VERTEX_ATTRIB_ARB      0x8626\n#define GL_PROGRAM_LENGTH_ARB             0x8627\n#define GL_PROGRAM_STRING_ARB             0x8628\n#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E\n#define GL_MAX_PROGRAM_MATRICES_ARB       0x862F\n#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640\n#define GL_CURRENT_MATRIX_ARB             0x8641\n#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB    0x8643\n#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645\n#define GL_PROGRAM_ERROR_POSITION_ARB     0x864B\n#define GL_PROGRAM_BINDING_ARB            0x8677\n#define GL_MAX_VERTEX_ATTRIBS_ARB         0x8869\n#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A\n#define GL_PROGRAM_ERROR_STRING_ARB       0x8874\n#define GL_PROGRAM_FORMAT_ASCII_ARB       0x8875\n#define GL_PROGRAM_FORMAT_ARB             0x8876\n#define GL_PROGRAM_INSTRUCTIONS_ARB       0x88A0\n#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB   0x88A1\n#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2\n#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3\n#define GL_PROGRAM_TEMPORARIES_ARB        0x88A4\n#define GL_MAX_PROGRAM_TEMPORARIES_ARB    0x88A5\n#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6\n#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7\n#define GL_PROGRAM_PARAMETERS_ARB         0x88A8\n#define GL_MAX_PROGRAM_PARAMETERS_ARB     0x88A9\n#define GL_PROGRAM_NATIVE_PARAMETERS_ARB  0x88AA\n#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB\n#define GL_PROGRAM_ATTRIBS_ARB            0x88AC\n#define GL_MAX_PROGRAM_ATTRIBS_ARB        0x88AD\n#define GL_PROGRAM_NATIVE_ATTRIBS_ARB     0x88AE\n#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF\n#define GL_PROGRAM_ADDRESS_REGISTERS_ARB  0x88B0\n#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1\n#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2\n#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3\n#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4\n#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5\n#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6\n#define GL_TRANSPOSE_CURRENT_MATRIX_ARB   0x88B7\n#define GL_MATRIX0_ARB                    0x88C0\n#define GL_MATRIX1_ARB                    0x88C1\n#define GL_MATRIX2_ARB                    0x88C2\n#define GL_MATRIX3_ARB                    0x88C3\n#define GL_MATRIX4_ARB                    0x88C4\n#define GL_MATRIX5_ARB                    0x88C5\n#define GL_MATRIX6_ARB                    0x88C6\n#define GL_MATRIX7_ARB                    0x88C7\n#define GL_MATRIX8_ARB                    0x88C8\n#define GL_MATRIX9_ARB                    0x88C9\n#define GL_MATRIX10_ARB                   0x88CA\n#define GL_MATRIX11_ARB                   0x88CB\n#define GL_MATRIX12_ARB                   0x88CC\n#define GL_MATRIX13_ARB                   0x88CD\n#define GL_MATRIX14_ARB                   0x88CE\n#define GL_MATRIX15_ARB                   0x88CF\n#define GL_MATRIX16_ARB                   0x88D0\n#define GL_MATRIX17_ARB                   0x88D1\n#define GL_MATRIX18_ARB                   0x88D2\n#define GL_MATRIX19_ARB                   0x88D3\n#define GL_MATRIX20_ARB                   0x88D4\n#define GL_MATRIX21_ARB                   0x88D5\n#define GL_MATRIX22_ARB                   0x88D6\n#define GL_MATRIX23_ARB                   0x88D7\n#define GL_MATRIX24_ARB                   0x88D8\n#define GL_MATRIX25_ARB                   0x88D9\n#define GL_MATRIX26_ARB                   0x88DA\n#define GL_MATRIX27_ARB                   0x88DB\n#define GL_MATRIX28_ARB                   0x88DC\n#define GL_MATRIX29_ARB                   0x88DD\n#define GL_MATRIX30_ARB                   0x88DE\n#define GL_MATRIX31_ARB                   0x88DF\n#endif\n\n#ifndef GL_ARB_fragment_program\n#define GL_FRAGMENT_PROGRAM_ARB           0x8804\n#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB   0x8805\n#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB   0x8806\n#define GL_PROGRAM_TEX_INDIRECTIONS_ARB   0x8807\n#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808\n#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809\n#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A\n#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B\n#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C\n#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D\n#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E\n#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F\n#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810\n#define GL_MAX_TEXTURE_COORDS_ARB         0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB    0x8872\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n#define GL_BUFFER_SIZE_ARB                0x8764\n#define GL_BUFFER_USAGE_ARB               0x8765\n#define GL_ARRAY_BUFFER_ARB               0x8892\n#define GL_ELEMENT_ARRAY_BUFFER_ARB       0x8893\n#define GL_ARRAY_BUFFER_BINDING_ARB       0x8894\n#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895\n#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896\n#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897\n#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898\n#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899\n#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A\n#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B\n#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C\n#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D\n#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E\n#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F\n#define GL_READ_ONLY_ARB                  0x88B8\n#define GL_WRITE_ONLY_ARB                 0x88B9\n#define GL_READ_WRITE_ARB                 0x88BA\n#define GL_BUFFER_ACCESS_ARB              0x88BB\n#define GL_BUFFER_MAPPED_ARB              0x88BC\n#define GL_BUFFER_MAP_POINTER_ARB         0x88BD\n#define GL_STREAM_DRAW_ARB                0x88E0\n#define GL_STREAM_READ_ARB                0x88E1\n#define GL_STREAM_COPY_ARB                0x88E2\n#define GL_STATIC_DRAW_ARB                0x88E4\n#define GL_STATIC_READ_ARB                0x88E5\n#define GL_STATIC_COPY_ARB                0x88E6\n#define GL_DYNAMIC_DRAW_ARB               0x88E8\n#define GL_DYNAMIC_READ_ARB               0x88E9\n#define GL_DYNAMIC_COPY_ARB               0x88EA\n#endif\n\n#ifndef GL_ARB_occlusion_query\n#define GL_QUERY_COUNTER_BITS_ARB         0x8864\n#define GL_CURRENT_QUERY_ARB              0x8865\n#define GL_QUERY_RESULT_ARB               0x8866\n#define GL_QUERY_RESULT_AVAILABLE_ARB     0x8867\n#define GL_SAMPLES_PASSED_ARB             0x8914\n#endif\n\n#ifndef GL_ARB_shader_objects\n#define GL_PROGRAM_OBJECT_ARB             0x8B40\n#define GL_SHADER_OBJECT_ARB              0x8B48\n#define GL_OBJECT_TYPE_ARB                0x8B4E\n#define GL_OBJECT_SUBTYPE_ARB             0x8B4F\n#define GL_FLOAT_VEC2_ARB                 0x8B50\n#define GL_FLOAT_VEC3_ARB                 0x8B51\n#define GL_FLOAT_VEC4_ARB                 0x8B52\n#define GL_INT_VEC2_ARB                   0x8B53\n#define GL_INT_VEC3_ARB                   0x8B54\n#define GL_INT_VEC4_ARB                   0x8B55\n#define GL_BOOL_ARB                       0x8B56\n#define GL_BOOL_VEC2_ARB                  0x8B57\n#define GL_BOOL_VEC3_ARB                  0x8B58\n#define GL_BOOL_VEC4_ARB                  0x8B59\n#define GL_FLOAT_MAT2_ARB                 0x8B5A\n#define GL_FLOAT_MAT3_ARB                 0x8B5B\n#define GL_FLOAT_MAT4_ARB                 0x8B5C\n#define GL_SAMPLER_1D_ARB                 0x8B5D\n#define GL_SAMPLER_2D_ARB                 0x8B5E\n#define GL_SAMPLER_3D_ARB                 0x8B5F\n#define GL_SAMPLER_CUBE_ARB               0x8B60\n#define GL_SAMPLER_1D_SHADOW_ARB          0x8B61\n#define GL_SAMPLER_2D_SHADOW_ARB          0x8B62\n#define GL_SAMPLER_2D_RECT_ARB            0x8B63\n#define GL_SAMPLER_2D_RECT_SHADOW_ARB     0x8B64\n#define GL_OBJECT_DELETE_STATUS_ARB       0x8B80\n#define GL_OBJECT_COMPILE_STATUS_ARB      0x8B81\n#define GL_OBJECT_LINK_STATUS_ARB         0x8B82\n#define GL_OBJECT_VALIDATE_STATUS_ARB     0x8B83\n#define GL_OBJECT_INFO_LOG_LENGTH_ARB     0x8B84\n#define GL_OBJECT_ATTACHED_OBJECTS_ARB    0x8B85\n#define GL_OBJECT_ACTIVE_UNIFORMS_ARB     0x8B86\n#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87\n#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88\n#endif\n\n#ifndef GL_ARB_vertex_shader\n#define GL_VERTEX_SHADER_ARB              0x8B31\n#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A\n#define GL_MAX_VARYING_FLOATS_ARB         0x8B4B\n#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C\n#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D\n#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB   0x8B89\n#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A\n#endif\n\n#ifndef GL_ARB_fragment_shader\n#define GL_FRAGMENT_SHADER_ARB            0x8B30\n#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49\n#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B\n#endif\n\n#ifndef GL_ARB_shading_language_100\n#define GL_SHADING_LANGUAGE_VERSION_ARB   0x8B8C\n#endif\n\n#ifndef GL_ARB_texture_non_power_of_two\n#endif\n\n#ifndef GL_ARB_point_sprite\n#define GL_POINT_SPRITE_ARB               0x8861\n#define GL_COORD_REPLACE_ARB              0x8862\n#endif\n\n#ifndef GL_ARB_fragment_program_shadow\n#endif\n\n#ifndef GL_ARB_draw_buffers\n#define GL_MAX_DRAW_BUFFERS_ARB           0x8824\n#define GL_DRAW_BUFFER0_ARB               0x8825\n#define GL_DRAW_BUFFER1_ARB               0x8826\n#define GL_DRAW_BUFFER2_ARB               0x8827\n#define GL_DRAW_BUFFER3_ARB               0x8828\n#define GL_DRAW_BUFFER4_ARB               0x8829\n#define GL_DRAW_BUFFER5_ARB               0x882A\n#define GL_DRAW_BUFFER6_ARB               0x882B\n#define GL_DRAW_BUFFER7_ARB               0x882C\n#define GL_DRAW_BUFFER8_ARB               0x882D\n#define GL_DRAW_BUFFER9_ARB               0x882E\n#define GL_DRAW_BUFFER10_ARB              0x882F\n#define GL_DRAW_BUFFER11_ARB              0x8830\n#define GL_DRAW_BUFFER12_ARB              0x8831\n#define GL_DRAW_BUFFER13_ARB              0x8832\n#define GL_DRAW_BUFFER14_ARB              0x8833\n#define GL_DRAW_BUFFER15_ARB              0x8834\n#endif\n\n#ifndef GL_ARB_texture_rectangle\n#define GL_TEXTURE_RECTANGLE_ARB          0x84F5\n#define GL_TEXTURE_BINDING_RECTANGLE_ARB  0x84F6\n#define GL_PROXY_TEXTURE_RECTANGLE_ARB    0x84F7\n#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8\n#endif\n\n#ifndef GL_ARB_color_buffer_float\n#define GL_RGBA_FLOAT_MODE_ARB            0x8820\n#define GL_CLAMP_VERTEX_COLOR_ARB         0x891A\n#define GL_CLAMP_FRAGMENT_COLOR_ARB       0x891B\n#define GL_CLAMP_READ_COLOR_ARB           0x891C\n#define GL_FIXED_ONLY_ARB                 0x891D\n#endif\n\n#ifndef GL_ARB_half_float_pixel\n#define GL_HALF_FLOAT_ARB                 0x140B\n#endif\n\n#ifndef GL_ARB_texture_float\n#define GL_TEXTURE_RED_TYPE_ARB           0x8C10\n#define GL_TEXTURE_GREEN_TYPE_ARB         0x8C11\n#define GL_TEXTURE_BLUE_TYPE_ARB          0x8C12\n#define GL_TEXTURE_ALPHA_TYPE_ARB         0x8C13\n#define GL_TEXTURE_LUMINANCE_TYPE_ARB     0x8C14\n#define GL_TEXTURE_INTENSITY_TYPE_ARB     0x8C15\n#define GL_TEXTURE_DEPTH_TYPE_ARB         0x8C16\n#define GL_UNSIGNED_NORMALIZED_ARB        0x8C17\n#define GL_RGBA32F_ARB                    0x8814\n#define GL_RGB32F_ARB                     0x8815\n#define GL_ALPHA32F_ARB                   0x8816\n#define GL_INTENSITY32F_ARB               0x8817\n#define GL_LUMINANCE32F_ARB               0x8818\n#define GL_LUMINANCE_ALPHA32F_ARB         0x8819\n#define GL_RGBA16F_ARB                    0x881A\n#define GL_RGB16F_ARB                     0x881B\n#define GL_ALPHA16F_ARB                   0x881C\n#define GL_INTENSITY16F_ARB               0x881D\n#define GL_LUMINANCE16F_ARB               0x881E\n#define GL_LUMINANCE_ALPHA16F_ARB         0x881F\n#endif\n\n#ifndef GL_ARB_pixel_buffer_object\n#define GL_PIXEL_PACK_BUFFER_ARB          0x88EB\n#define GL_PIXEL_UNPACK_BUFFER_ARB        0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING_ARB  0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF\n#endif\n\n#ifndef GL_ARB_depth_buffer_float\n#define GL_DEPTH_COMPONENT32F             0x8CAC\n#define GL_DEPTH32F_STENCIL8              0x8CAD\n#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD\n#endif\n\n#ifndef GL_ARB_draw_instanced\n#endif\n\n#ifndef GL_ARB_framebuffer_object\n#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506\n#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210\n#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211\n#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212\n#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213\n#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214\n#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215\n#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216\n#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217\n#define GL_FRAMEBUFFER_DEFAULT            0x8218\n#define GL_FRAMEBUFFER_UNDEFINED          0x8219\n#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A\n#define GL_INDEX                          0x8222\n#define GL_MAX_RENDERBUFFER_SIZE          0x84E8\n#define GL_DEPTH_STENCIL                  0x84F9\n#define GL_UNSIGNED_INT_24_8              0x84FA\n#define GL_DEPTH24_STENCIL8               0x88F0\n#define GL_TEXTURE_STENCIL_SIZE           0x88F1\n#define GL_FRAMEBUFFER_BINDING            0x8CA6\n#define GL_DRAW_FRAMEBUFFER_BINDING       GL_FRAMEBUFFER_BINDING\n#define GL_RENDERBUFFER_BINDING           0x8CA7\n#define GL_READ_FRAMEBUFFER               0x8CA8\n#define GL_DRAW_FRAMEBUFFER               0x8CA9\n#define GL_READ_FRAMEBUFFER_BINDING       0x8CAA\n#define GL_RENDERBUFFER_SAMPLES           0x8CAB\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4\n#define GL_FRAMEBUFFER_COMPLETE           0x8CD5\n#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6\n#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7\n#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB\n#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC\n#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD\n#define GL_MAX_COLOR_ATTACHMENTS          0x8CDF\n#define GL_COLOR_ATTACHMENT0              0x8CE0\n#define GL_COLOR_ATTACHMENT1              0x8CE1\n#define GL_COLOR_ATTACHMENT2              0x8CE2\n#define GL_COLOR_ATTACHMENT3              0x8CE3\n#define GL_COLOR_ATTACHMENT4              0x8CE4\n#define GL_COLOR_ATTACHMENT5              0x8CE5\n#define GL_COLOR_ATTACHMENT6              0x8CE6\n#define GL_COLOR_ATTACHMENT7              0x8CE7\n#define GL_COLOR_ATTACHMENT8              0x8CE8\n#define GL_COLOR_ATTACHMENT9              0x8CE9\n#define GL_COLOR_ATTACHMENT10             0x8CEA\n#define GL_COLOR_ATTACHMENT11             0x8CEB\n#define GL_COLOR_ATTACHMENT12             0x8CEC\n#define GL_COLOR_ATTACHMENT13             0x8CED\n#define GL_COLOR_ATTACHMENT14             0x8CEE\n#define GL_COLOR_ATTACHMENT15             0x8CEF\n#define GL_DEPTH_ATTACHMENT               0x8D00\n#define GL_STENCIL_ATTACHMENT             0x8D20\n#define GL_FRAMEBUFFER                    0x8D40\n#define GL_RENDERBUFFER                   0x8D41\n#define GL_RENDERBUFFER_WIDTH             0x8D42\n#define GL_RENDERBUFFER_HEIGHT            0x8D43\n#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44\n#define GL_STENCIL_INDEX1                 0x8D46\n#define GL_STENCIL_INDEX4                 0x8D47\n#define GL_STENCIL_INDEX8                 0x8D48\n#define GL_STENCIL_INDEX16                0x8D49\n#define GL_RENDERBUFFER_RED_SIZE          0x8D50\n#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51\n#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52\n#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53\n#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54\n#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55\n#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56\n#define GL_MAX_SAMPLES                    0x8D57\n#endif\n\n#ifndef GL_ARB_framebuffer_sRGB\n#define GL_FRAMEBUFFER_SRGB               0x8DB9\n#endif\n\n#ifndef GL_ARB_geometry_shader4\n#define GL_LINES_ADJACENCY_ARB            0x000A\n#define GL_LINE_STRIP_ADJACENCY_ARB       0x000B\n#define GL_TRIANGLES_ADJACENCY_ARB        0x000C\n#define GL_TRIANGLE_STRIP_ADJACENCY_ARB   0x000D\n#define GL_PROGRAM_POINT_SIZE_ARB         0x8642\n#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29\n#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9\n#define GL_GEOMETRY_SHADER_ARB            0x8DD9\n#define GL_GEOMETRY_VERTICES_OUT_ARB      0x8DDA\n#define GL_GEOMETRY_INPUT_TYPE_ARB        0x8DDB\n#define GL_GEOMETRY_OUTPUT_TYPE_ARB       0x8DDC\n#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD\n#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE\n#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF\n#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0\n#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1\n/* reuse GL_MAX_VARYING_COMPONENTS */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */\n#endif\n\n#ifndef GL_ARB_half_float_vertex\n#define GL_HALF_FLOAT                     0x140B\n#endif\n\n#ifndef GL_ARB_instanced_arrays\n#endif\n\n#ifndef GL_ARB_map_buffer_range\n#define GL_MAP_READ_BIT                   0x0001\n#define GL_MAP_WRITE_BIT                  0x0002\n#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004\n#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008\n#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010\n#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020\n#endif\n\n#ifndef GL_ARB_texture_buffer_object\n#define GL_TEXTURE_BUFFER_ARB             0x8C2A\n#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB    0x8C2B\n#define GL_TEXTURE_BINDING_BUFFER_ARB     0x8C2C\n#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D\n#define GL_TEXTURE_BUFFER_FORMAT_ARB      0x8C2E\n#endif\n\n#ifndef GL_ARB_texture_compression_rgtc\n#define GL_COMPRESSED_RED_RGTC1           0x8DBB\n#define GL_COMPRESSED_SIGNED_RED_RGTC1    0x8DBC\n#define GL_COMPRESSED_RG_RGTC2            0x8DBD\n#define GL_COMPRESSED_SIGNED_RG_RGTC2     0x8DBE\n#endif\n\n#ifndef GL_ARB_texture_rg\n#define GL_RG                             0x8227\n#define GL_RG_INTEGER                     0x8228\n#define GL_R8                             0x8229\n#define GL_R16                            0x822A\n#define GL_RG8                            0x822B\n#define GL_RG16                           0x822C\n#define GL_R16F                           0x822D\n#define GL_R32F                           0x822E\n#define GL_RG16F                          0x822F\n#define GL_RG32F                          0x8230\n#define GL_R8I                            0x8231\n#define GL_R8UI                           0x8232\n#define GL_R16I                           0x8233\n#define GL_R16UI                          0x8234\n#define GL_R32I                           0x8235\n#define GL_R32UI                          0x8236\n#define GL_RG8I                           0x8237\n#define GL_RG8UI                          0x8238\n#define GL_RG16I                          0x8239\n#define GL_RG16UI                         0x823A\n#define GL_RG32I                          0x823B\n#define GL_RG32UI                         0x823C\n#endif\n\n#ifndef GL_ARB_vertex_array_object\n#define GL_VERTEX_ARRAY_BINDING           0x85B5\n#endif\n\n#ifndef GL_EXT_abgr\n#define GL_ABGR_EXT                       0x8000\n#endif\n\n#ifndef GL_EXT_blend_color\n#define GL_CONSTANT_COLOR_EXT             0x8001\n#define GL_ONE_MINUS_CONSTANT_COLOR_EXT   0x8002\n#define GL_CONSTANT_ALPHA_EXT             0x8003\n#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT   0x8004\n#define GL_BLEND_COLOR_EXT                0x8005\n#endif\n\n#ifndef GL_EXT_polygon_offset\n#define GL_POLYGON_OFFSET_EXT             0x8037\n#define GL_POLYGON_OFFSET_FACTOR_EXT      0x8038\n#define GL_POLYGON_OFFSET_BIAS_EXT        0x8039\n#endif\n\n#ifndef GL_EXT_texture\n#define GL_ALPHA4_EXT                     0x803B\n#define GL_ALPHA8_EXT                     0x803C\n#define GL_ALPHA12_EXT                    0x803D\n#define GL_ALPHA16_EXT                    0x803E\n#define GL_LUMINANCE4_EXT                 0x803F\n#define GL_LUMINANCE8_EXT                 0x8040\n#define GL_LUMINANCE12_EXT                0x8041\n#define GL_LUMINANCE16_EXT                0x8042\n#define GL_LUMINANCE4_ALPHA4_EXT          0x8043\n#define GL_LUMINANCE6_ALPHA2_EXT          0x8044\n#define GL_LUMINANCE8_ALPHA8_EXT          0x8045\n#define GL_LUMINANCE12_ALPHA4_EXT         0x8046\n#define GL_LUMINANCE12_ALPHA12_EXT        0x8047\n#define GL_LUMINANCE16_ALPHA16_EXT        0x8048\n#define GL_INTENSITY_EXT                  0x8049\n#define GL_INTENSITY4_EXT                 0x804A\n#define GL_INTENSITY8_EXT                 0x804B\n#define GL_INTENSITY12_EXT                0x804C\n#define GL_INTENSITY16_EXT                0x804D\n#define GL_RGB2_EXT                       0x804E\n#define GL_RGB4_EXT                       0x804F\n#define GL_RGB5_EXT                       0x8050\n#define GL_RGB8_EXT                       0x8051\n#define GL_RGB10_EXT                      0x8052\n#define GL_RGB12_EXT                      0x8053\n#define GL_RGB16_EXT                      0x8054\n#define GL_RGBA2_EXT                      0x8055\n#define GL_RGBA4_EXT                      0x8056\n#define GL_RGB5_A1_EXT                    0x8057\n#define GL_RGBA8_EXT                      0x8058\n#define GL_RGB10_A2_EXT                   0x8059\n#define GL_RGBA12_EXT                     0x805A\n#define GL_RGBA16_EXT                     0x805B\n#define GL_TEXTURE_RED_SIZE_EXT           0x805C\n#define GL_TEXTURE_GREEN_SIZE_EXT         0x805D\n#define GL_TEXTURE_BLUE_SIZE_EXT          0x805E\n#define GL_TEXTURE_ALPHA_SIZE_EXT         0x805F\n#define GL_TEXTURE_LUMINANCE_SIZE_EXT     0x8060\n#define GL_TEXTURE_INTENSITY_SIZE_EXT     0x8061\n#define GL_REPLACE_EXT                    0x8062\n#define GL_PROXY_TEXTURE_1D_EXT           0x8063\n#define GL_PROXY_TEXTURE_2D_EXT           0x8064\n#define GL_TEXTURE_TOO_LARGE_EXT          0x8065\n#endif\n\n#ifndef GL_EXT_texture3D\n#define GL_PACK_SKIP_IMAGES_EXT           0x806B\n#define GL_PACK_IMAGE_HEIGHT_EXT          0x806C\n#define GL_UNPACK_SKIP_IMAGES_EXT         0x806D\n#define GL_UNPACK_IMAGE_HEIGHT_EXT        0x806E\n#define GL_TEXTURE_3D_EXT                 0x806F\n#define GL_PROXY_TEXTURE_3D_EXT           0x8070\n#define GL_TEXTURE_DEPTH_EXT              0x8071\n#define GL_TEXTURE_WRAP_R_EXT             0x8072\n#define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073\n#endif\n\n#ifndef GL_SGIS_texture_filter4\n#define GL_FILTER4_SGIS                   0x8146\n#define GL_TEXTURE_FILTER4_SIZE_SGIS      0x8147\n#endif\n\n#ifndef GL_EXT_subtexture\n#endif\n\n#ifndef GL_EXT_copy_texture\n#endif\n\n#ifndef GL_EXT_histogram\n#define GL_HISTOGRAM_EXT                  0x8024\n#define GL_PROXY_HISTOGRAM_EXT            0x8025\n#define GL_HISTOGRAM_WIDTH_EXT            0x8026\n#define GL_HISTOGRAM_FORMAT_EXT           0x8027\n#define GL_HISTOGRAM_RED_SIZE_EXT         0x8028\n#define GL_HISTOGRAM_GREEN_SIZE_EXT       0x8029\n#define GL_HISTOGRAM_BLUE_SIZE_EXT        0x802A\n#define GL_HISTOGRAM_ALPHA_SIZE_EXT       0x802B\n#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT   0x802C\n#define GL_HISTOGRAM_SINK_EXT             0x802D\n#define GL_MINMAX_EXT                     0x802E\n#define GL_MINMAX_FORMAT_EXT              0x802F\n#define GL_MINMAX_SINK_EXT                0x8030\n#define GL_TABLE_TOO_LARGE_EXT            0x8031\n#endif\n\n#ifndef GL_EXT_convolution\n#define GL_CONVOLUTION_1D_EXT             0x8010\n#define GL_CONVOLUTION_2D_EXT             0x8011\n#define GL_SEPARABLE_2D_EXT               0x8012\n#define GL_CONVOLUTION_BORDER_MODE_EXT    0x8013\n#define GL_CONVOLUTION_FILTER_SCALE_EXT   0x8014\n#define GL_CONVOLUTION_FILTER_BIAS_EXT    0x8015\n#define GL_REDUCE_EXT                     0x8016\n#define GL_CONVOLUTION_FORMAT_EXT         0x8017\n#define GL_CONVOLUTION_WIDTH_EXT          0x8018\n#define GL_CONVOLUTION_HEIGHT_EXT         0x8019\n#define GL_MAX_CONVOLUTION_WIDTH_EXT      0x801A\n#define GL_MAX_CONVOLUTION_HEIGHT_EXT     0x801B\n#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C\n#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D\n#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E\n#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F\n#define GL_POST_CONVOLUTION_RED_BIAS_EXT  0x8020\n#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021\n#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022\n#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023\n#endif\n\n#ifndef GL_SGI_color_matrix\n#define GL_COLOR_MATRIX_SGI               0x80B1\n#define GL_COLOR_MATRIX_STACK_DEPTH_SGI   0x80B2\n#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3\n#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4\n#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5\n#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6\n#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7\n#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8\n#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9\n#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA\n#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB\n#endif\n\n#ifndef GL_SGI_color_table\n#define GL_COLOR_TABLE_SGI                0x80D0\n#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1\n#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2\n#define GL_PROXY_COLOR_TABLE_SGI          0x80D3\n#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4\n#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5\n#define GL_COLOR_TABLE_SCALE_SGI          0x80D6\n#define GL_COLOR_TABLE_BIAS_SGI           0x80D7\n#define GL_COLOR_TABLE_FORMAT_SGI         0x80D8\n#define GL_COLOR_TABLE_WIDTH_SGI          0x80D9\n#define GL_COLOR_TABLE_RED_SIZE_SGI       0x80DA\n#define GL_COLOR_TABLE_GREEN_SIZE_SGI     0x80DB\n#define GL_COLOR_TABLE_BLUE_SIZE_SGI      0x80DC\n#define GL_COLOR_TABLE_ALPHA_SIZE_SGI     0x80DD\n#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE\n#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF\n#endif\n\n#ifndef GL_SGIS_pixel_texture\n#define GL_PIXEL_TEXTURE_SGIS             0x8353\n#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354\n#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355\n#define GL_PIXEL_GROUP_COLOR_SGIS         0x8356\n#endif\n\n#ifndef GL_SGIX_pixel_texture\n#define GL_PIXEL_TEX_GEN_SGIX             0x8139\n#define GL_PIXEL_TEX_GEN_MODE_SGIX        0x832B\n#endif\n\n#ifndef GL_SGIS_texture4D\n#define GL_PACK_SKIP_VOLUMES_SGIS         0x8130\n#define GL_PACK_IMAGE_DEPTH_SGIS          0x8131\n#define GL_UNPACK_SKIP_VOLUMES_SGIS       0x8132\n#define GL_UNPACK_IMAGE_DEPTH_SGIS        0x8133\n#define GL_TEXTURE_4D_SGIS                0x8134\n#define GL_PROXY_TEXTURE_4D_SGIS          0x8135\n#define GL_TEXTURE_4DSIZE_SGIS            0x8136\n#define GL_TEXTURE_WRAP_Q_SGIS            0x8137\n#define GL_MAX_4D_TEXTURE_SIZE_SGIS       0x8138\n#define GL_TEXTURE_4D_BINDING_SGIS        0x814F\n#endif\n\n#ifndef GL_SGI_texture_color_table\n#define GL_TEXTURE_COLOR_TABLE_SGI        0x80BC\n#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI  0x80BD\n#endif\n\n#ifndef GL_EXT_cmyka\n#define GL_CMYK_EXT                       0x800C\n#define GL_CMYKA_EXT                      0x800D\n#define GL_PACK_CMYK_HINT_EXT             0x800E\n#define GL_UNPACK_CMYK_HINT_EXT           0x800F\n#endif\n\n#ifndef GL_EXT_texture_object\n#define GL_TEXTURE_PRIORITY_EXT           0x8066\n#define GL_TEXTURE_RESIDENT_EXT           0x8067\n#define GL_TEXTURE_1D_BINDING_EXT         0x8068\n#define GL_TEXTURE_2D_BINDING_EXT         0x8069\n#define GL_TEXTURE_3D_BINDING_EXT         0x806A\n#endif\n\n#ifndef GL_SGIS_detail_texture\n#define GL_DETAIL_TEXTURE_2D_SGIS         0x8095\n#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096\n#define GL_LINEAR_DETAIL_SGIS             0x8097\n#define GL_LINEAR_DETAIL_ALPHA_SGIS       0x8098\n#define GL_LINEAR_DETAIL_COLOR_SGIS       0x8099\n#define GL_DETAIL_TEXTURE_LEVEL_SGIS      0x809A\n#define GL_DETAIL_TEXTURE_MODE_SGIS       0x809B\n#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C\n#endif\n\n#ifndef GL_SGIS_sharpen_texture\n#define GL_LINEAR_SHARPEN_SGIS            0x80AD\n#define GL_LINEAR_SHARPEN_ALPHA_SGIS      0x80AE\n#define GL_LINEAR_SHARPEN_COLOR_SGIS      0x80AF\n#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0\n#endif\n\n#ifndef GL_EXT_packed_pixels\n#define GL_UNSIGNED_BYTE_3_3_2_EXT        0x8032\n#define GL_UNSIGNED_SHORT_4_4_4_4_EXT     0x8033\n#define GL_UNSIGNED_SHORT_5_5_5_1_EXT     0x8034\n#define GL_UNSIGNED_INT_8_8_8_8_EXT       0x8035\n#define GL_UNSIGNED_INT_10_10_10_2_EXT    0x8036\n#endif\n\n#ifndef GL_SGIS_texture_lod\n#define GL_TEXTURE_MIN_LOD_SGIS           0x813A\n#define GL_TEXTURE_MAX_LOD_SGIS           0x813B\n#define GL_TEXTURE_BASE_LEVEL_SGIS        0x813C\n#define GL_TEXTURE_MAX_LEVEL_SGIS         0x813D\n#endif\n\n#ifndef GL_SGIS_multisample\n#define GL_MULTISAMPLE_SGIS               0x809D\n#define GL_SAMPLE_ALPHA_TO_MASK_SGIS      0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_SGIS       0x809F\n#define GL_SAMPLE_MASK_SGIS               0x80A0\n#define GL_1PASS_SGIS                     0x80A1\n#define GL_2PASS_0_SGIS                   0x80A2\n#define GL_2PASS_1_SGIS                   0x80A3\n#define GL_4PASS_0_SGIS                   0x80A4\n#define GL_4PASS_1_SGIS                   0x80A5\n#define GL_4PASS_2_SGIS                   0x80A6\n#define GL_4PASS_3_SGIS                   0x80A7\n#define GL_SAMPLE_BUFFERS_SGIS            0x80A8\n#define GL_SAMPLES_SGIS                   0x80A9\n#define GL_SAMPLE_MASK_VALUE_SGIS         0x80AA\n#define GL_SAMPLE_MASK_INVERT_SGIS        0x80AB\n#define GL_SAMPLE_PATTERN_SGIS            0x80AC\n#endif\n\n#ifndef GL_EXT_rescale_normal\n#define GL_RESCALE_NORMAL_EXT             0x803A\n#endif\n\n#ifndef GL_EXT_vertex_array\n#define GL_VERTEX_ARRAY_EXT               0x8074\n#define GL_NORMAL_ARRAY_EXT               0x8075\n#define GL_COLOR_ARRAY_EXT                0x8076\n#define GL_INDEX_ARRAY_EXT                0x8077\n#define GL_TEXTURE_COORD_ARRAY_EXT        0x8078\n#define GL_EDGE_FLAG_ARRAY_EXT            0x8079\n#define GL_VERTEX_ARRAY_SIZE_EXT          0x807A\n#define GL_VERTEX_ARRAY_TYPE_EXT          0x807B\n#define GL_VERTEX_ARRAY_STRIDE_EXT        0x807C\n#define GL_VERTEX_ARRAY_COUNT_EXT         0x807D\n#define GL_NORMAL_ARRAY_TYPE_EXT          0x807E\n#define GL_NORMAL_ARRAY_STRIDE_EXT        0x807F\n#define GL_NORMAL_ARRAY_COUNT_EXT         0x8080\n#define GL_COLOR_ARRAY_SIZE_EXT           0x8081\n#define GL_COLOR_ARRAY_TYPE_EXT           0x8082\n#define GL_COLOR_ARRAY_STRIDE_EXT         0x8083\n#define GL_COLOR_ARRAY_COUNT_EXT          0x8084\n#define GL_INDEX_ARRAY_TYPE_EXT           0x8085\n#define GL_INDEX_ARRAY_STRIDE_EXT         0x8086\n#define GL_INDEX_ARRAY_COUNT_EXT          0x8087\n#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT   0x8088\n#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT   0x8089\n#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A\n#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT  0x808B\n#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT     0x808C\n#define GL_EDGE_FLAG_ARRAY_COUNT_EXT      0x808D\n#define GL_VERTEX_ARRAY_POINTER_EXT       0x808E\n#define GL_NORMAL_ARRAY_POINTER_EXT       0x808F\n#define GL_COLOR_ARRAY_POINTER_EXT        0x8090\n#define GL_INDEX_ARRAY_POINTER_EXT        0x8091\n#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092\n#define GL_EDGE_FLAG_ARRAY_POINTER_EXT    0x8093\n#endif\n\n#ifndef GL_EXT_misc_attribute\n#endif\n\n#ifndef GL_SGIS_generate_mipmap\n#define GL_GENERATE_MIPMAP_SGIS           0x8191\n#define GL_GENERATE_MIPMAP_HINT_SGIS      0x8192\n#endif\n\n#ifndef GL_SGIX_clipmap\n#define GL_LINEAR_CLIPMAP_LINEAR_SGIX     0x8170\n#define GL_TEXTURE_CLIPMAP_CENTER_SGIX    0x8171\n#define GL_TEXTURE_CLIPMAP_FRAME_SGIX     0x8172\n#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX    0x8173\n#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174\n#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175\n#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX     0x8176\n#define GL_MAX_CLIPMAP_DEPTH_SGIX         0x8177\n#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178\n#define GL_NEAREST_CLIPMAP_NEAREST_SGIX   0x844D\n#define GL_NEAREST_CLIPMAP_LINEAR_SGIX    0x844E\n#define GL_LINEAR_CLIPMAP_NEAREST_SGIX    0x844F\n#endif\n\n#ifndef GL_SGIX_shadow\n#define GL_TEXTURE_COMPARE_SGIX           0x819A\n#define GL_TEXTURE_COMPARE_OPERATOR_SGIX  0x819B\n#define GL_TEXTURE_LEQUAL_R_SGIX          0x819C\n#define GL_TEXTURE_GEQUAL_R_SGIX          0x819D\n#endif\n\n#ifndef GL_SGIS_texture_edge_clamp\n#define GL_CLAMP_TO_EDGE_SGIS             0x812F\n#endif\n\n#ifndef GL_SGIS_texture_border_clamp\n#define GL_CLAMP_TO_BORDER_SGIS           0x812D\n#endif\n\n#ifndef GL_EXT_blend_minmax\n#define GL_FUNC_ADD_EXT                   0x8006\n#define GL_MIN_EXT                        0x8007\n#define GL_MAX_EXT                        0x8008\n#define GL_BLEND_EQUATION_EXT             0x8009\n#endif\n\n#ifndef GL_EXT_blend_subtract\n#define GL_FUNC_SUBTRACT_EXT              0x800A\n#define GL_FUNC_REVERSE_SUBTRACT_EXT      0x800B\n#endif\n\n#ifndef GL_EXT_blend_logic_op\n#endif\n\n#ifndef GL_SGIX_interlace\n#define GL_INTERLACE_SGIX                 0x8094\n#endif\n\n#ifndef GL_SGIX_pixel_tiles\n#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E\n#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F\n#define GL_PIXEL_TILE_WIDTH_SGIX          0x8140\n#define GL_PIXEL_TILE_HEIGHT_SGIX         0x8141\n#define GL_PIXEL_TILE_GRID_WIDTH_SGIX     0x8142\n#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX    0x8143\n#define GL_PIXEL_TILE_GRID_DEPTH_SGIX     0x8144\n#define GL_PIXEL_TILE_CACHE_SIZE_SGIX     0x8145\n#endif\n\n#ifndef GL_SGIS_texture_select\n#define GL_DUAL_ALPHA4_SGIS               0x8110\n#define GL_DUAL_ALPHA8_SGIS               0x8111\n#define GL_DUAL_ALPHA12_SGIS              0x8112\n#define GL_DUAL_ALPHA16_SGIS              0x8113\n#define GL_DUAL_LUMINANCE4_SGIS           0x8114\n#define GL_DUAL_LUMINANCE8_SGIS           0x8115\n#define GL_DUAL_LUMINANCE12_SGIS          0x8116\n#define GL_DUAL_LUMINANCE16_SGIS          0x8117\n#define GL_DUAL_INTENSITY4_SGIS           0x8118\n#define GL_DUAL_INTENSITY8_SGIS           0x8119\n#define GL_DUAL_INTENSITY12_SGIS          0x811A\n#define GL_DUAL_INTENSITY16_SGIS          0x811B\n#define GL_DUAL_LUMINANCE_ALPHA4_SGIS     0x811C\n#define GL_DUAL_LUMINANCE_ALPHA8_SGIS     0x811D\n#define GL_QUAD_ALPHA4_SGIS               0x811E\n#define GL_QUAD_ALPHA8_SGIS               0x811F\n#define GL_QUAD_LUMINANCE4_SGIS           0x8120\n#define GL_QUAD_LUMINANCE8_SGIS           0x8121\n#define GL_QUAD_INTENSITY4_SGIS           0x8122\n#define GL_QUAD_INTENSITY8_SGIS           0x8123\n#define GL_DUAL_TEXTURE_SELECT_SGIS       0x8124\n#define GL_QUAD_TEXTURE_SELECT_SGIS       0x8125\n#endif\n\n#ifndef GL_SGIX_sprite\n#define GL_SPRITE_SGIX                    0x8148\n#define GL_SPRITE_MODE_SGIX               0x8149\n#define GL_SPRITE_AXIS_SGIX               0x814A\n#define GL_SPRITE_TRANSLATION_SGIX        0x814B\n#define GL_SPRITE_AXIAL_SGIX              0x814C\n#define GL_SPRITE_OBJECT_ALIGNED_SGIX     0x814D\n#define GL_SPRITE_EYE_ALIGNED_SGIX        0x814E\n#endif\n\n#ifndef GL_SGIX_texture_multi_buffer\n#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E\n#endif\n\n#ifndef GL_EXT_point_parameters\n#define GL_POINT_SIZE_MIN_EXT             0x8126\n#define GL_POINT_SIZE_MAX_EXT             0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_EXT  0x8128\n#define GL_DISTANCE_ATTENUATION_EXT       0x8129\n#endif\n\n#ifndef GL_SGIS_point_parameters\n#define GL_POINT_SIZE_MIN_SGIS            0x8126\n#define GL_POINT_SIZE_MAX_SGIS            0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128\n#define GL_DISTANCE_ATTENUATION_SGIS      0x8129\n#endif\n\n#ifndef GL_SGIX_instruments\n#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180\n#define GL_INSTRUMENT_MEASUREMENTS_SGIX   0x8181\n#endif\n\n#ifndef GL_SGIX_texture_scale_bias\n#define GL_POST_TEXTURE_FILTER_BIAS_SGIX  0x8179\n#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A\n#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B\n#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C\n#endif\n\n#ifndef GL_SGIX_framezoom\n#define GL_FRAMEZOOM_SGIX                 0x818B\n#define GL_FRAMEZOOM_FACTOR_SGIX          0x818C\n#define GL_MAX_FRAMEZOOM_FACTOR_SGIX      0x818D\n#endif\n\n#ifndef GL_SGIX_tag_sample_buffer\n#endif\n\n#ifndef GL_FfdMaskSGIX\n#define GL_TEXTURE_DEFORMATION_BIT_SGIX   0x00000001\n#define GL_GEOMETRY_DEFORMATION_BIT_SGIX  0x00000002\n#endif\n\n#ifndef GL_SGIX_polynomial_ffd\n#define GL_GEOMETRY_DEFORMATION_SGIX      0x8194\n#define GL_TEXTURE_DEFORMATION_SGIX       0x8195\n#define GL_DEFORMATIONS_MASK_SGIX         0x8196\n#define GL_MAX_DEFORMATION_ORDER_SGIX     0x8197\n#endif\n\n#ifndef GL_SGIX_reference_plane\n#define GL_REFERENCE_PLANE_SGIX           0x817D\n#define GL_REFERENCE_PLANE_EQUATION_SGIX  0x817E\n#endif\n\n#ifndef GL_SGIX_flush_raster\n#endif\n\n#ifndef GL_SGIX_depth_texture\n#define GL_DEPTH_COMPONENT16_SGIX         0x81A5\n#define GL_DEPTH_COMPONENT24_SGIX         0x81A6\n#define GL_DEPTH_COMPONENT32_SGIX         0x81A7\n#endif\n\n#ifndef GL_SGIS_fog_function\n#define GL_FOG_FUNC_SGIS                  0x812A\n#define GL_FOG_FUNC_POINTS_SGIS           0x812B\n#define GL_MAX_FOG_FUNC_POINTS_SGIS       0x812C\n#endif\n\n#ifndef GL_SGIX_fog_offset\n#define GL_FOG_OFFSET_SGIX                0x8198\n#define GL_FOG_OFFSET_VALUE_SGIX          0x8199\n#endif\n\n#ifndef GL_HP_image_transform\n#define GL_IMAGE_SCALE_X_HP               0x8155\n#define GL_IMAGE_SCALE_Y_HP               0x8156\n#define GL_IMAGE_TRANSLATE_X_HP           0x8157\n#define GL_IMAGE_TRANSLATE_Y_HP           0x8158\n#define GL_IMAGE_ROTATE_ANGLE_HP          0x8159\n#define GL_IMAGE_ROTATE_ORIGIN_X_HP       0x815A\n#define GL_IMAGE_ROTATE_ORIGIN_Y_HP       0x815B\n#define GL_IMAGE_MAG_FILTER_HP            0x815C\n#define GL_IMAGE_MIN_FILTER_HP            0x815D\n#define GL_IMAGE_CUBIC_WEIGHT_HP          0x815E\n#define GL_CUBIC_HP                       0x815F\n#define GL_AVERAGE_HP                     0x8160\n#define GL_IMAGE_TRANSFORM_2D_HP          0x8161\n#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162\n#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163\n#endif\n\n#ifndef GL_HP_convolution_border_modes\n#define GL_IGNORE_BORDER_HP               0x8150\n#define GL_CONSTANT_BORDER_HP             0x8151\n#define GL_REPLICATE_BORDER_HP            0x8153\n#define GL_CONVOLUTION_BORDER_COLOR_HP    0x8154\n#endif\n\n#ifndef GL_INGR_palette_buffer\n#endif\n\n#ifndef GL_SGIX_texture_add_env\n#define GL_TEXTURE_ENV_BIAS_SGIX          0x80BE\n#endif\n\n#ifndef GL_EXT_color_subtable\n#endif\n\n#ifndef GL_PGI_vertex_hints\n#define GL_VERTEX_DATA_HINT_PGI           0x1A22A\n#define GL_VERTEX_CONSISTENT_HINT_PGI     0x1A22B\n#define GL_MATERIAL_SIDE_HINT_PGI         0x1A22C\n#define GL_MAX_VERTEX_HINT_PGI            0x1A22D\n#define GL_COLOR3_BIT_PGI                 0x00010000\n#define GL_COLOR4_BIT_PGI                 0x00020000\n#define GL_EDGEFLAG_BIT_PGI               0x00040000\n#define GL_INDEX_BIT_PGI                  0x00080000\n#define GL_MAT_AMBIENT_BIT_PGI            0x00100000\n#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000\n#define GL_MAT_DIFFUSE_BIT_PGI            0x00400000\n#define GL_MAT_EMISSION_BIT_PGI           0x00800000\n#define GL_MAT_COLOR_INDEXES_BIT_PGI      0x01000000\n#define GL_MAT_SHININESS_BIT_PGI          0x02000000\n#define GL_MAT_SPECULAR_BIT_PGI           0x04000000\n#define GL_NORMAL_BIT_PGI                 0x08000000\n#define GL_TEXCOORD1_BIT_PGI              0x10000000\n#define GL_TEXCOORD2_BIT_PGI              0x20000000\n#define GL_TEXCOORD3_BIT_PGI              0x40000000\n#define GL_TEXCOORD4_BIT_PGI              0x80000000\n#define GL_VERTEX23_BIT_PGI               0x00000004\n#define GL_VERTEX4_BIT_PGI                0x00000008\n#endif\n\n#ifndef GL_PGI_misc_hints\n#define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8\n#define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD\n#define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE\n#define GL_NATIVE_GRAPHICS_HANDLE_PGI     0x1A202\n#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203\n#define GL_NATIVE_GRAPHICS_END_HINT_PGI   0x1A204\n#define GL_ALWAYS_FAST_HINT_PGI           0x1A20C\n#define GL_ALWAYS_SOFT_HINT_PGI           0x1A20D\n#define GL_ALLOW_DRAW_OBJ_HINT_PGI        0x1A20E\n#define GL_ALLOW_DRAW_WIN_HINT_PGI        0x1A20F\n#define GL_ALLOW_DRAW_FRG_HINT_PGI        0x1A210\n#define GL_ALLOW_DRAW_MEM_HINT_PGI        0x1A211\n#define GL_STRICT_DEPTHFUNC_HINT_PGI      0x1A216\n#define GL_STRICT_LIGHTING_HINT_PGI       0x1A217\n#define GL_STRICT_SCISSOR_HINT_PGI        0x1A218\n#define GL_FULL_STIPPLE_HINT_PGI          0x1A219\n#define GL_CLIP_NEAR_HINT_PGI             0x1A220\n#define GL_CLIP_FAR_HINT_PGI              0x1A221\n#define GL_WIDE_LINE_HINT_PGI             0x1A222\n#define GL_BACK_NORMALS_HINT_PGI          0x1A223\n#endif\n\n#ifndef GL_EXT_paletted_texture\n#define GL_COLOR_INDEX1_EXT               0x80E2\n#define GL_COLOR_INDEX2_EXT               0x80E3\n#define GL_COLOR_INDEX4_EXT               0x80E4\n#define GL_COLOR_INDEX8_EXT               0x80E5\n#define GL_COLOR_INDEX12_EXT              0x80E6\n#define GL_COLOR_INDEX16_EXT              0x80E7\n#define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED\n#endif\n\n#ifndef GL_EXT_clip_volume_hint\n#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT  0x80F0\n#endif\n\n#ifndef GL_SGIX_list_priority\n#define GL_LIST_PRIORITY_SGIX             0x8182\n#endif\n\n#ifndef GL_SGIX_ir_instrument1\n#define GL_IR_INSTRUMENT1_SGIX            0x817F\n#endif\n\n#ifndef GL_SGIX_calligraphic_fragment\n#define GL_CALLIGRAPHIC_FRAGMENT_SGIX     0x8183\n#endif\n\n#ifndef GL_SGIX_texture_lod_bias\n#define GL_TEXTURE_LOD_BIAS_S_SGIX        0x818E\n#define GL_TEXTURE_LOD_BIAS_T_SGIX        0x818F\n#define GL_TEXTURE_LOD_BIAS_R_SGIX        0x8190\n#endif\n\n#ifndef GL_SGIX_shadow_ambient\n#define GL_SHADOW_AMBIENT_SGIX            0x80BF\n#endif\n\n#ifndef GL_EXT_index_texture\n#endif\n\n#ifndef GL_EXT_index_material\n#define GL_INDEX_MATERIAL_EXT             0x81B8\n#define GL_INDEX_MATERIAL_PARAMETER_EXT   0x81B9\n#define GL_INDEX_MATERIAL_FACE_EXT        0x81BA\n#endif\n\n#ifndef GL_EXT_index_func\n#define GL_INDEX_TEST_EXT                 0x81B5\n#define GL_INDEX_TEST_FUNC_EXT            0x81B6\n#define GL_INDEX_TEST_REF_EXT             0x81B7\n#endif\n\n#ifndef GL_EXT_index_array_formats\n#define GL_IUI_V2F_EXT                    0x81AD\n#define GL_IUI_V3F_EXT                    0x81AE\n#define GL_IUI_N3F_V2F_EXT                0x81AF\n#define GL_IUI_N3F_V3F_EXT                0x81B0\n#define GL_T2F_IUI_V2F_EXT                0x81B1\n#define GL_T2F_IUI_V3F_EXT                0x81B2\n#define GL_T2F_IUI_N3F_V2F_EXT            0x81B3\n#define GL_T2F_IUI_N3F_V3F_EXT            0x81B4\n#endif\n\n#ifndef GL_EXT_compiled_vertex_array\n#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT   0x81A8\n#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT   0x81A9\n#endif\n\n#ifndef GL_EXT_cull_vertex\n#define GL_CULL_VERTEX_EXT                0x81AA\n#define GL_CULL_VERTEX_EYE_POSITION_EXT   0x81AB\n#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC\n#endif\n\n#ifndef GL_SGIX_ycrcb\n#define GL_YCRCB_422_SGIX                 0x81BB\n#define GL_YCRCB_444_SGIX                 0x81BC\n#endif\n\n#ifndef GL_SGIX_fragment_lighting\n#define GL_FRAGMENT_LIGHTING_SGIX         0x8400\n#define GL_FRAGMENT_COLOR_MATERIAL_SGIX   0x8401\n#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402\n#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403\n#define GL_MAX_FRAGMENT_LIGHTS_SGIX       0x8404\n#define GL_MAX_ACTIVE_LIGHTS_SGIX         0x8405\n#define GL_CURRENT_RASTER_NORMAL_SGIX     0x8406\n#define GL_LIGHT_ENV_MODE_SGIX            0x8407\n#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408\n#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409\n#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A\n#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B\n#define GL_FRAGMENT_LIGHT0_SGIX           0x840C\n#define GL_FRAGMENT_LIGHT1_SGIX           0x840D\n#define GL_FRAGMENT_LIGHT2_SGIX           0x840E\n#define GL_FRAGMENT_LIGHT3_SGIX           0x840F\n#define GL_FRAGMENT_LIGHT4_SGIX           0x8410\n#define GL_FRAGMENT_LIGHT5_SGIX           0x8411\n#define GL_FRAGMENT_LIGHT6_SGIX           0x8412\n#define GL_FRAGMENT_LIGHT7_SGIX           0x8413\n#endif\n\n#ifndef GL_IBM_rasterpos_clip\n#define GL_RASTER_POSITION_UNCLIPPED_IBM  0x19262\n#endif\n\n#ifndef GL_HP_texture_lighting\n#define GL_TEXTURE_LIGHTING_MODE_HP       0x8167\n#define GL_TEXTURE_POST_SPECULAR_HP       0x8168\n#define GL_TEXTURE_PRE_SPECULAR_HP        0x8169\n#endif\n\n#ifndef GL_EXT_draw_range_elements\n#define GL_MAX_ELEMENTS_VERTICES_EXT      0x80E8\n#define GL_MAX_ELEMENTS_INDICES_EXT       0x80E9\n#endif\n\n#ifndef GL_WIN_phong_shading\n#define GL_PHONG_WIN                      0x80EA\n#define GL_PHONG_HINT_WIN                 0x80EB\n#endif\n\n#ifndef GL_WIN_specular_fog\n#define GL_FOG_SPECULAR_TEXTURE_WIN       0x80EC\n#endif\n\n#ifndef GL_EXT_light_texture\n#define GL_FRAGMENT_MATERIAL_EXT          0x8349\n#define GL_FRAGMENT_NORMAL_EXT            0x834A\n#define GL_FRAGMENT_COLOR_EXT             0x834C\n#define GL_ATTENUATION_EXT                0x834D\n#define GL_SHADOW_ATTENUATION_EXT         0x834E\n#define GL_TEXTURE_APPLICATION_MODE_EXT   0x834F\n#define GL_TEXTURE_LIGHT_EXT              0x8350\n#define GL_TEXTURE_MATERIAL_FACE_EXT      0x8351\n#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352\n/* reuse GL_FRAGMENT_DEPTH_EXT */\n#endif\n\n#ifndef GL_SGIX_blend_alpha_minmax\n#define GL_ALPHA_MIN_SGIX                 0x8320\n#define GL_ALPHA_MAX_SGIX                 0x8321\n#endif\n\n#ifndef GL_SGIX_impact_pixel_texture\n#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX   0x8184\n#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX     0x8185\n#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX     0x8186\n#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187\n#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188\n#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX    0x8189\n#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX    0x818A\n#endif\n\n#ifndef GL_EXT_bgra\n#define GL_BGR_EXT                        0x80E0\n#define GL_BGRA_EXT                       0x80E1\n#endif\n\n#ifndef GL_SGIX_async\n#define GL_ASYNC_MARKER_SGIX              0x8329\n#endif\n\n#ifndef GL_SGIX_async_pixel\n#define GL_ASYNC_TEX_IMAGE_SGIX           0x835C\n#define GL_ASYNC_DRAW_PIXELS_SGIX         0x835D\n#define GL_ASYNC_READ_PIXELS_SGIX         0x835E\n#define GL_MAX_ASYNC_TEX_IMAGE_SGIX       0x835F\n#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX     0x8360\n#define GL_MAX_ASYNC_READ_PIXELS_SGIX     0x8361\n#endif\n\n#ifndef GL_SGIX_async_histogram\n#define GL_ASYNC_HISTOGRAM_SGIX           0x832C\n#define GL_MAX_ASYNC_HISTOGRAM_SGIX       0x832D\n#endif\n\n#ifndef GL_INTEL_texture_scissor\n#endif\n\n#ifndef GL_INTEL_parallel_arrays\n#define GL_PARALLEL_ARRAYS_INTEL          0x83F4\n#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5\n#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6\n#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7\n#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8\n#endif\n\n#ifndef GL_HP_occlusion_test\n#define GL_OCCLUSION_TEST_HP              0x8165\n#define GL_OCCLUSION_TEST_RESULT_HP       0x8166\n#endif\n\n#ifndef GL_EXT_pixel_transform\n#define GL_PIXEL_TRANSFORM_2D_EXT         0x8330\n#define GL_PIXEL_MAG_FILTER_EXT           0x8331\n#define GL_PIXEL_MIN_FILTER_EXT           0x8332\n#define GL_PIXEL_CUBIC_WEIGHT_EXT         0x8333\n#define GL_CUBIC_EXT                      0x8334\n#define GL_AVERAGE_EXT                    0x8335\n#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336\n#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337\n#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT  0x8338\n#endif\n\n#ifndef GL_EXT_pixel_transform_color_table\n#endif\n\n#ifndef GL_EXT_shared_texture_palette\n#define GL_SHARED_TEXTURE_PALETTE_EXT     0x81FB\n#endif\n\n#ifndef GL_EXT_separate_specular_color\n#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT  0x81F8\n#define GL_SINGLE_COLOR_EXT               0x81F9\n#define GL_SEPARATE_SPECULAR_COLOR_EXT    0x81FA\n#endif\n\n#ifndef GL_EXT_secondary_color\n#define GL_COLOR_SUM_EXT                  0x8458\n#define GL_CURRENT_SECONDARY_COLOR_EXT    0x8459\n#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A\n#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B\n#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C\n#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D\n#define GL_SECONDARY_COLOR_ARRAY_EXT      0x845E\n#endif\n\n#ifndef GL_EXT_texture_perturb_normal\n#define GL_PERTURB_EXT                    0x85AE\n#define GL_TEXTURE_NORMAL_EXT             0x85AF\n#endif\n\n#ifndef GL_EXT_multi_draw_arrays\n#endif\n\n#ifndef GL_EXT_fog_coord\n#define GL_FOG_COORDINATE_SOURCE_EXT      0x8450\n#define GL_FOG_COORDINATE_EXT             0x8451\n#define GL_FRAGMENT_DEPTH_EXT             0x8452\n#define GL_CURRENT_FOG_COORDINATE_EXT     0x8453\n#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT  0x8454\n#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455\n#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456\n#define GL_FOG_COORDINATE_ARRAY_EXT       0x8457\n#endif\n\n#ifndef GL_REND_screen_coordinates\n#define GL_SCREEN_COORDINATES_REND        0x8490\n#define GL_INVERTED_SCREEN_W_REND         0x8491\n#endif\n\n#ifndef GL_EXT_coordinate_frame\n#define GL_TANGENT_ARRAY_EXT              0x8439\n#define GL_BINORMAL_ARRAY_EXT             0x843A\n#define GL_CURRENT_TANGENT_EXT            0x843B\n#define GL_CURRENT_BINORMAL_EXT           0x843C\n#define GL_TANGENT_ARRAY_TYPE_EXT         0x843E\n#define GL_TANGENT_ARRAY_STRIDE_EXT       0x843F\n#define GL_BINORMAL_ARRAY_TYPE_EXT        0x8440\n#define GL_BINORMAL_ARRAY_STRIDE_EXT      0x8441\n#define GL_TANGENT_ARRAY_POINTER_EXT      0x8442\n#define GL_BINORMAL_ARRAY_POINTER_EXT     0x8443\n#define GL_MAP1_TANGENT_EXT               0x8444\n#define GL_MAP2_TANGENT_EXT               0x8445\n#define GL_MAP1_BINORMAL_EXT              0x8446\n#define GL_MAP2_BINORMAL_EXT              0x8447\n#endif\n\n#ifndef GL_EXT_texture_env_combine\n#define GL_COMBINE_EXT                    0x8570\n#define GL_COMBINE_RGB_EXT                0x8571\n#define GL_COMBINE_ALPHA_EXT              0x8572\n#define GL_RGB_SCALE_EXT                  0x8573\n#define GL_ADD_SIGNED_EXT                 0x8574\n#define GL_INTERPOLATE_EXT                0x8575\n#define GL_CONSTANT_EXT                   0x8576\n#define GL_PRIMARY_COLOR_EXT              0x8577\n#define GL_PREVIOUS_EXT                   0x8578\n#define GL_SOURCE0_RGB_EXT                0x8580\n#define GL_SOURCE1_RGB_EXT                0x8581\n#define GL_SOURCE2_RGB_EXT                0x8582\n#define GL_SOURCE0_ALPHA_EXT              0x8588\n#define GL_SOURCE1_ALPHA_EXT              0x8589\n#define GL_SOURCE2_ALPHA_EXT              0x858A\n#define GL_OPERAND0_RGB_EXT               0x8590\n#define GL_OPERAND1_RGB_EXT               0x8591\n#define GL_OPERAND2_RGB_EXT               0x8592\n#define GL_OPERAND0_ALPHA_EXT             0x8598\n#define GL_OPERAND1_ALPHA_EXT             0x8599\n#define GL_OPERAND2_ALPHA_EXT             0x859A\n#endif\n\n#ifndef GL_APPLE_specular_vector\n#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0\n#endif\n\n#ifndef GL_APPLE_transform_hint\n#define GL_TRANSFORM_HINT_APPLE           0x85B1\n#endif\n\n#ifndef GL_SGIX_fog_scale\n#define GL_FOG_SCALE_SGIX                 0x81FC\n#define GL_FOG_SCALE_VALUE_SGIX           0x81FD\n#endif\n\n#ifndef GL_SUNX_constant_data\n#define GL_UNPACK_CONSTANT_DATA_SUNX      0x81D5\n#define GL_TEXTURE_CONSTANT_DATA_SUNX     0x81D6\n#endif\n\n#ifndef GL_SUN_global_alpha\n#define GL_GLOBAL_ALPHA_SUN               0x81D9\n#define GL_GLOBAL_ALPHA_FACTOR_SUN        0x81DA\n#endif\n\n#ifndef GL_SUN_triangle_list\n#define GL_RESTART_SUN                    0x0001\n#define GL_REPLACE_MIDDLE_SUN             0x0002\n#define GL_REPLACE_OLDEST_SUN             0x0003\n#define GL_TRIANGLE_LIST_SUN              0x81D7\n#define GL_REPLACEMENT_CODE_SUN           0x81D8\n#define GL_REPLACEMENT_CODE_ARRAY_SUN     0x85C0\n#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1\n#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2\n#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3\n#define GL_R1UI_V3F_SUN                   0x85C4\n#define GL_R1UI_C4UB_V3F_SUN              0x85C5\n#define GL_R1UI_C3F_V3F_SUN               0x85C6\n#define GL_R1UI_N3F_V3F_SUN               0x85C7\n#define GL_R1UI_C4F_N3F_V3F_SUN           0x85C8\n#define GL_R1UI_T2F_V3F_SUN               0x85C9\n#define GL_R1UI_T2F_N3F_V3F_SUN           0x85CA\n#define GL_R1UI_T2F_C4F_N3F_V3F_SUN       0x85CB\n#endif\n\n#ifndef GL_SUN_vertex\n#endif\n\n#ifndef GL_EXT_blend_func_separate\n#define GL_BLEND_DST_RGB_EXT              0x80C8\n#define GL_BLEND_SRC_RGB_EXT              0x80C9\n#define GL_BLEND_DST_ALPHA_EXT            0x80CA\n#define GL_BLEND_SRC_ALPHA_EXT            0x80CB\n#endif\n\n#ifndef GL_INGR_color_clamp\n#define GL_RED_MIN_CLAMP_INGR             0x8560\n#define GL_GREEN_MIN_CLAMP_INGR           0x8561\n#define GL_BLUE_MIN_CLAMP_INGR            0x8562\n#define GL_ALPHA_MIN_CLAMP_INGR           0x8563\n#define GL_RED_MAX_CLAMP_INGR             0x8564\n#define GL_GREEN_MAX_CLAMP_INGR           0x8565\n#define GL_BLUE_MAX_CLAMP_INGR            0x8566\n#define GL_ALPHA_MAX_CLAMP_INGR           0x8567\n#endif\n\n#ifndef GL_INGR_interlace_read\n#define GL_INTERLACE_READ_INGR            0x8568\n#endif\n\n#ifndef GL_EXT_stencil_wrap\n#define GL_INCR_WRAP_EXT                  0x8507\n#define GL_DECR_WRAP_EXT                  0x8508\n#endif\n\n#ifndef GL_EXT_422_pixels\n#define GL_422_EXT                        0x80CC\n#define GL_422_REV_EXT                    0x80CD\n#define GL_422_AVERAGE_EXT                0x80CE\n#define GL_422_REV_AVERAGE_EXT            0x80CF\n#endif\n\n#ifndef GL_NV_texgen_reflection\n#define GL_NORMAL_MAP_NV                  0x8511\n#define GL_REFLECTION_MAP_NV              0x8512\n#endif\n\n#ifndef GL_EXT_texture_cube_map\n#define GL_NORMAL_MAP_EXT                 0x8511\n#define GL_REFLECTION_MAP_EXT             0x8512\n#define GL_TEXTURE_CUBE_MAP_EXT           0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP_EXT   0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP_EXT     0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT  0x851C\n#endif\n\n#ifndef GL_SUN_convolution_border_modes\n#define GL_WRAP_BORDER_SUN                0x81D4\n#endif\n\n#ifndef GL_EXT_texture_env_add\n#endif\n\n#ifndef GL_EXT_texture_lod_bias\n#define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD\n#define GL_TEXTURE_FILTER_CONTROL_EXT     0x8500\n#define GL_TEXTURE_LOD_BIAS_EXT           0x8501\n#endif\n\n#ifndef GL_EXT_texture_filter_anisotropic\n#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE\n#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF\n#endif\n\n#ifndef GL_EXT_vertex_weighting\n#define GL_MODELVIEW0_STACK_DEPTH_EXT     GL_MODELVIEW_STACK_DEPTH\n#define GL_MODELVIEW1_STACK_DEPTH_EXT     0x8502\n#define GL_MODELVIEW0_MATRIX_EXT          GL_MODELVIEW_MATRIX\n#define GL_MODELVIEW1_MATRIX_EXT          0x8506\n#define GL_VERTEX_WEIGHTING_EXT           0x8509\n#define GL_MODELVIEW0_EXT                 GL_MODELVIEW\n#define GL_MODELVIEW1_EXT                 0x850A\n#define GL_CURRENT_VERTEX_WEIGHT_EXT      0x850B\n#define GL_VERTEX_WEIGHT_ARRAY_EXT        0x850C\n#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT   0x850D\n#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT   0x850E\n#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F\n#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510\n#endif\n\n#ifndef GL_NV_light_max_exponent\n#define GL_MAX_SHININESS_NV               0x8504\n#define GL_MAX_SPOT_EXPONENT_NV           0x8505\n#endif\n\n#ifndef GL_NV_vertex_array_range\n#define GL_VERTEX_ARRAY_RANGE_NV          0x851D\n#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV   0x851E\n#define GL_VERTEX_ARRAY_RANGE_VALID_NV    0x851F\n#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520\n#define GL_VERTEX_ARRAY_RANGE_POINTER_NV  0x8521\n#endif\n\n#ifndef GL_NV_register_combiners\n#define GL_REGISTER_COMBINERS_NV          0x8522\n#define GL_VARIABLE_A_NV                  0x8523\n#define GL_VARIABLE_B_NV                  0x8524\n#define GL_VARIABLE_C_NV                  0x8525\n#define GL_VARIABLE_D_NV                  0x8526\n#define GL_VARIABLE_E_NV                  0x8527\n#define GL_VARIABLE_F_NV                  0x8528\n#define GL_VARIABLE_G_NV                  0x8529\n#define GL_CONSTANT_COLOR0_NV             0x852A\n#define GL_CONSTANT_COLOR1_NV             0x852B\n#define GL_PRIMARY_COLOR_NV               0x852C\n#define GL_SECONDARY_COLOR_NV             0x852D\n#define GL_SPARE0_NV                      0x852E\n#define GL_SPARE1_NV                      0x852F\n#define GL_DISCARD_NV                     0x8530\n#define GL_E_TIMES_F_NV                   0x8531\n#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532\n#define GL_UNSIGNED_IDENTITY_NV           0x8536\n#define GL_UNSIGNED_INVERT_NV             0x8537\n#define GL_EXPAND_NORMAL_NV               0x8538\n#define GL_EXPAND_NEGATE_NV               0x8539\n#define GL_HALF_BIAS_NORMAL_NV            0x853A\n#define GL_HALF_BIAS_NEGATE_NV            0x853B\n#define GL_SIGNED_IDENTITY_NV             0x853C\n#define GL_SIGNED_NEGATE_NV               0x853D\n#define GL_SCALE_BY_TWO_NV                0x853E\n#define GL_SCALE_BY_FOUR_NV               0x853F\n#define GL_SCALE_BY_ONE_HALF_NV           0x8540\n#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV   0x8541\n#define GL_COMBINER_INPUT_NV              0x8542\n#define GL_COMBINER_MAPPING_NV            0x8543\n#define GL_COMBINER_COMPONENT_USAGE_NV    0x8544\n#define GL_COMBINER_AB_DOT_PRODUCT_NV     0x8545\n#define GL_COMBINER_CD_DOT_PRODUCT_NV     0x8546\n#define GL_COMBINER_MUX_SUM_NV            0x8547\n#define GL_COMBINER_SCALE_NV              0x8548\n#define GL_COMBINER_BIAS_NV               0x8549\n#define GL_COMBINER_AB_OUTPUT_NV          0x854A\n#define GL_COMBINER_CD_OUTPUT_NV          0x854B\n#define GL_COMBINER_SUM_OUTPUT_NV         0x854C\n#define GL_MAX_GENERAL_COMBINERS_NV       0x854D\n#define GL_NUM_GENERAL_COMBINERS_NV       0x854E\n#define GL_COLOR_SUM_CLAMP_NV             0x854F\n#define GL_COMBINER0_NV                   0x8550\n#define GL_COMBINER1_NV                   0x8551\n#define GL_COMBINER2_NV                   0x8552\n#define GL_COMBINER3_NV                   0x8553\n#define GL_COMBINER4_NV                   0x8554\n#define GL_COMBINER5_NV                   0x8555\n#define GL_COMBINER6_NV                   0x8556\n#define GL_COMBINER7_NV                   0x8557\n/* reuse GL_TEXTURE0_ARB */\n/* reuse GL_TEXTURE1_ARB */\n/* reuse GL_ZERO */\n/* reuse GL_NONE */\n/* reuse GL_FOG */\n#endif\n\n#ifndef GL_NV_fog_distance\n#define GL_FOG_DISTANCE_MODE_NV           0x855A\n#define GL_EYE_RADIAL_NV                  0x855B\n#define GL_EYE_PLANE_ABSOLUTE_NV          0x855C\n/* reuse GL_EYE_PLANE */\n#endif\n\n#ifndef GL_NV_texgen_emboss\n#define GL_EMBOSS_LIGHT_NV                0x855D\n#define GL_EMBOSS_CONSTANT_NV             0x855E\n#define GL_EMBOSS_MAP_NV                  0x855F\n#endif\n\n#ifndef GL_NV_blend_square\n#endif\n\n#ifndef GL_NV_texture_env_combine4\n#define GL_COMBINE4_NV                    0x8503\n#define GL_SOURCE3_RGB_NV                 0x8583\n#define GL_SOURCE3_ALPHA_NV               0x858B\n#define GL_OPERAND3_RGB_NV                0x8593\n#define GL_OPERAND3_ALPHA_NV              0x859B\n#endif\n\n#ifndef GL_MESA_resize_buffers\n#endif\n\n#ifndef GL_MESA_window_pos\n#endif\n\n#ifndef GL_EXT_texture_compression_s3tc\n#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0\n#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1\n#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2\n#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3\n#endif\n\n#ifndef GL_IBM_cull_vertex\n#define GL_CULL_VERTEX_IBM                103050\n#endif\n\n#ifndef GL_IBM_multimode_draw_arrays\n#endif\n\n#ifndef GL_IBM_vertex_array_lists\n#define GL_VERTEX_ARRAY_LIST_IBM          103070\n#define GL_NORMAL_ARRAY_LIST_IBM          103071\n#define GL_COLOR_ARRAY_LIST_IBM           103072\n#define GL_INDEX_ARRAY_LIST_IBM           103073\n#define GL_TEXTURE_COORD_ARRAY_LIST_IBM   103074\n#define GL_EDGE_FLAG_ARRAY_LIST_IBM       103075\n#define GL_FOG_COORDINATE_ARRAY_LIST_IBM  103076\n#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077\n#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM   103080\n#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM   103081\n#define GL_COLOR_ARRAY_LIST_STRIDE_IBM    103082\n#define GL_INDEX_ARRAY_LIST_STRIDE_IBM    103083\n#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084\n#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085\n#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086\n#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087\n#endif\n\n#ifndef GL_SGIX_subsample\n#define GL_PACK_SUBSAMPLE_RATE_SGIX       0x85A0\n#define GL_UNPACK_SUBSAMPLE_RATE_SGIX     0x85A1\n#define GL_PIXEL_SUBSAMPLE_4444_SGIX      0x85A2\n#define GL_PIXEL_SUBSAMPLE_2424_SGIX      0x85A3\n#define GL_PIXEL_SUBSAMPLE_4242_SGIX      0x85A4\n#endif\n\n#ifndef GL_SGIX_ycrcb_subsample\n#endif\n\n#ifndef GL_SGIX_ycrcba\n#define GL_YCRCB_SGIX                     0x8318\n#define GL_YCRCBA_SGIX                    0x8319\n#endif\n\n#ifndef GL_SGI_depth_pass_instrument\n#define GL_DEPTH_PASS_INSTRUMENT_SGIX     0x8310\n#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311\n#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312\n#endif\n\n#ifndef GL_3DFX_texture_compression_FXT1\n#define GL_COMPRESSED_RGB_FXT1_3DFX       0x86B0\n#define GL_COMPRESSED_RGBA_FXT1_3DFX      0x86B1\n#endif\n\n#ifndef GL_3DFX_multisample\n#define GL_MULTISAMPLE_3DFX               0x86B2\n#define GL_SAMPLE_BUFFERS_3DFX            0x86B3\n#define GL_SAMPLES_3DFX                   0x86B4\n#define GL_MULTISAMPLE_BIT_3DFX           0x20000000\n#endif\n\n#ifndef GL_3DFX_tbuffer\n#endif\n\n#ifndef GL_EXT_multisample\n#define GL_MULTISAMPLE_EXT                0x809D\n#define GL_SAMPLE_ALPHA_TO_MASK_EXT       0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_EXT        0x809F\n#define GL_SAMPLE_MASK_EXT                0x80A0\n#define GL_1PASS_EXT                      0x80A1\n#define GL_2PASS_0_EXT                    0x80A2\n#define GL_2PASS_1_EXT                    0x80A3\n#define GL_4PASS_0_EXT                    0x80A4\n#define GL_4PASS_1_EXT                    0x80A5\n#define GL_4PASS_2_EXT                    0x80A6\n#define GL_4PASS_3_EXT                    0x80A7\n#define GL_SAMPLE_BUFFERS_EXT             0x80A8\n#define GL_SAMPLES_EXT                    0x80A9\n#define GL_SAMPLE_MASK_VALUE_EXT          0x80AA\n#define GL_SAMPLE_MASK_INVERT_EXT         0x80AB\n#define GL_SAMPLE_PATTERN_EXT             0x80AC\n#define GL_MULTISAMPLE_BIT_EXT            0x20000000\n#endif\n\n#ifndef GL_SGIX_vertex_preclip\n#define GL_VERTEX_PRECLIP_SGIX            0x83EE\n#define GL_VERTEX_PRECLIP_HINT_SGIX       0x83EF\n#endif\n\n#ifndef GL_SGIX_convolution_accuracy\n#define GL_CONVOLUTION_HINT_SGIX          0x8316\n#endif\n\n#ifndef GL_SGIX_resample\n#define GL_PACK_RESAMPLE_SGIX             0x842C\n#define GL_UNPACK_RESAMPLE_SGIX           0x842D\n#define GL_RESAMPLE_REPLICATE_SGIX        0x842E\n#define GL_RESAMPLE_ZERO_FILL_SGIX        0x842F\n#define GL_RESAMPLE_DECIMATE_SGIX         0x8430\n#endif\n\n#ifndef GL_SGIS_point_line_texgen\n#define GL_EYE_DISTANCE_TO_POINT_SGIS     0x81F0\n#define GL_OBJECT_DISTANCE_TO_POINT_SGIS  0x81F1\n#define GL_EYE_DISTANCE_TO_LINE_SGIS      0x81F2\n#define GL_OBJECT_DISTANCE_TO_LINE_SGIS   0x81F3\n#define GL_EYE_POINT_SGIS                 0x81F4\n#define GL_OBJECT_POINT_SGIS              0x81F5\n#define GL_EYE_LINE_SGIS                  0x81F6\n#define GL_OBJECT_LINE_SGIS               0x81F7\n#endif\n\n#ifndef GL_SGIS_texture_color_mask\n#define GL_TEXTURE_COLOR_WRITEMASK_SGIS   0x81EF\n#endif\n\n#ifndef GL_EXT_texture_env_dot3\n#define GL_DOT3_RGB_EXT                   0x8740\n#define GL_DOT3_RGBA_EXT                  0x8741\n#endif\n\n#ifndef GL_ATI_texture_mirror_once\n#define GL_MIRROR_CLAMP_ATI               0x8742\n#define GL_MIRROR_CLAMP_TO_EDGE_ATI       0x8743\n#endif\n\n#ifndef GL_NV_fence\n#define GL_ALL_COMPLETED_NV               0x84F2\n#define GL_FENCE_STATUS_NV                0x84F3\n#define GL_FENCE_CONDITION_NV             0x84F4\n#endif\n\n#ifndef GL_IBM_texture_mirrored_repeat\n#define GL_MIRRORED_REPEAT_IBM            0x8370\n#endif\n\n#ifndef GL_NV_evaluators\n#define GL_EVAL_2D_NV                     0x86C0\n#define GL_EVAL_TRIANGULAR_2D_NV          0x86C1\n#define GL_MAP_TESSELLATION_NV            0x86C2\n#define GL_MAP_ATTRIB_U_ORDER_NV          0x86C3\n#define GL_MAP_ATTRIB_V_ORDER_NV          0x86C4\n#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5\n#define GL_EVAL_VERTEX_ATTRIB0_NV         0x86C6\n#define GL_EVAL_VERTEX_ATTRIB1_NV         0x86C7\n#define GL_EVAL_VERTEX_ATTRIB2_NV         0x86C8\n#define GL_EVAL_VERTEX_ATTRIB3_NV         0x86C9\n#define GL_EVAL_VERTEX_ATTRIB4_NV         0x86CA\n#define GL_EVAL_VERTEX_ATTRIB5_NV         0x86CB\n#define GL_EVAL_VERTEX_ATTRIB6_NV         0x86CC\n#define GL_EVAL_VERTEX_ATTRIB7_NV         0x86CD\n#define GL_EVAL_VERTEX_ATTRIB8_NV         0x86CE\n#define GL_EVAL_VERTEX_ATTRIB9_NV         0x86CF\n#define GL_EVAL_VERTEX_ATTRIB10_NV        0x86D0\n#define GL_EVAL_VERTEX_ATTRIB11_NV        0x86D1\n#define GL_EVAL_VERTEX_ATTRIB12_NV        0x86D2\n#define GL_EVAL_VERTEX_ATTRIB13_NV        0x86D3\n#define GL_EVAL_VERTEX_ATTRIB14_NV        0x86D4\n#define GL_EVAL_VERTEX_ATTRIB15_NV        0x86D5\n#define GL_MAX_MAP_TESSELLATION_NV        0x86D6\n#define GL_MAX_RATIONAL_EVAL_ORDER_NV     0x86D7\n#endif\n\n#ifndef GL_NV_packed_depth_stencil\n#define GL_DEPTH_STENCIL_NV               0x84F9\n#define GL_UNSIGNED_INT_24_8_NV           0x84FA\n#endif\n\n#ifndef GL_NV_register_combiners2\n#define GL_PER_STAGE_CONSTANTS_NV         0x8535\n#endif\n\n#ifndef GL_NV_texture_compression_vtc\n#endif\n\n#ifndef GL_NV_texture_rectangle\n#define GL_TEXTURE_RECTANGLE_NV           0x84F5\n#define GL_TEXTURE_BINDING_RECTANGLE_NV   0x84F6\n#define GL_PROXY_TEXTURE_RECTANGLE_NV     0x84F7\n#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV  0x84F8\n#endif\n\n#ifndef GL_NV_texture_shader\n#define GL_OFFSET_TEXTURE_RECTANGLE_NV    0x864C\n#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D\n#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E\n#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9\n#define GL_UNSIGNED_INT_S8_S8_8_8_NV      0x86DA\n#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  0x86DB\n#define GL_DSDT_MAG_INTENSITY_NV          0x86DC\n#define GL_SHADER_CONSISTENT_NV           0x86DD\n#define GL_TEXTURE_SHADER_NV              0x86DE\n#define GL_SHADER_OPERATION_NV            0x86DF\n#define GL_CULL_MODES_NV                  0x86E0\n#define GL_OFFSET_TEXTURE_MATRIX_NV       0x86E1\n#define GL_OFFSET_TEXTURE_SCALE_NV        0x86E2\n#define GL_OFFSET_TEXTURE_BIAS_NV         0x86E3\n#define GL_OFFSET_TEXTURE_2D_MATRIX_NV    GL_OFFSET_TEXTURE_MATRIX_NV\n#define GL_OFFSET_TEXTURE_2D_SCALE_NV     GL_OFFSET_TEXTURE_SCALE_NV\n#define GL_OFFSET_TEXTURE_2D_BIAS_NV      GL_OFFSET_TEXTURE_BIAS_NV\n#define GL_PREVIOUS_TEXTURE_INPUT_NV      0x86E4\n#define GL_CONST_EYE_NV                   0x86E5\n#define GL_PASS_THROUGH_NV                0x86E6\n#define GL_CULL_FRAGMENT_NV               0x86E7\n#define GL_OFFSET_TEXTURE_2D_NV           0x86E8\n#define GL_DEPENDENT_AR_TEXTURE_2D_NV     0x86E9\n#define GL_DEPENDENT_GB_TEXTURE_2D_NV     0x86EA\n#define GL_DOT_PRODUCT_NV                 0x86EC\n#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV   0x86ED\n#define GL_DOT_PRODUCT_TEXTURE_2D_NV      0x86EE\n#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0\n#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1\n#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2\n#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3\n#define GL_HILO_NV                        0x86F4\n#define GL_DSDT_NV                        0x86F5\n#define GL_DSDT_MAG_NV                    0x86F6\n#define GL_DSDT_MAG_VIB_NV                0x86F7\n#define GL_HILO16_NV                      0x86F8\n#define GL_SIGNED_HILO_NV                 0x86F9\n#define GL_SIGNED_HILO16_NV               0x86FA\n#define GL_SIGNED_RGBA_NV                 0x86FB\n#define GL_SIGNED_RGBA8_NV                0x86FC\n#define GL_SIGNED_RGB_NV                  0x86FE\n#define GL_SIGNED_RGB8_NV                 0x86FF\n#define GL_SIGNED_LUMINANCE_NV            0x8701\n#define GL_SIGNED_LUMINANCE8_NV           0x8702\n#define GL_SIGNED_LUMINANCE_ALPHA_NV      0x8703\n#define GL_SIGNED_LUMINANCE8_ALPHA8_NV    0x8704\n#define GL_SIGNED_ALPHA_NV                0x8705\n#define GL_SIGNED_ALPHA8_NV               0x8706\n#define GL_SIGNED_INTENSITY_NV            0x8707\n#define GL_SIGNED_INTENSITY8_NV           0x8708\n#define GL_DSDT8_NV                       0x8709\n#define GL_DSDT8_MAG8_NV                  0x870A\n#define GL_DSDT8_MAG8_INTENSITY8_NV       0x870B\n#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV   0x870C\n#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D\n#define GL_HI_SCALE_NV                    0x870E\n#define GL_LO_SCALE_NV                    0x870F\n#define GL_DS_SCALE_NV                    0x8710\n#define GL_DT_SCALE_NV                    0x8711\n#define GL_MAGNITUDE_SCALE_NV             0x8712\n#define GL_VIBRANCE_SCALE_NV              0x8713\n#define GL_HI_BIAS_NV                     0x8714\n#define GL_LO_BIAS_NV                     0x8715\n#define GL_DS_BIAS_NV                     0x8716\n#define GL_DT_BIAS_NV                     0x8717\n#define GL_MAGNITUDE_BIAS_NV              0x8718\n#define GL_VIBRANCE_BIAS_NV               0x8719\n#define GL_TEXTURE_BORDER_VALUES_NV       0x871A\n#define GL_TEXTURE_HI_SIZE_NV             0x871B\n#define GL_TEXTURE_LO_SIZE_NV             0x871C\n#define GL_TEXTURE_DS_SIZE_NV             0x871D\n#define GL_TEXTURE_DT_SIZE_NV             0x871E\n#define GL_TEXTURE_MAG_SIZE_NV            0x871F\n#endif\n\n#ifndef GL_NV_texture_shader2\n#define GL_DOT_PRODUCT_TEXTURE_3D_NV      0x86EF\n#endif\n\n#ifndef GL_NV_vertex_array_range2\n#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533\n#endif\n\n#ifndef GL_NV_vertex_program\n#define GL_VERTEX_PROGRAM_NV              0x8620\n#define GL_VERTEX_STATE_PROGRAM_NV        0x8621\n#define GL_ATTRIB_ARRAY_SIZE_NV           0x8623\n#define GL_ATTRIB_ARRAY_STRIDE_NV         0x8624\n#define GL_ATTRIB_ARRAY_TYPE_NV           0x8625\n#define GL_CURRENT_ATTRIB_NV              0x8626\n#define GL_PROGRAM_LENGTH_NV              0x8627\n#define GL_PROGRAM_STRING_NV              0x8628\n#define GL_MODELVIEW_PROJECTION_NV        0x8629\n#define GL_IDENTITY_NV                    0x862A\n#define GL_INVERSE_NV                     0x862B\n#define GL_TRANSPOSE_NV                   0x862C\n#define GL_INVERSE_TRANSPOSE_NV           0x862D\n#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E\n#define GL_MAX_TRACK_MATRICES_NV          0x862F\n#define GL_MATRIX0_NV                     0x8630\n#define GL_MATRIX1_NV                     0x8631\n#define GL_MATRIX2_NV                     0x8632\n#define GL_MATRIX3_NV                     0x8633\n#define GL_MATRIX4_NV                     0x8634\n#define GL_MATRIX5_NV                     0x8635\n#define GL_MATRIX6_NV                     0x8636\n#define GL_MATRIX7_NV                     0x8637\n#define GL_CURRENT_MATRIX_STACK_DEPTH_NV  0x8640\n#define GL_CURRENT_MATRIX_NV              0x8641\n#define GL_VERTEX_PROGRAM_POINT_SIZE_NV   0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE_NV     0x8643\n#define GL_PROGRAM_PARAMETER_NV           0x8644\n#define GL_ATTRIB_ARRAY_POINTER_NV        0x8645\n#define GL_PROGRAM_TARGET_NV              0x8646\n#define GL_PROGRAM_RESIDENT_NV            0x8647\n#define GL_TRACK_MATRIX_NV                0x8648\n#define GL_TRACK_MATRIX_TRANSFORM_NV      0x8649\n#define GL_VERTEX_PROGRAM_BINDING_NV      0x864A\n#define GL_PROGRAM_ERROR_POSITION_NV      0x864B\n#define GL_VERTEX_ATTRIB_ARRAY0_NV        0x8650\n#define GL_VERTEX_ATTRIB_ARRAY1_NV        0x8651\n#define GL_VERTEX_ATTRIB_ARRAY2_NV        0x8652\n#define GL_VERTEX_ATTRIB_ARRAY3_NV        0x8653\n#define GL_VERTEX_ATTRIB_ARRAY4_NV        0x8654\n#define GL_VERTEX_ATTRIB_ARRAY5_NV        0x8655\n#define GL_VERTEX_ATTRIB_ARRAY6_NV        0x8656\n#define GL_VERTEX_ATTRIB_ARRAY7_NV        0x8657\n#define GL_VERTEX_ATTRIB_ARRAY8_NV        0x8658\n#define GL_VERTEX_ATTRIB_ARRAY9_NV        0x8659\n#define GL_VERTEX_ATTRIB_ARRAY10_NV       0x865A\n#define GL_VERTEX_ATTRIB_ARRAY11_NV       0x865B\n#define GL_VERTEX_ATTRIB_ARRAY12_NV       0x865C\n#define GL_VERTEX_ATTRIB_ARRAY13_NV       0x865D\n#define GL_VERTEX_ATTRIB_ARRAY14_NV       0x865E\n#define GL_VERTEX_ATTRIB_ARRAY15_NV       0x865F\n#define GL_MAP1_VERTEX_ATTRIB0_4_NV       0x8660\n#define GL_MAP1_VERTEX_ATTRIB1_4_NV       0x8661\n#define GL_MAP1_VERTEX_ATTRIB2_4_NV       0x8662\n#define GL_MAP1_VERTEX_ATTRIB3_4_NV       0x8663\n#define GL_MAP1_VERTEX_ATTRIB4_4_NV       0x8664\n#define GL_MAP1_VERTEX_ATTRIB5_4_NV       0x8665\n#define GL_MAP1_VERTEX_ATTRIB6_4_NV       0x8666\n#define GL_MAP1_VERTEX_ATTRIB7_4_NV       0x8667\n#define GL_MAP1_VERTEX_ATTRIB8_4_NV       0x8668\n#define GL_MAP1_VERTEX_ATTRIB9_4_NV       0x8669\n#define GL_MAP1_VERTEX_ATTRIB10_4_NV      0x866A\n#define GL_MAP1_VERTEX_ATTRIB11_4_NV      0x866B\n#define GL_MAP1_VERTEX_ATTRIB12_4_NV      0x866C\n#define GL_MAP1_VERTEX_ATTRIB13_4_NV      0x866D\n#define GL_MAP1_VERTEX_ATTRIB14_4_NV      0x866E\n#define GL_MAP1_VERTEX_ATTRIB15_4_NV      0x866F\n#define GL_MAP2_VERTEX_ATTRIB0_4_NV       0x8670\n#define GL_MAP2_VERTEX_ATTRIB1_4_NV       0x8671\n#define GL_MAP2_VERTEX_ATTRIB2_4_NV       0x8672\n#define GL_MAP2_VERTEX_ATTRIB3_4_NV       0x8673\n#define GL_MAP2_VERTEX_ATTRIB4_4_NV       0x8674\n#define GL_MAP2_VERTEX_ATTRIB5_4_NV       0x8675\n#define GL_MAP2_VERTEX_ATTRIB6_4_NV       0x8676\n#define GL_MAP2_VERTEX_ATTRIB7_4_NV       0x8677\n#define GL_MAP2_VERTEX_ATTRIB8_4_NV       0x8678\n#define GL_MAP2_VERTEX_ATTRIB9_4_NV       0x8679\n#define GL_MAP2_VERTEX_ATTRIB10_4_NV      0x867A\n#define GL_MAP2_VERTEX_ATTRIB11_4_NV      0x867B\n#define GL_MAP2_VERTEX_ATTRIB12_4_NV      0x867C\n#define GL_MAP2_VERTEX_ATTRIB13_4_NV      0x867D\n#define GL_MAP2_VERTEX_ATTRIB14_4_NV      0x867E\n#define GL_MAP2_VERTEX_ATTRIB15_4_NV      0x867F\n#endif\n\n#ifndef GL_SGIX_texture_coordinate_clamp\n#define GL_TEXTURE_MAX_CLAMP_S_SGIX       0x8369\n#define GL_TEXTURE_MAX_CLAMP_T_SGIX       0x836A\n#define GL_TEXTURE_MAX_CLAMP_R_SGIX       0x836B\n#endif\n\n#ifndef GL_SGIX_scalebias_hint\n#define GL_SCALEBIAS_HINT_SGIX            0x8322\n#endif\n\n#ifndef GL_OML_interlace\n#define GL_INTERLACE_OML                  0x8980\n#define GL_INTERLACE_READ_OML             0x8981\n#endif\n\n#ifndef GL_OML_subsample\n#define GL_FORMAT_SUBSAMPLE_24_24_OML     0x8982\n#define GL_FORMAT_SUBSAMPLE_244_244_OML   0x8983\n#endif\n\n#ifndef GL_OML_resample\n#define GL_PACK_RESAMPLE_OML              0x8984\n#define GL_UNPACK_RESAMPLE_OML            0x8985\n#define GL_RESAMPLE_REPLICATE_OML         0x8986\n#define GL_RESAMPLE_ZERO_FILL_OML         0x8987\n#define GL_RESAMPLE_AVERAGE_OML           0x8988\n#define GL_RESAMPLE_DECIMATE_OML          0x8989\n#endif\n\n#ifndef GL_NV_copy_depth_to_color\n#define GL_DEPTH_STENCIL_TO_RGBA_NV       0x886E\n#define GL_DEPTH_STENCIL_TO_BGRA_NV       0x886F\n#endif\n\n#ifndef GL_ATI_envmap_bumpmap\n#define GL_BUMP_ROT_MATRIX_ATI            0x8775\n#define GL_BUMP_ROT_MATRIX_SIZE_ATI       0x8776\n#define GL_BUMP_NUM_TEX_UNITS_ATI         0x8777\n#define GL_BUMP_TEX_UNITS_ATI             0x8778\n#define GL_DUDV_ATI                       0x8779\n#define GL_DU8DV8_ATI                     0x877A\n#define GL_BUMP_ENVMAP_ATI                0x877B\n#define GL_BUMP_TARGET_ATI                0x877C\n#endif\n\n#ifndef GL_ATI_fragment_shader\n#define GL_FRAGMENT_SHADER_ATI            0x8920\n#define GL_REG_0_ATI                      0x8921\n#define GL_REG_1_ATI                      0x8922\n#define GL_REG_2_ATI                      0x8923\n#define GL_REG_3_ATI                      0x8924\n#define GL_REG_4_ATI                      0x8925\n#define GL_REG_5_ATI                      0x8926\n#define GL_REG_6_ATI                      0x8927\n#define GL_REG_7_ATI                      0x8928\n#define GL_REG_8_ATI                      0x8929\n#define GL_REG_9_ATI                      0x892A\n#define GL_REG_10_ATI                     0x892B\n#define GL_REG_11_ATI                     0x892C\n#define GL_REG_12_ATI                     0x892D\n#define GL_REG_13_ATI                     0x892E\n#define GL_REG_14_ATI                     0x892F\n#define GL_REG_15_ATI                     0x8930\n#define GL_REG_16_ATI                     0x8931\n#define GL_REG_17_ATI                     0x8932\n#define GL_REG_18_ATI                     0x8933\n#define GL_REG_19_ATI                     0x8934\n#define GL_REG_20_ATI                     0x8935\n#define GL_REG_21_ATI                     0x8936\n#define GL_REG_22_ATI                     0x8937\n#define GL_REG_23_ATI                     0x8938\n#define GL_REG_24_ATI                     0x8939\n#define GL_REG_25_ATI                     0x893A\n#define GL_REG_26_ATI                     0x893B\n#define GL_REG_27_ATI                     0x893C\n#define GL_REG_28_ATI                     0x893D\n#define GL_REG_29_ATI                     0x893E\n#define GL_REG_30_ATI                     0x893F\n#define GL_REG_31_ATI                     0x8940\n#define GL_CON_0_ATI                      0x8941\n#define GL_CON_1_ATI                      0x8942\n#define GL_CON_2_ATI                      0x8943\n#define GL_CON_3_ATI                      0x8944\n#define GL_CON_4_ATI                      0x8945\n#define GL_CON_5_ATI                      0x8946\n#define GL_CON_6_ATI                      0x8947\n#define GL_CON_7_ATI                      0x8948\n#define GL_CON_8_ATI                      0x8949\n#define GL_CON_9_ATI                      0x894A\n#define GL_CON_10_ATI                     0x894B\n#define GL_CON_11_ATI                     0x894C\n#define GL_CON_12_ATI                     0x894D\n#define GL_CON_13_ATI                     0x894E\n#define GL_CON_14_ATI                     0x894F\n#define GL_CON_15_ATI                     0x8950\n#define GL_CON_16_ATI                     0x8951\n#define GL_CON_17_ATI                     0x8952\n#define GL_CON_18_ATI                     0x8953\n#define GL_CON_19_ATI                     0x8954\n#define GL_CON_20_ATI                     0x8955\n#define GL_CON_21_ATI                     0x8956\n#define GL_CON_22_ATI                     0x8957\n#define GL_CON_23_ATI                     0x8958\n#define GL_CON_24_ATI                     0x8959\n#define GL_CON_25_ATI                     0x895A\n#define GL_CON_26_ATI                     0x895B\n#define GL_CON_27_ATI                     0x895C\n#define GL_CON_28_ATI                     0x895D\n#define GL_CON_29_ATI                     0x895E\n#define GL_CON_30_ATI                     0x895F\n#define GL_CON_31_ATI                     0x8960\n#define GL_MOV_ATI                        0x8961\n#define GL_ADD_ATI                        0x8963\n#define GL_MUL_ATI                        0x8964\n#define GL_SUB_ATI                        0x8965\n#define GL_DOT3_ATI                       0x8966\n#define GL_DOT4_ATI                       0x8967\n#define GL_MAD_ATI                        0x8968\n#define GL_LERP_ATI                       0x8969\n#define GL_CND_ATI                        0x896A\n#define GL_CND0_ATI                       0x896B\n#define GL_DOT2_ADD_ATI                   0x896C\n#define GL_SECONDARY_INTERPOLATOR_ATI     0x896D\n#define GL_NUM_FRAGMENT_REGISTERS_ATI     0x896E\n#define GL_NUM_FRAGMENT_CONSTANTS_ATI     0x896F\n#define GL_NUM_PASSES_ATI                 0x8970\n#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI  0x8971\n#define GL_NUM_INSTRUCTIONS_TOTAL_ATI     0x8972\n#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973\n#define GL_NUM_LOOPBACK_COMPONENTS_ATI    0x8974\n#define GL_COLOR_ALPHA_PAIRING_ATI        0x8975\n#define GL_SWIZZLE_STR_ATI                0x8976\n#define GL_SWIZZLE_STQ_ATI                0x8977\n#define GL_SWIZZLE_STR_DR_ATI             0x8978\n#define GL_SWIZZLE_STQ_DQ_ATI             0x8979\n#define GL_SWIZZLE_STRQ_ATI               0x897A\n#define GL_SWIZZLE_STRQ_DQ_ATI            0x897B\n#define GL_RED_BIT_ATI                    0x00000001\n#define GL_GREEN_BIT_ATI                  0x00000002\n#define GL_BLUE_BIT_ATI                   0x00000004\n#define GL_2X_BIT_ATI                     0x00000001\n#define GL_4X_BIT_ATI                     0x00000002\n#define GL_8X_BIT_ATI                     0x00000004\n#define GL_HALF_BIT_ATI                   0x00000008\n#define GL_QUARTER_BIT_ATI                0x00000010\n#define GL_EIGHTH_BIT_ATI                 0x00000020\n#define GL_SATURATE_BIT_ATI               0x00000040\n#define GL_COMP_BIT_ATI                   0x00000002\n#define GL_NEGATE_BIT_ATI                 0x00000004\n#define GL_BIAS_BIT_ATI                   0x00000008\n#endif\n\n#ifndef GL_ATI_pn_triangles\n#define GL_PN_TRIANGLES_ATI               0x87F0\n#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1\n#define GL_PN_TRIANGLES_POINT_MODE_ATI    0x87F2\n#define GL_PN_TRIANGLES_NORMAL_MODE_ATI   0x87F3\n#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4\n#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5\n#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6\n#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7\n#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8\n#endif\n\n#ifndef GL_ATI_vertex_array_object\n#define GL_STATIC_ATI                     0x8760\n#define GL_DYNAMIC_ATI                    0x8761\n#define GL_PRESERVE_ATI                   0x8762\n#define GL_DISCARD_ATI                    0x8763\n#define GL_OBJECT_BUFFER_SIZE_ATI         0x8764\n#define GL_OBJECT_BUFFER_USAGE_ATI        0x8765\n#define GL_ARRAY_OBJECT_BUFFER_ATI        0x8766\n#define GL_ARRAY_OBJECT_OFFSET_ATI        0x8767\n#endif\n\n#ifndef GL_EXT_vertex_shader\n#define GL_VERTEX_SHADER_EXT              0x8780\n#define GL_VERTEX_SHADER_BINDING_EXT      0x8781\n#define GL_OP_INDEX_EXT                   0x8782\n#define GL_OP_NEGATE_EXT                  0x8783\n#define GL_OP_DOT3_EXT                    0x8784\n#define GL_OP_DOT4_EXT                    0x8785\n#define GL_OP_MUL_EXT                     0x8786\n#define GL_OP_ADD_EXT                     0x8787\n#define GL_OP_MADD_EXT                    0x8788\n#define GL_OP_FRAC_EXT                    0x8789\n#define GL_OP_MAX_EXT                     0x878A\n#define GL_OP_MIN_EXT                     0x878B\n#define GL_OP_SET_GE_EXT                  0x878C\n#define GL_OP_SET_LT_EXT                  0x878D\n#define GL_OP_CLAMP_EXT                   0x878E\n#define GL_OP_FLOOR_EXT                   0x878F\n#define GL_OP_ROUND_EXT                   0x8790\n#define GL_OP_EXP_BASE_2_EXT              0x8791\n#define GL_OP_LOG_BASE_2_EXT              0x8792\n#define GL_OP_POWER_EXT                   0x8793\n#define GL_OP_RECIP_EXT                   0x8794\n#define GL_OP_RECIP_SQRT_EXT              0x8795\n#define GL_OP_SUB_EXT                     0x8796\n#define GL_OP_CROSS_PRODUCT_EXT           0x8797\n#define GL_OP_MULTIPLY_MATRIX_EXT         0x8798\n#define GL_OP_MOV_EXT                     0x8799\n#define GL_OUTPUT_VERTEX_EXT              0x879A\n#define GL_OUTPUT_COLOR0_EXT              0x879B\n#define GL_OUTPUT_COLOR1_EXT              0x879C\n#define GL_OUTPUT_TEXTURE_COORD0_EXT      0x879D\n#define GL_OUTPUT_TEXTURE_COORD1_EXT      0x879E\n#define GL_OUTPUT_TEXTURE_COORD2_EXT      0x879F\n#define GL_OUTPUT_TEXTURE_COORD3_EXT      0x87A0\n#define GL_OUTPUT_TEXTURE_COORD4_EXT      0x87A1\n#define GL_OUTPUT_TEXTURE_COORD5_EXT      0x87A2\n#define GL_OUTPUT_TEXTURE_COORD6_EXT      0x87A3\n#define GL_OUTPUT_TEXTURE_COORD7_EXT      0x87A4\n#define GL_OUTPUT_TEXTURE_COORD8_EXT      0x87A5\n#define GL_OUTPUT_TEXTURE_COORD9_EXT      0x87A6\n#define GL_OUTPUT_TEXTURE_COORD10_EXT     0x87A7\n#define GL_OUTPUT_TEXTURE_COORD11_EXT     0x87A8\n#define GL_OUTPUT_TEXTURE_COORD12_EXT     0x87A9\n#define GL_OUTPUT_TEXTURE_COORD13_EXT     0x87AA\n#define GL_OUTPUT_TEXTURE_COORD14_EXT     0x87AB\n#define GL_OUTPUT_TEXTURE_COORD15_EXT     0x87AC\n#define GL_OUTPUT_TEXTURE_COORD16_EXT     0x87AD\n#define GL_OUTPUT_TEXTURE_COORD17_EXT     0x87AE\n#define GL_OUTPUT_TEXTURE_COORD18_EXT     0x87AF\n#define GL_OUTPUT_TEXTURE_COORD19_EXT     0x87B0\n#define GL_OUTPUT_TEXTURE_COORD20_EXT     0x87B1\n#define GL_OUTPUT_TEXTURE_COORD21_EXT     0x87B2\n#define GL_OUTPUT_TEXTURE_COORD22_EXT     0x87B3\n#define GL_OUTPUT_TEXTURE_COORD23_EXT     0x87B4\n#define GL_OUTPUT_TEXTURE_COORD24_EXT     0x87B5\n#define GL_OUTPUT_TEXTURE_COORD25_EXT     0x87B6\n#define GL_OUTPUT_TEXTURE_COORD26_EXT     0x87B7\n#define GL_OUTPUT_TEXTURE_COORD27_EXT     0x87B8\n#define GL_OUTPUT_TEXTURE_COORD28_EXT     0x87B9\n#define GL_OUTPUT_TEXTURE_COORD29_EXT     0x87BA\n#define GL_OUTPUT_TEXTURE_COORD30_EXT     0x87BB\n#define GL_OUTPUT_TEXTURE_COORD31_EXT     0x87BC\n#define GL_OUTPUT_FOG_EXT                 0x87BD\n#define GL_SCALAR_EXT                     0x87BE\n#define GL_VECTOR_EXT                     0x87BF\n#define GL_MATRIX_EXT                     0x87C0\n#define GL_VARIANT_EXT                    0x87C1\n#define GL_INVARIANT_EXT                  0x87C2\n#define GL_LOCAL_CONSTANT_EXT             0x87C3\n#define GL_LOCAL_EXT                      0x87C4\n#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5\n#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6\n#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7\n#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8\n#define GL_MAX_VERTEX_SHADER_LOCALS_EXT   0x87C9\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE\n#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF\n#define GL_VERTEX_SHADER_VARIANTS_EXT     0x87D0\n#define GL_VERTEX_SHADER_INVARIANTS_EXT   0x87D1\n#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2\n#define GL_VERTEX_SHADER_LOCALS_EXT       0x87D3\n#define GL_VERTEX_SHADER_OPTIMIZED_EXT    0x87D4\n#define GL_X_EXT                          0x87D5\n#define GL_Y_EXT                          0x87D6\n#define GL_Z_EXT                          0x87D7\n#define GL_W_EXT                          0x87D8\n#define GL_NEGATIVE_X_EXT                 0x87D9\n#define GL_NEGATIVE_Y_EXT                 0x87DA\n#define GL_NEGATIVE_Z_EXT                 0x87DB\n#define GL_NEGATIVE_W_EXT                 0x87DC\n#define GL_ZERO_EXT                       0x87DD\n#define GL_ONE_EXT                        0x87DE\n#define GL_NEGATIVE_ONE_EXT               0x87DF\n#define GL_NORMALIZED_RANGE_EXT           0x87E0\n#define GL_FULL_RANGE_EXT                 0x87E1\n#define GL_CURRENT_VERTEX_EXT             0x87E2\n#define GL_MVP_MATRIX_EXT                 0x87E3\n#define GL_VARIANT_VALUE_EXT              0x87E4\n#define GL_VARIANT_DATATYPE_EXT           0x87E5\n#define GL_VARIANT_ARRAY_STRIDE_EXT       0x87E6\n#define GL_VARIANT_ARRAY_TYPE_EXT         0x87E7\n#define GL_VARIANT_ARRAY_EXT              0x87E8\n#define GL_VARIANT_ARRAY_POINTER_EXT      0x87E9\n#define GL_INVARIANT_VALUE_EXT            0x87EA\n#define GL_INVARIANT_DATATYPE_EXT         0x87EB\n#define GL_LOCAL_CONSTANT_VALUE_EXT       0x87EC\n#define GL_LOCAL_CONSTANT_DATATYPE_EXT    0x87ED\n#endif\n\n#ifndef GL_ATI_vertex_streams\n#define GL_MAX_VERTEX_STREAMS_ATI         0x876B\n#define GL_VERTEX_STREAM0_ATI             0x876C\n#define GL_VERTEX_STREAM1_ATI             0x876D\n#define GL_VERTEX_STREAM2_ATI             0x876E\n#define GL_VERTEX_STREAM3_ATI             0x876F\n#define GL_VERTEX_STREAM4_ATI             0x8770\n#define GL_VERTEX_STREAM5_ATI             0x8771\n#define GL_VERTEX_STREAM6_ATI             0x8772\n#define GL_VERTEX_STREAM7_ATI             0x8773\n#define GL_VERTEX_SOURCE_ATI              0x8774\n#endif\n\n#ifndef GL_ATI_element_array\n#define GL_ELEMENT_ARRAY_ATI              0x8768\n#define GL_ELEMENT_ARRAY_TYPE_ATI         0x8769\n#define GL_ELEMENT_ARRAY_POINTER_ATI      0x876A\n#endif\n\n#ifndef GL_SUN_mesh_array\n#define GL_QUAD_MESH_SUN                  0x8614\n#define GL_TRIANGLE_MESH_SUN              0x8615\n#endif\n\n#ifndef GL_SUN_slice_accum\n#define GL_SLICE_ACCUM_SUN                0x85CC\n#endif\n\n#ifndef GL_NV_multisample_filter_hint\n#define GL_MULTISAMPLE_FILTER_HINT_NV     0x8534\n#endif\n\n#ifndef GL_NV_depth_clamp\n#define GL_DEPTH_CLAMP_NV                 0x864F\n#endif\n\n#ifndef GL_NV_occlusion_query\n#define GL_PIXEL_COUNTER_BITS_NV          0x8864\n#define GL_CURRENT_OCCLUSION_QUERY_ID_NV  0x8865\n#define GL_PIXEL_COUNT_NV                 0x8866\n#define GL_PIXEL_COUNT_AVAILABLE_NV       0x8867\n#endif\n\n#ifndef GL_NV_point_sprite\n#define GL_POINT_SPRITE_NV                0x8861\n#define GL_COORD_REPLACE_NV               0x8862\n#define GL_POINT_SPRITE_R_MODE_NV         0x8863\n#endif\n\n#ifndef GL_NV_texture_shader3\n#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850\n#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851\n#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852\n#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853\n#define GL_OFFSET_HILO_TEXTURE_2D_NV      0x8854\n#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855\n#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856\n#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857\n#define GL_DEPENDENT_HILO_TEXTURE_2D_NV   0x8858\n#define GL_DEPENDENT_RGB_TEXTURE_3D_NV    0x8859\n#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A\n#define GL_DOT_PRODUCT_PASS_THROUGH_NV    0x885B\n#define GL_DOT_PRODUCT_TEXTURE_1D_NV      0x885C\n#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D\n#define GL_HILO8_NV                       0x885E\n#define GL_SIGNED_HILO8_NV                0x885F\n#define GL_FORCE_BLUE_TO_ONE_NV           0x8860\n#endif\n\n#ifndef GL_NV_vertex_program1_1\n#endif\n\n#ifndef GL_EXT_shadow_funcs\n#endif\n\n#ifndef GL_EXT_stencil_two_side\n#define GL_STENCIL_TEST_TWO_SIDE_EXT      0x8910\n#define GL_ACTIVE_STENCIL_FACE_EXT        0x8911\n#endif\n\n#ifndef GL_ATI_text_fragment_shader\n#define GL_TEXT_FRAGMENT_SHADER_ATI       0x8200\n#endif\n\n#ifndef GL_APPLE_client_storage\n#define GL_UNPACK_CLIENT_STORAGE_APPLE    0x85B2\n#endif\n\n#ifndef GL_APPLE_element_array\n#define GL_ELEMENT_ARRAY_APPLE            0x8768\n#define GL_ELEMENT_ARRAY_TYPE_APPLE       0x8769\n#define GL_ELEMENT_ARRAY_POINTER_APPLE    0x876A\n#endif\n\n#ifndef GL_APPLE_fence\n#define GL_DRAW_PIXELS_APPLE              0x8A0A\n#define GL_FENCE_APPLE                    0x8A0B\n#endif\n\n#ifndef GL_APPLE_vertex_array_object\n#define GL_VERTEX_ARRAY_BINDING_APPLE     0x85B5\n#endif\n\n#ifndef GL_APPLE_vertex_array_range\n#define GL_VERTEX_ARRAY_RANGE_APPLE       0x851D\n#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E\n#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F\n#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521\n#define GL_STORAGE_CACHED_APPLE           0x85BE\n#define GL_STORAGE_SHARED_APPLE           0x85BF\n#endif\n\n#ifndef GL_APPLE_ycbcr_422\n#define GL_YCBCR_422_APPLE                0x85B9\n#define GL_UNSIGNED_SHORT_8_8_APPLE       0x85BA\n#define GL_UNSIGNED_SHORT_8_8_REV_APPLE   0x85BB\n#endif\n\n#ifndef GL_S3_s3tc\n#define GL_RGB_S3TC                       0x83A0\n#define GL_RGB4_S3TC                      0x83A1\n#define GL_RGBA_S3TC                      0x83A2\n#define GL_RGBA4_S3TC                     0x83A3\n#endif\n\n#ifndef GL_ATI_draw_buffers\n#define GL_MAX_DRAW_BUFFERS_ATI           0x8824\n#define GL_DRAW_BUFFER0_ATI               0x8825\n#define GL_DRAW_BUFFER1_ATI               0x8826\n#define GL_DRAW_BUFFER2_ATI               0x8827\n#define GL_DRAW_BUFFER3_ATI               0x8828\n#define GL_DRAW_BUFFER4_ATI               0x8829\n#define GL_DRAW_BUFFER5_ATI               0x882A\n#define GL_DRAW_BUFFER6_ATI               0x882B\n#define GL_DRAW_BUFFER7_ATI               0x882C\n#define GL_DRAW_BUFFER8_ATI               0x882D\n#define GL_DRAW_BUFFER9_ATI               0x882E\n#define GL_DRAW_BUFFER10_ATI              0x882F\n#define GL_DRAW_BUFFER11_ATI              0x8830\n#define GL_DRAW_BUFFER12_ATI              0x8831\n#define GL_DRAW_BUFFER13_ATI              0x8832\n#define GL_DRAW_BUFFER14_ATI              0x8833\n#define GL_DRAW_BUFFER15_ATI              0x8834\n#endif\n\n#ifndef GL_ATI_pixel_format_float\n#define GL_TYPE_RGBA_FLOAT_ATI            0x8820\n#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835\n#endif\n\n#ifndef GL_ATI_texture_env_combine3\n#define GL_MODULATE_ADD_ATI               0x8744\n#define GL_MODULATE_SIGNED_ADD_ATI        0x8745\n#define GL_MODULATE_SUBTRACT_ATI          0x8746\n#endif\n\n#ifndef GL_ATI_texture_float\n#define GL_RGBA_FLOAT32_ATI               0x8814\n#define GL_RGB_FLOAT32_ATI                0x8815\n#define GL_ALPHA_FLOAT32_ATI              0x8816\n#define GL_INTENSITY_FLOAT32_ATI          0x8817\n#define GL_LUMINANCE_FLOAT32_ATI          0x8818\n#define GL_LUMINANCE_ALPHA_FLOAT32_ATI    0x8819\n#define GL_RGBA_FLOAT16_ATI               0x881A\n#define GL_RGB_FLOAT16_ATI                0x881B\n#define GL_ALPHA_FLOAT16_ATI              0x881C\n#define GL_INTENSITY_FLOAT16_ATI          0x881D\n#define GL_LUMINANCE_FLOAT16_ATI          0x881E\n#define GL_LUMINANCE_ALPHA_FLOAT16_ATI    0x881F\n#endif\n\n#ifndef GL_NV_float_buffer\n#define GL_FLOAT_R_NV                     0x8880\n#define GL_FLOAT_RG_NV                    0x8881\n#define GL_FLOAT_RGB_NV                   0x8882\n#define GL_FLOAT_RGBA_NV                  0x8883\n#define GL_FLOAT_R16_NV                   0x8884\n#define GL_FLOAT_R32_NV                   0x8885\n#define GL_FLOAT_RG16_NV                  0x8886\n#define GL_FLOAT_RG32_NV                  0x8887\n#define GL_FLOAT_RGB16_NV                 0x8888\n#define GL_FLOAT_RGB32_NV                 0x8889\n#define GL_FLOAT_RGBA16_NV                0x888A\n#define GL_FLOAT_RGBA32_NV                0x888B\n#define GL_TEXTURE_FLOAT_COMPONENTS_NV    0x888C\n#define GL_FLOAT_CLEAR_COLOR_VALUE_NV     0x888D\n#define GL_FLOAT_RGBA_MODE_NV             0x888E\n#endif\n\n#ifndef GL_NV_fragment_program\n#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868\n#define GL_FRAGMENT_PROGRAM_NV            0x8870\n#define GL_MAX_TEXTURE_COORDS_NV          0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS_NV     0x8872\n#define GL_FRAGMENT_PROGRAM_BINDING_NV    0x8873\n#define GL_PROGRAM_ERROR_STRING_NV        0x8874\n#endif\n\n#ifndef GL_NV_half_float\n#define GL_HALF_FLOAT_NV                  0x140B\n#endif\n\n#ifndef GL_NV_pixel_data_range\n#define GL_WRITE_PIXEL_DATA_RANGE_NV      0x8878\n#define GL_READ_PIXEL_DATA_RANGE_NV       0x8879\n#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A\n#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B\n#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C\n#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D\n#endif\n\n#ifndef GL_NV_primitive_restart\n#define GL_PRIMITIVE_RESTART_NV           0x8558\n#define GL_PRIMITIVE_RESTART_INDEX_NV     0x8559\n#endif\n\n#ifndef GL_NV_texture_expand_normal\n#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F\n#endif\n\n#ifndef GL_NV_vertex_program2\n#endif\n\n#ifndef GL_ATI_map_object_buffer\n#endif\n\n#ifndef GL_ATI_separate_stencil\n#define GL_STENCIL_BACK_FUNC_ATI          0x8800\n#define GL_STENCIL_BACK_FAIL_ATI          0x8801\n#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802\n#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803\n#endif\n\n#ifndef GL_ATI_vertex_attrib_array_object\n#endif\n\n#ifndef GL_OES_read_format\n#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A\n#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B\n#endif\n\n#ifndef GL_EXT_depth_bounds_test\n#define GL_DEPTH_BOUNDS_TEST_EXT          0x8890\n#define GL_DEPTH_BOUNDS_EXT               0x8891\n#endif\n\n#ifndef GL_EXT_texture_mirror_clamp\n#define GL_MIRROR_CLAMP_EXT               0x8742\n#define GL_MIRROR_CLAMP_TO_EDGE_EXT       0x8743\n#define GL_MIRROR_CLAMP_TO_BORDER_EXT     0x8912\n#endif\n\n#ifndef GL_EXT_blend_equation_separate\n#define GL_BLEND_EQUATION_RGB_EXT         GL_BLEND_EQUATION\n#define GL_BLEND_EQUATION_ALPHA_EXT       0x883D\n#endif\n\n#ifndef GL_MESA_pack_invert\n#define GL_PACK_INVERT_MESA               0x8758\n#endif\n\n#ifndef GL_MESA_ycbcr_texture\n#define GL_UNSIGNED_SHORT_8_8_MESA        0x85BA\n#define GL_UNSIGNED_SHORT_8_8_REV_MESA    0x85BB\n#define GL_YCBCR_MESA                     0x8757\n#endif\n\n#ifndef GL_EXT_pixel_buffer_object\n#define GL_PIXEL_PACK_BUFFER_EXT          0x88EB\n#define GL_PIXEL_UNPACK_BUFFER_EXT        0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING_EXT  0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF\n#endif\n\n#ifndef GL_NV_fragment_program_option\n#endif\n\n#ifndef GL_NV_fragment_program2\n#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4\n#define GL_MAX_PROGRAM_CALL_DEPTH_NV      0x88F5\n#define GL_MAX_PROGRAM_IF_DEPTH_NV        0x88F6\n#define GL_MAX_PROGRAM_LOOP_DEPTH_NV      0x88F7\n#define GL_MAX_PROGRAM_LOOP_COUNT_NV      0x88F8\n#endif\n\n#ifndef GL_NV_vertex_program2_option\n/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */\n/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */\n#endif\n\n#ifndef GL_NV_vertex_program3\n/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */\n#endif\n\n#ifndef GL_EXT_framebuffer_object\n#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506\n#define GL_MAX_RENDERBUFFER_SIZE_EXT      0x84E8\n#define GL_FRAMEBUFFER_BINDING_EXT        0x8CA6\n#define GL_RENDERBUFFER_BINDING_EXT       0x8CA7\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4\n#define GL_FRAMEBUFFER_COMPLETE_EXT       0x8CD5\n#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6\n#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7\n#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9\n#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA\n#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB\n#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC\n#define GL_FRAMEBUFFER_UNSUPPORTED_EXT    0x8CDD\n#define GL_MAX_COLOR_ATTACHMENTS_EXT      0x8CDF\n#define GL_COLOR_ATTACHMENT0_EXT          0x8CE0\n#define GL_COLOR_ATTACHMENT1_EXT          0x8CE1\n#define GL_COLOR_ATTACHMENT2_EXT          0x8CE2\n#define GL_COLOR_ATTACHMENT3_EXT          0x8CE3\n#define GL_COLOR_ATTACHMENT4_EXT          0x8CE4\n#define GL_COLOR_ATTACHMENT5_EXT          0x8CE5\n#define GL_COLOR_ATTACHMENT6_EXT          0x8CE6\n#define GL_COLOR_ATTACHMENT7_EXT          0x8CE7\n#define GL_COLOR_ATTACHMENT8_EXT          0x8CE8\n#define GL_COLOR_ATTACHMENT9_EXT          0x8CE9\n#define GL_COLOR_ATTACHMENT10_EXT         0x8CEA\n#define GL_COLOR_ATTACHMENT11_EXT         0x8CEB\n#define GL_COLOR_ATTACHMENT12_EXT         0x8CEC\n#define GL_COLOR_ATTACHMENT13_EXT         0x8CED\n#define GL_COLOR_ATTACHMENT14_EXT         0x8CEE\n#define GL_COLOR_ATTACHMENT15_EXT         0x8CEF\n#define GL_DEPTH_ATTACHMENT_EXT           0x8D00\n#define GL_STENCIL_ATTACHMENT_EXT         0x8D20\n#define GL_FRAMEBUFFER_EXT                0x8D40\n#define GL_RENDERBUFFER_EXT               0x8D41\n#define GL_RENDERBUFFER_WIDTH_EXT         0x8D42\n#define GL_RENDERBUFFER_HEIGHT_EXT        0x8D43\n#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44\n#define GL_STENCIL_INDEX1_EXT             0x8D46\n#define GL_STENCIL_INDEX4_EXT             0x8D47\n#define GL_STENCIL_INDEX8_EXT             0x8D48\n#define GL_STENCIL_INDEX16_EXT            0x8D49\n#define GL_RENDERBUFFER_RED_SIZE_EXT      0x8D50\n#define GL_RENDERBUFFER_GREEN_SIZE_EXT    0x8D51\n#define GL_RENDERBUFFER_BLUE_SIZE_EXT     0x8D52\n#define GL_RENDERBUFFER_ALPHA_SIZE_EXT    0x8D53\n#define GL_RENDERBUFFER_DEPTH_SIZE_EXT    0x8D54\n#define GL_RENDERBUFFER_STENCIL_SIZE_EXT  0x8D55\n#endif\n\n#ifndef GL_GREMEDY_string_marker\n#endif\n\n#ifndef GL_EXT_packed_depth_stencil\n#define GL_DEPTH_STENCIL_EXT              0x84F9\n#define GL_UNSIGNED_INT_24_8_EXT          0x84FA\n#define GL_DEPTH24_STENCIL8_EXT           0x88F0\n#define GL_TEXTURE_STENCIL_SIZE_EXT       0x88F1\n#endif\n\n#ifndef GL_EXT_stencil_clear_tag\n#define GL_STENCIL_TAG_BITS_EXT           0x88F2\n#define GL_STENCIL_CLEAR_TAG_VALUE_EXT    0x88F3\n#endif\n\n#ifndef GL_EXT_texture_sRGB\n#define GL_SRGB_EXT                       0x8C40\n#define GL_SRGB8_EXT                      0x8C41\n#define GL_SRGB_ALPHA_EXT                 0x8C42\n#define GL_SRGB8_ALPHA8_EXT               0x8C43\n#define GL_SLUMINANCE_ALPHA_EXT           0x8C44\n#define GL_SLUMINANCE8_ALPHA8_EXT         0x8C45\n#define GL_SLUMINANCE_EXT                 0x8C46\n#define GL_SLUMINANCE8_EXT                0x8C47\n#define GL_COMPRESSED_SRGB_EXT            0x8C48\n#define GL_COMPRESSED_SRGB_ALPHA_EXT      0x8C49\n#define GL_COMPRESSED_SLUMINANCE_EXT      0x8C4A\n#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B\n#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT  0x8C4C\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F\n#endif\n\n#ifndef GL_EXT_framebuffer_blit\n#define GL_READ_FRAMEBUFFER_EXT           0x8CA8\n#define GL_DRAW_FRAMEBUFFER_EXT           0x8CA9\n#define GL_DRAW_FRAMEBUFFER_BINDING_EXT   GL_FRAMEBUFFER_BINDING_EXT\n#define GL_READ_FRAMEBUFFER_BINDING_EXT   0x8CAA\n#endif\n\n#ifndef GL_EXT_framebuffer_multisample\n#define GL_RENDERBUFFER_SAMPLES_EXT       0x8CAB\n#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56\n#define GL_MAX_SAMPLES_EXT                0x8D57\n#endif\n\n#ifndef GL_MESAX_texture_stack\n#define GL_TEXTURE_1D_STACK_MESAX         0x8759\n#define GL_TEXTURE_2D_STACK_MESAX         0x875A\n#define GL_PROXY_TEXTURE_1D_STACK_MESAX   0x875B\n#define GL_PROXY_TEXTURE_2D_STACK_MESAX   0x875C\n#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D\n#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E\n#endif\n\n#ifndef GL_EXT_timer_query\n#define GL_TIME_ELAPSED_EXT               0x88BF\n#endif\n\n#ifndef GL_EXT_gpu_program_parameters\n#endif\n\n#ifndef GL_APPLE_flush_buffer_range\n#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12\n#define GL_BUFFER_FLUSHING_UNMAP_APPLE    0x8A13\n#endif\n\n#ifndef GL_NV_gpu_program4\n#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV    0x8904\n#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV    0x8905\n#define GL_PROGRAM_ATTRIB_COMPONENTS_NV   0x8906\n#define GL_PROGRAM_RESULT_COMPONENTS_NV   0x8907\n#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908\n#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909\n#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5\n#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6\n#endif\n\n#ifndef GL_NV_geometry_program4\n#define GL_LINES_ADJACENCY_EXT            0x000A\n#define GL_LINE_STRIP_ADJACENCY_EXT       0x000B\n#define GL_TRIANGLES_ADJACENCY_EXT        0x000C\n#define GL_TRIANGLE_STRIP_ADJACENCY_EXT   0x000D\n#define GL_GEOMETRY_PROGRAM_NV            0x8C26\n#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27\n#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28\n#define GL_GEOMETRY_VERTICES_OUT_EXT      0x8DDA\n#define GL_GEOMETRY_INPUT_TYPE_EXT        0x8DDB\n#define GL_GEOMETRY_OUTPUT_TYPE_EXT       0x8DDC\n#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29\n#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4\n#define GL_PROGRAM_POINT_SIZE_EXT         0x8642\n#endif\n\n#ifndef GL_EXT_geometry_shader4\n#define GL_GEOMETRY_SHADER_EXT            0x8DD9\n/* reuse GL_GEOMETRY_VERTICES_OUT_EXT */\n/* reuse GL_GEOMETRY_INPUT_TYPE_EXT */\n/* reuse GL_GEOMETRY_OUTPUT_TYPE_EXT */\n/* reuse GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */\n#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD\n#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE\n#define GL_MAX_VARYING_COMPONENTS_EXT     0x8B4B\n#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF\n#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0\n#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1\n/* reuse GL_LINES_ADJACENCY_EXT */\n/* reuse GL_LINE_STRIP_ADJACENCY_EXT */\n/* reuse GL_TRIANGLES_ADJACENCY_EXT */\n/* reuse GL_TRIANGLE_STRIP_ADJACENCY_EXT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */\n/* reuse GL_PROGRAM_POINT_SIZE_EXT */\n#endif\n\n#ifndef GL_NV_vertex_program4\n#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD\n#endif\n\n#ifndef GL_EXT_gpu_shader4\n#define GL_SAMPLER_1D_ARRAY_EXT           0x8DC0\n#define GL_SAMPLER_2D_ARRAY_EXT           0x8DC1\n#define GL_SAMPLER_BUFFER_EXT             0x8DC2\n#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT    0x8DC3\n#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT    0x8DC4\n#define GL_SAMPLER_CUBE_SHADOW_EXT        0x8DC5\n#define GL_UNSIGNED_INT_VEC2_EXT          0x8DC6\n#define GL_UNSIGNED_INT_VEC3_EXT          0x8DC7\n#define GL_UNSIGNED_INT_VEC4_EXT          0x8DC8\n#define GL_INT_SAMPLER_1D_EXT             0x8DC9\n#define GL_INT_SAMPLER_2D_EXT             0x8DCA\n#define GL_INT_SAMPLER_3D_EXT             0x8DCB\n#define GL_INT_SAMPLER_CUBE_EXT           0x8DCC\n#define GL_INT_SAMPLER_2D_RECT_EXT        0x8DCD\n#define GL_INT_SAMPLER_1D_ARRAY_EXT       0x8DCE\n#define GL_INT_SAMPLER_2D_ARRAY_EXT       0x8DCF\n#define GL_INT_SAMPLER_BUFFER_EXT         0x8DD0\n#define GL_UNSIGNED_INT_SAMPLER_1D_EXT    0x8DD1\n#define GL_UNSIGNED_INT_SAMPLER_2D_EXT    0x8DD2\n#define GL_UNSIGNED_INT_SAMPLER_3D_EXT    0x8DD3\n#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT  0x8DD4\n#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5\n#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6\n#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7\n#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8\n#endif\n\n#ifndef GL_EXT_draw_instanced\n#endif\n\n#ifndef GL_EXT_packed_float\n#define GL_R11F_G11F_B10F_EXT             0x8C3A\n#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B\n#define GL_RGBA_SIGNED_COMPONENTS_EXT     0x8C3C\n#endif\n\n#ifndef GL_EXT_texture_array\n#define GL_TEXTURE_1D_ARRAY_EXT           0x8C18\n#define GL_PROXY_TEXTURE_1D_ARRAY_EXT     0x8C19\n#define GL_TEXTURE_2D_ARRAY_EXT           0x8C1A\n#define GL_PROXY_TEXTURE_2D_ARRAY_EXT     0x8C1B\n#define GL_TEXTURE_BINDING_1D_ARRAY_EXT   0x8C1C\n#define GL_TEXTURE_BINDING_2D_ARRAY_EXT   0x8C1D\n#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT   0x88FF\n#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */\n#endif\n\n#ifndef GL_EXT_texture_buffer_object\n#define GL_TEXTURE_BUFFER_EXT             0x8C2A\n#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT    0x8C2B\n#define GL_TEXTURE_BINDING_BUFFER_EXT     0x8C2C\n#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D\n#define GL_TEXTURE_BUFFER_FORMAT_EXT      0x8C2E\n#endif\n\n#ifndef GL_EXT_texture_compression_latc\n#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70\n#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71\n#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72\n#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73\n#endif\n\n#ifndef GL_EXT_texture_compression_rgtc\n#define GL_COMPRESSED_RED_RGTC1_EXT       0x8DBB\n#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC\n#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD\n#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE\n#endif\n\n#ifndef GL_EXT_texture_shared_exponent\n#define GL_RGB9_E5_EXT                    0x8C3D\n#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT   0x8C3E\n#define GL_TEXTURE_SHARED_SIZE_EXT        0x8C3F\n#endif\n\n#ifndef GL_NV_depth_buffer_float\n#define GL_DEPTH_COMPONENT32F_NV          0x8DAB\n#define GL_DEPTH32F_STENCIL8_NV           0x8DAC\n#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD\n#define GL_DEPTH_BUFFER_FLOAT_MODE_NV     0x8DAF\n#endif\n\n#ifndef GL_NV_fragment_program4\n#endif\n\n#ifndef GL_NV_framebuffer_multisample_coverage\n#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB\n#define GL_RENDERBUFFER_COLOR_SAMPLES_NV  0x8E10\n#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11\n#define GL_MULTISAMPLE_COVERAGE_MODES_NV  0x8E12\n#endif\n\n#ifndef GL_EXT_framebuffer_sRGB\n#define GL_FRAMEBUFFER_SRGB_EXT           0x8DB9\n#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT   0x8DBA\n#endif\n\n#ifndef GL_NV_geometry_shader4\n#endif\n\n#ifndef GL_NV_parameter_buffer_object\n#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0\n#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1\n#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2\n#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3\n#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4\n#endif\n\n#ifndef GL_EXT_draw_buffers2\n#endif\n\n#ifndef GL_NV_transform_feedback\n#define GL_BACK_PRIMARY_COLOR_NV          0x8C77\n#define GL_BACK_SECONDARY_COLOR_NV        0x8C78\n#define GL_TEXTURE_COORD_NV               0x8C79\n#define GL_CLIP_DISTANCE_NV               0x8C7A\n#define GL_VERTEX_ID_NV                   0x8C7B\n#define GL_PRIMITIVE_ID_NV                0x8C7C\n#define GL_GENERIC_ATTRIB_NV              0x8C7D\n#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV  0x8C7E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80\n#define GL_ACTIVE_VARYINGS_NV             0x8C81\n#define GL_ACTIVE_VARYING_MAX_LENGTH_NV   0x8C82\n#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83\n#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84\n#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85\n#define GL_TRANSFORM_FEEDBACK_RECORD_NV   0x8C86\n#define GL_PRIMITIVES_GENERATED_NV        0x8C87\n#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88\n#define GL_RASTERIZER_DISCARD_NV          0x8C89\n#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B\n#define GL_INTERLEAVED_ATTRIBS_NV         0x8C8C\n#define GL_SEPARATE_ATTRIBS_NV            0x8C8D\n#define GL_TRANSFORM_FEEDBACK_BUFFER_NV   0x8C8E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F\n#endif\n\n#ifndef GL_EXT_bindable_uniform\n#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2\n#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3\n#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4\n#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT  0x8DED\n#define GL_UNIFORM_BUFFER_EXT             0x8DEE\n#define GL_UNIFORM_BUFFER_BINDING_EXT     0x8DEF\n#endif\n\n#ifndef GL_EXT_texture_integer\n#define GL_RGBA32UI_EXT                   0x8D70\n#define GL_RGB32UI_EXT                    0x8D71\n#define GL_ALPHA32UI_EXT                  0x8D72\n#define GL_INTENSITY32UI_EXT              0x8D73\n#define GL_LUMINANCE32UI_EXT              0x8D74\n#define GL_LUMINANCE_ALPHA32UI_EXT        0x8D75\n#define GL_RGBA16UI_EXT                   0x8D76\n#define GL_RGB16UI_EXT                    0x8D77\n#define GL_ALPHA16UI_EXT                  0x8D78\n#define GL_INTENSITY16UI_EXT              0x8D79\n#define GL_LUMINANCE16UI_EXT              0x8D7A\n#define GL_LUMINANCE_ALPHA16UI_EXT        0x8D7B\n#define GL_RGBA8UI_EXT                    0x8D7C\n#define GL_RGB8UI_EXT                     0x8D7D\n#define GL_ALPHA8UI_EXT                   0x8D7E\n#define GL_INTENSITY8UI_EXT               0x8D7F\n#define GL_LUMINANCE8UI_EXT               0x8D80\n#define GL_LUMINANCE_ALPHA8UI_EXT         0x8D81\n#define GL_RGBA32I_EXT                    0x8D82\n#define GL_RGB32I_EXT                     0x8D83\n#define GL_ALPHA32I_EXT                   0x8D84\n#define GL_INTENSITY32I_EXT               0x8D85\n#define GL_LUMINANCE32I_EXT               0x8D86\n#define GL_LUMINANCE_ALPHA32I_EXT         0x8D87\n#define GL_RGBA16I_EXT                    0x8D88\n#define GL_RGB16I_EXT                     0x8D89\n#define GL_ALPHA16I_EXT                   0x8D8A\n#define GL_INTENSITY16I_EXT               0x8D8B\n#define GL_LUMINANCE16I_EXT               0x8D8C\n#define GL_LUMINANCE_ALPHA16I_EXT         0x8D8D\n#define GL_RGBA8I_EXT                     0x8D8E\n#define GL_RGB8I_EXT                      0x8D8F\n#define GL_ALPHA8I_EXT                    0x8D90\n#define GL_INTENSITY8I_EXT                0x8D91\n#define GL_LUMINANCE8I_EXT                0x8D92\n#define GL_LUMINANCE_ALPHA8I_EXT          0x8D93\n#define GL_RED_INTEGER_EXT                0x8D94\n#define GL_GREEN_INTEGER_EXT              0x8D95\n#define GL_BLUE_INTEGER_EXT               0x8D96\n#define GL_ALPHA_INTEGER_EXT              0x8D97\n#define GL_RGB_INTEGER_EXT                0x8D98\n#define GL_RGBA_INTEGER_EXT               0x8D99\n#define GL_BGR_INTEGER_EXT                0x8D9A\n#define GL_BGRA_INTEGER_EXT               0x8D9B\n#define GL_LUMINANCE_INTEGER_EXT          0x8D9C\n#define GL_LUMINANCE_ALPHA_INTEGER_EXT    0x8D9D\n#define GL_RGBA_INTEGER_MODE_EXT          0x8D9E\n#endif\n\n#ifndef GL_GREMEDY_frame_terminator\n#endif\n\n#ifndef GL_NV_conditional_render\n#define GL_QUERY_WAIT_NV                  0x8E13\n#define GL_QUERY_NO_WAIT_NV               0x8E14\n#define GL_QUERY_BY_REGION_WAIT_NV        0x8E15\n#define GL_QUERY_BY_REGION_NO_WAIT_NV     0x8E16\n#endif\n\n#ifndef GL_NV_present_video\n#define GL_FRAME_NV                       0x8E26\n#define GL_FIELDS_NV                      0x8E27\n#define GL_CURRENT_TIME_NV                0x8E28\n#define GL_NUM_FILL_STREAMS_NV            0x8E29\n#define GL_PRESENT_TIME_NV                0x8E2A\n#define GL_PRESENT_DURATION_NV            0x8E2B\n#endif\n\n#ifndef GL_EXT_transform_feedback\n#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT  0x8C8E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84\n#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85\n#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F\n#define GL_INTERLEAVED_ATTRIBS_EXT        0x8C8C\n#define GL_SEPARATE_ATTRIBS_EXT           0x8C8D\n#define GL_PRIMITIVES_GENERATED_EXT       0x8C87\n#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88\n#define GL_RASTERIZER_DISCARD_EXT         0x8C89\n#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80\n#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83\n#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F\n#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76\n#endif\n\n#ifndef GL_EXT_direct_state_access\n#define GL_PROGRAM_MATRIX_EXT             0x8E2D\n#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT   0x8E2E\n#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F\n#endif\n\n#ifndef GL_EXT_vertex_array_bgra\n/* reuse GL_BGRA */\n#endif\n\n#ifndef GL_EXT_texture_swizzle\n#define GL_TEXTURE_SWIZZLE_R_EXT          0x8E42\n#define GL_TEXTURE_SWIZZLE_G_EXT          0x8E43\n#define GL_TEXTURE_SWIZZLE_B_EXT          0x8E44\n#define GL_TEXTURE_SWIZZLE_A_EXT          0x8E45\n#define GL_TEXTURE_SWIZZLE_RGBA_EXT       0x8E46\n#endif\n\n#ifndef GL_NV_explicit_multisample\n#define GL_SAMPLE_POSITION_NV             0x8E50\n#define GL_SAMPLE_MASK_NV                 0x8E51\n#define GL_SAMPLE_MASK_VALUE_NV           0x8E52\n#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53\n#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54\n#define GL_MAX_SAMPLE_MASK_WORDS_NV       0x8E59\n#define GL_TEXTURE_RENDERBUFFER_NV        0x8E55\n#define GL_SAMPLER_RENDERBUFFER_NV        0x8E56\n#define GL_INT_SAMPLER_RENDERBUFFER_NV    0x8E57\n#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58\n#endif\n\n#ifndef GL_NV_transform_feedback2\n#define GL_TRANSFORM_FEEDBACK_NV          0x8E22\n#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23\n#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24\n#define GL_TRANSFORM_FEEDBACK_BINDING_NV  0x8E25\n#endif\n\n\n/*************************************************************/\n\n#include <stddef.h>\n#ifndef GL_VERSION_2_0\n/* GL type for program/shader text */\ntypedef char GLchar;\t\t\t/* native character */\n#endif\n\n#ifndef GL_VERSION_1_5\n/* GL types for handling large vertex buffer objects */\ntypedef ptrdiff_t GLintptr;\ntypedef ptrdiff_t GLsizeiptr;\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n/* GL types for handling large vertex buffer objects */\ntypedef ptrdiff_t GLintptrARB;\ntypedef ptrdiff_t GLsizeiptrARB;\n#endif\n\n#ifndef GL_ARB_shader_objects\n/* GL types for handling shader object handles and program/shader text */\ntypedef char GLcharARB;\t\t/* native character */\ntypedef unsigned int GLhandleARB;\t/* shader object handle */\n#endif\n\n/* GL types for \"half\" precision (s10e5) float data in host memory */\n#ifndef GL_ARB_half_float_pixel\ntypedef unsigned short GLhalfARB;\n#endif\n\n#ifndef GL_NV_half_float\ntypedef unsigned short GLhalfNV;\n#endif\n\n#ifndef GLEXT_64_TYPES_DEFINED\n/* This code block is duplicated in glxext.h, so must be protected */\n#define GLEXT_64_TYPES_DEFINED\n/* Define int32_t, int64_t, and uint64_t types for UST/MSC */\n/* (as used in the GL_EXT_timer_query extension). */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n#include <inttypes.h>\n#elif defined(__sun__) || defined(__digital__)\n#include <inttypes.h>\n#if defined(__STDC__)\n#if defined(__arch64__) || defined(_LP64)\ntypedef long int int64_t;\ntypedef unsigned long int uint64_t;\n#else\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#endif /* __arch64__ */\n#endif /* __STDC__ */\n#elif defined( __VMS ) || defined(__sgi)\n#include <inttypes.h>\n#elif defined(__SCO__) || defined(__USLC__)\n#include <stdint.h>\n#elif defined(__UNIXOS2__) || defined(__SOL64__)\ntypedef long int int32_t;\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#elif defined(_WIN32) && defined(__GNUC__)\n#include <stdint.h>\n#elif defined(_WIN32)\ntypedef __int32 int32_t;\ntypedef __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <inttypes.h>     /* Fallback option */\n#endif\n#endif\n\n#ifndef GL_EXT_timer_query\ntypedef int64_t GLint64EXT;\ntypedef uint64_t GLuint64EXT;\n#endif\n\n#ifndef GL_VERSION_1_2\n#define GL_VERSION_1_2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf);\nGLAPI void APIENTRY glBlendEquation (GLenum);\nGLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);\nGLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);\nGLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean);\nGLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean);\nGLAPI void APIENTRY glResetHistogram (GLenum);\nGLAPI void APIENTRY glResetMinmax (GLenum);\nGLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);\ntypedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_VERSION_1_3\n#define GL_VERSION_1_3 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveTexture (GLenum);\nGLAPI void APIENTRY glClientActiveTexture (GLenum);\nGLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint);\nGLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort);\nGLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *);\nGLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *);\nGLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *);\nGLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *);\nGLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean);\nGLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);\n#endif\n\n#ifndef GL_VERSION_1_4\n#define GL_VERSION_1_4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glFogCoordf (GLfloat);\nGLAPI void APIENTRY glFogCoordfv (const GLfloat *);\nGLAPI void APIENTRY glFogCoordd (GLdouble);\nGLAPI void APIENTRY glFogCoorddv (const GLdouble *);\nGLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);\nGLAPI void APIENTRY glPointParameterf (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glPointParameteri (GLenum, GLint);\nGLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *);\nGLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *);\nGLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *);\nGLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *);\nGLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint);\nGLAPI void APIENTRY glSecondaryColor3iv (const GLint *);\nGLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glSecondaryColor3sv (const GLshort *);\nGLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *);\nGLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *);\nGLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort);\nGLAPI void APIENTRY glSecondaryColor3usv (const GLushort *);\nGLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dv (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fv (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2i (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2iv (const GLint *);\nGLAPI void APIENTRY glWindowPos2s (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2sv (const GLshort *);\nGLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dv (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fv (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3iv (const GLint *);\nGLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3sv (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\ntypedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_VERSION_1_5\n#define GL_VERSION_1_5 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenQueries (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsQuery (GLuint);\nGLAPI void APIENTRY glBeginQuery (GLenum, GLuint);\nGLAPI void APIENTRY glEndQuery (GLenum);\nGLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *);\nGLAPI void APIENTRY glBindBuffer (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsBuffer (GLuint);\nGLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum);\nGLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *);\nGLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *);\nGLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum);\nGLAPI GLboolean APIENTRY glUnmapBuffer (GLenum);\nGLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);\ntypedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);\ntypedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);\ntypedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);\ntypedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);\ntypedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);\ntypedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);\n#endif\n\n#ifndef GL_VERSION_2_0\n#define GL_VERSION_2_0 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum);\nGLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *);\nGLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint);\nGLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint);\nGLAPI void APIENTRY glAttachShader (GLuint, GLuint);\nGLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *);\nGLAPI void APIENTRY glCompileShader (GLuint);\nGLAPI GLuint APIENTRY glCreateProgram (void);\nGLAPI GLuint APIENTRY glCreateShader (GLenum);\nGLAPI void APIENTRY glDeleteProgram (GLuint);\nGLAPI void APIENTRY glDeleteShader (GLuint);\nGLAPI void APIENTRY glDetachShader (GLuint, GLuint);\nGLAPI void APIENTRY glDisableVertexAttribArray (GLuint);\nGLAPI void APIENTRY glEnableVertexAttribArray (GLuint);\nGLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *);\nGLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *);\nGLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *);\nGLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgram (GLuint);\nGLAPI GLboolean APIENTRY glIsShader (GLuint);\nGLAPI void APIENTRY glLinkProgram (GLuint);\nGLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *);\nGLAPI void APIENTRY glUseProgram (GLuint);\nGLAPI void APIENTRY glUniform1f (GLint, GLfloat);\nGLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform1i (GLint, GLint);\nGLAPI void APIENTRY glUniform2i (GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glValidateProgram (GLuint);\nGLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);\ntypedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);\ntypedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);\ntypedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);\ntypedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);\ntypedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);\ntypedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);\ntypedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);\ntypedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);\ntypedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);\ntypedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);\ntypedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);\ntypedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);\ntypedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);\ntypedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);\ntypedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);\ntypedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_VERSION_2_1\n#define GL_VERSION_2_1 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glUniformMatrix2x3fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3x2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix2x4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4x2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3x4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4x3fv (GLint, GLsizei, GLboolean, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\n#endif\n\n#ifndef GL_VERSION_3_0\n#define GL_VERSION_3_0 1\n/* OpenGL 3.0 also reuses entry points from these extensions: */\n/* ARB_framebuffer_object */\n/* ARB_map_buffer_range */\n/* ARB_vertex_array_object */\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorMaski (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);\nGLAPI void APIENTRY glGetBooleani_v (GLenum, GLuint, GLboolean *);\nGLAPI void APIENTRY glGetIntegeri_v (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glEnablei (GLenum, GLuint);\nGLAPI void APIENTRY glDisablei (GLenum, GLuint);\nGLAPI GLboolean APIENTRY glIsEnabledi (GLenum, GLuint);\nGLAPI void APIENTRY glBeginTransformFeedback (GLenum);\nGLAPI void APIENTRY glEndTransformFeedback (void);\nGLAPI void APIENTRY glBindBufferRange (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);\nGLAPI void APIENTRY glBindBufferBase (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glTransformFeedbackVaryings (GLuint, GLsizei, const GLint *, GLenum);\nGLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint, GLuint, GLint *);\nGLAPI void APIENTRY glClampColor (GLenum, GLenum);\nGLAPI void APIENTRY glBeginConditionalRender (GLuint, GLenum);\nGLAPI void APIENTRY glEndConditionalRender (void);\nGLAPI void APIENTRY glVertexAttribI1i (GLuint, GLint);\nGLAPI void APIENTRY glVertexAttribI2i (GLuint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI3i (GLuint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI4i (GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI1ui (GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI2ui (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI3ui (GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI4ui (GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI1iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI2iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI3iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI4iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI1uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI2uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI3uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4bv (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttribI4sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttribI4ubv (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttribI4usv (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribIPointer (GLuint, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetVertexAttribIiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribIuiv (GLuint, GLenum, GLuint *);\nGLAPI void APIENTRY glGetUniformuiv (GLuint, GLint, GLuint *);\nGLAPI void APIENTRY glBindFragDataLocation (GLuint, GLuint, const GLchar *);\nGLAPI GLint APIENTRY glGetFragDataLocation (GLuint, const GLchar *);\nGLAPI void APIENTRY glUniform1ui (GLint, GLuint);\nGLAPI void APIENTRY glUniform2ui (GLint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform3ui (GLint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform4ui (GLint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform1uiv (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform2uiv (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform3uiv (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform4uiv (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glTexParameterIiv (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glTexParameterIuiv (GLenum, GLenum, const GLuint *);\nGLAPI void APIENTRY glGetTexParameterIiv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetTexParameterIuiv (GLenum, GLenum, GLuint *);\nGLAPI void APIENTRY glClearBufferiv (GLenum, GLint, const GLint *);\nGLAPI void APIENTRY glClearBufferuiv (GLenum, GLint, const GLuint *);\nGLAPI void APIENTRY glClearBufferfv (GLenum, GLint, const GLfloat *);\nGLAPI void APIENTRY glClearBufferfi (GLenum, GLint, GLfloat, GLint);\nGLAPI const GLubyte * APIENTRY glGetStringi (GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);\ntypedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);\ntypedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);\ntypedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);\ntypedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);\ntypedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);\ntypedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);\ntypedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLint *location);\ntypedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);\ntypedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);\ntypedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);\ntypedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);\ntypedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);\ntypedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);\ntypedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);\ntypedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);\n#endif\n\n#ifndef GL_ARB_multitexture\n#define GL_ARB_multitexture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveTextureARB (GLenum);\nGLAPI void APIENTRY glClientActiveTextureARB (GLenum);\nGLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint);\nGLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort);\nGLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);\n#endif\n\n#ifndef GL_ARB_transpose_matrix\n#define GL_ARB_transpose_matrix 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *);\nGLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *);\nGLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *);\nGLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);\n#endif\n\n#ifndef GL_ARB_multisample\n#define GL_ARB_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);\n#endif\n\n#ifndef GL_ARB_texture_env_add\n#define GL_ARB_texture_env_add 1\n#endif\n\n#ifndef GL_ARB_texture_cube_map\n#define GL_ARB_texture_cube_map 1\n#endif\n\n#ifndef GL_ARB_texture_compression\n#define GL_ARB_texture_compression 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img);\n#endif\n\n#ifndef GL_ARB_texture_border_clamp\n#define GL_ARB_texture_border_clamp 1\n#endif\n\n#ifndef GL_ARB_point_parameters\n#define GL_ARB_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_ARB_vertex_blend\n#define GL_ARB_vertex_blend 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *);\nGLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *);\nGLAPI void APIENTRY glWeightivARB (GLint, const GLint *);\nGLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *);\nGLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *);\nGLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *);\nGLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *);\nGLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *);\nGLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexBlendARB (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);\n#endif\n\n#ifndef GL_ARB_matrix_palette\n#define GL_ARB_matrix_palette 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint);\nGLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *);\nGLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *);\nGLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *);\nGLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_ARB_texture_env_combine\n#define GL_ARB_texture_env_combine 1\n#endif\n\n#ifndef GL_ARB_texture_env_crossbar\n#define GL_ARB_texture_env_crossbar 1\n#endif\n\n#ifndef GL_ARB_texture_env_dot3\n#define GL_ARB_texture_env_dot3 1\n#endif\n\n#ifndef GL_ARB_texture_mirrored_repeat\n#define GL_ARB_texture_mirrored_repeat 1\n#endif\n\n#ifndef GL_ARB_depth_texture\n#define GL_ARB_depth_texture 1\n#endif\n\n#ifndef GL_ARB_shadow\n#define GL_ARB_shadow 1\n#endif\n\n#ifndef GL_ARB_shadow_ambient\n#define GL_ARB_shadow_ambient 1\n#endif\n\n#ifndef GL_ARB_window_pos\n#define GL_ARB_window_pos 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2iARB (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2ivARB (const GLint *);\nGLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2svARB (const GLshort *);\nGLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3ivARB (const GLint *);\nGLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3svARB (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_ARB_vertex_program\n#define GL_ARB_vertex_program 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint);\nGLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint);\nGLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glBindProgramARB (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *);\nGLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgramARB (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);\ntypedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);\n#endif\n\n#ifndef GL_ARB_fragment_program\n#define GL_ARB_fragment_program 1\n/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n#define GL_ARB_vertex_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindBufferARB (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsBufferARB (GLuint);\nGLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);\nGLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);\nGLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);\nGLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum);\nGLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum);\nGLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);\ntypedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);\ntypedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);\ntypedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);\ntypedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);\ntypedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);\ntypedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);\n#endif\n\n#ifndef GL_ARB_occlusion_query\n#define GL_ARB_occlusion_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsQueryARB (GLuint);\nGLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint);\nGLAPI void APIENTRY glEndQueryARB (GLenum);\nGLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_ARB_shader_objects\n#define GL_ARB_shader_objects 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);\nGLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);\nGLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);\nGLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);\nGLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);\nGLAPI void APIENTRY glCompileShaderARB (GLhandleARB);\nGLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);\nGLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);\nGLAPI void APIENTRY glLinkProgramARB (GLhandleARB);\nGLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);\nGLAPI void APIENTRY glValidateProgramARB (GLhandleARB);\nGLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);\nGLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform1iARB (GLint, GLint);\nGLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);\nGLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);\nGLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);\nGLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);\nGLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);\nGLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);\nGLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);\nGLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);\ntypedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);\ntypedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);\ntypedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);\ntypedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);\ntypedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);\ntypedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);\ntypedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);\ntypedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);\ntypedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);\n#endif\n\n#ifndef GL_ARB_vertex_shader\n#define GL_ARB_vertex_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);\nGLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);\nGLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);\ntypedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);\n#endif\n\n#ifndef GL_ARB_fragment_shader\n#define GL_ARB_fragment_shader 1\n#endif\n\n#ifndef GL_ARB_shading_language_100\n#define GL_ARB_shading_language_100 1\n#endif\n\n#ifndef GL_ARB_texture_non_power_of_two\n#define GL_ARB_texture_non_power_of_two 1\n#endif\n\n#ifndef GL_ARB_point_sprite\n#define GL_ARB_point_sprite 1\n#endif\n\n#ifndef GL_ARB_fragment_program_shadow\n#define GL_ARB_fragment_program_shadow 1\n#endif\n\n#ifndef GL_ARB_draw_buffers\n#define GL_ARB_draw_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);\n#endif\n\n#ifndef GL_ARB_texture_rectangle\n#define GL_ARB_texture_rectangle 1\n#endif\n\n#ifndef GL_ARB_color_buffer_float\n#define GL_ARB_color_buffer_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glClampColorARB (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);\n#endif\n\n#ifndef GL_ARB_half_float_pixel\n#define GL_ARB_half_float_pixel 1\n#endif\n\n#ifndef GL_ARB_texture_float\n#define GL_ARB_texture_float 1\n#endif\n\n#ifndef GL_ARB_pixel_buffer_object\n#define GL_ARB_pixel_buffer_object 1\n#endif\n\n#ifndef GL_ARB_depth_buffer_float\n#define GL_ARB_depth_buffer_float 1\n#endif\n\n#ifndef GL_ARB_draw_instanced\n#define GL_ARB_draw_instanced 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawArraysInstancedARB (GLenum, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glDrawElementsInstancedARB (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);\n#endif\n\n#ifndef GL_ARB_framebuffer_object\n#define GL_ARB_framebuffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint);\nGLAPI void APIENTRY glBindRenderbuffer (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteRenderbuffers (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenRenderbuffers (GLsizei, GLuint *);\nGLAPI void APIENTRY glRenderbufferStorage (GLenum, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum, GLenum, GLint *);\nGLAPI GLboolean APIENTRY glIsFramebuffer (GLuint);\nGLAPI void APIENTRY glBindFramebuffer (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteFramebuffers (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenFramebuffers (GLsizei, GLuint *);\nGLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum);\nGLAPI void APIENTRY glFramebufferTexture1D (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture2D (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture3D (GLenum, GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferRenderbuffer (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGenerateMipmap (GLenum);\nGLAPI void APIENTRY glBlitFramebuffer (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);\nGLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum, GLsizei, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glFramebufferTextureLayer (GLenum, GLenum, GLuint, GLint, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);\ntypedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);\ntypedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);\n#endif\n\n#ifndef GL_ARB_framebuffer_sRGB\n#define GL_ARB_framebuffer_sRGB 1\n#endif\n\n#ifndef GL_ARB_geometry_shader4\n#define GL_ARB_geometry_shader4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramParameteriARB (GLuint, GLenum, GLint);\nGLAPI void APIENTRY glFramebufferTextureARB (GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum, GLenum, GLuint, GLint, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);\n#endif\n\n#ifndef GL_ARB_half_float_vertex\n#define GL_ARB_half_float_vertex 1\n#endif\n\n#ifndef GL_ARB_instanced_arrays\n#define GL_ARB_instanced_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttribDivisor (GLuint, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);\n#endif\n\n#ifndef GL_ARB_map_buffer_range\n#define GL_ARB_map_buffer_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMapBufferRange (GLenum, GLintptr, GLsizeiptr, GLbitfield);\nGLAPI void APIENTRY glFlushMappedBufferRange (GLenum, GLintptr, GLsizeiptr);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);\ntypedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);\n#endif\n\n#ifndef GL_ARB_texture_buffer_object\n#define GL_ARB_texture_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexBufferARB (GLenum, GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);\n#endif\n\n#ifndef GL_ARB_texture_compression_rgtc\n#define GL_ARB_texture_compression_rgtc 1\n#endif\n\n#ifndef GL_ARB_texture_rg\n#define GL_ARB_texture_rg 1\n#endif\n\n#ifndef GL_ARB_vertex_array_object\n#define GL_ARB_vertex_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindVertexArray (GLuint);\nGLAPI void APIENTRY glDeleteVertexArrays (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenVertexArrays (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsVertexArray (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);\ntypedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);\ntypedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);\ntypedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);\n#endif\n\n#ifndef GL_EXT_abgr\n#define GL_EXT_abgr 1\n#endif\n\n#ifndef GL_EXT_blend_color\n#define GL_EXT_blend_color 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);\n#endif\n\n#ifndef GL_EXT_polygon_offset\n#define GL_EXT_polygon_offset 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);\n#endif\n\n#ifndef GL_EXT_texture\n#define GL_EXT_texture 1\n#endif\n\n#ifndef GL_EXT_texture3D\n#define GL_EXT_texture3D 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_SGIS_texture_filter4\n#define GL_SGIS_texture_filter4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);\ntypedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);\n#endif\n\n#ifndef GL_EXT_subtexture\n#define GL_EXT_subtexture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_EXT_copy_texture\n#define GL_EXT_copy_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_EXT_histogram\n#define GL_EXT_histogram 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean);\nGLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean);\nGLAPI void APIENTRY glResetHistogramEXT (GLenum);\nGLAPI void APIENTRY glResetMinmaxEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);\n#endif\n\n#ifndef GL_EXT_convolution\n#define GL_EXT_convolution 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);\nGLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);\ntypedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);\n#endif\n\n#ifndef GL_SGI_color_matrix\n#define GL_SGI_color_matrix 1\n#endif\n\n#ifndef GL_SGI_color_table\n#define GL_SGI_color_table 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_SGIX_pixel_texture\n#define GL_SGIX_pixel_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTexGenSGIX (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);\n#endif\n\n#ifndef GL_SGIS_pixel_texture\n#define GL_SGIS_pixel_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint);\nGLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *);\nGLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat);\nGLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *);\nGLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_SGIS_texture4D\n#define GL_SGIS_texture4D 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_SGI_texture_color_table\n#define GL_SGI_texture_color_table 1\n#endif\n\n#ifndef GL_EXT_cmyka\n#define GL_EXT_cmyka 1\n#endif\n\n#ifndef GL_EXT_texture_object\n#define GL_EXT_texture_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *);\nGLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsTextureEXT (GLuint);\nGLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);\ntypedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);\ntypedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);\ntypedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);\ntypedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);\ntypedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);\n#endif\n\n#ifndef GL_SGIS_detail_texture\n#define GL_SGIS_detail_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);\n#endif\n\n#ifndef GL_SGIS_sharpen_texture\n#define GL_SGIS_sharpen_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);\n#endif\n\n#ifndef GL_EXT_packed_pixels\n#define GL_EXT_packed_pixels 1\n#endif\n\n#ifndef GL_SGIS_texture_lod\n#define GL_SGIS_texture_lod 1\n#endif\n\n#ifndef GL_SGIS_multisample\n#define GL_SGIS_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean);\nGLAPI void APIENTRY glSamplePatternSGIS (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);\n#endif\n\n#ifndef GL_EXT_rescale_normal\n#define GL_EXT_rescale_normal 1\n#endif\n\n#ifndef GL_EXT_vertex_array\n#define GL_EXT_vertex_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glArrayElementEXT (GLint);\nGLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei);\nGLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *);\nGLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *);\nGLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);\ntypedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);\ntypedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);\ntypedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_misc_attribute\n#define GL_EXT_misc_attribute 1\n#endif\n\n#ifndef GL_SGIS_generate_mipmap\n#define GL_SGIS_generate_mipmap 1\n#endif\n\n#ifndef GL_SGIX_clipmap\n#define GL_SGIX_clipmap 1\n#endif\n\n#ifndef GL_SGIX_shadow\n#define GL_SGIX_shadow 1\n#endif\n\n#ifndef GL_SGIS_texture_edge_clamp\n#define GL_SGIS_texture_edge_clamp 1\n#endif\n\n#ifndef GL_SGIS_texture_border_clamp\n#define GL_SGIS_texture_border_clamp 1\n#endif\n\n#ifndef GL_EXT_blend_minmax\n#define GL_EXT_blend_minmax 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);\n#endif\n\n#ifndef GL_EXT_blend_subtract\n#define GL_EXT_blend_subtract 1\n#endif\n\n#ifndef GL_EXT_blend_logic_op\n#define GL_EXT_blend_logic_op 1\n#endif\n\n#ifndef GL_SGIX_interlace\n#define GL_SGIX_interlace 1\n#endif\n\n#ifndef GL_SGIX_pixel_tiles\n#define GL_SGIX_pixel_tiles 1\n#endif\n\n#ifndef GL_SGIX_texture_select\n#define GL_SGIX_texture_select 1\n#endif\n\n#ifndef GL_SGIX_sprite\n#define GL_SGIX_sprite 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat);\nGLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *);\nGLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint);\nGLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_SGIX_texture_multi_buffer\n#define GL_SGIX_texture_multi_buffer 1\n#endif\n\n#ifndef GL_EXT_point_parameters\n#define GL_EXT_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_SGIS_point_parameters\n#define GL_SGIS_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_SGIX_instruments\n#define GL_SGIX_instruments 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLint APIENTRY glGetInstrumentsSGIX (void);\nGLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *);\nGLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *);\nGLAPI void APIENTRY glReadInstrumentsSGIX (GLint);\nGLAPI void APIENTRY glStartInstrumentsSGIX (void);\nGLAPI void APIENTRY glStopInstrumentsSGIX (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);\ntypedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);\ntypedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);\ntypedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);\ntypedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);\ntypedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);\n#endif\n\n#ifndef GL_SGIX_texture_scale_bias\n#define GL_SGIX_texture_scale_bias 1\n#endif\n\n#ifndef GL_SGIX_framezoom\n#define GL_SGIX_framezoom 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFrameZoomSGIX (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);\n#endif\n\n#ifndef GL_SGIX_tag_sample_buffer\n#define GL_SGIX_tag_sample_buffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTagSampleBufferSGIX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);\n#endif\n\n#ifndef GL_SGIX_polynomial_ffd\n#define GL_SGIX_polynomial_ffd 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *);\nGLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *);\nGLAPI void APIENTRY glDeformSGIX (GLbitfield);\nGLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);\ntypedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);\ntypedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);\n#endif\n\n#ifndef GL_SGIX_reference_plane\n#define GL_SGIX_reference_plane 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);\n#endif\n\n#ifndef GL_SGIX_flush_raster\n#define GL_SGIX_flush_raster 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFlushRasterSGIX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);\n#endif\n\n#ifndef GL_SGIX_depth_texture\n#define GL_SGIX_depth_texture 1\n#endif\n\n#ifndef GL_SGIS_fog_function\n#define GL_SGIS_fog_function 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);\n#endif\n\n#ifndef GL_SGIX_fog_offset\n#define GL_SGIX_fog_offset 1\n#endif\n\n#ifndef GL_HP_image_transform\n#define GL_HP_image_transform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_HP_convolution_border_modes\n#define GL_HP_convolution_border_modes 1\n#endif\n\n#ifndef GL_SGIX_texture_add_env\n#define GL_SGIX_texture_add_env 1\n#endif\n\n#ifndef GL_EXT_color_subtable\n#define GL_EXT_color_subtable 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);\n#endif\n\n#ifndef GL_PGI_vertex_hints\n#define GL_PGI_vertex_hints 1\n#endif\n\n#ifndef GL_PGI_misc_hints\n#define GL_PGI_misc_hints 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glHintPGI (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);\n#endif\n\n#ifndef GL_EXT_paletted_texture\n#define GL_EXT_paletted_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_EXT_clip_volume_hint\n#define GL_EXT_clip_volume_hint 1\n#endif\n\n#ifndef GL_SGIX_list_priority\n#define GL_SGIX_list_priority 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat);\nGLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *);\nGLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint);\nGLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_SGIX_ir_instrument1\n#define GL_SGIX_ir_instrument1 1\n#endif\n\n#ifndef GL_SGIX_calligraphic_fragment\n#define GL_SGIX_calligraphic_fragment 1\n#endif\n\n#ifndef GL_SGIX_texture_lod_bias\n#define GL_SGIX_texture_lod_bias 1\n#endif\n\n#ifndef GL_SGIX_shadow_ambient\n#define GL_SGIX_shadow_ambient 1\n#endif\n\n#ifndef GL_EXT_index_texture\n#define GL_EXT_index_texture 1\n#endif\n\n#ifndef GL_EXT_index_material\n#define GL_EXT_index_material 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);\n#endif\n\n#ifndef GL_EXT_index_func\n#define GL_EXT_index_func 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);\n#endif\n\n#ifndef GL_EXT_index_array_formats\n#define GL_EXT_index_array_formats 1\n#endif\n\n#ifndef GL_EXT_compiled_vertex_array\n#define GL_EXT_compiled_vertex_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei);\nGLAPI void APIENTRY glUnlockArraysEXT (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);\n#endif\n\n#ifndef GL_EXT_cull_vertex\n#define GL_EXT_cull_vertex 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *);\nGLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_SGIX_ycrcb\n#define GL_SGIX_ycrcb 1\n#endif\n\n#ifndef GL_SGIX_fragment_lighting\n#define GL_SGIX_fragment_lighting 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum);\nGLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint);\nGLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *);\nGLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);\n#endif\n\n#ifndef GL_IBM_rasterpos_clip\n#define GL_IBM_rasterpos_clip 1\n#endif\n\n#ifndef GL_HP_texture_lighting\n#define GL_HP_texture_lighting 1\n#endif\n\n#ifndef GL_EXT_draw_range_elements\n#define GL_EXT_draw_range_elements 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);\n#endif\n\n#ifndef GL_WIN_phong_shading\n#define GL_WIN_phong_shading 1\n#endif\n\n#ifndef GL_WIN_specular_fog\n#define GL_WIN_specular_fog 1\n#endif\n\n#ifndef GL_EXT_light_texture\n#define GL_EXT_light_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glApplyTextureEXT (GLenum);\nGLAPI void APIENTRY glTextureLightEXT (GLenum);\nGLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);\ntypedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);\n#endif\n\n#ifndef GL_SGIX_blend_alpha_minmax\n#define GL_SGIX_blend_alpha_minmax 1\n#endif\n\n#ifndef GL_EXT_bgra\n#define GL_EXT_bgra 1\n#endif\n\n#ifndef GL_SGIX_async\n#define GL_SGIX_async 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glAsyncMarkerSGIX (GLuint);\nGLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *);\nGLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *);\nGLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei);\nGLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei);\nGLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);\ntypedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);\ntypedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);\ntypedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);\ntypedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);\ntypedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);\n#endif\n\n#ifndef GL_SGIX_async_pixel\n#define GL_SGIX_async_pixel 1\n#endif\n\n#ifndef GL_SGIX_async_histogram\n#define GL_SGIX_async_histogram 1\n#endif\n\n#ifndef GL_INTEL_parallel_arrays\n#define GL_INTEL_parallel_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *);\nGLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *);\nGLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *);\nGLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\n#endif\n\n#ifndef GL_HP_occlusion_test\n#define GL_HP_occlusion_test 1\n#endif\n\n#ifndef GL_EXT_pixel_transform\n#define GL_EXT_pixel_transform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_EXT_pixel_transform_color_table\n#define GL_EXT_pixel_transform_color_table 1\n#endif\n\n#ifndef GL_EXT_shared_texture_palette\n#define GL_EXT_shared_texture_palette 1\n#endif\n\n#ifndef GL_EXT_separate_specular_color\n#define GL_EXT_separate_specular_color 1\n#endif\n\n#ifndef GL_EXT_secondary_color\n#define GL_EXT_secondary_color 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *);\nGLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *);\nGLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *);\nGLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *);\nGLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort);\nGLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *);\nGLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_texture_perturb_normal\n#define GL_EXT_texture_perturb_normal 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTextureNormalEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);\n#endif\n\n#ifndef GL_EXT_multi_draw_arrays\n#define GL_EXT_multi_draw_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);\n#endif\n\n#ifndef GL_EXT_fog_coord\n#define GL_EXT_fog_coord 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFogCoordfEXT (GLfloat);\nGLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *);\nGLAPI void APIENTRY glFogCoorddEXT (GLdouble);\nGLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *);\nGLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_REND_screen_coordinates\n#define GL_REND_screen_coordinates 1\n#endif\n\n#ifndef GL_EXT_coordinate_frame\n#define GL_EXT_coordinate_frame 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glTangent3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glTangent3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTangent3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glTangent3ivEXT (const GLint *);\nGLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glTangent3svEXT (const GLshort *);\nGLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glBinormal3ivEXT (const GLint *);\nGLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glBinormal3svEXT (const GLshort *);\nGLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);\ntypedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);\ntypedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);\ntypedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);\ntypedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);\ntypedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_texture_env_combine\n#define GL_EXT_texture_env_combine 1\n#endif\n\n#ifndef GL_APPLE_specular_vector\n#define GL_APPLE_specular_vector 1\n#endif\n\n#ifndef GL_APPLE_transform_hint\n#define GL_APPLE_transform_hint 1\n#endif\n\n#ifndef GL_SGIX_fog_scale\n#define GL_SGIX_fog_scale 1\n#endif\n\n#ifndef GL_SUNX_constant_data\n#define GL_SUNX_constant_data 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFinishTextureSUNX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);\n#endif\n\n#ifndef GL_SUN_global_alpha\n#define GL_SUN_global_alpha 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte);\nGLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort);\nGLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint);\nGLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat);\nGLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble);\nGLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte);\nGLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort);\nGLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);\n#endif\n\n#ifndef GL_SUN_triangle_list\n#define GL_SUN_triangle_list 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glReplacementCodeuiSUN (GLuint);\nGLAPI void APIENTRY glReplacementCodeusSUN (GLushort);\nGLAPI void APIENTRY glReplacementCodeubSUN (GLubyte);\nGLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *);\nGLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *);\nGLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *);\nGLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer);\n#endif\n\n#ifndef GL_SUN_vertex\n#define GL_SUN_vertex 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\n#endif\n\n#ifndef GL_EXT_blend_func_separate\n#define GL_EXT_blend_func_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\n#endif\n\n#ifndef GL_INGR_blend_func_separate\n#define GL_INGR_blend_func_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\n#endif\n\n#ifndef GL_INGR_color_clamp\n#define GL_INGR_color_clamp 1\n#endif\n\n#ifndef GL_INGR_interlace_read\n#define GL_INGR_interlace_read 1\n#endif\n\n#ifndef GL_EXT_stencil_wrap\n#define GL_EXT_stencil_wrap 1\n#endif\n\n#ifndef GL_EXT_422_pixels\n#define GL_EXT_422_pixels 1\n#endif\n\n#ifndef GL_NV_texgen_reflection\n#define GL_NV_texgen_reflection 1\n#endif\n\n#ifndef GL_SUN_convolution_border_modes\n#define GL_SUN_convolution_border_modes 1\n#endif\n\n#ifndef GL_EXT_texture_env_add\n#define GL_EXT_texture_env_add 1\n#endif\n\n#ifndef GL_EXT_texture_lod_bias\n#define GL_EXT_texture_lod_bias 1\n#endif\n\n#ifndef GL_EXT_texture_filter_anisotropic\n#define GL_EXT_texture_filter_anisotropic 1\n#endif\n\n#ifndef GL_EXT_vertex_weighting\n#define GL_EXT_vertex_weighting 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexWeightfEXT (GLfloat);\nGLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *);\nGLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_NV_light_max_exponent\n#define GL_NV_light_max_exponent 1\n#endif\n\n#ifndef GL_NV_vertex_array_range\n#define GL_NV_vertex_array_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFlushVertexArrayRangeNV (void);\nGLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);\ntypedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer);\n#endif\n\n#ifndef GL_NV_register_combiners\n#define GL_NV_register_combiners 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *);\nGLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat);\nGLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *);\nGLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint);\nGLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);\nGLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);\ntypedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);\ntypedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);\ntypedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_NV_fog_distance\n#define GL_NV_fog_distance 1\n#endif\n\n#ifndef GL_NV_texgen_emboss\n#define GL_NV_texgen_emboss 1\n#endif\n\n#ifndef GL_NV_blend_square\n#define GL_NV_blend_square 1\n#endif\n\n#ifndef GL_NV_texture_env_combine4\n#define GL_NV_texture_env_combine4 1\n#endif\n\n#ifndef GL_MESA_resize_buffers\n#define GL_MESA_resize_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glResizeBuffersMESA (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);\n#endif\n\n#ifndef GL_MESA_window_pos\n#define GL_MESA_window_pos 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2svMESA (const GLshort *);\nGLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3svMESA (const GLshort *);\nGLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos4ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos4svMESA (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_IBM_cull_vertex\n#define GL_IBM_cull_vertex 1\n#endif\n\n#ifndef GL_IBM_multimode_draw_arrays\n#define GL_IBM_multimode_draw_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint);\nGLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);\ntypedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);\n#endif\n\n#ifndef GL_IBM_vertex_array_lists\n#define GL_IBM_vertex_array_lists 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint);\nGLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\n#endif\n\n#ifndef GL_SGIX_subsample\n#define GL_SGIX_subsample 1\n#endif\n\n#ifndef GL_SGIX_ycrcba\n#define GL_SGIX_ycrcba 1\n#endif\n\n#ifndef GL_SGIX_ycrcb_subsample\n#define GL_SGIX_ycrcb_subsample 1\n#endif\n\n#ifndef GL_SGIX_depth_pass_instrument\n#define GL_SGIX_depth_pass_instrument 1\n#endif\n\n#ifndef GL_3DFX_texture_compression_FXT1\n#define GL_3DFX_texture_compression_FXT1 1\n#endif\n\n#ifndef GL_3DFX_multisample\n#define GL_3DFX_multisample 1\n#endif\n\n#ifndef GL_3DFX_tbuffer\n#define GL_3DFX_tbuffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTbufferMask3DFX (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);\n#endif\n\n#ifndef GL_EXT_multisample\n#define GL_EXT_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean);\nGLAPI void APIENTRY glSamplePatternEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);\n#endif\n\n#ifndef GL_SGIX_vertex_preclip\n#define GL_SGIX_vertex_preclip 1\n#endif\n\n#ifndef GL_SGIX_convolution_accuracy\n#define GL_SGIX_convolution_accuracy 1\n#endif\n\n#ifndef GL_SGIX_resample\n#define GL_SGIX_resample 1\n#endif\n\n#ifndef GL_SGIS_point_line_texgen\n#define GL_SGIS_point_line_texgen 1\n#endif\n\n#ifndef GL_SGIS_texture_color_mask\n#define GL_SGIS_texture_color_mask 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);\n#endif\n\n#ifndef GL_SGIX_igloo_interface\n#define GL_SGIX_igloo_interface 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params);\n#endif\n\n#ifndef GL_EXT_texture_env_dot3\n#define GL_EXT_texture_env_dot3 1\n#endif\n\n#ifndef GL_ATI_texture_mirror_once\n#define GL_ATI_texture_mirror_once 1\n#endif\n\n#ifndef GL_NV_fence\n#define GL_NV_fence 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsFenceNV (GLuint);\nGLAPI GLboolean APIENTRY glTestFenceNV (GLuint);\nGLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glFinishFenceNV (GLuint);\nGLAPI void APIENTRY glSetFenceNV (GLuint, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);\ntypedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);\ntypedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);\n#endif\n\n#ifndef GL_NV_evaluators\n#define GL_NV_evaluators 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *);\nGLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *);\nGLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);\ntypedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);\ntypedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);\n#endif\n\n#ifndef GL_NV_packed_depth_stencil\n#define GL_NV_packed_depth_stencil 1\n#endif\n\n#ifndef GL_NV_register_combiners2\n#define GL_NV_register_combiners2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_NV_texture_compression_vtc\n#define GL_NV_texture_compression_vtc 1\n#endif\n\n#ifndef GL_NV_texture_rectangle\n#define GL_NV_texture_rectangle 1\n#endif\n\n#ifndef GL_NV_texture_shader\n#define GL_NV_texture_shader 1\n#endif\n\n#ifndef GL_NV_texture_shader2\n#define GL_NV_texture_shader2 1\n#endif\n\n#ifndef GL_NV_vertex_array_range2\n#define GL_NV_vertex_array_range2 1\n#endif\n\n#ifndef GL_NV_vertex_program\n#define GL_NV_vertex_program 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *);\nGLAPI void APIENTRY glBindProgramNV (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *);\nGLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *);\nGLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgramNV (GLuint);\nGLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *);\nGLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *);\nGLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum);\nGLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);\ntypedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);\ntypedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);\ntypedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);\n#endif\n\n#ifndef GL_SGIX_texture_coordinate_clamp\n#define GL_SGIX_texture_coordinate_clamp 1\n#endif\n\n#ifndef GL_SGIX_scalebias_hint\n#define GL_SGIX_scalebias_hint 1\n#endif\n\n#ifndef GL_OML_interlace\n#define GL_OML_interlace 1\n#endif\n\n#ifndef GL_OML_subsample\n#define GL_OML_subsample 1\n#endif\n\n#ifndef GL_OML_resample\n#define GL_OML_resample 1\n#endif\n\n#ifndef GL_NV_copy_depth_to_color\n#define GL_NV_copy_depth_to_color 1\n#endif\n\n#ifndef GL_ATI_envmap_bumpmap\n#define GL_ATI_envmap_bumpmap 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *);\nGLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);\ntypedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);\ntypedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);\ntypedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);\n#endif\n\n#ifndef GL_ATI_fragment_shader\n#define GL_ATI_fragment_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint);\nGLAPI void APIENTRY glBindFragmentShaderATI (GLuint);\nGLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint);\nGLAPI void APIENTRY glBeginFragmentShaderATI (void);\nGLAPI void APIENTRY glEndFragmentShaderATI (void);\nGLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum);\nGLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum);\nGLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);\ntypedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);\ntypedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);\ntypedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);\ntypedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);\ntypedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);\n#endif\n\n#ifndef GL_ATI_pn_triangles\n#define GL_ATI_pn_triangles 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint);\nGLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);\n#endif\n\n#ifndef GL_ATI_vertex_array_object\n#define GL_ATI_vertex_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum);\nGLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint);\nGLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum);\nGLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glFreeObjectBufferATI (GLuint);\nGLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);\ntypedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);\ntypedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_EXT_vertex_shader\n#define GL_EXT_vertex_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginVertexShaderEXT (void);\nGLAPI void APIENTRY glEndVertexShaderEXT (void);\nGLAPI void APIENTRY glBindVertexShaderEXT (GLuint);\nGLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint);\nGLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint);\nGLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint);\nGLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *);\nGLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *);\nGLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *);\nGLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *);\nGLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *);\nGLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint);\nGLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint);\nGLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindParameterEXT (GLenum);\nGLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum);\nGLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *);\nGLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);\ntypedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);\ntypedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);\ntypedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);\ntypedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);\ntypedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);\ntypedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);\ntypedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);\ntypedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);\ntypedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);\ntypedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);\ntypedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);\ntypedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);\ntypedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);\ntypedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);\ntypedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);\ntypedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);\ntypedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);\ntypedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);\ntypedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);\ntypedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\n#endif\n\n#ifndef GL_ATI_vertex_streams\n#define GL_ATI_vertex_streams 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort);\nGLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint);\nGLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat);\nGLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble);\nGLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint);\nGLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *);\nGLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum);\nGLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint);\nGLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);\n#endif\n\n#ifndef GL_ATI_element_array\n#define GL_ATI_element_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *);\nGLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei);\nGLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);\n#endif\n\n#ifndef GL_SUN_mesh_array\n#define GL_SUN_mesh_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);\n#endif\n\n#ifndef GL_SUN_slice_accum\n#define GL_SUN_slice_accum 1\n#endif\n\n#ifndef GL_NV_multisample_filter_hint\n#define GL_NV_multisample_filter_hint 1\n#endif\n\n#ifndef GL_NV_depth_clamp\n#define GL_NV_depth_clamp 1\n#endif\n\n#ifndef GL_NV_occlusion_query\n#define GL_NV_occlusion_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint);\nGLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint);\nGLAPI void APIENTRY glEndOcclusionQueryNV (void);\nGLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);\ntypedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_NV_point_sprite\n#define GL_NV_point_sprite 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameteriNV (GLenum, GLint);\nGLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_NV_texture_shader3\n#define GL_NV_texture_shader3 1\n#endif\n\n#ifndef GL_NV_vertex_program1_1\n#define GL_NV_vertex_program1_1 1\n#endif\n\n#ifndef GL_EXT_shadow_funcs\n#define GL_EXT_shadow_funcs 1\n#endif\n\n#ifndef GL_EXT_stencil_two_side\n#define GL_EXT_stencil_two_side 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveStencilFaceEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);\n#endif\n\n#ifndef GL_ATI_text_fragment_shader\n#define GL_ATI_text_fragment_shader 1\n#endif\n\n#ifndef GL_APPLE_client_storage\n#define GL_APPLE_client_storage 1\n#endif\n\n#ifndef GL_APPLE_element_array\n#define GL_APPLE_element_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *);\nGLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei);\nGLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei);\nGLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);\n#endif\n\n#ifndef GL_APPLE_fence\n#define GL_APPLE_fence 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *);\nGLAPI void APIENTRY glSetFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint);\nGLAPI void APIENTRY glFinishFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint);\nGLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);\ntypedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);\ntypedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);\ntypedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);\n#endif\n\n#ifndef GL_APPLE_vertex_array_object\n#define GL_APPLE_vertex_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint);\nGLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);\ntypedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);\ntypedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);\ntypedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);\n#endif\n\n#ifndef GL_APPLE_vertex_array_range\n#define GL_APPLE_vertex_array_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *);\nGLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *);\nGLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);\n#endif\n\n#ifndef GL_APPLE_ycbcr_422\n#define GL_APPLE_ycbcr_422 1\n#endif\n\n#ifndef GL_S3_s3tc\n#define GL_S3_s3tc 1\n#endif\n\n#ifndef GL_ATI_draw_buffers\n#define GL_ATI_draw_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);\n#endif\n\n#ifndef GL_ATI_pixel_format_float\n#define GL_ATI_pixel_format_float 1\n/* This is really a WGL extension, but defines some associated GL enums.\n * ATI does not export \"GL_ATI_pixel_format_float\" in the GL_EXTENSIONS string.\n */\n#endif\n\n#ifndef GL_ATI_texture_env_combine3\n#define GL_ATI_texture_env_combine3 1\n#endif\n\n#ifndef GL_ATI_texture_float\n#define GL_ATI_texture_float 1\n#endif\n\n#ifndef GL_NV_float_buffer\n#define GL_NV_float_buffer 1\n#endif\n\n#ifndef GL_NV_fragment_program\n#define GL_NV_fragment_program 1\n/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *);\nGLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *);\nGLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);\n#endif\n\n#ifndef GL_NV_half_float\n#define GL_NV_half_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glColor3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glColor4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord1hNV (GLhalfNV);\nGLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glFogCoordhNV (GLhalfNV);\nGLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *);\nGLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertexWeighthNV (GLhalfNV);\nGLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);\ntypedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);\ntypedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);\ntypedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);\ntypedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);\ntypedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);\ntypedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);\ntypedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);\ntypedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);\ntypedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);\ntypedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);\ntypedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\n#endif\n\n#ifndef GL_NV_pixel_data_range\n#define GL_NV_pixel_data_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *);\nGLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);\n#endif\n\n#ifndef GL_NV_primitive_restart\n#define GL_NV_primitive_restart 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPrimitiveRestartNV (void);\nGLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);\ntypedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);\n#endif\n\n#ifndef GL_NV_texture_expand_normal\n#define GL_NV_texture_expand_normal 1\n#endif\n\n#ifndef GL_NV_vertex_program2\n#define GL_NV_vertex_program2 1\n#endif\n\n#ifndef GL_ATI_map_object_buffer\n#define GL_ATI_map_object_buffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint);\nGLAPI void APIENTRY glUnmapObjectBufferATI (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);\n#endif\n\n#ifndef GL_ATI_separate_stencil\n#define GL_ATI_separate_stencil 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);\ntypedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);\n#endif\n\n#ifndef GL_ATI_vertex_attrib_array_object\n#define GL_ATI_vertex_attrib_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_OES_read_format\n#define GL_OES_read_format 1\n#endif\n\n#ifndef GL_EXT_depth_bounds_test\n#define GL_EXT_depth_bounds_test 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);\n#endif\n\n#ifndef GL_EXT_texture_mirror_clamp\n#define GL_EXT_texture_mirror_clamp 1\n#endif\n\n#ifndef GL_EXT_blend_equation_separate\n#define GL_EXT_blend_equation_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);\n#endif\n\n#ifndef GL_MESA_pack_invert\n#define GL_MESA_pack_invert 1\n#endif\n\n#ifndef GL_MESA_ycbcr_texture\n#define GL_MESA_ycbcr_texture 1\n#endif\n\n#ifndef GL_EXT_pixel_buffer_object\n#define GL_EXT_pixel_buffer_object 1\n#endif\n\n#ifndef GL_NV_fragment_program_option\n#define GL_NV_fragment_program_option 1\n#endif\n\n#ifndef GL_NV_fragment_program2\n#define GL_NV_fragment_program2 1\n#endif\n\n#ifndef GL_NV_vertex_program2_option\n#define GL_NV_vertex_program2_option 1\n#endif\n\n#ifndef GL_NV_vertex_program3\n#define GL_NV_vertex_program3 1\n#endif\n\n#ifndef GL_EXT_framebuffer_object\n#define GL_EXT_framebuffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint);\nGLAPI void APIENTRY glBindRenderbufferEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *);\nGLAPI void APIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint);\nGLAPI void APIENTRY glBindFramebufferEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *);\nGLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum);\nGLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGenerateMipmapEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);\ntypedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);\ntypedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);\n#endif\n\n#ifndef GL_GREMEDY_string_marker\n#define GL_GREMEDY_string_marker 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);\n#endif\n\n#ifndef GL_EXT_packed_depth_stencil\n#define GL_EXT_packed_depth_stencil 1\n#endif\n\n#ifndef GL_EXT_stencil_clear_tag\n#define GL_EXT_stencil_clear_tag 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStencilClearTagEXT (GLsizei, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);\n#endif\n\n#ifndef GL_EXT_texture_sRGB\n#define GL_EXT_texture_sRGB 1\n#endif\n\n#ifndef GL_EXT_framebuffer_blit\n#define GL_EXT_framebuffer_blit 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlitFramebufferEXT (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);\n#endif\n\n#ifndef GL_EXT_framebuffer_multisample\n#define GL_EXT_framebuffer_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_MESAX_texture_stack\n#define GL_MESAX_texture_stack 1\n#endif\n\n#ifndef GL_EXT_timer_query\n#define GL_EXT_timer_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint, GLenum, GLint64EXT *);\nGLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint, GLenum, GLuint64EXT *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params);\n#endif\n\n#ifndef GL_EXT_gpu_program_parameters\n#define GL_EXT_gpu_program_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum, GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum, GLuint, GLsizei, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);\n#endif\n\n#ifndef GL_APPLE_flush_buffer_range\n#define GL_APPLE_flush_buffer_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBufferParameteriAPPLE (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum, GLintptr, GLsizeiptr);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);\n#endif\n\n#ifndef GL_NV_gpu_program4\n#define GL_NV_gpu_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum, GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum, GLuint, const GLint *);\nGLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum, GLuint, const GLuint *);\nGLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum, GLuint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum, GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum, GLuint, const GLint *);\nGLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum, GLuint, const GLuint *);\nGLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum, GLuint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum, GLuint, GLuint *);\nGLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum, GLuint, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);\n#endif\n\n#ifndef GL_NV_geometry_program4\n#define GL_NV_geometry_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramVertexLimitNV (GLenum, GLint);\nGLAPI void APIENTRY glFramebufferTextureEXT (GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum, GLenum, GLuint, GLint, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);\n#endif\n\n#ifndef GL_EXT_geometry_shader4\n#define GL_EXT_geometry_shader4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramParameteriEXT (GLuint, GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);\n#endif\n\n#ifndef GL_NV_vertex_program4\n#define GL_NV_vertex_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttribI1iEXT (GLuint, GLint);\nGLAPI void APIENTRY glVertexAttribI2iEXT (GLuint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI3iEXT (GLuint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI4iEXT (GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttribI4svEXT (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_EXT_gpu_shader4\n#define GL_EXT_gpu_shader4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetUniformuivEXT (GLuint, GLint, GLuint *);\nGLAPI void APIENTRY glBindFragDataLocationEXT (GLuint, GLuint, const GLchar *);\nGLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint, const GLchar *);\nGLAPI void APIENTRY glUniform1uiEXT (GLint, GLuint);\nGLAPI void APIENTRY glUniform2uiEXT (GLint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform3uiEXT (GLint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform4uiEXT (GLint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform1uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform2uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform3uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform4uivEXT (GLint, GLsizei, const GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);\ntypedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);\ntypedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\n#endif\n\n#ifndef GL_EXT_draw_instanced\n#define GL_EXT_draw_instanced 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);\n#endif\n\n#ifndef GL_EXT_packed_float\n#define GL_EXT_packed_float 1\n#endif\n\n#ifndef GL_EXT_texture_array\n#define GL_EXT_texture_array 1\n#endif\n\n#ifndef GL_EXT_texture_buffer_object\n#define GL_EXT_texture_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexBufferEXT (GLenum, GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);\n#endif\n\n#ifndef GL_EXT_texture_compression_latc\n#define GL_EXT_texture_compression_latc 1\n#endif\n\n#ifndef GL_EXT_texture_compression_rgtc\n#define GL_EXT_texture_compression_rgtc 1\n#endif\n\n#ifndef GL_EXT_texture_shared_exponent\n#define GL_EXT_texture_shared_exponent 1\n#endif\n\n#ifndef GL_NV_depth_buffer_float\n#define GL_NV_depth_buffer_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDepthRangedNV (GLdouble, GLdouble);\nGLAPI void APIENTRY glClearDepthdNV (GLdouble);\nGLAPI void APIENTRY glDepthBoundsdNV (GLdouble, GLdouble);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);\ntypedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);\ntypedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);\n#endif\n\n#ifndef GL_NV_fragment_program4\n#define GL_NV_fragment_program4 1\n#endif\n\n#ifndef GL_NV_framebuffer_multisample_coverage\n#define GL_NV_framebuffer_multisample_coverage 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum, GLsizei, GLsizei, GLenum, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_EXT_framebuffer_sRGB\n#define GL_EXT_framebuffer_sRGB 1\n#endif\n\n#ifndef GL_NV_geometry_shader4\n#define GL_NV_geometry_shader4 1\n#endif\n\n#ifndef GL_NV_parameter_buffer_object\n#define GL_NV_parameter_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum, GLuint, GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum, GLuint, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum, GLuint, GLuint, GLsizei, const GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);\n#endif\n\n#ifndef GL_EXT_draw_buffers2\n#define GL_EXT_draw_buffers2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorMaskIndexedEXT (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);\nGLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum, GLuint, GLboolean *);\nGLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glEnableIndexedEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDisableIndexedEXT (GLenum, GLuint);\nGLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);\ntypedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data);\ntypedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);\ntypedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);\n#endif\n\n#ifndef GL_NV_transform_feedback\n#define GL_NV_transform_feedback 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum);\nGLAPI void APIENTRY glEndTransformFeedbackNV (void);\nGLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint, const GLint *, GLenum);\nGLAPI void APIENTRY glBindBufferRangeNV (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);\nGLAPI void APIENTRY glBindBufferOffsetNV (GLenum, GLuint, GLuint, GLintptr);\nGLAPI void APIENTRY glBindBufferBaseNV (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint, GLsizei, const GLint *, GLenum);\nGLAPI void APIENTRY glActiveVaryingNV (GLuint, const GLchar *);\nGLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetActiveVaryingNV (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint, GLuint, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);\ntypedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);\ntypedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);\ntypedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);\ntypedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);\n#endif\n\n#ifndef GL_EXT_bindable_uniform\n#define GL_EXT_bindable_uniform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glUniformBufferEXT (GLuint, GLint, GLuint);\nGLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint, GLint);\nGLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);\ntypedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);\n#endif\n\n#ifndef GL_EXT_texture_integer\n#define GL_EXT_texture_integer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexParameterIivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glTexParameterIuivEXT (GLenum, GLenum, const GLuint *);\nGLAPI void APIENTRY glGetTexParameterIivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum, GLenum, GLuint *);\nGLAPI void APIENTRY glClearColorIiEXT (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glClearColorIuiEXT (GLuint, GLuint, GLuint, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);\ntypedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);\n#endif\n\n#ifndef GL_GREMEDY_frame_terminator\n#define GL_GREMEDY_frame_terminator 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFrameTerminatorGREMEDY (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);\n#endif\n\n#ifndef GL_NV_conditional_render\n#define GL_NV_conditional_render 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginConditionalRenderNV (GLuint, GLenum);\nGLAPI void APIENTRY glEndConditionalRenderNV (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);\ntypedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);\n#endif\n\n#ifndef GL_NV_present_video\n#define GL_NV_present_video 1\n#endif\n\n#ifndef GL_EXT_transform_feedback\n#define GL_EXT_transform_feedback 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum);\nGLAPI void APIENTRY glEndTransformFeedbackEXT (void);\nGLAPI void APIENTRY glBindBufferRangeEXT (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);\nGLAPI void APIENTRY glBindBufferOffsetEXT (GLenum, GLuint, GLuint, GLintptr);\nGLAPI void APIENTRY glBindBufferBaseEXT (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint, GLsizei, const GLint *, GLenum);\nGLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint, GLuint, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);\ntypedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);\ntypedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);\ntypedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);\ntypedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLint *location);\n#endif\n\n#ifndef GL_EXT_direct_state_access\n#define GL_EXT_direct_state_access 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield);\nGLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield);\nGLAPI void APIENTRY glMatrixLoadfEXT (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMatrixLoaddEXT (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMatrixMultfEXT (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMatrixMultdEXT (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum);\nGLAPI void APIENTRY glMatrixRotatefEXT (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMatrixRotatedEXT (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMatrixScalefEXT (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMatrixScaledEXT (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMatrixTranslatefEXT (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMatrixTranslatedEXT (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMatrixFrustumEXT (GLenum, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMatrixOrthoEXT (GLenum, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMatrixPopEXT (GLenum);\nGLAPI void APIENTRY glMatrixPushEXT (GLenum);\nGLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum, const GLdouble *);\nGLAPI void APIENTRY glTextureParameterfEXT (GLuint, GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glTextureParameterfvEXT (GLuint, GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glTextureParameteriEXT (GLuint, GLenum, GLenum, GLint);\nGLAPI void APIENTRY glTextureParameterivEXT (GLuint, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glTextureImage1DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTextureImage2DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTextureSubImage1DEXT (GLuint, GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTextureSubImage2DEXT (GLuint, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetTextureImageEXT (GLuint, GLenum, GLint, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetTextureParameterivEXT (GLuint, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint, GLenum, GLint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint, GLenum, GLint, GLenum, GLint *);\nGLAPI void APIENTRY glTextureImage3DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTextureSubImage3DEXT (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint, GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glMultiTexParameterfEXT (GLenum, GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum, GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexParameteriEXT (GLenum, GLenum, GLenum, GLint);\nGLAPI void APIENTRY glMultiTexParameterivEXT (GLenum, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexImage1DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glMultiTexImage2DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);\nGLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);\nGLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetMultiTexImageEXT (GLenum, GLenum, GLint, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum, GLenum, GLint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum, GLenum, GLint, GLenum, GLint *);\nGLAPI void APIENTRY glMultiTexImage3DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum, GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glBindMultiTextureEXT (GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum, GLuint);\nGLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glMultiTexEnvfEXT (GLenum, GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum, GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexEnviEXT (GLenum, GLenum, GLenum, GLint);\nGLAPI void APIENTRY glMultiTexEnvivEXT (GLenum, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexGendEXT (GLenum, GLenum, GLenum, GLdouble);\nGLAPI void APIENTRY glMultiTexGendvEXT (GLenum, GLenum, GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexGenfEXT (GLenum, GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexGenfvEXT (GLenum, GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexGeniEXT (GLenum, GLenum, GLenum, GLint);\nGLAPI void APIENTRY glMultiTexGenivEXT (GLenum, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum, GLenum, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum, GLuint, GLvoid* *);\nGLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint, GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint, GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint, GLenum, GLint, GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum, GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum, GLenum, GLint, GLvoid *);\nGLAPI void APIENTRY glNamedProgramStringEXT (GLuint, GLenum, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint, GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint, GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint, GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint, GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint, GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint, GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetNamedProgramivEXT (GLuint, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint, GLenum, GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint, GLenum, GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint, GLenum, GLuint, const GLint *);\nGLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint, GLenum, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint, GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint, GLenum, GLuint, const GLuint *);\nGLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint, GLenum, GLuint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint, GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint, GLenum, GLuint, GLuint *);\nGLAPI void APIENTRY glTextureParameterIivEXT (GLuint, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glTextureParameterIuivEXT (GLuint, GLenum, GLenum, const GLuint *);\nGLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint, GLenum, GLenum, GLuint *);\nGLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum, GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum, GLenum, GLenum, const GLuint *);\nGLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum, GLenum, GLenum, GLuint *);\nGLAPI void APIENTRY glProgramUniform1fEXT (GLuint, GLint, GLfloat);\nGLAPI void APIENTRY glProgramUniform2fEXT (GLuint, GLint, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramUniform3fEXT (GLuint, GLint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramUniform4fEXT (GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramUniform1iEXT (GLuint, GLint, GLint);\nGLAPI void APIENTRY glProgramUniform2iEXT (GLuint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramUniform3iEXT (GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramUniform4iEXT (GLuint, GLint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramUniform1fvEXT (GLuint, GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramUniform2fvEXT (GLuint, GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramUniform3fvEXT (GLuint, GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramUniform4fvEXT (GLuint, GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramUniform1ivEXT (GLuint, GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramUniform2ivEXT (GLuint, GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramUniform3ivEXT (GLuint, GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramUniform4ivEXT (GLuint, GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint, GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glProgramUniform1uiEXT (GLuint, GLint, GLuint);\nGLAPI void APIENTRY glProgramUniform2uiEXT (GLuint, GLint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramUniform3uiEXT (GLuint, GLint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramUniform4uiEXT (GLuint, GLint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramUniform1uivEXT (GLuint, GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glProgramUniform2uivEXT (GLuint, GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glProgramUniform3uivEXT (GLuint, GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glProgramUniform4uivEXT (GLuint, GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glNamedBufferDataEXT (GLuint, GLsizeiptr, const GLvoid *, GLenum);\nGLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint, GLintptr, GLsizeiptr, const GLvoid *);\nGLAPI GLvoid* APIENTRY glMapNamedBufferEXT (GLuint, GLenum);\nGLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint);\nGLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint, GLenum, GLvoid* *);\nGLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint, GLintptr, GLsizeiptr, GLvoid *);\nGLAPI void APIENTRY glTextureBufferEXT (GLuint, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glMultiTexBufferEXT (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint, GLenum, GLint *);\nGLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint, GLenum);\nGLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint, GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint, GLenum);\nGLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum, GLenum);\nGLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint, GLenum);\nGLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint, GLsizei, const GLenum *);\nGLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint, GLenum);\nGLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint, GLsizei, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint, GLsizei, GLsizei, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint, GLenum, GLuint, GLint, GLenum);\nGLAPI void APIENTRY glTextureRenderbufferEXT (GLuint, GLenum, GLuint);\nGLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum, GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);\ntypedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);\ntypedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);\ntypedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);\ntypedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);\ntypedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);\ntypedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data);\ntypedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data);\ntypedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid* *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, GLvoid *img);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, GLvoid *img);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params);\ntypedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage);\ntypedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);\ntypedef GLvoid* (APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);\ntypedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, GLvoid* *params);\ntypedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data);\ntypedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);\ntypedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);\ntypedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params);\ntypedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);\ntypedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);\ntypedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);\ntypedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);\ntypedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);\n#endif\n\n#ifndef GL_EXT_vertex_array_bgra\n#define GL_EXT_vertex_array_bgra 1\n#endif\n\n#ifndef GL_EXT_texture_swizzle\n#define GL_EXT_texture_swizzle 1\n#endif\n\n#ifndef GL_NV_explicit_multisample\n#define GL_NV_explicit_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetMultisamplefvNV (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glSampleMaskIndexedNV (GLuint, GLbitfield);\nGLAPI void APIENTRY glTexRenderbufferNV (GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val);\ntypedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);\ntypedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);\n#endif\n\n#ifndef GL_NV_transform_feedback2\n#define GL_NV_transform_feedback2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindTransformFeedbackNV (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint);\nGLAPI void APIENTRY glPauseTransformFeedbackNV (void);\nGLAPI void APIENTRY glResumeTransformFeedbackNV (void);\nGLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids);\ntypedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);\ntypedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);\ntypedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);\n#endif\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/gl/glxext.h",
    "content": "#ifndef __glxext_h_\n#define __glxext_h_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n** Copyright (c) 2007 The Khronos Group Inc.\n** \n** Permission is hereby granted, free of charge, to any person obtaining a\n** copy of this software and/or associated documentation files (the\n** \"Materials\"), to deal in the Materials without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Materials, and to\n** permit persons to whom the Materials are furnished to do so, subject to\n** the following conditions:\n** \n** The above copyright notice and this permission notice shall be included\n** in all copies or substantial portions of the Materials.\n** \n** THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n*/\n\n#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)\n#define WIN32_LEAN_AND_MEAN 1\n#include <windows.h>\n#endif\n\n#ifndef APIENTRY\n#define APIENTRY\n#endif\n#ifndef APIENTRYP\n#define APIENTRYP APIENTRY *\n#endif\n#ifndef GLAPI\n#define GLAPI extern\n#endif\n\n/*************************************************************/\n\n/* Header file version number, required by OpenGL ABI for Linux */\n/* glxext.h last updated 2008/10/22 */\n/* Current version at http://www.opengl.org/registry/ */\n#define GLX_GLXEXT_VERSION 21\n\n#ifndef GLX_VERSION_1_3\n#define GLX_WINDOW_BIT                     0x00000001\n#define GLX_PIXMAP_BIT                     0x00000002\n#define GLX_PBUFFER_BIT                    0x00000004\n#define GLX_RGBA_BIT                       0x00000001\n#define GLX_COLOR_INDEX_BIT                0x00000002\n#define GLX_PBUFFER_CLOBBER_MASK           0x08000000\n#define GLX_FRONT_LEFT_BUFFER_BIT          0x00000001\n#define GLX_FRONT_RIGHT_BUFFER_BIT         0x00000002\n#define GLX_BACK_LEFT_BUFFER_BIT           0x00000004\n#define GLX_BACK_RIGHT_BUFFER_BIT          0x00000008\n#define GLX_AUX_BUFFERS_BIT                0x00000010\n#define GLX_DEPTH_BUFFER_BIT               0x00000020\n#define GLX_STENCIL_BUFFER_BIT             0x00000040\n#define GLX_ACCUM_BUFFER_BIT               0x00000080\n#define GLX_CONFIG_CAVEAT                  0x20\n#define GLX_X_VISUAL_TYPE                  0x22\n#define GLX_TRANSPARENT_TYPE               0x23\n#define GLX_TRANSPARENT_INDEX_VALUE        0x24\n#define GLX_TRANSPARENT_RED_VALUE          0x25\n#define GLX_TRANSPARENT_GREEN_VALUE        0x26\n#define GLX_TRANSPARENT_BLUE_VALUE         0x27\n#define GLX_TRANSPARENT_ALPHA_VALUE        0x28\n#define GLX_DONT_CARE                      0xFFFFFFFF\n#define GLX_NONE                           0x8000\n#define GLX_SLOW_CONFIG                    0x8001\n#define GLX_TRUE_COLOR                     0x8002\n#define GLX_DIRECT_COLOR                   0x8003\n#define GLX_PSEUDO_COLOR                   0x8004\n#define GLX_STATIC_COLOR                   0x8005\n#define GLX_GRAY_SCALE                     0x8006\n#define GLX_STATIC_GRAY                    0x8007\n#define GLX_TRANSPARENT_RGB                0x8008\n#define GLX_TRANSPARENT_INDEX              0x8009\n#define GLX_VISUAL_ID                      0x800B\n#define GLX_SCREEN                         0x800C\n#define GLX_NON_CONFORMANT_CONFIG          0x800D\n#define GLX_DRAWABLE_TYPE                  0x8010\n#define GLX_RENDER_TYPE                    0x8011\n#define GLX_X_RENDERABLE                   0x8012\n#define GLX_FBCONFIG_ID                    0x8013\n#define GLX_RGBA_TYPE                      0x8014\n#define GLX_COLOR_INDEX_TYPE               0x8015\n#define GLX_MAX_PBUFFER_WIDTH              0x8016\n#define GLX_MAX_PBUFFER_HEIGHT             0x8017\n#define GLX_MAX_PBUFFER_PIXELS             0x8018\n#define GLX_PRESERVED_CONTENTS             0x801B\n#define GLX_LARGEST_PBUFFER                0x801C\n#define GLX_WIDTH                          0x801D\n#define GLX_HEIGHT                         0x801E\n#define GLX_EVENT_MASK                     0x801F\n#define GLX_DAMAGED                        0x8020\n#define GLX_SAVED                          0x8021\n#define GLX_WINDOW                         0x8022\n#define GLX_PBUFFER                        0x8023\n#define GLX_PBUFFER_HEIGHT                 0x8040\n#define GLX_PBUFFER_WIDTH                  0x8041\n#endif\n\n#ifndef GLX_VERSION_1_4\n#define GLX_SAMPLE_BUFFERS                 100000\n#define GLX_SAMPLES                        100001\n#endif\n\n#ifndef GLX_ARB_get_proc_address\n#endif\n\n#ifndef GLX_ARB_multisample\n#define GLX_SAMPLE_BUFFERS_ARB             100000\n#define GLX_SAMPLES_ARB                    100001\n#endif\n\n#ifndef GLX_ARB_fbconfig_float\n#define GLX_RGBA_FLOAT_TYPE_ARB            0x20B9\n#define GLX_RGBA_FLOAT_BIT_ARB             0x00000004\n#endif\n\n#ifndef GLX_ARB_create_context\n#define GLX_CONTEXT_DEBUG_BIT_ARB          0x00000001\n#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002\n#define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091\n#define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092\n#define GLX_CONTEXT_FLAGS_ARB              0x2094\n#endif\n\n#ifndef GLX_SGIS_multisample\n#define GLX_SAMPLE_BUFFERS_SGIS            100000\n#define GLX_SAMPLES_SGIS                   100001\n#endif\n\n#ifndef GLX_EXT_visual_info\n#define GLX_X_VISUAL_TYPE_EXT              0x22\n#define GLX_TRANSPARENT_TYPE_EXT           0x23\n#define GLX_TRANSPARENT_INDEX_VALUE_EXT    0x24\n#define GLX_TRANSPARENT_RED_VALUE_EXT      0x25\n#define GLX_TRANSPARENT_GREEN_VALUE_EXT    0x26\n#define GLX_TRANSPARENT_BLUE_VALUE_EXT     0x27\n#define GLX_TRANSPARENT_ALPHA_VALUE_EXT    0x28\n#define GLX_NONE_EXT                       0x8000\n#define GLX_TRUE_COLOR_EXT                 0x8002\n#define GLX_DIRECT_COLOR_EXT               0x8003\n#define GLX_PSEUDO_COLOR_EXT               0x8004\n#define GLX_STATIC_COLOR_EXT               0x8005\n#define GLX_GRAY_SCALE_EXT                 0x8006\n#define GLX_STATIC_GRAY_EXT                0x8007\n#define GLX_TRANSPARENT_RGB_EXT            0x8008\n#define GLX_TRANSPARENT_INDEX_EXT          0x8009\n#endif\n\n#ifndef GLX_SGI_swap_control\n#endif\n\n#ifndef GLX_SGI_video_sync\n#endif\n\n#ifndef GLX_SGI_make_current_read\n#endif\n\n#ifndef GLX_SGIX_video_source\n#endif\n\n#ifndef GLX_EXT_visual_rating\n#define GLX_VISUAL_CAVEAT_EXT              0x20\n#define GLX_SLOW_VISUAL_EXT                0x8001\n#define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D\n/* reuse GLX_NONE_EXT */\n#endif\n\n#ifndef GLX_EXT_import_context\n#define GLX_SHARE_CONTEXT_EXT              0x800A\n#define GLX_VISUAL_ID_EXT                  0x800B\n#define GLX_SCREEN_EXT                     0x800C\n#endif\n\n#ifndef GLX_SGIX_fbconfig\n#define GLX_WINDOW_BIT_SGIX                0x00000001\n#define GLX_PIXMAP_BIT_SGIX                0x00000002\n#define GLX_RGBA_BIT_SGIX                  0x00000001\n#define GLX_COLOR_INDEX_BIT_SGIX           0x00000002\n#define GLX_DRAWABLE_TYPE_SGIX             0x8010\n#define GLX_RENDER_TYPE_SGIX               0x8011\n#define GLX_X_RENDERABLE_SGIX              0x8012\n#define GLX_FBCONFIG_ID_SGIX               0x8013\n#define GLX_RGBA_TYPE_SGIX                 0x8014\n#define GLX_COLOR_INDEX_TYPE_SGIX          0x8015\n/* reuse GLX_SCREEN_EXT */\n#endif\n\n#ifndef GLX_SGIX_pbuffer\n#define GLX_PBUFFER_BIT_SGIX               0x00000004\n#define GLX_BUFFER_CLOBBER_MASK_SGIX       0x08000000\n#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX     0x00000001\n#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX    0x00000002\n#define GLX_BACK_LEFT_BUFFER_BIT_SGIX      0x00000004\n#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX     0x00000008\n#define GLX_AUX_BUFFERS_BIT_SGIX           0x00000010\n#define GLX_DEPTH_BUFFER_BIT_SGIX          0x00000020\n#define GLX_STENCIL_BUFFER_BIT_SGIX        0x00000040\n#define GLX_ACCUM_BUFFER_BIT_SGIX          0x00000080\n#define GLX_SAMPLE_BUFFERS_BIT_SGIX        0x00000100\n#define GLX_MAX_PBUFFER_WIDTH_SGIX         0x8016\n#define GLX_MAX_PBUFFER_HEIGHT_SGIX        0x8017\n#define GLX_MAX_PBUFFER_PIXELS_SGIX        0x8018\n#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX     0x8019\n#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX    0x801A\n#define GLX_PRESERVED_CONTENTS_SGIX        0x801B\n#define GLX_LARGEST_PBUFFER_SGIX           0x801C\n#define GLX_WIDTH_SGIX                     0x801D\n#define GLX_HEIGHT_SGIX                    0x801E\n#define GLX_EVENT_MASK_SGIX                0x801F\n#define GLX_DAMAGED_SGIX                   0x8020\n#define GLX_SAVED_SGIX                     0x8021\n#define GLX_WINDOW_SGIX                    0x8022\n#define GLX_PBUFFER_SGIX                   0x8023\n#endif\n\n#ifndef GLX_SGI_cushion\n#endif\n\n#ifndef GLX_SGIX_video_resize\n#define GLX_SYNC_FRAME_SGIX                0x00000000\n#define GLX_SYNC_SWAP_SGIX                 0x00000001\n#endif\n\n#ifndef GLX_SGIX_dmbuffer\n#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX     0x8024\n#endif\n\n#ifndef GLX_SGIX_swap_group\n#endif\n\n#ifndef GLX_SGIX_swap_barrier\n#endif\n\n#ifndef GLX_SGIS_blended_overlay\n#define GLX_BLENDED_RGBA_SGIS              0x8025\n#endif\n\n#ifndef GLX_SGIS_shared_multisample\n#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026\n#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027\n#endif\n\n#ifndef GLX_SUN_get_transparent_index\n#endif\n\n#ifndef GLX_3DFX_multisample\n#define GLX_SAMPLE_BUFFERS_3DFX            0x8050\n#define GLX_SAMPLES_3DFX                   0x8051\n#endif\n\n#ifndef GLX_MESA_copy_sub_buffer\n#endif\n\n#ifndef GLX_MESA_pixmap_colormap\n#endif\n\n#ifndef GLX_MESA_release_buffers\n#endif\n\n#ifndef GLX_MESA_set_3dfx_mode\n#define GLX_3DFX_WINDOW_MODE_MESA          0x1\n#define GLX_3DFX_FULLSCREEN_MODE_MESA      0x2\n#endif\n\n#ifndef GLX_SGIX_visual_select_group\n#define GLX_VISUAL_SELECT_GROUP_SGIX       0x8028\n#endif\n\n#ifndef GLX_OML_swap_method\n#define GLX_SWAP_METHOD_OML                0x8060\n#define GLX_SWAP_EXCHANGE_OML              0x8061\n#define GLX_SWAP_COPY_OML                  0x8062\n#define GLX_SWAP_UNDEFINED_OML             0x8063\n#endif\n\n#ifndef GLX_OML_sync_control\n#endif\n\n#ifndef GLX_NV_float_buffer\n#define GLX_FLOAT_COMPONENTS_NV            0x20B0\n#endif\n\n#ifndef GLX_SGIX_hyperpipe\n#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80\n#define GLX_BAD_HYPERPIPE_CONFIG_SGIX      91\n#define GLX_BAD_HYPERPIPE_SGIX             92\n#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX    0x00000001\n#define GLX_HYPERPIPE_RENDER_PIPE_SGIX     0x00000002\n#define GLX_PIPE_RECT_SGIX                 0x00000001\n#define GLX_PIPE_RECT_LIMITS_SGIX          0x00000002\n#define GLX_HYPERPIPE_STEREO_SGIX          0x00000003\n#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX   0x00000004\n#define GLX_HYPERPIPE_ID_SGIX              0x8030\n#endif\n\n#ifndef GLX_MESA_agp_offset\n#endif\n\n#ifndef GLX_EXT_fbconfig_packed_float\n#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT   0x20B1\n#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT    0x00000008\n#endif\n\n#ifndef GLX_EXT_framebuffer_sRGB\n#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT   0x20B2\n#endif\n\n#ifndef GLX_EXT_texture_from_pixmap\n#define GLX_TEXTURE_1D_BIT_EXT             0x00000001\n#define GLX_TEXTURE_2D_BIT_EXT             0x00000002\n#define GLX_TEXTURE_RECTANGLE_BIT_EXT      0x00000004\n#define GLX_BIND_TO_TEXTURE_RGB_EXT        0x20D0\n#define GLX_BIND_TO_TEXTURE_RGBA_EXT       0x20D1\n#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT     0x20D2\n#define GLX_BIND_TO_TEXTURE_TARGETS_EXT    0x20D3\n#define GLX_Y_INVERTED_EXT                 0x20D4\n#define GLX_TEXTURE_FORMAT_EXT             0x20D5\n#define GLX_TEXTURE_TARGET_EXT             0x20D6\n#define GLX_MIPMAP_TEXTURE_EXT             0x20D7\n#define GLX_TEXTURE_FORMAT_NONE_EXT        0x20D8\n#define GLX_TEXTURE_FORMAT_RGB_EXT         0x20D9\n#define GLX_TEXTURE_FORMAT_RGBA_EXT        0x20DA\n#define GLX_TEXTURE_1D_EXT                 0x20DB\n#define GLX_TEXTURE_2D_EXT                 0x20DC\n#define GLX_TEXTURE_RECTANGLE_EXT          0x20DD\n#define GLX_FRONT_LEFT_EXT                 0x20DE\n#define GLX_FRONT_RIGHT_EXT                0x20DF\n#define GLX_BACK_LEFT_EXT                  0x20E0\n#define GLX_BACK_RIGHT_EXT                 0x20E1\n#define GLX_FRONT_EXT                      GLX_FRONT_LEFT_EXT\n#define GLX_BACK_EXT                       GLX_BACK_LEFT_EXT\n#define GLX_AUX0_EXT                       0x20E2\n#define GLX_AUX1_EXT                       0x20E3\n#define GLX_AUX2_EXT                       0x20E4\n#define GLX_AUX3_EXT                       0x20E5\n#define GLX_AUX4_EXT                       0x20E6\n#define GLX_AUX5_EXT                       0x20E7\n#define GLX_AUX6_EXT                       0x20E8\n#define GLX_AUX7_EXT                       0x20E9\n#define GLX_AUX8_EXT                       0x20EA\n#define GLX_AUX9_EXT                       0x20EB\n#endif\n\n#ifndef GLX_NV_present_video\n#define GLX_NUM_VIDEO_SLOTS_NV             0x20F0\n#endif\n\n#ifndef GLX_NV_video_out\n#define GLX_VIDEO_OUT_COLOR_NV             0x20C3\n#define GLX_VIDEO_OUT_ALPHA_NV             0x20C4\n#define GLX_VIDEO_OUT_DEPTH_NV             0x20C5\n#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV   0x20C6\n#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV   0x20C7\n#define GLX_VIDEO_OUT_FRAME_NV             0x20C8\n#define GLX_VIDEO_OUT_FIELD_1_NV           0x20C9\n#define GLX_VIDEO_OUT_FIELD_2_NV           0x20CA\n#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB\n#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC\n#endif\n\n#ifndef GLX_NV_swap_group\n#endif\n\n\n/*************************************************************/\n\n#ifndef GLX_ARB_get_proc_address\ntypedef void (*__GLXextFuncPtr)(void);\n#endif\n\n#ifndef GLX_SGIX_video_source\ntypedef XID GLXVideoSourceSGIX;\n#endif\n\n#ifndef GLX_SGIX_fbconfig\ntypedef XID GLXFBConfigIDSGIX;\ntypedef struct __GLXFBConfigRec *GLXFBConfigSGIX;\n#endif\n\n#ifndef GLX_SGIX_pbuffer\ntypedef XID GLXPbufferSGIX;\ntypedef struct {\n    int type;\n    unsigned long serial;\t  /* # of last request processed by server */\n    Bool send_event;\t\t  /* true if this came for SendEvent request */\n    Display *display;\t\t  /* display the event was read from */\n    GLXDrawable drawable;\t  /* i.d. of Drawable */\n    int event_type;\t\t  /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */\n    int draw_type;\t\t  /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */\n    unsigned int mask;\t  /* mask indicating which buffers are affected*/\n    int x, y;\n    int width, height;\n    int count;\t\t  /* if nonzero, at least this many more */\n} GLXBufferClobberEventSGIX;\n#endif\n\n#ifndef GLEXT_64_TYPES_DEFINED\n/* This code block is duplicated in glext.h, so must be protected */\n#define GLEXT_64_TYPES_DEFINED\n/* Define int32_t, int64_t, and uint64_t types for UST/MSC */\n/* (as used in the GLX_OML_sync_control extension). */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n#include <inttypes.h>\n#elif defined(__sun__) || defined(__digital__)\n#include <inttypes.h>\n#if defined(__STDC__)\n#if defined(__arch64__) || defined(_LP64)\ntypedef long int int64_t;\ntypedef unsigned long int uint64_t;\n#else\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#endif /* __arch64__ */\n#endif /* __STDC__ */\n#elif defined( __VMS ) || defined(__sgi)\n#include <inttypes.h>\n#elif defined(__SCO__) || defined(__USLC__)\n#include <stdint.h>\n#elif defined(__UNIXOS2__) || defined(__SOL64__)\ntypedef long int int32_t;\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#elif defined(_WIN32) && defined(__GNUC__)\n#include <stdint.h>\n#elif defined(_WIN32)\ntypedef __int32 int32_t;\ntypedef __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <inttypes.h>     /* Fallback option */\n#endif\n#endif\n\n#ifndef GLX_VERSION_1_3\n#define GLX_VERSION_1_3 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXFBConfig * glXGetFBConfigs (Display *, int, int *);\nextern GLXFBConfig * glXChooseFBConfig (Display *, int, const int *, int *);\nextern int glXGetFBConfigAttrib (Display *, GLXFBConfig, int, int *);\nextern XVisualInfo * glXGetVisualFromFBConfig (Display *, GLXFBConfig);\nextern GLXWindow glXCreateWindow (Display *, GLXFBConfig, Window, const int *);\nextern void glXDestroyWindow (Display *, GLXWindow);\nextern GLXPixmap glXCreatePixmap (Display *, GLXFBConfig, Pixmap, const int *);\nextern void glXDestroyPixmap (Display *, GLXPixmap);\nextern GLXPbuffer glXCreatePbuffer (Display *, GLXFBConfig, const int *);\nextern void glXDestroyPbuffer (Display *, GLXPbuffer);\nextern void glXQueryDrawable (Display *, GLXDrawable, int, unsigned int *);\nextern GLXContext glXCreateNewContext (Display *, GLXFBConfig, int, GLXContext, Bool);\nextern Bool glXMakeContextCurrent (Display *, GLXDrawable, GLXDrawable, GLXContext);\nextern GLXDrawable glXGetCurrentReadDrawable (void);\nextern Display * glXGetCurrentDisplay (void);\nextern int glXQueryContext (Display *, GLXContext, int, int *);\nextern void glXSelectEvent (Display *, GLXDrawable, unsigned long);\nextern void glXGetSelectedEvent (Display *, GLXDrawable, unsigned long *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);\ntypedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);\ntypedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);\ntypedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);\ntypedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);\ntypedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);\ntypedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);\ntypedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);\ntypedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);\ntypedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);\ntypedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);\ntypedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);\ntypedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);\ntypedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void);\ntypedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void);\ntypedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);\ntypedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);\ntypedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);\n#endif\n\n#ifndef GLX_VERSION_1_4\n#define GLX_VERSION_1_4 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern __GLXextFuncPtr glXGetProcAddress (const GLubyte *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);\n#endif\n\n#ifndef GLX_ARB_get_proc_address\n#define GLX_ARB_get_proc_address 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName);\n#endif\n\n#ifndef GLX_ARB_multisample\n#define GLX_ARB_multisample 1\n#endif\n\n#ifndef GLX_ARB_fbconfig_float\n#define GLX_ARB_fbconfig_float 1\n#endif\n\n#ifndef GLX_ARB_create_context\n#define GLX_ARB_create_context 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXContext glXCreateContextAttribsARB (Display *, GLXFBConfig, GLXContext, Bool, const int *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);\n#endif\n\n#ifndef GLX_SGIS_multisample\n#define GLX_SGIS_multisample 1\n#endif\n\n#ifndef GLX_EXT_visual_info\n#define GLX_EXT_visual_info 1\n#endif\n\n#ifndef GLX_SGI_swap_control\n#define GLX_SGI_swap_control 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern int glXSwapIntervalSGI (int);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);\n#endif\n\n#ifndef GLX_SGI_video_sync\n#define GLX_SGI_video_sync 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern int glXGetVideoSyncSGI (unsigned int *);\nextern int glXWaitVideoSyncSGI (int, int, unsigned int *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count);\ntypedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);\n#endif\n\n#ifndef GLX_SGI_make_current_read\n#define GLX_SGI_make_current_read 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext);\nextern GLXDrawable glXGetCurrentReadDrawableSGI (void);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);\ntypedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);\n#endif\n\n#ifndef GLX_SGIX_video_source\n#define GLX_SGIX_video_source 1\n#ifdef _VL_H\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode);\nextern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);\ntypedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource);\n#endif /* _VL_H */\n#endif\n\n#ifndef GLX_EXT_visual_rating\n#define GLX_EXT_visual_rating 1\n#endif\n\n#ifndef GLX_EXT_import_context\n#define GLX_EXT_import_context 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Display * glXGetCurrentDisplayEXT (void);\nextern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *);\nextern GLXContextID glXGetContextIDEXT (const GLXContext);\nextern GLXContext glXImportContextEXT (Display *, GLXContextID);\nextern void glXFreeContextEXT (Display *, GLXContext);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void);\ntypedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value);\ntypedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context);\ntypedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID);\ntypedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context);\n#endif\n\n#ifndef GLX_SGIX_fbconfig\n#define GLX_SGIX_fbconfig 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *);\nextern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *);\nextern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap);\nextern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool);\nextern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX);\nextern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);\ntypedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements);\ntypedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);\ntypedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);\ntypedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config);\ntypedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis);\n#endif\n\n#ifndef GLX_SGIX_pbuffer\n#define GLX_SGIX_pbuffer 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *);\nextern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX);\nextern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *);\nextern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long);\nextern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);\ntypedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf);\ntypedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);\ntypedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask);\ntypedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask);\n#endif\n\n#ifndef GLX_SGI_cushion\n#define GLX_SGI_cushion 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern void glXCushionSGI (Display *, Window, float);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion);\n#endif\n\n#ifndef GLX_SGIX_video_resize\n#define GLX_SGIX_video_resize 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern int glXBindChannelToWindowSGIX (Display *, int, int, Window);\nextern int glXChannelRectSGIX (Display *, int, int, int, int, int, int);\nextern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *);\nextern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *);\nextern int glXChannelRectSyncSGIX (Display *, int, int, GLenum);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window);\ntypedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h);\ntypedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);\ntypedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h);\ntypedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype);\n#endif\n\n#ifndef GLX_SGIX_dmbuffer\n#define GLX_SGIX_dmbuffer 1\n#ifdef _DM_BUFFER_H_\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);\n#endif /* _DM_BUFFER_H_ */\n#endif\n\n#ifndef GLX_SGIX_swap_group\n#define GLX_SGIX_swap_group 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member);\n#endif\n\n#ifndef GLX_SGIX_swap_barrier\n#define GLX_SGIX_swap_barrier 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int);\nextern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier);\ntypedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max);\n#endif\n\n#ifndef GLX_SUN_get_transparent_index\n#define GLX_SUN_get_transparent_index 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex);\n#endif\n\n#ifndef GLX_MESA_copy_sub_buffer\n#define GLX_MESA_copy_sub_buffer 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);\n#endif\n\n#ifndef GLX_MESA_pixmap_colormap\n#define GLX_MESA_pixmap_colormap 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);\n#endif\n\n#ifndef GLX_MESA_release_buffers\n#define GLX_MESA_release_buffers 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Bool glXReleaseBuffersMESA (Display *, GLXDrawable);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable);\n#endif\n\n#ifndef GLX_MESA_set_3dfx_mode\n#define GLX_MESA_set_3dfx_mode 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Bool glXSet3DfxModeMESA (int);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode);\n#endif\n\n#ifndef GLX_SGIX_visual_select_group\n#define GLX_SGIX_visual_select_group 1\n#endif\n\n#ifndef GLX_OML_swap_method\n#define GLX_OML_swap_method 1\n#endif\n\n#ifndef GLX_OML_sync_control\n#define GLX_OML_sync_control 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern Bool glXGetSyncValuesOML (Display *, GLXDrawable, int64_t *, int64_t *, int64_t *);\nextern Bool glXGetMscRateOML (Display *, GLXDrawable, int32_t *, int32_t *);\nextern int64_t glXSwapBuffersMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t);\nextern Bool glXWaitForMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *);\nextern Bool glXWaitForSbcOML (Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc);\ntypedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);\ntypedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);\ntypedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);\ntypedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc);\n#endif\n\n#ifndef GLX_NV_float_buffer\n#define GLX_NV_float_buffer 1\n#endif\n\n#ifndef GLX_SGIX_hyperpipe\n#define GLX_SGIX_hyperpipe 1\n\ntypedef struct {\n    char    pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];\n    int     networkId;\n} GLXHyperpipeNetworkSGIX;\n\ntypedef struct {\n    char    pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];\n    int     channel;\n    unsigned int\n      participationType;\n    int     timeSlice;\n} GLXHyperpipeConfigSGIX;\n\ntypedef struct {\n    char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];\n    int srcXOrigin, srcYOrigin, srcWidth, srcHeight;\n    int destXOrigin, destYOrigin, destWidth, destHeight;\n} GLXPipeRect;\n\ntypedef struct {\n    char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];\n    int XOrigin, YOrigin, maxHeight, maxWidth;\n} GLXPipeRectLimits;\n\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern GLXHyperpipeNetworkSGIX * glXQueryHyperpipeNetworkSGIX (Display *, int *);\nextern int glXHyperpipeConfigSGIX (Display *, int, int, GLXHyperpipeConfigSGIX *, int *);\nextern GLXHyperpipeConfigSGIX * glXQueryHyperpipeConfigSGIX (Display *, int, int *);\nextern int glXDestroyHyperpipeConfigSGIX (Display *, int);\nextern int glXBindHyperpipeSGIX (Display *, int);\nextern int glXQueryHyperpipeBestAttribSGIX (Display *, int, int, int, void *, void *);\nextern int glXHyperpipeAttribSGIX (Display *, int, int, int, void *);\nextern int glXQueryHyperpipeAttribSGIX (Display *, int, int, int, void *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes);\ntypedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);\ntypedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes);\ntypedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId);\ntypedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId);\ntypedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);\ntypedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList);\ntypedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);\n#endif\n\n#ifndef GLX_MESA_agp_offset\n#define GLX_MESA_agp_offset 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern unsigned int glXGetAGPOffsetMESA (const void *);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void *pointer);\n#endif\n\n#ifndef GLX_EXT_fbconfig_packed_float\n#define GLX_EXT_fbconfig_packed_float 1\n#endif\n\n#ifndef GLX_EXT_framebuffer_sRGB\n#define GLX_EXT_framebuffer_sRGB 1\n#endif\n\n#ifndef GLX_EXT_texture_from_pixmap\n#define GLX_EXT_texture_from_pixmap 1\n#ifdef GLX_GLXEXT_PROTOTYPES\nextern void glXBindTexImageEXT (Display *, GLXDrawable, int, const int *);\nextern void glXReleaseTexImageEXT (Display *, GLXDrawable, int);\n#endif /* GLX_GLXEXT_PROTOTYPES */\ntypedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list);\ntypedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display *dpy, GLXDrawable drawable, int buffer);\n#endif\n\n#ifndef GLX_NV_present_video\n#define GLX_NV_present_video 1\n#endif\n\n#ifndef GLX_NV_video_out\n#define GLX_NV_video_out 1\n#endif\n\n#ifndef GLX_NV_swap_group\n#define GLX_NV_swap_group 1\n#endif\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/gl/wglext.h",
    "content": "#ifndef __wglext_h_\n#define __wglext_h_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n** Copyright (c) 2007 The Khronos Group Inc.\n** \n** Permission is hereby granted, free of charge, to any person obtaining a\n** copy of this software and/or associated documentation files (the\n** \"Materials\"), to deal in the Materials without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Materials, and to\n** permit persons to whom the Materials are furnished to do so, subject to\n** the following conditions:\n** \n** The above copyright notice and this permission notice shall be included\n** in all copies or substantial portions of the Materials.\n** \n** THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n*/\n\n#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)\n#define WIN32_LEAN_AND_MEAN 1\n#include <windows.h>\n#endif\n\n#ifndef APIENTRY\n#define APIENTRY\n#endif\n#ifndef APIENTRYP\n#define APIENTRYP APIENTRY *\n#endif\n#ifndef GLAPI\n#define GLAPI extern\n#endif\n\n/*************************************************************/\n\n/* Header file version number */\n/* wglext.h last updated 2008/10/07 */\n/* Current version at http://www.opengl.org/registry/ */\n#define WGL_WGLEXT_VERSION 11\n\n#ifndef WGL_ARB_buffer_region\n#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001\n#define WGL_BACK_COLOR_BUFFER_BIT_ARB  0x00000002\n#define WGL_DEPTH_BUFFER_BIT_ARB       0x00000004\n#define WGL_STENCIL_BUFFER_BIT_ARB     0x00000008\n#endif\n\n#ifndef WGL_ARB_multisample\n#define WGL_SAMPLE_BUFFERS_ARB         0x2041\n#define WGL_SAMPLES_ARB                0x2042\n#endif\n\n#ifndef WGL_ARB_extensions_string\n#endif\n\n#ifndef WGL_ARB_pixel_format\n#define WGL_NUMBER_PIXEL_FORMATS_ARB   0x2000\n#define WGL_DRAW_TO_WINDOW_ARB         0x2001\n#define WGL_DRAW_TO_BITMAP_ARB         0x2002\n#define WGL_ACCELERATION_ARB           0x2003\n#define WGL_NEED_PALETTE_ARB           0x2004\n#define WGL_NEED_SYSTEM_PALETTE_ARB    0x2005\n#define WGL_SWAP_LAYER_BUFFERS_ARB     0x2006\n#define WGL_SWAP_METHOD_ARB            0x2007\n#define WGL_NUMBER_OVERLAYS_ARB        0x2008\n#define WGL_NUMBER_UNDERLAYS_ARB       0x2009\n#define WGL_TRANSPARENT_ARB            0x200A\n#define WGL_TRANSPARENT_RED_VALUE_ARB  0x2037\n#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038\n#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039\n#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A\n#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B\n#define WGL_SHARE_DEPTH_ARB            0x200C\n#define WGL_SHARE_STENCIL_ARB          0x200D\n#define WGL_SHARE_ACCUM_ARB            0x200E\n#define WGL_SUPPORT_GDI_ARB            0x200F\n#define WGL_SUPPORT_OPENGL_ARB         0x2010\n#define WGL_DOUBLE_BUFFER_ARB          0x2011\n#define WGL_STEREO_ARB                 0x2012\n#define WGL_PIXEL_TYPE_ARB             0x2013\n#define WGL_COLOR_BITS_ARB             0x2014\n#define WGL_RED_BITS_ARB               0x2015\n#define WGL_RED_SHIFT_ARB              0x2016\n#define WGL_GREEN_BITS_ARB             0x2017\n#define WGL_GREEN_SHIFT_ARB            0x2018\n#define WGL_BLUE_BITS_ARB              0x2019\n#define WGL_BLUE_SHIFT_ARB             0x201A\n#define WGL_ALPHA_BITS_ARB             0x201B\n#define WGL_ALPHA_SHIFT_ARB            0x201C\n#define WGL_ACCUM_BITS_ARB             0x201D\n#define WGL_ACCUM_RED_BITS_ARB         0x201E\n#define WGL_ACCUM_GREEN_BITS_ARB       0x201F\n#define WGL_ACCUM_BLUE_BITS_ARB        0x2020\n#define WGL_ACCUM_ALPHA_BITS_ARB       0x2021\n#define WGL_DEPTH_BITS_ARB             0x2022\n#define WGL_STENCIL_BITS_ARB           0x2023\n#define WGL_AUX_BUFFERS_ARB            0x2024\n#define WGL_NO_ACCELERATION_ARB        0x2025\n#define WGL_GENERIC_ACCELERATION_ARB   0x2026\n#define WGL_FULL_ACCELERATION_ARB      0x2027\n#define WGL_SWAP_EXCHANGE_ARB          0x2028\n#define WGL_SWAP_COPY_ARB              0x2029\n#define WGL_SWAP_UNDEFINED_ARB         0x202A\n#define WGL_TYPE_RGBA_ARB              0x202B\n#define WGL_TYPE_COLORINDEX_ARB        0x202C\n#endif\n\n#ifndef WGL_ARB_make_current_read\n#define ERROR_INVALID_PIXEL_TYPE_ARB   0x2043\n#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054\n#endif\n\n#ifndef WGL_ARB_pbuffer\n#define WGL_DRAW_TO_PBUFFER_ARB        0x202D\n#define WGL_MAX_PBUFFER_PIXELS_ARB     0x202E\n#define WGL_MAX_PBUFFER_WIDTH_ARB      0x202F\n#define WGL_MAX_PBUFFER_HEIGHT_ARB     0x2030\n#define WGL_PBUFFER_LARGEST_ARB        0x2033\n#define WGL_PBUFFER_WIDTH_ARB          0x2034\n#define WGL_PBUFFER_HEIGHT_ARB         0x2035\n#define WGL_PBUFFER_LOST_ARB           0x2036\n#endif\n\n#ifndef WGL_ARB_render_texture\n#define WGL_BIND_TO_TEXTURE_RGB_ARB    0x2070\n#define WGL_BIND_TO_TEXTURE_RGBA_ARB   0x2071\n#define WGL_TEXTURE_FORMAT_ARB         0x2072\n#define WGL_TEXTURE_TARGET_ARB         0x2073\n#define WGL_MIPMAP_TEXTURE_ARB         0x2074\n#define WGL_TEXTURE_RGB_ARB            0x2075\n#define WGL_TEXTURE_RGBA_ARB           0x2076\n#define WGL_NO_TEXTURE_ARB             0x2077\n#define WGL_TEXTURE_CUBE_MAP_ARB       0x2078\n#define WGL_TEXTURE_1D_ARB             0x2079\n#define WGL_TEXTURE_2D_ARB             0x207A\n#define WGL_MIPMAP_LEVEL_ARB           0x207B\n#define WGL_CUBE_MAP_FACE_ARB          0x207C\n#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D\n#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E\n#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F\n#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080\n#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081\n#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082\n#define WGL_FRONT_LEFT_ARB             0x2083\n#define WGL_FRONT_RIGHT_ARB            0x2084\n#define WGL_BACK_LEFT_ARB              0x2085\n#define WGL_BACK_RIGHT_ARB             0x2086\n#define WGL_AUX0_ARB                   0x2087\n#define WGL_AUX1_ARB                   0x2088\n#define WGL_AUX2_ARB                   0x2089\n#define WGL_AUX3_ARB                   0x208A\n#define WGL_AUX4_ARB                   0x208B\n#define WGL_AUX5_ARB                   0x208C\n#define WGL_AUX6_ARB                   0x208D\n#define WGL_AUX7_ARB                   0x208E\n#define WGL_AUX8_ARB                   0x208F\n#define WGL_AUX9_ARB                   0x2090\n#endif\n\n#ifndef WGL_ARB_pixel_format_float\n#define WGL_TYPE_RGBA_FLOAT_ARB        0x21A0\n#endif\n\n#ifndef WGL_ARB_create_context\n#define WGL_CONTEXT_DEBUG_BIT_ARB      0x0001\n#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002\n#define WGL_CONTEXT_MAJOR_VERSION_ARB  0x2091\n#define WGL_CONTEXT_MINOR_VERSION_ARB  0x2092\n#define WGL_CONTEXT_LAYER_PLANE_ARB    0x2093\n#define WGL_CONTEXT_FLAGS_ARB          0x2094\n#define ERROR_INVALID_VERSION_ARB      0x2095\n#endif\n\n#ifndef WGL_EXT_make_current_read\n#define ERROR_INVALID_PIXEL_TYPE_EXT   0x2043\n#endif\n\n#ifndef WGL_EXT_pixel_format\n#define WGL_NUMBER_PIXEL_FORMATS_EXT   0x2000\n#define WGL_DRAW_TO_WINDOW_EXT         0x2001\n#define WGL_DRAW_TO_BITMAP_EXT         0x2002\n#define WGL_ACCELERATION_EXT           0x2003\n#define WGL_NEED_PALETTE_EXT           0x2004\n#define WGL_NEED_SYSTEM_PALETTE_EXT    0x2005\n#define WGL_SWAP_LAYER_BUFFERS_EXT     0x2006\n#define WGL_SWAP_METHOD_EXT            0x2007\n#define WGL_NUMBER_OVERLAYS_EXT        0x2008\n#define WGL_NUMBER_UNDERLAYS_EXT       0x2009\n#define WGL_TRANSPARENT_EXT            0x200A\n#define WGL_TRANSPARENT_VALUE_EXT      0x200B\n#define WGL_SHARE_DEPTH_EXT            0x200C\n#define WGL_SHARE_STENCIL_EXT          0x200D\n#define WGL_SHARE_ACCUM_EXT            0x200E\n#define WGL_SUPPORT_GDI_EXT            0x200F\n#define WGL_SUPPORT_OPENGL_EXT         0x2010\n#define WGL_DOUBLE_BUFFER_EXT          0x2011\n#define WGL_STEREO_EXT                 0x2012\n#define WGL_PIXEL_TYPE_EXT             0x2013\n#define WGL_COLOR_BITS_EXT             0x2014\n#define WGL_RED_BITS_EXT               0x2015\n#define WGL_RED_SHIFT_EXT              0x2016\n#define WGL_GREEN_BITS_EXT             0x2017\n#define WGL_GREEN_SHIFT_EXT            0x2018\n#define WGL_BLUE_BITS_EXT              0x2019\n#define WGL_BLUE_SHIFT_EXT             0x201A\n#define WGL_ALPHA_BITS_EXT             0x201B\n#define WGL_ALPHA_SHIFT_EXT            0x201C\n#define WGL_ACCUM_BITS_EXT             0x201D\n#define WGL_ACCUM_RED_BITS_EXT         0x201E\n#define WGL_ACCUM_GREEN_BITS_EXT       0x201F\n#define WGL_ACCUM_BLUE_BITS_EXT        0x2020\n#define WGL_ACCUM_ALPHA_BITS_EXT       0x2021\n#define WGL_DEPTH_BITS_EXT             0x2022\n#define WGL_STENCIL_BITS_EXT           0x2023\n#define WGL_AUX_BUFFERS_EXT            0x2024\n#define WGL_NO_ACCELERATION_EXT        0x2025\n#define WGL_GENERIC_ACCELERATION_EXT   0x2026\n#define WGL_FULL_ACCELERATION_EXT      0x2027\n#define WGL_SWAP_EXCHANGE_EXT          0x2028\n#define WGL_SWAP_COPY_EXT              0x2029\n#define WGL_SWAP_UNDEFINED_EXT         0x202A\n#define WGL_TYPE_RGBA_EXT              0x202B\n#define WGL_TYPE_COLORINDEX_EXT        0x202C\n#endif\n\n#ifndef WGL_EXT_pbuffer\n#define WGL_DRAW_TO_PBUFFER_EXT        0x202D\n#define WGL_MAX_PBUFFER_PIXELS_EXT     0x202E\n#define WGL_MAX_PBUFFER_WIDTH_EXT      0x202F\n#define WGL_MAX_PBUFFER_HEIGHT_EXT     0x2030\n#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT  0x2031\n#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032\n#define WGL_PBUFFER_LARGEST_EXT        0x2033\n#define WGL_PBUFFER_WIDTH_EXT          0x2034\n#define WGL_PBUFFER_HEIGHT_EXT         0x2035\n#endif\n\n#ifndef WGL_EXT_depth_float\n#define WGL_DEPTH_FLOAT_EXT            0x2040\n#endif\n\n#ifndef WGL_3DFX_multisample\n#define WGL_SAMPLE_BUFFERS_3DFX        0x2060\n#define WGL_SAMPLES_3DFX               0x2061\n#endif\n\n#ifndef WGL_EXT_multisample\n#define WGL_SAMPLE_BUFFERS_EXT         0x2041\n#define WGL_SAMPLES_EXT                0x2042\n#endif\n\n#ifndef WGL_I3D_digital_video_control\n#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050\n#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051\n#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052\n#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053\n#endif\n\n#ifndef WGL_I3D_gamma\n#define WGL_GAMMA_TABLE_SIZE_I3D       0x204E\n#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D  0x204F\n#endif\n\n#ifndef WGL_I3D_genlock\n#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044\n#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045\n#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046\n#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047\n#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048\n#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049\n#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A\n#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B\n#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C\n#endif\n\n#ifndef WGL_I3D_image_buffer\n#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001\n#define WGL_IMAGE_BUFFER_LOCK_I3D      0x00000002\n#endif\n\n#ifndef WGL_I3D_swap_frame_lock\n#endif\n\n#ifndef WGL_NV_render_depth_texture\n#define WGL_BIND_TO_TEXTURE_DEPTH_NV   0x20A3\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4\n#define WGL_DEPTH_TEXTURE_FORMAT_NV    0x20A5\n#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6\n#define WGL_DEPTH_COMPONENT_NV         0x20A7\n#endif\n\n#ifndef WGL_NV_render_texture_rectangle\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1\n#define WGL_TEXTURE_RECTANGLE_NV       0x20A2\n#endif\n\n#ifndef WGL_ATI_pixel_format_float\n#define WGL_TYPE_RGBA_FLOAT_ATI        0x21A0\n#endif\n\n#ifndef WGL_NV_float_buffer\n#define WGL_FLOAT_COMPONENTS_NV        0x20B0\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3\n#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4\n#define WGL_TEXTURE_FLOAT_R_NV         0x20B5\n#define WGL_TEXTURE_FLOAT_RG_NV        0x20B6\n#define WGL_TEXTURE_FLOAT_RGB_NV       0x20B7\n#define WGL_TEXTURE_FLOAT_RGBA_NV      0x20B8\n#endif\n\n#ifndef WGL_3DL_stereo_control\n#define WGL_STEREO_EMITTER_ENABLE_3DL  0x2055\n#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056\n#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057\n#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058\n#endif\n\n#ifndef WGL_EXT_pixel_format_packed_float\n#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8\n#endif\n\n#ifndef WGL_EXT_framebuffer_sRGB\n#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9\n#endif\n\n#ifndef WGL_NV_present_video\n#define WGL_NUM_VIDEO_SLOTS_NV         0x20F0\n#endif\n\n#ifndef WGL_NV_video_out\n#define WGL_BIND_TO_VIDEO_RGB_NV       0x20C0\n#define WGL_BIND_TO_VIDEO_RGBA_NV      0x20C1\n#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2\n#define WGL_VIDEO_OUT_COLOR_NV         0x20C3\n#define WGL_VIDEO_OUT_ALPHA_NV         0x20C4\n#define WGL_VIDEO_OUT_DEPTH_NV         0x20C5\n#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6\n#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7\n#define WGL_VIDEO_OUT_FRAME            0x20C8\n#define WGL_VIDEO_OUT_FIELD_1          0x20C9\n#define WGL_VIDEO_OUT_FIELD_2          0x20CA\n#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB\n#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC\n#endif\n\n#ifndef WGL_NV_swap_group\n#endif\n\n#ifndef WGL_NV_gpu_affinity\n#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0\n#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1\n#endif\n\n\n/*************************************************************/\n\n#ifndef WGL_ARB_pbuffer\nDECLARE_HANDLE(HPBUFFERARB);\n#endif\n#ifndef WGL_EXT_pbuffer\nDECLARE_HANDLE(HPBUFFEREXT);\n#endif\n#ifndef WGL_NV_present_video\nDECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);\n#endif\n#ifndef WGL_NV_video_out\nDECLARE_HANDLE(HPVIDEODEV);\n#endif\n#ifndef WGL_NV_gpu_affinity\nDECLARE_HANDLE(HPGPUNV);\nDECLARE_HANDLE(HGPUNV);\n\ntypedef struct _GPU_DEVICE {\n    DWORD  cb;\n    CHAR   DeviceName[32];\n    CHAR   DeviceString[128];\n    DWORD  Flags;\n    RECT   rcVirtualScreen;\n} GPU_DEVICE, *PGPU_DEVICE;\n#endif\n\n#ifndef WGL_ARB_buffer_region\n#define WGL_ARB_buffer_region 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT);\nextern VOID WINAPI wglDeleteBufferRegionARB (HANDLE);\nextern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int);\nextern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);\ntypedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);\ntypedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);\ntypedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);\n#endif\n\n#ifndef WGL_ARB_multisample\n#define WGL_ARB_multisample 1\n#endif\n\n#ifndef WGL_ARB_extensions_string\n#define WGL_ARB_extensions_string 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern const char * WINAPI wglGetExtensionsStringARB (HDC);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);\n#endif\n\n#ifndef WGL_ARB_pixel_format\n#define WGL_ARB_pixel_format 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *);\nextern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *);\nextern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);\ntypedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);\ntypedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);\n#endif\n\n#ifndef WGL_ARB_make_current_read\n#define WGL_ARB_make_current_read 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC);\nextern HDC WINAPI wglGetCurrentReadDCARB (void);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);\ntypedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);\n#endif\n\n#ifndef WGL_ARB_pbuffer\n#define WGL_ARB_pbuffer 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *);\nextern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB);\nextern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC);\nextern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB);\nextern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);\ntypedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);\ntypedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);\ntypedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);\ntypedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);\n#endif\n\n#ifndef WGL_ARB_render_texture\n#define WGL_ARB_render_texture 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int);\nextern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int);\nextern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);\ntypedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);\ntypedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);\n#endif\n\n#ifndef WGL_ARB_pixel_format_float\n#define WGL_ARB_pixel_format_float 1\n#endif\n\n#ifndef WGL_ARB_create_context\n#define WGL_ARB_create_context 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);\n#endif\n\n#ifndef WGL_EXT_display_color_table\n#define WGL_EXT_display_color_table 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort);\nextern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint);\nextern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort);\nextern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);\ntypedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length);\ntypedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);\ntypedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);\n#endif\n\n#ifndef WGL_EXT_extensions_string\n#define WGL_EXT_extensions_string 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern const char * WINAPI wglGetExtensionsStringEXT (void);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);\n#endif\n\n#ifndef WGL_EXT_make_current_read\n#define WGL_EXT_make_current_read 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC);\nextern HDC WINAPI wglGetCurrentReadDCEXT (void);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);\ntypedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void);\n#endif\n\n#ifndef WGL_EXT_pbuffer\n#define WGL_EXT_pbuffer 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *);\nextern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT);\nextern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC);\nextern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT);\nextern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);\ntypedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);\ntypedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);\ntypedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);\ntypedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);\n#endif\n\n#ifndef WGL_EXT_pixel_format\n#define WGL_EXT_pixel_format 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *);\nextern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *);\nextern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);\ntypedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);\ntypedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);\n#endif\n\n#ifndef WGL_EXT_swap_control\n#define WGL_EXT_swap_control 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglSwapIntervalEXT (int);\nextern int WINAPI wglGetSwapIntervalEXT (void);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);\ntypedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);\n#endif\n\n#ifndef WGL_EXT_depth_float\n#define WGL_EXT_depth_float 1\n#endif\n\n#ifndef WGL_NV_vertex_array_range\n#define WGL_NV_vertex_array_range 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat);\nextern void WINAPI wglFreeMemoryNV (void *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);\ntypedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);\n#endif\n\n#ifndef WGL_3DFX_multisample\n#define WGL_3DFX_multisample 1\n#endif\n\n#ifndef WGL_EXT_multisample\n#define WGL_EXT_multisample 1\n#endif\n\n#ifndef WGL_OML_sync_control\n#define WGL_OML_sync_control 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *);\nextern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *);\nextern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64);\nextern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64);\nextern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *);\nextern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);\ntypedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);\ntypedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);\ntypedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);\ntypedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);\ntypedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);\n#endif\n\n#ifndef WGL_I3D_digital_video_control\n#define WGL_I3D_digital_video_control 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *);\nextern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);\ntypedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);\n#endif\n\n#ifndef WGL_I3D_gamma\n#define WGL_I3D_gamma 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *);\nextern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *);\nextern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *);\nextern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);\ntypedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);\ntypedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);\ntypedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);\n#endif\n\n#ifndef WGL_I3D_genlock\n#define WGL_I3D_genlock 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglEnableGenlockI3D (HDC);\nextern BOOL WINAPI wglDisableGenlockI3D (HDC);\nextern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *);\nextern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT);\nextern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *);\nextern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT);\nextern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *);\nextern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT);\nextern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *);\nextern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT);\nextern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *);\nextern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);\ntypedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);\ntypedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag);\ntypedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);\ntypedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource);\ntypedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);\ntypedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge);\ntypedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);\ntypedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate);\ntypedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);\ntypedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay);\ntypedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);\n#endif\n\n#ifndef WGL_I3D_image_buffer\n#define WGL_I3D_image_buffer 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT);\nextern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID);\nextern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT);\nextern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);\ntypedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);\ntypedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);\ntypedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count);\n#endif\n\n#ifndef WGL_I3D_swap_frame_lock\n#define WGL_I3D_swap_frame_lock 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglEnableFrameLockI3D (void);\nextern BOOL WINAPI wglDisableFrameLockI3D (void);\nextern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *);\nextern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void);\ntypedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void);\ntypedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag);\ntypedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag);\n#endif\n\n#ifndef WGL_I3D_swap_frame_usage\n#define WGL_I3D_swap_frame_usage 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetFrameUsageI3D (float *);\nextern BOOL WINAPI wglBeginFrameTrackingI3D (void);\nextern BOOL WINAPI wglEndFrameTrackingI3D (void);\nextern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage);\ntypedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);\ntypedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);\ntypedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);\n#endif\n\n#ifndef WGL_ATI_pixel_format_float\n#define WGL_ATI_pixel_format_float 1\n#endif\n\n#ifndef WGL_NV_float_buffer\n#define WGL_NV_float_buffer 1\n#endif\n\n#ifndef WGL_EXT_pixel_format_packed_float\n#define WGL_EXT_pixel_format_packed_float 1\n#endif\n\n#ifndef WGL_EXT_framebuffer_sRGB\n#define WGL_EXT_framebuffer_sRGB 1\n#endif\n\n#ifndef WGL_NV_present_video\n#define WGL_NV_present_video 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern int WINAPI wglEnumerateVideoDevicesNV (HDC, HVIDEOOUTPUTDEVICENV *);\nextern BOOL WINAPI wglBindVideoDeviceNV (HDC, unsigned int, HVIDEOOUTPUTDEVICENV, const int *);\nextern BOOL WINAPI wglQueryCurrentContextNV (int, int *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);\ntypedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);\ntypedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue);\n#endif\n\n#ifndef WGL_NV_video_out\n#define WGL_NV_video_out 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglGetVideoDeviceNV (HDC, int, HPVIDEODEV *);\nextern BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV);\nextern BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV, HPBUFFERARB, int);\nextern BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB, int);\nextern BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB, int, unsigned long *, BOOL);\nextern BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV, unsigned long *, unsigned long *);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);\ntypedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);\ntypedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);\ntypedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);\ntypedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);\ntypedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);\n#endif\n\n#ifndef WGL_NV_swap_group\n#define WGL_NV_swap_group 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglJoinSwapGroupNV (HDC, GLuint);\nextern BOOL WINAPI wglBindSwapBarrierNV (GLuint, GLuint);\nextern BOOL WINAPI wglQuerySwapGroupNV (HDC, GLuint *, GLuint *);\nextern BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC, GLuint *, GLuint *);\nextern BOOL WINAPI wglQueryFrameCountNV (HDC, GLuint *);\nextern BOOL WINAPI wglResetFrameCountNV (HDC);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);\ntypedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);\ntypedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier);\ntypedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);\ntypedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count);\ntypedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);\n#endif\n\n#ifndef WGL_NV_gpu_affinity\n#define WGL_NV_gpu_affinity 1\n#ifdef WGL_WGLEXT_PROTOTYPES\nextern BOOL WINAPI wglEnumGpusNV (UINT, HGPUNV *);\nextern BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV, UINT, PGPU_DEVICE);\nextern HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *);\nextern BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC, UINT, HGPUNV *);\nextern BOOL WINAPI wglDeleteDCNV (HDC);\n#endif /* WGL_WGLEXT_PROTOTYPES */\ntypedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);\ntypedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);\ntypedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);\ntypedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);\ntypedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);\n#endif\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/image.c",
    "content": "/* \n * SGI rgb file reader borrowed from gltk library\n */\n\n#include \"togl.h\"               /* added by GG to include windows.h */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"image.h\"\n\n#ifndef SEEK_SET\n#  define SEEK_SET 0\n#endif\n\n\nstatic void\ntkQuit(void)\n{\n    exit(0);\n}\n\n\n/******************************************************************************/\n\ntypedef struct _rawImageRec\n{\n    unsigned short imagic;\n    unsigned short type;\n    unsigned short dim;\n    unsigned short sizeX, sizeY, sizeZ;\n    unsigned long min, max;\n    unsigned long wasteBytes;\n    char    name[80];\n    unsigned long colorMap;\n    FILE   *file;\n    unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;\n    unsigned long rleEnd;\n    GLuint *rowStart;\n    GLint  *rowSize;\n} rawImageRec;\n\n\n/******************************************************************************/\n\nstatic void\nConvertShort(unsigned short *array, long length)\n{\n    unsigned long b1, b2;\n    unsigned char *ptr;\n\n    ptr = (unsigned char *) array;\n    while (length--) {\n        b1 = *ptr++;\n        b2 = *ptr++;\n        *array++ = (unsigned short) ((b1 << 8) | b2);\n    }\n}\n\nstatic void\nConvertLong(GLuint *array, long length)\n{\n    unsigned long b1, b2, b3, b4;\n    unsigned char *ptr;\n\n    ptr = (unsigned char *) array;\n    while (length--) {\n        b1 = *ptr++;\n        b2 = *ptr++;\n        b3 = *ptr++;\n        b4 = *ptr++;\n        *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);\n    }\n}\n\nstatic rawImageRec *\nRawImageOpen(const char *fileName)\n{\n    union\n    {\n        int     testWord;\n        char    testByte[4];\n    } endianTest;\n    rawImageRec *raw;\n    GLenum  swapFlag;\n    int     x;\n\n    endianTest.testWord = 1;\n    if (endianTest.testByte[0] == 1) {\n        swapFlag = GL_TRUE;\n    } else {\n        swapFlag = GL_FALSE;\n    }\n\n    raw = (rawImageRec *) malloc(sizeof (rawImageRec));\n    if (raw == NULL) {\n        fprintf(stderr, \"Out of memory!\\n\");\n        tkQuit();\n    }\n    if ((raw->file = fopen(fileName, \"rb\")) == NULL) {\n        perror(fileName);\n        tkQuit();\n    }\n\n    fread(raw, 1, 12, raw->file);\n\n    if (swapFlag) {\n        ConvertShort(&raw->imagic, 6);\n    }\n\n    raw->tmp = (unsigned char *) malloc(raw->sizeX * 256);\n    raw->tmpR = (unsigned char *) malloc(raw->sizeX * 256);\n    raw->tmpG = (unsigned char *) malloc(raw->sizeX * 256);\n    raw->tmpB = (unsigned char *) malloc(raw->sizeX * 256);\n    raw->tmpA = (unsigned char *) malloc(raw->sizeX * 256);\n    if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||\n            raw->tmpB == NULL || raw->tmpA == NULL) {\n        fprintf(stderr, \"Out of memory!\\n\");\n        tkQuit();\n    }\n\n    if ((raw->type & 0xFF00) == 0x0100) {\n        x = raw->sizeY * raw->sizeZ * sizeof (GLuint);\n        raw->rowStart = (GLuint *) malloc(x);\n        raw->rowSize = (GLint *) malloc(x);\n        if (raw->rowStart == NULL || raw->rowSize == NULL) {\n            fprintf(stderr, \"Out of memory!\\n\");\n            tkQuit();\n        }\n        raw->rleEnd = 512 + (2 * x);\n        fseek(raw->file, 512, SEEK_SET);\n        fread(raw->rowStart, 1, x, raw->file);\n        fread(raw->rowSize, 1, x, raw->file);\n        if (swapFlag) {\n            ConvertLong(raw->rowStart, x / sizeof (GLuint));\n            ConvertLong((GLuint *) raw->rowSize, x / sizeof (GLint));\n        }\n    }\n    return raw;\n}\n\nstatic void\nRawImageClose(rawImageRec * raw)\n{\n\n    fclose(raw->file);\n    free(raw->tmp);\n    free(raw->tmpR);\n    free(raw->tmpG);\n    free(raw->tmpB);\n    free(raw->tmpA);\n    free(raw);\n}\n\nstatic void\nRawImageGetRow(rawImageRec * raw, unsigned char *buf, int y, int z)\n{\n    unsigned char *iPtr, *oPtr, pixel;\n    int     count;\n\n    if ((raw->type & 0xFF00) == 0x0100) {\n        fseek(raw->file, raw->rowStart[y + z * raw->sizeY], SEEK_SET);\n        fread(raw->tmp, 1, (unsigned int) raw->rowSize[y + z * raw->sizeY],\n                raw->file);\n\n        iPtr = raw->tmp;\n        oPtr = buf;\n        while (1) {\n            pixel = *iPtr++;\n            count = (int) (pixel & 0x7F);\n            if (!count) {\n                return;\n            }\n            if (pixel & 0x80) {\n                while (count--) {\n                    *oPtr++ = *iPtr++;\n                }\n            } else {\n                pixel = *iPtr++;\n                while (count--) {\n                    *oPtr++ = pixel;\n                }\n            }\n        }\n    } else {\n        fseek(raw->file, 512 + (y * raw->sizeX) + (z * raw->sizeX * raw->sizeY),\n                SEEK_SET);\n        fread(buf, 1, raw->sizeX, raw->file);\n    }\n}\n\nstatic void\nRawImageGetData(rawImageRec * raw, TK_RGBImageRec * final)\n{\n    unsigned char *ptr;\n    int     i, j;\n\n    final->data =\n            (unsigned char *) malloc((raw->sizeX + 1) * (raw->sizeY + 1) * 4);\n    if (final->data == NULL) {\n        fprintf(stderr, \"Out of memory!\\n\");\n        tkQuit();\n    }\n\n    ptr = final->data;\n    for (i = 0; i < (int) (raw->sizeY); i++) {\n        RawImageGetRow(raw, raw->tmpR, i, 0);\n        RawImageGetRow(raw, raw->tmpG, i, 1);\n        RawImageGetRow(raw, raw->tmpB, i, 2);\n        if (raw->sizeZ == 4) {\n            /* 4 components */\n            RawImageGetRow(raw, raw->tmpA, i, 3);\n            for (j = 0; j < (int) (raw->sizeX); j++) {\n                *ptr++ = *(raw->tmpR + j);\n                *ptr++ = *(raw->tmpG + j);\n                *ptr++ = *(raw->tmpB + j);\n                *ptr++ = *(raw->tmpA + j);\n            }\n        } else {\n            /* 3 components */\n            for (j = 0; j < (int) (raw->sizeX); j++) {\n                *ptr++ = *(raw->tmpR + j);\n                *ptr++ = *(raw->tmpG + j);\n                *ptr++ = *(raw->tmpB + j);\n            }\n        }\n    }\n}\n\nTK_RGBImageRec *\ntkRGBImageLoad(const char *fileName)\n{\n    rawImageRec *raw;\n    TK_RGBImageRec *final;\n\n    raw = RawImageOpen(fileName);\n    final = (TK_RGBImageRec *) malloc(sizeof (TK_RGBImageRec));\n    if (final == NULL) {\n        fprintf(stderr, \"Out of memory!\\n\");\n        tkQuit();\n    }\n    final->sizeX = raw->sizeX;\n    final->sizeY = raw->sizeY;\n    final->sizeZ = raw->sizeZ;\n    RawImageGetData(raw, final);\n    RawImageClose(raw);\n    return final;\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "ng/Togl2.1/image.h",
    "content": "/* image.h */\n\n#ifndef IMAGE_H\n#  define IMAGE_H\n\ntypedef struct _TK_RGBImageRec\n{\n    int     sizeX, sizeY, sizeZ;\n    unsigned char *data;\n} TK_RGBImageRec;\n\nextern TK_RGBImageRec *tkRGBImageLoad(const char *fileName);\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/index.c",
    "content": "/* $Id: index.c,v 1.13 2007/08/03 16:48:50 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2007  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n\n/* \n * An example Togl program using color-index mode.\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n\n/* Our color indexes: */\nstatic unsigned long black, red, green, blue;\n\n/* Rotation angle */\nstatic float Angle = 0;\n\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* allocate color indexes */\n    black = Togl_AllocColor(togl, 0, 0, 0);\n    red = Togl_AllocColor(togl, 1, 0, 0);\n    green = Togl_AllocColor(togl, 0, 1, 0);\n    blue = Togl_AllocColor(togl, 0, 0, 1);\n\n    /* If we were using a private read/write colormap we'd setup our color\n     * table with something like this: */\n    /* \n     * black = 1; Togl_SetColor( togl, black, 0, 0, 0 ); red = 2;\n     * Togl_SetColor( togl, red, 1, 0, 0 ); green = 3; Togl_SetColor(\n     * togl, green, 0, 1, 0 ); blue = 4; Togl_SetColor( togl, blue, 0,\n     * 0, 1 ); */\n\n    glShadeModel(GL_FLAT);\n    glDisable(GL_DITHER);\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    float   aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (float) width / (float) height;\n    glViewport(0, 0, width, height);\n\n    /* Set up projection transform */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glOrtho(-aspect, aspect, -1, 1, -1, 1);\n\n    /* Change back to model view transform for rendering */\n    glMatrixMode(GL_MODELVIEW);\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    glClearIndex((float) black);\n    glClear(GL_COLOR_BUFFER_BIT);\n\n    glPushMatrix();\n    glTranslatef(0.3f, -0.3f, 0);\n    glRotatef(Angle, 0, 0, 1);\n    glIndexi(red);\n    glBegin(GL_TRIANGLES);\n    glVertex2f(-0.5f, -0.3f);\n    glVertex2f(0.5f, -0.3f);\n    glVertex2f(0, 0.6f);\n    glEnd();\n    glPopMatrix();\n\n    glPushMatrix();\n    glRotatef(Angle, 0, 0, 1);\n    glIndexi(green);\n    glBegin(GL_TRIANGLES);\n    glVertex2f(-0.5f, -0.3f);\n    glVertex2f(0.5f, -0.3f);\n    glVertex2f(0, 0.6f);\n    glEnd();\n    glPopMatrix();\n\n    glPushMatrix();\n    glTranslatef(-0.3f, 0.3f, 0);\n    glRotatef(Angle, 0, 0, 1);\n    glIndexi(blue);\n    glBegin(GL_TRIANGLES);\n    glVertex2f(-0.5f, -0.3f);\n    glVertex2f(0.5f, -0.3f);\n    glVertex2f(0, 0.6f);\n    glEnd();\n    glPopMatrix();\n\n    glFlush();\n    Togl_SwapBuffers(togl);\n\n    return TCL_OK;\n}\n\n\nstatic int\ntimer_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Angle += 5.0;\n    Togl_PostRedisplay(togl);\n\n    return TCL_OK;\n}\n\n\nEXTERN int\nIndex_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"::index::create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"::index::display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"::index::reshape_cb\", reshape_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"::index::timer_cb\", timer_cb, NULL, NULL);\n\n    /* \n     * Make a new Togl widget command so the Tcl code can set a C variable.\n     */\n    /* NONE */\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/index.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: index.tcl,v 1.8 2007/08/03 16:48:50 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# A Tk/OpenGL widget demo using color-index mode.\n\npackage provide index 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/index[info sharedlibextension]\n\n# create ::index namespace\nnamespace eval ::index {\n}\n\nproc ::index::setup {} {\n    wm title . \"Color index demo\"\n\n    togl .win -width 200 -height 200 -rgba false -double true -privatecmap false -time 10 -timer ::index::timer_cb -create ::index::create_cb -reshape ::index::reshape_cb -display ::index::display_cb\n    button .photo -text \"Take Photo\" -command ::index::take_photo\n    button .btn -text Quit -command exit\n\n    pack .win -expand true -fill both\n    pack .photo -expand true -fill both\n    pack .btn -expand true -fill both\n}\n\nproc ::index::take_photo {} {\n\timage create photo img\n\t.win takephoto img\n\timg write image.ppm -format ppm\n}\n\n\n# Execution starts here!\nif { [info script] == $argv0 } {\n\t::index::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/multisample.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: multisample.tcl,v 1.3 2009/03/12 23:59:35 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# An Tk/OpenGL widget demo with two windows, one aliased and the\n# other multisampled.  Reuse C code from double buffering demo.\n\npackage provide multisample 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/double[info sharedlibextension]\n\n# create ::multisample namespace\nnamespace eval ::multisample {\n}\n\nproc multisample::setup {} {\n    wm title . \"Multisample vs Aliased\"\n\n    # create first Togl widget\n    togl .o1 -width 200 -height 200 -rgba true -double true -depth true -create double::create_cb -display double::display_cb -reshape double::reshape_cb -multisample false -ident Aliased\n\n    # create second Togl widget, share display lists with first widget\n    togl .o2 -width 200 -height 200 -rgba true -double true -depth true -create double::create_cb -display double::display_cb -reshape double::reshape_cb -multisample true -ident Multisampled -sharelist Aliased\n\n    scale .sx -label {X Axis} -from 0 -to 360 -command {::multisample::setAngle x} -orient horizontal\n    scale .sy -label {Y Axis} -from 0 -to 360 -command {::multisample::setAngle y} -orient horizontal\n    button .btn -text Quit -command exit\n\n    bind .o1 <B1-Motion> {\n\t::multisample::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    bind .o2 <B1-Motion> {\n\t::multisample::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    grid rowconfigure . 0 -weight 1\n    grid columnconfigure . 0 -weight 1 -uniform same\n    grid columnconfigure . 1 -weight 1 -uniform same\n    grid .o1 -row 0 -column 0 -sticky nesw -padx 3 -pady 3\n    grid .o2 -row 0 -column 1 -sticky nesw -padx 3 -pady 3\n    #grid .l1 -row 1 -column 0 -sticky ew -padx 3 -pady 3\n    #grid .l2 -row 1 -column 1 -sticky ew -padx 3 -pady 3\n    grid .sx -row 2 -column 0 -columnspan 2 -sticky ew\n    grid .sy -row 3 -column 0 -columnspan 2 -sticky ew\n    grid .btn -row 4 -column 0 -columnspan 2 -sticky ew\n}\n\n\n\n# This is called when mouse button 1 is pressed and moved in either of\n# the OpenGL windows.\nproc multisample::motion_event { width height x y } {\n    .sx set [double::setXrot [expr 360.0 * $y / $height]]\n    .sy set [double::setYrot [expr 360.0 * ($width - $x) / $width]]\n\n    .o1 postredisplay\n    .o2 postredisplay\n}\n\n# This is called when a slider is changed.\nproc multisample::setAngle {axis value} {\n    global xAngle yAngle zAngle\n\n    switch -exact $axis {\n\tx {double::setXrot $value\n\t   double::setXrot $value}\n\ty {double::setYrot $value\n\t   double::setYrot $value}\n    }\n\n    .o1 postredisplay\n    .o2 postredisplay\n}\n\n# Execution starts here!\nif { [info script] == $argv0 } {\n\t::multisample::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/overlay.c",
    "content": "/* $Id: overlay.c,v 1.10 2007/08/03 16:48:50 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2007  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n\n/* \n * An example Togl program using an overlay.\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n\n/* Overlay color indexes: */\nstatic unsigned long Red, Green;\n\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* allocate overlay color indexes */\n    Red = Togl_AllocColorOverlay(togl, 1, 0, 0);\n    Green = Togl_AllocColorOverlay(togl, 0, 1, 0);\n\n    /* in this demo we always show the overlay */\n    if (Togl_ExistsOverlay(togl)) {\n        Togl_ShowOverlay(togl);\n        printf(\"Red and green lines are in the overlay\\n\");\n    } else {\n        printf(\"Sorry, this display doesn't support overlays\\n\");\n    }\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    float   aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (float) width / (float) height;\n\n    /* Set up viewing for normal plane's context */\n    glViewport(0, 0, width, height);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glOrtho(-aspect, aspect, -1, 1, -1, 1);\n    glMatrixMode(GL_MODELVIEW);\n\n    /* Set up viewing for overlay plane's context */\n    if (Togl_ExistsOverlay(togl)) {\n        Togl_UseLayer(togl, TOGL_OVERLAY);\n        glViewport(0, 0, width, height);\n        glMatrixMode(GL_PROJECTION);\n        glLoadIdentity();\n        glOrtho(-1, 1, -1, 1, -1, 1);\n        glMatrixMode(GL_MODELVIEW);\n        Togl_UseLayer(togl, TOGL_NORMAL);\n    }\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget overlay display callback.  This is called by Tcl/Tk when the\n * overlay has to be redrawn.\n */\nstatic int\noverlay_display_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    glClear(GL_COLOR_BUFFER_BIT);\n\n    glIndexi(Red);\n    glBegin(GL_LINES);\n    glVertex2f(-1, -1);\n    glVertex2f(1, 1);\n    glVertex2f(-1, 1);\n    glVertex2f(1, -1);\n    glEnd();\n\n    glIndexi(Green);\n    glBegin(GL_LINE_LOOP);\n    glVertex2f(-0.5f, -0.5f);\n    glVertex2f(0.5f, -0.5f);\n    glVertex2f(0.5f, 0.5f);\n    glVertex2f(-0.5f, 0.5f);\n    glEnd();\n    glFlush();\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    glClear(GL_COLOR_BUFFER_BIT);\n\n    glLoadIdentity();\n\n    glBegin(GL_TRIANGLES);\n\n    glColor3f(1, 0, 1);\n    glVertex2f(-0.5f, -0.3f);\n    glVertex2f(0.5f, -0.3f);\n    glVertex2f(0, 0.6f);\n\n    glColor3f(1, 1, 0);\n    glVertex2f(-0.5f + 0.2f, -0.3f - 0.2f);\n    glVertex2f(0.5f + 0.2f, -0.3f - 0.2f);\n    glVertex2f(0 + 0.2f, 0.6f - 0.2f);\n\n    glColor3f(0, 1, 1);\n    glVertex2f(-0.5f + 0.4f, -0.3f - 0.4f);\n    glVertex2f(0.5f + 0.4f, -0.3f - 0.4f);\n    glVertex2f(0 + 0.4f, 0.6f - 0.4f);\n\n    glEnd();\n\n    glFlush();\n    return TCL_OK;\n}\n\n\n/* \n * Called by Tcl to let me initialize the modules (Togl) I will need.\n */\nEXTERN int\nOverlay_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape_cb\", reshape_cb, NULL, NULL);\n\n    Tcl_CreateObjCommand(interp, \"overlay_display_cb\", overlay_display_cb, NULL,\n            NULL);\n\n    /* \n     * Make a new Togl widget command so the Tcl code can set a C variable.\n     */\n    /* NONE */\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/overlay.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: overlay.tcl,v 1.7 2007/08/03 16:48:50 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# A Tk/OpenGL widget demo using an overlay.\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/overlay[info sharedlibextension]\n\nproc setup {} {\n    wm title . \"Overlay demo\"\n\n    togl .win -width 200 -height 200 -rgba true -double false -overlay true -create create_cb -reshape reshape_cb -display display_cb -overlaydisplay overlay_display_cb\n    button .btn -text Quit -command exit\n\n    pack .win -expand true -fill both\n    pack .btn -expand true -fill both\n}\n\n\n# Execution starts here!\n# Execution starts here!\nif { [info script] == $argv0 } {\n\tsetup\n}\n"
  },
  {
    "path": "ng/Togl2.1/pbuffer.c",
    "content": "/* $Id: pbuffer.c,v 1.2 2009/02/05 06:57:10 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2007  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n#undef PBUFFER_DEBUG\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <math.h>\n#if defined(TOGL_AGL)\n#  include <OpenGL/glu.h>\n#  include <AGL/agl.h>\n#elif defined(TOGL_NSOPENGL)\n#  include <OpenGL/glu.h>\n#  include <OpenGL/OpenGL.h>\n#else\n#  include <GL/glu.h>\n#endif\n#include <GL/glext.h>           /* OpenGL 1.4 GL_GENERATE_MIPMAP */\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\nstatic double xAngle = 0, yAngle = 0, zAngle = 0;\nstatic GLdouble CornerX, CornerY, CornerZ;      /* where to print strings */\nstatic GLuint texture;\nstatic Togl *output;\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n    double  version;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    version = atof((const char *) glGetString(GL_VERSION));\n    if (version < 1.4) {\n        Tcl_SetResult(interp, \"need OpenGL 1.4 or later\", TCL_STATIC);\n        return TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    double  aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (double) width / (double) height;\n\n    glViewport(0, 0, width, height);\n\n    /* Set up projection transform */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glFrustum(-aspect, aspect, -1, 1, 1, 10);\n\n    CornerX = -aspect;\n    CornerY = -1;\n    CornerZ = -1.1;\n\n    /* Change back to model view transform for rendering */\n    glMatrixMode(GL_MODELVIEW);\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape2_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    double  aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (double) width / (double) height;\n\n    glViewport(0, 0, width, height);\n\n    /* Set up projection transform */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glOrtho(-aspect, aspect, -1, 1, -1, 1);\n\n    /* Change back to model view transform for rendering */\n    glMatrixMode(GL_MODELVIEW);\n    glLoadIdentity();\n\n    return TCL_OK;\n}\n\n\nstatic void\ndraw_object()\n{\n    static GLuint cubeList = 0;\n\n    glLoadIdentity();           /* Reset modelview matrix to the identity\n                                 * matrix */\n    glTranslatef(0, 0, -3);     /* Move the camera back three units */\n    glRotated(xAngle, 1, 0, 0); /* Rotate by X, Y, and Z angles */\n    glRotated(yAngle, 0, 1, 0);\n    glRotated(zAngle, 0, 0, 1);\n\n    glEnable(GL_DEPTH_TEST);\n\n    if (!cubeList) {\n        cubeList = glGenLists(1);\n        glNewList(cubeList, GL_COMPILE);\n\n        /* Front face */\n        glBegin(GL_QUADS);\n        glColor3f(0, 0.7f, 0.1f);       /* Green */\n        glVertex3f(-1, 1, 1);\n        glVertex3f(1, 1, 1);\n        glVertex3f(1, -1, 1);\n        glVertex3f(-1, -1, 1);\n        /* Back face */\n        glColor3f(0.9f, 1, 0);  /* Yellow */\n        glVertex3f(-1, 1, -1);\n        glVertex3f(1, 1, -1);\n        glVertex3f(1, -1, -1);\n        glVertex3f(-1, -1, -1);\n        /* Top side face */\n        glColor3f(0.2f, 0.2f, 1);       /* Blue */\n        glVertex3f(-1, 1, 1);\n        glVertex3f(1, 1, 1);\n        glVertex3f(1, 1, -1);\n        glVertex3f(-1, 1, -1);\n        /* Bottom side face */\n        glColor3f(0.7f, 0, 0.1f);       /* Red */\n        glVertex3f(-1, -1, 1);\n        glVertex3f(1, -1, 1);\n        glVertex3f(1, -1, -1);\n        glVertex3f(-1, -1, -1);\n        glEnd();\n\n        glEndList();\n\n    }\n    glCallList(cubeList);\n}\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK)\n        return TCL_ERROR;\n\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    draw_object();\n\n#ifdef PBUFFER_DEBUG\n    {\n        Tk_PhotoHandle photo;\n\n        /* first tcl: image create photo test */\n        photo = Tk_FindPhoto(interp, \"test2\");\n        if (photo == NULL) {\n            fprintf(stderr, \"missing tk photo object test2\\n\");\n        } else {\n            Togl_TakePhoto(togl, photo);\n            Tcl_Eval(interp, \"test2 write test2.ppm -format ppm\");\n        }\n    }\n#endif\n    Togl_SwapBuffers(togl);\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay2_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK)\n        return TCL_ERROR;\n\n    glClear(GL_COLOR_BUFFER_BIT);\n\n    if (texture) {\n        glEnable(GL_TEXTURE_2D);\n        glBindTexture(GL_TEXTURE_2D, texture);\n        glBegin(GL_QUADS);\n        glTexCoord2i(0, 0);\n        glVertex2i(-1, -1);\n        glTexCoord2i(1, 0);\n        glVertex2i(1, -1);\n        glTexCoord2i(1, 1);\n        glVertex2i(1, 1);\n        glTexCoord2i(0, 1);\n        glVertex2i(-1, 1);\n        glEnd();\n        glBindTexture(GL_TEXTURE_2D, 0);\n    }\n\n    Togl_SwapBuffers(togl);\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\npbuffer_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n    int     width;\n    int     height;\n    GLenum  error;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK)\n        return TCL_ERROR;\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n\n    if (texture == 0) {\n        glGenTextures(1, &texture);\n        glBindTexture(GL_TEXTURE_2D, texture);\n        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n#if !defined(TOGL_AGL) && !defined(TOGL_NSOPENGL)\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,\n                GL_LINEAR_MIPMAP_LINEAR);\n#else\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n#endif\n        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,\n                GL_BYTE, NULL);\n        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);\n        glBindTexture(GL_TEXTURE_2D, 0);\n        error = glGetError();\n        if (error != GL_NO_ERROR) {\n            fprintf(stderr, \"texture init: %s\\n\", gluErrorString(error));\n        }\n#if 0 && defined(TOGL_AGL)\n        AGLContext ctx = aglGetCurrentContext();\n        AGLPbuffer pbuf;\n        GLint   face, level, screen;\n        GLenum  err;\n\n        aglGetPBuffer(ctx, &pbuf, &face, &level, &screen);\n        err = aglGetError();\n        if (err != AGL_NO_ERROR)\n            fprintf(stderr, \"getPBuffer: %s\\n\", aglErrorString(err));\n        aglTexImagePBuffer(ctx, pbuf, GL_FRONT);\n        err = aglGetError();\n        if (err != AGL_NO_ERROR)\n            fprintf(stderr, \"teximagepbuffer: %s\\n\", aglErrorString(err));\n#endif\n    }\n\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    draw_object();\n\n#if 1 || !defined(TOGL_AGL)\n    glBindTexture(GL_TEXTURE_2D, texture);\n    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);\n    glBindTexture(GL_TEXTURE_2D, 0);\n    error = glGetError();\n    if (error != GL_NO_ERROR) {\n        fprintf(stderr, \"after tex copy: %s\\n\", gluErrorString(error));\n    }\n#endif\n#ifdef PBUFFER_DEBUG\n    {\n        Tk_PhotoHandle photo;\n\n        /* first tcl: image create photo test */\n        photo = Tk_FindPhoto(interp, \"test\");\n        Togl_TakePhoto(togl, photo);\n        Tcl_Eval(interp, \"test write test.ppm -format ppm\");\n    }\n#endif\n    Togl_SwapBuffers(togl);\n    if (output)\n        Togl_PostRedisplay(output);\n\n    return TCL_OK;\n}\n\n\nstatic int\nsetXrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"angle\");\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[1], &xAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* printf( \"before %f \", xAngle ); */\n\n    xAngle = fmod(xAngle, 360.0);\n    if (xAngle < 0.0)\n        xAngle += 360.0;\n\n    /* printf( \"after %f \\n\", xAngle ); */\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[1]);\n    return TCL_OK;\n}\n\n\nstatic int\nsetYrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"angle\");\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[1], &yAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    yAngle = fmod(yAngle, 360.0);\n    if (yAngle < 0.0)\n        yAngle += 360.0;\n\n    /* Let result equal value */\n    Tcl_SetObjResult(interp, objv[1]);\n    return TCL_OK;\n}\n\nstatic int\nsetOutput_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &output) != TCL_OK)\n        return TCL_ERROR;\n\n    return TCL_OK;\n}\n\n/* \n * Called by Tcl to let me initialize the modules (Togl) I will need.\n */\nEXTERN int\nPbuffer_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n#ifdef PBUFFER_DEBUG\n            || Tk_InitStubs(interp, \"8.1\", 0) == NULL\n#endif\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"display2_cb\", display2_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"pbuffer_cb\", pbuffer_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape_cb\", reshape_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape2_cb\", reshape2_cb, NULL, NULL);\n\n    /* \n     * Make a new Togl widget command so the Tcl code can set a C variable.\n     */\n\n    Tcl_CreateObjCommand(interp, \"setXrot\", setXrot_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"setYrot\", setYrot_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"setOutput\", setOutput_cb, NULL, NULL);\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/pbuffer.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: pbuffer.tcl,v 1.1 2009/01/29 22:45:46 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# An Tk/OpenGL widget demo with two double-buffered OpenGL windows.\n# The first shows the aliased object, the second show the results of\n# rendering the same object in a higher resolution Pbuffer and using\n# texture mapping to antialias it.\n\npackage provide pbuffer 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/pbuffer[info sharedlibextension]\n\n# create ::pbuffer namespace\nnamespace eval ::pbuffer {\n}\n\nproc pbuffer::setup {} {\n    wm title . \"Pbuffer test\"\n\n#debug\n    image create photo test\n    image create photo test2\n#end debug\n\n    # create first Togl widget\n    togl .o1 -width 300 -height 300 -rgba true -double true -depth true -ident main -create create_cb -reshape reshape_cb -display display_cb\n    label .l1 -text \"RGB, Z, double\"\n\n    # create second Togl widget, share display lists with first widget, no depth\n    togl .o2 -width 300 -height 300 -rgba true -double true -sharelist main -reshape reshape2_cb -display display2_cb -ident second\n    setOutput .o2\n    label .l2 -text \"RGB from pbuffer texture\"\n\n    # create off-screen pbuffer, share display lists with other widgets\n    # must power of 2 squared in size\n    togl .pbuf -width 2048 -height 2048 -rgba true -depth true -sharelist main -pbuffer 1 -reshape reshape_cb -display pbuffer_cb -ident pbuffer\n\n    scale .sx -label {X Axis} -from 0 -to 360 -command {::pbuffer::setAngle x} -orient horizontal\n    scale .sy -label {Y Axis} -from 0 -to 360 -command {::pbuffer::setAngle y} -orient horizontal\n    button .btn -text Quit -command exit\n\n    bind .o1 <B1-Motion> {\n\t::pbuffer::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    bind .o2 <B1-Motion> {\n\t::pbuffer::motion_event [lindex [%W config -width] 4] \\\n\t\t     [lindex [%W config -height] 4] \\\n\t\t     %x %y\n    }\n\n    grid rowconfigure . 0 -weight 1\n    grid columnconfigure . 0 -weight 1 -uniform same\n    grid columnconfigure . 1 -weight 1 -uniform same\n    grid .o1 -row 0 -column 0 -sticky nesw -padx 3 -pady 3\n    grid .o2 -row 0 -column 1 -sticky nesw -padx 3 -pady 3\n    grid .l1 -row 1 -column 0 -sticky ew -padx 3 -pady 3\n    grid .l2 -row 1 -column 1 -sticky ew -padx 3 -pady 3\n    grid .sx -row 2 -column 0 -columnspan 2 -sticky ew\n    grid .sy -row 3 -column 0 -columnspan 2 -sticky ew\n    grid .btn -row 4 -column 0 -columnspan 2 -sticky ew\n}\n\n\nproc pbuffer::display { } {\n\tpbuffer_cb .pbuf\n\t.o2 postredisplay\n}\n\n\n# This is called when mouse button 1 is pressed and moved in either of\n# the OpenGL windows.\nproc pbuffer::motion_event { width height x y } {\n    .sx set [setXrot [expr 360.0 * $y / $height]]\n    .sy set [setYrot [expr 360.0 * ($width - $x) / $width]]\n\n    .o1 postredisplay\n    .pbuf postredisplay\n}\n\n# This is called when a slider is changed.\nproc pbuffer::setAngle {axis value} {\n    global xAngle yAngle zAngle\n\n    switch -exact $axis {\n\tx {setXrot $value\n\t   setXrot $value}\n\ty {setYrot $value\n\t   setYrot $value}\n    }\n\n    .o1 postredisplay\n    .pbuf postredisplay\n}\n\n# Execution starts here!\nif { [info script] == $argv0 } {\n\t::pbuffer::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/pkgIndex.tcl.in",
    "content": "#\n# Tcl package index file\n#\npackage ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \\\n    [list load [file join $dir @PKG_LIB_FILE@]]\n"
  },
  {
    "path": "ng/Togl2.1/stereo.c",
    "content": "/* $Id: stereo.c,v 1.14 2009/02/07 07:04:50 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n\nstatic Tcl_Obj *toglFont;\nstatic double xAngle = 0, yAngle = 0, zAngle = 0;\nstatic GLfloat CornerX, CornerY, CornerZ;       /* where to print strings */\nstatic double coord_scale = 1;\n\n\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    int     width;\n    int     height;\n    float   aspect;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n    aspect = (float) width / (float) height;\n\n    glViewport(0, 0, width, height);\n\n    /* Set up projection transform */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glFrustum(-aspect, aspect, -1, 1, 1, 10);\n\n    CornerX = -aspect;\n    CornerY = -1;\n    CornerZ = -1.1f;\n\n    /* Change back to model view transform for rendering */\n    glMatrixMode(GL_MODELVIEW);\n    return TCL_OK;\n}\n\n\nstatic void\ndraw_eye(Togl *togl)\n{\n    static GLuint cubeList = 0;\n\n    Togl_Clear(togl, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    Togl_Frustum(togl, -1, 1, -1, 1, 1, 10);\n    glMatrixMode(GL_MODELVIEW);\n\n    if (!cubeList) {\n        cubeList = glGenLists(1);\n        glNewList(cubeList, GL_COMPILE);\n\n\t/* Front face */\n\tglBegin(GL_QUADS);\n\tglColor3f(0.4f, 0.8f, 0.4f);        /* Green-ish */\n\tglVertex3f(-1, 1, 1);\n\tglVertex3f(1, 1, 1);\n\tglVertex3f(1, -1, 1);\n\tglVertex3f(-1, -1, 1);\n\t/* Back face */\n\tglColor3f(0.8f, 0.8f, 0.4f);        /* Yellow-ish */\n\tglVertex3f(-1, 1, -1);\n\tglVertex3f(1, 1, -1);\n\tglVertex3f(1, -1, -1);\n\tglVertex3f(-1, -1, -1);\n\t/* Top side face */\n\tglColor3f(0.4f, 0.4f, 0.8f);        /* Blue-ish */\n\tglVertex3f(-1, 1, 1);\n\tglVertex3f(1, 1, 1);\n\tglVertex3f(1, 1, -1);\n\tglVertex3f(-1, 1, -1);\n\t/* Bottom side face */\n\tglColor3f(0.8f, 0.4f, 0.4f);        /* Red-ish */\n\tglVertex3f(-1, -1, 1);\n\tglVertex3f(1, -1, 1);\n\tglVertex3f(1, -1, -1);\n\tglVertex3f(-1, -1, -1);\n\tglEnd();\n\n        glEndList();\n    }\n    glCallList(cubeList);\n}\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* setup modelview matrix */\n    glLoadIdentity();           /* Reset modelview matrix to the identity\n                                 * matrix */\n    glTranslatef(0, 0, -3.0);   /* Move the camera back three units */\n    glScaled(coord_scale, coord_scale, coord_scale);    /* Zoom in and out */\n    glRotated(xAngle, 1, 0, 0); /* Rotate by X, Y, and Z angles */\n    glRotated(yAngle, 0, 1, 0);\n    glRotated(zAngle, 0, 0, 1);\n\n    glEnable(GL_DEPTH_TEST);\n\n    if (Togl_NumEyes(togl) == 1) {\n        /* single eye */\n        Togl_DrawBuffer(togl, GL_BACK);\n        draw_eye(togl);\n    } else {\n        /* stereo left eye */\n        Togl_DrawBuffer(togl, GL_BACK_LEFT);\n        draw_eye(togl);\n\n        /* stereo right eye */\n        Togl_DrawBuffer(togl, GL_BACK_RIGHT);\n        draw_eye(togl);\n    }\n\n    glDisable(GL_DEPTH_TEST);\n    glLoadIdentity();\n    glColor3f(1, 1, 1);\n    glRasterPos3f(CornerX, CornerY, CornerZ);\n    Togl_SwapBuffers(togl);\n    return TCL_OK;\n}\n\n\nstatic int\nsetXrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName angle\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &xAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    /* printf( \"before %f \", xAngle ); */\n\n    if (xAngle < 0) {\n        xAngle += 360;\n    } else if (xAngle > 360) {\n        xAngle -= 360;\n    }\n\n    /* printf( \"after %f \\n\", xAngle ); */\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nstatic int\nsetYrot_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName angle\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &yAngle) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (yAngle < 0) {\n        yAngle += 360;\n    } else if (yAngle > 360) {\n        yAngle -= 360;\n    }\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nint\ngetXrot_cb(ClientData clientData, Tcl_Interp *interp,\n        int argc, CONST84 char *argv[])\n{\n    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(xAngle));\n    return TCL_OK;\n}\n\n\nint\ngetYrot_cb(ClientData clientData, Tcl_Interp *interp,\n        int argc, CONST84 char *argv[])\n{\n    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(yAngle));\n    return TCL_OK;\n}\n\n\nstatic int\ncoord_scale_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName value\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &coord_scale) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nEXTERN int\nStereo_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape_cb\", reshape_cb, NULL, NULL);\n\n    Tcl_CreateObjCommand(interp, \"setXrot\", setXrot_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"setYrot\", setYrot_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"coord_scale\", coord_scale_cb, NULL, NULL);\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n\n    Tcl_CreateCommand(interp, \"getXrot\", getXrot_cb, NULL, NULL);\n    Tcl_CreateCommand(interp, \"getYrot\", getYrot_cb, NULL, NULL);\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/stereo.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: stereo.tcl,v 1.13 2009/03/31 23:21:13 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2009  Greg Couch\n# See the LICENSE file for copyright details.\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/stereo[info sharedlibextension]\n\n# create ::stereo namespace\nnamespace eval ::stereo {\n}\n\nvariable stereo::mode none\nproc stereo::setup {} {\n\tgrid rowconfigure . 0 -weight 1 -minsize 200p\n\tgrid columnconfigure . 1 -weight 1 -minsize 200p\n\tlabelframe .c -text \"Stereo mode:\"\n\tgrid .c -padx 2 -pady 2 -ipadx 2 -ipady 1\n\tforeach {b} {none native sgioldstyle anaglyph cross-eye wall-eye DTI \"row interleaved\" \"left eye\" \"right eye\" } {\n\t\tset name [string map {- _ \" \" _} $b]\n\t\tradiobutton .c.b$name -text \"$b\" -command \"::stereo::makeGraphics {$b}\" -variable stereo::mode -value \"$b\"\n\t\tpack .c.b$name -padx 2 -pady 1 -anchor w\n\t}\n\tscale .sx -label {X Axis} -from 0 -to 360 -command {::stereo::setAngle x} -orient horizontal\n\tgrid .sx -columnspan 2 -sticky ew\n\tscale .sy -label {Y Axis} -from 0 -to 360 -command {::stereo::setAngle y} -orient horizontal\n\tgrid .sy -columnspan 2 -sticky ew\n\tif {[string first IRIX $::tcl_platform(os)] != -1} {\n\t\tlabel .irix -justify left -wraplength 250p -text \"Use /usr/gfx/setmon or /usr/bin/X11/xsetmon to change video mode for native stereo (eg., 1024x768_120s) or sgioldstyle stereo (eg., str_bot) and back.\"\n\t\tgrid .irix -sticky new -columnspan 2\n\t}\n\tbutton .quit -text Close -command exit\n\tgrid .quit -sticky se -columnspan 2 -padx 2 -pady 2\n\tframe .f -relief groove -borderwidth 2 -bg black\n\tgrid .f -row 0 -column 1 -sticky news\n\tbind . <Key-Escape> {exit}\n\tlabel .f.error -wraplength 100p -bg black -fg white\n\t::stereo::makeGraphics $stereo::mode\n}\n\nset stereo::count 0\nset stereo::gwidget \"\"\nproc stereo::makeGraphics {mode} {\n\tincr stereo::count\n\tset name .f.gr$stereo::count\n\tset width 200\n\tset height 200\n\tif { [catch { togl $name -width $width -height $height -rgba true -stereo \"$mode\" -double true -depth true -sharelist main -create create_cb -display display_cb -reshape reshape_cb -eyeseparation 0.05 -convergence 2.0 -stencil true } error] } {\n\t\tpack forget $stereo::gwidget\n\t\t.f.error configure -text \"$error\\n\\nMake another choice from the stereo modes on the left.\"\n\t\tpack .f.error -expand 1 -fill both\n\t} else {\n\t\tpack forget .f.error\n\t\t$name configure -ident main\n\t\tif { \"$stereo::gwidget\" != \"\" } {\n\t\t\tdestroy $stereo::gwidget\n\t\t}\n\t\tset stereo::gwidget $name\n\t\tpack $name -expand 1 -fill both\n\t\tbind $name <B1-Motion> {\n\t\t\t::stereo::motion_event %W \\\n\t\t\t\t[lindex [%W config -width] 4] \\\n\t\t\t\t[lindex [%W config -height] 4] %x %y\n\t\t}\n\t}\n}\n\n# This is called when mouse button 1 is pressed and moved\nproc stereo::motion_event { widget width height x y } {\n    setXrot $widget [expr 360.0 * $y / $height]\n    setYrot $widget [expr 360.0 * ($width - $x) / $width]\n\n#    .sx set [expr 360.0 * $y / $height]\n#    .sy set [expr 360.0 * ($width - $x) / $width]\n\n    .sx set [getXrot]\n    .sy set [getYrot]\n}\n\n# This is called when a slider is changed.\nproc stereo::setAngle {axis value} {\n    # catch because .f.gr might be a label instead of a Togl widget\n    catch {\n\t    switch -exact $axis {\n\t\tx {setXrot $stereo::gwidget $value}\n\t\ty {setYrot $stereo::gwidget $value}\n\t    }\n    }\n}\n\nif { [info script] == $argv0 } {\n\tif { $argc == 1 } {\n\t\tset stereo::mode [lindex $argv 0]\n\t}\n\t::stereo::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/tclconfig/install-sh",
    "content": "#!/bin/sh\n\n#\n# install - install a program, script, or datafile\n# This comes from X11R5; it is not part of GNU.\n#\n# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.\n#\n\n\n# set DOITPROG to echo to test this script\n\n# Don't use :- since 4.3BSD and earlier shells don't like it.\ndoit=\"${DOITPROG-}\"\n\n\n# put in absolute paths if you don't have them in your path; or use env. vars.\n\nmvprog=\"${MVPROG-mv}\"\ncpprog=\"${CPPROG-cp}\"\nchmodprog=\"${CHMODPROG-chmod}\"\nchownprog=\"${CHOWNPROG-chown}\"\nchgrpprog=\"${CHGRPPROG-chgrp}\"\nstripprog=\"${STRIPPROG-strip}\"\nrmprog=\"${RMPROG-rm}\"\n\ninstcmd=\"$mvprog\"\nchmodcmd=\"\"\nchowncmd=\"\"\nchgrpcmd=\"\"\nstripcmd=\"\"\nrmcmd=\"$rmprog -f\"\nmvcmd=\"$mvprog\"\nsrc=\"\"\ndst=\"\"\n\nwhile [ x\"$1\" != x ]; do\n    case $1 in\n\t-c) instcmd=\"$cpprog\"\n\t    shift\n\t    continue;;\n\n\t-m) chmodcmd=\"$chmodprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-o) chowncmd=\"$chownprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-g) chgrpcmd=\"$chgrpprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-s) stripcmd=\"$stripprog\"\n\t    shift\n\t    continue;;\n\n\t*)  if [ x\"$src\" = x ]\n\t    then\n\t\tsrc=$1\n\t    else\n\t\tdst=$1\n\t    fi\n\t    shift\n\t    continue;;\n    esac\ndone\n\nif [ x\"$src\" = x ]\nthen\n\techo \"install:  no input file specified\"\n\texit 1\nfi\n\nif [ x\"$dst\" = x ]\nthen\n\techo \"install:  no destination specified\"\n\texit 1\nfi\n\n\n# If destination is a directory, append the input filename; if your system\n# does not like double slashes in filenames, you may need to add some logic\n\nif [ -d $dst ]\nthen\n\tdst=\"$dst\"/`basename $src`\nfi\n\n# Make a temp file name in the proper directory.\n\ndstdir=`dirname $dst`\ndsttmp=$dstdir/#inst.$$#\n\n# Move or copy the file name to the temp name\n\n$doit $instcmd $src $dsttmp\n\n# and set any options; do chmod last to preserve setuid bits\n\nif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dsttmp; fi\nif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dsttmp; fi\nif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dsttmp; fi\nif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dsttmp; fi\n\n# Now rename the file to the real destination.\n\n$doit $rmcmd $dst\n$doit $mvcmd $dsttmp $dst\n\n\nexit 0\n"
  },
  {
    "path": "ng/Togl2.1/tclconfig/tcl.m4",
    "content": "# tcl.m4 --\n#\n#\tThis file provides a set of autoconf macros to help TEA-enable\n#\ta Tcl extension.\n#\n# Copyright (c) 1999-2000 Ajuba Solutions.\n# Copyright (c) 2002-2005 ActiveState Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n# RCS: @(#) $Id: tcl.m4,v 1.12 2009/01/08 04:40:39 gregcouch Exp $\n\nAC_PREREQ(2.57)\n\ndnl TEA extensions pass us the version of TEA they think they\ndnl are compatible with (must be set in TEA_INIT below)\ndnl TEA_VERSION=\"3.7\"\n\n# Possible values for key variables defined:\n#\n# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')\n# TEA_PLATFORM        - windows unix\n#\n\n#------------------------------------------------------------------------\n# TEA_PATH_TCLCONFIG --\n#\n#\tLocate the tclConfig.sh file and perform a sanity check on\n#\tthe Tcl compile flags\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tcl=...\n#\n#\tDefines the following vars:\n#\t\tTCL_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tclConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PATH_TCLCONFIG], [\n    dnl TEA specific: Make sure we are initialized\n    AC_REQUIRE([TEA_INIT])\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\tAC_ARG_WITH(tcl,\n\t    AC_HELP_STRING([--with-tcl],\n\t\t[directory containing tcl configuration (tclConfig.sh)]),\n\t    with_tclconfig=${withval})\n\tAC_MSG_CHECKING([for Tcl configuration])\n\tAC_CACHE_VAL(ac_cv_c_tclconfig,[\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase ${with_tclconfig} in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f ${with_tclconfig}; then\n\t\t\t    AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])\n\t\t\t    with_tclconfig=`echo ${with_tclconfig} | sed 's!/tclConfig\\.sh$!!'`\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /System/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tcl.framework/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # TEA specific: on Windows, check in common installation locations\n\t    if test \"${TEA_PLATFORM}\" = \"windows\" \\\n\t\t-a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=`(cd $i/unix; pwd)`\n\t\t    break\n\t\tfi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    AC_MSG_ERROR([Can't find Tcl configuration definitions])\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=${ac_cv_c_tclconfig}\n\t    AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_PATH_TKCONFIG --\n#\n#\tLocate the tkConfig.sh file\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tk=...\n#\n#\tDefines the following vars:\n#\t\tTK_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tkConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PATH_TKCONFIG], [\n    #\n    # Ok, lets find the tk configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tk\n    #\n\n    if test x\"${no_tk}\" = x ; then\n\t# we reset no_tk in case something fails here\n\tno_tk=true\n\tAC_ARG_WITH(tk,\n\t    AC_HELP_STRING([--with-tk],\n\t\t[directory containing tk configuration (tkConfig.sh)]),\n\t    with_tkconfig=${withval})\n\tAC_MSG_CHECKING([for Tk configuration])\n\tAC_CACHE_VAL(ac_cv_c_tkconfig,[\n\n\t    # First check to see if --with-tkconfig was specified.\n\t    if test x\"${with_tkconfig}\" != x ; then\n\t\tcase ${with_tkconfig} in\n\t\t    */tkConfig.sh )\n\t\t\tif test -f ${with_tkconfig}; then\n\t\t\t    AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])\n\t\t\t    with_tkconfig=`echo ${with_tkconfig} | sed 's!/tkConfig\\.sh$!!'`\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tkconfig}/tkConfig.sh\" ; then\n\t\t    ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tk library\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tk \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tk \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tk \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /System/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tk.framework/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/Tk.framework; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # TEA specific: on Windows, check in common installation locations\n\t    if test \"${TEA_PLATFORM}\" = \"windows\" \\\n\t\t-a x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tk \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t    TK_BIN_DIR=\"# no Tk configs found\"\n\t    AC_MSG_ERROR([Can't find Tk configuration definitions])\n\telse\n\t    no_tk=\n\t    TK_BIN_DIR=${ac_cv_c_tkconfig}\n\t    AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_LOAD_TCLCONFIG --\n#\n#\tLoad the tclConfig.sh file\n#\n# Arguments:\n#\t\n#\tRequires the following vars to be set:\n#\t\tTCL_BIN_DIR\n#\n# Results:\n#\n#\tSubst the following vars:\n#\t\tTCL_BIN_DIR\n#\t\tTCL_SRC_DIR\n#\t\tTCL_LIB_FILE\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_LOAD_TCLCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n        AC_MSG_RESULT([loading])\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])\n    fi\n\n    # eval is required to do the TCL_DBGX substitution\n    eval \"TCL_LIB_FILE=\\\"${TCL_LIB_FILE}\\\"\"\n    eval \"TCL_STUB_LIB_FILE=\\\"${TCL_STUB_LIB_FILE}\\\"\"\n\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}\n        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}\n        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tcl was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tcl.framework installed in an arbitrary location.\n\tcase ${TCL_DEFS} in\n\t    *TCL_FRAMEWORK*)\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_LIB_FILE}\"; then\n\t\t    for i in \"`cd ${TCL_BIN_DIR}; pwd`\" \\\n\t\t\t     \"`cd ${TCL_BIN_DIR}/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TCL_LIB_FILE}.framework\"; then\n\t\t\t    TCL_LIB_SPEC=\"-F`dirname \"$i\"` -framework ${TCL_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"; then\n\t\t    TCL_STUB_LIB_SPEC=\"-L${TCL_BIN_DIR} ${TCL_STUB_LIB_FLAG}\"\n\t\t    TCL_STUB_LIB_PATH=\"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    # eval is required to do the TCL_DBGX substitution\n    eval \"TCL_LIB_FLAG=\\\"${TCL_LIB_FLAG}\\\"\"\n    eval \"TCL_LIB_SPEC=\\\"${TCL_LIB_SPEC}\\\"\"\n    eval \"TCL_STUB_LIB_FLAG=\\\"${TCL_STUB_LIB_FLAG}\\\"\"\n    eval \"TCL_STUB_LIB_SPEC=\\\"${TCL_STUB_LIB_SPEC}\\\"\"\n\n    AC_SUBST(TCL_VERSION)\n    AC_SUBST(TCL_BIN_DIR)\n    AC_SUBST(TCL_SRC_DIR)\n\n    AC_SUBST(TCL_LIB_FILE)\n    AC_SUBST(TCL_LIB_FLAG)\n    AC_SUBST(TCL_LIB_SPEC)\n\n    AC_SUBST(TCL_STUB_LIB_FILE)\n    AC_SUBST(TCL_STUB_LIB_FLAG)\n    AC_SUBST(TCL_STUB_LIB_SPEC)\n\n    # TEA specific:\n    AC_SUBST(TCL_LIBS)\n    AC_SUBST(TCL_DEFS)\n    AC_SUBST(TCL_EXTRA_CFLAGS)\n    AC_SUBST(TCL_LD_FLAGS)\n    AC_SUBST(TCL_SHLIB_LD_LIBS)\n])\n\n#------------------------------------------------------------------------\n# TEA_LOAD_TKCONFIG --\n#\n#\tLoad the tkConfig.sh file\n#\n# Arguments:\n#\t\n#\tRequires the following vars to be set:\n#\t\tTK_BIN_DIR\n#\n# Results:\n#\n#\tSets the following vars that should be in tkConfig.sh:\n#\t\tTK_BIN_DIR\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_LOAD_TKCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])\n\n    if test -f \"${TK_BIN_DIR}/tkConfig.sh\" ; then\n        AC_MSG_RESULT([loading])\n\t. \"${TK_BIN_DIR}/tkConfig.sh\"\n    else\n        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])\n    fi\n\n    # eval is required to do the TK_DBGX substitution\n    eval \"TK_LIB_FILE=\\\"${TK_LIB_FILE}\\\"\"\n    eval \"TK_STUB_LIB_FILE=\\\"${TK_STUB_LIB_FILE}\\\"\"\n\n    # If the TK_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TK_LIB_SPEC will be set to the value\n    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC\n    # instead of TK_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n        TK_LIB_SPEC=${TK_BUILD_LIB_SPEC}\n        TK_STUB_LIB_SPEC=${TK_BUILD_STUB_LIB_SPEC}\n        TK_STUB_LIB_PATH=${TK_BUILD_STUB_LIB_PATH}\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tk was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tk.framework installed in an arbitrary location.\n\tcase ${TK_DEFS} in\n\t    *TK_FRAMEWORK*)\n\t\tif test -f \"${TK_BIN_DIR}/${TK_LIB_FILE}\"; then\n\t\t    for i in \"`cd ${TK_BIN_DIR}; pwd`\" \\\n\t\t\t     \"`cd ${TK_BIN_DIR}/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TK_LIB_FILE}.framework\"; then\n\t\t\t    TK_LIB_SPEC=\"-F`dirname \"$i\"` -framework ${TK_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"; then\n\t\t    TK_STUB_LIB_SPEC=\"-L${TK_BIN_DIR} ${TK_STUB_LIB_FLAG}\"\n\t\t    TK_STUB_LIB_PATH=\"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    # eval is required to do the TK_DBGX substitution\n    eval \"TK_LIB_FLAG=\\\"${TK_LIB_FLAG}\\\"\"\n    eval \"TK_LIB_SPEC=\\\"${TK_LIB_SPEC}\\\"\"\n    eval \"TK_STUB_LIB_FLAG=\\\"${TK_STUB_LIB_FLAG}\\\"\"\n    eval \"TK_STUB_LIB_SPEC=\\\"${TK_STUB_LIB_SPEC}\\\"\"\n\n    # TEA specific: Ensure windowingsystem is defined\n    if test \"${TEA_PLATFORM}\" = \"unix\" ; then\n\tcase ${TK_DEFS} in\n\t    *MAC_OSX_TK*)\n\t\tAC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])\n\t\tTEA_WINDOWINGSYSTEM=\"aqua\"\n\t\t;;\n\t    *)\n\t\tTEA_WINDOWINGSYSTEM=\"x11\"\n\t\t;;\n\tesac\n    elif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\tTEA_WINDOWINGSYSTEM=\"win32\"\n    fi\n\n    AC_SUBST(TK_VERSION)\n    AC_SUBST(TK_BIN_DIR)\n    AC_SUBST(TK_SRC_DIR)\n\n    AC_SUBST(TK_LIB_FILE)\n    AC_SUBST(TK_LIB_FLAG)\n    AC_SUBST(TK_LIB_SPEC)\n\n    AC_SUBST(TK_STUB_LIB_FILE)\n    AC_SUBST(TK_STUB_LIB_FLAG)\n    AC_SUBST(TK_STUB_LIB_SPEC)\n\n    # TEA specific:\n    AC_SUBST(TK_LIBS)\n    AC_SUBST(TK_XINCLUDES)\n])\n\n#------------------------------------------------------------------------\n# TEA_PROG_TCLSH\n#\tDetermine the fully qualified path name of the tclsh executable\n#\tin the Tcl build directory or the tclsh installed in a bin\n#\tdirectory. This macro will correctly determine the name\n#\tof the tclsh executable even if tclsh has not yet been\n#\tbuilt in the build directory. The tclsh found is always\n#\tassociated with a tclConfig.sh file. This tclsh should be used\n#\tonly for running extension test cases. It should never be\n#\tor generation of files (like pkgIndex.tcl) at build time.\n#\n# Arguments\n#\tnone\n#\n# Results\n#\tSubst's the following values:\n#\t\tTCLSH_PROG\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PROG_TCLSH], [\n    AC_MSG_CHECKING([for tclsh])\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n        # tclConfig.sh is in Tcl build directory\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            TCLSH_PROG=\"${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}\"\n        else\n            TCLSH_PROG=\"${TCL_BIN_DIR}/tclsh\"\n        fi\n    else\n        # tclConfig.sh is in install location\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            TCLSH_PROG=\"tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}\"\n        else\n            TCLSH_PROG=\"tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}\"\n        fi\n        list=\"`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \\\n              `ls -d ${TCL_BIN_DIR}/..     2>/dev/null` \\\n              `ls -d ${TCL_PREFIX}/bin     2>/dev/null`\"\n        for i in $list ; do\n            if test -f \"$i/${TCLSH_PROG}\" ; then\n                REAL_TCL_BIN_DIR=\"`cd \"$i\"; pwd`/\"\n                break\n            fi\n        done\n        TCLSH_PROG=\"${REAL_TCL_BIN_DIR}${TCLSH_PROG}\"\n    fi\n    AC_MSG_RESULT([${TCLSH_PROG}])\n    AC_SUBST(TCLSH_PROG)\n])\n\n#------------------------------------------------------------------------\n# TEA_PROG_WISH\n#\tDetermine the fully qualified path name of the wish executable\n#\tin the Tk build directory or the wish installed in a bin\n#\tdirectory. This macro will correctly determine the name\n#\tof the wish executable even if wish has not yet been\n#\tbuilt in the build directory. The wish found is always\n#\tassociated with a tkConfig.sh file. This wish should be used\n#\tonly for running extension test cases. It should never be\n#\tor generation of files (like pkgIndex.tcl) at build time.\n#\n# Arguments\n#\tnone\n#\n# Results\n#\tSubst's the following values:\n#\t\tWISH_PROG\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PROG_WISH], [\n    AC_MSG_CHECKING([for wish])\n    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n        # tkConfig.sh is in Tk build directory\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            WISH_PROG=\"${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}\"\n        else\n            WISH_PROG=\"${TK_BIN_DIR}/wish\"\n        fi\n    else\n        # tkConfig.sh is in install location\n        if test \"${TEA_PLATFORM}\" = \"windows\"; then\n            WISH_PROG=\"wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}\"\n        else\n            WISH_PROG=\"wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}\"\n        fi\n        list=\"`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \\\n              `ls -d ${TK_BIN_DIR}/..     2>/dev/null` \\\n              `ls -d ${TK_PREFIX}/bin     2>/dev/null`\"\n        for i in $list ; do\n            if test -f \"$i/${WISH_PROG}\" ; then\n                REAL_TK_BIN_DIR=\"`cd \"$i\"; pwd`/\"\n                break\n            fi\n        done\n        WISH_PROG=\"${REAL_TK_BIN_DIR}${WISH_PROG}\"\n    fi\n    AC_MSG_RESULT([${WISH_PROG}])\n    AC_SUBST(WISH_PROG)\n])\n\n#------------------------------------------------------------------------\n# TEA_ENABLE_SHARED --\n#\n#\tAllows the building of shared libraries\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-shared=yes|no\n#\n#\tDefines the following vars:\n#\t\tSTATIC_BUILD\tUsed for building import/export libraries\n#\t\t\t\ton Windows.\n#\n#\tSets the following vars:\n#\t\tSHARED_BUILD\tValue of 1 or 0\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_ENABLE_SHARED], [\n    AC_MSG_CHECKING([how to build libraries])\n    AC_ARG_ENABLE(shared,\n\tAC_HELP_STRING([--enable-shared],\n\t    [build and link with shared libraries (default: on)]),\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n\n    if test \"${enable_shared+set}\" = set; then\n\tenableval=\"$enable_shared\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\tAC_MSG_RESULT([shared])\n\tSHARED_BUILD=1\n    else\n\tAC_MSG_RESULT([static])\n\tSHARED_BUILD=0\n\tAC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])\n    fi\n    AC_SUBST(SHARED_BUILD)\n])\n\n#------------------------------------------------------------------------\n# TEA_ENABLE_THREADS --\n#\n#\tSpecify if thread support should be enabled.  If \"yes\" is specified\n#\tas an arg (optional), threads are enabled by default, \"no\" means\n#\tthreads are disabled.  \"yes\" is the default.\n#\n#\tTCL_THREADS is checked so that if you are compiling an extension\n#\tagainst a threaded core, your extension must be compiled threaded\n#\tas well.\n#\n#\tNote that it is legal to have a thread enabled extension run in a\n#\tthreaded or non-threaded Tcl core, but a non-threaded extension may\n#\tonly run in a non-threaded Tcl core.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-threads\n#\n#\tSets the following vars:\n#\t\tTHREADS_LIBS\tThread library(s)\n#\n#\tDefines the following vars:\n#\t\tTCL_THREADS\n#\t\t_REENTRANT\n#\t\t_THREAD_SAFE\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_ENABLE_THREADS], [\n    AC_ARG_ENABLE(threads,\n\tAC_HELP_STRING([--enable-threads],\n\t    [build with threads]),\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n\n    if test \"${enable_threads+set}\" = set; then\n\tenableval=\"$enable_threads\"\n\ttcl_ok=$enableval\n    else\n\ttcl_ok=yes\n    fi\n\n    if test \"$tcl_ok\" = \"yes\" -o \"${TCL_THREADS}\" = 1; then\n\tTCL_THREADS=1\n\n\tif test \"${TEA_PLATFORM}\" != \"windows\" ; then\n\t    # We are always OK on Windows, so check what this platform wants:\n\n\t    # USE_THREAD_ALLOC tells us to try the special thread-based\n\t    # allocator that significantly reduces lock contention\n\t    AC_DEFINE(USE_THREAD_ALLOC, 1,\n\t\t[Do we want to use the threaded memory allocator?])\n\t    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n\t    if test \"`uname -s`\" = \"SunOS\" ; then\n\t\tAC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,\n\t\t\t[Do we really want to follow the standard? Yes we do!])\n\t    fi\n\t    AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])\n\t    AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)\n\t    if test \"$tcl_ok\" = \"no\"; then\n\t\t# Check a little harder for __pthread_mutex_init in the same\n\t\t# library, as some systems hide it there until pthread.h is\n\t\t# defined.  We could alternatively do an AC_TRY_COMPILE with\n\t\t# pthread.h, but that will work with libpthread really doesn't\n\t\t# exist, like AIX 4.2.  [Bug: 4359]\n\t\tAC_CHECK_LIB(pthread, __pthread_mutex_init,\n\t\t    tcl_ok=yes, tcl_ok=no)\n\t    fi\n\n\t    if test \"$tcl_ok\" = \"yes\"; then\n\t\t# The space is needed\n\t\tTHREADS_LIBS=\" -lpthread\"\n\t    else\n\t\tAC_CHECK_LIB(pthreads, pthread_mutex_init,\n\t\t    tcl_ok=yes, tcl_ok=no)\n\t\tif test \"$tcl_ok\" = \"yes\"; then\n\t\t    # The space is needed\n\t\t    THREADS_LIBS=\" -lpthreads\"\n\t\telse\n\t\t    AC_CHECK_LIB(c, pthread_mutex_init,\n\t\t\ttcl_ok=yes, tcl_ok=no)\n\t\t    if test \"$tcl_ok\" = \"no\"; then\n\t\t\tAC_CHECK_LIB(c_r, pthread_mutex_init,\n\t\t\t    tcl_ok=yes, tcl_ok=no)\n\t\t\tif test \"$tcl_ok\" = \"yes\"; then\n\t\t\t    # The space is needed\n\t\t\t    THREADS_LIBS=\" -pthread\"\n\t\t\telse\n\t\t\t    TCL_THREADS=0\n\t\t\t    AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled])\n\t\t\tfi\n\t\t    fi\n\t\tfi\n\t    fi\n\tfi\n    else\n\tTCL_THREADS=0\n    fi\n    # Do checking message here to not mess up interleaved configure output\n    AC_MSG_CHECKING([for building with threads])\n    if test \"${TCL_THREADS}\" = 1; then\n\tAC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])\n\tAC_MSG_RESULT([yes (default)])\n    else\n\tAC_MSG_RESULT([no])\n    fi\n    # TCL_THREADS sanity checking.  See if our request for building with\n    # threads is the same as the way Tcl was built.  If not, warn the user.\n    case ${TCL_DEFS} in\n\t*THREADS=1*)\n\t    if test \"${TCL_THREADS}\" = \"0\"; then\n\t\tAC_MSG_WARN([\n    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl\n    that IS thread-enabled.  It is recommended to use --enable-threads.])\n\t    fi\n\t    ;;\n\t*)\n\t    if test \"${TCL_THREADS}\" = \"1\"; then\n\t\tAC_MSG_WARN([\n    --enable-threads requested, but building against a Tcl that is NOT\n    thread-enabled.  This is an OK configuration that will also run in\n    a thread-enabled core.])\n\t    fi\n\t    ;;\n    esac\n    AC_SUBST(TCL_THREADS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ENABLE_SYMBOLS --\n#\n#\tSpecify if debugging symbols should be used.\n#\tMemory (TCL_MEM_DEBUG) debugging can also be enabled.\n#\n# Arguments:\n#\tnone\n#\t\n#\tTEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives\n#\tthe value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted.\n#\tRequires the following vars to be set in the Makefile:\n#\t\tCFLAGS_DEFAULT\n#\t\tLDFLAGS_DEFAULT\n#\t\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-symbols\n#\n#\tDefines the following vars:\n#\t\tCFLAGS_DEFAULT\tSets to $(CFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(CFLAGS_OPTIMIZE) if false\n#\t\tLDFLAGS_DEFAULT\tSets to $(LDFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(LDFLAGS_OPTIMIZE) if false\n#\t\tDBGX\t\tFormerly used as debug library extension;\n#\t\t\t\talways blank now.\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_ENABLE_SYMBOLS], [\n    dnl TEA specific: Make sure we are initialized\n    AC_REQUIRE([TEA_CONFIG_CFLAGS])\n    AC_MSG_CHECKING([for build with symbols])\n    AC_ARG_ENABLE(symbols,\n\tAC_HELP_STRING([--enable-symbols],\n\t    [build with debugging symbols (default: off)]),\n\t[tcl_ok=$enableval], [tcl_ok=no])\n    DBGX=\"\"\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT=\"${CFLAGS_OPTIMIZE}\"\n\tLDFLAGS_DEFAULT=\"${LDFLAGS_OPTIMIZE}\"\n\tAC_MSG_RESULT([no])\n    else\n\tCFLAGS_DEFAULT=\"${CFLAGS_DEBUG}\"\n\tLDFLAGS_DEFAULT=\"${LDFLAGS_DEBUG}\"\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    AC_MSG_RESULT([yes (standard debugging)])\n\tfi\n    fi\n    # TEA specific:\n    if test \"${TEA_PLATFORM}\" != \"windows\" ; then\n\tLDFLAGS_DEFAULT=\"${LDFLAGS}\"\n    fi\n    AC_SUBST(CFLAGS_DEFAULT)\n    AC_SUBST(LDFLAGS_DEFAULT)\n    AC_SUBST(TCL_DBGX)\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\tAC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])\n    fi\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    AC_MSG_RESULT([enabled symbols mem debugging])\n\telse\n\t    AC_MSG_RESULT([enabled $tcl_ok debugging])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_ENABLE_LANGINFO --\n#\n#\tAllows use of modern nl_langinfo check for better l10n.\n#\tThis is only relevant for Unix.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-langinfo=yes|no (default is yes)\n#\n#\tDefines the following vars:\n#\t\tHAVE_LANGINFO\tTriggers use of nl_langinfo if defined.\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_ENABLE_LANGINFO], [\n    AC_ARG_ENABLE(langinfo,\n\tAC_HELP_STRING([--enable-langinfo],\n\t    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),\n\t[langinfo_ok=$enableval], [langinfo_ok=yes])\n\n    HAVE_LANGINFO=0\n    if test \"$langinfo_ok\" = \"yes\"; then\n\tAC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])\n    fi\n    AC_MSG_CHECKING([whether to use nl_langinfo])\n    if test \"$langinfo_ok\" = \"yes\"; then\n\tAC_CACHE_VAL(tcl_cv_langinfo_h, [\n\t    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],\n\t\t    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])\n\tAC_MSG_RESULT([$tcl_cv_langinfo_h])\n\tif test $tcl_cv_langinfo_h = yes; then\n\t    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])\n\tfi\n    else \n\tAC_MSG_RESULT([$langinfo_ok])\n    fi\n])\n\n#--------------------------------------------------------------------\n# TEA_CONFIG_SYSTEM\n#\n#\tDetermine what the system is (some things cannot be easily checked\n#\ton a feature-driven basis, alas). This can usually be done via the\n#\t\"uname\" command, but there are a few systems, like Next, where\n#\tthis doesn't work.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tDefines the following var:\n#\n#\tsystem -\tSystem/platform/version identification code.\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_CONFIG_SYSTEM], [\n    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [\n\t# TEA specific:\n\tif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t    tcl_cv_sys_version=windows\n\telif test -f /usr/lib/NextStep/software_version; then\n\t    tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`\n\telse\n\t    tcl_cv_sys_version=`uname -s`-`uname -r`\n\t    if test \"$?\" -ne 0 ; then\n\t\tAC_MSG_WARN([can't find uname command])\n\t\ttcl_cv_sys_version=unknown\n\t    else\n\t\t# Special check for weird MP-RAS system (uname returns weird\n\t\t# results, and the version is kept in special file).\n\n\t\tif test -r /etc/.relid -a \"X`uname -n`\" = \"X`uname -s`\" ; then\n\t\t    tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid`\n\t\tfi\n\t\tif test \"`uname -s`\" = \"AIX\" ; then\n\t\t    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`\n\t\tfi\n\t    fi\n\tfi\n    ])\n    system=$tcl_cv_sys_version\n])\n\n#--------------------------------------------------------------------\n# TEA_CONFIG_CFLAGS\n#\n#\tTry to determine the proper flags to pass to the compiler\n#\tfor building shared libraries and other such nonsense.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines and substitutes the following vars:\n#\n#       DL_OBJS -       Name of the object file that implements dynamic\n#                       loading for Tcl on this system.\n#       DL_LIBS -       Library file(s) to include in tclsh and other base\n#                       applications in order for the \"load\" command to work.\n#       LDFLAGS -      Flags to pass to the compiler when linking object\n#                       files into an executable application binary such\n#                       as tclsh.\n#       LD_SEARCH_FLAGS-Flags to pass to ld, such as \"-R /usr/local/tcl/lib\",\n#                       that tell the run-time dynamic linker where to look\n#                       for shared libraries such as libtcl.so.  Depends on\n#                       the variable LIB_RUNTIME_DIR in the Makefile. Could\n#                       be the same as CC_SEARCH_FLAGS if ${CC} is used to link.\n#       CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as \"-Wl,-rpath,/usr/local/tcl/lib\",\n#                       that tell the run-time dynamic linker where to look\n#                       for shared libraries such as libtcl.so.  Depends on\n#                       the variable LIB_RUNTIME_DIR in the Makefile.\n#       SHLIB_CFLAGS -  Flags to pass to cc when compiling the components\n#                       of a shared library (may request position-independent\n#                       code, among other things).\n#       SHLIB_LD -      Base command to use for combining object files\n#                       into a shared library.\n#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when\n#                       creating shared libraries.  This symbol typically\n#                       goes at the end of the \"ld\" commands that build\n#                       shared libraries. The value of the symbol is\n#                       \"${LIBS}\" if all of the dependent libraries should\n#                       be specified when creating a shared library.  If\n#                       dependent libraries should not be specified (as on\n#                       SunOS 4.x, where they cause the link to fail, or in\n#                       general if Tcl and Tk aren't themselves shared\n#                       libraries), then this symbol has an empty string\n#                       as its value.\n#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable\n#                       extensions.  An empty string means we don't know how\n#                       to use shared libraries on this platform.\n#       LIB_SUFFIX -    Specifies everything that comes after the \"libfoo\"\n#                       in a static or shared library name, using the $VERSION variable\n#                       to put the version in the right place.  This is used\n#                       by platforms that need non-standard library names.\n#                       Examples:  ${VERSION}.so.1.1 on NetBSD, since it needs\n#                       to have a version after the .so, and ${VERSION}.a\n#                       on AIX, since a shared library needs to have\n#                       a .a extension whereas shared objects for loadable\n#                       extensions have a .so extension.  Defaults to\n#                       ${VERSION}${SHLIB_SUFFIX}.\n#       TCL_NEEDS_EXP_FILE -\n#                       1 means that an export file is needed to link to a\n#                       shared library.\n#       TCL_EXP_FILE -  The name of the installed export / import file which\n#                       should be used to link to the Tcl shared library.\n#                       Empty if Tcl is unshared.\n#       TCL_BUILD_EXP_FILE -\n#                       The name of the built export / import file which\n#                       should be used to link to the Tcl shared library.\n#                       Empty if Tcl is unshared.\n#\tCFLAGS_DEBUG -\n#\t\t\tFlags used when running the compiler in debug mode\n#\tCFLAGS_OPTIMIZE -\n#\t\t\tFlags used when running the compiler in optimize mode\n#\tCFLAGS -\tAdditional CFLAGS added as necessary (usually 64-bit)\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_CONFIG_CFLAGS], [\n    dnl TEA specific: Make sure we are initialized\n    AC_REQUIRE([TEA_INIT])\n\n    # Step 0.a: Enable 64 bit support?\n\n    AC_MSG_CHECKING([if 64bit support is requested])\n    AC_ARG_ENABLE(64bit,\n\tAC_HELP_STRING([--enable-64bit],\n\t    [enable 64bit support (default: off)]),\n\t[do64bit=$enableval], [do64bit=no])\n    AC_MSG_RESULT([$do64bit])\n\n    # Step 0.b: Enable Solaris 64 bit VIS support?\n\n    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])\n    AC_ARG_ENABLE(64bit-vis,\n\tAC_HELP_STRING([--enable-64bit-vis],\n\t    [enable 64bit Sparc VIS support (default: off)]),\n\t[do64bitVIS=$enableval], [do64bitVIS=no])\n    AC_MSG_RESULT([$do64bitVIS])\n    # Force 64bit on with VIS\n    AS_IF([test \"$do64bitVIS\" = \"yes\"], [do64bit=yes])\n\n    # Step 0.c: Check if visibility support is available. Do this here so\n    # that platform specific alternatives can be used below if this fails.\n\n    AC_CACHE_CHECK([if compiler supports visibility \"hidden\"],\n\ttcl_cv_cc_visibility_hidden, [\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Werror\"\n\tAC_TRY_LINK([\n\t    extern __attribute__((__visibility__(\"hidden\"))) void f(void);\n\t    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,\n\t    tcl_cv_cc_visibility_hidden=no)\n\tCFLAGS=$hold_cflags])\n    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [\n\tAC_DEFINE(MODULE_SCOPE,\n\t    [extern __attribute__((__visibility__(\"hidden\")))],\n\t    [Compiler support for module scope symbols])\n    ])\n\n    # Step 0.d: Disable -rpath support?\n\n    AC_MSG_CHECKING([if rpath support is requested])\n    AC_ARG_ENABLE(rpath,\n\tAC_HELP_STRING([--disable-rpath],\n\t    [disable rpath support (default: on)]),\n\t[doRpath=$enableval], [doRpath=yes])\n    AC_MSG_RESULT([$doRpath])\n\n    # TEA specific: Cross-compiling options for Windows/CE builds?\n\n    AS_IF([test \"${TEA_PLATFORM}\" = windows], [\n\tAC_MSG_CHECKING([if Windows/CE build is requested])\n\tAC_ARG_ENABLE(wince,\n\t    AC_HELP_STRING([--enable-wince],\n\t\t[enable Win/CE support (where applicable)]),\n\t    [doWince=$enableval], [doWince=no])\n\tAC_MSG_RESULT([$doWince])\n    ])\n\n    # Step 1: set the variable \"system\" to hold the name and version number\n    # for the system.\n\n    TEA_CONFIG_SYSTEM\n\n    # Step 2: check for existence of -ldl library.  This is needed because\n    # Linux can use either -ldl or -ldld for dynamic loading.\n\n    AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)\n\n    # Require ranlib early so we can override it in special cases below.\n\n    AC_REQUIRE([AC_PROG_RANLIB])\n\n    # Step 3: set configuration options based on system name and version.\n    # This is similar to Tcl's unix/tcl.m4 except that we've added a\n    # \"windows\" case.\n\n    do64bit_ok=no\n    LDFLAGS_ORIG=\"$LDFLAGS\"\n    # When ld needs options to work in 64-bit mode, put them in\n    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]\n    # is disabled by the user. [Bug 1016796]\n    LDFLAGS_ARCH=\"\"\n    TCL_EXPORT_FILE_SUFFIX=\"\"\n    UNSHARED_LIB_SUFFIX=\"\"\n    # TEA specific: use PACKAGE_VERSION instead of VERSION\n    TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'\n    ECHO_VERSION='`echo ${PACKAGE_VERSION}`'\n    TCL_LIB_VERSIONS_OK=ok\n    CFLAGS_DEBUG=-g\n    CFLAGS_OPTIMIZE=-O\n    AS_IF([test \"$GCC\" = yes], [\n\t# TEA specific:\n\tCFLAGS_OPTIMIZE=-O2\n\tCFLAGS_WARNING=\"-Wall -Wno-implicit-int\"\n    ], [CFLAGS_WARNING=\"\"])\n    TCL_NEEDS_EXP_FILE=0\n    TCL_BUILD_EXP_FILE=\"\"\n    TCL_EXP_FILE=\"\"\ndnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed.\ndnl AC_CHECK_TOOL(AR, ar)\n    AC_CHECK_PROG(AR, ar, ar)\n    STLIB_LD='${AR} cr'\n    LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH\"\n    case $system in\n\t# TEA specific:\n\twindows)\n\t    # This is a 2-stage check to make sure we have the 64-bit SDK\n\t    # We have to know where the SDK is installed.\n\t    # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs\n\t    # MACHINE is IX86 for LINK, but this is used by the manifest,\n\t    # which requires x86|amd64|ia64.\n\t    MACHINE=\"X86\"\n\t    if test \"$do64bit\" != \"no\" ; then\n\t\tif test \"x${MSSDK}x\" = \"xx\" ; then\n\t\t    MSSDK=\"C:/Progra~1/Microsoft Platform SDK\"\n\t\tfi\n\t\tMSSDK=`echo \"$MSSDK\" | sed -e  's!\\\\\\!/!g'`\n\t\tPATH64=\"\"\n\t\tcase \"$do64bit\" in\n\t\t    amd64|x64|yes)\n\t\t\tMACHINE=\"AMD64\" ; # default to AMD64 64-bit build\n\t\t\tPATH64=\"${MSSDK}/Bin/Win64/x86/AMD64\"\n\t\t\t;;\n\t\t    ia64)\n\t\t\tMACHINE=\"IA64\"\n\t\t\tPATH64=\"${MSSDK}/Bin/Win64\"\n\t\t\t;;\n\t\tesac\n\t\tif test ! -d \"${PATH64}\" ; then\n\t\t    AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])\n\t\t    AC_MSG_WARN([Ensure latest Platform SDK is installed])\n\t\t    do64bit=\"no\"\n\t\telse\n\t\t    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])\n\t\t    do64bit_ok=\"yes\"\n\t\tfi\n\t    fi\n\n\t    if test \"$doWince\" != \"no\" ; then\n\t\tif test \"$do64bit\" != \"no\" ; then\n\t\t    AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])\n\t\tfi\n\t\tif test \"$GCC\" = \"yes\" ; then\n\t\t    AC_MSG_ERROR([Windows/CE and GCC builds incompatible])\n\t\tfi\n\t\tTEA_PATH_CELIB\n\t\t# Set defaults for common evc4/PPC2003 setup\n\t\t# Currently Tcl requires 300+, possibly 420+ for sockets\n\t\tCEVERSION=420; \t\t# could be 211 300 301 400 420 ...\n\t\tTARGETCPU=ARMV4;\t# could be ARMV4 ARM MIPS SH3 X86 ...\n\t\tARCH=ARM;\t\t# could be ARM MIPS X86EM ...\n\t\tPLATFORM=\"Pocket PC 2003\"; # or \"Pocket PC 2002\"\n\t\tif test \"$doWince\" != \"yes\"; then\n\t\t    # If !yes then the user specified something\n\t\t    # Reset ARCH to allow user to skip specifying it\n\t\t    ARCH=\n\t\t    eval `echo $doWince | awk -F, '{ \\\n\t    if (length([$]1)) { printf \"CEVERSION=\\\"%s\\\"\\n\", [$]1; \\\n\t    if ([$]1 < 400)   { printf \"PLATFORM=\\\"Pocket PC 2002\\\"\\n\" } }; \\\n\t    if (length([$]2)) { printf \"TARGETCPU=\\\"%s\\\"\\n\", toupper([$]2) }; \\\n\t    if (length([$]3)) { printf \"ARCH=\\\"%s\\\"\\n\", toupper([$]3) }; \\\n\t    if (length([$]4)) { printf \"PLATFORM=\\\"%s\\\"\\n\", [$]4 }; \\\n\t\t    }'`\n\t\t    if test \"x${ARCH}\" = \"x\" ; then\n\t\t\tARCH=$TARGETCPU;\n\t\t    fi\n\t\tfi\n\t\tOSVERSION=WCE$CEVERSION;\n\t    \tif test \"x${WCEROOT}\" = \"x\" ; then\n\t\t\tWCEROOT=\"C:/Program Files/Microsoft eMbedded C++ 4.0\"\n\t\t    if test ! -d \"${WCEROOT}\" ; then\n\t\t\tWCEROOT=\"C:/Program Files/Microsoft eMbedded Tools\"\n\t\t    fi\n\t\tfi\n\t\tif test \"x${SDKROOT}\" = \"x\" ; then\n\t\t    SDKROOT=\"C:/Program Files/Windows CE Tools\"\n\t\t    if test ! -d \"${SDKROOT}\" ; then\n\t\t\tSDKROOT=\"C:/Windows CE Tools\"\n\t\t    fi\n\t\tfi\n\t\tWCEROOT=`echo \"$WCEROOT\" | sed -e 's!\\\\\\!/!g'`\n\t\tSDKROOT=`echo \"$SDKROOT\" | sed -e 's!\\\\\\!/!g'`\n\t\tif test ! -d \"${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}\" \\\n\t\t    -o ! -d \"${WCEROOT}/EVC/${OSVERSION}/bin\"; then\n\t\t    AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])\n\t\t    doWince=\"no\"\n\t\telse\n\t\t    # We could PATH_NOSPACE these, but that's not important,\n\t\t    # as long as we quote them when used.\n\t\t    CEINCLUDE=\"${SDKROOT}/${OSVERSION}/${PLATFORM}/include\"\n\t\t    if test -d \"${CEINCLUDE}/${TARGETCPU}\" ; then\n\t\t\tCEINCLUDE=\"${CEINCLUDE}/${TARGETCPU}\"\n\t\t    fi\n\t\t    CELIBPATH=\"${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}\"\n    \t\tfi\n\t    fi\n\n\t    if test \"$GCC\" != \"yes\" ; then\n\t        if test \"${SHARED_BUILD}\" = \"0\" ; then\n\t\t    runtime=-MT\n\t        else\n\t\t    runtime=-MD\n\t        fi\n\n                if test \"$do64bit\" != \"no\" ; then\n\t\t    # All this magic is necessary for the Win64 SDK RC1 - hobbs\n\t\t    CC=\"\\\"${PATH64}/cl.exe\\\"\"\n\t\t    CFLAGS=\"${CFLAGS} -I\\\"${MSSDK}/Include\\\" -I\\\"${MSSDK}/Include/crt\\\" -I\\\"${MSSDK}/Include/crt/sys\\\"\"\n\t\t    RC=\"\\\"${MSSDK}/bin/rc.exe\\\"\"\n\t\t    lflags=\"-nologo -MACHINE:${MACHINE} -LIBPATH:\\\"${MSSDK}/Lib/${MACHINE}\\\"\"\n\t\t    LINKBIN=\"\\\"${PATH64}/link.exe\\\"\"\n\t\t    CFLAGS_DEBUG=\"-nologo -Zi -Od -W3 ${runtime}d\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -O2 -W2 ${runtime}\"\n\t\t    # Avoid 'unresolved external symbol __security_cookie'\n\t\t    # errors, c.f. http://support.microsoft.com/?id=894573\n\t\t    TEA_ADD_LIBS([bufferoverflowU.lib])\n\t\telif test \"$doWince\" != \"no\" ; then\n\t\t    CEBINROOT=\"${WCEROOT}/EVC/${OSVERSION}/bin\"\n\t\t    if test \"${TARGETCPU}\" = \"X86\"; then\n\t\t\tCC=\"\\\"${CEBINROOT}/cl.exe\\\"\"\n\t\t    else\n\t\t\tCC=\"\\\"${CEBINROOT}/cl${ARCH}.exe\\\"\"\n\t\t    fi\n\t\t    CFLAGS=\"$CFLAGS -I\\\"${CELIB_DIR}/inc\\\" -I\\\"${CEINCLUDE}\\\"\"\n\t\t    RC=\"\\\"${WCEROOT}/Common/EVC/bin/rc.exe\\\"\"\n\t\t    arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`\n\t\t    defs=\"${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS\"\n\t\t    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\t\t\t# Static CE builds require static celib as well\n\t\t    \tdefs=\"${defs} _DLL\"\n\t\t    fi\n\t\t    for i in $defs ; do\n\t\t\tAC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)\n\t\t    done\n\t\t    AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])\n\t\t    AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])\n\t\t    CFLAGS_DEBUG=\"-nologo -Zi -Od\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -Ox\"\n\t\t    lversion=`echo ${CEVERSION} | sed -e 's/\\(.\\)\\(..\\)/\\1\\.\\2/'`\n\t\t    lflags=\"-MACHINE:${ARCH} -LIBPATH:\\\"${CELIBPATH}\\\" -subsystem:windowsce,${lversion} -nologo\"\n\t\t    LINKBIN=\"\\\"${CEBINROOT}/link.exe\\\"\"\n\t\t    AC_SUBST(CELIB_DIR)\n\t\telse\n\t\t    RC=\"rc\"\n\t\t    lflags=\"-nologo\"\n    \t\t    LINKBIN=\"link\"\n\t\t    CFLAGS_DEBUG=\"-nologo -Z7 -Od -W3 -WX ${runtime}d\"\n\t\t    CFLAGS_OPTIMIZE=\"-nologo -O2 -W2 ${runtime}\"\n\t\tfi\n\t    fi\n\n\t    if test \"$GCC\" = \"yes\"; then\n\t\t# mingw gcc mode\n\t\tRC=\"windres\"\n\t\tCFLAGS_DEBUG=\"-g\"\n\t\tCFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\t\tSHLIB_LD=\"$CC -shared\"\n\t\tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t\tLDFLAGS_CONSOLE=\"-wl,--subsystem,console ${lflags}\"\n\t\tLDFLAGS_WINDOW=\"-wl,--subsystem,windows ${lflags}\"\n\t    else\n\t\tSHLIB_LD=\"${LINKBIN} -dll ${lflags}\"\n\t\t# link -lib only works when -lib is the first arg\n\t\tSTLIB_LD=\"${LINKBIN} -lib ${lflags}\"\n\t\tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'\n\t\tPATHTYPE=-w\n\t\t# For information on what debugtype is most useful, see:\n\t\t# http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp\n\t\t# and also\n\t\t# http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx\n\t\t# This essentially turns it all on.\n\t\tLDFLAGS_DEBUG=\"-debug -debugtype:cv\"\n\t\tLDFLAGS_OPTIMIZE=\"-release\"\n\t\tif test \"$doWince\" != \"no\" ; then\n\t\t    LDFLAGS_CONSOLE=\"-link ${lflags}\"\n\t\t    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}\n\t\telse\n\t\t    LDFLAGS_CONSOLE=\"-link -subsystem:console ${lflags}\"\n\t\t    LDFLAGS_WINDOW=\"-link -subsystem:windows ${lflags}\"\n\t\tfi\n\t    fi\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".dll\"\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'\n\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    # Bogus to avoid getting this turned off\n\t    DL_OBJS=\"tclLoadNone.obj\"\n    \t    ;;\n\tAIX-*)\n\t    AS_IF([test \"${TCL_THREADS}\" = \"1\" -a \"$GCC\" != \"yes\"], [\n\t\t# AIX requires the _r compiler when gcc isn't being used\n\t\tcase \"${CC}\" in\n\t\t    *_r)\n\t\t\t# ok ...\n\t\t\t;;\n\t\t    *)\n\t\t\tCC=${CC}_r\n\t\t\t;;\n\t\tesac\n\t\tAC_MSG_RESULT([Using $CC for compiling with threads])\n\t    ])\n\t    LIBS=\"$LIBS -lc\"\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    LD_LIBRARY_PATH_VAR=\"LIBPATH\"\n\n\t    # Check to enable 64-bit flags for compiler/linker on AIX 4+\n\t    AS_IF([test \"$do64bit\" = yes -a \"`uname -v`\" -gt 3], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    AC_MSG_WARN([64bit mode not supported with GCC on $system])\n\t\t], [\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS -q64\"\n\t\t    LDFLAGS_ARCH=\"-q64\"\n\t\t    RANLIB=\"${RANLIB} -X64\"\n\t\t    AR=\"${AR} -X64\"\n\t\t    SHLIB_LD_FLAGS=\"-b64\"\n\t\t])\n\t    ])\n\n\t    AS_IF([test \"`uname -m`\" = ia64], [\n\t\t# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\t# AIX-5 has dl* in libc.so\n\t\tDL_LIBS=\"\"\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\t], [\n\t\t    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'\n\t\t])\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t    ], [\n\t\tAS_IF([test \"$GCC\" = yes], [SHLIB_LD='${CC} -shared'], [\n\t\t    SHLIB_LD=\"/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry\"\n\t\t])\n\t\tSHLIB_LD=\"${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}\"\n\t\tDL_LIBS=\"-ldl\"\n\t\tCC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tTCL_NEEDS_EXP_FILE=1\n\t\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\t\tTCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp'\n\t    ])\n\n\t    # AIX v<=4.1 has some different flags than 4.2+\n\t    AS_IF([test \"$system\" = \"AIX-4.1\" -o \"`uname -v`\" -lt 4], [\n\t\tAC_LIBOBJ([tclLoadAix])\n\t\tDL_LIBS=\"-lld\"\n\t    ])\n\n\t    # On AIX <=v4 systems, libbsd.a has to be linked in to support\n\t    # non-blocking file IO.  This library has to be linked in after\n\t    # the MATH_LIBS or it breaks the pow() function.  The way to\n\t    # insure proper sequencing, is to add it to the tail of MATH_LIBS.\n\t    # This library also supplies gettimeofday.\n\t    #\n\t    # AIX does not have a timezone field in struct tm. When the AIX\n\t    # bsd library is used, the timezone global and the gettimeofday\n\t    # methods are to be avoided for timezone deduction instead, we\n\t    # deduce the timezone by comparing the localtime result on a\n\t    # known GMT value.\n\n\t    AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes, libbsd=no)\n\t    AS_IF([test $libbsd = yes], [\n\t    \tMATH_LIBS=\"$MATH_LIBS -lbsd\"\n\t    \tAC_DEFINE(USE_DELTA_FOR_TZ, 1, [Do we need a special AIX hack for timezones?])\n\t    ])\n\t    ;;\n\tBeOS*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -nostart'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\n\t    #-----------------------------------------------------------\n\t    # Check for inet_ntoa in -lbind, for BeOS (which also needs\n\t    # -lsocket, even if the network functions are in -lnet which\n\t    # is always linked to, for compatibility.\n\t    #-----------------------------------------------------------\n\t    AC_CHECK_LIB(bind, inet_ntoa, [LIBS=\"$LIBS -lbind -lsocket\"])\n\t    ;;\n\tBSD/OS-2.1*|BSD/OS-3*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"shlicc -r\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tBSD/OS-4.*)\n\t    SHLIB_CFLAGS=\"-export-dynamic -fPIC\"\n\t    SHLIB_LD='${CC} -shared'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tdgux*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tHP-UX-*.11.*)\n\t    # Use updated header definitions where possible\n\t    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])\n\t    # TEA specific: Needed by Tcl, but not most extensions\n\t    #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])\n\t    #LIBS=\"$LIBS -lxnet\"               # Use the XOPEN network library\n\n\t    AS_IF([test \"`uname -m`\" = ia64], [\n\t\tSHLIB_SUFFIX=\".so\"\n\t\t# Use newer C++ library for C++ extensions\n\t\t#if test \"$GCC\" != \"yes\" ; then\n\t\t#   CPPFLAGS=\"-AA\"\n\t\t#fi\n\t    ], [\n\t\tSHLIB_SUFFIX=\".sl\"\n\t    ])\n\t    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)\n\t    AS_IF([test \"$tcl_ok\" = yes], [\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS='${LIBS}'\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\t    ])\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tSHLIB_LD_LIBS='${LIBS}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ])\n\n\t    # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc\n\t    #CFLAGS=\"$CFLAGS +DAportable\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    AS_IF([test \"$do64bit\" = \"yes\"], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    case `${CC} -dumpmachine` in\n\t\t\thppa64*)\n\t\t\t    # 64-bit gcc in use.  Fix flags for GNU ld.\n\t\t\t    do64bit_ok=yes\n\t\t\t    SHLIB_LD='${CC} -shared'\n\t\t\t    SHLIB_LD_LIBS='${LIBS}'\n\t\t\t    AS_IF([test $doRpath = yes], [\n\t\t\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])\n\t\t\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\t\t    ;;\n\t\t\t*)\n\t\t\t    AC_MSG_WARN([64bit mode not supported with GCC on $system])\n\t\t\t    ;;\n\t\t    esac\n\t\t], [\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS +DD64\"\n\t\t    LDFLAGS_ARCH=\"+DD64\"\n\t\t])\n\t    ]) ;;\n\tHP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)\n\t    SHLIB_SUFFIX=\".sl\"\n\t    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)\n\t    AS_IF([test \"$tcl_ok\" = yes], [\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS=\"\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\t    ]) ;;\n\tIRIX-5.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    ;;\n\tIRIX-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tCFLAGS=\"$CFLAGS -mabi=n32\"\n\t\tLDFLAGS=\"$LDFLAGS -mabi=n32\"\n\t    ], [\n\t\tcase $system in\n\t\t    IRIX-6.3)\n\t\t\t# Use to build 6.2 compatible binaries on 6.3.\n\t\t\tCFLAGS=\"$CFLAGS -n32 -D_OLD_TERMIOS\"\n\t\t\t;;\n\t\t    *)\n\t\t\tCFLAGS=\"$CFLAGS -n32\"\n\t\t\t;;\n\t\tesac\n\t\tLDFLAGS=\"$LDFLAGS -n32\"\n\t    ])\n\t    ;;\n\tIRIX64-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\n\t    AS_IF([test \"$do64bit\" = yes], [\n\t        AS_IF([test \"$GCC\" = yes], [\n\t            AC_MSG_WARN([64bit mode not supported by gcc])\n\t        ], [\n\t            do64bit_ok=yes\n\t            SHLIB_LD=\"ld -64 -shared -rdata_shared\"\n\t            CFLAGS=\"$CFLAGS -64\"\n\t            LDFLAGS_ARCH=\"-64\"\n\t        ])\n\t    ])\n\t    ;;\n\tLinux*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    # TEA specific:\n\t    CFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\t    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings \n\t    # when you inline the string and math operations.  Turn this off to\n\t    # get rid of the warnings.\n\t    #CFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES\"\n\n\t    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS\n\t    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    AS_IF([test \"`uname -m`\" = \"alpha\"], [CFLAGS=\"$CFLAGS -mieee\"])\n\t    AS_IF([test $do64bit = yes], [\n\t\tAC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [\n\t\t    hold_cflags=$CFLAGS\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)\n\t\t    CFLAGS=$hold_cflags])\n\t\tAS_IF([test $tcl_cv_cc_m64 = yes], [\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    do64bit_ok=yes\n\t\t])\n\t   ])\n\n\t    # The combo of gcc + glibc has a bug related to inlining of\n\t    # functions like strtod(). The -fno-builtin flag should address\n\t    # this problem but it does not work. The -fno-inline flag is kind\n\t    # of overkill but it works. Disable inlining only when one of the\n\t    # files in compat/*.c is being linked in.\n\n\t    AS_IF([test x\"${USE_COMPAT}\" != x],[CFLAGS=\"$CFLAGS -fno-inline\"])\n\n\t    ;;\n\tGNU*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    AS_IF([test \"`uname -m`\" = \"alpha\"], [CFLAGS=\"$CFLAGS -mieee\"])\n\t    ;;\n\tLynx*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    CFLAGS_OPTIMIZE=-02\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-mshared -ldl\"\n\t    LD_FLAGS=\"-Wl,--export-dynamic\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])\n\t    ;;\n\tMP-RAS-02*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tMP-RAS-*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tNetBSD-1.*|FreeBSD-[[1-2]].*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [\n\t\tAC_EGREP_CPP(yes, [\n#ifdef __ELF__\n\tyes\n#endif\n\t\t], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])\n\t    AS_IF([test $tcl_cv_ld_elf = yes], [\n\t\tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'\n\t    ], [\n\t\tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\t    ])\n\n\t    # Ancient FreeBSD doesn't handle version numbers with dots.\n\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tOpenBSD-*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\t    AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [\n\t\tAC_EGREP_CPP(yes, [\n#ifdef __ELF__\n\tyes\n#endif\n\t\t], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])\n\t    AS_IF([test $tcl_cv_ld_elf = yes], [\n\t\tLDFLAGS=-Wl,-export-dynamic\n\t    ], [LDFLAGS=\"\"])\n\n\t    # OpenBSD doesn't do version numbers with dots.\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tNetBSD-*|FreeBSD-*)\n\t    # FreeBSD 3.* and greater have ELF.\n\t    # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    AS_IF([test \"${TCL_THREADS}\" = \"1\"], [\n\t\t# The -pthread needs to go in the CFLAGS, not LIBS\n\t\tLIBS=`echo $LIBS | sed s/-pthread//`\n\t\tCFLAGS=\"$CFLAGS -pthread\"\n\t    \tLDFLAGS=\"$LDFLAGS -pthread\"\n\t    ])\n\t    case $system in\n\t    FreeBSD-3.*)\n\t    \t# FreeBSD-3 doesn't handle version numbers with dots.\n\t    \tUNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    \tSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'\n\t    \tTCL_LIB_VERSIONS_OK=nodots\n\t\t;;\n\t    esac\n\t    ;;\n\tDarwin-*)\n\t    CFLAGS_OPTIMIZE=\"-Os\"\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    # To avoid discrepancies between what headers configure sees during\n\t    # preprocessing tests and compiling tests, move any -isysroot and\n\t    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:\n\t    CPPFLAGS=\"${CPPFLAGS} `echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif ([$]i~/^(isysroot|mmacosx-version-min)/) print \"-\"[$]i}'`\"\n\t    CFLAGS=\"`echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif (!([$]i~/^(isysroot|mmacosx-version-min)/)) print \"-\"[$]i}'`\"\n\t    AS_IF([test $do64bit = yes], [\n\t\tcase `arch` in\n\t\t    ppc)\n\t\t\tAC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],\n\t\t\t\ttcl_cv_cc_arch_ppc64, [\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,\n\t\t\t\t    tcl_cv_cc_arch_ppc64=no)\n\t\t\t    CFLAGS=$hold_cflags])\n\t\t\tAS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    do64bit_ok=yes\n\t\t\t]);;\n\t\t    i386)\n\t\t\tAC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],\n\t\t\t\ttcl_cv_cc_arch_x86_64, [\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,\n\t\t\t\t    tcl_cv_cc_arch_x86_64=no)\n\t\t\t    CFLAGS=$hold_cflags])\n\t\t\tAS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    do64bit_ok=yes\n\t\t\t]);;\n\t\t    *)\n\t\t\tAC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;\n\t\tesac\n\t    ], [\n\t\t# Check for combined 32-bit and 64-bit fat build\n\t\tAS_IF([echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc64|x86_64) ' \\\n\t\t    && echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc|i386) '], [\n\t\t    fat_32_64=yes])\n\t    ])\n\t    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS\n\t    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'\n\t    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -dynamiclib -Wl,-single_module\"\n\t\tAC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)\n\t\tLDFLAGS=$hold_ldflags])\n\t    AS_IF([test $tcl_cv_ld_single_module = yes], [\n\t\tSHLIB_LD=\"${SHLIB_LD} -Wl,-single_module\"\n\t    ])\n\t    # TEA specific: link shlib with current and compatibility version flags\n\t    vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\\([[0-9]]\\{1,5\\}\\)\\(\\(\\.[[0-9]]\\{1,3\\}\\)\\{0,2\\}\\).*$/\\1\\2/p' -e d`\n\t    SHLIB_LD=\"${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}\"\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".dylib\"\n\t    DL_OBJS=\"tclLoadDyld.o\"\n\t    DL_LIBS=\"\"\n\t    # Don't use -prebind when building for Mac OS X 10.4 or later only:\n\t    AS_IF([test \"`echo \"${MACOSX_DEPLOYMENT_TARGET}\" | awk -F '10\\\\.' '{print int([$]2)}'`\" -lt 4 -a \\\n\t\t\"`echo \"${CPPFLAGS}\" | awk -F '-mmacosx-version-min=10\\\\.' '{print int([$]2)}'`\" -lt 4], [\n\t\tLDFLAGS=\"$LDFLAGS -prebind\"])\n\t    LDFLAGS=\"$LDFLAGS -headerpad_max_install_names\"\n\t    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],\n\t\t    tcl_cv_ld_search_paths_first, [\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t\tAC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,\n\t\t\ttcl_cv_ld_search_paths_first=no)\n\t\tLDFLAGS=$hold_ldflags])\n\t    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t    ])\n\t    AS_IF([test \"$tcl_cv_cc_visibility_hidden\" != yes], [\n\t\tAC_DEFINE(MODULE_SCOPE, [__private_extern__],\n\t\t    [Compiler support for module scope symbols])\n\t    ])\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    LD_LIBRARY_PATH_VAR=\"DYLD_LIBRARY_PATH\"\n\t    # TEA specific: for combined 32 & 64 bit fat builds of Tk\n\t    # extensions, verify that 64-bit build is possible.\n\t    AS_IF([test \"$fat_32_64\" = yes && test -n \"${TK_BIN_DIR}\"], [\n\t\tAS_IF([test \"${TEA_WINDOWINGSYSTEM}\" = x11], [\n\t\t    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc / /g\" -e \"s/-arch i386 / /g\"`\"'\n\t\t\tdone\n\t\t\tCPPFLAGS=\"$CPPFLAGS -I/usr/X11R6/include\"\n\t\t\tLDFLAGS=\"$LDFLAGS -L/usr/X11R6/lib -lX11\"\n\t\t\tAC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],\n\t\t\t    tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone])\n\t\t])\n\t\t# remove 64-bit arch flags from CFLAGS et al. if configuration\n\t\t# does not support 64-bit.\n\t\tAS_IF([test \"${TEA_WINDOWINGSYSTEM}\" = aqua -o \"$tcl_cv_lib_x11_64\" = no], [\n\t\t    AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])\n\t\t    for v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\teval $v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc64 / /g\" -e \"s/-arch x86_64 / /g\"`\"'\n\t\t    done])\n\t    ])\n\t    ;;\n\tNEXTSTEP-*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD='${CC} -nostdlib -r'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadNext.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOS/390-*)\n\t    CFLAGS_OPTIMIZE=\"\"\t\t# Optimizer is buggy\n\t    AC_DEFINE(_OE_SOCKETS, 1,\t# needed in sys/socket.h\n\t\t[Should OS/390 do the right thing with sockets?])\n\t    ;;      \n\tOSF1-1.0|OSF1-1.1|OSF1-1.2)\n\t    # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    # Hack: make package name same as library name\n\t    SHLIB_LD='ld -R -export $@:'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadOSF.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOSF1-1.*)\n\t    # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    AS_IF([test \"$SHARED_BUILD\" = 1], [SHLIB_LD=\"ld -shared\"], [\n\t        SHLIB_LD=\"ld -non_shared\"\n\t    ])\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tOSF1-V*)\n\t    # Digital OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    AS_IF([test \"$SHARED_BUILD\" = 1], [\n\t        SHLIB_LD='${CC} -shared'\n\t    ], [\n\t        SHLIB_LD='${CC} -non_shared'\n\t    ])\n\t    SHLIB_LD_LIBS=\"${LIBS}\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    AS_IF([test \"$GCC\" = yes], [CFLAGS=\"$CFLAGS -mieee\"], [\n\t\tCFLAGS=\"$CFLAGS -DHAVE_TZSET -std1 -ieee\"])\n\t    # see pthread_intro(3) for pthread support on osf1, k.furukawa\n\t    AS_IF([test \"${TCL_THREADS}\" = 1], [\n\t\tCFLAGS=\"$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE\"\n\t\tCFLAGS=\"$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64\"\n\t\tLIBS=`echo $LIBS | sed s/-lpthreads//`\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    LIBS=\"$LIBS -lpthread -lmach -lexc\"\n\t\t], [\n\t\t    CFLAGS=\"$CFLAGS -pthread\"\n\t\t    LDFLAGS=\"$LDFLAGS -pthread\"\n\t\t])\n\t    ])\n\t    ;;\n\tQNX-6*)\n\t    # QNX RTP\n\t    # This may work for all QNX, but it was only reported for v6.\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    # dlopen is in -lc on QNX\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSCO_SV-3.2*)\n\t    # Note, dlopen is available only on SCO 3.2.5 and greater. However,\n\t    # this test works, since \"uname -s\" was non-standard in 3.2.4 and\n\t    # below.\n\t    AS_IF([test \"$GCC\" = yes], [\n\t    \tSHLIB_CFLAGS=\"-fPIC -melf\"\n\t    \tLDFLAGS=\"$LDFLAGS -melf -Wl,-Bexport\"\n\t    ], [\n\t    \tSHLIB_CFLAGS=\"-Kpic -belf\"\n\t    \tLDFLAGS=\"$LDFLAGS -belf -Wl,-Bexport\"\n\t    ])\n\t    SHLIB_LD=\"ld -G\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSINIX*5.4*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSunOS-4*)\n\t    SHLIB_CFLAGS=\"-PIC\"\n\t    SHLIB_LD=\"ld\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\n\t    # SunOS can't handle version numbers with dots in them in library\n\t    # specs, like -ltcl7.5, so use -ltcl75 instead.  Also, it\n\t    # requires an extra version number at the end of .so file names.\n\t    # So, the library has to have a name like libtcl75.so.1.0\n\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tSunOS-5.[[0-6]])\n\t    # Careful to not let 5.10+ fall into this case\n\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\t    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n\t    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,\n\t\t[Do we really want to follow the standard? Yes we do!])\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Note: need the LIBS below, otherwise Tk won't find Tcl's\n\t    # symbols when dynamically loaded into tclsh.\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ], [\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\tCC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ])\n\t    ;;\n\tSunOS-5*)\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\t    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n\t    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,\n\t\t[Do we really want to follow the standard? Yes we do!])\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    AS_IF([test \"$do64bit\" = yes], [\n\t\tarch=`isainfo`\n\t\tAS_IF([test \"$arch\" = \"sparcv9 sparc\"], [\n\t\t    AS_IF([test \"$GCC\" = yes], [\n\t\t\tAS_IF([test \"`${CC} -dumpversion | awk -F. '{print [$]1}'`\" -lt 3], [\n\t\t\t    AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])\n\t\t\t], [\n\t\t\t    do64bit_ok=yes\n\t\t\t    CFLAGS=\"$CFLAGS -m64 -mcpu=v9\"\n\t\t\t    LDFLAGS=\"$LDFLAGS -m64 -mcpu=v9\"\n\t\t\t    SHLIB_CFLAGS=\"-fPIC\"\n\t\t\t])\n\t\t    ], [\n\t\t\tdo64bit_ok=yes\n\t\t\tAS_IF([test \"$do64bitVIS\" = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9a\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9a\"\n\t\t\t], [\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9\"\n\t\t\t])\n\t\t\t# Solaris 64 uses this as well\n\t\t\t#LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH_64\"\n\t\t    ])\n\t\t], [AS_IF([test \"$arch\" = \"amd64 i386\"], [\n\t\t    AS_IF([test \"$GCC\" = yes], [\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)\n\t\t\t\tdo64bit_ok=yes\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tAC_MSG_WARN([64bit mode not supported with GCC on $system]);;\n\t\t\tesac\n\t\t    ], [\n\t\t\tdo64bit_ok=yes\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tCFLAGS=\"$CFLAGS -xarch=amd64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -xarch=amd64\";;\n\t\t\tesac\n\t\t    ])\n\t\t], [AC_MSG_WARN([64bit mode not supported for $arch])])])\n\t    ])\n\n\t    # Note: need the LIBS below, otherwise Tk won't find Tcl's\n\t    # symbols when dynamically loaded into tclsh.\n\n\t    SHLIB_LD_LIBS='${LIBS}'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tAS_IF([test \"$do64bit_ok\" = yes], [\n\t\t    AS_IF([test \"$arch\" = \"sparcv9 sparc\"], [\n\t\t\t# We need to specify -static-libgcc or we need to\n\t\t\t# add the path to the sparv9 libgcc.\n\t\t\t# JH: static-libgcc is necessary for core Tcl, but may\n\t\t\t# not be necessary for extensions.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -mcpu=v9 -static-libgcc\"\n\t\t\t# for finding sparcv9 libgcc, get the regular libgcc\n\t\t\t# path, remove so name and append 'sparcv9'\n\t\t\t#v9gcclibdir=\"`gcc -print-file-name=libgcc_s.so` | ...\"\n\t\t\t#CC_SEARCH_FLAGS=\"${CC_SEARCH_FLAGS},-R,$v9gcclibdir\"\n\t\t    ], [AS_IF([test \"$arch\" = \"amd64 i386\"], [\n\t\t\t# JH: static-libgcc is necessary for core Tcl, but may\n\t\t\t# not be necessary for extensions.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -static-libgcc\"\n\t\t    ])])\n\t\t])\n\t    ], [\n\t\tcase $system in\n\t\t    SunOS-5.[[1-9]][[0-9]]*)\n\t\t\tSHLIB_LD='${CC} -G -z text ${LDFLAGS}';;\n\t\t    *)\n\t\t\tSHLIB_LD='/usr/ccs/bin/ld -G -z text';;\n\t\tesac\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t    ])\n\t    ;;\n\tUNIX_SV* | UnixWare-5*)\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers\n\t    # that don't grok the -Bexport option.  Test that it does.\n\t    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t\tAC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)\n\t        LDFLAGS=$hold_ldflags])\n\t    AS_IF([test $tcl_cv_ld_Bexport = yes], [\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t    ])\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n    esac\n\n    AS_IF([test \"$do64bit\" = yes -a \"$do64bit_ok\" = no], [\n\tAC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])\n    ])\n\ndnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so\ndnl # until the end of configure, as configure's compile and link tests use\ndnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's\ndnl # preprocessing tests use only CPPFLAGS.\n    AC_CONFIG_COMMANDS_PRE([CFLAGS=\"${CFLAGS} ${CPPFLAGS}\"; CPPFLAGS=\"\"])\n\n    # Step 4: disable dynamic loading if requested via a command-line switch.\n\n    AC_ARG_ENABLE(load,\n\tAC_HELP_STRING([--enable-load],\n\t    [allow dynamic loading and \"load\" command (default: on)]),\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n    AS_IF([test \"$tcl_ok\" = no], [DL_OBJS=\"\"])\n\n    AS_IF([test \"x$DL_OBJS\" != x], [BUILD_DLTEST=\"\\$(DLTEST_TARGETS)\"], [\n\tAC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])\n\tSHLIB_CFLAGS=\"\"\n\tSHLIB_LD=\"\"\n\tSHLIB_SUFFIX=\"\"\n\tDL_OBJS=\"tclLoadNone.o\"\n\tDL_LIBS=\"\"\n\tLDFLAGS=\"$LDFLAGS_ORIG\"\n\tCC_SEARCH_FLAGS=\"\"\n\tLD_SEARCH_FLAGS=\"\"\n\tBUILD_DLTEST=\"\"\n    ])\n    LDFLAGS=\"$LDFLAGS $LDFLAGS_ARCH\"\n\n    # If we're running gcc, then change the C flags for compiling shared\n    # libraries to the right flags for gcc, instead of those for the\n    # standard manufacturer compiler.\n\n    AS_IF([test \"$DL_OBJS\" != \"tclLoadNone.o\" -a \"$GCC\" = yes], [\n\tcase $system in\n\t    AIX-*) ;;\n\t    BSD/OS*) ;;\n\t    IRIX*) ;;\n\t    NetBSD-*|FreeBSD-*) ;;\n\t    Darwin-*) ;;\n\t    SCO_SV-3.2*) ;;\n\t    *) SHLIB_CFLAGS=\"-fPIC\" ;;\n\tesac])\n\n    AS_IF([test \"$SHARED_LIB_SUFFIX\" = \"\"], [\n\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\tSHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])\n    AS_IF([test \"$UNSHARED_LIB_SUFFIX\" = \"\"], [\n\t# TEA specific: use PACKAGE_VERSION instead of VERSION\n\tUNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])\n\n    AC_SUBST(DL_LIBS)\n\n    AC_SUBST(CFLAGS_DEBUG)\n    AC_SUBST(CFLAGS_OPTIMIZE)\n    AC_SUBST(CFLAGS_WARNING)\n\n    AC_SUBST(STLIB_LD)\n    AC_SUBST(SHLIB_LD)\n\n    AC_SUBST(SHLIB_LD_LIBS)\n    AC_SUBST(SHLIB_CFLAGS)\n\n    AC_SUBST(LD_LIBRARY_PATH_VAR)\n\n    # These must be called after we do the basic CFLAGS checks and\n    # verify any possible 64-bit or similar switches are necessary\n    TEA_TCL_EARLY_FLAGS\n    TEA_TCL_64BIT_FLAGS\n])\n\n#--------------------------------------------------------------------\n# TEA_SERIAL_PORT\n#\n#\tDetermine which interface to use to talk to the serial port.\n#\tNote that #include lines must begin in leftmost column for\n#\tsome compilers to recognize them as preprocessor directives,\n#\tand some build environments have stdin not pointing at a\n#\tpseudo-terminal (usually /dev/null instead.)\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tDefines only one of the following vars:\n#\t\tHAVE_SYS_MODEM_H\n#\t\tUSE_TERMIOS\n#\t\tUSE_TERMIO\n#\t\tUSE_SGTTY\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_SERIAL_PORT], [\n    AC_CHECK_HEADERS(sys/modem.h)\n    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [\n    AC_TRY_RUN([\n#include <termios.h>\n\nint main() {\n    struct termios t;\n    if (tcgetattr(0, &t) == 0) {\n\tcfsetospeed(&t, 0);\n\tt.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;\n\treturn 0;\n    }\n    return 1;\n}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)\n    if test $tcl_cv_api_serial = no ; then\n\tAC_TRY_RUN([\n#include <termio.h>\n\nint main() {\n    struct termio t;\n    if (ioctl(0, TCGETA, &t) == 0) {\n\tt.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;\n\treturn 0;\n    }\n    return 1;\n}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)\n    fi\n    if test $tcl_cv_api_serial = no ; then\n\tAC_TRY_RUN([\n#include <sgtty.h>\n\nint main() {\n    struct sgttyb t;\n    if (ioctl(0, TIOCGETP, &t) == 0) {\n\tt.sg_ospeed = 0;\n\tt.sg_flags |= ODDP | EVENP | RAW;\n\treturn 0;\n    }\n    return 1;\n}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)\n    fi\n    if test $tcl_cv_api_serial = no ; then\n\tAC_TRY_RUN([\n#include <termios.h>\n#include <errno.h>\n\nint main() {\n    struct termios t;\n    if (tcgetattr(0, &t) == 0\n\t|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {\n\tcfsetospeed(&t, 0);\n\tt.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;\n\treturn 0;\n    }\n    return 1;\n}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)\n    fi\n    if test $tcl_cv_api_serial = no; then\n\tAC_TRY_RUN([\n#include <termio.h>\n#include <errno.h>\n\nint main() {\n    struct termio t;\n    if (ioctl(0, TCGETA, &t) == 0\n\t|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {\n\tt.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;\n\treturn 0;\n    }\n    return 1;\n    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)\n    fi\n    if test $tcl_cv_api_serial = no; then\n\tAC_TRY_RUN([\n#include <sgtty.h>\n#include <errno.h>\n\nint main() {\n    struct sgttyb t;\n    if (ioctl(0, TIOCGETP, &t) == 0\n\t|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {\n\tt.sg_ospeed = 0;\n\tt.sg_flags |= ODDP | EVENP | RAW;\n\treturn 0;\n    }\n    return 1;\n}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)\n    fi])\n    case $tcl_cv_api_serial in\n\ttermios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;\n\ttermio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;\n\tsgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;\n    esac\n])\n\n#--------------------------------------------------------------------\n# TEA_MISSING_POSIX_HEADERS\n#\n#\tSupply substitutes for missing POSIX header files.  Special\n#\tnotes:\n#\t    - stdlib.h doesn't define strtol, strtoul, or\n#\t      strtod insome versions of SunOS\n#\t    - some versions of string.h don't declare procedures such\n#\t      as strstr\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tNO_DIRENT_H\n#\t\tNO_ERRNO_H\n#\t\tNO_VALUES_H\n#\t\tHAVE_LIMITS_H or NO_LIMITS_H\n#\t\tNO_STDLIB_H\n#\t\tNO_STRING_H\n#\t\tNO_SYS_WAIT_H\n#\t\tNO_DLFCN_H\n#\t\tHAVE_SYS_PARAM_H\n#\n#\t\tHAVE_STRING_H ?\n#\n# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and\n# CHECK on limits.h\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_MISSING_POSIX_HEADERS], [\n    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [\n    AC_TRY_LINK([#include <sys/types.h>\n#include <dirent.h>], [\n#ifndef _POSIX_SOURCE\n#   ifdef __Lynx__\n\t/*\n\t * Generate compilation error to make the test fail:  Lynx headers\n\t * are only valid if really in the POSIX environment.\n\t */\n\n\tmissing_procedure();\n#   endif\n#endif\nDIR *d;\nstruct dirent *entryPtr;\nchar *p;\nd = opendir(\"foobar\");\nentryPtr = readdir(d);\np = entryPtr->d_name;\nclosedir(d);\n], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])\n\n    if test $tcl_cv_dirent_h = no; then\n\tAC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])\n    fi\n\n    # TEA specific:\n    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])\n    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])\n    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])\n    AC_CHECK_HEADER(limits.h,\n\t[AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],\n\t[AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])\n    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)\n    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)\n    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)\n    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)\n    if test $tcl_ok = 0; then\n\tAC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])\n    fi\n    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)\n    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)\n    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)\n\n    # See also memmove check below for a place where NO_STRING_H can be\n    # set and why.\n\n    if test $tcl_ok = 0; then\n\tAC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])\n    fi\n\n    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])\n    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])\n\n    # OS/390 lacks sys/param.h (and doesn't need it, by chance).\n    AC_HAVE_HEADERS(sys/param.h)\n])\n\n#--------------------------------------------------------------------\n# TEA_PATH_X\n#\n#\tLocate the X11 header files and the X11 library archive.  Try\n#\tthe ac_path_x macro first, but if it doesn't find the X stuff\n#\t(e.g. because there's no xmkmf program) then check through\n#\ta list of possible directories.  Under some conditions the\n#\tautoconf macro will return an include directory that contains\n#\tno include files, so double-check its result just to be safe.\n#\n#\tThis should be called after TEA_CONFIG_CFLAGS as setting the\n#\tLIBS line can confuse some configure macro magic.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tSets the following vars:\n#\t\tXINCLUDES\n#\t\tXLIBSW\n#\t\tPKG_LIBS (appends to)\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_PATH_X], [\n    if test \"${TEA_WINDOWINGSYSTEM}\" = \"x11\" ; then\n\tTEA_PATH_UNIX_X\n    fi\n])\n\nAC_DEFUN([TEA_PATH_UNIX_X], [\n    AC_PATH_X\n    not_really_there=\"\"\n    if test \"$no_x\" = \"\"; then\n\tif test \"$x_includes\" = \"\"; then\n\t    AC_TRY_CPP([#include <X11/XIntrinsic.h>], , not_really_there=\"yes\")\n\telse\n\t    if test ! -r $x_includes/X11/Intrinsic.h; then\n\t\tnot_really_there=\"yes\"\n\t    fi\n\tfi\n    fi\n    if test \"$no_x\" = \"yes\" -o \"$not_really_there\" = \"yes\"; then\n\tAC_MSG_CHECKING([for X11 header files])\n\tfound_xincludes=\"no\"\n\tAC_TRY_CPP([#include <X11/Intrinsic.h>], found_xincludes=\"yes\", found_xincludes=\"no\")\n\tif test \"$found_xincludes\" = \"no\"; then\n\t    dirs=\"/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include\"\n\t    for i in $dirs ; do\n\t\tif test -r $i/X11/Intrinsic.h; then\n\t\t    AC_MSG_RESULT([$i])\n\t\t    XINCLUDES=\" -I$i\"\n\t\t    found_xincludes=\"yes\"\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    else\n\tif test \"$x_includes\" != \"\"; then\n\t    XINCLUDES=\"-I$x_includes\"\n\t    found_xincludes=\"yes\"\n\tfi\n    fi\n    if test found_xincludes = \"no\"; then\n\tAC_MSG_RESULT([couldn't find any!])\n    fi\n\n    if test \"$no_x\" = yes; then\n\tAC_MSG_CHECKING([for X11 libraries])\n\tXLIBSW=nope\n\tdirs=\"/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib\"\n\tfor i in $dirs ; do\n\t    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then\n\t\tAC_MSG_RESULT([$i])\n\t\tXLIBSW=\"-L$i -lX11\"\n\t\tx_libraries=\"$i\"\n\t\tbreak\n\t    fi\n\tdone\n    else\n\tif test \"$x_libraries\" = \"\"; then\n\t    XLIBSW=-lX11\n\telse\n\t    XLIBSW=\"-L$x_libraries -lX11\"\n\tfi\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\tAC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\tAC_MSG_RESULT([could not find any!  Using -lX11.])\n\tXLIBSW=-lX11\n    fi\n    # TEA specific:\n    if test x\"${XLIBSW}\" != x ; then\n\tPKG_LIBS=\"${PKG_LIBS} ${XLIBSW}\"\n    fi\n])\n\n#--------------------------------------------------------------------\n# TEA_BLOCKING_STYLE\n#\n#\tThe statements below check for systems where POSIX-style\n#\tnon-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. \n#\tOn these systems (mostly older ones), use the old BSD-style\n#\tFIONBIO approach instead.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tHAVE_SYS_IOCTL_H\n#\t\tHAVE_SYS_FILIO_H\n#\t\tUSE_FIONBIO\n#\t\tO_NONBLOCK\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_BLOCKING_STYLE], [\n    AC_CHECK_HEADERS(sys/ioctl.h)\n    AC_CHECK_HEADERS(sys/filio.h)\n    TEA_CONFIG_SYSTEM\n    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])\n    case $system in\n\t# There used to be code here to use FIONBIO under AIX.  However, it\n\t# was reported that FIONBIO doesn't work under AIX 3.2.5.  Since\n\t# using O_NONBLOCK seems fine under AIX 4.*, I removed the FIONBIO\n\t# code (JO, 5/31/97).\n\n\tOSF*)\n\t    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])\n\t    AC_MSG_RESULT([FIONBIO])\n\t    ;;\n\tSunOS-4*)\n\t    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])\n\t    AC_MSG_RESULT([FIONBIO])\n\t    ;;\n\t*)\n\t    AC_MSG_RESULT([O_NONBLOCK])\n\t    ;;\n    esac\n])\n\n#--------------------------------------------------------------------\n# TEA_TIME_HANLDER\n#\n#\tChecks how the system deals with time.h, what time structures\n#\tare used on the system, and what fields the structures have.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tUSE_DELTA_FOR_TZ\n#\t\tHAVE_TM_GMTOFF\n#\t\tHAVE_TM_TZADJ\n#\t\tHAVE_TIMEZONE_VAR\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_TIME_HANDLER], [\n    AC_CHECK_HEADERS(sys/time.h)\n    AC_HEADER_TIME\n    AC_STRUCT_TIMEZONE\n\n    AC_CHECK_FUNCS(gmtime_r localtime_r)\n\n    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [\n\tAC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],\n\t    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])\n    if test $tcl_cv_member_tm_tzadj = yes ; then\n\tAC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])\n    fi\n\n    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [\n\tAC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],\n\t    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])\n    if test $tcl_cv_member_tm_gmtoff = yes ; then\n\tAC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])\n    fi\n\n    #\n    # Its important to include time.h in this check, as some systems\n    # (like convex) have timezone functions, etc.\n    #\n    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [\n\tAC_TRY_COMPILE([#include <time.h>],\n\t    [extern long timezone;\n\t    timezone += 1;\n\t    exit (0);],\n\t    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])\n    if test $tcl_cv_timezone_long = yes ; then\n\tAC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])\n    else\n\t#\n\t# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.\n\t#\n\tAC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [\n\t    AC_TRY_COMPILE([#include <time.h>],\n\t\t[extern time_t timezone;\n\t\ttimezone += 1;\n\t\texit (0);],\n\t\ttcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])\n\tif test $tcl_cv_timezone_time = yes ; then\n\t    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])\n\tfi\n    fi\n])\n\n#--------------------------------------------------------------------\n# TEA_BUGGY_STRTOD\n#\n#\tUnder Solaris 2.4, strtod returns the wrong value for the\n#\tterminating character under some conditions.  Check for this\n#\tand if the problem exists use a substitute procedure\n#\t\"fixstrtod\" (provided by Tcl) that corrects the error.\n#\tAlso, on Compaq's Tru64 Unix 5.0,\n#\tstrtod(\" \") returns 0.0 instead of a failure to convert.\n#\n# Arguments:\n#\tnone\n#\t\n# Results:\n#\n#\tMight defines some of the following vars:\n#\t\tstrtod (=fixstrtod)\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_BUGGY_STRTOD], [\n    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)\n    if test \"$tcl_strtod\" = 1; then\n\tAC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[\n\t    AC_TRY_RUN([\n\t\textern double strtod();\n\t\tint main() {\n\t\t    char *infString=\"Inf\", *nanString=\"NaN\", *spaceString=\" \";\n\t\t    char *term;\n\t\t    double value;\n\t\t    value = strtod(infString, &term);\n\t\t    if ((term != infString) && (term[-1] == 0)) {\n\t\t\texit(1);\n\t\t    }\n\t\t    value = strtod(nanString, &term);\n\t\t    if ((term != nanString) && (term[-1] == 0)) {\n\t\t\texit(1);\n\t\t    }\n\t\t    value = strtod(spaceString, &term);\n\t\t    if (term == (spaceString+1)) {\n\t\t\texit(1);\n\t\t    }\n\t\t    exit(0);\n\t\t}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,\n\t\t    tcl_cv_strtod_buggy=buggy)])\n\tif test \"$tcl_cv_strtod_buggy\" = buggy; then\n\t    AC_LIBOBJ([fixstrtod])\n\t    USE_COMPAT=1\n\t    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])\n\tfi\n    fi\n])\n\n#--------------------------------------------------------------------\n# TEA_TCL_LINK_LIBS\n#\n#\tSearch for the libraries needed to link the Tcl shell.\n#\tThings like the math library (-lm) and socket stuff (-lsocket vs.\n#\t-lnsl) are dealt with here.\n#\n# Arguments:\n#\tRequires the following vars to be set in the Makefile:\n#\t\tDL_LIBS\n#\t\tLIBS\n#\t\tMATH_LIBS\n#\t\n# Results:\n#\n#\tSubst's the following var:\n#\t\tTCL_LIBS\n#\t\tMATH_LIBS\n#\n#\tMight append to the following vars:\n#\t\tLIBS\n#\n#\tMight define the following vars:\n#\t\tHAVE_NET_ERRNO_H\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_TCL_LINK_LIBS], [\n    #--------------------------------------------------------------------\n    # On a few very rare systems, all of the libm.a stuff is\n    # already in libc.a.  Set compiler flags accordingly.\n    # Also, Linux requires the \"ieee\" library for math to work\n    # right (and it must appear before \"-lm\").\n    #--------------------------------------------------------------------\n\n    AC_CHECK_FUNC(sin, MATH_LIBS=\"\", MATH_LIBS=\"-lm\")\n    AC_CHECK_LIB(ieee, main, [MATH_LIBS=\"-lieee $MATH_LIBS\"])\n\n    #--------------------------------------------------------------------\n    # Interactive UNIX requires -linet instead of -lsocket, plus it\n    # needs net/errno.h to define the socket-related error codes.\n    #--------------------------------------------------------------------\n\n    AC_CHECK_LIB(inet, main, [LIBS=\"$LIBS -linet\"])\n    AC_CHECK_HEADER(net/errno.h, [\n\tAC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])\n\n    #--------------------------------------------------------------------\n    #\tCheck for the existence of the -lsocket and -lnsl libraries.\n    #\tThe order here is important, so that they end up in the right\n    #\torder in the command line generated by make.  Here are some\n    #\tspecial considerations:\n    #\t1. Use \"connect\" and \"accept\" to check for -lsocket, and\n    #\t   \"gethostbyname\" to check for -lnsl.\n    #\t2. Use each function name only once:  can't redo a check because\n    #\t   autoconf caches the results of the last check and won't redo it.\n    #\t3. Use -lnsl and -lsocket only if they supply procedures that\n    #\t   aren't already present in the normal libraries.  This is because\n    #\t   IRIX 5.2 has libraries, but they aren't needed and they're\n    #\t   bogus:  they goof up name resolution if used.\n    #\t4. On some SVR4 systems, can't use -lsocket without -lnsl too.\n    #\t   To get around this problem, check for both libraries together\n    #\t   if -lsocket doesn't work by itself.\n    #--------------------------------------------------------------------\n\n    tcl_checkBoth=0\n    AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)\n    if test \"$tcl_checkSocket\" = 1; then\n\tAC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,\n\t    LIBS=\"$LIBS -lsocket\", tcl_checkBoth=1)])\n    fi\n    if test \"$tcl_checkBoth\" = 1; then\n\ttk_oldLibs=$LIBS\n\tLIBS=\"$LIBS -lsocket -lnsl\"\n\tAC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])\n    fi\n    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,\n\t    [LIBS=\"$LIBS -lnsl\"])])\n\n    # TEA specific: Don't perform the eval of the libraries here because\n    # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS\n\n    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'\n    AC_SUBST(TCL_LIBS)\n    AC_SUBST(MATH_LIBS)\n])\n\n#--------------------------------------------------------------------\n# TEA_TCL_EARLY_FLAGS\n#\n#\tCheck for what flags are needed to be passed so the correct OS\n#\tfeatures are available.\n#\n# Arguments:\n#\tNone\n#\t\n# Results:\n#\n#\tMight define the following vars:\n#\t\t_ISOC99_SOURCE\n#\t\t_LARGEFILE64_SOURCE\n#\t\t_LARGEFILE_SOURCE64\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_TCL_EARLY_FLAG],[\n    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),\n\tAC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,\n\t    AC_TRY_COMPILE([[#define ]$1[ 1\n]$2], $3,\n\t\t[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,\n\t\t[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))\n    if test [\"x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}\" = \"xyes\"] ; then\n\tAC_DEFINE($1, 1, [Add the ]$1[ flag when building])\n\ttcl_flags=\"$tcl_flags $1\"\n    fi\n])\n\nAC_DEFUN([TEA_TCL_EARLY_FLAGS],[\n    AC_MSG_CHECKING([for required early compiler flags])\n    tcl_flags=\"\"\n    TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],\n\t[char *p = (char *)strtoll; char *q = (char *)strtoull;])\n    TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],\n\t[struct stat64 buf; int i = stat64(\"/\", &buf);])\n    TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],\n\t[char *p = (char *)open64;])\n    if test \"x${tcl_flags}\" = \"x\" ; then\n\tAC_MSG_RESULT([none])\n    else\n\tAC_MSG_RESULT([${tcl_flags}])\n    fi\n])\n\n#--------------------------------------------------------------------\n# TEA_TCL_64BIT_FLAGS\n#\n#\tCheck for what is defined in the way of 64-bit features.\n#\n# Arguments:\n#\tNone\n#\t\n# Results:\n#\n#\tMight define the following vars:\n#\t\tTCL_WIDE_INT_IS_LONG\n#\t\tTCL_WIDE_INT_TYPE\n#\t\tHAVE_STRUCT_DIRENT64\n#\t\tHAVE_STRUCT_STAT64\n#\t\tHAVE_TYPE_OFF64_T\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([TEA_TCL_64BIT_FLAGS], [\n    AC_MSG_CHECKING([for 64-bit integer type])\n    AC_CACHE_VAL(tcl_cv_type_64bit,[\n\ttcl_cv_type_64bit=none\n\t# See if the compiler knows natively about __int64\n\tAC_TRY_COMPILE(,[__int64 value = (__int64) 0;],\n\t    tcl_type_64bit=__int64, tcl_type_64bit=\"long long\")\n\t# See if we should use long anyway  Note that we substitute in the\n\t# type that is our current guess for a 64-bit type inside this check\n\t# program, so it should be modified only carefully...\n        AC_TRY_COMPILE(,[switch (0) { \n            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; \n        }],tcl_cv_type_64bit=${tcl_type_64bit})])\n    if test \"${tcl_cv_type_64bit}\" = none ; then\n\tAC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])\n\tAC_MSG_RESULT([using long])\n    elif test \"${tcl_cv_type_64bit}\" = \"__int64\" \\\n\t\t-a \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t# TEA specific: We actually want to use the default tcl.h checks in\n\t# this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*\n\tAC_MSG_RESULT([using Tcl header defaults])\n    else\n\tAC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},\n\t    [What type should be used to define wide integers?])\n\tAC_MSG_RESULT([${tcl_cv_type_64bit}])\n\n\t# Now check for auxiliary declarations\n\tAC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[\n\t    AC_TRY_COMPILE([#include <sys/types.h>\n#include <sys/dirent.h>],[struct dirent64 p;],\n\t\ttcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])\n\tif test \"x${tcl_cv_struct_dirent64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])\n\tfi\n\n\tAC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[\n\t    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;\n],\n\t\ttcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])\n\tif test \"x${tcl_cv_struct_stat64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])\n\tfi\n\n\tAC_CHECK_FUNCS(open64 lseek64)\n\tAC_MSG_CHECKING([for off64_t])\n\tAC_CACHE_VAL(tcl_cv_type_off64_t,[\n\t    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;\n],\n\t\ttcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])\n\tdnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the\n\tdnl functions lseek64 and open64 are defined.\n\tif test \"x${tcl_cv_type_off64_t}\" = \"xyes\" && \\\n\t        test \"x${ac_cv_func_lseek64}\" = \"xyes\" && \\\n\t        test \"x${ac_cv_func_open64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])\n\t    AC_MSG_RESULT([yes])\n\telse\n\t    AC_MSG_RESULT([no])\n\tfi\n    fi\n])\n\n##\n## Here ends the standard Tcl configuration bits and starts the\n## TEA specific functions\n##\n\n#------------------------------------------------------------------------\n# TEA_INIT --\n#\n#\tInit various Tcl Extension Architecture (TEA) variables.\n#\tThis should be the first called TEA_* macro.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tCYGPATH\n#\t\tEXEEXT\n#\tDefines only:\n#\t\tTEA_VERSION\n#\t\tTEA_INITED\n#\t\tTEA_PLATFORM (windows or unix)\n#\n# \"cygpath\" is used on windows to generate native path names for include\n# files. These variables should only be used with the compiler and linker\n# since they generate native path names.\n#\n# EXEEXT\n#\tSelect the executable extension based on the host type.  This\n#\tis a lightweight replacement for AC_EXEEXT that doesn't require\n#\ta compiler.\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_INIT], [\n    # TEA extensions pass this us the version of TEA they think they\n    # are compatible with.\n    TEA_VERSION=\"3.7\"\n\n    AC_MSG_CHECKING([for correct TEA configuration])\n    if test x\"${PACKAGE_NAME}\" = x ; then\n\tAC_MSG_ERROR([\nThe PACKAGE_NAME variable must be defined by your TEA configure.in])\n    fi\n    if test x\"$1\" = x ; then\n\tAC_MSG_ERROR([\nTEA version not specified.])\n    elif test \"$1\" != \"${TEA_VERSION}\" ; then\n\tAC_MSG_RESULT([warning: requested TEA version \"$1\", have \"${TEA_VERSION}\"])\n    else\n\tAC_MSG_RESULT([ok (TEA ${TEA_VERSION})])\n    fi\n    case \"`uname -s`\" in\n\t*win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*)\n\t    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)\n\t    EXEEXT=\".exe\"\n\t    TEA_PLATFORM=\"windows\"\n\t    ;;\n\t*)\n\t    CYGPATH=echo\n\t    EXEEXT=\"\"\n\t    TEA_PLATFORM=\"unix\"\n\t    ;;\n    esac\n\n    # Check if exec_prefix is set. If not use fall back to prefix.\n    # Note when adjusted, so that TEA_PREFIX can correct for this.\n    # This is needed for recursive configures, since autoconf propagates\n    # $prefix, but not $exec_prefix (doh!).\n    if test x$exec_prefix = xNONE ; then\n\texec_prefix_default=yes\n\texec_prefix=$prefix\n    fi\n\n    AC_SUBST(EXEEXT)\n    AC_SUBST(CYGPATH)\n\n    # This package name must be replaced statically for AC_SUBST to work\n    AC_SUBST(PKG_LIB_FILE)\n    # Substitute STUB_LIB_FILE in case package creates a stub library too.\n    AC_SUBST(PKG_STUB_LIB_FILE)\n\n    # We AC_SUBST these here to ensure they are subst'ed,\n    # in case the user doesn't call TEA_ADD_...\n    AC_SUBST(PKG_STUB_SOURCES)\n    AC_SUBST(PKG_STUB_OBJECTS)\n    AC_SUBST(PKG_TCL_SOURCES)\n    AC_SUBST(PKG_HEADERS)\n    AC_SUBST(PKG_INCLUDES)\n    AC_SUBST(PKG_LIBS)\n    AC_SUBST(PKG_CFLAGS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_SOURCES --\n#\n#\tSpecify one or more source files.  Users should check for\n#\tthe right platform before adding to their list.\n#\tIt is not important to specify the directory, as long as it is\n#\tin the generic, win or unix subdirectory of $(srcdir).\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_SOURCES\n#\t\tPKG_OBJECTS\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_SOURCES], [\n    vars=\"$@\"\n    for i in $vars; do\n\tcase $i in\n\t    [\\$]*)\n\t\t# allow $-var names\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $i\"\n\t\t;;\n\t    *)\n\t\t# check for existence - allows for generic/win/unix VPATH\n\t\t# To add more dirs here (like 'src'), you have to update VPATH\n\t\t# in Makefile.in as well\n\t\tif test ! -f \"${srcdir}/$i\" -a ! -f \"${srcdir}/generic/$i\" \\\n\t\t    -a ! -f \"${srcdir}/win/$i\" -a ! -f \"${srcdir}/unix/$i\" \\\n\t\t    ; then\n\t\t    AC_MSG_ERROR([could not find source file '$i'])\n\t\tfi\n\t\tPKG_SOURCES=\"$PKG_SOURCES $i\"\n\t\t# this assumes it is in a VPATH dir\n\t\ti=`basename $i`\n\t\t# handle user calling this before or after TEA_SETUP_COMPILER\n\t\tif test x\"${OBJEXT}\" != x ; then\n\t\t    j=\"`echo $i | sed -e 's/\\.[[^.]]*$//'`.${OBJEXT}\"\n\t\telse\n\t\t    j=\"`echo $i | sed -e 's/\\.[[^.]]*$//'`.\\${OBJEXT}\"\n\t\tfi\n\t\tPKG_OBJECTS=\"$PKG_OBJECTS $j\"\n\t\t;;\n\tesac\n    done\n    AC_SUBST(PKG_SOURCES)\n    AC_SUBST(PKG_OBJECTS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_STUB_SOURCES --\n#\n#\tSpecify one or more source files.  Users should check for\n#\tthe right platform before adding to their list.\n#\tIt is not important to specify the directory, as long as it is\n#\tin the generic, win or unix subdirectory of $(srcdir).\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_STUB_SOURCES\n#\t\tPKG_STUB_OBJECTS\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_STUB_SOURCES], [\n    vars=\"$@\"\n    for i in $vars; do\n\t# check for existence - allows for generic/win/unix VPATH\n\tif test ! -f \"${srcdir}/$i\" -a ! -f \"${srcdir}/generic/$i\" \\\n\t    -a ! -f \"${srcdir}/win/$i\" -a ! -f \"${srcdir}/unix/$i\" \\\n\t    ; then\n\t    AC_MSG_ERROR([could not find stub source file '$i'])\n\tfi\n\tPKG_STUB_SOURCES=\"$PKG_STUB_SOURCES $i\"\n\t# this assumes it is in a VPATH dir\n\ti=`basename $i`\n\t# handle user calling this before or after TEA_SETUP_COMPILER\n\tif test x\"${OBJEXT}\" != x ; then\n\t    j=\"`echo $i | sed -e 's/\\.[[^.]]*$//'`.${OBJEXT}\"\n\telse\n\t    j=\"`echo $i | sed -e 's/\\.[[^.]]*$//'`.\\${OBJEXT}\"\n\tfi\n\tPKG_STUB_OBJECTS=\"$PKG_STUB_OBJECTS $j\"\n    done\n    AC_SUBST(PKG_STUB_SOURCES)\n    AC_SUBST(PKG_STUB_OBJECTS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_TCL_SOURCES --\n#\n#\tSpecify one or more Tcl source files.  These should be platform\n#\tindependent runtime files.\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_TCL_SOURCES\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_TCL_SOURCES], [\n    vars=\"$@\"\n    for i in $vars; do\n\t# check for existence, be strict because it is installed\n\tif test ! -f \"${srcdir}/$i\" ; then\n\t    AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])\n\tfi\n\tPKG_TCL_SOURCES=\"$PKG_TCL_SOURCES $i\"\n    done\n    AC_SUBST(PKG_TCL_SOURCES)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_HEADERS --\n#\n#\tSpecify one or more source headers.  Users should check for\n#\tthe right platform before adding to their list.\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_HEADERS\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_HEADERS], [\n    vars=\"$@\"\n    for i in $vars; do\n\t# check for existence, be strict because it is installed\n\tif test ! -f \"${srcdir}/$i\" ; then\n\t    AC_MSG_ERROR([could not find header file '${srcdir}/$i'])\n\tfi\n\tPKG_HEADERS=\"$PKG_HEADERS $i\"\n    done\n    AC_SUBST(PKG_HEADERS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_INCLUDES --\n#\n#\tSpecify one or more include dirs.  Users should check for\n#\tthe right platform before adding to their list.\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_INCLUDES\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_INCLUDES], [\n    vars=\"$@\"\n    for i in $vars; do\n\tPKG_INCLUDES=\"$PKG_INCLUDES $i\"\n    done\n    AC_SUBST(PKG_INCLUDES)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_LIBS --\n#\n#\tSpecify one or more libraries.  Users should check for\n#\tthe right platform before adding to their list.  For Windows,\n#\tlibraries provided in \"foo.lib\" format will be converted to\n#\t\"-lfoo\" when using GCC (mingw).\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_LIBS\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_LIBS], [\n    vars=\"$@\"\n    for i in $vars; do\n\tif test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" = \"yes\" ; then\n\t    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib\n\t    i=`echo \"$i\" | sed -e 's/^\\([[^-]].*\\)\\.lib[$]/-l\\1/i'`\n\tfi\n\tPKG_LIBS=\"$PKG_LIBS $i\"\n    done\n    AC_SUBST(PKG_LIBS)\n])\n\n#------------------------------------------------------------------------\n# TEA_ADD_CFLAGS --\n#\n#\tSpecify one or more CFLAGS.  Users should check for\n#\tthe right platform before adding to their list.\n#\n# Arguments:\n#\tone or more file names\n#\n# Results:\n#\n#\tDefines and substs the following vars:\n#\t\tPKG_CFLAGS\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_ADD_CFLAGS], [\n    PKG_CFLAGS=\"$PKG_CFLAGS $@\"\n    AC_SUBST(PKG_CFLAGS)\n])\n\n#------------------------------------------------------------------------\n# TEA_PREFIX --\n#\n#\tHandle the --prefix=... option by defaulting to what Tcl gave\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tIf --prefix or --exec-prefix was not specified, $prefix and\n#\t$exec_prefix will be set to the values given to Tcl when it was\n#\tconfigured.\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_PREFIX], [\n    if test \"${prefix}\" = \"NONE\"; then\n\tprefix_default=yes\n\tif test x\"${TCL_PREFIX}\" != x; then\n\t    AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])\n\t    prefix=${TCL_PREFIX}\n\telse\n\t    AC_MSG_NOTICE([--prefix defaulting to /usr/local])\n\t    prefix=/usr/local\n\tfi\n    fi\n    if test \"${exec_prefix}\" = \"NONE\" -a x\"${prefix_default}\" = x\"yes\" \\\n\t-o x\"${exec_prefix_default}\" = x\"yes\" ; then\n\tif test x\"${TCL_EXEC_PREFIX}\" != x; then\n\t    AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])\n\t    exec_prefix=${TCL_EXEC_PREFIX}\n\telse\n\t    AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])\n\t    exec_prefix=$prefix\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_SETUP_COMPILER_CC --\n#\n#\tDo compiler checks the way we want.  This is just a replacement\n#\tfor AC_PROG_CC in TEA configure.in files to make them cleaner.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tSets up CC var and other standard bits we need to make executables.\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_SETUP_COMPILER_CC], [\n    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)\n    # in this macro, they need to go into TEA_SETUP_COMPILER instead.\n\n    # If the user did not set CFLAGS, set it now to keep\n    # the AC_PROG_CC macro from adding \"-g -O2\".\n    if test \"${CFLAGS+set}\" != \"set\" ; then\n\tCFLAGS=\"\"\n    fi\n\n    AC_PROG_CC\n    AC_PROG_CPP\n\n    AC_PROG_INSTALL\n\n    #--------------------------------------------------------------------\n    # Checks to see if the make program sets the $MAKE variable.\n    #--------------------------------------------------------------------\n\n    AC_PROG_MAKE_SET\n\n    #--------------------------------------------------------------------\n    # Find ranlib\n    #--------------------------------------------------------------------\n\n    AC_PROG_RANLIB\n\n    #--------------------------------------------------------------------\n    # Determines the correct binary file extension (.o, .obj, .exe etc.)\n    #--------------------------------------------------------------------\n\n    AC_OBJEXT\n    AC_EXEEXT\n])\n\n#------------------------------------------------------------------------\n# TEA_SETUP_COMPILER --\n#\n#\tDo compiler checks that use the compiler.  This must go after\n#\tTEA_SETUP_COMPILER_CC, which does the actual compiler check.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tSets up CC var and other standard bits we need to make executables.\n#------------------------------------------------------------------------\nAC_DEFUN([TEA_SETUP_COMPILER], [\n    # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.\n    AC_REQUIRE([TEA_SETUP_COMPILER_CC])\n\n    #------------------------------------------------------------------------\n    # If we're using GCC, see if the compiler understands -pipe. If so, use it.\n    # It makes compiling go faster.  (This is only a performance feature.)\n    #------------------------------------------------------------------------\n\n    if test -z \"$no_pipe\" -a -n \"$GCC\"; then\n\tAC_CACHE_CHECK([if the compiler understands -pipe],\n\t    tcl_cv_cc_pipe, [\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -pipe\"\n\t    AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)\n\t    CFLAGS=$hold_cflags])\n\tif test $tcl_cv_cc_pipe = yes; then\n\t    CFLAGS=\"$CFLAGS -pipe\"\n\tfi\n    fi\n\n    #--------------------------------------------------------------------\n    # Common compiler flag setup\n    #--------------------------------------------------------------------\n\n    AC_C_BIGENDIAN\n    if test \"${TEA_PLATFORM}\" = \"unix\" ; then\n\tTEA_TCL_LINK_LIBS\n\tTEA_MISSING_POSIX_HEADERS\n\t# Let the user call this, because if it triggers, they will\n\t# need a compat/strtod.c that is correct.  Users can also\n\t# use Tcl_GetDouble(FromObj) instead.\n\t#TEA_BUGGY_STRTOD\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_MAKE_LIB --\n#\n#\tGenerate a line that can be used to build a shared/unshared library\n#\tin a platform independent manner.\n#\n# Arguments:\n#\tnone\n#\n#\tRequires:\n#\n# Results:\n#\n#\tDefines the following vars:\n#\tCFLAGS -\tDone late here to note disturb other AC macros\n#       MAKE_LIB -      Command to execute to build the Tcl library;\n#                       differs depending on whether or not Tcl is being\n#                       compiled as a shared library.\n#\tMAKE_SHARED_LIB\tMakefile rule for building a shared library\n#\tMAKE_STATIC_LIB\tMakefile rule for building a static library\n#\tMAKE_STUB_LIB\tMakefile rule for building a stub library\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_MAKE_LIB], [\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \"$GCC\" != \"yes\"; then\n\tMAKE_STATIC_LIB=\"\\${STLIB_LD} -out:\\[$]@ \\$(PKG_OBJECTS)\"\n\tMAKE_SHARED_LIB=\"\\${SHLIB_LD} \\${SHLIB_LD_LIBS} \\${LDFLAGS_DEFAULT} -out:\\[$]@ \\$(PKG_OBJECTS)\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} -out:\\[$]@ \\$(PKG_STUB_OBJECTS)\"\n    else\n\tMAKE_STATIC_LIB=\"\\${STLIB_LD} \\[$]@ \\$(PKG_OBJECTS)\"\n\tMAKE_SHARED_LIB=\"\\${SHLIB_LD} -o \\[$]@ \\$(PKG_OBJECTS) \\${SHLIB_LD_LIBS}\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} \\[$]@ \\$(PKG_STUB_OBJECTS)\"\n    fi\n\n    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\tMAKE_LIB=\"${MAKE_SHARED_LIB} \"\n    else\n\tMAKE_LIB=\"${MAKE_STATIC_LIB} \"\n    fi\n\n    #--------------------------------------------------------------------\n    # Shared libraries and static libraries have different names.\n    # Use the double eval to make sure any variables in the suffix is\n    # substituted. (@@@ Might not be necessary anymore)\n    #--------------------------------------------------------------------\n\n    if test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\tif test \"${SHARED_BUILD}\" = \"1\" ; then\n\t    # We force the unresolved linking of symbols that are really in\n\t    # the private libraries of Tcl and Tk.\n\t    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\\"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\\\"\"\n\t    if test x\"${TK_BIN_DIR}\" != x ; then\n\t\tSHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\\"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\\\"\"\n\t    fi\n\t    eval eval \"PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}\"\n\telse\n\t    eval eval \"PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}\"\n\tfi\n\t# Some packages build their own stubs libraries\n\teval eval \"PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}\"\n\tif test \"$GCC\" = \"yes\"; then\n\t    PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}\n\tfi\n\t# These aren't needed on Windows (either MSVC or gcc)\n\tRANLIB=:\n\tRANLIB_STUB=:\n    else\n\tRANLIB_STUB=\"${RANLIB}\"\n\tif test \"${SHARED_BUILD}\" = \"1\" ; then\n\t    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}\"\n\t    if test x\"${TK_BIN_DIR}\" != x ; then\n\t\tSHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}\"\n\t    fi\n\t    eval eval \"PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}\"\n\t    RANLIB=:\n\telse\n\t    eval eval \"PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}\"\n\tfi\n\t# Some packages build their own stubs libraries\n\teval eval \"PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}\"\n    fi\n\n    # These are escaped so that only CFLAGS is picked up at configure time.\n    # The other values will be substituted at make time.\n    CFLAGS=\"${CFLAGS} \\${CFLAGS_DEFAULT} \\${CFLAGS_WARNING}\"\n    if test \"${SHARED_BUILD}\" = \"1\" ; then\n\tCFLAGS=\"${CFLAGS} \\${SHLIB_CFLAGS}\"\n    fi\n\n    AC_SUBST(MAKE_LIB)\n    AC_SUBST(MAKE_SHARED_LIB)\n    AC_SUBST(MAKE_STATIC_LIB)\n    AC_SUBST(MAKE_STUB_LIB)\n    AC_SUBST(RANLIB_STUB)\n])\n\n#------------------------------------------------------------------------\n# TEA_LIB_SPEC --\n#\n#\tCompute the name of an existing object library located in libdir\n#\tfrom the given base name and produce the appropriate linker flags.\n#\n# Arguments:\n#\tbasename\tThe base name of the library without version\n#\t\t\tnumbers, extensions, or \"lib\" prefixes.\n#\textra_dir\tExtra directory in which to search for the\n#\t\t\tlibrary.  This location is used first, then\n#\t\t\t$prefix/$exec-prefix, then some defaults.\n#\n# Requires:\n#\tTEA_INIT and TEA_PREFIX must be called first.\n#\n# Results:\n#\n#\tDefines the following vars:\n#\t\t${basename}_LIB_NAME\tThe computed library name.\n#\t\t${basename}_LIB_SPEC\tThe computed linker flags.\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_LIB_SPEC], [\n    AC_MSG_CHECKING([for $1 library])\n\n    # Look in exec-prefix for the library (defined by TEA_PREFIX).\n\n    tea_lib_name_dir=\"${exec_prefix}/lib\"\n\n    # Or in a user-specified location.\n\n    if test x\"$2\" != x ; then\n\ttea_extra_lib_dir=$2\n    else\n\ttea_extra_lib_dir=NONE\n    fi\n\n    for i in \\\n\t    `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \\\n\t    `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \\\n\t    `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \\\n\t    `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \\\n\t    `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \\\n\t    `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \\\n\t    `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \\\n\t    `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do\n\tif test -f \"$i\" ; then\n\t    tea_lib_name_dir=`dirname $i`\n\t    $1_LIB_NAME=`basename $i`\n\t    $1_LIB_PATH_NAME=$i\n\t    break\n\tfi\n    done\n\n    if test \"${TEA_PLATFORM}\" = \"windows\"; then\n\t$1_LIB_SPEC=\\\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\\\"\n    else\n\t# Strip off the leading \"lib\" and trailing \".a\" or \".so\"\n\n\ttea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\\.[[^.]]*$//' -e 's/\\.so.*//'`\n\t$1_LIB_SPEC=\"-L${tea_lib_name_dir} -l${tea_lib_name_lib}\"\n    fi\n\n    if test \"x${$1_LIB_NAME}\" = x ; then\n\tAC_MSG_ERROR([not found])\n    else\n\tAC_MSG_RESULT([${$1_LIB_SPEC}])\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_PRIVATE_TCL_HEADERS --\n#\n#\tLocate the private Tcl include files\n#\n# Arguments:\n#\n#\tRequires:\n#\t\tTCL_SRC_DIR\tAssumes that TEA_LOAD_TCLCONFIG has\n#\t\t\t\talready been called.\n#\n# Results:\n#\n#\tSubsts the following vars:\n#\t\tTCL_TOP_DIR_NATIVE\n#\t\tTCL_INCLUDES\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [\n    # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}\n    AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS])\n    AC_MSG_CHECKING([for Tcl private include files])\n\n    TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`\n    TCL_TOP_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}\\\"\n\n    # Check to see if tcl<Plat>Port.h isn't already with the public headers\n    # Don't look for tclInt.h because that resides with tcl.h in the core\n    # sources, but the <plat>Port headers are in a different directory\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \\\n\t-f \"${ac_cv_c_tclh}/tclWinPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    elif test \"${TEA_PLATFORM}\" = \"unix\" -a \\\n\t-f \"${ac_cv_c_tclh}/tclUnixPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    else\n\tTCL_GENERIC_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/generic\\\"\n\tif test \"${TEA_PLATFORM}\" = \"windows\"; then\n\t    TCL_PLATFORM_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/win\\\"\n\telse\n\t    TCL_PLATFORM_DIR_NATIVE=\\\"${TCL_SRC_DIR_NATIVE}/unix\\\"\n\tfi\n\t# Overwrite the previous TCL_INCLUDES as this should capture both\n\t# public and private headers in the same set.\n\t# We want to ensure these are substituted so as not to require\n\t# any *_NATIVE vars be defined in the Makefile\n\tTCL_INCLUDES=\"-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}\"\n\tif test \"`uname -s`\" = \"Darwin\"; then\n            # If Tcl was built as a framework, attempt to use\n            # the framework's Headers and PrivateHeaders directories\n            case ${TCL_DEFS} in\n\t    \t*TCL_FRAMEWORK*)\n\t\t    if test -d \"${TCL_BIN_DIR}/Headers\" -a \\\n\t\t\t    -d \"${TCL_BIN_DIR}/PrivateHeaders\"; then\n\t\t\tTCL_INCLUDES=\"-I\\\"${TCL_BIN_DIR}/Headers\\\" -I\\\"${TCL_BIN_DIR}/PrivateHeaders\\\" ${TCL_INCLUDES}\"\n\t\t    else\n\t\t\tTCL_INCLUDES=\"${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo \"${TCL_INCLUDE_SPEC}\" | sed -e 's/Headers/PrivateHeaders/'`\"\n\t\t    fi\n\t            ;;\n\t    esac\n\t    result=\"Using ${TCL_INCLUDES}\"\n\telse\n\t    if test ! -f \"${TCL_SRC_DIR}/generic/tclInt.h\" ; then\n\t\tAC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}])\n\t    fi\n\t    result=\"Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}\"\n\tfi\n    fi\n\n    AC_SUBST(TCL_TOP_DIR_NATIVE)\n\n    AC_SUBST(TCL_INCLUDES)\n    AC_MSG_RESULT([${result}])\n])\n\n#------------------------------------------------------------------------\n# TEA_PUBLIC_TCL_HEADERS --\n#\n#\tLocate the installed public Tcl header files\n#\n# Arguments:\n#\tNone.\n#\n# Requires:\n#\tCYGPATH must be set\n#\n# Results:\n#\n#\tAdds a --with-tclinclude switch to configure.\n#\tResult is cached.\n#\n#\tSubsts the following vars:\n#\t\tTCL_INCLUDES\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [\n    AC_MSG_CHECKING([for Tcl public headers])\n\n    AC_ARG_WITH(tclinclude, [  --with-tclinclude       directory containing the public Tcl header files], with_tclinclude=${withval})\n\n    AC_CACHE_VAL(ac_cv_c_tclh, [\n\t# Use the value from --with-tclinclude, if it was given\n\n\tif test x\"${with_tclinclude}\" != x ; then\n\t    if test -f \"${with_tclinclude}/tcl.h\" ; then\n\t\tac_cv_c_tclh=${with_tclinclude}\n\t    else\n\t\tAC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])\n\t    fi\n\telse\n\t    if test \"`uname -s`\" = \"Darwin\"; then\n\t\t# If Tcl was built as a framework, attempt to use\n\t\t# the framework's Headers directory\n\t\tcase ${TCL_DEFS} in\n\t\t    *TCL_FRAMEWORK*)\n\t\t\tlist=\"`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`\"\n\t\t\t;;\n\t\tesac\n\t    fi\n\n\t    # Look in the source dir only if Tcl is not installed,\n\t    # and in that situation, look there before installed locations.\n\t    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n\t\tlist=\"$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`\"\n\t    fi\n\n\t    # Check order: pkg --prefix location, Tcl's --prefix location,\n\t    # relative to directory of tclConfig.sh.\n\n\t    eval \"temp_includedir=${includedir}\"\n\t    list=\"$list \\\n\t\t`ls -d ${temp_includedir}        2>/dev/null` \\\n\t\t`ls -d ${TCL_PREFIX}/include     2>/dev/null` \\\n\t\t`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`\"\n\t    if test \"${TEA_PLATFORM}\" != \"windows\" -o \"$GCC\" = \"yes\"; then\n\t\tlist=\"$list /usr/local/include /usr/include\"\n\t\tif test x\"${TCL_INCLUDE_SPEC}\" != x ; then\n\t\t    d=`echo \"${TCL_INCLUDE_SPEC}\" | sed -e 's/^-I//'`\n\t\t    list=\"$list `ls -d ${d} 2>/dev/null`\"\n\t\tfi\n\t    fi\n\t    for i in $list ; do\n\t\tif test -f \"$i/tcl.h\" ; then\n\t\t    ac_cv_c_tclh=$i\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    ])\n\n    # Print a message based on how we determined the include path\n\n    if test x\"${ac_cv_c_tclh}\" = x ; then\n\tAC_MSG_ERROR([tcl.h not found.  Please specify its location with --with-tclinclude])\n    else\n\tAC_MSG_RESULT([${ac_cv_c_tclh}])\n    fi\n\n    # Convert to a native path and substitute into the output files.\n\n    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`\n\n    TCL_INCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\n    AC_SUBST(TCL_INCLUDES)\n])\n\n#------------------------------------------------------------------------\n# TEA_PRIVATE_TK_HEADERS --\n#\n#\tLocate the private Tk include files\n#\n# Arguments:\n#\n#\tRequires:\n#\t\tTK_SRC_DIR\tAssumes that TEA_LOAD_TKCONFIG has\n#\t\t\t\t already been called.\n#\n# Results:\n#\n#\tSubsts the following vars:\n#\t\tTK_INCLUDES\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PRIVATE_TK_HEADERS], [\n    # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}\n    AC_REQUIRE([TEA_PUBLIC_TK_HEADERS])\n    AC_MSG_CHECKING([for Tk private include files])\n\n    TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`\n    TK_TOP_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}\\\"\n\n    # Check to see if tk<Plat>Port.h isn't already with the public headers\n    # Don't look for tkInt.h because that resides with tk.h in the core\n    # sources, but the <plat>Port headers are in a different directory\n    if test \"${TEA_PLATFORM}\" = \"windows\" -a \\\n\t-f \"${ac_cv_c_tkh}/tkWinPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    elif test \"${TEA_PLATFORM}\" = \"unix\" -a \\\n\t-f \"${ac_cv_c_tkh}/tkUnixPort.h\"; then\n\tresult=\"private headers found with public headers\"\n    else\n\tTK_GENERIC_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/generic\\\"\n\tTK_XLIB_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/xlib\\\"\n\tif test \"${TEA_PLATFORM}\" = \"windows\"; then\n\t    TK_PLATFORM_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/win\\\"\n\telse\n\t    TK_PLATFORM_DIR_NATIVE=\\\"${TK_SRC_DIR_NATIVE}/unix\\\"\n\tfi\n\t# Overwrite the previous TK_INCLUDES as this should capture both\n\t# public and private headers in the same set.\n\t# We want to ensure these are substituted so as not to require\n\t# any *_NATIVE vars be defined in the Makefile\n\tTK_INCLUDES=\"-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}\"\n\t# Detect and add ttk subdir\n\tif test -d \"${TK_SRC_DIR}/generic/ttk\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I\\\"${TK_SRC_DIR_NATIVE}/generic/ttk\\\"\"\n\tfi\n\tif test \"${TEA_WINDOWINGSYSTEM}\" != \"x11\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I${TK_XLIB_DIR_NATIVE}\"\n\tfi\n\tif test \"${TEA_WINDOWINGSYSTEM}\" = \"aqua\"; then\n\t   TK_INCLUDES=\"${TK_INCLUDES} -I\\\"${TK_SRC_DIR_NATIVE}/macosx\\\"\"\n\tfi\n\tif test \"`uname -s`\" = \"Darwin\"; then\n\t    # If Tk was built as a framework, attempt to use\n\t    # the framework's Headers and PrivateHeaders directories\n\t    case ${TK_DEFS} in\n\t\t*TK_FRAMEWORK*)\n\t\t\tif test -d \"${TK_BIN_DIR}/Headers\" -a \\\n\t\t\t\t-d \"${TK_BIN_DIR}/PrivateHeaders\"; then\n\t\t\t    TK_INCLUDES=\"-I\\\"${TK_BIN_DIR}/Headers\\\" -I\\\"${TK_BIN_DIR}/PrivateHeaders\\\" ${TK_INCLUDES}\"\n\t\t\telse\n\t\t\t    TK_INCLUDES=\"${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo \"${TK_INCLUDE_SPEC}\" | sed -e 's/Headers/PrivateHeaders/'`\"\n\t\t\tfi\n\t\t\t;;\n\t    esac\n\t    result=\"Using ${TK_INCLUDES}\"\n\telse\n\t    if test ! -f \"${TK_SRC_DIR}/generic/tkInt.h\" ; then\n\t       AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}])\n\t    fi\n\t    result=\"Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}\"\n\tfi\n    fi\n\n    AC_SUBST(TK_TOP_DIR_NATIVE)\n    AC_SUBST(TK_XLIB_DIR_NATIVE)\n\n    AC_SUBST(TK_INCLUDES)\n    AC_MSG_RESULT([${result}])\n])\n\n#------------------------------------------------------------------------\n# TEA_PUBLIC_TK_HEADERS --\n#\n#\tLocate the installed public Tk header files\n#\n# Arguments:\n#\tNone.\n#\n# Requires:\n#\tCYGPATH must be set\n#\n# Results:\n#\n#\tAdds a --with-tkinclude switch to configure.\n#\tResult is cached.\n#\n#\tSubsts the following vars:\n#\t\tTK_INCLUDES\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PUBLIC_TK_HEADERS], [\n    AC_MSG_CHECKING([for Tk public headers])\n\n    AC_ARG_WITH(tkinclude, [  --with-tkinclude        directory containing the public Tk header files], with_tkinclude=${withval})\n\n    AC_CACHE_VAL(ac_cv_c_tkh, [\n\t# Use the value from --with-tkinclude, if it was given\n\n\tif test x\"${with_tkinclude}\" != x ; then\n\t    if test -f \"${with_tkinclude}/tk.h\" ; then\n\t\tac_cv_c_tkh=${with_tkinclude}\n\t    else\n\t\tAC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])\n\t    fi\n\telse\n\t    if test \"`uname -s`\" = \"Darwin\"; then\n\t\t# If Tk was built as a framework, attempt to use\n\t\t# the framework's Headers directory.\n\t\tcase ${TK_DEFS} in\n\t\t    *TK_FRAMEWORK*)\n\t\t\tlist=\"`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`\"\n\t\t\t;;\n\t\tesac\n\t    fi\n\n\t    # Look in the source dir only if Tk is not installed,\n\t    # and in that situation, look there before installed locations.\n\t    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n\t\tlist=\"$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`\"\n\t    fi\n\n\t    # Check order: pkg --prefix location, Tk's --prefix location,\n\t    # relative to directory of tkConfig.sh, Tcl's --prefix location, \n\t    # relative to directory of tclConfig.sh.\n\n\t    eval \"temp_includedir=${includedir}\"\n\t    list=\"$list \\\n\t\t`ls -d ${temp_includedir}        2>/dev/null` \\\n\t\t`ls -d ${TK_PREFIX}/include      2>/dev/null` \\\n\t\t`ls -d ${TK_BIN_DIR}/../include  2>/dev/null` \\\n\t\t`ls -d ${TCL_PREFIX}/include     2>/dev/null` \\\n\t\t`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`\"\n\t    if test \"${TEA_PLATFORM}\" != \"windows\" -o \"$GCC\" = \"yes\"; then\n\t\tlist=\"$list /usr/local/include /usr/include\"\n\t    fi\n\t    for i in $list ; do\n\t\tif test -f \"$i/tk.h\" ; then\n\t\t    ac_cv_c_tkh=$i\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    ])\n\n    # Print a message based on how we determined the include path\n\n    if test x\"${ac_cv_c_tkh}\" = x ; then\n\tAC_MSG_ERROR([tk.h not found.  Please specify its location with --with-tkinclude])\n    else\n\tAC_MSG_RESULT([${ac_cv_c_tkh}])\n    fi\n\n    # Convert to a native path and substitute into the output files.\n\n    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`\n\n    TK_INCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\n    AC_SUBST(TK_INCLUDES)\n\n    if test \"${TEA_WINDOWINGSYSTEM}\" != \"x11\"; then\n\t# On Windows and Aqua, we need the X compat headers\n\tAC_MSG_CHECKING([for X11 header files])\n\tif test ! -r \"${INCLUDE_DIR_NATIVE}/X11/Xlib.h\"; then\n\t    INCLUDE_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/xlib`\"\n\t    TK_XINCLUDES=-I\\\"${INCLUDE_DIR_NATIVE}\\\"\n\t    AC_SUBST(TK_XINCLUDES)\n\tfi\n\tAC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_PATH_CONFIG --\n#\n#\tLocate the ${1}Config.sh file and perform a sanity check on\n#\tthe ${1} compile flags.  These are used by packages like\n#\t[incr Tk] that load *Config.sh files from more than Tcl and Tk.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-$1=...\n#\n#\tDefines the following vars:\n#\t\t$1_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe $1Config.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PATH_CONFIG], [\n    #\n    # Ok, lets find the $1 configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-$1\n    #\n\n    if test x\"${no_$1}\" = x ; then\n\t# we reset no_$1 in case something fails here\n\tno_$1=true\n\tAC_ARG_WITH($1, [  --with-$1              directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})\n\tAC_MSG_CHECKING([for $1 configuration])\n\tAC_CACHE_VAL(ac_cv_c_$1config,[\n\n\t    # First check to see if --with-$1 was specified.\n\t    if test x\"${with_$1config}\" != x ; then\n\t\tcase ${with_$1config} in\n\t\t    */$1Config.sh )\n\t\t\tif test -f ${with_$1config}; then\n\t\t\t    AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])\n\t\t\t    with_$1config=`echo ${with_$1config} | sed 's!/$1Config\\.sh$!!'`\n\t\t\tfi;;\n\t\tesac\n\t\tif test -f \"${with_$1config}/$1Config.sh\" ; then\n\t\t    ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`\n\t\telse\n\t\t    AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private $1 installation\n\t    if test x\"${ac_cv_c_$1config}\" = x ; then\n\t\tfor i in \\\n\t\t\t../$1 \\\n\t\t\t`ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../$1 \\\n\t\t\t`ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../$1 \\\n\t\t\t`ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t${srcdir}/../$1 \\\n\t\t\t`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/$1Config.sh\" ; then\n\t\t\tac_cv_c_$1config=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\t    if test -f \"$i/unix/$1Config.sh\" ; then\n\t\t\tac_cv_c_$1config=`(cd $i/unix; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_$1config}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/$1Config.sh\" ; then\n\t\t\tac_cv_c_$1config=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_$1config}\" = x ; then\n\t    $1_BIN_DIR=\"# no $1 configs found\"\n\t    AC_MSG_WARN([Cannot find $1 configuration definitions])\n\t    exit 0\n\telse\n\t    no_$1=\n\t    $1_BIN_DIR=${ac_cv_c_$1config}\n\t    AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# TEA_LOAD_CONFIG --\n#\n#\tLoad the $1Config.sh file\n#\n# Arguments:\n#\t\n#\tRequires the following vars to be set:\n#\t\t$1_BIN_DIR\n#\n# Results:\n#\n#\tSubst the following vars:\n#\t\t$1_SRC_DIR\n#\t\t$1_LIB_FILE\n#\t\t$1_LIB_SPEC\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_LOAD_CONFIG], [\n    AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])\n\n    if test -f \"${$1_BIN_DIR}/$1Config.sh\" ; then\n        AC_MSG_RESULT([loading])\n\t. \"${$1_BIN_DIR}/$1Config.sh\"\n    else\n        AC_MSG_RESULT([file not found])\n    fi\n\n    #\n    # If the $1_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable $1_LIB_SPEC will be set to the value\n    # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC\n    # instead of $1_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    #\n\n    if test -f \"${$1_BIN_DIR}/Makefile\" ; then\n\tAC_MSG_WARN([Found Makefile - using build library specs for $1])\n        $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}\n        $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}\n        $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}\n    fi\n\n    AC_SUBST($1_VERSION)\n    AC_SUBST($1_BIN_DIR)\n    AC_SUBST($1_SRC_DIR)\n\n    AC_SUBST($1_LIB_FILE)\n    AC_SUBST($1_LIB_SPEC)\n\n    AC_SUBST($1_STUB_LIB_FILE)\n    AC_SUBST($1_STUB_LIB_SPEC)\n    AC_SUBST($1_STUB_LIB_PATH)\n])\n\n#------------------------------------------------------------------------\n# TEA_PATH_CELIB --\n#\n#\tLocate Keuchel's celib emulation layer for targeting Win/CE\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-celib=...\n#\n#\tDefines the following vars:\n#\t\tCELIB_DIR\tFull path to the directory containing\n#\t\t\t\tthe include and platform lib files\n#------------------------------------------------------------------------\n\nAC_DEFUN([TEA_PATH_CELIB], [\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-celib\n\n    if test x\"${no_celib}\" = x ; then\n\t# we reset no_celib in case something fails here\n\tno_celib=true\n\tAC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR], with_celibconfig=${withval})\n\tAC_MSG_CHECKING([for Windows/CE celib directory])\n\tAC_CACHE_VAL(ac_cv_c_celibconfig,[\n\t    # First check to see if --with-celibconfig was specified.\n\t    if test x\"${with_celibconfig}\" != x ; then\n\t\tif test -d \"${with_celibconfig}/inc\" ; then\n\t\t    ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`\n\t\telse\n\t\t    AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])\n\t\tfi\n\t    fi\n\n\t    # then check for a celib library\n\t    if test x\"${ac_cv_c_celibconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../celib-palm-3.0 \\\n\t\t\t../celib \\\n\t\t\t../../celib-palm-3.0 \\\n\t\t\t../../celib \\\n\t\t\t`ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \\\n\t\t\t${srcdir}/../celib-palm-3.0 \\\n\t\t\t${srcdir}/../celib \\\n\t\t\t`ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -d \"$i/inc\" ; then\n\t\t\tac_cv_c_celibconfig=`(cd $i; pwd)`\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\tif test x\"${ac_cv_c_celibconfig}\" = x ; then\n\t    AC_MSG_ERROR([Cannot find celib support library directory])\n\telse\n\t    no_celib=\n\t    CELIB_DIR=${ac_cv_c_celibconfig}\n\t    CELIB_DIR=`echo \"$CELIB_DIR\" | sed -e 's!\\\\\\!/!g'`\n\t    AC_MSG_RESULT([found $CELIB_DIR])\n\tfi\n    fi\n])\n\n\n# Local Variables:\n# mode: autoconf\n# End:\n"
  },
  {
    "path": "ng/Togl2.1/texture.c",
    "content": "/* $Id: texture.c,v 1.14 2007/08/03 16:48:50 gregcouch Exp $ */\n\n/* \n * Togl - a Tk OpenGL widget\n * Copyright (C) 1996-1997  Brian Paul and Ben Bederson\n * Copyright (C) 2006-2007  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n\n/* \n * An example Togl program demonstrating texture mapping\n */\n\n#define USE_TOGL_STUBS\n\n#include \"togl.h\"\n#include <stdlib.h>\n#include <string.h>\n#if defined(TOGL_AGL)\n#  include <OpenGL/glu.h>\n#else\n#  include <GL/glu.h>\n#endif\n#include \"image.h\"\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n#define CHECKER 0\n#define FACE 1\n#define TREE 2\n\n\nstatic GLenum minfilter = GL_NEAREST_MIPMAP_LINEAR;\nstatic GLenum magfilter = GL_LINEAR;\nstatic GLenum swrap = GL_REPEAT;\nstatic GLenum twrap = GL_REPEAT;\nstatic GLenum envmode = GL_MODULATE;\nstatic GLubyte polycolor[4] = { 255, 255, 255, 255 };\nstatic int teximage = CHECKER;\nstatic double coord_scale = 1;\nstatic double xrot = 0;\nstatic double yrot = 0;\nstatic double texscale = 1;\n\nstatic GLint width, height;\n\nstatic GLboolean blend = GL_FALSE;\n\n\n/* \n * Load a texture image.  n is one of CHECKER, FACE or TREE.\n */\nstatic void\ntexture_image(int n)\n{\n    if (n == CHECKER) {\n#define WIDTH 64\n#define HEIGHT 64\n        GLubyte teximage[WIDTH * HEIGHT][4];\n        int     i, j;\n\n        for (i = 0; i < HEIGHT; i++) {\n            for (j = 0; j < WIDTH; j++) {\n                GLubyte value;\n\n                value = ((i / 4 + j / 4) % 2) ? 0xff : 0x00;\n                teximage[i * WIDTH + j][0] = value;\n                teximage[i * WIDTH + j][1] = value;\n                teximage[i * WIDTH + j][2] = value;\n                teximage[i * WIDTH + j][3] = value;\n            }\n        }\n\n        glEnable(GL_TEXTURE_2D);\n        gluBuild2DMipmaps(GL_TEXTURE_2D, 4, WIDTH, HEIGHT,\n                GL_RGBA, GL_UNSIGNED_BYTE, teximage);\n        blend = GL_FALSE;\n\n#undef WIDTH\n#undef HEIGHT\n    } else if (n == FACE) {\n        TK_RGBImageRec *img = tkRGBImageLoad(\"ben.rgb\");\n\n        if (img) {\n            glEnable(GL_TEXTURE_2D);\n            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n            gluBuild2DMipmaps(GL_TEXTURE_2D, img->sizeZ, img->sizeX, img->sizeY,\n                    img->sizeZ == 3 ? GL_RGB : GL_RGBA,\n                    GL_UNSIGNED_BYTE, img->data);\n\n            blend = GL_TRUE;\n        }\n    } else if (n == TREE) {\n        TK_RGBImageRec *img = tkRGBImageLoad(\"tree2.rgba\");\n\n        if (img) {\n            glEnable(GL_TEXTURE_2D);\n            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n            gluBuild2DMipmaps(GL_TEXTURE_2D, img->sizeZ, img->sizeX, img->sizeY,\n                    img->sizeZ == 3 ? GL_RGB : GL_RGBA,\n                    GL_UNSIGNED_BYTE, img->data);\n\n            blend = GL_TRUE;\n        }\n    } else {\n        abort();\n    }\n}\n\n\n/* \n * Togl widget create callback.  This is called by Tcl/Tk when the widget has\n * been realized.  Here's where one may do some one-time context setup or\n * initializations.\n */\nstatic int\ncreate_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    glEnable(GL_DEPTH_TEST);    /* Enable depth buffering */\n\n    texture_image(CHECKER);\n\n    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter);\n    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl widget reshape callback.  This is called by Tcl/Tk when the widget\n * has been resized.  Typically, we call glViewport and perhaps setup the\n * projection matrix.\n */\nstatic int\nreshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    width = Togl_Width(togl);\n    height = Togl_Height(togl);\n\n    glViewport(0, 0, width, height);\n\n    return TCL_OK;\n}\n\n\nstatic void\ncheck_error(char *where)\n{\n    GLenum  error;\n\n    while (1) {\n        error = glGetError();\n        if (error == GL_NO_ERROR) {\n            break;\n        }\n        printf(\"OpenGL error near %s: %s\\n\", where, gluErrorString(error));\n    }\n}\n\n\n\n/* \n * Togl widget display callback.  This is called by Tcl/Tk when the widget's\n * contents have to be redrawn.  Typically, we clear the color and depth\n * buffers, render our objects, then swap the front/back color buffers.\n */\nstatic int\ndisplay_cb(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    float   aspect = (float) width / (float) height;\n    Togl   *togl;\n\n    if (objc != 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    check_error(\"begin display\\n\");\n\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n    /* Draw background image */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glMatrixMode(GL_MODELVIEW);\n    glLoadIdentity();\n\n    glDisable(GL_TEXTURE_2D);\n    glDisable(GL_DEPTH_TEST);\n    glBegin(GL_POLYGON);\n    glColor3f(0, 0, 0.3f);\n    glVertex2f(-1, -1);\n    glColor3f(0, 0, 0.3f);\n    glVertex2f(1, -1);\n    glColor3f(0, 0, 0.9f);\n    glVertex2f(1, 1);\n    glColor3f(0, 0, 0.9f);\n    glVertex2f(-1, 1);\n    glEnd();\n\n    /* draw textured object */\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glFrustum(-aspect, aspect, -1, 1, 2, 10);\n    glMatrixMode(GL_MODELVIEW);\n    glLoadIdentity();\n    glTranslatef(0, 0, -5);\n    glScaled(texscale, texscale, texscale);\n    glRotated(yrot, 0, 1, 0);\n    glRotated(xrot, 1, 0, 0);\n\n    glEnable(GL_DEPTH_TEST);\n    glEnable(GL_TEXTURE_2D);\n    glColor4ubv(polycolor);\n\n    if (blend) {\n        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n        glEnable(GL_BLEND);\n    }\n\n    glBegin(GL_POLYGON);\n    glTexCoord2f(0, 0);\n    glVertex2f(-1, -1);\n    glTexCoord2d(coord_scale, 0);\n    glVertex2f(1, -1);\n    glTexCoord2d(coord_scale, coord_scale);\n    glVertex2f(1, 1);\n    glTexCoord2d(0, coord_scale);\n    glVertex2f(-1, 1);\n    glEnd();\n\n    glDisable(GL_BLEND);\n\n    Togl_SwapBuffers(togl);\n\n    return TCL_OK;\n}\n\n\n/* \n * Called when a magnification filter radio button is pressed.\n */\nstatic int\nmagfilter_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = { \"GL_NEAREST\", \"GL_LINEAR\", NULL };\n    static const GLenum magfilters[] = { GL_NEAREST, GL_LINEAR };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName magnification-filter-type\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"magnification filter type\", 0, &index);\n    if (result == TCL_OK) {\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,\n                magfilters[index]);\n        Togl_PostRedisplay(togl);\n    }\n    return result;\n}\n\n\n/* \n * Called when a minification filter radio button is pressed.\n */\nstatic int\nminfilter_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = {\n        \"GL_NEAREST\", \"GL_LINEAR\",\n        \"GL_NEAREST_MIPMAP_NEAREST\", \"GL_LINEAR_MIPMAP_NEAREST\",\n        \"GL_NEAREST_MIPMAP_LINEAR\", \"GL_LINEAR_MIPMAP_LINEAR\", NULL\n    };\n    static const GLenum minfilters[] = {\n        GL_NEAREST, GL_LINEAR,\n        GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST,\n        GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR\n    };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName minification-filter-type\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"minification filter type\", 0, &index);\n    if (result == TCL_OK) {\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,\n                minfilters[index]);\n        Togl_PostRedisplay(togl);\n    }\n    return result;\n}\n\n\nstatic int\nxrot_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName angle\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &xrot) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nstatic int\nyrot_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName angle\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &yrot) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nstatic int\ntexscale_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName value\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &texscale) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    Togl_PostRedisplay(togl);\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\n/* \n * Called when S texture coordinate wrapping is changed.\n */\nstatic int\nswrap_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = { \"GL_CLAMP\", \"GL_REPEAT\", NULL };\n    static const GLenum swraps[] = { GL_CLAMP, GL_REPEAT };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName wrap-mode\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"wrap mode\", 0, &index);\n    if (result == TCL_OK) {\n        swrap = swraps[index];\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, swrap);\n        Togl_PostRedisplay(togl);\n        /* Let result string equal value */\n        Tcl_SetObjResult(interp, objv[2]);\n    }\n    return result;\n}\n\n\n/* \n * Called when T texture coordinate wrapping is changed.\n */\nstatic int\ntwrap_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = { \"GL_CLAMP\", \"GL_REPEAT\", NULL };\n    static const GLenum twraps[] = { GL_CLAMP, GL_REPEAT };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName wrap-mode\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"wrap mode\", 0, &index);\n    if (result == TCL_OK) {\n        twrap = twraps[index];\n        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, twrap);\n        Togl_PostRedisplay(togl);\n        /* Let result string equal value */\n        Tcl_SetObjResult(interp, objv[2]);\n    }\n    return result;\n}\n\n\n/* \n * Called when the texture environment mode is changed.\n */\nstatic int\nenvmode_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = {\n        \"GL_MODULATE\", \"GL_DECAL\", \"GL_BLEND\", NULL\n    };\n    static const GLenum envmodes[] = { GL_MODULATE, GL_DECAL, GL_BLEND };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName texture-env-mode\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"texture env mode\", 0, &index);\n    if (result == TCL_OK) {\n        envmode = envmodes[index];\n        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, envmode);\n        Togl_PostRedisplay(togl);\n        /* Let result string equal value */\n        Tcl_SetObjResult(interp, objv[2]);\n    }\n    return result;\n}\n\n\n/* \n * Called when the polygon color is changed.\n */\nstatic int\npolycolor_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl;\n    int     r, g, b;\n\n    if (objc != 5) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName r g b\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[2], &r) != TCL_OK\n            || Tcl_GetIntFromObj(interp, objv[3], &g) != TCL_OK\n            || Tcl_GetIntFromObj(interp, objv[4], &b) != TCL_OK) {\n        return TCL_ERROR;\n    }\n    polycolor[0] = r;\n    polycolor[1] = g;\n    polycolor[2] = b;\n\n    Togl_PostRedisplay(togl);\n\n    return TCL_OK;\n}\n\n\n/* \n * Called when the texture image is to be changed\n */\nstatic int\nteximage_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    static const char *names[] = {\n        \"CHECKER\", \"FACE\", \"TREE\", NULL\n    };\n    static const GLenum teximages[] = {\n        CHECKER, FACE, TREE\n    };\n    int     result, index;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName texture-image-name\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObj(interp, objv[2], names,\n            \"texture image name\", 0, &index);\n    if (result == TCL_OK) {\n        teximage = teximages[index];\n        texture_image(teximage);\n        Togl_PostRedisplay(togl);\n        /* Let result string equal value */\n        Tcl_SetObjResult(interp, objv[2]);\n    }\n    return result;\n}\n\n\n/* \n * Called when the texture coordinate scale is changed.\n */\nstatic int\ncoord_scale_cmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    double  s;\n    Togl   *togl;\n\n    if (objc != 3) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName scale\");\n        return TCL_ERROR;\n    }\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &s) != TCL_OK) {\n        return TCL_ERROR;\n    }\n    if (s > 0 && s < 10) {\n        coord_scale = s;\n        Togl_PostRedisplay(togl);\n    }\n\n    /* Let result string equal value */\n    Tcl_SetObjResult(interp, objv[2]);\n    return TCL_OK;\n}\n\n\nEXTERN int\nTexture_Init(Tcl_Interp *interp)\n{\n    /* \n     * Initialize Tcl and the Togl widget module.\n     */\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL\n            || Togl_InitStubs(interp, \"2.0\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* \n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"create_cb\", create_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"display_cb\", display_cb, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"reshape_cb\", reshape_cb, NULL, NULL);\n\n    /* \n     * Make a new Togl widget command so the Tcl code can set a C variable.\n     */\n    Tcl_CreateObjCommand(interp, \"min_filter\", minfilter_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"mag_filter\", magfilter_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"xrot\", xrot_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"yrot\", yrot_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"texscale\", texscale_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"swrap\", swrap_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"twrap\", twrap_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"envmode\", envmode_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"polycolor\", polycolor_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"teximage\", teximage_cmd, NULL, NULL);\n    Tcl_CreateObjCommand(interp, \"coord_scale\", coord_scale_cmd, NULL, NULL);\n\n    /* \n     * Call Tcl_CreateCommand for application-specific commands, if\n     * they weren't already created by the init procedures called above.\n     */\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "ng/Togl2.1/texture.tcl",
    "content": "#!/bin/sh\n# the next line restarts using tclsh \\\nexec tclsh \"$0\" \"$@\"\n\n# $Id: texture.tcl,v 1.8 2007/08/03 16:48:50 gregcouch Exp $\n\n# Togl - a Tk OpenGL widget\n# Copyright (C) 1996  Brian Paul and Ben Bederson\n# Copyright (C) 2006-2007  Greg Couch\n# See the LICENSE file for copyright details.\n\n\n# Togl texture map demo\n\npackage provide texture 1.0\n\n# add parent directory to path to find Togl's pkgIndex in current directory\nif { [file exists pkgIndex.tcl] } {\n    set auto_path [linsert $auto_path 0 ..]\n}\n# following load also loads Tk and Togl packages\nload [file dirname [info script]]/texture[info sharedlibextension]\n\n# create ::texture namespace\nnamespace eval ::texture {\n}\n\n# Called magnification filter changes\nproc ::texture::new_magfilter {} {\n    global magfilter\n    mag_filter .f1.view $magfilter\n}\n\n\n# Called minification filter changes\nproc ::texture::new_minfilter {} {\n    global minfilter\n    min_filter .f1.view $minfilter\n}\n\n\n# Called when texture image radio button changes\nproc ::texture::new_image {} {\n    global image\n    teximage .f1.view $image\n}\n\n\n# Called when texture S wrap button changes\nproc ::texture::new_swrap {} {\n    global swrap\n    swrap .f1.view $swrap\n}\n\n\n# Called when texture T wrap button changes\nproc ::texture::new_twrap {} {\n    global twrap\n    twrap .f1.view $twrap\n}\n\n\n# Called when texture environment radio button selected\nproc ::texture::new_env {} {\n    global envmode\n    envmode .f1.view $envmode\n}\n\n\n# Called when polygon color sliders change\nproc ::texture::new_color { foo } {\n    global poly_red poly_green poly_blue\n    polycolor .f1.view $poly_red $poly_green $poly_blue\n}\n\n\nproc ::texture::new_coord_scale { name element op } {\n    global coord_scale\n    coord_scale .f1.view $coord_scale\n}\n\nproc ::texture::take_photo {} {\n\timage create photo teximg\n\t.f1.view takephoto teximg\n\tteximg write image.ppm -format ppm\n}\n\n# Make the widgets\nproc ::texture::setup {} {\n    global magfilter\n    global minfilter\n    global image\n    global swrap\n    global twrap\n    global envmode\n    global poly_red\n    global poly_green\n    global poly_blue\n    global coord_scale\n    global startx starty         # location of mouse when button pressed\n    global xangle yangle\n    global xangle0 yangle0\n    global texscale texscale0\n\n    wm title . \"Texture Map Options\"\n\n    ### Two frames:  top half and bottom half\n    frame .f1\n    frame .f2\n\n    ### The OpenGL window\n    togl .f1.view -width 250 -height 250 -rgba true -double true -depth true -create create_cb -reshape reshape_cb -display display_cb\n\n\n    ### Filter radio buttons\n    frame .f1.filter -relief ridge -borderwidth 3\n\n    frame .f1.filter.mag -relief ridge -borderwidth 2\n\n    label .f1.filter.mag.label -text \"Magnification Filter\" -anchor w\n    radiobutton .f1.filter.mag.nearest -text GL_NEAREST -anchor w -variable magfilter -value GL_NEAREST -command ::texture::new_magfilter\n    radiobutton .f1.filter.mag.linear -text GL_LINEAR -anchor w -variable magfilter -value GL_LINEAR -command ::texture::new_magfilter\n\n    frame .f1.filter.min -relief ridge -borderwidth 2\n\n    label .f1.filter.min.label -text \"Minification Filter\" -anchor w\n    radiobutton .f1.filter.min.nearest -text GL_NEAREST -anchor w -variable minfilter -value GL_NEAREST -command ::texture::new_minfilter\n    radiobutton .f1.filter.min.linear -text GL_LINEAR -anchor w -variable minfilter -value GL_LINEAR -command ::texture::new_minfilter\n    radiobutton .f1.filter.min.nearest_mipmap_nearest -text GL_NEAREST_MIPMAP_NEAREST -anchor w -variable minfilter -value GL_NEAREST_MIPMAP_NEAREST -command ::texture::new_minfilter\n    radiobutton .f1.filter.min.linear_mipmap_nearest -text GL_LINEAR_MIPMAP_NEAREST -anchor w -variable minfilter -value GL_LINEAR_MIPMAP_NEAREST -command ::texture::new_minfilter\n    radiobutton .f1.filter.min.nearest_mipmap_linear -text GL_NEAREST_MIPMAP_LINEAR -anchor w -variable minfilter -value GL_NEAREST_MIPMAP_LINEAR -command ::texture::new_minfilter\n    radiobutton .f1.filter.min.linear_mipmap_linear -text GL_LINEAR_MIPMAP_LINEAR -anchor w -variable minfilter -value GL_LINEAR_MIPMAP_LINEAR -command ::texture::new_minfilter\n\n    pack .f1.filter.mag -fill x\n    pack .f1.filter.mag.label -fill x\n    pack .f1.filter.mag.nearest -side top -fill x\n    pack .f1.filter.mag.linear -side top -fill x\n\n    pack .f1.filter.min -fill both -expand true\n    pack .f1.filter.min.label -side top -fill x\n    pack .f1.filter.min.nearest -side top -fill x\n    pack .f1.filter.min.linear -side top -fill x \n    pack .f1.filter.min.nearest_mipmap_nearest -side top -fill x\n    pack .f1.filter.min.linear_mipmap_nearest -side top -fill x\n    pack .f1.filter.min.nearest_mipmap_linear -side top -fill x\n    pack .f1.filter.min.linear_mipmap_linear -side top -fill x\n\n\n    ### Texture coordinate scale and wrapping\n    frame .f2.coord -relief ridge -borderwidth 3\n    frame .f2.coord.scale -relief ridge -borderwidth 2\n    label .f2.coord.scale.label -text \"Max Texture Coord\" -anchor w\n    entry .f2.coord.scale.entry -textvariable coord_scale\n    trace variable coord_scale w ::texture::new_coord_scale\n\n    frame .f2.coord.s -relief ridge -borderwidth 2\n    label .f2.coord.s.label -text \"GL_TEXTURE_WRAP_S\" -anchor w\n    radiobutton .f2.coord.s.repeat -text \"GL_REPEAT\" -anchor w -variable swrap -value GL_REPEAT -command ::texture::new_swrap\n    radiobutton .f2.coord.s.clamp -text \"GL_CLAMP\" -anchor w -variable swrap -value GL_CLAMP -command ::texture::new_swrap\n\n    frame .f2.coord.t -relief ridge -borderwidth 2\n    label .f2.coord.t.label -text \"GL_TEXTURE_WRAP_T\" -anchor w\n    radiobutton .f2.coord.t.repeat -text \"GL_REPEAT\" -anchor w -variable twrap -value GL_REPEAT -command ::texture::new_twrap\n    radiobutton .f2.coord.t.clamp -text \"GL_CLAMP\" -anchor w -variable twrap -value GL_CLAMP -command ::texture::new_twrap\n\n    pack .f2.coord.scale -fill both -expand true\n    pack .f2.coord.scale.label -side top -fill x\n    pack .f2.coord.scale.entry -side top -fill x\n\n    pack .f2.coord.s -fill x\n    pack .f2.coord.s.label -side top -fill x\n    pack .f2.coord.s.repeat -side top -fill x\n    pack .f2.coord.s.clamp -side top -fill x\n\n    pack .f2.coord.t -fill x\n    pack .f2.coord.t.label -side top -fill x\n    pack .f2.coord.t.repeat -side top -fill x\n    pack .f2.coord.t.clamp -side top -fill x\n\n\n    ### Texture image radio buttons (just happens to fit into the coord frame)\n    frame .f2.env -relief ridge -borderwidth 3\n    frame .f2.env.image -relief ridge -borderwidth 2\n    label .f2.env.image.label -text \"Texture Image\" -anchor w\n    radiobutton .f2.env.image.checker -text \"Checker\" -anchor w -variable image -value CHECKER -command ::texture::new_image\n    radiobutton .f2.env.image.tree -text \"Tree\" -anchor w -variable image -value TREE -command ::texture::new_image\n    radiobutton .f2.env.image.face -text \"Face\" -anchor w -variable image -value FACE -command ::texture::new_image\n    pack .f2.env.image -fill x\n    pack .f2.env.image.label -side top -fill x\n    pack .f2.env.image.checker -side top -fill x\n    pack .f2.env.image.tree -side top -fill x\n    pack .f2.env.image.face -side top -fill x\n\n\n    ### Texture Environment\n    label .f2.env.label -text \"GL_TEXTURE_ENV_MODE\" -anchor w\n    radiobutton .f2.env.modulate -text \"GL_MODULATE\" -anchor w -variable envmode -value GL_MODULATE -command ::texture::new_env\n    radiobutton .f2.env.decal -text \"GL_DECAL\" -anchor w -variable envmode -value GL_DECAL -command ::texture::new_env\n    radiobutton .f2.env.blend -text \"GL_BLEND\" -anchor w -variable envmode -value GL_BLEND -command ::texture::new_env\n    pack .f2.env.label -fill x\n    pack .f2.env.modulate -side top -fill x\n    pack .f2.env.decal -side top -fill x\n    pack .f2.env.blend -side top -fill x\n\n    ### Polygon color\n    frame .f2.color -relief ridge -borderwidth 3\n    label .f2.color.label -text \"Polygon color\" -anchor w\n    scale .f2.color.red -label Red -from 0 -to 255 -orient horizontal -variable poly_red -command ::texture::new_color\n    scale .f2.color.green -label Green -from 0 -to 255 -orient horizontal -variable poly_green -command ::texture::new_color\n    scale .f2.color.blue -label Blue -from 0 -to 255 -orient horizontal -variable poly_blue -command ::texture::new_color\n    pack .f2.color.label -fill x\n    pack .f2.color.red -side top -fill x\n    pack .f2.color.green -side top -fill x\n    pack .f2.color.blue -side top -fill x\n\n\n    ### Main widgets\n    pack .f1.view -side left -fill both -expand true\n    pack .f1.filter -side left -fill y\n    pack .f1 -side top -fill both -expand true\n\n    pack .f2.coord .f2.env -side left -fill both\n    pack .f2.color -fill x\n    pack .f2 -side top -fill x\n\n    button .photo -text \"Take Photo\" -command ::texture::take_photo\n    pack .photo -expand true -fill both\n    button .quit -text Quit -command exit\n    pack .quit -expand true -fill both\n\n    bind .f1.view <ButtonPress-1> {\n\tset startx %x\n\tset starty %y\n\tset xangle0 $xangle\n\tset yangle0 $yangle\n    }\n\n    bind .f1.view <B1-Motion> {\n        set xangle [expr $xangle0 + (%x - $startx) / 3.0 ]\n        set yangle [expr $yangle0 + (%y - $starty) / 3.0 ]\n        yrot .f1.view $xangle\n        xrot .f1.view $yangle\n    }\n\n    bind .f1.view <ButtonPress-2> {\n\tset startx %x\n\tset starty %y\n\tset texscale0 $texscale\n    }\n\n    bind .f1.view <B2-Motion> {\n        set q [ expr ($starty - %y) / 400.0 ]\n\tset texscale [expr $texscale0 * exp($q)]\n        texscale .f1.view $texscale\n    }\n\n    # set default values:\n    set minfilter GL_NEAREST_MIPMAP_LINEAR\n    set magfilter GL_LINEAR\n    set swrap GL_REPEAT\n    set twrap GL_REPEAT\n    set envmode GL_MODULATE\n    set image CHECKER\n    set poly_red 255\n    set poly_green 255\n    set poly_blue 255\n    set coord_scale 1.0\n\n    set xangle 0.0\n    set yangle 0.0\n    set texscale 1.0\n}\n\n\n# Execution starts here!\nif { [info script] == $argv0 } {\n\t::texture::setup\n}\n"
  },
  {
    "path": "ng/Togl2.1/togl.c",
    "content": "/* $Id: togl.c,v 1.142 2009/12/23 21:50:49 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n/* \n * Currently we support X11, Win32 and Mac OS X only\n */\n\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#       define MODULE_SCOPE extern \"C\"\n#   else\n#       define MODULE_SCOPE extern\n#   endif\n#endif\n\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n\n#define USE_TOGL_STUB_PROCS\n#include \"togl.h\"\n#include <tkInt.h>   // don't need it on osx ???\n#include <limits.h>\n\n#ifndef TOGL_USE_FONTS\n#  define TOGL_USE_FONTS 1\n#endif\n#if (TK_MAJOR_VERSION > 8 || TK_MINOR_VERSION > 4) && !defined(TOGL_WGL)\n/* X11 and Aqua font technology changed in 8.5 */\n#  undef TOGL_USE_FONTS\n#endif\n#ifndef TOGL_USE_OVERLAY\n#  if defined(TOGL_X11) || defined(TOGL_WGL)\n#    define TOGL_USE_OVERLAY 1\n#  endif\n#endif\n\n/* Use TCL_STUPID to cast (const char *) to (char *) where the Tcl function\n * prototype argument should really be const */\n#define TCL_STUPID (char *)\n\n/* Use WIDGREC to cast widgRec or recordPtr arguments */\n#define WIDGREC\t(char *)\n\n/*** Windows headers ***/\n#if defined(TOGL_WGL)\n#  define WIN32_LEAN_AND_MEAN\n#  include <windows.h>\n#  undef WIN32_LEAN_AND_MEAN\n#  include <winnt.h>\n#  ifndef PFD_SUPPORT_COMPOSITION\n// for Vista -- not strictly needed because we don't use PFD_SUPPORT_GDI/BITMAP\n#    define PFD_SUPPORT_COMPOSITION 0x00008000\n#  endif\n#  include <GL/glext.h>\n#  include <objbase.h>\n#  include <GL/wglext.h>\n#  ifdef _MSC_VER\n#    include <strsafe.h>\n#  else\n#    ifdef UNICODE\n#      define StringCchPrintf snwprintf\n#    else\n#      define StringCchPrintf snprintf\n#    endif\n#  endif\n\n/*** X Window System headers ***/\n#elif defined(TOGL_X11)\n#  include <X11/Xlib.h>\n#  include <X11/Xutil.h>\n#  include <X11/Xatom.h>        /* for XA_RGB_DEFAULT_MAP atom */\n#  if !defined(USE_SYSTEM_XMU)\n#    include \"Xmu/StdCmap.h\"\n#  else\n#    if defined(__vms)\n#      include <X11/StdCmap.h>  /* for XmuLookupStandardColormap */\n#    else\n#      include <X11/Xmu/StdCmap.h>      /* for XmuLookupStandardColormap */\n#    endif\n#  endif\n#  define GLX_GLXEXT_LEGACY     /* include glxext.h separately */\n#  include <GL/glx.h>\n   /* we want the prototype typedefs from glxext.h */\n#  undef GLX_VERSION_1_3\n#  undef GLX_VERSION_1_4\n#  ifdef UNDEF_GET_PROC_ADDRESS\n#    undef GLX_ARB_get_proc_address\n#  endif\n#  include <GL/glxext.h>\n#  ifdef __sgi\n#    include <X11/extensions/SGIStereo.h>\n#  endif\n#  ifdef HAVE_AUTOSTEREO\n#    include <autostereo.h>\n#  endif\n\n/*** Mac Carbon headers ***/\n#elif defined(TOGL_AGL)\n#  define Cursor QDCursor\n#  include <AGL/agl.h>\n#  undef Cursor\n#  include <tkMacOSXInt.h>      /* usa MacDrawable */\n#  include <ApplicationServices/ApplicationServices.h>\n#  define Togl_MacOSXGetDrawablePort(togl) TkMacOSXGetDrawablePort((Drawable) ((TkWindow *) togl->TkWin)->privatePtr)\n\n/*** Mac Cocoa headers ***/\n#elif defined(TOGL_NSOPENGL)\n#undef panic\n#  include <OpenGL/OpenGL.h>\n#  include <AppKit/NSOpenGL.h>\t/* Use NSOpenGLContext */\n#  include <AppKit/NSView.h>\t/* Use NSView */\n#  include <AppKit/NSWindow.h>\t/* Use NSWindow */\n#  include <AppKit/NSOpenGLView.h>\t/* Use NSView setWantsBestResolutionOpenGLSurface */\n#  include <AppKit/NSEvent.h>\t/* Use NSEvent */\n#  include <AppKit/NSTouch.h>\t/* Use NSTouch */\n#  include <Foundation/Foundation.h>\t/* Use NSRect */\n#  include <tkMacOSXInt.h>      /* Use MacDrawable */\n#  include <ApplicationServices/ApplicationServices.h>\n#  define Togl_MacOSXGetDrawablePort(togl) TkMacOSXGetDrawablePort((Drawable) ((TkWindow *) togl->TkWin)->privatePtr)\n\n#  include <Availability.h>\n#  ifndef __MAC_10_7\n/* Define Mac retina display routines not available prior to Mac OS 10.7 */\n@interface NSView (NSOpenGLSurfaceResolution)\n- (BOOL)wantsBestResolutionOpenGLSurface;\n- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag;\n- (NSRect)convertRectToBacking:(NSRect)aRect;\n#define NSEventPhaseNone 0\n@end\n#  endif\n\n#else /* make sure only one platform defined */\n#  error Unsupported platform, or confused platform defines...\n#endif\n\n#define NC3D L\"NVidia Consumer 3D Stereo\"\n\n#ifndef STEREO_BUFFER_NONE\n/* From <X11/extensions/SGIStereo.h>, but we use this constants elsewhere */\n#  define STEREO_BUFFER_NONE 0\n#  define STEREO_BUFFER_LEFT 1\n#  define STEREO_BUFFER_RIGHT 2\n#endif\n\n/*** Standard C headers ***/\n#include <assert.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef TOGL_WGL\n#  include <tkPlatDecls.h>\n#endif\n\n#if TK_MAJOR_VERSION < 8\n#  error Sorry Togl requires Tcl/Tk ver 8.0 or higher.\n#endif\n\n#ifdef USE_TCL_STUBS\n#  if TK_MAJOR_VERSION < 8 || (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 1)\n#    error Sorry stub support requires Tcl/Tk ver 8.1 or higher.\n#  endif\n#endif\n\n#if defined(TOGL_AGL)\n#  if TK_MAJOR_VERSION < 8 || (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 4)\n#    error Sorry Mac Aqua version requires Tcl/Tk ver 8.4.0 or higher.\n#  endif\n#endif /* TOGL_AGL */\n\n// Seems to work with Apple Tcl 8.5 too....\n// #if defined(TOGL_NSOPENGL)\n// #  if TK_MAJOR_VERSION < 8 || (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 6)\n// #    error Sorry Mac Cocoa version requires Tcl/Tk ver 8.6.0 or higher.\n// #  endif\n// #endif /* TOGL_NSOPENGL */\n\n#if defined(TOGL_WGL) && defined(_MSC_VER)\n#  define snprintf _snprintf\n#  pragma warning(disable:4995)\n#endif\n\n/* workaround for bug #123153 in tcl ver8.4a2 (tcl.h) */\n#if defined(Tcl_InitHashTable) && defined(USE_TCL_STUBS)\n#  undef Tcl_InitHashTable\n#  define Tcl_InitHashTable (tclStubsPtr->tcl_InitHashTable)\n#endif\n#if TK_MAJOR_VERSION > 8 || (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION >= 4)\n#  define HAVE_TK_SETCLASSPROCS\n/* pointer to Tk_SetClassProcs function in the stub table */\n\n#if TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 6\nstatic void (*SetClassProcsPtr)\n        _ANSI_ARGS_((Tk_Window, Tk_ClassProcs *, ClientData));\n#else\nstatic void (*SetClassProcsPtr)\n        _ANSI_ARGS_((Tk_Window, const Tk_ClassProcs *, ClientData));\n#endif\n#endif\n\n/* \n * Copy of TkClassProcs declarations from tkInt.h\n * (this is needed for Tcl ver =< 8.4a3)\n */\n\ntypedef Window (TkClassCreateProc) _ANSI_ARGS_((Tk_Window tkwin,\n                Window parent, ClientData instanceData));\ntypedef void (TkClassGeometryProc) _ANSI_ARGS_((ClientData instanceData));\ntypedef void (TkClassModalProc) _ANSI_ARGS_((Tk_Window tkwin,\n                XEvent *eventPtr));\ntypedef struct TkClassProcs\n{\n    TkClassCreateProc *createProc;\n    TkClassGeometryProc *geometryProc;\n    TkClassModalProc *modalProc;\n} TkClassProcs;\n\n\n/* Defaults */\n#define DEFAULT_WIDTH\t\t\"400\"\n#define DEFAULT_HEIGHT\t\t\"400\"\n#define DEFAULT_IDENT\t\t\"\"\n#define DEFAULT_FONTNAME\t\"Courier\"\n#define DEFAULT_TIME\t\t\"1\"\n\n\n#ifdef TOGL_WGL\n/* Maximum size of a logical palette corresponding to a colormap in color index \n * mode. */\n#  define MAX_CI_COLORMAP_SIZE 4096\n#  define MAX_CI_COLORMAP_BITS 12\n\n#  if TOGL_USE_FONTS != 1\n/* \n * copy of TkWinColormap from tkWinInt.h\n */\n\ntypedef struct\n{\n    HPALETTE palette;           /* Palette handle used when drawing. */\n    UINT    size;               /* Number of entries in the palette. */\n    int     stale;              /* 1 if palette needs to be realized, otherwise \n                                 * 0.  If the palette is stale, then an idle\n                                 * handler is scheduled to realize the palette. \n                                 */\n    Tcl_HashTable refCounts;    /* Hash table of palette entry reference counts\n                                 * indexed by pixel value. */\n} TkWinColormap;\n#  else\n#    include <tkWinInt.h>\n#  endif\n\nstatic  LRESULT(CALLBACK *tkWinChildProc) (HWND hwnd, UINT message,\n        WPARAM wParam, LPARAM lParam) = NULL;\n\n#  ifndef TK_WIN_CHILD_CLASS_NAME \n#    define TK_WIN_CHILD_CLASS_NAME L\"TkChild\"\n#  endif\n\n#endif /* TOGL_WGL */\n\n\n#define MAX(a,b)\t(((a)>(b))?(a):(b))\n\n#define TCL_ERR(interp, string)\t\t\t\\\n   do {\t\t\t\t\t\t\\\n      Tcl_ResetResult(interp);\t\t\t\\\n      Tcl_AppendResult(interp, string, NULL);\t\\\n      return TCL_ERROR;\t\t\t\t\\\n   } while (0)\n\n#define ALL_EVENTS_MASK \t\\\n   (KeyPressMask\t\t\\\n   |KeyReleaseMask\t\t\\\n   |ButtonPressMask\t\t\\\n   |ButtonReleaseMask\t\t\\\n   |EnterWindowMask\t\t\\\n   |LeaveWindowMask\t\t\\\n   |PointerMotionMask\t\t\\\n   |ExposureMask\t\t\\\n   |VisibilityChangeMask\t\\\n   |FocusChangeMask\t\t\\\n   |PropertyChangeMask\t\t\\\n   |ColormapChangeMask)\n\n/* \n * The following structure contains pointers to functions used for\n * processing the custom \"-stereo\" option.  Copied from tkPanedWindow.c.\n */\nstatic int SetStereo(ClientData clientData, Tcl_Interp *interp,\n        Tk_Window tkwin, Tcl_Obj **value, char *recordPtr,\n        int internalOffset, char *oldInternalPtr, int flags);\nstatic Tcl_Obj *GetStereo(ClientData clientData, Tk_Window tkwin,\n        char *recordPtr, int internalOffset);\nstatic void RestoreStereo(ClientData clientData, Tk_Window tkwin,\n        char *internalPtr, char *oldInternalPtr);\n\nstatic Tk_ObjCustomOption stereoOption = {\n    \"stereo\",                   /* name */\n    SetStereo,                  /* setProc */\n    GetStereo,                  /* getProc */\n    RestoreStereo,              /* restoreProc */\n    NULL,                       /* freeProc */\n    0\n};\n\n/* \n * The following structure contains pointers to functions used for\n * processing the custom \"-pixelformat\" option.  Copied from tkPanedWindow.c.\n */\nstatic int SetWideInt(ClientData clientData, Tcl_Interp *interp,\n        Tk_Window tkwin, Tcl_Obj **value, char *recordPtr,\n        int internalOffset, char *oldInternalPtr, int flags);\nstatic Tcl_Obj *GetWideInt(ClientData clientData, Tk_Window tkwin,\n        char *recordPtr, int internalOffset);\nstatic void RestoreWideInt(ClientData clientData, Tk_Window tkwin,\n        char *internalPtr, char *oldInternalPtr);\n\nstatic Tk_ObjCustomOption wideIntOption = {\n    \"wide int\",                 /* name */\n    SetWideInt,                 /* setProc */\n    GetWideInt,                 /* getProc */\n    RestoreWideInt,             /* restoreProc */\n    NULL,                       /* freeProc */\n    0\n};\n\n/* \n * Stuff we initialize on a per package (Togl_Init) basis.\n * Since Tcl uses one interpreter per thread, any per-thread\n * data goes here.\n */\nstruct Togl_PackageGlobals\n{\n    Tk_OptionTable optionTable; /* Used to parse options */\n    Togl   *toglHead;           /* Head of linked list of all Togl widgets */\n    int     nextContextTag;     /* Used to assign similar context tags */\n};\ntypedef struct Togl_PackageGlobals Togl_PackageGlobals;\n\nextern ToglStubs toglStubs;     /* should be only non-const global */\n\n#if defined(TOGL_NSOPENGL)\n\n/* Handle window drags between retina and non-retina displays. */\n@interface ToglNSView : NSView {\n    struct Togl *togl;\n}\n- (void) setTogl: (struct Togl*)t;\n- (void) viewDidChangeBackingProperties;\n- (void) magnifyWithEvent: (NSEvent *)event;\n- (void) rotateWithEvent: (NSEvent *)event;\n- (void) scrollWheel: (NSEvent *)event;\n- (void)touchesBeganWithEvent:(NSEvent *)event;\n- (void)touchesMovedWithEvent:(NSEvent *)event;\n- (void)touchesEndedWithEvent:(NSEvent *)event;\n- (void)touchesCancelledWithEvent:(NSEvent *)event;\n- (void)reportEventTouches:(NSEvent *)event;\n\n@end\n\n#endif\n\nstruct Togl\n{\n    Togl   *Next;               /* next in linked list */\n\n#if defined(TOGL_WGL)\n    HGLRC   Ctx;                /* OpenGL rendering context to be made current */\n    HDC     tglGLHdc;           /* Device context of device that OpenGL calls\n                                 * will be drawn on */\n    int     CiColormapSize;     /* (Maximum) size of colormap in color index\n                                 * mode */\n#elif defined(TOGL_X11)\n    GLXContext Ctx;             /* Normal planes GLX context */\n#elif defined(TOGL_AGL)\n    AGLContext Ctx;\n#elif defined(TOGL_NSOPENGL)\n    NSOpenGLContext *Ctx;\n    ToglNSView *nsview;\n#endif\n    int     contextTag;         /* all contexts with same tag share display\n                                 * lists */\n\n    XVisualInfo *VisInfo;       /* Visual info of the current */\n\n    Display *display;           /* X's token for the window's display. */\n    Tk_Window TkWin;            /* Tk window structure */\n    Tcl_Interp *Interp;         /* Tcl interpreter */\n    Tcl_Command widgetCmd;      /* Token for togl's widget command */\n    Togl_PackageGlobals *tpg;   /* Used to access globals */\n#ifndef NO_TK_CURSOR\n    Tk_Cursor Cursor;           /* The widget's cursor */\n#endif\n    int     Width, Height;      /* Dimensions of window */\n    int     PixelScale;         /* Graphics pixels per Tk pixel. */\n                                /*    1 for normal display. */\n                                /*    2 for Mac retina display. */\n    int     SetGrid;            /* positive is grid size for window manager */\n    int     TimerInterval;      /* Time interval for timer in milliseconds */\n    Tcl_TimerToken timerHandler;        /* Token for togl's timer handler */\n    Bool    RgbaFlag;           /* configuration flags (ala GLX parameters) */\n    int     RgbaRed;\n    int     RgbaGreen;\n    int     RgbaBlue;\n    Bool    DoubleFlag;\n    Bool    DepthFlag;\n    int     DepthSize;\n    Bool    AccumFlag;\n    int     AccumRed;\n    int     AccumGreen;\n    int     AccumBlue;\n    int     AccumAlpha;\n    Bool    AlphaFlag;\n    int     AlphaSize;\n    Bool    StencilFlag;\n    int     StencilSize;\n    Bool    PrivateCmapFlag;\n    Bool    OverlayFlag;\n    int     Stereo;\n    double  EyeSeparation;\n    double  Convergence;\n    GLuint  riStencilBit;       /* row interleaved stencil bit */\n    int     AuxNumber;\n    Bool    Indirect;\n#if defined(TOGL_NSOPENGL)\n    NSOpenGLPixelFormat *PixelFormat;\n#else\n    Tcl_WideInt PixelFormat;\n#endif\n    int     SwapInterval;\n    Bool    MultisampleFlag;\n    Bool    FullscreenFlag;\n    Bool    PbufferFlag;\n    Bool    LargestPbufferFlag;\n#if defined(TOGL_X11)\n    GLXFBConfig fbcfg;          /* cache FBConfig for pbuffer creation */\n    GLXPbuffer pbuf;\n#elif defined(TOGL_WGL)\n    HPBUFFERARB pbuf;\n    int     pbufferLost;\n#elif defined(TOGL_AGL)\n    AGLPbuffer pbuf;\n#elif defined(TOGL_NSOPENGL)\n    NSOpenGLPixelBuffer *pbuf;\n#endif\n    const char *ShareList;      /* name (ident) of Togl to share dlists with */\n    const char *ShareContext;   /* name (ident) to share OpenGL context with */\n\n    const char *Ident;          /* User's identification string */\n    ClientData Client_Data;     /* Pointer to user data */\n\n    Bool    UpdatePending;      /* Should normal planes be redrawn? */\n\n    Tcl_Obj *CreateProc;        /* Callback when widget is realized */\n    Tcl_Obj *DisplayProc;       /* Callback when widget is redrawn */\n    Tcl_Obj *ReshapeProc;       /* Callback when window size changes */\n    Tcl_Obj *DestroyProc;       /* Callback when widget is destroyed */\n    Tcl_Obj *TimerProc;         /* Callback when widget is idle */\n    Tcl_Obj *MagnifyProc;       /* Callback for track pad pinch gesture */\n    Tcl_Obj *RotateProc;        /* Callback for track pad rotate gesture */\n    Tcl_Obj *ScrollProc;        /* Callback for track pad scroll gesture */\n    Tcl_Obj *ScrollWheelProc;   /* Callback for mouse scroll wheel, not trackpad */\n    Tcl_Obj *TouchesProc;       /* Callback for track pad touches */\n\n    /* Overlay stuff */\n#if defined(TOGL_X11)\n    GLXContext OverlayCtx;      /* Overlay planes OpenGL context */\n#elif defined(TOGL_WGL)\n    HGLRC   tglGLOverlayHglrc;\n#endif\n\n    Window  OverlayWindow;      /* The overlay window, or 0 */\n    Tcl_Obj *OverlayDisplayProc;        /* Overlay redraw proc */\n    Bool    OverlayUpdatePending;       /* Should overlay be redrawn? */\n    Colormap OverlayCmap;       /* colormap for overlay is created */\n    int     OverlayTransparentPixel;    /* transparent pixel */\n    Bool    OverlayIsMapped;\n\n    GLfloat *RedMap;            /* Index2RGB Maps for Color index modes */\n    GLfloat *GreenMap;\n    GLfloat *BlueMap;\n    GLint   MapSize;            /* = Number of indices in our Togl */\n    int     currentStereoBuffer;\n#ifdef HAVE_AUTOSTEREO\n    int     as_initialized;     /* for autostereo package */\n    ASHandle ash;               /* for autostereo package */\n#endif\n    int     badWindow;          /* true when Togl_MakeWindow fails or should\n                                 * create a dummy window */\n};\n\nint Togl_CallCallback(Togl *togl, Tcl_Obj *cmd);\nstatic int Togl_CallCallback_P(Togl *togl, Tcl_Obj *cmd, double *params, int nparams);\n\n#if defined(TOGL_NSOPENGL)\n\nstatic int viewPixelScale(NSView *nsview);\n@implementation ToglNSView\n\n- (void) setTogl: (struct Togl*)t\n{\n    togl = t;\n}\n\n- (void) viewDidChangeBackingProperties\n{\n    [super viewDidChangeBackingProperties];\n    if (togl && togl->ReshapeProc) {\n      int pscale = viewPixelScale(self);\n      if (pscale != togl->PixelScale) {\n\ttogl->PixelScale = pscale;\n\tif (togl->ReshapeProc)\n\t  (void) Togl_CallCallback(togl, togl->ReshapeProc);\n\tTogl_PostRedisplay(togl);\n      }\n    }\n}\n\n- (void) magnifyWithEvent: (NSEvent *)event\n{\n  if (togl && togl->MagnifyProc) {\n    double mag = [event magnification] + 1.0;\n    (void) Togl_CallCallback_P(togl, togl->MagnifyProc, &mag, 1);\n  }\n}\n\n- (void) rotateWithEvent: (NSEvent *)event\n{\n  if (togl && togl->RotateProc) {\n    double deg = [event rotation];\n    (void) Togl_CallCallback_P(togl, togl->RotateProc, &deg, 1);\n  }\n}\n\n- (void) scrollWheel: (NSEvent *)event\n{\n  if (togl && (togl->ScrollProc || togl->ScrollWheelProc)) {\n    float dx = [event deltaX], dy = [event deltaY];\n    if (dx != 0 || dy != 0) {\n      //      float track_pad = ((([event phase] == NSEventPhaseNone) &&\n      //\t\t\t  ([event momentumPhase] == NSEventPhaseNone)) ? 0 : 1);\n      float track_pad = ([event subtype] == NSMouseEventSubtype ? 0 : 1);\n      double args[3] = {dx, dy, track_pad};\n      if (togl->ScrollProc)\n\t(void) Togl_CallCallback_P(togl, togl->ScrollProc, args, 3);\n      if (togl->ScrollWheelProc && !track_pad)\n\t(void) Togl_CallCallback_P(togl, togl->ScrollWheelProc, args+1, 1);\n    }\n  }\n}\n\n- (void)touchesBeganWithEvent:(NSEvent *)event\n{  NSWindow *win = [self window];\n  [win makeKeyWindow];\n  [win makeMainWindow];\n  [self reportEventTouches:event];\n }\n- (void)touchesMovedWithEvent:(NSEvent *)event\n{ [self reportEventTouches:event]; }\n- (void)touchesEndedWithEvent:(NSEvent *)event\n{ [self reportEventTouches:event]; }\n- (void)touchesCancelledWithEvent:(NSEvent *)event;\n{ [self reportEventTouches:event]; }\n- (void)reportEventTouches: (NSEvent *)event\n{\n  if (togl && togl->TouchesProc) {\n    NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseTouching inView:self];\n    int n = touches.count, i;\n    double *id_xy = NULL;\n    if (n >= 0) {\n      id_xy = (double *)malloc(3*n*sizeof(double));\n      NSArray *array = [touches allObjects];\n      for (i = 0 ; i < n ; ++i) {\n\tNSTouch *t = [array objectAtIndex:i];\n\tid_xy[3*i] = (long)t.identity;\n\tid_xy[3*i+1] = t.normalizedPosition.x * t.deviceSize.width;\n\tid_xy[3*i+2] = t.normalizedPosition.y * t.deviceSize.height;\n      }\n      (void) Togl_CallCallback_P(togl, togl->TouchesProc, id_xy, 3*n);\n      if (id_xy)\n\tfree(id_xy);\n    }\n  }\n}\n\n@end\n\n#endif\n\n/* \n * Prototypes for functions local to this file\n */\nstatic int Togl_ObjCmd(ClientData clientData, Tcl_Interp *interp,\n        int objc, Tcl_Obj *const *objv);\nstatic void Togl_ObjCmdDelete(ClientData clientData);\nstatic void Togl_EventProc(ClientData clientData, XEvent *eventPtr);\nstatic void Togl_RedisplayProc(ClientData clientData, XEvent *eventPtr);\nstatic Window Togl_MakeWindow(Tk_Window, Window, ClientData);\nstatic void Togl_WorldChanged(ClientData);\nstatic void Togl_SetViewPort(const struct Togl *);\n\n#ifdef MESA_COLOR_HACK\nstatic int get_free_color_cells(Display *display, int screen,\n        Colormap colormap);\nstatic void free_default_color_cells(Display *display, Colormap colormap);\n#endif\nstatic void ToglCmdDeletedProc(ClientData);\n\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\nstatic void SetMacBufRect(Togl *togl);\n#endif\n\n#if defined(TOGL_WGL)\n#  include \"toglWGL.c\"\n#elif defined(TOGL_AGL)\n#  include \"toglAGL.c\"\n#elif defined(TOGL_NSOPENGL)\n#  include \"toglNSOpenGL.c\"\n#elif defined(TOGL_X11)\n#  include \"toglGLX.c\"\n#endif\n\n\n/* \n * Setup Togl widget configuration options:\n */\n\n#define GEOMETRY_MASK 0x1       /* widget geometry */\n#define FORMAT_MASK 0x2         /* pixel format */\n#define CURSOR_MASK 0x4\n#define TIMER_MASK 0x8\n#define OVERLAY_MASK 0x10\n#define SWAP_MASK 0x20\n#define STEREO_MASK 0x40\n#define STEREO_FORMAT_MASK 0x80\n\nstatic Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_PIXELS, TCL_STUPID \"-height\", \"height\", \"Height\",\n                DEFAULT_HEIGHT, -1, Tk_Offset(Togl, Height), 0, NULL,\n            GEOMETRY_MASK},\n    {TK_OPTION_PIXELS, TCL_STUPID \"-width\", \"width\", \"Width\",\n                DEFAULT_WIDTH, -1, Tk_Offset(Togl, Width), 0, NULL,\n            GEOMETRY_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-pixelscale\", \"pixelscale\", \"PixelScale\",\n            \"1\", -1, Tk_Offset(Togl, PixelScale), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-rgba\", \"rgba\", \"Rgba\",\n            \"true\", -1, Tk_Offset(Togl, RgbaFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-redsize\", \"redsize\", \"RedSize\",\n            \"1\", -1, Tk_Offset(Togl, RgbaRed), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-greensize\", \"greensize\", \"GreenSize\",\n            \"1\", -1, Tk_Offset(Togl, RgbaGreen), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-bluesize\", \"bluesize\", \"BlueSize\",\n            \"1\", -1, Tk_Offset(Togl, RgbaBlue), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-double\", \"double\", \"Double\",\n            \"false\", -1, Tk_Offset(Togl, DoubleFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-depth\", \"depth\", \"Depth\",\n            \"false\", -1, Tk_Offset(Togl, DepthFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-depthsize\", \"depthsize\", \"DepthSize\",\n            \"1\", -1, Tk_Offset(Togl, DepthSize), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-accum\", \"accum\", \"Accum\",\n            \"false\", -1, Tk_Offset(Togl, AccumFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-accumredsize\", \"accumredsize\", \"AccumRedSize\",\n            \"1\", -1, Tk_Offset(Togl, AccumRed), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-accumgreensize\", \"accumgreensize\",\n                \"AccumGreenSize\",\n            \"1\", -1, Tk_Offset(Togl, AccumGreen), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-accumbluesize\", \"accumbluesize\",\n                \"AccumBlueSize\",\n            \"1\", -1, Tk_Offset(Togl, AccumBlue), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-accumalphasize\", \"accumalphasize\",\n                \"AccumAlphaSize\",\n            \"1\", -1, Tk_Offset(Togl, AccumAlpha), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-alpha\", \"alpha\", \"Alpha\",\n            \"false\", -1, Tk_Offset(Togl, AlphaFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-alphasize\", \"alphasize\", \"AlphaSize\",\n            \"1\", -1, Tk_Offset(Togl, AlphaSize), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-stencil\", \"stencil\", \"Stencil\",\n            \"false\", -1, Tk_Offset(Togl, StencilFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-stencilsize\", \"stencilsize\", \"StencilSize\",\n            \"1\", -1, Tk_Offset(Togl, StencilSize), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-auxbuffers\", \"auxbuffers\", \"AuxBuffers\",\n            \"0\", -1, Tk_Offset(Togl, AuxNumber), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-privatecmap\", \"privateCmap\", \"PrivateCmap\",\n                \"false\", -1, Tk_Offset(Togl, PrivateCmapFlag), 0, NULL,\n            FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-overlay\", \"overlay\", \"Overlay\",\n            \"false\", -1, Tk_Offset(Togl, OverlayFlag), 0, NULL, OVERLAY_MASK},\n    {TK_OPTION_CUSTOM, TCL_STUPID \"-stereo\", \"stereo\", \"Stereo\",\n                \"\", -1, Tk_Offset(Togl, Stereo), 0,\n            (ClientData) &stereoOption, STEREO_FORMAT_MASK},\n    {TK_OPTION_DOUBLE, TCL_STUPID \"-eyeseparation\", \"eyeseparation\",\n                \"EyeSeparation\",\n            \"2.0\", -1, Tk_Offset(Togl, EyeSeparation), 0, NULL, STEREO_MASK},\n    {TK_OPTION_DOUBLE, TCL_STUPID \"-convergence\", \"convergence\", \"Convergence\",\n            \"35.0\", -1, Tk_Offset(Togl, Convergence), 0, NULL, STEREO_MASK},\n#ifndef NO_TK_CURSOR\n    {TK_OPTION_CURSOR, TCL_STUPID \"-cursor\", \"cursor\", \"Cursor\",\n                \"\", -1, Tk_Offset(Togl, Cursor), TK_OPTION_NULL_OK, NULL,\n            CURSOR_MASK},\n#endif\n    {TK_OPTION_INT, TCL_STUPID \"-setgrid\", \"setGrid\", \"SetGrid\",\n            \"0\", -1, Tk_Offset(Togl, SetGrid), 0, NULL, GEOMETRY_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-time\", \"time\", \"Time\",\n                DEFAULT_TIME, -1, Tk_Offset(Togl, TimerInterval), 0, NULL,\n            TIMER_MASK},\n    {TK_OPTION_STRING, TCL_STUPID \"-sharelist\", \"sharelist\", \"ShareList\",\n            NULL, -1, Tk_Offset(Togl, ShareList), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_STRING, TCL_STUPID \"-sharecontext\", \"sharecontext\",\n                \"ShareContext\", NULL,\n            -1, Tk_Offset(Togl, ShareContext), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_STRING, TCL_STUPID \"-ident\", \"ident\", \"Ident\",\n            DEFAULT_IDENT, -1, Tk_Offset(Togl, Ident), 0, NULL, 0},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-indirect\", \"indirect\", \"Indirect\",\n            \"false\", -1, Tk_Offset(Togl, Indirect), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_CUSTOM, TCL_STUPID \"-pixelformat\", \"pixelFormat\", \"PixelFormat\",\n                \"0\", -1, Tk_Offset(Togl, PixelFormat), 0,\n            (ClientData) &wideIntOption, FORMAT_MASK},\n    {TK_OPTION_INT, TCL_STUPID \"-swapinterval\", \"swapInterval\", \"SwapInterval\",\n            \"1\", -1, Tk_Offset(Togl, SwapInterval), 0, NULL, SWAP_MASK},\n#if 0\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-fullscreen\", \"fullscreen\", \"Fullscreen\",\n                \"false\", -1, Tk_Offset(Togl, FullscreenFlag), 0, NULL,\n            GEOMETRY_MASK|FORMAT_MASK},\n#endif\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-multisample\", \"multisample\", \"Multisample\",\n                \"false\", -1, Tk_Offset(Togl, MultisampleFlag), 0, NULL,\n            FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-pbuffer\", \"pbuffer\", \"Pbuffer\",\n            \"false\", -1, Tk_Offset(Togl, PbufferFlag), 0, NULL, FORMAT_MASK},\n    {TK_OPTION_BOOLEAN, TCL_STUPID \"-largestpbuffer\", \"largestpbuffer\",\n                \"LargestPbuffer\",\n            \"false\", -1, Tk_Offset(Togl, LargestPbufferFlag), 0, NULL, 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-createcommand\", \"createCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, CreateProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-create\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-createcommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-displaycommand\", \"displayCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, DisplayProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-display\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-displaycommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-reshapecommand\", \"reshapeCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, ReshapeProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-reshape\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-reshapecommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-destroycommand\", \"destroyCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, DestroyProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-destroy\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-destroycommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-timercommand\", \"timerCommand\",\n                \"CallabckCommand\", NULL,\n            Tk_Offset(Togl, TimerProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-timer\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-timercommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-overlaydisplaycommand\",\n                \"overlaydisplayCommand\", \"CallbackCommand\", NULL,\n                Tk_Offset(Togl, OverlayDisplayProc), -1,\n            TK_OPTION_NULL_OK, NULL, OVERLAY_MASK},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-overlaydisplay\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-overlaydisplaycommand\", 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-magnifycommand\", \"magnifyCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, MagnifyProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-rotatecommand\", \"rotateCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, RotateProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-scrollcommand\", \"scrollCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, ScrollProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-scrollwheelcommand\", \"scrollWheelCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, ScrollWheelProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, TCL_STUPID \"-touchescommand\", \"touchesCommand\",\n                \"CallbackCommand\", NULL,\n            Tk_Offset(Togl, TouchesProc), -1, TK_OPTION_NULL_OK, NULL, 0},\n\n    /* Tcl3D backwards compatibility */\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-createproc\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-createcommand\", 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-displayproc\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-displaycommand\", 0},\n    {TK_OPTION_SYNONYM, TCL_STUPID \"-reshapeproc\", NULL, NULL,\n            NULL, -1, -1, 0, (ClientData) \"-reshapecommand\", 0},\n    /* end Tcl3D compatibility */\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, -1, 0, NULL, 0}\n};\n\n/* \n * Add given togl widget to linked list.\n */\nstatic void\nAddToList(Togl *t)\n{\n    t->Next = t->tpg->toglHead;\n    t->tpg->toglHead = t;\n}\n\n/* \n * Remove given togl widget from linked list.\n */\nstatic void\nRemoveFromList(Togl *t)\n{\n    Togl   *prev;\n    Togl   *cur;\n\n    for (cur = t->tpg->toglHead, prev = NULL; cur; prev = cur, cur = cur->Next) {\n        if (t != cur)\n            continue;\n        if (prev) {\n            prev->Next = cur->Next;\n        } else {\n            t->tpg->toglHead = cur->Next;\n        }\n        break;\n    }\n    if (cur)\n        cur->Next = NULL;\n}\n\n/* \n * Return pointer to togl widget given a user identifier string.\n */\nstatic Togl *\nFindTogl(Togl *togl, const char *ident)\n{\n    Togl   *t;\n\n    if (ident[0] != '.') {\n        for (t = togl->tpg->toglHead; t; t = t->Next) {\n            if (strcmp(t->Ident, ident) == 0)\n                break;\n        }\n    } else {\n        for (t = togl->tpg->toglHead; t; t = t->Next) {\n            const char *pathname = Tk_PathName(t->TkWin);\n\n            if (strcmp(pathname, ident) == 0)\n                break;\n        }\n    }\n    return t;\n}\n\n\n/* \n * Return pointer to another togl widget with same OpenGL context.\n */\nstatic Togl *\nFindToglWithSameContext(const Togl *togl)\n{\n    Togl   *t;\n\n    for (t = togl->tpg->toglHead; t != NULL; t = t->Next) {\n        if (t == togl)\n            continue;\n        if (t->Ctx == togl->Ctx) {\n            return t;\n        }\n    }\n    return NULL;\n}\n\n#if TOGL_USE_OVERLAY\n/* \n * Return pointer to another togl widget with same OpenGL overlay context.\n */\nstatic Togl *\nFindToglWithSameOverlayContext(const Togl *togl)\n{\n    Togl   *t;\n\n    for (t = togl->tpg->toglHead; t != NULL; t = t->Next) {\n        if (t == togl)\n            continue;\n#  if defined(TOGL_X11)\n        if (t->OverlayCtx == togl->OverlayCtx)\n#  elif defined(TOGL_WGL)\n        if (t->tglGLOverlayHglrc == togl->tglGLOverlayHglrc)\n#  endif\n        {\n            return t;\n        }\n    }\n    return NULL;\n}\n#endif\n\n#if defined(TOGL_X11)\n/* \n * Return an X colormap to use for OpenGL RGB-mode rendering.\n * Input:  dpy - the X display\n *         scrnum - the X screen number\n *         visinfo - the XVisualInfo as returned by glXChooseVisual()\n * Return:  an X Colormap or 0 if there's a _serious_ error.\n */\nstatic Colormap\nget_rgb_colormap(Display *dpy,\n        int scrnum, const XVisualInfo *visinfo, Tk_Window tkwin)\n{\n    Atom    hp_cr_maps;\n    Status  status;\n    int     numCmaps;\n    int     i;\n    XStandardColormap *standardCmaps;\n    Window  root = XRootWindow(dpy, scrnum);\n    Bool    using_mesa;\n\n    /* \n     * First check if visinfo's visual matches the default/root visual.\n     */\n    if (visinfo->visual == Tk_Visual(tkwin)) {\n        /* use the default/root colormap */\n        Colormap cmap;\n\n        cmap = Tk_Colormap(tkwin);\n#  ifdef MESA_COLOR_HACK\n        (void) get_free_color_cells(dpy, scrnum, cmap);\n#  endif\n        return cmap;\n    }\n\n    /* \n     * Check if we're using Mesa.\n     */\n    if (strstr(glXQueryServerString(dpy, scrnum, GLX_VERSION), \"Mesa\")) {\n        using_mesa = True;\n    } else {\n        using_mesa = False;\n    }\n\n    /* \n     * Next, if we're using Mesa and displaying on an HP with the \"Color\n     * Recovery\" feature and the visual is 8-bit TrueColor, search for a\n     * special colormap initialized for dithering.  Mesa will know how to\n     * dither using this colormap.\n     */\n    if (using_mesa) {\n        hp_cr_maps = XInternAtom(dpy, \"_HP_RGB_SMOOTH_MAP_LIST\", True);\n        if (hp_cr_maps\n#  ifdef __cplusplus\n                && visinfo->visual->c_class == TrueColor\n#  else\n                && visinfo->visual->class == TrueColor\n#  endif\n                && visinfo->depth == 8) {\n            status = XGetRGBColormaps(dpy, root, &standardCmaps,\n                    &numCmaps, hp_cr_maps);\n            if (status) {\n                for (i = 0; i < numCmaps; i++) {\n                    if (standardCmaps[i].visualid == visinfo->visual->visualid) {\n                        Colormap cmap = standardCmaps[i].colormap;\n\n                        (void) XFree(standardCmaps);\n                        return cmap;\n                    }\n                }\n                (void) XFree(standardCmaps);\n            }\n        }\n    }\n\n    /* \n     * Next, try to find a standard X colormap.\n     */\n#  if !HP && !SUN\n#    ifndef SOLARIS_BUG\n    status = XmuLookupStandardColormap(dpy, visinfo->screen,\n            visinfo->visualid, visinfo->depth, XA_RGB_DEFAULT_MAP,\n            /* replace */ False, /* retain */ True);\n    if (status == 1) {\n        status = XGetRGBColormaps(dpy, root, &standardCmaps,\n                &numCmaps, XA_RGB_DEFAULT_MAP);\n        if (status == 1) {\n            for (i = 0; i < numCmaps; i++) {\n                if (standardCmaps[i].visualid == visinfo->visualid) {\n                    Colormap cmap = standardCmaps[i].colormap;\n\n                    (void) XFree(standardCmaps);\n                    return cmap;\n                }\n            }\n            (void) XFree(standardCmaps);\n        }\n    }\n#    endif\n#  endif\n\n    /* \n     * If we get here, give up and just allocate a new colormap.\n     */\n    return XCreateColormap(dpy, root, visinfo->visual, AllocNone);\n}\n#elif defined(TOGL_WGL)\n\n/* Code to create RGB palette is taken from the GENGL sample program of Win32\n * SDK */\n\nstatic const unsigned char threeto8[8] = {\n    0, 0111 >> 1, 0222 >> 1, 0333 >> 1, 0444 >> 1, 0555 >> 1, 0666 >> 1, 0377\n};\n\nstatic const unsigned char twoto8[4] = {\n    0, 0x55, 0xaa, 0xff\n};\n\nstatic const unsigned char oneto8[2] = {\n    0, 255\n};\n\nstatic const int defaultOverride[13] = {\n    0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91\n};\n\nstatic const PALETTEENTRY defaultPalEntry[20] = {\n    {0, 0, 0, 0},\n    {0x80, 0, 0, 0},\n    {0, 0x80, 0, 0},\n    {0x80, 0x80, 0, 0},\n    {0, 0, 0x80, 0},\n    {0x80, 0, 0x80, 0},\n    {0, 0x80, 0x80, 0},\n    {0xC0, 0xC0, 0xC0, 0},\n\n    {192, 220, 192, 0},\n    {166, 202, 240, 0},\n    {255, 251, 240, 0},\n    {160, 160, 164, 0},\n\n    {0x80, 0x80, 0x80, 0},\n    {0xFF, 0, 0, 0},\n    {0, 0xFF, 0, 0},\n    {0xFF, 0xFF, 0, 0},\n    {0, 0, 0xFF, 0},\n    {0xFF, 0, 0xFF, 0},\n    {0, 0xFF, 0xFF, 0},\n    {0xFF, 0xFF, 0xFF, 0}\n};\n\nstatic unsigned char\nComponentFromIndex(int i, UINT nbits, UINT shift)\n{\n    unsigned char val;\n\n    val = (unsigned char) (i >> shift);\n    switch (nbits) {\n\n      case 1:\n          val &= 0x1;\n          return oneto8[val];\n\n      case 2:\n          val &= 0x3;\n          return twoto8[val];\n\n      case 3:\n          val &= 0x7;\n          return threeto8[val];\n\n      default:\n          return 0;\n    }\n}\n\nstatic Colormap\nWin32CreateRgbColormap(PIXELFORMATDESCRIPTOR pfd)\n{\n    TkWinColormap *cmap = (TkWinColormap *) ckalloc(sizeof (TkWinColormap));\n    LOGPALETTE *pPal;\n    int     n, i;\n\n    n = 1 << pfd.cColorBits;\n    pPal = (PLOGPALETTE) LocalAlloc(LMEM_FIXED, sizeof (LOGPALETTE)\n            + n * sizeof (PALETTEENTRY));\n    pPal->palVersion = 0x300;\n    pPal->palNumEntries = n;\n    for (i = 0; i < n; i++) {\n        pPal->palPalEntry[i].peRed =\n                ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);\n        pPal->palPalEntry[i].peGreen =\n                ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);\n        pPal->palPalEntry[i].peBlue =\n                ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);\n        pPal->palPalEntry[i].peFlags = 0;\n    }\n\n    /* fix up the palette to include the default GDI palette */\n    if ((pfd.cColorBits == 8)\n            && (pfd.cRedBits == 3) && (pfd.cRedShift == 0)\n            && (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3)\n            && (pfd.cBlueBits == 2) && (pfd.cBlueShift == 6)) {\n        for (i = 1; i <= 12; i++)\n            pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];\n    }\n\n    cmap->palette = CreatePalette(pPal);\n    LocalFree(pPal);\n    cmap->size = n;\n    cmap->stale = 0;\n\n    /* Since this is a private colormap of a fix size, we do not need a valid\n     * hash table, but a dummy one */\n\n    Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);\n    return (Colormap) cmap;\n}\n\nstatic Colormap\nWin32CreateCiColormap(Togl *togl)\n{\n    /* Create a colormap with size of togl->CiColormapSize and set all entries\n     * to black */\n\n    LOGPALETTE logPalette;\n    TkWinColormap *cmap = (TkWinColormap *) ckalloc(sizeof (TkWinColormap));\n\n    logPalette.palVersion = 0x300;\n    logPalette.palNumEntries = 1;\n    logPalette.palPalEntry[0].peRed = 0;\n    logPalette.palPalEntry[0].peGreen = 0;\n    logPalette.palPalEntry[0].peBlue = 0;\n    logPalette.palPalEntry[0].peFlags = 0;\n\n    cmap->palette = CreatePalette(&logPalette);\n    cmap->size = togl->CiColormapSize;\n    ResizePalette(cmap->palette, cmap->size);   /* sets new entries to black */\n    cmap->stale = 0;\n\n    /* Since this is a private colormap of a fix size, we do not need a valid\n     * hash table, but a dummy one */\n\n    Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);\n    return (Colormap) cmap;\n}\n\n/* ErrorExit is from <http://msdn2.microsoft.com/en-us/library/ms680582.aspx> */\nstatic void\nErrorExit(LPTSTR lpszFunction)\n{\n    /* Retrieve the system error message for the last-error code */\n    LPTSTR  lpMsgBuf;\n    LPTSTR  lpDisplayBuf;\n    DWORD   err = GetLastError();\n\n    if (err == 0) {\n        /* The function said it failed, but GetLastError says it didn't, so\n         * pretend it didn't. */\n        return;\n    }\n\n    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER\n            | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n            NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n            (LPTSTR) &lpMsgBuf, 0, NULL);\n\n    /* Display the error message and exit the process */\n\n    lpDisplayBuf = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,\n            (lstrlen(lpMsgBuf) + lstrlen(lpszFunction) + 40) * sizeof (TCHAR));\n    StringCchPrintf(lpDisplayBuf, LocalSize(lpDisplayBuf),\n            TEXT(\"%s failed with error %ld: %s\"), lpszFunction, err, lpMsgBuf);\n    MessageBox(NULL, lpDisplayBuf, TEXT(\"Error\"), MB_OK);\n\n    LocalFree(lpMsgBuf);\n    LocalFree(lpDisplayBuf);\n    ExitProcess(err);\n}\n#endif\n\n/* \n * Togl_Init\n *\n *   Called upon system startup to create togl command.\n */\nint\nTogl_Init(Tcl_Interp *interp)\n{\n    int     major, minor, patchLevel, releaseType;\n\n#ifdef USE_TCL_STUBS\n    if (Tcl_InitStubs(interp, \"8.1\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n#endif\n#ifdef USE_TK_STUBS\n    if (Tk_InitStubs(interp, TCL_STUPID \"8.1\", 0) == NULL) {\n        return TCL_ERROR;\n    }\n#endif\n\n    Tcl_GetVersion(&major, &minor, &patchLevel, &releaseType);\n#ifdef HAVE_TK_SETCLASSPROCS\n    if (major > 8\n            || (major == 8\n                    && (minor > 4\n                            || (minor == 4 && (releaseType > 0\n                                            || patchLevel >= 2))))) {\n#  ifdef USE_TK_STUBS\n        SetClassProcsPtr = tkStubsPtr->tk_SetClassProcs;\n#  else\n        SetClassProcsPtr = Tk_SetClassProcs;\n#  endif\n    } else {\n        SetClassProcsPtr = NULL;\n    }\n#else\n    if (major > 8\n            || (major == 8\n                    && (minor > 4\n                            || (minor == 4 && (releaseType > 0\n                                            || patchLevel >= 2))))) {\n        TCL_ERR(interp,\n                \"Sorry, this instance of Togl was not compiled to work with Tcl/Tk 8.4a2 or higher.\");\n    }\n#endif\n\n    if (Tcl_CreateObjCommand(interp, \"togl\", Togl_ObjCmd, NULL,\n                    Togl_ObjCmdDelete) == NULL) {\n        return TCL_ERROR;\n    }\n\n    if (Tcl_PkgProvideEx(interp, \"Togl\", TOGL_VERSION, &toglStubs) != TCL_OK) {\n        return TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n\n/* \n * Togl_CallCallback\n *\n * Call command with togl widget as only argument\n */\n\nint\nTogl_CallCallback(Togl *togl, Tcl_Obj *cmd)\n{\n    int     result;\n    Tcl_Obj *objv[3];\n\n    if (cmd == NULL || togl->widgetCmd == NULL)\n        return TCL_OK;\n\n    objv[0] = cmd;\n    Tcl_IncrRefCount(objv[0]);\n    objv[1] =\n            Tcl_NewStringObj(Tcl_GetCommandName(togl->Interp, togl->widgetCmd),\n            -1);\n    Tcl_IncrRefCount(objv[1]);\n    objv[2] = NULL;\n    result = Tcl_EvalObjv(togl->Interp, 2, objv, TCL_EVAL_GLOBAL);\n    Tcl_DecrRefCount(objv[1]);\n    Tcl_DecrRefCount(objv[0]);\n    if (result != TCL_OK)\n        Tcl_BackgroundError(togl->Interp);\n    return result;\n}\n\nstatic int\nTogl_CallCallback_P(Togl *togl, Tcl_Obj *cmd, double *params, int nparams)\n{\n    int     result, i;\n    Tcl_Obj **objv = (Tcl_Obj **)malloc((3+nparams)*sizeof(Tcl_Obj *));\n\n    if (cmd == NULL || togl->widgetCmd == NULL)\n        return TCL_OK;\n\n    objv[0] = cmd;\n    Tcl_IncrRefCount(objv[0]);\n    objv[1] = Tcl_NewStringObj(Tcl_GetCommandName(togl->Interp, togl->widgetCmd), -1);\n    Tcl_IncrRefCount(objv[1]);\n    for (i = 0 ; i < nparams ; ++i) {\n      objv[2+i] = Tcl_NewDoubleObj(params[i]);\n      Tcl_IncrRefCount(objv[2+i]);\n    }\n    objv[2+nparams] = NULL;\n    result = Tcl_EvalObjv(togl->Interp, 2+nparams, objv, TCL_EVAL_GLOBAL);\n    for (i = 1+nparams ; i >= 0 ; --i)\n      Tcl_DecrRefCount(objv[i]);\n    free(objv);\n    if (result != TCL_OK)\n        Tcl_BackgroundError(togl->Interp);\n    return result;\n}\n\n\n/* \n * Togl_Timer\n *\n * Gets called from Tk_CreateTimerHandler.\n */\nstatic void\nTogl_Timer(ClientData clientData)\n{\n    Togl   *togl = (Togl *) clientData;\n\n    if (togl->TimerProc) {\n        if (Togl_CallCallback(togl, togl->TimerProc) != TCL_OK) {\n            togl->timerHandler = NULL;\n            return;\n        }\n        /* \n         * Re-register this callback since Tcl/Tk timers are \"one-shot\".\n         * That is, after the timer callback is called it not normally\n         * called again.  That's not the behavior we want for Togl.\n         */\n        togl->timerHandler =\n                Tcl_CreateTimerHandler(togl->TimerInterval, Togl_Timer,\n                (ClientData) togl);\n    }\n}\n\n\n/* \n * Togl_MakeCurrent\n *\n *   Bind the OpenGL rendering context to the specified\n *   Togl widget.  If given a NULL argument, then the\n *   OpenGL context is released without assigning a new one.\n */\nvoid\nTogl_MakeCurrent(const Togl *togl)\n{\n#if defined(TOGL_WGL)\n    int     res = TRUE;\n\n    if (togl == NULL) {\n        HDC     hdc = wglGetCurrentDC();\n\n        if (hdc != NULL)\n            res = wglMakeCurrent(hdc, NULL);\n    } else {\n        if (togl->pbufferLost) {\n            Bool    keepContext = FindToglWithSameContext(togl) != NULL;\n            Togl   *t = (Togl *) togl;  /* conceptually const */\n\n            if (!keepContext) {\n                wglDeleteContext(t->Ctx);\n            }\n            togl_destroyPbuffer(t);\n            t->pbuf = togl_createPbuffer(t);\n            if (!keepContext) {\n                t->Ctx = wglCreateContext(t->tglGLHdc);\n            }\n        }\n        res = wglMakeCurrent(togl->tglGLHdc, togl->Ctx);\n    }\n    if (!res) {\n        ErrorExit(TEXT(\"wglMakeCurrent\"));\n    }\n#elif defined(TOGL_X11)\n    Display *display = togl ? togl->display : glXGetCurrentDisplay();\n\n    if (display) {\n        GLXDrawable drawable;\n\n        if (!togl)\n            drawable = None;\n        else if (togl->PbufferFlag)\n            drawable = togl->pbuf;\n        else if (togl->TkWin)\n            drawable = Tk_WindowId(togl->TkWin);\n        else\n            drawable = None;\n        (void) glXMakeCurrent(display, drawable, drawable ? togl->Ctx : NULL);\n    }\n#elif defined(TOGL_AGL)\n    if (togl == NULL || togl->Ctx == NULL) {\n        (void) aglSetCurrentContext(NULL);\n    } else {\n        (void) aglSetCurrentContext(togl->Ctx);\n        if (FindToglWithSameContext(togl) != NULL) {\n            if (!togl->PbufferFlag) {\n                AGLDrawable d = Togl_MacOSXGetDrawablePort(togl);\n\n                aglSetDrawable(togl->Ctx, d);\n            } else {\n                GLint   virtualScreen = aglGetVirtualScreen(togl->Ctx);\n\n                aglSetPBuffer(togl->Ctx, togl->pbuf, 0, 0, virtualScreen);\n            }\n        }\n    }\n#elif defined(TOGL_NSOPENGL)\n    if (togl != NULL && togl->Ctx != NULL) {\n        [togl->Ctx makeCurrentContext];\n        if (FindToglWithSameContext(togl) != NULL) {\n            if (!togl->PbufferFlag) {\n\t        [togl->Ctx setView:togl->nsview];\n            } else {\n\t        GLint   virtualScreen =\t[togl->Ctx currentVirtualScreen];\n                [togl->Ctx setPixelBuffer:togl->pbuf cubeMapFace:0\n\t\t mipMapLevel:0 currentVirtualScreen:virtualScreen];\n            }\n        }\n    }\n#endif\n}\n\n/* \n * Togl_TakePhoto\n *\n *   Take a photo image of the current OpenGL window.  May have problems\n *   if window is partially obscured, either by other windows or by the\n *   edges of the display.\n */\nint\nTogl_TakePhoto(Togl *togl, Tk_PhotoHandle photo)\n{\n    GLubyte *buffer;\n    Tk_PhotoImageBlock photoBlock;\n    int     y, midy;\n    unsigned char *cp;\n    int     width = togl->Width, height = togl->Height;\n\n    /* \n     * TIP #116 altered Tk_PhotoPutBlock API to add interp arg that 8.4\n     * doesn't have.\n     * We need to remove that for compiling with 8.4.\n     */\n#if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5)\n#  define TK_PHOTOPUTBLOCK(interp, hdl, blk, x, y, w, h, cr) \\\n   \t\tTk_PhotoPutBlock(hdl, blk, x, y, w, h, cr)\n#else\n#  define TK_PHOTOPUTBLOCK\tTk_PhotoPutBlock\n#endif\n    buffer = (GLubyte *) ckalloc(width * height * 4);\n    photoBlock.pixelPtr = buffer;\n    photoBlock.width = width;\n    photoBlock.height = height;\n    photoBlock.pitch = width * 4;\n    photoBlock.pixelSize = 4;\n    photoBlock.offset[0] = 0;\n    photoBlock.offset[1] = 1;\n    photoBlock.offset[2] = 2;\n    photoBlock.offset[3] = 3;\n\n    if (!togl->RgbaFlag) {\n#if defined(TOGL_WGL)\n        /* Due to the lack of a unique inverse mapping from the frame buffer to\n         * the logical palette we need a translation map from the complete\n         * logical palette. */\n        int     n, i;\n        TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);\n        LPPALETTEENTRY entry = (LPPALETTEENTRY) malloc(togl->MapSize *\n                sizeof (PALETTEENTRY));\n\n        n = GetPaletteEntries(cmap->palette, 0, togl->MapSize, entry);\n        for (i = 0; i < n; i++) {\n            togl->RedMap[i] = (GLfloat) (entry[i].peRed / 255.0);\n            togl->GreenMap[i] = (GLfloat) (entry[i].peGreen / 255.0);\n            togl->BlueMap[i] = (GLfloat) (entry[i].peBlue / 255.0);\n        }\n        free(entry);\n#endif /* TOGL_WGL */\n\n        glPixelMapfv(GL_PIXEL_MAP_I_TO_R, togl->MapSize, togl->RedMap);\n        glPixelMapfv(GL_PIXEL_MAP_I_TO_G, togl->MapSize, togl->GreenMap);\n        glPixelMapfv(GL_PIXEL_MAP_I_TO_B, togl->MapSize, togl->BlueMap);\n    }\n\n    glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);\n    glPixelStorei(GL_PACK_ALIGNMENT, 4);        /* guarantee performance */\n    glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);\n    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);\n\n#if 1\n    glPixelStorei(GL_PACK_ROW_LENGTH, 0);\n    glPixelStorei(GL_PACK_SKIP_ROWS, 0);\n    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);\n    /* Some OpenGL drivers are buggy and return zero for Alpha instead of one\n     * for RGB pixel formats.  If that is happening to you, upgrade your\n     * graphics driver. */\n\n    /* OpenGL's origin is bottom-left, Tk Photo image's is top-left, so mirror\n     * the rows around the middle row. */\n    midy = height / 2;\n    cp = buffer;\n    for (y = 0; y < midy; ++y) {\n        int     m_y = height - 1 - y;   /* mirror y */\n        unsigned char *m_cp = buffer + m_y * photoBlock.pitch;\n        int     x;\n\n        for (x = 0; x < photoBlock.pitch; ++x) {\n            unsigned char c = *cp;\n\n            *cp++ = *m_cp;\n            *m_cp++ = c;\n        }\n    }\n#else\n    /* OpenGL's origin is bottom-left, Tk Photo image's is top-left, so save\n     * rows in reverse order. */\n    glPixelStorei(GL_PACK_ROW_LENGTH, width);\n    glPixelStorei(GL_PACK_SKIP_ROWS, -1);\n    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,\n            buffer + width * (height - 1) * 4);\n#endif\n\n    TK_PHOTOPUTBLOCK(togl->Interp, photo, &photoBlock, 0, 0, width, height,\n            TK_PHOTO_COMPOSITE_SET);\n\n    glPopClientAttrib();        /* restore PACK_ALIGNMENT */\n    ckfree((char *) buffer);\n    return TCL_OK;\n}\n\nBool\nTogl_SwapInterval(const Togl *togl, int interval)\n{\n#ifdef TOGL_AGL\n    GLint   swapInterval = interval;\n\n    return aglSetInteger(togl->Ctx, AGL_SWAP_INTERVAL, &swapInterval);\n#endif\n#ifdef TOGL_NSOPENGL\n    GLint   swapInterval = interval;\n    [togl->Ctx setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];\n    return True;\n#endif\n#ifdef TOGL_WGL\n    typedef BOOL (WINAPI *BOOLFuncInt) (int);\n    typedef const char *(WINAPI *StrFuncHDC) (HDC);\n    static BOOLFuncInt swapInterval = NULL;\n    static BOOL initialized = False;\n\n    if (!initialized) {\n        const char *extensions;\n        StrFuncHDC getExtensionsString;\n\n        getExtensionsString = (StrFuncHDC)\n                wglGetProcAddress(\"wglGetExtensionsStringARB\");\n        if (getExtensionsString == NULL)\n            getExtensionsString = (StrFuncHDC)\n                    wglGetProcAddress(\"wglGetExtensionsStringEXT\");\n        if (getExtensionsString) {\n            extensions = getExtensionsString(togl->tglGLHdc);\n            if (strstr(extensions, \"WGL_EXT_swap_control\") != NULL) {\n                swapInterval =\n                        (BOOLFuncInt) wglGetProcAddress(\"wglSwapIntervalEXT\");\n            }\n        }\n        initialized = True;\n    }\n    if (swapInterval)\n        return swapInterval(interval);\n    return False;\n#endif\n#ifdef TOGL_X11\n    typedef int (*IntFuncInt) (int);\n    static IntFuncInt swapInterval = NULL;\n    static int initialized = False;\n\n    if (!initialized) {\n        const char *extensions = glXQueryExtensionsString(togl->display,\n                Tk_ScreenNumber(togl->TkWin));\n\n        if (strstr(extensions, \"GLX_SGI_swap_control\") != NULL) {\n            swapInterval = (IntFuncInt) Togl_GetProcAddr(\"glXSwapIntervalSGI\");\n        } else if (strstr(extensions, \"GLX_MESA_swap_control\") != NULL) {\n            swapInterval = (IntFuncInt) Togl_GetProcAddr(\"glXSwapIntervalMESA\");\n        }\n        initialized = True;\n    }\n    if (swapInterval)\n        return swapInterval(interval) == 0;\n    return False;\n#endif\n}\n\n#if defined(TOGL_AGL)\n/* tell OpenGL which part of the Mac window to render to */\nstatic void\nSetMacBufRect(Togl *togl)\n{\n    GLint   wrect[4];\n    Rect    r;\n    MacDrawable *d = ((TkWindow *) togl->TkWin)->privatePtr;\n\n    /* set wrect[0,1] to lower left corner of widget */\n    wrect[2] = Tk_Width(togl->TkWin);\n    wrect[3] = Tk_Height(togl->TkWin);\n    wrect[0] = d->xOff;\n\n    GetPortBounds(Togl_MacOSXGetDrawablePort(togl), &r);\n\n    wrect[1] = r.bottom - wrect[3] - d->yOff;\n\n    if (togl->FullscreenFlag) {\n        aglEnable(togl->Ctx, AGL_FS_CAPTURE_SINGLE);\n        aglSetFullScreen(togl->Ctx, 0, 0, 0, 0);\n    } else {\n        aglUpdateContext(togl->Ctx);\n    }\n    aglSetInteger(togl->Ctx, AGL_BUFFER_RECT, wrect);\n    aglEnable(togl->Ctx, AGL_BUFFER_RECT);\n}\n\nstatic void\nReconfigureCB(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags,\n        void *closure)\n{\n    /* Display reconfiguration callback. Documented as needed by Apple QA1209.\n     * Updated for 10.3 (and later) to use\n     * CGDisplayRegisterReconfigurationCallback. */\n    Togl   *togl = (Togl *) closure;\n\n    if (0 != (flags & kCGDisplayBeginConfigurationFlag))\n        return;                 /* wait until display is reconfigured */\n\n    SetMacBufRect(togl);\n    Togl_MakeCurrent(togl);\n    if (togl->Ctx) {\n        if (togl->ReshapeProc) {\n            Togl_CallCallback(togl, togl->ReshapeProc);\n        } else {\n\t    Togl_SetViewPort(togl);\n        }\n    }\n}\n#endif\n\n#if defined(TOGL_NSOPENGL)\n/*\nTODO: It appears that Tk only makes an NSView for toplevel windows.\nAlso it looks like NSOpenGL does not have the equivalent of AGL_BUFFER_RECT\nthat allows opengl drawing to just part of an NSView.  So we might need to\ncreate our own NSView for controlling the opengl bounds.\nLook at TkMacOSXMakeRealWindowExist() in tkMacOSXWm.c.\n*/\n\n/* tell OpenGL which part of the Mac window to render to */\nstatic void\nSetMacBufRect(Togl *togl)\n{\n    Rect r, rt;\n    NSRect    rect;\n    TkWindow *w = (TkWindow *) togl->TkWin;\n    TkWindow *t = w->privatePtr->toplevel->winPtr;\n\n    TkMacOSXWinBounds(w, &r);\n    TkMacOSXWinBounds(t, &rt);\n\n    rect.origin.x = r.left - rt.left;\n    rect.origin.y = rt.bottom - r.bottom;\n    rect.size.width = r.right - r.left;\n    rect.size.height = r.bottom - r.top;\n\n    [togl->nsview setFrame:rect];\n    [togl->Ctx update];\n    \n    /* TODO: Support full screen. */\n}\n\nstatic void\nReconfigureCB(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags,\n        void *closure)\n{\n    /* Display reconfiguration callback. Documented as needed by Apple QA1209.\n     * Updated for 10.3 (and later) to use\n     * CGDisplayRegisterReconfigurationCallback. */\n    Togl   *togl = (Togl *) closure;\n\n    if (0 != (flags & kCGDisplayBeginConfigurationFlag))\n        return;                 /* wait until display is reconfigured */\n\n    SetMacBufRect(togl);\n    Togl_MakeCurrent(togl);\n    if (togl->Ctx) {\n        if (togl->ReshapeProc) {\n            Togl_CallCallback(togl, togl->ReshapeProc);\n        } else {\n            Togl_SetViewPort(togl);\n        }\n    }\n}\n#endif\n\n/* \n * Called when the widget's contents must be redrawn.  Basically, we\n * just call the user's render callback function.\n *\n * Note that the parameter type is ClientData so this function can be\n * passed to Tk_DoWhenIdle().\n */\nstatic void\nTogl_Render(ClientData clientData)\n{\n    Togl   *togl = (Togl *) clientData;\n\n    if (togl->DisplayProc) {\n        Togl_MakeCurrent(togl);\n        Togl_CallCallback(togl, togl->DisplayProc);\n    }\n    togl->UpdatePending = False;\n}\n\n\nstatic void\nTogl_RenderOverlay(ClientData clientData)\n{\n    Togl   *togl = (Togl *) clientData;\n\n    if (togl->OverlayFlag && togl->OverlayDisplayProc) {\n#if defined(TOGL_WGL)\n        int     res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLOverlayHglrc);\n\n        if (!res) {\n            ErrorExit(TEXT(\"wglMakeCurrent overlay\"));\n        }\n#elif defined(TOGL_X11)\n        (void) glXMakeCurrent(Tk_Display(togl->TkWin),\n                togl->OverlayWindow, togl->OverlayCtx);\n#endif /* TOGL_WGL */\n\n        Togl_CallCallback(togl, togl->OverlayDisplayProc);\n    }\n    togl->OverlayUpdatePending = False;\n}\n\n\nstatic int\nTogl_EnterStereo(Togl *togl)\n{\n    if (togl->Stereo == TOGL_STEREO_ROW_INTERLEAVED) {\n        GLint   stencil_bits;\n        Tk_Window top;\n\n        Togl_MakeCurrent(togl);\n        glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);\n        if (stencil_bits == 0) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"need stencil buffer for row interleaved stereo\",\n                    TCL_STATIC);\n            return False;\n        }\n        togl->riStencilBit = 1u << (stencil_bits - 1);\n        glEnable(GL_STENCIL_TEST);\n\n        /* Need to redraw window when moved between odd and even scanlines, so\n         * bind to top level window so we're notified when that happens. */\n        top = togl->TkWin;\n        while (!Tk_IsTopLevel(top)) {\n            top = Tk_Parent(top);\n            if (top == NULL)\n                break;\n        }\n        if (top) {\n            Tk_CreateEventHandler(top, StructureNotifyMask, Togl_RedisplayProc,\n                    (ClientData) togl);\n        }\n    }\n    return True;\n}\n\n\nstatic void\nTogl_LeaveStereo(Togl *togl, int oldStereo)\n{\n    switch (oldStereo) {\n      default:\n          break;\n#ifdef HAVE_AUTOSTEREO\n      case TOGL_STEREO_NATIVE:\n          if (togl->ash != -1) {\n              ASClosedStereoWindow(togl->ash);\n              togl->ash = -1;\n          }\n          break;\n#endif\n#ifdef __sgi\n      case TOGL_STEREO_SGIOLDSTYLE:\n          togl->currentStereoBuffer = STEREO_BUFFER_NONE;\n          glXWaitGL();          /* sync with GL command stream before calling X \n                                 */\n          XSGISetStereoBuffer(togl->display, Tk_WindowId(togl->TkWin),\n                  togl->currentStereoBuffer);\n          glXWaitX();           /* sync with X command stream before calling GL \n                                 */\n          break;\n#endif\n      case TOGL_STEREO_ROW_INTERLEAVED:\n          if (togl->riStencilBit) {\n              Tk_Window top;\n\n              glDisable(GL_STENCIL_TEST);\n\n              /* need to remove previously added top level event handler */\n              top = togl->TkWin;\n              while (!Tk_IsTopLevel(top)) {\n                  top = Tk_Parent(top);\n                  if (top == NULL)\n                      break;\n              }\n              if (top) {\n                  Tk_DeleteEventHandler(top, StructureNotifyMask,\n                          Togl_RedisplayProc, (ClientData) togl);\n              }\n          }\n          break;\n    }\n}\n\n\n/* \n * See domentation about what can't be changed\n */\nstatic int\nTogl_ObjConfigure(Tcl_Interp *interp, Togl *togl,\n        int objc, Tcl_Obj *const *objv)\n{\n    Tk_SavedOptions savedOptions;\n    int     error, mask;\n    int     undoMask = 0;\n    Tcl_Obj *errorResult = NULL;\n    int     oldStereo = togl->Stereo;\n    int     oldWidth = togl->Width;\n    int     oldHeight = togl->Height;\n\n    for (error = 0; error <= 1; ++error, mask = undoMask) {\n        if (error == 0) {\n            /* \n             * Tk_SetOptions parses the command arguments\n             * and looks for defaults in the resource database.\n             */\n            if (Tk_SetOptions(interp, WIDGREC togl, togl->tpg->optionTable,\n                            objc, objv, togl->TkWin, &savedOptions, &mask)\n                    != TCL_OK) {\n                /* previous values are restored, so nothing to do */\n                return TCL_ERROR;\n            }\n        } else {\n            /* \n             * Restore options from saved values\n             */\n            errorResult = Tcl_GetObjResult(interp);\n            Tcl_IncrRefCount(errorResult);\n            Tk_RestoreSavedOptions(&savedOptions);\n        }\n\n        if (togl->Ident && togl->Ident[0] == '.') {\n            Tcl_AppendResult(interp, \"Can not set ident to a window path name\",\n                    NULL);\n            continue;\n        }\n\n        if (togl->FullscreenFlag) {\n            /* override width and height */\n            togl->Width = WidthOfScreen(Tk_Screen(togl->TkWin));\n            togl->Height = HeightOfScreen(Tk_Screen(togl->TkWin));\n            undoMask |= GEOMETRY_MASK;\n        }\n\n        if (mask & GEOMETRY_MASK) {\n            if (!togl->PbufferFlag) {\n                Togl_WorldChanged((ClientData) togl);\n                /* Reset width and height so ConfigureNotify\n                 * event will call reshape callback */\n                togl->Width = oldWidth;\n                togl->Height = oldHeight;\n                undoMask |= GEOMETRY_MASK;\n            }\n        }\n\n        if (mask & OVERLAY_MASK) {\n#if !TOGL_USE_OVERLAY\n            if (togl->OverlayFlag) {\n                Tcl_AppendResult(interp, \"Sorry, overlay was disabled\", NULL);\n                continue;\n            }\n#else\n#  if defined(TOGL_X11)\n            if (togl->OverlayCtx)\n#  elif defined(TOGL_WGL)\n            if (togl->tglGLOverlayHglrc)\n#  endif\n            {\n                /* \n                 * Trying to change existing pixel format/graphics context\n                 */\n                Tcl_AppendResult(interp,\n                        \"Unable to change overlay pixel format\", NULL);\n                continue;\n            }\n#endif\n        }\n\n        if (mask & SWAP_MASK) {\n            if (togl->Ctx) {\n                /* \n                 * Change existing swap interval\n                 */\n                Togl_MakeCurrent(togl); /* TODO: needed? */\n                Togl_SwapInterval(togl, togl->SwapInterval);\n                undoMask |= SWAP_MASK;\n            }\n        }\n\n        if (error == 0 && (mask & STEREO_FORMAT_MASK) != 0) {\n            if (oldStereo == TOGL_STEREO_NATIVE\n                    || togl->Stereo == TOGL_STEREO_NATIVE) {\n                /* only native stereo affects the visual format */\n                mask |= FORMAT_MASK;\n            }\n            if (togl->Stereo == TOGL_STEREO_SGIOLDSTYLE) {\n#ifndef __sgi\n                Tcl_AppendResult(interp,\n                        \"sgioldstyle: only available on SGI computers\", NULL);\n                continue;\n#else\n                int     event, error;\n\n                /* Make sure Display supports SGIStereo */\n                if (XSGIStereoQueryExtension(Tk_Display(togl->TkWin), &event,\n                                &error) == False) {\n                    Tcl_AppendResult(interp,\n                            \"sgioldstyle: SGIStereo X extension is missing\",\n                            NULL);\n                    continue;\n                }\n                /* Make sure Window (Screen) supports SGIStereo */\n                if (XSGIQueryStereoMode(Tk_Display(togl->TkWin),\n                                Tk_WindowId(Tk_Parent(togl->TkWin))) ==\n                        X_STEREO_UNSUPPORTED) {\n                    Tcl_AppendResult(interp,\n                            \"sgioldstyle: unsupported by screen\", NULL);\n                    continue;\n                }\n#endif\n            }\n        }\n\n        if (mask & FORMAT_MASK) {\n            if (togl->Ctx) {\n                /* \n                 * Trying to change existing pixel format/graphics context\n                 * TODO: (re)create graphics context\n                 *\n                 * save old graphics context\n                 * try to create new one and share display lists\n                 * if failure, then restore old one\n                 */\n                Tcl_AppendResult(interp, \"Unable to change pixel format\", NULL);\n                continue;\n            }\n            if (togl->ShareContext && togl->ShareList) {\n                Tcl_AppendResult(interp,\n                        \"only one of -sharelist and -sharecontext allowed\",\n                        NULL);\n                continue;\n            }\n            if (togl->PbufferFlag && togl->Stereo) {\n                Tcl_AppendResult(interp, \"pbuffer not supported with stereo\",\n                        NULL);\n                continue;\n            }\n            if (togl->PbufferFlag && togl->OverlayFlag) {\n                Tcl_AppendResult(interp, \"pbuffer not supported with overlay\",\n                        NULL);\n                continue;\n            }\n            if (togl->FullscreenFlag) {\n#if defined(TOGL_NSOPENGL)\n\t        Tcl_AppendResult(interp,\n                       \"Fullscreen not supported with Cocoa Tk\", NULL);\n                continue;\n#endif\n#ifndef TOGL_AGL\n#  if TK_MAJOR_VERSION < 8 || (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 5)\n                Tcl_AppendResult(interp,\n                        \"Need Tk 8.5 or later for fullscreen support\", NULL);\n                continue;\n#  endif\n#endif\n            }\n            /* Whether or not the format is okay is figured out when togl tries \n             * to create the window. */\n#ifdef MESA_COLOR_HACK\n            free_default_color_cells(Tk_Display(togl->TkWin),\n                    Tk_Colormap(togl->TkWin));\n#endif\n            undoMask |= FORMAT_MASK;\n        }\n\n        if (togl->Ctx) {\n            if (oldStereo != togl->Stereo) {\n                /* leaving stereo */\n                Togl_LeaveStereo(togl, oldStereo);\n                if (togl->Stereo && !Togl_EnterStereo(togl))\n                    continue;\n            }\n        }\n\n        if (mask & TIMER_MASK) {\n            if (togl->timerHandler != NULL) {\n                Tcl_DeleteTimerHandler(togl->timerHandler);\n            }\n            if (togl->TimerProc) {\n                togl->timerHandler =\n                        Tcl_CreateTimerHandler(togl->TimerInterval, Togl_Timer,\n                        (ClientData) togl);\n            }\n            undoMask |= TIMER_MASK;\n        }\n        break;\n    }\n\n    if (error == 0) {\n        Tk_FreeSavedOptions(&savedOptions);\n        return TCL_OK;\n    } else {\n        Tcl_SetObjResult(interp, errorResult);\n        Tcl_DecrRefCount(errorResult);\n        return TCL_ERROR;\n    }\n}\n\n\nstatic int\nTogl_ObjWidget(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl   *togl = (Togl *) clientData;\n    const char *commands[] = {\n        \"cget\", \"configure\", \"extensions\",\n        \"postredisplay\", \"render\",\n        \"swapbuffers\", \"makecurrent\", \"takephoto\",\n        \"loadbitmapfont\", \"unloadbitmapfont\", \"write\",\n        \"uselayer\", \"showoverlay\", \"hideoverlay\",\n        \"postredisplayoverlay\", \"renderoverlay\",\n        \"existsoverlay\", \"ismappedoverlay\",\n        \"getoverlaytransparentvalue\",\n        \"drawbuffer\", \"clear\", \"frustum\", \"ortho\",\n        \"numeyes\", \"contexttag\", \"copycontextto\", \"maketopfortrackpadevents\",\n        NULL\n    };\n    enum command\n    {\n        TOGL_CGET, TOGL_CONFIGURE, TOGL_EXTENSIONS,\n        TOGL_POSTREDISPLAY, TOGL_RENDER,\n        TOGL_SWAPBUFFERS, TOGL_MAKECURRENT, TOGL_TAKEPHOTO,\n        TOGL_LOADBITMAPFONT, TOGL_UNLOADBITMAPFONT, TOGL_WRITE,\n        TOGL_USELAYER, TOGL_SHOWOVERLAY, TOGL_HIDEOVERLAY,\n        TOGL_POSTREDISPLAYOVERLAY, TOGL_RENDEROVERLAY,\n        TOGL_EXISTSOVERLAY, TOGL_ISMAPPEDOVERLAY,\n        TOGL_GETOVERLAYTRANSPARENTVALUE,\n        TOGL_DRAWBUFFER, TOGL_CLEAR, TOGL_FRUSTUM, TOGL_ORTHO,\n        TOGL_NUMEYES, TOGL_CONTEXTTAG, TOGL_COPYCONTEXTTO, TOGL_MAKETOPFORTRACKPADEVENTS\n    };\n    int     result = TCL_OK;\n    Tcl_Obj *objPtr;\n    int     index;\n\n    if (objc < 2) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"command ?arg arg ...?\");\n        return TCL_ERROR;\n    }\n\n    Tk_Preserve((ClientData) togl);\n\n    result = Tcl_GetIndexFromObj(interp, objv[1], commands, \"option\", 0,\n            &index);\n\n    switch (index) {\n      case TOGL_CGET:\n          if (objc != 3) {\n              Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n              result = TCL_ERROR;\n              break;\n          }\n          objPtr = Tk_GetOptionValue(interp, WIDGREC togl,\n                  togl->tpg->optionTable, (objc == 3) ? objv[2] : NULL,\n                  togl->TkWin);\n          if (objPtr == NULL) {\n              result = TCL_ERROR;\n              break;\n          }\n          Tcl_SetObjResult(interp, objPtr);\n          break;\n\n      case TOGL_CONFIGURE:\n          if (objc <= 3) {\n              /* \n               * Return one item if the option is given,\n               * or return all configuration information\n               */\n              objPtr = Tk_GetOptionInfo(interp, WIDGREC togl,\n                      togl->tpg->optionTable, (objc == 3) ? objv[2] : NULL,\n                      togl->TkWin);\n              if (objPtr == NULL) {\n                  result = TCL_ERROR;\n              } else {\n                  Tcl_SetObjResult(interp, objPtr);\n              }\n          } else {\n              /* Execute a configuration change */\n              result = Togl_ObjConfigure(interp, togl, objc - 2, objv + 2);\n          }\n          break;\n\n      case TOGL_EXTENSIONS:\n          /* Return a list of OpenGL extensions available */\n          /* TODO: -glu for glu extensions, -platform for glx/wgl extensions */\n          if (objc == 2) {\n              const char *extensions;\n              Tcl_Obj *objPtr;\n              int     length = -1;\n\n              extensions = (const char *) glGetString(GL_EXTENSIONS);\n              objPtr = Tcl_NewStringObj(extensions, -1);\n              /* convert to list by asking for its length */\n              (void) Tcl_ListObjLength(interp, objPtr, &length);\n              Tcl_SetObjResult(interp, objPtr);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_POSTREDISPLAY:\n          /* schedule the widget to be redrawn */\n          if (objc == 2) {\n              Togl_PostRedisplay(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_RENDER:\n          /* force the widget to be redrawn */\n          if (objc == 2) {\n              Togl_Render((ClientData) togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_SWAPBUFFERS:\n          /* force the widget to be redrawn */\n          if (objc == 2) {\n              Togl_SwapBuffers(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_MAKECURRENT:\n          /* force the widget to be redrawn */\n          if (objc == 2) {\n              Togl_MakeCurrent(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_TAKEPHOTO:\n      {\n          /* force the widget to be redrawn */\n          if (objc != 3) {\n              Tcl_WrongNumArgs(interp, 2, objv, \"name\");\n              result = TCL_ERROR;\n          } else {\n              const char *name;\n              Tk_PhotoHandle photo;\n\n              name = Tcl_GetStringFromObj(objv[2], NULL);\n              photo = Tk_FindPhoto(interp, name);\n              if (photo == NULL) {\n                  Tcl_AppendResult(interp, \"image \\\"\", name,\n                          \"\\\" doesn't exist or is not a photo image\", NULL);\n                  result = TCL_ERROR;\n                  break;\n              }\n              glPushAttrib(GL_PIXEL_MODE_BIT);\n              if (togl->DoubleFlag) {\n                  glReadBuffer(GL_FRONT);\n              }\n              Togl_TakePhoto(togl, photo);\n              glPopAttrib();    /* restore glReadBuffer */\n          }\n          break;\n      }\n\n      case TOGL_LOADBITMAPFONT:\n#if TOGL_USE_FONTS != 1\n          Tcl_AppendResult(interp, \"unsupported\", NULL);\n          result = TCL_ERROR;\n#else\n          if (objc >= 3) {\n              Tcl_Obj *font, *list;\n\n              list = Tcl_NewListObj(objc - 2, objv + 2);\n              Tcl_IncrRefCount(list);\n              font = Togl_LoadBitmapFont(togl, Tcl_GetString(list));\n              Tcl_DecrRefCount(list);\n              if (font) {\n                  Tcl_SetObjResult(interp, font);\n                  result = TCL_OK;\n              } else {\n                  Tcl_AppendResult(interp, \"Could not allocate font\", NULL);\n                  result = TCL_ERROR;\n              }\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, \"fontname\");\n              result = TCL_ERROR;\n          }\n#endif\n          break;\n\n      case TOGL_UNLOADBITMAPFONT:\n#if TOGL_USE_FONTS != 1\n          Tcl_AppendResult(interp, \"unsupported\", NULL);\n          result = TCL_ERROR;\n#else\n          if (objc == 3) {\n              result = Togl_UnloadBitmapFont(togl, objv[2]);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, \"toglfont\");\n              result = TCL_ERROR;\n          }\n#endif\n          break;\n\n      case TOGL_WRITE:{\n#if TOGL_USE_FONTS != 1\n          Tcl_AppendResult(interp, \"unsupported\", NULL);\n          result = TCL_ERROR;\n#else\n          /* Tcl_Obj *toglfont = objv[2]; */\n          int     wobjc = objc - 3;\n          Tcl_Obj *const *wobjv = objv + 3;\n\n          while (wobjc > 1) {\n              const char *name = Tcl_GetStringFromObj(wobjv[0], NULL);\n              int     oc, i;\n              Tcl_Obj **ov;\n              double  args[4];\n\n              if (Tcl_ListObjGetElements(NULL, wobjv[1], &oc, &ov) != TCL_OK) {\n                  oc = 0;\n              } else if (oc <= 4) {\n                  for (i = 0; i < oc; ++i) {\n                      if (Tcl_GetDoubleFromObj(NULL, ov[i], &args[i]) != TCL_OK) {\n                      }\n                  }\n              }\n              if (strcmp(name, \"-color\") == 0) {\n                  if (oc == 4)\n                      glColor4d(args[0], args[1], args[2], args[3]);\n                  else if (oc == 3)\n                      glColor3d(args[0], args[1], args[2]);\n                  else\n                      goto write_usage;\n              } else if (strcmp(name, \"-pos\") == 0) {\n                  if (oc == 4)\n                      glRasterPos4d(args[0], args[1], args[2], args[3]);\n                  else if (oc == 3)\n                      glRasterPos3d(args[0], args[1], args[2]);\n                  else if (oc == 2)\n                      glRasterPos2d(args[0], args[1]);\n                  else\n                      goto write_usage;\n              } else\n                  goto write_usage;\n              wobjc -= 2;\n              wobjv += 2;\n          }\n          if (wobjc != 1)\n              goto write_usage;\n          result = Togl_WriteObj(togl, objv[2], wobjv[0]);\n          if (result != -1)\n              result = TCL_OK;\n          else {\n              Tcl_AppendResult(interp, \"togl write failed\", NULL);\n              result = TCL_ERROR;\n          }\n          break;\n        write_usage:\n          Tcl_WrongNumArgs(interp, 2, objv, \"[-pos {x y [z [w]]}]\"\n                  \" [-color {r g b [a]}\" \" string\");\n          result = TCL_ERROR;\n#endif\n          break;\n      }\n\n      case TOGL_USELAYER:\n          if (objc == 3) {\n              int     layer;\n\n              result = Tcl_GetIntFromObj(interp, objv[2], &layer);\n              if (result == TCL_OK) {\n                  Togl_UseLayer(togl, layer);\n              }\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, \"layer\");\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_SHOWOVERLAY:\n          if (objc == 2) {\n              Togl_ShowOverlay(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_HIDEOVERLAY:\n          if (objc == 2) {\n              Togl_HideOverlay(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_POSTREDISPLAYOVERLAY:\n          if (objc == 2) {\n              Togl_PostOverlayRedisplay(togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_RENDEROVERLAY:\n          /* force the overlay to be redrawn */\n          if (objc == 2) {\n              Togl_RenderOverlay((ClientData) togl);\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_EXISTSOVERLAY:\n          if (objc == 2) {\n              Tcl_SetObjResult(interp, Tcl_NewIntObj(Togl_ExistsOverlay(togl)));\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_ISMAPPEDOVERLAY:\n          if (objc == 2) {\n              Tcl_SetObjResult(interp,\n                      Tcl_NewIntObj(Togl_IsMappedOverlay(togl)));\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_GETOVERLAYTRANSPARENTVALUE:\n          if (objc == 2) {\n              Tcl_SetObjResult(interp,\n                      Tcl_NewIntObj(Togl_GetOverlayTransparentValue(togl)));\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_DRAWBUFFER:\n          if (objc != 3) {\n              Tcl_WrongNumArgs(interp, 2, objv, \"mode\");\n              result = TCL_ERROR;\n          } else {\n              int     mask;\n\n              result = Tcl_GetIntFromObj(interp, objv[2], &mask);\n              if (result == TCL_ERROR)\n                  break;\n              Togl_DrawBuffer(togl, (GLenum) mask);\n          }\n          break;\n\n      case TOGL_CLEAR:\n          if (objc != 3) {\n              Tcl_WrongNumArgs(interp, 2, objv, \"mask\");\n              result = TCL_ERROR;\n          } else {\n              int     mask;\n\n              result = Tcl_GetIntFromObj(interp, objv[2], &mask);\n              if (result == TCL_ERROR)\n                  break;\n              Togl_Clear(togl, (GLbitfield) mask);\n          }\n          break;\n\n      case TOGL_FRUSTUM:\n          if (objc != 8) {\n              Tcl_WrongNumArgs(interp, 2, objv,\n                      \"left right bottom top near far\");\n              result = TCL_ERROR;\n          } else {\n              double  left, right, bottom, top, zNear, zFar;\n\n              if (Tcl_GetDoubleFromObj(interp, objv[2], &left) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[3],\n                              &right) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[4],\n                              &bottom) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[5],\n                              &top) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[6],\n                              &zNear) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[7],\n                              &zFar) == TCL_ERROR) {\n                  result = TCL_ERROR;\n                  break;\n              }\n              Togl_Frustum(togl, left, right, bottom, top, zNear, zFar);\n          }\n          break;\n\n      case TOGL_ORTHO:\n          if (objc != 8) {\n              Tcl_WrongNumArgs(interp, 2, objv,\n                      \"left right bottom top near far\");\n              result = TCL_ERROR;\n          } else {\n              double  left, right, bottom, top, zNear, zFar;\n\n              if (Tcl_GetDoubleFromObj(interp, objv[2], &left) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[3],\n                              &right) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[4],\n                              &bottom) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[5],\n                              &top) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[6],\n                              &zNear) == TCL_ERROR\n                      || Tcl_GetDoubleFromObj(interp, objv[7],\n                              &zFar) == TCL_ERROR) {\n                  result = TCL_ERROR;\n                  break;\n              }\n              Togl_Ortho(togl, left, right, bottom, top, zNear, zFar);\n          }\n          break;\n\n      case TOGL_NUMEYES:\n          if (objc == 2) {\n              Tcl_SetObjResult(interp, Tcl_NewIntObj(Togl_NumEyes(togl)));\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_CONTEXTTAG:\n          if (objc == 2) {\n              Tcl_SetObjResult(interp, Tcl_NewIntObj(Togl_ContextTag(togl)));\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n\n      case TOGL_COPYCONTEXTTO:\n          if (objc != 4) {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          } else {\n              Togl   *to;\n              unsigned int mask;\n\n              if (Togl_GetToglFromObj(togl->Interp, objv[2], &to) == TCL_ERROR\n                      || Tcl_GetIntFromObj(togl->Interp, objv[3],\n                              (int *) &mask) == TCL_ERROR) {\n                  result = TCL_ERROR;\n                  break;\n              }\n              result = Togl_CopyContext(togl, to, mask);\n          }\n#ifdef TOGL_NSOPENGL\n    case TOGL_MAKETOPFORTRACKPADEVENTS:\n          if (objc == 2) {\n\t    // This hack places the Togl NSView at the top of sibling views so that it receives\n\t    // trackpad events.  The hierarchy is not used for drawing, nor for mouse event dispatching.\n\t    [togl->nsview retain];\n\t    [togl->nsview removeFromSuperview];\n\t    MacDrawable *d = ((TkWindow *) togl->TkWin)->privatePtr;\n\t    NSView *topview = d->toplevel->view;\n\t    [topview addSubview:togl->nsview];\n\t    [togl->nsview release];\n          } else {\n              Tcl_WrongNumArgs(interp, 2, objv, NULL);\n              result = TCL_ERROR;\n          }\n          break;\n#endif\n    }\n\n    Tk_Release((ClientData) togl);\n    return result;\n}\n\n/* \n * Togl_ObjCmdDelete\n *\n * Called when togl command is removed from interpreter.\n */\n\nstatic void\nTogl_ObjCmdDelete(ClientData clientData)\n{\n    if (clientData != NULL) {\n        Togl_PackageGlobals *tpg = (Togl_PackageGlobals *) clientData;\n\n        Tk_DeleteOptionTable(tpg->optionTable);\n        ckfree((char *) clientData);\n    }\n}\n\n\n/* \n * Togl_ObjCmd\n *\n *   Called when Togl is executed - creation of a Togl widget.\n *     * Creates a new window\n *     * Creates an 'Togl' data structure\n *     * Creates an event handler for this window\n *     * Creates a command that handles this object\n *     * Configures this Togl for the given arguments\n */\nint\nTogl_ObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,\n        Tcl_Obj *const *objv)\n{\n    Togl_PackageGlobals *tpg;\n    Togl   *togl;\n    Tk_Window tkwin;\n    Tcl_SavedResult saveError;\n\n    if (objc <= 1) {\n        Tcl_WrongNumArgs(interp, 1, objv, \"pathName ?options?\");\n        return TCL_ERROR;\n    }\n    tpg = (Togl_PackageGlobals *) clientData;\n    if (tpg == NULL) {\n        Tcl_CmdInfo info;\n        const char *name;\n\n        /* \n         * Initialize the Togl_PackageGlobals for this widget the\n         * first time a Togl widget is created.  The globals are\n         * saved as our client data.\n         */\n\n        tpg = (Togl_PackageGlobals *) ckalloc(sizeof (Togl_PackageGlobals));\n        if (tpg == NULL) {\n            return TCL_ERROR;\n        }\n        tpg->nextContextTag = 0;\n        tpg->optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n        tpg->toglHead = NULL;\n\n        name = Tcl_GetString(objv[0]);\n        Tcl_GetCommandInfo(interp, name, &info);\n        info.objClientData = (ClientData) tpg;\n        Tcl_SetCommandInfo(interp, name, &info);\n    }\n\n    /* Create the window. */\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n            Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n        return TCL_ERROR;\n    }\n\n    Tk_SetClass(tkwin, \"Togl\");\n\n    /* Create Togl data structure */\n    togl = (Togl *) ckalloc(sizeof (Togl));\n    if (togl == NULL) {\n        return TCL_ERROR;\n    }\n\n    /* initialize Togl data structures values */\n    togl->Next = NULL;\n    togl->Ctx = NULL;\n#if defined(TOGL_WGL)\n    togl->tglGLHdc = NULL;\n    togl->tglGLOverlayHglrc = NULL;\n#elif defined(TOGL_X11)\n    togl->OverlayCtx = NULL;\n#endif\n    togl->contextTag = 0;\n    togl->display = Tk_Display(tkwin);\n    togl->TkWin = tkwin;\n    togl->Interp = interp;\n    togl->VisInfo = NULL;\n    togl->OverlayWindow = None;\n    togl->OverlayCmap = None;\n    togl->OverlayTransparentPixel = 0;\n    togl->OverlayIsMapped = False;\n\n    togl->UpdatePending = False;\n    togl->OverlayUpdatePending = False;\n    togl->tpg = tpg;\n    togl->Client_Data = NULL;\n\n    /* for color index mode photos */\n    togl->RedMap = togl->GreenMap = togl->BlueMap = NULL;\n    togl->MapSize = 0;\n\n#ifndef NO_TK_CURSOR\n    togl->Cursor = None;\n#endif\n    togl->Width = 0;\n    togl->Height = 0;\n    togl->PixelScale = 1;\n    togl->SetGrid = 0;\n    togl->TimerInterval = 0;\n    togl->RgbaFlag = True;\n    togl->RgbaRed = 1;\n    togl->RgbaGreen = 1;\n    togl->RgbaBlue = 1;\n    togl->DoubleFlag = False;\n    togl->DepthFlag = False;\n    togl->DepthSize = 1;\n    togl->AccumFlag = False;\n    togl->AccumRed = 1;\n    togl->AccumGreen = 1;\n    togl->AccumBlue = 1;\n    togl->AccumAlpha = 1;\n    togl->AlphaFlag = False;\n    togl->AlphaSize = 1;\n    togl->StencilFlag = False;\n    togl->StencilSize = 1;\n    togl->OverlayFlag = False;\n    togl->Stereo = TOGL_STEREO_NONE;\n    togl->EyeSeparation = 0;\n    togl->Convergence = 0;\n    togl->riStencilBit = 0;\n    togl->AuxNumber = 0;\n    togl->Indirect = False;\n    togl->PixelFormat = 0;\n    togl->SwapInterval = 1;\n    togl->MultisampleFlag = False;\n    togl->FullscreenFlag = False;\n    togl->PbufferFlag = False;\n    togl->LargestPbufferFlag = False;\n#if defined(TOGL_X11)\n    togl->fbcfg = None;\n    togl->pbuf = None;\n#elif defined(TOGL_WGL)\n    togl->pbuf = None;\n    togl->pbufferLost = 0;\n#elif defined(TOGL_AGL)\n    togl->pbuf = NULL;\n#elif defined(TOGL_NSOPENGL)\n    togl->pbuf = NULL;\n#endif\n\n    togl->CreateProc = NULL;\n    togl->DisplayProc = NULL;\n    togl->ReshapeProc = NULL;\n    togl->DestroyProc = NULL;\n    togl->TimerProc = NULL;\n    togl->timerHandler = NULL;\n    togl->OverlayDisplayProc = NULL;\n    togl->MagnifyProc = NULL;\n    togl->RotateProc = NULL;\n    togl->ScrollProc = NULL;\n    togl->ScrollWheelProc = NULL;\n    togl->TouchesProc = NULL;\n    togl->ShareList = NULL;\n    togl->ShareContext = NULL;\n    togl->Ident = NULL;\n    togl->PrivateCmapFlag = False;\n    togl->currentStereoBuffer = STEREO_BUFFER_NONE;\n#ifdef HAVE_AUTOSTEREO\n    togl->as_initialized = False;\n    togl->ash = -1;\n#endif\n    togl->badWindow = False;\n\n    /* Create command event handler */\n    togl->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),\n            Togl_ObjWidget, (ClientData) togl, ToglCmdDeletedProc);\n\n    /* \n     * Setup the Tk_ClassProcs callbacks to point at our own window creation\n     * function\n     *\n     * We need to check at runtime if we should use the new Tk_SetClassProcs()\n     * API or if we need to modify the window structure directly\n     */\n#ifdef HAVE_TK_SETCLASSPROCS\n\n    if (SetClassProcsPtr != NULL) {     /* use public API (Tk 8.4+) */\n        Tk_ClassProcs *procsPtr;\n\n        procsPtr = (Tk_ClassProcs *) ckalloc(sizeof (Tk_ClassProcs));\n        procsPtr->size = sizeof (Tk_ClassProcs);\n        procsPtr->createProc = Togl_MakeWindow;\n        procsPtr->worldChangedProc = Togl_WorldChanged;\n        procsPtr->modalProc = NULL;\n        /* Tk_SetClassProcs(togl->TkWin, procsPtr, (ClientData) togl); */\n        (SetClassProcsPtr) (togl->TkWin, procsPtr, (ClientData) togl);\n    } else\n#endif\n    {                           /* use private API */\n        /* \n         * We need to set these fields in the Tk_FakeWin structure: dummy17 =\n         * classProcsPtr dummy18 = instanceData */\n        TkClassProcs *procsPtr;\n        Tk_FakeWin *winPtr = (Tk_FakeWin *) (togl->TkWin);\n\n        procsPtr = (TkClassProcs *) ckalloc(sizeof (TkClassProcs));\n        procsPtr->createProc = Togl_MakeWindow;\n        procsPtr->geometryProc = Togl_WorldChanged;\n        procsPtr->modalProc = NULL;\n        winPtr->dummy17 = (char *) procsPtr;\n        winPtr->dummy18 = (ClientData) togl;\n    }\n\n    Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,\n            Togl_EventProc, (ClientData) togl);\n\n    /* Configure Togl widget */\n    if (Tk_InitOptions(interp, WIDGREC togl, tpg->optionTable, tkwin) != TCL_OK\n            || Togl_ObjConfigure(interp, togl, objc - 2, objv + 2) != TCL_OK) {\n        goto error;\n    }\n\n    /* \n     * If OpenGL window wasn't already created by Togl_ObjConfigure() we\n     * create it now.  We can tell by checking if the OpenGL context has\n     * been initialized.\n     */\n    if (!togl->Ctx) {\n        Tk_MakeWindowExist(togl->TkWin);\n        if (togl->badWindow) {\n            goto error;\n        }\n    }\n    Togl_MakeCurrent(togl);\n    if (togl->contextTag == 0)\n        togl->contextTag = ++tpg->nextContextTag;\n\n    (void) Togl_SwapInterval(togl, togl->SwapInterval);\n\n    /* If defined, call create callback */\n    if (togl->CreateProc) {\n        if (Togl_CallCallback(togl, togl->CreateProc) != TCL_OK) {\n            goto error;\n        }\n    }\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    if (!togl->PbufferFlag)\n        SetMacBufRect(togl);\n#endif\n    /* If defined, call reshape proc */\n    if (togl->ReshapeProc) {\n        if (Togl_CallCallback(togl, togl->ReshapeProc) != TCL_OK) {\n            goto error;\n        }\n    } else {\n        Togl_SetViewPort(togl);\n#if defined(TOGL_X11)\n        if (togl->OverlayFlag) {\n            Togl_UseLayer(togl, TOGL_OVERLAY);\n            Togl_SetViewPort(togl);\n            Togl_UseLayer(togl, TOGL_NORMAL);\n        }\n#endif\n    }\n\n    if (togl->Stereo && !Togl_EnterStereo(togl))\n        goto error;\n\n    Tcl_AppendResult(interp, Tk_PathName(tkwin), NULL);\n\n    /* Add to linked list */\n    AddToList(togl);\n\n    return TCL_OK;\n\n  error:\n    Tcl_SaveResult(interp, &saveError);\n    togl->badWindow = True;\n    (void) Tcl_DeleteCommandFromToken(interp, togl->widgetCmd);\n    Tcl_RestoreResult(interp, &saveError);\n    Tcl_AppendResult(interp, \"\\nCouldn't configure togl widget\", NULL);\n    return TCL_ERROR;\n}\n\n\n#if TOGL_USE_OVERLAY\n\n/* \n * Do all the setup for overlay planes\n * Return:   TCL_OK or TCL_ERROR\n */\nstatic int\nSetupOverlay(Togl *togl)\n{\n#  if defined(TOGL_X11)\n\n#    ifdef GLX_TRANSPARENT_TYPE_EXT\n    static int ovAttributeList[] = {\n        GLX_BUFFER_SIZE, 2,\n        GLX_LEVEL, 1,\n        GLX_TRANSPARENT_TYPE_EXT, GLX_TRANSPARENT_INDEX_EXT,\n        None\n    };\n#    else\n    static int ovAttributeList[] = {\n        GLX_BUFFER_SIZE, 2,\n        GLX_LEVEL, 1,\n        None\n    };\n#    endif\n\n    XVisualInfo *visinfo;\n    TkWindow *winPtr = (TkWindow *) togl->TkWin;\n\n    XSetWindowAttributes swa;\n    Tcl_HashEntry *hPtr;\n    int     new_flag;\n\n    visinfo =\n            glXChooseVisual(togl->display, Tk_ScreenNumber(winPtr),\n            ovAttributeList);\n    if (!visinfo) {\n        Tcl_AppendResult(togl->Interp, Tk_PathName(winPtr),\n                \": No suitable overlay index visual available\", NULL);\n        togl->OverlayCtx = NULL;\n        togl->OverlayWindow = 0;\n        togl->OverlayCmap = 0;\n        return TCL_ERROR;\n    }\n#    ifdef GLX_TRANSPARENT_INDEX_EXT\n    {\n        int     fail = glXGetConfig(togl->display, visinfo,\n                GLX_TRANSPARENT_INDEX_VALUE_EXT,\n                &togl->OverlayTransparentPixel);\n\n        if (fail)\n            togl->OverlayTransparentPixel = 0;  /* maybe, maybe ... */\n    }\n#    else\n    togl->OverlayTransparentPixel = 0;  /* maybe, maybe ... */\n#    endif\n\n    /* share display lists with normal layer context */\n    togl->OverlayCtx = glXCreateContext(togl->display, visinfo, togl->Ctx,\n            !togl->Indirect);\n\n    swa.colormap = XCreateColormap(togl->display,\n            XRootWindow(togl->display, visinfo->screen),\n            visinfo->visual, AllocNone);\n    togl->OverlayCmap = swa.colormap;\n\n    swa.border_pixel = 0;\n    swa.event_mask = ALL_EVENTS_MASK;\n    togl->OverlayWindow = XCreateWindow(togl->display,\n            Tk_WindowId(togl->TkWin), 0, 0,\n            togl->Width, togl->Height, 0,\n            visinfo->depth, InputOutput,\n            visinfo->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);\n\n    hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,\n            (const char *) togl->OverlayWindow, &new_flag);\n    Tcl_SetHashValue(hPtr, winPtr);\n\n    /* XMapWindow(togl->display, togl->OverlayWindow); */\n    togl->OverlayIsMapped = False;\n\n    /* Make sure window manager installs our colormap */\n    XSetWMColormapWindows(togl->display, togl->OverlayWindow,\n            &togl->OverlayWindow, 1);\n\n    return TCL_OK;\n\n#  elif defined(TOGL_WGL) || defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    /* not yet implemented on these */\n    return TCL_ERROR;\n#  endif\n}\n\n#endif /* TOGL_USE_OVERLAY */\n\n\n\n#ifdef TOGL_WGL\n#  define TOGL_CLASS_NAME \"Togl Class\"\nstatic Bool ToglClassInitialized = False;\n\nstatic LRESULT CALLBACK\nWin32WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\n{\n    LONG    result;\n    Togl   *togl = (Togl *) GetWindowLongPtr(hwnd, 0);\n    WNDCLASS childClass;\n\n    switch (message) {\n\n      case WM_WINDOWPOSCHANGED:\n          /* Should be processed by DefWindowProc, otherwise a double buffered\n           * context is not properly resized when the corresponding window is\n           * resized. */\n          break;\n\n      case WM_DESTROY:\n          if (togl && togl->TkWin != NULL) {\n              if (togl->SetGrid > 0) {\n                  Tk_UnsetGrid(togl->TkWin);\n              }\n              (void) Tcl_DeleteCommandFromToken(togl->Interp, togl->widgetCmd);\n          }\n          break;\n\n      case WM_ERASEBKGND:\n          /* We clear our own window */\n          return 1;\n\n      case WM_DISPLAYCHANGE:\n          if (togl->PbufferFlag && hasARBPbuffer && !togl->pbufferLost) {\n              queryPbuffer(togl->pbuf, WGL_PBUFFER_LOST_ARB,\n                      &togl->pbufferLost);\n          }\n          /* FALLTHROUGH */\n\n      default:\n#  if USE_STATIC_LIB\n          return TkWinChildProc(hwnd, message, wParam, lParam);\n#  else\n          /* \n           * OK, since TkWinChildProc is not explicitly exported in the\n           * dynamic libraries, we have to retrieve it from the class info\n           * registered with windows.\n           *\n           */\n          if (tkWinChildProc == NULL) {\n              GetClassInfo(Tk_GetHINSTANCE(), TK_WIN_CHILD_CLASS_NAME,\n                      &childClass);\n              tkWinChildProc = childClass.lpfnWndProc;\n          }\n          return tkWinChildProc(hwnd, message, wParam, lParam);\n#  endif\n    }\n    result = DefWindowProc(hwnd, message, wParam, lParam);\n    Tcl_ServiceAll();\n    return result;\n}\n#endif /* TOGL_WGL */\n\n\n/* \n * Togl_MakeWindow\n *\n *   Window creation function, invoked as a callback from Tk_MakeWindowExist.\n *   This is called instead of TkpMakeWindow and must always succeed.\n */\nstatic Window\nTogl_MakeWindow(Tk_Window tkwin, Window parent, ClientData instanceData)\n{\n    Togl   *togl = (Togl *) instanceData;\n    Display *dpy;\n    Colormap cmap;\n    int     scrnum;\n    Window  window = None;\n\n#if defined(TOGL_X11)\n    Bool    directCtx = True;\n    XSetWindowAttributes swa;\n    int     width, height;\n#elif defined(TOGL_WGL)\n    HWND    hwnd, parentWin;\n    DWORD   style;\n    HINSTANCE hInstance;\n    PIXELFORMATDESCRIPTOR pfd;\n    int     width, height;\n    Bool    createdPbufferDC = False;\n#elif defined(TOGL_AGL)\n#endif\n\n    if (togl->badWindow) {\n        TkWindow *winPtr = (TkWindow *) tkwin;\n\n        return TkpMakeWindow(winPtr, parent);\n    }\n\n    /* for color index mode photos */\n    if (togl->RedMap)\n        free(togl->RedMap);\n    if (togl->GreenMap)\n        free(togl->GreenMap);\n    if (togl->BlueMap)\n        free(togl->BlueMap);\n    togl->RedMap = togl->GreenMap = togl->BlueMap = NULL;\n    togl->MapSize = 0;\n\n    dpy = Tk_Display(tkwin);\n    scrnum = Tk_ScreenNumber(tkwin);\n\n    /* \n     * Windows and Mac OS X need the window created before OpenGL context\n     * is created.  So do that now and set the window variable. \n     */\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    {\n        TkWindow *winPtr = (TkWindow *) tkwin;\n\n        window = TkpMakeWindow(winPtr, parent);\n        if (!togl->PbufferFlag)\n            (void) XMapWindow(dpy, window);\n    }\n#elif defined(TOGL_WGL)\n    hInstance = Tk_GetHINSTANCE();\n    if (!ToglClassInitialized) {\n        WNDCLASS ToglClass;\n\n        ToglClassInitialized = True;\n        ToglClass.style = CS_HREDRAW | CS_VREDRAW;\n        ToglClass.cbClsExtra = 0;\n        ToglClass.cbWndExtra = sizeof (LONG_PTR);       /* to save Togl* */\n        ToglClass.hInstance = hInstance;\n        ToglClass.hbrBackground = NULL;\n        ToglClass.lpszMenuName = NULL;\n        ToglClass.lpszClassName = TOGL_CLASS_NAME;\n        ToglClass.lpfnWndProc = Win32WinProc;\n        ToglClass.hIcon = NULL;\n        ToglClass.hCursor = NULL;\n        if (!RegisterClass(&ToglClass)) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable register Togl window class\", TCL_STATIC);\n            goto error;\n        }\n    }\n\n    /* duplicate tkpMakeWindow logic from tk8.[45]/win/tkWinWindow.c */\n    if (parent != None) {\n        parentWin = Tk_GetHWND(parent);\n        style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;\n    } else {\n        parentWin = NULL;\n        style = WS_POPUP | WS_CLIPCHILDREN;\n    }\n    if (togl->PbufferFlag) {\n        width = height = 1;     /* TODO: demo code mishaves when set to 1000 */\n    } else {\n        width = togl->Width;\n        height = togl->Height;\n    }\n    hwnd = CreateWindowEx(WS_EX_NOPARENTNOTIFY, TOGL_CLASS_NAME, NULL, style,\n            0, 0, width, height, parentWin, NULL, hInstance, NULL);\n    SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\n            SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n    window = Tk_AttachHWND(tkwin, hwnd);\n    SetWindowLongPtr(hwnd, 0, (LONG_PTR) togl);\n    if (togl->PbufferFlag) {\n        ShowWindow(hwnd, SW_HIDE);      /* make sure it's hidden */\n    }\n#endif\n\n    /* \n     * Figure out which OpenGL context to use\n     */\n\n#ifdef TOGL_WGL\n    togl->tglGLHdc = GetDC(hwnd);\n#endif\n    if (togl->PixelFormat) {\n#if defined(TOGL_X11)\n        XVisualInfo template;\n        int     count = 0;\n\n        template.visualid = togl->PixelFormat;\n        togl->VisInfo = XGetVisualInfo(dpy, VisualIDMask, &template, &count);\n        if (togl->VisInfo == NULL) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"missing visual information\", TCL_STATIC);\n            goto error;\n        }\n#endif\n        if (!togl_describePixelFormat(togl)) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"couldn't choose pixel format\", TCL_STATIC);\n            goto error;\n        }\n    } else {\n#if defined(TOGL_X11)\n        togl->VisInfo = togl_pixelFormat(togl, scrnum);\n        if (togl->VisInfo == NULL)\n#elif defined(TOGL_WGL) || defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n#  ifdef TOGL_WGL\n        togl->PixelFormat = togl_pixelFormat(togl, hwnd);\n#  elif defined(TOGL_NSOPENGL)\n        togl->PixelFormat = (void *)togl_pixelFormat(togl);\n#  else\n        togl->PixelFormat = (Tcl_WideInt)togl_pixelFormat(togl);\n#  endif\n        if (togl->PixelFormat == 0)\n#endif\n        {\n            goto error;\n        }\n    }\n#ifdef TOGL_WGL\n    if (togl->PbufferFlag) {\n        togl->pbuf = togl_createPbuffer(togl);\n        if (togl->pbuf == NULL) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"couldn't create pbuffer\", TCL_STATIC);\n            goto error;\n        }\n        ReleaseDC(hwnd, togl->tglGLHdc);\n        togl->tglGLHdc = getPbufferDC(togl->pbuf);\n        createdPbufferDC = True;\n    } else if (SetPixelFormat(togl->tglGLHdc, (int) togl->PixelFormat,\n                    NULL) == FALSE) {\n        Tcl_SetResult(togl->Interp, TCL_STUPID \"couldn't set pixel format\",\n                TCL_STATIC);\n        goto error;\n    }\n#endif\n#if defined(TOGL_WGL) || defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    if (togl->VisInfo == NULL) {\n        /* \n         * Create a new OpenGL rendering context. And check to share lists.\n         */\n        Visual *visual;\n\n        /* Just for portability, define the simplest visinfo */\n        visual = DefaultVisual(dpy, scrnum);\n        togl->VisInfo = (XVisualInfo *) calloc(1, sizeof (XVisualInfo));\n        togl->VisInfo->screen = scrnum;\n        togl->VisInfo->visual = visual;\n        togl->VisInfo->visualid = visual->visualid;\n#  if defined(__cplusplus) || defined(c_plusplus)\n        togl->VisInfo->c_class = visual->c_class;\n#  else\n        togl->VisInfo->class = visual->class;\n#  endif\n        togl->VisInfo->depth = visual->bits_per_rgb;\n    }\n#endif\n\n#if defined(TOGL_X11)\n    if (togl->Indirect) {\n        directCtx = False;\n    }\n#endif\n\n    /* \n     * Create a new OpenGL rendering context.\n     */\n#if defined(TOGL_X11)\n    if (togl->ShareList) {\n        /* share display lists with existing togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareList);\n        GLXContext shareCtx;\n        int     error_code;\n\n        if (shareWith) {\n            shareCtx = shareWith->Ctx;\n            togl->contextTag = shareWith->contextTag;\n        } else {\n            shareCtx = None;\n        }\n        if (shareCtx) {\n            togl_SetupXErrorHandler();\n        }\n        togl->Ctx = glXCreateContext(dpy, togl->VisInfo, shareCtx, directCtx);\n        if (shareCtx && (error_code = togl_CheckForXError(togl))) {\n            char    buf[256];\n\n            togl->Ctx = NULL;\n            XGetErrorText(dpy, error_code, buf, sizeof buf);\n            Tcl_AppendResult(togl->Interp,\n                    \"unable to share display lists: \", buf, NULL);\n            goto error;\n        }\n    } else {\n        if (togl->ShareContext && FindTogl(togl, togl->ShareContext)) {\n            /* share OpenGL context with existing Togl widget */\n            Togl   *shareWith = FindTogl(togl, togl->ShareContext);\n\n            if (togl->VisInfo->visualid != shareWith->VisInfo->visualid) {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"unable to share OpenGL context\",\n                        TCL_STATIC);\n                goto error;\n            }\n            togl->Ctx = shareWith->Ctx;\n        } else {\n            /* don't share display lists */\n            togl->ShareContext = False;\n            togl->Ctx = glXCreateContext(dpy, togl->VisInfo, None, directCtx);\n        }\n    }\n#elif defined(TOGL_WGL)\n    if (togl->ShareContext && FindTogl(togl, togl->ShareContext)) {\n        /* share OpenGL context with existing Togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareContext);\n\n        if (togl->PixelFormat != shareWith->PixelFormat) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share OpenGL context\", TCL_STATIC);\n            goto error;\n        }\n        togl->Ctx = shareWith->Ctx;\n    } else {\n        togl->Ctx = wglCreateContext(togl->tglGLHdc);\n    }\n\n    if (togl->ShareList) {\n        /* share display lists with existing togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareList);\n\n        if (shareWith) {\n            if (!wglShareLists(shareWith->Ctx, togl->Ctx)) {\n#  if 0\n                LPVOID  lpMsgBuf;\n                DWORD   err = GetLastError();\n\n                FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                        FORMAT_MESSAGE_FROM_SYSTEM,\n                        NULL, err,\n                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n                        (LPTSTR) &lpMsgBuf, 0, NULL);\n                fprintf(stderr, \"unable to share display lists: %d: %s\\n\",\n                        err, lpMsgBuf);\n                LocalFree(lpMsgBuf);\n#  endif\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"unable to share display lists\", TCL_STATIC);\n                goto error;\n            }\n            togl->contextTag = shareWith->contextTag;\n        }\n    }\n#elif defined(TOGL_AGL)\n    AGLContext shareCtx = NULL;\n\n    if (togl->ShareList) {\n        /* share display lists with existing togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareList);\n\n        if (shareWith) {\n            shareCtx = shareWith->Ctx;\n            togl->contextTag = shareWith->contextTag;\n        }\n    }\n    if (togl->ShareContext && FindTogl(togl, togl->ShareContext)) {\n        /* share OpenGL context with existing Togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareContext);\n\n        if (togl->PixelFormat != shareWith->PixelFormat) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share OpenGL context\", TCL_STATIC);\n            goto error;\n        }\n        togl->Ctx = shareWith->Ctx;\n    } else if ((togl->Ctx = aglCreateContext((AGLPixelFormat) togl->PixelFormat,\n                            shareCtx)) == NULL) {\n        GLenum  err = aglGetError();\n\n        aglDestroyPixelFormat((AGLPixelFormat) togl->PixelFormat);\n        togl->PixelFormat = 0;\n        if (err == AGL_BAD_MATCH)\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share display lists\"\n                    \": shared context doesn't match\", TCL_STATIC);\n        else if (err == AGL_BAD_CONTEXT)\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share display lists\"\n                    \": bad shared context\", TCL_STATIC);\n        else if (err == AGL_BAD_PIXELFMT)\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"could not create rendering context\"\n                    \": bad pixel format\", TCL_STATIC);\n        else\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"could not create rendering context\"\n                    \": unknown reason\", TCL_STATIC);\n        goto error;\n    }\n\n    if (!togl->PbufferFlag\n            && !aglSetDrawable(togl->Ctx, Togl_MacOSXGetDrawablePort(togl))) {\n        /* aglSetDrawable is deprecated in OS X 10.5 */\n        aglDestroyContext(togl->Ctx);\n        togl->Ctx = NULL;\n        aglDestroyPixelFormat((AGLPixelFormat) togl->PixelFormat);\n        togl->PixelFormat = 0;\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"couldn't set drawable\", TCL_STATIC);\n        goto error;\n    }\n#elif defined(TOGL_NSOPENGL)\n    NSOpenGLContext *shareCtx = NULL;\n    if (togl->ShareList) {\n        /* share display lists with existing togl widget */\n        Togl   *shareWith = FindTogl(togl, togl->ShareList);\n\n        if (shareWith) {\n            shareCtx = shareWith->Ctx;\n            togl->contextTag = shareWith->contextTag;\n        }\n    }\n    if (togl->ShareContext && FindTogl(togl, togl->ShareContext)) {\n        /* share OpenGL context with existing Togl widget */\n      Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share NSOpenGL context\", TCL_STATIC);\n      goto error;\n      /*\n        Togl   *shareWith = FindTogl(togl, togl->ShareContext);\n\n        if (togl->PixelFormat != shareWith->PixelFormat) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to share OpenGL context\", TCL_STATIC);\n            goto error;\n        }\n\ttogl->Ctx = [[NSOpenGLContext alloc] initWithCGLContextObj:shareWith->Ctx];\n      */\n\t/* initWithCGLContextObj requires Mac OS 10.6 */\n    } else {\n      togl->Ctx = [NSOpenGLContext alloc];\n      if ([togl->Ctx initWithFormat:togl->PixelFormat shareContext:shareCtx]\n\t  == nil)\n\t{\n\t  [togl->PixelFormat release];\n\t  togl->PixelFormat = 0;\n\t  Tcl_SetResult(togl->Interp,\n\t\t\tTCL_STUPID \"Could not obtain OpenGL context\",\n\t\t\tTCL_STATIC);\n\t  goto error;\n\t}\n    }\n\n    if (!togl->PbufferFlag) {\n      togl->nsview = [[ToglNSView alloc] initWithFrame:NSZeroRect];\n      [togl->nsview setTogl:togl];\n      if ([togl->nsview respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {\n\t[togl->nsview setWantsBestResolutionOpenGLSurface:YES];\n      }\n      [togl->nsview setAcceptsTouchEvents:YES];\n      MacDrawable *d = ((TkWindow *) togl->TkWin)->privatePtr;\n      NSView *topview = d->toplevel->view;\n      [topview addSubview:togl->nsview];\n      /* TODO: Appears setView has to be deferred until window mapped.\n       * or it gives \"invalid drawable\" error.  But MapNotify doesn't happen.\n       * I think toplevel is already mapped.  Iconifying and uniconifying\n       * main window makes the graphics work.\n       */\n      /*      [togl->Ctx setView:togl->nsview];*/\n    }\n#endif\n\n    if (togl->Ctx == NULL) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"could not create rendering context\", TCL_STATIC);\n        goto error;\n    }\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    CGDisplayRegisterReconfigurationCallback(ReconfigureCB, togl);\n#endif\n\n    if (togl->PbufferFlag) {\n        /* Don't need a colormap, nor overlay, nor be displayed */\n#if defined(TOGL_X11) || defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n        togl->pbuf = togl_createPbuffer(togl);\n        if (!togl->pbuf) {\n            /* tcl result set in togl_createPbuffer */\n#  ifdef TOGL_AGL\n            if (!togl->ShareContext) {\n                aglDestroyContext(togl->Ctx);\n                aglDestroyPixelFormat((AGLPixelFormat) togl->PixelFormat);\n            }\n            togl->Ctx = NULL;\n            togl->PixelFormat = 0;\n#  endif\n#  ifdef TOGL_NSOPENGL\n            if (!togl->ShareContext) {\n\t        [togl->Ctx release];\n\t\t[togl->PixelFormat release];\n            }\n            togl->Ctx = NULL;\n            togl->PixelFormat = 0;\n#  endif\n            goto error;\n        }\n#  ifdef TOGL_X11\n        window = TkpMakeWindow((TkWindow *) tkwin, parent);\n#  endif\n#endif\n        return window;\n    }\n#ifdef TOGL_WGL\n    DescribePixelFormat(togl->tglGLHdc, (int) togl->PixelFormat, sizeof (pfd),\n            &pfd);\n#endif\n\n    /* \n     * find a colormap\n     */\n    if (togl->RgbaFlag) {\n        /* Colormap for RGB mode */\n#if defined(TOGL_X11)\n        cmap = get_rgb_colormap(dpy, scrnum, togl->VisInfo, tkwin);\n#elif defined(TOGL_WGL)\n        if (pfd.dwFlags & PFD_NEED_PALETTE) {\n            cmap = Win32CreateRgbColormap(pfd);\n        } else {\n            cmap = DefaultColormap(dpy, scrnum);\n        }\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n        cmap = DefaultColormap(dpy, scrnum);\n#endif\n    } else {\n        /* Colormap for CI mode */\n#ifdef TOGL_WGL\n        /* this logic is to overcome a combination driver/compiler bug: (1)\n         * cColorBits may be unusually large (e.g., 32 instead of 8 or 12) and\n         * (2) 1 << 32 might be 1 instead of zero (gcc for ia32) */\n        if (pfd.cColorBits >= MAX_CI_COLORMAP_BITS) {\n            togl->CiColormapSize = MAX_CI_COLORMAP_SIZE;\n        } else {\n            togl->CiColormapSize = 1 << pfd.cColorBits;\n            if (togl->CiColormapSize >= MAX_CI_COLORMAP_SIZE)\n                togl->CiColormapSize = MAX_CI_COLORMAP_SIZE;\n        }\n\n#endif\n        if (togl->PrivateCmapFlag) {\n            /* need read/write colormap so user can store own color entries */\n#if defined(TOGL_X11)\n            cmap = XCreateColormap(dpy, XRootWindow(dpy, togl->VisInfo->screen),\n                    togl->VisInfo->visual, AllocAll);\n#elif defined(TOGL_WGL)\n            cmap = Win32CreateCiColormap(togl);\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n            /* need to figure out how to do this correctly on Mac... */\n            cmap = DefaultColormap(dpy, scrnum);\n#endif\n        } else {\n            if (togl->VisInfo->visual == DefaultVisual(dpy, scrnum)) {\n                /* share default/root colormap */\n                cmap = Tk_Colormap(tkwin);\n            } else {\n                /* make a new read-only colormap */\n                cmap = XCreateColormap(dpy,\n                        XRootWindow(dpy, togl->VisInfo->screen),\n                        togl->VisInfo->visual, AllocNone);\n            }\n        }\n    }\n\n    /* Make sure Tk knows to switch to the new colormap when the cursor is over\n     * this window when running in color index mode. */\n    (void) Tk_SetWindowVisual(tkwin, togl->VisInfo->visual,\n            togl->VisInfo->depth, cmap);\n\n#ifdef TOGL_WGL\n    /* Install the colormap */\n    SelectPalette(togl->tglGLHdc, ((TkWinColormap *) cmap)->palette, TRUE);\n    RealizePalette(togl->tglGLHdc);\n#endif\n\n#if defined(TOGL_X11)\n    swa.background_pixmap = None;\n    swa.border_pixel = 0;\n    swa.colormap = cmap;\n    swa.event_mask = ALL_EVENTS_MASK;\n    if (togl->PbufferFlag) {\n        width = height = 1;\n    } else {\n        width = togl->Width;\n        height = togl->Height;\n    }\n    window = XCreateWindow(dpy, parent,\n            0, 0, width, height,\n            0, togl->VisInfo->depth, InputOutput, togl->VisInfo->visual,\n            CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask, &swa);\n    /* Make sure window manager installs our colormap */\n    (void) XSetWMColormapWindows(dpy, window, &window, 1);\n\n    if (!togl->DoubleFlag) {\n        int     dbl_flag;\n\n        /* See if we requested single buffering but had to accept a double\n         * buffered visual.  If so, set the GL draw buffer to be the front\n         * buffer to simulate single buffering. */\n        if (glXGetConfig(dpy, togl->VisInfo, GLX_DOUBLEBUFFER, &dbl_flag)) {\n            if (dbl_flag) {\n                glXMakeCurrent(dpy, window, togl->Ctx);\n                glDrawBuffer(GL_FRONT);\n                glReadBuffer(GL_FRONT);\n            }\n        }\n    }\n#elif defined(TOGL_WGL)\n    if (!togl->DoubleFlag) {\n        /* See if we requested single buffering but had to accept a double\n         * buffered visual.  If so, set the GL draw buffer to be the front\n         * buffer to simulate single buffering. */\n        if (getPixelFormatAttribiv == NULL) {\n            /* pfd is already set */\n            if ((pfd.dwFlags & PFD_DOUBLEBUFFER) != 0) {\n                wglMakeCurrent(togl->tglGLHdc, togl->Ctx);\n                glDrawBuffer(GL_FRONT);\n                glReadBuffer(GL_FRONT);\n            }\n        } else {\n            static int attribs[] = {\n                WGL_DOUBLE_BUFFER_ARB,\n            };\n#  define NUM_ATTRIBS (sizeof attribs / sizeof attribs[0])\n            int     info[NUM_ATTRIBS];\n\n            getPixelFormatAttribiv(togl->tglGLHdc, (int) togl->PixelFormat, 0,\n                    NUM_ATTRIBS, attribs, info);\n#  undef NUM_ATTRIBS\n            if (info[0]) {\n                wglMakeCurrent(togl->tglGLHdc, togl->Ctx);\n                glDrawBuffer(GL_FRONT);\n                glReadBuffer(GL_FRONT);\n            }\n        }\n    }\n#endif\n\n#if TOGL_USE_OVERLAY\n    if (togl->OverlayFlag) {\n        if (SetupOverlay(togl) == TCL_ERROR) {\n            fprintf(stderr, \"Warning: couldn't setup overlay.\\n\");\n            togl->OverlayFlag = False;\n        }\n    }\n#endif\n\n#if !defined(TOGL_AGL)\n    /* Request the X window to be displayed */\n    (void) XMapWindow(dpy, window);\n#endif\n\n    if (!togl->RgbaFlag) {\n        int     index_size;\n\n#if defined(TOGL_X11) || defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n        GLint   index_bits;\n\n        glGetIntegerv(GL_INDEX_BITS, &index_bits);\n        index_size = 1 << index_bits;\n#elif defined(TOGL_WGL)\n        index_size = togl->CiColormapSize;\n#endif\n        if (togl->MapSize != index_size) {\n            if (togl->RedMap)\n                free(togl->RedMap);\n            if (togl->GreenMap)\n                free(togl->GreenMap);\n            if (togl->BlueMap)\n                free(togl->BlueMap);\n            togl->MapSize = index_size;\n            togl->RedMap = (GLfloat *) calloc(index_size, sizeof (GLfloat));\n            togl->GreenMap = (GLfloat *) calloc(index_size, sizeof (GLfloat));\n            togl->BlueMap = (GLfloat *) calloc(index_size, sizeof (GLfloat));\n        }\n    }\n#ifdef HAVE_AUTOSTEREO\n    if (togl->Stereo == TOGL_STEREO_NATIVE) {\n        if (!togl->as_initialized) {\n            const char *autostereod;\n\n            togl->as_initialized = True;\n            if ((autostereod = getenv(\"AUTOSTEREOD\")) == NULL)\n                autostereod = AUTOSTEREOD;\n            if (autostereod && *autostereod) {\n                if (ASInitialize(togl->display, autostereod) == Success) {\n                    togl->ash = ASCreatedStereoWindow(dpy);\n                }\n            }\n        } else {\n            togl->ash = ASCreatedStereoWindow(dpy);\n        }\n    }\n#endif\n\n    return window;\n\n  error:\n\n    togl->badWindow = True;\n\n#if defined(TOGL_X11)\n    if (window == None) {\n        TkWindow *winPtr = (TkWindow *) tkwin;\n\n        window = TkpMakeWindow(winPtr, parent);\n    }\n#elif defined(TOGL_WGL)\n    if (togl->tglGLHdc) {\n        if (createdPbufferDC)\n            releasePbufferDC(togl->pbuf, togl->tglGLHdc);\n        else\n            ReleaseDC(hwnd, togl->tglGLHdc);\n        togl->tglGLHdc = NULL;\n    }\n#endif\n    return window;\n}\n\n/* \n * Togl_WorldChanged\n *\n *    Add support for setgrid option.\n */\nstatic void\nTogl_WorldChanged(ClientData instanceData)\n{\n    Togl   *togl = (Togl *) instanceData;\n    int     width;\n    int     height;\n\n    if (togl->PbufferFlag)\n        width = height = 1;\n    else {\n        width = togl->Width;\n        height = togl->Height;\n    }\n    Tk_GeometryRequest(togl->TkWin, width, height);\n    Tk_SetInternalBorder(togl->TkWin, 0);\n    if (togl->SetGrid > 0) {\n        Tk_SetGrid(togl->TkWin, width / togl->SetGrid,\n                height / togl->SetGrid, togl->SetGrid, togl->SetGrid);\n    } else {\n        Tk_UnsetGrid(togl->TkWin);\n    }\n}\n\nstatic void\nTogl_SetViewPort(const struct Togl *togl)\n{\n  glViewport(0, 0, togl->Width*togl->PixelScale, togl->Height*togl->PixelScale);\n}\n\n/* \n * ToglFree\n *\n *      Wrap the ckfree macro.\n */\nstatic void\nToglFree(char *clientData)\n{\n    ckfree(clientData);\n}\n\n/* \n * ToglCmdDeletedProc\n *\n *      This procedure is invoked when a widget command is deleted.  If\n *      the widget isn't already in the process of being destroyed,\n *      this command destroys it.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      The widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\nstatic void\nToglCmdDeletedProc(ClientData clientData)\n{\n    Togl   *togl = (Togl *) clientData;\n    Tk_Window tkwin = togl->TkWin;\n\n    /* \n     * This procedure could be invoked either because the window was\n     * destroyed and the command was then deleted (in which case tkwin\n     * is NULL) or because the command was deleted, and then this procedure\n     * destroys the widget.\n     */\n\n    if (tkwin) {\n        Tk_DeleteEventHandler(tkwin, ExposureMask | StructureNotifyMask,\n                Togl_EventProc, (ClientData) togl);\n    }\n\n    Tk_Preserve((ClientData) togl);\n    Tcl_EventuallyFree((ClientData) togl, ToglFree);\n\n    Togl_LeaveStereo(togl, togl->Stereo);\n\n    if (togl->DestroyProc) {\n        /* call user's cleanup code */\n        Togl_CallCallback(togl, togl->DestroyProc);\n    }\n\n    if (togl->TimerProc != NULL) {\n        Tcl_DeleteTimerHandler(togl->timerHandler);\n        togl->timerHandler = NULL;\n    }\n    if (togl->UpdatePending) {\n        Tcl_CancelIdleCall(Togl_Render, (ClientData) togl);\n        togl->UpdatePending = False;\n    }\n#ifndef NO_TK_CURSOR\n    if (togl->Cursor != None) {\n        Tk_FreeCursor(togl->display, togl->Cursor);\n        togl->Cursor = None;\n    }\n#endif\n\n    /* remove from linked list */\n    RemoveFromList(togl);\n\n    togl->TkWin = NULL;\n    if (tkwin != NULL) {\n\n        if (togl->Ctx) {\n            if (FindToglWithSameContext(togl) == NULL) {\n#if defined(TOGL_X11)\n                glXDestroyContext(togl->display, togl->Ctx);\n#elif defined(TOGL_WGL)\n                wglDeleteContext(togl->Ctx);\n#elif defined(TOGL_AGL)\n                aglDestroyContext(togl->Ctx);\n                CGDisplayRemoveReconfigurationCallback(ReconfigureCB, togl);\n#elif defined(TOGL_NSOPENGL)\n\t\t[togl->Ctx release];\n\t\ttogl->Ctx = nil;\n\t\t[togl->nsview setTogl:nil];\n\t\t[togl->nsview release];\n\t\ttogl->nsview = nil;\n                CGDisplayRemoveReconfigurationCallback(ReconfigureCB, togl);\n#endif\n#if defined(TOGL_X11)\n                XFree(togl->VisInfo);\n#else\n                free(togl->VisInfo);\n#endif\n            }\n#if defined(TOGL_WGL)\n            if (togl->tglGLHdc) {\n                if (togl->PbufferFlag) {\n                    releasePbufferDC(togl->pbuf, togl->tglGLHdc);\n                } else {\n                    HWND    hwnd = Tk_GetHWND(Tk_WindowId(tkwin));\n\n                    ReleaseDC(hwnd, togl->tglGLHdc);\n                }\n                togl->tglGLHdc = NULL;\n            }\n#endif\n            if (togl->PbufferFlag && togl->pbuf) {\n                togl_destroyPbuffer(togl);\n                togl->pbuf = 0;\n            }\n            togl->Ctx = NULL;\n            togl->VisInfo = NULL;\n        }\n#if defined(TOGL_X11)\n#  if TOGL_USE_OVERLAY\n        if (togl->OverlayCtx) {\n            Tcl_HashEntry *entryPtr;\n            TkWindow *winPtr = (TkWindow *) tkwin;\n\n            if (winPtr) {\n                entryPtr = Tcl_FindHashEntry(&winPtr->dispPtr->winTable,\n                        (const char *) togl->OverlayWindow);\n                Tcl_DeleteHashEntry(entryPtr);\n            }\n            if (FindToglWithSameOverlayContext(togl) == NULL)\n                glXDestroyContext(togl->display, togl->OverlayCtx);\n            togl->OverlayCtx = NULL;\n        }\n#  endif /* TOGL_USE_OVERLAY */\n#endif\n\n        if (togl->SetGrid > 0) {\n            Tk_UnsetGrid(tkwin);\n        }\n        Tk_DestroyWindow(tkwin);\n    }\n\n    Tk_Release((ClientData) togl);\n}\n\n\n/* \n * This gets called to track top level position changes for\n * row interleaved stereo.\n */\nstatic void\nTogl_RedisplayProc(ClientData clientData, XEvent *eventPtr)\n{\n    Togl   *togl = (Togl *) clientData;\n\n    switch (eventPtr->type) {\n      case ConfigureNotify:\n          Togl_PostRedisplay(togl);\n          break;\n    }\n}\n\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\nstatic int\nviewPixelScale(NSView *nsview)\n{\n  int pixelScale = 1;\n  if ([nsview respondsToSelector:@selector(convertRectToBacking:)])\n    {\n      NSRect wbounds = [nsview bounds];\n      NSRect gbounds = [nsview convertRectToBacking:wbounds];\n      pixelScale = (wbounds.size.width > 0 ?\n\t\t    gbounds.size.width / wbounds.size.width : 1);\n    }\n  return pixelScale;\n}\n#endif\n\n/* \n * This gets called to handle Togl window configuration events\n */\nstatic void\nTogl_EventProc(ClientData clientData, XEvent *eventPtr)\n{\n    Togl   *togl = (Togl *) clientData;\n\n    switch (eventPtr->type) {\n      case Expose:\n#if defined(TOGL_NSOPENGL)\n          if (!Tk_IsMapped(togl->TkWin))\n              /* Tk Cocoa generates expose events for unmapped windows! */\n              break;\n#endif\n          if (eventPtr->xexpose.count == 0) {\n              if (!togl->UpdatePending\n                      && eventPtr->xexpose.window == Tk_WindowId(togl->TkWin)) {\n                  Togl_PostRedisplay(togl);\n              }\n#if defined(TOGL_X11)\n              if (!togl->OverlayUpdatePending && togl->OverlayFlag\n                      && togl->OverlayIsMapped\n                      && eventPtr->xexpose.window == togl->OverlayWindow) {\n                  Togl_PostOverlayRedisplay(togl);\n              }\n#endif\n#if defined(TOGL_NSOPENGL)\n              [togl->Ctx setView:togl->nsview];\n              SetMacBufRect(togl);\n#endif\n          }\n          break;\n      case ConfigureNotify:\n          if (togl->PbufferFlag)\n              break;\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n\t  int pixelScale = viewPixelScale(togl->nsview);\n          if (togl->Width == Tk_Width(togl->TkWin)\n\t      && togl->Height == Tk_Height(togl->TkWin)\n\t      && togl->PixelScale == pixelScale) {\n\n              // Even though the size hasn't changed,\n              // it's position on the screen may have.\n              if (Tk_IsMapped(togl->TkWin))\n                  SetMacBufRect(togl);\n              break;\n          }\n#endif\n          togl->Width = Tk_Width(togl->TkWin);\n          togl->Height = Tk_Height(togl->TkWin);\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n\t  togl->PixelScale = pixelScale;\n#endif\n          (void) XResizeWindow(Tk_Display(togl->TkWin),\n                  Tk_WindowId(togl->TkWin), togl->Width, togl->Height);\n#if defined(TOGL_X11)\n          if (togl->OverlayFlag) {\n              (void) XResizeWindow(Tk_Display(togl->TkWin),\n                      togl->OverlayWindow, togl->Width, togl->Height);\n              (void) XRaiseWindow(Tk_Display(togl->TkWin), togl->OverlayWindow);\n          }\n#endif\n\n#if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n          SetMacBufRect(togl);\n#endif\n\n          Togl_MakeCurrent(togl);\n          if (togl->ReshapeProc) {\n              Togl_SetViewPort(togl);\n              (void) Togl_CallCallback(togl, togl->ReshapeProc);\n          } else {\n              Togl_SetViewPort(togl);\n#if defined(TOGL_X11)\n              if (togl->OverlayFlag) {\n                  Togl_UseLayer(togl, TOGL_OVERLAY);\n                  Togl_SetViewPort(togl);\n                  Togl_UseLayer(togl, TOGL_NORMAL);\n              }\n#endif\n          }\n          break;\n      case MapNotify:\n#if defined(TOGL_AGL)\n          if (!togl->PbufferFlag) {\n              /* \n               * See comment for the UnmapNotify case below.\n               */\n              AGLDrawable d = Togl_MacOSXGetDrawablePort(togl);\n\n              /* aglSetDrawable is deprecated in OS X 10.5 */\n              aglSetDrawable(togl->Ctx, d);\n              SetMacBufRect(togl);\n          }\n#endif\n#if defined(TOGL_NSOPENGL)\n          if (!togl->PbufferFlag) {\n              /* \n               * See comment for the UnmapNotify case below.\n               */\n\t      [togl->Ctx setView:togl->nsview];\n              SetMacBufRect(togl);\n          }\n#endif\n          break;\n      case UnmapNotify:\n#if defined(TOGL_AGL)\n          if (!togl->PbufferFlag) {\n              /* \n               * For Mac OS X Aqua, Tk subwindows are not implemented as\n               * separate Aqua windows.  They are just different regions of\n               * a single Aqua window.  To unmap them they are just not drawn.\n               * Have to disconnect the AGL context otherwise they will continue\n               * to be displayed directly by Aqua.\n               */\n              /* aglSetDrawable is deprecated in OS X 10.5 */\n              aglSetDrawable(togl->Ctx, NULL);\n          }\n#endif\n#if defined(TOGL_NSOPENGL)\n          if (!togl->PbufferFlag) {\n              /* \n               * For Mac OS X Aqua, Tk subwindows are not implemented as\n               * separate Aqua windows.  They are just different regions of\n               * a single Aqua window.  To unmap them they are just not drawn.\n               * Have to disconnect the NSView otherwise they will continue\n               * to be displayed directly by Aqua.\n               */\n              [togl->Ctx clearDrawable];\n          }\n#endif\n          break;\n      case DestroyNotify:\n          if (togl->TkWin != NULL) {\n#ifdef TOGL_WGL\n              HWND    hwnd = Tk_GetHWND(Tk_WindowId(togl->TkWin));\n\n              /* Prevent Win32WinProc from calling Tcl_DeleteCommandFromToken\n               * a second time */\n              SetWindowLongPtr(hwnd, 0, (LONG_PTR) 0);\n#endif\n              if (togl->SetGrid > 0) {\n                  Tk_UnsetGrid(togl->TkWin);\n              }\n              (void) Tcl_DeleteCommandFromToken(togl->Interp, togl->widgetCmd);\n          }\n          break;\n      default:\n          /* nothing */\n          ;\n    }\n}\n\n\nvoid\nTogl_PostRedisplay(Togl *togl)\n{\n    if (!togl->UpdatePending) {\n        togl->UpdatePending = True;\n        Tk_DoWhenIdle(Togl_Render, (ClientData) togl);\n    }\n}\n\n\nBool\nTogl_UpdatePending(const Togl *togl)\n{\n    return togl->UpdatePending;\n}\n\n\nvoid\nTogl_SwapBuffers(const Togl *togl)\n{\n    if (togl->DoubleFlag) {\n#if defined(TOGL_WGL)\n        int     res = SwapBuffers(togl->tglGLHdc);\n\n        if (!res) {\n            ErrorExit(TEXT(\"SwapBuffers\"));\n        }\n#elif defined(TOGL_X11)\n        glXSwapBuffers(Tk_Display(togl->TkWin), Tk_WindowId(togl->TkWin));\n#elif defined(TOGL_AGL)\n        aglSwapBuffers(togl->Ctx);\n#elif defined(TOGL_NSOPENGL)\n        [togl->Ctx flushBuffer];\n#endif\n    } else {\n        glFlush();\n    }\n}\n\n\n\nconst char *\nTogl_Ident(const Togl *togl)\n{\n    return togl->Ident;\n}\n\n\nint\nTogl_Width(const Togl *togl)\n{\n    return togl->Width;\n}\n\n\nint\nTogl_Height(const Togl *togl)\n{\n    return togl->Height;\n}\n\nint\nTogl_PixelScale(const Togl *togl)\n{\n    return togl->PixelScale;\n}\n\n\nTcl_Interp *\nTogl_Interp(const Togl *togl)\n{\n    return togl->Interp;\n}\n\n\nTk_Window\nTogl_TkWin(const Togl *togl)\n{\n    return togl->TkWin;\n}\n\n\nconst char *\nTogl_CommandName(const Togl *togl)\n{\n    return Tcl_GetCommandName(togl->Interp, togl->widgetCmd);\n}\n\nint\nTogl_ContextTag(const Togl *togl)\n{\n    return togl->contextTag;\n}\n\nBool\nTogl_HasRGBA(const Togl *togl)\n{\n    return togl->RgbaFlag;\n}\n\nBool\nTogl_IsDoubleBuffered(const Togl *togl)\n{\n    return togl->DoubleFlag;\n}\n\nBool\nTogl_HasDepthBuffer(const Togl *togl)\n{\n    return togl->DepthFlag;\n}\n\nBool\nTogl_HasAccumulationBuffer(const Togl *togl)\n{\n    return togl->AccumFlag;\n}\n\nBool\nTogl_HasDestinationAlpha(const Togl *togl)\n{\n    return togl->AlphaFlag;\n}\n\nBool\nTogl_HasStencilBuffer(const Togl *togl)\n{\n    return togl->StencilFlag;\n}\n\nint\nTogl_StereoMode(const Togl *togl)\n{\n    return togl->Stereo;\n}\n\nBool\nTogl_HasMultisample(const Togl *togl)\n{\n    return togl->MultisampleFlag;\n}\n\n\n#if defined(TOGL_X11)\n/* \n * A replacement for XAllocColor.  This function should never\n * fail to allocate a color.  When XAllocColor fails, we return\n * the nearest matching color.  If we have to allocate many colors\n * this function isn't too efficient; the XQueryColors() could be\n * done just once.\n * Written by Michael Pichler, Brian Paul, Mark Kilgard\n * Input:  dpy - X display\n *         cmap - X colormap\n *         cmapSize - size of colormap\n * In/Out: color - the XColor struct\n * Output:  exact - 1=exact color match, 0=closest match\n */\nstatic void\nnoFaultXAllocColor(Display *dpy, Colormap cmap, int cmapSize,\n        XColor *color, int *exact)\n{\n    XColor *ctable, subColor;\n    int     i, bestmatch;\n    double  mindist;            /* 3*2^16^2 exceeds long int precision. */\n\n    /* First try just using XAllocColor. */\n    if (XAllocColor(dpy, cmap, color)) {\n        *exact = 1;\n        return;\n    }\n\n    /* Retrieve color table entries. */\n    /* XXX alloca candidate. */\n    ctable = (XColor *) ckalloc(cmapSize * sizeof (XColor));\n    for (i = 0; i < cmapSize; i++) {\n        ctable[i].pixel = i;\n    }\n    (void) XQueryColors(dpy, cmap, ctable, cmapSize);\n\n    /* Find best match. */\n    bestmatch = -1;\n    mindist = 0;\n    for (i = 0; i < cmapSize; i++) {\n        double  dr = (double) color->red - (double) ctable[i].red;\n        double  dg = (double) color->green - (double) ctable[i].green;\n        double  db = (double) color->blue - (double) ctable[i].blue;\n        double  dist = dr * dr + dg * dg + db * db;\n\n        if (bestmatch < 0 || dist < mindist) {\n            bestmatch = i;\n            mindist = dist;\n        }\n    }\n\n    /* Return result. */\n    subColor.red = ctable[bestmatch].red;\n    subColor.green = ctable[bestmatch].green;\n    subColor.blue = ctable[bestmatch].blue;\n    ckfree((char *) ctable);\n    /* Try to allocate the closest match color.  This should only fail if the\n     * cell is read/write.  Otherwise, we're incrementing the cell's reference\n     * count. */\n    if (!XAllocColor(dpy, cmap, &subColor)) {\n        /* do this to work around a problem reported by Frank Ortega */\n        subColor.pixel = (unsigned long) bestmatch;\n        subColor.red = ctable[bestmatch].red;\n        subColor.green = ctable[bestmatch].green;\n        subColor.blue = ctable[bestmatch].blue;\n        subColor.flags = DoRed | DoGreen | DoBlue;\n    }\n    *color = subColor;\n}\n\n#elif defined(TOGL_WGL)\n\nstatic UINT\nWin32AllocColor(const Togl *togl, float red, float green, float blue)\n{\n    /* Modified version of XAllocColor emulation of Tk. - returns index,\n     * instead of color itself - allocates logical palette entry even for\n     * non-palette devices */\n\n    TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);\n    UINT    index;\n    COLORREF newColor, closeColor;\n    PALETTEENTRY entry, closeEntry;\n    int     isNew, refCount;\n    Tcl_HashEntry *entryPtr;\n\n    entry.peRed = (unsigned char) (red * 255 + .5);\n    entry.peGreen = (unsigned char) (green * 255 + .5);\n    entry.peBlue = (unsigned char) (blue * 255 + .5);\n    entry.peFlags = 0;\n\n    /* \n     * Find the nearest existing palette entry.\n     */\n\n    newColor = RGB(entry.peRed, entry.peGreen, entry.peBlue);\n    index = GetNearestPaletteIndex(cmap->palette, newColor);\n    GetPaletteEntries(cmap->palette, index, 1, &closeEntry);\n    closeColor = RGB(closeEntry.peRed, closeEntry.peGreen, closeEntry.peBlue);\n\n    /* \n     * If this is not a duplicate and colormap is not full, allocate a new entry.\n     */\n\n    if (newColor != closeColor) {\n        if (cmap->size == (unsigned int) togl->CiColormapSize) {\n            entry = closeEntry;\n        } else {\n            cmap->size++;\n            ResizePalette(cmap->palette, cmap->size);\n            index = cmap->size - 1;\n            SetPaletteEntries(cmap->palette, index, 1, &entry);\n            SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);\n            RealizePalette(togl->tglGLHdc);\n        }\n    }\n    newColor = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);\n    entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,\n            (CONST char *) newColor, &isNew);\n    if (isNew) {\n        refCount = 1;\n    } else {\n        refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;\n    }\n    Tcl_SetHashValue(entryPtr, (ClientData) refCount);\n\n    /* for color index mode photos */\n    togl->RedMap[index] = (GLfloat) (entry.peRed / 255.0);\n    togl->GreenMap[index] = (GLfloat) (entry.peGreen / 255.0);\n    togl->BlueMap[index] = (GLfloat) (entry.peBlue / 255.0);\n    return index;\n}\n\nstatic void\nWin32FreeColor(const Togl *togl, unsigned long index)\n{\n    TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);\n    COLORREF cref;\n    UINT    count, refCount;\n    PALETTEENTRY entry, *entries;\n    Tcl_HashEntry *entryPtr;\n\n    if (index >= cmap->size) {\n        panic(\"Tried to free a color that isn't allocated.\");\n    }\n    GetPaletteEntries(cmap->palette, index, 1, &entry);\n\n    cref = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);\n    entryPtr = Tcl_FindHashEntry(&cmap->refCounts, (CONST char *) cref);\n    if (!entryPtr) {\n        panic(\"Tried to free a color that isn't allocated.\");\n    }\n    refCount = (int) Tcl_GetHashValue(entryPtr) - 1;\n    if (refCount == 0) {\n        count = cmap->size - index;\n        entries = (PALETTEENTRY *) ckalloc(sizeof (PALETTEENTRY) * count);\n        GetPaletteEntries(cmap->palette, index + 1, count, entries);\n        SetPaletteEntries(cmap->palette, index, count, entries);\n        SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);\n        RealizePalette(togl->tglGLHdc);\n        ckfree((char *) entries);\n        cmap->size--;\n        Tcl_DeleteHashEntry(entryPtr);\n    } else {\n        Tcl_SetHashValue(entryPtr, (ClientData) refCount);\n    }\n}\n\nstatic void\nWin32SetColor(const Togl *togl,\n        unsigned long index, float red, float green, float blue)\n{\n    TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);\n    PALETTEENTRY entry;\n\n    entry.peRed = (unsigned char) (red * 255 + .5);\n    entry.peGreen = (unsigned char) (green * 255 + .5);\n    entry.peBlue = (unsigned char) (blue * 255 + .5);\n    entry.peFlags = 0;\n    SetPaletteEntries(cmap->palette, index, 1, &entry);\n    SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);\n    RealizePalette(togl->tglGLHdc);\n\n    /* for color index mode photos */\n    togl->RedMap[index] = (GLfloat) (entry.peRed / 255.0);\n    togl->GreenMap[index] = (GLfloat) (entry.peGreen / 255.0);\n    togl->BlueMap[index] = (GLfloat) (entry.peBlue / 255.0);\n}\n#endif /* TOGL_X11 */\n\n\nunsigned long\nTogl_AllocColor(const Togl *togl, float red, float green, float blue)\n{\n    if (togl->RgbaFlag) {\n        (void) fprintf(stderr,\n                \"Error: Togl_AllocColor illegal in RGBA mode.\\n\");\n        return 0;\n    }\n    /* TODO: maybe not... */\n    if (togl->PrivateCmapFlag) {\n        (void) fprintf(stderr,\n                \"Error: Togl_AllocColor illegal with private colormap\\n\");\n        return 0;\n    }\n#if defined(TOGL_X11)\n    {\n        XColor  xcol;\n        int     exact;\n\n        xcol.red = (short) (red * 65535.0);\n        xcol.green = (short) (green * 65535.0);\n        xcol.blue = (short) (blue * 65535.0);\n\n        noFaultXAllocColor(Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin),\n                Tk_Visual(togl->TkWin)->map_entries, &xcol, &exact);\n        /* for color index mode photos */\n        togl->RedMap[xcol.pixel] = (float) xcol.red / 65535.0;\n        togl->GreenMap[xcol.pixel] = (float) xcol.green / 65535.0;\n        togl->BlueMap[xcol.pixel] = (float) xcol.blue / 65535.0;\n\n        return xcol.pixel;\n    }\n\n#elif defined(TOGL_WGL)\n    return Win32AllocColor(togl, red, green, blue);\n\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    /* still need to implement this on Mac... */\n    return 0;\n\n#endif\n}\n\n\n\nvoid\nTogl_FreeColor(const Togl *togl, unsigned long pixel)\n{\n    if (togl->RgbaFlag) {\n        (void) fprintf(stderr, \"Error: Togl_FreeColor illegal in RGBA mode.\\n\");\n        return;\n    }\n    /* TODO: maybe not... */\n    if (togl->PrivateCmapFlag) {\n        (void) fprintf(stderr,\n                \"Error: Togl_FreeColor illegal with private colormap\\n\");\n        return;\n    }\n#if defined(TOGL_X11)\n    (void) XFreeColors(Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin),\n            &pixel, 1, 0);\n#elif defined(TOGL_WGL)\n    Win32FreeColor(togl, pixel);\n#endif\n}\n\n\n\nvoid\nTogl_SetColor(const Togl *togl,\n        unsigned long index, float red, float green, float blue)\n{\n\n    if (togl->RgbaFlag) {\n        (void) fprintf(stderr, \"Error: Togl_SetColor illegal in RGBA mode.\\n\");\n        return;\n    }\n    if (!togl->PrivateCmapFlag) {\n        (void) fprintf(stderr,\n                \"Error: Togl_SetColor requires a private colormap\\n\");\n        return;\n    }\n#if defined(TOGL_X11)\n    {\n        XColor  xcol;\n\n        xcol.pixel = index;\n        xcol.red = (short) (red * 65535.0);\n        xcol.green = (short) (green * 65535.0);\n        xcol.blue = (short) (blue * 65535.0);\n        xcol.flags = DoRed | DoGreen | DoBlue;\n\n        (void) XStoreColor(Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin),\n                &xcol);\n\n        /* for color index mode photos */\n        togl->RedMap[xcol.pixel] = (float) xcol.red / 65535.0;\n        togl->GreenMap[xcol.pixel] = (float) xcol.green / 65535.0;\n        togl->BlueMap[xcol.pixel] = (float) xcol.blue / 65535.0;\n    }\n#elif defined(TOGL_WGL)\n    Win32SetColor(togl, index, red, green, blue);\n#endif\n}\n\n\n#if TOGL_USE_FONTS == 1\n#  include \"toglFont.c\"\n#else\n\nTcl_Obj *\nTogl_LoadBitmapFont(const Togl *togl, const char *fontname)\n{\n    return NULL;\n}\n\nint\nTogl_UnloadBitmapFont(const Togl *togl, Tcl_Obj *bitmapfont)\n{\n    return TCL_OK;\n}\n\nint\nTogl_WriteObj(const Togl *togl, const Tcl_Obj *toglfont, Tcl_Obj *obj)\n{\n    return -1;\n}\n\nint\nTogl_WriteChars(const Togl *togl, const Tcl_Obj *toglfont, const char *str,\n        int len)\n{\n    return -1;\n}\n#endif /* TOGL_USE_FONTS */\n\n\n\n/* \n * Overlay functions\n */\n\n\nvoid\nTogl_UseLayer(Togl *togl, int layer)\n{\n    if (layer == TOGL_NORMAL) {\n#if defined(TOGL_WGL)\n        int     res = wglMakeCurrent(togl->tglGLHdc, togl->Ctx);\n\n        if (!res) {\n            ErrorExit(TEXT(\"wglMakeCurrent\"));\n        }\n#elif defined(TOGL_X11)\n        (void) glXMakeCurrent(Tk_Display(togl->TkWin),\n                Tk_WindowId(togl->TkWin), togl->Ctx);\n#elif defined(TOGL_AGL)\n        (void) aglSetCurrentContext(togl->Ctx);\n#elif defined(TOGL_NSOPENGL)\n        [togl->Ctx makeCurrentContext];\n#endif\n    } else if (layer == TOGL_OVERLAY && togl->OverlayWindow) {\n#if defined(TOGL_WGL)\n        int     res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLOverlayHglrc);\n\n        if (!res) {\n            ErrorExit(TEXT(\"wglMakeCurrent overlay\"));\n        }\n#elif defined(TOGL_X11)\n        (void) glXMakeCurrent(Tk_Display(togl->TkWin),\n                togl->OverlayWindow, togl->OverlayCtx);\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n#endif\n    } else {\n        /* error */\n    }\n}\n\n\nvoid\nTogl_ShowOverlay(Togl *togl)\n{\n#if defined(TOGL_X11)           /* not yet implemented on Windows */\n    if (togl->OverlayWindow) {\n        (void) XMapWindow(Tk_Display(togl->TkWin), togl->OverlayWindow);\n        (void) XInstallColormap(Tk_Display(togl->TkWin), togl->OverlayCmap);\n        togl->OverlayIsMapped = True;\n    }\n#endif\n}\n\n\nvoid\nTogl_HideOverlay(Togl *togl)\n{\n    if (togl->OverlayWindow && togl->OverlayIsMapped) {\n        (void) XUnmapWindow(Tk_Display(togl->TkWin), togl->OverlayWindow);\n        togl->OverlayIsMapped = False;\n    }\n}\n\n\nvoid\nTogl_PostOverlayRedisplay(Togl *togl)\n{\n    if (!togl->OverlayUpdatePending\n            && togl->OverlayWindow && togl->OverlayDisplayProc) {\n        Tk_DoWhenIdle(Togl_RenderOverlay, (ClientData) togl);\n        togl->OverlayUpdatePending = True;\n    }\n}\n\n\nint\nTogl_ExistsOverlay(const Togl *togl)\n{\n    return togl->OverlayFlag;\n}\n\n\nint\nTogl_GetOverlayTransparentValue(const Togl *togl)\n{\n    return togl->OverlayTransparentPixel;\n}\n\n\nint\nTogl_IsMappedOverlay(const Togl *togl)\n{\n    return togl->OverlayFlag && togl->OverlayIsMapped;\n}\n\n\nunsigned long\nTogl_AllocColorOverlay(const Togl *togl, float red, float green, float blue)\n{\n#if defined(TOGL_X11)           /* not yet implemented on Windows */\n    if (togl->OverlayFlag && togl->OverlayCmap) {\n        XColor  xcol;\n\n        xcol.red = (short) (red * 65535.0);\n        xcol.green = (short) (green * 65535.0);\n        xcol.blue = (short) (blue * 65535.0);\n        if (!XAllocColor(Tk_Display(togl->TkWin), togl->OverlayCmap, &xcol))\n            return (unsigned long) -1;\n        return xcol.pixel;\n    }\n#endif /* TOGL_X11 */\n    return (unsigned long) -1;\n}\n\n\nvoid\nTogl_FreeColorOverlay(const Togl *togl, unsigned long pixel)\n{\n#if defined(TOGL_X11)           /* not yet implemented on Windows */\n    if (togl->OverlayFlag && togl->OverlayCmap) {\n        (void) XFreeColors(Tk_Display(togl->TkWin), togl->OverlayCmap, &pixel,\n                1, 0);\n    }\n#endif /* TOGL_X11 */\n}\n\n\n/* \n * User client data\n */\n\nClientData\nTogl_GetClientData(const Togl *togl)\n{\n    return togl->Client_Data;\n}\n\n\nvoid\nTogl_SetClientData(Togl *togl, ClientData clientData)\n{\n    togl->Client_Data = clientData;\n}\n\nint\nTogl_CopyContext(const Togl *from, const Togl *to, unsigned mask)\n{\n#ifdef TOGL_X11\n    int     error_code;\n    int     same = (glXGetCurrentContext() == to->Ctx);\n\n    if (same)\n        (void) glXMakeCurrent(to->display, None, NULL);\n    togl_SetupXErrorHandler();\n    glXCopyContext(from->display, from->Ctx, to->Ctx, mask);\n    if (error_code = togl_CheckForXError(from)) {\n        char    buf[256];\n\n        XGetErrorText(from->display, error_code, buf, sizeof buf);\n        Tcl_AppendResult(from->Interp, \"unable to copy context: \", buf, NULL);\n        return TCL_ERROR;\n    }\n#elif defined(TOGL_WGL)\n    int     same = (wglGetCurrentContext() == to->Ctx);\n\n    if (same)\n        (void) wglMakeCurrent(to->tglGLHdc, NULL);\n    if (!wglCopyContext(from->Ctx, to->Ctx, mask)) {\n        char buf[256];\n\n        snprintf(buf, sizeof buf, \"unable to copy context: %d\", GetLastError());\n        Tcl_AppendElement(from->Interp, buf);\n        return TCL_ERROR;\n    }\n#elif defined(TOGL_AGL)\n    int     same = (aglGetCurrentContext() == to->Ctx);\n\n    if (same)\n        (void) aglSetCurrentContext(NULL);\n    if (!aglCopyContext(from->Ctx, to->Ctx, mask)) {\n        Tcl_AppendResult(from->Interp, \"unable to copy context: \",\n                aglErrorString(aglGetError()), NULL);\n        return TCL_ERROR;\n    }\n#elif defined(TOGL_NSOPENGL)\n    int     same = (from->Ctx == to->Ctx);\n\n    if (same) {\n      [NSOpenGLContext clearCurrentContext];\n    }\n    [to->Ctx copyAttributesFromContext:from->Ctx withMask:mask];\n#endif\n    if (same)\n        Togl_MakeCurrent(to);\n    return TCL_OK;\n}\n\n\n#ifdef MESA_COLOR_HACK\n/* \n * Let's know how many free colors do we have\n */\n#  define RLEVELS     5\n#  define GLEVELS     9\n#  define BLEVELS     5\n\n/* to free dithered_rgb_colormap pixels allocated by Mesa */\nstatic unsigned long *ToglMesaUsedPixelCells = NULL;\nstatic int ToglMesaUsedFreeCells = 0;\n\nstatic int\nget_free_color_cells(Display *display, int screen, Colormap colormap)\n{\n    if (!ToglMesaUsedPixelCells) {\n        XColor  xcol;\n        int     i;\n        int     colorsfailed, ncolors = XDisplayCells(display, screen);\n\n        long    r, g, b;\n\n        ToglMesaUsedPixelCells =\n                (unsigned long *) ckalloc(ncolors * sizeof (unsigned long));\n\n        /* Allocate X colors and initialize color_table[], red_table[], etc */\n        /* de Mesa 2.1: xmesa1.c setup_dithered_(...) */\n        i = colorsfailed = 0;\n        for (r = 0; r < RLEVELS; r++)\n            for (g = 0; g < GLEVELS; g++)\n                for (b = 0; b < BLEVELS; b++) {\n                    int     exact;\n\n                    xcol.red = (r * 65535) / (RLEVELS - 1);\n                    xcol.green = (g * 65535) / (GLEVELS - 1);\n                    xcol.blue = (b * 65535) / (BLEVELS - 1);\n                    noFaultXAllocColor(display, colormap, ncolors,\n                            &xcol, &exact);\n                    ToglMesaUsedPixelCells[i++] = xcol.pixel;\n                    if (!exact) {\n                        colorsfailed++;\n                    }\n                }\n        ToglMesaUsedFreeCells = i;\n\n        XFreeColors(display, colormap, ToglMesaUsedPixelCells,\n                ToglMesaUsedFreeCells, 0x00000000);\n    }\n    return ToglMesaUsedFreeCells;\n}\n\n\nstatic void\nfree_default_color_cells(Display *display, Colormap colormap)\n{\n    if (ToglMesaUsedPixelCells) {\n        XFreeColors(display, colormap, ToglMesaUsedPixelCells,\n                ToglMesaUsedFreeCells, 0x00000000);\n        ckfree((char *) ToglMesaUsedPixelCells);\n        ToglMesaUsedPixelCells = NULL;\n        ToglMesaUsedFreeCells = 0;\n    }\n}\n#endif\n\n/* \n * Original stereo code contributed by Ben Evans (Ben.Evans@anusf.anu.edu.au)\n * and was based on SGI's /usr/share/src/OpenGL/teach/stereo/glwstereo.c,\n * which is identical to the 1997/12/1 glwstereo.c code in the CrystalEyes\n * Software Development Kit.\n */\n\nint\nTogl_NumEyes(const Togl *togl)\n{\n    if (togl->Stereo > TOGL_STEREO_ONE_EYE_MAX)\n        return 2;\n    return 1;\n}\n\n/* call instead of glDrawBuffer */\nvoid\nTogl_DrawBuffer(Togl *togl, GLenum mode)\n{\n    if (togl->Stereo <= TOGL_STEREO_ONE_EYE_MAX) {\n        /* Only drawing a single eye */\n        if (togl->currentStereoBuffer != STEREO_BUFFER_NONE) {\n            Togl_SetViewPort(togl);\n            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);\n            togl->currentStereoBuffer = STEREO_BUFFER_NONE;\n        }\n        switch (mode) {\n          case GL_FRONT:\n          case GL_BACK:\n          case GL_FRONT_AND_BACK:\n              break;\n          case GL_LEFT:\n          case GL_FRONT_LEFT:\n          case GL_RIGHT:\n          case GL_FRONT_RIGHT:\n              mode = GL_FRONT;\n              break;\n          case GL_BACK_LEFT:\n          case GL_BACK_RIGHT:\n              mode = GL_BACK;\n              break;\n          default:\n              break;\n        }\n        glDrawBuffer(mode);\n        return;\n    }\n    /* called once for each eye */\n    switch (mode) {\n      case GL_FRONT:\n      case GL_BACK:\n      case GL_FRONT_AND_BACK:\n          /* \n           ** Simultaneous drawing to both left and right buffers isn't\n           ** really possible if we don't have a stereo capable visual.\n           ** For now just fall through and use the left buffer.\n           */\n      case GL_LEFT:\n      case GL_FRONT_LEFT:\n      case GL_BACK_LEFT:\n          togl->currentStereoBuffer = STEREO_BUFFER_LEFT;\n          break;\n      case GL_RIGHT:\n      case GL_FRONT_RIGHT:\n      case GL_BACK_RIGHT:\n          togl->currentStereoBuffer = STEREO_BUFFER_RIGHT;\n          break;\n      default:\n          break;\n    }\n    if (togl->Stereo != TOGL_STEREO_NATIVE) {\n        switch (mode) {\n          default:\n              mode = GL_FRONT;\n              break;\n          case GL_BACK:\n          case GL_BACK_LEFT:\n          case GL_BACK_RIGHT:\n              mode = GL_BACK;\n              break;\n        }\n    }\n    int w = togl->Width*togl->PixelScale, h = togl->Height*togl->PixelScale;\n    switch (togl->Stereo) {\n      default:\n          break;\n#ifdef __sgi\n      case TOGL_STEREO_SGIOLDSTYLE:\n          glXWaitGL();          /* sync with GL command stream before calling X \n                                 */\n          XSGISetStereoBuffer(togl->display, Tk_WindowId(togl->TkWin),\n                  togl->currentStereoBuffer);\n          glXWaitX();           /* sync with X command stream before calling GL \n                                 */\n          break;\n#endif\n      case TOGL_STEREO_ANAGLYPH:\n          if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n              glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);\n          else\n              glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);\n          glViewport(0, 0, w, h);\n          break;\n      case TOGL_STEREO_CROSS_EYE:\n          if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n              glViewport(w / 2 + 1, 0, w / 2, h);\n          else\n              glViewport(0, 0, w / 2, h);\n          break;\n      case TOGL_STEREO_WALL_EYE:\n          if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n              glViewport(0, 0, w / 2, h);\n          else\n              glViewport(w / 2 + 1, 0, w / 2, h);\n          break;\n      case TOGL_STEREO_DTI:\n          if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n              glViewport(0, 0, w / 2, h);\n          else\n              glViewport(w / 2 + 1, 0, w / 2, h);\n          break;\n      case TOGL_STEREO_ROW_INTERLEAVED:\n          glViewport(0, 0, w, h);\n          break;\n    }\n    glDrawBuffer(mode);\n}\n\n/* call instead of glClear */\nvoid\nTogl_Clear(const Togl *togl, GLbitfield mask)\n{\n    GLint   stencil_write_mask = 0;\n    GLint   stencil_clear_value = 0;\n\n    switch (togl->Stereo) {\n      default:\n          break;\n      case TOGL_STEREO_CROSS_EYE:\n      case TOGL_STEREO_WALL_EYE:\n      case TOGL_STEREO_DTI:\n          if (togl->currentStereoBuffer != STEREO_BUFFER_LEFT) {\n              /* Since glViewport does not affect what is cleared (unlike\n               * glScissor), only clear in left eye */\n              return;\n          }\n          break;\n      case TOGL_STEREO_ROW_INTERLEAVED:\n          if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT) {\n              if ((mask & GL_STENCIL_BUFFER_BIT) == 0) {\n                  mask |= GL_STENCIL_BUFFER_BIT;\n                  glStencilMask(~0u);\n                  glClearStencil(0);\n              } else {\n                  glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_write_mask);\n                  glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencil_clear_value);\n                  glStencilMask(stencil_write_mask | togl->riStencilBit);\n                  glClearStencil(stencil_clear_value & ~togl->riStencilBit);\n              }\n          } else {\n              mask &= ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n          }\n          break;\n    }\n#if 0\n    /* only needed if we wish to support multi-eye clears */\n    if (togl->Stereo > TOGL_STEREO_ONE_EYE_MAX) {\n        GLenum  drawBuffer = togl->currentDrawBuffer;\n\n        switch (drawBuffer) {\n          case GL_FRONT:\n              Togl_DrawBuffer(togl, GL_FRONT_RIGHT);\n              glClear(mask);\n              Togl_DrawBuffer(togl, drawBuffer);\n              break;\n          case GL_BACK:\n              Togl_DrawBuffer(togl, GL_BACK_RIGHT);\n              glClear(mask);\n              Togl_DrawBuffer(togl, drawBuffer);\n              break;\n          case GL_FRONT_AND_BACK:\n              Togl_DrawBuffer(togl, GL_RIGHT);\n              glClear(mask);\n              Togl_DrawBuffer(togl, drawBuffer);\n              break;\n          case GL_LEFT:\n          case GL_FRONT_LEFT:\n          case GL_BACK_LEFT:\n          case GL_RIGHT:\n          case GL_FRONT_RIGHT:\n          case GL_BACK_RIGHT:\n          default:\n              break;\n        }\n    }\n#endif\n    if (mask != 0)\n        glClear(mask);\n    if (togl->Stereo == TOGL_STEREO_ROW_INTERLEAVED) {\n        int     x, y;\n\n        if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT) {\n            int     i;\n\n            /* initialize stencil buffer mask */\n            glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT\n                    | GL_LINE_BIT | GL_VIEWPORT_BIT);\n            // 2d projection\n            Togl_SetViewPort(togl);\n            glMatrixMode(GL_PROJECTION);\n            glPushMatrix();\n            glLoadIdentity();\n            glOrtho(0, togl->Width, 0, togl->Height, -1, 1);\n            glMatrixMode(GL_MODELVIEW);\n            glPushMatrix();\n            glLoadIdentity();\n            glTranslatef(0.375f, 0.375f, 0);\n            glDisable(GL_ALPHA_TEST);\n            glDisable(GL_COLOR_LOGIC_OP);\n            glDisable(GL_DEPTH_TEST);\n            glDisable(GL_DITHER);\n            glDisable(GL_INDEX_LOGIC_OP);\n            glDisable(GL_LIGHTING);\n            glDisable(GL_LINE_SMOOTH);\n            glDisable(GL_MULTISAMPLE);\n            glLineWidth(1);\n            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);\n            glStencilFunc(GL_ALWAYS, togl->riStencilBit, togl->riStencilBit);\n            glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);\n            glBegin(GL_LINES);\n            for (i = 0; i < togl->Height; i += 2) {\n                glVertex2i(0, i);\n                glVertex2i(togl->Width, i);\n            }\n            glEnd();\n            glMatrixMode(GL_PROJECTION);\n            glPopMatrix();\n            glMatrixMode(GL_MODELVIEW);\n            glPopMatrix();\n            glPopAttrib();\n\n            if (stencil_write_mask) {\n                glStencilMask(stencil_write_mask & ~togl->riStencilBit);\n            } else {\n                glStencilMask(~togl->riStencilBit);\n            }\n\n            Tk_GetRootCoords(togl->TkWin, &x, &y);\n            if ((y + togl->Height) % 2) {\n                glStencilFunc(GL_NOTEQUAL, togl->riStencilBit,\n                        togl->riStencilBit);\n            } else {\n                glStencilFunc(GL_EQUAL, togl->riStencilBit, togl->riStencilBit);\n            }\n        } else {\n            Tk_GetRootCoords(togl->TkWin, &x, &y);\n            if ((y + togl->Height) % 2) {\n                glStencilFunc(GL_EQUAL, togl->riStencilBit, togl->riStencilBit);\n            } else {\n                glStencilFunc(GL_NOTEQUAL, togl->riStencilBit,\n                        togl->riStencilBit);\n            }\n        }\n    }\n}\n\n/*\n * Togl_Frustum and Togl_Ortho:\n *\n *     eyeOffset is the distance from the center line\n *     and is negative for the left eye and positive for right eye.\n *     eyeDist and eyeOffset need to be in the same units as your model space.\n *     In physical space, eyeDist might be 30 inches from the screen\n *     and eyeDist would be +/- 1.25 inch (for a total interocular distance\n *     of 2.5 inches).\n */\n\nvoid\nTogl_Frustum(const Togl *togl, GLdouble left, GLdouble right,\n        GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)\n{\n    GLdouble eyeOffset = 0, eyeShift = 0;\n\n    if (togl->Stereo == TOGL_STEREO_LEFT_EYE\n            || togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n        eyeOffset = -togl->EyeSeparation / 2;   /* for left eye */\n    else if (togl->Stereo == TOGL_STEREO_RIGHT_EYE\n            || togl->currentStereoBuffer == STEREO_BUFFER_RIGHT)\n        eyeOffset = togl->EyeSeparation / 2;    /* for right eye */\n    eyeShift = (togl->Convergence - zNear) * (eyeOffset / togl->Convergence);\n\n    /* compensate for altered viewports */\n    switch (togl->Stereo) {\n      default:\n          break;\n      case TOGL_STEREO_SGIOLDSTYLE:\n      case TOGL_STEREO_DTI:\n          /* squished image is expanded, nothing needed */\n          break;\n      case TOGL_STEREO_CROSS_EYE:\n      case TOGL_STEREO_WALL_EYE:{\n          GLdouble delta = (top - bottom) / 2;\n\n          top += delta;\n          bottom -= delta;\n          break;\n      }\n    }\n\n    glFrustum(left + eyeShift, right + eyeShift, bottom, top, zNear, zFar);\n    glTranslated(-eyeShift, 0, 0);\n}\n\nvoid\nTogl_Ortho(const Togl *togl, GLdouble left, GLdouble right,\n        GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)\n{\n    /* TODO: debug this */\n    GLdouble eyeOffset = 0, eyeShift = 0;\n\n    if (togl->currentStereoBuffer == STEREO_BUFFER_LEFT)\n        eyeOffset = -togl->EyeSeparation / 2;   /* for left eye */\n    else if (togl->currentStereoBuffer == STEREO_BUFFER_RIGHT)\n        eyeOffset = togl->EyeSeparation / 2;    /* for right eye */\n    eyeShift = (togl->Convergence - zNear) * (eyeOffset / togl->Convergence);\n\n    /* compensate for altered viewports */\n    switch (togl->Stereo) {\n      default:\n          break;\n      case TOGL_STEREO_SGIOLDSTYLE:\n      case TOGL_STEREO_DTI:\n          /* squished image is expanded, nothing needed */\n          break;\n      case TOGL_STEREO_CROSS_EYE:\n      case TOGL_STEREO_WALL_EYE:{\n          GLdouble delta = (top - bottom) / 2;\n\n          top += delta;\n          bottom -= delta;\n          break;\n      }\n    }\n\n    glOrtho(left + eyeShift, right + eyeShift, bottom, top, zNear, zFar);\n    glTranslated(-eyeShift, 0, 0);\n}\n\nint\nTogl_GetToglFromObj(Tcl_Interp *interp, Tcl_Obj *obj, Togl **toglPtr)\n{\n    Tcl_Command toglCmd;\n    Tcl_CmdInfo info;\n\n    toglCmd = Tcl_GetCommandFromObj(interp, obj);\n    if (Tcl_GetCommandInfoFromToken(toglCmd, &info) == 0\n            || info.objProc != Togl_ObjWidget) {\n        Tcl_AppendResult(interp, \"expected togl command argument\", NULL);\n        return TCL_ERROR;\n    }\n    *toglPtr = (Togl *) info.objClientData;\n    return TCL_OK;\n}\n\nint\nTogl_GetToglFromName(Tcl_Interp *interp, const char *cmdName, Togl **toglPtr)\n{\n    Tcl_CmdInfo info;\n\n    if (Tcl_GetCommandInfo(interp, cmdName, &info) == 0\n            || info.objProc != Togl_ObjWidget) {\n        Tcl_AppendResult(interp, \"expected togl command argument\", NULL);\n        return TCL_ERROR;\n    }\n    *toglPtr = (Togl *) info.objClientData;\n    return TCL_OK;\n}\n\f\nstatic int ObjectIsEmpty(Tcl_Obj *objPtr);\n\n/* \n *----------------------------------------------------------------------\n *\n * GetStereo -\n *\n *      Converts an internal int into a Tcl string obj.\n *\n * Results:\n *      Tcl_Obj containing the string representation of the stereo value.\n *\n * Side effects:\n *      Creates a new Tcl_Obj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetStereo(ClientData clientData, Tk_Window tkwin, char *recordPtr,\n        int internalOffset)\n    /* recordPtr is a pointer to widget record. */\n    /* internalOffset is the offset within *recordPtr containing the stereo\n     * value. */\n{\n    int     stereo = *(int *) (recordPtr + internalOffset);\n    const char *name = \"unknown\";\n\n    switch (stereo) {\n      case TOGL_STEREO_NONE:\n          name = \"\";\n          break;\n      case TOGL_STEREO_LEFT_EYE:\n          name = \"left eye\";\n          break;\n      case TOGL_STEREO_RIGHT_EYE:\n          name = \"right eye\";\n          break;\n      case TOGL_STEREO_NATIVE:\n          name = \"native\";\n          break;\n      case TOGL_STEREO_SGIOLDSTYLE:\n          name = \"sgioldstyle\";\n          break;\n      case TOGL_STEREO_ANAGLYPH:\n          name = \"anaglyph\";\n          break;\n      case TOGL_STEREO_CROSS_EYE:\n          name = \"cross-eye\";\n          break;\n      case TOGL_STEREO_WALL_EYE:\n          name = \"wall-eye\";\n          break;\n      case TOGL_STEREO_DTI:\n          name = \"dti\";\n          break;\n      case TOGL_STEREO_ROW_INTERLEAVED:\n          name = \"row interleaved\";\n          break;\n    }\n    return Tcl_NewStringObj(name, -1);\n}\n\f\n/* \n *----------------------------------------------------------------------\n *\n * SetStereo --\n *\n *      Converts a Tcl_Obj representing a widgets stereo into an\n *      integer value.\n *\n * Results:\n *      Standard Tcl result.\n *\n * Side effects:\n *      May store the integer value into the internal representation\n *      pointer.  May change the pointer to the Tcl_Obj to NULL to indicate\n *      that the specified string was empty and that is acceptable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetStereo(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin,\n        Tcl_Obj **value, char *recordPtr, int internalOffset,\n        char *oldInternalPtr, int flags)\n    /* interp is the current interp; may be used for errors. */\n    /* tkwin is the Window for which option is being set. */\n    /* value is a pointer to the pointer to the value object. We use a pointer\n     * to the pointer because we may need to return a value (NULL). */\n    /* recordPtr is a pointer to storage for the widget record. */\n    /* internalOffset is the offset within *recordPtr at which the internal\n     * value is to be stored. */\n    /* oldInternalPtr is a pointer to storage for the old value. */\n    /* flags are the flags for the option, set Tk_SetOptions. */\n{\n    int     stereo = 0;\n    char   *string, *internalPtr;\n\n    internalPtr = (internalOffset > 0) ? recordPtr + internalOffset : NULL;\n\n    if ((flags & TK_OPTION_NULL_OK) && ObjectIsEmpty(*value)) {\n        *value = NULL;\n    } else {\n        /* \n         * Convert the stereo specifier into an integer value.\n         */\n\n        if (Tcl_GetBooleanFromObj(NULL, *value, &stereo) == TCL_OK) {\n            stereo = stereo ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE;\n        } else {\n            string = Tcl_GetString(*value);\n\n            if (strcmp(string, \"\") == 0 || strcasecmp(string, \"none\") == 0) {\n                stereo = TOGL_STEREO_NONE;\n            } else if (strcasecmp(string, \"native\") == 0) {\n                stereo = TOGL_STEREO_NATIVE;\n                /* check if available when creating visual */\n            } else if (strcasecmp(string, \"left eye\") == 0) {\n                stereo = TOGL_STEREO_LEFT_EYE;\n            } else if (strcasecmp(string, \"right eye\") == 0) {\n                stereo = TOGL_STEREO_RIGHT_EYE;\n            } else if (strcasecmp(string, \"sgioldstyle\") == 0) {\n                stereo = TOGL_STEREO_SGIOLDSTYLE;\n            } else if (strcasecmp(string, \"anaglyph\") == 0) {\n                stereo = TOGL_STEREO_ANAGLYPH;\n            } else if (strcasecmp(string, \"cross-eye\") == 0) {\n                stereo = TOGL_STEREO_CROSS_EYE;\n            } else if (strcasecmp(string, \"wall-eye\") == 0) {\n                stereo = TOGL_STEREO_WALL_EYE;\n            } else if (strcasecmp(string, \"dti\") == 0) {\n                stereo = TOGL_STEREO_DTI;\n            } else if (strcasecmp(string, \"row interleaved\") == 0) {\n                stereo = TOGL_STEREO_ROW_INTERLEAVED;\n            } else {\n                Tcl_ResetResult(interp);\n                Tcl_AppendResult(interp, \"bad stereo value \\\"\",\n                        Tcl_GetString(*value), \"\\\"\", NULL);\n                return TCL_ERROR;\n            }\n        }\n    }\n\n    if (internalPtr != NULL) {\n        *((int *) oldInternalPtr) = *((int *) internalPtr);\n        *((int *) internalPtr) = stereo;\n    }\n    return TCL_OK;\n}\n\f\n/* \n *----------------------------------------------------------------------\n * RestoreStereo --\n *\n *      Restore a stereo option value from a saved value.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      Restores the old value.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRestoreStereo(ClientData clientData, Tk_Window tkwin, char *internalPtr,\n        char *oldInternalPtr)\n{\n    *(int *) internalPtr = *(int *) oldInternalPtr;\n}\n\n/* \n *----------------------------------------------------------------------\n *\n * GetWideInt -\n *\n *      Converts an internal wide integer into a Tcl WideInt obj.\n *\n * Results:\n *      Tcl_Obj containing the wide int value.\n *\n * Side effects:\n *      Creates a new Tcl_Obj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetWideInt(ClientData clientData, Tk_Window tkwin, char *recordPtr,\n        int internalOffset)\n    /* recordPtr is a pointer to widget record. */\n    /* internalOffset is the offset within *recordPtr containing the wide int\n     * value. */\n{\n    Tcl_WideInt wi = *(Tcl_WideInt *) (recordPtr + internalOffset);\n\n    return Tcl_NewWideIntObj(wi);\n}\n\f\n/* \n *----------------------------------------------------------------------\n *\n * SetWideInt --\n *\n *      Converts a Tcl_Obj representing a Tcl_WideInt.\n *\n * Results:\n *      Standard Tcl result.\n *\n * Side effects:\n *      May store the wide int value into the internal representation\n *      pointer.  May change the pointer to the Tcl_Obj to NULL to indicate\n *      that the specified string was empty and that is acceptable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetWideInt(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin,\n        Tcl_Obj **value, char *recordPtr, int internalOffset,\n        char *oldInternalPtr, int flags)\n    /* interp is the current interp; may be used for errors. */\n    /* tkwin is the Window for which option is being set. */\n    /* value is a pointer to the pointer to the value object. We use a pointer\n     * to the pointer because we may need to return a value (NULL). */\n    /* recordPtr is a pointer to storage for the widget record. */\n    /* internalOffset is the offset within *recordPtr at which the internal\n     * value is to be stored. */\n    /* oldInternalPtr is a pointer to storage for the old value. */\n    /* flags are the flags for the option, set Tk_SetOptions. */\n{\n    char   *internalPtr;\n    Tcl_WideInt w;\n\n    internalPtr = (internalOffset > 0) ? recordPtr + internalOffset : NULL;\n\n    if ((flags & TK_OPTION_NULL_OK) && ObjectIsEmpty(*value)) {\n        *value = NULL;\n        w = 0;\n    } else {\n        if (Tcl_GetWideIntFromObj(interp, *value, &w) != TCL_OK) {\n            return TCL_ERROR;\n        }\n    }\n\n    if (internalPtr != NULL) {\n        *((Tcl_WideInt *) oldInternalPtr) = *((Tcl_WideInt *) internalPtr);\n        *((Tcl_WideInt *) internalPtr) = w;\n    }\n    return TCL_OK;\n}\n\f\n/* \n *----------------------------------------------------------------------\n * RestoreWideInt --\n *\n *      Restore a wide int option value from a saved value.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      Restores the old value.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRestoreWideInt(ClientData clientData, Tk_Window tkwin, char *internalPtr,\n        char *oldInternalPtr)\n{\n    *(Tcl_WideInt *) internalPtr = *(Tcl_WideInt *) oldInternalPtr;\n}\n\f\n/* \n *----------------------------------------------------------------------\n *\n * ObjectIsEmpty --\n *\n *      This procedure tests whether the string value of an object is\n *      empty.\n *\n * Results:\n *      The return value is 1 if the string value of objPtr has length\n *      zero, and 0 otherwise.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nObjectIsEmpty(Tcl_Obj *objPtr)\n/* objPtr = Object to test.  May be NULL. */\n{\n    int     length;\n\n    if (objPtr == NULL) {\n        return 1;\n    }\n    if (objPtr->bytes != NULL) {\n        return (objPtr->length == 0);\n    }\n    Tcl_GetStringFromObj(objPtr, &length);\n    return (length == 0);\n}\n"
  },
  {
    "path": "ng/Togl2.1/togl.decls",
    "content": "library togl\ninterface togl\n\n# Declare each of the functions in the public Togl interface.  Note that\n# the an index should never be reused for a different function in order\n# to preserve backwards compatibility.\n\n# package initialization\ndeclare 0 generic {\n\tint Togl_Init(Tcl_Interp *interp)\n}\n\n# Miscellaneous\ndeclare 1 generic {\n\tvoid Togl_MakeCurrent(const Togl *togl)\n}\ndeclare 2 generic {\n\tvoid Togl_PostRedisplay(Togl *togl)\n}\ndeclare 3 generic {\n\tvoid Togl_SwapBuffers(const Togl *togl)\n}\ndeclare 33 generic {\n\tBool Togl_SwapInterval(const Togl *togl, int interval)\n}\ndeclare 48 generic {\n\tint Togl_CopyContext(const Togl *from, const Togl *to, unsigned int mask)\n}\n\n# Query functions\ndeclare 4 generic {\n\tconst char *Togl_Ident(const Togl *togl)\n}\ndeclare 5 generic {\n\tint Togl_Width(const Togl *togl)\n}\ndeclare 6 generic {\n\tint Togl_Height(const Togl *togl)\n}\ndeclare 7 generic {\n\tTcl_Interp *Togl_Interp(const Togl *togl)\n}\ndeclare 8 generic {\n\tTk_Window Togl_TkWin(const Togl *togl)\n}\ndeclare 9 generic {\n\tconst char *Togl_CommandName(const Togl *togl)\n}\ndeclare 36 generic {\n\tint Togl_ContextTag(const Togl *togl)\n}\ndeclare 37 generic {\n\tBool Togl_UpdatePending(const Togl *togl)\n}\n\ndeclare 40 generic {\n\tBool Togl_HasRGBA(const Togl *togl)\n}\n\ndeclare 41 generic {\n\tBool Togl_IsDoubleBuffered(const Togl *togl)\n}\n\ndeclare 42 generic {\n\tBool Togl_HasDepthBuffer(const Togl *togl)\n}\n\ndeclare 43 generic {\n\tBool Togl_HasAccumulationBuffer(const Togl *togl)\n}\n\ndeclare 44 generic {\n\tBool Togl_HasDestinationAlpha(const Togl *togl)\n}\n\ndeclare 45 generic {\n\tBool Togl_HasStencilBuffer(const Togl *togl)\n}\n\ndeclare 46 generic {\n\tint Togl_StereoMode(const Togl *togl)\n}\n\ndeclare 47 generic {\n\tBool Togl_HasMultisample(const Togl *togl)\n}\n\ndeclare 49 generic {\n\tint Togl_PixelScale(const Togl *togl)\n}\n\n\n# Color Index mode\ndeclare 10 generic {\n\tunsigned long Togl_AllocColor(const Togl *togl, float red,\n\t\tfloat green, float blue)\n}\ndeclare 11 generic {\n\tvoid Togl_FreeColor(const Togl *togl, unsigned long index)\n}\ndeclare 12 generic {\n\tvoid Togl_SetColor(const Togl *togl, unsigned long index,\n\t\tfloat red, float green, float blue)\n}\n\n# Bitmap fonts\ndeclare 13 generic {\n\tTcl_Obj *Togl_LoadBitmapFont(const Togl *togl, const char *fontname)\n}\ndeclare 14 generic {\n\tint Togl_UnloadBitmapFont(const Togl *togl, Tcl_Obj *toglfont)\n}\n\ndeclare 38 generic {\n\tint Togl_WriteObj(const Togl *togl, const Tcl_Obj *toglfont, Tcl_Obj *obj)\n}\n\ndeclare 39 generic {\n\tint Togl_WriteChars(const Togl *togl, const Tcl_Obj *toglfont, const char *str, int len)\n}\n\n# Overlay functions\ndeclare 15 generic {\n\tvoid Togl_UseLayer(Togl *togl, int layer)\n}\ndeclare 16 generic {\n\tvoid Togl_ShowOverlay(Togl *togl)\n}\ndeclare 17 generic {\n\tvoid Togl_HideOverlay(Togl *togl)\n}\ndeclare 18 generic {\n\tvoid Togl_PostOverlayRedisplay(Togl *togl)\n}\ndeclare 19 generic {\n\tint Togl_ExistsOverlay(const Togl *togl)\n}\ndeclare 20 generic {\n\tint Togl_GetOverlayTransparentValue(const Togl *togl)\n}\ndeclare 21 generic {\n\tint Togl_IsMappedOverlay(const Togl *togl)\n}\ndeclare 22 generic {\n\tunsigned long Togl_AllocColorOverlay(const Togl *togl,\n\t\tfloat red, float green, float blue)\n}\ndeclare 23 generic {\n\tvoid Togl_FreeColorOverlay(const Togl *togl, unsigned long index)\n}\n\n# User client data\ndeclare 24 generic {\n\tClientData Togl_GetClientData(const Togl *togl)\n}\ndeclare 25 generic {\n\tvoid Togl_SetClientData(Togl *togl, ClientData clientData)\n}\n\n# Stereo support\ndeclare 26 generic {\n\tvoid Togl_DrawBuffer(Togl *togl, GLenum mode)\n}\ndeclare 27 generic {\n\tvoid Togl_Clear(const Togl *togl, GLbitfield mask)\n}\ndeclare 28 generic {\n\tvoid Togl_Frustum(const Togl *togl, GLdouble left, GLdouble right,\n\t\tGLdouble bottom, GLdouble top, GLdouble near, GLdouble far)\n}\ndeclare 34 generic {\n\tvoid Togl_Ortho(const Togl *togl, GLdouble left, GLdouble right,\n\t\tGLdouble bottom, GLdouble top, GLdouble near, GLdouble far)\n}\ndeclare 35 generic {\n\tint Togl_NumEyes(const Togl *togl)\n}\n\n# save current contents of OpenGL window into photo image\ndeclare 30 generic {\n\tint Togl_TakePhoto(Togl *togl, Tk_PhotoHandle photo)\n}\n\n# platform-independent lookup of OpenGL functions\ndeclare 31 generic {\n\tTogl_FuncPtr Togl_GetProcAddr(const char *funcname)\n}\n\n# Return the Togl data associated with pathName\ndeclare 29 generic {\n\tint Togl_GetToglFromObj(Tcl_Interp *interp, Tcl_Obj *obj, Togl **toglPtr)\n}\ndeclare 32 generic {\n\tint Togl_GetToglFromName(Tcl_Interp *interp, const char *cmdName, Togl **toglPtr)\n}\n"
  },
  {
    "path": "ng/Togl2.1/togl.h",
    "content": "/* $Id: togl.h,v 1.39 2009/03/31 23:21:13 gregcouch Exp $ */\n\n/* vi:set sw=4: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n\n#ifndef TOGL_H\n#  define TOGL_H\n\n//#  include \"togl_ws.h\"\n\n#  ifdef TOGL_WGL\n#    define WIN32_LEAN_AND_MEAN\n#    include <windows.h>\n#    undef WIN32_LEAN_AND_MEAN\n#    if defined(_MSC_VER)\n#      \tdefine DllEntryPoint DllMain\n#    endif\n#  endif\n\n#  if defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n#    ifndef MAC_OSX_TCL\n#      define MAC_OSX_TCL 1\n#    endif\n#    ifndef MAC_OSX_TK\n#      define MAC_OSX_TK 1\n#    endif\n#  endif\n\n#  ifdef USE_TOGL_STUBS\n#    ifndef USE_TCL_STUBS\n#      define USE_TCL_STUBS\n#    endif\n#    ifndef USE_TK_STUBS\n#      define USE_TK_STUBS\n#    endif\n#  endif\n\n#  include <tcl.h>\n#  include <tk.h>\n#  if defined(TOGL_AGL)\n#    include <OpenGL/gl.h>\n#  elif defined(TOGL_NSOPENGL)\n#define GL_SILENCE_DEPRECATION\n#    include <OpenGL/OpenGL.h>\n#    include <OpenGL/gl.h>\n#  else\n#    include <GL/gl.h>\n#  endif\n\n#  ifdef BUILD_togl\n#    undef TCL_STORAGE_CLASS\n#    define TCL_STORAGE_CLASS DLLEXPORT\n#  endif\n\n#  ifndef CONST84\n#    define CONST84\n#  endif\n\n#  ifndef NULL\n#    define NULL 0\n#  endif\n\n#  ifndef EXTERN\n#    define EXTERN extern\n#  endif\n\n#  ifdef __cplusplus\n/* *INDENT-OFF* */\nextern \"C\" {\n/* *INDENT-ON* */\n#  endif\n\n#  define TOGL_VERSION \"2.1\"\n#  define TOGL_MAJOR_VERSION 2\n#  define TOGL_MINOR_VERSION 1\n\n/* \n * \"Standard\" fonts which can be specified to Togl_LoadBitmapFont()\n * Deprecated.  Use the Tk font name or description instead.\n */\n#  define TOGL_BITMAP_8_BY_13\t\t\"8x13\"\n#  define TOGL_BITMAP_9_BY_15\t\t\"9x15\"\n#  define TOGL_BITMAP_TIMES_ROMAN_10 \t\"Times 10\"\n#  define TOGL_BITMAP_TIMES_ROMAN_24 \t\"Times 24\"\n#  define TOGL_BITMAP_HELVETICA_10 \t\"Helvetica 10\"\n#  define TOGL_BITMAP_HELVETICA_12 \t\"Helvetica 12\"\n#  define TOGL_BITMAP_HELVETICA_18 \t\"Helvetica 18\"\n\n/* \n * Normal and overlay plane constants\n */\n#  define TOGL_NORMAL\t1\n#  define TOGL_OVERLAY\t2\n\n/* \n * Stereo techniques:\n *      Only the native method uses OpenGL quad-buffered stereo.\n *      All need the eye offset and eye distance set properly.\n */\n/* These versions need one eye drawn */\n#  define TOGL_STEREO_NONE\t\t0\n#  define TOGL_STEREO_LEFT_EYE\t\t1       /* just the left eye */\n#  define TOGL_STEREO_RIGHT_EYE\t\t2       /* just the right eye */\n#  define TOGL_STEREO_ONE_EYE_MAX\t127\n/* These versions need both eyes drawn */\n#  define TOGL_STEREO_NATIVE\t\t128\n#  define TOGL_STEREO_SGIOLDSTYLE\t129     /* interlaced, SGI API */\n#  define TOGL_STEREO_ANAGLYPH\t\t130\n#  define TOGL_STEREO_CROSS_EYE\t\t131\n#  define TOGL_STEREO_WALL_EYE\t\t132\n#  define TOGL_STEREO_DTI\t\t133     /* dti3d.com */\n#  define TOGL_STEREO_ROW_INTERLEAVED\t134     /* www.vrex.com/developer/interleave.htm */\n\nstruct Togl;\ntypedef struct Togl Togl;\ntypedef void (*Togl_FuncPtr) ();\n\nconst char *Togl_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, const char *version,\n                int exact));\n\n#  ifndef USE_TOGL_STUBS\n#    define Togl_InitStubs(interp, version, exact) \\\n\tTcl_PkgRequire(interp, \"Togl\", version, exact)\n#  endif\n\n/* \n * Platform independent exported functions\n */\n\n#  include \"toglDecls.h\"\n\n#  ifdef __cplusplus\n/* *INDENT-OFF* */\n}\n/* *INDENT-ON* */\n#  endif\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/toglAGL.c",
    "content": "/* $Id: toglAGL.c,v 1.7 2009/10/22 00:06:41 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\nstruct FBInfo\n{\n    GLint   acceleration;\n    GLint   colors;\n    GLint   depth;\n    GLint   samples;\n    AGLPixelFormat pix;\n};\ntypedef struct FBInfo FBInfo;\n\nstatic int\nFBInfoCmp(const void *a, const void *b)\n{\n    /* \n     * 1. full acceleration is better\n     * 2. greater color bits is better\n     * 3. greater depth bits is better\n     * 4. more multisampling is better\n     */\n    const FBInfo *x = (const FBInfo *) a;\n    const FBInfo *y = (const FBInfo *) b;\n\n    if (x->acceleration != y->acceleration)\n        return y->acceleration - x->acceleration;\n    if (x->colors != y->colors)\n        return y->colors - x->colors;\n    if (x->depth != y->depth)\n        return y->depth - x->depth;\n    if (x->samples != y->samples)\n        return y->samples - x->samples;\n    return 0;\n}\n\nstatic AGLPixelFormat\ntogl_pixelFormat(Togl *togl)\n{\n    GLint   attribs[32];\n    int     na = 0;\n    AGLPixelFormat pix;\n    GDHandle display = NULL;\n    FBInfo *info = NULL;\n    int     count;\n\n#if 0\n    if (togl->MultisampleFlag && !hasMultisampling) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n        return NULL;\n    }\n#endif\n\n    if (togl->PbufferFlag && !togl->RgbaFlag) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"puffer must be RGB[A]\", TCL_STATIC);\n        return NULL;\n    }\n\n    attribs[na++] = AGL_MINIMUM_POLICY;\n    /* ask for hardware-accelerated onscreen */\n    attribs[na++] = AGL_ACCELERATED;\n    attribs[na++] = AGL_NO_RECOVERY;\n    if (togl->RgbaFlag) {\n        /* RGB[A] mode */\n        attribs[na++] = AGL_RGBA;\n        attribs[na++] = AGL_RED_SIZE;\n        attribs[na++] = togl->RgbaRed;\n        attribs[na++] = AGL_GREEN_SIZE;\n        attribs[na++] = togl->RgbaGreen;\n        attribs[na++] = AGL_BLUE_SIZE;\n        attribs[na++] = togl->RgbaBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = AGL_ALPHA_SIZE;\n            attribs[na++] = togl->AlphaSize;\n        }\n    } else {\n        /* Color index mode */\n        attribs[na++] = AGL_BUFFER_SIZE;\n        attribs[na++] = 8;\n    }\n    if (togl->DepthFlag) {\n        attribs[na++] = AGL_DEPTH_SIZE;\n        attribs[na++] = togl->DepthSize;\n    }\n    if (togl->DoubleFlag) {\n        attribs[na++] = AGL_DOUBLEBUFFER;\n    }\n    if (togl->StencilFlag) {\n        attribs[na++] = AGL_STENCIL_SIZE;\n        attribs[na++] = togl->StencilSize;\n    }\n    if (togl->AccumFlag) {\n        attribs[na++] = AGL_ACCUM_RED_SIZE;\n        attribs[na++] = togl->AccumRed;\n        attribs[na++] = AGL_ACCUM_GREEN_SIZE;\n        attribs[na++] = togl->AccumGreen;\n        attribs[na++] = AGL_ACCUM_BLUE_SIZE;\n        attribs[na++] = togl->AccumBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = AGL_ACCUM_ALPHA_SIZE;\n            attribs[na++] = togl->AccumAlpha;\n        }\n    }\n    if (togl->MultisampleFlag) {\n        attribs[na++] = AGL_MULTISAMPLE;\n#ifdef AGL_SAMPLES_ARB\n        /* OS X 10.2 and later */\n        attribs[na++] = AGL_SAMPLE_BUFFERS_ARB;\n        attribs[na++] = 1;\n        attribs[na++] = AGL_SAMPLES_ARB;\n        attribs[na++] = 2;\n#endif\n    }\n    if (togl->AuxNumber != 0) {\n        attribs[na++] = AGL_AUX_BUFFERS;\n        attribs[na++] = togl->AuxNumber;\n    }\n    if (togl->Stereo == TOGL_STEREO_NATIVE) {\n        attribs[na++] = AGL_STEREO;\n    }\n    if (togl->FullscreenFlag) {\n        attribs[na++] = AGL_FULLSCREEN;\n        /* TODO: convert Tk screen to display device */\n        display = GetMainDevice();\n    }\n    attribs[na++] = AGL_NONE;\n\n    if ((pix = aglChoosePixelFormat(&display, togl->FullscreenFlag ? 1 : 0,\n                            attribs)) == NULL) {\n        Tcl_SetResult(togl->Interp, TCL_STUPID \"couldn't choose pixel format\",\n                TCL_STATIC);\n        return NULL;\n    }\n\n    /* TODO: since we aglDestroyPixelFormat elsewhere, this code may leak\n     * memory if the pixel format chosen is not the original (because\n     * aglDestroyPixelFormat will give an error). */\n    count = 0;\n    do {\n        info = (FBInfo *) realloc(info, (count + 1) * sizeof (FBInfo));\n        info[count].pix = pix;\n        aglDescribePixelFormat(pix, AGL_ACCELERATED, &info[count].acceleration);\n        aglDescribePixelFormat(pix, AGL_BUFFER_SIZE, &info[count].colors);\n        aglDescribePixelFormat(pix, AGL_DEPTH_SIZE, &info[count].depth);\n#ifdef AGL_SAMPLES_ARB\n        aglDescribePixelFormat(pix, AGL_SAMPLES_ARB, &info[count].samples);\n#else\n        info[count].samples = 0;\n#endif\n        ++count;\n    } while (pix = aglNextPixelFormat(pix));\n    qsort(info, count, sizeof info[0], FBInfoCmp);\n    pix = info[0].pix;\n    free(info);\n    return pix;\n}\n\nstatic int\ntogl_describePixelFormat(Togl *togl)\n{\n    AGLPixelFormat pixelformat;\n\n    /* fill in RgbaFlag, DoubleFlag, and Stereo */\n    pixelformat = (AGLPixelFormat) togl->PixelFormat;\n    GLint   has_rgba, has_doublebuf, has_depth, has_accum, has_alpha,\n            has_stencil, has_stereo, has_multisample;\n\n    if (aglDescribePixelFormat(pixelformat, AGL_RGBA, &has_rgba)\n            && aglDescribePixelFormat(pixelformat, AGL_DOUBLEBUFFER,\n                    &has_doublebuf)\n            && aglDescribePixelFormat(pixelformat, AGL_DEPTH_SIZE, &has_depth)\n            && aglDescribePixelFormat(pixelformat, AGL_ACCUM_RED_SIZE,\n                    &has_accum)\n            && aglDescribePixelFormat(pixelformat, AGL_ALPHA_SIZE, &has_alpha)\n            && aglDescribePixelFormat(pixelformat, AGL_STENCIL_SIZE,\n                    &has_stencil)\n            && aglDescribePixelFormat(pixelformat, AGL_STEREO, &has_stereo)\n#ifdef AGL_SAMPLES_ARB\n            && aglDescribePixelFormat(pixelformat, AGL_SAMPLES_ARB,\n                    &has_multisample)\n#endif\n            ) {\n        togl->RgbaFlag = (has_rgba != 0);\n        togl->DoubleFlag = (has_doublebuf != 0);\n        togl->DepthFlag = (has_depth != 0);\n        togl->AccumFlag = (has_accum != 0);\n        togl->AlphaFlag = (has_alpha != 0);\n        togl->StencilFlag = (has_stencil != 0);\n        togl->Stereo = (has_stereo ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE);\n#ifdef AGL_SAMPLES_ARB\n        togl->MultisampleFlag = (has_multisample != 0);\n#else\n        togl->MultisampleFlag = False;\n#endif\n        return True;\n    } else {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"failed querying pixel format attributes\",\n                TCL_STATIC);\n        return False;\n    }\n}\n\n#define isPow2(x) (((x) & ((x) - 1)) == 0)\n\nstatic AGLPbuffer\ntogl_createPbuffer(Togl *togl)\n{\n    GLint   min_size[2], max_size[2];\n    Bool    hasPbuffer;\n    const char *extensions;\n    GLboolean good;\n    GLint   target;\n    GLint   virtualScreen;\n    AGLPbuffer pbuf;\n\n    extensions = (const char *) glGetString(GL_EXTENSIONS);\n    hasPbuffer = (strstr(extensions, \"GL_APPLE_pixel_buffer\") != NULL);\n    if (!hasPbuffer) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"pbuffers are not supported\", TCL_STATIC);\n        return NULL;\n    }\n    glGetIntegerv(GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE, min_size);\n    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_size);\n    virtualScreen = aglGetVirtualScreen(togl->Ctx);\n    for (;;) {\n        /* make sure we don't exceed the maximum size because if we do,\n         * aglCreatePbuffer may succeed and later uses of the pbuffer fail */\n        if (togl->Width < min_size[0])\n            togl->Width = min_size[0];\n        else if (togl->Width > max_size[0]) {\n            if (togl->LargestPbufferFlag)\n                togl->Width = max_size[0];\n            else {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"pbuffer too large\", TCL_STATIC);\n                return NULL;\n            }\n        }\n        if (togl->Height < min_size[1])\n            togl->Height = min_size[1];\n        else if (togl->Height > max_size[1]) {\n            if (togl->LargestPbufferFlag)\n                togl->Height = max_size[1];\n            else {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"pbuffer too large\", TCL_STATIC);\n                return NULL;\n            }\n        }\n\n        if (isPow2(togl->Width) && isPow2(togl->Height))\n            target = GL_TEXTURE_2D;\n        else\n            target = GL_TEXTURE_RECTANGLE_ARB;\n\n        good = aglCreatePBuffer(togl->Width, togl->Height, target,\n                togl->AlphaFlag ? GL_RGBA : GL_RGB, 0, &pbuf);\n        if (good) {\n            /* aglSetPbuffer allocates the framebuffer space */\n            if (aglSetPBuffer(togl->Ctx, pbuf, 0, 0, virtualScreen)) {\n                return pbuf;\n            }\n        }\n        if (!togl->LargestPbufferFlag\n                || togl->Width == min_size[0] || togl->Height == min_size[1]) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to create pbuffer\", TCL_STATIC);\n            return NULL;\n        }\n        /* largest unavailable, try something smaller */\n        togl->Width = togl->Width / 2 + togl->Width % 2;\n        togl->Height = togl->Width / 2 + togl->Height % 2;\n    }\n}\n\nstatic void\ntogl_destroyPbuffer(Togl *togl)\n{\n    aglDestroyPBuffer(togl->pbuf);\n}\n"
  },
  {
    "path": "ng/Togl2.1/toglDecls.h",
    "content": "#ifndef ToglDecls_H\n#  define ToglDecls_H\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n/* !BEGIN!: Do not edit below this line. */\n\n/*\n * Exported function declarations:\n */\n\n#ifndef Togl_Init_TCL_DECLARED\n#define Togl_Init_TCL_DECLARED\n/* 0 */\nEXTERN int\t\tTogl_Init(Tcl_Interp *interp);\n#endif\n#ifndef Togl_MakeCurrent_TCL_DECLARED\n#define Togl_MakeCurrent_TCL_DECLARED\n/* 1 */\nEXTERN void\t\tTogl_MakeCurrent(const Togl *togl);\n#endif\n#ifndef Togl_PostRedisplay_TCL_DECLARED\n#define Togl_PostRedisplay_TCL_DECLARED\n/* 2 */\nEXTERN void\t\tTogl_PostRedisplay(Togl *togl);\n#endif\n#ifndef Togl_SwapBuffers_TCL_DECLARED\n#define Togl_SwapBuffers_TCL_DECLARED\n/* 3 */\nEXTERN void\t\tTogl_SwapBuffers(const Togl *togl);\n#endif\n#ifndef Togl_Ident_TCL_DECLARED\n#define Togl_Ident_TCL_DECLARED\n/* 4 */\nEXTERN const char *\tTogl_Ident(const Togl *togl);\n#endif\n#ifndef Togl_Width_TCL_DECLARED\n#define Togl_Width_TCL_DECLARED\n/* 5 */\nEXTERN int\t\tTogl_Width(const Togl *togl);\n#endif\n#ifndef Togl_Height_TCL_DECLARED\n#define Togl_Height_TCL_DECLARED\n/* 6 */\nEXTERN int\t\tTogl_Height(const Togl *togl);\n#endif\n#ifndef Togl_PixelScale_TCL_DECLARED\n#define Togl_PixelScale_TCL_DECLARED\n/* 6 */\nEXTERN int\t\tTogl_PixelScale(const Togl *togl);\n#endif\n#ifndef Togl_Interp_TCL_DECLARED\n#define Togl_Interp_TCL_DECLARED\n/* 7 */\nEXTERN Tcl_Interp *\tTogl_Interp(const Togl *togl);\n#endif\n#ifndef Togl_TkWin_TCL_DECLARED\n#define Togl_TkWin_TCL_DECLARED\n/* 8 */\nEXTERN Tk_Window\tTogl_TkWin(const Togl *togl);\n#endif\n#ifndef Togl_CommandName_TCL_DECLARED\n#define Togl_CommandName_TCL_DECLARED\n/* 9 */\nEXTERN const char *\tTogl_CommandName(const Togl *togl);\n#endif\n#ifndef Togl_AllocColor_TCL_DECLARED\n#define Togl_AllocColor_TCL_DECLARED\n/* 10 */\nEXTERN unsigned long\tTogl_AllocColor(const Togl *togl, float red,\n\t\t\t\tfloat green, float blue);\n#endif\n#ifndef Togl_FreeColor_TCL_DECLARED\n#define Togl_FreeColor_TCL_DECLARED\n/* 11 */\nEXTERN void\t\tTogl_FreeColor(const Togl *togl, unsigned long index);\n#endif\n#ifndef Togl_SetColor_TCL_DECLARED\n#define Togl_SetColor_TCL_DECLARED\n/* 12 */\nEXTERN void\t\tTogl_SetColor(const Togl *togl, unsigned long index,\n\t\t\t\tfloat red, float green, float blue);\n#endif\n#ifndef Togl_LoadBitmapFont_TCL_DECLARED\n#define Togl_LoadBitmapFont_TCL_DECLARED\n/* 13 */\nEXTERN Tcl_Obj *\tTogl_LoadBitmapFont(const Togl *togl,\n\t\t\t\tconst char *fontname);\n#endif\n#ifndef Togl_UnloadBitmapFont_TCL_DECLARED\n#define Togl_UnloadBitmapFont_TCL_DECLARED\n/* 14 */\nEXTERN int\t\tTogl_UnloadBitmapFont(const Togl *togl,\n\t\t\t\tTcl_Obj *toglfont);\n#endif\n#ifndef Togl_UseLayer_TCL_DECLARED\n#define Togl_UseLayer_TCL_DECLARED\n/* 15 */\nEXTERN void\t\tTogl_UseLayer(Togl *togl, int layer);\n#endif\n#ifndef Togl_ShowOverlay_TCL_DECLARED\n#define Togl_ShowOverlay_TCL_DECLARED\n/* 16 */\nEXTERN void\t\tTogl_ShowOverlay(Togl *togl);\n#endif\n#ifndef Togl_HideOverlay_TCL_DECLARED\n#define Togl_HideOverlay_TCL_DECLARED\n/* 17 */\nEXTERN void\t\tTogl_HideOverlay(Togl *togl);\n#endif\n#ifndef Togl_PostOverlayRedisplay_TCL_DECLARED\n#define Togl_PostOverlayRedisplay_TCL_DECLARED\n/* 18 */\nEXTERN void\t\tTogl_PostOverlayRedisplay(Togl *togl);\n#endif\n#ifndef Togl_ExistsOverlay_TCL_DECLARED\n#define Togl_ExistsOverlay_TCL_DECLARED\n/* 19 */\nEXTERN int\t\tTogl_ExistsOverlay(const Togl *togl);\n#endif\n#ifndef Togl_GetOverlayTransparentValue_TCL_DECLARED\n#define Togl_GetOverlayTransparentValue_TCL_DECLARED\n/* 20 */\nEXTERN int\t\tTogl_GetOverlayTransparentValue(const Togl *togl);\n#endif\n#ifndef Togl_IsMappedOverlay_TCL_DECLARED\n#define Togl_IsMappedOverlay_TCL_DECLARED\n/* 21 */\nEXTERN int\t\tTogl_IsMappedOverlay(const Togl *togl);\n#endif\n#ifndef Togl_AllocColorOverlay_TCL_DECLARED\n#define Togl_AllocColorOverlay_TCL_DECLARED\n/* 22 */\nEXTERN unsigned long\tTogl_AllocColorOverlay(const Togl *togl, float red,\n\t\t\t\tfloat green, float blue);\n#endif\n#ifndef Togl_FreeColorOverlay_TCL_DECLARED\n#define Togl_FreeColorOverlay_TCL_DECLARED\n/* 23 */\nEXTERN void\t\tTogl_FreeColorOverlay(const Togl *togl,\n\t\t\t\tunsigned long index);\n#endif\n#ifndef Togl_GetClientData_TCL_DECLARED\n#define Togl_GetClientData_TCL_DECLARED\n/* 24 */\nEXTERN ClientData\tTogl_GetClientData(const Togl *togl);\n#endif\n#ifndef Togl_SetClientData_TCL_DECLARED\n#define Togl_SetClientData_TCL_DECLARED\n/* 25 */\nEXTERN void\t\tTogl_SetClientData(Togl *togl, ClientData clientData);\n#endif\n#ifndef Togl_DrawBuffer_TCL_DECLARED\n#define Togl_DrawBuffer_TCL_DECLARED\n/* 26 */\nEXTERN void\t\tTogl_DrawBuffer(Togl *togl, GLenum mode);\n#endif\n#ifndef Togl_Clear_TCL_DECLARED\n#define Togl_Clear_TCL_DECLARED\n/* 27 */\nEXTERN void\t\tTogl_Clear(const Togl *togl, GLbitfield mask);\n#endif\n#ifndef Togl_Frustum_TCL_DECLARED\n#define Togl_Frustum_TCL_DECLARED\n/* 28 */\nEXTERN void\t\tTogl_Frustum(const Togl *togl, GLdouble left,\n\t\t\t\tGLdouble right, GLdouble bottom,\n\t\t\t\tGLdouble top, GLdouble near, GLdouble far);\n#endif\n#ifndef Togl_GetToglFromObj_TCL_DECLARED\n#define Togl_GetToglFromObj_TCL_DECLARED\n/* 29 */\nEXTERN int\t\tTogl_GetToglFromObj(Tcl_Interp *interp, Tcl_Obj *obj,\n\t\t\t\tTogl **toglPtr);\n#endif\n#ifndef Togl_TakePhoto_TCL_DECLARED\n#define Togl_TakePhoto_TCL_DECLARED\n/* 30 */\nEXTERN int\t\tTogl_TakePhoto(Togl *togl, Tk_PhotoHandle photo);\n#endif\n#ifndef Togl_GetProcAddr_TCL_DECLARED\n#define Togl_GetProcAddr_TCL_DECLARED\n/* 31 */\nEXTERN Togl_FuncPtr\tTogl_GetProcAddr(const char *funcname);\n#endif\n#ifndef Togl_GetToglFromName_TCL_DECLARED\n#define Togl_GetToglFromName_TCL_DECLARED\n/* 32 */\nEXTERN int\t\tTogl_GetToglFromName(Tcl_Interp *interp,\n\t\t\t\tconst char *cmdName, Togl **toglPtr);\n#endif\n#ifndef Togl_SwapInterval_TCL_DECLARED\n#define Togl_SwapInterval_TCL_DECLARED\n/* 33 */\nEXTERN Bool\t\tTogl_SwapInterval(const Togl *togl, int interval);\n#endif\n#ifndef Togl_Ortho_TCL_DECLARED\n#define Togl_Ortho_TCL_DECLARED\n/* 34 */\nEXTERN void\t\tTogl_Ortho(const Togl *togl, GLdouble left,\n\t\t\t\tGLdouble right, GLdouble bottom,\n\t\t\t\tGLdouble top, GLdouble near, GLdouble far);\n#endif\n#ifndef Togl_NumEyes_TCL_DECLARED\n#define Togl_NumEyes_TCL_DECLARED\n/* 35 */\nEXTERN int\t\tTogl_NumEyes(const Togl *togl);\n#endif\n#ifndef Togl_ContextTag_TCL_DECLARED\n#define Togl_ContextTag_TCL_DECLARED\n/* 36 */\nEXTERN int\t\tTogl_ContextTag(const Togl *togl);\n#endif\n#ifndef Togl_UpdatePending_TCL_DECLARED\n#define Togl_UpdatePending_TCL_DECLARED\n/* 37 */\nEXTERN Bool\t\tTogl_UpdatePending(const Togl *togl);\n#endif\n#ifndef Togl_WriteObj_TCL_DECLARED\n#define Togl_WriteObj_TCL_DECLARED\n/* 38 */\nEXTERN int\t\tTogl_WriteObj(const Togl *togl,\n\t\t\t\tconst Tcl_Obj *toglfont, Tcl_Obj *obj);\n#endif\n#ifndef Togl_WriteChars_TCL_DECLARED\n#define Togl_WriteChars_TCL_DECLARED\n/* 39 */\nEXTERN int\t\tTogl_WriteChars(const Togl *togl,\n\t\t\t\tconst Tcl_Obj *toglfont, const char *str,\n\t\t\t\tint len);\n#endif\n#ifndef Togl_HasRGBA_TCL_DECLARED\n#define Togl_HasRGBA_TCL_DECLARED\n/* 40 */\nEXTERN Bool\t\tTogl_HasRGBA(const Togl *togl);\n#endif\n#ifndef Togl_IsDoubleBuffered_TCL_DECLARED\n#define Togl_IsDoubleBuffered_TCL_DECLARED\n/* 41 */\nEXTERN Bool\t\tTogl_IsDoubleBuffered(const Togl *togl);\n#endif\n#ifndef Togl_HasDepthBuffer_TCL_DECLARED\n#define Togl_HasDepthBuffer_TCL_DECLARED\n/* 42 */\nEXTERN Bool\t\tTogl_HasDepthBuffer(const Togl *togl);\n#endif\n#ifndef Togl_HasAccumulationBuffer_TCL_DECLARED\n#define Togl_HasAccumulationBuffer_TCL_DECLARED\n/* 43 */\nEXTERN Bool\t\tTogl_HasAccumulationBuffer(const Togl *togl);\n#endif\n#ifndef Togl_HasDestinationAlpha_TCL_DECLARED\n#define Togl_HasDestinationAlpha_TCL_DECLARED\n/* 44 */\nEXTERN Bool\t\tTogl_HasDestinationAlpha(const Togl *togl);\n#endif\n#ifndef Togl_HasStencilBuffer_TCL_DECLARED\n#define Togl_HasStencilBuffer_TCL_DECLARED\n/* 45 */\nEXTERN Bool\t\tTogl_HasStencilBuffer(const Togl *togl);\n#endif\n#ifndef Togl_StereoMode_TCL_DECLARED\n#define Togl_StereoMode_TCL_DECLARED\n/* 46 */\nEXTERN int\t\tTogl_StereoMode(const Togl *togl);\n#endif\n#ifndef Togl_HasMultisample_TCL_DECLARED\n#define Togl_HasMultisample_TCL_DECLARED\n/* 47 */\nEXTERN Bool\t\tTogl_HasMultisample(const Togl *togl);\n#endif\n#ifndef Togl_CopyContext_TCL_DECLARED\n#define Togl_CopyContext_TCL_DECLARED\n/* 48 */\nEXTERN int\t\tTogl_CopyContext(const Togl *from, const Togl *to,\n\t\t\t\tunsigned int mask);\n#endif\n\ntypedef struct ToglStubs {\n    int magic;\n    const struct ToglStubHooks *hooks;\n\n    int (*togl_Init) (Tcl_Interp *interp); /* 0 */\n    void (*togl_MakeCurrent) (const Togl *togl); /* 1 */\n    void (*togl_PostRedisplay) (Togl *togl); /* 2 */\n    void (*togl_SwapBuffers) (const Togl *togl); /* 3 */\n    const char * (*togl_Ident) (const Togl *togl); /* 4 */\n    int (*togl_Width) (const Togl *togl); /* 5 */\n    int (*togl_Height) (const Togl *togl); /* 6 */\n    Tcl_Interp * (*togl_Interp) (const Togl *togl); /* 7 */\n    Tk_Window (*togl_TkWin) (const Togl *togl); /* 8 */\n    const char * (*togl_CommandName) (const Togl *togl); /* 9 */\n    unsigned long (*togl_AllocColor) (const Togl *togl, float red, float green, float blue); /* 10 */\n    void (*togl_FreeColor) (const Togl *togl, unsigned long index); /* 11 */\n    void (*togl_SetColor) (const Togl *togl, unsigned long index, float red, float green, float blue); /* 12 */\n    Tcl_Obj * (*togl_LoadBitmapFont) (const Togl *togl, const char *fontname); /* 13 */\n    int (*togl_UnloadBitmapFont) (const Togl *togl, Tcl_Obj *toglfont); /* 14 */\n    void (*togl_UseLayer) (Togl *togl, int layer); /* 15 */\n    void (*togl_ShowOverlay) (Togl *togl); /* 16 */\n    void (*togl_HideOverlay) (Togl *togl); /* 17 */\n    void (*togl_PostOverlayRedisplay) (Togl *togl); /* 18 */\n    int (*togl_ExistsOverlay) (const Togl *togl); /* 19 */\n    int (*togl_GetOverlayTransparentValue) (const Togl *togl); /* 20 */\n    int (*togl_IsMappedOverlay) (const Togl *togl); /* 21 */\n    unsigned long (*togl_AllocColorOverlay) (const Togl *togl, float red, float green, float blue); /* 22 */\n    void (*togl_FreeColorOverlay) (const Togl *togl, unsigned long index); /* 23 */\n    ClientData (*togl_GetClientData) (const Togl *togl); /* 24 */\n    void (*togl_SetClientData) (Togl *togl, ClientData clientData); /* 25 */\n    void (*togl_DrawBuffer) (Togl *togl, GLenum mode); /* 26 */\n    void (*togl_Clear) (const Togl *togl, GLbitfield mask); /* 27 */\n    void (*togl_Frustum) (const Togl *togl, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); /* 28 */\n    int (*togl_GetToglFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, Togl **toglPtr); /* 29 */\n    int (*togl_TakePhoto) (Togl *togl, Tk_PhotoHandle photo); /* 30 */\n    Togl_FuncPtr (*togl_GetProcAddr) (const char *funcname); /* 31 */\n    int (*togl_GetToglFromName) (Tcl_Interp *interp, const char *cmdName, Togl **toglPtr); /* 32 */\n    Bool (*togl_SwapInterval) (const Togl *togl, int interval); /* 33 */\n    void (*togl_Ortho) (const Togl *togl, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); /* 34 */\n    int (*togl_NumEyes) (const Togl *togl); /* 35 */\n    int (*togl_ContextTag) (const Togl *togl); /* 36 */\n    Bool (*togl_UpdatePending) (const Togl *togl); /* 37 */\n    int (*togl_WriteObj) (const Togl *togl, const Tcl_Obj *toglfont, Tcl_Obj *obj); /* 38 */\n    int (*togl_WriteChars) (const Togl *togl, const Tcl_Obj *toglfont, const char *str, int len); /* 39 */\n    Bool (*togl_HasRGBA) (const Togl *togl); /* 40 */\n    Bool (*togl_IsDoubleBuffered) (const Togl *togl); /* 41 */\n    Bool (*togl_HasDepthBuffer) (const Togl *togl); /* 42 */\n    Bool (*togl_HasAccumulationBuffer) (const Togl *togl); /* 43 */\n    Bool (*togl_HasDestinationAlpha) (const Togl *togl); /* 44 */\n    Bool (*togl_HasStencilBuffer) (const Togl *togl); /* 45 */\n    int (*togl_StereoMode) (const Togl *togl); /* 46 */\n    Bool (*togl_HasMultisample) (const Togl *togl); /* 47 */\n    int (*togl_CopyContext) (const Togl *from, const Togl *to, unsigned int mask); /* 48 */\n} ToglStubs;\n\n#if defined(USE_TOGL_STUBS) && !defined(USE_TOGL_STUB_PROCS)\nextern const ToglStubs *toglStubsPtr;\n#endif /* defined(USE_TOGL_STUBS) && !defined(USE_TOGL_STUB_PROCS) */\n\n#if defined(USE_TOGL_STUBS) && !defined(USE_TOGL_STUB_PROCS)\n\n/*\n * Inline function declarations:\n */\n\n#ifndef Togl_Init\n#define Togl_Init \\\n\t(toglStubsPtr->togl_Init) /* 0 */\n#endif\n#ifndef Togl_MakeCurrent\n#define Togl_MakeCurrent \\\n\t(toglStubsPtr->togl_MakeCurrent) /* 1 */\n#endif\n#ifndef Togl_PostRedisplay\n#define Togl_PostRedisplay \\\n\t(toglStubsPtr->togl_PostRedisplay) /* 2 */\n#endif\n#ifndef Togl_SwapBuffers\n#define Togl_SwapBuffers \\\n\t(toglStubsPtr->togl_SwapBuffers) /* 3 */\n#endif\n#ifndef Togl_Ident\n#define Togl_Ident \\\n\t(toglStubsPtr->togl_Ident) /* 4 */\n#endif\n#ifndef Togl_Width\n#define Togl_Width \\\n\t(toglStubsPtr->togl_Width) /* 5 */\n#endif\n#ifndef Togl_Height\n#define Togl_Height \\\n\t(toglStubsPtr->togl_Height) /* 6 */\n#endif\n#ifndef Togl_Interp\n#define Togl_Interp \\\n\t(toglStubsPtr->togl_Interp) /* 7 */\n#endif\n#ifndef Togl_TkWin\n#define Togl_TkWin \\\n\t(toglStubsPtr->togl_TkWin) /* 8 */\n#endif\n#ifndef Togl_CommandName\n#define Togl_CommandName \\\n\t(toglStubsPtr->togl_CommandName) /* 9 */\n#endif\n#ifndef Togl_AllocColor\n#define Togl_AllocColor \\\n\t(toglStubsPtr->togl_AllocColor) /* 10 */\n#endif\n#ifndef Togl_FreeColor\n#define Togl_FreeColor \\\n\t(toglStubsPtr->togl_FreeColor) /* 11 */\n#endif\n#ifndef Togl_SetColor\n#define Togl_SetColor \\\n\t(toglStubsPtr->togl_SetColor) /* 12 */\n#endif\n#ifndef Togl_LoadBitmapFont\n#define Togl_LoadBitmapFont \\\n\t(toglStubsPtr->togl_LoadBitmapFont) /* 13 */\n#endif\n#ifndef Togl_UnloadBitmapFont\n#define Togl_UnloadBitmapFont \\\n\t(toglStubsPtr->togl_UnloadBitmapFont) /* 14 */\n#endif\n#ifndef Togl_UseLayer\n#define Togl_UseLayer \\\n\t(toglStubsPtr->togl_UseLayer) /* 15 */\n#endif\n#ifndef Togl_ShowOverlay\n#define Togl_ShowOverlay \\\n\t(toglStubsPtr->togl_ShowOverlay) /* 16 */\n#endif\n#ifndef Togl_HideOverlay\n#define Togl_HideOverlay \\\n\t(toglStubsPtr->togl_HideOverlay) /* 17 */\n#endif\n#ifndef Togl_PostOverlayRedisplay\n#define Togl_PostOverlayRedisplay \\\n\t(toglStubsPtr->togl_PostOverlayRedisplay) /* 18 */\n#endif\n#ifndef Togl_ExistsOverlay\n#define Togl_ExistsOverlay \\\n\t(toglStubsPtr->togl_ExistsOverlay) /* 19 */\n#endif\n#ifndef Togl_GetOverlayTransparentValue\n#define Togl_GetOverlayTransparentValue \\\n\t(toglStubsPtr->togl_GetOverlayTransparentValue) /* 20 */\n#endif\n#ifndef Togl_IsMappedOverlay\n#define Togl_IsMappedOverlay \\\n\t(toglStubsPtr->togl_IsMappedOverlay) /* 21 */\n#endif\n#ifndef Togl_AllocColorOverlay\n#define Togl_AllocColorOverlay \\\n\t(toglStubsPtr->togl_AllocColorOverlay) /* 22 */\n#endif\n#ifndef Togl_FreeColorOverlay\n#define Togl_FreeColorOverlay \\\n\t(toglStubsPtr->togl_FreeColorOverlay) /* 23 */\n#endif\n#ifndef Togl_GetClientData\n#define Togl_GetClientData \\\n\t(toglStubsPtr->togl_GetClientData) /* 24 */\n#endif\n#ifndef Togl_SetClientData\n#define Togl_SetClientData \\\n\t(toglStubsPtr->togl_SetClientData) /* 25 */\n#endif\n#ifndef Togl_DrawBuffer\n#define Togl_DrawBuffer \\\n\t(toglStubsPtr->togl_DrawBuffer) /* 26 */\n#endif\n#ifndef Togl_Clear\n#define Togl_Clear \\\n\t(toglStubsPtr->togl_Clear) /* 27 */\n#endif\n#ifndef Togl_Frustum\n#define Togl_Frustum \\\n\t(toglStubsPtr->togl_Frustum) /* 28 */\n#endif\n#ifndef Togl_GetToglFromObj\n#define Togl_GetToglFromObj \\\n\t(toglStubsPtr->togl_GetToglFromObj) /* 29 */\n#endif\n#ifndef Togl_TakePhoto\n#define Togl_TakePhoto \\\n\t(toglStubsPtr->togl_TakePhoto) /* 30 */\n#endif\n#ifndef Togl_GetProcAddr\n#define Togl_GetProcAddr \\\n\t(toglStubsPtr->togl_GetProcAddr) /* 31 */\n#endif\n#ifndef Togl_GetToglFromName\n#define Togl_GetToglFromName \\\n\t(toglStubsPtr->togl_GetToglFromName) /* 32 */\n#endif\n#ifndef Togl_SwapInterval\n#define Togl_SwapInterval \\\n\t(toglStubsPtr->togl_SwapInterval) /* 33 */\n#endif\n#ifndef Togl_Ortho\n#define Togl_Ortho \\\n\t(toglStubsPtr->togl_Ortho) /* 34 */\n#endif\n#ifndef Togl_NumEyes\n#define Togl_NumEyes \\\n\t(toglStubsPtr->togl_NumEyes) /* 35 */\n#endif\n#ifndef Togl_ContextTag\n#define Togl_ContextTag \\\n\t(toglStubsPtr->togl_ContextTag) /* 36 */\n#endif\n#ifndef Togl_UpdatePending\n#define Togl_UpdatePending \\\n\t(toglStubsPtr->togl_UpdatePending) /* 37 */\n#endif\n#ifndef Togl_WriteObj\n#define Togl_WriteObj \\\n\t(toglStubsPtr->togl_WriteObj) /* 38 */\n#endif\n#ifndef Togl_WriteChars\n#define Togl_WriteChars \\\n\t(toglStubsPtr->togl_WriteChars) /* 39 */\n#endif\n#ifndef Togl_HasRGBA\n#define Togl_HasRGBA \\\n\t(toglStubsPtr->togl_HasRGBA) /* 40 */\n#endif\n#ifndef Togl_IsDoubleBuffered\n#define Togl_IsDoubleBuffered \\\n\t(toglStubsPtr->togl_IsDoubleBuffered) /* 41 */\n#endif\n#ifndef Togl_HasDepthBuffer\n#define Togl_HasDepthBuffer \\\n\t(toglStubsPtr->togl_HasDepthBuffer) /* 42 */\n#endif\n#ifndef Togl_HasAccumulationBuffer\n#define Togl_HasAccumulationBuffer \\\n\t(toglStubsPtr->togl_HasAccumulationBuffer) /* 43 */\n#endif\n#ifndef Togl_HasDestinationAlpha\n#define Togl_HasDestinationAlpha \\\n\t(toglStubsPtr->togl_HasDestinationAlpha) /* 44 */\n#endif\n#ifndef Togl_HasStencilBuffer\n#define Togl_HasStencilBuffer \\\n\t(toglStubsPtr->togl_HasStencilBuffer) /* 45 */\n#endif\n#ifndef Togl_StereoMode\n#define Togl_StereoMode \\\n\t(toglStubsPtr->togl_StereoMode) /* 46 */\n#endif\n#ifndef Togl_HasMultisample\n#define Togl_HasMultisample \\\n\t(toglStubsPtr->togl_HasMultisample) /* 47 */\n#endif\n#ifndef Togl_CopyContext\n#define Togl_CopyContext \\\n\t(toglStubsPtr->togl_CopyContext) /* 48 */\n#endif\n\n#endif /* defined(USE_TOGL_STUBS) && !defined(USE_TOGL_STUB_PROCS) */\n\n/* !END!: Do not edit above this line. */\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/toglFont.c",
    "content": "/* $Id: toglFont.c,v 1.8 2009/05/22 00:18:36 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2008  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n/* \n * Togl Bitmap Font support\n *\n * If bitmap font support is requested, then this file is included into\n * togl.c.  Parts of this file are based on <http://wiki.tcl.tk/13881>,\n * \"Creating and Using Tcl Handles in C Extensions\".\n *\n * Neither the Tk public nor the internal interface give enough information\n * to reuse the font in OpenGL, so we copy the private structures here to\n * access what we need.\n *\n * Globals needed by the font module are in togl.c\n */\n\n#include <tkFont.h>\n\nstruct Togl_BitmapFontInfo\n{\n    GLuint  base;\n    GLuint  first;\n    GLuint  last;\n    int     contextTag;\n    /* TODO: keep original font and/or encoding */\n};\ntypedef struct Togl_BitmapFontInfo Togl_BitmapFontInfo;\n\n#define BITMAP_FONT_INFO(obj) \\\n                ((Togl_BitmapFontInfo *) (obj)->internalRep.otherValuePtr)\n#define SET_BITMAP_FONT_INFO(obj) \\\n                (obj)->internalRep.otherValuePtr\n\nstatic void Togl_FontFree(Tcl_Obj *obj);\nstatic void Togl_FontDup(Tcl_Obj *src, Tcl_Obj *dup);\nstatic void Togl_FontString(Tcl_Obj *obj);\nstatic int Togl_FontSet(Tcl_Interp *interp, Tcl_Obj *obj);\n\nstatic Tcl_ObjType Togl_BitmapFontType = {\n    \"Togl BitmapFont\",          /* name */\n    Togl_FontFree,              /* free internal rep */\n    Togl_FontDup,               /* dup internal rep */\n    Togl_FontString,            /* update string from internal rep */\n    Togl_FontSet                /* set internal rep from string */\n};\n\nstatic int\nTogl_FontSet(Tcl_Interp *interp, Tcl_Obj *obj)\n{\n    if (interp)\n        Tcl_AppendResult(interp, \"cannot (re)build object of type \\\"\",\n                Togl_BitmapFontType.name, \"\\\"\", NULL);\n    return TCL_ERROR;\n}\n\nstatic void\nTogl_FontFree(Tcl_Obj *obj)\n{\n    Togl_BitmapFontInfo *bfi = BITMAP_FONT_INFO(obj);\n\n    ckfree((char *) bfi);\n}\n\nstatic void\nTogl_FontString(Tcl_Obj *obj)\n{\n    /* assert(obj->bytes == NULL) */\n    static char buf[256];\n    register unsigned len;\n    Togl_BitmapFontInfo *bfi = BITMAP_FONT_INFO(obj);\n\n#if !defined(TOGL_AGL) && !defined(TOGL_NSOPENGL)\n    snprintf(buf, sizeof buf - 1, \"{{%s} %d %d %d}\",\n            Togl_BitmapFontType.name, bfi->base, bfi->first, bfi->last);\n#else\n    /* unlike every other platform, on Aqua, GLint is long */\n    snprintf(buf, sizeof buf - 1, \"{{%s} %ld %ld %ld}\",\n            Togl_BitmapFontType.name, bfi->base, bfi->first, bfi->last);\n#endif\n    buf[sizeof buf - 1] = '\\0';\n    len = strlen(buf);\n    obj->bytes = (char *) ckalloc(len + 1);\n    strcpy(obj->bytes, buf);\n    obj->length = len;\n}\n\nstatic void\nTogl_FontDup(Tcl_Obj *src, Tcl_Obj *dup)\n{\n    /* \n     * When duplicated, lose the font-ness and just be a string.\n     * So don't copy the internal representation and don't set\n     * dup->typePtr.\n     */\n}\n\n#if defined(TOGL_X11)\n/* From tkUnixFont.c */\n/* \n * The following structure encapsulates an individual screen font.  A font\n * object is made up of however many SubFonts are necessary to display a\n * stream of multilingual characters.\n */\n\ntypedef struct FontFamily FontFamily;\n\ntypedef struct SubFont\n{\n    char  **fontMap;            /* Pointer to font map from the FontFamily,\n                                 * cached here to save a dereference. */\n    XFontStruct *fontStructPtr; /* The specific screen font that will be used\n                                 * when displaying/measuring chars belonging to \n                                 * the FontFamily. */\n    FontFamily *familyPtr;      /* The FontFamily for this SubFont. */\n} SubFont;\n\n/* \n * The following structure represents Unix's implementation of a font\n * object.\n */\n\n#  define SUBFONT_SPACE\t\t3\n#  define BASE_CHARS\t\t256\n\ntypedef struct UnixFont\n{\n    TkFont  font;               /* Stuff used by generic font package.  Must be \n                                 * first in structure. */\n    SubFont staticSubFonts[SUBFONT_SPACE];\n    /* Builtin space for a limited number of SubFonts. */\n    int     numSubFonts;        /* Length of following array. */\n    SubFont *subFontArray;      /* Array of SubFonts that have been loaded in\n                                 * order to draw/measure all the characters\n                                 * encountered by this font so far.  All fonts\n                                 * start off with one SubFont initialized by\n                                 * AllocFont() from the original set of font\n                                 * attributes.  Usually points to\n                                 * staticSubFonts, but may point to malloced\n                                 * space if there are lots of SubFonts. */\n    SubFont controlSubFont;     /* Font to use to display control-character\n                                 * expansions. */\n\n#  if 0\n    Display *display;           /* Display that owns font. */\n    int     pixelSize;          /* Original pixel size used when font was\n                                 * constructed. */\n    TkXLFDAttributes xa;        /* Additional attributes that specify the\n                                 * preferred foundry and encoding to use when\n                                 * constructing additional SubFonts. */\n    int     widths[BASE_CHARS]; /* Widths of first 256 chars in the base font,\n                                 * for handling common case. */\n    int     underlinePos;       /* Offset from baseline to origin of underline\n                                 * bar (used when drawing underlined font)\n                                 * (pixels). */\n    int     barHeight;          /* Height of underline or overstrike bar (used\n                                 * when drawing underlined or strikeout font)\n                                 * (pixels). */\n#  endif\n} UnixFont;\n\n#elif defined(TOGL_WGL)\n#  include <tkWinInt.h>\n/* From tkWinFont.c */\n\ntypedef struct FontFamily FontFamily;\n\n/* \n * The following structure encapsulates an individual screen font.  A font\n * object is made up of however many SubFonts are necessary to display a\n * stream of multilingual characters.\n */\n\ntypedef struct SubFont\n{\n    char  **fontMap;            /* Pointer to font map from the FontFamily,\n                                 * cached here to save a dereference. */\n    HFONT   hFont;              /* The specific screen font that will be used\n                                 * when displaying/measuring chars belonging to \n                                 * the FontFamily. */\n    FontFamily *familyPtr;      /* The FontFamily for this SubFont. */\n} SubFont;\n\n/* \n * The following structure represents Windows' implementation of a font\n * object.\n */\n\n#  define SUBFONT_SPACE\t\t3\n#  define BASE_CHARS\t\t128\n\ntypedef struct WinFont\n{\n    TkFont  font;               /* Stuff used by generic font package.  Must be \n                                 * first in structure. */\n    SubFont staticSubFonts[SUBFONT_SPACE];\n    /* Builtin space for a limited number of SubFonts. */\n    int     numSubFonts;        /* Length of following array. */\n    SubFont *subFontArray;      /* Array of SubFonts that have been loaded in\n                                 * order to draw/measure all the characters\n                                 * encountered by this font so far.  All fonts\n                                 * start off with one SubFont initialized by\n                                 * AllocFont() from the original set of font\n                                 * attributes.  Usually points to\n                                 * staticSubFonts, but may point to malloced\n                                 * space if there are lots of SubFonts. */\n\n    HWND    hwnd;               /* Toplevel window of application that owns\n                                 * this font, used for getting HDC for\n                                 * offscreen measurements. */\n    int     pixelSize;          /* Original pixel size used when font was\n                                 * constructed. */\n    int     widths[BASE_CHARS]; /* Widths of first 128 chars in the base font,\n                                 * for handling common case.  The base font is\n                                 * always used to draw characters between\n                                 * 0x0000 and 0x007f. */\n} WinFont;\n\n#elif defined(TOGL_AGL)\n\ntypedef struct FontFamily\n{\n    struct FontFamily *nextPtr; /* Next in list of all known font families. */\n    int     refCount;           /* How many SubFonts are referring to this\n                                 * FontFamily.  When the refCount drops to\n                                 * zero, this FontFamily may be freed. */\n    /* \n     * Key.\n     */\n\n    FMFontFamily faceNum;       /* Unique face number key for this FontFamily. */\n\n    /* \n     * Derived properties.\n     */\n\n    Tcl_Encoding encoding;      /* Encoding for this font family. */\n#  if 0\n    int     isSymbolFont;       /* Non-zero if this is a symbol family. */\n    int     isMultiByteFont;    /* Non-zero if this is a multi-byte family. */\n    char    typeTable[256];     /* Table that identfies all lead bytes for a\n                                 * multi-byte family, used when measuring\n                                 * chars. If a byte is a lead byte, the value\n                                 * at the corresponding position in the\n                                 * typeTable is 1, otherwise 0.  If this is a\n                                 * single-byte font, all entries are 0. */\n    char   *fontMap[FONTMAP_PAGES];\n    /* Two-level sparse table used to determine quickly if the specified\n     * character exists. As characters are encountered, more pages in this\n     * table are dynamically added.  The contents of each page is a bitmask\n     * consisting of FONTMAP_BITSPERPAGE bits, representing whether this font\n     * can be used to display the given character at the corresponding bit\n     * position.  The high bits of the character are used to pick which page of \n     * the table is used. */\n#  endif\n} FontFamily;\n\n/* \n * The following structure encapsulates an individual screen font.  A font\n * object is made up of however many SubFonts are necessary to display a\n * stream of multilingual characters.\n */\n\ntypedef struct SubFont\n{\n    char  **fontMap;            /* Pointer to font map from the FontFamily,\n                                 * cached here to save a dereference. */\n    FontFamily *familyPtr;      /* The FontFamily for this SubFont. */\n} SubFont;\n\n/* \n * The following structure represents Macintosh's implementation of a font\n * object.\n */\n\n#  define SUBFONT_SPACE                3\n\ntypedef struct MacFont\n{\n    TkFont  font;               /* Stuff used by generic font package.  Must be \n                                 * first in structure. */\n    SubFont staticSubFonts[SUBFONT_SPACE];\n    /* Builtin space for a limited number of SubFonts. */\n    int     numSubFonts;        /* Length of following array. */\n    SubFont *subFontArray;      /* Array of SubFonts that have been loaded in\n                                 * order to draw/measure all the characters\n                                 * encountered by this font so far.  All fonts\n                                 * start off with one SubFont initialized by\n                                 * AllocFont() from the original set of font\n                                 * attributes.  Usually points to\n                                 * staticSubFonts, but may point to malloced\n                                 * space if there are lots of SubFonts. */\n\n    short   size;               /* Font size in pixels, constructed from font\n                                 * attributes. */\n    short   style;              /* Style bits, constructed from font\n                                 * attributes. */\n} MacFont;\n#endif\n\n/* \n * Load the named bitmap font as a sequence of bitmaps in a display list.\n * fontname may be any font recognized by Tk_GetFont.\n */\nTcl_Obj *\nTogl_LoadBitmapFont(const Togl *togl, const char *fontname)\n{\n    Tk_Font font;\n    Togl_BitmapFontInfo *bfi;\n    Tcl_Obj *obj;\n\n#if defined(TOGL_X11)\n    UnixFont *unixfont;\n    XFontStruct *fontinfo;\n#elif defined(TOGL_WGL)\n    WinFont *winfont;\n    HFONT   oldFont;\n    TEXTMETRIC tm;\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    MacFont *macfont;\n#endif\n    int     first, last, count;\n    GLuint  fontbase;\n\n    if (!fontname) {\n        fontname = DEFAULT_FONTNAME;\n    }\n\n    font = Tk_GetFont(togl->Interp, togl->TkWin, fontname);\n    if (!font) {\n        return NULL;\n    }\n#if defined(TOGL_X11)\n    unixfont = (UnixFont *) font;\n    fontinfo = unixfont->subFontArray->fontStructPtr;\n    first = fontinfo->min_char_or_byte2;\n    last = fontinfo->max_char_or_byte2;\n#elif defined(TOGL_WGL)\n    winfont = (WinFont *) font;\n    oldFont =\n            (HFONT) SelectObject(togl->tglGLHdc, winfont->subFontArray->hFont);\n    GetTextMetrics(togl->tglGLHdc, &tm);\n    first = tm.tmFirstChar;\n    last = tm.tmLastChar;\n#elif defined(TOGL_AGL) || defined(TOGL_NSOPENGL)\n    macfont = (MacFont *) font;\n    first = 10;                 /* don't know how to determine font range on\n                                 * Mac... */\n    last = 255;\n#endif\n\n    if (last > 255)\n        last = 255;             /* no unicode support */\n\n    count = last - first + 1;\n    fontbase = glGenLists((GLuint) (last + 1));\n    if (fontbase == 0) {\n#ifdef TOGL_WGL\n        SelectObject(togl->tglGLHdc, oldFont);\n#endif\n        Tk_FreeFont(font);\n        return NULL;\n    }\n#if defined(TOGL_WGL)\n    wglUseFontBitmaps(togl->tglGLHdc, first, count, fontbase + first);\n    SelectObject(togl->tglGLHdc, oldFont);\n#elif defined(TOGL_X11)\n    glXUseXFont(fontinfo->fid, first, count, (int) fontbase + first);\n#elif defined(TOGL_AGL)\n    /* deprecated in OS X 10.5 */\n    aglUseFont(togl->Ctx,\n            macfont->subFontArray->familyPtr->faceNum,\n            macfont->style, macfont->size, first, count, fontbase + first);\n#elif defined(TOGL_NSOPENGL)\n    /* No NSOpenGL equivalent to aglUseFont(). */\n#endif\n    Tk_FreeFont(font);\n\n    bfi = (Togl_BitmapFontInfo *) ckalloc(sizeof (Togl_BitmapFontInfo));\n    bfi->base = fontbase;\n    bfi->first = first;\n    bfi->last = last;\n    bfi->contextTag = togl->contextTag;\n\n    obj = Tcl_NewObj();\n    SET_BITMAP_FONT_INFO(obj) = bfi;\n    obj->typePtr = &Togl_BitmapFontType;\n\n    return obj;\n}\n\n/* \n * Release the display lists which were generated by Togl_LoadBitmapFont().\n */\nint\nTogl_UnloadBitmapFont(const Togl *togl, Tcl_Obj *toglfont)\n{\n    Togl_BitmapFontInfo *bfi;\n\n    if (toglfont == NULL || toglfont->typePtr != &Togl_BitmapFontType) {\n        Tcl_Interp *interp = Togl_Interp(togl);\n\n        Tcl_AppendResult(interp, \"font not found\", NULL);\n        return TCL_ERROR;\n    }\n    bfi = BITMAP_FONT_INFO(toglfont);\n    glDeleteLists(bfi->base, bfi->last + 1);    /* match glGenLists */\n    return TCL_OK;\n}\n\nint\nTogl_WriteObj(const Togl *togl, const Tcl_Obj *toglfont, Tcl_Obj *obj)\n{\n    const char *str;\n    int     len;\n\n    str = Tcl_GetStringFromObj(obj, &len);\n    return Togl_WriteChars(togl, toglfont, str, len);\n}\n\nint\nTogl_WriteChars(const Togl *togl, const Tcl_Obj *toglfont, const char *str,\n        int len)\n{\n    /* TODO: assume utf8 encoding and convert to font encoding */\n    Togl_BitmapFontInfo *bfi;\n\n    if (toglfont == NULL || toglfont->typePtr != &Togl_BitmapFontType)\n        return -1;\n    bfi = BITMAP_FONT_INFO(toglfont);\n    if (Togl_ContextTag(togl) != bfi->contextTag)\n        return -1;\n    if (len == 0)\n        len = strlen(str);\n    glListBase(bfi->base);\n    glCallLists(len, GL_UNSIGNED_BYTE, str);\n    return len;\n}\n"
  },
  {
    "path": "ng/Togl2.1/toglGLX.c",
    "content": "/* $Id: toglGLX.c,v 1.12 2009/10/22 20:40:52 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n/* TODO: fullscreen support */\n\n#undef DEBUG_GLX\n\nstatic PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig = NULL;\nstatic PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttrib = NULL;\nstatic PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfig = NULL;\nstatic PFNGLXCREATEPBUFFERPROC createPbuffer = NULL;\nstatic PFNGLXCREATEGLXPBUFFERSGIXPROC createPbufferSGIX = NULL;\nstatic PFNGLXDESTROYPBUFFERPROC destroyPbuffer = NULL;\nstatic PFNGLXQUERYDRAWABLEPROC queryPbuffer = NULL;\nstatic Bool hasMultisampling = False;\nstatic Bool hasPbuffer = False;\n\nstruct FBInfo\n{\n    int     acceleration;\n    int     samples;\n    int     depth;\n    int     colors;\n    GLXFBConfig fbcfg;\n    XVisualInfo *visInfo;\n};\ntypedef struct FBInfo FBInfo;\n\nstatic int\nFBInfoCmp(const void *a, const void *b)\n{\n    /* \n     * 1. full acceleration is better\n     * 2. greater color bits is better\n     * 3. greater depth bits is better\n     * 4. more multisampling is better\n     */\n    const FBInfo *x = (const FBInfo *) a;\n    const FBInfo *y = (const FBInfo *) b;\n\n    if (x->acceleration != y->acceleration)\n        return y->acceleration - x->acceleration;\n    if (x->colors != y->colors)\n        return y->colors - x->colors;\n    if (x->depth != y->depth)\n        return y->depth - x->depth;\n    if (x->samples != y->samples)\n        return y->samples - x->samples;\n    return 0;\n}\n\n#ifdef DEBUG_GLX\nstatic int\nfatal_error(Display *dpy, XErrorEvent * event)\n{\n    char    buf[256];\n\n    XGetErrorText(dpy, event->error_code, buf, sizeof buf);\n    fprintf(stderr, \"%s\\n\", buf);\n    abort();\n}\n#endif\n\nstatic XVisualInfo *\ntogl_pixelFormat(Togl *togl, int scrnum)\n{\n    int     attribs[256];\n    int     na = 0;\n    int     i;\n    XVisualInfo *visinfo;\n    FBInfo *info;\n    static int loadedOpenGL = False;\n\n    if (!loadedOpenGL) {\n        int     dummy;\n        int     major, minor;\n        const char *extensions;\n\n        /* Make sure OpenGL's GLX extension supported */\n        if (!glXQueryExtension(togl->display, &dummy, &dummy)) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"X server is missing OpenGL GLX extension\",\n                    TCL_STATIC);\n            return NULL;\n        }\n\n        loadedOpenGL = True;\n#ifdef DEBUG_GLX\n        (void) XSetErrorHandler(fatal_error);\n#endif\n\n        glXQueryVersion(togl->display, &major, &minor);\n        extensions = glXQueryExtensionsString(togl->display, scrnum);\n\n        if (major > 1 || (major == 1 && minor >= 3)) {\n            chooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)\n                    Togl_GetProcAddr(\"glXChooseFBConfig\");\n            getFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)\n                    Togl_GetProcAddr(\"glXGetFBConfigAttrib\");\n            getVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)\n                    Togl_GetProcAddr(\"glXGetVisualFromFBConfig\");\n            createPbuffer = (PFNGLXCREATEPBUFFERPROC)\n                    Togl_GetProcAddr(\"glXCreatePbuffer\");\n            destroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)\n                    Togl_GetProcAddr(\"glXDestroyPbuffer\");\n            queryPbuffer = (PFNGLXQUERYDRAWABLEPROC)\n                    Togl_GetProcAddr(\"glXQueryDrawable\");\n            if (createPbuffer && destroyPbuffer && queryPbuffer) {\n                hasPbuffer = True;\n            } else {\n                createPbuffer = NULL;\n                destroyPbuffer = NULL;\n                queryPbuffer = NULL;\n            }\n        }\n        if (major == 1 && minor == 2) {\n            chooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)\n                    Togl_GetProcAddr(\"glXChooseFBConfigSGIX\");\n            getFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)\n                    Togl_GetProcAddr(\"glXGetFBConfigAttribSGIX\");\n            getVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)\n                    Togl_GetProcAddr(\"glXGetVisualFromFBConfigSGIX\");\n            if (strstr(extensions, \"GLX_SGIX_pbuffer\") != NULL) {\n                createPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)\n                        Togl_GetProcAddr(\"glXCreateGLXPbufferSGIX\");\n                destroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)\n                        Togl_GetProcAddr(\"glXDestroyGLXPbufferSGIX\");\n                queryPbuffer = (PFNGLXQUERYDRAWABLEPROC)\n                        Togl_GetProcAddr(\"glXQueryGLXPbufferSGIX\");\n                if (createPbufferSGIX && destroyPbuffer && queryPbuffer) {\n                    hasPbuffer = True;\n                } else {\n                    createPbufferSGIX = NULL;\n                    destroyPbuffer = NULL;\n                    queryPbuffer = NULL;\n                }\n            }\n        }\n        if (chooseFBConfig) {\n            /* verify that chooseFBConfig works (workaround Mesa 6.5 bug) */\n            int     n = 0;\n            GLXFBConfig *cfgs;\n\n            attribs[n++] = GLX_RENDER_TYPE;\n            attribs[n++] = GLX_RGBA_BIT;\n            attribs[n++] = None;\n\n            cfgs = chooseFBConfig(togl->display, scrnum, attribs, &n);\n            if (cfgs == NULL || n == 0) {\n                chooseFBConfig = NULL;\n            }\n            XFree(cfgs);\n        }\n        if (chooseFBConfig == NULL\n                || getFBConfigAttrib == NULL || getVisualFromFBConfig == NULL) {\n            chooseFBConfig = NULL;\n            getFBConfigAttrib = NULL;\n            getVisualFromFBConfig = NULL;\n        }\n        if (hasPbuffer && !chooseFBConfig) {\n            hasPbuffer = False;\n        }\n\n        if ((major > 1 || (major == 1 && minor >= 4))\n                || strstr(extensions, \"GLX_ARB_multisample\") != NULL\n                || strstr(extensions, \"GLX_SGIS_multisample\") != NULL) {\n            /* Client GLX supports multisampling, but does the server? Well, we \n             * can always ask. */\n            hasMultisampling = True;\n        }\n    }\n\n    if (togl->MultisampleFlag && !hasMultisampling) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n        return NULL;\n    }\n\n    if (togl->PbufferFlag && !hasPbuffer) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"pbuffers are not supported\", TCL_STATIC);\n        return NULL;\n    }\n\n    /* \n     * Only use the newer glXGetFBConfig if there's an explicit need for it\n     * because it is buggy on many systems:\n     *  (1) NVidia 96.43.07 on Linux, single-buffered windows don't work\n     *  (2) Mesa 6.5.X and earlier fail\n     */\n    if (chooseFBConfig) {\n        /* have new glXGetFBConfig! */\n        int     count;\n        GLXFBConfig *cfgs;\n\n        attribs[na++] = GLX_RENDER_TYPE;\n        if (togl->RgbaFlag) {\n            /* RGB[A] mode */\n            attribs[na++] = GLX_RGBA_BIT;\n            attribs[na++] = GLX_RED_SIZE;\n            attribs[na++] = togl->RgbaRed;\n            attribs[na++] = GLX_GREEN_SIZE;\n            attribs[na++] = togl->RgbaGreen;\n            attribs[na++] = GLX_BLUE_SIZE;\n            attribs[na++] = togl->RgbaBlue;\n            if (togl->AlphaFlag) {\n                attribs[na++] = GLX_ALPHA_SIZE;\n                attribs[na++] = togl->AlphaSize;\n            }\n        } else {\n            /* Color index mode */\n            attribs[na++] = GLX_COLOR_INDEX_BIT;\n            attribs[na++] = GLX_BUFFER_SIZE;\n            attribs[na++] = 1;\n        }\n        if (togl->DepthFlag) {\n            attribs[na++] = GLX_DEPTH_SIZE;\n            attribs[na++] = togl->DepthSize;\n        }\n        if (togl->DoubleFlag) {\n            attribs[na++] = GLX_DOUBLEBUFFER;\n            attribs[na++] = True;\n        }\n        if (togl->StencilFlag) {\n            attribs[na++] = GLX_STENCIL_SIZE;\n            attribs[na++] = togl->StencilSize;\n        }\n        if (togl->AccumFlag) {\n            attribs[na++] = GLX_ACCUM_RED_SIZE;\n            attribs[na++] = togl->AccumRed;\n            attribs[na++] = GLX_ACCUM_GREEN_SIZE;\n            attribs[na++] = togl->AccumGreen;\n            attribs[na++] = GLX_ACCUM_BLUE_SIZE;\n            attribs[na++] = togl->AccumBlue;\n            if (togl->AlphaFlag) {\n                attribs[na++] = GLX_ACCUM_ALPHA_SIZE;\n                attribs[na++] = togl->AccumAlpha;\n            }\n        }\n        if (togl->Stereo == TOGL_STEREO_NATIVE) {\n            attribs[na++] = GLX_STEREO;\n            attribs[na++] = True;\n        }\n        if (togl->MultisampleFlag) {\n            attribs[na++] = GLX_SAMPLE_BUFFERS_ARB;\n            attribs[na++] = 1;\n            attribs[na++] = GLX_SAMPLES_ARB;\n            attribs[na++] = 2;\n        }\n        if (togl->PbufferFlag) {\n            attribs[na++] = GLX_DRAWABLE_TYPE;\n            attribs[na++] = GLX_WINDOW_BIT | GLX_PBUFFER_BIT;\n        }\n        if (togl->AuxNumber != 0) {\n            attribs[na++] = GLX_AUX_BUFFERS;\n            attribs[na++] = togl->AuxNumber;\n        }\n        attribs[na++] = None;\n\n        cfgs = chooseFBConfig(togl->display, scrnum, attribs, &count);\n        if (cfgs == NULL || count == 0) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"couldn't choose pixel format\", TCL_STATIC);\n            return NULL;\n        }\n        /* \n         * Pick best format\n         */\n        info = (FBInfo *) malloc(count * sizeof (FBInfo));\n        for (i = 0; i != count; ++i) {\n            info[i].visInfo = getVisualFromFBConfig(togl->display, cfgs[i]);\n            info[i].fbcfg = cfgs[i];\n            getFBConfigAttrib(togl->display, cfgs[i], GLX_CONFIG_CAVEAT,\n                    &info[i].acceleration);\n            getFBConfigAttrib(togl->display, cfgs[i], GLX_BUFFER_SIZE,\n                    &info[i].colors);\n            getFBConfigAttrib(togl->display, cfgs[i], GLX_DEPTH_SIZE,\n                    &info[i].depth);\n            getFBConfigAttrib(togl->display, cfgs[i], GLX_SAMPLES,\n                    &info[i].samples);\n            /* revise attributes so larger is better */\n            info[i].acceleration = -(info[i].acceleration - GLX_NONE);\n            if (!togl->DepthFlag)\n                info[i].depth = -info[i].depth;\n            if (!togl->MultisampleFlag)\n                info[i].samples = -info[i].samples;\n        }\n        qsort(info, count, sizeof info[0], FBInfoCmp);\n\n        togl->fbcfg = info[0].fbcfg;\n        visinfo = info[0].visInfo;\n        for (i = 1; i != count; ++i)\n            XFree(info[i].visInfo);\n        free(info);\n        XFree(cfgs);\n        return visinfo;\n    }\n\n    /* use original glXChooseVisual */\n\n    attribs[na++] = GLX_USE_GL;\n    if (togl->RgbaFlag) {\n        /* RGB[A] mode */\n        attribs[na++] = GLX_RGBA;\n        attribs[na++] = GLX_RED_SIZE;\n        attribs[na++] = togl->RgbaRed;\n        attribs[na++] = GLX_GREEN_SIZE;\n        attribs[na++] = togl->RgbaGreen;\n        attribs[na++] = GLX_BLUE_SIZE;\n        attribs[na++] = togl->RgbaBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = GLX_ALPHA_SIZE;\n            attribs[na++] = togl->AlphaSize;\n        }\n    } else {\n        /* Color index mode */\n        attribs[na++] = GLX_BUFFER_SIZE;\n        attribs[na++] = 1;\n    }\n    if (togl->DepthFlag) {\n        attribs[na++] = GLX_DEPTH_SIZE;\n        attribs[na++] = togl->DepthSize;\n    }\n    if (togl->DoubleFlag) {\n        attribs[na++] = GLX_DOUBLEBUFFER;\n    }\n    if (togl->StencilFlag) {\n        attribs[na++] = GLX_STENCIL_SIZE;\n        attribs[na++] = togl->StencilSize;\n    }\n    if (togl->AccumFlag) {\n        attribs[na++] = GLX_ACCUM_RED_SIZE;\n        attribs[na++] = togl->AccumRed;\n        attribs[na++] = GLX_ACCUM_GREEN_SIZE;\n        attribs[na++] = togl->AccumGreen;\n        attribs[na++] = GLX_ACCUM_BLUE_SIZE;\n        attribs[na++] = togl->AccumBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = GLX_ACCUM_ALPHA_SIZE;\n            attribs[na++] = togl->AccumAlpha;\n        }\n    }\n    if (togl->Stereo == TOGL_STEREO_NATIVE) {\n        attribs[na++] = GLX_STEREO;\n    }\n    if (togl->AuxNumber != 0) {\n        attribs[na++] = GLX_AUX_BUFFERS;\n        attribs[na++] = togl->AuxNumber;\n    }\n    attribs[na++] = None;\n\n    visinfo = glXChooseVisual(togl->display, scrnum, attribs);\n    if (visinfo == NULL) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"couldn't choose pixel format\", TCL_STATIC);\n        return NULL;\n    }\n    return visinfo;\n}\n\nstatic int\ntogl_describePixelFormat(Togl *togl)\n{\n    int     tmp = 0;\n\n    /* fill in flags normally passed in that affect behavior */\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_RGBA,\n            &togl->RgbaFlag);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_DOUBLEBUFFER,\n            &togl->DoubleFlag);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_DEPTH_SIZE, &tmp);\n    togl->DepthFlag = (tmp != 0);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_ACCUM_RED_SIZE, &tmp);\n    togl->AccumFlag = (tmp != 0);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_ALPHA_SIZE, &tmp);\n    togl->AlphaFlag = (tmp != 0);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_STENCIL_SIZE, &tmp);\n    togl->StencilFlag = (tmp != 0);\n    (void) glXGetConfig(togl->display, togl->VisInfo, GLX_STEREO, &tmp);\n    togl->Stereo = tmp ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE;\n    if (hasMultisampling) {\n        (void) glXGetConfig(togl->display, togl->VisInfo, GLX_SAMPLES, &tmp);\n        togl->MultisampleFlag = (tmp != 0);\n    }\n    return True;\n}\n\nstatic Tcl_ThreadDataKey togl_XError;\nstruct ErrorData\n{\n    int     error_code;\n    XErrorHandler prevHandler;\n};\ntypedef struct ErrorData ErrorData;\n\nstatic int\ntogl_HandleXError(Display *dpy, XErrorEvent * event)\n{\n    ErrorData *data = Tcl_GetThreadData(&togl_XError, (int) sizeof (ErrorData));\n\n    data->error_code = event->error_code;\n    return 0;\n}\n\nstatic void\ntogl_SetupXErrorHandler()\n{\n    ErrorData *data = Tcl_GetThreadData(&togl_XError, (int) sizeof (ErrorData));\n\n    data->error_code = Success; /* 0 */\n    data->prevHandler = XSetErrorHandler(togl_HandleXError);\n}\n\nstatic int\ntogl_CheckForXError(const Togl *togl)\n{\n    ErrorData *data = Tcl_GetThreadData(&togl_XError, (int) sizeof (ErrorData));\n\n    XSync(togl->display, False);\n    (void) XSetErrorHandler(data->prevHandler);\n    return data->error_code;\n}\n\nstatic GLXPbuffer\ntogl_createPbuffer(Togl *togl)\n{\n    int     attribs[32];\n    int     na = 0;\n    GLXPbuffer pbuf;\n\n    togl_SetupXErrorHandler();\n    if (togl->LargestPbufferFlag) {\n        attribs[na++] = GLX_LARGEST_PBUFFER;\n        attribs[na++] = True;\n    }\n    attribs[na++] = GLX_PRESERVED_CONTENTS;\n    attribs[na++] = True;\n    if (createPbuffer) {\n        attribs[na++] = GLX_PBUFFER_WIDTH;\n        attribs[na++] = togl->Width;\n        attribs[na++] = GLX_PBUFFER_HEIGHT;\n        attribs[na++] = togl->Width;\n        attribs[na++] = None;\n        pbuf = createPbuffer(togl->display, togl->fbcfg, attribs);\n    } else {\n        attribs[na++] = None;\n        pbuf = createPbufferSGIX(togl->display, togl->fbcfg, togl->Width,\n                togl->Height, attribs);\n    }\n    if (togl_CheckForXError(togl) || pbuf == None) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"unable to allocate pbuffer\", TCL_STATIC);\n        return None;\n    }\n    if (pbuf && togl->LargestPbufferFlag) {\n        int     tmp;\n\n        queryPbuffer(togl->display, pbuf, GLX_WIDTH, &tmp);\n        if (tmp != 0)\n            togl->Width = tmp;\n        queryPbuffer(togl->display, pbuf, GLX_HEIGHT, &tmp);\n        if (tmp != 0)\n            togl->Height = tmp;\n    }\n    return pbuf;\n}\n\nstatic void\ntogl_destroyPbuffer(Togl *togl)\n{\n    destroyPbuffer(togl->display, togl->pbuf);\n}\n"
  },
  {
    "path": "ng/Togl2.1/toglNSOpenGL.c",
    "content": "/* $Id: toglNSOpenGL.c,v 1.7 2009/10/22 00:06:41 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\nstatic NSOpenGLPixelFormat *\ntogl_pixelFormat(Togl *togl)\n{\n    NSOpenGLPixelFormatAttribute   attribs[32];\n    int     na = 0;\n    NSOpenGLPixelFormat *pix;\n\n#if 0\n    if (togl->MultisampleFlag && !hasMultisampling) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n        return NULL;\n    }\n#endif\n\n    if (togl->PbufferFlag && !togl->RgbaFlag) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"puffer must be RGB[A]\", TCL_STATIC);\n        return NULL;\n    }\n\n    attribs[na++] = NSOpenGLPFAMinimumPolicy;\n    /* ask for hardware-accelerated onscreen */\n    attribs[na++] = NSOpenGLPFAAccelerated;\n    attribs[na++] = NSOpenGLPFANoRecovery;\n    if (togl->RgbaFlag) {\n        /* RGB[A] mode */\n        attribs[na++] = NSOpenGLPFAColorSize;\n\tattribs[na++] = togl->RgbaRed + togl->RgbaGreen + togl->RgbaBlue;\n\t/* NSOpenGL does not take separate red,green,blue sizes. */\n        if (togl->AlphaFlag) {\n            attribs[na++] = NSOpenGLPFAAlphaSize;\n            attribs[na++] = togl->AlphaSize;\n        }\n    } else {\n        /* Color index mode */\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"Color index mode not supported\", TCL_STATIC);\n        return NULL;\n    }\n    if (togl->DepthFlag) {\n        attribs[na++] = NSOpenGLPFADepthSize;\n        attribs[na++] = togl->DepthSize;\n    }\n    if (togl->DoubleFlag) {\n        attribs[na++] = NSOpenGLPFADoubleBuffer;\n    }\n    if (togl->StencilFlag) {\n        attribs[na++] = NSOpenGLPFAStencilSize;\n        attribs[na++] = togl->StencilSize;\n    }\n    if (togl->AccumFlag) {\n        attribs[na++] = NSOpenGLPFAAccumSize;\n        attribs[na++] = togl->AccumRed + togl->AccumGreen + togl->AccumBlue + (togl->AlphaFlag ? togl->AccumAlpha : 0);\n    }\n    if (togl->MultisampleFlag) {\n        attribs[na++] = NSOpenGLPFAMultisample;\n        attribs[na++] = NSOpenGLPFASampleBuffers;\n        attribs[na++] = 1;\n        attribs[na++] = NSOpenGLPFASamples;\n        attribs[na++] = 2;\n    }\n    if (togl->AuxNumber != 0) {\n        attribs[na++] = NSOpenGLPFAAuxBuffers;\n        attribs[na++] = togl->AuxNumber;\n    }\n    if (togl->Stereo == TOGL_STEREO_NATIVE) {\n        attribs[na++] = NSOpenGLPFAStereo;\n    }\n    if (togl->FullscreenFlag) {\n        attribs[na++] = NSOpenGLPFAFullScreen;\n    }\n    attribs[na++] = 0;\t/* End of attributes. */\n\n    pix = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];\n    if (pix == nil) {\n        Tcl_SetResult(togl->Interp, TCL_STUPID \"couldn't choose pixel format\",\n                TCL_STATIC);\n        return NULL;\n    }\n    return pix;\n}\n\nstatic int\ntogl_describePixelFormat(Togl *togl)\n{\n    NSOpenGLPixelFormat *pfmt = togl->PixelFormat;\n\n    /* fill in RgbaFlag, DoubleFlag, and Stereo */\n    GLint   has_rgba, has_doublebuf, has_depth, has_accum, has_alpha,\n            has_stencil, has_stereo, has_multisample;\n\n    GLint   vscr = 0;\n    [pfmt getValues:&has_rgba forAttribute:NSOpenGLPFAColorSize forVirtualScreen:vscr];\n    [pfmt getValues:&has_doublebuf forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:vscr];\n    [pfmt getValues:&has_depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:vscr];\n    [pfmt getValues:&has_accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:vscr];\n    [pfmt getValues:&has_alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:vscr];\n    [pfmt getValues:&has_stencil forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:vscr];\n    [pfmt getValues:&has_stereo forAttribute:NSOpenGLPFAStereo forVirtualScreen:vscr];\n    [pfmt getValues:&has_multisample forAttribute:NSOpenGLPFASampleBuffers forVirtualScreen:vscr];\n\n    togl->RgbaFlag = (has_rgba != 0);\n    togl->DoubleFlag = (has_doublebuf != 0);\n    togl->DepthFlag = (has_depth != 0);\n    togl->AccumFlag = (has_accum != 0);\n    togl->AlphaFlag = (has_alpha != 0);\n    togl->StencilFlag = (has_stencil != 0);\n    togl->Stereo = (has_stereo ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE);\n    togl->MultisampleFlag = (has_multisample != 0);\n    return True;\n}\n\n#define isPow2(x) (((x) & ((x) - 1)) == 0)\n\nstatic NSOpenGLPixelBuffer *\ntogl_createPbuffer(Togl *togl)\n{\n    GLint   min_size[2], max_size[2];\n    Bool    hasPbuffer;\n    const char *extensions;\n    GLint   target;\n    GLint   virtualScreen;\n    NSOpenGLPixelBuffer *pbuf;\n\n    extensions = (const char *) glGetString(GL_EXTENSIONS);\n    hasPbuffer = (strstr(extensions, \"GL_APPLE_pixel_buffer\") != NULL);\n    if (!hasPbuffer) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"pbuffers are not supported\", TCL_STATIC);\n        return NULL;\n    }\n    glGetIntegerv(GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE, min_size);\n    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_size);\n    virtualScreen = [togl->Ctx currentVirtualScreen];\n    for (;;) {\n        /* make sure we don't exceed the maximum size because if we do,\n         * NSOpenGLPixelBuffer allocationmay succeed and later uses of\n\t * the pbuffer fail\n\t */\n        if (togl->Width < min_size[0])\n            togl->Width = min_size[0];\n        else if (togl->Width > max_size[0]) {\n            if (togl->LargestPbufferFlag)\n                togl->Width = max_size[0];\n            else {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"pbuffer too large\", TCL_STATIC);\n                return NULL;\n            }\n        }\n        if (togl->Height < min_size[1])\n            togl->Height = min_size[1];\n        else if (togl->Height > max_size[1]) {\n            if (togl->LargestPbufferFlag)\n                togl->Height = max_size[1];\n            else {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"pbuffer too large\", TCL_STATIC);\n                return NULL;\n            }\n        }\n\n        if (isPow2(togl->Width) && isPow2(togl->Height))\n            target = GL_TEXTURE_2D;\n        else\n            target = GL_TEXTURE_RECTANGLE_ARB;\n\n\tpbuf = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target\n\t\ttextureInternalFormat:(togl->AlphaFlag ? GL_RGBA : GL_RGB)\n\t\ttextureMaxMipMapLevel:0\n\t\tpixelsWide:togl->Width pixelsHigh:togl->Height];\n        if (pbuf != nil) {\n            /* setPixelBuffer allocates the framebuffer space */\n\t  [togl->Ctx setPixelBuffer:pbuf cubeMapFace:0 mipMapLevel:0 \n\t   currentVirtualScreen:virtualScreen];\n\t  return pbuf;\n\t}\n        if (!togl->LargestPbufferFlag\n                || togl->Width == min_size[0] || togl->Height == min_size[1]) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"unable to create pbuffer\", TCL_STATIC);\n            return NULL;\n        }\n        /* largest unavailable, try something smaller */\n        togl->Width = togl->Width / 2 + togl->Width % 2;\n        togl->Height = togl->Width / 2 + togl->Height % 2;\n    }\n}\n\nstatic void\ntogl_destroyPbuffer(Togl *togl)\n{\n    [togl->pbuf release];\n}"
  },
  {
    "path": "ng/Togl2.1/toglProcAddr.c",
    "content": "/* $Id */\n\n/* vi:set sw=4: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n\n#include \"togl.h\"\n\n#if defined(TOGL_OSMESA) || defined(TOGL_WGL)\n/* nothing extra to include */\n#elif defined(__APPLE__)\n#  include <mach-o/dyld.h>\n#else\n#  if !defined(TOGL_X11) || !defined(GLX_VERSION_1_4)\n#    include <dlfcn.h>\n#  endif\n#endif\n\nTogl_FuncPtr\nTogl_GetProcAddr(const char *funcname)\n{\n#if defined(TOGL_OSMESA)\n    return (Togl_FuncPtr) OSMesaGetProcAddress(funcname);\n#elif defined(TOGL_WGL)\n    return (Togl_FuncPtr) wglGetProcAddress(funcname);\n#elif defined(__APPLE__)\n    char    buf[256];\n\n    snprintf(buf, sizeof buf - 1, \"_%s\", funcname);\n    buf[sizeof buf - 1] = '\\0';\n    if (NSIsSymbolNameDefined(buf)) {\n        NSSymbol nssym;\n\n        nssym = NSLookupAndBindSymbol(buf);\n        if (nssym)\n            return (Togl_FuncPtr) NSAddressOfSymbol(nssym);\n    }\n    return NULL;\n#else\n#  if defined(TOGL_X11) && defined(GLX_VERSION_1_4)\n    /* Strictly speaking, we can only call glXGetProcAddress if glXQueryVersion \n     * says we're using version 1.4 or later. */\n    return (Togl_FuncPtr) glXGetProcAddress(funcname);\n#  else\n    /* Linux, IRIX, OSF/1, ? */\n    static void *dlHandle = NULL;\n\n    if (dlHandle == NULL)\n        dlHandle = dlopen(NULL, RTLD_LAZY);\n    /* Strictly speaking, the following cast of a data pointer to a function\n     * pointer is not legal in ISO C, but we don't have any choice. */\n    return (Togl_FuncPtr) dlsym(dlHandle, funcname);\n#  endif\n#endif\n}\n"
  },
  {
    "path": "ng/Togl2.1/toglStubInit.c",
    "content": "/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n#include \"togl.h\"\n\nextern const ToglStubs toglStubs;\n\n/* !BEGIN!: Do not edit below this line. */\n\nconst ToglStubs toglStubs = {\n    TCL_STUB_MAGIC,\n    NULL,\n    Togl_Init, /* 0 */\n    Togl_MakeCurrent, /* 1 */\n    Togl_PostRedisplay, /* 2 */\n    Togl_SwapBuffers, /* 3 */\n    Togl_Ident, /* 4 */\n    Togl_Width, /* 5 */\n    Togl_Height, /* 6 */\n    Togl_Interp, /* 7 */\n    Togl_TkWin, /* 8 */\n    Togl_CommandName, /* 9 */\n    Togl_AllocColor, /* 10 */\n    Togl_FreeColor, /* 11 */\n    Togl_SetColor, /* 12 */\n    Togl_LoadBitmapFont, /* 13 */\n    Togl_UnloadBitmapFont, /* 14 */\n    Togl_UseLayer, /* 15 */\n    Togl_ShowOverlay, /* 16 */\n    Togl_HideOverlay, /* 17 */\n    Togl_PostOverlayRedisplay, /* 18 */\n    Togl_ExistsOverlay, /* 19 */\n    Togl_GetOverlayTransparentValue, /* 20 */\n    Togl_IsMappedOverlay, /* 21 */\n    Togl_AllocColorOverlay, /* 22 */\n    Togl_FreeColorOverlay, /* 23 */\n    Togl_GetClientData, /* 24 */\n    Togl_SetClientData, /* 25 */\n    Togl_DrawBuffer, /* 26 */\n    Togl_Clear, /* 27 */\n    Togl_Frustum, /* 28 */\n    Togl_GetToglFromObj, /* 29 */\n    Togl_TakePhoto, /* 30 */\n    Togl_GetProcAddr, /* 31 */\n    Togl_GetToglFromName, /* 32 */\n    Togl_SwapInterval, /* 33 */\n    Togl_Ortho, /* 34 */\n    Togl_NumEyes, /* 35 */\n    Togl_ContextTag, /* 36 */\n    Togl_UpdatePending, /* 37 */\n    Togl_WriteObj, /* 38 */\n    Togl_WriteChars, /* 39 */\n    Togl_HasRGBA, /* 40 */\n    Togl_IsDoubleBuffered, /* 41 */\n    Togl_HasDepthBuffer, /* 42 */\n    Togl_HasAccumulationBuffer, /* 43 */\n    Togl_HasDestinationAlpha, /* 44 */\n    Togl_HasStencilBuffer, /* 45 */\n    Togl_StereoMode, /* 46 */\n    Togl_HasMultisample, /* 47 */\n    Togl_CopyContext, /* 48 */\n};\n\n/* !END!: Do not edit above this line. */\n"
  },
  {
    "path": "ng/Togl2.1/toglStubLib.c",
    "content": "#ifndef   USE_TCL_STUBS\n#  define USE_TCL_STUBS\n#endif\n#undef USE_TCL_STUB_PROCS\n#ifndef   USE_TK_STUBS\n#  define USE_TK_STUBS\n#endif\n#undef USE_TK_STUB_PROCS\n\n#include \"togl.h\"\n\nconst ToglStubs *toglStubsPtr;\n\n/* \n ** Ensure that Togl_InitStubs is built as an exported symbol.  The other stub\n ** functions should be built as non-exported symbols.\n */\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n\n/* \n * Togl_InitStubs --\n *\n *    Checks that the correct version of Togl is loaded and that it\n *    supports stubs.  It then initialises the stub table pointers.\n *\n * Results:\n *     The actual version of Togl that satisfies the request, or\n *     NULL to indicate that an error occurred.\n *\n * Side effects:\n *     sets the stub table pointer.\n *\n */\n\n#ifdef Togl_InitStubs\n#  undef Togl_InitStubs\n#endif\n\nconst char *\nTogl_InitStubs(Tcl_Interp *interp, const char *version, int exact)\n{\n    const char *actualVersion;\n\n    actualVersion = Tcl_PkgRequireEx(interp, \"Togl\", version, exact,\n            (ClientData *) &toglStubsPtr);\n    if (!actualVersion) {\n        return NULL;\n    }\n\n    if (!toglStubsPtr) {\n        Tcl_SetResult(interp,\n                \"This implementation of Togl does not support stubs\",\n                TCL_STATIC);\n        return NULL;\n    }\n\n    return actualVersion;\n}\n"
  },
  {
    "path": "ng/Togl2.1/toglWGL.c",
    "content": "/* $Id: toglWGL.c,v 1.8 2009/12/23 21:50:49 gregcouch Exp $ */\n\n/* vi:set sw=4 expandtab: */\n\n/* \n * Togl - a Tk OpenGL widget\n *\n * Copyright (C) 1996-2002  Brian Paul and Ben Bederson\n * Copyright (C) 2005-2009  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\n/* TODO: fullscreen support */\n\n#include <windows.h>\n#include <GL/gl.h>\n#include <wingdi.h>\n#include <tk.h>\n#include <tkPlatDecls.h>\n#include <GL/wglext.h>\n\n#ifndef PFD_SUPPORT_COMPOSITION\n/* for Vista -- not needed because we don't use PFD_SUPPORT_GDI/BITMAP */\n#  define PFD_SUPPORT_COMPOSITION 0x00008000\n#endif\n\n/* TODO: move these statics into global structure */\nstatic PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionsString = NULL;\nstatic PFNWGLCHOOSEPIXELFORMATARBPROC choosePixelFormat;\nstatic PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribiv;\nstatic PFNWGLCREATEPBUFFERARBPROC createPbuffer = NULL;\nstatic PFNWGLDESTROYPBUFFERARBPROC destroyPbuffer = NULL;\nstatic PFNWGLGETPBUFFERDCARBPROC getPbufferDC = NULL;\nstatic PFNWGLRELEASEPBUFFERDCARBPROC releasePbufferDC = NULL;\nstatic PFNWGLQUERYPBUFFERARBPROC queryPbuffer = NULL;\nstatic int hasMultisampling = FALSE;\nstatic int hasPbuffer = FALSE;\nstatic int hasARBPbuffer = FALSE;\n\nstatic HWND\ntoglCreateTestWindow(HWND parent)\n{\n    static char ClassName[] = \"ToglTestWindow\";\n    WNDCLASS wc;\n    HINSTANCE instance = GetModuleHandle(NULL);\n    HWND    wnd;\n    HDC     dc;\n    PIXELFORMATDESCRIPTOR pfd;\n    int     pixelFormat;\n\n    wc.style = CS_OWNDC;\n    wc.lpfnWndProc = DefWindowProc;\n    wc.cbClsExtra = 0;\n    wc.cbWndExtra = 0;\n    wc.hInstance = instance;\n    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);\n    wc.hCursor = LoadCursor(NULL, IDC_ARROW);\n    wc.hbrBackground = NULL;\n    wc.lpszMenuName = NULL;\n    wc.lpszClassName = ClassName;\n    if (!RegisterClass(&wc)) {\n        DWORD   err = GetLastError();\n\n        if (err != ERROR_CLASS_ALREADY_EXISTS) {\n            fprintf(stderr, \"Unable to register Togl Test Window class\\n\");\n            return NULL;\n        }\n    }\n\n    wnd = CreateWindow(ClassName, \"test OpenGL capabilities\",\n            WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,\n            0, 0, 1, 1, parent, NULL, instance, NULL);\n    if (wnd == NULL) {\n        fprintf(stderr, \"Unable to create temporary OpenGL window\\n\");\n        return NULL;\n    }\n    dc = GetDC(wnd);\n\n    memset(&pfd, 0, sizeof pfd);\n    pfd.nSize = sizeof pfd;\n    pfd.nVersion = 1;\n    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;\n    pfd.iPixelType = PFD_TYPE_RGBA;\n    pfd.cColorBits = 3;\n    pfd.iLayerType = PFD_MAIN_PLANE;\n    pixelFormat = ChoosePixelFormat(dc, &pfd);\n    if (pixelFormat == 0) {\n        fprintf(stderr, \"Unable to choose simple pixel format\\n\");\n        ReleaseDC(wnd, dc);\n        return NULL;\n    }\n    if (!SetPixelFormat(dc, pixelFormat, &pfd)) {\n        fprintf(stderr, \"Unable to set simple pixel format\\n\");\n        ReleaseDC(wnd, dc);\n        return NULL;\n    }\n\n    ShowWindow(wnd, SW_HIDE);   // make sure it's hidden\n    ReleaseDC(wnd, dc);\n    return wnd;\n}\n\nstruct FBInfo\n{\n    int     stereo;\n    int     acceleration;\n    int     colors;\n    int     depth;\n    int     samples;\n    int     pixelFormat;\n};\ntypedef struct FBInfo FBInfo;\nstatic int FBAttribs[] = {\n    /* must match order in FBInfo structure */\n    WGL_STEREO_ARB,\n    WGL_ACCELERATION_ARB,\n    WGL_COLOR_BITS_ARB,\n    WGL_DEPTH_BITS_ARB,\n    WGL_SAMPLES_ARB,\n};\n\n#define NUM_FBAttribs (sizeof FBAttribs / sizeof FBAttribs[0])\n\nstatic int\nFBInfoCmp(const void *a, const void *b)\n{\n    /* \n     * 1. stereo is better\n     * 2. full acceleration is better\n     * 3. greater color bits is better\n     * 4. greater depth bits is better\n     * 5. more multisampling is better\n     */\n    const FBInfo *x = (const FBInfo *) a;\n    const FBInfo *y = (const FBInfo *) b;\n\n    if (x->stereo != y->stereo)\n        return y->stereo - x->stereo;\n    if (x->acceleration != y->acceleration)\n        return y->acceleration - x->acceleration;\n    if (x->colors != y->colors)\n        return y->colors - x->colors;\n    if (x->depth != y->depth)\n        return y->depth - x->depth;\n    if (x->samples != y->samples)\n        return y->samples - x->samples;\n    return 0;\n}\n\nstatic int\ntogl_pixelFormat(Togl *togl, HWND hwnd)\n{\n    /* return 0 when pixel format is unavailable. */\n    int     pixelformat = 0;\n    static int loadedOpenGL = FALSE;\n    int     formats[256];\n    UINT    numFormats;\n    FBInfo *info;\n    UINT    i;\n    int     attribs[128];\n    int     na = 0;\n\n    if (!loadedOpenGL) {\n        HWND    test = NULL;\n        HDC     dc;\n        HGLRC   rc;\n\n        if (wglGetCurrentContext() != NULL) {\n            dc = wglGetCurrentDC();\n        } else {\n            /* HWND hwnd = Tk_GetHWND(Tk_WindowId(togl->TkWin)); */\n\n            test = toglCreateTestWindow(hwnd);\n            if (test == NULL) {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"can't create dummy OpenGL window\",\n                        TCL_STATIC);\n                return 0;\n            }\n\n            dc = GetDC(test);\n            rc = wglCreateContext(dc);\n            wglMakeCurrent(dc, rc);\n        }\n        loadedOpenGL = TRUE;\n\n        /* \n         * Now that we have an OpenGL window, we can initialize all\n         * OpenGL information and figure out if multisampling is supported.\n         */\n        getExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)\n                wglGetProcAddress(\"wglGetExtensionsStringARB\");\n        if (getExtensionsString == NULL)\n            getExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)\n                    wglGetProcAddress(\"wglGetExtensionsStringEXT\");\n        if (getExtensionsString) {\n            const char *extensions = getExtensionsString(dc);\n\n            if (strstr(extensions, \"WGL_ARB_multisample\") != NULL\n                    || strstr(extensions, \"WGL_EXT_multisample\") != NULL)\n                hasMultisampling = TRUE;\n\n            if (strstr(extensions, \"WGL_ARB_pixel_format\") != NULL) {\n                choosePixelFormat = (PFNWGLCHOOSEPIXELFORMATARBPROC)\n                        wglGetProcAddress(\"wglChoosePixelFormatARB\");\n                getPixelFormatAttribiv = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)\n                        wglGetProcAddress(\"wglGetPixelFormatAttribivARB\");\n                if (choosePixelFormat == NULL || getPixelFormatAttribiv == NULL) {\n                    choosePixelFormat = NULL;\n                    getPixelFormatAttribiv = NULL;\n                }\n            }\n            if (choosePixelFormat == NULL\n                    && strstr(extensions, \"WGL_EXT_pixel_format\") != NULL) {\n                choosePixelFormat = (PFNWGLCHOOSEPIXELFORMATARBPROC)\n                        wglGetProcAddress(\"wglChoosePixelFormatEXT\");\n                getPixelFormatAttribiv = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)\n                        wglGetProcAddress(\"wglGetPixelFormatAttribivEXT\");\n                if (choosePixelFormat == NULL || getPixelFormatAttribiv == NULL) {\n                    choosePixelFormat = NULL;\n                    getPixelFormatAttribiv = NULL;\n                }\n            }\n            if (createPbuffer == NULL\n                    && strstr(extensions, \"WGL_ARB_pbuffer\") != NULL) {\n                createPbuffer = (PFNWGLCREATEPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglCreatePbufferARB\");\n                destroyPbuffer = (PFNWGLDESTROYPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglDestroyPbufferARB\");\n                getPbufferDC = (PFNWGLGETPBUFFERDCARBPROC)\n                        wglGetProcAddress(\"wglGetPbufferDCARB\");\n                releasePbufferDC = (PFNWGLRELEASEPBUFFERDCARBPROC)\n                        wglGetProcAddress(\"wglReleasePbufferDCARB\");\n                queryPbuffer = (PFNWGLQUERYPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglQueryPbufferARB\");\n                if (createPbuffer == NULL || destroyPbuffer == NULL\n                        || getPbufferDC == NULL || releasePbufferDC == NULL\n                        || queryPbuffer == NULL) {\n                    createPbuffer = NULL;\n                    destroyPbuffer = NULL;\n                    getPbufferDC = NULL;\n                    releasePbufferDC = NULL;\n                    queryPbuffer = NULL;\n                } else {\n                    hasPbuffer = TRUE;\n                    hasARBPbuffer = TRUE;\n                }\n            }\n            if (createPbuffer == NULL\n                    && strstr(extensions, \"WGL_EXT_pbuffer\") != NULL) {\n                createPbuffer = (PFNWGLCREATEPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglCreatePbufferEXT\");\n                destroyPbuffer = (PFNWGLDESTROYPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglDestroyPbufferEXT\");\n                getPbufferDC = (PFNWGLGETPBUFFERDCARBPROC)\n                        wglGetProcAddress(\"wglGetPbufferDCEXT\");\n                releasePbufferDC = (PFNWGLRELEASEPBUFFERDCARBPROC)\n                        wglGetProcAddress(\"wglReleasePbufferDCEXT\");\n                queryPbuffer = (PFNWGLQUERYPBUFFERARBPROC)\n                        wglGetProcAddress(\"wglQueryPbufferEXT\");\n                if (createPbuffer == NULL || destroyPbuffer == NULL\n                        || getPbufferDC == NULL || releasePbufferDC == NULL\n                        || queryPbuffer == NULL) {\n                    createPbuffer = NULL;\n                    destroyPbuffer = NULL;\n                    getPbufferDC = NULL;\n                    releasePbufferDC = NULL;\n                    queryPbuffer = NULL;\n                } else {\n                    hasPbuffer = TRUE;\n                }\n            }\n        }\n\n        /* No need to confirm multisampling is in glGetString(GL_EXTENSIONS)\n         * because OpenGL driver is local */\n\n        if (test != NULL) {\n            /* cleanup by removing temporary OpenGL window */\n            wglMakeCurrent(NULL, NULL);\n            wglDeleteContext(rc);\n            ReleaseDC(test, dc);\n            DestroyWindow(test);\n        }\n    }\n\n    if (togl->MultisampleFlag && !hasMultisampling) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n        return 0;\n    }\n\n    if (togl->PbufferFlag && !hasPbuffer) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"pbuffers are not supported\", TCL_STATIC);\n        return 0;\n    }\n\n    if (choosePixelFormat == NULL) {\n        PIXELFORMATDESCRIPTOR pfd;\n\n        /* Don't have the great wglChoosePixelFormatARB() function, so do it\n         * the old way. */\n        if (togl->MultisampleFlag) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n            return 0;\n        }\n\n        memset(&pfd, 0, sizeof pfd);\n        pfd.nSize = sizeof pfd;\n        pfd.nVersion = 1;\n        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL\n                | PFD_SUPPORT_COMPOSITION;\n        if (togl->DoubleFlag) {\n            pfd.dwFlags |= PFD_DOUBLEBUFFER;\n        }\n        if (togl->Stereo == TOGL_STEREO_NATIVE) {\n            pfd.dwFlags |= PFD_STEREO;\n        }\n        pfd.iPixelType = togl->RgbaFlag ? PFD_TYPE_RGBA : PFD_TYPE_COLORINDEX;\n        pfd.cColorBits = togl->RgbaRed + togl->RgbaGreen + togl->RgbaBlue;\n        /* Alpha bitplanes are not supported in the current generic OpenGL\n         * implementation, but may be supported by specific hardware devices. */\n        pfd.cAlphaBits = togl->AlphaFlag ? togl->AlphaSize : 0;\n        pfd.cAccumBits = togl->AccumFlag ? (togl->AccumRed + togl->AccumGreen +\n                togl->AccumBlue + togl->AccumAlpha) : 0;\n        pfd.cDepthBits = togl->DepthFlag ? togl->DepthSize : 0;\n        pfd.cStencilBits = togl->StencilFlag ? togl->StencilSize : 0;\n        /* Auxiliary buffers are not supported in the current generic OpenGL\n         * implementation, but may be supported by specific hardware devices. */\n        pfd.cAuxBuffers = togl->AuxNumber;\n        pfd.iLayerType = PFD_MAIN_PLANE;\n\n        if ((pixelformat = ChoosePixelFormat(togl->tglGLHdc, &pfd)) == 0) {\n            Tcl_SetResult(togl->Interp,\n                    TCL_STUPID \"couldn't choose pixel format\", TCL_STATIC);\n            return 0;\n        }\n\n        /* double check that we got the stereo format we requested */\n        if (togl->Stereo == TOGL_STEREO_NATIVE) {\n            DescribePixelFormat(togl->tglGLHdc, pixelformat, sizeof (pfd),\n                    &pfd);\n            if ((pfd.dwFlags & PFD_STEREO) == 0) {\n                Tcl_SetResult(togl->Interp,\n                        TCL_STUPID \"couldn't choose stereo pixel format\",\n                        TCL_STATIC);\n                return 0;\n            }\n        }\n        return pixelformat;\n    }\n    // We have the new wglChoosePixelFormat!!\n    if (togl->MultisampleFlag && !hasMultisampling) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"multisampling not supported\", TCL_STATIC);\n        return 0;\n    }\n\n    if (togl->PbufferFlag)\n        attribs[na++] = WGL_DRAW_TO_PBUFFER_ARB;\n    else\n        attribs[na++] = WGL_DRAW_TO_WINDOW_ARB;\n    attribs[na++] = GL_TRUE;\n    attribs[na++] = WGL_SUPPORT_OPENGL_ARB;\n    attribs[na++] = GL_TRUE;\n    attribs[na++] = WGL_PIXEL_TYPE_ARB;\n    if (!togl->RgbaFlag) {\n        attribs[na++] = WGL_TYPE_COLORINDEX_ARB;\n    } else {\n        attribs[na++] = WGL_TYPE_RGBA_ARB;\n        attribs[na++] = WGL_RED_BITS_ARB;\n        attribs[na++] = togl->RgbaRed;\n        attribs[na++] = WGL_GREEN_BITS_ARB;\n        attribs[na++] = togl->RgbaGreen;\n        attribs[na++] = WGL_BLUE_BITS_ARB;\n        attribs[na++] = togl->RgbaBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = WGL_ALPHA_BITS_ARB;\n            attribs[na++] = togl->AlphaSize;\n        }\n    }\n    if (togl->DepthFlag) {\n        attribs[na++] = WGL_DEPTH_BITS_ARB;\n        attribs[na++] = togl->DepthSize;\n    }\n    if (togl->DoubleFlag) {\n        attribs[na++] = WGL_DOUBLE_BUFFER_ARB;\n        attribs[na++] = GL_TRUE;\n    }\n    if (togl->StencilFlag) {\n        attribs[na++] = WGL_STENCIL_BITS_ARB;\n        attribs[na++] = togl->StencilSize;\n    }\n    if (togl->AccumFlag) {\n        attribs[na++] = WGL_ACCUM_RED_BITS_ARB;\n        attribs[na++] = togl->AccumRed;\n        attribs[na++] = WGL_ACCUM_GREEN_BITS_ARB;\n        attribs[na++] = togl->AccumGreen;\n        attribs[na++] = WGL_ACCUM_BLUE_BITS_ARB;\n        attribs[na++] = togl->AccumBlue;\n        if (togl->AlphaFlag) {\n            attribs[na++] = WGL_ACCUM_ALPHA_BITS_ARB;\n            attribs[na++] = togl->AccumAlpha;\n        }\n    }\n    if (togl->Stereo == TOGL_STEREO_NATIVE) {\n        attribs[na++] = WGL_STEREO_ARB;\n        attribs[na++] = GL_TRUE;\n    }\n    if (togl->MultisampleFlag) {\n        attribs[na++] = WGL_SAMPLE_BUFFERS_ARB;\n        attribs[na++] = 1;\n        attribs[na++] = WGL_SAMPLES_ARB;\n        attribs[na++] = 2;\n    }\n    if (togl->AuxNumber) {\n        attribs[na++] = WGL_AUX_BUFFERS_ARB;\n        attribs[na++] = togl->AuxNumber;\n    }\n    attribs[na++] = 0;          // must be last\n\n    if (!choosePixelFormat(togl->tglGLHdc, &attribs[0], NULL, 256, formats,\n                    &numFormats) || numFormats == 0) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"couldn't choose pixel format\", TCL_STATIC);\n        return 0;\n    }\n\n    /* \n     * Pick best format\n     */\n    info = (FBInfo *) malloc(numFormats * sizeof (FBInfo));\n    for (i = 0; i != numFormats; ++i) {\n        info[i].pixelFormat = formats[i];\n        getPixelFormatAttribiv(togl->tglGLHdc, formats[i], 0,\n                NUM_FBAttribs, FBAttribs, &info[i].stereo);\n        /* revise attributes so larger is better */\n        if (!togl->DepthFlag)\n            info[i].depth = -info[i].depth;\n        if (!togl->MultisampleFlag)\n            info[i].samples = -info[i].samples;\n        if (togl->Stereo != TOGL_STEREO_NATIVE)\n            info[i].stereo = -info[i].stereo;\n    }\n    qsort(info, numFormats, sizeof info[0], FBInfoCmp);\n    pixelformat = info[0].pixelFormat;\n    /* double check that we got the stereo format we requested */\n    if (togl->Stereo == TOGL_STEREO_NATIVE && !info[0].stereo) {\n        Tcl_SetResult(togl->Interp,\n                TCL_STUPID \"couldn't choose stereo pixel format\", TCL_STATIC);\n        free(info);\n        return 0;\n    }\n    free(info);\n    return pixelformat;\n}\n\nstatic int\ntogl_describePixelFormat(Togl *togl)\n{\n    if (getPixelFormatAttribiv == NULL) {\n        PIXELFORMATDESCRIPTOR pfd;\n\n        DescribePixelFormat(togl->tglGLHdc, (int) togl->PixelFormat,\n                sizeof (pfd), &pfd);\n        /* fill in flags normally passed in that affect behavior */\n        togl->RgbaFlag = pfd.iPixelType == PFD_TYPE_RGBA;\n        togl->DoubleFlag = (pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;\n        togl->DepthFlag = (pfd.cDepthBits != 0);\n        togl->AccumFlag = (pfd.cAccumBits != 0);\n        togl->AlphaFlag = (pfd.cAlphaBits != 0);\n        togl->StencilFlag = (pfd.cStencilBits != 0);\n        if ((pfd.dwFlags & PFD_STEREO) != 0)\n            togl->Stereo = TOGL_STEREO_NATIVE;\n        else\n            togl->Stereo = TOGL_STEREO_NONE;\n    } else {\n        static int attribs[] = {\n            WGL_PIXEL_TYPE_ARB,\n            WGL_DOUBLE_BUFFER_ARB,\n            WGL_DEPTH_BITS_ARB,\n            WGL_ACCUM_RED_BITS_ARB,\n            WGL_ALPHA_BITS_ARB,\n            WGL_STENCIL_BITS_ARB,\n            WGL_STEREO_ARB,\n            WGL_SAMPLES_ARB\n        };\n#define NUM_ATTRIBS (sizeof attribs / sizeof attribs[0])\n        int     info[NUM_ATTRIBS];\n\n        getPixelFormatAttribiv(togl->tglGLHdc, (int) togl->PixelFormat, 0,\n                NUM_ATTRIBS, attribs, info);\n#undef NUM_ATTRIBS\n        togl->RgbaFlag = info[0];\n        togl->DoubleFlag = info[1];\n        togl->DepthFlag = (info[2] != 0);\n        togl->AccumFlag = (info[3] != 0);\n        togl->AlphaFlag = (info[4] != 0);\n        togl->StencilFlag = (info[5] != 0);\n        togl->Stereo = info[6] ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE;\n        togl->MultisampleFlag = (info[7] != 0);\n    }\n    return True;\n}\n\nstatic HPBUFFERARB\ntogl_createPbuffer(Togl *togl)\n{\n    int     attribs[32];\n    int     na = 0;\n    HPBUFFERARB pbuf;\n\n    if (togl->LargestPbufferFlag) {\n        attribs[na++] = WGL_PBUFFER_LARGEST_ARB;\n        attribs[na++] = 1;\n    }\n    attribs[na] = 0;\n    pbuf = createPbuffer(togl->tglGLHdc, (int) togl->PixelFormat, togl->Width,\n            togl->Height, attribs);\n    if (pbuf && togl->LargestPbufferFlag) {\n        queryPbuffer(pbuf, WGL_PBUFFER_WIDTH_ARB, &togl->Width);\n        queryPbuffer(pbuf, WGL_PBUFFER_HEIGHT_ARB, &togl->Height);\n    }\n    return pbuf;\n}\n\nstatic void\ntogl_destroyPbuffer(Togl *togl)\n{\n    destroyPbuffer(togl->pbuf);\n}\n\n#if 0\n// From nvidia.com\n\nMultisampling requires WGL_ARB_extension_string and WGL_ARB_pixel_format\nwglGetProcAddress(\"wglGetExtensionsStringARB\")\n// From msdn.microsoft.com, various ways to enumerate PixelFormats\n        void    CPixForm::OnClickedLastPfd()\n{\n    COpenGL gl;\n    PIXELFORMATDESCRIPTOR pfd;\n\n    // \n    // Get the hwnd of the view window.\n    // \n    HWND    hwndview = GetViewHwnd();\n\n    // \n    // Get a DC associated with the view window.\n    // \n    HDC     dc =::GetDC(hwndview);\n    int     nID = (m_nNextID > 1) ? m_nNextID-- : 1;\n\n    // \n    // Get a description of the pixel format. If it is valid, then go and \n    // update the controls in the dialog box, otherwise do nothing.\n    // \n    if (gl.DescribePixelFormat(dc, nID, sizeof (PIXELFORMATDESCRIPTOR), &pfd))\n        UpdateDlg(&pfd);\n    // \n    // Release the DC.\n    // \n    ::ReleaseDC(hwndview, dc);\n}\n\n----------------------\n        // local variables \nint     iMax;\nPIXELFORMATDESCRIPTOR pfd;\nint     iPixelFormat;\n\n// initialize a pixel format index variable \niPixelFormat = 1;\n\n// keep obtaining and examining pixel format data... \ndo {\n    // try to obtain some pixel format data \n    iMax = DescribePixelFormat(dc, iPixelFormat, sizeof (pfd), &pfd);\n\n    // if there was some problem with that...  \n    if (iMax == 0)\n        // return indicating failure \n        return (FALSE);\n\n    // we have successfully obtained pixel format data \n\n    // let's examine the pixel format data... \n    myPixelFormatExaminer(&pfd);\n}\n// ...until we've looked at all the device context's pixel formats \nwhile (++iPixelFormat <= iMax);\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/togl_ws.h.in",
    "content": "#ifndef TOGL_WS_H\n# define TOGL_WS_H\n\n/* define windowing system togl is compiled with */\n# define @TOGL_WINDOWINGSYSTEM@\n\n#endif\n"
  },
  {
    "path": "ng/Togl2.1/toglpy.h",
    "content": "/* \n * getToglFromWidget:\n *\n * Given a Python widget, get the corresponding Togl pointer.  <Python.h>\n * and <togl.h> should be included before this.  If included into a C file,\n * there should be a static keyword just before the include.\n * \n * There should be one copy of getToglFromWidget per-shared library so that\n * the library's Tcl/Tk/Togl stub pointers are properly initialized.\n *\n * Copyright (C) 2006  Greg Couch\n * See the LICENSE file for copyright details.\n */\n\nTogl   *\ngetToglFromWidget(PyObject *widget)\n{\n    PyObject *cmdNameObj, *tk, *interpAddr;\n    const char *cmdName;\n    Tcl_Interp *interp;\n    Togl   *curTogl;\n\n#ifdef USE_TOGL_STUBS\n    static int didOnce = 0;\n#endif\n\n    /* Python: cmdName = widget._w */\n    /* Python: interpAddr = widget.tk.interpaddr() */\n    cmdNameObj = PyObject_GetAttrString(widget, \"_w\");\n    tk = PyObject_GetAttrString(widget, \"tk\");\n    if (cmdNameObj == NULL || !PyString_Check(cmdNameObj) || tk == NULL) {\n        Py_XDECREF(cmdNameObj);\n        Py_XDECREF(tk);\n#ifdef __cplusplus\n        throw   std::invalid_argument(\"not a Tk widget\");\n#else\n        return NULL;\n#endif\n    }\n\n    interpAddr = PyEval_CallMethod(tk, \"interpaddr\", \"()\");\n    if (interpAddr == NULL || !PyInt_Check(interpAddr)) {\n        Py_DECREF(cmdNameObj);\n        Py_DECREF(tk);\n        Py_XDECREF(interpAddr);\n#ifdef __cplusplus\n        throw   std::invalid_argument(\"not a Tk widget\");\n#else\n        return NULL;\n#endif\n    }\n\n    cmdName = PyString_AsString(cmdNameObj);\n    interp = (Tcl_Interp *) PyInt_AsLong(interpAddr);\n\n#ifdef USE_TOGL_STUBS\n    if (!didOnce) {\n        /* make sure stubs are initialized before calling a Togl function. */\n        if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL\n                || Tk_InitStubs(interp, TK_VERSION, 0) == NULL\n                || Togl_InitStubs(interp, TOGL_VERSION, 0) == NULL)\n#  ifdef __cplusplus\n            throw   std::runtime_error(\"unable to initialize Togl\");\n#  else\n            return NULL;\n#  endif\n        didOnce = 1;\n    }\n#endif\n\n    if (Togl_GetToglFromName(interp, cmdName, &curTogl) != TCL_OK)\n        curTogl = NULL;\n    Py_DECREF(cmdNameObj);\n    Py_DECREF(tk);\n    Py_DECREF(interpAddr);\n#ifdef __cplusplus\n    if (curTogl == NULL)\n        throw   std::invalid_argument(\"not a Togl widget\");\n#endif\n    return curTogl;\n}\n"
  },
  {
    "path": "ng/acisgeom.tcl",
    "content": "if { [Ng_ACISCommand isACISavailable] == \"yes\" } {\n    .ngmenu.geometry add command -label \"ACIS Topology Explorer...\" \\\n        -command { acisdialog; }\n\n    .ngmenu.geometry add command -label \"ACIS combine all\" \\\n        -command { Ng_ACISCommand combineall }\n    .ngmenu.geometry add command -label \"ACIS Create CT\" \\\n        -command { Ng_ACISCommand createct }\n}\n\n\n"
  },
  {
    "path": "ng/csgeom.tcl",
    "content": ".ngmenu.geometry add command -label \"Scan CSG Geometry\" -command { Ng_ParseGeometry }\n.ngmenu.geometry add command -label \"CSG Options...\" -command geometryoptionsdialog\n\n# only intern version !\n# .ngmenu.geometry add separator\n# .ngmenu.geometry add command -label \"New Primitive\"  \\\n#     -command newprimitivedialog -accelerator \"<n><p>\"\n# .ngmenu.geometry add command -label \"Edit Primitive\" \\\n#     -command editprimitivedialog -accelerator \"<e><p>\"\n# .ngmenu.geometry add command -label \"Edit Solid\" \\\n#     -command newsoliddialog -accelerator \"<e><s>\"\n# .ngmenu.geometry add command -label \"Choose Top Level \" \\\n#     -command topleveldialog \n# .ngmenu.geometry add command -label \"Identify\" \\\n#     -command identifydialog \n.ngmenu.geometry add command -label \"CSG Properties...\" \\\n    -command topleveldialog2 \n\n\n\n\n\n\n\n\n\n\n\nproc geometryoptionsdialog { } {\n\n\n    set w .geometry_dlg\n    \n    if {[winfo exists .geometry_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\n\ttoplevel $w\n\t\n\tglobal geooptions\n\t\n\tNg_GeometryOptions get\n\n\tcheckbutton $w.drawcsg -text \"Draw Geometry\" \\\n\t-variable geooptions.drawcsg \n\tpack $w.drawcsg\n\n\tframe $w.fac\n\tpack $w.fac -pady 5\n\tttk::label $w.fac.lab -text \"Facets:\";\n\tentry $w.fac.ent -width 8 -relief sunken \\\n\t    -textvariable geooptions.facets\n\tpack $w.fac.lab $w.fac.ent  -side left\n\t\n \n\tframe $w.det\n\tpack $w.det -pady 5\n\tttk::label $w.det.lab -text \"Detail:\";\n\tentry $w.det.ent -width 8 -relief sunken \\\n\t    -textvariable geooptions.detail\n\tpack $w.det.lab $w.det.ent  -side left\n\t\n\tframe $w.cox\n\tpack $w.cox -pady 5\n\tttk::label $w.cox.lab -text \"min/max x:\";\n\tentry $w.cox.ent1 -width 8 -relief sunken \\\n\t    -textvariable geooptions.minx\n\tentry $w.cox.ent2 -width 8 -relief sunken \\\n\t    -textvariable geooptions.maxx\n\tpack $w.cox.lab $w.cox.ent1 \\\n\t    $w.cox.ent2  -side left\n\t\n\tframe $w.coy\n\tpack $w.coy -pady 5\n\tttk::label $w.coy.lab -text \"min/max y:\";\n\tentry $w.coy.ent1 -width 8 -relief sunken \\\n\t    -textvariable geooptions.miny\n\tentry $w.coy.ent2 -width 8 -relief sunken \\\n\t    -textvariable geooptions.maxy\n\tpack $w.coy.lab $w.coy.ent1 \\\n\t    $w.coy.ent2  -side left\n\t\n\tframe $w.coz\n\tpack $w.coz -pady 5\n\tttk::label $w.coz.lab -text \"min/max z:\";\n\tentry $w.coz.ent1 -width 8 -relief sunken \\\n\t    -textvariable geooptions.minz\n\tentry $w.coz.ent2 -width 8 -relief sunken \\\n\t    -textvariable geooptions.maxz\n\tpack $w.coz.lab $w.coz.ent1 \\\n\t    $w.coz.ent2  -side left\n\t\n\n\n# \ttixButtonBox $w.bbox -orientation horizontal\n# \t$w.bbox add ok    -text Apply  -underline 0 -width 5 \\\n# \t    -command { Ng_GeometryOptions set }\n\t\n# \t$w.bbox add close -text Done   -underline 0 -width 5 \\\n# \t    -command { \n# \t\tNg_GeometryOptions set\n# \t\tdestroy .geometry_dlg\n# \t    }\n# \tpack $w.bbox -side bottom -fill x\n\t\n\n \tframe $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n\n \tttk::button $w.bu.app -text \"Apply\" -command {\n \t    Ng_GeometryOptions set\n \t}\n \tttk::button $w.bu.ok -text \"Done\" -command {\n \t    Ng_GeometryOptions set\n \t    destroy .geometry_dlg\n \t}\n \tpack  $w.bu.app $w.bu.ok -side left -expand yes\n    \n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Geometry options\"\n\tfocus $w\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#\n#\n#   Edit primitive\n#\n#\nproc editprimitivedialog2 { name } {\n\n    global w classname\n\n    set w .ep_dlg\n    toplevel .$w\n\n    Ng_GetPrimitiveData $name classname valuelist\n        \n    \n    ttk::label $w.lab1 -text \"Primitive Name:  $name\";\n    ttk::label $w.lab2 -text \"Primitive Class: $classname\";\n    pack $w.lab1 $w.lab2 -fill x -pady 1m -padx 5m \n    \n    frame $w.specific -relief groove\n\n    global spec\n    set spec(sphere) { cx cy cz rad }\n    set spec(cylinder) { ax ay az bx by bz rad }\n    set spec(plane) { px py pz nx ny nz }\n    set spec(cone) { ax ay az bx by bz ra rb }\n    set spec(brick) { p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z } \n   \n    set cnt 0\n    foreach field $spec($classname) {\n\n\tframe $w.specific.f$cnt \n\tpack $w.specific.f$cnt -side top -anchor ne\n\n\tttk::label $w.specific.f$cnt.lab -text \"$field\"\n\tentry $w.specific.f$cnt.ent -textvariable dataval($cnt) \\\n\t    -width 6 -relief sunken\n\tpack $w.specific.f$cnt.ent $w.specific.f$cnt.lab -side right\n\t$w.specific.f$cnt.ent delete 0 end\n\t$w.specific.f$cnt.ent insert 0 [lindex $valuelist $cnt]\n\tset cnt [expr $cnt + 1]\n    }\n    pack $w.specific\n\n\n    ttk::button $w.cancel -text \"cancel\" -command {\n\tdestroy $w \n    }\n\n    ttk::button $w.ok -text \"ok\" -command {\n\n\tset valuelist \"\"\n\tset cnt 0\n\tforeach field $spec($classname) {\n\t    lappend valuelist $dataval($cnt)\n\t    set cnt [expr $cnt + 1]\n\t}\n\tNg_SetPrimitiveData $name $valuelist\n\tdestroy $w\n    }\n    pack  $w.cancel $w.ok -side left -expand yes\n\n    bind $w <Return> { $w.ok  invoke}\n    bind $w <Escape> { $w.cancel  invoke}\n    \n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\n#    grab $w\n    focus $w.specific.f0.ent\n}\n\n\n\n#\n#\n#      Select primitive to edit\n#\n#\n\nproc editprimitivedialog { } {\n    global w\n\n    set w .ep_dlg\n    toplevel $w\n\n    frame $w.frame -borderwidth 5m\n    pack $w.frame -side top -expand yes -fill y\n\n    listbox $w.frame.list -yscroll \"$w.frame.scroll set\" -setgrid 1 -height 12\n    scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\n    pack $w.frame.scroll -side right -fill y\n    pack $w.frame.list -side left -expand 1 -fill both\n    \n\n    Ng_GetPrimitiveList primlist\n    foreach el $primlist {\n\t$w.frame.list insert end $el }\n\n    ttk::button $w.cancel -text \"cancel\" -command { destroy $w }\n    ttk::button $w.ok -text \"ok\" -command {\n\tset name [.ep_dlg.frame.list get active]\n\tputs \"name=($name)\"\n\tdestroy $w\n\tif { $name != \"\" } { editprimitivedialog2 $name }\n    }\n    \n    bind $w <Escape> { $w.cancel invoke }\n    bind $w <Return> { $w.ok invoke }\n    \n\n    pack  $w.cancel $w.ok -side left -expand yes\n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\n#    grab $w\n    focus $w.frame.list\n}\n\n\n\n#\n#\n#         Create new primitive\n#\n#\nproc newprimitivedialog { } {\n\n    global w name\n\n    set w .ap_dlg\n    \n    toplevel $w\n\n    set name \"\"\n    frame $w.f1\n    pack $w.f1 -pady 2m\n    ttk::label $w.f1.lab -text \"Primitive Name: \";\n    entry $w.f1.ent -width 5 -relief sunken \\\n\t-textvariable name\n    pack $w.f1.lab $w.f1.ent -side left\n    \n    frame $w.frame -borderwidth .5c\n    pack $w.frame -side top -expand yes -fill y\n\n    listbox $w.frame.list -yscroll \"$w.frame.scroll set\" -setgrid 1 -height 8 \n    scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\n    pack $w.frame.scroll -side right -fill y\n    pack $w.frame.list -side left -expand 1 -fill both\n    \n    $w.frame.list insert 0 sphere cylinder plane cone brick\n    $w.frame.list activate 0\n    \n    ttk::button $w.ok -text \"ok\" -command {\n\tNg_CreatePrimitive [$w.frame.list get active]  $name\n\tdestroy $w\n\teditprimitivedialog2 $name\n    }\n\n    ttk::button $w.cancel -text \"cancel\" -command {\n\tdestroy $w\n    }\n    \n    pack  $w.cancel $w.ok -side left -expand yes -pady 2m\n\n\n    bind $w <Escape> { $w.cancel invoke }\n    bind $w <Return> { $w.ok invoke }\n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\n#    grab $w\n    focus $w.f1.ent\n}\n\n\n\n\n\n\nproc newsoliddialog { } {\n\n    global w name val sollist\n\n    set w .ns_dlg\n    toplevel $w\n\n    set name \"\"\n    frame $w.f1\n    ttk::label $w.f1.lab -text \"Solid Name: \";\n    entry $w.f1.ent -width 5 -relief sunken \\\n\t-textvariable name\n    $w.f1.ent delete 0 end\n    ttk::button $w.f1.getsel -text \"Get Selected\" -command { \n\t$w.f1.ent delete 0 end\n\t$w.f1.ent insert 0 [$w.f3.list get active]\n\t$w.bu.get invoke\n    }\n    pack $w.f1.getsel -side bottom\n    pack $w.f1.ent $w.f1.lab -side right\n\n\n    frame $w.f3 -borderwidth .5c\n    listbox $w.f3.list -yscroll \"$w.f3.scroll set\" -setgrid 1 -height 12\n    scrollbar $w.f3.scroll -command \"$w.f3.list yview\"\n    pack $w.f3.scroll -side right -fill y\n    pack $w.f3.list -side left -expand 1 -fill both\n    \n    Ng_GetSolidList sollist\n    foreach el $sollist {\n\t$w.f3.list insert end $el }\n\n    frame $w.f2\n    ttk::label $w.f2.lab -text \"Solid Description: \";\n    pack $w.f2.lab\n\n\n    entry $w.f2.ent -width 100 -relief sunken \\\n\t-textvariable val  -xscrollcommand \"$w.f2.scr set\"\n    scrollbar $w.f2.scr -relief sunken -orient horiz -command \\\n\t\"$w.f2.ent xview\"\n    $w.f2.ent delete 0 end\n    pack $w.f2.ent $w.f2.scr -fill x\n\n\n\n    frame $w.bu\n    ttk::button $w.bu.close -text \"close\" -command {\n\tdestroy $w\n    }\n\n    ttk::button $w.bu.get -text \"get data\" -command {\n\tNg_GetSolidData $name val\n    }\n\n    ttk::button $w.bu.set -text \"set data\" -command {\n\tNg_SetSolidData $name $val\n    }\n\n    pack $w.bu.get $w.bu.set $w.bu.close -side left \n\n\n    pack $w.bu -pady 5 -side bottom                     ;# buttons\n    pack $w.f2 -pady 5 -side bottom                     ;# edit field\n    pack $w.f1 -pady 5 -side left                       ;# name\n    pack $w.f3 -side left -expand yes -fill y           ;# listbox\n\n\n\n    bind $w <Escape> { $w.bu.close invoke }\n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\n#    grab $w\n    focus $w\n}\n\n\n\n\n\n\n\n#\n#  Edit top level objects\n#\n#\n\n\nproc toplevelproperties { w solname surfname } {\n\n    global properties\n\n    Ng_TopLevel getprop $solname $surfname properties\n\n\n    set w .tlprop_dlg\n\n    if {[winfo exists $w] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n    \n\tttk::label $w.lab1 -text \"Red\"\n\tscale $w.scale1 -orient horizontal -length 300 -from 0 -to 1 \\\n\t    -resolution 0.01  -tickinterval 0.2 \\\n\t    -command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(red)\n\t\n\tttk::label $w.lab2 -text \"Green\"\n\tscale $w.scale2 -orient horizontal -length 300 -from 0 -to 1 \\\n\t    -resolution 0.01  -tickinterval 0.2 \\\n\t-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(green)\n\t\n\tttk::label $w.lab3 -text \"Blue\"\n\tscale $w.scale3 -orient horizontal -length 300 -from 0 -to 1 \\\n\t    -resolution 0.01  -tickinterval 0.2 \\\n\t    -command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(blue)\n\n\t\n\tpack $w.lab1 $w.scale1 $w.lab2 $w.scale2 $w.lab3 $w.scale3\n\n\tcheckbutton $w.cb4 -text \"Visible\" \\\n\t    -command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\n\t    -variable properties(visible)\n\t\n\tcheckbutton $w.cb5 -text \"Transparent\" \\\n\t    -command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\n\t    -variable properties(transp)\n\t\n\t\n\tpack  $w.cb4 $w.cb5\n\t\n\t\n\tframe $w.bu\n\tpack $w.bu -fill x\n\tttk::button $w.bu.ok -text \"Ok\" -command \"destroy .tlprop_dlg\"\n\tpack $w.bu.ok  -expand yes\n    \n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\tfocus $w\n    }\n    wm title $w \"Properties $solname $surfname\"\n}\n\n\n\n\n\n\nproc topleveldialog { } {\n\n    global w name val sollist\n\n    set w .tl_dlg\n    toplevel $w\n\n\n\n    frame $w.sol -borderwidth .5c\n    listbox $w.sol.list -yscroll \"$w.sol.scroll set\" -setgrid 1 -height 12\n    scrollbar $w.sol.scroll -command \"$w.sol.list yview\"\n    pack $w.sol.scroll -side right -fill y\n    pack $w.sol.list -side left -expand 1 -fill both\n    \n    Ng_GetSolidList sollist\n    foreach el $sollist {\n\t$w.sol.list insert end $el }\n    Ng_GetPrimitiveList sollist\n    foreach el $sollist {\n\t$w.sol.list insert end $el }\n\n\n\n\n    frame $w.sul -borderwidth .5c\n    listbox $w.sul.list -yscroll \"$w.sul.scroll set\" -setgrid 1 -height 12\n    scrollbar $w.sul.scroll -command \"$w.sul.list yview\"\n    pack $w.sul.scroll -side right -fill y\n    pack $w.sul.list -side left -expand 1 -fill both\n    \n    Ng_GetSurfaceList sollist\n    foreach el $sollist {\n\t$w.sul.list insert end $el }\n\n\n\n\n\n    frame $w.topl -borderwidth .5c\n    listbox $w.topl.list -yscroll \"$w.topl.scroll set\" -setgrid 1 -height 12 \\\n\t-command { puts hi }\n    scrollbar $w.topl.scroll -command \"$w.topl.list yview\"\n    pack $w.topl.scroll -side right -fill y\n    pack $w.topl.list -side left -expand 1 -fill both\n    \n    Ng_TopLevel getlist sollist\n    puts $sollist\n    foreach el $sollist {\n\tset hel \"[ lindex $el 0 ]\"\n\tif { [ llength $el ] == 2 } {\n\t    set hel \"[ lindex $el 1 ] on [ lindex $el 0 ]\"\n\t}\n\t$w.topl.list insert end $hel \n    }\n\n\n    frame $w.bu\n\n    ttk::button $w.bu.close -text \"close\" -command {\n\tdestroy $w\n    }\n    ttk::button $w.bu.addsol -text \"Add Solid\" -command {\n\tset solname [$w.sol.list get active]\n\tNg_TopLevel set $solname \"\"\n\tNg_ParseGeometry\n\t$w.topl.list insert end $solname\n    }\n\n    ttk::button $w.bu.addsurf -text \"Add Surface\" -command {\n\tset solname [$w.sol.list get active]\n\tset surfname [$w.sul.list get active]\n\tNg_TopLevel set $solname $surfname\n\tNg_ParseGeometry\n\tputs \"$solname on $surfname\"\n\t$w.topl.list insert end \"$surfname on $solname\"\n    }\n\n    ttk::button $w.bu.remsol -text \"Remove\" -command {\n\tset solname [$w.topl.list get active]\n\tset surfname \"\"\n\tif { [llength $solname] == 3 } {\n\t    set surfname [lindex $solname 0]\n\t    set solname [lindex $solname 2]\n\t}\n\tNg_TopLevel remove $solname $surfname\n\tNg_ParseGeometry\n\t$w.topl.list delete active\n    }\n\n    ttk::button $w.bu.prop -text \"Properties\" -command {\n\tset solname [$w.topl.list get active]\n\tset surfname \"\"\n\tif { [llength $solname] == 3 } {\n\t    set surfname [lindex $solname 0]\n\t    set solname [lindex $solname 2]\n\t}\n\ttoplevelproperties tlp $solname $surfname\n    }\n\n\n    \n\n    pack  $w.bu.close $w.bu.addsol $w.bu.addsurf $w.bu.remsol $w.bu.prop  -side left \n\n\n    pack $w.bu -side bottom\n    pack $w.sol -side left -expand yes -fill y           ;# listbox\n    pack $w.sul -side left -expand yes -fill y           ;# listbox\n    pack $w.topl -side left -expand yes -fill y           ;# listbox\n\n\n    bind $w <Escape> { $w.bu.close invoke }\n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\n#    grab $w\n    focus $w\n}\n\n\n\n\n\n\nproc topleveldialog2 { } {\n    set w .tl2_dlg\n    \n    if {[winfo exists .tl2_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n\tglobal name val sollist\n\n\tframe $w.topl -borderwidth .5c\n\tlistbox $w.topl.list -yscroll \"$w.topl.scroll set\" -setgrid 1 -height 12\n\tscrollbar $w.topl.scroll -command \"$w.topl.list yview\"\n\tpack $w.topl.scroll -side right -fill y\n\tpack $w.topl.list -side left -expand 1 -fill both\n\t\n\tNg_TopLevel getlist sollist\n\tputs $sollist\n\tset i 1\n\tforeach el $sollist {\n\t    set hel \"$i: [ lindex $el 0 ]\"\n\t    if { [ llength $el ] == 2 } {\n\t\tset hel \"$i: [ lindex $el 1 ] on [ lindex $el 0 ]\"\n\t    }\n\t    incr i\n\t    $w.topl.list insert end $hel }\n\t\n\t\n\tframe $w.bu\n\t\n\tttk::button $w.bu.close -text \"close\" -command {\n\t    destroy .tl2_dlg\n\t}\n\t\n\n\tttk::button $w.bu.prop -text \"Properties\" -command {\n\t    set solname [.tl2_dlg.topl.list get active]\n\t    set surfname \"\"\n\t    if { [llength $solname] == 2 } {\n\t\tset solname [lindex $solname 1]\n\t    }\n\t    if { [llength $solname] == 4 } {\n\t\tset surfname [lindex $solname 1]\n\t\tset solname [lindex $solname 3]\n\t    }\n\t    toplevelproperties tlp $solname $surfname\n\t}\n\t\n\tpack $w.bu.close $w.bu.prop  -side left \n\tpack $w.bu -side bottom\n\tpack $w.topl -side left -expand yes -fill y           ;# listbox\n\t\t\n\tbind .tl2_dlg.topl.list <Double-1> {\n\t    set solname [.tl2_dlg.topl.list get  @%x,%y]\n\t    set surfname \"\"\n\t    if { [llength $solname] == 2 } {\n\t\tset solname [lindex $solname 1]\n\t    }\n\t    if { [llength $solname] == 4 } {\n\t\tset surfname [lindex $solname 1]\n\t\tset solname [lindex $solname 3]\n\t    }\n\t    toplevelproperties tlp $solname $surfname\n\t}\n\t\n\tbind .tl2_dlg <Escape> { .tl2_dlg.bu.close invoke }\n\t\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Top-Level Options\"\t\n\tfocus $w\n    }\n}\n\n\n\n\n\n"
  },
  {
    "path": "ng/demoview.cpp",
    "content": "/*********************************************************************/\n/* File:   demoview.cpp                                              */\n/* Author: Robert, Joachim                                           */\n/* Date:   6. Mar. 2003                                              */\n/*********************************************************************/\n\n\n#include <mystdlib.h>\n\n\n//#include <iostream.h>\n#include <myadt.hpp>\n#include <linalg.hpp>\n#include <gprim.hpp>\n#include <csg.hpp> \n#include <geometry2d.hpp>\n#include <stlgeom.hpp>\n#include <meshing.hpp>\n#include \"inctcl.hpp\"\n#include <visual.hpp>\n\nnamespace netgen {  \n#include \"demoview.hpp\"\n\n\n  /*\n    static demokwstruct defkw[] =\n    {\n    { TOK_TIME,     \"t\" },\n    { TOK_CAMPOS,   \"camerapos\" },\n    { TOK_CAMPOINT, \"camerapointto\" },\n    { TOK_CAMUP,    \"cameraup\" }\n    };\n  */\n\n\n  static demoview_kwstruct demoview_defkw[] =\n    {\n      { DTOK_TIME,     \"t\" },\n      { DTOK_CAMPOS,   \"camerapos\" },\n      { DTOK_CAMPOINT, \"camerapointto\" },\n      { DTOK_CAMUP,    \"cameraup\" }\n    };\n\n\n  DemoScanner :: DemoScanner (ifstream & ascanin)\n  {\n    scanin = &ascanin;\n    token = DTOK_END;\n    num_value = 0;\n    linenum = 1;\n  }\n\n\n\n  void DemoScanner :: ReadNext ()\n  {\n    char ch;\n  \n\n    // whitespaces ueberspringen\n    do\n      { \n\tscanin->get(ch);\n\n\tif (ch == '\\n') \n\t  linenum++;\n\n\t// end of file reached\n\tif (scanin->eof())\n\t  {\n\t    token = DTOK_END;\n\t    return;\n\t  }\n\n\t// skip comment line\n\tif (ch == '#')\n\t  {\n\t    while (ch != '\\n')\n\t      {\n\t\tscanin->get(ch);\n\t\tif (scanin->eof())\n\t\t  {\n\t\t    token = DTOK_END;\n\t\t    return;\n\t\t  }\n\t      }\n\t    linenum++;\n\t  }\t\n      }\n    while (isspace(ch));\n  \n    switch (ch)\n      {\n      case '(': case ')': \n      case '[': case ']': \n      case '-': case ':':\n      case '=': case ',':\n      case ';': case '+':\n\t{\n\t  token = DEMOVIEW_TOKEN_TYPE (ch);\n\t  break;\n\t}\n  \n      default:\n\t{\n\t  if (isdigit (ch) || ch == '.')\n\t    {\n\t      scanin->putback (ch);\n\t      (*scanin) >> num_value;\n\t      token = DTOK_NUM;\n\t      return;\n\t    }\n\n\t  if (isalpha (ch))\n\t    {\n\t      string_value = string (1, ch);\n\t      scanin->get(ch);\n\t      while (isalnum(ch))\n\t\t{\n\t\t  string_value += ch;\n\t\t  scanin->get(ch);\n\t\t}\n\t      scanin->putback (ch);\n\t    }\n\n\t  int nr = 0;\n\t  while (demoview_defkw[nr].kw)\n\t    {\n\t      if (string_value == demoview_defkw[nr].name)\n\t\t{\n\t\t  token = demoview_defkw[nr].kw;\n\t\t  return;\n\t\t}\n\t      nr++;\n\t    }\n\n\t  token = DTOK_STRING;\n\t}\n      }\n  }\n\n\n\n  void DemoScanner :: Error (const string & err)\n  {\n    stringstream errstr;\n    errstr << \"Parsing error in line \" << linenum << \": \" << endl << err << endl;\n    throw string(errstr.str());\n  }\n\n\n\n  void ParseChar (DemoScanner & scan, char ch)\n  {\n    char str[2];\n    str[0] = ch;\n    str[1] = 0;\n    if (scan.GetToken() != DEMOVIEW_TOKEN_TYPE(ch)) \n      scan.Error (string (\"token '\") + string(str) + string(\"' expected\"));\n    scan.ReadNext();\n  }\n  \n\n\n  double ParseNumber(DemoScanner & scan)\n  {\n    if (scan.GetToken() == '-')\n      {\n\tscan.ReadNext();\n\treturn -ParseNumber (scan);\n      }\n    if (scan.GetToken() != DTOK_NUM) scan.Error (\"number expected\");\n    double val = scan.GetNumValue();\n    scan.ReadNext();\n    return val;\t\n  }\n\n\n  Vec<3> ParseVector (DemoScanner & scan)\n  {\n    Vec<3> s;\n\n    s(0) = ParseNumber (scan);\n    ParseChar (scan, ',');\n\n    s(1) = ParseNumber (scan);\n    ParseChar (scan, ',');\n\n    s(2) = ParseNumber (scan);\n\n    return s;\n  }\n\n\n  void ParseConstLineOrSpline (DemoScanner & scan, double * t, Vec<3> * s)\n  {\n    int np = 1;\n  \n    scan.ReadNext();\n    ParseChar (scan, '(');\n  \n    t[0] = ParseNumber (scan)*1000;\n    ParseChar (scan, ':');\n\n    s[0] = ParseVector (scan);\n  \n    if (scan.GetToken() != DTOK_RP && \n\tscan.GetToken() != DTOK_SEMICOLON)\n      scan.Error (\") or ; expected\");\t   \n  \n    if (scan.GetToken() == DTOK_SEMICOLON)\n      {\n\tnp++;\n      \n\tscan.ReadNext();\n\n\tt[1] = ParseNumber (scan)*1000;\n\tParseChar (scan, ':');\n      \n\ts[1] = ParseVector (scan);\n      \n\tif (scan.GetToken() != DTOK_RP && \n\t    scan.GetToken() != DTOK_SEMICOLON)\n\t  scan.Error (\") or ; expected\");\t   \n      \n\tif (scan.GetToken() == DTOK_SEMICOLON)\n\t  {\n\t    np++;\n\t  \n\t    scan.ReadNext();\n\t  \n\t    t[2] = ParseNumber (scan)*1000;\n\t    ParseChar (scan, ':');\n\t  \n\t    s[2] = ParseVector (scan);\n\t  \n\t    ParseChar (scan, ')');\n\t    ParseChar (scan, ';');\n\t  }\n\telse if (scan.GetToken() == DTOK_RP)\n\t  {\n\t    scan.ReadNext();\n\t    ParseChar (scan, ';');\n\t  }\n      }\n    else if (scan.GetToken() == DTOK_RP)\n      {\n\tscan.ReadNext();\n\tParseChar (scan, ';');\n      }\n  \n    if (np == 1) // constant spline\n      {\n\tt[1] = t[2] = t[0];\n\ts[1] = s[2] = s[0];\n      }\n    if (np == 2) // linear spline\n      {\n\tt[2] = t[1]; t[1] = 0.5*(t[0] + t[2]);\n\ts[2] = s[1]; s[1] = 0.5*(s[0] + s[2]);\n      }\n  }\n\n\n\n\n  template <class S>\n  void InterpolationSpline<S> :: AddSpline(double t1, double t2, double t3, S s1, S s2, S s3)\n  {\n    int pos, i, j;\n    // find pos to insert interpotation point\n    for (pos = 0; pos < ip.Size() && ip[pos][0].GetT() < t1; pos++) ;\n\n    ip.SetSize( ip.Size()+1 );\n    for (i = ip.Size()-2; i >= pos; i--)\n      for (j = 0; j < 3; j++)\n\tip[i+1][j] = ip[i][j];\n\n    ip[pos][0].SetTS (t1, s1);\n    ip[pos][1].SetTS (t2, s2);\n    ip[pos][2].SetTS (t3, s3);\n  }\n\n\n\n  template <class S>\n  S InterpolationSpline<S> :: Evaluate (double t)\n  { \n    if (t < ip[0][0].GetT())\n      return (ip[0][0].GetS());\n    \n    if (t > ip[ip.Size()-1][2].GetT())\n      {\n\tfinished = 1;\n\treturn (ip[ip.Size()-1][2].GetS());\n      }\n\n    int pos;\n    for (pos = 0; pos < ip.Size() && t >= ip[pos][0].GetT(); pos++) ;\n    pos--;\n  \n    if (t >= ip[pos][0].GetT() && t <= ip[pos][2].GetT())\n      {\n\tdouble t0 = ip[pos][0].GetT();\n\tdouble t1 = ip[pos][2].GetT();\n\n\tdouble t01 = (t-t0)/(t1-t0);\n\n\tdouble b1, b2, b3, w;\n\n\tb1 = (1-t01)*(1-t01);\n\tb2 = sqrt(2.0) * t01 * (1-t01);\n\tb3 = t01 * t01;\n\tw = b1 + b2 + b3;\n \n\treturn ( (1/w) * (b1 * ip[pos][0].GetS() +\n\t\t\t  b2 * ip[pos][1].GetS() +\n\t\t\t  b3 * ip[pos][2].GetS()) );\n      }\n    else\n      return (ip[pos][2].GetS());\n  }\n\n\n\n  DemoView :: DemoView (const char * filename)\n    : campos( Vec<3>(5,0,0) ),\n      campoint ( Vec<3>(0,0,0) ),\n      camup ( Vec<3>(0,0,1) )\n  {\n    double time = 0;\n\n    ifstream istr;\n    istr.open(filename);\n\n    DemoScanner scan(istr);\n\n    double t[3];\n    Vec<3> s[3];\n\n    scan.ReadNext();\n\n    try\n      {\n\twhile (1)\n\t  {\n\t    if (scan.GetToken() == DTOK_END) break;\n\t    \n\t    if (scan.GetToken() == DTOK_CAMPOS)\n\t      {\n\t\tParseConstLineOrSpline (scan, &t[0], &s[0]);\n\t\tcampos.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]);\n\t      }\n\t    \n\t    else if (scan.GetToken() == DTOK_CAMUP)\n\t      {\n\t\tParseConstLineOrSpline (scan, &t[0], &s[0]);\n\t\tcamup.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]);\n\t      }\n\t    \n\t    else if (scan.GetToken() == DTOK_CAMPOINT)\n\t      {\n\t\tParseConstLineOrSpline (scan, &t[0], &s[0]);\n\t\tcampoint.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]);\n\t      }\n\t    \n\t    else if (scan.GetToken() == DTOK_TIME)\n\t      {\n\t\tscan.ReadNext();\n\n\t\tif (scan.GetToken() != DTOK_EQU && \n\t\t    scan.GetToken() != DTOK_PLUS)\n\t\t  scan.Error (\"= or += expected\");\t   \n      \n\t\tif (scan.GetToken() == DTOK_EQU)\n\t\t  {\n\t\t    scan.ReadNext();\n\t\t    time = ParseNumber (scan)*1000;\n\t\t    ParseChar (scan, ';');\n\t\t  }\n\t\telse if (scan.GetToken() == DTOK_PLUS)\n\t\t  {\n\t\t    scan.ReadNext();\n\t\t    ParseChar (scan, '=');\n\t\t    time += ParseNumber (scan)*1000;\n\t\t    ParseChar (scan, ';');\n\t\t  }\n\t      }\n\t    \n\t    else\n\t      {\n\t\tcout << \"read unidentified token \" << scan.GetToken() \n\t\t     << \" string = \" << scan.GetStringValue() << endl;\n\t\tscan.ReadNext();\n\t      }\n\t  }\n      }\n    catch (string errstr)\n      {\n\tcout << \"caught error \" << errstr << endl;\n      }\n\n\n  }\n\n\n  DemoView :: ~DemoView ()\n  {\n    ;\n  }\n\n  int DemoView :: SetTime (double time)\n  {\n    /*\n      cout << \"time = \" << time << endl;\n  \n      cout << \"campos  : \" << campos.Evaluate (time) << endl;\n      cout << \"campoint: \" << campoint.Evaluate (time) << endl;\n      cout << \"camup   : \" << camup.Evaluate (time) << endl;\n    */\n\n\n    visual_scene -> LookAt ( Point<3>(  campos.Evaluate (time)),\n\t\t   Point<3>(campoint.Evaluate (time)),\n\t\t   Point<3>(   camup.Evaluate (time)) );\n\n    if (campos.IsFinished() &&\n\tcampoint.IsFinished() &&\n\tcamup.IsFinished())\n      {\n\treturn -1;\n      }\n\n    return 0;\n  }\n\n\n}\n"
  },
  {
    "path": "ng/demoview.hpp",
    "content": "#ifndef FILE_DEMOVIEW\n#define FILE_DEMOVIEW\n\n/*********************************************************************/\n/* File:   demoview.hpp                                              */\n/* Author: Robert, Joachim                                           */\n/* Date:   6. Mar. 2003                                              */\n/*********************************************************************/\n\nusing namespace netgen;\n\n\nenum DEMOVIEW_TOKEN_TYPE\n  { \n    DTOK_MINUS = '-', DTOK_LP = '(', DTOK_RP = ')', DTOK_LSP = '[', DTOK_RSP = ']',\n    DTOK_EQU = '=', DTOK_COMMA = ',', DTOK_SEMICOLON = ';', DTOK_COLON = ':', DTOK_PLUS = '+',\n    DTOK_NUM = 100, DTOK_STRING, DTOK_TIME, DTOK_CAMPOS, DTOK_CAMPOINT, DTOK_CAMUP,\n    DTOK_END \n  };\n\nstruct demoview_kwstruct\n{\n  DEMOVIEW_TOKEN_TYPE kw; \n  const char * name;\n};\n\n\n\n\nclass DemoScanner\n{\n  DEMOVIEW_TOKEN_TYPE token;\n  double num_value;\n  string string_value;\n    \n  int linenum;\n  ifstream * scanin;\n\npublic:\n\n  DemoScanner (ifstream & ascanin);\n\n  DEMOVIEW_TOKEN_TYPE GetToken() const\n  { return token; }\n\n  double GetNumValue() const\n  { return num_value; }\n\n  const string & GetStringValue() const\n  { return string_value; }\n\n  void ReadNext();\n  void Error (const string & err);\n};\n\n\nvoid ParseChar (DemoScanner & scan, char ch);\n\ndouble ParseNumber(DemoScanner & scan);\n\nVec<3> ParseVector (DemoScanner & scan);\n\n\n\ntemplate <class S>\nclass InterpolationPoint\n{\n  double t;\n  S s;\n\npublic:\n  InterpolationPoint()\n  {};\n\n  ~InterpolationPoint()\n  {};\n\n  double GetT() const\n  { return t; };\n\n  S GetS() const\n  { return s; };\n\n  void SetTS(double at, S as)\n  { t = at; s = as; };\n\n  InterpolationPoint & operator= (const InterpolationPoint<S> & ip2)\n  {\n    SetTS (ip2.t, ip2.s);\n    return (*this);\n  };\n\n};\n\n\n\ntemplate <class S>\nclass InterpolationSpline\n{\nprotected:\n  // NgArray < InterpolationPoint<S>[3] > ip;\n\n  class intpts\n  {\n  public:\n    InterpolationPoint<S> pts[3];\n    InterpolationPoint<S> & operator[](int i) { return pts[i]; }\n  };\n  NgArray < intpts > ip;\n  \n  int finished;\n\npublic:\n  InterpolationSpline() : finished(0)\n  {};\n\n  InterpolationSpline( S s1 ) : finished(0)\n  {\n    AddSpline (-1e99, -1e99, -1e99, s1, s1, s1);\n    // InterpolationSpline();\n  }\n\n  ~InterpolationSpline()\n  {};\n\n  void AddSpline(double t1, double t2, double t3, S s1, S s2, S s3);\n\n  S Evaluate (double t);\n\n  int IsFinished() const\n  {\n    return finished;\n  }\n};\n\n\n\n\n\nclass DemoView\n{\n  InterpolationSpline< Vec<3> > campos;\n  InterpolationSpline< Vec<3> > campoint;\n  InterpolationSpline< Vec<3> > camup;\n\npublic:\n  DemoView (const char * filename);\n  ~DemoView ();\n  \n  int SetTime (double time);\n};\n\n\n\n#endif\n"
  },
  {
    "path": "ng/dialog.tcl",
    "content": "proc meshingoptionsdialog { } {\n\n    set w .options_dlg\n    \n    if {[winfo exists .options_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w\n        \n    } {\n        \n\ttoplevel $w\n        #wm resizable $w 0 0 \n\n#\tglobal options.meshsize\n\n        pack [ttk::notebook $w.nb]  -fill both -side top\n        $w.nb add [ttk::frame $w.nb.general] -text \"General\" -underline 0 \n        $w.nb add [ttk::frame $w.nb.meshsize] -text \"Mesh Size\" -underline 0\n        $w.nb add [ttk::frame $w.nb.chartopt] -text \"STL Charts\" -underline 0\n        $w.nb add [ttk::frame $w.nb.optimizer] -text \"Optimizer\" -underline 0\n        # $w.nb add [ttk::frame $w.nb.insider] -text \"Insider\" -underline 0\n        $w.nb add [ttk::frame $w.nb.debug] -text \"Debug\" -underline 0\n        \n\t# tixNoteBook $w.nbold -ipadx 6 -ipady 6\n\t# $w.nbold add general -label \"General\" -underline 0 \n\t# $w.nbold add meshsize -label \"Mesh Size\"   -underline 0\n\t# $w.nbold add chartopt -label \"STL Charts\" -underline 0\n\t# $w.nbold add optimizer -label \"Optimizer\"   -underline 0\n\t# $w.nbold add insider -label \"Insider\"   -underline 0\n\t# $w.nbold add debug -label \"Debug\"   -underline 0\n\t# pack $w.nb -expand yes -fill both -padx 5 -pady 5 -side top\t\n\n\n        # ############################################################\n\t# General meshing options\n        # ############################################################\n        \n        set f $w.nb.general\n        ttk::frame $f.background\n        pack $f.background -fill both \n        set f $f.background\n        ttk::labelframe $f.f2 -relief groove -borderwidth 3 -text \"General meshing options\"\n        pack $f.f2  -pady 15 -fill x \n        set f $f.f2\n        \n\tset finevals { 1 2 3 4 5 6 }\n\tset finelabs(1) \"very coarse\" \n\tset finelabs(2) \"coarse\" \n\tset finelabs(3) \"moderate\" \n\tset finelabs(4) \"fine\" \n\tset finelabs(5) \"very fine\" \n\tset finelabs(6) \"user defined\"\n\n\t#tixOptionMenu $f.fine -label \"Mesh granularity : \" \\\n\t    -options {\n\t#\tlabel.width  19\n\t#\tlabel.anchor e\n\t#\tmenubutton.width 15\n\t#    } \n\n\t#foreach finev $finevals {\n\t#    $f.fine add command $finev -label $finelabs($finev)\n\t#}\n\t#$f.fine config -variable meshoptions.fineness\n\t#$f.fine config -command { setgranularity }\n\t#global meshoptions.fineness\n        #setgranularity ${meshoptions.fineness}\n        #pack $f.fine\n\n        global meshoptions.fineness\n        ttk::label  $f.fine2l -text \"Mesh granularity: \"\n        ttk::menubutton $f.fine2c -menu $f.fine2m -text \"coarse\" -width 16\n\n        menu $f.fine2m  -tearoff 0\n\tforeach finev { 1 2 3 4 5 6 } {\n\t    $f.fine2m add command -label $finelabs($finev) \\\n                -command \"set meshoptions.fineness $finev ; setgranularity $finev; $f.fine2c configure -text \\\"$finelabs($finev)\\\"\"\n\t}\n        $f.fine2m invoke $finelabs(${meshoptions.fineness})                \n\n\n        grid $f.fine2l $f.fine2c -sticky nw\n        \n\n\tset mgsteps { ag me ms os mv ov }\n\tset mgsteplabel(ag) \"Analyze Geometry\"\n\tset mgsteplabel(me) \"Mesh Edges\"\n\tset mgsteplabel(ms) \"Mesh Surface\"\n\tset mgsteplabel(os) \"Optimize Surface\"\n\tset mgsteplabel(mv) \"Mesh Volume\"\n\tset mgsteplabel(ov) \"Optimize Volume\"\n\n        global meshoptions.firststep \n        ttk::label  $f.first2l -text \"First Step: \"\n        # ttk::menubutton $f.first2.c -menu $f.first2.m -text \"Analyze Geometry\" -width 12\n        ttk::menubutton $f.first2c -menu $f.first2m  -width 16\n        \n        menu $f.first2m  -tearoff 0\n\tforeach i $mgsteps {\n\t    $f.first2m add command -label $mgsteplabel($i) -command \"set meshoptions.firststep $i ; $f.first2c configure -text \\\"$mgsteplabel($i)\\\"\"\n\t}\n        $f.first2m invoke $mgsteplabel(${meshoptions.firststep})        \n        grid $f.first2l $f.first2c -sticky nw\n\n        global meshoptions.laststep \n        ttk::label  $f.last2l -text \"Last Step: \"\n        ttk::menubutton $f.last2c -menu $f.last2m -width 16\n\n        menu $f.last2m  -tearoff 0\n\n\tforeach i $mgsteps {\n\t    $f.last2m add command -label $mgsteplabel($i) -command \"set meshoptions.laststep $i ; $f.last2c configure -text \\\"$mgsteplabel($i)\\\"\"\n\t}\n        $f.last2m invoke $mgsteplabel(${meshoptions.laststep})\n        grid $f.last2l $f.last2c -sticky nw\n        grid anchor $f center\n\n\t\n\t# tixOptionMenu $f.first -label \"First Step : \" \\\n\t#     -options {\n\t# \tlabel.width  19\n\t# \tlabel.anchor e\n\t# \tmenubutton.width 15\n\t#     } \n\n\t# tixOptionMenu $f.last -label \"Last Step : \" \\\n\t#     -options {\n\t# \tlabel.width  19\n\t# \tlabel.anchor e\n\t# \tmenubutton.width 15\n\t#     } \n\n\t# foreach step $mgsteps {\n\t#     $f.first add command $step -label $mgsteplabel($step)\n\t#     $f.last add command $step -label $mgsteplabel($step)\n\t# }\n\n\t# $f.first config -variable meshoptions.firststep \n\t# $f.last config  -variable meshoptions.laststep \n\n\t# pack $f.first $f.last\n\t\n\n\n\n\n\tset msg(0) \"None\"\n\tset msg(1) \"Least\"\n\tset msg(2) \"Little\"\n\tset msg(3) \"Moderate\"\n\tset msg(4) \"Much\"\n\tset msg(5) \"Most\"\n\t\n\t#tixOptionMenu $f.msg -label \"Print Messages : \" \\\n\t    -options {\n\t#\tlabel.width  19\n\t#\tlabel.anchor e\n\t#\tmenubutton.width 15\n\t#    } \n\n        #foreach step {0 1 2 3 4 5 } {\n        #    $f.msg add command $step -label $msg($step)\n\t#}\n\t#$f.msg config -variable options.printmsg \n\t# pack $f.msg\n\n        \n        global options.printmsg\n        #ttk::frame $f.msg2 \n        ttk::label  $f.msg2l -text \"Print Messages: \"\n        menu $f.msg2m  -tearoff 0\n        ttk::menubutton $f.msg2c -menu $f.msg2m  -width 16\n\tforeach step {0 1 2 3 4 5 } {\n\t    $f.msg2m add command -label $msg($step) -command \"set options.printmsg $step ; $f.msg2c configure -text $msg($step)\"\n            #            if { ${options.printmsg} == $step } { $f.msg2.c configure -text $msg($step) }\n\t}\n        $f.msg2m invoke ${options.printmsg}\n        grid $f.msg2l $f.msg2c -sticky nw\n                \n        set f $w.nb.general\n        \n        ttk::labelframe $f.bts -borderwidth 3 -relief groove -text \"Additional meshing options\"\n        pack $f.bts -fill x -pady 15\n\tttk::frame $f.bts.btnframe\n\tttk::checkbutton $f.bts.btnframe.parthread -text \"Separate meshing thread\" \\\n\t    -variable options.parthread\n\tttk::checkbutton $f.bts.btnframe.second -text \"Second order elements\" \\\n\t    -variable options.secondorder\n\tttk::checkbutton $f.bts.btnframe.quad -text \"Quad dominated\" \\\n\t    -variable options.quad -command {\n\t\tif { ${options.quad} } {\n\t\t    set meshoptions.laststep os\n\t\t}\n\t    }\n\tttk::checkbutton $f.bts.btnframe.invtets -text \"Invert volume elements\" \\\n\t    -variable options.inverttets\n\tttk::checkbutton $f.bts.btnframe.invtrigs -text \"Invert surface elements\" \\\n\t    -variable options.inverttrigs\n\tttk::checkbutton $f.bts.btnframe.azref -text \"Automatic Z-refinement\" \\\n\t    -variable options.autozrefine\n\tpack $f.bts.btnframe -anchor center\n\tpack $f.bts.btnframe.parthread $f.bts.btnframe.second $f.bts.btnframe.quad $f.bts.btnframe.invtets $f.bts.btnframe.invtrigs $f.bts.btnframe.azref -anchor w\n\n\n\t# tixControl $f.elementorder -label \"Element order: \" -integer true \\\n\t#     -variable options.elementorder -min 1 -max 20 \\\n\t#     -options {\n\t# \tentry.width 2\n\t# \tlabel.width 20\n\t# \tlabel.anchor e\n\t#     }\t\n        # pack $f.elementorder\n\n        #ttk::frame $f.bts.sbox        \n        #pack $f.bts.sbox -anchor w -pady 10\n        ttk::frame $f.bts.btnframe.elorder\n        ttk::label $f.bts.btnframe.elorder.l -text \"Element order\"\n        ttk::spinbox $f.bts.btnframe.elorder.elementorder2 -from 1 -to 20 -textvariable options.elementorder -width 2\n        pack $f.bts.btnframe.elorder -fill x\n        pack $f.bts.btnframe.elorder.elementorder2 $f.bts.btnframe.elorder.l  -anchor w -side left\n\n        ttk::frame $f.bts.btnframe.pm\n        ttk::checkbutton $f.bts.btnframe.pm.parallel_meshing -text \"Parallel meshing\" \\\n            -variable options.parallel_meshing\n        pack $f.bts.btnframe.pm -fill x -pady 5\n        pack $f.bts.btnframe.pm.parallel_meshing  -anchor w\n\n        ttk::label $f.bts.btnframe.pm.lnthreads -text \"Number of meshing threads\"\n        ttk::spinbox $f.bts.btnframe.pm.nthreads -from 1 -to 128 -textvariable options.nthreads -width 2\n        pack $f.bts.btnframe.pm.nthreads $f.bts.btnframe.pm.lnthreads  -anchor w -side left\n        \n\n\n        # ############################################################\n        # Mesh - Size options\n        # ############################################################        \n\n        set f $w.nb.meshsize\n\n        ttk::frame $f.f2\n        pack $f.f2 -pady 10\n\n        # # ttk::style configure Tframe -background red\n        # puts \"********************\"\n        # puts \"found these themes:\"\n        # puts [ttk::themes]\n        # ttk::setTheme classic\n        # ttk::setTheme aqua\n        # puts \"style Tframe foreground = \"\n        # puts [ttk::style lookup Tframe -foreground]\n        # puts \"f2 style:\"\n        # puts [$f.f2 cget -style]\n        # puts [winfo class $f.f2] \n        # puts \"style element names gives:\"\n        # puts [ttk::style element names] \n\n        \n        set f $f.f2\n        \n        ttk::frame $f.meshsize\n        ttk::label $f.meshsize.l -text \"max mesh-size\"\n        ttk::spinbox $f.meshsize.s -from 1e-9 -to 1e9 -textvariable options.meshsize -width 5 -validate focus -validatecommand \"my_validatespinbox %W %P 10\" \\\n\t    -invalidcommand \"my_invalidspinbox %W\"\n        pack $f.meshsize -fill x\n        pack $f.meshsize.s $f.meshsize.l -side right\n\n        ttk::frame $f.minmeshsize\n        ttk::label $f.minmeshsize.l -text \"min mesh-size\"\n        ttk::spinbox $f.minmeshsize.s -from 0 -to 1e9 -textvariable options.minmeshsize -width 5 -validate focus -validatecommand \"my_validatespinbox %W %P 10\" \\\n\t    -invalidcommand \"my_invalidspinbox %W\"\n        pack $f.minmeshsize -fill x\n        pack $f.minmeshsize.s $f.minmeshsize.l -side right\n\n        ttk::frame $f.grading\n        ttk::label $f.grading.l -text \"mesh-size grading\"\n        ttk::spinbox $f.grading.s -from 0.1 -to 1.0 -textvariable options.grading -width 5 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n        pack $f.grading -fill x\n        pack $f.grading.s $f.grading.l -side right\n\n        \n\t# tixControl $f.meshsize -label \"max mesh-size: \" -integer false \\\n\t#     -variable options.meshsize -min 1e-9 -max 1e6 \\\n\t#     -options {\n\t# \tentry.width 6\n\t# \tlabel.width 25\n\t# \tlabel.anchor e\n\t#     }\t\n\n\t# tixControl $f.minmeshsize -label \"min mesh-size: \" -integer false \\\n\t#     -variable options.minmeshsize -min 0 -max 1e6 \\\n\t#     -options {\n\t# \tentry.width 6\n\t# \tlabel.width 25\n\t# \tlabel.anchor e\n\t#     }\t\n\n\t# tixControl $f.grading -label \"mesh-size grading: \" -integer false \\\n\t#     -variable options.grading -min 0.1 -max 1 -step 0.1 \\\n\t#     -options {\n\t# \tentry.width 6\n\t# \tlabel.width 25\n\t# \tlabel.anchor e\n\t#     }\t\n\t\n\t# pack $f.meshsize $f.minmeshsize $f.grading\n\n        set f $w.nb.meshsize\n\n\tttk::labelframe $f.msf -text \"mesh-size file:\" -relief groove -borderwidth 3\n\tpack $f.msf\n\n \t# tixLabelEntry $f.msf.ent -label \"mesh-size file: \"  \\\n \t#     -labelside top \\\n \t#     -options {  \n \t# \tentry.textVariable options.meshsizefilename \n \t# \tentry.width 35\n \t# \tlabel.width 25\n \t# \tlabel.anchor w\n \t#     }\n\n        ttk::entry $f.msf.ent -textvariable options.meshsizefilename -width 30\n \tttk::button $f.msf.btn -text \"Browse\" -command {\n\t    global options.meshsizefilename\n\t    set types {\n\t\t{\"Meshsize file\"   {.msz}\t} }\n\t    set options.meshsizefilename [tk_getOpenFile -filetypes $types -initialfile ${options.meshsizefilename}]\n\t}\n\n \tpack $f.msf.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n \tpack $f.msf.btn -side left -anchor s -padx 4 -pady 4\n\n\n\tttk::label $f.lab -text \"Additional mesh size restrictions:\"\n\n\t#csg-meshsize options\n\n\tttk::labelframe $f.csg -relief groove -borderwidth 3 -text \"CSG mesh-size\"\n\tpack $f.csg -fill x\n        proc test {a} {puts $a}\n\t#ttk::frame $f.csg.curv\n\t#pack $f.csg.curv -fill x -anchor center\n        ttk::scale $f.csg.curvsc -orient horizontal -length 150 -from 0.2 -to 5 \\\n            -variable options.curvaturesafety -takefocus 0 -command \"roundscale $f.csg.curvsc 1\"\n        #  -resolution 0.1 \n        ttk::entry $f.csg.curve -textvariable options.curvaturesafety -width 3 \\\n            -validatecommand \"my_validate %W [$f.csg.curvsc cget -from] [$f.csg.curvsc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n        ttk::label $f.csg.curvla -text \"Elements per curvature radius\"\n\tgrid $f.csg.curvsc $f.csg.curve $f.csg.curvla -sticky nw -padx 4\n        \n\t#ttk::frame $f.csg.elen \n\t#pack $f.csg.elen  -fill x -anchor center\n\tttk::scale $f.csg.elensc -orient horizontal -length 150 -from 0.2 -to 5 \\\n            -variable options.segmentsperedge -takefocus 0 -command \"roundscale $f.csg.elensc 1\"\n        # -resolution 0.1\n        ttk::entry $f.csg.elene -textvariable options.segmentsperedge -width 3 \\\n            -validatecommand \"my_validate %W [$f.csg.elensc cget -from] [$f.csg.elensc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::label $f.csg.elenla -text \"Elements per edge\"\n\tgrid $f.csg.elensc $f.csg.elene $f.csg.elenla -sticky nw -padx 4\n        grid anchor $f.csg center\n\t\n\n\t#stl-meshsize options\n\tttk::labelframe $f.stl -relief groove -borderwidth 3 -text \"STL mesh-size\"\n\tpack $f.stl -fill x \n\n\t#ttk::frame $f.stl.r2\n\t#pack $f.stl.r2 -fill x\n\tttk::scale $f.stl.r2sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n            -variable stloptions.resthchartdistfac -takefocus 0 -command \"roundscale $f.stl.r2sc 1\"\n        ttk::entry $f.stl.r2e -textvariable stloptions.resthchartdistfac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r2sc cget -from] [$f.stl.r2sc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::checkbutton $f.stl.r2bu -text \"STL - chart distance\" \\\n\t    -variable stloptions.resthchartdistenable\n\tgrid $f.stl.r2sc $f.stl.r2e $f.stl.r2bu -sticky nw -padx 4\n\t\n\t#ttk::frame $f.stl.r6\n\t#pack $f.stl.r6 -anchor w\n\tttk::scale $f.stl.r6sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n            -variable stloptions.resthlinelengthfac -takefocus 0 -command \"roundscale $f.stl.r6sc 1\"\n        ttk::entry $f.stl.r6e -textvariable stloptions.resthlinelengthfac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r6sc cget -from] [$f.stl.r6sc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::checkbutton $f.stl.r6bu -text \"STL - line length\" \\\n\t    -variable stloptions.resthlinelengthenable\n\tgrid $f.stl.r6sc $f.stl.r6e $f.stl.r6bu -sticky nw -padx 4\n\t\n\t#ttk::frame $f.stl.r3\n\t#pack $f.stl.r3 -anchor w\n\tttk::scale $f.stl.r3sc -orient horizontal -length 150 -from 0.2 -to 8 \\\n            -variable stloptions.resthcloseedgefac -takefocus 0 -command \"roundscale $f.stl.r3sc 1\"\n        ttk::entry $f.stl.r3e -textvariable stloptions.resthcloseedgefac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r3sc cget -from] [$f.stl.r3sc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::checkbutton $f.stl.r3bu -text \"STL/IGES/STEP - close edges\" \\\n\t    -variable stloptions.resthcloseedgeenable \n\t\n\tgrid $f.stl.r3sc $f.stl.r3e $f.stl.r3bu -sticky nw -padx 4\n\t\n\t#ttk::frame $f.stl.r1\n\t#pack $f.stl.r1 -anchor w\n\tttk::scale $f.stl.r1sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n\t    -variable stloptions.resthsurfcurvfac -takefocus 0 -command \"roundscale $f.stl.r1sc 1\"\n        ttk::entry $f.stl.r1e -textvariable stloptions.resthsurfcurvfac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r1sc cget -from] [$f.stl.r1sc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::checkbutton $f.stl.r1bu -text \"STL - surface curvature\" \\\n\t    -variable stloptions.resthsurfcurvenable\n\tgrid $f.stl.r1sc $f.stl.r1e $f.stl.r1bu -sticky nw -padx 4\n\n\t#ttk::frame $f.stl.r3b\n\t#pack $f.stl.r3b -anchor w\n\tttk::scale $f.stl.r3bsc -orient horizontal -length 150 -from 0.2 -to 5 \\\n\t    -variable stloptions.resthedgeanglefac -takefocus 0 -command \"roundscale $f.stl.r3bsc 1\"\n        ttk::entry $f.stl.r3be -textvariable stloptions.resthedgeanglefac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r3bsc cget -from] [$f.stl.r3bsc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n        ttk::checkbutton $f.stl.r3bbu -text \"STL - edge angle\" \\\n            -variable stloptions.resthedgeangleenable\n\tgrid $f.stl.r3bsc  $f.stl.r3be $f.stl.r3bbu -sticky nw -padx 4\n\t\n\t#ttk::frame $f.stl.r5\n\t#pack $f.stl.r5 -anchor w\n\tttk::scale $f.stl.r5sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n            -variable stloptions.resthsurfmeshcurvfac -takefocus 0 -command \"roundscale $f.stl.r5sc 1\"\n        ttk::entry $f.stl.r5e -textvariable stloptions.resthsurfmeshcurvfac -width 3 \\\n            -validatecommand \"my_validate %W [$f.stl.r5sc cget -from] [$f.stl.r5sc cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\" -validate focus\n\tttk::checkbutton $f.stl.r5bu -text \"STL - surface mesh curv\" \\\n\t    -variable stloptions.resthsurfmeshcurvenable\n\tgrid $f.stl.r5sc  $f.stl.r5e  $f.stl.r5bu -sticky nw -padx 4\n\t\n\t\n\tttk::checkbutton $f.stl.recalch -text \"STL - Recalc mesh size for surface optimization\" \\\n\t    -variable stloptions.recalchopt\n\tgrid $f.stl.recalch -sticky n -columnspan 3 -column 0\n\n\tttk::button $f.stl.calch -text \"Calc New H\" -command { redraw; Ng_STLCalcLocalH }\n\tgrid $f.stl.calch -columnspan 3 -column 0\n\tgrid anchor $f.stl center\n        # set f [$w.nb subwidget chartopt]\n\t\n        # round ttk::scale values to n_digits\n        proc roundscale {w n_digits args} {\n            set val [$w get]\n\t    global [$w cget -variable]\n\t    if {$n_digits == 0 } {\n                set [$w cget -variable] [tcl::mathfunc::round $val]\n\t    } else {\n                set [$w cget -variable] [format \"%.[append n_digits \"f\"]\" $val]\n\t    }\n\t}\n\n        # validate ttk::entry which are linked to ttk::scales widgets\n        global last_accepted_sc\n        proc my_validate {w mini maxi val n_digits} {\n            global last_accepted_sc [$w cget -textvariable]            \n            if {[string length $val] == 0} {return 0}\n            if {[string is double $val] == 1} {\n                if { $n_digits == 0 } {\n                    set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [tcl::mathfunc::round $val]]]                    \n                } else {\n                    if { $n_digits < 9 } {\n                        set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [format \"%.[append n_digits \"f\"]\" $val]]]\n                    }\n                }                    \n                    set last_accepted_sc $val\n                    set [$w cget -textvariable] $val\n                    return 1\n                } else {\n                    return 0\n                }\n        }\n\n        # if my_validate returns 0, this function gets called\n        proc my_invalid {w} {\n            global last_accepted_sc [$w cget -textvariable]\n            set [$w cget -textvariable] $last_accepted_sc\n        }\n\n        set f $w.nb.chartopt\n        ttk::labelframe $f.mainframe -text \"STL angles\" -relief groove -borderwidth 3\n\n        pack $f.mainframe -fill x -pady 15\n        set f $f.mainframe\n\n        #ttk::frame $f.f1\n        ttk::label $f.labYangles -text \"Yellow Edges Angle ()\"\n        ttk::scale $f.scale1 -orient horizontal -length 150 -from 0 -to 90 -variable stloptions.yangle -takefocus 0 -command \"roundscale $f.scale1 1\"\n        ttk::entry $f.entry1 -textvariable stloptions.yangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\"\n\n        #pack $f.f1 -anchor center\n        grid $f.scale1 $f.entry1 $f.labYangles -sticky nw -padx 4 -pady 6\n\n        #ttk::frame $f.f21\n        ttk::label $f.labEangles -text \"Edge Corner Angle ()\"\n        ttk::scale $f.scale2 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.edgecornerangle -takefocus 0 -command \"roundscale $f.scale2 1\"\n        ttk::entry $f.entry2 -textvariable stloptions.edgecornerangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\"\n\n        #pack $f.f21 -anchor center\n        grid $f.scale2 $f.entry2 $f.labEangles -sticky nw -padx 4 -pady 6\n\n        #ttk::frame $f.f31\n        ttk::label $f.lab31 -text \"Chart Angle ()\"\n        ttk::scale $f.scale3 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.chartangle -takefocus 0 -command \"roundscale $f.scale3 1\"\n        ttk::entry $f.entry3 -textvariable stloptions.chartangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\"\n\n        #pack $f.f31 -anchor center\n        grid $f.scale3 $f.entry3 $f.lab31 -sticky nw -padx 4 -pady 6\n\n        #ttk::frame $f.f41\n        ttk::label $f.lab41 -text \"Outer Chart Angle ()\"\n        ttk::scale $f.scale4 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.outerchartangle -takefocus 0 -command \"roundscale $f.scale4 1\"\n        ttk::entry $f.entry4 -textvariable stloptions.outerchartangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 1\" \\\n            -invalidcommand \"my_invalid %W\"\n\n        #pack $f.f41 -anchor center\n        grid $f.scale4 $f.entry4 $f.lab41 -sticky nw -padx 4 -pady 6\n\tgrid anchor $f center\n\t# Optimization options\n\n        global last_accepted_sp\n        # Used to validate the entries linked with a ttk::spinbox widget\n        proc my_validatespinbox {w val n_digits} {\n            global last_accepted_sp            \n                if {[string length $val] == 0} {return 0}\n                if {[string is double $val] == 1} {\n                    if { $n_digits == 0 } {\n                        if { $n_digits < 9 } {\n                            set val [tcl::mathfunc::round $val] } else { set val [format \"%.[append n_digits \"f\"]\" $val]\n                        }\n                    }\n                        $w set [tcl::mathfunc::max [$w cget -from] [tcl::mathfunc::min [$w cget -to] $val]]\n                        set last_accepted_sp $val                        \n                        return 1\n                } else {\n                    return 0\n                }\n        }\n\t\n        proc my_invalidspinbox {w} {\n            global last_accepted_sp\n            $w set $last_accepted_sp\n        }\n        # set f [$w.nb subwidget optimizer]\n        set f $w.nb.optimizer\n        ttk::labelframe $f.optframe -text \"Optimization settings\" -relief groove -borderwidth 3\n\tpack $f.optframe -fill x -pady 15\n\t\n        #ttk::frame $f.optframe.sos\n        ttk::label $f.optframe.sosl -text \"Surface opt steps\"\n        ttk::spinbox $f.optframe.soss -from 0 -to 99 -textvariable options.optsteps2d -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        #pack $f.optframe.sos -anchor center\n        grid $f.optframe.sosl $f.optframe.soss -sticky nw;# -side right -fill x -pady 2\n\n        #ttk::frame $f.optframe.vos\n        ttk::label $f.optframe.vosl -text \"Volume opt steps\"\n        ttk::spinbox $f.optframe.voss -from 0 -to 99 -textvariable options.optsteps3d -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        #pack $f.optframe.vos -anchor center\n        grid $f.optframe.vosl $f.optframe.voss -sticky nw;# -side right -fill x -pady 2\n\t\n        #ttk::frame $f.optframe.esw\n        ttk::label $f.optframe.eswl -text \"Element size weight\"\n        ttk::spinbox $f.optframe.esws -from 0 -to 1 -textvariable options.elsizeweight -width 5 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 1\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        #pack $f.optframe.esw -anchor center\n        grid $f.optframe.eswl $f.optframe.esws -sticky nw;# -side right -fill x -pady 2\n\n        #ttk::frame $f.optframe.wem\n        ttk::label $f.optframe.weml -text \"Worst element measure\"\n        ttk::spinbox $f.optframe.wems -from 1 -to 10 -textvariable options.opterrpow -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        #pack $f.optframe.wem -anchor e\n        grid $f.optframe.weml $f.optframe.wems -sticky nw;# -side right -fill x -pady 2\n        grid anchor $f.optframe center \n        # These functions are needed due to a bug within the aqua theme\n        # if a ttk::scale widget has a from value larger than 100.\n\tproc roundscale_helper_osx {w val} {\n            global [$w cget -variable] options.badellimit\n            set [$w cget -variable] [tcl::mathfunc::round $val]\n            set options.badellimit [expr [tcl::mathfunc::round $val]+160]\n        }\n\n        proc my_validate_helper_osx {w val} {\n            if {[string length $val] == 0} {return 0}\n            if {[string is double $val] == 1} {\t\t\t\n                set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]            \n                global [$scale_loc cget -variable] options.badellimit\n                set [$scale_loc cget -variable] [tcl::mathfunc::max [$scale_loc cget -from] [tcl::mathfunc::min [$scale_loc cget -to] [expr [tcl::mathfunc::round $val]-160]]]\n                set options.badellimit [tcl::mathfunc::max [expr [$scale_loc cget -from]+160] [tcl::mathfunc::min [expr [$scale_loc cget -to]+160] [tcl::mathfunc::round $val]]]\n                return 1\n            } else {\n                return 0\n            }\n        }\n\n        proc my_invalid_helper_osx {w} {\n            global options.badellimit\n            set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]\n            global [$scale_loc cget -variable]\n            set [$scale_loc cget -variable] [tcl::mathfunc::round [$scale_loc get]]\n            set options.badellimit [expr [tcl::mathfunc::round [$scale_loc get]]+160]\n        }    \n    \n        global dummy_badellimit\n        set dummy_badellimit 15 \n        ttk::labelframe $f.optframe2 -text \"Bad elements\" -relief groove -borderwidth 3\n        pack $f.optframe2 -fill x -pady 15 -ipady 5\n        ttk::frame $f.optframe2.badellimit        \n        ttk::label $f.optframe2.lab -text \"bad element criterion\";\n        ttk::scale $f.optframe2.scale -orient horizontal -length 100 -from 00 -to 20 -variable dummy_badellimit -takefocus 0 -command \"roundscale_helper_osx $f.optframe2.scale\"\n        ttk::entry $f.optframe2.entry -textvariable options.badellimit -width 3 -validate focusout -takefocus 0 -validatecommand \"my_validate_helper_osx %W %P\" \\\n            -invalidcommand \"my_invalid_helper_osx %W\"\n        #pack $f.optframe2.badellimit -anchor center\n        grid $f.optframe2.scale $f.optframe2.entry $f.optframe2.lab -padx 4 -sticky nw\n        grid anchor $f.optframe2 center\n\n\n\n\t# insider options\n        # set f [$w.nb subwidget insider]\n        set f $w.nb.debug    \n        ttk::labelframe $f.f2 -text \"Advanced options\" -borderwidth 3 -relief groove\n        pack $f.f2 -fill x -pady 15\n        #ttk::frame $f.f2.frame\n        #pack $f.f2.frame \n        set f $f.f2\n\tttk::checkbutton $f.localh -text \"Use Local Meshsize\" \\\n\t    -variable options.localh\n\tttk::checkbutton $f.delauney -text \"Use Delaunay\" \\\n\t    -variable options.delaunay\n\tttk::checkbutton $f.checkoverlap -text \"Check Overlapping\" \\\n\t    -variable options.checkoverlap\n\tttk::checkbutton $f.checkcb -text \"Check Chart Boundary\" \\\n\t    -variable options.checkchartboundary\n\tttk::checkbutton $f.blockfill -text \"Do Blockfilling\" \\\n\t    -variable options.blockfill\n\n        grid $f.localh  $f.delauney -sticky nw\n        grid $f.checkoverlap $f.blockfill -sticky nw\n        grid $f.checkcb -sticky nw\n\tgrid anchor $f center\n        # debugging options    \n        set f $w.nb.debug\n\n        # enable / disable ttk::entry widgets linked to ttk::checkbuttons\n        proc enable_cb {w1 w2 w3} {\n            Ng_SetDebugParameters\n            if {[string match *selected* [$w1 state]] == 1 } {\n                $w2 configure -state normal\n                $w3 configure -state normal\n            } else {\n                $w2 configure -state disabled\n                $w3 configure -state disabled\n            }\n        }\n\t\n        ttk::labelframe $f.cb1 -text \"Debugging options\" -borderwidth 3 -relief groove\n        pack $f.cb1 -fill x -pady 15\n        \n        #frame $f.cb1.cb0\n        #pack $f.cb1.cb0 -fill x \n        \n        ttk::checkbutton $f.cb1.slowchecks -text \"Slow checks\" \\\n            -variable debug.slowchecks -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.debugoutput -text \"Debugging output\" \\\n            -variable debug.debugoutput -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltexline -text \"Halt on existing line\" \\\n            -variable debug.haltexistingline  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltoverlap -text \"Halt on Overlap\" \\\n            -variable debug.haltoverlap  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltsuc -text \"Halt on success\" \\\n            -variable debug.haltsuccess  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltnosuc -text \"Halt on no success\" \\\n            -variable debug.haltnosuccess  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltlargequal -text \"Halt on large quality class\" \\\n            -variable debug.haltlargequalclass  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltseg -text \"Halt on Segment:\" \\\n            -variable debug.haltsegment  -command { Ng_SetDebugParameters }\n        ttk::checkbutton $f.cb1.haltnode -text \"Halt on Node:\" \\\n            -variable debug.haltnode  -command { Ng_SetDebugParameters }\n        ttk::frame $f.cb1.fr\n        ttk::checkbutton $f.cb1.fr.cb -text \"Halt on Face:\" \\\n            -variable debug.haltface -command { Ng_SetDebugParameters }\n        ttk::entry $f.cb1.fr.ent -textvariable debug.haltfacenr -width 3\n        \n        pack $f.cb1.fr.cb $f.cb1.fr.ent -side left \n\n        ttk::frame $f.cb1.segs\n        ttk::label $f.cb1.segs.lab1 -text \"P1:\"\n        ttk::entry $f.cb1.segs.ent1 -width 6 \\\n            -textvariable debug.haltsegmentp1\n        ttk::label $f.cb1.segs.lab2 -text \"P2:\"\n        ttk::entry $f.cb1.segs.ent2 -width 6 \\\n            -textvariable debug.haltsegmentp2\n\n        pack $f.cb1.segs.lab1 $f.cb1.segs.ent1 $f.cb1.segs.lab2 $f.cb1.segs.ent2 -side left\n\n\n        grid $f.cb1.slowchecks $f.cb1.debugoutput -sticky nw\n        grid $f.cb1.haltexline $f.cb1.haltoverlap -sticky nw\n        grid $f.cb1.haltsuc $f.cb1.haltnosuc  -sticky nw\n        grid $f.cb1.haltlargequal  $f.cb1.fr -sticky nw\n        grid $f.cb1.haltnode -sticky nw\n        grid $f.cb1.haltseg  -stick nw\n        grid $f.cb1.segs -stick w -row 4 -rowspan 2 -column 1\n\n        grid rowconfigure $f.cb1 3 -pad 8\n        grid anchor $f.cb1 center\n        ttk::checkbutton $f.cb1.showactivechart -text \"Show Active Meshing-Chart\" -variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\n\n        grid $f.cb1.showactivechart\n        grid rowconfigure $f.cb1 3 -pad 8\n        grid rowconfigure $f.cb1 5 -pad 8\n        \n        set f $w.nb.debug        \n        ttk::labelframe $f.cont -relief groove -borderwidth 3 -text \"Debugging visualization\"\n        pack $f.cont -fill x -pady 15\n        #ttk::frame $f.cont.f\n        #pack $f.cont.f\n\n        ttk::checkbutton $f.cont.multidrawing -text \"Draw Meshing\" -variable multithread_drawing\n        ttk::checkbutton $f.cont.multitestmode -text \"Meshing Testmode\" -variable multithread_testmode\n        ttk::button $f.cont.goon -text \"Go On\" -command { set multithread_pause 0 }\n\n        grid $f.cont.multidrawing -sticky nw\n        grid $f.cont.multitestmode -sticky nw\n        grid $f.cont.goon -row 0 -rowspan 2 -column 1 -sticky w\n        grid columnconfigure $f.cont 0 -pad 30\n        grid columnconfigure $f.cont 1 -pad 20\n        grid anchor $f.cont center\n\n\tglobal userlevel\n\tif { $userlevel < 3} {\n\t    $w.nb delete insider\n\t    $w.nb delete debug\n\t}\n\n\n\n# \ttixButtonBox $w.bbox -orientation horizontal\n# \t$w.bbox add ok    -text Apply  -underline 0 -width 5 \\\n# \t    -command { \n# \t\t[.options_dlg.nb subwidget meshsize].meshsize invoke\n# \t\t[.options_dlg.nb subwidget meshsize].grading invoke\n# \t\t[.options_dlg.nb subwidget optimizer].os2d invoke\n# \t\t[.options_dlg.nb subwidget optimizer].os3d invoke\n# \t\t[.options_dlg.nb subwidget optimizer].elw invoke\n# \t\t[.options_dlg.nb subwidget optimizer].wem invoke\n\t\t\n# \t\tNg_SetMeshingParameters \n# \t    }\n\t\n# \t$w.bbox add close -text Done   -underline 0 -width 5 \\\n# \t    -command {\n# \t\t[.options_dlg.nb subwidget meshsize].meshsize invoke\n# \t\t[.options_dlg.nb subwidget meshsize].grading invoke\n# \t\t[.options_dlg.nb subwidget optimizer].os2d invoke\n# \t\t[.options_dlg.nb subwidget optimizer].os3d invoke\n# \t\t[.options_dlg.nb subwidget optimizer].elw invoke\n# \t\t[.options_dlg.nb subwidget optimizer].wem invoke\n\t\t\n# \t\tNg_SetMeshingParameters\n# \t\tdestroy .options_dlg\n# \t    }\n\t\n#       pack $w.bbox -side bottom -fill x\n\n\n        ttk::frame $w.bu\n        pack $w.bu -fill x -ipady 3\n\n        ttk::button $w.bu.apl -text \"Apply\" -command { \t    \n            Ng_SetMeshingParameters \n            Ng_SetDebugParameters\n        }\n\n        ttk::button $w.bu.ok -text \"Done\" -command {\n            Ng_SetMeshingParameters\n            Ng_SetDebugParameters\n            wm withdraw .options_dlg\n#           destroy .options_dlg\n        }\n\n        pack  $w.bu.apl $w.bu.ok -side left -expand yes \n        wm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Meshing Options\"\n\tfocus .options_dlg\n    }\n}\n\n\nmeshingoptionsdialog\nwm withdraw .options_dlg\n\n\n\n\n\n\n\n\n\n#\n#\n#  Viewing dialog\n#\n#\nproc viewingoptionsdialog { } {\n\n    global userlevel\n\n    set w .viewopts_dlg\n    \n    if {[winfo exists .viewopts_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n        #wm resizable $w 0 0 \n \n        \n        pack [ttk::notebook $w.nb]  -fill both -fill both -side top\n        $w.nb add [ttk::frame $w.nb.general] -text \"General\" -underline 0\n        $w.nb add [ttk::frame $w.nb.stl] -text \"STL\" -underline 0\n        $w.nb add [ttk::frame $w.nb.occ] -text \"IGES/STEP\" -underline 0\n        $w.nb add [ttk::frame $w.nb.mesh] -text \"Mesh\" -underline 0\n        $w.nb add [ttk::frame $w.nb.light] -text \"Light\" -underline 0\n        $w.nb add [ttk::frame $w.nb.edges] -text \"Edges\" -underline 0\n        $w.nb add [ttk::frame $w.nb.misc] -text \"Misc.\" -underline 3\n        \n\n\t# tixNoteBook $w.nb -ipadx 6 -ipady 6\n\t\n\t# $w.nb add general -label \"General\" -underline 0\n\t# $w.nb add stl -label \"STL\" -underline 0\n\t# $w.nb add occ -label \"IGES/STEP\" -underline 0\n\t# $w.nb add mesh -label \"Mesh\"   -underline 0\n\t# $w.nb add light -label \"Light\"   -underline 0\n\t# $w.nb add edges -label \"Edges\"   -underline 0\n\t# $w.nb add misc -label \"Misc.\"  -underline 3\n\n\t# pack $w.nb -expand yes -fill both -padx 5 -pady 5 -side top\t\n\n\n\n\n\n\t# general\n\tset f $w.nb.general\n        ttk::labelframe $f.gvop -text \"General viewing options\" -relief groove -borderwidth 3\n        pack $f.gvop -fill x -pady 15\n        set f $f.gvop\n\tttk::checkbutton $f.backcol -text \"White Background\" \\\n\t-variable viewoptions.whitebackground \\\n\t-command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.cross -text \"Draw Coordinate Cross\" \\\n\t-variable viewoptions.drawcoordinatecross \\\n\t-command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.color -text \"Draw Color-bar\" \\\n\t-variable viewoptions.drawcolorbar \\\n\t-command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.netgen -text \"Draw Netgen-logo\" \\\n\t-variable viewoptions.drawnetgenlogo \\\n\t-command { Ng_SetVisParameters; redraw }\n\n\tgrid $f.backcol -sticky nw\n        grid $f.cross -stick nw\n        grid $f.color  -sticky nw\n        grid $f.netgen -sticky nw\n# \tcheckbutton $f.stereo -text \"Stereo View\" \\\n# \t-variable viewoptions.stereo \\\n# \t-command { Ng_SetVisParameters; redraw }\n# \tpack $f.stereo\n\n\n        menu $f.stylemenu\n        ttk::menubutton $f.style -menu $f.stylemenu -width 10 -text [ttk::style theme use]\n        grid $f.style -sticky nw \n        grid anchor $f center\n        \n        foreach theme [ttk::themes] {\n            $f.stylemenu add command -label  $theme \\\n                -command \" $f.style configure -text $theme; puts $theme ; ttk::setTheme $theme\"\n        }\n        \n\t# stl geometry \n\tset f $w.nb.stl\n\tttk::labelframe $f.show -relief groove -borderwidth 3 -text \"STL viewing options\"\n\tpack $f.show -fill x -pady 15\n\tttk::checkbutton $f.show.showtrias -text \"Show STL-Triangles\" \\\n\t    -variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\n\t#grid $f.show.showtrias -stick nw\n\t\n\tttk::checkbutton $f.show.showfilledtrias -text \"Show Filled Triangles\" \\\n\t    -variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\n\tgrid $f.show.showtrias $f.show.showfilledtrias -sticky nw\n\t\n\tttk::checkbutton $f.show.showactivechart -text \"Show Active Meshing-Chart\" \\\n\t    -variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\n\t#grid $f.show.showactivechart -sticky nw\n\t\n\tttk::checkbutton $f.show.showedges -text \"Show Edges\" \\\n\t    -variable stloptions.showedges -command { Ng_SetVisParameters; redraw }\n\tgrid $f.show.showactivechart $f.show.showedges -sticky nw\n\tgrid anchor $f.show center\n\t#frame $f.special -relief groove -borderwidth 3\n\t#pack $f.special\n\tttk::checkbutton $f.show.showmarktrias -text \"Show Chart Triangles\" \\\n\t    -variable stloptions.showmarktrias \\\n\t    -command {set stldoctor.showfaces 0; Ng_STLDoctor; Ng_SetVisParameters; redraw }\n\t#pack $f.show.showmarktrias -side left\n\n\tttk::checkbutton $f.show.showfaces -text \"Show Faces\" \\\n\t    -variable stldoctor.showfaces \\\n\t    -command {set stloptions.showmarktrias 0; Ng_STLDoctor; Ng_SetVisParameters; redraw}    \n\t#pack $f.show.showfaces -side left\n        grid $f.show.showmarktrias $f.show.showfaces -sticky nw\n\n        \n        ttk::labelframe $f.fn -relief groove -borderwidth 3 -text \"Chart/Face number\"\n\tpack $f.fn -fill x \n\tttk::label $f.fn.lab3 -text \"Chart/Face number\"        \n\tttk::scale $f.fn.scale3 -orient horizontal -length 150 -from 0 -to 200 \\\n            -variable stloptions.chartnumber -command \"Ng_SetVisParameters; redraw;roundscale $f.fn.scale3 0\"\n        ttk::entry $f.fn.ent3 -textvariable stloptions.chartnumber -width 3 -validate focus -takefocus 0 \\\n            -validatecommand \"Ng_SetVisParameters; redraw;my_validate %W [$f.fn.scale3 cget -from] [$f.fn.scale3 cget -to] %P 0\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n            \n\tgrid $f.fn.scale3 $f.fn.ent3 $f.fn.lab3 -sticky nw -padx 4        \n        \n\t\n\t#frame $f.fo -relief groove -borderwidth 3\n\t#pack $f.fo\n\ttk::label $f.fn.lab -text \"Chart/Face Offset:\";\n\tttk::entry $f.fn.ent -width 3 \\\n\t    -textvariable stloptions.chartnumberoffset -validate focus -takefocus 0 \\\n            -validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n            -invalidcommand \"my_invalid %W\"\n\n        ttk::button $f.fn.btn_write_chart -text \"Write selected chart to chart.stlb\" -command {\n            Ng_STLDoctor writechart\n        }\n\n\tgrid $f.fn.lab -sticky ne -padx 4\n        grid $f.fn.ent -sticky nw -padx 4 -row 1 -column 1\n        grid $f.fn.btn_write_chart -padx 4 -row 2 -column 1\n        grid anchor $f.fn center \n        \n\tttk::labelframe $f.advstl -text \"Advanced STL options\" -relief groove -borderwidth 3\n        pack $f.advstl -fill x -pady 15\n        #frame $f.mt\n\t#pack $f.mt -fill x\n\tttk::checkbutton $f.advstl.bu1 -text \"Show Marked (Dirty) Triangles\" \\\n\t    -variable stldoctor.showmarkedtrigs \\\n\t    -command {Ng_STLDoctor; redraw}    \n\t#pack $f.mt.bu\n\n\t#frame $f.ep\n\t#pack $f.ep -fill x\n\tttk::checkbutton $f.advstl.bu2 -text \"show edge corner points\" \\\n\t    -variable stldoctor.showedgecornerpoints \\\n\t    -command {Ng_STLDoctor; redraw}    \n\t#pack $f.ep.bu\n\n\t#frame $f.stt\n\t#pack $f.stt -fill x\n\tttk::checkbutton $f.advstl.bu3 -text \"show touched triangle chart\" \\\n\t    -variable stldoctor.showtouchedtrigchart \\\n\t    -command {set stldoctor.showfaces 0; set stloptions.showmarktrias 1; \\\n\t\t\t  Ng_STLDoctor; Ng_SetVisParameters; redraw}    \n\t#pack $f.stt.bu\n\n\t#frame $f.sml\n\t#pack $f.sml -fill x\n\tttk::checkbutton $f.advstl.bu4 -text \"draw meshed edges\" \\\n\t    -variable stldoctor.drawmeshededges \\\n\t    -command {Ng_STLDoctor;}    \n\t#pack $f.sml.bu\n\t\n\t\n\t#frame $f.sm\n\t#pack $f.sm -fill x\n\tttk::checkbutton $f.advstl.bu5 -text \"select with mouse\" \\\n\t    -variable stldoctor.selectwithmouse\n\t#pack $f.sm.bu\n\tgrid $f.advstl.bu1 -stick nw\n        grid $f.advstl.bu2 -sticky nw\n        grid $f.advstl.bu3 -stick nw\n        grid $f.advstl.bu4 -stick nw\n        grid $f.advstl.bu5 -stick nw\n        grid anchor $f.advstl center\n\tttk::frame $f.advstl.tbn\n\tttk::label $f.advstl.tbn.lab -text \"Select triangle by number\";\n\tttk::entry $f.advstl.tbn.ent -width 5 \\\n\t    -textvariable stldoctor.selecttrig \n        pack $f.advstl.tbn.lab $f.advstl.tbn.ent -padx 4 -side left\n\tgrid $f.advstl.tbn -sticky nw\n\tgrid anchor $f.advstl center\n        grid rowconfigure $f.advstl 4 -pad 8\n\t\n        ttk::labelframe $f.vc -relief groove -borderwidth 3 -text \"Vicinity options\"\n\tpack $f.vc -fill x -pady 15\n\tttk::checkbutton $f.vc.bu -text \"show vicinity\" \\\n\t    -variable stldoctor.showvicinity \\\n\t    -command {Ng_STLDoctor vicinity; redraw}\n\tttk::label $f.vc.lab -text \"vicinity size\";\n\tttk::scale $f.vc.scale -orient horizontal -length 150 -from 0 -to 200 \\\n\t    -variable stldoctor.vicinity \\\n             -takefocus 0 \\\n             -command \"roundscale $f.vc.scale 0; Ng_STLDoctor vicinity; redraw\"\n\t    #-command { Ng_STLDoctor vicinity; redraw }\n        ttk::entry $f.vc.ent -width 4 -textvariable stldoctor.vicinity -validate focus \\\n        -takefocus 0 -validatecommand \"Ng_STLDoctor vicinity; redraw;my_validate %W [$f.vc.scale cget -from] [$f.vc.scale cget -to] %P 0\" \\\n            -invalidcommand \"my_invalid %W;Ng_STLDoctor vicinity; redraw\"\n\t#pack $f.vc.bu $f.vc.lab $f.vc.sc -expand yes\n\tgrid $f.vc.bu -stick nw -columnspan 3 -column 0 \n        grid $f.vc.scale $f.vc.ent $f.vc.lab -sticky nw -padx 4\n        grid anchor $f.vc center\n\n\n\t# IGES/STEP\n\tset f $w.nb.occ\n\tttk::labelframe $f.occframe -text \"IGES/STEP options\" -relief groove -borderwidth 3\n        pack $f.occframe -fill x -pady 15 -ipady 8\n        #set f $f.occframe\n\tttk::checkbutton $f.occframe.occshowsurfaces -text \"Show surfaces \" \\\n\t    -variable occoptions.showsurfaces \\\n\t    -command { Ng_SetOCCVisParameters; redraw }\n\n\tttk::checkbutton $f.occframe.occshowedges -text \"Show edges \" \\\n\t    -variable occoptions.showedges \\\n\t    -command { Ng_SetOCCVisParameters; redraw }\n        grid $f.occframe.occshowsurfaces $f.occframe.occshowedges -sticky nw -padx 4\n        grid anchor $f.occframe center\n\t#ttk::frame $f.deflection -relief groove -borderwidth 3\n\t#pack $f.occframe.deflection -fill x\n\tttk::button $f.occframe.btn -text \"Rebuild visualization data\" \\\n\t    -command {\n\t\tNg_SetOCCVisParameters\n\t\tNg_OCCCommand buildvisualizationmesh\n\t\tredraw\n\t    }\n\n\t#tixControl $f.occframe.ent -label \"Visualization smoothness\" -integer false \\\n\t    -variable occoptions.deflection -min 0.1 -max 3 -step 0.1 \\\n\t    -options { entry.width 3 } \\\n\t    -command { Ng_SetOCCVisParameters }\n        ttk::frame $f.occframe.vssm\n        ttk::label $f.occframe.vssm.lab -text \"Visulization smoothness\"        \n        ttk::spinbox $f.occframe.vssm.sp -textvariable occoptions.deflection \\\n            -from 0.1 -to 3 -increment 0.1 -width 4 -command { catch Ng_SetOCCVisParameters } \\\n            -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n        pack $f.occframe.vssm.lab $f.occframe.vssm.sp -side left -padx 4\n        grid $f.occframe.vssm -sticky nw -columnspan 2 -column 0 -pady 8        \n        grid $f.occframe.btn -columnspan 2 -column 0 -sticky n\n\n\n\n\t#grid $f.occframe.ent $f.occframe.lab -sticky nw\t\n\n\n\t# ACIS visualization / construction\n        \n        ttk::labelframe $f.occframe1 -relief groove -borderwidth 3 -text \"ACIS visulization / construction\"\n        pack $f.occframe1 -fill x -pady 15 -ipady 8 \n        #ttk::frame $f.occframe1.shso\n        ttk::label $f.occframe1.lab1 -text \"Show solid (0 for all)\"\n        ttk::spinbox $f.occframe1.sp1 -textvariable occoptions.showsolidnr \\\n            -from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\n            -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n        #pack $f.occframe1.shso.lab $f.occframe1.shso.sp -side left -padx 4\n\n        #ttk::frame $f.occframe1.shso2\n        ttk::label $f.occframe1.lab2 -text \"Show solid 2\"\n        ttk::spinbox $f.occframe1.sp2 -textvariable occoptions.showsolidnr2 \\\n            -from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\n            -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n        #pack $f.occframe1.shso2.lab $f.occframe1.shso2.sp -side left -padx 4\n        \n\t#tixControl $f.showsolid -label \"Show solid (0 for all)\" -integer true \\\n            -variable occoptions.showsolidnr -min 0 -max 999 \\\n\t    -options { entry.width 3 } \\\n\t    -command { Ng_SetOCCVisParameters; redraw }\n    \n\t#tixControl $f.showsolid2 -label \"Show solid 2\" -integer true \\\n            -variable occoptions.showsolidnr2 -min 0 -max 999 \\\n\t    -options { entry.width 3 } \\\n\t    -command { Ng_SetOCCVisParameters; redraw }\n\n\tttk::button $f.occframe1.subtract -text \"Subtract (2 minus 1)\" \\\n\t    -command {\n\t\tNg_ACISCommand subtract ${occoptions.showsolidnr} ${occoptions.showsolidnr2}\n\t\tredraw\n\t    }\n\n            \n            \n\tttk::button $f.occframe1.combine -text \"Combine all\" \\\n\t    -command {\n\t\tNg_ACISCommand combineall\n\t\tredraw\n\t    }\n\n\t#pack $f.showsolid $f.showsolid2 $f.subtract $f.combine;# -sticky nw\n        grid $f.occframe1.lab1 -row 0 -column 0 -sticky ne\n        grid $f.occframe1.sp1 -row 0 -column 1 -sticky nw\n        grid $f.occframe1.lab2 -row 1 -column 0 -sticky ne\n        grid $f.occframe1.sp2 -row 1 -column 1 -sticky nw\n        grid $f.occframe1.combine -columnspan 2 -column 0 -sticky n\n        grid anchor $f.occframe1 center        \n\n\n\n\n\t# mesh options\n\tset f $w.nb.mesh\n        \n\tttk::labelframe $f.center -relief groove -borderwidth 3 -text \"how shall i name you?\"\n\tpack $f.center -fill x -pady 15\n\tttk::button $f.center.lab1 -text \"Set Center Point\" \\\n\t    -command { Ng_SetVisParameters; Ng_Center; redraw }\n\tttk::entry $f.center.ent1 -width 5 \\\n\t    -textvariable viewoptions.centerpoint -validate focus \\\n            -validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n            -invalidcommand \"my_invalid %W\"\n\tgrid $f.center.ent1 $f.center.lab1 -padx 4 -pady 4 -sticky nw\n\t\n\t#ttk::frame $f.drawel -relief groove -borderwidth 3\n\t#pack $f.drawel -fill x\n\tttk::button $f.center.lab2 -text \"Draw Element\" \\\n\t    -command { Ng_SetVisParameters; Ng_ZoomAll; redraw }\n\tttk::entry $f.center.ent2 -width 5 \\\n\t    -textvariable viewoptions.drawelement -validate focus \\\n            -validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n            -invalidcommand \"my_invalid %W\"\n\tgrid $f.center.ent2 $f.center.lab2 -padx 4 -pady 4 -sticky nw\n        grid anchor $f.center center\n        \n        ttk::labelframe $f.meshframe -text \"Mesh visualization options\" -relief groove -borderwidth 3\n        pack $f.meshframe -fill x -pady 15\n        set f $f.meshframe\n\tttk::checkbutton $f.showcolor -text \"Meshsize Visualization\" \\\n\t    -variable viewoptions.colormeshsize \\\n\t    -command { Ng_SetVisParameters;redraw; }\n\n\tttk::checkbutton $f.showfilledtrigs -text \"Show filled triangles\" \\\n\t    -variable viewoptions.drawfilledtrigs \\\n\t    -command { Ng_SetVisParameters; redraw }\n\t\n\tttk::checkbutton $f.showedges -text \"Show edges\" \\\n\t    -variable viewoptions.drawedges \\\n\t    -command { Ng_SetVisParameters; redraw }\n\t\n\tttk::checkbutton $f.showoutline -text \"Show Triangle Outline\" \\\n\t    -variable viewoptions.drawoutline \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showbadels -text \"Show bad elements\" \\\n\t    -variable viewoptions.drawbadels \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showprisms -text \"Show prisms\" \\\n\t    -variable viewoptions.drawprisms \\\n\t    -command { Ng_SetVisParameters; redraw }\n            \n\tttk::checkbutton $f.showpyramids -text \"Show pyramids\" \\\n\t    -variable viewoptions.drawpyramids \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showhexes -text \"Show hexes\" \\\n\t    -variable viewoptions.drawhexes \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showidentified -text \"Show identified points\" \\\n\t    -variable viewoptions.drawidentified \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showmetispartition -text \"Show METIS Partition\" \\\n\t    -variable viewoptions.drawmetispartition \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::checkbutton $f.showpointnumbers -text \"Show Point-numbers\" \\\n\t    -variable viewoptions.drawpointnumbers \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showedgenumbers -text \"Show Edge-numbers\" \\\n\t    -variable viewoptions.drawedgenumbers \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showfacenumbers -text \"Show Face-numbers\" \\\n\t    -variable viewoptions.drawfacenumbers \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showelementnumbers -text \"Show Element-numbers\" \\\n\t    -variable viewoptions.drawelementnumbers \\\n\t    -command { Ng_SetVisParameters; redraw }\n        ttk::checkbutton $f.showsegmentnumbers -text \"Show Segment-numbers\" \\\n            -variable viewoptions.drawsegmentnumbers \\\n            -command { Ng_SetVisParameters; redraw }\n        ttk::checkbutton $f.showsurfaceelementnumbers -text \"Show Surfaceelement-numbers\" \\\n            -variable viewoptions.drawsurfaceelementnumbers \\\n            -command { Ng_SetVisParameters; redraw }\n\t\n\t# label $f.showdomainlab -text \"Domain Surface\"\n#\tscale $f.showdomain -orient horizontal -length 100 -from 0 -to 50 \\\n\t    -resolution 1 -variable  viewoptions.drawdomainsurf    \\\n\t    -command { Ng_SetVisParameters; redraw } \\\n\t    -label \"Domain Surface\" \n\n        #pack $f.showfilledtrigs\n\t#pack $f.showoutline $f.subdiv $f.showedges  $f.showbadels \n\t## pack $f.showdomainlab \n\t#pack $f.showdomain \n\t#pack $f.showpointnumbers \n\t#pack $f.showedgenumbers $f.showfacenumbers $f.showelementnumbers \n\t#pack $f.showmetispartition\n\n\n        \n        \n\tttk::frame $f.frametets\n\tttk::checkbutton $f.frametets.showtets -text \"\" \\\n\t    -variable viewoptions.drawtets \\\n\t    -command { Ng_SetVisParameters; redraw }\n        ttk::label $f.frametets.label -text \"\\Show Tets\\rin domain\"\n        ttk::spinbox $f.frametets.showtetsdomain -from 0 -to 500 -increment 1 -width 3 \\\n            -textvariable viewoptions.drawtetsdomain -validate focus \\\n            -command \"Ng_SetVisParameters; redraw;\" \\\n            -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n        \n        #ttk::frame $f.frametets\n        ttk::label $f.frametets.label1 -text \"Subdivision\"\n        ttk::spinbox $f.frametets.subdiv -from 0 -to 8 -increment 1 -width 3 \\\n            -textvariable visoptions.subdivisions -validate focus \\\n            -command { Ng_SetVisParameters; Ng_Vis_Set parameters; Ng_SetNextTimeStamp; redraw } \\\n            -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        ttk::label $f.frametets.label2 -text \"Show surface\\rof domain\"\n        ttk::spinbox $f.frametets.showdomain -from 0 -to 50 -increment 1 -width 3 \\\n            -textvariable viewoptions.drawdomainsurf -validate focus \\\n            -command { Ng_SetVisParameters; Ng_Vis_Set parameters; redraw } \\\n            -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n            \n\t#tixControl $f.showdomain -label \"Show surface\\rof domain\" -integer true \\\n            -variable viewoptions.drawdomainsurf -min 0 -max 50 \\\n\t    -options { entry.width 2 } \\\n\t    -command { Ng_SetVisParameters; Ng_Vis_Set parameters; redraw }\n\n\n        #tixControl $f.subdiv -label \"Subdivision\" -integer true \\        \n        #    -variable visoptions.subdivisions -min 0 -max 8 \\\n\t    -options { entry.width 2 } \\\n\t    -command { Ng_SetVisParameters; Ng_Vis_Set parameters; Ng_SetNextTimeStamp; redraw }\n            \n\t#tixControl $f.frametets.showtetsdomain -label \"\" -integer true \\\n\t    -variable viewoptions.drawtetsdomain -min 0 -max 500 \\\n\t    -options { entry.width 2 } \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\t#pack $f.frametets\t\n        grid $f.frametets.showtets $f.frametets.label $f.frametets.showtetsdomain -sticky w\n        grid x $f.frametets.label2 $f.frametets.showdomain -stick w \n        grid x $f.frametets.label1 $f.frametets.subdiv -sticky w\n        grid $f.showfilledtrigs $f.showoutline -sticky nw\n        grid $f.showedges $f.showbadels -sticky nw\n        grid $f.showpointnumbers $f.showedgenumbers -sticky nw\n        grid $f.showfacenumbers $f.showelementnumbers -sticky nw\n        grid $f.showsurfaceelementnumbers $f.showsegmentnumbers -sticky nw\n        grid $f.showmetispartition $f.showidentified -sticky nw\n\tgrid $f.showcolor $f.showpyramids -sticky nw \n        grid $f.showprisms $f.showhexes -sticky nw        \n        \n        \n        grid  $f.frametets -sticky n -columnspan 2 -column 0 -pady 8\n        #grid  $f.showdomain -stick ne;# -columnspan 3 -column 0 -pady 6\n        #grid  $f.framesubdiv -sticky nw;# -columnspan 3 -column 0 -pady 6\n        grid anchor $f center\n\n        set f $w.nb.mesh\n\tttk::labelframe $f.fshrink -text \"Element visualization\" -relief groove -borderwidth 3\n\tttk::label $f.fshrink.lab -text \"Shrink elements\"\n\t#scale $f.fshrink.scale -orient horizontal -length 200 -from 0 -to 1.0001 \\\n\t    -resolution 0.01  -tickinterval 0.25 \\\n\t    -command { Ng_SetVisParameters; after idle redraw } \\\n            -variable  viewoptions.shrink\n\tttk::scale $f.fshrink.scale -orient horizontal -length 200 -from 0 -to 1.0001 \\\n            -command \"roundscale $f.fshrink.scale 2;Ng_SetVisParameters; after idle redraw\" \\\n            -variable  viewoptions.shrink\n        ttk::entry $f.fshrink.entry -textvariable viewoptions.shrink -width 4 -validate focus \\\n            -takefocus 0 -validatecommand \"Ng_SetVisParameters; after idle redraw;my_validate %W [$f.fshrink.scale cget -from] [$f.fshrink.scale cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; after idle redraw;\"\n\tpack $f.fshrink -fill x -ipady 8\n\tgrid $f.fshrink.scale $f.fshrink.entry $f.fshrink.lab -padx 4\n        grid anchor $f.fshrink center\n\t\n#\tif {$userlevel == 3} {\n#\t    frame $f.framecurveproj\n#\t    checkbutton $f.framecurveproj.showcurveproj -text \"Show curved edge projection \" \\\n\t\t-variable viewoptions.drawcurveproj \\\n\t\t-command { Ng_SetVisParameters; redraw }\n\t#    tixControl $f.framecurveproj.showcurveprojedge -label \"\" -integer true \\\n\t\t-variable viewoptions.drawcurveprojedge -min 1 -max 99999 \\\n\t\t-options { entry.width 5 } \\\n\t\t-command { Ng_SetVisParameters; redraw }\n\n#\t    pack $f.framecurveproj\n#\t    pack $f.framecurveproj.showcurveproj $f.framecurveproj.showcurveprojedge -side left\n#\t}\n\t\n\t\n\n\n\n\n\t# light options\n\tset f $w.nb.light\n\tttk::labelframe $f.main -text \"Lighting options\" -relief groove -borderwidth 3\n        pack $f.main -fill x -pady 15\n        set f $f.main\n\tttk::label $f.lab1 -text \"Ambient Light\"\n\tttk::scale $f.scale1 -orient horizontal -length 200 -from 0 -to 1 \\\n\t    -command \"roundscale $f.scale1 2; Ng_SetVisParameters; redraw\" \\\n            -variable viewoptions.light.amb\n        ttk::entry $f.ent1 -textvariable viewoptions.light.amb -validate focus -width 4 \\\n            -validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n\n        ttk::label $f.lab2 -text \"Diffuse Light\"\n        ttk::scale $f.scale2 -orient horizontal -length 200 -from 0 -to 1 \\\n\t    -command \"roundscale $f.scale2 2; Ng_SetVisParameters; redraw \" \\\n            -variable  viewoptions.light.diff \n        ttk::entry $f.ent2 -textvariable viewoptions.light.diff -validate focus -width 4 \\\n            -validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n            \n\tttk::label $f.lab3 -text \"Specular Light\"\n\tttk::scale $f.scale3 -orient horizontal -length 200 -from 0 -to 1 \\\n\t    -command \"roundscale $f.scale3 2; Ng_SetVisParameters; redraw \" \\\n            -variable  viewoptions.light.spec \n        ttk::entry $f.ent3 -textvariable viewoptions.light.spec -validate focus -width 4 \\\n            -validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n        \n        grid $f.scale1 $f.ent1 $f.lab1 -sticky nw -padx 4 -pady 8\n        grid $f.scale2 $f.ent2 $f.lab2 -sticky nw -padx 4 -pady 8    \n        grid $f.scale3 $f.ent3 $f.lab3 -sticky nw -padx 4 -pady 8\n        grid anchor $f center\n        set f $w.nb.light\n        ttk::labelframe $f.main1 -text \"Material options\" -relief groove -borderwidth 3\n        pack $f.main1 -fill x -pady 15\n        set f $f.main1\n        ttk::label $f.lab4 -text \"Material Shininess\"        \n\tttk::scale $f.scale4 -orient horizontal -length 200 -from 0 -to 128 \\\n\t    -command \"roundscale $f.scale4 0; Ng_SetVisParameters; redraw \" \\\n            -variable  viewoptions.mat.shininess \n        ttk::entry $f.ent4 -textvariable viewoptions.mat.shininess -validate focus -width 4 \\\n            -validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 0\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n\n            \n\tttk::label $f.lab5 -text \"Material Transparency\"\n\tttk::scale $f.scale5 -orient horizontal -length 200 -from 0 -to 1 \\\n\t-command \"roundscale $f.scale5 2; Ng_SetVisParameters; redraw \" \\\n        -variable  viewoptions.mat.transp \n        ttk::entry $f.ent5 -textvariable viewoptions.mat.transp -validate focus -width 4 \\\n            -validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale5 cget -from] [$f.scale5 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n\n\n        grid $f.scale4 $f.ent4 $f.lab4 -sticky nw -padx 4 -pady 8          \n        grid $f.scale5 $f.ent5 $f.lab5 -sticky nw -padx 4 -pady 8\n        grid anchor $f center\n        #$f.lab2 $f.scale2 $f.lab3 $f.scale3 $f.lab4 $f.scale4 $f.lab5 $f.scale5\n\t\n\n\n\n\n\t# edges options\n\tset f $w.nb.edges\n        ttk::labelframe $f.main -text \"Edge viewing options\" -relief groove -borderwidth 3\n        pack $f.main -fill x -pady 15\n        set f $f.main\n        ttk::frame $f.helper \n        pack $f.helper -anchor center\n        set f $f.helper\n\tttk::checkbutton $f.showedges -text \"Show Edges\" \\\n\t    -variable viewoptions.drawededges \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showpoints -text \"Show Points\" \\\n\t    -variable viewoptions.drawedpoints \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showpointnrs -text \"Show Points Nrs\" \\\n\t    -variable viewoptions.drawedpointnrs \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.showtang -text \"Show CP Tangents\" \\\n\t    -variable viewoptions.drawedtangents \\\n\t    -command { Ng_SetVisParameters; redraw }\n\tttk::checkbutton $f.drawedgenrs -text \"Show Edge Nrs\" \\\n\t    -variable viewoptions.drawededgenrs \\\n\t    -command { Ng_SetVisParameters; redraw }\n\t\n\tpack $f.showedges $f.showpoints $f.showpointnrs $f.showtang $f.drawedgenrs -anchor w\n        set f $w.nb.edges\n        ttk::labelframe $f.main1 -text \"Center point\" -relief groove -borderwidth 3\n        pack $f.main1 -fill x -pady 15\n        set f $f.main1\n\tttk::frame $f.center\n\tpack $f.center -anchor center \n\tttk::button $f.center.btn -text \"Set Center Point\" \\\n\t    -command { Ng_SetVisParameters; Ng_Center; redraw }\n\tttk::entry $f.center.ent -width 5 -textvariable viewoptions.centerpoint -validate focus \\\n            -validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n            -invalidcommand \"my_invalid %W\"\n\tgrid $f.center.ent $f.center.btn -sticky nw -padx 4\n\t\n\n\n\t#ttk::frame $f.f1\n\t#pack $f.f1 -pady 5 -anchor center\n\tttk::label $f.center.lab1 -text \"SpecPoint Veclen\"\n\tttk::entry $f.center.ent1 -width 5 -textvariable viewoptions.specpointvlen -validate focus \\\n            -validatecommand \"my_validate %W 0 1e9 %P 4\" \\\n            -invalidcommand \"my_invalid %W\"\n\tgrid $f.center.ent1 $f.center.lab1 -sticky nw -padx 4\n\t\n\n\n\n\t# misc options\n\tset f $w.nb.misc\n\n\tttk::labelframe $f.point -relief groove -borderwidth 3 -text \"Special point\"\n\n\tttk::frame $f.point.dp\n\t\n\tttk::checkbutton $f.point.dp.drawpoint -text \"Draw Point\" \\\n\t    -variable viewoptions.drawspecpoint \\\n\t    -command { Ng_SetVisParameters; redraw }\n\n\tttk::entry $f.point.dp.px -width 8 -textvariable viewoptions.specpointx -validate focus \\\n            -validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n            -invalidcommand \"my_invalid %W\"\n\tttk::entry $f.point.dp.py -width 8 -textvariable viewoptions.specpointy -validate focus \\\n            -validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n            -invalidcommand \"my_invalid %W\"\n\tttk::entry $f.point.dp.pz -width 8 -textvariable viewoptions.specpointz -validate focus \\\n            -validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n            -invalidcommand \"my_invalid %W\"\n\n\tgrid $f.point.dp.drawpoint $f.point.dp.px $f.point.dp.py $f.point.dp.pz -sticky nw -padx 4;# -side left\n\n\t\n\n\tttk::checkbutton $f.point.dp.center -text \"Use as Center\" \\\n\t    -variable viewoptions.usecentercoords \\\n\t    -command { \n\t\tif { ${viewoptions.usecentercoords} } {\n\t\t    set viewoptions.centerx ${viewoptions.specpointx}\n\t\t    set viewoptions.centery ${viewoptions.specpointy}\n\t\t    set viewoptions.centerz ${viewoptions.specpointz}\n\t\t    Ng_SetVisParameters; Ng_Center\n\t\t    redraw\n\t\t} {\n\t\t    Ng_SetVisParameters\n\t\t}\n\t\t\n\t\t    \n\t    }\n\n\tgrid $f.point.dp.center -sticky nw -padx 4\n\tpack $f.point.dp\n\tpack $f.point -fill x -ipady 3 -pady 15\n\n\n\t\n\tttk::frame $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n\n\tttk::button $w.bu.done -text \"Done\" -command {\n\t    Ng_SetVisParameters;\n\t    redraw\n\t    destroy .viewopts_dlg\n\t}\n\tttk::button $w.bu.apply -text \"Apply\" -command {\n\t    Ng_SetVisParameters;\n\t    redraw\n\t}\n\tpack $w.bu.apply $w.bu.done -expand yes -side left\n\t\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Viewing options\"\n\tfocus $w\n    }\n}\n\n\n\nproc clipplanecommand { { optionalvar 0 } } {\n    Ng_SetVisParameters\n    after idle redraw \n}\n\n\nset clippingdialog_pop1 0\nset clippingdialog_pop2 0\nset clippingdialog_pop3 0\nset clippingdialog_pop4 0\n\n\n#\n#\n#  clipping dialog\n#\n# \nproc clippingdialog { } {\n\n    global clippingdialog_pop1\n    global clippingdialog_pop2\n    global clippingdialog_pop3\n    global clippingdialog_pop4\n    set clippingdialog_pop1 1\n    set clippingdialog_pop2 1\n    set clippingdialog_pop3 1\n    set clippingdialog_pop4 1\n    \n    set w .clipping_dlg\n    \n    if {[winfo exists .clipping_dlg] == 1} {\n\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n\n    } {\n\ttoplevel $w\n        ttk::frame $w.background\n        pack $w.background -fill x -fill y \n        set w $w.background\n        ttk::labelframe $w.main -text \"Visual clipping\" -relief groove -borderwidth 3\n        pack $w.main -fill x -pady 15\n        set w $w.main\n\tttk::label $w.lab1 -text \"Normal x\"\n\tttk::scale $w.scale1 -orient horizontal -length 300 -from -1 -to 1 \\\n            -variable  viewoptions.clipping.nx \\\n            -command \"roundscale $w.scale1 2; clipplanecommand \"\n        ttk::entry $w.entry1 -width 5 -textvariable  viewoptions.clipping.nx \\\n            -validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale1 cget -from] [$w.scale1 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W; clipplanecommand\"\n\t\n\tttk::label $w.lab2 -text \"Normal y\"\n\tttk::scale $w.scale2 -orient horizontal -length 300 -from -1 -to 1 \\\n            -variable  viewoptions.clipping.ny \\\n            -command \"roundscale $w.scale2 2; clipplanecommand \"\n        ttk::entry $w.entry2 -width 5 -textvariable  viewoptions.clipping.ny \\\n            -validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale2 cget -from] [$w.scale2 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid $w.entry2;clipplanecommand\"            \n\n\tttk::label $w.lab3 -text \"Normal z\"\n\tttk::scale $w.scale3 -orient horizontal -length 300 -from -1 -to 1 \\\n            -variable  viewoptions.clipping.nz \\\n            -command \"roundscale $w.scale3 2; clipplanecommand \"\n        ttk::entry $w.entry3 -width 5 -textvariable  viewoptions.clipping.nz \\\n            -validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale3 cget -from] [$w.scale3 cget -to] %P 2\" \\\n            -invalidcommand \"my_invalid %W;clipplanecommand\"\n\n        ttk::label $w.lab4 -text \"Distance\"\n\tttk::scale $w.scale4 -orient horizontal -length 300 -from -1 -to 1.001 \\\n            -variable  viewoptions.clipping.dist \\\n            -command \"roundscale $w.scale4 3; clipplanecommand \"\n        ttk::entry $w.entry4 -width 5 -textvariable  viewoptions.clipping.dist \\\n            -validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale4 cget -from] [$w.scale4 cget -to] %P 3\" \\\n            -invalidcommand \"my_invalid %W;clipplanecommand\"\n\n        \n        proc my_Press {w x y} {\n            set inc [expr {([$w get $x $y] <= [$w get]) ? -1 : 1}]\n            ttk::Repeatedly ttk::scale::Increment $w [expr 0.001*$inc]\n            \n        }\n        bind $w.scale4 <ButtonPress-1> { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\n        bind $w.scale4 <ButtonRelease-1> {ttk::scale::Release %W %x %y}\n            \n\tttk::label $w.lab5 -text \"Additional\\rDistance\"\n\tttk::scale $w.scale5 -orient horizontal -length 300 -from -1 -to 1.001 \\\n            -variable  viewoptions.clipping.dist2 \\\n            -command \"roundscale $w.scale5 3; clipplanecommand \"\n        ttk::entry $w.entry5 -width 5 -textvariable  viewoptions.clipping.dist2 \\\n            -validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale5 cget -from] [$w.scale5 cget -to] %P 3\" \\\n            -invalidcommand \"my_invalid %W;clipplanecommand\"\n\n        bind $w.scale5 <ButtonPress-1> { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\n        bind $w.scale5 <ButtonRelease-1> {ttk::scale::Release %W %x %y}\n        \n        ttk::label $w.clipdomainlabel -text \"Clip only domain\"\n        ttk::spinbox $w.clipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\n            -textvariable viewoptions.clipping.onlydomain -validate focus \\\n            -command {clipplanecommand;} \\\n            -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        ttk::label $w.donotclipdomainlabel -text \"Do not clip domain\"\n        ttk::spinbox $w.donotclipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\n            -textvariable viewoptions.clipping.notdomain -validate focus \\\n            -command \"clipplanecommand\" \\\n            -validatecommand \"my_validatespinbox %W %P 0\" \\\n            -invalidcommand \"my_invalidspinbox %W\"\n\n        \n\t#tixControl $w.clipdomain -label \"Clip only domain\" -integer true \\\n\t    -variable viewoptions.clipping.onlydomain -min 0 -max 50 \\\n\t    -options { entry.width 2 } \\\n\t    -command { clipplanecommand; }\n#\t    -command { Ng_SetVisParameters; redraw }\n\t#tixControl $w.donotclipdomain -label \"Do not clip domain\" -integer true \\\n\t    -variable viewoptions.clipping.notdomain -min 0 -max 50 \\\n\t    -options { entry.width 2 } \\\n\t    -command { clipplanecommand; }\n#\t    -command { Ng_SetVisParameters; redraw }\n\n\tgrid $w.scale1 $w.entry1 $w.lab1 -sticky nw -padx 4 -pady 14\n        grid $w.scale2 $w.entry2 $w.lab2 -sticky nw -padx 4 -pady 14\n        grid $w.scale3 $w.entry3 $w.lab3 -sticky nw -padx 4 -pady 14\n        grid $w.scale4 $w.entry4 $w.lab4 -sticky nw -padx 4 -pady 14\n        grid $w.scale5 $w.entry5 $w.lab5 -sticky w -padx 4 -pady 14        \n        grid $w.clipdomainlabel -sticky ne -padx 4 -pady 14\n        grid $w.clipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 5\n        grid $w.donotclipdomainlabel -sticky ne -padx 4 -pady 14\n        grid $w.donotclipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 6\n        grid anchor $w center\n        #pack $w.lab2 $w.scale2 $w.lab3 $w.scale3 $w.lab4 $w.scale4 $w.lab5 $w.scale5 $w.clipdomain $w.donotclipdomain\n\n\tset w .clipping_dlg.background.main\n\tttk::checkbutton $w.cb1 -text \"Enable clipping\" \\\n\t    -variable viewoptions.clipping.enable \\\n\t    -command { Ng_SetVisParameters; redraw } \n            \n\tgrid  $w.cb1 -columnspan 2 -sticky ne \n\t\n\n\t\n\tttk::frame $w.bu\n#\tpack $w.bu -fill x\n\tgrid $w.bu;# -fill x -ipady 3\n        \n\tttk::button $w.cancle -text \"Done\" -command \"destroy .clipping_dlg\"\n\tgrid $w.cancle -columnspan 3 -pady 16 \n\t\n\tset w .clipping_dlg\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Clipping Plane\"\n\t#    grab $w\n\tfocus $w\n\n#\t$w.scale1 configure -command { puts \"call1b\"; Ng_SetVisParameters; redraw } \n#\tputs \"after\"\n\n\tclipplanecommand\n    }\n}\n\n\n\n\n\n#\n#  refinement dialog\n#\n#\nproc refinementdialog { } {\n\n    set w .refinement_dlg\n    \n    if {[winfo exists .refinement_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\n\ttoplevel $w\n\n\t#ttk::labelframe $w.main -text \"Refinement options\" -relief groove -borderwidth 3\n        #pack $w.main -fill x -pady 15\n        #set w $w.main\n\t# tixControl $w.meshsize -label \"max mesh-size: \" -integer false \\\n\t    # -variable options.meshize -min 1e-6 -max 1e6 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\t\n\n\t# pack $w.meshsize -anchor e\n\n\tglobal localh\n\tset localh 1\n\t# tixControl $w.loch -label \"local mesh-size: \" -integer false \\\n\t    # -variable localh -min 1e-6 -max 1e6 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\t\n\t\n\t# pack $w.loch -anchor e\n\n\tttk::frame $w.meshsize\n    \n    ttk::label $w.meshsize.l1 -text \"max mesh-size: \"\n    ttk::spinbox $w.meshsize.sp1 -from 1e-6 -to 1e6 -textvariable options.meshsize -validate focus -validatecommand \"my_validatespinbox %W %P 4\" \\\n\t    -invalidcommand \"my_invalidspinbox %W\" -width 6 -increment 0.1\n    #pack $w.meshsize.l1 $w.meshsize.sp1  -fill x -side left\n\n\tttk::frame $w.meshsizeloc\n    #pack $w.meshsize -anchor e\n    #pack $w.meshsizeloc -anchor e\n    ttk::label $w.meshsizeloc.l1 -text \"local mesh-size: \"\n    ttk::spinbox $w.meshsizeloc.sp1 -from 1e-6 -to 1e6 -textvariable localh -validate focus -validatecommand \"my_validatespinbox %W %P 4\" \\\n\t    -invalidcommand \"my_invalidspinbox %W\" -width 6 -increment 0.1\n    #pack $w.meshsizeloc.l1 $w.meshsizeloc.sp1  -expand yes -fill x\n    pack $w.meshsize \n    pack $w.meshsizeloc \n    grid $w.meshsize.l1 $w.meshsize.sp1\n    grid $w.meshsizeloc.l1 $w.meshsizeloc.sp1\n\t\n\t\n\tttk::button $w.restface -text \"Restrict H at face\"  \\\n\t    -command {\n\t\t.refinement_dlg.meshsize invoke\n\t\t.refinement_dlg.loch invoke\n\t\tNg_RestrictH face $localh\n\t    }\n\tttk::button $w.restedge -text \"Restrict H at edge\"  \\\n\t    -command {\n\t\t.refinement_dlg.meshsize invoke\n\t\t.refinement_dlg.loch invoke\n\t\tNg_RestrictH edge $localh\n\t    }\n\tttk::button $w.restelement -text \"Restrict H at element\"  \\\n\t    -command {\n\t\t.refinement_dlg.meshsize invoke\n\t\t.refinement_dlg.loch invoke\n\t\tNg_RestrictH element $localh\n\t    }\n\tttk::button $w.restpoint -text \"Restrict H at point\"  \\\n\t    -command {\n\t\t.refinement_dlg.meshsize invoke\n\t\t.refinement_dlg.loch invoke\n\t\tNg_RestrictH point $localh\n\t    }\n\n\n\tpack $w.restface $w.restedge $w.restelement $w.restpoint \n\n\n\n\tttk::button $w.anisoedge -text \"Declare Anisotropic edge\"  \\\n\t    -command {\n\t\tNg_Anisotropy edge \n\t    }\n\tpack $w.anisoedge\n\t\n\n\tframe $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n\n\tttk::button $w.bu.cancle -text \"Done\" -command \"destroy .refinement_dlg\"\n\tttk::button $w.bu.refine -text \"Refine\"  \\\n\t    -command { \n#\t\tNg_BisectCopyMesh; \n\t\tset oldnp 0; set newnp $status_np; \n\t\twhile { $oldnp < $newnp } {\n\t\t    set level [expr $level+1]\n\t\t    Ng_Bisect; \n\t\t    Ng_HighOrder ${options.elementorder}\n\t\t    Ng_ReadStatus;\n\t\tredraw; \n\t\t    set oldnp $newnp\n\t\t    set newnp $status_np\n\t\t    puts \"oldnp $oldnp newnp $newnp\"\n\t\t}\n\t    }\t \n\tttk::button $w.bu.zrefine -text \"Z-Refine\"  \\\n\t    -command { Ng_ZRefinement; Ng_ReadStatus; redraw; }\n   \n\tpack $w.bu.zrefine $w.bu.refine $w.bu.cancle  -expand yes -side left\n\t\t\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Select Refinement\"\n\tfocus $w\n    }\n}\n\n\n\n\n#\n#  boundcondessing dialog\n#\n#\nproc bcpropdialog { } {\n\n    set w .bcprop_dlg\n    \n    if {[winfo exists .bcprop_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n    } {\n\ttoplevel $w\n\t\n\tttk::frame $w.face  -borderwidth 3\n\tpack $w.face -fill x\n\tttk::label $w.face.lab -text \"face index:\"\n\tttk::label $w.face.ent -text 1  \n\tttk::button $w.face.next -text \"next\" -command {\n\t    set w .bcprop_dlg;\t\n\t    set facenr [$w.face.ent cget -text]\n\t    if {$facenr == [Ng_BCProp getnfd]} {\n\t\tset facenr 1 \n\t    } {\n\t\tset facenr [expr $facenr + 1]\n\t    }\n\t    $w.face.ent configure -text $facenr\n\t    Ng_BCProp setactive $facenr\n\t    set bcnr [Ng_BCProp getbc $facenr]\n\t    $w.bc.ent delete 0 end\n\t    $w.bc.ent insert 0 $bcnr\n\n\t    redraw\n\t} \n\tttk::button $w.face.prev -text \"prev\" -command {\n\t    set w .bcprop_dlg;\t\n\t    set facenr [$w.face.ent cget -text]\n\t    if {$facenr == 1} {\n\t\tset facenr [Ng_BCProp getnfd]\n\t    } {\n\t\tset facenr [expr $facenr - 1]\n\t    }\n\t    $w.face.ent configure -text $facenr\n\t    Ng_BCProp setactive $facenr\n\t    set bcnr [Ng_BCProp getbc $facenr]\n\t    $w.bc.ent delete 0 end\n\t    $w.bc.ent insert 0 $bcnr\n\n\t    redraw\n\t} \n\t\n\t\n\tpack $w.face.lab $w.face.ent $w.face.prev $w.face.next  -side left  \n\t\n\tttk::frame $w.bc  -borderwidth 3\n\tpack $w.bc -fill x\n\tttk::label $w.bc.lab -text \"bc property:\"\n\tentry $w.bc.ent -width 5 -relief sunken \n\tttk::button $w.bc.but -text \"change\" -command { \n\t    set w .bcprop_dlg;\t    \n\t    Ng_BCProp setbc [$w.face.ent cget -text] [$w.bc.ent get]; \n\t}\n\tttk::button $w.bc.but2 -text \"all\" -command { \n\t    set w .bcprop_dlg;\t    \n\t    Ng_BCProp setall [$w.bc.ent get]; \n\t}\n\tpack $w.bc.lab $w.bc.ent $w.bc.but $w.bc.but2 -side left  -expand yes\n\n\tttk::frame $w.bcname  -borderwidth 3\n\tpack $w.bcname -fill x\n\tttk::label $w.bcname.lab -text \"bc name:\"\n\tttk::label $w.bcname.ent -text \"-\"\n\tpack $w.bcname.lab $w.bcname.ent -side left  -expand yes\n\t\n\n\tttk::frame $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n\tttk::button $w.bu.close -text \"Close\" -command { destroy .bcprop_dlg }\n\n\tpack $w.bu.close  -expand yes -side left\n\t\t\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Boundary Conditions\"\n    }\n\n    focus $w \n\n    set facenr [Ng_BCProp getactive]\n    $w.face.ent configure -text $facenr\n    \n    set bcnr [Ng_BCProp getbc $facenr]\n    $w.bc.ent delete 0 end\n    $w.bc.ent insert 0 $bcnr\n\n    set bcname [Ng_BCProp getbcname $facenr]\n    $w.bcname.ent configure -text $bcname\n\n}\n\n\n\n\n#\n# Philippose - 25/07/2010\n# Display the face colours currently \n# available in the mesh\n#\nproc currmeshcoloursdialog { } {\n\n    set w .currmeshcolours_dlg\n    \n    if {[winfo exists .currmeshcolours_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n\tglobal facecolslist\n\n\tframe $w.facecols -borderwidth 3\n    \n\tlistbox $w.facecols.list -yscroll \"$w.facecols.scroll set\" -selectmode single -setgrid 1 -width 32 -height 12\n\tscrollbar $w.facecols.scroll -command \"$w.facecols.list yview\"\n\tpack $w.facecols.scroll -side right -fill y\n\tpack $w.facecols.list -side left -expand yes -fill both\n    \n\tNg_CurrentFaceColours getcolours facecolslist\n\tset i 1\n\tforeach el $facecolslist {\n\t    set hel [format \"%d: (%.4f %.4f %.4f)\" $i [ lindex $el 0 ] [ lindex $el 1 ] [ lindex $el 2 ]]\n\t    incr i\n\t    $w.facecols.list insert end $hel }\n\n\tframe $w.bu1 -borderwidth 3\n    ttk::button $w.bu1.showonly -text \"show only\" -command {\n        Ng_CurrentFaceColours showonly [.currmeshcolours_dlg.facecols.list curselection]\n        redraw\n    }\n    ttk::button $w.bu1.hideonly -text \"hide only\" -command {\n        Ng_CurrentFaceColours hideonly [.currmeshcolours_dlg.facecols.list curselection]\n        redraw\n    }\n    ttk::button $w.bu1.showalso -text \"show\" -command {\n        Ng_CurrentFaceColours showalso [.currmeshcolours_dlg.facecols.list curselection]\n        redraw\n    }\n    ttk::button $w.bu1.hidealso -text \"hide\" -command {\n        Ng_CurrentFaceColours hidealso [.currmeshcolours_dlg.facecols.list curselection]\n        redraw\n    }\n    pack $w.bu1.showonly $w.bu1.hideonly $w.bu1.showalso $w.bu1.hidealso -expand yes -fill x -padx 2 -pady 2 -side left    \n    \n    frame $w.bu2\n    ttk::button $w.bu2.showall -text \"show all\" -command {\n        Ng_CurrentFaceColours showall\n        redraw\n    }\n    ttk::button $w.bu2.hideall -text \"hide all\" -command {\n        Ng_CurrentFaceColours hideall\n        redraw\n    }\n    pack $w.bu2.showall $w.bu2.hideall -expand yes -fill x -padx 2 -pady 2 -side left \n    \n    frame $w.bu3\n\tttk::button $w.bu3.close -text \"close\" -command {\n\t    destroy .currmeshcolours_dlg\n\t}\n    pack $w.bu3.close -expand yes -fill x -pady 3 -side right\n\n\n\tpack $w.facecols -side top -expand yes -fill x -fill y\n    pack $w.bu3 -side bottom\n    pack $w.bu2 -side bottom    \n    pack $w.bu1 -expand yes -fill x -side left    \n    \n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Inspect Mesh Colours\"\t\n\tfocus $w\n    }\n}\n\n\n\n\n#\n#  Philippose - 30/01/2009\n#  Local Surface Mesh Size Selection\n#  (Currently only supports OCC Geometry)\n#\n#\nproc surfacemeshsizedialog { } {\n\n    set w .surfacemeshsize_dlg\n\n    if {[winfo exists .surfacemeshsize_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n    } {\n\ttoplevel $w\n\n\tframe $w.face  -borderwidth 3\n\tpack $w.face -fill x -padx 5\n\tttk::label $w.face.lab -text \"face index:\"\n\tttk::label $w.face.ent -text 1\n\tttk::button $w.face.next -text \"next\" -command {\n\t    set w .surfacemeshsize_dlg;\t\n\t    set facenr [$w.face.ent cget -text]\n\t    if {$facenr == [Ng_SurfaceMeshSize getnfd]} {\n\t\tset facenr 1 \n\t    } {\n\t\tset facenr [expr $facenr + 1]\n\t    }\n\t    $w.face.ent configure -text $facenr\n\t    Ng_SurfaceMeshSize setactive $facenr\n\t    set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n\t    $w.sms.ent delete 0 end\n\t    $w.sms.ent insert 0 $surfms\n\n\t    redraw\n\t} \n\tttk::button $w.face.prev -text \"prev\" -command {\n\t    set w .surfacemeshsize_dlg;\n\t    set facenr [$w.face.ent cget -text]\n\t    if {$facenr == 1} {\n\t\tset facenr [Ng_SurfaceMeshSize getnfd]\n\t    } {\n\t\tset facenr [expr $facenr - 1]\n\t    }\n\t    $w.face.ent configure -text $facenr\n\t    Ng_SurfaceMeshSize setactive $facenr\n\t    set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n\t    $w.sms.ent delete 0 end\n\t    $w.sms.ent insert 0 $surfms\n\n\t    redraw\n\t} \n\n\n\tpack $w.face.lab $w.face.ent $w.face.prev $w.face.next  -side left  \n\n\tframe $w.sms  -borderwidth 3\n\tpack $w.sms -fill x\n\tttk::label $w.sms.lab -text \"max mesh size:\"\n\tentry $w.sms.ent -width 8 -relief sunken \n\tttk::button $w.sms.but -text \"change\" -command { \n\t    set w .surfacemeshsize_dlg;\t    \n\t    Ng_SurfaceMeshSize setsurfms [$w.face.ent cget -text] [$w.sms.ent get];\n\t}\n\tttk::button $w.sms.but2 -text \"all\" -command {\n\t    set w .surfacemeshsize_dlg;\t    \n\t    Ng_SurfaceMeshSize setall [$w.sms.ent get];\n\t}\n\tpack $w.sms.lab $w.sms.ent $w.sms.but $w.sms.but2 -side left -padx 5 -expand yes\n\n\tframe $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n\tttk::button $w.bu.close -text \"Close\" -command { destroy .surfacemeshsize_dlg }\n\n\tpack $w.bu.close  -expand yes -side left\n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Edit Surface Mesh Size\"\n    }\n\n    focus $w \n\n    set facenr [Ng_SurfaceMeshSize getactive]\n    $w.face.ent configure -text $facenr\n\n    set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n    $w.sms.ent delete 0 end\n    $w.sms.ent insert 0 $surfms\n\n}\n\n\n\n\n#\n#  METIS dialog\n#\n#\nproc METISdialog { } {\n\n    set w .metis_dlg\n    set w.parts 64\n    \n    if {[winfo exists .metis_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n    } {\n\ttoplevel $w\n\t\n\tframe $w.a -borderwidth 0\n\tframe $w.b -borderwidth 0\n\tpack $w.a $w.b\n\n\tttk::label $w.a.lab -text \"Number of partitions:\"\n\tentry $w.a.ent -textvariable w.parts -width 4 -relief sunken\n\n\tttk::button $w.b.start -text \"Start METIS\" -command { \n\t    Ng_Metis ${w.parts}\n\t    redraw\n\t}\n\tttk::button $w.b.cancel -text \"Cancel\" -command { destroy .metis_dlg }\n\tpack $w.a.lab $w.a.ent -side left  -expand yes\n\tpack $w.b.start $w.b.cancel -side left\n\n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"METIS Partitioning\"\n\tfocus $w\n \n    }\n}\n\n\n\n#\n#  STL dialog\n#\nproc stloptionsdialog { } {\n\n    set w .stlopts_dlg\n    \n    if {[winfo exists .stlopts_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n        pack [ttk::notebook $w.nb]  -fill both -fill both -side top\n\t# tixNoteBook $w.nb -ipadx 6 -ipady 6\n\t#\t$w config -bg gray\n\t#\t$w.nb subwidget nbframe config -backpagecolor gray\n\t\n\t# Create the two tabs on the notebook. The -underline option\n\t# puts a underline on the first character of the labels of the tabs.\n\t# Keyboard accelerators will be defined automatically according\n\t# to the underlined character.\t\n\t#\n\t\n# \t$w.nb add chartopt -label \"Chart Options\" -underline 0\n# \t#$w.nb add meshsize   -label \"Mesh Size\"   -underline 0\n# \tpack $w.nb -expand yes -fill both -padx 5 -pady 5 -side top\t\n\n\n# \tset f [$w.nb subwidget chartopt]\n\n\n# \tlabel $f.lab1 -text \"Yellow Edges Angle ()\"\n# \tscale $f.scale1 -orient horizontal -length 300 \\\n# \t    -from 0 -to 90 -resolution 1  -tickinterval 10 \\\n# \t    -variable  stloptions.yangle \n\n# \tpack $f.lab1 $f.scale1\n\n# \tlabel $f.lab2e -text \"Edge Corner Angle ()\"\n# \tscale $f.scale2e -orient horizontal -length 360 -from 0 -to 180 \\\n# \t    -resolution 1  -tickinterval 20 \\\n# \t    -variable  stloptions.edgecornerangle \n# \tpack $f.lab2e $f.scale2e\n\t\n# \tlabel $f.lab2 -text \"Chart Angle ()\"\n# \tscale $f.scale2 -orient horizontal -length 360 -from 0 -to 180 \\\n# \t    -resolution 1  -tickinterval 20 \\\n# \t    -variable  stloptions.chartangle \n# \tpack $f.lab2 $f.scale2\n\t\n# \tlabel $f.lab2b -text \"Outer Chart Angle ()\"\n# \tscale $f.scale2b -orient horizontal -length 360 -from 0 -to 180 \\\n# \t    -resolution 1  -tickinterval 20 \\\n# \t    -variable  stloptions.outerchartangle \n# \tpack $f.lab2b $f.scale2b\n\t\n#\tframe $f.r4\n#\tpack $f.r4 -anchor w\n#\tscale $f.r4.sc -orient horizontal -length 200 -from 0.1 -to 10 \\\n#\t    -resolution 0.1 -variable stloptions.resthatlasfac\n#\tcheckbutton $f.r4.bu -text \"Restrict h for Calc Atlas (Faster)\" \\\n#\t    -variable stloptions.resthatlasenable\n#\tpack $f.r4.sc $f.r4.bu -side left\n\t\n\n\t#set f [$w.nb subwidget meshsize]\n\n\t\n\n#    checkbutton $w.seat -text \"Use Searchtrees\" \\\n#\t-variable stloptions.usesearchtree\n#   pack $w.seat\n\n\n\n\n\tframe $w.bu\n#    pack $w.bu\n\tpack $w.bu -fill x -ipady 3\n\n# -fill x\n\n    ttk::button $w.bu.apply -text \"Apply\" -command { redraw; Ng_GenerateMesh 1 2}\n\tttk::button $w.bu.cancle -text \"Done\" -command { destroy .stlopts_dlg }\n    pack $w.bu.cancle  $w.bu.apply  -side left -expand yes\n    \n\n    wm withdraw $w\n    wm geom $w +100+100\n    wm deiconify $w\n\twm title $w \"STL Options\"\n#    grab $w\n\tfocus $w\n    }\n}\n\nproc stldoctordialog { } {\n    Ng_STLDoctor\n    set wd .stldoctor_dlg\n\n    if {[winfo exists .stldoctor_dlg] == 1} {\n    \n\twm withdraw $wd\n\twm deiconify $wd\n\tfocus $wd \n    } {\n\t\n    toplevel $wd\n    pack [ttk::notebook $wd.nb] -fill both -fill both -side top\n    $wd.nb add [ttk::frame $wd.nb.general] -text \"General\" -underline 0\n    $wd.nb add [ttk::frame $wd.nb.topology] -text \"Edit Topology\" -underline 5\n    $wd.nb add [ttk::frame $wd.nb.edges] -text \"Edit Edges\" -underline 5\n    $wd.nb add [ttk::frame $wd.nb.normals] -text \"Edit Normals\" -underline 5\n    $wd.nb add [ttk::frame $wd.nb.advanced] -text \"Advanced\" -underline 0\n    \n    # tixNoteBook $wd.nb -ipadx 6 -ipady 6\n    # $wd.nb add general -label \"General\" -underline 0\n    # $wd.nb add topology -label \"Edit Topology\"  -underline 5\n    # $wd.nb add edges -label \"Edit Edges\"   -underline 5\n    # $wd.nb add normals -label \"Edit Normals\"   -underline 5\n    # $wd.nb add advanced -label \"Advanced\"   -underline 0\n    # pack $wd.nb -expand yes -fill both -padx 5 -pady 5 -side top\t\n\n\n    # GENERAL *****************************\n\n    set f $wd.nb.general\n    ttk::frame $f.selectframe -borderwidth 0\n    #ttk::frame $f.show\n    #pack $f.show -fill x\n    ttk::checkbutton $f.selectframe.showtrias -text \"Show STL-Triangles\" \\\n\t-variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\n    #pack $f.selectframe.showtrias -anchor w\n    \n    ttk::checkbutton $f.selectframe.showfilledtrias -text \"Show Filled Triangles\" \\\n\t-variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\n    #pack $f.show.showfilledtrias -anchor w\n\n    set selmodevals { 0 1 2 3 4 }\n    set selmodelabs(0) \"triangle\" \n    set selmodelabs(1) \"edge\" \n    set selmodelabs(2) \"point\" \n    set selmodelabs(3) \"line\" \n    set selmodelabs(4) \"line cluster\" \n\n    # tixOptionMenu $f.selmode -label \"Double Click selects :\" \\\n\t# -options {\n\t    # label.width  19\n\t    # label.anchor e\n\t    # menubutton.width 15\n\t# } \n\n    # foreach selmodev $selmodevals {\n\t# $f.selmode add command $selmodev -label $selmodelabs($selmodev)\n    # }\n    # $f.selmode config -variable stldoctor.selectmode\n    # $f.selmode config -command { Ng_STLDoctor }\n    global stldoctor.selectmode\n    # pack $f.selmode\n    \n    ttk::label  $f.selectframe.dblcsellab -text \"Double Click selects : \"\n    ttk::menubutton $f.selectframe.dblcselbut -menu $f.selectframe.dblcselmen -text \"triangle\" -width 16\n    menu $f.selectframe.dblcselmen  -tearoff 0\n\tforeach selmode { 0 1 2 3 4 } {\n\t    $f.selectframe.dblcselmen add command -label $selmodelabs($selmode) \\\n                -command \"set stldoctor.selectmode $selmode ; Ng_STLDoctor ; $f.selectframe.dblcselbut configure -text \\\"$selmodelabs($selmode)\\\"\"\n\t}\n    $f.selectframe.dblcselmen invoke $selmodelabs(${stldoctor.selectmode})\n    pack $f.selectframe\n    grid $f.selectframe.showtrias -sticky nw\n    grid $f.selectframe.showfilledtrias -sticky nw\n    grid $f.selectframe.dblcsellab $f.selectframe.dblcselbut -sticky nw\n    \n    \n    \n    \n    ttk::frame $f.sm\n    pack $f.sm -fill x\n    ttk::checkbutton $f.sm.bu -text \"select with mouse\" \\\n\t-variable stldoctor.selectwithmouse\n    pack $f.sm.bu \n\n    ttk::frame $f.st -relief groove -borderwidth 3\n    pack $f.st -fill x\n    ttk::label $f.st.lab -text \"Select triangle by number\";\n    ttk::entry $f.st.ent -width 5 \\\n\t-textvariable stldoctor.selecttrig\n    pack $f.st.ent $f.st.lab -side left -expand yes\n\n    ttk::frame $f.vc -relief groove -borderwidth 3\n    pack $f.vc -fill x\n    ttk::checkbutton $f.vc.bu -text \"show vicinity\" \\\n\t-variable stldoctor.showvicinity \\\n\t-command {Ng_STLDoctor vicinity; redraw}\n    ttk::label $f.vc.lab -text \"vicinity size\";\n    \n    #scale $f.vc.sc -orient horizontal -length 200 -from 0 -to 200 \\\n\t-resolution 1 -variable stldoctor.vicinity \\\n\t-command { Ng_STLDoctor vicinity; redraw }\n    ttk::frame $f.vc.sc\n    ttk::scale $f.vc.sc.scale -orient horizontal -length 200 -from 0 -to 200 \\\n    -variable stldoctor.vicinity -takefocus 0 -command \"Ng_STLDoctor vicinity; redraw; roundscale $f.vc.sc.scale 0\"\n    ttk::entry $f.vc.sc.entry -textvariable stldoctor.vicinity -width 3 \\\n    -validatecommand \"Ng_STLDoctor vicinity; redraw; my_validate %W [$f.vc.sc.scale cget -from] [$f.vc.sc.scale cget -to] %P 0\" \\\n    -invalidcommand \"my_invalid %W;Ng_STLDoctor vicinity; redraw;\" -validate focus\n    ttk::label $f.vc.sc.lab -text \"vicinity size\"\n\tgrid $f.vc.sc.scale $f.vc.sc.entry $f.vc.sc.lab -sticky nw -padx 4    \n    pack $f.vc.bu $f.vc.lab $f.vc.sc -expand yes\n\n    ttk::frame $f.ge -relief groove -borderwidth 0\n    pack $f.ge -expand yes\n    ttk::button $f.ge.neighbourangles -text \"calc neighbourangles\" -command {Ng_STLDoctor neighbourangles}\n    ttk::button $f.ge.showcoords -text \"show coords of touched triangle\" -command {Ng_STLDoctor showcoords}\n    ttk::button $f.ge.moveptm -text \"move point to middle of trianglepoints\" -command {Ng_STLDoctor movepointtomiddle; redraw}\n    ttk::button $f.ge.destroy0trigs -text \"destroy 0-volume triangles\" -command {Ng_STLDoctor destroy0trigs}\n    grid $f.ge.neighbourangles -sticky nw -padx 4 -pady 4\n    grid $f.ge.showcoords -sticky nw -padx 4 -pady 4\n    grid $f.ge.moveptm -sticky nw -padx 4 -pady 4\n    grid $f.ge.destroy0trigs -sticky nw -padx 4 -pady 4\n\n\n    ttk::button $f.ge.cancle -text \"Done\" -command {destroy .stldoctor_dlg }\n    grid $f.ge.cancle  -sticky nw\n\n    # TOPOLOGY ********************\n    set f $wd.nb.topology\n\n    ttk::frame $f.oc -relief groove -borderwidth 3\n    pack $f.oc -pady 3 -ipady 3 -fill y -fill x\n    ttk::frame $f.oc.oc1 -borderwidth 0\n    pack $f.oc.oc1\n    ttk::button $f.oc.oc1.bu -text \"invert orientation \\n of selected trig\" -command {Ng_STLDoctor invertselectedtrig; redraw }\n    ttk::button $f.oc.oc1.bu2 -text \"orient after \\n selected trig\" -command {Ng_STLDoctor orientafterselectedtrig; redraw }\n    \n\n    ttk::button $f.oc.oc1.toperr -text \"mark inconsistent triangles\" -command {Ng_STLDoctor marktoperrortrigs; redraw }\n    ttk::button $f.oc.oc1.deltrig -text \"delete selected triangle\" -command {Ng_STLDoctor deleteselectedtrig; redraw }\n    ttk::button $f.oc.oc1.geosmooth -text \"geometric smoothing\" -command {Ng_STLDoctor smoothgeometry; redraw }\n    \n    grid $f.oc.oc1.bu x $f.oc.oc1.bu2 -sticky nw -padx 4 -pady 4\n    grid $f.oc.oc1.toperr - x -sticky nw -padx 4 -pady 4\n    grid $f.oc.oc1.deltrig - x -sticky nw -padx 4 -pady 4\n    grid $f.oc.oc1.geosmooth - x -sticky nw -padx 4 -pady 4\n\n\n\n\n\n    # EDGES ***********************\n    set f $wd.nb.edges\n\n\n    ttk::frame $f.be -relief groove -borderwidth 3 \n    pack $f.be -fill x\n    \n    #scale $f.be.sc -orient horizontal -length 200 -from 0 -to 100 \\\n\t#-resolution 0.5\n    ttk::frame $f.be.frame\n    pack $f.be.frame -ipady 4 -pady 4\n    ttk::label $f.be.frame.lab -text \"build edges with yellow angle:\";\n    ttk::scale $f.be.frame.scale -orient horizontal -length 200 -from 0 -to 200 \\\n    -variable stloptions.yangle -takefocus 0 -command \"roundscale $f.be.frame.scale 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\"\n    ttk::entry $f.be.frame.entry -textvariable stloptions.yangle -width 5 \\\n    -validatecommand \"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale cget -from] [$f.be.frame.scale cget -to] %P 1\" \\\n    -invalidcommand \"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\" -validate focus\n\tgrid $f.be.frame.lab - -sticky nw -padx 4\n    grid $f.be.frame.scale $f.be.frame.entry -sticky nw -padx 4    \n    \n    \n    \n    #$f.be.sc config -variable stloptions.yangle \n    #$f.be.sc config -command { Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw }\n    ttk::label $f.be.frame.lab2 -text \"continue edges with yellow angle:\";\n#    scale $f.be.sc2 -orient horizontal -length 200 -from 0 -to 100 \\\n\t-resolution 0.5\n    ttk::scale $f.be.frame.scale2 -orient horizontal -length 200 -from 0 -to 100 \\\n    -variable stloptions.contyangle -takefocus 0 -command \"roundscale $f.be.frame.scale2 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\"\n    ttk::entry $f.be.frame.entry2 -textvariable stloptions.contyangle -width 5 \\\n    -validatecommand \"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale2 cget -from] [$f.be.frame.scale2 cget -to] %P 1\" \\\n    -invalidcommand \"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\" -validate focus\n\n\tgrid $f.be.frame.lab2 - -sticky nw -padx 4\n    grid $f.be.frame.scale2 $f.be.frame.entry2 -sticky nw -padx 4    \n    \n    #$f.be.sc2 config -variable stloptions.contyangle \n    #$f.be.sc2 config -command { Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw }\n\n\n\n    ttk::button $f.be.frame.buildedges -text \"Build Edges\" -command {Ng_STLDoctor buildedges; redraw}\n    grid $f.be.frame.buildedges - -sticky n -padx 4 -pady 4\n    #pack $f.be.lab $f.be.sc $f.be.lab2 $f.be.sc2 $f.be.buildedges -expand yes\n\n    ttk::frame $f.se -relief groove -borderwidth 3\n    pack $f.se -fill x\n    ttk::checkbutton $f.se.bu -text \"show excluded\" \\\n\t-variable stldoctor.showexcluded \\\n\t-command {Ng_STLDoctor; redraw}\n    pack $f.se.bu \n\n    # edgeselectmode ******\n\n    set edgeselmodevals { 0 1 2 3 4 }\n    set edgeselmodelabs(0) \"no change\" \n    set edgeselmodelabs(1) \"undefined\" \n    set edgeselmodelabs(2) \"confirmed\" \n    set edgeselmodelabs(3) \"candidate\"\n    set edgeselmodelabs(4) \"excluded\"\n\n    # tixOptionMenu $f.edgeselmode -label \"Double Click sets edge :\" \\\n\t# -options {\n\t    # label.width  19\n\t    # label.anchor e\n\t    # menubutton.width 15\n\t# } \n\n    # foreach edgeselmodev $edgeselmodevals {\n\t# $f.edgeselmode add command $edgeselmodev -label $edgeselmodelabs($edgeselmodev)\n    # }\n    # $f.edgeselmode config -variable stldoctor.edgeselectmode\n    # $f.edgeselmode config -command { Ng_STLDoctor }\n    global stldoctor.edgeselectmode    \n    # pack $f.edgeselmode\n\n    ttk::frame $f.scaleframe -relief groove -borderwidth 0\n    pack $f.scaleframe -ipadx 4 -pady 4 -expand yes\n    ttk::label  $f.scaleframe.dblcedgelab -text \"Double Click sets edge :\"\n    ttk::menubutton $f.scaleframe.dblcledgebut -menu $f.scaleframe.dblcledgem -text \"coarse\" -width 16\n\n    menu $f.scaleframe.dblcledgem  -tearoff 0\n\tforeach selectmode { 0 1 2 3 4 } {\n\t$f.scaleframe.dblcledgem add command -label $edgeselmodelabs($selectmode) \\\n    -command \"set stldoctor.edgeselectmode $selectmode ; $f.scaleframe.dblcledgebut configure -text \\\"$edgeselmodelabs($selectmode)\\\"\"\n\t}\n    $f.scaleframe.dblcledgem invoke $edgeselmodelabs(${stldoctor.edgeselectmode})                \n    grid $f.scaleframe.dblcedgelab $f.scaleframe.dblcledgebut -sticky n -ipadx 4\n\n    \n    \n    \n    # edge buttons\n\n    ttk::frame $f.edg -relief groove -borderwidth 3\n    pack $f.edg -fill x -ipadx 4 -ipady 4\n\n#    checkbutton $f.edg.bu -text \"use external edges\" \\\n#\t-variable stldoctor.useexternaledges \\\n#\t-command {Ng_STLDoctor; redraw}\n#   pack $f.edg.bu -expand yes\n\n\n    ttk::frame $f.edg.f0\n    pack $f.edg.f0\n    ttk::button $f.edg.f0.confirmedge -text \"confirm\" -command {Ng_STLDoctor confirmedge; redraw}\n    ttk::button $f.edg.f0.candidateedge -text \"candidate\" -command {Ng_STLDoctor candidateedge; redraw}\n    ttk::button $f.edg.f0.excludeedge -text \"exclude\" -command {Ng_STLDoctor excludeedge; redraw}\n    ttk::button $f.edg.f0.undefinededge -text \"undefined\" -command {Ng_STLDoctor undefinededge; redraw}\n    pack $f.edg.f0.confirmedge $f.edg.f0.candidateedge $f.edg.f0.excludeedge $f.edg.f0.undefinededge  -side left\n\n    ttk::frame $f.edg.fa\n    pack $f.edg.fa\n    ttk::button $f.edg.fa.setallundefined -text \"all undefined\" -command {Ng_STLDoctor setallundefinededges; redraw}\n    ttk::button $f.edg.fa.erasecandidates -text \"candidates to undefined\" -command {Ng_STLDoctor erasecandidateedges; redraw}\n    pack $f.edg.fa.setallundefined $f.edg.fa.erasecandidates -side left\n\n\n    ttk::frame $f.edg.fb\n    pack $f.edg.fb\n    ttk::button $f.edg.fb.confirmcandidates -text \"candidates to confirmed\" -command {Ng_STLDoctor confirmcandidateedges; redraw}\n    ttk::button $f.edg.fb.confirmedtocandidates -text \"confirmed to candidates\" -command {Ng_STLDoctor confirmedtocandidateedges; redraw}\n    pack $f.edg.fb.confirmcandidates $f.edg.fb.confirmedtocandidates -side left\n\n    ttk::frame $f.edg.f1\n    ttk::frame $f.edg.f2\n    ttk::frame $f.edg.f3\n    ttk::frame $f.edg.f4\n    pack $f.edg.f1 $f.edg.f2 $f.edg.f3 $f.edg.f4\n\n    ttk::button $f.edg.f1.exportedges -text \"export edges\" -command {Ng_STLDoctor exportedges}\n    ttk::button $f.edg.f1.importedges -text \"import edges\" -command {Ng_STLDoctor importedges; redraw}\n    ttk::button $f.edg.f1.saveedgedata -text \"save edgedata\" \\\n\t-command { \n\t    set types {\n\t\t{\"Netgen Edgedata\"   {.ned} } \n\t    }\n\t    set file [tk_getSaveFile -filetypes $types -defaultextension \".ned\"]\n\t    if {$file != \"\"} {\n\t\tNg_STLDoctor saveedgedata $file\n\t}\n    }\n\n    ttk::button $f.edg.f1.loadedgedata -text \"load edgedata\" \\\n\t-command { \n\t    set types {\n\t\t{\"Netgen Edgedata\"  {.ned} }\n\t    }\n\t    set file [tk_getOpenFile -filetypes $types -defaultextension \".ned\"]\n\t    if {$file != \"\"} {\n\t\tNg_STLDoctor loadedgedata $file \n\t\tputs \"loading done\"\n\t\t\n\t\tredraw\n\t\t\n#\t\twm title . [concat \"NETGEN - \" $file]\n\t    }\n\t} \n\n    ttk::button $f.edg.f1.importAVLedges -text \"import AVL edges\" \\\n\t-command {\n\t    set types {{\"Edge file\"  {.edg }}}\n\n\t    set file [tk_getOpenFile -filetypes $types -defaultextension \".edg\"]\n\t    if {$file != \"\"} {\n\t\tNg_STLDoctor importexternaledges $file; \n\t    }\n\t}\n\n    pack $f.edg.f1.importAVLedges $f.edg.f1.loadedgedata $f.edg.f1.saveedgedata -side left\n\n#    button $f.edg.f1.buildedges -text \"build external edges\" -command {Ng_STLDoctor buildexternaledges; redraw}\n    ttk::frame $f.edg2 -relief groove -borderwidth 3\n    pack $f.edg2 -fill x\n\n\n#    button $f.edg2.addlonglines -text \"make long lines candidates (% of diam)\" -command {Ng_STLDoctor addlonglines; redraw}\n    ttk::label $f.edg2.lab -text \"length (%):\"\n    scale $f.edg2.sc -orient horizontal -length 200 -from 0 -to 100 \\\n\t-resolution 0.5 \\\n        -variable stldoctor.longlinefact \n\n #   button $f.edg2.deletedirtyedges -text \"make dirty edges candidates\" -command {Ng_STLDoctor deletedirtyedges; redraw}\n    ttk::button $f.edg2.undoedge -text \"undo last edge change\" -command {Ng_STLDoctor undoedgechange; redraw}\n    \n #   pack $f.edg2.addlonglines $f.edg2.deletedirtyedges -expand yes\n #   pack $f.edg2.lab $f.edg2.sc -side left\n    pack $f.edg2.undoedge -expand yes\n\n\n\n    # NORMALS ***********************\n    set f $wd.nb.normals\n\n    ttk::frame $f.dt -relief groove -borderwidth 3\n    pack $f.dt -fill x\n    ttk::label $f.dt.lab -text \"dirty triangle factor\";\n    ttk::entry $f.dt.ent -width 5 \\\n\t-textvariable stldoctor.dirtytrigfact -validatecommand \"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 3\" \\\n    -invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n    pack $f.dt.ent $f.dt.lab -side left -expand yes -pady 8\n\n    ttk::frame $f.srt -relief groove -borderwidth 3\n    pack $f.srt -fill x\n    ttk::button $f.srt.bu -text \"smooth reverted triangles geometric\" -command {Ng_STLDoctor smoothrevertedtrigs; redraw }\n    ttk::entry $f.srt.ent -width 5 \\\n\t-textvariable stldoctor.smoothangle -validatecommand \"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 2\" \\\n    -invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n    pack $f.srt.ent $f.srt.bu -side left  -expand yes -pady 8\n\n    ttk::frame $f.bdt -relief groove -borderwidth 3\n    pack $f.bdt -fill x\n    ttk::button $f.bdt.bu -text \"mark dirty triangles\" -command {Ng_STLDoctor markdirtytrigs; redraw }\n    ttk::button $f.bdt.bu2 -text \"smooth dirty triangles normal\" -command {Ng_STLDoctor smoothdirtytrigs; redraw }\n    pack $f.bdt.bu $f.bdt.bu2 -side left  -expand yes -pady 8\n\n    \n    ttk::frame $f.sno -relief groove -borderwidth 3\n    pack $f.sno -fill x\n    ttk::frame $f.sno.snoframe -borderwidth 0\n    #ttk::label $f.sno.labrough -text \"rough\"\n    #scale $f.sno.scsmooth -orient horizontal -length 100 -from 0 -to 0.8 \\\n\t-resolution 0.01 -variable stldoctor.smoothnormalsweight \\\n\t-command { Ng_SetSTLParameters }\n    #ttk::label $f.sno.labsmooth -text \"smooth\"\n    ttk::button $f.sno.smoothnormals -text \"smooth normals\" -command { Ng_STLDoctor smoothnormals; redraw}\n\n    ttk::scale $f.sno.snoframe.scale -orient horizontal -length 100 -from 0.0 -to 0.8 \\\n    -variable stldoctor.smoothnormalsweight -takefocus 0 -command \"roundscale $f.sno.snoframe.scale 2;Ng_SetSTLParameters\"\n    ttk::entry $f.sno.snoframe.entry -textvariable stldoctor.smoothnormalsweight -width 4 \\\n    -validatecommand \"Ng_SetSTLParameters;my_validate %W [$f.sno.snoframe.scale cget -from] [$f.sno.snoframe.scale cget -to] %P 2\" \\\n    -invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n    ttk::label $f.sno.snoframe.labrough -text \"rough\"\n    ttk::label $f.sno.snoframe.labsmooth -text \"smooth\"\n\tgrid $f.sno.snoframe.labrough $f.sno.snoframe.scale $f.sno.snoframe.labsmooth $f.sno.snoframe.entry -sticky nw -padx 4    \n    \n    #pack $f.sno.labrough $f.sno.scsmooth $f.sno.labsmooth $f.sno.smoothnormals -side left -padx 5\n    pack $f.sno.snoframe $f.sno.smoothnormals -side left -padx 5 -pady 8\n    ttk::frame $f.no -relief groove -borderwidth 3\n    pack $f.no -fill x\n\n    ttk::button $f.no.marknonsmoothnormals -text \"mark non-smooth triangles\" -command {Ng_STLDoctor marknonsmoothnormals; redraw}\n    ttk::button $f.no.calcnormals -text \"calculate normals from geometry\" -command {Ng_STLDoctor calcnormals; redraw}\n\n    pack $f.no.marknonsmoothnormals $f.no.calcnormals -expand yes -pady 8\n\n\n    # ADVANCED **************************\n    set f $wd.nb.advanced\n\n\n    ttk::frame $f.sc\n    pack $f.sc -fill x\n    ttk::checkbutton $f.sc.bu -text \"spiral check\" \\\n\t-variable stldoctor.spiralcheck \\\n\t-command {Ng_STLDoctor;}    \n    ttk::checkbutton $f.sc.bu2 -text \"cone check\" \\\n\t-variable stldoctor.conecheck \\\n\t-command {Ng_STLDoctor;}    \n    pack $f.sc.bu $f.sc.bu2\n\n    \n    #tixControl $f.gtol -label \"load-geometry tolerance factor\" -integer false \\\n\t# -variable stldoctor.geom_tol_fact \\\n\t# -options {\n\t#    entry.width 8\n\t#    label.width 30\n\t#    label.anchor e\n\t#}\t\n    ttk::label $f.gtol_lbl -text \"LoadSTL tolerance factor\"\n    ttk::spinbox $f.gtol -from 1e-15 -to 0.001 -textvariable stldoctor.geom_tol_fact -width 8\n    pack $f.gtol_lbl $f.gtol\n\n    ttk::button $f.adap -text \"Apply\" -command {\n\tNg_STLDoctor; \n    }\n    pack $f.adap -expand yes\n\n#    frame $f.gtol -relief groove -borderwidth 3\n#    pack $f.gtol -fill x\n#    label $f.gtol.lab -text \"Geometry-Load-Tolerance-Factor\";\n#    entry $f.gtol.ent -width 5 -relief sunken \\\n#\t-textvariable stldoctor.geom_tol_fact\n#   pack $f.gtol.lab $f.gtol.ent -side left -expand yes\n\n    #*******************************    \n    wm withdraw $wd\n    wm geom $wd +100+100\n    wm deiconify $wd\n    wm title $wd \"STL Doctor\"\n\n    focus $wd\n}\n}\n\n\n\n\n\nproc meshdoctordialog { } {\n\n    set w .meshdoc_dlg\n    global meshdoctor.active\n\n    if {[winfo exists .meshdoc_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n\tset meshdoctor.active 1\n\tNg_MeshDoctor;\n\n\n\tttk::frame $w.vis -relief groove -borderwidth 3\n\tpack $w.vis\n\n\tttk::checkbutton $w.vis.showfilledtrigs -text \"Show filled triangles\" \\\n\t-variable viewoptions.drawfilledtrigs \\\n\t-command { Ng_SetVisParameters; redraw }\n\t\n\tttk::checkbutton $w.vis.showedges -text \"Show edges\" \\\n\t-variable viewoptions.drawedges \\\n\t-command { Ng_SetVisParameters; redraw }\n\t\n\n\tttk::checkbutton $w.vis.showoutline -text \"Show Triangle Outline\" \\\n\t-variable viewoptions.drawoutline \\\n\t-command { Ng_SetVisParameters; redraw }\n\n\tpack $w.vis.showfilledtrigs  $w.vis.showoutline $w.vis.showedges\n\n    ttk::frame $w.markedgedist\n    ttk::label $w.markedgedist.l -text \"Mark edge dist: \"\n    ttk::spinbox $w.markedgedist.s -from 0 -to 999 -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n    -invalidcommand \"my_invalidspinbox %W\" -command {Ng_MeshDoctor markedgedist ${meshdoc.markedgedist};redraw} -textvariable meshdoc.markedgedist\n    #pack $f.grading -fill x\n    pack $w.markedgedist.l $w.markedgedist.s -side left\n    \n\t# tixControl $w.markedgedist -label \"Mark edge dist: \" -integer true \\\n\t    # -min 0 -max 999  \\\n\t    # -variable meshdoc.markedgedist \\\n\t    # -options {\n\t\t# entry.width 3\n\t\t# label.width 20\n\t\t# label.anchor e\n\t    # } \\\n\t    # -command {\n\t\t# Ng_MeshDoctor markedgedist ${meshdoc.markedgedist}\n\t\t# redraw\n\t    # }\n\tpack $w.markedgedist\n\t\n\tttk::button $w.deledge -text \"Delete marked segments\" -command {\n\t    Ng_MeshDoctor deletemarkedsegments\n\t    redraw\n\t}\n\tpack $w.deledge\n\t\n\tttk::button $w.close -text \"Close\" -command { \n\t    set meshdoctor.active 0;\n\t    Ng_MeshDoctor;\n\t    destroy .meshdoc_dlg \n\t}\n\tpack $w.close -expand yes\n\t\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Mesh Doctor\"\n    }\n}\n\n\n\n#\n#  Quality viewer\n#\n\nproc qualityviewdialog { show } {\n\n    set w .qualityview_dlg\n    \n    if {[winfo exists .qualityview_dlg] == 1} {\n\n\tif { $show == 1 } {\n\t    wm withdraw .qualityview_dlg\n\t    wm deiconify $w\n\t    focus $w \n\t} {\n\t    wm withdraw $w\n\t}\n    } {\n\ttoplevel $w\n\t\n\tset c $w.c\n\n\tcanvas $c -relief raised -width 450 -height 300\n\tpack $w.c -side top -fill x\n\n\tset plotFont {Helvetica 12}\n\tset smallFont {Helvetica 12}\n\n\t$c create line 100 250 400 250 -width 2\n\t$c create line 100 250 100 50 -width 2\n\n\tfor {set i 0} {$i <= 10} {incr i} {\n\t    set x [expr {100 + ($i*30)}]\n\t    $c create line $x 250 $x 245 -width 2\n\t    if { [expr {$i % 2}] == 0 } {\n\t\t$c create text $x 254 -text [format %1.1f [expr 0.1*$i]] -anchor n -font $plotFont\n\t    }\n\t}\n\n\tglobal qualbar\n\tglobal qualbarnull\n\tglobal qualbaraxis\n\n\tfor {set i 0} {$i <= 5} {incr i} {\n\t    set y [expr {250 - ($i*40)}]\n\t    $c create line 100 $y 105 $y -width 2\n\n#            global qualbaraxis($i)\n\t    set qualbaraxis($i) \\\n\t\t[$c create text 96 $y -text [expr $i*50].0 -anchor e -font $plotFont]\n\t}\n\n\tfor {set i 0} {$i < 20} {incr i} {\n\t    set x1 [expr {100 + ($i*15) + 2}]\n\t    set x2 [expr {$x1+10}]\n\t    set y [expr {250 - 10 * $i}]\n#\t    global qualbar($i)\n\t    set qualbar($i) [$c create rectangle $x1 250 $x2 245 -fill blue]\n\t    set qualbarnull($i) [$c create text [expr {($x1+$x2)/2}] 245 -text 0 -anchor s -font $smallFont -fill blue]\t\n\t}\n\n\tframe $w.bu\n\tpack $w.bu\n\t# -fill x\n\t\n\tttk::button $w.close -text \"Close\" \\\n\t    -command { \n\t\twm withdraw .qualityview_dlg\n\t\tset viewqualityplot 0\n\t    }\n\tpack $w.close\n    \n\t\n\tif { $show == 1 } {\n\t    wm withdraw $w\n\t    wm geom $w +100+100\n\t    wm deiconify $w\n\t    wm title $w \"Mesh Quality\"\n\t    focus $w\n\t}\n    }\n}\n\n\n\n\n\n\n\n\n\n\n#\n#  Quality viewer\n#\nproc memusedialog { show } {\n\n    set w .memuse_dlg\n    \n    if {[winfo exists .memuse_dlg] == 1} {\n\n\tif { $show == 1 } {\n\t    wm withdraw .memuse_dlg\n\t    wm deiconify $w\n\t    focus $w \n\t} {\n\t    wm withdraw $w\n\t}\n    } {\n\ttoplevel $w\n\t\n\tset c $w.c\n\n\tcanvas $c -relief raised -width 600 -height 300\n\tpack $w.c -side top -fill x\n\n\tset plotFont {Helvetica 18}\n\tset smallFont {Helvetica 12}\n\n\n\tglobal memmark\n\tfor {set i 0} {$i < 512} { incr i } {\n\t    set memmark($i) [$c create line [expr 50+$i] 50 [expr 50+$i] 70 -fill blue]\n\t}\n\n\n\tset plotFont {Helvetica 18}\n\tset smallFont {Helvetica 12}\n\n\t$c create text 50 90 -text \"0 GB\" -anchor n -font $plotFont\n\t$c create text 178 90 -text \"1 GB\" -anchor n -font $plotFont\n\t$c create text 306 90 -text \"2 GB\" -anchor n -font $plotFont\n\t$c create text 434 90 -text \"3 GB\" -anchor n -font $plotFont\n\t$c create text 562 90 -text \"4 GB\" -anchor n -font $plotFont\n\n\n\tttk::frame $w.bu\n\tpack $w.bu\n\t# -fill x\n\t\n\tttk::button $w.close -text \"Close\" \\\n\t    -command { \n\t\twm withdraw .memuse_dlg\n\t\tset memuseplot 0\n\t    }\n\tpack $w.close\n\t\n\tif { $show == 1 } {\n\t    wm withdraw $w\n\t    wm geom $w +100+100\n\t    wm deiconify $w\n\t    wm title $w \"Memory Usage\"\n\t    focus $w\n\t}\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#\n#  STL INFO dialog\n#\nproc STLinfodialog { show } {\n\n    set w .STLinfo_dlg\n    \n    if {[winfo exists .STLinfo_dlg] == 1} {\n\n\tif { $show == 1 } {\n\t    wm withdraw .STLinfo_dlg\n\t    wm deiconify $w\n\t    focus $w \n\t} {\n\t    wm withdraw $w\n\t}\n    } {\n\ttoplevel $w\n\t\n\tset c $w.c\n\n\tcanvas $c -relief raised -width 450 -height 300\n\tpack $w.c -side top -fill x\n\n\tset plotFont {Helvetica 18}\n\tset smallFont {Helvetica 12}\n\n\t$c create line 100 250 400 250 -width 2\n\t$c create line 100 250 100 50 -width 2\n\n\tttk::frame $w.bu\n\tpack $w.bu\n\t# -fill x\n\t\n\tttk::button $w.close -text \"Close\" \\\n\t    -command { \n\t\twm withdraw .STLinfo_dlg\n\t\t#set STLinfoopen 0\n\t    }\n\tpack $w.close\n    \n\t\n\tif { $show == 1 } {\n\t    wm withdraw $w\n\t    wm geom $w +100+100\n\t    wm deiconify $w\n\t    wm title $w \"STL Geometry Info\"\n\t    focus $w\n\t}\n    }\n}\n\n\n\n\n\n\n\n\nproc logwindow { } {\n    set w .logwindow\n    \n    if {[winfo exists .logwindow] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n\ttext $w.edit -yscroll \"$w.scrolly set\" -setgrid 1 -height 12\n\tscrollbar $w.scrolly -command \"$w.edit yview\"\t\n\tpack $w.edit -side left -fill both -expand 1\n\tpack $w.scrolly -side left -fill both -expand 0\n\n\t.logwindow.edit insert end \"Netgen Log Window\\n\"\n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Netgen Log\"\t\n\tfocus $w\n    }\n}\n# logwindow\n\n\n\n# Opens a window with a table. tablevar is a list, the first entry is the title, the second the number of rows, the third the number of columns,\n# then the entries follow.\n\nproc printtable { tablevar } {\n    set w newtcltable\n    while {[winfo exists .$w] == 1} {set w 1$w}\n    set w .$w\n    toplevel $w\n    for {set i 0} {$i < [lindex $tablevar 2]} { incr i } {\n\tframe $w.col$i\n\tfor {set j 0} {$j < [lindex $tablevar 1]} { incr j } {\n\t    frame $w.col$i.row$j\n\t    message $w.col$i.row$j.txt -aspect 10000000 -text [lindex $tablevar [expr 3+[lindex $tablevar 2]*$j+$i]]\n\t    pack $w.col$i.row$j.txt\n\t    pack $w.col$i.row$j -side top\n\t}\n\tpack $w.col$i -side left\n    }\n    wm withdraw $w\n    wm geom $w +200+100; wm deiconify $w\n    wm title $w [lindex $tablevar 0]\n    focus $w\n}\n\n\nset latestwarning 0\n\n\nproc printwarning { textvar } {\n    global latestwarning\n    set latestwarning $textvar\n    set w warning\n    while {[winfo exists .$w] == 1} {set w 1$w}\n    set w .$w\n    toplevel $w\n    message $w.mes -aspect 2000 -text \"WARNING:\\n$textvar\"\n    ttk::button $w.done -text \"Done\" -command \"destroy $w\"\n    pack $w.mes\n    pack $w.done\n    wm withdraw $w\n    wm deiconify $w\n    wm title $w \"Warning\"\n    focus $w\n}\n\n\nproc printlatestwarning { } { \n    global latestwarning \n    if {$latestwarning != 0} {printwarning $latestwarning}\n}\n\n\n\n# proc runtestdialog { } {\n    # source $::ngdir/ngshell.tcl\n    # set w .runtest_dlg\n    \n    # if {[winfo exists .runtest_dlg] == 1} {\n\t# wm withdraw $w\n\t# wm deiconify $w\n\n\t# focus $w \n    # } {\n\t# toplevel $w\n\n# # in2d testing #\n\t# frame $w.in2dframe \n\t# pack $w.in2dframe\n\n        # set in2dlogfile \"\"\n \t# tixLabelEntry $w.in2dframe.ent -label \"in2d log-file: console if empty\"  \\\n \t    # -labelside top \\\n \t    # -options {  \n \t\t# entry.textVariable in2dlogfile\n \t\t# entry.width 35\n \t\t# label.width 25\n \t\t# label.anchor w\n \t    # }\t\n \t# button $w.in2dframe.btn -text \"Browse\" -command {\n\t    # set types { { \"Log file\"   {.log}\t} }\n\t    # set in2dlogfile [tk_getOpenFile -filetypes $types -initialfile $in2dlogfile]\n\t# }\n \t# button $w.in2dframe.test -text \"Test in2d meshing\" -command { ngtest in2d $in2dlogfile }\n\n        \n \t# pack $w.in2dframe.test -side left -anchor s -padx 4 -pady 4\n \t# pack $w.in2dframe.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n \t# pack $w.in2dframe.btn -side left -anchor s -padx 4 -pady 4\n\n        \n# # geo testing #\n\t# frame $w.geoframe \n\t# pack $w.geoframe\n\n        # set geologfile \"\" \n \t# tixLabelEntry $w.geoframe.ent -label \"geo log-file: console if empty\"  \\\n \t    # -labelside top \\\n \t    # -options {  \n \t\t# entry.textVariable geologfile\n \t\t# entry.width 35\n \t\t# label.width 25\n \t\t# label.anchor w\n \t    # }\t\n \t# button $w.geoframe.btn -text \"Browse\" -command {\n\t    # set types { { \"Log file\"   {.log}\t} }\n\t    # set geologfile [tk_getOpenFile -filetypes $types -initialfile $geologfile]\n\t# }\n \t# button $w.geoframe.test -text \"Test geo meshing\" -command { ngtest geo $geologfile }\n\n        \n \t# pack $w.geoframe.test -side left -anchor s -padx 4 -pady 4\n \t# pack $w.geoframe.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n \t# pack $w.geoframe.btn -side left -anchor s -padx 4 -pady 4\n\n# # stl testing #\n\t# frame $w.stlframe \n\t# pack $w.stlframe\n\n        # set stllogfile \"\"\n \t# tixLabelEntry $w.stlframe.ent -label \"stl log-file: console if empty\"  \\\n \t    # -labelside top \\\n \t    # -options {  \n \t\t# entry.textVariable stllogfile\n \t\t# entry.width 35\n \t\t# label.width 25\n \t\t# label.anchor w\n \t    # }\t\n \t# button $w.stlframe.btn -text \"Browse\" -command {\n\t    # set types { { \"Log file\"   {.log}\t} }\n\t    # set stllogfile [tk_getOpenFile -filetypes $types -initialfile $stllogfile]\n\t# }\n \t# button $w.stlframe.test -text \"Test stl meshing\" -command { ngtest stl $stllogfile }\n\n        \n \t# pack $w.stlframe.test -side left -anchor s -padx 4 -pady 4\n \t# pack $w.stlframe.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n \t# pack $w.stlframe.btn -side left -anchor s -padx 4 -pady 4\n\n# # pde testing #\n\t# frame $w.pdeframe \n\t# pack $w.pdeframe\n\n        # set pdelogfile \"\"\n \t# tixLabelEntry $w.pdeframe.ent -label \"pde log-file: console if empty\"  \\\n \t    # -labelside top \\\n \t    # -options {  \n \t\t# entry.textVariable pdelogfile\n \t\t# entry.width 35\n \t\t# label.width 25\n \t\t# label.anchor w\n \t    # }\t\n \t# button $w.pdeframe.btn -text \"Browse\" -command {\n\t    # set types { { \"Log file\"   {.log}\t} }\n\t    # set pdelogfile [tk_getOpenFile -filetypes $types -initialfile $pdelogfile]\n\t# }\n \t# button $w.pdeframe.test -text \"Test ngsolve pde's\" -command { ngtest pde $pdelogfile }\n\n        \n \t# pack $w.pdeframe.test -side left -anchor s -padx 4 -pady 4\n \t# pack $w.pdeframe.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n \t# pack $w.pdeframe.btn -side left -anchor s -padx 4 -pady 4\n \n\t# wm title $w \"Testing\"\n\t# focus .runtest_dlg \n    # }\n# }\n\n"
  },
  {
    "path": "ng/drawing.tcl",
    "content": "#\n#  Creates a drawing frame, and binds mouse events\n#\nset oldmousex 0\nset oldmousey 0\n#\n\n\n# if { 1 } {\n\n# use this one for Togl 2.0\n#if {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false }] } {\n\n# if {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false -create init  -display draw -reshape reshape  }] } {    \n#   puts \"no OpenGL\" \n# } {\n\nset toglversion [Ng_GetToglVersion]\nputs \"togl-version : $toglversion\"\n\nset toglok 0\nif { [Ng_GetToglVersion] == 2 } {\n    # Togl 2.x\n    if {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false  -create init  -display draw -reshape reshape }] } {    \n        puts \"no OpenGL\" \n    } {\n        # puts \"have Togl 2.1\"        \n        set toglok 1\n    }\n}\n\nif { $toglok == 1} {\n    \n    #\n    pack .ndraw -expand true -fill both -padx 0 -pady 0\n    catch { tkdnd::drop_target register .ndraw DND_Files }\n    #\n    bind .ndraw <Button-1> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <Button-2> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <Button-3> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <B1-Motion> {\n\tNg_MouseMove $oldmousex $oldmousey %x %y $drawmode\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n\n    bind .ndraw <Double-1> {\n\tNg_MouseDblClick %x %y\n\t.ndraw render\n\tif { [winfo exists .bcprop_dlg] } { bcpropdialog }\n\tif { [winfo exists .surfacemeshsize_dlg] } { surfacemeshsizedialog }\n\tif { [winfo exists .fieldlines_dlg] } { fieldlinesdialog }\n    }\n\n    bind .ndraw <B2-Motion> {\n\tNg_MouseMove $oldmousex $oldmousey %x %y move\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n\n    bind .ndraw <B3-Motion> {\n        if { $tcl_platform(os) == \"Darwin\" } {\n            Ng_MouseMove $oldmousex $oldmousey %x %y move\n        } { \n            Ng_MouseMove $oldmousex $oldmousey %x %y zoom\n        }\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n    \n    bind .ndraw <Alt-B2-Motion> {\n        Ng_MouseMove $oldmousex $oldmousey %x %y Move2d\n        .ndraw render\n        set oldmousex %x; set oldmousey %y;\n    }\n    \n    bind .ndraw <Alt-B3-Motion> {\n        Ng_MouseMove $oldmousex $oldmousey %x %y Zoom2d\n        .ndraw render\n        set oldmousex %x; set oldmousey %y;\n    }\n}\n\n\nproc popupcheckredraw { vari { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n        #        puts \"popup-redraw $vari\"\n\tNg_Vis_Set parameters\n\tredraw\n    }\n}\nproc popupcheckredraw2 { vari boolvar { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n\tNg_SetVisParameters\n\tNg_Vis_Set parameters\n\tif { $boolvar == 1 } { redraw }\n\tNg_SetVisParameters\n    }\n}\nproc popupcheckredraw3 { vari { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n\tNg_Vis_Set parameters\n    }\n}\n\n\n\n\nproc redraw { {x 0} } {\n    if {[winfo exists .ndraw]} { .ndraw render } \n}\n\n\n\nbind . <Left> { Ng_MouseMove 0 0 -10 0 rotate; redraw }\nbind . <Right> { Ng_MouseMove 0 0 10 0 rotate; redraw }\nbind . <Up> { Ng_MouseMove 0 0 0 -10 rotate; redraw }\nbind . <Down> { Ng_MouseMove 0 0 0 10 rotate; redraw }\nbind . <Shift-Left> { Ng_MouseMove 0 0 -10 0 move; redraw }\nbind . <Shift-Right> { Ng_MouseMove 0 0 10 0 move; redraw }\nbind . <Shift-Up> { Ng_MouseMove 0 0 0 -10 move; redraw }\nbind . <Shift-Down> { Ng_MouseMove 0 0 0 10 move; redraw }\nbind . <Control-Up> { Ng_MouseMove 0 0 0 -10 zoom; redraw }\nbind . <Control-Down> { Ng_MouseMove 0 0 0 10 zoom; redraw }\n\nbind . <Button-4> \\\n   {event generate [focus -displayof %W] <MouseWheel> -delta  120}\n\nbind . <Button-5> \\\n   {event generate [focus -displayof %W] <MouseWheel> -delta -120}\n\nbind . <MouseWheel> { Ng_MouseMove 0 0 0 [expr {%D/-5}] zoom; redraw }\n\n\n\n# Drop callbacks:\nbind .ndraw <<Drop:DND_Files>> {\n  #tk_messageBox -message \"Dropped files: \\\"[join %D {, }]\\\"\"\n  set filename [join %D \" \"]\n\n  #%W state !active  \n  set index [string last . $filename]\n  #tk_messageBox -message $index\n  set type [string range $filename $index+1 end]\n  # tk_messageBox -message $type\n  set ispde [string match -nocase $type \"pde\"]\n  set isgeo [expr max([string match -nocase $type \"geo\"],[string match -nocase $type \"in2d\"])]\n  set ismesh [expr max([string match -nocase $type \"vol\"],[string match -nocase $type \"vol.gz\"])]\n  set ispy [string match -nocase $type \"py\"]\n  if {$ispde == 1} {\n      AddRecentNGSFile $filename;\n      NGS_LoadPDE  $filename;\n      SetNumProcHelpMenu\n      set selectvisual mesh;\n      Ng_SetVisParameters\n  }\n  if {$ispy == 1} {\n      AddRecentPYNGSFile $filename;\n      NGS_LoadPy  $filename;\n  }\n  if {$isgeo == 1} {\n\t    AddRecentFile $filename;\n\t    Ng_LoadGeometry $filename;\n\t    Ng_ParseGeometry\n\t    set selectvisual geometry\n\t    Ng_SetVisParameters\n\t    redraw\n\t    wm title . [concat \"$progname - \" $filename]\n\t    set dirname [file dirname $filename]\n\t    set basefilename [file tail [file rootname $filename]]\n\t}\n\tif {$ismesh == 1} {\n\t    AddRecentMeshFile $filename;\n\t    Ng_LoadMesh $filename; \n\t    set selectvisual mesh\n\t    Ng_SetVisParameters\n\t    redraw\n\t    Ng_ReadStatus; \n\t    wm title . [concat \"$progname - \" %D] \n\t    set dirname [file dirname %D]\n\t    set basefilename [file tail [file rootname %D]]\n\t}\n  return %A\n}\n"
  },
  {
    "path": "ng/drawing_togl17.tcl",
    "content": "#\n#  Creates a drawing frame, and binds mouse events\n#\nset oldmousex 0\nset oldmousey 0\n#\n\n\n# if { 1 } {\n\n\nif {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false }] } {\n  puts \"no OpenGL\" \n} {\n    #\n    pack .ndraw -expand true -fill both -padx 10 -pady 10\n    catch { tkdnd::drop_target register .ndraw DND_Files }\n    #\n    bind .ndraw <Button-1> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <Button-2> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <Button-3> {\n\tset oldmousex %x; set oldmousey %y;\n    }\n    bind .ndraw <B1-Motion> {\n\tNg_MouseMove $oldmousex $oldmousey %x %y $drawmode\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n\n    bind .ndraw <Double-1> {\n\tNg_MouseDblClick %x %y\n\t.ndraw render\n\tif { [winfo exists .bcprop_dlg] } { bcpropdialog }\n\tif { [winfo exists .surfacemeshsize_dlg] } { surfacemeshsizedialog }\n\tif { [winfo exists .fieldlines_dlg] } { fieldlinesdialog }\n    }\n\n    bind .ndraw <B2-Motion> {\n\tNg_MouseMove $oldmousex $oldmousey %x %y move\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n\n    bind .ndraw <B3-Motion> {\n        if { $tcl_platform(os) == \"Darwin\" } {\n            Ng_MouseMove $oldmousex $oldmousey %x %y move\n        } { \n            Ng_MouseMove $oldmousex $oldmousey %x %y zoom\n        }\n\t.ndraw render\n\tset oldmousex %x; set oldmousey %y;\n    }\n    \n    bind .ndraw <Alt-B2-Motion> {\n        Ng_MouseMove $oldmousex $oldmousey %x %y Move2d\n        .ndraw render\n        set oldmousex %x; set oldmousey %y;\n    }\n    \n    bind .ndraw <Alt-B3-Motion> {\n        Ng_MouseMove $oldmousex $oldmousey %x %y Zoom2d\n        .ndraw render\n        set oldmousex %x; set oldmousey %y;\n    }\n}\n\n\nproc popupcheckredraw { vari { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n        #        puts \"popup-redraw $vari\"\n\tNg_Vis_Set parameters\n\tredraw\n    }\n}\nproc popupcheckredraw2 { vari boolvar { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n\tNg_SetVisParameters\n\tNg_Vis_Set parameters\n\tif { $boolvar == 1 } { redraw }\n\tNg_SetVisParameters\n    }\n}\nproc popupcheckredraw3 { vari { x 0 } } {\n    upvar $vari varname\n    if { $varname == 1 } {\n\tset varname 0\n    } {\n\tNg_Vis_Set parameters\n    }\n}\n\n\n\n\nproc redraw { {x 0} } {\n    if {[winfo exists .ndraw]} { .ndraw render } \n}\n\n\n\nbind . <Left> { Ng_MouseMove 0 0 -10 0 rotate; redraw }\nbind . <Right> { Ng_MouseMove 0 0 10 0 rotate; redraw }\nbind . <Up> { Ng_MouseMove 0 0 0 -10 rotate; redraw }\nbind . <Down> { Ng_MouseMove 0 0 0 10 rotate; redraw }\nbind . <Shift-Left> { Ng_MouseMove 0 0 -10 0 move; redraw }\nbind . <Shift-Right> { Ng_MouseMove 0 0 10 0 move; redraw }\nbind . <Shift-Up> { Ng_MouseMove 0 0 0 -10 move; redraw }\nbind . <Shift-Down> { Ng_MouseMove 0 0 0 10 move; redraw }\nbind . <Control-Up> { Ng_MouseMove 0 0 0 -10 zoom; redraw }\nbind . <Control-Down> { Ng_MouseMove 0 0 0 10 zoom; redraw }\n\nbind . <Button-4> \\\n   {event generate [focus -displayof %W] <MouseWheel> -delta  120}\n\nbind . <Button-5> \\\n   {event generate [focus -displayof %W] <MouseWheel> -delta -120}\n\nbind . <MouseWheel> { Ng_MouseMove 0 0 0 [expr {%D/-5}] zoom; redraw }\n\n\n\n# Drop callbacks:\nbind .ndraw <<Drop:DND_Files>> {\n  #tk_messageBox -message \"Dropped files: \\\"[join %D {, }]\\\"\"\n  #%W state !active  \n  set index [string first . %D end-6]\n  #tk_messageBox -message $index\n  set type [string range %D $index+1 end]\n  # tk_messageBox -message $type\n  set ispde [string match -nocase $type \"pde\"]\n  set isgeo [expr max([string match -nocase $type \"geo\"],[string match -nocase $type \"in2d\"])]\n  set ismesh [expr max([string match -nocase $type \"vol\"],[string match -nocase $type \"vol.gz\"])]\n  set ispy [string match -nocase $type \"py\"]\n  if {$ispde == 1} {\n      AddRecentNGSFile %D;\n      NGS_LoadPDE  %D;\n      SetNumProcHelpMenu\n      set selectvisual mesh;\n      Ng_SetVisParameters\n  }\n  if {$ispy == 1} {\n      AddRecentPYNGSFile %D;\n      NGS_LoadPy  %D;\n  }\n  if {$isgeo == 1} {\n\t    AddRecentFile %D;\n\t    Ng_LoadGeometry %D;\n\t    Ng_ParseGeometry\n\t    set selectvisual geometry\n\t    Ng_SetVisParameters\n\t    redraw\n\t    wm title . [concat \"$progname - \" %D]\n\t    set dirname [file dirname %D]\n\t    set basefilename [file tail [file rootname %D]]\n\t}\n\tif {$ismesh == 1} {\n\t    AddRecentMeshFile %D;\n\t    Ng_LoadMesh %D; \n\t    set selectvisual mesh\n\t    Ng_SetVisParameters\n\t    redraw\n\t    Ng_ReadStatus; \n\t    wm title . [concat \"$progname - \" %D] \n\t    set dirname [file dirname %D]\n\t    set basefilename [file tail [file rootname %D]]\n\t}\n  return %A\n}\n"
  },
  {
    "path": "ng/encoding.hpp",
    "content": "#ifndef ENCODING_HPP_INCLUDED__\n#define ENCODING_HPP_INCLUDED__\n\n#ifdef FFMPEG\n\nextern \"C\" {\n#include <libavutil/avassert.h>\n#include <libavcodec/avcodec.h>\n#include <libavutil/channel_layout.h>\n#include <libavutil/opt.h>\n#include <libavutil/mathematics.h>\n#include <libavutil/timestamp.h>\n#include <libavutil/imgutils.h>\n#include <libavformat/avformat.h>\n#include <libswscale/swscale.h>\n#include <libswresample/swresample.h>\n}\n\nconstexpr int BITRATE = 50000000;\n\nclass Mpeg {\n  private:\n    bool is_started =false;\n    int framerate = 25;\n    AVOutputFormat *fmt;\n    AVFormatContext *oc;\n\n    AVStream *st;\n    AVCodecContext *enc;\n\n    AVFrame *frame;\n    AVFrame *rgb_frame;\n    uint8_t *rgb_buffer;\n\n    struct SwsContext *sws_ctx;\n\n    AVFrame *alloc_picture(enum AVPixelFormat pix_fmt)\n    {\n        AVFrame *picture;\n\n        picture = av_frame_alloc();\n        if (!picture)\n            return NULL;\n\n        picture->format = pix_fmt;\n        picture->width  = width;\n        picture->height = height;\n\n        av_frame_get_buffer(picture, 32);\n        return picture;\n    }\n\n  public:\n    int width;\n    int height;\n    bool IsStarted() { return is_started; }\n    int AddFrame() {\n        int ret;\n        int got_packet = 0;\n        AVPacket pkt = { 0 };\n\n        glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb_buffer);\n        av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, rgb_buffer, AV_PIX_FMT_RGB24, width, height, 1);\n\n\n        if (av_frame_make_writable(frame) < 0)\n            return 1;\n\n        // The picture is upside down - flip it:\n        auto data = rgb_frame->data[0] + 3*width*height;\n        uint8_t *flipped_data[4] = { data, data, data, data };\n        int flipped_stride[4] = { -rgb_frame->linesize[0], -rgb_frame->linesize[1], -rgb_frame->linesize[2], -rgb_frame->linesize[3] };\n        sws_scale(sws_ctx, flipped_data, flipped_stride, 0, enc->height, frame->data, frame->linesize);\n\n\n        av_init_packet(&pkt);\n\n        got_packet = 0;\n        ret = avcodec_send_frame(enc, frame);\n        if (ret < 0)\n        {\n            cerr << \"Error encoding video frame: \" << endl;\n            return(1);\n        }\n\n        ret = avcodec_receive_packet(enc, &pkt);\n        if (!ret)\n            got_packet = 1;\n        if (ret == AVERROR(EAGAIN))\n            return 0;\n\n        if (ret < 0) {\n            cerr << \"Error encoding video frame: \" << endl;\n            return 1;\n        }\n\n        if (got_packet) {\n            /* rescale output packet timestamp values from codec to stream timebase */\n            av_packet_rescale_ts(&pkt, enc->time_base, st->time_base);\n            pkt.stream_index = st->index;\n\n            /* Write the compressed frame to the media file. */\n            ret = av_interleaved_write_frame(oc, &pkt);\n        } else {\n            ret = 0;\n        }\n\n        if (ret < 0) {\n            cerr << \"Error while writing video frame: \" << endl;\n            return(1);\n        }\n\n        return 0;\n    }\n\n    int Start(string filename) {\n        AVCodec *video_codec;\n        if(is_started) {\n            cerr << \"Stream already started\" << endl;\n            return 1;\n        }\n        is_started = true;\n\n        GLint dims[4] = {0};\n        glGetIntegerv(GL_VIEWPORT, dims);\n        width = dims[2];\n        height= dims[3];\n\n        width = int((width+1)/4)*4+4;\n        height = 2 * (height/2);\n\n        int ret;\n        int i;\n\n        // av_register_all();\n\n        avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str());\n//         oc->preload= (int)(0.5*AV_TIME_BASE);\n        oc->max_delay= (int)(0.7*AV_TIME_BASE);\n\n        fmt = (AVOutputFormat*) oc->oformat;\n\n        if (fmt->video_codec != AV_CODEC_ID_NONE) {\n            /* find the encoder */\n            video_codec = (AVCodec*) avcodec_find_encoder(fmt->video_codec);\n            if (!(video_codec)) {\n                cerr << \"Could not find encoder for '\" << avcodec_get_name(fmt->video_codec) << \"'\" << endl;\n                return 1;\n            }\n\n            st = avformat_new_stream(oc, NULL);\n            if (!st) {\n                cerr << \"Could not allocate stream\\n\";\n                return 1;\n            }\n            st->id = oc->nb_streams-1;\n            enc = avcodec_alloc_context3(video_codec);\n            if (!enc) {\n                cerr << \"Could not alloc an encoding context\\n\";\n                return 1;\n            }\n\n            enc->codec_id = fmt->video_codec;\n\n            enc->bit_rate = BITRATE;\n            enc->width    = width;\n            enc->height   = height;\n            AVRational tb;\n            tb.num=1;\n            tb.den=framerate;\n            st->time_base = tb;\n            enc->time_base       = st->time_base;\n\n            enc->gop_size      = 200;\n            enc->pix_fmt       = AV_PIX_FMT_YUV420P;\n            if (enc->codec_id == AV_CODEC_ID_MPEG2VIDEO) {\n                enc->max_b_frames = 3;\n            }\n            if (enc->codec_id == AV_CODEC_ID_MPEG1VIDEO) {\n                enc->mb_decision = 2;\n            }\n\n            if (oc->oformat->flags & AVFMT_GLOBALHEADER)\n                enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;\n\n//             enc->flags |= CODEC_FLAG_QSCALE;\n//             enc->global_quality = 1180;\n        }\n        else {\n            cerr << \"could not init codecs!\" << endl;\n            return 1;\n        }\n\n        AVDictionary *opt = NULL;\n\n        /* open the codec */\n        ret = avcodec_open2(enc, video_codec, &opt);\n        av_dict_free(&opt);\n        if (ret < 0) {\n            cerr << \"Could not open video codec\" << endl;\n            return 1;\n        }\n\n        /* allocate and init a re-usable frame */\n        frame = alloc_picture(enc->pix_fmt);\n        if (!frame) {\n            cerr << \"Could not allocate video frame\\n\";\n            return 1;\n        }\n\n        /* copy the stream parameters to the muxer */\n        ret = avcodec_parameters_from_context(st->codecpar, enc);\n        if (ret < 0) {\n            cerr << \"Could not copy the stream parameters\\n\";\n            return 1;\n        }\n\n        av_dump_format(oc, 0, filename.c_str(), 1);\n\n        if (!(fmt->flags & AVFMT_NOFILE)) {\n            ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE);\n            if (ret < 0) {\n                cerr << \"Could not open \" << filename << \" : \" << endl;\n                return 1;\n            }\n        }\n\n        ret = avformat_write_header(oc, &opt);\n        if (ret < 0) {\n            cerr << \"Error occurred when opening output file: \" << endl;;\n            return 1;\n        }\n\n        rgb_frame = alloc_picture(AV_PIX_FMT_RGB24);\n        rgb_buffer = new uint8_t[width*height*4];\n        sws_ctx = sws_getContext( width, height, AV_PIX_FMT_RGB24,\n                                 width, height, AV_PIX_FMT_YUV420P,\n                                 SWS_BICUBIC, NULL, NULL, NULL );\n        return 0;\n    }\n\n    void Stop() {\n        av_write_trailer(oc);\n        avcodec_free_context(&enc);\n        av_frame_free(&frame);\n        sws_freeContext(sws_ctx);\n        if (!(fmt->flags & AVFMT_NOFILE))\n            avio_closep(&oc->pb);\n        avformat_free_context(oc);\n        delete [] rgb_buffer;\n        is_started = false;\n    }\n};\n#endif // FFMPEG\n#endif // ENCODING_HPP_INCLUDED__\n"
  },
  {
    "path": "ng/fonts.hpp",
    "content": "#define font12_width 591\n#define font12_height 12\nstatic unsigned char font12_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x20, 0x01, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x84, 0x44, 0x10, 0x88, 0x00, \n  0x00, 0x00, 0x00, 0x40, 0x0E, 0xE1, 0x38, 0xD0, 0xE7, 0x7C, 0x8E, 0x03, \n  0x00, 0x00, 0x00, 0x38, 0x8E, 0xF3, 0x38, 0xC7, 0xF7, 0x39, 0x91, 0xC3, \n  0x45, 0x41, 0x14, 0x39, 0x8F, 0xF3, 0x38, 0x5F, 0x14, 0x45, 0x51, 0xF4, \n  0x39, 0x82, 0xA3, 0x00, 0x00, 0x10, 0x00, 0x10, 0x80, 0x01, 0x01, 0x01, \n  0x09, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, \n  0x60, 0x84, 0x51, 0x01, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x4E, 0xA5, 0x10, \n  0x04, 0x01, 0x00, 0x00, 0x00, 0x40, 0x91, 0x11, 0x45, 0x58, 0x10, 0x40, \n  0x51, 0x04, 0x00, 0x10, 0x20, 0x44, 0x51, 0x14, 0x45, 0x49, 0x10, 0x44, \n  0x11, 0x81, 0x24, 0xC1, 0x16, 0x45, 0x51, 0x14, 0x45, 0x44, 0x14, 0x45, \n  0x51, 0x04, 0x09, 0x02, 0x12, 0x01, 0x00, 0x10, 0x00, 0x10, 0x40, 0x00, \n  0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, \n  0x00, 0x00, 0x10, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7C, 0x95, \n  0xA2, 0x00, 0x02, 0xA2, 0x10, 0x00, 0x00, 0x20, 0x19, 0x11, 0x41, 0x54, \n  0x10, 0x40, 0x51, 0x44, 0x10, 0xC8, 0x47, 0x44, 0x59, 0x14, 0x05, 0x51, \n  0x10, 0x04, 0x11, 0x81, 0x14, 0x41, 0x35, 0x45, 0x51, 0x14, 0x05, 0x44, \n  0x14, 0x45, 0x8A, 0x82, 0x08, 0x04, 0x02, 0x00, 0x80, 0xF3, 0x38, 0x9E, \n  0xE3, 0x78, 0x8F, 0x81, 0x49, 0xC4, 0xF3, 0x38, 0x8F, 0xD7, 0x79, 0x4E, \n  0x14, 0x45, 0x51, 0xF4, 0x11, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, \n  0x28, 0x05, 0x42, 0x00, 0x02, 0x42, 0x10, 0x00, 0x00, 0x20, 0x15, 0x01, \n  0x31, 0xD2, 0xF3, 0x20, 0x4E, 0x44, 0x10, 0x04, 0x80, 0x20, 0x55, 0xF4, \n  0x04, 0xD1, 0xF3, 0x04, 0x1F, 0x81, 0x0C, 0x41, 0x55, 0x45, 0x51, 0x14, \n  0x39, 0x44, 0xA4, 0x44, 0x84, 0x42, 0x08, 0x04, 0x02, 0x00, 0x00, 0x14, \n  0x45, 0x51, 0x44, 0x44, 0x11, 0x01, 0x29, 0x44, 0x15, 0x45, 0x51, 0x34, \n  0x04, 0x44, 0x14, 0x45, 0x4A, 0x84, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, \n  0x00, 0x01, 0x28, 0x0E, 0x61, 0x01, 0x02, 0xF2, 0x7D, 0xC0, 0x07, 0x10, \n  0x13, 0x81, 0x40, 0x11, 0x14, 0x21, 0x91, 0x07, 0x00, 0x02, 0x00, 0x11, \n  0xD5, 0x17, 0x05, 0x51, 0x10, 0x74, 0x11, 0x81, 0x0C, 0x41, 0x94, 0x45, \n  0x4F, 0xF4, 0x40, 0x44, 0xA4, 0x54, 0x04, 0x21, 0x08, 0x08, 0x02, 0x00, \n  0x80, 0x17, 0x05, 0xD1, 0x47, 0x44, 0x11, 0x01, 0x19, 0x44, 0x15, 0x45, \n  0x51, 0x14, 0x38, 0x44, 0xA4, 0x54, 0x44, 0x44, 0x10, 0x04, 0x02, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x7C, 0x14, 0x95, 0x00, 0x02, 0x42, 0x10, 0x00, \n  0x00, 0x10, 0x11, 0x41, 0x40, 0x1F, 0x14, 0x11, 0x11, 0x04, 0x00, 0xC4, \n  0x87, 0x00, 0x59, 0x14, 0x05, 0x51, 0x10, 0x44, 0x11, 0x91, 0x14, 0x41, \n  0x14, 0x45, 0x41, 0x54, 0x40, 0x44, 0xA4, 0x54, 0x0A, 0x11, 0x08, 0x08, \n  0x02, 0x00, 0x40, 0x14, 0x05, 0x51, 0x40, 0x44, 0x11, 0x01, 0x19, 0x44, \n  0x15, 0x45, 0x51, 0x14, 0x40, 0x44, 0xA4, 0x54, 0x44, 0x24, 0x10, 0x04, \n  0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x95, 0x9A, 0x00, 0x04, 0xA1, \n  0x10, 0x04, 0x40, 0x08, 0x11, 0x21, 0x44, 0x50, 0x14, 0x11, 0x11, 0x44, \n  0x10, 0x08, 0x40, 0x10, 0x41, 0x14, 0x45, 0x49, 0x10, 0x44, 0x11, 0x91, \n  0x24, 0x41, 0x14, 0x45, 0x41, 0x95, 0x44, 0x44, 0x44, 0x6C, 0x11, 0x11, \n  0x08, 0x10, 0x02, 0x00, 0x40, 0x14, 0x45, 0x51, 0x40, 0x44, 0x11, 0x01, \n  0x29, 0x44, 0x15, 0x45, 0x51, 0x14, 0x40, 0x44, 0x44, 0x54, 0x4A, 0x14, \n  0x10, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x8E, 0x64, 0x01, \n  0x88, 0x00, 0x00, 0x04, 0x40, 0x08, 0x8E, 0xF3, 0x39, 0x90, 0xE3, 0x10, \n  0x8E, 0x43, 0x10, 0x10, 0x20, 0x10, 0x5E, 0xF4, 0x38, 0xC7, 0x17, 0x38, \n  0x91, 0x63, 0x44, 0x5F, 0x14, 0x39, 0x81, 0x13, 0x39, 0x84, 0x43, 0x44, \n  0x11, 0xF1, 0x39, 0x90, 0x03, 0x00, 0x80, 0xF7, 0x38, 0x9E, 0x47, 0x78, \n  0x91, 0x03, 0x49, 0x4E, 0x15, 0x39, 0x8F, 0x17, 0x3C, 0x98, 0x47, 0x38, \n  0x91, 0xF7, 0x61, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x40, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, \n  0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  };\n#define font14_width 789\n#define font14_height 14\nstatic unsigned char font14_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x08, 0x66, \n  0x1C, 0x18, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3E, 0x18, \n  0x3E, 0x3E, 0x60, 0x7F, 0x3C, 0x7F, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x3E, 0x3E, 0x3E, 0x3F, 0x3E, 0x1F, 0x7F, 0x7F, 0x3E, 0x63, 0x3C, \n  0x78, 0x63, 0x03, 0x41, 0x63, 0x3E, 0x3F, 0x3E, 0x3F, 0x3E, 0xFF, 0x63, \n  0x63, 0x63, 0x63, 0xC3, 0x7F, 0x3C, 0x06, 0x3C, 0x3C, 0x00, 0x00, 0x00, \n  0x03, 0x00, 0x60, 0x00, 0x78, 0x00, 0x03, 0x18, 0x60, 0x03, 0x1C, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x38, 0x18, 0x0E, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, \n  0x36, 0x3E, 0x6B, 0x36, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x60, 0x63, 0x1C, 0x63, 0x63, 0x70, 0x03, 0x06, 0x60, 0x63, 0x63, 0x00, \n  0x00, 0x60, 0x00, 0x06, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, \n  0x63, 0x63, 0x18, 0x30, 0x63, 0x03, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, \n  0x63, 0x18, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x60, 0x0C, 0x06, 0x30, 0x66, \n  0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x18, 0x60, \n  0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x73, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x36, 0x6B, 0x36, 0x36, 0x00, 0x0C, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x30, 0x63, 0x1E, 0x63, 0x63, 0x78, 0x03, 0x03, 0x60, \n  0x63, 0x63, 0x00, 0x00, 0x30, 0x00, 0x0C, 0x63, 0x73, 0x63, 0x63, 0x63, \n  0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x33, 0x03, 0x77, 0x63, 0x63, \n  0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x60, 0x0C, \n  0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, \n  0x03, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x0B, 0x30, 0x1C, 0x00, 0x0C, \n  0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30, 0x73, 0x18, 0x60, 0x60, 0x6C, \n  0x03, 0x03, 0x30, 0x63, 0x63, 0x18, 0x18, 0x18, 0x7F, 0x18, 0x63, 0x6B, \n  0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x03, 0x63, 0x18, 0x30, 0x1B, 0x03, \n  0x7F, 0x67, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, \n  0x66, 0x30, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x3E, 0x7E, \n  0x3E, 0x3F, 0x7E, 0x3F, 0x1C, 0x70, 0x63, 0x18, 0x3F, 0x3F, 0x3E, 0x3F, \n  0x7E, 0x7B, 0x7E, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x0C, 0x18, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x0B, 0x18, \n  0x6E, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x18, 0x7B, 0x18, \n  0x30, 0x3C, 0x66, 0x3F, 0x3F, 0x30, 0x3E, 0x63, 0x18, 0x18, 0x0C, 0x00, \n  0x30, 0x30, 0x6B, 0x63, 0x3F, 0x03, 0x63, 0x1F, 0x1F, 0x03, 0x7F, 0x18, \n  0x30, 0x0F, 0x03, 0x6B, 0x6F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x18, 0x63, \n  0x63, 0x63, 0x1C, 0x3C, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x60, \n  0x63, 0x63, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, \n  0x63, 0x63, 0x63, 0x63, 0x0F, 0x03, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, \n  0x30, 0x06, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, \n  0x36, 0x3E, 0x18, 0x3B, 0x00, 0x0C, 0x30, 0x7F, 0x7E, 0x00, 0x7F, 0x00, \n  0x18, 0x6F, 0x18, 0x18, 0x60, 0x63, 0x60, 0x63, 0x18, 0x63, 0x7E, 0x00, \n  0x00, 0x06, 0x00, 0x60, 0x18, 0x6B, 0x7F, 0x63, 0x03, 0x63, 0x03, 0x03, \n  0x7B, 0x63, 0x18, 0x30, 0x0F, 0x03, 0x63, 0x7B, 0x63, 0x3F, 0x63, 0x3F, \n  0x60, 0x18, 0x63, 0x36, 0x6B, 0x1C, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, \n  0x00, 0x00, 0x7E, 0x63, 0x03, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, \n  0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x07, 0x03, 0x0C, 0x63, 0x63, \n  0x6B, 0x36, 0x63, 0x18, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x7F, 0x68, 0x0C, 0x33, 0x00, 0x0C, 0x30, 0x1C, 0x18, \n  0x00, 0x00, 0x00, 0x0C, 0x67, 0x18, 0x0C, 0x60, 0x7F, 0x60, 0x63, 0x18, \n  0x63, 0x60, 0x00, 0x00, 0x0C, 0x7F, 0x30, 0x18, 0x6B, 0x63, 0x63, 0x03, \n  0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x63, 0x73, 0x63, \n  0x03, 0x63, 0x0F, 0x60, 0x18, 0x63, 0x36, 0x7F, 0x36, 0x18, 0x06, 0x0C, \n  0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x7F, 0x0C, 0x63, \n  0x63, 0x18, 0x60, 0x0F, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x3E, \n  0x0C, 0x63, 0x36, 0x6B, 0x1C, 0x63, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x68, 0x6C, 0x33, 0x00, 0x0C, \n  0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x63, 0x18, 0x06, 0x63, 0x60, \n  0x60, 0x63, 0x0C, 0x63, 0x60, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x73, \n  0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x33, 0x03, \n  0x63, 0x63, 0x63, 0x03, 0x63, 0x1B, 0x63, 0x18, 0x63, 0x36, 0x77, 0x36, \n  0x18, 0x03, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, \n  0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, \n  0x63, 0x03, 0x60, 0x0C, 0x63, 0x36, 0x6B, 0x36, 0x63, 0x06, 0x0C, 0x18, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0xD6, \n  0x3B, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x63, 0x18, \n  0x03, 0x63, 0x60, 0x63, 0x63, 0x0C, 0x63, 0x30, 0x18, 0x18, 0x30, 0x00, \n  0x0C, 0x18, 0x03, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, \n  0x33, 0x63, 0x03, 0x63, 0x63, 0x63, 0x03, 0x7B, 0x33, 0x63, 0x18, 0x63, \n  0x1C, 0x63, 0x63, 0x18, 0x03, 0x0C, 0x60, 0x30, 0x00, 0x00, 0x00, 0x63, \n  0x63, 0x63, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, \n  0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x1C, 0x6B, 0x63, 0x63, \n  0x03, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, \n  0x36, 0x3E, 0x66, 0x6E, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x18, \n  0x06, 0x3E, 0x7E, 0x7F, 0x3E, 0x60, 0x3E, 0x3E, 0x0C, 0x3E, 0x1E, 0x18, \n  0x18, 0x60, 0x00, 0x06, 0x18, 0x7E, 0x63, 0x3F, 0x3E, 0x1F, 0x7F, 0x03, \n  0x3E, 0x63, 0x3C, 0x1E, 0x63, 0x7F, 0x63, 0x63, 0x3E, 0x03, 0x3E, 0x63, \n  0x3E, 0x18, 0x3E, 0x1C, 0x41, 0x63, 0x18, 0x7F, 0x3C, 0x60, 0x3C, 0x00, \n  0x00, 0x00, 0x7E, 0x3F, 0x3E, 0x7E, 0x3E, 0x0C, 0x7E, 0x63, 0x3C, 0x66, \n  0x63, 0x3C, 0x6B, 0x63, 0x3E, 0x3F, 0x7E, 0x03, 0x3F, 0x78, 0x7E, 0x1C, \n  0x3E, 0x63, 0x7E, 0x7F, 0x38, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };\n#define font16_width 789\n#define font16_height 16\nstatic unsigned char font16_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x08, 0x66, \n  0x1C, 0x18, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3E, 0x18, \n  0x3E, 0x3E, 0x60, 0x7F, 0x3C, 0x7F, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x3E, 0x3E, 0x3E, 0x3F, 0x3E, 0x1F, 0x7F, 0x7F, 0x3E, 0x63, 0x3C, \n  0x78, 0x63, 0x03, 0x41, 0x63, 0x3E, 0x3F, 0x3E, 0x3F, 0x3E, 0xFF, 0x63, \n  0x63, 0x63, 0x63, 0xC3, 0x7F, 0x3C, 0x06, 0x3C, 0x3C, 0x00, 0x00, 0x00, \n  0x03, 0x00, 0x60, 0x00, 0x78, 0x00, 0x03, 0x18, 0x60, 0x03, 0x1C, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x38, 0x18, 0x0E, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, \n  0x36, 0x3E, 0x6B, 0x36, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x60, 0x63, 0x1C, 0x63, 0x63, 0x70, 0x03, 0x06, 0x60, 0x63, 0x63, 0x00, \n  0x00, 0x60, 0x00, 0x06, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, \n  0x63, 0x63, 0x18, 0x30, 0x63, 0x03, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, \n  0x63, 0x18, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x60, 0x0C, 0x06, 0x30, 0x66, \n  0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x18, 0x60, \n  0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x73, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x36, 0x6B, 0x36, 0x36, 0x00, 0x0C, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x30, 0x63, 0x1E, 0x63, 0x63, 0x78, 0x03, 0x03, 0x60, \n  0x63, 0x63, 0x00, 0x00, 0x30, 0x00, 0x0C, 0x63, 0x73, 0x63, 0x63, 0x63, \n  0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x33, 0x03, 0x77, 0x63, 0x63, \n  0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x60, 0x0C, \n  0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, \n  0x03, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x0B, 0x30, 0x1C, 0x00, 0x0C, \n  0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30, 0x73, 0x18, 0x60, 0x60, 0x6C, \n  0x03, 0x03, 0x30, 0x63, 0x63, 0x18, 0x18, 0x18, 0x7F, 0x18, 0x63, 0x6B, \n  0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x03, 0x63, 0x18, 0x30, 0x1B, 0x03, \n  0x7F, 0x67, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, \n  0x66, 0x30, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x3E, 0x7E, \n  0x3E, 0x3F, 0x7E, 0x3F, 0x1C, 0x70, 0x63, 0x18, 0x3F, 0x3F, 0x3E, 0x3F, \n  0x7E, 0x7B, 0x7E, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x0C, 0x18, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x0B, 0x18, \n  0x6E, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x18, 0x7B, 0x18, \n  0x30, 0x3C, 0x66, 0x3F, 0x3F, 0x30, 0x3E, 0x63, 0x18, 0x18, 0x0C, 0x00, \n  0x30, 0x30, 0x6B, 0x63, 0x3F, 0x03, 0x63, 0x1F, 0x1F, 0x03, 0x7F, 0x18, \n  0x30, 0x0F, 0x03, 0x6B, 0x6F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x18, 0x63, \n  0x63, 0x63, 0x1C, 0x3C, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x60, \n  0x63, 0x63, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, \n  0x63, 0x63, 0x63, 0x63, 0x0F, 0x03, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, \n  0x30, 0x06, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, \n  0x36, 0x3E, 0x18, 0x3B, 0x00, 0x0C, 0x30, 0x7F, 0x7E, 0x00, 0x7F, 0x00, \n  0x18, 0x6F, 0x18, 0x18, 0x60, 0x63, 0x60, 0x63, 0x18, 0x63, 0x7E, 0x00, \n  0x00, 0x06, 0x00, 0x60, 0x18, 0x6B, 0x7F, 0x63, 0x03, 0x63, 0x03, 0x03, \n  0x7B, 0x63, 0x18, 0x30, 0x0F, 0x03, 0x63, 0x7B, 0x63, 0x3F, 0x63, 0x3F, \n  0x60, 0x18, 0x63, 0x36, 0x6B, 0x1C, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, \n  0x00, 0x00, 0x7E, 0x63, 0x03, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, \n  0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x07, 0x03, 0x0C, 0x63, 0x63, \n  0x6B, 0x36, 0x63, 0x18, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x7F, 0x68, 0x0C, 0x33, 0x00, 0x0C, 0x30, 0x1C, 0x18, \n  0x00, 0x00, 0x00, 0x0C, 0x67, 0x18, 0x0C, 0x60, 0x7F, 0x60, 0x63, 0x18, \n  0x63, 0x60, 0x00, 0x00, 0x0C, 0x7F, 0x30, 0x18, 0x6B, 0x63, 0x63, 0x03, \n  0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x63, 0x73, 0x63, \n  0x03, 0x63, 0x0F, 0x60, 0x18, 0x63, 0x36, 0x7F, 0x36, 0x18, 0x06, 0x0C, \n  0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x7F, 0x0C, 0x63, \n  0x63, 0x18, 0x60, 0x0F, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x3E, \n  0x0C, 0x63, 0x36, 0x6B, 0x1C, 0x63, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x68, 0x6C, 0x33, 0x00, 0x0C, \n  0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x63, 0x18, 0x06, 0x63, 0x60, \n  0x60, 0x63, 0x0C, 0x63, 0x60, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x73, \n  0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x33, 0x03, \n  0x63, 0x63, 0x63, 0x03, 0x63, 0x1B, 0x63, 0x18, 0x63, 0x36, 0x77, 0x36, \n  0x18, 0x03, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, \n  0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, \n  0x63, 0x03, 0x60, 0x0C, 0x63, 0x36, 0x6B, 0x36, 0x63, 0x06, 0x0C, 0x18, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0xD6, \n  0x3B, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x63, 0x18, \n  0x03, 0x63, 0x60, 0x63, 0x63, 0x0C, 0x63, 0x30, 0x18, 0x18, 0x30, 0x00, \n  0x0C, 0x18, 0x03, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, \n  0x33, 0x63, 0x03, 0x63, 0x63, 0x63, 0x03, 0x7B, 0x33, 0x63, 0x18, 0x63, \n  0x1C, 0x63, 0x63, 0x18, 0x03, 0x0C, 0x60, 0x30, 0x00, 0x00, 0x00, 0x63, \n  0x63, 0x63, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, \n  0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x1C, 0x6B, 0x63, 0x63, \n  0x03, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, \n  0x36, 0x3E, 0x66, 0x6E, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x18, \n  0x06, 0x3E, 0x7E, 0x7F, 0x3E, 0x60, 0x3E, 0x3E, 0x0C, 0x3E, 0x1E, 0x18, \n  0x18, 0x60, 0x00, 0x06, 0x18, 0x7E, 0x63, 0x3F, 0x3E, 0x1F, 0x7F, 0x03, \n  0x3E, 0x63, 0x3C, 0x1E, 0x63, 0x7F, 0x63, 0x63, 0x3E, 0x03, 0x3E, 0x63, \n  0x3E, 0x18, 0x3E, 0x1C, 0x41, 0x63, 0x18, 0x7F, 0x3C, 0x60, 0x3C, 0x00, \n  0x00, 0x00, 0x7E, 0x3F, 0x3E, 0x7E, 0x3E, 0x0C, 0x7E, 0x63, 0x3C, 0x60, \n  0x63, 0x3C, 0x6B, 0x63, 0x3E, 0x3F, 0x7E, 0x03, 0x3F, 0x78, 0x7E, 0x1C, \n  0x3E, 0x63, 0x7E, 0x7F, 0x38, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  };\n#define font18_width 987\n#define font18_height 18\nstatic unsigned char font18_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, \n  0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0xC0, 0x0C, 0x33, 0x30, 0x38, 0xC3, 0x03, 0x0C, 0x60, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFC, 0xC0, 0xC0, 0x0F, \n  0x3F, 0x80, 0xF9, 0x87, 0x8F, 0x7F, 0xFC, 0xF0, 0x03, 0x00, 0x00, 0xC0, \n  0x00, 0x60, 0x00, 0x1E, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0x7E, 0xF8, 0xE7, \n  0x1F, 0x3F, 0x86, 0xE1, 0x01, 0x9E, 0x61, 0x06, 0x04, 0x64, 0x18, 0x3F, \n  0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0xFE, 0x19, 0x66, 0xD8, 0x60, 0x86, 0x19, \n  0xE6, 0x1F, 0x1E, 0x06, 0xE0, 0xC1, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x1E, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x38, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x70, 0x60, 0x1B, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0xFC, 0x28, 0x63, \n  0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x86, 0xE1, 0x60, 0x98, 0x61, 0xC0, 0x19, 0xC0, 0x80, 0x61, 0x86, 0x19, \n  0x06, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x33, 0x83, 0x19, 0x66, 0x98, \n  0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x61, 0x06, \n  0x0C, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, \n  0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, 0x80, 0x61, 0x18, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0xC0, \n  0x00, 0x8C, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, \n  0xC0, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0xB6, 0xB9, 0x61, 0x06, 0x00, 0x30, 0xC0, 0x60, 0x0C, 0x0C, 0x00, \n  0x00, 0x00, 0x00, 0x18, 0x86, 0xF1, 0x60, 0x98, 0x61, 0xE0, 0x19, 0x60, \n  0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0x30, 0x00, 0x80, 0x81, 0x61, \n  0x83, 0x19, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x31, 0x06, 0x1C, 0x67, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, \n  0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x18, 0x06, 0x18, 0x06, 0x0C, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, \n  0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x80, 0x7F, 0x36, 0x80, 0x61, 0x06, 0x00, 0x18, 0x80, \n  0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xC1, 0x60, 0x18, \n  0x60, 0xB0, 0x19, 0x60, 0x00, 0x60, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x18, \n  0xF8, 0x07, 0x83, 0x61, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, \n  0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x06, 0xBC, 0xE7, 0x98, 0x61, \n  0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x30, \n  0x03, 0x0C, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE3, 0x0F, \n  0x3F, 0xFC, 0xF1, 0xC3, 0x0F, 0x7F, 0xFE, 0xE0, 0x00, 0x8E, 0x61, 0x30, \n  0xF8, 0xE3, 0x0F, 0x3F, 0xFE, 0xF0, 0x67, 0x1F, 0x3F, 0x7E, 0x18, 0x66, \n  0x98, 0x61, 0x86, 0x19, 0xE6, 0x1F, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xC0, 0xC0, \n  0x03, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0C, \n  0xE6, 0xC1, 0x00, 0x18, 0x60, 0x98, 0x19, 0x60, 0x00, 0x30, 0x86, 0x19, \n  0x06, 0x03, 0x0C, 0x0C, 0x00, 0x00, 0x06, 0x60, 0x9B, 0x19, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, \n  0xEC, 0xE6, 0x99, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0xC6, \n  0xCC, 0x60, 0x78, 0x30, 0x03, 0x06, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x81, \n  0x61, 0x18, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x18, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0x36, 0xC0, 0xC0, 0x19, 0x00, 0x18, 0x80, 0xF1, 0x9F, 0x7F, 0x00, \n  0xF8, 0x07, 0x00, 0x0C, 0xB6, 0xC1, 0x00, 0x0C, 0x3E, 0x8C, 0xF9, 0xE3, \n  0x0F, 0x30, 0xFC, 0x18, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x30, \n  0x9B, 0x19, 0xE6, 0x8F, 0x01, 0x86, 0xF9, 0xE1, 0x87, 0x01, 0xFE, 0xC1, \n  0x00, 0x8C, 0x07, 0x06, 0x4C, 0x66, 0x9B, 0x61, 0x86, 0x19, 0x66, 0x18, \n  0x3F, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x30, 0xE0, 0x01, 0x03, 0x06, 0x18, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x01, 0x86, 0x19, 0x06, \n  0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, \n  0x86, 0x19, 0xE6, 0x80, 0x01, 0x18, 0x18, 0x66, 0x98, 0x61, 0xCC, 0x18, \n  0x06, 0x0C, 0x07, 0x30, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0x60, 0x60, 0x1B, 0x00, 0x18, 0x80, \n  0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9E, 0xC1, 0x00, 0x06, \n  0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0xF1, 0x07, 0x00, 0x00, 0x06, \n  0x00, 0x00, 0x0C, 0x18, 0x9B, 0xF9, 0x67, 0x98, 0x01, 0x86, 0x19, 0x60, \n  0x80, 0x79, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x06, 0x0C, 0x66, 0x9E, 0x61, \n  0xFE, 0x18, 0xE6, 0x0F, 0x60, 0x30, 0x18, 0xC6, 0xCC, 0x64, 0x30, 0xC0, \n  0x80, 0x01, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x67, 0x98, \n  0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, \n  0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, 0x01, 0x18, 0x18, 0xC6, \n  0x8C, 0x6D, 0x78, 0x18, 0x06, 0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB0, 0x61, 0x30, \n  0x0E, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x8E, 0xC1, 0x00, 0x03, 0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0x01, \n  0x06, 0x00, 0x00, 0x0C, 0xF8, 0x07, 0x06, 0x0C, 0x9B, 0x19, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, \n  0x0C, 0x66, 0x9C, 0x61, 0x06, 0x18, 0xE6, 0x01, 0x60, 0x30, 0x18, 0xC6, \n  0xCC, 0x6E, 0x78, 0xC0, 0xC0, 0x00, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0xF9, 0x07, 0x83, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x07, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, \n  0x3F, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x30, 0x18, 0x06, 0x03, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, \n  0x7F, 0xB0, 0x31, 0x30, 0x0C, 0x00, 0x18, 0x80, 0x61, 0x0C, 0x0C, 0x00, \n  0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0x80, 0x01, 0x60, 0xFE, 0x01, 0x66, \n  0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x18, 0x00, 0x00, 0x03, 0x0C, \n  0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, \n  0x60, 0x8C, 0x19, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x03, \n  0x60, 0x30, 0x18, 0x86, 0xC7, 0x7B, 0xCC, 0xC0, 0x60, 0x00, 0x06, 0x60, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, \n  0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, \n  0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, \n  0x86, 0x01, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x33, 0xB0, 0xB1, 0x33, 0x0C, 0x00, 0x30, 0xC0, \n  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0xC0, 0x80, \n  0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x03, 0x0C, 0x30, \n  0x00, 0x80, 0x01, 0x00, 0x03, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, \n  0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x31, 0x06, 0x0C, 0x66, 0x98, 0x61, \n  0x06, 0x18, 0x66, 0x86, 0x61, 0x30, 0x18, 0x86, 0xC7, 0x71, 0xCC, 0xC0, \n  0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, \n  0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0x86, \n  0x87, 0x6D, 0xCC, 0x18, 0xC6, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB6, 0x99, 0x62, \n  0x1E, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, \n  0x86, 0xC1, 0x60, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, \n  0x03, 0x03, 0x0C, 0x60, 0x00, 0xC0, 0x00, 0x0C, 0x03, 0x18, 0x66, 0x98, \n  0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x61, 0x06, \n  0x0C, 0x66, 0x98, 0x61, 0x06, 0x98, 0x67, 0x8C, 0x61, 0x30, 0x18, 0x06, \n  0xC3, 0x60, 0x86, 0xC1, 0x60, 0x00, 0x06, 0xC0, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, \n  0x61, 0x18, 0x18, 0x06, 0x83, 0x6D, 0x86, 0x19, 0x66, 0x00, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0xFC, 0x98, 0xC3, 0x1B, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x83, 0x01, 0xFC, 0xF0, 0xE3, 0x1F, 0x3F, 0x80, 0xF1, 0xC3, \n  0x0F, 0x0C, 0xFC, 0xF0, 0x01, 0x00, 0x0C, 0xC0, 0x00, 0x60, 0x00, 0x0C, \n  0xFE, 0x19, 0xE6, 0x0F, 0x3F, 0x7E, 0xF8, 0x67, 0x00, 0x3F, 0x86, 0xE1, \n  0xC1, 0x87, 0x61, 0xFE, 0x0D, 0x66, 0x18, 0x3F, 0x06, 0xF0, 0x63, 0x18, \n  0x3F, 0x30, 0xF0, 0x03, 0x43, 0x40, 0x86, 0xC1, 0xE0, 0x1F, 0x1E, 0xC0, \n  0xE0, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE7, 0x0F, 0x3F, 0xFC, 0xF1, 0x03, \n  0x03, 0x7F, 0x86, 0xE1, 0x01, 0x8C, 0x61, 0x78, 0xD8, 0x66, 0x18, 0x3F, \n  0xFE, 0xF0, 0x67, 0x00, 0x3F, 0xF0, 0xF0, 0x07, 0x03, 0x3F, 0x86, 0xF1, \n  0xE7, 0x1F, 0x38, 0x30, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, \n  0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, \n  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  };\n#define font20_width 987\n#define font20_height 20\nstatic unsigned char font20_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, \n  0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0xC0, 0x0C, 0x33, 0x30, 0x00, 0xC0, 0x03, 0x0C, 0x60, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x0F, \n  0x3F, 0x80, 0xF9, 0x87, 0x8F, 0x7F, 0xFC, 0xF0, 0x03, 0x00, 0x00, 0x80, \n  0x01, 0x60, 0x00, 0x1E, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0x7E, 0xF8, 0xE7, \n  0x1F, 0x3F, 0x86, 0xE1, 0x01, 0x9E, 0x61, 0x06, 0x04, 0x64, 0x18, 0x3F, \n  0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0xFE, 0x19, 0x66, 0xD8, 0x60, 0x86, 0x19, \n  0xE6, 0x1F, 0x1E, 0x00, 0xE0, 0xC1, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x1E, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x38, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x70, 0x60, 0x1B, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0xFC, 0x38, 0x63, \n  0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x86, 0xE1, 0x60, 0x98, 0x61, 0xC0, 0x19, 0xC0, 0x80, 0x61, 0x86, 0x19, \n  0x06, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x33, 0x83, 0x19, 0x66, 0x98, \n  0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x61, 0x06, \n  0x0C, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, \n  0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, 0x80, 0x61, 0x18, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0xC0, \n  0x00, 0x8C, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, \n  0xC0, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0xB6, 0x29, 0x63, 0x06, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x30, 0x86, 0xF1, 0x60, 0x98, 0x61, 0xE0, 0x19, 0x60, \n  0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0x60, 0x00, 0x80, 0x81, 0x61, \n  0x83, 0x19, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x31, 0x06, 0x1C, 0x67, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, \n  0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, \n  0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xB8, 0x61, 0x06, 0x00, 0x18, 0x80, \n  0x61, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xC1, 0x60, 0x18, \n  0x60, 0xB0, 0x19, 0x60, 0x00, 0x60, 0x86, 0x19, 0x06, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x83, 0x61, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, \n  0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x06, 0xBC, 0x67, 0x98, 0x61, \n  0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x30, \n  0x03, 0x18, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0x7F, 0x36, 0x80, 0xC1, \n  0x03, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, \n  0xC6, 0xC1, 0x00, 0x18, 0x60, 0x98, 0x19, 0x60, 0x00, 0x30, 0x86, 0x19, \n  0x06, 0x03, 0x0C, 0x18, 0xF8, 0x07, 0x06, 0x60, 0x9B, 0x19, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, \n  0xEC, 0xE6, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, \n  0xD8, 0x60, 0xCC, 0x30, 0x03, 0x0C, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0xF0, 0xE3, 0x0F, 0x3F, 0xFC, 0xF1, 0xC3, 0x0F, 0x7F, 0xFE, 0xE0, \n  0x00, 0x8E, 0x61, 0x30, 0xF8, 0xE3, 0x0F, 0x3F, 0xFE, 0xF0, 0x67, 0x1F, \n  0x3F, 0x7E, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x1F, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0x36, 0xC0, 0x80, 0x01, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, \n  0x00, 0x00, 0x00, 0x0C, 0xE6, 0xC1, 0x00, 0x18, 0x60, 0x8C, 0xF9, 0xE3, \n  0x0F, 0x30, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x30, \n  0x9B, 0x19, 0xE6, 0x8F, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, \n  0x00, 0x8C, 0x07, 0x06, 0x4C, 0xE6, 0x99, 0x61, 0x86, 0x19, 0x66, 0x98, \n  0x01, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x78, 0x30, 0x03, 0x06, 0x06, 0x18, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, \n  0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, \n  0x86, 0x19, 0xE6, 0x81, 0x61, 0x18, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, \n  0x06, 0x18, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0xC0, 0xC0, 0x19, 0x00, 0x18, 0x80, \n  0xF1, 0x9F, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x0C, 0xB6, 0xC1, 0x00, 0x0C, \n  0x3E, 0x86, 0x01, 0x66, 0x18, 0x18, 0xFC, 0x18, 0x06, 0x00, 0x00, 0x06, \n  0x00, 0x00, 0x18, 0x18, 0x9B, 0xF9, 0x67, 0x98, 0x01, 0x86, 0xF9, 0xE1, \n  0x87, 0x79, 0xFE, 0xC1, 0x00, 0x8C, 0x03, 0x06, 0x0C, 0x66, 0x9B, 0x61, \n  0xFE, 0x18, 0xE6, 0x0F, 0x3F, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x30, 0xE0, \n  0x01, 0x03, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, \n  0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x80, 0x01, 0x18, 0x18, 0x66, \n  0x98, 0x61, 0xCC, 0x18, 0x06, 0x0C, 0x07, 0x30, 0x80, 0x03, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB0, 0x61, 0x60, \n  0x1B, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x9E, 0xC1, 0x00, 0x06, 0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0xF1, \n  0x07, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x9B, 0x19, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x06, \n  0x0C, 0x66, 0x9E, 0x61, 0x06, 0x18, 0xE6, 0x01, 0x60, 0x30, 0x18, 0xC6, \n  0xCC, 0x64, 0x78, 0xC0, 0x80, 0x01, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0xF0, 0x67, 0x98, 0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, \n  0x01, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, 0x06, 0x06, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, \n  0x7F, 0xB0, 0x61, 0x30, 0x0E, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, \n  0x00, 0x00, 0x00, 0x06, 0x8E, 0xC1, 0x00, 0x03, 0x60, 0x86, 0x01, 0x66, \n  0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x18, 0xF8, 0x07, 0x06, 0x0C, \n  0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x0D, 0x06, 0x0C, 0x66, 0x9C, 0x61, 0x06, 0x18, 0x66, 0x03, \n  0x60, 0x30, 0x18, 0xC6, 0xCC, 0x6E, 0xCC, 0xC0, 0xC0, 0x00, 0x06, 0x30, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0xF9, 0x07, \n  0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x30, 0xD8, 0x66, 0x98, 0x61, \n  0x86, 0x19, 0x66, 0x00, 0x3F, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x30, 0x18, \n  0x06, 0x03, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x33, 0xB0, 0x31, 0x30, 0x0C, 0x00, 0x18, 0x80, \n  0x61, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0x80, 0x01, \n  0x60, 0xFE, 0x01, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x03, 0x00, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, \n  0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x19, 0x06, 0x0C, 0x66, 0x98, 0x61, \n  0x06, 0x18, 0x66, 0x06, 0x60, 0x30, 0x18, 0x86, 0xC7, 0x7B, 0xCC, 0xC0, \n  0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, \n  0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, \n  0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0xC6, \n  0x8C, 0x6D, 0x78, 0x18, 0x86, 0x01, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xB6, 0xB1, 0x33, \n  0x0C, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, \n  0x86, 0xC1, 0xC0, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, \n  0x06, 0x03, 0x0C, 0x60, 0x00, 0x80, 0x01, 0x00, 0x03, 0x18, 0x66, 0x98, \n  0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x31, 0x06, \n  0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x8C, 0x61, 0x30, 0x18, 0x86, \n  0xC7, 0x71, 0x86, 0xC1, 0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, \n  0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, \n  0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, \n  0x60, 0x18, 0x18, 0x86, 0x87, 0x6D, 0xCC, 0x18, 0xC6, 0x00, 0x0C, 0x30, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x33, 0xFC, 0x98, 0x62, 0x1E, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x83, 0x01, 0x86, 0xC1, 0x60, 0x80, 0x61, 0x80, 0x19, 0x66, \n  0x18, 0x0C, 0x86, 0x01, 0x03, 0x03, 0x0C, 0xC0, 0x00, 0xC0, 0x00, 0x0C, \n  0x03, 0x18, 0x66, 0x98, 0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, \n  0x60, 0x8C, 0x61, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x98, 0x67, 0x98, \n  0x61, 0x30, 0x18, 0x06, 0xC3, 0x60, 0x86, 0xC1, 0x60, 0x00, 0x06, 0xC0, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, \n  0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, \n  0x86, 0x19, 0x66, 0x80, 0x61, 0x18, 0x18, 0x06, 0x83, 0x6D, 0x86, 0x19, \n  0x66, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x00, 0x33, 0x30, 0x98, 0xC3, 0x1B, 0x00, 0x60, 0x60, \n  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, 0xFC, 0xF0, 0xE3, 0x1F, \n  0x3F, 0x80, 0xF1, 0xC3, 0x0F, 0x0C, 0xFC, 0xF0, 0x01, 0x00, 0x0C, 0x80, \n  0x01, 0x60, 0x00, 0x0C, 0xFE, 0x19, 0xE6, 0x0F, 0x3F, 0x7E, 0xF8, 0x67, \n  0x00, 0x3F, 0x86, 0xE1, 0xC1, 0x87, 0x61, 0xFE, 0x0D, 0x66, 0x18, 0x3F, \n  0x06, 0xF0, 0x63, 0x18, 0x3F, 0x30, 0xF0, 0x03, 0x43, 0x40, 0x86, 0xC1, \n  0xE0, 0x1F, 0x1E, 0xC0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE7, 0x0F, \n  0x3F, 0xFC, 0xF1, 0x03, 0x03, 0x7F, 0x86, 0xE1, 0x01, 0x8C, 0x61, 0x78, \n  0xD8, 0x66, 0x18, 0x3F, 0xFE, 0xF0, 0x67, 0x00, 0x3F, 0xF0, 0xF0, 0x07, \n  0x03, 0x3F, 0x86, 0xF1, 0xE7, 0x1F, 0x38, 0x30, 0x70, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, \n  0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };\n#define font22_width 1086\n#define font22_height 22\nstatic unsigned char font22_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x70, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, \n  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x33, 0x98, 0x01, 0x03, 0xC7, 0xF0, 0x01, 0x06, 0xC0, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xF8, 0x00, \n  0x03, 0x3E, 0xF0, 0x01, 0x30, 0xFF, 0xE1, 0xC7, 0x7F, 0xF8, 0xC0, 0x07, \n  0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F, 0xFC, 0xC0, 0x87, 0x3F, \n  0xF0, 0xE1, 0x0F, 0xFF, 0xF9, 0x0F, 0x1F, 0x06, 0xE3, 0x07, 0xF8, 0x0D, \n  0x66, 0x80, 0x00, 0x19, 0x0C, 0x1F, 0xFE, 0xC0, 0x87, 0x3F, 0xF0, 0xF1, \n  0x3F, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x1B, 0x98, 0xFF, 0xF0, 0x61, 0x00, \n  0x7C, 0x60, 0x03, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, \n  0x80, 0x0F, 0x00, 0x06, 0x00, 0x03, 0x60, 0x18, 0x80, 0x07, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x03, 0x0E, 0x98, 0x0D, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x33, 0x98, 0xC1, 0x8F, 0xCD, \n  0x18, 0x03, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x30, 0x8C, 0x81, 0x03, 0x63, 0x18, 0x03, 0x38, 0x03, 0x30, 0xC0, \n  0x60, 0x8C, 0x61, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x30, 0x80, 0x31, \n  0x86, 0x61, 0x8C, 0x61, 0x18, 0x63, 0x18, 0x03, 0x18, 0x80, 0x31, 0x06, \n  0x83, 0x01, 0x60, 0x0C, 0x66, 0x80, 0x81, 0x19, 0x8C, 0x31, 0x86, 0x61, \n  0x8C, 0x61, 0x18, 0x03, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x1B, 0x18, \n  0xC0, 0x30, 0x60, 0x00, 0x60, 0x30, 0x06, 0x00, 0x00, 0x00, 0x80, 0x01, \n  0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x06, 0x00, 0x03, 0x60, 0x18, \n  0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x03, \n  0x18, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x33, \n  0x98, 0x61, 0x9B, 0x6D, 0x18, 0x03, 0x06, 0x30, 0x00, 0x03, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0xC3, 0x83, 0xC1, 0x0C, 0x06, \n  0x3C, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x33, 0x18, 0x00, 0x00, 0x00, 0x06, \n  0x00, 0x60, 0xC0, 0x60, 0x03, 0x33, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, \n  0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x0C, 0x63, 0x80, 0xC3, 0x19, \n  0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x0C, 0x06, 0x03, 0x83, 0x19, 0x6C, \n  0x60, 0x8C, 0x31, 0x0C, 0xC0, 0x30, 0xC0, 0x00, 0x60, 0x18, 0x0C, 0x00, \n  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x06, \n  0x00, 0x03, 0x60, 0x18, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x98, 0x31, 0x33, 0x67, 0x18, 0x03, 0x00, 0x30, \n  0x00, 0x83, 0x61, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x63, \n  0x83, 0xC1, 0x00, 0x06, 0x36, 0x03, 0x18, 0x00, 0x60, 0x06, 0x33, 0x18, \n  0x0C, 0x60, 0x00, 0x03, 0x00, 0xC0, 0xC0, 0x60, 0xE3, 0x33, 0x98, 0xC1, \n  0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x8C, \n  0x61, 0x80, 0xE7, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x0C, 0x00, \n  0x03, 0x83, 0x19, 0x6C, 0x60, 0x8C, 0x31, 0x0C, 0xC0, 0x30, 0xC0, 0x00, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, \n  0xC0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x06, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xFE, 0x37, 0x03, 0x30, \n  0xB0, 0x01, 0x00, 0x18, 0x00, 0x06, 0x33, 0x60, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x0C, 0x86, 0x03, 0x83, 0xC1, 0x00, 0x06, 0x33, 0x03, 0x18, 0x00, \n  0x30, 0x06, 0x33, 0x18, 0x0C, 0x60, 0x80, 0x01, 0xFF, 0x81, 0x01, 0x60, \n  0x33, 0x33, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x00, 0x06, \n  0x83, 0x01, 0x60, 0xCC, 0x60, 0x80, 0xBD, 0x39, 0xCC, 0x60, 0x06, 0x33, \n  0x98, 0xC1, 0x0C, 0x00, 0x03, 0x83, 0x19, 0x6C, 0x60, 0xD8, 0x60, 0x06, \n  0x60, 0x30, 0x80, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x87, 0x3F, \n  0xF0, 0x81, 0x3F, 0x7C, 0xF8, 0x07, 0x7F, 0xFE, 0xC0, 0x03, 0x78, 0x18, \n  0x06, 0x86, 0x7F, 0xF8, 0x03, 0x1F, 0xFE, 0xC0, 0x9F, 0xF9, 0xF8, 0xE3, \n  0x1F, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x33, 0x98, 0xFF, 0x60, 0x00, 0x03, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, \n  0x98, 0x31, 0x03, 0x30, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x06, 0x1E, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC6, 0x03, 0x03, 0xC0, 0x00, 0x83, \n  0x31, 0x7F, 0xF8, 0x03, 0x30, 0x8C, 0x31, 0x18, 0x0C, 0x60, 0xC0, 0x00, \n  0x00, 0x00, 0x03, 0x30, 0x1B, 0x33, 0x98, 0x61, 0x0C, 0x60, 0x30, 0x03, \n  0x18, 0xC0, 0x00, 0x06, 0x83, 0x01, 0x60, 0x6C, 0x60, 0x80, 0x99, 0x79, \n  0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x18, 0x00, 0x03, 0x83, 0x31, 0x66, \n  0x60, 0xD8, 0x60, 0x06, 0x30, 0x30, 0x80, 0x01, 0x60, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x8C, 0x61, 0x18, 0xC3, 0x30, 0xC6, 0xC0, 0x80, 0x61, 0x86, \n  0x01, 0x03, 0x60, 0x18, 0x03, 0x86, 0xD9, 0x18, 0x86, 0x31, 0x86, 0x61, \n  0x98, 0x0D, 0x0C, 0x06, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x33, 0x18, \n  0xC0, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x98, 0x61, 0x03, 0x18, 0xF0, 0x00, 0x00, 0x18, \n  0x00, 0x06, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x66, 0x03, \n  0x03, 0x60, 0xE0, 0xC1, 0x30, 0xC0, 0x18, 0x06, 0x18, 0xF8, 0x30, 0x18, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x18, 0x1B, 0x33, 0x98, 0x3F, \n  0x0C, 0x60, 0x30, 0x7F, 0xF8, 0xC3, 0x00, 0xFE, 0x83, 0x01, 0x60, 0x3C, \n  0x60, 0x80, 0x81, 0xD9, 0xCC, 0x60, 0x86, 0x31, 0x98, 0x61, 0xF0, 0x01, \n  0x03, 0x83, 0x31, 0x66, 0x60, 0x70, 0xC0, 0x03, 0x18, 0x30, 0x00, 0x03, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x83, \n  0xC1, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x98, 0x01, 0x86, 0x99, 0x19, \n  0xCC, 0x60, 0x06, 0x33, 0x98, 0x07, 0x0C, 0x00, 0x03, 0x83, 0x19, 0x6C, \n  0x60, 0x8C, 0x31, 0x18, 0x60, 0x38, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0xC1, 0x0F, 0x18, \n  0x98, 0x0D, 0x00, 0x18, 0x00, 0xC6, 0xFF, 0xFE, 0x07, 0x00, 0xFF, 0x01, \n  0x00, 0x06, 0x36, 0x03, 0x03, 0x30, 0x00, 0x63, 0x30, 0x80, 0x19, 0x0C, \n  0x18, 0x8C, 0x61, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x0C, \n  0x1B, 0xF3, 0x9F, 0x61, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x7C, 0x06, \n  0x83, 0x01, 0x60, 0x3C, 0x60, 0x80, 0x81, 0x99, 0xCD, 0x60, 0xFE, 0x30, \n  0x98, 0x3F, 0x00, 0x03, 0x03, 0x83, 0x31, 0x66, 0x66, 0x70, 0xC0, 0x03, \n  0x0C, 0x30, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xC1, \n  0x0C, 0x60, 0x30, 0x83, 0xC1, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0xD8, \n  0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x03, 0x0C, 0x00, \n  0x03, 0x83, 0x31, 0x66, 0x66, 0xD8, 0x30, 0x18, 0x30, 0x60, 0x00, 0x03, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, \n  0x98, 0x01, 0x1B, 0x0C, 0x0C, 0x0F, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1E, 0x03, 0x03, 0x18, 0x00, 0x66, \n  0x30, 0x80, 0x19, 0x0C, 0x0C, 0x06, 0xC3, 0x1F, 0x00, 0x00, 0xC0, 0x00, \n  0x00, 0x00, 0x03, 0x0C, 0x1B, 0x33, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, \n  0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x6C, 0x60, 0x80, 0x81, 0x19, \n  0xCF, 0x60, 0x06, 0x30, 0x98, 0x07, 0x00, 0x06, 0x03, 0x83, 0x31, 0x66, \n  0x66, 0xD8, 0x80, 0x01, 0x06, 0x30, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, \n  0x00, 0xE0, 0x9F, 0xC1, 0x0C, 0x60, 0x30, 0xFF, 0xC1, 0xC0, 0x60, 0x06, \n  0x03, 0x03, 0x60, 0x78, 0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, \n  0x98, 0x01, 0xF8, 0x03, 0x03, 0x83, 0x31, 0x66, 0x66, 0x70, 0x30, 0x18, \n  0x18, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x33, 0x0C, 0x0C, 0x06, 0x00, 0x18, \n  0x00, 0x06, 0x1E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x03, \n  0x03, 0x0C, 0x00, 0x66, 0x30, 0x80, 0x19, 0x0C, 0x0C, 0x06, 0x03, 0x18, \n  0x00, 0x00, 0x80, 0x01, 0xFF, 0x81, 0x01, 0x00, 0x33, 0x33, 0x98, 0xC1, \n  0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x81, 0x61, 0xCC, \n  0x60, 0x80, 0x81, 0x19, 0xCE, 0x60, 0x06, 0x30, 0x98, 0x0D, 0x00, 0x06, \n  0x03, 0x83, 0x61, 0x63, 0x6F, 0xD8, 0x80, 0x01, 0x03, 0x30, 0x00, 0x06, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, \n  0xC0, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x78, 0x00, 0x86, 0x99, 0x19, \n  0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0x00, 0x06, 0x03, 0x83, 0x31, 0x66, \n  0x66, 0x70, 0x30, 0x18, 0x0C, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x33, 0xE6, \n  0x0C, 0x06, 0x00, 0x30, 0x00, 0x03, 0x33, 0x60, 0x00, 0x03, 0x00, 0x00, \n  0x80, 0x01, 0x06, 0x03, 0x03, 0x06, 0x00, 0xE6, 0x3F, 0x83, 0x19, 0x0C, \n  0x06, 0x06, 0x03, 0x18, 0x0C, 0x60, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, \n  0xE3, 0x33, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, \n  0x83, 0x81, 0x61, 0x8C, 0x61, 0x80, 0x81, 0x19, 0xCC, 0x60, 0x06, 0x30, \n  0x98, 0x19, 0x00, 0x06, 0x03, 0x83, 0x61, 0xE3, 0x79, 0x8C, 0x81, 0x81, \n  0x01, 0x30, 0x00, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0xC1, \n  0x0C, 0x60, 0x30, 0x03, 0xC0, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0xD8, \n  0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0x00, 0x06, \n  0x03, 0x83, 0x61, 0x63, 0x66, 0xD8, 0x30, 0x18, 0x06, 0x60, 0x00, 0x03, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, \n  0x98, 0x31, 0x33, 0xB6, 0x0D, 0x06, 0x00, 0x30, 0x00, 0x83, 0x61, 0x60, \n  0x00, 0x03, 0x00, 0xC0, 0x80, 0x01, 0x06, 0x03, 0x03, 0x03, 0x0C, 0x06, \n  0x30, 0x83, 0x19, 0x0C, 0x06, 0x06, 0x03, 0x18, 0x0C, 0x60, 0x00, 0x06, \n  0x00, 0x60, 0x00, 0x0C, 0x03, 0x30, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, \n  0x18, 0xC0, 0x60, 0x06, 0x83, 0x81, 0x61, 0x0C, 0x63, 0x80, 0x81, 0x19, \n  0xCC, 0x60, 0x06, 0x30, 0x98, 0x31, 0x0C, 0x06, 0x03, 0x83, 0xC1, 0xE1, \n  0x70, 0x8C, 0x81, 0x81, 0x01, 0x30, 0x00, 0x0C, 0x60, 0x00, 0x00, 0x00, \n  0x00, 0x30, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0xC0, 0xC0, 0x60, 0x06, \n  0x03, 0x03, 0x60, 0x98, 0x01, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, \n  0x98, 0x01, 0x00, 0x06, 0x03, 0x83, 0x61, 0x63, 0x66, 0x8C, 0x31, 0x18, \n  0x03, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x98, 0x61, 0x1B, 0xB3, 0x19, 0x0F, 0x00, 0x60, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xC0, 0xC0, 0x00, 0x8C, 0x01, \n  0x83, 0x01, 0x18, 0x03, 0x30, 0xC6, 0x30, 0x06, 0x06, 0x8C, 0x01, 0x0C, \n  0x0C, 0x60, 0x00, 0x0C, 0x00, 0x30, 0x00, 0x0C, 0x06, 0x30, 0x98, 0x61, \n  0x18, 0x63, 0x18, 0x03, 0x18, 0x80, 0x31, 0x06, 0x83, 0x01, 0x33, 0x0C, \n  0x66, 0x80, 0x81, 0x19, 0x8C, 0x31, 0x06, 0x60, 0x8F, 0x61, 0x18, 0x03, \n  0x03, 0xC6, 0xC0, 0x61, 0x60, 0x06, 0x83, 0x81, 0x01, 0x30, 0x00, 0x18, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0x61, 0x18, 0xC3, 0x30, 0x86, \n  0xC1, 0x80, 0x61, 0x06, 0x03, 0x03, 0x60, 0x18, 0x03, 0x86, 0x99, 0x19, \n  0x8C, 0x31, 0x86, 0x61, 0x98, 0x01, 0x0C, 0x06, 0x03, 0x86, 0xC1, 0x61, \n  0x66, 0x06, 0x63, 0x98, 0x01, 0xC0, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0xC1, 0x0F, 0xE3, \n  0xF0, 0x0D, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xC0, \n  0xC0, 0x00, 0xF8, 0xE0, 0x9F, 0xFF, 0xF0, 0x01, 0x30, 0x7C, 0xE0, 0x03, \n  0x06, 0xF8, 0xE0, 0x07, 0x00, 0x60, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0C, \n  0xFC, 0x33, 0x98, 0x3F, 0xF0, 0xE1, 0x0F, 0xFF, 0x19, 0x00, 0x1F, 0x06, \n  0xE3, 0x07, 0x1E, 0x0C, 0xE6, 0xBF, 0x81, 0x19, 0x0C, 0x1F, 0x06, 0xC0, \n  0x87, 0xC1, 0xF0, 0x01, 0x03, 0x7C, 0xC0, 0x21, 0x40, 0x06, 0x83, 0x81, \n  0xFF, 0xF0, 0x01, 0x18, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x9F, 0x3F, \n  0xF0, 0x81, 0x3F, 0xFC, 0xC0, 0x00, 0x7F, 0x06, 0xC3, 0x0F, 0x60, 0x18, \n  0x86, 0x9F, 0x99, 0x19, 0x0C, 0x1F, 0xFE, 0xC0, 0x9F, 0x01, 0xF8, 0x03, \n  0x3E, 0xFC, 0xC1, 0xC1, 0x3F, 0x06, 0xC3, 0x9F, 0xFF, 0x80, 0x03, 0x03, \n  0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x63, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, \n  0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, };\n#define font24_width 1185\n#define font24_height 24\nstatic unsigned char font24_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x60, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x66, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x98, \n  0x81, 0x19, 0x60, 0x00, 0x00, 0x70, 0x00, 0x06, 0xC0, 0x80, 0x01, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x06, 0xF8, \n  0x81, 0x1F, 0x00, 0xE6, 0x7F, 0xF8, 0xE3, 0x7F, 0xF8, 0x81, 0x1F, 0x00, \n  0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x80, 0x1F, 0xFC, 0x81, 0x1F, 0xFE, \n  0x81, 0x1F, 0xFE, 0xE1, 0x7F, 0xFE, 0x87, 0x1F, 0x06, 0x86, 0x1F, 0xC0, \n  0x6F, 0x60, 0x06, 0x10, 0x40, 0x06, 0x86, 0x1F, 0xFE, 0x81, 0x1F, 0xFE, \n  0x81, 0x1F, 0xFE, 0x67, 0x60, 0x06, 0x36, 0x60, 0x06, 0x66, 0x60, 0xFE, \n  0x87, 0x0F, 0x00, 0x80, 0x0F, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x00, 0x00, 0x00, 0x06, 0x00, 0xC0, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, \n  0xC3, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x1C, 0x60, 0xC0, 0x01, 0x66, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x06, 0x98, 0x81, 0x19, 0xF8, 0xC1, 0x31, 0xD8, 0x00, \n  0x06, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x30, 0x0C, 0x03, 0x07, 0x0C, 0xC3, 0x30, 0x00, 0x67, 0x00, 0x0C, 0x60, \n  0x60, 0x0C, 0xC3, 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0C, 0xC0, \n  0x30, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x30, 0x06, 0x63, 0x00, 0x06, 0xC0, \n  0x30, 0x06, 0x06, 0x06, 0x00, 0x63, 0x30, 0x06, 0x30, 0x60, 0x06, 0xC6, \n  0x30, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x30, 0x60, 0x60, 0x60, 0x06, 0x36, \n  0x60, 0x06, 0x66, 0x60, 0x00, 0x86, 0x01, 0x0C, 0x00, 0x0C, 0x0C, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, \n  0x00, 0x06, 0x00, 0x06, 0x00, 0xC3, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x03, 0xC6, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x98, 0x81, 0x19, \n  0x6C, 0x63, 0x33, 0x8C, 0x01, 0x06, 0x30, 0x00, 0x06, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x86, 0x07, 0x06, 0x66, 0x60, \n  0x80, 0x67, 0x00, 0x06, 0x60, 0x60, 0x06, 0x66, 0x60, 0x00, 0x00, 0x00, \n  0xC0, 0x00, 0x00, 0x18, 0x60, 0x60, 0x03, 0x66, 0x60, 0x06, 0x66, 0x60, \n  0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0x63, 0x18, \n  0x06, 0x70, 0x70, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, \n  0x60, 0x60, 0x60, 0x06, 0x36, 0x60, 0x0C, 0xC3, 0x30, 0x00, 0x86, 0x01, \n  0x0C, 0x00, 0x0C, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, \n  0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC3, 0x00, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, \n  0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x06, 0x00, 0x80, 0x19, 0x66, 0x66, 0x1B, 0x8C, 0x01, 0x00, 0x30, \n  0x00, 0x06, 0x06, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, \n  0xC6, 0x06, 0x06, 0x06, 0x60, 0xC0, 0x66, 0x00, 0x06, 0x00, 0x60, 0x06, \n  0x66, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x60, 0x60, 0xC3, \n  0x67, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, \n  0x06, 0x06, 0x00, 0x63, 0x0C, 0x06, 0xF0, 0x78, 0x06, 0x66, 0x60, 0x06, \n  0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x36, 0x60, 0x0C, \n  0xC3, 0x30, 0x00, 0x86, 0x01, 0x18, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x06, \n  0x00, 0x00, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xE0, 0x7F, 0x66, 0xC0, \n  0x19, 0x8C, 0x01, 0x00, 0x18, 0x00, 0x0C, 0x8C, 0x01, 0x06, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x18, 0x06, 0x07, 0x06, 0x06, 0x06, 0x60, 0x60, 0x66, \n  0x00, 0x06, 0x00, 0x30, 0x06, 0x66, 0x60, 0x60, 0x00, 0x06, 0x30, 0x00, \n  0x00, 0x60, 0x60, 0x60, 0x63, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, \n  0x00, 0x06, 0x60, 0x00, 0x06, 0x06, 0x06, 0x00, 0x63, 0x06, 0x06, 0xB0, \n  0x6D, 0x0E, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, \n  0x60, 0x0C, 0x33, 0x60, 0x98, 0x81, 0x19, 0x00, 0x83, 0x01, 0x18, 0x00, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0xFE, 0x81, 0x1F, 0xF8, 0x87, \n  0x1F, 0xFC, 0x83, 0x7F, 0xFE, 0x81, 0x07, 0xC0, 0xC3, 0x60, 0x60, 0xE0, \n  0x1F, 0xFE, 0x81, 0x1F, 0xFE, 0x81, 0x7F, 0xE6, 0xC7, 0x3F, 0xFE, 0x61, \n  0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0xFE, 0x07, 0x03, 0x60, 0x00, \n  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x00, 0x80, 0x19, 0x66, 0x00, 0x0C, 0xD8, 0x00, 0x00, 0x18, 0x00, 0x0C, \n  0xD8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x86, 0x07, 0x06, \n  0x00, 0x06, 0x60, 0x30, 0x66, 0x00, 0x06, 0x00, 0x30, 0x06, 0x66, 0x60, \n  0x60, 0x00, 0x06, 0x18, 0xE0, 0x7F, 0xC0, 0x00, 0x30, 0x33, 0x66, 0x60, \n  0x06, 0x63, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x00, 0x06, 0x06, 0x06, \n  0x00, 0x63, 0x03, 0x06, 0x30, 0x67, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x60, \n  0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0x98, 0x81, 0x19, \n  0x80, 0x81, 0x01, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x06, 0xC3, 0x30, 0x0C, 0xC6, 0x30, 0x60, 0xC0, 0x60, 0x06, 0x03, 0x06, \n  0x00, 0xC3, 0x30, 0x60, 0x60, 0x36, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x60, \n  0x36, 0x60, 0x60, 0x30, 0x60, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, \n  0x00, 0x06, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x6C, 0x00, 0x0C, 0x70, \n  0x00, 0x00, 0x18, 0x00, 0x0C, 0x70, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x0C, 0xC6, 0x06, 0x06, 0x00, 0x03, 0x30, 0x18, 0xE6, 0x1F, 0xFE, \n  0x01, 0x18, 0x0C, 0x63, 0x60, 0x60, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x80, \n  0x01, 0x18, 0x33, 0x66, 0x60, 0xFE, 0x61, 0x00, 0x06, 0x66, 0x00, 0x06, \n  0x60, 0x00, 0x06, 0x06, 0x06, 0x00, 0xE3, 0x01, 0x06, 0x30, 0x62, 0x36, \n  0x66, 0x60, 0x06, 0x63, 0x60, 0x06, 0xC3, 0x00, 0x60, 0x60, 0x60, 0x0C, \n  0x33, 0x60, 0xF0, 0x00, 0x0F, 0xC0, 0x80, 0x01, 0x30, 0x00, 0x0C, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x60, \n  0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x18, 0x60, 0x60, 0x66, 0x06, \n  0x66, 0x60, 0x06, 0x66, 0x60, 0x1E, 0x60, 0x00, 0x30, 0x60, 0x60, 0x06, \n  0x66, 0x60, 0x0C, 0x63, 0x60, 0x00, 0x03, 0x03, 0x60, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, \n  0x19, 0xF8, 0x01, 0x06, 0x78, 0x06, 0x00, 0x18, 0x00, 0x0C, 0xFF, 0xE7, \n  0x7F, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x06, 0x66, 0x06, 0x06, 0x80, 0x01, \n  0x1F, 0x0C, 0x06, 0x30, 0x06, 0x03, 0x18, 0xF8, 0xC1, 0x60, 0x00, 0x00, \n  0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x33, 0x66, 0x60, 0x06, 0x63, \n  0x00, 0x06, 0xE6, 0x1F, 0xFE, 0x61, 0x7C, 0xFE, 0x07, 0x06, 0x00, 0xE3, \n  0x00, 0x06, 0x30, 0x60, 0x66, 0x66, 0x60, 0xFE, 0x61, 0x60, 0xFE, 0x81, \n  0x1F, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0x60, 0x00, 0x0F, 0x60, 0x80, \n  0x01, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x66, \n  0x00, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, \n  0x0C, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x0E, 0x60, \n  0x00, 0x30, 0x60, 0x60, 0x0C, 0x63, 0x60, 0x98, 0x61, 0x60, 0x80, 0xC1, \n  0x01, 0x60, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x60, 0x03, 0x06, 0xCC, 0x06, 0x00, \n  0x18, 0x00, 0x0C, 0x70, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x36, 0x06, 0x06, 0xC0, 0x00, 0x30, 0x06, 0x06, 0x60, 0x06, 0x06, 0x0C, \n  0x0C, 0x83, 0x7F, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x01, 0x06, \n  0x33, 0xE6, 0x7F, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, \n  0x06, 0x06, 0x06, 0x00, 0xE3, 0x01, 0x06, 0x30, 0x60, 0xC6, 0x66, 0x60, \n  0x06, 0x60, 0x60, 0x1E, 0x00, 0x30, 0x60, 0x60, 0x60, 0x98, 0x31, 0x62, \n  0xF0, 0x00, 0x06, 0x30, 0x80, 0x01, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x7F, 0x06, 0x66, 0x00, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, \n  0x06, 0x06, 0x06, 0x00, 0xC3, 0x06, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, \n  0x06, 0x66, 0x60, 0x06, 0x60, 0x00, 0x30, 0x60, 0x60, 0x0C, 0x63, 0x66, \n  0xF0, 0x60, 0x60, 0xC0, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x60, \n  0x06, 0x03, 0x86, 0x03, 0x00, 0x18, 0x00, 0x0C, 0xD8, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x03, 0x1E, 0x06, 0x06, 0x60, 0x00, 0x60, 0x06, \n  0x06, 0x60, 0x06, 0x06, 0x0C, 0x06, 0x06, 0x60, 0x00, 0x00, 0x00, 0x18, \n  0x00, 0x00, 0xC0, 0x00, 0x06, 0x33, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, \n  0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0x63, 0x03, 0x06, \n  0x30, 0x60, 0x86, 0x67, 0x60, 0x06, 0x60, 0x60, 0x36, 0x00, 0x60, 0x60, \n  0x60, 0x60, 0x98, 0x31, 0x67, 0x98, 0x01, 0x06, 0x18, 0x80, 0x01, 0xC0, \n  0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x06, 0x66, 0x00, 0x06, \n  0xE6, 0x7F, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x03, 0x60, \n  0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0xC0, 0x3F, 0x30, \n  0x60, 0x60, 0x98, 0x61, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x03, 0x60, \n  0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x7F, 0x60, 0x06, 0x03, 0x06, 0x03, 0x00, 0x18, 0x00, \n  0x0C, 0x8C, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x06, \n  0x06, 0x30, 0x00, 0x60, 0x06, 0x06, 0x60, 0x06, 0x06, 0x06, 0x06, 0x06, \n  0x60, 0x00, 0x00, 0x00, 0x30, 0xE0, 0x7F, 0x60, 0x00, 0x00, 0x63, 0x66, \n  0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, \n  0x06, 0x06, 0x63, 0x06, 0x06, 0x30, 0x60, 0x06, 0x67, 0x60, 0x06, 0x60, \n  0x60, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x98, 0xB1, 0x6D, 0x98, 0x01, \n  0x06, 0x0C, 0x80, 0x01, 0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x06, \n  0x06, 0x00, 0xC3, 0x06, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, \n  0x60, 0x06, 0x00, 0x60, 0x30, 0x60, 0x60, 0x98, 0x61, 0x66, 0xF0, 0x60, \n  0x60, 0x30, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x19, 0x66, 0x86, 0x39, \n  0x06, 0x03, 0x00, 0x30, 0x00, 0x06, 0x06, 0x03, 0x06, 0x60, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x06, 0x06, 0x06, 0x18, 0x00, 0x60, 0xFE, 0x07, 0x60, \n  0x06, 0x06, 0x06, 0x06, 0x06, 0x60, 0x60, 0x00, 0x06, 0x60, 0x00, 0x00, \n  0x30, 0x00, 0x00, 0xC3, 0x67, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, \n  0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x06, 0x63, 0x0C, 0x06, 0x30, 0x60, \n  0x06, 0x66, 0x60, 0x06, 0x60, 0x60, 0xC6, 0x00, 0x60, 0x60, 0x60, 0x60, \n  0xF0, 0xF0, 0x78, 0x0C, 0x03, 0x06, 0x06, 0x80, 0x01, 0x80, 0x01, 0x0C, \n  0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, \n  0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x0C, 0x60, 0x60, 0x66, \n  0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x00, 0x60, 0x30, 0x60, 0x60, \n  0xF0, 0x60, 0x66, 0x98, 0x61, 0x60, 0x18, 0x00, 0x03, 0x60, 0x00, 0x06, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x80, 0x19, 0x6C, 0x83, 0x6D, 0x86, 0x03, 0x00, 0x30, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x80, 0x01, 0x06, 0x06, 0x06, 0x0C, \n  0x60, 0x60, 0x00, 0x66, 0x60, 0x06, 0x06, 0x06, 0x06, 0x06, 0x60, 0x60, \n  0x00, 0x06, 0xC0, 0x00, 0x00, 0x18, 0x00, 0x06, 0x03, 0x60, 0x60, 0x06, \n  0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x06, \n  0x63, 0x18, 0x06, 0x30, 0x60, 0x06, 0x66, 0x60, 0x06, 0x60, 0x66, 0x86, \n  0x61, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x70, 0x70, 0x0C, 0x03, 0x06, 0x06, \n  0x80, 0x01, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x06, \n  0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, \n  0xC3, 0x18, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, \n  0x00, 0x60, 0x30, 0x60, 0x60, 0xF0, 0x60, 0x66, 0x0C, 0x63, 0x60, 0x0C, \n  0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0xF8, 0xC1, 0x6C, 0xCC, 0x06, \n  0x00, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0xC0, \n  0x00, 0x0C, 0x03, 0x06, 0x06, 0xC0, 0x30, 0x00, 0xC6, 0x30, 0x0C, 0x03, \n  0x06, 0x0C, 0x03, 0x30, 0x60, 0x00, 0x06, 0x80, 0x01, 0x00, 0x0C, 0x00, \n  0x06, 0x06, 0x60, 0x60, 0x06, 0xC3, 0x30, 0x06, 0x63, 0x00, 0x06, 0xC0, \n  0x30, 0x06, 0x06, 0x06, 0x8C, 0x61, 0x30, 0x06, 0x30, 0x60, 0x06, 0xC6, \n  0x30, 0x06, 0xC0, 0x3C, 0x06, 0xC3, 0x30, 0x60, 0xC0, 0x30, 0x60, 0x30, \n  0x60, 0x06, 0x06, 0x06, 0x06, 0x80, 0x01, 0x00, 0x03, 0x0C, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x60, 0x06, 0xC3, 0x30, 0x0C, 0xC6, 0x60, 0x60, 0xC0, \n  0x70, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x30, 0x60, 0x60, 0x66, 0x06, 0xC6, \n  0x30, 0x06, 0xC3, 0x60, 0x06, 0x60, 0x60, 0x30, 0xC0, 0x60, 0x60, 0x60, \n  0x66, 0x06, 0xC6, 0x70, 0x06, 0x00, 0x06, 0x60, 0x00, 0x03, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, \n  0x60, 0xC0, 0x38, 0x78, 0x06, 0x00, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, \n  0x60, 0x00, 0x00, 0x60, 0xC0, 0x00, 0xF8, 0xC1, 0x3F, 0xFE, 0x87, 0x1F, \n  0x00, 0x86, 0x1F, 0xF8, 0x01, 0x06, 0xF8, 0xC1, 0x1F, 0x00, 0x00, 0x06, \n  0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0xFC, 0x67, 0x60, 0xFE, 0x81, 0x1F, \n  0xFE, 0xE1, 0x7F, 0x06, 0x80, 0x1F, 0x06, 0x86, 0x1F, 0xF8, 0x60, 0x60, \n  0xFE, 0x37, 0x60, 0x06, 0x86, 0x1F, 0x06, 0x80, 0x1F, 0x06, 0x86, 0x1F, \n  0x60, 0x80, 0x1F, 0x60, 0x10, 0x40, 0x06, 0x06, 0x06, 0xFE, 0x87, 0x0F, \n  0x00, 0x83, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0xFE, 0x81, 0x1F, \n  0xF8, 0x87, 0x3F, 0x60, 0x80, 0x7F, 0x06, 0x86, 0x1F, 0x00, 0xC3, 0x60, \n  0xF8, 0x61, 0x66, 0x06, 0x86, 0x1F, 0xFE, 0x81, 0x7F, 0x06, 0xC0, 0x3F, \n  0xE0, 0x83, 0x7F, 0x60, 0xC0, 0x3F, 0x06, 0x86, 0x7F, 0xFE, 0x07, 0x1C, \n  0x60, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, \n  0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, \n  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, \n  0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xC0, 0x1F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  };\n#define font28_width 1383\n#define font28_height 28\nstatic unsigned char font28_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x31, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, \n  0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC3, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0x00, 0x00, 0xC0, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, \n  0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, \n  0x31, 0x60, 0x0C, 0xC0, 0x00, 0x0F, 0x03, 0x0F, 0x00, 0x03, 0x80, 0x01, \n  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0xF8, 0x03, 0x30, 0x80, 0x3F, 0xE0, 0x0F, 0x00, 0x8C, 0xFF, 0x83, 0x7F, \n  0xF8, 0x3F, 0xF8, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x0F, 0xF8, 0x07, 0xFE, 0xE0, 0x3F, 0xE0, 0x0F, 0xFE, \n  0x80, 0xFF, 0xE3, 0xFF, 0xE0, 0x0F, 0x06, 0x0C, 0xFC, 0x00, 0xF8, 0x19, \n  0x30, 0x06, 0x80, 0x01, 0x66, 0xC0, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0xE0, \n  0x3F, 0xE0, 0x0F, 0xFE, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, \n  0x01, 0xE6, 0xFF, 0xC0, 0x0F, 0x0C, 0x00, 0xFC, 0x00, 0x1F, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, \n  0x00, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, 0x30, 0x00, 0xF0, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0E, 0xC0, 0x00, 0x0E, 0x60, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xF8, 0x87, 0x1F, 0x83, \n  0x1F, 0x00, 0x03, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x30, 0xFC, 0x07, 0x38, 0xC0, 0x7F, 0xF0, 0x1F, \n  0x00, 0x8E, 0xFF, 0xC3, 0x7F, 0xF8, 0x3F, 0xFC, 0x07, 0xFF, 0x01, 0x00, \n  0x00, 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0xF0, 0x1F, 0xFC, 0x0F, 0xFF, \n  0xE1, 0x7F, 0xF0, 0x1F, 0xFE, 0x83, 0xFF, 0xE3, 0xFF, 0xF0, 0x1F, 0x06, \n  0x0C, 0xFC, 0x00, 0xF8, 0x19, 0x38, 0x06, 0x80, 0x01, 0x66, 0xC0, 0xF0, \n  0x1F, 0xFE, 0x07, 0xFF, 0xE1, 0x7F, 0xF0, 0x1F, 0xFE, 0x9F, 0x01, 0x63, \n  0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE6, 0xFF, 0xC0, 0x0F, 0x0C, 0x00, \n  0xFC, 0x80, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, \n  0x00, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, \n  0x30, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x1E, 0x60, 0xFC, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, \n  0x0C, 0xFC, 0x8F, 0x99, 0xC1, 0x39, 0x00, 0x03, 0x60, 0x00, 0x30, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0E, 0x0E, \n  0x3C, 0xE0, 0xE0, 0x38, 0x38, 0x00, 0x8F, 0x01, 0xE0, 0x00, 0x18, 0x30, \n  0x0E, 0x8E, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, \n  0x38, 0x38, 0x0E, 0x9C, 0x83, 0x63, 0xE0, 0x38, 0x38, 0x06, 0x87, 0x01, \n  0x60, 0x00, 0x38, 0x38, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x18, 0x1C, 0x06, \n  0x80, 0x03, 0x67, 0xC0, 0x38, 0x38, 0x06, 0x8E, 0x83, 0x63, 0xE0, 0x38, \n  0x38, 0xC0, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x0C, 0x06, 0x03, 0x03, \n  0xC0, 0xC0, 0x00, 0x18, 0x00, 0xC0, 0xC0, 0x71, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, \n  0x06, 0x00, 0x30, 0x00, 0x60, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xC0, \n  0x00, 0x38, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xCE, 0x9C, 0x9F, 0xC1, 0x30, 0x00, \n  0x03, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x18, 0x06, 0x0C, 0x3E, 0x60, 0xC0, 0x18, 0x30, 0x80, 0x8F, \n  0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x03, 0x00, 0x00, 0x00, \n  0x80, 0x03, 0x00, 0x80, 0x03, 0x18, 0x30, 0x06, 0x98, 0x01, 0x63, 0xC0, \n  0x18, 0x30, 0x06, 0x86, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, \n  0x00, 0x60, 0x18, 0x0E, 0x06, 0x80, 0x87, 0x67, 0xC0, 0x18, 0x30, 0x06, \n  0x8C, 0x01, 0x63, 0xC0, 0x18, 0x30, 0xC0, 0x80, 0x01, 0x63, 0xC0, 0x18, \n  0x60, 0x0C, 0x06, 0x03, 0x03, 0xC0, 0xC0, 0x00, 0x18, 0x00, 0xC0, 0xE0, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, \n  0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x3F, 0xC6, \n  0x18, 0xCF, 0xC0, 0x30, 0x00, 0x00, 0x30, 0x00, 0x60, 0xC0, 0x71, 0x00, \n  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x0E, 0x30, 0x60, \n  0xC0, 0x00, 0x30, 0xC0, 0x8D, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x8C, \n  0x01, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x07, 0x18, 0x30, \n  0x86, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x60, 0x00, \n  0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x18, 0x07, 0x06, 0x80, 0xCF, \n  0xE7, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x00, 0xC0, \n  0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x18, 0x03, 0x86, 0x01, 0xE0, 0xC0, \n  0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, \n  0x00, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x30, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0xF8, 0x3F, 0xC6, 0x00, 0xC0, 0xC0, 0x39, 0x00, 0x00, 0x30, \n  0x00, 0x60, 0x80, 0x3B, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0C, 0x06, 0x0F, 0x30, 0x60, 0xC0, 0x00, 0x30, 0xE0, 0x8C, 0x01, 0x60, \n  0x00, 0x00, 0x18, 0x06, 0x8C, 0x01, 0x03, 0x0C, 0x00, 0x03, 0xE0, 0x80, \n  0xFF, 0x03, 0x0E, 0x18, 0x30, 0xC6, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x00, \n  0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x30, 0x00, 0x60, \n  0x98, 0x03, 0x06, 0x80, 0xFD, 0xE6, 0xC1, 0x18, 0x30, 0x06, 0x8C, 0x01, \n  0x63, 0xC0, 0x18, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x18, \n  0x03, 0x86, 0x01, 0x70, 0xC0, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xFE, 0xE0, 0x3F, 0xE0, 0x0F, 0xF8, 0x0F, 0xFE, 0xC0, \n  0x3F, 0xE0, 0x3F, 0xFE, 0x03, 0x3C, 0x00, 0x78, 0x30, 0x38, 0xC0, 0x80, \n  0xFF, 0xE1, 0x3F, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0x63, 0xFE, 0xE0, 0x0F, \n  0xFC, 0x83, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE3, 0xFF, \n  0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC6, 0x00, 0x60, \n  0x80, 0x1F, 0x00, 0x00, 0x30, 0x00, 0x60, 0x00, 0x1F, 0x00, 0x03, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x86, 0x0F, 0x30, 0x00, 0xC0, 0x00, \n  0x30, 0x70, 0x8C, 0x01, 0x60, 0x00, 0x00, 0x18, 0x06, 0x8C, 0x01, 0x03, \n  0x0C, 0x00, 0x03, 0x70, 0x80, 0xFF, 0x03, 0x1C, 0x00, 0x38, 0xE6, 0x98, \n  0x01, 0x63, 0x60, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x00, \n  0x06, 0x0C, 0x30, 0x00, 0x60, 0xD8, 0x01, 0x06, 0x80, 0x79, 0xE6, 0xC3, \n  0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x00, 0xC0, 0x80, 0x01, \n  0xC3, 0x60, 0x18, 0x60, 0xB0, 0x01, 0xCC, 0x00, 0x38, 0xC0, 0x00, 0x60, \n  0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE1, 0x7F, 0xF0, \n  0x1F, 0xFC, 0x0F, 0xFF, 0xC1, 0x3F, 0xF0, 0x3F, 0xFE, 0x07, 0x3C, 0x00, \n  0x78, 0x30, 0x1C, 0xC0, 0x80, 0xFF, 0xE3, 0x7F, 0xF0, 0x1F, 0xFE, 0x07, \n  0xFF, 0x63, 0xFF, 0xF0, 0x1F, 0xFC, 0x83, 0x01, 0x63, 0xC0, 0x18, 0x60, \n  0x06, 0x8C, 0x01, 0xE3, 0xFF, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, \n  0x60, 0x0C, 0xCE, 0x00, 0x60, 0x00, 0x0F, 0x00, 0x00, 0x30, 0x00, 0x60, \n  0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xC6, \n  0x0D, 0x30, 0x00, 0xE0, 0x00, 0x38, 0x38, 0x8C, 0xFF, 0xE0, 0x3F, 0x00, \n  0x0C, 0x0E, 0x8E, 0x01, 0x03, 0x0C, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, \n  0x38, 0x00, 0x1C, 0x66, 0x98, 0x01, 0xE3, 0x3F, 0x18, 0x00, 0x06, 0x8C, \n  0x01, 0x60, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF8, 0x00, \n  0x06, 0x80, 0x31, 0x66, 0xC7, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, \n  0x38, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0xB0, 0x01, 0xCC, \n  0x00, 0x1C, 0xC0, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x63, 0xE0, 0x38, 0x38, 0x0E, 0x8C, 0x83, 0x03, 0x06, 0x38, \n  0x30, 0x06, 0x0E, 0x30, 0x00, 0x60, 0x30, 0x0E, 0xC0, 0x80, 0x31, 0x67, \n  0xE0, 0x38, 0x38, 0x06, 0x8E, 0x03, 0xE3, 0x03, 0x38, 0x38, 0x60, 0x80, \n  0x01, 0x63, 0xC0, 0x18, 0x60, 0x0E, 0x8E, 0x01, 0x03, 0xE0, 0x80, 0x01, \n  0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xFC, 0x07, 0x30, 0x00, 0x07, \n  0x00, 0x00, 0x30, 0x00, 0x60, 0xE0, 0xFF, 0xF8, 0x7F, 0x00, 0x80, 0xFF, \n  0x03, 0x00, 0x00, 0x03, 0xE6, 0x0C, 0x30, 0x00, 0x70, 0xC0, 0x1F, 0x1C, \n  0x8C, 0xFF, 0xE1, 0x7F, 0x00, 0x0C, 0xFC, 0x87, 0x03, 0x03, 0x0C, 0x00, \n  0x03, 0x1C, 0x00, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x66, 0x98, 0x01, 0xE3, \n  0x3F, 0x18, 0x00, 0x06, 0x8C, 0x7F, 0xE0, 0x1F, 0x18, 0x3F, 0xFE, 0x0F, \n  0x30, 0x00, 0x60, 0x78, 0x00, 0x06, 0x80, 0x01, 0x66, 0xCE, 0x18, 0x30, \n  0x06, 0x8E, 0x01, 0x63, 0xE0, 0xF0, 0x0F, 0xC0, 0x80, 0x01, 0x83, 0x31, \n  0x18, 0x60, 0xE0, 0x00, 0x78, 0x00, 0x0E, 0xC0, 0x00, 0xC0, 0x00, 0xC0, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xC0, 0x18, 0x00, 0x06, \n  0x8C, 0x01, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, \n  0x07, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0xE3, \n  0x01, 0x18, 0x00, 0x60, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x1C, 0x87, \n  0x01, 0x03, 0x70, 0xE0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, \n  0xF8, 0x0F, 0x30, 0x80, 0x8F, 0x01, 0x00, 0x30, 0x00, 0x60, 0xE0, 0xFF, \n  0xF8, 0x7F, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00, 0x03, 0x76, 0x0C, 0x30, \n  0x00, 0x38, 0xC0, 0x1F, 0x0E, 0x0C, 0x80, 0x63, 0xE0, 0x00, 0x06, 0xFC, \n  0x07, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xE0, 0x00, \n  0x07, 0x66, 0x98, 0xFF, 0x63, 0x60, 0x18, 0x00, 0x06, 0x8C, 0x7F, 0xE0, \n  0x1F, 0x18, 0x3F, 0xFE, 0x0F, 0x30, 0x00, 0x60, 0x78, 0x00, 0x06, 0x80, \n  0x01, 0x66, 0xDC, 0x18, 0x30, 0xFE, 0x87, 0x01, 0xE3, 0x7F, 0xE0, 0x1F, \n  0xC0, 0x80, 0x01, 0x83, 0x31, 0x18, 0x60, 0xE0, 0x00, 0x78, 0x00, 0x07, \n  0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, \n  0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x03, 0x06, 0x18, 0x30, 0x06, \n  0x0C, 0x30, 0x00, 0x60, 0xB0, 0x03, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, \n  0x30, 0x06, 0x8C, 0x01, 0xE3, 0x00, 0x38, 0x00, 0x60, 0x80, 0x01, 0xC3, \n  0x60, 0x18, 0x63, 0xB8, 0x83, 0x01, 0x03, 0x38, 0xE0, 0x00, 0xC0, 0x00, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x30, 0x00, 0x00, 0x60, 0x0C, 0xC0, 0x1C, 0x18, 0xC0, 0xDD, 0x01, 0x00, \n  0x30, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x80, 0x01, 0x3E, 0x0C, 0x30, 0x00, 0x1C, 0x00, 0x38, 0x06, 0x0C, 0x00, \n  0x63, 0xC0, 0x00, 0x06, 0x0E, 0x0E, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x1C, \n  0x00, 0x00, 0x00, 0x70, 0x00, 0x03, 0x66, 0x98, 0xFF, 0x63, 0xC0, 0x18, \n  0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, \n  0x60, 0xF8, 0x00, 0x06, 0x80, 0x01, 0x66, 0xF8, 0x18, 0x30, 0xFE, 0x83, \n  0x01, 0xE3, 0x3F, 0x00, 0x38, 0xC0, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, \n  0xB0, 0x01, 0x30, 0x80, 0x03, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xFF, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0xFF, \n  0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF0, 0x01, 0xC0, \n  0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0xF0, \n  0x0F, 0x60, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x63, 0xF0, 0x81, 0x01, 0x03, \n  0x1C, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC0, 0x18, \n  0x18, 0xE0, 0xF8, 0x00, 0x00, 0x30, 0x00, 0x60, 0x00, 0x1F, 0x00, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x1E, 0x0C, 0x30, 0x00, 0x0E, \n  0x00, 0x30, 0x06, 0x0C, 0x00, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, \n  0x03, 0x00, 0x00, 0x00, 0x38, 0x80, 0xFF, 0x03, 0x38, 0x00, 0x03, 0xE6, \n  0x98, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, \n  0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xD8, 0x01, 0x06, 0x80, 0x01, 0x66, \n  0xF0, 0x18, 0x30, 0x06, 0x80, 0x01, 0xE3, 0x03, 0x00, 0x30, 0xC0, 0x80, \n  0x01, 0x83, 0x31, 0x98, 0x67, 0xB0, 0x01, 0x30, 0xC0, 0x01, 0xC0, 0x00, \n  0x80, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x63, 0xC0, \n  0x18, 0x00, 0x06, 0x8C, 0xFF, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, \n  0x00, 0x60, 0xF0, 0x00, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, \n  0x8C, 0x01, 0x63, 0x00, 0xE0, 0x1F, 0x60, 0x80, 0x01, 0x83, 0x31, 0x18, \n  0x63, 0xE0, 0x80, 0x01, 0x03, 0x0E, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0xF8, 0x3F, 0xC0, 0x18, 0x0C, 0x60, 0x70, 0x00, 0x00, 0x30, 0x00, \n  0x60, 0x80, 0x3B, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, \n  0x0E, 0x0C, 0x30, 0x00, 0x07, 0x00, 0x30, 0xFE, 0x0F, 0x00, 0x63, 0xC0, \n  0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x80, 0xFF, \n  0x03, 0x1C, 0x00, 0x00, 0xC6, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, \n  0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x60, 0x60, 0x98, \n  0x03, 0x06, 0x80, 0x01, 0x66, 0xE0, 0x18, 0x30, 0x06, 0x80, 0x01, 0x63, \n  0x07, 0x00, 0x30, 0xC0, 0x80, 0x01, 0x03, 0x1B, 0xD8, 0x6F, 0x18, 0x03, \n  0x30, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x00, 0x06, \n  0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF0, 0x01, 0xC0, 0x80, 0x31, \n  0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0x00, 0x38, 0x60, \n  0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xF0, 0x81, 0x01, 0x03, 0x07, 0x80, \n  0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xC6, 0x18, 0xCC, 0x63, \n  0x70, 0x00, 0x00, 0x30, 0x00, 0x60, 0xC0, 0x71, 0x00, 0x03, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xC0, 0x00, 0x06, 0x0C, 0x30, 0x80, 0x03, 0x00, 0x30, \n  0xFE, 0x0F, 0x00, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x00, \n  0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x86, 0x97, 0x01, \n  0x63, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, \n  0x0C, 0x30, 0x60, 0x60, 0x18, 0x07, 0x06, 0x80, 0x01, 0x66, 0xC0, 0x18, \n  0x30, 0x06, 0x80, 0x01, 0x63, 0x0E, 0x00, 0x30, 0xC0, 0x80, 0x01, 0x03, \n  0x1B, 0xF8, 0x7C, 0x18, 0x03, 0x30, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x03, \n  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x00, \n  0x06, 0x8C, 0x01, 0x00, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, \n  0xB0, 0x03, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, \n  0x63, 0x00, 0x00, 0x30, 0x60, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xB8, \n  0x83, 0x01, 0x83, 0x03, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, \n  0x0C, 0xCE, 0x1C, 0xE6, 0x67, 0x70, 0x00, 0x00, 0x60, 0x00, 0x30, 0x00, \n  0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x00, 0x06, 0x0C, \n  0x30, 0xC0, 0x01, 0x18, 0x30, 0x00, 0x8C, 0x01, 0x63, 0xC0, 0x00, 0x03, \n  0x06, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x03, 0xC0, 0x01, 0x00, 0x00, 0x07, \n  0x00, 0x03, 0x06, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x86, 0x01, \n  0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x60, 0x60, 0x18, 0x0E, 0x06, \n  0x80, 0x01, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x80, 0x71, 0x63, 0x1C, 0x18, \n  0x30, 0xC0, 0x80, 0x01, 0x03, 0x1B, 0x78, 0x78, 0x0C, 0x06, 0x30, 0x60, \n  0x00, 0xC0, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, \n  0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x00, 0x06, 0x18, 0x30, \n  0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, 0x07, 0xC0, 0x80, 0x31, 0x66, 0xC0, \n  0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0x00, 0x30, 0x60, 0x80, 0x01, \n  0x03, 0x1B, 0x18, 0x63, 0x1C, 0x87, 0x01, 0xC3, 0x01, 0x80, 0x01, 0xC0, \n  0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xFC, 0x0F, 0x66, 0xE6, 0xF8, 0x00, \n  0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, \n  0x0C, 0x60, 0x00, 0x0E, 0x0E, 0x30, 0xE0, 0x00, 0x38, 0x38, 0x00, 0x8C, \n  0x83, 0xE3, 0xE0, 0x00, 0x03, 0x0E, 0x0E, 0x80, 0x03, 0x0C, 0x00, 0x03, \n  0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x03, 0x0E, 0x80, 0x01, 0x63, 0xE0, \n  0x38, 0x38, 0x06, 0x87, 0x01, 0x60, 0x00, 0x38, 0x38, 0x06, 0x0C, 0x30, \n  0xE0, 0x70, 0x18, 0x1C, 0x06, 0x80, 0x01, 0x66, 0xC0, 0x38, 0x38, 0x06, \n  0x80, 0xE3, 0x63, 0x38, 0x38, 0x38, 0xC0, 0x80, 0x83, 0x03, 0x0E, 0x38, \n  0x70, 0x0C, 0x06, 0x30, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x06, 0xC0, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x63, 0xE0, 0x38, 0x38, 0x0E, 0x8C, \n  0x83, 0x03, 0x06, 0x38, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, 0x0E, \n  0xC0, 0x80, 0x31, 0x66, 0xC0, 0x38, 0x38, 0x06, 0x8E, 0x03, 0x63, 0x00, \n  0x38, 0x38, 0x60, 0x80, 0x03, 0x03, 0x1B, 0x38, 0x73, 0x0E, 0x8E, 0x03, \n  0xE3, 0x00, 0x80, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xF8, \n  0x07, 0xE3, 0xC7, 0xDF, 0x01, 0x00, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x00, \n  0x00, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x00, 0xFC, 0x07, 0xFE, 0xE1, \n  0xFF, 0xF0, 0x1F, 0x00, 0x0C, 0xFF, 0xC1, 0x7F, 0x00, 0x03, 0xFC, 0x07, \n  0xFF, 0x01, 0x0C, 0x00, 0x03, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0x03, \n  0xFC, 0x9F, 0x01, 0xE3, 0x7F, 0xF0, 0x1F, 0xFE, 0x83, 0xFF, 0x63, 0x00, \n  0xF0, 0x1F, 0x06, 0x0C, 0xFC, 0xC0, 0x3F, 0x18, 0x38, 0xFE, 0x8F, 0x01, \n  0x66, 0xC0, 0xF0, 0x1F, 0x06, 0x00, 0xFF, 0x61, 0x70, 0xF0, 0x1F, 0xC0, \n  0x00, 0xFF, 0x01, 0x0E, 0x18, 0x60, 0x06, 0x0C, 0x30, 0xE0, 0xFF, 0xC0, \n  0x0F, 0x00, 0x0C, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE3, \n  0x7F, 0xF0, 0x1F, 0xFC, 0x0F, 0xFF, 0x01, 0x06, 0xF0, 0x3F, 0x06, 0x0C, \n  0xFC, 0x00, 0x60, 0x30, 0x1C, 0xF0, 0x83, 0x31, 0x66, 0xC0, 0xF0, 0x1F, \n  0xFE, 0x07, 0xFF, 0x63, 0x00, 0xF0, 0x1F, 0xE0, 0x07, 0xFF, 0x03, 0x0E, \n  0xF0, 0x3F, 0x06, 0x0C, 0xFF, 0xE3, 0xFF, 0x00, 0x0F, 0xC0, 0x00, 0x1E, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, \n  0x00, 0x00, 0x60, 0x0C, 0xC0, 0x00, 0xC3, 0x83, 0x8F, 0x01, 0x00, 0x80, \n  0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x30, \n  0x00, 0xF8, 0x03, 0xFE, 0xE1, 0xFF, 0xE0, 0x0F, 0x00, 0x0C, 0xFE, 0x80, \n  0x3F, 0x00, 0x03, 0xF8, 0x03, 0xFF, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x0E, \n  0x00, 0xE0, 0x00, 0x00, 0x03, 0xF8, 0x9F, 0x01, 0xE3, 0x3F, 0xE0, 0x0F, \n  0xFE, 0x80, 0xFF, 0x63, 0x00, 0xE0, 0x0F, 0x06, 0x0C, 0xFC, 0x80, 0x1F, \n  0x18, 0x30, 0xFE, 0x8F, 0x01, 0x66, 0xC0, 0xE0, 0x0F, 0x06, 0x00, 0xFE, \n  0x61, 0xE0, 0xE0, 0x0F, 0xC0, 0x00, 0xFE, 0x00, 0x0E, 0x18, 0x60, 0x06, \n  0x0C, 0x30, 0xE0, 0xFF, 0xC0, 0x0F, 0x00, 0x0C, 0xFC, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0xFE, 0xE3, 0x3F, 0xE0, 0x0F, 0xF8, 0x0F, 0xFE, 0x00, \n  0x06, 0xE0, 0x3F, 0x06, 0x0C, 0xFC, 0x00, 0x60, 0x30, 0x38, 0xF0, 0x83, \n  0x31, 0x66, 0xC0, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0x63, 0x00, 0xE0, 0x0F, \n  0xC0, 0x07, 0xFE, 0x03, 0x0E, 0xE0, 0x1F, 0x06, 0x0C, 0xFE, 0xE3, 0xFF, \n  0x00, 0x0E, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xC0, \n  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, \n  0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x30, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1F, 0x00, \n  0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };\n#define font32_width 1581\n#define font32_height 32\nstatic unsigned char font32_bits[] = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xFC, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xC0, 0x01, 0xF8, 0x38, \n  0xF0, 0x03, 0xC0, 0x01, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xF8, 0x0F, 0xC0, 0x01, \n  0xF8, 0x0F, 0xF8, 0x0F, 0x00, 0x38, 0xFE, 0x3F, 0xF8, 0x1F, 0xFE, 0x3F, \n  0xF8, 0x0F, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, \n  0x1C, 0x00, 0xF8, 0x0F, 0xF8, 0x1F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, \n  0xFE, 0x03, 0xFE, 0x3F, 0xFE, 0x3F, 0xF8, 0x0F, 0x0E, 0x38, 0xF0, 0x07, \n  0x00, 0x7F, 0x0E, 0x30, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0xF8, 0x0F, \n  0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x3F, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xF0, 0x0F, \n  0x1C, 0x00, 0xF0, 0x0F, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, \n  0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xF0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x80, 0x0F, 0xC0, 0x01, 0x7C, 0x00, 0xEE, 0x39, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, \n  0x38, 0x0E, 0xF8, 0x0F, 0xFC, 0x39, 0xF8, 0x07, 0xC0, 0x01, 0x80, 0x03, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x38, 0xFC, 0x1F, 0xE0, 0x01, 0xFC, 0x1F, 0xFC, 0x1F, 0x00, 0x3C, \n  0xFE, 0x3F, 0xFC, 0x1F, 0xFE, 0x3F, 0xFC, 0x1F, 0xFC, 0x1F, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, \n  0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x0F, 0xFE, 0x3F, 0xFE, 0x3F, \n  0xFC, 0x1F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x7F, 0x0E, 0x38, 0x0E, 0x00, \n  0x0E, 0x70, 0x0E, 0x38, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x1F, \n  0xFC, 0x1F, 0xFE, 0x3F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x0E, 0x38, \n  0x0E, 0x38, 0xFE, 0x3F, 0xF0, 0x0F, 0x1C, 0x00, 0xF0, 0x0F, 0x38, 0x0E, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, \n  0x1C, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x01, \n  0xFC, 0x00, 0xCE, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xFC, 0x1F, 0xDC, 0x1D, \n  0x1C, 0x0E, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1E, 0x3C, 0xF0, 0x01, \n  0x1E, 0x3C, 0x1E, 0x3C, 0x00, 0x3E, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x38, \n  0x1E, 0x3C, 0x1E, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, \n  0x70, 0x00, 0x1E, 0x3C, 0x1E, 0x70, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, \n  0x0E, 0x1E, 0x0E, 0x00, 0x0E, 0x00, 0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, \n  0x00, 0x1C, 0x0E, 0x1C, 0x0E, 0x00, 0x1E, 0x78, 0x0E, 0x38, 0x1E, 0x3C, \n  0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x70, 0x1C, 0x1C, 0x0E, 0x38, 0x00, 0x38, 0x70, 0x00, \n  0x38, 0x00, 0x00, 0x0E, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, \n  0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xE0, 0x01, 0x8E, 0x1F, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, \n  0x38, 0x0E, 0xDE, 0x3D, 0xDC, 0x1D, 0x1C, 0x0E, 0xC0, 0x01, 0xE0, 0x00, \n  0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x1C, 0x0E, 0x38, 0xF8, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x3F, \n  0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x0E, 0x60, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x0E, 0x0E, 0x0E, 0x00, \n  0x3E, 0x7C, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x1C, 0x1C, \n  0x1C, 0x1C, 0x00, 0x38, 0x70, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x0E, 0x38, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, \n  0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xCE, 0x39, 0xFC, 0x0F, \n  0x1C, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x1C, 0x1C, 0xC0, 0x01, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x38, 0xF8, 0x01, \n  0x0E, 0x38, 0x0E, 0x38, 0x80, 0x3B, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, \n  0xC0, 0x01, 0x0E, 0x38, 0x8E, 0x7F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x00, 0x1C, 0x0E, 0x07, 0x0E, 0x00, 0x7E, 0x7E, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x70, 0x38, 0x0E, 0x1C, 0x1C, 0x00, 0x38, 0x70, 0x00, \n  0x70, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0xFE, 0x3F, 0xCE, 0x01, 0xF8, 0x0E, 0x1C, 0x0E, 0x00, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0x38, 0x0E, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x0E, 0x0E, 0x3C, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0xC0, 0x39, \n  0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x1C, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x03, 0x0E, 0x38, 0xCE, 0x7F, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x8E, 0x03, 0x0E, 0x00, \n  0x7E, 0x7E, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0x38, 0x0E, \n  0x38, 0x0E, 0x00, 0x1C, 0x70, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xFE, 0x3F, 0xCE, 0x01, 0x00, 0x07, \n  0x1C, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x70, 0x07, 0xC0, 0x01, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x3E, 0xC0, 0x01, \n  0x0E, 0x38, 0x00, 0x38, 0xE0, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x1C, \n  0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xFE, 0x3F, \n  0x00, 0x07, 0x0E, 0x38, 0xEE, 0x71, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, \n  0x00, 0x1C, 0xCE, 0x01, 0x0E, 0x00, 0xEE, 0x77, 0x3E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, \n  0x1C, 0x1C, 0x0E, 0x70, 0x70, 0x07, 0x38, 0x0E, 0x00, 0x0E, 0x70, 0x00, \n  0xE0, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, \n  0xFE, 0x0F, 0xF8, 0x0F, 0xF8, 0x3F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x3F, \n  0xFE, 0x0F, 0xF0, 0x01, 0x00, 0x1F, 0x1C, 0x38, 0xC0, 0x01, 0xFE, 0x0F, \n  0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x3F, 0xCE, 0x3F, 0xF8, 0x0F, \n  0xFE, 0x0F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0xFE, 0x3F, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x38, 0x0E, 0xCE, 0x01, 0x00, 0x07, 0x38, 0x07, 0x00, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x07, 0x0E, 0x3F, 0xC0, 0x01, 0x00, 0x38, 0x00, 0x38, 0x70, 0x38, \n  0x0E, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0xC0, 0x01, 0x70, 0x00, 0xFE, 0x3F, 0x00, 0x0E, 0x00, 0x1C, 0xEE, 0x70, \n  0x0E, 0x38, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xEE, 0x00, 0x0E, 0x00, \n  0xCE, 0x73, 0x7E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0x70, 0x07, \n  0x70, 0x07, 0x00, 0x07, 0x70, 0x00, 0xE0, 0x00, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, \n  0xFC, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFE, 0x1F, 0xF0, 0x01, 0x00, 0x1F, \n  0x1C, 0x1C, 0xC0, 0x01, 0xFE, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x1F, \n  0xFC, 0x3F, 0xEE, 0x3F, 0xFC, 0x1F, 0xFE, 0x0F, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xDE, 0x01, 0x80, 0x03, \n  0xF0, 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xC0, 0x01, 0xC0, 0x01, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x8E, 0x3B, 0xC0, 0x01, \n  0x00, 0x1C, 0x00, 0x3C, 0x38, 0x38, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x0E, \n  0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x38, 0x00, 0x00, 0x00, \n  0x00, 0x1C, 0x00, 0x0E, 0xEE, 0x70, 0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, \n  0x00, 0x1C, 0x7E, 0x00, 0x0E, 0x00, 0xCE, 0x73, 0xEE, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x00, 0xC0, 0x01, 0x0E, 0x38, \n  0x1C, 0x1C, 0x0E, 0x70, 0xE0, 0x03, 0x70, 0x07, 0x80, 0x03, 0x70, 0x00, \n  0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, \n  0x0E, 0x3C, 0x1E, 0x3C, 0x1E, 0x38, 0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x38, \n  0x0E, 0x3C, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x0E, 0xC0, 0x01, 0xCE, 0x3D, \n  0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x38, 0x7E, 0x00, 0x1E, 0x3C, \n  0xE0, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x00, 0x1C, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x38, 0x0E, 0xFC, 0x0F, 0x80, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0xFE, 0x3F, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, \n  0x80, 0x03, 0xCE, 0x39, 0xC0, 0x01, 0x00, 0x0E, 0xF0, 0x1F, 0x1C, 0x38, \n  0xFE, 0x1F, 0xFE, 0x1F, 0x00, 0x07, 0xFC, 0x1F, 0x1E, 0x38, 0xC0, 0x01, \n  0xC0, 0x01, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x07, 0xEE, 0x70, \n  0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x07, 0xFE, 0x07, \n  0x8E, 0x3F, 0xFE, 0x3F, 0xC0, 0x01, 0x00, 0x1C, 0x3E, 0x00, 0x0E, 0x00, \n  0x8E, 0x71, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x3C, 0x0E, 0x38, 0x0E, 0x3C, \n  0xFC, 0x0F, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0xE0, 0x03, \n  0xE0, 0x03, 0xC0, 0x01, 0x70, 0x00, 0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, \n  0x1C, 0x07, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x3E, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, \n  0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x38, 0x00, 0x0E, 0x7C, 0x00, 0xC0, 0x01, \n  0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xF8, 0x1F, 0xC0, 0x01, \n  0xF8, 0x73, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xFE, 0x3F, 0xFE, 0x3F, \n  0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xC0, 0x01, 0xEE, 0x38, 0xC0, 0x01, \n  0x00, 0x07, 0xF0, 0x1F, 0x0E, 0x38, 0x00, 0x3C, 0x0E, 0x3C, 0x00, 0x07, \n  0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, \n  0x00, 0x38, 0x80, 0x03, 0xEE, 0x70, 0xFE, 0x3F, 0x0E, 0x1C, 0x0E, 0x00, \n  0x0E, 0x38, 0xFE, 0x07, 0xFE, 0x07, 0x8E, 0x3F, 0xFE, 0x3F, 0xC0, 0x01, \n  0x00, 0x1C, 0x3E, 0x00, 0x0E, 0x00, 0x0E, 0x70, 0x8E, 0x3B, 0x0E, 0x38, \n  0xFE, 0x1F, 0x0E, 0x38, 0xFE, 0x1F, 0xF8, 0x1F, 0xC0, 0x01, 0x0E, 0x38, \n  0x38, 0x0E, 0x8E, 0x71, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x00, 0x70, 0x00, \n  0x80, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x9C, 0x03, 0xC0, 0x01, 0xCE, 0x39, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x00, 0x0E, 0x00, \n  0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, 0xCE, 0x39, 0x38, 0x0E, 0x0E, 0x38, \n  0x00, 0x07, 0x7C, 0x00, 0xC0, 0x01, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x38, 0x0E, 0xC0, 0x3D, 0xC0, 0x01, 0x1C, 0x77, 0x00, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xC0, 0x01, 0x7E, 0x38, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x3C, 0x0E, 0x38, \n  0x00, 0x38, 0x0E, 0x38, 0x80, 0x03, 0x1E, 0x3C, 0xF8, 0x3F, 0x00, 0x00, \n  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xC0, 0x01, 0xEE, 0x70, \n  0xFE, 0x3F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x7E, 0x00, 0x0E, 0x00, \n  0x0E, 0x70, 0x0E, 0x3F, 0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x38, 0xFE, 0x0F, \n  0x00, 0x3C, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x73, 0xE0, 0x03, \n  0xC0, 0x01, 0x70, 0x00, 0x70, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, \n  0xDC, 0x01, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0x1E, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, \n  0xCE, 0x39, 0x70, 0x07, 0x0E, 0x38, 0x80, 0x03, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xC0, 0x39, 0xE0, 0x00, \n  0x0E, 0x3E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xE0, 0x03, 0xC0, 0x01, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x3E, 0x38, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x38, 0x0E, 0x38, 0x00, 0x38, 0x0E, 0x38, 0x80, 0x03, \n  0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xFE, 0x3F, \n  0x00, 0x0E, 0xC0, 0x01, 0xEE, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x00, 0x1C, 0xEE, 0x00, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x3E, 0x0E, 0x38, \n  0x0E, 0x00, 0x0E, 0x38, 0x7E, 0x00, 0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, \n  0x38, 0x0E, 0xCE, 0x73, 0x70, 0x07, 0xC0, 0x01, 0x38, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x3F, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xFC, 0x00, 0xC0, 0x01, 0xCE, 0x39, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xFC, 0x0F, \n  0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x39, 0xE0, 0x03, 0x0E, 0x38, \n  0xC0, 0x01, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xFE, 0x3F, 0xC0, 0x39, 0xE0, 0x00, 0x0E, 0x1C, 0x00, 0x00, 0x70, 0x00, \n  0x00, 0x07, 0x70, 0x07, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xE0, 0x00, 0x1E, 0x38, 0xC0, 0x01, 0xE0, 0x00, 0x00, 0x38, 0xFE, 0x3F, \n  0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0xE0, 0x00, 0xFE, 0x3F, 0x00, 0x07, 0xC0, 0x01, 0xEE, 0x79, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xCE, 0x01, 0x0E, 0x00, \n  0x0E, 0x70, 0x0E, 0x3C, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xEE, 0x00, \n  0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0xEE, 0x77, 0x70, 0x07, \n  0xC0, 0x01, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, \n  0xFE, 0x3F, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, \n  0xFC, 0x00, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0xF8, 0x1F, 0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, \n  0xCE, 0x39, 0xE0, 0x03, 0x0E, 0x38, 0xE0, 0x00, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0xC0, 0x39, 0x70, 0x1F, \n  0x0E, 0x1C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x38, 0x0E, 0xC0, 0x01, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x38, 0xC0, 0x01, \n  0x70, 0x00, 0x00, 0x38, 0xFE, 0x3F, 0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x80, 0x03, 0x00, 0x00, 0xCE, 0x7F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x0E, 0x1C, 0x8E, 0x03, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x00, 0x0E, 0x38, 0xCE, 0x01, 0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, \n  0x70, 0x07, 0x7E, 0x7E, 0x38, 0x0E, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, \n  0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xDC, 0x01, 0xC0, 0x01, 0xCE, 0x39, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00, 0x3C, \n  0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x39, 0x70, 0x07, 0x0E, 0x38, \n  0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x38, 0x0E, 0xCE, 0x39, 0xF0, 0x3F, 0x0E, 0x1C, 0x00, 0x00, 0xE0, 0x00, \n  0x80, 0x03, 0x1C, 0x1C, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x70, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x38, \n  0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x8E, 0x6F, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, \n  0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x1C, 0x0E, 0x07, 0x0E, 0x00, \n  0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x8E, 0x03, \n  0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x70, 0x07, 0x7E, 0x7E, 0x38, 0x0E, \n  0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, \n  0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, \n  0x9C, 0x03, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x0E, 0x38, 0x70, 0x07, \n  0xCE, 0x39, 0x38, 0x0E, 0x0E, 0x38, 0x38, 0x00, 0xE0, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xDE, 0x3D, 0xB8, 0x3B, \n  0x0E, 0x1C, 0x00, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, \n  0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x00, 0x0E, 0x38, 0xC0, 0x01, \n  0x1C, 0x00, 0x0E, 0x38, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x0E, 0x38, 0x00, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x07, 0x00, 0x00, \n  0xE0, 0x00, 0xC0, 0x01, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, \n  0x0E, 0x1C, 0x0E, 0x0E, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, \n  0x0E, 0x00, 0xCE, 0x39, 0x0E, 0x07, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, \n  0x70, 0x07, 0x3E, 0x7C, 0x1C, 0x1C, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, \n  0x00, 0x1C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, \n  0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x07, 0xC0, 0x01, 0xCE, 0x39, \n  0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00, 0x38, \n  0xE0, 0x00, 0x0E, 0x38, 0x70, 0x07, 0xCE, 0x39, 0x1C, 0x1C, 0x0E, 0x38, \n  0x1C, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x38, 0x0E, 0xFC, 0x1F, 0xB8, 0x3B, 0x1E, 0x3E, 0x00, 0x00, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, \n  0x38, 0x00, 0x1E, 0x3C, 0xC0, 0x01, 0x0E, 0x00, 0x1E, 0x3C, 0x00, 0x38, \n  0x1E, 0x38, 0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x3C, 0x00, 0x3C, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0xC0, 0x01, 0x1E, 0x00, \n  0x0E, 0x38, 0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x1E, 0x0E, 0x00, 0x0E, 0x00, \n  0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, 0x1E, 0x1E, 0x0E, 0x1C, 0x0E, 0x00, \n  0x0E, 0x70, 0x0E, 0x38, 0x1E, 0x3C, 0x0E, 0x00, 0x9E, 0x3F, 0x0E, 0x0E, \n  0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x3C, 0xE0, 0x03, 0x1E, 0x78, 0x1C, 0x1C, \n  0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0x0E, 0x3C, 0x1E, 0x3C, 0x1E, 0x38, \n  0x1E, 0x38, 0xC0, 0x01, 0x1E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, \n  0x1C, 0x0E, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x1E, 0x3C, 0x0E, 0x3C, \n  0x1E, 0x38, 0x0E, 0x00, 0x1E, 0x3C, 0xE0, 0x01, 0x1E, 0x38, 0xE0, 0x03, \n  0xDE, 0x3D, 0x0E, 0x38, 0x1E, 0x38, 0x0E, 0x00, 0xE0, 0x01, 0xC0, 0x01, \n  0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xF8, 0x0F, 0x9C, 0x3F, \n  0xFC, 0x77, 0x00, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x1C, 0x00, 0xFC, 0x1F, 0xF8, 0x0F, \n  0xFE, 0x3F, 0xFC, 0x1F, 0x00, 0x38, 0xFC, 0x1F, 0xFC, 0x1F, 0xC0, 0x01, \n  0xFC, 0x1F, 0xFC, 0x1F, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x1C, 0x00, 0x00, \n  0x38, 0x00, 0xC0, 0x01, 0xFC, 0x7F, 0x0E, 0x38, 0xFE, 0x1F, 0xFC, 0x1F, \n  0xFE, 0x0F, 0xFE, 0x3F, 0x0E, 0x00, 0xFC, 0x1F, 0x0E, 0x38, 0xF0, 0x07, \n  0xFC, 0x0F, 0x0E, 0x38, 0xFE, 0x3F, 0x0E, 0x70, 0x0E, 0x38, 0xFC, 0x1F, \n  0x0E, 0x00, 0xFC, 0x1F, 0x0E, 0x1C, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, \n  0xE0, 0x03, 0x0E, 0x70, 0x0E, 0x38, 0xC0, 0x01, 0xFE, 0x3F, 0xF0, 0x0F, \n  0x00, 0x38, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, \n  0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xC0, 0x01, 0xFC, 0x3F, \n  0x0E, 0x38, 0xF0, 0x07, 0x00, 0x1C, 0x1C, 0x1C, 0xF0, 0x07, 0xCE, 0x39, \n  0x0E, 0x38, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x3F, 0x0E, 0x00, 0xFC, 0x1F, \n  0xC0, 0x3F, 0xFC, 0x3F, 0xE0, 0x03, 0xFC, 0x1F, 0x0E, 0x38, 0xFC, 0x3F, \n  0xFE, 0x3F, 0xC0, 0x0F, 0xC0, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x38, 0x0E, 0xC0, 0x01, 0x1C, 0x1F, 0xF8, 0x73, 0x00, 0x00, 0x00, 0x07, \n  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, \n  0x1C, 0x00, 0xF8, 0x0F, 0xF8, 0x0F, 0xFE, 0x3F, 0xF8, 0x0F, 0x00, 0x38, \n  0xF8, 0x0F, 0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x0F, 0xFC, 0x0F, 0xC0, 0x01, \n  0xC0, 0x01, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0xC0, 0x01, 0xF8, 0x7F, \n  0x0E, 0x38, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x03, 0xFE, 0x3F, 0x0E, 0x00, \n  0xF8, 0x0F, 0x0E, 0x38, 0xF0, 0x07, 0xF8, 0x07, 0x0E, 0x30, 0xFE, 0x3F, \n  0x0E, 0x70, 0x0E, 0x38, 0xF8, 0x0F, 0x0E, 0x00, 0xF8, 0x0F, 0x0E, 0x38, \n  0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x0F, 0xE0, 0x03, 0x0E, 0x70, 0x0E, 0x38, \n  0xC0, 0x01, 0xFE, 0x3F, 0xF0, 0x0F, 0x00, 0x38, 0xF0, 0x0F, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xFE, 0x0F, 0xF8, 0x0F, 0xF8, 0x3F, \n  0xF8, 0x1F, 0xC0, 0x01, 0xF8, 0x3F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x1C, \n  0x1C, 0x38, 0xF0, 0x07, 0xCE, 0x39, 0x0E, 0x38, 0xF8, 0x0F, 0xFE, 0x0F, \n  0xF8, 0x3F, 0x0E, 0x00, 0xF8, 0x0F, 0x80, 0x3F, 0xF8, 0x3F, 0xE0, 0x03, \n  0xF8, 0x0F, 0x0E, 0x38, 0xF8, 0x3F, 0xFE, 0x3F, 0x80, 0x0F, 0xC0, 0x01, \n  0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, \n  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, \n  0x00, 0x00, 0x00, 0x00, 0x3C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, \n  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, \n  0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  };\n\nnamespace netgen { \n    class Font {\n        // opengl display list index (-1 if not initialized)\n        int list_base;\n\n        // width and height of font in pixels\n        int w;\n        int h;\n\n        // raw data to draw for opengl\n        unsigned char *char_bitmaps;\n\n        // size of one character in bitmap (in bytes)\n        int char_length;\n        int char_w;\n        int char_h;\n\n        // first and last+1 character in bitmap font\n        static constexpr char char_first = ' ';\n        static constexpr char char_next = '~'+1;\n\n        void setBit( char c, int x, int y) {\n            unsigned char *cbits = getCharBitmap(c);\n            int offset = x/8+(h-1-y)*char_w;\n            int bit_nr = 7-x%8;\n            cbits[offset] |= 1UL<<bit_nr;\n        }\n\n      public:\n        Font(const Font & font) = delete;\n        Font(int bitmap_width, int font_height, unsigned char *bits) {\n            list_base = -1;\n\n            // bitmap contains 99 printable characters ( ' ' to '~' )\n            // round up due to missing boarders at beginning and end of bitmap\n            w = (bitmap_width+98)/99;\n            h = font_height;\n\n            char_w = (w+7)/8;        // round up to full bytes\n            char_w = (char_w+3)/4*4; // align rows to 4 bytes\n            char_h = h;\n            char_length = char_w*char_h;\n\n            char_bitmaps = new unsigned char[99*char_length+16];\n            for (int i=0; i< 99*char_length; i++)\n              char_bitmaps[i] = 0;\n\n            for (char c = ' '; c<='~'; c++) {\n                int xstart = (c-char_first)*w;\n                for (int y=0; y<h; y++) {\n                    for (int x=xstart; x<xstart+w; x++) {\n                        int offset = x/8+y*((bitmap_width+7)/8);\n                        if(bits[offset] & (1U<<(x%8)) )\n                          setBit(c,x-xstart,y);\n                    }\n                }\n            }\n        }\n\n        ~Font() {\n            if(list_base>-1)\n              glDeleteLists(list_base, char_next-char_first);\n            delete[] char_bitmaps;\n        }\n\n        unsigned char *getCharBitmap(char c) {\n            return char_bitmaps + (c-char_first)*char_length;\n        }\n\n        int getDisplayListsBase() {\n            // already initialized\n            if(list_base>-1) return list_base;\n\n            list_base = glGenLists(char_next-char_first) - char_first;\n\n            for (char c=char_first; c<char_next; c++) {\n                glNewList(list_base+c, GL_COMPILE);\n                unsigned char *char_bitmap = char_bitmaps + (c-char_first)*char_length;\n                // size of bitmap for opengl: 8*char_w x char_h\n                // shift position by width of font (w)\n                glBitmap(8*char_w,  char_h,  0.0,  0.0,  w,  0.0,  char_bitmap);\n                glEndList();\n            }\n\n            return list_base;\n        }\n        int Width() { return w; };\n        int Height() { return h; };\n    };\n\n    // create Fonts statically and return pointer on selecting\n    static Font font12(font12_width, font12_height, font12_bits); \n    static Font font14(font14_width, font14_height, font14_bits); \n    static Font font16(font16_width, font16_height, font16_bits); \n    static Font font18(font18_width, font18_height, font18_bits); \n    static Font font20(font20_width, font20_height, font20_bits); \n    static Font font22(font22_width, font22_height, font22_bits); \n    static Font font24(font24_width, font24_height, font24_bits); \n    static Font font28(font28_width, font28_height, font28_bits); \n    static Font font32(font32_width, font32_height, font32_bits); \n\n    Font * selectFont(int height) {\n        // ensure height is even and in allowed range\n        height += height%2;\n        height = min2(32,height);\n        height = max2(12,height);\n\n        switch(height) {\n          case 12:\n            return &font12; \n          case 14:\n            return &font14; \n          case 16:\n            return &font16; \n          case 18:\n            return &font18; \n          case 20:\n            return &font20; \n          case 22:\n            return &font22; \n          case 24:\n          case 26:\n            return &font24; \n          case 28:\n          case 30:\n            return &font28; \n          case 32:\n            return &font32; \n          default:\n            return &font18; \n        }\n    }\n}\n"
  },
  {
    "path": "ng/gui.cpp",
    "content": "#include <mystdlib.h> \n#include <meshing.hpp>\n#include <inctcl.hpp>\n#include <core/ngcore_api.hpp>\n\nusing std::string;\nusing std::endl;\nusing std::cout;\nusing std::cerr;\n\nnamespace netgen\n{\n  NGCORE_API_EXPORT Flags parameters;\n}\n\nNGCORE_API_EXPORT bool nodisplay = false;\n\nextern \"C\" int Ng_Init (Tcl_Interp * interp);\nextern \"C\" int Ng_Vis_Init (Tcl_Interp * interp);\nextern \"C\" void Ng_TclCmd(string);\n\n// tcl package dynamic load\nextern \"C\" int NGCORE_API_EXPORT Gui_Init (Tcl_Interp * interp)\n{\n  Tcl_InitStubs( interp, TCL_VERSION, 0 );\n  Tk_InitStubs( interp, TK_VERSION, 0 );\n  if (Ng_Init(interp) == TCL_ERROR) {\n    cerr << \"Problem in Ng_Init: \" << endl;\n    cout << \"result = \" << Tcl_GetStringResult (interp) << endl;\n    return TCL_ERROR;\n  }\n \n  if (!nodisplay && Ng_Vis_Init(interp) == TCL_ERROR) {\n    cerr << \"Problem in Ng_Vis_Init: \" << endl;\n    cout << \"result = \" << Tcl_GetStringResult (interp) << endl;\n    return TCL_ERROR;\n  }\n\n  return TCL_OK;\n}\n"
  },
  {
    "path": "ng/menustat.tcl",
    "content": "if { $tcl_platform(os) eq \"Linux\" && [tk scaling] > 1.5 } {\r\n  # On some Linux systems, the scaling setting is only applied after\r\n  # overwriting some default font settings.\r\n  # This is a workaround to scale up fonts on high resolution displays.\r\n  font create ngFont -family Helvetica\r\n  option add *font ngFont\r\n  ttk::style configure \".\" -font ngFont\r\n}\r\n\r\n# netgen menus:\r\n\r\nmenu .ngmenu -tearoff 0  -relief raised -bd 2\r\n. configure -menu .ngmenu\r\n\r\n.ngmenu add cascade -label \"File\" -menu .ngmenu.file -underline 0\r\n.ngmenu add cascade -label \"Geometry\" -menu .ngmenu.geometry -underline 0\r\n.ngmenu add cascade -label \"Mesh\" -menu .ngmenu.mesh -underline 0\r\n.ngmenu add cascade -label \"View\" -menu .ngmenu.view -underline 0\r\n.ngmenu add cascade -label \"Refinement\" -menu .ngmenu.meshsize -underline 5\r\n\r\nif { $userlevel == 3} {\r\n    .ngmenu add cascade -label \"Special\" -menu .ngmenu.special -underline 3\r\n}\r\n\r\n.ngmenu add cascade -label \"Help\" -menu .ngmenu.help -underline 0\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu File                                     #\r\n#                                                   #\r\n#####################################################\r\n\r\nmenu .ngmenu.file\r\n\r\n.ngmenu.file add command -label \"Load Geometry...\" -accelerator \"<l><g>\" \\\r\n    -command { \r\n\tset types {\r\n\t    {\"All Geometry types\"   { .stl .stlb .step .stp .geo .in2d .igs .iges .brep .sat} }\r\n\t    {\"IGES Geometry\"\t{.igs .iges} }\r\n\t    {\"BREP OpenCascade Geometry\"    {.brep} }\r\n\t    {\"STL Geometry\"        {.stl} }\r\n\t    {\"Binary STL Geometry\"    {.stlb} }\r\n\t    {\"STEP Geometry\"    {.step .stp} }\r\n\t    {\"Geometry file\"       {.geo} }\r\n\t    {\"2D Geometry\"   {.in2d } } \r\n\t} \r\n\r\n\tset ACISavailable [Ng_ACISCommand isACISavailable]\r\n\tif {$ACISavailable == \"yes\" } {\r\n\t    lappend types {\"ACIS Geometry\" {.sat} }\r\n\t}\r\n\r\n\tif {[catch {\r\n\t    set file [tk_getOpenFile -filetypes $types -initialdir $dirname -typevariable loadgeomtypevar]\r\n\t}]} {\r\n\t    set file [tk_getOpenFile -filetypes $types -initialdir $dirname]\r\n\t}\r\n\r\n\tif {$file != \"\"} {\r\n\t    AddRecentFile $file\r\n\t    Ng_LoadGeometry $file \r\n\t    Ng_ParseGeometry\r\n#\t    if { [Ng_STLInfo status]==\"ERROR\" } {\r\n#\t\ttk_messageBox -message  \"STL ERROR: \\n [Ng_STLInfo statustext]\" -type ok\r\n#\t    }\r\n\t    set selectvisual geometry\r\n\t    Ng_SetVisParameters\r\n\t    redraw\r\n\t    wm title . [concat \"$progname - \" $file]\r\n\t    set dirname [file dirname $file]\r\n\t    set basefilename [file tail [file rootname $file]]\r\n\r\n\t    if { $hasocc == \"yes\" } {\r\n\t\trebuildoccdialog\r\n\t    }\r\n\t}\r\n    }\r\n\r\n\r\n\r\n.ngmenu.file add command -label \"Save Geometry...\" \\\r\n    -command { \r\n\tset occgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\r\n\tputs $occgeometryloaded\r\n\tif {$occgeometryloaded == 1 } {\r\n\t    set types {\r\n\t\t{\"IGES Geometry file\"   {.igs} } \r\n\t\t{\"STEP Geometry file\"   {.stp} } \r\n\t\t{\"STL Geometry file\"   {.stl} } \r\n\t\t{\"STL BIN Geometry file\"   {.stlb} } \r\n\t    }\r\n\t} {\r\n\t    set types {\r\n\t\t{\"STL Geometry file\"   {.stl} } \r\n\t\t{\"STL BIN Geometry file\"   {.stlb} } \r\n\t    }\r\n\t}\r\n\r\n\tset ACISavailable [Ng_ACISCommand isACISavailable]\r\n\tputs $ACISavailable\r\n\tif {$ACISavailable == \"yes\" } {\r\n\t    lappend types {\"ACIS Geometry\" {.sat} }\r\n\t}\r\n\r\n\tset file [tk_getSaveFile -filetypes $types -initialdir $dirname -initialfile $basefilename ]\r\n\tif {$file != \"\"} {\r\n\t    Ng_SaveGeometry $file \r\n\t}\r\n    }\r\n \r\n\r\n\r\n.ngmenu.file add cascade -label \"Recent Files\" -menu .ngmenu.file.recent \r\nmenu .ngmenu.file.recent -tearoff 0\r\n\r\n\r\nproc AddRecentFile { filename } {\r\n    global progname\r\n    global dirname\r\n    catch { [.ngmenu.file.recent delete $filename] }\r\n    .ngmenu.file.recent insert 0 command -label $filename \\\r\n\t-command \"AddRecentFile {$filename}; \r\n                  Ng_LoadGeometry {$filename}; \r\n\t\t  Ng_ParseGeometry;\r\n\t\t  set selectvisual geometry;\r\n\t\t  Ng_SetVisParameters;\r\n\t          redraw;\r\n\t\t  wm title . [concat \\\" $progname - $filename \\\"];\r\n                  set dirname {[file dirname $filename]};\r\n                  set basefilename {[file tail [file rootname $filename]]};\r\n        \t  rebuildoccdialog;\"\r\n\r\n    \r\n    if { [.ngmenu.file.recent index last] >= 6 } {\r\n\t.ngmenu.file.recent delete last }\r\n    \r\n    saveinifile;\r\n    }\r\nloadinifile;\r\n\r\n.ngmenu.file add separator\r\n\r\n\r\n.ngmenu.file add command -label \"Load Mesh...\" -accelerator \"<l><m>\" \\\r\n    -command {\r\n\tset types {\r\n\t    {\"Mesh file\"   {.vol .vol.gz}\t} }\r\n\tset file [tk_getOpenFile -filetypes $types -defaultextension \".vol\"]\r\n\tif {$file != \"\"} {\r\n\t    AddRecentMeshFile $file;\r\n\t    Ng_LoadMesh $file; \r\n\t    set selectvisual mesh\r\n\t    Ng_SetVisParameters\r\n\t    redraw\r\n\t    Ng_ReadStatus; \r\n#\t    Ng_MeshSizeFromSurfaceMesh\r\n\t    wm title . [concat \"$progname - \" $file] \r\n\t    set dirname [file dirname $file]\r\n\t    set basefilename [file tail [file rootname $file]]\r\n\t}\r\n    }\r\n\r\n\r\n\r\n# astrid\r\n.ngmenu.file add cascade -label \"Recent Meshes\" -menu .ngmenu.file.recentmesh \r\nmenu .ngmenu.file.recentmesh\r\n\r\n\r\nproc AddRecentMeshFile { filename } {\r\n    global progname\r\n    global dirname\r\n    catch { [.ngmenu.file.recentmesh delete $filename] }\r\n    .ngmenu.file.recentmesh insert 0 command -label $filename \\\r\n\t-command \"AddRecentMeshFile {$filename}; \r\n                  Ng_LoadMesh {$filename};\r\n\t\t  set selectvisual mesh;\r\n\t\t  Ng_SetVisParameters;\r\n\t          redraw;\r\n\t\t  wm title . [concat \\\" $progname - $filename \\\"];\r\n                  set dirname {[file dirname $filename]};\r\n                  set basefilename {[file tail [file rootname $filename]]};\r\n                  rebuildoccdialog;\"\r\n    \r\n    if { [.ngmenu.file.recentmesh index last] >= 6 } {\r\n\t.ngmenu.file.recentmesh delete last }\r\n   \r\n    savemeshinifile;\r\n    }\r\nloadmeshinifile;\r\n\r\n# astrid end\r\n\r\n\r\n.ngmenu.file add command -label \"Save Mesh...\" -accelerator \"<s><m>\" \\\r\n    -command {\r\n\tset types {\r\n\t    {\"Mesh file\"   {.vol .vol.gz}\t} }\r\n\r\n\tset file [tk_getSaveFile -filetypes $types -defaultextension \".vol.gz\" -initialfile $basefilename -initialdir $dirname ]\r\n\tif {$file != \"\"} {\r\n\t    Ng_SaveMesh $file }\r\n\tAddRecentMeshFile $file;\r\n\r\n    }\r\n\r\n.ngmenu.file add command -label \"Merge Mesh...\" \\\r\n    -command {\r\n\tset types {\r\n\t    {\"Mesh file\"   {.vol}\t} }\r\n\tset file [tk_getOpenFile -filetypes $types -defaultextension \".vol\"]\r\n\tif {$file != \"\"} {\r\n\t    Ng_MergeMesh $file; \r\n\t    set selectvisual mesh\r\n\t    Ng_SetVisParameters\r\n\t    redraw\r\n\t    Ng_ReadStatus; \r\n\t}\r\n    }\r\n\r\n\r\n\r\n\r\nset meshimportformats [Ng_GetImportFormats]\r\n\r\n.ngmenu.file add command -label \"Import Mesh...\" \\\r\n    -command { \r\n\tforeach importformat $meshimportformats {\r\n\t    if { [lindex $importformat 0] == $importfiletype } {\r\n\t\tset extension [lindex $importformat 1]\r\n\t    }\r\n\t}\r\n\tset types {\r\n\t    {\"Neutral format\"  {.mesh .emt} }\r\n\t    {\"Surface mesh format\"  {.surf} }\r\n\t    {\"Universal format\"  {.unv} }\r\n\t    {\"Olaf format\"  {.emt} }\r\n\t    {\"TET format\" {.tet} }\r\n\t    {\"STL format\" {.stl .stlb} }\r\n\t    {\"Pro/ENGINEER neutral format\" {.fnf} }\r\n\t    {\"CFD General Notation System\" {.cgns} }\r\n\t          }\r\n  set file [tk_getOpenFile -filetypes $meshimportformats -typevariable importfiletype]\r\n\tif {$file != \"\"} {\r\n\t    Ng_ImportMesh $file $importfiletype\r\n\t    set selectvisual mesh\r\n\t    Ng_SetVisParameters\r\n\t    redraw\r\n\t    Ng_ReadStatus; \r\n\t}\r\n    }\r\n\r\n\r\nset meshexportformats [Ng_GetExportFormats]\r\n\r\n.ngmenu.file add command -label \"Export Mesh...\" \\\r\n    -command {\r\n\r\n# \tglobal meshexportformats\r\n\tforeach exportformat $meshexportformats {\r\n\t    if { [lindex $exportformat 0] == $exportfiletype } {\r\n\t\tset extension [lindex $exportformat 1]\r\n\t    }\r\n\t}\r\n\r\n\tif { $exportfiletype == \"Elmer Format\"} {\r\n\t    set file [file nativename [tk_chooseDirectory -title \"Elmer Mesh Export - Select Directory\"]]\r\n        } elseif { $exportfiletype == \"OpenFOAM 1.5+ Format\"} {\r\n\t    set file [file nativename [tk_chooseDirectory -title \"OpenFOAM 1.5+ Mesh Export - Select Case Directory\"]]\r\n        } elseif { $exportfiletype == \"OpenFOAM 1.5+ Compressed\"} {\r\n\t    set file [file nativename [tk_chooseDirectory -title \"OpenFOAM 1.5+ Mesh Export - Select Case Directory\"]]\r\n        } else {\r\n            # set file [tk_getSaveFile  -filetypes \"{ \\\"$exportfiletype\\\" {$extension} }\" ]\r\n\t    # set file [tk_getSaveFile  -filetypes \"{ \\\"$exportfiletype\\\" {*}}\" ]\r\n            set file [tk_getSaveFile  -filetypes $meshexportformats -typevariable exportfiletype]\r\n            puts \"type = $exportfiletype\"\r\n            puts \"filename = $file\"\r\n\t}\r\n\r\n\tif {$file != \"\"} {\r\n\t    Ng_ExportMesh $file $exportfiletype \r\n\t}\r\n    }\r\n\r\n.ngmenu.file add cascade -label \"Export Filetype\" -menu .ngmenu.file.filetype \r\nmenu .ngmenu.file.filetype \r\n\r\nforeach exportformat $meshexportformats {\r\n    .ngmenu.file.filetype add radio -label [lindex $exportformat 0] -variable exportfiletype -command { .ngmenu.file invoke \"Export Mesh...\" }\r\n}\r\n\r\n\r\n.ngmenu.file add separator\r\n\r\n\r\n.ngmenu.file add command -label \"Save Solution...\" \\\r\n    -command { \r\n\tset types { \r\n            {\"Solution File\"  {.sol} } \r\n            {\"VTK File\"  {.vtk} } \r\n        }\r\n\tset file [tk_getSaveFile -filetypes $types ]\r\n\tif {$file != \"\"} {\r\n\t    Ng_SaveSolution $file \r\n\t}\r\n    }\r\n#-defaultextension \".sol\"  ]\r\n\r\n.ngmenu.file add command -label \"Import Solution...\" \\\r\n    -command { \r\n\tset types { {\"Solution File\"  {.sol} } }\r\n\tset file [tk_getOpenFile -filetypes $types -defaultextension \".sol\"  ]\r\n\tif {$file != \"\"} {\r\n\t    Ng_ImportSolution $file \r\n\t    set selectvisual solution\r\n\t    Ng_SetVisParameters\r\n\t    redraw\r\n\t}\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\nset demostarttime [clock clicks -millisecond]\r\nset stopdemo 0\r\nproc demoredraw { } {\r\n    global demostarttime\r\n    global stopdemo\r\n    set curtime [clock clicks -millisecond]\r\n    set result [ Ng_DemoSetTime [expr $curtime - $demostarttime] ]\r\n    redraw\r\n    global videoactive\r\n    if { $videoactive == 1 } {\r\n        puts \"addframe\"\r\n        Ng_VideoClip .ndraw addframe\r\n    }\r\n    if { $result == 0 && $stopdemo == 0 } {\r\n\tafter 1 { demoredraw }\r\n    }\r\n}\r\n.ngmenu.file add command -label \"Show Demo...\" \\\r\n    -command {\r\n\tset types { {\"Demo File\"  {.dem} } }\r\n\tset file [tk_getOpenFile -filetypes $types -defaultextension \".dem\"  ]\r\n\tif {$file != \"\"} {\r\n\t    Ng_ShowDemo $file \r\n\t    set demostarttime [clock clicks -millisecond]\r\n\t    set stopdemo 0\r\n\t    demoredraw\r\n \t}\r\n     }\r\n\r\n\r\n\r\n\r\n.ngmenu.file add separator\r\n\r\n.ngmenu.file add command -label \"Snapshot...\" \\\r\n    -command { \r\n\tset types { \r\n\t    {\"JPG file\" {.jpg} } \r\n\t    {\"GIF file\" {.gif} } \r\n\t    {\"PPM file\" {.ppm} } \r\n\t}\r\n\tset file [tk_getSaveFile -filetypes $types]\r\n#  -defaultextension \".ppm\"]\r\n\tif {$file != \"\"} {\r\n\t    Ng_SnapShot .ndraw $file }\r\n    }\r\n\r\n\r\n.ngmenu.file add cascade -label \"Video clip\" -menu .ngmenu.file.video\r\nmenu .ngmenu.file.video\r\n\r\nset videoactive 0\r\n.ngmenu.file.video add command -label \"start...\" \\\r\n    -command { \r\n \tset types { \r\n \t    {\"MPG file\" {.mpg} } \r\n \t}\r\n \tset file [tk_getSaveFile -filetypes $types]\r\n \tif {$file != \"\"} {\r\n \t    Ng_VideoClip .ndraw init $file \r\n            global videoactive\r\n            set videoactive 1\r\n        }\r\n     }\r\n\r\n.ngmenu.file.video add command -label \"add frame...\" \\\r\n    -command {Ng_VideoClip .ndraw addframe }\r\n\r\n.ngmenu.file.video add command -label \"one cycle\" \\\r\n    -command {\r\n\tset visoptions.redrawperiodic 1\r\n\tfor { set j 0 } { $j < 100 } { incr j } {\r\n\t    puts \"j =  $j\"\r\n\t    Ng_Vis_Set time [expr (1000 * $j / 100)]\r\n\t    redraw\r\n\t    Ng_VideoClip .ndraw addframe \r\n\t    after 200\r\n\t}\r\n    }\r\n\r\n.ngmenu.file.video add command -label \"finalize...\" \\\r\n    -command {\r\n        Ng_VideoClip .ndraw finalize \r\n        global videoactive\r\n        set videoactive 0\r\n    }\r\n\r\n\r\n\r\n.ngmenu.file add command -label \"Save Options\" \\\r\n    -command { saveoptions }\r\n\r\n\r\n    \r\n\r\n.ngmenu.file add separator\r\n\r\n\r\n## herbert tcl load menu\r\n# .ngmenu.file add command -label \"Run tests ...\" \\\r\n\\#    -command { runtestdialog }\r\n##\r\n# .ngmenu.file add separator\r\n\r\n.ngmenu.file add command -label \"Quit\" -accelerator \"<q>\" \\\r\n    -command { \r\n        puts \"Thank you for using $progname\"; \r\n\r\n        if { [catch { unload libngsolve[info sharedlibextension] ngsolve } result ] } {\r\n            # puts \"cannot unload ngsolve\" \r\n            # puts \"error: $result\"\r\n        } \r\n\r\n        after cancel { timer2 }\r\n        Ng_Exit; \r\n        destroy . \r\n    }\r\n# exit\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu Mesh                                     #\r\n#                                                   #\r\n#####################################################\r\n\r\nmenu .ngmenu.mesh\r\n.ngmenu.mesh add command -label \"Generate Mesh\" -accelerator \"<g><m>\" \\\r\n    -command { \r\n\tset selectvisual mesh\r\n\tNg_SetVisParameters\r\n\tNg_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\r\n\tNg_ReadStatus\r\n\tredraw\r\n    }\r\n\r\n.ngmenu.mesh add command -label \"Stop Meshing\" \\\r\n    -command { Ng_StopMeshing }\r\n\r\n.ngmenu.mesh add command -label \"Meshing Options...\" \\\r\n    -command meshingoptionsdialog\r\n\r\n\r\n.ngmenu.mesh add separator\r\n\r\n.ngmenu.mesh add command -label \"Delete Mesh\" \\\r\n    -command { Ng_New mesh; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.mesh add command -label \"Delete Vol Mesh\" \\\r\n    -command { Ng_DeleteVolMesh; Ng_ReadStatus; redraw }\r\n\r\n\r\n.ngmenu.mesh add command -label \"Mesh Info\" \\\r\n    -command {\r\n\tset dim [Ng_MeshInfo dim]\r\n\tset np [Ng_MeshInfo np]\r\n\tset ne [Ng_MeshInfo ne]\r\n\tset nse [Ng_MeshInfo nse]\r\n\tset nseg [Ng_MeshInfo nseg]\r\n\tset bbox [Ng_MeshInfo bbox]\r\n\ttk_messageBox -message  \"Dimension: $dim\\nPoints: $np\\nElements: $ne\\nSurface Els: $nse\\nSegments: $nseg\\nxmin [lindex $bbox 0] xmax [lindex $bbox 1]\\nymin [lindex $bbox 2] ymax [lindex $bbox 3]\\nzmin [lindex $bbox 4] zmax [lindex $bbox 5]\"\r\n    }\r\n\r\n\r\n.ngmenu.mesh add command -label \"Mesh Quality\" \\\r\n    -command {\r\n\tset inplanemin 0\r\n\tset inplanemax 0\r\n\tset betplanemin 0\r\n\tset betplanemax 0\r\n\tNg_MeshQuality inplanemin inplanemax betplanemin betplanemax\r\n\tputs \"Triangle angles : $inplanemin - $inplanemax\"\r\n\tputs \"Tet angles      : $betplanemin - $betplanemax\"\r\n\ttk_messageBox -message  \"Triangle angles : $inplanemin - $inplanemax \\n Tet angles      : $betplanemin - $betplanemax\"\r\n    }\r\n\r\n# .ngmenu.mesh add command -label \"Quality Plot\" \\\r\n#    -command { qualityviewdialog 1 }\r\n\r\n\r\n\r\n\r\n.ngmenu.mesh add command -label \"Check Surface Mesh\" \\\r\n    -command { Ng_CheckSurfaceMesh }\r\n.ngmenu.mesh add command -label \"Check Volume Mesh\" \\\r\n    -command { Ng_CheckVolumeMesh }\r\n\r\n.ngmenu.mesh add command -label \"Edit Boundary Conditions...\" \\\r\n    -command { bcpropdialog }\r\n\r\nif { $userlevel == 3 } {\r\n    .ngmenu.mesh add command -label \"Mesh Doctor...\" \\\r\n\t-command { meshdoctordialog }\r\n}\r\n\r\n.ngmenu.mesh add command -label \"METIS Mesh Partitioning...\" \\\r\n\t-command { METISdialog }\r\n\r\n.ngmenu.mesh add separator\r\n\r\n.ngmenu.mesh add command -label \"Analyze Geometry\" \\\r\n    -command { Ng_GenerateMesh ag ag; Ng_ReadStatus; redraw }\r\n.ngmenu.mesh add command -label \"Mesh Edges\" \\\r\n    -command { Ng_GenerateMesh me me; Ng_ReadStatus; redraw }\r\n.ngmenu.mesh add command -label \"Mesh Surface\" \\\r\n    -command { set selectvisual mesh; Ng_SetVisParameters; \\\r\n\t\t   Ng_GenerateMesh ms ms; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.mesh add command -label \"Optimize Surface\" \\\r\n    -command { Ng_GenerateMesh os os cmsmSm; redraw }\r\n\r\n.ngmenu.mesh add cascade -label \"Surface Optim. Step\" -menu .ngmenu.mesh.surfoptstep \r\n\r\nmenu .ngmenu.mesh.surfoptstep \r\n.ngmenu.mesh.surfoptstep add command -label \"Mesh Smoothing\" \\\r\n    -command { Ng_GenerateMesh os os m; redraw}\r\n.ngmenu.mesh.surfoptstep add command -label \"Edge swapping (topologic)\" \\\r\n    -command { Ng_GenerateMesh os os s; redraw}\r\n.ngmenu.mesh.surfoptstep add command -label \"Edge swapping (metric)\" \\\r\n    -command { Ng_GenerateMesh os os S; redraw}\r\n.ngmenu.mesh.surfoptstep add command -label \"Combine points\" \\\r\n    -command { Ng_GenerateMesh os os c; redraw}\r\n\r\n\r\n.ngmenu.mesh add separator\r\n.ngmenu.mesh add command -label \"Mesh Volume\" \\\r\n    -command { Ng_GenerateMesh mv mv; Ng_ReadStatus }\r\n.ngmenu.mesh add command -label \"Optimize Volume\" \\\r\n    -command { Ng_GenerateMesh ov ov; Ng_ReadStatus }\r\n.ngmenu.mesh add command -label \"Smooth Opt Volume\" \\\r\n    -command { Ng_GenerateMesh ov ov m; Ng_ReadStatus }\r\n.ngmenu.mesh add command -label \"Smooth Opt Volume Jacobian\" \\\r\n    -command { Ng_GenerateMesh ov ov j; Ng_ReadStatus }\r\n\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu Geometry                                 #\r\n#                                                   #\r\n#####################################################\r\n\r\nmenu .ngmenu.geometry\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu View                                     #\r\n#                                                   #\r\n#####################################################\r\n\r\nmenu .ngmenu.view\r\n.ngmenu.view add command -label \"Zoom all\" \\\r\n    -command { Ng_ZoomAll; redraw }\r\n.ngmenu.view add command -label \"Center\" \\\r\n    -command { Ng_Center; redraw }\r\n\r\n.ngmenu.view add command -label \"x-y plane\" \\\r\n    -command { Ng_StandardRotation xy; redraw }\r\n.ngmenu.view add command -label \"y-x plane\" \\\r\n    -command { Ng_StandardRotation yx; redraw }\r\n.ngmenu.view add command -label \"x-z plane\" \\\r\n    -command { Ng_StandardRotation xz; redraw }\r\n.ngmenu.view add command -label \"z-x plane\" \\\r\n    -command { Ng_StandardRotation zx; redraw }\r\n.ngmenu.view add command -label \"y-z plane\" \\\r\n    -command { Ng_StandardRotation yz; redraw }\r\n.ngmenu.view add command -label \"z-y plane\" \\\r\n    -command { Ng_StandardRotation zy; redraw }\r\n\r\n.ngmenu.view add command -label \"Viewing Options...\" \\\r\n    -command { viewingoptionsdialog; redraw }\r\n.ngmenu.view add command -label \"Clipping Plane...\" \\\r\n    -command { clippingdialog; redraw }\r\n.ngmenu.view add command -label \"Solution Data...\" \\\r\n    -command { visual_dialog; redraw }\r\n.ngmenu.view add checkbutton -variable viewqualityplot \\\r\n    -label \"Quality Plot\" \\\r\n    -command { qualityviewdialog $viewqualityplot }\r\n.ngmenu.view add checkbutton -variable memuseplot \\\r\n    -label \"Memory Usage\" \\\r\n    -command { memusedialog $memuseplot }\r\n\r\n\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu Refinement                               #\r\n#                                                   #\r\n#####################################################\r\n#\r\n# Mesh size menu\r\n#\r\nmenu .ngmenu.meshsize\r\n.ngmenu.meshsize add command -label \"Refine uniform\" \\\r\n    -command { Ng_Refine; Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.meshsize add command -label \"Second Order\" \\\r\n    -command { Ng_SecondOrder; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.meshsize add command -label \"Validate Second Order\" \\\r\n    -command { Ng_ValidateSecondOrder; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.meshsize add command -label \"High Order\" \\\r\n    -command { Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.meshsize add separator\r\n\r\n.ngmenu.meshsize add command -label \"Refinement Dialog...\" \\\r\n    -command { refinementdialog }\r\n.ngmenu.meshsize add command -label \"Load Meshsize...\" \\\r\n    -command {\r\n\tset types {\r\n\t    {\"Meshsize file\"   {.msz}\t} }\r\n\tset file [tk_getOpenFile -filetypes $types]\r\n\tif {$file != \"\"} {\r\n\t    Ng_LoadMeshSize $file; \r\n\t}\r\n    }\r\n.ngmenu.meshsize add command -label \"MS from Surf Mesh\" \\\r\n    -command { Ng_MeshSizeFromSurfaceMesh }\r\n\r\n\r\nif { $userlevel == 3 } {\r\n.ngmenu.meshsize add command -label \"Singular point ms\" \\\r\n    -command { Ng_SingularPointMS; }\r\n\r\n.ngmenu.meshsize add command -label \"Singular edge ms\" \\\r\n    -command { Ng_SingularEdgeMS; }\r\n\r\n.ngmenu.meshsize add separator\r\n\r\nset bisectfilename \"\";\r\n\r\n.ngmenu.meshsize add command -label \"Bisection\" \\\r\n    -command { Ng_ReadStatus; set oldnp 0; set newnp $status_np; \r\n#\tNg_BisectCopyMesh; \r\n#\tNg_Split2Tets;\r\n\tNg_ReadStatus;\r\n\t\r\n\twhile { $oldnp < $newnp } {\r\n#\t    if { $level == 0 } {\r\n#\t\tNg_ExportMesh feppmesh.vol fepp;\r\n#\t    } {\r\n#\t\tNg_ExportMesh feppmesh$level feppml \r\n#\t    }\r\n\t    set level [expr $level+1]\r\n\t    if { $bisectfilename == \"\"} {\r\n\t\tNg_Bisect;\r\n\t    } else {\r\n\t\tNg_Bisect $bisectfilename;\r\n\t    }\r\n#\t    Ng_HighOrder ${options.elementorder} \"noparallel\"\r\n#\t    Ng_Split2Tets;\r\n\t    Ng_ReadStatus;\r\n\t    redraw; \r\n\t    \r\n\t    if { $bisectfilename == \"\"} {\r\n\t\tset oldnp $newnp;\r\n\t\tset newnp $status_np;\r\n\t\tputs \"oldnp $oldnp newnp $newnp\";\r\n\t    } else {\r\n\t\tset oldnp $newnp;\r\n\t    }\r\n\t}\r\n    }\r\n#    -command { Ng_Bisect; Ng_ReadStatus; redraw }\r\n#    -command { exec netgen abc >outfile 2>errfile; Ng_ReadStatus; redraw }\r\n\r\n}\r\n\r\n.ngmenu.meshsize add command -label \"Load Refinement Info...\" \\\r\n    -command {\r\n\tset types {\r\n\t    {\"Refinement info\" {.refine} }}\r\n\tset bisectfilename [tk_getOpenFile -filetypes $types]\r\n    }\r\n\r\n.ngmenu.meshsize add command -label \"Z-Refinement\" \\\r\n    -command { Ng_ZRefinement 2; Ng_ReadStatus; redraw }\r\n\r\n\r\n# .ngmenu.meshsize add command -label \"hp-Refinement\" \\\r\n\\#    -command { Ng_HPRefinement 4; Ng_ReadStatus; redraw }\r\n\r\n.ngmenu.meshsize add cascade -label \"hp-Refinement\" -menu .ngmenu.meshsize.hpref\r\nmenu .ngmenu.meshsize.hpref\r\n.ngmenu.meshsize.hpref add command -label \"1 Level\" \\\r\n    -command { Ng_HPRefinement 1; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"2 Levels\" \\\r\n    -command { Ng_HPRefinement 2; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"3 Levels\" \\\r\n    -command { Ng_HPRefinement 3; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"4 Levels\" \\\r\n    -command { Ng_HPRefinement 4; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"5 Levels\" \\\r\n    -command { Ng_HPRefinement 5; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"6 Levels\" \\\r\n    -command { Ng_HPRefinement 6; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"7 Levels\" \\\r\n    -command { Ng_HPRefinement 7; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"8 Levels\" \\\r\n    -command { Ng_HPRefinement 8; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"9 Levels\" \\\r\n    -command { Ng_HPRefinement 9; Ng_ReadStatus; redraw }\r\n.ngmenu.meshsize.hpref add command -label \"10 Levels\" \\\r\n    -command { Ng_HPRefinement 10; Ng_ReadStatus; redraw }\r\n\r\n\r\n.ngmenu.meshsize add command -label \"Split to Tets\" \\\r\n    -command { Ng_Split2Tets; Ng_ReadStatus; redraw }\r\n\r\n\r\n\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu Special                                  #\r\n#                                                   #\r\n#####################################################\r\n\r\nmenu .ngmenu.special\r\n.ngmenu.special add command -label \"Prismatic Boundary Layer\" \\\r\n    -command { Ng_GenerateBoundaryLayer; redraw }\r\n.ngmenu.special add command -label \"Insert virtual boundary layer\" \\\r\n    -command { Ng_InsertVirtualBL; redraw }\r\n.ngmenu.special add command -label \"Cut off and combine with other\" \\\r\n    -command { \r\n\tset types { {\"Mesh file\"   {.vol}\t} }\r\n\tset file [tk_getOpenFile -filetypes $types]\r\n\tif {$file != \"\"} {\r\n\t    Ng_CutOffAndCombine $file;  }\r\n\tredraw \r\n    }\r\n.ngmenu.special add command -label \"Helmholtz Mesh grading\" \\\r\n    -command { Ng_HelmholtzMesh; }\r\n.ngmenu.special add cascade -label \"Colour-based boundary conditions\" -menu .ngmenu.special.colbndcond\r\n\r\nmenu .ngmenu.special.colbndcond \r\n .ngmenu.special.colbndcond add command -label \"Inspect Colours in mesh\" \\\r\n    -command { currmeshcoloursdialog }\r\n    \r\n .ngmenu.special.colbndcond add separator\t\r\n    \r\n .ngmenu.special.colbndcond add command -label \"Automatic Assignment\" \\\r\n    -command { Ng_AutoColourBcProps auto; redraw }\r\n\t\r\n .ngmenu.special.colbndcond add separator\t\r\n\r\n set ocffile [file join ${ngdir} netgen.ocf];\r\n \r\n .ngmenu.special.colbndcond add command -label \"Select Colour Profile file\" \\\r\n    -command {\r\n\tset types { {\"Colour Profile file\"   {.ocf}   } }\r\n\tset ocffile [tk_getOpenFile -filetypes $types]\r\n\tif {$ocffile == \"\"} {\r\n\t    set ocffile [file join ${ngdir} netgen.ocf]; }\r\n\t} \r\n .ngmenu.special.colbndcond add command -label \"Profile based Assignment\" \\\r\n\t-command { Ng_AutoColourBcProps profile ${ocffile}; redraw }\r\n\r\n\r\n# menu .mbar.stl.menu\r\n# .mbar.stl.menu add command -label \"STL options\" \\\r\n#     -command { stloptionsdialog; }\r\n#.mbar.stl.menu add command -label \"STL Doctor\" \\\r\n#    -command { stldoctordialog; }\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Menu Help                                     #\r\n#                                                   #\r\n#####################################################\r\n\r\n\r\n\r\n\r\nmenu .ngmenu.help\r\n# .ngmenu.help add command -label \"Ng Help...\" \\\r\n\\#\t-command { help_main }\r\n# .ngmenu.view add checkbutton -variable showsensitivehelp \\\r\n#\t-label \"Sensitive Help\" \\\r\n#\t-command { sensitivehelpdialog $showsensitivehelp }\r\n.ngmenu.view add checkbutton -label \"Help Line\" -variable showhelpline \\\r\n\t-command {\r\n    if { $showhelpline == 1} {\r\n\tpack .helpline -before .statbar -side bottom -fill x -padx 3p\r\n    } {\r\n\tpack forget .helpline \r\n    }\r\n} \r\n\r\n.ngmenu.help add command -label \"About...\" \\\r\n    -command {\r\ntk_messageBox -message \"This is NETGEN \\nmainly written by \\nJoachim Schoeberl \\nthanks to \\nRobert Gaisbauer, Johannes Gerstmayr, Philippose Rajan\"\r\n}\r\n\r\n# tk_menuBar .mbar .mbar.file .mbar.mesh .mbar.test .mbar.help\r\n# focus .mbar\r\n\r\n\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Button bar                                    #\r\n#                                                   #\r\n#####################################################\r\n\r\nttk::frame .bubar\r\n# -relief raised\r\n#-relief raised -bd 2\r\npack .bubar -side top -fill x\r\n\r\nttk::button .bubar.testb -text \"Test\" -command { Ng_SaveGeometry }\r\nttk::button .bubar.surfm -text \"Generate Mesh\" -command \\\r\n    { \r\n\t.ngmenu.mesh invoke \"Generate Mesh\"; \r\n#\tset selectvisual mesh; \r\n#\tNg_SetVisParameters;\r\n#\tNg_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\r\n#\tredraw \r\n    }\r\nttk::button .bubar.stopm -text \"Stop\" -command \\\r\n    { \r\n\t# Ng_StopMeshing;  \r\n\tset multithread_terminate 1;\r\n\tset stopdemo 1;\r\n    }\r\nttk::button .bubar.exitb -text \"Quit\" \\\r\n    -command { \r\n\t   set ans [tk_messageBox -title \"Quit Netgen?\" -message \"Do you really want to quit Netgen?\" -type yesno -default \"no\" -icon question]\r\n\t   if { $ans == \"yes\" } {\r\n\t     .ngmenu.file invoke \"Quit\"; \r\n\t   }\t \r\n\t}\r\npack  .bubar.exitb .bubar.surfm .bubar.stopm -side left\r\n\r\n#button .bubar.scan -text \"Scan\" \\\r\n#    -command { Ng_ParseGeometry; set selectvisual geometry; Ng_SetVisParameters; redraw }\r\n\r\nttk::button .bubar.zoomall -text \"Zoom All\" \\\r\n    -command { Ng_ZoomAll; redraw }\r\n\r\nttk::button .bubar.center -text \"Center\" \\\r\n    -command { Ng_Center; redraw }\r\n\r\n# tk_optionMenu .bubar.modesel drawmode \"rotate\" \"move  \" \"zoom  \"\r\n# tixOptionMenu .bubar.modesel \\\r\n     # -options {\r\n \t# label.width  0\r\n \t# label.anchor e\r\n \t# menubutton.width 6\r\n     # } \\\r\n     # -variable drawmode\r\n\r\n# .bubar.modesel add command rotate -label Rotate\r\n# .bubar.modesel add command move -label Move\r\n# .bubar.modesel add command zoom -label Zoom\r\n\r\nttk::menubutton .bubar.modesel -menu .bubar.modesel.menu -text \"\" -width 6\r\n\r\nmenu .bubar.modesel.menu  -tearoff 0\r\n\r\n.bubar.modesel.menu add command -label \"Rotate\" -command \"set drawmode \\\"rotate\\\" ;.bubar.modesel configure -text \\\"Rotate\\\"\"\r\n.bubar.modesel.menu add command -label \"Move\" -command \"set drawmode \\\"move\\\" ;.bubar.modesel configure -text \\\"Move\\\"\"\r\n.bubar.modesel.menu add command -label \"Zoom\" -command \"set drawmode \\\"zoom\\\" ;.bubar.modesel configure -text \\\"Zoom\\\"\"\r\n\r\n.bubar.modesel.menu invoke \"Rotate\"\r\n\r\n\r\n\r\n      \r\nset viewvals { geometry specpoints mesh solution}\r\nif { $userlevel == 3} {\r\n    set viewvals { geometry mesh specpoints surfmeshing modelview solution}\r\n}\r\n\r\nset viewvallabs(cross)     \"Cross\" \r\nset viewvallabs(geometry)  \"Geometry\" \r\nset viewvallabs(mesh)      \"Mesh\" \r\nset viewvallabs(specpoints) \"Edges\" \r\nset viewvallabs(surfmeshing) \"Mesh Gen\" \r\nset viewvallabs(modelview)     \"Modeller\" \r\nset viewvallabs(solution)     \"Solution\" \r\n\r\n# tixOptionMenu .bubar.selview \\\r\n    # -options {\r\n\t# label.width  0\r\n\t# label.anchor e\r\n\t# menubutton.width 10\r\n    # } \\\r\n\r\n# foreach viewv $viewvals {\r\n    # .bubar.selview add command $viewv -label $viewvallabs($viewv)\r\n# }\r\n\r\n# .bubar.selview config -variable selectvisual\r\n# .bubar.selview config -command { Ng_SetVisParameters; redraw }\r\n\r\n\r\n\r\n# pack .bubar.modesel -side right\r\n# pack forget .bubar.modesel\r\n\r\npack .bubar.center .bubar.zoomall -side right\r\n# pack .bubar.selview -side right\r\n\r\n.ngmenu.view add checkbutton -variable viewrotatebutton \\\r\n    -label \"Enable LeftButton Selection\" \\\r\n    -command { \r\n\tif { $viewrotatebutton } {\r\n\t    pack .bubar.modesel -side right\r\n\t} {\r\n\t    pack forget .bubar.modesel\r\n\t}\r\n    }\r\n\r\nmenu .bubar.selviewmenu\r\nttk::menubutton .bubar.selview1 -menu .bubar.selviewmenu -text \"Geometry\"\r\nforeach viewv $viewvals {\r\n    .bubar.selviewmenu add command -label $viewvallabs($viewv) -command \\\r\n        \".bubar.selview1 configure -text \\\"$viewvallabs($viewv)\\\" ; set selectvisual $viewv ; Ng_SetVisParameters; redraw\"\r\n}\r\npack .bubar.selview1 -side right\r\n# .bubar.selviewmenu invoke $viewvallabs($selectvisual)\r\n\r\ntrace add variable selectvisual write selvis_monitor\r\nproc selvis_monitor { name args } {\r\n    global selectvisual viewvallabs    \r\n    .bubar.selviewmenu invoke $viewvallabs($selectvisual)\r\n} \r\n# set selectvisual solution\r\n\r\n\r\n#####################################################\r\n#                                                   #\r\n#     Status bar                                    #\r\n#                                                   #\r\n#####################################################\r\n\r\nttk::label .helpline -text \"None\"\r\npack forget .helpline -side bottom -fill x\r\n\r\nttk::frame .statbar -relief flat\r\n# -bd 2\r\npack .statbar -side bottom -fill x\r\n\r\nttk::label .statbar.ptslabel -text \"   Points: \"\r\nttk::label .statbar.ptsval -textvariable status_np\r\nttk::label .statbar.elslabel -text \"   Elements: \"\r\nttk::label .statbar.elsval -textvariable status_ne\r\nttk::label .statbar.selslabel -text \"   Surf Elements: \"\r\nttk::label .statbar.selsval -textvariable status_nse\r\n# label .statbar.memlabel -text \"   Mem: \"\r\n# label .statbar.memval -textvariable mem_moveable\r\nttk::label .statbar.task -textvariable status_task\r\n\r\npack .statbar.ptslabel .statbar.ptsval -side left -ipady 3p \r\npack .statbar.elslabel .statbar.elsval -side left -ipady 3p \r\npack .statbar.selslabel .statbar.selsval -side left -ipady 3p\r\n\r\n# if { $userlevel == 3 } {\r\n#    pack .statbar.memlabel .statbar.memval -side left -ipady 3p\r\n# }\r\n\r\n\r\n#tixMeter .statbar.per -value 0 -text 0%\r\nttk::progressbar .statbar.per -value 0 -maximum 1\r\n#.statbar.per configure -fillcolor blue\r\n\r\npack .statbar.per -side right\r\npack .statbar.task -side right -ipady 4\r\n\r\nset qualbaraxis(0) 0\r\nset qualbar(0) 0\r\nset qualbarnull(0) 0\r\n\r\n\r\n\r\nproc timer2 { } {\r\n    global status_np\r\n    global status_ne\r\n    global status_nse\r\n    global multithread_running\r\n    global multithread_redraw\r\n    global status_working\r\n    global status_task\r\n    global status_percent\r\n    global status_tetqualclasses\r\n    \r\n\r\n    Ng_ReadStatus \r\n\r\n    if { $multithread_redraw == 1 } {\r\n        # non-blocking redraw\r\n\tset multithread_redraw 0;\r\n\tredraw;\r\n        \r\n        global videoactive\r\n        if { $videoactive == 1 } {\r\n            puts \"addframe\"\r\n            Ng_VideoClip .ndraw addframe\r\n        }\r\n    }\r\n    if { $multithread_redraw == 2 } {\r\n        # blocking redraw\r\n\tredraw;\r\n\tset multithread_redraw 0;\r\n        \r\n        global videoactive\r\n        if { $videoactive == 1 } {\r\n            puts \"addframe\"\r\n            Ng_VideoClip .ndraw addframe\r\n        }\r\n        after 1 { timer2 }\r\n        return\r\n    }\r\n\r\n\r\n    # global mem_moveable\r\n    # set mem_moveable [Ng_MemInfo moveable]\r\n\r\n\r\n    .statbar.per configure -value [expr $status_percent/100]\r\n#    -text [format %2.1f [expr 0.1*int(10*$status_percent)]]%\r\n\r\n\r\n    if { $multithread_running } {\r\n\tpack .statbar.per -side right -before .statbar.task -padx 6\r\n    } { \r\n\tpack forget .statbar.per\r\n    }\r\n\t\r\n\r\n\r\n    # tet quality\r\n    if {[winfo exists .qualityview_dlg] == 1} {\r\n\t\r\n\tglobal qualbar\r\n\tglobal qualbarnull\r\n\tglobal qualbaraxis\r\n\r\n\tset maxval 0\r\n\tfor {set i 0} {$i < 20} {incr i} {\r\n\t    if {[lindex $status_tetqualclasses $i] > $maxval} {\r\n\t\tset maxval [lindex $status_tetqualclasses $i]\r\n\t    }\r\n\t} \r\n\r\n\tset ubound 1\r\n\twhile { $ubound < $maxval } {\r\n\t    set ubound [expr {10 * $ubound}]\r\n\t}\r\n\tif { $ubound/5 > $maxval } {\r\n\t    set ubound [expr $ubound/5]\r\n\t}\r\n\tif { $ubound/2 > $maxval } {\r\n\t    set ubound [expr $ubound/2]\r\n\t}\r\n\r\n\r\n\t\r\n\tfor {set i 1} {$i <= 5} {incr i} {\r\n\t    # global qualbaraxis($i)\r\n\r\n\t    set value [expr { $i * $ubound / 5 }]\r\n\t    .qualityview_dlg.c dchars $qualbaraxis($i) 0 end\r\n\t    .qualityview_dlg.c insert $qualbaraxis($i) end $value  \r\n\t}\r\n\r\n\t\r\n\tfor {set i 0} {$i < 20} {incr i} {\r\n\t    set x1 [expr {100 + ($i*15) + 2}]\r\n\t    set x2 [expr {$x1+10}]\r\n\t    \r\n\t    set nbrs [lindex $status_tetqualclasses $i]\r\n\t    set y [expr (249 - (200 * $nbrs / $ubound ) )]\r\n\t    \r\n\t    # global qualbar($i)\r\n\t    .qualityview_dlg.c coords $qualbar($i) $x1 250 $x2 $y\r\n\r\n#\t    global qualbarnull($i)\r\n\t    if { $nbrs == 0 } {\r\n\t\t.qualityview_dlg.c itemconfigure $qualbarnull($i) -text 0\r\n\t    } {\r\n\t\t.qualityview_dlg.c itemconfigure $qualbarnull($i) -text \"\" \r\n\t    }\t\t\r\n\t}\r\n\t\r\n    }\r\n\r\n\r\n    if {[winfo exists .memuse_dlg] == 1} {    \r\n\t\r\n\tglobal memmark\r\n\tset usemb [Ng_MemInfo usedmb]\r\n\tfor {set i 0} {$i < [string length $usemb] } {incr i} {\r\n\t    if { [string index $usemb $i] == 0 } {\r\n\t\t.memuse_dlg.c coords $memmark($i)  [expr 50+$i] 68 [expr 50+$i] 70\r\n\t    } {\r\n\t\t.memuse_dlg.c coords $memmark($i)  [expr 50+$i] 50 [expr 50+$i] 70\r\n\t    }\r\n\t}\r\n\r\n    }\r\n    after 40 { timer2 }\r\n}\r\n# after 1000 { timer2 }\r\ntimer2\r\n\r\n\r\n\r\n\r\nproc bgerror { error } {\r\n    global errorInfo userlevel\r\n    if { $userlevel == 3} {\r\n\tputs \"ERROR: $error\" \r\n\tputs \"errinfo: $errorInfo\"\r\n    }\r\n    tk_messageBox -title \"Error Message\" -message $error -type ok \r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nproc smh2 { menuitem } {\r\n    if {[catch {$menuitem entrycget active -label} name]} {\r\n\tset name \"    \"\r\n    } \r\n    show_menu_help $name \r\n    update idletasks\r\n}\r\n\r\nbind .ngmenu <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.file <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.geometry <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.mesh <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.view <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.meshsize <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.special <<MenuSelect>> { smh2 %W }\r\nbind .ngmenu.help <<MenuSelect>> { smh2 %W }\r\n\r\n\r\n# command bindings  \r\nbind . <q> { .ngmenu.file invoke \"Quit\" }\r\nbind . <l><g> { .ngmenu.file invoke \"Load Geometry...\" }  ; \r\nbind . <l><m> { .ngmenu.file invoke \"Load Mesh...\" }  ;\r\nbind . <s><m> { .ngmenu.file invoke \"Save Mesh...\" }  ;\r\nbind . <r><f> { .ngmenu.file activate \"Recent Files\" }  ;\r\nbind . <n><p> { newprimitivedialog }      ; # \r\nbind . <e><p> { editprimitivedialog }\r\nbind . <e><s> { newsoliddialog }\r\nbind . <g><m> { .ngmenu.mesh invoke \"Generate Mesh\" }  ;\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "ng/netgen.ocf",
    "content": "# Netgen Mesher\r\n# Boundary Condition Colour Profile\r\n#\r\n# Name: netgen.ocf\r\n#\r\n# Description: Netgen default colour \r\n# profile file for colour based automatic \r\n# assignment of boundary condition numbers\r\n#\r\n# Format: \r\n# [boundary_colours] (mandatory keyword)\r\n# <num of entries>\r\n# <bc_num1> <R> <G> <B>\r\n# <bc_num2> <R> <G> <B>\r\n# ....\r\n# ....\r\n# NOTE: \r\n# * Currently, the default Boundary \r\n# Condition number assigned to faces without \r\n# any colour defined is \"1\"\r\n# * Boundary Condition number \"0\" is invalid, \r\n# and should not be used\r\n\r\nboundary_colours\r\n7\r\n2\t0.0000\t0.0000\t0.0000\r\n3\t1.0000\t0.0000\t0.0000\r\n4\t0.0000\t0.0000\t1.0000\r\n5\t1.0000\t1.0000\t0.0000\r\n6\t0.0000\t1.0000\t1.0000\r\n7\t1.0000\t0.0000\t1.0000\r\n8\t1.0000\t1.0000\t1.0000\r\n"
  },
  {
    "path": "ng/netgenpy.cpp",
    "content": "// a wrapper to load netgen-dll into python\r\n\r\n#include <iostream>\r\n#include <../general/ngpython.hpp>\r\n#include <core/ngcore_api.hpp>\r\n\r\nvoid NGCORE_API_IMPORT ExportNetgenMeshing(py::module &m);\r\nvoid NGCORE_API_IMPORT ExportCSG(py::module &m);\r\nvoid NGCORE_API_IMPORT ExportGeom2d(py::module &m);\r\nvoid NGCORE_API_IMPORT ExportSTL(py::module &m);\r\n#ifdef OCCGEOMETRY\r\nvoid NGCORE_API_IMPORT ExportNgOCC(py::module &m);\r\n#endif // OCCGEOMETRY\r\n\r\nPYBIND11_MODULE(libngpy, ngpy)\r\n{\r\n  py::module::import(\"pyngcore\");\r\n    py::module meshing = ngpy.def_submodule(\"_meshing\", \"pybind meshing module\");\r\n    ExportNetgenMeshing(meshing);\r\n    py::module csg = ngpy.def_submodule(\"_csg\", \"pybind csg module\");\r\n    ExportCSG(csg);\r\n    py::module geom2d = ngpy.def_submodule(\"_geom2d\", \"pybind geom2d module\");\r\n    ExportGeom2d(geom2d);\r\n    py::module stl = ngpy.def_submodule(\"_stl\", \"pybind stl module\");\r\n    ExportSTL(stl);\r\n#ifdef OCCGEOMETRY\r\n    py::module NgOCC = ngpy.def_submodule(\"_NgOCC\", \"pybind NgOCC module\");\r\n    ExportNgOCC(NgOCC);\r\n#endif // OCCGEOMETRY\r\n}\r\n"
  },
  {
    "path": "ng/ng.tcl",
    "content": "catch {lappend auto_path $env(NETGENDIR) }\ncatch {lappend auto_path $env(NETGENDIR)/../lib }\n\nif {[catch {Ng_GetCommandLineParameter batchmode} result ]} {\n\tload libnggui[info sharedlibextension] gui\n}\n\nset batchmode [Ng_GetCommandLineParameter batchmode]\nif {$batchmode==\"undefined\"} {\n    # if {[catch {package require Tix } result ]} {\n    # puts \"cannot load package Tix\"\n    # puts \"error : $result\"\n    # }\n    if {[catch {package require tkdnd } result ]} {\n#        puts \"cannot load package tkdnd\"\n#        puts \"error : $result\"\n    }\t\n}\n# if {[catch {package require Togl 2.0 } result ]} {\n#    puts \"cannot load package Togl 2.0\"\n#    puts \"error : $result\"\n# }\n\n# load [file dirname [info script]]/gears[info sharedlibextension]\n# puts \"load togl lib\"\n# load /Users/joachim/tcl_native3/Togl2.1/libTogl2.1.dylib\n# puts \"have togl lib\"\n# if {[catch {package require Togl 2.0 } result ]} {\n#    puts \"cannot load package Togl 2.0\"\n#    puts \"error : $result\"\n# }\n\n\n\n# userlevel 1..standard user 2..power-user 3..developer\n\nset userlevel 3\nif { [Ng_GetCommandLineParameter expert]==\"defined\" } {\n    set userlevel 3\n}\n\nset progname \"NETGEN\"\n\nset ngdir \"\"\nif { [lsearch [array names env] NETGENDIR] != -1 } {\n    set ngdir $env(NETGENDIR) \n}\nif { [string length $ngdir] == 0 } {\n    set ngdir \".\" \n}\n\nset nguserdir \"\"\nif { [lsearch [array names env] NETGEN_USER_DIR] != -1 } {\n    set nguserdir $env(NETGEN_USER_DIR) \n}\nif { [string length $nguserdir] == 0 } {\n    set nguserdir \".\" \n}\n\n\n\n\nset batchmode [Ng_GetCommandLineParameter batchmode]\n\nset solvemode 0\nif { [Ng_GetCommandLineParameter solve] != \"undefined\" || \\\n\t [Ng_GetCommandLineParameter recent] == \"defined\" } {\n    set solvemode defined\n}\n\nset shellmode [Ng_GetCommandLineParameter shellmode]\n\nif { $shellmode == \"defined\" } {\n  set batchmode \"defined\"\n}\n\n\nif { $batchmode != \"defined\" } {\n    catch {\n\twm withdraw .\n     \n\twm title . $progname\n\twm geometry . =850x600\n\twm minsize . 400 300\n    }\n}\n\n\nsource ${ngdir}/variables.tcl\nsource ${ngdir}/parameters.tcl\n\nif { $batchmode != \"defined\" } {\n    catch {\n\tsource ${ngdir}/menustat.tcl\n    }\n}\n\ncatch { \n    source ${ngdir}/dialog.tcl\n}\n\ncatch {\n    source ${ngdir}/drawing.tcl\n}\n\n\n# if { [catch { load libgeom2dvis[info sharedlibextension] Ng_Geom2d } result ] } {\n#    puts \"cannot load 2d meshing module\" \n#    puts \"error: $result\"\n# }\n\ncatch { source ${ngdir}/csgeom.tcl }\ncatch { source ${ngdir}/stlgeom.tcl }\n\nset hasocc no\ncatch { source ${ngdir}/occgeom.tcl }\n\nsource ${ngdir}/acisgeom.tcl\n\n\ncatch { source ${ngdir}/nghelp.tcl }\ncatch { source ${ngdir}/ngvisual.tcl }\ncatch { source ${ngdir}/sockets.tcl }\ncatch { source ${ngdir}/acis.tcl }\n\n\n\nset zugstange 0\ncatch { source ${ngdir}/trafo/menu.tcl } \n\n\n\nsetgranularity ${meshoptions.fineness}\n\nNg_SetMeshingParameters\nNg_SetVisParameters\nNg_SetDebugParameters\nNg_STLDoctor\nNg_GeometryOptions set\n\nif { $hasocc == \"yes\" } {\n    Ng_SetOCCVisParameters\n}\n\n\nif { $batchmode != \"defined\" } {\n    catch { \n\twm protocol . WM_DELETE_WINDOW { .ngmenu.file invoke \"Quit\" }\n\twm deiconify .\n    }\n}\n\nset trafoapp 0\ncatch { source ${ngdir}/trafoapp/trafoapp.tcl }\n\nset geofilename [Ng_GetCommandLineParameter geofile]\n\nif { $geofilename != \"undefined\" && \n     [info exists trafo] == 0 && $zugstange == 0} {\n\n    if { [ catch { Ng_LoadGeometry $geofilename } errstring] == 0 } {\n\tif { $batchmode != \"defined\" } {\n\t    AddRecentFile $geofilename\n\t}\n\tNg_ParseGeometry\n\tif { $batchmode != \"defined\" } {\n\t    set selectvisual geometry\n\t    Ng_SetVisParameters\n\t    redraw\n\t    wm title . [concat \"$progname - \" $geofilename]\n\t}\n\tset dirname [file dirname $geofilename]\n\tset basefilename [file tail [file rootname $geofilename]]\n    } {\n\tputs \"Problem with input file:\"\n\tputs \"$errstring\"\n    }\n}\n\n\nset cnt 0\nforeach { gran } { verycoarse coarse moderate fine veryfine } {\n    set cnt [expr $cnt + 1]\n    if { [Ng_GetCommandLineParameter $gran] == \"defined\" } {\n\tset meshoptions.fineness $cnt\n\tsetgranularity ${meshoptions.fineness}\n    }\n}\n\n\nset meshfilename [Ng_GetCommandLineParameter meshfile]\nif { $meshfilename == \"undefined\" } {\n    set meshfilename out.mesh\n}\n\nset meshfiletype [Ng_GetCommandLineParameter meshfiletype]\nif { $meshfiletype == \"undefined\" } {\n    set meshfiletype netgen\n}\n\nset inputmeshfilename [Ng_GetCommandLineParameter inputmeshfile]\n\nset mergemeshfilename [Ng_GetCommandLineParameter mergefile]\n\nset meshsizefilename [Ng_GetCommandLineParameter meshsizefile]\n\nif { $meshsizefilename != \"undefined\" } {\n    set options.meshsizefilename $meshsizefilename\n}\n\nset refinementfilename [Ng_GetCommandLineParameter refinementfile]\n\n\nif { $batchmode == \"defined\" && $solvemode != \"defined\"} {\n    set options.parthread 0\n    if { $shellmode == \"undefined\" } {\n# old batchmode: only processes commandline arguments    \n      set selectvisual mesh\n      Ng_SetVisParameters\n\n      set meshsize [Ng_GetCommandLineParameter meshsize]\n      if {$meshsize != \"undefined\"} { set options.meshsize $meshsize }\n        \n      if { $inputmeshfilename == \"undefined\" } {\n\tNg_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\n      } else {\n\tNg_LoadMesh $inputmeshfilename\n\tif { $mergemeshfilename != \"undefined\" } {\n\t    Ng_MergeMesh $mergemeshfilename\n        }\n      }\n\t\n      if { $refinementfilename != \"undefined\" } {\n\t  Ng_Bisect $refinementfilename\n      }\n\n      if { $meshfiletype == \"netgen\" } {\n\tNg_SaveMesh $meshfilename\n      } else {\n\tif { [catch { Ng_ExportMesh $meshfilename $meshfiletype } ] == 1 } {\n\t    puts \"Unknown file format $meshfiletype\"\n        }\n      }\n      Ng_Exit;\n\n      exit\n  } else {\n      set code [catch { source ${ngdir}/ngshell.tcl } errcode]\n      if {$code} {\n\t  puts \"error: $errcode\"\n      }  \n      set code [ catch {Ng_RunShell} errcode]\n      if {$code} {\n\t  puts \"error: $errcode\"\n      }  \n      \n      Ng_Exit;\n      exit\n  }\n    \n}\n\nset stereo [Ng_GetCommandLineParameter stereo]\nif { $stereo == \"defined\" } {\n    set viewoptions.stereo 1 \n    puts \"use stereo mode\" \n    Ng_SetVisParameters; \n    redraw \n}\n\n\nset ngsolve_loaded 0\ncatch {\n  source ${ngdir}/ngsolve.tcl;\n  set ngsolve_loaded 1\n}\n\n# try to find ngsolve.tcl in PATH\nset pathlist [split $::env(PATH) \\ [expr {$::tcl_platform(platform) == \"windows\" ? \";\" : \":\"}]]\nforeach dir $pathlist {\n  if { $ngsolve_loaded != 1 } {\n    catch {\n      source ${dir}/ngsolve.tcl\n      set ngsolve_loaded 1\n    }\n  }\n}\n\n\nset scriptfilename [Ng_GetCommandLineParameter script]\nif { $scriptfilename != \"undefined\" } {\n    if { [catch { source $scriptfilename } errstring] == 1 } {\n\tputs \"Error in input: $errstring\"\n    }\n}\n\n\nif { [Ng_GetCommandLineParameter help]==\"defined\" } {\n    if { $zugstange == 1 } {\n\tprint_zug_commandline_help\n\texit;\n    } {\n\tif { $trafoapp == 1 } {\n\t    print_trafo_commandline_help;\n\t} {\n\t    print_commandline_help; \n\t    Ng_Exit;\n\t    exit\n\t}\n    }\n}\n\n\nif { [file exists startup.tcl] } {\n    source startup.tcl }\n\n\n\n\ncatch { source ${ngdir}/demoapp.tcl } \ncatch { source ${ngdir}/dropsexp.tcl } \n\n"
  },
  {
    "path": "ng/ng_acis.hpp",
    "content": "#include <acisgeom.hpp>\n#ifdef ACIS_R17\nextern void unlock_spatial_products_661();\n#endif\n\n\nnamespace netgen {\n\n\nACISGeometry * acisgeometry = NULL;\n\nstatic VisualSceneACISGeometry vsacisgeom;\n\n\nextern int ACISGenerateMesh (ACISGeometry & geometry, Mesh*& mesh,\n                             int perfstepsstart, int perfstepsend, char* optstring);\n\n\n\n\n\n\n\n\n\n\n  int Ng_ACISCommand (ClientData /* clientData */,\n\t\t      Tcl_Interp * interp,\n\t\t      int argc, tcl_const char *argv[]) \n  {\n    if (argc >= 2)\n      {\n\tif (strcmp (argv[1], \"isACISavailable\") == 0)\n\t  {\n\t    Tcl_SetResult (interp, (char*)\"yes\", TCL_STATIC);\n\t    return TCL_OK;\n\t  }\n      }\n    \n\n    if (!acisgeometry)\n      {\n\tTcl_SetResult (interp, (char*)\"This operation needs an ACIS geometry\", TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n\n\n    if (argc >= 2 && strcmp (argv[1], \"getentities\") == 0)\n      {\n        stringstream str;\n        const ENTITY_LIST & entlist = acisgeometry -> entlist;\n\n\n        ENTITY_LIST cellList;\n        api_ct_get_all_cells( entlist, cellList );\n        for(int j=0; j<cellList.count(); j++)\n          {\n            str << \"cell\" << j << \" {Cell \" << j << \"} \\n\";\n\n            ATTRIB * ap = cellList[j]->attrib();\n            int k = 0; \n\n            while (ap)\n              {\n                ATTRIB_GEN_INTEGER * aip = dynamic_cast<ATTRIB_GEN_INTEGER *>(ap);\n                if (aip)\n                  str << \"cell\" << j << \"/attrib\" << k \n                      << \" { name = \" << aip->name() << \" val = \" << aip->value() << \"}  \\n\";\n                else\n                  str << \"cell\" << j << \"/attrib\" << k \n                      << \" { typename = \" << ap->type_name() << \"}  \\n\";\n                      \n                ap = ap->next();\n                k++;\n              }\n          }\n\n\n        for (int i = 0; i < entlist.count(); i++)\n          {\n            str << \"entity\" << i << \" {Entity \" << i << \"} \\n\";\n            ENTITY_LIST faceList;\n            ENTITY_LIST edgeList;\n            \n            api_get_faces_from_all_entities(entlist[i], faceList);\n\n            for(int j=0; j<faceList.count(); j++)\n              {\n                FACE * face = (FACE*) faceList[j];\n\n                str << \"entity\" << i << \"/face\" << j << \" {Face \" << j << \"} \\n\";\n              \n                ATTRIB * ap = faceList[j]->attrib();\n                int k = 0; \n\n                while (ap)\n                  {\n                    ATTRIB_GEN_INTEGER * aip = dynamic_cast<ATTRIB_GEN_INTEGER *>(ap);\n                    if (aip)\n                      str << \"entity\" << i << \"/face\" << j << \"/attrib\" << k \n                          << \" { name = \" << aip->name() << \" val = \" << aip->value() << \"}  \\n\";\n                    else\n                      str << \"entity\" << i << \"/face\" << j << \"/attrib\" << k \n                          << \" { typename = \" << ap->type_name() << \"}  \\n\";\n                      \n                    ap = ap->next();\n                    k++;\n                  }\n\n                SPAbox * box = face->bound();\n                str << \"entity\" << i << \"/face\" << j << \"/bbox\" \n                    << \" { BBox (\" \n                    << box->low().x() << \", \" << box->low().y() << \", \" << box->low().z() << \";\" \n                    << box->high().x() << \", \" << box->high().y() << \", \" << box->high().z() << \")\" \n                    << \" }\\n\";\n              }\n\n        \n            api_get_edges_from_all_entities(entlist[i], edgeList);\n            \n            for(int j=0; j<edgeList.count(); j++)\n              {\n                str << \"entity\" << i << \"/edge\" << j << \" {Edge \" << j << \"} \\n\";\n              }\n          }\n        \n        Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE);\n        return TCL_OK;\n      }\n    \n    if (argc >= 2 && strcmp (argv[1], \"selectentity\") == 0)\n      {\n        int ientry = -1, iface = -1;\n\n        string select = argv[2];\n        cout << \"ACIS selectentity: \" << select << endl;\n\n        int pos_ent1 = select.find(\"entity\", 0);\n        int pos_ent2 = select.find(\"/\", pos_ent1);\n        if (pos_ent1 != -1 && pos_ent2 == -1) pos_ent2 = select.length();\n        if (pos_ent1 != -1) ientry = atoi (select.substr(pos_ent1+6, pos_ent2).c_str());\n\n        int pos_face1 = select.find(\"face\", 0);\n        int pos_face2 = select.find(\"/\", pos_face1);\n        if (pos_face1 != -1 && pos_face2 == -1) pos_face2 = select.length();\n        if (pos_face1 != -1) iface = atoi (select.substr(pos_face1+4, pos_face2).c_str());\n\n        cout << \"entry = \" << ientry << \", face = \" << iface << endl;\n\n        const ENTITY_LIST & entlist = acisgeometry -> entlist;\n\n        if (ientry != -1 && iface == -1)\n          vsacisgeom.SelectEntity (entlist[ientry]);\n\n        if (iface != -1)\n          {\n            ENTITY_LIST faceList;\n            api_get_faces_from_all_entities(entlist[ientry], faceList);\n            vsacisgeom.SelectEntity (faceList[iface]);\n          }\n      }\n\n\n    if (argc >= 2 && strcmp (argv[1], \"createct\") == 0)\n      {\n\tacisgeometry -> CreateCT();\n      }\n\n    if (argc >= 2 && strcmp (argv[1], \"combineall\") == 0)\n      {\n\tcout << \"combineall \" << endl;\n\tacisgeometry -> Combine();\n      }\n\n\n\n    if (argc >= 4)\n      {\n\tif (strcmp (argv[1], \"subtract\") == 0)\n\t  {\n\t    cout << \"subtract \" << argv[2] << \" minus \" << argv[3] << endl;\n\t    acisgeometry -> Subtract (atoi (argv[2])-1, atoi (argv[3])-1);\n\t  }\n\n      }\n\n    return TCL_OK;\n  }\n\n\n}\n"
  },
  {
    "path": "ng/ngappinit.cpp",
    "content": "/*\n  The main function of netgen.\n  This file is a modification of tkAppInit.c from the Tcl/Tk package\n*/\n\n#undef USE_TCL_STUBS\n#undef USE_TK_STUBS\n\n#include <mystdlib.h> \n#include <inctcl.hpp>\n#include <meshing.hpp>\n#include <core/mpi_wrapper.hpp>\n\n#include \"../libsrc/interface/writeuser.hpp\"\n\n#ifdef NETGEN_PYTHON\n#include <core/python_ngcore.hpp>\n#endif\n\nnamespace netgen\n{\n  DLL_HEADER extern Flags parameters;\n  DLL_HEADER extern bool netgen_executable_started;\n}\n \nDLL_HEADER extern bool nodisplay;\n\n\nusing netgen::parameters;\nusing netgen::ngdir;\nusing netgen::verbose;\nusing netgen::NgArray;\nusing netgen::RegisterUserFormats;\n\nusing std::string;\nusing std::endl;\nusing std::cout;\nusing std::cerr;\nusing std::ofstream;\n\n\n\n/*\n * The following variable is a special hack that is needed in order for\n * Sun shared libraries to be used for Tcl.\n */\n\n// extern \"C\" int matherr();\n// int *tclDummyMathPtr = (int *) matherr;\n\nextern \"C\" int Ng_ServerSocketManagerInit (int port);\nextern \"C\" int Ng_ServerSocketManagerRun (void);\n \nbool shellmode = false;\n\n\n/*\n *\n *     The Netgen main function\n *\n */\n\nint main(int argc, char ** argv)\n{\n  netgen::netgen_executable_started = true;\n\n  if ( netgen::id == 0 )\n    {\n      cout << \"NETGEN-\" << netgen::netgen_version << endl;\n      \n      cout << \"Developed by Joachim Schoeberl at\" << endl\n\t   << \"2010-xxxx Vienna University of Technology\" << endl\n\t   << \"2006-2010 RWTH Aachen University\" << endl\n           << \"1996-2006 Johannes Kepler University Linz\" << endl;\n      \n#ifdef OCCGEOMETRY\n      cout << \"Including OpenCascade geometry kernel\" << endl;\n#endif\n      \n#ifdef ACIS\n      cout << \"Including ACIS geometry kernel\" << endl;\n#endif\n\n#ifdef LINUX\n      //feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);\n      //feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW);\n      //cout << \"Handle Floating Point Exceptions: \" << fegetexcept() << endl; \n#endif  \n\n#ifdef DEBUG\n      cout << \"You are running the debug version !\" << endl;\n#endif\n    }\n\n\n  netgen::h_argc = argc;\n  netgen::h_argv = argv;\n\n  // command line arguments:\n  for (int i = 1; i < argc; i++)\n    {\n      if (argv[i][0] == '-')\n\tparameters.SetCommandLineFlag (argv[i]);\n      else\n        {\n          if (strstr(argv[i], \".py\"))\n            parameters.SetFlag (\"py\", argv[i]);\n          else\n            parameters.SetFlag (\"geofile\", argv[i]);\n        }\n    }\n\n\n  if (getenv (\"NETGENDIR\") && strlen (getenv (\"NETGENDIR\")))\n    ngdir = getenv (\"NETGENDIR\");\n  else\n    ngdir = \".\";\n  \n  verbose = parameters.GetDefineFlag (\"V\");\n\n  if (verbose)\n    cout << \"NETGENDIR = \" << ngdir << endl;\n  \n\n  if ( netgen::id == 0 )\n    {\n      if (parameters.StringFlagDefined (\"testout\"))\n        {\n          delete ngcore::testout;\n          ngcore::testout = new ofstream (parameters.GetStringFlag (\"testout\", \"test.out\"));\n        }\n\n\n#ifdef SOCKETS\n      Ng_ServerSocketManagerInit(static_cast<int>(parameters.GetNumFlag(\"serversocket\",-1)));\n      if(parameters.GetNumFlag(\"serversocket\",-1) > 0 && !parameters.GetDefineFlag(\"display\")) \n        nodisplay = true;\n#endif\n  \n      if(parameters.GetDefineFlag(\"batchmode\"))\n        nodisplay = true;\n\n    \n      if(parameters.GetDefineFlag(\"shellmode\"))\n        {\n          nodisplay = true;\n          shellmode = true;\n        }\n\n      Tcl_FindExecutable(NULL);\n\n      // initialize application\n      Tcl_Interp * myinterp = Tcl_CreateInterp ();\n      if (Tcl_AppInit (myinterp) == TCL_ERROR)\n        {\n          cerr << \"Exit Netgen due to initialization problem\" << endl;\n          exit (1);\n        }\n\n\n\n      // parse tcl-script\n      int errcode;\n\n      bool internaltcl = INTERNAL_TCL_DEFAULT;\n      if (shellmode)\n        internaltcl = false;\n  \n      if (verbose)\n        {\n          cout << \"Tcl header version = \" << TCL_PATCH_LEVEL << endl;\n          Tcl_Eval (myinterp, \"puts \\\"Tcl runtime version = [info patchlevel] \\\";\");\n        }\n\n      if (parameters.GetDefineFlag (\"internaltcl\"))\n        internaltcl=true;\n      if (parameters.GetDefineFlag (\"externaltcl\"))\n        internaltcl=false;\n\n \n\n      if (internaltcl)\n        {\n          if (verbose)\n            cout << \"using internal Tcl-script\" << endl;\n      \n          // connect to one string \n          DLL_HEADER extern const char * ngscript[];\n          const char ** hcp = ngscript;\n          int len = 0;\n          while (*hcp)\n            len += strlen (*hcp++); \n\n          char * tr1 = new char[len+1];\n          *tr1 = 0;\n          hcp = ngscript;\n      \n          char * tt1 = tr1;\n          while (*hcp)\n            {\n              strcat (tt1, *hcp); \n              tt1 += strlen (*hcp++);\n            }\n      \n          errcode = Tcl_Eval (myinterp, tr1);\n          delete [] tr1;\n        }\n\n      else\n\n        {\n          string startfile = ngdir + \"/ng.tcl\";\n      \n          if (verbose)\n            cout << \"Load Tcl-script from \" << startfile << endl;\n      \n          errcode = Tcl_EvalFile (myinterp, (char*)startfile.c_str());\n        }\n\n      if (errcode)\n        {\n          cout << \"Error in Tcl-Script:\" << endl;\n          // cout << \"result = \" << myinterp->result << endl;\n          cout << \"result = \" << Tcl_GetStringResult (myinterp) << endl;\n          // cout << \"in line \" << myinterp->errorLine << endl;\n\n          cout << \"\\nMake sure to set environment variable NETGENDIR to directory containing ng.tcl\" << endl;\n          exit (1);\n        }\n\n      /*\n      // lookup user file formats and insert into format list:\n      NgArray<const char*> userformats;\n      NgArray<const char*> extensions;\n      RegisterUserFormats (userformats, extensions);\n\n      ostringstream fstr;\n      \n      tcl_const char * exportft = Tcl_GetVar (myinterp, \"exportfiletype\", 0);\n      for (int i = 1; i <= userformats.Size(); i++)\n\t{\n\t  fstr << \".ngmenu.file.filetype add radio -label \\\"\" \n\t       << userformats.Get(i) << \"\\\" -variable exportfiletype -command { .ngmenu.file invoke \\\"Export Mesh...\\\" } \\n\";\n\t  fstr << \"lappend meshexportformats { {\" << userformats.Get(i) << \"} {\" << extensions.Get(i) << \"} }\\n\";\n\t}\n\n        Tcl_Eval (myinterp, (char*)fstr.str().c_str());\n      Tcl_SetVar (myinterp, \"exportfiletype\", exportft, 0);\n      */\n\n#ifdef SOCKETS\n      Ng_ServerSocketManagerRun();\n#endif\n\n      // start event-loop\n      Tk_MainLoop();\n      Tcl_DeleteInterp (myinterp); \n#ifdef NETGEN_PYTHON\n      py::gil_scoped_acquire ensure_gil;\n#endif\n\n      Tcl_Exit(0);\n    }\n\n  return 0;\t\t\n}\n\n\n\n/*\nextern \"C\" int Tix_Init (Tcl_Interp * interp);\nextern \"C\" int Itcl_Init (Tcl_Interp * interp);\nextern \"C\" int Itk_Init (Tcl_Interp * interp);\n*/\nextern \"C\" int Ng_Init (Tcl_Interp * interp);\nextern \"C\" int Ng_Vis_Init (Tcl_Interp * interp);\n\n\n\n// extern Tcl_PackageInitProc * Tk_SafeInit;\n\n/*\n *\n * Initialize packages\n *\n */\n\n// extern \"C\" int NGSolve_Init (Tcl_Interp * interp);\n\n\nint Tcl_AppInit(Tcl_Interp * interp)\n{\n\n  if (Tcl_Init(interp) == TCL_ERROR) { \n    cerr << \"Problem in Tcl_Init: \" << endl;\n    cout << \"result = \" << Tcl_GetStringResult (interp) << endl;\n    // cerr << interp->result << endl;\n    // return TCL_ERROR;\n  }\n  \n  if (!nodisplay && Tk_Init(interp) == TCL_ERROR) {\n    cerr << \"Problem in Tk_Init: \" << endl;\n    cout << \"result = \" << Tcl_GetStringResult (interp) << endl;\n    // cerr << interp->result << endl;\n    // return TCL_ERROR;\n  }\n\n#ifdef TRAFO\n  //   extern int Trafo_Init (Tcl_Interp * interp);\n  //   if (Trafo_Init(interp) == TCL_ERROR) \n  //     {\n  //       cerr << \"Problem in Trafo_Init: \" << endl;\n  //       cerr << interp->result << endl;\n  //       return TCL_ERROR;\n  //     }\n#endif\n\n#ifdef EBGELAST\n  extern int EBGElast_Init (Tcl_Interp * interp);\n  if(EBGElast_Init(interp) == TCL_ERROR)\n    {\n      cerr << \"Problem in EBGElast_Init: \" << endl;\n      cerr << interp->result << endl;\n      return TCL_ERROR;\n    }\n\n#endif\n\n#ifdef SMALLTRAFO\n  extern int SmallModels_Init (Tcl_Interp * interp);\n  if(SmallModels_Init(interp) == TCL_ERROR)\n    {\n      cerr << \"Problem in SmallModel_Init: \" << endl;\n      cerr << interp->result << endl;\n      return TCL_ERROR;\n    }\n\n#endif\n\n#ifdef SOCKETS\n  extern int Ng_Socket_Init (Tcl_Interp * interp);\n  if ( Ng_Socket_Init(interp) == TCL_ERROR)\n    {\n      cerr << \"Problem in Ng_Socket_Init: \" << endl;\n      cerr << interp->result << endl;\n      return TCL_ERROR;\n    }\n\n#endif\n\n\n#ifdef ZUGSTANGE\n  extern int Zugstange_Init (Tcl_Interp * interp);\n  if (Zugstange_Init(interp) == TCL_ERROR)\n    {\n      cerr << \"Problem in Zugstange_Init: \" << endl;\n      cerr << interp->result << endl;\n      return TCL_ERROR;\n    }\n#endif\n\n\n  Tcl_StaticPackage(interp, \"Tk\", Tk_Init, 0);\n  return TCL_OK;\n}\n\n"
  },
  {
    "path": "ng/ngguipy.cpp",
    "content": "#include <iostream>\n#include <../general/ngpython.hpp>\n#include <core/ngcore_api.hpp>\n\nvoid NGCORE_API_IMPORT ExportMeshVis(py::module &m);\nvoid NGCORE_API_IMPORT ExportCSGVis(py::module &m);\nvoid NGCORE_API_IMPORT ExportSTLVis(py::module &m);\nnamespace netgen\n{\n  std::vector<unsigned char> NGCORE_API_IMPORT Snapshot( int w, int h );\n}\n\nPYBIND11_MODULE(libngguipy, ngpy)\n{\n    py::module::import(\"pyngcore\");\n    py::module meshvis = ngpy.def_submodule(\"meshvis\", \"pybind meshvis module\");\n    ExportMeshVis(meshvis);\n    py::module csgvis = ngpy.def_submodule(\"csgvis\", \"pybind csgvis module\");\n    ExportCSGVis(csgvis);\n    py::module stlvis = ngpy.def_submodule(\"stlvis\", \"pybind stlvis module\");\n    ExportSTLVis(stlvis);\n    ngpy.def(\"Snapshot\", netgen::Snapshot);\n}\n"
  },
  {
    "path": "ng/nghelp.tcl",
    "content": "proc print_commandline_help { } {\n    \n    puts \"Usage: ng { options }\"\n\n    puts \"-geofile=filename      Input geometry file (alternative:  ng filename)\"\n    puts \"-meshfile=filename     Output mesh file\"\n    puts \"-verycoarse, -coarse, -moderate, -fine, -veryfine\"\n    puts \"                       Automatic mesh-size selection\"\n    puts \"-meshsizefile=filename Load mesh-size file with local mesh sizes\"\n    puts \"-meshfiletype={\\\"Neutral Format\\\", ...}\"\n    puts \"                       Filetype of output file, default is netgen file\"\n    puts \"-batchmode             Run Netgen in batchmode\"\n    puts \"-inputmeshfile=filename\"\n    puts \"                       Input mesh file (batchmode only)\"\n    puts \"-mergefile=filename    Merge with mesh file (batchmode only)\"\n    puts \"-refinementfile=filename\"\n    puts \"                       Use refinementinfo from file (batchmode only)\"\n    puts \"-serversocket=\\#num    Start a Netgen server with port \\#num\"\n    puts \"-V                     Print additional information\"\n    puts \"-testout=filename      file for test output\"\n\n    if { [catch { NGS_GetData } ] == 0 } { \n\tputs \"\\nNGSolve parameters:\"\n\tputs \"-pdefile=filename      Load pde input file\"\n\tputs \"-solve                 Solve pde once\"\n\tputs \"-solve=n               Solve pde by n adaptive refinement steps\"\n\tputs \"-recent                Load and solve most recently loaded pde\"\n    }\n\n}\n\n\n\nproc set_menu_help { entry helpmsg } {\n    global menuhelps\n    set menuhelps($entry) $helpmsg\n}\n\nproc show_menu_help { entry } {\n    global menuhelps\n\n\n    if {[catch {set helptext $menuhelps($entry)}]} {\n\tset helptext \"no help available   \"\n    }    \n\n    .helpline configure -text $helptext\n    \n    if {[winfo exists .senshelp_dlg]==1} {\n\t.senshelp_dlg.text delete 1.0 end\n\t.senshelp_dlg.text insert end \"Menu item: $entry\\n\\n\"\n\t.senshelp_dlg.text insert end $helptext\n    }\n}\n\n\n#tixBalloon .balloon -statusbar .helpline\n\nproc set_control_help { control helpmsg } {\n    bind $control <Enter> \"show_control_help {$helpmsg}\"\n    bind $control <Leave> \"show_control_help {None}\"\n    .balloon bind  $control -balloonmsg $helpmsg -statusmsg $helpmsg\n#    puts \"Add Help to $control\"\n}\n\nproc show_control_help { helpmsg } {\n    .helpline configure -text $helpmsg\n    if {[winfo exists .senshelp_dlg]==1} {\n\t.senshelp_dlg.text delete 1.0 end\n\t.senshelp_dlg.text insert end $helpmsg\n    }\n}\n\n\nproc sensitivehelpdialog { show } {\n\n    set w .senshelp_dlg\n    \n    if {[winfo exists .senshelp_dlg] == 1} {\n\n\tif { $show == 1 } {\n\t    wm withdraw .senshelp_dlg\n\t    wm deiconify $w\n\t    focus $w \n\t} {\n\t    wm withdraw $w\n\t}\n    } {\n\ttoplevel $w\n#\twm minsize $w 200 150\n\n\tglobal senshelptext\n\n\ttext $w.text -yscrollcommand \"$w.scroll set\" -setgrid true \\\n\t    -width 40 -height 10  -wrap word\n\tscrollbar $w.scroll -command \"$w.text yview\"\n\tpack $w.scroll -side right -fill y\n\tpack $w.text -expand yes -fill both\n\n\tttk::frame $w.bu\n\tpack $w.bu\n\t# -fill x\n\t\n\tttk::button $w.close -text \"Close\" \\\n\t    -command { \n\t\twm withdraw .senshelp_dlg\n\t\tset showsensitivehelp 0\n\t    }\n\tpack $w.close\n    \n\t\n\tif { $show == 1 } {\n\t    wm withdraw $w\n\t    wm geom $w +100+100\n\t    wm deiconify $w\n\t    wm title $w \"Help\"\n\t    focus $w\n\t}\n    }\n}\n\n\n\nset_menu_help \"File\"  \"In File menu you can load and store geometries, meshes etc.\" \n\nset_menu_help \"New Geometry\"  \"Deletes current geometry\"\nset_menu_help \"Load Geometry\"  \"Loads Geometry file in one of the formats STL (ASCII or binary), Constructive Solid Geometry (.geo) or 2D geometry. Please have a look into Netgen User's manuel for more details.\"\nset_menu_help \"Save Geometry\" \"Saves STL Geometry in in either ASCII or binary STL format.\"\nset_menu_help \"Load Mesh\" \"Loads surface and volume mesh in Netgen internal format.\"\nset_menu_help \"Save Mesh\" \"Saves surface and volume mesh in Netgen internal format.\"\nset_menu_help \"Write EPS File\" \"Dumps OpenGL rendering to EPS File.\"\nset_menu_help \"Save Options\" \"Saves current options in file \\\"ng.opt\\\". These options will be loaded again when starting ng in the same directory.\"\nset_menu_help \"Export Mesh\" \"Exports mesh in format defined by Export Filetype.\"\nset_menu_help \"Export Filetype\" \"Selects file format for exporting mesh. Please have a look into the Netgen User's manual for more information.\"\nset_menu_help \"Import Mesh\" \"Imports surface or volume mesh in exchange format.\"\nset_menu_help \"Quit\" \"Quits Netgen\"\n\nset_menu_help \"Geometry\" \"Preparing geometries, visualiztion of geometries.\"\nset_menu_help \"Scan CSG Geometry\" \"Generates surface triangulation for rendering\"\nset_menu_help \"CSG Options\" \"Sets Options for CSG visualization (bounding box, detail size, number of facets).\"\nset_menu_help \"CSG Properties\" \"Defines appearance of current CSG geometry (color, visibility, transparency)\"\nset_menu_help \"STL Doctor\" \"Calls STL Doctor for preprocessing STL geometry files.\"\nset_menu_help \"STL Info\" \"Retrieves information about current STL geometry.\"\n\nset_menu_help \"Mesh\" \"Menu for mesh generation\"\nset_menu_help \"Generate Mesh\" \"Generates mesh from geometry, same as Button \\\"Generate Mesh\\\"\"\nset_menu_help \"Stop Meshing\" \"Terminates meshgeneration. It may take a while until meshing terminates, please be patient.\"\nset_menu_help \"Meshing Options\" \"Set options for mesh generation.\"\nset_menu_help \"Delete Mesh\" \"Deletes mesh. Not necessary before generation of new mesh.\"\nset_menu_help \"Delete Vol Mesh\" \"Deletes only volume mesh.\"\nset_menu_help \"Mesh Quality\" \"Computs element shape measures. Triangle angles are inner angles of all triangles (faces of tetrahedra). Tet angles are angles between faces of tetrahedra.\"\nset_menu_help \"Check Surface Mesh\" \"Checks consistency and overlap of surface mesh. Marks overlapping elements as bad elements, please enable visualization of bad elements in View->Mesh.\"\nset_menu_help \"Check Volume Mesh\" \"Checks conformity of volume mesh.\"\nset_menu_help \"Edit Boundary Conditions\" \"Open dialog for setting boundary condition numbers for individual faces.\"\nset_menu_help \"Analyze Geometry\" \"Perform only first step in mesh generation. Action depends on geometry type, e.g. generates charts for STL mesh, find vertices in CSG geometries.\"\nset_menu_help \"Mesh Edges\" \"Meshes edges\"\nset_menu_help \"Mesh Surface\" \"Generates surface mesh. Includes already surface optimization for some geometry types.\"\nset_menu_help \"Optimize Surface\" \"Optimizes surface mesh.\"\nset_menu_help \"Surface Optim. Step\" \"Performs a specific surface optimiztion step. Mesh smoothing moves nodes. edge swapping swaps the diagonal of a quadrilateral built by two triangles, criterion either by number of nodes, or anlges. Combine points eliminates triangles by combining points (in the center of gravity).\"\nset_menu_help \"Mesh Volume\" \"Performs volume meshing. Algorithm is a combination of Delaunay and Rule-based Advancing Front\"\nset_menu_help \"Optimize Volume\" \"Performs additional volume optimization steps\"\nset_menu_help \"Smooth Opt Volume\" \"Performs optimization steps by smoothing iterations\"\nset_menu_help \"Smooth Opt Volume Jacobian\" \"Volume optimization by smoothing iterations. Criterion is optimization of Jacobi determinants. This optimization step is also available for 10-node tetrahedra.\"\n\nset_menu_help \"View\" \"Sets viewing options\"\nset_menu_help \"Zoom all\" \"Zooms scene to show whole object\"\nset_menu_help \"Center\" \"Defines center of rotation\"\nset_menu_help \"Viewing Options\" \"Sets viewing options for geometry, mesh, lighting\"\nset_menu_help \"Clipping Plane\" \"Introduces clipping plane. The clipping plane is defined by the normal vector, and a scaled offset. Clipping of performed by OpenGl rendering\"\nset_menu_help \"Quality Plot\" \"Shows the element quality distribution histogram. Measure is volume scaled by edge-length to the third. Optimal elements have measure 1.\"\nset_menu_help \"Sensitive Help\" \"Shows this help window\"\n\nset_menu_help \"Mesh-size\" \"Manipulations of existing mesh\"\nset_menu_help \"Refine uniform\" \"Refines mesh by splitting elements into eight childs (algorithm of J. Bey)\"\nset_menu_help \"Second Order\" \"Converts 4 node elements to 10 node elements. Edge-midpoitns are projected to the geometry.\"\nset_menu_help \"Refinement Dialog\" \"Controls local mesh refinement\"\nset_menu_help \"Load Meshsize\" \"Loads mesh-size file for local mesh refinement.\"\nset_menu_help \"MS from Surf Mesh\" \"Defines mesh-size by the surface mesh.\"\n\n\n\n\nset f .options_dlg.nb.nbframe.general\n# set_control_help $f \"General meshing page\"\nset_control_help $f.fine \"Controls relative mesh size.\\nThis control affects other mesh-size controls in common\"\nset_control_help $f.first \"First step in mesh generation. Usually, meshing starts from \\\"analyze geometry\\\". If the surface mesh is already available \\\"First step\\\" should be set to \\\"mesh volume\\\"\"\nset_control_help $f.last \"Last step in mesh generation. If only the surface mesh is required, please set \\\"Last Step\\\" to \\\"Optimize Surface\\\"\"\n\nset_control_help .bubar.surfm \"Start mesh generation\"\nset_control_help .bubar.stopm \"Stop mesh generation\"\n\nproc help_item { helptext } {p\n    puts $helptext\n}\n\n\n\n\n\n\n\nproc show_help { } {\n    \n    set w .help\n    \n    if {[winfo exists .help] == 1} {\n\twm withdraw $w\n\twm deiconif $w\n\tfocus $w \n    } {\n\t\n\ttoplevel $w\n\t\n\tframe $w.buttons\n\tpack $w.buttons -side bottom -fill x -pady 2m\n\tbutton $w.buttons.done -text Done -command \"destroy $w\"\n\tpack $w.buttons.done  -side left -expand 1\n\n\ttext $w.text -yscrollcommand \"$w.scroll set\" -setgrid true \\\n\t    -width 60 -height 24 -wrap word\n\tscrollbar $w.scroll -command \"$w.text yview\"\n\tpack $w.scroll -side right -fill y\n\tpack $w.text -expand yes -fill both\n\n    }\n    $w.text configure -state normal\n    $w.text delete 1.0 end\n}\n\n\n\n\n\n\nset bold \"-background #43ce80 -relief raised -borderwidth 1\"\nset normal \"-background {} -relief flat\"\n\n\nproc help_main { } {\n\n    show_help;\n    set w .help\n    global bold\n    global normal\n\n\n    \n    $w.text insert 0.0 \\\n\t{NETGEN Help}\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{1. General} d1\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{2. Menu items } d2\n    $w.text insert end \\n\\n\n\n    foreach tag {d1 d2} {\n\t$w.text tag bind $tag <Any-Enter> \"$w.text tag configure $tag $bold\"\n\t$w.text tag bind $tag <Any-Leave> \"$w.text tag configure $tag $normal\"\n    }\n    \n    $w.text tag bind d1 <1> { puts \"general\"; help_general }\n    $w.text tag bind d2 <1> { help_menus }\n\n    $w.text configure -state disabled\n}\n\n\n\n\n\n\nproc help_general { } {\n\n    show_help;\n    set w .help\n    global bold\n    global normal\n\n    puts \"general called\"\n\n    $w.text insert 0.0 \\\n\t{NETGEN is an automatic three dimensional tetrahedral mesh generation system. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STEP or STL file format. NETGEN contains modules for mesh optimization and hierarchical mesh refinement.}\n\n    $w.text configure -state disabled\n}\n\n\n\n\n\nproc help_menus { } {\n\n    show_help;\n    set w .help\n    global bold\n    global normal\n\n\n    $w.text insert 0.0 \\\n\t{The NETGEN Menu items are}\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{1. File} d1\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{2. Geometry } d2\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{3. Mesh } d3\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{4. View } d4\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{5. Mesh-size } d5\n    $w.text insert end \\n\\n\n    $w.text insert end \\\n\t{6. STL } d6\n\n    foreach tag {d1 d2 d3 d4 d5 d6} {\n\t$w.text tag bind $tag <Any-Enter> \"$w.text tag configure $tag $bold\"\n\t$w.text tag bind $tag <Any-Leave> \"$w.text tag configure $tag $normal\"\n    }\n    \n    $w.text tag bind d1 <1> {puts \"File menu\"}\n    $w.text tag bind d2 <1> {puts \"Geometry menu\"}\n    $w.text tag bind d3 <1> {puts \"Mesh menu\"}\n    $w.text tag bind d4 <1> {puts \"View menu\"}\n    $w.text tag bind d5 <1> {puts \"Mesh-size menu\"}\n    $w.text tag bind d6 <1> {puts \"STL menu\"}\n\n    $w.text configure -state disabled\n}\n\n\n\n"
  },
  {
    "path": "ng/ngicon.tcl",
    "content": "set icon_data {\n/* XPM */\nstatic char *icon2[] = {\n/* width height num_colors chars_per_pixel */\n\"   60    60        6            1\",\n/* colors */\n\". c #000000\",\n\"# c #008000\",\n\"a c #00b700\",\n\"b c #00c700\",\n\"c c #00ff00\",\n\"d s c None c None\",\n/* pixels */\n\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\n\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\n\"dddddddddddddddd..........dddddddddddddddddddddddddddddddddd\",\n\"ddddddddddddddd.c..cc#####................dddddddddddddddddd\",\n\"ddddddddddddd..cccc..ccccccccccccccccc...#...............ddd\",\n\"dddddddddddd.cccccccc..cccccccccccc...ccc..cccccccccc###..dd\",\n\"ddddddddddd.ccccccccccc..ccccccccc.cccccccc.ccccccccccc...dd\",\n\"dddddddddd.cccccccccccccc.cccccc..cccccccccc.ccccccccc.b..dd\",\n\"ddddddddd.cccccccccccccccc..ccc.ccccccccccccc..cccccc.bb..dd\",\n\"ddddddd........................cccccccccccccccc.cccc.bbb..dd\",\n\"dddddd.ccc.ccccccccccccccccc..#..............ccc.c..bbbb..dd\",\n\"dddd..ccccc..cccccccccccccc.#..##############.....bbbbb.b.dd\",\n\"ddd.ccccccccc..ccccccccccc.##.#.#################.bbbbb.b.dd\",\n\"dd.cccccccccccc..cccccccc.###.##.################.bbbbb.b.dd\",\n\"d..cccccccccccccc..ccccc.####.###.###############.bbbbb.b.dd\",\n\"d.a..............cc..cc.#####.####.##############.bbbb.bb.dd\",\n\"d..aaaaaaaaaaaaaa......######.#####.#############.bbbb.bb.dd\",\n\"d.a.aaaaaaaaaaaaaaaaa...#####.######..###########.bbbb.bb.dd\",\n\"d.aa.aaaaaaaaaaaaaaaa...#####.########.##########.bbbb.bb.dd\",\n\"d.aaa.aaaaaaaaaaaaaaa..#.####.#########.##########..b.bbb.dd\",\n\"d.aaaa.aaaaaaaaaaaaaa..#.####.##########.#########..b.bbb.dd\",\n\"d.aaaaa..aaaaaaaaaaaa..##.###.###########.########..b.bbb.dd\",\n\"d.aaaaaaa.aaaaaaaaaaa..###.###.###########.#######..b.bbb.dd\",\n\"d.aaaaaaaa.aaaaaaaaaa..###.###.############.######..b.bbb#.d\",\n\"d.aaaaaaaaa.aaaaaaaaa..####.##.#############.#####...bbbb#.d\",\n\"d.aaaaaaaaaa.aaaaaaaa..#####.#.##############.####...bbbb#.d\",\n\"d.aaaaaaaaaaa.aaaaaaa..#####.#.###############.###...bbbb#.d\",\n\"d.aaaaaaaaaaaa.aaaaaa..######..################.##...bbbb#.d\",\n\"d.aaaaaaaaaaaaa.aaaaaaa.#####..#################.#..bbbbb#.d\",\n\"d.aaaaaaaaaaaaaa.aaaaaa.#####.............#######...bbbbb#.d\",\n\"d.aaaaaaaaaaaaaaa.aaaaa.####.###.#########..........bbbbbb.d\",\n\"dd.aaaaaaaaaaaaaaa.aaaa.###.#####..##############...bbbbbb.d\",\n\"dd.aaaaaaaaaaaaaaaa.aaa.##.########.############.b...bbbbb.d\",\n\"dd.aaaaaaaaaaaaaaaaa.aa.#.##########...########.b.bbb.bbbb.d\",\n\"dd.aaaaaaaaaaaaaaaaaa....##############.######.bb.bbb.bbbb.d\",\n\"dd.aaaaaaaaaaaaaaaaaaaa...##############..###.bbb.bbbb.bbb.d\",\n\"dd.aaaaaaaaaaaaaaaaaa..a.a..............##.#.bbbb.bbbb.bbb.d\",\n\"dd.aaaaaaaaaaaaaaaaa.aaaa.aaaaaaaaaaaaaa....bbbb.bbbbbb.bb.d\",\n\"dd.aaaaaaaaaaaaaaaa.aaaaa.aaaaaaaaaaaaaaaaa.bbbb.bbbbbbb.b.d\",\n\"dd.aaaaaaaaaaaaaaa.aaaaaaa.aaaaaaaaaaaaaaaa.bbbb.bbbbbbb.b.d\",\n\"dd.aaaaaaaaaaaaaa.aaaaaaaaa.aaaaaaaaaaaaaaa.bbbb.bbbbbbbb..d\",\n\"dd.aaaaaaaaaaaaa.aaaaaaaaaaa.aaaaaaaaaaaaaa.bbb.bbbbbbbbb..d\",\n\"dd.aaaaaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaa.bbb.bbbbbbbbbb.d\",\n\"dd.aaaaaaaaaaa.aaaaaaaaaaaaaaa.aaaaaaaaaaaa.bbb.bbbbbbbbbb.d\",\n\"dd.aaaaaaaaaa.aaaaaaaaaaaaaaaaa.aaaaaaaaaaaa.bb.bbbbbbbbb.dd\",\n\"dd.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa.aaaaaaaaaaa.bb.bbbbbbbb.ddd\",\n\"dd.aaaaaaaa.aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaa.b.bbbbbbbb.dddd\",\n\"dd.aaaaaaa.aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaa.b.bbbbbbb.ddddd\",\n\"dd.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa.b.bbbbbb.dddddd\",\n\"dd.aaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa.b.bbbbb.ddddddd\",\n\"ddd.aa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaa..bbbb..dddddddd\",\n\"ddd.a.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaa..bbb.dddddddddd\",\n\"ddd..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaa..bb.ddddddddddd\",\n\"ddd........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aa..b.dddddddddddd\",\n\"ddddddddddd.............aaaaaaaaaaaaaaaaaa.a...ddddddddddddd\",\n\"dddddddddddddddddddddddd............aaaaaaa...dddddddddddddd\",\n\"dddddddddddddddddddddddddddddddddddd.........ddddddddddddddd\",\n\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\n\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\n\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\"\n};\n}\n"
  },
  {
    "path": "ng/ngpkg.cpp",
    "content": "/*\n\nThe interface between the GUI and the netgen library\n\n*/\n\n#include <mystdlib.h>\n#include <myadt.hpp>\n#include <linalg.hpp>\n\n#include <meshing.hpp>\n#include \"../libsrc/meshing/boundarylayer.hpp\"\n\n\n#include <inctcl.hpp>\n#include <visual.hpp>\n\n\n#include <csg.hpp>\n\n#ifdef SOCKETS\n#include \"../libsrc/sockets/sockets.hpp\"\n#include \"../libsrc/sockets/socketmanager.hpp\"\n#endif\n\n#include \"../libsrc/general/gzstream.h\"\n\n\n// to be sure to include the 'right' togl-version\n#include \"Togl2.1/togl.h\"\n// EXTERN int Togl_PixelScale (const Togl * togl);\n\n#include \"fonts.hpp\"\n\nextern bool nodisplay;\n\n#include <nginterface.h>\n\n\n#include \"../libsrc/interface/writeuser.hpp\"\n\nnamespace netgen\n{\n  DLL_HEADER extern MeshingParameters mparam;\n  DLL_HEADER extern void ImportSolution2(const char * filename);\n#include \"demoview.hpp\"\n}\n\n\n#ifdef ACIS\n#include \"ng_acis.hpp\"\n#endif\n\n\n#ifdef JPEGLIB\n#include <jpeglib.h>\n#endif\n\n#ifdef FFMPEG\n#include \"encoding.hpp\"\n#endif\n\n#ifdef NGSOLVE\nextern \"C\" void NGSolve_Exit();\n#endif\n\n// extern void * ngsolve_handle;\n\n\nnamespace netgen\n{\n  extern Flags parameters;\n\n  /*\n  NetgenOutStream operator<< ( ostream & ost, Imp  imp )\n  {\n    return ( NetgenOutStream ( &ost, imp ) );\n  }\n\n  NetgenOutStream operator<< ( ostream & ost, Proc proc )\n  {\n    return ( NetgenOutStream ( &ost, proc ) );\n  }\n\n\n  NetgenOutStream operator<< ( ostream & ost, Procs & procs )\n  {\n    return ( NetgenOutStream ( &ost, procs ) );\n  }\n  */\n\n  DLL_HEADER extern std::shared_ptr<NetgenGeometry> ng_geometry;\n  DLL_HEADER extern std::shared_ptr<Mesh> mesh;\n  Tcl_Interp * tcl_interp;\n\n\n#ifdef SOCKETS\n  AutoPtr<ClientSocket> clientsocket;\n  ServerSocketManager serversocketmanager;\n  //NgArray< AutoPtr < ServerInfo > > servers;\n  NgArray< ServerInfo* > servers;\n  AutoPtr<ServerSocketUserNetgen> serversocketusernetgen;\n#endif\n\n\n\n  // visualization scenes, pointer vs selects which one is drawn:\n\n  DLL_HEADER extern VisualSceneSurfaceMeshing vssurfacemeshing;\n  DLL_HEADER extern VisualSceneMeshDoctor vsmeshdoc;\n\n  static VisualSceneSpecPoints vsspecpoints;\n\n\n\n  DLL_HEADER extern VisualScene *visual_scene;\n  DLL_HEADER extern VisualScene visual_scene_cross;\n\n\n\n  extern char * err_needsmesh;// = (char*) \"This operation needs a mesh\";\n  extern char * err_jobrunning;// = (char*) \"Meshing Job already running\";\n\n\n\n\n\n  static clock_t starttimea;\n  void ResetTime2 ()\n  {\n    starttimea = clock();\n  }\n\n#ifndef SMALLLIB\n  double GetTime2 ()\n  {\n    return double(clock() - starttimea) / CLOCKS_PER_SEC;\n  }\n#endif\n\n\n\n\n\n  // file handling ..\n  int Ng_New (ClientData clientData,\n\t      Tcl_Interp * interp,\n\t      int argc, tcl_const char *argv[])\n  {\n    if (strcmp (argv[1], \"mesh\") == 0)\n      mesh.reset();\n\n    if (strcmp (argv[1], \"geom\") == 0)\n      {\n        /*\n\tdelete ng_geometry;\n\tng_geometry = new NetgenGeometry;\n        */\n        ng_geometry = make_shared<NetgenGeometry>();\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_ImportMesh (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[]);\n\n  int Ng_LoadMesh (ClientData clientData,\n\t\t   Tcl_Interp * interp,\n\t\t   int argc, tcl_const char *argv[])\n  {\n    auto filename = filesystem::u8path(argv[1]);\n\n    if (filename.string().find(\".vol\") == string::npos)\n      {\n\treturn Ng_ImportMesh(clientData,interp,argc,argv);\n      }\n\n    PrintMessage (1, \"load mesh from file \", filename);\n\n    mesh = make_shared<Mesh>();\n    try\n      {\n\tmesh -> Load(filename);\n        SetGlobalMesh (mesh);\n\n#ifdef PARALLEL_NETGEN\n\tMyMPI_SendCmd (\"mesh\");\n\tmesh -> Distribute();\n#endif\n        if(mesh->GetGeometry())\n          ng_geometry = mesh->GetGeometry();\n      }\n    catch (const NgException & e)\n      {\n\tPrintMessage (3, e.What());\n\treturn TCL_ERROR;\n      }\n\n    PrintMessage (2,  mesh->GetNP(), \" Points, \",\n\t\t  mesh->GetNE(), \" Elements.\");\n\n    return TCL_OK;\n  }\n\n\n\n\n\n  int Ng_SaveMesh (ClientData clientData,\n\t\t   Tcl_Interp * interp,\n\t\t   int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    string filename (argv[1]);\n    PrintMessage (1, \"Save mesh to file \", filename, \".... Please Wait!\");\n    \n    ostream * outfile;\n    if (filename.substr (filename.length()-3, 3) == \".gz\")\n      outfile = new ogzstream (filename.c_str());\n    else\n      outfile = new ofstream (filename.c_str());\n\n    mesh -> Save (*outfile);\n    // *outfile << endl << endl << \"endmesh\" << endl << endl;\n\n    if (ng_geometry && !mesh->GetGeometry())\n      ng_geometry -> SaveToMeshFile (*outfile);\n\n    delete outfile;\n    PrintMessage (1, \"Save mesh to file .... DONE!\");\n    return TCL_OK;\n  }\n\n\n\n\n\n  int Ng_MergeMesh (ClientData clientData,\n\t\t    Tcl_Interp * interp,\n\t\t    int argc, tcl_const char *argv[])\n  {\n    string filename (argv[1]);\n\n    PrintMessage (1, \"merge with mesh from file \", filename);\n\n    try\n      {\n\tCSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());\n    \n\t//mesh -> Merge (filename);\n\tifstream infile(filename.c_str());\n\tconst int offset = (geometry) ? geometry->GetNSurf() : 0;\n\tmesh -> Merge(infile,offset);\n\n\tstring auxstring;\n\tif(infile.good())\n\t  {\n\t    infile >> auxstring;\n\t    if(geometry && auxstring == \"csgsurfaces\")\n\t      geometry -> LoadSurfaces(infile);\n\t  }\n      }\n    catch (const NgException & e)\n      {\n\tPrintMessage (3, e.What());\n\treturn TCL_ERROR;\n      }\n\n    PrintMessage (2,  mesh->GetNP(), \" Points, \",\n\t\t  mesh->GetNSE(), \" Surface Elements.\");\n\n    return TCL_OK;\n  }\n\n\n  int Ng_GetImportFormats (ClientData clientData,\n                           Tcl_Interp * interp,\n                           int argc, tcl_const char *argv[])\n  {\n    ostringstream fstr;\n    UserFormatRegister::IterateFormats([&](auto & entry) {\n      fstr << \"{ {\" << entry.format << \"} {\" << entry.extensions[0];\n      for(auto ext : entry.extensions.Range(1, entry.extensions.Size()))\n        fstr << ' ' << ext;\n      fstr << \"} }\\n\";\n    }, true, false);\n    \n    Tcl_SetResult (interp, const_cast<char*>(fstr.str().c_str()), TCL_VOLATILE);\n    return TCL_OK;\n  }\n\n  int Ng_GetExportFormats (ClientData clientData,\n                           Tcl_Interp * interp,\n                           int argc, tcl_const char *argv[])\n  {\n    ostringstream fstr;\n    UserFormatRegister::IterateFormats([&](auto & entry) {\n      fstr << \"{ {\" << entry.format << \"} {\" << entry.extensions[0];\n      for(auto ext : entry.extensions.Range(1, entry.extensions.Size()))\n        fstr << ' ' << ext;\n      fstr << \"} }\\n\";\n    }, false, true);\n    \n    Tcl_SetResult (interp, const_cast<char*>(fstr.str().c_str()), TCL_VOLATILE);\n    return TCL_OK;\n  }\n\n\n  int Ng_ExportMesh (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    string filename (argv[1]);\n    string filetype (argv[2]);\n    PrintMessage (1, \"Export mesh to file \", filename, \".... Please Wait!\");\n\n    // CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry);\n    if (WriteUserFormat (filetype, *mesh, /* *ng_geometry, */ filename))\n      {\n\tostringstream ost;\n\tost << \"Sorry, nothing known about file format \" << filetype << endl;\n\tTcl_SetResult (interp, (char*)ost.str().c_str(), TCL_VOLATILE);\n\treturn TCL_ERROR;\n      }\n\n    PrintMessage (1, \"Export mesh to file .... DONE!\");\n    return TCL_OK;\n  }\n\n\n\n  int Ng_ImportMesh (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[])\n  {\n    const string filename (argv[1]);\n    const string format (argv[2]);\n    PrintMessage (1, \"import mesh from \", filename);\n\n    mesh = make_shared<Mesh>();\n\n    ReadUserFormat (*mesh, filename, format);\n    PrintMessage (2, mesh->GetNP(), \" Points, \",\n\t\t  mesh->GetNE(), \" Elements.\");\n\n    SetGlobalMesh (mesh);\n    mesh->SetGlobalH (mparam.maxh);\n    mesh->CalcLocalH(mparam.grading);\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_ImportSolution (ClientData clientData,\n\t\t\t Tcl_Interp * interp,\n\t\t\t int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    const char * filename = argv[1];\n    PrintMessage (1, \"Import solution from file \", filename);\n\n    ImportSolution2 (filename);\n    return TCL_OK;\n  }\n\n\n\n  static DemoView * demoview = 0;\n  int Ng_ShowDemo (ClientData clientData,\n\t\t   Tcl_Interp * interp,\n\t\t   int argc, tcl_const char *argv[])\n  {\n    const char * filename = argv[1];\n    PrintMessage (1, \"Show demo \", filename);\n    demoview = new DemoView (filename);\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_DemoSetTime (ClientData clientData,\n\t\t      Tcl_Interp * interp,\n\t\t      int argc, tcl_const char *argv[])\n  {\n    cout << \"demosettime, time = \" << argv[1] << endl;\n    int result = -1;\n\n    static char strminusone[] = \"-1\";\n    static char str0[] = \"0\";\n\n    if (demoview)\n      result = demoview->SetTime (atof (argv[1]));\n\n    if (result == -1)\n      Tcl_SetResult (interp, strminusone, TCL_STATIC);\n    else\n      Tcl_SetResult (interp, str0, TCL_STATIC);\n\n    return TCL_OK;\n  }\n\n\n\n\n\n\n\n  int Ng_SaveSolution (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    const char * filename = argv[1];\n    PrintMessage (1, \"Save solution to file \", filename);\n\n    netgen::GetVSSolution().SaveSolutionData (filename);\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_SetNextTimeStamp  (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argqc, tcl_const char *argv[])\n  {\n    if (mesh)\n      mesh -> SetNextTimeStamp();\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_LoadGeometry (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    tcl_const char * lgfilename = argv[1];\n\n#ifdef LOG_STREAM\n    (*logout) << \"Load geometry file: \" << lgfilename << endl;\n#endif\n\n#ifdef STAT_STREAM\n    (*statout) << lgfilename << \" & \" << endl;\n#endif\n\n\n    try\n      {\n\tfor (auto loader : GeometryRegister())\n\t  {\n\t    NetgenGeometry * hgeom = loader->Load (lgfilename);\n\t    if (hgeom)\n\t      {\n                // delete ng_geometry;\n\t\t// ng_geometry = hgeom;\n                ng_geometry = shared_ptr<NetgenGeometry> (hgeom);\n                loader->SetParameters(interp);\n\t\t\n\t\tmesh.reset();\n\t\treturn TCL_OK;\n\t      }\n\t  }\n\n\n\tifstream infile(lgfilename);\n\n\tif (strlen(lgfilename) < 4)\n\t  {\n\t    cout << \"ERROR: cannot recognise file format!\" << endl;\n\t  }\n\telse\n\t  {\n\t    if ((strcmp (&lgfilename[strlen(lgfilename)-4], \"iges\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-3], \"igs\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-3], \"IGS\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-4], \"IGES\") == 0))\n\t      {\n\t\tTcl_SetResult (interp, (char*)\"IGES import requires the OpenCascade geometry kernel. \"\n\t\t\t       \"Please install OpenCascade as described in the Netgen-website\",\n\t\t\t       TCL_STATIC);\n\t\treturn TCL_ERROR;\n\t      }\n\n\t    else if (strcmp (&lgfilename[strlen(lgfilename)-3], \"sat\") == 0)\n\t      {\n#ifdef ACIS\n\t\tPrintMessage (1, \"Load ACIS geometry file \", lgfilename);\n\t\tacisgeometry = netgen::LoadACIS_SAT (lgfilename);\n#endif\n\t      }\n\t    else if ((strcmp (&lgfilename[strlen(lgfilename)-4], \"step\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-3], \"stp\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-3], \"STP\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-4], \"STEP\") == 0))\n\t      {\n#ifdef ACISxxx\n\t\tPrintMessage (1, \"Load STEP geometry file \", lgfilename);\n\t\tacisgeometry = netgen::LoadACIS_STEP (lgfilename);\n#else\n\t\tTcl_SetResult (interp, (char*)\"IGES import requires the OpenCascade geometry kernel. \"\n\t\t\t       \"Please install OpenCascade as described in the Netgen-website\",\n\t\t\t       TCL_STATIC);\n\t\treturn TCL_ERROR;\n#endif\n\t      }\n\t    else if ((strcmp (&lgfilename[strlen(lgfilename)-4], \"brep\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-4], \"Brep\") == 0) ||\n\t\t     (strcmp (&lgfilename[strlen(lgfilename)-4], \"BREP\") == 0))\n\t      {\n\t\tTcl_SetResult (interp, (char*)\"BREP import requires the OpenCascade geometry kernel. \"\n\t\t\t       \"Please install OpenCascade as described in the Netgen-website\",\n\t\t\t       TCL_STATIC);\n\t\treturn TCL_ERROR;\n\t      }\n\t  }\n      }\n\n    catch (const NgException & e)\n      {\n\tTcl_SetResult (interp, const_cast<char*> (e.What().c_str()), TCL_VOLATILE);\n\treturn TCL_ERROR;\n      }\n\n    mesh.reset();\n    return TCL_OK;\n  }\n\n\n\n\n\n\n\n\n\n\n  int Ng_SaveGeometry (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (argc == 2)\n      {\n\tconst char * cfilename = argv[1];\n\n\ttry\n\t  {\n\t    ng_geometry -> Save (string (cfilename));\n\t  }\n\tcatch (const NgException & e)\n\t  {\n\t    Tcl_SetResult (interp, const_cast<char*> (e.What().c_str()), TCL_VOLATILE);\n\t    return TCL_ERROR;\n\t  }\n\n\tPrintMessage (1, \"Save geometry to file \", cfilename);\n\n\tif (strlen(cfilename) < 4) {cout << \"ERROR: can not recognise file format!!!\" << endl;}\n\telse\n\t  {\n#ifdef ACIS\n\t    if (acisgeometry)\n\t      {\n\t\tchar * filename = const_cast<char*> (argv[1]);\n\t\tif (strcmp (&filename[strlen(filename)-3], \"sat\") == 0)\n\t\t  {\n\t\t    acisgeometry -> SaveSATFile (filename);\n\t\t  }\n\t      }\n#endif\n\t    /*\n\t    if (strcmp (&cfilename[strlen(cfilename)-3], \"ngg\") == 0)\n\t      {\n\t\tCSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry);\n\t\tif (geometry)\n\t\t  {\n\t\t    ofstream of(cfilename);\n\t\t    geometry->Save (of);\n\t\t  }\n\t      }\n\t    */\n\t  }\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n\n\n\n\n\n  int Ng_ReadStatus (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[])\n  {\n    char buf[20], lstring[200];\n    static int prev_np = -1;\n    static int prev_ne = -1;\n    static int prev_nse = -1;\n    \n    if (mesh)\n      {\n        if (prev_np != mesh->GetNP())\n          {\n            snprintf (buf, size(buf),  \"%u\", unsigned(mesh->GetNP()));\n            Tcl_SetVar  (interp, \"::status_np\", buf, 0);\n            prev_np = mesh->GetNP();\n          }\n\n        if (prev_ne != mesh->GetNE())\n          {\n            snprintf (buf, size(buf),  \"%u\", unsigned(mesh->GetNE()));\n            Tcl_SetVar  (interp, \"::status_ne\", buf, 0);\n            prev_ne = mesh->GetNE();\n          }\n\n        if (prev_nse != mesh->GetNSE())\n          {\n            snprintf (buf, size(buf),  \"%u\", unsigned(mesh->GetNSE()));\n            Tcl_SetVar  (interp, \"::status_nse\", buf, 0);\n            prev_nse = mesh->GetNSE();\n          }\n        \n        auto tets_in_qualclass = mesh->GetQualityHistogram();\n        lstring[0] = 0;\n        for (int i = 0; i < tets_in_qualclass.Size(); i++)\n          {\n            snprintf (buf, size(buf),  \" %d\", tets_in_qualclass[i]);\n            strcat (lstring, buf);\n          }\n        for (int i = tets_in_qualclass.Size(); i < 20; i++)\n            strcat (lstring, \" 0\");\n        Tcl_SetVar  (interp, \"::status_tetqualclasses\", lstring, 0);\n      }\n    else\n      {\n        if (prev_np != 0)\n          {\n            Tcl_SetVar  (interp, \"::status_np\", \"0\", 0);\n            prev_np = 0;\n          }\n\n        if (prev_ne != 0)\n          {\n            Tcl_SetVar  (interp, \"::status_ne\", \"0\", 0);\n            prev_ne = 0;\n          }\n\n        if (prev_nse != 0)\n          {\n            Tcl_SetVar  (interp, \"::status_nse\", \"0\", 0);\n            prev_nse = 0;\n          }\n        Tcl_SetVar  (interp, \"::status_tetqualclasses\", \"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\", 0);\n      }\n\n    static string prev_working;\n    string working = multithread.running ? \"working\" : \"       \";\n    if (working != prev_working)\n      {\n        Tcl_SetVar (interp, \"::status_working\", working.c_str(), 0);\n        prev_working = working;\n      }\n\n    /*\n    if (multithread.running)\n      Tcl_SetVar (interp, \"::status_working\", \"working\", 0);\n    else\n      Tcl_SetVar (interp, \"::status_working\", \"       \", 0);\n    */\n    \n    static string prev_task;\n    if (prev_task != string(multithread.task))\n      {\n        prev_task = multithread.task;\n        Tcl_SetVar (interp, \"::status_task\", prev_task.c_str(), 0);\n      }\n\n    static double prev_percent = -1;\n    if (prev_percent != multithread.percent)\n      {\n        prev_percent = multithread.percent;\n        snprintf (buf, size(buf),  \"%lf\", prev_percent);\n        Tcl_SetVar  (interp, \"::status_percent\", buf, 0);\n      }\n        \n\n    {\n      lock_guard<mutex> guard(tcl_todo_mutex);\n      if (multithread.tcl_todo->length())\n        {\n          Tcl_Eval (interp, multithread.tcl_todo->c_str());\n          *multithread.tcl_todo = \"\";\n        }\n    }\n\n    return TCL_OK;\n  }\n\n\n  int Ng_MemInfo (ClientData clientData,\n\t\t  Tcl_Interp * interp,\n\t\t  int argc, tcl_const char *argv[])\n  {/*\n    if (argc < 2) return TCL_ERROR;\n\n    if (strcmp (argv[1], \"usedmb\") == 0)\n      { // returns string of 512 '0' or '1'\n\n\tstatic char usedmb[513];\n\tfor (int i = 0; i < 512; i++)\n\t  usedmb[i] = (i % 7 == 0) ? '1' : '0';\n\n\tusedmb[512] = 0;\n\tBaseDynamicMem::GetUsed (512, usedmb);\n\tTcl_SetResult (interp, usedmb, TCL_STATIC);\n\treturn TCL_OK;\n      }\n\t*/\n    return TCL_ERROR;\n  }\n\n\n\n  int Ng_BCProp (ClientData clientData,\n\t\t Tcl_Interp * interp,\n\t\t int argc, tcl_const char *argv[])\n  {\n    static char buf[100];\n\n    if (argc < 2)\n      {\n\tTcl_SetResult (interp, (char*)\"Ng_BCProp needs arguments\", TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    if (strcmp (argv[1], \"setbc\") == 0)\n      {\n\tint facenr = atoi (argv[2]);\n\tint bcnr = atoi (argv[3]);\n\tif (mesh && facenr >= 1 && facenr <= mesh->GetNFD())\n\t  mesh->GetFaceDescriptor (facenr).SetBCProperty (bcnr);\n      }\n\n    if (strcmp (argv[1], \"setall\") == 0)\n      {\n\tint bcnr = atoi (argv[2]);\n\tif (mesh)\n\t  {\n\t    int nfd = mesh->GetNFD();\n\t    for (int i = 1; i <= nfd; i++)\n\t      mesh->GetFaceDescriptor (i).SetBCProperty (bcnr);\n\t  }\n      }\n\n    if (strcmp (argv[1], \"getbc\") == 0)\n      {\n\tint facenr = atoi (argv[2]);\n\tif (mesh && facenr >= 1 && facenr <= mesh->GetNFD())\n\t  {\n\t    snprintf (buf, size(buf),  \"%d\", mesh->GetFaceDescriptor(facenr).BCProperty());\n\t  }\n\telse\n\t  {\n\t    strcpy (buf, \"0\");\n\t  }\n\tTcl_SetResult (interp, buf, TCL_STATIC);\n      }\n\n    if (strcmp (argv[1], \"getbcname\") == 0)\n      {\n\tint facenr = atoi (argv[2]);\n\tif (mesh && facenr >= 1 && facenr <= mesh->GetNFD())\n\t  {\n\t    snprintf (buf, size(buf),  \"%s\", mesh->GetFaceDescriptor(facenr).GetBCName().c_str());\n\t  }\n\telse\n\t  {\n\t    strcpy (buf, \"-\");\n\t  }\n\tTcl_SetResult (interp, buf, TCL_STATIC);\n      }\n\n\n    if (strcmp (argv[1], \"getactive\") == 0)\n      {\n\tsnprintf (buf, size(buf),  \"%d\", vsmesh.SelectedFace());\n\tTcl_SetResult (interp, buf, TCL_STATIC);\n      }\n\n    if (strcmp (argv[1], \"setactive\") == 0)\n      {\n\tint facenr = atoi (argv[2]);\n\tif (mesh && facenr >= 1 && facenr <= mesh->GetNFD())\n\t  {\n\t    vsmesh.SetSelectedFace (facenr);\n\t  }\n      }\n\n    if (strcmp (argv[1], \"getnfd\") == 0)\n      {\n\tif (mesh)\n\t  snprintf (buf, size(buf),  \"%d\", mesh->GetNFD());\n\telse\n\t  snprintf (buf, size(buf),  \"0\");\n\tTcl_SetResult (interp, buf, TCL_STATIC);\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n\n  int Ng_Refine  (ClientData clientData,\n\t\t  Tcl_Interp * interp,\n\t\t  int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n#ifdef ACIS\n    if (acisgeometry)\n      {\n\tACISRefinementSurfaces ref (*acisgeometry);\n\tACISMeshOptimize2dSurfaces opt(*acisgeometry);\n\tref.Set2dOptimizer(&opt);\n\tref.Refine (*mesh);\n      }\n    else\n#endif\n      {\n\t// ng_geometry -> GetRefinement().Refine(*mesh);\n        mesh->GetGeometry()->GetRefinement().Refine(*mesh);\n      }\n\n//redo second order refinement if desired\n    if (mparam.secondorder)\n      const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder(*mesh);\n\n    return TCL_OK;\n  }\n\n  int Ng_SecondOrder  (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    \n    const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder (*mesh);\n\n    return TCL_OK;\n  }\n\n\n  void * HighOrderDummy (void *)\n  {\n    //  mparam.elementorder = atoi (Tcl_GetVar (interp, \"options.elementorder\", 0));\n    const char * savetask = multithread.task;\n\n    Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n    mesh -> GetCurvedElements().BuildCurvedElements (&ref, mparam.elementorder);\n\n    multithread.task = savetask;\n    multithread.running = 0;\n    multithread.terminate = 1;\n\n    mesh -> SetNextMajorTimeStamp();\n    return 0;\n  }\n\n  int Ng_HighOrder  (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    multithread.running = 1;\n    multithread.terminate = 0;\n\n    mparam.elementorder = atoi(argv[1]);\n\n\n    HighOrderDummy(NULL);\n\n    return TCL_OK;\n  }\n\n\n\n  void * ValidateDummy (void *)\n  {\n    Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n    ref.ValidateSecondOrder (*mesh);\n\n    multithread.running = 0;\n    return NULL;\n  }\n\n\n\n  int Ng_ValidateSecondOrder  (ClientData clientData,\n\t\t\t       Tcl_Interp * interp,\n\t\t\t       int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    multithread.running = 1;\n    RunParallel (ValidateDummy, NULL);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_ZRefinement  (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    ZRefinementOptions opt;\n    opt.minref = 5;\n\n    if (argc >= 2) opt.minref = atoi (argv[1]);\n\n    ZRefinement (*mesh, ng_geometry.get(), opt);\n\n    return TCL_OK;\n  }\n\n  int Ng_HPRefinement  (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    int levels = atoi (argv[1]);\n\n\n    Refinement & ref = const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement());\n    HPRefinement (*mesh, &ref, levels);\n    return TCL_OK;\n  }\n\n\n  int Ng_LoadMeshSize  (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    mesh->LoadLocalMeshSize(argv[1]);\n    return TCL_OK;\n  }\n\n\n  int Ng_MeshSizeFromSurfaceMesh  (ClientData clientData,\n\t\t\t\t   Tcl_Interp * interp,\n\t\t\t\t   int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    mesh->SetGlobalH (mparam.maxh);\n    mesh->CalcLocalH(mparam.grading);\n\n    return TCL_OK;\n  }\n\n\n\n\n\n  // Philippose Rajan - 13 June 2009\n  // Added a new TCL function call for the generation \n  // of prismatic boundary layers\n  int Ng_GenerateBoundaryLayer (ClientData clientData,\n           Tcl_Interp * interp,\n           int argc, tcl_const char *argv[])\n  {\n     if (!mesh)\n     {\n        Tcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n        return TCL_ERROR;\n     }\n\n     if(multithread.running)\n     {\n        Tcl_SetResult(interp, err_jobrunning, TCL_STATIC);\n        return TCL_ERROR;\n     }\n\n\n\n\n     \n     cout << \"Generate Prismatic Boundary Layers (Experimental)....\" << endl;\n     \n     // Use an array to support creation of boundary \n     // layers for multiple surfaces in the future...\n     std::vector<int> surfid;\n     int surfinp = 0;\n     int prismlayers = 1;\n     double hfirst = 0.01;\n     double growthfactor = 1.0;\n\n     \n     while(surfinp >= 0)\n       {\n         cout << \"Enter Surface ID (-1 to end list): \";\n         cin >> surfinp;\n         if(surfinp >= 0) surfid.push_back(surfinp);\n      }\n\n     cout << \"Number of surfaces entered = \" << surfid.size() << endl; \n     cout << \"Selected surfaces are:\" << endl;\n     \n     for(auto i : Range(surfid.size()))\n       cout << \"Surface \" << i << \": \" << surfid[i] << endl;\n     \n     cout << endl << \"Enter number of prism layers: \";\n     cin >> prismlayers;\n     if(prismlayers < 1) prismlayers = 1;\n     \n     cout << \"Enter height of first layer: \";\n     cin >> hfirst;\n     if(hfirst <= 0.0) hfirst = 0.01;\n     \n     cout << \"Enter layer growth / shrink factor: \";\n     cin >> growthfactor;\n     if(growthfactor <= 0.0) growthfactor = 0.5;\n     \n     BoundaryLayerParameters blp;\n     blp.boundary = surfid;\n     std::vector<double> thickness;\n     for(auto i : Range(prismlayers))\n       {\n         auto layer = i+1;\n         if(growthfactor == 1)\n           thickness.push_back(layer * hfirst);\n         else\n           thickness.push_back(hfirst * (pow(growthfactor, (layer+1))-1)/(growthfactor-1));\n       }\n     blp.thickness = thickness;\n     GenerateBoundaryLayer (*mesh, blp);\n     return TCL_OK;\n  }\n\n\n  int Ng_InsertVirtualBL (ClientData clientData,\n\t\t\t  Tcl_Interp * interp,\n\t\t\t  int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    InsertVirtualBoundaryLayer (*mesh);\n    return TCL_OK;\n  }\n\n  int Ng_CutOffAndCombine (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    Mesh othermesh;\n    othermesh.Load (argv[1]);\n    othermesh.SetGlobalH (mparam.maxh);\n    othermesh.CalcLocalH(mparam.grading);\n\n    CutOffAndCombine (*mesh, othermesh);\n    return TCL_OK;\n  }\n\n\n  int Ng_HelmholtzMesh (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    HelmholtzMesh (*mesh);\n    return TCL_OK;\n  }\n\n\n\n\n  int Ng_SetMeshingParameters  (ClientData clientData,\n\t\t\t\tTcl_Interp * interp,\n\t\t\t\tint argc, tcl_const char *argv[])\n  {\n    mparam.maxh = atof (Tcl_GetVar (interp, \"::options.meshsize\", 0));\n    mparam.minh = atof (Tcl_GetVar (interp, \"::options.minmeshsize\", 0));\n\n    mparam.meshsizefilename = Tcl_GetVar (interp, \"::options.meshsizefilename\", 0);\n    // if (!strlen (mparam.meshsizefilename)) mparam.meshsizefilename = NULL;\n\n    mparam.curvaturesafety = atof (Tcl_GetVar (interp, \"::options.curvaturesafety\", 0));\n    mparam.segmentsperedge = atof (Tcl_GetVar (interp, \"::options.segmentsperedge\", 0));\n    mparam.badellimit = atof (Tcl_GetVar (interp, \"::options.badellimit\", 0));\n    mparam.secondorder = atoi (Tcl_GetVar (interp, \"::options.secondorder\", 0));\n    mparam.elementorder = atoi (Tcl_GetVar (interp, \"::options.elementorder\", 0));\n    mparam.quad = atoi (Tcl_GetVar (interp, \"::options.quad\", 0));\n    mparam.try_hexes = atoi (Tcl_GetVar (interp, \"::options.try_hexes\", 0));\n\n    mparam.inverttets = atoi (Tcl_GetVar (interp, \"::options.inverttets\", 0));\n    mparam.inverttrigs = atoi (Tcl_GetVar (interp, \"::options.inverttrigs\", 0));\n    mparam.uselocalh = atoi (Tcl_GetVar (interp, \"::options.localh\", 0));\n    mparam.grading = atof (Tcl_GetVar (interp, \"::options.grading\", 0));\n    mparam.delaunay = atoi (Tcl_GetVar (interp, \"::options.delaunay\", 0));\n    mparam.checkoverlap = atoi (Tcl_GetVar (interp, \"::options.checkoverlap\", 0));\n    mparam.checkoverlappingboundary = atoi (Tcl_GetVar (interp, \"::options.checkoverlappingboundary\", 0));\n    mparam.checkchartboundary = atoi (Tcl_GetVar (interp, \"::options.checkchartboundary\", 0));\n    mparam.optsteps3d = atoi (Tcl_GetVar (interp, \"::options.optsteps3d\", 0));\n    mparam.optsteps2d = atoi (Tcl_GetVar (interp, \"::options.optsteps2d\", 0));\n    mparam.opterrpow = atof (Tcl_GetVar (interp, \"::options.opterrpow\", 0));\n\n    mparam.parthread = atoi (Tcl_GetVar (interp, \"::options.parthread\", 0));\n    mparam.elsizeweight = atof (Tcl_GetVar (interp, \"::options.elsizeweight\", 0));\n\n    mparam.autozrefine = atoi (Tcl_GetVar (interp, \"::options.autozrefine\", 0));\n\n    // extern int printmessage_importance;\n    extern int printdots;\n    printmessage_importance = atoi (Tcl_GetVar (interp, \"::options.printmsg\", 0));\n    printdots = (printmessage_importance >= 4);\n\n    mparam.parallel_meshing = atoi (Tcl_GetVar (interp, \"::options.parallel_meshing\", 0));\n    mparam.nthreads = atoi (Tcl_GetVar (interp, \"::options.nthreads\", 0));\n    if(atoi(Tcl_GetVar (interp, \"::stloptions.resthcloseedgeenable\", 0)))\n      mparam.closeedgefac = atof(Tcl_GetVar (interp, \"::stloptions.resthcloseedgefac\", 0));\n    else\n      mparam.closeedgefac = {};\n\n    //BaseMoveableMem::totalsize = 0;\n    // 1048576 * atoi (Tcl_GetVar (interp, \"::options.memory\", 0));\n    if (mesh)\n      {\n\tmesh->SetGlobalH (mparam.maxh);\n\tmesh->SetMinimalH (mparam.minh);\n      }\n\n#ifdef PARALLELGL\n    MyMPI_SendCmd (\"bcastparthread\");\n    MyMPI_Bcast (mparam.parthread, MPI_COMM_WORLD);\n#endif\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_SetDebugParameters  (ClientData clientData,\n\t\t\t      Tcl_Interp * interp,\n\t\t\t      int argc, tcl_const char *argv[])\n  {\n    debugparam.slowchecks = atoi (Tcl_GetVar (interp, \"::debug.slowchecks\", 0));\n    debugparam.debugoutput = atoi (Tcl_GetVar (interp, \"::debug.debugoutput\", 0));\n    debugparam.haltexistingline = atoi (Tcl_GetVar (interp, \"::debug.haltexistingline\", 0));\n    debugparam.haltoverlap = atoi (Tcl_GetVar (interp, \"::debug.haltoverlap\", 0));\n    debugparam.haltsuccess = atoi (Tcl_GetVar (interp, \"::debug.haltsuccess\", 0));\n    debugparam.haltnosuccess = atoi (Tcl_GetVar (interp, \"::debug.haltnosuccess\", 0));\n    debugparam.haltlargequalclass = atoi (Tcl_GetVar (interp, \"::debug.haltlargequalclass\", 0));\n    debugparam.haltsegment = atoi (Tcl_GetVar (interp, \"::debug.haltsegment\", 0));\n    debugparam.haltnode = atoi (Tcl_GetVar (interp, \"::debug.haltnode\", 0));\n    debugparam.haltface = atoi (Tcl_GetVar (interp, \"::debug.haltface\", 0));\n    debugparam.haltsegmentp1 = atoi (Tcl_GetVar (interp, \"::debug.haltsegmentp1\", 0));\n    debugparam.haltsegmentp2 = atoi (Tcl_GetVar (interp, \"::debug.haltsegmentp2\", 0));\n    debugparam.haltfacenr = atoi (Tcl_GetVar (interp, \"::debug.haltfacenr\", 0));\n    return TCL_OK;\n  }\n\n\n\n  int Ng_SetCommandLineParameter  (ClientData clientData,\n\t\t\t\t   Tcl_Interp * interp,\n\t\t\t\t   int argc, tcl_const char *argv[])\n  {\n    if (argc != 2)\n      {\n\tTcl_SetResult (interp, (char*)\"Ng_SetCommandLineParameter needs 1 parameter\",\n                       TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    if (argv[1][0] == '-')\n      parameters.SetCommandLineFlag (argv[1]);\n    else\n      {\n        if (strstr(argv[1], \".py\"))\n          parameters.SetFlag (\"py\", argv[1]);\n        else\n          parameters.SetFlag (\"geofile\", argv[1]);\n      }\n    return TCL_OK;\n  }\n\n\n  int Ng_GetCommandLineParameter  (ClientData clientData,\n\t\t\t\t   Tcl_Interp * interp,\n\t\t\t\t   int argc, tcl_const char *argv[])\n  {\n    if (argc != 2)\n      {\n\tTcl_SetResult (interp, (char*)\"Ng_GetCommandLineParameter needs 1 parameter\",\n                       TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    static char buf[10];\n\n    if (parameters.StringFlagDefined (argv[1]))\n        Tcl_SetResult (interp,\n                       const_cast<char*>(parameters.GetStringFlag (argv[1], NULL).c_str()), TCL_VOLATILE);\n    else if (parameters.NumFlagDefined (argv[1]))\n      {\n\tsnprintf (buf, size(buf),  \"%lf\", parameters.GetNumFlag (argv[1], 0));\n\tTcl_SetResult (interp, buf, TCL_STATIC);\n      }\n    else if (parameters.GetDefineFlag (argv[1]))\n      Tcl_SetResult (interp, (char*)\"defined\", TCL_STATIC);\n    else\n      Tcl_SetResult (interp, (char*)\"undefined\", TCL_STATIC);\n\n    return TCL_OK;\n  }\n\n\n  static int perfstepsstart;\n  static int perfstepsend;\n\n  static char* optstring = NULL;\n  static char* optstringcsg = NULL;\n\n  void * MeshingDummy (void *)\n  {\n\n    const char * savetask = multithread.task;\n    multithread.task = \"Generate Mesh\";\n\n    ResetTime();\n\n\n    try\n      {\n\n#ifdef LOG_STREAM\n\t(*logout) << \"Start meshing\" << endl;\n\t(*logout) << \"Meshing parameters:\" << endl;\n\tmparam.Print (*logout);\n#endif\n\n#ifdef ACIS\n\tif (acisgeometry)\n\t  {\n\t    ACISGenerateMesh(*acisgeometry, mesh.Ptr(), perfstepsstart, perfstepsend, optstring);\n\t  }\n\telse\n#endif\n          if (ng_geometry)\n\t    {\n              if (perfstepsstart == 1)\n                {\n                  mesh = make_shared<Mesh> ();\n                  // vsmesh.SetMesh (mesh);\n                  SetGlobalMesh (mesh);\n                  mesh -> SetGeometry(ng_geometry);\n                }\n              if(!mesh)\n                throw Exception(\"Need existing global mesh\");\n              mparam.perfstepsstart = perfstepsstart;\n\t      mparam.perfstepsend = perfstepsend;\n              if(optstring)\n                mparam.optimize3d = *optstring;\n              int res = ng_geometry -> GenerateMesh (mesh, mparam);\n\n\t      if (res != MESHING3_OK) \n\t\t{\n\t\t  multithread.task = savetask;\n\t\t  multithread.running = 0;\n\t\t  return 0;\n\t\t}\n\t    }\n          else if (mesh)\n            {\n              if(perfstepsstart > 1 && perfstepsstart < 5)\n                throw Exception(\"Need geometry for surface mesh operations!\");\n              MeshVolume(mparam, *mesh);\n              OptimizeVolume(mparam, *mesh);\n              return 0;\n            }\n          else // no ng_geometry\n            {\n              multithread.task = savetask;\n              multithread.running = 0;\n              return 0;\n            }\n\n\n\n\tif (mparam.autozrefine)\n\t  {\n\t    ZRefinementOptions opt;\n\t    opt.minref = 5;\n\t    ZRefinement (*mesh, ng_geometry.get(), opt);\n\t    mesh -> SetNextMajorTimeStamp();\n\t  }\n\t\n\tif (mparam.secondorder)\n\t  {\n\t    const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder (*mesh);\n\t    mesh -> SetNextMajorTimeStamp();\n\t  }\n\n\tif (mparam.elementorder > 1)\n\t  {\n\t    mesh -> GetCurvedElements().BuildCurvedElements (&const_cast<Refinement&> (mesh->GetGeometry()->GetRefinement()),\n\t\t\t\t\t\t\t     mparam.elementorder);\n\n\t    mesh -> SetNextMajorTimeStamp();\n\t  }\n\n\n\tPrintMessage (1, \"Meshing done, time = \", GetTime(), \" sec\");\n      }\n\n    catch (const NgException & e)\n      {\n\tcout << e.What() << endl;\n      }\n\n    multithread.task = savetask;\n    multithread.running = 0;\n\n#ifdef OCCGEOMETRYorig\n    // currently not active\n    OCCGeometry * occgeometry = dynamic_cast<OCCGeometry*> (ng_geometry);\n    if (occgeometry && occgeometry->ErrorInSurfaceMeshing())\n      {\n\tchar script[] = \"rebuildoccdialog\";\n\tTcl_GlobalEval (tcl_interp, script);\n      }\n#endif\n    return NULL;\n  }\n\n  \n  int MeshingVal(tcl_const char* str)\n  {\n    if (strcmp(str, \"ag\") == 0) {return MESHCONST_ANALYSE;}\n    if (strcmp(str, \"me\") == 0) {return MESHCONST_MESHEDGES;}\n    if (strcmp(str, \"ms\") == 0) {return MESHCONST_MESHSURFACE;}\n    if (strcmp(str, \"os\") == 0) {return MESHCONST_OPTSURFACE;}\n    if (strcmp(str, \"mv\") == 0) {return MESHCONST_MESHVOLUME;}\n    if (strcmp(str, \"ov\") == 0) {return MESHCONST_OPTVOLUME;}\n\n    cout << \"TCL TK ERROR, wrong meshing value, return='\" << str << \"'\" << endl;\n    return 0;\n  }\n\n\n\n  int Ng_GenerateMesh  (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    multithread.running = 1;\n    multithread.terminate = 0;\n    \n    extern void Render(bool blocking);\n    mparam.render_function = &Render;\n\n    for (auto loader : GeometryRegister())\n      loader -> SetParameters (interp);\n\n\n    Ng_SetMeshingParameters (clientData, interp, 0, argv);\n\n    perfstepsstart = 1;\n    perfstepsend = 6;\n\n    if (optstringcsg) delete optstringcsg;\n    optstringcsg = NULL;\n    if (optstring) delete optstring;\n    optstring = NULL;\n\n    if (argc == 2)\n      {\n\tperfstepsstart = 1;\n\tperfstepsend = MeshingVal(argv[1]);\n      }\n    else if (argc == 3)\n      {\n\tperfstepsstart = MeshingVal(argv[1]);\n\tperfstepsend = MeshingVal(argv[2]);\n      }\n    else if (argc == 4)\n      {\n\tperfstepsstart = MeshingVal(argv[1]);\n\tperfstepsend = MeshingVal(argv[2]);\n\toptstring = new char[strlen(argv[3])+1];\n\tstrcpy(optstring, argv[3]);\n\toptstringcsg = new char[strlen(argv[3])+1];\n\tstrcpy(optstringcsg, argv[3]);\n      }\n\n    RunParallel (MeshingDummy, NULL);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_StopMeshing  (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    multithread.terminate = 1;\n    return TCL_OK;\n  }\n\n  int Ng_MeshInfo  (ClientData clientData,\n\t\t    Tcl_Interp * interp,\n\t\t    int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    ostringstream str;\n\n    if (argc >= 2 && strcmp (argv[1], \"dim\") == 0)\n      str << mesh->GetDimension();\n    else if (argc >= 2 && strcmp (argv[1], \"np\") == 0)\n      str << mesh->GetNP();\n    else if (argc >= 2 && strcmp (argv[1], \"ne\") == 0)\n      str << mesh->GetNE();\n    else if (argc >= 2 && strcmp (argv[1], \"nse\") == 0)\n      str << mesh->GetNSE();\n    else if (argc >= 2 && strcmp (argv[1], \"nseg\") == 0)\n      str << mesh->GetNSeg();\n    else if (argc >= 2 && strcmp (argv[1], \"bbox\") == 0)\n      {\n\tPoint3d pmin, pmax;\n\tmesh->GetBox (pmin, pmax);\n\tstr << pmin.X() << \" \" << pmax.X() << \" \"\n\t    << pmin.Y() << \" \" << pmax.Y() << \" \"\n\t    << pmin.Z() << \" \" << pmax.Z() << endl;\n      }\n    else\n      {\n\tcout << \"argv[1] = \" << argv[1] << endl;\n\tTcl_SetResult (interp, (char*)\"Ng_MeshInfo requires an argument out of \\n dim np ne\", TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    Tcl_SetResult  (interp, (char*)str.str().c_str(), TCL_VOLATILE);\n    return TCL_OK;\n  }\n\n  int Ng_MeshQuality  (ClientData clientData,\n\t\t       Tcl_Interp * interp,\n\t\t       int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    double angles[4];\n    char buf[10];\n\n    if (mesh)\n      mesh->CalcMinMaxAngle(mparam.badellimit, angles);\n    else\n      {\n\tangles[0] = angles[1] = angles[2] = angles[3] = 0;\n      }\n    snprintf (buf, size(buf),  \"%5.1lf\", angles[0]);\n    Tcl_SetVar (interp, argv[1], buf, 0);\n    snprintf (buf, size(buf),  \"%5.1lf\", angles[1]);\n    Tcl_SetVar (interp, argv[2], buf, 0);\n    snprintf (buf, size(buf),  \"%5.1lf\", angles[2]);\n    Tcl_SetVar (interp, argv[3], buf, 0);\n    snprintf (buf, size(buf),  \"%5.1lf\", angles[3]);\n    Tcl_SetVar (interp, argv[4], buf, 0);\n\n    return TCL_OK;\n  }\n\n  int Ng_CheckSurfaceMesh  (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    mesh->FindOpenElements();\n    if (mesh->CheckConsistentBoundary())\n      {\n\tPrintMessage (1, \"surface mesh not consistent, trying orientation\");\n\tmesh->SurfaceMeshOrientation();\n      }\n    else\n      {\n\tPrintMessage (1, \"surface mesh consistent\");\n      }\n\n    mesh->CheckOverlappingBoundary();\n    return TCL_OK;\n  }\n\n  int Ng_CheckVolumeMesh  (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    mesh->CheckVolumeMesh();\n    return TCL_OK;\n  }\n\n\n  int Ng_DeleteVolMesh  (ClientData clientData,\n\t\t\t Tcl_Interp * interp,\n\t\t\t int argc, tcl_const char *argv[])\n  {\n    if (mesh)\n      mesh->ClearVolumeElements();\n\n    return TCL_OK;\n  }\n\n\n  int Ng_SplitSeparatedFaces (ClientData clientData,\n\t\t\t      Tcl_Interp * interp,\n\t\t\t      int argc, tcl_const char *argv[])\n  {\n    if (mesh)\n      mesh->SplitSeparatedFaces ();\n    return TCL_OK;\n  }\n\n\n\n  int Ng_RestrictH  (ClientData clientData,\n\t\t     Tcl_Interp * interp,\n\t\t     int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    if (argc != 3)\n      return TCL_OK;\n    if (!mesh)\n      return TCL_OK;\n\n\n    double loch = atof (argv[2]);\n    if (strcmp (argv[1], \"face\") == 0)\n      {\n\tcout << \"Restrict h at face to \" << loch << endl;\n\tmesh -> RestrictLocalH  (RESTRICTH_FACE, vsmesh.SelectedFace(), loch);\n      }\n    if (strcmp (argv[1], \"edge\") == 0)\n      {\n\tcout << \"Restrict h at edge to \" << loch << endl;\n\tmesh -> RestrictLocalH  (RESTRICTH_EDGE, vsmesh.SelectedEdge(), loch);\n      }\n    if (strcmp (argv[1], \"point\") == 0)\n      {\n\tcout << \"Restrict h at point to \" << loch << endl;\n\tmesh -> RestrictLocalH  (RESTRICTH_POINT, vsmesh.SelectedPoint(), loch);\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n\n  int Ng_Anisotropy  (ClientData clientData,\n\t\t      Tcl_Interp * interp,\n\t\t      int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    if (argc != 2)\n      return TCL_OK;\n    if (!mesh)\n      return TCL_OK;\n\n    if (strcmp (argv[1], \"edge\") == 0)\n      {\n\tint edgenr = vsmesh.SelectedEdge();\n\tfor (int i = 1; i <= mesh->GetNSeg(); i++)\n\t  {\n\t    Segment & seg = mesh->LineSegment(i);\n\t    if (seg.edgenr == edgenr)\n\t      {\n\t\tseg.singedge_left = 1 - seg.singedge_left;\n\t\tseg.singedge_right = 1 - seg.singedge_right;\n\t      }\n\t  }\n      }\n\n    return TCL_OK;\n  }\n\n\n\n\n  BisectionOptions biopt;\n\n  void * BisectDummy (void *)\n  {\n    const Refinement & ref = mesh->GetGeometry()->GetRefinement();\n    MeshOptimize2d * opt = NULL;\n\n    /*\n#ifdef ACIS\n    if (acisgeometry)\n      {\n\t// ref = new ACISRefinementSurfaces(*acisgeometry);\n\topt = new ACISMeshOptimize2dSurfaces(*acisgeometry);\n\tref->Set2dOptimizer(opt);\n      }\n#endif\n    else\n      {\n\tref = new RefinementSurfaces(*geometry);\n\topt = new MeshOptimize2dSurfaces(*geometry);\n\tref->Set2dOptimizer(opt);\n      }\n    */\n\n    if(!mesh->LocalHFunctionGenerated())\n      mesh->CalcLocalH(mparam.grading);\n\n    mesh->LocalHFunction().SetGrading (mparam.grading);\n    ref . Bisect (*mesh, biopt);\n    mesh -> UpdateTopology();\n    mesh -> GetCurvedElements().BuildCurvedElements (&ref, mparam.elementorder);\n\n    multithread.running = 0;\n\n    delete opt;\n    return NULL;\n  }\n\n\n  int Ng_Bisect  (ClientData clientData,\n\t\t  Tcl_Interp * interp,\n\t\t  int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n\n    if (multithread.running)\n      {\n\tcout << \"Thread alrad running\" << endl;\n\treturn TCL_OK;\n      }\n    multithread.running = 1;\n\n    biopt.outfilename = NULL; // \"ngfepp.vol\";\n    biopt.femcode = \"fepp\";\n    biopt.refinementfilename = NULL;\n\n    if (argc >= 2)\n      biopt.refinementfilename = argv[1];\n\n\n    BisectDummy (0);\n\n    /*\n      extern void BisectTets (Mesh &, const CSGeometry *);\n      BisectTets (*mesh, geometry);\n    */\n    return TCL_OK;\n  }\n\n\n\n  //   int Ng_BisectCopyMesh  (ClientData clientData,\n  // \t\t\t  Tcl_Interp * interp,\n  // \t\t\t  int argc, tcl_const char *argv[])\n  //   {\n  //     if (!mesh)\n  //       {\n  // \tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n  // \treturn TCL_ERROR;\n  //       }\n  //     if (multithread.running)\n  //       {\n  // \tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n  // \treturn TCL_ERROR;\n  //       }\n\n  //     BisectTetsCopyMesh (*mesh, geometry.Ptr(), biopt);\n  //     return TCL_OK;\n  //   }\n\n\n\n\n\n\n  int Ng_Split2Tets  (ClientData clientData,\n\t\t      Tcl_Interp * interp,\n\t\t      int argc, tcl_const char *argv[])\n  {\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n    if (multithread.running)\n      {\n\tTcl_SetResult (interp, err_jobrunning, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    mesh->Split2Tets ();\n\n    return TCL_OK;\n  }\n\n\n\n\n\n\n\n\n  extern int Ng_MeshDoctor (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argc, tcl_const char *argv[]);\n\n\n\n\n\n\n\n  SymbolTable<VisualScene*> & GetVisualizationScenes ()\n  {\n    static SymbolTable<VisualScene*> vss;\n    return vss;\n  }\n\n  void AddVisualizationScene (const string & name,\n\t\t\t      VisualScene * avs)\n  {\n    GetVisualizationScenes().Set (name.c_str(), avs);\n  }\n\n\n  void SetVisualScene (Tcl_Interp * interp)\n  {\n    const char * vismode = vispar.selectvisual;\n    // Tcl_GetVar (interp, \"selectvisual\", 0);\n    VisualScene *& vs = visual_scene;\n    vs = &visual_scene_cross;\n    if (GetVisualizationScenes().Used(vismode))\n      {\n\tvs = GetVisualizationScenes()[vismode];\n      }\n    else if (vismode)\n      {\n\tif (strcmp (vismode, \"geometry\") == 0)\n\t  {\n\t    for (auto loader : GeometryRegister())\n\t      {\n\t\tVisualScene * hvs = loader->GetVisualScene (ng_geometry.get());\n\t\tif (hvs)\n\t\t  {\n\t\t    vs = hvs;\n\t\t    return;\n\t\t  }\n\t      }\n\n#ifdef ACIS\n\t    else if (acisgeometry)\n\t      vs = &vsacisgeom;\n#endif // ACIS\n\t  }\n\t\n\tif (strcmp (vismode, \"mesh\") == 0)\n\t  {\n\t    if (!meshdoctor.active)\n\t      vs = &vsmesh;\n\t    else\n\t      vs = &vsmeshdoc;\n\t  }\n\n\tif (strcmp (vismode, \"surfmeshing\") == 0) vs = &vssurfacemeshing;\n\tif (strcmp (vismode, \"specpoints\") == 0) vs = &vsspecpoints;\n        if (strcmp (vismode, \"solution\") == 0) vs = &netgen::GetVSSolution();\n      }\n  }\n\n\n\n  Font * font = nullptr;\n  Togl * togl = NULL;\n\n  void MyOpenGLText_GUI (const char * text)\n  {\n    glListBase (font->getDisplayListsBase());\n    glCallLists (GLsizei(strlen(text)), GL_UNSIGNED_BYTE, text);\n  }\n\n  static int\n  Ng_ToglVersion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n  {\n    Tcl_SetResult (interp,  (char*)\"2\", TCL_STATIC);\n    return TCL_OK;\n  }\n  \n  static int\n  init(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n  {\n    // cout << \"call init\" << endl;\n\n\n    if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) \n      return TCL_ERROR;\n\n    // possible values: 12,14,16,18,20,22,24,28,32\n    font = selectFont(18);\n\n    LoadOpenGLFunctionPointers();\n\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    glMatrixMode(GL_MODELVIEW);\n\n    SetVisualScene (Togl_Interp(togl));\n    visual_scene->DrawScene();\n    Set_OpenGLText_Callback (&MyOpenGLText_GUI, font->Width());\n    return TCL_OK;\n  }\n\n  static int\n  zap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n  {\n    return TCL_OK;\n  }\n\n\n  static int\n  draw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n  {\n    SetVisualScene (interp);\n\n    glPushMatrix();\n\n    glLoadIdentity();\n    visual_scene->DrawScene();\n    Togl_SwapBuffers(togl);\n\n    glPopMatrix();\n\n    return TCL_OK;\n  }\n\n  static int\n  reshape(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)\n  {\n    int w = Togl_Width (togl);\n    int h = Togl_Height (togl);\n\n    // glViewport(0, 0, w, h);\n    int res[4];\n    glGetIntegerv(GL_VIEWPORT, res);\n    // cout << \"w = \" << w << \" h = \" << h << endl;\n    w = res[2];\n    h = res[3];\n    /*\n    cout << \"viewport: \"\n         << res[0] << \" \"\n         << res[1] << \" \"\n         << res[2] << \" \"\n         << res[3] << endl;\n    */\n    // change font size according to window width\n    font = selectFont(w/80);\n\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n\n    // OpenGL near and far clipping planes\n    double pnear = 0.1;\n    double pfar = 10;\n\n    gluPerspective(20.0f, double(w) / h, pnear, pfar);\n    glMatrixMode(GL_MODELVIEW);\n\n    return TCL_OK;\n  }\n\n  static int Ng_SnapShot(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv)\n  {\n    struct Togl *togl;\n    if (Togl_GetToglFromObj(interp, argv[1], &togl) != TCL_OK) \n      return TCL_ERROR;\n    const char * filename = Tcl_GetString(argv[2]);\n\n    int w = Togl_PixelScale(togl)*Togl_Width (togl);\n    int h = Togl_PixelScale(togl)*Togl_Height (togl);\n\n    NgArray<unsigned char> buffer(w*h*3);\n    glPixelStorei(GL_UNPACK_ALIGNMENT,1);\n    glPixelStorei(GL_PACK_ALIGNMENT,1);\n    glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &buffer[0]);\n\n#ifdef JPEGLIB\n    int len = strlen(filename);\n    if (strcmp (\"jpg\", filename+len-3) == 0)\n      {\n        cout << \"Snapshot to file '\" << filename << \"'\" << endl;\n\n        struct jpeg_compress_struct cinfo;\n        struct jpeg_error_mgr jerr;\n        FILE *outfile = fopen(filename,\"wb\");\n        JSAMPROW row_pointer[1];\n        int row_stride, quality = 100; // 1...100\n\n        cinfo.err = jpeg_std_error( &jerr );\n        jpeg_create_compress( &cinfo );\n        jpeg_stdio_dest( &cinfo, outfile );\n\n\n        cinfo.image_width = w;\n        cinfo.image_height = h;\n        cinfo.input_components = 3;\n        cinfo.in_color_space = JCS_RGB;\n\n        jpeg_set_defaults( &cinfo );\n        jpeg_set_quality( &cinfo, quality, FALSE );   // TRUE\n        jpeg_start_compress( &cinfo, TRUE );\n\n        row_stride = 3*w;\n        while( cinfo.next_scanline < cinfo.image_height ) {\n          row_pointer[0] = &buffer[ (h-1-cinfo.next_scanline) * row_stride ];\n          (void)jpeg_write_scanlines( &cinfo, row_pointer, 1 );\n        }\n\n        jpeg_finish_compress( &cinfo );\n        fclose( outfile );\n\n        jpeg_destroy_compress( &cinfo );\n        fprintf( stdout, \"done [ok]\\n\" );\n        fflush( stdout );\n\n        return TCL_OK;\n      }\n#endif // JPEGLIB\n    {\n        string command;\n        std::filesystem::path filepath(filename);\n\n        bool need_conversion = filepath.extension() != \".ppm\";\n        if (need_conversion)\n          filepath += \".ppm\";\n\n        cout << IM(3) << \"Snapshot to file '\" << filepath.string() << endl;\n\n        ofstream outfile(filepath);\n        outfile << \"P6\" << endl\n          << \"# CREATOR: Netgen\" << endl\n          << w << \" \" << h << endl\n          << \"255\" << endl;\n        for (int i = 0; i < h; i++)\n            for (int j = 0; j < w; j++)\n                for (int k = 0; k < 3; k++)\n                    outfile.put (buffer[k+3*j+3*w*(h-i-1)]);\n        outfile << flush;\n\n        if (need_conversion)\n        {\n          // convert image file (Unix/Linux only):\n          command = string(\"convert -quality 100 \") + filepath.string() + \" \" + filename;\n\n          int err = system(command.c_str());\n          if (err != 0)\n          {\n              Tcl_SetResult (Togl_Interp(togl), (char*)\"Cannot convert image file, stored as .ppm\", TCL_VOLATILE);\n              return TCL_ERROR;\n          }\n\n          std::filesystem::remove(filepath);\n        }\n\n        return TCL_OK;\n    }\n  }\n\n\n\n#ifdef FFMPEG\n  static int Ng_VideoClip(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv)\n    {\n      static Mpeg mpeg;\n      struct Togl *togl;\n    if (Togl_GetToglFromObj(interp, argv[1], &togl) != TCL_OK) \n      return TCL_ERROR;\n\n    if (strcmp (Tcl_GetString(argv[2]), \"init\") == 0)\n      {\n        // Can't initialize when running:\n        //-------------------------------\n        if( mpeg.IsStarted() )  {\n          cout << \"cannot initialize: already running\" << endl;\n          return TCL_ERROR;\n        }\n\n        const char * filename = Tcl_GetString(argv[3]);\n        mpeg.Start(filename);\n\n        return TCL_OK;\n      }\n\n\n\n    else if (strcmp (Tcl_GetString(argv[2]), \"addframe\") == 0)\n      {\n        if(mpeg.AddFrame())\n          return TCL_ERROR;\n      }\n\n\n\n    else if (strcmp (Tcl_GetString(argv[2]), \"finalize\") == 0)\n      {\n        mpeg.Stop();\n      }\n    return TCL_OK;\n  }\n\n#else // FFMPEG\n  static int Ng_VideoClip(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv)\n  {\n    Tcl_SetResult (Togl_Interp(togl), (char*)\"Video not available, Netgen was not compiled with FFMPEG library\", TCL_STATIC);\n    return TCL_ERROR;\n  }\n#endif // FFMPEG\n\n\n\n\n\n\n\n  int Ng_MouseMove (ClientData clientData,\n\t\t    Tcl_Interp * interp,\n\t\t    int argc, tcl_const char *argv[])\n  {\n    int oldx, oldy;\n    int newx, newy;\n\n    oldx = atoi (argv[1]);\n    oldy = atoi (argv[2]);\n    newx = atoi (argv[3]);\n    newy = atoi (argv[4]);\n\n    SetVisualScene(interp);\n    visual_scene->MouseMove (oldx, oldy, newx, newy, argv[5][0]);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_MouseDblClick (ClientData clientData,\n\t\t\tTcl_Interp * interp,\n\t\t\tint argc, tcl_const char *argv[])\n  {\n    int px = Togl_PixelScale(togl)*atoi (argv[1]);\n    int py = Togl_PixelScale(togl)*atoi (argv[2]);\n\n    SetVisualScene(interp);\n    visual_scene->MouseDblClick (px, py);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_ZoomAll (ClientData clientData,\n\t\t  Tcl_Interp * interp,\n\t\t  int argc, tcl_const char *argv[])\n  {\n    SetVisualScene(interp);\n    visual_scene->BuildScene (1);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_Center (ClientData clientData,\n\t\t Tcl_Interp * interp,\n\t\t int argc, tcl_const char *argv[])\n  {\n    SetVisualScene(interp);\n    visual_scene->BuildScene (2);\n\n    return TCL_OK;\n  }\n\n\n  int Ng_StandardRotation (ClientData clientData,\n\t\t\t   Tcl_Interp * interp,\n\t\t\t   int argc, tcl_const char *argv[])\n  {\n    SetVisualScene(interp);\n    visual_scene->StandardRotation (argv[1]);\n\n    return TCL_OK;\n  }\n\n  int Ng_ArbitraryRotation (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argc, tcl_const char *argv[])\n  {\n    SetVisualScene(interp);\n    NgArray<double> alpha;\n    NgArray<Vec3d> vec;\n\n    for(int i=1; i<argc; i+=4)\n      {\n\talpha.Append(atof(argv[i]));\n\tvec.Append(Vec3d(atof(argv[i+1]),atof(argv[i+2]),atof(argv[i+3])));\n      }\n\n    visual_scene->ArbitraryRotation (alpha,vec);\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_Metis (ClientData clientData,\n\t\tTcl_Interp * interp,\n\t\tint argc, tcl_const char *argv[])\n  {\n#ifdef PARALLEL\n    if (!mesh)\n      {\n\tTcl_SetResult (interp, err_needsmesh, TCL_STATIC);\n\treturn TCL_ERROR;\n      }\n\n    int nparts = atoi (argv[1]);\n    ntasks = nparts+1;\n    cout << \"calling metis ... \" << flush;\n    mesh->ParallelMetis(ntasks);\n    cout << \"done\" << endl;\n    ntasks = 1;\n\n    // for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++)\n    // (*mesh)[ei].SetIndex ( (*mesh)[ei].GetPartition() );\n\n    return TCL_OK;\n\n#else\n    Tcl_SetResult (interp, (char*)\"metis not available\", TCL_STATIC);\n    return TCL_ERROR;\n    \n#endif\n\n\n\n#ifdef OLDOLD\n    // METIS Partitioning\n\n    if (mesh->GetDimension() == 3)\n      {\n\tusing namespace metis;\n\n\tint ne = mesh->GetNE();\n\tif (ne < 3)\n\t  {\n\t    Tcl_SetResult (interp, \"This operation needs a volume mesh\", TCL_STATIC);\n\t    return TCL_ERROR;\n\t  }\n\n\tint nn = mesh->GetNP();\n\n\tELEMENT_TYPE elementtype = mesh->VolumeElement(1).GetType();\n\tint npe = mesh->VolumeElement(1).GetNP();\n\n\tfor (int i = 2; i<=ne; i++)\n\t  if (mesh->VolumeElement(i).GetType() != elementtype)\n\t    {\n\t      Tcl_SetResult (interp, \"Works in 3D only uniformal tet or hex meshes\", TCL_STATIC);\n\t      return TCL_ERROR;\n\t    }\n\n\tidxtype *elmnts;\n\telmnts = new idxtype[ne*npe];\n\n\tint etype;\n\tif (elementtype == TET)\n\t  etype = 2;\n\telse if (elementtype == HEX)\n\t  etype = 3;\n\telse\n\t  {\n\t    Tcl_SetResult (interp, \"Works in 3D only uniformal tet or hex meshes\", TCL_STATIC);\n\t    return TCL_ERROR;\n\t  }\n\n\tfor (int i=1; i<=ne; i++)\n\t  for (int j=1; j<=npe; j++)\n\t    elmnts[(i-1)*npe+(j-1)] = mesh->VolumeElement(i).PNum(j)-1;\n\n\n\tint numflag = 0;\n\tint nparts = atoi (argv[1]);\n\tint edgecut;\n\tidxtype *epart, *npart;\n\tepart = new idxtype[ne];\n\tnpart = new idxtype[nn];\n\n\tcout << \"Starting Metis (\" << ne << \" Elements, \" << nn << \" Nodes, \" << nparts << \" Partitions) ... \" << flush;\n\n\tMETIS_PartMeshNodal (&ne, &nn, elmnts, &etype, &numflag, &nparts,\n\t\t\t     &edgecut, epart, npart);\n\n\tcout << \"done\" << endl;\n\n\tcout << \"edge-cut: \" << edgecut << \", balance: \" << ComputeElementBalance(ne, nparts, epart) << endl;\n\n\tfor (int i=1; i<=ne; i++)\n\t  mesh->VolumeElement(i).SetPartition(epart[i-1]);\n\n\tmesh->SetNextTimeStamp();\n      }\n\n\n#endif\n    return TCL_OK;\n  }\n\n\n\n\n\n  void SelectFaceInOCCDialogTree (int facenr)\n  {\n    char script[50];\n    snprintf (script, size(script), \"selectentity {Face %i}\", facenr);\n    Tcl_GlobalEval (tcl_interp, script);\n  }\n\n\n\n\n\n#ifndef ACIS\n  int Ng_ACISCommand (ClientData clientData,\n\t\t      Tcl_Interp * interp,\n\t\t      int argc, tcl_const char *argv[])\n  {\n    if (argc >= 2)\n      {\n\tif (strcmp (argv[1], \"isACISavailable\") == 0)\n\t  {\n            Tcl_SetResult (interp, (char*)\"no\", TCL_STATIC);\n\t    return TCL_OK;\n\t  }\n      }\n    Tcl_SetResult (interp, (char*)\"undefined ACiS command\", TCL_STATIC);\n    return TCL_ERROR;\n  }\n#endif\n\n\n  // from ng_interface\n  void Ng_SetVisualizationParameter (const char * name, const char * value)\n  {\n    // #ifdef OPENGL\n    // #ifndef NOTCL\n    char buf[100];\n    snprintf (buf, size(buf),  \"visoptions.%s\", name);\n    if (printmessage_importance>0)\n      {\n\tcout << \"name = \" << name << \", value = \" << value << endl;\n\tcout << \"set tcl-variable \" << buf << \" to \" << value << endl;\n      }\n    Tcl_SetVar (tcl_interp, buf, const_cast<char*> (value), 0);\n    Tcl_Eval (tcl_interp, \"Ng_Vis_Set parameters;\");\n    // #endif\n    // #endif\n  }\n}\n\n\nusing namespace netgen;\n\nvoid Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler)\n{\n  vsmesh.SetMouseEventHandler (handler);\n}\n\nvoid Ng_SetUserVisualizationObject (netgen::UserVisualizationObject * vis)\n{\n  netgen::GetVSSolution().AddUserVisualizationObject (vis);\n}\n\n\n\n\nnamespace netgen\n{\n\n\nint firsttime = 1;\nint animcnt = 0;\nvoid PlayAnimFile(const char* name, int speed, int maxcnt)\n{\n  //extern Mesh * mesh;\n\n  /*\n    if (mesh) mesh->DeleteMesh();\n    if (!mesh) mesh = new Mesh();\n  */\n  mesh = make_shared<Mesh>();\n\n  int ne, np, i;\n\n  char str[80];\n  char str2[80];\n\n  //int tend = 5000;\n  //  for (ti = 1; ti <= tend; ti++)\n  //{\n  int rti = (animcnt%(maxcnt-1)) + 1;\n  animcnt+=speed;\n  \n  snprintf(str2, sizeof(str2), \"%05i.sol\",rti);\n  strcpy(str,\"mbssol/\");\n  strcat(str,name);\n  strcat(str,str2);\n\n  if (printmessage_importance>0)\n    cout << \"read file '\" << str << \"'\" << endl;\n  \n  ifstream infile(str);\n  infile >> ne;\n  for (i = 1; i <= ne; i++)\n    {\n      int j;\n      Element2d tri(TRIG);\n      tri.SetIndex(1); //faceind\n      \n      for (j = 1; j <= 3; j++)\n\tinfile >> tri.PNum(j);\n\n      infile >> np;\n      for (i = 1; i <= np; i++)\n\t{\n\t  Point3d p;\n\t  infile >> p.X() >> p.Y() >> p.Z();\n\t  if (firsttime)\n\t    mesh->AddPoint (p);\n\t  else\n\t    mesh->Point(i) = Point<3> (p);\n\t}\n\n      //firsttime = 0;\n      Ng_Redraw();\n    }\n}\n\n\n\n\n  int Ng_SetVisParameters  (ClientData clientData,\n\t\t\t    Tcl_Interp * interp,\n\t\t\t    int argc, tcl_const char *argv[])\n  {\n    if (!Tcl_GetVar (interp, \"::viewoptions.light.amb\", TCL_GLOBAL_ONLY))\n      return TCL_ERROR;\n\n    vispar.lightamb = atof (Tcl_GetVar (interp, \"::viewoptions.light.amb\", TCL_GLOBAL_ONLY));\n    vispar.lightdiff = atof (Tcl_GetVar (interp, \"::viewoptions.light.diff\", TCL_GLOBAL_ONLY));\n    vispar.lightspec = atof (Tcl_GetVar (interp, \"::viewoptions.light.spec\", TCL_GLOBAL_ONLY));\n    vispar.shininess = atof (Tcl_GetVar (interp, \"::viewoptions.mat.shininess\", TCL_GLOBAL_ONLY));\n    vispar.locviewer = atoi (Tcl_GetVar (interp, \"::viewoptions.light.locviewer\", TCL_GLOBAL_ONLY));\n    vispar.transp = atof (Tcl_GetVar (interp, \"::viewoptions.mat.transp\", TCL_GLOBAL_ONLY));\n    \n    VisualizationParameters::Clipping hclip;\n    hclip.normal.X() = atof (Tcl_GetVar (interp, \"::viewoptions.clipping.nx\", TCL_GLOBAL_ONLY));\n    hclip.normal.Y() = atof (Tcl_GetVar (interp, \"::viewoptions.clipping.ny\", TCL_GLOBAL_ONLY));\n    hclip.normal.Z() = atof (Tcl_GetVar (interp, \"::viewoptions.clipping.nz\", TCL_GLOBAL_ONLY));\n    hclip.dist = atof (Tcl_GetVar (interp, \"::viewoptions.clipping.dist\", TCL_GLOBAL_ONLY));\n    hclip.dist2 = atof (Tcl_GetVar (interp, \"::viewoptions.clipping.dist2\", TCL_GLOBAL_ONLY));\n    hclip.enable = atoi (Tcl_GetVar (interp, \"::viewoptions.clipping.enable\", TCL_GLOBAL_ONLY));\n    vispar.clipdomain =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.clipping.onlydomain\", TCL_GLOBAL_ONLY));\n    vispar.donotclipdomain =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.clipping.notdomain\", TCL_GLOBAL_ONLY));\n\n    if ( ! (hclip == vispar.clipping) )\n      {\n\tvispar.clipping = hclip;\n\tvispar.clipping.timestamp = NextTimeStamp();\n      }\n\n    vispar.whitebackground = atoi (Tcl_GetVar (interp, \"::viewoptions.whitebackground\", TCL_GLOBAL_ONLY));\n    vispar.drawcoordinatecross = atoi (Tcl_GetVar (interp, \"::viewoptions.drawcoordinatecross\", TCL_GLOBAL_ONLY));\n    vispar.drawcolorbar = atoi (Tcl_GetVar (interp, \"::viewoptions.drawcolorbar\", TCL_GLOBAL_ONLY));\n    vispar.drawnetgenlogo = atoi (Tcl_GetVar (interp, \"::viewoptions.drawnetgenlogo\", TCL_GLOBAL_ONLY));\n    vispar.stereo = atoi (Tcl_GetVar (interp, \"::viewoptions.stereo\", TCL_GLOBAL_ONLY));\n    vispar.colormeshsize = atoi (Tcl_GetVar (interp, \"::viewoptions.colormeshsize\", TCL_GLOBAL_ONLY));\n    VisualScene :: SetBackGroundColor (vispar.whitebackground ? 1 : 0);\n\n    strcpy (vispar.selectvisual, Tcl_GetVar (interp, \"::selectvisual\", TCL_GLOBAL_ONLY));\n\n    //  vispar.showstltrias = atoi (Tcl_GetVar (interp, \"::viewoptions.stl.showtrias\", TCL_GLOBAL_ONLY));\n\n    vispar.stlshowtrias =\n      atoi (Tcl_GetVar (interp, \"::stloptions.showtrias\", TCL_GLOBAL_ONLY));\n    vispar.stlshowfilledtrias =\n      atoi (Tcl_GetVar (interp, \"::stloptions.showfilledtrias\", TCL_GLOBAL_ONLY));\n    vispar.stlshowedges =\n      atoi (Tcl_GetVar (interp, \"::stloptions.showedges\", TCL_GLOBAL_ONLY));\n    vispar.stlshowmarktrias =\n      atoi (Tcl_GetVar (interp, \"::stloptions.showmarktrias\", TCL_GLOBAL_ONLY));\n    vispar.stlshowactivechart =\n      atoi (Tcl_GetVar (interp, \"::stloptions.showactivechart\", TCL_GLOBAL_ONLY));\n    vispar.stlchartnumber =\n      atoi (Tcl_GetVar (interp, \"::stloptions.chartnumber\", TCL_GLOBAL_ONLY));\n    vispar.stlchartnumberoffset =\n      atoi (Tcl_GetVar (interp, \"::stloptions.chartnumberoffset\", TCL_GLOBAL_ONLY));\n\n    vispar.occshowsurfaces =\n      atoi (Tcl_GetVar (interp, \"::occoptions.showsurfaces\", TCL_GLOBAL_ONLY));\n    vispar.occshowedges =\n      atoi (Tcl_GetVar (interp, \"::occoptions.showedges\", TCL_GLOBAL_ONLY));\n\n    vispar.drawoutline =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawoutline\", TCL_GLOBAL_ONLY));\n    vispar.drawfilledtrigs =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawfilledtrigs\", TCL_GLOBAL_ONLY));\n    vispar.subdivisions =\n      atoi (Tcl_GetVar (interp, \"::visoptions.subdivisions\", TCL_GLOBAL_ONLY));\n    vispar.drawbadels =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawbadels\", TCL_GLOBAL_ONLY));\n    vispar.drawedges =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawedges\", TCL_GLOBAL_ONLY));\n\n    vispar.drawtetsdomain =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawtetsdomain\", TCL_GLOBAL_ONLY));\n    vispar.drawtets =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawtets\", TCL_GLOBAL_ONLY));\n    vispar.drawprisms =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawprisms\", TCL_GLOBAL_ONLY));\n    vispar.drawpyramids =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawpyramids\", TCL_GLOBAL_ONLY));\n    vispar.drawhexes =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawhexes\", TCL_GLOBAL_ONLY));\n    /*\n    vispar.shrink =\n      atof (Tcl_GetVar (interp, \"::viewoptions.shrink\", TCL_GLOBAL_ONLY));\n    */\n    double hshrink = atof (Tcl_GetVar (interp, \"::viewoptions.shrink\", TCL_GLOBAL_ONLY));\n    if (hshrink != vispar.shrink)\n      { vispar.shrink = hshrink; vispar.clipping.timestamp = NextTimeStamp();}\n    vispar.drawidentified =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawidentified\", TCL_GLOBAL_ONLY));\n    vispar.drawpointnumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawpointnumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawedgenumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawedgenumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawfacenumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawfacenumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawelementnumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawelementnumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawsurfaceelementnumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawsurfaceelementnumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawsegmentnumbers =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawsegmentnumbers\", TCL_GLOBAL_ONLY));\n    vispar.drawdomainsurf =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawdomainsurf\", TCL_GLOBAL_ONLY));\n\n    vispar.drawededges =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawededges\", TCL_GLOBAL_ONLY));\n    vispar.drawedpoints =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawedpoints\", TCL_GLOBAL_ONLY));\n    vispar.drawedpointnrs =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawedpointnrs\", TCL_GLOBAL_ONLY));\n    vispar.drawedtangents =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawedtangents\", TCL_GLOBAL_ONLY));\n    vispar.drawededgenrs =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawededgenrs\", TCL_GLOBAL_ONLY));\n\n    vispar.drawcurveproj =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawcurveproj\", TCL_GLOBAL_ONLY));\n    vispar.drawcurveprojedge =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawcurveprojedge\", TCL_GLOBAL_ONLY));\n\n    vispar.centerpoint =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.centerpoint\", TCL_GLOBAL_ONLY));\n    vispar.use_center_coords =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.usecentercoords\", TCL_GLOBAL_ONLY)) > 0;\n    vispar.centerx =\n      atof (Tcl_GetVar (interp, \"::viewoptions.centerx\", TCL_GLOBAL_ONLY));\n    vispar.centery =\n      atof (Tcl_GetVar (interp, \"::viewoptions.centery\", TCL_GLOBAL_ONLY));\n    vispar.centerz =\n      atof (Tcl_GetVar (interp, \"::viewoptions.centerz\", TCL_GLOBAL_ONLY));\n    vispar.drawelement =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawelement\", TCL_GLOBAL_ONLY));\n    vispar.drawmetispartition =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawmetispartition\", TCL_GLOBAL_ONLY));\n\n    vispar.drawspecpoint =\n      atoi (Tcl_GetVar (interp, \"::viewoptions.drawspecpoint\", TCL_GLOBAL_ONLY));\n    vispar.specpointx =\n      atof (Tcl_GetVar (interp, \"::viewoptions.specpointx\", TCL_GLOBAL_ONLY));\n    vispar.specpointy =\n      atof (Tcl_GetVar (interp, \"::viewoptions.specpointy\", TCL_GLOBAL_ONLY));\n    vispar.specpointz =\n      atof (Tcl_GetVar (interp, \"::viewoptions.specpointz\", TCL_GLOBAL_ONLY));\n\n\n    vsspecpoints.len =\n      atof (Tcl_GetVar (interp, \"::viewoptions.specpointvlen\", TCL_GLOBAL_ONLY));\n\n    vispar.occdeflection = pow(10.0,-1-atof (Tcl_GetVar (interp, \"::occoptions.deflection\", TCL_GLOBAL_ONLY)));\n\n\n\n#ifdef PARALLELGL\n    vsmesh.Broadcast ();\n#endif\n\n    return TCL_OK;\n  }\n\n\n\n  int Ng_BuildFieldLines (ClientData clientData,\n\t\t\t  Tcl_Interp * interp,\n\t\t\t  int argc, tcl_const char *argv[])\n  {\n    netgen::GetVSSolution().BuildFieldLinesPlot();\n    return TCL_OK;\n  }\n\n\n\n  int Ng_Exit (ClientData clientData,\n\t       Tcl_Interp * interp,\n\t       int argc, tcl_const char *argv[])\n  {\n    /*\n#ifdef PARALLEL\n    int id, rc, ntasks;\n    MPI_Comm_size(MPI_COMM_WORLD, &ntasks);\n    MPI_Comm_rank(MPI_COMM_WORLD, &id);\n    if ( id != 0 )\n      return TCL_OK;\n#endif\n    */\n\n    /*\n    if (ngsolve_handle)\n      {\n        void (*ngs_exit)();\n        ngs_exit = ( void (*)() ) dlsym (ngsolve_handle, \"NGSolve_Exit\");\n        if (ngs_exit) (*ngs_exit)();\n      }\n    */\n\n#ifdef NGSOLVE\n    NGSolve_Exit ();\n#endif\n\n\n\n#ifdef ACIS\n    outcome res;\n    res = api_terminate_faceter();\n    if(!res.ok())\n      cerr << \"problem with terminating acis faceter\" << endl;\n    res = api_terminate_constructors();\n    if(!res.ok())\n      cerr << \"problem with terminating acis constructors\" << endl;\n    res = api_terminate_kernel();\n    if(!res.ok())\n      cerr << \"problem with terminating acis kernel\" << endl;\n    res = api_stop_modeller();\n    if(!res.ok())\n      cerr << \"problem with terminating acis modeller\" << endl;\n\n    //cout << \"stopped acis, outcome = \" << res.ok() << endl;\n#endif\n\n#ifdef PARALLELGL\n    if (id == 0) MyMPI_SendCmd (\"end\");\n    MPI_Finalize();\n#endif\n\n    mesh.reset();\n    ng_geometry.reset();\n    \n    if (testout != &cout)\n      delete testout;\n\n    return TCL_OK;\n  }\n\n\n#ifdef SOCKETS\n  void * ServerSocketManagerRunDummy ( void * nix )\n  {\n    serversocketmanager.Run();\n    return NULL;\n  }\n\n  extern \"C\" int Ng_ServerSocketManagerRun( void );\n  int Ng_ServerSocketManagerRun( void )\n  {\n    if(mparam.parthread)\n      RunParallel(ServerSocketManagerRunDummy,NULL);\n    else\n      serversocketmanager.Run();\n\n    return TCL_OK;\n  }\n\n  extern \"C\" int Ng_ServerSocketManagerInit(int port);\n  int Ng_ServerSocketManagerInit(int port)\n  {\n    serversocketmanager.Init(port);\n    return TCL_OK;\n  }\n#endif //SOCKETS\n\n\n  extern \"C\" int Ng_Init (Tcl_Interp * interp);\n  extern \"C\" int Ng_CSG_Init (Tcl_Interp * interp);\n\n  extern \"C\" int Ng_stl_Init (Tcl_Interp * interp);\n  extern \"C\" int Ng_geom2d_Init (Tcl_Interp * interp);\n  #ifdef OCCGEOMETRY\n    extern \"C\" int Ng_occ_Init (Tcl_Interp * interp);\n#endif\n\n\n  // extern \"C\" int Ng_Geom2d_Init (Tcl_Interp * interp); \n\n  //   int main_Eero (ClientData clientData,\n  // \t       Tcl_Interp * interp,\n  // \t\t int argc, tcl_const char *argv[]);\n\n\n  int Ng_Init (Tcl_Interp * interp)\n  {\n#ifdef SOCKETS\n    if(serversocketmanager.Good())\n      serversocketusernetgen.Reset(new ServerSocketUserNetgen (serversocketmanager, mesh, geometry));\n#endif\n\n    Ng_CSG_Init(interp);\n    Ng_stl_Init(interp);\n    Ng_geom2d_Init (interp);\n#ifdef OCCGEOMETRY\n    Ng_occ_Init (interp);\n#endif\n\n\n    // Ng_Geom2d_Init(interp);\n\n    tcl_interp = interp;\n\n    //     Tcl_CreateCommand (interp, \"Ng_Eero\", main_Eero,\n    // \t\t       (ClientData)NULL,\n    // \t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_New\", Ng_New,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    //     Tcl_CreateCommand (interp, \"Ng_Lock\", Ng_Lock,\n    // \t\t       (ClientData)NULL,\n    // \t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_LoadGeometry\", Ng_LoadGeometry,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SaveGeometry\", Ng_SaveGeometry,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_LoadMesh\", Ng_LoadMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SaveMesh\", Ng_SaveMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MergeMesh\", Ng_MergeMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_GetImportFormats\", Ng_GetImportFormats,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_GetExportFormats\", Ng_GetExportFormats,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ExportMesh\", Ng_ExportMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ImportMesh\", Ng_ImportMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ImportSolution\", Ng_ImportSolution,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ShowDemo\", Ng_ShowDemo,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_DemoSetTime\", Ng_DemoSetTime,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SaveSolution\", Ng_SaveSolution,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n\n\n    \n\n    // meshing\n    Tcl_CreateCommand (interp, \"Ng_GenerateMesh\", Ng_GenerateMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_StopMeshing\", Ng_StopMeshing,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MeshInfo\", Ng_MeshInfo,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MeshQuality\", Ng_MeshQuality,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_CheckSurfaceMesh\", Ng_CheckSurfaceMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_CheckVolumeMesh\", Ng_CheckVolumeMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_DeleteVolMesh\", Ng_DeleteVolMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SplitSeparatedFaces\", Ng_SplitSeparatedFaces,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SetNextTimeStamp\", Ng_SetNextTimeStamp,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Refine\", Ng_Refine,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SecondOrder\", Ng_SecondOrder,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_HighOrder\", Ng_HighOrder,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ValidateSecondOrder\", Ng_ValidateSecondOrder,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_RestrictH\", Ng_RestrictH,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Anisotropy\", Ng_Anisotropy,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Bisect\", Ng_Bisect,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    //     Tcl_CreateCommand (interp, \"Ng_BisectCopyMesh\", Ng_BisectCopyMesh,\n    // \t\t       (ClientData)NULL,\n    // \t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Split2Tets\", Ng_Split2Tets,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ZRefinement\", Ng_ZRefinement,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_HPRefinement\", Ng_HPRefinement,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_LoadMeshSize\", Ng_LoadMeshSize,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MeshSizeFromSurfaceMesh\", Ng_MeshSizeFromSurfaceMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_GenerateBoundaryLayer\", Ng_GenerateBoundaryLayer,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_InsertVirtualBL\", Ng_InsertVirtualBL,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_CutOffAndCombine\", Ng_CutOffAndCombine,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_HelmholtzMesh\", Ng_HelmholtzMesh,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ReadStatus\", Ng_ReadStatus,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MemInfo\", Ng_MemInfo,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_MeshDoctor\", Ng_MeshDoctor,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_BCProp\", Ng_BCProp,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n\n\n    Tcl_CreateCommand (interp, \"Ng_ACISCommand\",\n\t\t       Ng_ACISCommand,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_MouseMove\", Ng_MouseMove,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_MouseDblClick\", Ng_MouseDblClick,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_ZoomAll\", Ng_ZoomAll,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Center\", Ng_Center,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_StandardRotation\", Ng_StandardRotation,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_ArbitraryRotation\", Ng_ArbitraryRotation,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_SetVisParameters\", Ng_SetVisParameters,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SetMeshingParameters\", Ng_SetMeshingParameters,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SetDebugParameters\", Ng_SetDebugParameters,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_SetCommandLineParameter\",\n\t\t       Ng_SetCommandLineParameter,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_GetCommandLineParameter\",\n\t\t       Ng_GetCommandLineParameter,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Exit\",\n\t\t       Ng_Exit,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    Tcl_CreateCommand (interp, \"Ng_Metis\",\n\t\t       Ng_Metis,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n\n    Tcl_CreateCommand (interp, \"Ng_BuildFieldLines\",\n\t\t       Ng_BuildFieldLines,\n\t\t       (ClientData)NULL,\n\t\t       (Tcl_CmdDeleteProc*) NULL);\n\n    /*\n     * Specify the C callback functions for widget creation, display,\n     * and reshape.\n     */\n    Tcl_CreateObjCommand(interp, \"Ng_GetToglVersion\", Ng_ToglVersion, NULL, NULL);\n\n    if (!nodisplay)\n      {\n\tif (Togl_Init(interp) == TCL_ERROR) \n\t  return TCL_ERROR;\n\t\n\t\n\tTcl_CreateObjCommand(interp, \"init\", init, NULL, NULL);\n\tTcl_CreateObjCommand(interp, \"zap\", zap, NULL, NULL);\n\tTcl_CreateObjCommand(interp, \"draw\", draw, NULL, NULL);\n\tTcl_CreateObjCommand(interp, \"reshape\", reshape, NULL, NULL);\n\t\n\t//   Togl_TimerFunc(  idle );\n\tTcl_CreateObjCommand(interp, \"Ng_SnapShot\", Ng_SnapShot, NULL, NULL);\n        Tcl_CreateObjCommand(interp, \"Ng_VideoClip\", Ng_VideoClip, NULL, NULL);\n      }\n\n\n    multithread.pause = 0;\n    multithread.testmode = 0;\n    multithread.redraw = 0;\n    multithread.drawing = 1;\n    multithread.terminate = 0;\n    multithread.running = 0;\n\n    multithread.task = \"\";\n    multithread.percent = 20;\n\n\n    Tcl_LinkVar (interp, \"multithread_pause\",\n\t\t (char*)&multithread.pause, TCL_LINK_INT);\n    Tcl_LinkVar (interp, \"multithread_testmode\",\n\t\t (char*)&multithread.testmode, TCL_LINK_INT);\n    Tcl_LinkVar (interp, \"multithread_redraw\",\n\t\t (char*)&multithread.redraw, TCL_LINK_INT);\n    Tcl_LinkVar (interp, \"multithread_drawing\",\n\t\t (char*)&multithread.drawing, TCL_LINK_INT);\n    Tcl_LinkVar (interp, \"multithread_terminate\",\n\t\t (char*)&multithread.terminate, TCL_LINK_INT);\n    Tcl_LinkVar (interp, \"multithread_running\",\n\t\t (char*)&multithread.running, TCL_LINK_INT);\n\n\n    //testout->setstate(ios_base::badbit);\n\n    myerr = &cerr;\n    extern ostream * mycout;\n    mycout = &cout;\n\n    testmode = 0;\n\n\n\n#ifdef ACIS\n    outcome res;\n    res = api_start_modeller (0);\n    if(!res.ok())\n      cerr << \"problem with starting acis modeller\" << endl;\n\n#ifdef ACIS_R17\n    unlock_spatial_products_661();\n#endif\n    res = api_initialize_kernel();\n    if(!res.ok())\n      cerr << \"problem with starting acis kernel\" << endl;\n    res = api_initialize_constructors();\n    if(!res.ok())\n      cerr << \"problem with starting acis constructors\" << endl;\n    res = api_initialize_faceter();\n    if(!res.ok())\n      cerr << \"problem with starting acis faceter\" << endl;\n#endif\n\n\n    return TCL_OK;\n  }\n\n\n}\n\n\n"
  },
  {
    "path": "ng/ngshell.tcl",
    "content": "## the shell loop\n\nproc dotest {} {\n  source ngtest.tcl\n}\n\nproc Ng_RunShell {} {\n  puts \"Wellcome to NG Shell mode\"\n  set line 1\n  while { 1 } {\n    puts -nonewline \"$line: \"\n    flush stdout\n    set cmdline [gets stdin] \n    if { [catch $cmdline errcode] } {\n#      puts \"error in command: '$cmdline'\"\n      puts \"$errcode\"\n    } \n    incr line 1\n  }\n}\n\n## global list for help index\n# ---> global var in variables.tcl\n# set cmdindex {}\n# set hlpindex {}\n# set secindex {}\n\n\n\n# print comd list\nproc Ng_PrintCmdIndex { } {\n  global cmdindex\n  foreach { lst } $cmdindex {\n    puts $lst \n  }  \n}\n\n# print formatted help index\nproc Ng_PrintHlpIndex { } {\n  global hlpindex\n  global secindex\n  foreach {sec} $secindex {\n    puts \"\\n  * $sec:\"\n    foreach {lst} $hlpindex {\n      if {$sec == [lindex $lst 1]} {\n        puts \"    * [lindex $lst 2]: [lindex $lst 3]\"\n      }\n    }\n  } \n}\n\n# register a cmd to the help index\nproc Ng_RegisterCmd { cmd section syntax {help \"\"} } {\n  global hlpindex\n  global cmdindex\n  global secindex\n\n    puts \"register command $cmd\"\n\n  if { [lsearch $cmdindex cmd] != -1 } {\n    puts \"command '$cmd' already defined\"\n  } else {\n    lappend cmdindex $cmd\n\n    lappend hlpindex [list $cmd $section $syntax $help]\n    if {[lsearch $secindex $section]==-1} {\n      lappend secindex $section\n    }\n#    puts \"registered command $cmd\"\n  }\n}\n\n\n# general purpose commands\nNg_RegisterCmd \"exit\" \"general\" \"exit\" \"exit Netgen shell mode\" \n#Ng_RegisterCmd \"Ng_LoadGeometry\" \"netgen\" \"Ng_LoadGeometry <file>\" \"load geometry file\" \n#Ng_RegisterCmd \"Ng_ParseGeometry\" \"netgen\" \"Ng_ParseGeometry\" \"parse geometry\"\n#Ng_RegisterCmd \"Ng_GenerateMesh\" \"netgen\" \"Ng_GenerateMesh\" \"generate mesh\"\n#Ng_RegisterCmd \"Ng_SaveMesh\" \"netgen\" \"Ng_SaveMesh <file>\" \"save mesh to file\" \n\n\n## public domain shell functions\n\n# print hel information\nproc nghelp { {sec \"\"} } {\n  global secindex\n  global hlpindex\n  global cmdindex\n  if { $sec == \"\" } {\n      Ng_PrintHlpIndex\n      puts \"\\n  type help 'section'\\n\"\n      return\n  } \n  \n  \n  if { [lsearch $secindex $sec] != -1} {\n    foreach {lst} $hlpindex {\n      if {[lindex $lst 1] == $sec } {\n        puts \"  * [lindex $lst 2]: [lindex $lst 3]\"\n      }\n    }\n    return\n  }\n  \n  set ind [lsearch $cmdindex $sec]\n  if {$ind != -1} {\n    set lst [lindex $hlpindex $ind]\n    puts \"  * [lindex $lst 2]: [lindex $lst 3]\"\n    return\n  }\n  \n  puts \"  unknown section or command $sec\"\n}\n\nset ngtimer 0\n\nproc nggettimer {} {\n   return [clock clicks -milliseconds]\n}\n\nproc ngtic {} {\n  set ::ngtimer [nggettimer]\n}\n\n\nproc ngtoc { {logfile stdout} } {\n  set end [nggettimer]\n  set tim [expr ($end - $::ngtimer)/1000.0]\n  puts $logfile \"$tim s\"\n}\n\n\n# load geometry file\nproc ngloadgeometry { fname } {\n  if { ![file exists $fname] } {\n    puts \"error: file $fname does not exist\"\n  } else {\n    set err [catch {Ng_LoadGeometry $fname}]\n    if {$err != 0} {\n      puts \"error: loading geometry failed\"\n    }\n  }\n} \nNg_RegisterCmd \"ngloadgeometry\" \"netgen\" \"ngloadgeometry <file>\" \"load geometry file\"  \n\n# parse geometry\nproc ngparsegeometry {} {\n  set err [catch {Ng_ParseGeometry}]\n  if {$err} {\n    puts \"error: parsing geometry failed\"\n  }\n}\nNg_RegisterCmd \"ngparsegeometry\" \"netgen\" \"ngparsegeometry\" \"parse geometry\"  \n \n# generate mesh\nproc nggeneratemesh {} {\n  set err [catch {Ng_GenerateMesh}]\n  if {$err} {\n    puts \"error:  mesh generation failed\"\n  }\n}\nNg_RegisterCmd \"nggeneratemesh\" \"netgen\" \"nggeneratemesh\" \"generate mesh\"  \n\n# save mesh\nproc ngsavemesh { fname } {\n  if { [file exists $fname]} {\n    puts \"warning: existing file $fname overwritten\"\n  } else {\n    set err [catch {Ng_SaveMesh $fname}]\n    if {$err != 0} {\n      puts \"error: saving mesh failed\"\n    }\n  }\n}  \nNg_RegisterCmd \"ngsavemesh\" \"netgen\" \"ngsavemesh <file>\" \"save mesh to file\"  \n\n#set option\nproc ngset { opt {val 0} } {\n  if {$opt == \"meshsize\"} {\n    set ::options.meshsize $val\n    Ng_SetMeshingParameters\n  } elseif {$opt == \"printmsg\"} {\n    set ::options.printmsg $val\n    Ng_SetMeshingParameters\n  } else {\n    puts \"error: unknown option $opt\";\n  }\n}\nNg_RegisterCmd \"ngset\" \"netgen\" \"ngset <option> <val>\" \"set option to val\"  \n\nproc nganalyzegeometry {} {\n  Ng_GenerateMesh ag ag\n  Ng_ReadStatus\n}\n\nproc ngmeshedges {} {\n  Ng_GenerateMesh me me \n  Ng_ReadStatus\n}\n\nproc ngmeshsurface { } {\n Ng_GenerateMesh ms ms\n Ng_ReadStatus\n}\n\nproc ngoptimizesurface { {step all} } {\n  if {$step == \"all\"} {\n    Ng_GenerateMesh os os cmsmSm\n  } elseif {$step == \"meshsmoothing\"} {\n    Ng_GenerateMesh os os m\n  } elseif {$step == \"topologicedgeswapping\" } {\n    Ng_GenerateMesh os os s\n  } elseif {$step == \"metricedgeswapping\"} {\n    Ng_GenerateMesh os os S\n  } elseif {$step == \"combinepoints\"} {\n    Ng_GenerateMesh os os c \n  } else {\n    puts \"error: unknown option in ngoptimizesurface\"\n    return\n  }\n  Ng_ReadStatus\n}\n\nproc ngmeshvolume { } {\n  Ng_GenerateMesh mv mv \n  Ng_ReadStatus \n}\n\nproc ngoptimizevolume {{step \"\"} } {\n  if {$step == \"\"} {\n    Ng_GenerateMesh ov ov \n  } elseif {$step == \"smooth\"} {\n    Ng_GenerateMesh ov ov m\n  } elseif {$step == \"smoothjacobian\"} {\n    Ng_GenerateMesh ov ov j \n  } else {\n    puts \"error: unknown step $step in ngoptimizevolume\"\n    return\n  }\n  Ng_ReadStatus \n}\n\n\nproc ngsloadpde {fname} {\n  if { ![file exists $fname] } {\n    puts \"warning: pdefile $fname does not exist\"\n  } else {\n    puts \"load pde $fname\"\n    NGS_LoadPDE $fname\n  }\n}\n\nproc ngssolvepde {} { \n  NGS_SolvePDE \n}\n\ncatch {source \"${::ngdir}/ngtesting.tcl\"} errcode\n# puts \"errcode = $errcode\"\n"
  },
  {
    "path": "ng/ngtcl.cpp",
    "content": "#include <meshing.hpp>\n#include <inctcl.hpp>\n#include \"../libsrc/meshing/visual_interface.hpp\"\n\n\nstatic void Impl_Ng_Tcl_SetResult(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc)\n{\n    Tcl_SetResult(interp, result, freeProc);\n}\n\nstatic void Impl_Ng_Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc)\n{\n    Tcl_CreateCommand(interp, cmdName, proc, nullptr, nullptr);\n}\n\nstatic bool dummy_init_pointers = [](){\n    netgen::Ptr_Ng_Tcl_SetResult = Impl_Ng_Tcl_SetResult;\n    netgen::Ptr_Ng_Tcl_CreateCommand = Impl_Ng_Tcl_CreateCommand;\n    return true;\n}();\n"
  },
  {
    "path": "ng/ngtesting.tcl",
    "content": "\n# tests.tcl\nproc Ng_TestMeshing { infile outfile logfile} {\n  if { ![file exists $infile]} {\n    puts $logfile \"error: file $infile does not exist\"\n  } else {\n    puts -nonewline $logfile \"      loading geometry: \";\n    ngtic; Ng_LoadGeometry \"$infile\"; ngtoc $logfile\n    puts -nonewline $logfile \"      parsing geometry: \";\n    ngtic; Ng_ParseGeometry; ngtoc $logfile\n    puts -nonewline $logfile \"      generating mesh:  \";\n    ngtic; Ng_GenerateMesh; ngtoc $logfile\n    puts -nonewline $logfile \"      saving mesh:      \";\n    ngtic; Ng_SaveMesh \"$outfile\"; ngtoc $logfile\n    flush $logfile\n  }\n}\n\n# tests.tcl\nproc Ngs_TestPDE { infile {nsolves 1} logfile } {\n  if { ![file exists $infile]} {\n    puts $logfile \"error: file $infile does not exist\"\n  } else {\n    puts -nonewline $logfile \"       loading PDE file: \";\n    ngtic; ngsloadpde \"$infile\"; ngtoc $logfile\n    for {set i 1} {$i<=$nsolves} {incr i 1} {\n      puts -nonewline $logfile \"      solve PDE level $i: \";\n      ngtic; ngssolvepde; ngtoc $logfile\n    }\n    flush $logfile\n  }\n}\n\n\nproc ngtest { {t all} {f \"\"}} {\n  ngset printmsg 0\n  if {$f == \"\" } { \n    set logfile stdout \n  } else {\n    set logfile [open $f \"w\"]\n  }\n    global options.parthread\n    set options.parthread 0\n    Ng_SetMeshingParameters \n\n  if {$t == \"all\"} {\n    ngtest in2d $f\n    ngtest geo  $f\n    ngtest stl  $f\n    ngtest pde  $f\n    return\n  \n  } elseif {$t == \"in2d\"} {\n    puts \"\\n*** performing in2d file tests ***\"\n    puts \" ** writing results to $f\"\n    puts \"\\n ** testing in2d files in examples/ **\" \n    set testdir \"$::ngdir/../examples\"\n    set in2dfiles { beam2d hyperbolic piezo2dround rectangle\n                    squareincl squareinsquare }\n    foreach {tfile} $in2dfiles {\n      if {$f != \"\"} { puts \"  * meshing file examples/$tfile.in2d...\" }\n      puts $logfile \"\\n  * meshing file examples/$tfile.in2d...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.in2d\" \"$testdir/$tfile.vol\" $logfile\n    }  \n  \n    puts \"\\n ** testing in2d files in tutorials/ **\"\n    set testdir \"$::ngdir/../share/netgen\"\n    set in2dfiles { demo2d  newin2d  square  v2in2d }\n    foreach {tfile} $in2dfiles {\n      if {$f != \"\"} { puts \"  * meshing file tutorials/$tfile.in2d...\" }\n      puts $logfile \"\\n  * meshing file tutorials/$tfile.in2d...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.in2d\" \"$testdir/$tfile.vol\" $logfile\n    }\n    puts \"*** in2d tests complete\"\n  } elseif {$t == \"geo\"} {\n    puts \"\\n*** performing geo file tests ***\"\n    puts \" ** writing results to $f\"\n    puts \"\\n ** testing geo files in examples/ **\"\n    set testdir \"$::ngdir/../examples\"\n    set geofiles { beam cylsphere rboxcyl thinc \n       boxcyl fichera period saw_3d thinplate \n       coilshield  gamm3d plate shaft tripelpendel \n       cube halfsphere  poly shell twocubes \n       cylinder kaese  quarter3d  skew_prisms }\n    foreach {tfile} $geofiles {\n      if {$f != \"\"} { puts \"  * meshing file examples/$tfile.geo...\"; flush $logfile }\n      puts $logfile \"\\n  * meshing file examples/$tfile.geo...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.geo\" \"$testdir/$tfile.vol\" $logfile\n    } \n  \n    puts \"\\n ** testing geo files in tutorials/ **\"\n    set testdir \"$::ngdir/../share/netgen\"\n    set geofiles { boxcyl          cubemcyl     extrusion  revolution    trafo\n                   circle_on_cube  cubemsphere  fichera    sculpture     twobricks\n                   cone            cylinder     lshape3d   shaft         twocubes\n                   cubeandring     cylsphere    manyholes  sphere        twocyl\n                   cubeandspheres  ellipsoid    matrix     sphereincube\n                   cube            ellipticcyl  period     torus }\n    foreach {tfile} $geofiles {\n      if {$f != \"\"} { puts \"  * meshing file $tfile.geo...\" }\n      puts $logfile \"\\n  * meshing file $tfile.geo...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.geo\" \"$testdir/$tfile.vol\" $logfile\n    } \n  \n  } elseif {$t == \"stl\"} {\n    puts \"\\n*** performing stl file tests ***\"  \n#    set logfile [open stltest.log \"w\"]\n    puts \" ** writing results to $f\"\n    puts \"\\n ** testing stl files in examples/ **\"\n    set testdir \"$::ngdir/../examples\"\n    set stlfiles { crankshaft hinge1 }\n    foreach {tfile} $stlfiles {\n      if {$f != \"\"} { puts \"  * meshing file examples/$tfile.stl...\" }\n      puts $logfile \"\\n  * meshing file examples/$tfile.stl...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.stl\" \"$testdir/$tfile.vol\" $logfile\n    }\n  \n    puts \"\\n ** testing stl files in tutorials/ **\"\n    set testdir \"$::ngdir/../tutorials\"\n    set stlfiles { hinge part1 }\n    foreach {tfile} $stlfiles {\n      if {$f != \"\"} { puts \"  * meshing file tutorials/$tfile.stl...\" }\n      puts $logfile \"\\n  * meshing file tutorials/$tfile.stl...\"; flush $logfile \n      Ng_TestMeshing \"$testdir/$tfile.stl\" \"$testdir/$tfile.vol\" $logfile\n    }\n    puts \"*** stl tests complete\"    \n  } elseif {$t == \"pde\"} {\n    puts \"\\n*** preforming pde tests ***\"\n#    set logfile [open pdetest.log \"w\"]\n    puts \" ** writing results to $f\"\n    \n    puts \"\\n ** testing pde files in ngsolve/pde_tutorial/ **\"\n    set testdir \"$::ngdir/../ngsolve/pde_tutorial\"\n    set pdefiles { d1_square.pde d2_chip.pde d3_helmholtz.pde d4_cube.pde\n                   d5_beam.pde d6_shaft.pde d7_coil.pde d8_coilshield.pde }\n     \n    foreach {tfile} $pdefiles {\n      if {$f != \"\"} { puts \"  * testing ngsolve/pde_tutorial/$tfile...\" }\n      puts $logfile \"\\n  * testing ngsolve/pde_tutorial/$tfile...\"; flush $logfile \n      Ngs_TestPDE \"$testdir/$tfile\" 1 $logfile    \n    }\n    puts \"*** pde tests complete\"    \n\n  } else {\n    puts $logfile \"error: unknown test program '$t'\"; flush $logfile \n  }\n  puts \"\"\n}\nNg_RegisterCmd \"ngtest\" \"netgen\" \"ngtest\" \"perform ng standard tests: all in2d geo stl\"  \n\n\n\n\n"
  },
  {
    "path": "ng/ngvisual.tcl",
    "content": "Ng_Vis_Set parameters\n\n\n\nset viscnt 0\nproc snapshottimer { } {\n    after 2000 { snapshottimer }\n\n    global viscnt\n    set viscnt [expr $viscnt+1]\n    set s1 0000$viscnt\n#    puts $s1\n    set cnt [string range $s1 [expr [string length $s1]-4] end]\n    set filename \"p$cnt.jpg\"\n#    puts \"cnt = $cnt\"\n#    puts \"filename = $filename\"\n#    .ndraw Ng_SnapShot pictures/$filename\n}\nsnapshottimer\n\n\n\nproc redrawtimer { } {\n    global visoptions.autoredraw\n    global visoptions.autoredrawtime\n\n    set delay [expr int(${visoptions.autoredrawtime}*1000)]\n    if { ${visoptions.autoredraw} == 1 } { redraw; }\n    after $delay { redrawtimer } \n}\nredrawtimer\n\n\nset perstarttime [clock clicks -millisecond]\nproc redrawperiodic { } {\n    global visoptions.redrawperiodic\n    global perstarttime\n    set curtime [clock clicks -millisecond]\n#    puts \"redraw periodic, time = $curtime\"\n    Ng_Vis_Set time [expr ($curtime - $perstarttime) / 5]\n    redraw\n    if { ${visoptions.redrawperiodic} == 1 } { after 30 { redrawperiodic } };\n\n}\n\n\n\nproc addplotline { identifier datax datay plotinfo {color black}} {\n    set c $identifier.c\n\n    set xstart [lindex $plotinfo 0]\n    set ystart [lindex $plotinfo 1]\n    set xmin [lindex $plotinfo 2]\n    set ymin [lindex $plotinfo 3]\n    set unitx [lindex $plotinfo 4]\n    set unity [lindex $plotinfo 5]\n    \n    \n    \n    set latestx [expr ([lindex $datax 0]-$xmin)*$unitx + $xstart]\n    set latesty [expr ([lindex $datay 0]-$ymin)*$unity + $ystart]\n    \n    for {set i 1} {$i < [llength $datax]} {incr i} {\n\tset xpos [expr ([lindex $datax $i]-$xmin)*$unitx + $xstart]\n\tset ypos [expr ([lindex $datay $i]-$ymin)*$unity + $ystart]\n\t$c create line $latestx $latesty $xpos $ypos -width 1 -fill $color\n\tset latestx $xpos\n\tset latesty $ypos\n    }\n}\n\n\n\nproc createlineplot { width height identifier title xmin xmax ymin ymax plotinfo} {\n    set thiswidth $width\n    set thisheight $height\n    if { $thiswidth < 275 } { set thiswidth 275 }\n    if { $thisheight < 225 } { seth thisheight 225 }\n\n    set w $identifier\n\n    if {[winfo exists $w] == 1} {\n\t\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\t\n\tset c $w.c\n\t\n\tcanvas $c -relief raised -width $thiswidth -height $thisheight\n\tpack $w.c -side top -fill x\n\t\n\tset titleFont {Helvetica 18}\n\tset smallFont {Helvetica 12}\n\n\tset xstart 100\n\tset xend [expr $thiswidth-75]\n\tset ystart [expr $thisheight-75]\n\tset yend 75\n\n\t$c create line $xstart $ystart $xstart $yend -width 2\n\t$c create line $xstart $ystart $xend $ystart -width 2\n\n\t\n\n\t\n\tset unitx [expr double($xend-$xstart)/($xmax-$xmin)]\n\tset unity [expr double($yend-$ystart)/($ymax-$ymin)]\n\n\tfor {set i 0} {$i <= 1} {set i [expr $i+0.2]} {\n\t    $c create line [expr $xstart+$i*($xend-$xstart)] [expr $ystart] [expr $xstart+$i*($xend-$xstart)] [expr $ystart+5] -width 2\n\t    $c create text [expr $xstart+$i*($xend-$xstart)] [expr $ystart+7] -anchor n -font $smallFont \\\n\t\t-text [format \"%.3g\" [expr $xmin+$i*($xmax-$xmin)]]\n\t    $c create line [expr $xstart] [expr $ystart+$i*($yend-$ystart)] [expr $xstart-7] [expr $ystart+$i*($yend-$ystart)] -width 2\n\t    $c create text [expr $xstart-9] [expr $ystart+$i*($yend-$ystart)] -anchor e -font $smallFont \\\n\t\t-text [format \"%.3g\" [expr $ymin+$i*($ymax-$ymin)]]\n\t}\n\n\tupvar $plotinfo ploti\n\n\tset ploti \"$xstart $ystart $xmin $ymin $unitx $unity\"\n\n\t\t\n\tbutton $w.close -text \"Close\" -command \"destroy $w\"\n\tpack $w.close\n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w $title\n\tfocus $w\n\n    }\n\n}\n\n\nproc getlineplotdata { datax datay xmini xmaxi ymini ymaxi} {\n\n    upvar $datax datx\n    upvar $datay daty\n    \n    upvar $xmini xmin\n    upvar $xmaxi xmax\n    upvar $ymini ymin\n    upvar $ymaxi ymax\n\n    global visoptions.lineplotusingx\n    global visoptions.lineplotusingy\n    global visoptions.lineplotsource\n    global visoptions.lineplotfile\n\n    set datx \"\"\n    set daty \"\"\n\n    set xmin 1e20\n    set xmax -1e20\n    set ymin 1e20\n    set ymax -1e20\n    \n\n    if {${visoptions.lineplotsource} == \"file\"} {\n\tset fileId [open ${visoptions.lineplotfile} r]\n\tset line \"\"\n\t\n\twhile {[gets $fileId line] >= 0} {\n\t    if { [string index [lindex $line 0] 0] != \"\\#\" } {\n\t\tif { ${visoptions.lineplotusingx} < [llength $line] } {\n\t\t    lappend datx [lindex $line ${visoptions.lineplotusingx}]\n\t\t    \n\t\t    if { [lindex $datx end] < $xmin } {set xmin [lindex $datx end]}\n\t\t    if { [lindex $datx end] > $xmax } {set xmax [lindex $datx end]}\n\t\t} {\n\t\t    lappend datx 0\n\t\t}\n\t\tif { ${visoptions.lineplotusingy} < [llength $line] } {\n\t\t    lappend daty [lindex $line ${visoptions.lineplotusingy}]\n\n\t\t    if { [lindex $daty end] < $ymin } {set ymin [lindex $daty end]}\n\t\t    if { [lindex $daty end] > $ymax } {set ymax [lindex $daty end]}\n\t\t} {\n\t\t    lappend daty 0\n\t\t}\n\t    }\n\t    \n\t}\n\tclose $fileId\n    }\n}\n\n\nproc lineplotdialog { } {\n\n    set w .lineplot_dlg\n    \n    if {[winfo exists .lineplot_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\t\n\ttoplevel $w\n\t\n\tttk::frame $w.filesettings -relief  groove -borderwidth 3\n\tttk::frame $w.filesettings.title\n\tttk::radiobutton $w.filesettings.title.choose -variable visoptions.lineplotsource \\\n\t    -value file -text \"Data from File\"\n\n\tpack $w.filesettings.title.choose -side left\n\n\tpack $w.filesettings.title\n\n\t\n\tglobal visoptions.lineplotselectedeval\n\tglobal visoptions.lineplotfile\n\tglobal visoptions.evaluatefilenames\n\tglobal visoptions.evaluatefiledescriptions\n\n\tset evdata [NGS_GetData evaluatefiles]\n\tset visoptions.evaluatefilenames none\n\tset visoptions.evaluatefiledescriptions none\n\tfor {set i 0} {[expr $i+1] < [llength $evdata]} {incr i 2} {\n\t    lappend visoptions.evaluatefilenames [lindex $evdata $i]\n\t    lappend visoptions.evaluatefiledescriptions [lindex $evdata [expr $i+1]]\t    \n\t}\n\t\n\n\t# tixOptionMenu $w.filesettings.latestevals -label \"Use Evaluate Results: \" \\\n\t    # -options {\n\t\t# label.width  25\n\t\t# label.anchor e\n\t\t# menubutton.width 40\n\t    # } \n\t\n\t# for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} {\n\t    # $w.filesettings.latestevals add command $i \\\n\t\t# -label \"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\"\n\t# }\n\t# $w.filesettings.latestevals config -variable visoptions.lineplotselectedeval\n\n\t# pack $w.filesettings.latestevals\n    ttk::frame $w.filesettings.latestevals\n    ttk::label  $w.filesettings.latestevals.lab -text \"Use Evaluate Results: \"\n    ttk::menubutton $w.filesettings.latestevals.but -menu $w.filesettings.latestevals.menu -text \"coarse\" -width 40\n\n    menu $w.filesettings.latestevals.menu -tearoff 0\n\tfor {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} {\n\t    $w.filesettings.latestevals.menu add command -label $i\\\n                -command \"set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \\\"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\\\"\"\n\t}\n   $w.filesettings.latestevals.menu invoke ${visoptions.lineplotselectedeval}               \n\n\n    grid $w.filesettings.latestevals.lab $w.filesettings.latestevals.but -sticky nw\n\tpack $w.filesettings.latestevals\n\tttk::frame $w.filesettings.sfn\n\n\tttk::button $w.filesettings.sfn.bb -text \"Browse\" \\\n\t    -command { set visoptions.lineplotfile [tk_getOpenFile] }\n\n\t\n\tttk::entry $w.filesettings.sfn.fn -width 50 \\\n\t    -textvariable visoptions.lineplotfile\n\n\tpack $w.filesettings.sfn.bb $w.filesettings.sfn.fn -side left\n\n\tpack $w.filesettings.sfn\n\n\tttk::button $w.filesettings.refresh -text \"Refresh\" -command {\n\t    if { ${visoptions.lineplotselectedeval} != 0} {\n\t\tset visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n\t    }\n\t    \n\t    set saveusingx ${visoptions.lineplotusingx}\n\t    set saveusingy ${visoptions.lineplotusingy}\n\t    \n\n\t    \n\t    for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t\t${visoptions.lineplotxcoordselector} delete $i\n\t    }\n\t    for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t\t${visoptions.lineplotycoordselector} delete $i\n\t    }\n\n\t    \n\t    set fileId [open ${visoptions.lineplotfile} r]\n\t    set line \"\"\n\t    gets $fileId line\n\t    close $fileId\n\t    if { [lindex $line 0] == \"\\#nglineplotinfo\" } {\n\t\tset visoptions.lineplotdatadescr [lrange $line 1 end]\t\n\t    } {\n\t\tset visoptions.lineplotdatadescr \"\"\n\t\tfor { set i 0 } { $i < [llength $line] } { incr i } {\n\t\t    lappend visoptions.lineplotdatadescr \"data[expr $i+1]\"\n\t\t}\n\t    }\n\n\t    for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t\t${visoptions.lineplotxcoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n\t    }\n\t    for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t\t${visoptions.lineplotycoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n\t    }\n\n\t    if { $saveusingx < [llength ${visoptions.lineplotdatadescr}] } {\n\t\tset visoptions.lineplotusingx $saveusingx\n\t    } {\n\t\tset visoptions.lineplotusingx 0\n\t    }\n\t    if { $saveusingy < [llength ${visoptions.lineplotdatadescr}] } {\n\t\tset visoptions.lineplotusingy $saveusingy\n\t    } {\n\t\tset visoptions.lineplotusingy 1\n\t    }\t    \n\t}\n\n\tpack $w.filesettings.refresh\n\n\n\tttk::frame $w.filesettings.using\n\n\tglobal visoptions.lineplotdatadescr\n\n\t# tixOptionMenu $w.filesettings.using.xco -label \"X-Coord:\"\\\n\t    # -options {\n\t\t# label.width  8\n\t\t# label.anchor e\n\t\t# menubutton.width 15\n\t    # } \n\t# for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t    # $w.filesettings.using.xco add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n\t# }\n    \n    ttk::frame $w.filesettings.using.xco\n    ttk::label  $w.filesettings.using.xco.lab -text \"X-Coord:\"\n    ttk::menubutton $w.filesettings.using.xco.but -menu $w.filesettings.using.xco.menu -text \"\" -width 15\n\n    menu $w.filesettings.using.xco.menu -tearoff 0\n\tfor {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\n\t    $w.filesettings.using.xco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\n                -command \"set visoptions.lineplotusingx $i ; $w.filesettings.using.xco.but configure -text \\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\"\"\n\t}\n   $w.filesettings.using.xco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\n\n\n    grid $w.filesettings.using.xco.lab $w.filesettings.using.xco.but -sticky nw\n\t#pack $w.filesettings.using.xco    \n    \n    \n    \n\t# $w.filesettings.using.xco config -variable visoptions.lineplotusingx\n\t\n\t# tixOptionMenu $w.filesettings.using.yco -label \"Y-Coord:\"\\\n\t    # -options {\n\t\t# label.width  8\n\t\t# label.anchor e\n\t\t# menubutton.width 15\n\t    # } \n\t# for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n\t    # $w.filesettings.using.yco add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n\t# }\n\t# $w.filesettings.using.yco config -variable visoptions.lineplotusingy\n    ttk::frame $w.filesettings.using.yco\n    ttk::label  $w.filesettings.using.yco.lab -text \"Y-Coord:\"\n    ttk::menubutton $w.filesettings.using.yco.but -menu $w.filesettings.using.yco.menu -text \"\" -width 15\n\n    menu $w.filesettings.using.yco.menu -tearoff 0\n\tfor {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\n\t    $w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\n                -command \"set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\"\"\n\t}\n   $w.filesettings.using.yco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\n   grid $w.filesettings.using.yco.lab $w.filesettings.using.yco.but -sticky nw\n    \n\tglobal visoptions.lineplotxcoordselector\n\tglobal visoptions.lineplotycoordselector\n\tset visoptions.lineplotxcoordselector $w.filesettings.using.xco\n\tset visoptions.lineplotycoordselector $w.filesettings.using.yco\n\t\n\n\tpack $w.filesettings.using.xco $w.filesettings.using.yco -side left\n\tpack $w.filesettings.using\n\n\tpack $w.filesettings -fill x -ipady 3\n\t\n\tttk::frame $w.settings -relief  groove -borderwidth 3\n\tttk::label $w.settings.title -text \"\\nSettings\\n\"\n\tpack $w.settings.title \n\n\tttk::frame $w.settings.minmax \n\tttk::checkbutton $w.settings.minmax.autoscale -text \"Autoscale\" -variable visoptions.lineplotautoscale\n\t# tixControl $w.settings.minmax.xmin -label \"Min. x: \" \\\n\t    # -integer false -variable visoptions.lineplotxmin \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 8\n\t\t# label.anchor e\n\t    # }\t\n    ttk::frame $w.settings.minmax.xmin\n    ttk::label $w.settings.minmax.xmin.label -text \"Min. x: \"\n    ttk::spinbox $w.settings.minmax.xmin.sp -textvariable visoptions.lineplotxmin -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9 \n\n        # tixControl $w.settings.minmax.xmax -label \"Max. x: \" \\\n\t    # -integer false -variable visoptions.lineplotxmax \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 8\n\t\t# label.anchor e\n\t    # }\t\n    ttk::frame $w.settings.minmax.xmax\n    ttk::label $w.settings.minmax.xmax.label -text \"Max. x: \"\n    ttk::spinbox $w.settings.minmax.xmax.sp -textvariable visoptions.lineplotxmax -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9 \n        \n\t# tixControl $w.settings.minmax.ymin -label \"Min. y: \" \\\n\t    # -integer false -variable visoptions.lineplotymin \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 8\n\t\t# label.anchor e\n\t    # }\t\n    ttk::frame $w.settings.minmax.ymin\n    ttk::label $w.settings.minmax.ymin.label -text \"Min. y: \"\n    ttk::spinbox $w.settings.minmax.ymin.sp -textvariable visoptions.lineplotymin -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9 \n        \n\t# tixControl $w.settings.minmax.ymax -label \"Max. y: \" \\\n\t    # -integer false -variable visoptions.lineplotymax \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 8\n\t\t# label.anchor e\n\t    # }\t\n    ttk::frame $w.settings.minmax.ymax\n    ttk::label $w.settings.minmax.ymax.label -text \"Max. y: \"\n    ttk::spinbox $w.settings.minmax.ymax.sp -textvariable visoptions.lineplotymax -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9 \n    pack $w.settings.minmax.xmin.label $w.settings.minmax.xmin.sp\n    pack $w.settings.minmax.xmax.label $w.settings.minmax.xmax.sp\n    pack $w.settings.minmax.ymin.label $w.settings.minmax.ymin.sp\n    pack $w.settings.minmax.ymax.label $w.settings.minmax.ymax.sp\n\tpack $w.settings.minmax.autoscale $w.settings.minmax.xmin $w.settings.minmax.xmax \\\n\t    $w.settings.minmax.ymin $w.settings.minmax.ymax -side left\n\n\tpack $w.settings.minmax\n\n\t\n\tttk::label $w.settings.empty1 -text \"\"\n\tpack $w.settings.empty1\n\n\tttk::frame $w.settings.plotsize\n\n\t# tixControl $w.settings.plotsize.xsize -label \"Plotsize  x: \"\\\n\t    # -integer true -variable visoptions.lineplotsizex \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 13\n\t\t# label.anchor e\n\t    # }\n        \n    ttk::frame $w.settings.plotsize.xsize\n    ttk::label $w.settings.plotsize.xsize.label -text \"Plotsize  x: \"\n    ttk::spinbox $w.settings.plotsize.xsize.sp -textvariable visoptions.lineplotsizex -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n    pack $w.settings.plotsize.xsize.label $w.settings.plotsize.xsize.sp\n    \n\t# tixControl $w.settings.plotsize.ysize -label \"y: \"\\\n\t    # -integer true -variable visoptions.lineplotsizey \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 3\n\t\t# label.anchor e\n\t    # }\t\n    \n    ttk::frame $w.settings.plotsize.ysize\n    ttk::label $w.settings.plotsize.ysize.label -text \"Plotsize  y: \"\n    ttk::spinbox $w.settings.plotsize.ysize.sp -textvariable visoptions.lineplotsizey -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n    pack $w.settings.plotsize.ysize.label $w.settings.plotsize.ysize.sp\n\n\tpack $w.settings.plotsize.xsize $w.settings.plotsize.ysize -side left\n\n\tpack $w.settings.plotsize\n\n\tttk::label $w.settings.empty2 -text \"\"\n\tpack $w.settings.empty2\n\t\n\t# tixOptionMenu $w.settings.color -label \"Linecolor: \" \\\n\t    # -options {\n\t\t# label.width  19\n\t\t# label.anchor e\n\t\t# menubutton.width 15\n\t    # }\n\t# foreach step { red black blue green yellow } {\n\t    # $w.settings.color add command $step -label $step\n\t# }\n\t# $w.settings.color config -variable visoptions.lineplotcolor\n    ttk::frame $w.settings.color\n    ttk::label  $w.settings.color.lab -text \"Linecolor: \"\n    ttk::menubutton $w.settings.color.but -menu $w.settings.color.menu -text \"\" -width 15\n\n    menu $w.settings.color.menu -tearoff 0\n\tforeach step { red black blue green yellow } {\n\t    $w.settings.color.menu add command -label $step -command \"set visoptions.lineplotcolor $step; $w.settings.color.but configure -text \\\"$step\\\"\"\n    }\n\t# for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\n\t    # $w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\n                # -command \"set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\"\"\n\t# }\n   $w.settings.color.menu invoke \"red\"\n   grid $w.settings.color.lab $w.settings.color.but -sticky nw    \n    \n\tpack $w.settings.color\n\n\n\tpack $w.settings -fill x \n\n\tset datax \"\"\n\tset datay \"\"\n\tset xmin 0\n\tset xmax 0\n\tset ymin 0\n\tset ymax 0\n\n\tttk::frame $w.plots -relief  groove -borderwidth 3\n\n\t# tixOptionMenu $w.plots.selplot -label \"Selected Plot: \" \\\n\t    # -options {\n\t\t# label.width  19\n\t\t# label.anchor e\n\t\t# menubutton.width 15\n\t    # } \n\t# $w.plots.selplot add command none -label \"None\"\n\n\t# $w.plots.selplot config -variable visoptions.lineplotselected\n\n    ttk::frame $w.plots.selplot\n    ttk::label  $w.plots.selplot.lab -text \"Linecolor: \"\n    ttk::menubutton $w.plots.selplot.but -menu $w.plots.selplot.menu -text \"\" -width 15\n\n    menu $w.plots.selplot.menu -tearoff 0\n\t$w.plots.selplot.menu add command -label \"None\" -command \"set visoptions.lineplotselected \\\"None\\\"; $w.plots.selplot.but configure -text \\\"None\\\"\"\n    grid $w.plots.selplot.lab $w.plots.selplot.but -sticky nw    \n    $w.plots.selplot.menu invoke \"None\"\n    \n\tglobal visoptions.lineplotselector\n\tset visoptions.lineplotselector $w.plots.selplot.menu\n\n\t\n\n\tttk::button $w.plots.new -text \"Generate New Plot\" -command {\n\t    if { ${visoptions.lineplotselectedeval} != 0} {\n\t\tset visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n\t    }\n\n\t    getlineplotdata datax datay xmin xmax ymin ymax\n\n\t    puts stdout \"xmin $xmin xmax $xmax ymin $ymin ymax $ymax\"\n\n\t    global visoptions.lineplotautoscale\n\n\t    if {! ${visoptions.lineplotautoscale}} {\n\t\tputs \"using set min/max values\"\n\t\tset xmin ${visoptions.lineplotxmin}\n\t\tset xmax ${visoptions.lineplotxmax}\n\t\tset ymin ${visoptions.lineplotymin}\n\t\tset ymax ${visoptions.lineplotymax}\n\t    }\n\t    \n\t    incr visoptions.lineplotcurrentnum\n\t    \n\t    set ident .newplot${visoptions.lineplotcurrentnum}\n\t    set plotinfo \"\"\n\t    \n\t    createlineplot ${visoptions.lineplotsizex} ${visoptions.lineplotsizey} \\\n\t\t$ident \"Lineplot ${visoptions.lineplotcurrentnum}\" \\\n\t\t$xmin $xmax $ymin $ymax plotinfo\n\t    \n\t    lappend visoptions.lineplotinfos $plotinfo\n\n\t    \n\t    ${visoptions.lineplotselector} add command ${visoptions.lineplotcurrentnum} -label \"Lineplot ${visoptions.lineplotcurrentnum}\"\n\n\t    addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\n\t}\n\t\n\tttk::button $w.plots.addto -text \"Add to Selected Plot\" -command {\n\t    if { ${visoptions.lineplotselectedeval} != 0} {\n\t\tset visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n\t    }\n\n\t    if { ${visoptions.lineplotselected} != \"none\" } {\n\n\t\tgetlineplotdata datax datay xmin xmax ymin ymax\n\n\t\tset ident .newplot${visoptions.lineplotselected}\n\t\tset plotinfo [lindex ${visoptions.lineplotinfos} ${visoptions.lineplotselected}]\n\n\t\taddplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\n\t    }\n\t}\n\t    \n\t\n\t\n\tpack $w.plots.new $w.plots.addto $w.plots.selplot\n\t\n\t\n\tpack $w.plots -fill x -ipady 3\n\t\n\n\n\tttk::button $w.close -text \"Close\" -command \"destroy $w\"\n\tpack $w.close\n\t\n\twm withdraw $w\n\twm geom $w +200+100\n\twm deiconify $w\n\twm title $w \"2D Lineplots\"\n\n\tfocus $w\n    \n\n    }\n}\n\n\nset fieldlinesdialog_pop1 0\n\n\nproc fieldlinesdialog { } {\n    \n    set w .fieldlines_dlg\n\n    global fieldlinesdialog_pop1\n    set fieldlinesdialog_pop1 1\n\n    \n    if {[winfo exists .fieldlines_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\t\n\ttoplevel $w\n\n\t#tixNoteBook $w.nb -ipadx 6 -ipady 6\n\n        pack [ttk::notebook $w.nb]  -fill both -side top -ipadx 6 -ipady 6\n        $w.nb add [ttk::frame $w.nb.draw] -text \"Draw\" -underline 0 \n        $w.nb add [ttk::frame $w.nb.settings] -text \"Settings\" -underline 0        \n        \n\t#$w.nb add draw -label \"Draw\"\n\t#$w.nb add settings -label \"Settings\"\n\n\t#pack $w.nb -expand yes -fill both -padx 5 -pady 5 -side top\n\n\n\t# Main Window\n\n\tset f $w.nb.draw\n\t\n\tttk::labelframe $f.general -text \"General settings\" -relief groove -borderwidth 3\n\n\t\n\tttk::checkbutton $f.general.enable -text \"Enable Fieldlines\" \\\n\t    -variable visoptions.drawfieldlines \\\n\t    -command { \n\t\t# set visoptions.redrawperiodic ${visoptions.drawfieldlines}\n\t\t# redrawperiodic\n\t\t# redrawperiodic # sonst \n\t\tNg_Vis_Set parameters; \n\t\tredraw \n\t    }\n        ttk::label $f.general.numl -text \"num:\"\n\tttk::spinbox $f.general.num -from 0 -to 100 -increment 1 \\\n            -textvariable visoptions.numfieldlines -width 4\n        #tixControl $f.general.num -label \"Num: \" -integer true \\\n\t    -variable visoptions.numfieldlines \\\n\t    -command { Ng_Vis_Set parameters; redraw } \\\n\t    -options {\n\t#\tentry.width 6\n\t#\tlabel.width 12\n\t#\tlabel.anchor e\n\t#    }\t\n\n\t\n\tgrid $f.general.enable -sticky nw -padx 4 -pady 2\n        grid x $f.general.numl $f.general.num -rowspan 3 -sticky w -padx 4 -row 0 -pady 2\n        grid anchor $f.general center\n\n\tpack $f.general -pady 15 -fill x -ipady 3\n\n\tttk::label $f.labe0 -text \" \"\n\n\tpack $f.labe0\n\n\t#ttk::frame $f.general1\n\t\n\tttk::checkbutton $f.general.randomstart -text \"Field dependent density    \" \\\n\t    -variable visoptions.fieldlinesrandomstart \\\n\t    -command { Ng_Vis_Set parameters; redraw}\n\n\t\n\tttk::checkbutton $f.general.redrawperiodic -text \"Animate periodic\" \\\n\t    -variable visoptions.redrawperiodic \\\n\t    -command { \n\t\tredrawperiodic\n\t\tNg_Vis_Set parameters; \n\t\tredraw \n\t    }\n\n\tgrid $f.general.randomstart -sticky nw -padx 4 -row 1\n        grid $f.general.redrawperiodic -sticky nw -padx 4 -row 2\n\n\t#pack $f.general1\n\n\n\n\tttk::label $f.lab0 -text \" \"\n\n\tpack $f.lab0\n\n\n\t\n\t# tixOptionMenu $f.vecfun -label \"Vector Function: \" \\\n\t    # -options {\n\t\t# label.width  18\n\t\t# label.anchor e\n\t\t# menubutton.width 12\n\t    # }\n\t# $f.vecfun add command none -label None \n\t# for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n\t    # set fname [Ng_Vis_Field getfieldname $i]\n\t    # set fcomp [Ng_Vis_Field getfieldcomponents $i]\n\t    # set iscomplex [Ng_Vis_Field iscomplex $i]\n\t    # set sdim [Ng_Vis_Field getdimension]\n\t    # if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\n\t    # if { ($fcomp == $sdim) || ($fcomp == 3) } {\n\t\t# $f.vecfun add command $fname -label $fname\n\t    # } \n\t# }\n\t# $f.vecfun configure -variable visoptions.fieldlinesvecfunction\n\t# $f.vecfun configure -command { Ng_Vis_Set parameters; redraw }\n    ttk::frame $f.vecfun\n    ttk::label  $f.vecfun.lab -text \"Vector Function: \"     \n    ttk::menubutton $f.vecfun.but -menu $f.vecfun.menu -text \"\" -width 12     \n    menu $f.vecfun.menu -tearoff 0 \t\n    # for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} {\n    # $w.filesettings.latestevals.menu add command -label $i\\                 \n    # -command \"set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \\\"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\\\"\" \t\n    # } \t\n    for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n    set fname [Ng_Vis_Field getfieldname $i] \t    \n    set fcomp [Ng_Vis_Field getfieldcomponents $i] \t    \n    set iscomplex [Ng_Vis_Field iscomplex $i] \t    \n    set sdim [Ng_Vis_Field getdimension] \t    \n    if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] } \t    \n    if { ($fcomp == $sdim) || ($fcomp == 3) } {\n    $f.vecfun.menu add command -label $fname -command \"set visoptions.fieldlinesvecfunction $fname;Ng_Vis_Set parameters; redraw;$f.vecfun.but configure -text \\\"$fname\\\" \" \t    }         \n    }\n    grid $f.vecfun.lab $f.vecfun.but -sticky nw\n\tpack $f.vecfun\n\t\n\n\n\tttk::label $f.lab00 -text \" \"\n\n\tpack $f.lab00\n\n\tttk::frame $f.phasesettings\n\n\tttk::checkbutton $f.phasesettings.onephase -text \"Fix Phase\" -variable visoptions.fieldlinesonlyonephase\n\t# scale $f.phasesettings.phase -orient horizontal -length 300 -from 0 -to 360 \\\n\t    # -label \"phi\" \\\n\t    # -resolution 1 \\\n\t    # -variable visoptions.fieldlinesphase \\\n\t    # -command { popupcheckredraw3 fieldlinesdialog_pop1 }\n\n    ttk::frame $f.phasesettings.phase\n    ttk::label $f.phasesettings.phase.lab -text \"phi\"\n    ttk::scale $f.phasesettings.phase.sc -orient horizontal -length 100 -from 0 -to 360 -variable visoptions.fieldlinesphase \\\n        -command \"roundscale $f.phasesettings.phase.sc 0; popupcheckredraw3 fieldlinesdialog_pop1\"\n    ttk::entry $f.phasesettings.phase.ent -width 4 -textvariable visoptions.fieldlinesphase -validate focus -takefocus 0 \\\n        -validatecommand \"popupcheckredraw3 fieldlinesdialog_pop1;my_validate %W 0 1 %P 0\" \\\n        -invalidcommand \"my_invalid %W;popupcheckredraw3 fieldlinesdialog_pop1\"\n    grid $f.phasesettings.phase.lab $f.phasesettings.phase.sc $f.phasesettings.phase.ent -sticky nw -ipadx 4\n\tpack $f.phasesettings.onephase $f.phasesettings.phase -side left\n\t\n\tpack $f.phasesettings\n\n\n\n\tttk::label $f.lab1 -text \" \"\n\n\tpack $f.lab1\n\n\n\t\n\tttk::frame $f.boxsettings -relief groove -borderwidth 3\n\tttk::frame $f.boxsettings.title\n\tttk::radiobutton $f.boxsettings.title.choose -variable visoptions.fieldlinesstartarea \\\n\t    -value box -text \"Startpoints in Box\"\n\n\tpack $f.boxsettings.title.choose -side left\n\n\tpack $f.boxsettings.title\n\n\tttk::frame $f.boxsettings.points\n\n\tttk::label $f.boxsettings.points.lab2 -text \"Pmin\";\n\tttk::entry $f.boxsettings.points.ent1x -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap1x\n\tttk::entry $f.boxsettings.points.ent1y -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap1y\n\tttk::entry $f.boxsettings.points.ent1z -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap1z\n\tttk::label $f.boxsettings.points.lab3 -text \"   Pmax\";\n\tttk::entry $f.boxsettings.points.ent2x -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap2x\n\tttk::entry $f.boxsettings.points.ent2y -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap2y\n\tttk::entry $f.boxsettings.points.ent2z -width 8 \\\n\t    -textvariable visoptions.fieldlinesstartareap2z\n\t\n\tpack $f.boxsettings.points\n\tpack $f.boxsettings.points.lab2 $f.boxsettings.points.ent1x $f.boxsettings.points.ent1y $f.boxsettings.points.ent1z -side left\n\tpack $f.boxsettings.points.lab3 $f.boxsettings.points.ent2x $f.boxsettings.points.ent2y $f.boxsettings.points.ent2z -side left\n\n\tttk::button $f.boxsettings.settobb -text \"Bounding Box\" -command {\n\t    set bbox [Ng_MeshInfo bbox]\n\t    set visoptions.fieldlinesstartareap1x [lindex $bbox 0]\n\t    set visoptions.fieldlinesstartareap2x [lindex $bbox 1]\n\t    set visoptions.fieldlinesstartareap1y [lindex $bbox 2]\n\t    set visoptions.fieldlinesstartareap2y [lindex $bbox 3]\n\t    set visoptions.fieldlinesstartareap1z [lindex $bbox 4]\n\t    set visoptions.fieldlinesstartareap2z [lindex $bbox 5]\n\t}\n\n\tpack $f.boxsettings.settobb\n\t    \n\t\n\tpack $f.boxsettings -fill x -ipady 3\n\n\n\tttk::frame $f.facesettings -relief groove -borderwidth 3\n\tttk::frame $f.facesettings.title\n\tttk::radiobutton $f.facesettings.title.choose -variable visoptions.fieldlinesstartarea \\\n\t    -value face -text \"Startpoints on Face\"\n\n\tpack $f.facesettings.title.choose -side left\n\n\tpack $f.facesettings.title\n\t\n\tttk::frame $f.facesettings.index\n\tttk::label $f.facesettings.index.lab -text \"face index:\"\n\tttk::label $f.facesettings.index.ent -text 1;# -padx 4\n\n\tpack $f.facesettings.index.lab $f.facesettings.index.ent -side left\n\n\tpack $f.facesettings.index\n\t\n\tpack $f.facesettings -fill x -ipady 3\n\n\n\tglobal visoptions.fieldlinesfilename\n\n\tttk::frame $f.filesettings -relief  groove -borderwidth 3\n\tttk::frame $f.filesettings.title\n\tttk::radiobutton $f.filesettings.title.choose -variable visoptions.fieldlinesstartarea \\\n\t    -value file -text \"Startpoints from File\"\n\n\tpack $f.filesettings.title.choose -side left\n\n\tpack $f.filesettings.title\n\n\tttk::frame $f.filesettings.sfn\n\n\tttk::button $f.filesettings.sfn.bb -text \"Browse\" \\\n\t    -command {\n\t\tset types {\n\t\t    { \"Netgen Fieldlines\" {.nef} }\n\t\t}\n\t\tset visoptions.fieldlinesfilename [tk_getOpenFile -filetypes $types -defaultextension \".nef\"]\n\t    }\n\n\t\n\tttk::entry $f.filesettings.sfn.fn -width 50 \\\n\t    -textvariable visoptions.fieldlinesfilename\n\n\tpack $f.filesettings.sfn.bb $f.filesettings.sfn.fn -side left\n\n\tpack $f.filesettings.sfn\n\n\tpack $f.filesettings -fill x -ipady 3\n\t\n\n\n\t\n\t# Settings\n\n\tset g $w.nb.settings\n\n\tttk::frame $g.linesettings -relief groove -borderwidth 3\n\tttk::label $g.linesettings.title -text \"\\nLine Settings\\n\"\n\t# tixControl $g.linesettings.length -label \"rel. Length: \" -integer false \\\n\t    # -variable visoptions.fieldlineslength -min 0.00001 -max 10000 -step 0.1 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\n\n    ttk::frame $g.linesettings.length\n    ttk::label $g.linesettings.length.lab -text \"rel. Length: \"\n    ttk::spinbox $g.linesettings.length.sp -textvariable visoptions.fieldlineslength -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 5\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from 0.00001 -to 10000\n    grid $g.linesettings.length.lab $g.linesettings.length.sp -sticky nw\n        \n\t# tixControl $g.linesettings.maxpoints -label \"max. Points: \" -integer true \\\n\t    # -variable visoptions.fieldlinesmaxpoints -min 0 -max 10000 -step 1 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\n    ttk::frame $g.linesettings.maxpoints\n    ttk::label $g.linesettings.maxpoints.lab -text \"max. Points: \"\n    ttk::spinbox $g.linesettings.maxpoints.sp -textvariable visoptions.fieldlinesmaxpoints -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from 0 -to 10000\n    grid $g.linesettings.maxpoints.lab $g.linesettings.maxpoints.sp -sticky nw\n\n        \n\t# tixControl $g.linesettings.thick -label \"rel. Thickness: \" -integer false \\\n\t    # -variable visoptions.fieldlinesthickness -min 1e-10 -max 0.5 -step 0.001 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\n        \n    ttk::frame $g.linesettings.thick\n    ttk::label $g.linesettings.thick.lab -text \"rel. Thickness: \"\n    ttk::spinbox $g.linesettings.thick.sp -textvariable visoptions.fieldlinesthickness -width 6 -increment 0.001 -validate focus -validatecommand \"my_validatespinbox %W %P 6\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from 1e-10 -to 0.5\n    grid $g.linesettings.thick.lab $g.linesettings.thick.sp -stick nw\n    \n\tpack $g.linesettings.title $g.linesettings.length $g.linesettings.maxpoints $g.linesettings.thick\n\n\tpack $g.linesettings -fill x -ipady 3\n\n\n\t\n\n\n\tglobal visoptions.fieldlinestolerance\n\n\tttk::frame $g.odesettings -relief groove -borderwidth 3\n\tttk::label $g.odesettings.title -text \"\\nODE Settings\\n\"\n\t# tixControl $g.odesettings.tol -label \"rel. Tolerance: \" -integer false \\\n\t    # -variable visoptions.fieldlinestolerance -min 0.00001 -max 1 -step 0.01 \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 25\n\t\t# label.anchor e\n\t    # }\t\n    \n    ttk::frame $g.odesettings.tol\n    ttk::label $g.odesettings.tol.lab -text \"rel. Thickness: \"\n    ttk::spinbox $g.odesettings.tol.sp -textvariable visoptions.fieldlinestolerance -width 6 -increment 0.01 -validate focus -validatecommand \"my_validatespinbox %W %P 5\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from 0.00001 -to 1\n    grid $g.odesettings.tol.lab $g.odesettings.tol.sp -stick nw\n\n        \n\t# tixOptionMenu $g.odesettings.rktype -label \"RK-Type \" \\\n\t    # -options {\n\t\t# label.width  20\n\t\t# label.anchor e\n\t\t# menubutton.width 25\n\t    # }\n\t# $g.odesettings.rktype add command euler -label \"Euler, order 1\"\n\t# $g.odesettings.rktype add command eulercauchy -label \"Euler-Cauchy, order 2\"\n\t# $g.odesettings.rktype add command simpson -label \"Simpson, order 3\"\n\t# $g.odesettings.rktype add command crungekutta -label \"classical Runge-Kutta, order 4\"\n\t# $g.odesettings.rktype configure -variable visoptions.fieldlinesrktype\n\t# $g.odesettings.rktype configure -command { Ng_Vis_Set parameters; redraw }\n    ttk::frame $g.odesettings.rktype     \n    ttk::label  $g.odesettings.rktype.lab -text \"RK-Type \"     \n    ttk::menubutton $g.odesettings.rktype.but -menu $g.odesettings.rktype.menu -text \"\" -width 25     \n    menu $g.odesettings.rktype.menu -tearoff 0     \n    $g.odesettings.rktype.menu add command -label \"Euler, order 1\" -command \"set visoptions.fieldlinesrktype \\\"euler\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Euler,order 1\\\" \"     \n    $g.odesettings.rktype.menu add command -label \"Euler-Cauchy, order 2\" -command \"set visoptions.fieldlinesrktype \\\"eulercauchy\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Euler-Cauchy,order 2\\\" \"     \n    $g.odesettings.rktype.menu add command -label \"Simpson, order 3\" -command \"set visoptions.fieldlinesrktype \\\"simpson\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Simpson,order 3\\\"\"     \n    $g.odesettings.rktype.menu add command -label \"classical Runge-Kutta, order 4\" -command \"set visoptions.fieldlinesrktype \\\"crungekutta\\\" ;Ng_Vis_Set parameters; redraw; $g.odesettings.rktype.but configure -text \\\"classical Runge-Kutta,order 4\\\"\"        \n    $g.odesettings.rktype.menu invoke \"classical Runge-Kutta, order 4\"     \n    \n    grid $g.odesettings.rktype.lab $g.odesettings.rktype.but -sticky nw \t\n\t\n\tpack $g.odesettings.title $g.odesettings.tol $g.odesettings.rktype\n\n\tpack $g.odesettings -fill x -ipady 3\n\n\n\n\t# buttons\n\t\n\n\tttk::frame $w.bu \n\tpack $w.bu -fill x -ipady 3\n\n\tttk::button $w.bu.calc -text \"Build Fieldlines\" -command { \n\t    if { ${visoptions.fieldlinesvecfunction} == \"none\" } {\n\t\tbgerror \"Please select the vector function first!\"\n\t    } {\n\t\tset visoptions.drawfieldlines 1\n\t\tNg_Vis_Set parameters\n\t\tNg_BuildFieldLines\n\t\tredraw \n\t    }\n\t}\n\n\tttk::button $w.bu.help -text \"Help\" -command {\n\t    if {[winfo exists .fieldlines_help] == 1} {\n\t\twm withdraw .fieldlines_help\n\t\twm deiconify .fieldlines_help\n\t\tfocus .fieldlines_help\n\t    } {\n\t\ttoplevel .fieldlines_help\n\n        set f [frame .fieldlines_help.ht]\n        #ttk::scrollbar $f.hsb -orient horizontal -command [list $f.t xview]\n        ttk::scrollbar $f.vsb -orient vertical -command [list $f.t yview]\n        text $f.t -yscrollcommand [list $f.vsb set] \n        grid $f.t -row 0 -column 0 -sticky nsew\n        grid $f.vsb -row 0 -column 1 -sticky nsew\n        grid columnconfigure $f 0 -weight 1\n        grid rowconfigure $f 0 -weight 1\n\t\t#tixScrolledText .fieldlines_help.ht -scrollbar y\n\t\tset text $f.t\n\n\t\t$text configure -setgrid true -wrap word \n\n\t\t$text tag configure bold -font *-*-bold-*-*-*-*\n\n\t\t\n\t\t$text insert end \\\n\t\t    \"Draw menu\\n \\n\" bold\n\t\t$text insert end \\\n\t\t    \"Enable Fieldlines\\n    To turn on and off the calculated fieldlines. (Has to be turned on to start the calculation)\\n\"\n\t\t$text insert end \\\n\t\t    \"Num\\n    Number of fieldlines to calculate. (May not be used exactly.)\"\n\t\t$text insert end \\\n\t\t    \"Field dependent density\\n    There will be more fieldline startpoints where the field is stronger\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"Animate periodic\\n    (for quasistationary fields) The fieldlines of the different phase angles are animated.\\n    ATTENTION: \\\"Fix Phase\\\" has to be turned off\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"Vector Function\\n    The function fixing the direction of the lines\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"Fix Phase\\n    (for quasistationary fields) Only calculate and draw fieldlines for one special phase angle.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"Startpoints in Box\\n    Set the startpoints inside the box \\[Pmin1,Pmax1\\] x \\[Pmin2,Pmax2\\] x \\[Pmin3,Pmax3\\]\\n\"\n\t\t$text insert end \\\n\t\t    \"    With the button \\\"Bounding Box\\\" the whole bounding box of the geometry is selected.\\n\\n\" \n\t\t$text insert end \\\n\t\t    \"Startpoints on Face\\n    All startpoints will be set on one face. This face is selected by double-clicking with the mouse.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"Startpoints from File\\n    The startpoint information will be read from the selected file.\\n    The entries in the file can be as follows:\\n\"\n\t\t$text insert end \\\n\t\t    \"        point <x> <y> <z>\\n            set a (potential) startpoint\\n\"\n\t\t$text insert end \\\n\t\t    \"        line <x1> <y1> <z1> <x2> <y2> <z2> <n>\\n            set n (potential) startpoints on the line from (x1,y1,z1) to (x2,y2,z2)\\n\"\n\t\t$text insert end \\\n\t\t    \"        box <x1> <y1> <z1> <x2> <y2> <z2> <n>\\n            set n (potential) startpoints inside the box \\[x1,x2\\] x \\[y1,y2\\] x \\[z1,z2\\]\\n\"\n\t\t$text insert end \\\n\t\t    \"    ATTENTION: These are potential startpoints.\\n               The total number of startpoints will be bounded by the \\\"Num\\\"-parameter.\\n \\n \\n \\n\"\n\t\t$text insert end \\\n\t\t    \"Settings Menu\\n \\n\" bold\n\t\t$text insert end \\\n\t\t    \"rel. Length\\n    The maximal length of a fieldline relative to the diameter of the geometry.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"max. Points\\n    The maximum number of Runge-Kutta steps.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"rel. Thickness\\n    The thickness of the fieldlines relative to the diameter of the geometry.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"rel. Tolerance\\n    The tolerance for the step-length control of the Runge-Kutta method.\\n\\n\"\n\t\t$text insert end \\\n\t\t    \"RK-Type\\n    Which Runge-Kutta scheme to use\\n \\n \\n \\n\"\n\t\t$text insert end \\\n\t\t    \"Button \\\"Build Fieldlines\\\"\\n\" bold\n\t\t$text insert end \\\n\t\t    \"    Build the fieldlines.\"\n\t\t\n\n\t\t$text configure -state disabled\n\n\t\tpack .fieldlines_help.ht -expand yes -fill both\n\n\t\twm withdraw .fieldlines_help\n\t\twm geom .fieldlines_help +300+200\n\t\twm deiconify .fieldlines_help\n\t\twm title .fieldlines_help \"Fieldlines Help\"\n\t\tfocus .fieldlines_help\n\t\t\n\t    }\n\n\n\t}\n\n\tttk::button $w.bu.cancel -text \"Done\" -command \"destroy $w\"\n\tgrid $w.bu.calc $w.bu.help $w.bu.cancel -sticky nw -padx 4\n        grid anchor $w.bu center\n\t\n\t\n\twm withdraw $w\n\twm geom $w +200+100\n\twm deiconify $w\n\twm title $w \"Fieldlines\"\n\t#    grab $w\n\tfocus $w\n\n    }\n\n    global visoptions.fieldlinesstartface\n\n    \n    set f $w.nb.draw\n    set visoptions.fieldlinesstartface [Ng_BCProp getactive]\n    $f.facesettings.index.ent configure -text ${visoptions.fieldlinesstartface}\n\n}\n\n\n#proc popupcheckredraw { vari { x 0 } } {\n#    upvar $vari varname\n#    if { $varname == 1 } {\n#\tset varname 0\n#    } {\n#\tNg_Vis_Set parameters\n#\tredraw\n#    }\n#}\n\n\nset visual_dialog_pop1 0\nset visual_dialog_pop2 0\nset visual_dialog_pop3 0\nset visual_dialog_pop4 0\nset visual_dialog_pop5 0\nset visual_dialog_pop6 0\nset visual_dialog_pop7 0\n\nproc visual_dialog { } {\n\n    set w .visoptions_dlg\n\n    global visual_dialog_pop1\n    global visual_dialog_pop2\n    global visual_dialog_pop3\n    global visual_dialog_pop4\n    global visual_dialog_pop5\n    global visual_dialog_pop6\n    global visual_dialog_pop7\n    set visual_dialog_pop1 1\n    set visual_dialog_pop2 1\n    set visual_dialog_pop3 1\n    set visual_dialog_pop4 1\n    set visual_dialog_pop5 1\n    set visual_dialog_pop6 1\n    set visual_dialog_pop7 1\n   \n    if {[winfo exists .visoptions_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w\n    } {\n\n\ttoplevel $w \n        \n\t#ttk::frame $w.grid -relief groove -borderwidth 0\n\t# change to: max gridsize 200\n\t#scale $w.grid.size -orient horizontal -length 100 -from 1 -to 200 \\\n\t    -label \"Grid\" \\\n\t    -resolution 1    \\\n\t    -variable  visoptions.gridsize \\\n\t    -command { popupcheckredraw visual_dialog_pop2 }\n        \n\n\t# x- and y- offset\n\t#scale $w.grid.xoffset -orient horizontal -length 80 -from 0 -to 1 \\\n\t    -label \"x-Offset\" \\\n\t    -resolution 0.05    \\\n\t    -variable  visoptions.xoffset \\\n\t    -command { popupcheckredraw visual_dialog_pop3 }\n        ttk::frame $w.main\n        pack $w.main -fill x \n        set w $w.main\n        ttk::frame $w.upperfr ;# -relief groove -borderwidth 3 -height 10\n        pack $w.upperfr -fill x;# -ipady 8\n        \n        ttk::labelframe $w.upperfr.size -text \"Grid\" -relief groove -borderwidth 3\n        ttk::entry $w.upperfr.size.ent -width 3 -textvariable visoptions.gridsize -validate focus -takefocus 0 -validatecommand \"popupcheckredraw visual_dialog_pop2;my_validate %W 0 200 %P 0\" \\\n            -invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop2\"\n        ttk::scale $w.upperfr.size.sc -orient horizontal -length 100 -from 1 -to 200 -variable visoptions.gridsize\\\n            -command \"roundscale $w.upperfr.size.sc 0;popupcheckredraw visual_dialog_pop2\"\n\n        ttk::labelframe $w.upperfr.offsets -text \"x / y offsets\" -relief groove -borderwidth 3\n        ttk::label $w.upperfr.offsets.xlab -text \"x\"\n        ttk::label $w.upperfr.offsets.ylab -text \"y\"\n        ttk::scale $w.upperfr.offsets.xoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.xoffset \\\n            -command \"roundscale $w.upperfr.offsets.xoffset 2; popupcheckredraw visual_dialog_pop3\"\n        ttk::scale $w.upperfr.offsets.yoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.yoffset \\\n            -command \"roundscale $w.upperfr.offsets.yoffset 2; popupcheckredraw visual_dialog_pop4\"\n        ttk::entry $w.upperfr.offsets.entx -width 4 -textvariable visoptions.xoffset -validate focus -takefocus 0 \\\n            -validatecommand \"popupcheckredraw visual_dialog_pop3;my_validate %W 0 1 %P 2\" \\\n            -invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop3\"\n        ttk::entry $w.upperfr.offsets.enty -width 4 -textvariable visoptions.yoffset -validate focus -takefocus 0 \\\n            -validatecommand \"popupcheckredraw visual_dialog_pop4;my_validate %W 0 1 %P 2\" \\\n            -invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop4\"\n\n\t# pack $w.showclipsolution \n        \n        pack $w.upperfr.size.sc $w.upperfr.size.ent -padx 4  -pady 12 -side left\n        grid $w.upperfr.offsets.xoffset $w.upperfr.offsets.entx $w.upperfr.offsets.xlab -sticky nw -padx 4\n        grid $w.upperfr.offsets.yoffset $w.upperfr.offsets.enty $w.upperfr.offsets.ylab -sticky nw -padx 4\n\tgrid $w.upperfr.size $w.upperfr.offsets -sticky nw -pady 7 -padx 10\n        grid anchor $w.upperfr center\n\t\n\n\n\n\t#\tpack $w.lineartexture $w.numcols \n\n\n\n\tttk::labelframe $w.deform -relief groove -borderwidth 3 -text \"Deformation settings\"\n\tttk::checkbutton $w.deform.cb -text \"Deformation\" \\\n\t    -variable visoptions.deformation \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n        ttk::label $w.deform.l -text \"Scale: \"\n        ttk::spinbox $w.deform.sc1 -from 0 -to 1e99 -textvariable visoptions.scaledeform1 -width 5 \\\n            -command { Ng_Vis_Set parameters; redraw } \\\n            -validate focusout -validatecommand { Ng_Vis_Set parameters; redraw; string is double %P } \\\n            -invalidcommand { puts \"invalid value, %P %s\"; set visoptions.scaledeform1 1; }\n        \n\t# tixControl $w.deform.sc1 -label \"Scale: \" -integer false \\\n\t#     -variable visoptions.scaledeform1 \\\n\t#     -command { Ng_Vis_Set parameters; redraw } \\\n\t#     -options {\n\t# \tentry.width 6\n\t# \tlabel.width 7\n\t# \tlabel.anchor e\n\t#     }\t\n\n\tttk::scale $w.deform.sc2 -orient horizontal -length 100 -from 0 -to 1 \\\n\t    -variable  visoptions.scaledeform2 \\\n\t    -command { popupcheckredraw visual_dialog_pop5 }\n\n\tpack $w.deform -fill x -ipady 2 -pady 4 -ipady 3\n\tgrid $w.deform.cb $w.deform.l $w.deform.sc1 $w.deform.sc2 -sticky nw -padx 4;# -side left -expand yes -anchor center -padx 4\n\tgrid anchor $w.deform center\n        grid columnconfigure $w.deform 0 -pad 20\n        grid columnconfigure $w.deform 2 -pad 20\n\n\tttk::labelframe $w.as -relief groove -borderwidth 3 -text \"Scaling options\"     \n\tttk::checkbutton $w.as.autoscale -text \"Autoscale\" \\\n\t    -variable visoptions.autoscale \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n        ttk::label $w.as.lmin -text \"Min-value\"\n        ttk::spinbox $w.as.smin -textvariable visoptions.mminval -width 5 -validate focus \\\n            -validatecommand \"my_validatespinbox %W %P 10\" \\\n            -command \"Ng_Vis_Set parameters; redraw;\" \\\n            -invalidcommand \"my_invalidspinbox %W\" -from -1e10 -to 1e10 -increment 0.001\n            \n        ttk::label $w.as.lmax -text \"Max-value\"\n        ttk::spinbox $w.as.smax -textvariable visoptions.mmaxval -width 5 -validate focus \\\n            -validatecommand \"Ng_Vis_Set parameters; redraw;my_validatespinbox %W %P 10\" \\\n            -command \"Ng_Vis_Set parameters; redraw;\" \\\n            -invalidcommand \"my_invalidspinbox %W;Ng_Vis_Set parameters; redraw\" -from -1e10 -to 1e10 -increment 0.001\n\n\n        ttk::label $w.as.lncols -text \"N Colors\"\n\tttk::spinbox $w.as.snumcols -textvariable visoptions.numtexturecols -width 5 -validate focus \\\n            -command \"Ng_Vis_Set parameters; redraw;\" \\\n            -from 2 -to 31 -increment 1\n\n            \n        #tixControl $w.as.minval -label \"Min-value: \" -integer false \\\n\t    -variable visoptions.mminval \\\n\t    -command { Ng_Vis_Set parametersrange; redraw } \\\n\t    -options {\n\t#\tentry.width 6\n\t#\tlabel.width 12\n\t#\tlabel.anchor e\n\t#    }\t\n\t#tixControl $w.as.maxval -label \"Max-value: \" -integer false \\\n\t    -variable visoptions.mmaxval \\\n\t    -command { Ng_Vis_Set parametersrange; redraw } \\\n\t    -options {\n\t#\tentry.width 6\n\t#\tlabel.width 12\n\t#\tlabel.anchor e\n\t#    }\t\n\n\tpack $w.as -fill x -pady 5 -ipady 3\n\tgrid $w.as.autoscale $w.as.lmin $w.as.smin $w.as.lmax $w.as.smax $w.as.lncols $w.as.snumcols -sticky nw -padx 4\n        grid columnconfigure $w.as 0 -pad 20\n        grid columnconfigure $w.as 2 -pad 20\n        grid anchor $w.as center \n\n\n\n\n\tttk::frame $w.iso; #-relief groove -borderwidth 0\n\tpack $w.iso -anchor center;# -ipady 3\n\n\tttk::labelframe $w.iso.cb -relief groove -borderwidth 3 -text \"Iso lines / surfaces\"\n\tpack $w.iso.cb -side left -pady 7 -fill y\n\n\tttk::checkbutton $w.iso.cb.isolines -text \"Iso-lines\" \\\n\t    -variable visoptions.isolines \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\t#pack $w.iso.cb.isolines -side top -anchor w\n\n\tttk::checkbutton $w.iso.cb.isosurf -text \"Iso-Surface\" \\\n\t    -variable visoptions.isosurf \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\t#pack $w.iso.cb.isosurf -side top -anchor w\n\n        ttk::label $w.iso.cb.numisol -text \"amount\"\n\tttk::scale $w.iso.cb.numiso -orient horizontal -length 100 -from 2 -to 50 \\\n\t    -variable  visoptions.numiso \\\n\t    -command \"roundscale $w.iso.cb.numiso 0;popupcheckredraw visual_dialog_pop6\"\n        ttk::entry $w.iso.cb.entry -textvariable visoptions.numiso -width 3 \\\n            -validate focus -validatecommand \"popupcheckredraw visual_dialog_pop6;\\\n            my_validate %W [$w.iso.cb.numiso cget -from] [$w.iso.cb.numiso cget -to] %P 0\" \\\n            -invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop6\"\n\t    # -resolution 1    \\\n\t    # -label \"\" \\\n        \n        grid $w.iso.cb.isolines $w.iso.cb.numisol $w.iso.cb.entry -sticky nw -padx 4\n        grid $w.iso.cb.isosurf  -sticky nw -padx 4\n        grid $w.iso.cb.numiso  -sticky nw -padx 4 -columnspan 2 -column 1 -row 1 \n\t#pack $w.iso.cb.numisol $w.iso.cb.numiso  -anchor n\n\n\n# \tscale $w.iso.subdiv -orient horizontal -length 100 -from 0 -to 5 \\\n# \t    -label \"subdivision\" \\\n# \t    -resolution 1    \\\n# \t    -variable  visoptions.subdivisions \\\n# \t    -command { popupcheckredraw visual_dialog_pop7  }\n# #\t    -command { puts \"subdiv-vis\"; Ng_Vis_Set parameters; puts \"cal redraw\"; redraw  }\n\n\tttk::labelframe $w.iso.subdiv -text \"Subdivision\" -relief groove -borderwidth 3\n\tttk::radiobutton $w.iso.subdiv.zero -text \"0\" -variable visoptions.subdivisions -value 0 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  1; \n\t\tNg_Vis_Set parameters; redraw;\n\t}\n\tttk::radiobutton $w.iso.subdiv.one -text \"1\" -variable visoptions.subdivisions -value 1 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  1; \n\t\tNg_Vis_Set parameters; redraw;\n\t}\n\tttk::radiobutton $w.iso.subdiv.two -text \"2\" -variable visoptions.subdivisions -value 2 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  2; \n\t\tNg_Vis_Set parameters; redraw;\n\t}\n\tttk::radiobutton $w.iso.subdiv.three -text \"3\" -variable visoptions.subdivisions -value 3 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  3; \n\t\tNg_Vis_Set parameters; redraw;\n\t}\n\tttk::radiobutton $w.iso.subdiv.four -text \"4\" -variable visoptions.subdivisions -value 4 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  4; \n\t\tNg_Vis_Set parameters; redraw;\n\t}\n\tttk::radiobutton $w.iso.subdiv.five -text \"5\" -variable visoptions.subdivisions -value 5 \\\n\t    -command { \n\t\t#set visoptions.subdivisions  5; \n\t\tNg_Vis_Set parameters; redraw;\n\t    }\n\n \tttk::label $w.iso.subdiv.text  -text \"subdivision\"\n\n\tpack $w.iso.subdiv -side right -fill y -padx 4 -pady 7 \n# ; Ng_SetNextTimeStamp\n\t#pack $w.iso.subdiv.text  -side top\n\t#pack $w.iso.subdiv.zero  -side left\n\t#pack $w.iso.subdiv.one   -side left\n\t#pack $w.iso.subdiv.two   -side left\n\t#pack $w.iso.subdiv.three -side left\n\t#pack $w.iso.subdiv.four  -side left\n\t#pack $w.iso.subdiv.five  -side left\n        grid $w.iso.subdiv.zero $w.iso.subdiv.one $w.iso.subdiv.two $w.iso.subdiv.three $w.iso.subdiv.four $w.iso.subdiv.five \n        grid anchor $w.iso.subdiv center\n#\tscale $w.iso.zpos -orient horizontal -length 100 -from 0 -to 1 \\\n#\t    -label \"z-position\" \\\n#\t    -resolution 0.01 \\\n#\t    -variable visoptions.zposition \\\n#\t    -command {\n#\t\tcatch {NGS_Set zpos ${visoptions.zposition};}\n#\t\tredraw }\n#\tpack $w.iso.zpos -side right\n\n\n\n\tttk::labelframe $w.redraw -relief groove -borderwidth 3 -text \"Auto-redraw\"\n\tttk::checkbutton $w.redraw.auto -text \"Auto-redraw after (sec)\" \\\n\t    -variable visoptions.autoredraw \n\n\t# tixControl $w.redraw.val -integer false \\\n\t#     -variable visoptions.autoredrawtime \\\n\t#     -options {\n\t# \tentry.width 6\n\t# \tlabel.width 0\n\t# \tlabel.anchor w\n\t#     }\t\n        ttk::spinbox $w.redraw.val -textvariable visoptions.autoredrawtime -from 0 -to 100 -width 3 \n\tpack $w.redraw -fill x -ipady 3 -pady 7\n\tgrid $w.redraw.auto  $w.redraw.val -sticky nw\n        grid anchor $w.redraw center\n\n\n        ttk::labelframe $w.lowerframe -text \"Additional viewing options\" -relief groove -borderwidth 3\n        pack $w.lowerframe -fill x \n        set w $w.lowerframe \n\n        #pack [frame $w.f] -fill x\n        #pack [ttk::frame $w.f1] -expand yes\n        ttk::frame $w.f1\n        \n        set f [ttk::frame $w.f1.clipsol] \n        pack $f -anchor e\n        menu $f.m\n        ttk::menubutton $f.b -menu $f.m -width 12\n        ttk::label $f.l -text \"Clipping Plane Sol: \"\n        \n        global visoptions.clipsolution        \n        set clipsollabs(none) \"None\"\n        set clipsollabs(scal) \"Scalar Function\"\n        set clipsollabs(vec) \"Vector Function\"\n        foreach i { none scal vec } {\n            set textval $clipsollabs($i)\n            $f.m add command -label \"$textval\" -command \\\n                \"$f.b configure -text \\\"$textval\\\" ; set visoptions.clipsolution $i ; Ng_Vis_Set parameters ; redraw \"                \n        }\n\n        pack $f.b $f.l -side right\n        $f.m invoke $clipsollabs(${visoptions.clipsolution})\n\n        \n        # pack [ttk::frame $w.f1.scalfun] -anchor e\n        set f [ttk::frame $w.f1.scalfun] \n        pack $f -anchor e\n        menu $f.m\n        ttk::menubutton $f.b -menu $f.m -width 12\n        ttk::label $f.l -text \"Scalar Function: \"\n        set scalentries [list none None]\n\n\tfor { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n            set fname [Ng_Vis_Field getfieldname $i]\n            set fcomp [Ng_Vis_Field getfieldcomponents $i]\n            if { $fcomp == 1 } {\n                lappend scalentries $fname:1 $fname\n            } {\n                for { set j 1 } { $j <= $fcomp } { incr j } {\n                    lappend scalentries $fname:$j \"$fname ($j)\"\n                }\n                lappend scalentries $fname:0 \"func ($fname)\"\n            }\n        }\n        global visoptions.scalfunction\n        foreach { name textval } $scalentries {\n            $f.m add command -label \"$textval\" -command \\\n                \"$f.b configure -text \\\"$textval\\\" ; set visoptions.scalfunction \\\"$name\\\" ; Ng_Vis_Set parameters ; redraw ; \"\n        }\n        \n        pack $f.b $f.l -side right\n        foreach { name textval } $scalentries {\n            if { ${visoptions.scalfunction} == $name } {\n                $f.m invoke $textval\n            }\n        }\n        \n\n\n\n        set f [ttk::frame $w.f1.vecfun]\n        pack $f -anchor e\n        menu $f.m\n        ttk::menubutton $f.b -menu $f.m -width 12\n        ttk::label $f.l -text \"Vector Function: \"\n        set vecentries [list none None]\n\n\tfor { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n\t    set fname [Ng_Vis_Field getfieldname $i]\n\t    set fcomp [Ng_Vis_Field getfieldcomponents $i]\n\t    set iscomplex [Ng_Vis_Field iscomplex $i]\n\t    set sdim [Ng_Vis_Field getdimension]\n\t    if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\n\t    if { ($fcomp == $sdim) || ($fcomp == 3) } {\n                lappend vecentries $fname $fname\n\t    } \n        }\n        global visoptions.vecfunction\n        foreach { name textval } $vecentries {\n            $f.m add command -label \"$textval\" -command \\\n                \"$f.b configure -text \\\"$textval\\\" ; set visoptions.vecfunction $name ; Ng_Vis_Set parameters ; redraw ; \"\n        }\n        \n        pack $f.b $f.l -side right\n        foreach { name textval } $vecentries {\n            if { ${visoptions.vecfunction} == $name } {\n                $f.m invoke $textval\n            }\n        }\n        \n\n\n        set f [ttk::frame $w.f1.evaluate]\n        pack $f -anchor e\n\n        menu $f.m\n        ttk::menubutton $f.b -menu $f.m -width 12\n        ttk::label $f.l -text \"Evaluate: \"\n        \n        global visoptions.evaluate        \n        set evallabs(abs) \"| |\"\n        set evallabs(abstens) \"|tensor|\"\n        set evallabs(mises) \"Mises\"\n        set evallabs(main) \"Main\"\n        foreach i { abs abstens mises main } {\n            set textval $evallabs($i)\n            $f.m add command -label \"$textval\" -command \\\n                \"$f.b configure -text \\\"$textval\\\" ; set visoptions.evaluate $i ; \"\n        }\n        pack $f.b $f.l -side right\n        $f.m invoke $evallabs(${visoptions.evaluate})\n\n        \n        \n                \n        pack [ttk::frame $w.f1.multidim] -fill x\n        set f [ttk::frame $w.f1.multidim.f]\n        pack $f -anchor e\n        ttk::label $f.l1 -text \"multidim-component: \"\n        ttk::spinbox $f.sb1 -from 0 -to 1e99 -textvariable visoptions.multidimcomponent -width 3 \\\n            -command { Ng_Vis_Set parameters; redraw }\n        pack $f.l1 $f.sb1 -side left\n\n        ttk::frame $w.fcb\n        # the 2 main frames\n        grid $w.f1 $w.fcb -sticky nw -padx 7 -ipady 3\n        grid anchor $w center\n        \n        #pack $w.fcb \n        ttk::frame $w.fcb.cb\n        pack $w.fcb.cb\n        \n\tttk::checkbutton $w.fcb.cb.showsurfsolution -text \"Draw Surface Vectors\" \\\n\t    -variable visoptions.showsurfacesolution \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\tttk::checkbutton $w.fcb.cb.showcurves -text \"Show Curves\" \\\n\t    -variable visoptions.drawpointcurves \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\tttk::checkbutton $w.fcb.cb.imaginary -text \"Imaginary Part\" \\\n\t    -variable visoptions.imaginary \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\tttk::checkbutton $w.fcb.cb.logscale -text \"Log Scale\" \\\n\t    -variable visoptions.logscale \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\tttk::checkbutton $w.fcb.cb.invcolor -text \"Inverse Color\" \\\n\t    -variable visoptions.invcolor \\\n\t    -command { Ng_Vis_Set parametersrange; redraw }\n\n\n\tttk::frame $w.fcb.cb.texframe\n\n\tttk::checkbutton $w.fcb.cb.texframe.usetexture -text \"Use Textures (\" \\\n\t    -variable visoptions.usetexture \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\t\n\tttk::checkbutton $w.fcb.cb.texframe.lintexture -text \"Linear )\" \\\n\t    -variable visoptions.lineartexture \\\n\t    -command { Ng_Vis_Set parametersrange; redraw }\n\t\n\tttk::checkbutton $w.fcb.cb.lineartexture -text \"Use Linear Texture\" \\\n\t    -variable visoptions.lineartexture \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\tttk::checkbutton $w.fcb.cb.showclipsolution -text \"Draw Clipping Plane Solution\" \\\n\t    -variable visoptions.showclipsolution \\\n\t    -command { Ng_Vis_Set parameters; redraw }\n\n\n\tttk::checkbutton $w.fcb.cb.redrawperiodic -text \"Animate periodic\" \\\n\t    -variable visoptions.redrawperiodic \\\n\t    -command { \n\t\tredrawperiodic\n\t\tNg_Vis_Set parameters; \n\t\tredraw \n\t    }\n\n\t#pack $w.fcb.cb.showsurfsolution $w.fcb.cb.showcurves -anchor w\n\t#pack $w.fcb.cb.imaginary $w.fcb.cb.logscale $w.fcb.cb.texframe $w.fcb.cb.invcolor $w.fcb.cb.redrawperiodic -side top -anchor w\n\t#pack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes\n\tgrid $w.fcb.cb.showsurfsolution -sticky nw\n        grid $w.fcb.cb.showcurves -sticky nw\n\tgrid $w.fcb.cb.imaginary -sticky nw\n        grid $w.fcb.cb.logscale -sticky nw \n        grid $w.fcb.cb.texframe -sticky nw\n        grid $w.fcb.cb.invcolor -sticky nw\n        grid $w.fcb.cb.redrawperiodic -sticky nw\n\tpack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes\n\t\n\n\n        set w .visoptions_dlg.main\n\tttk::frame $w.bu;# -relief groove -borderwidth 3\n\tpack $w.bu  -pady 5 -padx 4\n        \n\tttk::button $w.bu.showsol -text \"Show Solution\" -command { \n\t    set selectvisual solution\n\t    Ng_SetVisParameters\n\t    redraw\n\t}\n\tttk::button $w.bu.clipping -text \"Clipping\" -command { \n\t    clippingdialog; \n\t}\n\tttk::button $w.bu.fieldlines -text \"Fieldlines\" -command { \n\t    fieldlinesdialog; \n\t}\n\n\tttk::button $w.bu.lineplot -text \"2D Lineplot\" -command {\n\t    lineplotdialog;\n\t}\n\n\tttk::button $w.bu.done -text \"Close\" -command { \n\t    destroy .visoptions_dlg\n\t}\n\n\tpack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes \n        set w .visoptions_dlg\n\n\twm withdraw $w\n\twm geom $w +100+100\n\twm deiconify $w\n\twm title $w \"Visualization\"\n\n    }\n}\n\n\n\n# proc reset_visual_dialog { } {\n    \n    # set w .visoptions_dlg\n    \n      # if {[winfo exists .visoptions_dlg] == 1} {\n    \n    \n\t  # destroy $w.scalfun $w.vecfun $w.evaluate $w.multidimcomp\n\t  # destroy $w.imaginary $w.logscale $w.texframe.usetexture $w.texframe.lintexture\n          # destroy $w.texframe\n          # destroy $w.invcolor $w.redrawperiodic\n\t  # destroy $w.bu  -pady 5\n\t  # destroy $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes\n\t  \n\t  \n\t  # checkbutton $w.imaginary -text \"Imaginary Part\" \\\n\t      # -variable visoptions.imaginary \\\n\t      # -command { Ng_Vis_Set parameters; redraw }\n\n\t  # frame $w.texframe\n\n\t  # checkbutton $w.texframe.usetexture -text \"Use Textures (\" \\\n\t      # -variable visoptions.usetexture \\\n\t      # -command { Ng_Vis_Set parameters; redraw }\n\n\t  # checkbutton $w.texframe.lintexture -text \"Linear )\" \\\n\t      # -variable visoptions.lineartexture \\\n\t      # -command { Ng_Vis_Set parameters; redraw }\n\n\n\n\t  \n\t  \n\t  # checkbutton $w.invcolor -text \"Inverse Color\" \\\n\t      # -variable visoptions.invcolor \\\n\t      # -command { Ng_Vis_Set parameters; redraw }\n\n\t  # checkbutton $w.logscale -text \"Log Scale\" \\\n\t      # -variable visoptions.logscale \\\n\t      # -command { Ng_Vis_Set parameters; redraw }\n\t  \n\n\t  \n\t  # checkbutton $w.redrawperiodic -text \"Animate periodic\" \\\n\t      # -variable visoptions.redrawperiodic \\\n\t      # -command { \n\t\t  # redrawperiodic\n\t\t  # Ng_Vis_Set parameters; \n\t\t  # redraw \n\t      # }\n\t  \n\n\t# tixOptionMenu $w.scalfun -label \"Scalar Function: \" \\\n\t    # -options {\n\t\t# label.width  18\n\t\t# label.anchor e\n\t\t# menubutton.width 12\n\t    # }\n\n\t# tixOptionMenu $w.vecfun -label \"Vector Function: \" \\\n\t    # -options {\n\t\t# label.width  18\n\t\t# label.anchor e\n\t\t# menubutton.width 12\n\t    # }\n\n\n\n\t# $w.scalfun add command none -label None\n\t# for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n\t    # set fname [Ng_Vis_Field getfieldname $i]\n\t    # set fcomp [Ng_Vis_Field getfieldcomponents $i]\n\t    # if { $fcomp == 1 } {\n\t\t# $w.scalfun add command $fname.1 -label $fname\n\t    # } {\n\t\t# for { set j 1 } { $j <= $fcomp } { incr j } {\n\t\t    # $w.scalfun add command $fname.$j -label \"$fname ($j)\"\n\t\t# }\n\t\t# $w.scalfun add command $fname.0 -label \"func ($fname)\"\n\t    # }\n\t# }\n\n\t# $w.vecfun add command none -label None \n\t# for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n\t    # set fname [Ng_Vis_Field getfieldname $i]\n\t    # set fcomp [Ng_Vis_Field getfieldcomponents $i]\n\t    # set iscomplex [Ng_Vis_Field iscomplex $i]\n\t    # set sdim [Ng_Vis_Field getdimension]\n\t    # if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\n\t    # if { ($fcomp == $sdim) || ($fcomp == 3) } {\n\t\t# $w.vecfun add command $fname -label $fname\n\t    # } \n\t# }\n\n\n\n\t# $w.scalfun configure -variable visoptions.scalfunction \n\t# $w.scalfun configure -command { Ng_Vis_Set parameters; redraw }\n\t# $w.vecfun configure -variable visoptions.vecfunction\n\t# $w.vecfun configure -command { Ng_Vis_Set parameters; redraw }\n\n\n# #\tputs \"sclfunction = ${visoptions.scalfunction}\"\n\n\n\t# tixOptionMenu $w.evaluate -label \"Evaluate: \" \\\n\t    # -options {\n\t\t# label.width  18\n\t\t# label.anchor e\n\t\t# menubutton.width 12\n\t    # }\t\n\t# $w.evaluate add command abs -label \"|.|\"\n\t# $w.evaluate add command abstens -label \"|tensor|\"\n\t# $w.evaluate add command mises -label \"Mises\"\n\t# $w.evaluate add command main  -label \"Main\"\n\t# $w.evaluate configure -variable visoptions.evaluate\n\t# $w.evaluate configure -command { \n\t    # Ng_Vis_Set parameters; \n\t    # redraw \n\t# }\n\n\t# pack $w.scalfun $w.vecfun $w.evaluate\n\n\t# tixControl $w.multidimcomp -label \"multidim-component: \" -integer true \\\n\t    # -variable visoptions.multidimcomponent -min 0 \\\n\t    # -command { Ng_Vis_Set parameters; redraw } \\\n\t    # -options {\n\t\t# entry.width 6\n\t\t# label.width 18\n\t\t# label.anchor e\n\t    # }\t\n\n\n          # pack $w.multidimcomp\n\n          # pack $w.imaginary $w.logscale $w.texframe $w.invcolor $w.redrawperiodic\n          # pack $w.texframe.usetexture $w.texframe.lintexture  -side left -expand yes\n\n\n\t# frame $w.bu\n\t# pack $w.bu  -pady 5\n\n\t# button $w.bu.showsol -text \"Show Solution\" -command { \n\t    # set selectvisual solution\n\t    # Ng_SetVisParameters\n\t    # redraw\n\t# }\n\t# button $w.bu.clipping -text \"Clipping\" -command { \n\t    # clippingdialog; \n\t# }\n\t# button $w.bu.fieldlines -text \"Fieldlines\" -command { \n\t    # fieldlinesdialog; \n\t# }\n\n\t# button $w.bu.lineplot -text \"2D Lineplot\" -command {\n\t    # lineplotdialog;\n\t# }\n\n\t# button $w.bu.done -text \"Close\" -command { \n\t    # destroy .visoptions_dlg\n\t# }\n\n\t# pack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes\n\n\t# wm withdraw $w\n\t# wm deiconify $w\n\n\n      # }\n\n# }\n\n\n\n"
  },
  {
    "path": "ng/occgeom.tcl",
    "content": "if { [catch { load liboccvis[info sharedlibextension] Ng_OCC } result ] } {\n    # puts \"cannot load occ\" \n    # puts \"error: $result\"\n}\n\n\nif { [catch { Ng_OCCCommand isoccgeometryloaded }] } {\n    # dummy \t\n    proc rebuildoccdialog { } { }\n} {\n    puts \"OCC module loaded\"\n    set hasocc yes\n\n\n\n.ngmenu.geometry add separator\n\n.ngmenu.geometry add command -label \"IGES/STEP Topology Explorer/Doctor...\" \\\n    -command { occdialog; }\n\n\n# Philippose - 30/01/2009\n# Add menu item for local face mesh size definition in the \n# TCL Gui\n.ngmenu.geometry add command -label \"Edit Face Mesh Size...\" \\\n    -command { surfacemeshsizedialog }\n\n\n# .ngmenu.geometry add command -label \"OCC Construction\" \\\n    #     -command { Ng_OCCConstruction; }\n\n\n\n\nset entities [ ]\n\n\nproc occdialogbuildtree {} {\n    global entities\n\n    set w .occ_dlg\n    #set hlist [$w.mtre subwidget hlist]\n\n    set entities [Ng_GetOCCData getentities]\n    set nrentities [expr [llength $entities]]\n\n\n    if {$nrentities != 0} {\n    \n\t#$hlist add Topology -itemtype text -text \"Topology\"\n\t\n\t#$hlist add Topology/CompSolids   -itemtype text -text \"Composite Solids\" -data \"Composite Solids\"\n\t#$hlist add Topology/FreeSolids   -itemtype text -text \"Free Solids\" -data \"Free Solids\"\n\t#$hlist add Topology/FreeShells   -itemtype text -text \"Free Shells\" -data \"Free Shells\"\n\t#$hlist add Topology/FreeFaces    -itemtype text -text \"Free Faces\" -data \"Free Faces\"\n\t#$hlist add Topology/FreeWires    -itemtype text -text \"Free Wires\" -data \"Free Wires\"\n\t#$hlist add Topology/FreeEdges    -itemtype text -text \"Free Edges\" -data \"Free Edges\"\n\t#$hlist add Topology/FreeVertices -itemtype text -text \"Free Vertices\" -data \"Free Vertices\"\n    $w.tree insert {Topology} end -id \"CompSolids\" -text \"Composite Solids\"\n    $w.tree insert {Topology} end -id \"FreeSolids\" -text \"Free Solids\"\n    $w.tree insert {Topology} end -id \"FreeShells\" -text \"Free Shells\"\n    $w.tree insert {Topology} end -id \"FreeFaces\" -text \"Free Faces\"\n    $w.tree insert {Topology} end -id \"FreeWires\" -text \"Free Wires\"\n    $w.tree insert {Topology} end -id \"FreeEdges\" -text \"Free Edges\"\n    $w.tree insert {Topology} end -id \"FreeVertices\" -text \"Free Vertices\"\n    \n\t#\t$hlist add SingularEntities -itemtype text -text \"Entities marked as singular\"\n    $w.tree item \"Topology\" -open true\n\tset i [expr 0]\n\twhile {$i < $nrentities} {\n\t    set entity [lindex $entities [expr $i]]\n\t    incr i 1\n\t    set entityname [lindex $entities [expr $i]]\n\t    #$hlist add Topology/$entity -text $entityname -data $entityname\n        set myroot [string range $entity 0 [string last / $entity]-1]\n        $w.tree insert $myroot end -id $entity -text $entityname -value 1\n\t    incr i 1\n\t    #$w.mtre close Topology/$entity\n\t}\n\t\n\t#$w.mtre autosetmode\n\t\n\t#$w.mtre open Topology\n\t#$w.mtre close Topology/CompSolids\n\t#$w.mtre close Topology/FreeSolids\n\t#$w.mtre close Topology/FreeShells\n\t#$w.mtre close Topology/FreeFaces\n\t#$w.mtre close Topology/FreeWires\n\t#$w.mtre close Topology/FreeEdges\n\t#$w.mtre close Topology/FreeVertices\n\t\n\tset i [expr 0]\n\twhile {$i < $nrentities} {\n\t    set entity [lindex $entities [expr $i]]\n\t    #$w.mtre close Topology/$entity\n        $w.tree item $entity -open false\n\t    incr i 2\n\t}\n\t\n\tset faces [Ng_OCCCommand getunmeshedfaceinfo]    \n\tset nrfaces [expr [llength $faces]]\n\tif {$nrfaces >= 2} {\n\t    #$hlist add ErrorFaces -itemtype text -text \"Faces with surface meshing error\"\n        $w.tree insert {} end -id \"ErrorFaces\" -text \"Faces with surface meshing error\"\n\t    #$w.mtre open ErrorFaces\n        $w.tree item ErrorFaces -open true\n\t    set i [expr 0]\n\t    while {$i < $nrfaces} {\n\t\tset entity [lindex $faces [expr $i]]\n        set myroot [string range $entity 0 [string last / $entity]-1]\n        if { [string length $myroot] == 0 } {\n            set myroot \"ErrorFaces\"\n                }\n\t\tincr i 1\n\t\tset entityname [lindex $faces [expr $i]]\n\t\t#$hlist add ErrorFaces/$entity -text $entityname -data $entityname\n        $w.tree insert $myroot end -id $entity -text $entityname -value 0\n\t\tincr i 1\n\t    }\n\t}\n\t\n\n\tset faces [Ng_OCCCommand getnotdrawablefaces]    \n\tset nrfaces [expr [llength $faces]]\n\tif {$nrfaces >= 2} {\n\t    #$hlist add NotDrawableFaces -itemtype text -text \"Faces impossible to visualize\"\n        $w.tree insert {} -id NotDrawableFaces -text \"Faces impossible to visualize\"\n\t    #$w.mtre open NotDrawableFaces\n        $w.tree item NotDrawableFaces -open true\n\t    set i [expr 0]\n\t    while {$i < $nrfaces} {\n\t\tset entity [lindex $faces [expr $i]]\n        set myroot [string range $entity 0 [string last / $entity]-1]\n        if { [string length $myroot ] == 0 } {\n            set myroot NotDrawableFaces\n        }\n\t\tincr i 1\n\t\tset entityname [lindex $faces [expr $i]]\n\t\t#$hlist add NotDrawableFaces/$entity -text $entityname -data $entityname\n        $w.tree insert $myroot end -id $entity -text $entityname -value 0\n\t\tincr i 1\n\t    }\n\t}\n\n\n\t#$w.mtre autosetmode\n\n\tputs \"done\"\n    }\n}\n\n\nproc rebuildoccdialog {} {\n    if {[winfo exists .occ_dlg] == 1} {\n    .occ_dlg.tree delete [.occ_dlg.tree children Topology]\n\t#[.occ_dlg.mtre subwidget hlist] delete all\n\toccdialogbuildtree \n    }\n}\n\nproc checkoccloaded { } {\n    set isoccgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\n    if {$isoccgeometryloaded == 0} {\n\tputs \"no IGES/STEP geometry loaded\"\n\tdestroy .occ_dlg\n    }\n}\n\n#proc setocctolerance { } {\n#    set w .setocctolerance\n#}\n\n\nproc selectentity { entityname } {\n    global entities\n    set nrentities [expr [llength $entities]]\n    set i [expr 0]\n    while {$i < $nrentities} {\n\tset entitylength []\n\tset entity2 [lindex $entities [expr $i]]\n\tincr i 1\n\tset entityname2 [lindex $entities [expr $i]]\n\tincr i 1\n\tset entityname2 [string range $entityname2 0 [expr [string length $entityname]-1]]\n\tif {$entityname == $entityname2} {\n\t    # #set hlist [.occ_dlg.mtre subwidget hlist]\n\t    # #.occ_dlg.mtre open Topology\n        # .occ_dlg.tree item Topology -open true\n        # puts $entity2\n\t    # set slashpos [string last \"/\" $entity2]\n\t    # set entity3 [string range $entity2 0 [expr $slashpos-1]]\n\t    # while {$slashpos != -1} {\n\t\t# #.occ_dlg.mtre open Topology/$entity3\n        # .occ_dlg.tree item $entity3 -open true\n\t\t# puts $entity3\n\t\t# set slashpos [string last \"/\" $entity3]\n\t\t# set entity3 [string range $entity3 0 [expr $slashpos-1]]\n\t    # }\n\t    #$hlist selection clear\n\t    .occ_dlg.tree see $entity2\n\t    .occ_dlg.tree selection set $entity2\n\t} \n    }\t    \n}\n\n\n\nproc occdialog { } {\n    \n    uplevel 1 {\n\n\tglobal entities\n\tset selectvisual geometry\n\tNg_SetVisParameters\n\tredraw\n\n\tset w .occ_dlg\n\t\n\tif {[winfo exists .occ_dlg] == 1} {\n\t    wm withdraw $w\n\t    wm deiconify $w\n\t    focus $w \n\t} {\t\n\t    toplevel $w\n\n        ttk::treeview $w.tree\n        $w.tree insert {} end -id \"Topology\" -text \"Topology\"\n        pack $w.tree -fill both -expand yes\n\t    occdialogbuildtree\n\t            \n        bind $w.tree <Double-1> {\n            set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n            set rootname \"\"\n            if {[.occ_dlg.tree item [.occ_dlg.tree selection] -value] == 1 } {\n                set rootname \"Topology\"\n            }\n\t\t    set spacepos [string first \" \" $entityname]\n\t\t    set entitytype [string range $entityname 0 [expr $spacepos-1]]            \n\t\t    set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n\t\t    set spacepos2 [string first \" \" $helpstring]\n\t\t    set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]            \n\t\t    if {$rootname == \"Topology\"} {\n\t\t\tNg_OCCCommand highlightentity $entitytype $entitynumber\n\t\t\tset selectvisual geometry\n\t\t\tredraw\n\t\t    } {\n\t\t\tset brackpos [string first \" (\" $entityname]\n\t\t\tif {$brackpos != -1} {\n\t\t\t    set entityname [string range $entityname 0 $brackpos]\n\t\t\t}\n\t\t\tselectentity $entityname\n\t\t    }\n            }\n\t    ttk::button $w.cl -text \"Close\" -command {\n\t\tdestroy .occ_dlg\n\t    }\n\t    \n\t    ttk::button $w.show -text \"Show\" -command {\n        set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n\t\tset spacepos [string first \" \" $entityname]\n\t\tset entitytype [string range $entityname 0 [expr $spacepos-1]]\n\t\tset helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n\t\tset spacepos2 [string first \" \" $helpstring]\n\t\tset entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n\n\t\tNg_OCCCommand show $entitytype $entitynumber\n\t\tset selectvisual geometry\n\t\t#\t    Ng_SetVisParameters\n\t\tredraw\n\t    }\n\t    ttk::button $w.hide -text \"Hide\" -command {\n        set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]        \n\t\tset spacepos [string first \" \" $entityname]\n\t\tset entitytype [string range $entityname 0 [expr $spacepos-1]]\n\t\tset helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n\t\tset spacepos2 [string first \" \" $helpstring]\n\t\tset entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n\n\t\tNg_OCCCommand hide $entitytype $entitynumber\n\t\tset selectvisual geometry\n\t\t#\t    Ng_SetVisParameters\n\t\tredraw\n\t    }\n\n\t    ttk::button $w.swaporientation -text \"Swap orientation\" -command {\n        set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]                \n\t\tset spacepos [string first \" \" $entityname]\n\t\tset entitytype [string range $entityname 0 [expr $spacepos-1]]\n\t\tset helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n\t\tset spacepos2 [string first \" \" $helpstring]\n\t\tset entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n\n\t\tNg_OCCCommand swaporientation $entitytype $entitynumber\n\t\tset selectvisual geometry\n\t\t#\t    Ng_SetVisParameters\n\t\tredraw\n        .occ_dlg.tree delete [.occ_dlg.tree children Topology]\n\t\t#[.occ_dlg.mtre subwidget hlist] delete all\n\t\toccdialogbuildtree\t\n\t    }\n\n\t    ttk::button $w.marksingular -text \"Mark/Unmark as singular\" -command {\n        set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n\t\tset spacepos [string first \" \" $entityname]\n\t\tif { $spacepos != 0 } {\n\t\t    set entitytype [string range $entityname 0 [expr $spacepos-1]]\n\t\t    set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n\t\t    set spacepos2 [string first \" \" $helpstring]\n\t\t    if { $spacepos2 != 0 } {\n\t\t\tset entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n\t\t\tputs $entitytype\n            puts $entitynumber\n\t\t\tglobal ismarkedsingular\n\t\t\tNg_OCCCommand marksingular $entitytype $entitynumber\n\t\t\t\t\t\t\n\t\t\tif { $ismarkedsingular == 0 } {\n                .occ_dlg.tree tag remove \"Color\" [.occ_dlg.tree selection]\n\t\t\t} {\n                .occ_dlg.tree tag add \"Color\" [.occ_dlg.tree selection]\n                .occ_dlg.tree tag configure \"Color\" -foreground \"red\"\n                .occ_dlg.tree tag configure \"Color\" -background \"blue\"\n\t\t\t}\n\t\t    }\n\t\t}                \n\t    }\n\n\t    ttk::checkbutton $w.zoomtohighlightedentity -text \"Zoom to highlighted entity\" \\\n\t\t-variable occoptions.zoomtohighlightedentity \\\n\t\t-command {\n\t\t    Ng_SetOCCVisParameters\n\t\t    if { ${occoptions.zoomtohighlightedentity} == 1} {\n\t\t\tset selectvisual geometry\n\t\t\t#\t\t    Ng_SetVisParameters\n\t\t\tNg_OCCCommand redrawstatus 1\n\t\t\tredraw\n\t\t    } {\n\t\t\tNg_OCCCommand redrawstatus 0\n\t\t    }\n\t\t}\n\n\n\n\t    ttk::frame $w.healing -relief groove -borderwidth 3\n\n\t    ttk::button $w.healing.checkentities -text \"Analyze geometry\" -command {\n\t\tset irregent [Ng_OCCCommand findsmallentities]\n\t\tset w .occ_dlg\n\t\tset nritems [expr [llength $irregent]]\n\t\tset i [expr 0]\n        if {$nritems > 0 } {\n            if { [.occ_dlg.tree exists ProblematicEntities] == 1 } {\n                $w.tree delete ProblematicEntities\n            }\n            $w.tree insert {} end -id ProblematicEntities -text \"Problematic Entities\"\n        }\n\t\twhile {$i < $nritems} {\n\t\t    set entity [lindex $irregent [expr $i]]\n\t\t    incr i 1\n\t\t    set entityname [lindex $irregent [expr $i]]\n            #puts $entity\n            #puts $entityname\n            set myroot [string range $entity 0 [string last / $entity]-1]\n            if { [string length $myroot] == 0 } {\n                set myroot ProblematicEntities\n            }\n            $w.tree insert $myroot end -id $entity -text $entityname            \n\t\t    incr i 1\n\t\t}\n        $w.tree item ProblematicEntities -open true\n\t    }\n\n\t    # tixControl $w.healing.tolerance -label \"Healing tolerance: \" -integer false \\\n\t\t# -variable occoptions.tolerance -min 1e-9 -max 1e6 \\\n\t\t# -options {\n\t\t    # entry.width 6\n\t\t    # label.width 25\n\t\t    # label.anchor e\n\t\t# }\t\n        \n        ttk::frame $w.healing.tolerance\n        ttk::label $w.healing.tolerance.label -text \"Healing tolerance: \"\n        ttk::spinbox $w.healing.tolerance.sp -textvariable occoptions.tolerance -width 6 -increment 0.01 -validate focus -validatecommand \"my_validatespinbox %W %P 12\" \\\n        -invalidcommand \"my_invalidspinbox %W\" -from -1e-9 -to 1e6 \n        grid $w.healing.tolerance.label $w.healing.tolerance.sp\n        \n\t    ttk::checkbutton $w.healing.fixsmalledges -text \"Fix small edges\" \\\n\t\t-variable occoptions.fixsmalledges\n\t    \n\t    ttk::checkbutton $w.healing.fixspotstripfaces -text \"Fix spot/strip faces\" \\\n\t\t-variable occoptions.fixspotstripfaces\n\t    \n\t    ttk::checkbutton $w.healing.sewfaces -text \"Sew faces\" \\\n\t\t-variable occoptions.sewfaces\n\t    \n\t    ttk::checkbutton $w.healing.makesolids -text \"Make solids\" \\\n\t\t-variable occoptions.makesolids\n\t    \n\t    ttk::checkbutton $w.healing.splitpartitions -text \"Split partitions\" \\\n\t\t-variable occoptions.splitpartitions\n\t    \n\t    ttk::button $w.healing.heal -text \"Heal geometry\" -command { \n\t\t#.occ_dlg.healing.tolerance.sp invoke\n\t\tNg_OCCCommand shapehealing\n\t\tredraw \n        .occ_dlg.tree delete [.occ_dlg.tree children Topology]        \n\t\t#[.occ_dlg.mtre subwidget hlist] delete all        \n\t\toccdialogbuildtree\n\t    }\n\n\t    pack $w.healing.checkentities\n\n\t    pack $w.healing.tolerance $w.healing.fixsmalledges \\\n\t\t$w.healing.fixspotstripfaces $w.healing.sewfaces \\\n\t\t$w.healing.makesolids $w.healing.splitpartitions -anchor w\n\n\t    pack $w.healing.heal\t\n\n\n\n\n\t    pack $w.show $w.hide\n\n\t    pack $w.zoomtohighlightedentity -anchor w\n\t    #\tpack $w.checkentities\n\t    pack $w.swaporientation\n\t    pack $w.marksingular\n\t    pack $w.healing -fill x\n\t    pack $w.cl\n\t    \n\t    \n\t    wm withdraw $w\n\t    wm geom $w +100+100\n\t    wm deiconify $w\n\t    wm title $w \"IGES/STEP Topology Explorer/Doctor\"\n\t    focus .occ_dlg\n\t}\n    }\n}\n\n\n}"
  },
  {
    "path": "ng/onetcl.cpp",
    "content": "#include <mydefs.hpp>\nDLL_HEADER const char * ngscript[] = {\"\"\n,\"catch {lappend auto_path $env(NETGENDIR) }\\n\"\n,\"catch {lappend auto_path $env(NETGENDIR)/../lib }\\n\"\n,\"if {[catch {Ng_GetCommandLineParameter batchmode} result ]} {\\n\"\n,\"load libnggui[info sharedlibextension] gui\\n\"\n,\"}\\n\"\n,\"set batchmode [Ng_GetCommandLineParameter batchmode]\\n\"\n,\"if {$batchmode==\\\"undefined\\\"} {\\n\"\n,\"if {[catch {package require tkdnd } result ]} {\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set userlevel 3\\n\"\n,\"if { [Ng_GetCommandLineParameter expert]==\\\"defined\\\" } {\\n\"\n,\"set userlevel 3\\n\"\n,\"}\\n\"\n,\"set progname \\\"NETGEN\\\"\\n\"\n,\"set ngdir \\\"\\\"\\n\"\n,\"if { [lsearch [array names env] NETGENDIR] != -1 } {\\n\"\n,\"set ngdir $env(NETGENDIR)\\n\"\n,\"}\\n\"\n,\"if { [string length $ngdir] == 0 } {\\n\"\n,\"set ngdir \\\".\\\"\\n\"\n,\"}\\n\"\n,\"set nguserdir \\\"\\\"\\n\"\n,\"if { [lsearch [array names env] NETGEN_USER_DIR] != -1 } {\\n\"\n,\"set nguserdir $env(NETGEN_USER_DIR)\\n\"\n,\"}\\n\"\n,\"if { [string length $nguserdir] == 0 } {\\n\"\n,\"set nguserdir \\\".\\\"\\n\"\n,\"}\\n\"\n,\"set batchmode [Ng_GetCommandLineParameter batchmode]\\n\"\n,\"set solvemode 0\\n\"\n,\"if { [Ng_GetCommandLineParameter solve] != \\\"undefined\\\" || \\\\\\n\"\n,\"[Ng_GetCommandLineParameter recent] == \\\"defined\\\" } {\\n\"\n,\"set solvemode defined\\n\"\n,\"}\\n\"\n,\"set shellmode [Ng_GetCommandLineParameter shellmode]\\n\"\n,\"if { $shellmode == \\\"defined\\\" } {\\n\"\n,\"set batchmode \\\"defined\\\"\\n\"\n,\"}\\n\"\n,\"if { $batchmode != \\\"defined\\\" } {\\n\"\n,\"catch {\\n\"\n,\"wm withdraw .\\n\"\n,\"wm title . $progname\\n\"\n,\"wm geometry . =850x600\\n\"\n,\"wm minsize . 400 300\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set drawmode rotate\\n\"\n,\"set selectvisual geometry\\n\"\n,\"set dirname .\\n\"\n,\"set loadgeomtypevar \\\"All Geometry types\\\"\\n\"\n,\"set basefilename filename\\n\"\n,\"set meshoptions.fineness 3\\n\"\n,\"set meshoptions.firststep ag\\n\"\n,\"set meshoptions.laststep ov\\n\"\n,\"set options.memory 0\\n\"\n,\"set options.localh 1\\n\"\n,\"set options.delaunay 1\\n\"\n,\"set options.checkoverlap 1\\n\"\n,\"set options.checkoverlappingboundary 0\\n\"\n,\"set options.checkchartboundary 1\\n\"\n,\"set options.startinsurface 0\\n\"\n,\"set options.blockfill 1\\n\"\n,\"set options.debugmode 0\\n\"\n,\"set options.dooptimize 1\\n\"\n,\"set options.parthread 1\\n\"\n,\"set options.elsizeweight 0.2\\n\"\n,\"set options.secondorder 0\\n\"\n,\"set options.elementorder 1\\n\"\n,\"set options.quad 0\\n\"\n,\"set options.try_hexes 0\\n\"\n,\"set options.inverttets 0\\n\"\n,\"set options.inverttrigs 0\\n\"\n,\"set options.autozrefine 0\\n\"\n,\"set options.meshsize 1000\\n\"\n,\"set options.minmeshsize 0\\n\"\n,\"set options.curvaturesafety 2\\n\"\n,\"set options.segmentsperedge 2\\n\"\n,\"set options.meshsizefilename \\\"\\\"\\n\"\n,\"set options.badellimit 175\\n\"\n,\"set options.optsteps2d 3\\n\"\n,\"set options.optsteps3d 5\\n\"\n,\"set options.opterrpow 2\\n\"\n,\"set options.grading 0.5\\n\"\n,\"set options.printmsg 2\\n\"\n,\"set options.parallel_meshing 1\\n\"\n,\"set options.nthreads 4\\n\"\n,\"set debug.slowchecks 0\\n\"\n,\"set debug.debugoutput 0\\n\"\n,\"set debug.haltexistingline 0\\n\"\n,\"set debug.haltoverlap 0\\n\"\n,\"set debug.haltsuccess 0\\n\"\n,\"set debug.haltnosuccess 0\\n\"\n,\"set debug.haltlargequalclass 0\\n\"\n,\"set debug.haltsegment 0\\n\"\n,\"set debug.haltnode 0\\n\"\n,\"set debug.haltface 0\\n\"\n,\"set debug.haltfacenr 0\\n\"\n,\"set debug.haltsegmentp1 0\\n\"\n,\"set debug.haltsegmentp2 0\\n\"\n,\"set geooptions.drawcsg 1\\n\"\n,\"set geooptions.detail 0.001\\n\"\n,\"set geooptions.accuracy 1e-6\\n\"\n,\"set geooptions.facets 20\\n\"\n,\"set geooptions.minx -1000\\n\"\n,\"set geooptions.miny -1000\\n\"\n,\"set geooptions.minz -1000\\n\"\n,\"set geooptions.maxx 1000\\n\"\n,\"set geooptions.maxy 1000\\n\"\n,\"set geooptions.maxz 1000\\n\"\n,\"set viewqualityplot 0\\n\"\n,\"set memuseplot 0\\n\"\n,\"set viewrotatebutton 0\\n\"\n,\"set showsensitivehelp 0\\n\"\n,\"set showhelpline 0\\n\"\n,\"set viewoptions.specpointvlen 0.3\\n\"\n,\"set viewoptions.light.amb 0.3\\n\"\n,\"set viewoptions.light.diff 0.7\\n\"\n,\"set viewoptions.light.spec 1\\n\"\n,\"set viewoptions.light.locviewer 0\\n\"\n,\"set viewoptions.mat.shininess 50\\n\"\n,\"set viewoptions.mat.transp 0.3\\n\"\n,\"set viewoptions.colormeshsize 0\\n\"\n,\"set viewoptions.whitebackground 1\\n\"\n,\"set viewoptions.drawcoordinatecross 1\\n\"\n,\"set viewoptions.drawcolorbar 1\\n\"\n,\"set viewoptions.drawnetgenlogo 1\\n\"\n,\"set viewoptions.stereo 0\\n\"\n,\"set viewoptions.shrink 1\\n\"\n,\"set viewoptions.drawfilledtrigs 1\\n\"\n,\"set viewoptions.drawedges 0\\n\"\n,\"set viewoptions.drawbadels 0\\n\"\n,\"set viewoptions.centerpoint 0\\n\"\n,\"set viewoptions.drawelement 0\\n\"\n,\"set viewoptions.drawoutline 1\\n\"\n,\"set viewoptions.drawtets 0\\n\"\n,\"set viewoptions.drawtetsdomain 0\\n\"\n,\"set viewoptions.drawprisms 0\\n\"\n,\"set viewoptions.drawpyramids 0\\n\"\n,\"set viewoptions.drawhexes 0\\n\"\n,\"set viewoptions.drawidentified 0\\n\"\n,\"set viewoptions.drawpointnumbers 0\\n\"\n,\"set viewoptions.drawedgenumbers 0\\n\"\n,\"set viewoptions.drawfacenumbers 0\\n\"\n,\"set viewoptions.drawelementnumbers 0\\n\"\n,\"set viewoptions.drawsegmentnumbers 0\\n\"\n,\"set viewoptions.drawsurfaceelementnumbers 0\\n\"\n,\"set viewoptions.drawdomainsurf 0\\n\"\n,\"set viewoptions.drawededges 1\\n\"\n,\"set viewoptions.drawedpoints 1\\n\"\n,\"set viewoptions.drawedpointnrs 0\\n\"\n,\"set viewoptions.drawedtangents 0\\n\"\n,\"set viewoptions.drawededgenrs 0\\n\"\n,\"set viewoptions.drawmetispartition 0\\n\"\n,\"set viewoptions.drawcurveproj 0\\n\"\n,\"set viewoptions.drawcurveprojedge 1\\n\"\n,\"set viewoptions.clipping.nx 0\\n\"\n,\"set viewoptions.clipping.ny 1\\n\"\n,\"set viewoptions.clipping.nz 0\\n\"\n,\"set viewoptions.clipping.dist 0\\n\"\n,\"set viewoptions.clipping.dist2 0\\n\"\n,\"set viewoptions.clipping.enable 0\\n\"\n,\"set viewoptions.clipping.onlydomain 0\\n\"\n,\"set viewoptions.clipping.notdomain 0\\n\"\n,\"set viewoptions.usecentercoords 0\\n\"\n,\"set viewoptions.centerx 0\\n\"\n,\"set viewoptions.centery 0\\n\"\n,\"set viewoptions.centerz 0\\n\"\n,\"set viewoptions.drawspecpoint 0\\n\"\n,\"set viewoptions.specpointx 0\\n\"\n,\"set viewoptions.specpointy 0\\n\"\n,\"set viewoptions.specpointz 0\\n\"\n,\"set stloptions.showtrias 0\\n\"\n,\"set stloptions.showfilledtrias 1\\n\"\n,\"set stloptions.showedges 1\\n\"\n,\"set stloptions.showmarktrias 0\\n\"\n,\"set stloptions.showactivechart 0\\n\"\n,\"set stloptions.yangle 30\\n\"\n,\"set stloptions.contyangle 20\\n\"\n,\"set stloptions.edgecornerangle 60\\n\"\n,\"set stloptions.chartangle 15\\n\"\n,\"set stloptions.outerchartangle 70\\n\"\n,\"set stloptions.usesearchtree 0\\n\"\n,\"set stloptions.chartnumber 1\\n\"\n,\"set stloptions.charttrignumber 1\\n\"\n,\"set stloptions.chartnumberoffset 0\\n\"\n,\"set stloptions.atlasminh 0.1\\n\"\n,\"set stloptions.resthsurfcurvfac 2\\n\"\n,\"set stloptions.resthsurfcurvenable 0\\n\"\n,\"set stloptions.resthatlasfac 2\\n\"\n,\"set stloptions.resthatlasenable 1\\n\"\n,\"set stloptions.resthchartdistfac 1.2\\n\"\n,\"set stloptions.resthchartdistenable 1\\n\"\n,\"set stloptions.resthlinelengthfac 0.5\\n\"\n,\"set stloptions.resthlinelengthenable 1\\n\"\n,\"set stloptions.resthcloseedgefac 1\\n\"\n,\"set stloptions.resthcloseedgeenable 1\\n\"\n,\"set stloptions.resthminedgelen 0.01\\n\"\n,\"set stloptions.resthminedgelenenable 1\\n\"\n,\"set stloptions.resthedgeanglefac 1\\n\"\n,\"set stloptions.resthedgeangleenable 0\\n\"\n,\"set stloptions.resthsurfmeshcurvfac 1\\n\"\n,\"set stloptions.resthsurfmeshcurvenable 0\\n\"\n,\"set stloptions.recalchopt 1\\n\"\n,\"set stldoctor.drawmeshededges 1\\n\"\n,\"set stldoctor.geom_tol_fact 0.000001\\n\"\n,\"set stldoctor.useexternaledges 0\\n\"\n,\"set stldoctor.showfaces 0\\n\"\n,\"set stldoctor.conecheck 1\\n\"\n,\"set stldoctor.spiralcheck 1\\n\"\n,\"set stldoctor.selecttrig 0\\n\"\n,\"set stldoctor.selectmode 1\\n\"\n,\"set stldoctor.longlinefact 0\\n\"\n,\"set stldoctor.showexcluded 1\\n\"\n,\"set stldoctor.edgeselectmode 0\\n\"\n,\"set stldoctor.nodeofseltrig 1\\n\"\n,\"set stldoctor.showtouchedtrigchart 0\\n\"\n,\"set stldoctor.showedgecornerpoints 0\\n\"\n,\"set stldoctor.showmarkedtrigs 1\\n\"\n,\"set stldoctor.dirtytrigfact 0.01\\n\"\n,\"set stldoctor.smoothangle 90\\n\"\n,\"set stldoctor.selectwithmouse 1\\n\"\n,\"set stldoctor.showvicinity 0\\n\"\n,\"set stldoctor.vicinity 50\\n\"\n,\"set stldoctor.smoothnormalsweight 0.2\\n\"\n,\"set occoptions.showvolumenr 0\\n\"\n,\"set occoptions.showsurfaces 1\\n\"\n,\"set occoptions.showedges 1\\n\"\n,\"set occoptions.showsolidnr 0\\n\"\n,\"set occoptions.showsolidnr2 0\\n\"\n,\"set occoptions.visproblemfaces 0\\n\"\n,\"set occoptions.zoomtohighlightedentity 0\\n\"\n,\"set occoptions.deflection 1\\n\"\n,\"set occoptions.tolerance 1e-3\\n\"\n,\"set occoptions.fixsmalledges 1\\n\"\n,\"set occoptions.fixspotstripfaces 1\\n\"\n,\"set occoptions.sewfaces 1\\n\"\n,\"set occoptions.makesolids 1\\n\"\n,\"set occoptions.splitpartitions 0\\n\"\n,\"set meshdoctor.active 0\\n\"\n,\"set meshdoctor.markedgedist 1\\n\"\n,\"set status_np 0\\n\"\n,\"set status_ne 0\\n\"\n,\"set status_nse 0\\n\"\n,\"set status_working \\\" \\\"\\n\"\n,\"set status_task \\\" \\\"\\n\"\n,\"set status_percent 0\\n\"\n,\"set status_filename 0\\n\"\n,\"set status_tetqualclasses \\\"10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40\\\"\\n\"\n,\"set exportfiletype \\\"Neutral Format\\\"\\n\"\n,\"set importfiletype \\\"Neutral Format\\\"\\n\"\n,\"set preproc.facenr 0\\n\"\n,\"set preproc.selectmode query\\n\"\n,\"set preproc.numtrig 0\\n\"\n,\"set mem_moveable 0\\n\"\n,\"set multithread_pause 0\\n\"\n,\"set multithread_testmode 0\\n\"\n,\"set multithread_redraw 0\\n\"\n,\"set multithread_drawing 0\\n\"\n,\"set multithread_terminate 0\\n\"\n,\"set multithread_running 0\\n\"\n,\"set level 0\\n\"\n,\"set tablesforoutput {}\\n\"\n,\"set optlist {\\n\"\n,\"options.localh\\n\"\n,\"options.delaunay\\n\"\n,\"options.checkoverlap\\n\"\n,\"options.startinsurface\\n\"\n,\"options.blockfill\\n\"\n,\"options.dooptimize\\n\"\n,\"options.elsizeweight\\n\"\n,\"options.meshsize\\n\"\n,\"options.minmeshsize\\n\"\n,\"options.curvaturesafety\\n\"\n,\"options.optsteps2d\\n\"\n,\"options.optsteps3d\\n\"\n,\"options.secondorder\\n\"\n,\"}\\n\"\n,\"set visoptions.usetexture 1\\n\"\n,\"set visoptions.invcolor 0\\n\"\n,\"set visoptions.imaginary 0\\n\"\n,\"set visoptions.lineartexture 0\\n\"\n,\"set visoptions.numtexturecols 8\\n\"\n,\"set visoptions.showclipsolution 1\\n\"\n,\"set visoptions.showsurfacesolution 0\\n\"\n,\"set visoptions.drawfieldlines 0\\n\"\n,\"set visoptions.drawpointcurves 1\\n\"\n,\"set visoptions.numfieldlines 100\\n\"\n,\"set visoptions.fieldlinesrandomstart 0\\n\"\n,\"set visoptions.fieldlinesstartarea box\\n\"\n,\"set visoptions.fieldlinesstartareap1x 1\\n\"\n,\"set visoptions.fieldlinesstartareap1y 1\\n\"\n,\"set visoptions.fieldlinesstartareap1z 1\\n\"\n,\"set visoptions.fieldlinesstartareap2x 0\\n\"\n,\"set visoptions.fieldlinesstartareap2y 0\\n\"\n,\"set visoptions.fieldlinesstartareap2z 0\\n\"\n,\"set visoptions.fieldlinesstartface -1\\n\"\n,\"set visoptions.fieldlinesfilename none\\n\"\n,\"set visoptions.fieldlinestolerance 0.0005\\n\"\n,\"set visoptions.fieldlinesrktype crungekutta\\n\"\n,\"set visoptions.fieldlineslength 0.5\\n\"\n,\"set visoptions.fieldlinesmaxpoints 500\\n\"\n,\"set visoptions.fieldlinesthickness 0.0015\\n\"\n,\"set visoptions.fieldlinesvecfunction none\\n\"\n,\"set visoptions.fieldlinesphase 0\\n\"\n,\"set visoptions.fieldlinesonlyonephase 1\\n\"\n,\"set visoptions.lineplotfile empty\\n\"\n,\"set visoptions.lineplotsource file\\n\"\n,\"set visoptions.lineplotusingx 0\\n\"\n,\"set visoptions.lineplotusingy 1\\n\"\n,\"set visoptions.lineplotautoscale 1\\n\"\n,\"set visoptions.lineplotxmin 0\\n\"\n,\"set visoptions.lineplotxmax 1\\n\"\n,\"set visoptions.lineplotymin 0\\n\"\n,\"set visoptions.lineplotymax 1\\n\"\n,\"set visoptions.lineplotcurrentnum -1\\n\"\n,\"set visoptions.lineplotinfos \\\"\\\"\\n\"\n,\"set visoptions.lineplotselected none\\n\"\n,\"set visoptions.lineplotselector \\\"\\\"\\n\"\n,\"set visoptions.lineplotcolor red\\n\"\n,\"set visoptions.lineplotsizex 500\\n\"\n,\"set visoptions.lineplotsizey 400\\n\"\n,\"set visoptions.lineplotselectedeval 0\\n\"\n,\"set visoptions.lineplotdatadescr \\\"column1 column2 column3\\\"\\n\"\n,\"set visoptions.lineplotxcoordselector \\\"\\\"\\n\"\n,\"set visoptions.lineplotycoordselector \\\"\\\"\\n\"\n,\"set visoptions.evaluatefilenames none\\n\"\n,\"set visoptions.evaluatefiledescriptions none\\n\"\n,\"set visoptions.clipsolution none\\n\"\n,\"set visoptions.scalfunction none\\n\"\n,\"set visoptions.vecfunction none\\n\"\n,\"set visoptions.evaluate abs\\n\"\n,\"set visoptions.gridsize 20\\n\"\n,\"set visoptions.xoffset 0\\n\"\n,\"set visoptions.yoffset 0\\n\"\n,\"set visoptions.autoscale 1\\n\"\n,\"set visoptions.redrawperiodic 0\\n\"\n,\"set visoptions.logscale 0\\n\"\n,\"set visoptions.mminval 0\\n\"\n,\"set visoptions.mmaxval 1\\n\"\n,\"set visoptions.isolines 0\\n\"\n,\"set visoptions.isosurf 0\\n\"\n,\"set visoptions.subdivisions 1\\n\"\n,\"set visoptions.numiso 10\\n\"\n,\"set visoptions.autoredraw 0\\n\"\n,\"set visoptions.autoredrawtime 2\\n\"\n,\"set visoptions.simulationtime 0\\n\"\n,\"set visoptions.multidimcomponent 0\\n\"\n,\"set visoptions.deformation 0\\n\"\n,\"set visoptions.scaledeform1 1\\n\"\n,\"set visoptions.scaledeform2 1\\n\"\n,\"set parallel_netgen 0\\n\"\n,\"set optfilename [file join $nguserdir ng.opt]\\n\"\n,\"set inifilename [file join $nguserdir ng.ini]\\n\"\n,\"set meshinifilename [file join $nguserdir ngmesh.ini]\\n\"\n,\"global env\\n\"\n,\"if { [llength [array names env NG_OPT]] == 1 } {\\n\"\n,\"if { [string length $env(NG_OPT)] > 0 } {\\n\"\n,\"set optfilename $env(NG_OPT)\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { [file exists $optfilename] == 1 } {\\n\"\n,\"set datei [open $optfilename r]\\n\"\n,\"while { [gets $datei line] >= 0 } {\\n\"\n,\"set [lindex $line 0] [lindex $line 1]\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"} {\\n\"\n,\"puts \\\"optfile $optfilename does not exist - using default values\\\"\\n\"\n,\"}\\n\"\n,\"proc saveoptions { } {\\n\"\n,\"uplevel 1  {\\n\"\n,\"set file $optfilename\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"set datei [open $file w]\\n\"\n,\"puts $datei \\\"dirname  ${dirname}\\\"\\n\"\n,\"puts $datei \\\"loadgeomtypevar  \\\\\\\"${loadgeomtypevar}\\\\\\\"\\\"\\n\"\n,\"puts $datei \\\"exportfiletype  \\\\\\\"${exportfiletype}\\\\\\\"\\\"\\n\"\n,\"puts $datei \\\"meshoptions.fineness  ${meshoptions.fineness}\\\"\\n\"\n,\"puts $datei \\\"meshoptions.firststep ${meshoptions.firststep}\\\"\\n\"\n,\"puts $datei \\\"meshoptions.laststep  ${meshoptions.laststep}\\\"\\n\"\n,\"puts $datei \\\"options.localh  ${options.localh}\\\"\\n\"\n,\"puts $datei \\\"options.delaunay  ${options.delaunay}\\\"\\n\"\n,\"puts $datei \\\"options.checkoverlap  ${options.checkoverlap}\\\"\\n\"\n,\"puts $datei \\\"options.checkchartboundary  ${options.checkchartboundary}\\\"\\n\"\n,\"puts $datei \\\"options.startinsurface  ${options.startinsurface}\\\"\\n\"\n,\"puts $datei \\\"options.blockfill  ${options.blockfill}\\\"\\n\"\n,\"puts $datei \\\"options.debugmode  ${options.debugmode}\\\"\\n\"\n,\"puts $datei \\\"options.dooptimize ${options.dooptimize}\\\"\\n\"\n,\"puts $datei \\\"options.parthread  ${options.parthread}\\\"\\n\"\n,\"puts $datei \\\"options.elsizeweight  ${options.elsizeweight}\\\"\\n\"\n,\"puts $datei \\\"options.secondorder  ${options.secondorder}\\\"\\n\"\n,\"puts $datei \\\"options.elementorder  ${options.elementorder}\\\"\\n\"\n,\"puts $datei \\\"options.quad  ${options.quad}\\\"\\n\"\n,\"puts $datei \\\"options.try_hexes  ${options.try_hexes}\\\"\\n\"\n,\"puts $datei \\\"options.inverttets  ${options.inverttets}\\\"\\n\"\n,\"puts $datei \\\"options.inverttrigs  ${options.inverttrigs}\\\"\\n\"\n,\"puts $datei \\\"options.autozrefine ${options.autozrefine}\\\"\\n\"\n,\"puts $datei \\\"options.meshsize  ${options.meshsize}\\\"\\n\"\n,\"puts $datei \\\"options.minmeshsize  ${options.minmeshsize}\\\"\\n\"\n,\"puts $datei \\\"options.curvaturesafety  ${options.curvaturesafety}\\\"\\n\"\n,\"puts $datei \\\"options.segmentsperedge  ${options.segmentsperedge}\\\"\\n\"\n,\"puts $datei \\\"options.meshsizefilename  ${options.meshsizefilename}\\\"\\n\"\n,\"puts $datei \\\"options.badellimit  ${options.badellimit}\\\"\\n\"\n,\"puts $datei \\\"options.optsteps2d  ${options.optsteps2d}\\\"\\n\"\n,\"puts $datei \\\"options.optsteps3d  ${options.optsteps3d}\\\"\\n\"\n,\"puts $datei \\\"options.opterrpow  ${options.opterrpow}\\\"\\n\"\n,\"puts $datei \\\"options.grading  ${options.grading}\\\"\\n\"\n,\"puts $datei \\\"options.printmsg  ${options.printmsg}\\\"\\n\"\n,\"puts $datei \\\"options.parallel_meshing  ${options.parallel_meshing}\\\"\\n\"\n,\"puts $datei \\\"options.nthreads  ${options.nthreads}\\\"\\n\"\n,\"puts $datei \\\"geooptions.drawcsg  ${geooptions.drawcsg}\\\"\\n\"\n,\"puts $datei \\\"geooptions.detail  ${geooptions.detail}\\\"\\n\"\n,\"puts $datei \\\"geooptions.accuracy  ${geooptions.accuracy}\\\"\\n\"\n,\"puts $datei \\\"geooptions.facets  ${geooptions.facets}\\\"\\n\"\n,\"puts $datei \\\"geooptions.minx  ${geooptions.minx}\\\"\\n\"\n,\"puts $datei \\\"geooptions.miny  ${geooptions.miny}\\\"\\n\"\n,\"puts $datei \\\"geooptions.minz  ${geooptions.minz}\\\"\\n\"\n,\"puts $datei \\\"geooptions.maxx  ${geooptions.maxx}\\\"\\n\"\n,\"puts $datei \\\"geooptions.maxy  ${geooptions.maxy}\\\"\\n\"\n,\"puts $datei \\\"geooptions.maxz  ${geooptions.maxz}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.specpointvlen  ${viewoptions.specpointvlen}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.light.amb  ${viewoptions.light.amb}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.light.diff ${viewoptions.light.diff}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.light.spec ${viewoptions.light.spec}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.light.locviewer ${viewoptions.light.locviewer}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.mat.shininess  ${viewoptions.mat.shininess}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.mat.transp  ${viewoptions.mat.transp}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.colormeshsize ${viewoptions.colormeshsize}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.whitebackground  ${viewoptions.whitebackground}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawcolorbar  ${viewoptions.drawcolorbar}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawcoordinatecross  ${viewoptions.drawcoordinatecross}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawnetgenlogo  ${viewoptions.drawnetgenlogo}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.stereo  ${viewoptions.stereo}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawfilledtrigs  ${viewoptions.drawfilledtrigs}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawedges  ${viewoptions.drawedges}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawbadels  ${viewoptions.drawbadels}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.centerpoint  ${viewoptions.centerpoint}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawelement  ${viewoptions.drawelement}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawoutline  ${viewoptions.drawoutline}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawtets  ${viewoptions.drawtets}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawprisms  ${viewoptions.drawprisms}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawpyramids  ${viewoptions.drawpyramids}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawhexes  ${viewoptions.drawhexes}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawidentified  ${viewoptions.drawidentified}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawpointnumbers  ${viewoptions.drawpointnumbers}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawededges  ${viewoptions.drawededges}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawedpoints  ${viewoptions.drawedpoints}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawedpointnrs  ${viewoptions.drawedpointnrs}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.drawedtangents  ${viewoptions.drawedtangents}\\\"\\n\"\n,\"puts $datei \\\"viewoptions.shrink  ${viewoptions.shrink}\\\"\\n\"\n,\"puts $datei \\\"stloptions.showtrias  ${stloptions.showtrias}\\\"\\n\"\n,\"puts $datei \\\"stloptions.showfilledtrias  ${stloptions.showfilledtrias}\\\"\\n\"\n,\"puts $datei \\\"stloptions.showedges  ${stloptions.showedges}\\\"\\n\"\n,\"puts $datei \\\"stloptions.showmarktrias  ${stloptions.showmarktrias}\\\"\\n\"\n,\"puts $datei \\\"stloptions.showactivechart  ${stloptions.showactivechart}\\\"\\n\"\n,\"puts $datei \\\"stloptions.yangle  ${stloptions.yangle}\\\"\\n\"\n,\"puts $datei \\\"stloptions.contyangle  ${stloptions.contyangle}\\\"\\n\"\n,\"puts $datei \\\"stloptions.edgecornerangle  ${stloptions.edgecornerangle}\\\"\\n\"\n,\"puts $datei \\\"stloptions.chartangle  ${stloptions.chartangle}\\\"\\n\"\n,\"puts $datei \\\"stloptions.outerchartangle  ${stloptions.outerchartangle}\\\"\\n\"\n,\"puts $datei \\\"stloptions.usesearchtree  ${stloptions.usesearchtree}\\\"\\n\"\n,\"puts $datei \\\"stloptions.chartnumber  ${stloptions.chartnumber}\\\"\\n\"\n,\"puts $datei \\\"stloptions.charttrignumber  ${stloptions.charttrignumber}\\\"\\n\"\n,\"puts $datei \\\"stloptions.chartnumberoffset  ${stloptions.chartnumberoffset}\\\"\\n\"\n,\"puts $datei \\\"stloptions.atlasminh  ${stloptions.atlasminh}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthsurfcurvfac  ${stloptions.resthsurfcurvfac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthsurfcurvenable  ${stloptions.resthsurfcurvenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthatlasfac  ${stloptions.resthatlasfac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthatlasenable  ${stloptions.resthatlasenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthchartdistfac  ${stloptions.resthchartdistfac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthchartdistenable  ${stloptions.resthchartdistenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthlinelengthfac  ${stloptions.resthlinelengthfac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthlinelengthenable  ${stloptions.resthlinelengthenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthminedgelen ${stloptions.resthminedgelen}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthminedgelenenable ${stloptions.resthminedgelenenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthcloseedgefac  ${stloptions.resthcloseedgefac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthcloseedgeenable  ${stloptions.resthcloseedgeenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthedgeanglefac  ${stloptions.resthedgeanglefac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthedgeangleenable  ${stloptions.resthedgeangleenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthsurfmeshcurvfac  ${stloptions.resthsurfmeshcurvfac}\\\"\\n\"\n,\"puts $datei \\\"stloptions.resthsurfmeshcurvenable  ${stloptions.resthsurfmeshcurvenable}\\\"\\n\"\n,\"puts $datei \\\"stloptions.recalchopt  ${stloptions.recalchopt}\\\"\\n\"\n,\"puts $datei \\\"visoptions.subdivisions ${visoptions.subdivisions}\\\"\\n\"\n,\"puts $datei \\\"visoptions.autoredraw ${visoptions.autoredraw}\\\"\\n\"\n,\"puts $datei \\\"visoptions.autoredrawtime ${visoptions.autoredrawtime}\\\"\\n\"\n,\"if { [info exists trafooptions.solver] == 1 } {\\n\"\n,\"puts $datei \\\"trafooptions.solver ${trafooptions.solver}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.levels ${trafooptions.levels}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.linits ${trafooptions.linits}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.nonlinits ${trafooptions.nonlinits}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.stabcurrent ${trafooptions.stabcurrent}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.checkcond ${trafooptions.checkcond}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.maxdirect ${trafooptions.maxdirect}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.secondorder ${trafooptions.secondorder}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.homogenizedcore ${trafooptions.homogenizedcore}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.ordercore ${trafooptions.ordercore}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.simplecurrents ${trafooptions.simplecurrents}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.assemblecomplexmatrix ${trafooptions.assemblecomplexmatrix}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.meshcasing  ${trafooptions.meshcasing}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.meshcore    ${trafooptions.meshcore}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.meshclumps  ${trafooptions.meshclumps}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.meshshields ${trafooptions.meshshields}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.meshcoils   ${trafooptions.meshcoils}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.bcmdirectory  ${trafooptions.bcmdirectory}\\\"\\n\"\n,\"puts $datei \\\"trafooptions.lossdensityfile  ${trafooptions.lossdensityfile}\\\"\\n\"\n,\"}\\n\"\n,\"if { [info exists smalltrafomodell.tankheight] == 1 } {\\n\"\n,\"puts $datei \\\"smalltrafomodell.tankheight ${smalltrafomodell.tankheight}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.tankwidth ${smalltrafomodell.tankwidth}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.tanklength ${smalltrafomodell.tanklength}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.corewidth ${smalltrafomodell.corewidth}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.windowheight ${smalltrafomodell.windowheight}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbdistance ${smalltrafomodell.limbdistance}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.xposcore ${smalltrafomodell.xposcore}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.yposcore ${smalltrafomodell.yposcore}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcore ${smalltrafomodell.zposcore}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.leakagefluxguidethickness ${smalltrafomodell.leakagefluxguidethickness}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.leakagefluxguidewidth ${smalltrafomodell.leakagefluxguidewidth}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.leakagefluxguidezposition ${smalltrafomodell.leakagefluxguidezposition}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.1 ${smalltrafomodell.limbcoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.1 ${smalltrafomodell.ricoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.1 ${smalltrafomodell.rocoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.1 ${smalltrafomodell.zposcoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.1 ${smalltrafomodell.heightcoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.1 ${smalltrafomodell.currentcoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.1 ${smalltrafomodell.nturnscoil.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.2 ${smalltrafomodell.limbcoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.2 ${smalltrafomodell.ricoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.2 ${smalltrafomodell.rocoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.2 ${smalltrafomodell.zposcoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.2 ${smalltrafomodell.heightcoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.2 ${smalltrafomodell.currentcoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.2 ${smalltrafomodell.nturnscoil.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.3 ${smalltrafomodell.limbcoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.3 ${smalltrafomodell.ricoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.3 ${smalltrafomodell.rocoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.3 ${smalltrafomodell.zposcoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.3 ${smalltrafomodell.heightcoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.3 ${smalltrafomodell.currentcoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.3 ${smalltrafomodell.nturnscoil.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.4 ${smalltrafomodell.limbcoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.4 ${smalltrafomodell.ricoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.4 ${smalltrafomodell.rocoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.4 ${smalltrafomodell.zposcoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.4 ${smalltrafomodell.heightcoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.4 ${smalltrafomodell.currentcoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.4 ${smalltrafomodell.nturnscoil.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.5 ${smalltrafomodell.limbcoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.5 ${smalltrafomodell.ricoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.5 ${smalltrafomodell.rocoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.5 ${smalltrafomodell.zposcoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.5 ${smalltrafomodell.heightcoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.5 ${smalltrafomodell.currentcoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.5 ${smalltrafomodell.nturnscoil.5}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbcoil.6 ${smalltrafomodell.limbcoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.ricoil.6 ${smalltrafomodell.ricoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rocoil.6 ${smalltrafomodell.rocoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zposcoil.6 ${smalltrafomodell.zposcoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heightcoil.6 ${smalltrafomodell.heightcoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.currentcoil.6 ${smalltrafomodell.currentcoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nturnscoil.6 ${smalltrafomodell.nturnscoil.6}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbtest.1 ${smalltrafomodell.limbtest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heighttest.1 ${smalltrafomodell.heighttest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.widthtest.1 ${smalltrafomodell.widthtest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rtest.1 ${smalltrafomodell.rtest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zpostest.1 ${smalltrafomodell.zpostest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.edgeradiustest.1 ${smalltrafomodell.edgeradiustest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.finetest.1 ${smalltrafomodell.finetest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.conductivetest.1 ${smalltrafomodell.conductivetest.1}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbtest.2 ${smalltrafomodell.limbtest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heighttest.2 ${smalltrafomodell.heighttest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.widthtest.2 ${smalltrafomodell.widthtest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rtest.2 ${smalltrafomodell.rtest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zpostest.2 ${smalltrafomodell.zpostest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.edgeradiustest.2 ${smalltrafomodell.edgeradiustest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.finetest.2 ${smalltrafomodell.finetest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.conductivetest.2 ${smalltrafomodell.conductivetest.2}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbtest.3 ${smalltrafomodell.limbtest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heighttest.3 ${smalltrafomodell.heighttest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.widthtest.3 ${smalltrafomodell.widthtest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rtest.3 ${smalltrafomodell.rtest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zpostest.3 ${smalltrafomodell.zpostest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.edgeradiustest.3 ${smalltrafomodell.edgeradiustest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.finetest.3 ${smalltrafomodell.finetest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.conductivetest.3 ${smalltrafomodell.conductivetest.3}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.limbtest.4 ${smalltrafomodell.limbtest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.heighttest.4 ${smalltrafomodell.heighttest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.widthtest.4 ${smalltrafomodell.widthtest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.rtest.4 ${smalltrafomodell.rtest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.zpostest.4 ${smalltrafomodell.zpostest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.edgeradiustest.4 ${smalltrafomodell.edgeradiustest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.finetest.4 ${smalltrafomodell.finetest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.conductivetest.4 ${smalltrafomodell.conductivetest.4}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.nperitest ${smalltrafomodell.nperitest}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.filename ${smalltrafomodell.filename}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.murlfguide ${smalltrafomodell.murlfguide}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.murtestwire ${smalltrafomodell.murtestwire}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.murcore ${smalltrafomodell.murcore}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.kappalfguide ${smalltrafomodell.kappalfguide}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.kappatestwire ${smalltrafomodell.kappatestwire}\\\"\\n\"\n,\"puts $datei \\\"smalltrafomodell.kappacore ${smalltrafomodell.kappacore}\\\"\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc saveinifile { } {\\n\"\n,\"global inifilename\\n\"\n,\"if {[catch { set datei [open $inifilename w] } result ]} {\\n\"\n,\"puts \\\"cannot write file $inifilename\\\"\\n\"\n,\"} {\\n\"\n,\"for { set i [.ngmenu.file.recent index last] } { $i >= 0 } { incr i -1 } {\\n\"\n,\"puts $datei \\\"recentfile \\\\\\\"[.ngmenu.file.recent entrycget $i -label]\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc savemeshinifile { } {\\n\"\n,\"global meshinifilename\\n\"\n,\"if {[catch { set datei [open $meshinifilename w] } result ]} {\\n\"\n,\"puts \\\"cannot write file $meshinifilename\\\"\\n\"\n,\"} {\\n\"\n,\"for { set i [.ngmenu.file.recentmesh index last] } { $i >= 1 } { incr i -1 } {\\n\"\n,\"puts $datei \\\"recentfile \\\\\\\"[.ngmenu.file.recentmesh entrycget $i -label]\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc loadinifile { } {\\n\"\n,\"global inifilename\\n\"\n,\"if { [file exists $inifilename] == 1 } {\\n\"\n,\"set datei [open $inifilename r]\\n\"\n,\"while { [gets $datei line] >= 0 } {\\n\"\n,\"if {[lindex $line 0] == \\\"recentfile\\\"} {\\n\"\n,\"set filename [lindex $line 1]\\n\"\n,\"if { [file exists $filename] == 1 } {\\n\"\n,\"AddRecentFile $filename\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc loadmeshinifile { } {\\n\"\n,\"global meshinifilename\\n\"\n,\"if { [file exists $meshinifilename] == 1 } {\\n\"\n,\"set datei [open $meshinifilename r]\\n\"\n,\"while { [gets $datei line] >= 0 } {\\n\"\n,\"if {[lindex $line 0] == \\\"recentfile\\\"} {\\n\"\n,\"set filename [lindex $line 1]\\n\"\n,\"if { [file exists $filename] == 1 } {\\n\"\n,\"AddRecentMeshFile $filename\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"close $datei\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set cmdindex {}\\n\"\n,\"set hlpindex {}\\n\"\n,\"set secindex {}\\n\"\n,\"proc setgranularity { gran } {\\n\"\n,\"if {$gran == 6} { return }\\n\"\n,\"set gran [expr $gran - 1]\\n\"\n,\"global options.curvaturesafety\\n\"\n,\"set surfcurvlist { 1 1.5 2 3 5 }\\n\"\n,\"set options.curvaturesafety [lindex $surfcurvlist $gran]\\n\"\n,\"global options.segmentsperedge\\n\"\n,\"set spelist { 0.3 0.5 1 2 3 }\\n\"\n,\"set options.segmentsperedge [lindex $spelist $gran]\\n\"\n,\"global stloptions.resthsurfcurvfac\\n\"\n,\"set surfcurvfaclist { 0.25 0.5 1 1.5 3 }\\n\"\n,\"set stloptions.resthsurfcurvfac [lindex $surfcurvfaclist $gran]\\n\"\n,\"global stloptions.resthchartdistfac\\n\"\n,\"set chartdistfaclist { 0.8 1 1.5 2 5 }\\n\"\n,\"set stloptions.resthchartdistfac [lindex $chartdistfaclist $gran]\\n\"\n,\"global stloptions.resthlinelengthfac\\n\"\n,\"set linelengthfaclist { 0.2 0.35 0.5 1.5 3 }\\n\"\n,\"set stloptions.resthlinelengthfac [lindex $linelengthfaclist $gran]\\n\"\n,\"global stloptions.resthcloseedgefac\\n\"\n,\"set closeedgefaclist { 0.5 1 2 3.5 5 }\\n\"\n,\"set stloptions.resthcloseedgefac [lindex $closeedgefaclist $gran]\\n\"\n,\"global stloptions.resthminedgelen\\n\"\n,\"set minedgelenlist { 0.002 0.02 0.2 1.0 2.0 5.0 10.0 }\\n\"\n,\"set stloptions.resthminedgelen [lindex $minedgelenlist $gran]\\n\"\n,\"global stloptions.resthedgeanglefac\\n\"\n,\"set edgeanglefaclist { 0.25 0.5 1 1.5 3 }\\n\"\n,\"set stloptions.resthedgeanglefac [lindex $edgeanglefaclist $gran]\\n\"\n,\"global stloptions.resthsurfmeshcurvfac\\n\"\n,\"set surfmeshcurvlist { 1 1.5 2 3 5 }\\n\"\n,\"set stloptions.resthsurfmeshcurvfac [lindex $surfmeshcurvlist $gran]\\n\"\n,\"global options.grading\\n\"\n,\"set gradinglist { 0.7 0.5 0.3 0.2 0.1 }\\n\"\n,\"set options.grading [lindex $gradinglist $gran]\\n\"\n,\"}\\n\"\n,\"if { $batchmode != \\\"defined\\\" } {\\n\"\n,\"catch {\\n\"\n,\"if { $tcl_platform(os) eq \\\"Linux\\\" && [tk scaling] > 1.5 } {\\n\"\n,\"font create ngFont -family Helvetica\\n\"\n,\"option add *font ngFont\\n\"\n,\"ttk::style configure \\\".\\\" -font ngFont\\n\"\n,\"}\\n\"\n,\"menu .ngmenu -tearoff 0  -relief raised -bd 2\\n\"\n,\". configure -menu .ngmenu\\n\"\n,\".ngmenu add cascade -label \\\"File\\\" -menu .ngmenu.file -underline 0\\n\"\n,\".ngmenu add cascade -label \\\"Geometry\\\" -menu .ngmenu.geometry -underline 0\\n\"\n,\".ngmenu add cascade -label \\\"Mesh\\\" -menu .ngmenu.mesh -underline 0\\n\"\n,\".ngmenu add cascade -label \\\"View\\\" -menu .ngmenu.view -underline 0\\n\"\n,\".ngmenu add cascade -label \\\"Refinement\\\" -menu .ngmenu.meshsize -underline 5\\n\"\n,\"if { $userlevel == 3} {\\n\"\n,\".ngmenu add cascade -label \\\"Special\\\" -menu .ngmenu.special -underline 3\\n\"\n,\"}\\n\"\n,\".ngmenu add cascade -label \\\"Help\\\" -menu .ngmenu.help -underline 0\\n\"\n,\"menu .ngmenu.file\\n\"\n,\".ngmenu.file add command -label \\\"Load Geometry...\\\" -accelerator \\\"<l><g>\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"All Geometry types\\\"   { .stl .stlb .step .stp .geo .in2d .igs .iges .brep .sat} }\\n\"\n,\"{\\\"IGES Geometry\\\"\t{.igs .iges} }\\n\"\n,\"{\\\"BREP OpenCascade Geometry\\\"    {.brep} }\\n\"\n,\"{\\\"STL Geometry\\\"        {.stl} }\\n\"\n,\"{\\\"Binary STL Geometry\\\"    {.stlb} }\\n\"\n,\"{\\\"STEP Geometry\\\"    {.step .stp} }\\n\"\n,\"{\\\"Geometry file\\\"       {.geo} }\\n\"\n,\"{\\\"2D Geometry\\\"   {.in2d } }\\n\"\n,\"}\\n\"\n,\"set ACISavailable [Ng_ACISCommand isACISavailable]\\n\"\n,\"if {$ACISavailable == \\\"yes\\\" } {\\n\"\n,\"lappend types {\\\"ACIS Geometry\\\" {.sat} }\\n\"\n,\"}\\n\"\n,\"if {[catch {\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -initialdir $dirname -typevariable loadgeomtypevar]\\n\"\n,\"}]} {\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -initialdir $dirname]\\n\"\n,\"}\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"AddRecentFile $file\\n\"\n,\"Ng_LoadGeometry $file\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"set selectvisual geometry\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"wm title . [concat \\\"$progname - \\\" $file]\\n\"\n,\"set dirname [file dirname $file]\\n\"\n,\"set basefilename [file tail [file rootname $file]]\\n\"\n,\"if { $hasocc == \\\"yes\\\" } {\\n\"\n,\"rebuildoccdialog\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add command -label \\\"Save Geometry...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set occgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\\n\"\n,\"puts $occgeometryloaded\\n\"\n,\"if {$occgeometryloaded == 1 } {\\n\"\n,\"set types {\\n\"\n,\"{\\\"IGES Geometry file\\\"   {.igs} }\\n\"\n,\"{\\\"STEP Geometry file\\\"   {.stp} }\\n\"\n,\"{\\\"STL Geometry file\\\"   {.stl} }\\n\"\n,\"{\\\"STL BIN Geometry file\\\"   {.stlb} }\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"set types {\\n\"\n,\"{\\\"STL Geometry file\\\"   {.stl} }\\n\"\n,\"{\\\"STL BIN Geometry file\\\"   {.stlb} }\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set ACISavailable [Ng_ACISCommand isACISavailable]\\n\"\n,\"puts $ACISavailable\\n\"\n,\"if {$ACISavailable == \\\"yes\\\" } {\\n\"\n,\"lappend types {\\\"ACIS Geometry\\\" {.sat} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getSaveFile -filetypes $types -initialdir $dirname -initialfile $basefilename ]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_SaveGeometry $file\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add cascade -label \\\"Recent Files\\\" -menu .ngmenu.file.recent\\n\"\n,\"menu .ngmenu.file.recent -tearoff 0\\n\"\n,\"proc AddRecentFile { filename } {\\n\"\n,\"global progname\\n\"\n,\"global dirname\\n\"\n,\"catch { [.ngmenu.file.recent delete $filename] }\\n\"\n,\".ngmenu.file.recent insert 0 command -label $filename \\\\\\n\"\n,\"-command \\\"AddRecentFile {$filename};\\n\"\n,\"Ng_LoadGeometry {$filename};\\n\"\n,\"Ng_ParseGeometry;\\n\"\n,\"set selectvisual geometry;\\n\"\n,\"Ng_SetVisParameters;\\n\"\n,\"redraw;\\n\"\n,\"wm title . [concat \\\\\\\" $progname - $filename \\\\\\\"];\\n\"\n,\"set dirname {[file dirname $filename]};\\n\"\n,\"set basefilename {[file tail [file rootname $filename]]};\\n\"\n,\"rebuildoccdialog;\\\"\\n\"\n,\"if { [.ngmenu.file.recent index last] >= 6 } {\\n\"\n,\".ngmenu.file.recent delete last }\\n\"\n,\"saveinifile;\\n\"\n,\"}\\n\"\n,\"loadinifile;\\n\"\n,\".ngmenu.file add separator\\n\"\n,\".ngmenu.file add command -label \\\"Load Mesh...\\\" -accelerator \\\"<l><m>\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Mesh file\\\"   {.vol .vol.gz}\t} }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".vol\\\"]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"AddRecentMeshFile $file;\\n\"\n,\"Ng_LoadMesh $file;\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"wm title . [concat \\\"$progname - \\\" $file]\\n\"\n,\"set dirname [file dirname $file]\\n\"\n,\"set basefilename [file tail [file rootname $file]]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add cascade -label \\\"Recent Meshes\\\" -menu .ngmenu.file.recentmesh\\n\"\n,\"menu .ngmenu.file.recentmesh\\n\"\n,\"proc AddRecentMeshFile { filename } {\\n\"\n,\"global progname\\n\"\n,\"global dirname\\n\"\n,\"catch { [.ngmenu.file.recentmesh delete $filename] }\\n\"\n,\".ngmenu.file.recentmesh insert 0 command -label $filename \\\\\\n\"\n,\"-command \\\"AddRecentMeshFile {$filename};\\n\"\n,\"Ng_LoadMesh {$filename};\\n\"\n,\"set selectvisual mesh;\\n\"\n,\"Ng_SetVisParameters;\\n\"\n,\"redraw;\\n\"\n,\"wm title . [concat \\\\\\\" $progname - $filename \\\\\\\"];\\n\"\n,\"set dirname {[file dirname $filename]};\\n\"\n,\"set basefilename {[file tail [file rootname $filename]]};\\n\"\n,\"rebuildoccdialog;\\\"\\n\"\n,\"if { [.ngmenu.file.recentmesh index last] >= 6 } {\\n\"\n,\".ngmenu.file.recentmesh delete last }\\n\"\n,\"savemeshinifile;\\n\"\n,\"}\\n\"\n,\"loadmeshinifile;\\n\"\n,\".ngmenu.file add command -label \\\"Save Mesh...\\\" -accelerator \\\"<s><m>\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Mesh file\\\"   {.vol .vol.gz}\t} }\\n\"\n,\"set file [tk_getSaveFile -filetypes $types -defaultextension \\\".vol.gz\\\" -initialfile $basefilename -initialdir $dirname ]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_SaveMesh $file }\\n\"\n,\"AddRecentMeshFile $file;\\n\"\n,\"}\\n\"\n,\".ngmenu.file add command -label \\\"Merge Mesh...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Mesh file\\\"   {.vol}\t} }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".vol\\\"]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_MergeMesh $file;\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set meshimportformats [Ng_GetImportFormats]\\n\"\n,\".ngmenu.file add command -label \\\"Import Mesh...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"foreach importformat $meshimportformats {\\n\"\n,\"if { [lindex $importformat 0] == $importfiletype } {\\n\"\n,\"set extension [lindex $importformat 1]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set types {\\n\"\n,\"{\\\"Neutral format\\\"  {.mesh .emt} }\\n\"\n,\"{\\\"Surface mesh format\\\"  {.surf} }\\n\"\n,\"{\\\"Universal format\\\"  {.unv} }\\n\"\n,\"{\\\"Olaf format\\\"  {.emt} }\\n\"\n,\"{\\\"TET format\\\" {.tet} }\\n\"\n,\"{\\\"STL format\\\" {.stl .stlb} }\\n\"\n,\"{\\\"Pro/ENGINEER neutral format\\\" {.fnf} }\\n\"\n,\"{\\\"CFD General Notation System\\\" {.cgns} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getOpenFile -filetypes $meshimportformats -typevariable importfiletype]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_ImportMesh $file $importfiletype\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set meshexportformats [Ng_GetExportFormats]\\n\"\n,\".ngmenu.file add command -label \\\"Export Mesh...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"foreach exportformat $meshexportformats {\\n\"\n,\"if { [lindex $exportformat 0] == $exportfiletype } {\\n\"\n,\"set extension [lindex $exportformat 1]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { $exportfiletype == \\\"Elmer Format\\\"} {\\n\"\n,\"set file [file nativename [tk_chooseDirectory -title \\\"Elmer Mesh Export - Select Directory\\\"]]\\n\"\n,\"} elseif { $exportfiletype == \\\"OpenFOAM 1.5+ Format\\\"} {\\n\"\n,\"set file [file nativename [tk_chooseDirectory -title \\\"OpenFOAM 1.5+ Mesh Export - Select Case Directory\\\"]]\\n\"\n,\"} elseif { $exportfiletype == \\\"OpenFOAM 1.5+ Compressed\\\"} {\\n\"\n,\"set file [file nativename [tk_chooseDirectory -title \\\"OpenFOAM 1.5+ Mesh Export - Select Case Directory\\\"]]\\n\"\n,\"} else {\\n\"\n,\"set file [tk_getSaveFile  -filetypes $meshexportformats -typevariable exportfiletype]\\n\"\n,\"puts \\\"type = $exportfiletype\\\"\\n\"\n,\"puts \\\"filename = $file\\\"\\n\"\n,\"}\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_ExportMesh $file $exportfiletype\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add cascade -label \\\"Export Filetype\\\" -menu .ngmenu.file.filetype\\n\"\n,\"menu .ngmenu.file.filetype\\n\"\n,\"foreach exportformat $meshexportformats {\\n\"\n,\".ngmenu.file.filetype add radio -label [lindex $exportformat 0] -variable exportfiletype -command { .ngmenu.file invoke \\\"Export Mesh...\\\" }\\n\"\n,\"}\\n\"\n,\".ngmenu.file add separator\\n\"\n,\".ngmenu.file add command -label \\\"Save Solution...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Solution File\\\"  {.sol} }\\n\"\n,\"{\\\"VTK File\\\"  {.vtk} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getSaveFile -filetypes $types ]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_SaveSolution $file\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add command -label \\\"Import Solution...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types { {\\\"Solution File\\\"  {.sol} } }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".sol\\\"  ]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_ImportSolution $file\\n\"\n,\"set selectvisual solution\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set demostarttime [clock clicks -millisecond]\\n\"\n,\"set stopdemo 0\\n\"\n,\"proc demoredraw { } {\\n\"\n,\"global demostarttime\\n\"\n,\"global stopdemo\\n\"\n,\"set curtime [clock clicks -millisecond]\\n\"\n,\"set result [ Ng_DemoSetTime [expr $curtime - $demostarttime] ]\\n\"\n,\"redraw\\n\"\n,\"global videoactive\\n\"\n,\"if { $videoactive == 1 } {\\n\"\n,\"puts \\\"addframe\\\"\\n\"\n,\"Ng_VideoClip .ndraw addframe\\n\"\n,\"}\\n\"\n,\"if { $result == 0 && $stopdemo == 0 } {\\n\"\n,\"after 1 { demoredraw }\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add command -label \\\"Show Demo...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types { {\\\"Demo File\\\"  {.dem} } }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".dem\\\"  ]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_ShowDemo $file\\n\"\n,\"set demostarttime [clock clicks -millisecond]\\n\"\n,\"set stopdemo 0\\n\"\n,\"demoredraw\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file add separator\\n\"\n,\".ngmenu.file add command -label \\\"Snapshot...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"JPG file\\\" {.jpg} }\\n\"\n,\"{\\\"GIF file\\\" {.gif} }\\n\"\n,\"{\\\"PPM file\\\" {.ppm} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getSaveFile -filetypes $types]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_SnapShot .ndraw $file }\\n\"\n,\"}\\n\"\n,\".ngmenu.file add cascade -label \\\"Video clip\\\" -menu .ngmenu.file.video\\n\"\n,\"menu .ngmenu.file.video\\n\"\n,\"set videoactive 0\\n\"\n,\".ngmenu.file.video add command -label \\\"start...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"MPG file\\\" {.mpg} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getSaveFile -filetypes $types]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_VideoClip .ndraw init $file\\n\"\n,\"global videoactive\\n\"\n,\"set videoactive 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file.video add command -label \\\"add frame...\\\" \\\\\\n\"\n,\"-command {Ng_VideoClip .ndraw addframe }\\n\"\n,\".ngmenu.file.video add command -label \\\"one cycle\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set visoptions.redrawperiodic 1\\n\"\n,\"for { set j 0 } { $j < 100 } { incr j } {\\n\"\n,\"puts \\\"j =  $j\\\"\\n\"\n,\"Ng_Vis_Set time [expr (1000 * $j / 100)]\\n\"\n,\"redraw\\n\"\n,\"Ng_VideoClip .ndraw addframe\\n\"\n,\"after 200\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.file.video add command -label \\\"finalize...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_VideoClip .ndraw finalize\\n\"\n,\"global videoactive\\n\"\n,\"set videoactive 0\\n\"\n,\"}\\n\"\n,\".ngmenu.file add command -label \\\"Save Options\\\" \\\\\\n\"\n,\"-command { saveoptions }\\n\"\n,\".ngmenu.file add separator\\n\"\n,\".ngmenu.file add command -label \\\"Quit\\\" -accelerator \\\"<q>\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"puts \\\"Thank you for using $progname\\\";\\n\"\n,\"if { [catch { unload libngsolve[info sharedlibextension] ngsolve } result ] } {\\n\"\n,\"}\\n\"\n,\"after cancel { timer2 }\\n\"\n,\"Ng_Exit;\\n\"\n,\"destroy .\\n\"\n,\"}\\n\"\n,\"menu .ngmenu.mesh\\n\"\n,\".ngmenu.mesh add command -label \\\"Generate Mesh\\\" -accelerator \\\"<g><m>\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\".ngmenu.mesh add command -label \\\"Stop Meshing\\\" \\\\\\n\"\n,\"-command { Ng_StopMeshing }\\n\"\n,\".ngmenu.mesh add command -label \\\"Meshing Options...\\\" \\\\\\n\"\n,\"-command meshingoptionsdialog\\n\"\n,\".ngmenu.mesh add separator\\n\"\n,\".ngmenu.mesh add command -label \\\"Delete Mesh\\\" \\\\\\n\"\n,\"-command { Ng_New mesh; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.mesh add command -label \\\"Delete Vol Mesh\\\" \\\\\\n\"\n,\"-command { Ng_DeleteVolMesh; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Info\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set dim [Ng_MeshInfo dim]\\n\"\n,\"set np [Ng_MeshInfo np]\\n\"\n,\"set ne [Ng_MeshInfo ne]\\n\"\n,\"set nse [Ng_MeshInfo nse]\\n\"\n,\"set nseg [Ng_MeshInfo nseg]\\n\"\n,\"set bbox [Ng_MeshInfo bbox]\\n\"\n,\"tk_messageBox -message  \\\"Dimension: $dim\\\\nPoints: $np\\\\nElements: $ne\\\\nSurface Els: $nse\\\\nSegments: $nseg\\\\nxmin [lindex $bbox 0] xmax [lindex $bbox 1]\\\\nymin [lindex $bbox 2] ymax [lindex $bbox 3]\\\\nzmin [lindex $bbox 4] zmax [lindex $bbox 5]\\\"\\n\"\n,\"}\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Quality\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set inplanemin 0\\n\"\n,\"set inplanemax 0\\n\"\n,\"set betplanemin 0\\n\"\n,\"set betplanemax 0\\n\"\n,\"Ng_MeshQuality inplanemin inplanemax betplanemin betplanemax\\n\"\n,\"puts \\\"Triangle angles : $inplanemin - $inplanemax\\\"\\n\"\n,\"puts \\\"Tet angles      : $betplanemin - $betplanemax\\\"\\n\"\n,\"tk_messageBox -message  \\\"Triangle angles : $inplanemin - $inplanemax \\\\n Tet angles      : $betplanemin - $betplanemax\\\"\\n\"\n,\"}\\n\"\n,\".ngmenu.mesh add command -label \\\"Check Surface Mesh\\\" \\\\\\n\"\n,\"-command { Ng_CheckSurfaceMesh }\\n\"\n,\".ngmenu.mesh add command -label \\\"Check Volume Mesh\\\" \\\\\\n\"\n,\"-command { Ng_CheckVolumeMesh }\\n\"\n,\".ngmenu.mesh add command -label \\\"Edit Boundary Conditions...\\\" \\\\\\n\"\n,\"-command { bcpropdialog }\\n\"\n,\"if { $userlevel == 3 } {\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Doctor...\\\" \\\\\\n\"\n,\"-command { meshdoctordialog }\\n\"\n,\"}\\n\"\n,\".ngmenu.mesh add command -label \\\"METIS Mesh Partitioning...\\\" \\\\\\n\"\n,\"-command { METISdialog }\\n\"\n,\".ngmenu.mesh add separator\\n\"\n,\".ngmenu.mesh add command -label \\\"Analyze Geometry\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh ag ag; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Edges\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh me me; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Surface\\\" \\\\\\n\"\n,\"-command { set selectvisual mesh; Ng_SetVisParameters; \\\\\\n\"\n,\"Ng_GenerateMesh ms ms; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.mesh add command -label \\\"Optimize Surface\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh os os cmsmSm; redraw }\\n\"\n,\".ngmenu.mesh add cascade -label \\\"Surface Optim. Step\\\" -menu .ngmenu.mesh.surfoptstep\\n\"\n,\"menu .ngmenu.mesh.surfoptstep\\n\"\n,\".ngmenu.mesh.surfoptstep add command -label \\\"Mesh Smoothing\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh os os m; redraw}\\n\"\n,\".ngmenu.mesh.surfoptstep add command -label \\\"Edge swapping (topologic)\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh os os s; redraw}\\n\"\n,\".ngmenu.mesh.surfoptstep add command -label \\\"Edge swapping (metric)\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh os os S; redraw}\\n\"\n,\".ngmenu.mesh.surfoptstep add command -label \\\"Combine points\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh os os c; redraw}\\n\"\n,\".ngmenu.mesh add separator\\n\"\n,\".ngmenu.mesh add command -label \\\"Mesh Volume\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh mv mv; Ng_ReadStatus }\\n\"\n,\".ngmenu.mesh add command -label \\\"Optimize Volume\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh ov ov; Ng_ReadStatus }\\n\"\n,\".ngmenu.mesh add command -label \\\"Smooth Opt Volume\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh ov ov m; Ng_ReadStatus }\\n\"\n,\".ngmenu.mesh add command -label \\\"Smooth Opt Volume Jacobian\\\" \\\\\\n\"\n,\"-command { Ng_GenerateMesh ov ov j; Ng_ReadStatus }\\n\"\n,\"menu .ngmenu.geometry\\n\"\n,\"menu .ngmenu.view\\n\"\n,\".ngmenu.view add command -label \\\"Zoom all\\\" \\\\\\n\"\n,\"-command { Ng_ZoomAll; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"Center\\\" \\\\\\n\"\n,\"-command { Ng_Center; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"x-y plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation xy; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"y-x plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation yx; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"x-z plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation xz; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"z-x plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation zx; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"y-z plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation yz; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"z-y plane\\\" \\\\\\n\"\n,\"-command { Ng_StandardRotation zy; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"Viewing Options...\\\" \\\\\\n\"\n,\"-command { viewingoptionsdialog; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"Clipping Plane...\\\" \\\\\\n\"\n,\"-command { clippingdialog; redraw }\\n\"\n,\".ngmenu.view add command -label \\\"Solution Data...\\\" \\\\\\n\"\n,\"-command { visual_dialog; redraw }\\n\"\n,\".ngmenu.view add checkbutton -variable viewqualityplot \\\\\\n\"\n,\"-label \\\"Quality Plot\\\" \\\\\\n\"\n,\"-command { qualityviewdialog $viewqualityplot }\\n\"\n,\".ngmenu.view add checkbutton -variable memuseplot \\\\\\n\"\n,\"-label \\\"Memory Usage\\\" \\\\\\n\"\n,\"-command { memusedialog $memuseplot }\\n\"\n,\"menu .ngmenu.meshsize\\n\"\n,\".ngmenu.meshsize add command -label \\\"Refine uniform\\\" \\\\\\n\"\n,\"-command { Ng_Refine; Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add command -label \\\"Second Order\\\" \\\\\\n\"\n,\"-command { Ng_SecondOrder; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add command -label \\\"Validate Second Order\\\" \\\\\\n\"\n,\"-command { Ng_ValidateSecondOrder; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add command -label \\\"High Order\\\" \\\\\\n\"\n,\"-command { Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add separator\\n\"\n,\".ngmenu.meshsize add command -label \\\"Refinement Dialog...\\\" \\\\\\n\"\n,\"-command { refinementdialog }\\n\"\n,\".ngmenu.meshsize add command -label \\\"Load Meshsize...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Meshsize file\\\"   {.msz}\t} }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_LoadMeshSize $file;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.meshsize add command -label \\\"MS from Surf Mesh\\\" \\\\\\n\"\n,\"-command { Ng_MeshSizeFromSurfaceMesh }\\n\"\n,\"if { $userlevel == 3 } {\\n\"\n,\".ngmenu.meshsize add command -label \\\"Singular point ms\\\" \\\\\\n\"\n,\"-command { Ng_SingularPointMS; }\\n\"\n,\".ngmenu.meshsize add command -label \\\"Singular edge ms\\\" \\\\\\n\"\n,\"-command { Ng_SingularEdgeMS; }\\n\"\n,\".ngmenu.meshsize add separator\\n\"\n,\"set bisectfilename \\\"\\\";\\n\"\n,\".ngmenu.meshsize add command -label \\\"Bisection\\\" \\\\\\n\"\n,\"-command { Ng_ReadStatus; set oldnp 0; set newnp $status_np;\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"while { $oldnp < $newnp } {\\n\"\n,\"set level [expr $level+1]\\n\"\n,\"if { $bisectfilename == \\\"\\\"} {\\n\"\n,\"Ng_Bisect;\\n\"\n,\"} else {\\n\"\n,\"Ng_Bisect $bisectfilename;\\n\"\n,\"}\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"redraw;\\n\"\n,\"if { $bisectfilename == \\\"\\\"} {\\n\"\n,\"set oldnp $newnp;\\n\"\n,\"set newnp $status_np;\\n\"\n,\"puts \\\"oldnp $oldnp newnp $newnp\\\";\\n\"\n,\"} else {\\n\"\n,\"set oldnp $newnp;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.meshsize add command -label \\\"Load Refinement Info...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Refinement info\\\" {.refine} }}\\n\"\n,\"set bisectfilename [tk_getOpenFile -filetypes $types]\\n\"\n,\"}\\n\"\n,\".ngmenu.meshsize add command -label \\\"Z-Refinement\\\" \\\\\\n\"\n,\"-command { Ng_ZRefinement 2; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add cascade -label \\\"hp-Refinement\\\" -menu .ngmenu.meshsize.hpref\\n\"\n,\"menu .ngmenu.meshsize.hpref\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"1 Level\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 1; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"2 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 2; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"3 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 3; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"4 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 4; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"5 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 5; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"6 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 6; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"7 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 7; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"8 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 8; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"9 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 9; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize.hpref add command -label \\\"10 Levels\\\" \\\\\\n\"\n,\"-command { Ng_HPRefinement 10; Ng_ReadStatus; redraw }\\n\"\n,\".ngmenu.meshsize add command -label \\\"Split to Tets\\\" \\\\\\n\"\n,\"-command { Ng_Split2Tets; Ng_ReadStatus; redraw }\\n\"\n,\"menu .ngmenu.special\\n\"\n,\".ngmenu.special add command -label \\\"Prismatic Boundary Layer\\\" \\\\\\n\"\n,\"-command { Ng_GenerateBoundaryLayer; redraw }\\n\"\n,\".ngmenu.special add command -label \\\"Insert virtual boundary layer\\\" \\\\\\n\"\n,\"-command { Ng_InsertVirtualBL; redraw }\\n\"\n,\".ngmenu.special add command -label \\\"Cut off and combine with other\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types { {\\\"Mesh file\\\"   {.vol}\t} }\\n\"\n,\"set file [tk_getOpenFile -filetypes $types]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_CutOffAndCombine $file;  }\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\".ngmenu.special add command -label \\\"Helmholtz Mesh grading\\\" \\\\\\n\"\n,\"-command { Ng_HelmholtzMesh; }\\n\"\n,\".ngmenu.special add cascade -label \\\"Colour-based boundary conditions\\\" -menu .ngmenu.special.colbndcond\\n\"\n,\"menu .ngmenu.special.colbndcond\\n\"\n,\".ngmenu.special.colbndcond add command -label \\\"Inspect Colours in mesh\\\" \\\\\\n\"\n,\"-command { currmeshcoloursdialog }\\n\"\n,\".ngmenu.special.colbndcond add separator\\n\"\n,\".ngmenu.special.colbndcond add command -label \\\"Automatic Assignment\\\" \\\\\\n\"\n,\"-command { Ng_AutoColourBcProps auto; redraw }\\n\"\n,\".ngmenu.special.colbndcond add separator\\n\"\n,\"set ocffile [file join ${ngdir} netgen.ocf];\\n\"\n,\".ngmenu.special.colbndcond add command -label \\\"Select Colour Profile file\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types { {\\\"Colour Profile file\\\"   {.ocf}   } }\\n\"\n,\"set ocffile [tk_getOpenFile -filetypes $types]\\n\"\n,\"if {$ocffile == \\\"\\\"} {\\n\"\n,\"set ocffile [file join ${ngdir} netgen.ocf]; }\\n\"\n,\"}\\n\"\n,\".ngmenu.special.colbndcond add command -label \\\"Profile based Assignment\\\" \\\\\\n\"\n,\"-command { Ng_AutoColourBcProps profile ${ocffile}; redraw }\\n\"\n,\"menu .ngmenu.help\\n\"\n,\".ngmenu.view add checkbutton -label \\\"Help Line\\\" -variable showhelpline \\\\\\n\"\n,\"-command {\\n\"\n,\"if { $showhelpline == 1} {\\n\"\n,\"pack .helpline -before .statbar -side bottom -fill x -padx 3p\\n\"\n,\"} {\\n\"\n,\"pack forget .helpline\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\".ngmenu.help add command -label \\\"About...\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"tk_messageBox -message \\\"This is NETGEN \\\\nmainly written by \\\\nJoachim Schoeberl \\\\nthanks to \\\\nRobert Gaisbauer, Johannes Gerstmayr, Philippose Rajan\\\"\\n\"\n,\"}\\n\"\n,\"ttk::frame .bubar\\n\"\n,\"pack .bubar -side top -fill x\\n\"\n,\"ttk::button .bubar.testb -text \\\"Test\\\" -command { Ng_SaveGeometry }\\n\"\n,\"ttk::button .bubar.surfm -text \\\"Generate Mesh\\\" -command \\\\\\n\"\n,\"{\\n\"\n,\".ngmenu.mesh invoke \\\"Generate Mesh\\\";\\n\"\n,\"}\\n\"\n,\"ttk::button .bubar.stopm -text \\\"Stop\\\" -command \\\\\\n\"\n,\"{\\n\"\n,\"set multithread_terminate 1;\\n\"\n,\"set stopdemo 1;\\n\"\n,\"}\\n\"\n,\"ttk::button .bubar.exitb -text \\\"Quit\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set ans [tk_messageBox -title \\\"Quit Netgen?\\\" -message \\\"Do you really want to quit Netgen?\\\" -type yesno -default \\\"no\\\" -icon question]\\n\"\n,\"if { $ans == \\\"yes\\\" } {\\n\"\n,\".ngmenu.file invoke \\\"Quit\\\";\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack  .bubar.exitb .bubar.surfm .bubar.stopm -side left\\n\"\n,\"ttk::button .bubar.zoomall -text \\\"Zoom All\\\" \\\\\\n\"\n,\"-command { Ng_ZoomAll; redraw }\\n\"\n,\"ttk::button .bubar.center -text \\\"Center\\\" \\\\\\n\"\n,\"-command { Ng_Center; redraw }\\n\"\n,\"ttk::menubutton .bubar.modesel -menu .bubar.modesel.menu -text \\\"\\\" -width 6\\n\"\n,\"menu .bubar.modesel.menu  -tearoff 0\\n\"\n,\".bubar.modesel.menu add command -label \\\"Rotate\\\" -command \\\"set drawmode \\\\\\\"rotate\\\\\\\" ;.bubar.modesel configure -text \\\\\\\"Rotate\\\\\\\"\\\"\\n\"\n,\".bubar.modesel.menu add command -label \\\"Move\\\" -command \\\"set drawmode \\\\\\\"move\\\\\\\" ;.bubar.modesel configure -text \\\\\\\"Move\\\\\\\"\\\"\\n\"\n,\".bubar.modesel.menu add command -label \\\"Zoom\\\" -command \\\"set drawmode \\\\\\\"zoom\\\\\\\" ;.bubar.modesel configure -text \\\\\\\"Zoom\\\\\\\"\\\"\\n\"\n,\".bubar.modesel.menu invoke \\\"Rotate\\\"\\n\"\n,\"set viewvals { geometry specpoints mesh solution}\\n\"\n,\"if { $userlevel == 3} {\\n\"\n,\"set viewvals { geometry mesh specpoints surfmeshing modelview solution}\\n\"\n,\"}\\n\"\n,\"set viewvallabs(cross)     \\\"Cross\\\"\\n\"\n,\"set viewvallabs(geometry)  \\\"Geometry\\\"\\n\"\n,\"set viewvallabs(mesh)      \\\"Mesh\\\"\\n\"\n,\"set viewvallabs(specpoints) \\\"Edges\\\"\\n\"\n,\"set viewvallabs(surfmeshing) \\\"Mesh Gen\\\"\\n\"\n,\"set viewvallabs(modelview)     \\\"Modeller\\\"\\n\"\n,\"set viewvallabs(solution)     \\\"Solution\\\"\\n\"\n,\"pack .bubar.center .bubar.zoomall -side right\\n\"\n,\".ngmenu.view add checkbutton -variable viewrotatebutton \\\\\\n\"\n,\"-label \\\"Enable LeftButton Selection\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"if { $viewrotatebutton } {\\n\"\n,\"pack .bubar.modesel -side right\\n\"\n,\"} {\\n\"\n,\"pack forget .bubar.modesel\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"menu .bubar.selviewmenu\\n\"\n,\"ttk::menubutton .bubar.selview1 -menu .bubar.selviewmenu -text \\\"Geometry\\\"\\n\"\n,\"foreach viewv $viewvals {\\n\"\n,\".bubar.selviewmenu add command -label $viewvallabs($viewv) -command \\\\\\n\"\n,\"\\\".bubar.selview1 configure -text \\\\\\\"$viewvallabs($viewv)\\\\\\\" ; set selectvisual $viewv ; Ng_SetVisParameters; redraw\\\"\\n\"\n,\"}\\n\"\n,\"pack .bubar.selview1 -side right\\n\"\n,\"trace add variable selectvisual write selvis_monitor\\n\"\n,\"proc selvis_monitor { name args } {\\n\"\n,\"global selectvisual viewvallabs\\n\"\n,\".bubar.selviewmenu invoke $viewvallabs($selectvisual)\\n\"\n,\"}\\n\"\n,\"ttk::label .helpline -text \\\"None\\\"\\n\"\n,\"pack forget .helpline -side bottom -fill x\\n\"\n,\"ttk::frame .statbar -relief flat\\n\"\n,\"pack .statbar -side bottom -fill x\\n\"\n,\"ttk::label .statbar.ptslabel -text \\\"   Points: \\\"\\n\"\n,\"ttk::label .statbar.ptsval -textvariable status_np\\n\"\n,\"ttk::label .statbar.elslabel -text \\\"   Elements: \\\"\\n\"\n,\"ttk::label .statbar.elsval -textvariable status_ne\\n\"\n,\"ttk::label .statbar.selslabel -text \\\"   Surf Elements: \\\"\\n\"\n,\"ttk::label .statbar.selsval -textvariable status_nse\\n\"\n,\"ttk::label .statbar.task -textvariable status_task\\n\"\n,\"pack .statbar.ptslabel .statbar.ptsval -side left -ipady 3p\\n\"\n,\"pack .statbar.elslabel .statbar.elsval -side left -ipady 3p\\n\"\n,\"pack .statbar.selslabel .statbar.selsval -side left -ipady 3p\\n\"\n,\"ttk::progressbar .statbar.per -value 0 -maximum 1\\n\"\n,\"pack .statbar.per -side right\\n\"\n,\"pack .statbar.task -side right -ipady 4\\n\"\n,\"set qualbaraxis(0) 0\\n\"\n,\"set qualbar(0) 0\\n\"\n,\"set qualbarnull(0) 0\\n\"\n,\"proc timer2 { } {\\n\"\n,\"global status_np\\n\"\n,\"global status_ne\\n\"\n,\"global status_nse\\n\"\n,\"global multithread_running\\n\"\n,\"global multithread_redraw\\n\"\n,\"global status_working\\n\"\n,\"global status_task\\n\"\n,\"global status_percent\\n\"\n,\"global status_tetqualclasses\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"if { $multithread_redraw == 1 } {\\n\"\n,\"set multithread_redraw 0;\\n\"\n,\"redraw;\\n\"\n,\"global videoactive\\n\"\n,\"if { $videoactive == 1 } {\\n\"\n,\"puts \\\"addframe\\\"\\n\"\n,\"Ng_VideoClip .ndraw addframe\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { $multithread_redraw == 2 } {\\n\"\n,\"redraw;\\n\"\n,\"set multithread_redraw 0;\\n\"\n,\"global videoactive\\n\"\n,\"if { $videoactive == 1 } {\\n\"\n,\"puts \\\"addframe\\\"\\n\"\n,\"Ng_VideoClip .ndraw addframe\\n\"\n,\"}\\n\"\n,\"after 1 { timer2 }\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\".statbar.per configure -value [expr $status_percent/100]\\n\"\n,\"if { $multithread_running } {\\n\"\n,\"pack .statbar.per -side right -before .statbar.task -padx 6\\n\"\n,\"} {\\n\"\n,\"pack forget .statbar.per\\n\"\n,\"}\\n\"\n,\"if {[winfo exists .qualityview_dlg] == 1} {\\n\"\n,\"global qualbar\\n\"\n,\"global qualbarnull\\n\"\n,\"global qualbaraxis\\n\"\n,\"set maxval 0\\n\"\n,\"for {set i 0} {$i < 20} {incr i} {\\n\"\n,\"if {[lindex $status_tetqualclasses $i] > $maxval} {\\n\"\n,\"set maxval [lindex $status_tetqualclasses $i]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set ubound 1\\n\"\n,\"while { $ubound < $maxval } {\\n\"\n,\"set ubound [expr {10 * $ubound}]\\n\"\n,\"}\\n\"\n,\"if { $ubound/5 > $maxval } {\\n\"\n,\"set ubound [expr $ubound/5]\\n\"\n,\"}\\n\"\n,\"if { $ubound/2 > $maxval } {\\n\"\n,\"set ubound [expr $ubound/2]\\n\"\n,\"}\\n\"\n,\"for {set i 1} {$i <= 5} {incr i} {\\n\"\n,\"set value [expr { $i * $ubound / 5 }]\\n\"\n,\".qualityview_dlg.c dchars $qualbaraxis($i) 0 end\\n\"\n,\".qualityview_dlg.c insert $qualbaraxis($i) end $value\\n\"\n,\"}\\n\"\n,\"for {set i 0} {$i < 20} {incr i} {\\n\"\n,\"set x1 [expr {100 + ($i*15) + 2}]\\n\"\n,\"set x2 [expr {$x1+10}]\\n\"\n,\"set nbrs [lindex $status_tetqualclasses $i]\\n\"\n,\"set y [expr (249 - (200 * $nbrs / $ubound ) )]\\n\"\n,\".qualityview_dlg.c coords $qualbar($i) $x1 250 $x2 $y\\n\"\n,\"if { $nbrs == 0 } {\\n\"\n,\".qualityview_dlg.c itemconfigure $qualbarnull($i) -text 0\\n\"\n,\"} {\\n\"\n,\".qualityview_dlg.c itemconfigure $qualbarnull($i) -text \\\"\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if {[winfo exists .memuse_dlg] == 1} {\\n\"\n,\"global memmark\\n\"\n,\"set usemb [Ng_MemInfo usedmb]\\n\"\n,\"for {set i 0} {$i < [string length $usemb] } {incr i} {\\n\"\n,\"if { [string index $usemb $i] == 0 } {\\n\"\n,\".memuse_dlg.c coords $memmark($i)  [expr 50+$i] 68 [expr 50+$i] 70\\n\"\n,\"} {\\n\"\n,\".memuse_dlg.c coords $memmark($i)  [expr 50+$i] 50 [expr 50+$i] 70\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"after 40 { timer2 }\\n\"\n,\"}\\n\"\n,\"timer2\\n\"\n,\"proc bgerror { error } {\\n\"\n,\"global errorInfo userlevel\\n\"\n,\"if { $userlevel == 3} {\\n\"\n,\"puts \\\"ERROR: $error\\\"\\n\"\n,\"puts \\\"errinfo: $errorInfo\\\"\\n\"\n,\"}\\n\"\n,\"tk_messageBox -title \\\"Error Message\\\" -message $error -type ok\\n\"\n,\"}\\n\"\n,\"proc smh2 { menuitem } {\\n\"\n,\"if {[catch {$menuitem entrycget active -label} name]} {\\n\"\n,\"set name \\\"    \\\"\\n\"\n,\"}\\n\"\n,\"show_menu_help $name\\n\"\n,\"update idletasks\\n\"\n,\"}\\n\"\n,\"bind .ngmenu <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.file <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.geometry <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.mesh <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.view <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.meshsize <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.special <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind .ngmenu.help <<MenuSelect>> { smh2 %W }\\n\"\n,\"bind . <q> { .ngmenu.file invoke \\\"Quit\\\" }\\n\"\n,\"bind . <l><g> { .ngmenu.file invoke \\\"Load Geometry...\\\" }  ;\\n\"\n,\"bind . <l><m> { .ngmenu.file invoke \\\"Load Mesh...\\\" }  ;\\n\"\n,\"bind . <s><m> { .ngmenu.file invoke \\\"Save Mesh...\\\" }  ;\\n\"\n,\"bind . <r><f> { .ngmenu.file activate \\\"Recent Files\\\" }  ;\\n\"\n,\"bind . <n><p> { newprimitivedialog }      ; \\n\"\n,\"bind . <e><p> { editprimitivedialog }\\n\"\n,\"bind . <e><s> { newsoliddialog }\\n\"\n,\"bind . <g><m> { .ngmenu.mesh invoke \\\"Generate Mesh\\\" }  ;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch {\\n\"\n,\"proc meshingoptionsdialog { } {\\n\"\n,\"set w .options_dlg\\n\"\n,\"if {[winfo exists .options_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"pack [ttk::notebook $w.nb]  -fill both -side top\\n\"\n,\"$w.nb add [ttk::frame $w.nb.general] -text \\\"General\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.meshsize] -text \\\"Mesh Size\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.chartopt] -text \\\"STL Charts\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.optimizer] -text \\\"Optimizer\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.debug] -text \\\"Debug\\\" -underline 0\\n\"\n,\"set f $w.nb.general\\n\"\n,\"ttk::frame $f.background\\n\"\n,\"pack $f.background -fill both\\n\"\n,\"set f $f.background\\n\"\n,\"ttk::labelframe $f.f2 -relief groove -borderwidth 3 -text \\\"General meshing options\\\"\\n\"\n,\"pack $f.f2  -pady 15 -fill x\\n\"\n,\"set f $f.f2\\n\"\n,\"set finevals { 1 2 3 4 5 6 }\\n\"\n,\"set finelabs(1) \\\"very coarse\\\"\\n\"\n,\"set finelabs(2) \\\"coarse\\\"\\n\"\n,\"set finelabs(3) \\\"moderate\\\"\\n\"\n,\"set finelabs(4) \\\"fine\\\"\\n\"\n,\"set finelabs(5) \\\"very fine\\\"\\n\"\n,\"set finelabs(6) \\\"user defined\\\"\\n\"\n,\"global meshoptions.fineness\\n\"\n,\"ttk::label  $f.fine2l -text \\\"Mesh granularity: \\\"\\n\"\n,\"ttk::menubutton $f.fine2c -menu $f.fine2m -text \\\"coarse\\\" -width 16\\n\"\n,\"menu $f.fine2m  -tearoff 0\\n\"\n,\"foreach finev { 1 2 3 4 5 6 } {\\n\"\n,\"$f.fine2m add command -label $finelabs($finev) \\\\\\n\"\n,\"-command \\\"set meshoptions.fineness $finev ; setgranularity $finev; $f.fine2c configure -text \\\\\\\"$finelabs($finev)\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$f.fine2m invoke $finelabs(${meshoptions.fineness})\\n\"\n,\"grid $f.fine2l $f.fine2c -sticky nw\\n\"\n,\"set mgsteps { ag me ms os mv ov }\\n\"\n,\"set mgsteplabel(ag) \\\"Analyze Geometry\\\"\\n\"\n,\"set mgsteplabel(me) \\\"Mesh Edges\\\"\\n\"\n,\"set mgsteplabel(ms) \\\"Mesh Surface\\\"\\n\"\n,\"set mgsteplabel(os) \\\"Optimize Surface\\\"\\n\"\n,\"set mgsteplabel(mv) \\\"Mesh Volume\\\"\\n\"\n,\"set mgsteplabel(ov) \\\"Optimize Volume\\\"\\n\"\n,\"global meshoptions.firststep\\n\"\n,\"ttk::label  $f.first2l -text \\\"First Step: \\\"\\n\"\n,\"ttk::menubutton $f.first2c -menu $f.first2m  -width 16\\n\"\n,\"menu $f.first2m  -tearoff 0\\n\"\n,\"foreach i $mgsteps {\\n\"\n,\"$f.first2m add command -label $mgsteplabel($i) -command \\\"set meshoptions.firststep $i ; $f.first2c configure -text \\\\\\\"$mgsteplabel($i)\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$f.first2m invoke $mgsteplabel(${meshoptions.firststep})\\n\"\n,\"grid $f.first2l $f.first2c -sticky nw\\n\"\n,\"global meshoptions.laststep\\n\"\n,\"ttk::label  $f.last2l -text \\\"Last Step: \\\"\\n\"\n,\"ttk::menubutton $f.last2c -menu $f.last2m -width 16\\n\"\n,\"menu $f.last2m  -tearoff 0\\n\"\n,\"foreach i $mgsteps {\\n\"\n,\"$f.last2m add command -label $mgsteplabel($i) -command \\\"set meshoptions.laststep $i ; $f.last2c configure -text \\\\\\\"$mgsteplabel($i)\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$f.last2m invoke $mgsteplabel(${meshoptions.laststep})\\n\"\n,\"grid $f.last2l $f.last2c -sticky nw\\n\"\n,\"grid anchor $f center\\n\"\n,\"set msg(0) \\\"None\\\"\\n\"\n,\"set msg(1) \\\"Least\\\"\\n\"\n,\"set msg(2) \\\"Little\\\"\\n\"\n,\"set msg(3) \\\"Moderate\\\"\\n\"\n,\"set msg(4) \\\"Much\\\"\\n\"\n,\"set msg(5) \\\"Most\\\"\\n\"\n,\"global options.printmsg\\n\"\n,\"ttk::label  $f.msg2l -text \\\"Print Messages: \\\"\\n\"\n,\"menu $f.msg2m  -tearoff 0\\n\"\n,\"ttk::menubutton $f.msg2c -menu $f.msg2m  -width 16\\n\"\n,\"foreach step {0 1 2 3 4 5 } {\\n\"\n,\"$f.msg2m add command -label $msg($step) -command \\\"set options.printmsg $step ; $f.msg2c configure -text $msg($step)\\\"\\n\"\n,\"}\\n\"\n,\"$f.msg2m invoke ${options.printmsg}\\n\"\n,\"grid $f.msg2l $f.msg2c -sticky nw\\n\"\n,\"set f $w.nb.general\\n\"\n,\"ttk::labelframe $f.bts -borderwidth 3 -relief groove -text \\\"Additional meshing options\\\"\\n\"\n,\"pack $f.bts -fill x -pady 15\\n\"\n,\"ttk::frame $f.bts.btnframe\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.parthread -text \\\"Separate meshing thread\\\" \\\\\\n\"\n,\"-variable options.parthread\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.second -text \\\"Second order elements\\\" \\\\\\n\"\n,\"-variable options.secondorder\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.quad -text \\\"Quad dominated\\\" \\\\\\n\"\n,\"-variable options.quad -command {\\n\"\n,\"if { ${options.quad} } {\\n\"\n,\"set meshoptions.laststep os\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.invtets -text \\\"Invert volume elements\\\" \\\\\\n\"\n,\"-variable options.inverttets\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.invtrigs -text \\\"Invert surface elements\\\" \\\\\\n\"\n,\"-variable options.inverttrigs\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.azref -text \\\"Automatic Z-refinement\\\" \\\\\\n\"\n,\"-variable options.autozrefine\\n\"\n,\"pack $f.bts.btnframe -anchor center\\n\"\n,\"pack $f.bts.btnframe.parthread $f.bts.btnframe.second $f.bts.btnframe.quad $f.bts.btnframe.invtets $f.bts.btnframe.invtrigs $f.bts.btnframe.azref -anchor w\\n\"\n,\"ttk::frame $f.bts.btnframe.elorder\\n\"\n,\"ttk::label $f.bts.btnframe.elorder.l -text \\\"Element order\\\"\\n\"\n,\"ttk::spinbox $f.bts.btnframe.elorder.elementorder2 -from 1 -to 20 -textvariable options.elementorder -width 2\\n\"\n,\"pack $f.bts.btnframe.elorder -fill x\\n\"\n,\"pack $f.bts.btnframe.elorder.elementorder2 $f.bts.btnframe.elorder.l  -anchor w -side left\\n\"\n,\"ttk::frame $f.bts.btnframe.pm\\n\"\n,\"ttk::checkbutton $f.bts.btnframe.pm.parallel_meshing -text \\\"Parallel meshing\\\" \\\\\\n\"\n,\"-variable options.parallel_meshing\\n\"\n,\"pack $f.bts.btnframe.pm -fill x -pady 5\\n\"\n,\"pack $f.bts.btnframe.pm.parallel_meshing  -anchor w\\n\"\n,\"ttk::label $f.bts.btnframe.pm.lnthreads -text \\\"Number of meshing threads\\\"\\n\"\n,\"ttk::spinbox $f.bts.btnframe.pm.nthreads -from 1 -to 128 -textvariable options.nthreads -width 2\\n\"\n,\"pack $f.bts.btnframe.pm.nthreads $f.bts.btnframe.pm.lnthreads  -anchor w -side left\\n\"\n,\"set f $w.nb.meshsize\\n\"\n,\"ttk::frame $f.f2\\n\"\n,\"pack $f.f2 -pady 10\\n\"\n,\"set f $f.f2\\n\"\n,\"ttk::frame $f.meshsize\\n\"\n,\"ttk::label $f.meshsize.l -text \\\"max mesh-size\\\"\\n\"\n,\"ttk::spinbox $f.meshsize.s -from 1e-9 -to 1e9 -textvariable options.meshsize -width 5 -validate focus -validatecommand \\\"my_validatespinbox %W %P 10\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"pack $f.meshsize -fill x\\n\"\n,\"pack $f.meshsize.s $f.meshsize.l -side right\\n\"\n,\"ttk::frame $f.minmeshsize\\n\"\n,\"ttk::label $f.minmeshsize.l -text \\\"min mesh-size\\\"\\n\"\n,\"ttk::spinbox $f.minmeshsize.s -from 0 -to 1e9 -textvariable options.minmeshsize -width 5 -validate focus -validatecommand \\\"my_validatespinbox %W %P 10\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"pack $f.minmeshsize -fill x\\n\"\n,\"pack $f.minmeshsize.s $f.minmeshsize.l -side right\\n\"\n,\"ttk::frame $f.grading\\n\"\n,\"ttk::label $f.grading.l -text \\\"mesh-size grading\\\"\\n\"\n,\"ttk::spinbox $f.grading.s -from 0.1 -to 1.0 -textvariable options.grading -width 5 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"pack $f.grading -fill x\\n\"\n,\"pack $f.grading.s $f.grading.l -side right\\n\"\n,\"set f $w.nb.meshsize\\n\"\n,\"ttk::labelframe $f.msf -text \\\"mesh-size file:\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.msf\\n\"\n,\"ttk::entry $f.msf.ent -textvariable options.meshsizefilename -width 30\\n\"\n,\"ttk::button $f.msf.btn -text \\\"Browse\\\" -command {\\n\"\n,\"global options.meshsizefilename\\n\"\n,\"set types {\\n\"\n,\"{\\\"Meshsize file\\\"   {.msz}\t} }\\n\"\n,\"set options.meshsizefilename [tk_getOpenFile -filetypes $types -initialfile ${options.meshsizefilename}]\\n\"\n,\"}\\n\"\n,\"pack $f.msf.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\\n\"\n,\"pack $f.msf.btn -side left -anchor s -padx 4 -pady 4\\n\"\n,\"ttk::label $f.lab -text \\\"Additional mesh size restrictions:\\\"\\n\"\n,\"ttk::labelframe $f.csg -relief groove -borderwidth 3 -text \\\"CSG mesh-size\\\"\\n\"\n,\"pack $f.csg -fill x\\n\"\n,\"proc test {a} {puts $a}\\n\"\n,\"ttk::scale $f.csg.curvsc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable options.curvaturesafety -takefocus 0 -command \\\"roundscale $f.csg.curvsc 1\\\"\\n\"\n,\"ttk::entry $f.csg.curve -textvariable options.curvaturesafety -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.csg.curvsc cget -from] [$f.csg.curvsc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::label $f.csg.curvla -text \\\"Elements per curvature radius\\\"\\n\"\n,\"grid $f.csg.curvsc $f.csg.curve $f.csg.curvla -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.csg.elensc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable options.segmentsperedge -takefocus 0 -command \\\"roundscale $f.csg.elensc 1\\\"\\n\"\n,\"ttk::entry $f.csg.elene -textvariable options.segmentsperedge -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.csg.elensc cget -from] [$f.csg.elensc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::label $f.csg.elenla -text \\\"Elements per edge\\\"\\n\"\n,\"grid $f.csg.elensc $f.csg.elene $f.csg.elenla -sticky nw -padx 4\\n\"\n,\"grid anchor $f.csg center\\n\"\n,\"ttk::labelframe $f.stl -relief groove -borderwidth 3 -text \\\"STL mesh-size\\\"\\n\"\n,\"pack $f.stl -fill x\\n\"\n,\"ttk::scale $f.stl.r2sc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable stloptions.resthchartdistfac -takefocus 0 -command \\\"roundscale $f.stl.r2sc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r2e -textvariable stloptions.resthchartdistfac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r2sc cget -from] [$f.stl.r2sc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r2bu -text \\\"STL - chart distance\\\" \\\\\\n\"\n,\"-variable stloptions.resthchartdistenable\\n\"\n,\"grid $f.stl.r2sc $f.stl.r2e $f.stl.r2bu -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.stl.r6sc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable stloptions.resthlinelengthfac -takefocus 0 -command \\\"roundscale $f.stl.r6sc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r6e -textvariable stloptions.resthlinelengthfac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r6sc cget -from] [$f.stl.r6sc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r6bu -text \\\"STL - line length\\\" \\\\\\n\"\n,\"-variable stloptions.resthlinelengthenable\\n\"\n,\"grid $f.stl.r6sc $f.stl.r6e $f.stl.r6bu -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.stl.r3sc -orient horizontal -length 150 -from 0.2 -to 8 \\\\\\n\"\n,\"-variable stloptions.resthcloseedgefac -takefocus 0 -command \\\"roundscale $f.stl.r3sc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r3e -textvariable stloptions.resthcloseedgefac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r3sc cget -from] [$f.stl.r3sc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r3bu -text \\\"STL/IGES/STEP - close edges\\\" \\\\\\n\"\n,\"-variable stloptions.resthcloseedgeenable\\n\"\n,\"grid $f.stl.r3sc $f.stl.r3e $f.stl.r3bu -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.stl.r1sc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable stloptions.resthsurfcurvfac -takefocus 0 -command \\\"roundscale $f.stl.r1sc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r1e -textvariable stloptions.resthsurfcurvfac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r1sc cget -from] [$f.stl.r1sc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r1bu -text \\\"STL - surface curvature\\\" \\\\\\n\"\n,\"-variable stloptions.resthsurfcurvenable\\n\"\n,\"grid $f.stl.r1sc $f.stl.r1e $f.stl.r1bu -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.stl.r3bsc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable stloptions.resthedgeanglefac -takefocus 0 -command \\\"roundscale $f.stl.r3bsc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r3be -textvariable stloptions.resthedgeanglefac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r3bsc cget -from] [$f.stl.r3bsc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r3bbu -text \\\"STL - edge angle\\\" \\\\\\n\"\n,\"-variable stloptions.resthedgeangleenable\\n\"\n,\"grid $f.stl.r3bsc  $f.stl.r3be $f.stl.r3bbu -sticky nw -padx 4\\n\"\n,\"ttk::scale $f.stl.r5sc -orient horizontal -length 150 -from 0.2 -to 5 \\\\\\n\"\n,\"-variable stloptions.resthsurfmeshcurvfac -takefocus 0 -command \\\"roundscale $f.stl.r5sc 1\\\"\\n\"\n,\"ttk::entry $f.stl.r5e -textvariable stloptions.resthsurfmeshcurvfac -width 3 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W [$f.stl.r5sc cget -from] [$f.stl.r5sc cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\" -validate focus\\n\"\n,\"ttk::checkbutton $f.stl.r5bu -text \\\"STL - surface mesh curv\\\" \\\\\\n\"\n,\"-variable stloptions.resthsurfmeshcurvenable\\n\"\n,\"grid $f.stl.r5sc  $f.stl.r5e  $f.stl.r5bu -sticky nw -padx 4\\n\"\n,\"ttk::checkbutton $f.stl.recalch -text \\\"STL - Recalc mesh size for surface optimization\\\" \\\\\\n\"\n,\"-variable stloptions.recalchopt\\n\"\n,\"grid $f.stl.recalch -sticky n -columnspan 3 -column 0\\n\"\n,\"ttk::button $f.stl.calch -text \\\"Calc New H\\\" -command { redraw; Ng_STLCalcLocalH }\\n\"\n,\"grid $f.stl.calch -columnspan 3 -column 0\\n\"\n,\"grid anchor $f.stl center\\n\"\n,\"proc roundscale {w n_digits args} {\\n\"\n,\"set val [$w get]\\n\"\n,\"global [$w cget -variable]\\n\"\n,\"if {$n_digits == 0 } {\\n\"\n,\"set [$w cget -variable] [tcl::mathfunc::round $val]\\n\"\n,\"} else {\\n\"\n,\"set [$w cget -variable] [format \\\"%.[append n_digits \\\"f\\\"]\\\" $val]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"global last_accepted_sc\\n\"\n,\"proc my_validate {w mini maxi val n_digits} {\\n\"\n,\"global last_accepted_sc [$w cget -textvariable]\\n\"\n,\"if {[string length $val] == 0} {return 0}\\n\"\n,\"if {[string is double $val] == 1} {\\n\"\n,\"if { $n_digits == 0 } {\\n\"\n,\"set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [tcl::mathfunc::round $val]]]\\n\"\n,\"} else {\\n\"\n,\"if { $n_digits < 9 } {\\n\"\n,\"set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [format \\\"%.[append n_digits \\\"f\\\"]\\\" $val]]]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set last_accepted_sc $val\\n\"\n,\"set [$w cget -textvariable] $val\\n\"\n,\"return 1\\n\"\n,\"} else {\\n\"\n,\"return 0\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc my_invalid {w} {\\n\"\n,\"global last_accepted_sc [$w cget -textvariable]\\n\"\n,\"set [$w cget -textvariable] $last_accepted_sc\\n\"\n,\"}\\n\"\n,\"set f $w.nb.chartopt\\n\"\n,\"ttk::labelframe $f.mainframe -text \\\"STL angles\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.mainframe -fill x -pady 15\\n\"\n,\"set f $f.mainframe\\n\"\n,\"ttk::label $f.labYangles -text \\\"Yellow Edges Angle ()\\\"\\n\"\n,\"ttk::scale $f.scale1 -orient horizontal -length 150 -from 0 -to 90 -variable stloptions.yangle -takefocus 0 -command \\\"roundscale $f.scale1 1\\\"\\n\"\n,\"ttk::entry $f.entry1 -textvariable stloptions.yangle -width 5 -validate focus -takefocus 0 -validatecommand \\\"my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.scale1 $f.entry1 $f.labYangles -sticky nw -padx 4 -pady 6\\n\"\n,\"ttk::label $f.labEangles -text \\\"Edge Corner Angle ()\\\"\\n\"\n,\"ttk::scale $f.scale2 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.edgecornerangle -takefocus 0 -command \\\"roundscale $f.scale2 1\\\"\\n\"\n,\"ttk::entry $f.entry2 -textvariable stloptions.edgecornerangle -width 5 -validate focus -takefocus 0 -validatecommand \\\"my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.scale2 $f.entry2 $f.labEangles -sticky nw -padx 4 -pady 6\\n\"\n,\"ttk::label $f.lab31 -text \\\"Chart Angle ()\\\"\\n\"\n,\"ttk::scale $f.scale3 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.chartangle -takefocus 0 -command \\\"roundscale $f.scale3 1\\\"\\n\"\n,\"ttk::entry $f.entry3 -textvariable stloptions.chartangle -width 5 -validate focus -takefocus 0 -validatecommand \\\"my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.scale3 $f.entry3 $f.lab31 -sticky nw -padx 4 -pady 6\\n\"\n,\"ttk::label $f.lab41 -text \\\"Outer Chart Angle ()\\\"\\n\"\n,\"ttk::scale $f.scale4 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.outerchartangle -takefocus 0 -command \\\"roundscale $f.scale4 1\\\"\\n\"\n,\"ttk::entry $f.entry4 -textvariable stloptions.outerchartangle -width 5 -validate focus -takefocus 0 -validatecommand \\\"my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.scale4 $f.entry4 $f.lab41 -sticky nw -padx 4 -pady 6\\n\"\n,\"grid anchor $f center\\n\"\n,\"global last_accepted_sp\\n\"\n,\"proc my_validatespinbox {w val n_digits} {\\n\"\n,\"global last_accepted_sp\\n\"\n,\"if {[string length $val] == 0} {return 0}\\n\"\n,\"if {[string is double $val] == 1} {\\n\"\n,\"if { $n_digits == 0 } {\\n\"\n,\"if { $n_digits < 9 } {\\n\"\n,\"set val [tcl::mathfunc::round $val] } else { set val [format \\\"%.[append n_digits \\\"f\\\"]\\\" $val]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"$w set [tcl::mathfunc::max [$w cget -from] [tcl::mathfunc::min [$w cget -to] $val]]\\n\"\n,\"set last_accepted_sp $val\\n\"\n,\"return 1\\n\"\n,\"} else {\\n\"\n,\"return 0\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc my_invalidspinbox {w} {\\n\"\n,\"global last_accepted_sp\\n\"\n,\"$w set $last_accepted_sp\\n\"\n,\"}\\n\"\n,\"set f $w.nb.optimizer\\n\"\n,\"ttk::labelframe $f.optframe -text \\\"Optimization settings\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.optframe -fill x -pady 15\\n\"\n,\"ttk::label $f.optframe.sosl -text \\\"Surface opt steps\\\"\\n\"\n,\"ttk::spinbox $f.optframe.soss -from 0 -to 99 -textvariable options.optsteps2d -width 5 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $f.optframe.sosl $f.optframe.soss -sticky nw;\\n\"\n,\"ttk::label $f.optframe.vosl -text \\\"Volume opt steps\\\"\\n\"\n,\"ttk::spinbox $f.optframe.voss -from 0 -to 99 -textvariable options.optsteps3d -width 5 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $f.optframe.vosl $f.optframe.voss -sticky nw;\\n\"\n,\"ttk::label $f.optframe.eswl -text \\\"Element size weight\\\"\\n\"\n,\"ttk::spinbox $f.optframe.esws -from 0 -to 1 -textvariable options.elsizeweight -width 5 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $f.optframe.eswl $f.optframe.esws -sticky nw;\\n\"\n,\"ttk::label $f.optframe.weml -text \\\"Worst element measure\\\"\\n\"\n,\"ttk::spinbox $f.optframe.wems -from 1 -to 10 -textvariable options.opterrpow -width 5 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $f.optframe.weml $f.optframe.wems -sticky nw;\\n\"\n,\"grid anchor $f.optframe center\\n\"\n,\"proc roundscale_helper_osx {w val} {\\n\"\n,\"global [$w cget -variable] options.badellimit\\n\"\n,\"set [$w cget -variable] [tcl::mathfunc::round $val]\\n\"\n,\"set options.badellimit [expr [tcl::mathfunc::round $val]+160]\\n\"\n,\"}\\n\"\n,\"proc my_validate_helper_osx {w val} {\\n\"\n,\"if {[string length $val] == 0} {return 0}\\n\"\n,\"if {[string is double $val] == 1} {\\n\"\n,\"set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]\\n\"\n,\"global [$scale_loc cget -variable] options.badellimit\\n\"\n,\"set [$scale_loc cget -variable] [tcl::mathfunc::max [$scale_loc cget -from] [tcl::mathfunc::min [$scale_loc cget -to] [expr [tcl::mathfunc::round $val]-160]]]\\n\"\n,\"set options.badellimit [tcl::mathfunc::max [expr [$scale_loc cget -from]+160] [tcl::mathfunc::min [expr [$scale_loc cget -to]+160] [tcl::mathfunc::round $val]]]\\n\"\n,\"return 1\\n\"\n,\"} else {\\n\"\n,\"return 0\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc my_invalid_helper_osx {w} {\\n\"\n,\"global options.badellimit\\n\"\n,\"set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]\\n\"\n,\"global [$scale_loc cget -variable]\\n\"\n,\"set [$scale_loc cget -variable] [tcl::mathfunc::round [$scale_loc get]]\\n\"\n,\"set options.badellimit [expr [tcl::mathfunc::round [$scale_loc get]]+160]\\n\"\n,\"}\\n\"\n,\"global dummy_badellimit\\n\"\n,\"set dummy_badellimit 15\\n\"\n,\"ttk::labelframe $f.optframe2 -text \\\"Bad elements\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.optframe2 -fill x -pady 15 -ipady 5\\n\"\n,\"ttk::frame $f.optframe2.badellimit\\n\"\n,\"ttk::label $f.optframe2.lab -text \\\"bad element criterion\\\";\\n\"\n,\"ttk::scale $f.optframe2.scale -orient horizontal -length 100 -from 00 -to 20 -variable dummy_badellimit -takefocus 0 -command \\\"roundscale_helper_osx $f.optframe2.scale\\\"\\n\"\n,\"ttk::entry $f.optframe2.entry -textvariable options.badellimit -width 3 -validate focusout -takefocus 0 -validatecommand \\\"my_validate_helper_osx %W %P\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid_helper_osx %W\\\"\\n\"\n,\"grid $f.optframe2.scale $f.optframe2.entry $f.optframe2.lab -padx 4 -sticky nw\\n\"\n,\"grid anchor $f.optframe2 center\\n\"\n,\"set f $w.nb.debug\\n\"\n,\"ttk::labelframe $f.f2 -text \\\"Advanced options\\\" -borderwidth 3 -relief groove\\n\"\n,\"pack $f.f2 -fill x -pady 15\\n\"\n,\"set f $f.f2\\n\"\n,\"ttk::checkbutton $f.localh -text \\\"Use Local Meshsize\\\" \\\\\\n\"\n,\"-variable options.localh\\n\"\n,\"ttk::checkbutton $f.delauney -text \\\"Use Delaunay\\\" \\\\\\n\"\n,\"-variable options.delaunay\\n\"\n,\"ttk::checkbutton $f.checkoverlap -text \\\"Check Overlapping\\\" \\\\\\n\"\n,\"-variable options.checkoverlap\\n\"\n,\"ttk::checkbutton $f.checkcb -text \\\"Check Chart Boundary\\\" \\\\\\n\"\n,\"-variable options.checkchartboundary\\n\"\n,\"ttk::checkbutton $f.blockfill -text \\\"Do Blockfilling\\\" \\\\\\n\"\n,\"-variable options.blockfill\\n\"\n,\"grid $f.localh  $f.delauney -sticky nw\\n\"\n,\"grid $f.checkoverlap $f.blockfill -sticky nw\\n\"\n,\"grid $f.checkcb -sticky nw\\n\"\n,\"grid anchor $f center\\n\"\n,\"set f $w.nb.debug\\n\"\n,\"proc enable_cb {w1 w2 w3} {\\n\"\n,\"Ng_SetDebugParameters\\n\"\n,\"if {[string match *selected* [$w1 state]] == 1 } {\\n\"\n,\"$w2 configure -state normal\\n\"\n,\"$w3 configure -state normal\\n\"\n,\"} else {\\n\"\n,\"$w2 configure -state disabled\\n\"\n,\"$w3 configure -state disabled\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::labelframe $f.cb1 -text \\\"Debugging options\\\" -borderwidth 3 -relief groove\\n\"\n,\"pack $f.cb1 -fill x -pady 15\\n\"\n,\"ttk::checkbutton $f.cb1.slowchecks -text \\\"Slow checks\\\" \\\\\\n\"\n,\"-variable debug.slowchecks -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.debugoutput -text \\\"Debugging output\\\" \\\\\\n\"\n,\"-variable debug.debugoutput -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltexline -text \\\"Halt on existing line\\\" \\\\\\n\"\n,\"-variable debug.haltexistingline  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltoverlap -text \\\"Halt on Overlap\\\" \\\\\\n\"\n,\"-variable debug.haltoverlap  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltsuc -text \\\"Halt on success\\\" \\\\\\n\"\n,\"-variable debug.haltsuccess  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltnosuc -text \\\"Halt on no success\\\" \\\\\\n\"\n,\"-variable debug.haltnosuccess  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltlargequal -text \\\"Halt on large quality class\\\" \\\\\\n\"\n,\"-variable debug.haltlargequalclass  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltseg -text \\\"Halt on Segment:\\\" \\\\\\n\"\n,\"-variable debug.haltsegment  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::checkbutton $f.cb1.haltnode -text \\\"Halt on Node:\\\" \\\\\\n\"\n,\"-variable debug.haltnode  -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::frame $f.cb1.fr\\n\"\n,\"ttk::checkbutton $f.cb1.fr.cb -text \\\"Halt on Face:\\\" \\\\\\n\"\n,\"-variable debug.haltface -command { Ng_SetDebugParameters }\\n\"\n,\"ttk::entry $f.cb1.fr.ent -textvariable debug.haltfacenr -width 3\\n\"\n,\"pack $f.cb1.fr.cb $f.cb1.fr.ent -side left\\n\"\n,\"ttk::frame $f.cb1.segs\\n\"\n,\"ttk::label $f.cb1.segs.lab1 -text \\\"P1:\\\"\\n\"\n,\"ttk::entry $f.cb1.segs.ent1 -width 6 \\\\\\n\"\n,\"-textvariable debug.haltsegmentp1\\n\"\n,\"ttk::label $f.cb1.segs.lab2 -text \\\"P2:\\\"\\n\"\n,\"ttk::entry $f.cb1.segs.ent2 -width 6 \\\\\\n\"\n,\"-textvariable debug.haltsegmentp2\\n\"\n,\"pack $f.cb1.segs.lab1 $f.cb1.segs.ent1 $f.cb1.segs.lab2 $f.cb1.segs.ent2 -side left\\n\"\n,\"grid $f.cb1.slowchecks $f.cb1.debugoutput -sticky nw\\n\"\n,\"grid $f.cb1.haltexline $f.cb1.haltoverlap -sticky nw\\n\"\n,\"grid $f.cb1.haltsuc $f.cb1.haltnosuc  -sticky nw\\n\"\n,\"grid $f.cb1.haltlargequal  $f.cb1.fr -sticky nw\\n\"\n,\"grid $f.cb1.haltnode -sticky nw\\n\"\n,\"grid $f.cb1.haltseg  -stick nw\\n\"\n,\"grid $f.cb1.segs -stick w -row 4 -rowspan 2 -column 1\\n\"\n,\"grid rowconfigure $f.cb1 3 -pad 8\\n\"\n,\"grid anchor $f.cb1 center\\n\"\n,\"ttk::checkbutton $f.cb1.showactivechart -text \\\"Show Active Meshing-Chart\\\" -variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\\n\"\n,\"grid $f.cb1.showactivechart\\n\"\n,\"grid rowconfigure $f.cb1 3 -pad 8\\n\"\n,\"grid rowconfigure $f.cb1 5 -pad 8\\n\"\n,\"set f $w.nb.debug\\n\"\n,\"ttk::labelframe $f.cont -relief groove -borderwidth 3 -text \\\"Debugging visualization\\\"\\n\"\n,\"pack $f.cont -fill x -pady 15\\n\"\n,\"ttk::checkbutton $f.cont.multidrawing -text \\\"Draw Meshing\\\" -variable multithread_drawing\\n\"\n,\"ttk::checkbutton $f.cont.multitestmode -text \\\"Meshing Testmode\\\" -variable multithread_testmode\\n\"\n,\"ttk::button $f.cont.goon -text \\\"Go On\\\" -command { set multithread_pause 0 }\\n\"\n,\"grid $f.cont.multidrawing -sticky nw\\n\"\n,\"grid $f.cont.multitestmode -sticky nw\\n\"\n,\"grid $f.cont.goon -row 0 -rowspan 2 -column 1 -sticky w\\n\"\n,\"grid columnconfigure $f.cont 0 -pad 30\\n\"\n,\"grid columnconfigure $f.cont 1 -pad 20\\n\"\n,\"grid anchor $f.cont center\\n\"\n,\"global userlevel\\n\"\n,\"if { $userlevel < 3} {\\n\"\n,\"$w.nb delete insider\\n\"\n,\"$w.nb delete debug\\n\"\n,\"}\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.apl -text \\\"Apply\\\" -command {\\n\"\n,\"Ng_SetMeshingParameters\\n\"\n,\"Ng_SetDebugParameters\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.ok -text \\\"Done\\\" -command {\\n\"\n,\"Ng_SetMeshingParameters\\n\"\n,\"Ng_SetDebugParameters\\n\"\n,\"wm withdraw .options_dlg\\n\"\n,\"}\\n\"\n,\"pack  $w.bu.apl $w.bu.ok -side left -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Meshing Options\\\"\\n\"\n,\"focus .options_dlg\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"meshingoptionsdialog\\n\"\n,\"wm withdraw .options_dlg\\n\"\n,\"proc viewingoptionsdialog { } {\\n\"\n,\"global userlevel\\n\"\n,\"set w .viewopts_dlg\\n\"\n,\"if {[winfo exists .viewopts_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"pack [ttk::notebook $w.nb]  -fill both -fill both -side top\\n\"\n,\"$w.nb add [ttk::frame $w.nb.general] -text \\\"General\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.stl] -text \\\"STL\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.occ] -text \\\"IGES/STEP\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.mesh] -text \\\"Mesh\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.light] -text \\\"Light\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.edges] -text \\\"Edges\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.misc] -text \\\"Misc.\\\" -underline 3\\n\"\n,\"set f $w.nb.general\\n\"\n,\"ttk::labelframe $f.gvop -text \\\"General viewing options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.gvop -fill x -pady 15\\n\"\n,\"set f $f.gvop\\n\"\n,\"ttk::checkbutton $f.backcol -text \\\"White Background\\\" \\\\\\n\"\n,\"-variable viewoptions.whitebackground \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.cross -text \\\"Draw Coordinate Cross\\\" \\\\\\n\"\n,\"-variable viewoptions.drawcoordinatecross \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.color -text \\\"Draw Color-bar\\\" \\\\\\n\"\n,\"-variable viewoptions.drawcolorbar \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.netgen -text \\\"Draw Netgen-logo\\\" \\\\\\n\"\n,\"-variable viewoptions.drawnetgenlogo \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"grid $f.backcol -sticky nw\\n\"\n,\"grid $f.cross -stick nw\\n\"\n,\"grid $f.color  -sticky nw\\n\"\n,\"grid $f.netgen -sticky nw\\n\"\n,\"menu $f.stylemenu\\n\"\n,\"ttk::menubutton $f.style -menu $f.stylemenu -width 10 -text [ttk::style theme use]\\n\"\n,\"grid $f.style -sticky nw\\n\"\n,\"grid anchor $f center\\n\"\n,\"foreach theme [ttk::themes] {\\n\"\n,\"$f.stylemenu add command -label  $theme \\\\\\n\"\n,\"-command \\\" $f.style configure -text $theme; puts $theme ; ttk::setTheme $theme\\\"\\n\"\n,\"}\\n\"\n,\"set f $w.nb.stl\\n\"\n,\"ttk::labelframe $f.show -relief groove -borderwidth 3 -text \\\"STL viewing options\\\"\\n\"\n,\"pack $f.show -fill x -pady 15\\n\"\n,\"ttk::checkbutton $f.show.showtrias -text \\\"Show STL-Triangles\\\" \\\\\\n\"\n,\"-variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.show.showfilledtrias -text \\\"Show Filled Triangles\\\" \\\\\\n\"\n,\"-variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\\n\"\n,\"grid $f.show.showtrias $f.show.showfilledtrias -sticky nw\\n\"\n,\"ttk::checkbutton $f.show.showactivechart -text \\\"Show Active Meshing-Chart\\\" \\\\\\n\"\n,\"-variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.show.showedges -text \\\"Show Edges\\\" \\\\\\n\"\n,\"-variable stloptions.showedges -command { Ng_SetVisParameters; redraw }\\n\"\n,\"grid $f.show.showactivechart $f.show.showedges -sticky nw\\n\"\n,\"grid anchor $f.show center\\n\"\n,\"ttk::checkbutton $f.show.showmarktrias -text \\\"Show Chart Triangles\\\" \\\\\\n\"\n,\"-variable stloptions.showmarktrias \\\\\\n\"\n,\"-command {set stldoctor.showfaces 0; Ng_STLDoctor; Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.show.showfaces -text \\\"Show Faces\\\" \\\\\\n\"\n,\"-variable stldoctor.showfaces \\\\\\n\"\n,\"-command {set stloptions.showmarktrias 0; Ng_STLDoctor; Ng_SetVisParameters; redraw}\\n\"\n,\"grid $f.show.showmarktrias $f.show.showfaces -sticky nw\\n\"\n,\"ttk::labelframe $f.fn -relief groove -borderwidth 3 -text \\\"Chart/Face number\\\"\\n\"\n,\"pack $f.fn -fill x\\n\"\n,\"ttk::label $f.fn.lab3 -text \\\"Chart/Face number\\\"\\n\"\n,\"ttk::scale $f.fn.scale3 -orient horizontal -length 150 -from 0 -to 200 \\\\\\n\"\n,\"-variable stloptions.chartnumber -command \\\"Ng_SetVisParameters; redraw;roundscale $f.fn.scale3 0\\\"\\n\"\n,\"ttk::entry $f.fn.ent3 -textvariable stloptions.chartnumber -width 3 -validate focus -takefocus 0 \\\\\\n\"\n,\"-validatecommand \\\"Ng_SetVisParameters; redraw;my_validate %W [$f.fn.scale3 cget -from] [$f.fn.scale3 cget -to] %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"grid $f.fn.scale3 $f.fn.ent3 $f.fn.lab3 -sticky nw -padx 4\\n\"\n,\"tk::label $f.fn.lab -text \\\"Chart/Face Offset:\\\";\\n\"\n,\"ttk::entry $f.fn.ent -width 3 \\\\\\n\"\n,\"-textvariable stloptions.chartnumberoffset -validate focus -takefocus 0 \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W 0 1e9 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"ttk::button $f.fn.btn_write_chart -text \\\"Write selected chart to chart.stlb\\\" -command {\\n\"\n,\"Ng_STLDoctor writechart\\n\"\n,\"}\\n\"\n,\"grid $f.fn.lab -sticky ne -padx 4\\n\"\n,\"grid $f.fn.ent -sticky nw -padx 4 -row 1 -column 1\\n\"\n,\"grid $f.fn.btn_write_chart -padx 4 -row 2 -column 1\\n\"\n,\"grid anchor $f.fn center\\n\"\n,\"ttk::labelframe $f.advstl -text \\\"Advanced STL options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.advstl -fill x -pady 15\\n\"\n,\"ttk::checkbutton $f.advstl.bu1 -text \\\"Show Marked (Dirty) Triangles\\\" \\\\\\n\"\n,\"-variable stldoctor.showmarkedtrigs \\\\\\n\"\n,\"-command {Ng_STLDoctor; redraw}\\n\"\n,\"ttk::checkbutton $f.advstl.bu2 -text \\\"show edge corner points\\\" \\\\\\n\"\n,\"-variable stldoctor.showedgecornerpoints \\\\\\n\"\n,\"-command {Ng_STLDoctor; redraw}\\n\"\n,\"ttk::checkbutton $f.advstl.bu3 -text \\\"show touched triangle chart\\\" \\\\\\n\"\n,\"-variable stldoctor.showtouchedtrigchart \\\\\\n\"\n,\"-command {set stldoctor.showfaces 0; set stloptions.showmarktrias 1; \\\\\\n\"\n,\"Ng_STLDoctor; Ng_SetVisParameters; redraw}\\n\"\n,\"ttk::checkbutton $f.advstl.bu4 -text \\\"draw meshed edges\\\" \\\\\\n\"\n,\"-variable stldoctor.drawmeshededges \\\\\\n\"\n,\"-command {Ng_STLDoctor;}\\n\"\n,\"ttk::checkbutton $f.advstl.bu5 -text \\\"select with mouse\\\" \\\\\\n\"\n,\"-variable stldoctor.selectwithmouse\\n\"\n,\"grid $f.advstl.bu1 -stick nw\\n\"\n,\"grid $f.advstl.bu2 -sticky nw\\n\"\n,\"grid $f.advstl.bu3 -stick nw\\n\"\n,\"grid $f.advstl.bu4 -stick nw\\n\"\n,\"grid $f.advstl.bu5 -stick nw\\n\"\n,\"grid anchor $f.advstl center\\n\"\n,\"ttk::frame $f.advstl.tbn\\n\"\n,\"ttk::label $f.advstl.tbn.lab -text \\\"Select triangle by number\\\";\\n\"\n,\"ttk::entry $f.advstl.tbn.ent -width 5 \\\\\\n\"\n,\"-textvariable stldoctor.selecttrig\\n\"\n,\"pack $f.advstl.tbn.lab $f.advstl.tbn.ent -padx 4 -side left\\n\"\n,\"grid $f.advstl.tbn -sticky nw\\n\"\n,\"grid anchor $f.advstl center\\n\"\n,\"grid rowconfigure $f.advstl 4 -pad 8\\n\"\n,\"ttk::labelframe $f.vc -relief groove -borderwidth 3 -text \\\"Vicinity options\\\"\\n\"\n,\"pack $f.vc -fill x -pady 15\\n\"\n,\"ttk::checkbutton $f.vc.bu -text \\\"show vicinity\\\" \\\\\\n\"\n,\"-variable stldoctor.showvicinity \\\\\\n\"\n,\"-command {Ng_STLDoctor vicinity; redraw}\\n\"\n,\"ttk::label $f.vc.lab -text \\\"vicinity size\\\";\\n\"\n,\"ttk::scale $f.vc.scale -orient horizontal -length 150 -from 0 -to 200 \\\\\\n\"\n,\"-variable stldoctor.vicinity \\\\\\n\"\n,\"-takefocus 0 \\\\\\n\"\n,\"-command \\\"roundscale $f.vc.scale 0; Ng_STLDoctor vicinity; redraw\\\"\\n\"\n,\"ttk::entry $f.vc.ent -width 4 -textvariable stldoctor.vicinity -validate focus \\\\\\n\"\n,\"-takefocus 0 -validatecommand \\\"Ng_STLDoctor vicinity; redraw;my_validate %W [$f.vc.scale cget -from] [$f.vc.scale cget -to] %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_STLDoctor vicinity; redraw\\\"\\n\"\n,\"grid $f.vc.bu -stick nw -columnspan 3 -column 0\\n\"\n,\"grid $f.vc.scale $f.vc.ent $f.vc.lab -sticky nw -padx 4\\n\"\n,\"grid anchor $f.vc center\\n\"\n,\"set f $w.nb.occ\\n\"\n,\"ttk::labelframe $f.occframe -text \\\"IGES/STEP options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.occframe -fill x -pady 15 -ipady 8\\n\"\n,\"ttk::checkbutton $f.occframe.occshowsurfaces -text \\\"Show surfaces \\\" \\\\\\n\"\n,\"-variable occoptions.showsurfaces \\\\\\n\"\n,\"-command { Ng_SetOCCVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.occframe.occshowedges -text \\\"Show edges \\\" \\\\\\n\"\n,\"-variable occoptions.showedges \\\\\\n\"\n,\"-command { Ng_SetOCCVisParameters; redraw }\\n\"\n,\"grid $f.occframe.occshowsurfaces $f.occframe.occshowedges -sticky nw -padx 4\\n\"\n,\"grid anchor $f.occframe center\\n\"\n,\"ttk::button $f.occframe.btn -text \\\"Rebuild visualization data\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_SetOCCVisParameters\\n\"\n,\"Ng_OCCCommand buildvisualizationmesh\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::frame $f.occframe.vssm\\n\"\n,\"ttk::label $f.occframe.vssm.lab -text \\\"Visulization smoothness\\\"\\n\"\n,\"ttk::spinbox $f.occframe.vssm.sp -textvariable occoptions.deflection \\\\\\n\"\n,\"-from 0.1 -to 3 -increment 0.1 -width 4 -command { catch Ng_SetOCCVisParameters } \\\\\\n\"\n,\"-validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"pack $f.occframe.vssm.lab $f.occframe.vssm.sp -side left -padx 4\\n\"\n,\"grid $f.occframe.vssm -sticky nw -columnspan 2 -column 0 -pady 8\\n\"\n,\"grid $f.occframe.btn -columnspan 2 -column 0 -sticky n\\n\"\n,\"ttk::labelframe $f.occframe1 -relief groove -borderwidth 3 -text \\\"ACIS visulization / construction\\\"\\n\"\n,\"pack $f.occframe1 -fill x -pady 15 -ipady 8\\n\"\n,\"ttk::label $f.occframe1.lab1 -text \\\"Show solid (0 for all)\\\"\\n\"\n,\"ttk::spinbox $f.occframe1.sp1 -textvariable occoptions.showsolidnr \\\\\\n\"\n,\"-from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\\\\n\"\n,\"-validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"ttk::label $f.occframe1.lab2 -text \\\"Show solid 2\\\"\\n\"\n,\"ttk::spinbox $f.occframe1.sp2 -textvariable occoptions.showsolidnr2 \\\\\\n\"\n,\"-from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\\\\n\"\n,\"-validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"ttk::button $f.occframe1.subtract -text \\\"Subtract (2 minus 1)\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_ACISCommand subtract ${occoptions.showsolidnr} ${occoptions.showsolidnr2}\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $f.occframe1.combine -text \\\"Combine all\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_ACISCommand combineall\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"grid $f.occframe1.lab1 -row 0 -column 0 -sticky ne\\n\"\n,\"grid $f.occframe1.sp1 -row 0 -column 1 -sticky nw\\n\"\n,\"grid $f.occframe1.lab2 -row 1 -column 0 -sticky ne\\n\"\n,\"grid $f.occframe1.sp2 -row 1 -column 1 -sticky nw\\n\"\n,\"grid $f.occframe1.combine -columnspan 2 -column 0 -sticky n\\n\"\n,\"grid anchor $f.occframe1 center\\n\"\n,\"set f $w.nb.mesh\\n\"\n,\"ttk::labelframe $f.center -relief groove -borderwidth 3 -text \\\"how shall i name you?\\\"\\n\"\n,\"pack $f.center -fill x -pady 15\\n\"\n,\"ttk::button $f.center.lab1 -text \\\"Set Center Point\\\" \\\\\\n\"\n,\"-command { Ng_SetVisParameters; Ng_Center; redraw }\\n\"\n,\"ttk::entry $f.center.ent1 -width 5 \\\\\\n\"\n,\"-textvariable viewoptions.centerpoint -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W 0 1e9 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.center.ent1 $f.center.lab1 -padx 4 -pady 4 -sticky nw\\n\"\n,\"ttk::button $f.center.lab2 -text \\\"Draw Element\\\" \\\\\\n\"\n,\"-command { Ng_SetVisParameters; Ng_ZoomAll; redraw }\\n\"\n,\"ttk::entry $f.center.ent2 -width 5 \\\\\\n\"\n,\"-textvariable viewoptions.drawelement -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W 0 1e9 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.center.ent2 $f.center.lab2 -padx 4 -pady 4 -sticky nw\\n\"\n,\"grid anchor $f.center center\\n\"\n,\"ttk::labelframe $f.meshframe -text \\\"Mesh visualization options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.meshframe -fill x -pady 15\\n\"\n,\"set f $f.meshframe\\n\"\n,\"ttk::checkbutton $f.showcolor -text \\\"Meshsize Visualization\\\" \\\\\\n\"\n,\"-variable viewoptions.colormeshsize \\\\\\n\"\n,\"-command { Ng_SetVisParameters;redraw; }\\n\"\n,\"ttk::checkbutton $f.showfilledtrigs -text \\\"Show filled triangles\\\" \\\\\\n\"\n,\"-variable viewoptions.drawfilledtrigs \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showedges -text \\\"Show edges\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedges \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showoutline -text \\\"Show Triangle Outline\\\" \\\\\\n\"\n,\"-variable viewoptions.drawoutline \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showbadels -text \\\"Show bad elements\\\" \\\\\\n\"\n,\"-variable viewoptions.drawbadels \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showprisms -text \\\"Show prisms\\\" \\\\\\n\"\n,\"-variable viewoptions.drawprisms \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showpyramids -text \\\"Show pyramids\\\" \\\\\\n\"\n,\"-variable viewoptions.drawpyramids \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showhexes -text \\\"Show hexes\\\" \\\\\\n\"\n,\"-variable viewoptions.drawhexes \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showidentified -text \\\"Show identified points\\\" \\\\\\n\"\n,\"-variable viewoptions.drawidentified \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showmetispartition -text \\\"Show METIS Partition\\\" \\\\\\n\"\n,\"-variable viewoptions.drawmetispartition \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showpointnumbers -text \\\"Show Point-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawpointnumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showedgenumbers -text \\\"Show Edge-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedgenumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showfacenumbers -text \\\"Show Face-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawfacenumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showelementnumbers -text \\\"Show Element-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawelementnumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showsegmentnumbers -text \\\"Show Segment-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawsegmentnumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showsurfaceelementnumbers -text \\\"Show Surfaceelement-numbers\\\" \\\\\\n\"\n,\"-variable viewoptions.drawsurfaceelementnumbers \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::frame $f.frametets\\n\"\n,\"ttk::checkbutton $f.frametets.showtets -text \\\"\\\" \\\\\\n\"\n,\"-variable viewoptions.drawtets \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::label $f.frametets.label -text \\\"\\\\Show Tets\\\\rin domain\\\"\\n\"\n,\"ttk::spinbox $f.frametets.showtetsdomain -from 0 -to 500 -increment 1 -width 3 \\\\\\n\"\n,\"-textvariable viewoptions.drawtetsdomain -validate focus \\\\\\n\"\n,\"-command \\\"Ng_SetVisParameters; redraw;\\\" \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"ttk::label $f.frametets.label1 -text \\\"Subdivision\\\"\\n\"\n,\"ttk::spinbox $f.frametets.subdiv -from 0 -to 8 -increment 1 -width 3 \\\\\\n\"\n,\"-textvariable visoptions.subdivisions -validate focus \\\\\\n\"\n,\"-command { Ng_SetVisParameters; Ng_Vis_Set parameters; Ng_SetNextTimeStamp; redraw } \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"ttk::label $f.frametets.label2 -text \\\"Show surface\\\\rof domain\\\"\\n\"\n,\"ttk::spinbox $f.frametets.showdomain -from 0 -to 50 -increment 1 -width 3 \\\\\\n\"\n,\"-textvariable viewoptions.drawdomainsurf -validate focus \\\\\\n\"\n,\"-command { Ng_SetVisParameters; Ng_Vis_Set parameters; redraw } \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $f.frametets.showtets $f.frametets.label $f.frametets.showtetsdomain -sticky w\\n\"\n,\"grid x $f.frametets.label2 $f.frametets.showdomain -stick w\\n\"\n,\"grid x $f.frametets.label1 $f.frametets.subdiv -sticky w\\n\"\n,\"grid $f.showfilledtrigs $f.showoutline -sticky nw\\n\"\n,\"grid $f.showedges $f.showbadels -sticky nw\\n\"\n,\"grid $f.showpointnumbers $f.showedgenumbers -sticky nw\\n\"\n,\"grid $f.showfacenumbers $f.showelementnumbers -sticky nw\\n\"\n,\"grid $f.showsurfaceelementnumbers $f.showsegmentnumbers -sticky nw\\n\"\n,\"grid $f.showmetispartition $f.showidentified -sticky nw\\n\"\n,\"grid $f.showcolor $f.showpyramids -sticky nw\\n\"\n,\"grid $f.showprisms $f.showhexes -sticky nw\\n\"\n,\"grid  $f.frametets -sticky n -columnspan 2 -column 0 -pady 8\\n\"\n,\"grid anchor $f center\\n\"\n,\"set f $w.nb.mesh\\n\"\n,\"ttk::labelframe $f.fshrink -text \\\"Element visualization\\\" -relief groove -borderwidth 3\\n\"\n,\"ttk::label $f.fshrink.lab -text \\\"Shrink elements\\\"\\n\"\n,\"ttk::scale $f.fshrink.scale -orient horizontal -length 200 -from 0 -to 1.0001 \\\\\\n\"\n,\"-command \\\"roundscale $f.fshrink.scale 2;Ng_SetVisParameters; after idle redraw\\\" \\\\\\n\"\n,\"-variable  viewoptions.shrink\\n\"\n,\"ttk::entry $f.fshrink.entry -textvariable viewoptions.shrink -width 4 -validate focus \\\\\\n\"\n,\"-takefocus 0 -validatecommand \\\"Ng_SetVisParameters; after idle redraw;my_validate %W [$f.fshrink.scale cget -from] [$f.fshrink.scale cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; after idle redraw;\\\"\\n\"\n,\"pack $f.fshrink -fill x -ipady 8\\n\"\n,\"grid $f.fshrink.scale $f.fshrink.entry $f.fshrink.lab -padx 4\\n\"\n,\"grid anchor $f.fshrink center\\n\"\n,\"set f $w.nb.light\\n\"\n,\"ttk::labelframe $f.main -text \\\"Lighting options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.main -fill x -pady 15\\n\"\n,\"set f $f.main\\n\"\n,\"ttk::label $f.lab1 -text \\\"Ambient Light\\\"\\n\"\n,\"ttk::scale $f.scale1 -orient horizontal -length 200 -from 0 -to 1 \\\\\\n\"\n,\"-command \\\"roundscale $f.scale1 2; Ng_SetVisParameters; redraw\\\" \\\\\\n\"\n,\"-variable viewoptions.light.amb\\n\"\n,\"ttk::entry $f.ent1 -textvariable viewoptions.light.amb -validate focus -width 4 \\\\\\n\"\n,\"-validatecommand \\\" Ng_SetVisParameters; redraw;my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"ttk::label $f.lab2 -text \\\"Diffuse Light\\\"\\n\"\n,\"ttk::scale $f.scale2 -orient horizontal -length 200 -from 0 -to 1 \\\\\\n\"\n,\"-command \\\"roundscale $f.scale2 2; Ng_SetVisParameters; redraw \\\" \\\\\\n\"\n,\"-variable  viewoptions.light.diff\\n\"\n,\"ttk::entry $f.ent2 -textvariable viewoptions.light.diff -validate focus -width 4 \\\\\\n\"\n,\"-validatecommand \\\" Ng_SetVisParameters; redraw;my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"ttk::label $f.lab3 -text \\\"Specular Light\\\"\\n\"\n,\"ttk::scale $f.scale3 -orient horizontal -length 200 -from 0 -to 1 \\\\\\n\"\n,\"-command \\\"roundscale $f.scale3 2; Ng_SetVisParameters; redraw \\\" \\\\\\n\"\n,\"-variable  viewoptions.light.spec\\n\"\n,\"ttk::entry $f.ent3 -textvariable viewoptions.light.spec -validate focus -width 4 \\\\\\n\"\n,\"-validatecommand \\\" Ng_SetVisParameters; redraw;my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"grid $f.scale1 $f.ent1 $f.lab1 -sticky nw -padx 4 -pady 8\\n\"\n,\"grid $f.scale2 $f.ent2 $f.lab2 -sticky nw -padx 4 -pady 8\\n\"\n,\"grid $f.scale3 $f.ent3 $f.lab3 -sticky nw -padx 4 -pady 8\\n\"\n,\"grid anchor $f center\\n\"\n,\"set f $w.nb.light\\n\"\n,\"ttk::labelframe $f.main1 -text \\\"Material options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.main1 -fill x -pady 15\\n\"\n,\"set f $f.main1\\n\"\n,\"ttk::label $f.lab4 -text \\\"Material Shininess\\\"\\n\"\n,\"ttk::scale $f.scale4 -orient horizontal -length 200 -from 0 -to 128 \\\\\\n\"\n,\"-command \\\"roundscale $f.scale4 0; Ng_SetVisParameters; redraw \\\" \\\\\\n\"\n,\"-variable  viewoptions.mat.shininess\\n\"\n,\"ttk::entry $f.ent4 -textvariable viewoptions.mat.shininess -validate focus -width 4 \\\\\\n\"\n,\"-validatecommand \\\" Ng_SetVisParameters; redraw;my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"ttk::label $f.lab5 -text \\\"Material Transparency\\\"\\n\"\n,\"ttk::scale $f.scale5 -orient horizontal -length 200 -from 0 -to 1 \\\\\\n\"\n,\"-command \\\"roundscale $f.scale5 2; Ng_SetVisParameters; redraw \\\" \\\\\\n\"\n,\"-variable  viewoptions.mat.transp\\n\"\n,\"ttk::entry $f.ent5 -textvariable viewoptions.mat.transp -validate focus -width 4 \\\\\\n\"\n,\"-validatecommand \\\" Ng_SetVisParameters; redraw;my_validate %W [$f.scale5 cget -from] [$f.scale5 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetVisParameters; redraw;\\\"\\n\"\n,\"grid $f.scale4 $f.ent4 $f.lab4 -sticky nw -padx 4 -pady 8\\n\"\n,\"grid $f.scale5 $f.ent5 $f.lab5 -sticky nw -padx 4 -pady 8\\n\"\n,\"grid anchor $f center\\n\"\n,\"set f $w.nb.edges\\n\"\n,\"ttk::labelframe $f.main -text \\\"Edge viewing options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.main -fill x -pady 15\\n\"\n,\"set f $f.main\\n\"\n,\"ttk::frame $f.helper\\n\"\n,\"pack $f.helper -anchor center\\n\"\n,\"set f $f.helper\\n\"\n,\"ttk::checkbutton $f.showedges -text \\\"Show Edges\\\" \\\\\\n\"\n,\"-variable viewoptions.drawededges \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showpoints -text \\\"Show Points\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedpoints \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showpointnrs -text \\\"Show Points Nrs\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedpointnrs \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.showtang -text \\\"Show CP Tangents\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedtangents \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.drawedgenrs -text \\\"Show Edge Nrs\\\" \\\\\\n\"\n,\"-variable viewoptions.drawededgenrs \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"pack $f.showedges $f.showpoints $f.showpointnrs $f.showtang $f.drawedgenrs -anchor w\\n\"\n,\"set f $w.nb.edges\\n\"\n,\"ttk::labelframe $f.main1 -text \\\"Center point\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $f.main1 -fill x -pady 15\\n\"\n,\"set f $f.main1\\n\"\n,\"ttk::frame $f.center\\n\"\n,\"pack $f.center -anchor center\\n\"\n,\"ttk::button $f.center.btn -text \\\"Set Center Point\\\" \\\\\\n\"\n,\"-command { Ng_SetVisParameters; Ng_Center; redraw }\\n\"\n,\"ttk::entry $f.center.ent -width 5 -textvariable viewoptions.centerpoint -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W 0 1e9 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.center.ent $f.center.btn -sticky nw -padx 4\\n\"\n,\"ttk::label $f.center.lab1 -text \\\"SpecPoint Veclen\\\"\\n\"\n,\"ttk::entry $f.center.ent1 -width 5 -textvariable viewoptions.specpointvlen -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W 0 1e9 %P 4\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.center.ent1 $f.center.lab1 -sticky nw -padx 4\\n\"\n,\"set f $w.nb.misc\\n\"\n,\"ttk::labelframe $f.point -relief groove -borderwidth 3 -text \\\"Special point\\\"\\n\"\n,\"ttk::frame $f.point.dp\\n\"\n,\"ttk::checkbutton $f.point.dp.drawpoint -text \\\"Draw Point\\\" \\\\\\n\"\n,\"-variable viewoptions.drawspecpoint \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::entry $f.point.dp.px -width 8 -textvariable viewoptions.specpointx -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W -1e9 1e9 %P 10\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"ttk::entry $f.point.dp.py -width 8 -textvariable viewoptions.specpointy -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W -1e9 1e9 %P 10\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"ttk::entry $f.point.dp.pz -width 8 -textvariable viewoptions.specpointz -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validate %W -1e9 1e9 %P 10\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W\\\"\\n\"\n,\"grid $f.point.dp.drawpoint $f.point.dp.px $f.point.dp.py $f.point.dp.pz -sticky nw -padx 4;\\n\"\n,\"ttk::checkbutton $f.point.dp.center -text \\\"Use as Center\\\" \\\\\\n\"\n,\"-variable viewoptions.usecentercoords \\\\\\n\"\n,\"-command {\\n\"\n,\"if { ${viewoptions.usecentercoords} } {\\n\"\n,\"set viewoptions.centerx ${viewoptions.specpointx}\\n\"\n,\"set viewoptions.centery ${viewoptions.specpointy}\\n\"\n,\"set viewoptions.centerz ${viewoptions.specpointz}\\n\"\n,\"Ng_SetVisParameters; Ng_Center\\n\"\n,\"redraw\\n\"\n,\"} {\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"grid $f.point.dp.center -sticky nw -padx 4\\n\"\n,\"pack $f.point.dp\\n\"\n,\"pack $f.point -fill x -ipady 3 -pady 15\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.done -text \\\"Done\\\" -command {\\n\"\n,\"Ng_SetVisParameters;\\n\"\n,\"redraw\\n\"\n,\"destroy .viewopts_dlg\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.apply -text \\\"Apply\\\" -command {\\n\"\n,\"Ng_SetVisParameters;\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.bu.apply $w.bu.done -expand yes -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Viewing options\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc clipplanecommand { { optionalvar 0 } } {\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"after idle redraw\\n\"\n,\"}\\n\"\n,\"set clippingdialog_pop1 0\\n\"\n,\"set clippingdialog_pop2 0\\n\"\n,\"set clippingdialog_pop3 0\\n\"\n,\"set clippingdialog_pop4 0\\n\"\n,\"proc clippingdialog { } {\\n\"\n,\"global clippingdialog_pop1\\n\"\n,\"global clippingdialog_pop2\\n\"\n,\"global clippingdialog_pop3\\n\"\n,\"global clippingdialog_pop4\\n\"\n,\"set clippingdialog_pop1 1\\n\"\n,\"set clippingdialog_pop2 1\\n\"\n,\"set clippingdialog_pop3 1\\n\"\n,\"set clippingdialog_pop4 1\\n\"\n,\"set w .clipping_dlg\\n\"\n,\"if {[winfo exists .clipping_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::frame $w.background\\n\"\n,\"pack $w.background -fill x -fill y\\n\"\n,\"set w $w.background\\n\"\n,\"ttk::labelframe $w.main -text \\\"Visual clipping\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $w.main -fill x -pady 15\\n\"\n,\"set w $w.main\\n\"\n,\"ttk::label $w.lab1 -text \\\"Normal x\\\"\\n\"\n,\"ttk::scale $w.scale1 -orient horizontal -length 300 -from -1 -to 1 \\\\\\n\"\n,\"-variable  viewoptions.clipping.nx \\\\\\n\"\n,\"-command \\\"roundscale $w.scale1 2; clipplanecommand \\\"\\n\"\n,\"ttk::entry $w.entry1 -width 5 -textvariable  viewoptions.clipping.nx \\\\\\n\"\n,\"-validate focus -validatecommand \\\" clipplanecommand;my_validate %W [$w.scale1 cget -from] [$w.scale1 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W; clipplanecommand\\\"\\n\"\n,\"ttk::label $w.lab2 -text \\\"Normal y\\\"\\n\"\n,\"ttk::scale $w.scale2 -orient horizontal -length 300 -from -1 -to 1 \\\\\\n\"\n,\"-variable  viewoptions.clipping.ny \\\\\\n\"\n,\"-command \\\"roundscale $w.scale2 2; clipplanecommand \\\"\\n\"\n,\"ttk::entry $w.entry2 -width 5 -textvariable  viewoptions.clipping.ny \\\\\\n\"\n,\"-validate focus -validatecommand \\\" clipplanecommand;my_validate %W [$w.scale2 cget -from] [$w.scale2 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid $w.entry2;clipplanecommand\\\"\\n\"\n,\"ttk::label $w.lab3 -text \\\"Normal z\\\"\\n\"\n,\"ttk::scale $w.scale3 -orient horizontal -length 300 -from -1 -to 1 \\\\\\n\"\n,\"-variable  viewoptions.clipping.nz \\\\\\n\"\n,\"-command \\\"roundscale $w.scale3 2; clipplanecommand \\\"\\n\"\n,\"ttk::entry $w.entry3 -width 5 -textvariable  viewoptions.clipping.nz \\\\\\n\"\n,\"-validate focus -validatecommand \\\" clipplanecommand;my_validate %W [$w.scale3 cget -from] [$w.scale3 cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;clipplanecommand\\\"\\n\"\n,\"ttk::label $w.lab4 -text \\\"Distance\\\"\\n\"\n,\"ttk::scale $w.scale4 -orient horizontal -length 300 -from -1 -to 1.001 \\\\\\n\"\n,\"-variable  viewoptions.clipping.dist \\\\\\n\"\n,\"-command \\\"roundscale $w.scale4 3; clipplanecommand \\\"\\n\"\n,\"ttk::entry $w.entry4 -width 5 -textvariable  viewoptions.clipping.dist \\\\\\n\"\n,\"-validate focus -validatecommand \\\" clipplanecommand;my_validate %W [$w.scale4 cget -from] [$w.scale4 cget -to] %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;clipplanecommand\\\"\\n\"\n,\"proc my_Press {w x y} {\\n\"\n,\"set inc [expr {([$w get $x $y] <= [$w get]) ? -1 : 1}]\\n\"\n,\"ttk::Repeatedly ttk::scale::Increment $w [expr 0.001*$inc]\\n\"\n,\"}\\n\"\n,\"bind $w.scale4 <ButtonPress-1> { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\\n\"\n,\"bind $w.scale4 <ButtonRelease-1> {ttk::scale::Release %W %x %y}\\n\"\n,\"ttk::label $w.lab5 -text \\\"Additional\\\\rDistance\\\"\\n\"\n,\"ttk::scale $w.scale5 -orient horizontal -length 300 -from -1 -to 1.001 \\\\\\n\"\n,\"-variable  viewoptions.clipping.dist2 \\\\\\n\"\n,\"-command \\\"roundscale $w.scale5 3; clipplanecommand \\\"\\n\"\n,\"ttk::entry $w.entry5 -width 5 -textvariable  viewoptions.clipping.dist2 \\\\\\n\"\n,\"-validate focus -validatecommand \\\" clipplanecommand;my_validate %W [$w.scale5 cget -from] [$w.scale5 cget -to] %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;clipplanecommand\\\"\\n\"\n,\"bind $w.scale5 <ButtonPress-1> { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\\n\"\n,\"bind $w.scale5 <ButtonRelease-1> {ttk::scale::Release %W %x %y}\\n\"\n,\"ttk::label $w.clipdomainlabel -text \\\"Clip only domain\\\"\\n\"\n,\"ttk::spinbox $w.clipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\\\\n\"\n,\"-textvariable viewoptions.clipping.onlydomain -validate focus \\\\\\n\"\n,\"-command {clipplanecommand;} \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"ttk::label $w.donotclipdomainlabel -text \\\"Do not clip domain\\\"\\n\"\n,\"ttk::spinbox $w.donotclipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\\\\n\"\n,\"-textvariable viewoptions.clipping.notdomain -validate focus \\\\\\n\"\n,\"-command \\\"clipplanecommand\\\" \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\"\\n\"\n,\"grid $w.scale1 $w.entry1 $w.lab1 -sticky nw -padx 4 -pady 14\\n\"\n,\"grid $w.scale2 $w.entry2 $w.lab2 -sticky nw -padx 4 -pady 14\\n\"\n,\"grid $w.scale3 $w.entry3 $w.lab3 -sticky nw -padx 4 -pady 14\\n\"\n,\"grid $w.scale4 $w.entry4 $w.lab4 -sticky nw -padx 4 -pady 14\\n\"\n,\"grid $w.scale5 $w.entry5 $w.lab5 -sticky w -padx 4 -pady 14\\n\"\n,\"grid $w.clipdomainlabel -sticky ne -padx 4 -pady 14\\n\"\n,\"grid $w.clipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 5\\n\"\n,\"grid $w.donotclipdomainlabel -sticky ne -padx 4 -pady 14\\n\"\n,\"grid $w.donotclipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 6\\n\"\n,\"grid anchor $w center\\n\"\n,\"set w .clipping_dlg.background.main\\n\"\n,\"ttk::checkbutton $w.cb1 -text \\\"Enable clipping\\\" \\\\\\n\"\n,\"-variable viewoptions.clipping.enable \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"grid  $w.cb1 -columnspan 2 -sticky ne\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"grid $w.bu;\\n\"\n,\"ttk::button $w.cancle -text \\\"Done\\\" -command \\\"destroy .clipping_dlg\\\"\\n\"\n,\"grid $w.cancle -columnspan 3 -pady 16\\n\"\n,\"set w .clipping_dlg\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Clipping Plane\\\"\\n\"\n,\"focus $w\\n\"\n,\"clipplanecommand\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc refinementdialog { } {\\n\"\n,\"set w .refinement_dlg\\n\"\n,\"if {[winfo exists .refinement_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global localh\\n\"\n,\"set localh 1\\n\"\n,\"ttk::frame $w.meshsize\\n\"\n,\"ttk::label $w.meshsize.l1 -text \\\"max mesh-size: \\\"\\n\"\n,\"ttk::spinbox $w.meshsize.sp1 -from 1e-6 -to 1e6 -textvariable options.meshsize -validate focus -validatecommand \\\"my_validatespinbox %W %P 4\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -width 6 -increment 0.1\\n\"\n,\"ttk::frame $w.meshsizeloc\\n\"\n,\"ttk::label $w.meshsizeloc.l1 -text \\\"local mesh-size: \\\"\\n\"\n,\"ttk::spinbox $w.meshsizeloc.sp1 -from 1e-6 -to 1e6 -textvariable localh -validate focus -validatecommand \\\"my_validatespinbox %W %P 4\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -width 6 -increment 0.1\\n\"\n,\"pack $w.meshsize\\n\"\n,\"pack $w.meshsizeloc\\n\"\n,\"grid $w.meshsize.l1 $w.meshsize.sp1\\n\"\n,\"grid $w.meshsizeloc.l1 $w.meshsizeloc.sp1\\n\"\n,\"ttk::button $w.restface -text \\\"Restrict H at face\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\".refinement_dlg.meshsize invoke\\n\"\n,\".refinement_dlg.loch invoke\\n\"\n,\"Ng_RestrictH face $localh\\n\"\n,\"}\\n\"\n,\"ttk::button $w.restedge -text \\\"Restrict H at edge\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\".refinement_dlg.meshsize invoke\\n\"\n,\".refinement_dlg.loch invoke\\n\"\n,\"Ng_RestrictH edge $localh\\n\"\n,\"}\\n\"\n,\"ttk::button $w.restelement -text \\\"Restrict H at element\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\".refinement_dlg.meshsize invoke\\n\"\n,\".refinement_dlg.loch invoke\\n\"\n,\"Ng_RestrictH element $localh\\n\"\n,\"}\\n\"\n,\"ttk::button $w.restpoint -text \\\"Restrict H at point\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\".refinement_dlg.meshsize invoke\\n\"\n,\".refinement_dlg.loch invoke\\n\"\n,\"Ng_RestrictH point $localh\\n\"\n,\"}\\n\"\n,\"pack $w.restface $w.restedge $w.restelement $w.restpoint\\n\"\n,\"ttk::button $w.anisoedge -text \\\"Declare Anisotropic edge\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Anisotropy edge\\n\"\n,\"}\\n\"\n,\"pack $w.anisoedge\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.cancle -text \\\"Done\\\" -command \\\"destroy .refinement_dlg\\\"\\n\"\n,\"ttk::button $w.bu.refine -text \\\"Refine\\\"  \\\\\\n\"\n,\"-command {\\n\"\n,\"set oldnp 0; set newnp $status_np;\\n\"\n,\"while { $oldnp < $newnp } {\\n\"\n,\"set level [expr $level+1]\\n\"\n,\"Ng_Bisect;\\n\"\n,\"Ng_HighOrder ${options.elementorder}\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"redraw;\\n\"\n,\"set oldnp $newnp\\n\"\n,\"set newnp $status_np\\n\"\n,\"puts \\\"oldnp $oldnp newnp $newnp\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.zrefine -text \\\"Z-Refine\\\"  \\\\\\n\"\n,\"-command { Ng_ZRefinement; Ng_ReadStatus; redraw; }\\n\"\n,\"pack $w.bu.zrefine $w.bu.refine $w.bu.cancle  -expand yes -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Select Refinement\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc bcpropdialog { } {\\n\"\n,\"set w .bcprop_dlg\\n\"\n,\"if {[winfo exists .bcprop_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::frame $w.face  -borderwidth 3\\n\"\n,\"pack $w.face -fill x\\n\"\n,\"ttk::label $w.face.lab -text \\\"face index:\\\"\\n\"\n,\"ttk::label $w.face.ent -text 1\\n\"\n,\"ttk::button $w.face.next -text \\\"next\\\" -command {\\n\"\n,\"set w .bcprop_dlg;\\n\"\n,\"set facenr [$w.face.ent cget -text]\\n\"\n,\"if {$facenr == [Ng_BCProp getnfd]} {\\n\"\n,\"set facenr 1\\n\"\n,\"} {\\n\"\n,\"set facenr [expr $facenr + 1]\\n\"\n,\"}\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"Ng_BCProp setactive $facenr\\n\"\n,\"set bcnr [Ng_BCProp getbc $facenr]\\n\"\n,\"$w.bc.ent delete 0 end\\n\"\n,\"$w.bc.ent insert 0 $bcnr\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.face.prev -text \\\"prev\\\" -command {\\n\"\n,\"set w .bcprop_dlg;\\n\"\n,\"set facenr [$w.face.ent cget -text]\\n\"\n,\"if {$facenr == 1} {\\n\"\n,\"set facenr [Ng_BCProp getnfd]\\n\"\n,\"} {\\n\"\n,\"set facenr [expr $facenr - 1]\\n\"\n,\"}\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"Ng_BCProp setactive $facenr\\n\"\n,\"set bcnr [Ng_BCProp getbc $facenr]\\n\"\n,\"$w.bc.ent delete 0 end\\n\"\n,\"$w.bc.ent insert 0 $bcnr\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.face.lab $w.face.ent $w.face.prev $w.face.next  -side left\\n\"\n,\"ttk::frame $w.bc  -borderwidth 3\\n\"\n,\"pack $w.bc -fill x\\n\"\n,\"ttk::label $w.bc.lab -text \\\"bc property:\\\"\\n\"\n,\"entry $w.bc.ent -width 5 -relief sunken\\n\"\n,\"ttk::button $w.bc.but -text \\\"change\\\" -command {\\n\"\n,\"set w .bcprop_dlg;\\n\"\n,\"Ng_BCProp setbc [$w.face.ent cget -text] [$w.bc.ent get];\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bc.but2 -text \\\"all\\\" -command {\\n\"\n,\"set w .bcprop_dlg;\\n\"\n,\"Ng_BCProp setall [$w.bc.ent get];\\n\"\n,\"}\\n\"\n,\"pack $w.bc.lab $w.bc.ent $w.bc.but $w.bc.but2 -side left  -expand yes\\n\"\n,\"ttk::frame $w.bcname  -borderwidth 3\\n\"\n,\"pack $w.bcname -fill x\\n\"\n,\"ttk::label $w.bcname.lab -text \\\"bc name:\\\"\\n\"\n,\"ttk::label $w.bcname.ent -text \\\"-\\\"\\n\"\n,\"pack $w.bcname.lab $w.bcname.ent -side left  -expand yes\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.close -text \\\"Close\\\" -command { destroy .bcprop_dlg }\\n\"\n,\"pack $w.bu.close  -expand yes -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Boundary Conditions\\\"\\n\"\n,\"}\\n\"\n,\"focus $w\\n\"\n,\"set facenr [Ng_BCProp getactive]\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"set bcnr [Ng_BCProp getbc $facenr]\\n\"\n,\"$w.bc.ent delete 0 end\\n\"\n,\"$w.bc.ent insert 0 $bcnr\\n\"\n,\"set bcname [Ng_BCProp getbcname $facenr]\\n\"\n,\"$w.bcname.ent configure -text $bcname\\n\"\n,\"}\\n\"\n,\"proc currmeshcoloursdialog { } {\\n\"\n,\"set w .currmeshcolours_dlg\\n\"\n,\"if {[winfo exists .currmeshcolours_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global facecolslist\\n\"\n,\"frame $w.facecols -borderwidth 3\\n\"\n,\"listbox $w.facecols.list -yscroll \\\"$w.facecols.scroll set\\\" -selectmode single -setgrid 1 -width 32 -height 12\\n\"\n,\"scrollbar $w.facecols.scroll -command \\\"$w.facecols.list yview\\\"\\n\"\n,\"pack $w.facecols.scroll -side right -fill y\\n\"\n,\"pack $w.facecols.list -side left -expand yes -fill both\\n\"\n,\"Ng_CurrentFaceColours getcolours facecolslist\\n\"\n,\"set i 1\\n\"\n,\"foreach el $facecolslist {\\n\"\n,\"set hel [format \\\"%d: (%.4f %.4f %.4f)\\\" $i [ lindex $el 0 ] [ lindex $el 1 ] [ lindex $el 2 ]]\\n\"\n,\"incr i\\n\"\n,\"$w.facecols.list insert end $hel }\\n\"\n,\"frame $w.bu1 -borderwidth 3\\n\"\n,\"ttk::button $w.bu1.showonly -text \\\"show only\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours showonly [.currmeshcolours_dlg.facecols.list curselection]\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu1.hideonly -text \\\"hide only\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours hideonly [.currmeshcolours_dlg.facecols.list curselection]\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu1.showalso -text \\\"show\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours showalso [.currmeshcolours_dlg.facecols.list curselection]\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu1.hidealso -text \\\"hide\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours hidealso [.currmeshcolours_dlg.facecols.list curselection]\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.bu1.showonly $w.bu1.hideonly $w.bu1.showalso $w.bu1.hidealso -expand yes -fill x -padx 2 -pady 2 -side left\\n\"\n,\"frame $w.bu2\\n\"\n,\"ttk::button $w.bu2.showall -text \\\"show all\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours showall\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu2.hideall -text \\\"hide all\\\" -command {\\n\"\n,\"Ng_CurrentFaceColours hideall\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.bu2.showall $w.bu2.hideall -expand yes -fill x -padx 2 -pady 2 -side left\\n\"\n,\"frame $w.bu3\\n\"\n,\"ttk::button $w.bu3.close -text \\\"close\\\" -command {\\n\"\n,\"destroy .currmeshcolours_dlg\\n\"\n,\"}\\n\"\n,\"pack $w.bu3.close -expand yes -fill x -pady 3 -side right\\n\"\n,\"pack $w.facecols -side top -expand yes -fill x -fill y\\n\"\n,\"pack $w.bu3 -side bottom\\n\"\n,\"pack $w.bu2 -side bottom\\n\"\n,\"pack $w.bu1 -expand yes -fill x -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Inspect Mesh Colours\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc surfacemeshsizedialog { } {\\n\"\n,\"set w .surfacemeshsize_dlg\\n\"\n,\"if {[winfo exists .surfacemeshsize_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"frame $w.face  -borderwidth 3\\n\"\n,\"pack $w.face -fill x -padx 5\\n\"\n,\"ttk::label $w.face.lab -text \\\"face index:\\\"\\n\"\n,\"ttk::label $w.face.ent -text 1\\n\"\n,\"ttk::button $w.face.next -text \\\"next\\\" -command {\\n\"\n,\"set w .surfacemeshsize_dlg;\\n\"\n,\"set facenr [$w.face.ent cget -text]\\n\"\n,\"if {$facenr == [Ng_SurfaceMeshSize getnfd]} {\\n\"\n,\"set facenr 1\\n\"\n,\"} {\\n\"\n,\"set facenr [expr $facenr + 1]\\n\"\n,\"}\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"Ng_SurfaceMeshSize setactive $facenr\\n\"\n,\"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\\n\"\n,\"$w.sms.ent delete 0 end\\n\"\n,\"$w.sms.ent insert 0 $surfms\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.face.prev -text \\\"prev\\\" -command {\\n\"\n,\"set w .surfacemeshsize_dlg;\\n\"\n,\"set facenr [$w.face.ent cget -text]\\n\"\n,\"if {$facenr == 1} {\\n\"\n,\"set facenr [Ng_SurfaceMeshSize getnfd]\\n\"\n,\"} {\\n\"\n,\"set facenr [expr $facenr - 1]\\n\"\n,\"}\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"Ng_SurfaceMeshSize setactive $facenr\\n\"\n,\"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\\n\"\n,\"$w.sms.ent delete 0 end\\n\"\n,\"$w.sms.ent insert 0 $surfms\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.face.lab $w.face.ent $w.face.prev $w.face.next  -side left\\n\"\n,\"frame $w.sms  -borderwidth 3\\n\"\n,\"pack $w.sms -fill x\\n\"\n,\"ttk::label $w.sms.lab -text \\\"max mesh size:\\\"\\n\"\n,\"entry $w.sms.ent -width 8 -relief sunken\\n\"\n,\"ttk::button $w.sms.but -text \\\"change\\\" -command {\\n\"\n,\"set w .surfacemeshsize_dlg;\\n\"\n,\"Ng_SurfaceMeshSize setsurfms [$w.face.ent cget -text] [$w.sms.ent get];\\n\"\n,\"}\\n\"\n,\"ttk::button $w.sms.but2 -text \\\"all\\\" -command {\\n\"\n,\"set w .surfacemeshsize_dlg;\\n\"\n,\"Ng_SurfaceMeshSize setall [$w.sms.ent get];\\n\"\n,\"}\\n\"\n,\"pack $w.sms.lab $w.sms.ent $w.sms.but $w.sms.but2 -side left -padx 5 -expand yes\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.close -text \\\"Close\\\" -command { destroy .surfacemeshsize_dlg }\\n\"\n,\"pack $w.bu.close  -expand yes -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Edit Surface Mesh Size\\\"\\n\"\n,\"}\\n\"\n,\"focus $w\\n\"\n,\"set facenr [Ng_SurfaceMeshSize getactive]\\n\"\n,\"$w.face.ent configure -text $facenr\\n\"\n,\"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\\n\"\n,\"$w.sms.ent delete 0 end\\n\"\n,\"$w.sms.ent insert 0 $surfms\\n\"\n,\"}\\n\"\n,\"proc METISdialog { } {\\n\"\n,\"set w .metis_dlg\\n\"\n,\"set w.parts 64\\n\"\n,\"if {[winfo exists .metis_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"frame $w.a -borderwidth 0\\n\"\n,\"frame $w.b -borderwidth 0\\n\"\n,\"pack $w.a $w.b\\n\"\n,\"ttk::label $w.a.lab -text \\\"Number of partitions:\\\"\\n\"\n,\"entry $w.a.ent -textvariable w.parts -width 4 -relief sunken\\n\"\n,\"ttk::button $w.b.start -text \\\"Start METIS\\\" -command {\\n\"\n,\"Ng_Metis ${w.parts}\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.b.cancel -text \\\"Cancel\\\" -command { destroy .metis_dlg }\\n\"\n,\"pack $w.a.lab $w.a.ent -side left  -expand yes\\n\"\n,\"pack $w.b.start $w.b.cancel -side left\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"METIS Partitioning\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc stloptionsdialog { } {\\n\"\n,\"set w .stlopts_dlg\\n\"\n,\"if {[winfo exists .stlopts_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"pack [ttk::notebook $w.nb]  -fill both -fill both -side top\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.apply -text \\\"Apply\\\" -command { redraw; Ng_GenerateMesh 1 2}\\n\"\n,\"ttk::button $w.bu.cancle -text \\\"Done\\\" -command { destroy .stlopts_dlg }\\n\"\n,\"pack $w.bu.cancle  $w.bu.apply  -side left -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"STL Options\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc stldoctordialog { } {\\n\"\n,\"Ng_STLDoctor\\n\"\n,\"set wd .stldoctor_dlg\\n\"\n,\"if {[winfo exists .stldoctor_dlg] == 1} {\\n\"\n,\"wm withdraw $wd\\n\"\n,\"wm deiconify $wd\\n\"\n,\"focus $wd\\n\"\n,\"} {\\n\"\n,\"toplevel $wd\\n\"\n,\"pack [ttk::notebook $wd.nb] -fill both -fill both -side top\\n\"\n,\"$wd.nb add [ttk::frame $wd.nb.general] -text \\\"General\\\" -underline 0\\n\"\n,\"$wd.nb add [ttk::frame $wd.nb.topology] -text \\\"Edit Topology\\\" -underline 5\\n\"\n,\"$wd.nb add [ttk::frame $wd.nb.edges] -text \\\"Edit Edges\\\" -underline 5\\n\"\n,\"$wd.nb add [ttk::frame $wd.nb.normals] -text \\\"Edit Normals\\\" -underline 5\\n\"\n,\"$wd.nb add [ttk::frame $wd.nb.advanced] -text \\\"Advanced\\\" -underline 0\\n\"\n,\"set f $wd.nb.general\\n\"\n,\"ttk::frame $f.selectframe -borderwidth 0\\n\"\n,\"ttk::checkbutton $f.selectframe.showtrias -text \\\"Show STL-Triangles\\\" \\\\\\n\"\n,\"-variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $f.selectframe.showfilledtrias -text \\\"Show Filled Triangles\\\" \\\\\\n\"\n,\"-variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\\n\"\n,\"set selmodevals { 0 1 2 3 4 }\\n\"\n,\"set selmodelabs(0) \\\"triangle\\\"\\n\"\n,\"set selmodelabs(1) \\\"edge\\\"\\n\"\n,\"set selmodelabs(2) \\\"point\\\"\\n\"\n,\"set selmodelabs(3) \\\"line\\\"\\n\"\n,\"set selmodelabs(4) \\\"line cluster\\\"\\n\"\n,\"global stldoctor.selectmode\\n\"\n,\"ttk::label  $f.selectframe.dblcsellab -text \\\"Double Click selects : \\\"\\n\"\n,\"ttk::menubutton $f.selectframe.dblcselbut -menu $f.selectframe.dblcselmen -text \\\"triangle\\\" -width 16\\n\"\n,\"menu $f.selectframe.dblcselmen  -tearoff 0\\n\"\n,\"foreach selmode { 0 1 2 3 4 } {\\n\"\n,\"$f.selectframe.dblcselmen add command -label $selmodelabs($selmode) \\\\\\n\"\n,\"-command \\\"set stldoctor.selectmode $selmode ; Ng_STLDoctor ; $f.selectframe.dblcselbut configure -text \\\\\\\"$selmodelabs($selmode)\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$f.selectframe.dblcselmen invoke $selmodelabs(${stldoctor.selectmode})\\n\"\n,\"pack $f.selectframe\\n\"\n,\"grid $f.selectframe.showtrias -sticky nw\\n\"\n,\"grid $f.selectframe.showfilledtrias -sticky nw\\n\"\n,\"grid $f.selectframe.dblcsellab $f.selectframe.dblcselbut -sticky nw\\n\"\n,\"ttk::frame $f.sm\\n\"\n,\"pack $f.sm -fill x\\n\"\n,\"ttk::checkbutton $f.sm.bu -text \\\"select with mouse\\\" \\\\\\n\"\n,\"-variable stldoctor.selectwithmouse\\n\"\n,\"pack $f.sm.bu\\n\"\n,\"ttk::frame $f.st -relief groove -borderwidth 3\\n\"\n,\"pack $f.st -fill x\\n\"\n,\"ttk::label $f.st.lab -text \\\"Select triangle by number\\\";\\n\"\n,\"ttk::entry $f.st.ent -width 5 \\\\\\n\"\n,\"-textvariable stldoctor.selecttrig\\n\"\n,\"pack $f.st.ent $f.st.lab -side left -expand yes\\n\"\n,\"ttk::frame $f.vc -relief groove -borderwidth 3\\n\"\n,\"pack $f.vc -fill x\\n\"\n,\"ttk::checkbutton $f.vc.bu -text \\\"show vicinity\\\" \\\\\\n\"\n,\"-variable stldoctor.showvicinity \\\\\\n\"\n,\"-command {Ng_STLDoctor vicinity; redraw}\\n\"\n,\"ttk::label $f.vc.lab -text \\\"vicinity size\\\";\\n\"\n,\"ttk::frame $f.vc.sc\\n\"\n,\"ttk::scale $f.vc.sc.scale -orient horizontal -length 200 -from 0 -to 200 \\\\\\n\"\n,\"-variable stldoctor.vicinity -takefocus 0 -command \\\"Ng_STLDoctor vicinity; redraw; roundscale $f.vc.sc.scale 0\\\"\\n\"\n,\"ttk::entry $f.vc.sc.entry -textvariable stldoctor.vicinity -width 3 \\\\\\n\"\n,\"-validatecommand \\\"Ng_STLDoctor vicinity; redraw; my_validate %W [$f.vc.sc.scale cget -from] [$f.vc.sc.scale cget -to] %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_STLDoctor vicinity; redraw;\\\" -validate focus\\n\"\n,\"ttk::label $f.vc.sc.lab -text \\\"vicinity size\\\"\\n\"\n,\"grid $f.vc.sc.scale $f.vc.sc.entry $f.vc.sc.lab -sticky nw -padx 4\\n\"\n,\"pack $f.vc.bu $f.vc.lab $f.vc.sc -expand yes\\n\"\n,\"ttk::frame $f.ge -relief groove -borderwidth 0\\n\"\n,\"pack $f.ge -expand yes\\n\"\n,\"ttk::button $f.ge.neighbourangles -text \\\"calc neighbourangles\\\" -command {Ng_STLDoctor neighbourangles}\\n\"\n,\"ttk::button $f.ge.showcoords -text \\\"show coords of touched triangle\\\" -command {Ng_STLDoctor showcoords}\\n\"\n,\"ttk::button $f.ge.moveptm -text \\\"move point to middle of trianglepoints\\\" -command {Ng_STLDoctor movepointtomiddle; redraw}\\n\"\n,\"ttk::button $f.ge.destroy0trigs -text \\\"destroy 0-volume triangles\\\" -command {Ng_STLDoctor destroy0trigs}\\n\"\n,\"grid $f.ge.neighbourangles -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.ge.showcoords -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.ge.moveptm -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.ge.destroy0trigs -sticky nw -padx 4 -pady 4\\n\"\n,\"ttk::button $f.ge.cancle -text \\\"Done\\\" -command {destroy .stldoctor_dlg }\\n\"\n,\"grid $f.ge.cancle  -sticky nw\\n\"\n,\"set f $wd.nb.topology\\n\"\n,\"ttk::frame $f.oc -relief groove -borderwidth 3\\n\"\n,\"pack $f.oc -pady 3 -ipady 3 -fill y -fill x\\n\"\n,\"ttk::frame $f.oc.oc1 -borderwidth 0\\n\"\n,\"pack $f.oc.oc1\\n\"\n,\"ttk::button $f.oc.oc1.bu -text \\\"invert orientation \\\\n of selected trig\\\" -command {Ng_STLDoctor invertselectedtrig; redraw }\\n\"\n,\"ttk::button $f.oc.oc1.bu2 -text \\\"orient after \\\\n selected trig\\\" -command {Ng_STLDoctor orientafterselectedtrig; redraw }\\n\"\n,\"ttk::button $f.oc.oc1.toperr -text \\\"mark inconsistent triangles\\\" -command {Ng_STLDoctor marktoperrortrigs; redraw }\\n\"\n,\"ttk::button $f.oc.oc1.deltrig -text \\\"delete selected triangle\\\" -command {Ng_STLDoctor deleteselectedtrig; redraw }\\n\"\n,\"ttk::button $f.oc.oc1.geosmooth -text \\\"geometric smoothing\\\" -command {Ng_STLDoctor smoothgeometry; redraw }\\n\"\n,\"grid $f.oc.oc1.bu x $f.oc.oc1.bu2 -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.oc.oc1.toperr - x -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.oc.oc1.deltrig - x -sticky nw -padx 4 -pady 4\\n\"\n,\"grid $f.oc.oc1.geosmooth - x -sticky nw -padx 4 -pady 4\\n\"\n,\"set f $wd.nb.edges\\n\"\n,\"ttk::frame $f.be -relief groove -borderwidth 3\\n\"\n,\"pack $f.be -fill x\\n\"\n,\"ttk::frame $f.be.frame\\n\"\n,\"pack $f.be.frame -ipady 4 -pady 4\\n\"\n,\"ttk::label $f.be.frame.lab -text \\\"build edges with yellow angle:\\\";\\n\"\n,\"ttk::scale $f.be.frame.scale -orient horizontal -length 200 -from 0 -to 200 \\\\\\n\"\n,\"-variable stloptions.yangle -takefocus 0 -command \\\"roundscale $f.be.frame.scale 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\\\"\\n\"\n,\"ttk::entry $f.be.frame.entry -textvariable stloptions.yangle -width 5 \\\\\\n\"\n,\"-validatecommand \\\"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale cget -from] [$f.be.frame.scale cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\\\" -validate focus\\n\"\n,\"grid $f.be.frame.lab - -sticky nw -padx 4\\n\"\n,\"grid $f.be.frame.scale $f.be.frame.entry -sticky nw -padx 4\\n\"\n,\"ttk::label $f.be.frame.lab2 -text \\\"continue edges with yellow angle:\\\";\\n\"\n,\"ttk::scale $f.be.frame.scale2 -orient horizontal -length 200 -from 0 -to 100 \\\\\\n\"\n,\"-variable stloptions.contyangle -takefocus 0 -command \\\"roundscale $f.be.frame.scale2 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\\\"\\n\"\n,\"ttk::entry $f.be.frame.entry2 -textvariable stloptions.contyangle -width 5 \\\\\\n\"\n,\"-validatecommand \\\"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale2 cget -from] [$f.be.frame.scale2 cget -to] %P 1\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\\\" -validate focus\\n\"\n,\"grid $f.be.frame.lab2 - -sticky nw -padx 4\\n\"\n,\"grid $f.be.frame.scale2 $f.be.frame.entry2 -sticky nw -padx 4\\n\"\n,\"ttk::button $f.be.frame.buildedges -text \\\"Build Edges\\\" -command {Ng_STLDoctor buildedges; redraw}\\n\"\n,\"grid $f.be.frame.buildedges - -sticky n -padx 4 -pady 4\\n\"\n,\"ttk::frame $f.se -relief groove -borderwidth 3\\n\"\n,\"pack $f.se -fill x\\n\"\n,\"ttk::checkbutton $f.se.bu -text \\\"show excluded\\\" \\\\\\n\"\n,\"-variable stldoctor.showexcluded \\\\\\n\"\n,\"-command {Ng_STLDoctor; redraw}\\n\"\n,\"pack $f.se.bu\\n\"\n,\"set edgeselmodevals { 0 1 2 3 4 }\\n\"\n,\"set edgeselmodelabs(0) \\\"no change\\\"\\n\"\n,\"set edgeselmodelabs(1) \\\"undefined\\\"\\n\"\n,\"set edgeselmodelabs(2) \\\"confirmed\\\"\\n\"\n,\"set edgeselmodelabs(3) \\\"candidate\\\"\\n\"\n,\"set edgeselmodelabs(4) \\\"excluded\\\"\\n\"\n,\"global stldoctor.edgeselectmode\\n\"\n,\"ttk::frame $f.scaleframe -relief groove -borderwidth 0\\n\"\n,\"pack $f.scaleframe -ipadx 4 -pady 4 -expand yes\\n\"\n,\"ttk::label  $f.scaleframe.dblcedgelab -text \\\"Double Click sets edge :\\\"\\n\"\n,\"ttk::menubutton $f.scaleframe.dblcledgebut -menu $f.scaleframe.dblcledgem -text \\\"coarse\\\" -width 16\\n\"\n,\"menu $f.scaleframe.dblcledgem  -tearoff 0\\n\"\n,\"foreach selectmode { 0 1 2 3 4 } {\\n\"\n,\"$f.scaleframe.dblcledgem add command -label $edgeselmodelabs($selectmode) \\\\\\n\"\n,\"-command \\\"set stldoctor.edgeselectmode $selectmode ; $f.scaleframe.dblcledgebut configure -text \\\\\\\"$edgeselmodelabs($selectmode)\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$f.scaleframe.dblcledgem invoke $edgeselmodelabs(${stldoctor.edgeselectmode})\\n\"\n,\"grid $f.scaleframe.dblcedgelab $f.scaleframe.dblcledgebut -sticky n -ipadx 4\\n\"\n,\"ttk::frame $f.edg -relief groove -borderwidth 3\\n\"\n,\"pack $f.edg -fill x -ipadx 4 -ipady 4\\n\"\n,\"ttk::frame $f.edg.f0\\n\"\n,\"pack $f.edg.f0\\n\"\n,\"ttk::button $f.edg.f0.confirmedge -text \\\"confirm\\\" -command {Ng_STLDoctor confirmedge; redraw}\\n\"\n,\"ttk::button $f.edg.f0.candidateedge -text \\\"candidate\\\" -command {Ng_STLDoctor candidateedge; redraw}\\n\"\n,\"ttk::button $f.edg.f0.excludeedge -text \\\"exclude\\\" -command {Ng_STLDoctor excludeedge; redraw}\\n\"\n,\"ttk::button $f.edg.f0.undefinededge -text \\\"undefined\\\" -command {Ng_STLDoctor undefinededge; redraw}\\n\"\n,\"pack $f.edg.f0.confirmedge $f.edg.f0.candidateedge $f.edg.f0.excludeedge $f.edg.f0.undefinededge  -side left\\n\"\n,\"ttk::frame $f.edg.fa\\n\"\n,\"pack $f.edg.fa\\n\"\n,\"ttk::button $f.edg.fa.setallundefined -text \\\"all undefined\\\" -command {Ng_STLDoctor setallundefinededges; redraw}\\n\"\n,\"ttk::button $f.edg.fa.erasecandidates -text \\\"candidates to undefined\\\" -command {Ng_STLDoctor erasecandidateedges; redraw}\\n\"\n,\"pack $f.edg.fa.setallundefined $f.edg.fa.erasecandidates -side left\\n\"\n,\"ttk::frame $f.edg.fb\\n\"\n,\"pack $f.edg.fb\\n\"\n,\"ttk::button $f.edg.fb.confirmcandidates -text \\\"candidates to confirmed\\\" -command {Ng_STLDoctor confirmcandidateedges; redraw}\\n\"\n,\"ttk::button $f.edg.fb.confirmedtocandidates -text \\\"confirmed to candidates\\\" -command {Ng_STLDoctor confirmedtocandidateedges; redraw}\\n\"\n,\"pack $f.edg.fb.confirmcandidates $f.edg.fb.confirmedtocandidates -side left\\n\"\n,\"ttk::frame $f.edg.f1\\n\"\n,\"ttk::frame $f.edg.f2\\n\"\n,\"ttk::frame $f.edg.f3\\n\"\n,\"ttk::frame $f.edg.f4\\n\"\n,\"pack $f.edg.f1 $f.edg.f2 $f.edg.f3 $f.edg.f4\\n\"\n,\"ttk::button $f.edg.f1.exportedges -text \\\"export edges\\\" -command {Ng_STLDoctor exportedges}\\n\"\n,\"ttk::button $f.edg.f1.importedges -text \\\"import edges\\\" -command {Ng_STLDoctor importedges; redraw}\\n\"\n,\"ttk::button $f.edg.f1.saveedgedata -text \\\"save edgedata\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Netgen Edgedata\\\"   {.ned} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getSaveFile -filetypes $types -defaultextension \\\".ned\\\"]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_STLDoctor saveedgedata $file\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $f.edg.f1.loadedgedata -text \\\"load edgedata\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{\\\"Netgen Edgedata\\\"  {.ned} }\\n\"\n,\"}\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".ned\\\"]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_STLDoctor loadedgedata $file\\n\"\n,\"puts \\\"loading done\\\"\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $f.edg.f1.importAVLedges -text \\\"import AVL edges\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {{\\\"Edge file\\\"  {.edg }}}\\n\"\n,\"set file [tk_getOpenFile -filetypes $types -defaultextension \\\".edg\\\"]\\n\"\n,\"if {$file != \\\"\\\"} {\\n\"\n,\"Ng_STLDoctor importexternaledges $file;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $f.edg.f1.importAVLedges $f.edg.f1.loadedgedata $f.edg.f1.saveedgedata -side left\\n\"\n,\"ttk::frame $f.edg2 -relief groove -borderwidth 3\\n\"\n,\"pack $f.edg2 -fill x\\n\"\n,\"ttk::label $f.edg2.lab -text \\\"length (%):\\\"\\n\"\n,\"scale $f.edg2.sc -orient horizontal -length 200 -from 0 -to 100 \\\\\\n\"\n,\"-resolution 0.5 \\\\\\n\"\n,\"-variable stldoctor.longlinefact\\n\"\n,\"ttk::button $f.edg2.undoedge -text \\\"undo last edge change\\\" -command {Ng_STLDoctor undoedgechange; redraw}\\n\"\n,\"pack $f.edg2.undoedge -expand yes\\n\"\n,\"set f $wd.nb.normals\\n\"\n,\"ttk::frame $f.dt -relief groove -borderwidth 3\\n\"\n,\"pack $f.dt -fill x\\n\"\n,\"ttk::label $f.dt.lab -text \\\"dirty triangle factor\\\";\\n\"\n,\"ttk::entry $f.dt.ent -width 5 \\\\\\n\"\n,\"-textvariable stldoctor.dirtytrigfact -validatecommand \\\"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetSTLParameters\\\" -validate focus\\n\"\n,\"pack $f.dt.ent $f.dt.lab -side left -expand yes -pady 8\\n\"\n,\"ttk::frame $f.srt -relief groove -borderwidth 3\\n\"\n,\"pack $f.srt -fill x\\n\"\n,\"ttk::button $f.srt.bu -text \\\"smooth reverted triangles geometric\\\" -command {Ng_STLDoctor smoothrevertedtrigs; redraw }\\n\"\n,\"ttk::entry $f.srt.ent -width 5 \\\\\\n\"\n,\"-textvariable stldoctor.smoothangle -validatecommand \\\"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetSTLParameters\\\" -validate focus\\n\"\n,\"pack $f.srt.ent $f.srt.bu -side left  -expand yes -pady 8\\n\"\n,\"ttk::frame $f.bdt -relief groove -borderwidth 3\\n\"\n,\"pack $f.bdt -fill x\\n\"\n,\"ttk::button $f.bdt.bu -text \\\"mark dirty triangles\\\" -command {Ng_STLDoctor markdirtytrigs; redraw }\\n\"\n,\"ttk::button $f.bdt.bu2 -text \\\"smooth dirty triangles normal\\\" -command {Ng_STLDoctor smoothdirtytrigs; redraw }\\n\"\n,\"pack $f.bdt.bu $f.bdt.bu2 -side left  -expand yes -pady 8\\n\"\n,\"ttk::frame $f.sno -relief groove -borderwidth 3\\n\"\n,\"pack $f.sno -fill x\\n\"\n,\"ttk::frame $f.sno.snoframe -borderwidth 0\\n\"\n,\"ttk::button $f.sno.smoothnormals -text \\\"smooth normals\\\" -command { Ng_STLDoctor smoothnormals; redraw}\\n\"\n,\"ttk::scale $f.sno.snoframe.scale -orient horizontal -length 100 -from 0.0 -to 0.8 \\\\\\n\"\n,\"-variable stldoctor.smoothnormalsweight -takefocus 0 -command \\\"roundscale $f.sno.snoframe.scale 2;Ng_SetSTLParameters\\\"\\n\"\n,\"ttk::entry $f.sno.snoframe.entry -textvariable stldoctor.smoothnormalsweight -width 4 \\\\\\n\"\n,\"-validatecommand \\\"Ng_SetSTLParameters;my_validate %W [$f.sno.snoframe.scale cget -from] [$f.sno.snoframe.scale cget -to] %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;Ng_SetSTLParameters\\\" -validate focus\\n\"\n,\"ttk::label $f.sno.snoframe.labrough -text \\\"rough\\\"\\n\"\n,\"ttk::label $f.sno.snoframe.labsmooth -text \\\"smooth\\\"\\n\"\n,\"grid $f.sno.snoframe.labrough $f.sno.snoframe.scale $f.sno.snoframe.labsmooth $f.sno.snoframe.entry -sticky nw -padx 4\\n\"\n,\"pack $f.sno.snoframe $f.sno.smoothnormals -side left -padx 5 -pady 8\\n\"\n,\"ttk::frame $f.no -relief groove -borderwidth 3\\n\"\n,\"pack $f.no -fill x\\n\"\n,\"ttk::button $f.no.marknonsmoothnormals -text \\\"mark non-smooth triangles\\\" -command {Ng_STLDoctor marknonsmoothnormals; redraw}\\n\"\n,\"ttk::button $f.no.calcnormals -text \\\"calculate normals from geometry\\\" -command {Ng_STLDoctor calcnormals; redraw}\\n\"\n,\"pack $f.no.marknonsmoothnormals $f.no.calcnormals -expand yes -pady 8\\n\"\n,\"set f $wd.nb.advanced\\n\"\n,\"ttk::frame $f.sc\\n\"\n,\"pack $f.sc -fill x\\n\"\n,\"ttk::checkbutton $f.sc.bu -text \\\"spiral check\\\" \\\\\\n\"\n,\"-variable stldoctor.spiralcheck \\\\\\n\"\n,\"-command {Ng_STLDoctor;}\\n\"\n,\"ttk::checkbutton $f.sc.bu2 -text \\\"cone check\\\" \\\\\\n\"\n,\"-variable stldoctor.conecheck \\\\\\n\"\n,\"-command {Ng_STLDoctor;}\\n\"\n,\"pack $f.sc.bu $f.sc.bu2\\n\"\n,\"ttk::label $f.gtol_lbl -text \\\"LoadSTL tolerance factor\\\"\\n\"\n,\"ttk::spinbox $f.gtol -from 1e-15 -to 0.001 -textvariable stldoctor.geom_tol_fact -width 8\\n\"\n,\"pack $f.gtol_lbl $f.gtol\\n\"\n,\"ttk::button $f.adap -text \\\"Apply\\\" -command {\\n\"\n,\"Ng_STLDoctor;\\n\"\n,\"}\\n\"\n,\"pack $f.adap -expand yes\\n\"\n,\"wm withdraw $wd\\n\"\n,\"wm geom $wd +100+100\\n\"\n,\"wm deiconify $wd\\n\"\n,\"wm title $wd \\\"STL Doctor\\\"\\n\"\n,\"focus $wd\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc meshdoctordialog { } {\\n\"\n,\"set w .meshdoc_dlg\\n\"\n,\"global meshdoctor.active\\n\"\n,\"if {[winfo exists .meshdoc_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"set meshdoctor.active 1\\n\"\n,\"Ng_MeshDoctor;\\n\"\n,\"ttk::frame $w.vis -relief groove -borderwidth 3\\n\"\n,\"pack $w.vis\\n\"\n,\"ttk::checkbutton $w.vis.showfilledtrigs -text \\\"Show filled triangles\\\" \\\\\\n\"\n,\"-variable viewoptions.drawfilledtrigs \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $w.vis.showedges -text \\\"Show edges\\\" \\\\\\n\"\n,\"-variable viewoptions.drawedges \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"ttk::checkbutton $w.vis.showoutline -text \\\"Show Triangle Outline\\\" \\\\\\n\"\n,\"-variable viewoptions.drawoutline \\\\\\n\"\n,\"-command { Ng_SetVisParameters; redraw }\\n\"\n,\"pack $w.vis.showfilledtrigs  $w.vis.showoutline $w.vis.showedges\\n\"\n,\"ttk::frame $w.markedgedist\\n\"\n,\"ttk::label $w.markedgedist.l -text \\\"Mark edge dist: \\\"\\n\"\n,\"ttk::spinbox $w.markedgedist.s -from 0 -to 999 -width 5 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -command {Ng_MeshDoctor markedgedist ${meshdoc.markedgedist};redraw} -textvariable meshdoc.markedgedist\\n\"\n,\"pack $w.markedgedist.l $w.markedgedist.s -side left\\n\"\n,\"pack $w.markedgedist\\n\"\n,\"ttk::button $w.deledge -text \\\"Delete marked segments\\\" -command {\\n\"\n,\"Ng_MeshDoctor deletemarkedsegments\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"pack $w.deledge\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" -command {\\n\"\n,\"set meshdoctor.active 0;\\n\"\n,\"Ng_MeshDoctor;\\n\"\n,\"destroy .meshdoc_dlg\\n\"\n,\"}\\n\"\n,\"pack $w.close -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Mesh Doctor\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc qualityviewdialog { show } {\\n\"\n,\"set w .qualityview_dlg\\n\"\n,\"if {[winfo exists .qualityview_dlg] == 1} {\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw .qualityview_dlg\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"set c $w.c\\n\"\n,\"canvas $c -relief raised -width 450 -height 300\\n\"\n,\"pack $w.c -side top -fill x\\n\"\n,\"set plotFont {Helvetica 12}\\n\"\n,\"set smallFont {Helvetica 12}\\n\"\n,\"$c create line 100 250 400 250 -width 2\\n\"\n,\"$c create line 100 250 100 50 -width 2\\n\"\n,\"for {set i 0} {$i <= 10} {incr i} {\\n\"\n,\"set x [expr {100 + ($i*30)}]\\n\"\n,\"$c create line $x 250 $x 245 -width 2\\n\"\n,\"if { [expr {$i % 2}] == 0 } {\\n\"\n,\"$c create text $x 254 -text [format %1.1f [expr 0.1*$i]] -anchor n -font $plotFont\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"global qualbar\\n\"\n,\"global qualbarnull\\n\"\n,\"global qualbaraxis\\n\"\n,\"for {set i 0} {$i <= 5} {incr i} {\\n\"\n,\"set y [expr {250 - ($i*40)}]\\n\"\n,\"$c create line 100 $y 105 $y -width 2\\n\"\n,\"set qualbaraxis($i) \\\\\\n\"\n,\"[$c create text 96 $y -text [expr $i*50].0 -anchor e -font $plotFont]\\n\"\n,\"}\\n\"\n,\"for {set i 0} {$i < 20} {incr i} {\\n\"\n,\"set x1 [expr {100 + ($i*15) + 2}]\\n\"\n,\"set x2 [expr {$x1+10}]\\n\"\n,\"set y [expr {250 - 10 * $i}]\\n\"\n,\"set qualbar($i) [$c create rectangle $x1 250 $x2 245 -fill blue]\\n\"\n,\"set qualbarnull($i) [$c create text [expr {($x1+$x2)/2}] 245 -text 0 -anchor s -font $smallFont -fill blue]\\n\"\n,\"}\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"wm withdraw .qualityview_dlg\\n\"\n,\"set viewqualityplot 0\\n\"\n,\"}\\n\"\n,\"pack $w.close\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Mesh Quality\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc memusedialog { show } {\\n\"\n,\"set w .memuse_dlg\\n\"\n,\"if {[winfo exists .memuse_dlg] == 1} {\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw .memuse_dlg\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"set c $w.c\\n\"\n,\"canvas $c -relief raised -width 600 -height 300\\n\"\n,\"pack $w.c -side top -fill x\\n\"\n,\"set plotFont {Helvetica 18}\\n\"\n,\"set smallFont {Helvetica 12}\\n\"\n,\"global memmark\\n\"\n,\"for {set i 0} {$i < 512} { incr i } {\\n\"\n,\"set memmark($i) [$c create line [expr 50+$i] 50 [expr 50+$i] 70 -fill blue]\\n\"\n,\"}\\n\"\n,\"set plotFont {Helvetica 18}\\n\"\n,\"set smallFont {Helvetica 12}\\n\"\n,\"$c create text 50 90 -text \\\"0 GB\\\" -anchor n -font $plotFont\\n\"\n,\"$c create text 178 90 -text \\\"1 GB\\\" -anchor n -font $plotFont\\n\"\n,\"$c create text 306 90 -text \\\"2 GB\\\" -anchor n -font $plotFont\\n\"\n,\"$c create text 434 90 -text \\\"3 GB\\\" -anchor n -font $plotFont\\n\"\n,\"$c create text 562 90 -text \\\"4 GB\\\" -anchor n -font $plotFont\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"wm withdraw .memuse_dlg\\n\"\n,\"set memuseplot 0\\n\"\n,\"}\\n\"\n,\"pack $w.close\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Memory Usage\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc STLinfodialog { show } {\\n\"\n,\"set w .STLinfo_dlg\\n\"\n,\"if {[winfo exists .STLinfo_dlg] == 1} {\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw .STLinfo_dlg\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"set c $w.c\\n\"\n,\"canvas $c -relief raised -width 450 -height 300\\n\"\n,\"pack $w.c -side top -fill x\\n\"\n,\"set plotFont {Helvetica 18}\\n\"\n,\"set smallFont {Helvetica 12}\\n\"\n,\"$c create line 100 250 400 250 -width 2\\n\"\n,\"$c create line 100 250 100 50 -width 2\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"wm withdraw .STLinfo_dlg\\n\"\n,\"}\\n\"\n,\"pack $w.close\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"STL Geometry Info\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc logwindow { } {\\n\"\n,\"set w .logwindow\\n\"\n,\"if {[winfo exists .logwindow] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"text $w.edit -yscroll \\\"$w.scrolly set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.scrolly -command \\\"$w.edit yview\\\"\\n\"\n,\"pack $w.edit -side left -fill both -expand 1\\n\"\n,\"pack $w.scrolly -side left -fill both -expand 0\\n\"\n,\".logwindow.edit insert end \\\"Netgen Log Window\\\\n\\\"\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Netgen Log\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc printtable { tablevar } {\\n\"\n,\"set w newtcltable\\n\"\n,\"while {[winfo exists .$w] == 1} {set w 1$w}\\n\"\n,\"set w .$w\\n\"\n,\"toplevel $w\\n\"\n,\"for {set i 0} {$i < [lindex $tablevar 2]} { incr i } {\\n\"\n,\"frame $w.col$i\\n\"\n,\"for {set j 0} {$j < [lindex $tablevar 1]} { incr j } {\\n\"\n,\"frame $w.col$i.row$j\\n\"\n,\"message $w.col$i.row$j.txt -aspect 10000000 -text [lindex $tablevar [expr 3+[lindex $tablevar 2]*$j+$i]]\\n\"\n,\"pack $w.col$i.row$j.txt\\n\"\n,\"pack $w.col$i.row$j -side top\\n\"\n,\"}\\n\"\n,\"pack $w.col$i -side left\\n\"\n,\"}\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +200+100; wm deiconify $w\\n\"\n,\"wm title $w [lindex $tablevar 0]\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"set latestwarning 0\\n\"\n,\"proc printwarning { textvar } {\\n\"\n,\"global latestwarning\\n\"\n,\"set latestwarning $textvar\\n\"\n,\"set w warning\\n\"\n,\"while {[winfo exists .$w] == 1} {set w 1$w}\\n\"\n,\"set w .$w\\n\"\n,\"toplevel $w\\n\"\n,\"message $w.mes -aspect 2000 -text \\\"WARNING:\\\\n$textvar\\\"\\n\"\n,\"ttk::button $w.done -text \\\"Done\\\" -command \\\"destroy $w\\\"\\n\"\n,\"pack $w.mes\\n\"\n,\"pack $w.done\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Warning\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"proc printlatestwarning { } {\\n\"\n,\"global latestwarning\\n\"\n,\"if {$latestwarning != 0} {printwarning $latestwarning}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch {\\n\"\n,\"set oldmousex 0\\n\"\n,\"set oldmousey 0\\n\"\n,\"set toglversion [Ng_GetToglVersion]\\n\"\n,\"puts \\\"togl-version : $toglversion\\\"\\n\"\n,\"set toglok 0\\n\"\n,\"if { [Ng_GetToglVersion] == 2 } {\\n\"\n,\"if {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false  -create init  -display draw -reshape reshape }] } {\\n\"\n,\"puts \\\"no OpenGL\\\"\\n\"\n,\"} {\\n\"\n,\"set toglok 1\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"if {[catch {togl .ndraw -width 400 -height 300  -rgba true -double true -depth true -privatecmap false -stereo false -indirect false  }] } {\\n\"\n,\"puts \\\"no OpenGL\\\"\\n\"\n,\"} {\\n\"\n,\"set toglok 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { $toglok == 1} {\\n\"\n,\"pack .ndraw -expand true -fill both -padx 0 -pady 0\\n\"\n,\"catch { tkdnd::drop_target register .ndraw DND_Files }\\n\"\n,\"bind .ndraw <Button-1> {\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <Button-2> {\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <Button-3> {\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <B1-Motion> {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y $drawmode\\n\"\n,\".ndraw render\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <Double-1> {\\n\"\n,\"Ng_MouseDblClick %x %y\\n\"\n,\".ndraw render\\n\"\n,\"if { [winfo exists .bcprop_dlg] } { bcpropdialog }\\n\"\n,\"if { [winfo exists .surfacemeshsize_dlg] } { surfacemeshsizedialog }\\n\"\n,\"if { [winfo exists .fieldlines_dlg] } { fieldlinesdialog }\\n\"\n,\"}\\n\"\n,\"bind .ndraw <B2-Motion> {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y move\\n\"\n,\".ndraw render\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <B3-Motion> {\\n\"\n,\"if { $tcl_platform(os) == \\\"Darwin\\\" } {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y move\\n\"\n,\"} {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y zoom\\n\"\n,\"}\\n\"\n,\".ndraw render\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <Alt-B2-Motion> {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y Move2d\\n\"\n,\".ndraw render\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"bind .ndraw <Alt-B3-Motion> {\\n\"\n,\"Ng_MouseMove $oldmousex $oldmousey %x %y Zoom2d\\n\"\n,\".ndraw render\\n\"\n,\"set oldmousex %x; set oldmousey %y;\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc popupcheckredraw { vari { x 0 } } {\\n\"\n,\"upvar $vari varname\\n\"\n,\"if { $varname == 1 } {\\n\"\n,\"set varname 0\\n\"\n,\"} {\\n\"\n,\"Ng_Vis_Set parameters\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc popupcheckredraw2 { vari boolvar { x 0 } } {\\n\"\n,\"upvar $vari varname\\n\"\n,\"if { $varname == 1 } {\\n\"\n,\"set varname 0\\n\"\n,\"} {\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"Ng_Vis_Set parameters\\n\"\n,\"if { $boolvar == 1 } { redraw }\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc popupcheckredraw3 { vari { x 0 } } {\\n\"\n,\"upvar $vari varname\\n\"\n,\"if { $varname == 1 } {\\n\"\n,\"set varname 0\\n\"\n,\"} {\\n\"\n,\"Ng_Vis_Set parameters\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc redraw { {x 0} } {\\n\"\n,\"if {[winfo exists .ndraw]} { .ndraw render }\\n\"\n,\"}\\n\"\n,\"bind . <Left> { Ng_MouseMove 0 0 -10 0 rotate; redraw }\\n\"\n,\"bind . <Right> { Ng_MouseMove 0 0 10 0 rotate; redraw }\\n\"\n,\"bind . <Up> { Ng_MouseMove 0 0 0 -10 rotate; redraw }\\n\"\n,\"bind . <Down> { Ng_MouseMove 0 0 0 10 rotate; redraw }\\n\"\n,\"bind . <Shift-Left> { Ng_MouseMove 0 0 -10 0 move; redraw }\\n\"\n,\"bind . <Shift-Right> { Ng_MouseMove 0 0 10 0 move; redraw }\\n\"\n,\"bind . <Shift-Up> { Ng_MouseMove 0 0 0 -10 move; redraw }\\n\"\n,\"bind . <Shift-Down> { Ng_MouseMove 0 0 0 10 move; redraw }\\n\"\n,\"bind . <Control-Up> { Ng_MouseMove 0 0 0 -10 zoom; redraw }\\n\"\n,\"bind . <Control-Down> { Ng_MouseMove 0 0 0 10 zoom; redraw }\\n\"\n,\"bind . <Button-4> \\\\\\n\"\n,\"{event generate [focus -displayof %W] <MouseWheel> -delta  120}\\n\"\n,\"bind . <Button-5> \\\\\\n\"\n,\"{event generate [focus -displayof %W] <MouseWheel> -delta -120}\\n\"\n,\"bind . <MouseWheel> { Ng_MouseMove 0 0 0 [expr {%D/-5}] zoom; redraw }\\n\"\n,\"bind .ndraw <<Drop:DND_Files>> {\\n\"\n,\"set filename [join %D \\\" \\\"]\\n\"\n,\"set index [string last . $filename]\\n\"\n,\"set type [string range $filename $index+1 end]\\n\"\n,\"set ispde [string match -nocase $type \\\"pde\\\"]\\n\"\n,\"set isgeo [expr max([string match -nocase $type \\\"geo\\\"],[string match -nocase $type \\\"in2d\\\"])]\\n\"\n,\"set ismesh [expr max([string match -nocase $type \\\"vol\\\"],[string match -nocase $type \\\"vol.gz\\\"])]\\n\"\n,\"set ispy [string match -nocase $type \\\"py\\\"]\\n\"\n,\"if {$ispde == 1} {\\n\"\n,\"AddRecentNGSFile $filename;\\n\"\n,\"NGS_LoadPDE  $filename;\\n\"\n,\"SetNumProcHelpMenu\\n\"\n,\"set selectvisual mesh;\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"}\\n\"\n,\"if {$ispy == 1} {\\n\"\n,\"AddRecentPYNGSFile $filename;\\n\"\n,\"NGS_LoadPy  $filename;\\n\"\n,\"}\\n\"\n,\"if {$isgeo == 1} {\\n\"\n,\"AddRecentFile $filename;\\n\"\n,\"Ng_LoadGeometry $filename;\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"set selectvisual geometry\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"wm title . [concat \\\"$progname - \\\" $filename]\\n\"\n,\"set dirname [file dirname $filename]\\n\"\n,\"set basefilename [file tail [file rootname $filename]]\\n\"\n,\"}\\n\"\n,\"if {$ismesh == 1} {\\n\"\n,\"AddRecentMeshFile $filename;\\n\"\n,\"Ng_LoadMesh $filename;\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"Ng_ReadStatus;\\n\"\n,\"wm title . [concat \\\"$progname - \\\" %D]\\n\"\n,\"set dirname [file dirname %D]\\n\"\n,\"set basefilename [file tail [file rootname %D]]\\n\"\n,\"}\\n\"\n,\"return %A\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch { .ngmenu.geometry add command -label \\\"Scan CSG Geometry\\\" -command { Ng_ParseGeometry }\\n\"\n,\".ngmenu.geometry add command -label \\\"CSG Options...\\\" -command geometryoptionsdialog\\n\"\n,\".ngmenu.geometry add command -label \\\"CSG Properties...\\\" \\\\\\n\"\n,\"-command topleveldialog2\\n\"\n,\"proc geometryoptionsdialog { } {\\n\"\n,\"set w .geometry_dlg\\n\"\n,\"if {[winfo exists .geometry_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global geooptions\\n\"\n,\"Ng_GeometryOptions get\\n\"\n,\"checkbutton $w.drawcsg -text \\\"Draw Geometry\\\" \\\\\\n\"\n,\"-variable geooptions.drawcsg\\n\"\n,\"pack $w.drawcsg\\n\"\n,\"frame $w.fac\\n\"\n,\"pack $w.fac -pady 5\\n\"\n,\"ttk::label $w.fac.lab -text \\\"Facets:\\\";\\n\"\n,\"entry $w.fac.ent -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.facets\\n\"\n,\"pack $w.fac.lab $w.fac.ent  -side left\\n\"\n,\"frame $w.det\\n\"\n,\"pack $w.det -pady 5\\n\"\n,\"ttk::label $w.det.lab -text \\\"Detail:\\\";\\n\"\n,\"entry $w.det.ent -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.detail\\n\"\n,\"pack $w.det.lab $w.det.ent  -side left\\n\"\n,\"frame $w.cox\\n\"\n,\"pack $w.cox -pady 5\\n\"\n,\"ttk::label $w.cox.lab -text \\\"min/max x:\\\";\\n\"\n,\"entry $w.cox.ent1 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.minx\\n\"\n,\"entry $w.cox.ent2 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.maxx\\n\"\n,\"pack $w.cox.lab $w.cox.ent1 \\\\\\n\"\n,\"$w.cox.ent2  -side left\\n\"\n,\"frame $w.coy\\n\"\n,\"pack $w.coy -pady 5\\n\"\n,\"ttk::label $w.coy.lab -text \\\"min/max y:\\\";\\n\"\n,\"entry $w.coy.ent1 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.miny\\n\"\n,\"entry $w.coy.ent2 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.maxy\\n\"\n,\"pack $w.coy.lab $w.coy.ent1 \\\\\\n\"\n,\"$w.coy.ent2  -side left\\n\"\n,\"frame $w.coz\\n\"\n,\"pack $w.coz -pady 5\\n\"\n,\"ttk::label $w.coz.lab -text \\\"min/max z:\\\";\\n\"\n,\"entry $w.coz.ent1 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.minz\\n\"\n,\"entry $w.coz.ent2 -width 8 -relief sunken \\\\\\n\"\n,\"-textvariable geooptions.maxz\\n\"\n,\"pack $w.coz.lab $w.coz.ent1 \\\\\\n\"\n,\"$w.coz.ent2  -side left\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.app -text \\\"Apply\\\" -command {\\n\"\n,\"Ng_GeometryOptions set\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.ok -text \\\"Done\\\" -command {\\n\"\n,\"Ng_GeometryOptions set\\n\"\n,\"destroy .geometry_dlg\\n\"\n,\"}\\n\"\n,\"pack  $w.bu.app $w.bu.ok -side left -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Geometry options\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc editprimitivedialog2 { name } {\\n\"\n,\"global w classname\\n\"\n,\"set w .ep_dlg\\n\"\n,\"toplevel .$w\\n\"\n,\"Ng_GetPrimitiveData $name classname valuelist\\n\"\n,\"ttk::label $w.lab1 -text \\\"Primitive Name:  $name\\\";\\n\"\n,\"ttk::label $w.lab2 -text \\\"Primitive Class: $classname\\\";\\n\"\n,\"pack $w.lab1 $w.lab2 -fill x -pady 1m -padx 5m\\n\"\n,\"frame $w.specific -relief groove\\n\"\n,\"global spec\\n\"\n,\"set spec(sphere) { cx cy cz rad }\\n\"\n,\"set spec(cylinder) { ax ay az bx by bz rad }\\n\"\n,\"set spec(plane) { px py pz nx ny nz }\\n\"\n,\"set spec(cone) { ax ay az bx by bz ra rb }\\n\"\n,\"set spec(brick) { p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z }\\n\"\n,\"set cnt 0\\n\"\n,\"foreach field $spec($classname) {\\n\"\n,\"frame $w.specific.f$cnt\\n\"\n,\"pack $w.specific.f$cnt -side top -anchor ne\\n\"\n,\"ttk::label $w.specific.f$cnt.lab -text \\\"$field\\\"\\n\"\n,\"entry $w.specific.f$cnt.ent -textvariable dataval($cnt) \\\\\\n\"\n,\"-width 6 -relief sunken\\n\"\n,\"pack $w.specific.f$cnt.ent $w.specific.f$cnt.lab -side right\\n\"\n,\"$w.specific.f$cnt.ent delete 0 end\\n\"\n,\"$w.specific.f$cnt.ent insert 0 [lindex $valuelist $cnt]\\n\"\n,\"set cnt [expr $cnt + 1]\\n\"\n,\"}\\n\"\n,\"pack $w.specific\\n\"\n,\"ttk::button $w.cancel -text \\\"cancel\\\" -command {\\n\"\n,\"destroy $w\\n\"\n,\"}\\n\"\n,\"ttk::button $w.ok -text \\\"ok\\\" -command {\\n\"\n,\"set valuelist \\\"\\\"\\n\"\n,\"set cnt 0\\n\"\n,\"foreach field $spec($classname) {\\n\"\n,\"lappend valuelist $dataval($cnt)\\n\"\n,\"set cnt [expr $cnt + 1]\\n\"\n,\"}\\n\"\n,\"Ng_SetPrimitiveData $name $valuelist\\n\"\n,\"destroy $w\\n\"\n,\"}\\n\"\n,\"pack  $w.cancel $w.ok -side left -expand yes\\n\"\n,\"bind $w <Return> { $w.ok  invoke}\\n\"\n,\"bind $w <Escape> { $w.cancel  invoke}\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w.specific.f0.ent\\n\"\n,\"}\\n\"\n,\"proc editprimitivedialog { } {\\n\"\n,\"global w\\n\"\n,\"set w .ep_dlg\\n\"\n,\"toplevel $w\\n\"\n,\"frame $w.frame -borderwidth 5m\\n\"\n,\"pack $w.frame -side top -expand yes -fill y\\n\"\n,\"listbox $w.frame.list -yscroll \\\"$w.frame.scroll set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.frame.scroll -command \\\"$w.frame.list yview\\\"\\n\"\n,\"pack $w.frame.scroll -side right -fill y\\n\"\n,\"pack $w.frame.list -side left -expand 1 -fill both\\n\"\n,\"Ng_GetPrimitiveList primlist\\n\"\n,\"foreach el $primlist {\\n\"\n,\"$w.frame.list insert end $el }\\n\"\n,\"ttk::button $w.cancel -text \\\"cancel\\\" -command { destroy $w }\\n\"\n,\"ttk::button $w.ok -text \\\"ok\\\" -command {\\n\"\n,\"set name [.ep_dlg.frame.list get active]\\n\"\n,\"puts \\\"name=($name)\\\"\\n\"\n,\"destroy $w\\n\"\n,\"if { $name != \\\"\\\" } { editprimitivedialog2 $name }\\n\"\n,\"}\\n\"\n,\"bind $w <Escape> { $w.cancel invoke }\\n\"\n,\"bind $w <Return> { $w.ok invoke }\\n\"\n,\"pack  $w.cancel $w.ok -side left -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w.frame.list\\n\"\n,\"}\\n\"\n,\"proc newprimitivedialog { } {\\n\"\n,\"global w name\\n\"\n,\"set w .ap_dlg\\n\"\n,\"toplevel $w\\n\"\n,\"set name \\\"\\\"\\n\"\n,\"frame $w.f1\\n\"\n,\"pack $w.f1 -pady 2m\\n\"\n,\"ttk::label $w.f1.lab -text \\\"Primitive Name: \\\";\\n\"\n,\"entry $w.f1.ent -width 5 -relief sunken \\\\\\n\"\n,\"-textvariable name\\n\"\n,\"pack $w.f1.lab $w.f1.ent -side left\\n\"\n,\"frame $w.frame -borderwidth .5c\\n\"\n,\"pack $w.frame -side top -expand yes -fill y\\n\"\n,\"listbox $w.frame.list -yscroll \\\"$w.frame.scroll set\\\" -setgrid 1 -height 8\\n\"\n,\"scrollbar $w.frame.scroll -command \\\"$w.frame.list yview\\\"\\n\"\n,\"pack $w.frame.scroll -side right -fill y\\n\"\n,\"pack $w.frame.list -side left -expand 1 -fill both\\n\"\n,\"$w.frame.list insert 0 sphere cylinder plane cone brick\\n\"\n,\"$w.frame.list activate 0\\n\"\n,\"ttk::button $w.ok -text \\\"ok\\\" -command {\\n\"\n,\"Ng_CreatePrimitive [$w.frame.list get active]  $name\\n\"\n,\"destroy $w\\n\"\n,\"editprimitivedialog2 $name\\n\"\n,\"}\\n\"\n,\"ttk::button $w.cancel -text \\\"cancel\\\" -command {\\n\"\n,\"destroy $w\\n\"\n,\"}\\n\"\n,\"pack  $w.cancel $w.ok -side left -expand yes -pady 2m\\n\"\n,\"bind $w <Escape> { $w.cancel invoke }\\n\"\n,\"bind $w <Return> { $w.ok invoke }\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w.f1.ent\\n\"\n,\"}\\n\"\n,\"proc newsoliddialog { } {\\n\"\n,\"global w name val sollist\\n\"\n,\"set w .ns_dlg\\n\"\n,\"toplevel $w\\n\"\n,\"set name \\\"\\\"\\n\"\n,\"frame $w.f1\\n\"\n,\"ttk::label $w.f1.lab -text \\\"Solid Name: \\\";\\n\"\n,\"entry $w.f1.ent -width 5 -relief sunken \\\\\\n\"\n,\"-textvariable name\\n\"\n,\"$w.f1.ent delete 0 end\\n\"\n,\"ttk::button $w.f1.getsel -text \\\"Get Selected\\\" -command {\\n\"\n,\"$w.f1.ent delete 0 end\\n\"\n,\"$w.f1.ent insert 0 [$w.f3.list get active]\\n\"\n,\"$w.bu.get invoke\\n\"\n,\"}\\n\"\n,\"pack $w.f1.getsel -side bottom\\n\"\n,\"pack $w.f1.ent $w.f1.lab -side right\\n\"\n,\"frame $w.f3 -borderwidth .5c\\n\"\n,\"listbox $w.f3.list -yscroll \\\"$w.f3.scroll set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.f3.scroll -command \\\"$w.f3.list yview\\\"\\n\"\n,\"pack $w.f3.scroll -side right -fill y\\n\"\n,\"pack $w.f3.list -side left -expand 1 -fill both\\n\"\n,\"Ng_GetSolidList sollist\\n\"\n,\"foreach el $sollist {\\n\"\n,\"$w.f3.list insert end $el }\\n\"\n,\"frame $w.f2\\n\"\n,\"ttk::label $w.f2.lab -text \\\"Solid Description: \\\";\\n\"\n,\"pack $w.f2.lab\\n\"\n,\"entry $w.f2.ent -width 100 -relief sunken \\\\\\n\"\n,\"-textvariable val  -xscrollcommand \\\"$w.f2.scr set\\\"\\n\"\n,\"scrollbar $w.f2.scr -relief sunken -orient horiz -command \\\\\\n\"\n,\"\\\"$w.f2.ent xview\\\"\\n\"\n,\"$w.f2.ent delete 0 end\\n\"\n,\"pack $w.f2.ent $w.f2.scr -fill x\\n\"\n,\"frame $w.bu\\n\"\n,\"ttk::button $w.bu.close -text \\\"close\\\" -command {\\n\"\n,\"destroy $w\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.get -text \\\"get data\\\" -command {\\n\"\n,\"Ng_GetSolidData $name val\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.set -text \\\"set data\\\" -command {\\n\"\n,\"Ng_SetSolidData $name $val\\n\"\n,\"}\\n\"\n,\"pack $w.bu.get $w.bu.set $w.bu.close -side left\\n\"\n,\"pack $w.bu -pady 5 -side bottom                     ;\\n\"\n,\"pack $w.f2 -pady 5 -side bottom                     ;\\n\"\n,\"pack $w.f1 -pady 5 -side left                       ;\\n\"\n,\"pack $w.f3 -side left -expand yes -fill y           ;\\n\"\n,\"bind $w <Escape> { $w.bu.close invoke }\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"proc toplevelproperties { w solname surfname } {\\n\"\n,\"global properties\\n\"\n,\"Ng_TopLevel getprop $solname $surfname properties\\n\"\n,\"set w .tlprop_dlg\\n\"\n,\"if {[winfo exists $w] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::label $w.lab1 -text \\\"Red\\\"\\n\"\n,\"scale $w.scale1 -orient horizontal -length 300 -from 0 -to 1 \\\\\\n\"\n,\"-resolution 0.01  -tickinterval 0.2 \\\\\\n\"\n,\"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(red)\\n\"\n,\"ttk::label $w.lab2 -text \\\"Green\\\"\\n\"\n,\"scale $w.scale2 -orient horizontal -length 300 -from 0 -to 1 \\\\\\n\"\n,\"-resolution 0.01  -tickinterval 0.2 \\\\\\n\"\n,\"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(green)\\n\"\n,\"ttk::label $w.lab3 -text \\\"Blue\\\"\\n\"\n,\"scale $w.scale3 -orient horizontal -length 300 -from 0 -to 1 \\\\\\n\"\n,\"-resolution 0.01  -tickinterval 0.2 \\\\\\n\"\n,\"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable  properties(blue)\\n\"\n,\"pack $w.lab1 $w.scale1 $w.lab2 $w.scale2 $w.lab3 $w.scale3\\n\"\n,\"checkbutton $w.cb4 -text \\\"Visible\\\" \\\\\\n\"\n,\"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\\\\n\"\n,\"-variable properties(visible)\\n\"\n,\"checkbutton $w.cb5 -text \\\"Transparent\\\" \\\\\\n\"\n,\"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\\\\n\"\n,\"-variable properties(transp)\\n\"\n,\"pack  $w.cb4 $w.cb5\\n\"\n,\"frame $w.bu\\n\"\n,\"pack $w.bu -fill x\\n\"\n,\"ttk::button $w.bu.ok -text \\\"Ok\\\" -command \\\"destroy .tlprop_dlg\\\"\\n\"\n,\"pack $w.bu.ok  -expand yes\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"wm title $w \\\"Properties $solname $surfname\\\"\\n\"\n,\"}\\n\"\n,\"proc topleveldialog { } {\\n\"\n,\"global w name val sollist\\n\"\n,\"set w .tl_dlg\\n\"\n,\"toplevel $w\\n\"\n,\"frame $w.sol -borderwidth .5c\\n\"\n,\"listbox $w.sol.list -yscroll \\\"$w.sol.scroll set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.sol.scroll -command \\\"$w.sol.list yview\\\"\\n\"\n,\"pack $w.sol.scroll -side right -fill y\\n\"\n,\"pack $w.sol.list -side left -expand 1 -fill both\\n\"\n,\"Ng_GetSolidList sollist\\n\"\n,\"foreach el $sollist {\\n\"\n,\"$w.sol.list insert end $el }\\n\"\n,\"Ng_GetPrimitiveList sollist\\n\"\n,\"foreach el $sollist {\\n\"\n,\"$w.sol.list insert end $el }\\n\"\n,\"frame $w.sul -borderwidth .5c\\n\"\n,\"listbox $w.sul.list -yscroll \\\"$w.sul.scroll set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.sul.scroll -command \\\"$w.sul.list yview\\\"\\n\"\n,\"pack $w.sul.scroll -side right -fill y\\n\"\n,\"pack $w.sul.list -side left -expand 1 -fill both\\n\"\n,\"Ng_GetSurfaceList sollist\\n\"\n,\"foreach el $sollist {\\n\"\n,\"$w.sul.list insert end $el }\\n\"\n,\"frame $w.topl -borderwidth .5c\\n\"\n,\"listbox $w.topl.list -yscroll \\\"$w.topl.scroll set\\\" -setgrid 1 -height 12 \\\\\\n\"\n,\"-command { puts hi }\\n\"\n,\"scrollbar $w.topl.scroll -command \\\"$w.topl.list yview\\\"\\n\"\n,\"pack $w.topl.scroll -side right -fill y\\n\"\n,\"pack $w.topl.list -side left -expand 1 -fill both\\n\"\n,\"Ng_TopLevel getlist sollist\\n\"\n,\"puts $sollist\\n\"\n,\"foreach el $sollist {\\n\"\n,\"set hel \\\"[ lindex $el 0 ]\\\"\\n\"\n,\"if { [ llength $el ] == 2 } {\\n\"\n,\"set hel \\\"[ lindex $el 1 ] on [ lindex $el 0 ]\\\"\\n\"\n,\"}\\n\"\n,\"$w.topl.list insert end $hel\\n\"\n,\"}\\n\"\n,\"frame $w.bu\\n\"\n,\"ttk::button $w.bu.close -text \\\"close\\\" -command {\\n\"\n,\"destroy $w\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.addsol -text \\\"Add Solid\\\" -command {\\n\"\n,\"set solname [$w.sol.list get active]\\n\"\n,\"Ng_TopLevel set $solname \\\"\\\"\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"$w.topl.list insert end $solname\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.addsurf -text \\\"Add Surface\\\" -command {\\n\"\n,\"set solname [$w.sol.list get active]\\n\"\n,\"set surfname [$w.sul.list get active]\\n\"\n,\"Ng_TopLevel set $solname $surfname\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"puts \\\"$solname on $surfname\\\"\\n\"\n,\"$w.topl.list insert end \\\"$surfname on $solname\\\"\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.remsol -text \\\"Remove\\\" -command {\\n\"\n,\"set solname [$w.topl.list get active]\\n\"\n,\"set surfname \\\"\\\"\\n\"\n,\"if { [llength $solname] == 3 } {\\n\"\n,\"set surfname [lindex $solname 0]\\n\"\n,\"set solname [lindex $solname 2]\\n\"\n,\"}\\n\"\n,\"Ng_TopLevel remove $solname $surfname\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"$w.topl.list delete active\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.prop -text \\\"Properties\\\" -command {\\n\"\n,\"set solname [$w.topl.list get active]\\n\"\n,\"set surfname \\\"\\\"\\n\"\n,\"if { [llength $solname] == 3 } {\\n\"\n,\"set surfname [lindex $solname 0]\\n\"\n,\"set solname [lindex $solname 2]\\n\"\n,\"}\\n\"\n,\"toplevelproperties tlp $solname $surfname\\n\"\n,\"}\\n\"\n,\"pack  $w.bu.close $w.bu.addsol $w.bu.addsurf $w.bu.remsol $w.bu.prop  -side left\\n\"\n,\"pack $w.bu -side bottom\\n\"\n,\"pack $w.sol -side left -expand yes -fill y           ;\\n\"\n,\"pack $w.sul -side left -expand yes -fill y           ;\\n\"\n,\"pack $w.topl -side left -expand yes -fill y           ;\\n\"\n,\"bind $w <Escape> { $w.bu.close invoke }\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"proc topleveldialog2 { } {\\n\"\n,\"set w .tl2_dlg\\n\"\n,\"if {[winfo exists .tl2_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global name val sollist\\n\"\n,\"frame $w.topl -borderwidth .5c\\n\"\n,\"listbox $w.topl.list -yscroll \\\"$w.topl.scroll set\\\" -setgrid 1 -height 12\\n\"\n,\"scrollbar $w.topl.scroll -command \\\"$w.topl.list yview\\\"\\n\"\n,\"pack $w.topl.scroll -side right -fill y\\n\"\n,\"pack $w.topl.list -side left -expand 1 -fill both\\n\"\n,\"Ng_TopLevel getlist sollist\\n\"\n,\"puts $sollist\\n\"\n,\"set i 1\\n\"\n,\"foreach el $sollist {\\n\"\n,\"set hel \\\"$i: [ lindex $el 0 ]\\\"\\n\"\n,\"if { [ llength $el ] == 2 } {\\n\"\n,\"set hel \\\"$i: [ lindex $el 1 ] on [ lindex $el 0 ]\\\"\\n\"\n,\"}\\n\"\n,\"incr i\\n\"\n,\"$w.topl.list insert end $hel }\\n\"\n,\"frame $w.bu\\n\"\n,\"ttk::button $w.bu.close -text \\\"close\\\" -command {\\n\"\n,\"destroy .tl2_dlg\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.prop -text \\\"Properties\\\" -command {\\n\"\n,\"set solname [.tl2_dlg.topl.list get active]\\n\"\n,\"set surfname \\\"\\\"\\n\"\n,\"if { [llength $solname] == 2 } {\\n\"\n,\"set solname [lindex $solname 1]\\n\"\n,\"}\\n\"\n,\"if { [llength $solname] == 4 } {\\n\"\n,\"set surfname [lindex $solname 1]\\n\"\n,\"set solname [lindex $solname 3]\\n\"\n,\"}\\n\"\n,\"toplevelproperties tlp $solname $surfname\\n\"\n,\"}\\n\"\n,\"pack $w.bu.close $w.bu.prop  -side left\\n\"\n,\"pack $w.bu -side bottom\\n\"\n,\"pack $w.topl -side left -expand yes -fill y           ;\\n\"\n,\"bind .tl2_dlg.topl.list <Double-1> {\\n\"\n,\"set solname [.tl2_dlg.topl.list get  @%x,%y]\\n\"\n,\"set surfname \\\"\\\"\\n\"\n,\"if { [llength $solname] == 2 } {\\n\"\n,\"set solname [lindex $solname 1]\\n\"\n,\"}\\n\"\n,\"if { [llength $solname] == 4 } {\\n\"\n,\"set surfname [lindex $solname 1]\\n\"\n,\"set solname [lindex $solname 3]\\n\"\n,\"}\\n\"\n,\"toplevelproperties tlp $solname $surfname\\n\"\n,\"}\\n\"\n,\"bind .tl2_dlg <Escape> { .tl2_dlg.bu.close invoke }\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Top-Level Options\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch { \\n\"\n,\".ngmenu.geometry add separator\\n\"\n,\".ngmenu.geometry add command -label \\\"STL Doctor...\\\" \\\\\\n\"\n,\"-command { stldoctordialog; }\\n\"\n,\".ngmenu.geometry add command -label \\\"STL Info\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set notriangles 0\\n\"\n,\"set minx 0\\n\"\n,\"set maxx 0\\n\"\n,\"set miny 0\\n\"\n,\"set maxy 0\\n\"\n,\"set minz 0\\n\"\n,\"set maxz 0\\n\"\n,\"set trigscons 0\\n\"\n,\"Ng_STLInfo notriangles minx maxx miny maxy minz maxz trigscons\\n\"\n,\"set msgtext \\\"NO STL-Triangles : $notriangles\\\\nGeometry:\\\\nX = $minx - $maxx\\\\nY = $miny - $maxy\\\\nZ = $minz - $maxz\\\\nConsistency Check = $trigscons\\\\n\\\"\\n\"\n,\"set msgtext \\\"$msgtext Status: [Ng_STLInfo status]\\\"\\n\"\n,\"tk_messageBox -title \\\"STL Info\\\" -message  $msgtext -type ok\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set hasocc no\\n\"\n,\"catch { if { [catch { load liboccvis[info sharedlibextension] Ng_OCC } result ] } {\\n\"\n,\"}\\n\"\n,\"if { [catch { Ng_OCCCommand isoccgeometryloaded }] } {\\n\"\n,\"proc rebuildoccdialog { } { }\\n\"\n,\"} {\\n\"\n,\"puts \\\"OCC module loaded\\\"\\n\"\n,\"set hasocc yes\\n\"\n,\".ngmenu.geometry add separator\\n\"\n,\".ngmenu.geometry add command -label \\\"IGES/STEP Topology Explorer/Doctor...\\\" \\\\\\n\"\n,\"-command { occdialog; }\\n\"\n,\".ngmenu.geometry add command -label \\\"Edit Face Mesh Size...\\\" \\\\\\n\"\n,\"-command { surfacemeshsizedialog }\\n\"\n,\"set entities [ ]\\n\"\n,\"proc occdialogbuildtree {} {\\n\"\n,\"global entities\\n\"\n,\"set w .occ_dlg\\n\"\n,\"set entities [Ng_GetOCCData getentities]\\n\"\n,\"set nrentities [expr [llength $entities]]\\n\"\n,\"if {$nrentities != 0} {\\n\"\n,\"$w.tree insert {Topology} end -id \\\"CompSolids\\\" -text \\\"Composite Solids\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeSolids\\\" -text \\\"Free Solids\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeShells\\\" -text \\\"Free Shells\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeFaces\\\" -text \\\"Free Faces\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeWires\\\" -text \\\"Free Wires\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeEdges\\\" -text \\\"Free Edges\\\"\\n\"\n,\"$w.tree insert {Topology} end -id \\\"FreeVertices\\\" -text \\\"Free Vertices\\\"\\n\"\n,\"$w.tree item \\\"Topology\\\" -open true\\n\"\n,\"set i [expr 0]\\n\"\n,\"while {$i < $nrentities} {\\n\"\n,\"set entity [lindex $entities [expr $i]]\\n\"\n,\"incr i 1\\n\"\n,\"set entityname [lindex $entities [expr $i]]\\n\"\n,\"set myroot [string range $entity 0 [string last / $entity]-1]\\n\"\n,\"$w.tree insert $myroot end -id $entity -text $entityname -value 1\\n\"\n,\"incr i 1\\n\"\n,\"}\\n\"\n,\"set i [expr 0]\\n\"\n,\"while {$i < $nrentities} {\\n\"\n,\"set entity [lindex $entities [expr $i]]\\n\"\n,\"$w.tree item $entity -open false\\n\"\n,\"incr i 2\\n\"\n,\"}\\n\"\n,\"set faces [Ng_OCCCommand getunmeshedfaceinfo]\\n\"\n,\"set nrfaces [expr [llength $faces]]\\n\"\n,\"if {$nrfaces >= 2} {\\n\"\n,\"$w.tree insert {} end -id \\\"ErrorFaces\\\" -text \\\"Faces with surface meshing error\\\"\\n\"\n,\"$w.tree item ErrorFaces -open true\\n\"\n,\"set i [expr 0]\\n\"\n,\"while {$i < $nrfaces} {\\n\"\n,\"set entity [lindex $faces [expr $i]]\\n\"\n,\"set myroot [string range $entity 0 [string last / $entity]-1]\\n\"\n,\"if { [string length $myroot] == 0 } {\\n\"\n,\"set myroot \\\"ErrorFaces\\\"\\n\"\n,\"}\\n\"\n,\"incr i 1\\n\"\n,\"set entityname [lindex $faces [expr $i]]\\n\"\n,\"$w.tree insert $myroot end -id $entity -text $entityname -value 0\\n\"\n,\"incr i 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set faces [Ng_OCCCommand getnotdrawablefaces]\\n\"\n,\"set nrfaces [expr [llength $faces]]\\n\"\n,\"if {$nrfaces >= 2} {\\n\"\n,\"$w.tree insert {} -id NotDrawableFaces -text \\\"Faces impossible to visualize\\\"\\n\"\n,\"$w.tree item NotDrawableFaces -open true\\n\"\n,\"set i [expr 0]\\n\"\n,\"while {$i < $nrfaces} {\\n\"\n,\"set entity [lindex $faces [expr $i]]\\n\"\n,\"set myroot [string range $entity 0 [string last / $entity]-1]\\n\"\n,\"if { [string length $myroot ] == 0 } {\\n\"\n,\"set myroot NotDrawableFaces\\n\"\n,\"}\\n\"\n,\"incr i 1\\n\"\n,\"set entityname [lindex $faces [expr $i]]\\n\"\n,\"$w.tree insert $myroot end -id $entity -text $entityname -value 0\\n\"\n,\"incr i 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"puts \\\"done\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc rebuildoccdialog {} {\\n\"\n,\"if {[winfo exists .occ_dlg] == 1} {\\n\"\n,\".occ_dlg.tree delete [.occ_dlg.tree children Topology]\\n\"\n,\"occdialogbuildtree\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc checkoccloaded { } {\\n\"\n,\"set isoccgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\\n\"\n,\"if {$isoccgeometryloaded == 0} {\\n\"\n,\"puts \\\"no IGES/STEP geometry loaded\\\"\\n\"\n,\"destroy .occ_dlg\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc selectentity { entityname } {\\n\"\n,\"global entities\\n\"\n,\"set nrentities [expr [llength $entities]]\\n\"\n,\"set i [expr 0]\\n\"\n,\"while {$i < $nrentities} {\\n\"\n,\"set entitylength []\\n\"\n,\"set entity2 [lindex $entities [expr $i]]\\n\"\n,\"incr i 1\\n\"\n,\"set entityname2 [lindex $entities [expr $i]]\\n\"\n,\"incr i 1\\n\"\n,\"set entityname2 [string range $entityname2 0 [expr [string length $entityname]-1]]\\n\"\n,\"if {$entityname == $entityname2} {\\n\"\n,\".occ_dlg.tree see $entity2\\n\"\n,\".occ_dlg.tree selection set $entity2\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc occdialog { } {\\n\"\n,\"uplevel 1 {\\n\"\n,\"global entities\\n\"\n,\"set selectvisual geometry\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"set w .occ_dlg\\n\"\n,\"if {[winfo exists .occ_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::treeview $w.tree\\n\"\n,\"$w.tree insert {} end -id \\\"Topology\\\" -text \\\"Topology\\\"\\n\"\n,\"pack $w.tree -fill both -expand yes\\n\"\n,\"occdialogbuildtree\\n\"\n,\"bind $w.tree <Double-1> {\\n\"\n,\"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\\n\"\n,\"set rootname \\\"\\\"\\n\"\n,\"if {[.occ_dlg.tree item [.occ_dlg.tree selection] -value] == 1 } {\\n\"\n,\"set rootname \\\"Topology\\\"\\n\"\n,\"}\\n\"\n,\"set spacepos [string first \\\" \\\" $entityname]\\n\"\n,\"set entitytype [string range $entityname 0 [expr $spacepos-1]]\\n\"\n,\"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\\n\"\n,\"set spacepos2 [string first \\\" \\\" $helpstring]\\n\"\n,\"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\\n\"\n,\"if {$rootname == \\\"Topology\\\"} {\\n\"\n,\"Ng_OCCCommand highlightentity $entitytype $entitynumber\\n\"\n,\"set selectvisual geometry\\n\"\n,\"redraw\\n\"\n,\"} {\\n\"\n,\"set brackpos [string first \\\" (\\\" $entityname]\\n\"\n,\"if {$brackpos != -1} {\\n\"\n,\"set entityname [string range $entityname 0 $brackpos]\\n\"\n,\"}\\n\"\n,\"selectentity $entityname\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.cl -text \\\"Close\\\" -command {\\n\"\n,\"destroy .occ_dlg\\n\"\n,\"}\\n\"\n,\"ttk::button $w.show -text \\\"Show\\\" -command {\\n\"\n,\"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\\n\"\n,\"set spacepos [string first \\\" \\\" $entityname]\\n\"\n,\"set entitytype [string range $entityname 0 [expr $spacepos-1]]\\n\"\n,\"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\\n\"\n,\"set spacepos2 [string first \\\" \\\" $helpstring]\\n\"\n,\"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\\n\"\n,\"Ng_OCCCommand show $entitytype $entitynumber\\n\"\n,\"set selectvisual geometry\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.hide -text \\\"Hide\\\" -command {\\n\"\n,\"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\\n\"\n,\"set spacepos [string first \\\" \\\" $entityname]\\n\"\n,\"set entitytype [string range $entityname 0 [expr $spacepos-1]]\\n\"\n,\"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\\n\"\n,\"set spacepos2 [string first \\\" \\\" $helpstring]\\n\"\n,\"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\\n\"\n,\"Ng_OCCCommand hide $entitytype $entitynumber\\n\"\n,\"set selectvisual geometry\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.swaporientation -text \\\"Swap orientation\\\" -command {\\n\"\n,\"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\\n\"\n,\"set spacepos [string first \\\" \\\" $entityname]\\n\"\n,\"set entitytype [string range $entityname 0 [expr $spacepos-1]]\\n\"\n,\"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\\n\"\n,\"set spacepos2 [string first \\\" \\\" $helpstring]\\n\"\n,\"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\\n\"\n,\"Ng_OCCCommand swaporientation $entitytype $entitynumber\\n\"\n,\"set selectvisual geometry\\n\"\n,\"redraw\\n\"\n,\".occ_dlg.tree delete [.occ_dlg.tree children Topology]\\n\"\n,\"occdialogbuildtree\\n\"\n,\"}\\n\"\n,\"ttk::button $w.marksingular -text \\\"Mark/Unmark as singular\\\" -command {\\n\"\n,\"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\\n\"\n,\"set spacepos [string first \\\" \\\" $entityname]\\n\"\n,\"if { $spacepos != 0 } {\\n\"\n,\"set entitytype [string range $entityname 0 [expr $spacepos-1]]\\n\"\n,\"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\\n\"\n,\"set spacepos2 [string first \\\" \\\" $helpstring]\\n\"\n,\"if { $spacepos2 != 0 } {\\n\"\n,\"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\\n\"\n,\"puts $entitytype\\n\"\n,\"puts $entitynumber\\n\"\n,\"global ismarkedsingular\\n\"\n,\"Ng_OCCCommand marksingular $entitytype $entitynumber\\n\"\n,\"if { $ismarkedsingular == 0 } {\\n\"\n,\".occ_dlg.tree tag remove \\\"Color\\\" [.occ_dlg.tree selection]\\n\"\n,\"} {\\n\"\n,\".occ_dlg.tree tag add \\\"Color\\\" [.occ_dlg.tree selection]\\n\"\n,\".occ_dlg.tree tag configure \\\"Color\\\" -foreground \\\"red\\\"\\n\"\n,\".occ_dlg.tree tag configure \\\"Color\\\" -background \\\"blue\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::checkbutton $w.zoomtohighlightedentity -text \\\"Zoom to highlighted entity\\\" \\\\\\n\"\n,\"-variable occoptions.zoomtohighlightedentity \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_SetOCCVisParameters\\n\"\n,\"if { ${occoptions.zoomtohighlightedentity} == 1} {\\n\"\n,\"set selectvisual geometry\\n\"\n,\"Ng_OCCCommand redrawstatus 1\\n\"\n,\"redraw\\n\"\n,\"} {\\n\"\n,\"Ng_OCCCommand redrawstatus 0\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::frame $w.healing -relief groove -borderwidth 3\\n\"\n,\"ttk::button $w.healing.checkentities -text \\\"Analyze geometry\\\" -command {\\n\"\n,\"set irregent [Ng_OCCCommand findsmallentities]\\n\"\n,\"set w .occ_dlg\\n\"\n,\"set nritems [expr [llength $irregent]]\\n\"\n,\"set i [expr 0]\\n\"\n,\"if {$nritems > 0 } {\\n\"\n,\"if { [.occ_dlg.tree exists ProblematicEntities] == 1 } {\\n\"\n,\"$w.tree delete ProblematicEntities\\n\"\n,\"}\\n\"\n,\"$w.tree insert {} end -id ProblematicEntities -text \\\"Problematic Entities\\\"\\n\"\n,\"}\\n\"\n,\"while {$i < $nritems} {\\n\"\n,\"set entity [lindex $irregent [expr $i]]\\n\"\n,\"incr i 1\\n\"\n,\"set entityname [lindex $irregent [expr $i]]\\n\"\n,\"set myroot [string range $entity 0 [string last / $entity]-1]\\n\"\n,\"if { [string length $myroot] == 0 } {\\n\"\n,\"set myroot ProblematicEntities\\n\"\n,\"}\\n\"\n,\"$w.tree insert $myroot end -id $entity -text $entityname\\n\"\n,\"incr i 1\\n\"\n,\"}\\n\"\n,\"$w.tree item ProblematicEntities -open true\\n\"\n,\"}\\n\"\n,\"ttk::frame $w.healing.tolerance\\n\"\n,\"ttk::label $w.healing.tolerance.label -text \\\"Healing tolerance: \\\"\\n\"\n,\"ttk::spinbox $w.healing.tolerance.sp -textvariable occoptions.tolerance -width 6 -increment 0.01 -validate focus -validatecommand \\\"my_validatespinbox %W %P 12\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e-9 -to 1e6\\n\"\n,\"grid $w.healing.tolerance.label $w.healing.tolerance.sp\\n\"\n,\"ttk::checkbutton $w.healing.fixsmalledges -text \\\"Fix small edges\\\" \\\\\\n\"\n,\"-variable occoptions.fixsmalledges\\n\"\n,\"ttk::checkbutton $w.healing.fixspotstripfaces -text \\\"Fix spot/strip faces\\\" \\\\\\n\"\n,\"-variable occoptions.fixspotstripfaces\\n\"\n,\"ttk::checkbutton $w.healing.sewfaces -text \\\"Sew faces\\\" \\\\\\n\"\n,\"-variable occoptions.sewfaces\\n\"\n,\"ttk::checkbutton $w.healing.makesolids -text \\\"Make solids\\\" \\\\\\n\"\n,\"-variable occoptions.makesolids\\n\"\n,\"ttk::checkbutton $w.healing.splitpartitions -text \\\"Split partitions\\\" \\\\\\n\"\n,\"-variable occoptions.splitpartitions\\n\"\n,\"ttk::button $w.healing.heal -text \\\"Heal geometry\\\" -command {\\n\"\n,\"Ng_OCCCommand shapehealing\\n\"\n,\"redraw\\n\"\n,\".occ_dlg.tree delete [.occ_dlg.tree children Topology]\\n\"\n,\"occdialogbuildtree\\n\"\n,\"}\\n\"\n,\"pack $w.healing.checkentities\\n\"\n,\"pack $w.healing.tolerance $w.healing.fixsmalledges \\\\\\n\"\n,\"$w.healing.fixspotstripfaces $w.healing.sewfaces \\\\\\n\"\n,\"$w.healing.makesolids $w.healing.splitpartitions -anchor w\\n\"\n,\"pack $w.healing.heal\\n\"\n,\"pack $w.show $w.hide\\n\"\n,\"pack $w.zoomtohighlightedentity -anchor w\\n\"\n,\"pack $w.swaporientation\\n\"\n,\"pack $w.marksingular\\n\"\n,\"pack $w.healing -fill x\\n\"\n,\"pack $w.cl\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"IGES/STEP Topology Explorer/Doctor\\\"\\n\"\n,\"focus .occ_dlg\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"} }\\n\"\n,\"if { [Ng_ACISCommand isACISavailable] == \\\"yes\\\" } {\\n\"\n,\".ngmenu.geometry add command -label \\\"ACIS Topology Explorer...\\\" \\\\\\n\"\n,\"-command { acisdialog; }\\n\"\n,\".ngmenu.geometry add command -label \\\"ACIS combine all\\\" \\\\\\n\"\n,\"-command { Ng_ACISCommand combineall }\\n\"\n,\".ngmenu.geometry add command -label \\\"ACIS Create CT\\\" \\\\\\n\"\n,\"-command { Ng_ACISCommand createct }\\n\"\n,\"}\\n\"\n,\"catch { proc print_commandline_help { } {\\n\"\n,\"puts \\\"Usage: ng { options }\\\"\\n\"\n,\"puts \\\"-geofile=filename      Input geometry file (alternative:  ng filename)\\\"\\n\"\n,\"puts \\\"-meshfile=filename     Output mesh file\\\"\\n\"\n,\"puts \\\"-verycoarse, -coarse, -moderate, -fine, -veryfine\\\"\\n\"\n,\"puts \\\"                       Automatic mesh-size selection\\\"\\n\"\n,\"puts \\\"-meshsizefile=filename Load mesh-size file with local mesh sizes\\\"\\n\"\n,\"puts \\\"-meshfiletype={\\\\\\\"Neutral Format\\\\\\\", ...}\\\"\\n\"\n,\"puts \\\"                       Filetype of output file, default is netgen file\\\"\\n\"\n,\"puts \\\"-batchmode             Run Netgen in batchmode\\\"\\n\"\n,\"puts \\\"-inputmeshfile=filename\\\"\\n\"\n,\"puts \\\"                       Input mesh file (batchmode only)\\\"\\n\"\n,\"puts \\\"-mergefile=filename    Merge with mesh file (batchmode only)\\\"\\n\"\n,\"puts \\\"-refinementfile=filename\\\"\\n\"\n,\"puts \\\"                       Use refinementinfo from file (batchmode only)\\\"\\n\"\n,\"puts \\\"-serversocket=\\\\\\n\"\n,\"puts \\\"-V                     Print additional information\\\"\\n\"\n,\"puts \\\"-testout=filename      file for test output\\\"\\n\"\n,\"if { [catch { NGS_GetData } ] == 0 } {\\n\"\n,\"puts \\\"\\\\nNGSolve parameters:\\\"\\n\"\n,\"puts \\\"-pdefile=filename      Load pde input file\\\"\\n\"\n,\"puts \\\"-solve                 Solve pde once\\\"\\n\"\n,\"puts \\\"-solve=n               Solve pde by n adaptive refinement steps\\\"\\n\"\n,\"puts \\\"-recent                Load and solve most recently loaded pde\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc set_menu_help { entry helpmsg } {\\n\"\n,\"global menuhelps\\n\"\n,\"set menuhelps($entry) $helpmsg\\n\"\n,\"}\\n\"\n,\"proc show_menu_help { entry } {\\n\"\n,\"global menuhelps\\n\"\n,\"if {[catch {set helptext $menuhelps($entry)}]} {\\n\"\n,\"set helptext \\\"no help available   \\\"\\n\"\n,\"}\\n\"\n,\".helpline configure -text $helptext\\n\"\n,\"if {[winfo exists .senshelp_dlg]==1} {\\n\"\n,\".senshelp_dlg.text delete 1.0 end\\n\"\n,\".senshelp_dlg.text insert end \\\"Menu item: $entry\\\\n\\\\n\\\"\\n\"\n,\".senshelp_dlg.text insert end $helptext\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc set_control_help { control helpmsg } {\\n\"\n,\"bind $control <Enter> \\\"show_control_help {$helpmsg}\\\"\\n\"\n,\"bind $control <Leave> \\\"show_control_help {None}\\\"\\n\"\n,\".balloon bind  $control -balloonmsg $helpmsg -statusmsg $helpmsg\\n\"\n,\"}\\n\"\n,\"proc show_control_help { helpmsg } {\\n\"\n,\".helpline configure -text $helpmsg\\n\"\n,\"if {[winfo exists .senshelp_dlg]==1} {\\n\"\n,\".senshelp_dlg.text delete 1.0 end\\n\"\n,\".senshelp_dlg.text insert end $helpmsg\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc sensitivehelpdialog { show } {\\n\"\n,\"set w .senshelp_dlg\\n\"\n,\"if {[winfo exists .senshelp_dlg] == 1} {\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw .senshelp_dlg\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"}\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global senshelptext\\n\"\n,\"text $w.text -yscrollcommand \\\"$w.scroll set\\\" -setgrid true \\\\\\n\"\n,\"-width 40 -height 10  -wrap word\\n\"\n,\"scrollbar $w.scroll -command \\\"$w.text yview\\\"\\n\"\n,\"pack $w.scroll -side right -fill y\\n\"\n,\"pack $w.text -expand yes -fill both\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"wm withdraw .senshelp_dlg\\n\"\n,\"set showsensitivehelp 0\\n\"\n,\"}\\n\"\n,\"pack $w.close\\n\"\n,\"if { $show == 1 } {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Help\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set_menu_help \\\"File\\\"  \\\"In File menu you can load and store geometries, meshes etc.\\\"\\n\"\n,\"set_menu_help \\\"New Geometry\\\"  \\\"Deletes current geometry\\\"\\n\"\n,\"set_menu_help \\\"Load Geometry\\\"  \\\"Loads Geometry file in one of the formats STL (ASCII or binary), Constructive Solid Geometry (.geo) or 2D geometry. Please have a look into Netgen User's manuel for more details.\\\"\\n\"\n,\"set_menu_help \\\"Save Geometry\\\" \\\"Saves STL Geometry in in either ASCII or binary STL format.\\\"\\n\"\n,\"set_menu_help \\\"Load Mesh\\\" \\\"Loads surface and volume mesh in Netgen internal format.\\\"\\n\"\n,\"set_menu_help \\\"Save Mesh\\\" \\\"Saves surface and volume mesh in Netgen internal format.\\\"\\n\"\n,\"set_menu_help \\\"Write EPS File\\\" \\\"Dumps OpenGL rendering to EPS File.\\\"\\n\"\n,\"set_menu_help \\\"Save Options\\\" \\\"Saves current options in file \\\\\\\"ng.opt\\\\\\\". These options will be loaded again when starting ng in the same directory.\\\"\\n\"\n,\"set_menu_help \\\"Export Mesh\\\" \\\"Exports mesh in format defined by Export Filetype.\\\"\\n\"\n,\"set_menu_help \\\"Export Filetype\\\" \\\"Selects file format for exporting mesh. Please have a look into the Netgen User's manual for more information.\\\"\\n\"\n,\"set_menu_help \\\"Import Mesh\\\" \\\"Imports surface or volume mesh in exchange format.\\\"\\n\"\n,\"set_menu_help \\\"Quit\\\" \\\"Quits Netgen\\\"\\n\"\n,\"set_menu_help \\\"Geometry\\\" \\\"Preparing geometries, visualiztion of geometries.\\\"\\n\"\n,\"set_menu_help \\\"Scan CSG Geometry\\\" \\\"Generates surface triangulation for rendering\\\"\\n\"\n,\"set_menu_help \\\"CSG Options\\\" \\\"Sets Options for CSG visualization (bounding box, detail size, number of facets).\\\"\\n\"\n,\"set_menu_help \\\"CSG Properties\\\" \\\"Defines appearance of current CSG geometry (color, visibility, transparency)\\\"\\n\"\n,\"set_menu_help \\\"STL Doctor\\\" \\\"Calls STL Doctor for preprocessing STL geometry files.\\\"\\n\"\n,\"set_menu_help \\\"STL Info\\\" \\\"Retrieves information about current STL geometry.\\\"\\n\"\n,\"set_menu_help \\\"Mesh\\\" \\\"Menu for mesh generation\\\"\\n\"\n,\"set_menu_help \\\"Generate Mesh\\\" \\\"Generates mesh from geometry, same as Button \\\\\\\"Generate Mesh\\\\\\\"\\\"\\n\"\n,\"set_menu_help \\\"Stop Meshing\\\" \\\"Terminates meshgeneration. It may take a while until meshing terminates, please be patient.\\\"\\n\"\n,\"set_menu_help \\\"Meshing Options\\\" \\\"Set options for mesh generation.\\\"\\n\"\n,\"set_menu_help \\\"Delete Mesh\\\" \\\"Deletes mesh. Not necessary before generation of new mesh.\\\"\\n\"\n,\"set_menu_help \\\"Delete Vol Mesh\\\" \\\"Deletes only volume mesh.\\\"\\n\"\n,\"set_menu_help \\\"Mesh Quality\\\" \\\"Computs element shape measures. Triangle angles are inner angles of all triangles (faces of tetrahedra). Tet angles are angles between faces of tetrahedra.\\\"\\n\"\n,\"set_menu_help \\\"Check Surface Mesh\\\" \\\"Checks consistency and overlap of surface mesh. Marks overlapping elements as bad elements, please enable visualization of bad elements in View->Mesh.\\\"\\n\"\n,\"set_menu_help \\\"Check Volume Mesh\\\" \\\"Checks conformity of volume mesh.\\\"\\n\"\n,\"set_menu_help \\\"Edit Boundary Conditions\\\" \\\"Open dialog for setting boundary condition numbers for individual faces.\\\"\\n\"\n,\"set_menu_help \\\"Analyze Geometry\\\" \\\"Perform only first step in mesh generation. Action depends on geometry type, e.g. generates charts for STL mesh, find vertices in CSG geometries.\\\"\\n\"\n,\"set_menu_help \\\"Mesh Edges\\\" \\\"Meshes edges\\\"\\n\"\n,\"set_menu_help \\\"Mesh Surface\\\" \\\"Generates surface mesh. Includes already surface optimization for some geometry types.\\\"\\n\"\n,\"set_menu_help \\\"Optimize Surface\\\" \\\"Optimizes surface mesh.\\\"\\n\"\n,\"set_menu_help \\\"Surface Optim. Step\\\" \\\"Performs a specific surface optimiztion step. Mesh smoothing moves nodes. edge swapping swaps the diagonal of a quadrilateral built by two triangles, criterion either by number of nodes, or anlges. Combine points eliminates triangles by combining points (in the center of gravity).\\\"\\n\"\n,\"set_menu_help \\\"Mesh Volume\\\" \\\"Performs volume meshing. Algorithm is a combination of Delaunay and Rule-based Advancing Front\\\"\\n\"\n,\"set_menu_help \\\"Optimize Volume\\\" \\\"Performs additional volume optimization steps\\\"\\n\"\n,\"set_menu_help \\\"Smooth Opt Volume\\\" \\\"Performs optimization steps by smoothing iterations\\\"\\n\"\n,\"set_menu_help \\\"Smooth Opt Volume Jacobian\\\" \\\"Volume optimization by smoothing iterations. Criterion is optimization of Jacobi determinants. This optimization step is also available for 10-node tetrahedra.\\\"\\n\"\n,\"set_menu_help \\\"View\\\" \\\"Sets viewing options\\\"\\n\"\n,\"set_menu_help \\\"Zoom all\\\" \\\"Zooms scene to show whole object\\\"\\n\"\n,\"set_menu_help \\\"Center\\\" \\\"Defines center of rotation\\\"\\n\"\n,\"set_menu_help \\\"Viewing Options\\\" \\\"Sets viewing options for geometry, mesh, lighting\\\"\\n\"\n,\"set_menu_help \\\"Clipping Plane\\\" \\\"Introduces clipping plane. The clipping plane is defined by the normal vector, and a scaled offset. Clipping of performed by OpenGl rendering\\\"\\n\"\n,\"set_menu_help \\\"Quality Plot\\\" \\\"Shows the element quality distribution histogram. Measure is volume scaled by edge-length to the third. Optimal elements have measure 1.\\\"\\n\"\n,\"set_menu_help \\\"Sensitive Help\\\" \\\"Shows this help window\\\"\\n\"\n,\"set_menu_help \\\"Mesh-size\\\" \\\"Manipulations of existing mesh\\\"\\n\"\n,\"set_menu_help \\\"Refine uniform\\\" \\\"Refines mesh by splitting elements into eight childs (algorithm of J. Bey)\\\"\\n\"\n,\"set_menu_help \\\"Second Order\\\" \\\"Converts 4 node elements to 10 node elements. Edge-midpoitns are projected to the geometry.\\\"\\n\"\n,\"set_menu_help \\\"Refinement Dialog\\\" \\\"Controls local mesh refinement\\\"\\n\"\n,\"set_menu_help \\\"Load Meshsize\\\" \\\"Loads mesh-size file for local mesh refinement.\\\"\\n\"\n,\"set_menu_help \\\"MS from Surf Mesh\\\" \\\"Defines mesh-size by the surface mesh.\\\"\\n\"\n,\"set f .options_dlg.nb.nbframe.general\\n\"\n,\"set_control_help $f.fine \\\"Controls relative mesh size.\\\\nThis control affects other mesh-size controls in common\\\"\\n\"\n,\"set_control_help $f.first \\\"First step in mesh generation. Usually, meshing starts from \\\\\\\"analyze geometry\\\\\\\". If the surface mesh is already available \\\\\\\"First step\\\\\\\" should be set to \\\\\\\"mesh volume\\\\\\\"\\\"\\n\"\n,\"set_control_help $f.last \\\"Last step in mesh generation. If only the surface mesh is required, please set \\\\\\\"Last Step\\\\\\\" to \\\\\\\"Optimize Surface\\\\\\\"\\\"\\n\"\n,\"set_control_help .bubar.surfm \\\"Start mesh generation\\\"\\n\"\n,\"set_control_help .bubar.stopm \\\"Stop mesh generation\\\"\\n\"\n,\"proc help_item { helptext } {p\\n\"\n,\"puts $helptext\\n\"\n,\"}\\n\"\n,\"proc show_help { } {\\n\"\n,\"set w .help\\n\"\n,\"if {[winfo exists .help] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconif $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"frame $w.buttons\\n\"\n,\"pack $w.buttons -side bottom -fill x -pady 2m\\n\"\n,\"button $w.buttons.done -text Done -command \\\"destroy $w\\\"\\n\"\n,\"pack $w.buttons.done  -side left -expand 1\\n\"\n,\"text $w.text -yscrollcommand \\\"$w.scroll set\\\" -setgrid true \\\\\\n\"\n,\"-width 60 -height 24 -wrap word\\n\"\n,\"scrollbar $w.scroll -command \\\"$w.text yview\\\"\\n\"\n,\"pack $w.scroll -side right -fill y\\n\"\n,\"pack $w.text -expand yes -fill both\\n\"\n,\"}\\n\"\n,\"$w.text configure -state normal\\n\"\n,\"$w.text delete 1.0 end\\n\"\n,\"}\\n\"\n,\"set bold \\\"-background \\n\"\n,\"set normal \\\"-background {} -relief flat\\\"\\n\"\n,\"proc help_main { } {\\n\"\n,\"show_help;\\n\"\n,\"set w .help\\n\"\n,\"global bold\\n\"\n,\"global normal\\n\"\n,\"$w.text insert 0.0 \\\\\\n\"\n,\"{NETGEN Help}\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{1. General} d1\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{2. Menu items } d2\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"foreach tag {d1 d2} {\\n\"\n,\"$w.text tag bind $tag <Any-Enter> \\\"$w.text tag configure $tag $bold\\\"\\n\"\n,\"$w.text tag bind $tag <Any-Leave> \\\"$w.text tag configure $tag $normal\\\"\\n\"\n,\"}\\n\"\n,\"$w.text tag bind d1 <1> { puts \\\"general\\\"; help_general }\\n\"\n,\"$w.text tag bind d2 <1> { help_menus }\\n\"\n,\"$w.text configure -state disabled\\n\"\n,\"}\\n\"\n,\"proc help_general { } {\\n\"\n,\"show_help;\\n\"\n,\"set w .help\\n\"\n,\"global bold\\n\"\n,\"global normal\\n\"\n,\"puts \\\"general called\\\"\\n\"\n,\"$w.text insert 0.0 \\\\\\n\"\n,\"{NETGEN is an automatic three dimensional tetrahedral mesh generation system. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STEP or STL file format. NETGEN contains modules for mesh optimization and hierarchical mesh refinement.}\\n\"\n,\"$w.text configure -state disabled\\n\"\n,\"}\\n\"\n,\"proc help_menus { } {\\n\"\n,\"show_help;\\n\"\n,\"set w .help\\n\"\n,\"global bold\\n\"\n,\"global normal\\n\"\n,\"$w.text insert 0.0 \\\\\\n\"\n,\"{The NETGEN Menu items are}\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{1. File} d1\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{2. Geometry } d2\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{3. Mesh } d3\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{4. View } d4\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{5. Mesh-size } d5\\n\"\n,\"$w.text insert end \\\\n\\\\n\\n\"\n,\"$w.text insert end \\\\\\n\"\n,\"{6. STL } d6\\n\"\n,\"foreach tag {d1 d2 d3 d4 d5 d6} {\\n\"\n,\"$w.text tag bind $tag <Any-Enter> \\\"$w.text tag configure $tag $bold\\\"\\n\"\n,\"$w.text tag bind $tag <Any-Leave> \\\"$w.text tag configure $tag $normal\\\"\\n\"\n,\"}\\n\"\n,\"$w.text tag bind d1 <1> {puts \\\"File menu\\\"}\\n\"\n,\"$w.text tag bind d2 <1> {puts \\\"Geometry menu\\\"}\\n\"\n,\"$w.text tag bind d3 <1> {puts \\\"Mesh menu\\\"}\\n\"\n,\"$w.text tag bind d4 <1> {puts \\\"View menu\\\"}\\n\"\n,\"$w.text tag bind d5 <1> {puts \\\"Mesh-size menu\\\"}\\n\"\n,\"$w.text tag bind d6 <1> {puts \\\"STL menu\\\"}\\n\"\n,\"$w.text configure -state disabled\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch { Ng_Vis_Set parameters\\n\"\n,\"set viscnt 0\\n\"\n,\"proc snapshottimer { } {\\n\"\n,\"after 2000 { snapshottimer }\\n\"\n,\"global viscnt\\n\"\n,\"set viscnt [expr $viscnt+1]\\n\"\n,\"set s1 0000$viscnt\\n\"\n,\"set cnt [string range $s1 [expr [string length $s1]-4] end]\\n\"\n,\"set filename \\\"p$cnt.jpg\\\"\\n\"\n,\"}\\n\"\n,\"snapshottimer\\n\"\n,\"proc redrawtimer { } {\\n\"\n,\"global visoptions.autoredraw\\n\"\n,\"global visoptions.autoredrawtime\\n\"\n,\"set delay [expr int(${visoptions.autoredrawtime}*1000)]\\n\"\n,\"if { ${visoptions.autoredraw} == 1 } { redraw; }\\n\"\n,\"after $delay { redrawtimer }\\n\"\n,\"}\\n\"\n,\"redrawtimer\\n\"\n,\"set perstarttime [clock clicks -millisecond]\\n\"\n,\"proc redrawperiodic { } {\\n\"\n,\"global visoptions.redrawperiodic\\n\"\n,\"global perstarttime\\n\"\n,\"set curtime [clock clicks -millisecond]\\n\"\n,\"Ng_Vis_Set time [expr ($curtime - $perstarttime) / 5]\\n\"\n,\"redraw\\n\"\n,\"if { ${visoptions.redrawperiodic} == 1 } { after 30 { redrawperiodic } };\\n\"\n,\"}\\n\"\n,\"proc addplotline { identifier datax datay plotinfo {color black}} {\\n\"\n,\"set c $identifier.c\\n\"\n,\"set xstart [lindex $plotinfo 0]\\n\"\n,\"set ystart [lindex $plotinfo 1]\\n\"\n,\"set xmin [lindex $plotinfo 2]\\n\"\n,\"set ymin [lindex $plotinfo 3]\\n\"\n,\"set unitx [lindex $plotinfo 4]\\n\"\n,\"set unity [lindex $plotinfo 5]\\n\"\n,\"set latestx [expr ([lindex $datax 0]-$xmin)*$unitx + $xstart]\\n\"\n,\"set latesty [expr ([lindex $datay 0]-$ymin)*$unity + $ystart]\\n\"\n,\"for {set i 1} {$i < [llength $datax]} {incr i} {\\n\"\n,\"set xpos [expr ([lindex $datax $i]-$xmin)*$unitx + $xstart]\\n\"\n,\"set ypos [expr ([lindex $datay $i]-$ymin)*$unity + $ystart]\\n\"\n,\"$c create line $latestx $latesty $xpos $ypos -width 1 -fill $color\\n\"\n,\"set latestx $xpos\\n\"\n,\"set latesty $ypos\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc createlineplot { width height identifier title xmin xmax ymin ymax plotinfo} {\\n\"\n,\"set thiswidth $width\\n\"\n,\"set thisheight $height\\n\"\n,\"if { $thiswidth < 275 } { set thiswidth 275 }\\n\"\n,\"if { $thisheight < 225 } { seth thisheight 225 }\\n\"\n,\"set w $identifier\\n\"\n,\"if {[winfo exists $w] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"set c $w.c\\n\"\n,\"canvas $c -relief raised -width $thiswidth -height $thisheight\\n\"\n,\"pack $w.c -side top -fill x\\n\"\n,\"set titleFont {Helvetica 18}\\n\"\n,\"set smallFont {Helvetica 12}\\n\"\n,\"set xstart 100\\n\"\n,\"set xend [expr $thiswidth-75]\\n\"\n,\"set ystart [expr $thisheight-75]\\n\"\n,\"set yend 75\\n\"\n,\"$c create line $xstart $ystart $xstart $yend -width 2\\n\"\n,\"$c create line $xstart $ystart $xend $ystart -width 2\\n\"\n,\"set unitx [expr double($xend-$xstart)/($xmax-$xmin)]\\n\"\n,\"set unity [expr double($yend-$ystart)/($ymax-$ymin)]\\n\"\n,\"for {set i 0} {$i <= 1} {set i [expr $i+0.2]} {\\n\"\n,\"$c create line [expr $xstart+$i*($xend-$xstart)] [expr $ystart] [expr $xstart+$i*($xend-$xstart)] [expr $ystart+5] -width 2\\n\"\n,\"$c create text [expr $xstart+$i*($xend-$xstart)] [expr $ystart+7] -anchor n -font $smallFont \\\\\\n\"\n,\"-text [format \\\"%.3g\\\" [expr $xmin+$i*($xmax-$xmin)]]\\n\"\n,\"$c create line [expr $xstart] [expr $ystart+$i*($yend-$ystart)] [expr $xstart-7] [expr $ystart+$i*($yend-$ystart)] -width 2\\n\"\n,\"$c create text [expr $xstart-9] [expr $ystart+$i*($yend-$ystart)] -anchor e -font $smallFont \\\\\\n\"\n,\"-text [format \\\"%.3g\\\" [expr $ymin+$i*($ymax-$ymin)]]\\n\"\n,\"}\\n\"\n,\"upvar $plotinfo ploti\\n\"\n,\"set ploti \\\"$xstart $ystart $xmin $ymin $unitx $unity\\\"\\n\"\n,\"button $w.close -text \\\"Close\\\" -command \\\"destroy $w\\\"\\n\"\n,\"pack $w.close\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w $title\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc getlineplotdata { datax datay xmini xmaxi ymini ymaxi} {\\n\"\n,\"upvar $datax datx\\n\"\n,\"upvar $datay daty\\n\"\n,\"upvar $xmini xmin\\n\"\n,\"upvar $xmaxi xmax\\n\"\n,\"upvar $ymini ymin\\n\"\n,\"upvar $ymaxi ymax\\n\"\n,\"global visoptions.lineplotusingx\\n\"\n,\"global visoptions.lineplotusingy\\n\"\n,\"global visoptions.lineplotsource\\n\"\n,\"global visoptions.lineplotfile\\n\"\n,\"set datx \\\"\\\"\\n\"\n,\"set daty \\\"\\\"\\n\"\n,\"set xmin 1e20\\n\"\n,\"set xmax -1e20\\n\"\n,\"set ymin 1e20\\n\"\n,\"set ymax -1e20\\n\"\n,\"if {${visoptions.lineplotsource} == \\\"file\\\"} {\\n\"\n,\"set fileId [open ${visoptions.lineplotfile} r]\\n\"\n,\"set line \\\"\\\"\\n\"\n,\"while {[gets $fileId line] >= 0} {\\n\"\n,\"if { [string index [lindex $line 0] 0] != \\\"\\\\\\n\"\n,\"if { ${visoptions.lineplotusingx} < [llength $line] } {\\n\"\n,\"lappend datx [lindex $line ${visoptions.lineplotusingx}]\\n\"\n,\"if { [lindex $datx end] < $xmin } {set xmin [lindex $datx end]}\\n\"\n,\"if { [lindex $datx end] > $xmax } {set xmax [lindex $datx end]}\\n\"\n,\"} {\\n\"\n,\"lappend datx 0\\n\"\n,\"}\\n\"\n,\"if { ${visoptions.lineplotusingy} < [llength $line] } {\\n\"\n,\"lappend daty [lindex $line ${visoptions.lineplotusingy}]\\n\"\n,\"if { [lindex $daty end] < $ymin } {set ymin [lindex $daty end]}\\n\"\n,\"if { [lindex $daty end] > $ymax } {set ymax [lindex $daty end]}\\n\"\n,\"} {\\n\"\n,\"lappend daty 0\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"close $fileId\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc lineplotdialog { } {\\n\"\n,\"set w .lineplot_dlg\\n\"\n,\"if {[winfo exists .lineplot_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::frame $w.filesettings -relief  groove -borderwidth 3\\n\"\n,\"ttk::frame $w.filesettings.title\\n\"\n,\"ttk::radiobutton $w.filesettings.title.choose -variable visoptions.lineplotsource \\\\\\n\"\n,\"-value file -text \\\"Data from File\\\"\\n\"\n,\"pack $w.filesettings.title.choose -side left\\n\"\n,\"pack $w.filesettings.title\\n\"\n,\"global visoptions.lineplotselectedeval\\n\"\n,\"global visoptions.lineplotfile\\n\"\n,\"global visoptions.evaluatefilenames\\n\"\n,\"global visoptions.evaluatefiledescriptions\\n\"\n,\"set evdata [NGS_GetData evaluatefiles]\\n\"\n,\"set visoptions.evaluatefilenames none\\n\"\n,\"set visoptions.evaluatefiledescriptions none\\n\"\n,\"for {set i 0} {[expr $i+1] < [llength $evdata]} {incr i 2} {\\n\"\n,\"lappend visoptions.evaluatefilenames [lindex $evdata $i]\\n\"\n,\"lappend visoptions.evaluatefiledescriptions [lindex $evdata [expr $i+1]]\\n\"\n,\"}\\n\"\n,\"ttk::frame $w.filesettings.latestevals\\n\"\n,\"ttk::label  $w.filesettings.latestevals.lab -text \\\"Use Evaluate Results: \\\"\\n\"\n,\"ttk::menubutton $w.filesettings.latestevals.but -menu $w.filesettings.latestevals.menu -text \\\"coarse\\\" -width 40\\n\"\n,\"menu $w.filesettings.latestevals.menu -tearoff 0\\n\"\n,\"for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} {\\n\"\n,\"$w.filesettings.latestevals.menu add command -label $i\\\\\\n\"\n,\"-command \\\"set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \\\\\\\"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$w.filesettings.latestevals.menu invoke ${visoptions.lineplotselectedeval}\\n\"\n,\"grid $w.filesettings.latestevals.lab $w.filesettings.latestevals.but -sticky nw\\n\"\n,\"pack $w.filesettings.latestevals\\n\"\n,\"ttk::frame $w.filesettings.sfn\\n\"\n,\"ttk::button $w.filesettings.sfn.bb -text \\\"Browse\\\" \\\\\\n\"\n,\"-command { set visoptions.lineplotfile [tk_getOpenFile] }\\n\"\n,\"ttk::entry $w.filesettings.sfn.fn -width 50 \\\\\\n\"\n,\"-textvariable visoptions.lineplotfile\\n\"\n,\"pack $w.filesettings.sfn.bb $w.filesettings.sfn.fn -side left\\n\"\n,\"pack $w.filesettings.sfn\\n\"\n,\"ttk::button $w.filesettings.refresh -text \\\"Refresh\\\" -command {\\n\"\n,\"if { ${visoptions.lineplotselectedeval} != 0} {\\n\"\n,\"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\\n\"\n,\"}\\n\"\n,\"set saveusingx ${visoptions.lineplotusingx}\\n\"\n,\"set saveusingy ${visoptions.lineplotusingy}\\n\"\n,\"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\\n\"\n,\"${visoptions.lineplotxcoordselector} delete $i\\n\"\n,\"}\\n\"\n,\"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\\n\"\n,\"${visoptions.lineplotycoordselector} delete $i\\n\"\n,\"}\\n\"\n,\"set fileId [open ${visoptions.lineplotfile} r]\\n\"\n,\"set line \\\"\\\"\\n\"\n,\"gets $fileId line\\n\"\n,\"close $fileId\\n\"\n,\"if { [lindex $line 0] == \\\"\\\\\\n\"\n,\"set visoptions.lineplotdatadescr [lrange $line 1 end]\\n\"\n,\"} {\\n\"\n,\"set visoptions.lineplotdatadescr \\\"\\\"\\n\"\n,\"for { set i 0 } { $i < [llength $line] } { incr i } {\\n\"\n,\"lappend visoptions.lineplotdatadescr \\\"data[expr $i+1]\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\\n\"\n,\"${visoptions.lineplotxcoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\\n\"\n,\"}\\n\"\n,\"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\\n\"\n,\"${visoptions.lineplotycoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\\n\"\n,\"}\\n\"\n,\"if { $saveusingx < [llength ${visoptions.lineplotdatadescr}] } {\\n\"\n,\"set visoptions.lineplotusingx $saveusingx\\n\"\n,\"} {\\n\"\n,\"set visoptions.lineplotusingx 0\\n\"\n,\"}\\n\"\n,\"if { $saveusingy < [llength ${visoptions.lineplotdatadescr}] } {\\n\"\n,\"set visoptions.lineplotusingy $saveusingy\\n\"\n,\"} {\\n\"\n,\"set visoptions.lineplotusingy 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.filesettings.refresh\\n\"\n,\"ttk::frame $w.filesettings.using\\n\"\n,\"global visoptions.lineplotdatadescr\\n\"\n,\"ttk::frame $w.filesettings.using.xco\\n\"\n,\"ttk::label  $w.filesettings.using.xco.lab -text \\\"X-Coord:\\\"\\n\"\n,\"ttk::menubutton $w.filesettings.using.xco.but -menu $w.filesettings.using.xco.menu -text \\\"\\\" -width 15\\n\"\n,\"menu $w.filesettings.using.xco.menu -tearoff 0\\n\"\n,\"for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\\n\"\n,\"$w.filesettings.using.xco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\\\\n\"\n,\"-command \\\"set visoptions.lineplotusingx $i ; $w.filesettings.using.xco.but configure -text \\\\\\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$w.filesettings.using.xco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\\n\"\n,\"grid $w.filesettings.using.xco.lab $w.filesettings.using.xco.but -sticky nw\\n\"\n,\"ttk::frame $w.filesettings.using.yco\\n\"\n,\"ttk::label  $w.filesettings.using.yco.lab -text \\\"Y-Coord:\\\"\\n\"\n,\"ttk::menubutton $w.filesettings.using.yco.but -menu $w.filesettings.using.yco.menu -text \\\"\\\" -width 15\\n\"\n,\"menu $w.filesettings.using.yco.menu -tearoff 0\\n\"\n,\"for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\\n\"\n,\"$w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\\\\n\"\n,\"-command \\\"set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \\\\\\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$w.filesettings.using.yco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\\n\"\n,\"grid $w.filesettings.using.yco.lab $w.filesettings.using.yco.but -sticky nw\\n\"\n,\"global visoptions.lineplotxcoordselector\\n\"\n,\"global visoptions.lineplotycoordselector\\n\"\n,\"set visoptions.lineplotxcoordselector $w.filesettings.using.xco\\n\"\n,\"set visoptions.lineplotycoordselector $w.filesettings.using.yco\\n\"\n,\"pack $w.filesettings.using.xco $w.filesettings.using.yco -side left\\n\"\n,\"pack $w.filesettings.using\\n\"\n,\"pack $w.filesettings -fill x -ipady 3\\n\"\n,\"ttk::frame $w.settings -relief  groove -borderwidth 3\\n\"\n,\"ttk::label $w.settings.title -text \\\"\\\\nSettings\\\\n\\\"\\n\"\n,\"pack $w.settings.title\\n\"\n,\"ttk::frame $w.settings.minmax\\n\"\n,\"ttk::checkbutton $w.settings.minmax.autoscale -text \\\"Autoscale\\\" -variable visoptions.lineplotautoscale\\n\"\n,\"ttk::frame $w.settings.minmax.xmin\\n\"\n,\"ttk::label $w.settings.minmax.xmin.label -text \\\"Min. x: \\\"\\n\"\n,\"ttk::spinbox $w.settings.minmax.xmin.sp -textvariable visoptions.lineplotxmin -width 6 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"ttk::frame $w.settings.minmax.xmax\\n\"\n,\"ttk::label $w.settings.minmax.xmax.label -text \\\"Max. x: \\\"\\n\"\n,\"ttk::spinbox $w.settings.minmax.xmax.sp -textvariable visoptions.lineplotxmax -width 6 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"ttk::frame $w.settings.minmax.ymin\\n\"\n,\"ttk::label $w.settings.minmax.ymin.label -text \\\"Min. y: \\\"\\n\"\n,\"ttk::spinbox $w.settings.minmax.ymin.sp -textvariable visoptions.lineplotymin -width 6 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"ttk::frame $w.settings.minmax.ymax\\n\"\n,\"ttk::label $w.settings.minmax.ymax.label -text \\\"Max. y: \\\"\\n\"\n,\"ttk::spinbox $w.settings.minmax.ymax.sp -textvariable visoptions.lineplotymax -width 6 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 3\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"pack $w.settings.minmax.xmin.label $w.settings.minmax.xmin.sp\\n\"\n,\"pack $w.settings.minmax.xmax.label $w.settings.minmax.xmax.sp\\n\"\n,\"pack $w.settings.minmax.ymin.label $w.settings.minmax.ymin.sp\\n\"\n,\"pack $w.settings.minmax.ymax.label $w.settings.minmax.ymax.sp\\n\"\n,\"pack $w.settings.minmax.autoscale $w.settings.minmax.xmin $w.settings.minmax.xmax \\\\\\n\"\n,\"$w.settings.minmax.ymin $w.settings.minmax.ymax -side left\\n\"\n,\"pack $w.settings.minmax\\n\"\n,\"ttk::label $w.settings.empty1 -text \\\"\\\"\\n\"\n,\"pack $w.settings.empty1\\n\"\n,\"ttk::frame $w.settings.plotsize\\n\"\n,\"ttk::frame $w.settings.plotsize.xsize\\n\"\n,\"ttk::label $w.settings.plotsize.xsize.label -text \\\"Plotsize  x: \\\"\\n\"\n,\"ttk::spinbox $w.settings.plotsize.xsize.sp -textvariable visoptions.lineplotsizex -width 6 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"pack $w.settings.plotsize.xsize.label $w.settings.plotsize.xsize.sp\\n\"\n,\"ttk::frame $w.settings.plotsize.ysize\\n\"\n,\"ttk::label $w.settings.plotsize.ysize.label -text \\\"Plotsize  y: \\\"\\n\"\n,\"ttk::spinbox $w.settings.plotsize.ysize.sp -textvariable visoptions.lineplotsizey -width 6 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e9 -to 1e9\\n\"\n,\"pack $w.settings.plotsize.ysize.label $w.settings.plotsize.ysize.sp\\n\"\n,\"pack $w.settings.plotsize.xsize $w.settings.plotsize.ysize -side left\\n\"\n,\"pack $w.settings.plotsize\\n\"\n,\"ttk::label $w.settings.empty2 -text \\\"\\\"\\n\"\n,\"pack $w.settings.empty2\\n\"\n,\"ttk::frame $w.settings.color\\n\"\n,\"ttk::label  $w.settings.color.lab -text \\\"Linecolor: \\\"\\n\"\n,\"ttk::menubutton $w.settings.color.but -menu $w.settings.color.menu -text \\\"\\\" -width 15\\n\"\n,\"menu $w.settings.color.menu -tearoff 0\\n\"\n,\"foreach step { red black blue green yellow } {\\n\"\n,\"$w.settings.color.menu add command -label $step -command \\\"set visoptions.lineplotcolor $step; $w.settings.color.but configure -text \\\\\\\"$step\\\\\\\"\\\"\\n\"\n,\"}\\n\"\n,\"$w.settings.color.menu invoke \\\"red\\\"\\n\"\n,\"grid $w.settings.color.lab $w.settings.color.but -sticky nw\\n\"\n,\"pack $w.settings.color\\n\"\n,\"pack $w.settings -fill x\\n\"\n,\"set datax \\\"\\\"\\n\"\n,\"set datay \\\"\\\"\\n\"\n,\"set xmin 0\\n\"\n,\"set xmax 0\\n\"\n,\"set ymin 0\\n\"\n,\"set ymax 0\\n\"\n,\"ttk::frame $w.plots -relief  groove -borderwidth 3\\n\"\n,\"ttk::frame $w.plots.selplot\\n\"\n,\"ttk::label  $w.plots.selplot.lab -text \\\"Linecolor: \\\"\\n\"\n,\"ttk::menubutton $w.plots.selplot.but -menu $w.plots.selplot.menu -text \\\"\\\" -width 15\\n\"\n,\"menu $w.plots.selplot.menu -tearoff 0\\n\"\n,\"$w.plots.selplot.menu add command -label \\\"None\\\" -command \\\"set visoptions.lineplotselected \\\\\\\"None\\\\\\\"; $w.plots.selplot.but configure -text \\\\\\\"None\\\\\\\"\\\"\\n\"\n,\"grid $w.plots.selplot.lab $w.plots.selplot.but -sticky nw\\n\"\n,\"$w.plots.selplot.menu invoke \\\"None\\\"\\n\"\n,\"global visoptions.lineplotselector\\n\"\n,\"set visoptions.lineplotselector $w.plots.selplot.menu\\n\"\n,\"ttk::button $w.plots.new -text \\\"Generate New Plot\\\" -command {\\n\"\n,\"if { ${visoptions.lineplotselectedeval} != 0} {\\n\"\n,\"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\\n\"\n,\"}\\n\"\n,\"getlineplotdata datax datay xmin xmax ymin ymax\\n\"\n,\"puts stdout \\\"xmin $xmin xmax $xmax ymin $ymin ymax $ymax\\\"\\n\"\n,\"global visoptions.lineplotautoscale\\n\"\n,\"if {! ${visoptions.lineplotautoscale}} {\\n\"\n,\"puts \\\"using set min/max values\\\"\\n\"\n,\"set xmin ${visoptions.lineplotxmin}\\n\"\n,\"set xmax ${visoptions.lineplotxmax}\\n\"\n,\"set ymin ${visoptions.lineplotymin}\\n\"\n,\"set ymax ${visoptions.lineplotymax}\\n\"\n,\"}\\n\"\n,\"incr visoptions.lineplotcurrentnum\\n\"\n,\"set ident .newplot${visoptions.lineplotcurrentnum}\\n\"\n,\"set plotinfo \\\"\\\"\\n\"\n,\"createlineplot ${visoptions.lineplotsizex} ${visoptions.lineplotsizey} \\\\\\n\"\n,\"$ident \\\"Lineplot ${visoptions.lineplotcurrentnum}\\\" \\\\\\n\"\n,\"$xmin $xmax $ymin $ymax plotinfo\\n\"\n,\"lappend visoptions.lineplotinfos $plotinfo\\n\"\n,\"${visoptions.lineplotselector} add command ${visoptions.lineplotcurrentnum} -label \\\"Lineplot ${visoptions.lineplotcurrentnum}\\\"\\n\"\n,\"addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.plots.addto -text \\\"Add to Selected Plot\\\" -command {\\n\"\n,\"if { ${visoptions.lineplotselectedeval} != 0} {\\n\"\n,\"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\\n\"\n,\"}\\n\"\n,\"if { ${visoptions.lineplotselected} != \\\"none\\\" } {\\n\"\n,\"getlineplotdata datax datay xmin xmax ymin ymax\\n\"\n,\"set ident .newplot${visoptions.lineplotselected}\\n\"\n,\"set plotinfo [lindex ${visoptions.lineplotinfos} ${visoptions.lineplotselected}]\\n\"\n,\"addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.plots.new $w.plots.addto $w.plots.selplot\\n\"\n,\"pack $w.plots -fill x -ipady 3\\n\"\n,\"ttk::button $w.close -text \\\"Close\\\" -command \\\"destroy $w\\\"\\n\"\n,\"pack $w.close\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +200+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"2D Lineplots\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set fieldlinesdialog_pop1 0\\n\"\n,\"proc fieldlinesdialog { } {\\n\"\n,\"set w .fieldlines_dlg\\n\"\n,\"global fieldlinesdialog_pop1\\n\"\n,\"set fieldlinesdialog_pop1 1\\n\"\n,\"if {[winfo exists .fieldlines_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"pack [ttk::notebook $w.nb]  -fill both -side top -ipadx 6 -ipady 6\\n\"\n,\"$w.nb add [ttk::frame $w.nb.draw] -text \\\"Draw\\\" -underline 0\\n\"\n,\"$w.nb add [ttk::frame $w.nb.settings] -text \\\"Settings\\\" -underline 0\\n\"\n,\"set f $w.nb.draw\\n\"\n,\"ttk::labelframe $f.general -text \\\"General settings\\\" -relief groove -borderwidth 3\\n\"\n,\"ttk::checkbutton $f.general.enable -text \\\"Enable Fieldlines\\\" \\\\\\n\"\n,\"-variable visoptions.drawfieldlines \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters;\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::label $f.general.numl -text \\\"num:\\\"\\n\"\n,\"ttk::spinbox $f.general.num -from 0 -to 100 -increment 1 \\\\\\n\"\n,\"-textvariable visoptions.numfieldlines -width 4\\n\"\n,\"grid $f.general.enable -sticky nw -padx 4 -pady 2\\n\"\n,\"grid x $f.general.numl $f.general.num -rowspan 3 -sticky w -padx 4 -row 0 -pady 2\\n\"\n,\"grid anchor $f.general center\\n\"\n,\"pack $f.general -pady 15 -fill x -ipady 3\\n\"\n,\"ttk::label $f.labe0 -text \\\" \\\"\\n\"\n,\"pack $f.labe0\\n\"\n,\"ttk::checkbutton $f.general.randomstart -text \\\"Field dependent density    \\\" \\\\\\n\"\n,\"-variable visoptions.fieldlinesrandomstart \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw}\\n\"\n,\"ttk::checkbutton $f.general.redrawperiodic -text \\\"Animate periodic\\\" \\\\\\n\"\n,\"-variable visoptions.redrawperiodic \\\\\\n\"\n,\"-command {\\n\"\n,\"redrawperiodic\\n\"\n,\"Ng_Vis_Set parameters;\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"grid $f.general.randomstart -sticky nw -padx 4 -row 1\\n\"\n,\"grid $f.general.redrawperiodic -sticky nw -padx 4 -row 2\\n\"\n,\"ttk::label $f.lab0 -text \\\" \\\"\\n\"\n,\"pack $f.lab0\\n\"\n,\"ttk::frame $f.vecfun\\n\"\n,\"ttk::label  $f.vecfun.lab -text \\\"Vector Function: \\\"\\n\"\n,\"ttk::menubutton $f.vecfun.but -menu $f.vecfun.menu -text \\\"\\\" -width 12\\n\"\n,\"menu $f.vecfun.menu -tearoff 0\\n\"\n,\"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\\n\"\n,\"set fname [Ng_Vis_Field getfieldname $i]\\n\"\n,\"set fcomp [Ng_Vis_Field getfieldcomponents $i]\\n\"\n,\"set iscomplex [Ng_Vis_Field iscomplex $i]\\n\"\n,\"set sdim [Ng_Vis_Field getdimension]\\n\"\n,\"if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\\n\"\n,\"if { ($fcomp == $sdim) || ($fcomp == 3) } {\\n\"\n,\"$f.vecfun.menu add command -label $fname -command \\\"set visoptions.fieldlinesvecfunction $fname;Ng_Vis_Set parameters; redraw;$f.vecfun.but configure -text \\\\\\\"$fname\\\\\\\" \\\" \t    }\\n\"\n,\"}\\n\"\n,\"grid $f.vecfun.lab $f.vecfun.but -sticky nw\\n\"\n,\"pack $f.vecfun\\n\"\n,\"ttk::label $f.lab00 -text \\\" \\\"\\n\"\n,\"pack $f.lab00\\n\"\n,\"ttk::frame $f.phasesettings\\n\"\n,\"ttk::checkbutton $f.phasesettings.onephase -text \\\"Fix Phase\\\" -variable visoptions.fieldlinesonlyonephase\\n\"\n,\"ttk::frame $f.phasesettings.phase\\n\"\n,\"ttk::label $f.phasesettings.phase.lab -text \\\"phi\\\"\\n\"\n,\"ttk::scale $f.phasesettings.phase.sc -orient horizontal -length 100 -from 0 -to 360 -variable visoptions.fieldlinesphase \\\\\\n\"\n,\"-command \\\"roundscale $f.phasesettings.phase.sc 0; popupcheckredraw3 fieldlinesdialog_pop1\\\"\\n\"\n,\"ttk::entry $f.phasesettings.phase.ent -width 4 -textvariable visoptions.fieldlinesphase -validate focus -takefocus 0 \\\\\\n\"\n,\"-validatecommand \\\"popupcheckredraw3 fieldlinesdialog_pop1;my_validate %W 0 1 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;popupcheckredraw3 fieldlinesdialog_pop1\\\"\\n\"\n,\"grid $f.phasesettings.phase.lab $f.phasesettings.phase.sc $f.phasesettings.phase.ent -sticky nw -ipadx 4\\n\"\n,\"pack $f.phasesettings.onephase $f.phasesettings.phase -side left\\n\"\n,\"pack $f.phasesettings\\n\"\n,\"ttk::label $f.lab1 -text \\\" \\\"\\n\"\n,\"pack $f.lab1\\n\"\n,\"ttk::frame $f.boxsettings -relief groove -borderwidth 3\\n\"\n,\"ttk::frame $f.boxsettings.title\\n\"\n,\"ttk::radiobutton $f.boxsettings.title.choose -variable visoptions.fieldlinesstartarea \\\\\\n\"\n,\"-value box -text \\\"Startpoints in Box\\\"\\n\"\n,\"pack $f.boxsettings.title.choose -side left\\n\"\n,\"pack $f.boxsettings.title\\n\"\n,\"ttk::frame $f.boxsettings.points\\n\"\n,\"ttk::label $f.boxsettings.points.lab2 -text \\\"Pmin\\\";\\n\"\n,\"ttk::entry $f.boxsettings.points.ent1x -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap1x\\n\"\n,\"ttk::entry $f.boxsettings.points.ent1y -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap1y\\n\"\n,\"ttk::entry $f.boxsettings.points.ent1z -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap1z\\n\"\n,\"ttk::label $f.boxsettings.points.lab3 -text \\\"   Pmax\\\";\\n\"\n,\"ttk::entry $f.boxsettings.points.ent2x -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap2x\\n\"\n,\"ttk::entry $f.boxsettings.points.ent2y -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap2y\\n\"\n,\"ttk::entry $f.boxsettings.points.ent2z -width 8 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesstartareap2z\\n\"\n,\"pack $f.boxsettings.points\\n\"\n,\"pack $f.boxsettings.points.lab2 $f.boxsettings.points.ent1x $f.boxsettings.points.ent1y $f.boxsettings.points.ent1z -side left\\n\"\n,\"pack $f.boxsettings.points.lab3 $f.boxsettings.points.ent2x $f.boxsettings.points.ent2y $f.boxsettings.points.ent2z -side left\\n\"\n,\"ttk::button $f.boxsettings.settobb -text \\\"Bounding Box\\\" -command {\\n\"\n,\"set bbox [Ng_MeshInfo bbox]\\n\"\n,\"set visoptions.fieldlinesstartareap1x [lindex $bbox 0]\\n\"\n,\"set visoptions.fieldlinesstartareap2x [lindex $bbox 1]\\n\"\n,\"set visoptions.fieldlinesstartareap1y [lindex $bbox 2]\\n\"\n,\"set visoptions.fieldlinesstartareap2y [lindex $bbox 3]\\n\"\n,\"set visoptions.fieldlinesstartareap1z [lindex $bbox 4]\\n\"\n,\"set visoptions.fieldlinesstartareap2z [lindex $bbox 5]\\n\"\n,\"}\\n\"\n,\"pack $f.boxsettings.settobb\\n\"\n,\"pack $f.boxsettings -fill x -ipady 3\\n\"\n,\"ttk::frame $f.facesettings -relief groove -borderwidth 3\\n\"\n,\"ttk::frame $f.facesettings.title\\n\"\n,\"ttk::radiobutton $f.facesettings.title.choose -variable visoptions.fieldlinesstartarea \\\\\\n\"\n,\"-value face -text \\\"Startpoints on Face\\\"\\n\"\n,\"pack $f.facesettings.title.choose -side left\\n\"\n,\"pack $f.facesettings.title\\n\"\n,\"ttk::frame $f.facesettings.index\\n\"\n,\"ttk::label $f.facesettings.index.lab -text \\\"face index:\\\"\\n\"\n,\"ttk::label $f.facesettings.index.ent -text 1;\\n\"\n,\"pack $f.facesettings.index.lab $f.facesettings.index.ent -side left\\n\"\n,\"pack $f.facesettings.index\\n\"\n,\"pack $f.facesettings -fill x -ipady 3\\n\"\n,\"global visoptions.fieldlinesfilename\\n\"\n,\"ttk::frame $f.filesettings -relief  groove -borderwidth 3\\n\"\n,\"ttk::frame $f.filesettings.title\\n\"\n,\"ttk::radiobutton $f.filesettings.title.choose -variable visoptions.fieldlinesstartarea \\\\\\n\"\n,\"-value file -text \\\"Startpoints from File\\\"\\n\"\n,\"pack $f.filesettings.title.choose -side left\\n\"\n,\"pack $f.filesettings.title\\n\"\n,\"ttk::frame $f.filesettings.sfn\\n\"\n,\"ttk::button $f.filesettings.sfn.bb -text \\\"Browse\\\" \\\\\\n\"\n,\"-command {\\n\"\n,\"set types {\\n\"\n,\"{ \\\"Netgen Fieldlines\\\" {.nef} }\\n\"\n,\"}\\n\"\n,\"set visoptions.fieldlinesfilename [tk_getOpenFile -filetypes $types -defaultextension \\\".nef\\\"]\\n\"\n,\"}\\n\"\n,\"ttk::entry $f.filesettings.sfn.fn -width 50 \\\\\\n\"\n,\"-textvariable visoptions.fieldlinesfilename\\n\"\n,\"pack $f.filesettings.sfn.bb $f.filesettings.sfn.fn -side left\\n\"\n,\"pack $f.filesettings.sfn\\n\"\n,\"pack $f.filesettings -fill x -ipady 3\\n\"\n,\"set g $w.nb.settings\\n\"\n,\"ttk::frame $g.linesettings -relief groove -borderwidth 3\\n\"\n,\"ttk::label $g.linesettings.title -text \\\"\\\\nLine Settings\\\\n\\\"\\n\"\n,\"ttk::frame $g.linesettings.length\\n\"\n,\"ttk::label $g.linesettings.length.lab -text \\\"rel. Length: \\\"\\n\"\n,\"ttk::spinbox $g.linesettings.length.sp -textvariable visoptions.fieldlineslength -width 6 -increment 0.1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 5\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from 0.00001 -to 10000\\n\"\n,\"grid $g.linesettings.length.lab $g.linesettings.length.sp -sticky nw\\n\"\n,\"ttk::frame $g.linesettings.maxpoints\\n\"\n,\"ttk::label $g.linesettings.maxpoints.lab -text \\\"max. Points: \\\"\\n\"\n,\"ttk::spinbox $g.linesettings.maxpoints.sp -textvariable visoptions.fieldlinesmaxpoints -width 6 -increment 1 -validate focus -validatecommand \\\"my_validatespinbox %W %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from 0 -to 10000\\n\"\n,\"grid $g.linesettings.maxpoints.lab $g.linesettings.maxpoints.sp -sticky nw\\n\"\n,\"ttk::frame $g.linesettings.thick\\n\"\n,\"ttk::label $g.linesettings.thick.lab -text \\\"rel. Thickness: \\\"\\n\"\n,\"ttk::spinbox $g.linesettings.thick.sp -textvariable visoptions.fieldlinesthickness -width 6 -increment 0.001 -validate focus -validatecommand \\\"my_validatespinbox %W %P 6\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from 1e-10 -to 0.5\\n\"\n,\"grid $g.linesettings.thick.lab $g.linesettings.thick.sp -stick nw\\n\"\n,\"pack $g.linesettings.title $g.linesettings.length $g.linesettings.maxpoints $g.linesettings.thick\\n\"\n,\"pack $g.linesettings -fill x -ipady 3\\n\"\n,\"global visoptions.fieldlinestolerance\\n\"\n,\"ttk::frame $g.odesettings -relief groove -borderwidth 3\\n\"\n,\"ttk::label $g.odesettings.title -text \\\"\\\\nODE Settings\\\\n\\\"\\n\"\n,\"ttk::frame $g.odesettings.tol\\n\"\n,\"ttk::label $g.odesettings.tol.lab -text \\\"rel. Thickness: \\\"\\n\"\n,\"ttk::spinbox $g.odesettings.tol.sp -textvariable visoptions.fieldlinestolerance -width 6 -increment 0.01 -validate focus -validatecommand \\\"my_validatespinbox %W %P 5\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from 0.00001 -to 1\\n\"\n,\"grid $g.odesettings.tol.lab $g.odesettings.tol.sp -stick nw\\n\"\n,\"ttk::frame $g.odesettings.rktype\\n\"\n,\"ttk::label  $g.odesettings.rktype.lab -text \\\"RK-Type \\\"\\n\"\n,\"ttk::menubutton $g.odesettings.rktype.but -menu $g.odesettings.rktype.menu -text \\\"\\\" -width 25\\n\"\n,\"menu $g.odesettings.rktype.menu -tearoff 0\\n\"\n,\"$g.odesettings.rktype.menu add command -label \\\"Euler, order 1\\\" -command \\\"set visoptions.fieldlinesrktype \\\\\\\"euler\\\\\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\\\\\"Euler,order 1\\\\\\\" \\\"\\n\"\n,\"$g.odesettings.rktype.menu add command -label \\\"Euler-Cauchy, order 2\\\" -command \\\"set visoptions.fieldlinesrktype \\\\\\\"eulercauchy\\\\\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\\\\\"Euler-Cauchy,order 2\\\\\\\" \\\"\\n\"\n,\"$g.odesettings.rktype.menu add command -label \\\"Simpson, order 3\\\" -command \\\"set visoptions.fieldlinesrktype \\\\\\\"simpson\\\\\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\\\\\"Simpson,order 3\\\\\\\"\\\"\\n\"\n,\"$g.odesettings.rktype.menu add command -label \\\"classical Runge-Kutta, order 4\\\" -command \\\"set visoptions.fieldlinesrktype \\\\\\\"crungekutta\\\\\\\" ;Ng_Vis_Set parameters; redraw; $g.odesettings.rktype.but configure -text \\\\\\\"classical Runge-Kutta,order 4\\\\\\\"\\\"\\n\"\n,\"$g.odesettings.rktype.menu invoke \\\"classical Runge-Kutta, order 4\\\"\\n\"\n,\"grid $g.odesettings.rktype.lab $g.odesettings.rktype.but -sticky nw\\n\"\n,\"pack $g.odesettings.title $g.odesettings.tol $g.odesettings.rktype\\n\"\n,\"pack $g.odesettings -fill x -ipady 3\\n\"\n,\"ttk::frame $w.bu\\n\"\n,\"pack $w.bu -fill x -ipady 3\\n\"\n,\"ttk::button $w.bu.calc -text \\\"Build Fieldlines\\\" -command {\\n\"\n,\"if { ${visoptions.fieldlinesvecfunction} == \\\"none\\\" } {\\n\"\n,\"bgerror \\\"Please select the vector function first!\\\"\\n\"\n,\"} {\\n\"\n,\"set visoptions.drawfieldlines 1\\n\"\n,\"Ng_Vis_Set parameters\\n\"\n,\"Ng_BuildFieldLines\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.help -text \\\"Help\\\" -command {\\n\"\n,\"if {[winfo exists .fieldlines_help] == 1} {\\n\"\n,\"wm withdraw .fieldlines_help\\n\"\n,\"wm deiconify .fieldlines_help\\n\"\n,\"focus .fieldlines_help\\n\"\n,\"} {\\n\"\n,\"toplevel .fieldlines_help\\n\"\n,\"set f [frame .fieldlines_help.ht]\\n\"\n,\"ttk::scrollbar $f.vsb -orient vertical -command [list $f.t yview]\\n\"\n,\"text $f.t -yscrollcommand [list $f.vsb set]\\n\"\n,\"grid $f.t -row 0 -column 0 -sticky nsew\\n\"\n,\"grid $f.vsb -row 0 -column 1 -sticky nsew\\n\"\n,\"grid columnconfigure $f 0 -weight 1\\n\"\n,\"grid rowconfigure $f 0 -weight 1\\n\"\n,\"set text $f.t\\n\"\n,\"$text configure -setgrid true -wrap word\\n\"\n,\"$text tag configure bold -font *-*-bold-*-*-*-*\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Draw menu\\\\n \\\\n\\\" bold\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Enable Fieldlines\\\\n    To turn on and off the calculated fieldlines. (Has to be turned on to start the calculation)\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Num\\\\n    Number of fieldlines to calculate. (May not be used exactly.)\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Field dependent density\\\\n    There will be more fieldline startpoints where the field is stronger\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Animate periodic\\\\n    (for quasistationary fields) The fieldlines of the different phase angles are animated.\\\\n    ATTENTION: \\\\\\\"Fix Phase\\\\\\\" has to be turned off\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Vector Function\\\\n    The function fixing the direction of the lines\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Fix Phase\\\\n    (for quasistationary fields) Only calculate and draw fieldlines for one special phase angle.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Startpoints in Box\\\\n    Set the startpoints inside the box \\\\[Pmin1,Pmax1\\\\] x \\\\[Pmin2,Pmax2\\\\] x \\\\[Pmin3,Pmax3\\\\]\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"    With the button \\\\\\\"Bounding Box\\\\\\\" the whole bounding box of the geometry is selected.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Startpoints on Face\\\\n    All startpoints will be set on one face. This face is selected by double-clicking with the mouse.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Startpoints from File\\\\n    The startpoint information will be read from the selected file.\\\\n    The entries in the file can be as follows:\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"        point <x> <y> <z>\\\\n            set a (potential) startpoint\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"        line <x1> <y1> <z1> <x2> <y2> <z2> <n>\\\\n            set n (potential) startpoints on the line from (x1,y1,z1) to (x2,y2,z2)\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"        box <x1> <y1> <z1> <x2> <y2> <z2> <n>\\\\n            set n (potential) startpoints inside the box \\\\[x1,x2\\\\] x \\\\[y1,y2\\\\] x \\\\[z1,z2\\\\]\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"    ATTENTION: These are potential startpoints.\\\\n               The total number of startpoints will be bounded by the \\\\\\\"Num\\\\\\\"-parameter.\\\\n \\\\n \\\\n \\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Settings Menu\\\\n \\\\n\\\" bold\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"rel. Length\\\\n    The maximal length of a fieldline relative to the diameter of the geometry.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"max. Points\\\\n    The maximum number of Runge-Kutta steps.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"rel. Thickness\\\\n    The thickness of the fieldlines relative to the diameter of the geometry.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"rel. Tolerance\\\\n    The tolerance for the step-length control of the Runge-Kutta method.\\\\n\\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"RK-Type\\\\n    Which Runge-Kutta scheme to use\\\\n \\\\n \\\\n \\\\n\\\"\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"Button \\\\\\\"Build Fieldlines\\\\\\\"\\\\n\\\" bold\\n\"\n,\"$text insert end \\\\\\n\"\n,\"\\\"    Build the fieldlines.\\\"\\n\"\n,\"$text configure -state disabled\\n\"\n,\"pack .fieldlines_help.ht -expand yes -fill both\\n\"\n,\"wm withdraw .fieldlines_help\\n\"\n,\"wm geom .fieldlines_help +300+200\\n\"\n,\"wm deiconify .fieldlines_help\\n\"\n,\"wm title .fieldlines_help \\\"Fieldlines Help\\\"\\n\"\n,\"focus .fieldlines_help\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.cancel -text \\\"Done\\\" -command \\\"destroy $w\\\"\\n\"\n,\"grid $w.bu.calc $w.bu.help $w.bu.cancel -sticky nw -padx 4\\n\"\n,\"grid anchor $w.bu center\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +200+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Fieldlines\\\"\\n\"\n,\"focus $w\\n\"\n,\"}\\n\"\n,\"global visoptions.fieldlinesstartface\\n\"\n,\"set f $w.nb.draw\\n\"\n,\"set visoptions.fieldlinesstartface [Ng_BCProp getactive]\\n\"\n,\"$f.facesettings.index.ent configure -text ${visoptions.fieldlinesstartface}\\n\"\n,\"}\\n\"\n,\"set visual_dialog_pop1 0\\n\"\n,\"set visual_dialog_pop2 0\\n\"\n,\"set visual_dialog_pop3 0\\n\"\n,\"set visual_dialog_pop4 0\\n\"\n,\"set visual_dialog_pop5 0\\n\"\n,\"set visual_dialog_pop6 0\\n\"\n,\"set visual_dialog_pop7 0\\n\"\n,\"proc visual_dialog { } {\\n\"\n,\"set w .visoptions_dlg\\n\"\n,\"global visual_dialog_pop1\\n\"\n,\"global visual_dialog_pop2\\n\"\n,\"global visual_dialog_pop3\\n\"\n,\"global visual_dialog_pop4\\n\"\n,\"global visual_dialog_pop5\\n\"\n,\"global visual_dialog_pop6\\n\"\n,\"global visual_dialog_pop7\\n\"\n,\"set visual_dialog_pop1 1\\n\"\n,\"set visual_dialog_pop2 1\\n\"\n,\"set visual_dialog_pop3 1\\n\"\n,\"set visual_dialog_pop4 1\\n\"\n,\"set visual_dialog_pop5 1\\n\"\n,\"set visual_dialog_pop6 1\\n\"\n,\"set visual_dialog_pop7 1\\n\"\n,\"if {[winfo exists .visoptions_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"ttk::frame $w.main\\n\"\n,\"pack $w.main -fill x\\n\"\n,\"set w $w.main\\n\"\n,\"ttk::frame $w.upperfr ;\\n\"\n,\"pack $w.upperfr -fill x;\\n\"\n,\"ttk::labelframe $w.upperfr.size -text \\\"Grid\\\" -relief groove -borderwidth 3\\n\"\n,\"ttk::entry $w.upperfr.size.ent -width 3 -textvariable visoptions.gridsize -validate focus -takefocus 0 -validatecommand \\\"popupcheckredraw visual_dialog_pop2;my_validate %W 0 200 %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;popupcheckredraw visual_dialog_pop2\\\"\\n\"\n,\"ttk::scale $w.upperfr.size.sc -orient horizontal -length 100 -from 1 -to 200 -variable visoptions.gridsize\\\\\\n\"\n,\"-command \\\"roundscale $w.upperfr.size.sc 0;popupcheckredraw visual_dialog_pop2\\\"\\n\"\n,\"ttk::labelframe $w.upperfr.offsets -text \\\"x / y offsets\\\" -relief groove -borderwidth 3\\n\"\n,\"ttk::label $w.upperfr.offsets.xlab -text \\\"x\\\"\\n\"\n,\"ttk::label $w.upperfr.offsets.ylab -text \\\"y\\\"\\n\"\n,\"ttk::scale $w.upperfr.offsets.xoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.xoffset \\\\\\n\"\n,\"-command \\\"roundscale $w.upperfr.offsets.xoffset 2; popupcheckredraw visual_dialog_pop3\\\"\\n\"\n,\"ttk::scale $w.upperfr.offsets.yoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.yoffset \\\\\\n\"\n,\"-command \\\"roundscale $w.upperfr.offsets.yoffset 2; popupcheckredraw visual_dialog_pop4\\\"\\n\"\n,\"ttk::entry $w.upperfr.offsets.entx -width 4 -textvariable visoptions.xoffset -validate focus -takefocus 0 \\\\\\n\"\n,\"-validatecommand \\\"popupcheckredraw visual_dialog_pop3;my_validate %W 0 1 %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;popupcheckredraw visual_dialog_pop3\\\"\\n\"\n,\"ttk::entry $w.upperfr.offsets.enty -width 4 -textvariable visoptions.yoffset -validate focus -takefocus 0 \\\\\\n\"\n,\"-validatecommand \\\"popupcheckredraw visual_dialog_pop4;my_validate %W 0 1 %P 2\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;popupcheckredraw visual_dialog_pop4\\\"\\n\"\n,\"pack $w.upperfr.size.sc $w.upperfr.size.ent -padx 4  -pady 12 -side left\\n\"\n,\"grid $w.upperfr.offsets.xoffset $w.upperfr.offsets.entx $w.upperfr.offsets.xlab -sticky nw -padx 4\\n\"\n,\"grid $w.upperfr.offsets.yoffset $w.upperfr.offsets.enty $w.upperfr.offsets.ylab -sticky nw -padx 4\\n\"\n,\"grid $w.upperfr.size $w.upperfr.offsets -sticky nw -pady 7 -padx 10\\n\"\n,\"grid anchor $w.upperfr center\\n\"\n,\"ttk::labelframe $w.deform -relief groove -borderwidth 3 -text \\\"Deformation settings\\\"\\n\"\n,\"ttk::checkbutton $w.deform.cb -text \\\"Deformation\\\" \\\\\\n\"\n,\"-variable visoptions.deformation \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::label $w.deform.l -text \\\"Scale: \\\"\\n\"\n,\"ttk::spinbox $w.deform.sc1 -from 0 -to 1e99 -textvariable visoptions.scaledeform1 -width 5 \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw } \\\\\\n\"\n,\"-validate focusout -validatecommand { Ng_Vis_Set parameters; redraw; string is double %P } \\\\\\n\"\n,\"-invalidcommand { puts \\\"invalid value, %P %s\\\"; set visoptions.scaledeform1 1; }\\n\"\n,\"ttk::scale $w.deform.sc2 -orient horizontal -length 100 -from 0 -to 1 \\\\\\n\"\n,\"-variable  visoptions.scaledeform2 \\\\\\n\"\n,\"-command { popupcheckredraw visual_dialog_pop5 }\\n\"\n,\"pack $w.deform -fill x -ipady 2 -pady 4 -ipady 3\\n\"\n,\"grid $w.deform.cb $w.deform.l $w.deform.sc1 $w.deform.sc2 -sticky nw -padx 4;\\n\"\n,\"grid anchor $w.deform center\\n\"\n,\"grid columnconfigure $w.deform 0 -pad 20\\n\"\n,\"grid columnconfigure $w.deform 2 -pad 20\\n\"\n,\"ttk::labelframe $w.as -relief groove -borderwidth 3 -text \\\"Scaling options\\\"\\n\"\n,\"ttk::checkbutton $w.as.autoscale -text \\\"Autoscale\\\" \\\\\\n\"\n,\"-variable visoptions.autoscale \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::label $w.as.lmin -text \\\"Min-value\\\"\\n\"\n,\"ttk::spinbox $w.as.smin -textvariable visoptions.mminval -width 5 -validate focus \\\\\\n\"\n,\"-validatecommand \\\"my_validatespinbox %W %P 10\\\" \\\\\\n\"\n,\"-command \\\"Ng_Vis_Set parameters; redraw;\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W\\\" -from -1e10 -to 1e10 -increment 0.001\\n\"\n,\"ttk::label $w.as.lmax -text \\\"Max-value\\\"\\n\"\n,\"ttk::spinbox $w.as.smax -textvariable visoptions.mmaxval -width 5 -validate focus \\\\\\n\"\n,\"-validatecommand \\\"Ng_Vis_Set parameters; redraw;my_validatespinbox %W %P 10\\\" \\\\\\n\"\n,\"-command \\\"Ng_Vis_Set parameters; redraw;\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalidspinbox %W;Ng_Vis_Set parameters; redraw\\\" -from -1e10 -to 1e10 -increment 0.001\\n\"\n,\"ttk::label $w.as.lncols -text \\\"N Colors\\\"\\n\"\n,\"ttk::spinbox $w.as.snumcols -textvariable visoptions.numtexturecols -width 5 -validate focus \\\\\\n\"\n,\"-command \\\"Ng_Vis_Set parameters; redraw;\\\" \\\\\\n\"\n,\"-from 2 -to 31 -increment 1\\n\"\n,\"pack $w.as -fill x -pady 5 -ipady 3\\n\"\n,\"grid $w.as.autoscale $w.as.lmin $w.as.smin $w.as.lmax $w.as.smax $w.as.lncols $w.as.snumcols -sticky nw -padx 4\\n\"\n,\"grid columnconfigure $w.as 0 -pad 20\\n\"\n,\"grid columnconfigure $w.as 2 -pad 20\\n\"\n,\"grid anchor $w.as center\\n\"\n,\"ttk::frame $w.iso; \\n\"\n,\"pack $w.iso -anchor center;\\n\"\n,\"ttk::labelframe $w.iso.cb -relief groove -borderwidth 3 -text \\\"Iso lines / surfaces\\\"\\n\"\n,\"pack $w.iso.cb -side left -pady 7 -fill y\\n\"\n,\"ttk::checkbutton $w.iso.cb.isolines -text \\\"Iso-lines\\\" \\\\\\n\"\n,\"-variable visoptions.isolines \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.iso.cb.isosurf -text \\\"Iso-Surface\\\" \\\\\\n\"\n,\"-variable visoptions.isosurf \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::label $w.iso.cb.numisol -text \\\"amount\\\"\\n\"\n,\"ttk::scale $w.iso.cb.numiso -orient horizontal -length 100 -from 2 -to 50 \\\\\\n\"\n,\"-variable  visoptions.numiso \\\\\\n\"\n,\"-command \\\"roundscale $w.iso.cb.numiso 0;popupcheckredraw visual_dialog_pop6\\\"\\n\"\n,\"ttk::entry $w.iso.cb.entry -textvariable visoptions.numiso -width 3 \\\\\\n\"\n,\"-validate focus -validatecommand \\\"popupcheckredraw visual_dialog_pop6;\\\\\\n\"\n,\"my_validate %W [$w.iso.cb.numiso cget -from] [$w.iso.cb.numiso cget -to] %P 0\\\" \\\\\\n\"\n,\"-invalidcommand \\\"my_invalid %W;popupcheckredraw visual_dialog_pop6\\\"\\n\"\n,\"grid $w.iso.cb.isolines $w.iso.cb.numisol $w.iso.cb.entry -sticky nw -padx 4\\n\"\n,\"grid $w.iso.cb.isosurf  -sticky nw -padx 4\\n\"\n,\"grid $w.iso.cb.numiso  -sticky nw -padx 4 -columnspan 2 -column 1 -row 1\\n\"\n,\"ttk::labelframe $w.iso.subdiv -text \\\"Subdivision\\\" -relief groove -borderwidth 3\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.zero -text \\\"0\\\" -variable visoptions.subdivisions -value 0 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.one -text \\\"1\\\" -variable visoptions.subdivisions -value 1 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.two -text \\\"2\\\" -variable visoptions.subdivisions -value 2 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.three -text \\\"3\\\" -variable visoptions.subdivisions -value 3 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.four -text \\\"4\\\" -variable visoptions.subdivisions -value 4 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::radiobutton $w.iso.subdiv.five -text \\\"5\\\" -variable visoptions.subdivisions -value 5 \\\\\\n\"\n,\"-command {\\n\"\n,\"Ng_Vis_Set parameters; redraw;\\n\"\n,\"}\\n\"\n,\"ttk::label $w.iso.subdiv.text  -text \\\"subdivision\\\"\\n\"\n,\"pack $w.iso.subdiv -side right -fill y -padx 4 -pady 7\\n\"\n,\"grid $w.iso.subdiv.zero $w.iso.subdiv.one $w.iso.subdiv.two $w.iso.subdiv.three $w.iso.subdiv.four $w.iso.subdiv.five\\n\"\n,\"grid anchor $w.iso.subdiv center\\n\"\n,\"ttk::labelframe $w.redraw -relief groove -borderwidth 3 -text \\\"Auto-redraw\\\"\\n\"\n,\"ttk::checkbutton $w.redraw.auto -text \\\"Auto-redraw after (sec)\\\" \\\\\\n\"\n,\"-variable visoptions.autoredraw\\n\"\n,\"ttk::spinbox $w.redraw.val -textvariable visoptions.autoredrawtime -from 0 -to 100 -width 3\\n\"\n,\"pack $w.redraw -fill x -ipady 3 -pady 7\\n\"\n,\"grid $w.redraw.auto  $w.redraw.val -sticky nw\\n\"\n,\"grid anchor $w.redraw center\\n\"\n,\"ttk::labelframe $w.lowerframe -text \\\"Additional viewing options\\\" -relief groove -borderwidth 3\\n\"\n,\"pack $w.lowerframe -fill x\\n\"\n,\"set w $w.lowerframe\\n\"\n,\"ttk::frame $w.f1\\n\"\n,\"set f [ttk::frame $w.f1.clipsol]\\n\"\n,\"pack $f -anchor e\\n\"\n,\"menu $f.m\\n\"\n,\"ttk::menubutton $f.b -menu $f.m -width 12\\n\"\n,\"ttk::label $f.l -text \\\"Clipping Plane Sol: \\\"\\n\"\n,\"global visoptions.clipsolution\\n\"\n,\"set clipsollabs(none) \\\"None\\\"\\n\"\n,\"set clipsollabs(scal) \\\"Scalar Function\\\"\\n\"\n,\"set clipsollabs(vec) \\\"Vector Function\\\"\\n\"\n,\"foreach i { none scal vec } {\\n\"\n,\"set textval $clipsollabs($i)\\n\"\n,\"$f.m add command -label \\\"$textval\\\" -command \\\\\\n\"\n,\"\\\"$f.b configure -text \\\\\\\"$textval\\\\\\\" ; set visoptions.clipsolution $i ; Ng_Vis_Set parameters ; redraw \\\"\\n\"\n,\"}\\n\"\n,\"pack $f.b $f.l -side right\\n\"\n,\"$f.m invoke $clipsollabs(${visoptions.clipsolution})\\n\"\n,\"set f [ttk::frame $w.f1.scalfun]\\n\"\n,\"pack $f -anchor e\\n\"\n,\"menu $f.m\\n\"\n,\"ttk::menubutton $f.b -menu $f.m -width 12\\n\"\n,\"ttk::label $f.l -text \\\"Scalar Function: \\\"\\n\"\n,\"set scalentries [list none None]\\n\"\n,\"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\\n\"\n,\"set fname [Ng_Vis_Field getfieldname $i]\\n\"\n,\"set fcomp [Ng_Vis_Field getfieldcomponents $i]\\n\"\n,\"if { $fcomp == 1 } {\\n\"\n,\"lappend scalentries $fname:1 $fname\\n\"\n,\"} {\\n\"\n,\"for { set j 1 } { $j <= $fcomp } { incr j } {\\n\"\n,\"lappend scalentries $fname:$j \\\"$fname ($j)\\\"\\n\"\n,\"}\\n\"\n,\"lappend scalentries $fname:0 \\\"func ($fname)\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"global visoptions.scalfunction\\n\"\n,\"foreach { name textval } $scalentries {\\n\"\n,\"$f.m add command -label \\\"$textval\\\" -command \\\\\\n\"\n,\"\\\"$f.b configure -text \\\\\\\"$textval\\\\\\\" ; set visoptions.scalfunction \\\\\\\"$name\\\\\\\" ; Ng_Vis_Set parameters ; redraw ; \\\"\\n\"\n,\"}\\n\"\n,\"pack $f.b $f.l -side right\\n\"\n,\"foreach { name textval } $scalentries {\\n\"\n,\"if { ${visoptions.scalfunction} == $name } {\\n\"\n,\"$f.m invoke $textval\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set f [ttk::frame $w.f1.vecfun]\\n\"\n,\"pack $f -anchor e\\n\"\n,\"menu $f.m\\n\"\n,\"ttk::menubutton $f.b -menu $f.m -width 12\\n\"\n,\"ttk::label $f.l -text \\\"Vector Function: \\\"\\n\"\n,\"set vecentries [list none None]\\n\"\n,\"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\\n\"\n,\"set fname [Ng_Vis_Field getfieldname $i]\\n\"\n,\"set fcomp [Ng_Vis_Field getfieldcomponents $i]\\n\"\n,\"set iscomplex [Ng_Vis_Field iscomplex $i]\\n\"\n,\"set sdim [Ng_Vis_Field getdimension]\\n\"\n,\"if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\\n\"\n,\"if { ($fcomp == $sdim) || ($fcomp == 3) } {\\n\"\n,\"lappend vecentries $fname $fname\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"global visoptions.vecfunction\\n\"\n,\"foreach { name textval } $vecentries {\\n\"\n,\"$f.m add command -label \\\"$textval\\\" -command \\\\\\n\"\n,\"\\\"$f.b configure -text \\\\\\\"$textval\\\\\\\" ; set visoptions.vecfunction $name ; Ng_Vis_Set parameters ; redraw ; \\\"\\n\"\n,\"}\\n\"\n,\"pack $f.b $f.l -side right\\n\"\n,\"foreach { name textval } $vecentries {\\n\"\n,\"if { ${visoptions.vecfunction} == $name } {\\n\"\n,\"$f.m invoke $textval\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set f [ttk::frame $w.f1.evaluate]\\n\"\n,\"pack $f -anchor e\\n\"\n,\"menu $f.m\\n\"\n,\"ttk::menubutton $f.b -menu $f.m -width 12\\n\"\n,\"ttk::label $f.l -text \\\"Evaluate: \\\"\\n\"\n,\"global visoptions.evaluate\\n\"\n,\"set evallabs(abs) \\\"| |\\\"\\n\"\n,\"set evallabs(abstens) \\\"|tensor|\\\"\\n\"\n,\"set evallabs(mises) \\\"Mises\\\"\\n\"\n,\"set evallabs(main) \\\"Main\\\"\\n\"\n,\"foreach i { abs abstens mises main } {\\n\"\n,\"set textval $evallabs($i)\\n\"\n,\"$f.m add command -label \\\"$textval\\\" -command \\\\\\n\"\n,\"\\\"$f.b configure -text \\\\\\\"$textval\\\\\\\" ; set visoptions.evaluate $i ; \\\"\\n\"\n,\"}\\n\"\n,\"pack $f.b $f.l -side right\\n\"\n,\"$f.m invoke $evallabs(${visoptions.evaluate})\\n\"\n,\"pack [ttk::frame $w.f1.multidim] -fill x\\n\"\n,\"set f [ttk::frame $w.f1.multidim.f]\\n\"\n,\"pack $f -anchor e\\n\"\n,\"ttk::label $f.l1 -text \\\"multidim-component: \\\"\\n\"\n,\"ttk::spinbox $f.sb1 -from 0 -to 1e99 -textvariable visoptions.multidimcomponent -width 3 \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"pack $f.l1 $f.sb1 -side left\\n\"\n,\"ttk::frame $w.fcb\\n\"\n,\"grid $w.f1 $w.fcb -sticky nw -padx 7 -ipady 3\\n\"\n,\"grid anchor $w center\\n\"\n,\"ttk::frame $w.fcb.cb\\n\"\n,\"pack $w.fcb.cb\\n\"\n,\"ttk::checkbutton $w.fcb.cb.showsurfsolution -text \\\"Draw Surface Vectors\\\" \\\\\\n\"\n,\"-variable visoptions.showsurfacesolution \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.showcurves -text \\\"Show Curves\\\" \\\\\\n\"\n,\"-variable visoptions.drawpointcurves \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.imaginary -text \\\"Imaginary Part\\\" \\\\\\n\"\n,\"-variable visoptions.imaginary \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.logscale -text \\\"Log Scale\\\" \\\\\\n\"\n,\"-variable visoptions.logscale \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.invcolor -text \\\"Inverse Color\\\" \\\\\\n\"\n,\"-variable visoptions.invcolor \\\\\\n\"\n,\"-command { Ng_Vis_Set parametersrange; redraw }\\n\"\n,\"ttk::frame $w.fcb.cb.texframe\\n\"\n,\"ttk::checkbutton $w.fcb.cb.texframe.usetexture -text \\\"Use Textures (\\\" \\\\\\n\"\n,\"-variable visoptions.usetexture \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.texframe.lintexture -text \\\"Linear )\\\" \\\\\\n\"\n,\"-variable visoptions.lineartexture \\\\\\n\"\n,\"-command { Ng_Vis_Set parametersrange; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.lineartexture -text \\\"Use Linear Texture\\\" \\\\\\n\"\n,\"-variable visoptions.lineartexture \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.showclipsolution -text \\\"Draw Clipping Plane Solution\\\" \\\\\\n\"\n,\"-variable visoptions.showclipsolution \\\\\\n\"\n,\"-command { Ng_Vis_Set parameters; redraw }\\n\"\n,\"ttk::checkbutton $w.fcb.cb.redrawperiodic -text \\\"Animate periodic\\\" \\\\\\n\"\n,\"-variable visoptions.redrawperiodic \\\\\\n\"\n,\"-command {\\n\"\n,\"redrawperiodic\\n\"\n,\"Ng_Vis_Set parameters;\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"grid $w.fcb.cb.showsurfsolution -sticky nw\\n\"\n,\"grid $w.fcb.cb.showcurves -sticky nw\\n\"\n,\"grid $w.fcb.cb.imaginary -sticky nw\\n\"\n,\"grid $w.fcb.cb.logscale -sticky nw\\n\"\n,\"grid $w.fcb.cb.texframe -sticky nw\\n\"\n,\"grid $w.fcb.cb.invcolor -sticky nw\\n\"\n,\"grid $w.fcb.cb.redrawperiodic -sticky nw\\n\"\n,\"pack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes\\n\"\n,\"set w .visoptions_dlg.main\\n\"\n,\"ttk::frame $w.bu;\\n\"\n,\"pack $w.bu  -pady 5 -padx 4\\n\"\n,\"ttk::button $w.bu.showsol -text \\\"Show Solution\\\" -command {\\n\"\n,\"set selectvisual solution\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.clipping -text \\\"Clipping\\\" -command {\\n\"\n,\"clippingdialog;\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.fieldlines -text \\\"Fieldlines\\\" -command {\\n\"\n,\"fieldlinesdialog;\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.lineplot -text \\\"2D Lineplot\\\" -command {\\n\"\n,\"lineplotdialog;\\n\"\n,\"}\\n\"\n,\"ttk::button $w.bu.done -text \\\"Close\\\" -command {\\n\"\n,\"destroy .visoptions_dlg\\n\"\n,\"}\\n\"\n,\"pack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes\\n\"\n,\"set w .visoptions_dlg\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +100+100\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Visualization\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch { set sockets.serverport 0\\n\"\n,\"set sockets.serverhost \\\"localhost\\\"\\n\"\n,\"set sockets.serverlistbox 0\\n\"\n,\"set sockets.queuelistbox 0\\n\"\n,\"set sockets.currentjoblistbox 0\\n\"\n,\"set sockets.answerlistbox 0\\n\"\n,\"set sockets.myidlabel -1\\n\"\n,\"proc updateserverlist { } {\\n\"\n,\"global sockets.serverlistbox\\n\"\n,\"set retval [Ng_Socket getserverlist]\\n\"\n,\"${sockets.serverlistbox} delete 0 end\\n\"\n,\"for {set i 0} {$i < [llength $retval]} {incr i 3} {\\n\"\n,\"${sockets.serverlistbox} insert end \\\\\\n\"\n,\"[format \\\"%-16s   %6i   %6i\\\" [lindex $retval $i] [lindex $retval [expr $i+1]] [lindex $retval [expr $i+2]]]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc clientsocketdialog { } {\\n\"\n,\"set w .clientsock_dlg\\n\"\n,\"if {[winfo exists .clientsock_dlg] == 1} {\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm deiconify $w\\n\"\n,\"focus $w\\n\"\n,\"} {\\n\"\n,\"toplevel $w\\n\"\n,\"global sockets.serverhost\\n\"\n,\"global sockets.serverport\\n\"\n,\"ttk::frame $w.general\\n\"\n,\"ttk::frame $w.host\\n\"\n,\"ttk::label $w.host.lab -text \\\"Serverhost: \\\"\\n\"\n,\"ttk::entry $w.host.name -width 30 -textvariable sockets.serverhost\\n\"\n,\"pack $w.host.lab $w.host.name -side left\\n\"\n,\"pack $w.host\\n\"\n,\"ttk::frame $w.ports\\n\"\n,\"ttk::label $w.ports.lab1 -text \\\"Serverport: \\\"\\n\"\n,\"ttk::entry $w.ports.statport -width 6 -textvariable sockets.serverport\\n\"\n,\"pack $w.ports.lab1 $w.ports.statport -side left\\n\"\n,\"pack $w.ports\\n\"\n,\"ttk::frame $w.listboxes\\n\"\n,\"ttk::frame $w.listboxes.choosesocketframe\\n\"\n,\"tixScrolledListBox $w.listboxes.choosesocketframe.choosesocket -scrollbar auto\\n\"\n,\"global sockets.serverlistbox\\n\"\n,\"set sockets.serverlistbox [$w.listboxes.choosesocketframe.choosesocket subwidget listbox]\\n\"\n,\"${sockets.serverlistbox} configure -width 35\\n\"\n,\"${sockets.serverlistbox} configure -selectmode browse\\n\"\n,\"${sockets.serverlistbox} configure -exportselection false\\n\"\n,\"ttk::button $w.addserver -text \\\"Add ServerSocket\\\" -command {\\n\"\n,\"Ng_Socket addserver ${sockets.serverport} ${sockets.serverhost}\\n\"\n,\"updateserverlist\\n\"\n,\"}\\n\"\n,\"pack $w.addserver\\n\"\n,\"ttk::label $w.linefeed -text \\\"\\\\n\\\"\\n\"\n,\"pack $w.linefeed\\n\"\n,\"ttk::frame $w.clientidframe\\n\"\n,\"ttk::label $w.clientidframe.lab -text \\\"Client ID: \\\";\\n\"\n,\"global sockets.myidlabel\\n\"\n,\"ttk::entry $w.clientidframe.val -width 5 -textvariable sockets.myidlabel\\n\"\n,\"ttk::button $w.clientidframe.but -text \\\"Set\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"Ng_Socket setid $opserver ${sockets.myidlabel}\\n\"\n,\"updateserverlist\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.clientidframe.lab $w.clientidframe.val $w.clientidframe.but -side left\\n\"\n,\"pack $w.clientidframe\\n\"\n,\"ttk::label $w.listboxes.choosesocketframe.chooselab -text [format \\\"\\\\n\\\\n%-16s    %6s  %6s                       \\\" Host Socket MyID ]\\n\"\n,\"pack $w.listboxes.choosesocketframe.chooselab\\n\"\n,\"pack $w.listboxes.choosesocketframe.choosesocket\\n\"\n,\"ttk::frame $w.listboxes.choosesocketframe.serverbuttons\\n\"\n,\"ttk::button $w.listboxes.choosesocketframe.serverbuttons.save -text \\\"Save\\\" -command {\\n\"\n,\"Ng_Socket saveserverlist\\n\"\n,\"}\\n\"\n,\"global sockets.serverlist\\n\"\n,\"Ng_Socket loadserverlist\\n\"\n,\"updateserverlist\\n\"\n,\"ttk::button $w.listboxes.choosesocketframe.serverbuttons.delete -text \\\"Delete\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"Ng_Socket deletesocket [lindex $opsel 0]\\n\"\n,\"updateserverlist\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.listboxes.choosesocketframe.serverbuttons.save $w.listboxes.choosesocketframe.serverbuttons.delete -side left\\n\"\n,\"pack $w.listboxes.choosesocketframe.serverbuttons\\n\"\n,\"ttk::frame $w.listboxes.statusframe\\n\"\n,\"ttk::label $w.listboxes.statusframe.statuslabel1 -text \\\"\\\\n\\\\njobqueue\\\"\\n\"\n,\"tixScrolledListBox $w.listboxes.statusframe.queuestatus -scrollbar auto\\n\"\n,\"ttk::label $w.listboxes.statusframe.statuslabel2 -text \\\"\\\\ncurrent job\\\"\\n\"\n,\"tixScrolledListBox $w.listboxes.statusframe.currentjobstatus -scrollbar auto\\n\"\n,\"ttk::label $w.listboxes.statusframe.statuslabel3 -text \\\"\\\\nanswers\\\"\\n\"\n,\"tixScrolledListBox $w.listboxes.statusframe.answers -scrollbar auto\\n\"\n,\"global sockets.queuelistbox\\n\"\n,\"global sockets.currentjoblistbox\\n\"\n,\"global sockets.answerlistbox\\n\"\n,\"set sockets.queuelistbox [$w.listboxes.statusframe.queuestatus subwidget listbox]\\n\"\n,\"set sockets.currentjoblistbox [$w.listboxes.statusframe.currentjobstatus subwidget listbox]\\n\"\n,\"set sockets.answerlistbox [$w.listboxes.statusframe.answers subwidget listbox]\\n\"\n,\"${sockets.queuelistbox} configure -width 50\\n\"\n,\"${sockets.queuelistbox} configure -height 5\\n\"\n,\"${sockets.queuelistbox} configure -selectmode browse\\n\"\n,\"${sockets.queuelistbox} configure -exportselection false\\n\"\n,\"${sockets.currentjoblistbox} configure -width 50\\n\"\n,\"${sockets.currentjoblistbox} configure -height 1\\n\"\n,\"${sockets.currentjoblistbox} configure -selectmode browse\\n\"\n,\"${sockets.currentjoblistbox} configure -exportselection false\\n\"\n,\"${sockets.answerlistbox} configure -width 50\\n\"\n,\"${sockets.answerlistbox} configure -height 5\\n\"\n,\"${sockets.answerlistbox} configure -selectmode browse\\n\"\n,\"${sockets.answerlistbox} configure -exportselection false\\n\"\n,\"ttk::button $w.listboxes.statusframe.updatebutton -text \\\"Update\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [Ng_Socket sendqueuestatus $opserver]\\n\"\n,\"${sockets.queuelistbox} delete 0 end\\n\"\n,\"if {[lindex $retval 0] > 0} {\\n\"\n,\"${sockets.queuelistbox} insert end [format \\\"Blocked for user %i\\\" [lindex $retval 0]]\\n\"\n,\"} {\\n\"\n,\"${sockets.queuelistbox} insert end \\\"Not blocked\\\"\\n\"\n,\"}\\n\"\n,\"for {set i 2} {$i < [expr 2*[lindex $retval 1]+2]} {incr i 2} {\\n\"\n,\"${sockets.queuelistbox} insert end [format \\\"client %i, command %s\\\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\\n\"\n,\"}\\n\"\n,\"${sockets.answerlistbox} delete 0 end\\n\"\n,\"for {set i [expr 2*[lindex $retval 1]+3]} {$i < [llength $retval]} {incr i 2} {\\n\"\n,\"${sockets.answerlistbox} insert end [format \\\"client %i, command %s\\\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\\n\"\n,\"}\\n\"\n,\"${sockets.currentjoblistbox} delete 0 end\\n\"\n,\"set retval [Ng_Socket sendjobstatus $opserver]\\n\"\n,\"if {[lindex $retval 0] != 0} {\\n\"\n,\"${sockets.currentjoblistbox} insert end [format \\\"client %i, command %s: %s\\\" [lindex $retval 0] [lindex $retval 1] [lrange $retval 2 end]]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.listboxes.statusframe.statuslabel1 $w.listboxes.statusframe.queuestatus \\\\\\n\"\n,\"$w.listboxes.statusframe.statuslabel2 $w.listboxes.statusframe.currentjobstatus \\\\\\n\"\n,\"$w.listboxes.statusframe.statuslabel3 $w.listboxes.statusframe.answers \\\\\\n\"\n,\"$w.listboxes.statusframe.updatebutton\\n\"\n,\"pack $w.listboxes.choosesocketframe $w.listboxes.statusframe -side left\\n\"\n,\"pack $w.listboxes\\n\"\n,\"ttk::label $w.lab1 -text \\\"\\\\n\\\"\\n\"\n,\"pack $w.lab1\\n\"\n,\"ttk::frame $w.buttons1\\n\"\n,\"ttk::frame $w.buttons2\\n\"\n,\"ttk::button $w.buttons1.getid -text \\\"Get ID\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [Ng_Socket getid $opserver]\\n\"\n,\"updateserverlist\\n\"\n,\"set sockets.myidlabel $retval\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons1.killjob -text \\\"Kill Cur. Job\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"Ng_Socket killcurrentjob $opserver\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons2.sendmesh -text \\\"Send Mesh\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [Ng_Socket sendmesh $opserver]\\n\"\n,\"set sockets.meshsent 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons2.sendpde -text \\\"Send PDE\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [NGS_Socket sendpdefile $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons2.solvepde -text \\\"Solve PDE\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [NGS_Socket solvepde $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons2.writesol -text \\\"Write Solution\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [NGS_Socket writesolution $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons2.sendsol -text \\\"Receive Solution\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [NGS_Socket sendsolution $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons1.blockserver -text \\\"Block Server\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [Ng_Socket blockserver $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"ttk::button $w.buttons1.unblockserver -text \\\"UnBlock Server\\\" -command {\\n\"\n,\"set opsel [${sockets.serverlistbox} curselection]\\n\"\n,\"if {[llength $opsel] > 0} {\\n\"\n,\"set opserver [lindex $opsel 0]\\n\"\n,\"set retval [Ng_Socket unblockserver $opserver]\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"pack $w.buttons1.getid $w.buttons1.blockserver $w.buttons1.unblockserver $w.buttons1.killjob -side left\\n\"\n,\"pack $w.buttons2.sendmesh $w.buttons2.sendpde $w.buttons2.solvepde $w.buttons2.writesol $w.buttons2.sendsol -side left\\n\"\n,\"pack $w.buttons1 $w.buttons2\\n\"\n,\"wm withdraw $w\\n\"\n,\"wm geom $w +200+200\\n\"\n,\"wm deiconify $w\\n\"\n,\"wm title $w \\\"Client Socket\\\"\\n\"\n,\"focus .options_dlg\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"catch { source ${ngdir}/acis.tcl }\\n\"\n,\"set zugstange 0\\n\"\n,\"catch { source ${ngdir}/trafo/menu.tcl }\\n\"\n,\"setgranularity ${meshoptions.fineness}\\n\"\n,\"Ng_SetMeshingParameters\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"Ng_SetDebugParameters\\n\"\n,\"Ng_STLDoctor\\n\"\n,\"Ng_GeometryOptions set\\n\"\n,\"if { $hasocc == \\\"yes\\\" } {\\n\"\n,\"Ng_SetOCCVisParameters\\n\"\n,\"}\\n\"\n,\"if { $batchmode != \\\"defined\\\" } {\\n\"\n,\"catch {\\n\"\n,\"wm protocol . WM_DELETE_WINDOW { .ngmenu.file invoke \\\"Quit\\\" }\\n\"\n,\"wm deiconify .\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set trafoapp 0\\n\"\n,\"catch { source ${ngdir}/trafoapp/trafoapp.tcl }\\n\"\n,\"set geofilename [Ng_GetCommandLineParameter geofile]\\n\"\n,\"if { $geofilename != \\\"undefined\\\" &&\\n\"\n,\"[info exists trafo] == 0 && $zugstange == 0} {\\n\"\n,\"if { [ catch { Ng_LoadGeometry $geofilename } errstring] == 0 } {\\n\"\n,\"if { $batchmode != \\\"defined\\\" } {\\n\"\n,\"AddRecentFile $geofilename\\n\"\n,\"}\\n\"\n,\"Ng_ParseGeometry\\n\"\n,\"if { $batchmode != \\\"defined\\\" } {\\n\"\n,\"set selectvisual geometry\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"redraw\\n\"\n,\"wm title . [concat \\\"$progname - \\\" $geofilename]\\n\"\n,\"}\\n\"\n,\"set dirname [file dirname $geofilename]\\n\"\n,\"set basefilename [file tail [file rootname $geofilename]]\\n\"\n,\"} {\\n\"\n,\"puts \\\"Problem with input file:\\\"\\n\"\n,\"puts \\\"$errstring\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set cnt 0\\n\"\n,\"foreach { gran } { verycoarse coarse moderate fine veryfine } {\\n\"\n,\"set cnt [expr $cnt + 1]\\n\"\n,\"if { [Ng_GetCommandLineParameter $gran] == \\\"defined\\\" } {\\n\"\n,\"set meshoptions.fineness $cnt\\n\"\n,\"setgranularity ${meshoptions.fineness}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set meshfilename [Ng_GetCommandLineParameter meshfile]\\n\"\n,\"if { $meshfilename == \\\"undefined\\\" } {\\n\"\n,\"set meshfilename out.mesh\\n\"\n,\"}\\n\"\n,\"set meshfiletype [Ng_GetCommandLineParameter meshfiletype]\\n\"\n,\"if { $meshfiletype == \\\"undefined\\\" } {\\n\"\n,\"set meshfiletype netgen\\n\"\n,\"}\\n\"\n,\"set inputmeshfilename [Ng_GetCommandLineParameter inputmeshfile]\\n\"\n,\"set mergemeshfilename [Ng_GetCommandLineParameter mergefile]\\n\"\n,\"set meshsizefilename [Ng_GetCommandLineParameter meshsizefile]\\n\"\n,\"if { $meshsizefilename != \\\"undefined\\\" } {\\n\"\n,\"set options.meshsizefilename $meshsizefilename\\n\"\n,\"}\\n\"\n,\"set refinementfilename [Ng_GetCommandLineParameter refinementfile]\\n\"\n,\"if { $batchmode == \\\"defined\\\" && $solvemode != \\\"defined\\\"} {\\n\"\n,\"set options.parthread 0\\n\"\n,\"if { $shellmode == \\\"undefined\\\" } {\\n\"\n,\"set selectvisual mesh\\n\"\n,\"Ng_SetVisParameters\\n\"\n,\"set meshsize [Ng_GetCommandLineParameter meshsize]\\n\"\n,\"if {$meshsize != \\\"undefined\\\"} { set options.meshsize $meshsize }\\n\"\n,\"if { $inputmeshfilename == \\\"undefined\\\" } {\\n\"\n,\"Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\\n\"\n,\"} else {\\n\"\n,\"Ng_LoadMesh $inputmeshfilename\\n\"\n,\"if { $mergemeshfilename != \\\"undefined\\\" } {\\n\"\n,\"Ng_MergeMesh $mergemeshfilename\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { $refinementfilename != \\\"undefined\\\" } {\\n\"\n,\"Ng_Bisect $refinementfilename\\n\"\n,\"}\\n\"\n,\"if { $meshfiletype == \\\"netgen\\\" } {\\n\"\n,\"Ng_SaveMesh $meshfilename\\n\"\n,\"} else {\\n\"\n,\"if { [catch { Ng_ExportMesh $meshfilename $meshfiletype } ] == 1 } {\\n\"\n,\"puts \\\"Unknown file format $meshfiletype\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_Exit;\\n\"\n,\"exit\\n\"\n,\"} else {\\n\"\n,\"set code [catch { \\n\"\n,\"proc dotest {} {\\n\"\n,\"source ngtest.tcl\\n\"\n,\"}\\n\"\n,\"proc Ng_RunShell {} {\\n\"\n,\"puts \\\"Wellcome to NG Shell mode\\\"\\n\"\n,\"set line 1\\n\"\n,\"while { 1 } {\\n\"\n,\"puts -nonewline \\\"$line: \\\"\\n\"\n,\"flush stdout\\n\"\n,\"set cmdline [gets stdin]\\n\"\n,\"if { [catch $cmdline errcode] } {\\n\"\n,\"puts \\\"$errcode\\\"\\n\"\n,\"}\\n\"\n,\"incr line 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc Ng_PrintCmdIndex { } {\\n\"\n,\"global cmdindex\\n\"\n,\"foreach { lst } $cmdindex {\\n\"\n,\"puts $lst\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc Ng_PrintHlpIndex { } {\\n\"\n,\"global hlpindex\\n\"\n,\"global secindex\\n\"\n,\"foreach {sec} $secindex {\\n\"\n,\"puts \\\"\\\\n  * $sec:\\\"\\n\"\n,\"foreach {lst} $hlpindex {\\n\"\n,\"if {$sec == [lindex $lst 1]} {\\n\"\n,\"puts \\\"    * [lindex $lst 2]: [lindex $lst 3]\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc Ng_RegisterCmd { cmd section syntax {help \\\"\\\"} } {\\n\"\n,\"global hlpindex\\n\"\n,\"global cmdindex\\n\"\n,\"global secindex\\n\"\n,\"puts \\\"register command $cmd\\\"\\n\"\n,\"if { [lsearch $cmdindex cmd] != -1 } {\\n\"\n,\"puts \\\"command '$cmd' already defined\\\"\\n\"\n,\"} else {\\n\"\n,\"lappend cmdindex $cmd\\n\"\n,\"lappend hlpindex [list $cmd $section $syntax $help]\\n\"\n,\"if {[lsearch $secindex $section]==-1} {\\n\"\n,\"lappend secindex $section\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"exit\\\" \\\"general\\\" \\\"exit\\\" \\\"exit Netgen shell mode\\\"\\n\"\n,\"proc nghelp { {sec \\\"\\\"} } {\\n\"\n,\"global secindex\\n\"\n,\"global hlpindex\\n\"\n,\"global cmdindex\\n\"\n,\"if { $sec == \\\"\\\" } {\\n\"\n,\"Ng_PrintHlpIndex\\n\"\n,\"puts \\\"\\\\n  type help 'section'\\\\n\\\"\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\"if { [lsearch $secindex $sec] != -1} {\\n\"\n,\"foreach {lst} $hlpindex {\\n\"\n,\"if {[lindex $lst 1] == $sec } {\\n\"\n,\"puts \\\"  * [lindex $lst 2]: [lindex $lst 3]\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\"set ind [lsearch $cmdindex $sec]\\n\"\n,\"if {$ind != -1} {\\n\"\n,\"set lst [lindex $hlpindex $ind]\\n\"\n,\"puts \\\"  * [lindex $lst 2]: [lindex $lst 3]\\\"\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\"puts \\\"  unknown section or command $sec\\\"\\n\"\n,\"}\\n\"\n,\"set ngtimer 0\\n\"\n,\"proc nggettimer {} {\\n\"\n,\"return [clock clicks -milliseconds]\\n\"\n,\"}\\n\"\n,\"proc ngtic {} {\\n\"\n,\"set ::ngtimer [nggettimer]\\n\"\n,\"}\\n\"\n,\"proc ngtoc { {logfile stdout} } {\\n\"\n,\"set end [nggettimer]\\n\"\n,\"set tim [expr ($end - $::ngtimer)/1000.0]\\n\"\n,\"puts $logfile \\\"$tim s\\\"\\n\"\n,\"}\\n\"\n,\"proc ngloadgeometry { fname } {\\n\"\n,\"if { ![file exists $fname] } {\\n\"\n,\"puts \\\"error: file $fname does not exist\\\"\\n\"\n,\"} else {\\n\"\n,\"set err [catch {Ng_LoadGeometry $fname}]\\n\"\n,\"if {$err != 0} {\\n\"\n,\"puts \\\"error: loading geometry failed\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"ngloadgeometry\\\" \\\"netgen\\\" \\\"ngloadgeometry <file>\\\" \\\"load geometry file\\\"\\n\"\n,\"proc ngparsegeometry {} {\\n\"\n,\"set err [catch {Ng_ParseGeometry}]\\n\"\n,\"if {$err} {\\n\"\n,\"puts \\\"error: parsing geometry failed\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"ngparsegeometry\\\" \\\"netgen\\\" \\\"ngparsegeometry\\\" \\\"parse geometry\\\"\\n\"\n,\"proc nggeneratemesh {} {\\n\"\n,\"set err [catch {Ng_GenerateMesh}]\\n\"\n,\"if {$err} {\\n\"\n,\"puts \\\"error:  mesh generation failed\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"nggeneratemesh\\\" \\\"netgen\\\" \\\"nggeneratemesh\\\" \\\"generate mesh\\\"\\n\"\n,\"proc ngsavemesh { fname } {\\n\"\n,\"if { [file exists $fname]} {\\n\"\n,\"puts \\\"warning: existing file $fname overwritten\\\"\\n\"\n,\"} else {\\n\"\n,\"set err [catch {Ng_SaveMesh $fname}]\\n\"\n,\"if {$err != 0} {\\n\"\n,\"puts \\\"error: saving mesh failed\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"ngsavemesh\\\" \\\"netgen\\\" \\\"ngsavemesh <file>\\\" \\\"save mesh to file\\\"\\n\"\n,\"proc ngset { opt {val 0} } {\\n\"\n,\"if {$opt == \\\"meshsize\\\"} {\\n\"\n,\"set ::options.meshsize $val\\n\"\n,\"Ng_SetMeshingParameters\\n\"\n,\"} elseif {$opt == \\\"printmsg\\\"} {\\n\"\n,\"set ::options.printmsg $val\\n\"\n,\"Ng_SetMeshingParameters\\n\"\n,\"} else {\\n\"\n,\"puts \\\"error: unknown option $opt\\\";\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"Ng_RegisterCmd \\\"ngset\\\" \\\"netgen\\\" \\\"ngset <option> <val>\\\" \\\"set option to val\\\"\\n\"\n,\"proc nganalyzegeometry {} {\\n\"\n,\"Ng_GenerateMesh ag ag\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngmeshedges {} {\\n\"\n,\"Ng_GenerateMesh me me\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngmeshsurface { } {\\n\"\n,\"Ng_GenerateMesh ms ms\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngoptimizesurface { {step all} } {\\n\"\n,\"if {$step == \\\"all\\\"} {\\n\"\n,\"Ng_GenerateMesh os os cmsmSm\\n\"\n,\"} elseif {$step == \\\"meshsmoothing\\\"} {\\n\"\n,\"Ng_GenerateMesh os os m\\n\"\n,\"} elseif {$step == \\\"topologicedgeswapping\\\" } {\\n\"\n,\"Ng_GenerateMesh os os s\\n\"\n,\"} elseif {$step == \\\"metricedgeswapping\\\"} {\\n\"\n,\"Ng_GenerateMesh os os S\\n\"\n,\"} elseif {$step == \\\"combinepoints\\\"} {\\n\"\n,\"Ng_GenerateMesh os os c\\n\"\n,\"} else {\\n\"\n,\"puts \\\"error: unknown option in ngoptimizesurface\\\"\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngmeshvolume { } {\\n\"\n,\"Ng_GenerateMesh mv mv\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngoptimizevolume {{step \\\"\\\"} } {\\n\"\n,\"if {$step == \\\"\\\"} {\\n\"\n,\"Ng_GenerateMesh ov ov\\n\"\n,\"} elseif {$step == \\\"smooth\\\"} {\\n\"\n,\"Ng_GenerateMesh ov ov m\\n\"\n,\"} elseif {$step == \\\"smoothjacobian\\\"} {\\n\"\n,\"Ng_GenerateMesh ov ov j\\n\"\n,\"} else {\\n\"\n,\"puts \\\"error: unknown step $step in ngoptimizevolume\\\"\\n\"\n,\"return\\n\"\n,\"}\\n\"\n,\"Ng_ReadStatus\\n\"\n,\"}\\n\"\n,\"proc ngsloadpde {fname} {\\n\"\n,\"if { ![file exists $fname] } {\\n\"\n,\"puts \\\"warning: pdefile $fname does not exist\\\"\\n\"\n,\"} else {\\n\"\n,\"puts \\\"load pde $fname\\\"\\n\"\n,\"NGS_LoadPDE $fname\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"proc ngssolvepde {} {\\n\"\n,\"NGS_SolvePDE\\n\"\n,\"}\\n\"\n,\"catch {source \\\"${::ngdir}/ngtesting.tcl\\\"} errcode\\n\"\n,\"} errcode]\\n\"\n,\"if {$code} {\\n\"\n,\"puts \\\"error: $errcode\\\"\\n\"\n,\"}\\n\"\n,\"set code [ catch {Ng_RunShell} errcode]\\n\"\n,\"if {$code} {\\n\"\n,\"puts \\\"error: $errcode\\\"\\n\"\n,\"}\\n\"\n,\"Ng_Exit;\\n\"\n,\"exit\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set stereo [Ng_GetCommandLineParameter stereo]\\n\"\n,\"if { $stereo == \\\"defined\\\" } {\\n\"\n,\"set viewoptions.stereo 1\\n\"\n,\"puts \\\"use stereo mode\\\"\\n\"\n,\"Ng_SetVisParameters;\\n\"\n,\"redraw\\n\"\n,\"}\\n\"\n,\"set ngsolve_loaded 0\\n\"\n,\"catch {\\n\"\n,\"source ${ngdir}/ngsolve.tcl;\\n\"\n,\"set ngsolve_loaded 1\\n\"\n,\"}\\n\"\n,\"set pathlist [split $::env(PATH) \\\\ [expr {$::tcl_platform(platform) == \\\"windows\\\" ? \\\";\\\" : \\\":\\\"}]]\\n\"\n,\"foreach dir $pathlist {\\n\"\n,\"if { $ngsolve_loaded != 1 } {\\n\"\n,\"catch {\\n\"\n,\"source ${dir}/ngsolve.tcl\\n\"\n,\"set ngsolve_loaded 1\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"set scriptfilename [Ng_GetCommandLineParameter script]\\n\"\n,\"if { $scriptfilename != \\\"undefined\\\" } {\\n\"\n,\"if { [catch { source $scriptfilename } errstring] == 1 } {\\n\"\n,\"puts \\\"Error in input: $errstring\\\"\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { [Ng_GetCommandLineParameter help]==\\\"defined\\\" } {\\n\"\n,\"if { $zugstange == 1 } {\\n\"\n,\"print_zug_commandline_help\\n\"\n,\"exit;\\n\"\n,\"} {\\n\"\n,\"if { $trafoapp == 1 } {\\n\"\n,\"print_trafo_commandline_help;\\n\"\n,\"} {\\n\"\n,\"print_commandline_help;\\n\"\n,\"Ng_Exit;\\n\"\n,\"exit\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"}\\n\"\n,\"if { [file exists startup.tcl] } {\\n\"\n,\"source startup.tcl }\\n\"\n,\"catch { source ${ngdir}/demoapp.tcl }\\n\"\n,\"catch { source ${ngdir}/dropsexp.tcl }\\n\"\n, nullptr\n};\n"
  },
  {
    "path": "ng/onetcl.py",
    "content": "import glob\nimport functools\n\n# load all tcl files in current folder\ntclfiles = {}\nfor fname in glob.glob('*.tcl'):\n    tclfiles[fname] = open(fname,'r').read()\n\n# do a topological sorting (such that if a.tcl is including b.tcl,\n# a will come after b in the sorted list)\nfnames = list(tclfiles.keys())\nfnames.sort(key=functools.cmp_to_key( lambda x,y: tclfiles[x].find('/'+y) ))\n\n# replace all occurrences of 'source bla.tcl' with the code of bla.tcl\nfor f in fnames:\n    for g in fnames:\n        if(tclfiles[f].find('/'+g) >= 0):\n            tclfiles[f] = tclfiles[f].replace(\"source ${ngdir}/\"+g, tclfiles[g])\n\n# write a cpp file containing the result of ng.tcl\nonetclcpp = open(\"onetcl.cpp\",'w')\nonetclcpp.write('#include <mydefs.hpp>\\n');\nonetclcpp.write('DLL_HEADER const char * ngscript[] = {\"\"'+'\\n');\n\n# make sure to remove comments (and if lines with comments end with '\\' also the next line(s) )\nskip_next = False # flag to indicate that the next line should be removed\nfor line in tclfiles[\"ng.tcl\"].split('\\n'):\n    line = line.strip()\n    if len(line)==0:\n        skip_next = False\n        continue\n    if skip_next:\n        # skip as long as lines end with '\\'\n        skip_next = line[-1]=='\\\\'\n        continue\n    if(line.find('#')>-1):\n        # comment found (not necessarily the whole line)\n        skip_next = line[-1]=='\\\\'\n        line = line[:line.find('#')]\n    if len(line)>0:\n        s = ',\"' + line.replace('\\\\', r'\\\\').replace('\"', r'\\\"') + '\\\\n\"\\n'\n        onetclcpp.write(s)\n\nonetclcpp.write(', nullptr\\n');\nonetclcpp.write('};\\n');\nonetclcpp.close();\n"
  },
  {
    "path": "ng/parallelfunc.cpp",
    "content": "#ifdef OLDFILE\n\n\n#ifdef PARALLEL\n\n#include \"dlfcn.h\"\n\n\n// #include <mystdlib.h>\n\n#include <meshing.hpp>\n\n// #include \"incvis.hpp\"\n#include <visual.hpp>\n\n\n#ifdef PARALLELGL\n\n#ifndef WIN32\n\n#define GLX_GLXEXT_LEGACY\n#define GLX_GLXEXT_PROTOTYPES\n\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xatom.h>  /* for XA_RGB_DEFAULT_MAP atom */\n#include <GL/glx.h>  \n#include <GL/glxext.h>\n#endif\n\n#endif\n\n\n#include <meshing.hpp>\n#include \"../interface/writeuser.hpp\"\n\nvoid (*NGS_ParallelRun) (const string & message) = NULL;\n\n\nnamespace netgen\n{\n  extern string ngdir;\n\n#ifdef OPENGL\n  extern VisualSceneMesh vsmesh;\n#endif\n}\n\nvoid Parallel_Exit();\n\n\nnamespace netgen {\n  extern std::shared_ptr<NetgenGeometry> ng_geometry;\n  extern shared_ptr<Mesh>  mesh;\n  extern VisualSceneMesh vsmesh;\n  extern VisualSceneSolution & GetVSSolution();\n  extern Flags parameters;\n  extern DLL_HEADER MeshingParameters mparam;\n}\n\nusing namespace netgen;\nusing netgen::RegisterUserFormats;\n\n\n\nvoid ParallelRun()\n{   \n  VisualSceneSolution vssolution = GetVSSolution();\n\n  string message;\n  MPI_Status status;\n      \n\n  MPI_Comm_size(MPI_COMM_WORLD, &ntasks);\n  MPI_Comm_rank(MPI_COMM_WORLD, &id);\n\n  if (parameters.StringFlagDefined (\"testout\"))\n    {\n      delete testout;\n      testout = new ofstream (string(\"testout_proc\") + id  );\n    }\n\n    \n\n  while ( true )\n    {\n      message = MyMPI_RecvCmd();\n\n      if ( message.compare(0, 3, \"ngs\") == 0 ) \n        {\n          // PrintMessage ( 1, \"Starting NgSolve routine \", message ) ;\n\n\t  if (NGS_ParallelRun == NULL)\n\t    {\n\t      static int timer = NgProfiler::CreateTimer (\"load shared library ngsolve\");\n\t      NgProfiler::RegionTimer reg (timer);\n  \n\n\t      void * handle = dlopen (\"libngsolve.so\", RTLD_NOW | RTLD_GLOBAL);\n\t      if (!handle)\n\t\t{\n\t\t  cerr << \"cannot load shared library libngsolve.so\" << endl;\n\t\t  exit(1);\n\t\t}\n\t      \n\t      NGS_ParallelRun = (void (*) (const string & message))  dlsym (handle, \"NGS_ParallelRun\");\n\t      \n\t      if (!NGS_ParallelRun)\n\t\t{\n\t\t  cerr << \"cannot bind function NGS_ParallelRun\" << endl;\n\t\t  exit(1);\n\t\t}\n\t    }\n          (*NGS_ParallelRun) (message);\n        }\n      else if ( message == \"mesh\" )\n\t{\n\t  VT_USER_START (\"Mesh::ReceiveParallelMesh\");\n\t  mesh.reset( new netgen::Mesh);\n\t  mesh->SendRecvMesh();\n// \t  vsmesh.SetMesh (mesh);\n// \t  vssolution.SetMesh (mesh);\n      SetGlobalMesh (mesh);\n\t  VT_USER_END (\"Mesh::ReceiveParallelMesh\");\n\t}\n\n      else if ( message == \"visualize\" )\n\t{\n\t  cout << \"parallel message visualize depreciated\" << endl;\n\t}\n      \n      else if ( message == \"bcastparthread\" )\n\t{\n\t  MyMPI_Bcast (mparam.parthread, MPI_COMM_WORLD);\n\t}\n\n\n#ifdef PARALLELGL\n\n      else if ( message == \"redraw\" )\n\t{\n\t  // draw into the same GLX - drawing context\n\t  // works on parallel machine, but \n\t  // did not manage to get glXImportContextEXT working on Laptop (JS)\n\n\t  string redraw_cmd;\n\t  // MyMPI_Recv (redraw_cmd, 0, MPI_TAG_VIS);\n\t  redraw_cmd = MyMPI_RecvCmd();\n\t  \n\t  // PrintMessage (1, \"Redraw - \", redraw_cmd);\n                  \n\t  static string displname;\n\t  static int curDrawable, contextid;\n\t    \n\t  static Display * display = NULL;\n\t  static GLXContext context;\n\t  static XVisualInfo * visinfo = 0;\n\t  \n\t  // if (!display)\n\t  if (redraw_cmd == \"init\")\n\t    {\n\t      MyMPI_Recv (displname, 0, MPI_TAG_VIS);\n\t      MyMPI_Recv (curDrawable, 0, MPI_TAG_VIS);\n\t      MyMPI_Recv (contextid, 0, MPI_TAG_VIS);\n\t      \n\t      display = XOpenDisplay (displname.c_str());\n\n\t      \n\t      /*\n\t\tPrintMessage (3, \"displ - name = \", displname);\n\t\tPrintMessage (3, \"display = \", display,\n\t\t\" display props: \",\n\t\t\" screen w = \", XDisplayWidth (display, 0),\n\t\t\" , h = \", XDisplayHeight (display, 0));\n\t      */\n\n\t      /*\n\t\tWindow win;\n\t\tint wx, wy;\n\t\tunsigned int ww, wh, bw, depth;\n\t\tcout << \"got drawable: \" << curDrawable << \", contextid: \" << contextid <<  endl;\n\t\t\n\t\tcout << \"get geometriy...\" << endl;\n\t\tXGetGeometry(display, curDrawable, &win,\n\t\t&wx, &wy, &ww, &wh,\n\t\t&bw, &depth);\n\t\tcout << \"have!\" << endl;\n\t      \n\t\tcout << \"P\" << id << \": window-props:  x = \" << wx << \", y = \" << wy \n\t\t<< \", w = \" << ww << \", h = \" << wh << \", depth = \" << depth << endl;\n\t      */\n\t      \n#define VISUAL\n#ifdef VISUAL\n\n#ifdef VISINFO_OLD\n\t      //this does not seem to work anymore (but might still be with togl1.7?)\n\t      // make a new GLXContext\n\t      // first, generate a visual (copied from togl)\n\t\t\n\t      int     attrib_list[1000];\n\t\t\n#  define MAX_ATTEMPTS 12\n\t      static int ci_depths[MAX_ATTEMPTS] = {\n\t\t8, 4, 2, 1, 12, 16, 8, 4, 2, 1, 12, 16\n\t      };\n\t      static int dbl_flags[MAX_ATTEMPTS] = {\n\t\t0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1\n\t      };\n\t\t\n\t      /* It may take a few tries to get a visual */\n\t\t\n\t      for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) \n\t\t{\n\t\t  int attrib_count = 0;\n\t\t  attrib_list[attrib_count++] = GLX_USE_GL;\n\t\t      \n                      \n\t\t  /* RGB[A] mode */\n\t\t  attrib_list[attrib_count++] = GLX_RGBA;\n\t\t  attrib_list[attrib_count++] = GLX_RED_SIZE;\n\t\t  attrib_list[attrib_count++] = 1;\n\t\t  attrib_list[attrib_count++] = GLX_GREEN_SIZE;\n\t\t  attrib_list[attrib_count++] = 1;\n\t\t  attrib_list[attrib_count++] = GLX_BLUE_SIZE;\n\t\t  attrib_list[attrib_count++] = 1;\n\t\t  // attrib_list[attrib_count++] = GLX_ALPHA_SIZE;\n\t\t  // attrib_list[attrib_count++] = 1;\n                      \n\t\t  attrib_list[attrib_count++] = GLX_DEPTH_SIZE;\n\t\t  attrib_list[attrib_count++] = 1;\n\n\t\t  attrib_list[attrib_count++] = GLX_DOUBLEBUFFER;\n\n\t\t  attrib_list[attrib_count++] = None;\n\n\t\t  visinfo = glXChooseVisual(display, 0, \n\t\t\t\t\t    attrib_list);\n\t\t  cout << \"have vis?\" << endl;\n\n\t\t  if (visinfo) {\n\t\t    /* found a GLX visual! */\n\t\t    // cout << \"found VISINFO !!!\" << endl;\n\t\t    cout << \"found VISINFO !!!\" << endl;\n\n\t\t    /*\n\t\t    int hi = 0;\n\t\t    std::cout << \"attribs = \";\n\t\t    while (attrib_list[hi] != None)\n\t\t      std::cout << attrib_list[hi++] << \" \";\n\t\t    std::cout << std::endl;\n\t\t    */\n\t\t    \n\t\t    break;\n\t\t  }\n\t\t}\n\t      if (!visinfo)\n\t\tcerr << \"no VISINFO found\" << endl;\n\n#else\n\t      //get all possible confs\n\t      int nconfs;\n\t      auto cptr = glXGetFBConfigs (display,0, &nconfs);\n\t      NgArray<int> conf_ids(nconfs);\n\t      for(int k=0;k<nconfs;k++)\n\t\tglXGetFBConfigAttrib(display, cptr[k], GLX_FBCONFIG_ID, &(conf_ids[k]));\n\t      \n\t      //get drawable->FBConfig->visual\n\t      unsigned int d_fbc_id;\n\t      glXQueryDrawable( display, curDrawable, GLX_FBCONFIG_ID, &d_fbc_id); \n\t      GLXFBConfig d_fbc;\n\t      for(int k=0;k<nconfs;k++)\n\t\tif(d_fbc_id==conf_ids[k])\n\t\t  d_fbc = cptr[k];\n\t      visinfo = glXGetVisualFromFBConfig(display,d_fbc);\n#endif\n\n\t      // context = glXCreateContext( display, visinfo, 0, /* curContext, */ False );\n\t      context = glXCreateContext( display, visinfo, glXImportContextEXT ( display, contextid ), False);\n\t      glXMakeCurrent (display, curDrawable, context);\n\n\n#else\n\t      // try to get GLXcontext from the master. \n\t      // this needs an indirect context (BUT DOES NOT WORK ????)\n\n\t      context = glXImportContextEXT ( display, contextid );\n\n\t      PrintMessage (1, \"GLX-contextid = \" , contextid,\n\t\t\t    \" imported context \", context);\n\n\t      glXMakeCurrent (display, curDrawable, context);\n#endif\n\n\t      // PrintMessage (1, \"redraw - init complete\");\n\t    }\n\t  \n\t  if (redraw_cmd == \"broadcast\")\n\t    {\n\t      vsmesh.Broadcast ();\n\t    }\n\n\t  if (redraw_cmd == \"linelist\")\n\t    {\n\t      // glXMakeCurrent (display, curDrawable, context);\n\t      vsmesh.BuildLineList();\n\t      // glXMakeCurrent (display, None, NULL);\n\t    }\n\n\t  if (redraw_cmd == \"filledlist\")\n\t    {\n\t      vsmesh.BuildFilledList (false);\n\t    }\n\n\t  if (redraw_cmd == \"solsurfellist\")\n\t    {\n\t      vssolution.DrawSurfaceElements();\n\t    }\n\n\t  if (redraw_cmd == \"solsurfellinelist\")\n\t    {\n\t      vssolution.DrawSurfaceElementLines();\n\t    }\n\n\t  if (redraw_cmd == \"clipplanetrigs\")\n\t    {\n\t      vssolution.DrawClipPlaneTrigs();\n\t    }\n\t    \n\t  if (redraw_cmd == \"getminmax\")\n\t    {\n\t      double hmin, hmax;\n\t      vssolution.GetMinMax (-1, -1, hmin, hmax);\n\t    }\n\t}\n#endif\n\n\n\n      else if ( message ==  \"end\" )\n\t{\n\t  mesh.reset();\n\t  ng_geometry.reset();\n\t  break;\n\t}\n      \n      else\n\t{\n\t  PrintMessage ( 1, \"received unidentified message '\" + message + \"'\\n\");\n\t  break;\n\t}\n      \n    }\n}\n\n\n\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "ng/parallelfunc.hpp",
    "content": "das braucht keiner mehr\n\n\n\n#ifndef FILE_PARALLELFUNC\n#define FILE_PARALLELFUNC\n\n\nvoid ParallelRun();\n\nvoid LoadPDEParallel ( const char*  filename );\n\n\n#ifdef NGSOLVE\n// void NGS_ParallelRun ( const string & message);\n#endif\n\n#endif\n"
  },
  {
    "path": "ng/parameters.tcl",
    "content": "proc setgranularity { gran } {\r\n#\r\n#    puts \"set granularity $gran\"\r\n#\r\n    if {$gran == 6} { return }\r\n    set gran [expr $gran - 1]\r\n#\r\n    global options.curvaturesafety\r\n    set surfcurvlist { 1 1.5 2 3 5 }\r\n    set options.curvaturesafety [lindex $surfcurvlist $gran]\r\n\r\n    global options.segmentsperedge\r\n    set spelist { 0.3 0.5 1 2 3 }\r\n    set options.segmentsperedge [lindex $spelist $gran]\r\n    \r\n    global stloptions.resthsurfcurvfac\r\n    set surfcurvfaclist { 0.25 0.5 1 1.5 3 }\r\n    set stloptions.resthsurfcurvfac [lindex $surfcurvfaclist $gran]\r\n\r\n    global stloptions.resthchartdistfac\r\n    set chartdistfaclist { 0.8 1 1.5 2 5 }\r\n    set stloptions.resthchartdistfac [lindex $chartdistfaclist $gran]\r\n\r\n    global stloptions.resthlinelengthfac\r\n    set linelengthfaclist { 0.2 0.35 0.5 1.5 3 }\r\n    set stloptions.resthlinelengthfac [lindex $linelengthfaclist $gran]\r\n\r\n    global stloptions.resthcloseedgefac\r\n    set closeedgefaclist { 0.5 1 2 3.5 5 }\r\n    set stloptions.resthcloseedgefac [lindex $closeedgefaclist $gran]\r\n\r\n\tglobal stloptions.resthminedgelen\r\n    set minedgelenlist { 0.002 0.02 0.2 1.0 2.0 5.0 10.0 }\r\n    set stloptions.resthminedgelen [lindex $minedgelenlist $gran]\r\n\t\r\n    global stloptions.resthedgeanglefac\r\n    set edgeanglefaclist { 0.25 0.5 1 1.5 3 }\r\n    set stloptions.resthedgeanglefac [lindex $edgeanglefaclist $gran]\r\n\r\n\r\n    global stloptions.resthsurfmeshcurvfac \r\n    set surfmeshcurvlist { 1 1.5 2 3 5 }\r\n    set stloptions.resthsurfmeshcurvfac [lindex $surfmeshcurvlist $gran]\r\n\r\n\r\n    global options.grading\r\n    set gradinglist { 0.7 0.5 0.3 0.2 0.1 }\r\n    set options.grading [lindex $gradinglist $gran]\r\n    \r\n}\r\n"
  },
  {
    "path": "ng/sockets.tcl",
    "content": "set sockets.serverport 0\nset sockets.serverhost \"localhost\"\nset sockets.serverlistbox 0\nset sockets.queuelistbox 0\nset sockets.currentjoblistbox 0\nset sockets.answerlistbox 0\nset sockets.myidlabel -1\n\n\nproc updateserverlist { } {\n    global sockets.serverlistbox\n    \n    set retval [Ng_Socket getserverlist]\n\n    ${sockets.serverlistbox} delete 0 end\n\n    for {set i 0} {$i < [llength $retval]} {incr i 3} {\n\t${sockets.serverlistbox} insert end \\\n\t    [format \"%-16s   %6i   %6i\" [lindex $retval $i] [lindex $retval [expr $i+1]] [lindex $retval [expr $i+2]]]\n    }\n}\n\nproc clientsocketdialog { } {\n    set w .clientsock_dlg\n    \n    if {[winfo exists .clientsock_dlg] == 1} {\n\twm withdraw $w\n\twm deiconify $w\n\tfocus $w \n    } {\n\ttoplevel $w\n\n\tglobal sockets.serverhost\n\tglobal sockets.serverport\n\n\tttk::frame $w.general\n\tttk::frame $w.host\n\tttk::label $w.host.lab -text \"Serverhost: \"\n\tttk::entry $w.host.name -width 30 -textvariable sockets.serverhost\n\n\tpack $w.host.lab $w.host.name -side left\n\tpack $w.host\n\n\tttk::frame $w.ports\n\tttk::label $w.ports.lab1 -text \"Serverport: \"\n\tttk::entry $w.ports.statport -width 6 -textvariable sockets.serverport\n\t\n\tpack $w.ports.lab1 $w.ports.statport -side left\n\tpack $w.ports\n\n\tttk::frame $w.listboxes\n\n\tttk::frame $w.listboxes.choosesocketframe\n\n\ttixScrolledListBox $w.listboxes.choosesocketframe.choosesocket -scrollbar auto\n\n\tglobal sockets.serverlistbox\n\n\tset sockets.serverlistbox [$w.listboxes.choosesocketframe.choosesocket subwidget listbox]\n\n\t${sockets.serverlistbox} configure -width 35\n\t${sockets.serverlistbox} configure -selectmode browse\n\t${sockets.serverlistbox} configure -exportselection false\n\n\tttk::button $w.addserver -text \"Add ServerSocket\" -command {\n\t    Ng_Socket addserver ${sockets.serverport} ${sockets.serverhost}\n\t    updateserverlist\n\t}\n\t\n\tpack $w.addserver\n\n\tttk::label $w.linefeed -text \"\\n\"\n\tpack $w.linefeed\n\t\n\tttk::frame $w.clientidframe\n\tttk::label $w.clientidframe.lab -text \"Client ID: \";\n\tglobal sockets.myidlabel\n\tttk::entry $w.clientidframe.val -width 5 -textvariable sockets.myidlabel\n\tttk::button $w.clientidframe.but -text \"Set\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tNg_Socket setid $opserver ${sockets.myidlabel}\n\t\tupdateserverlist\n\t    }\n\t}\n\n\tpack $w.clientidframe.lab $w.clientidframe.val $w.clientidframe.but -side left\n\tpack $w.clientidframe\n\n\n#\tlabel $w.clientidlabel -text \"\\nClient ID: -1\"\n#\tglobal sockets.myidlabel\n#\tset sockets.myidlabel $w.clientidlabel\n#\tpack $w.clientidlabel\n\n\n\tttk::label $w.listboxes.choosesocketframe.chooselab -text [format \"\\n\\n%-16s    %6s  %6s                       \" Host Socket MyID ]\n\tpack $w.listboxes.choosesocketframe.chooselab\n\tpack $w.listboxes.choosesocketframe.choosesocket\n\n\tttk::frame $w.listboxes.choosesocketframe.serverbuttons\n\n\tttk::button $w.listboxes.choosesocketframe.serverbuttons.save -text \"Save\" -command {\n\t    Ng_Socket saveserverlist\n\t}\n\n\tglobal sockets.serverlist\n\tNg_Socket loadserverlist\n\tupdateserverlist\n\n\tttk::button $w.listboxes.choosesocketframe.serverbuttons.delete -text \"Delete\" -command {\n\t   set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tNg_Socket deletesocket [lindex $opsel 0]\n\t\tupdateserverlist\n\t    } \n\t}\n\t\n\tpack $w.listboxes.choosesocketframe.serverbuttons.save $w.listboxes.choosesocketframe.serverbuttons.delete -side left\n\tpack $w.listboxes.choosesocketframe.serverbuttons\n\n\tttk::frame $w.listboxes.statusframe\n\n\tttk::label $w.listboxes.statusframe.statuslabel1 -text \"\\n\\njobqueue\"\n\n\ttixScrolledListBox $w.listboxes.statusframe.queuestatus -scrollbar auto\n\n\tttk::label $w.listboxes.statusframe.statuslabel2 -text \"\\ncurrent job\"\n\n\ttixScrolledListBox $w.listboxes.statusframe.currentjobstatus -scrollbar auto\n\n\tttk::label $w.listboxes.statusframe.statuslabel3 -text \"\\nanswers\"\n\n\ttixScrolledListBox $w.listboxes.statusframe.answers -scrollbar auto\n\n\tglobal sockets.queuelistbox\n\tglobal sockets.currentjoblistbox\n\tglobal sockets.answerlistbox\n\n\tset sockets.queuelistbox [$w.listboxes.statusframe.queuestatus subwidget listbox]\n\tset sockets.currentjoblistbox [$w.listboxes.statusframe.currentjobstatus subwidget listbox]\n\tset sockets.answerlistbox [$w.listboxes.statusframe.answers subwidget listbox]\n\n\t${sockets.queuelistbox} configure -width 50\n\t${sockets.queuelistbox} configure -height 5\n\t${sockets.queuelistbox} configure -selectmode browse\n\t${sockets.queuelistbox} configure -exportselection false\n\t\n\t${sockets.currentjoblistbox} configure -width 50\n\t${sockets.currentjoblistbox} configure -height 1\n\t${sockets.currentjoblistbox} configure -selectmode browse\n\t${sockets.currentjoblistbox} configure -exportselection false\n\n\t${sockets.answerlistbox} configure -width 50\n\t${sockets.answerlistbox} configure -height 5\n\t${sockets.answerlistbox} configure -selectmode browse\n\t${sockets.answerlistbox} configure -exportselection false\n\n\tttk::button $w.listboxes.statusframe.updatebutton -text \"Update\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [Ng_Socket sendqueuestatus $opserver]\n\n\t\t${sockets.queuelistbox} delete 0 end\n\t\t\n\t\tif {[lindex $retval 0] > 0} {\n\t\t    ${sockets.queuelistbox} insert end [format \"Blocked for user %i\" [lindex $retval 0]]\n\t\t} {\n\t\t    ${sockets.queuelistbox} insert end \"Not blocked\"\n\t\t}\n\t\t\n\t\tfor {set i 2} {$i < [expr 2*[lindex $retval 1]+2]} {incr i 2} {\n\t\t    ${sockets.queuelistbox} insert end [format \"client %i, command %s\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\n\t\t}\n\t\t\n\t\t${sockets.answerlistbox} delete 0 end\n\t\t\n\t\tfor {set i [expr 2*[lindex $retval 1]+3]} {$i < [llength $retval]} {incr i 2} {\n\t\t    ${sockets.answerlistbox} insert end [format \"client %i, command %s\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\n\t\t}\n\n\t\t${sockets.currentjoblistbox} delete 0 end\n\t\tset retval [Ng_Socket sendjobstatus $opserver]\n\t\tif {[lindex $retval 0] != 0} {\n\t\t    ${sockets.currentjoblistbox} insert end [format \"client %i, command %s: %s\" [lindex $retval 0] [lindex $retval 1] [lrange $retval 2 end]]\n\t\t}\n\t\t\n\t    }\n\t}\n\n\tpack $w.listboxes.statusframe.statuslabel1 $w.listboxes.statusframe.queuestatus \\\n\t    $w.listboxes.statusframe.statuslabel2 $w.listboxes.statusframe.currentjobstatus \\\n\t    $w.listboxes.statusframe.statuslabel3 $w.listboxes.statusframe.answers \\\n\t    $w.listboxes.statusframe.updatebutton\n\n\tpack $w.listboxes.choosesocketframe $w.listboxes.statusframe -side left\n\t\n\tpack $w.listboxes\n\n\tttk::label $w.lab1 -text \"\\n\"\n\tpack $w.lab1\n\n\n\tttk::frame $w.buttons1\n\tttk::frame $w.buttons2\n\t\n\tttk::button $w.buttons1.getid -text \"Get ID\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [Ng_Socket getid $opserver]\n\t\tupdateserverlist\n\t\tset sockets.myidlabel $retval\n\t    }\n\t}\n\n\tttk::button $w.buttons1.killjob -text \"Kill Cur. Job\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tNg_Socket killcurrentjob $opserver\n\t    }\n\t}\n\n\tttk::button $w.buttons2.sendmesh -text \"Send Mesh\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [Ng_Socket sendmesh $opserver]\n\t\tset sockets.meshsent 1\n\t    }\n\t}\n\n\tttk::button $w.buttons2.sendpde -text \"Send PDE\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [NGS_Socket sendpdefile $opserver]\n\t    }\n\t}\n\n\tttk::button $w.buttons2.solvepde -text \"Solve PDE\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [NGS_Socket solvepde $opserver]\n\t    }\n\t}\n\n\tttk::button $w.buttons2.writesol -text \"Write Solution\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [NGS_Socket writesolution $opserver]\n\t    }\n\t}\n\n\tttk::button $w.buttons2.sendsol -text \"Receive Solution\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [NGS_Socket sendsolution $opserver]\n\t    }\n\t}\n\n\tttk::button $w.buttons1.blockserver -text \"Block Server\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [Ng_Socket blockserver $opserver]\n\t    }\n\t}\n\n\tttk::button $w.buttons1.unblockserver -text \"UnBlock Server\" -command {\n\t    set opsel [${sockets.serverlistbox} curselection]\n\t    if {[llength $opsel] > 0} {\n\t\tset opserver [lindex $opsel 0]\n\t\tset retval [Ng_Socket unblockserver $opserver]\n\t    }\n\t}\n\n\t\n\tpack $w.buttons1.getid $w.buttons1.blockserver $w.buttons1.unblockserver $w.buttons1.killjob -side left\n\tpack $w.buttons2.sendmesh $w.buttons2.sendpde $w.buttons2.solvepde $w.buttons2.writesol $w.buttons2.sendsol -side left\n\n\tpack $w.buttons1 $w.buttons2\n\n\n\twm withdraw $w\n\twm geom $w +200+200\n\twm deiconify $w\n\twm title $w \"Client Socket\"\n\tfocus .options_dlg\n\n    }\n    \n\n}\n\n#.ngmenu.special add command -label \"Client Socket\" \\\n    -command { clientsocketdialog }\n"
  },
  {
    "path": "ng/stlgeom.tcl",
    "content": "#if { [catch { load libstlvis[info sharedlibextension] Ng_STL } result ] } {\n#    puts \"cannot load stl\" \n#    puts \"error: $result\"\n#}\n\n\n.ngmenu.geometry add separator\n\n.ngmenu.geometry add command -label \"STL Doctor...\" \\\n    -command { stldoctordialog; }\n\n.ngmenu.geometry add command -label \"STL Info\" \\\n    -command {\n\tset notriangles 0\n\tset minx 0\n\tset maxx 0\n\tset miny 0\n\tset maxy 0\n\tset minz 0\n\tset maxz 0\n\tset trigscons 0\n\tNg_STLInfo notriangles minx maxx miny maxy minz maxz trigscons\n\tset msgtext \"NO STL-Triangles : $notriangles\\nGeometry:\\nX = $minx - $maxx\\nY = $miny - $maxy\\nZ = $minz - $maxz\\nConsistency Check = $trigscons\\n\"\n\tset msgtext \"$msgtext Status: [Ng_STLInfo status]\"\n\ttk_messageBox -title \"STL Info\" -message  $msgtext -type ok \n    }\n\n"
  },
  {
    "path": "ng/variables.tcl",
    "content": "# netgen global tcl-variables\r\n\r\nset drawmode rotate\r\nset selectvisual geometry\r\n\r\nset dirname .\r\nset loadgeomtypevar \"All Geometry types\"\r\n\r\nset basefilename filename\r\n\r\nset meshoptions.fineness 3\r\nset meshoptions.firststep ag\r\nset meshoptions.laststep ov\r\nset options.memory 0\r\n\r\nset options.localh 1\r\nset options.delaunay 1\r\nset options.checkoverlap 1\r\nset options.checkoverlappingboundary 0\r\nset options.checkchartboundary 1\r\nset options.startinsurface 0\r\nset options.blockfill 1\r\nset options.debugmode 0\r\nset options.dooptimize 1\r\nset options.parthread 1\r\nset options.elsizeweight 0.2\r\nset options.secondorder 0\r\nset options.elementorder 1\r\nset options.quad 0\r\nset options.try_hexes 0\r\nset options.inverttets 0\r\nset options.inverttrigs 0\r\nset options.autozrefine 0\r\n\r\n\r\nset options.meshsize 1000\r\nset options.minmeshsize 0\r\n\r\nset options.curvaturesafety 2\r\nset options.segmentsperedge 2\r\nset options.meshsizefilename \"\"\r\nset options.badellimit 175\r\nset options.optsteps2d 3\r\nset options.optsteps3d 5\r\nset options.opterrpow 2\r\n\r\nset options.grading 0.5\r\nset options.printmsg 2\r\n\r\nset options.parallel_meshing 1\r\nset options.nthreads 4\r\n\r\nset debug.slowchecks 0\r\nset debug.debugoutput 0\r\nset debug.haltexistingline 0\r\nset debug.haltoverlap 0\r\nset debug.haltsuccess 0\r\nset debug.haltnosuccess 0\r\nset debug.haltlargequalclass 0\r\nset debug.haltsegment 0\r\nset debug.haltnode 0\r\nset debug.haltface 0\r\nset debug.haltfacenr 0\r\nset debug.haltsegmentp1 0\r\nset debug.haltsegmentp2 0\r\n\r\nset geooptions.drawcsg 1\r\nset geooptions.detail 0.001\r\nset geooptions.accuracy 1e-6\r\nset geooptions.facets 20\r\nset geooptions.minx -1000\r\nset geooptions.miny -1000\r\nset geooptions.minz -1000\r\nset geooptions.maxx 1000\r\nset geooptions.maxy 1000\r\nset geooptions.maxz 1000\r\n\r\nset viewqualityplot 0\r\nset memuseplot 0\r\nset viewrotatebutton 0\r\nset showsensitivehelp 0\r\nset showhelpline 0\r\n\r\nset viewoptions.specpointvlen 0.3\r\nset viewoptions.light.amb 0.3\r\nset viewoptions.light.diff 0.7\r\nset viewoptions.light.spec 1\r\nset viewoptions.light.locviewer 0\r\nset viewoptions.mat.shininess 50\r\nset viewoptions.mat.transp 0.3\r\nset viewoptions.colormeshsize 0\r\nset viewoptions.whitebackground 1\r\nset viewoptions.drawcoordinatecross 1\r\nset viewoptions.drawcolorbar 1\r\nset viewoptions.drawnetgenlogo 1\r\nset viewoptions.stereo 0\r\nset viewoptions.shrink 1\r\n\r\nset viewoptions.drawfilledtrigs 1\r\nset viewoptions.drawedges 0\r\nset viewoptions.drawbadels 0\r\nset viewoptions.centerpoint 0\r\nset viewoptions.drawelement 0\r\nset viewoptions.drawoutline 1\r\nset viewoptions.drawtets 0\r\nset viewoptions.drawtetsdomain 0\r\nset viewoptions.drawprisms 0\r\nset viewoptions.drawpyramids 0\r\nset viewoptions.drawhexes 0\r\nset viewoptions.drawidentified 0\r\nset viewoptions.drawpointnumbers 0\r\nset viewoptions.drawedgenumbers 0\r\nset viewoptions.drawfacenumbers 0\r\nset viewoptions.drawelementnumbers 0\r\nset viewoptions.drawsegmentnumbers 0\r\nset viewoptions.drawsurfaceelementnumbers 0\r\nset viewoptions.drawdomainsurf 0\r\n\r\nset viewoptions.drawededges 1\r\nset viewoptions.drawedpoints 1\r\nset viewoptions.drawedpointnrs 0\r\nset viewoptions.drawedtangents 0\r\nset viewoptions.drawededgenrs 0\r\nset viewoptions.drawmetispartition 0\r\n\r\nset viewoptions.drawcurveproj 0\r\nset viewoptions.drawcurveprojedge 1\r\n\r\nset viewoptions.clipping.nx 0\r\nset viewoptions.clipping.ny 1\r\nset viewoptions.clipping.nz 0\r\nset viewoptions.clipping.dist 0\r\nset viewoptions.clipping.dist2 0\r\nset viewoptions.clipping.enable 0\r\nset viewoptions.clipping.onlydomain 0\r\nset viewoptions.clipping.notdomain 0\r\n\r\nset viewoptions.usecentercoords 0\r\nset viewoptions.centerx 0\r\nset viewoptions.centery 0\r\nset viewoptions.centerz 0\r\n\r\nset viewoptions.drawspecpoint 0\r\nset viewoptions.specpointx 0\r\nset viewoptions.specpointy 0\r\nset viewoptions.specpointz 0\r\n\r\n\r\nset stloptions.showtrias 0\r\nset stloptions.showfilledtrias 1\r\nset stloptions.showedges 1\r\nset stloptions.showmarktrias 0\r\nset stloptions.showactivechart 0\r\nset stloptions.yangle 30\r\nset stloptions.contyangle 20\r\nset stloptions.edgecornerangle 60\r\nset stloptions.chartangle 15\r\nset stloptions.outerchartangle 70\r\nset stloptions.usesearchtree 0\r\nset stloptions.chartnumber 1\r\nset stloptions.charttrignumber 1\r\nset stloptions.chartnumberoffset 0\r\n\r\nset stloptions.atlasminh 0.1\r\nset stloptions.resthsurfcurvfac 2\r\nset stloptions.resthsurfcurvenable 0\r\nset stloptions.resthatlasfac 2\r\nset stloptions.resthatlasenable 1\r\nset stloptions.resthchartdistfac 1.2\r\nset stloptions.resthchartdistenable 1\r\nset stloptions.resthlinelengthfac 0.5\r\nset stloptions.resthlinelengthenable 1\r\nset stloptions.resthcloseedgefac 1\r\nset stloptions.resthcloseedgeenable 1\r\nset stloptions.resthminedgelen 0.01\r\nset stloptions.resthminedgelenenable 1\r\nset stloptions.resthedgeanglefac 1\r\nset stloptions.resthedgeangleenable 0\r\nset stloptions.resthsurfmeshcurvfac 1\r\nset stloptions.resthsurfmeshcurvenable 0\r\nset stloptions.recalchopt 1\r\n\r\nset stldoctor.drawmeshededges 1\r\nset stldoctor.geom_tol_fact 0.000001\r\nset stldoctor.useexternaledges 0\r\nset stldoctor.showfaces 0\r\nset stldoctor.conecheck 1\r\nset stldoctor.spiralcheck 1\r\nset stldoctor.selecttrig 0\r\nset stldoctor.selectmode 1\r\nset stldoctor.longlinefact 0\r\nset stldoctor.showexcluded 1\r\nset stldoctor.edgeselectmode 0\r\nset stldoctor.nodeofseltrig 1\r\nset stldoctor.showtouchedtrigchart 0\r\nset stldoctor.showedgecornerpoints 0\r\nset stldoctor.showmarkedtrigs 1\r\nset stldoctor.dirtytrigfact 0.01\r\nset stldoctor.smoothangle 90\r\nset stldoctor.selectwithmouse 1\r\nset stldoctor.showvicinity 0\r\nset stldoctor.vicinity 50\r\nset stldoctor.smoothnormalsweight 0.2\r\n\r\nset occoptions.showvolumenr 0\r\nset occoptions.showsurfaces 1\r\nset occoptions.showedges 1\r\nset occoptions.showsolidnr 0\r\nset occoptions.showsolidnr2 0\r\nset occoptions.visproblemfaces 0\r\nset occoptions.zoomtohighlightedentity 0\r\nset occoptions.deflection 1\r\nset occoptions.tolerance 1e-3\r\nset occoptions.fixsmalledges 1\r\nset occoptions.fixspotstripfaces 1\r\nset occoptions.sewfaces 1\r\nset occoptions.makesolids 1\r\nset occoptions.splitpartitions 0\r\n\r\nset meshdoctor.active 0\r\nset meshdoctor.markedgedist 1\r\n\r\n\r\n# variablenname mit punkt problematisch!\r\nset status_np 0\r\nset status_ne 0\r\nset status_nse 0\r\nset status_working \" \"\r\nset status_task \" \"\r\nset status_percent 0\r\nset status_filename 0\r\nset status_tetqualclasses \"10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40\"\r\n\r\nset exportfiletype \"Neutral Format\"\r\nset importfiletype \"Neutral Format\"\r\n\r\nset preproc.facenr 0\r\nset preproc.selectmode query\r\nset preproc.numtrig 0\r\n\r\nset mem_moveable 0\r\n\r\n\r\nset multithread_pause 0\r\nset multithread_testmode 0\r\nset multithread_redraw 0\r\nset multithread_drawing 0\r\nset multithread_terminate 0\r\nset multithread_running 0\r\n\r\nset level 0\r\n\r\n\r\nset tablesforoutput {}\r\n\r\n\r\n\r\nset optlist {\r\n    options.localh \r\n    options.delaunay \r\n    options.checkoverlap \r\n    options.startinsurface \r\n    options.blockfill \r\n    options.dooptimize \r\n    options.elsizeweight \r\n    options.meshsize \r\n    options.minmeshsize \r\n    options.curvaturesafety \r\n    options.optsteps2d \r\n    options.optsteps3d \r\n    options.secondorder\r\n}\r\n\r\n\r\nset visoptions.usetexture 1\r\nset visoptions.invcolor 0\r\nset visoptions.imaginary 0\r\nset visoptions.lineartexture 0\r\nset visoptions.numtexturecols 8\r\nset visoptions.showclipsolution 1\r\nset visoptions.showsurfacesolution 0\r\nset visoptions.drawfieldlines 0\r\nset visoptions.drawpointcurves 1\r\nset visoptions.numfieldlines 100\r\nset visoptions.fieldlinesrandomstart 0\r\nset visoptions.fieldlinesstartarea box\r\nset visoptions.fieldlinesstartareap1x 1\r\nset visoptions.fieldlinesstartareap1y 1\r\nset visoptions.fieldlinesstartareap1z 1\r\nset visoptions.fieldlinesstartareap2x 0\r\nset visoptions.fieldlinesstartareap2y 0\r\nset visoptions.fieldlinesstartareap2z 0\r\nset visoptions.fieldlinesstartface -1\r\nset visoptions.fieldlinesfilename none\r\nset visoptions.fieldlinestolerance 0.0005\r\nset visoptions.fieldlinesrktype crungekutta\r\nset visoptions.fieldlineslength 0.5\r\nset visoptions.fieldlinesmaxpoints 500\r\nset visoptions.fieldlinesthickness 0.0015\r\nset visoptions.fieldlinesvecfunction none\r\nset visoptions.fieldlinesphase 0\r\nset visoptions.fieldlinesonlyonephase 1\r\n\r\n\r\nset visoptions.lineplotfile empty\r\nset visoptions.lineplotsource file\r\nset visoptions.lineplotusingx 0\r\nset visoptions.lineplotusingy 1\r\nset visoptions.lineplotautoscale 1\r\nset visoptions.lineplotxmin 0\r\nset visoptions.lineplotxmax 1\r\nset visoptions.lineplotymin 0\r\nset visoptions.lineplotymax 1\r\nset visoptions.lineplotcurrentnum -1\r\nset visoptions.lineplotinfos \"\"\r\nset visoptions.lineplotselected none\r\nset visoptions.lineplotselector \"\"\r\nset visoptions.lineplotcolor red\r\nset visoptions.lineplotsizex 500\r\nset visoptions.lineplotsizey 400\r\nset visoptions.lineplotselectedeval 0\r\nset visoptions.lineplotdatadescr \"column1 column2 column3\"\r\nset visoptions.lineplotxcoordselector \"\"\r\nset visoptions.lineplotycoordselector \"\"\r\nset visoptions.evaluatefilenames none\r\nset visoptions.evaluatefiledescriptions none\r\n\r\n\r\nset visoptions.clipsolution none\r\nset visoptions.scalfunction none\r\nset visoptions.vecfunction none\r\nset visoptions.evaluate abs\r\nset visoptions.gridsize 20\r\nset visoptions.xoffset 0\r\nset visoptions.yoffset 0\r\nset visoptions.autoscale 1\r\nset visoptions.redrawperiodic 0\r\nset visoptions.logscale 0\r\nset visoptions.mminval 0\r\nset visoptions.mmaxval 1\r\nset visoptions.isolines 0\r\nset visoptions.isosurf 0\r\nset visoptions.subdivisions 1\r\nset visoptions.numiso 10\r\nset visoptions.autoredraw 0\r\nset visoptions.autoredrawtime 2\r\nset visoptions.simulationtime 0\r\nset visoptions.multidimcomponent 0\r\n\r\n# deform by vector function\r\nset visoptions.deformation 0\r\nset visoptions.scaledeform1 1\r\nset visoptions.scaledeform2 1\r\n\r\nset parallel_netgen 0\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nset optfilename [file join $nguserdir ng.opt]\r\nset inifilename [file join $nguserdir ng.ini]\r\nset meshinifilename [file join $nguserdir ngmesh.ini]\r\n\r\nglobal env\r\nif { [llength [array names env NG_OPT]] == 1 } {\r\n    if { [string length $env(NG_OPT)] > 0 } {\r\n\tset optfilename $env(NG_OPT) \r\n    }\r\n}\r\n\r\nif { [file exists $optfilename] == 1 } {\r\n    set datei [open $optfilename r]\r\n    while { [gets $datei line] >= 0 } {\r\n\tset [lindex $line 0] [lindex $line 1]\r\n    }\r\n    close $datei\r\n} {\r\n    puts \"optfile $optfilename does not exist - using default values\"\r\n}\r\n\r\n\r\n\r\n\r\nproc saveoptions { } {\r\n    uplevel 1  {\r\n\tset file $optfilename\r\n\t\r\n\tif {$file != \"\"} {\r\n\t    set datei [open $file w]\r\n\t    puts $datei \"dirname  ${dirname}\"\r\n\t    puts $datei \"loadgeomtypevar  \\\"${loadgeomtypevar}\\\"\"\r\n\t    puts $datei \"exportfiletype  \\\"${exportfiletype}\\\"\"\r\n\t    puts $datei \"meshoptions.fineness  ${meshoptions.fineness}\"\r\n\t    puts $datei \"meshoptions.firststep ${meshoptions.firststep}\"\r\n\t    puts $datei \"meshoptions.laststep  ${meshoptions.laststep}\" \r\n\t    puts $datei \"options.localh  ${options.localh}\"\r\n\t    puts $datei \"options.delaunay  ${options.delaunay}\"\r\n\t    puts $datei \"options.checkoverlap  ${options.checkoverlap}\"\r\n\t    puts $datei \"options.checkchartboundary  ${options.checkchartboundary}\"\r\n\t    puts $datei \"options.startinsurface  ${options.startinsurface}\" \r\n\t    puts $datei \"options.blockfill  ${options.blockfill}\" \r\n\t    puts $datei \"options.debugmode  ${options.debugmode}\" \r\n\t    puts $datei \"options.dooptimize ${options.dooptimize}\" \r\n\t    puts $datei \"options.parthread  ${options.parthread}\"  \r\n\t    puts $datei \"options.elsizeweight  ${options.elsizeweight}\" \r\n\t    puts $datei \"options.secondorder  ${options.secondorder}\" \r\n\t    puts $datei \"options.elementorder  ${options.elementorder}\" \r\n#\t    puts $datei \"options.memory  ${options.memory}\" \r\n\t    puts $datei \"options.quad  ${options.quad}\"\r\n            puts $datei \"options.try_hexes  ${options.try_hexes}\" \r\n\t    puts $datei \"options.inverttets  ${options.inverttets}\" \r\n\t    puts $datei \"options.inverttrigs  ${options.inverttrigs}\" \r\n\t    puts $datei \"options.autozrefine ${options.autozrefine}\" \r\n\t    puts $datei \"options.meshsize  ${options.meshsize}\" \r\n\t    puts $datei \"options.minmeshsize  ${options.minmeshsize}\" \r\n\t    puts $datei \"options.curvaturesafety  ${options.curvaturesafety}\" \r\n\t    puts $datei \"options.segmentsperedge  ${options.segmentsperedge}\" \r\n\t    puts $datei \"options.meshsizefilename  ${options.meshsizefilename}\" \r\n\t    puts $datei \"options.badellimit  ${options.badellimit}\" \r\n\t    puts $datei \"options.optsteps2d  ${options.optsteps2d}\" \r\n\t    puts $datei \"options.optsteps3d  ${options.optsteps3d}\" \r\n\t    puts $datei \"options.opterrpow  ${options.opterrpow}\" \r\n\t    puts $datei \"options.grading  ${options.grading}\" \r\n\t    puts $datei \"options.printmsg  ${options.printmsg}\" \r\n\t    puts $datei \"options.parallel_meshing  ${options.parallel_meshing}\"\r\n\t    puts $datei \"options.nthreads  ${options.nthreads}\"\r\n\t    puts $datei \"geooptions.drawcsg  ${geooptions.drawcsg}\" \r\n\t    puts $datei \"geooptions.detail  ${geooptions.detail}\" \r\n\t    puts $datei \"geooptions.accuracy  ${geooptions.accuracy}\" \r\n\t    puts $datei \"geooptions.facets  ${geooptions.facets}\" \r\n\t    puts $datei \"geooptions.minx  ${geooptions.minx}\" \r\n\t    puts $datei \"geooptions.miny  ${geooptions.miny}\" \r\n\t    puts $datei \"geooptions.minz  ${geooptions.minz}\" \r\n\t    puts $datei \"geooptions.maxx  ${geooptions.maxx}\" \r\n\t    puts $datei \"geooptions.maxy  ${geooptions.maxy}\" \r\n\t    puts $datei \"geooptions.maxz  ${geooptions.maxz}\" \r\n\t    puts $datei \"viewoptions.specpointvlen  ${viewoptions.specpointvlen}\" \r\n\t    puts $datei \"viewoptions.light.amb  ${viewoptions.light.amb}\" \r\n\t    puts $datei \"viewoptions.light.diff ${viewoptions.light.diff}\"\r\n\t    puts $datei \"viewoptions.light.spec ${viewoptions.light.spec}\"\r\n\t    puts $datei \"viewoptions.light.locviewer ${viewoptions.light.locviewer}\"\r\n\t    puts $datei \"viewoptions.mat.shininess  ${viewoptions.mat.shininess}\" \r\n\t    puts $datei \"viewoptions.mat.transp  ${viewoptions.mat.transp}\" \r\n\t    puts $datei \"viewoptions.colormeshsize ${viewoptions.colormeshsize}\"\r\n\t    puts $datei \"viewoptions.whitebackground  ${viewoptions.whitebackground}\" \r\n\t    puts $datei \"viewoptions.drawcolorbar  ${viewoptions.drawcolorbar}\" \r\n\t    puts $datei \"viewoptions.drawcoordinatecross  ${viewoptions.drawcoordinatecross}\" \r\n\t    puts $datei \"viewoptions.drawnetgenlogo  ${viewoptions.drawnetgenlogo}\" \r\n\t    puts $datei \"viewoptions.stereo  ${viewoptions.stereo}\" \r\n\t    puts $datei \"viewoptions.drawfilledtrigs  ${viewoptions.drawfilledtrigs}\" \r\n\t    puts $datei \"viewoptions.drawedges  ${viewoptions.drawedges}\" \r\n\t    puts $datei \"viewoptions.drawbadels  ${viewoptions.drawbadels}\" \r\n\t    puts $datei \"viewoptions.centerpoint  ${viewoptions.centerpoint}\" \r\n\t    puts $datei \"viewoptions.drawelement  ${viewoptions.drawelement}\" \r\n\t    puts $datei \"viewoptions.drawoutline  ${viewoptions.drawoutline}\" \r\n\t    puts $datei \"viewoptions.drawtets  ${viewoptions.drawtets}\"\r\n\t    puts $datei \"viewoptions.drawprisms  ${viewoptions.drawprisms}\"\r\n\t    puts $datei \"viewoptions.drawpyramids  ${viewoptions.drawpyramids}\" \r\n\t    puts $datei \"viewoptions.drawhexes  ${viewoptions.drawhexes}\" \r\n\t    puts $datei \"viewoptions.drawidentified  ${viewoptions.drawidentified}\" \r\n\t    puts $datei \"viewoptions.drawpointnumbers  ${viewoptions.drawpointnumbers}\" \r\n\t    \r\n\t    puts $datei \"viewoptions.drawededges  ${viewoptions.drawededges}\" \r\n\t    puts $datei \"viewoptions.drawedpoints  ${viewoptions.drawedpoints}\" \r\n\t    puts $datei \"viewoptions.drawedpointnrs  ${viewoptions.drawedpointnrs}\" \r\n\t    puts $datei \"viewoptions.drawedtangents  ${viewoptions.drawedtangents}\" \r\n\t    puts $datei \"viewoptions.shrink  ${viewoptions.shrink}\" \r\n\t    \r\n\t    puts $datei \"stloptions.showtrias  ${stloptions.showtrias}\" \r\n\t    puts $datei \"stloptions.showfilledtrias  ${stloptions.showfilledtrias}\" \r\n\t    puts $datei \"stloptions.showedges  ${stloptions.showedges}\" \r\n\t    puts $datei \"stloptions.showmarktrias  ${stloptions.showmarktrias}\" \r\n\t    puts $datei \"stloptions.showactivechart  ${stloptions.showactivechart}\" \r\n\t    puts $datei \"stloptions.yangle  ${stloptions.yangle}\" \r\n\t    puts $datei \"stloptions.contyangle  ${stloptions.contyangle}\" \r\n\t    puts $datei \"stloptions.edgecornerangle  ${stloptions.edgecornerangle}\" \r\n\t    puts $datei \"stloptions.chartangle  ${stloptions.chartangle}\" \r\n\t    puts $datei \"stloptions.outerchartangle  ${stloptions.outerchartangle}\" \r\n\t    puts $datei \"stloptions.usesearchtree  ${stloptions.usesearchtree}\" \r\n\t    puts $datei \"stloptions.chartnumber  ${stloptions.chartnumber}\" \r\n\t    puts $datei \"stloptions.charttrignumber  ${stloptions.charttrignumber}\" \r\n\t    puts $datei \"stloptions.chartnumberoffset  ${stloptions.chartnumberoffset}\" \r\n\t    puts $datei \"stloptions.atlasminh  ${stloptions.atlasminh}\" \r\n\t    puts $datei \"stloptions.resthsurfcurvfac  ${stloptions.resthsurfcurvfac}\" \r\n\t    puts $datei \"stloptions.resthsurfcurvenable  ${stloptions.resthsurfcurvenable}\" \r\n\t    puts $datei \"stloptions.resthatlasfac  ${stloptions.resthatlasfac}\" \r\n\t    puts $datei \"stloptions.resthatlasenable  ${stloptions.resthatlasenable}\" \r\n\t    puts $datei \"stloptions.resthchartdistfac  ${stloptions.resthchartdistfac}\" \r\n\t    puts $datei \"stloptions.resthchartdistenable  ${stloptions.resthchartdistenable}\" \r\n\t    puts $datei \"stloptions.resthlinelengthfac  ${stloptions.resthlinelengthfac}\" \r\n\t    puts $datei \"stloptions.resthlinelengthenable  ${stloptions.resthlinelengthenable}\" \r\n\t\tputs $datei \"stloptions.resthminedgelen ${stloptions.resthminedgelen}\"\r\n\t\tputs $datei \"stloptions.resthminedgelenenable ${stloptions.resthminedgelenenable}\"\r\n\t    puts $datei \"stloptions.resthcloseedgefac  ${stloptions.resthcloseedgefac}\" \r\n\t    puts $datei \"stloptions.resthcloseedgeenable  ${stloptions.resthcloseedgeenable}\" \r\n\t    puts $datei \"stloptions.resthedgeanglefac  ${stloptions.resthedgeanglefac}\" \r\n\t    puts $datei \"stloptions.resthedgeangleenable  ${stloptions.resthedgeangleenable}\" \r\n\t    puts $datei \"stloptions.resthsurfmeshcurvfac  ${stloptions.resthsurfmeshcurvfac}\" \r\n\t    puts $datei \"stloptions.resthsurfmeshcurvenable  ${stloptions.resthsurfmeshcurvenable}\" \r\n\t    puts $datei \"stloptions.recalchopt  ${stloptions.recalchopt}\" \r\n\t    \r\n\t    puts $datei \"visoptions.subdivisions ${visoptions.subdivisions}\"\r\n\t    puts $datei \"visoptions.autoredraw ${visoptions.autoredraw}\"\r\n\t    puts $datei \"visoptions.autoredrawtime ${visoptions.autoredrawtime}\"\r\n\r\n\r\n\t    # trafo options   \r\n\t    # if exist trafooptions then ...\r\n\t    if { [info exists trafooptions.solver] == 1 } {\r\n\t\tputs $datei \"trafooptions.solver ${trafooptions.solver}\" \r\n\t\tputs $datei \"trafooptions.levels ${trafooptions.levels}\" \r\n\t\tputs $datei \"trafooptions.linits ${trafooptions.linits}\" \r\n\t\tputs $datei \"trafooptions.nonlinits ${trafooptions.nonlinits}\" \r\n\t\tputs $datei \"trafooptions.stabcurrent ${trafooptions.stabcurrent}\" \r\n\t\tputs $datei \"trafooptions.checkcond ${trafooptions.checkcond}\" \r\n\t\tputs $datei \"trafooptions.maxdirect ${trafooptions.maxdirect}\" \r\n\t\tputs $datei \"trafooptions.secondorder ${trafooptions.secondorder}\" \r\n\t\tputs $datei \"trafooptions.homogenizedcore ${trafooptions.homogenizedcore}\" \r\n\t\tputs $datei \"trafooptions.ordercore ${trafooptions.ordercore}\" \r\n\t\tputs $datei \"trafooptions.simplecurrents ${trafooptions.simplecurrents}\" \r\n\t\tputs $datei \"trafooptions.assemblecomplexmatrix ${trafooptions.assemblecomplexmatrix}\" \r\n\r\n\t\tputs $datei \"trafooptions.meshcasing  ${trafooptions.meshcasing}\" \r\n\t\tputs $datei \"trafooptions.meshcore    ${trafooptions.meshcore}\" \r\n\t\tputs $datei \"trafooptions.meshclumps  ${trafooptions.meshclumps}\" \r\n\t\tputs $datei \"trafooptions.meshshields ${trafooptions.meshshields}\" \r\n\t\tputs $datei \"trafooptions.meshcoils   ${trafooptions.meshcoils}\" \r\n\t\tputs $datei \"trafooptions.bcmdirectory  ${trafooptions.bcmdirectory}\" \r\n\t\tputs $datei \"trafooptions.lossdensityfile  ${trafooptions.lossdensityfile}\" \r\n\t    }\r\n\r\n\t    if { [info exists smalltrafomodell.tankheight] == 1 } {\r\n\t\tputs $datei \"smalltrafomodell.tankheight ${smalltrafomodell.tankheight}\"\r\n\t\tputs $datei \"smalltrafomodell.tankwidth ${smalltrafomodell.tankwidth}\"\r\n\t\tputs $datei \"smalltrafomodell.tanklength ${smalltrafomodell.tanklength}\"\r\n\t\tputs $datei \"smalltrafomodell.corewidth ${smalltrafomodell.corewidth}\"\r\n\t\tputs $datei \"smalltrafomodell.windowheight ${smalltrafomodell.windowheight}\"\r\n\t\tputs $datei \"smalltrafomodell.limbdistance ${smalltrafomodell.limbdistance}\"\r\n\t\tputs $datei \"smalltrafomodell.xposcore ${smalltrafomodell.xposcore}\"\r\n\t\tputs $datei \"smalltrafomodell.yposcore ${smalltrafomodell.yposcore}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcore ${smalltrafomodell.zposcore}\"\r\n\t\tputs $datei \"smalltrafomodell.leakagefluxguidethickness ${smalltrafomodell.leakagefluxguidethickness}\"\r\n\t\tputs $datei \"smalltrafomodell.leakagefluxguidewidth ${smalltrafomodell.leakagefluxguidewidth}\"\r\n\t\tputs $datei \"smalltrafomodell.leakagefluxguidezposition ${smalltrafomodell.leakagefluxguidezposition}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.1 ${smalltrafomodell.limbcoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.1 ${smalltrafomodell.ricoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.1 ${smalltrafomodell.rocoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.1 ${smalltrafomodell.zposcoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.1 ${smalltrafomodell.heightcoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.1 ${smalltrafomodell.currentcoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.1 ${smalltrafomodell.nturnscoil.1}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.2 ${smalltrafomodell.limbcoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.2 ${smalltrafomodell.ricoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.2 ${smalltrafomodell.rocoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.2 ${smalltrafomodell.zposcoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.2 ${smalltrafomodell.heightcoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.2 ${smalltrafomodell.currentcoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.2 ${smalltrafomodell.nturnscoil.2}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.3 ${smalltrafomodell.limbcoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.3 ${smalltrafomodell.ricoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.3 ${smalltrafomodell.rocoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.3 ${smalltrafomodell.zposcoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.3 ${smalltrafomodell.heightcoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.3 ${smalltrafomodell.currentcoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.3 ${smalltrafomodell.nturnscoil.3}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.4 ${smalltrafomodell.limbcoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.4 ${smalltrafomodell.ricoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.4 ${smalltrafomodell.rocoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.4 ${smalltrafomodell.zposcoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.4 ${smalltrafomodell.heightcoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.4 ${smalltrafomodell.currentcoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.4 ${smalltrafomodell.nturnscoil.4}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.5 ${smalltrafomodell.limbcoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.5 ${smalltrafomodell.ricoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.5 ${smalltrafomodell.rocoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.5 ${smalltrafomodell.zposcoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.5 ${smalltrafomodell.heightcoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.5 ${smalltrafomodell.currentcoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.5 ${smalltrafomodell.nturnscoil.5}\"\r\n\t\tputs $datei \"smalltrafomodell.limbcoil.6 ${smalltrafomodell.limbcoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.ricoil.6 ${smalltrafomodell.ricoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.rocoil.6 ${smalltrafomodell.rocoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.zposcoil.6 ${smalltrafomodell.zposcoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.heightcoil.6 ${smalltrafomodell.heightcoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.currentcoil.6 ${smalltrafomodell.currentcoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.nturnscoil.6 ${smalltrafomodell.nturnscoil.6}\"\r\n\t\tputs $datei \"smalltrafomodell.limbtest.1 ${smalltrafomodell.limbtest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.heighttest.1 ${smalltrafomodell.heighttest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.widthtest.1 ${smalltrafomodell.widthtest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.rtest.1 ${smalltrafomodell.rtest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.zpostest.1 ${smalltrafomodell.zpostest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.edgeradiustest.1 ${smalltrafomodell.edgeradiustest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.finetest.1 ${smalltrafomodell.finetest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.conductivetest.1 ${smalltrafomodell.conductivetest.1}\"\r\n\t\tputs $datei \"smalltrafomodell.limbtest.2 ${smalltrafomodell.limbtest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.heighttest.2 ${smalltrafomodell.heighttest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.widthtest.2 ${smalltrafomodell.widthtest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.rtest.2 ${smalltrafomodell.rtest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.zpostest.2 ${smalltrafomodell.zpostest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.edgeradiustest.2 ${smalltrafomodell.edgeradiustest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.finetest.2 ${smalltrafomodell.finetest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.conductivetest.2 ${smalltrafomodell.conductivetest.2}\"\r\n\t\tputs $datei \"smalltrafomodell.limbtest.3 ${smalltrafomodell.limbtest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.heighttest.3 ${smalltrafomodell.heighttest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.widthtest.3 ${smalltrafomodell.widthtest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.rtest.3 ${smalltrafomodell.rtest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.zpostest.3 ${smalltrafomodell.zpostest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.edgeradiustest.3 ${smalltrafomodell.edgeradiustest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.finetest.3 ${smalltrafomodell.finetest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.conductivetest.3 ${smalltrafomodell.conductivetest.3}\"\r\n\t\tputs $datei \"smalltrafomodell.limbtest.4 ${smalltrafomodell.limbtest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.heighttest.4 ${smalltrafomodell.heighttest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.widthtest.4 ${smalltrafomodell.widthtest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.rtest.4 ${smalltrafomodell.rtest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.zpostest.4 ${smalltrafomodell.zpostest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.edgeradiustest.4 ${smalltrafomodell.edgeradiustest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.finetest.4 ${smalltrafomodell.finetest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.conductivetest.4 ${smalltrafomodell.conductivetest.4}\"\r\n\t\tputs $datei \"smalltrafomodell.nperitest ${smalltrafomodell.nperitest}\"\r\n\t\tputs $datei \"smalltrafomodell.filename ${smalltrafomodell.filename}\"\r\n\t\tputs $datei \"smalltrafomodell.murlfguide ${smalltrafomodell.murlfguide}\"\r\n\t\tputs $datei \"smalltrafomodell.murtestwire ${smalltrafomodell.murtestwire}\"\r\n\t\tputs $datei \"smalltrafomodell.murcore ${smalltrafomodell.murcore}\"\r\n\t\tputs $datei \"smalltrafomodell.kappalfguide ${smalltrafomodell.kappalfguide}\"\r\n\t\tputs $datei \"smalltrafomodell.kappatestwire ${smalltrafomodell.kappatestwire}\"\r\n\t\tputs $datei \"smalltrafomodell.kappacore ${smalltrafomodell.kappacore}\"\r\n\t    }\r\n\t    \r\n\t    \r\n\t    close $datei\r\n\t}\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n# the ini file is saved on demand :\r\nproc saveinifile { } {\r\n    global inifilename\r\n    if {[catch { set datei [open $inifilename w] } result ]} {\r\n\tputs \"cannot write file $inifilename\"\r\n    } {\r\n\tfor { set i [.ngmenu.file.recent index last] } { $i >= 0 } { incr i -1 } {\r\n\t    puts $datei \"recentfile \\\"[.ngmenu.file.recent entrycget $i -label]\\\"\"\r\n\t}\r\n\tclose $datei\r\n    }    \r\n}\r\n\r\n\r\nproc savemeshinifile { } {\r\n    global meshinifilename \r\n    if {[catch { set datei [open $meshinifilename w] } result ]} {\r\n\tputs \"cannot write file $meshinifilename\"\r\n    } {\r\n\tfor { set i [.ngmenu.file.recentmesh index last] } { $i >= 1 } { incr i -1 } {\r\n\t    puts $datei \"recentfile \\\"[.ngmenu.file.recentmesh entrycget $i -label]\\\"\"\r\n\t}\r\n\tclose $datei\r\n    }    \r\n}\r\n\r\n\r\n\r\nproc loadinifile { } { \r\n    global inifilename\r\n    if { [file exists $inifilename] == 1 } {\r\n\tset datei [open $inifilename r]\r\n\twhile { [gets $datei line] >= 0 } {\r\n\t    if {[lindex $line 0] == \"recentfile\"} {\r\n\t\t    set filename [lindex $line 1]\r\n\t\t    if { [file exists $filename] == 1 } {\r\n\t\t        AddRecentFile $filename\r\n\t\t    }\t\r\n\t    }\r\n\t}\r\n\tclose $datei\r\n    }\r\n}\r\n\r\n\r\nproc loadmeshinifile { } {\r\n    global meshinifilename\r\n    if { [file exists $meshinifilename] == 1 } {\r\n\tset datei [open $meshinifilename r]\r\n\twhile { [gets $datei line] >= 0 } {\r\n\t    if {[lindex $line 0] == \"recentfile\"} {\r\n\t\tset filename [lindex $line 1]\r\n\t\tif { [file exists $filename] == 1 } {\r\n\t\t    AddRecentMeshFile $filename\r\n\t\t}\t\r\n\t    }\r\n\t}\r\n\tclose $datei\r\n    }\r\n }\r\n\r\n\r\n\r\n\r\n\r\nset cmdindex {}\r\nset hlpindex {}\r\nset secindex {}\r\n"
  },
  {
    "path": "nglib/CMakeLists.txt",
    "content": "target_sources(nglib PRIVATE nglib.cpp)\n\nif(USE_OCC)\n    target_sources(nglib PRIVATE nglib_occ.cpp)\n    install(FILES nglib_occ.h DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)\nendif(USE_OCC)\n\ntarget_link_libraries(nglib PRIVATE ${ZLIB_LIBRARIES})\ntarget_link_libraries( nglib PUBLIC ngcore PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} occ_libs netgen_cgns )\n\ninstall(TARGETS nglib netgen_cgns ${NG_INSTALL_DIR})\ninstall(FILES nglib.h DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)\n"
  },
  {
    "path": "nglib/cube.surf",
    "content": "8\n         0         0         0\n         1         0         0\n         1         1         1\n         1         0         1\n         0         1         1\n         0         0         1\n         0         1         0\n         1         1         0\n12\n       2       1       7\n       8       2       7\n       6       1       2\n       4       6       2\n       4       3       5\n       5       6       4\n       8       3       4\n       8       4       2\n       5       3       8\n       7       5       8\n       1       6       5\n       7       1       5\n"
  },
  {
    "path": "nglib/hinge.stl",
    "content": "solid\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 5.300545e-016\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 1.440206e-016\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015\n    outer loop\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015\n    outer loop\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016\n    outer loop\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015\n    outer loop\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.038636e-017\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316081e-016\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.855272e-016\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 3.307707e-016\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -6.826070e-016\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -4.180408e-016\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.800343e-017\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -3.659639e-016\n    outer loop\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 5.956618e-016\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 8.614567e-016\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -3.257609e-016\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 3.166431e-016\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -1.411631e-016\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -4.198697e-016\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 3.691957e-016\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 3.330001e-016\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.855272e-016\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 2.090204e-016\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 9.048915e-016\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 1.030095e-015\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 1.954566e-016\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 2.606088e-016\n    outer loop\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 5.710544e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 3.981523e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 1.216174e-015\n    outer loop\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 5.284567e-016\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 1.013479e-016\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 2.497501e-016\n    outer loop\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 2.461305e-016\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 2.678479e-016\n    outer loop\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 0.000000e+000\n    outer loop\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 1.520218e-015\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 4.850219e-016\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 -3.438588e-017\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 1.414640e-015\n    outer loop\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016\n    outer loop\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016\n    outer loop\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 3.519318e-017\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -5.710544e-016\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 1.706518e-016\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316081e-016\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -2.855272e-016\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -3.413035e-016\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -2.090204e-016\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -7.038636e-017\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 -3.318735e-016\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.090204e-016\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 1.324456e-016\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 5.710544e-016\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 -3.413035e-016\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -1.045102e-016\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -2.063153e-016\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 6.587610e-016\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 2.895653e-016\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 3.402392e-016\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -1.845979e-016\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 7.058154e-017\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -7.058154e-017\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -2.099348e-016\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 -1.303044e-016\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.895653e-016\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316522e-016\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -3.909131e-016\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 1.049674e-016\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 9.048915e-016\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 1.134605e-015\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 5.863697e-016\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 9.266089e-016\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 8.542176e-016\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 8.612394e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 8.542176e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 9.193698e-016\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 9.051759e-016\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 1.031576e-015\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 5.863697e-016\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 9.266089e-016\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 1.143783e-015\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 6.298045e-016\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 1.049674e-015\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 5.300545e-016\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016\n    outer loop\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015\n    outer loop\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016\n    outer loop\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.038636e-017\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -3.900374e-016\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -1.829819e-016\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 6.622278e-017\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -6.583952e-030\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 2.149666e-016\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -2.559776e-016\n    outer loop\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -1.567653e-016\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -1.759659e-017\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 7.038636e-017\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -2.855272e-016\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -1.953121e-016\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -9.916256e-017\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 3.659639e-016\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 3.909131e-016\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -9.410872e-017\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -1.954566e-016\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.099348e-016\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 1.809783e-017\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -5.429349e-017\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -1.592609e-016\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 2.750870e-016\n    outer loop\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 9.916256e-017\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 1.447826e-016\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 -1.592609e-016\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -3.691957e-016\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 2.099348e-016\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 7.040056e-016\n    outer loop\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 6.400577e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 9.338481e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 5.942889e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 4.271088e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 6.298045e-016\n    outer loop\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 1.049674e-015\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 5.300545e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 1.013479e-016\n    outer loop\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 3.547175e-016\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 7.601089e-016\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 2.678479e-016\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 8.542176e-016\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 8.614567e-016\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 8.542176e-016\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.639778e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -2.425509e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 2.425509e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.635355e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.101317e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -5.024296e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.870609e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -4.973720e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.930284e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.872123e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -5.049222e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.815345e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -4.851017e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -5.189602e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.739404e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -5.015272e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -4.479280e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -5.101317e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.688432e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.971507e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.936122e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.670740e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.776893e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 4.891892e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.741508e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.759201e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 4.546894e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.639778e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -2.425509e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 2.425509e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.635355e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.101317e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -5.024296e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.870609e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -4.973720e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.930284e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.872123e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -5.049222e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.815345e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -4.851017e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -5.189602e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.739404e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -5.015272e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -4.479280e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -5.101317e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.688432e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.971507e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.936122e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.670740e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.776893e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 4.891892e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.741508e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.759201e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 4.546894e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.966323e-001 8.200039e-002\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -4.306895e-017 -9.698266e-001 2.437957e-001\n    outer loop\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal -4.425936e-017 -9.966323e-001 8.200039e-002\n    outer loop\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal 1.692405e-017 -9.698266e-001 2.437957e-001\n    outer loop\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal -3.581497e-018 -9.169362e-001 3.990338e-001\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.169362e-001 3.990338e-001\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.313813e-017 -8.393837e-001 5.435393e-001\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.392549e-001 6.734257e-001\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -6.192429e-001 7.851995e-001\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -6.192429e-001 7.851995e-001\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal 2.820675e-018 -7.392549e-001 6.734257e-001\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.393837e-001 5.435393e-001\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.432567e-016 1.253334e-017 -1.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.174024e-016 3.145787e-017 -1.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 9.887861e-017 4.610785e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.409715e-017 5.888546e-017 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.118001e-017 7.118001e-017 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.888546e-017 8.409715e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 4.610785e-017 9.887861e-017 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.145787e-017 1.174024e-016 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.253334e-017 1.432567e-016 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.618835e-017 1.850337e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.259975e-017 2.709460e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.571783e-016 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.383491e-031 1.571783e-016 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.259975e-017 2.709460e-016 -1.000000e+000\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.618835e-017 1.850337e-016 -1.000000e+000\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.253334e-017 1.432567e-016 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.145787e-017 1.174024e-016 -1.000000e+000\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -4.610785e-017 9.887861e-017 -1.000000e+000\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.888546e-017 8.409715e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.118001e-017 7.118001e-017 -1.000000e+000\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -8.409715e-017 5.888546e-017 -1.000000e+000\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.887861e-017 4.610785e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.174024e-016 3.145787e-017 -1.000000e+000\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.432567e-016 1.253334e-017 -1.000000e+000\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.015055e-016 3.552714e-017 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.719385e-017 7.719385e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -8.446175e-017 1.206239e-016 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.719385e-017 7.719385e-017 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -5.921189e-017 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.446175e-017 1.206239e-016 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 5.921189e-017 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.015055e-016 3.552714e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 1.776357e-016 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.628500e-015 1.840496e-015\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.086809e-015 9.730950e-016\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.863973e-015 4.994500e-016\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.776357e-015 1.554111e-016\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -7.105427e-016 4.029688e-015\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.318329e-017 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 7.232290e-018 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -2.172279e-030 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 3.884310e-017 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 8.428841e-017 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal -2.322295e-017 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 4.159406e-017 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 5.816399e-017 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 3.884310e-017 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 7.145594e-017 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.910757e-017 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -8.492254e-018 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -4.344559e-030 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.153573e-017 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -6.793803e-017 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 2.866136e-017 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -8.492254e-018 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -5.944578e-017 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -3.821514e-017 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -1.910757e-017 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal -9.023020e-017 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\nendsolid\n"
  },
  {
    "path": "nglib/netgen.py",
    "content": "import sys\ntry:\n    # Linux\n    from libmesh import meshing\n    from libgeom2d import geom2d\n    from libcsg import csg\nexcept:\n    # Windows\n    from nglib import *\n\nsys.modules['netgen.meshing'] = meshing\nsys.modules['netgen.geom2d'] = geom2d\nsys.modules['netgen.csg'] = csg\ndel sys\n\n"
  },
  {
    "path": "nglib/ng_occ.cpp",
    "content": "#include <iostream>\r\n#include <climits>\r\n\r\n#include \"TopTools_IndexedMapOfShape.hxx\"\r\n#include \"TopoDS.hxx\"\r\n#include \"TopoDS_Face.hxx\"\r\n#include \"TopoDS_Shape.hxx\"\r\n#include \"GProp_GProps.hxx\"\r\n#include \"BRepGProp.hxx\"\r\n\r\nusing namespace std;\r\n\r\nnamespace nglib {\r\n#include <nglib.h>\r\n}\r\n\r\nint main (int argc, char ** argv)\r\n{\r\n   using namespace nglib;\r\n   \r\n   cout << \"Netgen NgLib - OpenCascade Test Case\" << endl;\r\n   \r\n   if (argc != 2)\r\n   {\r\n      cerr << \"use: ng_occ <src_step>\" << endl;\r\n      return 1;\r\n   }\r\n   \r\n   // Define pointer to OCC Geometry\r\n   Ng_OCC_Geometry *occ_geom;\r\n   \r\n   Ng_Mesh *occ_mesh;\r\n   \r\n   Ng_Meshing_Parameters mp;\r\n   \r\n   TopTools_IndexedMapOfShape FMap;\r\n   \r\n   Ng_OCC_TopTools_IndexedMapOfShape *occ_fmap = (Ng_OCC_TopTools_IndexedMapOfShape*)&FMap;\r\n   \r\n   // Result of Netgen Operations\r\n   Ng_Result ng_res;\r\n\r\n   // Initialise the Netgen Core library\r\n   Ng_Init();\r\n\r\n   // Read in the OCC File\r\n   occ_geom = Ng_OCC_Load_STEP(argv[1]);\r\n   if(!occ_geom)\r\n   {\r\n      cout << \"Error reading in STEP File: \" << argv[1] << endl;\r\n\t  return 1;\r\n   }\r\n   cout << \"Successfully loaded STEP File: \" << argv[1] << endl;\r\n\r\n   occ_mesh = Ng_NewMesh();\r\n   \r\n   ng_res = Ng_OCC_GetFMap(occ_geom,occ_fmap);\r\n\r\n   cout << \"ng_res = \" << ng_res << endl;\r\n\t  \r\n   if(!FMap.Extent())\r\n   {\r\n      cout << \"Error retrieving Face map....\" << endl;\r\n\t  return 1;\r\n   }\r\n\r\n   cout << \"Successfully extracted the Face Map....:\" << FMap.Extent() << endl;\r\n   \r\n   for(int i = 1; i <= FMap.Extent(); i++)\r\n   {\r\n      TopoDS_Face OCCface;\r\n\t  OCCface = TopoDS::Face(FMap.FindKey(i));\r\n\t  \r\n\t  GProp_GProps faceProps;\r\n\t  BRepGProp::SurfaceProperties(OCCface,faceProps);\r\n\t  \r\n      cout << \"Index: \" << i \r\n\t       << \" :: Area: \" << faceProps.Mass() \r\n\t\t   << \" :: Hash: \" << OCCface.HashCode(1e+6) \r\n\t\t   << endl;\r\n   }\t \r\n   \r\n   mp.uselocalh = 1;\r\n   mp.elementsperedge = 2.0;\r\n   mp.elementspercurve = 2.0;\r\n   mp.maxh = 10.0;\r\n   mp.grading = 0.2;   \r\n   mp.closeedgeenable = 0;\r\n   mp.closeedgefact = 1.0;\r\n   mp.optsurfmeshenable = 1;\r\n   \r\n   \r\n   cout << \"Setting Local Mesh size.....\" << endl;\r\n   cout << \"OCC Mesh Pointer before call = \" << occ_mesh << endl;\r\n   Ng_OCC_SetLocalMeshSize(occ_geom, occ_mesh, &mp);\r\n   cout << \"Local Mesh size successfully set.....\" << endl;\r\n      cout << \"OCC Mesh Pointer after call = \" << occ_mesh << endl;\r\n   \r\n   cout << \"Creating Edge Mesh.....\" << endl;\r\n   ng_res = Ng_OCC_GenerateEdgeMesh(occ_geom, occ_mesh, &mp);\r\n   if(ng_res != NG_OK)\r\n   {\r\n      Ng_DeleteMesh(occ_mesh);\r\n\t  cout << \"Error creating Edge Mesh.... Aborting!!\" << endl;\r\n\t  return 1;\r\n   }\r\n   else\r\n   {\r\n      cout << \"Edge Mesh successfully created.....\" << endl;\r\n\t  cout << \"Number of points = \" << Ng_GetNP(occ_mesh) << endl;\r\n   }\r\n\r\n   cout << \"Creating Surface Mesh.....\" << endl;\r\n \r\n   ng_res = Ng_OCC_GenerateSurfaceMesh(occ_geom, occ_mesh, &mp);\r\n   if(ng_res != NG_OK)\r\n   {\r\n      Ng_DeleteMesh(occ_mesh);\r\n\t  cout << \"Error creating Surface Mesh..... Aborting!!\" << endl;\r\n\t  return 1;\r\n   }\r\n   else\r\n   {\r\n      cout << \"Surface Mesh successfully created.....\" << endl;\r\n\t  cout << \"Number of points = \" << Ng_GetNP(occ_mesh) << endl;\r\n\t  cout << \"Number of surface elements = \" << Ng_GetNSE(occ_mesh) << endl;\r\n   }\r\n\r\n   cout << \"Creating Volume Mesh.....\" << endl;\r\n   \r\n   ng_res = Ng_GenerateVolumeMesh(occ_mesh, &mp);\r\n   \r\n   cout << \"Volume Mesh successfully created.....\" << endl;\r\n   cout << \"Number of points = \" << Ng_GetNP(occ_mesh) << endl;\r\n   cout << \"Number of volume elements = \" << Ng_GetNE(occ_mesh) << endl;\r\n   \r\n   cout << \"Saving Mesh as VOL file.....\" << endl;\r\n   Ng_SaveMesh(occ_mesh,\"test_occ.vol\");\r\n      \r\n   return 0;\r\n}\r\n   \r\n"
  },
  {
    "path": "nglib/ng_stl.cpp",
    "content": "/*!\n   \\file ng_stl.cpp\n   \\author Philippose Rajan\n   \\date 14 Feb 2009 (Created)\n\n   This sample utility demonstrates the use of the Netgen \n   nglib library for reading, and meshing an STL geometry. \n\n   The Program takes as input the name of an STL file \n   saved in the STL ASCII Format, and generates a 3D Volume \n   mesh which is saved into the file \"test.vol\".\n\n   test.vol can be viewed using the usual Netgen Mesher GUI\n*/\n\n\n#include <iostream>\n#include <fstream>\n\nusing namespace std;\n\nnamespace nglib {\n#include <nglib.h>\n}\n\nint main (int argc, char ** argv)\n{\n   using namespace nglib;\n\n   cout << \"Netgen (nglib) STL Testing\" << endl;\n\n   if (argc < 2)\n   {\n      cerr << \"use: ng_stl STL_filename\" << endl;\n      return 1;\n   }\n\n   // Define pointer to a new Netgen Mesh\n   Ng_Mesh *mesh;\n   \n   // Define pointer to STL Geometry\n   Ng_STL_Geometry *stl_geom;\n\n   // Result of Netgen Operations\n   Ng_Result ng_res;\n   \n   // Initialise the Netgen Core library\n   Ng_Init();\n\n   // Actually create the mesh structure\n   mesh = Ng_NewMesh();\n\n   int np, ne;\n\n   // Read in the STL File\n   stl_geom = Ng_STL_LoadGeometry(argv[1]);\n   if(!stl_geom)\n   {\n      cout << \"Error reading in STL File: \" << argv[1] << endl;\n\t  return 1;\n   }\n   cout << \"Successfully loaded STL File: \" << argv[1] << endl;\n\n\n   // Set the Meshing Parameters to be used\n   Ng_Meshing_Parameters mp;\n   mp.maxh = 1.0e+6;\n   mp.fineness = 0.4;\n   mp.second_order = 0;\n\n   cout << \"Initialise the STL Geometry structure....\" << endl;\n   ng_res = Ng_STL_InitSTLGeometry(stl_geom);\n   if(ng_res != NG_OK)\n   {\n      cout << \"Error Initialising the STL Geometry....Aborting!!\" << endl;\n\t   return 1;\n   }\n\n   cout << \"Start Edge Meshing....\" << endl;\n   ng_res = Ng_STL_MakeEdges(stl_geom, mesh, &mp);\n   if(ng_res != NG_OK)\n   {\n      cout << \"Error in Edge Meshing....Aborting!!\" << endl;\n\t   return 1;\n   }\n\n   cout << \"Start Surface Meshing....\" << endl;\n   ng_res = Ng_STL_GenerateSurfaceMesh(stl_geom, mesh, &mp);\n   if(ng_res != NG_OK)\n   {\n      cout << \"Error in Surface Meshing....Aborting!!\" << endl;\n\t   return 1;\n   }\n   \n   cout << \"Start Volume Meshing....\" << endl;\n   ng_res = Ng_GenerateVolumeMesh (mesh, &mp);\n   if(ng_res != NG_OK)\n   {\n      cout << \"Error in Volume Meshing....Aborting!!\" << endl;\n\t  return 1;\n   }\n   \n   cout << \"Meshing successfully completed....!!\" << endl;\n\n   // volume mesh output\n   np = Ng_GetNP(mesh);\n   cout << \"Points: \" << np << endl;\n\n   ne = Ng_GetNE(mesh);\n   cout << \"Elements: \" << ne << endl;\n\n   cout << \"Saving Mesh in VOL Format....\" << endl;\n   Ng_SaveMesh(mesh,\"test.vol\");\n\n\n   // refinement without geometry adaption:\n   // Ng_Uniform_Refinement (mesh);\n\n   // refinement with geometry adaption:   \n   Ng_STL_Uniform_Refinement (stl_geom, mesh);\n\n   cout << \"elements after refinement: \" << Ng_GetNE(mesh) << endl;\n   cout << \"points   after refinement: \" << Ng_GetNP(mesh) << endl;\n\n   Ng_SaveMesh(mesh,\"test_ref.vol\");\n\n   return 0;\n}\n"
  },
  {
    "path": "nglib/ng_vol.cpp",
    "content": "#include <iostream>\n#include <fstream>\n\nusing namespace std;\n\nnamespace nglib {\n#include <nglib.h>\n}\n\nint main (int argc, char ** argv)\n{\n  using namespace nglib;\n\n  cout << \"Netgen Testing\" << endl;\n\n  if (argc < 2)\n    {\n      cerr << \"use: ng_vol filename\" << endl;\n      return 1;\n    }\n\n\n\n  Ng_Mesh * mesh;\n\n  Ng_Init();\n\n  // creates mesh structure\n  mesh = Ng_NewMesh ();\n\n\n\n\n\n  int i, np, nse, ne;\n  double point[3];\n  int trig[3], tet[4];\n\n\n  // reads surface mesh from file\n  ifstream in(argv[1]);\n\n  in >> np;\n  cout << \"Reading \" << np  << \" points...\"; cout.flush();\n  for (i = 1; i <= np; i++)\n    {\n      in >> point[0] >> point[1] >> point[2];\n      Ng_AddPoint (mesh, point);\n    }\n  cout << \"done\" << endl;\n\n  in >> nse;\n  cout << \"Reading \" << nse  << \" faces...\"; cout.flush();\n  for (i = 1; i <= nse; i++)\n    {\n      in >> trig[0] >> trig[1] >> trig[2];\n      Ng_AddSurfaceElement (mesh, NG_TRIG, trig);\n    }\n  cout << \"done\" << endl;\n\n\n  // generate volume mesh\n  Ng_Meshing_Parameters mp;\n  mp.maxh = 1e6;\n  mp.fineness = 1;\n  mp.second_order = 0;\n\n  cout << \"start meshing\" << endl;\n  Ng_GenerateVolumeMesh (mesh, &mp);\n  cout << \"meshing done\" << endl;\n\n  // volume mesh output\n  np = Ng_GetNP(mesh);\n  cout << \"Points: \" << np << endl;\n\n  for (i = 1; i <= np; i++)\n    {\n      Ng_GetPoint (mesh, i, point);\n      cout << i << \": \" << point[0] << \" \" << point[1] << \" \" << point[2] << endl;\n    }\n\n  ne = Ng_GetNE(mesh);\n  cout << \"Elements: \" << ne << endl;\n  for (i = 1; i <= ne; i++)\n    {\n      Ng_GetVolumeElement (mesh, i, tet);\n      cout << i << \": \" << tet[0] << \" \" << tet[1] \n\t   << \" \" << tet[2] << \" \" << tet[3] << endl;\n    }\n\n  Ng_SaveMesh(mesh,\"test.vol\");\n\n\n  return 0;\n}\n"
  },
  {
    "path": "nglib/nglib.cpp",
    "content": "/**************************************************************************/\r\n/* File:   nglib.cpp                                                      */\r\n/* Author: Joachim Schoeberl                                              */\r\n/* Date:   7. May. 2000                                                   */\r\n/**************************************************************************/\r\n\r\n/*\r\n  \r\n  Interface to the netgen meshing kernel\r\n  \r\n*/\r\n#include <mystdlib.h>\r\n#include <myadt.hpp>\r\n\r\n#include <linalg.hpp>\r\n#include <csg.hpp>\r\n#include <stlgeom.hpp>\r\n#include <geometry2d.hpp>\r\n#include <meshing.hpp>\r\n#include <../meshing/soldata.hpp>\r\n\r\n#include <nginterface.h>\r\n\r\n\r\nnamespace netgen {\r\n   extern void MeshFromSpline2D (SplineGeometry2d & geometry,\r\n                                 shared_ptr<Mesh> & mesh, \r\n                                 MeshingParameters & mp);\r\n   extern MeshingParameters mparam;\r\n   DLL_HEADER extern STLParameters stlparam;\r\n}\r\n\r\n\r\n\r\n/*\r\nnamespace netgen\r\n{\r\n  int id = 0, ntasks = 1;\r\n}\r\n*/\r\n\r\n\r\n/*\r\n// should not be needed (occ currently requires it)\r\nnamespace netgen {\r\n#include \"../libsrc/visualization/vispar.hpp\"\r\n  VisualizationParameters vispar;\r\n  VisualizationParameters :: VisualizationParameters() { ; }\r\n}\r\n*/\r\n\r\n\r\nnamespace nglib {\r\n#include \"nglib.h\"\r\n}\r\n\r\nusing namespace netgen;\r\n\r\n// constants and types:\r\n\r\nnamespace nglib\r\n{\r\n  inline void NOOP_Deleter(void *) { ; }\r\n\r\n  \r\n   // initialize, deconstruct Netgen library:\r\n   NGLIB_API void Ng_Init ()\r\n   {\r\n      mycout = &cout;\r\n      myerr = &cerr;\r\n      // netgen::testout->SetOutStream (new ofstream (\"test.out\"));\r\n      // testout = new ofstream (\"test.out\");\r\n   }\r\n\r\n\r\n\r\n\r\n   // Clean-up functions before ending usage of nglib\r\n   NGLIB_API void Ng_Exit ()\r\n   {\r\n      ;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Create a new netgen mesh object\r\n   NGLIB_API Ng_Mesh * Ng_NewMesh ()\r\n   {\r\n      Mesh * mesh = new Mesh;  \r\n      mesh->AddFaceDescriptor (FaceDescriptor (1, 1, 0, 1));\r\n      return (Ng_Mesh*)(void*)mesh;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Delete an existing netgen mesh object\r\n   NGLIB_API void Ng_DeleteMesh (Ng_Mesh * mesh)\r\n   {\r\n      if(mesh != NULL)\r\n      {\r\n         // Delete the Mesh structures\r\n         ((Mesh*)mesh)->DeleteMesh();\r\n\r\n         // Now delete the Mesh class itself\r\n         delete (Mesh*)mesh;\r\n\r\n         // Set the Ng_Mesh pointer to NULL\r\n         mesh = NULL;\r\n      }\r\n   }\r\n\r\n\r\n\r\n\r\n   // Save a netgen mesh in the native VOL format \r\n   NGLIB_API void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename)\r\n   {\r\n      ((Mesh*)mesh)->Save(filename);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Load a netgen native VOL mesh from a given file\r\n   NGLIB_API Ng_Mesh * Ng_LoadMesh(const char* filename)\r\n   {\r\n      Mesh * mesh = new Mesh;\r\n      mesh->Load(filename);\r\n      return ( (Ng_Mesh*)mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   // Merge another mesh file into the currently loaded one\r\n   NGLIB_API Ng_Result Ng_MergeMesh( Ng_Mesh* mesh, const char* filename)\r\n   {\r\n      Ng_Result status = NG_OK;\r\n\r\n      ifstream infile(filename);\r\n      Mesh * m = (Mesh*)mesh;\r\n\r\n      if(!infile.good())\r\n      {\r\n         status = NG_FILE_NOT_FOUND;\r\n      }\r\n\r\n      if(!m)\r\n      {\r\n         status = NG_ERROR;\r\n      }\r\n\r\n      if(status == NG_OK)\r\n      {\r\n         const int num_pts = m->GetNP();\r\n         const int face_offset = m->GetNFD();\r\n\r\n         m->Merge(infile, face_offset);\r\n\r\n         if(m->GetNP() > num_pts)\r\n         {\r\n            status = NG_OK;\r\n         }\r\n         else\r\n         {\r\n            status = NG_ERROR;\r\n         }\r\n      }\r\n\r\n      return status;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Merge another mesh file into the currently loaded one\r\n   NGLIB_API Ng_Result Ng_MergeMesh( Ng_Mesh* mesh1, Ng_Mesh* mesh2)\r\n   {\r\n      return NG_ERROR;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Manually add a point to an existing mesh object\r\n   NGLIB_API void Ng_AddPoint (Ng_Mesh * mesh, double * x)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      m->AddPoint (Point3d (x[0], x[1], x[2]));\r\n   }\r\n\r\n\r\n\r\n\r\n   // Manually add a surface element of a given type to an existing mesh object\r\n   NGLIB_API void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et,\r\n                                         int * pi)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      Element2d el (3);\r\n      el.SetIndex (1);\r\n      el.PNum(1) = pi[0];\r\n      el.PNum(2) = pi[1];\r\n      el.PNum(3) = pi[2];\r\n      m->AddSurfaceElement (el);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Manually add a volume element of a given type to an existing mesh object\r\n   NGLIB_API void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et,\r\n                                        int * pi)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      Element el (4);\r\n      el.SetIndex (1);\r\n      el.PNum(1) = pi[0];\r\n      el.PNum(2) = pi[1];\r\n      el.PNum(3) = pi[2];\r\n      el.PNum(4) = pi[3];\r\n      m->AddVolumeElement (el);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Obtain the number of points in the mesh\r\n   NGLIB_API int Ng_GetNP (Ng_Mesh * mesh)\r\n   {\r\n      return ((Mesh*)mesh) -> GetNP();\r\n   }\r\n\r\n\r\n\r\n\r\n   // Obtain the number of surface elements in the mesh\r\n   NGLIB_API int Ng_GetNSE (Ng_Mesh * mesh)\r\n   {\r\n      return ((Mesh*)mesh) -> GetNSE();\r\n   }\r\n\r\n\r\n\r\n\r\n   // Obtain the number of volume elements in the mesh\r\n   NGLIB_API int Ng_GetNE (Ng_Mesh * mesh)\r\n   {\r\n      return ((Mesh*)mesh) -> GetNE();\r\n   }\r\n\r\n\r\n\r\n\r\n   //  Return point coordinates of a given point index in the mesh\r\n   NGLIB_API void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x)\r\n   {\r\n      const Point3d & p = ((Mesh*)mesh)->Point(num);\r\n      x[0] = p.X();\r\n      x[1] = p.Y();\r\n      x[2] = p.Z();\r\n   }\r\n\r\n\r\n\r\n\r\n   // Return the surface element at a given index \"pi\"\r\n   NGLIB_API Ng_Surface_Element_Type \r\n      Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi)\r\n   {\r\n     const Element2d & el = ((Mesh*)mesh)->SurfaceElement(SurfaceElementIndex(num-1));\r\n      for (int i = 1; i <= el.GetNP(); i++)\r\n         pi[i-1] = el.PNum(i);\r\n      Ng_Surface_Element_Type et;\r\n      switch (el.GetNP())\r\n      {\r\n      case 3: et = NG_TRIG; break;\r\n      case 4: et = NG_QUAD; break;\r\n      case 6: \r\n         switch (el.GetNV())\r\n         {\r\n         case 3: et = NG_TRIG6; break;\r\n         case 4: et = NG_QUAD6; break;\r\n         default:\r\n            et = NG_TRIG6; break;\r\n         }\r\n         break;\r\n      case 8: et = NG_QUAD8; break;\r\n      default:\r\n         et = NG_TRIG; break; // for the compiler\r\n      }\r\n      return et;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Return the volume element at a given index \"pi\"\r\n   NGLIB_API Ng_Volume_Element_Type\r\n      Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi)\r\n   {\r\n     const Element & el = ((Mesh*)mesh)->VolumeElement(ElementIndex(num-1));\r\n      for (int i = 1; i <= el.GetNP(); i++)\r\n         pi[i-1] = el.PNum(i);\r\n      Ng_Volume_Element_Type et;\r\n      switch (el.GetNP())\r\n      {\r\n      case 4: et = NG_TET; break;\r\n      case 5: et = NG_PYRAMID; break;\r\n      case 6: et = NG_PRISM; break;\r\n      case 10: et = NG_TET10; break;\r\n      default:\r\n         et = NG_TET; break; // for the compiler\r\n      }\r\n      return et;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Set a global limit on the maximum mesh size allowed\r\n   NGLIB_API void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h)\r\n   {\r\n      ((Mesh*)mesh) -> SetGlobalH (h);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Set a local limit on the maximum mesh size allowed around the given point\r\n   NGLIB_API void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h)\r\n   {\r\n      ((Mesh*)mesh) -> RestrictLocalH (Point3d (p[0], p[1], p[2]), h);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Set a local limit on the maximum mesh size allowed within a given box region\r\n   NGLIB_API void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h)\r\n   {\r\n      for (double x = pmin[0]; x < pmax[0]; x += h)\r\n         for (double y = pmin[1]; y < pmax[1]; y += h)\r\n            for (double z = pmin[2]; z < pmax[2]; z += h)\r\n               ((Mesh*)mesh) -> RestrictLocalH (Point3d (x, y, z), h);\r\n   }\r\n\r\n\r\n\r\n\r\n   // Generates volume mesh from an existing surface mesh\r\n   NGLIB_API Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n\r\n      // Philippose - 30/08/2009\r\n      // Do not locally re-define \"mparam\" here... \"mparam\" is a global \r\n      // object \r\n      //MeshingParameters mparam;\r\n      mp->Transfer_Parameters();\r\n\r\n      m->CalcLocalH(mparam.grading);\r\n\r\n      MeshVolume (mparam, *m);\r\n      RemoveIllegalElements (*m);\r\n      OptimizeVolume (mparam, *m);\r\n\r\n      return NG_OK;\r\n   }\r\n\r\n\r\n\r\n\r\n   /* ------------------ 2D Meshing Functions ------------------------- */\r\n   NGLIB_API void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n\r\n      m->AddPoint (Point3d (x[0], x[1], 0));\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n\r\n      Segment seg;\r\n      seg[0] = pi1;\r\n      seg[1] = pi2;\r\n      m->AddSegment (seg);\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API int Ng_GetNP_2D (Ng_Mesh * mesh)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      return m->GetNP();\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API int Ng_GetNE_2D (Ng_Mesh * mesh)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      return m->GetNSE();\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API int Ng_GetNSeg_2D (Ng_Mesh * mesh)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n      return m->GetNSeg();\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x)\r\n   {\r\n      Mesh * m = (Mesh*)mesh;\r\n\r\n      Point<3> & p = m->Point(num);\r\n      x[0] = p(0);\r\n      x[1] = p(1);\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API Ng_Surface_Element_Type\r\n      Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum)\r\n   {\r\n     const Element2d & el = ((Mesh*)mesh)->SurfaceElement(SurfaceElementIndex(num-1));\r\n      for (int i = 1; i <= el.GetNP(); i++)\r\n         pi[i-1] = el.PNum(i);\r\n\r\n      Ng_Surface_Element_Type et;\r\n      switch (el.GetNP())\r\n      {\r\n      case 3: et = NG_TRIG; break;\r\n      case 4: et = NG_QUAD; break;\r\n      case 6: \r\n         switch (el.GetNV())\r\n         {\r\n         case 3: et = NG_TRIG6; break;\r\n         case 4: et = NG_QUAD6; break;\r\n         default:\r\n            et = NG_TRIG6; break;\r\n         }\r\n         break;\r\n      case 8: et = NG_QUAD8; break;\r\n      default:\r\n         et = NG_TRIG; break; // for the compiler\r\n      }\r\n\r\n      if (matnum)\r\n         *matnum = el.GetIndex();\r\n\r\n      return et;\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum)\r\n   {\r\n      const Segment & seg = ((Mesh*)mesh)->LineSegment(num);\r\n      pi[0] = seg[0];\r\n      pi[1] = seg[1];\r\n\r\n      if (matnum)\r\n         *matnum = seg.edgenr;\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename)\r\n   {\r\n      SplineGeometry2d * geom = new SplineGeometry2d();\r\n      geom -> Load (filename);\r\n      return (Ng_Geometry_2D *)geom;\r\n   }\r\n\r\n\r\n   NGLIB_API Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom,\r\n                                            Ng_Mesh ** mesh,\r\n                                            Ng_Meshing_Parameters * mp)\r\n   {\r\n      // use global variable mparam\r\n      //  MeshingParameters mparam;  \r\n      mp->Transfer_Parameters();\r\n\r\n      shared_ptr<Mesh> m(new Mesh, &NOOP_Deleter);\r\n      MeshFromSpline2D (*(SplineGeometry2d*)geom, m, mparam);\r\n      // new shared_ptr<Mesh> (m);  // hack to keep mesh m alive \r\n      \r\n      cout << m->GetNSE() << \" elements, \" << m->GetNP() << \" points\" << endl;\r\n\r\n      *mesh = (Ng_Mesh*)m.get();\r\n      return NG_OK;\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_HP_Refinement (Ng_Geometry_2D * geom,\r\n      Ng_Mesh * mesh,\r\n      int levels)\r\n   {\r\n      Refinement ref(*(SplineGeometry2d*)geom);\r\n      HPRefinement (*(Mesh*)mesh, &ref, levels);\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_HP_Refinement (Ng_Geometry_2D * geom,\r\n      Ng_Mesh * mesh,\r\n      int levels, double parameter)\r\n   {\r\n      Refinement ref(*(SplineGeometry2d*)geom);\r\n      HPRefinement (*(Mesh*)mesh, &ref, levels, parameter);\r\n   }\r\n\r\n\r\n\r\n\r\n   NgArray<STLReadTriangle> readtrias; //only before initstlgeometry\r\n   NgArray<Point<3> > readedges; //only before init stlgeometry\r\n\r\n   // loads geometry from STL file\r\n   NGLIB_API Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary)\r\n   {\r\n      int i;\r\n      STLGeometry geom;\r\n      STLGeometry* geo;\r\n      ifstream ist(filename);\r\n\r\n      if (binary)\r\n      {\r\n         geo = geom.LoadBinary(ist);\r\n      }\r\n      else\r\n      {\r\n         geo = geom.Load(ist);\r\n      }\r\n\r\n      readtrias.SetSize(0);\r\n      readedges.SetSize(0);\r\n\r\n      Point3d p;\r\n      Vec3d normal;\r\n      double p1[3];\r\n      double p2[3];\r\n      double p3[3];\r\n      double n[3];\r\n\r\n      Ng_STL_Geometry * geo2 = Ng_STL_NewGeometry();\r\n\r\n      for (i = 1; i <= geo->GetNT(); i++)\r\n      {\r\n         const STLTriangle& t = geo->GetTriangle(i);\r\n         p = geo->GetPoint(t.PNum(1));\r\n         p1[0] = p.X(); p1[1] = p.Y(); p1[2] = p.Z(); \r\n         p = geo->GetPoint(t.PNum(2));\r\n         p2[0] = p.X(); p2[1] = p.Y(); p2[2] = p.Z(); \r\n         p = geo->GetPoint(t.PNum(3));\r\n         p3[0] = p.X(); p3[1] = p.Y(); p3[2] = p.Z();\r\n         normal = t.Normal();\r\n         n[0] = normal.X(); n[1] = normal.Y(); n[2] = normal.Z();\r\n\r\n         Ng_STL_AddTriangle(geo2, p1, p2, p3, n);\r\n      }\r\n\r\n      return geo2;\r\n   }\r\n\r\n\r\n\r\n\r\n   // generate new STL Geometry\r\n   NGLIB_API Ng_STL_Geometry * Ng_STL_NewGeometry ()\r\n   {\r\n      return (Ng_STL_Geometry*)(void*)new STLGeometry;\r\n   } \r\n\r\n\r\n\r\n\r\n   // after adding triangles (and edges) initialize\r\n   NGLIB_API Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom)\r\n   {\r\n      STLGeometry* geo = (STLGeometry*)geom;\r\n      geo->InitSTLGeometry(readtrias);\r\n      readtrias.SetSize(0);\r\n\r\n      if (readedges.Size() != 0)\r\n      {\r\n         /*\r\n         for (int i = 1; i <= readedges.Size(); i+=2)\r\n         {\r\n         cout << \"e(\" << readedges.Get(i) << \",\" << readedges.Get(i+1) << \")\" << endl;\r\n         }\r\n         */\r\n         geo->AddEdges(readedges);\r\n      }\r\n\r\n      if (geo->GetStatus() == STLTopology::STL_GOOD || geo->GetStatus() == STLTopology::STL_WARNING) return NG_OK;\r\n      return NG_SURFACE_INPUT_ERROR;\r\n   }\r\n\r\n\r\n\r\n\r\n   // automatically generates edges:\r\n   NGLIB_API Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom,\r\n                                          Ng_Mesh* mesh,\r\n                                          Ng_Meshing_Parameters * mp)\r\n   {\r\n      STLGeometry* stlgeometry = (STLGeometry*)geom;\r\n      Mesh* me = (Mesh*)mesh;\r\n      me->SetGeometry( shared_ptr<NetgenGeometry>(stlgeometry, &NOOP_Deleter) );\r\n\r\n      // Philippose - 27/07/2009\r\n      // Do not locally re-define \"mparam\" here... \"mparam\" is a global \r\n      // object \r\n      //MeshingParameters mparam;\r\n      mp->Transfer_Parameters();\r\n\r\n      me -> SetGlobalH (mparam.maxh);\r\n      me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\r\n                       stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\r\n                       0.3);\r\n\r\n      // cout << \"meshsize = \" << mp->meshsize_filename << endl;\r\n      if (mp->meshsize_filename)\r\n        me -> LoadLocalMeshSize (mp->meshsize_filename);\r\n\r\n      /*\r\n      if (mp->meshsize_filename)\r\n        {\r\n          ifstream infile (mp->meshsize_filename);\r\n          if (!infile.good()) return NG_FILE_NOT_FOUND;\r\n          me -> LoadLocalMeshSize (infile);\r\n        }\r\n      */\r\n\r\n      STLMeshing (*stlgeometry, *me, mparam, stlparam);\r\n\r\n      stlgeometry->edgesfound = 1;\r\n      stlgeometry->surfacemeshed = 0;\r\n      stlgeometry->surfaceoptimized = 0;\r\n      stlgeometry->volumemeshed = 0;\r\n\r\n      return NG_OK;\r\n   }\r\n\r\n\r\n\r\n\r\n   // generates mesh, empty mesh be already created.\r\n   NGLIB_API Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom,\r\n                                                    Ng_Mesh* mesh,\r\n                                                    Ng_Meshing_Parameters * mp)\r\n   {\r\n      STLGeometry* stlgeometry = (STLGeometry*)geom;\r\n      Mesh* me = (Mesh*)mesh;\r\n      me->SetGeometry( shared_ptr<NetgenGeometry>(stlgeometry, &NOOP_Deleter) );\r\n\r\n      // Philippose - 27/07/2009\r\n      // Do not locally re-define \"mparam\" here... \"mparam\" is a global \r\n      // object\r\n      //MeshingParameters mparam;\r\n      mp->Transfer_Parameters();\r\n\r\n\r\n      /*\r\n      me -> SetGlobalH (mparam.maxh);\r\n      me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),\r\n      stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),\r\n      0.3);\r\n      */\r\n      /*\r\n      STLMeshing (*stlgeometry, *me);\r\n\r\n      stlgeometry->edgesfound = 1;\r\n      stlgeometry->surfacemeshed = 0;\r\n      stlgeometry->surfaceoptimized = 0;\r\n      stlgeometry->volumemeshed = 0;\r\n      */  \r\n      int retval = STLSurfaceMeshing (*stlgeometry, *me, mparam, stlparam);\r\n      if (retval == MESHING3_OK)\r\n      {\r\n         (*mycout) << \"Success !!!!\" << endl;\r\n         stlgeometry->surfacemeshed = 1;\r\n         stlgeometry->surfaceoptimized = 0;\r\n         stlgeometry->volumemeshed = 0;\r\n      } \r\n      else if (retval == MESHING3_OUTERSTEPSEXCEEDED)\r\n      {\r\n         (*mycout) << \"ERROR: Give up because of too many trials. Meshing aborted!\" << endl;\r\n      }\r\n      else if (retval == MESHING3_TERMINATE)\r\n      {\r\n         (*mycout) << \"Meshing Stopped!\" << endl;\r\n      }\r\n      else\r\n      {\r\n         (*mycout) << \"ERROR: Surface meshing not successful. Meshing aborted!\" << endl;\r\n      }\r\n\r\n\r\n      STLSurfaceOptimization (*stlgeometry, *me, mparam);\r\n\r\n      return NG_OK;\r\n   }\r\n\r\n\r\n\r\n\r\n   // fills STL Geometry\r\n   // positive orientation\r\n   // normal vector may be null-pointer\r\n   NGLIB_API void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, \r\n                                       double * p1, double * p2, double * p3, \r\n                                       double * nv)\r\n   {\r\n      Point<3> apts[3];\r\n      apts[0] = Point<3>(p1[0],p1[1],p1[2]);\r\n      apts[1] = Point<3>(p2[0],p2[1],p2[2]);\r\n      apts[2] = Point<3>(p3[0],p3[1],p3[2]);\r\n\r\n      Vec<3> n;\r\n      if (!nv)\r\n         n = Cross (apts[0]-apts[1], apts[0]-apts[2]);\r\n      else\r\n         n = Vec<3>(nv[0],nv[1],nv[2]);\r\n\r\n      readtrias.Append(STLReadTriangle(apts,n));\r\n   }\r\n\r\n   // add (optional) edges:\r\n   NGLIB_API void Ng_STL_AddEdge (Ng_STL_Geometry * geom, \r\n      double * p1, double * p2)\r\n   {\r\n      readedges.Append(Point3d(p1[0],p1[1],p1[2]));\r\n      readedges.Append(Point3d(p2[0],p2[1],p2[2]));\r\n   }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n   // ------------------ Begin - Meshing Parameters related functions ------------------\r\n   // Constructor for the local nglib meshing parameters class\r\n   NGLIB_API Ng_Meshing_Parameters :: Ng_Meshing_Parameters()\r\n   {\r\n      uselocalh = 1;\r\n\r\n      maxh = 1000;\r\n      minh = 0.0;\r\n\r\n      fineness = 0.5;\r\n      grading = 0.3;\r\n\r\n      elementsperedge = 2.0;\r\n      elementspercurve = 2.0;\r\n\r\n      closeedgeenable = 0;\r\n      closeedgefact = 2.0;\r\n\r\n\t  minedgelenenable = 0;\r\n\t  minedgelen = 1e-4;\r\n\r\n      second_order = 0;\r\n      quad_dominated = 0;\r\n\r\n      meshsize_filename = 0;\r\n\r\n      optsurfmeshenable = 1;\r\n      optvolmeshenable = 1;\r\n\r\n      optsteps_2d = 3;\r\n      optsteps_3d = 3;\r\n\r\n      invert_tets = 0;\r\n      invert_trigs = 0;\r\n\r\n      check_overlap = 1;\r\n      check_overlapping_boundary = 1;\r\n   }\r\n\r\n\r\n\r\n\r\n   // Reset the local meshing parameters to the default values\r\n   NGLIB_API void Ng_Meshing_Parameters :: Reset_Parameters()\r\n   {\r\n      uselocalh = 1;\r\n\r\n      maxh = 1000;\r\n      minh = 0;\r\n\r\n      fineness = 0.5;\r\n      grading = 0.3;\r\n\r\n      elementsperedge = 2.0;\r\n      elementspercurve = 2.0;\r\n\r\n      closeedgeenable = 0;\r\n      closeedgefact = 2.0;\r\n\r\n  \t  minedgelenenable = 0;\r\n\t  minedgelen = 1e-4;\r\n\r\n      second_order = 0;\r\n      quad_dominated = 0;\r\n\r\n      meshsize_filename = 0;\r\n\r\n      optsurfmeshenable = 1;\r\n      optvolmeshenable = 1;\r\n\r\n      optsteps_2d = 3;\r\n      optsteps_3d = 3;\r\n\r\n      invert_tets = 0;\r\n      invert_trigs = 0;\r\n\r\n      check_overlap = 1;\r\n      check_overlapping_boundary = 1;\r\n   }\r\n\r\n\r\n\r\n\r\n   // \r\n   NGLIB_API void Ng_Meshing_Parameters :: Transfer_Parameters()\r\n   {\r\n      mparam.uselocalh = uselocalh;\r\n      \r\n      mparam.maxh = maxh;\r\n      mparam.minh = minh;\r\n\r\n      mparam.grading = grading;\r\n      mparam.curvaturesafety = elementspercurve;\r\n      mparam.segmentsperedge = elementsperedge;\r\n\r\n      mparam.secondorder = second_order;\r\n      mparam.quad = quad_dominated;\r\n\r\n      if (meshsize_filename)\r\n        mparam.meshsizefilename = meshsize_filename;\r\n      else\r\n        mparam.meshsizefilename = \"\";\r\n      mparam.optsteps2d = optsteps_2d;\r\n      mparam.optsteps3d = optsteps_3d;\r\n\r\n      mparam.inverttets = invert_tets;\r\n      mparam.inverttrigs = invert_trigs;\r\n\r\n      mparam.checkoverlap = check_overlap;\r\n      mparam.checkoverlappingboundary = check_overlapping_boundary;\r\n   }\r\n   // ------------------ End - Meshing Parameters related functions --------------------\r\n\r\n\r\n\r\n\r\n   // ------------------ Begin - Second Order Mesh generation functions ----------------\r\n   NGLIB_API void Ng_Generate_SecondOrder(Ng_Mesh * mesh)\r\n   {\r\n     Refinement ref(*((Mesh*) mesh)->GetGeometry());\r\n      ref.MakeSecondOrder(*(Mesh*) mesh);\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_2D_Generate_SecondOrder(Ng_Geometry_2D * geom,\r\n\t\t\t\t\t  Ng_Mesh * mesh)\r\n   {\r\n      ( (SplineGeometry2d*)geom ) -> GetRefinement().MakeSecondOrder( * (Mesh*) mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_STL_Generate_SecondOrder(Ng_STL_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh)\r\n   {\r\n      ((STLGeometry*)geom)->GetRefinement().MakeSecondOrder(*(Mesh*) mesh);\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_CSG_Generate_SecondOrder (Ng_CSG_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh)\r\n   {\r\n      ((CSGeometry*)geom)->GetRefinement().MakeSecondOrder(*(Mesh*) mesh);\r\n   }\r\n\r\n\r\n\r\n\r\n   // ------------------ End - Second Order Mesh generation functions ------------------\r\n\r\n\r\n\r\n\r\n   // ------------------ Begin - Uniform Mesh Refinement functions ---------------------\r\n   NGLIB_API void Ng_Uniform_Refinement (Ng_Mesh * mesh)\r\n   {\r\n     Refinement ref(*((Mesh*)mesh)->GetGeometry());\r\n     ref.Refine ( * (Mesh*) mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_2D_Uniform_Refinement (Ng_Geometry_2D * geom,\r\n      Ng_Mesh * mesh)\r\n   {\r\n      ( (SplineGeometry2d*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_STL_Uniform_Refinement (Ng_STL_Geometry * geom,\r\n      Ng_Mesh * mesh)\r\n   {\r\n      ( (STLGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   NGLIB_API void Ng_CSG_Uniform_Refinement (Ng_CSG_Geometry * geom,\r\n      Ng_Mesh * mesh)\r\n   {\r\n      ( (CSGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh );\r\n   }\r\n\r\n\r\n\r\n\r\n   // ------------------ End - Uniform Mesh Refinement functions -----------------------\r\n} // End of namespace nglib\r\n\r\n\r\n\r\n\r\n// compatibility functions:\r\nnamespace netgen \r\n{\r\n   char geomfilename[255];\r\n\r\n   NGLIB_API void MyError2 (const char * ch)\r\n   {\r\n      cerr << ch;\r\n   }\r\n\r\n\r\n\r\n\r\n   //Destination for messages, errors, ...\r\n   NGLIB_API void Ng_PrintDest2(const char * s)\r\n   {\r\n#ifdef PARALLEL\r\n     int id = 0;\r\n     NG_MPI_Comm_rank(NG_MPI_COMM_WORLD, &id);\r\n     if (id != 0) return;\r\n#endif\r\n     (*mycout) << s << flush;\r\n   }\r\n\r\n\r\n  /*\r\n   NGLIB_API double GetTime ()\r\n   {\r\n      return 0;\r\n   }\r\n  */\r\n\r\n  /*\r\n#ifndef WIN32\r\n   void ResetTime ()\r\n   {\r\n      ;\r\n   }\r\n#endif\r\n  */\r\n\r\n\r\n   void MyBeep (int i)\r\n   {\r\n      ;\r\n   }\r\n\r\n\r\n\r\n  //void Render() { ; }\r\n\r\n} // End of namespace netgen\r\n\r\n\r\n/*\r\n\r\n#ifndef WIN32\r\nvoid Ng_Redraw () { ; }\r\nvoid Ng_ClearSolutionData() { ; }\r\n#endif\r\nvoid Ng_SetSolutionData (Ng_SolutionData * soldata) \r\n{ \r\n  delete soldata->solclass;\r\n}\r\nvoid Ng_InitSolutionData (Ng_SolutionData * soldata) { ; }\r\n*/\r\n\r\n// Force linking libinterface to libnglib\r\n#include <../interface/writeuser.hpp>\r\nvoid MyDummyToForceLinkingLibInterface(Mesh &mesh, NetgenGeometry &geom)\r\n{\r\n  netgen::WriteUserFormat(\"\", mesh, /* geom, */ \"\");\r\n}\r\n\r\n"
  },
  {
    "path": "nglib/nglib.h",
    "content": "#ifndef NGLIB\r\n#define NGLIB\r\n\r\n/**************************************************************************/\r\n/* File:   nglib.h                                                        */\r\n/* Author: Joachim Schoeberl                                              */\r\n/* Date:   7. May. 2000                                                   */\r\n/**************************************************************************/\r\n\r\n#include <stddef.h>\r\n\r\n/*!\r\n   \\file nglib.h\r\n   \\brief Library interface to the netgen meshing kernel\r\n   \\author Joachim Schoeberl\r\n   \\date 7. May 2000\r\n\r\n   This header file provides access to the core functionality of the Netgen \r\n   Mesher via a library interface, without an interactive User Interface.\r\n\r\n   The intention of providing these set of functions is to allow system \r\n   developers to integrate Netgen into top-level code, to act as the low \r\n   level mesh generation / optimisation kernel.  \r\n*/\r\n\r\n// Philippose - 14.02.2009\r\n// Modifications for creating a DLL in Windows\r\n#ifdef WIN32\r\n   #ifdef nglib_EXPORTS\r\n      #define NGLIB_API   __declspec(dllexport)\r\n   #else\r\n      #define NGLIB_API   __declspec(dllimport)\r\n   #endif\r\n#else\r\n  #define NGLIB_API __attribute__((visibility(\"default\")))\r\n#endif\r\n\r\n\r\n// ** Constants used within Netgen *********************\r\n/// Maximum allowed number of nodes per volume element\r\n#define NG_VOLUME_ELEMENT_MAXPOINTS 10\r\n\r\n/// Maximum allowed number of nodes per surface element\r\n#define NG_SURFACE_ELEMENT_MAXPOINTS 8\r\n\r\n\r\n\r\n// *** Data-types for accessing Netgen functionality ***\r\n/// Data type for NETGEN mesh\r\ntypedef void * Ng_Mesh;\r\n\r\n/// Data type for NETGEN CSG geometry\r\ntypedef void * Ng_CSG_Geometry;\r\n\r\n/// Data type for NETGEN 2D geometry\r\ntypedef void * Ng_Geometry_2D;\r\n\r\n/// Data type for NETGEN STL geometry\r\ntypedef void * Ng_STL_Geometry;\r\n\r\n\r\n\r\n// *** Special Enum types used within Netgen ***********\r\n/// Currently implemented surface element types\r\nenum Ng_Surface_Element_Type \r\n   { NG_TRIG = 1, NG_QUAD = 2, NG_TRIG6 = 3, NG_QUAD6 = 4, NG_QUAD8 = 5 };\r\n\r\n/// Currently implemented volume element types\r\nenum Ng_Volume_Element_Type \r\n   { NG_TET = 1, NG_PYRAMID = 2, NG_PRISM = 3, NG_TET10 = 4 };\r\n\r\n/// Values returned by Netgen functions\r\nenum Ng_Result \r\n   { \r\n     NG_ERROR               = -1,   \r\n     NG_OK                  = 0, \r\n     NG_SURFACE_INPUT_ERROR = 1,\r\n     NG_VOLUME_FAILURE      = 2, \r\n     NG_STL_INPUT_ERROR     = 3,\r\n     NG_SURFACE_FAILURE     = 4,\r\n     NG_FILE_NOT_FOUND      = 5 \r\n   };\r\n\r\n\r\n\r\n// *** Classes required for use within Netgen **********\r\n/// Netgen Meshing Parameters class\r\nclass Ng_Meshing_Parameters \r\n{\r\npublic:\r\n   int uselocalh;                      //!< Switch to enable / disable usage of local mesh size modifiers\r\n\r\n   double maxh;                        //!< Maximum global mesh size allowed\r\n   double minh;                        //!< Minimum global mesh size allowed\r\n\r\n   double fineness;                    //!< Mesh density: 0...1 (0 => coarse; 1 => fine)\r\n   double grading;                     //!< Mesh grading: 0...1 (0 => uniform mesh; 1 => aggressive local grading)\r\n\r\n   double elementsperedge;             //!< Number of elements to generate per edge of the geometry\r\n   double elementspercurve;            //!< Elements to generate per curvature radius\r\n\r\n   int closeedgeenable;                //!< Enable / Disable mesh refinement at close edges\r\n   double closeedgefact;               //!< Factor to use for refinement at close edges (larger => finer)\r\n\r\n   int minedgelenenable;\t\t\t   //!< Enable / Disable user defined minimum edge length for edge subdivision\r\n   double minedgelen;                  //!< Minimum edge length to use while subdividing the edges (default = 1e-4)\r\n\r\n   int second_order;                   //!< Generate second-order surface and volume elements\r\n   int quad_dominated;                 //!< Creates a Quad-dominated mesh \r\n\r\n   char * meshsize_filename;           //!< Optional external mesh size file \r\n\r\n   int optsurfmeshenable;              //!< Enable / Disable automatic surface mesh optimization\r\n   int optvolmeshenable;               //!< Enable / Disable automatic volume mesh optimization\r\n\r\n   int optsteps_3d;                     //!< Number of optimize steps to use for 3-D mesh optimization\r\n   int optsteps_2d;                     //!< Number of optimize steps to use for 2-D mesh optimization\r\n\r\n   // Philippose - 13/09/2010\r\n   // Added a couple more parameters into the meshing parameters list \r\n   // from Netgen into Nglib\r\n   int invert_tets;                    //!< Invert all the volume elements\r\n   int invert_trigs;                   //!< Invert all the surface triangle elements\r\n\r\n   int check_overlap;                  //!< Check for overlapping surfaces during Surface meshing\r\n   int check_overlapping_boundary;     //!< Check for overlapping surface elements before volume meshing\r\n\r\n\r\n   /*!\r\n      Default constructor for the Mesh Parameters class\r\n\r\n      Note: This constructor initialises the variables in the \r\n      class with the following default values\r\n      - #uselocalh: 1\r\n      - #maxh: 1000.0\r\n      - #fineness: 0.5\r\n      - #grading: 0.3\r\n      - #elementsperedge: 2.0\r\n      - #elementspercurve: 2.0\r\n      - #closeedgeenable: 0\r\n      - #closeedgefact: 2.0\r\n      - #secondorder: 0\r\n      - #meshsize_filename: null\r\n      - #quad_dominated: 0\r\n      - #optsurfmeshenable: 1\r\n      - #optvolmeshenable: 1\r\n      - #optsteps_2d: 3\r\n      - #optsteps_3d: 3\r\n      - #invert_tets: 0\r\n      - #invert_trigs:0 \r\n      - #check_overlap: 1\r\n      - #check_overlapping_boundary: 1\r\n   */\r\n   NGLIB_API Ng_Meshing_Parameters();\r\n\r\n\r\n\r\n   /*!\r\n       Reset the meshing parameters to their defaults\r\n\r\n       This member function resets all the meshing parameters \r\n       of the object to the default values\r\n   */\r\n   NGLIB_API void Reset_Parameters();\r\n\r\n\r\n\r\n   /*!\r\n       Transfer local meshing parameters to internal meshing parameters\r\n\r\n       This member function transfers all the meshing parameters \r\n       defined in the local meshing parameters structure of nglib into \r\n       the internal meshing parameters structure used by the Netgen core\r\n   */\r\n   NGLIB_API void Transfer_Parameters();\r\n};\r\n\r\n\r\n\r\n\r\n// *** Functions Exported by this Library *************\r\n\r\n// ------------------------------------------------------------------\r\n// Netgen library initialisation / destruction functions\r\n\r\n/*! \\brief Initialise the Netgen library and prepare for use\r\n\r\n    This function needs to be called by the third-party \r\n    program before beginning to use the other Netgen \r\n    specific functions.\r\n*/\r\nNGLIB_API void Ng_Init ();\r\n\r\n\r\n/*! \\brief Exit the Netgen meshing kernel in a clean manner\r\n\r\n    Use this function to exit the meshing sub-system in \r\n    a clean and orderly manner.\r\n*/\r\nNGLIB_API void Ng_Exit ();\r\n  \r\n\r\n/*! \\brief Create a new (and empty) Netgen Mesh Structure\r\n\r\n    This function creates a new Netgen Mesh, initialises \r\n    it, and returns a pointer to the created mesh structure. \r\n\r\n    Use the returned pointer for subsequent operations \r\n    which involve mesh operations.\r\n\r\n    \\return Ng_Mesh Pointer to a Netgen Mesh type #Ng_Mesh\r\n*/\r\nNGLIB_API  Ng_Mesh * Ng_NewMesh ();\r\n\r\n\r\n/*! \\brief Delete an existing Netgen Mesh Structure\r\n\r\n    Use this function to delete an existing Netgen mesh \r\n    structure and release the used memory. \r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure \r\n                of type #Ng_Mesh\r\n*/\r\nNGLIB_API void Ng_DeleteMesh (Ng_Mesh * mesh);\r\n\r\n\r\n/*! \\brief Save a Netgen Mesh to disk\r\n\r\n    This function allows a generated mesh structure to be saved \r\n    to disk.\r\n\r\n    A Mesh saved using this function, will be written to disk \r\n    in the Netgen VOL file format.\r\n\r\n    \\param mesh    Pointer to an existing Netgen Mesh structure \r\n                   of type #Ng_Mesh\r\n    \\param filename Pointer to a character array containing the \r\n                    name of the file to which the mesh should \r\n                    be saved\r\n*/\r\nNGLIB_API void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename);\r\n\r\n\r\n/*! \\brief Load a Netgen VOL Mesh from disk into memory\r\n\r\n    A Netgen mesh saved in the internal VOL format can be loaded \r\n    into a Netgen Mesh structure using this function. \r\n\r\n    \\param filename Pointer to a character array containing the \r\n                    name of the file to load\r\n    \\return Ng_Mesh Pointer to a Netgen Mesh type #Ng_Mesh containing \r\n                    the mesh loaded from disk\r\n*/\r\nNGLIB_API Ng_Mesh * Ng_LoadMesh(const char* filename);\r\n\r\n\r\n/*! \\brief Merge a Netgen VOL Mesh from disk into an existing mesh in memory\r\n\r\n    A Netgen mesh saved in the internal VOL format can be merged \r\n    into an existing Netgen Mesh structure using this function. \r\n\r\n    \\param mesh       Name of the Mesh structure already existent in memory\r\n    \\param filename   Pointer to a character array containing the \r\n                      name of the file to load\r\n    \\return Ng_Result Status of the merge operation\r\n*/\r\nNGLIB_API Ng_Result Ng_MergeMesh(Ng_Mesh * mesh, const char* filename);\r\n\r\n\r\n/*! \\brief Merge one Netgen Mesh into another Netgen Mesh in the case \r\n    when both are already in memory\r\n\r\n    (NOTE: FUNCTION STILL WORK IN PROGRESS!!!)\r\n\r\n    This function can be used to merge two Netgen meshes already present \r\n    in memory.\r\n\r\n    \\param mesh1      Parent Mesh structure into which the second mesh \r\n                      will be merged\r\n    \\param mesh2      Child mesh structure which will get merged into \r\n                      the parent mesh\r\n    \\return Ng_Result Status of the merge operation\r\n*/\r\nNGLIB_API Ng_Result Ng_MergeMesh(Ng_Mesh * mesh1, Ng_Mesh * mesh2);\r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n// ------------------------------------------------------------------\r\n// Basic Meshing functions for manually adding points, surface elements \r\n// and volume elements to a Netgen Mesh structure\r\n\r\n/*! \\brief Add a point to a given Netgen Mesh Structure\r\n\r\n    This function allows points to be directly added to a Netgen \r\n    mesh structure by providing the co-ordinates.\r\n\r\n    Each call to the function allows only one point to be added.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param x    Pointer to an array of type double containing the co-ordinates \r\n                of the point to be added in the form: \\n\r\n                - x[0] = X co-ordinate\r\n                - x[1] = Y co-ordinate\r\n                - x[2] = Z co-ordinate\r\n*/\r\nNGLIB_API void Ng_AddPoint (Ng_Mesh * mesh, double * x);\r\n\r\n\r\n/*! \\brief Add a surface element to a given Netgen Mesh Structure\r\n\r\n    This function allows the top-level code to directly add individual \r\n    Surface Elements to a Netgen Mesh Structure by providing the type of \r\n    element to be added and the indices of the points which constitute the \r\n    element.\r\n\r\n    <i>Note:</i> \r\n    - The points referred to by the surface elements must have been\r\n      added prior to calling this function. \r\n    - Currently only triangular elements are supported, and the Surface Element \r\n      Type argument is not used.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param et   Surface Element type provided via the enumerated type \r\n                #Ng_Surface_Element_Type \r\n    \\param pi   Pointer to an array of integers containing the indices of the \r\n                points which constitute the surface element being added\r\n*/\r\nNGLIB_API void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, int * pi);\r\n\r\n\r\n/*! \\brief Add a volume element to a given Netgen Mesh Structure\r\n\r\n    This function allows the top-level code to directly add individual \r\n    Volume Elements to a Netgen Mesh Structure by providing the type of \r\n    element to be added and the indices of the points which constitute the \r\n    element.\r\n\r\n    <i>Note:</i> \r\n    - The points referred to by the volume elements must have been\r\n      added prior to calling this function. \r\n    - Currently only tetrahedral elements are supported, and the Volume Element \r\n      Type argument is not used.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param et   Volume Element type provided via the enumerated type \r\n                #Ng_Volume_Element_Type \r\n    \\param pi   Pointer to an array of integers containing the indices of the \r\n                points which constitute the volume element being added\r\n\r\n*/\r\nNGLIB_API void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, int * pi);\r\n  \r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n// ------------------------------------------------------------------\r\n// Local Mesh Size restriction / limiting utilities\r\n\r\n/*! \\brief Apply a global restriction on mesh element size\r\n\r\n    This utility allows the user to apply a global mesh element \r\n    size limitation. \r\n\r\n    During mesh creation, in the absence of an explicit local \r\n    size restriction around the neighbourhood of a point within \r\n    the meshing domain, this global size restriction will be \r\n    utilised.\r\n\r\n    <b>Note</b>: This function only limits the <b>Maximum</b> \r\n    size of an element within the mesh.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param h    Variable of type <i>double</i>, specifying the maximum\r\n                allowable mesh size\r\n*/\r\nNGLIB_API void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h);\r\n\r\n\r\n/*! \\brief Locally restrict the mesh element size at the given point\r\n\r\n    Unlike the function #Ng_RestrictMeshSizeGlobal, this function \r\n    allows the user to locally restrict the maximum allowable mesh \r\n    size at a given point.\r\n\r\n    The point is specified via its three cartesian co-ordinates.\r\n\r\n    <b>Note</b>: This function only limits the <b>Maximum</b> size \r\n    of the elements around the specified point.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param p    Pointer to an Array of type <i>double</i>, containing \r\n                the three co-ordinates of the point in the form: \\n\r\n                - p[0] = X co-ordinate\r\n                - p[1] = Y co-ordinate\r\n                - p[2] = Z co-ordinate\r\n    \\param h    Variable of type <i>double</i>, specifying the maximum\r\n                allowable mesh size at that point\r\n*/\r\nNGLIB_API void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h);\r\n\r\n\r\n/*! \\brief Locally restrict the mesh element size within a specified box\r\n\r\n    Similar to the function #Ng_RestrictMeshSizePoint, this function \r\n    allows the size of elements within a mesh to be locally limited.\r\n\r\n    However, rather than limit the mesh size at a single point, this \r\n    utility restricts the local mesh size within a 3D Box region, specified \r\n    via the co-ordinates of the two diagonally opposite points of a cuboid.\r\n\r\n    <b>Note</b>: This function only limits the <b>Maximum</b> size \r\n    of the elements within the specified region.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param pmin Pointer to an Array of type <i>double</i>, containing \r\n                the three co-ordinates of the first point of the cuboid: \\n\r\n                - pmin[0] = X co-ordinate\r\n                - pmin[1] = Y co-ordinate\r\n                - pmin[2] = Z co-ordinate\r\n    \\param pmax Pointer to an Array of type <i>double</i>, containing \r\n                the three co-ordinates of the opposite point of the \r\n                cuboid: \\n\r\n                - pmax[0] = X co-ordinate\r\n                - pmax[1] = Y co-ordinate\r\n                - pmax[2] = Z co-ordinate\r\n    \\param h    Variable of type <i>double</i>, specifying the maximum\r\n                allowable mesh size at that point\r\n*/\r\nNGLIB_API void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h);\r\n\r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n// ------------------------------------------------------------------\r\n// 3D Mesh Generation functions\r\n\r\n/*! \\brief Create a 3D Volume Mesh given a Surface Mesh\r\n\r\n    After creating a surface mesh, this function can be utilised \r\n    to automatically generate the corresponding 3D Volume Mesh.\r\n\r\n    Mesh generation parameters (such as grading, maximum element size, \r\n    etc.) are specified via the meshing parameters class which also \r\n    needs to be passed to this function.\r\n\r\n    <b>Note</b>: Currently, Netgen generates pure tetrahedral volume \r\n    meshes.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\param mp   Pointer to a copy of the Meshing Parameters class\r\n                (#Ng_Meshing_Parameters), filled up with the \r\n                required values\r\n\r\n    \\return Ng_Result Status of the Mesh Generation routine. More \r\n                      details regarding the return value can be \r\n                      found in the description of #Ng_Result\r\n*/\r\nNGLIB_API Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp);\r\n\r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n// ------------------------------------------------------------------\r\n// Basic Mesh information functions\r\n\r\n/*! \\brief Returns the Number of Points present in the specified Mesh\r\n\r\n    Given an already existent Netgen Mesh Structure, this function \r\n    returns the number of points currently present within the Mesh.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\return \r\n                Integer Data-type with the number of points in the Mesh\r\n*/\r\nNGLIB_API int Ng_GetNP (Ng_Mesh * mesh);\r\n\r\n\r\n/*! \\brief Returns the Number of Surface Elements present in the specified Mesh\r\n\r\n    Given an already existent Netgen Mesh Structure, this function \r\n    returns the number of surface elements currently present within \r\n    the Mesh.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\return \r\n                Integer Data-type with the number of surface elements in the Mesh\r\n*/\r\nNGLIB_API int Ng_GetNSE (Ng_Mesh * mesh);\r\n\r\n\r\n/*! \\brief Returns the Number of Volume Elements present in the specified Mesh\r\n\r\n    Given an already existent Netgen Mesh Structure, this function \r\n    returns the number of volume elements currently present within \r\n    the Mesh.\r\n\r\n    \\param mesh Pointer to an existing Netgen Mesh structure of \r\n                type #Ng_Mesh\r\n    \\return \r\n                Integer Data-type with the number of volume elements in the Mesh\r\n*/\r\nNGLIB_API int Ng_GetNE (Ng_Mesh * mesh);\r\n\r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n// ------------------------------------------------------------------\r\n// Mesh Topology functions\r\n// Use these functions to extract points, surface / volume elements, \r\n// perform topological searches, etc..etc...\r\n  \r\n//  Return the Point Coordinates of a specified Point\r\n// The x, y and z co-ordinates are returned in the array pointer as \r\n// x[0] = x ; x[1] = y ; x[2] = z\r\nNGLIB_API void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x);\r\n\r\n\r\n\r\n// return surface and volume element in pi\r\nNGLIB_API Ng_Surface_Element_Type \r\nNg_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi);\r\n\r\nNGLIB_API Ng_Volume_Element_Type\r\nNg_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi);\r\n\r\n// ------------------------------------------------------------------\r\n\r\n\r\n\r\n\r\n// **********************************************************\r\n// **   2D Meshing                                         **\r\n// **********************************************************\r\n\r\n\r\n// feeds points and boundary to mesh\r\n\r\nNGLIB_API void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x);\r\nNGLIB_API void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2);\r\n  \r\n// ask for number of points, elements and boundary segments\r\nNGLIB_API int Ng_GetNP_2D (Ng_Mesh * mesh);\r\nNGLIB_API int Ng_GetNE_2D (Ng_Mesh * mesh);\r\nNGLIB_API int Ng_GetNSeg_2D (Ng_Mesh * mesh);\r\n  \r\n//  return point coordinates\r\nNGLIB_API void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x);\r\n\r\n// return 2d elements\r\nNGLIB_API Ng_Surface_Element_Type \r\nNg_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL);\r\n\r\n// return 2d boundary segment\r\nNGLIB_API void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL);\r\n\r\n\r\n// load 2d netgen spline geometry\r\nNGLIB_API Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename);\r\n\r\n// generate 2d mesh, mesh is allocated by function\r\nNGLIB_API Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom,\r\n                                         Ng_Mesh ** mesh,\r\n                                         Ng_Meshing_Parameters * mp);\r\n  \r\nNGLIB_API void Ng_HP_Refinement (Ng_Geometry_2D * geom,\r\n                                  Ng_Mesh * mesh,\r\n                                  int levels);\r\n  \r\n\r\n\r\n\r\n\r\n// **********************************************************\r\n// **   STL Meshing                                        **\r\n// **********************************************************\r\n\r\n\r\n// loads geometry from STL file\r\nNGLIB_API Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary = 0);\r\n\r\n\r\n// generate new STL Geometry\r\nNGLIB_API Ng_STL_Geometry * Ng_STL_NewGeometry ();\r\n  \r\n\r\n// fills STL Geometry\r\n// positive orientation\r\n// normal vector may be null-pointer\r\nNGLIB_API void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, \r\n                         double * p1, double * p2, double * p3, \r\n                         double * nv = NULL);\r\n\r\n// add (optional) edges :\r\nNGLIB_API void Ng_STL_AddEdge (Ng_STL_Geometry * geom, \r\n                     double * p1, double * p2);\r\n\r\n// after adding triangles (and edges) initialize\r\nNGLIB_API Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom);\r\n\r\n// automatically generates edges:\r\nNGLIB_API Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom,\r\n                            Ng_Mesh* mesh,\r\n                            Ng_Meshing_Parameters * mp);\r\n\r\n\r\n// generates mesh, empty mesh must be already created.\r\nNGLIB_API Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom,\r\n                                                 Ng_Mesh * mesh,\r\n                                                 Ng_Meshing_Parameters * mp);\r\n\r\n\r\n#ifdef ACIS\r\n\r\n// **********************************************************\r\n// **   ACIS Meshing                                       **\r\n// **********************************************************\r\n\r\n/// Data type for NETGEN STL geomty\r\ntypedef void * Ng_ACIS_Geometry;\r\n\r\n// loads geometry from STL file\r\nNGLIB_API Ng_ACIS_Geometry * Ng_ACIS_LoadGeometry (const char * filename);\r\n  \r\n// generates mesh, empty mesh must be already created.\r\nNGLIB_API Ng_Result Ng_ACIS_GenerateSurfaceMesh (Ng_ACIS_Geometry * geom,\r\n                                                  Ng_Mesh * mesh,\r\n                                                  Ng_Meshing_Parameters * mp);\r\n\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n// **********************************************************\r\n// **   Mesh refinement algorithms                         **\r\n// **********************************************************\r\n\r\n// uniform mesh refinement\r\nNGLIB_API void Ng_Uniform_Refinement (Ng_Mesh * mesh);\r\n\r\n\r\n// uniform mesh refinement with geometry adaption:\r\n\r\nNGLIB_API void Ng_2D_Uniform_Refinement (Ng_Geometry_2D * geom,\r\n\t\t\t\t\t  Ng_Mesh * mesh);\r\n\r\nNGLIB_API void Ng_STL_Uniform_Refinement (Ng_STL_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh);\r\n\r\nNGLIB_API void Ng_CSG_Uniform_Refinement (Ng_CSG_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh);\r\n\r\n\r\n\r\n\r\n// **********************************************************\r\n// **   Second Order mesh algorithms                       **\r\n// **********************************************************\r\n\r\n// convert mesh to second order\r\nNGLIB_API void Ng_Generate_SecondOrder (Ng_Mesh * mesh);\r\n\r\n\r\n// convert mesh to second order with geometry adaption:\r\n\r\nNGLIB_API void Ng_2D_Generate_SecondOrder (Ng_Geometry_2D * geom,\r\n\t\t\t\t\t  Ng_Mesh * mesh);\r\n\r\nNGLIB_API void Ng_STL_Generate_SecondOrder (Ng_STL_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh);\r\n\r\nNGLIB_API void Ng_CSG_Generate_SecondOrder (Ng_CSG_Geometry * geom,\r\n\t\t\t\t\t   Ng_Mesh * mesh);\r\n\r\n\r\n#ifdef OCCGEOMETRY\r\n#include \"nglib_occ.h\"\r\n#endif // OCCGEOMETRY\r\n       //\r\n#endif // NGLIB\r\n"
  },
  {
    "path": "nglib/nglib_occ.cpp",
    "content": "#include <mystdlib.h>\n#include <myadt.hpp>\n#include <occgeom.hpp>\n\n#define OCCGEOMETRY 1\nnamespace nglib {\n#include \"nglib.h\"\n}\n\n\nnamespace netgen\n{\n   inline void NOOP_Deleter(void *) { ; }\n   extern MeshingParameters mparam;\n   DLL_HEADER extern OCCParameters occparam;\n} // namespace netgen\n\nusing namespace netgen;\n\nnamespace nglib\n{\n\n   // --------------------- OCC Geometry / Meshing Utility Functions -------------------\n   // Create new OCC Geometry Object\n   NGLIB_API Ng_OCC_Geometry * Ng_OCC_NewGeometry ()\n   {\n      return (Ng_OCC_Geometry*)(void*)new OCCGeometry;\n   }\n\n\n   // Delete the OCC Geometry Object\n   NGLIB_API Ng_Result Ng_OCC_DeleteGeometry(Ng_OCC_Geometry * geom)\n   {\n      if (geom != NULL)\n      {\n         delete (OCCGeometry*)geom;\n         geom = NULL;\n         return NG_OK;\n      }\n\n      return NG_ERROR;\n   }\n\n\n   // Loads geometry from STEP File\n   NGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_STEP (const char * filename)\n   {\n      // Call the STEP File Load function. Note.. the geometry class\n      // is created and instantiated within the load function\n      OCCGeometry * occgeo = LoadOCC_STEP(filename);\n\n      return ((Ng_OCC_Geometry *)occgeo);\n   }\n\n\n   // Loads geometry from IGES File\n   NGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_IGES (const char * filename)\n   {\n      // Call the IGES File Load function. Note.. the geometry class\n      // is created and instantiated within the load function\n      OCCGeometry * occgeo = LoadOCC_IGES(filename);\n\n      return ((Ng_OCC_Geometry *)occgeo);\n   }\n\n\n   // Loads geometry from BREP File\n   NGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_BREP (const char * filename)\n   {\n      // Call the BREP File Load function. Note.. the geometry class\n      // is created and instantiated within the load function\n      OCCGeometry * occgeo = LoadOCC_BREP(filename);\n\n      return ((Ng_OCC_Geometry *)occgeo);\n   }\n\n\n   // Locally limit the size of the mesh to be generated at various points\n   // based on the topology of the geometry\n   NGLIB_API Ng_Result Ng_OCC_SetLocalMeshSize (Ng_OCC_Geometry * geom,\n                                                 Ng_Mesh * mesh,\n                                                 Ng_Meshing_Parameters * mp)\n   {\n      OCCGeometry * occgeom = (OCCGeometry*)geom;\n      Mesh * me = (Mesh*)mesh;\n      me->SetGeometry( shared_ptr<NetgenGeometry>(occgeom, &NOOP_Deleter) );\n\n      me->geomtype = Mesh::GEOM_OCC;\n\n      mp->Transfer_Parameters();\n\n      if(mp->closeedgeenable)\n        mparam.closeedgefac = mp->closeedgefact;\n\n      // Delete the mesh structures in order to start with a clean\n      // slate\n      me->DeleteMesh();\n\n      OCCSetLocalMeshSize(*occgeom, *me, mparam, occparam);\n\n      return(NG_OK);\n   }\n\n\n\n\n   // Mesh the edges and add Face descriptors to prepare for surface meshing\n   NGLIB_API Ng_Result Ng_OCC_GenerateEdgeMesh (Ng_OCC_Geometry * geom,\n                                                 Ng_Mesh * mesh,\n                                                 Ng_Meshing_Parameters * mp)\n   {\n      OCCGeometry * occgeom = (OCCGeometry*)geom;\n      Mesh * me = (Mesh*)mesh;\n      me->SetGeometry( shared_ptr<NetgenGeometry>(occgeom, &NOOP_Deleter) );\n\n      mp->Transfer_Parameters();\n\n      occgeom->FindEdges(*me, mparam);\n\n      if((me->GetNP()))\n      {\n         return NG_OK;\n      }\n      else\n      {\n         return NG_ERROR;\n      }\n   }\n\n\n\n\n   // Mesh the edges and add Face descriptors to prepare for surface meshing\n   NGLIB_API Ng_Result Ng_OCC_GenerateSurfaceMesh (Ng_OCC_Geometry * geom,\n                                                    Ng_Mesh * mesh,\n                                                    Ng_Meshing_Parameters * mp)\n   {\n      int numpoints = 0;\n\n      OCCGeometry * occgeom = (OCCGeometry*)geom;\n      Mesh * me = (Mesh*)mesh;\n      me->SetGeometry( shared_ptr<NetgenGeometry>(occgeom, &NOOP_Deleter) );\n\n      // Set the internal meshing parameters structure from the nglib meshing\n      // parameters structure\n      mp->Transfer_Parameters();\n\n      numpoints = me->GetNP();\n\n      // Initially set up only for surface meshing without any optimisation\n      // int perfstepsend = MESHCONST_MESHSURFACE;\n\n      // Check and if required, enable surface mesh optimisation step\n      /*\n      if(mp->optsurfmeshenable)\n      {\n        perfstepsend = MESHCONST_OPTSURFACE;\n      }\n      */\n\n      occgeom->MeshSurface(*me, mparam);\n      occgeom->OptimizeSurface(*me, mparam);\n\n      me->CalcSurfacesOfNode();\n\n      if(me->GetNP() <= numpoints)\n         return NG_ERROR;\n\n      if(me->GetNSE() <= 0)\n         return NG_ERROR;\n\n      return NG_OK;\n   }\n\n\n\n\n   // Extract the face map from the OCC geometry\n   // The face map basically gives an index to each face in the geometry,\n   // which can be used to access a specific face\n   NGLIB_API Ng_Result Ng_OCC_GetFMap(Ng_OCC_Geometry * geom,\n                                       Ng_OCC_TopTools_IndexedMapOfShape * FMap)\n   {\n      OCCGeometry* occgeom = (OCCGeometry*)geom;\n      TopTools_IndexedMapOfShape *occfmap = (TopTools_IndexedMapOfShape *)FMap;\n\n      // Copy the face map from the geometry to the given variable\n      occfmap->Assign(occgeom->fmap);\n\n      if(occfmap->Extent())\n      {\n         return NG_OK;\n      }\n      else\n      {\n         return NG_ERROR;\n      }\n   }\n\n   // ------------------ End - OCC Geometry / Meshing Utility Functions ----------------\n\n   NGLIB_API void Ng_OCC_Generate_SecondOrder (Ng_OCC_Geometry * geom,\n                  Ng_Mesh * mesh)\n   {\n      ((OCCGeometry*)geom )->GetRefinement().MakeSecondOrder(*(Mesh*) mesh);\n   }\n\n   NGLIB_API void Ng_OCC_Uniform_Refinement (Ng_OCC_Geometry * geom,\n      Ng_Mesh * mesh)\n   {\n      ( (OCCGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh );\n   }\n\n} // namespace nglib\n"
  },
  {
    "path": "nglib/nglib_occ.h",
    "content": "#ifndef NGLIB_OCC_HPP_INCLUDED\n#define NGLIB_OCC_HPP_INCLUDED\n\n/// Data type for NETGEN OpenCascade geometry\ntypedef void * Ng_OCC_Geometry;\ntypedef void * Ng_OCC_TopTools_IndexedMapOfShape;\n\n// **********************************************************\n// **   OpenCascade Geometry / Meshing Utilities           **\n// **********************************************************\n\n// Create new OCC Geometry Object\nNGLIB_API Ng_OCC_Geometry * Ng_OCC_NewGeometry ();\n\n// Delete an OCC Geometry Object\nNGLIB_API Ng_Result Ng_OCC_DeleteGeometry (Ng_OCC_Geometry * geom);\n\n// Loads geometry from STEP file\nNGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_STEP (const char * filename);\n\n// Loads geometry from IGES file\nNGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_IGES (const char * filename);\n\n// Loads geometry from BREP file\nNGLIB_API Ng_OCC_Geometry * Ng_OCC_Load_BREP (const char * filename);\n\n// Set the local mesh size based on geometry / topology\nNGLIB_API Ng_Result Ng_OCC_SetLocalMeshSize (Ng_OCC_Geometry * geom,\n                                              Ng_Mesh * mesh,\n                                              Ng_Meshing_Parameters * mp);\n\n// Mesh the edges and add Face descriptors to prepare for surface meshing\nNGLIB_API Ng_Result Ng_OCC_GenerateEdgeMesh (Ng_OCC_Geometry * geom,\n                                              Ng_Mesh * mesh,\n                                              Ng_Meshing_Parameters * mp);\n\n// Mesh the surfaces of an OCC geometry\nNGLIB_API Ng_Result Ng_OCC_GenerateSurfaceMesh (Ng_OCC_Geometry * geom,\n                                                 Ng_Mesh * mesh,\n                                                 Ng_Meshing_Parameters * mp);\n\n// Get the face map of an already loaded OCC geometry\nNGLIB_API Ng_Result Ng_OCC_GetFMap(Ng_OCC_Geometry * geom,\n                                    Ng_OCC_TopTools_IndexedMapOfShape * FMap);\n\nNGLIB_API void Ng_OCC_Uniform_Refinement (Ng_OCC_Geometry * geom,\n\t\t\t\t\t   Ng_Mesh * mesh);\nNGLIB_API void Ng_OCC_Generate_SecondOrder (Ng_OCC_Geometry * geom,\n\t\t\t\t\t   Ng_Mesh * mesh);\n#endif // NGLIB_OCC_HPP_INCLUDED\n"
  },
  {
    "path": "nglib/parallelfunc.cpp",
    "content": "#ifdef PARALLEL\n\n#include \"dlfcn.h\"\n\n\n// #include <mystdlib.h>\n\n#include <meshing.hpp>\n\n// #include <visual.hpp>\n\n\n#include <meshing.hpp>\n\nvoid (*NGS_ParallelRun) (const string & message) = NULL;\n\n\nnamespace netgen\n{\n#include \"../interface/writeuser.hpp\"\n  extern string ngdir;\n}\n\nvoid Parallel_Exit();\n\n\nnamespace netgen {\n  extern AutoPtr<Mesh>  mesh;\n  // extern VisualSceneMesh vsmesh;\n  extern NGLIB_API MeshingParameters mparam;\n}\n\nusing namespace netgen;\nusing netgen::RegisterUserFormats;\n\n\nvoid ParallelRun()\n{   \n  string message;\n  MPI_Status status;\n      \n\n  MPI_Comm_size(MPI_COMM_WORLD, &ntasks);\n  MPI_Comm_rank(MPI_COMM_WORLD, &id);\n\n  while ( true )\n    {\n      message = MyMPI_RecvCmd();\n\n      if ( message.compare(0, 3, \"ngs\") == 0 ) \n        {\n\t  if (NGS_ParallelRun == NULL)\n\t    {\n\t      static int timer = NgProfiler::CreateTimer (\"load shared library ngsolve\");\n\t      NgProfiler::RegionTimer reg (timer);\n  \n\n\t      void * handle = dlopen (\"libngsolve.so\", RTLD_NOW | RTLD_GLOBAL);\n\t      if (!handle)\n\t\t{\n\t\t  cerr << \"cannot load shared library libngsolve.so\" << endl;\n\t\t  exit(1);\n\t\t}\n\t      \n\t      NGS_ParallelRun = (void (*) (const string & message))  dlsym (handle, \"NGS_ParallelRun\");\n\t      \n\t      if (!NGS_ParallelRun)\n\t\t{\n\t\t  cerr << \"cannot bind function NGS_ParallelRun\" << endl;\n\t\t  exit(1);\n\t\t}\n\t    }\n          (*NGS_ParallelRun) (message);\n        }\n      else if ( message == \"mesh\" )\n\t{\n\t  VT_USER_START (\"Mesh::ReceiveParallelMesh\");\n\t  mesh.Reset( new netgen::Mesh);\n\t  mesh->SendRecvMesh();\n\t  VT_USER_END (\"Mesh::ReceiveParallelMesh\");\n\t}\n\n      else if ( message == \"visualize\" )\n\t{\n\t  cout << \"parallel message visualize depreciated\" << endl;\n\t}\n      \n      else if ( message == \"bcastparthread\" )\n\t{\n\t  MyMPI_Bcast (mparam.parthread);\n\t}\n\n      else if ( message ==  \"end\" )\n\t{\n\t  break;\n\t}\n      \n      else\n\t{\n\t  PrintMessage ( 1, \"received unidentified message '\" + message + \"'\\n\");\n\t  break;\n\t}\n      \n    }\n}\n\n#endif\n"
  },
  {
    "path": "py_tutorials/CMakeLists.txt",
    "content": "install( FILES \n        shaft.geo mesh.py exportNeutral.py\n        DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX}/py_tutorials\n        COMPONENT netgen_tutorial\n       )\n"
  },
  {
    "path": "py_tutorials/csg2d.py",
    "content": "from random import random, seed\nfrom ngsolve import Draw, Mesh\n\nimport netgen\nfrom pyngcore import *\nfrom netgen.geom2d import *\n\nseed(4)\n\ng = CSG2d()\nouter = Rectangle((0, 0), (1, 1), \"outer\",\"outer\")\ninner = Solid2d()\n\nfor i in range(30):\n    cx = random()\n    cy = random()\n    r  = 0.03+0.05*random()\n    print(\"Add Circle\", i, cx, cy, r, flush = True)\n    circle = Circle((cx, cy), r, \"circle\"+str(i), \"circle\"+str(i))\n    inner += circle\n    outer -= circle\n\n\ng.Add(inner)\ng.Add(outer)\ngeo = g.GenerateSplineGeometry()\n\nm = geo.GenerateMesh(maxh=0.1)\n\ntry:\n    from ngsolve import Draw, Mesh\n    Draw(geo)\n    mesh = Mesh(m)\n    mesh.Curve(3)\n    Draw(mesh)\nexcept:\n    pass\n"
  },
  {
    "path": "py_tutorials/csg_first_example.py",
    "content": "from netgen.csg import *\nimport netgen.meshing as meshing\n\n#from OpenGL.GL import *\n#from OpenGL.GLU import *\n#from OpenGL.GLUT import *\n\n\n\nsp1 = Sphere (Pnt(0,0,0), 0.2)\nsp2 = Sphere (Pnt(0.5,0,0), 0.2)\nsp3 = Sphere (Pnt(0,0,0.5), 0.2)\nsp4 = Sphere (Pnt(0,0.2,0.7), 0.2)\n\nall = sp1+sp2+sp3+sp4\n\n\ngeom = CSGeometry()\ngeom.Add (all)\n\n\n\n#vis = VS(geom)\n# vis.Draw()\n\n\n#window = 0                                             # glut window number\n#width, height = 500, 500\n\n\n\n#def mydraw():\n#    glViewport(0, 0, width, height);\n#    glMatrixMode(GL_PROJECTION);\n#    glLoadIdentity();\n#    pnear = 0.1;\n#    pfar = 10;\n#    gluPerspective(20.0, 1.0*width / height, pnear, pfar);\n#    glMatrixMode(GL_MODELVIEW);    \n#    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)\n#    glLoadIdentity()\n#    gluLookAt (0, 0, 6, 0, 0, 0, 0, 1, 0);\n##    glBegin(GL_QUADS)\n##    glColor4d(0.0, 1.0, 0.0, 0.0);\n##    glVertex3d(0.0,0.0,0.7)\n##    glVertex3d(1.0,0.0,2.1)\n##    glColor4d(1.0, 1.0, 1.0, 0.0);\n##    glVertex3d(1.0,1.0,0.2)\n##    glVertex3d(0.0,1.0,0.5)\n##    glEnd()\n#    vis.Draw()\n#    glutSwapBuffers()\n\n#glutInit(\"mainwin\")                                   # initialize glut\n#glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)\n#glutInitWindowSize(width, height)                      # set window size\n#glutInitWindowPosition(0, 0)                           # set window position\n#window = glutCreateWindow(b\"ngs\")                      # create window with title\n#glutDisplayFunc(vis.Draw)                                 # set draw function callback\n#glutIdleFunc(mydraw)                                     # draw all the time\n#glutMainLoop()        \n\nparam = meshing.MeshingParameters(maxh=0.2)\nmesh = GenerateMesh (geom, param)\nmesh.Save (\"test.vol\")\n"
  },
  {
    "path": "py_tutorials/cube.geo",
    "content": "#\n## A cube\n#\nalgebraic3d\n\n# cube consisting of 6 planes:\n\nsolid cube = plane (0, 0, 0; 0, 0, -1) \n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\ntlo cube;\n\n"
  },
  {
    "path": "py_tutorials/exportNeutral.py",
    "content": "import sys\n\ndef Export (mesh, filename):\n    \"\"\" export Netgen mesh to neutral format \"\"\"\n    \n    print (\"export mesh in neutral format to file = \", filename)\n\n    f = open (filename, 'w')\n\n    points = mesh.Points()\n    print (len(points), file=f)\n    for p in points:\n        print (p.p[0], p.p[1], p.p[2], file=f)\n\n\n    volels = mesh.Elements3D();\n    print (len(volels), file=f)\n    for el in volels:\n        print (el.index, end=\"   \", file=f)\n        for p in el.points:\n            print (p.nr, end=\" \", file=f)\n        print(file=f)\n\n\n\n\n"
  },
  {
    "path": "py_tutorials/merge.py",
    "content": "from netgen.meshing import *\nfrom netgen.csg import *\n\nfrom ngsolve import ngsglobals\nngsglobals.msg_level = 2\n# generate brick and mesh it\ngeo1 = CSGeometry()\ngeo1.Add (OrthoBrick( Pnt(0,0,0), Pnt(1,1,1) ))\nm1 = geo1.GenerateMesh (maxh=0.1)\nm1.Refine()\n\n# generate sphere and mesh it\ngeo2 = CSGeometry()\ngeo2.Add (Sphere (Pnt(0.5,0.5,0.5), 0.1))\nm2 = geo2.GenerateMesh (maxh=0.05)\nm2.Refine()\nm2.Refine()\n\nprint (\"****************************\")\nprint (\"** merging surface meshes **\")\nprint (\"****************************\")\n\n# create an empty mesh\nmesh = Mesh()\n\n# a face-descriptor stores properties associated with a set of surface elements\n# bc .. boundary condition marker,\n# domin/domout .. domain-number in front/back of surface elements (0 = void),\n# surfnr .. number of the surface described by the face-descriptor\n\nfd_outside = mesh.Add (FaceDescriptor(bc=1,domin=1,surfnr=1))\nfd_inside = mesh.Add (FaceDescriptor(bc=2,domin=2,domout=1,surfnr=2))\n# copy all boundary points from first mesh to new mesh.\n# pmap1 maps point-numbers from old to new mesh\n\npmap1 = { }\nfor e in m1.Elements2D():\n    for v in e.vertices:\n        if (v not in pmap1):\n            pmap1[v] = mesh.Add (m1[v])\n\n\n# copy surface elements from first mesh to new mesh\n# we have to map point-numbers:\n\nfor e in m1.Elements2D():\n    mesh.Add (Element2D (fd_outside, [pmap1[v] for v in e.vertices]))\n\n\n\n# same for the second mesh:\n\npmap2 = { }\nfor e in m2.Elements2D():\n    for v in e.vertices:\n        if (v not in pmap2):\n            pmap2[v] = mesh.Add (m2[v])\n\nfor e in m2.Elements2D():\n    mesh.Add (Element2D (fd_inside, [pmap2[v] for v in e.vertices]))\n\n\nprint (\"******************\")\nprint (\"** merging done **\")\nprint (\"******************\")\n\n\nmesh.GenerateVolumeMesh()\nmesh.Save (\"newmesh.vol\")\n\n    \n"
  },
  {
    "path": "py_tutorials/mesh.py",
    "content": "from netgen.meshing import *\nfrom netgen.csg import *\n\ngeo = CSGeometry(\"shaft.geo\")\n\nparam = MeshingParameters()\nparam.maxh = 10\nprint (param)\n\nm1 = GenerateMesh (geo, param)\nm1.SecondOrder()\n\nimport exportNeutral\nexportNeutral.Export (m1, \"shaft.mesh\")\n\n\n\nSave (m1, \"mesh.vol\", geo)\n\n"
  },
  {
    "path": "py_tutorials/opengl.py",
    "content": "from netgen.csg import *\nimport netgen.meshing as meshing\nimport libvisual\n\nfrom OpenGL.GLUT import *\n\n# import Window class from other file\nfrom opengl_window import Window\n\nsp1 = Sphere (Pnt(0,0,0), 0.2)\nsp2 = Sphere (Pnt(0.5,0,0), 0.2)\nall = sp1+sp2\n\ngeom = CSGeometry()\ngeom.Add (all)\n\nparam = meshing.MeshingParameters()\nparam.maxh = 0.1\nm1 = GenerateMesh (geom, param)\n\nvis = VS(geom)\n\n\n# window callback functions\ndef mydraw():\n    vis.Draw()\n    glutSwapBuffers()\n\ndef mymouse(xold, yold, x, y, mode):\n    MouseMove(vis,xold,yold, x,y, mode)\n\n# init glut and create window\nglutInit(\"mainwin\")\nwin_geom = Window( name=b\"ngs\", drawfunc=mydraw, mousefunc=mymouse)\n\n###########################################\n# press ctrl+c to break loop\nwhile(True):\n    for i in range(10000):\n        glutMainLoopEvent()\n        print('press ctrl+c to create second window!')\n\n###########################################\n# create second window (transformation matrices are shared)\nvismesh = libvisual.meshvis.VS(m1)\ndef mydraw2():\n    vismesh.Draw()\n    glutSwapBuffers()\n\nwin_mesh = Window( name=b\"ngs2\", drawfunc=mydraw2, mousefunc=mymouse)\n\n###########################################\n# press ctrl+c to break loop\ntry:\n    while(True):\n        for i in range(10000):\n            glutMainLoopEvent()\n        print('press ctrl+c to hide/destroy first window!')\nexcept:\n    pass\n\n###########################################\n\n## BREAKS (on numericus) as soon as mouse touches remaining window (\"Error of failed request:  GLXBadContextTag\")\n# glutDestroyWindow(win_geom.handle)\n\n## WORKS\nglutHideWindow(win_geom.handle)\n\ntry:\n    while(True):\n        glutMainLoopEvent()\nexcept:\n    pass\n"
  },
  {
    "path": "py_tutorials/opengl_thread.py",
    "content": "from netgen.csg import *\nimport netgen.meshing as meshing\nimport libvisual\n\nfrom OpenGL.GLUT import *\n\n# import Window class from other file\nfrom opengl_window import Window\n\nsp1 = Sphere (Pnt(0,0,0), 0.2)\nsp2 = Sphere (Pnt(0.5,0,0), 0.2)\n\nall = sp1+sp2\n\ngeom = CSGeometry()\ngeom.Add (all)\n\n\nparam = meshing.MeshingParameters()\nparam.maxh = 0.1\nm1 = GenerateMesh (geom, param)\n\n\nvis = VS(geom)\n\n\n# window callback functions\ndef mydraw():\n    vis.Draw()\n    glutSwapBuffers()\n\ndef mymouse(xold, yold, x, y, mode):\n    MouseMove(vis,xold,yold, x,y, mode)\n\n\n###########################################\nglutInit(\"mainwin\")  \n\n# IMPORTANT: create window in the mainloop - thread!\n\n## not working:\n#win_geom = Window( name=b\"ngs\", drawfunc=mydraw, mousefunc=mymouse)\n\ndef runVisualization():\n## working:\n    win_geom = Window( name=b\"ngs\", drawfunc=mydraw, mousefunc=mymouse)\n    glutMainLoop()\n\n# create thread\nfrom threading import Thread\nthread = Thread(target = runVisualization)        \nthread.start()\nthread.join()\n"
  },
  {
    "path": "py_tutorials/opengl_window.py",
    "content": "from OpenGL.GL import *\nfrom OpenGL.GLU import *\nfrom OpenGL.GLUT import *\n\nclass Window():\n    xold = -1;\n    yold = -1;\n    mode = 'r'\n    modes = {0:'r', 1:'m', 2:'z'}\n    drawfunc = None\n    mousefunc = None\n\n    def draw(self):\n        glutSetWindow(self.handle)\n        self.drawfunc()\n\n    def __init__( self, name=b\"Window\", width=500, height=500, drawfunc=None, mousefunc=None ):\n#        glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS) \n        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)\n        glutInitWindowSize(width, height)                      # set window size\n        glutInitWindowPosition(0, 0)                           # set window position\n        self.handle = glutCreateWindow(b\"ngs\")                      # create window with title\n        glutMotionFunc(self.motionHandler)\n        glutMouseFunc(self.mouseHandler)\n        glutPassiveMotionFunc(self.passiveMotionHandler)\n        glMatrixMode(GL_PROJECTION);\n        glLoadIdentity();\n        pnear = 0.1;\n        pfar = 10;\n        gluPerspective(20.0, 1.0*width / height, pnear, pfar);\n        glViewport(0, 0, width, height);\n        glMatrixMode(GL_MODELVIEW);\n        self.drawfunc = drawfunc\n        self.mousefunc = mousefunc\n        if drawfunc:\n            glutDisplayFunc(self.draw)                               # set draw function callback\n\n    def motionHandler(self, x, y ):\n        self.mousefunc(self.xold,self.yold, x,y, self.mode)  # 'm','z'\n        self.xold = x\n        self.yold = y\n        glutPostRedisplay()\n\n    def passiveMotionHandler(self, x, y ):\n        self.xold = x\n        self.yold = y\n\n    def mouseHandler(self, button, state, x, y ):\n        print(button,state,x,y)\n        if button<3:\n            if state==0:\n                self.mode = self.modes[button]\n            else:\n                self.mode = 'r'\n\n\nglutInit(\"mainwin\")                                   # initialize glut\n"
  },
  {
    "path": "py_tutorials/python_geometry.py",
    "content": "from netgen.occ import *\nfrom netgen.meshing import NetgenGeometry, Mesh as NGMesh\nimport numpy as np\n\n\nclass UnitSphereGeometry(NetgenGeometry):\n    def midpoint(self, newp, p1, p2, secpoint=0.5):\n        p1 = np.array([p1[0], p1[1], p1[2]])\n        p2 = np.array([p2[0], p2[1], p2[2]])\n        p = p1 + secpoint * (p2 - p1)\n        self.project(newp, p)\n\n    def project(self, newp, p):\n        pt = np.array([p[0], p[1], p[2]])\n        pt /= np.linalg.norm(pt)\n        newp[0] = pt[0]\n        newp[1] = pt[1]\n        newp[2] = pt[2]\n\n    def PointBetweenEdge(self, p1, p2, secpoint, surfi1, surfi2, ep1, ep2, newp, newgi):\n        self.midpoint(newp, p1, p2, secpoint)\n\n    def PointBetween(self, p1, p2, secpoint, surfi, gi1, gi2, newp, newgi):\n        self.midpoint(newp, p1, p2, secpoint)\n\n    def ProjectPointGI(self, surfind, p, gi):\n        self.project(p, p)\n        return True\n\n\nm = OCCGeometry(Sphere(Pnt(0, 0, 0), 1)).GenerateMesh()\nmy_geo = UnitSphereGeometry()\nm.SetGeometry(my_geo)\nm.Refine()\nm.Curve(3)\n\nfrom ngsolve import *\n\nmesh = Mesh(m)\nDraw(mesh)\n"
  },
  {
    "path": "py_tutorials/shaft.geo",
    "content": "#\n## Crankshaft\n#\nalgebraic3d\nsolid p1 = plane (0, 0, 0; -1, 0, 0)\n         and plane (10, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, -1, 3)\n           and plane (35, 0, -28; 0, -1, -3)\n           and plane (35, 0, 0; 0, 1, 0)\n           and plane (35, -30, 0; 0, -1, 0)\n           or cylinder (-10, 0, 0; 20, 0, 0; 30)\n           or cylinder (-10, -30, 0; 20, -30, 0; 20)\n         );\nsolid p2 = plane (35, 0, 0; -1, 0, 0)\n         and plane (45, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, -1, 3)\n           and plane (35, 0, -28; 0, -1, -3)\n           and plane (35, 0, 0; 0, 1, 0)\n           and plane (35, -30, 0; 0, -1, 0)\n           or cylinder (30, 0, 0; 50, 0, 0; 30)\n           or cylinder (30, -30, 0; 50, -30, 0; 20)\n         );\nsolid p3 = plane (80, 0, 0; -1, 0, 0)\n         and plane (90, 0, 0; 1, 0, 0)\n         and\n         (     plane (0, 0, 28; 0, 1, 3)\n           and plane (0, 0, -28; 0, 1, -3)\n           and plane (0, 0, 0; 0, -1, 0)\n           and plane (0, 30, 0; 0, 1, 0)\n           or cylinder (70, 0, 0; 100, 0, 0; 30)\n           or cylinder (70, 30, 0; 100, 30, 0; 20)\n         );\nsolid p4 = plane (115, 0, 0; -1, 0, 0)\n         and plane (125, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, 1, 3)\n           and plane (35, 0, -28; 0, 1, -3)\n           and plane (35, 0, 0; 0, -1, 0)\n           and plane (35, 30, 0; 0, 1, 0)\n           or cylinder (110, 0, 0; 130, 0, 0; 30)\n           or cylinder (110, 30, 0;130, 30, 0; 20)\n         );\nsolid sh1 =   cylinder (-50, 0, 0; 10, 0, 0; 15)\n            and plane (-40, 0, 0; -1, 0, 0)\n            and plane (5, 0, 0; 1, 0, 0);\nsolid sh2 =   cylinder (30, 0, 0; 90, 0, 0; 15)\n            and plane (40, 0, 0; -1, 0, 0)\n            and plane (85, 0, 0; 1, 0, 0);\nsolid sh3 =   cylinder (110, 0, 0; 170, 0, 0; 15)\n            and plane (120, 0, 0; -1, 0, 0)\n            and plane (165, 0, 0; 1, 0, 0);\n\nsolid pl1 = cylinder (0, -30, 0; 50, -30, 0; 10)\n            and plane (5, 0, 0; -1, 0, 0)\n            and plane (40, 0, 0; 1, 0, 0);\nsolid pl2 = cylinder (80, 30, 0; 130, 30, 0; 10)\n            and plane (85, 0, 0; -1, 0, 0)\n            and plane (120, 0, 0; 1, 0, 0);\n#\n#\nsolid main = p1 or p2 or p3 or p4 or sh1 or sh2 or sh3 or pl1 or pl2;\n\ntlo main;\n"
  },
  {
    "path": "python/.gitignore",
    "content": "version.py\n"
  },
  {
    "path": "python/CMakeLists.txt",
    "content": "get_target_property(ngcore_compile_definitions ngcore INTERFACE_COMPILE_DEFINITIONS)\nget_property(have_options TARGET ngcore PROPERTY INTERFACE_COMPILE_OPTIONS SET)\nif(have_options)\n    get_target_property(ngcore_compile_options ngcore INTERFACE_COMPILE_OPTIONS)\nendif(have_options)\n\nconfigure_file(config/config_template.py ${CMAKE_CURRENT_BINARY_DIR}/config.py @ONLY)\nconfigure_file(version_template.py ${CMAKE_CURRENT_BINARY_DIR}/version.py @ONLY)\n\ninstall(FILES\n        config/__init__.py\n        config/__main__.py\n        ${CMAKE_CURRENT_BINARY_DIR}/config.py\n        DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX}/config/\n        COMPONENT netgen\n        )\n\ninstall(FILES\n        ${CMAKE_CURRENT_BINARY_DIR}/version.py\n        __main__.py __init__.py\n        meshing.py csg.py geom2d.py stl.py gui.py NgOCC.py occ.py\n        read_gmsh.py read_meshio.py\n        webgui.py\n        DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX}\n        COMPONENT netgen\n        )\n\ninstall(FILES\n        pyngcore/__init__.py\n        DESTINATION ${NG_INSTALL_DIR_PYTHON}/pyngcore\n        COMPONENT netgen\n        )\n\n# build stub files for pybind11 packages\nif(BUILD_STUB_FILES)\nexecute_process(COMMAND ${Python3_EXECUTABLE} -c \"from importlib.metadata import version; print(version('pybind11-stubgen'))\" OUTPUT_VARIABLE stubgen_version RESULT_VARIABLE pybind11_stubgen)\nif(pybind11_stubgen AND NOT ${pybind11_stubgen} EQUAL 0)\n  message(WARNING \"pybind11-stubgen not found, if you want to create stub files\nfor better autocompletion support install it with pip.\")\nelse()\n  if(stubgen_version LESS \"1.0\")\n    message(WARNING \"pybind11-stubgen version is too old, if you want to create stub files for better autocompletion support upgrade it with pip.\")\n  else()\n  message(\"-- Found pybind11-stubgen version: ${stubgen_version}\")\n  install(CODE \"\\\n  set(ENV{PYTHONPATH} ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_PYTHON})\\n \\\n  execute_process(COMMAND ${Python3_EXECUTABLE} -m pybind11_stubgen --ignore-all-errors netgen)\\n \\\n  execute_process(COMMAND ${Python3_EXECUTABLE} -m pybind11_stubgen --ignore-all-errors pyngcore)\\n \\\n  \")\n  install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../stubs/ DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)\n  endif()\nendif()\nendif(BUILD_STUB_FILES)\n"
  },
  {
    "path": "python/NgOCC.py",
    "content": "\nimport logging\nlogger = logging.getLogger(__name__)\n\nlogger.warning(\"This module is deprecated and just a wrapper for netgen.occ, import netgen.occ instead\")\n\nfrom .occ import *\n"
  },
  {
    "path": "python/__init__.py",
    "content": "import os\nimport sys\nfrom pathlib import Path\n\nfrom . import config\n_netgen_bin_dir=os.path.realpath(os.path.join(os.path.dirname(__file__),'..',config.NETGEN_PYTHON_RPATH_BIN))\n_netgen_lib_dir=os.path.realpath(os.path.join(os.path.dirname(__file__),'..',config.NETGEN_PYTHON_RPATH))\n\ndef load_occ_libs():\n    try:\n        try:\n            import importlib.metadata as metadata\n        except ImportError:\n            import importlib_metadata as metadata\n        import ctypes\n        metadata.metadata('netgen-occt')\n        lib_names = [\n            \"TKOffset\",\n            \"TKFillet\",\n            \"TKDEIGES\",\n            \"TKBool\",\n            \"TKDESTEP\",\n            \"TKXSBase\",\n            \"TKDESTL\",\n            \"TKXCAF\",\n            \"TKVCAF\",\n            \"TKCAF\",\n            \"TKBO\",\n            \"TKPrim\",\n            \"TKLCAF\",\n            \"TKCDF\",\n            \"TKV3d\",\n            \"TKHLR\",\n            \"TKMesh\",\n            \"TKService\",\n            \"TKShHealing\",\n            \"TKTopAlgo\",\n            \"TKGeomAlgo\",\n            \"TKBRep\",\n            \"TKGeomBase\",\n            \"TKG3d\",\n            \"TKG2d\",\n            \"TKMath\",\n            \"TKDE\",\n            \"TKernel\",\n        ]\n        lib_names.reverse()\n        lib_paths = {}\n        for f in metadata.files('netgen-occt'):\n            if f.match('*libTK*') or f.match(\"*.dll\"):\n                p = f.locate()\n                name = p.name.split('.')[0].lower().replace(\"lib\",\"\")\n                lib_paths[name] = str(p)\n        for lib_name in lib_names:\n            p = lib_paths[lib_name.lower()]\n            ctypes.CDLL(p, mode=ctypes.RTLD_GLOBAL)\n\n    except metadata.PackageNotFoundError:\n        pass\n\nload_occ_libs()\n\n__diagnostics_template = \"\"\"\nNetgen diagnostics:\n    sys.platform:          {sys.platform}\n    sys.executable:        {sys.executable}\n    sys.version:           {sys.version}\n    Netgen python version: {config.PYTHON_VERSION}\n    Netgen path            {__file__}\n    Netgen config          {config.__file__}\n    Netgen version         {config.NETGEN_VERSION}\n    sys.path: {sys.path}\n\"\"\"\n\ndef _get_diagnostics():\n    return __diagnostics_template.format(sys=sys, config=config, __file__=__file__)\n\n# compare compile-time and run-time python version\ndef _check_python_version():\n    sys_version = f\"{sys.version_info.major}.{sys.version_info.minor}\"\n    compile_version = f\"{config.PYTHON_VERSION_MAJOR}.{config.PYTHON_VERSION_MINOR}\"\n\n    if sys_version != compile_version:\n        print(_get_diagnostics(), file=sys.stderr)\n        raise RuntimeError(f\"Python version mismatch: compile-time version is {compile_version}, run-time version is {sys_version}\")\n\n_check_python_version()\n\nif sys.platform.startswith('win'):\n    v = sys.version_info\n    if v.major == 3 and v.minor >= 8:\n        os.add_dll_directory(_netgen_bin_dir)\n    os.environ['PATH'] += ';'+_netgen_bin_dir\n\ndel sys\ndel os\n\nfrom pyngcore import Timer\nfrom . import libngpy\n\nfrom netgen.libngpy._meshing import _Redraw\n\ndef Redraw(*args, **kwargs):\n    return _Redraw(*args, **kwargs)\n\ndef TimeFunction(func, name=None):\n    name = name or func.__qualname__\n    timer = Timer(name)\n    def retfunc(*args,**kwargs):\n        with timer:\n            ret = func(*args, **kwargs)\n        return ret\n    return retfunc\n\n"
  },
  {
    "path": "python/__main__.py",
    "content": "import importlib.util, threading, sys, os\n\ndef _py_handler(f):\n    spec = importlib.util.spec_from_file_location(os.path.basename(f), os.path.abspath(f))\n    module = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(module)\n    return module\n\ndef _geo_handler(f):\n    from netgen.csg import CSGeometry\n    print(\"load\", f)\n    geo = CSGeometry(f)\n    geo.Draw()\n\ndef _step_handler(f):\n    from netgen.occ import OCCGeometry\n    print(\"load\", f)\n    geo = OCCGeometry(f)\n    geo.Draw()\n\ndef _stl_handler(f):\n    from netgen.stl import STLGeometry\n    print(\"load\", f)\n    geo = STLGeometry(f)\n    geo.Draw()\n\n_file_handler = {}\n_file_handler['.py'] = _py_handler\n_file_handler['.geo'] = _geo_handler\n_file_handler['.step'] = _step_handler\n_file_handler['.stl'] = _stl_handler\n\ndef handle_arguments():\n    import __main__\n    import os.path\n    argv = sys.argv\n    if len(argv)>1:\n      _, ext = os.path.splitext(argv[1])\n      if ext in _file_handler:\n          _file_handler[ext](argv[1])\n\ndef main():\n    import netgen\n    # Use Redraw without event handling\n    netgen.Redraw = netgen._Redraw\n\n    from .gui import win\n    th = threading.Thread(target=handle_arguments)\n    th.start()\n    win.tk.mainloop()\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "python/config/__init__.py",
    "content": "from .config import *\n"
  },
  {
    "path": "python/config/__main__.py",
    "content": "from .config import get_cmake_dir\n\nif __name__ == '__main__':\n    print(get_cmake_dir())\n"
  },
  {
    "path": "python/config/config_template.py",
    "content": "def _cmake_to_bool(s):\n    return s.upper() not in ['', '0','FALSE','OFF','N','NO','IGNORE','NOTFOUND']\n\nis_python_package    = _cmake_to_bool(\"@SKBUILD@\")\n\nBUILD_FOR_CONDA     = _cmake_to_bool(\"@BUILD_FOR_CONDA@\")\nBUILD_STUB_FILES    = _cmake_to_bool(\"@BUILD_STUB_FILES@\")\nCHECK_RANGE         = _cmake_to_bool(\"@CHECK_RANGE@\")\nDEBUG_LOG           = _cmake_to_bool(\"@DEBUG_LOG@\")\nENABLE_CPP_CORE_GUIDELINES_CHECK  = _cmake_to_bool(\"@ENABLE_CPP_CORE_GUIDELINES_CHECK@\")\nENABLE_UNIT_TESTS   = _cmake_to_bool(\"@ENABLE_UNIT_TESTS@\")\nINSTALL_PROFILES    = _cmake_to_bool(\"@INSTALL_PROFILES@\")\nINTEL_MIC           = _cmake_to_bool(\"@INTEL_MIC@\")\nTRACE_MEMORY        = _cmake_to_bool(\"@TRACE_MEMORY@\")\nUSE_CCACHE          = _cmake_to_bool(\"@USE_CCACHE@\")\nUSE_CGNS            = _cmake_to_bool(\"@USE_CGNS@\")\nUSE_GUI             = _cmake_to_bool(\"@USE_GUI@\")\nUSE_INTERNAL_TCL    = _cmake_to_bool(\"@USE_INTERNAL_TCL@\")\nUSE_JPEG            = _cmake_to_bool(\"@USE_JPEG@\")\nUSE_MPEG            = _cmake_to_bool(\"@USE_MPEG@\")\nUSE_MPI             = _cmake_to_bool(\"@USE_MPI@\")\nUSE_MPI4PY          = _cmake_to_bool(\"@USE_MPI4PY@\")\nUSE_NATIVE_ARCH     = _cmake_to_bool(\"@USE_NATIVE_ARCH@\")\nUSE_NUMA            = _cmake_to_bool(\"@USE_NUMA@\")\nUSE_OCC             = _cmake_to_bool(\"@USE_OCC@\")\nUSE_PYTHON          = _cmake_to_bool(\"@USE_PYTHON@\")\nUSE_SPDLOG          = _cmake_to_bool(\"@USE_SPDLOG@\")\n\nCMAKE_INSTALL_PREFIX  = \"@CMAKE_INSTALL_PREFIX@\"\nNG_INSTALL_DIR_PYTHON   = \"@NG_INSTALL_DIR_PYTHON@\"\nNG_INSTALL_DIR_BIN      = \"@NG_INSTALL_DIR_BIN@\"\nNG_INSTALL_DIR_LIB      = \"@NG_INSTALL_DIR_LIB@\"\nNG_INSTALL_DIR_INCLUDE  = \"@NG_INSTALL_DIR_INCLUDE@\"\nNG_INSTALL_DIR_CMAKE    = \"@NG_INSTALL_DIR_CMAKE@\"\nNG_INSTALL_DIR_RES      = \"@NG_INSTALL_DIR_RES@\"\n\nNETGEN_PYTHON_RPATH_BIN = \"@NETGEN_PYTHON_RPATH_BIN@\"\nNETGEN_PYTHON_RPATH     = \"@NETGEN_PYTHON_RPATH@\"\nNETGEN_PYTHON_PACKAGE_NAME = \"@NETGEN_PYTHON_PACKAGE_NAME@\"\n\nNG_COMPILE_FLAGS           = \"@NG_COMPILE_FLAGS@\"\nngcore_compile_options     = \"@ngcore_compile_options@\"\nngcore_compile_definitions = \"@ngcore_compile_definitions@\"\n\nNETGEN_VERSION = \"@NETGEN_VERSION@\"\nNETGEN_VERSION_GIT = \"@git_version_string@\"\nNETGEN_VERSION_PYTHON = \"@NETGEN_VERSION_PYTHON@\"\n\nNETGEN_VERSION_MAJOR = \"@NETGEN_VERSION_MAJOR@\"\nNETGEN_VERSION_MINOR = \"@NETGEN_VERSION_MINOR@\"\nNETGEN_VERSION_TWEAK = \"@NETGEN_VERSION_TWEAK@\"\nNETGEN_VERSION_PATCH = \"@NETGEN_VERSION_PATCH@\"\nNETGEN_VERSION_HASH = \"@NETGEN_VERSION_HASH@\"\n\nPYTHON_VERSION       = \"@Python3_VERSION@\"\nPYTHON_VERSION_MAJOR = \"@Python3_VERSION_MAJOR@\"\nPYTHON_VERSION_MINOR = \"@Python3_VERSION_MINOR@\"\n\nversion = NETGEN_VERSION_GIT\n\ndef get_cmake_dir():\n    import os.path as p\n    d_python = p.dirname(p.dirname(p.dirname(__file__)))\n    py_to_cmake = p.relpath(\n            NG_INSTALL_DIR_CMAKE,\n            NG_INSTALL_DIR_PYTHON\n            )\n    return p.normpath(p.join(d_python,py_to_cmake))\n"
  },
  {
    "path": "python/csg.py",
    "content": "from .libngpy._csg import *\nfrom .libngpy._meshing import Pnt, Vec, Trafo\nfrom .meshing import meshsize\n\ntry:\n    from . import csgvis\n    from .csgvis import MouseMove\n    CSGeometry.VS = csgvis.VS\n    SetBackGroundColor = csgvis.SetBackGroundColor\n    del csgvis\n\n    def VS (obj):\n        return obj.VS()\nexcept:\n    pass\n\nunit_cube = CSGeometry()\np1 = Plane(Pnt(0,0,0),Vec(-1,0,0)).bc(\"back\")\np2 = Plane(Pnt(1,1,1),Vec(1,0,0)).bc(\"front\")\np3 = Plane(Pnt(0,0,0),Vec(0,-1,0)).bc(\"left\")\np4 = Plane(Pnt(1,1,1),Vec(0,1,0)).bc(\"right\")\np5 = Plane(Pnt(0,0,0),Vec(0,0,-1)).bc(\"bottom\")\np6 = Plane(Pnt(1,1,1),Vec(0,0,1)).bc(\"top\")\nunit_cube.Add (p1*p2*p3*p4*p5*p6, col=(0,0,1))\n\n"
  },
  {
    "path": "python/gengeom.py",
    "content": "\r\ngeom = SplineGeometry()\r\n\r\n# Define Points\r\npi1 = geom.AppendPoint(0,0)\r\npi2 = geom.AppendPoint(1,0)\r\npi3 = geom.AppendPoint(1,1)\r\npi4 = geom.AppendPoint(0,1)\r\n\r\n# Define Segments\r\ngeom.AppendSegment([pi1,pi2])\r\ngeom.AppendSegment([pi2,pi3])\r\ngeom.AppendSegment([pi3,pi4])\r\ngeom.AppendSegment([pi4,pi1])\r\n\r\n# Plot Geometry\r\ngeom.Plot()\r\n\r\n# Plot Point Index\r\ngeom.ShowPoints()\r\n# Plot Domain Numbers\r\ngeom.ShowDomains()\r\n\r\n# Set Meshing Parameters\r\nmparam = MeshingParameters()\r\nmparam.maxh = 0.1\r\n\r\nmesh = geom.GenerateMesh(mparam)"
  },
  {
    "path": "python/gengeom_curve.py",
    "content": "\r\ngeom = SplineGeometry()\r\n\r\n# Define Points\r\npi1 = geom.AppendPoint(0,0)\r\npi2 = geom.AppendPoint(1,0)\r\npi3 = geom.AppendPoint(1,0.5)\r\npi4 = geom.AppendPoint(1,1)\r\npi5 = geom.AppendPoint(0.5,1)\r\npi6 = geom.AppendPoint(0,1)\r\n\r\n# Define Segments\r\ngeom.Append(Line(pi1,pi2))\r\ngeom.Append(Line(pi2,pi3))\r\ngeom.Append(Spline3(pi3,pi4,pi5))\r\ngeom.Append(Line(pi5,pi6))\r\ngeom.Append(Line(pi6,pi1))\r\n\r\n# Plot Geometry\r\ngeom.Plot()\r\n\r\n# Plot Point Index\r\ngeom.ShowPoints()\r\n# Plot Domain Numbers\r\ngeom.ShowDomains()\r\n\r\n# Hide point indices and domain numbers\r\ngeom.ShowPoints(False)\r\ngeom.ShowDomains(False)\r\n\r\n# Set Meshing Parameters\r\nmparam = MeshingParameters()\r\nmparam.maxh = 0.1\r\n\r\nmesh = geom.GenerateMesh(mparam)"
  },
  {
    "path": "python/geom2d.py",
    "content": "from .libngpy._geom2d import SplineGeometry, Solid2d, CSG2d, Rectangle, Circle, EdgeInfo, PointInfo\nfrom .meshing import meshsize\nimport math as math\n\nunit_square = SplineGeometry()\n_pnts = [ (0,0), (1,0), (1,1), (0,1) ]\n_lines = [ (0,1,1,\"bottom\"), (1,2,2,\"right\"), (2,3,3,\"top\"), (3,0,4,\"left\") ]\n_pnums = [unit_square.AppendPoint(*p) for p in _pnts]\nfor l1,l2,bc,bcname in _lines:\n    unit_square.Append( [\"line\", _pnums[l1], _pnums[l2]], bc=bcname)\n\n\ndef MakeRectangle (geo, p1, p2, bc=None, bcs=None, **args):\n    p1x, p1y = p1\n    p2x, p2y = p2\n    p1x,p2x = min(p1x,p2x), max(p1x, p2x)\n    p1y,p2y = min(p1y,p2y), max(p1y, p2y)\n    if not bcs: bcs=4*[bc]\n    pts = [geo.AppendPoint(*p) for p in [(p1x,p1y), (p2x, p1y), (p2x, p2y), (p1x, p2y)]]\n    for p1,p2,bc in [(0,1,bcs[0]), (1, 2, bcs[1]), (2, 3, bcs[2]), (3, 0, bcs[3])]:\n        geo.Append( [\"line\", pts[p1], pts[p2]], bc=bc, **args)\n\ndef MakeCircle (geo, c, r, **args):\n    cx,cy = c\n    pts = [geo.AppendPoint(*p) for p in [(cx,cy-r), (cx+r,cy-r), (cx+r,cy), (cx+r,cy+r), \\\n                                         (cx,cy+r), (cx-r,cy+r), (cx-r,cy), (cx-r,cy-r)]]\n    for p1,p2,p3 in [(0,1,2), (2,3,4), (4, 5, 6), (6, 7, 0)]:\n        geo.Append( [\"spline3\", pts[p1], pts[p2], pts[p3]], **args)\n\n    \n\ndef CreatePML(geo, pml_size, tol=1e-12):\n    \"\"\"Create a pml layer around the geometry. This function works only on convex geometries and\nthe highest existing domain number must be named by using the function geo.SetMaterial(domnr, name).\nPoints in the geometry are assumed to be the same if (pt1 - pt2).Norm() < tol.\nReturned is a dict with information to create the pml layer:\n  normals: A dict from the names of the linear pml domains to the normal vectors pointing inside the pml.\"\"\"\n\n    def Start(spline):\n        if spline.rightdom == 0:\n            return spline.StartPoint()\n        return spline.EndPoint()\n    def End(spline):\n        if spline.rightdom == 0:\n            return spline.EndPoint()\n        return spline.StartPoint()\n\n    splines = []\n    for i in range(geo.GetNSplines()):\n        splines.append(geo.GetSpline(i))\n    border = []\n    is_closed = False\n    current_endpoint = None\n    while not is_closed:\n        for spline in splines:\n            if spline.leftdom == 0 or spline.rightdom == 0:\n                if current_endpoint is not None:\n                    if (Start(spline)-current_endpoint).Norm() < tol:\n                        border.append(spline)\n                        current_endpoint = End(spline)\n                        if (current_endpoint - startpoint).Norm() < tol:\n                            is_closed = True\n                        break\n                else:\n                    startpoint = Start(spline)\n                    current_endpoint = End(spline)\n                    border.append(spline)\n                    break\n        else:\n            raise Exception(\"Couldn't find closed spline around domain\")\n    endpointindex_map = []\n    for spline in border:\n        pnt = End(spline)\n        for i in range(geo.GetNPoints()):\n            if (pnt - geo.GetPoint(i)).Norm() < tol:\n                endpointindex_map.append(i)\n                break\n        else:\n            raise Exception(\"Couldn't find endpoint of spline in geometry\")\n    start_ndoms = ndoms = geo.GetNDomains() + 1\n    new_spline_domains = []\n    normals = {}\n    duplicate_cnt = 0\n\n    for i, spline in enumerate(border):\n        if i == 0:\n            global_start = Start(spline) + pml_size * spline.GetNormal(0)\n            global_start_pnt = current_start = geo.AppendPoint(global_start[0], global_start[1])\n        next_spline = border[(i+1)%len(border)]\n        new_end =  End(spline) + pml_size * spline.GetNormal(1)\n        spline_name = geo.GetBCName(spline.bc)\n\n        if \"pml_\" + spline_name in normals \\\n        and normals[\"pml_\" + spline_name] != spline.GetNormal(0):\n            duplicate_cnt += 1\n            spline_name = spline_name + \"_duplicate_\" + str(duplicate_cnt)\n\n        if (new_end - global_start).Norm() < tol:\n            new_spline_domains.append(ndoms)\n            geo.Append([\"line\", current_start, global_start_pnt], bc=\"outer_\" + spline_name, leftdomain = ndoms)\n            geo.Append([\"line\", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms)\n            geo.SetMaterial(ndoms, \"pml_\" + spline_name)\n            normals[\"pml_\" + spline_name] = spline.GetNormal(0)\n            ndoms += 1\n            break\n        end = geo.AppendPoint(new_end[0], new_end[1])\n        new_spline_domains.append(ndoms)\n        geo.Append([\"line\", current_start, end], bc=\"outer_\" + spline_name, leftdomain = ndoms)\n        geo.Append([\"line\", end, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1)\n        geo.SetMaterial(ndoms, \"pml_\" + spline_name)\n        normals[\"pml_\" + spline_name] = spline.GetNormal(0)\n        ndoms += 1\n        new_start = Start(next_spline) + pml_size * next_spline.GetNormal(0)\n        if (new_start - global_start).Norm() < tol:\n            geo.Append([\"line\", end, global_start_pnt], bc=\"outer\", leftdomain = ndoms)\n            geo.Append([\"line\", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms)\n            geo.SetMaterial(ndoms, \"pml_corner\")\n            ndoms += 1\n            break\n        if (new_end - new_start).Norm() < tol:\n            current_start = end\n        else:\n            current_start = geo.AppendPoint(new_start[0], new_start[1])\n            geo.Append([\"line\", end, current_start], bc=\"outer\", leftdomain = ndoms)\n            geo.Append([\"line\", current_start, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1)\n            geo.SetMaterial(ndoms, \"pml_corner\")\n            ndoms += 1\n    for spline, domnr in zip(border, new_spline_domains):\n        if spline.leftdom == 0:\n            spline.leftdom = domnr\n        else:\n            spline.rightdom = domnr\n    return {\"normals\" : normals}\n\nSplineGeometry.AddCircle = lambda geo, c, r, **args : MakeCircle(geo, c, r, **args)\nSplineGeometry.AddRectangle = lambda geo, p1, p2, **args : MakeRectangle(geo, p1, p2, **args)\nSplineGeometry.AddSegment = lambda *args, **kwargs : SplineGeometry.Append(*args, **kwargs)\nSplineGeometry.AddPoint = lambda *args, **kwargs : SplineGeometry.AppendPoint(*args, **kwargs)\nSplineGeometry.CreatePML = CreatePML\n\nbc = lambda s : EdgeInfo(bc=s)\nmaxh = lambda h : EdgeInfo(maxh=h)\ndef cp(p_or_px, py_or_none = None):\n    if py_or_none is None:\n        return EdgeInfo(control_point=p)\n    else:\n        return EdgeInfo(control_point=(p_or_px,py_or_none))\n\n\ndef Ellipse(center, a, b, bc=\"ellipse\", mat=\"ellipse\"):\n    \"\"\"Creates ellipse centered at point center with principle axis a and b.\n\n    Parameters\n    ---------\n    center : Vec2\n      center of ellipse\n    a : Vec2\n      first principle axis, needs to be perpendicular to b\n    b : Vec2\n      second principle axis, needs to be perpendicular to a\n    bc : string\n      boundary name\n    mat : string\n      material name\n    \"\"\"\n    if abs(a[0]*b[0] + a[1]*b[1]) > 1e-12:\n        raise Exception(\"In Ellipse: principle axis a and b are not perpendicular\")\n    \n    ellipse = Circle( center=(0,0), radius=1.0, mat=mat, bc=bc )\n    \n    alpha = math.pi/2-math.atan2(a[0],a[1])\n    r_a = math.sqrt(a[0]**2+a[1]**2)\n    r_b = math.sqrt(b[0]**2+b[1]**2)\n    ellipse.Scale( (r_a,r_b) )\n    ellipse.Rotate( alpha/math.pi*180, center=(0,0) )\n    ellipse.Move( center )\n    \n    return ellipse\n"
  },
  {
    "path": "python/gui.py",
    "content": "import netgen\n\nfrom . import libngguipy\nfrom . import libngpy\n\ndef StartGUI():\n    from tkinter import Tk\n    from netgen import config\n    import sys, os\n\n    try:\n        # the GUI tries to load ngsolve.tcl (which loads ngsolve shared libraries)\n        # BUT might fail to load dependencies (like mkl), these are handled by the\n        # ngsolve __init__.py script, so import ngsolve from python already here\n        import ngsolve\n    except:\n        pass\n\n    global win\n    win = Tk()\n    win.tk.eval('lappend ::auto_path ' + netgen._netgen_lib_dir)\n    win.tk.eval('lappend ::auto_path ' + netgen._netgen_bin_dir)\n    # load with absolute path to avoid issues on MacOS\n    win.tk.eval('load \"'+netgen._netgen_lib_dir.replace('\\\\','/')+'/libnggui[info sharedlibextension]\" gui')\n\n    if config.is_python_package and 'darwin' in sys.platform:\n        # libngsolve and other libraries are installed into netgen python dir to keep relative installation paths, but tcl won't find them there automatically\n        netgen_dir = os.path.abspath(os.path.dirname(netgen.__file__))\n        win.tk.eval(f'set netgen_library_dir {netgen_dir}')\n\n    win.tk.eval( netgen.libngpy._meshing._ngscript)\n\n    try:\n        from IPython import get_ipython\n        ipython = get_ipython()\n        ipython.magic('gui tk')\n    except:\n        pass\n\n    def _Redraw(*args, **kwargs):\n        if libngpy._meshing._Redraw(*args, **kwargs):\n            import netgen\n            import tkinter\n            cnt = 0\n            while(win.tk.dooneevent(tkinter._tkinter.DONT_WAIT) and cnt < 100):\n                cnt += 1\n\n    netgen._Redraw = _Redraw\n    _Redraw(blocking=True)\n\n    \n\ndef Snapshot(w,h, filename=None):\n    netgen.Redraw(blocking=True)\n    import numpy\n    image = netgen.libngguipy.Snapshot(w, h)\n    image = numpy.array(image, dtype=numpy.uint8).reshape(h, w, 3)\n    image = image[::-1,:,:]\n    if filename:\n        import PIL.Image\n        im = PIL.Image.fromarray(image)\n        im.save(filename)\n    return image\n\ndef run_pyfile(filename):\n    with open(filename) as f:\n        exec(f.read(), {})\n\nif __name__ == \"__main__\":\n    import sys, threading\n    StartGUI()\n    if(len(sys.argv) > 1):\n        if(sys.argv[1].endswith(\".py\")):\n            t = threading.Thread(target=run_pyfile, args=(sys.argv[1],),\n                                 daemon=True)\n            t.start()\n    win.mainloop()\nelse:\n    if not netgen.libngpy._meshing._netgen_executable_started:\n        import os\n        if not \"NETGEN_DOCUMENTATION_RST_FORMAT\" in os.environ:\n            StartGUI()\n"
  },
  {
    "path": "python/init_geom2d.py",
    "content": "try:\n\t# Linux\n    from libgeom2d.geom2d import *\nexcept:\n\t# Windows\n    from nglib.geom2d import *\n\nimport matplotlib.pyplot as plt\n\n############################################################################\n\ndef plotgeom(self):\n\tplt.close()\n\tcoords = self.PlotData()\n\tfor i in range(0,len(coords[2])):\n\t\tplt.plot(coords[2][i],coords[3][i],color='b')\n\t\n\tplt.axis('equal')\n\tplt.xlim(coords[0])\n\tplt.ylim(coords[1])\n\tplt.show(block=False)\n\nSplineGeometry.Plot = plotgeom\ndel plotgeom\n\n############################################################################\n\ndef plotpointindex(self,show = True):\n\ttry:\n\t\tself._txt\n\texcept:\n\t\tself._txt = list()\n\tif show:\n\t\tif len(self._txt) == 0:\n\t\t\tpi = self.PointData()\n\t\t\tfor i in range(0,len(pi[0])):\n\t\t\t\tself._txt.append(plt.text(pi[0][i],pi[1][i],str(pi[2][i])))\n\t\t\t\tself._txt.append(plt.plot(pi[0][i],pi[1][i],'ro'))\n\t\telse:\n\t\t\tpass\n\telse:\n\t\tfor i in range(0,len(self._txt)):\n\t\t\ttry:\n\t\t\t\tself._txt[i].remove()\n\t\t\texcept:\n\t\t\t\tself._txt[i][0].remove()\n\t\tself._txt.clear()\n\t#plt.draw()\n\tplt.show(block=False)\n\t\nSplineGeometry.ShowPoints = plotpointindex\ndel plotpointindex\n\n############################################################################\n\ndef plotdomainindex(self, show = True):\n\ttry:\n\t\tself._dom\n\texcept:\n\t\tself._dom = list()\n\tif show:\n\t\tif len(self._dom) == 0:\n\t\t\tsegdata = self.SegmentData()\n\t\t\tfor i in range(0,len(segdata[0])):\n\t\t\t\tif segdata[0][i][2]:\n\t\t\t\t\thorr = 'right'\n\t\t\t\t\thorl = 'left'\n\t\t\t\telse:\n\t\t\t\t\thorr = 'left'\n\t\t\t\t\thorl = 'right'\n\t\t\t\tif segdata[0][i][3]:\n\t\t\t\t\tvertr = 'top'\n\t\t\t\t\tvertl = 'bottom'\n\t\t\t\telse:\n\t\t\t\t\tvertr = 'bottom'\n\t\t\t\t\tvertl = 'top'\n\t\t\t\tself._dom.append(plt.text(segdata[0][i][0],segdata[0][i][1],str(segdata[2][i]),horizontalalignment=horl,verticalalignment=vertl))\n\t\t\t\tself._dom.append(plt.text(segdata[1][i][0],segdata[1][i][1],str(segdata[3][i]),horizontalalignment=horr,verticalalignment=vertr))\n\t\telse:\n\t\t\tpass\n\telse:\n\t\tfor i in range(0,len(self._dom)):\n\t\t\tself._dom[i].remove()\n\t\tself._dom.clear()\n\t#plt.draw()\n\tplt.show(block=False)\n\nSplineGeometry.ShowDomains = plotdomainindex\ndel plotdomainindex\n\t\n############################################################################\n\ndef Line(point_index1,point_index2):\n\treturn [\"line\",point_index1,point_index2]\n\ndef Spline3(point_index1,point_index2,point_index3):\n\treturn [\"spline3\",point_index1,point_index2,point_index3]\n\t\n"
  },
  {
    "path": "python/meshing.py",
    "content": "from .libngpy._meshing import *\nfrom pyngcore import MPI_Comm\n\nclass _MeshsizeObject:\n    @property\n    def very_coarse(self):\n        return MeshingParameters(curvaturesafety=1,\n                                 segmentsperedge=0.3,\n                                 grading=0.7,\n                                 chartdistfac=0.8,\n                                 linelengthfac=0.2,\n                                 closeedgefac=0.5,\n                                 minedgelen=0.002,\n                                 surfmeshcurvfac=1.,\n                                 optsteps3d=5)\n    @property\n    def coarse(self):\n        return MeshingParameters(curvaturesafety=1.5,\n                                 segmentsperedge=0.5,\n                                 grading=0.5,\n                                 chartdistfac=1,\n                                 linelengthfac=0.35,\n                                 closeedgefac=1,\n                                 minedgelen=0.02,\n                                 surfmeshcurvfac=1.5,\n                                 optsteps3d=5)\n    @property\n    def moderate(self):\n        return MeshingParameters(curvaturesafety=2,\n                                 segmentsperedge=1,\n                                 grading=0.3,\n                                 chartdistfac=1.5,\n                                 linelengthfac=0.5,\n                                 closeedgefac=2,\n                                 minedgelen=0.2,\n                                 surfmeshcurvfac=2.,\n                                 optsteps3d=5)\n    @property\n    def fine(self):\n        return MeshingParameters(curvaturesafety=3,\n                                 segmentsperedge=2,\n                                 grading=0.2,\n                                 chartdistfac=2,\n                                 linelengthfac=1.5,\n                                 closeedgefac=3.5,\n                                 minedgelen=1.,\n                                 surfmeshcurvfac=3.,\n                                 optsteps3d=5)\n\n    @property\n    def very_fine(self):\n        return  MeshingParameters(curvaturesafety=5,\n                                  segmentsperedge=3,\n                                  grading=0.1,\n                                  chartdistfac=5,\n                                  linelengthfac=3,\n                                  closeedgefac=5,\n                                  minedgelen=2.,\n                                  surfmeshcurvfac=5.,\n                                  optsteps3d=5)\n\nmeshsize = _MeshsizeObject()\n\n\nclearsol = ClearSolutionClass()\n"
  },
  {
    "path": "python/occ.py",
    "content": "\"\"\" Netgen OCC documentation \n\nThis module provides the Netgen OCCGeometry class, as well as Python wrappers \nfor OpenCascade functionality. This allows the construction from scratch, as well as\nediting geometries imported via STEP format.\n\nMost of the classes are directly py-wrapped from the OCCT classes. \nFor more detailed documentation consult the OCCT docs, a good starting point is\nhttps://dev.opencascade.org/doc/refman/html/class_b_rep_builder_a_p_i___make_shape.html\n\"\"\"\n\nfrom .config import USE_OCC\nif not USE_OCC:\n    raise ImportError(\"Netgen was not built with Opencascade support\")\n\nfrom .libngpy._NgOCC import *\nfrom .meshing import meshsize, IdentificationType\n\n\ngp_Ax3 = Axes\ngp_Ax1 = Axis\n\nTranslation = gp_Trsf.Translation\nRotation = gp_Trsf.Rotation\nMirror = gp_Trsf.Mirror\n\n\ndef Rectangle(l,w): return WorkPlane().Rectangle(l,w)\ndef MoveTo(x,y): return WorkPlane().MoveTo(x,y)\ndef LineTo(x,y): return WorkPlane().LineTo(x,y)\ndef Line(l): return WorkPlane().Line(l)    \n\n\nunit_square_shape = WorkPlane().Line(1, name=\"bottom\").Rotate(90) \\\n  .Line(1, name=\"right\").Rotate(90) \\\n  .Line(1, name=\"top\").Rotate(90) \\\n  .Line(1, name=\"left\").Rotate(90).Face()\n\nunit_square = OCCGeometry(unit_square_shape, dim=2)\n\n\n\nuc_shape = Box((0,0,0),(1,1,1))\nuc_shape.faces.Max(X).name = \"front\"\nuc_shape.faces.Min(X).name = \"back\"\nuc_shape.faces.Max(Y).name = \"right\"\nuc_shape.faces.Min(Y).name = \"left\"\nuc_shape.faces.Max(Z).name = \"top\"\nuc_shape.faces.Min(Z).name = \"bottom\"\n    \nunit_cube = OCCGeometry(uc_shape)\n\n"
  },
  {
    "path": "python/pyngcore/__init__.py",
    "content": "from .pyngcore import *\n"
  },
  {
    "path": "python/read_gmsh.py",
    "content": "from netgen.meshing import *\n\ndef ReadGmsh(filename):\n    if not filename.endswith(\".msh\"):\n        filename += \".msh\"\n    meshdim = 1\n    with open(filename, 'r') as f:\n        while f.readline().split()[0] != \"$Elements\":\n            pass\n        nelem = int(f.readline())\n        for i in range(nelem):\n            line = f.readline()\n            eltype = int(line.split()[1])\n            if eltype > 1 and eltype != 15:\n                meshdim = 2\n            if eltype > 3 and eltype != 15:\n                meshdim = 3\n                break\n\n    f = open(filename, 'r')\n    mesh = Mesh(dim=meshdim)\n\n    pointmap = {}\n    facedescriptormap = {}\n    namemap = { 0 : { 0 : \"default\" },\n                1: { 0 : \"default\" },\n                2: { 0 : \"default\" },\n                3: { 0 : \"default\" } }\n    materialmap = {}\n    bbcmap = {}\n    bbbcmap = {}\n    \n\n    segm = 1\n    trig = 2\n    quad = 3\n    tet = 4\n    hex = 5\n    prism = 6\n    pyramid = 7\n    segm3 = 8      # 2nd order line\n    trig6 = 9      # 2nd order trig\n    tet10 = 11     # 2nd order tet\n    point = 15\n    quad8 = 16     # 2nd order quad\n    hex20 = 17     # 2nd order hex\n    prism15 = 18   # 2nd order prism\n    pyramid13 = 19 # 2nd order pyramid\n    segms = [segm, segm3]\n    trigs = [trig, trig6]\n    quads = [quad, quad8]\n    tets = [tet, tet10]\n    hexes = [hex, hex20]\n    prisms = [prism, prism15]\n    pyramids = [pyramid, pyramid13]\n    elem0d = [point]\n    elem1d = segms\n    elem2d = trigs + quads\n    elem3d = tets + hexes + prisms + pyramids\n\n    num_nodes_map = { segm : 2,\n                      trig : 3,\n                      quad : 4,\n                      tet : 4,\n                      hex : 8,\n                      prism : 6,\n                      pyramid : 5,\n                      segm3 : 3,\n                      trig6 : 6,\n                      tet10 : 10,\n                      point : 1,\n                      quad8 : 8,\n                      hex20 : 20,\n                      prism15 : 18,\n                      pyramid13 : 19 }\n\n    while True:\n        line = f.readline()\n        if line == \"\":\n            break\n\n        if line.split()[0] == \"$PhysicalNames\":\n            print('WARNING: Physical groups detected - Be sure to define them for every geometrical entity.')\n            numnames = int(f.readline())\n            for i in range(numnames):\n                f.readline\n                line = f.readline()\n                namemap[int(line.split()[0])][int(line.split()[1])] = line.split()[2][1:-1]\n\n        if line.split()[0] == \"$Nodes\":\n            num = int(f.readline().split()[0])\n            for i in range(num):\n                line = f.readline()\n                nodenum, x, y, z = line.split()[0:4]\n                pnum = mesh.Add(MeshPoint(Pnt(float(x), float(y), float(z))))\n                pointmap[int(nodenum)] = pnum\n\n        if line.split()[0] == \"$Elements\":\n            num = int(f.readline().split()[0])\n\n            for i in range(num):\n                line = f.readline().split()\n                elmnum = int(line[0])\n                elmtype = int(line[1])\n                numtags = int(line[2])\n                # the first tag is the physical group nr, the second tag is the group nr of the dim\n                tags = [int(line[3 + k]) for k in range(numtags)]\n\n                if elmtype not in num_nodes_map:\n                    raise Exception(\"element type\", elmtype, \"not implemented\")\n                num_nodes = num_nodes_map[elmtype]\n\n                nodenums = line[3 + numtags:3 + numtags + num_nodes]\n                nodenums2 = [pointmap[int(nn)] for nn in nodenums]\n\n\n                if elmtype in elem0d:\n                    if meshdim == 3:\n                        if tags[1] in bbbcmap:\n                            index = bbbcmap[tags[1]]\n                        else:\n                            index = len(bbbcmap) + 1\n                            if len(namemap):\n                                mesh.SetCD3Name(index, namemap[0][tags[0]])\n                            else:\n                                mesh.SetCD3Name(index, \"point\" + str(tags[1]))\n                            bbbcmap[tags[1]] = index\n                    elif meshdim == 2:\n                        if tags[1] in bbcmap:\n                            index = bbcmap[tags[1]]\n                        else:\n                            index = len(bbcmap) + 1\n                            if len(namemap):\n                                mesh.SetCD2Name(index, namemap[0][tags[0]])\n                            else:\n                                mesh.SetCD2Name(index, \"point\" + str(tags[1]))\n                            bbcmap[tags[1]] = index\n                    else:\n                        if tags[1] in facedescriptormap.keys():\n                            index = facedescriptormap[tags[1]]\n                        else:\n                            index = len(facedescriptormap) + 1\n                            fd = FaceDescriptor(bc=index)\n                            if len(namemap):\n                                fd.bcname = namemap[0][tags[0]]\n                            else:\n                                fd.bcname = 'point' + str(tags[1])\n                            mesh.SetBCName(index - 1, fd.bcname)\n                            mesh.Add(fd)\n                            facedescriptormap[tags[1]] = index\n\n                    mesh.Add(Element0D(nodenums2[0], index=index))\n\n                \n                if elmtype in elem1d:\n                    if meshdim == 3:\n                        if tags[1] in bbcmap:\n                            index = bbcmap[tags[1]]\n                        else:\n                            index = len(bbcmap) + 1\n                            if len(namemap):\n                                mesh.SetCD2Name(index, namemap[1][tags[0]])\n                            else:\n                                mesh.SetCD2Name(index, \"line\" + str(tags[1]))\n                            bbcmap[tags[1]] = index\n\n                    elif meshdim == 2:\n                        if tags[1] in facedescriptormap.keys():\n                            index = facedescriptormap[tags[1]]\n                        else:\n                            index = len(facedescriptormap) + 1\n                            fd = FaceDescriptor(bc=index)\n                            if len(namemap):\n                                fd.bcname = namemap[1][tags[0]]\n                            else:\n                                fd.bcname = 'line' + str(tags[1])\n                            mesh.SetBCName(index - 1, fd.bcname)\n                            mesh.Add(fd)\n                            facedescriptormap[tags[1]] = index\n                    else:\n                        if tags[1] in materialmap:\n                            index = materialmap[tags[1]]\n                        else:\n                            index = len(materialmap) + 1\n                            if len(namemap):\n                                mesh.SetMaterial(index, namemap[1][tags[0]])\n                            else:\n                                mesh.SetMaterial(index, \"line\" + str(tags[1]))\n                            materialmap[tags[1]] = index\n\n                    mesh.Add(Element1D(index=index, vertices=nodenums2))\n\n                if elmtype in elem2d:  # 2d elements\n                    if meshdim == 3:\n                        if tags[1] in facedescriptormap.keys():\n                            index = facedescriptormap[tags[1]]\n                        else:\n                            index = len(facedescriptormap) + 1\n                            fd = FaceDescriptor(bc=index)\n                            if len(namemap):\n                                fd.bcname = namemap[2][tags[0]]\n                            else:\n                                fd.bcname = \"surf\" + str(tags[1])\n                            mesh.SetBCName(index - 1, fd.bcname)\n                            mesh.Add(fd)\n                            facedescriptormap[tags[1]] = index\n                    else:\n                        if tags[1] in materialmap:\n                            index = materialmap[tags[1]]\n                        else:\n                            index = len(materialmap) + 1\n                            if len(namemap):\n                                mesh.SetMaterial(index, namemap[2][tags[0]])\n                            else:\n                                mesh.SetMaterial(index, \"surf\" + str(tags[1]))\n                            materialmap[tags[1]] = index\n\n                    if elmtype in trigs:\n                        ordering = [i for i in range(3)]\n                        if elmtype == trig6:\n                            ordering += [4,5,3]\n                    if elmtype in quads:\n                        ordering = [i for i in range(4)]\n                        if elmtype == quad8:\n                            ordering += [4, 6, 7, 5]\n                    mesh.Add(Element2D(index, [nodenums2[i] for i in ordering]))\n\n                if elmtype in elem3d:  # volume elements\n                    if tags[1] in materialmap:\n                        index = materialmap[tags[1]]\n                    else:\n                        index = len(materialmap) + 1\n                        if len(namemap):\n                            mesh.SetMaterial(index, namemap[3][tags[0]])\n                        else:\n                            mesh.SetMaterial(index, \"vol\" + str(tags[1]))\n                        materialmap[tags[1]] = index\n\n                    nodenums2 = [pointmap[int(nn)] for nn in nodenums]\n\n                    if elmtype in tets:\n                        ordering = [0,1,2,3]\n                        if elmtype == tet10:\n                            ordering += [4,6,7,5,9,8]\n                    elif elmtype in hexes:\n                        ordering = [0,1,5,4,3,2,6,7]\n                        if elmtype == hex20:\n                            ordering += [8,16,10,12,13,19,15,14,9,11,18,17]\n                    elif elmtype in prisms:\n                        ordering = [0,2,1,3,5,4]\n                        if elmtype == prism15:\n                            ordering += [7,6,9,8,11,10,13,12,14]\n                    elif elmtype in pyramids:\n                        ordering = [3,2,1,0,4]\n                        if elmtype == pyramid13:\n                            ordering += [10,5,6,8,12,11,9,7]\n                    mesh.Add(Element3D(index, [nodenums2[i] for i in ordering]))\n\n    return mesh\n"
  },
  {
    "path": "python/read_meshio.py",
    "content": "from netgen.meshing import *\n\ndef ReadViaMeshIO(filename):\n    import meshio\n    import numpy as np\n    \n    # print (\"reading via meshio:\", filename)\n\n    m = meshio.read(filename)\n    pts = m.points\n    \n    mesh = Mesh(dim=pts.shape[1])\n    # mesh.AddPoints ( np.asarray(pts, dtype=np.float64) )  # needed for correct little/big endian\n    mesh.AddPoints ( pts )  \n\n    fd = mesh.Add (FaceDescriptor(bc=1))\n    for cb in m.cells:\n        # mesh.AddElements(dim=cb.dim, index=1, data=np.asarray(cb.data, dtype=np.int32), base=0)\n        mesh.AddElements(dim=cb.dim, index=1, data=cb.data, base=0)\n            \n    return mesh\n\n"
  },
  {
    "path": "python/stl.py",
    "content": "from netgen.libngpy._stl import *\nfrom .meshing import meshsize\n"
  },
  {
    "path": "python/version_template.py",
    "content": "__version__ = \"@NETGEN_VERSION_PYTHON@\"\n__package_name__ = \"@NETGEN_PYTHON_PACKAGE_NAME@\"\n"
  },
  {
    "path": "python/webgui.py",
    "content": "import math\nimport numpy as np\nfrom time import time\nimport os\n\ntry:\n    import webgui_jupyter_widgets\n    from webgui_jupyter_widgets import BaseWebGuiScene, WebGuiDocuWidget\n    import webgui_jupyter_widgets.widget as wg\nexcept ImportError:\n    class BaseWebGuiScene:\n        pass\n\n    wg = None\n\ndef encodeData( data, dtype=None, encoding='b64' ):\n    import numpy as np\n    from base64 import b64encode\n    dtype = dtype or data.dtype\n    values = np.array(data.flatten(), dtype=dtype)\n    if encoding=='b64':\n        return b64encode(values).decode(\"ascii\")\n    elif encoding=='binary':\n        return values.tobytes()\n    else:\n        raise RuntimeError(\"unknown encoding\" + str(encoding))\n\nfrom packaging.version import parse\n\nimport netgen.meshing as ng\n\nif wg is not None and parse(webgui_jupyter_widgets.__version__) >= parse(\"0.2.18\"):\n    _default_width = None\n    _default_height = None\nelse:\n    _default_width = \"100%\"\n    _default_height = \"50vh\"\n\n\n_registered_draw_types = {}\n\n\ndef register_draw_type(*types):\n    \"\"\"Decorator to register a drawing handler for one or more types.\n\n    The decorated function is called as ``func(obj, args, kwargs)`` where\n    *obj* is the object passed to :func:`Draw`, *args* are its positional\n    arguments, and *kwargs* is a dict of keyword arguments merged with the\n    default Draw options.  It must return a dict of render data.\n\n    Parameters\n    ----------\n    *types\n        One or more types for which the handler should be invoked.\n\n    Example\n    -------\n    >>> @register_draw_type(MyMesh)\n    ... def draw_my_mesh(obj, args, kwargs):\n    ...     return {\"mesh_dim\": 3, ...}\n    \"\"\"\n    def inner(func):\n        for typ in types:\n            _registered_draw_types[typ] = func\n\n    return inner\n\n\n_bernstein_cache = {}\n\n\ndef GetIBernsteinBasis(etype, order):\n    if (etype, order) in _bernstein_cache:\n        return _bernstein_cache[(etype, order)]\n    bvals = None\n\n    if etype == \"segment\":\n\n        def Binomial(n, i):\n            return math.factorial(n) / math.factorial(i) / math.factorial(n - i)\n\n        def Bernstein(x, i, n):\n            return Binomial(n, i) * x**i * (1 - x) ** (n - i)\n\n        bvals = np.zeros(\n            (order + 1, order + 1), dtype=float\n        )  # .Matrix(order+1,order+1)\n        for i in range(order + 1):\n            for j in range(order + 1):\n                bvals[i, j] = Bernstein(i / order, j, order)\n\n    if etype == \"trig\":\n\n        def BernsteinTrig(x, y, i, j, n):\n            return (\n                math.factorial(n)\n                / math.factorial(i)\n                / math.factorial(j)\n                / math.factorial(n - i - j)\n                * x**i\n                * y**j\n                * (1 - x - y) ** (n - i - j)\n            )\n\n        og = order\n        ndtrig = int((og + 1) * (og + 2) / 2)\n        bvals = np.zeros((ndtrig, ndtrig))\n        ii = 0\n        for ix in range(og + 1):\n            for iy in range(og + 1 - ix):\n                jj = 0\n                for jx in range(og + 1):\n                    for jy in range(og + 1 - jx):\n                        bvals[ii, jj] = BernsteinTrig(ix / og, iy / og, jx, jy, og)\n                        jj += 1\n                ii += 1\n\n    if bvals is None:\n        raise RuntimeError(f\"Unkown element type {etype}\")\n\n    ibvals = _bernstein_cache[(etype, order)] = np.linalg.inv(bvals)\n    return ibvals\n\n\ndef GetWireframePoints(etype, order):\n    n = order\n    if etype == \"trig\":\n        return np.array(\n            [(i / n, 0) for i in range(n + 1)]\n            + [(0, i / n) for i in range(n + 1)]\n            + [(i / n, 1.0 - i / n) for i in range(n + 1)]\n        )\n    if etype == \"quad\":\n        return np.array(\n            [(i / n, 0) for i in range(n + 1)]\n            + [(0, i / n) for i in range(n + 1)]\n            + [(i / n, 1.0) for i in range(n + 1)]\n            + [(1.0, i / n) for i in range(n + 1)]\n        )\n\n    raise RuntimeError(f\"Unknown element type {etype}\")\n\n\ndef GetElementPoints(etype, order):\n    n = order\n    if etype == \"trig\":\n        return np.array(\n            [(i / n, j / n) for j in range(n + 1) for i in range(n + 1 - j)]\n        )\n    if etype == \"quad\":\n        return np.array(\n            [(i / n, j / n) for j in range(n + 1) for i in range(n + 1 - j)]\n            + [(1 - i / n, 1 - j / n) for j in range(n + 1) for i in range(n + 1 - j)]\n        )\n\n    raise RuntimeError(f\"Unknown element type {etype}\")\n\n\ndef MapBernstein(pnts, etype, order):\n    \"\"\"\n    Maps function values at equidistant control points to the Bernstein basis function.\n    Parameters:\n       pnts (numpy.ndarray): The input control points with shape (number_of_elements, points_per_element, function_dimension)\n            point_per_element must be a multiple of the basis size\n       etype (str): Element type (currently ignored and trig assumed)\n       order (int): Polynomial order\n\n    Returns:\n        numpy.ndarray: The mapped points with the shape (points_per_element, number_of_elements, function_dimension)\n    \"\"\"\n    ibvals = GetIBernsteinBasis(etype, order)\n    # for wireframe or subdivided elements, we have multiple point sets per element\n    # so do a reshape to simulate more elements with correct number of control points per element instead\n    if pnts.shape[1] != ibvals.shape[0]:\n        pnts = pnts.reshape((-1, ibvals.shape[0], pnts.shape[2]))\n\n    points = np.zeros(pnts.shape, dtype=np.float32).transpose(1, 0, 2)\n    for i in range(points.shape[2]):\n        points[:, :, i] = np.tensordot(ibvals, pnts[:, :, i], axes=(1, 1))\n    return points\n\n\n@register_draw_type(ng.Mesh)\ndef GetData(mesh, args, kwargs):\n    d = {}\n    d[\"gui_settings\"] = kwargs[\"settings\"]\n    d[\"mesh_dim\"] = mesh.dim\n\n    pmin, pmax = mesh.bounding_box\n    diag = pmax - pmin\n    pmid = pmin + 0.5 * diag\n    d[\"mesh_center\"] = [pmid[i] for i in range(3)]\n    d[\"mesh_radius\"] = diag.Norm()\n\n    d[\"funcdim\"] = 0\n    d[\"show_mesh\"] = True\n    d[\"draw_surf\"] = True\n    d[\"funcmin\"] = 0.0\n    d[\"funcmax\"] = 1.0\n\n    # Generate surface element data\n    # webgui code assumes 4 scalar fields (x,y,z, mesh_index)\n    # TODO: other element types than trigs\n    order = kwargs[\"order\"]\n    refpts = GetElementPoints(\"trig\", order)\n    pnts = np.ndarray((len(mesh.Elements2D()), refpts.shape[0], 4))\n    mesh.CalcElementMapping(refpts, pnts)\n\n    # set mesh_index\n    for i, el in enumerate(mesh.Elements2D()):\n        pnts[i, :, 3] = el.index - 1\n    fds = mesh.FaceDescriptors()\n    d[\"colors\"] = [fd.color +(fd.transparency,) for fd in fds]\n    d[\"mesh_regions_2d\"] = len(fds)\n    d[\"names\"] = [fd.bcname for fd in fds]\n\n    d[\"Bezier_trig_points\"] = MapBernstein(pnts, \"trig\", order)\n    d[\"order2d\"] = order\n\n    # Generate wireframe data\n    refpts = GetWireframePoints(\"trig\", order)\n    pnts = np.ndarray((len(mesh.Elements2D()), refpts.shape[0], 4))\n    mesh.CalcElementMapping(refpts, pnts)\n    d[\"Bezier_points\"] = MapBernstein(pnts, \"segment\", order)\n    d[\"show_wireframe\"] = True\n\n    # TODO: Generate edge data\n    d[\"edges\"] = []\n\n    # encode data as b64\n    for name in [\"Bezier_trig_points\", \"edges\", \"Bezier_points\"]:\n        pnew = []\n        for plist in d[name]:\n            pnew.append(encodeData(np.array(plist, dtype=np.float32)))\n        d[name] = pnew\n    return d\n\nclass WebGLScene(BaseWebGuiScene):\n    class Widget:\n        def __init__(self):\n            self.value = {}\n\n    def __init__(self, obj, args=[], kwargs={}):\n        self.widget = self.Widget()\n        self.obj = obj\n        self.args = args\n        self.kwargs = kwargs\n        self.encoding = \"b64\"\n\n    def Redraw(self, *args, **kwargs):\n        if args or kwargs:\n            if 'show' not in kwargs:\n                kwargs['show'] = False\n\n            new_scene = Draw(*args, **kwargs)\n            self.obj = new_scene.obj\n            self.args = new_scene.args\n            self.kwargs = new_scene.kwargs\n        super().Redraw()\n\n    def GetData(self, set_minmax=True):\n        self.kwargs[\"encoding\"] = self.encoding\n        typ = type(self.obj)\n        d = None\n        if type(self.obj) in _registered_draw_types:\n            d = _registered_draw_types[typ](self.obj, self.args, self.kwargs)\n        else:\n            import inspect\n\n            for t in inspect.getmro(typ):\n                if t in _registered_draw_types:\n                    d = _registered_draw_types[t](self.obj, self.args, self.kwargs)\n                    break\n        if d is None and hasattr(self.obj, \"_webgui_data\"):\n            d = self.obj._webgui_data()\n            bp = d[\"Bezier_trig_points\"]\n            for i in range(len(bp)):\n                bp[i] = encodeData(np.array(bp[i], dtype=np.float32))\n\n            ep = d[\"edges\"]\n            for i in range(len(ep)):\n                ep[i] = encodeData(np.array(ep[i], dtype=np.float32))\n\n        if d is None:\n            raise RuntimeError(f\"Cannot draw object of type {typ}\")\n\n        args = self.args\n        kwargs = self.kwargs\n        if \"clipping\" in kwargs:\n            clipping = kwargs[\"clipping\"]\n            d[\"clipping\"] = True\n            if isinstance(clipping, dict):\n                allowed_args = (\"x\", \"y\", \"z\", \"dist\", \"function\", \"pnt\", \"vec\")\n                if \"vec\" in clipping:\n                    vec = clipping[\"vec\"]\n                    clipping[\"x\"] = vec[0]\n                    clipping[\"y\"] = vec[1]\n                    clipping[\"z\"] = vec[2]\n                if \"pnt\" in clipping:\n                    d[\"mesh_center\"] = list(clipping[\"pnt\"])\n                for name, val in clipping.items():\n                    if not (name in allowed_args):\n                        raise Exception(\n                            \"Only {} allowed as arguments for clipping!\".format(\n                                \", \".join(allowed_args)\n                            )\n                        )\n                    d[\"clipping_\" + name] = val\n\n        id_ = kwargs.get(\"id\", None)\n        js_code = kwargs.get(\"js_code\", \"\")\n        if id_ is not None:\n            js_code += f\"\"\"\n                if(window._webgui_scenes === undefined)\n                    window._webgui_scenes = {{}};\n                window._webgui_scenes['{id_}'] = scene;\n            \"\"\"\n        if js_code:\n            d[\"on_init\"] = js_code\n\n        if \"min\" in kwargs:\n            d[\"funcmin\"] = kwargs[\"min\"]\n        if \"max\" in kwargs:\n            d[\"funcmax\"] = kwargs[\"max\"]\n        d[\"autoscale\"] = kwargs[\"autoscale\"]\n\n        if \"vectors\" in kwargs:\n            d[\"vectors\"] = True\n            if isinstance(kwargs[\"vectors\"], dict):\n                for name, val in kwargs[\"vectors\"].items():\n                    if not (name in (\"grid_size\", \"offset\")):\n                        raise Exception(\n                            'Only \"grid_size\" and \"offset\" allowed as arguments for vectors!'\n                        )\n                    d[\"vectors_\" + name] = val\n\n        if \"eval_function\" in kwargs:\n            d[\"user_eval_function\"] = kwargs[\"eval_function\"]\n\n        # see shaders/utils.h for value explanation (function_mode)\n        if \"eval_\" in kwargs:\n            eval_ = kwargs[\"eval\"]\n            if isinstance(eval_, int):\n                d[\"eval\"] = eval_\n            elif eval_ == \"norm\":\n                d[\"eval\"] = 3\n            elif eval_ == \"real\":\n                d[\"eval\"] = 5\n            elif eval_ == \"imag\":\n                d[\"eval\"] = 6\n\n        if \"fullscreen\" in kwargs:\n            d[\"fullscreen\"] = kwargs[\"fullscreen\"]\n        if \"gui_settings\" not in d:\n            d[\"gui_settings\"] = self.kwargs[\"settings\"]\n\n        if \"euler_angles\" in kwargs:\n            camera = d[\"gui_settings\"].get(\"camera\", {})\n            camera[\"euler_angles\"] = kwargs[\"euler_angles\"]\n            d[\"gui_settings\"]['camera'] = camera\n\n        d[\"objects\"] = []\n        for obj in kwargs[\"objects\"]:\n            if isinstance(obj, dict):\n                d[\"objects\"].append(obj)\n            else:\n                d[\"objects\"].append(obj._GetWebguiData())\n\n        if 'center' in kwargs:\n            center = list(kwargs['center'])\n            if len(center) == 2:\n                center.append(0.)\n            d[\"mesh_center\"] = center\n\n        if 'radius' in kwargs:\n            d[\"mesh_radius\"] = kwargs['radius']\n\n        return d\n\n    def DownloadScreenshot(self, filename=\"image.jpg\"):\n        from IPython.display import Javascript, display\n\n        if \"id\" not in self.kwargs:\n            raise Exception(\n                \"To make a screenshot, please provide an id='some_unique_id' argument to Draw()\"\n            )\n        format = filename.split(\".\")[-1].lower()\n        display(\n            Javascript(\n                f\"\"\"\n        {{\n            var scene = window._webgui_scenes['{self.kwargs['id']}'];\n            console.log(\"screenshot of scene\", scene);\n            const toimage = () => {{\n                var link = document.createElement('a');\n                link.href = scene.renderer.domElement.toDataURL('image/{format}');\n                link.download = '{filename}';\n                link.click();\n                scene.event_handlers['afterrender'].pop(toimage);\n            }};\n            scene.on('afterrender', toimage);\n            scene.render();\n        }}\n        \"\"\"\n            )\n        )\n\n\nbezier_trig_trafos = {}  # cache trafos for different orders\n\n# def Draw(shape, clipping=None, js_code=None, filename=\"\"):\n#     # todo: also handle occ geometry, list of shapes, etc.\n\n#     scene = WebGLScene(shape, clipping=clipping, on_init=js_code)\n\n#     if wg._IN_IPYTHON:\n#         if wg._IN_GOOGLE_COLAB:\n#             from IPython.display import display, HTML\n#             html = scene.GenerateHTML()\n#             display(HTML(html))\n#         else:\n#             # render scene using widgets.DOMWidget\n#             scene.Draw()\n#             return scene\n#     else:\n#         if filename:\n#             scene.GenerateHTML(filename=filename)\n#         return scene\n\n\ndef _get_draw_default_args():\n    return dict(\n        name=\"function\",\n        order=2,\n        draw_vol=True,\n        draw_surf=True,\n        autoscale=True,\n        deformation=False,\n        interpolate_multidim=False,\n        animate=False,\n        objects=[],\n        nodal_p1=False,\n        settings={},\n        fullscreen=False,\n        scale=1.0,\n        width=_default_width,\n        height=_default_height,\n    )\n\n\ndef Draw(obj, *args, show=True, **kwargs):\n    \"\"\"Visualise a mesh or field in the webgui (Jupyter or standalone).\n\n    The object type determines how it is rendered.  Netgen meshes\n    (``netgen.meshing.Mesh``) are supported out of the box.  When\n    *ngsolve* is imported, ``ngsolve.Mesh``, ``CoefficientFunction``\n    and ``GridFunction`` are registered as well via\n    :func:`register_draw_type`.\n\n    Parameters\n    ----------\n    obj : mesh, function, or any registered draw type\n        The object to visualise.  For an ``ngsolve.CoefficientFunction``\n        pass the mesh or region as the first positional argument.\n    show : bool\n        Display the widget immediately in Jupyter (default ``True``).\n    order : int\n        Polynomial order used for visualisation (default 2).\n    draw_vol : bool\n        Draw volume elements (default ``True``).\n    draw_surf : bool\n        Draw surface elements (default ``True``).\n    deformation : bool or GridFunction\n        Apply deformation to the mesh (default ``False``).\n    scale : float\n        Scaling factor for the deformation (default 1.0).\n    autoscale : bool\n        Automatically determine color range (default ``True``).\n    min, max : float\n        Explicit color-range bounds (override *autoscale*).\n    clipping : dict\n        Clipping-plane specification, e.g.\n        ``{\"x\": 1, \"y\": 0, \"z\": 0, \"dist\": 0}`` or with\n        ``\"vec\"``/``\"pnt\"`` keys.\n    vectors : bool or dict\n        Show vector arrows.  Pass a dict with ``\"grid_size\"`` and/or\n        ``\"offset\"`` for fine control.\n    eval_function : str\n        Custom JavaScript evaluation expression for the color map.\n    objects : list\n        Additional overlay objects to render.\n    settings : dict\n        GUI settings forwarded to the viewer.  Supported keys:\n\n        - **Colormap** (*dict*) — ``autoscale`` (bool), ``ncolors`` (int),\n          ``min`` / ``max`` (float).\n        - **Clipping** (*dict*) — ``enable`` (bool), ``function`` (bool),\n          ``x``, ``y``, ``z``, ``dist`` (float).\n        - **Light** (*dict*) — ``ambient``, ``diffuse`` (float, 0–1),\n          ``shininess`` (float, 0–100), ``specularity`` (float, 0–1).\n        - **Vectors** (*dict*) — ``show`` (bool), ``grid_size`` (int),\n          ``offset`` (float).\n        - **Misc** (*dict*) — ``subdivision`` (int, 1–20),\n          ``line_thickness`` (int, 1–20), ``fast_draw`` (bool).\n        - **Complex** (*dict*) — ``phase`` (float), ``speed`` (float),\n          ``animate`` (bool).\n        - **Multidim** (*dict*) — ``t`` (float), ``speed`` (float),\n          ``animate`` (bool).\n        - **Objects** (*dict*) — visibility toggles by name, e.g.\n          ``{\"Edges\": True, \"Wireframe\": False, \"Surface\": True}``.\n        - **camera** (*dict*) — ``euler_angles`` ([x, y, z] in degrees),\n          ``transformations`` (list of rotation/move dicts).\n        - **axes_labels** (*list*) — axis labels, default\n          ``[\"X\", \"Y\", \"Z\"]``.\n\n        Flat shortcuts are also accepted: ``autoscale``,\n        ``colormap_min``, ``colormap_max``, ``colormap_ncolors``,\n        ``subdivision``, ``line_thickness``, ``edges``, ``mesh``,\n        ``elements``.\n    euler_angles : tuple\n        Initial camera orientation as ``[x, y, z]`` in degrees.\n    center : list\n        Override the centre of the scene.\n    radius : float\n        Override the bounding-sphere radius.\n    interpolate_multidim : bool\n        Interpolate between multi-dim components (default ``False``).\n    animate : bool\n        Animate multi-dim data (default ``False``).\n    animate_complex : bool\n        Animate the complex phase (default ``False``).\n    colors : list\n        Custom color table.\n    fullscreen : bool\n        Open in fullscreen mode (default ``False``).\n    width, height : str\n        Widget size, e.g. ``\"100%\"`` / ``\"50vh\"``.\n    filename : str\n        If given, export the scene to an HTML file.\n    nodal_p1 : bool\n        Use nodal P1 interpolation (default ``False``).\n    js_code : str\n        JavaScript snippet executed after scene initialisation.\n    id : str\n        Register the scene under this name in\n        ``window._webgui_scenes`` for JS access.\n\n    Returns\n    -------\n    WebGLScene\n        The scene object.  Call ``scene.Redraw()`` to update after\n        changes.\n\n    See Also\n    --------\n    register_draw_type : Register a handler for additional types.\n    \"\"\"\n    kwargs_with_defaults = _get_draw_default_args()\n    kwargs_with_defaults.update(kwargs)\n\n    scene = WebGLScene(obj, args, kwargs_with_defaults)\n    if show and wg is not None and wg._IN_IPYTHON:\n        if wg._IN_GOOGLE_COLAB:\n            from IPython.display import display, HTML\n\n            html = scene.GenerateHTML()\n            display(HTML(html))\n            return\n        else:\n            import webgui_jupyter_widgets as wjw\n            from packaging.version import parse\n\n            # render scene using widgets.DOMWidget\n            if parse(wjw.__version__) < parse(\"0.2.15\"):\n                scene.Draw()\n            else:\n                scene.Draw(\n                    kwargs_with_defaults[\"width\"], kwargs_with_defaults[\"height\"]\n                )\n    if \"filename\" in kwargs_with_defaults:\n        scene.GenerateHTML(filename=kwargs_with_defaults[\"filename\"])\n    return scene\n\nasync def _MakeScreenshot(data, png_file, width=1200, height=600):\n    \"\"\"Uses playwright to make a screenshot of the given html file.\"\"\"\n    # pylint: disable=import-outside-toplevel\n    from playwright.async_api import async_playwright\n    from webgui_jupyter_widgets.html import GenerateHTML, getScreenshotHTML\n\n    html_file = png_file + \".html\"\n    GenerateHTML(data, filename=html_file, template=getScreenshotHTML())\n\n    async with async_playwright() as play:\n        browser = await play.chromium.launch()\n        page = await browser.new_page(viewport={\"width\": width, \"height\": height})\n        await page.goto(f\"file://{os.path.abspath(html_file)}\")\n        await page.screenshot(path=png_file)\n        await browser.close()\n\ndef _DrawDocu(obj, *args, **kwargs):\n    import json\n    import asyncio\n\n    kwargs_with_defaults = _get_draw_default_args()\n    kwargs_with_defaults.update(kwargs)\n    scene = WebGLScene(obj, args, kwargs_with_defaults)\n\n    docu_path = os.environ[\"NETGEN_DOCUMENTATION_OUT_DIR\"]\n    src_path = os.environ[\"NETGEN_DOCUMENTATION_SRC_DIR\"]\n    cwd_path = os.path.abspath(\".\")\n    rel_path = os.path.relpath(\".\", src_path)\n    path = os.path.join(docu_path, rel_path)\n\n    if not os.path.exists(path):\n        os.makedirs(path)\n    counter_file = os.path.join(docu_path, \".counter\")\n    if os.path.exists(counter_file):\n        file_counter = int(open(counter_file, \"r\").read()) + 1\n    else:\n        file_counter = 0\n\n    open(counter_file, \"w\").write(str(file_counter))\n\n    data_file = \"render_data_{}.json\".format(file_counter)\n    data_file_abs = os.path.join(path, data_file)\n    preview_file = \"preview_{}.png\".format(file_counter)\n    preview_file_abs = os.path.join(path, preview_file)\n\n    widget = WebGuiDocuWidget()\n    widget.value = {\"render_data\": data_file, \"preview\": preview_file}\n    scene.widget = widget\n    data = scene.GetData()\n    json.dump(data, open(data_file_abs, \"w\"))\n    asyncio.run(_MakeScreenshot(data, preview_file_abs, 1200, 600))\n    scene.Redraw = lambda: None\n    from IPython.display import display, HTML\n\n    display(widget)\n    return scene\n\n\nif \"NETGEN_DOCUMENTATION_SRC_DIR\" in os.environ:\n    # use nest_asyncio to allow reentrant asyncio when executing jupyter notebooks\n    import nest_asyncio\n    nest_asyncio.apply()\n\n    # we are buiding the documentation, some things are handled differently:\n    # 1) Draw() is generating a .png (using headless chromium via selenium) and a render_data.json\n    #    to show a preview image and load the render_data only when requested by user\n    # 2) return a NGSDocuWebGuiWidget instead of NGSWebGuiWidget implementing the preview/load on demand of webgui\n\n    _Draw = Draw\n    Draw = _DrawDocu\n"
  },
  {
    "path": "rules/CMakeLists.txt",
    "content": "# this file is included from the parent directory (otherwise generated source files are not recognized properly by cmake)\n\n# generate .cpp files containing the string of the .rls meshing rule files\nif(EMSCRIPTEN)\n  add_custom_command(OUTPUT makerls\n    COMMAND g++ ${CMAKE_CURRENT_SOURCE_DIR}/rules/makerlsfile.cpp -o ${CMAKE_CURRENT_BINARY_DIR}/makerls\n    )\n  set(rules_command ${CMAKE_BINARY_DIR}/makerls)\nelse(EMSCRIPTEN)\n  add_executable(makerls rules/makerlsfile.cpp)\n  if(USE_CCACHE)\n    set_target_properties(makerls PROPERTIES RULE_LAUNCH_COMPILE \"\")\n  endif(USE_CCACHE)\n  set(rules_command makerls)\nendif()\n\nset(rules\n    hexrules\n    prismrules2\n    pyramidrules\n    pyramidrules2\n    quadrules\n    tetrules\n    triarules\n)\n\nfile(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/rules/)\n\nforeach(rule ${rules})\n    list(APPEND rules_sources ${CMAKE_CURRENT_BINARY_DIR}/rules/rule_${rule}.cpp)\n    set(rule_file ${CMAKE_CURRENT_SOURCE_DIR}/rules/${rule}.rls)\n    set(rule_cpp ${CMAKE_CURRENT_BINARY_DIR}/rules/rule_${rule}.cpp)\n\n    add_custom_command(OUTPUT ${rule_cpp}\n      COMMAND ${rules_command} ${rule_file} ${rule_cpp} ${rule}\n      DEPENDS makerls ${rule_file}\n    )\nendforeach()\n\ntarget_sources(nglib PRIVATE ${rules_sources})\n"
  },
  {
    "path": "rules/hexrules.rls",
    "content": "rule \"Hexa left-right-top\"\n\nquality 1\n\nflags t;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 } ;\n(1, 1, 0) { 1 } ;\n(0, 1, 0) { 1 } ;\n(0, 0, 1) { 1 } ;\n(1, 0, 1) { 1 } ;\n(1, 1, 1) { 1 } ;\n(0, 1, 1) { 1 } ;\n\nmapfaces\n(4, 3, 2, 1) del;\n(3, 7, 6, 2) del;\n(7, 8, 5, 6) del;\n(8, 4, 1, 5) del;\n\nnewpoints\n\nnewfaces\n(5, 6, 2, 1);\n(7, 8, 4, 3);\n\nelements\n(4, 3, 2, 1, 8, 7, 6, 5);\n\nfreezone2\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.3 P1, 0.3 P2, 0.3 P5, 0.3 P6, -0.05 P3, -0.05 P4, -0.05 P7, -0.05 P8 };\n{ 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 };\n\nfreezonelimit\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 };\n{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n\n\nendrule\n\n\n\nrule \"Hexa left-right-top (10)\"\n\nquality 10\n\nflags t;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 } ;\n(1, 1, 0) { 1 } ;\n(0, 1, 0) { 1 } ;\n(0, 0, 1) { 1 } ;\n(1, 0, 1) { 1 } ;\n(1, 1, 1) { 1 } ;\n(0, 1, 1) { 1 } ;\n\nmapfaces\n(4, 3, 2, 1) del;\n(3, 7, 6, 2) del;\n(7, 8, 5, 6) del;\n(8, 4, 1, 5) del;\n\nnewpoints\n\nnewfaces\n(5, 6, 2, 1);\n(7, 8, 4, 3);\n\nelements\n(4, 3, 2, 1, 8, 7, 6, 5);\n\nfreezone2\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.251 P1, 0.251 P2, 0.251 P5, 0.251 P6, -0.05 P3, -0.001 P4, -0.001 P7, -0.001 P8 };\n{ 0.251 P3, 0.251 P4, 0.251 P7, 0.251 P8, -0.05 P1, -0.001 P2, -0.001 P5, -0.001 P6 };\n\nfreezonelimit\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 };\n{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n\n\nendrule\n\n\n\n\n\nrule \"Hexa left-right-top-front\"\n\nquality 1\n\nflags t;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 } ;\n(1, 1, 0) { 1 } ;\n(0, 1, 0) { 1 } ;\n(0, 0, 1) { 1 } ;\n(1, 0, 1) { 1 } ;\n(1, 1, 1) { 1 } ;\n(0, 1, 1) { 1 } ;\n\nmapfaces\n(4, 3, 2, 1) del;\n(3, 7, 6, 2) del;\n(7, 8, 5, 6) del;\n(8, 4, 1, 5) del;\n(1, 2, 6, 5) del;\nnewpoints\n\nnewfaces\n(7, 8, 4, 3);\n\nelements\n(4, 3, 2, 1, 8, 7, 6, 5);\n\nfreezone2\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 };\n\nfreezonelimit\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P2 };\n{ 1 P3 };\n{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n\n\nendrule\n\n\n\n\n\n\n\nrule \"Hexa fill\"\n\nquality 1\n\nflags t;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 } ;\n(1, 1, 0) { 1 } ;\n(0, 1, 0) { 1 } ;\n(0, 0, 1) { 1 } ;\n(1, 0, 1) { 1 } ;\n(1, 1, 1) { 1 } ;\n(0, 1, 1) { 1 } ;\n\nmapfaces\n(4, 3, 2, 1) del;\n(3, 7, 6, 2) del;\n(7, 8, 5, 6) del;\n(8, 4, 1, 5) del;\n(1, 2, 6, 5) del;\n(3, 4, 8, 7) del;\n\nnewpoints\n\nnewfaces\n\nelements\n(4, 3, 2, 1, 8, 7, 6, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P5 };\n{ 1 P3 };\n\n\nendrule\n\n\n\n\n\n"
  },
  {
    "path": "rules/makerlsfile.cpp",
    "content": "#include <stdlib.h>\n#include <iostream>\n#include <fstream>\n#include <string>\n\nusing namespace std;\n\n#define maxlen 1000\n\nint main (int argc, char ** argv)\n{\n  if (argc != 4)\n    {\n      cout << \"use:  makerlsfile  infile outfile rulename\" << endl;\n      exit(1);\n    }\n  \n  \n  char line[maxlen]; // , infile[maxlen], outfile[maxlen];   \n  char ch;\n  int i;\n\n  /*\n  cout << \"infile: \";\n  cin >> infile;\n  cout << \"outfile: \";\n  cin >> outfile;\n  */\n\n  ifstream inf (argv[1]);\n  ofstream outf (argv[2]);\n  string rulename = argv[3];\n\n  outf << \"namespace netgen\" << endl << '{' << endl;\n  outf << \"const char * \" << rulename << \"[] = {\" << endl;\n  while (inf.good())\n    {\n      i = 0;\n\n      inf.get(ch);\n      while (ch != '\\n' && inf.good() && i < maxlen)\n\t{\n\t  if (ch == '\\\"')\n\t    {\n\t      line[i] = '\\\\';\n\t      line[i+1] = '\\\"';\n\t      i+= 2;\n\t    }\n\t  else if (ch == '\\\\')\n\t    {\n\t      line[i] = '\\\\';\n\t      line[i+1] = '\\\\';\n\t      i+= 2;\n\t    }\n\t  else\n\t    {\n\t      line[i] = ch;\n\t      i++;\n\t    }\n\t  inf.get(ch);\n\t}\n      line[i] = 0;\n      // cout << line << endl;\n      outf << \"\\\"\" << line << \"\\\\n\\\",\\\\\" << endl;\n    }\n  outf << \"0};\" << endl;\n  outf << '}' << endl;\n  return 0;\n}\n"
  },
  {
    "path": "rules/prismrules2.rls",
    "content": "tolfak 0.5\n\nrule \"prism on quad\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(5, 2, 3, 6);\n(1, 5, 6, 4);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 4 5 6 7;\n\nfreeset\n2 3 4 5 6 8;\n\nendrule\n\n\n\n\n\nrule \"prism on quad, one trig\"\n\nquality 2\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(1, 5, 2) del;\n\nnewpoints\n\nnewfaces\n(5, 2, 3, 6);\n(1, 5, 6, 4);\n(4, 6, 3);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 4 5 6 7;\n\nfreeset\n2 3 4 5 6 8;\n\n\nendrule\n\n\n\n\n\n\n\n\nrule \"prism on 2 quad\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(1, 5, 6, 4);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 4 5 6 7;\n\nfreeset\n2 3 4 6;\n\n\nendrule\n\n\n\n\n\n\n\n\nrule \"prism on 2 quad, one trig\"\n\nquality 2\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(1, 5, 2) del;\n\nnewpoints\n\nnewfaces\n(1, 5, 6, 4);\n(4, 6, 3);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 4 5 6 7;\n\nfreeset\n2 3 4 6;\n\n\nendrule\n\n\n\n\n\n\n\n\n\n\n\nrule \"prism on 2 quada\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(5, 1, 4, 6) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(5, 2, 3, 6);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 3 5 6 7;\n\nfreeset\n1 3 4 6;\n\n\nendrule\n\n\n\n\n\nrule \"fill prism\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(5, 1, 4, 6) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\nfreeset\n1 2 4 5;\n\nfreeset\n2 3 4 6;\n\nendrule\n\n\n\n\n\nrule \"prism on 3 quad, one trig\"\n\nquality 2\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(5, 1, 4, 6) del;\n(1, 5, 2) del;\n\nnewpoints\n\nnewfaces\n(4, 6, 3);\n\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\nfreeset\n1 2 4 5;\n\nfreeset\n2 3 4 6;\n\nendrule\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nrule \"flat prism\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(0.5, 0.866, 0);\n(0, 0, -1);\n(1, 0, -1);\n(0.5, 0.866, -1);\n\n\nmapfaces\n(1, 2, 3) del;\n(5, 4, 6) del;\n\nnewpoints\n\nnewfaces\n(1, 2, 4);\n(4, 2, 5);\n(2, 3, 5);\n(5, 3, 6);\n(3, 1, 6);\n(6, 1, 4);\n\n\n\nelements\n(1, 2, 3, 5, 4, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P5 };\n{ 1 P6 };\nendrule\n"
  },
  {
    "path": "rules/prisms.rls",
    "content": "tolfak 0.5\n\nrule \"prism on quad\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(5, 2, 3, 6);\n(1, 5, 6, 4);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n\n\nendrule\n\n\n\nrule \"prism on 2 quad\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(1, 5, 6, 4);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 4 5 6 7;\n\nfreeset\n2 3 4 6;\n\n\nendrule\n\n\n\n\nrule \"prism on 2 quada\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(5, 1, 4, 6) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n(5, 2, 3, 6);\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n\nfreeset\n1 2 3 5 6 7;\n\nfreeset\n1 3 4 6;\n\n\nendrule\n\n\n\n\n\nrule \"fill prism\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0, -0.86);\n(0.5, 1, -0.86);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 5, 6, 3) del;\n(5, 1, 4, 6) del;\n(1, 5, 2) del;\n(4, 3, 6) del;\n\nnewpoints\n\nnewfaces\n\n\nelements\n(1, 5, 2, 4, 6, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\nfreeset\n1 2 4 5;\n\nfreeset\n2 3 4 6;\n\nendrule\n\n\n\n\n\n\n\n\n\nrule \"flat prism\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(0.5, 0.866, 0);\n(0, 0, -1);\n(1, 0, -1);\n(0.5, 0.866, -1);\n\n\nmapfaces\n(1, 2, 3) del;\n(5, 4, 6) del;\n\nnewpoints\n\nnewfaces\n(1, 2, 4);\n(4, 2, 5);\n(2, 3, 5);\n(5, 3, 6);\n(3, 1, 6);\n(6, 1, 4);\n\n\n\nelements\n(1, 2, 3, 5, 4, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P5 };\n{ 1 P6 };\nendrule\n"
  },
  {
    "path": "rules/pyramidrules.rls",
    "content": "tolfak 0.5\n\nrule \"Pyramid on quad\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n\nmapfaces\n(1, 2, 3, 4) del;\n\nnewpoints\n(0.5, 0.5, -0.5) \n\t{ 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \t\n\t{ 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n\nnewfaces\n(1, 2, 5);\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\nrule \"small Pyramid on quad\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n\nmapfaces\n(1, 2, 3, 4) del;\n\nnewpoints\n(0.5, 0.5, -0.1 )\n\t{ 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n\t{ 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n\nnewfaces\n(1, 2, 5);\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\n\n\nrule \"connect pyramid\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n\nnewpoints\n\nnewfaces\n(1, 2, 5);\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\n\n\n\n\nrule \"pyramid with one trig\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 1, 5) del;\n\nnewpoints\n\nnewfaces\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P3 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P3 };\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 5);\n\n\nfreeset\n1 2 3 5;\nfreeset\n1 3 4 5;\nfreeset\n2 3 5 6;\nfreeset\n3 4 5 7;\nfreeset \n1 4 5 8;\nendrule\n\n\n\n\n\n\nrule \"pyramid with two trig\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 1, 5) del;\n(3, 2, 5) del;\nnewpoints\n\nnewfaces\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\n\n"
  },
  {
    "path": "rules/pyramidrules2.rls",
    "content": "tolfak 0.5\n\nrule \"Pyramid on quad\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n\nmapfaces\n(1, 2, 3, 4) del;\n\nnewpoints\n(0.5, 0.5, -0.5) \n\t{ 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \t\n\t{ 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n\nnewfaces\n(1, 2, 5);\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\nrule \"small Pyramid on quad\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n\nmapfaces\n(1, 2, 3, 4) del;\n\nnewpoints\n(0.5, 0.5, -0.1 )\n\t{ 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n\t{ 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n\nnewfaces\n(1, 2, 5);\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\nrule \"pyramid with one trig\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 1, 5) del;\n\nnewpoints\n\nnewfaces\n(2, 3, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P2 };\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 5);\n\n\nfreeset\n1 2 3 5;\nfreeset\n1 3 4 5;\nfreeset\n2 3 5 6;\nfreeset\n3 4 5 7;\nfreeset \n1 4 5 8;\nendrule\n\n\nrule \"pyramid with one trig, left\"\n\nquality 20\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(3, 2, 5) del;\n\nnewpoints\n\nnewfaces\n(1, 2, 5);\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.34 P1, 0.34 P2, 0.34 P5, -0.01 P3 };\n{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 0.333 P1, 0.333 P2, 0.334 P5, 0 P3 };\n{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P2 };\n\norientations\n(1, 2, 3, 5);\n(1, 3, 4, 5);\n\n\nfreeset\n1 2 3 5;\nfreeset\n1 3 4 5;\nfreeset\n1 2 5 6;\nfreeset\n3 4 5 7;\nfreeset \n1 4 5 8;\nendrule\n\n\n\n\n\n\nrule \"pyramid with two trig\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 1, 5) del;\n(3, 2, 5) del;\nnewpoints\n\nnewfaces\n(3, 4, 5);\n(4, 1, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\n\n\n\n\n\nrule \"pyramid with two trig, left\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(1, 1, 0);\n(0, 1, 0);\n(0.5, 0.5, -0.5);\n\nmapfaces\n(1, 2, 3, 4) del;\n(2, 1, 5) del;\n(1, 4, 5) del;\nnewpoints\n\nnewfaces\n(3, 4, 5);\n(2, 3, 5);\n\nelements\n(1, 2, 3, 4, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nendrule\n\n\n\n\n"
  },
  {
    "path": "rules/quadrules.rls",
    "content": "rule \"Free Quad (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(1, 1) { 1 X2 } { };\n(0, 1) { } { };\n\nnewlines\n(3, 2);\n(4, 3);\n(1, 4);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 1.5) { 1.5 X2 } { };\n(-0.5, 1.5) { -0.5 X2 } { };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Free Quad (5)\"\n\nquality 5\n\nmappoints\n(0, 0);\n(1, 0);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(1, 1) { 1 X2 } { };\n(0, 1) { } { };\n\nnewlines\n(3, 2);\n(4, 3);\n(1, 4);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 1.5) { 1.5 X2 } { };\n(-0.5, 1.5) { -0.5 X2 } { };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X2 } { };\n(0, 1) { } { };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\n\n\n\n\nrule \"Quad Right (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n(0, 1) { } { 1 y3 };\n\nnewlines\n(1, 4);\n(4, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(-0.5, 1.5) { } { 1.5 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { } { 1 Y3 };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\nrule \"Quad P Right (2)\"\n\nquality 2\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n\nnewlines\n(1, 4);\n(4, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 3, 4);\n\n\norientations\n(1, 2, 3);\n\n\nendrule\n\n\nrule \"Quad P Right (150)\"\n\nquality 150\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n\nnewlines\n(1, 4);\n(4, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 3, 4);\n\norientations\n(1, 2, 3);\n\nendrule\n\n\nrule \"Quad Right PL (2)\"\n\nquality 2\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n\nnewlines\n(1, 4);\n(4, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(-0.2, 0.5) { -0.1 X2, -0.1 X3, 0.6 X4 } { -0.1 Y2, -0.1 Y3, 0.6 Y4 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n\nelements\n(1, 2, 3, 4);\n\norientations\n(1, 2, 3);\n(1, 3, 4);\n(1, 2, 4);\n(4, 2, 3);\n\n\nendrule\n\n\n\n\n\n\n\n\n\nrule \"Left Quad (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n\nnewpoints\n(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n\nnewlines\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 4, 3);\n\nendrule\n\n\n\nrule \"Left P Quad (2)\"\n\nquality 2\n\nmappoints\n(0, 0);\n(1, 0);\n(0, 1);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n\nnewlines\n(1, 3);\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 4, 3);\n\nendrule\n\n\n\n\nrule \"Left P Quad (150)\"\n\nquality 150\n\nmappoints\n(0, 0);\n(1, 0);\n(0, 1);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n\nnewlines\n(1, 3);\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n(0, 1) { 1 X3 } { 1 Y3 };\n(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 4, 3);\n\nendrule\n\n\n\n\n\nrule \"Left Quad RP (2)\"\n\nquality 2\n\nmappoints\n(0, 0);\n(1, 0);\n(0, 1);\n(1, 1);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n\nnewpoints\n\nnewlines\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.2, 0.5) { 0.6 X2, 0.6 X4, -0.1 X3 } { 0.6 Y2, 0.6 Y4, -0.1 Y3 };\n(1, 1) { 1 X4 } { 1 Y4 };\n(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n(0, 1) { 1 X3 } { 1 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 0.5 X2, 0.5 X4 } { 0.5 Y2, 0.5 Y4 };\n(1, 1) { 1 X4 } { 1 Y4 };\n(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n(0, 1) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 4, 3);\n\norientations\n(1, 2, 4);\n(1, 4, 3);\n\nendrule\n\n\n\n\n\n\nrule \"Two left (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(3, 4) del;\n(4, 1) del;\n\nnewpoints\n\nnewlines\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Two Right (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n(3, 4) del;\n\nnewpoints\n\nnewlines\n(1, 4);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nrule \"Right 120 (1)\"\n\nquality 1000\n\nmappoints\n(0, 0);\n(1, 0);\n(1.5, 0.866);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n\nnewlines\n(1, 4);\n(4, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.866) { 1 X3 } { 1 Y3 };\n(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n\nelements\n(1, 2, 4);\n(2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Left 120 (1)\"\n\nquality 1000\n\nmappoints\n(0, 0);\n(1, 0);\n(-0.5, 0.866);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n\nnewpoints\n(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n\nnewlines\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n(0, 1.732) { -1 X2, 2 X3 } { 2 Y3 };\n(-0.5, 0.866) { 1 X3 } {1 Y3 };\n\nelements\n(1, 2, 4);\n(2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Left Right (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n(4, 1) del;\n\n\nnewlines\n(4, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0.5, 1.5) { -0.25 X2, 0.75 X3, 0.75 X4 } { 0.75 Y3, 0.75 Y4 };\n(0, 1) { 1 X4 } { 1 Y4 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n(0, 1) { 1 X4 } { 1 Y4 };\n\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\n\nrule \"Fill Quad\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n(3, 4) del;\n(4, 1) del;\n\nnewpoints\n\nnewlines\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { 1 Y2 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n\nelements\n(1, 2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Fill Triangle\"\n\nquality 10\n\nmappoints\n(0, 0);\n(1, 0);\n(0.5, 0.86);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n(3, 1) del;\n\nnewpoints\n\nnewlines\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { 1 Y2 };\n(0.5, 0.86) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\nrule \"Right 60 (1)\"\n\nquality 10\n\nmappoints\n(0, 0);\n(1, 0) { 0.5, 0, 1.0 };\n(0.5, 0.866) { 0.6, 0, 0.8 };\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n\nnewlines\n(1, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\nrule \"Vis A Vis (2)\"\n\nquality 2\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1);\n(0, 1);\n\nmaplines\n(1, 2) del;\n(3, 4) del;\n\nnewpoints\n\nnewlines\n(1, 4);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n(1, 1) { 1 X3 } { 1 Y3 };\n(0, 1) { 1 X4 } { 1 Y4 };\n(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n\nelements\n(1, 2, 3, 4);\n\norientations\n(1, 3, 4);\n(2, 3, 4);\n(1, 2, 3);\n(1, 2, 4);\n\nendrule\n\n\n\n\nrule \"Triangle Vis A Vis (200)\"\n\nquality 200\n\nmappoints\n(0, 0);\n(1, 0);\n(0.5, 0.866);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\nrule \"2 h Vis A Vis (1)\"\n\nquality 3000\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1.732);\n(0, 1.732);\n\nmaplines\n(1, 2) del;\n(3, 4) del;\n\nnewpoints\n(0.5, 0.866) { 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n\nnewlines\n(1, 5);\n(5, 4);\n(3, 5);\n(5, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { 1 Y2 };\n(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n(1, 1.732) { 1 X3 } { 1 Y3 };\n(0, 1.732) { 1 X4 } { 1 Y4 };\n(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n\nelements\n(1, 2, 5);\n(3, 4, 5);\n\nendrule\n\n\n\n\n\n"
  },
  {
    "path": "rules/tetrules.rls",
    "content": "tolfak 0.5\n\nrule \"Free Tetrahedron\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0);\n(0.5, 0.866, 0);\n\nmapfaces\n(1, 2, 3) del;\n\nnewpoints\n(0.5, 0.288, -0.816)\n\t{ 0.333 X1, 0.333 X2, 0.333 X3 }\n\t{ 0.333 Y1, 0.333 Y2, 0.333 Y3 } { };\n\nnewfaces\n(4, 1, 2);\n(4, 2, 3);\n(4, 3, 1);\n\nelements\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1.6 P4, -0.2 P1, -0.2 P2, -0.2 P3 };\n{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\nendrule\n\n\n\n\n\n\nrule \"Tetrahedron 60\"\n\nquality 1\n\nflags c;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 } ;\n(0.5, 0.866, 0) { 0.5 };\n(0.5, 0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n\nnewfaces\n(1, 4, 3);\n(4, 2, 3);\n\nelements\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n{ 0.65 P3, 0.35 P4 };\nendrule\n\n\n\n\nrule \"Tetrahedron 60 with edge(1)\"\n\nquality 1\n\nflags c;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.8 };\n(0.5, 0.866, 0) { 0.8 };\n(0.5, 0.288, -0.816) { 0.8 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nmapedges\n(3, 4);\n\nnewpoints\n\nnewfaces\n(1, 4, 3);\n(4, 2, 3);\n\nelements\n(1, 2, 3, 4);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n{ 0.4 P2, 0.4 P4, 0.4 P3, -0.2 P1 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P1, 0.3333 P4, 0.3334 P3 };\n{ 0.3333 P2, 0.3333 P4, 0.3334 P3 };\nendrule\n\n\n\n\nrule \"Tetrahedron Vis a Vis Point (1)\"\n\nquality 20\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 0.866, 0) { 0.5 };\n(0.5, 0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n\nnewpoints\n\nnewfaces\n(4, 3, 1);\n(4, 2, 3);\n(4, 1, 2);\n\nelements\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\n{ 0.8 P1, -0.1 P2, -0.1 P3, 0.4 P4 };\n{ -0.1 P1, 0.8 P2, -0.1 P3, 0.4 P4 };\n{ -0.1 P1, -0.1 P2, 0.8 P3, 0.4 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n{ 0.7 P1, 0.3 P4 };\n{ 0.7 P2, 0.3 P4 };\n{ 0.7 P3, 0.3 P4 };\nendrule\n\n\n\nrule \"Tetrahedron Vis a Vis Point with edge(1)\"\n\nquality 1\n\n\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 0.866, 0) { 0.5 };\n(0.5, 0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n\nmapedges\n(1, 4);\n\nnewpoints\n\nnewfaces\n(4, 3, 1);\n(4, 2, 3);\n(4, 1, 2);\n\nelements\n(1, 2, 3, 4);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n{ -0.05 P1, 0.7 P2, -0.05 P3, 0.4 P4 };\n{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n{ 0.65 P2, 0.35 P4 };\n{ 0.65 P3, 0.35 P4 };\nendrule\n\n\n\nrule \"Tetrahedron Vis a Vis Point with 2 edges (1)\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 0.866, 0) { 0.5 };\n(0.5, 0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n\nmapedges\n(1, 4);\n(2, 4);\n\nnewpoints\n\nnewfaces\n(4, 3, 1);\n(4, 2, 3);\n(4, 1, 2);\n\nelements\n(1, 2, 3, 4);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n{ 0.65 P3, 0.35 P4 };\nendrule\n\n\n\n\nrule \"Tetrahedron Vis a Vis Point with 3 edges (1)\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 0.866, 0) { 0.5 };\n(0.5, 0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n\nmapedges\n(1, 4);\n(2, 4);\n(3, 4);\n\nnewpoints\n\nnewfaces\n(4, 3, 1);\n(4, 2, 3);\n(4, 1, 2);\n\nelements\n(1, 2, 3, 4);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\nendrule\n\n\n\n\n\n\nrule \"Tetrahedron Vis a Vis Triangle (1)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 0.866, 0) { 0.5 };\n(0, 0, -0.816) { 0.5 };\n(1, 0, -0.816) { 0.5 };\n(0.5, 0.866, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(4, 6, 5) del;\n\nnewpoints\n\nnewfaces\n(1, 2, 4);\n(2, 5, 4);\n(2, 3, 6);\n(2, 6, 5);\n(3, 1, 4);\n(3, 4, 6);\n\n\nelements\n(1, 2, 3, 4);\n(4, 2, 3, 6);\n(4, 2, 6, 5);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ -0.2 P1, 0.35 P2, 0.35 P3, -0.2 P4, 0.35 P5, 0.35 P6 };\n{ 0.35 P1, -0.2 P2, 0.35 P3, 0.35 P4, -0.2 P5, 0.35 P6 };\n{ 0.35 P1, 0.35 P2, -0.2 P3, 0.35 P4, 0.35 P5, -0.2 P6 };\nendrule\n\n\n\n\nrule \"Octaeder 1\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.95 };\n(0.5, 0.866, 0) { 0.95 };\n(0.5, -0.288, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nnewfaces\n(2, 3, 5);\n(3, 1, 6);\n(3, 6, 5);\n(2, 5, 4);\n(1, 4, 6);\n(4, 5, 6);\n\nelements\n(3, 4, 1, 2);\n(3, 4, 2, 5);\n(3, 4, 5, 6);\n(3, 4, 6, 1);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n( 1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n\nendrule\n\n\n\nrule \"Octaeder 2\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.95 };\n(0.5, 0.866, 0) { 0.95 };\n(0.5, -0.288, -0.816) { 0.5 };\n(1, 0.578, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nnewfaces\n(2, 3, 5);\n(3, 1, 6);\n(3, 6, 5);\n(2, 5, 4);\n(1, 4, 6);\n(4, 5, 6);\n\nelements\n(3, 4, 1, 2);\n(3, 4, 2, 5);\n(3, 4, 5, 6);\n(3, 4, 6, 1);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n\n(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n                     { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n                     { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n(0.9, 0.481, -0.272) { 0.333 X2, 0.333 X3, 0.333 X5 }\n                     { 0.333 Y2, 0.333 Y3, 0.333 Y5 }\n                     { 0.333 Z2, 0.333 Z3, 0.333 Z5 };\n\n(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n\nendrule\n\n\nrule \"Octaeder 2a\"\n\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.95 };\n(0.5, 0.866, 0) { 0.95 };\n(0.5, -0.288, -0.816) { 0.5 };\n(1, 0.578, -0.816) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(3, 2, 5) del;\n\nnewpoints\n(0, 0.578, -0.816)\n\t{ -1 X2, 1 X3, 1 X4 }\n\t{ -1 Y2, 1 Y3, 1 Y4 }\n\t{ -1 Z2, 1 Z3, 1 Z4 };\n\nnewfaces\n(1, 2, 4);\n(3, 1, 6);\n(3, 6, 5);\n(2, 5, 4);\n(1, 4, 6);\n(4, 5, 6);\n\nelements\n(3, 4, 1, 2);\n(3, 4, 2, 5);\n(3, 4, 5, 6);\n(3, 4, 6, 1);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n\n(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n                     { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n                     { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n\n(0.5, -0.097, -0.272) { 0.333 X2, 0.333 X4, 0.333 X1 }\n                     { 0.333 Y2, 0.333 Y4, 0.333 Y1 }\n                     { 0.333 Z2, 0.333 Z4, 0.333 Z1 };\n\n(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n\nendrule\n\n\n\n\nrule \"Pyramid 1\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 };\n(0.5, 0.866, 0) { 1 };\n(0.5, -0.288, -0.816) { 1 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nnewfaces\n(1, 4, 3);\n(2, 3, 5);\n(2, 5, 4);\n(4, 5, 3);\n\nelements\n(1, 2, 3, 4);\n(4, 2, 3, 5);\n\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n(0, 1, -1) { 0.5 X3, 0.5 X4 } { 1 Y3 } { 1 Z4 };\n(1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nendrule\n\n\n\n\n\n\n\n\nrule \"Tetrahedron 2 times 60\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.3 };\n(0.5, 0.866, 0) { 0.3 };\n(0.5, 0.288, -0.816) { 0.3 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(2, 4, 3) del;\n\nnewpoints\n\nnewfaces\n(1, 4, 3);\n\nelements\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\nendrule\n\n\n\nrule \"Fill Tetrahedron (1)\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.2 };\n(0.5, 0.866, 0) { 0.2 };\n(0.5, 0.288, -0.816) { 0.2 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(2, 4, 3) del;\n(3, 4, 1) del;\n\nnewpoints\n\nnewfaces\n\nelements\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\nendrule\n\n\n\n\n\n\n\n\n\n\nrule \"Tetrahedron 120 (1)\"\n\nquality 1\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 };\n(0.5, 0.866, 0) { 1 };\n(0.5, -0.674, -0.544) { 1 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n(0.5, 0.288, -0.816)\n\t{ -0.5 X1, -0.5 X2, 1 X3, 1 X4 }\n\t{ -0.5 Y1, -0.5 Y2, 1 Y3, 1 Y4}\n\t{ -0.5 Z1, -0.5 Z2, 1 Z3, 1 Z4};\n\nnewfaces\n(1, 5, 3);\n(3, 5, 2);\n(1, 4, 5);\n(2, 5, 4);\n\nelements\n(1, 2, 3, 5);\n(1, 4, 2, 5);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.3 P5, -0.3 P1 };\n{ 1.3 P5, -0.3 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P5 };\nendrule\n\n\n\n\n\nrule \"Tetrahedron 2 times 120 (1)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 };\n(0.5, 0.866, 0) { 1 };\n(0.5, -0.674, -0.544) { 0.8 };\n(1.334, 0.77, -0.544) { 0.8 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(3, 2, 5) del;\n\nnewpoints\n(0.5, 0.288, -0.816) { 0.25 X1, -0.5 X2, 0.25 X3, 0.5 X4, 0.5 X5 }\n\t\t { 0.25 Y1, -0.5 Y2, 0.25 Y3, 0.5 Y4, 0.5 Y5 }\n\t\t { 0.25 Z1, -0.5 Z2, 0.25 Z3, 0.5 Z4, 0.5 Z5 };\n\nnewfaces\n(6, 3, 1);\n(6, 1, 4);\n(6, 4, 2);\n(6, 2, 5);\n(6, 5, 3);\n\nelements\n(1, 2, 3, 6);\n(1, 4, 2, 6);\n(2, 5, 3, 6);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1.4 P6, -0.4 P2 };\n{ 1.4 P6, -0.4 P1 };\n{ 1.4 P6, -0.4 P3 };\nendrule\n\n\n\n\nrule \"four Tetrahedron non convex (4)\"\n\nquality 4\nflags l;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.1 };\n(0.5, 1, 0) { 0.1 };\n(0.5, 0, -1) { 0.1 };\n(0.5, 0.3, -0.3) { 0.1 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(1, 5, 4) del;\n(1, 3, 5) del;\n\n\nnewpoints\n(0.5, 0.1, -0.1)\n\t { 0.333 X1, 0.333 X2, 0.334 X5 }\n\t { 0.333 Y1, 0.333 Y2, 0.334 Y5 }\n\t { 0.333 Z1, 0.333 Z2, 0.334 Z5 };\n\nnewfaces\n(6, 2, 3) del;\n(6, 4, 2) del;\n(6, 5, 4) del;\n(6, 3, 5) del;\n\n\nelements\n(1, 2, 3, 6);\n(1, 4, 2, 6);\n(1, 5, 4, 6);\n(1, 3, 5, 6);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1.5 P6, -0.5 P1 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\n\n\nfreeset\n1 6 2 3;\n\nfreeset\n1 6 3 5;\n\nfreeset\n1 6 5 4;\n\nfreeset\n1 6 4 2;\n\nendrule\n\n\n\n\n\n\nrule \"five Tetrahedron non convex (4)\"\n\nquality 4\nflags l;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0, 0.8, -0.2) { 0.5 };\n(0, 0.2, -0.8) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n\n\nmapfaces\n(1, 2, 3) del;\n(1, 3, 4) del;\n(1, 4, 5) del;\n(1, 5, 6) del;\n(1, 6, 2) del;\n\nnewpoints\n(0.1, 0.1, -0.1)\n\t { 0.75 X1, 0.05 X2, 0.05 X3, 0.05 X4, 0.05 X5, 0.05 X6 }\n\t { 0.75 Y1, 0.05 Y2, 0.05 Y3, 0.05 Y4, 0.05 Y5, 0.05 Y6 }\n\t { 0.75 Z1, 0.05 Z2, 0.05 Z3, 0.05 Z4, 0.05 Z5, 0.05 Z6 };\n\nnewfaces\n(7, 2, 3);\n(7, 3, 4);\n(7, 4, 5);\n(7, 5, 6);\n(7, 6, 2);\n\n\nelements\n(1, 2, 3, 7);\n(1, 3, 4, 7);\n(1, 4, 5, 7);\n(1, 5, 6, 7);\n(1, 6, 2, 7);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 1.5 P7, -0.5 P1 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n{ 1 P7 };\n\n\n\nfreeset\n1 7 2 3;\n\nfreeset\n1 7 3 4;\n\nfreeset\n1 7 4 5;\n\nfreeset\n1 7 5 6;\n\nfreeset\n1 7 6 2;\n\nendrule\n\n\n\n\n\n\n\nrule \"four Tetrahedron non convex (6)\"\n\nquality 6\nflags l;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n(0.5, 0.3, -0.3) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(1, 5, 4) del;\n(1, 3, 5) del;\n\n\nnewpoints\n(0.095, 0.003, -0.003)\n\t { 0.9 X1, 0.09 X2, 0.01 X5 }\n\t { 0.9 Y1, 0.09 Y2, 0.01 Y5 }\n\t { 0.9 Z1, 0.09 Z2, 0.01 Z5 };\n\nnewfaces\n(6, 2, 3) del;\n(6, 4, 2) del;\n(6, 5, 4) del;\n(6, 3, 5) del;\n\n\nelements\n(1, 2, 3, 6);\n(1, 4, 2, 6);\n(1, 5, 4, 6);\n(1, 3, 5, 6);\n\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1.499 P6, -0.5 P1, 0.001 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\n\n\nfreeset\n1 6 2 3;\n\nfreeset\n1 6 3 5;\n\nfreeset\n1 6 5 4;\n\nfreeset\n1 6 4 2;\n\nendrule\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nrule \"four Tetrahedron non convex (6)\"\n\nquality 100\n\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n(0.5, 0.4, -0.4) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(4, 5, 2) del;\n(5, 3, 2) del;\n\nnewpoints\n(0.925, 0.02, -0.02)\n\t { 0.05 X1, 0.9 X2, 0.05 X5 }\n\t { 0.05 Y1, 0.9 Y2, 0.05 Y5 }\n\t { 0.05 Z1, 0.9 Z2, 0.05 Z5 };\n\nnewfaces\n(3, 1, 6);\n(1, 4, 6);\n(4, 5, 6);\n(5, 3, 6);\n\nelements\n(3, 1, 2, 6);\n(1, 4, 2, 6);\n(4, 5, 2, 6);\n(5, 3, 2, 6);\n\norientations\n(3, 1, 2, 5);\n(1, 4, 2, 5);\n(2, 4, 5, 1);\n(3, 2, 5, 1);\n(5, 4, 2, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1.5 P6, -0.5 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n{ 1 P6 };\n\nfreeset\n3 1 2 6;\n\nfreeset\n1 4 2 6;\n\nfreeset\n4 5 2 6;\n\nfreeset\n5 3 2 6;\n\nendrule\n\n\n\n\n\n\n\n\n\n\nrule \"three Tetrahedron non convex (4)\"\n\nquality 4\nflags l;\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(1, 3, 4) del;\n\nnewpoints\n(0.5, 0.25, -0.25)\n\t { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 }\n\t { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 }\n\t { 0.25 Z1, 0.25 Z2, 0.25 Z3, 0.25 Z4 };\n\nnewfaces\n(5, 2, 3);\n(5, 4, 2);\n(5, 3, 4);\n\nelements\n(2, 3, 1, 5);\n(3, 4, 1, 5);\n(4, 2, 1, 5;\n\norientations\n(1, 2, 4, 3);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.5 P5, -0.5 P1 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nfreeset\n1 4 2 5;\n\nendrule\n\n\n\n\n\nrule \"three Tetrahedron non convex (6)\"\n\nquality 100\n\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(1, 3, 4) del;\n\nnewpoints\n(0.2, 0.1, -0.1)\n\t { 0.7 X1, 0.1 X2, 0.1 X3, 0.1 X4 }\n\t { 0.7 Y1, 0.1 Y2, 0.1 Y3, 0.1 Y4 }\n\t { 0.7 Z1, 0.1 Z2, 0.1 Z3, 0.1 Z4 };\n\nnewfaces\n(5, 2, 3);\n(5, 4, 2);\n(5, 3, 4);\n\nelements\n(2, 3, 1, 5);\n(3, 4, 1, 5);\n(4, 2, 1, 5;\n\norientations\n(1, 2, 3, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.5 P5, -0.5 P1 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 3 4 5;\n\nfreeset\n1 4 2 5;\n\nendrule\n\n\n\n\n\n\n\n\n\n\nrule \"four Tetrahedron non convex (6)\"\n\nquality 100\n\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n(0.5, 0.4, -0.4) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n(4, 5, 2) del;\n(5, 3, 2) del;\n\nnewpoints\n(0.7, 0.08, -0.08) { 0.6 X2, 0.2 X5 } { 0.2 Y5 } { 0.2 Z5 };\n\nnewfaces\n(3, 1, 6);\n(1, 4, 6);\n(4, 5, 6);\n(5, 3, 6);\n\nelements\n(3, 1, 2, 6);\n(1, 4, 2, 6);\n(4, 5, 2, 6);\n(5, 3, 2, 6);\n\n\norientations\n(3, 1, 2, 5);\n(5, 1, 2, 4);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 1, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, 0, -1) { 1 X4 } { 1 Y4 } { 1 Z4 };\n(0.5, 0.4, -0.4) { 1 X5 } { 1 Y5 } { 1 Z5 };\n(0.55, 0.12, -0.12) { 0.4 X2, 0.3 X5 } { 0.3 Y5 } { 0.3 Z5 };\n\nfreeset\n3 1 2 6;\n\nfreeset\n1 4 2 6;\n\nfreeset\n4 5 2 6;\n\nfreeset\n5 3 2 6;\n\nendrule\n\n\n\n\n\n\n\n\n\n\n\nrule \"Tetrahedron 2 in 60 (12)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 0.5 };\n(0.5, 1, 0) { 0.5 };\n(0.5, 0, -1) { 0.5 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2) del;\n\nnewpoints\n(0.5, 0.1, -0.1)\n\t{ 0.4 X1, 0.4 X2, 0.1 X3, 0.1 X4 }\n\t{ 0.4 Y1, 0.4 Y2, 0.1 Y3, 0.1 Y4 }\n\t{ 0.4 Z1, 0.4 Z2, 0.1 Z3, 0.1 Z4 };\n\nnewfaces\n(5, 2, 3);\n(5, 3, 1);\n(5, 4, 2);\n(5, 1, 4);\n\nelements\n(1, 2, 3, 5);\n(1, 2, 5, 4);\n\nfreezone2\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1.5 P5, -0.25 P1, -0.25 P2 };\n\nfreezonelimit\n{ 1 P1 };\n{ 1 P2 };\n{ 1 P3 };\n{ 1 P4 };\n{ 1 P5 };\n\nfreeset\n1 2 3 5;\n\nfreeset\n1 2 4 5;\n\nendrule\n\n\n\n\nrule \"Tetrahedron 120, but more than 180 (13)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1 };\n(0.5, 0.866, 0) { 1 };\n(0.5, -0.866, 0) { 1 };\n\nmapfaces\n(1, 2, 3) del;\n(1, 4, 2);\n\nnewpoints\n(0.5, 0, -0.3) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nnewfaces\n(1, 5, 3);\n(3, 5, 2);\n(2, 5, 1);\n\nelements\n(1, 2, 3, 5);\n\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, -0.1, -0.4)  { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n\nendrule\n\n\n\n\n\nrule \"Free Tetrahedron (14)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1.0 };\n(0.5, 0.866, 0) { 1.0 };\n\nmapfaces\n(1, 2, 3) del;\n\nnewpoints\n(0.5, 0.288, -0.2) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n\nnewfaces\n(4, 1, 2);\n(4, 2, 3);\n(4, 3, 1);\n\nelements\n(1, 2, 3, 4);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, 0.288, -0.25) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n\nendrule\n\n\n\nrule \"Free Tetrahedron (15)\"\n\nquality 100\n\nmappoints\n(0, 0, 0);\n(1, 0, 0) { 1.0 };\n(0.5, 0.866, 0) { 1.0 };\n\nmapfaces\n(1, 2, 3) del;\n\nnewpoints\n(0.5, 0.288, -0.1) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n\nnewfaces\n(4, 1, 2);\n(4, 2, 3);\n(4, 3, 1);\n\nelements\n(1, 2, 3, 4);\n\nfreezone\n(0, 0, 0);\n(1, 0, 0) { 1 X2 } { } { };\n(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n(0.5, 0.288, -0.15) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n\nendrule\n"
  },
  {
    "path": "rules/triarules.rls",
    "content": "rule \"Free Triangle (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0) { 1.0, 0, 1.0 };\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0.5, 0.866) { 0.5 X2 } { };\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.7) { 0.5 X2 } { };\n(0.5, 1.5) { 0.5 X2 } { };\n(-0.5, 0.7) { 0.5 X2 } { };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.866) { 0.5 X2 } { };\n(0.5, 0.866) { 0.5 X2 } { };\n(0.5, 0.866) { 0.5 X2 } { };\n\n\nelements\n(1, 2, 3);\n\nendrule\n\n\nrule \"Free Triangle (5)\"\n\nquality 5\n\nmappoints\n(0, 0);\n(1, 0) { 1.0, 0, 1.0 };\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0.5, 0.5) { 0.5 X2 } { };\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.7) { 1 X2 } { };\n(0, 0.7) { } { };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.5) { 0.5 X2 } { };\n(0.5, 0.5) { 0.5 X2 } { };\n\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\nrule \"Free Triangle (10)\"\n\nquality 10\n\nmappoints\n(0, 0);\n(1, 0) { 1.0, 0, 1.0 };\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0.5, 0.3) { 0.5 X2 } { };\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.5) { 1 X2 } { };\n(0, 0.5) { } { };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.3) { 0.5 X2 } { };\n(0.5, 0.3) { 0.5 X2 } { };\n\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\nrule \"Free Triangle (20)\"\n\nquality 20\n\nmappoints\n(0, 0);\n(1, 0) { 1.0, 0, 1.0 };\n\nmaplines\n(1, 2) del;\n\nnewpoints\n(0.5, 0.1) { 0.5 X2 } { };\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1, 0.2) { 1 X2 } { };\n(0, 0.2) { } { };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.1) { 0.5 X2 } { };\n(0.5, 0.1) { 0.5 X2 } { };\n\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\n\n\n\n\n\nrule \"Right 60 (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0) { 0.5, 0, 1.0 };\n(0.5, 0.866) { 0.6, 0, 0.8 };\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n\nnewlines\n(1, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\nrule \"Left 60 (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(0.5, 0.866);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n\nnewpoints\n\nnewlines\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.125, 0.6495) { 0.75 X2, 0.75 X3 } { 0.75 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\nrule \"Right 120 (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(1.5, 0.866);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n\nnewpoints\n(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n\nnewlines\n(1, 4);\n(4, 3);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.866) { 1 X3 } { 1 Y3 };\n(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n\nelements\n(1, 2, 4);\n(2, 3, 4);\n\nendrule\n\n\n\n\nrule \"Left 120 (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(-0.5, 0.866);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n\nnewpoints\n(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n\nnewlines\n(3, 4);\n(4, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n(0, 1.732) { 1 X2, 2 X3 } { 2 Y3 };\n(-0.5, 0.866) { 1 X3 } {1 Y3 };\n\nelements\n(1, 2, 4);\n(1, 4, 3);\n\nendrule\n\n\n\n\nrule \"Left Right 120 (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(-0.5, 0.866);\n(1.5, 0.866);\n\nmaplines\n(1, 2) del;\n(3, 1) del;\n(2, 4) del;\n\nnewpoints\n(0.5, 0.866) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n\nnewlines\n(3, 5);\n(5, 4);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.5, 0.866) { 1 X4 } { 1 Y4 };\n(1, 1.299) { -0.5 X2, 0.375 X3, 1.125 X4 } { -0.5 Y2, 0.375 Y3, 1.125 Y4 };\n(0, 1.299) { 1.125 X3, 0.375 X4 } { 1.125 Y3, 0.375 Y4 };\n(-0.5, 0.866) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 5);\n(3, 1, 5);\n(2, 4, 5);\n\nendrule\n\n\nrule \"Fill Triangle\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(0.5, 0.866);\n\nmaplines\n(1, 2) del;\n(2, 3) del;\n(3, 1) del;\n\nnewpoints\n\nnewlines\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { 1 Y2 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\nrule \"Vis A Vis (1)\"\n\nquality 1\n\nmappoints\n(0, 0);\n(1, 0);\n(0.5, 0.866);\n\nmaplines\n(1, 2) del;\n\nnewpoints\n\nnewlines\n(1, 3);\n(3, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { };\n(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n\nfreearea2\n(0, 0);\n(1, 0) { 1 X2 } { };\n(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n(0.5, 0.866) { 1 X3 } { 1 Y3 };\n(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n\nelements\n(1, 2, 3);\n\nendrule\n\n\n\n\n\n\nrule \"2 h Vis A Vis (1)\"\n\nquality 3\n\nmappoints\n(0, 0);\n(1, 0);\n(1, 1.732);\n(0, 1.732);\n\nmaplines\n(1, 2) del;\n(3, 4) del;\n\nnewpoints\n(0.5, 0.866) { 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n\nnewlines\n(1, 5);\n(5, 4);\n(3, 5);\n(5, 2);\n\nfreearea\n(0, 0);\n(1, 0) { 1 X2 } { 1 Y2 };\n(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n(1, 1.732) { 1 X3 } { 1 Y3 };\n(0, 1.732) { 1 X4 } { 1 Y4 };\n(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n\nelements\n(1, 2, 5);\n(3, 4, 5);\n\nendrule\n\n\n\n\n\n"
  },
  {
    "path": "setup.py",
    "content": "import glob\nimport os.path\nimport os\nimport sys\nimport pathlib\nimport sysconfig\nimport importlib.metadata\n\nfrom skbuild import setup\nimport skbuild.cmaker\nfrom subprocess import check_output\n\nsetup_requires = ['pybind11-stubgen>=2.5', 'netgen-occt-devel']\n\npyprefix = pathlib.Path(sys.prefix).as_posix()\n\ndef find_occt_dir():\n    for f in importlib.metadata.files(\"netgen-occt-devel\"):\n        if f.match(\"OpenCASCADEConfig.cmake\"):\n            return f.locate().parent.resolve().absolute().as_posix()\n\ndef install_filter(cmake_manifest):\n    print(cmake_manifest)\n    return cmake_manifest\n\ndef _patched_parse_manifests(self):\n    paths = \\\n        glob.glob(os.path.join(skbuild.cmaker.CMAKE_BUILD_DIR(), \"netgen\", \"install_manifest*.txt\"))\n    try:\n        return [self._parse_manifest(path) for path in paths][0]\n    except IndexError:\n        return []\n   \n# we are using the netgen superbuild (to download and build some dependencies)\n# patch the parse_manifests function to point to the actual netgen cmake project within the superbuild\nskbuild.cmaker.CMaker._parse_manifests = _patched_parse_manifests\n\ndef is_dev_build():\n    if 'NG_NO_DEV_PIP_VERSION' in os.environ:\n        return False\n    if 'CI_COMMIT_REF_NAME' in os.environ and os.environ['CI_COMMIT_REF_NAME'] == 'release':\n        return False\n    return True\n\ngit_version = check_output([sys.executable, os.path.join('tests', 'utils.py'), '--get-git-version']).decode('utf-8').strip()\nversion = check_output([sys.executable, os.path.join('tests', 'utils.py'), '--get-version']).decode('utf-8').strip()\n\npy_install_dir = os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')).replace('\\\\','/')\n\nname = \"netgen-mesher\"\narch = None\ncmake_args = [\n        f'-DNETGEN_VERSION_GIT={git_version}',\n        f'-DNETGEN_VERSION_PYTHON={version}',\n        f'-DOpenCascade_DIR={find_occt_dir()}',\n    ]\n\nif 'NETGEN_ARCH' in os.environ and os.environ['NETGEN_ARCH'] == 'avx2':\n    # build for avx2 architecture\n    if 'darwin' in sys.platform:\n        flag = \"'-Xarch_x86_64;-march=core-avx2'\"\n    elif 'win' in sys.platform:\n        flag = '/arch:AVX2'\n    else:\n        flag = '-march=core-avx2'\n    cmake_args += [f'-DNG_COMPILE_FLAGS={flag}']\n\nif 'NETGEN_CCACHE' in os.environ:\n  cmake_args += [f'-DUSE_CCACHE=ON']\n\npackages = ['netgen', 'pyngcore']\n\nhave_mpi = False\nif 'darwin' in sys.platform:\n    cmake_args += [\n        '-DNG_INSTALL_DIR_LIB=netgen',\n        '-DNG_INSTALL_DIR_PYTHON=.',\n        '-DNG_INSTALL_DIR_BIN=bin',\n        '-DNG_INSTALL_DIR_CMAKE=netgen/cmake',\n        '-DNG_INSTALL_DIR_INCLUDE=netgen/include',\n        '-DNG_INSTALL_DIR_RES=share',\n    ]\n    if os.path.exists('/usr/local/include/mpi.h'):\n        have_mpi = True\n        cmake_args += [\n            '-DOPENMPI_INCLUDE_DIR=/usr/local/include',\n        ]\nelif 'win' in sys.platform:\n    cmake_args += [\n        '-A Win64',\n        '-DNG_INSTALL_DIR_BIN=netgen',\n        '-DNG_INSTALL_DIR_PYTHON=.',\n        '-DNG_INSTALL_DIR_LIB=netgen/lib',\n        '-DNG_INSTALL_DIR_CMAKE=netgen/cmake',\n        '-DNG_INSTALL_DIR_INCLUDE=netgen/include',\n    ]\n    py_libdir = pathlib.Path(sys.prefix) / 'Library'\n    lib_file = py_libdir / 'lib' / 'impi.lib'\n    include_dir = py_libdir / 'include'\n    if lib_file.exists():\n        have_mpi = True\n        cmake_args += [\n            f'-DINTEL_MPI_INCLUDE_DIR={include_dir.as_posix()}',\n            f'-DINTEL_MPI_LIBRARY={lib_file.as_posix()}',\n        ]\nelif 'linux' in sys.platform:\n    name_dir = name.replace('-','_')\n    cmake_args += [\n        f'-DNG_INSTALL_DIR_LIB={py_install_dir}/{name_dir}.libs',\n        '-DNG_INSTALL_DIR_BIN=bin',\n        '-DNG_INSTALL_DIR_INCLUDE=include/netgen',\n        '-DTCL_INCLUDE_PATH=/usr/include',\n        '-DTK_INCLUDE_PATH=/usr/include',\n    ]\n    mpich_include = '/opt/mpich/include'\n    openmpi_include = '/opt/openmpi/include'\n    if os.path.exists(mpich_include+'/mpi.h'):\n        have_mpi = True\n        cmake_args += [\n            f'-DMPICH_INCLUDE_DIR={mpich_include}',\n        ]\n    if os.path.exists(openmpi_include+'/mpi.h'):\n        have_mpi = True\n        cmake_args += [\n            f'-DOPENMPI_INCLUDE_DIR={openmpi_include}',\n        ]\n    packages = []\n\nif have_mpi:\n    cmake_args += [\n        '-DUSE_MPI=ON',\n        '-DUSE_MPI_WRAPPER=ON',\n    ]\n\ncmake_args += [\n        '-DUSE_SUPERBUILD:BOOL=ON',\n        '-DUSE_CCACHE:BOOL=ON',\n        '-DUSE_GUI=ON',\n        '-DUSE_NATIVE_ARCH=OFF',\n        '-DBUILD_ZLIB=ON',\n        '-DZLIB_USE_STATIC_LIBS=ON',\n        '-DBUILD_OCC=OFF',\n        '-DUSE_OCC=ON',\n        '-DBUILD_FOR_CONDA=ON',\n        f'-DNETGEN_PYTHON_PACKAGE_NAME={name}',\n        '-DBUILD_STUB_FILES=ON',\n]\n\ncmake_args += [f'-DCMAKE_PREFIX_PATH={pyprefix}', f'-DPython3_ROOT_DIR={pyprefix}']\n\nsetup(\n    name=name,\n    version=version,\n    description=\"Netgen\",\n    author='The Netgen team',\n    license=\"LGPL2.1\",\n    packages=packages,\n    #package_dir={'netgen': 'python'},\n    install_requires=[f\"netgen-occt=={importlib.metadata.version('netgen-occt-devel')}\", \"numpy\"],\n    tests_require=['pytest'],\n    #include_package_data=True,\n    cmake_process_manifest_hook=install_filter,\n    cmake_args = cmake_args,\n    setup_requires=setup_requires,\n    entry_points={\n    'console_scripts': [\n        'netgen = netgen.__main__:main',\n    ],\n},\n)\n"
  },
  {
    "path": "tests/CMakeLists.txt",
    "content": "add_subdirectory(catch)\nadd_subdirectory(pytest)\n\n# this code goes here, because tests is the last add_subdirectory (otherwise it gets executed too early)\nif(APPLE AND BUILD_FOR_CONDA)\n    install(CODE \"execute_process(COMMAND sh -c \\\"codesign --force -s - netgen/*.so netgen/*.dylib pyngcore/*.so\\\" WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX})\")\nendif(APPLE AND BUILD_FOR_CONDA)\n"
  },
  {
    "path": "tests/build_debug.sh",
    "content": "cd\nmkdir -p build/netgen\ncd build/netgen\ncmake \\\n    -DCMAKE_CXX_FLAGS=\"-Og -Wall -Wno-sign-compare -DDebug\" \\\n    -DUSE_CCACHE=ON \\\n    -DCMAKE_BUILD_TYPE=DEBUG \\\n    -DENABLE_UNIT_TESTS=ON \\\n    -DUSE_OCC=ON \\\n    -DCHECK_RANGE=ON \\\n    -DUSE_CGNS=ON \\\n    -DCMAKE_INSTALL_PREFIX=/usr \\\n    ../../src/netgen\nmake -j12\nmake install\n"
  },
  {
    "path": "tests/build_guidelines.sh",
    "content": "cd\nmkdir -p build/netgen\ncd build/netgen\ncmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON -DCMAKE_CXX_COMPILER=clang++ \\\n      -DCMAKE_C_COMPILER=clang\nmake -j12\nmake install\n\n"
  },
  {
    "path": "tests/build_mpi.sh",
    "content": "cd\nmkdir -p build/netgen\ncd build/netgen\ncmake ../../src/netgen \\\n  -DCHECK_RANGE=ON \\\n  -DUSE_CCACHE=ON \\\n  -DUSE_MPI=ON \\\n  -DUSE_OCC=OFF \\\n  -DENABLE_UNIT_TESTS=ON\nmake -j12\nmake install\n"
  },
  {
    "path": "tests/build_ngsolve.sh",
    "content": "cd ~/src\ngit clone https://github.com/NGSolve/ngsolve.git\nmkdir -p ~/build/ngsolve\ncd ~/build/ngsolve\ncmake \\\n  -DCHECK_RANGE=ON \\\n  -DUSE_MKL=ON \\\n  -DUSE_CCACHE=ON \\\n  -DNETGEN_DIR=/opt/netgen \\\n  -DCMAKE_BUILD_TYPE=DEBUG \\\n  ~/src/ngsolve\nmake -j12\nmake install\n"
  },
  {
    "path": "tests/build_nospdlog.sh",
    "content": "cd\nmkdir -p build/netgen\ncd build/netgen\ncmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \\\n      -DCMAKE_C_COMPILER=clang\nmake -j12\nmake install\n\n"
  },
  {
    "path": "tests/build_pip.ps1",
    "content": "if (test-path _skbuild) {\n    cmd.exe /c rd /s /q _skbuild\n}\nif (test-path dist) {\n    cmd.exe /c rd /s /q dist\n}\n\n$env:NETGEN_CCACHE = 1\n$env:NETGEN_ARCH = 'avx2'\n\n$pydir=$args[0]\n& $pydir\\python.exe --version\n& $pydir\\python.exe -m pip install packaging requests\n& $pydir\\python.exe tests\\utils.py --check-pip\nif ($LASTEXITCODE -ne 0) {\n    exit 0\n}\n& $pydir\\python.exe -m pip install scikit-build wheel numpy twine pybind11-stubgen build\n& $pydir\\python.exe -m pip install --upgrade netgen-occt==7.8.1 netgen-occt-devel==7.8.1\n& $pydir\\python -m build -wn .\n& $pydir\\python -m twine upload dist\\*.whl\n"
  },
  {
    "path": "tests/build_pip.sh",
    "content": "set -e\nulimit -n 1024000 # lower open file limit, seems to affect performance\nyum -y update\nyum -y install ninja-build fontconfig-devel tk-devel tcl-devel libXmu-devel mesa-libGLU-devel openmpi-devel mpich-devel\n\nmkdir -p /opt/openmpi/include /opt/mpich/include\ncp -a /usr/include/openmpi-x86_64/* /opt/openmpi/include/\ncp -a /usr/include/mpich-x86_64/* /opt/mpich/include/\n\ncurl https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/c/ccache-3.7.7-1.el8.x86_64.rpm -o ccache.rpm\ndnf -y install ccache.rpm\n\nrm -rf wheelhouse\nexport NETGEN_CCACHE=1\n\nfor pyversion in 314 313 312 311 310\ndo\n    export PYDIR=\"/opt/python/cp${pyversion}-cp${pyversion}/bin\"\n    echo $PYDIR\n    $PYDIR/pip install requests packaging\n    $PYDIR/python3 ./tests/utils.py --check-pip || continue\n    $PYDIR/pip install -U pytest-check numpy wheel scikit-build pybind11-stubgen netgen-occt==7.8.1 netgen-occt-devel==7.8.1\n    $PYDIR/pip install -i https://pypi.anaconda.org/mpi4py/simple/ --pre mpi4py\n\n    rm -rf _skbuild\n    NETGEN_ARCH=avx2 $PYDIR/pip wheel --no-build-isolation .\n    mkdir -p wheelhouse\n    rename linux_x86_64 manylinux_2_17_x86_64.manylinux2014_x86_64 netgen_mesher*-cp${pyversion}-*.whl\n    mv netgen_mesher*-cp${pyversion}-*.whl wheelhouse/\n\n    $PYDIR/pip install wheelhouse/netgen_mesher*-cp${pyversion}-*.whl\n    $PYDIR/python3 -c 'import netgen'\n    $PYDIR/pip install -U twine\n    $PYDIR/twine upload --skip-existing wheelhouse/netgen_mesher*-cp${pyversion}*manylinux*.whl\n    #cd ../tests/pytest\n    #$PYDIR/python3 -m pytest\ndone\n\n"
  },
  {
    "path": "tests/build_pip_mac.sh",
    "content": "set -e\n\nrm -rf _skbuild dist\n\nexport PYDIR=/Library/Frameworks/Python.framework/Versions/$1/bin\nexport PATH=$PYDIR:/Applications/CMake.app/Contents/bin:$PATH\nexport NETGEN_CCACHE=1\n\n$PYDIR/python3 --version\n$PYDIR/python3 -m pip install packaging requests\n$PYDIR/python3 tests/utils.py --check-pip || exit 0\n$PYDIR/python3 -m pip install --user numpy twine scikit-build wheel pybind11-stubgen\n$PYDIR/python3 -m pip install --user -U netgen-occt==7.8.1 netgen-occt-devel==7.8.1\n\nexport CMAKE_OSX_ARCHITECTURES='arm64;x86_64'\nexport NETGEN_ARCH='avx2'\n$PYDIR/python3 setup.py bdist_wheel --plat-name macosx-10.15-universal2 -j10\n$PYDIR/python3 -m twine upload dist/*.whl\n"
  },
  {
    "path": "tests/catch/CMakeLists.txt",
    "content": "\nif(ENABLE_UNIT_TESTS)\nadd_custom_target(unit_tests)\n\n# Build catch_main test object\ninclude_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR})\nadd_library(catch_main STATIC main.cpp)\nset_target_properties(catch_main PROPERTIES CXX_STANDARD 17)\nadd_dependencies(unit_tests catch_main)\nadd_dependencies(catch_main project_catch)\n\n# ensure the test targets are built before testing\nadd_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_tests --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../.. )\n\nmacro(add_unit_test name sources)\n  add_executable(test_${name} ${sources} )\n  target_link_libraries(test_${name} ngcore catch_main nglib)\n\n  add_dependencies(unit_tests test_${name})\n  add_test(NAME unit_${name} COMMAND test_${name})\n  set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built)\n\n  if(ENABLE_CPP_CORE_GUIDELINES_CHECK)\n    set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY \"${DO_CLANG_TIDY}\")\n  endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)\nendmacro()\n\nadd_unit_test(archive archive.cpp)\n# RegisterForArchive needs Python.h if built with Python\ntarget_link_libraries(test_archive netgen_python)\nadd_unit_test(array array.cpp)\nadd_unit_test(ranges ranges.cpp)\nadd_unit_test(symboltable symboltable.cpp)\nadd_unit_test(utils utils.cpp)\nadd_unit_test(version version.cpp)\n\nendif(ENABLE_UNIT_TESTS)\n"
  },
  {
    "path": "tests/catch/archive.cpp",
    "content": "\n#include <catch2/catch.hpp>\n#include <../core/ngcore.hpp>\n#include <core/register_archive.hpp>\n#include <core/logging.hpp>\n#include <meshing.hpp>\nusing namespace ngcore;\nusing namespace std;\n\nclass CommonBase\n{\npublic:\n  int a;\n  virtual ~CommonBase() {}\n\n  virtual void DoArchive(Archive& archive) { archive & a; }\n};\n\n// pure abstract base class\nclass SharedPtrHolder : virtual public CommonBase\n{\npublic:\n  vector<shared_ptr<string>> names;\n  virtual ~SharedPtrHolder()\n  { }\n\n  virtual void abstract() = 0;\n  virtual void DoArchive(Archive& archive)\n  {\n    CommonBase::DoArchive(archive);\n    archive & names;\n  }\n};\n\nclass PtrHolder : virtual public CommonBase\n{\npublic:\n  vector<int*> numbers;\n  virtual ~PtrHolder() {}\n\n  virtual void DoArchive(Archive& archive)\n  {\n    CommonBase::DoArchive(archive);\n    archive & numbers;\n  }\n};\n\nclass SharedPtrAndPtrHolder : public SharedPtrHolder, public PtrHolder\n{\npublic:\n  virtual ~SharedPtrAndPtrHolder() {}\n  virtual void DoArchive(Archive& archive)\n  {\n    SharedPtrHolder::DoArchive(archive);\n    PtrHolder::DoArchive(archive);\n  }\n  virtual void abstract() {}\n};\n\n// Classes without virt. or multiple inheritance do not need to be registered\nclass SimpleClass : public CommonBase\n{\npublic:\n  double d;\n  virtual void DoArchive(Archive& ar)\n  {\n    CommonBase::DoArchive(ar);\n    ar & d;\n  }\n};\n\nclass NotRegisteredForArchive : public SharedPtrAndPtrHolder {};\n\nclass ClassWithConstPtr\n{\nprivate:\n  const int* ptr;\npublic:\n  ClassWithConstPtr(const int* aptr) : ptr(aptr) { }\n  // constructor only for archive\n  ClassWithConstPtr() {}\n  void DoArchive(Archive& ar)\n  {\n    ar & ptr;\n  }\n  const int* getPtr() { return ptr; }\n};\n\nclass ClassWithoutDefaultConstructor\n{\npublic:\n  int a;\n  double b;\n  double c;\n  ClassWithoutDefaultConstructor(int aa, double c) : a(aa), c(c) {}\n\n  void DoArchive(Archive& ar)\n  {\n    ar & b;\n  }\n\n  auto GetCArgs()\n  {\n    return make_tuple(a, c);\n  }\n};\n\nstatic RegisterClassForArchive<ClassWithoutDefaultConstructor> regwdc;\n\nclass OneMoreDerivedClass : public SharedPtrAndPtrHolder {\n};\n\nstatic RegisterClassForArchive<CommonBase> regb;\nstatic RegisterClassForArchive<SharedPtrHolder, CommonBase> regsp;\nstatic RegisterClassForArchive<PtrHolder, CommonBase> regp;\nstatic RegisterClassForArchive<SharedPtrAndPtrHolder, tuple<SharedPtrHolder, PtrHolder>> regspp;\nstatic RegisterClassForArchive<OneMoreDerivedClass, SharedPtrAndPtrHolder> regom;\n\nvoid testNullPtr(Archive& in, Archive& out)\n{\n  SharedPtrHolder* p = nullptr;\n  shared_ptr<string> sp = nullptr;\n  out & p & sp;\n  out.FlushBuffer();\n  SharedPtrHolder* pin = nullptr;\n  shared_ptr<string> spin = nullptr;\n  in & pin & spin;\n  CHECK(pin == nullptr);\n  CHECK(spin == nullptr);\n}\n\nvoid testSharedPointer(Archive& in, Archive& out)\n{\n  SECTION(\"Same shared ptr\")\n    {\n      static_assert(detail::has_DoArchive<SharedPtrHolder>::value, \"\");\n      SharedPtrAndPtrHolder holder, holder2;\n      holder.names.push_back(make_shared<string>(\"name\"));\n      holder2.names = holder.names; // same shared ptr\n      out & holder & holder2;\n      out.FlushBuffer();\n      SharedPtrAndPtrHolder inholder, inholder2;\n      in & inholder & inholder2;\n      CHECK(inholder.names.size() == 1);\n      CHECK(inholder.names[0] == inholder2.names[0]);\n      CHECK(inholder.names[0].use_count() == 3); // one shared ptr is still kept in the archive\n      CHECK(*inholder.names[0] == \"name\");\n    }\n}\n\nvoid testPointer(Archive& in, Archive& out)\n{\n  PtrHolder holder, holder2;\n  holder.numbers.push_back(new int(3));\n  holder2.numbers = holder.numbers; // same shared ptr\n  out & holder & holder2;\n  out.FlushBuffer();\n  PtrHolder inholder, inholder2;\n  in & inholder & inholder2;\n  CHECK(inholder.numbers.size() == 1);\n  CHECK(inholder.numbers[0] == inholder2.numbers[0]);\n  CHECK(*inholder.numbers[0] == 3);\n}\n\nvoid testConstPointer(Archive& in, Archive& out)\n{\n  SECTION(\"Const pointer\")\n    {\n      int* iptr = new int(4);\n      double d = 0.1;\n      ClassWithConstPtr cls(iptr);\n      out & cls & iptr & d;\n      out.FlushBuffer();\n      ClassWithConstPtr incls;\n      int* iniptr;\n      double ind;\n      in & incls & iniptr & ind;\n      CHECK(*incls.getPtr() == 4);\n      CHECK(incls.getPtr() == iniptr);\n      CHECK(ind == 0.1);\n      delete iptr;\n      delete iniptr;\n    }\n}\n\nvoid testMultipleInheritance(Archive& in, Archive& out)\n{\n  PtrHolder* p = new OneMoreDerivedClass;\n  p->numbers.push_back(new int(2));\n  p->a = 5;\n  auto p2 = dynamic_cast<SharedPtrHolder*>(p);\n  p2->names.push_back(make_shared<string>(\"test\"));\n  auto sp1 = shared_ptr<PtrHolder>(p);\n  auto sp2 = dynamic_pointer_cast<SharedPtrHolder>(sp1);\n  auto checkPtr = [] (auto pin, auto pin2)\n  {\n      CHECK(typeid(*pin) == typeid(*pin2));\n      CHECK(typeid(*pin) == typeid(OneMoreDerivedClass));\n      CHECK(*pin2->names[0] == \"test\");\n      CHECK(*pin->numbers[0] == 2);\n      CHECK(dynamic_cast<SharedPtrAndPtrHolder*>(pin) == dynamic_cast<SharedPtrAndPtrHolder*>(pin2));\n      CHECK(pin->a == pin2->a);\n      CHECK(pin->a == 5);\n      REQUIRE(dynamic_cast<SharedPtrAndPtrHolder*>(pin2) != nullptr);\n      CHECK(*dynamic_cast<SharedPtrAndPtrHolder*>(pin2)->numbers[0] == 2);\n      CHECK(*pin->numbers[0] == *dynamic_cast<SharedPtrAndPtrHolder*>(pin2)->numbers[0]);\n      REQUIRE(dynamic_cast<SharedPtrAndPtrHolder*>(pin) != nullptr);\n      CHECK(dynamic_cast<SharedPtrAndPtrHolder*>(pin)->names[0] == pin2->names[0]);\n  };\n  SECTION(\"Archive ptrs to leaves of mult. inh.\")\n    {\n      out & p & p2;\n      out.FlushBuffer();\n      PtrHolder* pin = nullptr;\n      SharedPtrHolder* pin2 = nullptr;\n      in & pin & pin2;\n      checkPtr(pin, pin2);\n    }\n  SECTION(\"Archive shared ptrs to leaves of mult. inh.\")\n    {\n      out & sp1 & sp2;\n      out.FlushBuffer();\n      shared_ptr<PtrHolder> pin;\n      shared_ptr<SharedPtrHolder> pin2;\n      in & pin & pin2;\n      checkPtr(pin.get(), pin2.get());\n    }\n  SECTION(\"Virtual base class\")\n    {\n      CommonBase* b = dynamic_cast<CommonBase*>(p);\n      out & b & p;\n      PtrHolder* pin;\n      CommonBase* bin;\n      in & bin & pin;\n      checkPtr(pin, dynamic_cast<SharedPtrHolder*>(bin));\n    }\n  SECTION(\"Simple class without register\")\n    {\n      auto a = new SimpleClass;\n      a->a = 5;\n      a->d = 2.3;\n      SECTION(\"check pointer\")\n        {\n          out & a;\n          out.FlushBuffer();\n          SimpleClass* ain;\n          in & ain;\n          CHECK(ain->a == 5);\n          CHECK(ain->d == 2.3);\n        }\n      SECTION(\"check shared pointer\")\n        {\n          auto spa = shared_ptr<SimpleClass>(a);\n          out & spa;\n          out.FlushBuffer();\n          shared_ptr<SimpleClass> spain;\n          in & spain;\n          CHECK(spain->a == 5);\n          CHECK(spain->d == 2.3);\n        }\n    }\n}\n\nvoid testMap(Archive& in, Archive& out)\n{\n  map<string, VersionInfo> map1;\n  map1[\"netgen\"] = \"v6.2.1901\";\n  out & map1;\n  out.FlushBuffer();\n  map<string, VersionInfo> map2;\n  in & map2;\n  CHECK(map2.size() == 1);\n  CHECK(map2[\"netgen\"] == \"v6.2.1901\");\n}\n\nenum MyEnum\n  {\n   CASE1,\n   CASE2\n  };\n\nvoid testEnum(Archive& in, Archive& out)\n  {\n   MyEnum en = CASE2;\n   out & en;\n   out.FlushBuffer();\n   MyEnum enin;\n   in & enin;\n   CHECK(enin == CASE2);\n  }\n\nvoid testOptional(Archive& in, Archive& out)\n  {\n    {\n      std::optional<int> no_value;\n      std::optional<int> myint = 42;\n      std::optional<string> mystr = \"have an optional string\";\n      out & no_value & myint & mystr;\n      out.FlushBuffer();\n    }\n    {\n      std::optional<int> no_value_;\n      std::optional<int> myint_;\n      std::optional<string> mystr_;\n      in & no_value_ & myint_ & mystr_;\n      CHECK(no_value_.has_value() == false);\n      CHECK(myint_.has_value() == true);\n      CHECK(*myint_ == 42);\n      CHECK(mystr_.has_value() == true);\n      CHECK(*mystr_ == \"have an optional string\");\n    }\n  }\n\nvoid testArchive(Archive& in, Archive& out)\n{\n  SECTION(\"Empty String\")\n    {\n      char* cstr = nullptr;\n      char* empty = new char[1];\n      char* simple = new char[7] {'s','i','m','p','l','e','\\0'};\n      empty[0] = '\\0';\n      out << string(\"\") << cstr << empty << simple << string(\"simple\") << long(1);\n      out.FlushBuffer();\n      string str; long i; char* readempty; char* readsimple;\n      string simplestr;\n      in & str & cstr & readempty & readsimple & simplestr & i;\n      CHECK(str == \"\");\n      CHECK(cstr == nullptr);\n      CHECK(strcmp(readempty,\"\") == 0);\n      CHECK(strcmp(readsimple,\"simple\") == 0);\n      CHECK(i == 1);\n      CHECK(simplestr == \"simple\");\n      delete[] readempty;\n      delete[] empty;\n      delete[] simple;\n      delete[] readsimple;\n    }\n  SECTION(\"SharedPtr\")\n    {\n      testSharedPointer(in, out);\n    }\n  SECTION(\"Pointer\")\n    {\n      testPointer(in, out);\n    }\n  SECTION(\"Const Pointer\")\n    {\n      testConstPointer(in, out);\n    }\n  SECTION(\"Multiple inheritance\")\n    {\n      testMultipleInheritance(in, out);\n    }\n  SECTION(\"Not registered\")\n    {\n      SharedPtrAndPtrHolder* p = new NotRegisteredForArchive;\n      REQUIRE_THROWS(out & p, Catch::Contains(\"not registered for archive\"));\n    }\n  SECTION(\"Non-default constructor\")\n    {\n      ClassWithoutDefaultConstructor c(5, 2.2);\n      c.b = 3.2;\n      auto p = &c;\n      out & p;\n      out.FlushBuffer();\n      ClassWithoutDefaultConstructor* cin;\n      in & cin;\n      CHECK(cin->a == 5);\n      CHECK(cin->b == 3.2);\n      CHECK(cin->c == 2.2);\n    }\n  SECTION(\"nullptr\")\n    {\n      testNullPtr(in, out);\n    }\n  SECTION(\"map\")\n    {\n      testMap(in, out);\n    }\n  SECTION(\"enum\")\n    {\n      testEnum(in, out);\n    }\n  SECTION(\"optional\")\n    {\n      testOptional(in, out);\n    }\n}\n\nTEST_CASE(\"BinaryArchive\")\n{\n  auto stream = make_shared<stringstream>();\n  BinaryOutArchive out(stream);\n  BinaryInArchive in(stream);\n  testArchive(in, out);\n}\n\nTEST_CASE(\"TextArchive\")\n{\n  auto stream = make_shared<stringstream>();\n  TextOutArchive out(stream);\n  TextInArchive in(stream);\n  testArchive(in, out);\n}\n\n\ntemplate <typename T>\nauto CheckCopyWithArchive(const T * v) {\n  T * tcopy = nullptr;\n  auto tstream = make_shared<stringstream>();\n  TextOutArchive tout(tstream);\n  tout & v;\n  TextInArchive tin(tstream);\n  tin & tcopy;\n\n  T *bcopy = nullptr;\n  auto bstream = make_shared<stringstream>();\n  BinaryOutArchive bout(bstream);\n  bout & v;\n  bout.FlushBuffer();\n  BinaryInArchive in(bstream);\n  in & bcopy;\n\n  CHECK(*v == *tcopy);\n  CHECK(*v == *bcopy);\n  CHECK(*bcopy == *bcopy);\n}\n\nTEST_CASE(\"CopyWithArchive\")\n{\n  Array<int> aint{1,2,5,67,23252};\n  CheckCopyWithArchive(&aint);\n\n  std::vector<byte> abyte{byte(1), byte(3), byte(255), byte(0), byte(76)};\n  CheckCopyWithArchive(&abyte);\n}\n"
  },
  {
    "path": "tests/catch/array.cpp",
    "content": "\n#include <catch2/catch.hpp>\n#include <core/array.hpp>\nusing namespace ngcore;\nusing namespace std;\n\n#include \"meshing.hpp\"\n\ntemplate<typename TIND>\nclass ClsWithIndexType\n{\n  size_t size;\npublic:\n  ClsWithIndexType(size_t asize) : size(asize) {}\n  using index_type = TIND;\n  size_t Size() const { return size; }\n};\n\ntemplate<typename TIND>\nclass ClsWithRange : public ClsWithIndexType<TIND>\n{\npublic:\n  ClsWithRange(size_t size) : ClsWithIndexType<TIND>(size) {}\n  T_Range<size_t> Range() const { return {1, 1+this->Size()}; }\n};\n\n\nTEST_CASE(\"Array\")\n{\n  Array<int> array;\n#ifdef DEBUG\n  CHECK_THROWS_AS(array[0], RangeException);\n  CHECK_THROWS_AS(array.DeleteLast(), RangeException);\n  CHECK_THROWS_AS(array.Last(), RangeException);\n#endif // DEBUG\n  Array<double> a_initlst = { 1., 2., 3.};\n  CHECK(a_initlst[1] == 2.);\n  CHECK(a_initlst.Size() == 3);\n  FlatArray fa_a = a_initlst;\n  CHECK(typeid(fa_a) == typeid(FlatArray<double>));\n  CHECK(fa_a.Size() == 3);\n  CHECK(fa_a.Last() == 3.);\n  a_initlst.DeleteLast();\n  CHECK(a_initlst.Last() == 2.);\n  CHECK(a_initlst.Size() == 2);\n#ifdef DEBUG\n  CHECK_THROWS_AS(fa_a[5], RangeException);\n#endif // DEBUG\n  Array b = Array<int>(4);\n  b = 2;\n  int count = 0;\n  for(auto val : b)\n  {\n    count++;\n    CHECK(val == 2);\n  }\n  CHECK(count == 4);\n\n  // range tests\n  CHECK(typeid(array.Range()) == typeid(T_Range<size_t>));\n  Array<int, int> intarray;\n  CHECK(typeid(intarray.Range()) == typeid(T_Range<int>));\n  CHECK(typeid(Range(intarray)) == typeid(T_Range<int>));\n  int i = 0;\n  for(auto j : Range(b))\n    CHECK(j == i++);\n  i = 0;\n  for(auto j : b.Range())\n    CHECK(j == i++);\n\n  // pointindex is still 1 based\n  Array<double, netgen::PointIndex> piarray(2);\n  netgen::PointIndex pi = IndexBASE<netgen::PointIndex>();\n  for(auto j : Range(piarray))\n    CHECK(j == pi++);\n  pi = IndexBASE<netgen::PointIndex>();\n  for(auto j : piarray.Range())\n    CHECK(j == pi++);\n  // a class can implement index_type and Size as well.\n  ClsWithIndexType<int> clsi(3);\n  CHECK(typeid(Range(clsi)) == typeid(T_Range<int>));\n  i = 0;\n  for(auto j : Range(clsi))\n    CHECK(j == i++);\n  // if the class has a Range function prefer that one\n  ClsWithRange<int> clsr(3);\n  CHECK(typeid(Range(clsr)) == typeid(T_Range<size_t>));\n  i=1;\n  for(auto j : Range(clsr))\n    CHECK(j == i++);\n  CHECK(typeid(Range(size_t(4))) == typeid(T_Range<size_t>));\n  CHECK(typeid(Range(4)) == typeid(T_Range<int>));\n}\n"
  },
  {
    "path": "tests/catch/main.cpp",
    "content": "#define CATCH_CONFIG_MAIN\n#define DO_NOT_USE_WMAIN\n#include <catch2/catch.hpp>\n"
  },
  {
    "path": "tests/catch/ranges.cpp",
    "content": "\n#include <catch2/catch.hpp>\n\n#include <core/array.hpp>\n#include <core/ranges.hpp>\n\nusing namespace ngcore;\n\nTEST_CASE(\"ranges\")\n{\n  Array<int> a { 3, -1, 10, -5 };\n  Array<int> positive { 3, 10 };\n  int i = 0;\n  for(auto pos_val : a | filter([](auto val) { return val >= 0; }))\n    {\n      CHECK(pos_val == positive[i++]);\n    }\n}\n"
  },
  {
    "path": "tests/catch/symboltable.cpp",
    "content": "\n#include <catch2/catch.hpp>\n#include <../core/ngcore.hpp>\nusing namespace ngcore;\nusing namespace std;\n\nTEST_CASE(\"Symboltable\")\n{\n  SymbolTable<int> table;\n  CHECK_THROWS_AS(table[\"test\"], RangeException);\n  table.Set(\"first\", 1);\n  CHECK(table[\"first\"] == 1);\n  table[\"first\"] = 2;\n  CHECK(table[\"first\"] == 2);\n  auto index = table.Index(\"first\");\n  CHECK(index == 0);\n  CHECK(table[index] == 2);\n  table[index] = 3;\n  CHECK(table[\"first\"] == 3);\n#ifndef NDEBUG\n  int a;\n  CHECK_THROWS_AS(a = table[5], RangeException);\n  CHECK_THROWS_AS(table.GetName(5), RangeException);\n#endif\n  CHECK(table.Used(\"first\"));\n  CHECK(!table.Used(\"second\"));\n  SymbolTable<int> another;\n  another.Set(\"first\", 1);\n  another.Set(\"second\", 2);\n  table.Update(another);\n  CHECK(table[\"first\"] == 1);\n  CHECK(table[\"second\"] == 2);\n  std::stringstream s;\n  s << table;\n  CHECK(s.str() == \"first : 1\\nsecond : 2\\n\");\n  auto ss = std::make_shared<std::stringstream>();\n  BinaryOutArchive ao(ss);\n  ao & table;\n  ao.FlushBuffer();\n  BinaryInArchive ai(ss);\n  SymbolTable<int> read;\n  ai & read;\n  for(size_t i = 0; i<table.Size(); i++)\n    {\n      CHECK(read[i] == table[i]);\n      CHECK(read.GetName(i) == table.GetName(i));\n    }\n  table.DeleteAll();\n  CHECK(table.Size() == 0);\n  // SymbolTable<bool> is special because of vector<bool> is special...\n  SymbolTable<bool> btable;\n  btable.Set(\"true\", true);\n  btable.Set(\"false\", false);\n  CHECK(btable[0]);\n  CHECK(!btable[1]);\n  CHECK(btable[\"true\"]);\n  CHECK(!btable[\"false\"]);\n  ao & btable;\n  ao.FlushBuffer();\n  SymbolTable<bool> bread;\n  ai & bread;\n  CHECK(bread[\"true\"]);\n  CHECK(!bread[\"false\"]);\n}\n"
  },
  {
    "path": "tests/catch/utils.cpp",
    "content": "\n#include <catch2/catch.hpp>\n#include <core/ngcore.hpp>\nusing namespace ngcore;\nusing namespace std;\n\n\nuint64_t shuffle(uint64_t N, uint64_t i) {\n    // Shuffle the numbers using multiplication with a prime number to force many updates of min, max\n    constexpr uint64_t P = 101;\n    return (N/2 + i*P) % N;\n}\n\nvoid testThreading(int n_threads)\n{\n  TaskManager::SetNumThreads(n_threads);\n  n_threads = EnterTaskManager();\n\n  constexpr uint64_t N = 100000;\n\n\n  SECTION( \"atomic operations\" ) {\n      uint64_t i_min = 2*N;\n      uint64_t i_max = 0;\n      uint64_t i_sum = 0;\n\n      double d_min = 1e100;\n      double d_max = 0.0;\n      double d_sum = 0.0;\n\n      ParallelFor( Range(N), [&] (uint64_t i) {\n          AtomicMin(i_min, shuffle(N,i));\n      });\n      REQUIRE( i_min==0 );\n\n      ParallelFor( Range(N), [&] (uint64_t i) {\n          AtomicMax(i_max, shuffle(N,i));\n      });\n      REQUIRE( i_max==N-1 );\n\n      ParallelFor( Range(N), [&] (uint64_t i) {\n          AsAtomic(i_sum) += i;\n      });\n      REQUIRE( i_sum==N*(N-1)/2 );\n\n      ParallelFor( Range(N), [&] (double i) {\n          AtomicMin(d_min, static_cast<double>(shuffle(N,i)));\n      });\n      REQUIRE( d_min==0 );\n\n      ParallelFor( Range(N), [&] (double i) {\n          AtomicMax(d_max, static_cast<double>(shuffle(N,i)));\n      });\n      REQUIRE( d_max==N-1 );\n\n      ParallelFor( Range(N), [&] (double i) {\n          AtomicAdd(d_sum, i);\n      });\n      REQUIRE( d_sum==N*(N-1)/2 );\n\n  }\n  ExitTaskManager(n_threads);\n}\n\nTEST_CASE(\"Threading - 1 Thread\") { testThreading(1); }\nTEST_CASE(\"Threading - 2 Thread\") { testThreading(2); }\nTEST_CASE(\"Threading - 8 Thread\") { testThreading(8); }\n"
  },
  {
    "path": "tests/catch/version.cpp",
    "content": "\n#include <catch2/catch.hpp>\n#include <../core/ngcore.hpp>\nusing namespace ngcore;\nusing namespace std;\n\n\nTEST_CASE(\"Version\")\n{\n  VersionInfo v(\"v6.2.1811-3-asdf\");\n  CHECK(v.to_string() == \"v6.2.1811-3-asdf\");\n  VersionInfo v2(\"6.2\");\n  CHECK(v2.to_string() == \"v6.2\");\n  CHECK(v < \"v7\");\n  CHECK(v >= \"6.2\");\n  CHECK(v > \"6.2.1811\");\n  CHECK(v < \"6.2.1811-5\");\n  CHECK(v == \"v6.2.1811-3\");\n}\n"
  },
  {
    "path": "tests/dockerfile",
    "content": "FROM ubuntu:22.04\nENV DEBIAN_FRONTEND=noninteractive\nMAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>\nRUN apt-get update && apt-get -y install \\\n        ccache \\\n        clang occt-misc \\\n        clang-tidy \\\n        cmake \\\n        g++ \\\n        git \\\n        libcgns-dev \\\n        libglu1-mesa-dev \\\n        libhdf5-dev \\\n        libocct-ocaf-dev \\\n        libocct-visualization-dev \\\n        libocct-data-exchange-dev \\\n        libocct-draw-dev \\\n        libpython3-dev \\\n        libtbb-dev \\\n        libxi-dev \\\n        libxmu-dev \\\n        occt-misc \\\n        python3 \\\n        python3-distutils \\\n        python3-numpy \\\n        python3-pip \\\n        python3-pytest \\\n        python3-tk \\\n        tcl-dev \\\n        tk-dev\n\nRUN python3 -m pip install pytest-check pybind11-stubgen\nADD . /root/src/netgen\n"
  },
  {
    "path": "tests/dockerfile_mpi",
    "content": "FROM ubuntu:22.04\nENV DEBIAN_FRONTEND=noninteractive\nMAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>\nRUN apt-get update && apt-get -y install \\\n        ccache \\\n        clang \\\n        clang-tidy \\\n        cmake \\\n        g++ \\\n        gfortran \\\n        git \\\n        libglu1-mesa-dev \\\n        libopenmpi-dev \\\n        libpython3-dev \\\n        libxmu-dev \\\n        openmpi-bin \\\n        python3 \\\n        python3-distutils \\\n        python3-mpi4py \\\n        python3-numpy \\\n        python3-pip \\\n        python3-tk \\\n        tcl-dev \\\n        tk-dev\n\nRUN python3 -m pip install pytest-mpi pytest-check pytest pybind11-stubgen\nADD . /root/src/netgen\n"
  },
  {
    "path": "tests/pytest/CMakeLists.txt",
    "content": "if(USE_PYTHON)\n    add_test(NAME pytest COMMAND ${Python3_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\n    add_custom_target(pytest ${Python3_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\n    set_tests_properties ( pytest PROPERTIES TIMEOUT 1800 )\n    if(USE_MPI AND USE_MPI4PY)\n      add_test(NAME pytest-mpi COMMAND ${MPIEXEC_EXECUTABLE} --allow-run-as-root -np 4 ${Python3_EXECUTABLE} -m pytest --with-mpi test_mpi4py.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\n    endif(USE_MPI AND USE_MPI4PY)\nendif(USE_PYTHON)\n"
  },
  {
    "path": "tests/pytest/compare_results.py",
    "content": "import json\nimport sys\nimport subprocess\nimport statistics\n\ndef readData(a, files):\n    amin=[]\n    amax=[]\n    amin1=[]\n    amax1=[]\n    bad=[]\n    ne1d=[]\n    ne2d=[]\n    ne3d=[]\n    file=[]\n    for f in files:\n        if f == 'cylinder.geo':\n            continue\n        for t in a[f]:\n            if t['ne1d']>0:\n                ne1d.append(t['ne1d'])\n            if t['ne2d']>0:\n                ne2d.append(t['ne2d'])\n            if t['ne3d']>0:\n                ne3d.append(t['ne3d'])\n            if t['total_badness']>0.0:\n                bad.append(t['total_badness'])\n                file.append(f)\n                if 'angles_tet' in t:\n                    amin.append(t['angles_tet'][0])\n                    amax.append(t['angles_tet'][1])\n                if 'angles_trig' in t:\n                    amin1.append(t['angles_trig'][0])\n                    amax1.append(t['angles_trig'][1])\n    return {\n            \"min tet angle\":amin,\n            \"max tet angle\" : amax,\n            \"min trig angle\":amin1,\n            \"max trig angle\" : amax1,\n            \"badness\" : bad,\n            \"#edges\" : ne1d,\n            \"#trigs\" : ne2d,\n            \"#tets\" : ne3d,\n            \"file\" : file,\n            }\n\nimport matplotlib.pyplot as plt\n\nref = 'master'\nif len(sys.argv)>1:\n    ref = sys.argv[1]\n\nres = subprocess.run(['git','show','{}:./results.json'.format(ref)], capture_output=True)\ns = json.loads(res.stdout.decode())\n\nif len(sys.argv) > 2:\n    ref2 = sys.argv[2]\n    res = subprocess.run(['git','show','{}:./results.json'.format(ref2)], capture_output=True)\n    s2 = res.stdout.decode()\nelse:\n    ref2 = 'current'\n    s2 = open('results.json','r').read()\ns2 = json.loads(s2)\n\nfilenames = [f for f in s if f in s2]\ndata = readData(s, filenames)\ndata2 = readData(s2, filenames)\n\nassert(len(data) == len(data2))\n\nw = 90\nGREEN = '\\033[92m'\nRED = '\\033[91m'\nRESET = '\\033[0m'\n\nfor bad1,bad2, f1, f2 in zip(data['badness'], data2['badness'], data['file'], data2['file']):\n    assert f1==f2\n\n    diff = f\"{100*(bad2-bad1)/bad1:+.2f}%\"\n    if bad2>0 and bad2>1.2*bad1:\n        print(f\"{RED}badness {f1} got worse:  {bad1} -> {bad2}\".ljust(w) + diff + RESET)\n    if bad2>0 and bad2<0.8*bad1:\n        print(f\"{GREEN}badness {f1} got better: {bad1} -> {bad2}\".ljust(w) + diff + RESET)\n\nfor bad1,bad2, f1, f2 in zip(data['#trigs'], data2['#trigs'], data['file'], data2['file']):\n    assert f1==f2\n    diff = f\"{100*(bad2-bad1)/bad1:+.2f}%\"\n    if bad2>0 and bad2>1.2*bad1:\n        print(f\"{RED}ntrigs {f1} got worse:  {bad1} -> {bad2}\".ljust(w) + diff + RESET)\n    if bad2>0 and bad2<0.8*bad1:\n        print(f\"{GREEN}ntrigs {f1} got better: {bad1} -> {bad2}\".ljust(w) + diff + RESET)\n\nn = len(data) + 1\nfig, ax = plt.subplots(figsize=(15, 7))  # Adjust figsize as needed\nplt.xticks([])\nplt.yticks([])\nax.yaxis.grid(False)\nax.xaxis.grid(False)\nfor i, d in enumerate(['min trig angle', 'min tet angle', 'max trig angle', 'max tet angle']):\n    plt.subplot(2, 4, i + 1)  # Remove ax = \n    plt.title(d)\n    # plt.xticks([1, 2])\n    if len(data[d]) == 0 or len(data2[d]) == 0:\n        continue\n\n    plt.violinplot([data[d], data2[d]], showmedians=True)\n    med = statistics.median(data[d])\n    plt.hlines(med, 1, 2, linestyle='dotted')\n    if d == 'badness':\n        plt.yscale('log')\n    plt.xticks([1, 2], [ref, ref2])\n\nfor i, d in enumerate(['badness', '#edges', '#trigs', '#tets']):\n    plt.xticks([])\n    plt.subplot(2, 4, 5 + i)\n    plt.title('difference ' + d + ' (in %)')\n    plt.boxplot([100.0 * (y - x) / x for x, y in zip(data[d], data2[d])])\n    plt.hlines(0.0, 0.5, 1.5, linestyle='dotted')\n\nplt.tight_layout()  # Adjust layout\n\n\n# plt.savefig('comparison.png', dpi=100)\nplt.show()\n \n"
  },
  {
    "path": "tests/pytest/conftest.py",
    "content": "\"\"\"\nPytest configuration file to run slow test only if pytest is started with option --runslow or if\nenvironment variable RUN_SLOW_TESTS is set.\n\"\"\"\n\nimport pytest, os\n\ndef pytest_addoption(parser):\n    parser.addoption(\"--runslow\", action=\"store_true\", default=False, help=\"run slow tests\")\n\ndef pytest_configure(config):\n    config.addinivalue_line(\"markers\", \"slow: mark test as slow to run\")\n\n\ndef pytest_collection_modifyitems(config, items):\n    import platform\n\n    run_slow_tests = config.getoption(\"--runslow\")\n\n    # gitlab-ci: run slow tests only on Linux\n    if platform.system()=='Linux' and 'RUN_SLOW_TESTS' in os.environ and os.environ['RUN_SLOW_TESTS']:\n        run_slow_tests = True\n\n    if not run_slow_tests:\n        skip_slow = pytest.mark.skip(reason=\"need --runslow option to run\")\n        for item in items:\n            if \"slow\" in item.keywords:\n                item.add_marker(skip_slow)\n"
  },
  {
    "path": "tests/pytest/geofiles/plane.stl",
    "content": "solid Exported from Blender-2.80 (sub 74)\nfacet normal 0.191110 0.013657 0.981474\nouter loop\nvertex 21.194145 2.557368 9.374599\nvertex 21.148577 1.562913 9.397309\nvertex 22.736126 1.562173 9.088195\nendloop\nendfacet\nfacet normal 0.185636 0.004848 0.982607\nouter loop\nvertex 21.194145 2.557368 9.374599\nvertex 22.736126 1.562173 9.088195\nvertex 22.751976 2.556384 9.080295\nendloop\nendfacet\nfacet normal 0.204879 0.041043 0.977926\nouter loop\nvertex 21.148577 1.562913 9.397309\nvertex 21.028854 0.738857 9.456977\nvertex 22.697634 0.738462 9.107379\nendloop\nendfacet\nfacet normal 0.191110 0.013928 0.981470\nouter loop\nvertex 21.148577 1.562913 9.397309\nvertex 22.697634 0.738462 9.107379\nvertex 22.736126 1.562173 9.088195\nendloop\nendfacet\nfacet normal 0.217324 0.004292 0.976090\nouter loop\nvertex 22.751976 2.556384 9.080295\nvertex 22.736126 1.562173 9.088195\nvertex 24.224312 1.561327 8.756858\nendloop\nendfacet\nfacet normal 0.214909 0.000543 0.976634\nouter loop\nvertex 22.751976 2.556384 9.080295\nvertex 24.224312 1.561327 8.756858\nvertex 24.226292 2.555258 8.755870\nendloop\nendfacet\nfacet normal 0.222975 0.012281 0.974747\nouter loop\nvertex 22.736126 1.562173 9.088195\nvertex 22.697634 0.738462 9.107379\nvertex 24.219498 0.738010 8.759255\nendloop\nendfacet\nfacet normal 0.217324 0.001572 0.976098\nouter loop\nvertex 22.736126 1.562173 9.088195\nvertex 24.219498 0.738010 8.759255\nvertex 24.224312 1.561327 8.756858\nendloop\nendfacet\nfacet normal 0.135843 0.002594 0.990727\nouter loop\nvertex 19.769468 3.808219 9.566667\nvertex 19.760412 2.558099 9.571181\nvertex 21.194145 2.557368 9.374599\nendloop\nendfacet\nfacet normal 0.135217 0.001868 0.990814\nouter loop\nvertex 19.769468 3.808219 9.566667\nvertex 21.194145 2.557368 9.374599\nvertex 21.200653 3.807420 9.371354\nendloop\nendfacet\nfacet normal 0.140126 0.022514 0.989878\nouter loop\nvertex 19.760412 2.558099 9.571181\nvertex 19.697014 1.563463 9.602778\nvertex 21.148577 1.562913 9.397309\nendloop\nendfacet\nfacet normal 0.135833 0.016398 0.990596\nouter loop\nvertex 19.760412 2.558099 9.571181\nvertex 21.148577 1.562913 9.397309\nvertex 21.194145 2.557368 9.374599\nendloop\nendfacet\nfacet normal 0.155681 0.077323 0.984776\nouter loop\nvertex 19.697014 1.563463 9.602778\nvertex 19.506817 0.739151 9.697570\nvertex 21.028854 0.738857 9.456977\nendloop\nendfacet\nfacet normal 0.139988 0.051260 0.988825\nouter loop\nvertex 19.697014 1.563463 9.602778\nvertex 21.028854 0.738857 9.456977\nvertex 21.148577 1.562913 9.397309\nendloop\nendfacet\nfacet normal 0.219664 0.209516 0.952812\nouter loop\nvertex 19.506817 0.739151 9.697570\nvertex 18.900000 0.000000 10.000000\nvertex 20.833847 0.000000 9.554167\nendloop\nendfacet\nfacet normal 0.155540 0.088368 0.983869\nouter loop\nvertex 19.506817 0.739151 9.697570\nvertex 20.833847 0.000000 9.554167\nvertex 21.028854 0.738857 9.456977\nendloop\nendfacet\nfacet normal 0.225734 0.068252 0.971795\nouter loop\nvertex 21.028854 0.738857 9.456977\nvertex 20.833847 0.000000 9.554167\nvertex 22.645555 0.000000 9.133333\nendloop\nendfacet\nfacet normal 0.205006 0.019935 0.978558\nouter loop\nvertex 21.028854 0.738857 9.456977\nvertex 22.645555 0.000000 9.133333\nvertex 22.697634 0.738462 9.107379\nendloop\nendfacet\nfacet normal 0.230193 0.017963 0.972979\nouter loop\nvertex 22.697634 0.738462 9.107379\nvertex 22.645555 0.000000 9.133333\nvertex 24.212990 0.000000 8.762500\nendloop\nendfacet\nfacet normal 0.222988 0.002319 0.974818\nouter loop\nvertex 22.697634 0.738462 9.107379\nvertex 24.212990 0.000000 8.762500\nvertex 24.219498 0.738010 8.759255\nendloop\nendfacet\nfacet normal 0.239169 0.002159 0.970976\nouter loop\nvertex 24.219498 0.738010 8.759255\nvertex 24.212990 0.000000 8.762500\nvertex 25.414011 0.000000 8.466667\nendloop\nendfacet\nfacet normal 0.237910 0.000000 0.971287\nouter loop\nvertex 24.219498 0.738010 8.759255\nvertex 25.414011 0.000000 8.466667\nvertex 25.414009 0.737545 8.466667\nendloop\nendfacet\nfacet normal 0.237910 0.001437 0.971286\nouter loop\nvertex 24.224312 1.561327 8.756858\nvertex 24.219498 0.738010 8.759255\nvertex 25.414009 0.737545 8.466667\nendloop\nendfacet\nfacet normal 0.236973 0.000002 0.971516\nouter loop\nvertex 24.224312 1.561327 8.756858\nvertex 25.414009 0.737545 8.466667\nvertex 25.414009 1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.236973 0.000494 0.971516\nouter loop\nvertex 24.226292 2.555258 8.755870\nvertex 24.224312 1.561327 8.756858\nvertex 25.414009 1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.236582 -0.000001 0.971611\nouter loop\nvertex 24.226292 2.555258 8.755870\nvertex 25.414009 1.560457 8.466666\nvertex 25.414009 2.554101 8.466667\nendloop\nendfacet\nfacet normal 0.236583 0.000056 0.971611\nouter loop\nvertex 24.226574 3.805111 8.755730\nvertex 24.226292 2.555258 8.755870\nvertex 25.414009 2.554101 8.466667\nendloop\nendfacet\nfacet normal 0.236526 -0.000001 0.971625\nouter loop\nvertex 24.226574 3.805111 8.755730\nvertex 25.414009 2.554101 8.466667\nvertex 25.414011 3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.214909 0.000492 0.976634\nouter loop\nvertex 22.754240 3.806343 9.079166\nvertex 22.751976 2.556384 9.080295\nvertex 24.226292 2.555258 8.755870\nendloop\nendfacet\nfacet normal 0.214560 0.000062 0.976711\nouter loop\nvertex 22.754240 3.806343 9.079166\nvertex 24.226292 2.555258 8.755870\nvertex 24.226574 3.805111 8.755730\nendloop\nendfacet\nfacet normal 0.185636 0.001584 0.982617\nouter loop\nvertex 21.200653 3.807420 9.371354\nvertex 21.194145 2.557368 9.374599\nvertex 22.751976 2.556384 9.080295\nendloop\nendfacet\nfacet normal 0.184832 0.000552 0.982770\nouter loop\nvertex 21.200653 3.807420 9.371354\nvertex 22.751976 2.556384 9.080295\nvertex 22.754240 3.806343 9.079166\nendloop\nendfacet\nfacet normal -0.091368 0.009363 0.995773\nouter loop\nvertex 18.613682 2.558479 9.619390\nvertex 17.733503 2.558462 9.538629\nvertex 17.717653 1.563737 9.546528\nendloop\nendfacet\nfacet normal -0.111632 0.027793 0.993361\nouter loop\nvertex 18.613682 2.558479 9.619390\nvertex 17.717653 1.563737 9.546528\nvertex 18.568115 1.563749 9.642101\nendloop\nendfacet\nfacet normal -0.247479 0.001455 0.968892\nouter loop\nvertex 17.733503 2.558462 9.538629\nvertex 17.054708 2.558016 9.365246\nvertex 17.052727 1.563401 9.366233\nendloop\nendfacet\nfacet normal -0.261688 0.011834 0.965080\nouter loop\nvertex 17.733503 2.558462 9.538629\nvertex 17.052727 1.563401 9.366233\nvertex 17.717653 1.563737 9.546528\nendloop\nendfacet\nfacet normal -0.111632 0.028326 0.993346\nouter loop\nvertex 18.568115 1.563749 9.642101\nvertex 17.717653 1.563737 9.546528\nvertex 17.679161 0.739297 9.565712\nendloop\nendfacet\nfacet normal -0.173365 0.096112 0.980157\nouter loop\nvertex 18.568115 1.563749 9.642101\nvertex 17.679161 0.739297 9.565712\nvertex 18.448393 0.739303 9.701769\nendloop\nendfacet\nfacet normal -0.261698 0.004334 0.965140\nouter loop\nvertex 17.717653 1.563737 9.546528\nvertex 17.052727 1.563401 9.366233\nvertex 17.047916 0.739118 9.368630\nendloop\nendfacet\nfacet normal -0.297839 0.036104 0.953933\nouter loop\nvertex 17.717653 1.563737 9.546528\nvertex 17.047916 0.739118 9.368630\nvertex 17.679161 0.739297 9.565712\nendloop\nendfacet\nfacet normal 0.043013 0.002369 0.999072\nouter loop\nvertex 19.769468 3.808219 9.566667\nvertex 18.620193 3.808635 9.616146\nvertex 18.613682 2.558479 9.619390\nendloop\nendfacet\nfacet normal 0.042005 0.003304 0.999112\nouter loop\nvertex 19.769468 3.808219 9.566667\nvertex 18.613682 2.558479 9.619390\nvertex 19.760412 2.558099 9.571181\nendloop\nendfacet\nfacet normal -0.088572 0.001059 0.996069\nouter loop\nvertex 18.620193 3.808635 9.616146\nvertex 17.735767 3.808617 9.537500\nvertex 17.733503 2.558462 9.538629\nendloop\nendfacet\nfacet normal -0.091374 0.003061 0.995812\nouter loop\nvertex 18.620193 3.808635 9.616146\nvertex 17.733503 2.558462 9.538629\nvertex 18.613682 2.558479 9.619390\nendloop\nendfacet\nfacet normal -0.245484 0.000165 0.969401\nouter loop\nvertex 17.735767 3.808617 9.537500\nvertex 17.054991 3.808129 9.365105\nvertex 17.054708 2.558016 9.365246\nendloop\nendfacet\nfacet normal -0.247484 0.001322 0.968891\nouter loop\nvertex 17.735767 3.808617 9.537500\nvertex 17.054708 2.558016 9.365246\nvertex 17.733503 2.558462 9.538629\nendloop\nendfacet\nfacet normal -0.395446 0.000000 0.918489\nouter loop\nvertex 17.054991 3.808129 9.365105\nvertex 16.516666 3.807135 9.133333\nvertex 16.516666 2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.395828 0.000193 0.918324\nouter loop\nvertex 17.054991 3.808129 9.365105\nvertex 16.516666 2.557108 9.133333\nvertex 17.054708 2.558016 9.365246\nendloop\nendfacet\nfacet normal -0.395827 0.000000 0.918325\nouter loop\nvertex 17.054708 2.558016 9.365246\nvertex 16.516666 2.557108 9.133333\nvertex 16.516666 1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.398483 0.001704 0.917174\nouter loop\nvertex 17.054708 2.558016 9.365246\nvertex 16.516666 1.562718 9.133333\nvertex 17.052727 1.563401 9.366233\nendloop\nendfacet\nfacet normal -0.398481 0.000000 0.917176\nouter loop\nvertex 17.052727 1.563401 9.366233\nvertex 16.516666 1.562718 9.133333\nvertex 16.516666 0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.404967 0.005022 0.914317\nouter loop\nvertex 17.052727 1.563401 9.366233\nvertex 16.516666 0.738753 9.133333\nvertex 17.047916 0.739118 9.368630\nendloop\nendfacet\nfacet normal -0.404970 0.000000 0.914330\nouter loop\nvertex 17.047916 0.739118 9.368630\nvertex 16.516666 0.738753 9.133333\nvertex 16.516666 0.000000 9.133333\nendloop\nendfacet\nfacet normal -0.413823 0.007640 0.910325\nouter loop\nvertex 17.047916 0.739118 9.368630\nvertex 16.516666 0.000000 9.133333\nvertex 17.041407 0.000000 9.371875\nendloop\nendfacet\nfacet normal -0.298019 0.006815 0.954536\nouter loop\nvertex 17.679161 0.739297 9.565712\nvertex 17.047916 0.739118 9.368630\nvertex 17.041407 0.000000 9.371875\nendloop\nendfacet\nfacet normal -0.350771 0.057525 0.934693\nouter loop\nvertex 17.679161 0.739297 9.565712\nvertex 17.041407 0.000000 9.371875\nvertex 17.627083 0.000000 9.591667\nendloop\nendfacet\nfacet normal -0.173979 0.046789 0.983637\nouter loop\nvertex 18.448393 0.739303 9.701769\nvertex 17.679161 0.739297 9.565712\nvertex 17.627083 0.000000 9.591667\nendloop\nendfacet\nfacet normal -0.307649 0.203345 0.929518\nouter loop\nvertex 18.448393 0.739303 9.701769\nvertex 17.627083 0.000000 9.591667\nvertex 18.253386 0.000000 9.798959\nendloop\nendfacet\nfacet normal 0.003953 0.129314 0.991596\nouter loop\nvertex 19.506817 0.739151 9.697570\nvertex 18.448393 0.739303 9.701769\nvertex 18.253386 0.000000 9.798959\nendloop\nendfacet\nfacet normal -0.250697 0.535724 0.806319\nouter loop\nvertex 19.506817 0.739151 9.697570\nvertex 18.253386 0.000000 9.798959\nvertex 18.900000 0.000000 10.000000\nendloop\nendfacet\nfacet normal 0.034751 0.067120 0.997140\nouter loop\nvertex 19.697014 1.563463 9.602778\nvertex 18.568115 1.563749 9.642101\nvertex 18.448393 0.739303 9.701769\nendloop\nendfacet\nfacet normal 0.003957 0.113339 0.993548\nouter loop\nvertex 19.697014 1.563463 9.602778\nvertex 18.448393 0.739303 9.701769\nvertex 19.506817 0.739151 9.697570\nendloop\nendfacet\nfacet normal 0.042000 0.020882 0.998899\nouter loop\nvertex 19.760412 2.558099 9.571181\nvertex 18.613682 2.558479 9.619390\nvertex 18.568115 1.563749 9.642101\nendloop\nendfacet\nfacet normal 0.034805 0.029516 0.998958\nouter loop\nvertex 19.760412 2.558099 9.571181\nvertex 18.568115 1.563749 9.642101\nvertex 19.697014 1.563463 9.602778\nendloop\nendfacet\nfacet normal 0.288243 0.045314 -0.956485\nouter loop\nvertex 26.129168 11.849633 8.070150\nvertex 26.005474 12.920404 8.083603\nvertex 26.240326 12.930573 8.154860\nendloop\nendfacet\nfacet normal 0.274405 0.047052 -0.960462\nouter loop\nvertex 26.129168 11.849633 8.070150\nvertex 26.240326 12.930573 8.154860\nvertex 26.372263 11.851037 8.139670\nendloop\nendfacet\nfacet normal 0.318796 0.178510 -0.930862\nouter loop\nvertex 26.005474 12.920404 8.083603\nvertex 25.675266 13.692222 8.118527\nvertex 25.882959 13.725335 8.196007\nendloop\nendfacet\nfacet normal 0.278988 0.174332 -0.944338\nouter loop\nvertex 26.005474 12.920404 8.083603\nvertex 25.882959 13.725335 8.196007\nvertex 26.240326 12.930573 8.154860\nendloop\nendfacet\nfacet normal 0.468854 0.044890 0.882134\nouter loop\nvertex 26.372263 11.851037 8.139670\nvertex 26.240326 12.930573 8.154860\nvertex 26.005474 12.920482 8.280198\nendloop\nendfacet\nfacet normal 0.458197 0.040470 0.887929\nouter loop\nvertex 26.372263 11.851037 8.139670\nvertex 26.005474 12.920482 8.280198\nvertex 26.129166 11.849897 8.265168\nendloop\nendfacet\nfacet normal 0.487982 0.175154 0.855099\nouter loop\nvertex 26.240326 12.930573 8.154860\nvertex 25.882959 13.725335 8.196007\nvertex 25.675266 13.692232 8.321312\nendloop\nendfacet\nfacet normal 0.460435 0.150400 0.874859\nouter loop\nvertex 26.240326 12.930573 8.154860\nvertex 25.675266 13.692232 8.321312\nvertex 26.005474 12.920482 8.280198\nendloop\nendfacet\nfacet normal 0.047924 0.001828 -0.998849\nouter loop\nvertex 25.414011 10.480907 8.033333\nvertex 25.400063 11.848212 8.035166\nvertex 26.129168 11.849633 8.070150\nendloop\nendfacet\nfacet normal 0.047563 0.002017 -0.998866\nouter loop\nvertex 25.414011 10.480907 8.033333\nvertex 26.129168 11.849633 8.070150\nvertex 26.146835 10.481279 8.068229\nendloop\nendfacet\nfacet normal 0.050335 0.016690 -0.998593\nouter loop\nvertex 25.400063 11.848212 8.035166\nvertex 25.302427 12.910231 8.047994\nvertex 26.005474 12.920404 8.083603\nendloop\nendfacet\nfacet normal 0.047885 0.018078 -0.998689\nouter loop\nvertex 25.400063 11.848212 8.035166\nvertex 26.005474 12.920404 8.083603\nvertex 26.129168 11.849633 8.070150\nendloop\nendfacet\nfacet normal 0.057660 0.062379 -0.996386\nouter loop\nvertex 25.302427 12.910231 8.047994\nvertex 25.061609 13.654374 8.080646\nvertex 25.675266 13.692222 8.118527\nendloop\nendfacet\nfacet normal 0.049517 0.066280 -0.996572\nouter loop\nvertex 25.302427 12.910231 8.047994\nvertex 25.675266 13.692222 8.118527\nvertex 26.005474 12.920404 8.083603\nendloop\nendfacet\nfacet normal 0.095358 0.176334 -0.979701\nouter loop\nvertex 25.061609 13.654374 8.080646\nvertex 24.762611 14.062502 8.125000\nvertex 25.047661 14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.049852 0.175785 -0.983165\nouter loop\nvertex 25.061609 13.654374 8.080646\nvertex 25.047661 14.199250 8.177359\nvertex 25.675266 13.692222 8.118527\nendloop\nendfacet\nfacet normal 0.320723 0.490980 -0.809985\nouter loop\nvertex 25.675266 13.692222 8.118527\nvertex 25.047661 14.199250 8.177359\nvertex 25.190845 14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.249862 0.445005 -0.859965\nouter loop\nvertex 25.675266 13.692222 8.118527\nvertex 25.190845 14.267941 8.275694\nvertex 25.882959 13.725335 8.196007\nendloop\nendfacet\nfacet normal 0.459444 0.475901 0.749953\nouter loop\nvertex 25.882959 13.725335 8.196007\nvertex 25.190845 14.267941 8.275694\nvertex 25.047661 14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.428374 0.392727 0.813794\nouter loop\nvertex 25.882959 13.725335 8.196007\nvertex 25.047661 14.199251 8.407001\nvertex 25.675266 13.692232 8.321312\nendloop\nendfacet\nfacet normal 0.290536 0.201539 0.935399\nouter loop\nvertex 25.675266 13.692232 8.321312\nvertex 25.047661 14.199251 8.407001\nvertex 24.762611 14.062502 8.525001\nendloop\nendfacet\nfacet normal 0.269544 0.140295 0.952714\nouter loop\nvertex 25.675266 13.692232 8.321312\nvertex 24.762611 14.062502 8.525001\nvertex 25.061607 13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.275863 0.066949 0.958863\nouter loop\nvertex 26.005474 12.920482 8.280198\nvertex 25.675266 13.692232 8.321312\nvertex 25.061607 13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.269238 0.057685 0.961344\nouter loop\nvertex 26.005474 12.920482 8.280198\nvertex 25.061607 13.654394 8.500504\nvertex 25.302429 12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.270178 0.017701 0.962648\nouter loop\nvertex 26.129166 11.849897 8.265168\nvertex 26.005474 12.920482 8.280198\nvertex 25.302429 12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.268016 0.015887 0.963283\nouter loop\nvertex 26.129166 11.849897 8.265168\nvertex 25.302429 12.910394 8.477700\nvertex 25.400064 11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.268070 0.001951 0.963397\nouter loop\nvertex 26.146837 10.481909 8.263021\nvertex 26.129166 11.849897 8.265168\nvertex 25.400064 11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.267745 0.001759 0.963488\nouter loop\nvertex 26.146837 10.481909 8.263021\nvertex 25.400064 11.848762 8.468046\nvertex 25.414009 10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.458701 0.004906 0.888577\nouter loop\nvertex 26.391113 10.481605 8.137500\nvertex 26.372263 11.851037 8.139670\nvertex 26.129166 11.849897 8.265168\nendloop\nendfacet\nfacet normal 0.457041 0.004507 0.889434\nouter loop\nvertex 26.391113 10.481605 8.137500\nvertex 26.129166 11.849897 8.265168\nvertex 26.146837 10.481909 8.263021\nendloop\nendfacet\nfacet normal 0.274929 0.004899 -0.961452\nouter loop\nvertex 26.146835 10.481279 8.068229\nvertex 26.129168 11.849633 8.070150\nvertex 26.372263 11.851037 8.139670\nendloop\nendfacet\nfacet normal 0.272809 0.005281 -0.962054\nouter loop\nvertex 26.146835 10.481279 8.068229\nvertex 26.372263 11.851037 8.139670\nvertex 26.391113 10.481605 8.137500\nendloop\nendfacet\nfacet normal 0.094174 0.867630 0.488210\nouter loop\nvertex 21.163698 14.718087 8.937361\nvertex 22.682304 14.658746 8.749882\nvertex 22.698479 14.771414 8.546528\nendloop\nendfacet\nfacet normal 0.074718 0.905827 0.417007\nouter loop\nvertex 21.163698 14.718087 8.937361\nvertex 22.698479 14.771414 8.546528\nvertex 21.149673 14.834710 8.686545\nendloop\nendfacet\nfacet normal 0.175628 0.798933 0.575206\nouter loop\nvertex 22.682304 14.658746 8.749882\nvertex 24.028313 14.500335 8.558929\nvertex 24.096714 14.599972 8.399652\nendloop\nendfacet\nfacet normal 0.156554 0.858600 0.488157\nouter loop\nvertex 22.682304 14.658746 8.749882\nvertex 24.096714 14.599972 8.399652\nvertex 22.698479 14.771414 8.546528\nendloop\nendfacet\nfacet normal -0.008983 0.870139 -0.492724\nouter loop\nvertex 21.149673 14.834710 8.686545\nvertex 22.698479 14.771414 8.546528\nvertex 22.672430 14.658748 8.348035\nendloop\nendfacet\nfacet normal 0.010635 0.906013 -0.423115\nouter loop\nvertex 21.149673 14.834710 8.686545\nvertex 22.672430 14.658748 8.348035\nvertex 21.130371 14.718086 8.436337\nendloop\nendfacet\nfacet normal 0.038324 0.811775 -0.582711\nouter loop\nvertex 22.698479 14.771414 8.546528\nvertex 24.096714 14.599972 8.399652\nvertex 24.027081 14.500335 8.256269\nendloop\nendfacet\nfacet normal 0.067209 0.863893 -0.499172\nouter loop\nvertex 22.698479 14.771414 8.546528\nvertex 24.027081 14.500335 8.256269\nvertex 22.672430 14.658748 8.348035\nendloop\nendfacet\nfacet normal 0.097537 0.510328 0.854431\nouter loop\nvertex 19.733356 14.375003 9.305555\nvertex 21.174864 14.368311 9.145000\nvertex 21.163698 14.718087 8.937361\nendloop\nendfacet\nfacet normal 0.077329 0.561655 0.823750\nouter loop\nvertex 19.733356 14.375003 9.305555\nvertex 21.163698 14.718087 8.937361\nvertex 19.700632 14.726565 9.068924\nendloop\nendfacet\nfacet normal 0.149635 0.432774 0.888997\nouter loop\nvertex 21.174864 14.368311 9.145000\nvertex 22.665283 14.321471 8.916937\nvertex 22.682304 14.658746 8.749882\nendloop\nendfacet\nfacet normal 0.125014 0.509412 0.851394\nouter loop\nvertex 21.174864 14.368311 9.145000\nvertex 22.682304 14.658746 8.749882\nvertex 21.163698 14.718087 8.937361\nendloop\nendfacet\nfacet normal 0.195237 0.347732 0.917041\nouter loop\nvertex 22.665283 14.321471 8.916937\nvertex 23.949944 14.205942 8.687243\nvertex 24.028313 14.500335 8.558929\nendloop\nendfacet\nfacet normal 0.176210 0.429746 0.885590\nouter loop\nvertex 22.665283 14.321471 8.916937\nvertex 24.028313 14.500335 8.558929\nvertex 22.682304 14.658746 8.749882\nendloop\nendfacet\nfacet normal 0.237569 0.301556 0.923377\nouter loop\nvertex 23.949944 14.205942 8.687243\nvertex 24.762611 14.062502 8.525001\nvertex 25.047661 14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.234975 0.335129 0.912401\nouter loop\nvertex 23.949944 14.205942 8.687243\nvertex 25.047661 14.199251 8.407001\nvertex 24.028313 14.500335 8.558929\nendloop\nendfacet\nfacet normal 0.299377 0.671564 0.677772\nouter loop\nvertex 24.028313 14.500335 8.558929\nvertex 25.047661 14.199251 8.407001\nvertex 25.190845 14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.294422 0.748252 0.594504\nouter loop\nvertex 24.028313 14.500335 8.558929\nvertex 25.190845 14.267941 8.275694\nvertex 24.096714 14.599972 8.399652\nendloop\nendfacet\nfacet normal 0.136319 0.707929 -0.693003\nouter loop\nvertex 24.096714 14.599972 8.399652\nvertex 25.190845 14.267941 8.275694\nvertex 25.047661 14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.178012 0.765464 -0.618366\nouter loop\nvertex 24.096714 14.599972 8.399652\nvertex 25.047661 14.199250 8.177359\nvertex 24.027081 14.500335 8.256269\nendloop\nendfacet\nfacet normal 0.020907 0.319184 -0.947462\nouter loop\nvertex 24.027081 14.500335 8.256269\nvertex 25.047661 14.199250 8.177359\nvertex 24.762611 14.062502 8.125000\nendloop\nendfacet\nfacet normal 0.035814 0.341726 -0.939117\nouter loop\nvertex 24.027081 14.500335 8.256269\nvertex 24.762611 14.062502 8.125000\nvertex 23.947687 14.205942 8.146118\nendloop\nendfacet\nfacet normal -0.021727 0.355488 -0.934428\nouter loop\nvertex 22.672430 14.658748 8.348035\nvertex 24.027081 14.500335 8.256269\nvertex 23.947687 14.205942 8.146118\nendloop\nendfacet\nfacet normal 0.010905 0.432699 -0.901473\nouter loop\nvertex 22.672430 14.658748 8.348035\nvertex 23.947687 14.205942 8.146118\nvertex 22.647228 14.321472 8.185841\nendloop\nendfacet\nfacet normal -0.034768 0.435232 -0.899647\nouter loop\nvertex 21.130371 14.718086 8.436337\nvertex 22.672430 14.658748 8.348035\nvertex 22.647228 14.321472 8.185841\nendloop\nendfacet\nfacet normal -0.008821 0.509649 -0.860337\nouter loop\nvertex 21.130371 14.718086 8.436337\nvertex 22.647228 14.321472 8.185841\nvertex 21.113926 14.368312 8.229306\nendloop\nendfacet\nfacet normal -0.032112 0.510214 -0.859448\nouter loop\nvertex 19.621639 14.726565 8.497743\nvertex 21.130371 14.718086 8.436337\nvertex 21.113926 14.368312 8.229306\nendloop\nendfacet\nfacet normal -0.014833 0.559269 -0.828854\nouter loop\nvertex 19.621639 14.726565 8.497743\nvertex 21.113926 14.368312 8.229306\nvertex 19.588913 14.375001 8.261111\nendloop\nendfacet\nfacet normal -0.021865 0.906804 -0.420984\nouter loop\nvertex 19.661137 14.843751 8.783334\nvertex 21.149673 14.834710 8.686545\nvertex 21.130371 14.718086 8.436337\nendloop\nendfacet\nfacet normal -0.010198 0.925593 -0.378382\nouter loop\nvertex 19.661137 14.843751 8.783334\nvertex 21.130371 14.718086 8.436337\nvertex 19.621639 14.726565 8.497743\nendloop\nendfacet\nfacet normal 0.042957 0.906849 0.419261\nouter loop\nvertex 19.700632 14.726565 9.068924\nvertex 21.163698 14.718087 8.937361\nvertex 21.149673 14.834710 8.686545\nendloop\nendfacet\nfacet normal 0.030065 0.926179 0.375884\nouter loop\nvertex 19.700632 14.726565 9.068924\nvertex 21.149673 14.834710 8.686545\nvertex 19.661137 14.843751 8.783334\nendloop\nendfacet\nfacet normal -0.595026 0.014885 0.803569\nouter loop\nvertex 15.731250 2.553990 8.604167\nvertex 15.695139 1.560369 8.595834\nvertex 16.068663 1.561682 8.872396\nendloop\nendfacet\nfacet normal -0.618699 0.001989 0.785625\nouter loop\nvertex 15.731250 2.553990 8.604167\nvertex 16.068663 1.561682 8.872396\nvertex 16.073177 2.555731 8.873438\nendloop\nendfacet\nfacet normal -0.585481 0.007650 0.810650\nouter loop\nvertex 15.695139 1.560369 8.595834\nvertex 15.679340 0.737497 8.592188\nvertex 16.066689 0.738199 8.871941\nendloop\nendfacet\nfacet normal -0.595062 0.000980 0.803679\nouter loop\nvertex 15.695139 1.560369 8.595834\nvertex 16.066689 0.738199 8.871941\nvertex 16.068663 1.561682 8.872396\nendloop\nendfacet\nfacet normal -0.897700 0.269418 0.348638\nouter loop\nvertex 15.767362 3.799347 8.177083\nvertex 15.437763 2.799557 8.101022\nvertex 15.527117 2.781798 8.344819\nendloop\nendfacet\nfacet normal -0.820203 0.100823 -0.563118\nouter loop\nvertex 15.767362 3.799347 8.177083\nvertex 15.527117 2.781798 8.344819\nvertex 15.635330 3.801585 8.369792\nendloop\nendfacet\nfacet normal -0.584159 0.001216 0.811638\nouter loop\nvertex 15.679340 0.737497 8.592188\nvertex 15.677083 0.000000 8.591667\nvertex 16.066406 0.000000 8.871875\nendloop\nendfacet\nfacet normal -0.585496 0.000154 0.810675\nouter loop\nvertex 15.679340 0.737497 8.592188\nvertex 16.066406 0.000000 8.871875\nvertex 16.066689 0.738199 8.871941\nendloop\nendfacet\nfacet normal -0.502158 0.000114 0.864776\nouter loop\nvertex 16.066689 0.738199 8.871941\nvertex 16.066406 0.000000 8.871875\nvertex 16.516666 0.000000 9.133333\nendloop\nendfacet\nfacet normal -0.502302 0.000000 0.864693\nouter loop\nvertex 16.066689 0.738199 8.871941\nvertex 16.516666 0.000000 9.133333\nvertex 16.516666 0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.502301 0.000725 0.864692\nouter loop\nvertex 16.068663 1.561682 8.872396\nvertex 16.066689 0.738199 8.871941\nvertex 16.516666 0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.503297 0.000000 0.864113\nouter loop\nvertex 16.068663 1.561682 8.872396\nvertex 16.516666 0.738753 9.133333\nvertex 16.516666 1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.503299 0.001380 0.864111\nouter loop\nvertex 16.073177 2.555731 8.873438\nvertex 16.068663 1.561682 8.872396\nvertex 16.516666 1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.505600 0.000000 0.862768\nouter loop\nvertex 16.073177 2.555731 8.873438\nvertex 16.516666 1.562718 9.133333\nvertex 16.516666 2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.505605 0.001107 0.862764\nouter loop\nvertex 16.077690 3.805630 8.874479\nvertex 16.073177 2.555731 8.873438\nvertex 16.516666 2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.507944 0.000000 0.861390\nouter loop\nvertex 16.077690 3.805630 8.874479\nvertex 16.516666 2.557108 9.133333\nvertex 16.516666 3.807135 9.133333\nendloop\nendfacet\nfacet normal -0.618684 0.012638 0.785538\nouter loop\nvertex 15.767361 3.803730 8.612500\nvertex 15.731250 2.553990 8.604167\nvertex 16.073177 2.555731 8.873438\nendloop\nendfacet\nfacet normal -0.645074 0.001693 0.764118\nouter loop\nvertex 15.767361 3.803730 8.612500\nvertex 16.073177 2.555731 8.873438\nvertex 16.077690 3.805630 8.874479\nendloop\nendfacet\nfacet normal -0.875831 0.081288 0.475723\nouter loop\nvertex 15.767361 3.803730 8.612500\nvertex 15.635330 3.801585 8.369792\nvertex 15.527117 2.781798 8.344819\nendloop\nendfacet\nfacet normal -0.755954 0.064263 0.651463\nouter loop\nvertex 15.538307 2.783193 8.357668\nvertex 15.518668 2.552154 8.357668\nvertex 15.731250 2.553990 8.604167\nendloop\nendfacet\nfacet normal -0.754405 0.005387 0.656388\nouter loop\nvertex 15.767361 3.803730 8.612500\nvertex 15.527117 2.781798 8.344819\nvertex 15.538307 2.783193 8.357668\nendloop\nendfacet\nfacet normal -0.778982 0.018329 0.626778\nouter loop\nvertex 15.538307 2.783193 8.357668\nvertex 15.731250 2.553990 8.604167\nvertex 15.767361 3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.931106 0.000000 0.364749\nouter loop\nvertex 15.694011 8.850069 8.383333\nvertex 15.694011 7.087864 8.383333\nvertex 15.785417 7.089402 8.616667\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364751\nouter loop\nvertex 15.694011 8.850069 8.383333\nvertex 15.785417 7.089402 8.616667\nvertex 15.785417 8.851082 8.616667\nendloop\nendfacet\nfacet normal -0.925850 0.003136 0.377877\nouter loop\nvertex 15.694011 7.087864 8.383333\nvertex 15.687522 5.352535 8.381836\nvertex 15.783160 5.354500 8.616146\nendloop\nendfacet\nfacet normal -0.931107 0.001101 0.364744\nouter loop\nvertex 15.694011 7.087864 8.383333\nvertex 15.783160 5.354500 8.616146\nvertex 15.785417 7.089402 8.616667\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 8.851082 8.616667\nvertex 15.785417 7.089402 8.616667\nvertex 16.079948 7.090765 8.875000\nendloop\nendfacet\nfacet normal -0.659398 0.000000 0.751794\nouter loop\nvertex 15.785417 8.851082 8.616667\nvertex 16.079948 7.090765 8.875000\nvertex 16.079948 8.851977 8.875000\nendloop\nendfacet\nfacet normal -0.657566 0.000627 0.753396\nouter loop\nvertex 15.785417 7.089402 8.616667\nvertex 15.783160 5.354500 8.616146\nvertex 16.079666 5.356243 8.874935\nendloop\nendfacet\nfacet normal -0.659397 0.000080 0.751795\nouter loop\nvertex 15.785417 7.089402 8.616667\nvertex 16.079666 5.356243 8.874935\nvertex 16.079948 7.090765 8.875000\nendloop\nendfacet\nfacet normal -0.727986 0.000000 -0.685592\nouter loop\nvertex 15.866667 10.481091 8.200000\nvertex 15.866667 8.849014 8.200000\nvertex 15.694011 8.850069 8.383333\nendloop\nendfacet\nfacet normal -0.727990 0.000000 -0.685587\nouter loop\nvertex 15.866667 10.481091 8.200000\nvertex 15.694011 8.850069 8.383333\nvertex 15.694011 10.481650 8.383333\nendloop\nendfacet\nfacet normal -0.727987 0.000000 -0.685591\nouter loop\nvertex 15.866667 8.849014 8.200000\nvertex 15.866667 7.086260 8.200000\nvertex 15.694011 7.087864 8.383333\nendloop\nendfacet\nfacet normal -0.727987 0.000000 -0.685591\nouter loop\nvertex 15.866667 8.849014 8.200000\nvertex 15.694011 7.087864 8.383333\nvertex 15.694011 8.850069 8.383333\nendloop\nendfacet\nfacet normal -0.734084 0.004633 -0.679043\nouter loop\nvertex 15.866667 7.086260 8.200000\nvertex 15.857639 5.350487 8.197917\nvertex 15.687522 5.352535 8.381836\nendloop\nendfacet\nfacet normal -0.727966 0.003314 -0.685605\nouter loop\nvertex 15.866667 7.086260 8.200000\nvertex 15.687522 5.352535 8.381836\nvertex 15.694011 7.087864 8.383333\nendloop\nendfacet\nfacet normal -0.823380 0.055509 -0.564769\nouter loop\nvertex 15.857639 5.350487 8.197917\nvertex 15.767362 3.799347 8.177083\nvertex 15.635330 3.801585 8.369792\nendloop\nendfacet\nfacet normal -0.733620 0.029959 -0.678900\nouter loop\nvertex 15.857639 5.350487 8.197917\nvertex 15.635330 3.801585 8.369792\nvertex 15.687522 5.352535 8.381836\nendloop\nendfacet\nfacet normal -0.878237 0.025846 0.477526\nouter loop\nvertex 15.687522 5.352535 8.381836\nvertex 15.635330 3.801585 8.369792\nvertex 15.767361 3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.925837 0.008545 0.377827\nouter loop\nvertex 15.687522 5.352535 8.381836\nvertex 15.767361 3.803730 8.612500\nvertex 15.783160 5.354500 8.616146\nendloop\nendfacet\nfacet normal -0.645081 0.004776 0.764099\nouter loop\nvertex 15.783160 5.354500 8.616146\nvertex 15.767361 3.803730 8.612500\nvertex 16.077690 3.805630 8.874479\nendloop\nendfacet\nfacet normal -0.657567 0.000617 0.753395\nouter loop\nvertex 15.783160 5.354500 8.616146\nvertex 16.077690 3.805630 8.874479\nvertex 16.079666 5.356243 8.874935\nendloop\nendfacet\nfacet normal -0.507942 0.000393 0.861391\nouter loop\nvertex 16.079666 5.356243 8.874935\nvertex 16.077690 3.805630 8.874479\nvertex 16.516666 3.807135 9.133333\nendloop\nendfacet\nfacet normal -0.508979 0.000000 0.860779\nouter loop\nvertex 16.079666 5.356243 8.874935\nvertex 16.516666 3.807135 9.133333\nvertex 16.516666 5.357624 9.133333\nendloop\nendfacet\nfacet normal -0.508979 0.000051 0.860779\nouter loop\nvertex 16.079948 7.090765 8.875000\nvertex 16.079666 5.356243 8.874935\nvertex 16.516666 5.357624 9.133333\nendloop\nendfacet\nfacet normal -0.509126 0.000000 0.860692\nouter loop\nvertex 16.079948 7.090765 8.875000\nvertex 16.516666 5.357624 9.133333\nvertex 16.516666 7.091847 9.133333\nendloop\nendfacet\nfacet normal -0.509128 0.000000 0.860691\nouter loop\nvertex 16.079948 8.851977 8.875000\nvertex 16.079948 7.090765 8.875000\nvertex 16.516666 7.091847 9.133333\nendloop\nendfacet\nfacet normal -0.509127 0.000000 0.860691\nouter loop\nvertex 16.079948 8.851977 8.875000\nvertex 16.516666 7.091847 9.133333\nvertex 16.516666 8.852689 9.133333\nendloop\nendfacet\nfacet normal -0.509127 0.000000 0.860691\nouter loop\nvertex 16.079948 10.482659 8.875000\nvertex 16.079948 8.851977 8.875000\nvertex 16.516666 8.852689 9.133333\nendloop\nendfacet\nfacet normal -0.509128 0.000000 0.860691\nouter loop\nvertex 16.079948 10.482659 8.875000\nvertex 16.516666 8.852689 9.133333\nvertex 16.516666 10.483034 9.133333\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 10.482183 8.616667\nvertex 15.785417 8.851082 8.616667\nvertex 16.079948 8.851977 8.875000\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 10.482183 8.616667\nvertex 16.079948 8.851977 8.875000\nvertex 16.079948 10.482659 8.875000\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364750\nouter loop\nvertex 15.694011 10.481650 8.383333\nvertex 15.694011 8.850069 8.383333\nvertex 15.785417 8.851082 8.616667\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364750\nouter loop\nvertex 15.694011 10.481650 8.383333\nvertex 15.785417 8.851082 8.616667\nvertex 15.785417 10.482183 8.616667\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200653 8.852824 9.371354\nvertex 21.200655 7.092052 9.371354\nvertex 22.754240 7.091278 9.079166\nendloop\nendfacet\nfacet normal 0.184832 -0.000001 0.982770\nouter loop\nvertex 21.200653 8.852824 9.371354\nvertex 22.754240 7.091278 9.079166\nvertex 22.754240 8.852315 9.079167\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200655 7.092052 9.371354\nvertex 21.200653 5.357885 9.371354\nvertex 22.754240 5.356898 9.079166\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200655 7.092052 9.371354\nvertex 22.754240 5.356898 9.079166\nvertex 22.754240 7.091278 9.079166\nendloop\nendfacet\nfacet normal 0.214559 -0.000000 0.976711\nouter loop\nvertex 22.754240 8.852315 9.079167\nvertex 22.754240 7.091278 9.079166\nvertex 24.226576 7.090393 8.755729\nendloop\nendfacet\nfacet normal 0.214560 -0.000001 0.976711\nouter loop\nvertex 22.754240 8.852315 9.079167\nvertex 24.226576 7.090393 8.755729\nvertex 24.226576 8.851733 8.755730\nendloop\nendfacet\nfacet normal 0.214560 0.000000 0.976711\nouter loop\nvertex 22.754240 7.091278 9.079166\nvertex 22.754240 5.356898 9.079166\nvertex 24.226576 5.355767 8.755730\nendloop\nendfacet\nfacet normal 0.214560 0.000001 0.976711\nouter loop\nvertex 22.754240 7.091278 9.079166\nvertex 24.226576 5.355767 8.755730\nvertex 24.226576 7.090393 8.755729\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 10.483306 9.566667\nvertex 19.769468 8.853203 9.566667\nvertex 21.200653 8.852824 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 10.483306 9.566667\nvertex 21.200653 8.852824 9.371354\nvertex 21.200653 10.483106 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 8.853203 9.566667\nvertex 19.769468 7.092627 9.566667\nvertex 21.200655 7.092052 9.371354\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 8.853203 9.566667\nvertex 21.200655 7.092052 9.371354\nvertex 21.200653 8.852824 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 7.092627 9.566667\nvertex 19.769468 5.358619 9.566667\nvertex 21.200653 5.357885 9.371354\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 7.092627 9.566667\nvertex 21.200653 5.357885 9.371354\nvertex 21.200655 7.092052 9.371354\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 5.358619 9.566667\nvertex 19.769468 3.808219 9.566667\nvertex 21.200653 3.807420 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 5.358619 9.566667\nvertex 21.200653 3.807420 9.371354\nvertex 21.200653 5.357885 9.371354\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200653 5.357885 9.371354\nvertex 21.200653 3.807420 9.371354\nvertex 22.754240 3.806343 9.079166\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200653 5.357885 9.371354\nvertex 22.754240 3.806343 9.079166\nvertex 22.754240 5.356898 9.079166\nendloop\nendfacet\nfacet normal 0.214560 0.000000 0.976711\nouter loop\nvertex 22.754240 5.356898 9.079166\nvertex 22.754240 3.806343 9.079166\nvertex 24.226574 3.805111 8.755730\nendloop\nendfacet\nfacet normal 0.214559 -0.000001 0.976711\nouter loop\nvertex 22.754240 5.356898 9.079166\nvertex 24.226574 3.805111 8.755730\nvertex 24.226576 5.355767 8.755730\nendloop\nendfacet\nfacet normal 0.236528 0.000000 0.971625\nouter loop\nvertex 24.226576 5.355767 8.755730\nvertex 24.226574 3.805111 8.755730\nvertex 25.414011 3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.236527 0.000000 0.971625\nouter loop\nvertex 24.226576 5.355767 8.755730\nvertex 25.414011 3.803846 8.466667\nvertex 25.414009 5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.236529 0.000001 0.971625\nouter loop\nvertex 24.226576 7.090393 8.755729\nvertex 24.226576 5.355767 8.755730\nvertex 25.414009 5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.236525 -0.000001 0.971625\nouter loop\nvertex 24.226576 7.090393 8.755729\nvertex 25.414009 5.354605 8.466666\nvertex 25.414009 7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.236526 -0.000000 0.971625\nouter loop\nvertex 24.226576 8.851733 8.755730\nvertex 24.226576 7.090393 8.755729\nvertex 25.414009 7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.236527 0.000000 0.971625\nouter loop\nvertex 24.226576 8.851733 8.755730\nvertex 25.414009 7.089484 8.466667\nvertex 25.414009 8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.236527 0.000000 0.971625\nouter loop\nvertex 24.226574 10.482530 8.755730\nvertex 24.226576 8.851733 8.755730\nvertex 25.414009 8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.236527 -0.000000 0.971625\nouter loop\nvertex 24.226574 10.482530 8.755730\nvertex 25.414009 8.851135 8.466666\nvertex 25.414009 10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.214560 0.000000 0.976711\nouter loop\nvertex 22.754240 10.482836 9.079166\nvertex 22.754240 8.852315 9.079167\nvertex 24.226576 8.851733 8.755730\nendloop\nendfacet\nfacet normal 0.214560 0.000001 0.976711\nouter loop\nvertex 22.754240 10.482836 9.079166\nvertex 24.226576 8.851733 8.755730\nvertex 24.226574 10.482530 8.755730\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200653 10.483106 9.371354\nvertex 21.200653 8.852824 9.371354\nvertex 22.754240 8.852315 9.079167\nendloop\nendfacet\nfacet normal 0.184833 0.000001 0.982770\nouter loop\nvertex 21.200653 10.483106 9.371354\nvertex 22.754240 8.852315 9.079167\nvertex 22.754240 10.482836 9.079166\nendloop\nendfacet\nfacet normal 0.002253 0.000000 -0.999997\nouter loop\nvertex 21.109249 8.846521 8.000521\nvertex 22.727156 8.847102 8.004167\nvertex 22.727156 7.083351 8.004167\nendloop\nendfacet\nfacet normal 0.002254 0.000000 -0.999997\nouter loop\nvertex 21.109249 8.846521 8.000521\nvertex 22.727156 7.083351 8.004167\nvertex 21.109247 7.082470 8.000521\nendloop\nendfacet\nfacet normal 0.006615 0.000000 -0.999978\nouter loop\nvertex 22.727156 8.847102 8.004167\nvertex 24.223190 8.847869 8.014062\nvertex 24.223190 7.084518 8.014062\nendloop\nendfacet\nfacet normal 0.006614 0.000000 -0.999978\nouter loop\nvertex 22.727156 8.847102 8.004167\nvertex 24.223190 7.084518 8.014062\nvertex 22.727156 7.083351 8.004167\nendloop\nendfacet\nfacet normal 0.002254 0.000054 -0.999997\nouter loop\nvertex 21.109247 7.082470 8.000521\nvertex 22.727156 7.083351 8.004167\nvertex 22.730549 5.346774 8.004080\nendloop\nendfacet\nfacet normal 0.002202 0.000007 -0.999998\nouter loop\nvertex 21.109247 7.082470 8.000521\nvertex 22.730549 5.346774 8.004080\nvertex 21.109673 5.345647 8.000510\nendloop\nendfacet\nfacet normal 0.006614 0.000181 -0.999978\nouter loop\nvertex 22.727156 7.083351 8.004167\nvertex 24.223190 7.084518 8.014062\nvertex 24.232944 5.348269 8.013813\nendloop\nendfacet\nfacet normal 0.006477 0.000063 -0.999979\nouter loop\nvertex 22.727156 7.083351 8.004167\nvertex 24.232944 5.348269 8.013813\nvertex 22.730549 5.346774 8.004080\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 10.479649 8.000000\nvertex 21.109249 10.479773 8.000521\nvertex 21.109249 8.846521 8.000521\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 10.479649 8.000000\nvertex 21.109249 8.846521 8.000521\nvertex 19.552803 8.846289 8.000000\nendloop\nendfacet\nfacet normal 0.002252 -0.000000 -0.999997\nouter loop\nvertex 21.109249 10.479773 8.000521\nvertex 22.727158 10.480080 8.004167\nvertex 22.727156 8.847102 8.004167\nendloop\nendfacet\nfacet normal 0.002254 0.000000 -0.999997\nouter loop\nvertex 21.109249 10.479773 8.000521\nvertex 22.727156 8.847102 8.004167\nvertex 21.109249 8.846521 8.000521\nendloop\nendfacet\nfacet normal 0.006614 0.000000 -0.999978\nouter loop\nvertex 22.727158 10.480080 8.004167\nvertex 24.223190 10.480485 8.014062\nvertex 24.223190 8.847869 8.014062\nendloop\nendfacet\nfacet normal 0.006615 0.000000 -0.999978\nouter loop\nvertex 22.727158 10.480080 8.004167\nvertex 24.223190 8.847869 8.014062\nvertex 22.727156 8.847102 8.004167\nendloop\nendfacet\nfacet normal 0.016182 0.000000 -0.999869\nouter loop\nvertex 24.223190 10.480485 8.014062\nvertex 25.414011 10.480907 8.033333\nvertex 25.414009 8.848668 8.033333\nendloop\nendfacet\nfacet normal 0.016180 0.000000 -0.999869\nouter loop\nvertex 24.223190 10.480485 8.014062\nvertex 25.414009 8.848668 8.033333\nvertex 24.223190 8.847869 8.014062\nendloop\nendfacet\nfacet normal 0.016181 0.000000 -0.999869\nouter loop\nvertex 24.223190 8.847869 8.014062\nvertex 25.414009 8.848668 8.033333\nvertex 25.414009 7.085731 8.033333\nendloop\nendfacet\nfacet normal 0.016180 0.000000 -0.999869\nouter loop\nvertex 24.223190 8.847869 8.014062\nvertex 25.414009 7.085731 8.033333\nvertex 24.223190 7.084518 8.014062\nendloop\nendfacet\nfacet normal 0.016182 0.000326 -0.999869\nouter loop\nvertex 24.223190 7.084518 8.014062\nvertex 25.414009 7.085731 8.033333\nvertex 25.427582 5.349819 8.032986\nendloop\nendfacet\nfacet normal 0.016046 0.000234 -0.999871\nouter loop\nvertex 24.223190 7.084518 8.014062\nvertex 25.427582 5.349819 8.032986\nvertex 24.232944 5.348269 8.013813\nendloop\nendfacet\nfacet normal 0.016042 0.003642 -0.999865\nouter loop\nvertex 24.232944 5.348269 8.013813\nvertex 25.427582 5.349819 8.032986\nvertex 25.563290 3.798691 8.029513\nendloop\nendfacet\nfacet normal 0.014140 0.002009 -0.999898\nouter loop\nvertex 24.232944 5.348269 8.013813\nvertex 25.563290 3.798691 8.029513\nvertex 24.311401 3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.006478 0.001622 -0.999978\nouter loop\nvertex 22.730549 5.346774 8.004080\nvertex 24.232944 5.348269 8.013813\nvertex 24.311401 3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.005350 0.000473 -0.999986\nouter loop\nvertex 22.730549 5.346774 8.004080\nvertex 24.311401 3.796976 8.011806\nvertex 22.754299 3.795325 8.003472\nendloop\nendfacet\nfacet normal 0.002203 0.000425 -0.999997\nouter loop\nvertex 21.109673 5.345647 8.000510\nvertex 22.730549 5.346774 8.004080\nvertex 22.754299 3.795325 8.003472\nendloop\nendfacet\nfacet normal 0.001851 0.000053 -0.999998\nouter loop\nvertex 21.109673 5.345647 8.000510\nvertex 22.754299 3.795325 8.003472\nvertex 21.112640 3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.000327 0.000050 -1.000000\nouter loop\nvertex 19.552801 5.345193 8.000000\nvertex 21.109673 5.345647 8.000510\nvertex 21.112640 3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.000279 0.000000 -1.000000\nouter loop\nvertex 19.552801 5.345193 8.000000\nvertex 21.112640 3.794090 8.000434\nvertex 19.552803 3.793593 8.000000\nendloop\nendfacet\nfacet normal 0.000334 0.000006 -1.000000\nouter loop\nvertex 19.552803 7.082114 8.000000\nvertex 21.109247 7.082470 8.000521\nvertex 21.109673 5.345647 8.000510\nendloop\nendfacet\nfacet normal 0.000328 0.000000 -1.000000\nouter loop\nvertex 19.552803 7.082114 8.000000\nvertex 21.109673 5.345647 8.000510\nvertex 19.552801 5.345193 8.000000\nendloop\nendfacet\nfacet normal 0.000334 -0.000000 -1.000000\nouter loop\nvertex 19.552803 8.846289 8.000000\nvertex 21.109249 8.846521 8.000521\nvertex 21.109247 7.082470 8.000521\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 8.846289 8.000000\nvertex 21.109247 7.082470 8.000521\nvertex 19.552803 7.082114 8.000000\nendloop\nendfacet\nfacet normal -0.008823 0.066099 -0.997774\nouter loop\nvertex 21.108089 13.782950 8.097133\nvertex 22.668369 13.756055 8.081554\nvertex 22.706612 12.940510 8.027189\nendloop\nendfacet\nfacet normal -0.000779 0.081272 -0.996692\nouter loop\nvertex 21.108089 13.782950 8.097133\nvertex 22.706612 12.940510 8.027189\nvertex 21.108513 12.949333 8.029158\nendloop\nendfacet\nfacet normal -0.004329 0.051922 -0.998642\nouter loop\nvertex 22.668369 13.756055 8.081554\nvertex 24.034252 13.696052 8.072515\nvertex 24.159176 12.921573 8.031707\nendloop\nendfacet\nfacet normal 0.003973 0.066698 -0.997765\nouter loop\nvertex 22.668369 13.756055 8.081554\nvertex 24.159176 12.921573 8.031707\nvertex 22.706612 12.940510 8.027189\nendloop\nendfacet\nfacet normal -0.001129 0.018480 -0.999829\nouter loop\nvertex 21.108513 12.949333 8.029158\nvertex 22.706612 12.940510 8.027189\nvertex 22.724588 11.851659 8.007044\nendloop\nendfacet\nfacet normal 0.001837 0.022844 -0.999737\nouter loop\nvertex 21.108513 12.949333 8.029158\nvertex 22.724588 11.851659 8.007044\nvertex 21.109156 11.852637 8.004100\nendloop\nendfacet\nfacet normal 0.003299 0.014571 -0.999888\nouter loop\nvertex 22.706612 12.940510 8.027189\nvertex 24.159176 12.921573 8.031707\nvertex 24.215187 11.849457 8.016268\nendloop\nendfacet\nfacet normal 0.006215 0.018601 -0.999808\nouter loop\nvertex 22.706612 12.940510 8.027189\nvertex 24.215187 11.849457 8.016268\nvertex 22.724588 11.851659 8.007044\nendloop\nendfacet\nfacet normal -0.019371 0.220396 -0.975218\nouter loop\nvertex 19.588913 14.375001 8.261111\nvertex 21.113926 14.368312 8.229306\nvertex 21.108089 13.782950 8.097133\nendloop\nendfacet\nfacet normal -0.007570 0.248826 -0.968519\nouter loop\nvertex 19.588913 14.375001 8.261111\nvertex 21.108089 13.782950 8.097133\nvertex 19.568035 13.786793 8.110156\nendloop\nendfacet\nfacet normal -0.022359 0.180528 -0.983316\nouter loop\nvertex 21.113926 14.368312 8.229306\nvertex 22.647228 14.321472 8.185841\nvertex 22.668369 13.756055 8.081554\nendloop\nendfacet\nfacet normal -0.005942 0.220306 -0.975413\nouter loop\nvertex 21.113926 14.368312 8.229306\nvertex 22.668369 13.756055 8.081554\nvertex 21.108089 13.782950 8.097133\nendloop\nendfacet\nfacet normal -0.017813 0.139884 -0.990008\nouter loop\nvertex 22.647228 14.321472 8.185841\nvertex 23.947687 14.205942 8.146118\nvertex 24.034252 13.696052 8.072515\nendloop\nendfacet\nfacet normal 0.001462 0.181435 -0.983402\nouter loop\nvertex 22.647228 14.321472 8.185841\nvertex 24.034252 13.696052 8.072515\nvertex 22.668369 13.756055 8.081554\nendloop\nendfacet\nfacet normal -0.007751 0.102426 -0.994711\nouter loop\nvertex 23.947687 14.205942 8.146118\nvertex 24.762611 14.062502 8.125000\nvertex 25.061609 13.654374 8.080646\nendloop\nendfacet\nfacet normal 0.013719 0.145136 -0.989317\nouter loop\nvertex 23.947687 14.205942 8.146118\nvertex 25.061609 13.654374 8.080646\nvertex 24.034252 13.696052 8.072515\nendloop\nendfacet\nfacet normal 0.009810 0.047003 -0.998847\nouter loop\nvertex 24.034252 13.696052 8.072515\nvertex 25.061609 13.654374 8.080646\nvertex 25.302427 12.910231 8.047994\nendloop\nendfacet\nfacet normal 0.014770 0.054988 -0.998378\nouter loop\nvertex 24.034252 13.696052 8.072515\nvertex 25.302427 12.910231 8.047994\nvertex 24.159176 12.921573 8.031707\nendloop\nendfacet\nfacet normal 0.014378 0.013398 -0.999807\nouter loop\nvertex 24.159176 12.921573 8.031707\nvertex 25.302427 12.910231 8.047994\nvertex 25.400063 11.848212 8.035166\nendloop\nendfacet\nfacet normal 0.015961 0.015231 -0.999757\nouter loop\nvertex 24.159176 12.921573 8.031707\nvertex 25.400063 11.848212 8.035166\nvertex 24.215187 11.849457 8.016268\nendloop\nendfacet\nfacet normal 0.015950 0.001503 -0.999872\nouter loop\nvertex 24.215187 11.849457 8.016268\nvertex 25.400063 11.848212 8.035166\nvertex 25.414011 10.480907 8.033333\nendloop\nendfacet\nfacet normal 0.016180 0.001706 -0.999868\nouter loop\nvertex 24.215187 11.849457 8.016268\nvertex 25.414011 10.480907 8.033333\nvertex 24.223190 10.480485 8.014062\nendloop\nendfacet\nfacet normal 0.006190 0.001647 -0.999980\nouter loop\nvertex 22.724588 11.851659 8.007044\nvertex 24.215187 11.849457 8.016268\nvertex 24.223190 10.480485 8.014062\nendloop\nendfacet\nfacet normal 0.006613 0.002110 -0.999976\nouter loop\nvertex 22.724588 11.851659 8.007044\nvertex 24.223190 10.480485 8.014062\nvertex 22.727158 10.480080 8.004167\nendloop\nendfacet\nfacet normal 0.001824 0.002101 -0.999996\nouter loop\nvertex 21.109156 11.852637 8.004100\nvertex 22.724588 11.851659 8.007044\nvertex 22.727158 10.480080 8.004167\nendloop\nendfacet\nfacet normal 0.002254 0.002607 -0.999994\nouter loop\nvertex 21.109156 11.852637 8.004100\nvertex 22.727158 10.480080 8.004167\nvertex 21.109249 10.479773 8.000521\nendloop\nendfacet\nfacet normal 0.000012 0.002607 -0.999997\nouter loop\nvertex 19.553366 11.852744 8.004080\nvertex 21.109156 11.852637 8.004100\nvertex 21.109249 10.479773 8.000521\nendloop\nendfacet\nfacet normal 0.000335 0.002971 -0.999996\nouter loop\nvertex 19.553366 11.852744 8.004080\nvertex 21.109249 10.479773 8.000521\nvertex 19.552803 10.479649 8.000000\nendloop\nendfacet\nfacet normal -0.002227 0.022841 -0.999737\nouter loop\nvertex 19.557316 12.950583 8.032639\nvertex 21.108513 12.949333 8.029158\nvertex 21.109156 11.852637 8.004100\nendloop\nendfacet\nfacet normal 0.000016 0.026005 -0.999662\nouter loop\nvertex 19.557316 12.950583 8.032639\nvertex 21.109156 11.852637 8.004100\nvertex 19.553366 11.852744 8.004080\nendloop\nendfacet\nfacet normal -0.008225 0.081266 -0.996659\nouter loop\nvertex 19.568035 13.786793 8.110156\nvertex 21.108089 13.782950 8.097133\nvertex 21.108513 12.949333 8.029158\nendloop\nendfacet\nfacet normal -0.002161 0.092332 -0.995726\nouter loop\nvertex 19.568035 13.786793 8.110156\nvertex 21.108513 12.949333 8.029158\nvertex 19.557316 12.950583 8.032639\nendloop\nendfacet\nfacet normal 0.180586 0.080679 0.980245\nouter loop\nvertex 21.186642 13.783004 9.276489\nvertex 21.196112 12.949749 9.343325\nvertex 22.732565 12.940852 9.061005\nendloop\nendfacet\nfacet normal 0.171458 0.063177 0.983164\nouter loop\nvertex 21.186642 13.783004 9.276489\nvertex 22.732565 12.940852 9.061005\nvertex 22.691643 13.756097 9.015754\nendloop\nendfacet\nfacet normal 0.184294 0.022663 0.982610\nouter loop\nvertex 21.196112 12.949749 9.343325\nvertex 21.200087 11.854041 9.367850\nvertex 22.751530 11.852822 9.076897\nendloop\nendfacet\nfacet normal 0.180792 0.017514 0.983365\nouter loop\nvertex 21.196112 12.949749 9.343325\nvertex 22.751530 11.852822 9.076897\nvertex 22.732565 12.940852 9.061005\nendloop\nendfacet\nfacet normal 0.211063 0.064731 0.975327\nouter loop\nvertex 22.691643 13.756097 9.015754\nvertex 22.732565 12.940852 9.061005\nvertex 24.162418 12.921827 8.752842\nendloop\nendfacet\nfacet normal 0.202004 0.047845 0.978215\nouter loop\nvertex 22.691643 13.756097 9.015754\nvertex 24.162418 12.921827 8.752842\nvertex 24.037163 13.696084 8.740838\nendloop\nendfacet\nfacet normal 0.214084 0.017997 0.976649\nouter loop\nvertex 22.732565 12.940852 9.061005\nvertex 22.751530 11.852822 9.076897\nvertex 24.218555 11.850319 8.755368\nendloop\nendfacet\nfacet normal 0.210835 0.013350 0.977430\nouter loop\nvertex 22.732565 12.940852 9.061005\nvertex 24.218555 11.850319 8.755368\nvertex 24.162418 12.921827 8.752842\nendloop\nendfacet\nfacet normal 0.121374 0.250804 0.960399\nouter loop\nvertex 19.733356 14.375003 9.305555\nvertex 19.754234 13.786851 9.456511\nvertex 21.186642 13.783004 9.276489\nendloop\nendfacet\nfacet normal 0.108992 0.219970 0.969399\nouter loop\nvertex 19.733356 14.375003 9.305555\nvertex 21.186642 13.783004 9.276489\nvertex 21.174864 14.368311 9.145000\nendloop\nendfacet\nfacet normal 0.131593 0.093219 0.986911\nouter loop\nvertex 19.754234 13.786851 9.456511\nvertex 19.764956 12.951040 9.534028\nvertex 21.196112 12.949749 9.343325\nendloop\nendfacet\nfacet normal 0.124502 0.080737 0.988929\nouter loop\nvertex 19.754234 13.786851 9.456511\nvertex 21.196112 12.949749 9.343325\nvertex 21.186642 13.783004 9.276489\nendloop\nendfacet\nfacet normal 0.134783 0.026278 0.990527\nouter loop\nvertex 19.764956 12.951040 9.534028\nvertex 19.768904 11.854286 9.562587\nvertex 21.200087 11.854041 9.367850\nendloop\nendfacet\nfacet normal 0.132070 0.022661 0.990981\nouter loop\nvertex 19.764956 12.951040 9.534028\nvertex 21.200087 11.854041 9.367850\nvertex 21.196112 12.949749 9.343325\nendloop\nendfacet\nfacet normal 0.135215 0.003004 0.990812\nouter loop\nvertex 19.768904 11.854286 9.562587\nvertex 19.769468 10.483306 9.566667\nvertex 21.200653 10.483106 9.371354\nendloop\nendfacet\nfacet normal 0.134824 0.002588 0.990866\nouter loop\nvertex 19.768904 11.854286 9.562587\nvertex 21.200653 10.483106 9.371354\nvertex 21.200087 11.854041 9.367850\nendloop\nendfacet\nfacet normal 0.184832 0.002589 0.982767\nouter loop\nvertex 21.200087 11.854041 9.367850\nvertex 21.200653 10.483106 9.371354\nvertex 22.754240 10.482836 9.079166\nendloop\nendfacet\nfacet normal 0.184326 0.001993 0.982863\nouter loop\nvertex 21.200087 11.854041 9.367850\nvertex 22.754240 10.482836 9.079166\nvertex 22.751530 11.852822 9.076897\nendloop\nendfacet\nfacet normal 0.214560 0.002042 0.976709\nouter loop\nvertex 22.751530 11.852822 9.076897\nvertex 22.754240 10.482836 9.079166\nvertex 24.226574 10.482530 8.755730\nendloop\nendfacet\nfacet normal 0.214092 0.001513 0.976812\nouter loop\nvertex 22.751530 11.852822 9.076897\nvertex 24.226574 10.482530 8.755730\nvertex 24.218555 11.850319 8.755368\nendloop\nendfacet\nfacet normal 0.236527 0.001643 0.971624\nouter loop\nvertex 24.218555 11.850319 8.755368\nvertex 24.226574 10.482530 8.755730\nvertex 25.414009 10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.236297 0.001430 0.971680\nouter loop\nvertex 24.218555 11.850319 8.755368\nvertex 25.414009 10.482211 8.466667\nvertex 25.400064 11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.236288 0.014670 0.971572\nouter loop\nvertex 24.162418 12.921827 8.752842\nvertex 24.218555 11.850319 8.755368\nvertex 25.400064 11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.234715 0.012748 0.971981\nouter loop\nvertex 24.162418 12.921827 8.752842\nvertex 25.400064 11.848762 8.468046\nvertex 25.302429 12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.234786 0.053031 0.970600\nouter loop\nvertex 24.037163 13.696084 8.740838\nvertex 24.162418 12.921827 8.752842\nvertex 25.302429 12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.229893 0.044615 0.972193\nouter loop\nvertex 24.037163 13.696084 8.740838\nvertex 25.302429 12.910394 8.477700\nvertex 25.061607 13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.231550 0.140794 0.962581\nouter loop\nvertex 23.949944 14.205942 8.687243\nvertex 24.037163 13.696084 8.740838\nvertex 25.061607 13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.211196 0.096345 0.972684\nouter loop\nvertex 23.949944 14.205942 8.687243\nvertex 25.061607 13.654394 8.500504\nvertex 24.762611 14.062502 8.525001\nendloop\nendfacet\nfacet normal 0.204599 0.177777 0.962567\nouter loop\nvertex 22.665283 14.321471 8.916937\nvertex 22.691643 13.756097 9.015754\nvertex 24.037163 13.696084 8.740838\nendloop\nendfacet\nfacet normal 0.186093 0.134147 0.973331\nouter loop\nvertex 22.665283 14.321471 8.916937\nvertex 24.037163 13.696084 8.740838\nvertex 23.949944 14.205942 8.687243\nendloop\nendfacet\nfacet normal 0.170355 0.219245 0.960682\nouter loop\nvertex 21.174864 14.368311 9.145000\nvertex 21.186642 13.783004 9.276489\nvertex 22.691643 13.756097 9.015754\nendloop\nendfacet\nfacet normal 0.154304 0.177086 0.972024\nouter loop\nvertex 21.174864 14.368311 9.145000\nvertex 22.691643 13.756097 9.015754\nvertex 22.665283 14.321471 8.916937\nendloop\nendfacet\nfacet normal -0.925336 0.179809 0.333800\nouter loop\nvertex 15.926517 13.692226 8.431500\nvertex 15.764791 12.920452 8.398901\nvertex 15.848109 12.930644 8.624383\nendloop\nendfacet\nfacet normal -0.942867 0.169688 0.286718\nouter loop\nvertex 15.926517 13.692226 8.431500\nvertex 15.848109 12.930644 8.624383\nvertex 15.996692 13.725345 8.642670\nendloop\nendfacet\nfacet normal -0.930933 0.049248 0.361855\nouter loop\nvertex 15.764791 12.920452 8.398901\nvertex 15.702858 11.849790 8.385280\nvertex 15.793253 11.851281 8.617631\nendloop\nendfacet\nfacet normal -0.937705 0.045501 0.344440\nouter loop\nvertex 15.764791 12.920452 8.398901\nvertex 15.793253 11.851281 8.617631\nvertex 15.848109 12.930644 8.624383\nendloop\nendfacet\nfacet normal -0.661215 0.106536 0.742593\nouter loop\nvertex 15.996692 13.725345 8.642670\nvertex 15.848109 12.930644 8.624383\nvertex 16.126717 12.920577 8.873900\nendloop\nendfacet\nfacet normal -0.680988 0.098469 0.725644\nouter loop\nvertex 15.996692 13.725345 8.642670\nvertex 16.126717 12.920577 8.873900\nvertex 16.239573 13.692245 8.875096\nendloop\nendfacet\nfacet normal -0.659997 0.028847 0.750714\nouter loop\nvertex 15.848109 12.930644 8.624383\nvertex 15.793253 11.851281 8.617631\nvertex 16.085794 11.850214 8.874863\nendloop\nendfacet\nfacet normal -0.666398 0.026147 0.745138\nouter loop\nvertex 15.848109 12.930644 8.624383\nvertex 16.085794 11.850214 8.874863\nvertex 16.126717 12.920577 8.873900\nendloop\nendfacet\nfacet normal -0.638856 0.372476 -0.673145\nouter loop\nvertex 16.245834 14.062501 8.333333\nvertex 16.073439 13.654376 8.271119\nvertex 15.926517 13.692226 8.431500\nendloop\nendfacet\nfacet normal -0.679728 0.428326 -0.595404\nouter loop\nvertex 16.245834 14.062501 8.333333\nvertex 15.926517 13.692226 8.431500\nvertex 16.212664 14.199250 8.469577\nendloop\nendfacet\nfacet normal -0.708344 0.179013 -0.682791\nouter loop\nvertex 16.073439 13.654376 8.271119\nvertex 15.932369 12.910254 8.222376\nvertex 15.764791 12.920452 8.398901\nendloop\nendfacet\nfacet normal -0.704649 0.176686 -0.687205\nouter loop\nvertex 16.073439 13.654376 8.271119\nvertex 15.764791 12.920452 8.398901\nvertex 15.926517 13.692226 8.431500\nendloop\nendfacet\nfacet normal -0.726457 0.051960 -0.685245\nouter loop\nvertex 15.932369 12.910254 8.222376\nvertex 15.874880 11.848289 8.202797\nvertex 15.702858 11.849790 8.385280\nendloop\nendfacet\nfacet normal -0.722856 0.050581 -0.689144\nouter loop\nvertex 15.932369 12.910254 8.222376\nvertex 15.702858 11.849790 8.385280\nvertex 15.764791 12.920452 8.398901\nendloop\nendfacet\nfacet normal -0.727964 0.005775 -0.685591\nouter loop\nvertex 15.874880 11.848289 8.202797\nvertex 15.866667 10.481091 8.200000\nvertex 15.694011 10.481650 8.383333\nendloop\nendfacet\nfacet normal -0.727620 0.005683 -0.685957\nouter loop\nvertex 15.874880 11.848289 8.202797\nvertex 15.694011 10.481650 8.383333\nvertex 15.702858 11.849790 8.385280\nendloop\nendfacet\nfacet normal -0.931095 0.005502 0.364735\nouter loop\nvertex 15.702858 11.849790 8.385280\nvertex 15.694011 10.481650 8.383333\nvertex 15.785417 10.482183 8.616667\nendloop\nendfacet\nfacet normal -0.931956 0.005079 0.362536\nouter loop\nvertex 15.702858 11.849790 8.385280\nvertex 15.785417 10.482183 8.616667\nvertex 15.793253 11.851281 8.617631\nendloop\nendfacet\nfacet normal -0.659395 0.003245 0.751790\nouter loop\nvertex 15.793253 11.851281 8.617631\nvertex 15.785417 10.482183 8.616667\nvertex 16.079948 10.482659 8.875000\nendloop\nendfacet\nfacet normal -0.660322 0.002898 0.750977\nouter loop\nvertex 15.793253 11.851281 8.617631\nvertex 16.079948 10.482659 8.875000\nvertex 16.085794 11.850214 8.874863\nendloop\nendfacet\nfacet normal -0.509129 0.002264 0.860687\nouter loop\nvertex 16.085794 11.850214 8.874863\nvertex 16.079948 10.482659 8.875000\nvertex 16.516666 10.483034 9.133333\nendloop\nendfacet\nfacet normal -0.509449 0.002124 0.860498\nouter loop\nvertex 16.085794 11.850214 8.874863\nvertex 16.516666 10.483034 9.133333\nvertex 16.520052 11.849110 9.131964\nendloop\nendfacet\nfacet normal -0.509309 0.020245 0.860346\nouter loop\nvertex 16.126717 12.920577 8.873900\nvertex 16.085794 11.850214 8.874863\nvertex 16.520052 11.849110 9.131964\nendloop\nendfacet\nfacet normal -0.511418 0.019182 0.859118\nouter loop\nvertex 16.126717 12.920577 8.873900\nvertex 16.520052 11.849110 9.131964\nvertex 16.543751 12.910495 9.122376\nendloop\nendfacet\nfacet normal -0.509175 0.073137 0.857550\nouter loop\nvertex 16.239573 13.692245 8.875096\nvertex 16.126717 12.920577 8.873900\nvertex 16.543751 12.910495 9.122376\nendloop\nendfacet\nfacet normal -0.516933 0.068762 0.853260\nouter loop\nvertex 16.239573 13.692245 8.875096\nvertex 16.543751 12.910495 9.122376\nvertex 16.602932 13.654407 9.098280\nendloop\nendfacet\nfacet normal -0.499636 0.188695 0.845433\nouter loop\nvertex 16.475306 14.199250 8.901251\nvertex 16.239573 13.692245 8.875096\nvertex 16.602932 13.654407 9.098280\nendloop\nendfacet\nfacet normal -0.551613 0.166355 0.817343\nouter loop\nvertex 16.475306 14.199250 8.901251\nvertex 16.602932 13.654407 9.098280\nvertex 16.679167 14.062502 9.066667\nendloop\nendfacet\nfacet normal -0.639902 0.292996 0.710408\nouter loop\nvertex 16.284452 14.267941 8.678086\nvertex 15.996692 13.725345 8.642670\nvertex 16.239573 13.692245 8.875096\nendloop\nendfacet\nfacet normal -0.684012 0.283353 0.672190\nouter loop\nvertex 16.284452 14.267941 8.678086\nvertex 16.239573 13.692245 8.875096\nvertex 16.475306 14.199250 8.901251\nendloop\nendfacet\nfacet normal -0.857875 0.468253 0.211637\nouter loop\nvertex 16.212664 14.199250 8.469577\nvertex 15.926517 13.692226 8.431500\nvertex 15.996692 13.725345 8.642670\nendloop\nendfacet\nfacet normal -0.877249 0.455323 0.152037\nouter loop\nvertex 16.212664 14.199250 8.469577\nvertex 15.996692 13.725345 8.642670\nvertex 16.284452 14.267941 8.678086\nendloop\nendfacet\nfacet normal 0.272812 0.001670 -0.962066\nouter loop\nvertex 26.156590 5.351182 8.067980\nvertex 26.146835 7.086800 8.068229\nvertex 26.391111 7.087739 8.137500\nendloop\nendfacet\nfacet normal 0.280158 0.000596 -0.959954\nouter loop\nvertex 26.156590 5.351182 8.067980\nvertex 26.391111 7.087739 8.137500\nvertex 26.394505 5.352378 8.137413\nendloop\nendfacet\nfacet normal 0.272823 0.000000 -0.962064\nouter loop\nvertex 26.146835 7.086800 8.068229\nvertex 26.146837 8.849369 8.068229\nvertex 26.391111 8.849988 8.137500\nendloop\nendfacet\nfacet normal 0.272818 0.000000 -0.962066\nouter loop\nvertex 26.146835 7.086800 8.068229\nvertex 26.391111 8.849988 8.137500\nvertex 26.391111 7.087739 8.137500\nendloop\nendfacet\nfacet normal 0.457040 0.000850 0.889446\nouter loop\nvertex 26.394505 5.352378 8.137413\nvertex 26.391111 7.087739 8.137500\nvertex 26.146837 7.088612 8.263021\nendloop\nendfacet\nfacet normal 0.452912 0.000105 0.891555\nouter loop\nvertex 26.394505 5.352378 8.137413\nvertex 26.146837 7.088612 8.263021\nvertex 26.147263 5.353491 8.263010\nendloop\nendfacet\nfacet normal 0.457043 0.000000 0.889445\nouter loop\nvertex 26.391111 7.087739 8.137500\nvertex 26.391111 8.849988 8.137500\nvertex 26.146837 8.850560 8.263021\nendloop\nendfacet\nfacet normal 0.457042 0.000000 0.889445\nouter loop\nvertex 26.391111 7.087739 8.137500\nvertex 26.146837 8.850560 8.263021\nvertex 26.146837 7.088612 8.263021\nendloop\nendfacet\nfacet normal 0.047932 0.006430 -0.998830\nouter loop\nvertex 25.563290 3.798691 8.029513\nvertex 25.427582 5.349819 8.032986\nvertex 26.156590 5.351182 8.067980\nendloop\nendfacet\nfacet normal 0.054188 0.004033 -0.998523\nouter loop\nvertex 25.563290 3.798691 8.029513\nvertex 26.156590 5.351182 8.067980\nvertex 26.235046 3.800150 8.065972\nendloop\nendfacet\nfacet normal 0.047565 0.000572 -0.998868\nouter loop\nvertex 25.427582 5.349819 8.032986\nvertex 25.414009 7.085731 8.033333\nvertex 26.146835 7.086800 8.068229\nendloop\nendfacet\nfacet normal 0.047943 0.000413 -0.998850\nouter loop\nvertex 25.427582 5.349819 8.032986\nvertex 26.146835 7.086800 8.068229\nvertex 26.156590 5.351182 8.067980\nendloop\nendfacet\nfacet normal 0.047566 0.000000 -0.998868\nouter loop\nvertex 25.414009 7.085731 8.033333\nvertex 25.414009 8.848668 8.033333\nvertex 26.146837 8.849369 8.068229\nendloop\nendfacet\nfacet normal 0.047563 0.000000 -0.998868\nouter loop\nvertex 25.414009 7.085731 8.033333\nvertex 26.146837 8.849369 8.068229\nvertex 26.146835 7.086800 8.068229\nendloop\nendfacet\nfacet normal 0.047565 0.000000 -0.998868\nouter loop\nvertex 25.414009 8.848668 8.033333\nvertex 25.414011 10.480907 8.033333\nvertex 26.146835 10.481279 8.068229\nendloop\nendfacet\nfacet normal 0.047563 0.000000 -0.998868\nouter loop\nvertex 25.414009 8.848668 8.033333\nvertex 26.146835 10.481279 8.068229\nvertex 26.146837 8.849369 8.068229\nendloop\nendfacet\nfacet normal 0.272819 0.000000 -0.962065\nouter loop\nvertex 26.146837 8.849369 8.068229\nvertex 26.146835 10.481279 8.068229\nvertex 26.391113 10.481605 8.137500\nendloop\nendfacet\nfacet normal 0.272821 0.000000 -0.962065\nouter loop\nvertex 26.146837 8.849369 8.068229\nvertex 26.391113 10.481605 8.137500\nvertex 26.391111 8.849988 8.137500\nendloop\nendfacet\nfacet normal 0.457041 0.000000 0.889446\nouter loop\nvertex 26.391111 8.849988 8.137500\nvertex 26.391113 10.481605 8.137500\nvertex 26.146837 10.481909 8.263021\nendloop\nendfacet\nfacet normal 0.457041 0.000000 0.889446\nouter loop\nvertex 26.391111 8.849988 8.137500\nvertex 26.146837 10.481909 8.263021\nvertex 26.146837 8.850560 8.263021\nendloop\nendfacet\nfacet normal 0.267744 0.000000 0.963490\nouter loop\nvertex 26.146837 8.850560 8.263021\nvertex 26.146837 10.481909 8.263021\nvertex 25.414009 10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.267747 -0.000000 0.963489\nouter loop\nvertex 26.146837 8.850560 8.263021\nvertex 25.414009 10.482211 8.466667\nvertex 25.414009 8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.267745 0.000000 0.963490\nouter loop\nvertex 26.146837 7.088612 8.263021\nvertex 26.146837 8.850560 8.263021\nvertex 25.414009 8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.267747 0.000000 0.963489\nouter loop\nvertex 26.146837 7.088612 8.263021\nvertex 25.414009 8.851135 8.466666\nvertex 25.414009 7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.267745 0.000061 0.963490\nouter loop\nvertex 26.147263 5.353491 8.263010\nvertex 26.146837 7.088612 8.263021\nvertex 25.414009 7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.267615 -0.000001 0.963526\nouter loop\nvertex 26.147263 5.353491 8.263010\nvertex 25.414009 7.089484 8.466667\nvertex 25.414009 5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.267612 0.000465 0.963526\nouter loop\nvertex 26.150230 3.802635 8.262934\nvertex 26.147263 5.353491 8.263010\nvertex 25.414009 5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.266708 0.000000 0.963777\nouter loop\nvertex 26.150230 3.802635 8.262934\nvertex 25.414009 5.354605 8.466666\nvertex 25.414011 3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.452912 0.006587 0.891531\nouter loop\nvertex 26.418255 3.801430 8.136806\nvertex 26.394505 5.352378 8.137413\nvertex 26.147263 5.353491 8.263010\nendloop\nendfacet\nfacet normal 0.425800 0.000771 0.904817\nouter loop\nvertex 26.418255 3.801430 8.136806\nvertex 26.147263 5.353491 8.263010\nvertex 26.150230 3.802635 8.262934\nendloop\nendfacet\nfacet normal 0.280041 0.015408 -0.959864\nouter loop\nvertex 26.235046 3.800150 8.065972\nvertex 26.156590 5.351182 8.067980\nvertex 26.394505 5.352378 8.137413\nendloop\nendfacet\nfacet normal 0.360580 0.005887 -0.932710\nouter loop\nvertex 26.235046 3.800150 8.065972\nvertex 26.394505 5.352378 8.137413\nvertex 26.418255 3.801430 8.136806\nendloop\nendfacet\nfacet normal 0.000279 -0.000002 -1.000000\nouter loop\nvertex 19.549603 3.206118 8.000000\nvertex 19.552803 3.793593 8.000000\nvertex 21.112640 3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.000278 0.000141 -1.000000\nouter loop\nvertex 21.112640 3.794090 8.000434\nvertex 21.113426 3.276875 8.000361\nvertex 20.253862 3.238130 8.000117\nendloop\nendfacet\nfacet normal 0.000149 0.000336 -1.000000\nouter loop\nvertex 21.112640 3.794090 8.000434\nvertex 20.253862 3.238130 8.000117\nvertex 19.549603 3.206118 8.000000\nendloop\nendfacet\nfacet normal 0.001849 0.001191 -0.999998\nouter loop\nvertex 21.112640 3.794090 8.000434\nvertex 22.754299 3.795325 8.003472\nvertex 22.772949 3.352315 8.002979\nendloop\nendfacet\nfacet normal 0.001572 0.000143 -0.999999\nouter loop\nvertex 21.112640 3.794090 8.000434\nvertex 22.772949 3.352315 8.002979\nvertex 21.113426 3.276875 8.000361\nendloop\nendfacet\nfacet normal 0.005351 0.001338 -0.999985\nouter loop\nvertex 22.772949 3.352315 8.002979\nvertex 22.754299 3.795325 8.003472\nvertex 24.311401 3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.004311 0.004769 -0.999979\nouter loop\nvertex 24.311401 3.796976 8.011806\nvertex 24.394966 3.272750 8.009665\nvertex 22.854446 3.356021 8.003421\nendloop\nendfacet\nfacet normal 0.005352 0.001310 -0.999985\nouter loop\nvertex 24.311401 3.796976 8.011806\nvertex 22.854446 3.356021 8.003421\nvertex 22.772949 3.352315 8.002979\nendloop\nendfacet\nfacet normal 0.014136 0.006335 -0.999880\nouter loop\nvertex 24.394966 3.272750 8.009665\nvertex 24.311401 3.796976 8.011806\nvertex 25.563290 3.798691 8.029513\nendloop\nendfacet\nfacet normal 0.004153 0.014740 -0.999883\nouter loop\nvertex 25.563290 3.798691 8.029513\nvertex 25.864864 3.190336 8.021798\nvertex 25.666662 3.218757 8.021394\nendloop\nendfacet\nfacet normal 0.005494 -0.086999 -0.996193\nouter loop\nvertex 25.666662 3.218757 8.021394\nvertex 25.143169 3.211766 8.019117\nvertex 24.394966 3.272750 8.009665\nendloop\nendfacet\nfacet normal 0.009890 0.015761 -0.999827\nouter loop\nvertex 25.563290 3.798691 8.029513\nvertex 25.666662 3.218757 8.021394\nvertex 24.394966 3.272750 8.009665\nendloop\nendfacet\nfacet normal -0.239839 0.068515 0.968392\nouter loop\nvertex 17.072617 13.696096 9.291351\nvertex 17.062820 12.921923 9.343699\nvertex 17.730688 12.940925 9.507764\nendloop\nendfacet\nfacet normal -0.226513 0.080775 0.970653\nouter loop\nvertex 17.072617 13.696096 9.291351\nvertex 17.730688 12.940925 9.507764\nvertex 17.714960 13.756108 9.436255\nendloop\nendfacet\nfacet normal -0.244656 0.018514 0.969433\nouter loop\nvertex 17.062820 12.921923 9.343699\nvertex 17.055969 11.850637 9.362429\nvertex 17.735132 11.853064 9.533783\nendloop\nendfacet\nfacet normal -0.239097 0.022242 0.970741\nouter loop\nvertex 17.062820 12.921923 9.343699\nvertex 17.735132 11.853064 9.533783\nvertex 17.730688 12.940925 9.507764\nendloop\nendfacet\nfacet normal -0.085274 0.085436 0.992688\nouter loop\nvertex 17.714960 13.756108 9.436255\nvertex 17.730688 12.940925 9.507764\nvertex 18.612646 12.949788 9.582764\nendloop\nendfacet\nfacet normal -0.078599 0.092845 0.992573\nouter loop\nvertex 17.714960 13.756108 9.436255\nvertex 18.612646 12.949788 9.582764\nvertex 18.594265 13.783009 9.503368\nendloop\nendfacet\nfacet normal -0.088100 0.023458 0.995835\nouter loop\nvertex 17.730688 12.940925 9.507764\nvertex 17.735132 11.853064 9.533783\nvertex 18.619249 11.854171 9.611973\nendloop\nendfacet\nfacet normal -0.084963 0.026042 0.996044\nouter loop\nvertex 17.730688 12.940925 9.507764\nvertex 18.619249 11.854171 9.611973\nvertex 18.612646 12.949788 9.582764\nendloop\nendfacet\nfacet normal -0.387115 0.142882 0.910893\nouter loop\nvertex 16.679167 14.062502 9.066667\nvertex 16.602932 13.654407 9.098280\nvertex 17.072617 13.696096 9.291351\nendloop\nendfacet\nfacet normal -0.356462 0.179492 0.916906\nouter loop\nvertex 16.679167 14.062502 9.066667\nvertex 17.072617 13.696096 9.291351\nvertex 17.038143 14.205942 9.178142\nendloop\nendfacet\nfacet normal -0.392621 0.060960 0.917678\nouter loop\nvertex 16.602932 13.654407 9.098280\nvertex 16.543751 12.910495 9.122376\nvertex 17.062820 12.921923 9.343699\nendloop\nendfacet\nfacet normal -0.384431 0.067120 0.920710\nouter loop\nvertex 16.602932 13.654407 9.098280\nvertex 17.062820 12.921923 9.343699\nvertex 17.072617 13.696096 9.291351\nendloop\nendfacet\nfacet normal -0.395039 0.017117 0.918505\nouter loop\nvertex 16.543751 12.910495 9.122376\nvertex 16.520052 11.849110 9.131964\nvertex 17.055969 11.850637 9.362429\nendloop\nendfacet\nfacet normal -0.392498 0.018588 0.919565\nouter loop\nvertex 16.543751 12.910495 9.122376\nvertex 17.055969 11.850637 9.362429\nvertex 17.062820 12.921923 9.343699\nendloop\nendfacet\nfacet normal -0.395447 0.001900 0.918487\nouter loop\nvertex 16.520052 11.849110 9.131964\nvertex 16.516666 10.483034 9.133333\nvertex 17.054993 10.483283 9.365105\nendloop\nendfacet\nfacet normal -0.395063 0.002080 0.918652\nouter loop\nvertex 16.520052 11.849110 9.131964\nvertex 17.054993 10.483283 9.365105\nvertex 17.055969 11.850637 9.362429\nendloop\nendfacet\nfacet normal -0.245485 0.002073 0.969398\nouter loop\nvertex 17.055969 11.850637 9.362429\nvertex 17.054993 10.483283 9.365105\nvertex 17.735767 10.483404 9.537500\nendloop\nendfacet\nfacet normal -0.244643 0.002518 0.969610\nouter loop\nvertex 17.055969 11.850637 9.362429\nvertex 17.735767 10.483404 9.537500\nvertex 17.735132 11.853064 9.533783\nendloop\nendfacet\nfacet normal -0.088573 0.002662 0.996066\nouter loop\nvertex 17.735132 11.853064 9.533783\nvertex 17.735767 10.483404 9.537500\nvertex 18.620193 10.483410 9.616146\nendloop\nendfacet\nfacet normal -0.088099 0.002972 0.996107\nouter loop\nvertex 17.735132 11.853064 9.533783\nvertex 18.620193 10.483410 9.616146\nvertex 18.619249 11.854171 9.611973\nendloop\nendfacet\nfacet normal 0.043015 0.003071 0.999070\nouter loop\nvertex 18.619249 11.854171 9.611973\nvertex 18.620193 10.483410 9.616146\nvertex 19.769468 10.483306 9.566667\nendloop\nendfacet\nfacet normal 0.042916 0.002991 0.999074\nouter loop\nvertex 18.619249 11.854171 9.611973\nvertex 19.769468 10.483306 9.566667\nvertex 19.768904 11.854286 9.562587\nendloop\nendfacet\nfacet normal 0.042899 0.026884 0.998718\nouter loop\nvertex 18.612646 12.949788 9.582764\nvertex 18.619249 11.854171 9.611973\nvertex 19.768904 11.854286 9.562587\nendloop\nendfacet\nfacet normal 0.042213 0.026159 0.998766\nouter loop\nvertex 18.612646 12.949788 9.582764\nvertex 19.768904 11.854286 9.562587\nvertex 19.764956 12.951040 9.534028\nendloop\nendfacet\nfacet normal 0.041959 0.095692 0.994526\nouter loop\nvertex 18.594265 13.783009 9.503368\nvertex 18.612646 12.949788 9.582764\nvertex 19.764956 12.951040 9.534028\nendloop\nendfacet\nfacet normal 0.039880 0.092783 0.994887\nouter loop\nvertex 18.594265 13.783009 9.503368\nvertex 19.764956 12.951040 9.534028\nvertex 19.754234 13.786851 9.456511\nendloop\nendfacet\nfacet normal 0.038138 0.258394 0.965287\nouter loop\nvertex 18.556152 14.368310 9.348197\nvertex 18.594265 13.783009 9.503368\nvertex 19.754234 13.786851 9.456511\nendloop\nendfacet\nfacet normal 0.033635 0.249582 0.967769\nouter loop\nvertex 18.556152 14.368310 9.348197\nvertex 19.754234 13.786851 9.456511\nvertex 19.733356 14.375003 9.305555\nendloop\nendfacet\nfacet normal -0.081163 0.238954 0.967633\nouter loop\nvertex 17.665802 14.321471 9.292516\nvertex 17.714960 13.756108 9.436255\nvertex 18.594265 13.783009 9.503368\nendloop\nendfacet\nfacet normal -0.073570 0.251088 0.965164\nouter loop\nvertex 17.665802 14.321471 9.292516\nvertex 18.594265 13.783009 9.503368\nvertex 18.556152 14.368310 9.348197\nendloop\nendfacet\nfacet normal -0.233162 0.195746 0.952533\nouter loop\nvertex 17.038143 14.205942 9.178142\nvertex 17.072617 13.696096 9.291351\nvertex 17.714960 13.756108 9.436255\nendloop\nendfacet\nfacet normal -0.214355 0.223125 0.950930\nouter loop\nvertex 17.038143 14.205942 9.178142\nvertex 17.714960 13.756108 9.436255\nvertex 17.665802 14.321471 9.292516\nendloop\nendfacet\nfacet normal -0.070047 0.096169 -0.992897\nouter loop\nvertex 16.490507 13.696053 8.177488\nvertex 17.211208 13.756058 8.132457\nvertex 17.162565 12.940511 8.056896\nendloop\nendfacet\nfacet normal -0.074129 0.092546 -0.992945\nouter loop\nvertex 16.490507 13.696053 8.177488\nvertex 17.162565 12.940511 8.056896\nvertex 16.396286 12.921580 8.112339\nendloop\nendfacet\nfacet normal -0.017663 0.095869 -0.995237\nouter loop\nvertex 17.211208 13.756058 8.132457\nvertex 18.246180 13.782951 8.116679\nvertex 18.223684 12.949332 8.036777\nendloop\nendfacet\nfacet normal -0.019650 0.093399 -0.995435\nouter loop\nvertex 17.211208 13.756058 8.132457\nvertex 18.223684 12.949332 8.036777\nvertex 17.162565 12.940511 8.056896\nendloop\nendfacet\nfacet normal -0.072800 0.026879 -0.996984\nouter loop\nvertex 16.396286 12.921580 8.112339\nvertex 17.162565 12.940511 8.056896\nvertex 17.142763 11.851664 8.028987\nendloop\nendfacet\nfacet normal -0.074728 0.025524 -0.996877\nouter loop\nvertex 16.396286 12.921580 8.112339\nvertex 17.142763 11.851664 8.028987\nvertex 16.356508 11.849483 8.087871\nendloop\nendfacet\nfacet normal -0.019174 0.026985 -0.999452\nouter loop\nvertex 17.162565 12.940511 8.056896\nvertex 18.223684 12.949332 8.036777\nvertex 18.215160 11.852634 8.007331\nendloop\nendfacet\nfacet normal -0.020208 0.025985 -0.999458\nouter loop\nvertex 17.162565 12.940511 8.056896\nvertex 18.215160 11.852634 8.007331\nvertex 17.142763 11.851664 8.028987\nendloop\nendfacet\nfacet normal -0.199719 0.267532 -0.942623\nouter loop\nvertex 16.245834 14.062501 8.333333\nvertex 16.597235 14.205941 8.299591\nvertex 16.490507 13.696053 8.177488\nendloop\nendfacet\nfacet normal -0.235532 0.242939 -0.941013\nouter loop\nvertex 16.245834 14.062501 8.333333\nvertex 16.490507 13.696053 8.177488\nvertex 16.073439 13.654376 8.271119\nendloop\nendfacet\nfacet normal -0.073220 0.257975 -0.963373\nouter loop\nvertex 16.597235 14.205941 8.299591\nvertex 17.280115 14.321469 8.278626\nvertex 17.211208 13.756058 8.132457\nendloop\nendfacet\nfacet normal -0.080975 0.248118 -0.965340\nouter loop\nvertex 16.597235 14.205941 8.299591\nvertex 17.211208 13.756058 8.132457\nvertex 16.490507 13.696053 8.177488\nendloop\nendfacet\nfacet normal -0.018209 0.257842 -0.966015\nouter loop\nvertex 17.280115 14.321469 8.278626\nvertex 18.286760 14.368312 8.272155\nvertex 18.246180 13.782951 8.116679\nendloop\nendfacet\nfacet normal -0.021312 0.252667 -0.967319\nouter loop\nvertex 17.280115 14.321469 8.278626\nvertex 18.246180 13.782951 8.116679\nvertex 17.211208 13.756058 8.132457\nendloop\nendfacet\nfacet normal -0.009492 0.248886 -0.968486\nouter loop\nvertex 18.286760 14.368312 8.272155\nvertex 19.588913 14.375001 8.261111\nvertex 19.568035 13.786793 8.110156\nendloop\nendfacet\nfacet normal -0.005515 0.257059 -0.966380\nouter loop\nvertex 18.286760 14.368312 8.272155\nvertex 19.568035 13.786793 8.110156\nvertex 18.246180 13.782951 8.116679\nendloop\nendfacet\nfacet normal -0.005183 0.092370 -0.995711\nouter loop\nvertex 18.246180 13.782951 8.116679\nvertex 19.568035 13.786793 8.110156\nvertex 19.557316 12.950583 8.032639\nendloop\nendfacet\nfacet normal -0.003178 0.095497 -0.995425\nouter loop\nvertex 18.246180 13.782951 8.116679\nvertex 19.557316 12.950583 8.032639\nvertex 18.223684 12.949332 8.036777\nendloop\nendfacet\nfacet normal -0.003128 0.026016 -0.999657\nouter loop\nvertex 18.223684 12.949332 8.036777\nvertex 19.557316 12.950583 8.032639\nvertex 19.553366 11.852744 8.004080\nendloop\nendfacet\nfacet normal -0.002431 0.026859 -0.999636\nouter loop\nvertex 18.223684 12.949332 8.036777\nvertex 19.553366 11.852744 8.004080\nvertex 18.215160 11.852634 8.007331\nendloop\nendfacet\nfacet normal -0.002431 0.002972 -0.999993\nouter loop\nvertex 18.215160 11.852634 8.007331\nvertex 19.553366 11.852744 8.004080\nvertex 19.552803 10.479649 8.000000\nendloop\nendfacet\nfacet normal -0.002333 0.003066 -0.999993\nouter loop\nvertex 18.215160 11.852634 8.007331\nvertex 19.552803 10.479649 8.000000\nvertex 18.213943 10.479768 8.003125\nendloop\nendfacet\nfacet normal -0.020192 0.003081 -0.999791\nouter loop\nvertex 17.142763 11.851664 8.028987\nvertex 18.215160 11.852634 8.007331\nvertex 18.213943 10.479768 8.003125\nendloop\nendfacet\nfacet normal -0.020361 0.002948 -0.999788\nouter loop\nvertex 17.142763 11.851664 8.028987\nvertex 18.213943 10.479768 8.003125\nvertex 17.139935 10.480088 8.025000\nendloop\nendfacet\nfacet normal -0.074690 0.003053 -0.997202\nouter loop\nvertex 16.356508 11.849483 8.087871\nvertex 17.142763 11.851664 8.028987\nvertex 17.139935 10.480088 8.025000\nendloop\nendfacet\nfacet normal -0.075031 0.002858 -0.997177\nouter loop\nvertex 16.356508 11.849483 8.087871\nvertex 17.139935 10.480088 8.025000\nvertex 16.350824 10.480552 8.084374\nendloop\nendfacet\nfacet normal -0.232106 0.003448 -0.972684\nouter loop\nvertex 15.874880 11.848289 8.202797\nvertex 16.356508 11.849483 8.087871\nvertex 16.350824 10.480552 8.084374\nendloop\nendfacet\nfacet normal -0.232286 0.003385 -0.972641\nouter loop\nvertex 15.874880 11.848289 8.202797\nvertex 16.350824 10.480552 8.084374\nvertex 15.866667 10.481091 8.200000\nendloop\nendfacet\nfacet normal -0.231388 0.030777 -0.972375\nouter loop\nvertex 15.932369 12.910254 8.222376\nvertex 16.396286 12.921580 8.112339\nvertex 16.356508 11.849483 8.087871\nendloop\nendfacet\nfacet normal -0.232069 0.030489 -0.972221\nouter loop\nvertex 15.932369 12.910254 8.222376\nvertex 16.356508 11.849483 8.087871\nvertex 15.874880 11.848289 8.202797\nendloop\nendfacet\nfacet normal -0.228104 0.109138 -0.967501\nouter loop\nvertex 16.073439 13.654376 8.271119\nvertex 16.490507 13.696053 8.177488\nvertex 16.396286 12.921580 8.112339\nendloop\nendfacet\nfacet normal -0.231940 0.107299 -0.966794\nouter loop\nvertex 16.073439 13.654376 8.271119\nvertex 16.396286 12.921580 8.112339\nvertex 15.932369 12.910254 8.222376\nendloop\nendfacet\nfacet normal -0.075032 0.000000 -0.997181\nouter loop\nvertex 16.350824 8.847996 8.084374\nvertex 17.139935 8.847120 8.025000\nvertex 17.139935 7.083379 8.025000\nendloop\nendfacet\nfacet normal -0.075029 0.000000 -0.997181\nouter loop\nvertex 16.350824 8.847996 8.084374\nvertex 17.139935 7.083379 8.025000\nvertex 16.350824 7.084708 8.084374\nendloop\nendfacet\nfacet normal -0.020364 0.000000 -0.999793\nouter loop\nvertex 17.139935 8.847120 8.025000\nvertex 18.213943 8.846513 8.003125\nvertex 18.213943 7.082455 8.003125\nendloop\nendfacet\nfacet normal -0.020362 0.000000 -0.999793\nouter loop\nvertex 17.139935 8.847120 8.025000\nvertex 18.213943 7.082455 8.003125\nvertex 17.139935 7.083379 8.025000\nendloop\nendfacet\nfacet normal -0.075030 0.000396 -0.997181\nouter loop\nvertex 16.350824 7.084708 8.084374\nvertex 17.139935 7.083379 8.025000\nvertex 17.137676 5.346809 8.024479\nendloop\nendfacet\nfacet normal -0.073410 0.001135 -0.997301\nouter loop\nvertex 16.350824 7.084708 8.084374\nvertex 17.137676 5.346809 8.024479\nvertex 16.344336 5.348505 8.082877\nendloop\nendfacet\nfacet normal -0.020363 0.000041 -0.999793\nouter loop\nvertex 17.139935 7.083379 8.025000\nvertex 18.213943 7.082455 8.003125\nvertex 18.213661 5.345628 8.003059\nendloop\nendfacet\nfacet normal -0.019902 0.000326 -0.999802\nouter loop\nvertex 17.139935 7.083379 8.025000\nvertex 18.213661 5.345628 8.003059\nvertex 17.137676 5.346809 8.024479\nendloop\nendfacet\nfacet normal -0.232287 0.000000 -0.972647\nouter loop\nvertex 15.866667 10.481091 8.200000\nvertex 16.350824 10.480552 8.084374\nvertex 16.350824 8.847996 8.084374\nendloop\nendfacet\nfacet normal -0.232285 0.000000 -0.972648\nouter loop\nvertex 15.866667 10.481091 8.200000\nvertex 16.350824 8.847996 8.084374\nvertex 15.866667 8.849014 8.200000\nendloop\nendfacet\nfacet normal -0.075030 0.000000 -0.997181\nouter loop\nvertex 16.350824 10.480552 8.084374\nvertex 17.139935 10.480088 8.025000\nvertex 17.139935 8.847120 8.025000\nendloop\nendfacet\nfacet normal -0.075030 0.000000 -0.997181\nouter loop\nvertex 16.350824 10.480552 8.084374\nvertex 17.139935 8.847120 8.025000\nvertex 16.350824 8.847996 8.084374\nendloop\nendfacet\nfacet normal -0.020364 0.000000 -0.999793\nouter loop\nvertex 17.139935 10.480088 8.025000\nvertex 18.213943 10.479768 8.003125\nvertex 18.213943 8.846513 8.003125\nendloop\nendfacet\nfacet normal -0.020362 0.000000 -0.999793\nouter loop\nvertex 17.139935 10.480088 8.025000\nvertex 18.213943 8.846513 8.003125\nvertex 17.139935 8.847120 8.025000\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 10.479768 8.003125\nvertex 19.552803 10.479649 8.000000\nvertex 19.552803 8.846289 8.000000\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 10.479768 8.003125\nvertex 19.552803 8.846289 8.000000\nvertex 18.213943 8.846513 8.003125\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 8.846513 8.003125\nvertex 19.552803 8.846289 8.000000\nvertex 19.552803 7.082114 8.000000\nendloop\nendfacet\nfacet normal -0.002335 0.000000 -0.999997\nouter loop\nvertex 18.213943 8.846513 8.003125\nvertex 19.552803 7.082114 8.000000\nvertex 18.213943 7.082455 8.003125\nendloop\nendfacet\nfacet normal -0.002333 0.000000 -0.999997\nouter loop\nvertex 18.213943 7.082455 8.003125\nvertex 19.552803 7.082114 8.000000\nvertex 19.552801 5.345193 8.000000\nendloop\nendfacet\nfacet normal -0.002284 0.000038 -0.999997\nouter loop\nvertex 18.213943 7.082455 8.003125\nvertex 19.552801 5.345193 8.000000\nvertex 18.213661 5.345628 8.003059\nendloop\nendfacet\nfacet normal -0.002284 0.000000 -0.999997\nouter loop\nvertex 18.213661 5.345628 8.003059\nvertex 19.552801 5.345193 8.000000\nvertex 19.552803 3.793593 8.000000\nendloop\nendfacet\nfacet normal -0.001942 0.000296 -0.999998\nouter loop\nvertex 18.213661 5.345628 8.003059\nvertex 19.552803 3.793593 8.000000\nvertex 18.211685 3.794066 8.002604\nendloop\nendfacet\nfacet normal -0.019902 0.000319 -0.999802\nouter loop\nvertex 17.137676 5.346809 8.024479\nvertex 18.213661 5.345628 8.003059\nvertex 18.211685 3.794066 8.002604\nendloop\nendfacet\nfacet normal -0.016721 0.002520 -0.999857\nouter loop\nvertex 17.137676 5.346809 8.024479\nvertex 18.211685 3.794066 8.002604\nvertex 17.121878 3.795351 8.020833\nendloop\nendfacet\nfacet normal -0.073407 0.003091 -0.997297\nouter loop\nvertex 16.344336 5.348505 8.082877\nvertex 17.137676 5.346809 8.024479\nvertex 17.121878 3.795351 8.020833\nendloop\nendfacet\nfacet normal -0.060126 0.009772 -0.998143\nouter loop\nvertex 16.344336 5.348505 8.082877\nvertex 17.121878 3.795351 8.020833\nvertex 16.292145 3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.229944 0.015290 -0.973084\nouter loop\nvertex 15.857639 5.350487 8.197917\nvertex 16.344336 5.348505 8.082877\nvertex 16.292145 3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.198281 0.024701 -0.979834\nouter loop\nvertex 15.857639 5.350487 8.197917\nvertex 16.292145 3.797194 8.070833\nvertex 15.767362 3.799347 8.177083\nendloop\nendfacet\nfacet normal -0.232282 0.001707 -0.972647\nouter loop\nvertex 15.866667 7.086260 8.200000\nvertex 16.350824 7.084708 8.084374\nvertex 16.344336 5.348505 8.082877\nendloop\nendfacet\nfacet normal -0.230020 0.002364 -0.973183\nouter loop\nvertex 15.866667 7.086260 8.200000\nvertex 16.344336 5.348505 8.082877\nvertex 15.857639 5.350487 8.197917\nendloop\nendfacet\nfacet normal -0.232285 0.000000 -0.972648\nouter loop\nvertex 15.866667 8.849014 8.200000\nvertex 16.350824 8.847996 8.084374\nvertex 16.350824 7.084708 8.084374\nendloop\nendfacet\nfacet normal -0.232286 0.000000 -0.972647\nouter loop\nvertex 15.866667 8.849014 8.200000\nvertex 16.350824 7.084708 8.084374\nvertex 15.866667 7.086260 8.200000\nendloop\nendfacet\nfacet normal -0.245485 0.000000 0.969400\nouter loop\nvertex 17.054993 8.853159 9.365105\nvertex 17.054991 7.092562 9.365105\nvertex 17.735767 7.092913 9.537500\nendloop\nendfacet\nfacet normal -0.245487 0.000000 0.969400\nouter loop\nvertex 17.054993 8.853159 9.365105\nvertex 17.735767 7.092913 9.537500\nvertex 17.735767 8.853391 9.537500\nendloop\nendfacet\nfacet normal -0.245487 -0.000000 0.969400\nouter loop\nvertex 17.054991 7.092562 9.365105\nvertex 17.054993 5.358536 9.365105\nvertex 17.735767 5.358985 9.537500\nendloop\nendfacet\nfacet normal -0.245484 0.000000 0.969401\nouter loop\nvertex 17.054991 7.092562 9.365105\nvertex 17.735767 5.358985 9.537500\nvertex 17.735767 7.092913 9.537500\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 8.853391 9.537500\nvertex 17.735767 7.092913 9.537500\nvertex 18.620193 7.092926 9.616146\nendloop\nendfacet\nfacet normal -0.088574 0.000000 0.996070\nouter loop\nvertex 17.735767 8.853391 9.537500\nvertex 18.620193 7.092926 9.616146\nvertex 18.620193 8.853397 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 7.092913 9.537500\nvertex 17.735767 5.358985 9.537500\nvertex 18.620193 5.359001 9.616146\nendloop\nendfacet\nfacet normal -0.088572 0.000000 0.996070\nouter loop\nvertex 17.735767 7.092913 9.537500\nvertex 18.620193 5.359001 9.616146\nvertex 18.620193 7.092926 9.616146\nendloop\nendfacet\nfacet normal -0.395446 0.000000 0.918489\nouter loop\nvertex 16.516666 10.483034 9.133333\nvertex 16.516666 8.852689 9.133333\nvertex 17.054993 8.853159 9.365105\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 10.483034 9.133333\nvertex 17.054993 8.853159 9.365105\nvertex 17.054993 10.483283 9.365105\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 8.852689 9.133333\nvertex 16.516666 7.091847 9.133333\nvertex 17.054991 7.092562 9.365105\nendloop\nendfacet\nfacet normal -0.395445 0.000001 0.918489\nouter loop\nvertex 16.516666 8.852689 9.133333\nvertex 17.054991 7.092562 9.365105\nvertex 17.054993 8.853159 9.365105\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 7.091847 9.133333\nvertex 16.516666 5.357624 9.133333\nvertex 17.054993 5.358536 9.365105\nendloop\nendfacet\nfacet normal -0.395448 -0.000001 0.918488\nouter loop\nvertex 16.516666 7.091847 9.133333\nvertex 17.054993 5.358536 9.365105\nvertex 17.054991 7.092562 9.365105\nendloop\nendfacet\nfacet normal -0.395449 0.000000 0.918488\nouter loop\nvertex 16.516666 5.357624 9.133333\nvertex 16.516666 3.807135 9.133333\nvertex 17.054991 3.808129 9.365105\nendloop\nendfacet\nfacet normal -0.395446 0.000001 0.918489\nouter loop\nvertex 16.516666 5.357624 9.133333\nvertex 17.054991 3.808129 9.365105\nvertex 17.054993 5.358536 9.365105\nendloop\nendfacet\nfacet normal -0.245485 0.000000 0.969400\nouter loop\nvertex 17.054993 5.358536 9.365105\nvertex 17.054991 3.808129 9.365105\nvertex 17.735767 3.808617 9.537500\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 5.358536 9.365105\nvertex 17.735767 3.808617 9.537500\nvertex 17.735767 5.358985 9.537500\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 5.358985 9.537500\nvertex 17.735767 3.808617 9.537500\nvertex 18.620193 3.808635 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 5.358985 9.537500\nvertex 18.620193 3.808635 9.616146\nvertex 18.620193 5.359001 9.616146\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 5.359001 9.616146\nvertex 18.620193 3.808635 9.616146\nvertex 19.769468 3.808219 9.566667\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 5.359001 9.616146\nvertex 19.769468 3.808219 9.566667\nvertex 19.769468 5.358619 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999075\nouter loop\nvertex 18.620193 7.092926 9.616146\nvertex 18.620193 5.359001 9.616146\nvertex 19.769468 5.358619 9.566667\nendloop\nendfacet\nfacet normal 0.043012 0.000000 0.999075\nouter loop\nvertex 18.620193 7.092926 9.616146\nvertex 19.769468 5.358619 9.566667\nvertex 19.769468 7.092627 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999074\nouter loop\nvertex 18.620193 8.853397 9.616146\nvertex 18.620193 7.092926 9.616146\nvertex 19.769468 7.092627 9.566667\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 8.853397 9.616146\nvertex 19.769468 7.092627 9.566667\nvertex 19.769468 8.853203 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999074\nouter loop\nvertex 18.620193 10.483410 9.616146\nvertex 18.620193 8.853397 9.616146\nvertex 19.769468 8.853203 9.566667\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999074\nouter loop\nvertex 18.620193 10.483410 9.616146\nvertex 19.769468 8.853203 9.566667\nvertex 19.769468 10.483306 9.566667\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 10.483404 9.537500\nvertex 17.735767 8.853391 9.537500\nvertex 18.620193 8.853397 9.616146\nendloop\nendfacet\nfacet normal -0.088574 0.000000 0.996070\nouter loop\nvertex 17.735767 10.483404 9.537500\nvertex 18.620193 8.853397 9.616146\nvertex 18.620193 10.483410 9.616146\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 10.483283 9.365105\nvertex 17.054993 8.853159 9.365105\nvertex 17.735767 8.853391 9.537500\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 10.483283 9.365105\nvertex 17.735767 8.853391 9.537500\nvertex 17.735767 10.483404 9.537500\nendloop\nendfacet\nfacet normal -0.260777 0.853498 0.451151\nouter loop\nvertex 16.905079 14.500335 8.978137\nvertex 17.568832 14.658748 9.062117\nvertex 17.455404 14.771413 8.783410\nendloop\nendfacet\nfacet normal -0.242171 0.840189 0.485218\nouter loop\nvertex 16.905079 14.500335 8.978137\nvertex 17.455404 14.771413 8.783410\nvertex 16.756197 14.599973 8.731298\nendloop\nendfacet\nfacet normal -0.076539 0.920191 0.383914\nouter loop\nvertex 17.568832 14.658748 9.062117\nvertex 18.493919 14.718086 9.104320\nvertex 18.419262 14.834710 8.809905\nendloop\nendfacet\nfacet normal -0.071003 0.914397 0.398542\nouter loop\nvertex 17.568832 14.658748 9.062117\nvertex 18.419262 14.834710 8.809905\nvertex 17.455404 14.771413 8.783410\nendloop\nendfacet\nfacet normal -0.204917 0.929214 -0.307524\nouter loop\nvertex 16.756197 14.599973 8.731298\nvertex 17.455404 14.771413 8.783410\nvertex 17.359531 14.658748 8.506865\nendloop\nendfacet\nfacet normal -0.205023 0.929081 -0.307853\nouter loop\nvertex 16.756197 14.599973 8.731298\nvertex 17.359531 14.658748 8.506865\nvertex 16.664705 14.500335 8.491524\nendloop\nendfacet\nfacet normal -0.051432 0.932644 -0.357113\nouter loop\nvertex 17.455404 14.771413 8.783410\nvertex 18.419262 14.834710 8.809905\nvertex 18.346798 14.718087 8.515761\nendloop\nendfacet\nfacet normal -0.052708 0.931059 -0.361041\nouter loop\nvertex 17.455404 14.771413 8.783410\nvertex 18.346798 14.718087 8.515761\nvertex 17.359531 14.658748 8.506865\nendloop\nendfacet\nfacet normal -0.409180 0.378964 0.830035\nouter loop\nvertex 16.679167 14.062502 9.066667\nvertex 17.038143 14.205942 9.178142\nvertex 16.905079 14.500335 8.978137\nendloop\nendfacet\nfacet normal -0.414807 0.381097 0.826257\nouter loop\nvertex 16.679167 14.062502 9.066667\nvertex 16.905079 14.500335 8.978137\nvertex 16.475306 14.199250 8.901251\nendloop\nendfacet\nfacet normal -0.243370 0.498430 0.832069\nouter loop\nvertex 17.038143 14.205942 9.178142\nvertex 17.665802 14.321471 9.292516\nvertex 17.568832 14.658748 9.062117\nendloop\nendfacet\nfacet normal -0.221536 0.477507 0.850241\nouter loop\nvertex 17.038143 14.205942 9.178142\nvertex 17.568832 14.658748 9.062117\nvertex 16.905079 14.500335 8.978137\nendloop\nendfacet\nfacet normal -0.081027 0.560320 0.824303\nouter loop\nvertex 17.665802 14.321471 9.292516\nvertex 18.556152 14.368310 9.348197\nvertex 18.493919 14.718086 9.104320\nendloop\nendfacet\nfacet normal -0.073170 0.548127 0.833189\nouter loop\nvertex 17.665802 14.321471 9.292516\nvertex 18.493919 14.718086 9.104320\nvertex 17.568832 14.658748 9.062117\nendloop\nendfacet\nfacet normal 0.026814 0.559897 0.828128\nouter loop\nvertex 18.556152 14.368310 9.348197\nvertex 19.733356 14.375003 9.305555\nvertex 19.700632 14.726565 9.068924\nendloop\nendfacet\nfacet normal 0.019972 0.574211 0.818464\nouter loop\nvertex 18.556152 14.368310 9.348197\nvertex 19.700632 14.726565 9.068924\nvertex 18.493919 14.718086 9.104320\nendloop\nendfacet\nfacet normal 0.004617 0.925364 0.379051\nouter loop\nvertex 18.493919 14.718086 9.104320\nvertex 19.700632 14.726565 9.068924\nvertex 19.661137 14.843751 8.783334\nendloop\nendfacet\nfacet normal 0.001105 0.929810 0.368039\nouter loop\nvertex 18.493919 14.718086 9.104320\nvertex 19.661137 14.843751 8.783334\nvertex 18.419262 14.834710 8.809905\nendloop\nendfacet\nfacet normal -0.014824 0.925763 -0.377813\nouter loop\nvertex 18.419262 14.834710 8.809905\nvertex 19.661137 14.843751 8.783334\nvertex 19.621639 14.726565 8.497743\nendloop\nendfacet\nfacet normal -0.011363 0.930494 -0.366131\nouter loop\nvertex 18.419262 14.834710 8.809905\nvertex 19.621639 14.726565 8.497743\nvertex 18.346798 14.718087 8.515761\nendloop\nendfacet\nfacet normal -0.015434 0.559302 -0.828820\nouter loop\nvertex 18.346798 14.718087 8.515761\nvertex 19.621639 14.726565 8.497743\nvertex 19.588913 14.375001 8.261111\nendloop\nendfacet\nfacet normal -0.009894 0.572629 -0.819755\nouter loop\nvertex 18.346798 14.718087 8.515761\nvertex 19.588913 14.375001 8.261111\nvertex 18.286760 14.368312 8.272155\nendloop\nendfacet\nfacet normal -0.027153 0.574440 -0.818096\nouter loop\nvertex 17.359531 14.658748 8.506865\nvertex 18.346798 14.718087 8.515761\nvertex 18.286760 14.368312 8.272155\nendloop\nendfacet\nfacet normal -0.031604 0.565255 -0.824310\nouter loop\nvertex 17.359531 14.658748 8.506865\nvertex 18.286760 14.368312 8.272155\nvertex 17.280115 14.321469 8.278626\nendloop\nendfacet\nfacet normal -0.113200 0.574987 -0.810294\nouter loop\nvertex 16.664705 14.500335 8.491524\nvertex 17.359531 14.658748 8.506865\nvertex 17.280115 14.321469 8.278626\nendloop\nendfacet\nfacet normal -0.120109 0.561358 -0.818811\nouter loop\nvertex 16.664705 14.500335 8.491524\nvertex 17.280115 14.321469 8.278626\nvertex 16.597235 14.205941 8.299591\nendloop\nendfacet\nfacet normal -0.341250 0.566992 -0.749712\nouter loop\nvertex 16.212664 14.199250 8.469577\nvertex 16.664705 14.500335 8.491524\nvertex 16.597235 14.205941 8.299591\nendloop\nendfacet\nfacet normal -0.324005 0.627125 -0.708333\nouter loop\nvertex 16.212664 14.199250 8.469577\nvertex 16.597235 14.205941 8.299591\nvertex 16.245834 14.062501 8.333333\nendloop\nendfacet\nfacet normal -0.561493 0.817890 -0.125621\nouter loop\nvertex 16.284452 14.267941 8.678086\nvertex 16.756197 14.599973 8.731298\nvertex 16.664705 14.500335 8.491524\nendloop\nendfacet\nfacet normal -0.549505 0.831193 -0.084632\nouter loop\nvertex 16.284452 14.267941 8.678086\nvertex 16.664705 14.500335 8.491524\nvertex 16.212664 14.199250 8.469577\nendloop\nendfacet\nfacet normal -0.536386 0.619208 0.573473\nouter loop\nvertex 16.475306 14.199250 8.901251\nvertex 16.905079 14.500335 8.978137\nvertex 16.756197 14.599973 8.731298\nendloop\nendfacet\nfacet normal -0.499132 0.610628 0.614818\nouter loop\nvertex 16.475306 14.199250 8.901251\nvertex 16.756197 14.599973 8.731298\nvertex 16.284452 14.267941 8.678086\nendloop\nendfacet\nfacet normal 0.266707 0.001315 0.963777\nouter loop\nvertex 26.157015 2.552997 8.262760\nvertex 26.150230 3.802635 8.262934\nvertex 25.414011 3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.264650 -0.000001 0.964345\nouter loop\nvertex 26.157015 2.552997 8.262760\nvertex 25.414011 3.803846 8.466667\nvertex 25.414009 2.554101 8.466667\nendloop\nendfacet\nfacet normal 0.185636 -0.004848 0.982607\nouter loop\nvertex 21.194145 -2.557368 9.374599\nvertex 22.751976 -2.556384 9.080295\nvertex 22.736126 -1.562173 9.088195\nendloop\nendfacet\nfacet normal 0.191110 -0.013657 0.981474\nouter loop\nvertex 21.194145 -2.557368 9.374599\nvertex 22.736126 -1.562173 9.088195\nvertex 21.148577 -1.562913 9.397309\nendloop\nendfacet\nfacet normal 0.191110 -0.013928 0.981470\nouter loop\nvertex 21.148577 -1.562913 9.397309\nvertex 22.736126 -1.562173 9.088195\nvertex 22.697634 -0.738462 9.107379\nendloop\nendfacet\nfacet normal 0.204879 -0.041043 0.977926\nouter loop\nvertex 21.148577 -1.562913 9.397309\nvertex 22.697634 -0.738462 9.107379\nvertex 21.028854 -0.738857 9.456977\nendloop\nendfacet\nfacet normal 0.214909 -0.000543 0.976634\nouter loop\nvertex 22.751976 -2.556384 9.080295\nvertex 24.226292 -2.555258 8.755870\nvertex 24.224312 -1.561327 8.756858\nendloop\nendfacet\nfacet normal 0.217324 -0.004292 0.976090\nouter loop\nvertex 22.751976 -2.556384 9.080295\nvertex 24.224312 -1.561327 8.756858\nvertex 22.736126 -1.562173 9.088195\nendloop\nendfacet\nfacet normal 0.217324 -0.001572 0.976098\nouter loop\nvertex 22.736126 -1.562173 9.088195\nvertex 24.224312 -1.561327 8.756858\nvertex 24.219498 -0.738010 8.759255\nendloop\nendfacet\nfacet normal 0.222975 -0.012281 0.974747\nouter loop\nvertex 22.736126 -1.562173 9.088195\nvertex 24.219498 -0.738010 8.759255\nvertex 22.697634 -0.738462 9.107379\nendloop\nendfacet\nfacet normal 0.135217 -0.001868 0.990814\nouter loop\nvertex 19.769468 -3.808219 9.566667\nvertex 21.200653 -3.807420 9.371354\nvertex 21.194145 -2.557368 9.374599\nendloop\nendfacet\nfacet normal 0.135843 -0.002594 0.990727\nouter loop\nvertex 19.769468 -3.808219 9.566667\nvertex 21.194145 -2.557368 9.374599\nvertex 19.760412 -2.558099 9.571181\nendloop\nendfacet\nfacet normal 0.135833 -0.016398 0.990596\nouter loop\nvertex 19.760412 -2.558099 9.571181\nvertex 21.194145 -2.557368 9.374599\nvertex 21.148577 -1.562913 9.397309\nendloop\nendfacet\nfacet normal 0.140126 -0.022514 0.989878\nouter loop\nvertex 19.760412 -2.558099 9.571181\nvertex 21.148577 -1.562913 9.397309\nvertex 19.697014 -1.563463 9.602778\nendloop\nendfacet\nfacet normal 0.139988 -0.051260 0.988825\nouter loop\nvertex 19.697014 -1.563463 9.602778\nvertex 21.148577 -1.562913 9.397309\nvertex 21.028854 -0.738857 9.456977\nendloop\nendfacet\nfacet normal 0.155681 -0.077323 0.984776\nouter loop\nvertex 19.697014 -1.563463 9.602778\nvertex 21.028854 -0.738857 9.456977\nvertex 19.506817 -0.739151 9.697570\nendloop\nendfacet\nfacet normal 0.155540 -0.088368 0.983869\nouter loop\nvertex 19.506817 -0.739151 9.697570\nvertex 21.028854 -0.738857 9.456977\nvertex 20.833847 0.000000 9.554167\nendloop\nendfacet\nfacet normal 0.219664 -0.209516 0.952812\nouter loop\nvertex 19.506817 -0.739151 9.697570\nvertex 20.833847 0.000000 9.554167\nvertex 18.900000 0.000000 10.000000\nendloop\nendfacet\nfacet normal 0.205006 -0.019935 0.978558\nouter loop\nvertex 21.028854 -0.738857 9.456977\nvertex 22.697634 -0.738462 9.107379\nvertex 22.645555 0.000000 9.133333\nendloop\nendfacet\nfacet normal 0.225734 -0.068252 0.971795\nouter loop\nvertex 21.028854 -0.738857 9.456977\nvertex 22.645555 0.000000 9.133333\nvertex 20.833847 0.000000 9.554167\nendloop\nendfacet\nfacet normal 0.222988 -0.002319 0.974818\nouter loop\nvertex 22.697634 -0.738462 9.107379\nvertex 24.219498 -0.738010 8.759255\nvertex 24.212990 0.000000 8.762500\nendloop\nendfacet\nfacet normal 0.230193 -0.017963 0.972979\nouter loop\nvertex 22.697634 -0.738462 9.107379\nvertex 24.212990 0.000000 8.762500\nvertex 22.645555 0.000000 9.133333\nendloop\nendfacet\nfacet normal 0.237910 0.000000 0.971287\nouter loop\nvertex 24.219498 -0.738010 8.759255\nvertex 25.414009 -0.737545 8.466667\nvertex 25.414011 0.000000 8.466667\nendloop\nendfacet\nfacet normal 0.239169 -0.002159 0.970976\nouter loop\nvertex 24.219498 -0.738010 8.759255\nvertex 25.414011 0.000000 8.466667\nvertex 24.212990 0.000000 8.762500\nendloop\nendfacet\nfacet normal 0.236973 -0.000002 0.971516\nouter loop\nvertex 24.224312 -1.561327 8.756858\nvertex 25.414009 -1.560457 8.466666\nvertex 25.414009 -0.737545 8.466667\nendloop\nendfacet\nfacet normal 0.237910 -0.001437 0.971286\nouter loop\nvertex 24.224312 -1.561327 8.756858\nvertex 25.414009 -0.737545 8.466667\nvertex 24.219498 -0.738010 8.759255\nendloop\nendfacet\nfacet normal 0.236582 0.000001 0.971611\nouter loop\nvertex 24.226292 -2.555258 8.755870\nvertex 25.414009 -2.554101 8.466667\nvertex 25.414009 -1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.236973 -0.000494 0.971516\nouter loop\nvertex 24.226292 -2.555258 8.755870\nvertex 25.414009 -1.560457 8.466666\nvertex 24.224312 -1.561327 8.756858\nendloop\nendfacet\nfacet normal 0.236526 0.000001 0.971625\nouter loop\nvertex 24.226574 -3.805111 8.755730\nvertex 25.414011 -3.803846 8.466667\nvertex 25.414009 -2.554101 8.466667\nendloop\nendfacet\nfacet normal 0.236583 -0.000056 0.971611\nouter loop\nvertex 24.226574 -3.805111 8.755730\nvertex 25.414009 -2.554101 8.466667\nvertex 24.226292 -2.555258 8.755870\nendloop\nendfacet\nfacet normal 0.214560 -0.000062 0.976711\nouter loop\nvertex 22.754240 -3.806343 9.079166\nvertex 24.226574 -3.805111 8.755730\nvertex 24.226292 -2.555258 8.755870\nendloop\nendfacet\nfacet normal 0.214909 -0.000492 0.976634\nouter loop\nvertex 22.754240 -3.806343 9.079166\nvertex 24.226292 -2.555258 8.755870\nvertex 22.751976 -2.556384 9.080295\nendloop\nendfacet\nfacet normal 0.184832 -0.000552 0.982770\nouter loop\nvertex 21.200653 -3.807420 9.371354\nvertex 22.754240 -3.806343 9.079166\nvertex 22.751976 -2.556384 9.080295\nendloop\nendfacet\nfacet normal 0.185636 -0.001584 0.982617\nouter loop\nvertex 21.200653 -3.807420 9.371354\nvertex 22.751976 -2.556384 9.080295\nvertex 21.194145 -2.557368 9.374599\nendloop\nendfacet\nfacet normal -0.111632 -0.027793 0.993361\nouter loop\nvertex 18.613682 -2.558479 9.619390\nvertex 18.568115 -1.563749 9.642101\nvertex 17.717653 -1.563737 9.546528\nendloop\nendfacet\nfacet normal -0.091368 -0.009363 0.995773\nouter loop\nvertex 18.613682 -2.558479 9.619390\nvertex 17.717653 -1.563737 9.546528\nvertex 17.733503 -2.558462 9.538629\nendloop\nendfacet\nfacet normal -0.261688 -0.011834 0.965080\nouter loop\nvertex 17.733503 -2.558462 9.538629\nvertex 17.717653 -1.563737 9.546528\nvertex 17.052727 -1.563401 9.366233\nendloop\nendfacet\nfacet normal -0.247479 -0.001455 0.968892\nouter loop\nvertex 17.733503 -2.558462 9.538629\nvertex 17.052727 -1.563401 9.366233\nvertex 17.054708 -2.558016 9.365246\nendloop\nendfacet\nfacet normal -0.173365 -0.096112 0.980157\nouter loop\nvertex 18.568115 -1.563749 9.642101\nvertex 18.448393 -0.739303 9.701769\nvertex 17.679161 -0.739297 9.565712\nendloop\nendfacet\nfacet normal -0.111632 -0.028326 0.993346\nouter loop\nvertex 18.568115 -1.563749 9.642101\nvertex 17.679161 -0.739297 9.565712\nvertex 17.717653 -1.563737 9.546528\nendloop\nendfacet\nfacet normal -0.297839 -0.036104 0.953933\nouter loop\nvertex 17.717653 -1.563737 9.546528\nvertex 17.679161 -0.739297 9.565712\nvertex 17.047916 -0.739118 9.368630\nendloop\nendfacet\nfacet normal -0.261698 -0.004334 0.965140\nouter loop\nvertex 17.717653 -1.563737 9.546528\nvertex 17.047916 -0.739118 9.368630\nvertex 17.052727 -1.563401 9.366233\nendloop\nendfacet\nfacet normal 0.042005 -0.003304 0.999112\nouter loop\nvertex 19.769468 -3.808219 9.566667\nvertex 19.760412 -2.558099 9.571181\nvertex 18.613682 -2.558479 9.619390\nendloop\nendfacet\nfacet normal 0.043013 -0.002369 0.999072\nouter loop\nvertex 19.769468 -3.808219 9.566667\nvertex 18.613682 -2.558479 9.619390\nvertex 18.620193 -3.808635 9.616146\nendloop\nendfacet\nfacet normal -0.091374 -0.003061 0.995812\nouter loop\nvertex 18.620193 -3.808635 9.616146\nvertex 18.613682 -2.558479 9.619390\nvertex 17.733503 -2.558462 9.538629\nendloop\nendfacet\nfacet normal -0.088572 -0.001059 0.996069\nouter loop\nvertex 18.620193 -3.808635 9.616146\nvertex 17.733503 -2.558462 9.538629\nvertex 17.735767 -3.808617 9.537500\nendloop\nendfacet\nfacet normal -0.247484 -0.001322 0.968891\nouter loop\nvertex 17.735767 -3.808617 9.537500\nvertex 17.733503 -2.558462 9.538629\nvertex 17.054708 -2.558016 9.365246\nendloop\nendfacet\nfacet normal -0.245484 -0.000165 0.969401\nouter loop\nvertex 17.735767 -3.808617 9.537500\nvertex 17.054708 -2.558016 9.365246\nvertex 17.054991 -3.808129 9.365105\nendloop\nendfacet\nfacet normal -0.395828 -0.000193 0.918324\nouter loop\nvertex 17.054991 -3.808129 9.365105\nvertex 17.054708 -2.558016 9.365246\nvertex 16.516666 -2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.395446 0.000000 0.918489\nouter loop\nvertex 17.054991 -3.808129 9.365105\nvertex 16.516666 -2.557108 9.133333\nvertex 16.516666 -3.807135 9.133333\nendloop\nendfacet\nfacet normal -0.398483 -0.001704 0.917174\nouter loop\nvertex 17.054708 -2.558016 9.365246\nvertex 17.052727 -1.563401 9.366233\nvertex 16.516666 -1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.395827 0.000000 0.918325\nouter loop\nvertex 17.054708 -2.558016 9.365246\nvertex 16.516666 -1.562718 9.133333\nvertex 16.516666 -2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.404967 -0.005022 0.914317\nouter loop\nvertex 17.052727 -1.563401 9.366233\nvertex 17.047916 -0.739118 9.368630\nvertex 16.516666 -0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.398481 0.000000 0.917176\nouter loop\nvertex 17.052727 -1.563401 9.366233\nvertex 16.516666 -0.738753 9.133333\nvertex 16.516666 -1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.413823 -0.007640 0.910325\nouter loop\nvertex 17.047916 -0.739118 9.368630\nvertex 17.041407 0.000000 9.371875\nvertex 16.516666 0.000000 9.133333\nendloop\nendfacet\nfacet normal -0.404970 0.000000 0.914330\nouter loop\nvertex 17.047916 -0.739118 9.368630\nvertex 16.516666 0.000000 9.133333\nvertex 16.516666 -0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.350771 -0.057525 0.934693\nouter loop\nvertex 17.679161 -0.739297 9.565712\nvertex 17.627083 0.000000 9.591667\nvertex 17.041407 0.000000 9.371875\nendloop\nendfacet\nfacet normal -0.298019 -0.006815 0.954536\nouter loop\nvertex 17.679161 -0.739297 9.565712\nvertex 17.041407 0.000000 9.371875\nvertex 17.047916 -0.739118 9.368630\nendloop\nendfacet\nfacet normal -0.307649 -0.203345 0.929518\nouter loop\nvertex 18.448393 -0.739303 9.701769\nvertex 18.253386 0.000000 9.798959\nvertex 17.627083 0.000000 9.591667\nendloop\nendfacet\nfacet normal -0.173979 -0.046789 0.983637\nouter loop\nvertex 18.448393 -0.739303 9.701769\nvertex 17.627083 0.000000 9.591667\nvertex 17.679161 -0.739297 9.565712\nendloop\nendfacet\nfacet normal -0.250697 -0.535724 0.806319\nouter loop\nvertex 19.506817 -0.739151 9.697570\nvertex 18.900000 0.000000 10.000000\nvertex 18.253386 0.000000 9.798959\nendloop\nendfacet\nfacet normal 0.003953 -0.129314 0.991596\nouter loop\nvertex 19.506817 -0.739151 9.697570\nvertex 18.253386 0.000000 9.798959\nvertex 18.448393 -0.739303 9.701769\nendloop\nendfacet\nfacet normal 0.003957 -0.113339 0.993548\nouter loop\nvertex 19.697014 -1.563463 9.602778\nvertex 19.506817 -0.739151 9.697570\nvertex 18.448393 -0.739303 9.701769\nendloop\nendfacet\nfacet normal 0.034751 -0.067120 0.997140\nouter loop\nvertex 19.697014 -1.563463 9.602778\nvertex 18.448393 -0.739303 9.701769\nvertex 18.568115 -1.563749 9.642101\nendloop\nendfacet\nfacet normal 0.034805 -0.029516 0.998958\nouter loop\nvertex 19.760412 -2.558099 9.571181\nvertex 19.697014 -1.563463 9.602778\nvertex 18.568115 -1.563749 9.642101\nendloop\nendfacet\nfacet normal 0.042000 -0.020882 0.998899\nouter loop\nvertex 19.760412 -2.558099 9.571181\nvertex 18.568115 -1.563749 9.642101\nvertex 18.613682 -2.558479 9.619390\nendloop\nendfacet\nfacet normal 0.274405 -0.047052 -0.960462\nouter loop\nvertex 26.129168 -11.849633 8.070150\nvertex 26.372263 -11.851037 8.139670\nvertex 26.240326 -12.930573 8.154860\nendloop\nendfacet\nfacet normal 0.288243 -0.045314 -0.956485\nouter loop\nvertex 26.129168 -11.849633 8.070150\nvertex 26.240326 -12.930573 8.154860\nvertex 26.005474 -12.920404 8.083603\nendloop\nendfacet\nfacet normal 0.278988 -0.174332 -0.944338\nouter loop\nvertex 26.005474 -12.920404 8.083603\nvertex 26.240326 -12.930573 8.154860\nvertex 25.882959 -13.725335 8.196007\nendloop\nendfacet\nfacet normal 0.318796 -0.178510 -0.930862\nouter loop\nvertex 26.005474 -12.920404 8.083603\nvertex 25.882959 -13.725335 8.196007\nvertex 25.675266 -13.692222 8.118527\nendloop\nendfacet\nfacet normal 0.458197 -0.040470 0.887929\nouter loop\nvertex 26.372263 -11.851037 8.139670\nvertex 26.129166 -11.849897 8.265168\nvertex 26.005474 -12.920482 8.280198\nendloop\nendfacet\nfacet normal 0.468854 -0.044890 0.882134\nouter loop\nvertex 26.372263 -11.851037 8.139670\nvertex 26.005474 -12.920482 8.280198\nvertex 26.240326 -12.930573 8.154860\nendloop\nendfacet\nfacet normal 0.460435 -0.150400 0.874859\nouter loop\nvertex 26.240326 -12.930573 8.154860\nvertex 26.005474 -12.920482 8.280198\nvertex 25.675266 -13.692232 8.321312\nendloop\nendfacet\nfacet normal 0.487982 -0.175154 0.855099\nouter loop\nvertex 26.240326 -12.930573 8.154860\nvertex 25.675266 -13.692232 8.321312\nvertex 25.882959 -13.725335 8.196007\nendloop\nendfacet\nfacet normal 0.047563 -0.002017 -0.998866\nouter loop\nvertex 25.414011 -10.480907 8.033333\nvertex 26.146835 -10.481279 8.068229\nvertex 26.129168 -11.849633 8.070150\nendloop\nendfacet\nfacet normal 0.047924 -0.001828 -0.998849\nouter loop\nvertex 25.414011 -10.480907 8.033333\nvertex 26.129168 -11.849633 8.070150\nvertex 25.400063 -11.848212 8.035166\nendloop\nendfacet\nfacet normal 0.047885 -0.018078 -0.998689\nouter loop\nvertex 25.400063 -11.848212 8.035166\nvertex 26.129168 -11.849633 8.070150\nvertex 26.005474 -12.920404 8.083603\nendloop\nendfacet\nfacet normal 0.050335 -0.016690 -0.998593\nouter loop\nvertex 25.400063 -11.848212 8.035166\nvertex 26.005474 -12.920404 8.083603\nvertex 25.302427 -12.910231 8.047994\nendloop\nendfacet\nfacet normal 0.049517 -0.066280 -0.996572\nouter loop\nvertex 25.302427 -12.910231 8.047994\nvertex 26.005474 -12.920404 8.083603\nvertex 25.675266 -13.692222 8.118527\nendloop\nendfacet\nfacet normal 0.057660 -0.062379 -0.996386\nouter loop\nvertex 25.302427 -12.910231 8.047994\nvertex 25.675266 -13.692222 8.118527\nvertex 25.061609 -13.654374 8.080646\nendloop\nendfacet\nfacet normal 0.049852 -0.175785 -0.983165\nouter loop\nvertex 25.061609 -13.654374 8.080646\nvertex 25.675266 -13.692222 8.118527\nvertex 25.047661 -14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.095358 -0.176334 -0.979701\nouter loop\nvertex 25.061609 -13.654374 8.080646\nvertex 25.047661 -14.199250 8.177359\nvertex 24.762611 -14.062502 8.125000\nendloop\nendfacet\nfacet normal 0.249862 -0.445005 -0.859965\nouter loop\nvertex 25.675266 -13.692222 8.118527\nvertex 25.882959 -13.725335 8.196007\nvertex 25.190845 -14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.320723 -0.490980 -0.809985\nouter loop\nvertex 25.675266 -13.692222 8.118527\nvertex 25.190845 -14.267941 8.275694\nvertex 25.047661 -14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.428374 -0.392727 0.813794\nouter loop\nvertex 25.882959 -13.725335 8.196007\nvertex 25.675266 -13.692232 8.321312\nvertex 25.047661 -14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.459444 -0.475901 0.749953\nouter loop\nvertex 25.882959 -13.725335 8.196007\nvertex 25.047661 -14.199251 8.407001\nvertex 25.190845 -14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.269544 -0.140295 0.952714\nouter loop\nvertex 25.675266 -13.692232 8.321312\nvertex 25.061607 -13.654394 8.500504\nvertex 24.762611 -14.062502 8.525001\nendloop\nendfacet\nfacet normal 0.290536 -0.201539 0.935399\nouter loop\nvertex 25.675266 -13.692232 8.321312\nvertex 24.762611 -14.062502 8.525001\nvertex 25.047661 -14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.269238 -0.057685 0.961344\nouter loop\nvertex 26.005474 -12.920482 8.280198\nvertex 25.302429 -12.910394 8.477700\nvertex 25.061607 -13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.275863 -0.066949 0.958863\nouter loop\nvertex 26.005474 -12.920482 8.280198\nvertex 25.061607 -13.654394 8.500504\nvertex 25.675266 -13.692232 8.321312\nendloop\nendfacet\nfacet normal 0.268016 -0.015887 0.963283\nouter loop\nvertex 26.129166 -11.849897 8.265168\nvertex 25.400064 -11.848762 8.468046\nvertex 25.302429 -12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.270178 -0.017701 0.962648\nouter loop\nvertex 26.129166 -11.849897 8.265168\nvertex 25.302429 -12.910394 8.477700\nvertex 26.005474 -12.920482 8.280198\nendloop\nendfacet\nfacet normal 0.267745 -0.001759 0.963488\nouter loop\nvertex 26.146837 -10.481909 8.263021\nvertex 25.414009 -10.482211 8.466667\nvertex 25.400064 -11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.268070 -0.001951 0.963397\nouter loop\nvertex 26.146837 -10.481909 8.263021\nvertex 25.400064 -11.848762 8.468046\nvertex 26.129166 -11.849897 8.265168\nendloop\nendfacet\nfacet normal 0.457041 -0.004507 0.889434\nouter loop\nvertex 26.391113 -10.481605 8.137500\nvertex 26.146837 -10.481909 8.263021\nvertex 26.129166 -11.849897 8.265168\nendloop\nendfacet\nfacet normal 0.458701 -0.004906 0.888577\nouter loop\nvertex 26.391113 -10.481605 8.137500\nvertex 26.129166 -11.849897 8.265168\nvertex 26.372263 -11.851037 8.139670\nendloop\nendfacet\nfacet normal 0.272809 -0.005281 -0.962054\nouter loop\nvertex 26.146835 -10.481279 8.068229\nvertex 26.391113 -10.481605 8.137500\nvertex 26.372263 -11.851037 8.139670\nendloop\nendfacet\nfacet normal 0.274929 -0.004899 -0.961452\nouter loop\nvertex 26.146835 -10.481279 8.068229\nvertex 26.372263 -11.851037 8.139670\nvertex 26.129168 -11.849633 8.070150\nendloop\nendfacet\nfacet normal 0.074718 -0.905827 0.417007\nouter loop\nvertex 21.163698 -14.718087 8.937361\nvertex 21.149673 -14.834710 8.686545\nvertex 22.698479 -14.771414 8.546528\nendloop\nendfacet\nfacet normal 0.094174 -0.867630 0.488210\nouter loop\nvertex 21.163698 -14.718087 8.937361\nvertex 22.698479 -14.771414 8.546528\nvertex 22.682304 -14.658746 8.749882\nendloop\nendfacet\nfacet normal 0.156554 -0.858600 0.488157\nouter loop\nvertex 22.682304 -14.658746 8.749882\nvertex 22.698479 -14.771414 8.546528\nvertex 24.096714 -14.599972 8.399652\nendloop\nendfacet\nfacet normal 0.175628 -0.798933 0.575206\nouter loop\nvertex 22.682304 -14.658746 8.749882\nvertex 24.096714 -14.599972 8.399652\nvertex 24.028313 -14.500335 8.558929\nendloop\nendfacet\nfacet normal 0.010635 -0.906013 -0.423115\nouter loop\nvertex 21.149673 -14.834710 8.686545\nvertex 21.130371 -14.718086 8.436337\nvertex 22.672430 -14.658748 8.348035\nendloop\nendfacet\nfacet normal -0.008983 -0.870139 -0.492724\nouter loop\nvertex 21.149673 -14.834710 8.686545\nvertex 22.672430 -14.658748 8.348035\nvertex 22.698479 -14.771414 8.546528\nendloop\nendfacet\nfacet normal 0.067209 -0.863893 -0.499172\nouter loop\nvertex 22.698479 -14.771414 8.546528\nvertex 22.672430 -14.658748 8.348035\nvertex 24.027081 -14.500335 8.256269\nendloop\nendfacet\nfacet normal 0.038324 -0.811775 -0.582711\nouter loop\nvertex 22.698479 -14.771414 8.546528\nvertex 24.027081 -14.500335 8.256269\nvertex 24.096714 -14.599972 8.399652\nendloop\nendfacet\nfacet normal 0.077329 -0.561655 0.823750\nouter loop\nvertex 19.733356 -14.375003 9.305555\nvertex 19.700632 -14.726565 9.068924\nvertex 21.163698 -14.718087 8.937361\nendloop\nendfacet\nfacet normal 0.097537 -0.510328 0.854431\nouter loop\nvertex 19.733356 -14.375003 9.305555\nvertex 21.163698 -14.718087 8.937361\nvertex 21.174864 -14.368311 9.145000\nendloop\nendfacet\nfacet normal 0.125014 -0.509412 0.851394\nouter loop\nvertex 21.174864 -14.368311 9.145000\nvertex 21.163698 -14.718087 8.937361\nvertex 22.682304 -14.658746 8.749882\nendloop\nendfacet\nfacet normal 0.149635 -0.432774 0.888997\nouter loop\nvertex 21.174864 -14.368311 9.145000\nvertex 22.682304 -14.658746 8.749882\nvertex 22.665283 -14.321471 8.916937\nendloop\nendfacet\nfacet normal 0.176210 -0.429746 0.885590\nouter loop\nvertex 22.665283 -14.321471 8.916937\nvertex 22.682304 -14.658746 8.749882\nvertex 24.028313 -14.500335 8.558929\nendloop\nendfacet\nfacet normal 0.195237 -0.347732 0.917041\nouter loop\nvertex 22.665283 -14.321471 8.916937\nvertex 24.028313 -14.500335 8.558929\nvertex 23.949944 -14.205942 8.687243\nendloop\nendfacet\nfacet normal 0.234975 -0.335129 0.912401\nouter loop\nvertex 23.949944 -14.205942 8.687243\nvertex 24.028313 -14.500335 8.558929\nvertex 25.047661 -14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.237569 -0.301556 0.923377\nouter loop\nvertex 23.949944 -14.205942 8.687243\nvertex 25.047661 -14.199251 8.407001\nvertex 24.762611 -14.062502 8.525001\nendloop\nendfacet\nfacet normal 0.294422 -0.748252 0.594504\nouter loop\nvertex 24.028313 -14.500335 8.558929\nvertex 24.096714 -14.599972 8.399652\nvertex 25.190845 -14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.299377 -0.671564 0.677772\nouter loop\nvertex 24.028313 -14.500335 8.558929\nvertex 25.190845 -14.267941 8.275694\nvertex 25.047661 -14.199251 8.407001\nendloop\nendfacet\nfacet normal 0.178012 -0.765464 -0.618366\nouter loop\nvertex 24.096714 -14.599972 8.399652\nvertex 24.027081 -14.500335 8.256269\nvertex 25.047661 -14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.136319 -0.707929 -0.693003\nouter loop\nvertex 24.096714 -14.599972 8.399652\nvertex 25.047661 -14.199250 8.177359\nvertex 25.190845 -14.267941 8.275694\nendloop\nendfacet\nfacet normal 0.035814 -0.341726 -0.939117\nouter loop\nvertex 24.027081 -14.500335 8.256269\nvertex 23.947687 -14.205942 8.146118\nvertex 24.762611 -14.062502 8.125000\nendloop\nendfacet\nfacet normal 0.020907 -0.319184 -0.947462\nouter loop\nvertex 24.027081 -14.500335 8.256269\nvertex 24.762611 -14.062502 8.125000\nvertex 25.047661 -14.199250 8.177359\nendloop\nendfacet\nfacet normal 0.010905 -0.432699 -0.901473\nouter loop\nvertex 22.672430 -14.658748 8.348035\nvertex 22.647228 -14.321472 8.185841\nvertex 23.947687 -14.205942 8.146118\nendloop\nendfacet\nfacet normal -0.021727 -0.355488 -0.934428\nouter loop\nvertex 22.672430 -14.658748 8.348035\nvertex 23.947687 -14.205942 8.146118\nvertex 24.027081 -14.500335 8.256269\nendloop\nendfacet\nfacet normal -0.008821 -0.509649 -0.860337\nouter loop\nvertex 21.130371 -14.718086 8.436337\nvertex 21.113926 -14.368312 8.229306\nvertex 22.647228 -14.321472 8.185841\nendloop\nendfacet\nfacet normal -0.034768 -0.435232 -0.899647\nouter loop\nvertex 21.130371 -14.718086 8.436337\nvertex 22.647228 -14.321472 8.185841\nvertex 22.672430 -14.658748 8.348035\nendloop\nendfacet\nfacet normal -0.014833 -0.559269 -0.828854\nouter loop\nvertex 19.621639 -14.726565 8.497743\nvertex 19.588913 -14.375001 8.261111\nvertex 21.113926 -14.368312 8.229306\nendloop\nendfacet\nfacet normal -0.032112 -0.510214 -0.859448\nouter loop\nvertex 19.621639 -14.726565 8.497743\nvertex 21.113926 -14.368312 8.229306\nvertex 21.130371 -14.718086 8.436337\nendloop\nendfacet\nfacet normal -0.010198 -0.925593 -0.378382\nouter loop\nvertex 19.661137 -14.843751 8.783334\nvertex 19.621639 -14.726565 8.497743\nvertex 21.130371 -14.718086 8.436337\nendloop\nendfacet\nfacet normal -0.021865 -0.906804 -0.420984\nouter loop\nvertex 19.661137 -14.843751 8.783334\nvertex 21.130371 -14.718086 8.436337\nvertex 21.149673 -14.834710 8.686545\nendloop\nendfacet\nfacet normal 0.030065 -0.926179 0.375884\nouter loop\nvertex 19.700632 -14.726565 9.068924\nvertex 19.661137 -14.843751 8.783334\nvertex 21.149673 -14.834710 8.686545\nendloop\nendfacet\nfacet normal 0.042957 -0.906849 0.419261\nouter loop\nvertex 19.700632 -14.726565 9.068924\nvertex 21.149673 -14.834710 8.686545\nvertex 21.163698 -14.718087 8.937361\nendloop\nendfacet\nfacet normal -0.618699 -0.001989 0.785625\nouter loop\nvertex 15.731250 -2.553990 8.604167\nvertex 16.073177 -2.555731 8.873438\nvertex 16.068663 -1.561682 8.872396\nendloop\nendfacet\nfacet normal -0.595026 -0.014885 0.803569\nouter loop\nvertex 15.731250 -2.553990 8.604167\nvertex 16.068663 -1.561682 8.872396\nvertex 15.695139 -1.560369 8.595834\nendloop\nendfacet\nfacet normal -0.595062 -0.000980 0.803679\nouter loop\nvertex 15.695139 -1.560369 8.595834\nvertex 16.068663 -1.561682 8.872396\nvertex 16.066689 -0.738199 8.871941\nendloop\nendfacet\nfacet normal -0.585481 -0.007650 0.810650\nouter loop\nvertex 15.695139 -1.560369 8.595834\nvertex 16.066689 -0.738199 8.871941\nvertex 15.679340 -0.737497 8.592188\nendloop\nendfacet\nfacet normal -0.785302 -0.300087 -0.541525\nouter loop\nvertex 15.436029 -2.794299 8.100622\nvertex 15.767362 -3.799347 8.177083\nvertex 15.635330 -3.801585 8.369792\nendloop\nendfacet\nfacet normal -0.969785 -0.108257 -0.218626\nouter loop\nvertex 15.635330 -3.801585 8.369792\nvertex 15.527050 -2.781158 8.344804\nvertex 15.539762 -2.781838 8.288755\nendloop\nendfacet\nfacet normal -0.873666 -0.043369 0.484590\nouter loop\nvertex 15.635330 -3.801585 8.369792\nvertex 15.539762 -2.781838 8.288755\nvertex 15.436029 -2.794299 8.100622\nendloop\nendfacet\nfacet normal -0.585496 -0.000154 0.810675\nouter loop\nvertex 15.679340 -0.737497 8.592188\nvertex 16.066689 -0.738199 8.871941\nvertex 16.066406 0.000000 8.871875\nendloop\nendfacet\nfacet normal -0.584159 -0.001216 0.811638\nouter loop\nvertex 15.679340 -0.737497 8.592188\nvertex 16.066406 0.000000 8.871875\nvertex 15.677083 0.000000 8.591667\nendloop\nendfacet\nfacet normal -0.502302 0.000000 0.864693\nouter loop\nvertex 16.066689 -0.738199 8.871941\nvertex 16.516666 -0.738753 9.133333\nvertex 16.516666 0.000000 9.133333\nendloop\nendfacet\nfacet normal -0.502158 -0.000114 0.864776\nouter loop\nvertex 16.066689 -0.738199 8.871941\nvertex 16.516666 0.000000 9.133333\nvertex 16.066406 0.000000 8.871875\nendloop\nendfacet\nfacet normal -0.503297 0.000000 0.864113\nouter loop\nvertex 16.068663 -1.561682 8.872396\nvertex 16.516666 -1.562718 9.133333\nvertex 16.516666 -0.738753 9.133333\nendloop\nendfacet\nfacet normal -0.502301 -0.000725 0.864692\nouter loop\nvertex 16.068663 -1.561682 8.872396\nvertex 16.516666 -0.738753 9.133333\nvertex 16.066689 -0.738199 8.871941\nendloop\nendfacet\nfacet normal -0.505600 0.000000 0.862768\nouter loop\nvertex 16.073177 -2.555731 8.873438\nvertex 16.516666 -2.557108 9.133333\nvertex 16.516666 -1.562718 9.133333\nendloop\nendfacet\nfacet normal -0.503299 -0.001380 0.864111\nouter loop\nvertex 16.073177 -2.555731 8.873438\nvertex 16.516666 -1.562718 9.133333\nvertex 16.068663 -1.561682 8.872396\nendloop\nendfacet\nfacet normal -0.507944 0.000000 0.861390\nouter loop\nvertex 16.077690 -3.805630 8.874479\nvertex 16.516666 -3.807135 9.133333\nvertex 16.516666 -2.557108 9.133333\nendloop\nendfacet\nfacet normal -0.505605 -0.001107 0.862764\nouter loop\nvertex 16.077690 -3.805630 8.874479\nvertex 16.516666 -2.557108 9.133333\nvertex 16.073177 -2.555731 8.873438\nendloop\nendfacet\nfacet normal -0.645074 -0.001693 0.764118\nouter loop\nvertex 15.767361 -3.803730 8.612500\nvertex 16.077690 -3.805630 8.874479\nvertex 16.073177 -2.555731 8.873438\nendloop\nendfacet\nfacet normal -0.618684 -0.012638 0.785538\nouter loop\nvertex 15.767361 -3.803730 8.612500\nvertex 16.073177 -2.555731 8.873438\nvertex 15.731250 -2.553990 8.604167\nendloop\nendfacet\nfacet normal -0.875831 -0.081287 0.475723\nouter loop\nvertex 15.527050 -2.781158 8.344804\nvertex 15.635330 -3.801585 8.369792\nvertex 15.767361 -3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.757231 -0.017527 0.652912\nouter loop\nvertex 15.767361 -3.803730 8.612500\nvertex 15.731250 -2.553990 8.604167\nvertex 15.518668 -2.552154 8.357668\nendloop\nendfacet\nfacet normal -0.820034 0.000000 0.572315\nouter loop\nvertex 15.518668 -2.552154 8.357668\nvertex 15.533590 -2.727700 8.357668\nvertex 15.538308 -2.783193 8.357668\nendloop\nendfacet\nfacet normal -0.752865 -0.004612 0.658159\nouter loop\nvertex 15.538308 -2.783193 8.357668\nvertex 15.527050 -2.781158 8.344804\nvertex 15.767361 -3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.870708 -0.074008 0.486199\nouter loop\nvertex 15.767361 -3.803730 8.612500\nvertex 15.518668 -2.552154 8.357668\nvertex 15.538308 -2.783193 8.357668\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364751\nouter loop\nvertex 15.694011 -8.850069 8.383333\nvertex 15.785417 -8.851082 8.616667\nvertex 15.785417 -7.089402 8.616667\nendloop\nendfacet\nfacet normal -0.931106 0.000000 0.364749\nouter loop\nvertex 15.694011 -8.850069 8.383333\nvertex 15.785417 -7.089402 8.616667\nvertex 15.694011 -7.087864 8.383333\nendloop\nendfacet\nfacet normal -0.931107 -0.001101 0.364744\nouter loop\nvertex 15.694011 -7.087864 8.383333\nvertex 15.785417 -7.089402 8.616667\nvertex 15.783160 -5.354500 8.616146\nendloop\nendfacet\nfacet normal -0.925850 -0.003136 0.377877\nouter loop\nvertex 15.694011 -7.087864 8.383333\nvertex 15.783160 -5.354500 8.616146\nvertex 15.687522 -5.352535 8.381836\nendloop\nendfacet\nfacet normal -0.659398 0.000000 0.751794\nouter loop\nvertex 15.785417 -8.851082 8.616667\nvertex 16.079948 -8.851977 8.875000\nvertex 16.079948 -7.090765 8.875000\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 -8.851082 8.616667\nvertex 16.079948 -7.090765 8.875000\nvertex 15.785417 -7.089402 8.616667\nendloop\nendfacet\nfacet normal -0.659397 -0.000080 0.751795\nouter loop\nvertex 15.785417 -7.089402 8.616667\nvertex 16.079948 -7.090765 8.875000\nvertex 16.079666 -5.356243 8.874935\nendloop\nendfacet\nfacet normal -0.657566 -0.000627 0.753396\nouter loop\nvertex 15.785417 -7.089402 8.616667\nvertex 16.079666 -5.356243 8.874935\nvertex 15.783160 -5.354500 8.616146\nendloop\nendfacet\nfacet normal -0.727990 0.000000 -0.685587\nouter loop\nvertex 15.866667 -10.481091 8.200000\nvertex 15.694011 -10.481650 8.383333\nvertex 15.694011 -8.850069 8.383333\nendloop\nendfacet\nfacet normal -0.727986 0.000000 -0.685592\nouter loop\nvertex 15.866667 -10.481091 8.200000\nvertex 15.694011 -8.850069 8.383333\nvertex 15.866667 -8.849014 8.200000\nendloop\nendfacet\nfacet normal -0.727987 0.000000 -0.685591\nouter loop\nvertex 15.866667 -8.849014 8.200000\nvertex 15.694011 -8.850069 8.383333\nvertex 15.694011 -7.087864 8.383333\nendloop\nendfacet\nfacet normal -0.727987 0.000000 -0.685591\nouter loop\nvertex 15.866667 -8.849014 8.200000\nvertex 15.694011 -7.087864 8.383333\nvertex 15.866667 -7.086260 8.200000\nendloop\nendfacet\nfacet normal -0.727966 -0.003314 -0.685605\nouter loop\nvertex 15.866667 -7.086260 8.200000\nvertex 15.694011 -7.087864 8.383333\nvertex 15.687522 -5.352535 8.381836\nendloop\nendfacet\nfacet normal -0.734084 -0.004633 -0.679043\nouter loop\nvertex 15.866667 -7.086260 8.200000\nvertex 15.687522 -5.352535 8.381836\nvertex 15.857639 -5.350487 8.197917\nendloop\nendfacet\nfacet normal -0.733620 -0.029959 -0.678900\nouter loop\nvertex 15.857639 -5.350487 8.197917\nvertex 15.687522 -5.352535 8.381836\nvertex 15.635330 -3.801585 8.369792\nendloop\nendfacet\nfacet normal -0.823380 -0.055509 -0.564769\nouter loop\nvertex 15.857639 -5.350487 8.197917\nvertex 15.635330 -3.801585 8.369792\nvertex 15.767362 -3.799347 8.177083\nendloop\nendfacet\nfacet normal -0.925837 -0.008545 0.377827\nouter loop\nvertex 15.687522 -5.352535 8.381836\nvertex 15.783160 -5.354500 8.616146\nvertex 15.767361 -3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.878237 -0.025846 0.477526\nouter loop\nvertex 15.687522 -5.352535 8.381836\nvertex 15.767361 -3.803730 8.612500\nvertex 15.635330 -3.801585 8.369792\nendloop\nendfacet\nfacet normal -0.657567 -0.000617 0.753395\nouter loop\nvertex 15.783160 -5.354500 8.616146\nvertex 16.079666 -5.356243 8.874935\nvertex 16.077690 -3.805630 8.874479\nendloop\nendfacet\nfacet normal -0.645081 -0.004776 0.764099\nouter loop\nvertex 15.783160 -5.354500 8.616146\nvertex 16.077690 -3.805630 8.874479\nvertex 15.767361 -3.803730 8.612500\nendloop\nendfacet\nfacet normal -0.508979 0.000000 0.860779\nouter loop\nvertex 16.079666 -5.356243 8.874935\nvertex 16.516666 -5.357624 9.133333\nvertex 16.516666 -3.807135 9.133333\nendloop\nendfacet\nfacet normal -0.507942 -0.000393 0.861391\nouter loop\nvertex 16.079666 -5.356243 8.874935\nvertex 16.516666 -3.807135 9.133333\nvertex 16.077690 -3.805630 8.874479\nendloop\nendfacet\nfacet normal -0.509126 0.000000 0.860692\nouter loop\nvertex 16.079948 -7.090765 8.875000\nvertex 16.516666 -7.091847 9.133333\nvertex 16.516666 -5.357624 9.133333\nendloop\nendfacet\nfacet normal -0.508979 -0.000051 0.860779\nouter loop\nvertex 16.079948 -7.090765 8.875000\nvertex 16.516666 -5.357624 9.133333\nvertex 16.079666 -5.356243 8.874935\nendloop\nendfacet\nfacet normal -0.509127 0.000000 0.860691\nouter loop\nvertex 16.079948 -8.851977 8.875000\nvertex 16.516666 -8.852689 9.133333\nvertex 16.516666 -7.091847 9.133333\nendloop\nendfacet\nfacet normal -0.509128 0.000000 0.860691\nouter loop\nvertex 16.079948 -8.851977 8.875000\nvertex 16.516666 -7.091847 9.133333\nvertex 16.079948 -7.090765 8.875000\nendloop\nendfacet\nfacet normal -0.509128 0.000000 0.860691\nouter loop\nvertex 16.079948 -10.482659 8.875000\nvertex 16.516666 -10.483034 9.133333\nvertex 16.516666 -8.852689 9.133333\nendloop\nendfacet\nfacet normal -0.509127 0.000000 0.860691\nouter loop\nvertex 16.079948 -10.482659 8.875000\nvertex 16.516666 -8.852689 9.133333\nvertex 16.079948 -8.851977 8.875000\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 -10.482183 8.616667\nvertex 16.079948 -10.482659 8.875000\nvertex 16.079948 -8.851977 8.875000\nendloop\nendfacet\nfacet normal -0.659397 0.000000 0.751795\nouter loop\nvertex 15.785417 -10.482183 8.616667\nvertex 16.079948 -8.851977 8.875000\nvertex 15.785417 -8.851082 8.616667\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364750\nouter loop\nvertex 15.694011 -10.481650 8.383333\nvertex 15.785417 -10.482183 8.616667\nvertex 15.785417 -8.851082 8.616667\nendloop\nendfacet\nfacet normal -0.931105 0.000000 0.364750\nouter loop\nvertex 15.694011 -10.481650 8.383333\nvertex 15.785417 -8.851082 8.616667\nvertex 15.694011 -8.850069 8.383333\nendloop\nendfacet\nfacet normal 0.184832 0.000001 0.982770\nouter loop\nvertex 21.200653 -8.852824 9.371354\nvertex 22.754240 -8.852315 9.079167\nvertex 22.754240 -7.091278 9.079166\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200653 -8.852824 9.371354\nvertex 22.754240 -7.091278 9.079166\nvertex 21.200655 -7.092052 9.371354\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200655 -7.092052 9.371354\nvertex 22.754240 -7.091278 9.079166\nvertex 22.754240 -5.356898 9.079166\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200655 -7.092052 9.371354\nvertex 22.754240 -5.356898 9.079166\nvertex 21.200653 -5.357885 9.371354\nendloop\nendfacet\nfacet normal 0.214560 0.000001 0.976711\nouter loop\nvertex 22.754240 -8.852315 9.079167\nvertex 24.226576 -8.851733 8.755730\nvertex 24.226576 -7.090393 8.755729\nendloop\nendfacet\nfacet normal 0.214559 0.000000 0.976711\nouter loop\nvertex 22.754240 -8.852315 9.079167\nvertex 24.226576 -7.090393 8.755729\nvertex 22.754240 -7.091278 9.079166\nendloop\nendfacet\nfacet normal 0.214560 -0.000001 0.976711\nouter loop\nvertex 22.754240 -7.091278 9.079166\nvertex 24.226576 -7.090393 8.755729\nvertex 24.226576 -5.355767 8.755730\nendloop\nendfacet\nfacet normal 0.214560 0.000000 0.976711\nouter loop\nvertex 22.754240 -7.091278 9.079166\nvertex 24.226576 -5.355767 8.755730\nvertex 22.754240 -5.356898 9.079166\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 -10.483306 9.566667\nvertex 21.200653 -10.483106 9.371354\nvertex 21.200653 -8.852824 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 -10.483306 9.566667\nvertex 21.200653 -8.852824 9.371354\nvertex 19.769468 -8.853203 9.566667\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 -8.853203 9.566667\nvertex 21.200653 -8.852824 9.371354\nvertex 21.200655 -7.092052 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 -8.853203 9.566667\nvertex 21.200655 -7.092052 9.371354\nvertex 19.769468 -7.092627 9.566667\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 -7.092627 9.566667\nvertex 21.200655 -7.092052 9.371354\nvertex 21.200653 -5.357885 9.371354\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 -7.092627 9.566667\nvertex 21.200653 -5.357885 9.371354\nvertex 19.769468 -5.358619 9.566667\nendloop\nendfacet\nfacet normal 0.135216 0.000000 0.990816\nouter loop\nvertex 19.769468 -5.358619 9.566667\nvertex 21.200653 -5.357885 9.371354\nvertex 21.200653 -3.807420 9.371354\nendloop\nendfacet\nfacet normal 0.135215 0.000000 0.990816\nouter loop\nvertex 19.769468 -5.358619 9.566667\nvertex 21.200653 -3.807420 9.371354\nvertex 19.769468 -3.808219 9.566667\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200653 -5.357885 9.371354\nvertex 22.754240 -5.356898 9.079166\nvertex 22.754240 -3.806343 9.079166\nendloop\nendfacet\nfacet normal 0.184833 0.000000 0.982770\nouter loop\nvertex 21.200653 -5.357885 9.371354\nvertex 22.754240 -3.806343 9.079166\nvertex 21.200653 -3.807420 9.371354\nendloop\nendfacet\nfacet normal 0.214559 0.000001 0.976711\nouter loop\nvertex 22.754240 -5.356898 9.079166\nvertex 24.226576 -5.355767 8.755730\nvertex 24.226574 -3.805111 8.755730\nendloop\nendfacet\nfacet normal 0.214560 0.000000 0.976711\nouter loop\nvertex 22.754240 -5.356898 9.079166\nvertex 24.226574 -3.805111 8.755730\nvertex 22.754240 -3.806343 9.079166\nendloop\nendfacet\nfacet normal 0.236527 -0.000000 0.971625\nouter loop\nvertex 24.226576 -5.355767 8.755730\nvertex 25.414009 -5.354605 8.466666\nvertex 25.414011 -3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.236528 0.000000 0.971625\nouter loop\nvertex 24.226576 -5.355767 8.755730\nvertex 25.414011 -3.803846 8.466667\nvertex 24.226574 -3.805111 8.755730\nendloop\nendfacet\nfacet normal 0.236525 0.000001 0.971625\nouter loop\nvertex 24.226576 -7.090393 8.755729\nvertex 25.414009 -7.089484 8.466667\nvertex 25.414009 -5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.236529 -0.000001 0.971625\nouter loop\nvertex 24.226576 -7.090393 8.755729\nvertex 25.414009 -5.354605 8.466666\nvertex 24.226576 -5.355767 8.755730\nendloop\nendfacet\nfacet normal 0.236527 -0.000000 0.971625\nouter loop\nvertex 24.226576 -8.851733 8.755730\nvertex 25.414009 -8.851135 8.466666\nvertex 25.414009 -7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.236526 0.000000 0.971625\nouter loop\nvertex 24.226576 -8.851733 8.755730\nvertex 25.414009 -7.089484 8.466667\nvertex 24.226576 -7.090393 8.755729\nendloop\nendfacet\nfacet normal 0.236527 0.000000 0.971625\nouter loop\nvertex 24.226574 -10.482530 8.755730\nvertex 25.414009 -10.482211 8.466667\nvertex 25.414009 -8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.236527 -0.000000 0.971625\nouter loop\nvertex 24.226574 -10.482530 8.755730\nvertex 25.414009 -8.851135 8.466666\nvertex 24.226576 -8.851733 8.755730\nendloop\nendfacet\nfacet normal 0.214560 -0.000001 0.976711\nouter loop\nvertex 22.754240 -10.482836 9.079166\nvertex 24.226574 -10.482530 8.755730\nvertex 24.226576 -8.851733 8.755730\nendloop\nendfacet\nfacet normal 0.214560 -0.000000 0.976711\nouter loop\nvertex 22.754240 -10.482836 9.079166\nvertex 24.226576 -8.851733 8.755730\nvertex 22.754240 -8.852315 9.079167\nendloop\nendfacet\nfacet normal 0.184833 -0.000001 0.982770\nouter loop\nvertex 21.200653 -10.483106 9.371354\nvertex 22.754240 -10.482836 9.079166\nvertex 22.754240 -8.852315 9.079167\nendloop\nendfacet\nfacet normal 0.184832 0.000000 0.982770\nouter loop\nvertex 21.200653 -10.483106 9.371354\nvertex 22.754240 -8.852315 9.079167\nvertex 21.200653 -8.852824 9.371354\nendloop\nendfacet\nfacet normal 0.002254 0.000000 -0.999997\nouter loop\nvertex 21.109249 -8.846521 8.000521\nvertex 21.109247 -7.082470 8.000521\nvertex 22.727156 -7.083351 8.004167\nendloop\nendfacet\nfacet normal 0.002253 0.000000 -0.999997\nouter loop\nvertex 21.109249 -8.846521 8.000521\nvertex 22.727156 -7.083351 8.004167\nvertex 22.727156 -8.847102 8.004167\nendloop\nendfacet\nfacet normal 0.006614 0.000000 -0.999978\nouter loop\nvertex 22.727156 -8.847102 8.004167\nvertex 22.727156 -7.083351 8.004167\nvertex 24.223190 -7.084518 8.014062\nendloop\nendfacet\nfacet normal 0.006615 0.000000 -0.999978\nouter loop\nvertex 22.727156 -8.847102 8.004167\nvertex 24.223190 -7.084518 8.014062\nvertex 24.223190 -8.847869 8.014062\nendloop\nendfacet\nfacet normal 0.002202 -0.000007 -0.999998\nouter loop\nvertex 21.109247 -7.082470 8.000521\nvertex 21.109673 -5.345647 8.000510\nvertex 22.730549 -5.346774 8.004080\nendloop\nendfacet\nfacet normal 0.002254 -0.000054 -0.999997\nouter loop\nvertex 21.109247 -7.082470 8.000521\nvertex 22.730549 -5.346774 8.004080\nvertex 22.727156 -7.083351 8.004167\nendloop\nendfacet\nfacet normal 0.006477 -0.000063 -0.999979\nouter loop\nvertex 22.727156 -7.083351 8.004167\nvertex 22.730549 -5.346774 8.004080\nvertex 24.232944 -5.348269 8.013813\nendloop\nendfacet\nfacet normal 0.006614 -0.000181 -0.999978\nouter loop\nvertex 22.727156 -7.083351 8.004167\nvertex 24.232944 -5.348269 8.013813\nvertex 24.223190 -7.084518 8.014062\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 -10.479649 8.000000\nvertex 19.552803 -8.846289 8.000000\nvertex 21.109249 -8.846521 8.000521\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 -10.479649 8.000000\nvertex 21.109249 -8.846521 8.000521\nvertex 21.109249 -10.479773 8.000521\nendloop\nendfacet\nfacet normal 0.002254 0.000000 -0.999997\nouter loop\nvertex 21.109249 -10.479773 8.000521\nvertex 21.109249 -8.846521 8.000521\nvertex 22.727156 -8.847102 8.004167\nendloop\nendfacet\nfacet normal 0.002252 0.000000 -0.999997\nouter loop\nvertex 21.109249 -10.479773 8.000521\nvertex 22.727156 -8.847102 8.004167\nvertex 22.727158 -10.480080 8.004167\nendloop\nendfacet\nfacet normal 0.006615 0.000000 -0.999978\nouter loop\nvertex 22.727158 -10.480080 8.004167\nvertex 22.727156 -8.847102 8.004167\nvertex 24.223190 -8.847869 8.014062\nendloop\nendfacet\nfacet normal 0.006614 0.000000 -0.999978\nouter loop\nvertex 22.727158 -10.480080 8.004167\nvertex 24.223190 -8.847869 8.014062\nvertex 24.223190 -10.480485 8.014062\nendloop\nendfacet\nfacet normal 0.016180 0.000000 -0.999869\nouter loop\nvertex 24.223190 -10.480485 8.014062\nvertex 24.223190 -8.847869 8.014062\nvertex 25.414009 -8.848668 8.033333\nendloop\nendfacet\nfacet normal 0.016182 0.000000 -0.999869\nouter loop\nvertex 24.223190 -10.480485 8.014062\nvertex 25.414009 -8.848668 8.033333\nvertex 25.414011 -10.480907 8.033333\nendloop\nendfacet\nfacet normal 0.016180 0.000000 -0.999869\nouter loop\nvertex 24.223190 -8.847869 8.014062\nvertex 24.223190 -7.084518 8.014062\nvertex 25.414009 -7.085731 8.033333\nendloop\nendfacet\nfacet normal 0.016181 0.000000 -0.999869\nouter loop\nvertex 24.223190 -8.847869 8.014062\nvertex 25.414009 -7.085731 8.033333\nvertex 25.414009 -8.848668 8.033333\nendloop\nendfacet\nfacet normal 0.016046 -0.000234 -0.999871\nouter loop\nvertex 24.223190 -7.084518 8.014062\nvertex 24.232944 -5.348269 8.013813\nvertex 25.427582 -5.349819 8.032986\nendloop\nendfacet\nfacet normal 0.016182 -0.000326 -0.999869\nouter loop\nvertex 24.223190 -7.084518 8.014062\nvertex 25.427582 -5.349819 8.032986\nvertex 25.414009 -7.085731 8.033333\nendloop\nendfacet\nfacet normal 0.014140 -0.002009 -0.999898\nouter loop\nvertex 24.232944 -5.348269 8.013813\nvertex 24.311401 -3.796976 8.011806\nvertex 25.563290 -3.798691 8.029513\nendloop\nendfacet\nfacet normal 0.016042 -0.003642 -0.999865\nouter loop\nvertex 24.232944 -5.348269 8.013813\nvertex 25.563290 -3.798691 8.029513\nvertex 25.427582 -5.349819 8.032986\nendloop\nendfacet\nfacet normal 0.005350 -0.000473 -0.999986\nouter loop\nvertex 22.730549 -5.346774 8.004080\nvertex 22.754299 -3.795325 8.003472\nvertex 24.311401 -3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.006478 -0.001622 -0.999978\nouter loop\nvertex 22.730549 -5.346774 8.004080\nvertex 24.311401 -3.796976 8.011806\nvertex 24.232944 -5.348269 8.013813\nendloop\nendfacet\nfacet normal 0.001851 -0.000053 -0.999998\nouter loop\nvertex 21.109673 -5.345647 8.000510\nvertex 21.112640 -3.794090 8.000434\nvertex 22.754299 -3.795325 8.003472\nendloop\nendfacet\nfacet normal 0.002203 -0.000425 -0.999997\nouter loop\nvertex 21.109673 -5.345647 8.000510\nvertex 22.754299 -3.795325 8.003472\nvertex 22.730549 -5.346774 8.004080\nendloop\nendfacet\nfacet normal 0.000279 0.000000 -1.000000\nouter loop\nvertex 19.552801 -5.345193 8.000000\nvertex 19.552803 -3.793593 8.000000\nvertex 21.112640 -3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.000327 -0.000050 -1.000000\nouter loop\nvertex 19.552801 -5.345193 8.000000\nvertex 21.112640 -3.794090 8.000434\nvertex 21.109673 -5.345647 8.000510\nendloop\nendfacet\nfacet normal 0.000328 0.000000 -1.000000\nouter loop\nvertex 19.552803 -7.082114 8.000000\nvertex 19.552801 -5.345193 8.000000\nvertex 21.109673 -5.345647 8.000510\nendloop\nendfacet\nfacet normal 0.000334 -0.000006 -1.000000\nouter loop\nvertex 19.552803 -7.082114 8.000000\nvertex 21.109673 -5.345647 8.000510\nvertex 21.109247 -7.082470 8.000521\nendloop\nendfacet\nfacet normal 0.000335 0.000000 -1.000000\nouter loop\nvertex 19.552803 -8.846289 8.000000\nvertex 19.552803 -7.082114 8.000000\nvertex 21.109247 -7.082470 8.000521\nendloop\nendfacet\nfacet normal 0.000334 0.000000 -1.000000\nouter loop\nvertex 19.552803 -8.846289 8.000000\nvertex 21.109247 -7.082470 8.000521\nvertex 21.109249 -8.846521 8.000521\nendloop\nendfacet\nfacet normal -0.000779 -0.081272 -0.996692\nouter loop\nvertex 21.108089 -13.782950 8.097133\nvertex 21.108513 -12.949333 8.029158\nvertex 22.706612 -12.940510 8.027189\nendloop\nendfacet\nfacet normal -0.008823 -0.066099 -0.997774\nouter loop\nvertex 21.108089 -13.782950 8.097133\nvertex 22.706612 -12.940510 8.027189\nvertex 22.668369 -13.756055 8.081554\nendloop\nendfacet\nfacet normal 0.003973 -0.066698 -0.997765\nouter loop\nvertex 22.668369 -13.756055 8.081554\nvertex 22.706612 -12.940510 8.027189\nvertex 24.159176 -12.921573 8.031707\nendloop\nendfacet\nfacet normal -0.004329 -0.051922 -0.998642\nouter loop\nvertex 22.668369 -13.756055 8.081554\nvertex 24.159176 -12.921573 8.031707\nvertex 24.034252 -13.696052 8.072515\nendloop\nendfacet\nfacet normal 0.001837 -0.022844 -0.999737\nouter loop\nvertex 21.108513 -12.949333 8.029158\nvertex 21.109156 -11.852637 8.004100\nvertex 22.724588 -11.851659 8.007044\nendloop\nendfacet\nfacet normal -0.001129 -0.018480 -0.999829\nouter loop\nvertex 21.108513 -12.949333 8.029158\nvertex 22.724588 -11.851659 8.007044\nvertex 22.706612 -12.940510 8.027189\nendloop\nendfacet\nfacet normal 0.006215 -0.018601 -0.999808\nouter loop\nvertex 22.706612 -12.940510 8.027189\nvertex 22.724588 -11.851659 8.007044\nvertex 24.215187 -11.849457 8.016268\nendloop\nendfacet\nfacet normal 0.003299 -0.014571 -0.999888\nouter loop\nvertex 22.706612 -12.940510 8.027189\nvertex 24.215187 -11.849457 8.016268\nvertex 24.159176 -12.921573 8.031707\nendloop\nendfacet\nfacet normal -0.007570 -0.248826 -0.968519\nouter loop\nvertex 19.588913 -14.375001 8.261111\nvertex 19.568035 -13.786793 8.110156\nvertex 21.108089 -13.782950 8.097133\nendloop\nendfacet\nfacet normal -0.019371 -0.220396 -0.975218\nouter loop\nvertex 19.588913 -14.375001 8.261111\nvertex 21.108089 -13.782950 8.097133\nvertex 21.113926 -14.368312 8.229306\nendloop\nendfacet\nfacet normal -0.005942 -0.220306 -0.975413\nouter loop\nvertex 21.113926 -14.368312 8.229306\nvertex 21.108089 -13.782950 8.097133\nvertex 22.668369 -13.756055 8.081554\nendloop\nendfacet\nfacet normal -0.022359 -0.180528 -0.983316\nouter loop\nvertex 21.113926 -14.368312 8.229306\nvertex 22.668369 -13.756055 8.081554\nvertex 22.647228 -14.321472 8.185841\nendloop\nendfacet\nfacet normal 0.001462 -0.181435 -0.983402\nouter loop\nvertex 22.647228 -14.321472 8.185841\nvertex 22.668369 -13.756055 8.081554\nvertex 24.034252 -13.696052 8.072515\nendloop\nendfacet\nfacet normal -0.017813 -0.139884 -0.990008\nouter loop\nvertex 22.647228 -14.321472 8.185841\nvertex 24.034252 -13.696052 8.072515\nvertex 23.947687 -14.205942 8.146118\nendloop\nendfacet\nfacet normal 0.013719 -0.145136 -0.989317\nouter loop\nvertex 23.947687 -14.205942 8.146118\nvertex 24.034252 -13.696052 8.072515\nvertex 25.061609 -13.654374 8.080646\nendloop\nendfacet\nfacet normal -0.007751 -0.102426 -0.994711\nouter loop\nvertex 23.947687 -14.205942 8.146118\nvertex 25.061609 -13.654374 8.080646\nvertex 24.762611 -14.062502 8.125000\nendloop\nendfacet\nfacet normal 0.014770 -0.054988 -0.998378\nouter loop\nvertex 24.034252 -13.696052 8.072515\nvertex 24.159176 -12.921573 8.031707\nvertex 25.302427 -12.910231 8.047994\nendloop\nendfacet\nfacet normal 0.009810 -0.047003 -0.998847\nouter loop\nvertex 24.034252 -13.696052 8.072515\nvertex 25.302427 -12.910231 8.047994\nvertex 25.061609 -13.654374 8.080646\nendloop\nendfacet\nfacet normal 0.015961 -0.015231 -0.999757\nouter loop\nvertex 24.159176 -12.921573 8.031707\nvertex 24.215187 -11.849457 8.016268\nvertex 25.400063 -11.848212 8.035166\nendloop\nendfacet\nfacet normal 0.014378 -0.013398 -0.999807\nouter loop\nvertex 24.159176 -12.921573 8.031707\nvertex 25.400063 -11.848212 8.035166\nvertex 25.302427 -12.910231 8.047994\nendloop\nendfacet\nfacet normal 0.016180 -0.001706 -0.999868\nouter loop\nvertex 24.215187 -11.849457 8.016268\nvertex 24.223190 -10.480485 8.014062\nvertex 25.414011 -10.480907 8.033333\nendloop\nendfacet\nfacet normal 0.015950 -0.001503 -0.999872\nouter loop\nvertex 24.215187 -11.849457 8.016268\nvertex 25.414011 -10.480907 8.033333\nvertex 25.400063 -11.848212 8.035166\nendloop\nendfacet\nfacet normal 0.006613 -0.002110 -0.999976\nouter loop\nvertex 22.724588 -11.851659 8.007044\nvertex 22.727158 -10.480080 8.004167\nvertex 24.223190 -10.480485 8.014062\nendloop\nendfacet\nfacet normal 0.006190 -0.001647 -0.999980\nouter loop\nvertex 22.724588 -11.851659 8.007044\nvertex 24.223190 -10.480485 8.014062\nvertex 24.215187 -11.849457 8.016268\nendloop\nendfacet\nfacet normal 0.002254 -0.002607 -0.999994\nouter loop\nvertex 21.109156 -11.852637 8.004100\nvertex 21.109249 -10.479773 8.000521\nvertex 22.727158 -10.480080 8.004167\nendloop\nendfacet\nfacet normal 0.001824 -0.002101 -0.999996\nouter loop\nvertex 21.109156 -11.852637 8.004100\nvertex 22.727158 -10.480080 8.004167\nvertex 22.724588 -11.851659 8.007044\nendloop\nendfacet\nfacet normal 0.000335 -0.002971 -0.999996\nouter loop\nvertex 19.553366 -11.852744 8.004080\nvertex 19.552803 -10.479649 8.000000\nvertex 21.109249 -10.479773 8.000521\nendloop\nendfacet\nfacet normal 0.000012 -0.002607 -0.999997\nouter loop\nvertex 19.553366 -11.852744 8.004080\nvertex 21.109249 -10.479773 8.000521\nvertex 21.109156 -11.852637 8.004100\nendloop\nendfacet\nfacet normal 0.000016 -0.026005 -0.999662\nouter loop\nvertex 19.557316 -12.950583 8.032639\nvertex 19.553366 -11.852744 8.004080\nvertex 21.109156 -11.852637 8.004100\nendloop\nendfacet\nfacet normal -0.002227 -0.022841 -0.999737\nouter loop\nvertex 19.557316 -12.950583 8.032639\nvertex 21.109156 -11.852637 8.004100\nvertex 21.108513 -12.949333 8.029158\nendloop\nendfacet\nfacet normal -0.002161 -0.092332 -0.995726\nouter loop\nvertex 19.568035 -13.786793 8.110156\nvertex 19.557316 -12.950583 8.032639\nvertex 21.108513 -12.949333 8.029158\nendloop\nendfacet\nfacet normal -0.008225 -0.081266 -0.996659\nouter loop\nvertex 19.568035 -13.786793 8.110156\nvertex 21.108513 -12.949333 8.029158\nvertex 21.108089 -13.782950 8.097133\nendloop\nendfacet\nfacet normal 0.171458 -0.063177 0.983164\nouter loop\nvertex 21.186642 -13.783004 9.276489\nvertex 22.691643 -13.756097 9.015754\nvertex 22.732565 -12.940852 9.061005\nendloop\nendfacet\nfacet normal 0.180586 -0.080679 0.980245\nouter loop\nvertex 21.186642 -13.783004 9.276489\nvertex 22.732565 -12.940852 9.061005\nvertex 21.196112 -12.949749 9.343325\nendloop\nendfacet\nfacet normal 0.180792 -0.017514 0.983365\nouter loop\nvertex 21.196112 -12.949749 9.343325\nvertex 22.732565 -12.940852 9.061005\nvertex 22.751530 -11.852822 9.076897\nendloop\nendfacet\nfacet normal 0.184294 -0.022663 0.982610\nouter loop\nvertex 21.196112 -12.949749 9.343325\nvertex 22.751530 -11.852822 9.076897\nvertex 21.200087 -11.854041 9.367850\nendloop\nendfacet\nfacet normal 0.202004 -0.047845 0.978215\nouter loop\nvertex 22.691643 -13.756097 9.015754\nvertex 24.037163 -13.696084 8.740838\nvertex 24.162418 -12.921827 8.752842\nendloop\nendfacet\nfacet normal 0.211063 -0.064731 0.975327\nouter loop\nvertex 22.691643 -13.756097 9.015754\nvertex 24.162418 -12.921827 8.752842\nvertex 22.732565 -12.940852 9.061005\nendloop\nendfacet\nfacet normal 0.210835 -0.013350 0.977430\nouter loop\nvertex 22.732565 -12.940852 9.061005\nvertex 24.162418 -12.921827 8.752842\nvertex 24.218555 -11.850319 8.755368\nendloop\nendfacet\nfacet normal 0.214084 -0.017997 0.976649\nouter loop\nvertex 22.732565 -12.940852 9.061005\nvertex 24.218555 -11.850319 8.755368\nvertex 22.751530 -11.852822 9.076897\nendloop\nendfacet\nfacet normal 0.108992 -0.219970 0.969399\nouter loop\nvertex 19.733356 -14.375003 9.305555\nvertex 21.174864 -14.368311 9.145000\nvertex 21.186642 -13.783004 9.276489\nendloop\nendfacet\nfacet normal 0.121374 -0.250804 0.960399\nouter loop\nvertex 19.733356 -14.375003 9.305555\nvertex 21.186642 -13.783004 9.276489\nvertex 19.754234 -13.786851 9.456511\nendloop\nendfacet\nfacet normal 0.124502 -0.080737 0.988929\nouter loop\nvertex 19.754234 -13.786851 9.456511\nvertex 21.186642 -13.783004 9.276489\nvertex 21.196112 -12.949749 9.343325\nendloop\nendfacet\nfacet normal 0.131593 -0.093219 0.986911\nouter loop\nvertex 19.754234 -13.786851 9.456511\nvertex 21.196112 -12.949749 9.343325\nvertex 19.764956 -12.951040 9.534028\nendloop\nendfacet\nfacet normal 0.132070 -0.022661 0.990981\nouter loop\nvertex 19.764956 -12.951040 9.534028\nvertex 21.196112 -12.949749 9.343325\nvertex 21.200087 -11.854041 9.367850\nendloop\nendfacet\nfacet normal 0.134783 -0.026278 0.990527\nouter loop\nvertex 19.764956 -12.951040 9.534028\nvertex 21.200087 -11.854041 9.367850\nvertex 19.768904 -11.854286 9.562587\nendloop\nendfacet\nfacet normal 0.134824 -0.002588 0.990866\nouter loop\nvertex 19.768904 -11.854286 9.562587\nvertex 21.200087 -11.854041 9.367850\nvertex 21.200653 -10.483106 9.371354\nendloop\nendfacet\nfacet normal 0.135215 -0.003004 0.990812\nouter loop\nvertex 19.768904 -11.854286 9.562587\nvertex 21.200653 -10.483106 9.371354\nvertex 19.769468 -10.483306 9.566667\nendloop\nendfacet\nfacet normal 0.184326 -0.001993 0.982863\nouter loop\nvertex 21.200087 -11.854041 9.367850\nvertex 22.751530 -11.852822 9.076897\nvertex 22.754240 -10.482836 9.079166\nendloop\nendfacet\nfacet normal 0.184832 -0.002589 0.982767\nouter loop\nvertex 21.200087 -11.854041 9.367850\nvertex 22.754240 -10.482836 9.079166\nvertex 21.200653 -10.483106 9.371354\nendloop\nendfacet\nfacet normal 0.214092 -0.001513 0.976812\nouter loop\nvertex 22.751530 -11.852822 9.076897\nvertex 24.218555 -11.850319 8.755368\nvertex 24.226574 -10.482530 8.755730\nendloop\nendfacet\nfacet normal 0.214560 -0.002042 0.976709\nouter loop\nvertex 22.751530 -11.852822 9.076897\nvertex 24.226574 -10.482530 8.755730\nvertex 22.754240 -10.482836 9.079166\nendloop\nendfacet\nfacet normal 0.236297 -0.001430 0.971680\nouter loop\nvertex 24.218555 -11.850319 8.755368\nvertex 25.400064 -11.848762 8.468046\nvertex 25.414009 -10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.236527 -0.001643 0.971624\nouter loop\nvertex 24.218555 -11.850319 8.755368\nvertex 25.414009 -10.482211 8.466667\nvertex 24.226574 -10.482530 8.755730\nendloop\nendfacet\nfacet normal 0.234715 -0.012748 0.971981\nouter loop\nvertex 24.162418 -12.921827 8.752842\nvertex 25.302429 -12.910394 8.477700\nvertex 25.400064 -11.848762 8.468046\nendloop\nendfacet\nfacet normal 0.236288 -0.014670 0.971572\nouter loop\nvertex 24.162418 -12.921827 8.752842\nvertex 25.400064 -11.848762 8.468046\nvertex 24.218555 -11.850319 8.755368\nendloop\nendfacet\nfacet normal 0.229893 -0.044615 0.972193\nouter loop\nvertex 24.037163 -13.696084 8.740838\nvertex 25.061607 -13.654394 8.500504\nvertex 25.302429 -12.910394 8.477700\nendloop\nendfacet\nfacet normal 0.234786 -0.053031 0.970600\nouter loop\nvertex 24.037163 -13.696084 8.740838\nvertex 25.302429 -12.910394 8.477700\nvertex 24.162418 -12.921827 8.752842\nendloop\nendfacet\nfacet normal 0.211196 -0.096345 0.972684\nouter loop\nvertex 23.949944 -14.205942 8.687243\nvertex 24.762611 -14.062502 8.525001\nvertex 25.061607 -13.654394 8.500504\nendloop\nendfacet\nfacet normal 0.231550 -0.140794 0.962581\nouter loop\nvertex 23.949944 -14.205942 8.687243\nvertex 25.061607 -13.654394 8.500504\nvertex 24.037163 -13.696084 8.740838\nendloop\nendfacet\nfacet normal 0.186093 -0.134147 0.973331\nouter loop\nvertex 22.665283 -14.321471 8.916937\nvertex 23.949944 -14.205942 8.687243\nvertex 24.037163 -13.696084 8.740838\nendloop\nendfacet\nfacet normal 0.204599 -0.177777 0.962567\nouter loop\nvertex 22.665283 -14.321471 8.916937\nvertex 24.037163 -13.696084 8.740838\nvertex 22.691643 -13.756097 9.015754\nendloop\nendfacet\nfacet normal 0.154304 -0.177086 0.972024\nouter loop\nvertex 21.174864 -14.368311 9.145000\nvertex 22.665283 -14.321471 8.916937\nvertex 22.691643 -13.756097 9.015754\nendloop\nendfacet\nfacet normal 0.170355 -0.219245 0.960682\nouter loop\nvertex 21.174864 -14.368311 9.145000\nvertex 22.691643 -13.756097 9.015754\nvertex 21.186642 -13.783004 9.276489\nendloop\nendfacet\nfacet normal -0.942867 -0.169688 0.286718\nouter loop\nvertex 15.926517 -13.692226 8.431500\nvertex 15.996692 -13.725345 8.642670\nvertex 15.848109 -12.930644 8.624383\nendloop\nendfacet\nfacet normal -0.925336 -0.179809 0.333800\nouter loop\nvertex 15.926517 -13.692226 8.431500\nvertex 15.848109 -12.930644 8.624383\nvertex 15.764791 -12.920452 8.398901\nendloop\nendfacet\nfacet normal -0.937705 -0.045501 0.344440\nouter loop\nvertex 15.764791 -12.920452 8.398901\nvertex 15.848109 -12.930644 8.624383\nvertex 15.793253 -11.851281 8.617631\nendloop\nendfacet\nfacet normal -0.930933 -0.049248 0.361855\nouter loop\nvertex 15.764791 -12.920452 8.398901\nvertex 15.793253 -11.851281 8.617631\nvertex 15.702858 -11.849790 8.385280\nendloop\nendfacet\nfacet normal -0.680988 -0.098469 0.725644\nouter loop\nvertex 15.996692 -13.725345 8.642670\nvertex 16.239573 -13.692245 8.875096\nvertex 16.126717 -12.920577 8.873900\nendloop\nendfacet\nfacet normal -0.661215 -0.106536 0.742593\nouter loop\nvertex 15.996692 -13.725345 8.642670\nvertex 16.126717 -12.920577 8.873900\nvertex 15.848109 -12.930644 8.624383\nendloop\nendfacet\nfacet normal -0.666398 -0.026147 0.745138\nouter loop\nvertex 15.848109 -12.930644 8.624383\nvertex 16.126717 -12.920577 8.873900\nvertex 16.085794 -11.850214 8.874863\nendloop\nendfacet\nfacet normal -0.659997 -0.028847 0.750714\nouter loop\nvertex 15.848109 -12.930644 8.624383\nvertex 16.085794 -11.850214 8.874863\nvertex 15.793253 -11.851281 8.617631\nendloop\nendfacet\nfacet normal -0.679728 -0.428326 -0.595404\nouter loop\nvertex 16.245834 -14.062501 8.333333\nvertex 16.212664 -14.199250 8.469577\nvertex 15.926517 -13.692226 8.431500\nendloop\nendfacet\nfacet normal -0.638856 -0.372476 -0.673145\nouter loop\nvertex 16.245834 -14.062501 8.333333\nvertex 15.926517 -13.692226 8.431500\nvertex 16.073439 -13.654376 8.271119\nendloop\nendfacet\nfacet normal -0.704649 -0.176686 -0.687205\nouter loop\nvertex 16.073439 -13.654376 8.271119\nvertex 15.926517 -13.692226 8.431500\nvertex 15.764791 -12.920452 8.398901\nendloop\nendfacet\nfacet normal -0.708344 -0.179013 -0.682791\nouter loop\nvertex 16.073439 -13.654376 8.271119\nvertex 15.764791 -12.920452 8.398901\nvertex 15.932369 -12.910254 8.222376\nendloop\nendfacet\nfacet normal -0.722856 -0.050581 -0.689144\nouter loop\nvertex 15.932369 -12.910254 8.222376\nvertex 15.764791 -12.920452 8.398901\nvertex 15.702858 -11.849790 8.385280\nendloop\nendfacet\nfacet normal -0.726457 -0.051960 -0.685245\nouter loop\nvertex 15.932369 -12.910254 8.222376\nvertex 15.702858 -11.849790 8.385280\nvertex 15.874880 -11.848289 8.202797\nendloop\nendfacet\nfacet normal -0.727620 -0.005683 -0.685957\nouter loop\nvertex 15.874880 -11.848289 8.202797\nvertex 15.702858 -11.849790 8.385280\nvertex 15.694011 -10.481650 8.383333\nendloop\nendfacet\nfacet normal -0.727964 -0.005775 -0.685591\nouter loop\nvertex 15.874880 -11.848289 8.202797\nvertex 15.694011 -10.481650 8.383333\nvertex 15.866667 -10.481091 8.200000\nendloop\nendfacet\nfacet normal -0.931956 -0.005079 0.362536\nouter loop\nvertex 15.702858 -11.849790 8.385280\nvertex 15.793253 -11.851281 8.617631\nvertex 15.785417 -10.482183 8.616667\nendloop\nendfacet\nfacet normal -0.931095 -0.005502 0.364735\nouter loop\nvertex 15.702858 -11.849790 8.385280\nvertex 15.785417 -10.482183 8.616667\nvertex 15.694011 -10.481650 8.383333\nendloop\nendfacet\nfacet normal -0.660322 -0.002898 0.750977\nouter loop\nvertex 15.793253 -11.851281 8.617631\nvertex 16.085794 -11.850214 8.874863\nvertex 16.079948 -10.482659 8.875000\nendloop\nendfacet\nfacet normal -0.659395 -0.003245 0.751790\nouter loop\nvertex 15.793253 -11.851281 8.617631\nvertex 16.079948 -10.482659 8.875000\nvertex 15.785417 -10.482183 8.616667\nendloop\nendfacet\nfacet normal -0.509449 -0.002124 0.860498\nouter loop\nvertex 16.085794 -11.850214 8.874863\nvertex 16.520052 -11.849110 9.131964\nvertex 16.516666 -10.483034 9.133333\nendloop\nendfacet\nfacet normal -0.509129 -0.002264 0.860687\nouter loop\nvertex 16.085794 -11.850214 8.874863\nvertex 16.516666 -10.483034 9.133333\nvertex 16.079948 -10.482659 8.875000\nendloop\nendfacet\nfacet normal -0.511418 -0.019182 0.859118\nouter loop\nvertex 16.126717 -12.920577 8.873900\nvertex 16.543751 -12.910495 9.122376\nvertex 16.520052 -11.849110 9.131964\nendloop\nendfacet\nfacet normal -0.509309 -0.020245 0.860346\nouter loop\nvertex 16.126717 -12.920577 8.873900\nvertex 16.520052 -11.849110 9.131964\nvertex 16.085794 -11.850214 8.874863\nendloop\nendfacet\nfacet normal -0.516933 -0.068762 0.853260\nouter loop\nvertex 16.239573 -13.692245 8.875096\nvertex 16.602932 -13.654407 9.098280\nvertex 16.543751 -12.910495 9.122376\nendloop\nendfacet\nfacet normal -0.509175 -0.073137 0.857550\nouter loop\nvertex 16.239573 -13.692245 8.875096\nvertex 16.543751 -12.910495 9.122376\nvertex 16.126717 -12.920577 8.873900\nendloop\nendfacet\nfacet normal -0.551613 -0.166355 0.817343\nouter loop\nvertex 16.475306 -14.199250 8.901251\nvertex 16.679167 -14.062502 9.066667\nvertex 16.602932 -13.654407 9.098280\nendloop\nendfacet\nfacet normal -0.499636 -0.188695 0.845433\nouter loop\nvertex 16.475306 -14.199250 8.901251\nvertex 16.602932 -13.654407 9.098280\nvertex 16.239573 -13.692245 8.875096\nendloop\nendfacet\nfacet normal -0.684012 -0.283353 0.672190\nouter loop\nvertex 16.284452 -14.267941 8.678086\nvertex 16.475306 -14.199250 8.901251\nvertex 16.239573 -13.692245 8.875096\nendloop\nendfacet\nfacet normal -0.639902 -0.292996 0.710408\nouter loop\nvertex 16.284452 -14.267941 8.678086\nvertex 16.239573 -13.692245 8.875096\nvertex 15.996692 -13.725345 8.642670\nendloop\nendfacet\nfacet normal -0.877249 -0.455323 0.152037\nouter loop\nvertex 16.212664 -14.199250 8.469577\nvertex 16.284452 -14.267941 8.678086\nvertex 15.996692 -13.725345 8.642670\nendloop\nendfacet\nfacet normal -0.857875 -0.468253 0.211637\nouter loop\nvertex 16.212664 -14.199250 8.469577\nvertex 15.996692 -13.725345 8.642670\nvertex 15.926517 -13.692226 8.431500\nendloop\nendfacet\nfacet normal 0.280158 -0.000596 -0.959954\nouter loop\nvertex 26.156590 -5.351182 8.067980\nvertex 26.394505 -5.352378 8.137413\nvertex 26.391111 -7.087739 8.137500\nendloop\nendfacet\nfacet normal 0.272812 -0.001670 -0.962066\nouter loop\nvertex 26.156590 -5.351182 8.067980\nvertex 26.391111 -7.087739 8.137500\nvertex 26.146835 -7.086800 8.068229\nendloop\nendfacet\nfacet normal 0.272818 0.000000 -0.962066\nouter loop\nvertex 26.146835 -7.086800 8.068229\nvertex 26.391111 -7.087739 8.137500\nvertex 26.391111 -8.849988 8.137500\nendloop\nendfacet\nfacet normal 0.272823 0.000000 -0.962064\nouter loop\nvertex 26.146835 -7.086800 8.068229\nvertex 26.391111 -8.849988 8.137500\nvertex 26.146837 -8.849369 8.068229\nendloop\nendfacet\nfacet normal 0.452912 -0.000105 0.891555\nouter loop\nvertex 26.394505 -5.352378 8.137413\nvertex 26.147263 -5.353491 8.263010\nvertex 26.146837 -7.088612 8.263021\nendloop\nendfacet\nfacet normal 0.457040 -0.000850 0.889446\nouter loop\nvertex 26.394505 -5.352378 8.137413\nvertex 26.146837 -7.088612 8.263021\nvertex 26.391111 -7.087739 8.137500\nendloop\nendfacet\nfacet normal 0.457042 0.000000 0.889445\nouter loop\nvertex 26.391111 -7.087739 8.137500\nvertex 26.146837 -7.088612 8.263021\nvertex 26.146837 -8.850560 8.263021\nendloop\nendfacet\nfacet normal 0.457043 0.000000 0.889445\nouter loop\nvertex 26.391111 -7.087739 8.137500\nvertex 26.146837 -8.850560 8.263021\nvertex 26.391111 -8.849988 8.137500\nendloop\nendfacet\nfacet normal 0.054188 -0.004033 -0.998523\nouter loop\nvertex 25.563290 -3.798691 8.029513\nvertex 26.235046 -3.800150 8.065972\nvertex 26.156590 -5.351182 8.067980\nendloop\nendfacet\nfacet normal 0.047932 -0.006430 -0.998830\nouter loop\nvertex 25.563290 -3.798691 8.029513\nvertex 26.156590 -5.351182 8.067980\nvertex 25.427582 -5.349819 8.032986\nendloop\nendfacet\nfacet normal 0.047943 -0.000413 -0.998850\nouter loop\nvertex 25.427582 -5.349819 8.032986\nvertex 26.156590 -5.351182 8.067980\nvertex 26.146835 -7.086800 8.068229\nendloop\nendfacet\nfacet normal 0.047565 -0.000572 -0.998868\nouter loop\nvertex 25.427582 -5.349819 8.032986\nvertex 26.146835 -7.086800 8.068229\nvertex 25.414009 -7.085731 8.033333\nendloop\nendfacet\nfacet normal 0.047563 0.000000 -0.998868\nouter loop\nvertex 25.414009 -7.085731 8.033333\nvertex 26.146835 -7.086800 8.068229\nvertex 26.146837 -8.849369 8.068229\nendloop\nendfacet\nfacet normal 0.047566 0.000000 -0.998868\nouter loop\nvertex 25.414009 -7.085731 8.033333\nvertex 26.146837 -8.849369 8.068229\nvertex 25.414009 -8.848668 8.033333\nendloop\nendfacet\nfacet normal 0.047563 0.000000 -0.998868\nouter loop\nvertex 25.414009 -8.848668 8.033333\nvertex 26.146837 -8.849369 8.068229\nvertex 26.146835 -10.481279 8.068229\nendloop\nendfacet\nfacet normal 0.047565 0.000000 -0.998868\nouter loop\nvertex 25.414009 -8.848668 8.033333\nvertex 26.146835 -10.481279 8.068229\nvertex 25.414011 -10.480907 8.033333\nendloop\nendfacet\nfacet normal 0.272821 0.000000 -0.962065\nouter loop\nvertex 26.146837 -8.849369 8.068229\nvertex 26.391111 -8.849988 8.137500\nvertex 26.391113 -10.481605 8.137500\nendloop\nendfacet\nfacet normal 0.272819 0.000000 -0.962065\nouter loop\nvertex 26.146837 -8.849369 8.068229\nvertex 26.391113 -10.481605 8.137500\nvertex 26.146835 -10.481279 8.068229\nendloop\nendfacet\nfacet normal 0.457041 0.000000 0.889446\nouter loop\nvertex 26.391111 -8.849988 8.137500\nvertex 26.146837 -8.850560 8.263021\nvertex 26.146837 -10.481909 8.263021\nendloop\nendfacet\nfacet normal 0.457041 0.000000 0.889446\nouter loop\nvertex 26.391111 -8.849988 8.137500\nvertex 26.146837 -10.481909 8.263021\nvertex 26.391113 -10.481605 8.137500\nendloop\nendfacet\nfacet normal 0.267747 0.000000 0.963489\nouter loop\nvertex 26.146837 -8.850560 8.263021\nvertex 25.414009 -8.851135 8.466666\nvertex 25.414009 -10.482211 8.466667\nendloop\nendfacet\nfacet normal 0.267744 0.000000 0.963490\nouter loop\nvertex 26.146837 -8.850560 8.263021\nvertex 25.414009 -10.482211 8.466667\nvertex 26.146837 -10.481909 8.263021\nendloop\nendfacet\nfacet normal 0.267747 -0.000000 0.963489\nouter loop\nvertex 26.146837 -7.088612 8.263021\nvertex 25.414009 -7.089484 8.466667\nvertex 25.414009 -8.851135 8.466666\nendloop\nendfacet\nfacet normal 0.267745 0.000000 0.963490\nouter loop\nvertex 26.146837 -7.088612 8.263021\nvertex 25.414009 -8.851135 8.466666\nvertex 26.146837 -8.850560 8.263021\nendloop\nendfacet\nfacet normal 0.267615 0.000001 0.963526\nouter loop\nvertex 26.147263 -5.353491 8.263010\nvertex 25.414009 -5.354605 8.466666\nvertex 25.414009 -7.089484 8.466667\nendloop\nendfacet\nfacet normal 0.267745 -0.000061 0.963490\nouter loop\nvertex 26.147263 -5.353491 8.263010\nvertex 25.414009 -7.089484 8.466667\nvertex 26.146837 -7.088612 8.263021\nendloop\nendfacet\nfacet normal 0.266708 -0.000000 0.963777\nouter loop\nvertex 26.150230 -3.802635 8.262934\nvertex 25.414011 -3.803846 8.466667\nvertex 25.414009 -5.354605 8.466666\nendloop\nendfacet\nfacet normal 0.267612 -0.000465 0.963526\nouter loop\nvertex 26.150230 -3.802635 8.262934\nvertex 25.414009 -5.354605 8.466666\nvertex 26.147263 -5.353491 8.263010\nendloop\nendfacet\nfacet normal 0.425800 -0.000771 0.904817\nouter loop\nvertex 26.418255 -3.801430 8.136806\nvertex 26.150230 -3.802635 8.262934\nvertex 26.147263 -5.353491 8.263010\nendloop\nendfacet\nfacet normal 0.452912 -0.006587 0.891531\nouter loop\nvertex 26.418255 -3.801430 8.136806\nvertex 26.147263 -5.353491 8.263010\nvertex 26.394505 -5.352378 8.137413\nendloop\nendfacet\nfacet normal 0.360580 -0.005887 -0.932710\nouter loop\nvertex 26.235046 -3.800150 8.065972\nvertex 26.418255 -3.801430 8.136806\nvertex 26.394505 -5.352378 8.137413\nendloop\nendfacet\nfacet normal 0.280041 -0.015408 -0.959864\nouter loop\nvertex 26.235046 -3.800150 8.065972\nvertex 26.394505 -5.352378 8.137413\nvertex 26.156590 -5.351182 8.067980\nendloop\nendfacet\nfacet normal 0.000279 0.000002 -1.000000\nouter loop\nvertex 21.112640 -3.794090 8.000434\nvertex 19.552803 -3.793593 8.000000\nvertex 19.549599 -3.205483 8.000000\nendloop\nendfacet\nfacet normal 0.000277 -0.000139 -1.000000\nouter loop\nvertex 20.747240 -3.260331 8.000258\nvertex 21.113426 -3.276976 8.000362\nvertex 21.112640 -3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.000208 -0.000187 -1.000000\nouter loop\nvertex 19.549599 -3.205483 8.000000\nvertex 20.747240 -3.260331 8.000258\nvertex 21.112640 -3.794090 8.000434\nendloop\nendfacet\nfacet normal 0.001571 -0.000141 -0.999999\nouter loop\nvertex 21.112640 -3.794090 8.000434\nvertex 21.113426 -3.276976 8.000362\nvertex 22.772945 -3.352415 8.002979\nendloop\nendfacet\nfacet normal 0.001849 -0.001191 -0.999997\nouter loop\nvertex 21.112640 -3.794090 8.000434\nvertex 22.772945 -3.352415 8.002979\nvertex 22.754299 -3.795325 8.003472\nendloop\nendfacet\nfacet normal 0.005351 -0.001338 -0.999985\nouter loop\nvertex 24.311401 -3.796976 8.011806\nvertex 22.754299 -3.795325 8.003472\nvertex 22.772945 -3.352415 8.002979\nendloop\nendfacet\nfacet normal 0.003892 -0.004703 -0.999981\nouter loop\nvertex 23.345116 -3.377946 8.006075\nvertex 24.391867 -3.292191 8.009745\nvertex 24.311401 -3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.005347 -0.001337 -0.999985\nouter loop\nvertex 22.772945 -3.352415 8.002979\nvertex 23.345116 -3.377946 8.006075\nvertex 24.311401 -3.796976 8.011806\nendloop\nendfacet\nfacet normal 0.014136 -0.006335 -0.999880\nouter loop\nvertex 25.563290 -3.798691 8.029513\nvertex 24.311401 -3.796976 8.011806\nvertex 24.391867 -3.292191 8.009745\nendloop\nendfacet\nfacet normal 0.004140 -0.014740 -0.999883\nouter loop\nvertex 25.696550 -3.224265 8.021599\nvertex 25.854183 -3.211885 8.022071\nvertex 25.563290 -3.798691 8.029513\nendloop\nendfacet\nfacet normal 0.009923 -0.016077 -0.999822\nouter loop\nvertex 24.391867 -3.292191 8.009745\nvertex 25.696550 -3.224265 8.021599\nvertex 25.563290 -3.798691 8.029513\nendloop\nendfacet\nfacet normal -0.226513 -0.080775 0.970653\nouter loop\nvertex 17.072617 -13.696096 9.291351\nvertex 17.714960 -13.756108 9.436255\nvertex 17.730688 -12.940925 9.507764\nendloop\nendfacet\nfacet normal -0.239839 -0.068515 0.968392\nouter loop\nvertex 17.072617 -13.696096 9.291351\nvertex 17.730688 -12.940925 9.507764\nvertex 17.062820 -12.921923 9.343699\nendloop\nendfacet\nfacet normal -0.239097 -0.022242 0.970741\nouter loop\nvertex 17.062820 -12.921923 9.343699\nvertex 17.730688 -12.940925 9.507764\nvertex 17.735132 -11.853064 9.533783\nendloop\nendfacet\nfacet normal -0.244656 -0.018514 0.969433\nouter loop\nvertex 17.062820 -12.921923 9.343699\nvertex 17.735132 -11.853064 9.533783\nvertex 17.055969 -11.850637 9.362429\nendloop\nendfacet\nfacet normal -0.078599 -0.092845 0.992573\nouter loop\nvertex 17.714960 -13.756108 9.436255\nvertex 18.594265 -13.783009 9.503368\nvertex 18.612646 -12.949788 9.582764\nendloop\nendfacet\nfacet normal -0.085274 -0.085436 0.992688\nouter loop\nvertex 17.714960 -13.756108 9.436255\nvertex 18.612646 -12.949788 9.582764\nvertex 17.730688 -12.940925 9.507764\nendloop\nendfacet\nfacet normal -0.084963 -0.026042 0.996044\nouter loop\nvertex 17.730688 -12.940925 9.507764\nvertex 18.612646 -12.949788 9.582764\nvertex 18.619249 -11.854171 9.611973\nendloop\nendfacet\nfacet normal -0.088100 -0.023458 0.995835\nouter loop\nvertex 17.730688 -12.940925 9.507764\nvertex 18.619249 -11.854171 9.611973\nvertex 17.735132 -11.853064 9.533783\nendloop\nendfacet\nfacet normal -0.356462 -0.179492 0.916906\nouter loop\nvertex 16.679167 -14.062502 9.066667\nvertex 17.038143 -14.205942 9.178142\nvertex 17.072617 -13.696096 9.291351\nendloop\nendfacet\nfacet normal -0.387115 -0.142882 0.910893\nouter loop\nvertex 16.679167 -14.062502 9.066667\nvertex 17.072617 -13.696096 9.291351\nvertex 16.602932 -13.654407 9.098280\nendloop\nendfacet\nfacet normal -0.384431 -0.067120 0.920710\nouter loop\nvertex 16.602932 -13.654407 9.098280\nvertex 17.072617 -13.696096 9.291351\nvertex 17.062820 -12.921923 9.343699\nendloop\nendfacet\nfacet normal -0.392621 -0.060960 0.917678\nouter loop\nvertex 16.602932 -13.654407 9.098280\nvertex 17.062820 -12.921923 9.343699\nvertex 16.543751 -12.910495 9.122376\nendloop\nendfacet\nfacet normal -0.392498 -0.018588 0.919565\nouter loop\nvertex 16.543751 -12.910495 9.122376\nvertex 17.062820 -12.921923 9.343699\nvertex 17.055969 -11.850637 9.362429\nendloop\nendfacet\nfacet normal -0.395039 -0.017117 0.918505\nouter loop\nvertex 16.543751 -12.910495 9.122376\nvertex 17.055969 -11.850637 9.362429\nvertex 16.520052 -11.849110 9.131964\nendloop\nendfacet\nfacet normal -0.395063 -0.002080 0.918652\nouter loop\nvertex 16.520052 -11.849110 9.131964\nvertex 17.055969 -11.850637 9.362429\nvertex 17.054993 -10.483283 9.365105\nendloop\nendfacet\nfacet normal -0.395447 -0.001900 0.918487\nouter loop\nvertex 16.520052 -11.849110 9.131964\nvertex 17.054993 -10.483283 9.365105\nvertex 16.516666 -10.483034 9.133333\nendloop\nendfacet\nfacet normal -0.244643 -0.002518 0.969610\nouter loop\nvertex 17.055969 -11.850637 9.362429\nvertex 17.735132 -11.853064 9.533783\nvertex 17.735767 -10.483404 9.537500\nendloop\nendfacet\nfacet normal -0.245485 -0.002073 0.969398\nouter loop\nvertex 17.055969 -11.850637 9.362429\nvertex 17.735767 -10.483404 9.537500\nvertex 17.054993 -10.483283 9.365105\nendloop\nendfacet\nfacet normal -0.088099 -0.002972 0.996107\nouter loop\nvertex 17.735132 -11.853064 9.533783\nvertex 18.619249 -11.854171 9.611973\nvertex 18.620193 -10.483410 9.616146\nendloop\nendfacet\nfacet normal -0.088573 -0.002662 0.996066\nouter loop\nvertex 17.735132 -11.853064 9.533783\nvertex 18.620193 -10.483410 9.616146\nvertex 17.735767 -10.483404 9.537500\nendloop\nendfacet\nfacet normal 0.042916 -0.002991 0.999074\nouter loop\nvertex 18.619249 -11.854171 9.611973\nvertex 19.768904 -11.854286 9.562587\nvertex 19.769468 -10.483306 9.566667\nendloop\nendfacet\nfacet normal 0.043015 -0.003071 0.999070\nouter loop\nvertex 18.619249 -11.854171 9.611973\nvertex 19.769468 -10.483306 9.566667\nvertex 18.620193 -10.483410 9.616146\nendloop\nendfacet\nfacet normal 0.042213 -0.026159 0.998766\nouter loop\nvertex 18.612646 -12.949788 9.582764\nvertex 19.764956 -12.951040 9.534028\nvertex 19.768904 -11.854286 9.562587\nendloop\nendfacet\nfacet normal 0.042899 -0.026884 0.998718\nouter loop\nvertex 18.612646 -12.949788 9.582764\nvertex 19.768904 -11.854286 9.562587\nvertex 18.619249 -11.854171 9.611973\nendloop\nendfacet\nfacet normal 0.039880 -0.092783 0.994887\nouter loop\nvertex 18.594265 -13.783009 9.503368\nvertex 19.754234 -13.786851 9.456511\nvertex 19.764956 -12.951040 9.534028\nendloop\nendfacet\nfacet normal 0.041959 -0.095692 0.994526\nouter loop\nvertex 18.594265 -13.783009 9.503368\nvertex 19.764956 -12.951040 9.534028\nvertex 18.612646 -12.949788 9.582764\nendloop\nendfacet\nfacet normal 0.033635 -0.249582 0.967769\nouter loop\nvertex 18.556152 -14.368310 9.348197\nvertex 19.733356 -14.375003 9.305555\nvertex 19.754234 -13.786851 9.456511\nendloop\nendfacet\nfacet normal 0.038138 -0.258394 0.965287\nouter loop\nvertex 18.556152 -14.368310 9.348197\nvertex 19.754234 -13.786851 9.456511\nvertex 18.594265 -13.783009 9.503368\nendloop\nendfacet\nfacet normal -0.073570 -0.251088 0.965164\nouter loop\nvertex 17.665802 -14.321471 9.292516\nvertex 18.556152 -14.368310 9.348197\nvertex 18.594265 -13.783009 9.503368\nendloop\nendfacet\nfacet normal -0.081163 -0.238954 0.967633\nouter loop\nvertex 17.665802 -14.321471 9.292516\nvertex 18.594265 -13.783009 9.503368\nvertex 17.714960 -13.756108 9.436255\nendloop\nendfacet\nfacet normal -0.214355 -0.223125 0.950930\nouter loop\nvertex 17.038143 -14.205942 9.178142\nvertex 17.665802 -14.321471 9.292516\nvertex 17.714960 -13.756108 9.436255\nendloop\nendfacet\nfacet normal -0.233162 -0.195746 0.952533\nouter loop\nvertex 17.038143 -14.205942 9.178142\nvertex 17.714960 -13.756108 9.436255\nvertex 17.072617 -13.696096 9.291351\nendloop\nendfacet\nfacet normal -0.074129 -0.092546 -0.992945\nouter loop\nvertex 16.490507 -13.696053 8.177488\nvertex 16.396286 -12.921580 8.112339\nvertex 17.162565 -12.940511 8.056896\nendloop\nendfacet\nfacet normal -0.070047 -0.096169 -0.992897\nouter loop\nvertex 16.490507 -13.696053 8.177488\nvertex 17.162565 -12.940511 8.056896\nvertex 17.211208 -13.756058 8.132457\nendloop\nendfacet\nfacet normal -0.019650 -0.093399 -0.995435\nouter loop\nvertex 17.211208 -13.756058 8.132457\nvertex 17.162565 -12.940511 8.056896\nvertex 18.223684 -12.949332 8.036777\nendloop\nendfacet\nfacet normal -0.017663 -0.095869 -0.995237\nouter loop\nvertex 17.211208 -13.756058 8.132457\nvertex 18.223684 -12.949332 8.036777\nvertex 18.246180 -13.782951 8.116679\nendloop\nendfacet\nfacet normal -0.074728 -0.025524 -0.996877\nouter loop\nvertex 16.396286 -12.921580 8.112339\nvertex 16.356508 -11.849483 8.087871\nvertex 17.142763 -11.851664 8.028987\nendloop\nendfacet\nfacet normal -0.072800 -0.026879 -0.996984\nouter loop\nvertex 16.396286 -12.921580 8.112339\nvertex 17.142763 -11.851664 8.028987\nvertex 17.162565 -12.940511 8.056896\nendloop\nendfacet\nfacet normal -0.020208 -0.025985 -0.999458\nouter loop\nvertex 17.162565 -12.940511 8.056896\nvertex 17.142763 -11.851664 8.028987\nvertex 18.215160 -11.852634 8.007331\nendloop\nendfacet\nfacet normal -0.019174 -0.026985 -0.999452\nouter loop\nvertex 17.162565 -12.940511 8.056896\nvertex 18.215160 -11.852634 8.007331\nvertex 18.223684 -12.949332 8.036777\nendloop\nendfacet\nfacet normal -0.235532 -0.242939 -0.941013\nouter loop\nvertex 16.245834 -14.062501 8.333333\nvertex 16.073439 -13.654376 8.271119\nvertex 16.490507 -13.696053 8.177488\nendloop\nendfacet\nfacet normal -0.199719 -0.267532 -0.942623\nouter loop\nvertex 16.245834 -14.062501 8.333333\nvertex 16.490507 -13.696053 8.177488\nvertex 16.597235 -14.205941 8.299591\nendloop\nendfacet\nfacet normal -0.080975 -0.248118 -0.965340\nouter loop\nvertex 16.597235 -14.205941 8.299591\nvertex 16.490507 -13.696053 8.177488\nvertex 17.211208 -13.756058 8.132457\nendloop\nendfacet\nfacet normal -0.073220 -0.257975 -0.963373\nouter loop\nvertex 16.597235 -14.205941 8.299591\nvertex 17.211208 -13.756058 8.132457\nvertex 17.280115 -14.321469 8.278626\nendloop\nendfacet\nfacet normal -0.021312 -0.252667 -0.967319\nouter loop\nvertex 17.280115 -14.321469 8.278626\nvertex 17.211208 -13.756058 8.132457\nvertex 18.246180 -13.782951 8.116679\nendloop\nendfacet\nfacet normal -0.018209 -0.257842 -0.966015\nouter loop\nvertex 17.280115 -14.321469 8.278626\nvertex 18.246180 -13.782951 8.116679\nvertex 18.286760 -14.368312 8.272155\nendloop\nendfacet\nfacet normal -0.005515 -0.257059 -0.966380\nouter loop\nvertex 18.286760 -14.368312 8.272155\nvertex 18.246180 -13.782951 8.116679\nvertex 19.568035 -13.786793 8.110156\nendloop\nendfacet\nfacet normal -0.009492 -0.248886 -0.968486\nouter loop\nvertex 18.286760 -14.368312 8.272155\nvertex 19.568035 -13.786793 8.110156\nvertex 19.588913 -14.375001 8.261111\nendloop\nendfacet\nfacet normal -0.003178 -0.095497 -0.995425\nouter loop\nvertex 18.246180 -13.782951 8.116679\nvertex 18.223684 -12.949332 8.036777\nvertex 19.557316 -12.950583 8.032639\nendloop\nendfacet\nfacet normal -0.005183 -0.092370 -0.995711\nouter loop\nvertex 18.246180 -13.782951 8.116679\nvertex 19.557316 -12.950583 8.032639\nvertex 19.568035 -13.786793 8.110156\nendloop\nendfacet\nfacet normal -0.002431 -0.026859 -0.999636\nouter loop\nvertex 18.223684 -12.949332 8.036777\nvertex 18.215160 -11.852634 8.007331\nvertex 19.553366 -11.852744 8.004080\nendloop\nendfacet\nfacet normal -0.003128 -0.026016 -0.999657\nouter loop\nvertex 18.223684 -12.949332 8.036777\nvertex 19.553366 -11.852744 8.004080\nvertex 19.557316 -12.950583 8.032639\nendloop\nendfacet\nfacet normal -0.002333 -0.003066 -0.999993\nouter loop\nvertex 18.215160 -11.852634 8.007331\nvertex 18.213943 -10.479768 8.003125\nvertex 19.552803 -10.479649 8.000000\nendloop\nendfacet\nfacet normal -0.002431 -0.002972 -0.999993\nouter loop\nvertex 18.215160 -11.852634 8.007331\nvertex 19.552803 -10.479649 8.000000\nvertex 19.553366 -11.852744 8.004080\nendloop\nendfacet\nfacet normal -0.020361 -0.002948 -0.999788\nouter loop\nvertex 17.142763 -11.851664 8.028987\nvertex 17.139935 -10.480088 8.025000\nvertex 18.213943 -10.479768 8.003125\nendloop\nendfacet\nfacet normal -0.020192 -0.003081 -0.999791\nouter loop\nvertex 17.142763 -11.851664 8.028987\nvertex 18.213943 -10.479768 8.003125\nvertex 18.215160 -11.852634 8.007331\nendloop\nendfacet\nfacet normal -0.075031 -0.002858 -0.997177\nouter loop\nvertex 16.356508 -11.849483 8.087871\nvertex 16.350824 -10.480552 8.084374\nvertex 17.139935 -10.480088 8.025000\nendloop\nendfacet\nfacet normal -0.074690 -0.003053 -0.997202\nouter loop\nvertex 16.356508 -11.849483 8.087871\nvertex 17.139935 -10.480088 8.025000\nvertex 17.142763 -11.851664 8.028987\nendloop\nendfacet\nfacet normal -0.232286 -0.003385 -0.972641\nouter loop\nvertex 15.874880 -11.848289 8.202797\nvertex 15.866667 -10.481091 8.200000\nvertex 16.350824 -10.480552 8.084374\nendloop\nendfacet\nfacet normal -0.232106 -0.003448 -0.972684\nouter loop\nvertex 15.874880 -11.848289 8.202797\nvertex 16.350824 -10.480552 8.084374\nvertex 16.356508 -11.849483 8.087871\nendloop\nendfacet\nfacet normal -0.232069 -0.030489 -0.972221\nouter loop\nvertex 15.932369 -12.910254 8.222376\nvertex 15.874880 -11.848289 8.202797\nvertex 16.356508 -11.849483 8.087871\nendloop\nendfacet\nfacet normal -0.231388 -0.030777 -0.972375\nouter loop\nvertex 15.932369 -12.910254 8.222376\nvertex 16.356508 -11.849483 8.087871\nvertex 16.396286 -12.921580 8.112339\nendloop\nendfacet\nfacet normal -0.231940 -0.107299 -0.966794\nouter loop\nvertex 16.073439 -13.654376 8.271119\nvertex 15.932369 -12.910254 8.222376\nvertex 16.396286 -12.921580 8.112339\nendloop\nendfacet\nfacet normal -0.228104 -0.109138 -0.967501\nouter loop\nvertex 16.073439 -13.654376 8.271119\nvertex 16.396286 -12.921580 8.112339\nvertex 16.490507 -13.696053 8.177488\nendloop\nendfacet\nfacet normal -0.075029 0.000000 -0.997181\nouter loop\nvertex 16.350824 -8.847996 8.084374\nvertex 16.350824 -7.084708 8.084374\nvertex 17.139935 -7.083379 8.025000\nendloop\nendfacet\nfacet normal -0.075032 0.000000 -0.997181\nouter loop\nvertex 16.350824 -8.847996 8.084374\nvertex 17.139935 -7.083379 8.025000\nvertex 17.139935 -8.847120 8.025000\nendloop\nendfacet\nfacet normal -0.020362 0.000000 -0.999793\nouter loop\nvertex 17.139935 -8.847120 8.025000\nvertex 17.139935 -7.083379 8.025000\nvertex 18.213943 -7.082455 8.003125\nendloop\nendfacet\nfacet normal -0.020364 0.000000 -0.999793\nouter loop\nvertex 17.139935 -8.847120 8.025000\nvertex 18.213943 -7.082455 8.003125\nvertex 18.213943 -8.846513 8.003125\nendloop\nendfacet\nfacet normal -0.073410 -0.001135 -0.997301\nouter loop\nvertex 16.350824 -7.084708 8.084374\nvertex 16.344336 -5.348505 8.082877\nvertex 17.137676 -5.346809 8.024479\nendloop\nendfacet\nfacet normal -0.075030 -0.000396 -0.997181\nouter loop\nvertex 16.350824 -7.084708 8.084374\nvertex 17.137676 -5.346809 8.024479\nvertex 17.139935 -7.083379 8.025000\nendloop\nendfacet\nfacet normal -0.019902 -0.000326 -0.999802\nouter loop\nvertex 17.139935 -7.083379 8.025000\nvertex 17.137676 -5.346809 8.024479\nvertex 18.213661 -5.345628 8.003059\nendloop\nendfacet\nfacet normal -0.020363 -0.000041 -0.999793\nouter loop\nvertex 17.139935 -7.083379 8.025000\nvertex 18.213661 -5.345628 8.003059\nvertex 18.213943 -7.082455 8.003125\nendloop\nendfacet\nfacet normal -0.232285 0.000000 -0.972648\nouter loop\nvertex 15.866667 -10.481091 8.200000\nvertex 15.866667 -8.849014 8.200000\nvertex 16.350824 -8.847996 8.084374\nendloop\nendfacet\nfacet normal -0.232287 0.000000 -0.972647\nouter loop\nvertex 15.866667 -10.481091 8.200000\nvertex 16.350824 -8.847996 8.084374\nvertex 16.350824 -10.480552 8.084374\nendloop\nendfacet\nfacet normal -0.075030 0.000000 -0.997181\nouter loop\nvertex 16.350824 -10.480552 8.084374\nvertex 16.350824 -8.847996 8.084374\nvertex 17.139935 -8.847120 8.025000\nendloop\nendfacet\nfacet normal -0.075030 0.000000 -0.997181\nouter loop\nvertex 16.350824 -10.480552 8.084374\nvertex 17.139935 -8.847120 8.025000\nvertex 17.139935 -10.480088 8.025000\nendloop\nendfacet\nfacet normal -0.020362 0.000000 -0.999793\nouter loop\nvertex 17.139935 -10.480088 8.025000\nvertex 17.139935 -8.847120 8.025000\nvertex 18.213943 -8.846513 8.003125\nendloop\nendfacet\nfacet normal -0.020364 0.000000 -0.999793\nouter loop\nvertex 17.139935 -10.480088 8.025000\nvertex 18.213943 -8.846513 8.003125\nvertex 18.213943 -10.479768 8.003125\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 -10.479768 8.003125\nvertex 18.213943 -8.846513 8.003125\nvertex 19.552803 -8.846289 8.000000\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 -10.479768 8.003125\nvertex 19.552803 -8.846289 8.000000\nvertex 19.552803 -10.479649 8.000000\nendloop\nendfacet\nfacet normal -0.002335 0.000000 -0.999997\nouter loop\nvertex 18.213943 -8.846513 8.003125\nvertex 18.213943 -7.082455 8.003125\nvertex 19.552803 -7.082114 8.000000\nendloop\nendfacet\nfacet normal -0.002334 0.000000 -0.999997\nouter loop\nvertex 18.213943 -8.846513 8.003125\nvertex 19.552803 -7.082114 8.000000\nvertex 19.552803 -8.846289 8.000000\nendloop\nendfacet\nfacet normal -0.002284 -0.000038 -0.999997\nouter loop\nvertex 18.213943 -7.082455 8.003125\nvertex 18.213661 -5.345628 8.003059\nvertex 19.552801 -5.345193 8.000000\nendloop\nendfacet\nfacet normal -0.002333 0.000000 -0.999997\nouter loop\nvertex 18.213943 -7.082455 8.003125\nvertex 19.552801 -5.345193 8.000000\nvertex 19.552803 -7.082114 8.000000\nendloop\nendfacet\nfacet normal -0.001942 -0.000296 -0.999998\nouter loop\nvertex 18.213661 -5.345628 8.003059\nvertex 18.211685 -3.794066 8.002604\nvertex 19.552803 -3.793593 8.000000\nendloop\nendfacet\nfacet normal -0.002284 0.000000 -0.999997\nouter loop\nvertex 18.213661 -5.345628 8.003059\nvertex 19.552803 -3.793593 8.000000\nvertex 19.552801 -5.345193 8.000000\nendloop\nendfacet\nfacet normal -0.016721 -0.002520 -0.999857\nouter loop\nvertex 17.137676 -5.346809 8.024479\nvertex 17.121878 -3.795351 8.020833\nvertex 18.211685 -3.794066 8.002604\nendloop\nendfacet\nfacet normal -0.019902 -0.000319 -0.999802\nouter loop\nvertex 17.137676 -5.346809 8.024479\nvertex 18.211685 -3.794066 8.002604\nvertex 18.213661 -5.345628 8.003059\nendloop\nendfacet\nfacet normal -0.060126 -0.009772 -0.998143\nouter loop\nvertex 16.344336 -5.348505 8.082877\nvertex 16.292145 -3.797194 8.070833\nvertex 17.121878 -3.795351 8.020833\nendloop\nendfacet\nfacet normal -0.073407 -0.003091 -0.997297\nouter loop\nvertex 16.344336 -5.348505 8.082877\nvertex 17.121878 -3.795351 8.020833\nvertex 17.137676 -5.346809 8.024479\nendloop\nendfacet\nfacet normal -0.198281 -0.024701 -0.979834\nouter loop\nvertex 15.857639 -5.350487 8.197917\nvertex 15.767362 -3.799347 8.177083\nvertex 16.292145 -3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.229944 -0.015290 -0.973084\nouter loop\nvertex 15.857639 -5.350487 8.197917\nvertex 16.292145 -3.797194 8.070833\nvertex 16.344336 -5.348505 8.082877\nendloop\nendfacet\nfacet normal -0.230020 -0.002364 -0.973183\nouter loop\nvertex 15.866667 -7.086260 8.200000\nvertex 15.857639 -5.350487 8.197917\nvertex 16.344336 -5.348505 8.082877\nendloop\nendfacet\nfacet normal -0.232282 -0.001707 -0.972647\nouter loop\nvertex 15.866667 -7.086260 8.200000\nvertex 16.344336 -5.348505 8.082877\nvertex 16.350824 -7.084708 8.084374\nendloop\nendfacet\nfacet normal -0.232286 0.000000 -0.972647\nouter loop\nvertex 15.866667 -8.849014 8.200000\nvertex 15.866667 -7.086260 8.200000\nvertex 16.350824 -7.084708 8.084374\nendloop\nendfacet\nfacet normal -0.232285 0.000000 -0.972648\nouter loop\nvertex 15.866667 -8.849014 8.200000\nvertex 16.350824 -7.084708 8.084374\nvertex 16.350824 -8.847996 8.084374\nendloop\nendfacet\nfacet normal -0.245487 0.000000 0.969400\nouter loop\nvertex 17.054993 -8.853159 9.365105\nvertex 17.735767 -8.853391 9.537500\nvertex 17.735767 -7.092913 9.537500\nendloop\nendfacet\nfacet normal -0.245485 -0.000000 0.969400\nouter loop\nvertex 17.054993 -8.853159 9.365105\nvertex 17.735767 -7.092913 9.537500\nvertex 17.054991 -7.092562 9.365105\nendloop\nendfacet\nfacet normal -0.245484 0.000000 0.969401\nouter loop\nvertex 17.054991 -7.092562 9.365105\nvertex 17.735767 -7.092913 9.537500\nvertex 17.735767 -5.358985 9.537500\nendloop\nendfacet\nfacet normal -0.245487 0.000000 0.969400\nouter loop\nvertex 17.054991 -7.092562 9.365105\nvertex 17.735767 -5.358985 9.537500\nvertex 17.054993 -5.358536 9.365105\nendloop\nendfacet\nfacet normal -0.088574 0.000000 0.996070\nouter loop\nvertex 17.735767 -8.853391 9.537500\nvertex 18.620193 -8.853397 9.616146\nvertex 18.620193 -7.092926 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 -8.853391 9.537500\nvertex 18.620193 -7.092926 9.616146\nvertex 17.735767 -7.092913 9.537500\nendloop\nendfacet\nfacet normal -0.088572 0.000000 0.996070\nouter loop\nvertex 17.735767 -7.092913 9.537500\nvertex 18.620193 -7.092926 9.616146\nvertex 18.620193 -5.359001 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 -7.092913 9.537500\nvertex 18.620193 -5.359001 9.616146\nvertex 17.735767 -5.358985 9.537500\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 -10.483034 9.133333\nvertex 17.054993 -10.483283 9.365105\nvertex 17.054993 -8.853159 9.365105\nendloop\nendfacet\nfacet normal -0.395446 0.000000 0.918489\nouter loop\nvertex 16.516666 -10.483034 9.133333\nvertex 17.054993 -8.853159 9.365105\nvertex 16.516666 -8.852689 9.133333\nendloop\nendfacet\nfacet normal -0.395445 -0.000001 0.918489\nouter loop\nvertex 16.516666 -8.852689 9.133333\nvertex 17.054993 -8.853159 9.365105\nvertex 17.054991 -7.092562 9.365105\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 -8.852689 9.133333\nvertex 17.054991 -7.092562 9.365105\nvertex 16.516666 -7.091847 9.133333\nendloop\nendfacet\nfacet normal -0.395448 0.000001 0.918488\nouter loop\nvertex 16.516666 -7.091847 9.133333\nvertex 17.054991 -7.092562 9.365105\nvertex 17.054993 -5.358536 9.365105\nendloop\nendfacet\nfacet normal -0.395448 0.000000 0.918488\nouter loop\nvertex 16.516666 -7.091847 9.133333\nvertex 17.054993 -5.358536 9.365105\nvertex 16.516666 -5.357624 9.133333\nendloop\nendfacet\nfacet normal -0.395446 -0.000001 0.918489\nouter loop\nvertex 16.516666 -5.357624 9.133333\nvertex 17.054993 -5.358536 9.365105\nvertex 17.054991 -3.808129 9.365105\nendloop\nendfacet\nfacet normal -0.395449 0.000000 0.918488\nouter loop\nvertex 16.516666 -5.357624 9.133333\nvertex 17.054991 -3.808129 9.365105\nvertex 16.516666 -3.807135 9.133333\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 -5.358536 9.365105\nvertex 17.735767 -5.358985 9.537500\nvertex 17.735767 -3.808617 9.537500\nendloop\nendfacet\nfacet normal -0.245485 -0.000000 0.969400\nouter loop\nvertex 17.054993 -5.358536 9.365105\nvertex 17.735767 -3.808617 9.537500\nvertex 17.054991 -3.808129 9.365105\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 -5.358985 9.537500\nvertex 18.620193 -5.359001 9.616146\nvertex 18.620193 -3.808635 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 -5.358985 9.537500\nvertex 18.620193 -3.808635 9.616146\nvertex 17.735767 -3.808617 9.537500\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 -5.359001 9.616146\nvertex 19.769468 -5.358619 9.566667\nvertex 19.769468 -3.808219 9.566667\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 -5.359001 9.616146\nvertex 19.769468 -3.808219 9.566667\nvertex 18.620193 -3.808635 9.616146\nendloop\nendfacet\nfacet normal 0.043012 0.000000 0.999075\nouter loop\nvertex 18.620193 -7.092926 9.616146\nvertex 19.769468 -7.092627 9.566667\nvertex 19.769468 -5.358619 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999075\nouter loop\nvertex 18.620193 -7.092926 9.616146\nvertex 19.769468 -5.358619 9.566667\nvertex 18.620193 -5.359001 9.616146\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999075\nouter loop\nvertex 18.620193 -8.853397 9.616146\nvertex 19.769468 -8.853203 9.566667\nvertex 19.769468 -7.092627 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999074\nouter loop\nvertex 18.620193 -8.853397 9.616146\nvertex 19.769468 -7.092627 9.566667\nvertex 18.620193 -7.092926 9.616146\nendloop\nendfacet\nfacet normal 0.043013 0.000000 0.999074\nouter loop\nvertex 18.620193 -10.483410 9.616146\nvertex 19.769468 -10.483306 9.566667\nvertex 19.769468 -8.853203 9.566667\nendloop\nendfacet\nfacet normal 0.043014 0.000000 0.999074\nouter loop\nvertex 18.620193 -10.483410 9.616146\nvertex 19.769468 -8.853203 9.566667\nvertex 18.620193 -8.853397 9.616146\nendloop\nendfacet\nfacet normal -0.088574 0.000000 0.996070\nouter loop\nvertex 17.735767 -10.483404 9.537500\nvertex 18.620193 -10.483410 9.616146\nvertex 18.620193 -8.853397 9.616146\nendloop\nendfacet\nfacet normal -0.088573 0.000000 0.996070\nouter loop\nvertex 17.735767 -10.483404 9.537500\nvertex 18.620193 -8.853397 9.616146\nvertex 17.735767 -8.853391 9.537500\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 -10.483283 9.365105\nvertex 17.735767 -10.483404 9.537500\nvertex 17.735767 -8.853391 9.537500\nendloop\nendfacet\nfacet normal -0.245486 0.000000 0.969400\nouter loop\nvertex 17.054993 -10.483283 9.365105\nvertex 17.735767 -8.853391 9.537500\nvertex 17.054993 -8.853159 9.365105\nendloop\nendfacet\nfacet normal -0.242171 -0.840189 0.485218\nouter loop\nvertex 16.905079 -14.500335 8.978137\nvertex 16.756197 -14.599973 8.731298\nvertex 17.455404 -14.771413 8.783410\nendloop\nendfacet\nfacet normal -0.260777 -0.853498 0.451151\nouter loop\nvertex 16.905079 -14.500335 8.978137\nvertex 17.455404 -14.771413 8.783410\nvertex 17.568832 -14.658748 9.062117\nendloop\nendfacet\nfacet normal -0.071003 -0.914397 0.398542\nouter loop\nvertex 17.568832 -14.658748 9.062117\nvertex 17.455404 -14.771413 8.783410\nvertex 18.419262 -14.834710 8.809905\nendloop\nendfacet\nfacet normal -0.076539 -0.920191 0.383914\nouter loop\nvertex 17.568832 -14.658748 9.062117\nvertex 18.419262 -14.834710 8.809905\nvertex 18.493919 -14.718086 9.104320\nendloop\nendfacet\nfacet normal -0.205023 -0.929081 -0.307853\nouter loop\nvertex 16.756197 -14.599973 8.731298\nvertex 16.664705 -14.500335 8.491524\nvertex 17.359531 -14.658748 8.506865\nendloop\nendfacet\nfacet normal -0.204917 -0.929214 -0.307524\nouter loop\nvertex 16.756197 -14.599973 8.731298\nvertex 17.359531 -14.658748 8.506865\nvertex 17.455404 -14.771413 8.783410\nendloop\nendfacet\nfacet normal -0.052708 -0.931059 -0.361041\nouter loop\nvertex 17.455404 -14.771413 8.783410\nvertex 17.359531 -14.658748 8.506865\nvertex 18.346798 -14.718087 8.515761\nendloop\nendfacet\nfacet normal -0.051432 -0.932644 -0.357113\nouter loop\nvertex 17.455404 -14.771413 8.783410\nvertex 18.346798 -14.718087 8.515761\nvertex 18.419262 -14.834710 8.809905\nendloop\nendfacet\nfacet normal -0.414807 -0.381097 0.826257\nouter loop\nvertex 16.679167 -14.062502 9.066667\nvertex 16.475306 -14.199250 8.901251\nvertex 16.905079 -14.500335 8.978137\nendloop\nendfacet\nfacet normal -0.409180 -0.378964 0.830035\nouter loop\nvertex 16.679167 -14.062502 9.066667\nvertex 16.905079 -14.500335 8.978137\nvertex 17.038143 -14.205942 9.178142\nendloop\nendfacet\nfacet normal -0.221536 -0.477507 0.850241\nouter loop\nvertex 17.038143 -14.205942 9.178142\nvertex 16.905079 -14.500335 8.978137\nvertex 17.568832 -14.658748 9.062117\nendloop\nendfacet\nfacet normal -0.243370 -0.498430 0.832069\nouter loop\nvertex 17.038143 -14.205942 9.178142\nvertex 17.568832 -14.658748 9.062117\nvertex 17.665802 -14.321471 9.292516\nendloop\nendfacet\nfacet normal -0.073170 -0.548127 0.833189\nouter loop\nvertex 17.665802 -14.321471 9.292516\nvertex 17.568832 -14.658748 9.062117\nvertex 18.493919 -14.718086 9.104320\nendloop\nendfacet\nfacet normal -0.081027 -0.560320 0.824303\nouter loop\nvertex 17.665802 -14.321471 9.292516\nvertex 18.493919 -14.718086 9.104320\nvertex 18.556152 -14.368310 9.348197\nendloop\nendfacet\nfacet normal 0.019972 -0.574211 0.818464\nouter loop\nvertex 18.556152 -14.368310 9.348197\nvertex 18.493919 -14.718086 9.104320\nvertex 19.700632 -14.726565 9.068924\nendloop\nendfacet\nfacet normal 0.026814 -0.559897 0.828128\nouter loop\nvertex 18.556152 -14.368310 9.348197\nvertex 19.700632 -14.726565 9.068924\nvertex 19.733356 -14.375003 9.305555\nendloop\nendfacet\nfacet normal 0.001105 -0.929810 0.368039\nouter loop\nvertex 18.493919 -14.718086 9.104320\nvertex 18.419262 -14.834710 8.809905\nvertex 19.661137 -14.843751 8.783334\nendloop\nendfacet\nfacet normal 0.004617 -0.925364 0.379051\nouter loop\nvertex 18.493919 -14.718086 9.104320\nvertex 19.661137 -14.843751 8.783334\nvertex 19.700632 -14.726565 9.068924\nendloop\nendfacet\nfacet normal -0.011363 -0.930494 -0.366131\nouter loop\nvertex 18.419262 -14.834710 8.809905\nvertex 18.346798 -14.718087 8.515761\nvertex 19.621639 -14.726565 8.497743\nendloop\nendfacet\nfacet normal -0.014824 -0.925763 -0.377813\nouter loop\nvertex 18.419262 -14.834710 8.809905\nvertex 19.621639 -14.726565 8.497743\nvertex 19.661137 -14.843751 8.783334\nendloop\nendfacet\nfacet normal -0.009894 -0.572629 -0.819755\nouter loop\nvertex 18.346798 -14.718087 8.515761\nvertex 18.286760 -14.368312 8.272155\nvertex 19.588913 -14.375001 8.261111\nendloop\nendfacet\nfacet normal -0.015434 -0.559302 -0.828820\nouter loop\nvertex 18.346798 -14.718087 8.515761\nvertex 19.588913 -14.375001 8.261111\nvertex 19.621639 -14.726565 8.497743\nendloop\nendfacet\nfacet normal -0.031604 -0.565255 -0.824310\nouter loop\nvertex 17.359531 -14.658748 8.506865\nvertex 17.280115 -14.321469 8.278626\nvertex 18.286760 -14.368312 8.272155\nendloop\nendfacet\nfacet normal -0.027153 -0.574440 -0.818096\nouter loop\nvertex 17.359531 -14.658748 8.506865\nvertex 18.286760 -14.368312 8.272155\nvertex 18.346798 -14.718087 8.515761\nendloop\nendfacet\nfacet normal -0.120109 -0.561358 -0.818811\nouter loop\nvertex 16.664705 -14.500335 8.491524\nvertex 16.597235 -14.205941 8.299591\nvertex 17.280115 -14.321469 8.278626\nendloop\nendfacet\nfacet normal -0.113200 -0.574987 -0.810294\nouter loop\nvertex 16.664705 -14.500335 8.491524\nvertex 17.280115 -14.321469 8.278626\nvertex 17.359531 -14.658748 8.506865\nendloop\nendfacet\nfacet normal -0.324005 -0.627125 -0.708333\nouter loop\nvertex 16.212664 -14.199250 8.469577\nvertex 16.245834 -14.062501 8.333333\nvertex 16.597235 -14.205941 8.299591\nendloop\nendfacet\nfacet normal -0.341250 -0.566992 -0.749712\nouter loop\nvertex 16.212664 -14.199250 8.469577\nvertex 16.597235 -14.205941 8.299591\nvertex 16.664705 -14.500335 8.491524\nendloop\nendfacet\nfacet normal -0.549505 -0.831193 -0.084632\nouter loop\nvertex 16.284452 -14.267941 8.678086\nvertex 16.212664 -14.199250 8.469577\nvertex 16.664705 -14.500335 8.491524\nendloop\nendfacet\nfacet normal -0.561493 -0.817890 -0.125621\nouter loop\nvertex 16.284452 -14.267941 8.678086\nvertex 16.664705 -14.500335 8.491524\nvertex 16.756197 -14.599973 8.731298\nendloop\nendfacet\nfacet normal -0.499132 -0.610628 0.614818\nouter loop\nvertex 16.475306 -14.199250 8.901251\nvertex 16.284452 -14.267941 8.678086\nvertex 16.756197 -14.599973 8.731298\nendloop\nendfacet\nfacet normal -0.536386 -0.619208 0.573473\nouter loop\nvertex 16.475306 -14.199250 8.901251\nvertex 16.756197 -14.599973 8.731298\nvertex 16.905079 -14.500335 8.978137\nendloop\nendfacet\nfacet normal 1.000000 -0.000008 -0.000007\nouter loop\nvertex 55.000004 -0.141782 3.373485\nvertex 55.000004 0.281395 2.732860\nvertex 55.000008 0.484375 3.003500\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000003\nouter loop\nvertex 55.000004 -0.141782 3.373485\nvertex 55.000008 0.484375 3.003500\nvertex 55.000008 0.281395 3.515847\nendloop\nendfacet\nfacet normal 1.000000 0.000008 -0.000006\nouter loop\nvertex 55.000004 0.761863 2.168624\nvertex 55.000008 0.868634 2.732860\nvertex 55.000008 0.484375 3.003500\nendloop\nendfacet\nfacet normal 1.000000 -0.000023 -0.000007\nouter loop\nvertex 55.000004 0.761863 2.168624\nvertex 55.000008 0.484375 3.003500\nvertex 55.000004 0.281395 2.732860\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 0.767072 3.380429\nvertex 55.000008 0.281395 3.515847\nvertex 55.000008 0.484375 3.003500\nendloop\nendfacet\nfacet normal 1.000000 -0.000009 0.000000\nouter loop\nvertex 55.000008 0.767072 3.380429\nvertex 55.000008 0.484375 3.003500\nvertex 55.000008 0.868634 2.732860\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000005\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 55.000008 -0.500000 3.024334\nvertex 55.000004 -0.141782 3.373485\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000004\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 55.000004 -0.141782 3.373485\nvertex 55.000008 -0.546875 4.066000\nendloop\nendfacet\nfacet normal 1.000000 0.000010 -0.000003\nouter loop\nvertex 55.000008 -0.500000 3.024334\nvertex 55.000004 0.000000 2.357667\nvertex 55.000004 0.281395 2.732860\nendloop\nendfacet\nfacet normal 1.000000 0.000020 0.000004\nouter loop\nvertex 55.000008 -0.500000 3.024334\nvertex 55.000004 0.281395 2.732860\nvertex 55.000004 -0.141782 3.373485\nendloop\nendfacet\nfacet normal 1.000000 0.000011 -0.000009\nouter loop\nvertex 55.000008 -0.546875 4.066000\nvertex 55.000004 -0.141782 3.373485\nvertex 55.000008 0.281395 3.515847\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 -0.546875 4.066000\nvertex 55.000008 0.281395 3.515847\nvertex 55.000008 0.000000 4.191000\nendloop\nendfacet\nfacet normal 1.000000 0.000008 0.000002\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 55.000008 1.281250 1.628500\nvertex 55.000004 0.761863 2.168624\nendloop\nendfacet\nfacet normal 1.000000 -0.000009 0.000005\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 55.000004 0.761863 2.168624\nvertex 55.000008 0.500000 1.691000\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 1.281250 1.628500\nvertex 55.000008 1.375000 2.357667\nvertex 55.000008 0.868634 2.732860\nendloop\nendfacet\nfacet normal 1.000000 -0.000011 -0.000004\nouter loop\nvertex 55.000008 1.281250 1.628500\nvertex 55.000008 0.868634 2.732860\nvertex 55.000004 0.761863 2.168624\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000005\nouter loop\nvertex 55.000008 0.500000 1.691000\nvertex 55.000004 0.761863 2.168624\nvertex 55.000004 0.281395 2.732860\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000003\nouter loop\nvertex 55.000008 0.500000 1.691000\nvertex 55.000004 0.281395 2.732860\nvertex 55.000004 0.000000 2.357667\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000007\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 55.000008 0.546875 4.066000\nvertex 55.000008 0.767072 3.380429\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000017\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 55.000008 0.767072 3.380429\nvertex 55.000008 1.281250 3.086834\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 0.546875 4.066000\nvertex 55.000008 0.000000 4.191000\nvertex 55.000008 0.281395 3.515847\nendloop\nendfacet\nfacet normal 1.000000 -0.000003 0.000000\nouter loop\nvertex 55.000008 0.546875 4.066000\nvertex 55.000008 0.281395 3.515847\nvertex 55.000008 0.767072 3.380429\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 1.281250 3.086834\nvertex 55.000008 0.767072 3.380429\nvertex 55.000008 0.868634 2.732860\nendloop\nendfacet\nfacet normal 1.000000 -0.000011 0.000000\nouter loop\nvertex 55.000008 1.281250 3.086834\nvertex 55.000008 0.868634 2.732860\nvertex 55.000008 1.375000 2.357667\nendloop\nendfacet\nfacet normal -0.185267 -0.973818 0.131736\nouter loop\nvertex 1.539941 -2.191099 4.267486\nvertex 1.943580 -2.370726 3.507300\nvertex 2.261111 -2.373071 3.936525\nendloop\nendfacet\nfacet normal -0.161360 -0.970018 0.181739\nouter loop\nvertex 1.539941 -2.191099 4.267486\nvertex 2.261111 -2.373071 3.936525\nvertex 2.133636 -2.233862 4.566360\nendloop\nendfacet\nfacet normal -0.052033 -0.998532 -0.015070\nouter loop\nvertex 2.649281 -2.376406 2.817216\nvertex 2.909109 -2.402924 3.677179\nvertex 2.261111 -2.373071 3.936525\nendloop\nendfacet\nfacet normal -0.007770 -0.999970 0.000285\nouter loop\nvertex 2.649281 -2.376406 2.817216\nvertex 2.261111 -2.373071 3.936525\nvertex 1.943580 -2.370726 3.507300\nendloop\nendfacet\nfacet normal -0.036345 -0.977314 0.208654\nouter loop\nvertex 3.071936 -2.259743 4.608581\nvertex 2.133636 -2.233862 4.566360\nvertex 2.261111 -2.373071 3.936525\nendloop\nendfacet\nfacet normal 0.014282 -0.988661 0.149487\nouter loop\nvertex 3.071936 -2.259743 4.608581\nvertex 2.261111 -2.373071 3.936525\nvertex 2.909109 -2.402924 3.677179\nendloop\nendfacet\nfacet normal -0.516100 -0.776904 0.360639\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 1.143440 -2.154511 3.778884\nvertex 1.539941 -2.191099 4.267486\nendloop\nendfacet\nfacet normal -0.524418 -0.778073 0.345815\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 1.539941 -2.191099 4.267486\nvertex 1.394066 -1.776039 4.980145\nendloop\nendfacet\nfacet normal -0.230695 -0.968710 0.091543\nouter loop\nvertex 1.143440 -2.154511 3.778884\nvertex 1.609877 -2.343493 2.954529\nvertex 1.943580 -2.370726 3.507300\nendloop\nendfacet\nfacet normal -0.224445 -0.968300 0.109629\nouter loop\nvertex 1.143440 -2.154511 3.778884\nvertex 1.943580 -2.370726 3.507300\nvertex 1.539941 -2.191099 4.267486\nendloop\nendfacet\nfacet normal -0.282420 -0.852964 0.438966\nouter loop\nvertex 1.394066 -1.776039 4.980145\nvertex 1.539941 -2.191099 4.267486\nvertex 2.133636 -2.233862 4.566360\nendloop\nendfacet\nfacet normal -0.282277 -0.852910 0.439164\nouter loop\nvertex 1.394066 -1.776039 4.980145\nvertex 2.133636 -2.233862 4.566360\nvertex 2.083642 -1.867799 5.245167\nendloop\nendfacet\nfacet normal -0.129097 -0.929282 -0.346077\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 3.804913 -2.318981 2.231933\nvertex 2.649281 -2.376406 2.817216\nendloop\nendfacet\nfacet normal 0.197745 -0.949578 -0.243307\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 2.649281 -2.376406 2.817216\nvertex 2.251229 -2.276334 2.103142\nendloop\nendfacet\nfacet normal -0.053123 -0.994461 -0.090688\nouter loop\nvertex 3.804913 -2.318981 2.231933\nvertex 4.081018 -2.428884 3.275362\nvertex 2.909109 -2.402924 3.677179\nendloop\nendfacet\nfacet normal 0.029515 -0.998775 -0.039717\nouter loop\nvertex 3.804913 -2.318981 2.231933\nvertex 2.909109 -2.402924 3.677179\nvertex 2.649281 -2.376406 2.817216\nendloop\nendfacet\nfacet normal -0.093136 -0.991838 -0.087081\nouter loop\nvertex 2.251229 -2.276334 2.103142\nvertex 2.649281 -2.376406 2.817216\nvertex 1.943580 -2.370726 3.507300\nendloop\nendfacet\nfacet normal 0.021777 -0.997820 -0.062305\nouter loop\nvertex 2.251229 -2.276334 2.103142\nvertex 1.943580 -2.370726 3.507300\nvertex 1.609877 -2.343493 2.954529\nendloop\nendfacet\nfacet normal -0.041653 -0.900109 0.433670\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 3.171496 -1.861331 5.445072\nvertex 3.071936 -2.259743 4.608581\nendloop\nendfacet\nfacet normal 0.014831 -0.942051 0.335141\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 3.071936 -2.259743 4.608581\nvertex 4.454588 -2.322237 4.371733\nendloop\nendfacet\nfacet normal -0.080858 -0.879766 0.468481\nouter loop\nvertex 3.171496 -1.861331 5.445072\nvertex 2.083642 -1.867799 5.245167\nvertex 2.133636 -2.233862 4.566360\nendloop\nendfacet\nfacet normal -0.044344 -0.899879 0.433880\nouter loop\nvertex 3.171496 -1.861331 5.445072\nvertex 2.133636 -2.233862 4.566360\nvertex 3.071936 -2.259743 4.608581\nendloop\nendfacet\nfacet normal -0.018092 -0.987748 0.155005\nouter loop\nvertex 4.454588 -2.322237 4.371733\nvertex 3.071936 -2.259743 4.608581\nvertex 2.909109 -2.402924 3.677179\nendloop\nendfacet\nfacet normal 0.009985 -0.995575 0.093441\nouter loop\nvertex 4.454588 -2.322237 4.371733\nvertex 2.909109 -2.402924 3.677179\nvertex 4.081018 -2.428884 3.275362\nendloop\nendfacet\nfacet normal -0.993309 0.019026 0.113909\nouter loop\nvertex 0.194632 0.223443 3.953737\nvertex 0.108384 -0.402336 3.306158\nvertex 0.138021 -0.720486 3.617737\nendloop\nendfacet\nfacet normal -0.991586 0.013646 0.128731\nouter loop\nvertex 0.194632 0.223443 3.953737\nvertex 0.138021 -0.720486 3.617737\nvertex 0.211878 -0.430331 4.155883\nendloop\nendfacet\nfacet normal -0.991095 -0.132667 0.011403\nouter loop\nvertex 0.171079 -1.043817 2.729306\nvertex 0.204478 -1.241022 3.337755\nvertex 0.138021 -0.720486 3.617737\nendloop\nendfacet\nfacet normal -0.995464 -0.095109 -0.002428\nouter loop\nvertex 0.171079 -1.043817 2.729306\nvertex 0.138021 -0.720486 3.617737\nvertex 0.108384 -0.402336 3.306158\nendloop\nendfacet\nfacet normal -0.959496 -0.171004 0.223886\nouter loop\nvertex 0.314128 -1.133957 4.056663\nvertex 0.211878 -0.430331 4.155883\nvertex 0.138021 -0.720486 3.617737\nendloop\nendfacet\nfacet normal -0.959260 -0.218682 0.178878\nouter loop\nvertex 0.314128 -1.133957 4.056663\nvertex 0.138021 -0.720486 3.617737\nvertex 0.204478 -1.241022 3.337755\nendloop\nendfacet\nfacet normal -0.934846 0.235015 0.266140\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.208924 0.785330 3.507765\nvertex 0.194632 0.223443 3.953737\nendloop\nendfacet\nfacet normal -0.956068 0.248838 0.154963\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.194632 0.223443 3.953737\nvertex 0.439913 0.780122 4.573130\nendloop\nendfacet\nfacet normal -0.994651 0.071555 0.074493\nouter loop\nvertex 0.208924 0.785330 3.507765\nvertex 0.106944 0.041667 2.860445\nvertex 0.108384 -0.402336 3.306158\nendloop\nendfacet\nfacet normal -0.995389 0.073877 0.061180\nouter loop\nvertex 0.208924 0.785330 3.507765\nvertex 0.108384 -0.402336 3.306158\nvertex 0.194632 0.223443 3.953737\nendloop\nendfacet\nfacet normal -0.947655 0.071239 0.311248\nouter loop\nvertex 0.439913 0.780122 4.573130\nvertex 0.194632 0.223443 3.953737\nvertex 0.211878 -0.430331 4.155883\nendloop\nendfacet\nfacet normal -0.959548 0.088655 0.267224\nouter loop\nvertex 0.439913 0.780122 4.573130\nvertex 0.211878 -0.430331 4.155883\nvertex 0.423611 0.000000 4.773408\nendloop\nendfacet\nfacet normal -0.963034 -0.214320 -0.163196\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.380729 -1.598091 2.220051\nvertex 0.171079 -1.043817 2.729306\nendloop\nendfacet\nfacet normal -0.963975 -0.209317 -0.164130\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.171079 -1.043817 2.729306\nvertex 0.171354 -0.640046 2.212759\nendloop\nendfacet\nfacet normal -0.948706 -0.312201 -0.049864\nouter loop\nvertex 0.380729 -1.598091 2.220051\nvertex 0.406945 -1.789352 2.918778\nvertex 0.204478 -1.241022 3.337755\nendloop\nendfacet\nfacet normal -0.948377 -0.313261 -0.049474\nouter loop\nvertex 0.380729 -1.598091 2.220051\nvertex 0.204478 -1.241022 3.337755\nvertex 0.171079 -1.043817 2.729306\nendloop\nendfacet\nfacet normal -0.997359 -0.056961 -0.045056\nouter loop\nvertex 0.171354 -0.640046 2.212759\nvertex 0.171079 -1.043817 2.729306\nvertex 0.108384 -0.402336 3.306158\nendloop\nendfacet\nfacet normal -0.997662 -0.050000 -0.046586\nouter loop\nvertex 0.171354 -0.640046 2.212759\nvertex 0.108384 -0.402336 3.306158\nvertex 0.106944 0.041667 2.860445\nendloop\nendfacet\nfacet normal -0.800291 -0.397577 0.448850\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 0.537691 -0.780122 4.768686\nvertex 0.314128 -1.133957 4.056663\nendloop\nendfacet\nfacet normal -0.791815 -0.482389 0.374606\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 0.314128 -1.133957 4.056663\nvertex 0.535608 -1.766233 3.710613\nendloop\nendfacet\nfacet normal -0.904731 -0.134748 0.404110\nouter loop\nvertex 0.537691 -0.780122 4.768686\nvertex 0.423611 0.000000 4.773408\nvertex 0.211878 -0.430331 4.155883\nendloop\nendfacet\nfacet normal -0.907576 -0.185039 0.376917\nouter loop\nvertex 0.537691 -0.780122 4.768686\nvertex 0.211878 -0.430331 4.155883\nvertex 0.314128 -1.133957 4.056663\nendloop\nendfacet\nfacet normal -0.886417 -0.418619 0.197544\nouter loop\nvertex 0.535608 -1.766233 3.710613\nvertex 0.314128 -1.133957 4.056663\nvertex 0.204478 -1.241022 3.337755\nendloop\nendfacet\nfacet normal -0.881790 -0.445001 0.156272\nouter loop\nvertex 0.535608 -1.766233 3.710613\nvertex 0.204478 -1.241022 3.337755\nvertex 0.406945 -1.789352 2.918778\nendloop\nendfacet\nfacet normal 0.181319 0.966822 0.179941\nouter loop\nvertex 52.671993 1.719298 3.280712\nvertex 51.794785 1.992473 2.696870\nvertex 51.186733 2.056906 2.963377\nendloop\nendfacet\nfacet normal 0.157565 0.949203 0.272374\nouter loop\nvertex 52.671993 1.719298 3.280712\nvertex 51.186733 2.056906 2.963377\nvertex 51.447769 1.881940 3.422114\nendloop\nendfacet\nfacet normal 0.115521 0.993281 0.006967\nouter loop\nvertex 50.440521 2.149413 2.147905\nvertex 49.957466 2.201473 2.735353\nvertex 51.186733 2.056906 2.963377\nendloop\nendfacet\nfacet normal 0.110433 0.993815 0.011685\nouter loop\nvertex 50.440521 2.149413 2.147905\nvertex 51.186733 2.056906 2.963377\nvertex 51.794785 1.992473 2.696870\nendloop\nendfacet\nfacet normal 0.088219 0.946386 0.310758\nouter loop\nvertex 49.641869 2.055952 3.404844\nvertex 51.447769 1.881940 3.422114\nvertex 51.186733 2.056906 2.963377\nendloop\nendfacet\nfacet normal 0.068771 0.967648 0.242749\nouter loop\nvertex 49.641869 2.055952 3.404844\nvertex 51.186733 2.056906 2.963377\nvertex 49.957466 2.201473 2.735353\nendloop\nendfacet\nfacet normal 0.231328 0.923403 0.306290\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 53.526051 1.599617 2.996491\nvertex 52.671993 1.719298 3.280712\nendloop\nendfacet\nfacet normal 0.150699 0.810556 0.565941\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 52.671993 1.719298 3.280712\nvertex 53.066593 1.283501 3.799797\nendloop\nendfacet\nfacet normal 0.208283 0.975178 0.075135\nouter loop\nvertex 53.526051 1.599617 2.996491\nvertex 52.409729 1.888375 2.343264\nvertex 51.794785 1.992473 2.696870\nendloop\nendfacet\nfacet normal 0.190815 0.967490 0.165988\nouter loop\nvertex 53.526051 1.599617 2.996491\nvertex 51.794785 1.992473 2.696870\nvertex 52.671993 1.719298 3.280712\nendloop\nendfacet\nfacet normal 0.172183 0.814978 0.553322\nouter loop\nvertex 53.066593 1.283501 3.799797\nvertex 52.671993 1.719298 3.280712\nvertex 51.447769 1.881940 3.422114\nendloop\nendfacet\nfacet normal 0.154133 0.790788 0.592366\nouter loop\nvertex 53.066593 1.283501 3.799797\nvertex 51.447769 1.881940 3.422114\nvertex 51.558132 1.499486 3.903964\nendloop\nendfacet\nfacet normal 0.127358 0.916657 -0.378840\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 48.242996 2.261178 1.679576\nvertex 50.440521 2.149413 2.147905\nendloop\nendfacet\nfacet normal 0.017056 0.955880 -0.293263\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 50.440521 2.149413 2.147905\nvertex 51.159924 1.990409 1.671474\nendloop\nendfacet\nfacet normal 0.089429 0.991998 -0.089126\nouter loop\nvertex 48.242996 2.261178 1.679576\nvertex 47.717857 2.373972 2.408079\nvertex 49.957466 2.201473 2.735353\nendloop\nendfacet\nfacet normal 0.059195 0.997456 -0.039721\nouter loop\nvertex 48.242996 2.261178 1.679576\nvertex 49.957466 2.201473 2.735353\nvertex 50.440521 2.149413 2.147905\nendloop\nendfacet\nfacet normal 0.153223 0.983435 -0.096846\nouter loop\nvertex 51.159924 1.990409 1.671474\nvertex 50.440521 2.149413 2.147905\nvertex 51.794785 1.992473 2.696870\nendloop\nendfacet\nfacet normal 0.122667 0.989383 -0.077939\nouter loop\nvertex 51.159924 1.990409 1.671474\nvertex 51.794785 1.992473 2.696870\nvertex 52.409729 1.888375 2.343264\nendloop\nendfacet\nfacet normal 0.074646 0.818859 0.569120\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 49.445156 1.646948 4.019125\nvertex 49.641869 2.055952 3.404844\nendloop\nendfacet\nfacet normal 0.042905 0.894888 0.444223\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 49.641869 2.055952 3.404844\nvertex 46.986958 2.274199 3.221608\nendloop\nendfacet\nfacet normal 0.088201 0.789948 0.606797\nouter loop\nvertex 49.445156 1.646948 4.019125\nvertex 51.558132 1.499486 3.903964\nvertex 51.447769 1.881940 3.422114\nendloop\nendfacet\nfacet normal 0.073486 0.819108 0.568913\nouter loop\nvertex 49.445156 1.646948 4.019125\nvertex 51.447769 1.881940 3.422114\nvertex 49.641869 2.055952 3.404844\nendloop\nendfacet\nfacet normal 0.063046 0.968657 0.240268\nouter loop\nvertex 46.986958 2.274199 3.221608\nvertex 49.641869 2.055952 3.404844\nvertex 49.957466 2.201473 2.735353\nendloop\nendfacet\nfacet normal 0.051438 0.984619 0.166970\nouter loop\nvertex 46.986958 2.274199 3.221608\nvertex 49.957466 2.201473 2.735353\nvertex 47.717857 2.373972 2.408079\nendloop\nendfacet\nfacet normal 0.030800 -0.006309 -0.999506\nouter loop\nvertex 2.637526 -0.290024 0.511322\nvertex 1.918631 0.381511 0.484930\nvertex 2.191551 0.712577 0.491251\nendloop\nendfacet\nfacet normal -0.028449 -0.032655 -0.999062\nouter loop\nvertex 2.637526 -0.290024 0.511322\nvertex 2.191551 0.712577 0.491251\nvertex 2.830451 0.411186 0.482909\nendloop\nendfacet\nfacet normal -0.094545 0.195170 -0.976202\nouter loop\nvertex 1.460494 1.042770 0.628068\nvertex 1.971341 1.252340 0.620492\nvertex 2.191551 0.712577 0.491251\nendloop\nendfacet\nfacet normal -0.128002 0.124306 -0.983953\nouter loop\nvertex 1.460494 1.042770 0.628068\nvertex 2.191551 0.712577 0.491251\nvertex 1.918631 0.381511 0.484930\nendloop\nendfacet\nfacet normal 0.076297 0.188834 -0.979041\nouter loop\nvertex 2.813697 1.169283 0.627823\nvertex 2.830451 0.411186 0.482909\nvertex 2.191551 0.712577 0.491251\nendloop\nendfacet\nfacet normal 0.032619 0.245301 -0.968898\nouter loop\nvertex 2.813697 1.169283 0.627823\nvertex 2.191551 0.712577 0.491251\nvertex 1.971341 1.252340 0.620492\nendloop\nendfacet\nfacet normal 0.211938 -0.298412 -0.930609\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 2.250708 -0.876450 0.611273\nvertex 2.637526 -0.290024 0.511322\nendloop\nendfacet\nfacet normal -0.140373 -0.416817 -0.898086\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 2.637526 -0.290024 0.511322\nvertex 3.794400 -0.906173 0.616465\nendloop\nendfacet\nfacet normal 0.053562 -0.085780 -0.994873\nouter loop\nvertex 2.250708 -0.876450 0.611273\nvertex 1.605710 -0.068030 0.506844\nvertex 1.918631 0.381511 0.484930\nendloop\nendfacet\nfacet normal -0.075041 -0.119242 -0.990025\nouter loop\nvertex 2.250708 -0.876450 0.611273\nvertex 1.918631 0.381511 0.484930\nvertex 2.637526 -0.290024 0.511322\nendloop\nendfacet\nfacet normal 0.060239 -0.056955 -0.996558\nouter loop\nvertex 3.794400 -0.906173 0.616465\nvertex 2.637526 -0.290024 0.511322\nvertex 2.830451 0.411186 0.482909\nendloop\nendfacet\nfacet normal -0.039881 -0.129627 -0.990760\nouter loop\nvertex 3.794400 -0.906173 0.616465\nvertex 2.830451 0.411186 0.482909\nvertex 3.996914 -0.050026 0.496299\nendloop\nendfacet\nfacet normal -0.401257 0.315867 -0.859779\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 1.136574 1.600775 0.984242\nvertex 1.460494 1.042770 0.628068\nendloop\nendfacet\nfacet normal -0.403919 0.308189 -0.861318\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 1.460494 1.042770 0.628068\nvertex 1.126061 0.636751 0.639624\nendloop\nendfacet\nfacet normal -0.190824 0.452324 -0.871200\nouter loop\nvertex 1.136574 1.600775 0.984242\nvertex 1.689815 1.810828 0.972122\nvertex 1.971341 1.252340 0.620492\nendloop\nendfacet\nfacet normal -0.195352 0.444584 -0.874175\nouter loop\nvertex 1.136574 1.600775 0.984242\nvertex 1.971341 1.252340 0.620492\nvertex 1.460494 1.042770 0.628068\nendloop\nendfacet\nfacet normal -0.158596 0.102685 -0.981989\nouter loop\nvertex 1.126061 0.636751 0.639624\nvertex 1.460494 1.042770 0.628068\nvertex 1.918631 0.381511 0.484930\nendloop\nendfacet\nfacet normal -0.169346 0.069959 -0.983071\nouter loop\nvertex 1.126061 0.636751 0.639624\nvertex 1.918631 0.381511 0.484930\nvertex 1.605710 -0.068030 0.506844\nendloop\nendfacet\nfacet normal 0.109645 0.460478 -0.880873\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 4.148535 0.817264 0.609955\nvertex 2.813697 1.169283 0.627823\nendloop\nendfacet\nfacet normal 0.067900 0.529447 -0.845621\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 2.813697 1.169283 0.627823\nvertex 2.556761 1.841754 1.028229\nendloop\nendfacet\nfacet normal 0.058674 0.119622 -0.991084\nouter loop\nvertex 4.148535 0.817264 0.609955\nvertex 3.996914 -0.050026 0.496299\nvertex 2.830451 0.411186 0.482909\nendloop\nendfacet\nfacet normal 0.036550 0.188409 -0.981410\nouter loop\nvertex 4.148535 0.817264 0.609955\nvertex 2.830451 0.411186 0.482909\nvertex 2.813697 1.169283 0.627823\nendloop\nendfacet\nfacet normal 0.059374 0.527350 -0.847571\nouter loop\nvertex 2.556761 1.841754 1.028229\nvertex 2.813697 1.169283 0.627823\nvertex 1.971341 1.252340 0.620492\nendloop\nendfacet\nfacet normal 0.034776 0.544975 -0.837731\nouter loop\nvertex 2.556761 1.841754 1.028229\nvertex 1.971341 1.252340 0.620492\nvertex 1.689815 1.810828 0.972122\nendloop\nendfacet\nfacet normal 0.054321 -0.000385 0.998523\nouter loop\nvertex 50.247066 -0.515539 4.374654\nvertex 51.737465 0.086181 4.293806\nvertex 51.157322 0.422284 4.325496\nendloop\nendfacet\nfacet normal 0.099741 -0.044705 0.994009\nouter loop\nvertex 50.247066 -0.515539 4.374654\nvertex 51.157322 0.422284 4.325496\nvertex 49.893200 0.184938 4.441665\nendloop\nendfacet\nfacet normal 0.091326 0.179932 0.979430\nouter loop\nvertex 52.664707 0.710669 4.131961\nvertex 51.443138 0.940804 4.203588\nvertex 51.157322 0.422284 4.325496\nendloop\nendfacet\nfacet normal 0.108925 0.094716 0.989527\nouter loop\nvertex 52.664707 0.710669 4.131961\nvertex 51.157322 0.422284 4.325496\nvertex 51.737465 0.086181 4.293806\nendloop\nendfacet\nfacet normal 0.064417 0.140482 0.987985\nouter loop\nvertex 49.633720 0.952742 4.349410\nvertex 49.893200 0.184938 4.441665\nvertex 51.157322 0.422284 4.325496\nendloop\nendfacet\nfacet normal 0.080147 0.186057 0.979265\nouter loop\nvertex 49.633720 0.952742 4.349410\nvertex 51.157322 0.422284 4.325496\nvertex 51.443138 0.940804 4.203588\nendloop\nendfacet\nfacet normal -0.018545 -0.272988 0.961839\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 50.865345 -1.042833 4.236919\nvertex 50.247066 -0.515539 4.374654\nendloop\nendfacet\nfacet normal 0.176459 -0.509150 0.842394\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 50.247066 -0.515539 4.374654\nvertex 47.781036 -1.082973 4.548262\nendloop\nendfacet\nfacet normal 0.012548 -0.059983 0.998121\nouter loop\nvertex 50.865345 -1.042833 4.236919\nvertex 52.331310 -0.308579 4.262618\nvertex 51.737465 0.086181 4.293806\nendloop\nendfacet\nfacet normal 0.106815 -0.132165 0.985456\nouter loop\nvertex 50.865345 -1.042833 4.236919\nvertex 51.737465 0.086181 4.293806\nvertex 50.247066 -0.515539 4.374654\nendloop\nendfacet\nfacet normal 0.082388 -0.053580 0.995159\nouter loop\nvertex 47.781036 -1.082973 4.548262\nvertex 50.247066 -0.515539 4.374654\nvertex 49.893200 0.184938 4.441665\nendloop\nendfacet\nfacet normal 0.137683 -0.147011 0.979506\nouter loop\nvertex 47.781036 -1.082973 4.548262\nvertex 49.893200 0.184938 4.441665\nvertex 47.583881 -0.209556 4.707063\nendloop\nendfacet\nfacet normal 0.114295 0.437116 0.892114\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 53.066593 1.283501 3.799797\nvertex 52.664707 0.710669 4.131961\nendloop\nendfacet\nfacet normal 0.137123 0.321287 0.937002\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 52.664707 0.710669 4.131961\nvertex 53.516247 0.366665 4.125300\nendloop\nendfacet\nfacet normal 0.125353 0.448738 0.884828\nouter loop\nvertex 53.066593 1.283501 3.799797\nvertex 51.558132 1.499486 3.903964\nvertex 51.443138 0.940804 4.203588\nendloop\nendfacet\nfacet normal 0.132709 0.425872 0.894998\nouter loop\nvertex 53.066593 1.283501 3.799797\nvertex 51.443138 0.940804 4.203588\nvertex 52.664707 0.710669 4.131961\nendloop\nendfacet\nfacet normal 0.069339 0.152545 0.985861\nouter loop\nvertex 53.516247 0.366665 4.125300\nvertex 52.664707 0.710669 4.131961\nvertex 51.737465 0.086181 4.293806\nendloop\nendfacet\nfacet normal 0.086202 0.051068 0.994968\nouter loop\nvertex 53.516247 0.366665 4.125300\nvertex 51.737465 0.086181 4.293806\nvertex 52.331310 -0.308579 4.262618\nendloop\nendfacet\nfacet normal 0.076994 0.391550 0.916930\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 46.970215 0.694892 4.683170\nvertex 49.633720 0.952742 4.349410\nendloop\nendfacet\nfacet normal 0.087657 0.447287 0.890085\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 49.633720 0.952742 4.349410\nvertex 49.445156 1.646948 4.019125\nendloop\nendfacet\nfacet normal 0.098039 0.092693 0.990856\nouter loop\nvertex 46.970215 0.694892 4.683170\nvertex 47.583881 -0.209556 4.707063\nvertex 49.893200 0.184938 4.441665\nendloop\nendfacet\nfacet normal 0.108100 0.154533 0.982056\nouter loop\nvertex 46.970215 0.694892 4.683170\nvertex 49.893200 0.184938 4.441665\nvertex 49.633720 0.952742 4.349410\nendloop\nendfacet\nfacet normal 0.074857 0.444928 0.892432\nouter loop\nvertex 49.445156 1.646948 4.019125\nvertex 49.633720 0.952742 4.349410\nvertex 51.443138 0.940804 4.203588\nendloop\nendfacet\nfacet normal 0.080225 0.458227 0.885207\nouter loop\nvertex 49.445156 1.646948 4.019125\nvertex 51.443138 0.940804 4.203588\nvertex 51.558132 1.499486 3.903964\nendloop\nendfacet\nfacet normal -0.485056 -0.030205 0.873961\nouter loop\nvertex 0.883993 -0.216975 5.304646\nvertex 1.361070 0.453238 5.592591\nvertex 1.118056 0.746528 5.467853\nendloop\nendfacet\nfacet normal -0.533801 -0.013542 0.845501\nouter loop\nvertex 0.883993 -0.216975 5.304646\nvertex 1.118056 0.746528 5.467853\nvertex 0.761446 0.434430 5.237710\nendloop\nendfacet\nfacet normal -0.291023 0.241946 0.925618\nouter loop\nvertex 1.958024 1.200380 5.613314\nvertex 1.345271 1.293371 5.396353\nvertex 1.118056 0.746528 5.467853\nendloop\nendfacet\nfacet normal -0.263567 0.184324 0.946867\nouter loop\nvertex 1.958024 1.200380 5.613314\nvertex 1.118056 0.746528 5.467853\nvertex 1.361070 0.453238 5.592591\nendloop\nendfacet\nfacet normal -0.665781 0.239685 0.706602\nouter loop\nvertex 0.832530 1.140606 5.065147\nvertex 0.761446 0.434430 5.237710\nvertex 1.118056 0.746528 5.467853\nendloop\nendfacet\nfacet normal -0.579649 0.337804 0.741549\nouter loop\nvertex 0.832530 1.140606 5.065147\nvertex 1.118056 0.746528 5.467853\nvertex 1.345271 1.293371 5.396353\nendloop\nendfacet\nfacet normal -0.728589 -0.294154 0.618572\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 1.153953 -0.776505 5.356543\nvertex 0.883993 -0.216975 5.304646\nendloop\nendfacet\nfacet normal -0.559611 -0.364320 0.744383\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 0.883993 -0.216975 5.304646\nvertex 0.537691 -0.780122 4.768686\nendloop\nendfacet\nfacet normal -0.428798 -0.100120 0.897835\nouter loop\nvertex 1.153953 -0.776505 5.356543\nvertex 1.693982 0.028935 5.704272\nvertex 1.361070 0.453238 5.592591\nendloop\nendfacet\nfacet normal -0.398405 -0.107739 0.910860\nouter loop\nvertex 1.153953 -0.776505 5.356543\nvertex 1.361070 0.453238 5.592591\nvertex 0.883993 -0.216975 5.304646\nendloop\nendfacet\nfacet normal -0.792535 -0.087077 0.603578\nouter loop\nvertex 0.537691 -0.780122 4.768686\nvertex 0.883993 -0.216975 5.304646\nvertex 0.761446 0.434430 5.237710\nendloop\nendfacet\nfacet normal -0.749797 -0.113591 0.651845\nouter loop\nvertex 0.537691 -0.780122 4.768686\nvertex 0.761446 0.434430 5.237710\nvertex 0.423611 0.000000 4.773408\nendloop\nendfacet\nfacet normal -0.108158 0.511312 0.852562\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 2.553637 1.874253 5.284729\nvertex 1.958024 1.200380 5.613314\nendloop\nendfacet\nfacet normal -0.072594 0.396995 0.914945\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 1.958024 1.200380 5.613314\nvertex 2.557282 0.880763 5.799543\nendloop\nendfacet\nfacet normal -0.194633 0.559673 0.805533\nouter loop\nvertex 2.553637 1.874253 5.284729\nvertex 1.664815 1.871528 5.071865\nvertex 1.345271 1.293371 5.396353\nendloop\nendfacet\nfacet normal -0.197768 0.565292 0.800832\nouter loop\nvertex 2.553637 1.874253 5.284729\nvertex 1.345271 1.293371 5.396353\nvertex 1.958024 1.200380 5.613314\nendloop\nendfacet\nfacet normal -0.220066 0.149091 0.964024\nouter loop\nvertex 2.557282 0.880763 5.799543\nvertex 1.958024 1.200380 5.613314\nvertex 1.361070 0.453238 5.592591\nendloop\nendfacet\nfacet normal -0.203227 0.096995 0.974316\nouter loop\nvertex 2.557282 0.880763 5.799543\nvertex 1.361070 0.453238 5.592591\nvertex 1.693982 0.028935 5.704272\nendloop\nendfacet\nfacet normal -0.838045 0.384748 0.386846\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.439913 0.780122 4.573130\nvertex 0.832530 1.140606 5.065147\nendloop\nendfacet\nfacet normal -0.759342 0.501413 0.414710\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.832530 1.140606 5.065147\nvertex 1.052529 1.776505 4.699124\nendloop\nendfacet\nfacet normal -0.859391 0.143921 0.490647\nouter loop\nvertex 0.439913 0.780122 4.573130\nvertex 0.423611 0.000000 4.773408\nvertex 0.761446 0.434430 5.237710\nendloop\nendfacet\nfacet normal -0.833280 0.208954 0.511842\nouter loop\nvertex 0.439913 0.780122 4.573130\nvertex 0.761446 0.434430 5.237710\nvertex 0.832530 1.140606 5.065147\nendloop\nendfacet\nfacet normal -0.562590 0.549949 0.617291\nouter loop\nvertex 1.052529 1.776505 4.699124\nvertex 0.832530 1.140606 5.065147\nvertex 1.345271 1.293371 5.396353\nendloop\nendfacet\nfacet normal -0.477260 0.615689 0.627017\nouter loop\nvertex 1.052529 1.776505 4.699124\nvertex 1.345271 1.293371 5.396353\nvertex 1.664815 1.871528 5.071865\nendloop\nendfacet\nfacet normal 0.021991 -0.005668 -0.999742\nouter loop\nvertex 12.125395 -0.422749 0.552052\nvertex 10.102764 0.354268 0.503155\nvertex 10.985365 0.736143 0.520405\nendloop\nendfacet\nfacet normal -0.005850 -0.033048 -0.999437\nouter loop\nvertex 12.125395 -0.422749 0.552052\nvertex 10.985365 0.736143 0.520405\nvertex 12.626919 0.410041 0.521579\nendloop\nendfacet\nfacet normal -0.012352 0.221554 -0.975070\nouter loop\nvertex 8.320804 1.187877 0.656801\nvertex 10.215493 1.381170 0.676720\nvertex 10.985365 0.736143 0.520405\nendloop\nendfacet\nfacet normal -0.031048 0.116599 -0.992694\nouter loop\nvertex 8.320804 1.187877 0.656801\nvertex 10.985365 0.736143 0.520405\nvertex 10.102764 0.354268 0.503155\nendloop\nendfacet\nfacet normal 0.043132 0.213605 -0.975968\nouter loop\nvertex 12.492224 1.328601 0.716666\nvertex 12.626919 0.410041 0.521579\nvertex 10.985365 0.736143 0.520405\nendloop\nendfacet\nfacet normal 0.022964 0.261264 -0.964994\nouter loop\nvertex 12.492224 1.328601 0.716666\nvertex 10.985365 0.736143 0.520405\nvertex 10.215493 1.381170 0.676720\nendloop\nendfacet\nfacet normal 0.112351 -0.356707 -0.927436\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 11.022995 -1.088743 0.674657\nvertex 12.125395 -0.422749 0.552052\nendloop\nendfacet\nfacet normal -0.085839 -0.463142 -0.882117\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 12.125395 -0.422749 0.552052\nvertex 14.364196 -1.103987 0.691866\nendloop\nendfacet\nfacet normal 0.032697 -0.097371 -0.994711\nouter loop\nvertex 11.022995 -1.088743 0.674657\nvertex 8.954733 -0.142490 0.514045\nvertex 10.102764 0.354268 0.503155\nendloop\nendfacet\nfacet normal -0.028179 -0.135674 -0.990353\nouter loop\nvertex 11.022995 -1.088743 0.674657\nvertex 10.102764 0.354268 0.503155\nvertex 12.125395 -0.422749 0.552052\nendloop\nendfacet\nfacet normal 0.043243 -0.062528 -0.997106\nouter loop\nvertex 14.364196 -1.103987 0.691866\nvertex 12.125395 -0.422749 0.552052\nvertex 12.626919 0.410041 0.521579\nendloop\nendfacet\nfacet normal -0.019751 -0.134098 -0.990771\nouter loop\nvertex 14.364196 -1.103987 0.691866\nvertex 12.626919 0.410041 0.521579\nvertex 14.778099 -0.081578 0.545235\nendloop\nendfacet\nfacet normal -0.032263 0.478369 -0.877566\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 6.835030 1.918170 1.109513\nvertex 8.320804 1.187877 0.656801\nendloop\nendfacet\nfacet normal -0.062221 0.329100 -0.942243\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 8.320804 1.187877 0.656801\nvertex 6.811232 0.793336 0.618684\nendloop\nendfacet\nfacet normal -0.027146 0.518106 -0.854885\nouter loop\nvertex 6.835030 1.918170 1.109513\nvertex 9.145125 2.041365 1.110822\nvertex 10.215493 1.381170 0.676720\nendloop\nendfacet\nfacet normal -0.038536 0.468681 -0.882526\nouter loop\nvertex 6.835030 1.918170 1.109513\nvertex 10.215493 1.381170 0.676720\nvertex 8.320804 1.187877 0.656801\nendloop\nendfacet\nfacet normal -0.014535 0.151107 -0.988411\nouter loop\nvertex 6.811232 0.793336 0.618684\nvertex 8.320804 1.187877 0.656801\nvertex 10.102764 0.354268 0.503155\nendloop\nendfacet\nfacet normal -0.029022 0.045179 -0.998557\nouter loop\nvertex 6.811232 0.793336 0.618684\nvertex 10.102764 0.354268 0.503155\nvertex 8.954733 -0.142490 0.514045\nendloop\nendfacet\nfacet normal 0.067961 0.508823 -0.858184\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 15.017767 0.994756 0.718727\nvertex 12.492224 1.328601 0.716666\nendloop\nendfacet\nfacet normal 0.040768 0.564627 -0.824339\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 12.492224 1.328601 0.716666\nvertex 11.705572 2.128252 1.225479\nendloop\nendfacet\nfacet normal 0.044961 0.149207 -0.987783\nouter loop\nvertex 15.017767 0.994756 0.718727\nvertex 14.778099 -0.081578 0.545235\nvertex 12.626919 0.410041 0.521579\nendloop\nendfacet\nfacet normal 0.028781 0.211701 -0.976911\nouter loop\nvertex 15.017767 0.994756 0.718727\nvertex 12.626919 0.410041 0.521579\nvertex 12.492224 1.328601 0.716666\nendloop\nendfacet\nfacet normal 0.027410 0.555686 -0.830940\nouter loop\nvertex 11.705572 2.128252 1.225479\nvertex 12.492224 1.328601 0.716666\nvertex 10.215493 1.381170 0.676720\nendloop\nendfacet\nfacet normal 0.017508 0.568987 -0.822160\nouter loop\nvertex 11.705572 2.128252 1.225479\nvertex 10.215493 1.381170 0.676720\nvertex 9.145125 2.041365 1.110822\nendloop\nendfacet\nfacet normal -0.262091 0.964859 0.018878\nouter loop\nvertex 0.832788 2.175980 2.905423\nvertex 1.345435 2.325378 2.386925\nvertex 1.119097 2.270641 2.042254\nendloop\nendfacet\nfacet normal -0.340166 0.940315 -0.009710\nouter loop\nvertex 0.832788 2.175980 2.905423\nvertex 1.119097 2.270641 2.042254\nvertex 0.763476 2.143866 2.223727\nendloop\nendfacet\nfacet normal -0.045910 0.971407 -0.232939\nouter loop\nvertex 1.958174 2.226874 1.694363\nvertex 1.362232 2.158928 1.528469\nvertex 1.119097 2.270641 2.042254\nendloop\nendfacet\nfacet normal -0.010634 0.988625 -0.150022\nouter loop\nvertex 1.958174 2.226874 1.694363\nvertex 1.119097 2.270641 2.042254\nvertex 1.345435 2.325378 2.386925\nendloop\nendfacet\nfacet normal -0.452941 0.839023 -0.301470\nouter loop\nvertex 0.886872 1.968978 1.551597\nvertex 0.763476 2.143866 2.223727\nvertex 1.119097 2.270641 2.042254\nendloop\nendfacet\nfacet normal -0.361419 0.860851 -0.358207\nouter loop\nvertex 0.886872 1.968978 1.551597\nvertex 1.119097 2.270641 2.042254\nvertex 1.362232 2.158928 1.528469\nendloop\nendfacet\nfacet normal -0.643293 0.728833 0.234471\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 1.052529 2.154190 3.576036\nvertex 0.832788 2.175980 2.905423\nendloop\nendfacet\nfacet normal -0.634599 0.734736 0.239681\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.832788 2.175980 2.905423\nvertex 0.440260 1.766233 3.122204\nendloop\nendfacet\nfacet normal -0.195052 0.976419 0.092523\nouter loop\nvertex 1.052529 2.154190 3.576036\nvertex 1.664815 2.340921 2.896196\nvertex 1.345435 2.325378 2.386925\nendloop\nendfacet\nfacet normal -0.189796 0.977318 0.093947\nouter loop\nvertex 1.052529 2.154190 3.576036\nvertex 1.345435 2.325378 2.386925\nvertex 0.832788 2.175980 2.905423\nendloop\nendfacet\nfacet normal -0.711112 0.701984 0.039233\nouter loop\nvertex 0.440260 1.766233 3.122204\nvertex 0.832788 2.175980 2.905423\nvertex 0.763476 2.143866 2.223727\nendloop\nendfacet\nfacet normal -0.719474 0.693746 0.032763\nouter loop\nvertex 0.440260 1.766233 3.122204\nvertex 0.763476 2.143866 2.223727\nvertex 0.426389 1.789352 2.328038\nendloop\nendfacet\nfacet normal 0.054097 0.884757 -0.462903\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 2.556761 1.841754 1.028229\nvertex 1.958174 2.226874 1.694363\nendloop\nendfacet\nfacet normal 0.115189 0.957054 -0.266045\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 1.958174 2.226874 1.694363\nvertex 2.553637 2.266812 2.095851\nendloop\nendfacet\nfacet normal 0.003942 0.848771 -0.528746\nouter loop\nvertex 2.556761 1.841754 1.028229\nvertex 1.689815 1.810828 0.972122\nvertex 1.362232 2.158928 1.528469\nendloop\nendfacet\nfacet normal 0.032949 0.877804 -0.477886\nouter loop\nvertex 2.556761 1.841754 1.028229\nvertex 1.362232 2.158928 1.528469\nvertex 1.958174 2.226874 1.694363\nendloop\nendfacet\nfacet normal 0.017912 0.991964 -0.125243\nouter loop\nvertex 2.553637 2.266812 2.095851\nvertex 1.958174 2.226874 1.694363\nvertex 1.345435 2.325378 2.386925\nendloop\nendfacet\nfacet normal 0.035651 0.997968 -0.052815\nouter loop\nvertex 2.553637 2.266812 2.095851\nvertex 1.345435 2.325378 2.386925\nvertex 1.664815 2.340921 2.896196\nendloop\nendfacet\nfacet normal -0.624413 0.510585 -0.591110\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 0.541146 1.598091 1.596440\nvertex 0.886872 1.968978 1.551597\nendloop\nendfacet\nfacet normal -0.607987 0.516628 -0.602866\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 0.886872 1.968978 1.551597\nvertex 1.136574 1.600775 0.984242\nendloop\nendfacet\nfacet normal -0.735721 0.618057 -0.276983\nouter loop\nvertex 0.541146 1.598091 1.596440\nvertex 0.426389 1.789352 2.328038\nvertex 0.763476 2.143866 2.223727\nendloop\nendfacet\nfacet normal -0.716302 0.631929 -0.295934\nouter loop\nvertex 0.541146 1.598091 1.596440\nvertex 0.763476 2.143866 2.223727\nvertex 0.886872 1.968978 1.551597\nendloop\nendfacet\nfacet normal -0.319261 0.724598 -0.610762\nouter loop\nvertex 1.136574 1.600775 0.984242\nvertex 0.886872 1.968978 1.551597\nvertex 1.362232 2.158928 1.528469\nendloop\nendfacet\nfacet normal -0.289197 0.725664 -0.624321\nouter loop\nvertex 1.136574 1.600775 0.984242\nvertex 1.362232 2.158928 1.528469\nvertex 1.689815 1.810828 0.972122\nendloop\nendfacet\nfacet normal -0.098370 -0.991958 0.079637\nouter loop\nvertex 8.802366 -2.453447 5.302680\nvertex 10.254326 -2.673915 4.350039\nvertex 11.182098 -2.715471 4.978424\nendloop\nendfacet\nfacet normal -0.091691 -0.987867 0.125347\nouter loop\nvertex 8.802366 -2.453447 5.302680\nvertex 11.182098 -2.715471 4.978424\nvertex 10.676667 -2.563551 5.805993\nendloop\nendfacet\nfacet normal -0.068967 -0.996923 -0.037261\nouter loop\nvertex 12.164215 -2.729092 3.525036\nvertex 12.723382 -2.814001 4.761803\nvertex 11.182098 -2.715471 4.978424\nendloop\nendfacet\nfacet normal -0.035057 -0.999283 -0.014324\nouter loop\nvertex 12.164215 -2.729092 3.525036\nvertex 11.182098 -2.715471 4.978424\nvertex 10.254326 -2.673915 4.350039\nendloop\nendfacet\nfacet normal -0.102259 -0.987633 0.118849\nouter loop\nvertex 12.753977 -2.742223 6.108570\nvertex 10.676667 -2.563551 5.805993\nvertex 11.182098 -2.715471 4.978424\nendloop\nendfacet\nfacet normal -0.056085 -0.996942 0.054407\nouter loop\nvertex 12.753977 -2.742223 6.108570\nvertex 11.182098 -2.715471 4.978424\nvertex 12.723382 -2.814001 4.761803\nendloop\nendfacet\nfacet normal -0.137872 -0.950809 0.277406\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 7.178772 -2.418575 4.615271\nvertex 8.802366 -2.453447 5.302680\nendloop\nendfacet\nfacet normal -0.118476 -0.915260 0.385048\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 8.802366 -2.453447 5.302680\nvertex 8.131913 -1.975336 6.232861\nendloop\nendfacet\nfacet normal -0.078702 -0.995832 0.046086\nouter loop\nvertex 7.178772 -2.418575 4.615271\nvertex 9.061987 -2.615098 3.584776\nvertex 10.254326 -2.673915 4.350039\nendloop\nendfacet\nfacet normal -0.071898 -0.990218 0.119581\nouter loop\nvertex 7.178772 -2.418575 4.615271\nvertex 10.254326 -2.673915 4.350039\nvertex 8.802366 -2.453447 5.302680\nendloop\nendfacet\nfacet normal -0.151552 -0.919275 0.363271\nouter loop\nvertex 8.131913 -1.975336 6.232861\nvertex 8.802366 -2.453447 5.302680\nvertex 10.676667 -2.563551 5.805993\nendloop\nendfacet\nfacet normal -0.147266 -0.913073 0.380278\nouter loop\nvertex 8.131913 -1.975336 6.232861\nvertex 10.676667 -2.563551 5.805993\nvertex 10.391977 -2.143262 6.704890\nendloop\nendfacet\nfacet normal -0.087903 -0.950882 -0.296812\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 14.374381 -2.709676 2.808274\nvertex 12.164215 -2.729092 3.525036\nendloop\nendfacet\nfacet normal 0.069456 -0.971901 -0.224909\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 12.164215 -2.729092 3.525036\nvertex 11.040919 -2.582739 2.545703\nendloop\nendfacet\nfacet normal -0.064487 -0.992113 -0.107483\nouter loop\nvertex 14.374381 -2.709676 2.808274\nvertex 14.808001 -2.908951 4.387503\nvertex 12.723382 -2.814001 4.761803\nendloop\nendfacet\nfacet normal -0.011732 -0.997931 -0.063208\nouter loop\nvertex 14.374381 -2.709676 2.808274\nvertex 12.723382 -2.814001 4.761803\nvertex 12.164215 -2.729092 3.525036\nendloop\nendfacet\nfacet normal -0.062176 -0.995060 -0.077388\nouter loop\nvertex 11.040919 -2.582739 2.545703\nvertex 12.164215 -2.729092 3.525036\nvertex 10.254326 -2.673915 4.350039\nendloop\nendfacet\nfacet normal -0.013181 -0.998333 -0.056193\nouter loop\nvertex 11.040919 -2.582739 2.545703\nvertex 10.254326 -2.673915 4.350039\nvertex 9.061987 -2.615098 3.584776\nendloop\nendfacet\nfacet normal -0.251464 -0.923204 0.290621\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 12.673998 -2.361658 7.248292\nvertex 12.753977 -2.742223 6.108570\nendloop\nendfacet\nfacet normal -0.096803 -0.989875 0.103806\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 12.753977 -2.742223 6.108570\nvertex 14.999439 -2.963156 6.095771\nendloop\nendfacet\nfacet normal -0.175573 -0.911968 0.370795\nouter loop\nvertex 12.673998 -2.361658 7.248292\nvertex 10.391977 -2.143262 6.704890\nvertex 10.676667 -2.563551 5.805993\nendloop\nendfacet\nfacet normal -0.125769 -0.943605 0.306254\nouter loop\nvertex 12.673998 -2.361658 7.248292\nvertex 10.676667 -2.563551 5.805993\nvertex 12.753977 -2.742223 6.108570\nendloop\nendfacet\nfacet normal -0.097457 -0.993709 0.055176\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 12.753977 -2.742223 6.108570\nvertex 12.723382 -2.814001 4.761803\nendloop\nendfacet\nfacet normal -0.050154 -0.998401 -0.026060\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 12.723382 -2.814001 4.761803\nvertex 14.808001 -2.908951 4.387503\nendloop\nendfacet\nfacet normal -0.051461 -0.998001 -0.036676\nouter loop\nvertex 19.651859 -3.205200 6.661274\nvertex 21.579056 -3.249851 5.172173\nvertex 22.354593 -3.309949 5.719345\nendloop\nendfacet\nfacet normal -0.044917 -0.998832 -0.017805\nouter loop\nvertex 19.651859 -3.205200 6.661274\nvertex 22.354593 -3.309949 5.719345\nvertex 21.544149 -3.293628 6.848240\nendloop\nendfacet\nfacet normal -0.056996 -0.994801 -0.084395\nouter loop\nvertex 23.786083 -3.239633 3.923745\nvertex 23.963385 -3.355907 5.174582\nvertex 22.354593 -3.309949 5.719345\nendloop\nendfacet\nfacet normal -0.031831 -0.997414 -0.064435\nouter loop\nvertex 23.786083 -3.239633 3.923745\nvertex 22.354593 -3.309949 5.719345\nvertex 21.579056 -3.249851 5.172173\nendloop\nendfacet\nfacet normal -0.045489 -0.998799 -0.018217\nouter loop\nvertex 23.701311 -3.388976 6.689353\nvertex 21.544149 -3.293628 6.848240\nvertex 22.354593 -3.309949 5.719345\nendloop\nendfacet\nfacet normal -0.038154 -0.998868 -0.028407\nouter loop\nvertex 23.701311 -3.388976 6.689353\nvertex 22.354593 -3.309949 5.719345\nvertex 23.963385 -3.355907 5.174582\nendloop\nendfacet\nfacet normal -0.152695 -0.988014 -0.022656\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 15.539762 -2.781838 8.288755\nvertex 15.527050 -2.781158 8.344804\nendloop\nendfacet\nfacet normal -0.152690 -0.988015 -0.022633\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 15.527050 -2.781158 8.344804\nvertex 15.538308 -2.783193 8.357668\nendloop\nendfacet\nfacet normal -0.045050 -0.998122 -0.041513\nouter loop\nvertex 18.135849 -3.132686 6.091653\nvertex 20.531229 -3.172596 4.451771\nvertex 21.579056 -3.249851 5.172173\nendloop\nendfacet\nfacet normal -0.039722 -0.998980 -0.021454\nouter loop\nvertex 18.135849 -3.132686 6.091653\nvertex 21.579056 -3.249851 5.172173\nvertex 19.651859 -3.205200 6.661274\nendloop\nendfacet\nfacet normal -0.090711 -0.931835 -0.351362\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 26.704079 -3.180421 3.013374\nvertex 23.786083 -3.239633 3.923745\nendloop\nendfacet\nfacet normal 0.044079 -0.978215 -0.202863\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 23.786083 -3.239633 3.923745\nvertex 22.986065 -3.078571 2.973266\nendloop\nendfacet\nfacet normal -0.033742 -0.991793 -0.123322\nouter loop\nvertex 26.704079 -3.180421 3.013374\nvertex 26.492159 -3.367654 4.577150\nvertex 23.963385 -3.355907 5.174582\nendloop\nendfacet\nfacet normal -0.008305 -0.995781 -0.091387\nouter loop\nvertex 26.704079 -3.180421 3.013374\nvertex 23.963385 -3.355907 5.174582\nvertex 23.786083 -3.239633 3.923745\nendloop\nendfacet\nfacet normal -0.061262 -0.991309 -0.116416\nouter loop\nvertex 22.986065 -3.078571 2.973266\nvertex 23.786083 -3.239633 3.923745\nvertex 21.579056 -3.249851 5.172173\nendloop\nendfacet\nfacet normal -0.013958 -0.996152 -0.086525\nouter loop\nvertex 22.986065 -3.078571 2.973266\nvertex 21.579056 -3.249851 5.172173\nvertex 20.531229 -3.172596 4.451771\nendloop\nendfacet\nfacet normal -0.011662 -0.999648 -0.023841\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 23.701311 -3.388976 6.689353\nvertex 23.963385 -3.355907 5.174582\nendloop\nendfacet\nfacet normal -0.010755 -0.999608 -0.025868\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 23.963385 -3.355907 5.174582\nvertex 26.492159 -3.367654 4.577150\nendloop\nendfacet\nfacet normal 0.010801 0.002288 -0.999939\nouter loop\nvertex 24.168861 -0.458234 0.562916\nvertex 21.801546 0.458118 0.539441\nvertex 22.818352 0.906325 0.551450\nendloop\nendfacet\nfacet normal -0.019894 -0.028087 -0.999408\nouter loop\nvertex 24.168861 -0.458234 0.562916\nvertex 22.818352 0.906325 0.551450\nvertex 24.733583 0.530254 0.523895\nendloop\nendfacet\nfacet normal -0.028836 0.235589 -0.971425\nouter loop\nvertex 20.104874 1.469719 0.768631\nvertex 22.284901 1.664661 0.751195\nvertex 22.818352 0.906325 0.551450\nendloop\nendfacet\nfacet normal -0.050065 0.140071 -0.988875\nouter loop\nvertex 20.104874 1.469719 0.768631\nvertex 22.818352 0.906325 0.551450\nvertex 21.801546 0.458118 0.539441\nendloop\nendfacet\nfacet normal 0.021616 0.182112 -0.983040\nouter loop\nvertex 25.002594 1.567553 0.721974\nvertex 24.733583 0.530254 0.523895\nvertex 22.818352 0.906325 0.551450\nendloop\nendfacet\nfacet normal -0.001330 0.253837 -0.967246\nouter loop\nvertex 25.002594 1.567553 0.721974\nvertex 22.818352 0.906325 0.551450\nvertex 22.284901 1.664661 0.751195\nendloop\nendfacet\nfacet normal 0.088396 -0.283195 -0.954980\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 23.085478 -1.280291 0.706413\nvertex 24.168861 -0.458234 0.562916\nendloop\nendfacet\nfacet normal -0.068269 -0.447273 -0.891788\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 24.168861 -0.458234 0.562916\nvertex 27.419786 -1.179824 0.675958\nendloop\nendfacet\nfacet normal 0.026385 -0.076248 -0.996740\nouter loop\nvertex 23.085478 -1.280291 0.706413\nvertex 20.618484 -0.134188 0.553434\nvertex 21.801546 0.458118 0.539441\nendloop\nendfacet\nfacet normal -0.037858 -0.123208 -0.991658\nouter loop\nvertex 23.085478 -1.280291 0.706413\nvertex 21.801546 0.458118 0.539441\nvertex 24.168861 -0.458234 0.562916\nendloop\nendfacet\nfacet normal 0.023045 -0.052576 -0.998351\nouter loop\nvertex 27.419786 -1.179824 0.675958\nvertex 24.168861 -0.458234 0.562916\nvertex 24.733583 0.530254 0.523895\nendloop\nendfacet\nfacet normal -0.020444 -0.120370 -0.992518\nouter loop\nvertex 27.419786 -1.179824 0.675958\nvertex 24.733583 0.530254 0.523895\nvertex 27.720016 0.032394 0.522759\nendloop\nendfacet\nfacet normal -0.041999 0.539786 -0.840754\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 19.303099 2.379055 1.392499\nvertex 20.104874 1.469719 0.768631\nendloop\nendfacet\nfacet normal -0.082151 0.388844 -0.917634\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 20.104874 1.469719 0.768631\nvertex 18.347206 1.014438 0.733063\nendloop\nendfacet\nfacet normal -0.040911 0.567476 -0.822373\nouter loop\nvertex 19.303099 2.379055 1.392499\nvertex 21.998266 2.464462 1.317354\nvertex 22.284901 1.664661 0.751195\nendloop\nendfacet\nfacet normal -0.054321 0.531884 -0.845073\nouter loop\nvertex 19.303099 2.379055 1.392499\nvertex 22.284901 1.664661 0.751195\nvertex 20.104874 1.469719 0.768631\nendloop\nendfacet\nfacet normal -0.026364 0.178620 -0.983565\nouter loop\nvertex 18.347206 1.014438 0.733063\nvertex 20.104874 1.469719 0.768631\nvertex 21.801546 0.458118 0.539441\nendloop\nendfacet\nfacet normal -0.045141 0.066616 -0.996757\nouter loop\nvertex 18.347206 1.014438 0.733063\nvertex 21.801546 0.458118 0.539441\nvertex 20.618484 -0.134188 0.553434\nendloop\nendfacet\nfacet normal 0.023968 0.397051 -0.917484\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 28.402740 1.203649 0.653316\nvertex 25.002594 1.567553 0.721974\nendloop\nendfacet\nfacet normal -0.007408 0.544183 -0.838934\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 25.002594 1.567553 0.721974\nvertex 25.097067 2.476448 1.310704\nendloop\nendfacet\nfacet normal 0.016502 0.101261 -0.994723\nouter loop\nvertex 28.402740 1.203649 0.653316\nvertex 27.720016 0.032394 0.522759\nvertex 24.733583 0.530254 0.523895\nendloop\nendfacet\nfacet normal 0.000234 0.187509 -0.982263\nouter loop\nvertex 28.402740 1.203649 0.653316\nvertex 24.733583 0.530254 0.523895\nvertex 25.002594 1.567553 0.721974\nendloop\nendfacet\nfacet normal 0.010368 0.542868 -0.839754\nouter loop\nvertex 25.097067 2.476448 1.310704\nvertex 25.002594 1.567553 0.721974\nvertex 22.284901 1.664661 0.751195\nendloop\nendfacet\nfacet normal -0.003984 0.576812 -0.816867\nouter loop\nvertex 25.097067 2.476448 1.310704\nvertex 22.284901 1.664661 0.751195\nvertex 21.998266 2.464462 1.317354\nendloop\nendfacet\nfacet normal -0.214887 0.017602 0.976480\nouter loop\nvertex 6.192955 -0.172350 6.679617\nvertex 8.064869 0.641323 7.076889\nvertex 7.223382 0.924576 6.886603\nendloop\nendfacet\nfacet normal -0.166813 -0.029270 0.985554\nouter loop\nvertex 6.192955 -0.172350 6.679617\nvertex 7.223382 0.924576 6.886603\nvertex 5.782027 0.543884 6.631336\nendloop\nendfacet\nfacet normal -0.215357 0.333843 0.917698\nouter loop\nvertex 9.928230 1.566422 7.287859\nvertex 8.009556 1.544833 6.845456\nvertex 7.223382 0.924576 6.886603\nendloop\nendfacet\nfacet normal -0.176078 0.132208 0.975458\nouter loop\nvertex 9.928230 1.566422 7.287859\nvertex 7.223382 0.924576 6.886603\nvertex 8.064869 0.641323 7.076889\nendloop\nendfacet\nfacet normal -0.238549 0.279570 0.930019\nouter loop\nvertex 6.016459 1.322258 6.457483\nvertex 5.782027 0.543884 6.631336\nvertex 7.223382 0.924576 6.886603\nendloop\nendfacet\nfacet normal -0.215922 0.334532 0.917314\nouter loop\nvertex 6.016459 1.322258 6.457483\nvertex 7.223382 0.924576 6.886603\nvertex 8.009556 1.544833 6.845456\nendloop\nendfacet\nfacet normal -0.269489 -0.373729 0.887526\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 7.198318 -0.798686 6.721142\nvertex 6.192955 -0.172350 6.679617\nendloop\nendfacet\nfacet normal -0.043669 -0.483330 0.874349\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 6.192955 -0.172350 6.679617\nvertex 4.467706 -0.826319 6.231944\nendloop\nendfacet\nfacet normal -0.214387 -0.110735 0.970452\nouter loop\nvertex 7.198318 -0.798686 6.721142\nvertex 9.218365 0.199331 7.281278\nvertex 8.064869 0.641323 7.076889\nendloop\nendfacet\nfacet normal -0.138807 -0.157990 0.977636\nouter loop\nvertex 7.198318 -0.798686 6.721142\nvertex 8.064869 0.641323 7.076889\nvertex 6.192955 -0.172350 6.679617\nendloop\nendfacet\nfacet normal -0.227473 -0.065013 0.971612\nouter loop\nvertex 4.467706 -0.826319 6.231944\nvertex 6.192955 -0.172350 6.679617\nvertex 5.782027 0.543884 6.631336\nendloop\nendfacet\nfacet normal -0.144871 -0.146277 0.978578\nouter loop\nvertex 4.467706 -0.826319 6.231944\nvertex 5.782027 0.543884 6.631336\nvertex 4.185957 0.051183 6.321401\nendloop\nendfacet\nfacet normal -0.279639 0.728761 0.625068\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 11.587097 2.393663 7.065519\nvertex 9.928230 1.566422 7.287859\nendloop\nendfacet\nfacet normal -0.223054 0.171863 0.959536\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 9.928230 1.566422 7.287859\nvertex 11.600214 1.316005 7.721383\nendloop\nendfacet\nfacet normal -0.212020 0.723188 0.657302\nouter loop\nvertex 11.587097 2.393663 7.065519\nvertex 9.113427 2.193287 6.488069\nvertex 8.009556 1.544833 6.845456\nendloop\nendfacet\nfacet normal -0.187966 0.588312 0.786484\nouter loop\nvertex 11.587097 2.393663 7.065519\nvertex 8.009556 1.544833 6.845456\nvertex 9.928230 1.566422 7.287859\nendloop\nendfacet\nfacet normal -0.214757 0.215320 0.952637\nouter loop\nvertex 11.600214 1.316005 7.721383\nvertex 9.928230 1.566422 7.287859\nvertex 8.064869 0.641323 7.076889\nendloop\nendfacet\nfacet normal -0.177720 -0.008758 0.984042\nouter loop\nvertex 11.600214 1.316005 7.721383\nvertex 8.064869 0.641323 7.076889\nvertex 9.218365 0.199331 7.281278\nendloop\nendfacet\nfacet normal -0.251593 0.565476 0.785454\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 4.172165 0.918773 6.157211\nvertex 6.016459 1.322258 6.457483\nendloop\nendfacet\nfacet normal -0.181192 0.672813 0.717281\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 6.016459 1.322258 6.457483\nvertex 6.831068 2.026018 6.003131\nendloop\nendfacet\nfacet normal -0.239946 0.176832 0.954545\nouter loop\nvertex 4.172165 0.918773 6.157211\nvertex 4.185957 0.051183 6.321401\nvertex 5.782027 0.543884 6.631336\nendloop\nendfacet\nfacet normal -0.212574 0.273546 0.938075\nouter loop\nvertex 4.172165 0.918773 6.157211\nvertex 5.782027 0.543884 6.631336\nvertex 6.016459 1.322258 6.457483\nendloop\nendfacet\nfacet normal -0.211694 0.691156 0.691006\nouter loop\nvertex 6.831068 2.026018 6.003131\nvertex 6.016459 1.322258 6.457483\nvertex 8.009556 1.544833 6.845456\nendloop\nendfacet\nfacet normal -0.196068 0.707802 0.678655\nouter loop\nvertex 6.831068 2.026018 6.003131\nvertex 8.009556 1.544833 6.845456\nvertex 9.113427 2.193287 6.488069\nendloop\nendfacet\nfacet normal -0.055414 0.998326 -0.016585\nouter loop\nvertex 6.012343 2.489832 3.702746\nvertex 8.029861 2.588729 2.914806\nvertex 7.207201 2.535911 2.484139\nendloop\nendfacet\nfacet normal -0.027336 0.999566 0.010993\nouter loop\nvertex 6.012343 2.489832 3.702746\nvertex 7.207201 2.535911 2.484139\nvertex 5.726770 2.491796 2.814062\nendloop\nendfacet\nfacet normal -0.024669 0.979463 -0.200110\nouter loop\nvertex 9.997385 2.513603 2.030982\nvertex 8.029572 2.419185 1.811427\nvertex 7.207201 2.535911 2.484139\nendloop\nendfacet\nfacet normal -0.009050 0.994465 -0.104676\nouter loop\nvertex 9.997385 2.513603 2.030982\nvertex 7.207201 2.535911 2.484139\nvertex 8.029861 2.588729 2.914806\nendloop\nendfacet\nfacet normal -0.070899 0.979773 -0.187130\nouter loop\nvertex 6.012306 2.337867 1.899937\nvertex 5.726770 2.491796 2.814062\nvertex 7.207201 2.535911 2.484139\nendloop\nendfacet\nfacet normal -0.049233 0.972209 -0.228879\nouter loop\nvertex 6.012306 2.337867 1.899937\nvertex 7.207201 2.535911 2.484139\nvertex 8.029572 2.419185 1.811427\nendloop\nendfacet\nfacet normal -0.139711 0.969469 0.201520\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 6.835320 2.433162 4.545931\nvertex 6.012343 2.489832 3.702746\nendloop\nendfacet\nfacet normal 0.037649 0.932397 0.359469\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 6.012343 2.489832 3.702746\nvertex 4.161652 2.331292 4.307803\nendloop\nendfacet\nfacet normal -0.066258 0.996717 0.046537\nouter loop\nvertex 6.835320 2.433162 4.545931\nvertex 9.147440 2.632157 3.575842\nvertex 8.029861 2.588729 2.914806\nendloop\nendfacet\nfacet normal -0.016427 0.996414 0.083002\nouter loop\nvertex 6.835320 2.433162 4.545931\nvertex 8.029861 2.588729 2.914806\nvertex 6.012343 2.489832 3.702746\nendloop\nendfacet\nfacet normal -0.076614 0.996700 0.026822\nouter loop\nvertex 4.161652 2.331292 4.307803\nvertex 6.012343 2.489832 3.702746\nvertex 5.726770 2.491796 2.814062\nendloop\nendfacet\nfacet normal -0.014082 0.995638 0.092228\nouter loop\nvertex 4.161652 2.331292 4.307803\nvertex 5.726770 2.491796 2.814062\nvertex 4.101852 2.427727 3.257616\nendloop\nendfacet\nfacet normal -0.005546 0.897442 -0.441097\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 11.705572 2.128252 1.225479\nvertex 9.997385 2.513603 2.030982\nendloop\nendfacet\nfacet normal 0.014446 0.968220 -0.249682\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 9.997385 2.513603 2.030982\nvertex 11.713722 2.630891 2.585105\nendloop\nendfacet\nfacet normal -0.007990 0.874773 -0.484467\nouter loop\nvertex 11.705572 2.128252 1.225479\nvertex 9.145125 2.041365 1.110822\nvertex 8.029572 2.419185 1.811427\nendloop\nendfacet\nfacet normal 0.003950 0.905314 -0.424725\nouter loop\nvertex 11.705572 2.128252 1.225479\nvertex 8.029572 2.419185 1.811427\nvertex 9.997385 2.513603 2.030982\nendloop\nendfacet\nfacet normal -0.023563 0.990341 -0.136634\nouter loop\nvertex 11.713722 2.630891 2.585105\nvertex 9.997385 2.513603 2.030982\nvertex 8.029861 2.588729 2.914806\nendloop\nendfacet\nfacet normal -0.015034 0.999078 -0.040220\nouter loop\nvertex 11.713722 2.630891 2.585105\nvertex 8.029861 2.588729 2.914806\nvertex 9.147440 2.632157 3.575842\nendloop\nendfacet\nfacet normal -0.092009 0.897832 -0.430619\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 4.161652 2.306381 2.229715\nvertex 6.012306 2.337867 1.899937\nendloop\nendfacet\nfacet normal -0.047210 0.861043 -0.506335\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 6.012306 2.337867 1.899937\nvertex 6.835030 1.918170 1.109513\nendloop\nendfacet\nfacet normal -0.072084 0.990024 -0.121068\nouter loop\nvertex 4.161652 2.306381 2.229715\nvertex 4.101852 2.427727 3.257616\nvertex 5.726770 2.491796 2.814062\nendloop\nendfacet\nfacet normal -0.048911 0.982323 -0.180691\nouter loop\nvertex 4.161652 2.306381 2.229715\nvertex 5.726770 2.491796 2.814062\nvertex 6.012306 2.337867 1.899937\nendloop\nendfacet\nfacet normal -0.057052 0.855963 -0.513880\nouter loop\nvertex 6.835030 1.918170 1.109513\nvertex 6.012306 2.337867 1.899937\nvertex 8.029572 2.419185 1.811427\nendloop\nendfacet\nfacet normal -0.044906 0.847665 -0.528628\nouter loop\nvertex 6.835030 1.918170 1.109513\nvertex 8.029572 2.419185 1.811427\nvertex 9.145125 2.041365 1.110822\nendloop\nendfacet\nfacet normal 0.029138 -0.029900 -0.999128\nouter loop\nvertex 53.935028 0.015368 0.507757\nvertex 52.969692 0.580675 0.462687\nvertex 53.385418 0.730710 0.470321\nendloop\nendfacet\nfacet normal -0.019652 -0.067301 -0.997539\nouter loop\nvertex 53.935028 0.015368 0.507757\nvertex 53.385418 0.730710 0.470321\nvertex 54.087021 0.426941 0.476994\nendloop\nendfacet\nfacet normal 0.020521 0.271626 -0.962184\nouter loop\nvertex 52.143917 1.163148 0.565922\nvertex 53.116249 1.115542 0.573220\nvertex 53.385418 0.730710 0.470321\nendloop\nendfacet\nfacet normal -0.029884 0.133207 -0.990638\nouter loop\nvertex 52.143917 1.163148 0.565922\nvertex 53.385418 0.730710 0.470321\nvertex 52.969692 0.580675 0.462687\nendloop\nendfacet\nfacet normal 0.125923 0.269867 -0.954628\nouter loop\nvertex 54.058681 0.879590 0.601217\nvertex 54.087021 0.426941 0.476994\nvertex 53.385418 0.730710 0.470321\nendloop\nendfacet\nfacet normal 0.109944 0.327799 -0.938328\nouter loop\nvertex 54.058681 0.879590 0.601217\nvertex 53.385418 0.730710 0.470321\nvertex 53.116249 1.115542 0.573220\nendloop\nendfacet\nfacet normal 0.126970 -0.340753 -0.931540\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 53.526051 -0.368843 0.592556\nvertex 53.935028 0.015368 0.507757\nendloop\nendfacet\nfacet normal -0.228010 -0.620776 -0.750099\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 53.935028 0.015368 0.507757\nvertex 55.000008 -0.546875 0.649334\nendloop\nendfacet\nfacet normal 0.039999 -0.112360 -0.992862\nouter loop\nvertex 53.526051 -0.368843 0.592556\nvertex 52.409733 0.291152 0.472893\nvertex 52.969692 0.580675 0.462687\nendloop\nendfacet\nfacet normal -0.050105 -0.164103 -0.985170\nouter loop\nvertex 53.526051 -0.368843 0.592556\nvertex 52.969692 0.580675 0.462687\nvertex 53.935028 0.015368 0.507757\nendloop\nendfacet\nfacet normal 0.077576 -0.102770 -0.991676\nouter loop\nvertex 55.000008 -0.546875 0.649334\nvertex 53.935028 0.015368 0.507757\nvertex 54.087021 0.426941 0.476994\nendloop\nendfacet\nfacet normal -0.053575 -0.222505 -0.973459\nouter loop\nvertex 55.000008 -0.546875 0.649334\nvertex 54.087021 0.426941 0.476994\nvertex 55.000008 0.000000 0.524334\nendloop\nendfacet\nfacet normal 0.017534 0.550917 -0.834376\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 51.705059 1.646369 0.875757\nvertex 52.143917 1.163148 0.565922\nendloop\nendfacet\nfacet normal -0.043552 0.340707 -0.939160\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 52.143917 1.163148 0.565922\nvertex 51.159924 0.980571 0.545317\nendloop\nendfacet\nfacet normal 0.066111 0.620924 -0.781078\nouter loop\nvertex 51.705059 1.646369 0.875757\nvertex 52.962971 1.494856 0.861782\nvertex 53.116249 1.115542 0.573220\nendloop\nendfacet\nfacet normal 0.033673 0.560946 -0.827168\nouter loop\nvertex 51.705059 1.646369 0.875757\nvertex 53.116249 1.115542 0.573220\nvertex 52.143917 1.163148 0.565922\nendloop\nendfacet\nfacet normal -0.009333 0.161664 -0.986802\nouter loop\nvertex 51.159924 0.980571 0.545317\nvertex 52.143917 1.163148 0.565922\nvertex 52.969692 0.580675 0.462687\nendloop\nendfacet\nfacet normal -0.037392 0.037118 -0.998611\nouter loop\nvertex 51.159924 0.980571 0.545317\nvertex 52.969692 0.580675 0.462687\nvertex 52.409733 0.291152 0.472893\nendloop\nendfacet\nfacet normal 0.255913 0.616340 -0.744738\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 55.000008 0.546875 0.649334\nvertex 54.058681 0.879590 0.601217\nendloop\nendfacet\nfacet normal 0.250313 0.629107 -0.735913\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 54.058681 0.879590 0.601217\nvertex 54.016209 1.270190 0.920681\nendloop\nendfacet\nfacet normal 0.152927 0.220204 -0.963392\nouter loop\nvertex 55.000008 0.546875 0.649334\nvertex 55.000008 0.000000 0.524334\nvertex 54.087021 0.426941 0.476994\nendloop\nendfacet\nfacet normal 0.144186 0.270269 -0.951927\nouter loop\nvertex 55.000008 0.546875 0.649334\nvertex 54.087021 0.426941 0.476994\nvertex 54.058681 0.879590 0.601217\nendloop\nendfacet\nfacet normal 0.181146 0.634347 -0.751525\nouter loop\nvertex 54.016209 1.270190 0.920681\nvertex 54.058681 0.879590 0.601217\nvertex 53.116249 1.115542 0.573220\nendloop\nendfacet\nfacet normal 0.178378 0.640395 -0.747044\nouter loop\nvertex 54.016209 1.270190 0.920681\nvertex 53.116249 1.115542 0.573220\nvertex 52.962971 1.494856 0.861782\nendloop\nendfacet\nfacet normal 0.132022 -0.986409 0.097817\nouter loop\nvertex 51.965218 -1.882964 3.330094\nvertex 52.912369 -1.816551 2.721468\nvertex 53.356014 -1.733773 2.957440\nendloop\nendfacet\nfacet normal 0.148050 -0.975629 0.161953\nouter loop\nvertex 51.965218 -1.882964 3.330094\nvertex 53.356014 -1.733773 2.957440\nvertex 53.058926 -1.705439 3.399708\nendloop\nendfacet\nfacet normal 0.177278 -0.983315 -0.040787\nouter loop\nvertex 53.927742 -1.597909 2.166973\nvertex 54.082394 -1.592369 2.705612\nvertex 53.356014 -1.733773 2.957440\nendloop\nendfacet\nfacet normal 0.196776 -0.980100 -0.026136\nouter loop\nvertex 53.927742 -1.597909 2.166973\nvertex 53.356014 -1.733773 2.957440\nvertex 52.912369 -1.816551 2.721468\nendloop\nendfacet\nfacet normal 0.216482 -0.954187 0.206548\nouter loop\nvertex 54.051403 -1.504376 3.288356\nvertex 53.058926 -1.705439 3.399708\nvertex 53.356014 -1.733773 2.957440\nendloop\nendfacet\nfacet normal 0.241005 -0.957672 0.157423\nouter loop\nvertex 54.051403 -1.504376 3.288356\nvertex 53.356014 -1.733773 2.957440\nvertex 54.082394 -1.592369 2.705612\nendloop\nendfacet\nfacet normal 0.074341 -0.953236 0.292942\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 50.865349 -2.053394 3.054627\nvertex 51.965218 -1.882964 3.330094\nendloop\nendfacet\nfacet normal 0.086768 -0.920736 0.380415\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 51.965218 -1.882964 3.330094\nvertex 51.413963 -1.708487 3.878123\nendloop\nendfacet\nfacet normal 0.122716 -0.991214 0.049349\nouter loop\nvertex 50.865349 -2.053394 3.054627\nvertex 52.331310 -1.905801 2.373729\nvertex 52.912369 -1.816551 2.721468\nendloop\nendfacet\nfacet normal 0.129476 -0.987138 0.093775\nouter loop\nvertex 50.865349 -2.053394 3.054627\nvertex 52.912369 -1.816551 2.721468\nvertex 51.965218 -1.882964 3.330094\nendloop\nendfacet\nfacet normal 0.120734 -0.904347 0.409365\nouter loop\nvertex 51.413963 -1.708487 3.878123\nvertex 51.965218 -1.882964 3.330094\nvertex 53.058926 -1.705439 3.399708\nendloop\nendfacet\nfacet normal 0.123844 -0.898992 0.420092\nouter loop\nvertex 51.413963 -1.708487 3.878123\nvertex 53.058926 -1.705439 3.399708\nvertex 52.884544 -1.512283 3.864470\nendloop\nendfacet\nfacet normal 0.055707 -0.905175 -0.421374\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 55.000008 -1.281250 1.628500\nvertex 53.927742 -1.597909 2.166973\nendloop\nendfacet\nfacet normal 0.267480 -0.933803 -0.237626\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 53.927742 -1.597909 2.166973\nvertex 53.516243 -1.601796 1.719050\nendloop\nendfacet\nfacet normal 0.183430 -0.975007 -0.125357\nouter loop\nvertex 55.000008 -1.281250 1.628500\nvertex 55.000008 -1.375000 2.357667\nvertex 54.082394 -1.592369 2.705612\nendloop\nendfacet\nfacet normal 0.253503 -0.965290 -0.062857\nouter loop\nvertex 55.000008 -1.281250 1.628500\nvertex 54.082394 -1.592369 2.705612\nvertex 53.927742 -1.597909 2.166973\nendloop\nendfacet\nfacet normal 0.143887 -0.981837 -0.123667\nouter loop\nvertex 53.516243 -1.601796 1.719050\nvertex 53.927742 -1.597909 2.166973\nvertex 52.912369 -1.816551 2.721468\nendloop\nendfacet\nfacet normal 0.202054 -0.975479 -0.087260\nouter loop\nvertex 53.516243 -1.601796 1.719050\nvertex 52.912369 -1.816551 2.721468\nvertex 52.331310 -1.905801 2.373729\nendloop\nendfacet\nfacet normal 0.280961 -0.863225 0.419408\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 54.006409 -1.272369 3.796018\nvertex 54.051403 -1.504376 3.288356\nendloop\nendfacet\nfacet normal 0.289890 -0.867655 0.403905\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 54.051403 -1.504376 3.288356\nvertex 55.000008 -1.281250 3.086834\nendloop\nendfacet\nfacet normal 0.213291 -0.871231 0.442113\nouter loop\nvertex 54.006409 -1.272369 3.796018\nvertex 52.884544 -1.512283 3.864470\nvertex 53.058926 -1.705439 3.399708\nendloop\nendfacet\nfacet normal 0.225243 -0.878447 0.421421\nouter loop\nvertex 54.006409 -1.272369 3.796018\nvertex 53.058926 -1.705439 3.399708\nvertex 54.051403 -1.504376 3.288356\nendloop\nendfacet\nfacet normal 0.257717 -0.953272 0.157650\nouter loop\nvertex 55.000008 -1.281250 3.086834\nvertex 54.051403 -1.504376 3.288356\nvertex 54.082394 -1.592369 2.705612\nendloop\nendfacet\nfacet normal 0.272575 -0.954280 0.122692\nouter loop\nvertex 55.000008 -1.281250 3.086834\nvertex 54.082394 -1.592369 2.705612\nvertex 55.000008 -1.375000 2.357667\nendloop\nendfacet\nfacet normal 0.167439 0.067301 0.983583\nouter loop\nvertex 31.040508 -0.715920 7.494724\nvertex 35.292370 0.246160 6.705083\nvertex 33.537426 0.758488 6.968779\nendloop\nendfacet\nfacet normal 0.181584 0.042938 0.982438\nouter loop\nvertex 31.040508 -0.715920 7.494724\nvertex 33.537426 0.758488 6.968779\nvertex 30.348871 0.441312 7.571981\nendloop\nendfacet\nfacet normal 0.181361 0.207236 0.961333\nouter loop\nvertex 38.358265 1.213073 5.961304\nvertex 34.627728 1.534933 6.595708\nvertex 33.537426 0.758488 6.968779\nendloop\nendfacet\nfacet normal 0.188967 0.147609 0.970826\nouter loop\nvertex 38.358265 1.213073 5.961304\nvertex 33.537426 0.758488 6.968779\nvertex 35.292370 0.246160 6.705083\nendloop\nendfacet\nfacet normal 0.173255 0.117851 0.977801\nouter loop\nvertex 30.465677 1.665626 7.403723\nvertex 30.348871 0.441312 7.571981\nvertex 33.537426 0.758488 6.968779\nendloop\nendfacet\nfacet normal 0.192844 0.191595 0.962342\nouter loop\nvertex 30.465677 1.665626 7.403723\nvertex 33.537426 0.758488 6.968779\nvertex 34.627728 1.534933 6.595708\nendloop\nendfacet\nfacet normal 0.164600 0.019458 0.986168\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 37.555817 -0.354681 6.339149\nvertex 35.292370 0.246160 6.705083\nendloop\nendfacet\nfacet normal 0.184416 -0.008358 0.982813\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 35.292370 0.246160 6.705083\nvertex 31.040508 -0.715920 7.494724\nendloop\nendfacet\nfacet normal 0.162435 0.031240 0.986225\nouter loop\nvertex 26.000004 -1.750000 8.357668\nvertex 31.040508 -0.715920 7.494724\nvertex 30.348871 0.441312 7.571981\nendloop\nendfacet\nfacet normal 0.177786 0.000000 0.984069\nouter loop\nvertex 26.000004 -1.750000 8.357668\nvertex 30.348871 0.441312 7.571981\nvertex 26.000004 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.148415 0.534277 0.832178\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 39.717136 2.070559 5.168432\nvertex 38.358265 1.213073 5.961304\nendloop\nendfacet\nfacet normal 0.184967 0.343754 0.920663\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 38.358265 1.213073 5.961304\nvertex 41.577522 0.722469 5.497714\nendloop\nendfacet\nfacet normal 0.177666 0.526795 0.831217\nouter loop\nvertex 39.717136 2.070559 5.168432\nvertex 35.210911 2.342078 5.959519\nvertex 34.627728 1.534933 6.595708\nendloop\nendfacet\nfacet normal 0.187058 0.490538 0.851106\nouter loop\nvertex 39.717136 2.070559 5.168432\nvertex 34.627728 1.534933 6.595708\nvertex 38.358265 1.213073 5.961304\nendloop\nendfacet\nfacet normal 0.169836 0.203241 0.964287\nouter loop\nvertex 41.577522 0.722469 5.497714\nvertex 38.358265 1.213073 5.961304\nvertex 35.292370 0.246160 6.705083\nendloop\nendfacet\nfacet normal 0.181541 0.087342 0.979497\nouter loop\nvertex 41.577522 0.722469 5.497714\nvertex 35.292370 0.246160 6.705083\nvertex 37.555817 -0.354681 6.339149\nendloop\nendfacet\nfacet normal 0.177787 0.000000 0.984069\nouter loop\nvertex 26.000004 1.750000 8.357668\nvertex 26.000004 0.000000 8.357668\nvertex 30.348871 0.441312 7.571981\nendloop\nendfacet\nfacet normal 0.209605 0.113473 0.971180\nouter loop\nvertex 26.000004 1.750000 8.357668\nvertex 30.348871 0.441312 7.571981\nvertex 30.465677 1.665626 7.403723\nendloop\nendfacet\nfacet normal 0.184607 0.437281 0.880174\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 30.465677 1.665626 7.403723\nvertex 34.627728 1.534933 6.595708\nendloop\nendfacet\nfacet normal 0.202851 0.511551 0.834965\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 34.627728 1.534933 6.595708\nvertex 35.210911 2.342078 5.959519\nendloop\nendfacet\nfacet normal 0.081666 0.991806 0.098240\nouter loop\nvertex 38.388279 2.646122 4.363545\nvertex 35.528660 2.952158 3.651049\nvertex 33.655098 3.034144 4.380816\nendloop\nendfacet\nfacet normal 0.081322 0.985299 0.150242\nouter loop\nvertex 38.388279 2.646122 4.363545\nvertex 33.655098 3.034144 4.380816\nvertex 34.646252 2.840508 5.114205\nendloop\nendfacet\nfacet normal 0.054177 0.997517 -0.044985\nouter loop\nvertex 31.805523 3.078282 3.132048\nvertex 30.597834 3.201355 4.406643\nvertex 33.655098 3.034144 4.380816\nendloop\nendfacet\nfacet normal 0.036450 0.999161 -0.018671\nouter loop\nvertex 31.805523 3.078282 3.132048\nvertex 33.655098 3.034144 4.380816\nvertex 35.528660 2.952158 3.651049\nendloop\nendfacet\nfacet normal 0.087986 0.986031 0.141429\nouter loop\nvertex 30.497274 3.120947 5.740185\nvertex 34.646252 2.840508 5.114205\nvertex 33.655098 3.034144 4.380816\nendloop\nendfacet\nfacet normal 0.055040 0.996416 0.064231\nouter loop\nvertex 30.497274 3.120947 5.740185\nvertex 33.655098 3.034144 4.380816\nvertex 30.597834 3.201355 4.406643\nendloop\nendfacet\nfacet normal 0.115900 0.931453 0.344909\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 41.623692 2.542653 3.555777\nvertex 38.388279 2.646122 4.363545\nendloop\nendfacet\nfacet normal 0.110299 0.885594 0.451174\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 38.388279 2.646122 4.363545\nvertex 39.717136 2.070559 5.168432\nendloop\nendfacet\nfacet normal 0.067884 0.995692 0.063155\nouter loop\nvertex 41.623692 2.542653 3.555777\nvertex 37.925159 2.841050 2.826803\nvertex 35.528660 2.952158 3.651049\nendloop\nendfacet\nfacet normal 0.068602 0.986544 0.148409\nouter loop\nvertex 41.623692 2.542653 3.555777\nvertex 35.528660 2.952158 3.651049\nvertex 38.388279 2.646122 4.363545\nendloop\nendfacet\nfacet normal 0.131547 0.896208 0.423683\nouter loop\nvertex 39.717136 2.070559 5.168432\nvertex 38.388279 2.646122 4.363545\nvertex 34.646252 2.840508 5.114205\nendloop\nendfacet\nfacet normal 0.130413 0.889713 0.437496\nouter loop\nvertex 39.717136 2.070559 5.168432\nvertex 34.646252 2.840508 5.114205\nvertex 35.210911 2.342078 5.959519\nendloop\nendfacet\nfacet normal 0.039131 0.932981 -0.357793\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 27.830294 3.080580 2.703281\nvertex 31.805523 3.078282 3.132048\nendloop\nendfacet\nfacet normal -0.044689 0.954225 -0.295733\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 31.805523 3.078282 3.132048\nvertex 34.121059 2.869947 2.109917\nendloop\nendfacet\nfacet normal 0.038652 0.990359 -0.133021\nouter loop\nvertex 27.830294 3.080580 2.703281\nvertex 26.798485 3.337256 4.314457\nvertex 30.597834 3.201355 4.406643\nendloop\nendfacet\nfacet normal 0.009935 0.996178 -0.086776\nouter loop\nvertex 27.830294 3.080580 2.703281\nvertex 30.597834 3.201355 4.406643\nvertex 31.805523 3.078282 3.132048\nendloop\nendfacet\nfacet normal 0.047068 0.994265 -0.096028\nouter loop\nvertex 34.121059 2.869947 2.109917\nvertex 31.805523 3.078282 3.132048\nvertex 35.528660 2.952158 3.651049\nendloop\nendfacet\nfacet normal 0.021258 0.997134 -0.072607\nouter loop\nvertex 34.121059 2.869947 2.109917\nvertex 35.528660 2.952158 3.651049\nvertex 37.925159 2.841050 2.826803\nendloop\nendfacet\nfacet normal 0.149574 0.892197 0.426161\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 35.210911 2.342078 5.959519\nvertex 34.646252 2.840508 5.114205\nendloop\nendfacet\nfacet normal 0.116003 0.928432 0.352926\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 34.646252 2.840508 5.114205\nvertex 30.497274 3.120947 5.740185\nendloop\nendfacet\nfacet normal 0.073450 0.995143 0.065542\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 30.497274 3.120947 5.740185\nvertex 30.597834 3.201355 4.406643\nendloop\nendfacet\nfacet normal 0.036465 0.998875 -0.030321\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 30.597834 3.201355 4.406643\nvertex 26.798485 3.337256 4.314457\nendloop\nendfacet\nfacet normal -0.040504 0.998778 -0.028303\nouter loop\nvertex 21.356569 3.284150 6.661976\nvertex 19.487246 3.166282 5.177697\nvertex 18.679420 3.148952 5.722180\nendloop\nendfacet\nfacet normal -0.045724 0.998864 -0.013447\nouter loop\nvertex 21.356569 3.284150 6.661976\nvertex 18.679420 3.148952 5.722180\nvertex 19.461210 3.199903 6.848686\nendloop\nendfacet\nfacet normal -0.036095 0.997273 -0.064373\nouter loop\nvertex 17.431246 2.988852 3.941785\nvertex 17.108587 3.057137 5.180579\nvertex 18.679420 3.148952 5.722180\nendloop\nendfacet\nfacet normal -0.055571 0.997166 -0.050709\nouter loop\nvertex 17.431246 2.988852 3.941785\nvertex 18.679420 3.148952 5.722180\nvertex 19.487246 3.166282 5.177697\nendloop\nendfacet\nfacet normal -0.045336 0.998878 -0.013715\nouter loop\nvertex 17.307825 3.099989 6.690114\nvertex 19.461210 3.199903 6.848686\nvertex 18.679420 3.148952 5.722180\nendloop\nendfacet\nfacet normal -0.050904 0.998469 -0.021626\nouter loop\nvertex 17.307825 3.099989 6.690114\nvertex 18.679420 3.148952 5.722180\nvertex 17.108587 3.057137 5.180579\nendloop\nendfacet\nfacet normal -0.044284 0.998359 -0.036314\nouter loop\nvertex 22.875492 3.349853 6.092598\nvertex 20.559479 3.187713 4.459331\nvertex 19.487246 3.166282 5.177697\nendloop\nendfacet\nfacet normal -0.049537 0.998629 -0.016914\nouter loop\nvertex 22.875492 3.349853 6.092598\nvertex 19.487246 3.166282 5.177697\nvertex 21.356569 3.284150 6.661976\nendloop\nendfacet\nfacet normal 0.027002 0.955533 -0.293645\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 15.109202 2.798170 3.107773\nvertex 17.431246 2.988852 3.941785\nendloop\nendfacet\nfacet normal -0.116626 0.975840 -0.184755\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 17.431246 2.988852 3.941785\nvertex 18.347837 2.920243 3.000808\nendloop\nendfacet\nfacet normal -0.034878 0.995267 -0.090702\nouter loop\nvertex 15.109202 2.798170 3.107773\nvertex 15.010111 2.935162 4.649097\nvertex 17.108587 3.057137 5.180579\nendloop\nendfacet\nfacet normal -0.056758 0.995953 -0.069682\nouter loop\nvertex 15.109202 2.798170 3.107773\nvertex 17.108587 3.057137 5.180579\nvertex 17.431246 2.988852 3.941785\nendloop\nendfacet\nfacet normal -0.026645 0.994781 -0.098487\nouter loop\nvertex 18.347837 2.920243 3.000808\nvertex 17.431246 2.988852 3.941785\nvertex 19.487246 3.166282 5.177697\nendloop\nendfacet\nfacet normal -0.070482 0.994650 -0.075527\nouter loop\nvertex 18.347837 2.920243 3.000808\nvertex 19.487246 3.166282 5.177697\nvertex 20.559479 3.187713 4.459331\nendloop\nendfacet\nfacet normal -0.152667 0.987945 0.025655\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 15.538307 2.783193 8.357668\nvertex 15.527117 2.781798 8.344819\nendloop\nendfacet\nfacet normal -0.134205 0.983559 0.120833\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 15.527117 2.781798 8.344819\nvertex 15.437763 2.799557 8.101022\nendloop\nendfacet\nfacet normal -0.056032 0.998429 -0.000117\nouter loop\nvertex 17.658047 3.119799 8.010885\nvertex 17.307825 3.099989 6.690114\nvertex 14.959599 2.968169 6.376157\nendloop\nendfacet\nfacet normal -0.149732 0.976245 0.156610\nouter loop\nvertex 17.098806 3.033245 8.015749\nvertex 17.658047 3.119799 8.010885\nvertex 14.959599 2.968169 6.376157\nendloop\nendfacet\nfacet normal -0.071194 0.990627 0.116577\nouter loop\nvertex 14.959599 2.968169 6.376157\nvertex 15.458333 2.770834 8.357668\nvertex 15.437763 2.799557 8.101022\nendloop\nendfacet\nfacet normal -0.146431 0.977434 0.152256\nouter loop\nvertex 16.196001 2.892864 8.048681\nvertex 17.098806 3.033245 8.015749\nvertex 14.959599 2.968169 6.376157\nendloop\nendfacet\nfacet normal -0.112465 0.985441 0.127508\nouter loop\nvertex 15.437763 2.799557 8.101022\nvertex 16.196001 2.892864 8.048681\nvertex 14.959599 2.968169 6.376157\nendloop\nendfacet\nfacet normal -0.053193 0.998357 -0.021320\nouter loop\nvertex 14.959599 2.968169 6.376157\nvertex 17.307825 3.099989 6.690114\nvertex 17.108587 3.057137 5.180579\nendloop\nendfacet\nfacet normal -0.052808 0.998392 -0.020625\nouter loop\nvertex 14.959599 2.968169 6.376157\nvertex 17.108587 3.057137 5.180579\nvertex 15.010111 2.935162 4.649097\nendloop\nendfacet\nfacet normal 0.000002 0.000000 1.000000\nouter loop\nvertex 15.000001 -1.500000 8.357668\nvertex 15.458335 -2.770834 8.357668\nvertex 15.533590 -2.727700 8.357668\nendloop\nendfacet\nfacet normal -0.000003 0.000000 1.000000\nouter loop\nvertex 15.000001 -1.500000 8.357668\nvertex 15.533590 -2.727700 8.357668\nvertex 15.518668 -2.552154 8.357668\nendloop\nendfacet\nfacet normal 0.000002 0.000000 1.000000\nouter loop\nvertex 15.434759 -1.559115 8.357668\nvertex 15.427221 -1.296539 8.357668\nvertex 15.000001 -1.500000 8.357668\nendloop\nendfacet\nfacet normal 0.000003 0.000000 1.000000\nouter loop\nvertex 15.518668 -2.552154 8.357668\nvertex 15.434759 -1.559115 8.357668\nvertex 15.000001 -1.500000 8.357668\nendloop\nendfacet\nfacet normal -0.000001 0.000000 1.000000\nouter loop\nvertex 15.000001 0.000000 8.357668\nvertex 15.000001 -1.500000 8.357668\nvertex 15.427221 -1.296539 8.357668\nendloop\nendfacet\nfacet normal 0.000005 0.000000 1.000000\nouter loop\nvertex 15.000001 0.000000 8.357668\nvertex 15.427221 -1.296539 8.357668\nvertex 15.402760 -0.736852 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.398325 0.000000 8.357668\nvertex 15.399197 0.125639 8.357668\nvertex 15.000001 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.402760 -0.736852 8.357668\nvertex 15.398325 0.000000 8.357668\nvertex 15.000001 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.538307 2.783193 8.357668\nvertex 15.458333 2.770834 8.357668\nvertex 15.000001 1.500000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.000001 1.500000 8.357668\nvertex 15.435318 1.565411 8.357668\nvertex 15.518668 2.552154 8.357668\nendloop\nendfacet\nfacet normal -0.000007 0.000000 1.000000\nouter loop\nvertex 15.000001 1.500000 8.357668\nvertex 15.518668 2.552154 8.357668\nvertex 15.538307 2.783193 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.435318 1.565411 8.357668\nvertex 15.000001 1.500000 8.357668\nvertex 15.000001 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.000001 0.000000 8.357668\nvertex 15.399197 0.125639 8.357668\nvertex 15.402760 0.736852 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.434760 1.559115 8.357668\nvertex 15.435318 1.565411 8.357668\nvertex 15.000001 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000003 0.000000 1.000000\nouter loop\nvertex 15.000001 0.000000 8.357668\nvertex 15.402760 0.736852 8.357668\nvertex 15.434760 1.559115 8.357668\nendloop\nendfacet\nfacet normal 0.000078 0.016928 -0.999857\nouter loop\nvertex 43.736702 0.010560 0.445198\nvertex 40.305779 0.778190 0.457927\nvertex 42.050312 1.064699 0.462914\nendloop\nendfacet\nfacet normal -0.006061 0.007108 -0.999956\nouter loop\nvertex 43.736702 0.010560 0.445198\nvertex 42.050312 1.064699 0.462914\nvertex 44.715622 0.691151 0.444102\nendloop\nendfacet\nfacet normal -0.010645 0.174425 -0.984613\nouter loop\nvertex 37.501717 1.626225 0.611567\nvertex 41.149567 1.655752 0.577358\nvertex 42.050312 1.064699 0.462914\nendloop\nendfacet\nfacet normal -0.017296 0.122588 -0.992307\nouter loop\nvertex 37.501717 1.626225 0.611567\nvertex 42.050312 1.064699 0.462914\nvertex 40.305779 0.778190 0.457927\nendloop\nendfacet\nfacet normal 0.015202 0.158187 -0.987292\nouter loop\nvertex 44.902733 1.422932 0.564232\nvertex 44.715622 0.691151 0.444102\nvertex 42.050312 1.064699 0.462914\nendloop\nendfacet\nfacet normal 0.009205 0.203594 -0.979012\nouter loop\nvertex 44.902733 1.422932 0.564232\nvertex 42.050312 1.064699 0.462914\nvertex 41.149567 1.655752 0.577358\nendloop\nendfacet\nfacet normal 0.023074 -0.155230 -0.987609\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 41.912167 -0.620574 0.501772\nvertex 43.736702 0.010560 0.445198\nendloop\nendfacet\nfacet normal -0.024671 -0.225012 -0.974044\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 43.736702 0.010560 0.445198\nvertex 47.104279 -0.592443 0.499200\nendloop\nendfacet\nfacet normal 0.001842 -0.029217 -0.999571\nouter loop\nvertex 41.912167 -0.620574 0.501772\nvertex 38.036938 0.306147 0.467543\nvertex 40.305779 0.778190 0.457927\nendloop\nendfacet\nfacet normal -0.014413 -0.047859 -0.998750\nouter loop\nvertex 41.912167 -0.620574 0.501772\nvertex 40.305779 0.778190 0.457927\nvertex 43.736702 0.010560 0.445198\nendloop\nendfacet\nfacet normal 0.012519 -0.019616 -0.999729\nouter loop\nvertex 47.104279 -0.592443 0.499200\nvertex 43.736702 0.010560 0.445198\nvertex 44.715622 0.691151 0.444102\nendloop\nendfacet\nfacet normal -0.008058 -0.057846 -0.998293\nouter loop\nvertex 47.104279 -0.592443 0.499200\nvertex 44.715622 0.691151 0.444102\nvertex 47.743988 0.219856 0.446967\nendloop\nendfacet\nfacet normal -0.034582 0.395028 -0.918018\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 36.144936 2.362384 0.979452\nvertex 37.501717 1.626225 0.611567\nendloop\nendfacet\nfacet normal -0.039478 0.360558 -0.931901\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 37.501717 1.626225 0.611567\nvertex 34.217098 1.287853 0.619794\nendloop\nendfacet\nfacet normal -0.010260 0.438657 -0.898596\nouter loop\nvertex 36.144936 2.362384 0.979452\nvertex 40.623978 2.257716 0.877214\nvertex 41.149567 1.655752 0.577358\nendloop\nendfacet\nfacet normal -0.011944 0.429291 -0.903087\nouter loop\nvertex 36.144936 2.362384 0.979452\nvertex 41.149567 1.655752 0.577358\nvertex 37.501717 1.626225 0.611567\nendloop\nendfacet\nfacet normal -0.015658 0.127888 -0.991665\nouter loop\nvertex 34.217098 1.287853 0.619794\nvertex 37.501717 1.626225 0.611567\nvertex 40.305779 0.778190 0.457927\nendloop\nendfacet\nfacet normal -0.020111 0.076352 -0.996878\nouter loop\nvertex 34.217098 1.287853 0.619794\nvertex 40.305779 0.778190 0.457927\nvertex 38.036938 0.306147 0.467543\nendloop\nendfacet\nfacet normal 0.041462 0.392034 -0.919016\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 48.246258 1.017376 0.542076\nvertex 44.902733 1.422932 0.564232\nendloop\nendfacet\nfacet normal 0.035618 0.440952 -0.896824\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 44.902733 1.422932 0.564232\nvertex 44.908054 2.060014 0.877686\nendloop\nendfacet\nfacet normal 0.017659 0.107426 -0.994056\nouter loop\nvertex 48.246258 1.017376 0.542076\nvertex 47.743988 0.219856 0.446967\nvertex 44.715622 0.691151 0.444102\nendloop\nendfacet\nfacet normal 0.012721 0.158811 -0.987227\nouter loop\nvertex 48.246258 1.017376 0.542076\nvertex 44.715622 0.691151 0.444102\nvertex 44.902733 1.422932 0.564232\nendloop\nendfacet\nfacet normal 0.024230 0.441181 -0.897091\nouter loop\nvertex 44.908054 2.060014 0.877686\nvertex 44.902733 1.422932 0.564232\nvertex 41.149567 1.655752 0.577358\nendloop\nendfacet\nfacet normal 0.021356 0.460648 -0.887326\nouter loop\nvertex 44.908054 2.060014 0.877686\nvertex 41.149567 1.655752 0.577358\nvertex 40.623978 2.257716 0.877214\nendloop\nendfacet\nfacet normal 0.050301 -0.995695 -0.077854\nouter loop\nvertex 44.083652 -2.607777 2.596714\nvertex 40.060291 -2.776363 2.153366\nvertex 41.591160 -2.669416 1.774674\nendloop\nendfacet\nfacet normal 0.045011 -0.997079 -0.061711\nouter loop\nvertex 44.083652 -2.607777 2.596714\nvertex 41.591160 -2.669416 1.774674\nvertex 44.463726 -2.547658 1.902582\nendloop\nendfacet\nfacet normal 0.024502 -0.939142 -0.342654\nouter loop\nvertex 36.286263 -2.738104 1.583596\nvertex 39.933842 -2.550894 1.331318\nvertex 41.591160 -2.669416 1.774674\nendloop\nendfacet\nfacet normal 0.019783 -0.980233 -0.196857\nouter loop\nvertex 36.286263 -2.738104 1.583596\nvertex 41.591160 -2.669416 1.774674\nvertex 40.060291 -2.776363 2.153366\nendloop\nendfacet\nfacet normal 0.056317 -0.919188 -0.389771\nouter loop\nvertex 43.666763 -2.336409 1.289248\nvertex 44.463726 -2.547658 1.902582\nvertex 41.591160 -2.669416 1.774674\nendloop\nendfacet\nfacet normal 0.047362 -0.906565 -0.419399\nouter loop\nvertex 43.666763 -2.336409 1.289248\nvertex 41.591160 -2.669416 1.774674\nvertex 39.933842 -2.550894 1.331318\nendloop\nendfacet\nfacet normal 0.091668 -0.981384 0.168765\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 42.552837 -2.614465 3.389307\nvertex 44.083652 -2.607777 2.596714\nendloop\nendfacet\nfacet normal 0.050249 -0.956931 0.285932\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 44.083652 -2.607777 2.596714\nvertex 47.784302 -2.359905 2.775923\nendloop\nendfacet\nfacet normal 0.052838 -0.998310 0.024212\nouter loop\nvertex 42.552837 -2.614465 3.389307\nvertex 37.887997 -2.875850 2.791907\nvertex 40.060291 -2.776363 2.153366\nendloop\nendfacet\nfacet normal 0.035231 -0.997599 0.059627\nouter loop\nvertex 42.552837 -2.614465 3.389307\nvertex 40.060291 -2.776363 2.153366\nvertex 44.083652 -2.607777 2.596714\nendloop\nendfacet\nfacet normal 0.069089 -0.996432 -0.048472\nouter loop\nvertex 47.784302 -2.359905 2.775923\nvertex 44.083652 -2.607777 2.596714\nvertex 44.463726 -2.547658 1.902582\nendloop\nendfacet\nfacet normal 0.060172 -0.998087 -0.014212\nouter loop\nvertex 47.784302 -2.359905 2.775923\nvertex 44.463726 -2.547658 1.902582\nvertex 47.610008 -2.359042 1.977433\nendloop\nendfacet\nfacet normal -0.003913 -0.823107 -0.567873\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 33.108257 -2.339576 1.027848\nvertex 36.286263 -2.738104 1.583596\nendloop\nendfacet\nfacet normal -0.008918 -0.933554 -0.358327\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 36.286263 -2.738104 1.583596\nvertex 33.042091 -2.926533 2.155251\nendloop\nendfacet\nfacet normal 0.007482 -0.733841 -0.679280\nouter loop\nvertex 33.108257 -2.339576 1.027848\nvertex 37.724285 -2.146670 0.870290\nvertex 39.933842 -2.550894 1.331318\nendloop\nendfacet\nfacet normal 0.001003 -0.809926 -0.586532\nouter loop\nvertex 33.108257 -2.339576 1.027848\nvertex 39.933842 -2.550894 1.331318\nvertex 36.286263 -2.738104 1.583596\nendloop\nendfacet\nfacet normal 0.020887 -0.978733 -0.204074\nouter loop\nvertex 33.042091 -2.926533 2.155251\nvertex 36.286263 -2.738104 1.583596\nvertex 40.060291 -2.776363 2.153366\nendloop\nendfacet\nfacet normal 0.021297 -0.996340 -0.082783\nouter loop\nvertex 33.042091 -2.926533 2.155251\nvertex 40.060291 -2.776363 2.153366\nvertex 37.887997 -2.875850 2.791907\nendloop\nendfacet\nfacet normal 0.040971 -0.617963 -0.785139\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 47.087532 -2.123862 1.300462\nvertex 43.666763 -2.336409 1.289248\nendloop\nendfacet\nfacet normal 0.045439 -0.625789 -0.778668\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 43.666763 -2.336409 1.289248\nvertex 41.873085 -1.866991 0.807323\nendloop\nendfacet\nfacet normal 0.064363 -0.926222 -0.371443\nouter loop\nvertex 47.087532 -2.123862 1.300462\nvertex 47.610008 -2.359042 1.977433\nvertex 44.463726 -2.547658 1.902582\nendloop\nendfacet\nfacet normal 0.058331 -0.918106 -0.392018\nouter loop\nvertex 47.087532 -2.123862 1.300462\nvertex 44.463726 -2.547658 1.902582\nvertex 43.666763 -2.336409 1.289248\nendloop\nendfacet\nfacet normal 0.029403 -0.659127 -0.751457\nouter loop\nvertex 41.873085 -1.866991 0.807323\nvertex 43.666763 -2.336409 1.289248\nvertex 39.933842 -2.550894 1.331318\nendloop\nendfacet\nfacet normal 0.033597 -0.666132 -0.745077\nouter loop\nvertex 41.873085 -1.866991 0.807323\nvertex 39.933842 -2.550894 1.331318\nvertex 37.724285 -2.146670 0.870290\nendloop\nendfacet\nfacet normal 1.000000 -0.000008 0.000002\nouter loop\nvertex 55.000004 -0.761863 2.546710\nvertex 55.000004 -0.868634 1.982474\nvertex 55.000008 -0.484375 1.711834\nendloop\nendfacet\nfacet normal 1.000000 0.000016 0.000007\nouter loop\nvertex 55.000004 -0.761863 2.546710\nvertex 55.000008 -0.484375 1.711834\nvertex 55.000004 -0.281395 1.982474\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 -0.767072 1.334905\nvertex 55.000008 -0.281395 1.199488\nvertex 55.000008 -0.484375 1.711834\nendloop\nendfacet\nfacet normal 1.000000 -0.000009 0.000005\nouter loop\nvertex 55.000008 -0.767072 1.334905\nvertex 55.000008 -0.484375 1.711834\nvertex 55.000004 -0.868634 1.982474\nendloop\nendfacet\nfacet normal 1.000000 0.000016 0.000007\nouter loop\nvertex 55.000004 0.141782 1.341849\nvertex 55.000004 -0.281395 1.982474\nvertex 55.000008 -0.484375 1.711834\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000003\nouter loop\nvertex 55.000004 0.141782 1.341849\nvertex 55.000008 -0.484375 1.711834\nvertex 55.000008 -0.281395 1.199488\nendloop\nendfacet\nfacet normal 1.000000 0.000016 -0.000002\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 55.000008 -1.281250 3.086834\nvertex 55.000004 -0.761863 2.546710\nendloop\nendfacet\nfacet normal 1.000000 -0.000009 -0.000005\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 55.000004 -0.761863 2.546710\nvertex 55.000008 -0.500000 3.024334\nendloop\nendfacet\nfacet normal 1.000000 0.000009 -0.000001\nouter loop\nvertex 55.000008 -1.281250 3.086834\nvertex 55.000008 -1.375000 2.357667\nvertex 55.000004 -0.868634 1.982474\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000001\nouter loop\nvertex 55.000008 -1.281250 3.086834\nvertex 55.000004 -0.868634 1.982474\nvertex 55.000004 -0.761863 2.546710\nendloop\nendfacet\nfacet normal 1.000000 -0.000020 -0.000005\nouter loop\nvertex 55.000008 -0.500000 3.024334\nvertex 55.000004 -0.761863 2.546710\nvertex 55.000004 -0.281395 1.982474\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000003\nouter loop\nvertex 55.000008 -0.500000 3.024334\nvertex 55.000004 -0.281395 1.982474\nvertex 55.000004 0.000000 2.357667\nendloop\nendfacet\nfacet normal 1.000000 0.000000 -0.000004\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 55.000008 -0.546875 0.649334\nvertex 55.000008 -0.767072 1.334905\nendloop\nendfacet\nfacet normal 1.000000 0.000017 -0.000009\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 55.000008 -0.767072 1.334905\nvertex 55.000008 -1.281250 1.628500\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 -0.546875 0.649334\nvertex 55.000008 0.000000 0.524334\nvertex 55.000008 -0.281395 1.199488\nendloop\nendfacet\nfacet normal 1.000000 -0.000003 0.000000\nouter loop\nvertex 55.000008 -0.546875 0.649334\nvertex 55.000008 -0.281395 1.199488\nvertex 55.000008 -0.767072 1.334905\nendloop\nendfacet\nfacet normal 1.000000 0.000025 0.000006\nouter loop\nvertex 55.000008 -1.281250 1.628500\nvertex 55.000008 -0.767072 1.334905\nvertex 55.000004 -0.868634 1.982474\nendloop\nendfacet\nfacet normal 1.000000 0.000011 0.000001\nouter loop\nvertex 55.000008 -1.281250 1.628500\nvertex 55.000004 -0.868634 1.982474\nvertex 55.000008 -1.375000 2.357667\nendloop\nendfacet\nfacet normal 1.000000 0.000009 -0.000005\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 55.000008 0.500000 1.691000\nvertex 55.000004 0.141782 1.341849\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000004\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 55.000004 0.141782 1.341849\nvertex 55.000008 0.546875 0.649334\nendloop\nendfacet\nfacet normal 1.000000 -0.000010 0.000003\nouter loop\nvertex 55.000008 0.500000 1.691000\nvertex 55.000004 0.000000 2.357667\nvertex 55.000004 -0.281395 1.982474\nendloop\nendfacet\nfacet normal 1.000000 -0.000020 -0.000004\nouter loop\nvertex 55.000008 0.500000 1.691000\nvertex 55.000004 -0.281395 1.982474\nvertex 55.000004 0.141782 1.341849\nendloop\nendfacet\nfacet normal 1.000000 0.000003 0.000009\nouter loop\nvertex 55.000008 0.546875 0.649334\nvertex 55.000004 0.141782 1.341849\nvertex 55.000008 -0.281395 1.199488\nendloop\nendfacet\nfacet normal 1.000000 0.000000 0.000000\nouter loop\nvertex 55.000008 0.546875 0.649334\nvertex 55.000008 -0.281395 1.199488\nvertex 55.000008 0.000000 0.524334\nendloop\nendfacet\nfacet normal -0.347592 -0.937177 0.029666\nouter loop\nvertex 0.871076 -2.176219 3.139536\nvertex 0.727360 -2.144018 2.472892\nvertex 1.043808 -2.271605 2.150067\nendloop\nendfacet\nfacet normal -0.280931 -0.958747 0.043383\nouter loop\nvertex 0.871076 -2.176219 3.139536\nvertex 1.043808 -2.271605 2.150067\nvertex 1.281674 -2.327258 2.460489\nendloop\nendfacet\nfacet normal -0.483806 -0.826760 -0.287052\nouter loop\nvertex 0.725749 -1.969235 1.815254\nvertex 1.173840 -2.160953 1.612211\nvertex 1.043808 -2.271605 2.150067\nendloop\nendfacet\nfacet normal -0.545184 -0.810521 -0.214080\nouter loop\nvertex 0.725749 -1.969235 1.815254\nvertex 1.043808 -2.271605 2.150067\nvertex 0.727360 -2.144018 2.472892\nendloop\nendfacet\nfacet normal -0.039823 -0.988382 -0.146683\nouter loop\nvertex 1.698624 -2.233000 1.712161\nvertex 1.281674 -2.327258 2.460489\nvertex 1.043808 -2.271605 2.150067\nendloop\nendfacet\nfacet normal -0.091052 -0.970845 -0.221743\nouter loop\nvertex 1.698624 -2.233000 1.712161\nvertex 1.043808 -2.271605 2.150067\nvertex 1.173840 -2.160953 1.612211\nendloop\nendfacet\nfacet normal -0.445325 -0.830489 0.334624\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 0.535608 -1.766233 3.710613\nvertex 0.871076 -2.176219 3.139536\nendloop\nendfacet\nfacet normal -0.620246 -0.729234 0.288985\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 0.871076 -2.176219 3.139536\nvertex 1.143440 -2.154511 3.778884\nendloop\nendfacet\nfacet normal -0.650841 -0.748414 0.127605\nouter loop\nvertex 0.535608 -1.766233 3.710613\nvertex 0.406945 -1.789352 2.918778\nvertex 0.727360 -2.144018 2.472892\nendloop\nendfacet\nfacet normal -0.685904 -0.718842 0.113147\nouter loop\nvertex 0.535608 -1.766233 3.710613\nvertex 0.727360 -2.144018 2.472892\nvertex 0.871076 -2.176219 3.139536\nendloop\nendfacet\nfacet normal -0.178805 -0.977787 0.109370\nouter loop\nvertex 1.143440 -2.154511 3.778884\nvertex 0.871076 -2.176219 3.139536\nvertex 1.281674 -2.327258 2.460489\nendloop\nendfacet\nfacet normal -0.207227 -0.972565 0.105706\nouter loop\nvertex 1.143440 -2.154511 3.778884\nvertex 1.281674 -2.327258 2.460489\nvertex 1.609877 -2.343493 2.954529\nendloop\nendfacet\nfacet normal -0.836686 -0.437568 -0.329379\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.752797 -1.601241 1.257680\nvertex 0.725749 -1.969235 1.815254\nendloop\nendfacet\nfacet normal -0.841795 -0.437141 -0.316685\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.725749 -1.969235 1.815254\nvertex 0.380729 -1.598091 2.220051\nendloop\nendfacet\nfacet normal -0.501130 -0.699600 -0.509341\nouter loop\nvertex 0.752797 -1.601241 1.257680\nvertex 1.258488 -1.814558 1.053140\nvertex 1.173840 -2.160953 1.612211\nendloop\nendfacet\nfacet normal -0.520777 -0.700671 -0.487700\nouter loop\nvertex 0.752797 -1.601241 1.257680\nvertex 1.173840 -2.160953 1.612211\nvertex 0.725749 -1.969235 1.815254\nendloop\nendfacet\nfacet normal -0.801061 -0.578984 -0.151916\nouter loop\nvertex 0.380729 -1.598091 2.220051\nvertex 0.725749 -1.969235 1.815254\nvertex 0.727360 -2.144018 2.472892\nendloop\nendfacet\nfacet normal -0.809904 -0.572781 -0.126400\nouter loop\nvertex 0.380729 -1.598091 2.220051\nvertex 0.727360 -2.144018 2.472892\nvertex 0.406945 -1.789352 2.918778\nendloop\nendfacet\nfacet normal 0.138145 -0.943925 -0.299870\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 2.251229 -2.276334 2.103142\nvertex 1.698624 -2.233000 1.712161\nendloop\nendfacet\nfacet normal 0.054306 -0.878761 -0.474162\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 1.698624 -2.233000 1.712161\nvertex 1.937340 -1.854676 1.038357\nendloop\nendfacet\nfacet normal 0.032398 -0.997998 -0.054319\nouter loop\nvertex 2.251229 -2.276334 2.103142\nvertex 1.609877 -2.343493 2.954529\nvertex 1.281674 -2.327258 2.460489\nendloop\nendfacet\nfacet normal 0.007619 -0.992649 -0.120787\nouter loop\nvertex 2.251229 -2.276334 2.103142\nvertex 1.281674 -2.327258 2.460489\nvertex 1.698624 -2.233000 1.712161\nendloop\nendfacet\nfacet normal -0.024677 -0.867934 -0.496066\nouter loop\nvertex 1.937340 -1.854676 1.038357\nvertex 1.698624 -2.233000 1.712161\nvertex 1.173840 -2.160953 1.612211\nendloop\nendfacet\nfacet normal -0.061487 -0.844255 -0.532402\nouter loop\nvertex 1.937340 -1.854676 1.038357\nvertex 1.173840 -2.160953 1.612211\nvertex 1.258488 -1.814558 1.053140\nendloop\nendfacet\nfacet normal -0.989048 0.147517 -0.004837\nouter loop\nvertex 0.194890 1.137827 2.886624\nvertex 0.213908 1.243482 2.220033\nvertex 0.139063 0.736111 2.050549\nendloop\nendfacet\nfacet normal -0.992676 0.120519 0.008377\nouter loop\nvertex 0.194890 1.137827 2.886624\nvertex 0.139063 0.736111 2.050549\nvertex 0.108548 0.460785 2.395634\nendloop\nendfacet\nfacet normal -0.955710 0.170720 -0.239736\nouter loop\nvertex 0.318853 1.047687 1.555693\nvertex 0.206508 0.432790 1.565678\nvertex 0.139063 0.736111 2.050549\nendloop\nendfacet\nfacet normal -0.953775 0.211887 -0.213113\nouter loop\nvertex 0.318853 1.047687 1.555693\nvertex 0.139063 0.736111 2.050549\nvertex 0.213908 1.243482 2.220033\nendloop\nendfacet\nfacet normal -0.995369 -0.009567 -0.095650\nouter loop\nvertex 0.171337 -0.132326 1.801552\nvertex 0.108548 0.460785 2.395634\nvertex 0.139063 0.736111 2.050549\nendloop\nendfacet\nfacet normal -0.990176 0.003280 -0.139785\nouter loop\nvertex 0.171337 -0.132326 1.801552\nvertex 0.139063 0.736111 2.050549\nvertex 0.206508 0.432790 1.565678\nendloop\nendfacet\nfacet normal -0.936978 0.296676 0.184540\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.440260 1.766233 3.122204\nvertex 0.194890 1.137827 2.886624\nendloop\nendfacet\nfacet normal -0.938109 0.291692 0.186730\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 0.194890 1.137827 2.886624\nvertex 0.208924 0.785330 3.507765\nendloop\nendfacet\nfacet normal -0.933334 0.358014 0.026725\nouter loop\nvertex 0.440260 1.766233 3.122204\nvertex 0.426389 1.789352 2.328038\nvertex 0.213908 1.243482 2.220033\nendloop\nendfacet\nfacet normal -0.934793 0.353970 0.029434\nouter loop\nvertex 0.440260 1.766233 3.122204\nvertex 0.213908 1.243482 2.220033\nvertex 0.194890 1.137827 2.886624\nendloop\nendfacet\nfacet normal -0.994680 0.078319 0.066920\nouter loop\nvertex 0.208924 0.785330 3.507765\nvertex 0.194890 1.137827 2.886624\nvertex 0.108548 0.460785 2.395634\nendloop\nendfacet\nfacet normal -0.994693 0.078095 0.066986\nouter loop\nvertex 0.208924 0.785330 3.507765\nvertex 0.108548 0.460785 2.395634\nvertex 0.106944 0.041667 2.860445\nendloop\nendfacet\nfacet normal -0.767130 0.340593 -0.543606\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 0.539062 0.645255 0.992794\nvertex 0.318853 1.047687 1.555693\nendloop\nendfacet\nfacet normal -0.765771 0.349253 -0.540016\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 0.318853 1.047687 1.555693\nvertex 0.541146 1.598091 1.596440\nendloop\nendfacet\nfacet normal -0.878046 0.142192 -0.456964\nouter loop\nvertex 0.539062 0.645255 0.992794\nvertex 0.409722 -0.000000 1.040537\nvertex 0.206508 0.432790 1.565678\nendloop\nendfacet\nfacet normal -0.878248 0.153103 -0.453035\nouter loop\nvertex 0.539062 0.645255 0.992794\nvertex 0.206508 0.432790 1.565678\nvertex 0.318853 1.047687 1.555693\nendloop\nendfacet\nfacet normal -0.890632 0.378373 -0.252206\nouter loop\nvertex 0.541146 1.598091 1.596440\nvertex 0.318853 1.047687 1.555693\nvertex 0.213908 1.243482 2.220033\nendloop\nendfacet\nfacet normal -0.887071 0.393161 -0.241929\nouter loop\nvertex 0.541146 1.598091 1.596440\nvertex 0.213908 1.243482 2.220033\nvertex 0.426389 1.789352 2.328038\nendloop\nendfacet\nfacet normal -0.964031 -0.167303 -0.206530\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.171354 -0.640046 2.212759\nvertex 0.171337 -0.132326 1.801552\nendloop\nendfacet\nfacet normal -0.962614 -0.165977 -0.214069\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.171337 -0.132326 1.801552\nvertex 0.381076 -0.645255 1.256104\nendloop\nendfacet\nfacet normal -0.997662 -0.049007 -0.047631\nouter loop\nvertex 0.171354 -0.640046 2.212759\nvertex 0.106944 0.041667 2.860445\nvertex 0.108548 0.460785 2.395634\nendloop\nendfacet\nfacet normal -0.997185 -0.047215 -0.058256\nouter loop\nvertex 0.171354 -0.640046 2.212759\nvertex 0.108548 0.460785 2.395634\nvertex 0.171337 -0.132326 1.801552\nendloop\nendfacet\nfacet normal -0.950782 -0.067091 -0.302510\nouter loop\nvertex 0.381076 -0.645255 1.256104\nvertex 0.171337 -0.132326 1.801552\nvertex 0.206508 0.432790 1.565678\nendloop\nendfacet\nfacet normal -0.947141 -0.063041 -0.314562\nouter loop\nvertex 0.381076 -0.645255 1.256104\nvertex 0.206508 0.432790 1.565678\nvertex 0.409722 -0.000000 1.040537\nendloop\nendfacet\nfacet normal 0.176119 0.983530 0.040642\nouter loop\nvertex 53.935028 1.596290 2.549231\nvertex 54.087021 1.591341 2.010366\nvertex 53.385422 1.727238 1.761988\nendloop\nendfacet\nfacet normal 0.195731 0.980302 0.026412\nouter loop\nvertex 53.935028 1.596290 2.549231\nvertex 53.385422 1.727238 1.761988\nvertex 52.969688 1.803813 2.000689\nendloop\nendfacet\nfacet normal 0.215299 0.954276 -0.207373\nouter loop\nvertex 54.058685 1.502757 1.427992\nvertex 53.116249 1.692702 1.323606\nvertex 53.385422 1.727238 1.761988\nendloop\nendfacet\nfacet normal 0.241210 0.957624 -0.157398\nouter loop\nvertex 54.058685 1.502757 1.427992\nvertex 53.385422 1.727238 1.761988\nvertex 54.087021 1.591341 2.010366\nendloop\nendfacet\nfacet normal 0.122349 0.987069 -0.103565\nouter loop\nvertex 52.143909 1.843897 1.407164\nvertex 52.969688 1.803813 2.000689\nvertex 53.385422 1.727238 1.761988\nendloop\nendfacet\nfacet normal 0.138040 0.977132 -0.161736\nouter loop\nvertex 52.143909 1.843897 1.407164\nvertex 53.385422 1.727238 1.761988\nvertex 53.116249 1.692702 1.323606\nendloop\nendfacet\nfacet normal 0.055059 0.905206 0.421391\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 55.000008 1.281250 3.086834\nvertex 53.935028 1.596290 2.549231\nendloop\nendfacet\nfacet normal 0.267736 0.933666 0.237874\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 53.935028 1.596290 2.549231\nvertex 53.526051 1.599617 2.996491\nendloop\nendfacet\nfacet normal 0.183352 0.975022 0.125359\nouter loop\nvertex 55.000008 1.281250 3.086834\nvertex 55.000008 1.375000 2.357667\nvertex 54.087021 1.591341 2.010366\nendloop\nendfacet\nfacet normal 0.253856 0.965205 0.062737\nouter loop\nvertex 55.000008 1.281250 3.086834\nvertex 54.087021 1.591341 2.010366\nvertex 53.935028 1.596290 2.549231\nendloop\nendfacet\nfacet normal 0.141701 0.982330 0.122265\nouter loop\nvertex 53.526051 1.599617 2.996491\nvertex 53.935028 1.596290 2.549231\nvertex 52.969688 1.803813 2.000689\nendloop\nendfacet\nfacet normal 0.201020 0.975649 0.087751\nouter loop\nvertex 53.526051 1.599617 2.996491\nvertex 52.969688 1.803813 2.000689\nvertex 52.409729 1.888375 2.343264\nendloop\nendfacet\nfacet normal 0.281243 0.863203 -0.419266\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 54.016209 1.270190 0.920681\nvertex 54.058685 1.502757 1.427992\nendloop\nendfacet\nfacet normal 0.290181 0.867573 -0.403871\nouter loop\nvertex 55.000008 1.000000 1.024334\nvertex 54.058685 1.502757 1.427992\nvertex 55.000008 1.281250 1.628500\nendloop\nendfacet\nfacet normal 0.210646 0.871327 -0.443190\nouter loop\nvertex 54.016209 1.270190 0.920681\nvertex 52.962971 1.494856 0.861782\nvertex 53.116249 1.692702 1.323606\nendloop\nendfacet\nfacet normal 0.223803 0.878738 -0.421582\nouter loop\nvertex 54.016209 1.270190 0.920681\nvertex 53.116249 1.692702 1.323606\nvertex 54.058685 1.502757 1.427992\nendloop\nendfacet\nfacet normal 0.257870 0.953249 -0.157542\nouter loop\nvertex 55.000008 1.281250 1.628500\nvertex 54.058685 1.502757 1.427992\nvertex 54.087021 1.591341 2.010366\nendloop\nendfacet\nfacet normal 0.272780 0.954222 -0.122685\nouter loop\nvertex 55.000008 1.281250 1.628500\nvertex 54.087021 1.591341 2.010366\nvertex 55.000008 1.375000 2.357667\nendloop\nendfacet\nfacet normal 0.044312 0.934547 -0.353069\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 51.159924 1.990409 1.671474\nvertex 52.143909 1.843897 1.407164\nendloop\nendfacet\nfacet normal 0.049913 0.922009 -0.383936\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 52.143909 1.843897 1.407164\nvertex 51.705059 1.646369 0.875757\nendloop\nendfacet\nfacet normal 0.113147 0.991773 -0.059865\nouter loop\nvertex 51.159924 1.990409 1.671474\nvertex 52.409729 1.888375 2.343264\nvertex 52.969688 1.803813 2.000689\nendloop\nendfacet\nfacet normal 0.120095 0.987674 -0.100388\nouter loop\nvertex 51.159924 1.990409 1.671474\nvertex 52.969688 1.803813 2.000689\nvertex 52.143909 1.843897 1.407164\nendloop\nendfacet\nfacet normal 0.103964 0.901163 -0.420828\nouter loop\nvertex 51.705059 1.646369 0.875757\nvertex 52.143909 1.843897 1.407164\nvertex 53.116249 1.692702 1.323606\nendloop\nendfacet\nfacet normal 0.103885 0.901285 -0.420588\nouter loop\nvertex 51.705059 1.646369 0.875757\nvertex 53.116249 1.692702 1.323606\nvertex 52.962971 1.494856 0.861782\nendloop\nendfacet\nfacet normal -0.079497 -0.242369 -0.966922\nouter loop\nvertex 1.698774 -1.194074 0.641540\nvertex 1.174004 -1.261905 0.701687\nvertex 1.044850 -0.745563 0.582879\nendloop\nendfacet\nfacet normal -0.037206 -0.182741 -0.982457\nouter loop\nvertex 1.698774 -1.194074 0.641540\nvertex 1.044850 -0.745563 0.582879\nvertex 1.282836 -0.479353 0.524350\nendloop\nendfacet\nfacet normal -0.539801 -0.241520 -0.806401\nouter loop\nvertex 0.726007 -1.050028 0.887499\nvertex 0.729391 -0.434278 0.700814\nvertex 1.044850 -0.745563 0.582879\nendloop\nendfacet\nfacet normal -0.485511 -0.309565 -0.817587\nouter loop\nvertex 0.726007 -1.050028 0.887499\nvertex 1.044850 -0.745563 0.582879\nvertex 1.174004 -1.261905 0.701687\nendloop\nendfacet\nfacet normal -0.254551 0.014972 -0.966943\nouter loop\nvertex 0.873956 0.129967 0.641424\nvertex 1.282836 -0.479353 0.524350\nvertex 1.044850 -0.745563 0.582879\nendloop\nendfacet\nfacet normal -0.356281 -0.007064 -0.934352\nouter loop\nvertex 0.873956 0.129967 0.641424\nvertex 1.044850 -0.745563 0.582879\nvertex 0.729391 -0.434278 0.700814\nendloop\nendfacet\nfacet normal 0.076213 -0.493064 -0.866648\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 1.937340 -1.854676 1.038357\nvertex 1.698774 -1.194074 0.641540\nendloop\nendfacet\nfacet normal 0.152938 -0.353691 -0.922774\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 1.698774 -1.194074 0.641540\nvertex 2.250708 -0.876450 0.611273\nendloop\nendfacet\nfacet normal -0.050272 -0.541403 -0.839259\nouter loop\nvertex 1.937340 -1.854676 1.038357\nvertex 1.258488 -1.814558 1.053140\nvertex 1.174004 -1.261905 0.701687\nendloop\nendfacet\nfacet normal -0.030096 -0.522661 -0.852009\nouter loop\nvertex 1.937340 -1.854676 1.038357\nvertex 1.174004 -1.261905 0.701687\nvertex 1.698774 -1.194074 0.641540\nendloop\nendfacet\nfacet normal 0.029280 -0.145119 -0.988981\nouter loop\nvertex 2.250708 -0.876450 0.611273\nvertex 1.698774 -1.194074 0.641540\nvertex 1.282836 -0.479353 0.524350\nendloop\nendfacet\nfacet normal 0.054443 -0.085079 -0.994886\nouter loop\nvertex 2.250708 -0.876450 0.611273\nvertex 1.282836 -0.479353 0.524350\nvertex 1.605710 -0.068030 0.506844\nendloop\nendfacet\nfacet normal -0.841401 -0.321327 -0.434504\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.381076 -0.645255 1.256104\nvertex 0.726007 -1.050028 0.887499\nendloop\nendfacet\nfacet normal -0.836848 -0.332655 -0.434772\nouter loop\nvertex 0.388889 -1.203704 1.653963\nvertex 0.726007 -1.050028 0.887499\nvertex 0.752797 -1.601241 1.257680\nendloop\nendfacet\nfacet normal -0.809887 -0.153210 -0.566225\nouter loop\nvertex 0.381076 -0.645255 1.256104\nvertex 0.409722 -0.000000 1.040537\nvertex 0.729391 -0.434278 0.700814\nendloop\nendfacet\nfacet normal -0.805090 -0.168042 -0.568851\nouter loop\nvertex 0.381076 -0.645255 1.256104\nvertex 0.729391 -0.434278 0.700814\nvertex 0.726007 -1.050028 0.887499\nendloop\nendfacet\nfacet normal -0.521874 -0.492910 -0.696194\nouter loop\nvertex 0.752797 -1.601241 1.257680\nvertex 0.726007 -1.050028 0.887499\nvertex 1.174004 -1.261905 0.701687\nendloop\nendfacet\nfacet normal -0.499400 -0.517985 -0.694472\nouter loop\nvertex 0.752797 -1.601241 1.257680\nvertex 1.174004 -1.261905 0.701687\nvertex 1.258488 -1.814558 1.053140\nendloop\nendfacet\nfacet normal -0.489586 0.240574 -0.838111\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 1.126061 0.636751 0.639624\nvertex 0.873956 0.129967 0.641424\nendloop\nendfacet\nfacet normal -0.506824 0.235979 -0.829122\nouter loop\nvertex 0.777778 1.203704 1.005815\nvertex 0.873956 0.129967 0.641424\nvertex 0.539062 0.645255 0.992794\nendloop\nendfacet\nfacet normal -0.155176 0.079900 -0.984650\nouter loop\nvertex 1.126061 0.636751 0.639624\nvertex 1.605710 -0.068030 0.506844\nvertex 1.282836 -0.479353 0.524350\nendloop\nendfacet\nfacet normal -0.164661 0.078421 -0.983228\nouter loop\nvertex 1.126061 0.636751 0.639624\nvertex 1.282836 -0.479353 0.524350\nvertex 0.873956 0.129967 0.641424\nendloop\nendfacet\nfacet normal -0.653249 0.088217 -0.751986\nouter loop\nvertex 0.539062 0.645255 0.992794\nvertex 0.873956 0.129967 0.641424\nvertex 0.729391 -0.434278 0.700814\nendloop\nendfacet\nfacet normal -0.672584 0.080388 -0.735642\nouter loop\nvertex 0.539062 0.645255 0.992794\nvertex 0.729391 -0.434278 0.700814\nvertex 0.409722 -0.000000 1.040537\nendloop\nendfacet\nfacet normal 0.041553 -0.274803 0.960602\nouter loop\nvertex 51.965214 -1.202216 4.176255\nvertex 53.058922 -1.128279 4.150095\nvertex 53.356018 -0.737245 4.249107\nendloop\nendfacet\nfacet normal -0.011195 -0.122011 0.992466\nouter loop\nvertex 51.965214 -1.202216 4.176255\nvertex 53.356018 -0.737245 4.249107\nvertex 52.912373 -0.593412 4.261785\nendloop\nendfacet\nfacet normal 0.128077 -0.269565 0.954427\nouter loop\nvertex 54.051399 -0.881209 4.115131\nvertex 54.082394 -0.427969 4.238985\nvertex 53.356018 -0.737245 4.249107\nendloop\nendfacet\nfacet normal 0.113803 -0.324253 0.939100\nouter loop\nvertex 54.051399 -0.881209 4.115131\nvertex 53.356018 -0.737245 4.249107\nvertex 53.058922 -1.128279 4.150095\nendloop\nendfacet\nfacet normal 0.037141 0.026509 0.998958\nouter loop\nvertex 53.927742 -0.016987 4.208736\nvertex 52.912373 -0.593412 4.261785\nvertex 53.356018 -0.737245 4.249107\nendloop\nendfacet\nfacet normal -0.014965 0.067793 0.997587\nouter loop\nvertex 53.927742 -0.016987 4.208736\nvertex 53.356018 -0.737245 4.249107\nvertex 54.082394 -0.427969 4.238985\nendloop\nendfacet\nfacet normal 0.058644 -0.553201 0.830981\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 51.413963 -1.708487 3.878123\nvertex 51.965214 -1.202216 4.176255\nendloop\nendfacet\nfacet normal 0.004120 -0.330760 0.943706\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 51.965214 -1.202216 4.176255\nvertex 50.865345 -1.042833 4.236919\nendloop\nendfacet\nfacet normal 0.090004 -0.620383 0.779117\nouter loop\nvertex 51.413963 -1.708487 3.878123\nvertex 52.884544 -1.512283 3.864470\nvertex 53.058922 -1.128279 4.150095\nendloop\nendfacet\nfacet normal 0.057222 -0.552129 0.831793\nouter loop\nvertex 51.413963 -1.708487 3.878123\nvertex 53.058922 -1.128279 4.150095\nvertex 51.965214 -1.202216 4.176255\nendloop\nendfacet\nfacet normal 0.027912 -0.181522 0.982991\nouter loop\nvertex 50.865345 -1.042833 4.236919\nvertex 51.965214 -1.202216 4.176255\nvertex 52.912373 -0.593412 4.261785\nendloop\nendfacet\nfacet normal -0.007944 -0.019132 0.999785\nouter loop\nvertex 50.865345 -1.042833 4.236919\nvertex 52.912373 -0.593412 4.261785\nvertex 52.331310 -0.308579 4.262618\nendloop\nendfacet\nfacet normal 0.255804 -0.616356 0.744761\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 55.000008 -0.546875 4.066000\nvertex 54.051399 -0.881209 4.115131\nendloop\nendfacet\nfacet normal 0.250243 -0.629145 0.735904\nouter loop\nvertex 55.000008 -1.000000 3.691000\nvertex 54.051399 -0.881209 4.115131\nvertex 54.006409 -1.272369 3.796018\nendloop\nendfacet\nfacet normal 0.153076 -0.220201 0.963369\nouter loop\nvertex 55.000008 -0.546875 4.066000\nvertex 55.000008 0.000000 4.191000\nvertex 54.082394 -0.427969 4.238985\nendloop\nendfacet\nfacet normal 0.144470 -0.270011 0.951957\nouter loop\nvertex 55.000008 -0.546875 4.066000\nvertex 54.082394 -0.427969 4.238985\nvertex 54.051399 -0.881209 4.115131\nendloop\nendfacet\nfacet normal 0.184278 -0.633950 0.751099\nouter loop\nvertex 54.006409 -1.272369 3.796018\nvertex 54.051399 -0.881209 4.115131\nvertex 53.058922 -1.128279 4.150095\nendloop\nendfacet\nfacet normal 0.182211 -0.638753 0.747525\nouter loop\nvertex 54.006409 -1.272369 3.796018\nvertex 53.058922 -1.128279 4.150095\nvertex 52.884544 -1.512283 3.864470\nendloop\nendfacet\nfacet normal 0.127756 0.339678 0.931825\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 53.516247 0.366665 4.125300\nvertex 53.927742 -0.016987 4.208736\nendloop\nendfacet\nfacet normal -0.226665 0.620976 0.750341\nouter loop\nvertex 55.000015 1.000000 3.691000\nvertex 53.927742 -0.016987 4.208736\nvertex 55.000008 0.546875 4.066000\nendloop\nendfacet\nfacet normal 0.053967 0.107189 0.992773\nouter loop\nvertex 53.516247 0.366665 4.125300\nvertex 52.331310 -0.308579 4.262618\nvertex 52.912373 -0.593412 4.261785\nendloop\nendfacet\nfacet normal -0.043596 0.167437 0.984918\nouter loop\nvertex 53.516247 0.366665 4.125300\nvertex 52.912373 -0.593412 4.261785\nvertex 53.927742 -0.016987 4.208736\nendloop\nendfacet\nfacet normal 0.078160 0.102397 0.991668\nouter loop\nvertex 55.000008 0.546875 4.066000\nvertex 53.927742 -0.016987 4.208736\nvertex 54.082394 -0.427969 4.238985\nendloop\nendfacet\nfacet normal -0.052872 0.222516 0.973494\nouter loop\nvertex 55.000008 0.546875 4.066000\nvertex 54.082394 -0.427969 4.238985\nvertex 55.000008 0.000000 4.191000\nendloop\nendfacet\nfacet normal -0.354704 -0.234511 0.905091\nouter loop\nvertex 1.547216 -1.136979 5.509017\nvertex 2.138190 -1.286114 5.701979\nvertex 2.290046 -0.728202 5.906047\nendloop\nendfacet\nfacet normal -0.402864 -0.145558 0.903611\nouter loop\nvertex 1.547216 -1.136979 5.509017\nvertex 2.290046 -0.728202 5.906047\nvertex 2.000845 -0.410237 5.828329\nendloop\nendfacet\nfacet normal -0.147066 -0.220833 0.964160\nouter loop\nvertex 3.079537 -1.179202 5.923172\nvertex 2.968978 -0.413501 6.081686\nvertex 2.290046 -0.728202 5.906047\nendloop\nendfacet\nfacet normal -0.187207 -0.292097 0.937887\nouter loop\nvertex 3.079537 -1.179202 5.923172\nvertex 2.290046 -0.728202 5.906047\nvertex 2.138190 -1.286114 5.701979\nendloop\nendfacet\nfacet normal -0.230089 0.028490 0.972753\nouter loop\nvertex 2.833053 0.292040 6.004605\nvertex 2.000845 -0.410237 5.828329\nvertex 2.290046 -0.728202 5.906047\nendloop\nendfacet\nfacet normal -0.272804 0.052395 0.960642\nouter loop\nvertex 2.833053 0.292040 6.004605\nvertex 2.290046 -0.728202 5.906047\nvertex 2.968978 -0.413501 6.081686\nendloop\nendfacet\nfacet normal -0.607856 -0.414717 0.677142\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 1.394066 -1.776039 4.980145\nvertex 1.547216 -1.136979 5.509017\nendloop\nendfacet\nfacet normal -0.622161 -0.392137 0.677601\nouter loop\nvertex 0.840000 -1.566667 4.611000\nvertex 1.547216 -1.136979 5.509017\nvertex 1.153953 -0.776505 5.356543\nendloop\nendfacet\nfacet normal -0.361797 -0.554571 0.749369\nouter loop\nvertex 1.394066 -1.776039 4.980145\nvertex 2.083642 -1.867799 5.245167\nvertex 2.138190 -1.286114 5.701979\nendloop\nendfacet\nfacet normal -0.381163 -0.533510 0.755038\nouter loop\nvertex 1.394066 -1.776039 4.980145\nvertex 2.138190 -1.286114 5.701979\nvertex 1.547216 -1.136979 5.509017\nendloop\nendfacet\nfacet normal -0.446405 -0.111459 0.887863\nouter loop\nvertex 1.153953 -0.776505 5.356543\nvertex 1.547216 -1.136979 5.509017\nvertex 2.000845 -0.410237 5.828329\nendloop\nendfacet\nfacet normal -0.461265 -0.072506 0.884295\nouter loop\nvertex 1.153953 -0.776505 5.356543\nvertex 2.000845 -0.410237 5.828329\nvertex 1.693982 0.028935 5.704272\nendloop\nendfacet\nfacet normal -0.065862 -0.497668 0.864863\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 4.467706 -0.826319 6.231944\nvertex 3.079537 -1.179202 5.923172\nendloop\nendfacet\nfacet normal -0.094530 -0.579898 0.809186\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 3.079537 -1.179202 5.923172\nvertex 3.171496 -1.861331 5.445072\nendloop\nendfacet\nfacet normal -0.137956 -0.144190 0.979886\nouter loop\nvertex 4.467706 -0.826319 6.231944\nvertex 4.185957 0.051183 6.321401\nvertex 2.968978 -0.413501 6.081686\nendloop\nendfacet\nfacet normal -0.157608 -0.221957 0.962234\nouter loop\nvertex 4.467706 -0.826319 6.231944\nvertex 2.968978 -0.413501 6.081686\nvertex 3.079537 -1.179202 5.923172\nendloop\nendfacet\nfacet normal -0.123155 -0.580665 0.804774\nouter loop\nvertex 3.171496 -1.861331 5.445072\nvertex 3.079537 -1.179202 5.923172\nvertex 2.138190 -1.286114 5.701979\nendloop\nendfacet\nfacet normal -0.140668 -0.603298 0.785012\nouter loop\nvertex 3.171496 -1.861331 5.445072\nvertex 2.138190 -1.286114 5.701979\nvertex 2.083642 -1.867799 5.245167\nendloop\nendfacet\nfacet normal -0.022637 0.319377 0.947357\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 2.557282 0.880763 5.799543\nvertex 2.833053 0.292040 6.004605\nendloop\nendfacet\nfacet normal -0.346115 0.555417 0.756119\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 2.833053 0.292040 6.004605\nvertex 4.172165 0.918773 6.157211\nendloop\nendfacet\nfacet normal -0.222871 0.117637 0.967724\nouter loop\nvertex 2.557282 0.880763 5.799543\nvertex 1.693982 0.028935 5.704272\nvertex 2.000845 -0.410237 5.828329\nendloop\nendfacet\nfacet normal -0.336073 0.165526 0.927176\nouter loop\nvertex 2.557282 0.880763 5.799543\nvertex 2.000845 -0.410237 5.828329\nvertex 2.833053 0.292040 6.004605\nendloop\nendfacet\nfacet normal -0.149265 0.078927 0.985642\nouter loop\nvertex 4.172165 0.918773 6.157211\nvertex 2.833053 0.292040 6.004605\nvertex 2.968978 -0.413501 6.081686\nendloop\nendfacet\nfacet normal -0.254484 0.175919 0.950942\nouter loop\nvertex 4.172165 0.918773 6.157211\nvertex 2.968978 -0.413501 6.081686\nvertex 4.185957 0.051183 6.321401\nendloop\nendfacet\nfacet normal 0.019993 -0.243746 -0.969633\nouter loop\nvertex 9.308265 -1.414347 0.689740\nvertex 7.432445 -1.480433 0.667675\nvertex 6.950618 -0.894483 0.510445\nendloop\nendfacet\nfacet normal 0.041964 -0.150350 -0.987742\nouter loop\nvertex 9.308265 -1.414347 0.689740\nvertex 6.950618 -0.894483 0.510445\nvertex 7.816463 -0.594631 0.501587\nendloop\nendfacet\nfacet normal -0.039810 -0.206707 -0.977593\nouter loop\nvertex 5.514132 -1.298165 0.654298\nvertex 5.571075 -0.536503 0.490929\nvertex 6.950618 -0.894483 0.510445\nendloop\nendfacet\nfacet normal -0.019320 -0.273907 -0.961562\nouter loop\nvertex 5.514132 -1.298165 0.654298\nvertex 6.950618 -0.894483 0.510445\nvertex 7.432445 -1.480433 0.667675\nendloop\nendfacet\nfacet normal -0.008654 -0.004548 -0.999952\nouter loop\nvertex 5.970649 0.172968 0.514071\nvertex 7.816463 -0.594631 0.501587\nvertex 6.950618 -0.894483 0.510445\nendloop\nendfacet\nfacet normal 0.019719 0.021498 -0.999574\nouter loop\nvertex 5.970649 0.172968 0.514071\nvertex 6.950618 -0.894483 0.510445\nvertex 5.571075 -0.536503 0.490929\nendloop\nendfacet\nfacet normal 0.039007 -0.544753 -0.837689\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 10.028108 -2.122718 1.183917\nvertex 9.308265 -1.414347 0.689740\nendloop\nendfacet\nfacet normal 0.072566 -0.423970 -0.902765\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 9.308265 -1.414347 0.689740\nvertex 11.022995 -1.088743 0.674657\nendloop\nendfacet\nfacet normal 0.018704 -0.579360 -0.814857\nouter loop\nvertex 10.028108 -2.122718 1.183917\nvertex 7.706276 -2.079218 1.099694\nvertex 7.432445 -1.480433 0.667675\nendloop\nendfacet\nfacet normal 0.029242 -0.551751 -0.833496\nouter loop\nvertex 10.028108 -2.122718 1.183917\nvertex 7.432445 -1.480433 0.667675\nvertex 9.308265 -1.414347 0.689740\nendloop\nendfacet\nfacet normal 0.025427 -0.179458 -0.983437\nouter loop\nvertex 11.022995 -1.088743 0.674657\nvertex 9.308265 -1.414347 0.689740\nvertex 7.816463 -0.594631 0.501587\nendloop\nendfacet\nfacet normal 0.041784 -0.077744 -0.996097\nouter loop\nvertex 11.022995 -1.088743 0.674657\nvertex 7.816463 -0.594631 0.501587\nvertex 8.954733 -0.142490 0.514045\nendloop\nendfacet\nfacet normal -0.082683 -0.448631 -0.889884\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 3.794400 -0.906173 0.616465\nvertex 5.514132 -1.298165 0.654298\nendloop\nendfacet\nfacet normal -0.043684 -0.560753 -0.826830\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 5.514132 -1.298165 0.654298\nvertex 5.514146 -1.967330 1.108122\nendloop\nendfacet\nfacet normal -0.043195 -0.128838 -0.990724\nouter loop\nvertex 3.794400 -0.906173 0.616465\nvertex 3.996914 -0.050026 0.496299\nvertex 5.571075 -0.536503 0.490929\nendloop\nendfacet\nfacet normal -0.025854 -0.207801 -0.977829\nouter loop\nvertex 3.794400 -0.906173 0.616465\nvertex 5.571075 -0.536503 0.490929\nvertex 5.514132 -1.298165 0.654298\nendloop\nendfacet\nfacet normal -0.047506 -0.560655 -0.826686\nouter loop\nvertex 5.514146 -1.967330 1.108122\nvertex 5.514132 -1.298165 0.654298\nvertex 7.432445 -1.480433 0.667675\nendloop\nendfacet\nfacet normal -0.033447 -0.594788 -0.803187\nouter loop\nvertex 5.514146 -1.967330 1.108122\nvertex 7.432445 -1.480433 0.667675\nvertex 7.706276 -2.079218 1.099694\nendloop\nendfacet\nfacet normal -0.085594 0.277348 -0.956949\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 6.811232 0.793336 0.618684\nvertex 5.970649 0.172968 0.514071\nendloop\nendfacet\nfacet normal 0.116135 0.459484 -0.880561\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 5.970649 0.172968 0.514071\nvertex 4.148535 0.817264 0.609955\nendloop\nendfacet\nfacet normal -0.017477 0.071479 -0.997289\nouter loop\nvertex 6.811232 0.793336 0.618684\nvertex 8.954733 -0.142490 0.514045\nvertex 7.816463 -0.594631 0.501587\nendloop\nendfacet\nfacet normal 0.040235 0.112897 -0.992792\nouter loop\nvertex 6.811232 0.793336 0.618684\nvertex 7.816463 -0.594631 0.501587\nvertex 5.970649 0.172968 0.514071\nendloop\nendfacet\nfacet normal -0.034199 0.051816 -0.998071\nouter loop\nvertex 4.148535 0.817264 0.609955\nvertex 5.970649 0.172968 0.514071\nvertex 5.571075 -0.536503 0.490929\nendloop\nendfacet\nfacet normal 0.034895 0.123858 -0.991686\nouter loop\nvertex 4.148535 0.817264 0.609955\nvertex 5.571075 -0.536503 0.490929\nvertex 3.996914 -0.050026 0.496299\nendloop\nendfacet\nfacet normal -0.177314 0.972452 0.151314\nouter loop\nvertex 1.413100 2.191117 4.134416\nvertex 1.957623 2.235735 4.485753\nvertex 2.211112 2.373071 3.900183\nendloop\nendfacet\nfacet normal -0.192322 0.975924 0.102886\nouter loop\nvertex 1.413100 2.191117 4.134416\nvertex 2.211112 2.373071 3.900183\nvertex 1.957623 2.368998 3.464983\nendloop\nendfacet\nfacet normal 0.012141 0.988030 0.153781\nouter loop\nvertex 2.818975 2.265612 4.542609\nvertex 2.888844 2.402780 3.655801\nvertex 2.211112 2.373071 3.900183\nendloop\nendfacet\nfacet normal -0.047645 0.976865 0.208483\nouter loop\nvertex 2.818975 2.265612 4.542609\nvertex 2.211112 2.373071 3.900183\nvertex 1.957623 2.235735 4.485753\nendloop\nendfacet\nfacet normal -0.006157 0.999964 -0.005773\nouter loop\nvertex 2.818976 2.370519 2.809858\nvertex 1.957623 2.368998 3.464983\nvertex 2.211112 2.373071 3.900183\nendloop\nendfacet\nfacet normal -0.055802 0.997881 -0.033447\nouter loop\nvertex 2.818976 2.370519 2.809858\nvertex 2.211112 2.373071 3.900183\nvertex 2.888844 2.402780 3.655801\nendloop\nendfacet\nfacet normal -0.591580 0.781961 0.196391\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 1.052529 1.776505 4.699124\nvertex 1.413100 2.191117 4.134416\nendloop\nendfacet\nfacet normal -0.579142 0.747851 0.324520\nouter loop\nvertex 0.560000 1.566667 4.051001\nvertex 1.413100 2.191117 4.134416\nvertex 1.052529 2.154190 3.576036\nendloop\nendfacet\nfacet normal -0.353218 0.863464 0.360093\nouter loop\nvertex 1.052529 1.776505 4.699124\nvertex 1.664815 1.871528 5.071865\nvertex 1.957623 2.235735 4.485753\nendloop\nendfacet\nfacet normal -0.334023 0.848772 0.409897\nouter loop\nvertex 1.052529 1.776505 4.699124\nvertex 1.957623 2.235735 4.485753\nvertex 1.413100 2.191117 4.134416\nendloop\nendfacet\nfacet normal -0.221081 0.972093 0.078474\nouter loop\nvertex 1.052529 2.154190 3.576036\nvertex 1.413100 2.191117 4.134416\nvertex 1.957623 2.368998 3.464983\nendloop\nendfacet\nfacet normal -0.222661 0.972618 0.066613\nouter loop\nvertex 1.052529 2.154190 3.576036\nvertex 1.957623 2.368998 3.464983\nvertex 1.664815 2.340921 2.896196\nendloop\nendfacet\nfacet normal 0.017576 0.932290 0.361283\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 4.161652 2.331292 4.307803\nvertex 2.818975 2.265612 4.542609\nendloop\nendfacet\nfacet normal -0.053358 0.891025 0.450808\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 2.818975 2.265612 4.542609\nvertex 2.553637 1.874253 5.284729\nendloop\nendfacet\nfacet normal 0.009362 0.995815 0.090909\nouter loop\nvertex 4.161652 2.331292 4.307803\nvertex 4.101852 2.427727 3.257616\nvertex 2.888844 2.402780 3.655801\nendloop\nendfacet\nfacet normal -0.021913 0.988270 0.151135\nouter loop\nvertex 4.161652 2.331292 4.307803\nvertex 2.888844 2.402780 3.655801\nvertex 2.818975 2.265612 4.542609\nendloop\nendfacet\nfacet normal -0.060539 0.891686 0.448589\nouter loop\nvertex 2.553637 1.874253 5.284729\nvertex 2.818975 2.265612 4.542609\nvertex 1.957623 2.235735 4.485753\nendloop\nendfacet\nfacet normal -0.117852 0.868776 0.480976\nouter loop\nvertex 2.553637 1.874253 5.284729\nvertex 1.957623 2.235735 4.485753\nvertex 1.664815 1.871528 5.071865\nendloop\nendfacet\nfacet normal 0.155860 0.967636 -0.198467\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 2.553637 2.266812 2.095851\nvertex 2.818976 2.370519 2.809858\nendloop\nendfacet\nfacet normal -0.144269 0.890113 -0.432302\nouter loop\nvertex 4.272728 1.792930 1.135445\nvertex 2.818976 2.370519 2.809858\nvertex 4.161652 2.306381 2.229715\nendloop\nendfacet\nfacet normal 0.026538 0.997666 -0.062909\nouter loop\nvertex 2.553637 2.266812 2.095851\nvertex 1.664815 2.340921 2.896196\nvertex 1.957623 2.368998 3.464983\nendloop\nendfacet\nfacet normal -0.086627 0.989971 -0.111598\nouter loop\nvertex 2.553637 2.266812 2.095851\nvertex 1.957623 2.368998 3.464983\nvertex 2.818976 2.370519 2.809858\nendloop\nendfacet\nfacet normal 0.030174 0.998721 -0.040579\nouter loop\nvertex 4.161652 2.306381 2.229715\nvertex 2.818976 2.370519 2.809858\nvertex 2.888844 2.402780 3.655801\nendloop\nendfacet\nfacet normal -0.059923 0.990907 -0.120465\nouter loop\nvertex 4.161652 2.306381 2.229715\nvertex 2.888844 2.402780 3.655801\nvertex 4.101852 2.427727 3.257616\nendloop\nendfacet\nfacet normal -0.024915 -0.999333 0.026680\nouter loop\nvertex 6.154458 -2.483407 3.738467\nvertex 5.628341 -2.494678 2.824974\nvertex 6.979553 -2.537423 2.485754\nendloop\nendfacet\nfacet normal -0.051736 -0.998620 0.008983\nouter loop\nvertex 6.154458 -2.483407 3.738467\nvertex 6.979553 -2.537423 2.485754\nvertex 7.876621 -2.580005 2.918531\nendloop\nendfacet\nfacet normal -0.046870 -0.980837 -0.189108\nouter loop\nvertex 5.521408 -2.354881 1.900373\nvertex 7.436999 -2.427878 1.804205\nvertex 6.979553 -2.537423 2.485754\nendloop\nendfacet\nfacet normal -0.066795 -0.987667 -0.141609\nouter loop\nvertex 5.521408 -2.354881 1.900373\nvertex 6.979553 -2.537423 2.485754\nvertex 5.628341 -2.494678 2.824974\nendloop\nendfacet\nfacet normal -0.001211 -0.995435 -0.095434\nouter loop\nvertex 9.316480 -2.494374 2.007067\nvertex 7.876621 -2.580005 2.918531\nvertex 6.979553 -2.537423 2.485754\nendloop\nendfacet\nfacet normal -0.016568 -0.985391 -0.169501\nouter loop\nvertex 9.316480 -2.494374 2.007067\nvertex 6.979553 -2.537423 2.485754\nvertex 7.436999 -2.427878 1.804205\nendloop\nendfacet\nfacet normal 0.031593 -0.945072 0.325333\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 4.454588 -2.322237 4.371733\nvertex 6.154458 -2.483407 3.738467\nendloop\nendfacet\nfacet normal -0.154841 -0.955382 0.251534\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 6.154458 -2.483407 3.738467\nvertex 7.178772 -2.418575 4.615271\nendloop\nendfacet\nfacet normal -0.012858 -0.994788 0.101147\nouter loop\nvertex 4.454588 -2.322237 4.371733\nvertex 4.081018 -2.428884 3.275362\nvertex 5.628341 -2.494678 2.824974\nendloop\nendfacet\nfacet normal -0.073964 -0.995749 0.054885\nouter loop\nvertex 4.454588 -2.322237 4.371733\nvertex 5.628341 -2.494678 2.824974\nvertex 6.154458 -2.483407 3.738467\nendloop\nendfacet\nfacet normal -0.013366 -0.995919 0.089256\nouter loop\nvertex 7.178772 -2.418575 4.615271\nvertex 6.154458 -2.483407 3.738467\nvertex 7.876621 -2.580005 2.918531\nendloop\nendfacet\nfacet normal -0.067176 -0.995483 0.067083\nouter loop\nvertex 7.178772 -2.418575 4.615271\nvertex 7.876621 -2.580005 2.918531\nvertex 9.061987 -2.615098 3.584776\nendloop\nendfacet\nfacet normal -0.059376 -0.896912 -0.438204\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 5.514146 -1.967330 1.108122\nvertex 5.521408 -2.354881 1.900373\nendloop\nendfacet\nfacet normal -0.090043 -0.926304 -0.365858\nouter loop\nvertex 3.212122 -1.828283 1.135445\nvertex 5.521408 -2.354881 1.900373\nvertex 3.804913 -2.318981 2.231933\nendloop\nendfacet\nfacet normal -0.047082 -0.887985 -0.457456\nouter loop\nvertex 5.514146 -1.967330 1.108122\nvertex 7.706276 -2.079218 1.099694\nvertex 7.436999 -2.427878 1.804205\nendloop\nendfacet\nfacet normal -0.056189 -0.897066 -0.438309\nouter loop\nvertex 5.514146 -1.967330 1.108122\nvertex 7.436999 -2.427878 1.804205\nvertex 5.521408 -2.354881 1.900373\nendloop\nendfacet\nfacet normal -0.048457 -0.988414 -0.143842\nouter loop\nvertex 3.804913 -2.318981 2.231933\nvertex 5.521408 -2.354881 1.900373\nvertex 5.628341 -2.494678 2.824974\nendloop\nendfacet\nfacet normal -0.067534 -0.993932 -0.086819\nouter loop\nvertex 3.804913 -2.318981 2.231933\nvertex 5.628341 -2.494678 2.824974\nvertex 4.081018 -2.428884 3.275362\nendloop\nendfacet\nfacet normal 0.037829 -0.959677 -0.278547\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 11.040919 -2.582739 2.545703\nvertex 9.316480 -2.494374 2.007067\nendloop\nendfacet\nfacet normal 0.013280 -0.915584 -0.401908\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 9.316480 -2.494374 2.007067\nvertex 10.028108 -2.122718 1.183917\nendloop\nendfacet\nfacet normal -0.005840 -0.999091 -0.042236\nouter loop\nvertex 11.040919 -2.582739 2.545703\nvertex 9.061987 -2.615098 3.584776\nvertex 7.876621 -2.580005 2.918531\nendloop\nendfacet\nfacet normal -0.014561 -0.993107 -0.116304\nouter loop\nvertex 11.040919 -2.582739 2.545703\nvertex 7.876621 -2.580005 2.918531\nvertex 9.316480 -2.494374 2.007067\nendloop\nendfacet\nfacet normal 0.011175 -0.914939 -0.403438\nouter loop\nvertex 10.028108 -2.122718 1.183917\nvertex 9.316480 -2.494374 2.007067\nvertex 7.436999 -2.427878 1.804205\nendloop\nendfacet\nfacet normal -0.000692 -0.896144 -0.443763\nouter loop\nvertex 10.028108 -2.122718 1.183917\nvertex 7.436999 -2.427878 1.804205\nvertex 7.706276 -2.079218 1.099694\nendloop\nendfacet\nfacet normal -0.040521 -0.997608 -0.056007\nouter loop\nvertex 17.317537 -3.084208 5.004945\nvertex 16.903872 -2.995256 3.719807\nvertex 18.486927 -3.029857 3.190796\nendloop\nendfacet\nfacet normal -0.046639 -0.997112 -0.059936\nouter loop\nvertex 17.317537 -3.084208 5.004945\nvertex 18.486927 -3.029857 3.190796\nvertex 19.410824 -3.104883 3.720019\nendloop\nendfacet\nfacet normal -0.053940 -0.980851 -0.187143\nouter loop\nvertex 16.758194 -2.787295 2.417759\nvertex 19.016983 -2.881913 2.262618\nvertex 18.486927 -3.029857 3.190796\nendloop\nendfacet\nfacet normal -0.071516 -0.986171 -0.149509\nouter loop\nvertex 16.758194 -2.787295 2.417759\nvertex 18.486927 -3.029857 3.190796\nvertex 16.903872 -2.995256 3.719807\nendloop\nendfacet\nfacet normal -0.011128 -0.992556 -0.121283\nouter loop\nvertex 21.142828 -2.968985 2.448945\nvertex 19.410824 -3.104883 3.720019\nvertex 18.486927 -3.029857 3.190796\nendloop\nendfacet\nfacet normal -0.025313 -0.984870 -0.171436\nouter loop\nvertex 21.142828 -2.968985 2.448945\nvertex 18.486927 -3.029857 3.190796\nvertex 19.016983 -2.881913 2.262618\nendloop\nendfacet\nfacet normal -0.053978 -0.998535 -0.003898\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 17.317537 -3.084208 5.004945\nvertex 18.135849 -3.132686 6.091653\nendloop\nendfacet\nfacet normal -0.053604 -0.993996 0.095390\nouter loop\nvertex 18.135849 -3.132686 6.091653\nvertex 15.780942 -2.814433 8.084641\nvertex 15.436029 -2.794299 8.100622\nendloop\nendfacet\nfacet normal -0.053600 -0.993996 0.095388\nouter loop\nvertex 15.436029 -2.794299 8.100622\nvertex 15.539762 -2.781838 8.288755\nvertex 15.458335 -2.770834 8.357668\nendloop\nendfacet\nfacet normal -0.053602 -0.993996 0.095392\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 18.135849 -3.132686 6.091653\nvertex 15.436029 -2.794299 8.100622\nendloop\nendfacet\nfacet normal -0.053597 -0.993996 0.095394\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 14.999439 -2.963156 6.095771\nvertex 15.436029 -2.794299 8.100622\nendloop\nendfacet\nfacet normal -0.049442 -0.998435 -0.026141\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 14.808001 -2.908951 4.387503\nvertex 16.903872 -2.995256 3.719807\nendloop\nendfacet\nfacet normal -0.073363 -0.996274 -0.045343\nouter loop\nvertex 14.999439 -2.963156 6.095771\nvertex 16.903872 -2.995256 3.719807\nvertex 17.317537 -3.084208 5.004945\nendloop\nendfacet\nfacet normal -0.025465 -0.999353 -0.025406\nouter loop\nvertex 18.135849 -3.132686 6.091653\nvertex 17.317537 -3.084208 5.004945\nvertex 19.410824 -3.104883 3.720019\nendloop\nendfacet\nfacet normal -0.039013 -0.998704 -0.032681\nouter loop\nvertex 18.135849 -3.132686 6.091653\nvertex 19.410824 -3.104883 3.720019\nvertex 20.531229 -3.172596 4.451771\nendloop\nendfacet\nfacet normal -0.048406 -0.919580 -0.389908\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 16.677395 -2.328955 1.346818\nvertex 16.758194 -2.787295 2.417759\nendloop\nendfacet\nfacet normal -0.080440 -0.949832 -0.302241\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 16.758194 -2.787295 2.417759\nvertex 14.374381 -2.709676 2.808274\nendloop\nendfacet\nfacet normal -0.050820 -0.907086 -0.417866\nouter loop\nvertex 16.677395 -2.328955 1.346818\nvertex 19.305408 -2.463877 1.320084\nvertex 19.016983 -2.881913 2.262618\nendloop\nendfacet\nfacet normal -0.065183 -0.919157 -0.388461\nouter loop\nvertex 16.677395 -2.328955 1.346818\nvertex 19.016983 -2.881913 2.262618\nvertex 16.758194 -2.787295 2.417759\nendloop\nendfacet\nfacet normal -0.056911 -0.986856 -0.151252\nouter loop\nvertex 14.374381 -2.709676 2.808274\nvertex 16.758194 -2.787295 2.417759\nvertex 16.903872 -2.995256 3.719807\nendloop\nendfacet\nfacet normal -0.074213 -0.991724 -0.104763\nouter loop\nvertex 14.374381 -2.709676 2.808274\nvertex 16.903872 -2.995256 3.719807\nvertex 14.808001 -2.908951 4.387503\nendloop\nendfacet\nfacet normal 0.017575 -0.964533 -0.263376\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 22.986065 -3.078571 2.973266\nvertex 21.142828 -2.968985 2.448945\nendloop\nendfacet\nfacet normal -0.006963 -0.923448 -0.383662\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 21.142828 -2.968985 2.448945\nvertex 22.056328 -2.526146 1.366480\nendloop\nendfacet\nfacet normal -0.009040 -0.996881 -0.078405\nouter loop\nvertex 22.986065 -3.078571 2.973266\nvertex 20.531229 -3.172596 4.451771\nvertex 19.410824 -3.104883 3.720019\nendloop\nendfacet\nfacet normal -0.020734 -0.990740 -0.134179\nouter loop\nvertex 22.986065 -3.078571 2.973266\nvertex 19.410824 -3.104883 3.720019\nvertex 21.142828 -2.968985 2.448945\nendloop\nendfacet\nfacet normal -0.004391 -0.924230 -0.381811\nouter loop\nvertex 22.056328 -2.526146 1.366480\nvertex 21.142828 -2.968985 2.448945\nvertex 19.016983 -2.881913 2.262618\nendloop\nendfacet\nfacet normal -0.013758 -0.912470 -0.408912\nouter loop\nvertex 22.056328 -2.526146 1.366480\nvertex 19.016983 -2.881913 2.262618\nvertex 19.305408 -2.463877 1.320084\nendloop\nendfacet\nfacet normal 0.009464 -0.265393 -0.964094\nouter loop\nvertex 21.152800 -1.671543 0.753253\nvertex 19.011806 -1.749285 0.753637\nvertex 18.485788 -1.047572 0.555308\nendloop\nendfacet\nfacet normal 0.039705 -0.143966 -0.988786\nouter loop\nvertex 21.152800 -1.671543 0.753253\nvertex 18.485788 -1.047572 0.555308\nvertex 19.435152 -0.680933 0.540048\nendloop\nendfacet\nfacet normal -0.045444 -0.214786 -0.975603\nouter loop\nvertex 16.746109 -1.541689 0.745126\nvertex 16.898190 -0.628839 0.537072\nvertex 18.485788 -1.047572 0.555308\nendloop\nendfacet\nfacet normal -0.022762 -0.287675 -0.957458\nouter loop\nvertex 16.746109 -1.541689 0.745126\nvertex 18.485788 -1.047572 0.555308\nvertex 19.011806 -1.749285 0.753637\nendloop\nendfacet\nfacet normal -0.017933 0.004821 -0.999828\nouter loop\nvertex 17.376574 0.244999 0.581435\nvertex 19.435152 -0.680933 0.540048\nvertex 18.485788 -1.047572 0.555308\nendloop\nendfacet\nfacet normal 0.021717 0.038830 -0.999010\nouter loop\nvertex 17.376574 0.244999 0.581435\nvertex 18.485788 -1.047572 0.555308\nvertex 16.898190 -0.628839 0.537072\nendloop\nendfacet\nfacet normal 0.003884 -0.580278 -0.814409\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 22.056328 -2.526146 1.366480\nvertex 21.152800 -1.671543 0.753253\nendloop\nendfacet\nfacet normal 0.052271 -0.369286 -0.927845\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 21.152800 -1.671543 0.753253\nvertex 23.085478 -1.280291 0.706413\nendloop\nendfacet\nfacet normal -0.000852 -0.621409 -0.783486\nouter loop\nvertex 22.056328 -2.526146 1.366480\nvertex 19.305408 -2.463877 1.320084\nvertex 19.011806 -1.749285 0.753637\nendloop\nendfacet\nfacet normal 0.020495 -0.568482 -0.822441\nouter loop\nvertex 22.056328 -2.526146 1.366480\nvertex 19.011806 -1.749285 0.753637\nvertex 21.152800 -1.671543 0.753253\nendloop\nendfacet\nfacet normal 0.014057 -0.187031 -0.982253\nouter loop\nvertex 23.085478 -1.280291 0.706413\nvertex 21.152800 -1.671543 0.753253\nvertex 19.435152 -0.680933 0.540048\nendloop\nendfacet\nfacet normal 0.036513 -0.054596 -0.997841\nouter loop\nvertex 23.085478 -1.280291 0.706413\nvertex 19.435152 -0.680933 0.540048\nvertex 20.618484 -0.134188 0.553434\nendloop\nendfacet\nfacet normal -0.068268 -0.478058 -0.875671\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 14.364196 -1.103987 0.691866\nvertex 16.746109 -1.541689 0.745126\nendloop\nendfacet\nfacet normal -0.032443 -0.605127 -0.795467\nouter loop\nvertex 13.235235 -2.149359 1.350582\nvertex 16.746109 -1.541689 0.745126\nvertex 16.677395 -2.328955 1.346818\nendloop\nendfacet\nfacet normal -0.036678 -0.127304 -0.991185\nouter loop\nvertex 14.364196 -1.103987 0.691866\nvertex 14.778099 -0.081578 0.545235\nvertex 16.898190 -0.628839 0.537072\nendloop\nendfacet\nfacet normal -0.018478 -0.219254 -0.975493\nouter loop\nvertex 14.364196 -1.103987 0.691866\nvertex 16.898190 -0.628839 0.537072\nvertex 16.746109 -1.541689 0.745126\nendloop\nendfacet\nfacet normal -0.052309 -0.603519 -0.795631\nouter loop\nvertex 16.677395 -2.328955 1.346818\nvertex 16.746109 -1.541689 0.745126\nvertex 19.011806 -1.749285 0.753637\nendloop\nendfacet\nfacet normal -0.040268 -0.630799 -0.774901\nouter loop\nvertex 16.677395 -2.328955 1.346818\nvertex 19.011806 -1.749285 0.753637\nvertex 19.305408 -2.463877 1.320084\nendloop\nendfacet\nfacet normal -0.114675 0.329351 -0.937218\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 18.347206 1.014438 0.733063\nvertex 17.376574 0.244999 0.581435\nendloop\nendfacet\nfacet normal 0.107539 0.496098 -0.861581\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 17.376574 0.244999 0.581435\nvertex 15.017767 0.994756 0.718727\nendloop\nendfacet\nfacet normal -0.031693 0.092959 -0.995165\nouter loop\nvertex 18.347206 1.014438 0.733063\nvertex 20.618484 -0.134188 0.553434\nvertex 19.435152 -0.680933 0.540048\nendloop\nendfacet\nfacet normal 0.043249 0.140367 -0.989155\nouter loop\nvertex 18.347206 1.014438 0.733063\nvertex 19.435152 -0.680933 0.540048\nvertex 17.376574 0.244999 0.581435\nendloop\nendfacet\nfacet normal -0.035721 0.070167 -0.996895\nouter loop\nvertex 15.017767 0.994756 0.718727\nvertex 17.376574 0.244999 0.581435\nvertex 16.898190 -0.628839 0.537072\nendloop\nendfacet\nfacet normal 0.035271 0.151376 -0.987847\nouter loop\nvertex 15.017767 0.994756 0.718727\nvertex 16.898190 -0.628839 0.537072\nvertex 14.778099 -0.081578 0.545235\nendloop\nendfacet\nfacet normal -0.207907 -0.234473 0.949630\nouter loop\nvertex 8.814745 -1.206727 6.949300\nvertex 10.684258 -1.438964 7.301260\nvertex 11.230325 -0.752508 7.590306\nendloop\nendfacet\nfacet normal -0.221349 -0.176374 0.959112\nouter loop\nvertex 8.814745 -1.206727 6.949300\nvertex 11.230325 -0.752508 7.590306\nvertex 10.351794 -0.324887 7.466191\nendloop\nendfacet\nfacet normal -0.182416 -0.136784 0.973660\nouter loop\nvertex 12.766925 -1.493038 7.774157\nvertex 12.825415 -0.437871 7.933350\nvertex 11.230325 -0.752508 7.590306\nendloop\nendfacet\nfacet normal -0.221337 -0.223614 0.949214\nouter loop\nvertex 12.766925 -1.493038 7.774157\nvertex 11.230325 -0.752508 7.590306\nvertex 10.684258 -1.438964 7.301260\nendloop\nendfacet\nfacet normal -0.175156 -0.074923 0.981686\nouter loop\nvertex 12.479491 0.556369 7.913082\nvertex 10.351794 -0.324887 7.466191\nvertex 11.230325 -0.752508 7.590306\nendloop\nendfacet\nfacet normal -0.200587 -0.049845 0.978407\nouter loop\nvertex 12.479491 0.556369 7.913082\nvertex 11.230325 -0.752508 7.590306\nvertex 12.825415 -0.437871 7.933350\nendloop\nendfacet\nfacet normal -0.175617 -0.583240 0.793089\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 8.131913 -1.975336 6.232861\nvertex 8.814745 -1.206727 6.949300\nendloop\nendfacet\nfacet normal -0.231487 -0.428725 0.873275\nouter loop\nvertex 5.333334 -1.828283 5.721304\nvertex 8.814745 -1.206727 6.949300\nvertex 7.198318 -0.798686 6.721142\nendloop\nendfacet\nfacet normal -0.207574 -0.580538 0.787330\nouter loop\nvertex 8.131913 -1.975336 6.232861\nvertex 10.391977 -2.143262 6.704890\nvertex 10.684258 -1.438964 7.301260\nendloop\nendfacet\nfacet normal -0.219985 -0.553386 0.803349\nouter loop\nvertex 8.131913 -1.975336 6.232861\nvertex 10.684258 -1.438964 7.301260\nvertex 8.814745 -1.206727 6.949300\nendloop\nendfacet\nfacet normal -0.191770 -0.225608 0.955157\nouter loop\nvertex 7.198318 -0.798686 6.721142\nvertex 8.814745 -1.206727 6.949300\nvertex 10.351794 -0.324887 7.466191\nendloop\nendfacet\nfacet normal -0.211874 -0.115797 0.970413\nouter loop\nvertex 7.198318 -0.798686 6.721142\nvertex 10.351794 -0.324887 7.466191\nvertex 9.218365 0.199331 7.281278\nendloop\nendfacet\nfacet normal -0.252034 -0.090897 0.963440\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 15.000001 -1.500000 8.357668\nvertex 12.766925 -1.493038 7.774157\nendloop\nendfacet\nfacet normal -0.387026 -0.446878 0.806542\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 12.766925 -1.493038 7.774157\nvertex 12.673998 -2.361658 7.248292\nendloop\nendfacet\nfacet normal -0.191514 0.000000 0.981490\nouter loop\nvertex 15.000001 -1.500000 8.357668\nvertex 15.000001 0.000000 8.357668\nvertex 12.825415 -0.437871 7.933350\nendloop\nendfacet\nfacet normal -0.251025 -0.130785 0.959105\nouter loop\nvertex 15.000001 -1.500000 8.357668\nvertex 12.825415 -0.437871 7.933350\nvertex 12.766925 -1.493038 7.774157\nendloop\nendfacet\nfacet normal -0.205027 -0.490744 0.846838\nouter loop\nvertex 12.673998 -2.361658 7.248292\nvertex 12.766925 -1.493038 7.774157\nvertex 10.684258 -1.438964 7.301260\nendloop\nendfacet\nfacet normal -0.241796 -0.566639 0.787690\nouter loop\nvertex 12.673998 -2.361658 7.248292\nvertex 10.684258 -1.438964 7.301260\nvertex 10.391977 -2.143262 6.704890\nendloop\nendfacet\nfacet normal -0.178002 0.042065 0.983131\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 11.600214 1.316005 7.721383\nvertex 12.479491 0.556369 7.913082\nendloop\nendfacet\nfacet normal -0.199291 0.071876 0.977301\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 12.479491 0.556369 7.913082\nvertex 15.000001 1.500000 8.357668\nendloop\nendfacet\nfacet normal -0.171271 -0.022875 0.984958\nouter loop\nvertex 11.600214 1.316005 7.721383\nvertex 9.218365 0.199331 7.281278\nvertex 10.351794 -0.324887 7.466191\nendloop\nendfacet\nfacet normal -0.207969 0.006110 0.978116\nouter loop\nvertex 11.600214 1.316005 7.721383\nvertex 10.351794 -0.324887 7.466191\nvertex 12.479491 0.556369 7.913082\nendloop\nendfacet\nfacet normal -0.160593 -0.035767 0.986373\nouter loop\nvertex 15.000001 1.500000 8.357668\nvertex 12.479491 0.556369 7.913082\nvertex 12.825415 -0.437871 7.933350\nendloop\nendfacet\nfacet normal -0.191514 0.000000 0.981490\nouter loop\nvertex 15.000001 1.500000 8.357668\nvertex 12.825415 -0.437871 7.933350\nvertex 15.000001 0.000000 8.357668\nendloop\nendfacet\nfacet normal -0.084059 0.991947 0.094739\nouter loop\nvertex 8.334797 2.473336 5.217071\nvertex 10.207706 2.583551 5.724866\nvertex 11.047479 2.728813 4.949031\nendloop\nendfacet\nfacet normal -0.088305 0.994612 0.054306\nouter loop\nvertex 8.334797 2.473336 5.217071\nvertex 11.047479 2.728813 4.949031\nvertex 10.230559 2.689977 4.331943\nendloop\nendfacet\nfacet normal -0.053528 0.997617 0.043540\nouter loop\nvertex 12.456796 2.756068 6.057173\nvertex 12.761621 2.829240 4.755350\nvertex 11.047479 2.728813 4.949031\nendloop\nendfacet\nfacet normal -0.089260 0.992013 0.089121\nouter loop\nvertex 12.456796 2.756068 6.057173\nvertex 11.047479 2.728813 4.949031\nvertex 10.207706 2.583551 5.724866\nendloop\nendfacet\nfacet normal -0.036886 0.999221 -0.014055\nouter loop\nvertex 12.535257 2.764018 3.547343\nvertex 10.230559 2.689977 4.331943\nvertex 11.047479 2.728813 4.949031\nendloop\nendfacet\nfacet normal -0.063164 0.997119 -0.042001\nouter loop\nvertex 12.535257 2.764018 3.547343\nvertex 11.047479 2.728813 4.949031\nvertex 12.761621 2.829240 4.755350\nendloop\nendfacet\nfacet normal -0.119460 0.943694 0.308497\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 6.831068 2.026018 6.003131\nvertex 8.334797 2.473336 5.217071\nendloop\nendfacet\nfacet normal -0.128361 0.964920 0.229027\nouter loop\nvertex 4.272728 1.863636 5.509182\nvertex 8.334797 2.473336 5.217071\nvertex 6.835320 2.433162 4.545931\nendloop\nendfacet\nfacet normal -0.131981 0.946425 0.294720\nouter loop\nvertex 6.831068 2.026018 6.003131\nvertex 9.113427 2.193287 6.488069\nvertex 10.207706 2.583551 5.724866\nendloop\nendfacet\nfacet normal -0.133205 0.949137 0.285299\nouter loop\nvertex 6.831068 2.026018 6.003131\nvertex 10.207706 2.583551 5.724866\nvertex 8.334797 2.473336 5.217071\nendloop\nendfacet\nfacet normal -0.069128 0.993074 0.095003\nouter loop\nvertex 6.835320 2.433162 4.545931\nvertex 8.334797 2.473336 5.217071\nvertex 10.230559 2.689977 4.331943\nendloop\nendfacet\nfacet normal -0.073565 0.996864 0.029151\nouter loop\nvertex 6.835320 2.433162 4.545931\nvertex 10.230559 2.689977 4.331943\nvertex 9.147440 2.632157 3.575842\nendloop\nendfacet\nfacet normal -0.099396 0.987373 0.123348\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 14.959599 2.968169 6.376157\nvertex 12.456796 2.756068 6.057173\nendloop\nendfacet\nfacet normal -0.162862 0.964840 0.206300\nouter loop\nvertex 15.458333 2.770834 8.357668\nvertex 12.456796 2.756068 6.057173\nvertex 11.587097 2.393663 7.065519\nendloop\nendfacet\nfacet normal -0.048012 0.998637 -0.020490\nouter loop\nvertex 14.959599 2.968169 6.376157\nvertex 15.010111 2.935162 4.649097\nvertex 12.761621 2.829240 4.755350\nendloop\nendfacet\nfacet normal -0.088838 0.995426 0.035149\nouter loop\nvertex 14.959599 2.968169 6.376157\nvertex 12.761621 2.829240 4.755350\nvertex 12.456796 2.756068 6.057173\nendloop\nendfacet\nfacet normal -0.110743 0.961846 0.250177\nouter loop\nvertex 11.587097 2.393663 7.065519\nvertex 12.456796 2.756068 6.057173\nvertex 10.207706 2.583551 5.724866\nendloop\nendfacet\nfacet normal -0.142479 0.949067 0.281020\nouter loop\nvertex 11.587097 2.393663 7.065519\nvertex 10.207706 2.583551 5.724866\nvertex 9.113427 2.193287 6.488069\nendloop\nendfacet\nfacet normal 0.038270 0.984884 -0.168934\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 11.713722 2.630891 2.585105\nvertex 12.535257 2.764018 3.547343\nendloop\nendfacet\nfacet normal -0.066287 0.946914 -0.314580\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 12.535257 2.764018 3.547343\nvertex 15.109202 2.798170 3.107773\nendloop\nendfacet\nfacet normal -0.018665 0.998594 -0.049625\nouter loop\nvertex 11.713722 2.630891 2.585105\nvertex 9.147440 2.632157 3.575842\nvertex 10.230559 2.689977 4.331943\nendloop\nendfacet\nfacet normal -0.061045 0.994469 -0.085468\nouter loop\nvertex 11.713722 2.630891 2.585105\nvertex 10.230559 2.689977 4.331943\nvertex 12.535257 2.764018 3.547343\nendloop\nendfacet\nfacet normal -0.021759 0.998520 -0.049835\nouter loop\nvertex 15.109202 2.798170 3.107773\nvertex 12.535257 2.764018 3.547343\nvertex 12.761621 2.829240 4.755350\nendloop\nendfacet\nfacet normal -0.051180 0.994473 -0.091679\nouter loop\nvertex 15.109202 2.798170 3.107773\nvertex 12.761621 2.829240 4.755350\nvertex 15.010111 2.935162 4.649097\nendloop\nendfacet\nfacet normal 0.054722 -0.170693 -0.983804\nouter loop\nvertex 52.674423 -0.709498 0.593456\nvertex 51.466869 -0.919875 0.562790\nvertex 51.196529 -0.417554 0.460599\nendloop\nendfacet\nfacet normal 0.065258 -0.120434 -0.990574\nouter loop\nvertex 52.674423 -0.709498 0.593456\nvertex 51.196529 -0.417554 0.460599\nvertex 51.796329 -0.097145 0.461157\nendloop\nendfacet\nfacet normal -0.010837 -0.123996 -0.992224\nouter loop\nvertex 49.705631 -0.887627 0.535626\nvertex 49.976562 -0.176008 0.443738\nvertex 51.196529 -0.417554 0.460599\nendloop\nendfacet\nfacet normal 0.011591 -0.193348 -0.981062\nouter loop\nvertex 49.705631 -0.887627 0.535626\nvertex 51.196529 -0.417554 0.460599\nvertex 51.466869 -0.919875 0.562790\nendloop\nendfacet\nfacet normal -0.003247 0.007819 -0.999964\nouter loop\nvertex 50.442947 0.478647 0.470053\nvertex 51.796329 -0.097145 0.461157\nvertex 51.196529 -0.417554 0.460599\nendloop\nendfacet\nfacet normal 0.019077 0.026585 -0.999465\nouter loop\nvertex 50.442947 0.478647 0.470053\nvertex 51.196529 -0.417554 0.460599\nvertex 49.976562 -0.176008 0.443738\nendloop\nendfacet\nfacet normal 0.111522 -0.433531 -0.894211\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 53.069855 -1.279745 0.919241\nvertex 52.674423 -0.709498 0.593456\nendloop\nendfacet\nfacet normal 0.131659 -0.331615 -0.934183\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 52.674423 -0.709498 0.593456\nvertex 53.526051 -0.368843 0.592556\nendloop\nendfacet\nfacet normal 0.102334 -0.431799 -0.896146\nouter loop\nvertex 53.069855 -1.279745 0.919241\nvertex 51.584263 -1.469445 0.841000\nvertex 51.466869 -0.919875 0.562790\nendloop\nendfacet\nfacet normal 0.099437 -0.440718 -0.892121\nouter loop\nvertex 53.069855 -1.279745 0.919241\nvertex 51.466869 -0.919875 0.562790\nvertex 52.674423 -0.709498 0.593456\nendloop\nendfacet\nfacet normal 0.053660 -0.136761 -0.989150\nouter loop\nvertex 53.526051 -0.368843 0.592556\nvertex 52.674423 -0.709498 0.593456\nvertex 51.796329 -0.097145 0.461157\nendloop\nendfacet\nfacet normal 0.064366 -0.071597 -0.995355\nouter loop\nvertex 53.526051 -0.368843 0.592556\nvertex 51.796329 -0.097145 0.461157\nvertex 52.409733 0.291152 0.472893\nendloop\nendfacet\nfacet normal -0.013460 -0.238450 -0.971061\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 47.104279 -0.592443 0.499200\nvertex 49.705631 -0.887627 0.535626\nendloop\nendfacet\nfacet normal 0.011553 -0.381650 -0.924235\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 49.705631 -0.887627 0.535626\nvertex 49.558994 -1.541163 0.803662\nendloop\nendfacet\nfacet normal -0.011256 -0.055335 -0.998405\nouter loop\nvertex 47.104279 -0.592443 0.499200\nvertex 47.743988 0.219856 0.446967\nvertex 49.976562 -0.176008 0.443738\nendloop\nendfacet\nfacet normal -0.000617 -0.127831 -0.991796\nouter loop\nvertex 47.104279 -0.592443 0.499200\nvertex 49.976562 -0.176008 0.443738\nvertex 49.705631 -0.887627 0.535626\nendloop\nendfacet\nfacet normal 0.007287 -0.380846 -0.924610\nouter loop\nvertex 49.558994 -1.541163 0.803662\nvertex 49.705631 -0.887627 0.535626\nvertex 51.466869 -0.919875 0.562790\nendloop\nendfacet\nfacet normal 0.032282 -0.445925 -0.894488\nouter loop\nvertex 49.558994 -1.541163 0.803662\nvertex 51.466869 -0.919875 0.562790\nvertex 51.584263 -1.469445 0.841000\nendloop\nendfacet\nfacet normal -0.083283 0.263095 -0.961169\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 51.159924 0.980571 0.545317\nvertex 50.442947 0.478647 0.470053\nendloop\nendfacet\nfacet normal 0.060146 0.369231 -0.927389\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 50.442947 0.478647 0.470053\nvertex 48.246258 1.017376 0.542076\nendloop\nendfacet\nfacet normal -0.022004 0.064914 -0.997648\nouter loop\nvertex 51.159924 0.980571 0.545317\nvertex 52.409733 0.291152 0.472893\nvertex 51.796329 -0.097145 0.461157\nendloop\nendfacet\nfacet normal 0.035397 0.098564 -0.994501\nouter loop\nvertex 51.159924 0.980571 0.545317\nvertex 51.796329 -0.097145 0.461157\nvertex 50.442947 0.478647 0.470053\nendloop\nendfacet\nfacet normal -0.019487 0.054012 -0.998350\nouter loop\nvertex 48.246258 1.017376 0.542076\nvertex 50.442947 0.478647 0.470053\nvertex 49.976562 -0.176008 0.443738\nendloop\nendfacet\nfacet normal 0.017615 0.107453 -0.994054\nouter loop\nvertex 48.246258 1.017376 0.542076\nvertex 49.976562 -0.176008 0.443738\nvertex 47.743988 0.219856 0.446967\nendloop\nendfacet\nfacet normal 0.103997 -0.993227 -0.051811\nouter loop\nvertex 50.249496 -2.189126 2.495076\nvertex 49.912304 -2.191964 1.872657\nvertex 51.167130 -2.052176 1.711607\nendloop\nendfacet\nfacet normal 0.108150 -0.993027 -0.046913\nouter loop\nvertex 50.249496 -2.189126 2.495076\nvertex 51.167130 -2.052176 1.711607\nvertex 51.739006 -2.003437 1.998294\nendloop\nendfacet\nfacet normal 0.067192 -0.926506 -0.370233\nouter loop\nvertex 49.697483 -1.986714 1.281070\nvertex 51.462238 -1.861012 1.286779\nvertex 51.167130 -2.052176 1.711607\nendloop\nendfacet\nfacet normal 0.059813 -0.936137 -0.346512\nouter loop\nvertex 49.697483 -1.986714 1.281070\nvertex 51.167130 -2.052176 1.711607\nvertex 49.912304 -2.191964 1.872657\nendloop\nendfacet\nfacet normal 0.178912 -0.964775 -0.192870\nouter loop\nvertex 52.667137 -1.718126 1.432071\nvertex 51.739006 -2.003437 1.998294\nvertex 51.167130 -2.052176 1.711607\nendloop\nendfacet\nfacet normal 0.149342 -0.936386 -0.317613\nouter loop\nvertex 52.667137 -1.718126 1.432071\nvertex 51.167130 -2.052176 1.711607\nvertex 51.462238 -1.861012 1.286779\nendloop\nendfacet\nfacet normal 0.097164 -0.957821 0.270441\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 47.784302 -2.359905 2.775923\nvertex 50.249496 -2.189126 2.495076\nendloop\nendfacet\nfacet normal 0.041678 -0.980515 0.191974\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 50.249496 -2.189126 2.495076\nvertex 50.865349 -2.053394 3.054627\nendloop\nendfacet\nfacet normal 0.071613 -0.997293 -0.016709\nouter loop\nvertex 47.784302 -2.359905 2.775923\nvertex 47.610008 -2.359042 1.977433\nvertex 49.912304 -2.191964 1.872657\nendloop\nendfacet\nfacet normal 0.065565 -0.997367 -0.030972\nouter loop\nvertex 47.784302 -2.359905 2.775923\nvertex 49.912304 -2.191964 1.872657\nvertex 50.249496 -2.189126 2.495076\nendloop\nendfacet\nfacet normal 0.148268 -0.986023 0.075995\nouter loop\nvertex 50.865349 -2.053394 3.054627\nvertex 50.249496 -2.189126 2.495076\nvertex 51.739006 -2.003437 1.998294\nendloop\nendfacet\nfacet normal 0.126570 -0.990270 0.057849\nouter loop\nvertex 50.865349 -2.053394 3.054627\nvertex 51.739006 -2.003437 1.998294\nvertex 52.331310 -1.905801 2.373729\nendloop\nendfacet\nfacet normal -0.000003 -0.731078 -0.682293\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 49.558994 -1.541163 0.803662\nvertex 49.697483 -1.986714 1.281070\nendloop\nendfacet\nfacet normal 0.027440 -0.631728 -0.774704\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 49.697483 -1.986714 1.281070\nvertex 47.087532 -2.123862 1.300462\nendloop\nendfacet\nfacet normal 0.038818 -0.755992 -0.653429\nouter loop\nvertex 49.558994 -1.541163 0.803662\nvertex 51.584263 -1.469445 0.841000\nvertex 51.462238 -1.861012 1.286779\nendloop\nendfacet\nfacet normal 0.053673 -0.722210 -0.689588\nouter loop\nvertex 49.558994 -1.541163 0.803662\nvertex 51.462238 -1.861012 1.286779\nvertex 49.697483 -1.986714 1.281070\nendloop\nendfacet\nfacet normal 0.046763 -0.938340 -0.342535\nouter loop\nvertex 47.087532 -2.123862 1.300462\nvertex 49.697483 -1.986714 1.281070\nvertex 49.912304 -2.191964 1.872657\nendloop\nendfacet\nfacet normal 0.051025 -0.930529 -0.362647\nouter loop\nvertex 47.087532 -2.123862 1.300462\nvertex 49.912304 -2.191964 1.872657\nvertex 47.610008 -2.359042 1.977433\nendloop\nendfacet\nfacet normal 0.230432 -0.923203 -0.307567\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 53.516243 -1.601796 1.719050\nvertex 52.667137 -1.718126 1.432071\nendloop\nendfacet\nfacet normal 0.148033 -0.806161 -0.572879\nouter loop\nvertex 55.000004 -1.000000 1.024333\nvertex 52.667137 -1.718126 1.432071\nvertex 53.069855 -1.279745 0.919241\nendloop\nendfacet\nfacet normal 0.208521 -0.975108 -0.075387\nouter loop\nvertex 53.516243 -1.601796 1.719050\nvertex 52.331310 -1.905801 2.373729\nvertex 51.739006 -2.003437 1.998294\nendloop\nendfacet\nfacet normal 0.191047 -0.966100 -0.173645\nouter loop\nvertex 53.516243 -1.601796 1.719050\nvertex 51.739006 -2.003437 1.998294\nvertex 52.667137 -1.718126 1.432071\nendloop\nendfacet\nfacet normal 0.163964 -0.809735 -0.563422\nouter loop\nvertex 53.069855 -1.279745 0.919241\nvertex 52.667137 -1.718126 1.432071\nvertex 51.462238 -1.861012 1.286779\nendloop\nendfacet\nfacet normal 0.130727 -0.762334 -0.633843\nouter loop\nvertex 53.069855 -1.279745 0.919241\nvertex 51.462238 -1.861012 1.286779\nvertex 51.584263 -1.469445 0.841000\nendloop\nendfacet\nfacet normal 0.184375 -0.318695 0.929752\nouter loop\nvertex 36.147072 -1.831106 6.448225\nvertex 40.017311 -1.760391 5.704975\nvertex 41.560101 -1.103757 5.624108\nendloop\nendfacet\nfacet normal 0.165458 -0.122603 0.978566\nouter loop\nvertex 36.147072 -1.831106 6.448225\nvertex 41.560101 -1.103757 5.624108\nvertex 39.862602 -0.822579 5.946353\nendloop\nendfacet\nfacet normal 0.183797 -0.244654 0.952031\nouter loop\nvertex 44.075966 -1.492789 5.038428\nvertex 44.441277 -0.694113 5.173146\nvertex 41.560101 -1.103757 5.624108\nendloop\nendfacet\nfacet normal 0.173716 -0.292338 0.940405\nouter loop\nvertex 44.075966 -1.492789 5.038428\nvertex 41.560101 -1.103757 5.624108\nvertex 40.017311 -1.760391 5.704975\nendloop\nendfacet\nfacet normal 0.180735 -0.035334 0.982897\nouter loop\nvertex 43.582516 0.046202 5.293565\nvertex 39.862602 -0.822579 5.946353\nvertex 41.560101 -1.103757 5.624108\nendloop\nendfacet\nfacet normal 0.152392 0.016036 0.988190\nouter loop\nvertex 43.582516 0.046202 5.293565\nvertex 41.560101 -1.103757 5.624108\nvertex 44.441277 -0.694113 5.173146\nendloop\nendfacet\nfacet normal 0.172939 -0.712636 0.679884\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 37.831306 -2.456728 5.531137\nvertex 40.017311 -1.760391 5.704975\nendloop\nendfacet\nfacet normal 0.166410 -0.557232 0.813511\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 40.017311 -1.760391 5.704975\nvertex 36.147072 -1.831106 6.448225\nendloop\nendfacet\nfacet normal 0.187405 -0.213269 0.958851\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 36.147072 -1.831106 6.448225\nvertex 39.862602 -0.822579 5.946353\nendloop\nendfacet\nfacet normal 0.168591 0.003703 0.985679\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 39.862602 -0.822579 5.946353\nvertex 37.555817 -0.354681 6.339149\nendloop\nendfacet\nfacet normal 0.168089 -0.512462 0.842097\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 47.781036 -1.082973 4.548262\nvertex 44.075966 -1.492789 5.038428\nendloop\nendfacet\nfacet normal 0.136009 -0.619029 0.773502\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 44.075966 -1.492789 5.038428\nvertex 42.545757 -2.222376 4.723609\nendloop\nendfacet\nfacet normal 0.166339 -0.139921 0.976091\nouter loop\nvertex 47.781036 -1.082973 4.548262\nvertex 47.583881 -0.209556 4.707063\nvertex 44.441277 -0.694113 5.173146\nendloop\nendfacet\nfacet normal 0.152744 -0.231906 0.960671\nouter loop\nvertex 47.781036 -1.082973 4.548262\nvertex 44.441277 -0.694113 5.173146\nvertex 44.075966 -1.492789 5.038428\nendloop\nendfacet\nfacet normal 0.163914 -0.660109 0.733068\nouter loop\nvertex 42.545757 -2.222376 4.723609\nvertex 44.075966 -1.492789 5.038428\nvertex 40.017311 -1.760391 5.704975\nendloop\nendfacet\nfacet normal 0.157177 -0.673692 0.722104\nouter loop\nvertex 42.545757 -2.222376 4.723609\nvertex 40.017311 -1.760391 5.704975\nvertex 37.831306 -2.456728 5.531137\nendloop\nendfacet\nfacet normal 0.198517 0.307649 0.930561\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 41.577522 0.722469 5.497714\nvertex 43.582516 0.046202 5.293565\nendloop\nendfacet\nfacet normal 0.086579 0.404526 0.910419\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 43.582516 0.046202 5.293565\nvertex 46.970215 0.694892 4.683170\nendloop\nendfacet\nfacet normal 0.183268 0.081065 0.979715\nouter loop\nvertex 41.577522 0.722469 5.497714\nvertex 37.555817 -0.354681 6.339149\nvertex 39.862602 -0.822579 5.946353\nendloop\nendfacet\nfacet normal 0.142676 0.126675 0.981630\nouter loop\nvertex 41.577522 0.722469 5.497714\nvertex 39.862602 -0.822579 5.946353\nvertex 43.582516 0.046202 5.293565\nendloop\nendfacet\nfacet normal 0.170270 0.037342 0.984690\nouter loop\nvertex 46.970215 0.694892 4.683170\nvertex 43.582516 0.046202 5.293565\nvertex 44.441277 -0.694113 5.173146\nendloop\nendfacet\nfacet normal 0.128644 0.113311 0.985196\nouter loop\nvertex 46.970215 0.694892 4.683170\nvertex 44.441277 -0.694113 5.173146\nvertex 47.583881 -0.209556 4.707063\nendloop\nendfacet\nfacet normal 0.039897 0.997857 0.051864\nouter loop\nvertex 43.657722 2.568572 2.769760\nvertex 44.696526 2.563327 2.071559\nvertex 42.040512 2.681520 1.840692\nendloop\nendfacet\nfacet normal 0.050933 0.998167 0.032691\nouter loop\nvertex 43.657722 2.568572 2.769760\nvertex 42.040512 2.681520 1.840692\nvertex 40.275978 2.759886 2.197073\nendloop\nendfacet\nfacet normal 0.046625 0.963783 -0.262580\nouter loop\nvertex 44.900307 2.428381 1.419360\nvertex 41.148026 2.594087 1.361296\nvertex 42.040512 2.681520 1.840692\nendloop\nendfacet\nfacet normal 0.059680 0.981049 -0.184341\nouter loop\nvertex 44.900307 2.428381 1.419360\nvertex 42.040512 2.681520 1.840692\nvertex 44.696526 2.563327 2.071559\nendloop\nendfacet\nfacet normal 0.017645 0.991277 -0.130608\nouter loop\nvertex 37.490425 2.725876 1.562616\nvertex 40.275978 2.759886 2.197073\nvertex 42.040512 2.681520 1.840692\nendloop\nendfacet\nfacet normal 0.022990 0.975085 -0.220638\nouter loop\nvertex 37.490425 2.725876 1.562616\nvertex 42.040512 2.681520 1.840692\nvertex 41.148026 2.594087 1.361296\nendloop\nendfacet\nfacet normal 0.023267 0.907364 0.419702\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 46.986958 2.274199 3.221608\nvertex 43.657722 2.568572 2.769760\nendloop\nendfacet\nfacet normal 0.118241 0.934128 0.336784\nouter loop\nvertex 45.262634 1.792930 4.357667\nvertex 43.657722 2.568572 2.769760\nvertex 41.623692 2.542653 3.555777\nendloop\nendfacet\nfacet normal 0.043934 0.986073 0.160405\nouter loop\nvertex 46.986958 2.274199 3.221608\nvertex 47.717857 2.373972 2.408079\nvertex 44.696526 2.563327 2.071559\nendloop\nendfacet\nfacet normal 0.073819 0.992003 0.102378\nouter loop\nvertex 46.986958 2.274199 3.221608\nvertex 44.696526 2.563327 2.071559\nvertex 43.657722 2.568572 2.769760\nendloop\nendfacet\nfacet normal 0.035158 0.991699 0.123681\nouter loop\nvertex 41.623692 2.542653 3.555777\nvertex 43.657722 2.568572 2.769760\nvertex 40.275978 2.759886 2.197073\nendloop\nendfacet\nfacet normal 0.060704 0.993274 0.098594\nouter loop\nvertex 41.623692 2.542653 3.555777\nvertex 40.275978 2.759886 2.197073\nvertex 37.925159 2.841050 2.826803\nendloop\nendfacet\nfacet normal 0.055260 0.826010 -0.560941\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 44.908054 2.060014 0.877686\nvertex 44.900307 2.428381 1.419360\nendloop\nendfacet\nfacet normal 0.078874 0.895661 -0.437687\nouter loop\nvertex 49.363640 1.792930 0.923323\nvertex 44.900307 2.428381 1.419360\nvertex 48.242996 2.261178 1.679576\nendloop\nendfacet\nfacet normal 0.037049 0.801405 -0.596974\nouter loop\nvertex 44.908054 2.060014 0.877686\nvertex 40.623978 2.257716 0.877214\nvertex 41.148026 2.594087 1.361296\nendloop\nendfacet\nfacet normal 0.045179 0.826363 -0.561323\nouter loop\nvertex 44.908054 2.060014 0.877686\nvertex 41.148026 2.594087 1.361296\nvertex 44.900307 2.428381 1.419360\nendloop\nendfacet\nfacet normal 0.063333 0.981034 -0.183196\nouter loop\nvertex 48.242996 2.261178 1.679576\nvertex 44.900307 2.428381 1.419360\nvertex 44.696526 2.563327 2.071559\nendloop\nendfacet\nfacet normal 0.073402 0.992204 -0.100712\nouter loop\nvertex 48.242996 2.261178 1.679576\nvertex 44.696526 2.563327 2.071559\nvertex 47.717857 2.373972 2.408079\nendloop\nendfacet\nfacet normal -0.022142 0.924819 -0.379763\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 34.121059 2.869947 2.109917\nvertex 37.490425 2.725876 1.562616\nendloop\nendfacet\nfacet normal -0.013562 0.862312 -0.506196\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 37.490425 2.725876 1.562616\nvertex 36.144936 2.362384 0.979452\nendloop\nendfacet\nfacet normal 0.018682 0.998089 -0.058900\nouter loop\nvertex 34.121059 2.869947 2.109917\nvertex 37.925159 2.841050 2.826803\nvertex 40.275978 2.759886 2.197073\nendloop\nendfacet\nfacet normal 0.019679 0.990031 -0.139468\nouter loop\nvertex 34.121059 2.869947 2.109917\nvertex 40.275978 2.759886 2.197073\nvertex 37.490425 2.725876 1.562616\nendloop\nendfacet\nfacet normal 0.001296 0.847296 -0.531120\nouter loop\nvertex 36.144936 2.362384 0.979452\nvertex 37.490425 2.725876 1.562616\nvertex 41.148026 2.594087 1.361296\nendloop\nendfacet\nfacet normal 0.005994 0.818142 -0.574985\nouter loop\nvertex 36.144936 2.362384 0.979452\nvertex 41.148026 2.594087 1.361296\nvertex 40.623978 2.257716 0.877214\nendloop\nendfacet\nfacet normal -0.035335 0.996555 -0.075031\nouter loop\nvertex 23.709536 3.370836 5.004611\nvertex 24.248417 3.292628 3.712090\nvertex 22.616539 3.195441 3.189772\nendloop\nendfacet\nfacet normal -0.029504 0.996475 -0.078536\nouter loop\nvertex 23.709536 3.370836 5.004611\nvertex 22.616539 3.195441 3.189772\nvertex 21.666407 3.209487 3.724936\nendloop\nendfacet\nfacet normal -0.010336 0.973966 -0.226459\nouter loop\nvertex 24.699970 3.032526 2.394014\nvertex 22.188141 2.974855 2.260623\nvertex 22.616539 3.195441 3.189772\nendloop\nendfacet\nfacet normal 0.003188 0.981282 -0.192549\nouter loop\nvertex 24.699970 3.032526 2.394014\nvertex 22.616539 3.195441 3.189772\nvertex 24.248417 3.292628 3.712090\nendloop\nendfacet\nfacet normal -0.064025 0.988135 -0.139607\nouter loop\nvertex 20.080088 2.928699 2.465025\nvertex 21.666407 3.209487 3.724936\nvertex 22.616539 3.195441 3.189772\nendloop\nendfacet\nfacet normal -0.041972 0.976276 -0.212422\nouter loop\nvertex 20.080088 2.928699 2.465025\nvertex 22.616539 3.195441 3.189772\nvertex 22.188141 2.974855 2.260623\nendloop\nendfacet\nfacet normal -0.007926 0.999149 -0.040472\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 26.798485 3.337256 4.314457\nvertex 24.248417 3.292628 3.712090\nendloop\nendfacet\nfacet normal 0.009354 0.998358 -0.056509\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 24.248417 3.292628 3.712090\nvertex 23.709536 3.370836 5.004611\nendloop\nendfacet\nfacet normal -0.061375 0.997727 -0.027808\nouter loop\nvertex 22.875492 3.349853 6.092598\nvertex 23.709536 3.370836 5.004611\nvertex 21.666407 3.209487 3.724936\nendloop\nendfacet\nfacet normal -0.043999 0.998357 -0.036718\nouter loop\nvertex 22.875492 3.349853 6.092598\nvertex 21.666407 3.209487 3.724936\nvertex 20.559479 3.187713 4.459331\nendloop\nendfacet\nfacet normal 0.003337 0.890130 -0.455693\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 25.097067 2.476448 1.310704\nvertex 24.699970 3.032526 2.394014\nendloop\nendfacet\nfacet normal 0.023317 0.924814 -0.379705\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 24.699970 3.032526 2.394014\nvertex 27.830294 3.080580 2.703281\nendloop\nendfacet\nfacet normal -0.004423 0.879868 -0.475198\nouter loop\nvertex 25.097067 2.476448 1.310704\nvertex 21.998266 2.464462 1.317354\nvertex 22.188141 2.974855 2.260623\nendloop\nendfacet\nfacet normal 0.003754 0.890191 -0.455572\nouter loop\nvertex 25.097067 2.476448 1.310704\nvertex 22.188141 2.974855 2.260623\nvertex 24.699970 3.032526 2.394014\nendloop\nendfacet\nfacet normal 0.003935 0.981328 -0.192301\nouter loop\nvertex 27.830294 3.080580 2.703281\nvertex 24.699970 3.032526 2.394014\nvertex 24.248417 3.292628 3.712090\nendloop\nendfacet\nfacet normal 0.017294 0.989061 -0.146492\nouter loop\nvertex 27.830294 3.080580 2.703281\nvertex 24.248417 3.292628 3.712090\nvertex 26.798485 3.337256 4.314457\nendloop\nendfacet\nfacet normal -0.081501 0.965257 -0.248268\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 18.347837 2.920243 3.000808\nvertex 20.080088 2.928699 2.465025\nendloop\nendfacet\nfacet normal -0.034191 0.899259 -0.436078\nouter loop\nvertex 15.508273 2.303025 1.533252\nvertex 20.080088 2.928699 2.465025\nvertex 19.303099 2.379055 1.392499\nendloop\nendfacet\nfacet normal -0.070078 0.994632 -0.076136\nouter loop\nvertex 18.347837 2.920243 3.000808\nvertex 20.559479 3.187713 4.459331\nvertex 21.666407 3.209487 3.724936\nendloop\nendfacet\nfacet normal -0.052418 0.986695 -0.153901\nouter loop\nvertex 18.347837 2.920243 3.000808\nvertex 21.666407 3.209487 3.724936\nvertex 20.080088 2.928699 2.465025\nendloop\nendfacet\nfacet normal -0.060562 0.905436 -0.420139\nouter loop\nvertex 19.303099 2.379055 1.392499\nvertex 20.080088 2.928699 2.465025\nvertex 22.188141 2.974855 2.260623\nendloop\nendfacet\nfacet normal -0.041035 0.882197 -0.469088\nouter loop\nvertex 19.303099 2.379055 1.392499\nvertex 22.188141 2.974855 2.260623\nvertex 21.998266 2.464462 1.317354\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 15.458335 -2.770834 8.357668\nvertex 15.538308 -2.783193 8.357668\nvertex 15.533590 -2.727700 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 25.813204 -1.764621 8.357668\nvertex 26.000004 -1.750000 8.357668\nvertex 26.000004 0.000000 8.357668\nendloop\nendfacet\nfacet normal -0.000008 0.000000 1.000000\nouter loop\nvertex 26.000004 0.000000 8.357668\nvertex 25.816088 -0.050794 8.357668\nvertex 25.815907 -0.737309 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 25.814472 -1.560014 8.357668\nvertex 25.813204 -1.764621 8.357668\nvertex 26.000004 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 26.000004 0.000000 8.357668\nvertex 25.815907 -0.737309 8.357668\nvertex 25.814472 -1.560014 8.357668\nendloop\nendfacet\nfacet normal -0.000003 0.000000 1.000000\nouter loop\nvertex 26.000004 0.000000 8.357668\nvertex 26.000004 1.750000 8.357668\nvertex 25.813848 1.660502 8.357668\nendloop\nendfacet\nfacet normal 0.000013 0.000000 1.000000\nouter loop\nvertex 26.000004 0.000000 8.357668\nvertex 25.813848 1.660502 8.357668\nvertex 25.814472 1.560014 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 25.816114 0.000000 8.357668\nvertex 25.816088 -0.050794 8.357668\nvertex 26.000004 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 26.000004 0.000000 8.357668\nvertex 25.814472 1.560014 8.357668\nvertex 25.815907 0.737309 8.357668\nendloop\nendfacet\nfacet normal 0.000000 0.000000 1.000000\nouter loop\nvertex 25.815907 0.737309 8.357668\nvertex 25.816114 0.000000 8.357668\nvertex 26.000004 0.000000 8.357668\nendloop\nendfacet\nfacet normal 0.001470 -0.143936 -0.989586\nouter loop\nvertex 39.094803 -1.120972 0.539543\nvertex 35.647991 -1.432970 0.579802\nvertex 34.200043 -0.732904 0.475826\nendloop\nendfacet\nfacet normal 0.008056 -0.062250 -0.998028\nouter loop\nvertex 39.094803 -1.120972 0.539543\nvertex 34.200043 -0.732904 0.475826\nvertex 35.827679 -0.267875 0.459959\nendloop\nendfacet\nfacet normal -0.021287 -0.152833 -0.988023\nouter loop\nvertex 31.578562 -1.461071 0.644944\nvertex 31.257000 -0.427498 0.491994\nvertex 34.200043 -0.732904 0.475826\nendloop\nendfacet\nfacet normal -0.014538 -0.176252 -0.984238\nouter loop\nvertex 31.578562 -1.461071 0.644944\nvertex 34.200043 -0.732904 0.475826\nvertex 35.647991 -1.432970 0.579802\nendloop\nendfacet\nfacet normal -0.013702 0.013843 -0.999810\nouter loop\nvertex 32.156475 0.529089 0.521305\nvertex 35.827679 -0.267875 0.459959\nvertex 34.200043 -0.732904 0.475826\nendloop\nendfacet\nfacet normal -0.002107 0.032606 -0.999466\nouter loop\nvertex 32.156475 0.529089 0.521305\nvertex 34.200043 -0.732904 0.475826\nvertex 31.257000 -0.427498 0.491994\nendloop\nendfacet\nfacet normal 0.011105 -0.300928 -0.953582\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 41.873085 -1.866991 0.807323\nvertex 39.094803 -1.120972 0.539543\nendloop\nendfacet\nfacet normal 0.018277 -0.177180 -0.984009\nouter loop\nvertex 45.986675 -1.473333 0.731000\nvertex 39.094803 -1.120972 0.539543\nvertex 41.912167 -0.620574 0.501772\nendloop\nendfacet\nfacet normal 0.009590 -0.352907 -0.935609\nouter loop\nvertex 41.873085 -1.866991 0.807323\nvertex 37.724285 -2.146670 0.870290\nvertex 35.647991 -1.432970 0.579802\nendloop\nendfacet\nfacet normal 0.014902 -0.288180 -0.957460\nouter loop\nvertex 41.873085 -1.866991 0.807323\nvertex 35.647991 -1.432970 0.579802\nvertex 39.094803 -1.120972 0.539543\nendloop\nendfacet\nfacet normal 0.001875 -0.085762 -0.996314\nouter loop\nvertex 41.912167 -0.620574 0.501772\nvertex 39.094803 -1.120972 0.539543\nvertex 35.827679 -0.267875 0.459959\nendloop\nendfacet\nfacet normal 0.006244 -0.010821 -0.999922\nouter loop\nvertex 41.912167 -0.620574 0.501772\nvertex 35.827679 -0.267875 0.459959\nvertex 38.036938 0.306147 0.467543\nendloop\nendfacet\nfacet normal -0.037686 -0.459402 -0.887429\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 27.419786 -1.179824 0.675958\nvertex 31.578562 -1.461071 0.644944\nendloop\nendfacet\nfacet normal -0.038934 -0.455450 -0.889410\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 31.578562 -1.461071 0.644944\nvertex 33.108257 -2.339576 1.027848\nendloop\nendfacet\nfacet normal -0.024165 -0.119452 -0.992546\nouter loop\nvertex 27.419786 -1.179824 0.675958\nvertex 27.720016 0.032394 0.522759\nvertex 31.257000 -0.427498 0.491994\nendloop\nendfacet\nfacet normal -0.017631 -0.151731 -0.988265\nouter loop\nvertex 27.419786 -1.179824 0.675958\nvertex 31.257000 -0.427498 0.491994\nvertex 31.578562 -1.461071 0.644944\nendloop\nendfacet\nfacet normal -0.011675 -0.416542 -0.909041\nouter loop\nvertex 33.108257 -2.339576 1.027848\nvertex 31.578562 -1.461071 0.644944\nvertex 35.647991 -1.432970 0.579802\nendloop\nendfacet\nfacet normal -0.013914 -0.411410 -0.911344\nouter loop\nvertex 33.108257 -2.339576 1.027848\nvertex 35.647991 -1.432970 0.579802\nvertex 37.724285 -2.146670 0.870290\nendloop\nendfacet\nfacet normal -0.062065 0.292420 -0.954274\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 34.217098 1.287853 0.619794\nvertex 32.156475 0.529089 0.521305\nendloop\nendfacet\nfacet normal 0.036104 0.381657 -0.923599\nouter loop\nvertex 30.224367 2.412967 1.224249\nvertex 32.156475 0.529089 0.521305\nvertex 28.402740 1.203649 0.653316\nendloop\nendfacet\nfacet normal -0.018264 0.083456 -0.996344\nouter loop\nvertex 34.217098 1.287853 0.619794\nvertex 38.036938 0.306147 0.467543\nvertex 35.827679 -0.267875 0.459959\nendloop\nendfacet\nfacet normal 0.007171 0.109542 -0.993956\nouter loop\nvertex 34.217098 1.287853 0.619794\nvertex 35.827679 -0.267875 0.459959\nvertex 32.156475 0.529089 0.521305\nendloop\nendfacet\nfacet normal -0.025328 0.054402 -0.998198\nouter loop\nvertex 28.402740 1.203649 0.653316\nvertex 32.156475 0.529089 0.521305\nvertex 31.257000 -0.427498 0.491994\nendloop\nendfacet\nfacet normal 0.005356 0.107696 -0.994169\nouter loop\nvertex 28.402740 1.203649 0.653316\nvertex 31.257000 -0.427498 0.491994\nvertex 27.720016 0.032394 0.522759\nendloop\nendfacet\nfacet normal 0.065139 -0.992975 0.098780\nouter loop\nvertex 39.476257 -2.712869 4.191426\nvertex 35.635860 -2.889090 4.952492\nvertex 33.974491 -3.061083 4.319118\nendloop\nendfacet\nfacet normal 0.064169 -0.996860 0.046393\nouter loop\nvertex 39.476257 -2.712869 4.191426\nvertex 33.974491 -3.061083 4.319118\nvertex 35.673954 -2.984780 3.608021\nendloop\nendfacet\nfacet normal 0.048487 -0.998051 0.039288\nouter loop\nvertex 31.104549 -3.148645 5.636679\nvertex 30.579285 -3.223353 4.387111\nvertex 33.974491 -3.061083 4.319118\nendloop\nendfacet\nfacet normal 0.069964 -0.993805 0.086351\nouter loop\nvertex 31.104549 -3.148645 5.636679\nvertex 33.974491 -3.061083 4.319118\nvertex 35.635860 -2.889090 4.952492\nendloop\nendfacet\nfacet normal 0.033576 -0.999072 -0.026961\nouter loop\nvertex 31.234276 -3.121788 3.156084\nvertex 35.673954 -2.984780 3.608021\nvertex 33.974491 -3.061083 4.319118\nendloop\nendfacet\nfacet normal 0.046511 -0.997260 -0.057531\nouter loop\nvertex 31.234276 -3.121788 3.156084\nvertex 33.974491 -3.061083 4.319118\nvertex 30.579285 -3.223353 4.387111\nendloop\nendfacet\nfacet normal 0.087711 -0.931605 0.352731\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 42.545757 -2.222376 4.723609\nvertex 39.476257 -2.712869 4.191426\nendloop\nendfacet\nfacet normal 0.086649 -0.973212 0.212956\nouter loop\nvertex 48.166676 -2.000000 3.913223\nvertex 39.476257 -2.712869 4.191426\nvertex 42.552837 -2.614465 3.389307\nendloop\nendfacet\nfacet normal 0.101486 -0.942296 0.319029\nouter loop\nvertex 42.545757 -2.222376 4.723609\nvertex 37.831306 -2.456728 5.531137\nvertex 35.635860 -2.889090 4.952492\nendloop\nendfacet\nfacet normal 0.101432 -0.951147 0.291600\nouter loop\nvertex 42.545757 -2.222376 4.723609\nvertex 35.635860 -2.889090 4.952492\nvertex 39.476257 -2.712869 4.191426\nendloop\nendfacet\nfacet normal 0.056520 -0.993885 0.094858\nouter loop\nvertex 42.552837 -2.614465 3.389307\nvertex 39.476257 -2.712869 4.191426\nvertex 35.673954 -2.984780 3.608021\nendloop\nendfacet\nfacet normal 0.054186 -0.998436 0.013738\nouter loop\nvertex 42.552837 -2.614465 3.389307\nvertex 35.673954 -2.984780 3.608021\nvertex 37.887997 -2.875850 2.791907\nendloop\nendfacet\nfacet normal 0.034076 -0.999087 -0.025763\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 26.492159 -3.367654 4.577150\nvertex 30.579285 -3.223353 4.387111\nendloop\nendfacet\nfacet normal 0.061829 -0.997519 0.033649\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 30.579285 -3.223353 4.387111\nvertex 31.104549 -3.148645 5.636679\nendloop\nendfacet\nfacet normal 0.094295 -0.961011 0.259935\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 31.104549 -3.148645 5.636679\nvertex 35.635860 -2.889090 4.952492\nendloop\nendfacet\nfacet normal 0.111006 -0.950793 0.289259\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 35.635860 -2.889090 4.952492\nvertex 37.831306 -2.456728 5.531137\nendloop\nendfacet\nfacet normal -0.025109 -0.971689 -0.234924\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 33.042091 -2.926533 2.155251\nvertex 31.234276 -3.121788 3.156084\nendloop\nendfacet\nfacet normal 0.023137 -0.936595 -0.349649\nouter loop\nvertex 26.752544 -2.589665 1.434137\nvertex 31.234276 -3.121788 3.156084\nvertex 26.704079 -3.180421 3.013374\nendloop\nendfacet\nfacet normal 0.020573 -0.996801 -0.077235\nouter loop\nvertex 33.042091 -2.926533 2.155251\nvertex 37.887997 -2.875850 2.791907\nvertex 35.673954 -2.984780 3.608021\nendloop\nendfacet\nfacet normal 0.042510 -0.992246 -0.116794\nouter loop\nvertex 33.042091 -2.926533 2.155251\nvertex 35.673954 -2.984780 3.608021\nvertex 31.234276 -3.121788 3.156084\nendloop\nendfacet\nfacet normal 0.015242 -0.997130 -0.074158\nouter loop\nvertex 26.704079 -3.180421 3.013374\nvertex 31.234276 -3.121788 3.156084\nvertex 30.579285 -3.223353 4.387111\nendloop\nendfacet\nfacet normal 0.029716 -0.992937 -0.114859\nouter loop\nvertex 26.704079 -3.180421 3.013374\nvertex 30.579285 -3.223353 4.387111\nvertex 26.492159 -3.367654 4.577150\nendloop\nendfacet\nfacet normal -0.045029 0.998983 -0.002168\nouter loop\nvertex 19.461210 3.199903 6.848686\nvertex 20.253862 3.238130 8.000117\nvertex 21.113426 3.276875 8.000361\nendloop\nendfacet\nfacet normal -0.045408 0.998965 -0.002823\nouter loop\nvertex 22.772949 3.352315 8.002979\nvertex 22.854446 3.356021 8.003421\nvertex 21.356569 3.284150 6.661976\nendloop\nendfacet\nfacet normal -0.045409 0.998967 -0.001621\nouter loop\nvertex 19.461210 3.199903 6.848686\nvertex 21.113426 3.276875 8.000361\nvertex 22.772949 3.352315 8.002979\nendloop\nendfacet\nfacet normal -0.044751 0.998992 -0.003514\nouter loop\nvertex 22.772949 3.352315 8.002979\nvertex 21.356569 3.284150 6.661976\nvertex 19.461210 3.199903 6.848686\nendloop\nendfacet\nfacet normal -0.012835 -0.007060 -0.999893\nouter loop\nvertex 17.121878 -3.795351 8.020833\nvertex 17.098297 -3.016442 8.015636\nvertex 18.147570 -3.141765 8.003051\nendloop\nendfacet\nfacet normal -0.016735 -0.000960 -0.999860\nouter loop\nvertex 18.147570 -3.141765 8.003051\nvertex 18.206795 -3.144454 8.002062\nvertex 18.211685 -3.794066 8.002604\nendloop\nendfacet\nfacet normal -0.016724 -0.000958 -0.999860\nouter loop\nvertex 18.147570 -3.141765 8.003051\nvertex 18.211685 -3.794066 8.002604\nvertex 17.121878 -3.795351 8.020833\nendloop\nendfacet\nfacet normal 0.264648 -0.001304 0.964344\nouter loop\nvertex 26.150230 -3.802635 8.262934\nvertex 26.155199 -2.887410 8.262807\nvertex 25.946306 -2.553310 8.320586\nendloop\nendfacet\nfacet normal 0.264650 0.000001 0.964345\nouter loop\nvertex 25.946306 -2.553310 8.320586\nvertex 25.414009 -2.554101 8.466667\nvertex 25.414011 -3.803846 8.466667\nendloop\nendfacet\nfacet normal 0.266708 -0.000942 0.963777\nouter loop\nvertex 25.946306 -2.553310 8.320586\nvertex 25.414011 -3.803846 8.466667\nvertex 26.150230 -3.802635 8.262934\nendloop\nendfacet\nfacet normal -0.044557 -0.999000 -0.003685\nouter loop\nvertex 23.701311 -3.388976 6.689353\nvertex 23.345116 -3.377946 8.006075\nvertex 22.772945 -3.352415 8.002979\nendloop\nendfacet\nfacet normal -0.045407 -0.998965 -0.002538\nouter loop\nvertex 21.113426 -3.276976 8.000362\nvertex 20.747240 -3.260331 8.000258\nvertex 21.544149 -3.293628 6.848240\nendloop\nendfacet\nfacet normal -0.045404 -0.998960 -0.004285\nouter loop\nvertex 23.701311 -3.388976 6.689353\nvertex 22.772945 -3.352415 8.002979\nvertex 21.113426 -3.276976 8.000362\nendloop\nendfacet\nfacet normal -0.044314 -0.999015 -0.002128\nouter loop\nvertex 21.113426 -3.276976 8.000362\nvertex 21.544149 -3.293628 6.848240\nvertex 23.701311 -3.388976 6.689353\nendloop\nendfacet\nfacet normal 0.262625 0.000457 0.964898\nouter loop\nvertex 25.815907 0.737309 8.357668\nvertex 25.814472 1.560014 8.357668\nvertex 25.414009 1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.261761 0.000002 0.965133\nouter loop\nvertex 25.815907 0.737309 8.357668\nvertex 25.414009 1.560457 8.466666\nvertex 25.414009 0.737545 8.466667\nendloop\nendfacet\nfacet normal -0.045748 -0.998949 -0.002773\nouter loop\nvertex 21.544149 -3.293628 6.848240\nvertex 20.747240 -3.260331 8.000258\nvertex 19.549599 -3.205483 8.000000\nendloop\nendfacet\nfacet normal -0.045409 -0.998962 -0.003690\nouter loop\nvertex 18.206795 -3.144454 8.002062\nvertex 18.147570 -3.141765 8.003051\nvertex 19.651859 -3.205200 6.661274\nendloop\nendfacet\nfacet normal -0.045406 -0.998966 -0.002179\nouter loop\nvertex 21.544149 -3.293628 6.848240\nvertex 19.549599 -3.205483 8.000000\nvertex 18.206795 -3.144454 8.002062\nendloop\nendfacet\nfacet normal -0.046229 -0.998920 -0.004567\nouter loop\nvertex 18.206795 -3.144454 8.002062\nvertex 19.651859 -3.205200 6.661274\nvertex 21.544149 -3.293628 6.848240\nendloop\nendfacet\nfacet normal 0.095073 0.059732 -0.993677\nouter loop\nvertex 26.344246 3.115694 8.063178\nvertex 25.864864 3.190336 8.021798\nvertex 25.563290 3.798691 8.029513\nendloop\nendfacet\nfacet normal 0.054163 0.012717 -0.998451\nouter loop\nvertex 26.344246 3.115694 8.063178\nvertex 25.563290 3.798691 8.029513\nvertex 26.235046 3.800150 8.065972\nendloop\nendfacet\nfacet normal 0.054085 0.992060 -0.113543\nouter loop\nvertex 21.356569 3.284150 6.661976\nvertex 22.854446 3.356021 8.003421\nvertex 24.394966 3.272750 8.009665\nendloop\nendfacet\nfacet normal 0.081522 0.996369 -0.024541\nouter loop\nvertex 24.394966 3.272750 8.009665\nvertex 25.143169 3.211766 8.019117\nvertex 22.875492 3.349853 6.092598\nendloop\nendfacet\nfacet normal -0.021684 0.998120 0.057330\nouter loop\nvertex 24.394966 3.272750 8.009665\nvertex 22.875492 3.349853 6.092598\nvertex 21.356569 3.284150 6.661976\nendloop\nendfacet\nfacet normal 0.000009 0.000000 1.000000\nouter loop\nvertex 25.813204 -1.764621 8.357668\nvertex 25.811184 -2.342206 8.357668\nvertex 26.000004 -1.750000 8.357668\nendloop\nendfacet\nfacet normal -0.646731 0.003771 0.762709\nouter loop\nvertex 15.679340 0.737497 8.592188\nvertex 15.402760 0.736852 8.357668\nvertex 15.399197 0.125639 8.357668\nendloop\nendfacet\nfacet normal -0.642932 0.004442 0.765911\nouter loop\nvertex 15.399197 0.125639 8.357668\nvertex 15.398325 0.000000 8.357668\nvertex 15.677083 0.000000 8.591667\nendloop\nendfacet\nfacet normal -0.643740 0.001431 0.765243\nouter loop\nvertex 15.399197 0.125639 8.357668\nvertex 15.677083 0.000000 8.591667\nvertex 15.679340 0.737497 8.592188\nendloop\nendfacet\nfacet normal 0.261757 -0.000068 0.965134\nouter loop\nvertex 25.414009 -0.737545 8.466667\nvertex 25.815907 -0.737309 8.357668\nvertex 25.816088 -0.050794 8.357668\nendloop\nendfacet\nfacet normal 0.261630 -0.000135 0.965168\nouter loop\nvertex 25.816088 -0.050794 8.357668\nvertex 25.816114 0.000000 8.357668\nvertex 25.414011 0.000000 8.466667\nendloop\nendfacet\nfacet normal 0.261647 -0.000002 0.965164\nouter loop\nvertex 25.816088 -0.050794 8.357668\nvertex 25.414011 0.000000 8.466667\nvertex 25.414009 -0.737545 8.466667\nendloop\nendfacet\nfacet normal -0.037314 -0.007796 -0.999273\nouter loop\nvertex 16.194366 -2.877492 8.048306\nvertex 17.098297 -3.016442 8.015636\nvertex 17.121878 -3.795351 8.020833\nendloop\nendfacet\nfacet normal -0.060056 -0.030823 -0.997719\nouter loop\nvertex 16.194366 -2.877492 8.048306\nvertex 17.121878 -3.795351 8.020833\nvertex 16.292145 -3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.013682 0.996071 0.087501\nouter loop\nvertex 22.875492 3.349853 6.092598\nvertex 25.143169 3.211766 8.019117\nvertex 25.666662 3.218757 8.021394\nendloop\nendfacet\nfacet normal -0.041527 0.996154 0.077157\nouter loop\nvertex 25.666662 3.218757 8.021394\nvertex 26.406237 3.403702 6.031664\nvertex 23.709536 3.370836 5.004611\nendloop\nendfacet\nfacet normal 0.021972 0.999106 0.036112\nouter loop\nvertex 25.666662 3.218757 8.021394\nvertex 23.709536 3.370836 5.004611\nvertex 22.875492 3.349853 6.092598\nendloop\nendfacet\nfacet normal 0.374263 0.015226 0.927198\nouter loop\nvertex 26.157015 2.552997 8.262760\nvertex 26.450327 2.551991 8.144380\nvertex 26.471371 2.578741 8.135446\nendloop\nendfacet\nfacet normal 0.425797 0.017492 0.904649\nouter loop\nvertex 26.471371 2.578741 8.135446\nvertex 26.418255 3.801430 8.136806\nvertex 26.150230 3.802635 8.262934\nendloop\nendfacet\nfacet normal 0.375244 0.001908 0.926924\nouter loop\nvertex 26.471371 2.578741 8.135446\nvertex 26.150230 3.802635 8.262934\nvertex 26.157015 2.552997 8.262760\nendloop\nendfacet\nfacet normal 0.261756 0.000075 0.965134\nouter loop\nvertex 25.816114 0.000000 8.357668\nvertex 25.815907 0.737309 8.357668\nvertex 25.414009 0.737545 8.466667\nendloop\nendfacet\nfacet normal 0.261631 0.000000 0.965168\nouter loop\nvertex 25.816114 0.000000 8.357668\nvertex 25.414009 0.737545 8.466667\nvertex 25.414011 0.000000 8.466667\nendloop\nendfacet\nfacet normal 0.262627 0.001635 0.964896\nouter loop\nvertex 25.414009 1.560457 8.466666\nvertex 25.814472 1.560014 8.357668\nvertex 25.813848 1.660502 8.357668\nendloop\nendfacet\nfacet normal 0.263724 0.001634 0.964597\nouter loop\nvertex 25.811188 2.342197 8.357667\nvertex 26.159176 2.236687 8.262705\nvertex 26.157015 2.552997 8.262760\nendloop\nendfacet\nfacet normal 0.262766 0.001027 0.964859\nouter loop\nvertex 25.414009 1.560457 8.466666\nvertex 25.813848 1.660502 8.357668\nvertex 25.811188 2.342197 8.357667\nendloop\nendfacet\nfacet normal 0.264650 0.000006 0.964344\nouter loop\nvertex 25.811188 2.342197 8.357667\nvertex 26.157015 2.552997 8.262760\nvertex 25.414009 2.554101 8.466667\nendloop\nendfacet\nfacet normal 0.264654 -0.000002 0.964343\nouter loop\nvertex 25.811188 2.342197 8.357667\nvertex 25.414009 2.554101 8.466667\nvertex 25.414009 1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.179891 -0.057355 0.982013\nouter loop\nvertex 26.000004 -1.750000 8.357668\nvertex 25.811184 -2.342206 8.357668\nvertex 25.946306 -2.553310 8.320586\nendloop\nendfacet\nfacet normal 0.171538 -0.039531 0.984384\nouter loop\nvertex 26.155199 -2.887410 8.262807\nvertex 26.175591 -3.047504 8.252825\nvertex 32.798649 -1.584844 7.157436\nendloop\nendfacet\nfacet normal 0.179874 -0.057356 0.982016\nouter loop\nvertex 26.000004 -1.750000 8.357668\nvertex 25.946306 -2.553310 8.320586\nvertex 26.155199 -2.887410 8.262807\nendloop\nendfacet\nfacet normal 0.174462 -0.029048 0.984235\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 31.040508 -0.715920 7.494724\nvertex 26.000004 -1.750000 8.357668\nendloop\nendfacet\nfacet normal 0.174927 -0.058104 0.982866\nouter loop\nvertex 26.155199 -2.887410 8.262807\nvertex 32.798649 -1.584844 7.157436\nvertex 26.000004 -1.750000 8.357668\nendloop\nendfacet\nfacet normal -0.046076 0.998934 -0.002765\nouter loop\nvertex 17.307825 3.099989 6.690114\nvertex 17.658047 3.119799 8.010885\nvertex 18.206800 3.145085 8.002063\nendloop\nendfacet\nfacet normal -0.045408 0.998967 -0.001906\nouter loop\nvertex 19.549603 3.206118 8.000000\nvertex 20.253862 3.238130 8.000117\nvertex 19.461210 3.199903 6.848686\nendloop\nendfacet\nfacet normal -0.045409 0.998963 -0.003222\nouter loop\nvertex 17.307825 3.099989 6.690114\nvertex 18.206800 3.145085 8.002063\nvertex 19.549603 3.206118 8.000000\nendloop\nendfacet\nfacet normal -0.046213 0.998930 -0.001845\nouter loop\nvertex 19.549603 3.206118 8.000000\nvertex 19.461210 3.199903 6.848686\nvertex 17.307825 3.099989 6.690114\nendloop\nendfacet\nfacet normal 0.534949 -0.088776 -0.840207\nouter loop\nvertex 26.235046 -3.800150 8.065972\nvertex 26.337137 -3.160255 8.063360\nvertex 26.443146 -3.132867 8.127961\nendloop\nendfacet\nfacet normal 0.889279 -0.039139 -0.455688\nouter loop\nvertex 26.443146 -3.132867 8.127961\nvertex 26.448036 -3.115854 8.136044\nvertex 26.418255 -3.801430 8.136806\nendloop\nendfacet\nfacet normal 0.360335 -0.025751 -0.932467\nouter loop\nvertex 26.443146 -3.132867 8.127961\nvertex 26.418255 -3.801430 8.136806\nvertex 26.235046 -3.800150 8.065972\nendloop\nendfacet\nfacet normal -0.646510 -0.028257 0.762382\nouter loop\nvertex 15.679340 -0.737497 8.592188\nvertex 15.402760 -0.736852 8.357668\nvertex 15.427221 -1.296539 8.357668\nendloop\nendfacet\nfacet normal -0.674858 -0.019374 0.737694\nouter loop\nvertex 15.427221 -1.296539 8.357668\nvertex 15.434759 -1.559115 8.357668\nvertex 15.695139 -1.560369 8.595834\nendloop\nendfacet\nfacet normal -0.669606 -0.009564 0.742655\nouter loop\nvertex 15.427221 -1.296539 8.357668\nvertex 15.695139 -1.560369 8.595834\nvertex 15.679340 -0.737497 8.592188\nendloop\nendfacet\nfacet normal 0.050350 -0.990036 0.131507\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 25.696550 -3.224265 8.021599\nvertex 24.391867 -3.292191 8.009745\nendloop\nendfacet\nfacet normal 0.081508 -0.996209 0.030395\nouter loop\nvertex 24.391867 -3.292191 8.009745\nvertex 23.345116 -3.377946 8.006075\nvertex 23.701311 -3.388976 6.689353\nendloop\nendfacet\nfacet normal 0.001676 -0.997386 0.072232\nouter loop\nvertex 24.391867 -3.292191 8.009745\nvertex 23.701311 -3.388976 6.689353\nvertex 26.488607 -3.412277 6.302927\nendloop\nendfacet\nfacet normal 0.115149 -0.968319 0.221582\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 26.443146 -3.132867 8.127961\nvertex 26.337137 -3.160255 8.063360\nendloop\nendfacet\nfacet normal 0.077055 -0.986654 0.143447\nouter loop\nvertex 25.854183 -3.211885 8.022071\nvertex 25.696550 -3.224265 8.021599\nvertex 26.488607 -3.412277 6.302927\nendloop\nendfacet\nfacet normal 0.094369 -0.986971 0.130319\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 26.337137 -3.160255 8.063360\nvertex 25.854183 -3.211885 8.022071\nendloop\nendfacet\nfacet normal 0.092770 -0.960406 0.262706\nouter loop\nvertex 26.488607 -3.412277 6.302927\nvertex 31.104549 -3.148645 5.636679\nvertex 32.833088 -2.745604 6.499722\nendloop\nendfacet\nfacet normal 0.098669 -0.983587 0.151064\nouter loop\nvertex 25.854183 -3.211885 8.022071\nvertex 26.488607 -3.412277 6.302927\nvertex 32.833088 -2.745604 6.499722\nendloop\nendfacet\nfacet normal 0.087076 -0.017958 -0.996040\nouter loop\nvertex 25.854183 -3.211885 8.022071\nvertex 26.337137 -3.160255 8.063360\nvertex 26.235046 -3.800150 8.065972\nendloop\nendfacet\nfacet normal 0.054068 -0.039456 -0.997757\nouter loop\nvertex 25.854183 -3.211885 8.022071\nvertex 26.235046 -3.800150 8.065972\nvertex 25.563290 -3.798691 8.029513\nendloop\nendfacet\nfacet normal -0.646558 0.025163 0.762450\nouter loop\nvertex 15.434760 1.559115 8.357668\nvertex 15.402760 0.736852 8.357668\nvertex 15.679340 0.737497 8.592188\nendloop\nendfacet\nfacet normal -0.674927 0.009687 0.737821\nouter loop\nvertex 15.434760 1.559115 8.357668\nvertex 15.679340 0.737497 8.592188\nvertex 15.695139 1.560369 8.595834\nendloop\nendfacet\nfacet normal 0.287964 0.091813 0.953230\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 26.429348 3.098415 8.098086\nvertex 26.471371 2.578741 8.135446\nendloop\nendfacet\nfacet normal 0.287966 0.091854 0.953225\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 26.471371 2.578741 8.135446\nvertex 26.450327 2.551991 8.144380\nendloop\nendfacet\nfacet normal 0.195991 0.434585 0.879047\nouter loop\nvertex 26.000004 1.750000 8.357668\nvertex 30.465677 1.665626 7.403723\nvertex 30.651365 2.674705 6.863454\nendloop\nendfacet\nfacet normal 0.287964 0.091816 0.953230\nouter loop\nvertex 26.159176 2.236687 8.262705\nvertex 25.811188 2.342197 8.357667\nvertex 26.000004 1.750000 8.357668\nendloop\nendfacet\nfacet normal 0.287964 0.091814 0.953230\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 26.450327 2.551991 8.144380\nvertex 26.159176 2.236687 8.262705\nendloop\nendfacet\nfacet normal 0.287964 0.091817 0.953229\nouter loop\nvertex 26.159176 2.236687 8.262705\nvertex 26.000004 1.750000 8.357668\nvertex 30.651365 2.674705 6.863454\nendloop\nendfacet\nfacet normal -0.016121 0.000954 -0.999870\nouter loop\nvertex 18.211685 3.794066 8.002604\nvertex 18.206800 3.145085 8.002063\nvertex 17.658047 3.119799 8.010885\nendloop\nendfacet\nfacet normal -0.009774 0.006966 -0.999928\nouter loop\nvertex 17.658047 3.119799 8.010885\nvertex 17.098806 3.033245 8.015749\nvertex 17.121878 3.795351 8.020833\nendloop\nendfacet\nfacet normal -0.016724 0.001451 -0.999859\nouter loop\nvertex 17.658047 3.119799 8.010885\nvertex 17.121878 3.795351 8.020833\nvertex 18.211685 3.794066 8.002604\nendloop\nendfacet\nfacet normal 0.261755 -0.000457 0.965134\nouter loop\nvertex 25.814472 -1.560014 8.357668\nvertex 25.815907 -0.737309 8.357668\nvertex 25.414009 -0.737545 8.466667\nendloop\nendfacet\nfacet normal 0.262631 -0.000000 0.964896\nouter loop\nvertex 25.814472 -1.560014 8.357668\nvertex 25.414009 -0.737545 8.466667\nvertex 25.414009 -1.560457 8.466666\nendloop\nendfacet\nfacet normal -0.119174 -0.989068 -0.086848\nouter loop\nvertex 19.651859 -3.205200 6.661274\nvertex 18.147570 -3.141765 8.003051\nvertex 17.098297 -3.016442 8.015636\nendloop\nendfacet\nfacet normal -0.152691 -0.988015 -0.022647\nouter loop\nvertex 16.194366 -2.877492 8.048306\nvertex 15.780942 -2.814433 8.084641\nvertex 18.135849 -3.132686 6.091653\nendloop\nendfacet\nfacet normal -0.155594 -0.975192 -0.157450\nouter loop\nvertex 19.651859 -3.205200 6.661274\nvertex 17.098297 -3.016442 8.015636\nvertex 16.194366 -2.877492 8.048306\nendloop\nendfacet\nfacet normal -0.070236 -0.995714 0.060173\nouter loop\nvertex 16.194366 -2.877492 8.048306\nvertex 18.135849 -3.132686 6.091653\nvertex 19.651859 -3.205200 6.661274\nendloop\nendfacet\nfacet normal 0.264651 -0.000001 0.964344\nouter loop\nvertex 25.414009 -2.554101 8.466667\nvertex 25.946306 -2.553310 8.320586\nvertex 25.811184 -2.342206 8.357668\nendloop\nendfacet\nfacet normal 0.262626 -0.001634 0.964896\nouter loop\nvertex 25.813204 -1.764621 8.357668\nvertex 25.814472 -1.560014 8.357668\nvertex 25.414009 -1.560457 8.466666\nendloop\nendfacet\nfacet normal 0.265109 -0.000928 0.964218\nouter loop\nvertex 25.414009 -2.554101 8.466667\nvertex 25.811184 -2.342206 8.357668\nvertex 25.813204 -1.764621 8.357668\nendloop\nendfacet\nfacet normal 0.263406 0.000002 0.964685\nouter loop\nvertex 25.813204 -1.764621 8.357668\nvertex 25.414009 -1.560457 8.466666\nvertex 25.414009 -2.554101 8.466667\nendloop\nendfacet\nfacet normal -0.040914 0.028815 -0.998747\nouter loop\nvertex 17.098806 3.033245 8.015749\nvertex 16.196001 2.892864 8.048681\nvertex 16.292145 3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.060129 0.008479 -0.998155\nouter loop\nvertex 17.098806 3.033245 8.015749\nvertex 16.292145 3.797194 8.070833\nvertex 17.121878 3.795351 8.020833\nendloop\nendfacet\nfacet normal 0.390536 -0.015941 0.920450\nouter loop\nvertex 26.418255 -3.801430 8.136806\nvertex 26.448036 -3.115854 8.136044\nvertex 26.175591 -3.047504 8.252825\nendloop\nendfacet\nfacet normal 0.425774 -0.002187 0.904827\nouter loop\nvertex 26.175591 -3.047504 8.252825\nvertex 26.155199 -2.887410 8.262807\nvertex 26.150230 -3.802635 8.262934\nendloop\nendfacet\nfacet normal 0.425804 -0.002187 0.904813\nouter loop\nvertex 26.175591 -3.047504 8.252825\nvertex 26.150230 -3.802635 8.262934\nvertex 26.418255 -3.801430 8.136806\nendloop\nendfacet\nfacet normal 0.374271 0.002397 0.927316\nouter loop\nvertex 26.159176 2.236687 8.262705\nvertex 26.450327 2.551991 8.144380\nvertex 26.157015 2.552997 8.262760\nendloop\nendfacet\nfacet normal -0.001574 0.000845 -0.999998\nouter loop\nvertex 19.549603 3.206118 8.000000\nvertex 18.206800 3.145085 8.002063\nvertex 18.211685 3.794066 8.002604\nendloop\nendfacet\nfacet normal -0.001941 0.000011 -0.999998\nouter loop\nvertex 19.549603 3.206118 8.000000\nvertex 18.211685 3.794066 8.002604\nvertex 19.552803 3.793593 8.000000\nendloop\nendfacet\nfacet normal -0.646730 -0.003892 0.762709\nouter loop\nvertex 15.398325 0.000000 8.357668\nvertex 15.402760 -0.736852 8.357668\nvertex 15.679340 -0.737497 8.592188\nendloop\nendfacet\nfacet normal -0.642936 -0.001426 0.765918\nouter loop\nvertex 15.398325 0.000000 8.357668\nvertex 15.679340 -0.737497 8.592188\nvertex 15.677083 0.000000 8.591667\nendloop\nendfacet\nfacet normal 0.000000 0.000001 1.000000\nouter loop\nvertex 25.811188 2.342197 8.357667\nvertex 25.813848 1.660502 8.357668\nvertex 26.000004 1.750000 8.357668\nendloop\nendfacet\nfacet normal 0.889208 0.039135 -0.455825\nouter loop\nvertex 26.418255 3.801430 8.136806\nvertex 26.471371 2.578741 8.135446\nvertex 26.429348 3.098415 8.098086\nendloop\nendfacet\nfacet normal 0.390112 0.065989 -0.918400\nouter loop\nvertex 26.429348 3.098415 8.098086\nvertex 26.344246 3.115694 8.063178\nvertex 26.235046 3.800150 8.065972\nendloop\nendfacet\nfacet normal 0.359681 0.056970 -0.931335\nouter loop\nvertex 26.429348 3.098415 8.098086\nvertex 26.235046 3.800150 8.065972\nvertex 26.418255 3.801430 8.136806\nendloop\nendfacet\nfacet normal -0.051486 -0.092620 -0.994370\nouter loop\nvertex 15.767362 -3.799347 8.177083\nvertex 15.436029 -2.794299 8.100622\nvertex 15.780942 -2.814433 8.084641\nendloop\nendfacet\nfacet normal -0.092678 -0.034228 -0.995108\nouter loop\nvertex 15.780942 -2.814433 8.084641\nvertex 16.194366 -2.877492 8.048306\nvertex 16.292145 -3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.197299 -0.088913 -0.976303\nouter loop\nvertex 15.780942 -2.814433 8.084641\nvertex 16.292145 -3.797194 8.070833\nvertex 15.767362 -3.799347 8.177083\nendloop\nendfacet\nfacet normal -0.081004 0.102134 -0.991467\nouter loop\nvertex 16.196001 2.892864 8.048681\nvertex 15.437763 2.799557 8.101022\nvertex 15.767362 3.799347 8.177083\nendloop\nendfacet\nfacet normal -0.198061 0.045040 -0.979154\nouter loop\nvertex 16.196001 2.892864 8.048681\nvertex 15.767362 3.799347 8.177083\nvertex 16.292145 3.797194 8.070833\nendloop\nendfacet\nfacet normal -0.755974 0.063856 0.651480\nouter loop\nvertex 15.731250 2.553990 8.604167\nvertex 15.518668 2.552154 8.357668\nvertex 15.435318 1.565411 8.357668\nendloop\nendfacet\nfacet normal -0.673871 0.059786 0.736426\nouter loop\nvertex 15.435318 1.565411 8.357668\nvertex 15.434760 1.559115 8.357668\nvertex 15.695139 1.560369 8.595834\nendloop\nendfacet\nfacet normal -0.675412 0.018365 0.737212\nouter loop\nvertex 15.435318 1.565411 8.357668\nvertex 15.695139 1.560369 8.595834\nvertex 15.731250 2.553990 8.604167\nendloop\nendfacet\nfacet normal 0.140188 0.979719 0.143172\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 25.666662 3.218757 8.021394\nvertex 25.864864 3.190336 8.021798\nendloop\nendfacet\nfacet normal 0.140189 0.979720 0.143165\nouter loop\nvertex 26.344246 3.115694 8.063178\nvertex 26.429348 3.098415 8.098086\nvertex 30.651365 2.674705 6.863454\nendloop\nendfacet\nfacet normal 0.140192 0.979718 0.143174\nouter loop\nvertex 26.406237 3.403702 6.031664\nvertex 25.864864 3.190336 8.021798\nvertex 26.344246 3.115694 8.063178\nendloop\nendfacet\nfacet normal 0.089702 0.929763 0.357062\nouter loop\nvertex 30.651365 2.674705 6.863454\nvertex 30.497274 3.120947 5.740185\nvertex 26.406237 3.403702 6.031664\nendloop\nendfacet\nfacet normal 0.140190 0.979719 0.143173\nouter loop\nvertex 26.344246 3.115694 8.063178\nvertex 30.651365 2.674705 6.863454\nvertex 26.406237 3.403702 6.031664\nendloop\nendfacet\nfacet normal -0.755974 -0.063878 0.651478\nouter loop\nvertex 15.434759 -1.559115 8.357668\nvertex 15.518668 -2.552154 8.357668\nvertex 15.731250 -2.553990 8.604167\nendloop\nendfacet\nfacet normal -0.674866 -0.018339 0.737712\nouter loop\nvertex 15.434759 -1.559115 8.357668\nvertex 15.731250 -2.553990 8.604167\nvertex 15.695139 -1.560369 8.595834\nendloop\nendfacet\nfacet normal 0.244400 -0.472541 0.846743\nouter loop\nvertex 32.798649 -1.584844 7.157436\nvertex 26.175591 -3.047504 8.252825\nvertex 26.448036 -3.115854 8.136044\nendloop\nendfacet\nfacet normal 0.244393 -0.472518 0.846758\nouter loop\nvertex 26.448036 -3.115854 8.136044\nvertex 26.443146 -3.132867 8.127961\nvertex 32.833088 -2.745604 6.499722\nendloop\nendfacet\nfacet normal 0.147050 -0.484320 0.862445\nouter loop\nvertex 32.833088 -2.745604 6.499722\nvertex 36.147072 -1.831106 6.448225\nvertex 32.798649 -1.584844 7.157436\nendloop\nendfacet\nfacet normal 0.244400 -0.472535 0.846746\nouter loop\nvertex 26.448036 -3.115854 8.136044\nvertex 32.833088 -2.745604 6.499722\nvertex 32.798649 -1.584844 7.157436\nendloop\nendfacet\nfacet normal -0.001535 -0.000008 -0.999999\nouter loop\nvertex 18.206795 -3.144454 8.002062\nvertex 19.549599 -3.205483 8.000000\nvertex 19.552803 -3.793593 8.000000\nendloop\nendfacet\nfacet normal -0.001942 -0.000848 -0.999998\nouter loop\nvertex 18.206795 -3.144454 8.002062\nvertex 19.552803 -3.793593 8.000000\nvertex 18.211685 -3.794066 8.002604\nendloop\nendfacet\nendsolid Exported from Blender-2.80 (sub 74)\n"
  },
  {
    "path": "tests/pytest/meshes.py",
    "content": "import pytest\n\n@pytest.fixture\ndef unit_mesh_2d():\n    import netgen.geom2d as g2d\n    return g2d.unit_square.GenerateMesh(maxh=0.2)\n\n@pytest.fixture\ndef unit_mesh_3d():\n    import netgen.csg as csg\n    return csg.unit_cube.GenerateMesh(maxh=0.2)\n"
  },
  {
    "path": "tests/pytest/test_array.py",
    "content": "import netgen\nfrom pyngcore import *\nfrom numpy import sort, array\n\ndef test_array_numpy():\n    a = Array_I_S(5)\n    a[:] = 0\n    a[3:] = 2\n    assert(sum(a) == 4)\n    a[1] = 5\n    b = sort(a)\n    assert(all(b == array([0,0,2,2,5])))\n    assert(all(a == array([0,5,0,2,2])))\n    a.NumPy().sort()\n    assert(all(a == array([0,0,2,2,5])))\n\ndef test_mesh_elements_numpy_array_access():\n    from netgen.csg import unit_cube\n    mesh = unit_cube.GenerateMesh()\n    np_els = mesh.Elements3D().NumPy()\n    vol_nodes = np_els[\"nodes\"]\n    indices = np_els[\"index\"]\n    nps = np_els[\"np\"]\n    for nodes, el, index, np in zip(vol_nodes, mesh.Elements3D(), indices, nps):\n        for n1, n2 in zip(nodes, el.vertices):\n            assert n1 == n2\n        for n in nodes[len(el.vertices):]:\n            assert n == 0\n        assert el.index == index\n        assert len(el.vertices) == np\n\nif __name__ == \"__main__\":\n    test_array_numpy()\n    test_mesh_elements_numpy_array_access()\n"
  },
  {
    "path": "tests/pytest/test_bitarray.py",
    "content": "import netgen\nfrom pyngcore import BitArray\n\ndef test_bitarray():\n    a = BitArray(498)\n    assert len(a) == 498\n\n    a.Set()\n    for b in a:\n        assert b == True\n\n    a.Clear(23)\n    assert a[22] == True\n    assert a[23] == False\n    assert a[24] == True\n\n    a.Clear()\n    for b in a:\n        assert b == False\n\n    a.Set(23)\n    assert a[22] == False\n    assert a[23] == True\n    assert a[24] == False\n\n    a.Clear()\n    a[100:200:9] = True\n    for i in range(len(a)):\n        assert a[i] == bool(100<=i and i<200 and i%9==100%9)\n\n    ac = ~a\n\n    for b,bc in zip(a,ac):\n        assert b == (not bc)\n\n\n"
  },
  {
    "path": "tests/pytest/test_boundarylayer.py",
    "content": "\nimport pytest\nfrom netgen.csg import *\nfrom netgen.meshing import BoundaryLayerParameters\n\ngeometries=[unit_cube]\n\ntry:\n    import netgen.occ as occ\n    box = occ.Box( (0,0,0), (1,1,1) )\n    box.faces.Min(occ.Y).name = \"back\"\n    box.faces.Max(occ.Y).name = \"front\"\n    box.faces.Min(occ.X).name = \"left\"\n    box.faces.Max(occ.X).name = \"right\"\n    box.faces.Min(occ.Z).name = \"bottom\"\n    box.faces.Max(occ.Z).name = \"top\"\n    geometries.append(occ.OCCGeometry(box))\nexcept ImportError:\n    pass\n\ndef GetNSurfaceElements(mesh, boundaries, adjacent_domain=None):\n    nse_in_layer = 0\n    for el in mesh.Elements2D():\n        if len(el.vertices)==3 and mesh.GetBCName(el.index-1) in boundaries:\n            if adjacent_domain is None:\n                print(\"add el\", el.vertices)\n                nse_in_layer += 1\n            else:\n                if (mesh.FaceDescriptor(el.index).domin > 0 and mesh.GetMaterial(mesh.FaceDescriptor(el.index).domin) == adjacent_domain) or (mesh.FaceDescriptor(el.index).domout > 0 and mesh.GetMaterial(mesh.FaceDescriptor(el.index).domout) == adjacent_domain):\n                    nse_in_layer += 1\n    return nse_in_layer\n\ndef GetNPrisms(mesh):\n    nprisms = 0\n    for el in mesh.Elements3D():\n        if len(el.vertices) == 6:\n            nprisms += 1\n    return nprisms\n\n@pytest.mark.parametrize(\"outside\", [True, False])\n@pytest.mark.parametrize(\"geo\", geometries)\ndef test_boundarylayer(outside, geo, capfd):\n    layer_surfacenames = [\"right\", \"top\", \"left\", \"back\", \"bottom\"]\n    blayer_params = [BoundaryLayerParameters('|'.join(layer_surfacenames), [0.01, 0.01], \"layer\", outside=outside)]\n    mesh = geo.GenerateMesh(maxh=0.3, boundary_layers=blayer_params)\n    should_n_prisms = 2 * GetNSurfaceElements(mesh, layer_surfacenames)\n    assert GetNPrisms(mesh) == should_n_prisms\n    capture = capfd.readouterr()\n    assert not \"elements are not matching\" in capture.out\n\n    blayer_params.append(BoundaryLayerParameters(\"front\", [0.01, 0.01], \"layer\", outside=True)) # outside=outside not working...\n    mesh = geo.GenerateMesh(maxh=0.3, boundary_layers=blayer_params)\n    should_n_prisms += 2 * GetNSurfaceElements(mesh, [\"front\"])\n    assert GetNPrisms(mesh) == should_n_prisms\n    capture = capfd.readouterr()\n    assert not \"elements are not matching\" in capture.out\n\n@pytest.mark.parametrize(\"outside\", [True, False])\n@pytest.mark.parametrize(\"version\", [1, 2]) # version 2 not working yet\ndef test_boundarylayer2(outside, version, capfd):\n    geo = CSGeometry()\n    top = Plane(Pnt(0,0,0.5), Vec(0,0,1))\n    bot = Plane(Pnt(0,0,0.1), Vec(0,0,-1))\n    bigpart = OrthoBrick(Pnt(-5,-5,0), Pnt(1,1,1))\n    part = bigpart* top * bot\n    outer = ((OrthoBrick(Pnt(-1,-1,-1), Pnt(2,2,3)).bc(\"outer\") * Plane(Pnt(2,2,2), Vec(0,0,1)).bc(\"outertop\")))\n\n    geo.Add((part * outer).mat(\"part\"))\n    if version == 1:\n        geo.Add((outer-part).mat(\"rest\"))\n    else:\n        geo.Add((outer-top).mat(\"rest\"))\n        geo.Add((outer-bot).mat(\"rest\"))\n        geo.Add((outer*top*bot-bigpart).mat(\"rest\"))\n\n    geo.CloseSurfaces(top, bot, [])\n    layersize = 0.025\n    mesh = geo.GenerateMesh(boundary_layers=[BoundaryLayerParameters(\"default\", [layersize, layersize], \"part\", domain=\"part\", outside=outside)])\n\n    should_n_prisms = 2 * GetNSurfaceElements(mesh, [\"default\"], \"part\")\n    # assert GetNPrisms(mesh) == should_n_prisms\n    assert not \"elements are not matching\" in capfd.readouterr().out\n    # import netgen.gui\n    ngs = pytest.importorskip(\"ngsolve\")\n    ngs.Draw(ngs.Mesh(mesh))\n    mesh = ngs.Mesh(mesh)\n    assert ngs.Integrate(1, mesh.Materials(\"part\")) == pytest.approx(0.5*2.05*2.05 if outside else 0.4*2*2)\n    assert ngs.Integrate(1, mesh) == pytest.approx(3**3)\n\n\n@pytest.mark.parametrize(\"outside\", [True, False])\ndef test_wrong_orientation(outside, capfd):\n    geo = CSGeometry()\n    brick = OrthoBrick((-1,0,0),(1,1,1)) - Plane((0,0,0), (1,0,0))\n    geo.Add(brick.mat(\"air\"))\n\n    mesh = geo.GenerateMesh(boundary_layers=[BoundaryLayerParameters(\".*\", [0.1], \"air\", domain=\"air\", outside=outside)])\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(mesh)\n    assert ngs.Integrate(1, mesh) == pytest.approx(1.2**3 if outside else 1)\n\ndef test_splitted_surface():\n    geo = CSGeometry()\n\n    brick = OrthoBrick((0,0,0), (1,1,1))\n    slots = OrthoBrick((0.2,0,-1), (0.4, 1, 2)) + OrthoBrick((0.6, 0,-1), (0.8, 1,2))\n    geo.Add((brick-slots).mat(\"block\"))\n    geo.Add((brick*slots).mat(\"slot\"))\n\n    mesh = geo.GenerateMesh(boundary_layers=[BoundaryLayerParameters(\".*\", [0.001, 0.001], \"block\", domain=\"block\", outside=False)])\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(mesh)\n    assert ngs.Integrate(1, mesh) == pytest.approx(1)\n    assert ngs.Integrate(1, mesh.Materials(\"slot\")) == pytest.approx(0.4)\n\n@pytest.mark.parametrize(\"outside\", [True, False])\ndef test_pyramids(outside):\n    geo = CSGeometry()\n    box = OrthoBrick((0,0,0), (1,1,1))\n    dist = 0.3\n    plate = OrthoBrick((dist,dist,0.4),(1-dist,1-dist,1)) * Plane((0,0,0.6), (0,0,1)).bc(\"top\")\n    geo.Add((box-plate).mat(\"air\"))\n    geo.Add(plate.mat(\"plate\"))\n    blayers = [BoundaryLayerParameters(\"top\", [0.01], \"layer\", domain=\"plate\", outside=outside)]\n    mesh = geo.GenerateMesh(boundary_layers=blayers)\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(mesh)\n\n    assert ngs.Integrate(1, mesh.Materials(\"plate\")) == pytest.approx(0.032 if outside else 0.0304)\n    assert ngs.Integrate(1, mesh.Materials(\"layer\")) == pytest.approx(0.0016)\n    assert ngs.Integrate(1, mesh.Materials(\"air\")) == pytest.approx(0.9664 if outside else 0.968)\n\n# not working yet\n@pytest.mark.parametrize(\"outside\", [True, False])\ndef _test_with_inner_corner(outside, capfd):\n    geo = CSGeometry()\n\n    core_thickness = 0.1\n    limb_distance = 0.5\n    core_height = 0.5\n    coil_r1 = 0.08\n    coil_r2 = 0.16\n    coil_h = 0.2\n    domain_size = 1.2\n    domain_size_y = 0.7\n\n    def CreateCoil(x):\n        outer = Cylinder((x, 0, -1), (x, 0, 1), coil_r2)\n        inner = Cylinder((x, 0, -1), (x, 0, 1), coil_r1)\n        top = Plane((0,0,coil_h/2), (0,0,1))\n        bot = Plane((0,0,-coil_h/2), (0,0,-1))\n        return ((outer - inner) * top * bot, (outer, inner, top, bot))\n\n    core_front = Plane((0,-core_thickness/2, 0), (0,-1,0)).bc(\"core_front\")\n    core_back = Plane((0,core_thickness/2, 0), (0,1,0)).bc(\"core_front\")\n    core_limb1 = OrthoBrick((-limb_distance/2-core_thickness/2, -core_thickness, -core_height/2),(-limb_distance/2+core_thickness/2, core_thickness, core_height/2))\n    core_limb2 = OrthoBrick((limb_distance/2-core_thickness/2, -core_thickness, -core_height/2),(limb_distance/2+core_thickness/2, core_thickness, core_height/2))\n    core_top = OrthoBrick((-limb_distance/2-core_thickness/2, -core_thickness, core_height/2-core_thickness/2),(limb_distance/2+core_thickness/2, core_thickness, core_height/2+core_thickness/2))\n    core_bot = OrthoBrick((-limb_distance/2-core_thickness/2, -core_thickness, -core_height/2-core_thickness/2),(limb_distance/2+core_thickness/2, core_thickness, -core_height/2+core_thickness/2))\n\n    core = (core_limb1 + core_limb2 + core_top + core_bot).bc(\"core_rest\")\n    core = core * core_front * core_back\n    core.maxh(core_thickness * 0.4)\n\n    coil1, (outer1, inner1, top1, bot1) = CreateCoil(-limb_distance/2)\n    coil1.mat(\"coil_1\")\n    coil2, (outer2, inner2, top2, bot2) = CreateCoil(limb_distance/2)\n    coil2.mat(\"coil_2\")\n\n    oil = OrthoBrick((-domain_size/2, -domain_size_y/2, -domain_size/2), (domain_size/2, domain_size_y/2, domain_size/2)).bc(\"tank\") - core # - coil1 - coil2\n\n    geo.Add(core.mat(\"core\"), col=(0.4,0.4,0.4))\n    geo.Add(coil1, col=(0.72, 0.45, 0.2))\n    geo.Add(coil2, col=(0.72, 0.45, 0.2))\n    geo.Add(oil.mat(\"oil\"), transparent=True)\n    blayers = [BoundaryLayerParameters(\"core_front\", [0.001, 0.002], \"core\", domain=\"core\", outside=outside)]\n    mesh = geo.GenerateMesh(boundary_layers = blayers)\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(mesh)\n    capture = capfd.readouterr()\n    assert not \"elements are not matching\" in capture.out\n    assert ngs.Integrate(1, mesh.Materials(\"core\")) == pytest.approx(0.0212 if outside else 0.02)\n    assert ngs.Integrate(1, mesh.Materials(\"oil\")) == pytest.approx(0.9868 if outside else 0.988)\n"
  },
  {
    "path": "tests/pytest/test_csg.py",
    "content": "from netgen.csg import *\n\ndef create_2_polyhedra():\n    geo = CSGeometry()\n    first = Polyhedron([(0,0,0), (0,1,0), (3,1,0), (3,0,0),\n                        (0,1,1), (3,1,1), (3,0,1), (0,0,1)],\n                        [(0,1,2,3), (1,4,5,2), (2,5,6,3), (3,6,7,0),\n                         (0,7,4,1), (7,6,5,4)])\n    # TODO: height = 0.1 not working!\n    height = 0.3\n    second = Polyhedron([(0,0,1), (0,1,1), (3,1,1), (3,0,1),\n                         (0,1,1+height), (3,1,1+height),\n                         (3,0,1+height), (0,0,1+height)],\n                        [(0,1,2,3), (1,4,5,2), (2,5,6,3), (3,6,7,0),\n                         (0,7,4,1), (7,6,5,4)])\n\n    geo.Add(first)\n    geo.Add(second)\n    mesh = geo.GenerateMesh()\n    return mesh\n\ndef test_2_polyhedra():\n    create_2_polyhedra()\n\n\nif __name__ == \"__main__\":\n    from ngsolve import Mesh, Draw\n    mesh = Mesh(create_2_polyhedra())\n    Draw(mesh)\n"
  },
  {
    "path": "tests/pytest/test_csg2d.py",
    "content": "from netgen.geom2d import *\nimport pytest\nimport math\nfrom pytest import approx\nfrom pytest_check import check\n\n\ndef check_area(geo, area):\n    if isinstance(geo, Solid2d):\n        g = CSG2d()\n        g.Add(geo)\n        geo = g\n\n    m = geo.GenerateMesh(maxh=0.2)\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    with check: assert ngs.Integrate(1.0, mesh) == approx(area)\n\ndef test_two_circles():\n    c1 = Circle(center=(0,0), radius=1)\n    c2 = c1.Rotate(45)\n    s = c1*c2\n    geo = CSG2d()\n    geo.Add(s)\n    m = geo.GenerateMesh()\n    assert len(m.Elements2D()) > 0\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    assert ngs.Integrate(1.0, mesh) == approx(math.pi)\n    ngs.Draw(mesh)\n\ndef test_two_edge():\n    s = Solid2d( [(-1,0), cp(0,1), (1,0), cp(0,2)] )\n    geo = CSG2d()\n    geo.Add(s)\n    m = geo.GenerateMesh()\n    assert len(m.Elements2D()) > 0\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    g = geo.GenerateSplineGeometry()\n    ngs.Draw(g)\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    ngs.Draw(mesh)\n\ndef test_trig_and_circle():\n    g = CSG2d()\n\n    trig = Solid2d( [(0,0), (1,1), (-1,1) ] ).BC(\"diamond\")\n    circle = Circle( center=(0,0.101), radius=0.1).BC(\"circle\") # TODO: Failing with center=(0,0.1)\n\n    d = trig-circle\n    g.Add(d)\n    g.Add(circle)\n\n    m = g.GenerateMesh(maxh=0.1)\n    assert len(m.Elements2D()) > 0\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    geo = g.GenerateSplineGeometry()\n    ngs.Draw(geo)\n\n    mesh = ngs.Mesh(m)\n    mesh.Curve(3)\n    ngs.Draw(mesh)\n\n\ndef test_circle_plus_rect():\n    circle = Circle( center=(0,0), radius=1 )\n    rect = Rectangle( pmin=(-0.5,0.0), pmax=(0.5,0.5) )\n\n    geo = CSG2d()\n    geo.Add(circle+rect)\n    m = geo.GenerateMesh(maxh=0.2)\n\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    assert ngs.Integrate(1.0, mesh) == approx(math.pi)\n\ndef test_circle_plus_rect1():\n    circle = Circle( center=(0,0), radius=1 )\n    rect = Rectangle( pmin=(-0.5,-0.5), pmax=(0.5,0.5) )\n\n    geo = CSG2d()\n    geo.Add(circle+rect)\n    m = geo.GenerateMesh(maxh=0.2)\n\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    assert ngs.Integrate(1.0, mesh) == approx(math.pi)\n\ndef test_circle_and_rect():\n    c = Circle(center=(0,0),radius=1)\n    r = Rectangle((0,0),(1,1))\n\n    pi = math.pi\n    check_area(c-r, 3/4*pi)\n    check_area(c*r, 1/4*pi)\n    check_area(c+r, 3/4*pi+1)\n    check_area(r*c, 1/4*pi)\n    check_area(r+c, 3/4*pi+1)\n    check_area(r-c, 1-1/4*pi)\n\n\nif __name__ == \"__main__\":\n    test_two_circles()\n    test_two_edge()\n    test_trig_and_circle()\n"
  },
  {
    "path": "tests/pytest/test_geom2d.py",
    "content": "from netgen.geom2d import SplineGeometry\n\n\ndef test_leftdom_equals_rightdom():\n    geo = SplineGeometry()\n    pnts = [(0,0), (1,0), (2,0), (2,1), (1,1), (0,1)]\n    gp = [geo.AppendPoint(*p) for p in pnts]\n    lines = [(0,1,0), (1,2,0), (2,3,0), (3,4,0), (4,5,0), (5,0,0), (1,4,1)]\n    for p1, p2, rd in lines:\n        geo.Append([\"line\", p1, p2], leftdomain=1, rightdomain=rd)\n\n    mesh = geo.GenerateMesh()\n\n"
  },
  {
    "path": "tests/pytest/test_meshclass.py",
    "content": "import pyngcore\nimport netgen\nimport pytest\nimport tempfile\n\nfrom meshes import unit_mesh_3d\n\n\ndef test_element_arrays(unit_mesh_3d):\n    mesh = unit_mesh_3d\n    el1 = mesh.Elements1D()\n    el2 = mesh.Elements2D()\n    el3 = mesh.Elements3D()\n    p = mesh.Points()\n\n    assert len(el1) > 0\n    assert len(el2) > 0\n    assert len(el3) > 0\n    assert len(p) > 0\n\n    for el in el2:\n        assert len(el.vertices) == 3\n\n    for el in el3:\n        assert len(el.vertices) == 4\n\n\ndef test_copy_mesh():\n    pytest.importorskip(\"netgen.occ\")\n    import netgen.occ as occ\n\n    box1 = occ.Box((0, 0, 0), (1, 1, 1))\n    box2 = occ.Box((1, 0, 0), (2, 1, 1))\n    box1.faces.name = \"bnd1\"\n    box1.name = \"mat1\"\n    box2.faces.name = \"bnd2\"\n    box2.name = \"mat1\"\n\n    geo = occ.OCCGeometry(occ.Glue([box1, box2]))\n    m3d = geo.GenerateMesh(maxh=99)\n\n    plane1 = occ.WorkPlane(occ.Axes((0, 0, 0), occ.X, occ.Y)).Rectangle(1, 1).Face()\n    plane1.name = \"mat1\"\n    plane1.edges.name = \"bnd1\"\n\n    plane2 = occ.WorkPlane(occ.Axes((0, 0, 0), occ.X, occ.Y)).Rectangle(2, 2).Face()\n    plane2.name = \"mat2\"\n    plane2.edges.name = \"bnd2\"\n\n    geo2 = occ.OCCGeometry(occ.Glue([plane1, plane2]), dim=2)\n    m2d = geo2.GenerateMesh(maxh=99)\n\n    for mesh in [m2d, m3d]:\n        copy = mesh.Copy()\n\n        assert copy.dim == mesh.dim\n        assert len(copy.Elements0D()) == len(mesh.Elements0D())\n        assert len(copy.Elements1D()) == len(mesh.Elements1D())\n        assert len(copy.Elements2D()) == len(mesh.Elements2D())\n        assert len(copy.Elements3D()) == len(mesh.Elements3D())\n        assert copy.GetNDomains() == mesh.GetNDomains()\n        assert copy.GetNFaceDescriptors() == mesh.GetNFaceDescriptors()\n        for dim in range(1, mesh.dim + 1):\n            assert copy.GetRegionNames(dim) == mesh.GetRegionNames(dim)\n        assert copy.GetIdentifications() == mesh.GetIdentifications()\n"
  },
  {
    "path": "tests/pytest/test_mpi4py.py",
    "content": "import pytest\nimport netgen.meshing\n\nmpi4py = pytest.importorskip(\"mpi4py\")\n_ = pytest.importorskip(\"pytest_mpi\")\n\n@pytest.mark.mpi\ndef test_mpi4py():\n    comm = mpi4py.MPI.COMM_WORLD\n\n    if comm.rank==0:\n        from netgen.csg import unit_cube\n        m = unit_cube.GenerateMesh(maxh=0.1)\n        m.Save(\"mpimesh\")\n\n    comm.Barrier()\n\n    mesh = netgen.meshing.Mesh(3, comm)\n    mesh.Load(\"mpimesh.vol.gz\")\n\n    if comm.rank==0:\n        assert mesh.ne==0\n"
  },
  {
    "path": "tests/pytest/test_nonnative_master",
    "content": "tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)\ntend (must be vertically): (0, -1.82574)\ngenerate boundarycondition.geo\nneeded 0.12342000007629395 seconds\ngenerate boxcyl.geo\nneeded 0.801245927810669 seconds\ngenerate circle_on_cube.geo\nneeded 0.48620080947875977 seconds\ngenerate cone.geo\nneeded 1.186929702758789 seconds\ngenerate cube.geo\nneeded 0.09043073654174805 seconds\ngenerate cubeandring.geo\nneeded 2.1420021057128906 seconds\ngenerate cubeandspheres.geo\nneeded 0.26427721977233887 seconds\ngenerate cubemcyl.geo\nneeded 18.373886108398438 seconds\ngenerate cubemsphere.geo\nneeded 3.6954052448272705 seconds\ngenerate cylinder.geo\nneeded 0.44164204597473145 seconds\ngenerate cylsphere.geo\nneeded 0.8774328231811523 seconds\ngenerate ellipsoid.geo\nneeded 1.4510962963104248 seconds\ngenerate ellipticcone.geo\nneeded 3.0906074047088623 seconds\ngenerate ellipticcyl.geo\nneeded 2.0780415534973145 seconds\ngenerate extrusion.geo\nneeded 0.40680599212646484 seconds\ngenerate fichera.geo\nneeded 0.1265270709991455 seconds\ngenerate hinge.stl\nneeded 5.519087553024292 seconds\ngenerate lense.in2d\nneeded 0.05641365051269531 seconds\ngenerate lshape3d.geo\nneeded 0.09937620162963867 seconds\ngenerate manyholes.geo\nneeded 9.43863034248352 seconds\ngenerate manyholes2.geo\nneeded 7.40019965171814 seconds\ngenerate matrix.geo\nneeded 3.734792709350586 seconds\ngenerate ortho.geo\nneeded 0.09516167640686035 seconds\ngenerate part1.stl\nneeded 2.6940107345581055 seconds\ngenerate period.geo\nneeded 2.709449291229248 seconds\ngenerate revolution.geo\nneeded 7.7064368724823 seconds\ngenerate sculpture.geo\nneeded 0.6283819675445557 seconds\ngenerate shaft.geo\nneeded 2.921243190765381 seconds\ngenerate shell.geo\ngenerate sphere.geo\nneeded 0.18424725532531738 seconds\ngenerate sphereincube.geo\nneeded 0.6060984134674072 seconds\ngenerate square.in2d\nneeded 0.021883487701416016 seconds\ngenerate squarecircle.in2d\nneeded 0.04081606864929199 seconds\ngenerate squarehole.in2d\nneeded 0.03681302070617676 seconds\ngenerate torus.geo\nneeded 6.590093612670898 seconds\ngenerate trafo.geo\nneeded 3.2712368965148926 seconds\ngenerate twobricks.geo\nneeded 0.13849091529846191 seconds\ngenerate twocubes.geo\nneeded 0.13361692428588867 seconds\ngenerate twocyl.geo\nneeded 0.8036918640136719 seconds\ngenerate plane.stl\nneeded 15.712460041046143 seconds\ndone\nsin (must not be 0) = 0.447214sin (must not be 0) = 0.447214"
  },
  {
    "path": "tests/pytest/test_occ.py",
    "content": "import pytest\nimport math\nfrom pytest import approx\nfrom pytest_check import check\n\ndef check_volume(shape, volume, dim=3):\n    from netgen.occ import OCCGeometry\n    geo = OCCGeometry(shape, dim=dim)\n\n    m = geo.GenerateMesh()\n    assert len(m.Elements2D()) > 0\n    assert len(m.Elements1D()) > 0\n    if dim==3:\n        assert len(m.Elements3D()) > 0\n\n    ngs = pytest.importorskip(\"ngsolve\")\n    mesh = ngs.Mesh(m)\n    mesh.Curve(5)\n    with check: assert ngs.Integrate(1.0, mesh) == approx(volume)\n\ndef test_rect_with_two_holes():\n    occ = pytest.importorskip(\"netgen.occ\")\n\n    face = occ.WorkPlane().Rectangle(7,4) \\\n    .Circle(2,2,1).Reverse() \\\n    .Circle(5,2,1).Reverse().Face()\n    check_volume(face, 7*4-2*math.pi, 2)\n\ndef test_unit_square():\n    occ = pytest.importorskip(\"netgen.occ\")\n    check_volume(occ.unit_square.shape, 1, dim=2)\n\ndef test_box_and_cyl():\n    occ = pytest.importorskip(\"netgen.occ\")\n    box = occ.Box(occ.Pnt(0,0,0), occ.Pnt(1,1,1))\n    check_volume(box, 1)\n    r = 0.3\n    h = 0.5\n    vcyl = r*r*math.pi*h\n    cyl = occ.Cylinder(occ.Pnt(1,0.5,0.5), occ.X, r=r, h=h)\n    check_volume(cyl, vcyl)\n    fused = box+cyl\n    check_volume(fused, 1+vcyl)\n\ndef test_internal_face():\n    occ = pytest.importorskip(\"netgen.occ\")\n    box = occ.Box((0,0,0), (3, 1, 10))\n\n    face = occ.WorkPlane(occ.Axes((1.5,0,0), occ.X, occ.Y)).Rectangle(1, 6).Face()\n\n    shape = occ.Glue([box, face])\n    geo = occ.OCCGeometry(shape)\n    mesh = geo.GenerateMesh(maxh=0.5)\n    assert any(mesh.Elements2D().NumPy()['index'] == 8)\n\n"
  },
  {
    "path": "tests/pytest/test_occ_identifications.py",
    "content": "import pytest\n\nfrom netgen.meshing import IdentificationType\nidtype = IdentificationType.CLOSESURFACES\n\ndef test_two_boxes():\n    occ = pytest.importorskip(\"netgen.occ\")\n    inner = occ.Box((0,0,0), (1,1,1))\n    trafo = occ.gp_Trsf().Scale(inner.center, 1.1)\n    outer = trafo(inner)\n\n    inner.Identify(outer, \"\", idtype, trafo)\n    shape = occ.Glue([outer-inner, inner])\n\n    geo = occ.OCCGeometry(shape)\n    mesh = geo.GenerateMesh(maxh=0.3)\n    have_prisms = False\n\n    for el in mesh.Elements3D():\n        if len(el.vertices)==6:\n            have_prisms = True\n            break\n\n    assert have_prisms\n\ndef test_two_circles():\n    occ = pytest.importorskip(\"netgen.occ\")\n    circ1 = occ.WorkPlane().Circle(1).Face()\n    trafo = occ.gp_Trsf().Scale(circ1.center, 1.1)\n\n    circ2 = trafo(circ1)\n    circ1.edges[0].Identify(circ2.edges[0], \"\", idtype, trafo)\n    circ2 -= circ1\n    shape = occ.Glue([circ1, circ2])\n\n    geo = occ.OCCGeometry(shape, 2)\n    mesh = geo.GenerateMesh(maxh=0.2)\n    have_quads = False\n\n    for el in mesh.Elements2D():\n        if len(el.vertices)==4:\n            have_quads = True\n            break\n\n    assert have_quads\n\ndef test_cut_identified_face():\n    occ = pytest.importorskip(\"netgen.occ\")\n    from netgen.occ import Z, Box, Cylinder, Glue, OCCGeometry\n    box = Box((-1,-1,0), (1,1,1))\n    cyl = Cylinder( (0,0,0), Z, 0.5, 1 )\n\n    box.faces.Min(Z).Identify(box.faces.Max(Z), \"\", idtype)\n    shape = Glue([cyl, box])\n    geo = OCCGeometry(shape)\n    mesh = geo.GenerateMesh(maxh=0.5)\n\n    for el in mesh.Elements3D():\n        assert len(el.vertices)==6\n\ndef test_identify_multiple_faces():\n    occ = pytest.importorskip(\"netgen.occ\")\n    from netgen.occ import Z, Box, Cylinder, Glue, OCCGeometry, gp_Trsf\n    box = Box((-1,-1,0), (1,1,1))\n    cyl = Cylinder( (0,0,0), Z, 0.5, 1 )\n\n    shape = Glue([box, cyl])\n    bot_faces = shape.faces[Z < 0.1]\n    top_faces = shape.faces[Z > 0.1]\n    bot_faces.Identify(top_faces, \"\", idtype, gp_Trsf.Translation((0,0,1)))\n\n    geo = OCCGeometry(shape)\n    mesh = geo.GenerateMesh(maxh=0.3)\n\n    for el in mesh.Elements3D():\n        assert len(el.vertices)==6\n"
  },
  {
    "path": "tests/pytest/test_pickling.py",
    "content": "\nimport pickle, numpy\n\ndef test_pickle_csg():\n    import netgen.csg as csg\n    geo = csg.CSGeometry()\n    geo.Add(csg.Sphere(csg.Pnt(0,0,0), 2).bc(\"sphere\"))\n    brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3))\n    geo.Add(csg.Cylinder(csg.Pnt(0,0,0), csg.Pnt(1,0,0), 0.5) * brick)\n    geo.Add(csg.Ellipsoid(csg.Pnt(0,0,0), csg.Vec(1,0,0), csg.Vec(0,1,0), csg.Vec(0,0,0.5)))\n    geo.Add(csg.Cone(csg.Pnt(0,0,0), csg.Pnt(3,0,0), 1, 0.5) * brick)\n    geo.Add(csg.EllipticCone(csg.Pnt(0,0,0), csg.Vec(2,0,0), csg.Vec(0,1,0), 3, 0.5) * brick)\n    geo.Add(csg.Torus(csg.Pnt(0,0,0), csg.Vec(0,1,0), 0.3, 0.05))\n    pts2d = [[1,1], [1,-1], [-1,-1], [-1,1]]\n    segs = [[0,1], [1,2], [2,3], [3,0]]\n    curve = csg.SplineCurve2d()\n    pnrs = [curve.AddPoint(*p) for p in pts2d]\n    for s in segs:\n            curve.AddSegment(pnrs[s[0]], pnrs[s[1]])\n    geo.Add(csg.Revolution(csg.Pnt(0,0,0), csg.Pnt(1,0,0), curve))\n    path = csg.SplineCurve3d()\n    pnts = [(0,0,0), (2,0,0), (2,2,0)]\n    segs = [(0,1,2)]\n    for pnt in pnts:\n        path.AddPoint (*pnt)\n\n    for seg in segs:\n        path.AddSegment (*seg)\n    geo.Add(csg.Extrusion(path, curve, csg.Vec(0,0,1)))\n\n    geo_dump = pickle.dumps(geo)\n    geo2 = pickle.loads(geo_dump)\n    vd1 = geo._visualizationData()\n    vd2 = geo2._visualizationData()\n    for val1, val2 in zip(vd1.values(), vd2.values()):\n        assert numpy.array_equal(val1, val2)\n\ndef test_pickle_stl():\n    import netgen.stl as stl\n    geo = stl.LoadSTLGeometry(\"../../tutorials/hinge.stl\")\n    geo_dump = pickle.dumps(geo)\n    geo2 = pickle.loads(geo_dump)\n    vd1 = geo._visualizationData()\n    vd2 = geo2._visualizationData()\n    for val1, val2 in zip(vd1.values(), vd2.values()):\n        assert numpy.array_equal(val1, val2)\n\n\ndef test_pickle_occ():\n    try:\n        import netgen.occ as occ\n    except:\n        import pytest\n        pytest.skip(\"can't import occ\")\n    geo = occ.OCCGeometry(\"../../tutorials/frame.step\")\n    geo_dump = pickle.dumps(geo)\n    geo2 = pickle.loads(geo_dump)\n    vd1 = geo._visualizationData()\n    vd2 = geo2._visualizationData()\n    # TODO: it looks fine, but tests fail, so I assume we loose some info?\n    # for val1, val2 in zip(vd1.values(), vd2.values()):\n    #     assert numpy.allclose(val1, val2, rtol=0.01)\n\ndef test_pickle_geom2d():\n    import netgen.geom2d as geom2d\n    geo = geom2d.SplineGeometry()\n\n    # point coordinates ...\n    pnts = [ (0,0), (1,0), (1,0.6), (0,0.6), \\\n             (0.2,0.6), (0.8,0.6), (0.8,0.8), (0.2,0.8), \\\n             (0.5,0.15), (0.65,0.3), (0.5,0.45), (0.35,0.3) ]\n    pnums = [geo.AppendPoint(*p) for p in pnts]\n\n    # start-point, end-point, boundary-condition, domain on left side, domain on right side:\n    lines = [ (0,1,1,1,0), (1,2,2,1,0), (2,5,2,1,0), (5,4,2,1,2), (4,3,2,1,0), (3,0,2,1,0), \\\n              (5,6,2,2,0), (6,7,2,2,0), (7,4,2,2,0), \\\n              (8,9,2,3,1), (9,10,2,3,1), (10,11,2,3,1), (11,8,2,3,1) ]\n\n    for p1,p2,bc,left,right in lines:\n        geo.Append( [\"line\", pnums[p1], pnums[p2]], bc=bc, leftdomain=left, rightdomain=right)\n    geo_dump = pickle.dumps(geo)\n    geo2 = pickle.loads(geo_dump)\n    vd1 = geo._visualizationData()\n    vd2 = geo2._visualizationData()\n    for val1, val2 in zip(vd1.values(), vd2.values()):\n        assert numpy.array_equal(val1, val2)\n\ndef test_pickle_mesh():\n    import netgen.csg as csg\n    geo1 = csg.CSGeometry()\n    geo2 = csg.CSGeometry()\n    brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3))\n    geo2.Add(brick)\n\n    for geo in [geo1, geo2]:\n        mesh = geo.GenerateMesh(maxh=2)\n        assert geo == mesh.GetGeometry()\n        dump = pickle.dumps([geo,mesh])\n        geo2, mesh2 = pickle.loads(dump)\n        assert geo2 == mesh2.GetGeometry()\n        mesh.Save(\"msh1.vol.gz\")\n        mesh2.Save(\"msh2.vol.gz\")\n        import filecmp, os\n        assert filecmp.cmp(\"msh1.vol.gz\", \"msh2.vol.gz\")\n        os.remove(\"msh1.vol.gz\")\n        os.remove(\"msh2.vol.gz\")\n\nif __name__ == \"__main__\":\n    test_pickle_mesh()\n"
  },
  {
    "path": "tests/pytest/test_savemesh.py",
    "content": "\nfrom netgen.csg import *\nfrom netgen import meshing\nimport filecmp\nimport difflib\nfrom math import sqrt, cos, sin\n\ndef CreateQuad():\n    base = Plane(Pnt(0,0,0),Vec(0,0,1))\n    surface = SplineSurface(base)\n    pts = [(-0.2,-0.2,0),(-0.2,0.2,0),(0.2,0.2,0),(0.2,-0.2,0)]\n    geopts = [surface.AddPoint(*p) for p in pts]\n    for p1,p2,bc in [(0,1,\"wire\"), (1, 2,\"contact\"),(2,3,\"wire\"),(3,0,\"wire\")]:\n        surface.AddSegment(geopts[p1],geopts[p2],bc)\n    return surface\n\nCross = lambda a,b: [a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-b[0]*a[1]]\n\n\ndef CreateGeo():\n    geo = CSGeometry()\n    air = OrthoBrick(Pnt(-1,-1,-1),Pnt(1,1,1))\n    geo.Add(air.mat(\"air\"))\n    surface = CreateQuad()\n    geo.AddSplineSurface(surface)\n    return geo\n\ndef test_BBNDsave():\n    mesh = CreateGeo().GenerateMesh(maxh=0.4,perfstepsend = meshing.MeshingStep.MESHSURFACE)\n    for i in range(2):\n        mesh.GenerateVolumeMesh(only3D_domain_nr=i+1,maxh=0.4)\n    mesh.SetGeometry(None)\n    mesh.Save(\"test.vol\")\n    mesh2 = meshing.Mesh()\n    mesh2.Load(\"test.vol\")\n    mesh2.Save(\"test2.vol\")\n    with open(\"test.vol\",\"r\") as f:\n        first = f.readlines()\n    with open(\"test2.vol\",\"r\") as f:\n        second = f.readlines()\n    # exclude the face colours section (because they aren't in the same order)\n    for i,line in enumerate(first):\n        if line[0:12] == \"face_colours\":\n            first = first[0:i]\n            second = second[0:i]\n            break\n    diff = difflib.context_diff(first,second)\n    print(\"File diff:\")\n    l = list(diff)\n    print(*l)\n    assert len(l)==0\n\n"
  },
  {
    "path": "tests/pytest/test_splinegeo_tensordomainmeshing.py",
    "content": "from netgen.geom2d import *\n\ndef test_tensordomainmeshing():\n    geo = SplineGeometry()\n    w = 10\n    h = 0.01\n\n    p = [ (0, 0), (w, 0), (w, h), (0, h) ]\n    p = [geo.AppendPoint(*px) for px in p]\n\n    l0 = geo.Append ( [\"line\", p[0], p[1]], leftdomain=1, rightdomain=0 )\n    l1 = geo.Append ( [\"line\", p[1], p[2]], leftdomain=1, rightdomain=0)\n    geo.Append ( [\"line\", p[3], p[2]], leftdomain=0, rightdomain=1, copy=l0 )\n    geo.Append ( [\"line\", p[0], p[3]], leftdomain=0, rightdomain=1, copy=l1 )\n\n    geo._SetDomainTensorMeshing(1, True)\n\n    mesh = geo.GenerateMesh(maxh=1)\n\n    for el in mesh.Elements2D():\n        print(el.vertices)\n        assert len(el.vertices) == 4\n"
  },
  {
    "path": "tests/pytest/test_tutorials.py",
    "content": "\nimport os, pytest\nfrom netgen.meshing import meshsize, MeshingParameters, SetMessageImportance\nimport netgen.csg as csg\nimport netgen.stl as stl\nimport netgen.geom2d as geom2d\nfrom pyngcore import TaskManager\nimport json\ntry:\n    import netgen.occ as occ\n    has_occ = occ.occ_version >= \"7.4.0\"\n    has_occ = False # skip occ tests (current development on interface)\nexcept ImportError:\n    has_occ = False\n\nSetMessageImportance(0)\n\ndef round(x, digits=11):\n    try:\n        return float((\"{:.\"+str(digits)+\"g}\").format(x))\n    except: #list\n        return [float((\"{:.\"+str(digits)+\"g}\").format(y)) for y in x]\n\n\ndef getData(mesh, mp):\n    out = {}\n    out['ne1d'] = len(mesh.Elements1D())\n    out['ne2d'] = len(mesh.Elements2D())\n    out['ne3d'] = len(mesh.Elements3D())\n    # round badness to avoid fluctuations in last digits\n    out[\"total_badness\"] = round(mesh.CalcTotalBadness(mp))\n    angles = mesh.CalcMinMaxAngle()\n    out[\"angles_trig\"] = round(angles[\"trig\"], 5)\n    out[\"angles_tet\"] = round(angles[\"tet\"], 5)\n    out[\"quality_histogram\"] = str(list(mesh.GetQualityHistogram()))\n    return out\n\ndef checkData(mesh, mp, ref):\n    data = getData(mesh, mp)\n    # assert ref['ne1d'] == pytest.approx(data['ne1d'], rel=1e-2)\n    # assert ref['ne2d'] == pytest.approx(data['ne2d'], rel=1e-2)\n    # assert ref['ne3d'] == pytest.approx(data['ne3d'], rel=1e-2)\n    # assert json.loads(ref['quality_histogram']) == pytest.approx(json.loads(data['quality_histogram']), abs=3, rel=0.4)\n    # assert ref['total_badness'] == pytest.approx(data['total_badness'], rel=1e-2)\n    # assert ref['angles_trig'] == pytest.approx(data['angles_trig'], rel=1e-3)\n    # assert ref['angles_tet'] == pytest.approx(data['angles_tet'], rel=1e-3)\n\n# get tutorials\ndef getFiles(fileEnding):\n    r, d, files = next(os.walk(os.path.join(\"..\",\"..\",\"tutorials\")))\n    return [f for f in files if f.endswith(fileEnding)]\n\n# get additional tests\ndef getAdditionalFiles(fileEnding):\n    r, d, files = next(os.walk(\"geofiles\"))\n    return [f for f in files if f.endswith(fileEnding)]\n\n@pytest.fixture\ndef refdata():\n    return json.load(open('results.json','r'))\n\n\ndef getMeshingparameters(filename):\n    standard = [MeshingParameters()] + [MeshingParameters(ms)  for ms in (meshsize.very_coarse, meshsize.coarse, meshsize.moderate, meshsize.fine, meshsize.very_fine)]\n    if filename == \"shell.geo\":\n        return [] # do not test this example cause it needs so long...\n    if filename == \"manyholes2.geo\":\n        return [standard[1]] # this gets too big for finer meshsizes\n    if filename in (\"manyholes.geo\", \"frame.step\"):\n        return standard[:3] # this gets too big for finer meshsizes\n    if filename == \"extrusion.geo\":\n        return standard[:-1]\n    if filename == \"screw.step\":\n        return standard[3:] # coarser meshes don't work here\n    if filename == \"cylinder.geo\":\n        return [] # gives inconsistent reults\n    if filename == \"cylsphere.geo\":\n        return standard[0:2] + standard[3:] # coarse gives inconsistent reults (other mesh on MacOS)\n    if filename == \"part1.stl\":\n        return standard[0:1] + standard[2:] # very coarse does not work\n    return standard\n\n_geofiles =  getFiles(\".in2d\") + getFiles(\".geo\") + getFiles(\".stl\")\nif has_occ:\n    _geofiles += getFiles(\".step\")\n_geofiles.sort()\n_additional_testfiles = getAdditionalFiles(\".stl\")\nif has_occ:\n    _additional_testfiles += getAdditionalFiles(\".step\")\n_additional_testfiles.sort()\n\ndef generateMesh(filename, mp):\n    folder = os.path.join(\"..\",\"..\",\"tutorials\") if filename in _geofiles else \"geofiles\"\n    if filename.endswith(\".geo\"):\n        geo = csg.CSGeometry(os.path.join(folder, filename))\n    elif filename.endswith(\".stl\"):\n        geo = stl.STLGeometry(os.path.join(folder, filename))\n    elif filename.endswith(\".step\"):\n        geo = occ.OCCGeometry(os.path.join(folder, filename))\n    elif filename.endswith(\".in2d\"):\n        geo = geom2d.SplineGeometry(os.path.join(folder, filename))\n    return geo.GenerateMesh(mp)\n\ndef isSlowTest(filename):\n    return filename in [\"cubemcyl.geo\", \"frame.step\", \"revolution.geo\", \"manyholes.geo\", \"torus.geo\",\n                        \"cubemsphere.geo\", \"manyholes2.geo\", \"matrix.geo\", \"trafo.geo\", \"ellipticcone.geo\",\n                        \"period.geo\", \"shaft.geo\", \"cubeandring.geo\", \"ellipticcyl.geo\",\n                        \"ellipsoid.geo\", \"cone.geo\", \"plane.stl\"]\n\ndef getParameters():\n    res = []\n    for f in _geofiles + _additional_testfiles:\n        for i,mp in enumerate(getMeshingparameters(f)):\n            if isSlowTest(f):\n                res.append( pytest.param(f, mp, i, marks=pytest.mark.slow ) )\n            else:\n                res.append( (f, mp, i) )\n    return res\n\n@pytest.mark.parametrize((\"filename\", \"mp\", \"i\"), getParameters())\ndef test_geoFiles(filename, mp, i, refdata):\n    ref = refdata[filename]\n    import filecmp\n    print(\"load geo\", filename)\n    mp = MeshingParameters(mp, parallel_meshing=False)\n    mesh = generateMesh(filename, mp)\n    mesh.Save(filename+'_seq.vol.gz')\n    with TaskManager():\n        mesh_par = generateMesh(filename, mp)\n        mesh_par.Save(filename+'_par.vol.gz')\n\n    assert filecmp.cmp(filename+'_seq.vol.gz', filename+'_par.vol.gz')\n    checkData(mesh, mp, ref[i])\n\n\ndef generateResultFile(output_file='results.json'):\n    import time\n    data = {}\n    with TaskManager():\n        for _file in _geofiles + _additional_testfiles:\n            print(\"generate \"+_file)\n            start = time.time()\n            mps = getMeshingparameters(_file)\n            if not mps:\n                continue\n            meshdata = []\n            for mp in mps:\n                try:\n                    mesh = generateMesh(_file, mp)\n                except Exception as e:\n                    print(\"Meshingparameters: \", mp)\n                    raise e\n                meshdata.append( getData(mesh, mp) )\n            data[_file] = meshdata\n            print(\"needed\", time.time() - start, \"seconds\")\n        \n    s = json.dumps(data, sort_keys=True, indent=4)\n    open(output_file, \"w\").write(s)\n    print(\"done\")\n\nif __name__ == \"__main__\":\n    import sys\n    generateResultFile(*sys.argv[1:])\n"
  },
  {
    "path": "tests/utils.py",
    "content": "import argparse\nimport os\nimport requests\nimport sys\nimport time\nfrom subprocess import check_output\nfrom packaging import tags\nfrom packaging.utils import parse_wheel_filename\n\n\n_sys_tags = None\n\n\ndef _is_wheel_compatible(wheel_filename: str):\n    global _sys_tags\n    try:\n        if _sys_tags is None:\n            _sys_tags = set(tags.sys_tags())\n\n        for tag in parse_wheel_filename(wheel_filename)[-1]:\n            if tag in _sys_tags:\n                return True\n\n        return False\n    except Exception as e:\n        print(f\"Error parsing wheel file: {e}\")\n        return False\n\n\ndef is_package_available(package_name, version):\n    url = f\"https://pypi.org/pypi/{package_name}/{version}/json\"\n\n    try:\n        response = requests.get(url)\n        if response.status_code != 200:\n            return False\n\n        data = response.json()\n\n        for file_info in data[\"urls\"]:\n            name = file_info.get(\"filename\", \"\")\n            if _is_wheel_compatible(name):\n                return True\n\n        return False\n\n    except requests.RequestException as e:\n        print(f\"Error checking package: {e}\")\n        return False\n\n\ndef is_dev_build():\n    if \"NG_NO_DEV_PIP_VERSION\" in os.environ:\n        return False\n    if (\n        \"CI_COMMIT_REF_NAME\" in os.environ\n        and os.environ[\"CI_COMMIT_REF_NAME\"] == \"release\"\n    ):\n        return False\n    return True\n\n\ndef get_git_version(cwd):\n    return check_output([\"git\", \"describe\", \"--tags\"], cwd=cwd).decode(\"utf-8\").strip()\n\n\ndef get_version(cwd):\n    git_version = get_git_version(cwd)\n\n    version = git_version[1:].split(\"-\")\n    if len(version) > 2:\n        version = version[:2]\n    if len(version) > 1:\n        version = \".post\".join(version)\n        if is_dev_build():\n            version += \".dev0\"\n    else:\n        version = version[0]\n\n    return version\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Netgen pip building utilities\")\n    parser.add_argument(\n        \"--check-pip\",\n        action=\"store_true\",\n        help=\"Check if package is on pypi already, fails with exit code 1 if available\",\n    )\n    parser.add_argument(\n        \"--wait-pip\",\n        action=\"store_true\",\n        help=\"Wait until package is on pypi, fails with exit code 1 if still not available after 300s\",\n    )\n    parser.add_argument(\n        \"--get-git-version\",\n        action=\"store_true\",\n        help=\"Generate the current package git version string\",\n    )\n    parser.add_argument(\n        \"--get-version\",\n        action=\"store_true\",\n        help=\"Generate the current package version using git\",\n    )\n    parser.add_argument(\"--dir\", type=str, default=\".\", help=\"CWD to run git commands\")\n    parser.add_argument(\n        \"--package\",\n        type=str,\n        default=\"netgen-mesher\",\n        help=\"Package name to check on pypi\",\n    )\n\n    args = parser.parse_args()\n\n    if args.get_git_version:\n        print(get_git_version(args.dir))\n    elif args.get_version:\n        print(get_version(args.dir))\n    elif args.check_pip:\n        version = get_version(args.dir)\n        if is_package_available(args.package, version):\n            print(f\"{args.package}=={version} is already on pypi\")\n            sys.exit(1)\n    elif args.wait_pip:\n        version = get_version(args.dir)\n        t0 = time.time()\n        while time.time() - t0 < 300 and not is_package_available(\n            args.package, version\n        ):\n            time.sleep(20)\n\n        if not is_package_available(args.package, version):\n            print(\n                f\"Timeout waiting for package {args.package}=={version} to be available on pypi\"\n            )\n            sys.exit(1)\n    else:\n        print(\"no action\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "tutorials/CMakeLists.txt",
    "content": "install( FILES \n        boxcyl.geo circle_on_cube.geo cone.geo cube.geo\t\t\t   \n        cubeandring.geo cubeandspheres.geo cubemcyl.geo cubemsphere.geo cylinder.geo\t   \n        cylsphere.geo ellipsoid.geo ellipticcyl.geo extrusion.geo fichera.geo lshape3d.geo \n        manyholes.geo manyholes2.geo matrix.geo ortho.geo period.geo revolution.geo\t   \n        sculpture.geo shaft.geo shell.geo sphere.geo sphereincube.geo torus.geo trafo.geo  \n        twobricks.geo twocubes.geo twocyl.geo boundarycondition.geo\t\t\t   \n        hinge.stl  part1.stl frame.step  screw.step\t\t\t\t\t   \n        squarehole.in2d squarecircle.in2d square.in2d\n        DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX}\n        COMPONENT netgen_tutorial\n       )\n"
  },
  {
    "path": "tutorials/boundarycondition.geo",
    "content": "algebraic3d\n\nsolid p1 = plane (0.5, 0, 0; 1, 0, 0);\n\n# since surfaces of both bricks are identic they get the same bc id:\nsolid brick1 = orthobrick (0,0,0; 1,1,1) and p1 -bc=1;\nsolid brick2 = orthobrick (0,0,-1; 1,1,0) and p1 -bc=2;\n\n\ntlo brick1;\ntlo brick2;\n\n# override bc number: \n# all faces of solid p1 belonging to the boundary of tlo brick1 get bc=3\n\nboundarycondition p1 brick1 3;\n"
  },
  {
    "path": "tutorials/boxcyl.geo",
    "content": "#\n## Two cylinders on a box\n#\nalgebraic3d\n\n#define box:\n\nsolid box = plane (0, 0, 0.5; -1, 0, 0)\n\tand plane (0, 0, 0.5; 0, -1, 0)\n\tand plane (0, 0, 0.5; 0, 0, -1)\n\tand plane (2, 1.5, 1; 1, 0, 0)\n\tand plane (2, 1.5, 1; 0, 1, 0)\n\tand plane (2, 1.5, 1; 0, 0, 1);\n\n#define cylinders:\n\nsolid cyls = (cylinder (0.5, 0.75, 0; 0.5, 0.75, 2; 0.3) \n\tor cylinder (1.5, 0.75, 0; 1.5, 0.75, 2; 0.3) )\n\tand plane (0, 0, 0.7; 0, 0, -1)\n\tand plane (0, 0, 1.5; 0, 0, 1);\n\n#combine both:\n\nsolid main = box or cyls;\n\n\n#define sub-domains:\ntlo main;\n\nsingular edge box cyls;\n\n\t\n"
  },
  {
    "path": "tutorials/circle_on_cube.geo",
    "content": "#\n## A cube\n#\nalgebraic3d\n\n# cube consisting of 6 planes:\n\nsolid cube = plane (0, 0, 0; 0, 0, -1) \n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\n\nsolid top = plane (1,1,1; 0, 0, 1);\nsolid cyl = top \n\tand plane (0,0,0; 0, 0, -1)\n\tand cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.2);\n\t\n\ntlo cube;\n\n# take just surface 'top' of solid 'cyl'\ntlo cyl top -col=[1,0,0];\n\n\n"
  },
  {
    "path": "tutorials/cone.geo",
    "content": "#\n## A cone\n#\nalgebraic3d\n\n# Cone given by bottom circle and top circle\n# and cut by planes:\n\nsolid cutcone = cone ( 0, 0, 0; 1; 3, 0, 0; 0.1 )\n\tand plane (0, 0, 0; -1, 0, 0)\n\tand plane (3, 0, 0; 1, 0, 0);\n\ntlo cutcone;\n"
  },
  {
    "path": "tutorials/cube.geo",
    "content": "#\n## A cube\n#\nalgebraic3d\n\n# cube consisting of 6 planes:\n\nsolid cube = plane (0, 0, 0; 0, 0, -1) \n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\ntlo cube;\n\n"
  },
  {
    "path": "tutorials/cubeandring.geo",
    "content": "algebraic3d\n\ncurve2d testcurve=(8;\n\t-0.5,1;\n\t-0.55,1.5;\n#\t-0.275,1.775;\n\t-0.5,2;\n\t0,2.05;\n\t0.5,2;\n\t0.55,1.5;\n\t0.5,1;\n\t0,0.95;\n\t4;\n\t3,8,1,2;\n\t3,2,3,4;\t\n\t3,4,5,6;\n\t3,6,7,8);\n\n#curve2d testcurve=(8;\n#\t-0.5,1;\n#\t-0.55,1.5;\n#\t-0.5,2;\n#\t0,2.05;\n#\t0.5,2;\n#\t0.55,1.5;\n#\t0.5,1;\n#\t0,0.95;\n#\t4;\n#\t3,8,1,2;\n#\t3,2,3,4;\t\n#\t3,4,5,6;\n#\t3,6,7,8);\n\ncurve2d testcurve1=(4;\n\t-0.55,1.5;\n\t0,2.05;\n\t0.55,1.5;\n\t0,0.95;\n\t4;\n\t2,1,2;\n\t2,2,3;\n\t2,3,4;\n\t2,4,1);\n\n\nsolid mytorus = revolution(0,0,0.5;1,0,0.5;testcurve);\n#solid mytorus = revolution(0,0,0.5;1,0,0.5;testcurve1);\n\nsolid bbb = orthobrick(-4,-4,-4;4,4,0.1);\n\nsolid brickandring = mytorus or bbb;\n\n\ntlo brickandring;\n\n"
  },
  {
    "path": "tutorials/cubeandspheres.geo",
    "content": "#\n## Cube and Spheres\n#\nalgebraic3d\n\n# a cube\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\n# two spheres\nsolid sph1 = sphere (0.5, 0.5, 0.5; 0.58);\nsolid sph2 = sphere (0.5, 0.5, 0.5; 0.75);\n\n# cut cube with inner and outer sphere\nsolid main = cube and sph2 and not sph1;\n\ntlo main;\n"
  },
  {
    "path": "tutorials/cubemcyl.geo",
    "content": "#\n## Cube minus Cylinder\n#\nalgebraic3d\n\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\nsolid cyl = cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.03);\n\n# cut off small cylinder from cube:\n\nsolid main = cube and not cyl;\n\ntlo main;\n"
  },
  {
    "path": "tutorials/cubemsphere.geo",
    "content": "#\n## Cube minus Cylinder\n#\nalgebraic3d\n\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\nsolid sp = sphere (0.5, 0.5, 0; 0.001);\n\n# cut off small sphere:\n\nsolid main = cube and not sp;\n\ntlo main;\n\n"
  },
  {
    "path": "tutorials/cylinder.geo",
    "content": "#\n## a cylinder\n#\nalgebraic3d\n\n# cut cylinder by planes:\n\nsolid fincyl = cylinder ( 3, 0, 0; -1, 0, 0; 0.5 )\n\tand plane (0, 0, 0; -1, 0, 0)\n\tand plane (2, 0, 0; 1, 0, 0);\n\ntlo fincyl;\n"
  },
  {
    "path": "tutorials/cylsphere.geo",
    "content": "#\n## Cylinder and Spehre\n#\nalgebraic3d\nsolid cyl = cylinder ( 3, 0, 0; -3, 0, 0; 0.5 )\n\tand plane (-2, 0, 0; -1, 0, 0)\n\tand plane (2, 0, 0; 1, 0, 0);\nsolid sp = sphere (0, 0, 0; 1);\n\nsolid main = sp or cyl;\n\ntlo main;\n"
  },
  {
    "path": "tutorials/ellipsoid.geo",
    "content": "#\n## An elliptic cylinder\n#\nalgebraic3d\n\nsolid test = ellipsoid (0, 0, 0; 2, 0, 0; 0, 1, 0; 0, 0, 1) -maxh=0.5;\n\ntlo test;\n"
  },
  {
    "path": "tutorials/ellipticcone.geo",
    "content": "#\n## An elliptic cone\n#\n\n# An elliptic cone, given by the point c = (c x , c y , c z ) at the base of the cone along the main axis,\n# the vectors v and w of the long and short axis of the ellipse, respectively,\n# the height of the cone, h, and ratio of base long axis length to top long axis length, r:\n# ellipticcone (c x , c y , c z ; v x , v y , v z ; w x , w y , w z; h; r)\n\n# Note: The elliptic cone has to be truncated by planes similar to a cone or an elliptic cylinder.\n# When r =1, the truncated elliptic cone becomes an elliptic cylinder.\n# When r tends to zero, the truncated elliptic cone tends to a full elliptic cone.\n# However, when r = 0, the top part becomes a point(tip) and meshing fails!\n\nalgebraic3d\n\nsolid cutcone = ellipticcone ( 0, 0, 0; 5, 0, 0; 0, 2, 0; 5; 0.5)\n\tand plane (0, 0, 0; 0, 0, -1)\n\tand plane (0, 0, 5; 0, 0, 1);\n\ntlo cutcone;\n"
  },
  {
    "path": "tutorials/ellipticcyl.geo",
    "content": "#\n## An elliptic cylinder\n#\nalgebraic3d\n\nsolid cutcone = ellipticcylinder ( 0, 0, 0; 1, 0, 0; 0, 0.5, 0)\n\tand plane (0, 0, 0; 0, 0, -1)\n\tand plane (0, 0, 1; 0, 0, 1);\n\ntlo cutcone;\n"
  },
  {
    "path": "tutorials/extrusion.geo",
    "content": "algebraic3d\n\ncurve2d procurve1=(8;\n\t-1,0;\n\t-0.7,0.7;\n\t0,1;\n\t0.7,0.7;\n\t1,0;\n\t0.7,-0.7;\n\t0,-1;\n\t-0.7,-0.7;\n\t4;\n\t3,1,2,3;\n\t3,3,4,5;\n\t3,5,6,7;\n\t3,7,8,1);\n\ncurve2d procurve2=(4;\n\t1,1;\n\t1,-1;\n\t-1,-1;\n\t-1,1;\n\t4;\n\t2,1,2;\n\t2,2,3;\n\t2,3,4;\n\t2,4,1);\n\n\n\ncurve3d pathcurve1=(9;\n\t0,0,0;\n\t10,0,5;\n\t10,10,10;\n\t10,20,15;\n\t0,20,20;\n\t-10,20,25;\n\t-10,10,30;\n\t-10,0,35;\n\t0,0,40;\n\t4;\n\t3,1,2,3;\n\t3,3,4,5;\n\t3,5,6,7;\n\t3,7,8,9);\n\ncurve3d pathcurve2=(2;\n\t0,0,0;\n\t0,10,0;\n\t1;\n\t2,1,2);\n\n\ncurve3d pathcurve3=(3;\n\t0,0,0;\n\t10,0,5;\n\t10,10,10;\n\t1;\n\t3,1,2,3);\n\ncurve3d pathcurve4=(9;\n\t0,0,0;\n\t10,0,0;\n\t10,10,0;\n\t10,20,0;\n\t0,20,0;\n\t-10,20,0;\n\t-10,10,0;\n\t-10,0,0;\n\t0,0,0;\n\t4;\n\t3,1,2,3;\n\t3,3,4,5;\n\t3,5,6,7;\n\t3,7,8,9);\n\n\nsolid p1 = plane(1,0,0;-1,0,0);\nsolid p2 = plane(10,9,10;0,1,0);\nsolid p3 = plane(0,1,0;0,-1,0);\nsolid p4 = plane(0,9,0;0,1,0);\n\nsolid ob1 = orthobrick(-1,-5,-5;1,5,45);\n\nsolid ext = extrusion(pathcurve1;procurve2;0,0,1) and not ob1;\n\n#solid ext = extrusion(pathcurve4;procurve2;0,0,1);\n\n#solid ext = extrusion(pathcurve3;procurve1;0,0,1) and p1 and p2;\n\n#solid ext = extrusion(pathcurve2;procurve2;0,0,1) and p3 and p4;\n\nsolid sp = sphere(0,0,0;4);\n\nsolid comb = sp or ext;\n\n#tlo ext;\n\ntlo comb;"
  },
  {
    "path": "tutorials/fichera.geo",
    "content": "#\n## Fichera Cube\n#\nalgebraic3d\nsolid c1 = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0) -bc=2;\n\nsolid c2 = plane (-0.5, -0.5, -0.5; 0, 0, -1)\n         and plane (-0.5, -0.5, -0.5; 0, -1, 0)\n         and plane (-0.5, -0.5, -0.5; -1, 0, 0)\n         and plane (0.5, 0.5, 0.5; 0, 0, 1)\n         and plane (0.5, 0.5, 0.5; 0, 1, 0)\n         and plane (0.5, 0.5, 0.5; 1, 0, 0);\n\n# cut off small cube\n\nsolid main = c1 and not c2 -bc=1;\n\ntlo main;\n\n"
  },
  {
    "path": "tutorials/frame.step",
    "content": "ISO-10303-21;\r\nHEADER;\r\nFILE_DESCRIPTION((''),'2;1');\r\nFILE_NAME('PROESOURCE','2002-11-04T',('user-01'),(''),\r\n'PRO/ENGINEER BY PARAMETRIC TECHNOLOGY CORPORATION, 2002060',\r\n'PRO/ENGINEER BY PARAMETRIC TECHNOLOGY CORPORATION, 2002060','');\r\nFILE_SCHEMA(('CONFIG_CONTROL_DESIGN'));\r\nENDSEC;\r\nDATA;\r\n#1=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2=VECTOR('',#1,1.693725393319E1);\r\n#3=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0));\r\n#4=LINE('',#3,#2);\r\n#5=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6=VECTOR('',#5,9.E0);\r\n#7=CARTESIAN_POINT('',(1.65E1,0.E0,2.5E0));\r\n#8=LINE('',#7,#6);\r\n#9=CARTESIAN_POINT('',(1.8E1,0.E0,3.075E1));\r\n#10=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#12=AXIS2_PLACEMENT_3D('',#9,#10,#11);\r\n#14=CARTESIAN_POINT('',(1.8E1,0.E0,3.075E1));\r\n#15=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#16=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#17=AXIS2_PLACEMENT_3D('',#14,#15,#16);\r\n#19=CARTESIAN_POINT('',(1.8E1,0.E0,1.25E0));\r\n#20=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#21=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#22=AXIS2_PLACEMENT_3D('',#19,#20,#21);\r\n#24=CARTESIAN_POINT('',(1.8E1,0.E0,1.25E0));\r\n#25=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#26=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#27=AXIS2_PLACEMENT_3D('',#24,#25,#26);\r\n#29=CARTESIAN_POINT('',(1.2E1,0.E0,3.075E1));\r\n#30=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#31=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#32=AXIS2_PLACEMENT_3D('',#29,#30,#31);\r\n#34=CARTESIAN_POINT('',(1.2E1,0.E0,3.075E1));\r\n#35=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#36=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#37=AXIS2_PLACEMENT_3D('',#34,#35,#36);\r\n#39=CARTESIAN_POINT('',(6.E0,0.E0,3.075E1));\r\n#40=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#41=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#42=AXIS2_PLACEMENT_3D('',#39,#40,#41);\r\n#44=CARTESIAN_POINT('',(6.E0,0.E0,3.075E1));\r\n#45=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#46=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#47=AXIS2_PLACEMENT_3D('',#44,#45,#46);\r\n#49=CARTESIAN_POINT('',(1.2E1,0.E0,1.25E0));\r\n#50=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#51=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#52=AXIS2_PLACEMENT_3D('',#49,#50,#51);\r\n#54=CARTESIAN_POINT('',(1.2E1,0.E0,1.25E0));\r\n#55=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#56=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#57=AXIS2_PLACEMENT_3D('',#54,#55,#56);\r\n#59=CARTESIAN_POINT('',(2.2875E1,0.E0,2.4E1));\r\n#60=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#61=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#62=AXIS2_PLACEMENT_3D('',#59,#60,#61);\r\n#64=CARTESIAN_POINT('',(2.2875E1,0.E0,2.4E1));\r\n#65=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#66=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#67=AXIS2_PLACEMENT_3D('',#64,#65,#66);\r\n#69=CARTESIAN_POINT('',(2.2875E1,0.E0,1.8E1));\r\n#70=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#71=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#72=AXIS2_PLACEMENT_3D('',#69,#70,#71);\r\n#74=CARTESIAN_POINT('',(2.2875E1,0.E0,1.8E1));\r\n#75=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#76=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#77=AXIS2_PLACEMENT_3D('',#74,#75,#76);\r\n#79=CARTESIAN_POINT('',(2.2875E1,0.E0,1.2E1));\r\n#80=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#81=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#82=AXIS2_PLACEMENT_3D('',#79,#80,#81);\r\n#84=CARTESIAN_POINT('',(2.2875E1,0.E0,1.2E1));\r\n#85=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#86=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#87=AXIS2_PLACEMENT_3D('',#84,#85,#86);\r\n#89=CARTESIAN_POINT('',(2.2875E1,0.E0,6.E0));\r\n#90=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#91=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#92=AXIS2_PLACEMENT_3D('',#89,#90,#91);\r\n#94=CARTESIAN_POINT('',(2.2875E1,0.E0,6.E0));\r\n#95=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#96=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#97=AXIS2_PLACEMENT_3D('',#94,#95,#96);\r\n#99=CARTESIAN_POINT('',(1.125E0,0.E0,2.4E1));\r\n#100=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#101=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#102=AXIS2_PLACEMENT_3D('',#99,#100,#101);\r\n#104=CARTESIAN_POINT('',(1.125E0,0.E0,2.4E1));\r\n#105=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#106=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#107=AXIS2_PLACEMENT_3D('',#104,#105,#106);\r\n#109=CARTESIAN_POINT('',(1.125E0,0.E0,1.8E1));\r\n#110=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#111=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#112=AXIS2_PLACEMENT_3D('',#109,#110,#111);\r\n#114=CARTESIAN_POINT('',(1.125E0,0.E0,1.8E1));\r\n#115=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#116=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#117=AXIS2_PLACEMENT_3D('',#114,#115,#116);\r\n#119=CARTESIAN_POINT('',(1.125E0,0.E0,1.2E1));\r\n#120=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#121=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#122=AXIS2_PLACEMENT_3D('',#119,#120,#121);\r\n#124=CARTESIAN_POINT('',(1.125E0,0.E0,1.2E1));\r\n#125=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#126=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#127=AXIS2_PLACEMENT_3D('',#124,#125,#126);\r\n#129=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#130=VECTOR('',#129,1.E0);\r\n#131=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0));\r\n#132=LINE('',#131,#130);\r\n#133=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#134=VECTOR('',#133,3.E0);\r\n#135=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0));\r\n#136=LINE('',#135,#134);\r\n#137=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#138=VECTOR('',#137,1.6E1);\r\n#139=CARTESIAN_POINT('',(2.E1,0.E0,0.E0));\r\n#140=LINE('',#139,#138);\r\n#141=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#142=VECTOR('',#141,3.E0);\r\n#143=CARTESIAN_POINT('',(0.E0,0.E0,4.E0));\r\n#144=LINE('',#143,#142);\r\n#145=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#146=VECTOR('',#145,1.E0);\r\n#147=CARTESIAN_POINT('',(-1.E0,0.E0,8.E0));\r\n#148=LINE('',#147,#146);\r\n#149=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#150=VECTOR('',#149,3.75E0);\r\n#151=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0));\r\n#152=LINE('',#151,#150);\r\n#153=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#154=VECTOR('',#153,5.E-1);\r\n#155=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1));\r\n#156=LINE('',#155,#154);\r\n#157=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#158=VECTOR('',#157,1.475E1);\r\n#159=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1));\r\n#160=LINE('',#159,#158);\r\n#161=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#162=VECTOR('',#161,1.6E1);\r\n#163=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1));\r\n#164=LINE('',#163,#162);\r\n#165=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#166=VECTOR('',#165,1.475E1);\r\n#167=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1));\r\n#168=LINE('',#167,#166);\r\n#169=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#170=VECTOR('',#169,5.E-1);\r\n#171=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1));\r\n#172=LINE('',#171,#170);\r\n#173=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#174=VECTOR('',#173,3.75E0);\r\n#175=CARTESIAN_POINT('',(2.6E1,0.E0,8.E0));\r\n#176=LINE('',#175,#174);\r\n#177=CARTESIAN_POINT('',(1.125E0,0.E0,6.E0));\r\n#178=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#179=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#180=AXIS2_PLACEMENT_3D('',#177,#178,#179);\r\n#182=CARTESIAN_POINT('',(1.125E0,0.E0,6.E0));\r\n#183=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#184=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#185=AXIS2_PLACEMENT_3D('',#182,#183,#184);\r\n#187=CARTESIAN_POINT('',(6.E0,0.E0,1.25E0));\r\n#188=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#189=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#190=AXIS2_PLACEMENT_3D('',#187,#188,#189);\r\n#192=CARTESIAN_POINT('',(6.E0,0.E0,1.25E0));\r\n#193=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#194=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#195=AXIS2_PLACEMENT_3D('',#192,#193,#194);\r\n#197=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#198=VECTOR('',#197,1.3E1);\r\n#199=CARTESIAN_POINT('',(5.5E0,0.E0,1.89375E1));\r\n#200=LINE('',#199,#198);\r\n#201=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#202=VECTOR('',#201,2.5625E0);\r\n#203=CARTESIAN_POINT('',(2.15E1,0.E0,2.45E1));\r\n#204=LINE('',#203,#202);\r\n#205=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#206=VECTOR('',#205,9.E0);\r\n#207=CARTESIAN_POINT('',(7.5E0,0.E0,2.95E1));\r\n#208=LINE('',#207,#206);\r\n#209=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#210=VECTOR('',#209,2.5625E0);\r\n#211=CARTESIAN_POINT('',(2.5E0,0.E0,2.19375E1));\r\n#212=LINE('',#211,#210);\r\n#213=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#214=VECTOR('',#213,8.125E-1);\r\n#215=CARTESIAN_POINT('',(2.15E1,0.E0,1.40625E1));\r\n#216=LINE('',#215,#214);\r\n#217=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#218=VECTOR('',#217,1.3E1);\r\n#219=CARTESIAN_POINT('',(1.85E1,0.E0,1.70625E1));\r\n#220=LINE('',#219,#218);\r\n#221=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#222=VECTOR('',#221,8.125E-1);\r\n#223=CARTESIAN_POINT('',(2.5E0,0.E0,1.325E1));\r\n#224=LINE('',#223,#222);\r\n#225=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#226=VECTOR('',#225,1.E0);\r\n#227=CARTESIAN_POINT('',(3.5E0,0.E0,1.225E1));\r\n#228=LINE('',#227,#226);\r\n#229=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#230=VECTOR('',#229,7.5E-1);\r\n#231=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1));\r\n#232=LINE('',#231,#230);\r\n#233=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#234=VECTOR('',#233,1.2E1);\r\n#235=CARTESIAN_POINT('',(6.E0,0.E0,1.E1));\r\n#236=LINE('',#235,#234);\r\n#237=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#238=VECTOR('',#237,7.5E-1);\r\n#239=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1));\r\n#240=LINE('',#239,#238);\r\n#241=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#242=VECTOR('',#241,1.E0);\r\n#243=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1));\r\n#244=LINE('',#243,#242);\r\n#245=CARTESIAN_POINT('',(6.E0,0.E0,9.E0));\r\n#246=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#247=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#248=AXIS2_PLACEMENT_3D('',#245,#246,#247);\r\n#250=CARTESIAN_POINT('',(6.E0,0.E0,9.E0));\r\n#251=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#252=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#253=AXIS2_PLACEMENT_3D('',#250,#251,#252);\r\n#255=CARTESIAN_POINT('',(1.2E1,0.E0,9.E0));\r\n#256=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#257=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#258=AXIS2_PLACEMENT_3D('',#255,#256,#257);\r\n#260=CARTESIAN_POINT('',(1.2E1,0.E0,9.E0));\r\n#261=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#262=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#263=AXIS2_PLACEMENT_3D('',#260,#261,#262);\r\n#265=CARTESIAN_POINT('',(1.8E1,0.E0,9.E0));\r\n#266=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#267=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#268=AXIS2_PLACEMENT_3D('',#265,#266,#267);\r\n#270=CARTESIAN_POINT('',(1.8E1,0.E0,9.E0));\r\n#271=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#272=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#273=AXIS2_PLACEMENT_3D('',#270,#271,#272);\r\n#275=CARTESIAN_POINT('',(6.E0,0.E0,1.8E1));\r\n#276=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#277=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#278=AXIS2_PLACEMENT_3D('',#275,#276,#277);\r\n#280=CARTESIAN_POINT('',(6.E0,0.E0,1.8E1));\r\n#281=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#282=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#283=AXIS2_PLACEMENT_3D('',#280,#281,#282);\r\n#285=CARTESIAN_POINT('',(1.2E1,0.E0,1.8E1));\r\n#286=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#287=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#288=AXIS2_PLACEMENT_3D('',#285,#286,#287);\r\n#290=CARTESIAN_POINT('',(1.2E1,0.E0,1.8E1));\r\n#291=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#292=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#293=AXIS2_PLACEMENT_3D('',#290,#291,#292);\r\n#295=CARTESIAN_POINT('',(1.8E1,0.E0,1.8E1));\r\n#296=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#297=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#298=AXIS2_PLACEMENT_3D('',#295,#296,#297);\r\n#300=CARTESIAN_POINT('',(1.8E1,0.E0,1.8E1));\r\n#301=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#302=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#303=AXIS2_PLACEMENT_3D('',#300,#301,#302);\r\n#305=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#306=VECTOR('',#305,3.E0);\r\n#307=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1));\r\n#308=LINE('',#307,#306);\r\n#309=CARTESIAN_POINT('',(1.05E1,0.E0,1.25E0));\r\n#310=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#311=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#312=AXIS2_PLACEMENT_3D('',#309,#310,#311);\r\n#314=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#315=VECTOR('',#314,3.E0);\r\n#316=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0));\r\n#317=LINE('',#316,#315);\r\n#318=CARTESIAN_POINT('',(7.5E0,0.E0,1.25E0));\r\n#319=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#320=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#321=AXIS2_PLACEMENT_3D('',#318,#319,#320);\r\n#323=CARTESIAN_POINT('',(1.61E0,0.E0,4.5E0));\r\n#324=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#325=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#326=AXIS2_PLACEMENT_3D('',#323,#324,#325);\r\n#328=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#329=VECTOR('',#328,4.263248410977E0);\r\n#330=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0));\r\n#331=LINE('',#330,#329);\r\n#332=CARTESIAN_POINT('',(4.553039342392E0,0.E0,1.645354088550E0));\r\n#333=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#334=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#335=AXIS2_PLACEMENT_3D('',#332,#333,#334);\r\n#337=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0));\r\n#338=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#339=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#340=AXIS2_PLACEMENT_3D('',#337,#338,#339);\r\n#342=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#343=VECTOR('',#342,3.15E-1);\r\n#344=CARTESIAN_POINT('',(6.9E-1,0.E0,7.815E0));\r\n#345=LINE('',#344,#343);\r\n#346=CARTESIAN_POINT('',(1.25125E0,0.E0,7.5E0));\r\n#347=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#348=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#349=AXIS2_PLACEMENT_3D('',#346,#347,#348);\r\n#351=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#352=VECTOR('',#351,3.15E-1);\r\n#353=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0));\r\n#354=LINE('',#353,#352);\r\n#355=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#356=VECTOR('',#355,7.5E-1);\r\n#357=CARTESIAN_POINT('',(2.6875E0,0.E0,8.69E0));\r\n#358=LINE('',#357,#356);\r\n#359=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#360=VECTOR('',#359,8.1E-1);\r\n#361=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0));\r\n#362=LINE('',#361,#360);\r\n#363=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#364=VECTOR('',#363,3.875E0);\r\n#365=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1));\r\n#366=LINE('',#365,#364);\r\n#367=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#368=VECTOR('',#367,8.1E-1);\r\n#369=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1));\r\n#370=LINE('',#369,#368);\r\n#371=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#372=VECTOR('',#371,2.525E-1);\r\n#373=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0));\r\n#374=LINE('',#373,#372);\r\n#375=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#376=VECTOR('',#375,3.E0);\r\n#377=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1));\r\n#378=LINE('',#377,#376);\r\n#379=CARTESIAN_POINT('',(1.25E0,0.E0,1.35E1));\r\n#380=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#381=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#382=AXIS2_PLACEMENT_3D('',#379,#380,#381);\r\n#384=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#385=VECTOR('',#384,3.E0);\r\n#386=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1));\r\n#387=LINE('',#386,#385);\r\n#388=CARTESIAN_POINT('',(1.25E0,0.E0,1.65E1));\r\n#389=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#390=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#391=AXIS2_PLACEMENT_3D('',#388,#389,#390);\r\n#393=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#394=VECTOR('',#393,3.E0);\r\n#395=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1));\r\n#396=LINE('',#395,#394);\r\n#397=CARTESIAN_POINT('',(1.25E0,0.E0,1.95E1));\r\n#398=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#399=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#400=AXIS2_PLACEMENT_3D('',#397,#398,#399);\r\n#402=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#403=VECTOR('',#402,3.E0);\r\n#404=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1));\r\n#405=LINE('',#404,#403);\r\n#406=CARTESIAN_POINT('',(1.25E0,0.E0,2.25E1));\r\n#407=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#408=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#409=AXIS2_PLACEMENT_3D('',#406,#407,#408);\r\n#411=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#412=VECTOR('',#411,3.E0);\r\n#413=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0));\r\n#414=LINE('',#413,#412);\r\n#415=CARTESIAN_POINT('',(1.05E1,0.E0,9.E0));\r\n#416=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#417=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#418=AXIS2_PLACEMENT_3D('',#415,#416,#417);\r\n#420=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#421=VECTOR('',#420,3.E0);\r\n#422=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0));\r\n#423=LINE('',#422,#421);\r\n#424=CARTESIAN_POINT('',(7.5E0,0.E0,9.E0));\r\n#425=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#426=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#427=AXIS2_PLACEMENT_3D('',#424,#425,#426);\r\n#429=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#430=VECTOR('',#429,3.E0);\r\n#431=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1));\r\n#432=LINE('',#431,#430);\r\n#433=CARTESIAN_POINT('',(1.05E1,0.E0,1.8E1));\r\n#434=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#435=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#436=AXIS2_PLACEMENT_3D('',#433,#434,#435);\r\n#438=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#439=VECTOR('',#438,3.E0);\r\n#440=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1));\r\n#441=LINE('',#440,#439);\r\n#442=CARTESIAN_POINT('',(7.5E0,0.E0,1.8E1));\r\n#443=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#444=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#445=AXIS2_PLACEMENT_3D('',#442,#443,#444);\r\n#447=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#448=VECTOR('',#447,3.E0);\r\n#449=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1));\r\n#450=LINE('',#449,#448);\r\n#451=CARTESIAN_POINT('',(7.5E0,0.E0,3.075E1));\r\n#452=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#453=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#454=AXIS2_PLACEMENT_3D('',#451,#452,#453);\r\n#456=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#457=VECTOR('',#456,3.E0);\r\n#458=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1));\r\n#459=LINE('',#458,#457);\r\n#460=CARTESIAN_POINT('',(1.05E1,0.E0,3.075E1));\r\n#461=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#462=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#463=AXIS2_PLACEMENT_3D('',#460,#461,#462);\r\n#465=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#466=VECTOR('',#465,3.E0);\r\n#467=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1));\r\n#468=LINE('',#467,#466);\r\n#469=CARTESIAN_POINT('',(1.65E1,0.E0,1.25E0));\r\n#470=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#471=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#472=AXIS2_PLACEMENT_3D('',#469,#470,#471);\r\n#474=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#475=VECTOR('',#474,3.E0);\r\n#476=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0));\r\n#477=LINE('',#476,#475);\r\n#478=CARTESIAN_POINT('',(1.35E1,0.E0,1.25E0));\r\n#479=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#480=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#481=AXIS2_PLACEMENT_3D('',#478,#479,#480);\r\n#483=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#484=VECTOR('',#483,3.E0);\r\n#485=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1));\r\n#486=LINE('',#485,#484);\r\n#487=CARTESIAN_POINT('',(2.275E1,0.E0,1.65E1));\r\n#488=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#489=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#490=AXIS2_PLACEMENT_3D('',#487,#488,#489);\r\n#492=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#493=VECTOR('',#492,3.E0);\r\n#494=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1));\r\n#495=LINE('',#494,#493);\r\n#496=CARTESIAN_POINT('',(2.275E1,0.E0,1.35E1));\r\n#497=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#498=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#499=AXIS2_PLACEMENT_3D('',#496,#497,#498);\r\n#501=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#502=VECTOR('',#501,3.E0);\r\n#503=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1));\r\n#504=LINE('',#503,#502);\r\n#505=CARTESIAN_POINT('',(2.275E1,0.E0,2.25E1));\r\n#506=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#507=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#508=AXIS2_PLACEMENT_3D('',#505,#506,#507);\r\n#510=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#511=VECTOR('',#510,3.E0);\r\n#512=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1));\r\n#513=LINE('',#512,#511);\r\n#514=CARTESIAN_POINT('',(2.275E1,0.E0,1.95E1));\r\n#515=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#516=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#517=AXIS2_PLACEMENT_3D('',#514,#515,#516);\r\n#519=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#520=VECTOR('',#519,3.E0);\r\n#521=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0));\r\n#522=LINE('',#521,#520);\r\n#523=CARTESIAN_POINT('',(1.65E1,0.E0,9.E0));\r\n#524=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#525=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#526=AXIS2_PLACEMENT_3D('',#523,#524,#525);\r\n#528=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#529=VECTOR('',#528,3.E0);\r\n#530=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0));\r\n#531=LINE('',#530,#529);\r\n#532=CARTESIAN_POINT('',(1.35E1,0.E0,9.E0));\r\n#533=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#534=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#535=AXIS2_PLACEMENT_3D('',#532,#533,#534);\r\n#537=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#538=VECTOR('',#537,3.E0);\r\n#539=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1));\r\n#540=LINE('',#539,#538);\r\n#541=CARTESIAN_POINT('',(1.65E1,0.E0,1.8E1));\r\n#542=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#543=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#544=AXIS2_PLACEMENT_3D('',#541,#542,#543);\r\n#546=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#547=VECTOR('',#546,3.E0);\r\n#548=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1));\r\n#549=LINE('',#548,#547);\r\n#550=CARTESIAN_POINT('',(1.35E1,0.E0,1.8E1));\r\n#551=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#552=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#553=AXIS2_PLACEMENT_3D('',#550,#551,#552);\r\n#555=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#556=VECTOR('',#555,3.E0);\r\n#557=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1));\r\n#558=LINE('',#557,#556);\r\n#559=CARTESIAN_POINT('',(1.35E1,0.E0,3.075E1));\r\n#560=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#561=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#562=AXIS2_PLACEMENT_3D('',#559,#560,#561);\r\n#564=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#565=VECTOR('',#564,3.E0);\r\n#566=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1));\r\n#567=LINE('',#566,#565);\r\n#568=CARTESIAN_POINT('',(1.65E1,0.E0,3.075E1));\r\n#569=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#570=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#571=AXIS2_PLACEMENT_3D('',#568,#569,#570);\r\n#573=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#574=VECTOR('',#573,3.1E-1);\r\n#575=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0));\r\n#576=LINE('',#575,#574);\r\n#577=CARTESIAN_POINT('',(2.274875E1,0.E0,7.5E0));\r\n#578=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#579=DIRECTION('',(1.E0,0.E0,-3.956251312695E-14));\r\n#580=AXIS2_PLACEMENT_3D('',#577,#578,#579);\r\n#582=DIRECTION('',(2.292073341162E-14,0.E0,-1.E0));\r\n#583=VECTOR('',#582,3.1E-1);\r\n#584=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0));\r\n#585=LINE('',#584,#583);\r\n#586=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#587=VECTOR('',#586,2.425E-1);\r\n#588=CARTESIAN_POINT('',(2.44325E1,0.E0,8.69E0));\r\n#589=LINE('',#588,#587);\r\n#590=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#591=VECTOR('',#590,8.E-1);\r\n#592=CARTESIAN_POINT('',(2.53125E1,0.E0,1.037E1));\r\n#593=LINE('',#592,#591);\r\n#594=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#595=VECTOR('',#594,3.865E0);\r\n#596=CARTESIAN_POINT('',(2.05675E1,0.E0,1.125E1));\r\n#597=LINE('',#596,#595);\r\n#598=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#599=VECTOR('',#598,8.E-1);\r\n#600=CARTESIAN_POINT('',(1.96875E1,0.E0,9.57E0));\r\n#601=LINE('',#600,#599);\r\n#602=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#603=VECTOR('',#602,7.4E-1);\r\n#604=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0));\r\n#605=LINE('',#604,#603);\r\n#606=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#607=VECTOR('',#606,4.263248410977E0);\r\n#608=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0));\r\n#609=LINE('',#608,#607);\r\n#610=CARTESIAN_POINT('',(2.239E1,0.E0,4.5E0));\r\n#611=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#612=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#613=AXIS2_PLACEMENT_3D('',#610,#611,#612);\r\n#615=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0));\r\n#616=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#617=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#618=AXIS2_PLACEMENT_3D('',#615,#616,#617);\r\n#620=CARTESIAN_POINT('',(1.944696065761E1,0.E0,1.645354088550E0));\r\n#621=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#622=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811866E-1));\r\n#623=AXIS2_PLACEMENT_3D('',#620,#621,#622);\r\n#625=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#626=VECTOR('',#625,4.263248410977E0);\r\n#627=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1));\r\n#628=LINE('',#627,#626);\r\n#629=CARTESIAN_POINT('',(1.61E0,0.E0,2.75E1));\r\n#630=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#631=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#632=AXIS2_PLACEMENT_3D('',#629,#630,#631);\r\n#634=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1));\r\n#635=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#636=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#637=AXIS2_PLACEMENT_3D('',#634,#635,#636);\r\n#639=CARTESIAN_POINT('',(4.553039342392E0,0.E0,3.035464591145E1));\r\n#640=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#641=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#642=AXIS2_PLACEMENT_3D('',#639,#640,#641);\r\n#644=CARTESIAN_POINT('',(2.239E1,0.E0,2.75E1));\r\n#645=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#646=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#647=AXIS2_PLACEMENT_3D('',#644,#645,#646);\r\n#649=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#650=VECTOR('',#649,4.263248410977E0);\r\n#651=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1));\r\n#652=LINE('',#651,#650);\r\n#653=CARTESIAN_POINT('',(1.944696065761E1,0.E0,3.035464591145E1));\r\n#654=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#655=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811866E-1));\r\n#656=AXIS2_PLACEMENT_3D('',#653,#654,#655);\r\n#658=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1));\r\n#659=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#660=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#661=AXIS2_PLACEMENT_3D('',#658,#659,#660);\r\n#663=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0));\r\n#664=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#665=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#666=AXIS2_PLACEMENT_3D('',#663,#664,#665);\r\n#668=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0));\r\n#669=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#670=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#671=AXIS2_PLACEMENT_3D('',#668,#669,#670);\r\n#673=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0));\r\n#674=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#675=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#676=AXIS2_PLACEMENT_3D('',#673,#674,#675);\r\n#678=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0));\r\n#679=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#680=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#681=AXIS2_PLACEMENT_3D('',#678,#679,#680);\r\n#683=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0));\r\n#684=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#685=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#686=AXIS2_PLACEMENT_3D('',#683,#684,#685);\r\n#688=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0));\r\n#689=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#690=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#691=AXIS2_PLACEMENT_3D('',#688,#689,#690);\r\n#693=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0));\r\n#694=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#695=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#696=AXIS2_PLACEMENT_3D('',#693,#694,#695);\r\n#698=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0));\r\n#699=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#700=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#701=AXIS2_PLACEMENT_3D('',#698,#699,#700);\r\n#703=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0));\r\n#704=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#705=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#706=AXIS2_PLACEMENT_3D('',#703,#704,#705);\r\n#708=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0));\r\n#709=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#710=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#711=AXIS2_PLACEMENT_3D('',#708,#709,#710);\r\n#713=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0));\r\n#714=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#715=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#716=AXIS2_PLACEMENT_3D('',#713,#714,#715);\r\n#718=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0));\r\n#719=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#720=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#721=AXIS2_PLACEMENT_3D('',#718,#719,#720);\r\n#723=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0));\r\n#724=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#725=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#726=AXIS2_PLACEMENT_3D('',#723,#724,#725);\r\n#728=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0));\r\n#729=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#730=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#731=AXIS2_PLACEMENT_3D('',#728,#729,#730);\r\n#733=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0));\r\n#734=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#735=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#736=AXIS2_PLACEMENT_3D('',#733,#734,#735);\r\n#738=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0));\r\n#739=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#740=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#741=AXIS2_PLACEMENT_3D('',#738,#739,#740);\r\n#743=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#744=VECTOR('',#743,1.029563014099E1);\r\n#745=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0));\r\n#746=LINE('',#745,#744);\r\n#747=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#748=VECTOR('',#747,2.E0);\r\n#749=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0));\r\n#750=LINE('',#749,#748);\r\n#751=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#752=VECTOR('',#751,2.E0);\r\n#753=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0));\r\n#754=LINE('',#753,#752);\r\n#755=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#756=VECTOR('',#755,1.029563014099E1);\r\n#757=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0));\r\n#758=LINE('',#757,#756);\r\n#759=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#760=VECTOR('',#759,3.895172754280E0);\r\n#761=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0));\r\n#762=LINE('',#761,#760);\r\n#763=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#764=VECTOR('',#763,6.863753427325E0);\r\n#765=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0));\r\n#766=LINE('',#765,#764);\r\n#767=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#768=VECTOR('',#767,5.618394209466E-1);\r\n#769=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0));\r\n#770=LINE('',#769,#768);\r\n#771=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#772=VECTOR('',#771,6.E0);\r\n#773=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0));\r\n#774=LINE('',#773,#772);\r\n#775=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#776=VECTOR('',#775,6.863753427325E0);\r\n#777=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.E0));\r\n#778=LINE('',#777,#776);\r\n#779=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#780=VECTOR('',#779,3.895172754280E0);\r\n#781=CARTESIAN_POINT('',(2.025E1,2.E0,8.E0));\r\n#782=LINE('',#781,#780);\r\n#783=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#784=VECTOR('',#783,6.E0);\r\n#785=CARTESIAN_POINT('',(1.95E1,8.75E0,8.E0));\r\n#786=LINE('',#785,#784);\r\n#787=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#788=VECTOR('',#787,5.618394209466E-1);\r\n#789=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.E0));\r\n#790=LINE('',#789,#788);\r\n#791=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#792=VECTOR('',#791,2.5E-1);\r\n#793=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.E0));\r\n#794=LINE('',#793,#792);\r\n#795=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#796=VECTOR('',#795,2.5E-1);\r\n#797=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.E0));\r\n#798=LINE('',#797,#796);\r\n#799=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0));\r\n#800=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#801=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#802=AXIS2_PLACEMENT_3D('',#799,#800,#801);\r\n#804=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0));\r\n#805=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#806=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#807=AXIS2_PLACEMENT_3D('',#804,#805,#806);\r\n#809=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#810=VECTOR('',#809,2.E0);\r\n#811=CARTESIAN_POINT('',(1.95875E1,1.05E1,8.E0));\r\n#812=LINE('',#811,#810);\r\n#813=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#814=VECTOR('',#813,2.E0);\r\n#815=CARTESIAN_POINT('',(1.99125E1,1.05E1,8.E0));\r\n#816=LINE('',#815,#814);\r\n#817=CARTESIAN_POINT('',(1.975E1,1.05E1,1.E1));\r\n#818=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#819=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#820=AXIS2_PLACEMENT_3D('',#817,#818,#819);\r\n#822=CARTESIAN_POINT('',(1.975E1,1.05E1,1.E1));\r\n#823=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#824=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#825=AXIS2_PLACEMENT_3D('',#822,#823,#824);\r\n#827=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#828=VECTOR('',#827,5.E0);\r\n#829=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1));\r\n#830=LINE('',#829,#828);\r\n#831=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#832=VECTOR('',#831,1.75E0);\r\n#833=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1));\r\n#834=LINE('',#833,#832);\r\n#835=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#836=VECTOR('',#835,5.E0);\r\n#837=CARTESIAN_POINT('',(2.2E1,1.5E0,1.E1));\r\n#838=LINE('',#837,#836);\r\n#839=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#840=VECTOR('',#839,1.E1);\r\n#841=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1));\r\n#842=LINE('',#841,#840);\r\n#843=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#844=VECTOR('',#843,2.E0);\r\n#845=CARTESIAN_POINT('',(1.9E1,1.15E1,1.E1));\r\n#846=LINE('',#845,#844);\r\n#847=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#848=VECTOR('',#847,1.029563014099E1);\r\n#849=CARTESIAN_POINT('',(2.1E1,1.15E1,1.E1));\r\n#850=LINE('',#849,#848);\r\n#851=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#852=VECTOR('',#851,1.E0);\r\n#853=CARTESIAN_POINT('',(2.6E1,2.5E0,1.E1));\r\n#854=LINE('',#853,#852);\r\n#855=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#856=VECTOR('',#855,1.972007605460E-1);\r\n#857=CARTESIAN_POINT('',(2.204720076055E1,7.E0,1.E1));\r\n#858=LINE('',#857,#856);\r\n#859=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#860=VECTOR('',#859,2.059126028197E0);\r\n#861=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,1.E1));\r\n#862=LINE('',#861,#860);\r\n#863=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#864=VECTOR('',#863,1.197200760546E0);\r\n#865=CARTESIAN_POINT('',(1.985E1,9.5E0,1.E1));\r\n#866=LINE('',#865,#864);\r\n#867=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#868=VECTOR('',#867,6.8E0);\r\n#869=CARTESIAN_POINT('',(1.95E1,2.35E0,1.E1));\r\n#870=LINE('',#869,#868);\r\n#871=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#872=VECTOR('',#871,1.3E0);\r\n#873=CARTESIAN_POINT('',(2.115E1,2.E0,1.E1));\r\n#874=LINE('',#873,#872);\r\n#875=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#876=VECTOR('',#875,4.3E0);\r\n#877=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1));\r\n#878=LINE('',#877,#876);\r\n#879=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#880=VECTOR('',#879,5.773502691896E0);\r\n#881=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1));\r\n#882=LINE('',#881,#880);\r\n#883=CARTESIAN_POINT('',(6.45E0,1.5E0,2.975E1));\r\n#884=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#885=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#886=AXIS2_PLACEMENT_3D('',#883,#884,#885);\r\n#888=CARTESIAN_POINT('',(6.45E0,1.5E0,2.975E1));\r\n#889=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#890=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#891=AXIS2_PLACEMENT_3D('',#888,#889,#890);\r\n#893=CARTESIAN_POINT('',(7.45E0,1.5E0,2.975E1));\r\n#894=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#895=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#896=AXIS2_PLACEMENT_3D('',#893,#894,#895);\r\n#898=CARTESIAN_POINT('',(7.45E0,1.5E0,2.975E1));\r\n#899=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#900=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#901=AXIS2_PLACEMENT_3D('',#898,#899,#900);\r\n#903=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#904=VECTOR('',#903,4.531373033403E0);\r\n#905=CARTESIAN_POINT('',(2.5E1,1.5E0,8.E0));\r\n#906=LINE('',#905,#904);\r\n#907=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#908=VECTOR('',#907,9.E0);\r\n#909=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0));\r\n#910=LINE('',#909,#908);\r\n#911=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#912=VECTOR('',#911,4.531373033403E0);\r\n#913=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0));\r\n#914=LINE('',#913,#912);\r\n#915=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#916=VECTOR('',#915,3.E0);\r\n#917=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0));\r\n#918=LINE('',#917,#916);\r\n#919=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#920=VECTOR('',#919,1.6E1);\r\n#921=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0));\r\n#922=LINE('',#921,#920);\r\n#923=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#924=VECTOR('',#923,3.E0);\r\n#925=CARTESIAN_POINT('',(2.4E1,1.5E0,7.E0));\r\n#926=LINE('',#925,#924);\r\n#927=CARTESIAN_POINT('',(1.755E1,1.5E0,2.975E1));\r\n#928=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#929=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#930=AXIS2_PLACEMENT_3D('',#927,#928,#929);\r\n#932=CARTESIAN_POINT('',(1.755E1,1.5E0,2.975E1));\r\n#933=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#934=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#935=AXIS2_PLACEMENT_3D('',#932,#933,#934);\r\n#937=CARTESIAN_POINT('',(1.655E1,1.5E0,2.975E1));\r\n#938=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#939=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#940=AXIS2_PLACEMENT_3D('',#937,#938,#939);\r\n#942=CARTESIAN_POINT('',(1.655E1,1.5E0,2.975E1));\r\n#943=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#944=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#945=AXIS2_PLACEMENT_3D('',#942,#943,#944);\r\n#947=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#948=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#949=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#950=AXIS2_PLACEMENT_3D('',#947,#948,#949);\r\n#952=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#953=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#954=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#955=AXIS2_PLACEMENT_3D('',#952,#953,#954);\r\n#957=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#958=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#959=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#960=AXIS2_PLACEMENT_3D('',#957,#958,#959);\r\n#962=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#963=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#964=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#965=AXIS2_PLACEMENT_3D('',#962,#963,#964);\r\n#967=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#968=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#969=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#970=AXIS2_PLACEMENT_3D('',#967,#968,#969);\r\n#972=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#973=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#974=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#975=AXIS2_PLACEMENT_3D('',#972,#973,#974);\r\n#977=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#978=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#979=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#980=AXIS2_PLACEMENT_3D('',#977,#978,#979);\r\n#982=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#983=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#984=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#985=AXIS2_PLACEMENT_3D('',#982,#983,#984);\r\n#987=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#988=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#989=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#990=AXIS2_PLACEMENT_3D('',#987,#988,#989);\r\n#992=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#993=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#994=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#995=AXIS2_PLACEMENT_3D('',#992,#993,#994);\r\n#997=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#998=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#999=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1000=AXIS2_PLACEMENT_3D('',#997,#998,#999);\r\n#1002=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#1003=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1004=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1005=AXIS2_PLACEMENT_3D('',#1002,#1003,#1004);\r\n#1007=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#1008=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1009=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1010=AXIS2_PLACEMENT_3D('',#1007,#1008,#1009);\r\n#1012=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#1013=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1014=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1015=AXIS2_PLACEMENT_3D('',#1012,#1013,#1014);\r\n#1017=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#1018=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1019=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1020=AXIS2_PLACEMENT_3D('',#1017,#1018,#1019);\r\n#1022=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#1023=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1024=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1025=AXIS2_PLACEMENT_3D('',#1022,#1023,#1024);\r\n#1027=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#1028=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1029=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1030=AXIS2_PLACEMENT_3D('',#1027,#1028,#1029);\r\n#1032=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#1033=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1034=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1035=AXIS2_PLACEMENT_3D('',#1032,#1033,#1034);\r\n#1037=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#1038=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1039=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1040=AXIS2_PLACEMENT_3D('',#1037,#1038,#1039);\r\n#1042=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#1043=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1044=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1045=AXIS2_PLACEMENT_3D('',#1042,#1043,#1044);\r\n#1047=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#1048=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1049=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1050=AXIS2_PLACEMENT_3D('',#1047,#1048,#1049);\r\n#1052=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#1053=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1054=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1055=AXIS2_PLACEMENT_3D('',#1052,#1053,#1054);\r\n#1057=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#1058=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1059=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1060=AXIS2_PLACEMENT_3D('',#1057,#1058,#1059);\r\n#1062=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#1063=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1064=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1065=AXIS2_PLACEMENT_3D('',#1062,#1063,#1064);\r\n#1067=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1068=VECTOR('',#1067,2.5625E0);\r\n#1069=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1));\r\n#1070=LINE('',#1069,#1068);\r\n#1071=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1072=VECTOR('',#1071,1.3E1);\r\n#1073=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1));\r\n#1074=LINE('',#1073,#1072);\r\n#1075=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1076=VECTOR('',#1075,2.5625E0);\r\n#1077=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1));\r\n#1078=LINE('',#1077,#1076);\r\n#1079=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1080=VECTOR('',#1079,9.E0);\r\n#1081=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1));\r\n#1082=LINE('',#1081,#1080);\r\n#1083=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1084=VECTOR('',#1083,1.3E1);\r\n#1085=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1));\r\n#1086=LINE('',#1085,#1084);\r\n#1087=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1088=VECTOR('',#1087,8.125E-1);\r\n#1089=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1));\r\n#1090=LINE('',#1089,#1088);\r\n#1091=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1092=VECTOR('',#1091,1.E0);\r\n#1093=CARTESIAN_POINT('',(2.05E1,1.5E0,1.225E1));\r\n#1094=LINE('',#1093,#1092);\r\n#1095=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1096=VECTOR('',#1095,7.5E-1);\r\n#1097=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1));\r\n#1098=LINE('',#1097,#1096);\r\n#1099=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1100=VECTOR('',#1099,7.5E-1);\r\n#1101=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1));\r\n#1102=LINE('',#1101,#1100);\r\n#1103=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1104=VECTOR('',#1103,1.E0);\r\n#1105=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1));\r\n#1106=LINE('',#1105,#1104);\r\n#1107=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1108=VECTOR('',#1107,8.125E-1);\r\n#1109=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1));\r\n#1110=LINE('',#1109,#1108);\r\n#1111=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#1112=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1113=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1114=AXIS2_PLACEMENT_3D('',#1111,#1112,#1113);\r\n#1116=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#1117=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1118=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1119=AXIS2_PLACEMENT_3D('',#1116,#1117,#1118);\r\n#1121=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#1122=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1123=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1124=AXIS2_PLACEMENT_3D('',#1121,#1122,#1123);\r\n#1126=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#1127=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1128=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1129=AXIS2_PLACEMENT_3D('',#1126,#1127,#1128);\r\n#1131=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#1132=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1133=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1134=AXIS2_PLACEMENT_3D('',#1131,#1132,#1133);\r\n#1136=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#1137=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1138=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1139=AXIS2_PLACEMENT_3D('',#1136,#1137,#1138);\r\n#1141=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#1142=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1143=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1144=AXIS2_PLACEMENT_3D('',#1141,#1142,#1143);\r\n#1146=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#1147=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1148=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1149=AXIS2_PLACEMENT_3D('',#1146,#1147,#1148);\r\n#1151=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#1152=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1153=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1154=AXIS2_PLACEMENT_3D('',#1151,#1152,#1153);\r\n#1156=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#1157=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1158=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1159=AXIS2_PLACEMENT_3D('',#1156,#1157,#1158);\r\n#1161=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#1162=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1163=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1164=AXIS2_PLACEMENT_3D('',#1161,#1162,#1163);\r\n#1166=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#1167=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1168=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1169=AXIS2_PLACEMENT_3D('',#1166,#1167,#1168);\r\n#1171=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1172=VECTOR('',#1171,2.886751345948E0);\r\n#1173=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1));\r\n#1174=LINE('',#1173,#1172);\r\n#1175=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1176=VECTOR('',#1175,2.25E0);\r\n#1177=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1));\r\n#1178=LINE('',#1177,#1176);\r\n#1179=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1180=VECTOR('',#1179,1.75E0);\r\n#1181=CARTESIAN_POINT('',(2.6E1,1.5E0,1.E1));\r\n#1182=LINE('',#1181,#1180);\r\n#1183=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1184=VECTOR('',#1183,5.E-1);\r\n#1185=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1));\r\n#1186=LINE('',#1185,#1184);\r\n#1187=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1188=VECTOR('',#1187,1.475E1);\r\n#1189=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1));\r\n#1190=LINE('',#1189,#1188);\r\n#1191=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1192=VECTOR('',#1191,1.6E1);\r\n#1193=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1));\r\n#1194=LINE('',#1193,#1192);\r\n#1195=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1196=VECTOR('',#1195,1.475E1);\r\n#1197=CARTESIAN_POINT('',(0.E0,1.5E0,1.325E1));\r\n#1198=LINE('',#1197,#1196);\r\n#1199=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1200=VECTOR('',#1199,5.E-1);\r\n#1201=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1));\r\n#1202=LINE('',#1201,#1200);\r\n#1203=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1204=VECTOR('',#1203,1.75E0);\r\n#1205=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1));\r\n#1206=LINE('',#1205,#1204);\r\n#1207=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1208=VECTOR('',#1207,2.25E0);\r\n#1209=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1));\r\n#1210=LINE('',#1209,#1208);\r\n#1211=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1212=VECTOR('',#1211,2.886751345948E0);\r\n#1213=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1));\r\n#1214=LINE('',#1213,#1212);\r\n#1215=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1216=VECTOR('',#1215,1.75E0);\r\n#1217=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1));\r\n#1218=LINE('',#1217,#1216);\r\n#1219=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1220=VECTOR('',#1219,2.886751345948E0);\r\n#1221=CARTESIAN_POINT('',(2.E0,1.5E0,1.288675134595E1));\r\n#1222=LINE('',#1221,#1220);\r\n#1223=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1224=VECTOR('',#1223,3.E0);\r\n#1225=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1));\r\n#1226=LINE('',#1225,#1224);\r\n#1227=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1228=VECTOR('',#1227,1.4E1);\r\n#1229=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0));\r\n#1230=LINE('',#1229,#1228);\r\n#1231=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1232=VECTOR('',#1231,3.E0);\r\n#1233=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1));\r\n#1234=LINE('',#1233,#1232);\r\n#1235=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1236=VECTOR('',#1235,2.886751345948E0);\r\n#1237=CARTESIAN_POINT('',(2.2E1,1.5E0,1.288675134595E1));\r\n#1238=LINE('',#1237,#1236);\r\n#1239=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1240=VECTOR('',#1239,1.75E0);\r\n#1241=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1));\r\n#1242=LINE('',#1241,#1240);\r\n#1243=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1244=VECTOR('',#1243,2.5E-1);\r\n#1245=CARTESIAN_POINT('',(6.35E0,1.25E0,2.975E1));\r\n#1246=LINE('',#1245,#1244);\r\n#1247=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1248=VECTOR('',#1247,2.5E-1);\r\n#1249=CARTESIAN_POINT('',(6.55E0,1.25E0,2.975E1));\r\n#1250=LINE('',#1249,#1248);\r\n#1251=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0));\r\n#1252=VECTOR('',#1251,1.154700538379E-1);\r\n#1253=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1));\r\n#1254=LINE('',#1253,#1252);\r\n#1255=CARTESIAN_POINT('',(6.45E0,1.25E0,2.975E1));\r\n#1256=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1257=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1258=AXIS2_PLACEMENT_3D('',#1255,#1256,#1257);\r\n#1260=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0));\r\n#1261=VECTOR('',#1260,1.154700538379E-1);\r\n#1262=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1));\r\n#1263=LINE('',#1262,#1261);\r\n#1264=CARTESIAN_POINT('',(6.45E0,1.25E0,2.975E1));\r\n#1265=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1266=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1267=AXIS2_PLACEMENT_3D('',#1264,#1265,#1266);\r\n#1269=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1270=VECTOR('',#1269,2.5E-1);\r\n#1271=CARTESIAN_POINT('',(7.35E0,1.25E0,2.975E1));\r\n#1272=LINE('',#1271,#1270);\r\n#1273=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1274=VECTOR('',#1273,2.5E-1);\r\n#1275=CARTESIAN_POINT('',(7.55E0,1.25E0,2.975E1));\r\n#1276=LINE('',#1275,#1274);\r\n#1277=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0));\r\n#1278=VECTOR('',#1277,1.154700538379E-1);\r\n#1279=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1));\r\n#1280=LINE('',#1279,#1278);\r\n#1281=CARTESIAN_POINT('',(7.45E0,1.25E0,2.975E1));\r\n#1282=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1283=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1284=AXIS2_PLACEMENT_3D('',#1281,#1282,#1283);\r\n#1286=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0));\r\n#1287=VECTOR('',#1286,1.154700538379E-1);\r\n#1288=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1));\r\n#1289=LINE('',#1288,#1287);\r\n#1290=CARTESIAN_POINT('',(7.45E0,1.25E0,2.975E1));\r\n#1291=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1292=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1293=AXIS2_PLACEMENT_3D('',#1290,#1291,#1292);\r\n#1295=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1296=VECTOR('',#1295,1.5E0);\r\n#1297=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0));\r\n#1298=LINE('',#1297,#1296);\r\n#1299=CARTESIAN_POINT('',(2.046862696660E1,0.E0,7.E0));\r\n#1300=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1301=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1302=AXIS2_PLACEMENT_3D('',#1299,#1300,#1301);\r\n#1304=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1305=VECTOR('',#1304,1.5E0);\r\n#1306=CARTESIAN_POINT('',(2.146078370825E1,0.E0,6.875E0));\r\n#1307=LINE('',#1306,#1305);\r\n#1308=CARTESIAN_POINT('',(2.046862696660E1,1.5E0,7.E0));\r\n#1309=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1310=DIRECTION('',(9.921567416492E-1,0.E0,-1.25E-1));\r\n#1311=AXIS2_PLACEMENT_3D('',#1308,#1309,#1310);\r\n#1313=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0));\r\n#1314=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1315=DIRECTION('',(9.921567416492E-1,0.E0,-1.25E-1));\r\n#1316=AXIS2_PLACEMENT_3D('',#1313,#1314,#1315);\r\n#1318=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1319=VECTOR('',#1318,1.5E0);\r\n#1320=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0));\r\n#1321=LINE('',#1320,#1319);\r\n#1322=CARTESIAN_POINT('',(1.65E1,1.5E0,7.5E0));\r\n#1323=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1324=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1325=AXIS2_PLACEMENT_3D('',#1322,#1323,#1324);\r\n#1327=CARTESIAN_POINT('',(7.5E0,1.5E0,7.5E0));\r\n#1328=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1329=DIRECTION('',(-9.921567416492E-1,0.E0,-1.25E-1));\r\n#1330=AXIS2_PLACEMENT_3D('',#1327,#1328,#1329);\r\n#1332=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1333=VECTOR('',#1332,1.5E0);\r\n#1334=CARTESIAN_POINT('',(7.5E0,1.5E0,2.5E0));\r\n#1335=LINE('',#1334,#1333);\r\n#1336=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0));\r\n#1337=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1338=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1339=AXIS2_PLACEMENT_3D('',#1336,#1337,#1338);\r\n#1341=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1342=VECTOR('',#1341,1.5E0);\r\n#1343=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0));\r\n#1344=LINE('',#1343,#1342);\r\n#1345=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,7.E0));\r\n#1346=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1347=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1348=AXIS2_PLACEMENT_3D('',#1345,#1346,#1347);\r\n#1350=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1351=VECTOR('',#1350,1.5E0);\r\n#1352=CARTESIAN_POINT('',(2.539216291754E0,1.5E0,6.875E0));\r\n#1353=LINE('',#1352,#1351);\r\n#1354=CARTESIAN_POINT('',(3.531373033403E0,0.E0,7.E0));\r\n#1355=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1356=DIRECTION('',(-9.921567416492E-1,0.E0,-1.25E-1));\r\n#1357=AXIS2_PLACEMENT_3D('',#1354,#1355,#1356);\r\n#1359=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1360=VECTOR('',#1359,1.5E0);\r\n#1361=CARTESIAN_POINT('',(0.E0,1.5E0,7.E0));\r\n#1362=LINE('',#1361,#1360);\r\n#1363=CARTESIAN_POINT('',(-1.E0,1.5E0,7.E0));\r\n#1364=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1365=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1366=AXIS2_PLACEMENT_3D('',#1363,#1364,#1365);\r\n#1368=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1369=VECTOR('',#1368,1.5E0);\r\n#1370=CARTESIAN_POINT('',(-1.E0,1.5E0,8.E0));\r\n#1371=LINE('',#1370,#1369);\r\n#1372=CARTESIAN_POINT('',(-1.E0,0.E0,7.E0));\r\n#1373=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1374=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1375=AXIS2_PLACEMENT_3D('',#1372,#1373,#1374);\r\n#1377=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1378=VECTOR('',#1377,1.5E0);\r\n#1379=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1));\r\n#1380=LINE('',#1379,#1378);\r\n#1381=CARTESIAN_POINT('',(-1.E0,0.E0,1.325E1));\r\n#1382=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1383=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1384=AXIS2_PLACEMENT_3D('',#1381,#1382,#1383);\r\n#1386=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1387=VECTOR('',#1386,1.5E0);\r\n#1388=CARTESIAN_POINT('',(-1.E0,0.E0,1.225E1));\r\n#1389=LINE('',#1388,#1387);\r\n#1390=CARTESIAN_POINT('',(-1.E0,1.5E0,1.325E1));\r\n#1391=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1392=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1393=AXIS2_PLACEMENT_3D('',#1390,#1391,#1392);\r\n#1395=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1396=VECTOR('',#1395,1.5E0);\r\n#1397=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1));\r\n#1398=LINE('',#1397,#1396);\r\n#1399=CARTESIAN_POINT('',(3.5E0,1.5E0,1.325E1));\r\n#1400=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1401=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1402=AXIS2_PLACEMENT_3D('',#1399,#1400,#1401);\r\n#1404=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1405=VECTOR('',#1404,1.5E0);\r\n#1406=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1));\r\n#1407=LINE('',#1406,#1405);\r\n#1408=CARTESIAN_POINT('',(3.5E0,0.E0,1.325E1));\r\n#1409=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1410=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1411=AXIS2_PLACEMENT_3D('',#1408,#1409,#1410);\r\n#1413=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1414=VECTOR('',#1413,1.5E0);\r\n#1415=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1));\r\n#1416=LINE('',#1415,#1414);\r\n#1417=CARTESIAN_POINT('',(5.5E0,1.5E0,2.19375E1));\r\n#1418=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1419=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1420=AXIS2_PLACEMENT_3D('',#1417,#1418,#1419);\r\n#1422=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1423=VECTOR('',#1422,1.5E0);\r\n#1424=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1));\r\n#1425=LINE('',#1424,#1423);\r\n#1426=CARTESIAN_POINT('',(5.5E0,0.E0,2.19375E1));\r\n#1427=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1428=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1429=AXIS2_PLACEMENT_3D('',#1426,#1427,#1428);\r\n#1431=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1432=VECTOR('',#1431,1.5E0);\r\n#1433=CARTESIAN_POINT('',(2.15E1,0.E0,2.19375E1));\r\n#1434=LINE('',#1433,#1432);\r\n#1435=CARTESIAN_POINT('',(1.85E1,0.E0,2.19375E1));\r\n#1436=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1437=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1438=AXIS2_PLACEMENT_3D('',#1435,#1436,#1437);\r\n#1440=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1441=VECTOR('',#1440,1.5E0);\r\n#1442=CARTESIAN_POINT('',(1.85E1,0.E0,1.89375E1));\r\n#1443=LINE('',#1442,#1441);\r\n#1444=CARTESIAN_POINT('',(1.85E1,1.5E0,2.19375E1));\r\n#1445=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1446=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1447=AXIS2_PLACEMENT_3D('',#1444,#1445,#1446);\r\n#1449=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1450=VECTOR('',#1449,1.5E0);\r\n#1451=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1));\r\n#1452=LINE('',#1451,#1450);\r\n#1453=CARTESIAN_POINT('',(1.65E1,1.5E0,2.45E1));\r\n#1454=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1455=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1456=AXIS2_PLACEMENT_3D('',#1453,#1454,#1455);\r\n#1458=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1459=VECTOR('',#1458,1.5E0);\r\n#1460=CARTESIAN_POINT('',(1.65E1,1.5E0,2.95E1));\r\n#1461=LINE('',#1460,#1459);\r\n#1462=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1));\r\n#1463=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1464=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1465=AXIS2_PLACEMENT_3D('',#1462,#1463,#1464);\r\n#1467=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1468=VECTOR('',#1467,1.5E0);\r\n#1469=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1));\r\n#1470=LINE('',#1469,#1468);\r\n#1471=CARTESIAN_POINT('',(7.5E0,1.5E0,2.45E1));\r\n#1472=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1473=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1474=AXIS2_PLACEMENT_3D('',#1471,#1472,#1473);\r\n#1476=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1477=VECTOR('',#1476,1.5E0);\r\n#1478=CARTESIAN_POINT('',(2.5E0,1.5E0,2.45E1));\r\n#1479=LINE('',#1478,#1477);\r\n#1480=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1));\r\n#1481=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1482=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1483=AXIS2_PLACEMENT_3D('',#1480,#1481,#1482);\r\n#1485=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1486=VECTOR('',#1485,1.5E0);\r\n#1487=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1));\r\n#1488=LINE('',#1487,#1486);\r\n#1489=CARTESIAN_POINT('',(1.85E1,1.5E0,1.40625E1));\r\n#1490=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1491=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1492=AXIS2_PLACEMENT_3D('',#1489,#1490,#1491);\r\n#1494=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1495=VECTOR('',#1494,1.5E0);\r\n#1496=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1));\r\n#1497=LINE('',#1496,#1495);\r\n#1498=CARTESIAN_POINT('',(1.85E1,0.E0,1.40625E1));\r\n#1499=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1500=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1501=AXIS2_PLACEMENT_3D('',#1498,#1499,#1500);\r\n#1503=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1504=VECTOR('',#1503,1.5E0);\r\n#1505=CARTESIAN_POINT('',(2.5E0,0.E0,1.40625E1));\r\n#1506=LINE('',#1505,#1504);\r\n#1507=CARTESIAN_POINT('',(5.5E0,0.E0,1.40625E1));\r\n#1508=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1509=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1510=AXIS2_PLACEMENT_3D('',#1507,#1508,#1509);\r\n#1512=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1513=VECTOR('',#1512,1.5E0);\r\n#1514=CARTESIAN_POINT('',(5.5E0,0.E0,1.70625E1));\r\n#1515=LINE('',#1514,#1513);\r\n#1516=CARTESIAN_POINT('',(5.5E0,1.5E0,1.40625E1));\r\n#1517=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1518=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1519=AXIS2_PLACEMENT_3D('',#1516,#1517,#1518);\r\n#1521=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1522=VECTOR('',#1521,1.5E0);\r\n#1523=CARTESIAN_POINT('',(2.15E1,0.E0,1.325E1));\r\n#1524=LINE('',#1523,#1522);\r\n#1525=CARTESIAN_POINT('',(2.05E1,0.E0,1.325E1));\r\n#1526=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1527=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1528=AXIS2_PLACEMENT_3D('',#1525,#1526,#1527);\r\n#1530=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1531=VECTOR('',#1530,1.5E0);\r\n#1532=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1));\r\n#1533=LINE('',#1532,#1531);\r\n#1534=CARTESIAN_POINT('',(2.05E1,1.5E0,1.325E1));\r\n#1535=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1536=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1537=AXIS2_PLACEMENT_3D('',#1534,#1535,#1536);\r\n#1539=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1540=VECTOR('',#1539,1.5E0);\r\n#1541=CARTESIAN_POINT('',(2.4E1,1.5E0,1.325E1));\r\n#1542=LINE('',#1541,#1540);\r\n#1543=CARTESIAN_POINT('',(2.5E1,1.5E0,1.325E1));\r\n#1544=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1545=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1546=AXIS2_PLACEMENT_3D('',#1543,#1544,#1545);\r\n#1548=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1549=VECTOR('',#1548,1.5E0);\r\n#1550=CARTESIAN_POINT('',(2.5E1,1.5E0,1.225E1));\r\n#1551=LINE('',#1550,#1549);\r\n#1552=CARTESIAN_POINT('',(2.5E1,0.E0,1.325E1));\r\n#1553=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1554=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1555=AXIS2_PLACEMENT_3D('',#1552,#1553,#1554);\r\n#1557=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1558=VECTOR('',#1557,1.5E0);\r\n#1559=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1));\r\n#1560=LINE('',#1559,#1558);\r\n#1561=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1562=VECTOR('',#1561,5.656854249492E0);\r\n#1563=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1));\r\n#1564=LINE('',#1563,#1562);\r\n#1565=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1566=VECTOR('',#1565,1.5E0);\r\n#1567=CARTESIAN_POINT('',(2.E1,0.E0,3.2E1));\r\n#1568=LINE('',#1567,#1566);\r\n#1569=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1570=VECTOR('',#1569,5.656854249492E0);\r\n#1571=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1));\r\n#1572=LINE('',#1571,#1570);\r\n#1573=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1574=VECTOR('',#1573,1.5E0);\r\n#1575=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1));\r\n#1576=LINE('',#1575,#1574);\r\n#1577=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1578=VECTOR('',#1577,5.656854249492E0);\r\n#1579=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1));\r\n#1580=LINE('',#1579,#1578);\r\n#1581=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1582=VECTOR('',#1581,1.5E0);\r\n#1583=CARTESIAN_POINT('',(0.E0,0.E0,2.8E1));\r\n#1584=LINE('',#1583,#1582);\r\n#1585=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1586=VECTOR('',#1585,5.656854249492E0);\r\n#1587=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1));\r\n#1588=LINE('',#1587,#1586);\r\n#1589=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1590=VECTOR('',#1589,1.5E0);\r\n#1591=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0));\r\n#1592=LINE('',#1591,#1590);\r\n#1593=CARTESIAN_POINT('',(2.5E1,0.E0,7.E0));\r\n#1594=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1595=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1596=AXIS2_PLACEMENT_3D('',#1593,#1594,#1595);\r\n#1598=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1599=VECTOR('',#1598,1.5E0);\r\n#1600=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0));\r\n#1601=LINE('',#1600,#1599);\r\n#1602=CARTESIAN_POINT('',(2.5E1,1.5E0,7.E0));\r\n#1603=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1604=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1605=AXIS2_PLACEMENT_3D('',#1602,#1603,#1604);\r\n#1607=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1608=VECTOR('',#1607,1.5E0);\r\n#1609=CARTESIAN_POINT('',(2.E1,0.E0,0.E0));\r\n#1610=LINE('',#1609,#1608);\r\n#1611=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1612=VECTOR('',#1611,5.656854249492E0);\r\n#1613=CARTESIAN_POINT('',(2.E1,0.E0,0.E0));\r\n#1614=LINE('',#1613,#1612);\r\n#1615=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1616=VECTOR('',#1615,1.5E0);\r\n#1617=CARTESIAN_POINT('',(2.4E1,0.E0,4.E0));\r\n#1618=LINE('',#1617,#1616);\r\n#1619=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1620=VECTOR('',#1619,5.656854249492E0);\r\n#1621=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0));\r\n#1622=LINE('',#1621,#1620);\r\n#1623=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1624=VECTOR('',#1623,1.5E0);\r\n#1625=CARTESIAN_POINT('',(0.E0,0.E0,4.E0));\r\n#1626=LINE('',#1625,#1624);\r\n#1627=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1628=VECTOR('',#1627,5.656854249492E0);\r\n#1629=CARTESIAN_POINT('',(0.E0,0.E0,4.E0));\r\n#1630=LINE('',#1629,#1628);\r\n#1631=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1632=VECTOR('',#1631,1.5E0);\r\n#1633=CARTESIAN_POINT('',(4.E0,0.E0,0.E0));\r\n#1634=LINE('',#1633,#1632);\r\n#1635=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1636=VECTOR('',#1635,5.656854249492E0);\r\n#1637=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0));\r\n#1638=LINE('',#1637,#1636);\r\n#1639=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1640=VECTOR('',#1639,1.5E0);\r\n#1641=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1));\r\n#1642=LINE('',#1641,#1640);\r\n#1643=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1644=VECTOR('',#1643,7.071067811865E-1);\r\n#1645=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1));\r\n#1646=LINE('',#1645,#1644);\r\n#1647=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1648=VECTOR('',#1647,1.5E0);\r\n#1649=CARTESIAN_POINT('',(2.6E1,1.5E0,1.175E1));\r\n#1650=LINE('',#1649,#1648);\r\n#1651=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1652=VECTOR('',#1651,7.071067811865E-1);\r\n#1653=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1));\r\n#1654=LINE('',#1653,#1652);\r\n#1655=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1656=VECTOR('',#1655,2.5E0);\r\n#1657=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0));\r\n#1658=LINE('',#1657,#1656);\r\n#1659=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1660=VECTOR('',#1659,2.E0);\r\n#1661=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0));\r\n#1662=LINE('',#1661,#1660);\r\n#1663=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1664=VECTOR('',#1663,2.E0);\r\n#1665=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0));\r\n#1666=LINE('',#1665,#1664);\r\n#1667=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1668=VECTOR('',#1667,2.E0);\r\n#1669=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0));\r\n#1670=LINE('',#1669,#1668);\r\n#1671=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0));\r\n#1672=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1673=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1674=AXIS2_PLACEMENT_3D('',#1671,#1672,#1673);\r\n#1676=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0));\r\n#1677=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1678=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1679=AXIS2_PLACEMENT_3D('',#1676,#1677,#1678);\r\n#1681=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0));\r\n#1682=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1683=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1684=AXIS2_PLACEMENT_3D('',#1681,#1682,#1683);\r\n#1686=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0));\r\n#1687=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1688=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1689=AXIS2_PLACEMENT_3D('',#1686,#1687,#1688);\r\n#1691=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1692=VECTOR('',#1691,2.E0);\r\n#1693=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0));\r\n#1694=LINE('',#1693,#1692);\r\n#1695=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1696=VECTOR('',#1695,1.E1);\r\n#1697=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0));\r\n#1698=LINE('',#1697,#1696);\r\n#1699=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1700=VECTOR('',#1699,1.5E0);\r\n#1701=CARTESIAN_POINT('',(1.9E1,0.E0,1.1E1));\r\n#1702=LINE('',#1701,#1700);\r\n#1703=CARTESIAN_POINT('',(1.8E1,0.E0,1.1E1));\r\n#1704=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1705=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1706=AXIS2_PLACEMENT_3D('',#1703,#1704,#1705);\r\n#1708=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1709=VECTOR('',#1708,1.5E0);\r\n#1710=CARTESIAN_POINT('',(1.8E1,0.E0,1.E1));\r\n#1711=LINE('',#1710,#1709);\r\n#1712=CARTESIAN_POINT('',(1.8E1,1.5E0,1.1E1));\r\n#1713=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1714=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1715=AXIS2_PLACEMENT_3D('',#1712,#1713,#1714);\r\n#1717=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1718=VECTOR('',#1717,1.2E1);\r\n#1719=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1));\r\n#1720=LINE('',#1719,#1718);\r\n#1721=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1722=VECTOR('',#1721,1.5E0);\r\n#1723=CARTESIAN_POINT('',(5.E0,1.5E0,1.1E1));\r\n#1724=LINE('',#1723,#1722);\r\n#1725=CARTESIAN_POINT('',(6.E0,1.5E0,1.1E1));\r\n#1726=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1727=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1728=AXIS2_PLACEMENT_3D('',#1725,#1726,#1727);\r\n#1730=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1731=VECTOR('',#1730,1.5E0);\r\n#1732=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1));\r\n#1733=LINE('',#1732,#1731);\r\n#1734=CARTESIAN_POINT('',(6.E0,0.E0,1.1E1));\r\n#1735=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1736=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#1737=AXIS2_PLACEMENT_3D('',#1734,#1735,#1736);\r\n#1739=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1740=VECTOR('',#1739,2.E0);\r\n#1741=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0));\r\n#1742=LINE('',#1741,#1740);\r\n#1743=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1744=VECTOR('',#1743,1.E1);\r\n#1745=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0));\r\n#1746=LINE('',#1745,#1744);\r\n#1747=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1748=VECTOR('',#1747,1.5E0);\r\n#1749=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1));\r\n#1750=LINE('',#1749,#1748);\r\n#1751=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1752=VECTOR('',#1751,7.071067811865E-1);\r\n#1753=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1));\r\n#1754=LINE('',#1753,#1752);\r\n#1755=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1756=VECTOR('',#1755,1.5E0);\r\n#1757=CARTESIAN_POINT('',(4.5E0,0.E0,1.225E1));\r\n#1758=LINE('',#1757,#1756);\r\n#1759=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#1760=VECTOR('',#1759,7.071067811865E-1);\r\n#1761=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1));\r\n#1762=LINE('',#1761,#1760);\r\n#1763=CARTESIAN_POINT('',(4.25E0,1.05E1,1.E1));\r\n#1764=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1765=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1766=AXIS2_PLACEMENT_3D('',#1763,#1764,#1765);\r\n#1768=CARTESIAN_POINT('',(4.25E0,1.05E1,1.E1));\r\n#1769=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1770=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1771=AXIS2_PLACEMENT_3D('',#1768,#1769,#1770);\r\n#1773=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1774=VECTOR('',#1773,5.E0);\r\n#1775=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.E1));\r\n#1776=LINE('',#1775,#1774);\r\n#1777=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1778=VECTOR('',#1777,1.E0);\r\n#1779=CARTESIAN_POINT('',(-2.E0,2.5E0,1.E1));\r\n#1780=LINE('',#1779,#1778);\r\n#1781=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#1782=VECTOR('',#1781,1.029563014099E1);\r\n#1783=CARTESIAN_POINT('',(3.E0,1.15E1,1.E1));\r\n#1784=LINE('',#1783,#1782);\r\n#1785=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1786=VECTOR('',#1785,2.E0);\r\n#1787=CARTESIAN_POINT('',(5.E0,1.15E1,1.E1));\r\n#1788=LINE('',#1787,#1786);\r\n#1789=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1790=VECTOR('',#1789,1.E1);\r\n#1791=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1));\r\n#1792=LINE('',#1791,#1790);\r\n#1793=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1794=VECTOR('',#1793,5.E0);\r\n#1795=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1));\r\n#1796=LINE('',#1795,#1794);\r\n#1797=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1798=VECTOR('',#1797,1.75E0);\r\n#1799=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1));\r\n#1800=LINE('',#1799,#1798);\r\n#1801=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1802=VECTOR('',#1801,4.3E0);\r\n#1803=CARTESIAN_POINT('',(2.5E0,6.65E0,1.E1));\r\n#1804=LINE('',#1803,#1802);\r\n#1805=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1806=VECTOR('',#1805,1.3E0);\r\n#1807=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1));\r\n#1808=LINE('',#1807,#1806);\r\n#1809=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1810=VECTOR('',#1809,6.8E0);\r\n#1811=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1));\r\n#1812=LINE('',#1811,#1810);\r\n#1813=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1814=VECTOR('',#1813,1.197200760546E0);\r\n#1815=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1));\r\n#1816=LINE('',#1815,#1814);\r\n#1817=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#1818=VECTOR('',#1817,2.059126028197E0);\r\n#1819=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1));\r\n#1820=LINE('',#1819,#1818);\r\n#1821=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1822=VECTOR('',#1821,1.972007605460E-1);\r\n#1823=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1));\r\n#1824=LINE('',#1823,#1822);\r\n#1825=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1826=VECTOR('',#1825,2.E0);\r\n#1827=CARTESIAN_POINT('',(4.4125E0,1.05E1,8.E0));\r\n#1828=LINE('',#1827,#1826);\r\n#1829=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1830=VECTOR('',#1829,2.E0);\r\n#1831=CARTESIAN_POINT('',(4.0875E0,1.05E1,8.E0));\r\n#1832=LINE('',#1831,#1830);\r\n#1833=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#1834=VECTOR('',#1833,5.773502691896E0);\r\n#1835=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1));\r\n#1836=LINE('',#1835,#1834);\r\n#1837=CARTESIAN_POINT('',(8.675E-1,3.035898384862E0,1.2E1));\r\n#1838=CARTESIAN_POINT('',(8.675E-1,2.930774450068E0,1.206069333205E1));\r\n#1839=CARTESIAN_POINT('',(9.058386382037E-1,2.745461691651E0,1.216768370301E1));\r\n#1840=CARTESIAN_POINT('',(1.029862281194E0,2.608885438662E0,1.224653603944E1));\r\n#1841=CARTESIAN_POINT('',(1.125E0,2.580400233539E0,1.226298198028E1));\r\n#1842=CARTESIAN_POINT('',(1.220137718806E0,2.608885438662E0,1.224653603944E1));\r\n#1843=CARTESIAN_POINT('',(1.344161361796E0,2.745461691651E0,1.216768370301E1));\r\n#1844=CARTESIAN_POINT('',(1.3825E0,2.930774450068E0,1.206069333205E1));\r\n#1845=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1));\r\n#1847=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1));\r\n#1848=CARTESIAN_POINT('',(1.3825E0,3.141022319657E0,1.193930666795E1));\r\n#1849=CARTESIAN_POINT('',(1.344161361796E0,3.326335078073E0,1.183231629699E1));\r\n#1850=CARTESIAN_POINT('',(1.220137718806E0,3.462911331062E0,1.175346396056E1));\r\n#1851=CARTESIAN_POINT('',(1.125E0,3.491396536186E0,1.173701801972E1));\r\n#1852=CARTESIAN_POINT('',(1.029862281194E0,3.462911331062E0,1.175346396056E1));\r\n#1853=CARTESIAN_POINT('',(9.058386382037E-1,3.326335078073E0,1.183231629699E1));\r\n#1854=CARTESIAN_POINT('',(8.675E-1,3.141022319657E0,1.193930666795E1));\r\n#1855=CARTESIAN_POINT('',(8.675E-1,3.035898384862E0,1.2E1));\r\n#1857=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#1858=VECTOR('',#1857,5.773502691896E0);\r\n#1859=CARTESIAN_POINT('',(2.E0,6.5E0,1.E1));\r\n#1860=LINE('',#1859,#1858);\r\n#1861=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1862=VECTOR('',#1861,2.035898384862E0);\r\n#1863=CARTESIAN_POINT('',(8.675E-1,1.E0,1.2E1));\r\n#1864=LINE('',#1863,#1862);\r\n#1865=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1866=VECTOR('',#1865,2.035898384862E0);\r\n#1867=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1));\r\n#1868=LINE('',#1867,#1866);\r\n#1869=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1));\r\n#1870=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1871=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1872=AXIS2_PLACEMENT_3D('',#1869,#1870,#1871);\r\n#1874=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1));\r\n#1875=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1876=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1877=AXIS2_PLACEMENT_3D('',#1874,#1875,#1876);\r\n#1879=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1));\r\n#1880=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1881=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1882=AXIS2_PLACEMENT_3D('',#1879,#1880,#1881);\r\n#1884=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1));\r\n#1885=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1886=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1887=AXIS2_PLACEMENT_3D('',#1884,#1885,#1886);\r\n#1889=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1890=VECTOR('',#1889,1.E0);\r\n#1891=CARTESIAN_POINT('',(1.3175E0,1.E0,1.2E1));\r\n#1892=LINE('',#1891,#1890);\r\n#1893=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1894=VECTOR('',#1893,1.E0);\r\n#1895=CARTESIAN_POINT('',(9.325E-1,1.E0,1.2E1));\r\n#1896=LINE('',#1895,#1894);\r\n#1897=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1898=VECTOR('',#1897,2.5E0);\r\n#1899=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0));\r\n#1900=LINE('',#1899,#1898);\r\n#1901=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1902=VECTOR('',#1901,2.E0);\r\n#1903=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0));\r\n#1904=LINE('',#1903,#1902);\r\n#1905=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1906=VECTOR('',#1905,1.5E0);\r\n#1907=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1));\r\n#1908=LINE('',#1907,#1906);\r\n#1909=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1910=VECTOR('',#1909,7.071067811865E-1);\r\n#1911=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1));\r\n#1912=LINE('',#1911,#1910);\r\n#1913=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#1914=VECTOR('',#1913,1.5E0);\r\n#1915=CARTESIAN_POINT('',(-2.E0,0.E0,1.175E1));\r\n#1916=LINE('',#1915,#1914);\r\n#1917=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#1918=VECTOR('',#1917,7.071067811865E-1);\r\n#1919=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1));\r\n#1920=LINE('',#1919,#1918);\r\n#1921=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1922=VECTOR('',#1921,2.E0);\r\n#1923=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0));\r\n#1924=LINE('',#1923,#1922);\r\n#1925=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1926=VECTOR('',#1925,2.E0);\r\n#1927=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0));\r\n#1928=LINE('',#1927,#1926);\r\n#1929=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0));\r\n#1930=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1931=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1932=AXIS2_PLACEMENT_3D('',#1929,#1930,#1931);\r\n#1934=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0));\r\n#1935=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1936=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1937=AXIS2_PLACEMENT_3D('',#1934,#1935,#1936);\r\n#1939=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0));\r\n#1940=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1941=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1942=AXIS2_PLACEMENT_3D('',#1939,#1940,#1941);\r\n#1944=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0));\r\n#1945=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1946=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1947=AXIS2_PLACEMENT_3D('',#1944,#1945,#1946);\r\n#1949=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1950=VECTOR('',#1949,3.75E-1);\r\n#1951=CARTESIAN_POINT('',(4.095E0,1.15E1,9.E0));\r\n#1952=LINE('',#1951,#1950);\r\n#1953=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1954=VECTOR('',#1953,3.75E-1);\r\n#1955=CARTESIAN_POINT('',(3.905E0,1.15E1,9.E0));\r\n#1956=LINE('',#1955,#1954);\r\n#1957=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0));\r\n#1958=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1959=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1960=AXIS2_PLACEMENT_3D('',#1957,#1958,#1959);\r\n#1962=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0));\r\n#1963=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1964=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1965=AXIS2_PLACEMENT_3D('',#1962,#1963,#1964);\r\n#1967=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1968=VECTOR('',#1967,2.5E-1);\r\n#1969=CARTESIAN_POINT('',(3.929917478528E0,1.15E1,9.132582521472E0));\r\n#1970=LINE('',#1969,#1968);\r\n#1971=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1972=VECTOR('',#1971,2.5E-1);\r\n#1973=CARTESIAN_POINT('',(3.804917478528E0,1.15E1,9.132582521472E0));\r\n#1974=LINE('',#1973,#1972);\r\n#1975=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0));\r\n#1976=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1977=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1978=AXIS2_PLACEMENT_3D('',#1975,#1976,#1977);\r\n#1980=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0));\r\n#1981=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#1982=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#1983=AXIS2_PLACEMENT_3D('',#1980,#1981,#1982);\r\n#1985=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1986=VECTOR('',#1985,5.E-1);\r\n#1987=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0));\r\n#1988=LINE('',#1987,#1986);\r\n#1989=CARTESIAN_POINT('',(2.15E0,6.65E0,1.E1));\r\n#1990=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1991=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#1992=AXIS2_PLACEMENT_3D('',#1989,#1990,#1991);\r\n#1994=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#1995=VECTOR('',#1994,5.E-1);\r\n#1996=CARTESIAN_POINT('',(2.15E0,7.E0,9.5E0));\r\n#1997=LINE('',#1996,#1995);\r\n#1998=CARTESIAN_POINT('',(2.15E0,6.65E0,9.5E0));\r\n#1999=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2000=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2001=AXIS2_PLACEMENT_3D('',#1998,#1999,#2000);\r\n#2003=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2004=VECTOR('',#2003,4.3E0);\r\n#2005=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0));\r\n#2006=LINE('',#2005,#2004);\r\n#2007=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2008=VECTOR('',#2007,1.972007605460E-1);\r\n#2009=CARTESIAN_POINT('',(1.952799239454E0,7.E0,9.5E0));\r\n#2010=LINE('',#2009,#2008);\r\n#2011=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#2012=VECTOR('',#2011,2.059126028197E0);\r\n#2013=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,9.5E0));\r\n#2014=LINE('',#2013,#2012);\r\n#2015=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2016=VECTOR('',#2015,1.197200760546E0);\r\n#2017=CARTESIAN_POINT('',(4.15E0,9.5E0,9.5E0));\r\n#2018=LINE('',#2017,#2016);\r\n#2019=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2020=VECTOR('',#2019,6.8E0);\r\n#2021=CARTESIAN_POINT('',(4.5E0,2.35E0,9.5E0));\r\n#2022=LINE('',#2021,#2020);\r\n#2023=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2024=VECTOR('',#2023,1.3E0);\r\n#2025=CARTESIAN_POINT('',(2.85E0,2.E0,9.5E0));\r\n#2026=LINE('',#2025,#2024);\r\n#2027=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2028=VECTOR('',#2027,5.E-1);\r\n#2029=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1));\r\n#2030=LINE('',#2029,#2028);\r\n#2031=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,1.E1));\r\n#2032=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2033=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2034=AXIS2_PLACEMENT_3D('',#2031,#2032,#2033);\r\n#2036=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2037=VECTOR('',#2036,5.E-1);\r\n#2038=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,1.E1));\r\n#2039=LINE('',#2038,#2037);\r\n#2040=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,9.5E0));\r\n#2041=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2042=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#2043=AXIS2_PLACEMENT_3D('',#2040,#2041,#2042);\r\n#2045=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2046=VECTOR('',#2045,5.E-1);\r\n#2047=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1));\r\n#2048=LINE('',#2047,#2046);\r\n#2049=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,1.E1));\r\n#2050=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2051=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#2052=AXIS2_PLACEMENT_3D('',#2049,#2050,#2051);\r\n#2054=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2055=VECTOR('',#2054,5.E-1);\r\n#2056=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,1.E1));\r\n#2057=LINE('',#2056,#2055);\r\n#2058=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,9.5E0));\r\n#2059=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2060=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2061=AXIS2_PLACEMENT_3D('',#2058,#2059,#2060);\r\n#2063=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2064=VECTOR('',#2063,5.E-1);\r\n#2065=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1));\r\n#2066=LINE('',#2065,#2064);\r\n#2067=CARTESIAN_POINT('',(4.15E0,9.15E0,1.E1));\r\n#2068=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2069=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2070=AXIS2_PLACEMENT_3D('',#2067,#2068,#2069);\r\n#2072=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2073=VECTOR('',#2072,5.E-1);\r\n#2074=CARTESIAN_POINT('',(4.5E0,9.15E0,1.E1));\r\n#2075=LINE('',#2074,#2073);\r\n#2076=CARTESIAN_POINT('',(4.15E0,9.15E0,9.5E0));\r\n#2077=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2078=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2079=AXIS2_PLACEMENT_3D('',#2076,#2077,#2078);\r\n#2081=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2082=VECTOR('',#2081,5.E-1);\r\n#2083=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1));\r\n#2084=LINE('',#2083,#2082);\r\n#2085=CARTESIAN_POINT('',(4.15E0,2.35E0,1.E1));\r\n#2086=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2087=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2088=AXIS2_PLACEMENT_3D('',#2085,#2086,#2087);\r\n#2090=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2091=VECTOR('',#2090,5.E-1);\r\n#2092=CARTESIAN_POINT('',(4.15E0,2.E0,1.E1));\r\n#2093=LINE('',#2092,#2091);\r\n#2094=CARTESIAN_POINT('',(4.15E0,2.35E0,9.5E0));\r\n#2095=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2096=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2097=AXIS2_PLACEMENT_3D('',#2094,#2095,#2096);\r\n#2099=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2100=VECTOR('',#2099,5.E-1);\r\n#2101=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1));\r\n#2102=LINE('',#2101,#2100);\r\n#2103=CARTESIAN_POINT('',(2.85E0,2.35E0,1.E1));\r\n#2104=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2105=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2106=AXIS2_PLACEMENT_3D('',#2103,#2104,#2105);\r\n#2108=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2109=VECTOR('',#2108,5.E-1);\r\n#2110=CARTESIAN_POINT('',(2.5E0,2.35E0,1.E1));\r\n#2111=LINE('',#2110,#2109);\r\n#2112=CARTESIAN_POINT('',(2.85E0,2.35E0,9.5E0));\r\n#2113=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2114=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2115=AXIS2_PLACEMENT_3D('',#2112,#2113,#2114);\r\n#2117=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2118=VECTOR('',#2117,1.5E0);\r\n#2119=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1));\r\n#2120=LINE('',#2119,#2118);\r\n#2121=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#2122=VECTOR('',#2121,7.071067811865E-1);\r\n#2123=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1));\r\n#2124=LINE('',#2123,#2122);\r\n#2125=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2126=VECTOR('',#2125,1.5E0);\r\n#2127=CARTESIAN_POINT('',(1.95E1,1.5E0,1.225E1));\r\n#2128=LINE('',#2127,#2126);\r\n#2129=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#2130=VECTOR('',#2129,7.071067811865E-1);\r\n#2131=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1));\r\n#2132=LINE('',#2131,#2130);\r\n#2133=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2134=VECTOR('',#2133,3.75E-1);\r\n#2135=CARTESIAN_POINT('',(1.9905E1,1.15E1,9.E0));\r\n#2136=LINE('',#2135,#2134);\r\n#2137=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2138=VECTOR('',#2137,3.75E-1);\r\n#2139=CARTESIAN_POINT('',(2.0095E1,1.15E1,9.E0));\r\n#2140=LINE('',#2139,#2138);\r\n#2141=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0));\r\n#2142=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2143=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2144=AXIS2_PLACEMENT_3D('',#2141,#2142,#2143);\r\n#2146=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0));\r\n#2147=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2148=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2149=AXIS2_PLACEMENT_3D('',#2146,#2147,#2148);\r\n#2151=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2152=VECTOR('',#2151,2.5E-1);\r\n#2153=CARTESIAN_POINT('',(2.007008252147E1,1.15E1,9.132582521472E0));\r\n#2154=LINE('',#2153,#2152);\r\n#2155=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2156=VECTOR('',#2155,2.5E-1);\r\n#2157=CARTESIAN_POINT('',(2.019508252147E1,1.15E1,9.132582521472E0));\r\n#2158=LINE('',#2157,#2156);\r\n#2159=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0));\r\n#2160=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2161=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2162=AXIS2_PLACEMENT_3D('',#2159,#2160,#2161);\r\n#2164=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0));\r\n#2165=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2166=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2167=AXIS2_PLACEMENT_3D('',#2164,#2165,#2166);\r\n#2169=DIRECTION('',(1.421085471520E-14,1.E0,0.E0));\r\n#2170=VECTOR('',#2169,2.5E-1);\r\n#2171=CARTESIAN_POINT('',(1.745E1,1.25E0,2.975E1));\r\n#2172=LINE('',#2171,#2170);\r\n#2173=DIRECTION('',(-1.421085471520E-14,1.E0,0.E0));\r\n#2174=VECTOR('',#2173,2.5E-1);\r\n#2175=CARTESIAN_POINT('',(1.765E1,1.25E0,2.975E1));\r\n#2176=LINE('',#2175,#2174);\r\n#2177=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0));\r\n#2178=VECTOR('',#2177,1.154700538379E-1);\r\n#2179=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1));\r\n#2180=LINE('',#2179,#2178);\r\n#2181=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0));\r\n#2182=VECTOR('',#2181,1.154700538379E-1);\r\n#2183=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1));\r\n#2184=LINE('',#2183,#2182);\r\n#2185=CARTESIAN_POINT('',(1.755E1,1.25E0,2.975E1));\r\n#2186=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2187=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2188=AXIS2_PLACEMENT_3D('',#2185,#2186,#2187);\r\n#2190=CARTESIAN_POINT('',(1.755E1,1.25E0,2.975E1));\r\n#2191=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2192=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2193=AXIS2_PLACEMENT_3D('',#2190,#2191,#2192);\r\n#2195=DIRECTION('',(1.421085471520E-14,1.E0,0.E0));\r\n#2196=VECTOR('',#2195,2.5E-1);\r\n#2197=CARTESIAN_POINT('',(1.645E1,1.25E0,2.975E1));\r\n#2198=LINE('',#2197,#2196);\r\n#2199=DIRECTION('',(-1.421085471520E-14,1.E0,0.E0));\r\n#2200=VECTOR('',#2199,2.5E-1);\r\n#2201=CARTESIAN_POINT('',(1.665E1,1.25E0,2.975E1));\r\n#2202=LINE('',#2201,#2200);\r\n#2203=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0));\r\n#2204=VECTOR('',#2203,1.154700538379E-1);\r\n#2205=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1));\r\n#2206=LINE('',#2205,#2204);\r\n#2207=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0));\r\n#2208=VECTOR('',#2207,1.154700538379E-1);\r\n#2209=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1));\r\n#2210=LINE('',#2209,#2208);\r\n#2211=CARTESIAN_POINT('',(1.655E1,1.25E0,2.975E1));\r\n#2212=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2213=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2214=AXIS2_PLACEMENT_3D('',#2211,#2212,#2213);\r\n#2216=CARTESIAN_POINT('',(1.655E1,1.25E0,2.975E1));\r\n#2217=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2218=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2219=AXIS2_PLACEMENT_3D('',#2216,#2217,#2218);\r\n#2221=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2222=VECTOR('',#2221,5.E-1);\r\n#2223=CARTESIAN_POINT('',(1.3825E0,1.5E0,6.E0));\r\n#2224=LINE('',#2223,#2222);\r\n#2225=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2226=VECTOR('',#2225,5.E-1);\r\n#2227=CARTESIAN_POINT('',(8.675E-1,1.5E0,6.E0));\r\n#2228=LINE('',#2227,#2226);\r\n#2229=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0));\r\n#2230=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2231=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2232=AXIS2_PLACEMENT_3D('',#2229,#2230,#2231);\r\n#2234=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0));\r\n#2235=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2236=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2237=AXIS2_PLACEMENT_3D('',#2234,#2235,#2236);\r\n#2239=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0));\r\n#2240=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2241=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2242=AXIS2_PLACEMENT_3D('',#2239,#2240,#2241);\r\n#2244=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0));\r\n#2245=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2246=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2247=AXIS2_PLACEMENT_3D('',#2244,#2245,#2246);\r\n#2249=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2250=VECTOR('',#2249,1.E0);\r\n#2251=CARTESIAN_POINT('',(1.3175E0,1.E0,6.E0));\r\n#2252=LINE('',#2251,#2250);\r\n#2253=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2254=VECTOR('',#2253,1.E0);\r\n#2255=CARTESIAN_POINT('',(9.325E-1,1.E0,6.E0));\r\n#2256=LINE('',#2255,#2254);\r\n#2257=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2258=VECTOR('',#2257,5.E-1);\r\n#2259=CARTESIAN_POINT('',(1.3825E0,1.5E0,1.8E1));\r\n#2260=LINE('',#2259,#2258);\r\n#2261=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2262=VECTOR('',#2261,5.E-1);\r\n#2263=CARTESIAN_POINT('',(8.675E-1,1.5E0,1.8E1));\r\n#2264=LINE('',#2263,#2262);\r\n#2265=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1));\r\n#2266=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2267=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2268=AXIS2_PLACEMENT_3D('',#2265,#2266,#2267);\r\n#2270=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1));\r\n#2271=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2272=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2273=AXIS2_PLACEMENT_3D('',#2270,#2271,#2272);\r\n#2275=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1));\r\n#2276=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2277=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2278=AXIS2_PLACEMENT_3D('',#2275,#2276,#2277);\r\n#2280=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1));\r\n#2281=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2282=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2283=AXIS2_PLACEMENT_3D('',#2280,#2281,#2282);\r\n#2285=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2286=VECTOR('',#2285,1.E0);\r\n#2287=CARTESIAN_POINT('',(1.3175E0,1.E0,1.8E1));\r\n#2288=LINE('',#2287,#2286);\r\n#2289=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2290=VECTOR('',#2289,1.E0);\r\n#2291=CARTESIAN_POINT('',(9.325E-1,1.E0,1.8E1));\r\n#2292=LINE('',#2291,#2290);\r\n#2293=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2294=VECTOR('',#2293,5.E-1);\r\n#2295=CARTESIAN_POINT('',(1.3825E0,1.5E0,2.4E1));\r\n#2296=LINE('',#2295,#2294);\r\n#2297=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2298=VECTOR('',#2297,5.E-1);\r\n#2299=CARTESIAN_POINT('',(8.675E-1,1.5E0,2.4E1));\r\n#2300=LINE('',#2299,#2298);\r\n#2301=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1));\r\n#2302=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2303=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2304=AXIS2_PLACEMENT_3D('',#2301,#2302,#2303);\r\n#2306=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1));\r\n#2307=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2308=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2309=AXIS2_PLACEMENT_3D('',#2306,#2307,#2308);\r\n#2311=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1));\r\n#2312=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2313=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2314=AXIS2_PLACEMENT_3D('',#2311,#2312,#2313);\r\n#2316=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1));\r\n#2317=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2318=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2319=AXIS2_PLACEMENT_3D('',#2316,#2317,#2318);\r\n#2321=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2322=VECTOR('',#2321,1.E0);\r\n#2323=CARTESIAN_POINT('',(1.3175E0,1.E0,2.4E1));\r\n#2324=LINE('',#2323,#2322);\r\n#2325=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2326=VECTOR('',#2325,1.E0);\r\n#2327=CARTESIAN_POINT('',(9.325E-1,1.E0,2.4E1));\r\n#2328=LINE('',#2327,#2326);\r\n#2329=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2330=VECTOR('',#2329,5.E-1);\r\n#2331=CARTESIAN_POINT('',(2.31325E1,1.5E0,6.E0));\r\n#2332=LINE('',#2331,#2330);\r\n#2333=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2334=VECTOR('',#2333,5.E-1);\r\n#2335=CARTESIAN_POINT('',(2.26175E1,1.5E0,6.E0));\r\n#2336=LINE('',#2335,#2334);\r\n#2337=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0));\r\n#2338=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2339=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2340=AXIS2_PLACEMENT_3D('',#2337,#2338,#2339);\r\n#2342=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0));\r\n#2343=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2344=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2345=AXIS2_PLACEMENT_3D('',#2342,#2343,#2344);\r\n#2347=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0));\r\n#2348=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2349=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2350=AXIS2_PLACEMENT_3D('',#2347,#2348,#2349);\r\n#2352=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0));\r\n#2353=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2354=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2355=AXIS2_PLACEMENT_3D('',#2352,#2353,#2354);\r\n#2357=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2358=VECTOR('',#2357,1.E0);\r\n#2359=CARTESIAN_POINT('',(2.30675E1,1.E0,6.E0));\r\n#2360=LINE('',#2359,#2358);\r\n#2361=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2362=VECTOR('',#2361,1.E0);\r\n#2363=CARTESIAN_POINT('',(2.26825E1,1.E0,6.E0));\r\n#2364=LINE('',#2363,#2362);\r\n#2365=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2366=VECTOR('',#2365,5.E-1);\r\n#2367=CARTESIAN_POINT('',(2.31325E1,1.5E0,1.8E1));\r\n#2368=LINE('',#2367,#2366);\r\n#2369=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2370=VECTOR('',#2369,5.E-1);\r\n#2371=CARTESIAN_POINT('',(2.26175E1,1.5E0,1.8E1));\r\n#2372=LINE('',#2371,#2370);\r\n#2373=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1));\r\n#2374=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2375=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2376=AXIS2_PLACEMENT_3D('',#2373,#2374,#2375);\r\n#2378=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1));\r\n#2379=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2380=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2381=AXIS2_PLACEMENT_3D('',#2378,#2379,#2380);\r\n#2383=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1));\r\n#2384=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2385=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2386=AXIS2_PLACEMENT_3D('',#2383,#2384,#2385);\r\n#2388=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1));\r\n#2389=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2390=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2391=AXIS2_PLACEMENT_3D('',#2388,#2389,#2390);\r\n#2393=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2394=VECTOR('',#2393,1.E0);\r\n#2395=CARTESIAN_POINT('',(2.30675E1,1.E0,1.8E1));\r\n#2396=LINE('',#2395,#2394);\r\n#2397=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2398=VECTOR('',#2397,1.E0);\r\n#2399=CARTESIAN_POINT('',(2.26825E1,1.E0,1.8E1));\r\n#2400=LINE('',#2399,#2398);\r\n#2401=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2402=VECTOR('',#2401,5.E-1);\r\n#2403=CARTESIAN_POINT('',(2.31325E1,1.5E0,2.4E1));\r\n#2404=LINE('',#2403,#2402);\r\n#2405=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2406=VECTOR('',#2405,5.E-1);\r\n#2407=CARTESIAN_POINT('',(2.26175E1,1.5E0,2.4E1));\r\n#2408=LINE('',#2407,#2406);\r\n#2409=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1));\r\n#2410=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2411=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2412=AXIS2_PLACEMENT_3D('',#2409,#2410,#2411);\r\n#2414=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1));\r\n#2415=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2416=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2417=AXIS2_PLACEMENT_3D('',#2414,#2415,#2416);\r\n#2419=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1));\r\n#2420=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2421=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2422=AXIS2_PLACEMENT_3D('',#2419,#2420,#2421);\r\n#2424=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1));\r\n#2425=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2426=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2427=AXIS2_PLACEMENT_3D('',#2424,#2425,#2426);\r\n#2429=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2430=VECTOR('',#2429,1.E0);\r\n#2431=CARTESIAN_POINT('',(2.30675E1,1.E0,2.4E1));\r\n#2432=LINE('',#2431,#2430);\r\n#2433=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2434=VECTOR('',#2433,1.E0);\r\n#2435=CARTESIAN_POINT('',(2.26825E1,1.E0,2.4E1));\r\n#2436=LINE('',#2435,#2434);\r\n#2437=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2438=VECTOR('',#2437,5.E-1);\r\n#2439=CARTESIAN_POINT('',(6.256E0,1.5E0,1.25E0));\r\n#2440=LINE('',#2439,#2438);\r\n#2441=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2442=VECTOR('',#2441,5.E-1);\r\n#2443=CARTESIAN_POINT('',(5.744E0,1.5E0,1.25E0));\r\n#2444=LINE('',#2443,#2442);\r\n#2445=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0));\r\n#2446=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2447=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2448=AXIS2_PLACEMENT_3D('',#2445,#2446,#2447);\r\n#2450=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0));\r\n#2451=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2452=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2453=AXIS2_PLACEMENT_3D('',#2450,#2451,#2452);\r\n#2455=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0));\r\n#2456=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2457=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2458=AXIS2_PLACEMENT_3D('',#2455,#2456,#2457);\r\n#2460=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0));\r\n#2461=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2462=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2463=AXIS2_PLACEMENT_3D('',#2460,#2461,#2462);\r\n#2465=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2466=VECTOR('',#2465,1.E0);\r\n#2467=CARTESIAN_POINT('',(6.1925E0,1.E0,1.25E0));\r\n#2468=LINE('',#2467,#2466);\r\n#2469=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2470=VECTOR('',#2469,1.E0);\r\n#2471=CARTESIAN_POINT('',(5.8075E0,1.E0,1.25E0));\r\n#2472=LINE('',#2471,#2470);\r\n#2473=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2474=VECTOR('',#2473,5.E-1);\r\n#2475=CARTESIAN_POINT('',(1.2256E1,1.5E0,1.25E0));\r\n#2476=LINE('',#2475,#2474);\r\n#2477=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2478=VECTOR('',#2477,5.E-1);\r\n#2479=CARTESIAN_POINT('',(1.1744E1,1.5E0,1.25E0));\r\n#2480=LINE('',#2479,#2478);\r\n#2481=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0));\r\n#2482=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2483=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2484=AXIS2_PLACEMENT_3D('',#2481,#2482,#2483);\r\n#2486=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0));\r\n#2487=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2488=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2489=AXIS2_PLACEMENT_3D('',#2486,#2487,#2488);\r\n#2491=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0));\r\n#2492=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2493=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2494=AXIS2_PLACEMENT_3D('',#2491,#2492,#2493);\r\n#2496=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0));\r\n#2497=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2498=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2499=AXIS2_PLACEMENT_3D('',#2496,#2497,#2498);\r\n#2501=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2502=VECTOR('',#2501,1.E0);\r\n#2503=CARTESIAN_POINT('',(1.21925E1,1.E0,1.25E0));\r\n#2504=LINE('',#2503,#2502);\r\n#2505=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2506=VECTOR('',#2505,1.E0);\r\n#2507=CARTESIAN_POINT('',(1.18075E1,1.E0,1.25E0));\r\n#2508=LINE('',#2507,#2506);\r\n#2509=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2510=VECTOR('',#2509,5.E-1);\r\n#2511=CARTESIAN_POINT('',(1.8256E1,1.5E0,1.25E0));\r\n#2512=LINE('',#2511,#2510);\r\n#2513=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2514=VECTOR('',#2513,5.E-1);\r\n#2515=CARTESIAN_POINT('',(1.7744E1,1.5E0,1.25E0));\r\n#2516=LINE('',#2515,#2514);\r\n#2517=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0));\r\n#2518=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2519=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2520=AXIS2_PLACEMENT_3D('',#2517,#2518,#2519);\r\n#2522=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0));\r\n#2523=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2524=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2525=AXIS2_PLACEMENT_3D('',#2522,#2523,#2524);\r\n#2527=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0));\r\n#2528=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2529=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2530=AXIS2_PLACEMENT_3D('',#2527,#2528,#2529);\r\n#2532=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0));\r\n#2533=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2534=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2535=AXIS2_PLACEMENT_3D('',#2532,#2533,#2534);\r\n#2537=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2538=VECTOR('',#2537,1.E0);\r\n#2539=CARTESIAN_POINT('',(1.81925E1,1.E0,1.25E0));\r\n#2540=LINE('',#2539,#2538);\r\n#2541=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2542=VECTOR('',#2541,1.E0);\r\n#2543=CARTESIAN_POINT('',(1.78075E1,1.E0,1.25E0));\r\n#2544=LINE('',#2543,#2542);\r\n#2545=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2546=VECTOR('',#2545,5.E-1);\r\n#2547=CARTESIAN_POINT('',(6.256E0,1.5E0,3.075E1));\r\n#2548=LINE('',#2547,#2546);\r\n#2549=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2550=VECTOR('',#2549,5.E-1);\r\n#2551=CARTESIAN_POINT('',(5.744E0,1.5E0,3.075E1));\r\n#2552=LINE('',#2551,#2550);\r\n#2553=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1));\r\n#2554=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2555=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2556=AXIS2_PLACEMENT_3D('',#2553,#2554,#2555);\r\n#2558=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1));\r\n#2559=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2560=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2561=AXIS2_PLACEMENT_3D('',#2558,#2559,#2560);\r\n#2563=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1));\r\n#2564=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2565=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2566=AXIS2_PLACEMENT_3D('',#2563,#2564,#2565);\r\n#2568=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1));\r\n#2569=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2570=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2571=AXIS2_PLACEMENT_3D('',#2568,#2569,#2570);\r\n#2573=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2574=VECTOR('',#2573,1.E0);\r\n#2575=CARTESIAN_POINT('',(6.1925E0,1.E0,3.075E1));\r\n#2576=LINE('',#2575,#2574);\r\n#2577=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2578=VECTOR('',#2577,1.E0);\r\n#2579=CARTESIAN_POINT('',(5.8075E0,1.E0,3.075E1));\r\n#2580=LINE('',#2579,#2578);\r\n#2581=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2582=VECTOR('',#2581,5.E-1);\r\n#2583=CARTESIAN_POINT('',(1.2256E1,1.5E0,3.075E1));\r\n#2584=LINE('',#2583,#2582);\r\n#2585=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2586=VECTOR('',#2585,5.E-1);\r\n#2587=CARTESIAN_POINT('',(1.1744E1,1.5E0,3.075E1));\r\n#2588=LINE('',#2587,#2586);\r\n#2589=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1));\r\n#2590=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2591=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2592=AXIS2_PLACEMENT_3D('',#2589,#2590,#2591);\r\n#2594=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1));\r\n#2595=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2596=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2597=AXIS2_PLACEMENT_3D('',#2594,#2595,#2596);\r\n#2599=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1));\r\n#2600=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2601=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2602=AXIS2_PLACEMENT_3D('',#2599,#2600,#2601);\r\n#2604=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1));\r\n#2605=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2606=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2607=AXIS2_PLACEMENT_3D('',#2604,#2605,#2606);\r\n#2609=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2610=VECTOR('',#2609,1.E0);\r\n#2611=CARTESIAN_POINT('',(1.21925E1,1.E0,3.075E1));\r\n#2612=LINE('',#2611,#2610);\r\n#2613=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2614=VECTOR('',#2613,1.E0);\r\n#2615=CARTESIAN_POINT('',(1.18075E1,1.E0,3.075E1));\r\n#2616=LINE('',#2615,#2614);\r\n#2617=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2618=VECTOR('',#2617,5.E-1);\r\n#2619=CARTESIAN_POINT('',(1.8256E1,1.5E0,3.075E1));\r\n#2620=LINE('',#2619,#2618);\r\n#2621=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2622=VECTOR('',#2621,5.E-1);\r\n#2623=CARTESIAN_POINT('',(1.7744E1,1.5E0,3.075E1));\r\n#2624=LINE('',#2623,#2622);\r\n#2625=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1));\r\n#2626=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2627=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2628=AXIS2_PLACEMENT_3D('',#2625,#2626,#2627);\r\n#2630=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1));\r\n#2631=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2632=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2633=AXIS2_PLACEMENT_3D('',#2630,#2631,#2632);\r\n#2635=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1));\r\n#2636=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2637=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2638=AXIS2_PLACEMENT_3D('',#2635,#2636,#2637);\r\n#2640=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1));\r\n#2641=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2642=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2643=AXIS2_PLACEMENT_3D('',#2640,#2641,#2642);\r\n#2645=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2646=VECTOR('',#2645,1.E0);\r\n#2647=CARTESIAN_POINT('',(1.81925E1,1.E0,3.075E1));\r\n#2648=LINE('',#2647,#2646);\r\n#2649=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2650=VECTOR('',#2649,1.E0);\r\n#2651=CARTESIAN_POINT('',(1.78075E1,1.E0,3.075E1));\r\n#2652=LINE('',#2651,#2650);\r\n#2653=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2654=VECTOR('',#2653,5.E-1);\r\n#2655=CARTESIAN_POINT('',(6.2575E0,1.5E0,9.E0));\r\n#2656=LINE('',#2655,#2654);\r\n#2657=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2658=VECTOR('',#2657,5.E-1);\r\n#2659=CARTESIAN_POINT('',(5.7425E0,1.5E0,9.E0));\r\n#2660=LINE('',#2659,#2658);\r\n#2661=CARTESIAN_POINT('',(6.E0,1.E0,9.E0));\r\n#2662=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2663=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2664=AXIS2_PLACEMENT_3D('',#2661,#2662,#2663);\r\n#2666=CARTESIAN_POINT('',(6.E0,1.E0,9.E0));\r\n#2667=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2668=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2669=AXIS2_PLACEMENT_3D('',#2666,#2667,#2668);\r\n#2671=CARTESIAN_POINT('',(6.E0,1.E0,9.E0));\r\n#2672=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2673=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2674=AXIS2_PLACEMENT_3D('',#2671,#2672,#2673);\r\n#2676=CARTESIAN_POINT('',(6.E0,1.E0,9.E0));\r\n#2677=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2678=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2679=AXIS2_PLACEMENT_3D('',#2676,#2677,#2678);\r\n#2681=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2682=VECTOR('',#2681,1.E0);\r\n#2683=CARTESIAN_POINT('',(6.1925E0,1.E0,9.E0));\r\n#2684=LINE('',#2683,#2682);\r\n#2685=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2686=VECTOR('',#2685,1.E0);\r\n#2687=CARTESIAN_POINT('',(5.8075E0,1.E0,9.E0));\r\n#2688=LINE('',#2687,#2686);\r\n#2689=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2690=VECTOR('',#2689,5.E-1);\r\n#2691=CARTESIAN_POINT('',(1.22575E1,1.5E0,9.E0));\r\n#2692=LINE('',#2691,#2690);\r\n#2693=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2694=VECTOR('',#2693,5.E-1);\r\n#2695=CARTESIAN_POINT('',(1.17425E1,1.5E0,9.E0));\r\n#2696=LINE('',#2695,#2694);\r\n#2697=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0));\r\n#2698=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2699=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2700=AXIS2_PLACEMENT_3D('',#2697,#2698,#2699);\r\n#2702=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0));\r\n#2703=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2704=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2705=AXIS2_PLACEMENT_3D('',#2702,#2703,#2704);\r\n#2707=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0));\r\n#2708=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2709=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2710=AXIS2_PLACEMENT_3D('',#2707,#2708,#2709);\r\n#2712=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0));\r\n#2713=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2714=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2715=AXIS2_PLACEMENT_3D('',#2712,#2713,#2714);\r\n#2717=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2718=VECTOR('',#2717,1.E0);\r\n#2719=CARTESIAN_POINT('',(1.21925E1,1.E0,9.E0));\r\n#2720=LINE('',#2719,#2718);\r\n#2721=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2722=VECTOR('',#2721,1.E0);\r\n#2723=CARTESIAN_POINT('',(1.18075E1,1.E0,9.E0));\r\n#2724=LINE('',#2723,#2722);\r\n#2725=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2726=VECTOR('',#2725,5.E-1);\r\n#2727=CARTESIAN_POINT('',(1.82575E1,1.5E0,9.E0));\r\n#2728=LINE('',#2727,#2726);\r\n#2729=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2730=VECTOR('',#2729,5.E-1);\r\n#2731=CARTESIAN_POINT('',(1.77425E1,1.5E0,9.E0));\r\n#2732=LINE('',#2731,#2730);\r\n#2733=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0));\r\n#2734=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2735=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2736=AXIS2_PLACEMENT_3D('',#2733,#2734,#2735);\r\n#2738=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0));\r\n#2739=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2740=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2741=AXIS2_PLACEMENT_3D('',#2738,#2739,#2740);\r\n#2743=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0));\r\n#2744=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2745=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2746=AXIS2_PLACEMENT_3D('',#2743,#2744,#2745);\r\n#2748=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0));\r\n#2749=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2750=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2751=AXIS2_PLACEMENT_3D('',#2748,#2749,#2750);\r\n#2753=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2754=VECTOR('',#2753,1.E0);\r\n#2755=CARTESIAN_POINT('',(1.81925E1,1.E0,9.E0));\r\n#2756=LINE('',#2755,#2754);\r\n#2757=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2758=VECTOR('',#2757,1.E0);\r\n#2759=CARTESIAN_POINT('',(1.78075E1,1.E0,9.E0));\r\n#2760=LINE('',#2759,#2758);\r\n#2761=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2762=VECTOR('',#2761,5.E-1);\r\n#2763=CARTESIAN_POINT('',(6.2575E0,1.5E0,1.8E1));\r\n#2764=LINE('',#2763,#2762);\r\n#2765=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2766=VECTOR('',#2765,5.E-1);\r\n#2767=CARTESIAN_POINT('',(5.7425E0,1.5E0,1.8E1));\r\n#2768=LINE('',#2767,#2766);\r\n#2769=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1));\r\n#2770=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2771=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2772=AXIS2_PLACEMENT_3D('',#2769,#2770,#2771);\r\n#2774=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1));\r\n#2775=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2776=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2777=AXIS2_PLACEMENT_3D('',#2774,#2775,#2776);\r\n#2779=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1));\r\n#2780=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2781=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2782=AXIS2_PLACEMENT_3D('',#2779,#2780,#2781);\r\n#2784=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1));\r\n#2785=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2786=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2787=AXIS2_PLACEMENT_3D('',#2784,#2785,#2786);\r\n#2789=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2790=VECTOR('',#2789,1.E0);\r\n#2791=CARTESIAN_POINT('',(6.1925E0,1.E0,1.8E1));\r\n#2792=LINE('',#2791,#2790);\r\n#2793=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2794=VECTOR('',#2793,1.E0);\r\n#2795=CARTESIAN_POINT('',(5.8075E0,1.E0,1.8E1));\r\n#2796=LINE('',#2795,#2794);\r\n#2797=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2798=VECTOR('',#2797,5.E-1);\r\n#2799=CARTESIAN_POINT('',(1.22575E1,1.5E0,1.8E1));\r\n#2800=LINE('',#2799,#2798);\r\n#2801=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2802=VECTOR('',#2801,5.E-1);\r\n#2803=CARTESIAN_POINT('',(1.17425E1,1.5E0,1.8E1));\r\n#2804=LINE('',#2803,#2802);\r\n#2805=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1));\r\n#2806=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2807=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2808=AXIS2_PLACEMENT_3D('',#2805,#2806,#2807);\r\n#2810=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1));\r\n#2811=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2812=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2813=AXIS2_PLACEMENT_3D('',#2810,#2811,#2812);\r\n#2815=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1));\r\n#2816=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2817=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2818=AXIS2_PLACEMENT_3D('',#2815,#2816,#2817);\r\n#2820=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1));\r\n#2821=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2822=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2823=AXIS2_PLACEMENT_3D('',#2820,#2821,#2822);\r\n#2825=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2826=VECTOR('',#2825,1.E0);\r\n#2827=CARTESIAN_POINT('',(1.21925E1,1.E0,1.8E1));\r\n#2828=LINE('',#2827,#2826);\r\n#2829=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2830=VECTOR('',#2829,1.E0);\r\n#2831=CARTESIAN_POINT('',(1.18075E1,1.E0,1.8E1));\r\n#2832=LINE('',#2831,#2830);\r\n#2833=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2834=VECTOR('',#2833,5.E-1);\r\n#2835=CARTESIAN_POINT('',(1.82575E1,1.5E0,1.8E1));\r\n#2836=LINE('',#2835,#2834);\r\n#2837=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2838=VECTOR('',#2837,5.E-1);\r\n#2839=CARTESIAN_POINT('',(1.77425E1,1.5E0,1.8E1));\r\n#2840=LINE('',#2839,#2838);\r\n#2841=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1));\r\n#2842=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2843=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2844=AXIS2_PLACEMENT_3D('',#2841,#2842,#2843);\r\n#2846=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1));\r\n#2847=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2848=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2849=AXIS2_PLACEMENT_3D('',#2846,#2847,#2848);\r\n#2851=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1));\r\n#2852=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2853=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2854=AXIS2_PLACEMENT_3D('',#2851,#2852,#2853);\r\n#2856=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1));\r\n#2857=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2858=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2859=AXIS2_PLACEMENT_3D('',#2856,#2857,#2858);\r\n#2861=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2862=VECTOR('',#2861,1.E0);\r\n#2863=CARTESIAN_POINT('',(1.81925E1,1.E0,1.8E1));\r\n#2864=LINE('',#2863,#2862);\r\n#2865=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2866=VECTOR('',#2865,1.E0);\r\n#2867=CARTESIAN_POINT('',(1.78075E1,1.E0,1.8E1));\r\n#2868=LINE('',#2867,#2866);\r\n#2869=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#2870=VECTOR('',#2869,5.773502691896E0);\r\n#2871=CARTESIAN_POINT('',(2.2E1,6.5E0,1.E1));\r\n#2872=LINE('',#2871,#2870);\r\n#2873=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1));\r\n#2874=CARTESIAN_POINT('',(2.31325E1,2.930774450068E0,1.206069333205E1));\r\n#2875=CARTESIAN_POINT('',(2.309416136180E1,2.745461691651E0,1.216768370301E1));\r\n#2876=CARTESIAN_POINT('',(2.297013771881E1,2.608885438662E0,1.224653603944E1));\r\n#2877=CARTESIAN_POINT('',(2.2875E1,2.580400233539E0,1.226298198028E1));\r\n#2878=CARTESIAN_POINT('',(2.277986228119E1,2.608885438662E0,1.224653603944E1));\r\n#2879=CARTESIAN_POINT('',(2.265583863820E1,2.745461691651E0,1.216768370301E1));\r\n#2880=CARTESIAN_POINT('',(2.26175E1,2.930774450068E0,1.206069333205E1));\r\n#2881=CARTESIAN_POINT('',(2.26175E1,3.035898384862E0,1.2E1));\r\n#2883=CARTESIAN_POINT('',(2.26175E1,3.035898384862E0,1.2E1));\r\n#2884=CARTESIAN_POINT('',(2.26175E1,3.141022319657E0,1.193930666795E1));\r\n#2885=CARTESIAN_POINT('',(2.265583863820E1,3.326335078073E0,1.183231629699E1));\r\n#2886=CARTESIAN_POINT('',(2.277986228119E1,3.462911331062E0,1.175346396056E1));\r\n#2887=CARTESIAN_POINT('',(2.2875E1,3.491396536186E0,1.173701801972E1));\r\n#2888=CARTESIAN_POINT('',(2.297013771881E1,3.462911331062E0,1.175346396056E1));\r\n#2889=CARTESIAN_POINT('',(2.309416136180E1,3.326335078073E0,1.183231629699E1));\r\n#2890=CARTESIAN_POINT('',(2.31325E1,3.141022319657E0,1.193930666795E1));\r\n#2891=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1));\r\n#2893=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#2894=VECTOR('',#2893,2.035898384862E0);\r\n#2895=CARTESIAN_POINT('',(2.26175E1,1.E0,1.2E1));\r\n#2896=LINE('',#2895,#2894);\r\n#2897=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2898=VECTOR('',#2897,2.035898384862E0);\r\n#2899=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1));\r\n#2900=LINE('',#2899,#2898);\r\n#2901=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1));\r\n#2902=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2903=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2904=AXIS2_PLACEMENT_3D('',#2901,#2902,#2903);\r\n#2906=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1));\r\n#2907=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2908=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2909=AXIS2_PLACEMENT_3D('',#2906,#2907,#2908);\r\n#2911=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1));\r\n#2912=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2913=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2914=AXIS2_PLACEMENT_3D('',#2911,#2912,#2913);\r\n#2916=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1));\r\n#2917=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2918=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2919=AXIS2_PLACEMENT_3D('',#2916,#2917,#2918);\r\n#2921=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2922=VECTOR('',#2921,1.E0);\r\n#2923=CARTESIAN_POINT('',(2.30675E1,1.E0,1.2E1));\r\n#2924=LINE('',#2923,#2922);\r\n#2925=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2926=VECTOR('',#2925,1.E0);\r\n#2927=CARTESIAN_POINT('',(2.26825E1,1.E0,1.2E1));\r\n#2928=LINE('',#2927,#2926);\r\n#2929=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2930=VECTOR('',#2929,5.E-1);\r\n#2931=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1));\r\n#2932=LINE('',#2931,#2930);\r\n#2933=CARTESIAN_POINT('',(2.185E1,6.65E0,9.5E0));\r\n#2934=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2935=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2936=AXIS2_PLACEMENT_3D('',#2933,#2934,#2935);\r\n#2938=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2939=VECTOR('',#2938,5.E-1);\r\n#2940=CARTESIAN_POINT('',(2.185E1,7.E0,1.E1));\r\n#2941=LINE('',#2940,#2939);\r\n#2942=CARTESIAN_POINT('',(2.185E1,6.65E0,1.E1));\r\n#2943=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2944=DIRECTION('',(1.015061051086E-14,1.E0,0.E0));\r\n#2945=AXIS2_PLACEMENT_3D('',#2942,#2943,#2944);\r\n#2947=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2948=VECTOR('',#2947,5.E-1);\r\n#2949=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0));\r\n#2950=LINE('',#2949,#2948);\r\n#2951=CARTESIAN_POINT('',(2.115E1,2.35E0,9.5E0));\r\n#2952=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2953=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#2954=AXIS2_PLACEMENT_3D('',#2951,#2952,#2953);\r\n#2956=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2957=VECTOR('',#2956,5.E-1);\r\n#2958=CARTESIAN_POINT('',(2.15E1,2.35E0,9.5E0));\r\n#2959=LINE('',#2958,#2957);\r\n#2960=CARTESIAN_POINT('',(2.115E1,2.35E0,1.E1));\r\n#2961=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2962=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#2963=AXIS2_PLACEMENT_3D('',#2960,#2961,#2962);\r\n#2965=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2966=VECTOR('',#2965,5.E-1);\r\n#2967=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0));\r\n#2968=LINE('',#2967,#2966);\r\n#2969=CARTESIAN_POINT('',(1.985E1,2.35E0,9.5E0));\r\n#2970=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2971=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2972=AXIS2_PLACEMENT_3D('',#2969,#2970,#2971);\r\n#2974=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2975=VECTOR('',#2974,5.E-1);\r\n#2976=CARTESIAN_POINT('',(1.985E1,2.E0,9.5E0));\r\n#2977=LINE('',#2976,#2975);\r\n#2978=CARTESIAN_POINT('',(1.985E1,2.35E0,1.E1));\r\n#2979=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2980=DIRECTION('',(1.015061051086E-14,-1.E0,0.E0));\r\n#2981=AXIS2_PLACEMENT_3D('',#2978,#2979,#2980);\r\n#2983=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2984=VECTOR('',#2983,5.E-1);\r\n#2985=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0));\r\n#2986=LINE('',#2985,#2984);\r\n#2987=CARTESIAN_POINT('',(1.985E1,9.15E0,9.5E0));\r\n#2988=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2989=DIRECTION('',(1.015061051086E-14,1.E0,0.E0));\r\n#2990=AXIS2_PLACEMENT_3D('',#2987,#2988,#2989);\r\n#2992=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#2993=VECTOR('',#2992,5.E-1);\r\n#2994=CARTESIAN_POINT('',(1.95E1,9.15E0,9.5E0));\r\n#2995=LINE('',#2994,#2993);\r\n#2996=CARTESIAN_POINT('',(1.985E1,9.15E0,1.E1));\r\n#2997=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#2998=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#2999=AXIS2_PLACEMENT_3D('',#2996,#2997,#2998);\r\n#3001=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3002=VECTOR('',#3001,5.E-1);\r\n#3003=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0));\r\n#3004=LINE('',#3003,#3002);\r\n#3005=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,9.5E0));\r\n#3006=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3007=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3008=AXIS2_PLACEMENT_3D('',#3005,#3006,#3007);\r\n#3010=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3011=VECTOR('',#3010,5.E-1);\r\n#3012=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,9.5E0));\r\n#3013=LINE('',#3012,#3011);\r\n#3014=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,1.E1));\r\n#3015=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3016=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3017=AXIS2_PLACEMENT_3D('',#3014,#3015,#3016);\r\n#3019=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3020=VECTOR('',#3019,5.E-1);\r\n#3021=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0));\r\n#3022=LINE('',#3021,#3020);\r\n#3023=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,9.5E0));\r\n#3024=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3025=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3026=AXIS2_PLACEMENT_3D('',#3023,#3024,#3025);\r\n#3028=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3029=VECTOR('',#3028,5.E-1);\r\n#3030=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,9.5E0));\r\n#3031=LINE('',#3030,#3029);\r\n#3032=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,1.E1));\r\n#3033=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3034=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3035=AXIS2_PLACEMENT_3D('',#3032,#3033,#3034);\r\n#3037=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3038=VECTOR('',#3037,1.972007605460E-1);\r\n#3039=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0));\r\n#3040=LINE('',#3039,#3038);\r\n#3041=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3042=VECTOR('',#3041,4.3E0);\r\n#3043=CARTESIAN_POINT('',(2.15E1,6.65E0,9.5E0));\r\n#3044=LINE('',#3043,#3042);\r\n#3045=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3046=VECTOR('',#3045,1.3E0);\r\n#3047=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0));\r\n#3048=LINE('',#3047,#3046);\r\n#3049=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3050=VECTOR('',#3049,6.8E0);\r\n#3051=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0));\r\n#3052=LINE('',#3051,#3050);\r\n#3053=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3054=VECTOR('',#3053,1.197200760546E0);\r\n#3055=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0));\r\n#3056=LINE('',#3055,#3054);\r\n#3057=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#3058=VECTOR('',#3057,2.059126028197E0);\r\n#3059=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0));\r\n#3060=LINE('',#3059,#3058);\r\n#3061=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3062=VECTOR('',#3061,2.5E-1);\r\n#3063=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.E0));\r\n#3064=LINE('',#3063,#3062);\r\n#3065=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3066=VECTOR('',#3065,2.5E-1);\r\n#3067=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.E0));\r\n#3068=LINE('',#3067,#3066);\r\n#3069=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0));\r\n#3070=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3071=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3072=AXIS2_PLACEMENT_3D('',#3069,#3070,#3071);\r\n#3074=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0));\r\n#3075=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3076=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3077=AXIS2_PLACEMENT_3D('',#3074,#3075,#3076);\r\n#3079=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3080=VECTOR('',#3079,2.5E-1);\r\n#3081=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.E0));\r\n#3082=LINE('',#3081,#3080);\r\n#3083=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3084=VECTOR('',#3083,2.5E-1);\r\n#3085=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.E0));\r\n#3086=LINE('',#3085,#3084);\r\n#3087=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0));\r\n#3088=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3089=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3090=AXIS2_PLACEMENT_3D('',#3087,#3088,#3089);\r\n#3092=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0));\r\n#3093=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3094=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3095=AXIS2_PLACEMENT_3D('',#3092,#3093,#3094);\r\n#3097=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3098=VECTOR('',#3097,2.5E-1);\r\n#3099=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.E0));\r\n#3100=LINE('',#3099,#3098);\r\n#3101=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3102=VECTOR('',#3101,2.5E-1);\r\n#3103=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.E0));\r\n#3104=LINE('',#3103,#3102);\r\n#3105=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0));\r\n#3106=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3107=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3108=AXIS2_PLACEMENT_3D('',#3105,#3106,#3107);\r\n#3110=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0));\r\n#3111=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3112=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3113=AXIS2_PLACEMENT_3D('',#3110,#3111,#3112);\r\n#3115=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3116=VECTOR('',#3115,2.5E-1);\r\n#3117=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.E0));\r\n#3118=LINE('',#3117,#3116);\r\n#3119=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3120=VECTOR('',#3119,2.5E-1);\r\n#3121=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.E0));\r\n#3122=LINE('',#3121,#3120);\r\n#3123=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0));\r\n#3124=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3125=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3126=AXIS2_PLACEMENT_3D('',#3123,#3124,#3125);\r\n#3128=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0));\r\n#3129=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3130=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3131=AXIS2_PLACEMENT_3D('',#3128,#3129,#3130);\r\n#3133=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3134=VECTOR('',#3133,2.5E-1);\r\n#3135=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.E0));\r\n#3136=LINE('',#3135,#3134);\r\n#3137=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3138=VECTOR('',#3137,2.5E-1);\r\n#3139=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.E0));\r\n#3140=LINE('',#3139,#3138);\r\n#3141=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0));\r\n#3142=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3143=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3144=AXIS2_PLACEMENT_3D('',#3141,#3142,#3143);\r\n#3146=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0));\r\n#3147=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3148=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3149=AXIS2_PLACEMENT_3D('',#3146,#3147,#3148);\r\n#3151=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3152=VECTOR('',#3151,5.E-1);\r\n#3153=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0));\r\n#3154=LINE('',#3153,#3152);\r\n#3155=CARTESIAN_POINT('',(3.75E0,2.75E0,8.E0));\r\n#3156=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3157=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3158=AXIS2_PLACEMENT_3D('',#3155,#3156,#3157);\r\n#3160=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3161=VECTOR('',#3160,5.E-1);\r\n#3162=CARTESIAN_POINT('',(4.5E0,2.75E0,8.E0));\r\n#3163=LINE('',#3162,#3161);\r\n#3164=CARTESIAN_POINT('',(3.75E0,2.75E0,8.5E0));\r\n#3165=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3166=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3167=AXIS2_PLACEMENT_3D('',#3164,#3165,#3166);\r\n#3169=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3170=VECTOR('',#3169,5.E-1);\r\n#3171=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0));\r\n#3172=LINE('',#3171,#3170);\r\n#3173=CARTESIAN_POINT('',(3.75E0,8.75E0,8.E0));\r\n#3174=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3175=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3176=AXIS2_PLACEMENT_3D('',#3173,#3174,#3175);\r\n#3178=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3179=VECTOR('',#3178,5.E-1);\r\n#3180=CARTESIAN_POINT('',(3.75E0,9.5E0,8.E0));\r\n#3181=LINE('',#3180,#3179);\r\n#3182=CARTESIAN_POINT('',(3.75E0,8.75E0,8.5E0));\r\n#3183=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3184=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3185=AXIS2_PLACEMENT_3D('',#3182,#3183,#3184);\r\n#3187=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3188=VECTOR('',#3187,5.E-1);\r\n#3189=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0));\r\n#3190=LINE('',#3189,#3188);\r\n#3191=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,8.E0));\r\n#3192=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3193=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3194=AXIS2_PLACEMENT_3D('',#3191,#3192,#3193);\r\n#3196=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3197=VECTOR('',#3196,5.E-1);\r\n#3198=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.E0));\r\n#3199=LINE('',#3198,#3197);\r\n#3200=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,8.5E0));\r\n#3201=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3202=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3203=AXIS2_PLACEMENT_3D('',#3200,#3201,#3202);\r\n#3205=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3206=VECTOR('',#3205,5.E-1);\r\n#3207=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0));\r\n#3208=LINE('',#3207,#3206);\r\n#3209=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,8.E0));\r\n#3210=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3211=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3212=AXIS2_PLACEMENT_3D('',#3209,#3210,#3211);\r\n#3214=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3215=VECTOR('',#3214,5.E-1);\r\n#3216=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.E0));\r\n#3217=LINE('',#3216,#3215);\r\n#3218=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,8.5E0));\r\n#3219=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3220=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3221=AXIS2_PLACEMENT_3D('',#3218,#3219,#3220);\r\n#3223=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3224=VECTOR('',#3223,6.E0);\r\n#3225=CARTESIAN_POINT('',(4.5E0,8.75E0,8.5E0));\r\n#3226=LINE('',#3225,#3224);\r\n#3227=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3228=VECTOR('',#3227,5.618394209466E-1);\r\n#3229=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.5E0));\r\n#3230=LINE('',#3229,#3228);\r\n#3231=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#3232=VECTOR('',#3231,6.863753427325E0);\r\n#3233=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.5E0));\r\n#3234=LINE('',#3233,#3232);\r\n#3235=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3236=VECTOR('',#3235,3.895172754280E0);\r\n#3237=CARTESIAN_POINT('',(3.75E0,2.E0,8.5E0));\r\n#3238=LINE('',#3237,#3236);\r\n#3239=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3240=VECTOR('',#3239,5.E-1);\r\n#3241=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0));\r\n#3242=LINE('',#3241,#3240);\r\n#3243=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.5E0));\r\n#3244=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3245=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3246=AXIS2_PLACEMENT_3D('',#3243,#3244,#3245);\r\n#3248=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3249=VECTOR('',#3248,5.E-1);\r\n#3250=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.5E0));\r\n#3251=LINE('',#3250,#3249);\r\n#3252=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.E0));\r\n#3253=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3254=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3255=AXIS2_PLACEMENT_3D('',#3252,#3253,#3254);\r\n#3257=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3258=VECTOR('',#3257,3.895172754280E0);\r\n#3259=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0));\r\n#3260=LINE('',#3259,#3258);\r\n#3261=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#3262=VECTOR('',#3261,6.863753427325E0);\r\n#3263=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0));\r\n#3264=LINE('',#3263,#3262);\r\n#3265=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3266=VECTOR('',#3265,5.618394209466E-1);\r\n#3267=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0));\r\n#3268=LINE('',#3267,#3266);\r\n#3269=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3270=VECTOR('',#3269,6.E0);\r\n#3271=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0));\r\n#3272=LINE('',#3271,#3270);\r\n#3273=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3274=VECTOR('',#3273,5.E-1);\r\n#3275=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0));\r\n#3276=LINE('',#3275,#3274);\r\n#3277=CARTESIAN_POINT('',(2.025E1,2.75E0,8.5E0));\r\n#3278=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3279=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3280=AXIS2_PLACEMENT_3D('',#3277,#3278,#3279);\r\n#3282=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3283=VECTOR('',#3282,5.E-1);\r\n#3284=CARTESIAN_POINT('',(1.95E1,2.75E0,8.5E0));\r\n#3285=LINE('',#3284,#3283);\r\n#3286=CARTESIAN_POINT('',(2.025E1,2.75E0,8.E0));\r\n#3287=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3288=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3289=AXIS2_PLACEMENT_3D('',#3286,#3287,#3288);\r\n#3291=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3292=VECTOR('',#3291,5.E-1);\r\n#3293=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0));\r\n#3294=LINE('',#3293,#3292);\r\n#3295=CARTESIAN_POINT('',(2.025E1,8.75E0,8.5E0));\r\n#3296=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3297=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3298=AXIS2_PLACEMENT_3D('',#3295,#3296,#3297);\r\n#3300=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3301=VECTOR('',#3300,5.E-1);\r\n#3302=CARTESIAN_POINT('',(2.025E1,9.5E0,8.5E0));\r\n#3303=LINE('',#3302,#3301);\r\n#3304=CARTESIAN_POINT('',(2.025E1,8.75E0,8.E0));\r\n#3305=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3306=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3307=AXIS2_PLACEMENT_3D('',#3304,#3305,#3306);\r\n#3309=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3310=VECTOR('',#3309,5.E-1);\r\n#3311=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0));\r\n#3312=LINE('',#3311,#3310);\r\n#3313=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.5E0));\r\n#3314=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3315=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3316=AXIS2_PLACEMENT_3D('',#3313,#3314,#3315);\r\n#3318=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3319=VECTOR('',#3318,5.E-1);\r\n#3320=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.5E0));\r\n#3321=LINE('',#3320,#3319);\r\n#3322=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.E0));\r\n#3323=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3324=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#3325=AXIS2_PLACEMENT_3D('',#3322,#3323,#3324);\r\n#3327=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3328=VECTOR('',#3327,6.875E-1);\r\n#3329=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1));\r\n#3330=LINE('',#3329,#3328);\r\n#3331=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3332=VECTOR('',#3331,6.875E-1);\r\n#3333=CARTESIAN_POINT('',(7.5E0,0.E0,1.8125E0));\r\n#3334=LINE('',#3333,#3332);\r\n#3335=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3336=VECTOR('',#3335,6.875E-1);\r\n#3337=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0));\r\n#3338=LINE('',#3337,#3336);\r\n#3339=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3340=VECTOR('',#3339,6.875E-1);\r\n#3341=CARTESIAN_POINT('',(1.05E1,0.E0,6.875E-1));\r\n#3342=LINE('',#3341,#3340);\r\n#3343=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3344=VECTOR('',#3343,3.E0);\r\n#3345=CARTESIAN_POINT('',(7.5E0,6.875E-1,6.875E-1));\r\n#3346=LINE('',#3345,#3344);\r\n#3347=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.25E0));\r\n#3348=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3349=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3350=AXIS2_PLACEMENT_3D('',#3347,#3348,#3349);\r\n#3352=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3353=VECTOR('',#3352,3.E0);\r\n#3354=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8125E0));\r\n#3355=LINE('',#3354,#3353);\r\n#3356=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.25E0));\r\n#3357=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3358=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3359=AXIS2_PLACEMENT_3D('',#3356,#3357,#3358);\r\n#3361=CARTESIAN_POINT('',(1.61E0,6.875E-1,4.5E0));\r\n#3362=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3363=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#3364=AXIS2_PLACEMENT_3D('',#3361,#3362,#3363);\r\n#3366=CARTESIAN_POINT('',(7.5E0,6.875E-1,7.5E0));\r\n#3367=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3368=DIRECTION('',(-4.496088413988E-1,0.E0,-8.932255536739E-1));\r\n#3369=AXIS2_PLACEMENT_3D('',#3366,#3367,#3368);\r\n#3371=CARTESIAN_POINT('',(4.553039342392E0,6.875E-1,1.645354088550E0));\r\n#3372=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3373=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3374=AXIS2_PLACEMENT_3D('',#3371,#3372,#3373);\r\n#3376=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3377=VECTOR('',#3376,4.263248410977E0);\r\n#3378=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,4.046865146430E0));\r\n#3379=LINE('',#3378,#3377);\r\n#3380=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3381=VECTOR('',#3380,6.875E-1);\r\n#3382=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0));\r\n#3383=LINE('',#3382,#3381);\r\n#3384=CARTESIAN_POINT('',(1.455736763592E0,0.E0,4.577195232320E0));\r\n#3385=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3386=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3387=AXIS2_PLACEMENT_3D('',#3384,#3385,#3386);\r\n#3389=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3390=VECTOR('',#3389,6.875E-1);\r\n#3391=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,4.912826677187E0));\r\n#3392=LINE('',#3391,#3390);\r\n#3393=CARTESIAN_POINT('',(1.455736763592E0,6.875E-1,4.577195232320E0));\r\n#3394=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3395=DIRECTION('',(-8.942796313519E-1,0.E0,4.475085931567E-1));\r\n#3396=AXIS2_PLACEMENT_3D('',#3393,#3394,#3395);\r\n#3398=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3399=VECTOR('',#3398,6.875E-1);\r\n#3400=CARTESIAN_POINT('',(3.939978538987E0,0.E0,1.032293285145E0));\r\n#3401=LINE('',#3400,#3399);\r\n#3402=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3403=VECTOR('',#3402,6.875E-1);\r\n#3404=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.419779663480E0));\r\n#3405=LINE('',#3404,#3403);\r\n#3406=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3407=VECTOR('',#3406,6.875E-1);\r\n#3408=CARTESIAN_POINT('',(2.432015885023E0,0.E0,4.918683812405E0));\r\n#3409=LINE('',#3408,#3407);\r\n#3410=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3411=VECTOR('',#3410,6.875E-1);\r\n#3412=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0));\r\n#3413=LINE('',#3412,#3411);\r\n#3414=CARTESIAN_POINT('',(-1.85E-1,0.E0,7.815E0));\r\n#3415=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3416=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3417=AXIS2_PLACEMENT_3D('',#3414,#3415,#3416);\r\n#3419=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3420=VECTOR('',#3419,6.875E-1);\r\n#3421=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,8.69E0));\r\n#3422=LINE('',#3421,#3420);\r\n#3423=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,7.815E0));\r\n#3424=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3425=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3426=AXIS2_PLACEMENT_3D('',#3423,#3424,#3425);\r\n#3428=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3429=VECTOR('',#3428,7.5E-1);\r\n#3430=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0));\r\n#3431=LINE('',#3430,#3429);\r\n#3432=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3433=VECTOR('',#3432,3.15E-1);\r\n#3434=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.5E0));\r\n#3435=LINE('',#3434,#3433);\r\n#3436=CARTESIAN_POINT('',(1.25125E0,6.875E-1,7.5E0));\r\n#3437=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3438=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3439=AXIS2_PLACEMENT_3D('',#3436,#3437,#3438);\r\n#3441=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3442=VECTOR('',#3441,3.15E-1);\r\n#3443=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0));\r\n#3444=LINE('',#3443,#3442);\r\n#3445=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3446=VECTOR('',#3445,2.525E-1);\r\n#3447=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,8.69E0));\r\n#3448=LINE('',#3447,#3446);\r\n#3449=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3450=VECTOR('',#3449,8.1E-1);\r\n#3451=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,1.0375E1));\r\n#3452=LINE('',#3451,#3450);\r\n#3453=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3454=VECTOR('',#3453,3.875E0);\r\n#3455=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.125E1));\r\n#3456=LINE('',#3455,#3454);\r\n#3457=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3458=VECTOR('',#3457,8.1E-1);\r\n#3459=CARTESIAN_POINT('',(4.3125E0,6.875E-1,9.565E0));\r\n#3460=LINE('',#3459,#3458);\r\n#3461=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3462=VECTOR('',#3461,6.875E-1);\r\n#3463=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0));\r\n#3464=LINE('',#3463,#3462);\r\n#3465=CARTESIAN_POINT('',(2.6875E0,0.E0,7.815E0));\r\n#3466=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3467=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3468=AXIS2_PLACEMENT_3D('',#3465,#3466,#3467);\r\n#3470=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3471=VECTOR('',#3470,6.875E-1);\r\n#3472=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.815E0));\r\n#3473=LINE('',#3472,#3471);\r\n#3474=CARTESIAN_POINT('',(2.6875E0,6.875E-1,7.815E0));\r\n#3475=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3476=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3477=AXIS2_PLACEMENT_3D('',#3474,#3475,#3476);\r\n#3479=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3480=VECTOR('',#3479,6.875E-1);\r\n#3481=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0));\r\n#3482=LINE('',#3481,#3480);\r\n#3483=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3484=VECTOR('',#3483,6.875E-1);\r\n#3485=CARTESIAN_POINT('',(6.9E-1,0.E0,7.5E0));\r\n#3486=LINE('',#3485,#3484);\r\n#3487=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3488=VECTOR('',#3487,6.875E-1);\r\n#3489=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0));\r\n#3490=LINE('',#3489,#3488);\r\n#3491=CARTESIAN_POINT('',(3.4375E0,0.E0,9.565E0));\r\n#3492=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3493=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3494=AXIS2_PLACEMENT_3D('',#3491,#3492,#3493);\r\n#3496=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3497=VECTOR('',#3496,6.875E-1);\r\n#3498=CARTESIAN_POINT('',(3.4375E0,0.E0,8.69E0));\r\n#3499=LINE('',#3498,#3497);\r\n#3500=CARTESIAN_POINT('',(3.4375E0,6.875E-1,9.565E0));\r\n#3501=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3502=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3503=AXIS2_PLACEMENT_3D('',#3500,#3501,#3502);\r\n#3505=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3506=VECTOR('',#3505,6.875E-1);\r\n#3507=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1));\r\n#3508=LINE('',#3507,#3506);\r\n#3509=CARTESIAN_POINT('',(3.4375E0,0.E0,1.0375E1));\r\n#3510=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3511=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3512=AXIS2_PLACEMENT_3D('',#3509,#3510,#3511);\r\n#3514=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3515=VECTOR('',#3514,6.875E-1);\r\n#3516=CARTESIAN_POINT('',(4.3125E0,0.E0,1.0375E1));\r\n#3517=LINE('',#3516,#3515);\r\n#3518=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.0375E1));\r\n#3519=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3520=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3521=AXIS2_PLACEMENT_3D('',#3518,#3519,#3520);\r\n#3523=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3524=VECTOR('',#3523,6.875E-1);\r\n#3525=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1));\r\n#3526=LINE('',#3525,#3524);\r\n#3527=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.0375E1));\r\n#3528=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3529=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3530=AXIS2_PLACEMENT_3D('',#3527,#3528,#3529);\r\n#3532=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3533=VECTOR('',#3532,6.875E-1);\r\n#3534=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.125E1));\r\n#3535=LINE('',#3534,#3533);\r\n#3536=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,1.0375E1));\r\n#3537=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3538=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3539=AXIS2_PLACEMENT_3D('',#3536,#3537,#3538);\r\n#3541=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3542=VECTOR('',#3541,6.875E-1);\r\n#3543=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0));\r\n#3544=LINE('',#3543,#3542);\r\n#3545=CARTESIAN_POINT('',(-4.375E-1,0.E0,9.565E0));\r\n#3546=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3547=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3548=AXIS2_PLACEMENT_3D('',#3545,#3546,#3547);\r\n#3550=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3551=VECTOR('',#3550,6.875E-1);\r\n#3552=CARTESIAN_POINT('',(-1.3125E0,0.E0,9.565E0));\r\n#3553=LINE('',#3552,#3551);\r\n#3554=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,9.565E0));\r\n#3555=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3556=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3557=AXIS2_PLACEMENT_3D('',#3554,#3555,#3556);\r\n#3559=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3560=VECTOR('',#3559,6.875E-1);\r\n#3561=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1));\r\n#3562=LINE('',#3561,#3560);\r\n#3563=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3564=VECTOR('',#3563,6.875E-1);\r\n#3565=CARTESIAN_POINT('',(1.8125E0,0.E0,1.65E1));\r\n#3566=LINE('',#3565,#3564);\r\n#3567=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3568=VECTOR('',#3567,6.875E-1);\r\n#3569=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1));\r\n#3570=LINE('',#3569,#3568);\r\n#3571=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3572=VECTOR('',#3571,6.875E-1);\r\n#3573=CARTESIAN_POINT('',(6.875E-1,0.E0,1.35E1));\r\n#3574=LINE('',#3573,#3572);\r\n#3575=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3576=VECTOR('',#3575,3.E0);\r\n#3577=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.65E1));\r\n#3578=LINE('',#3577,#3576);\r\n#3579=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.65E1));\r\n#3580=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3581=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3582=AXIS2_PLACEMENT_3D('',#3579,#3580,#3581);\r\n#3584=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3585=VECTOR('',#3584,3.E0);\r\n#3586=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.35E1));\r\n#3587=LINE('',#3586,#3585);\r\n#3588=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.35E1));\r\n#3589=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3590=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3591=AXIS2_PLACEMENT_3D('',#3588,#3589,#3590);\r\n#3593=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3594=VECTOR('',#3593,6.875E-1);\r\n#3595=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1));\r\n#3596=LINE('',#3595,#3594);\r\n#3597=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3598=VECTOR('',#3597,6.875E-1);\r\n#3599=CARTESIAN_POINT('',(1.8125E0,0.E0,2.25E1));\r\n#3600=LINE('',#3599,#3598);\r\n#3601=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3602=VECTOR('',#3601,6.875E-1);\r\n#3603=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1));\r\n#3604=LINE('',#3603,#3602);\r\n#3605=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3606=VECTOR('',#3605,6.875E-1);\r\n#3607=CARTESIAN_POINT('',(6.875E-1,0.E0,1.95E1));\r\n#3608=LINE('',#3607,#3606);\r\n#3609=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3610=VECTOR('',#3609,3.E0);\r\n#3611=CARTESIAN_POINT('',(6.875E-1,6.875E-1,2.25E1));\r\n#3612=LINE('',#3611,#3610);\r\n#3613=CARTESIAN_POINT('',(1.25E0,6.875E-1,2.25E1));\r\n#3614=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3615=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3616=AXIS2_PLACEMENT_3D('',#3613,#3614,#3615);\r\n#3618=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3619=VECTOR('',#3618,3.E0);\r\n#3620=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.95E1));\r\n#3621=LINE('',#3620,#3619);\r\n#3622=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.95E1));\r\n#3623=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3624=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3625=AXIS2_PLACEMENT_3D('',#3622,#3623,#3624);\r\n#3627=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3628=VECTOR('',#3627,6.875E-1);\r\n#3629=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0));\r\n#3630=LINE('',#3629,#3628);\r\n#3631=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3632=VECTOR('',#3631,6.875E-1);\r\n#3633=CARTESIAN_POINT('',(7.5E0,0.E0,9.5E0));\r\n#3634=LINE('',#3633,#3632);\r\n#3635=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3636=VECTOR('',#3635,6.875E-1);\r\n#3637=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0));\r\n#3638=LINE('',#3637,#3636);\r\n#3639=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3640=VECTOR('',#3639,6.875E-1);\r\n#3641=CARTESIAN_POINT('',(1.05E1,0.E0,8.5E0));\r\n#3642=LINE('',#3641,#3640);\r\n#3643=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3644=VECTOR('',#3643,3.E0);\r\n#3645=CARTESIAN_POINT('',(7.5E0,6.875E-1,8.5E0));\r\n#3646=LINE('',#3645,#3644);\r\n#3647=CARTESIAN_POINT('',(7.5E0,6.875E-1,9.E0));\r\n#3648=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3649=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3650=AXIS2_PLACEMENT_3D('',#3647,#3648,#3649);\r\n#3652=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3653=VECTOR('',#3652,3.E0);\r\n#3654=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.5E0));\r\n#3655=LINE('',#3654,#3653);\r\n#3656=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.E0));\r\n#3657=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3658=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3659=AXIS2_PLACEMENT_3D('',#3656,#3657,#3658);\r\n#3661=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3662=VECTOR('',#3661,6.875E-1);\r\n#3663=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1));\r\n#3664=LINE('',#3663,#3662);\r\n#3665=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3666=VECTOR('',#3665,6.875E-1);\r\n#3667=CARTESIAN_POINT('',(7.5E0,0.E0,1.84375E1));\r\n#3668=LINE('',#3667,#3666);\r\n#3669=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3670=VECTOR('',#3669,6.875E-1);\r\n#3671=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1));\r\n#3672=LINE('',#3671,#3670);\r\n#3673=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3674=VECTOR('',#3673,6.875E-1);\r\n#3675=CARTESIAN_POINT('',(1.05E1,0.E0,1.75625E1));\r\n#3676=LINE('',#3675,#3674);\r\n#3677=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3678=VECTOR('',#3677,3.E0);\r\n#3679=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.75625E1));\r\n#3680=LINE('',#3679,#3678);\r\n#3681=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.8E1));\r\n#3682=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3683=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3684=AXIS2_PLACEMENT_3D('',#3681,#3682,#3683);\r\n#3686=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3687=VECTOR('',#3686,3.E0);\r\n#3688=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.84375E1));\r\n#3689=LINE('',#3688,#3687);\r\n#3690=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8E1));\r\n#3691=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3692=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3693=AXIS2_PLACEMENT_3D('',#3690,#3691,#3692);\r\n#3695=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3696=VECTOR('',#3695,6.875E-1);\r\n#3697=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1));\r\n#3698=LINE('',#3697,#3696);\r\n#3699=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3700=VECTOR('',#3699,6.875E-1);\r\n#3701=CARTESIAN_POINT('',(1.05E1,0.E0,3.13125E1));\r\n#3702=LINE('',#3701,#3700);\r\n#3703=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3704=VECTOR('',#3703,6.875E-1);\r\n#3705=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1));\r\n#3706=LINE('',#3705,#3704);\r\n#3707=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3708=VECTOR('',#3707,6.875E-1);\r\n#3709=CARTESIAN_POINT('',(7.5E0,0.E0,3.01875E1));\r\n#3710=LINE('',#3709,#3708);\r\n#3711=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3712=VECTOR('',#3711,3.E0);\r\n#3713=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.13125E1));\r\n#3714=LINE('',#3713,#3712);\r\n#3715=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.075E1));\r\n#3716=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3717=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3718=AXIS2_PLACEMENT_3D('',#3715,#3716,#3717);\r\n#3720=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3721=VECTOR('',#3720,3.E0);\r\n#3722=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.01875E1));\r\n#3723=LINE('',#3722,#3721);\r\n#3724=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.075E1));\r\n#3725=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3726=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3727=AXIS2_PLACEMENT_3D('',#3724,#3725,#3726);\r\n#3729=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#3730=VECTOR('',#3729,4.263248410977E0);\r\n#3731=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,2.795313485357E1));\r\n#3732=LINE('',#3731,#3730);\r\n#3733=CARTESIAN_POINT('',(4.553039342392E0,6.875E-1,3.035464591145E1));\r\n#3734=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3735=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#3736=AXIS2_PLACEMENT_3D('',#3733,#3734,#3735);\r\n#3738=CARTESIAN_POINT('',(7.5E0,6.875E-1,2.45E1));\r\n#3739=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3740=DIRECTION('',(-4.496088413988E-1,0.E0,8.932255536739E-1));\r\n#3741=AXIS2_PLACEMENT_3D('',#3738,#3739,#3740);\r\n#3743=CARTESIAN_POINT('',(1.61E0,6.875E-1,2.75E1));\r\n#3744=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3745=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#3746=AXIS2_PLACEMENT_3D('',#3743,#3744,#3745);\r\n#3748=DIRECTION('',(0.E0,1.E0,-1.033516706560E-14));\r\n#3749=VECTOR('',#3748,6.875E-1);\r\n#3750=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,2.708717332281E1));\r\n#3751=LINE('',#3750,#3749);\r\n#3752=CARTESIAN_POINT('',(1.455736763592E0,0.E0,2.742280476768E1));\r\n#3753=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3754=DIRECTION('',(-8.942796313519E-1,0.E0,-4.475085931567E-1));\r\n#3755=AXIS2_PLACEMENT_3D('',#3752,#3753,#3754);\r\n#3757=DIRECTION('',(0.E0,1.E0,1.033516706560E-14));\r\n#3758=VECTOR('',#3757,6.875E-1);\r\n#3759=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1));\r\n#3760=LINE('',#3759,#3758);\r\n#3761=CARTESIAN_POINT('',(1.455736763592E0,6.875E-1,2.742280476768E1));\r\n#3762=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3763=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811866E-1));\r\n#3764=AXIS2_PLACEMENT_3D('',#3761,#3762,#3763);\r\n#3766=DIRECTION('',(0.E0,1.E0,1.033516706560E-14));\r\n#3767=VECTOR('',#3766,6.875E-1);\r\n#3768=CARTESIAN_POINT('',(2.432015885023E0,0.E0,2.708131618759E1));\r\n#3769=LINE('',#3768,#3767);\r\n#3770=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3771=VECTOR('',#3770,6.875E-1);\r\n#3772=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.958022033652E1));\r\n#3773=LINE('',#3772,#3771);\r\n#3774=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3775=VECTOR('',#3774,6.875E-1);\r\n#3776=CARTESIAN_POINT('',(3.939978538987E0,0.E0,3.096770671486E1));\r\n#3777=LINE('',#3776,#3775);\r\n#3778=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3779=VECTOR('',#3778,6.875E-1);\r\n#3780=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1));\r\n#3781=LINE('',#3780,#3779);\r\n#3782=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3783=VECTOR('',#3782,6.875E-1);\r\n#3784=CARTESIAN_POINT('',(1.35E1,0.E0,6.875E-1));\r\n#3785=LINE('',#3784,#3783);\r\n#3786=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3787=VECTOR('',#3786,6.875E-1);\r\n#3788=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0));\r\n#3789=LINE('',#3788,#3787);\r\n#3790=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3791=VECTOR('',#3790,6.875E-1);\r\n#3792=CARTESIAN_POINT('',(1.65E1,0.E0,1.8125E0));\r\n#3793=LINE('',#3792,#3791);\r\n#3794=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3795=VECTOR('',#3794,3.E0);\r\n#3796=CARTESIAN_POINT('',(1.65E1,6.875E-1,6.875E-1));\r\n#3797=LINE('',#3796,#3795);\r\n#3798=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.25E0));\r\n#3799=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3800=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3801=AXIS2_PLACEMENT_3D('',#3798,#3799,#3800);\r\n#3803=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3804=VECTOR('',#3803,3.E0);\r\n#3805=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8125E0));\r\n#3806=LINE('',#3805,#3804);\r\n#3807=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.25E0));\r\n#3808=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3809=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3810=AXIS2_PLACEMENT_3D('',#3807,#3808,#3809);\r\n#3812=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3813=VECTOR('',#3812,4.263248410977E0);\r\n#3814=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,4.046865146430E0));\r\n#3815=LINE('',#3814,#3813);\r\n#3816=CARTESIAN_POINT('',(1.944696065761E1,6.875E-1,1.645354088550E0));\r\n#3817=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3818=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3819=AXIS2_PLACEMENT_3D('',#3816,#3817,#3818);\r\n#3821=CARTESIAN_POINT('',(1.65E1,6.875E-1,7.5E0));\r\n#3822=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3823=DIRECTION('',(4.496088413988E-1,0.E0,-8.932255536739E-1));\r\n#3824=AXIS2_PLACEMENT_3D('',#3821,#3822,#3823);\r\n#3826=CARTESIAN_POINT('',(2.239E1,6.875E-1,4.5E0));\r\n#3827=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3828=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1));\r\n#3829=AXIS2_PLACEMENT_3D('',#3826,#3827,#3828);\r\n#3831=DIRECTION('',(-1.033516706560E-14,1.E0,2.583791766400E-14));\r\n#3832=VECTOR('',#3831,6.875E-1);\r\n#3833=CARTESIAN_POINT('',(2.321497295992E1,0.E0,4.912826677187E0));\r\n#3834=LINE('',#3833,#3832);\r\n#3835=CARTESIAN_POINT('',(2.254426323641E1,0.E0,4.577195232320E0));\r\n#3836=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3837=DIRECTION('',(8.942796313519E-1,0.E0,4.475085931567E-1));\r\n#3838=AXIS2_PLACEMENT_3D('',#3835,#3836,#3837);\r\n#3840=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3841=VECTOR('',#3840,6.875E-1);\r\n#3842=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0));\r\n#3843=LINE('',#3842,#3841);\r\n#3844=CARTESIAN_POINT('',(2.254426323641E1,6.875E-1,4.577195232320E0));\r\n#3845=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#3846=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#3847=AXIS2_PLACEMENT_3D('',#3844,#3845,#3846);\r\n#3849=DIRECTION('',(-1.550275059840E-14,1.E0,-2.067033413120E-14));\r\n#3850=VECTOR('',#3849,6.875E-1);\r\n#3851=CARTESIAN_POINT('',(2.156798411498E1,0.E0,4.918683812405E0));\r\n#3852=LINE('',#3851,#3850);\r\n#3853=DIRECTION('',(1.550275059840E-14,1.E0,0.E0));\r\n#3854=VECTOR('',#3853,6.875E-1);\r\n#3855=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.419779663480E0));\r\n#3856=LINE('',#3855,#3854);\r\n#3857=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3858=VECTOR('',#3857,6.875E-1);\r\n#3859=CARTESIAN_POINT('',(2.006002146101E1,0.E0,1.032293285145E0));\r\n#3860=LINE('',#3859,#3858);\r\n#3861=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3862=VECTOR('',#3861,6.875E-1);\r\n#3863=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1));\r\n#3864=LINE('',#3863,#3862);\r\n#3865=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3866=VECTOR('',#3865,6.875E-1);\r\n#3867=CARTESIAN_POINT('',(2.33125E1,0.E0,1.35E1));\r\n#3868=LINE('',#3867,#3866);\r\n#3869=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3870=VECTOR('',#3869,6.875E-1);\r\n#3871=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1));\r\n#3872=LINE('',#3871,#3870);\r\n#3873=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3874=VECTOR('',#3873,6.875E-1);\r\n#3875=CARTESIAN_POINT('',(2.21875E1,0.E0,1.65E1));\r\n#3876=LINE('',#3875,#3874);\r\n#3877=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3878=VECTOR('',#3877,3.E0);\r\n#3879=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.65E1));\r\n#3880=LINE('',#3879,#3878);\r\n#3881=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.35E1));\r\n#3882=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3883=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3884=AXIS2_PLACEMENT_3D('',#3881,#3882,#3883);\r\n#3886=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3887=VECTOR('',#3886,3.E0);\r\n#3888=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.35E1));\r\n#3889=LINE('',#3888,#3887);\r\n#3890=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.65E1));\r\n#3891=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3892=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3893=AXIS2_PLACEMENT_3D('',#3890,#3891,#3892);\r\n#3895=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3896=VECTOR('',#3895,6.875E-1);\r\n#3897=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1));\r\n#3898=LINE('',#3897,#3896);\r\n#3899=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3900=VECTOR('',#3899,6.875E-1);\r\n#3901=CARTESIAN_POINT('',(2.33125E1,0.E0,1.95E1));\r\n#3902=LINE('',#3901,#3900);\r\n#3903=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3904=VECTOR('',#3903,6.875E-1);\r\n#3905=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1));\r\n#3906=LINE('',#3905,#3904);\r\n#3907=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3908=VECTOR('',#3907,6.875E-1);\r\n#3909=CARTESIAN_POINT('',(2.21875E1,0.E0,2.25E1));\r\n#3910=LINE('',#3909,#3908);\r\n#3911=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3912=VECTOR('',#3911,3.E0);\r\n#3913=CARTESIAN_POINT('',(2.33125E1,6.875E-1,2.25E1));\r\n#3914=LINE('',#3913,#3912);\r\n#3915=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.95E1));\r\n#3916=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3917=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3918=AXIS2_PLACEMENT_3D('',#3915,#3916,#3917);\r\n#3920=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3921=VECTOR('',#3920,3.E0);\r\n#3922=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.95E1));\r\n#3923=LINE('',#3922,#3921);\r\n#3924=CARTESIAN_POINT('',(2.275E1,6.875E-1,2.25E1));\r\n#3925=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3926=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3927=AXIS2_PLACEMENT_3D('',#3924,#3925,#3926);\r\n#3929=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3930=VECTOR('',#3929,6.875E-1);\r\n#3931=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0));\r\n#3932=LINE('',#3931,#3930);\r\n#3933=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3934=VECTOR('',#3933,6.875E-1);\r\n#3935=CARTESIAN_POINT('',(1.35E1,0.E0,8.5E0));\r\n#3936=LINE('',#3935,#3934);\r\n#3937=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3938=VECTOR('',#3937,6.875E-1);\r\n#3939=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0));\r\n#3940=LINE('',#3939,#3938);\r\n#3941=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3942=VECTOR('',#3941,6.875E-1);\r\n#3943=CARTESIAN_POINT('',(1.65E1,0.E0,9.5E0));\r\n#3944=LINE('',#3943,#3942);\r\n#3945=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3946=VECTOR('',#3945,3.E0);\r\n#3947=CARTESIAN_POINT('',(1.65E1,6.875E-1,8.5E0));\r\n#3948=LINE('',#3947,#3946);\r\n#3949=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.E0));\r\n#3950=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3951=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3952=AXIS2_PLACEMENT_3D('',#3949,#3950,#3951);\r\n#3954=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3955=VECTOR('',#3954,3.E0);\r\n#3956=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.5E0));\r\n#3957=LINE('',#3956,#3955);\r\n#3958=CARTESIAN_POINT('',(1.65E1,6.875E-1,9.E0));\r\n#3959=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3960=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3961=AXIS2_PLACEMENT_3D('',#3958,#3959,#3960);\r\n#3963=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3964=VECTOR('',#3963,6.875E-1);\r\n#3965=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1));\r\n#3966=LINE('',#3965,#3964);\r\n#3967=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3968=VECTOR('',#3967,6.875E-1);\r\n#3969=CARTESIAN_POINT('',(1.35E1,0.E0,1.75625E1));\r\n#3970=LINE('',#3969,#3968);\r\n#3971=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3972=VECTOR('',#3971,6.875E-1);\r\n#3973=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1));\r\n#3974=LINE('',#3973,#3972);\r\n#3975=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3976=VECTOR('',#3975,6.875E-1);\r\n#3977=CARTESIAN_POINT('',(1.65E1,0.E0,1.84375E1));\r\n#3978=LINE('',#3977,#3976);\r\n#3979=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#3980=VECTOR('',#3979,3.E0);\r\n#3981=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.75625E1));\r\n#3982=LINE('',#3981,#3980);\r\n#3983=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8E1));\r\n#3984=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3985=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#3986=AXIS2_PLACEMENT_3D('',#3983,#3984,#3985);\r\n#3988=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#3989=VECTOR('',#3988,3.E0);\r\n#3990=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.84375E1));\r\n#3991=LINE('',#3990,#3989);\r\n#3992=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.8E1));\r\n#3993=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3994=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#3995=AXIS2_PLACEMENT_3D('',#3992,#3993,#3994);\r\n#3997=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#3998=VECTOR('',#3997,6.875E-1);\r\n#3999=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1));\r\n#4000=LINE('',#3999,#3998);\r\n#4001=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4002=VECTOR('',#4001,6.875E-1);\r\n#4003=CARTESIAN_POINT('',(1.65E1,0.E0,3.01875E1));\r\n#4004=LINE('',#4003,#4002);\r\n#4005=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4006=VECTOR('',#4005,6.875E-1);\r\n#4007=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1));\r\n#4008=LINE('',#4007,#4006);\r\n#4009=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4010=VECTOR('',#4009,6.875E-1);\r\n#4011=CARTESIAN_POINT('',(1.35E1,0.E0,3.13125E1));\r\n#4012=LINE('',#4011,#4010);\r\n#4013=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4014=VECTOR('',#4013,3.E0);\r\n#4015=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.13125E1));\r\n#4016=LINE('',#4015,#4014);\r\n#4017=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.075E1));\r\n#4018=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4019=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#4020=AXIS2_PLACEMENT_3D('',#4017,#4018,#4019);\r\n#4022=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4023=VECTOR('',#4022,3.E0);\r\n#4024=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.01875E1));\r\n#4025=LINE('',#4024,#4023);\r\n#4026=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.075E1));\r\n#4027=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4028=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4029=AXIS2_PLACEMENT_3D('',#4026,#4027,#4028);\r\n#4031=CARTESIAN_POINT('',(2.239E1,6.875E-1,2.75E1));\r\n#4032=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4033=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1));\r\n#4034=AXIS2_PLACEMENT_3D('',#4031,#4032,#4033);\r\n#4036=CARTESIAN_POINT('',(1.65E1,6.875E-1,2.45E1));\r\n#4037=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4038=DIRECTION('',(4.496088413988E-1,0.E0,8.932255536739E-1));\r\n#4039=AXIS2_PLACEMENT_3D('',#4036,#4037,#4038);\r\n#4041=CARTESIAN_POINT('',(1.944696065761E1,6.875E-1,3.035464591145E1));\r\n#4042=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4043=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#4044=AXIS2_PLACEMENT_3D('',#4041,#4042,#4043);\r\n#4046=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#4047=VECTOR('',#4046,4.263248410977E0);\r\n#4048=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,2.795313485357E1));\r\n#4049=LINE('',#4048,#4047);\r\n#4050=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4051=VECTOR('',#4050,6.875E-1);\r\n#4052=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1));\r\n#4053=LINE('',#4052,#4051);\r\n#4054=CARTESIAN_POINT('',(2.254426323641E1,0.E0,2.742280476768E1));\r\n#4055=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4056=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#4057=AXIS2_PLACEMENT_3D('',#4054,#4055,#4056);\r\n#4059=DIRECTION('',(0.E0,1.E0,2.067033413120E-14));\r\n#4060=VECTOR('',#4059,6.875E-1);\r\n#4061=CARTESIAN_POINT('',(2.321497295992E1,0.E0,2.708717332281E1));\r\n#4062=LINE('',#4061,#4060);\r\n#4063=CARTESIAN_POINT('',(2.254426323641E1,6.875E-1,2.742280476768E1));\r\n#4064=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4065=DIRECTION('',(8.942796313519E-1,0.E0,-4.475085931567E-1));\r\n#4066=AXIS2_PLACEMENT_3D('',#4063,#4064,#4065);\r\n#4068=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4069=VECTOR('',#4068,6.875E-1);\r\n#4070=CARTESIAN_POINT('',(2.006002146101E1,0.E0,3.096770671486E1));\r\n#4071=LINE('',#4070,#4069);\r\n#4072=DIRECTION('',(1.033516706560E-14,1.E0,0.E0));\r\n#4073=VECTOR('',#4072,6.875E-1);\r\n#4074=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.958022033652E1));\r\n#4075=LINE('',#4074,#4073);\r\n#4076=DIRECTION('',(-2.067033413120E-14,1.E0,3.100550119680E-14));\r\n#4077=VECTOR('',#4076,6.875E-1);\r\n#4078=CARTESIAN_POINT('',(2.156798411498E1,0.E0,2.708131618759E1));\r\n#4079=LINE('',#4078,#4077);\r\n#4080=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4081=VECTOR('',#4080,6.875E-1);\r\n#4082=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0));\r\n#4083=LINE('',#4082,#4081);\r\n#4084=CARTESIAN_POINT('',(2.13075E1,6.875E-1,7.81E0));\r\n#4085=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4086=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4087=AXIS2_PLACEMENT_3D('',#4084,#4085,#4086);\r\n#4089=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4090=VECTOR('',#4089,6.875E-1);\r\n#4091=CARTESIAN_POINT('',(2.21875E1,0.E0,7.81E0));\r\n#4092=LINE('',#4091,#4090);\r\n#4093=CARTESIAN_POINT('',(2.13075E1,0.E0,7.81E0));\r\n#4094=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4095=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4096=AXIS2_PLACEMENT_3D('',#4093,#4094,#4095);\r\n#4098=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4099=VECTOR('',#4098,6.875E-1);\r\n#4100=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0));\r\n#4101=LINE('',#4100,#4099);\r\n#4102=CARTESIAN_POINT('',(2.05675E1,6.875E-1,9.57E0));\r\n#4103=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4104=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4105=AXIS2_PLACEMENT_3D('',#4102,#4103,#4104);\r\n#4107=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4108=VECTOR('',#4107,6.875E-1);\r\n#4109=CARTESIAN_POINT('',(2.05675E1,6.875E-1,8.69E0));\r\n#4110=LINE('',#4109,#4108);\r\n#4111=CARTESIAN_POINT('',(2.05675E1,0.E0,9.57E0));\r\n#4112=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4113=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#4114=AXIS2_PLACEMENT_3D('',#4111,#4112,#4113);\r\n#4116=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4117=VECTOR('',#4116,6.875E-1);\r\n#4118=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1));\r\n#4119=LINE('',#4118,#4117);\r\n#4120=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.037E1));\r\n#4121=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4122=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4123=AXIS2_PLACEMENT_3D('',#4120,#4121,#4122);\r\n#4125=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4126=VECTOR('',#4125,6.875E-1);\r\n#4127=CARTESIAN_POINT('',(1.96875E1,6.875E-1,1.037E1));\r\n#4128=LINE('',#4127,#4126);\r\n#4129=CARTESIAN_POINT('',(2.05675E1,0.E0,1.037E1));\r\n#4130=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4131=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4132=AXIS2_PLACEMENT_3D('',#4129,#4130,#4131);\r\n#4134=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4135=VECTOR('',#4134,6.875E-1);\r\n#4136=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1));\r\n#4137=LINE('',#4136,#4135);\r\n#4138=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.037E1));\r\n#4139=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4140=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4141=AXIS2_PLACEMENT_3D('',#4138,#4139,#4140);\r\n#4143=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4144=VECTOR('',#4143,6.875E-1);\r\n#4145=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.125E1));\r\n#4146=LINE('',#4145,#4144);\r\n#4147=CARTESIAN_POINT('',(2.44325E1,0.E0,1.037E1));\r\n#4148=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4149=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4150=AXIS2_PLACEMENT_3D('',#4147,#4148,#4149);\r\n#4152=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4153=VECTOR('',#4152,6.875E-1);\r\n#4154=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0));\r\n#4155=LINE('',#4154,#4153);\r\n#4156=CARTESIAN_POINT('',(2.44325E1,6.875E-1,9.57E0));\r\n#4157=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4158=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#4159=AXIS2_PLACEMENT_3D('',#4156,#4157,#4158);\r\n#4161=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4162=VECTOR('',#4161,6.875E-1);\r\n#4163=CARTESIAN_POINT('',(2.53125E1,6.875E-1,9.57E0));\r\n#4164=LINE('',#4163,#4162);\r\n#4165=CARTESIAN_POINT('',(2.44325E1,0.E0,9.57E0));\r\n#4166=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4167=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4168=AXIS2_PLACEMENT_3D('',#4165,#4166,#4167);\r\n#4170=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4171=VECTOR('',#4170,6.875E-1);\r\n#4172=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0));\r\n#4173=LINE('',#4172,#4171);\r\n#4174=CARTESIAN_POINT('',(2.419E1,6.875E-1,7.81E0));\r\n#4175=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4176=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4177=AXIS2_PLACEMENT_3D('',#4174,#4175,#4176);\r\n#4179=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4180=VECTOR('',#4179,6.875E-1);\r\n#4181=CARTESIAN_POINT('',(2.419E1,0.E0,8.69E0));\r\n#4182=LINE('',#4181,#4180);\r\n#4183=CARTESIAN_POINT('',(2.419E1,0.E0,7.81E0));\r\n#4184=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#4185=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4186=AXIS2_PLACEMENT_3D('',#4183,#4184,#4185);\r\n#4188=DIRECTION('',(0.E0,1.E0,1.033516706560E-14));\r\n#4189=VECTOR('',#4188,6.875E-1);\r\n#4190=CARTESIAN_POINT('',(2.331E1,0.E0,7.5E0));\r\n#4191=LINE('',#4190,#4189);\r\n#4192=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4193=VECTOR('',#4192,6.875E-1);\r\n#4194=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0));\r\n#4195=LINE('',#4194,#4193);\r\n#4196=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4197=VECTOR('',#4196,2.425E-1);\r\n#4198=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0));\r\n#4199=LINE('',#4198,#4197);\r\n#4200=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#4201=VECTOR('',#4200,3.1E-1);\r\n#4202=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.81E0));\r\n#4203=LINE('',#4202,#4201);\r\n#4204=CARTESIAN_POINT('',(2.274875E1,6.875E-1,7.5E0));\r\n#4205=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#4206=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4207=AXIS2_PLACEMENT_3D('',#4204,#4205,#4206);\r\n#4209=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4210=VECTOR('',#4209,3.1E-1);\r\n#4211=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.5E0));\r\n#4212=LINE('',#4211,#4210);\r\n#4213=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#4214=VECTOR('',#4213,7.4E-1);\r\n#4215=CARTESIAN_POINT('',(2.13075E1,6.875E-1,8.69E0));\r\n#4216=LINE('',#4215,#4214);\r\n#4217=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#4218=VECTOR('',#4217,8.E-1);\r\n#4219=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0));\r\n#4220=LINE('',#4219,#4218);\r\n#4221=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#4222=VECTOR('',#4221,3.865E0);\r\n#4223=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1));\r\n#4224=LINE('',#4223,#4222);\r\n#4225=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#4226=VECTOR('',#4225,8.E-1);\r\n#4227=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1));\r\n#4228=LINE('',#4227,#4226);\r\n#4229=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1));\r\n#4230=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1));\r\n#4231=VERTEX_POINT('',#4229);\r\n#4232=VERTEX_POINT('',#4230);\r\n#4233=CARTESIAN_POINT('',(2.E1,0.E0,3.2E1));\r\n#4234=CARTESIAN_POINT('',(2.E1,1.5E0,3.2E1));\r\n#4235=VERTEX_POINT('',#4233);\r\n#4236=VERTEX_POINT('',#4234);\r\n#4237=CARTESIAN_POINT('',(2.E1,0.E0,0.E0));\r\n#4238=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0));\r\n#4239=VERTEX_POINT('',#4237);\r\n#4240=VERTEX_POINT('',#4238);\r\n#4241=CARTESIAN_POINT('',(2.4E1,0.E0,4.E0));\r\n#4242=CARTESIAN_POINT('',(2.4E1,1.5E0,4.E0));\r\n#4243=VERTEX_POINT('',#4241);\r\n#4244=VERTEX_POINT('',#4242);\r\n#4245=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1));\r\n#4246=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1));\r\n#4247=VERTEX_POINT('',#4245);\r\n#4248=VERTEX_POINT('',#4246);\r\n#4249=CARTESIAN_POINT('',(0.E0,0.E0,2.8E1));\r\n#4250=CARTESIAN_POINT('',(0.E0,1.5E0,2.8E1));\r\n#4251=VERTEX_POINT('',#4249);\r\n#4252=VERTEX_POINT('',#4250);\r\n#4253=CARTESIAN_POINT('',(0.E0,0.E0,4.E0));\r\n#4254=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0));\r\n#4255=VERTEX_POINT('',#4253);\r\n#4256=VERTEX_POINT('',#4254);\r\n#4257=CARTESIAN_POINT('',(4.E0,0.E0,0.E0));\r\n#4258=CARTESIAN_POINT('',(4.E0,1.5E0,0.E0));\r\n#4259=VERTEX_POINT('',#4257);\r\n#4260=VERTEX_POINT('',#4258);\r\n#4261=CARTESIAN_POINT('',(7.5E0,1.5E0,2.5E0));\r\n#4262=CARTESIAN_POINT('',(7.5E0,0.E0,2.5E0));\r\n#4263=VERTEX_POINT('',#4261);\r\n#4264=VERTEX_POINT('',#4262);\r\n#4265=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0));\r\n#4266=CARTESIAN_POINT('',(1.65E1,0.E0,2.5E0));\r\n#4267=VERTEX_POINT('',#4265);\r\n#4268=VERTEX_POINT('',#4266);\r\n#4269=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1));\r\n#4270=CARTESIAN_POINT('',(7.5E0,0.E0,2.95E1));\r\n#4271=VERTEX_POINT('',#4269);\r\n#4272=VERTEX_POINT('',#4270);\r\n#4273=CARTESIAN_POINT('',(2.5E0,1.5E0,2.45E1));\r\n#4274=CARTESIAN_POINT('',(2.5E0,0.E0,2.45E1));\r\n#4275=VERTEX_POINT('',#4273);\r\n#4276=VERTEX_POINT('',#4274);\r\n#4277=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1));\r\n#4278=CARTESIAN_POINT('',(2.15E1,0.E0,2.45E1));\r\n#4279=VERTEX_POINT('',#4277);\r\n#4280=VERTEX_POINT('',#4278);\r\n#4281=CARTESIAN_POINT('',(1.65E1,1.5E0,2.95E1));\r\n#4282=CARTESIAN_POINT('',(1.65E1,0.E0,2.95E1));\r\n#4283=VERTEX_POINT('',#4281);\r\n#4284=VERTEX_POINT('',#4282);\r\n#4285=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0));\r\n#4286=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0));\r\n#4287=VERTEX_POINT('',#4285);\r\n#4288=VERTEX_POINT('',#4286);\r\n#4289=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0));\r\n#4290=VERTEX_POINT('',#4289);\r\n#4291=CARTESIAN_POINT('',(5.E0,1.15E1,1.E1));\r\n#4292=CARTESIAN_POINT('',(3.E0,1.15E1,1.E1));\r\n#4293=VERTEX_POINT('',#4291);\r\n#4294=VERTEX_POINT('',#4292);\r\n#4295=CARTESIAN_POINT('',(-2.E0,2.5E0,1.E1));\r\n#4296=VERTEX_POINT('',#4295);\r\n#4297=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1));\r\n#4298=VERTEX_POINT('',#4297);\r\n#4299=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0));\r\n#4300=VERTEX_POINT('',#4299);\r\n#4301=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1));\r\n#4302=CARTESIAN_POINT('',(2.5E0,0.E0,1.325E1));\r\n#4303=VERTEX_POINT('',#4301);\r\n#4304=VERTEX_POINT('',#4302);\r\n#4305=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1));\r\n#4306=CARTESIAN_POINT('',(3.5E0,0.E0,1.225E1));\r\n#4307=VERTEX_POINT('',#4305);\r\n#4308=VERTEX_POINT('',#4306);\r\n#4309=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1));\r\n#4310=CARTESIAN_POINT('',(0.E0,1.5E0,1.325E1));\r\n#4311=VERTEX_POINT('',#4309);\r\n#4312=VERTEX_POINT('',#4310);\r\n#4313=CARTESIAN_POINT('',(-1.E0,0.E0,1.225E1));\r\n#4314=CARTESIAN_POINT('',(-1.E0,1.5E0,1.225E1));\r\n#4315=VERTEX_POINT('',#4313);\r\n#4316=VERTEX_POINT('',#4314);\r\n#4317=CARTESIAN_POINT('',(0.E0,1.5E0,7.E0));\r\n#4318=CARTESIAN_POINT('',(0.E0,0.E0,7.E0));\r\n#4319=VERTEX_POINT('',#4317);\r\n#4320=VERTEX_POINT('',#4318);\r\n#4321=CARTESIAN_POINT('',(-1.E0,1.5E0,8.E0));\r\n#4322=CARTESIAN_POINT('',(-1.E0,0.E0,8.E0));\r\n#4323=VERTEX_POINT('',#4321);\r\n#4324=VERTEX_POINT('',#4322);\r\n#4325=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0));\r\n#4326=CARTESIAN_POINT('',(3.531373033403E0,0.E0,8.E0));\r\n#4327=VERTEX_POINT('',#4325);\r\n#4328=VERTEX_POINT('',#4326);\r\n#4329=CARTESIAN_POINT('',(2.539216291754E0,1.5E0,6.875E0));\r\n#4330=CARTESIAN_POINT('',(2.539216291754E0,0.E0,6.875E0));\r\n#4331=VERTEX_POINT('',#4329);\r\n#4332=VERTEX_POINT('',#4330);\r\n#4333=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1));\r\n#4334=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1));\r\n#4335=VERTEX_POINT('',#4333);\r\n#4336=VERTEX_POINT('',#4334);\r\n#4337=CARTESIAN_POINT('',(4.5E0,0.E0,1.225E1));\r\n#4338=CARTESIAN_POINT('',(4.5E0,1.5E0,1.225E1));\r\n#4339=VERTEX_POINT('',#4337);\r\n#4340=VERTEX_POINT('',#4338);\r\n#4341=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1));\r\n#4342=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1));\r\n#4343=VERTEX_POINT('',#4341);\r\n#4344=VERTEX_POINT('',#4342);\r\n#4345=CARTESIAN_POINT('',(-2.E0,0.E0,1.175E1));\r\n#4346=CARTESIAN_POINT('',(-2.E0,1.5E0,1.175E1));\r\n#4347=VERTEX_POINT('',#4345);\r\n#4348=VERTEX_POINT('',#4346);\r\n#4349=CARTESIAN_POINT('',(4.095E0,1.1125E1,9.E0));\r\n#4350=CARTESIAN_POINT('',(3.905E0,1.1125E1,9.E0));\r\n#4351=VERTEX_POINT('',#4349);\r\n#4352=VERTEX_POINT('',#4350);\r\n#4353=CARTESIAN_POINT('',(4.095E0,1.15E1,9.E0));\r\n#4354=CARTESIAN_POINT('',(3.905E0,1.15E1,9.E0));\r\n#4355=VERTEX_POINT('',#4353);\r\n#4356=VERTEX_POINT('',#4354);\r\n#4357=CARTESIAN_POINT('',(3.929917478528E0,1.125E1,9.132582521472E0));\r\n#4358=CARTESIAN_POINT('',(3.804917478528E0,1.125E1,9.132582521472E0));\r\n#4359=VERTEX_POINT('',#4357);\r\n#4360=VERTEX_POINT('',#4358);\r\n#4361=CARTESIAN_POINT('',(3.929917478528E0,1.15E1,9.132582521472E0));\r\n#4362=CARTESIAN_POINT('',(3.804917478528E0,1.15E1,9.132582521472E0));\r\n#4363=VERTEX_POINT('',#4361);\r\n#4364=VERTEX_POINT('',#4362);\r\n#4365=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1));\r\n#4366=CARTESIAN_POINT('',(6.55E0,1.25E0,2.975E1));\r\n#4367=VERTEX_POINT('',#4365);\r\n#4368=VERTEX_POINT('',#4366);\r\n#4369=CARTESIAN_POINT('',(6.35E0,1.25E0,2.975E1));\r\n#4370=VERTEX_POINT('',#4369);\r\n#4371=CARTESIAN_POINT('',(6.35E0,1.5E0,2.975E1));\r\n#4372=CARTESIAN_POINT('',(6.55E0,1.5E0,2.975E1));\r\n#4373=VERTEX_POINT('',#4371);\r\n#4374=VERTEX_POINT('',#4372);\r\n#4375=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1));\r\n#4376=CARTESIAN_POINT('',(7.55E0,1.25E0,2.975E1));\r\n#4377=VERTEX_POINT('',#4375);\r\n#4378=VERTEX_POINT('',#4376);\r\n#4379=CARTESIAN_POINT('',(7.35E0,1.25E0,2.975E1));\r\n#4380=VERTEX_POINT('',#4379);\r\n#4381=CARTESIAN_POINT('',(7.35E0,1.5E0,2.975E1));\r\n#4382=CARTESIAN_POINT('',(7.55E0,1.5E0,2.975E1));\r\n#4383=VERTEX_POINT('',#4381);\r\n#4384=VERTEX_POINT('',#4382);\r\n#4385=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0));\r\n#4386=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0));\r\n#4387=VERTEX_POINT('',#4385);\r\n#4388=VERTEX_POINT('',#4386);\r\n#4389=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0));\r\n#4390=VERTEX_POINT('',#4389);\r\n#4391=CARTESIAN_POINT('',(1.9E1,1.15E1,1.E1));\r\n#4392=CARTESIAN_POINT('',(2.1E1,1.15E1,1.E1));\r\n#4393=VERTEX_POINT('',#4391);\r\n#4394=VERTEX_POINT('',#4392);\r\n#4395=CARTESIAN_POINT('',(2.6E1,2.5E0,1.E1));\r\n#4396=VERTEX_POINT('',#4395);\r\n#4397=CARTESIAN_POINT('',(2.6E1,1.5E0,1.E1));\r\n#4398=VERTEX_POINT('',#4397);\r\n#4399=CARTESIAN_POINT('',(2.6E1,0.E0,8.E0));\r\n#4400=VERTEX_POINT('',#4399);\r\n#4401=CARTESIAN_POINT('',(2.4E1,1.5E0,1.325E1));\r\n#4402=CARTESIAN_POINT('',(2.4E1,0.E0,1.325E1));\r\n#4403=VERTEX_POINT('',#4401);\r\n#4404=VERTEX_POINT('',#4402);\r\n#4405=CARTESIAN_POINT('',(2.5E1,1.5E0,1.225E1));\r\n#4406=CARTESIAN_POINT('',(2.5E1,0.E0,1.225E1));\r\n#4407=VERTEX_POINT('',#4405);\r\n#4408=VERTEX_POINT('',#4406);\r\n#4409=CARTESIAN_POINT('',(2.15E1,0.E0,1.325E1));\r\n#4410=CARTESIAN_POINT('',(2.15E1,1.5E0,1.325E1));\r\n#4411=VERTEX_POINT('',#4409);\r\n#4412=VERTEX_POINT('',#4410);\r\n#4413=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1));\r\n#4414=CARTESIAN_POINT('',(2.05E1,1.5E0,1.225E1));\r\n#4415=VERTEX_POINT('',#4413);\r\n#4416=VERTEX_POINT('',#4414);\r\n#4417=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0));\r\n#4418=CARTESIAN_POINT('',(2.4E1,1.5E0,7.E0));\r\n#4419=VERTEX_POINT('',#4417);\r\n#4420=VERTEX_POINT('',#4418);\r\n#4421=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0));\r\n#4422=CARTESIAN_POINT('',(2.5E1,1.5E0,8.E0));\r\n#4423=VERTEX_POINT('',#4421);\r\n#4424=VERTEX_POINT('',#4422);\r\n#4425=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0));\r\n#4426=CARTESIAN_POINT('',(2.046862696660E1,1.5E0,8.E0));\r\n#4427=VERTEX_POINT('',#4425);\r\n#4428=VERTEX_POINT('',#4426);\r\n#4429=CARTESIAN_POINT('',(2.146078370825E1,0.E0,6.875E0));\r\n#4430=CARTESIAN_POINT('',(2.146078370825E1,1.5E0,6.875E0));\r\n#4431=VERTEX_POINT('',#4429);\r\n#4432=VERTEX_POINT('',#4430);\r\n#4433=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1));\r\n#4434=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1));\r\n#4435=VERTEX_POINT('',#4433);\r\n#4436=VERTEX_POINT('',#4434);\r\n#4437=CARTESIAN_POINT('',(1.95E1,1.5E0,1.225E1));\r\n#4438=CARTESIAN_POINT('',(1.95E1,0.E0,1.225E1));\r\n#4439=VERTEX_POINT('',#4437);\r\n#4440=VERTEX_POINT('',#4438);\r\n#4441=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1));\r\n#4442=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1));\r\n#4443=VERTEX_POINT('',#4441);\r\n#4444=VERTEX_POINT('',#4442);\r\n#4445=CARTESIAN_POINT('',(2.6E1,1.5E0,1.175E1));\r\n#4446=CARTESIAN_POINT('',(2.6E1,0.E0,1.175E1));\r\n#4447=VERTEX_POINT('',#4445);\r\n#4448=VERTEX_POINT('',#4446);\r\n#4449=CARTESIAN_POINT('',(1.9905E1,1.1125E1,9.E0));\r\n#4450=CARTESIAN_POINT('',(2.0095E1,1.1125E1,9.E0));\r\n#4451=VERTEX_POINT('',#4449);\r\n#4452=VERTEX_POINT('',#4450);\r\n#4453=CARTESIAN_POINT('',(1.9905E1,1.15E1,9.E0));\r\n#4454=CARTESIAN_POINT('',(2.0095E1,1.15E1,9.E0));\r\n#4455=VERTEX_POINT('',#4453);\r\n#4456=VERTEX_POINT('',#4454);\r\n#4457=CARTESIAN_POINT('',(2.007008252147E1,1.125E1,9.132582521472E0));\r\n#4458=CARTESIAN_POINT('',(2.019508252147E1,1.125E1,9.132582521472E0));\r\n#4459=VERTEX_POINT('',#4457);\r\n#4460=VERTEX_POINT('',#4458);\r\n#4461=CARTESIAN_POINT('',(2.007008252147E1,1.15E1,9.132582521472E0));\r\n#4462=CARTESIAN_POINT('',(2.019508252147E1,1.15E1,9.132582521472E0));\r\n#4463=VERTEX_POINT('',#4461);\r\n#4464=VERTEX_POINT('',#4462);\r\n#4465=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1));\r\n#4466=CARTESIAN_POINT('',(1.745E1,1.25E0,2.975E1));\r\n#4467=VERTEX_POINT('',#4465);\r\n#4468=VERTEX_POINT('',#4466);\r\n#4469=CARTESIAN_POINT('',(1.765E1,1.25E0,2.975E1));\r\n#4470=VERTEX_POINT('',#4469);\r\n#4471=CARTESIAN_POINT('',(1.765E1,1.5E0,2.975E1));\r\n#4472=CARTESIAN_POINT('',(1.745E1,1.5E0,2.975E1));\r\n#4473=VERTEX_POINT('',#4471);\r\n#4474=VERTEX_POINT('',#4472);\r\n#4475=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1));\r\n#4476=CARTESIAN_POINT('',(1.645E1,1.25E0,2.975E1));\r\n#4477=VERTEX_POINT('',#4475);\r\n#4478=VERTEX_POINT('',#4476);\r\n#4479=CARTESIAN_POINT('',(1.665E1,1.25E0,2.975E1));\r\n#4480=VERTEX_POINT('',#4479);\r\n#4481=CARTESIAN_POINT('',(1.665E1,1.5E0,2.975E1));\r\n#4482=CARTESIAN_POINT('',(1.645E1,1.5E0,2.975E1));\r\n#4483=VERTEX_POINT('',#4481);\r\n#4484=VERTEX_POINT('',#4482);\r\n#4485=CARTESIAN_POINT('',(1.3175E0,0.E0,6.E0));\r\n#4486=CARTESIAN_POINT('',(9.325E-1,0.E0,6.E0));\r\n#4487=VERTEX_POINT('',#4485);\r\n#4488=VERTEX_POINT('',#4486);\r\n#4489=CARTESIAN_POINT('',(1.3825E0,1.E0,6.E0));\r\n#4490=CARTESIAN_POINT('',(8.675E-1,1.E0,6.E0));\r\n#4491=VERTEX_POINT('',#4489);\r\n#4492=VERTEX_POINT('',#4490);\r\n#4493=CARTESIAN_POINT('',(1.3825E0,1.5E0,6.E0));\r\n#4494=CARTESIAN_POINT('',(8.675E-1,1.5E0,6.E0));\r\n#4495=VERTEX_POINT('',#4493);\r\n#4496=VERTEX_POINT('',#4494);\r\n#4497=CARTESIAN_POINT('',(1.3175E0,1.E0,6.E0));\r\n#4498=CARTESIAN_POINT('',(9.325E-1,1.E0,6.E0));\r\n#4499=VERTEX_POINT('',#4497);\r\n#4500=VERTEX_POINT('',#4498);\r\n#4501=CARTESIAN_POINT('',(1.3175E0,0.E0,1.2E1));\r\n#4502=CARTESIAN_POINT('',(9.325E-1,0.E0,1.2E1));\r\n#4503=VERTEX_POINT('',#4501);\r\n#4504=VERTEX_POINT('',#4502);\r\n#4505=CARTESIAN_POINT('',(1.3175E0,0.E0,1.8E1));\r\n#4506=CARTESIAN_POINT('',(9.325E-1,0.E0,1.8E1));\r\n#4507=VERTEX_POINT('',#4505);\r\n#4508=VERTEX_POINT('',#4506);\r\n#4509=CARTESIAN_POINT('',(1.3175E0,0.E0,2.4E1));\r\n#4510=CARTESIAN_POINT('',(9.325E-1,0.E0,2.4E1));\r\n#4511=VERTEX_POINT('',#4509);\r\n#4512=VERTEX_POINT('',#4510);\r\n#4513=CARTESIAN_POINT('',(2.30675E1,0.E0,6.E0));\r\n#4514=CARTESIAN_POINT('',(2.26825E1,0.E0,6.E0));\r\n#4515=VERTEX_POINT('',#4513);\r\n#4516=VERTEX_POINT('',#4514);\r\n#4517=CARTESIAN_POINT('',(2.30675E1,0.E0,1.2E1));\r\n#4518=CARTESIAN_POINT('',(2.26825E1,0.E0,1.2E1));\r\n#4519=VERTEX_POINT('',#4517);\r\n#4520=VERTEX_POINT('',#4518);\r\n#4521=CARTESIAN_POINT('',(2.30675E1,0.E0,1.8E1));\r\n#4522=CARTESIAN_POINT('',(2.26825E1,0.E0,1.8E1));\r\n#4523=VERTEX_POINT('',#4521);\r\n#4524=VERTEX_POINT('',#4522);\r\n#4525=CARTESIAN_POINT('',(2.30675E1,0.E0,2.4E1));\r\n#4526=CARTESIAN_POINT('',(2.26825E1,0.E0,2.4E1));\r\n#4527=VERTEX_POINT('',#4525);\r\n#4528=VERTEX_POINT('',#4526);\r\n#4529=CARTESIAN_POINT('',(1.3825E0,1.E0,1.2E1));\r\n#4530=CARTESIAN_POINT('',(8.675E-1,1.E0,1.2E1));\r\n#4531=VERTEX_POINT('',#4529);\r\n#4532=VERTEX_POINT('',#4530);\r\n#4533=CARTESIAN_POINT('',(1.3175E0,1.E0,1.2E1));\r\n#4534=CARTESIAN_POINT('',(9.325E-1,1.E0,1.2E1));\r\n#4535=VERTEX_POINT('',#4533);\r\n#4536=VERTEX_POINT('',#4534);\r\n#4537=CARTESIAN_POINT('',(1.3825E0,1.E0,1.8E1));\r\n#4538=CARTESIAN_POINT('',(8.675E-1,1.E0,1.8E1));\r\n#4539=VERTEX_POINT('',#4537);\r\n#4540=VERTEX_POINT('',#4538);\r\n#4541=CARTESIAN_POINT('',(1.3825E0,1.5E0,1.8E1));\r\n#4542=CARTESIAN_POINT('',(8.675E-1,1.5E0,1.8E1));\r\n#4543=VERTEX_POINT('',#4541);\r\n#4544=VERTEX_POINT('',#4542);\r\n#4545=CARTESIAN_POINT('',(1.3175E0,1.E0,1.8E1));\r\n#4546=CARTESIAN_POINT('',(9.325E-1,1.E0,1.8E1));\r\n#4547=VERTEX_POINT('',#4545);\r\n#4548=VERTEX_POINT('',#4546);\r\n#4549=CARTESIAN_POINT('',(1.3825E0,1.E0,2.4E1));\r\n#4550=CARTESIAN_POINT('',(8.675E-1,1.E0,2.4E1));\r\n#4551=VERTEX_POINT('',#4549);\r\n#4552=VERTEX_POINT('',#4550);\r\n#4553=CARTESIAN_POINT('',(1.3825E0,1.5E0,2.4E1));\r\n#4554=CARTESIAN_POINT('',(8.675E-1,1.5E0,2.4E1));\r\n#4555=VERTEX_POINT('',#4553);\r\n#4556=VERTEX_POINT('',#4554);\r\n#4557=CARTESIAN_POINT('',(1.3175E0,1.E0,2.4E1));\r\n#4558=CARTESIAN_POINT('',(9.325E-1,1.E0,2.4E1));\r\n#4559=VERTEX_POINT('',#4557);\r\n#4560=VERTEX_POINT('',#4558);\r\n#4561=CARTESIAN_POINT('',(2.31325E1,1.E0,6.E0));\r\n#4562=CARTESIAN_POINT('',(2.26175E1,1.E0,6.E0));\r\n#4563=VERTEX_POINT('',#4561);\r\n#4564=VERTEX_POINT('',#4562);\r\n#4565=CARTESIAN_POINT('',(2.31325E1,1.5E0,6.E0));\r\n#4566=CARTESIAN_POINT('',(2.26175E1,1.5E0,6.E0));\r\n#4567=VERTEX_POINT('',#4565);\r\n#4568=VERTEX_POINT('',#4566);\r\n#4569=CARTESIAN_POINT('',(2.30675E1,1.E0,6.E0));\r\n#4570=CARTESIAN_POINT('',(2.26825E1,1.E0,6.E0));\r\n#4571=VERTEX_POINT('',#4569);\r\n#4572=VERTEX_POINT('',#4570);\r\n#4573=CARTESIAN_POINT('',(2.31325E1,1.E0,1.2E1));\r\n#4574=CARTESIAN_POINT('',(2.26175E1,1.E0,1.2E1));\r\n#4575=VERTEX_POINT('',#4573);\r\n#4576=VERTEX_POINT('',#4574);\r\n#4577=CARTESIAN_POINT('',(2.30675E1,1.E0,1.2E1));\r\n#4578=CARTESIAN_POINT('',(2.26825E1,1.E0,1.2E1));\r\n#4579=VERTEX_POINT('',#4577);\r\n#4580=VERTEX_POINT('',#4578);\r\n#4581=CARTESIAN_POINT('',(2.31325E1,1.E0,1.8E1));\r\n#4582=CARTESIAN_POINT('',(2.26175E1,1.E0,1.8E1));\r\n#4583=VERTEX_POINT('',#4581);\r\n#4584=VERTEX_POINT('',#4582);\r\n#4585=CARTESIAN_POINT('',(2.31325E1,1.5E0,1.8E1));\r\n#4586=CARTESIAN_POINT('',(2.26175E1,1.5E0,1.8E1));\r\n#4587=VERTEX_POINT('',#4585);\r\n#4588=VERTEX_POINT('',#4586);\r\n#4589=CARTESIAN_POINT('',(2.30675E1,1.E0,1.8E1));\r\n#4590=CARTESIAN_POINT('',(2.26825E1,1.E0,1.8E1));\r\n#4591=VERTEX_POINT('',#4589);\r\n#4592=VERTEX_POINT('',#4590);\r\n#4593=CARTESIAN_POINT('',(2.31325E1,1.E0,2.4E1));\r\n#4594=CARTESIAN_POINT('',(2.26175E1,1.E0,2.4E1));\r\n#4595=VERTEX_POINT('',#4593);\r\n#4596=VERTEX_POINT('',#4594);\r\n#4597=CARTESIAN_POINT('',(2.31325E1,1.5E0,2.4E1));\r\n#4598=CARTESIAN_POINT('',(2.26175E1,1.5E0,2.4E1));\r\n#4599=VERTEX_POINT('',#4597);\r\n#4600=VERTEX_POINT('',#4598);\r\n#4601=CARTESIAN_POINT('',(2.30675E1,1.E0,2.4E1));\r\n#4602=CARTESIAN_POINT('',(2.26825E1,1.E0,2.4E1));\r\n#4603=VERTEX_POINT('',#4601);\r\n#4604=VERTEX_POINT('',#4602);\r\n#4605=CARTESIAN_POINT('',(6.1925E0,0.E0,1.25E0));\r\n#4606=CARTESIAN_POINT('',(5.8075E0,0.E0,1.25E0));\r\n#4607=VERTEX_POINT('',#4605);\r\n#4608=VERTEX_POINT('',#4606);\r\n#4609=CARTESIAN_POINT('',(6.256E0,1.E0,1.25E0));\r\n#4610=CARTESIAN_POINT('',(5.744E0,1.E0,1.25E0));\r\n#4611=VERTEX_POINT('',#4609);\r\n#4612=VERTEX_POINT('',#4610);\r\n#4613=CARTESIAN_POINT('',(6.256E0,1.5E0,1.25E0));\r\n#4614=CARTESIAN_POINT('',(5.744E0,1.5E0,1.25E0));\r\n#4615=VERTEX_POINT('',#4613);\r\n#4616=VERTEX_POINT('',#4614);\r\n#4617=CARTESIAN_POINT('',(6.1925E0,1.E0,1.25E0));\r\n#4618=CARTESIAN_POINT('',(5.8075E0,1.E0,1.25E0));\r\n#4619=VERTEX_POINT('',#4617);\r\n#4620=VERTEX_POINT('',#4618);\r\n#4621=CARTESIAN_POINT('',(1.21925E1,0.E0,1.25E0));\r\n#4622=CARTESIAN_POINT('',(1.18075E1,0.E0,1.25E0));\r\n#4623=VERTEX_POINT('',#4621);\r\n#4624=VERTEX_POINT('',#4622);\r\n#4625=CARTESIAN_POINT('',(6.1925E0,0.E0,3.075E1));\r\n#4626=CARTESIAN_POINT('',(5.8075E0,0.E0,3.075E1));\r\n#4627=VERTEX_POINT('',#4625);\r\n#4628=VERTEX_POINT('',#4626);\r\n#4629=CARTESIAN_POINT('',(1.21925E1,0.E0,3.075E1));\r\n#4630=CARTESIAN_POINT('',(1.18075E1,0.E0,3.075E1));\r\n#4631=VERTEX_POINT('',#4629);\r\n#4632=VERTEX_POINT('',#4630);\r\n#4633=CARTESIAN_POINT('',(1.81925E1,0.E0,1.25E0));\r\n#4634=CARTESIAN_POINT('',(1.78075E1,0.E0,1.25E0));\r\n#4635=VERTEX_POINT('',#4633);\r\n#4636=VERTEX_POINT('',#4634);\r\n#4637=CARTESIAN_POINT('',(1.81925E1,0.E0,3.075E1));\r\n#4638=CARTESIAN_POINT('',(1.78075E1,0.E0,3.075E1));\r\n#4639=VERTEX_POINT('',#4637);\r\n#4640=VERTEX_POINT('',#4638);\r\n#4641=CARTESIAN_POINT('',(1.2256E1,1.E0,1.25E0));\r\n#4642=CARTESIAN_POINT('',(1.1744E1,1.E0,1.25E0));\r\n#4643=VERTEX_POINT('',#4641);\r\n#4644=VERTEX_POINT('',#4642);\r\n#4645=CARTESIAN_POINT('',(1.2256E1,1.5E0,1.25E0));\r\n#4646=CARTESIAN_POINT('',(1.1744E1,1.5E0,1.25E0));\r\n#4647=VERTEX_POINT('',#4645);\r\n#4648=VERTEX_POINT('',#4646);\r\n#4649=CARTESIAN_POINT('',(1.21925E1,1.E0,1.25E0));\r\n#4650=CARTESIAN_POINT('',(1.18075E1,1.E0,1.25E0));\r\n#4651=VERTEX_POINT('',#4649);\r\n#4652=VERTEX_POINT('',#4650);\r\n#4653=CARTESIAN_POINT('',(1.8256E1,1.E0,1.25E0));\r\n#4654=CARTESIAN_POINT('',(1.7744E1,1.E0,1.25E0));\r\n#4655=VERTEX_POINT('',#4653);\r\n#4656=VERTEX_POINT('',#4654);\r\n#4657=CARTESIAN_POINT('',(1.8256E1,1.5E0,1.25E0));\r\n#4658=CARTESIAN_POINT('',(1.7744E1,1.5E0,1.25E0));\r\n#4659=VERTEX_POINT('',#4657);\r\n#4660=VERTEX_POINT('',#4658);\r\n#4661=CARTESIAN_POINT('',(1.81925E1,1.E0,1.25E0));\r\n#4662=CARTESIAN_POINT('',(1.78075E1,1.E0,1.25E0));\r\n#4663=VERTEX_POINT('',#4661);\r\n#4664=VERTEX_POINT('',#4662);\r\n#4665=CARTESIAN_POINT('',(6.256E0,1.E0,3.075E1));\r\n#4666=CARTESIAN_POINT('',(5.744E0,1.E0,3.075E1));\r\n#4667=VERTEX_POINT('',#4665);\r\n#4668=VERTEX_POINT('',#4666);\r\n#4669=CARTESIAN_POINT('',(6.256E0,1.5E0,3.075E1));\r\n#4670=CARTESIAN_POINT('',(5.744E0,1.5E0,3.075E1));\r\n#4671=VERTEX_POINT('',#4669);\r\n#4672=VERTEX_POINT('',#4670);\r\n#4673=CARTESIAN_POINT('',(6.1925E0,1.E0,3.075E1));\r\n#4674=CARTESIAN_POINT('',(5.8075E0,1.E0,3.075E1));\r\n#4675=VERTEX_POINT('',#4673);\r\n#4676=VERTEX_POINT('',#4674);\r\n#4677=CARTESIAN_POINT('',(1.2256E1,1.E0,3.075E1));\r\n#4678=CARTESIAN_POINT('',(1.1744E1,1.E0,3.075E1));\r\n#4679=VERTEX_POINT('',#4677);\r\n#4680=VERTEX_POINT('',#4678);\r\n#4681=CARTESIAN_POINT('',(1.2256E1,1.5E0,3.075E1));\r\n#4682=CARTESIAN_POINT('',(1.1744E1,1.5E0,3.075E1));\r\n#4683=VERTEX_POINT('',#4681);\r\n#4684=VERTEX_POINT('',#4682);\r\n#4685=CARTESIAN_POINT('',(1.21925E1,1.E0,3.075E1));\r\n#4686=CARTESIAN_POINT('',(1.18075E1,1.E0,3.075E1));\r\n#4687=VERTEX_POINT('',#4685);\r\n#4688=VERTEX_POINT('',#4686);\r\n#4689=CARTESIAN_POINT('',(1.8256E1,1.E0,3.075E1));\r\n#4690=CARTESIAN_POINT('',(1.7744E1,1.E0,3.075E1));\r\n#4691=VERTEX_POINT('',#4689);\r\n#4692=VERTEX_POINT('',#4690);\r\n#4693=CARTESIAN_POINT('',(1.8256E1,1.5E0,3.075E1));\r\n#4694=CARTESIAN_POINT('',(1.7744E1,1.5E0,3.075E1));\r\n#4695=VERTEX_POINT('',#4693);\r\n#4696=VERTEX_POINT('',#4694);\r\n#4697=CARTESIAN_POINT('',(1.81925E1,1.E0,3.075E1));\r\n#4698=CARTESIAN_POINT('',(1.78075E1,1.E0,3.075E1));\r\n#4699=VERTEX_POINT('',#4697);\r\n#4700=VERTEX_POINT('',#4698);\r\n#4701=CARTESIAN_POINT('',(4.4125E0,1.05E1,8.E0));\r\n#4702=CARTESIAN_POINT('',(4.0875E0,1.05E1,8.E0));\r\n#4703=VERTEX_POINT('',#4701);\r\n#4704=VERTEX_POINT('',#4702);\r\n#4705=CARTESIAN_POINT('',(4.4125E0,1.05E1,1.E1));\r\n#4706=CARTESIAN_POINT('',(4.0875E0,1.05E1,1.E1));\r\n#4707=VERTEX_POINT('',#4705);\r\n#4708=VERTEX_POINT('',#4706);\r\n#4709=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.25E0));\r\n#4710=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.25E0));\r\n#4711=VERTEX_POINT('',#4709);\r\n#4712=VERTEX_POINT('',#4710);\r\n#4713=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.E0));\r\n#4714=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.E0));\r\n#4715=VERTEX_POINT('',#4713);\r\n#4716=VERTEX_POINT('',#4714);\r\n#4717=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.25E0));\r\n#4718=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.25E0));\r\n#4719=VERTEX_POINT('',#4717);\r\n#4720=VERTEX_POINT('',#4718);\r\n#4721=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.E0));\r\n#4722=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.E0));\r\n#4723=VERTEX_POINT('',#4721);\r\n#4724=VERTEX_POINT('',#4722);\r\n#4725=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.25E0));\r\n#4726=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.25E0));\r\n#4727=VERTEX_POINT('',#4725);\r\n#4728=VERTEX_POINT('',#4726);\r\n#4729=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.E0));\r\n#4730=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.E0));\r\n#4731=VERTEX_POINT('',#4729);\r\n#4732=VERTEX_POINT('',#4730);\r\n#4733=CARTESIAN_POINT('',(1.95875E1,1.05E1,8.E0));\r\n#4734=CARTESIAN_POINT('',(1.99125E1,1.05E1,8.E0));\r\n#4735=VERTEX_POINT('',#4733);\r\n#4736=VERTEX_POINT('',#4734);\r\n#4737=CARTESIAN_POINT('',(1.95875E1,1.05E1,1.E1));\r\n#4738=CARTESIAN_POINT('',(1.99125E1,1.05E1,1.E1));\r\n#4739=VERTEX_POINT('',#4737);\r\n#4740=VERTEX_POINT('',#4738);\r\n#4741=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.25E0));\r\n#4742=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.25E0));\r\n#4743=VERTEX_POINT('',#4741);\r\n#4744=VERTEX_POINT('',#4742);\r\n#4745=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.E0));\r\n#4746=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.E0));\r\n#4747=VERTEX_POINT('',#4745);\r\n#4748=VERTEX_POINT('',#4746);\r\n#4749=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.25E0));\r\n#4750=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.25E0));\r\n#4751=VERTEX_POINT('',#4749);\r\n#4752=VERTEX_POINT('',#4750);\r\n#4753=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.E0));\r\n#4754=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.E0));\r\n#4755=VERTEX_POINT('',#4753);\r\n#4756=VERTEX_POINT('',#4754);\r\n#4757=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.25E0));\r\n#4758=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.25E0));\r\n#4759=VERTEX_POINT('',#4757);\r\n#4760=VERTEX_POINT('',#4758);\r\n#4761=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.E0));\r\n#4762=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.E0));\r\n#4763=VERTEX_POINT('',#4761);\r\n#4764=VERTEX_POINT('',#4762);\r\n#4765=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0));\r\n#4766=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0));\r\n#4767=VERTEX_POINT('',#4765);\r\n#4768=VERTEX_POINT('',#4766);\r\n#4769=CARTESIAN_POINT('',(5.E0,1.5E0,1.1E1));\r\n#4770=CARTESIAN_POINT('',(5.E0,0.E0,1.1E1));\r\n#4771=VERTEX_POINT('',#4769);\r\n#4772=VERTEX_POINT('',#4770);\r\n#4773=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1));\r\n#4774=CARTESIAN_POINT('',(6.E0,0.E0,1.E1));\r\n#4775=VERTEX_POINT('',#4773);\r\n#4776=VERTEX_POINT('',#4774);\r\n#4777=CARTESIAN_POINT('',(1.9E1,0.E0,1.1E1));\r\n#4778=CARTESIAN_POINT('',(1.9E1,1.5E0,1.1E1));\r\n#4779=VERTEX_POINT('',#4777);\r\n#4780=VERTEX_POINT('',#4778);\r\n#4781=CARTESIAN_POINT('',(1.8E1,0.E0,1.E1));\r\n#4782=CARTESIAN_POINT('',(1.8E1,1.5E0,1.E1));\r\n#4783=VERTEX_POINT('',#4781);\r\n#4784=VERTEX_POINT('',#4782);\r\n#4785=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1));\r\n#4786=VERTEX_POINT('',#4785);\r\n#4787=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1));\r\n#4788=VERTEX_POINT('',#4787);\r\n#4789=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1));\r\n#4790=CARTESIAN_POINT('',(2.5E0,0.E0,2.19375E1));\r\n#4791=VERTEX_POINT('',#4789);\r\n#4792=VERTEX_POINT('',#4790);\r\n#4793=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1));\r\n#4794=CARTESIAN_POINT('',(5.5E0,0.E0,1.89375E1));\r\n#4795=VERTEX_POINT('',#4793);\r\n#4796=VERTEX_POINT('',#4794);\r\n#4797=CARTESIAN_POINT('',(2.15E1,0.E0,2.19375E1));\r\n#4798=CARTESIAN_POINT('',(2.15E1,1.5E0,2.19375E1));\r\n#4799=VERTEX_POINT('',#4797);\r\n#4800=VERTEX_POINT('',#4798);\r\n#4801=CARTESIAN_POINT('',(1.85E1,0.E0,1.89375E1));\r\n#4802=CARTESIAN_POINT('',(1.85E1,1.5E0,1.89375E1));\r\n#4803=VERTEX_POINT('',#4801);\r\n#4804=VERTEX_POINT('',#4802);\r\n#4805=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1));\r\n#4806=CARTESIAN_POINT('',(2.15E1,0.E0,1.40625E1));\r\n#4807=VERTEX_POINT('',#4805);\r\n#4808=VERTEX_POINT('',#4806);\r\n#4809=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1));\r\n#4810=CARTESIAN_POINT('',(1.85E1,0.E0,1.70625E1));\r\n#4811=VERTEX_POINT('',#4809);\r\n#4812=VERTEX_POINT('',#4810);\r\n#4813=CARTESIAN_POINT('',(2.5E0,0.E0,1.40625E1));\r\n#4814=CARTESIAN_POINT('',(2.5E0,1.5E0,1.40625E1));\r\n#4815=VERTEX_POINT('',#4813);\r\n#4816=VERTEX_POINT('',#4814);\r\n#4817=CARTESIAN_POINT('',(5.5E0,0.E0,1.70625E1));\r\n#4818=CARTESIAN_POINT('',(5.5E0,1.5E0,1.70625E1));\r\n#4819=VERTEX_POINT('',#4817);\r\n#4820=VERTEX_POINT('',#4818);\r\n#4821=CARTESIAN_POINT('',(6.1925E0,0.E0,9.E0));\r\n#4822=CARTESIAN_POINT('',(5.8075E0,0.E0,9.E0));\r\n#4823=VERTEX_POINT('',#4821);\r\n#4824=VERTEX_POINT('',#4822);\r\n#4825=CARTESIAN_POINT('',(6.2575E0,1.E0,9.E0));\r\n#4826=CARTESIAN_POINT('',(5.7425E0,1.E0,9.E0));\r\n#4827=VERTEX_POINT('',#4825);\r\n#4828=VERTEX_POINT('',#4826);\r\n#4829=CARTESIAN_POINT('',(6.2575E0,1.5E0,9.E0));\r\n#4830=CARTESIAN_POINT('',(5.7425E0,1.5E0,9.E0));\r\n#4831=VERTEX_POINT('',#4829);\r\n#4832=VERTEX_POINT('',#4830);\r\n#4833=CARTESIAN_POINT('',(6.1925E0,1.E0,9.E0));\r\n#4834=CARTESIAN_POINT('',(5.8075E0,1.E0,9.E0));\r\n#4835=VERTEX_POINT('',#4833);\r\n#4836=VERTEX_POINT('',#4834);\r\n#4837=CARTESIAN_POINT('',(1.21925E1,0.E0,9.E0));\r\n#4838=CARTESIAN_POINT('',(1.18075E1,0.E0,9.E0));\r\n#4839=VERTEX_POINT('',#4837);\r\n#4840=VERTEX_POINT('',#4838);\r\n#4841=CARTESIAN_POINT('',(1.81925E1,0.E0,9.E0));\r\n#4842=CARTESIAN_POINT('',(1.78075E1,0.E0,9.E0));\r\n#4843=VERTEX_POINT('',#4841);\r\n#4844=VERTEX_POINT('',#4842);\r\n#4845=CARTESIAN_POINT('',(6.1925E0,0.E0,1.8E1));\r\n#4846=CARTESIAN_POINT('',(5.8075E0,0.E0,1.8E1));\r\n#4847=VERTEX_POINT('',#4845);\r\n#4848=VERTEX_POINT('',#4846);\r\n#4849=CARTESIAN_POINT('',(1.21925E1,0.E0,1.8E1));\r\n#4850=CARTESIAN_POINT('',(1.18075E1,0.E0,1.8E1));\r\n#4851=VERTEX_POINT('',#4849);\r\n#4852=VERTEX_POINT('',#4850);\r\n#4853=CARTESIAN_POINT('',(1.81925E1,0.E0,1.8E1));\r\n#4854=CARTESIAN_POINT('',(1.78075E1,0.E0,1.8E1));\r\n#4855=VERTEX_POINT('',#4853);\r\n#4856=VERTEX_POINT('',#4854);\r\n#4857=CARTESIAN_POINT('',(1.22575E1,1.E0,9.E0));\r\n#4858=CARTESIAN_POINT('',(1.17425E1,1.E0,9.E0));\r\n#4859=VERTEX_POINT('',#4857);\r\n#4860=VERTEX_POINT('',#4858);\r\n#4861=CARTESIAN_POINT('',(1.22575E1,1.5E0,9.E0));\r\n#4862=CARTESIAN_POINT('',(1.17425E1,1.5E0,9.E0));\r\n#4863=VERTEX_POINT('',#4861);\r\n#4864=VERTEX_POINT('',#4862);\r\n#4865=CARTESIAN_POINT('',(1.21925E1,1.E0,9.E0));\r\n#4866=CARTESIAN_POINT('',(1.18075E1,1.E0,9.E0));\r\n#4867=VERTEX_POINT('',#4865);\r\n#4868=VERTEX_POINT('',#4866);\r\n#4869=CARTESIAN_POINT('',(1.82575E1,1.E0,9.E0));\r\n#4870=CARTESIAN_POINT('',(1.77425E1,1.E0,9.E0));\r\n#4871=VERTEX_POINT('',#4869);\r\n#4872=VERTEX_POINT('',#4870);\r\n#4873=CARTESIAN_POINT('',(1.82575E1,1.5E0,9.E0));\r\n#4874=CARTESIAN_POINT('',(1.77425E1,1.5E0,9.E0));\r\n#4875=VERTEX_POINT('',#4873);\r\n#4876=VERTEX_POINT('',#4874);\r\n#4877=CARTESIAN_POINT('',(1.81925E1,1.E0,9.E0));\r\n#4878=CARTESIAN_POINT('',(1.78075E1,1.E0,9.E0));\r\n#4879=VERTEX_POINT('',#4877);\r\n#4880=VERTEX_POINT('',#4878);\r\n#4881=CARTESIAN_POINT('',(6.2575E0,1.E0,1.8E1));\r\n#4882=CARTESIAN_POINT('',(5.7425E0,1.E0,1.8E1));\r\n#4883=VERTEX_POINT('',#4881);\r\n#4884=VERTEX_POINT('',#4882);\r\n#4885=CARTESIAN_POINT('',(6.2575E0,1.5E0,1.8E1));\r\n#4886=CARTESIAN_POINT('',(5.7425E0,1.5E0,1.8E1));\r\n#4887=VERTEX_POINT('',#4885);\r\n#4888=VERTEX_POINT('',#4886);\r\n#4889=CARTESIAN_POINT('',(6.1925E0,1.E0,1.8E1));\r\n#4890=CARTESIAN_POINT('',(5.8075E0,1.E0,1.8E1));\r\n#4891=VERTEX_POINT('',#4889);\r\n#4892=VERTEX_POINT('',#4890);\r\n#4893=CARTESIAN_POINT('',(1.22575E1,1.E0,1.8E1));\r\n#4894=CARTESIAN_POINT('',(1.17425E1,1.E0,1.8E1));\r\n#4895=VERTEX_POINT('',#4893);\r\n#4896=VERTEX_POINT('',#4894);\r\n#4897=CARTESIAN_POINT('',(1.22575E1,1.5E0,1.8E1));\r\n#4898=CARTESIAN_POINT('',(1.17425E1,1.5E0,1.8E1));\r\n#4899=VERTEX_POINT('',#4897);\r\n#4900=VERTEX_POINT('',#4898);\r\n#4901=CARTESIAN_POINT('',(1.21925E1,1.E0,1.8E1));\r\n#4902=CARTESIAN_POINT('',(1.18075E1,1.E0,1.8E1));\r\n#4903=VERTEX_POINT('',#4901);\r\n#4904=VERTEX_POINT('',#4902);\r\n#4905=CARTESIAN_POINT('',(1.82575E1,1.E0,1.8E1));\r\n#4906=CARTESIAN_POINT('',(1.77425E1,1.E0,1.8E1));\r\n#4907=VERTEX_POINT('',#4905);\r\n#4908=VERTEX_POINT('',#4906);\r\n#4909=CARTESIAN_POINT('',(1.82575E1,1.5E0,1.8E1));\r\n#4910=CARTESIAN_POINT('',(1.77425E1,1.5E0,1.8E1));\r\n#4911=VERTEX_POINT('',#4909);\r\n#4912=VERTEX_POINT('',#4910);\r\n#4913=CARTESIAN_POINT('',(1.81925E1,1.E0,1.8E1));\r\n#4914=CARTESIAN_POINT('',(1.78075E1,1.E0,1.8E1));\r\n#4915=VERTEX_POINT('',#4913);\r\n#4916=VERTEX_POINT('',#4914);\r\n#4917=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1));\r\n#4918=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.E1));\r\n#4919=VERTEX_POINT('',#4917);\r\n#4920=VERTEX_POINT('',#4918);\r\n#4921=CARTESIAN_POINT('',(2.E0,1.5E0,1.288675134595E1));\r\n#4922=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1));\r\n#4923=VERTEX_POINT('',#4921);\r\n#4924=VERTEX_POINT('',#4922);\r\n#4925=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1));\r\n#4926=VERTEX_POINT('',#4925);\r\n#4927=CARTESIAN_POINT('',(2.E0,6.5E0,1.E1));\r\n#4928=VERTEX_POINT('',#4927);\r\n#4929=VERTEX_POINT('',#1837);\r\n#4930=VERTEX_POINT('',#1845);\r\n#4931=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1));\r\n#4932=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1));\r\n#4933=VERTEX_POINT('',#4931);\r\n#4934=VERTEX_POINT('',#4932);\r\n#4935=CARTESIAN_POINT('',(2.2E1,1.5E0,1.288675134595E1));\r\n#4936=CARTESIAN_POINT('',(2.2E1,1.5E0,1.E1));\r\n#4937=VERTEX_POINT('',#4935);\r\n#4938=VERTEX_POINT('',#4936);\r\n#4939=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1));\r\n#4940=VERTEX_POINT('',#4939);\r\n#4941=CARTESIAN_POINT('',(2.2E1,6.5E0,1.E1));\r\n#4942=VERTEX_POINT('',#4941);\r\n#4943=VERTEX_POINT('',#2873);\r\n#4944=VERTEX_POINT('',#2881);\r\n#4945=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0));\r\n#4946=CARTESIAN_POINT('',(3.75E0,2.E0,8.5E0));\r\n#4947=VERTEX_POINT('',#4945);\r\n#4948=VERTEX_POINT('',#4946);\r\n#4949=CARTESIAN_POINT('',(4.5E0,2.75E0,8.E0));\r\n#4950=CARTESIAN_POINT('',(4.5E0,2.75E0,8.5E0));\r\n#4951=VERTEX_POINT('',#4949);\r\n#4952=VERTEX_POINT('',#4950);\r\n#4953=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0));\r\n#4954=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.5E0));\r\n#4955=VERTEX_POINT('',#4953);\r\n#4956=VERTEX_POINT('',#4954);\r\n#4957=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.E0));\r\n#4958=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.5E0));\r\n#4959=VERTEX_POINT('',#4957);\r\n#4960=VERTEX_POINT('',#4958);\r\n#4961=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0));\r\n#4962=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.5E0));\r\n#4963=VERTEX_POINT('',#4961);\r\n#4964=VERTEX_POINT('',#4962);\r\n#4965=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.E0));\r\n#4966=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.5E0));\r\n#4967=VERTEX_POINT('',#4965);\r\n#4968=VERTEX_POINT('',#4966);\r\n#4969=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0));\r\n#4970=CARTESIAN_POINT('',(4.5E0,8.75E0,8.5E0));\r\n#4971=VERTEX_POINT('',#4969);\r\n#4972=VERTEX_POINT('',#4970);\r\n#4973=CARTESIAN_POINT('',(3.75E0,9.5E0,8.E0));\r\n#4974=CARTESIAN_POINT('',(3.75E0,9.5E0,8.5E0));\r\n#4975=VERTEX_POINT('',#4973);\r\n#4976=VERTEX_POINT('',#4974);\r\n#4977=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1));\r\n#4978=CARTESIAN_POINT('',(2.85E0,2.E0,9.5E0));\r\n#4979=VERTEX_POINT('',#4977);\r\n#4980=VERTEX_POINT('',#4978);\r\n#4981=CARTESIAN_POINT('',(2.5E0,2.35E0,1.E1));\r\n#4982=CARTESIAN_POINT('',(2.5E0,2.35E0,9.5E0));\r\n#4983=VERTEX_POINT('',#4981);\r\n#4984=VERTEX_POINT('',#4982);\r\n#4985=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1));\r\n#4986=CARTESIAN_POINT('',(4.5E0,2.35E0,9.5E0));\r\n#4987=VERTEX_POINT('',#4985);\r\n#4988=VERTEX_POINT('',#4986);\r\n#4989=CARTESIAN_POINT('',(4.15E0,2.E0,1.E1));\r\n#4990=CARTESIAN_POINT('',(4.15E0,2.E0,9.5E0));\r\n#4991=VERTEX_POINT('',#4989);\r\n#4992=VERTEX_POINT('',#4990);\r\n#4993=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1));\r\n#4994=CARTESIAN_POINT('',(1.952799239454E0,7.E0,9.5E0));\r\n#4995=VERTEX_POINT('',#4993);\r\n#4996=VERTEX_POINT('',#4994);\r\n#4997=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,1.E1));\r\n#4998=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,9.5E0));\r\n#4999=VERTEX_POINT('',#4997);\r\n#5000=VERTEX_POINT('',#4998);\r\n#5001=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1));\r\n#5002=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,9.5E0));\r\n#5003=VERTEX_POINT('',#5001);\r\n#5004=VERTEX_POINT('',#5002);\r\n#5005=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,1.E1));\r\n#5006=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,9.5E0));\r\n#5007=VERTEX_POINT('',#5005);\r\n#5008=VERTEX_POINT('',#5006);\r\n#5009=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1));\r\n#5010=CARTESIAN_POINT('',(4.15E0,9.5E0,9.5E0));\r\n#5011=VERTEX_POINT('',#5009);\r\n#5012=VERTEX_POINT('',#5010);\r\n#5013=CARTESIAN_POINT('',(4.5E0,9.15E0,1.E1));\r\n#5014=CARTESIAN_POINT('',(4.5E0,9.15E0,9.5E0));\r\n#5015=VERTEX_POINT('',#5013);\r\n#5016=VERTEX_POINT('',#5014);\r\n#5017=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0));\r\n#5018=CARTESIAN_POINT('',(2.5E0,6.65E0,1.E1));\r\n#5019=VERTEX_POINT('',#5017);\r\n#5020=VERTEX_POINT('',#5018);\r\n#5021=CARTESIAN_POINT('',(2.15E0,7.E0,1.E1));\r\n#5022=VERTEX_POINT('',#5021);\r\n#5023=CARTESIAN_POINT('',(2.15E0,7.E0,9.5E0));\r\n#5024=VERTEX_POINT('',#5023);\r\n#5025=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0));\r\n#5026=CARTESIAN_POINT('',(2.025E1,2.E0,8.E0));\r\n#5027=VERTEX_POINT('',#5025);\r\n#5028=VERTEX_POINT('',#5026);\r\n#5029=CARTESIAN_POINT('',(1.95E1,2.75E0,8.5E0));\r\n#5030=VERTEX_POINT('',#5029);\r\n#5031=CARTESIAN_POINT('',(1.95E1,2.75E0,8.E0));\r\n#5032=VERTEX_POINT('',#5031);\r\n#5033=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0));\r\n#5034=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.E0));\r\n#5035=VERTEX_POINT('',#5033);\r\n#5036=VERTEX_POINT('',#5034);\r\n#5037=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.5E0));\r\n#5038=VERTEX_POINT('',#5037);\r\n#5039=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.E0));\r\n#5040=VERTEX_POINT('',#5039);\r\n#5041=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0));\r\n#5042=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.E0));\r\n#5043=VERTEX_POINT('',#5041);\r\n#5044=VERTEX_POINT('',#5042);\r\n#5045=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.5E0));\r\n#5046=VERTEX_POINT('',#5045);\r\n#5047=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.E0));\r\n#5048=VERTEX_POINT('',#5047);\r\n#5049=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0));\r\n#5050=CARTESIAN_POINT('',(1.95E1,8.75E0,8.E0));\r\n#5051=VERTEX_POINT('',#5049);\r\n#5052=VERTEX_POINT('',#5050);\r\n#5053=CARTESIAN_POINT('',(2.025E1,9.5E0,8.5E0));\r\n#5054=VERTEX_POINT('',#5053);\r\n#5055=CARTESIAN_POINT('',(2.025E1,9.5E0,8.E0));\r\n#5056=VERTEX_POINT('',#5055);\r\n#5057=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0));\r\n#5058=CARTESIAN_POINT('',(2.115E1,2.E0,1.E1));\r\n#5059=VERTEX_POINT('',#5057);\r\n#5060=VERTEX_POINT('',#5058);\r\n#5061=CARTESIAN_POINT('',(2.15E1,2.35E0,9.5E0));\r\n#5062=VERTEX_POINT('',#5061);\r\n#5063=CARTESIAN_POINT('',(2.15E1,2.35E0,1.E1));\r\n#5064=VERTEX_POINT('',#5063);\r\n#5065=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0));\r\n#5066=CARTESIAN_POINT('',(1.95E1,2.35E0,1.E1));\r\n#5067=VERTEX_POINT('',#5065);\r\n#5068=VERTEX_POINT('',#5066);\r\n#5069=CARTESIAN_POINT('',(1.985E1,2.E0,9.5E0));\r\n#5070=VERTEX_POINT('',#5069);\r\n#5071=CARTESIAN_POINT('',(1.985E1,2.E0,1.E1));\r\n#5072=VERTEX_POINT('',#5071);\r\n#5073=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0));\r\n#5074=CARTESIAN_POINT('',(2.204720076055E1,7.E0,1.E1));\r\n#5075=VERTEX_POINT('',#5073);\r\n#5076=VERTEX_POINT('',#5074);\r\n#5077=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,9.5E0));\r\n#5078=VERTEX_POINT('',#5077);\r\n#5079=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,1.E1));\r\n#5080=VERTEX_POINT('',#5079);\r\n#5081=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0));\r\n#5082=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,1.E1));\r\n#5083=VERTEX_POINT('',#5081);\r\n#5084=VERTEX_POINT('',#5082);\r\n#5085=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,9.5E0));\r\n#5086=VERTEX_POINT('',#5085);\r\n#5087=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,1.E1));\r\n#5088=VERTEX_POINT('',#5087);\r\n#5089=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0));\r\n#5090=CARTESIAN_POINT('',(1.985E1,9.5E0,1.E1));\r\n#5091=VERTEX_POINT('',#5089);\r\n#5092=VERTEX_POINT('',#5090);\r\n#5093=CARTESIAN_POINT('',(1.95E1,9.15E0,9.5E0));\r\n#5094=VERTEX_POINT('',#5093);\r\n#5095=CARTESIAN_POINT('',(1.95E1,9.15E0,1.E1));\r\n#5096=VERTEX_POINT('',#5095);\r\n#5097=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1));\r\n#5098=CARTESIAN_POINT('',(2.15E1,6.65E0,9.5E0));\r\n#5099=VERTEX_POINT('',#5097);\r\n#5100=VERTEX_POINT('',#5098);\r\n#5101=CARTESIAN_POINT('',(2.185E1,7.E0,1.E1));\r\n#5102=CARTESIAN_POINT('',(2.185E1,7.E0,9.5E0));\r\n#5103=VERTEX_POINT('',#5101);\r\n#5104=VERTEX_POINT('',#5102);\r\n#5105=CARTESIAN_POINT('',(7.5E0,6.875E-1,6.875E-1));\r\n#5106=CARTESIAN_POINT('',(1.05E1,6.875E-1,6.875E-1));\r\n#5107=VERTEX_POINT('',#5105);\r\n#5108=VERTEX_POINT('',#5106);\r\n#5109=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8125E0));\r\n#5110=VERTEX_POINT('',#5109);\r\n#5111=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.8125E0));\r\n#5112=VERTEX_POINT('',#5111);\r\n#5113=CARTESIAN_POINT('',(3.939978538987E0,6.875E-1,1.032293285145E0));\r\n#5114=CARTESIAN_POINT('',(4.942849714544E0,6.875E-1,2.419779663480E0));\r\n#5115=VERTEX_POINT('',#5113);\r\n#5116=VERTEX_POINT('',#5114);\r\n#5117=CARTESIAN_POINT('',(2.432015885023E0,6.875E-1,4.918683812405E0));\r\n#5118=VERTEX_POINT('',#5117);\r\n#5119=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1));\r\n#5120=CARTESIAN_POINT('',(1.05E1,0.E0,6.875E-1));\r\n#5121=VERTEX_POINT('',#5119);\r\n#5122=VERTEX_POINT('',#5120);\r\n#5123=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0));\r\n#5124=VERTEX_POINT('',#5123);\r\n#5125=CARTESIAN_POINT('',(7.5E0,0.E0,1.8125E0));\r\n#5126=VERTEX_POINT('',#5125);\r\n#5127=CARTESIAN_POINT('',(3.939978538987E0,0.E0,1.032293285145E0));\r\n#5128=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.419779663480E0));\r\n#5129=VERTEX_POINT('',#5127);\r\n#5130=VERTEX_POINT('',#5128);\r\n#5131=CARTESIAN_POINT('',(2.432015885023E0,0.E0,4.918683812405E0));\r\n#5132=VERTEX_POINT('',#5131);\r\n#5133=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0));\r\n#5134=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,4.046865146430E0));\r\n#5135=VERTEX_POINT('',#5133);\r\n#5136=VERTEX_POINT('',#5134);\r\n#5137=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,4.912826677187E0));\r\n#5138=CARTESIAN_POINT('',(7.850270400779E-1,6.875E-1,4.912826677187E0));\r\n#5139=VERTEX_POINT('',#5137);\r\n#5140=VERTEX_POINT('',#5138);\r\n#5141=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.5E0));\r\n#5142=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.5E0));\r\n#5143=VERTEX_POINT('',#5141);\r\n#5144=VERTEX_POINT('',#5142);\r\n#5145=CARTESIAN_POINT('',(6.9E-1,0.E0,7.5E0));\r\n#5146=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0));\r\n#5147=VERTEX_POINT('',#5145);\r\n#5148=VERTEX_POINT('',#5146);\r\n#5149=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1));\r\n#5150=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,1.0375E1));\r\n#5151=VERTEX_POINT('',#5149);\r\n#5152=VERTEX_POINT('',#5150);\r\n#5153=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.125E1));\r\n#5154=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,1.125E1));\r\n#5155=VERTEX_POINT('',#5153);\r\n#5156=VERTEX_POINT('',#5154);\r\n#5157=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0));\r\n#5158=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,8.69E0));\r\n#5159=VERTEX_POINT('',#5157);\r\n#5160=VERTEX_POINT('',#5158);\r\n#5161=CARTESIAN_POINT('',(-1.3125E0,0.E0,9.565E0));\r\n#5162=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,9.565E0));\r\n#5163=VERTEX_POINT('',#5161);\r\n#5164=VERTEX_POINT('',#5162);\r\n#5165=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0));\r\n#5166=CARTESIAN_POINT('',(4.3125E0,6.875E-1,9.565E0));\r\n#5167=VERTEX_POINT('',#5165);\r\n#5168=VERTEX_POINT('',#5166);\r\n#5169=CARTESIAN_POINT('',(3.4375E0,0.E0,8.69E0));\r\n#5170=CARTESIAN_POINT('',(3.4375E0,6.875E-1,8.69E0));\r\n#5171=VERTEX_POINT('',#5169);\r\n#5172=VERTEX_POINT('',#5170);\r\n#5173=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1));\r\n#5174=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.125E1));\r\n#5175=VERTEX_POINT('',#5173);\r\n#5176=VERTEX_POINT('',#5174);\r\n#5177=CARTESIAN_POINT('',(4.3125E0,0.E0,1.0375E1));\r\n#5178=CARTESIAN_POINT('',(4.3125E0,6.875E-1,1.0375E1));\r\n#5179=VERTEX_POINT('',#5177);\r\n#5180=VERTEX_POINT('',#5178);\r\n#5181=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0));\r\n#5182=CARTESIAN_POINT('',(6.9E-1,0.E0,7.815E0));\r\n#5183=VERTEX_POINT('',#5181);\r\n#5184=VERTEX_POINT('',#5182);\r\n#5185=CARTESIAN_POINT('',(-1.85E-1,0.E0,8.69E0));\r\n#5186=VERTEX_POINT('',#5185);\r\n#5187=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,8.69E0));\r\n#5188=VERTEX_POINT('',#5187);\r\n#5189=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0));\r\n#5190=CARTESIAN_POINT('',(2.6875E0,0.E0,8.69E0));\r\n#5191=VERTEX_POINT('',#5189);\r\n#5192=VERTEX_POINT('',#5190);\r\n#5193=CARTESIAN_POINT('',(1.8125E0,0.E0,7.815E0));\r\n#5194=VERTEX_POINT('',#5193);\r\n#5195=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.815E0));\r\n#5196=VERTEX_POINT('',#5195);\r\n#5197=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.65E1));\r\n#5198=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.35E1));\r\n#5199=VERTEX_POINT('',#5197);\r\n#5200=VERTEX_POINT('',#5198);\r\n#5201=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.35E1));\r\n#5202=VERTEX_POINT('',#5201);\r\n#5203=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.65E1));\r\n#5204=VERTEX_POINT('',#5203);\r\n#5205=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1));\r\n#5206=CARTESIAN_POINT('',(6.875E-1,0.E0,1.35E1));\r\n#5207=VERTEX_POINT('',#5205);\r\n#5208=VERTEX_POINT('',#5206);\r\n#5209=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1));\r\n#5210=VERTEX_POINT('',#5209);\r\n#5211=CARTESIAN_POINT('',(1.8125E0,0.E0,1.65E1));\r\n#5212=VERTEX_POINT('',#5211);\r\n#5213=CARTESIAN_POINT('',(6.875E-1,6.875E-1,2.25E1));\r\n#5214=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.95E1));\r\n#5215=VERTEX_POINT('',#5213);\r\n#5216=VERTEX_POINT('',#5214);\r\n#5217=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.95E1));\r\n#5218=VERTEX_POINT('',#5217);\r\n#5219=CARTESIAN_POINT('',(1.8125E0,6.875E-1,2.25E1));\r\n#5220=VERTEX_POINT('',#5219);\r\n#5221=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1));\r\n#5222=CARTESIAN_POINT('',(6.875E-1,0.E0,1.95E1));\r\n#5223=VERTEX_POINT('',#5221);\r\n#5224=VERTEX_POINT('',#5222);\r\n#5225=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1));\r\n#5226=VERTEX_POINT('',#5225);\r\n#5227=CARTESIAN_POINT('',(1.8125E0,0.E0,2.25E1));\r\n#5228=VERTEX_POINT('',#5227);\r\n#5229=CARTESIAN_POINT('',(7.5E0,6.875E-1,8.5E0));\r\n#5230=CARTESIAN_POINT('',(1.05E1,6.875E-1,8.5E0));\r\n#5231=VERTEX_POINT('',#5229);\r\n#5232=VERTEX_POINT('',#5230);\r\n#5233=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.5E0));\r\n#5234=VERTEX_POINT('',#5233);\r\n#5235=CARTESIAN_POINT('',(7.5E0,6.875E-1,9.5E0));\r\n#5236=VERTEX_POINT('',#5235);\r\n#5237=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0));\r\n#5238=CARTESIAN_POINT('',(1.05E1,0.E0,8.5E0));\r\n#5239=VERTEX_POINT('',#5237);\r\n#5240=VERTEX_POINT('',#5238);\r\n#5241=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0));\r\n#5242=VERTEX_POINT('',#5241);\r\n#5243=CARTESIAN_POINT('',(7.5E0,0.E0,9.5E0));\r\n#5244=VERTEX_POINT('',#5243);\r\n#5245=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.75625E1));\r\n#5246=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.75625E1));\r\n#5247=VERTEX_POINT('',#5245);\r\n#5248=VERTEX_POINT('',#5246);\r\n#5249=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.84375E1));\r\n#5250=VERTEX_POINT('',#5249);\r\n#5251=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.84375E1));\r\n#5252=VERTEX_POINT('',#5251);\r\n#5253=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1));\r\n#5254=CARTESIAN_POINT('',(1.05E1,0.E0,1.75625E1));\r\n#5255=VERTEX_POINT('',#5253);\r\n#5256=VERTEX_POINT('',#5254);\r\n#5257=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1));\r\n#5258=VERTEX_POINT('',#5257);\r\n#5259=CARTESIAN_POINT('',(7.5E0,0.E0,1.84375E1));\r\n#5260=VERTEX_POINT('',#5259);\r\n#5261=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.13125E1));\r\n#5262=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.13125E1));\r\n#5263=VERTEX_POINT('',#5261);\r\n#5264=VERTEX_POINT('',#5262);\r\n#5265=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.01875E1));\r\n#5266=VERTEX_POINT('',#5265);\r\n#5267=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.01875E1));\r\n#5268=VERTEX_POINT('',#5267);\r\n#5269=CARTESIAN_POINT('',(3.939978538987E0,6.875E-1,3.096770671486E1));\r\n#5270=CARTESIAN_POINT('',(4.942849714544E0,6.875E-1,2.958022033652E1));\r\n#5271=VERTEX_POINT('',#5269);\r\n#5272=VERTEX_POINT('',#5270);\r\n#5273=CARTESIAN_POINT('',(2.432015885023E0,6.875E-1,2.708131618759E1));\r\n#5274=VERTEX_POINT('',#5273);\r\n#5275=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1));\r\n#5276=CARTESIAN_POINT('',(1.05E1,0.E0,3.13125E1));\r\n#5277=VERTEX_POINT('',#5275);\r\n#5278=VERTEX_POINT('',#5276);\r\n#5279=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1));\r\n#5280=VERTEX_POINT('',#5279);\r\n#5281=CARTESIAN_POINT('',(7.5E0,0.E0,3.01875E1));\r\n#5282=VERTEX_POINT('',#5281);\r\n#5283=CARTESIAN_POINT('',(3.939978538987E0,0.E0,3.096770671486E1));\r\n#5284=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.958022033652E1));\r\n#5285=VERTEX_POINT('',#5283);\r\n#5286=VERTEX_POINT('',#5284);\r\n#5287=CARTESIAN_POINT('',(2.432015885023E0,0.E0,2.708131618759E1));\r\n#5288=VERTEX_POINT('',#5287);\r\n#5289=CARTESIAN_POINT('',(1.65E1,6.875E-1,6.875E-1));\r\n#5290=CARTESIAN_POINT('',(1.35E1,6.875E-1,6.875E-1));\r\n#5291=VERTEX_POINT('',#5289);\r\n#5292=VERTEX_POINT('',#5290);\r\n#5293=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8125E0));\r\n#5294=VERTEX_POINT('',#5293);\r\n#5295=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.8125E0));\r\n#5296=VERTEX_POINT('',#5295);\r\n#5297=CARTESIAN_POINT('',(2.006002146101E1,6.875E-1,1.032293285145E0));\r\n#5298=CARTESIAN_POINT('',(1.905715028546E1,6.875E-1,2.419779663480E0));\r\n#5299=VERTEX_POINT('',#5297);\r\n#5300=VERTEX_POINT('',#5298);\r\n#5301=CARTESIAN_POINT('',(2.156798411498E1,6.875E-1,4.918683812405E0));\r\n#5302=VERTEX_POINT('',#5301);\r\n#5303=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1));\r\n#5304=CARTESIAN_POINT('',(1.35E1,0.E0,6.875E-1));\r\n#5305=VERTEX_POINT('',#5303);\r\n#5306=VERTEX_POINT('',#5304);\r\n#5307=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0));\r\n#5308=VERTEX_POINT('',#5307);\r\n#5309=CARTESIAN_POINT('',(1.65E1,0.E0,1.8125E0));\r\n#5310=VERTEX_POINT('',#5309);\r\n#5311=CARTESIAN_POINT('',(2.006002146101E1,0.E0,1.032293285145E0));\r\n#5312=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.419779663480E0));\r\n#5313=VERTEX_POINT('',#5311);\r\n#5314=VERTEX_POINT('',#5312);\r\n#5315=CARTESIAN_POINT('',(2.156798411498E1,0.E0,4.918683812405E0));\r\n#5316=VERTEX_POINT('',#5315);\r\n#5317=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.5E0));\r\n#5318=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.5E0));\r\n#5319=VERTEX_POINT('',#5317);\r\n#5320=VERTEX_POINT('',#5318);\r\n#5321=CARTESIAN_POINT('',(2.331E1,0.E0,7.5E0));\r\n#5322=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0));\r\n#5323=VERTEX_POINT('',#5321);\r\n#5324=VERTEX_POINT('',#5322);\r\n#5325=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.65E1));\r\n#5326=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.35E1));\r\n#5327=VERTEX_POINT('',#5325);\r\n#5328=VERTEX_POINT('',#5326);\r\n#5329=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.35E1));\r\n#5330=VERTEX_POINT('',#5329);\r\n#5331=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.65E1));\r\n#5332=VERTEX_POINT('',#5331);\r\n#5333=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1));\r\n#5334=CARTESIAN_POINT('',(2.33125E1,0.E0,1.35E1));\r\n#5335=VERTEX_POINT('',#5333);\r\n#5336=VERTEX_POINT('',#5334);\r\n#5337=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1));\r\n#5338=VERTEX_POINT('',#5337);\r\n#5339=CARTESIAN_POINT('',(2.21875E1,0.E0,1.65E1));\r\n#5340=VERTEX_POINT('',#5339);\r\n#5341=CARTESIAN_POINT('',(2.33125E1,6.875E-1,2.25E1));\r\n#5342=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.95E1));\r\n#5343=VERTEX_POINT('',#5341);\r\n#5344=VERTEX_POINT('',#5342);\r\n#5345=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.95E1));\r\n#5346=VERTEX_POINT('',#5345);\r\n#5347=CARTESIAN_POINT('',(2.21875E1,6.875E-1,2.25E1));\r\n#5348=VERTEX_POINT('',#5347);\r\n#5349=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1));\r\n#5350=CARTESIAN_POINT('',(2.33125E1,0.E0,1.95E1));\r\n#5351=VERTEX_POINT('',#5349);\r\n#5352=VERTEX_POINT('',#5350);\r\n#5353=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1));\r\n#5354=VERTEX_POINT('',#5353);\r\n#5355=CARTESIAN_POINT('',(2.21875E1,0.E0,2.25E1));\r\n#5356=VERTEX_POINT('',#5355);\r\n#5357=CARTESIAN_POINT('',(1.65E1,6.875E-1,8.5E0));\r\n#5358=CARTESIAN_POINT('',(1.35E1,6.875E-1,8.5E0));\r\n#5359=VERTEX_POINT('',#5357);\r\n#5360=VERTEX_POINT('',#5358);\r\n#5361=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.5E0));\r\n#5362=VERTEX_POINT('',#5361);\r\n#5363=CARTESIAN_POINT('',(1.65E1,6.875E-1,9.5E0));\r\n#5364=VERTEX_POINT('',#5363);\r\n#5365=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0));\r\n#5366=CARTESIAN_POINT('',(1.35E1,0.E0,8.5E0));\r\n#5367=VERTEX_POINT('',#5365);\r\n#5368=VERTEX_POINT('',#5366);\r\n#5369=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0));\r\n#5370=VERTEX_POINT('',#5369);\r\n#5371=CARTESIAN_POINT('',(1.65E1,0.E0,9.5E0));\r\n#5372=VERTEX_POINT('',#5371);\r\n#5373=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.75625E1));\r\n#5374=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.75625E1));\r\n#5375=VERTEX_POINT('',#5373);\r\n#5376=VERTEX_POINT('',#5374);\r\n#5377=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.84375E1));\r\n#5378=VERTEX_POINT('',#5377);\r\n#5379=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.84375E1));\r\n#5380=VERTEX_POINT('',#5379);\r\n#5381=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1));\r\n#5382=CARTESIAN_POINT('',(1.35E1,0.E0,1.75625E1));\r\n#5383=VERTEX_POINT('',#5381);\r\n#5384=VERTEX_POINT('',#5382);\r\n#5385=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1));\r\n#5386=VERTEX_POINT('',#5385);\r\n#5387=CARTESIAN_POINT('',(1.65E1,0.E0,1.84375E1));\r\n#5388=VERTEX_POINT('',#5387);\r\n#5389=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.13125E1));\r\n#5390=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.13125E1));\r\n#5391=VERTEX_POINT('',#5389);\r\n#5392=VERTEX_POINT('',#5390);\r\n#5393=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.01875E1));\r\n#5394=VERTEX_POINT('',#5393);\r\n#5395=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.01875E1));\r\n#5396=VERTEX_POINT('',#5395);\r\n#5397=CARTESIAN_POINT('',(2.006002146101E1,6.875E-1,3.096770671486E1));\r\n#5398=CARTESIAN_POINT('',(1.905715028546E1,6.875E-1,2.958022033652E1));\r\n#5399=VERTEX_POINT('',#5397);\r\n#5400=VERTEX_POINT('',#5398);\r\n#5401=CARTESIAN_POINT('',(2.156798411498E1,6.875E-1,2.708131618759E1));\r\n#5402=VERTEX_POINT('',#5401);\r\n#5403=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1));\r\n#5404=CARTESIAN_POINT('',(1.35E1,0.E0,3.13125E1));\r\n#5405=VERTEX_POINT('',#5403);\r\n#5406=VERTEX_POINT('',#5404);\r\n#5407=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1));\r\n#5408=VERTEX_POINT('',#5407);\r\n#5409=CARTESIAN_POINT('',(1.65E1,0.E0,3.01875E1));\r\n#5410=VERTEX_POINT('',#5409);\r\n#5411=CARTESIAN_POINT('',(2.006002146101E1,0.E0,3.096770671486E1));\r\n#5412=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.958022033652E1));\r\n#5413=VERTEX_POINT('',#5411);\r\n#5414=VERTEX_POINT('',#5412);\r\n#5415=CARTESIAN_POINT('',(2.156798411498E1,0.E0,2.708131618759E1));\r\n#5416=VERTEX_POINT('',#5415);\r\n#5417=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0));\r\n#5418=CARTESIAN_POINT('',(1.96875E1,0.E0,9.57E0));\r\n#5419=VERTEX_POINT('',#5417);\r\n#5420=VERTEX_POINT('',#5418);\r\n#5421=CARTESIAN_POINT('',(2.05675E1,6.875E-1,8.69E0));\r\n#5422=VERTEX_POINT('',#5421);\r\n#5423=CARTESIAN_POINT('',(2.05675E1,0.E0,8.69E0));\r\n#5424=VERTEX_POINT('',#5423);\r\n#5425=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1));\r\n#5426=CARTESIAN_POINT('',(2.05675E1,0.E0,1.125E1));\r\n#5427=VERTEX_POINT('',#5425);\r\n#5428=VERTEX_POINT('',#5426);\r\n#5429=CARTESIAN_POINT('',(1.96875E1,6.875E-1,1.037E1));\r\n#5430=VERTEX_POINT('',#5429);\r\n#5431=CARTESIAN_POINT('',(1.96875E1,0.E0,1.037E1));\r\n#5432=VERTEX_POINT('',#5431);\r\n#5433=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0));\r\n#5434=CARTESIAN_POINT('',(2.44325E1,0.E0,8.69E0));\r\n#5435=VERTEX_POINT('',#5433);\r\n#5436=VERTEX_POINT('',#5434);\r\n#5437=CARTESIAN_POINT('',(2.53125E1,6.875E-1,9.57E0));\r\n#5438=VERTEX_POINT('',#5437);\r\n#5439=CARTESIAN_POINT('',(2.53125E1,0.E0,9.57E0));\r\n#5440=VERTEX_POINT('',#5439);\r\n#5441=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1));\r\n#5442=CARTESIAN_POINT('',(2.53125E1,0.E0,1.037E1));\r\n#5443=VERTEX_POINT('',#5441);\r\n#5444=VERTEX_POINT('',#5442);\r\n#5445=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.125E1));\r\n#5446=VERTEX_POINT('',#5445);\r\n#5447=CARTESIAN_POINT('',(2.44325E1,0.E0,1.125E1));\r\n#5448=VERTEX_POINT('',#5447);\r\n#5449=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0));\r\n#5450=CARTESIAN_POINT('',(2.13075E1,6.875E-1,8.69E0));\r\n#5451=VERTEX_POINT('',#5449);\r\n#5452=VERTEX_POINT('',#5450);\r\n#5453=CARTESIAN_POINT('',(2.21875E1,0.E0,7.81E0));\r\n#5454=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.81E0));\r\n#5455=VERTEX_POINT('',#5453);\r\n#5456=VERTEX_POINT('',#5454);\r\n#5457=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0));\r\n#5458=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.81E0));\r\n#5459=VERTEX_POINT('',#5457);\r\n#5460=VERTEX_POINT('',#5458);\r\n#5461=CARTESIAN_POINT('',(2.419E1,0.E0,8.69E0));\r\n#5462=CARTESIAN_POINT('',(2.419E1,6.875E-1,8.69E0));\r\n#5463=VERTEX_POINT('',#5461);\r\n#5464=VERTEX_POINT('',#5462);\r\n#5465=CARTESIAN_POINT('',(2.321497295992E1,0.E0,4.912826677187E0));\r\n#5466=CARTESIAN_POINT('',(2.321497295992E1,6.875E-1,4.912826677187E0));\r\n#5467=VERTEX_POINT('',#5465);\r\n#5468=VERTEX_POINT('',#5466);\r\n#5469=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0));\r\n#5470=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,4.046865146430E0));\r\n#5471=VERTEX_POINT('',#5469);\r\n#5472=VERTEX_POINT('',#5470);\r\n#5473=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,2.708717332281E1));\r\n#5474=CARTESIAN_POINT('',(7.850270400779E-1,6.875E-1,2.708717332281E1));\r\n#5475=VERTEX_POINT('',#5473);\r\n#5476=VERTEX_POINT('',#5474);\r\n#5477=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1));\r\n#5478=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,2.795313485357E1));\r\n#5479=VERTEX_POINT('',#5477);\r\n#5480=VERTEX_POINT('',#5478);\r\n#5481=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1));\r\n#5482=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,2.795313485357E1));\r\n#5483=VERTEX_POINT('',#5481);\r\n#5484=VERTEX_POINT('',#5482);\r\n#5485=CARTESIAN_POINT('',(2.321497295992E1,0.E0,2.708717332281E1));\r\n#5486=CARTESIAN_POINT('',(2.321497295992E1,6.875E-1,2.708717332281E1));\r\n#5487=VERTEX_POINT('',#5485);\r\n#5488=VERTEX_POINT('',#5486);\r\n#5489=CARTESIAN_POINT('',(0.E0,0.E0,0.E0));\r\n#5490=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#5491=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#5492=AXIS2_PLACEMENT_3D('',#5489,#5490,#5491);\r\n#5493=PLANE('',#5492);\r\n#5495=ORIENTED_EDGE('',*,*,#5494,.F.);\r\n#5497=ORIENTED_EDGE('',*,*,#5496,.F.);\r\n#5499=ORIENTED_EDGE('',*,*,#5498,.T.);\r\n#5501=ORIENTED_EDGE('',*,*,#5500,.F.);\r\n#5503=ORIENTED_EDGE('',*,*,#5502,.T.);\r\n#5505=ORIENTED_EDGE('',*,*,#5504,.F.);\r\n#5507=ORIENTED_EDGE('',*,*,#5506,.T.);\r\n#5509=ORIENTED_EDGE('',*,*,#5508,.F.);\r\n#5511=ORIENTED_EDGE('',*,*,#5510,.T.);\r\n#5513=ORIENTED_EDGE('',*,*,#5512,.T.);\r\n#5515=ORIENTED_EDGE('',*,*,#5514,.F.);\r\n#5517=ORIENTED_EDGE('',*,*,#5516,.T.);\r\n#5519=ORIENTED_EDGE('',*,*,#5518,.F.);\r\n#5521=ORIENTED_EDGE('',*,*,#5520,.T.);\r\n#5523=ORIENTED_EDGE('',*,*,#5522,.F.);\r\n#5525=ORIENTED_EDGE('',*,*,#5524,.T.);\r\n#5527=ORIENTED_EDGE('',*,*,#5526,.F.);\r\n#5529=ORIENTED_EDGE('',*,*,#5528,.T.);\r\n#5531=ORIENTED_EDGE('',*,*,#5530,.F.);\r\n#5533=ORIENTED_EDGE('',*,*,#5532,.F.);\r\n#5535=ORIENTED_EDGE('',*,*,#5534,.T.);\r\n#5537=ORIENTED_EDGE('',*,*,#5536,.F.);\r\n#5538=EDGE_LOOP('',(#5495,#5497,#5499,#5501,#5503,#5505,#5507,#5509,#5511,#5513,\r\n#5515,#5517,#5519,#5521,#5523,#5525,#5527,#5529,#5531,#5533,#5535,#5537));\r\n#5539=FACE_OUTER_BOUND('',#5538,.F.);\r\n#5541=ORIENTED_EDGE('',*,*,#5540,.T.);\r\n#5543=ORIENTED_EDGE('',*,*,#5542,.F.);\r\n#5545=ORIENTED_EDGE('',*,*,#5544,.F.);\r\n#5547=ORIENTED_EDGE('',*,*,#5546,.F.);\r\n#5549=ORIENTED_EDGE('',*,*,#5548,.F.);\r\n#5551=ORIENTED_EDGE('',*,*,#5550,.F.);\r\n#5552=EDGE_LOOP('',(#5541,#5543,#5545,#5547,#5549,#5551));\r\n#5553=FACE_BOUND('',#5552,.F.);\r\n#5555=ORIENTED_EDGE('',*,*,#5554,.T.);\r\n#5557=ORIENTED_EDGE('',*,*,#5556,.T.);\r\n#5558=EDGE_LOOP('',(#5555,#5557));\r\n#5559=FACE_BOUND('',#5558,.F.);\r\n#5561=ORIENTED_EDGE('',*,*,#5560,.T.);\r\n#5563=ORIENTED_EDGE('',*,*,#5562,.T.);\r\n#5564=EDGE_LOOP('',(#5561,#5563));\r\n#5565=FACE_BOUND('',#5564,.F.);\r\n#5567=ORIENTED_EDGE('',*,*,#5566,.T.);\r\n#5569=ORIENTED_EDGE('',*,*,#5568,.T.);\r\n#5570=EDGE_LOOP('',(#5567,#5569));\r\n#5571=FACE_BOUND('',#5570,.F.);\r\n#5573=ORIENTED_EDGE('',*,*,#5572,.T.);\r\n#5575=ORIENTED_EDGE('',*,*,#5574,.T.);\r\n#5576=EDGE_LOOP('',(#5573,#5575));\r\n#5577=FACE_BOUND('',#5576,.F.);\r\n#5579=ORIENTED_EDGE('',*,*,#5578,.T.);\r\n#5581=ORIENTED_EDGE('',*,*,#5580,.T.);\r\n#5582=EDGE_LOOP('',(#5579,#5581));\r\n#5583=FACE_BOUND('',#5582,.F.);\r\n#5585=ORIENTED_EDGE('',*,*,#5584,.T.);\r\n#5587=ORIENTED_EDGE('',*,*,#5586,.T.);\r\n#5588=EDGE_LOOP('',(#5585,#5587));\r\n#5589=FACE_BOUND('',#5588,.F.);\r\n#5591=ORIENTED_EDGE('',*,*,#5590,.T.);\r\n#5593=ORIENTED_EDGE('',*,*,#5592,.T.);\r\n#5594=EDGE_LOOP('',(#5591,#5593));\r\n#5595=FACE_BOUND('',#5594,.F.);\r\n#5597=ORIENTED_EDGE('',*,*,#5596,.T.);\r\n#5599=ORIENTED_EDGE('',*,*,#5598,.T.);\r\n#5600=EDGE_LOOP('',(#5597,#5599));\r\n#5601=FACE_BOUND('',#5600,.F.);\r\n#5603=ORIENTED_EDGE('',*,*,#5602,.T.);\r\n#5605=ORIENTED_EDGE('',*,*,#5604,.T.);\r\n#5606=EDGE_LOOP('',(#5603,#5605));\r\n#5607=FACE_BOUND('',#5606,.F.);\r\n#5609=ORIENTED_EDGE('',*,*,#5608,.T.);\r\n#5611=ORIENTED_EDGE('',*,*,#5610,.T.);\r\n#5612=EDGE_LOOP('',(#5609,#5611));\r\n#5613=FACE_BOUND('',#5612,.F.);\r\n#5615=ORIENTED_EDGE('',*,*,#5614,.T.);\r\n#5617=ORIENTED_EDGE('',*,*,#5616,.T.);\r\n#5618=EDGE_LOOP('',(#5615,#5617));\r\n#5619=FACE_BOUND('',#5618,.F.);\r\n#5621=ORIENTED_EDGE('',*,*,#5620,.T.);\r\n#5623=ORIENTED_EDGE('',*,*,#5622,.T.);\r\n#5624=EDGE_LOOP('',(#5621,#5623));\r\n#5625=FACE_BOUND('',#5624,.F.);\r\n#5627=ORIENTED_EDGE('',*,*,#5626,.T.);\r\n#5629=ORIENTED_EDGE('',*,*,#5628,.T.);\r\n#5630=EDGE_LOOP('',(#5627,#5629));\r\n#5631=FACE_BOUND('',#5630,.F.);\r\n#5633=ORIENTED_EDGE('',*,*,#5632,.T.);\r\n#5635=ORIENTED_EDGE('',*,*,#5634,.T.);\r\n#5636=EDGE_LOOP('',(#5633,#5635));\r\n#5637=FACE_BOUND('',#5636,.F.);\r\n#5639=ORIENTED_EDGE('',*,*,#5638,.T.);\r\n#5641=ORIENTED_EDGE('',*,*,#5640,.F.);\r\n#5643=ORIENTED_EDGE('',*,*,#5642,.F.);\r\n#5645=ORIENTED_EDGE('',*,*,#5644,.F.);\r\n#5647=ORIENTED_EDGE('',*,*,#5646,.F.);\r\n#5649=ORIENTED_EDGE('',*,*,#5648,.F.);\r\n#5651=ORIENTED_EDGE('',*,*,#5650,.F.);\r\n#5653=ORIENTED_EDGE('',*,*,#5652,.F.);\r\n#5654=EDGE_LOOP('',(#5639,#5641,#5643,#5645,#5647,#5649,#5651,#5653));\r\n#5655=FACE_BOUND('',#5654,.F.);\r\n#5657=ORIENTED_EDGE('',*,*,#5656,.F.);\r\n#5659=ORIENTED_EDGE('',*,*,#5658,.F.);\r\n#5661=ORIENTED_EDGE('',*,*,#5660,.T.);\r\n#5663=ORIENTED_EDGE('',*,*,#5662,.F.);\r\n#5665=ORIENTED_EDGE('',*,*,#5664,.F.);\r\n#5667=ORIENTED_EDGE('',*,*,#5666,.F.);\r\n#5669=ORIENTED_EDGE('',*,*,#5668,.T.);\r\n#5671=ORIENTED_EDGE('',*,*,#5670,.F.);\r\n#5673=ORIENTED_EDGE('',*,*,#5672,.T.);\r\n#5675=ORIENTED_EDGE('',*,*,#5674,.F.);\r\n#5677=ORIENTED_EDGE('',*,*,#5676,.T.);\r\n#5679=ORIENTED_EDGE('',*,*,#5678,.F.);\r\n#5681=ORIENTED_EDGE('',*,*,#5680,.F.);\r\n#5683=ORIENTED_EDGE('',*,*,#5682,.T.);\r\n#5685=ORIENTED_EDGE('',*,*,#5684,.F.);\r\n#5687=ORIENTED_EDGE('',*,*,#5686,.F.);\r\n#5688=EDGE_LOOP('',(#5657,#5659,#5661,#5663,#5665,#5667,#5669,#5671,#5673,#5675,\r\n#5677,#5679,#5681,#5683,#5685,#5687));\r\n#5689=FACE_BOUND('',#5688,.F.);\r\n#5691=ORIENTED_EDGE('',*,*,#5690,.T.);\r\n#5693=ORIENTED_EDGE('',*,*,#5692,.T.);\r\n#5694=EDGE_LOOP('',(#5691,#5693));\r\n#5695=FACE_BOUND('',#5694,.F.);\r\n#5697=ORIENTED_EDGE('',*,*,#5696,.T.);\r\n#5699=ORIENTED_EDGE('',*,*,#5698,.T.);\r\n#5700=EDGE_LOOP('',(#5697,#5699));\r\n#5701=FACE_BOUND('',#5700,.F.);\r\n#5703=ORIENTED_EDGE('',*,*,#5702,.T.);\r\n#5705=ORIENTED_EDGE('',*,*,#5704,.T.);\r\n#5706=EDGE_LOOP('',(#5703,#5705));\r\n#5707=FACE_BOUND('',#5706,.F.);\r\n#5709=ORIENTED_EDGE('',*,*,#5708,.T.);\r\n#5711=ORIENTED_EDGE('',*,*,#5710,.T.);\r\n#5712=EDGE_LOOP('',(#5709,#5711));\r\n#5713=FACE_BOUND('',#5712,.F.);\r\n#5715=ORIENTED_EDGE('',*,*,#5714,.T.);\r\n#5717=ORIENTED_EDGE('',*,*,#5716,.T.);\r\n#5718=EDGE_LOOP('',(#5715,#5717));\r\n#5719=FACE_BOUND('',#5718,.F.);\r\n#5721=ORIENTED_EDGE('',*,*,#5720,.T.);\r\n#5723=ORIENTED_EDGE('',*,*,#5722,.T.);\r\n#5724=EDGE_LOOP('',(#5721,#5723));\r\n#5725=FACE_BOUND('',#5724,.F.);\r\n#5727=ORIENTED_EDGE('',*,*,#5726,.T.);\r\n#5729=ORIENTED_EDGE('',*,*,#5728,.T.);\r\n#5731=ORIENTED_EDGE('',*,*,#5730,.T.);\r\n#5733=ORIENTED_EDGE('',*,*,#5732,.T.);\r\n#5734=EDGE_LOOP('',(#5727,#5729,#5731,#5733));\r\n#5735=FACE_BOUND('',#5734,.F.);\r\n#5737=ORIENTED_EDGE('',*,*,#5736,.T.);\r\n#5739=ORIENTED_EDGE('',*,*,#5738,.F.);\r\n#5741=ORIENTED_EDGE('',*,*,#5740,.T.);\r\n#5743=ORIENTED_EDGE('',*,*,#5742,.T.);\r\n#5745=ORIENTED_EDGE('',*,*,#5744,.F.);\r\n#5746=EDGE_LOOP('',(#5737,#5739,#5741,#5743,#5745));\r\n#5747=FACE_BOUND('',#5746,.F.);\r\n#5749=ORIENTED_EDGE('',*,*,#5748,.F.);\r\n#5751=ORIENTED_EDGE('',*,*,#5750,.T.);\r\n#5753=ORIENTED_EDGE('',*,*,#5752,.T.);\r\n#5755=ORIENTED_EDGE('',*,*,#5754,.T.);\r\n#5757=ORIENTED_EDGE('',*,*,#5756,.F.);\r\n#5759=ORIENTED_EDGE('',*,*,#5758,.T.);\r\n#5761=ORIENTED_EDGE('',*,*,#5760,.F.);\r\n#5763=ORIENTED_EDGE('',*,*,#5762,.T.);\r\n#5765=ORIENTED_EDGE('',*,*,#5764,.F.);\r\n#5767=ORIENTED_EDGE('',*,*,#5766,.T.);\r\n#5769=ORIENTED_EDGE('',*,*,#5768,.F.);\r\n#5771=ORIENTED_EDGE('',*,*,#5770,.T.);\r\n#5773=ORIENTED_EDGE('',*,*,#5772,.F.);\r\n#5775=ORIENTED_EDGE('',*,*,#5774,.T.);\r\n#5776=EDGE_LOOP('',(#5749,#5751,#5753,#5755,#5757,#5759,#5761,#5763,#5765,#5767,\r\n#5769,#5771,#5773,#5775));\r\n#5777=FACE_BOUND('',#5776,.F.);\r\n#5779=ORIENTED_EDGE('',*,*,#5778,.T.);\r\n#5781=ORIENTED_EDGE('',*,*,#5780,.T.);\r\n#5783=ORIENTED_EDGE('',*,*,#5782,.T.);\r\n#5785=ORIENTED_EDGE('',*,*,#5784,.T.);\r\n#5786=EDGE_LOOP('',(#5779,#5781,#5783,#5785));\r\n#5787=FACE_BOUND('',#5786,.F.);\r\n#5789=ORIENTED_EDGE('',*,*,#5788,.T.);\r\n#5791=ORIENTED_EDGE('',*,*,#5790,.T.);\r\n#5793=ORIENTED_EDGE('',*,*,#5792,.T.);\r\n#5795=ORIENTED_EDGE('',*,*,#5794,.T.);\r\n#5796=EDGE_LOOP('',(#5789,#5791,#5793,#5795));\r\n#5797=FACE_BOUND('',#5796,.F.);\r\n#5799=ORIENTED_EDGE('',*,*,#5798,.T.);\r\n#5801=ORIENTED_EDGE('',*,*,#5800,.T.);\r\n#5803=ORIENTED_EDGE('',*,*,#5802,.T.);\r\n#5805=ORIENTED_EDGE('',*,*,#5804,.T.);\r\n#5806=EDGE_LOOP('',(#5799,#5801,#5803,#5805));\r\n#5807=FACE_BOUND('',#5806,.F.);\r\n#5809=ORIENTED_EDGE('',*,*,#5808,.T.);\r\n#5811=ORIENTED_EDGE('',*,*,#5810,.T.);\r\n#5813=ORIENTED_EDGE('',*,*,#5812,.T.);\r\n#5815=ORIENTED_EDGE('',*,*,#5814,.T.);\r\n#5816=EDGE_LOOP('',(#5809,#5811,#5813,#5815));\r\n#5817=FACE_BOUND('',#5816,.F.);\r\n#5819=ORIENTED_EDGE('',*,*,#5818,.F.);\r\n#5821=ORIENTED_EDGE('',*,*,#5820,.F.);\r\n#5823=ORIENTED_EDGE('',*,*,#5822,.F.);\r\n#5825=ORIENTED_EDGE('',*,*,#5824,.F.);\r\n#5826=EDGE_LOOP('',(#5819,#5821,#5823,#5825));\r\n#5827=FACE_BOUND('',#5826,.F.);\r\n#5829=ORIENTED_EDGE('',*,*,#5828,.F.);\r\n#5831=ORIENTED_EDGE('',*,*,#5830,.F.);\r\n#5833=ORIENTED_EDGE('',*,*,#5832,.F.);\r\n#5835=ORIENTED_EDGE('',*,*,#5834,.F.);\r\n#5836=EDGE_LOOP('',(#5829,#5831,#5833,#5835));\r\n#5837=FACE_BOUND('',#5836,.F.);\r\n#5839=ORIENTED_EDGE('',*,*,#5838,.F.);\r\n#5841=ORIENTED_EDGE('',*,*,#5840,.F.);\r\n#5843=ORIENTED_EDGE('',*,*,#5842,.F.);\r\n#5845=ORIENTED_EDGE('',*,*,#5844,.F.);\r\n#5846=EDGE_LOOP('',(#5839,#5841,#5843,#5845));\r\n#5847=FACE_BOUND('',#5846,.F.);\r\n#5849=ORIENTED_EDGE('',*,*,#5848,.F.);\r\n#5851=ORIENTED_EDGE('',*,*,#5850,.F.);\r\n#5853=ORIENTED_EDGE('',*,*,#5852,.F.);\r\n#5855=ORIENTED_EDGE('',*,*,#5854,.F.);\r\n#5856=EDGE_LOOP('',(#5849,#5851,#5853,#5855));\r\n#5857=FACE_BOUND('',#5856,.F.);\r\n#5859=ORIENTED_EDGE('',*,*,#5858,.F.);\r\n#5861=ORIENTED_EDGE('',*,*,#5860,.F.);\r\n#5863=ORIENTED_EDGE('',*,*,#5862,.F.);\r\n#5865=ORIENTED_EDGE('',*,*,#5864,.F.);\r\n#5866=EDGE_LOOP('',(#5859,#5861,#5863,#5865));\r\n#5867=FACE_BOUND('',#5866,.F.);\r\n#5869=ORIENTED_EDGE('',*,*,#5868,.F.);\r\n#5871=ORIENTED_EDGE('',*,*,#5870,.F.);\r\n#5873=ORIENTED_EDGE('',*,*,#5872,.F.);\r\n#5875=ORIENTED_EDGE('',*,*,#5874,.F.);\r\n#5876=EDGE_LOOP('',(#5869,#5871,#5873,#5875));\r\n#5877=FACE_BOUND('',#5876,.F.);\r\n#5879=ORIENTED_EDGE('',*,*,#5878,.T.);\r\n#5881=ORIENTED_EDGE('',*,*,#5880,.T.);\r\n#5883=ORIENTED_EDGE('',*,*,#5882,.T.);\r\n#5885=ORIENTED_EDGE('',*,*,#5884,.T.);\r\n#5886=EDGE_LOOP('',(#5879,#5881,#5883,#5885));\r\n#5887=FACE_BOUND('',#5886,.F.);\r\n#5889=ORIENTED_EDGE('',*,*,#5888,.F.);\r\n#5891=ORIENTED_EDGE('',*,*,#5890,.F.);\r\n#5893=ORIENTED_EDGE('',*,*,#5892,.F.);\r\n#5895=ORIENTED_EDGE('',*,*,#5894,.F.);\r\n#5897=ORIENTED_EDGE('',*,*,#5896,.F.);\r\n#5899=ORIENTED_EDGE('',*,*,#5898,.F.);\r\n#5901=ORIENTED_EDGE('',*,*,#5900,.F.);\r\n#5903=ORIENTED_EDGE('',*,*,#5902,.F.);\r\n#5905=ORIENTED_EDGE('',*,*,#5904,.F.);\r\n#5907=ORIENTED_EDGE('',*,*,#5906,.F.);\r\n#5909=ORIENTED_EDGE('',*,*,#5908,.F.);\r\n#5911=ORIENTED_EDGE('',*,*,#5910,.F.);\r\n#5913=ORIENTED_EDGE('',*,*,#5912,.F.);\r\n#5915=ORIENTED_EDGE('',*,*,#5914,.F.);\r\n#5916=EDGE_LOOP('',(#5889,#5891,#5893,#5895,#5897,#5899,#5901,#5903,#5905,#5907,\r\n#5909,#5911,#5913,#5915));\r\n#5917=FACE_BOUND('',#5916,.F.);\r\n#5919=ORIENTED_EDGE('',*,*,#5918,.F.);\r\n#5921=ORIENTED_EDGE('',*,*,#5920,.F.);\r\n#5923=ORIENTED_EDGE('',*,*,#5922,.F.);\r\n#5925=ORIENTED_EDGE('',*,*,#5924,.T.);\r\n#5927=ORIENTED_EDGE('',*,*,#5926,.F.);\r\n#5928=EDGE_LOOP('',(#5919,#5921,#5923,#5925,#5927));\r\n#5929=FACE_BOUND('',#5928,.F.);\r\n#5931=ORIENTED_EDGE('',*,*,#5930,.F.);\r\n#5933=ORIENTED_EDGE('',*,*,#5932,.F.);\r\n#5935=ORIENTED_EDGE('',*,*,#5934,.F.);\r\n#5937=ORIENTED_EDGE('',*,*,#5936,.T.);\r\n#5939=ORIENTED_EDGE('',*,*,#5938,.F.);\r\n#5940=EDGE_LOOP('',(#5931,#5933,#5935,#5937,#5939));\r\n#5941=FACE_BOUND('',#5940,.F.);\r\n#5943=ORIENTED_EDGE('',*,*,#5942,.T.);\r\n#5945=ORIENTED_EDGE('',*,*,#5944,.F.);\r\n#5947=ORIENTED_EDGE('',*,*,#5946,.T.);\r\n#5949=ORIENTED_EDGE('',*,*,#5948,.T.);\r\n#5951=ORIENTED_EDGE('',*,*,#5950,.F.);\r\n#5952=EDGE_LOOP('',(#5943,#5945,#5947,#5949,#5951));\r\n#5953=FACE_BOUND('',#5952,.F.);\r\n#5954=ADVANCED_FACE('',(#5539,#5553,#5559,#5565,#5571,#5577,#5583,#5589,#5595,\r\n#5601,#5607,#5613,#5619,#5625,#5631,#5637,#5655,#5689,#5695,#5701,#5707,#5713,\r\n#5719,#5725,#5735,#5747,#5777,#5787,#5797,#5807,#5817,#5827,#5837,#5847,#5857,\r\n#5867,#5877,#5887,#5917,#5929,#5941,#5953),#5493,.F.);\r\n#5955=CARTESIAN_POINT('',(0.E0,0.E0,8.E0));\r\n#5956=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#5957=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#5958=AXIS2_PLACEMENT_3D('',#5955,#5956,#5957);\r\n#5959=PLANE('',#5958);\r\n#5960=ORIENTED_EDGE('',*,*,#5540,.F.);\r\n#5962=ORIENTED_EDGE('',*,*,#5961,.T.);\r\n#5964=ORIENTED_EDGE('',*,*,#5963,.F.);\r\n#5966=ORIENTED_EDGE('',*,*,#5965,.F.);\r\n#5967=ORIENTED_EDGE('',*,*,#5494,.T.);\r\n#5969=ORIENTED_EDGE('',*,*,#5968,.F.);\r\n#5971=ORIENTED_EDGE('',*,*,#5970,.F.);\r\n#5973=ORIENTED_EDGE('',*,*,#5972,.T.);\r\n#5975=ORIENTED_EDGE('',*,*,#5974,.F.);\r\n#5977=ORIENTED_EDGE('',*,*,#5976,.F.);\r\n#5979=ORIENTED_EDGE('',*,*,#5978,.F.);\r\n#5981=ORIENTED_EDGE('',*,*,#5980,.T.);\r\n#5983=ORIENTED_EDGE('',*,*,#5982,.T.);\r\n#5985=ORIENTED_EDGE('',*,*,#5984,.F.);\r\n#5986=ORIENTED_EDGE('',*,*,#5510,.F.);\r\n#5988=ORIENTED_EDGE('',*,*,#5987,.F.);\r\n#5990=ORIENTED_EDGE('',*,*,#5989,.F.);\r\n#5992=ORIENTED_EDGE('',*,*,#5991,.T.);\r\n#5993=EDGE_LOOP('',(#5960,#5962,#5964,#5966,#5967,#5969,#5971,#5973,#5975,#5977,\r\n#5979,#5981,#5983,#5985,#5986,#5988,#5990,#5992));\r\n#5994=FACE_OUTER_BOUND('',#5993,.F.);\r\n#5996=ORIENTED_EDGE('',*,*,#5995,.T.);\r\n#5998=ORIENTED_EDGE('',*,*,#5997,.T.);\r\n#5999=EDGE_LOOP('',(#5996,#5998));\r\n#6000=FACE_BOUND('',#5999,.F.);\r\n#6002=ORIENTED_EDGE('',*,*,#6001,.T.);\r\n#6004=ORIENTED_EDGE('',*,*,#6003,.T.);\r\n#6005=EDGE_LOOP('',(#6002,#6004));\r\n#6006=FACE_BOUND('',#6005,.F.);\r\n#6008=ORIENTED_EDGE('',*,*,#6007,.T.);\r\n#6010=ORIENTED_EDGE('',*,*,#6009,.T.);\r\n#6011=EDGE_LOOP('',(#6008,#6010));\r\n#6012=FACE_BOUND('',#6011,.F.);\r\n#6014=ORIENTED_EDGE('',*,*,#6013,.T.);\r\n#6016=ORIENTED_EDGE('',*,*,#6015,.T.);\r\n#6017=EDGE_LOOP('',(#6014,#6016));\r\n#6018=FACE_BOUND('',#6017,.F.);\r\n#6020=ORIENTED_EDGE('',*,*,#6019,.F.);\r\n#6022=ORIENTED_EDGE('',*,*,#6021,.F.);\r\n#6023=EDGE_LOOP('',(#6020,#6022));\r\n#6024=FACE_BOUND('',#6023,.F.);\r\n#6026=ORIENTED_EDGE('',*,*,#6025,.F.);\r\n#6028=ORIENTED_EDGE('',*,*,#6027,.F.);\r\n#6029=EDGE_LOOP('',(#6026,#6028));\r\n#6030=FACE_BOUND('',#6029,.F.);\r\n#6032=ORIENTED_EDGE('',*,*,#6031,.F.);\r\n#6034=ORIENTED_EDGE('',*,*,#6033,.F.);\r\n#6035=EDGE_LOOP('',(#6032,#6034));\r\n#6036=FACE_BOUND('',#6035,.F.);\r\n#6038=ORIENTED_EDGE('',*,*,#6037,.F.);\r\n#6040=ORIENTED_EDGE('',*,*,#6039,.F.);\r\n#6041=EDGE_LOOP('',(#6038,#6040));\r\n#6042=FACE_BOUND('',#6041,.F.);\r\n#6044=ORIENTED_EDGE('',*,*,#6043,.T.);\r\n#6046=ORIENTED_EDGE('',*,*,#6045,.F.);\r\n#6048=ORIENTED_EDGE('',*,*,#6047,.T.);\r\n#6050=ORIENTED_EDGE('',*,*,#6049,.F.);\r\n#6052=ORIENTED_EDGE('',*,*,#6051,.T.);\r\n#6054=ORIENTED_EDGE('',*,*,#6053,.F.);\r\n#6056=ORIENTED_EDGE('',*,*,#6055,.T.);\r\n#6058=ORIENTED_EDGE('',*,*,#6057,.F.);\r\n#6059=EDGE_LOOP('',(#6044,#6046,#6048,#6050,#6052,#6054,#6056,#6058));\r\n#6060=FACE_BOUND('',#6059,.F.);\r\n#6062=ORIENTED_EDGE('',*,*,#6061,.F.);\r\n#6064=ORIENTED_EDGE('',*,*,#6063,.F.);\r\n#6066=ORIENTED_EDGE('',*,*,#6065,.F.);\r\n#6068=ORIENTED_EDGE('',*,*,#6067,.F.);\r\n#6070=ORIENTED_EDGE('',*,*,#6069,.F.);\r\n#6072=ORIENTED_EDGE('',*,*,#6071,.F.);\r\n#6074=ORIENTED_EDGE('',*,*,#6073,.F.);\r\n#6076=ORIENTED_EDGE('',*,*,#6075,.F.);\r\n#6077=EDGE_LOOP('',(#6062,#6064,#6066,#6068,#6070,#6072,#6074,#6076));\r\n#6078=FACE_BOUND('',#6077,.F.);\r\n#6079=ADVANCED_FACE('',(#5994,#6000,#6006,#6012,#6018,#6024,#6030,#6036,#6042,\r\n#6060,#6078),#5959,.F.);\r\n#6080=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0));\r\n#6081=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6082=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6083=AXIS2_PLACEMENT_3D('',#6080,#6081,#6082);\r\n#6084=CYLINDRICAL_SURFACE('',#6083,9.5E-2);\r\n#6085=ORIENTED_EDGE('',*,*,#5995,.F.);\r\n#6087=ORIENTED_EDGE('',*,*,#6086,.T.);\r\n#6089=ORIENTED_EDGE('',*,*,#6088,.T.);\r\n#6091=ORIENTED_EDGE('',*,*,#6090,.F.);\r\n#6092=EDGE_LOOP('',(#6085,#6087,#6089,#6091));\r\n#6093=FACE_OUTER_BOUND('',#6092,.F.);\r\n#6094=ADVANCED_FACE('',(#6093),#6084,.F.);\r\n#6095=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0));\r\n#6096=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6097=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6098=AXIS2_PLACEMENT_3D('',#6095,#6096,#6097);\r\n#6099=CYLINDRICAL_SURFACE('',#6098,9.5E-2);\r\n#6100=ORIENTED_EDGE('',*,*,#5997,.F.);\r\n#6101=ORIENTED_EDGE('',*,*,#6090,.T.);\r\n#6103=ORIENTED_EDGE('',*,*,#6102,.T.);\r\n#6104=ORIENTED_EDGE('',*,*,#6086,.F.);\r\n#6105=EDGE_LOOP('',(#6100,#6101,#6103,#6104));\r\n#6106=FACE_OUTER_BOUND('',#6105,.F.);\r\n#6107=ADVANCED_FACE('',(#6106),#6099,.F.);\r\n#6108=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0));\r\n#6109=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6110=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6111=AXIS2_PLACEMENT_3D('',#6108,#6109,#6110);\r\n#6112=PLANE('',#6111);\r\n#6113=ORIENTED_EDGE('',*,*,#6088,.F.);\r\n#6114=ORIENTED_EDGE('',*,*,#6102,.F.);\r\n#6115=EDGE_LOOP('',(#6113,#6114));\r\n#6116=FACE_OUTER_BOUND('',#6115,.F.);\r\n#6117=ADVANCED_FACE('',(#6116),#6112,.T.);\r\n#6118=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0));\r\n#6119=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6120=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6121=AXIS2_PLACEMENT_3D('',#6118,#6119,#6120);\r\n#6122=CYLINDRICAL_SURFACE('',#6121,1.625E-1);\r\n#6123=ORIENTED_EDGE('',*,*,#6001,.F.);\r\n#6125=ORIENTED_EDGE('',*,*,#6124,.T.);\r\n#6127=ORIENTED_EDGE('',*,*,#6126,.T.);\r\n#6129=ORIENTED_EDGE('',*,*,#6128,.F.);\r\n#6130=EDGE_LOOP('',(#6123,#6125,#6127,#6129));\r\n#6131=FACE_OUTER_BOUND('',#6130,.F.);\r\n#6132=ADVANCED_FACE('',(#6131),#6122,.F.);\r\n#6133=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0));\r\n#6134=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6135=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6136=AXIS2_PLACEMENT_3D('',#6133,#6134,#6135);\r\n#6137=CYLINDRICAL_SURFACE('',#6136,1.625E-1);\r\n#6138=ORIENTED_EDGE('',*,*,#6003,.F.);\r\n#6139=ORIENTED_EDGE('',*,*,#6128,.T.);\r\n#6141=ORIENTED_EDGE('',*,*,#6140,.T.);\r\n#6142=ORIENTED_EDGE('',*,*,#6124,.F.);\r\n#6143=EDGE_LOOP('',(#6138,#6139,#6141,#6142));\r\n#6144=FACE_OUTER_BOUND('',#6143,.F.);\r\n#6145=ADVANCED_FACE('',(#6144),#6137,.F.);\r\n#6146=CARTESIAN_POINT('',(2.4E1,0.E0,1.E1));\r\n#6147=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6148=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6149=AXIS2_PLACEMENT_3D('',#6146,#6147,#6148);\r\n#6150=PLANE('',#6149);\r\n#6152=ORIENTED_EDGE('',*,*,#6151,.T.);\r\n#6154=ORIENTED_EDGE('',*,*,#6153,.T.);\r\n#6156=ORIENTED_EDGE('',*,*,#6155,.F.);\r\n#6158=ORIENTED_EDGE('',*,*,#6157,.F.);\r\n#6160=ORIENTED_EDGE('',*,*,#6159,.T.);\r\n#6162=ORIENTED_EDGE('',*,*,#6161,.T.);\r\n#6164=ORIENTED_EDGE('',*,*,#6163,.T.);\r\n#6166=ORIENTED_EDGE('',*,*,#6165,.T.);\r\n#6168=ORIENTED_EDGE('',*,*,#6167,.F.);\r\n#6169=EDGE_LOOP('',(#6152,#6154,#6156,#6158,#6160,#6162,#6164,#6166,#6168));\r\n#6170=FACE_OUTER_BOUND('',#6169,.F.);\r\n#6171=ORIENTED_EDGE('',*,*,#6126,.F.);\r\n#6172=ORIENTED_EDGE('',*,*,#6140,.F.);\r\n#6173=EDGE_LOOP('',(#6171,#6172));\r\n#6174=FACE_BOUND('',#6173,.F.);\r\n#6176=ORIENTED_EDGE('',*,*,#6175,.F.);\r\n#6178=ORIENTED_EDGE('',*,*,#6177,.F.);\r\n#6180=ORIENTED_EDGE('',*,*,#6179,.F.);\r\n#6182=ORIENTED_EDGE('',*,*,#6181,.F.);\r\n#6184=ORIENTED_EDGE('',*,*,#6183,.F.);\r\n#6186=ORIENTED_EDGE('',*,*,#6185,.F.);\r\n#6188=ORIENTED_EDGE('',*,*,#6187,.F.);\r\n#6190=ORIENTED_EDGE('',*,*,#6189,.F.);\r\n#6192=ORIENTED_EDGE('',*,*,#6191,.F.);\r\n#6194=ORIENTED_EDGE('',*,*,#6193,.F.);\r\n#6196=ORIENTED_EDGE('',*,*,#6195,.F.);\r\n#6198=ORIENTED_EDGE('',*,*,#6197,.F.);\r\n#6199=EDGE_LOOP('',(#6176,#6178,#6180,#6182,#6184,#6186,#6188,#6190,#6192,#6194,\r\n#6196,#6198));\r\n#6200=FACE_BOUND('',#6199,.F.);\r\n#6201=ADVANCED_FACE('',(#6170,#6174,#6200),#6150,.F.);\r\n#6202=CARTESIAN_POINT('',(2.375E1,1.5E0,1.2E1));\r\n#6203=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6204=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6205=AXIS2_PLACEMENT_3D('',#6202,#6203,#6204);\r\n#6206=PLANE('',#6205);\r\n#6208=ORIENTED_EDGE('',*,*,#6207,.F.);\r\n#6210=ORIENTED_EDGE('',*,*,#6209,.F.);\r\n#6211=ORIENTED_EDGE('',*,*,#6151,.F.);\r\n#6212=EDGE_LOOP('',(#6208,#6210,#6211));\r\n#6213=FACE_OUTER_BOUND('',#6212,.F.);\r\n#6214=ADVANCED_FACE('',(#6213),#6206,.T.);\r\n#6215=CARTESIAN_POINT('',(0.E0,1.5E0,0.E0));\r\n#6216=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6217=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6218=AXIS2_PLACEMENT_3D('',#6215,#6216,#6217);\r\n#6219=PLANE('',#6218);\r\n#6220=ORIENTED_EDGE('',*,*,#5963,.T.);\r\n#6222=ORIENTED_EDGE('',*,*,#6221,.F.);\r\n#6224=ORIENTED_EDGE('',*,*,#6223,.F.);\r\n#6226=ORIENTED_EDGE('',*,*,#6225,.T.);\r\n#6228=ORIENTED_EDGE('',*,*,#6227,.F.);\r\n#6230=ORIENTED_EDGE('',*,*,#6229,.F.);\r\n#6231=ORIENTED_EDGE('',*,*,#5989,.T.);\r\n#6233=ORIENTED_EDGE('',*,*,#6232,.F.);\r\n#6235=ORIENTED_EDGE('',*,*,#6234,.F.);\r\n#6237=ORIENTED_EDGE('',*,*,#6236,.T.);\r\n#6239=ORIENTED_EDGE('',*,*,#6238,.F.);\r\n#6241=ORIENTED_EDGE('',*,*,#6240,.T.);\r\n#6243=ORIENTED_EDGE('',*,*,#6242,.F.);\r\n#6245=ORIENTED_EDGE('',*,*,#6244,.F.);\r\n#6246=EDGE_LOOP('',(#6220,#6222,#6224,#6226,#6228,#6230,#6231,#6233,#6235,#6237,\r\n#6239,#6241,#6243,#6245));\r\n#6247=FACE_OUTER_BOUND('',#6246,.F.);\r\n#6249=ORIENTED_EDGE('',*,*,#6248,.F.);\r\n#6251=ORIENTED_EDGE('',*,*,#6250,.F.);\r\n#6252=EDGE_LOOP('',(#6249,#6251));\r\n#6253=FACE_BOUND('',#6252,.F.);\r\n#6255=ORIENTED_EDGE('',*,*,#6254,.F.);\r\n#6257=ORIENTED_EDGE('',*,*,#6256,.F.);\r\n#6258=EDGE_LOOP('',(#6255,#6257));\r\n#6259=FACE_BOUND('',#6258,.F.);\r\n#6261=ORIENTED_EDGE('',*,*,#6260,.F.);\r\n#6263=ORIENTED_EDGE('',*,*,#6262,.F.);\r\n#6264=EDGE_LOOP('',(#6261,#6263));\r\n#6265=FACE_BOUND('',#6264,.F.);\r\n#6267=ORIENTED_EDGE('',*,*,#6266,.F.);\r\n#6269=ORIENTED_EDGE('',*,*,#6268,.F.);\r\n#6270=EDGE_LOOP('',(#6267,#6269));\r\n#6271=FACE_BOUND('',#6270,.F.);\r\n#6273=ORIENTED_EDGE('',*,*,#6272,.F.);\r\n#6275=ORIENTED_EDGE('',*,*,#6274,.F.);\r\n#6276=EDGE_LOOP('',(#6273,#6275));\r\n#6277=FACE_BOUND('',#6276,.F.);\r\n#6278=ADVANCED_FACE('',(#6247,#6253,#6259,#6265,#6271,#6277),#6219,.T.);\r\n#6279=CARTESIAN_POINT('',(0.E0,1.5E0,0.E0));\r\n#6280=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6281=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6282=AXIS2_PLACEMENT_3D('',#6279,#6280,#6281);\r\n#6283=PLANE('',#6282);\r\n#6284=ORIENTED_EDGE('',*,*,#6207,.T.);\r\n#6285=ORIENTED_EDGE('',*,*,#6167,.T.);\r\n#6287=ORIENTED_EDGE('',*,*,#6286,.T.);\r\n#6289=ORIENTED_EDGE('',*,*,#6288,.F.);\r\n#6291=ORIENTED_EDGE('',*,*,#6290,.T.);\r\n#6293=ORIENTED_EDGE('',*,*,#6292,.F.);\r\n#6295=ORIENTED_EDGE('',*,*,#6294,.F.);\r\n#6297=ORIENTED_EDGE('',*,*,#6296,.T.);\r\n#6299=ORIENTED_EDGE('',*,*,#6298,.F.);\r\n#6301=ORIENTED_EDGE('',*,*,#6300,.T.);\r\n#6303=ORIENTED_EDGE('',*,*,#6302,.F.);\r\n#6305=ORIENTED_EDGE('',*,*,#6304,.F.);\r\n#6307=ORIENTED_EDGE('',*,*,#6306,.F.);\r\n#6309=ORIENTED_EDGE('',*,*,#6308,.T.);\r\n#6311=ORIENTED_EDGE('',*,*,#6310,.F.);\r\n#6313=ORIENTED_EDGE('',*,*,#6312,.T.);\r\n#6315=ORIENTED_EDGE('',*,*,#6314,.F.);\r\n#6317=ORIENTED_EDGE('',*,*,#6316,.T.);\r\n#6319=ORIENTED_EDGE('',*,*,#6318,.T.);\r\n#6321=ORIENTED_EDGE('',*,*,#6320,.T.);\r\n#6323=ORIENTED_EDGE('',*,*,#6322,.F.);\r\n#6324=ORIENTED_EDGE('',*,*,#5976,.T.);\r\n#6326=ORIENTED_EDGE('',*,*,#6325,.T.);\r\n#6327=ORIENTED_EDGE('',*,*,#6157,.T.);\r\n#6329=ORIENTED_EDGE('',*,*,#6328,.F.);\r\n#6331=ORIENTED_EDGE('',*,*,#6330,.F.);\r\n#6332=EDGE_LOOP('',(#6284,#6285,#6287,#6289,#6291,#6293,#6295,#6297,#6299,#6301,\r\n#6303,#6305,#6307,#6309,#6311,#6313,#6315,#6317,#6319,#6321,#6323,#6324,#6326,\r\n#6327,#6329,#6331));\r\n#6333=FACE_OUTER_BOUND('',#6332,.F.);\r\n#6335=ORIENTED_EDGE('',*,*,#6334,.F.);\r\n#6337=ORIENTED_EDGE('',*,*,#6336,.F.);\r\n#6338=EDGE_LOOP('',(#6335,#6337));\r\n#6339=FACE_BOUND('',#6338,.F.);\r\n#6341=ORIENTED_EDGE('',*,*,#6340,.F.);\r\n#6343=ORIENTED_EDGE('',*,*,#6342,.F.);\r\n#6344=EDGE_LOOP('',(#6341,#6343));\r\n#6345=FACE_BOUND('',#6344,.F.);\r\n#6347=ORIENTED_EDGE('',*,*,#6346,.T.);\r\n#6349=ORIENTED_EDGE('',*,*,#6348,.T.);\r\n#6350=EDGE_LOOP('',(#6347,#6349));\r\n#6351=FACE_BOUND('',#6350,.F.);\r\n#6353=ORIENTED_EDGE('',*,*,#6352,.T.);\r\n#6355=ORIENTED_EDGE('',*,*,#6354,.T.);\r\n#6356=EDGE_LOOP('',(#6353,#6355));\r\n#6357=FACE_BOUND('',#6356,.F.);\r\n#6359=ORIENTED_EDGE('',*,*,#6358,.F.);\r\n#6361=ORIENTED_EDGE('',*,*,#6360,.F.);\r\n#6362=EDGE_LOOP('',(#6359,#6361));\r\n#6363=FACE_BOUND('',#6362,.F.);\r\n#6365=ORIENTED_EDGE('',*,*,#6364,.F.);\r\n#6367=ORIENTED_EDGE('',*,*,#6366,.F.);\r\n#6368=EDGE_LOOP('',(#6365,#6367));\r\n#6369=FACE_BOUND('',#6368,.F.);\r\n#6371=ORIENTED_EDGE('',*,*,#6370,.F.);\r\n#6373=ORIENTED_EDGE('',*,*,#6372,.F.);\r\n#6374=EDGE_LOOP('',(#6371,#6373));\r\n#6375=FACE_BOUND('',#6374,.F.);\r\n#6377=ORIENTED_EDGE('',*,*,#6376,.F.);\r\n#6379=ORIENTED_EDGE('',*,*,#6378,.F.);\r\n#6380=EDGE_LOOP('',(#6377,#6379));\r\n#6381=FACE_BOUND('',#6380,.F.);\r\n#6383=ORIENTED_EDGE('',*,*,#6382,.F.);\r\n#6385=ORIENTED_EDGE('',*,*,#6384,.F.);\r\n#6386=EDGE_LOOP('',(#6383,#6385));\r\n#6387=FACE_BOUND('',#6386,.F.);\r\n#6389=ORIENTED_EDGE('',*,*,#6388,.F.);\r\n#6391=ORIENTED_EDGE('',*,*,#6390,.F.);\r\n#6392=EDGE_LOOP('',(#6389,#6391));\r\n#6393=FACE_BOUND('',#6392,.F.);\r\n#6395=ORIENTED_EDGE('',*,*,#6394,.F.);\r\n#6397=ORIENTED_EDGE('',*,*,#6396,.F.);\r\n#6398=EDGE_LOOP('',(#6395,#6397));\r\n#6399=FACE_BOUND('',#6398,.F.);\r\n#6401=ORIENTED_EDGE('',*,*,#6400,.T.);\r\n#6403=ORIENTED_EDGE('',*,*,#6402,.F.);\r\n#6405=ORIENTED_EDGE('',*,*,#6404,.F.);\r\n#6407=ORIENTED_EDGE('',*,*,#6406,.F.);\r\n#6409=ORIENTED_EDGE('',*,*,#6408,.T.);\r\n#6411=ORIENTED_EDGE('',*,*,#6410,.F.);\r\n#6413=ORIENTED_EDGE('',*,*,#6412,.T.);\r\n#6415=ORIENTED_EDGE('',*,*,#6414,.F.);\r\n#6416=EDGE_LOOP('',(#6401,#6403,#6405,#6407,#6409,#6411,#6413,#6415));\r\n#6417=FACE_BOUND('',#6416,.F.);\r\n#6419=ORIENTED_EDGE('',*,*,#6418,.F.);\r\n#6421=ORIENTED_EDGE('',*,*,#6420,.F.);\r\n#6423=ORIENTED_EDGE('',*,*,#6422,.T.);\r\n#6425=ORIENTED_EDGE('',*,*,#6424,.F.);\r\n#6427=ORIENTED_EDGE('',*,*,#6426,.T.);\r\n#6429=ORIENTED_EDGE('',*,*,#6428,.F.);\r\n#6431=ORIENTED_EDGE('',*,*,#6430,.T.);\r\n#6433=ORIENTED_EDGE('',*,*,#6432,.F.);\r\n#6435=ORIENTED_EDGE('',*,*,#6434,.F.);\r\n#6437=ORIENTED_EDGE('',*,*,#6436,.F.);\r\n#6439=ORIENTED_EDGE('',*,*,#6438,.F.);\r\n#6441=ORIENTED_EDGE('',*,*,#6440,.T.);\r\n#6443=ORIENTED_EDGE('',*,*,#6442,.F.);\r\n#6445=ORIENTED_EDGE('',*,*,#6444,.F.);\r\n#6447=ORIENTED_EDGE('',*,*,#6446,.T.);\r\n#6449=ORIENTED_EDGE('',*,*,#6448,.F.);\r\n#6450=EDGE_LOOP('',(#6419,#6421,#6423,#6425,#6427,#6429,#6431,#6433,#6435,#6437,\r\n#6439,#6441,#6443,#6445,#6447,#6449));\r\n#6451=FACE_BOUND('',#6450,.F.);\r\n#6453=ORIENTED_EDGE('',*,*,#6452,.F.);\r\n#6455=ORIENTED_EDGE('',*,*,#6454,.F.);\r\n#6456=EDGE_LOOP('',(#6453,#6455));\r\n#6457=FACE_BOUND('',#6456,.F.);\r\n#6459=ORIENTED_EDGE('',*,*,#6458,.F.);\r\n#6461=ORIENTED_EDGE('',*,*,#6460,.F.);\r\n#6462=EDGE_LOOP('',(#6459,#6461));\r\n#6463=FACE_BOUND('',#6462,.F.);\r\n#6465=ORIENTED_EDGE('',*,*,#6464,.F.);\r\n#6467=ORIENTED_EDGE('',*,*,#6466,.F.);\r\n#6468=EDGE_LOOP('',(#6465,#6467));\r\n#6469=FACE_BOUND('',#6468,.F.);\r\n#6471=ORIENTED_EDGE('',*,*,#6470,.F.);\r\n#6473=ORIENTED_EDGE('',*,*,#6472,.F.);\r\n#6474=EDGE_LOOP('',(#6471,#6473));\r\n#6475=FACE_BOUND('',#6474,.F.);\r\n#6477=ORIENTED_EDGE('',*,*,#6476,.F.);\r\n#6479=ORIENTED_EDGE('',*,*,#6478,.F.);\r\n#6480=EDGE_LOOP('',(#6477,#6479));\r\n#6481=FACE_BOUND('',#6480,.F.);\r\n#6483=ORIENTED_EDGE('',*,*,#6482,.F.);\r\n#6485=ORIENTED_EDGE('',*,*,#6484,.F.);\r\n#6486=EDGE_LOOP('',(#6483,#6485));\r\n#6487=FACE_BOUND('',#6486,.F.);\r\n#6488=ADVANCED_FACE('',(#6333,#6339,#6345,#6351,#6357,#6363,#6369,#6375,#6381,\r\n#6387,#6393,#6399,#6417,#6451,#6457,#6463,#6469,#6475,#6481,#6487),#6283,.T.);\r\n#6489=CARTESIAN_POINT('',(6.45E0,1.176878221735E0,2.975E1));\r\n#6490=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6491=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6492=AXIS2_PLACEMENT_3D('',#6489,#6490,#6491);\r\n#6493=CYLINDRICAL_SURFACE('',#6492,1.E-1);\r\n#6494=ORIENTED_EDGE('',*,*,#6334,.T.);\r\n#6496=ORIENTED_EDGE('',*,*,#6495,.F.);\r\n#6498=ORIENTED_EDGE('',*,*,#6497,.F.);\r\n#6500=ORIENTED_EDGE('',*,*,#6499,.T.);\r\n#6501=EDGE_LOOP('',(#6494,#6496,#6498,#6500));\r\n#6502=FACE_OUTER_BOUND('',#6501,.F.);\r\n#6503=ADVANCED_FACE('',(#6502),#6493,.F.);\r\n#6504=CARTESIAN_POINT('',(6.45E0,1.176878221735E0,2.975E1));\r\n#6505=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6506=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6507=AXIS2_PLACEMENT_3D('',#6504,#6505,#6506);\r\n#6508=CYLINDRICAL_SURFACE('',#6507,1.E-1);\r\n#6509=ORIENTED_EDGE('',*,*,#6336,.T.);\r\n#6510=ORIENTED_EDGE('',*,*,#6499,.F.);\r\n#6512=ORIENTED_EDGE('',*,*,#6511,.T.);\r\n#6513=ORIENTED_EDGE('',*,*,#6495,.T.);\r\n#6514=EDGE_LOOP('',(#6509,#6510,#6512,#6513));\r\n#6515=FACE_OUTER_BOUND('',#6514,.F.);\r\n#6516=ADVANCED_FACE('',(#6515),#6508,.F.);\r\n#6517=CARTESIAN_POINT('',(6.45E0,1.234346967234E0,2.975E1));\r\n#6518=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6519=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6520=AXIS2_PLACEMENT_3D('',#6517,#6518,#6519);\r\n#6521=CONICAL_SURFACE('',#6520,7.288815195685E-2,6.E1);\r\n#6523=ORIENTED_EDGE('',*,*,#6522,.T.);\r\n#6524=ORIENTED_EDGE('',*,*,#6511,.F.);\r\n#6526=ORIENTED_EDGE('',*,*,#6525,.F.);\r\n#6527=EDGE_LOOP('',(#6523,#6524,#6526));\r\n#6528=FACE_OUTER_BOUND('',#6527,.F.);\r\n#6529=ADVANCED_FACE('',(#6528),#6521,.F.);\r\n#6530=CARTESIAN_POINT('',(6.45E0,1.234346967234E0,2.975E1));\r\n#6531=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6532=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6533=AXIS2_PLACEMENT_3D('',#6530,#6531,#6532);\r\n#6534=CONICAL_SURFACE('',#6533,7.288815195685E-2,6.E1);\r\n#6535=ORIENTED_EDGE('',*,*,#6522,.F.);\r\n#6536=ORIENTED_EDGE('',*,*,#6525,.T.);\r\n#6537=ORIENTED_EDGE('',*,*,#6497,.T.);\r\n#6538=EDGE_LOOP('',(#6535,#6536,#6537));\r\n#6539=FACE_OUTER_BOUND('',#6538,.F.);\r\n#6540=ADVANCED_FACE('',(#6539),#6534,.F.);\r\n#6541=CARTESIAN_POINT('',(7.45E0,1.176878221735E0,2.975E1));\r\n#6542=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6543=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6544=AXIS2_PLACEMENT_3D('',#6541,#6542,#6543);\r\n#6545=CYLINDRICAL_SURFACE('',#6544,1.E-1);\r\n#6546=ORIENTED_EDGE('',*,*,#6340,.T.);\r\n#6548=ORIENTED_EDGE('',*,*,#6547,.F.);\r\n#6550=ORIENTED_EDGE('',*,*,#6549,.F.);\r\n#6552=ORIENTED_EDGE('',*,*,#6551,.T.);\r\n#6553=EDGE_LOOP('',(#6546,#6548,#6550,#6552));\r\n#6554=FACE_OUTER_BOUND('',#6553,.F.);\r\n#6555=ADVANCED_FACE('',(#6554),#6545,.F.);\r\n#6556=CARTESIAN_POINT('',(7.45E0,1.176878221735E0,2.975E1));\r\n#6557=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6558=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6559=AXIS2_PLACEMENT_3D('',#6556,#6557,#6558);\r\n#6560=CYLINDRICAL_SURFACE('',#6559,1.E-1);\r\n#6561=ORIENTED_EDGE('',*,*,#6342,.T.);\r\n#6562=ORIENTED_EDGE('',*,*,#6551,.F.);\r\n#6564=ORIENTED_EDGE('',*,*,#6563,.T.);\r\n#6565=ORIENTED_EDGE('',*,*,#6547,.T.);\r\n#6566=EDGE_LOOP('',(#6561,#6562,#6564,#6565));\r\n#6567=FACE_OUTER_BOUND('',#6566,.F.);\r\n#6568=ADVANCED_FACE('',(#6567),#6560,.F.);\r\n#6569=CARTESIAN_POINT('',(7.45E0,1.234346967234E0,2.975E1));\r\n#6570=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6571=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6572=AXIS2_PLACEMENT_3D('',#6569,#6570,#6571);\r\n#6573=CONICAL_SURFACE('',#6572,7.288815195685E-2,6.E1);\r\n#6575=ORIENTED_EDGE('',*,*,#6574,.T.);\r\n#6576=ORIENTED_EDGE('',*,*,#6563,.F.);\r\n#6578=ORIENTED_EDGE('',*,*,#6577,.F.);\r\n#6579=EDGE_LOOP('',(#6575,#6576,#6578));\r\n#6580=FACE_OUTER_BOUND('',#6579,.F.);\r\n#6581=ADVANCED_FACE('',(#6580),#6573,.F.);\r\n#6582=CARTESIAN_POINT('',(7.45E0,1.234346967234E0,2.975E1));\r\n#6583=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6584=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6585=AXIS2_PLACEMENT_3D('',#6582,#6583,#6584);\r\n#6586=CONICAL_SURFACE('',#6585,7.288815195685E-2,6.E1);\r\n#6587=ORIENTED_EDGE('',*,*,#6574,.F.);\r\n#6588=ORIENTED_EDGE('',*,*,#6577,.T.);\r\n#6589=ORIENTED_EDGE('',*,*,#6549,.T.);\r\n#6590=EDGE_LOOP('',(#6587,#6588,#6589));\r\n#6591=FACE_OUTER_BOUND('',#6590,.F.);\r\n#6592=ADVANCED_FACE('',(#6591),#6586,.F.);\r\n#6593=CARTESIAN_POINT('',(2.046862696660E1,-7.805924235695E-2,7.E0));\r\n#6594=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6595=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6596=AXIS2_PLACEMENT_3D('',#6593,#6594,#6595);\r\n#6597=CYLINDRICAL_SURFACE('',#6596,1.E0);\r\n#6598=ORIENTED_EDGE('',*,*,#5961,.F.);\r\n#6599=ORIENTED_EDGE('',*,*,#5550,.T.);\r\n#6601=ORIENTED_EDGE('',*,*,#6600,.T.);\r\n#6602=ORIENTED_EDGE('',*,*,#6221,.T.);\r\n#6603=EDGE_LOOP('',(#6598,#6599,#6601,#6602));\r\n#6604=FACE_OUTER_BOUND('',#6603,.F.);\r\n#6605=ADVANCED_FACE('',(#6604),#6597,.F.);\r\n#6606=CARTESIAN_POINT('',(1.65E1,1.562633489099E0,7.5E0));\r\n#6607=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6608=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6609=AXIS2_PLACEMENT_3D('',#6606,#6607,#6608);\r\n#6610=CYLINDRICAL_SURFACE('',#6609,5.E0);\r\n#6611=ORIENTED_EDGE('',*,*,#6600,.F.);\r\n#6612=ORIENTED_EDGE('',*,*,#5548,.T.);\r\n#6614=ORIENTED_EDGE('',*,*,#6613,.F.);\r\n#6615=ORIENTED_EDGE('',*,*,#6223,.T.);\r\n#6616=EDGE_LOOP('',(#6611,#6612,#6614,#6615));\r\n#6617=FACE_OUTER_BOUND('',#6616,.F.);\r\n#6618=ADVANCED_FACE('',(#6617),#6610,.F.);\r\n#6619=CARTESIAN_POINT('',(2.15E1,1.5E0,2.5E0));\r\n#6620=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6621=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6622=AXIS2_PLACEMENT_3D('',#6619,#6620,#6621);\r\n#6623=PLANE('',#6622);\r\n#6625=ORIENTED_EDGE('',*,*,#6624,.F.);\r\n#6626=ORIENTED_EDGE('',*,*,#6225,.F.);\r\n#6627=ORIENTED_EDGE('',*,*,#6613,.T.);\r\n#6628=ORIENTED_EDGE('',*,*,#5546,.T.);\r\n#6629=EDGE_LOOP('',(#6625,#6626,#6627,#6628));\r\n#6630=FACE_OUTER_BOUND('',#6629,.F.);\r\n#6631=ADVANCED_FACE('',(#6630),#6623,.F.);\r\n#6632=CARTESIAN_POINT('',(7.5E0,1.562633489099E0,7.5E0));\r\n#6633=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6634=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6635=AXIS2_PLACEMENT_3D('',#6632,#6633,#6634);\r\n#6636=CYLINDRICAL_SURFACE('',#6635,5.E0);\r\n#6638=ORIENTED_EDGE('',*,*,#6637,.F.);\r\n#6639=ORIENTED_EDGE('',*,*,#6227,.T.);\r\n#6640=ORIENTED_EDGE('',*,*,#6624,.T.);\r\n#6641=ORIENTED_EDGE('',*,*,#5544,.T.);\r\n#6642=EDGE_LOOP('',(#6638,#6639,#6640,#6641));\r\n#6643=FACE_OUTER_BOUND('',#6642,.F.);\r\n#6644=ADVANCED_FACE('',(#6643),#6636,.F.);\r\n#6645=CARTESIAN_POINT('',(3.531373033403E0,1.157860978230E1,7.E0));\r\n#6646=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6647=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6648=AXIS2_PLACEMENT_3D('',#6645,#6646,#6647);\r\n#6649=CYLINDRICAL_SURFACE('',#6648,1.E0);\r\n#6650=ORIENTED_EDGE('',*,*,#5991,.F.);\r\n#6651=ORIENTED_EDGE('',*,*,#6229,.T.);\r\n#6652=ORIENTED_EDGE('',*,*,#6637,.T.);\r\n#6653=ORIENTED_EDGE('',*,*,#5542,.T.);\r\n#6654=EDGE_LOOP('',(#6650,#6651,#6652,#6653));\r\n#6655=FACE_OUTER_BOUND('',#6654,.F.);\r\n#6656=ADVANCED_FACE('',(#6655),#6649,.F.);\r\n#6657=CARTESIAN_POINT('',(-1.E0,1.161044894892E1,7.E0));\r\n#6658=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6659=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6660=AXIS2_PLACEMENT_3D('',#6657,#6658,#6659);\r\n#6661=CYLINDRICAL_SURFACE('',#6660,1.E0);\r\n#6663=ORIENTED_EDGE('',*,*,#6662,.F.);\r\n#6664=ORIENTED_EDGE('',*,*,#6232,.T.);\r\n#6665=ORIENTED_EDGE('',*,*,#5987,.T.);\r\n#6666=ORIENTED_EDGE('',*,*,#5508,.T.);\r\n#6667=EDGE_LOOP('',(#6663,#6664,#6665,#6666));\r\n#6668=FACE_OUTER_BOUND('',#6667,.F.);\r\n#6669=ADVANCED_FACE('',(#6668),#6661,.F.);\r\n#6670=CARTESIAN_POINT('',(0.E0,0.E0,0.E0));\r\n#6671=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6672=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6673=AXIS2_PLACEMENT_3D('',#6670,#6671,#6672);\r\n#6674=PLANE('',#6673);\r\n#6676=ORIENTED_EDGE('',*,*,#6675,.T.);\r\n#6677=ORIENTED_EDGE('',*,*,#6302,.T.);\r\n#6679=ORIENTED_EDGE('',*,*,#6678,.F.);\r\n#6680=ORIENTED_EDGE('',*,*,#5520,.F.);\r\n#6681=EDGE_LOOP('',(#6676,#6677,#6679,#6680));\r\n#6682=FACE_OUTER_BOUND('',#6681,.F.);\r\n#6683=ADVANCED_FACE('',(#6682),#6674,.T.);\r\n#6684=CARTESIAN_POINT('',(0.E0,0.E0,0.E0));\r\n#6685=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6686=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6687=AXIS2_PLACEMENT_3D('',#6684,#6685,#6686);\r\n#6688=PLANE('',#6687);\r\n#6689=ORIENTED_EDGE('',*,*,#6662,.T.);\r\n#6690=ORIENTED_EDGE('',*,*,#5506,.F.);\r\n#6692=ORIENTED_EDGE('',*,*,#6691,.T.);\r\n#6693=ORIENTED_EDGE('',*,*,#6234,.T.);\r\n#6694=EDGE_LOOP('',(#6689,#6690,#6692,#6693));\r\n#6695=FACE_OUTER_BOUND('',#6694,.F.);\r\n#6696=ADVANCED_FACE('',(#6695),#6688,.T.);\r\n#6697=CARTESIAN_POINT('',(-1.E0,-5.722942641981E-2,1.325E1));\r\n#6698=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6699=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6700=AXIS2_PLACEMENT_3D('',#6697,#6698,#6699);\r\n#6701=CYLINDRICAL_SURFACE('',#6700,1.E0);\r\n#6702=ORIENTED_EDGE('',*,*,#6675,.F.);\r\n#6703=ORIENTED_EDGE('',*,*,#5518,.T.);\r\n#6705=ORIENTED_EDGE('',*,*,#6704,.T.);\r\n#6706=ORIENTED_EDGE('',*,*,#6304,.T.);\r\n#6707=EDGE_LOOP('',(#6702,#6703,#6705,#6706));\r\n#6708=FACE_OUTER_BOUND('',#6707,.F.);\r\n#6709=ADVANCED_FACE('',(#6708),#6701,.F.);\r\n#6710=CARTESIAN_POINT('',(-2.E0,0.E0,1.225E1));\r\n#6711=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6712=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6713=AXIS2_PLACEMENT_3D('',#6710,#6711,#6712);\r\n#6714=PLANE('',#6713);\r\n#6716=ORIENTED_EDGE('',*,*,#6715,.F.);\r\n#6717=ORIENTED_EDGE('',*,*,#6442,.T.);\r\n#6719=ORIENTED_EDGE('',*,*,#6718,.F.);\r\n#6720=ORIENTED_EDGE('',*,*,#5668,.F.);\r\n#6721=EDGE_LOOP('',(#6716,#6717,#6719,#6720));\r\n#6722=FACE_OUTER_BOUND('',#6721,.F.);\r\n#6723=ADVANCED_FACE('',(#6722),#6714,.T.);\r\n#6724=CARTESIAN_POINT('',(-2.E0,0.E0,1.225E1));\r\n#6725=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6726=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6727=AXIS2_PLACEMENT_3D('',#6724,#6725,#6726);\r\n#6728=PLANE('',#6727);\r\n#6729=ORIENTED_EDGE('',*,*,#6704,.F.);\r\n#6730=ORIENTED_EDGE('',*,*,#5516,.F.);\r\n#6732=ORIENTED_EDGE('',*,*,#6731,.T.);\r\n#6733=ORIENTED_EDGE('',*,*,#6306,.T.);\r\n#6734=EDGE_LOOP('',(#6729,#6730,#6732,#6733));\r\n#6735=FACE_OUTER_BOUND('',#6734,.F.);\r\n#6736=ADVANCED_FACE('',(#6735),#6728,.T.);\r\n#6737=CARTESIAN_POINT('',(3.5E0,1.566978255297E0,1.325E1));\r\n#6738=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6739=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6740=AXIS2_PLACEMENT_3D('',#6737,#6738,#6739);\r\n#6741=CYLINDRICAL_SURFACE('',#6740,1.E0);\r\n#6743=ORIENTED_EDGE('',*,*,#6742,.F.);\r\n#6744=ORIENTED_EDGE('',*,*,#6444,.T.);\r\n#6745=ORIENTED_EDGE('',*,*,#6715,.T.);\r\n#6746=ORIENTED_EDGE('',*,*,#5666,.T.);\r\n#6747=EDGE_LOOP('',(#6743,#6744,#6745,#6746));\r\n#6748=FACE_OUTER_BOUND('',#6747,.F.);\r\n#6749=ADVANCED_FACE('',(#6748),#6741,.F.);\r\n#6750=CARTESIAN_POINT('',(2.5E0,1.5E0,2.5E0));\r\n#6751=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6752=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6753=AXIS2_PLACEMENT_3D('',#6750,#6751,#6752);\r\n#6754=PLANE('',#6753);\r\n#6756=ORIENTED_EDGE('',*,*,#6755,.T.);\r\n#6757=ORIENTED_EDGE('',*,*,#5650,.T.);\r\n#6759=ORIENTED_EDGE('',*,*,#6758,.F.);\r\n#6760=ORIENTED_EDGE('',*,*,#6408,.F.);\r\n#6761=EDGE_LOOP('',(#6756,#6757,#6759,#6760));\r\n#6762=FACE_OUTER_BOUND('',#6761,.F.);\r\n#6763=ADVANCED_FACE('',(#6762),#6754,.F.);\r\n#6764=CARTESIAN_POINT('',(2.5E0,1.5E0,2.5E0));\r\n#6765=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6766=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6767=AXIS2_PLACEMENT_3D('',#6764,#6765,#6766);\r\n#6768=PLANE('',#6767);\r\n#6770=ORIENTED_EDGE('',*,*,#6769,.T.);\r\n#6771=ORIENTED_EDGE('',*,*,#6446,.F.);\r\n#6772=ORIENTED_EDGE('',*,*,#6742,.T.);\r\n#6773=ORIENTED_EDGE('',*,*,#5664,.T.);\r\n#6774=EDGE_LOOP('',(#6770,#6771,#6772,#6773));\r\n#6775=FACE_OUTER_BOUND('',#6774,.F.);\r\n#6776=ADVANCED_FACE('',(#6775),#6768,.F.);\r\n#6777=CARTESIAN_POINT('',(5.5E0,1.568923974228E0,2.19375E1));\r\n#6778=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6779=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6780=AXIS2_PLACEMENT_3D('',#6777,#6778,#6779);\r\n#6781=CYLINDRICAL_SURFACE('',#6780,3.E0);\r\n#6782=ORIENTED_EDGE('',*,*,#6755,.F.);\r\n#6783=ORIENTED_EDGE('',*,*,#6406,.T.);\r\n#6785=ORIENTED_EDGE('',*,*,#6784,.T.);\r\n#6786=ORIENTED_EDGE('',*,*,#5652,.T.);\r\n#6787=EDGE_LOOP('',(#6782,#6783,#6785,#6786));\r\n#6788=FACE_OUTER_BOUND('',#6787,.F.);\r\n#6789=ADVANCED_FACE('',(#6788),#6781,.F.);\r\n#6790=CARTESIAN_POINT('',(2.5E0,0.E0,1.89375E1));\r\n#6791=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6792=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6793=AXIS2_PLACEMENT_3D('',#6790,#6791,#6792);\r\n#6794=PLANE('',#6793);\r\n#6795=ORIENTED_EDGE('',*,*,#6784,.F.);\r\n#6796=ORIENTED_EDGE('',*,*,#6404,.T.);\r\n#6798=ORIENTED_EDGE('',*,*,#6797,.F.);\r\n#6799=ORIENTED_EDGE('',*,*,#5638,.F.);\r\n#6800=EDGE_LOOP('',(#6795,#6796,#6798,#6799));\r\n#6801=FACE_OUTER_BOUND('',#6800,.F.);\r\n#6802=ADVANCED_FACE('',(#6801),#6794,.T.);\r\n#6803=CARTESIAN_POINT('',(1.85E1,-5.889194178308E-2,2.19375E1));\r\n#6804=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6805=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6806=AXIS2_PLACEMENT_3D('',#6803,#6804,#6805);\r\n#6807=CYLINDRICAL_SURFACE('',#6806,3.E0);\r\n#6809=ORIENTED_EDGE('',*,*,#6808,.F.);\r\n#6810=ORIENTED_EDGE('',*,*,#5640,.T.);\r\n#6811=ORIENTED_EDGE('',*,*,#6797,.T.);\r\n#6812=ORIENTED_EDGE('',*,*,#6402,.T.);\r\n#6813=EDGE_LOOP('',(#6809,#6810,#6811,#6812));\r\n#6814=FACE_OUTER_BOUND('',#6813,.F.);\r\n#6815=ADVANCED_FACE('',(#6814),#6807,.F.);\r\n#6816=CARTESIAN_POINT('',(2.15E1,1.5E0,2.95E1));\r\n#6817=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6818=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6819=AXIS2_PLACEMENT_3D('',#6816,#6817,#6818);\r\n#6820=PLANE('',#6819);\r\n#6821=ORIENTED_EDGE('',*,*,#6808,.T.);\r\n#6822=ORIENTED_EDGE('',*,*,#6400,.F.);\r\n#6824=ORIENTED_EDGE('',*,*,#6823,.T.);\r\n#6825=ORIENTED_EDGE('',*,*,#5642,.T.);\r\n#6826=EDGE_LOOP('',(#6821,#6822,#6824,#6825));\r\n#6827=FACE_OUTER_BOUND('',#6826,.F.);\r\n#6828=ADVANCED_FACE('',(#6827),#6820,.F.);\r\n#6829=CARTESIAN_POINT('',(2.15E1,1.5E0,2.95E1));\r\n#6830=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6831=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6832=AXIS2_PLACEMENT_3D('',#6829,#6830,#6831);\r\n#6833=PLANE('',#6832);\r\n#6835=ORIENTED_EDGE('',*,*,#6834,.T.);\r\n#6836=ORIENTED_EDGE('',*,*,#5656,.T.);\r\n#6838=ORIENTED_EDGE('',*,*,#6837,.T.);\r\n#6839=ORIENTED_EDGE('',*,*,#6422,.F.);\r\n#6840=EDGE_LOOP('',(#6835,#6836,#6838,#6839));\r\n#6841=FACE_OUTER_BOUND('',#6840,.F.);\r\n#6842=ADVANCED_FACE('',(#6841),#6833,.F.);\r\n#6843=CARTESIAN_POINT('',(1.65E1,1.562633489099E0,2.45E1));\r\n#6844=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6845=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6846=AXIS2_PLACEMENT_3D('',#6843,#6844,#6845);\r\n#6847=CYLINDRICAL_SURFACE('',#6846,5.E0);\r\n#6848=ORIENTED_EDGE('',*,*,#6823,.F.);\r\n#6849=ORIENTED_EDGE('',*,*,#6414,.T.);\r\n#6851=ORIENTED_EDGE('',*,*,#6850,.T.);\r\n#6852=ORIENTED_EDGE('',*,*,#5644,.T.);\r\n#6853=EDGE_LOOP('',(#6848,#6849,#6851,#6852));\r\n#6854=FACE_OUTER_BOUND('',#6853,.F.);\r\n#6855=ADVANCED_FACE('',(#6854),#6847,.F.);\r\n#6856=CARTESIAN_POINT('',(2.5E0,1.5E0,2.95E1));\r\n#6857=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6858=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6859=AXIS2_PLACEMENT_3D('',#6856,#6857,#6858);\r\n#6860=PLANE('',#6859);\r\n#6862=ORIENTED_EDGE('',*,*,#6861,.T.);\r\n#6863=ORIENTED_EDGE('',*,*,#5646,.T.);\r\n#6864=ORIENTED_EDGE('',*,*,#6850,.F.);\r\n#6865=ORIENTED_EDGE('',*,*,#6412,.F.);\r\n#6866=EDGE_LOOP('',(#6862,#6863,#6864,#6865));\r\n#6867=FACE_OUTER_BOUND('',#6866,.F.);\r\n#6868=ADVANCED_FACE('',(#6867),#6860,.F.);\r\n#6869=CARTESIAN_POINT('',(7.5E0,1.562633489099E0,2.45E1));\r\n#6870=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6871=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#6872=AXIS2_PLACEMENT_3D('',#6869,#6870,#6871);\r\n#6873=CYLINDRICAL_SURFACE('',#6872,5.E0);\r\n#6874=ORIENTED_EDGE('',*,*,#6861,.F.);\r\n#6875=ORIENTED_EDGE('',*,*,#6410,.T.);\r\n#6876=ORIENTED_EDGE('',*,*,#6758,.T.);\r\n#6877=ORIENTED_EDGE('',*,*,#5648,.T.);\r\n#6878=EDGE_LOOP('',(#6874,#6875,#6876,#6877));\r\n#6879=FACE_OUTER_BOUND('',#6878,.F.);\r\n#6880=ADVANCED_FACE('',(#6879),#6873,.F.);\r\n#6881=CARTESIAN_POINT('',(1.85E1,1.568923974228E0,1.40625E1));\r\n#6882=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6883=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6884=AXIS2_PLACEMENT_3D('',#6881,#6882,#6883);\r\n#6885=CYLINDRICAL_SURFACE('',#6884,3.E0);\r\n#6886=ORIENTED_EDGE('',*,*,#6834,.F.);\r\n#6887=ORIENTED_EDGE('',*,*,#6420,.T.);\r\n#6889=ORIENTED_EDGE('',*,*,#6888,.T.);\r\n#6890=ORIENTED_EDGE('',*,*,#5658,.T.);\r\n#6891=EDGE_LOOP('',(#6886,#6887,#6889,#6890));\r\n#6892=FACE_OUTER_BOUND('',#6891,.F.);\r\n#6893=ADVANCED_FACE('',(#6892),#6885,.F.);\r\n#6894=CARTESIAN_POINT('',(2.15E1,0.E0,1.70625E1));\r\n#6895=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6896=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6897=AXIS2_PLACEMENT_3D('',#6894,#6895,#6896);\r\n#6898=PLANE('',#6897);\r\n#6899=ORIENTED_EDGE('',*,*,#6888,.F.);\r\n#6900=ORIENTED_EDGE('',*,*,#6418,.T.);\r\n#6902=ORIENTED_EDGE('',*,*,#6901,.F.);\r\n#6903=ORIENTED_EDGE('',*,*,#5660,.F.);\r\n#6904=EDGE_LOOP('',(#6899,#6900,#6902,#6903));\r\n#6905=FACE_OUTER_BOUND('',#6904,.F.);\r\n#6906=ADVANCED_FACE('',(#6905),#6898,.T.);\r\n#6907=CARTESIAN_POINT('',(5.5E0,-5.889194178308E-2,1.40625E1));\r\n#6908=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6909=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6910=AXIS2_PLACEMENT_3D('',#6907,#6908,#6909);\r\n#6911=CYLINDRICAL_SURFACE('',#6910,3.E0);\r\n#6912=ORIENTED_EDGE('',*,*,#6769,.F.);\r\n#6913=ORIENTED_EDGE('',*,*,#5662,.T.);\r\n#6914=ORIENTED_EDGE('',*,*,#6901,.T.);\r\n#6915=ORIENTED_EDGE('',*,*,#6448,.T.);\r\n#6916=EDGE_LOOP('',(#6912,#6913,#6914,#6915));\r\n#6917=FACE_OUTER_BOUND('',#6916,.F.);\r\n#6918=ADVANCED_FACE('',(#6917),#6911,.F.);\r\n#6919=CARTESIAN_POINT('',(2.05E1,-5.889194178308E-2,1.325E1));\r\n#6920=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#6921=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6922=AXIS2_PLACEMENT_3D('',#6919,#6920,#6921);\r\n#6923=CYLINDRICAL_SURFACE('',#6922,1.E0);\r\n#6924=ORIENTED_EDGE('',*,*,#6837,.F.);\r\n#6925=ORIENTED_EDGE('',*,*,#5686,.T.);\r\n#6927=ORIENTED_EDGE('',*,*,#6926,.T.);\r\n#6928=ORIENTED_EDGE('',*,*,#6424,.T.);\r\n#6929=EDGE_LOOP('',(#6924,#6925,#6927,#6928));\r\n#6930=FACE_OUTER_BOUND('',#6929,.F.);\r\n#6931=ADVANCED_FACE('',(#6930),#6923,.F.);\r\n#6932=CARTESIAN_POINT('',(2.6E1,0.E0,1.225E1));\r\n#6933=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6934=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6935=AXIS2_PLACEMENT_3D('',#6932,#6933,#6934);\r\n#6936=PLANE('',#6935);\r\n#6938=ORIENTED_EDGE('',*,*,#6937,.F.);\r\n#6939=ORIENTED_EDGE('',*,*,#6290,.F.);\r\n#6941=ORIENTED_EDGE('',*,*,#6940,.T.);\r\n#6942=ORIENTED_EDGE('',*,*,#5532,.T.);\r\n#6943=EDGE_LOOP('',(#6938,#6939,#6941,#6942));\r\n#6944=FACE_OUTER_BOUND('',#6943,.F.);\r\n#6945=ADVANCED_FACE('',(#6944),#6936,.F.);\r\n#6946=CARTESIAN_POINT('',(2.6E1,0.E0,1.225E1));\r\n#6947=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6948=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6949=AXIS2_PLACEMENT_3D('',#6946,#6947,#6948);\r\n#6950=PLANE('',#6949);\r\n#6951=ORIENTED_EDGE('',*,*,#6926,.F.);\r\n#6952=ORIENTED_EDGE('',*,*,#5684,.T.);\r\n#6954=ORIENTED_EDGE('',*,*,#6953,.F.);\r\n#6955=ORIENTED_EDGE('',*,*,#6426,.F.);\r\n#6956=EDGE_LOOP('',(#6951,#6952,#6954,#6955));\r\n#6957=FACE_OUTER_BOUND('',#6956,.F.);\r\n#6958=ADVANCED_FACE('',(#6957),#6950,.F.);\r\n#6959=CARTESIAN_POINT('',(2.5E1,1.568923974228E0,1.325E1));\r\n#6960=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#6961=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#6962=AXIS2_PLACEMENT_3D('',#6959,#6960,#6961);\r\n#6963=CYLINDRICAL_SURFACE('',#6962,1.E0);\r\n#6965=ORIENTED_EDGE('',*,*,#6964,.F.);\r\n#6966=ORIENTED_EDGE('',*,*,#6292,.T.);\r\n#6967=ORIENTED_EDGE('',*,*,#6937,.T.);\r\n#6968=ORIENTED_EDGE('',*,*,#5530,.T.);\r\n#6969=EDGE_LOOP('',(#6965,#6966,#6967,#6968));\r\n#6970=FACE_OUTER_BOUND('',#6969,.F.);\r\n#6971=ADVANCED_FACE('',(#6970),#6963,.F.);\r\n#6972=CARTESIAN_POINT('',(2.4E1,0.E0,3.2E1));\r\n#6973=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6974=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6975=AXIS2_PLACEMENT_3D('',#6972,#6973,#6974);\r\n#6976=PLANE('',#6975);\r\n#6977=ORIENTED_EDGE('',*,*,#6964,.T.);\r\n#6978=ORIENTED_EDGE('',*,*,#5528,.F.);\r\n#6980=ORIENTED_EDGE('',*,*,#6979,.T.);\r\n#6981=ORIENTED_EDGE('',*,*,#6294,.T.);\r\n#6982=EDGE_LOOP('',(#6977,#6978,#6980,#6981));\r\n#6983=FACE_OUTER_BOUND('',#6982,.F.);\r\n#6984=ADVANCED_FACE('',(#6983),#6976,.T.);\r\n#6985=CARTESIAN_POINT('',(2.4E1,0.E0,3.2E1));\r\n#6986=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#6987=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#6988=AXIS2_PLACEMENT_3D('',#6985,#6986,#6987);\r\n#6989=PLANE('',#6988);\r\n#6991=ORIENTED_EDGE('',*,*,#6990,.T.);\r\n#6992=ORIENTED_EDGE('',*,*,#6242,.T.);\r\n#6994=ORIENTED_EDGE('',*,*,#6993,.F.);\r\n#6995=ORIENTED_EDGE('',*,*,#5498,.F.);\r\n#6996=EDGE_LOOP('',(#6991,#6992,#6994,#6995));\r\n#6997=FACE_OUTER_BOUND('',#6996,.F.);\r\n#6998=ADVANCED_FACE('',(#6997),#6989,.T.);\r\n#6999=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1));\r\n#7000=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7001=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7002=AXIS2_PLACEMENT_3D('',#6999,#7000,#7001);\r\n#7003=PLANE('',#7002);\r\n#7004=ORIENTED_EDGE('',*,*,#6979,.F.);\r\n#7005=ORIENTED_EDGE('',*,*,#5526,.T.);\r\n#7007=ORIENTED_EDGE('',*,*,#7006,.T.);\r\n#7008=ORIENTED_EDGE('',*,*,#6296,.F.);\r\n#7009=EDGE_LOOP('',(#7004,#7005,#7007,#7008));\r\n#7010=FACE_OUTER_BOUND('',#7009,.F.);\r\n#7011=ADVANCED_FACE('',(#7010),#7003,.T.);\r\n#7012=CARTESIAN_POINT('',(0.E0,0.E0,3.2E1));\r\n#7013=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7014=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7015=AXIS2_PLACEMENT_3D('',#7012,#7013,#7014);\r\n#7016=PLANE('',#7015);\r\n#7017=ORIENTED_EDGE('',*,*,#5524,.F.);\r\n#7019=ORIENTED_EDGE('',*,*,#7018,.T.);\r\n#7020=ORIENTED_EDGE('',*,*,#6298,.T.);\r\n#7021=ORIENTED_EDGE('',*,*,#7006,.F.);\r\n#7022=EDGE_LOOP('',(#7017,#7019,#7020,#7021));\r\n#7023=FACE_OUTER_BOUND('',#7022,.F.);\r\n#7024=ADVANCED_FACE('',(#7023),#7016,.T.);\r\n#7025=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1));\r\n#7026=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7027=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7028=AXIS2_PLACEMENT_3D('',#7025,#7026,#7027);\r\n#7029=PLANE('',#7028);\r\n#7030=ORIENTED_EDGE('',*,*,#7018,.F.);\r\n#7031=ORIENTED_EDGE('',*,*,#5522,.T.);\r\n#7032=ORIENTED_EDGE('',*,*,#6678,.T.);\r\n#7033=ORIENTED_EDGE('',*,*,#6300,.F.);\r\n#7034=EDGE_LOOP('',(#7030,#7031,#7032,#7033));\r\n#7035=FACE_OUTER_BOUND('',#7034,.F.);\r\n#7036=ADVANCED_FACE('',(#7035),#7029,.T.);\r\n#7037=CARTESIAN_POINT('',(2.5E1,-7.055249658685E-2,7.E0));\r\n#7038=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7039=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7040=AXIS2_PLACEMENT_3D('',#7037,#7038,#7039);\r\n#7041=CYLINDRICAL_SURFACE('',#7040,1.E0);\r\n#7042=ORIENTED_EDGE('',*,*,#6990,.F.);\r\n#7043=ORIENTED_EDGE('',*,*,#5496,.T.);\r\n#7044=ORIENTED_EDGE('',*,*,#5965,.T.);\r\n#7045=ORIENTED_EDGE('',*,*,#6244,.T.);\r\n#7046=EDGE_LOOP('',(#7042,#7043,#7044,#7045));\r\n#7047=FACE_OUTER_BOUND('',#7046,.F.);\r\n#7048=ADVANCED_FACE('',(#7047),#7041,.F.);\r\n#7049=CARTESIAN_POINT('',(2.E1,0.E0,0.E0));\r\n#7050=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#7051=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7052=AXIS2_PLACEMENT_3D('',#7049,#7050,#7051);\r\n#7053=PLANE('',#7052);\r\n#7055=ORIENTED_EDGE('',*,*,#7054,.F.);\r\n#7056=ORIENTED_EDGE('',*,*,#5500,.T.);\r\n#7057=ORIENTED_EDGE('',*,*,#6993,.T.);\r\n#7058=ORIENTED_EDGE('',*,*,#6240,.F.);\r\n#7059=EDGE_LOOP('',(#7055,#7056,#7057,#7058));\r\n#7060=FACE_OUTER_BOUND('',#7059,.F.);\r\n#7061=ADVANCED_FACE('',(#7060),#7053,.T.);\r\n#7062=CARTESIAN_POINT('',(2.4E1,0.E0,0.E0));\r\n#7063=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7064=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7065=AXIS2_PLACEMENT_3D('',#7062,#7063,#7064);\r\n#7066=PLANE('',#7065);\r\n#7067=ORIENTED_EDGE('',*,*,#5502,.F.);\r\n#7068=ORIENTED_EDGE('',*,*,#7054,.T.);\r\n#7069=ORIENTED_EDGE('',*,*,#6238,.T.);\r\n#7071=ORIENTED_EDGE('',*,*,#7070,.F.);\r\n#7072=EDGE_LOOP('',(#7067,#7068,#7069,#7071));\r\n#7073=FACE_OUTER_BOUND('',#7072,.F.);\r\n#7074=ADVANCED_FACE('',(#7073),#7066,.T.);\r\n#7075=CARTESIAN_POINT('',(0.E0,0.E0,4.E0));\r\n#7076=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#7077=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7078=AXIS2_PLACEMENT_3D('',#7075,#7076,#7077);\r\n#7079=PLANE('',#7078);\r\n#7080=ORIENTED_EDGE('',*,*,#6691,.F.);\r\n#7081=ORIENTED_EDGE('',*,*,#5504,.T.);\r\n#7082=ORIENTED_EDGE('',*,*,#7070,.T.);\r\n#7083=ORIENTED_EDGE('',*,*,#6236,.F.);\r\n#7084=EDGE_LOOP('',(#7080,#7081,#7082,#7083));\r\n#7085=FACE_OUTER_BOUND('',#7084,.F.);\r\n#7086=ADVANCED_FACE('',(#7085),#7079,.T.);\r\n#7087=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1));\r\n#7088=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7089=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7090=AXIS2_PLACEMENT_3D('',#7087,#7088,#7089);\r\n#7091=PLANE('',#7090);\r\n#7092=ORIENTED_EDGE('',*,*,#6940,.F.);\r\n#7093=ORIENTED_EDGE('',*,*,#6288,.T.);\r\n#7095=ORIENTED_EDGE('',*,*,#7094,.T.);\r\n#7096=ORIENTED_EDGE('',*,*,#5534,.F.);\r\n#7097=EDGE_LOOP('',(#7092,#7093,#7095,#7096));\r\n#7098=FACE_OUTER_BOUND('',#7097,.F.);\r\n#7099=ADVANCED_FACE('',(#7098),#7091,.T.);\r\n#7100=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0));\r\n#7101=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7102=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7103=AXIS2_PLACEMENT_3D('',#7100,#7101,#7102);\r\n#7104=PLANE('',#7103);\r\n#7105=ORIENTED_EDGE('',*,*,#5968,.T.);\r\n#7106=ORIENTED_EDGE('',*,*,#5536,.T.);\r\n#7107=ORIENTED_EDGE('',*,*,#7094,.F.);\r\n#7108=ORIENTED_EDGE('',*,*,#6286,.F.);\r\n#7109=ORIENTED_EDGE('',*,*,#6165,.F.);\r\n#7111=ORIENTED_EDGE('',*,*,#7110,.F.);\r\n#7112=EDGE_LOOP('',(#7105,#7106,#7107,#7108,#7109,#7111));\r\n#7113=FACE_OUTER_BOUND('',#7112,.F.);\r\n#7114=ADVANCED_FACE('',(#7113),#7104,.F.);\r\n#7115=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0));\r\n#7116=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0));\r\n#7117=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#7118=AXIS2_PLACEMENT_3D('',#7115,#7116,#7117);\r\n#7119=PLANE('',#7118);\r\n#7120=ORIENTED_EDGE('',*,*,#5970,.T.);\r\n#7121=ORIENTED_EDGE('',*,*,#7110,.T.);\r\n#7122=ORIENTED_EDGE('',*,*,#6163,.F.);\r\n#7124=ORIENTED_EDGE('',*,*,#7123,.F.);\r\n#7125=EDGE_LOOP('',(#7120,#7121,#7122,#7124));\r\n#7126=FACE_OUTER_BOUND('',#7125,.F.);\r\n#7127=ADVANCED_FACE('',(#7126),#7119,.F.);\r\n#7128=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0));\r\n#7129=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7130=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7131=AXIS2_PLACEMENT_3D('',#7128,#7129,#7130);\r\n#7132=PLANE('',#7131);\r\n#7133=ORIENTED_EDGE('',*,*,#5972,.F.);\r\n#7134=ORIENTED_EDGE('',*,*,#7123,.T.);\r\n#7135=ORIENTED_EDGE('',*,*,#6161,.F.);\r\n#7137=ORIENTED_EDGE('',*,*,#7136,.F.);\r\n#7138=EDGE_LOOP('',(#7133,#7134,#7135,#7137));\r\n#7139=FACE_OUTER_BOUND('',#7138,.F.);\r\n#7141=ORIENTED_EDGE('',*,*,#7140,.T.);\r\n#7143=ORIENTED_EDGE('',*,*,#7142,.T.);\r\n#7144=EDGE_LOOP('',(#7141,#7143));\r\n#7145=FACE_BOUND('',#7144,.F.);\r\n#7147=ORIENTED_EDGE('',*,*,#7146,.T.);\r\n#7149=ORIENTED_EDGE('',*,*,#7148,.T.);\r\n#7150=EDGE_LOOP('',(#7147,#7149));\r\n#7151=FACE_BOUND('',#7150,.F.);\r\n#7152=ADVANCED_FACE('',(#7139,#7145,#7151),#7132,.F.);\r\n#7153=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0));\r\n#7154=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7155=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7156=AXIS2_PLACEMENT_3D('',#7153,#7154,#7155);\r\n#7157=PLANE('',#7156);\r\n#7159=ORIENTED_EDGE('',*,*,#7158,.T.);\r\n#7160=ORIENTED_EDGE('',*,*,#6430,.F.);\r\n#7162=ORIENTED_EDGE('',*,*,#7161,.T.);\r\n#7163=ORIENTED_EDGE('',*,*,#5680,.T.);\r\n#7164=EDGE_LOOP('',(#7159,#7160,#7162,#7163));\r\n#7165=FACE_OUTER_BOUND('',#7164,.F.);\r\n#7166=ADVANCED_FACE('',(#7165),#7157,.F.);\r\n#7167=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0));\r\n#7168=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7169=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7170=AXIS2_PLACEMENT_3D('',#7167,#7168,#7169);\r\n#7171=PLANE('',#7170);\r\n#7172=ORIENTED_EDGE('',*,*,#6325,.F.);\r\n#7173=ORIENTED_EDGE('',*,*,#5974,.T.);\r\n#7174=ORIENTED_EDGE('',*,*,#7136,.T.);\r\n#7175=ORIENTED_EDGE('',*,*,#6159,.F.);\r\n#7176=EDGE_LOOP('',(#7172,#7173,#7174,#7175));\r\n#7177=FACE_OUTER_BOUND('',#7176,.F.);\r\n#7178=ADVANCED_FACE('',(#7177),#7171,.F.);\r\n#7179=CARTESIAN_POINT('',(1.8E1,-7.099592191979E-2,1.1E1));\r\n#7180=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7181=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7182=AXIS2_PLACEMENT_3D('',#7179,#7180,#7181);\r\n#7183=CYLINDRICAL_SURFACE('',#7182,1.E0);\r\n#7184=ORIENTED_EDGE('',*,*,#7158,.F.);\r\n#7185=ORIENTED_EDGE('',*,*,#5678,.T.);\r\n#7187=ORIENTED_EDGE('',*,*,#7186,.T.);\r\n#7188=ORIENTED_EDGE('',*,*,#6432,.T.);\r\n#7189=EDGE_LOOP('',(#7184,#7185,#7187,#7188));\r\n#7190=FACE_OUTER_BOUND('',#7189,.F.);\r\n#7191=ADVANCED_FACE('',(#7190),#7183,.F.);\r\n#7192=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1));\r\n#7193=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7194=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7195=AXIS2_PLACEMENT_3D('',#7192,#7193,#7194);\r\n#7196=PLANE('',#7195);\r\n#7198=ORIENTED_EDGE('',*,*,#7197,.F.);\r\n#7199=ORIENTED_EDGE('',*,*,#6434,.T.);\r\n#7200=ORIENTED_EDGE('',*,*,#7186,.F.);\r\n#7201=ORIENTED_EDGE('',*,*,#5676,.F.);\r\n#7202=EDGE_LOOP('',(#7198,#7199,#7200,#7201));\r\n#7203=FACE_OUTER_BOUND('',#7202,.F.);\r\n#7204=ADVANCED_FACE('',(#7203),#7196,.T.);\r\n#7205=CARTESIAN_POINT('',(6.E0,1.567729432957E0,1.1E1));\r\n#7206=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7207=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7208=AXIS2_PLACEMENT_3D('',#7205,#7206,#7207);\r\n#7209=CYLINDRICAL_SURFACE('',#7208,1.E0);\r\n#7211=ORIENTED_EDGE('',*,*,#7210,.F.);\r\n#7212=ORIENTED_EDGE('',*,*,#6436,.T.);\r\n#7213=ORIENTED_EDGE('',*,*,#7197,.T.);\r\n#7214=ORIENTED_EDGE('',*,*,#5674,.T.);\r\n#7215=EDGE_LOOP('',(#7211,#7212,#7213,#7214));\r\n#7216=FACE_OUTER_BOUND('',#7215,.F.);\r\n#7217=ADVANCED_FACE('',(#7216),#7209,.F.);\r\n#7218=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0));\r\n#7219=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7220=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7221=AXIS2_PLACEMENT_3D('',#7218,#7219,#7220);\r\n#7222=PLANE('',#7221);\r\n#7223=ORIENTED_EDGE('',*,*,#7210,.T.);\r\n#7224=ORIENTED_EDGE('',*,*,#5672,.F.);\r\n#7226=ORIENTED_EDGE('',*,*,#7225,.T.);\r\n#7227=ORIENTED_EDGE('',*,*,#6438,.T.);\r\n#7228=EDGE_LOOP('',(#7223,#7224,#7226,#7227));\r\n#7229=FACE_OUTER_BOUND('',#7228,.F.);\r\n#7230=ADVANCED_FACE('',(#7229),#7222,.T.);\r\n#7231=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0));\r\n#7232=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7233=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7234=AXIS2_PLACEMENT_3D('',#7231,#7232,#7233);\r\n#7235=PLANE('',#7234);\r\n#7236=ORIENTED_EDGE('',*,*,#6322,.T.);\r\n#7238=ORIENTED_EDGE('',*,*,#7237,.T.);\r\n#7240=ORIENTED_EDGE('',*,*,#7239,.F.);\r\n#7241=ORIENTED_EDGE('',*,*,#5978,.T.);\r\n#7242=EDGE_LOOP('',(#7236,#7238,#7240,#7241));\r\n#7243=FACE_OUTER_BOUND('',#7242,.F.);\r\n#7244=ADVANCED_FACE('',(#7243),#7235,.T.);\r\n#7245=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1));\r\n#7246=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7247=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7248=AXIS2_PLACEMENT_3D('',#7245,#7246,#7247);\r\n#7249=PLANE('',#7248);\r\n#7250=ORIENTED_EDGE('',*,*,#7225,.F.);\r\n#7251=ORIENTED_EDGE('',*,*,#5670,.T.);\r\n#7252=ORIENTED_EDGE('',*,*,#6718,.T.);\r\n#7253=ORIENTED_EDGE('',*,*,#6440,.F.);\r\n#7254=EDGE_LOOP('',(#7250,#7251,#7252,#7253));\r\n#7255=FACE_OUTER_BOUND('',#7254,.F.);\r\n#7256=ADVANCED_FACE('',(#7255),#7249,.T.);\r\n#7257=CARTESIAN_POINT('',(0.E0,0.E0,1.E1));\r\n#7258=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7259=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7260=AXIS2_PLACEMENT_3D('',#7257,#7258,#7259);\r\n#7261=PLANE('',#7260);\r\n#7263=ORIENTED_EDGE('',*,*,#7262,.F.);\r\n#7264=ORIENTED_EDGE('',*,*,#6312,.F.);\r\n#7266=ORIENTED_EDGE('',*,*,#7265,.F.);\r\n#7268=ORIENTED_EDGE('',*,*,#7267,.F.);\r\n#7270=ORIENTED_EDGE('',*,*,#7269,.F.);\r\n#7271=ORIENTED_EDGE('',*,*,#7237,.F.);\r\n#7272=ORIENTED_EDGE('',*,*,#6320,.F.);\r\n#7274=ORIENTED_EDGE('',*,*,#7273,.T.);\r\n#7276=ORIENTED_EDGE('',*,*,#7275,.F.);\r\n#7277=EDGE_LOOP('',(#7263,#7264,#7266,#7268,#7270,#7271,#7272,#7274,#7276));\r\n#7278=FACE_OUTER_BOUND('',#7277,.F.);\r\n#7280=ORIENTED_EDGE('',*,*,#7279,.T.);\r\n#7282=ORIENTED_EDGE('',*,*,#7281,.T.);\r\n#7283=EDGE_LOOP('',(#7280,#7282));\r\n#7284=FACE_BOUND('',#7283,.F.);\r\n#7286=ORIENTED_EDGE('',*,*,#7285,.F.);\r\n#7288=ORIENTED_EDGE('',*,*,#7287,.T.);\r\n#7290=ORIENTED_EDGE('',*,*,#7289,.F.);\r\n#7292=ORIENTED_EDGE('',*,*,#7291,.T.);\r\n#7294=ORIENTED_EDGE('',*,*,#7293,.F.);\r\n#7296=ORIENTED_EDGE('',*,*,#7295,.T.);\r\n#7298=ORIENTED_EDGE('',*,*,#7297,.F.);\r\n#7300=ORIENTED_EDGE('',*,*,#7299,.T.);\r\n#7302=ORIENTED_EDGE('',*,*,#7301,.F.);\r\n#7304=ORIENTED_EDGE('',*,*,#7303,.T.);\r\n#7306=ORIENTED_EDGE('',*,*,#7305,.F.);\r\n#7308=ORIENTED_EDGE('',*,*,#7307,.T.);\r\n#7309=EDGE_LOOP('',(#7286,#7288,#7290,#7292,#7294,#7296,#7298,#7300,#7302,#7304,\r\n#7306,#7308));\r\n#7310=FACE_BOUND('',#7309,.F.);\r\n#7311=ADVANCED_FACE('',(#7278,#7284,#7310),#7261,.T.);\r\n#7312=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0));\r\n#7313=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7314=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7315=AXIS2_PLACEMENT_3D('',#7312,#7313,#7314);\r\n#7316=CYLINDRICAL_SURFACE('',#7315,1.625E-1);\r\n#7317=ORIENTED_EDGE('',*,*,#6031,.T.);\r\n#7319=ORIENTED_EDGE('',*,*,#7318,.T.);\r\n#7320=ORIENTED_EDGE('',*,*,#7279,.F.);\r\n#7322=ORIENTED_EDGE('',*,*,#7321,.F.);\r\n#7323=EDGE_LOOP('',(#7317,#7319,#7320,#7322));\r\n#7324=FACE_OUTER_BOUND('',#7323,.F.);\r\n#7325=ADVANCED_FACE('',(#7324),#7316,.F.);\r\n#7326=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0));\r\n#7327=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7328=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7329=AXIS2_PLACEMENT_3D('',#7326,#7327,#7328);\r\n#7330=CYLINDRICAL_SURFACE('',#7329,1.625E-1);\r\n#7331=ORIENTED_EDGE('',*,*,#6033,.T.);\r\n#7332=ORIENTED_EDGE('',*,*,#7321,.T.);\r\n#7333=ORIENTED_EDGE('',*,*,#7281,.F.);\r\n#7334=ORIENTED_EDGE('',*,*,#7318,.F.);\r\n#7335=EDGE_LOOP('',(#7331,#7332,#7333,#7334));\r\n#7336=FACE_OUTER_BOUND('',#7335,.F.);\r\n#7337=ADVANCED_FACE('',(#7336),#7330,.F.);\r\n#7338=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.2E1));\r\n#7339=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7340=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7341=AXIS2_PLACEMENT_3D('',#7338,#7339,#7340);\r\n#7342=PLANE('',#7341);\r\n#7343=ORIENTED_EDGE('',*,*,#6314,.T.);\r\n#7344=ORIENTED_EDGE('',*,*,#7262,.T.);\r\n#7346=ORIENTED_EDGE('',*,*,#7345,.T.);\r\n#7347=EDGE_LOOP('',(#7343,#7344,#7346));\r\n#7348=FACE_OUTER_BOUND('',#7347,.F.);\r\n#7349=ADVANCED_FACE('',(#7348),#7342,.F.);\r\n#7350=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1));\r\n#7351=DIRECTION('',(0.E0,5.E-1,8.660254037844E-1));\r\n#7352=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#7353=AXIS2_PLACEMENT_3D('',#7350,#7351,#7352);\r\n#7354=PLANE('',#7353);\r\n#7355=ORIENTED_EDGE('',*,*,#6316,.F.);\r\n#7356=ORIENTED_EDGE('',*,*,#7345,.F.);\r\n#7357=ORIENTED_EDGE('',*,*,#7275,.T.);\r\n#7359=ORIENTED_EDGE('',*,*,#7358,.T.);\r\n#7360=EDGE_LOOP('',(#7355,#7356,#7357,#7359));\r\n#7361=FACE_OUTER_BOUND('',#7360,.F.);\r\n#7363=ORIENTED_EDGE('',*,*,#7362,.T.);\r\n#7365=ORIENTED_EDGE('',*,*,#7364,.T.);\r\n#7366=EDGE_LOOP('',(#7363,#7365));\r\n#7367=FACE_BOUND('',#7366,.F.);\r\n#7368=ADVANCED_FACE('',(#7361,#7367),#7354,.T.);\r\n#7369=CARTESIAN_POINT('',(2.E0,1.5E0,1.2E1));\r\n#7370=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7371=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7372=AXIS2_PLACEMENT_3D('',#7369,#7370,#7371);\r\n#7373=PLANE('',#7372);\r\n#7374=ORIENTED_EDGE('',*,*,#6318,.F.);\r\n#7375=ORIENTED_EDGE('',*,*,#7358,.F.);\r\n#7376=ORIENTED_EDGE('',*,*,#7273,.F.);\r\n#7377=EDGE_LOOP('',(#7374,#7375,#7376));\r\n#7378=FACE_OUTER_BOUND('',#7377,.F.);\r\n#7379=ADVANCED_FACE('',(#7378),#7373,.T.);\r\n#7380=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1));\r\n#7381=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7382=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7383=AXIS2_PLACEMENT_3D('',#7380,#7381,#7382);\r\n#7384=CYLINDRICAL_SURFACE('',#7383,2.575E-1);\r\n#7386=ORIENTED_EDGE('',*,*,#7385,.F.);\r\n#7387=ORIENTED_EDGE('',*,*,#7362,.F.);\r\n#7389=ORIENTED_EDGE('',*,*,#7388,.F.);\r\n#7391=ORIENTED_EDGE('',*,*,#7390,.F.);\r\n#7392=EDGE_LOOP('',(#7386,#7387,#7389,#7391));\r\n#7393=FACE_OUTER_BOUND('',#7392,.F.);\r\n#7394=ADVANCED_FACE('',(#7393),#7384,.F.);\r\n#7395=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1));\r\n#7396=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7397=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7398=AXIS2_PLACEMENT_3D('',#7395,#7396,#7397);\r\n#7399=CYLINDRICAL_SURFACE('',#7398,2.575E-1);\r\n#7400=ORIENTED_EDGE('',*,*,#7388,.T.);\r\n#7401=ORIENTED_EDGE('',*,*,#7364,.F.);\r\n#7402=ORIENTED_EDGE('',*,*,#7385,.T.);\r\n#7404=ORIENTED_EDGE('',*,*,#7403,.F.);\r\n#7405=EDGE_LOOP('',(#7400,#7401,#7402,#7404));\r\n#7406=FACE_OUTER_BOUND('',#7405,.F.);\r\n#7407=ADVANCED_FACE('',(#7406),#7399,.F.);\r\n#7408=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1));\r\n#7409=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7410=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7411=AXIS2_PLACEMENT_3D('',#7408,#7409,#7410);\r\n#7412=PLANE('',#7411);\r\n#7413=ORIENTED_EDGE('',*,*,#7390,.T.);\r\n#7414=ORIENTED_EDGE('',*,*,#7403,.T.);\r\n#7415=EDGE_LOOP('',(#7413,#7414));\r\n#7416=FACE_OUTER_BOUND('',#7415,.F.);\r\n#7418=ORIENTED_EDGE('',*,*,#7417,.F.);\r\n#7420=ORIENTED_EDGE('',*,*,#7419,.F.);\r\n#7421=EDGE_LOOP('',(#7418,#7420));\r\n#7422=FACE_BOUND('',#7421,.F.);\r\n#7423=ADVANCED_FACE('',(#7416,#7422),#7412,.F.);\r\n#7424=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1));\r\n#7425=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7426=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7427=AXIS2_PLACEMENT_3D('',#7424,#7425,#7426);\r\n#7428=CYLINDRICAL_SURFACE('',#7427,1.925E-1);\r\n#7429=ORIENTED_EDGE('',*,*,#7417,.T.);\r\n#7431=ORIENTED_EDGE('',*,*,#7430,.T.);\r\n#7432=ORIENTED_EDGE('',*,*,#5620,.F.);\r\n#7434=ORIENTED_EDGE('',*,*,#7433,.F.);\r\n#7435=EDGE_LOOP('',(#7429,#7431,#7432,#7434));\r\n#7436=FACE_OUTER_BOUND('',#7435,.F.);\r\n#7437=ADVANCED_FACE('',(#7436),#7428,.F.);\r\n#7438=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1));\r\n#7439=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7440=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7441=AXIS2_PLACEMENT_3D('',#7438,#7439,#7440);\r\n#7442=CYLINDRICAL_SURFACE('',#7441,1.925E-1);\r\n#7443=ORIENTED_EDGE('',*,*,#7419,.T.);\r\n#7444=ORIENTED_EDGE('',*,*,#7433,.T.);\r\n#7445=ORIENTED_EDGE('',*,*,#5622,.F.);\r\n#7446=ORIENTED_EDGE('',*,*,#7430,.F.);\r\n#7447=EDGE_LOOP('',(#7443,#7444,#7445,#7446));\r\n#7448=FACE_OUTER_BOUND('',#7447,.F.);\r\n#7449=ADVANCED_FACE('',(#7448),#7442,.F.);\r\n#7450=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0));\r\n#7451=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7452=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7453=AXIS2_PLACEMENT_3D('',#7450,#7451,#7452);\r\n#7454=PLANE('',#7453);\r\n#7455=ORIENTED_EDGE('',*,*,#7265,.T.);\r\n#7456=ORIENTED_EDGE('',*,*,#6310,.T.);\r\n#7458=ORIENTED_EDGE('',*,*,#7457,.F.);\r\n#7459=ORIENTED_EDGE('',*,*,#5512,.F.);\r\n#7460=ORIENTED_EDGE('',*,*,#5984,.T.);\r\n#7462=ORIENTED_EDGE('',*,*,#7461,.T.);\r\n#7463=EDGE_LOOP('',(#7455,#7456,#7458,#7459,#7460,#7462));\r\n#7464=FACE_OUTER_BOUND('',#7463,.F.);\r\n#7465=ADVANCED_FACE('',(#7464),#7454,.T.);\r\n#7466=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1));\r\n#7467=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7468=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7469=AXIS2_PLACEMENT_3D('',#7466,#7467,#7468);\r\n#7470=PLANE('',#7469);\r\n#7471=ORIENTED_EDGE('',*,*,#6731,.F.);\r\n#7472=ORIENTED_EDGE('',*,*,#5514,.T.);\r\n#7473=ORIENTED_EDGE('',*,*,#7457,.T.);\r\n#7474=ORIENTED_EDGE('',*,*,#6308,.F.);\r\n#7475=EDGE_LOOP('',(#7471,#7472,#7473,#7474));\r\n#7476=FACE_OUTER_BOUND('',#7475,.F.);\r\n#7477=ADVANCED_FACE('',(#7476),#7470,.T.);\r\n#7478=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0));\r\n#7479=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#7480=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#7481=AXIS2_PLACEMENT_3D('',#7478,#7479,#7480);\r\n#7482=PLANE('',#7481);\r\n#7483=ORIENTED_EDGE('',*,*,#5982,.F.);\r\n#7485=ORIENTED_EDGE('',*,*,#7484,.T.);\r\n#7486=ORIENTED_EDGE('',*,*,#7267,.T.);\r\n#7487=ORIENTED_EDGE('',*,*,#7461,.F.);\r\n#7488=EDGE_LOOP('',(#7483,#7485,#7486,#7487));\r\n#7489=FACE_OUTER_BOUND('',#7488,.F.);\r\n#7490=ADVANCED_FACE('',(#7489),#7482,.T.);\r\n#7491=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0));\r\n#7492=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7493=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7494=AXIS2_PLACEMENT_3D('',#7491,#7492,#7493);\r\n#7495=PLANE('',#7494);\r\n#7496=ORIENTED_EDGE('',*,*,#5980,.F.);\r\n#7497=ORIENTED_EDGE('',*,*,#7239,.T.);\r\n#7498=ORIENTED_EDGE('',*,*,#7269,.T.);\r\n#7499=ORIENTED_EDGE('',*,*,#7484,.F.);\r\n#7500=EDGE_LOOP('',(#7496,#7497,#7498,#7499));\r\n#7501=FACE_OUTER_BOUND('',#7500,.F.);\r\n#7503=ORIENTED_EDGE('',*,*,#7502,.F.);\r\n#7505=ORIENTED_EDGE('',*,*,#7504,.F.);\r\n#7506=EDGE_LOOP('',(#7503,#7505));\r\n#7507=FACE_BOUND('',#7506,.F.);\r\n#7509=ORIENTED_EDGE('',*,*,#7508,.F.);\r\n#7511=ORIENTED_EDGE('',*,*,#7510,.F.);\r\n#7512=EDGE_LOOP('',(#7509,#7511));\r\n#7513=FACE_BOUND('',#7512,.F.);\r\n#7514=ADVANCED_FACE('',(#7501,#7507,#7513),#7495,.T.);\r\n#7515=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0));\r\n#7516=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7517=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7518=AXIS2_PLACEMENT_3D('',#7515,#7516,#7517);\r\n#7519=CYLINDRICAL_SURFACE('',#7518,9.5E-2);\r\n#7520=ORIENTED_EDGE('',*,*,#7502,.T.);\r\n#7522=ORIENTED_EDGE('',*,*,#7521,.T.);\r\n#7524=ORIENTED_EDGE('',*,*,#7523,.F.);\r\n#7526=ORIENTED_EDGE('',*,*,#7525,.F.);\r\n#7527=EDGE_LOOP('',(#7520,#7522,#7524,#7526));\r\n#7528=FACE_OUTER_BOUND('',#7527,.F.);\r\n#7529=ADVANCED_FACE('',(#7528),#7519,.F.);\r\n#7530=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0));\r\n#7531=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7532=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7533=AXIS2_PLACEMENT_3D('',#7530,#7531,#7532);\r\n#7534=CYLINDRICAL_SURFACE('',#7533,9.5E-2);\r\n#7535=ORIENTED_EDGE('',*,*,#7504,.T.);\r\n#7536=ORIENTED_EDGE('',*,*,#7525,.T.);\r\n#7538=ORIENTED_EDGE('',*,*,#7537,.F.);\r\n#7539=ORIENTED_EDGE('',*,*,#7521,.F.);\r\n#7540=EDGE_LOOP('',(#7535,#7536,#7538,#7539));\r\n#7541=FACE_OUTER_BOUND('',#7540,.F.);\r\n#7542=ADVANCED_FACE('',(#7541),#7534,.F.);\r\n#7543=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0));\r\n#7544=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7545=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7546=AXIS2_PLACEMENT_3D('',#7543,#7544,#7545);\r\n#7547=PLANE('',#7546);\r\n#7548=ORIENTED_EDGE('',*,*,#7523,.T.);\r\n#7549=ORIENTED_EDGE('',*,*,#7537,.T.);\r\n#7550=EDGE_LOOP('',(#7548,#7549));\r\n#7551=FACE_OUTER_BOUND('',#7550,.F.);\r\n#7552=ADVANCED_FACE('',(#7551),#7547,.F.);\r\n#7553=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0));\r\n#7554=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7555=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7556=AXIS2_PLACEMENT_3D('',#7553,#7554,#7555);\r\n#7557=CYLINDRICAL_SURFACE('',#7556,6.25E-2);\r\n#7558=ORIENTED_EDGE('',*,*,#7508,.T.);\r\n#7560=ORIENTED_EDGE('',*,*,#7559,.T.);\r\n#7562=ORIENTED_EDGE('',*,*,#7561,.F.);\r\n#7564=ORIENTED_EDGE('',*,*,#7563,.F.);\r\n#7565=EDGE_LOOP('',(#7558,#7560,#7562,#7564));\r\n#7566=FACE_OUTER_BOUND('',#7565,.F.);\r\n#7567=ADVANCED_FACE('',(#7566),#7557,.F.);\r\n#7568=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0));\r\n#7569=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7570=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7571=AXIS2_PLACEMENT_3D('',#7568,#7569,#7570);\r\n#7572=CYLINDRICAL_SURFACE('',#7571,6.25E-2);\r\n#7573=ORIENTED_EDGE('',*,*,#7510,.T.);\r\n#7574=ORIENTED_EDGE('',*,*,#7563,.T.);\r\n#7576=ORIENTED_EDGE('',*,*,#7575,.F.);\r\n#7577=ORIENTED_EDGE('',*,*,#7559,.F.);\r\n#7578=EDGE_LOOP('',(#7573,#7574,#7576,#7577));\r\n#7579=FACE_OUTER_BOUND('',#7578,.F.);\r\n#7580=ADVANCED_FACE('',(#7579),#7572,.F.);\r\n#7581=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0));\r\n#7582=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7583=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7584=AXIS2_PLACEMENT_3D('',#7581,#7582,#7583);\r\n#7585=PLANE('',#7584);\r\n#7586=ORIENTED_EDGE('',*,*,#7561,.T.);\r\n#7587=ORIENTED_EDGE('',*,*,#7575,.T.);\r\n#7588=EDGE_LOOP('',(#7586,#7587));\r\n#7589=FACE_OUTER_BOUND('',#7588,.F.);\r\n#7590=ADVANCED_FACE('',(#7589),#7585,.F.);\r\n#7591=CARTESIAN_POINT('',(2.15E0,6.65E0,9.441108058217E0));\r\n#7592=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7593=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7594=AXIS2_PLACEMENT_3D('',#7591,#7592,#7593);\r\n#7595=CYLINDRICAL_SURFACE('',#7594,3.5E-1);\r\n#7597=ORIENTED_EDGE('',*,*,#7596,.T.);\r\n#7598=ORIENTED_EDGE('',*,*,#7285,.T.);\r\n#7600=ORIENTED_EDGE('',*,*,#7599,.F.);\r\n#7602=ORIENTED_EDGE('',*,*,#7601,.T.);\r\n#7603=EDGE_LOOP('',(#7597,#7598,#7600,#7602));\r\n#7604=FACE_OUTER_BOUND('',#7603,.F.);\r\n#7605=ADVANCED_FACE('',(#7604),#7595,.T.);\r\n#7606=CARTESIAN_POINT('',(2.5E0,7.E0,1.E1));\r\n#7607=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7608=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7609=AXIS2_PLACEMENT_3D('',#7606,#7607,#7608);\r\n#7610=PLANE('',#7609);\r\n#7611=ORIENTED_EDGE('',*,*,#7596,.F.);\r\n#7613=ORIENTED_EDGE('',*,*,#7612,.T.);\r\n#7615=ORIENTED_EDGE('',*,*,#7614,.F.);\r\n#7616=ORIENTED_EDGE('',*,*,#7287,.F.);\r\n#7617=EDGE_LOOP('',(#7611,#7613,#7615,#7616));\r\n#7618=FACE_OUTER_BOUND('',#7617,.F.);\r\n#7619=ADVANCED_FACE('',(#7618),#7610,.F.);\r\n#7620=CARTESIAN_POINT('',(0.E0,0.E0,9.5E0));\r\n#7621=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#7622=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7623=AXIS2_PLACEMENT_3D('',#7620,#7621,#7622);\r\n#7624=PLANE('',#7623);\r\n#7625=ORIENTED_EDGE('',*,*,#7612,.F.);\r\n#7626=ORIENTED_EDGE('',*,*,#7601,.F.);\r\n#7628=ORIENTED_EDGE('',*,*,#7627,.F.);\r\n#7630=ORIENTED_EDGE('',*,*,#7629,.F.);\r\n#7632=ORIENTED_EDGE('',*,*,#7631,.F.);\r\n#7634=ORIENTED_EDGE('',*,*,#7633,.F.);\r\n#7636=ORIENTED_EDGE('',*,*,#7635,.F.);\r\n#7638=ORIENTED_EDGE('',*,*,#7637,.F.);\r\n#7640=ORIENTED_EDGE('',*,*,#7639,.F.);\r\n#7642=ORIENTED_EDGE('',*,*,#7641,.F.);\r\n#7644=ORIENTED_EDGE('',*,*,#7643,.F.);\r\n#7646=ORIENTED_EDGE('',*,*,#7645,.F.);\r\n#7647=EDGE_LOOP('',(#7625,#7626,#7628,#7630,#7632,#7634,#7636,#7638,#7640,#7642,\r\n#7644,#7646));\r\n#7648=FACE_OUTER_BOUND('',#7647,.F.);\r\n#7649=ADVANCED_FACE('',(#7648),#7624,.T.);\r\n#7650=CARTESIAN_POINT('',(1.357969178416E0,7.E0,1.E1));\r\n#7651=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7652=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7653=AXIS2_PLACEMENT_3D('',#7650,#7651,#7652);\r\n#7654=PLANE('',#7653);\r\n#7655=ORIENTED_EDGE('',*,*,#7599,.T.);\r\n#7656=ORIENTED_EDGE('',*,*,#7307,.F.);\r\n#7658=ORIENTED_EDGE('',*,*,#7657,.T.);\r\n#7659=ORIENTED_EDGE('',*,*,#7627,.T.);\r\n#7660=EDGE_LOOP('',(#7655,#7656,#7658,#7659));\r\n#7661=FACE_OUTER_BOUND('',#7660,.F.);\r\n#7662=ADVANCED_FACE('',(#7661),#7654,.F.);\r\n#7663=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,1.006892397423E1));\r\n#7664=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7665=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7666=AXIS2_PLACEMENT_3D('',#7663,#7664,#7665);\r\n#7667=CYLINDRICAL_SURFACE('',#7666,3.5E-1);\r\n#7668=ORIENTED_EDGE('',*,*,#7657,.F.);\r\n#7669=ORIENTED_EDGE('',*,*,#7305,.T.);\r\n#7671=ORIENTED_EDGE('',*,*,#7670,.T.);\r\n#7672=ORIENTED_EDGE('',*,*,#7629,.T.);\r\n#7673=EDGE_LOOP('',(#7668,#7669,#7671,#7672));\r\n#7674=FACE_OUTER_BOUND('',#7673,.F.);\r\n#7675=ADVANCED_FACE('',(#7674),#7667,.F.);\r\n#7676=CARTESIAN_POINT('',(2.746858067304E0,9.5E0,1.E1));\r\n#7677=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#7678=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#7679=AXIS2_PLACEMENT_3D('',#7676,#7677,#7678);\r\n#7680=PLANE('',#7679);\r\n#7681=ORIENTED_EDGE('',*,*,#7670,.F.);\r\n#7682=ORIENTED_EDGE('',*,*,#7303,.F.);\r\n#7684=ORIENTED_EDGE('',*,*,#7683,.T.);\r\n#7685=ORIENTED_EDGE('',*,*,#7631,.T.);\r\n#7686=EDGE_LOOP('',(#7681,#7682,#7684,#7685));\r\n#7687=FACE_OUTER_BOUND('',#7686,.F.);\r\n#7688=ADVANCED_FACE('',(#7687),#7680,.F.);\r\n#7689=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,1.006892397423E1));\r\n#7690=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7691=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#7692=AXIS2_PLACEMENT_3D('',#7689,#7690,#7691);\r\n#7693=CYLINDRICAL_SURFACE('',#7692,3.5E-1);\r\n#7694=ORIENTED_EDGE('',*,*,#7683,.F.);\r\n#7695=ORIENTED_EDGE('',*,*,#7301,.T.);\r\n#7697=ORIENTED_EDGE('',*,*,#7696,.T.);\r\n#7698=ORIENTED_EDGE('',*,*,#7633,.T.);\r\n#7699=EDGE_LOOP('',(#7694,#7695,#7697,#7698));\r\n#7700=FACE_OUTER_BOUND('',#7699,.F.);\r\n#7701=ADVANCED_FACE('',(#7700),#7693,.F.);\r\n#7702=CARTESIAN_POINT('',(4.5E0,9.5E0,1.E1));\r\n#7703=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7704=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7705=AXIS2_PLACEMENT_3D('',#7702,#7703,#7704);\r\n#7706=PLANE('',#7705);\r\n#7707=ORIENTED_EDGE('',*,*,#7696,.F.);\r\n#7708=ORIENTED_EDGE('',*,*,#7299,.F.);\r\n#7710=ORIENTED_EDGE('',*,*,#7709,.T.);\r\n#7711=ORIENTED_EDGE('',*,*,#7635,.T.);\r\n#7712=EDGE_LOOP('',(#7707,#7708,#7710,#7711));\r\n#7713=FACE_OUTER_BOUND('',#7712,.F.);\r\n#7714=ADVANCED_FACE('',(#7713),#7706,.F.);\r\n#7715=CARTESIAN_POINT('',(4.15E0,9.15E0,1.006892397423E1));\r\n#7716=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7717=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7718=AXIS2_PLACEMENT_3D('',#7715,#7716,#7717);\r\n#7719=CYLINDRICAL_SURFACE('',#7718,3.5E-1);\r\n#7720=ORIENTED_EDGE('',*,*,#7709,.F.);\r\n#7721=ORIENTED_EDGE('',*,*,#7297,.T.);\r\n#7723=ORIENTED_EDGE('',*,*,#7722,.T.);\r\n#7724=ORIENTED_EDGE('',*,*,#7637,.T.);\r\n#7725=EDGE_LOOP('',(#7720,#7721,#7723,#7724));\r\n#7726=FACE_OUTER_BOUND('',#7725,.F.);\r\n#7727=ADVANCED_FACE('',(#7726),#7719,.F.);\r\n#7728=CARTESIAN_POINT('',(4.5E0,2.E0,1.E1));\r\n#7729=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7730=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7731=AXIS2_PLACEMENT_3D('',#7728,#7729,#7730);\r\n#7732=PLANE('',#7731);\r\n#7734=ORIENTED_EDGE('',*,*,#7733,.T.);\r\n#7735=ORIENTED_EDGE('',*,*,#7639,.T.);\r\n#7736=ORIENTED_EDGE('',*,*,#7722,.F.);\r\n#7737=ORIENTED_EDGE('',*,*,#7295,.F.);\r\n#7738=EDGE_LOOP('',(#7734,#7735,#7736,#7737));\r\n#7739=FACE_OUTER_BOUND('',#7738,.F.);\r\n#7740=ADVANCED_FACE('',(#7739),#7732,.F.);\r\n#7741=CARTESIAN_POINT('',(4.15E0,2.35E0,1.006892397423E1));\r\n#7742=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7743=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7744=AXIS2_PLACEMENT_3D('',#7741,#7742,#7743);\r\n#7745=CYLINDRICAL_SURFACE('',#7744,3.5E-1);\r\n#7746=ORIENTED_EDGE('',*,*,#7733,.F.);\r\n#7747=ORIENTED_EDGE('',*,*,#7293,.T.);\r\n#7749=ORIENTED_EDGE('',*,*,#7748,.T.);\r\n#7750=ORIENTED_EDGE('',*,*,#7641,.T.);\r\n#7751=EDGE_LOOP('',(#7746,#7747,#7749,#7750));\r\n#7752=FACE_OUTER_BOUND('',#7751,.F.);\r\n#7753=ADVANCED_FACE('',(#7752),#7745,.F.);\r\n#7754=CARTESIAN_POINT('',(2.5E0,2.E0,1.E1));\r\n#7755=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7756=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7757=AXIS2_PLACEMENT_3D('',#7754,#7755,#7756);\r\n#7758=PLANE('',#7757);\r\n#7760=ORIENTED_EDGE('',*,*,#7759,.T.);\r\n#7761=ORIENTED_EDGE('',*,*,#7643,.T.);\r\n#7762=ORIENTED_EDGE('',*,*,#7748,.F.);\r\n#7763=ORIENTED_EDGE('',*,*,#7291,.F.);\r\n#7764=EDGE_LOOP('',(#7760,#7761,#7762,#7763));\r\n#7765=FACE_OUTER_BOUND('',#7764,.F.);\r\n#7766=ADVANCED_FACE('',(#7765),#7758,.F.);\r\n#7767=CARTESIAN_POINT('',(2.85E0,2.35E0,1.006892397423E1));\r\n#7768=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#7769=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7770=AXIS2_PLACEMENT_3D('',#7767,#7768,#7769);\r\n#7771=CYLINDRICAL_SURFACE('',#7770,3.5E-1);\r\n#7772=ORIENTED_EDGE('',*,*,#7759,.F.);\r\n#7773=ORIENTED_EDGE('',*,*,#7289,.T.);\r\n#7774=ORIENTED_EDGE('',*,*,#7614,.T.);\r\n#7775=ORIENTED_EDGE('',*,*,#7645,.T.);\r\n#7776=EDGE_LOOP('',(#7772,#7773,#7774,#7775));\r\n#7777=FACE_OUTER_BOUND('',#7776,.F.);\r\n#7778=ADVANCED_FACE('',(#7777),#7771,.F.);\r\n#7779=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1));\r\n#7780=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#7781=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7782=AXIS2_PLACEMENT_3D('',#7779,#7780,#7781);\r\n#7783=PLANE('',#7782);\r\n#7784=ORIENTED_EDGE('',*,*,#7161,.F.);\r\n#7785=ORIENTED_EDGE('',*,*,#6428,.T.);\r\n#7786=ORIENTED_EDGE('',*,*,#6953,.T.);\r\n#7787=ORIENTED_EDGE('',*,*,#5682,.F.);\r\n#7788=EDGE_LOOP('',(#7784,#7785,#7786,#7787));\r\n#7789=FACE_OUTER_BOUND('',#7788,.F.);\r\n#7790=ADVANCED_FACE('',(#7789),#7783,.T.);\r\n#7791=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0));\r\n#7792=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7793=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7794=AXIS2_PLACEMENT_3D('',#7791,#7792,#7793);\r\n#7795=CYLINDRICAL_SURFACE('',#7794,9.5E-2);\r\n#7796=ORIENTED_EDGE('',*,*,#7140,.F.);\r\n#7798=ORIENTED_EDGE('',*,*,#7797,.T.);\r\n#7800=ORIENTED_EDGE('',*,*,#7799,.T.);\r\n#7802=ORIENTED_EDGE('',*,*,#7801,.F.);\r\n#7803=EDGE_LOOP('',(#7796,#7798,#7800,#7802));\r\n#7804=FACE_OUTER_BOUND('',#7803,.F.);\r\n#7805=ADVANCED_FACE('',(#7804),#7795,.F.);\r\n#7806=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0));\r\n#7807=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7808=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7809=AXIS2_PLACEMENT_3D('',#7806,#7807,#7808);\r\n#7810=CYLINDRICAL_SURFACE('',#7809,9.5E-2);\r\n#7811=ORIENTED_EDGE('',*,*,#7142,.F.);\r\n#7812=ORIENTED_EDGE('',*,*,#7801,.T.);\r\n#7814=ORIENTED_EDGE('',*,*,#7813,.T.);\r\n#7815=ORIENTED_EDGE('',*,*,#7797,.F.);\r\n#7816=EDGE_LOOP('',(#7811,#7812,#7814,#7815));\r\n#7817=FACE_OUTER_BOUND('',#7816,.F.);\r\n#7818=ADVANCED_FACE('',(#7817),#7810,.F.);\r\n#7819=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0));\r\n#7820=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7821=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7822=AXIS2_PLACEMENT_3D('',#7819,#7820,#7821);\r\n#7823=PLANE('',#7822);\r\n#7824=ORIENTED_EDGE('',*,*,#7799,.F.);\r\n#7825=ORIENTED_EDGE('',*,*,#7813,.F.);\r\n#7826=EDGE_LOOP('',(#7824,#7825));\r\n#7827=FACE_OUTER_BOUND('',#7826,.F.);\r\n#7828=ADVANCED_FACE('',(#7827),#7823,.T.);\r\n#7829=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0));\r\n#7830=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7831=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7832=AXIS2_PLACEMENT_3D('',#7829,#7830,#7831);\r\n#7833=CYLINDRICAL_SURFACE('',#7832,6.25E-2);\r\n#7834=ORIENTED_EDGE('',*,*,#7146,.F.);\r\n#7836=ORIENTED_EDGE('',*,*,#7835,.T.);\r\n#7838=ORIENTED_EDGE('',*,*,#7837,.T.);\r\n#7840=ORIENTED_EDGE('',*,*,#7839,.F.);\r\n#7841=EDGE_LOOP('',(#7834,#7836,#7838,#7840));\r\n#7842=FACE_OUTER_BOUND('',#7841,.F.);\r\n#7843=ADVANCED_FACE('',(#7842),#7833,.F.);\r\n#7844=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0));\r\n#7845=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7846=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7847=AXIS2_PLACEMENT_3D('',#7844,#7845,#7846);\r\n#7848=CYLINDRICAL_SURFACE('',#7847,6.25E-2);\r\n#7849=ORIENTED_EDGE('',*,*,#7148,.F.);\r\n#7850=ORIENTED_EDGE('',*,*,#7839,.T.);\r\n#7852=ORIENTED_EDGE('',*,*,#7851,.T.);\r\n#7853=ORIENTED_EDGE('',*,*,#7835,.F.);\r\n#7854=EDGE_LOOP('',(#7849,#7850,#7852,#7853));\r\n#7855=FACE_OUTER_BOUND('',#7854,.F.);\r\n#7856=ADVANCED_FACE('',(#7855),#7848,.F.);\r\n#7857=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0));\r\n#7858=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7859=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7860=AXIS2_PLACEMENT_3D('',#7857,#7858,#7859);\r\n#7861=PLANE('',#7860);\r\n#7862=ORIENTED_EDGE('',*,*,#7837,.F.);\r\n#7863=ORIENTED_EDGE('',*,*,#7851,.F.);\r\n#7864=EDGE_LOOP('',(#7862,#7863));\r\n#7865=FACE_OUTER_BOUND('',#7864,.F.);\r\n#7866=ADVANCED_FACE('',(#7865),#7861,.T.);\r\n#7867=CARTESIAN_POINT('',(1.755E1,1.176878221735E0,2.975E1));\r\n#7868=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7869=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7870=AXIS2_PLACEMENT_3D('',#7867,#7868,#7869);\r\n#7871=CYLINDRICAL_SURFACE('',#7870,1.E-1);\r\n#7872=ORIENTED_EDGE('',*,*,#6346,.F.);\r\n#7874=ORIENTED_EDGE('',*,*,#7873,.F.);\r\n#7876=ORIENTED_EDGE('',*,*,#7875,.T.);\r\n#7878=ORIENTED_EDGE('',*,*,#7877,.T.);\r\n#7879=EDGE_LOOP('',(#7872,#7874,#7876,#7878));\r\n#7880=FACE_OUTER_BOUND('',#7879,.F.);\r\n#7881=ADVANCED_FACE('',(#7880),#7871,.F.);\r\n#7882=CARTESIAN_POINT('',(1.755E1,1.176878221735E0,2.975E1));\r\n#7883=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7884=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7885=AXIS2_PLACEMENT_3D('',#7882,#7883,#7884);\r\n#7886=CYLINDRICAL_SURFACE('',#7885,1.E-1);\r\n#7887=ORIENTED_EDGE('',*,*,#6348,.F.);\r\n#7888=ORIENTED_EDGE('',*,*,#7877,.F.);\r\n#7890=ORIENTED_EDGE('',*,*,#7889,.F.);\r\n#7891=ORIENTED_EDGE('',*,*,#7873,.T.);\r\n#7892=EDGE_LOOP('',(#7887,#7888,#7890,#7891));\r\n#7893=FACE_OUTER_BOUND('',#7892,.F.);\r\n#7894=ADVANCED_FACE('',(#7893),#7886,.F.);\r\n#7895=CARTESIAN_POINT('',(1.755E1,1.234346967234E0,2.975E1));\r\n#7896=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7897=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7898=AXIS2_PLACEMENT_3D('',#7895,#7896,#7897);\r\n#7899=CONICAL_SURFACE('',#7898,7.288815195685E-2,6.E1);\r\n#7901=ORIENTED_EDGE('',*,*,#7900,.F.);\r\n#7903=ORIENTED_EDGE('',*,*,#7902,.T.);\r\n#7904=ORIENTED_EDGE('',*,*,#7889,.T.);\r\n#7905=EDGE_LOOP('',(#7901,#7903,#7904));\r\n#7906=FACE_OUTER_BOUND('',#7905,.F.);\r\n#7907=ADVANCED_FACE('',(#7906),#7899,.F.);\r\n#7908=CARTESIAN_POINT('',(1.755E1,1.234346967234E0,2.975E1));\r\n#7909=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7910=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7911=AXIS2_PLACEMENT_3D('',#7908,#7909,#7910);\r\n#7912=CONICAL_SURFACE('',#7911,7.288815195685E-2,6.E1);\r\n#7913=ORIENTED_EDGE('',*,*,#7900,.T.);\r\n#7914=ORIENTED_EDGE('',*,*,#7875,.F.);\r\n#7915=ORIENTED_EDGE('',*,*,#7902,.F.);\r\n#7916=EDGE_LOOP('',(#7913,#7914,#7915));\r\n#7917=FACE_OUTER_BOUND('',#7916,.F.);\r\n#7918=ADVANCED_FACE('',(#7917),#7912,.F.);\r\n#7919=CARTESIAN_POINT('',(1.655E1,1.176878221735E0,2.975E1));\r\n#7920=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7921=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7922=AXIS2_PLACEMENT_3D('',#7919,#7920,#7921);\r\n#7923=CYLINDRICAL_SURFACE('',#7922,1.E-1);\r\n#7924=ORIENTED_EDGE('',*,*,#6352,.F.);\r\n#7926=ORIENTED_EDGE('',*,*,#7925,.F.);\r\n#7928=ORIENTED_EDGE('',*,*,#7927,.T.);\r\n#7930=ORIENTED_EDGE('',*,*,#7929,.T.);\r\n#7931=EDGE_LOOP('',(#7924,#7926,#7928,#7930));\r\n#7932=FACE_OUTER_BOUND('',#7931,.F.);\r\n#7933=ADVANCED_FACE('',(#7932),#7923,.F.);\r\n#7934=CARTESIAN_POINT('',(1.655E1,1.176878221735E0,2.975E1));\r\n#7935=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7936=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7937=AXIS2_PLACEMENT_3D('',#7934,#7935,#7936);\r\n#7938=CYLINDRICAL_SURFACE('',#7937,1.E-1);\r\n#7939=ORIENTED_EDGE('',*,*,#6354,.F.);\r\n#7940=ORIENTED_EDGE('',*,*,#7929,.F.);\r\n#7942=ORIENTED_EDGE('',*,*,#7941,.F.);\r\n#7943=ORIENTED_EDGE('',*,*,#7925,.T.);\r\n#7944=EDGE_LOOP('',(#7939,#7940,#7942,#7943));\r\n#7945=FACE_OUTER_BOUND('',#7944,.F.);\r\n#7946=ADVANCED_FACE('',(#7945),#7938,.F.);\r\n#7947=CARTESIAN_POINT('',(1.655E1,1.234346967234E0,2.975E1));\r\n#7948=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7949=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7950=AXIS2_PLACEMENT_3D('',#7947,#7948,#7949);\r\n#7951=CONICAL_SURFACE('',#7950,7.288815195685E-2,6.E1);\r\n#7953=ORIENTED_EDGE('',*,*,#7952,.F.);\r\n#7955=ORIENTED_EDGE('',*,*,#7954,.T.);\r\n#7956=ORIENTED_EDGE('',*,*,#7941,.T.);\r\n#7957=EDGE_LOOP('',(#7953,#7955,#7956));\r\n#7958=FACE_OUTER_BOUND('',#7957,.F.);\r\n#7959=ADVANCED_FACE('',(#7958),#7951,.F.);\r\n#7960=CARTESIAN_POINT('',(1.655E1,1.234346967234E0,2.975E1));\r\n#7961=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#7962=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#7963=AXIS2_PLACEMENT_3D('',#7960,#7961,#7962);\r\n#7964=CONICAL_SURFACE('',#7963,7.288815195685E-2,6.E1);\r\n#7965=ORIENTED_EDGE('',*,*,#7952,.T.);\r\n#7966=ORIENTED_EDGE('',*,*,#7927,.F.);\r\n#7967=ORIENTED_EDGE('',*,*,#7954,.F.);\r\n#7968=EDGE_LOOP('',(#7965,#7966,#7967));\r\n#7969=FACE_OUTER_BOUND('',#7968,.F.);\r\n#7970=ADVANCED_FACE('',(#7969),#7964,.F.);\r\n#7971=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#7972=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7973=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7974=AXIS2_PLACEMENT_3D('',#7971,#7972,#7973);\r\n#7975=CYLINDRICAL_SURFACE('',#7974,2.575E-1);\r\n#7976=ORIENTED_EDGE('',*,*,#6248,.T.);\r\n#7978=ORIENTED_EDGE('',*,*,#7977,.T.);\r\n#7980=ORIENTED_EDGE('',*,*,#7979,.F.);\r\n#7982=ORIENTED_EDGE('',*,*,#7981,.F.);\r\n#7983=EDGE_LOOP('',(#7976,#7978,#7980,#7982));\r\n#7984=FACE_OUTER_BOUND('',#7983,.F.);\r\n#7985=ADVANCED_FACE('',(#7984),#7975,.F.);\r\n#7986=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#7987=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#7988=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#7989=AXIS2_PLACEMENT_3D('',#7986,#7987,#7988);\r\n#7990=CYLINDRICAL_SURFACE('',#7989,2.575E-1);\r\n#7991=ORIENTED_EDGE('',*,*,#6250,.T.);\r\n#7992=ORIENTED_EDGE('',*,*,#7981,.T.);\r\n#7994=ORIENTED_EDGE('',*,*,#7993,.F.);\r\n#7995=ORIENTED_EDGE('',*,*,#7977,.F.);\r\n#7996=EDGE_LOOP('',(#7991,#7992,#7994,#7995));\r\n#7997=FACE_OUTER_BOUND('',#7996,.F.);\r\n#7998=ADVANCED_FACE('',(#7997),#7990,.F.);\r\n#7999=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0));\r\n#8000=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8001=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8002=AXIS2_PLACEMENT_3D('',#7999,#8000,#8001);\r\n#8003=PLANE('',#8002);\r\n#8004=ORIENTED_EDGE('',*,*,#7979,.T.);\r\n#8005=ORIENTED_EDGE('',*,*,#7993,.T.);\r\n#8006=EDGE_LOOP('',(#8004,#8005));\r\n#8007=FACE_OUTER_BOUND('',#8006,.F.);\r\n#8009=ORIENTED_EDGE('',*,*,#8008,.F.);\r\n#8011=ORIENTED_EDGE('',*,*,#8010,.F.);\r\n#8012=EDGE_LOOP('',(#8009,#8011));\r\n#8013=FACE_BOUND('',#8012,.F.);\r\n#8014=ADVANCED_FACE('',(#8007,#8013),#8003,.F.);\r\n#8015=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#8016=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8017=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8018=AXIS2_PLACEMENT_3D('',#8015,#8016,#8017);\r\n#8019=CYLINDRICAL_SURFACE('',#8018,1.925E-1);\r\n#8020=ORIENTED_EDGE('',*,*,#8008,.T.);\r\n#8022=ORIENTED_EDGE('',*,*,#8021,.T.);\r\n#8023=ORIENTED_EDGE('',*,*,#5626,.F.);\r\n#8025=ORIENTED_EDGE('',*,*,#8024,.F.);\r\n#8026=EDGE_LOOP('',(#8020,#8022,#8023,#8025));\r\n#8027=FACE_OUTER_BOUND('',#8026,.F.);\r\n#8028=ADVANCED_FACE('',(#8027),#8019,.F.);\r\n#8029=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0));\r\n#8030=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8031=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8032=AXIS2_PLACEMENT_3D('',#8029,#8030,#8031);\r\n#8033=CYLINDRICAL_SURFACE('',#8032,1.925E-1);\r\n#8034=ORIENTED_EDGE('',*,*,#8010,.T.);\r\n#8035=ORIENTED_EDGE('',*,*,#8024,.T.);\r\n#8036=ORIENTED_EDGE('',*,*,#5628,.F.);\r\n#8037=ORIENTED_EDGE('',*,*,#8021,.F.);\r\n#8038=EDGE_LOOP('',(#8034,#8035,#8036,#8037));\r\n#8039=FACE_OUTER_BOUND('',#8038,.F.);\r\n#8040=ADVANCED_FACE('',(#8039),#8033,.F.);\r\n#8041=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#8042=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8043=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8044=AXIS2_PLACEMENT_3D('',#8041,#8042,#8043);\r\n#8045=CYLINDRICAL_SURFACE('',#8044,2.575E-1);\r\n#8046=ORIENTED_EDGE('',*,*,#6358,.T.);\r\n#8048=ORIENTED_EDGE('',*,*,#8047,.T.);\r\n#8050=ORIENTED_EDGE('',*,*,#8049,.F.);\r\n#8052=ORIENTED_EDGE('',*,*,#8051,.F.);\r\n#8053=EDGE_LOOP('',(#8046,#8048,#8050,#8052));\r\n#8054=FACE_OUTER_BOUND('',#8053,.F.);\r\n#8055=ADVANCED_FACE('',(#8054),#8045,.F.);\r\n#8056=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#8057=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8058=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8059=AXIS2_PLACEMENT_3D('',#8056,#8057,#8058);\r\n#8060=CYLINDRICAL_SURFACE('',#8059,2.575E-1);\r\n#8061=ORIENTED_EDGE('',*,*,#6360,.T.);\r\n#8062=ORIENTED_EDGE('',*,*,#8051,.T.);\r\n#8064=ORIENTED_EDGE('',*,*,#8063,.F.);\r\n#8065=ORIENTED_EDGE('',*,*,#8047,.F.);\r\n#8066=EDGE_LOOP('',(#8061,#8062,#8064,#8065));\r\n#8067=FACE_OUTER_BOUND('',#8066,.F.);\r\n#8068=ADVANCED_FACE('',(#8067),#8060,.F.);\r\n#8069=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1));\r\n#8070=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8071=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8072=AXIS2_PLACEMENT_3D('',#8069,#8070,#8071);\r\n#8073=PLANE('',#8072);\r\n#8074=ORIENTED_EDGE('',*,*,#8049,.T.);\r\n#8075=ORIENTED_EDGE('',*,*,#8063,.T.);\r\n#8076=EDGE_LOOP('',(#8074,#8075));\r\n#8077=FACE_OUTER_BOUND('',#8076,.F.);\r\n#8079=ORIENTED_EDGE('',*,*,#8078,.F.);\r\n#8081=ORIENTED_EDGE('',*,*,#8080,.F.);\r\n#8082=EDGE_LOOP('',(#8079,#8081));\r\n#8083=FACE_BOUND('',#8082,.F.);\r\n#8084=ADVANCED_FACE('',(#8077,#8083),#8073,.F.);\r\n#8085=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#8086=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8087=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8088=AXIS2_PLACEMENT_3D('',#8085,#8086,#8087);\r\n#8089=CYLINDRICAL_SURFACE('',#8088,1.925E-1);\r\n#8090=ORIENTED_EDGE('',*,*,#8078,.T.);\r\n#8092=ORIENTED_EDGE('',*,*,#8091,.T.);\r\n#8093=ORIENTED_EDGE('',*,*,#5614,.F.);\r\n#8095=ORIENTED_EDGE('',*,*,#8094,.F.);\r\n#8096=EDGE_LOOP('',(#8090,#8092,#8093,#8095));\r\n#8097=FACE_OUTER_BOUND('',#8096,.F.);\r\n#8098=ADVANCED_FACE('',(#8097),#8089,.F.);\r\n#8099=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1));\r\n#8100=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8101=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8102=AXIS2_PLACEMENT_3D('',#8099,#8100,#8101);\r\n#8103=CYLINDRICAL_SURFACE('',#8102,1.925E-1);\r\n#8104=ORIENTED_EDGE('',*,*,#8080,.T.);\r\n#8105=ORIENTED_EDGE('',*,*,#8094,.T.);\r\n#8106=ORIENTED_EDGE('',*,*,#5616,.F.);\r\n#8107=ORIENTED_EDGE('',*,*,#8091,.F.);\r\n#8108=EDGE_LOOP('',(#8104,#8105,#8106,#8107));\r\n#8109=FACE_OUTER_BOUND('',#8108,.F.);\r\n#8110=ADVANCED_FACE('',(#8109),#8103,.F.);\r\n#8111=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#8112=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8113=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8114=AXIS2_PLACEMENT_3D('',#8111,#8112,#8113);\r\n#8115=CYLINDRICAL_SURFACE('',#8114,2.575E-1);\r\n#8116=ORIENTED_EDGE('',*,*,#6364,.T.);\r\n#8118=ORIENTED_EDGE('',*,*,#8117,.T.);\r\n#8120=ORIENTED_EDGE('',*,*,#8119,.F.);\r\n#8122=ORIENTED_EDGE('',*,*,#8121,.F.);\r\n#8123=EDGE_LOOP('',(#8116,#8118,#8120,#8122));\r\n#8124=FACE_OUTER_BOUND('',#8123,.F.);\r\n#8125=ADVANCED_FACE('',(#8124),#8115,.F.);\r\n#8126=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#8127=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8128=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8129=AXIS2_PLACEMENT_3D('',#8126,#8127,#8128);\r\n#8130=CYLINDRICAL_SURFACE('',#8129,2.575E-1);\r\n#8131=ORIENTED_EDGE('',*,*,#6366,.T.);\r\n#8132=ORIENTED_EDGE('',*,*,#8121,.T.);\r\n#8134=ORIENTED_EDGE('',*,*,#8133,.F.);\r\n#8135=ORIENTED_EDGE('',*,*,#8117,.F.);\r\n#8136=EDGE_LOOP('',(#8131,#8132,#8134,#8135));\r\n#8137=FACE_OUTER_BOUND('',#8136,.F.);\r\n#8138=ADVANCED_FACE('',(#8137),#8130,.F.);\r\n#8139=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1));\r\n#8140=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8141=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8142=AXIS2_PLACEMENT_3D('',#8139,#8140,#8141);\r\n#8143=PLANE('',#8142);\r\n#8144=ORIENTED_EDGE('',*,*,#8119,.T.);\r\n#8145=ORIENTED_EDGE('',*,*,#8133,.T.);\r\n#8146=EDGE_LOOP('',(#8144,#8145));\r\n#8147=FACE_OUTER_BOUND('',#8146,.F.);\r\n#8149=ORIENTED_EDGE('',*,*,#8148,.F.);\r\n#8151=ORIENTED_EDGE('',*,*,#8150,.F.);\r\n#8152=EDGE_LOOP('',(#8149,#8151));\r\n#8153=FACE_BOUND('',#8152,.F.);\r\n#8154=ADVANCED_FACE('',(#8147,#8153),#8143,.F.);\r\n#8155=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#8156=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8157=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8158=AXIS2_PLACEMENT_3D('',#8155,#8156,#8157);\r\n#8159=CYLINDRICAL_SURFACE('',#8158,1.925E-1);\r\n#8160=ORIENTED_EDGE('',*,*,#8148,.T.);\r\n#8162=ORIENTED_EDGE('',*,*,#8161,.T.);\r\n#8163=ORIENTED_EDGE('',*,*,#5608,.F.);\r\n#8165=ORIENTED_EDGE('',*,*,#8164,.F.);\r\n#8166=EDGE_LOOP('',(#8160,#8162,#8163,#8165));\r\n#8167=FACE_OUTER_BOUND('',#8166,.F.);\r\n#8168=ADVANCED_FACE('',(#8167),#8159,.F.);\r\n#8169=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1));\r\n#8170=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8171=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8172=AXIS2_PLACEMENT_3D('',#8169,#8170,#8171);\r\n#8173=CYLINDRICAL_SURFACE('',#8172,1.925E-1);\r\n#8174=ORIENTED_EDGE('',*,*,#8150,.T.);\r\n#8175=ORIENTED_EDGE('',*,*,#8164,.T.);\r\n#8176=ORIENTED_EDGE('',*,*,#5610,.F.);\r\n#8177=ORIENTED_EDGE('',*,*,#8161,.F.);\r\n#8178=EDGE_LOOP('',(#8174,#8175,#8176,#8177));\r\n#8179=FACE_OUTER_BOUND('',#8178,.F.);\r\n#8180=ADVANCED_FACE('',(#8179),#8173,.F.);\r\n#8181=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#8182=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8183=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8184=AXIS2_PLACEMENT_3D('',#8181,#8182,#8183);\r\n#8185=CYLINDRICAL_SURFACE('',#8184,2.575E-1);\r\n#8186=ORIENTED_EDGE('',*,*,#6254,.T.);\r\n#8188=ORIENTED_EDGE('',*,*,#8187,.T.);\r\n#8190=ORIENTED_EDGE('',*,*,#8189,.F.);\r\n#8192=ORIENTED_EDGE('',*,*,#8191,.F.);\r\n#8193=EDGE_LOOP('',(#8186,#8188,#8190,#8192));\r\n#8194=FACE_OUTER_BOUND('',#8193,.F.);\r\n#8195=ADVANCED_FACE('',(#8194),#8185,.F.);\r\n#8196=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#8197=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8198=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8199=AXIS2_PLACEMENT_3D('',#8196,#8197,#8198);\r\n#8200=CYLINDRICAL_SURFACE('',#8199,2.575E-1);\r\n#8201=ORIENTED_EDGE('',*,*,#6256,.T.);\r\n#8202=ORIENTED_EDGE('',*,*,#8191,.T.);\r\n#8204=ORIENTED_EDGE('',*,*,#8203,.F.);\r\n#8205=ORIENTED_EDGE('',*,*,#8187,.F.);\r\n#8206=EDGE_LOOP('',(#8201,#8202,#8204,#8205));\r\n#8207=FACE_OUTER_BOUND('',#8206,.F.);\r\n#8208=ADVANCED_FACE('',(#8207),#8200,.F.);\r\n#8209=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0));\r\n#8210=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8211=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8212=AXIS2_PLACEMENT_3D('',#8209,#8210,#8211);\r\n#8213=PLANE('',#8212);\r\n#8214=ORIENTED_EDGE('',*,*,#8189,.T.);\r\n#8215=ORIENTED_EDGE('',*,*,#8203,.T.);\r\n#8216=EDGE_LOOP('',(#8214,#8215));\r\n#8217=FACE_OUTER_BOUND('',#8216,.F.);\r\n#8219=ORIENTED_EDGE('',*,*,#8218,.F.);\r\n#8221=ORIENTED_EDGE('',*,*,#8220,.F.);\r\n#8222=EDGE_LOOP('',(#8219,#8221));\r\n#8223=FACE_BOUND('',#8222,.F.);\r\n#8224=ADVANCED_FACE('',(#8217,#8223),#8213,.F.);\r\n#8225=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#8226=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8227=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8228=AXIS2_PLACEMENT_3D('',#8225,#8226,#8227);\r\n#8229=CYLINDRICAL_SURFACE('',#8228,1.925E-1);\r\n#8230=ORIENTED_EDGE('',*,*,#8218,.T.);\r\n#8232=ORIENTED_EDGE('',*,*,#8231,.T.);\r\n#8233=ORIENTED_EDGE('',*,*,#5602,.F.);\r\n#8235=ORIENTED_EDGE('',*,*,#8234,.F.);\r\n#8236=EDGE_LOOP('',(#8230,#8232,#8233,#8235));\r\n#8237=FACE_OUTER_BOUND('',#8236,.F.);\r\n#8238=ADVANCED_FACE('',(#8237),#8229,.F.);\r\n#8239=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0));\r\n#8240=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8241=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8242=AXIS2_PLACEMENT_3D('',#8239,#8240,#8241);\r\n#8243=CYLINDRICAL_SURFACE('',#8242,1.925E-1);\r\n#8244=ORIENTED_EDGE('',*,*,#8220,.T.);\r\n#8245=ORIENTED_EDGE('',*,*,#8234,.T.);\r\n#8246=ORIENTED_EDGE('',*,*,#5604,.F.);\r\n#8247=ORIENTED_EDGE('',*,*,#8231,.F.);\r\n#8248=EDGE_LOOP('',(#8244,#8245,#8246,#8247));\r\n#8249=FACE_OUTER_BOUND('',#8248,.F.);\r\n#8250=ADVANCED_FACE('',(#8249),#8243,.F.);\r\n#8251=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#8252=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8253=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8254=AXIS2_PLACEMENT_3D('',#8251,#8252,#8253);\r\n#8255=CYLINDRICAL_SURFACE('',#8254,2.575E-1);\r\n#8256=ORIENTED_EDGE('',*,*,#6370,.T.);\r\n#8258=ORIENTED_EDGE('',*,*,#8257,.T.);\r\n#8260=ORIENTED_EDGE('',*,*,#8259,.F.);\r\n#8262=ORIENTED_EDGE('',*,*,#8261,.F.);\r\n#8263=EDGE_LOOP('',(#8256,#8258,#8260,#8262));\r\n#8264=FACE_OUTER_BOUND('',#8263,.F.);\r\n#8265=ADVANCED_FACE('',(#8264),#8255,.F.);\r\n#8266=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#8267=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8268=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8269=AXIS2_PLACEMENT_3D('',#8266,#8267,#8268);\r\n#8270=CYLINDRICAL_SURFACE('',#8269,2.575E-1);\r\n#8271=ORIENTED_EDGE('',*,*,#6372,.T.);\r\n#8272=ORIENTED_EDGE('',*,*,#8261,.T.);\r\n#8274=ORIENTED_EDGE('',*,*,#8273,.F.);\r\n#8275=ORIENTED_EDGE('',*,*,#8257,.F.);\r\n#8276=EDGE_LOOP('',(#8271,#8272,#8274,#8275));\r\n#8277=FACE_OUTER_BOUND('',#8276,.F.);\r\n#8278=ADVANCED_FACE('',(#8277),#8270,.F.);\r\n#8279=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1));\r\n#8280=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8281=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8282=AXIS2_PLACEMENT_3D('',#8279,#8280,#8281);\r\n#8283=PLANE('',#8282);\r\n#8284=ORIENTED_EDGE('',*,*,#8259,.T.);\r\n#8285=ORIENTED_EDGE('',*,*,#8273,.T.);\r\n#8286=EDGE_LOOP('',(#8284,#8285));\r\n#8287=FACE_OUTER_BOUND('',#8286,.F.);\r\n#8289=ORIENTED_EDGE('',*,*,#8288,.F.);\r\n#8291=ORIENTED_EDGE('',*,*,#8290,.F.);\r\n#8292=EDGE_LOOP('',(#8289,#8291));\r\n#8293=FACE_BOUND('',#8292,.F.);\r\n#8294=ADVANCED_FACE('',(#8287,#8293),#8283,.F.);\r\n#8295=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#8296=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8297=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8298=AXIS2_PLACEMENT_3D('',#8295,#8296,#8297);\r\n#8299=CYLINDRICAL_SURFACE('',#8298,1.925E-1);\r\n#8300=ORIENTED_EDGE('',*,*,#8288,.T.);\r\n#8302=ORIENTED_EDGE('',*,*,#8301,.T.);\r\n#8303=ORIENTED_EDGE('',*,*,#5590,.F.);\r\n#8305=ORIENTED_EDGE('',*,*,#8304,.F.);\r\n#8306=EDGE_LOOP('',(#8300,#8302,#8303,#8305));\r\n#8307=FACE_OUTER_BOUND('',#8306,.F.);\r\n#8308=ADVANCED_FACE('',(#8307),#8299,.F.);\r\n#8309=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1));\r\n#8310=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8311=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8312=AXIS2_PLACEMENT_3D('',#8309,#8310,#8311);\r\n#8313=CYLINDRICAL_SURFACE('',#8312,1.925E-1);\r\n#8314=ORIENTED_EDGE('',*,*,#8290,.T.);\r\n#8315=ORIENTED_EDGE('',*,*,#8304,.T.);\r\n#8316=ORIENTED_EDGE('',*,*,#5592,.F.);\r\n#8317=ORIENTED_EDGE('',*,*,#8301,.F.);\r\n#8318=EDGE_LOOP('',(#8314,#8315,#8316,#8317));\r\n#8319=FACE_OUTER_BOUND('',#8318,.F.);\r\n#8320=ADVANCED_FACE('',(#8319),#8313,.F.);\r\n#8321=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#8322=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8323=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8324=AXIS2_PLACEMENT_3D('',#8321,#8322,#8323);\r\n#8325=CYLINDRICAL_SURFACE('',#8324,2.575E-1);\r\n#8326=ORIENTED_EDGE('',*,*,#6376,.T.);\r\n#8328=ORIENTED_EDGE('',*,*,#8327,.T.);\r\n#8330=ORIENTED_EDGE('',*,*,#8329,.F.);\r\n#8332=ORIENTED_EDGE('',*,*,#8331,.F.);\r\n#8333=EDGE_LOOP('',(#8326,#8328,#8330,#8332));\r\n#8334=FACE_OUTER_BOUND('',#8333,.F.);\r\n#8335=ADVANCED_FACE('',(#8334),#8325,.F.);\r\n#8336=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#8337=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8338=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8339=AXIS2_PLACEMENT_3D('',#8336,#8337,#8338);\r\n#8340=CYLINDRICAL_SURFACE('',#8339,2.575E-1);\r\n#8341=ORIENTED_EDGE('',*,*,#6378,.T.);\r\n#8342=ORIENTED_EDGE('',*,*,#8331,.T.);\r\n#8344=ORIENTED_EDGE('',*,*,#8343,.F.);\r\n#8345=ORIENTED_EDGE('',*,*,#8327,.F.);\r\n#8346=EDGE_LOOP('',(#8341,#8342,#8344,#8345));\r\n#8347=FACE_OUTER_BOUND('',#8346,.F.);\r\n#8348=ADVANCED_FACE('',(#8347),#8340,.F.);\r\n#8349=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1));\r\n#8350=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8351=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8352=AXIS2_PLACEMENT_3D('',#8349,#8350,#8351);\r\n#8353=PLANE('',#8352);\r\n#8354=ORIENTED_EDGE('',*,*,#8329,.T.);\r\n#8355=ORIENTED_EDGE('',*,*,#8343,.T.);\r\n#8356=EDGE_LOOP('',(#8354,#8355));\r\n#8357=FACE_OUTER_BOUND('',#8356,.F.);\r\n#8359=ORIENTED_EDGE('',*,*,#8358,.F.);\r\n#8361=ORIENTED_EDGE('',*,*,#8360,.F.);\r\n#8362=EDGE_LOOP('',(#8359,#8361));\r\n#8363=FACE_BOUND('',#8362,.F.);\r\n#8364=ADVANCED_FACE('',(#8357,#8363),#8353,.F.);\r\n#8365=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#8366=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8367=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8368=AXIS2_PLACEMENT_3D('',#8365,#8366,#8367);\r\n#8369=CYLINDRICAL_SURFACE('',#8368,1.925E-1);\r\n#8370=ORIENTED_EDGE('',*,*,#8358,.T.);\r\n#8372=ORIENTED_EDGE('',*,*,#8371,.T.);\r\n#8373=ORIENTED_EDGE('',*,*,#5584,.F.);\r\n#8375=ORIENTED_EDGE('',*,*,#8374,.F.);\r\n#8376=EDGE_LOOP('',(#8370,#8372,#8373,#8375));\r\n#8377=FACE_OUTER_BOUND('',#8376,.F.);\r\n#8378=ADVANCED_FACE('',(#8377),#8369,.F.);\r\n#8379=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1));\r\n#8380=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8381=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8382=AXIS2_PLACEMENT_3D('',#8379,#8380,#8381);\r\n#8383=CYLINDRICAL_SURFACE('',#8382,1.925E-1);\r\n#8384=ORIENTED_EDGE('',*,*,#8360,.T.);\r\n#8385=ORIENTED_EDGE('',*,*,#8374,.T.);\r\n#8386=ORIENTED_EDGE('',*,*,#5586,.F.);\r\n#8387=ORIENTED_EDGE('',*,*,#8371,.F.);\r\n#8388=EDGE_LOOP('',(#8384,#8385,#8386,#8387));\r\n#8389=FACE_OUTER_BOUND('',#8388,.F.);\r\n#8390=ADVANCED_FACE('',(#8389),#8383,.F.);\r\n#8391=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#8392=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8393=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8394=AXIS2_PLACEMENT_3D('',#8391,#8392,#8393);\r\n#8395=CYLINDRICAL_SURFACE('',#8394,2.56E-1);\r\n#8396=ORIENTED_EDGE('',*,*,#6260,.T.);\r\n#8398=ORIENTED_EDGE('',*,*,#8397,.T.);\r\n#8400=ORIENTED_EDGE('',*,*,#8399,.F.);\r\n#8402=ORIENTED_EDGE('',*,*,#8401,.F.);\r\n#8403=EDGE_LOOP('',(#8396,#8398,#8400,#8402));\r\n#8404=FACE_OUTER_BOUND('',#8403,.F.);\r\n#8405=ADVANCED_FACE('',(#8404),#8395,.F.);\r\n#8406=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#8407=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8408=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8409=AXIS2_PLACEMENT_3D('',#8406,#8407,#8408);\r\n#8410=CYLINDRICAL_SURFACE('',#8409,2.56E-1);\r\n#8411=ORIENTED_EDGE('',*,*,#6262,.T.);\r\n#8412=ORIENTED_EDGE('',*,*,#8401,.T.);\r\n#8414=ORIENTED_EDGE('',*,*,#8413,.F.);\r\n#8415=ORIENTED_EDGE('',*,*,#8397,.F.);\r\n#8416=EDGE_LOOP('',(#8411,#8412,#8414,#8415));\r\n#8417=FACE_OUTER_BOUND('',#8416,.F.);\r\n#8418=ADVANCED_FACE('',(#8417),#8410,.F.);\r\n#8419=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0));\r\n#8420=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8421=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8422=AXIS2_PLACEMENT_3D('',#8419,#8420,#8421);\r\n#8423=PLANE('',#8422);\r\n#8424=ORIENTED_EDGE('',*,*,#8399,.T.);\r\n#8425=ORIENTED_EDGE('',*,*,#8413,.T.);\r\n#8426=EDGE_LOOP('',(#8424,#8425));\r\n#8427=FACE_OUTER_BOUND('',#8426,.F.);\r\n#8429=ORIENTED_EDGE('',*,*,#8428,.F.);\r\n#8431=ORIENTED_EDGE('',*,*,#8430,.F.);\r\n#8432=EDGE_LOOP('',(#8429,#8431));\r\n#8433=FACE_BOUND('',#8432,.F.);\r\n#8434=ADVANCED_FACE('',(#8427,#8433),#8423,.F.);\r\n#8435=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#8436=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8437=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8438=AXIS2_PLACEMENT_3D('',#8435,#8436,#8437);\r\n#8439=CYLINDRICAL_SURFACE('',#8438,1.925E-1);\r\n#8440=ORIENTED_EDGE('',*,*,#8428,.T.);\r\n#8442=ORIENTED_EDGE('',*,*,#8441,.T.);\r\n#8443=ORIENTED_EDGE('',*,*,#5632,.F.);\r\n#8445=ORIENTED_EDGE('',*,*,#8444,.F.);\r\n#8446=EDGE_LOOP('',(#8440,#8442,#8443,#8445));\r\n#8447=FACE_OUTER_BOUND('',#8446,.F.);\r\n#8448=ADVANCED_FACE('',(#8447),#8439,.F.);\r\n#8449=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0));\r\n#8450=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8451=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8452=AXIS2_PLACEMENT_3D('',#8449,#8450,#8451);\r\n#8453=CYLINDRICAL_SURFACE('',#8452,1.925E-1);\r\n#8454=ORIENTED_EDGE('',*,*,#8430,.T.);\r\n#8455=ORIENTED_EDGE('',*,*,#8444,.T.);\r\n#8456=ORIENTED_EDGE('',*,*,#5634,.F.);\r\n#8457=ORIENTED_EDGE('',*,*,#8441,.F.);\r\n#8458=EDGE_LOOP('',(#8454,#8455,#8456,#8457));\r\n#8459=FACE_OUTER_BOUND('',#8458,.F.);\r\n#8460=ADVANCED_FACE('',(#8459),#8453,.F.);\r\n#8461=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#8462=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8463=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8464=AXIS2_PLACEMENT_3D('',#8461,#8462,#8463);\r\n#8465=CYLINDRICAL_SURFACE('',#8464,2.56E-1);\r\n#8466=ORIENTED_EDGE('',*,*,#6266,.T.);\r\n#8468=ORIENTED_EDGE('',*,*,#8467,.T.);\r\n#8470=ORIENTED_EDGE('',*,*,#8469,.F.);\r\n#8472=ORIENTED_EDGE('',*,*,#8471,.F.);\r\n#8473=EDGE_LOOP('',(#8466,#8468,#8470,#8472));\r\n#8474=FACE_OUTER_BOUND('',#8473,.F.);\r\n#8475=ADVANCED_FACE('',(#8474),#8465,.F.);\r\n#8476=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#8477=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8478=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8479=AXIS2_PLACEMENT_3D('',#8476,#8477,#8478);\r\n#8480=CYLINDRICAL_SURFACE('',#8479,2.56E-1);\r\n#8481=ORIENTED_EDGE('',*,*,#6268,.T.);\r\n#8482=ORIENTED_EDGE('',*,*,#8471,.T.);\r\n#8484=ORIENTED_EDGE('',*,*,#8483,.F.);\r\n#8485=ORIENTED_EDGE('',*,*,#8467,.F.);\r\n#8486=EDGE_LOOP('',(#8481,#8482,#8484,#8485));\r\n#8487=FACE_OUTER_BOUND('',#8486,.F.);\r\n#8488=ADVANCED_FACE('',(#8487),#8480,.F.);\r\n#8489=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0));\r\n#8490=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8491=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8492=AXIS2_PLACEMENT_3D('',#8489,#8490,#8491);\r\n#8493=PLANE('',#8492);\r\n#8494=ORIENTED_EDGE('',*,*,#8469,.T.);\r\n#8495=ORIENTED_EDGE('',*,*,#8483,.T.);\r\n#8496=EDGE_LOOP('',(#8494,#8495));\r\n#8497=FACE_OUTER_BOUND('',#8496,.F.);\r\n#8499=ORIENTED_EDGE('',*,*,#8498,.F.);\r\n#8501=ORIENTED_EDGE('',*,*,#8500,.F.);\r\n#8502=EDGE_LOOP('',(#8499,#8501));\r\n#8503=FACE_BOUND('',#8502,.F.);\r\n#8504=ADVANCED_FACE('',(#8497,#8503),#8493,.F.);\r\n#8505=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#8506=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8507=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8508=AXIS2_PLACEMENT_3D('',#8505,#8506,#8507);\r\n#8509=CYLINDRICAL_SURFACE('',#8508,1.925E-1);\r\n#8510=ORIENTED_EDGE('',*,*,#8498,.T.);\r\n#8512=ORIENTED_EDGE('',*,*,#8511,.T.);\r\n#8513=ORIENTED_EDGE('',*,*,#5578,.F.);\r\n#8515=ORIENTED_EDGE('',*,*,#8514,.F.);\r\n#8516=EDGE_LOOP('',(#8510,#8512,#8513,#8515));\r\n#8517=FACE_OUTER_BOUND('',#8516,.F.);\r\n#8518=ADVANCED_FACE('',(#8517),#8509,.F.);\r\n#8519=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0));\r\n#8520=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8521=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8522=AXIS2_PLACEMENT_3D('',#8519,#8520,#8521);\r\n#8523=CYLINDRICAL_SURFACE('',#8522,1.925E-1);\r\n#8524=ORIENTED_EDGE('',*,*,#8500,.T.);\r\n#8525=ORIENTED_EDGE('',*,*,#8514,.T.);\r\n#8526=ORIENTED_EDGE('',*,*,#5580,.F.);\r\n#8527=ORIENTED_EDGE('',*,*,#8511,.F.);\r\n#8528=EDGE_LOOP('',(#8524,#8525,#8526,#8527));\r\n#8529=FACE_OUTER_BOUND('',#8528,.F.);\r\n#8530=ADVANCED_FACE('',(#8529),#8523,.F.);\r\n#8531=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#8532=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8533=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8534=AXIS2_PLACEMENT_3D('',#8531,#8532,#8533);\r\n#8535=CYLINDRICAL_SURFACE('',#8534,2.56E-1);\r\n#8536=ORIENTED_EDGE('',*,*,#6272,.T.);\r\n#8538=ORIENTED_EDGE('',*,*,#8537,.T.);\r\n#8540=ORIENTED_EDGE('',*,*,#8539,.F.);\r\n#8542=ORIENTED_EDGE('',*,*,#8541,.F.);\r\n#8543=EDGE_LOOP('',(#8536,#8538,#8540,#8542));\r\n#8544=FACE_OUTER_BOUND('',#8543,.F.);\r\n#8545=ADVANCED_FACE('',(#8544),#8535,.F.);\r\n#8546=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#8547=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8548=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8549=AXIS2_PLACEMENT_3D('',#8546,#8547,#8548);\r\n#8550=CYLINDRICAL_SURFACE('',#8549,2.56E-1);\r\n#8551=ORIENTED_EDGE('',*,*,#6274,.T.);\r\n#8552=ORIENTED_EDGE('',*,*,#8541,.T.);\r\n#8554=ORIENTED_EDGE('',*,*,#8553,.F.);\r\n#8555=ORIENTED_EDGE('',*,*,#8537,.F.);\r\n#8556=EDGE_LOOP('',(#8551,#8552,#8554,#8555));\r\n#8557=FACE_OUTER_BOUND('',#8556,.F.);\r\n#8558=ADVANCED_FACE('',(#8557),#8550,.F.);\r\n#8559=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0));\r\n#8560=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8561=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8562=AXIS2_PLACEMENT_3D('',#8559,#8560,#8561);\r\n#8563=PLANE('',#8562);\r\n#8564=ORIENTED_EDGE('',*,*,#8539,.T.);\r\n#8565=ORIENTED_EDGE('',*,*,#8553,.T.);\r\n#8566=EDGE_LOOP('',(#8564,#8565));\r\n#8567=FACE_OUTER_BOUND('',#8566,.F.);\r\n#8569=ORIENTED_EDGE('',*,*,#8568,.F.);\r\n#8571=ORIENTED_EDGE('',*,*,#8570,.F.);\r\n#8572=EDGE_LOOP('',(#8569,#8571));\r\n#8573=FACE_BOUND('',#8572,.F.);\r\n#8574=ADVANCED_FACE('',(#8567,#8573),#8563,.F.);\r\n#8575=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#8576=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8577=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8578=AXIS2_PLACEMENT_3D('',#8575,#8576,#8577);\r\n#8579=CYLINDRICAL_SURFACE('',#8578,1.925E-1);\r\n#8580=ORIENTED_EDGE('',*,*,#8568,.T.);\r\n#8582=ORIENTED_EDGE('',*,*,#8581,.T.);\r\n#8583=ORIENTED_EDGE('',*,*,#5560,.F.);\r\n#8585=ORIENTED_EDGE('',*,*,#8584,.F.);\r\n#8586=EDGE_LOOP('',(#8580,#8582,#8583,#8585));\r\n#8587=FACE_OUTER_BOUND('',#8586,.F.);\r\n#8588=ADVANCED_FACE('',(#8587),#8579,.F.);\r\n#8589=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0));\r\n#8590=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8591=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8592=AXIS2_PLACEMENT_3D('',#8589,#8590,#8591);\r\n#8593=CYLINDRICAL_SURFACE('',#8592,1.925E-1);\r\n#8594=ORIENTED_EDGE('',*,*,#8570,.T.);\r\n#8595=ORIENTED_EDGE('',*,*,#8584,.T.);\r\n#8596=ORIENTED_EDGE('',*,*,#5562,.F.);\r\n#8597=ORIENTED_EDGE('',*,*,#8581,.F.);\r\n#8598=EDGE_LOOP('',(#8594,#8595,#8596,#8597));\r\n#8599=FACE_OUTER_BOUND('',#8598,.F.);\r\n#8600=ADVANCED_FACE('',(#8599),#8593,.F.);\r\n#8601=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#8602=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8603=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8604=AXIS2_PLACEMENT_3D('',#8601,#8602,#8603);\r\n#8605=CYLINDRICAL_SURFACE('',#8604,2.56E-1);\r\n#8606=ORIENTED_EDGE('',*,*,#6382,.T.);\r\n#8608=ORIENTED_EDGE('',*,*,#8607,.T.);\r\n#8610=ORIENTED_EDGE('',*,*,#8609,.F.);\r\n#8612=ORIENTED_EDGE('',*,*,#8611,.F.);\r\n#8613=EDGE_LOOP('',(#8606,#8608,#8610,#8612));\r\n#8614=FACE_OUTER_BOUND('',#8613,.F.);\r\n#8615=ADVANCED_FACE('',(#8614),#8605,.F.);\r\n#8616=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#8617=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8618=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8619=AXIS2_PLACEMENT_3D('',#8616,#8617,#8618);\r\n#8620=CYLINDRICAL_SURFACE('',#8619,2.56E-1);\r\n#8621=ORIENTED_EDGE('',*,*,#6384,.T.);\r\n#8622=ORIENTED_EDGE('',*,*,#8611,.T.);\r\n#8624=ORIENTED_EDGE('',*,*,#8623,.F.);\r\n#8625=ORIENTED_EDGE('',*,*,#8607,.F.);\r\n#8626=EDGE_LOOP('',(#8621,#8622,#8624,#8625));\r\n#8627=FACE_OUTER_BOUND('',#8626,.F.);\r\n#8628=ADVANCED_FACE('',(#8627),#8620,.F.);\r\n#8629=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1));\r\n#8630=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8631=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8632=AXIS2_PLACEMENT_3D('',#8629,#8630,#8631);\r\n#8633=PLANE('',#8632);\r\n#8634=ORIENTED_EDGE('',*,*,#8609,.T.);\r\n#8635=ORIENTED_EDGE('',*,*,#8623,.T.);\r\n#8636=EDGE_LOOP('',(#8634,#8635));\r\n#8637=FACE_OUTER_BOUND('',#8636,.F.);\r\n#8639=ORIENTED_EDGE('',*,*,#8638,.F.);\r\n#8641=ORIENTED_EDGE('',*,*,#8640,.F.);\r\n#8642=EDGE_LOOP('',(#8639,#8641));\r\n#8643=FACE_BOUND('',#8642,.F.);\r\n#8644=ADVANCED_FACE('',(#8637,#8643),#8633,.F.);\r\n#8645=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#8646=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8647=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8648=AXIS2_PLACEMENT_3D('',#8645,#8646,#8647);\r\n#8649=CYLINDRICAL_SURFACE('',#8648,1.925E-1);\r\n#8650=ORIENTED_EDGE('',*,*,#8638,.T.);\r\n#8652=ORIENTED_EDGE('',*,*,#8651,.T.);\r\n#8653=ORIENTED_EDGE('',*,*,#5572,.F.);\r\n#8655=ORIENTED_EDGE('',*,*,#8654,.F.);\r\n#8656=EDGE_LOOP('',(#8650,#8652,#8653,#8655));\r\n#8657=FACE_OUTER_BOUND('',#8656,.F.);\r\n#8658=ADVANCED_FACE('',(#8657),#8649,.F.);\r\n#8659=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1));\r\n#8660=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8661=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8662=AXIS2_PLACEMENT_3D('',#8659,#8660,#8661);\r\n#8663=CYLINDRICAL_SURFACE('',#8662,1.925E-1);\r\n#8664=ORIENTED_EDGE('',*,*,#8640,.T.);\r\n#8665=ORIENTED_EDGE('',*,*,#8654,.T.);\r\n#8666=ORIENTED_EDGE('',*,*,#5574,.F.);\r\n#8667=ORIENTED_EDGE('',*,*,#8651,.F.);\r\n#8668=EDGE_LOOP('',(#8664,#8665,#8666,#8667));\r\n#8669=FACE_OUTER_BOUND('',#8668,.F.);\r\n#8670=ADVANCED_FACE('',(#8669),#8663,.F.);\r\n#8671=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#8672=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8673=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8674=AXIS2_PLACEMENT_3D('',#8671,#8672,#8673);\r\n#8675=CYLINDRICAL_SURFACE('',#8674,2.56E-1);\r\n#8676=ORIENTED_EDGE('',*,*,#6388,.T.);\r\n#8678=ORIENTED_EDGE('',*,*,#8677,.T.);\r\n#8680=ORIENTED_EDGE('',*,*,#8679,.F.);\r\n#8682=ORIENTED_EDGE('',*,*,#8681,.F.);\r\n#8683=EDGE_LOOP('',(#8676,#8678,#8680,#8682));\r\n#8684=FACE_OUTER_BOUND('',#8683,.F.);\r\n#8685=ADVANCED_FACE('',(#8684),#8675,.F.);\r\n#8686=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#8687=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8688=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8689=AXIS2_PLACEMENT_3D('',#8686,#8687,#8688);\r\n#8690=CYLINDRICAL_SURFACE('',#8689,2.56E-1);\r\n#8691=ORIENTED_EDGE('',*,*,#6390,.T.);\r\n#8692=ORIENTED_EDGE('',*,*,#8681,.T.);\r\n#8694=ORIENTED_EDGE('',*,*,#8693,.F.);\r\n#8695=ORIENTED_EDGE('',*,*,#8677,.F.);\r\n#8696=EDGE_LOOP('',(#8691,#8692,#8694,#8695));\r\n#8697=FACE_OUTER_BOUND('',#8696,.F.);\r\n#8698=ADVANCED_FACE('',(#8697),#8690,.F.);\r\n#8699=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1));\r\n#8700=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8701=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8702=AXIS2_PLACEMENT_3D('',#8699,#8700,#8701);\r\n#8703=PLANE('',#8702);\r\n#8704=ORIENTED_EDGE('',*,*,#8679,.T.);\r\n#8705=ORIENTED_EDGE('',*,*,#8693,.T.);\r\n#8706=EDGE_LOOP('',(#8704,#8705));\r\n#8707=FACE_OUTER_BOUND('',#8706,.F.);\r\n#8709=ORIENTED_EDGE('',*,*,#8708,.F.);\r\n#8711=ORIENTED_EDGE('',*,*,#8710,.F.);\r\n#8712=EDGE_LOOP('',(#8709,#8711));\r\n#8713=FACE_BOUND('',#8712,.F.);\r\n#8714=ADVANCED_FACE('',(#8707,#8713),#8703,.F.);\r\n#8715=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#8716=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8717=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8718=AXIS2_PLACEMENT_3D('',#8715,#8716,#8717);\r\n#8719=CYLINDRICAL_SURFACE('',#8718,1.925E-1);\r\n#8720=ORIENTED_EDGE('',*,*,#8708,.T.);\r\n#8722=ORIENTED_EDGE('',*,*,#8721,.T.);\r\n#8723=ORIENTED_EDGE('',*,*,#5566,.F.);\r\n#8725=ORIENTED_EDGE('',*,*,#8724,.F.);\r\n#8726=EDGE_LOOP('',(#8720,#8722,#8723,#8725));\r\n#8727=FACE_OUTER_BOUND('',#8726,.F.);\r\n#8728=ADVANCED_FACE('',(#8727),#8719,.F.);\r\n#8729=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1));\r\n#8730=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8731=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8732=AXIS2_PLACEMENT_3D('',#8729,#8730,#8731);\r\n#8733=CYLINDRICAL_SURFACE('',#8732,1.925E-1);\r\n#8734=ORIENTED_EDGE('',*,*,#8710,.T.);\r\n#8735=ORIENTED_EDGE('',*,*,#8724,.T.);\r\n#8736=ORIENTED_EDGE('',*,*,#5568,.F.);\r\n#8737=ORIENTED_EDGE('',*,*,#8721,.F.);\r\n#8738=EDGE_LOOP('',(#8734,#8735,#8736,#8737));\r\n#8739=FACE_OUTER_BOUND('',#8738,.F.);\r\n#8740=ADVANCED_FACE('',(#8739),#8733,.F.);\r\n#8741=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#8742=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8743=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8744=AXIS2_PLACEMENT_3D('',#8741,#8742,#8743);\r\n#8745=CYLINDRICAL_SURFACE('',#8744,2.56E-1);\r\n#8746=ORIENTED_EDGE('',*,*,#6394,.T.);\r\n#8748=ORIENTED_EDGE('',*,*,#8747,.T.);\r\n#8750=ORIENTED_EDGE('',*,*,#8749,.F.);\r\n#8752=ORIENTED_EDGE('',*,*,#8751,.F.);\r\n#8753=EDGE_LOOP('',(#8746,#8748,#8750,#8752));\r\n#8754=FACE_OUTER_BOUND('',#8753,.F.);\r\n#8755=ADVANCED_FACE('',(#8754),#8745,.F.);\r\n#8756=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#8757=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8758=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8759=AXIS2_PLACEMENT_3D('',#8756,#8757,#8758);\r\n#8760=CYLINDRICAL_SURFACE('',#8759,2.56E-1);\r\n#8761=ORIENTED_EDGE('',*,*,#6396,.T.);\r\n#8762=ORIENTED_EDGE('',*,*,#8751,.T.);\r\n#8764=ORIENTED_EDGE('',*,*,#8763,.F.);\r\n#8765=ORIENTED_EDGE('',*,*,#8747,.F.);\r\n#8766=EDGE_LOOP('',(#8761,#8762,#8764,#8765));\r\n#8767=FACE_OUTER_BOUND('',#8766,.F.);\r\n#8768=ADVANCED_FACE('',(#8767),#8760,.F.);\r\n#8769=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1));\r\n#8770=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8771=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8772=AXIS2_PLACEMENT_3D('',#8769,#8770,#8771);\r\n#8773=PLANE('',#8772);\r\n#8774=ORIENTED_EDGE('',*,*,#8749,.T.);\r\n#8775=ORIENTED_EDGE('',*,*,#8763,.T.);\r\n#8776=EDGE_LOOP('',(#8774,#8775));\r\n#8777=FACE_OUTER_BOUND('',#8776,.F.);\r\n#8779=ORIENTED_EDGE('',*,*,#8778,.F.);\r\n#8781=ORIENTED_EDGE('',*,*,#8780,.F.);\r\n#8782=EDGE_LOOP('',(#8779,#8781));\r\n#8783=FACE_BOUND('',#8782,.F.);\r\n#8784=ADVANCED_FACE('',(#8777,#8783),#8773,.F.);\r\n#8785=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#8786=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8787=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8788=AXIS2_PLACEMENT_3D('',#8785,#8786,#8787);\r\n#8789=CYLINDRICAL_SURFACE('',#8788,1.925E-1);\r\n#8790=ORIENTED_EDGE('',*,*,#8778,.T.);\r\n#8792=ORIENTED_EDGE('',*,*,#8791,.T.);\r\n#8793=ORIENTED_EDGE('',*,*,#5554,.F.);\r\n#8795=ORIENTED_EDGE('',*,*,#8794,.F.);\r\n#8796=EDGE_LOOP('',(#8790,#8792,#8793,#8795));\r\n#8797=FACE_OUTER_BOUND('',#8796,.F.);\r\n#8798=ADVANCED_FACE('',(#8797),#8789,.F.);\r\n#8799=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1));\r\n#8800=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8801=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8802=AXIS2_PLACEMENT_3D('',#8799,#8800,#8801);\r\n#8803=CYLINDRICAL_SURFACE('',#8802,1.925E-1);\r\n#8804=ORIENTED_EDGE('',*,*,#8780,.T.);\r\n#8805=ORIENTED_EDGE('',*,*,#8794,.T.);\r\n#8806=ORIENTED_EDGE('',*,*,#5556,.F.);\r\n#8807=ORIENTED_EDGE('',*,*,#8791,.F.);\r\n#8808=EDGE_LOOP('',(#8804,#8805,#8806,#8807));\r\n#8809=FACE_OUTER_BOUND('',#8808,.F.);\r\n#8810=ADVANCED_FACE('',(#8809),#8803,.F.);\r\n#8811=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#8812=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8813=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8814=AXIS2_PLACEMENT_3D('',#8811,#8812,#8813);\r\n#8815=CYLINDRICAL_SURFACE('',#8814,2.575E-1);\r\n#8816=ORIENTED_EDGE('',*,*,#6452,.T.);\r\n#8818=ORIENTED_EDGE('',*,*,#8817,.T.);\r\n#8820=ORIENTED_EDGE('',*,*,#8819,.F.);\r\n#8822=ORIENTED_EDGE('',*,*,#8821,.F.);\r\n#8823=EDGE_LOOP('',(#8816,#8818,#8820,#8822));\r\n#8824=FACE_OUTER_BOUND('',#8823,.F.);\r\n#8825=ADVANCED_FACE('',(#8824),#8815,.F.);\r\n#8826=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#8827=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8828=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8829=AXIS2_PLACEMENT_3D('',#8826,#8827,#8828);\r\n#8830=CYLINDRICAL_SURFACE('',#8829,2.575E-1);\r\n#8831=ORIENTED_EDGE('',*,*,#6454,.T.);\r\n#8832=ORIENTED_EDGE('',*,*,#8821,.T.);\r\n#8834=ORIENTED_EDGE('',*,*,#8833,.F.);\r\n#8835=ORIENTED_EDGE('',*,*,#8817,.F.);\r\n#8836=EDGE_LOOP('',(#8831,#8832,#8834,#8835));\r\n#8837=FACE_OUTER_BOUND('',#8836,.F.);\r\n#8838=ADVANCED_FACE('',(#8837),#8830,.F.);\r\n#8839=CARTESIAN_POINT('',(6.E0,1.E0,9.E0));\r\n#8840=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8841=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8842=AXIS2_PLACEMENT_3D('',#8839,#8840,#8841);\r\n#8843=PLANE('',#8842);\r\n#8844=ORIENTED_EDGE('',*,*,#8819,.T.);\r\n#8845=ORIENTED_EDGE('',*,*,#8833,.T.);\r\n#8846=EDGE_LOOP('',(#8844,#8845));\r\n#8847=FACE_OUTER_BOUND('',#8846,.F.);\r\n#8849=ORIENTED_EDGE('',*,*,#8848,.F.);\r\n#8851=ORIENTED_EDGE('',*,*,#8850,.F.);\r\n#8852=EDGE_LOOP('',(#8849,#8851));\r\n#8853=FACE_BOUND('',#8852,.F.);\r\n#8854=ADVANCED_FACE('',(#8847,#8853),#8843,.F.);\r\n#8855=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#8856=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8857=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8858=AXIS2_PLACEMENT_3D('',#8855,#8856,#8857);\r\n#8859=CYLINDRICAL_SURFACE('',#8858,1.925E-1);\r\n#8860=ORIENTED_EDGE('',*,*,#8848,.T.);\r\n#8862=ORIENTED_EDGE('',*,*,#8861,.T.);\r\n#8863=ORIENTED_EDGE('',*,*,#5690,.F.);\r\n#8865=ORIENTED_EDGE('',*,*,#8864,.F.);\r\n#8866=EDGE_LOOP('',(#8860,#8862,#8863,#8865));\r\n#8867=FACE_OUTER_BOUND('',#8866,.F.);\r\n#8868=ADVANCED_FACE('',(#8867),#8859,.F.);\r\n#8869=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0));\r\n#8870=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8871=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8872=AXIS2_PLACEMENT_3D('',#8869,#8870,#8871);\r\n#8873=CYLINDRICAL_SURFACE('',#8872,1.925E-1);\r\n#8874=ORIENTED_EDGE('',*,*,#8850,.T.);\r\n#8875=ORIENTED_EDGE('',*,*,#8864,.T.);\r\n#8876=ORIENTED_EDGE('',*,*,#5692,.F.);\r\n#8877=ORIENTED_EDGE('',*,*,#8861,.F.);\r\n#8878=EDGE_LOOP('',(#8874,#8875,#8876,#8877));\r\n#8879=FACE_OUTER_BOUND('',#8878,.F.);\r\n#8880=ADVANCED_FACE('',(#8879),#8873,.F.);\r\n#8881=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#8882=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8883=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8884=AXIS2_PLACEMENT_3D('',#8881,#8882,#8883);\r\n#8885=CYLINDRICAL_SURFACE('',#8884,2.575E-1);\r\n#8886=ORIENTED_EDGE('',*,*,#6458,.T.);\r\n#8888=ORIENTED_EDGE('',*,*,#8887,.T.);\r\n#8890=ORIENTED_EDGE('',*,*,#8889,.F.);\r\n#8892=ORIENTED_EDGE('',*,*,#8891,.F.);\r\n#8893=EDGE_LOOP('',(#8886,#8888,#8890,#8892));\r\n#8894=FACE_OUTER_BOUND('',#8893,.F.);\r\n#8895=ADVANCED_FACE('',(#8894),#8885,.F.);\r\n#8896=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#8897=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8898=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8899=AXIS2_PLACEMENT_3D('',#8896,#8897,#8898);\r\n#8900=CYLINDRICAL_SURFACE('',#8899,2.575E-1);\r\n#8901=ORIENTED_EDGE('',*,*,#6460,.T.);\r\n#8902=ORIENTED_EDGE('',*,*,#8891,.T.);\r\n#8904=ORIENTED_EDGE('',*,*,#8903,.F.);\r\n#8905=ORIENTED_EDGE('',*,*,#8887,.F.);\r\n#8906=EDGE_LOOP('',(#8901,#8902,#8904,#8905));\r\n#8907=FACE_OUTER_BOUND('',#8906,.F.);\r\n#8908=ADVANCED_FACE('',(#8907),#8900,.F.);\r\n#8909=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0));\r\n#8910=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8911=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8912=AXIS2_PLACEMENT_3D('',#8909,#8910,#8911);\r\n#8913=PLANE('',#8912);\r\n#8914=ORIENTED_EDGE('',*,*,#8889,.T.);\r\n#8915=ORIENTED_EDGE('',*,*,#8903,.T.);\r\n#8916=EDGE_LOOP('',(#8914,#8915));\r\n#8917=FACE_OUTER_BOUND('',#8916,.F.);\r\n#8919=ORIENTED_EDGE('',*,*,#8918,.F.);\r\n#8921=ORIENTED_EDGE('',*,*,#8920,.F.);\r\n#8922=EDGE_LOOP('',(#8919,#8921));\r\n#8923=FACE_BOUND('',#8922,.F.);\r\n#8924=ADVANCED_FACE('',(#8917,#8923),#8913,.F.);\r\n#8925=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#8926=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8927=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8928=AXIS2_PLACEMENT_3D('',#8925,#8926,#8927);\r\n#8929=CYLINDRICAL_SURFACE('',#8928,1.925E-1);\r\n#8930=ORIENTED_EDGE('',*,*,#8918,.T.);\r\n#8932=ORIENTED_EDGE('',*,*,#8931,.T.);\r\n#8933=ORIENTED_EDGE('',*,*,#5696,.F.);\r\n#8935=ORIENTED_EDGE('',*,*,#8934,.F.);\r\n#8936=EDGE_LOOP('',(#8930,#8932,#8933,#8935));\r\n#8937=FACE_OUTER_BOUND('',#8936,.F.);\r\n#8938=ADVANCED_FACE('',(#8937),#8929,.F.);\r\n#8939=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0));\r\n#8940=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8941=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8942=AXIS2_PLACEMENT_3D('',#8939,#8940,#8941);\r\n#8943=CYLINDRICAL_SURFACE('',#8942,1.925E-1);\r\n#8944=ORIENTED_EDGE('',*,*,#8920,.T.);\r\n#8945=ORIENTED_EDGE('',*,*,#8934,.T.);\r\n#8946=ORIENTED_EDGE('',*,*,#5698,.F.);\r\n#8947=ORIENTED_EDGE('',*,*,#8931,.F.);\r\n#8948=EDGE_LOOP('',(#8944,#8945,#8946,#8947));\r\n#8949=FACE_OUTER_BOUND('',#8948,.F.);\r\n#8950=ADVANCED_FACE('',(#8949),#8943,.F.);\r\n#8951=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#8952=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8953=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8954=AXIS2_PLACEMENT_3D('',#8951,#8952,#8953);\r\n#8955=CYLINDRICAL_SURFACE('',#8954,2.575E-1);\r\n#8956=ORIENTED_EDGE('',*,*,#6464,.T.);\r\n#8958=ORIENTED_EDGE('',*,*,#8957,.T.);\r\n#8960=ORIENTED_EDGE('',*,*,#8959,.F.);\r\n#8962=ORIENTED_EDGE('',*,*,#8961,.F.);\r\n#8963=EDGE_LOOP('',(#8956,#8958,#8960,#8962));\r\n#8964=FACE_OUTER_BOUND('',#8963,.F.);\r\n#8965=ADVANCED_FACE('',(#8964),#8955,.F.);\r\n#8966=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#8967=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8968=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8969=AXIS2_PLACEMENT_3D('',#8966,#8967,#8968);\r\n#8970=CYLINDRICAL_SURFACE('',#8969,2.575E-1);\r\n#8971=ORIENTED_EDGE('',*,*,#6466,.T.);\r\n#8972=ORIENTED_EDGE('',*,*,#8961,.T.);\r\n#8974=ORIENTED_EDGE('',*,*,#8973,.F.);\r\n#8975=ORIENTED_EDGE('',*,*,#8957,.F.);\r\n#8976=EDGE_LOOP('',(#8971,#8972,#8974,#8975));\r\n#8977=FACE_OUTER_BOUND('',#8976,.F.);\r\n#8978=ADVANCED_FACE('',(#8977),#8970,.F.);\r\n#8979=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0));\r\n#8980=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8981=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8982=AXIS2_PLACEMENT_3D('',#8979,#8980,#8981);\r\n#8983=PLANE('',#8982);\r\n#8984=ORIENTED_EDGE('',*,*,#8959,.T.);\r\n#8985=ORIENTED_EDGE('',*,*,#8973,.T.);\r\n#8986=EDGE_LOOP('',(#8984,#8985));\r\n#8987=FACE_OUTER_BOUND('',#8986,.F.);\r\n#8989=ORIENTED_EDGE('',*,*,#8988,.F.);\r\n#8991=ORIENTED_EDGE('',*,*,#8990,.F.);\r\n#8992=EDGE_LOOP('',(#8989,#8991));\r\n#8993=FACE_BOUND('',#8992,.F.);\r\n#8994=ADVANCED_FACE('',(#8987,#8993),#8983,.F.);\r\n#8995=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#8996=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#8997=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#8998=AXIS2_PLACEMENT_3D('',#8995,#8996,#8997);\r\n#8999=CYLINDRICAL_SURFACE('',#8998,1.925E-1);\r\n#9000=ORIENTED_EDGE('',*,*,#8988,.T.);\r\n#9002=ORIENTED_EDGE('',*,*,#9001,.T.);\r\n#9003=ORIENTED_EDGE('',*,*,#5702,.F.);\r\n#9005=ORIENTED_EDGE('',*,*,#9004,.F.);\r\n#9006=EDGE_LOOP('',(#9000,#9002,#9003,#9005));\r\n#9007=FACE_OUTER_BOUND('',#9006,.F.);\r\n#9008=ADVANCED_FACE('',(#9007),#8999,.F.);\r\n#9009=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0));\r\n#9010=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9011=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9012=AXIS2_PLACEMENT_3D('',#9009,#9010,#9011);\r\n#9013=CYLINDRICAL_SURFACE('',#9012,1.925E-1);\r\n#9014=ORIENTED_EDGE('',*,*,#8990,.T.);\r\n#9015=ORIENTED_EDGE('',*,*,#9004,.T.);\r\n#9016=ORIENTED_EDGE('',*,*,#5704,.F.);\r\n#9017=ORIENTED_EDGE('',*,*,#9001,.F.);\r\n#9018=EDGE_LOOP('',(#9014,#9015,#9016,#9017));\r\n#9019=FACE_OUTER_BOUND('',#9018,.F.);\r\n#9020=ADVANCED_FACE('',(#9019),#9013,.F.);\r\n#9021=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#9022=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9023=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9024=AXIS2_PLACEMENT_3D('',#9021,#9022,#9023);\r\n#9025=CYLINDRICAL_SURFACE('',#9024,2.575E-1);\r\n#9026=ORIENTED_EDGE('',*,*,#6470,.T.);\r\n#9028=ORIENTED_EDGE('',*,*,#9027,.T.);\r\n#9030=ORIENTED_EDGE('',*,*,#9029,.F.);\r\n#9032=ORIENTED_EDGE('',*,*,#9031,.F.);\r\n#9033=EDGE_LOOP('',(#9026,#9028,#9030,#9032));\r\n#9034=FACE_OUTER_BOUND('',#9033,.F.);\r\n#9035=ADVANCED_FACE('',(#9034),#9025,.F.);\r\n#9036=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#9037=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9038=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9039=AXIS2_PLACEMENT_3D('',#9036,#9037,#9038);\r\n#9040=CYLINDRICAL_SURFACE('',#9039,2.575E-1);\r\n#9041=ORIENTED_EDGE('',*,*,#6472,.T.);\r\n#9042=ORIENTED_EDGE('',*,*,#9031,.T.);\r\n#9044=ORIENTED_EDGE('',*,*,#9043,.F.);\r\n#9045=ORIENTED_EDGE('',*,*,#9027,.F.);\r\n#9046=EDGE_LOOP('',(#9041,#9042,#9044,#9045));\r\n#9047=FACE_OUTER_BOUND('',#9046,.F.);\r\n#9048=ADVANCED_FACE('',(#9047),#9040,.F.);\r\n#9049=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1));\r\n#9050=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9051=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9052=AXIS2_PLACEMENT_3D('',#9049,#9050,#9051);\r\n#9053=PLANE('',#9052);\r\n#9054=ORIENTED_EDGE('',*,*,#9029,.T.);\r\n#9055=ORIENTED_EDGE('',*,*,#9043,.T.);\r\n#9056=EDGE_LOOP('',(#9054,#9055));\r\n#9057=FACE_OUTER_BOUND('',#9056,.F.);\r\n#9059=ORIENTED_EDGE('',*,*,#9058,.F.);\r\n#9061=ORIENTED_EDGE('',*,*,#9060,.F.);\r\n#9062=EDGE_LOOP('',(#9059,#9061));\r\n#9063=FACE_BOUND('',#9062,.F.);\r\n#9064=ADVANCED_FACE('',(#9057,#9063),#9053,.F.);\r\n#9065=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#9066=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9067=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9068=AXIS2_PLACEMENT_3D('',#9065,#9066,#9067);\r\n#9069=CYLINDRICAL_SURFACE('',#9068,1.925E-1);\r\n#9070=ORIENTED_EDGE('',*,*,#9058,.T.);\r\n#9072=ORIENTED_EDGE('',*,*,#9071,.T.);\r\n#9073=ORIENTED_EDGE('',*,*,#5708,.F.);\r\n#9075=ORIENTED_EDGE('',*,*,#9074,.F.);\r\n#9076=EDGE_LOOP('',(#9070,#9072,#9073,#9075));\r\n#9077=FACE_OUTER_BOUND('',#9076,.F.);\r\n#9078=ADVANCED_FACE('',(#9077),#9069,.F.);\r\n#9079=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1));\r\n#9080=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9081=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9082=AXIS2_PLACEMENT_3D('',#9079,#9080,#9081);\r\n#9083=CYLINDRICAL_SURFACE('',#9082,1.925E-1);\r\n#9084=ORIENTED_EDGE('',*,*,#9060,.T.);\r\n#9085=ORIENTED_EDGE('',*,*,#9074,.T.);\r\n#9086=ORIENTED_EDGE('',*,*,#5710,.F.);\r\n#9087=ORIENTED_EDGE('',*,*,#9071,.F.);\r\n#9088=EDGE_LOOP('',(#9084,#9085,#9086,#9087));\r\n#9089=FACE_OUTER_BOUND('',#9088,.F.);\r\n#9090=ADVANCED_FACE('',(#9089),#9083,.F.);\r\n#9091=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#9092=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9093=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9094=AXIS2_PLACEMENT_3D('',#9091,#9092,#9093);\r\n#9095=CYLINDRICAL_SURFACE('',#9094,2.575E-1);\r\n#9096=ORIENTED_EDGE('',*,*,#6476,.T.);\r\n#9098=ORIENTED_EDGE('',*,*,#9097,.T.);\r\n#9100=ORIENTED_EDGE('',*,*,#9099,.F.);\r\n#9102=ORIENTED_EDGE('',*,*,#9101,.F.);\r\n#9103=EDGE_LOOP('',(#9096,#9098,#9100,#9102));\r\n#9104=FACE_OUTER_BOUND('',#9103,.F.);\r\n#9105=ADVANCED_FACE('',(#9104),#9095,.F.);\r\n#9106=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#9107=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9108=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9109=AXIS2_PLACEMENT_3D('',#9106,#9107,#9108);\r\n#9110=CYLINDRICAL_SURFACE('',#9109,2.575E-1);\r\n#9111=ORIENTED_EDGE('',*,*,#6478,.T.);\r\n#9112=ORIENTED_EDGE('',*,*,#9101,.T.);\r\n#9114=ORIENTED_EDGE('',*,*,#9113,.F.);\r\n#9115=ORIENTED_EDGE('',*,*,#9097,.F.);\r\n#9116=EDGE_LOOP('',(#9111,#9112,#9114,#9115));\r\n#9117=FACE_OUTER_BOUND('',#9116,.F.);\r\n#9118=ADVANCED_FACE('',(#9117),#9110,.F.);\r\n#9119=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1));\r\n#9120=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9121=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9122=AXIS2_PLACEMENT_3D('',#9119,#9120,#9121);\r\n#9123=PLANE('',#9122);\r\n#9124=ORIENTED_EDGE('',*,*,#9099,.T.);\r\n#9125=ORIENTED_EDGE('',*,*,#9113,.T.);\r\n#9126=EDGE_LOOP('',(#9124,#9125));\r\n#9127=FACE_OUTER_BOUND('',#9126,.F.);\r\n#9129=ORIENTED_EDGE('',*,*,#9128,.F.);\r\n#9131=ORIENTED_EDGE('',*,*,#9130,.F.);\r\n#9132=EDGE_LOOP('',(#9129,#9131));\r\n#9133=FACE_BOUND('',#9132,.F.);\r\n#9134=ADVANCED_FACE('',(#9127,#9133),#9123,.F.);\r\n#9135=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#9136=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9137=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9138=AXIS2_PLACEMENT_3D('',#9135,#9136,#9137);\r\n#9139=CYLINDRICAL_SURFACE('',#9138,1.925E-1);\r\n#9140=ORIENTED_EDGE('',*,*,#9128,.T.);\r\n#9142=ORIENTED_EDGE('',*,*,#9141,.T.);\r\n#9143=ORIENTED_EDGE('',*,*,#5714,.F.);\r\n#9145=ORIENTED_EDGE('',*,*,#9144,.F.);\r\n#9146=EDGE_LOOP('',(#9140,#9142,#9143,#9145));\r\n#9147=FACE_OUTER_BOUND('',#9146,.F.);\r\n#9148=ADVANCED_FACE('',(#9147),#9139,.F.);\r\n#9149=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1));\r\n#9150=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9151=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9152=AXIS2_PLACEMENT_3D('',#9149,#9150,#9151);\r\n#9153=CYLINDRICAL_SURFACE('',#9152,1.925E-1);\r\n#9154=ORIENTED_EDGE('',*,*,#9130,.T.);\r\n#9155=ORIENTED_EDGE('',*,*,#9144,.T.);\r\n#9156=ORIENTED_EDGE('',*,*,#5716,.F.);\r\n#9157=ORIENTED_EDGE('',*,*,#9141,.F.);\r\n#9158=EDGE_LOOP('',(#9154,#9155,#9156,#9157));\r\n#9159=FACE_OUTER_BOUND('',#9158,.F.);\r\n#9160=ADVANCED_FACE('',(#9159),#9153,.F.);\r\n#9161=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#9162=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9163=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9164=AXIS2_PLACEMENT_3D('',#9161,#9162,#9163);\r\n#9165=CYLINDRICAL_SURFACE('',#9164,2.575E-1);\r\n#9166=ORIENTED_EDGE('',*,*,#6482,.T.);\r\n#9168=ORIENTED_EDGE('',*,*,#9167,.T.);\r\n#9170=ORIENTED_EDGE('',*,*,#9169,.F.);\r\n#9172=ORIENTED_EDGE('',*,*,#9171,.F.);\r\n#9173=EDGE_LOOP('',(#9166,#9168,#9170,#9172));\r\n#9174=FACE_OUTER_BOUND('',#9173,.F.);\r\n#9175=ADVANCED_FACE('',(#9174),#9165,.F.);\r\n#9176=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#9177=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9178=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9179=AXIS2_PLACEMENT_3D('',#9176,#9177,#9178);\r\n#9180=CYLINDRICAL_SURFACE('',#9179,2.575E-1);\r\n#9181=ORIENTED_EDGE('',*,*,#6484,.T.);\r\n#9182=ORIENTED_EDGE('',*,*,#9171,.T.);\r\n#9184=ORIENTED_EDGE('',*,*,#9183,.F.);\r\n#9185=ORIENTED_EDGE('',*,*,#9167,.F.);\r\n#9186=EDGE_LOOP('',(#9181,#9182,#9184,#9185));\r\n#9187=FACE_OUTER_BOUND('',#9186,.F.);\r\n#9188=ADVANCED_FACE('',(#9187),#9180,.F.);\r\n#9189=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1));\r\n#9190=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9191=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9192=AXIS2_PLACEMENT_3D('',#9189,#9190,#9191);\r\n#9193=PLANE('',#9192);\r\n#9194=ORIENTED_EDGE('',*,*,#9169,.T.);\r\n#9195=ORIENTED_EDGE('',*,*,#9183,.T.);\r\n#9196=EDGE_LOOP('',(#9194,#9195));\r\n#9197=FACE_OUTER_BOUND('',#9196,.F.);\r\n#9199=ORIENTED_EDGE('',*,*,#9198,.F.);\r\n#9201=ORIENTED_EDGE('',*,*,#9200,.F.);\r\n#9202=EDGE_LOOP('',(#9199,#9201));\r\n#9203=FACE_BOUND('',#9202,.F.);\r\n#9204=ADVANCED_FACE('',(#9197,#9203),#9193,.F.);\r\n#9205=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#9206=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9207=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9208=AXIS2_PLACEMENT_3D('',#9205,#9206,#9207);\r\n#9209=CYLINDRICAL_SURFACE('',#9208,1.925E-1);\r\n#9210=ORIENTED_EDGE('',*,*,#9198,.T.);\r\n#9212=ORIENTED_EDGE('',*,*,#9211,.T.);\r\n#9213=ORIENTED_EDGE('',*,*,#5720,.F.);\r\n#9215=ORIENTED_EDGE('',*,*,#9214,.F.);\r\n#9216=EDGE_LOOP('',(#9210,#9212,#9213,#9215));\r\n#9217=FACE_OUTER_BOUND('',#9216,.F.);\r\n#9218=ADVANCED_FACE('',(#9217),#9209,.F.);\r\n#9219=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1));\r\n#9220=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9221=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9222=AXIS2_PLACEMENT_3D('',#9219,#9220,#9221);\r\n#9223=CYLINDRICAL_SURFACE('',#9222,1.925E-1);\r\n#9224=ORIENTED_EDGE('',*,*,#9200,.T.);\r\n#9225=ORIENTED_EDGE('',*,*,#9214,.T.);\r\n#9226=ORIENTED_EDGE('',*,*,#5722,.F.);\r\n#9227=ORIENTED_EDGE('',*,*,#9211,.F.);\r\n#9228=EDGE_LOOP('',(#9224,#9225,#9226,#9227));\r\n#9229=FACE_OUTER_BOUND('',#9228,.F.);\r\n#9230=ADVANCED_FACE('',(#9229),#9223,.F.);\r\n#9231=CARTESIAN_POINT('',(2.2E1,1.5E0,1.2E1));\r\n#9232=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9233=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9234=AXIS2_PLACEMENT_3D('',#9231,#9232,#9233);\r\n#9235=PLANE('',#9234);\r\n#9236=ORIENTED_EDGE('',*,*,#6328,.T.);\r\n#9237=ORIENTED_EDGE('',*,*,#6155,.T.);\r\n#9239=ORIENTED_EDGE('',*,*,#9238,.T.);\r\n#9240=EDGE_LOOP('',(#9236,#9237,#9239));\r\n#9241=FACE_OUTER_BOUND('',#9240,.F.);\r\n#9242=ADVANCED_FACE('',(#9241),#9235,.F.);\r\n#9243=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1));\r\n#9244=DIRECTION('',(0.E0,-5.E-1,-8.660254037844E-1));\r\n#9245=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1));\r\n#9246=AXIS2_PLACEMENT_3D('',#9243,#9244,#9245);\r\n#9247=PLANE('',#9246);\r\n#9248=ORIENTED_EDGE('',*,*,#6330,.T.);\r\n#9249=ORIENTED_EDGE('',*,*,#9238,.F.);\r\n#9250=ORIENTED_EDGE('',*,*,#6153,.F.);\r\n#9251=ORIENTED_EDGE('',*,*,#6209,.T.);\r\n#9252=EDGE_LOOP('',(#9248,#9249,#9250,#9251));\r\n#9253=FACE_OUTER_BOUND('',#9252,.F.);\r\n#9255=ORIENTED_EDGE('',*,*,#9254,.F.);\r\n#9257=ORIENTED_EDGE('',*,*,#9256,.F.);\r\n#9258=EDGE_LOOP('',(#9255,#9257));\r\n#9259=FACE_BOUND('',#9258,.F.);\r\n#9260=ADVANCED_FACE('',(#9253,#9259),#9247,.F.);\r\n#9261=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1));\r\n#9262=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9263=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9264=AXIS2_PLACEMENT_3D('',#9261,#9262,#9263);\r\n#9265=CYLINDRICAL_SURFACE('',#9264,2.575E-1);\r\n#9267=ORIENTED_EDGE('',*,*,#9266,.F.);\r\n#9268=ORIENTED_EDGE('',*,*,#9254,.T.);\r\n#9270=ORIENTED_EDGE('',*,*,#9269,.F.);\r\n#9272=ORIENTED_EDGE('',*,*,#9271,.F.);\r\n#9273=EDGE_LOOP('',(#9267,#9268,#9270,#9272));\r\n#9274=FACE_OUTER_BOUND('',#9273,.F.);\r\n#9275=ADVANCED_FACE('',(#9274),#9265,.F.);\r\n#9276=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1));\r\n#9277=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9278=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9279=AXIS2_PLACEMENT_3D('',#9276,#9277,#9278);\r\n#9280=CYLINDRICAL_SURFACE('',#9279,2.575E-1);\r\n#9281=ORIENTED_EDGE('',*,*,#9269,.T.);\r\n#9282=ORIENTED_EDGE('',*,*,#9256,.T.);\r\n#9283=ORIENTED_EDGE('',*,*,#9266,.T.);\r\n#9285=ORIENTED_EDGE('',*,*,#9284,.F.);\r\n#9286=EDGE_LOOP('',(#9281,#9282,#9283,#9285));\r\n#9287=FACE_OUTER_BOUND('',#9286,.F.);\r\n#9288=ADVANCED_FACE('',(#9287),#9280,.F.);\r\n#9289=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1));\r\n#9290=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9291=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9292=AXIS2_PLACEMENT_3D('',#9289,#9290,#9291);\r\n#9293=PLANE('',#9292);\r\n#9294=ORIENTED_EDGE('',*,*,#9271,.T.);\r\n#9295=ORIENTED_EDGE('',*,*,#9284,.T.);\r\n#9296=EDGE_LOOP('',(#9294,#9295));\r\n#9297=FACE_OUTER_BOUND('',#9296,.F.);\r\n#9299=ORIENTED_EDGE('',*,*,#9298,.F.);\r\n#9301=ORIENTED_EDGE('',*,*,#9300,.F.);\r\n#9302=EDGE_LOOP('',(#9299,#9301));\r\n#9303=FACE_BOUND('',#9302,.F.);\r\n#9304=ADVANCED_FACE('',(#9297,#9303),#9293,.F.);\r\n#9305=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1));\r\n#9306=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9307=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9308=AXIS2_PLACEMENT_3D('',#9305,#9306,#9307);\r\n#9309=CYLINDRICAL_SURFACE('',#9308,1.925E-1);\r\n#9310=ORIENTED_EDGE('',*,*,#9298,.T.);\r\n#9312=ORIENTED_EDGE('',*,*,#9311,.T.);\r\n#9313=ORIENTED_EDGE('',*,*,#5596,.F.);\r\n#9315=ORIENTED_EDGE('',*,*,#9314,.F.);\r\n#9316=EDGE_LOOP('',(#9310,#9312,#9313,#9315));\r\n#9317=FACE_OUTER_BOUND('',#9316,.F.);\r\n#9318=ADVANCED_FACE('',(#9317),#9309,.F.);\r\n#9319=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1));\r\n#9320=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9321=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9322=AXIS2_PLACEMENT_3D('',#9319,#9320,#9321);\r\n#9323=CYLINDRICAL_SURFACE('',#9322,1.925E-1);\r\n#9324=ORIENTED_EDGE('',*,*,#9300,.T.);\r\n#9325=ORIENTED_EDGE('',*,*,#9314,.T.);\r\n#9326=ORIENTED_EDGE('',*,*,#5598,.F.);\r\n#9327=ORIENTED_EDGE('',*,*,#9311,.F.);\r\n#9328=EDGE_LOOP('',(#9324,#9325,#9326,#9327));\r\n#9329=FACE_OUTER_BOUND('',#9328,.F.);\r\n#9330=ADVANCED_FACE('',(#9329),#9323,.F.);\r\n#9331=CARTESIAN_POINT('',(2.185E1,6.65E0,1.006892397423E1));\r\n#9332=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9333=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9334=AXIS2_PLACEMENT_3D('',#9331,#9332,#9333);\r\n#9335=CYLINDRICAL_SURFACE('',#9334,3.5E-1);\r\n#9337=ORIENTED_EDGE('',*,*,#9336,.T.);\r\n#9339=ORIENTED_EDGE('',*,*,#9338,.T.);\r\n#9341=ORIENTED_EDGE('',*,*,#9340,.F.);\r\n#9342=ORIENTED_EDGE('',*,*,#6175,.T.);\r\n#9343=EDGE_LOOP('',(#9337,#9339,#9341,#9342));\r\n#9344=FACE_OUTER_BOUND('',#9343,.F.);\r\n#9345=ADVANCED_FACE('',(#9344),#9335,.T.);\r\n#9346=CARTESIAN_POINT('',(2.15E1,7.E0,1.E1));\r\n#9347=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9348=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9349=AXIS2_PLACEMENT_3D('',#9346,#9347,#9348);\r\n#9350=PLANE('',#9349);\r\n#9351=ORIENTED_EDGE('',*,*,#9336,.F.);\r\n#9352=ORIENTED_EDGE('',*,*,#6197,.T.);\r\n#9354=ORIENTED_EDGE('',*,*,#9353,.F.);\r\n#9356=ORIENTED_EDGE('',*,*,#9355,.F.);\r\n#9357=EDGE_LOOP('',(#9351,#9352,#9354,#9356));\r\n#9358=FACE_OUTER_BOUND('',#9357,.F.);\r\n#9359=ADVANCED_FACE('',(#9358),#9350,.T.);\r\n#9360=CARTESIAN_POINT('',(2.115E1,2.35E0,9.441108058217E0));\r\n#9361=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9362=DIRECTION('',(1.015061051086E-14,-1.E0,0.E0));\r\n#9363=AXIS2_PLACEMENT_3D('',#9360,#9361,#9362);\r\n#9364=CYLINDRICAL_SURFACE('',#9363,3.5E-1);\r\n#9366=ORIENTED_EDGE('',*,*,#9365,.F.);\r\n#9368=ORIENTED_EDGE('',*,*,#9367,.T.);\r\n#9369=ORIENTED_EDGE('',*,*,#9353,.T.);\r\n#9370=ORIENTED_EDGE('',*,*,#6195,.T.);\r\n#9371=EDGE_LOOP('',(#9366,#9368,#9369,#9370));\r\n#9372=FACE_OUTER_BOUND('',#9371,.F.);\r\n#9373=ADVANCED_FACE('',(#9372),#9364,.F.);\r\n#9374=CARTESIAN_POINT('',(2.15E1,2.E0,1.E1));\r\n#9375=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9376=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9377=AXIS2_PLACEMENT_3D('',#9374,#9375,#9376);\r\n#9378=PLANE('',#9377);\r\n#9379=ORIENTED_EDGE('',*,*,#9365,.T.);\r\n#9380=ORIENTED_EDGE('',*,*,#6193,.T.);\r\n#9382=ORIENTED_EDGE('',*,*,#9381,.F.);\r\n#9384=ORIENTED_EDGE('',*,*,#9383,.F.);\r\n#9385=EDGE_LOOP('',(#9379,#9380,#9382,#9384));\r\n#9386=FACE_OUTER_BOUND('',#9385,.F.);\r\n#9387=ADVANCED_FACE('',(#9386),#9378,.T.);\r\n#9388=CARTESIAN_POINT('',(1.985E1,2.35E0,9.441108058217E0));\r\n#9389=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9390=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9391=AXIS2_PLACEMENT_3D('',#9388,#9389,#9390);\r\n#9392=CYLINDRICAL_SURFACE('',#9391,3.5E-1);\r\n#9394=ORIENTED_EDGE('',*,*,#9393,.F.);\r\n#9396=ORIENTED_EDGE('',*,*,#9395,.T.);\r\n#9397=ORIENTED_EDGE('',*,*,#9381,.T.);\r\n#9398=ORIENTED_EDGE('',*,*,#6191,.T.);\r\n#9399=EDGE_LOOP('',(#9394,#9396,#9397,#9398));\r\n#9400=FACE_OUTER_BOUND('',#9399,.F.);\r\n#9401=ADVANCED_FACE('',(#9400),#9392,.F.);\r\n#9402=CARTESIAN_POINT('',(1.95E1,2.E0,1.E1));\r\n#9403=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9404=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9405=AXIS2_PLACEMENT_3D('',#9402,#9403,#9404);\r\n#9406=PLANE('',#9405);\r\n#9407=ORIENTED_EDGE('',*,*,#9393,.T.);\r\n#9408=ORIENTED_EDGE('',*,*,#6189,.T.);\r\n#9410=ORIENTED_EDGE('',*,*,#9409,.F.);\r\n#9412=ORIENTED_EDGE('',*,*,#9411,.F.);\r\n#9413=EDGE_LOOP('',(#9407,#9408,#9410,#9412));\r\n#9414=FACE_OUTER_BOUND('',#9413,.F.);\r\n#9415=ADVANCED_FACE('',(#9414),#9406,.T.);\r\n#9416=CARTESIAN_POINT('',(1.985E1,9.15E0,9.441108058217E0));\r\n#9417=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9418=DIRECTION('',(-1.015061051086E-14,1.E0,0.E0));\r\n#9419=AXIS2_PLACEMENT_3D('',#9416,#9417,#9418);\r\n#9420=CYLINDRICAL_SURFACE('',#9419,3.5E-1);\r\n#9422=ORIENTED_EDGE('',*,*,#9421,.F.);\r\n#9424=ORIENTED_EDGE('',*,*,#9423,.T.);\r\n#9425=ORIENTED_EDGE('',*,*,#9409,.T.);\r\n#9426=ORIENTED_EDGE('',*,*,#6187,.T.);\r\n#9427=EDGE_LOOP('',(#9422,#9424,#9425,#9426));\r\n#9428=FACE_OUTER_BOUND('',#9427,.F.);\r\n#9429=ADVANCED_FACE('',(#9428),#9420,.F.);\r\n#9430=CARTESIAN_POINT('',(1.95E1,9.5E0,1.E1));\r\n#9431=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9432=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9433=AXIS2_PLACEMENT_3D('',#9430,#9431,#9432);\r\n#9434=PLANE('',#9433);\r\n#9436=ORIENTED_EDGE('',*,*,#9435,.F.);\r\n#9438=ORIENTED_EDGE('',*,*,#9437,.F.);\r\n#9439=ORIENTED_EDGE('',*,*,#9421,.T.);\r\n#9440=ORIENTED_EDGE('',*,*,#6185,.T.);\r\n#9441=EDGE_LOOP('',(#9436,#9438,#9439,#9440));\r\n#9442=FACE_OUTER_BOUND('',#9441,.F.);\r\n#9443=ADVANCED_FACE('',(#9442),#9434,.T.);\r\n#9444=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,9.441108058217E0));\r\n#9445=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9446=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#9447=AXIS2_PLACEMENT_3D('',#9444,#9445,#9446);\r\n#9448=CYLINDRICAL_SURFACE('',#9447,3.5E-1);\r\n#9450=ORIENTED_EDGE('',*,*,#9449,.F.);\r\n#9452=ORIENTED_EDGE('',*,*,#9451,.T.);\r\n#9453=ORIENTED_EDGE('',*,*,#9435,.T.);\r\n#9454=ORIENTED_EDGE('',*,*,#6183,.T.);\r\n#9455=EDGE_LOOP('',(#9450,#9452,#9453,#9454));\r\n#9456=FACE_OUTER_BOUND('',#9455,.F.);\r\n#9457=ADVANCED_FACE('',(#9456),#9448,.F.);\r\n#9458=CARTESIAN_POINT('',(2.125314193270E1,9.5E0,1.E1));\r\n#9459=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0));\r\n#9460=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0));\r\n#9461=AXIS2_PLACEMENT_3D('',#9458,#9459,#9460);\r\n#9462=PLANE('',#9461);\r\n#9464=ORIENTED_EDGE('',*,*,#9463,.F.);\r\n#9466=ORIENTED_EDGE('',*,*,#9465,.F.);\r\n#9467=ORIENTED_EDGE('',*,*,#9449,.T.);\r\n#9468=ORIENTED_EDGE('',*,*,#6181,.T.);\r\n#9469=EDGE_LOOP('',(#9464,#9466,#9467,#9468));\r\n#9470=FACE_OUTER_BOUND('',#9469,.F.);\r\n#9471=ADVANCED_FACE('',(#9470),#9462,.T.);\r\n#9472=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,9.441108058217E0));\r\n#9473=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9474=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9475=AXIS2_PLACEMENT_3D('',#9472,#9473,#9474);\r\n#9476=CYLINDRICAL_SURFACE('',#9475,3.5E-1);\r\n#9478=ORIENTED_EDGE('',*,*,#9477,.F.);\r\n#9480=ORIENTED_EDGE('',*,*,#9479,.T.);\r\n#9481=ORIENTED_EDGE('',*,*,#9463,.T.);\r\n#9482=ORIENTED_EDGE('',*,*,#6179,.T.);\r\n#9483=EDGE_LOOP('',(#9478,#9480,#9481,#9482));\r\n#9484=FACE_OUTER_BOUND('',#9483,.F.);\r\n#9485=ADVANCED_FACE('',(#9484),#9476,.F.);\r\n#9486=CARTESIAN_POINT('',(2.264203082158E1,7.E0,1.E1));\r\n#9487=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9488=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9489=AXIS2_PLACEMENT_3D('',#9486,#9487,#9488);\r\n#9490=PLANE('',#9489);\r\n#9491=ORIENTED_EDGE('',*,*,#9340,.T.);\r\n#9493=ORIENTED_EDGE('',*,*,#9492,.F.);\r\n#9494=ORIENTED_EDGE('',*,*,#9477,.T.);\r\n#9495=ORIENTED_EDGE('',*,*,#6177,.T.);\r\n#9496=EDGE_LOOP('',(#9491,#9493,#9494,#9495));\r\n#9497=FACE_OUTER_BOUND('',#9496,.F.);\r\n#9498=ADVANCED_FACE('',(#9497),#9490,.T.);\r\n#9499=CARTESIAN_POINT('',(2.4E1,0.E0,9.5E0));\r\n#9500=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9501=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9502=AXIS2_PLACEMENT_3D('',#9499,#9500,#9501);\r\n#9503=PLANE('',#9502);\r\n#9504=ORIENTED_EDGE('',*,*,#9492,.T.);\r\n#9505=ORIENTED_EDGE('',*,*,#9338,.F.);\r\n#9506=ORIENTED_EDGE('',*,*,#9355,.T.);\r\n#9507=ORIENTED_EDGE('',*,*,#9367,.F.);\r\n#9508=ORIENTED_EDGE('',*,*,#9383,.T.);\r\n#9509=ORIENTED_EDGE('',*,*,#9395,.F.);\r\n#9510=ORIENTED_EDGE('',*,*,#9411,.T.);\r\n#9511=ORIENTED_EDGE('',*,*,#9423,.F.);\r\n#9512=ORIENTED_EDGE('',*,*,#9437,.T.);\r\n#9513=ORIENTED_EDGE('',*,*,#9451,.F.);\r\n#9514=ORIENTED_EDGE('',*,*,#9465,.T.);\r\n#9515=ORIENTED_EDGE('',*,*,#9479,.F.);\r\n#9516=EDGE_LOOP('',(#9504,#9505,#9506,#9507,#9508,#9509,#9510,#9511,#9512,#9513,\r\n#9514,#9515));\r\n#9517=FACE_OUTER_BOUND('',#9516,.F.);\r\n#9518=ADVANCED_FACE('',(#9517),#9503,.F.);\r\n#9519=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0));\r\n#9520=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9521=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9522=AXIS2_PLACEMENT_3D('',#9519,#9520,#9521);\r\n#9523=CYLINDRICAL_SURFACE('',#9522,9.5E-2);\r\n#9524=ORIENTED_EDGE('',*,*,#6007,.F.);\r\n#9526=ORIENTED_EDGE('',*,*,#9525,.T.);\r\n#9528=ORIENTED_EDGE('',*,*,#9527,.T.);\r\n#9530=ORIENTED_EDGE('',*,*,#9529,.F.);\r\n#9531=EDGE_LOOP('',(#9524,#9526,#9528,#9530));\r\n#9532=FACE_OUTER_BOUND('',#9531,.F.);\r\n#9533=ADVANCED_FACE('',(#9532),#9523,.F.);\r\n#9534=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0));\r\n#9535=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9536=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9537=AXIS2_PLACEMENT_3D('',#9534,#9535,#9536);\r\n#9538=CYLINDRICAL_SURFACE('',#9537,9.5E-2);\r\n#9539=ORIENTED_EDGE('',*,*,#6009,.F.);\r\n#9540=ORIENTED_EDGE('',*,*,#9529,.T.);\r\n#9542=ORIENTED_EDGE('',*,*,#9541,.T.);\r\n#9543=ORIENTED_EDGE('',*,*,#9525,.F.);\r\n#9544=EDGE_LOOP('',(#9539,#9540,#9542,#9543));\r\n#9545=FACE_OUTER_BOUND('',#9544,.F.);\r\n#9546=ADVANCED_FACE('',(#9545),#9538,.F.);\r\n#9547=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0));\r\n#9548=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9549=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9550=AXIS2_PLACEMENT_3D('',#9547,#9548,#9549);\r\n#9551=PLANE('',#9550);\r\n#9552=ORIENTED_EDGE('',*,*,#9527,.F.);\r\n#9553=ORIENTED_EDGE('',*,*,#9541,.F.);\r\n#9554=EDGE_LOOP('',(#9552,#9553));\r\n#9555=FACE_OUTER_BOUND('',#9554,.F.);\r\n#9556=ADVANCED_FACE('',(#9555),#9551,.T.);\r\n#9557=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0));\r\n#9558=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9559=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9560=AXIS2_PLACEMENT_3D('',#9557,#9558,#9559);\r\n#9561=CYLINDRICAL_SURFACE('',#9560,9.5E-2);\r\n#9562=ORIENTED_EDGE('',*,*,#6013,.F.);\r\n#9564=ORIENTED_EDGE('',*,*,#9563,.T.);\r\n#9566=ORIENTED_EDGE('',*,*,#9565,.T.);\r\n#9568=ORIENTED_EDGE('',*,*,#9567,.F.);\r\n#9569=EDGE_LOOP('',(#9562,#9564,#9566,#9568));\r\n#9570=FACE_OUTER_BOUND('',#9569,.F.);\r\n#9571=ADVANCED_FACE('',(#9570),#9561,.F.);\r\n#9572=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0));\r\n#9573=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9574=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9575=AXIS2_PLACEMENT_3D('',#9572,#9573,#9574);\r\n#9576=CYLINDRICAL_SURFACE('',#9575,9.5E-2);\r\n#9577=ORIENTED_EDGE('',*,*,#6015,.F.);\r\n#9578=ORIENTED_EDGE('',*,*,#9567,.T.);\r\n#9580=ORIENTED_EDGE('',*,*,#9579,.T.);\r\n#9581=ORIENTED_EDGE('',*,*,#9563,.F.);\r\n#9582=EDGE_LOOP('',(#9577,#9578,#9580,#9581));\r\n#9583=FACE_OUTER_BOUND('',#9582,.F.);\r\n#9584=ADVANCED_FACE('',(#9583),#9576,.F.);\r\n#9585=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0));\r\n#9586=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9587=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9588=AXIS2_PLACEMENT_3D('',#9585,#9586,#9587);\r\n#9589=PLANE('',#9588);\r\n#9590=ORIENTED_EDGE('',*,*,#9565,.F.);\r\n#9591=ORIENTED_EDGE('',*,*,#9579,.F.);\r\n#9592=EDGE_LOOP('',(#9590,#9591));\r\n#9593=FACE_OUTER_BOUND('',#9592,.F.);\r\n#9594=ADVANCED_FACE('',(#9593),#9589,.T.);\r\n#9595=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0));\r\n#9596=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9597=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9598=AXIS2_PLACEMENT_3D('',#9595,#9596,#9597);\r\n#9599=CYLINDRICAL_SURFACE('',#9598,9.5E-2);\r\n#9600=ORIENTED_EDGE('',*,*,#6019,.T.);\r\n#9602=ORIENTED_EDGE('',*,*,#9601,.T.);\r\n#9604=ORIENTED_EDGE('',*,*,#9603,.F.);\r\n#9606=ORIENTED_EDGE('',*,*,#9605,.F.);\r\n#9607=EDGE_LOOP('',(#9600,#9602,#9604,#9606));\r\n#9608=FACE_OUTER_BOUND('',#9607,.F.);\r\n#9609=ADVANCED_FACE('',(#9608),#9599,.F.);\r\n#9610=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0));\r\n#9611=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9612=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9613=AXIS2_PLACEMENT_3D('',#9610,#9611,#9612);\r\n#9614=CYLINDRICAL_SURFACE('',#9613,9.5E-2);\r\n#9615=ORIENTED_EDGE('',*,*,#6021,.T.);\r\n#9616=ORIENTED_EDGE('',*,*,#9605,.T.);\r\n#9618=ORIENTED_EDGE('',*,*,#9617,.F.);\r\n#9619=ORIENTED_EDGE('',*,*,#9601,.F.);\r\n#9620=EDGE_LOOP('',(#9615,#9616,#9618,#9619));\r\n#9621=FACE_OUTER_BOUND('',#9620,.F.);\r\n#9622=ADVANCED_FACE('',(#9621),#9614,.F.);\r\n#9623=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0));\r\n#9624=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9625=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9626=AXIS2_PLACEMENT_3D('',#9623,#9624,#9625);\r\n#9627=PLANE('',#9626);\r\n#9628=ORIENTED_EDGE('',*,*,#9603,.T.);\r\n#9629=ORIENTED_EDGE('',*,*,#9617,.T.);\r\n#9630=EDGE_LOOP('',(#9628,#9629));\r\n#9631=FACE_OUTER_BOUND('',#9630,.F.);\r\n#9632=ADVANCED_FACE('',(#9631),#9627,.F.);\r\n#9633=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0));\r\n#9634=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9635=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9636=AXIS2_PLACEMENT_3D('',#9633,#9634,#9635);\r\n#9637=CYLINDRICAL_SURFACE('',#9636,9.5E-2);\r\n#9638=ORIENTED_EDGE('',*,*,#6025,.T.);\r\n#9640=ORIENTED_EDGE('',*,*,#9639,.T.);\r\n#9642=ORIENTED_EDGE('',*,*,#9641,.F.);\r\n#9644=ORIENTED_EDGE('',*,*,#9643,.F.);\r\n#9645=EDGE_LOOP('',(#9638,#9640,#9642,#9644));\r\n#9646=FACE_OUTER_BOUND('',#9645,.F.);\r\n#9647=ADVANCED_FACE('',(#9646),#9637,.F.);\r\n#9648=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0));\r\n#9649=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9650=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9651=AXIS2_PLACEMENT_3D('',#9648,#9649,#9650);\r\n#9652=CYLINDRICAL_SURFACE('',#9651,9.5E-2);\r\n#9653=ORIENTED_EDGE('',*,*,#6027,.T.);\r\n#9654=ORIENTED_EDGE('',*,*,#9643,.T.);\r\n#9656=ORIENTED_EDGE('',*,*,#9655,.F.);\r\n#9657=ORIENTED_EDGE('',*,*,#9639,.F.);\r\n#9658=EDGE_LOOP('',(#9653,#9654,#9656,#9657));\r\n#9659=FACE_OUTER_BOUND('',#9658,.F.);\r\n#9660=ADVANCED_FACE('',(#9659),#9652,.F.);\r\n#9661=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0));\r\n#9662=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9663=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9664=AXIS2_PLACEMENT_3D('',#9661,#9662,#9663);\r\n#9665=PLANE('',#9664);\r\n#9666=ORIENTED_EDGE('',*,*,#9641,.T.);\r\n#9667=ORIENTED_EDGE('',*,*,#9655,.T.);\r\n#9668=EDGE_LOOP('',(#9666,#9667));\r\n#9669=FACE_OUTER_BOUND('',#9668,.F.);\r\n#9670=ADVANCED_FACE('',(#9669),#9665,.F.);\r\n#9671=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0));\r\n#9672=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9673=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9674=AXIS2_PLACEMENT_3D('',#9671,#9672,#9673);\r\n#9675=CYLINDRICAL_SURFACE('',#9674,9.5E-2);\r\n#9676=ORIENTED_EDGE('',*,*,#6037,.T.);\r\n#9678=ORIENTED_EDGE('',*,*,#9677,.T.);\r\n#9680=ORIENTED_EDGE('',*,*,#9679,.F.);\r\n#9682=ORIENTED_EDGE('',*,*,#9681,.F.);\r\n#9683=EDGE_LOOP('',(#9676,#9678,#9680,#9682));\r\n#9684=FACE_OUTER_BOUND('',#9683,.F.);\r\n#9685=ADVANCED_FACE('',(#9684),#9675,.F.);\r\n#9686=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0));\r\n#9687=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9688=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9689=AXIS2_PLACEMENT_3D('',#9686,#9687,#9688);\r\n#9690=CYLINDRICAL_SURFACE('',#9689,9.5E-2);\r\n#9691=ORIENTED_EDGE('',*,*,#6039,.T.);\r\n#9692=ORIENTED_EDGE('',*,*,#9681,.T.);\r\n#9694=ORIENTED_EDGE('',*,*,#9693,.F.);\r\n#9695=ORIENTED_EDGE('',*,*,#9677,.F.);\r\n#9696=EDGE_LOOP('',(#9691,#9692,#9694,#9695));\r\n#9697=FACE_OUTER_BOUND('',#9696,.F.);\r\n#9698=ADVANCED_FACE('',(#9697),#9690,.F.);\r\n#9699=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0));\r\n#9700=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9701=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9702=AXIS2_PLACEMENT_3D('',#9699,#9700,#9701);\r\n#9703=PLANE('',#9702);\r\n#9704=ORIENTED_EDGE('',*,*,#9679,.T.);\r\n#9705=ORIENTED_EDGE('',*,*,#9693,.T.);\r\n#9706=EDGE_LOOP('',(#9704,#9705));\r\n#9707=FACE_OUTER_BOUND('',#9706,.F.);\r\n#9708=ADVANCED_FACE('',(#9707),#9703,.F.);\r\n#9709=CARTESIAN_POINT('',(4.5E0,2.E0,8.E0));\r\n#9710=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9711=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9712=AXIS2_PLACEMENT_3D('',#9709,#9710,#9711);\r\n#9713=PLANE('',#9712);\r\n#9715=ORIENTED_EDGE('',*,*,#9714,.T.);\r\n#9717=ORIENTED_EDGE('',*,*,#9716,.T.);\r\n#9719=ORIENTED_EDGE('',*,*,#9718,.F.);\r\n#9720=ORIENTED_EDGE('',*,*,#6043,.F.);\r\n#9721=EDGE_LOOP('',(#9715,#9717,#9719,#9720));\r\n#9722=FACE_OUTER_BOUND('',#9721,.F.);\r\n#9723=ADVANCED_FACE('',(#9722),#9713,.F.);\r\n#9724=CARTESIAN_POINT('',(3.75E0,2.75E0,7.931076025772E0));\r\n#9725=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9726=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9727=AXIS2_PLACEMENT_3D('',#9724,#9725,#9726);\r\n#9728=CYLINDRICAL_SURFACE('',#9727,7.5E-1);\r\n#9729=ORIENTED_EDGE('',*,*,#9714,.F.);\r\n#9730=ORIENTED_EDGE('',*,*,#6057,.T.);\r\n#9732=ORIENTED_EDGE('',*,*,#9731,.T.);\r\n#9734=ORIENTED_EDGE('',*,*,#9733,.T.);\r\n#9735=EDGE_LOOP('',(#9729,#9730,#9732,#9734));\r\n#9736=FACE_OUTER_BOUND('',#9735,.F.);\r\n#9737=ADVANCED_FACE('',(#9736),#9728,.F.);\r\n#9738=CARTESIAN_POINT('',(4.5E0,9.5E0,8.E0));\r\n#9739=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9740=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9741=AXIS2_PLACEMENT_3D('',#9738,#9739,#9740);\r\n#9742=PLANE('',#9741);\r\n#9743=ORIENTED_EDGE('',*,*,#9731,.F.);\r\n#9744=ORIENTED_EDGE('',*,*,#6055,.F.);\r\n#9746=ORIENTED_EDGE('',*,*,#9745,.T.);\r\n#9748=ORIENTED_EDGE('',*,*,#9747,.T.);\r\n#9749=EDGE_LOOP('',(#9743,#9744,#9746,#9748));\r\n#9750=FACE_OUTER_BOUND('',#9749,.F.);\r\n#9751=ADVANCED_FACE('',(#9750),#9742,.F.);\r\n#9752=CARTESIAN_POINT('',(3.75E0,8.75E0,7.931076025772E0));\r\n#9753=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9754=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9755=AXIS2_PLACEMENT_3D('',#9752,#9753,#9754);\r\n#9756=CYLINDRICAL_SURFACE('',#9755,7.5E-1);\r\n#9757=ORIENTED_EDGE('',*,*,#9745,.F.);\r\n#9758=ORIENTED_EDGE('',*,*,#6053,.T.);\r\n#9760=ORIENTED_EDGE('',*,*,#9759,.T.);\r\n#9762=ORIENTED_EDGE('',*,*,#9761,.T.);\r\n#9763=EDGE_LOOP('',(#9757,#9758,#9760,#9762));\r\n#9764=FACE_OUTER_BOUND('',#9763,.F.);\r\n#9765=ADVANCED_FACE('',(#9764),#9756,.F.);\r\n#9766=CARTESIAN_POINT('',(2.746858067304E0,9.5E0,8.E0));\r\n#9767=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9768=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9769=AXIS2_PLACEMENT_3D('',#9766,#9767,#9768);\r\n#9770=PLANE('',#9769);\r\n#9772=ORIENTED_EDGE('',*,*,#9771,.T.);\r\n#9774=ORIENTED_EDGE('',*,*,#9773,.T.);\r\n#9775=ORIENTED_EDGE('',*,*,#9759,.F.);\r\n#9776=ORIENTED_EDGE('',*,*,#6051,.F.);\r\n#9777=EDGE_LOOP('',(#9772,#9774,#9775,#9776));\r\n#9778=FACE_OUTER_BOUND('',#9777,.F.);\r\n#9779=ADVANCED_FACE('',(#9778),#9770,.F.);\r\n#9780=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,7.931076025772E0));\r\n#9781=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9782=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9783=AXIS2_PLACEMENT_3D('',#9780,#9781,#9782);\r\n#9784=CYLINDRICAL_SURFACE('',#9783,7.5E-1);\r\n#9785=ORIENTED_EDGE('',*,*,#9771,.F.);\r\n#9786=ORIENTED_EDGE('',*,*,#6049,.T.);\r\n#9788=ORIENTED_EDGE('',*,*,#9787,.T.);\r\n#9790=ORIENTED_EDGE('',*,*,#9789,.T.);\r\n#9791=EDGE_LOOP('',(#9785,#9786,#9788,#9790));\r\n#9792=FACE_OUTER_BOUND('',#9791,.F.);\r\n#9793=ADVANCED_FACE('',(#9792),#9784,.F.);\r\n#9794=CARTESIAN_POINT('',(-1.419808599362E0,2.E0,8.E0));\r\n#9795=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#9796=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#9797=AXIS2_PLACEMENT_3D('',#9794,#9795,#9796);\r\n#9798=PLANE('',#9797);\r\n#9800=ORIENTED_EDGE('',*,*,#9799,.T.);\r\n#9802=ORIENTED_EDGE('',*,*,#9801,.T.);\r\n#9803=ORIENTED_EDGE('',*,*,#9787,.F.);\r\n#9804=ORIENTED_EDGE('',*,*,#6047,.F.);\r\n#9805=EDGE_LOOP('',(#9800,#9802,#9803,#9804));\r\n#9806=FACE_OUTER_BOUND('',#9805,.F.);\r\n#9807=ADVANCED_FACE('',(#9806),#9798,.F.);\r\n#9808=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,7.931076025772E0));\r\n#9809=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9810=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#9811=AXIS2_PLACEMENT_3D('',#9808,#9809,#9810);\r\n#9812=CYLINDRICAL_SURFACE('',#9811,7.5E-1);\r\n#9813=ORIENTED_EDGE('',*,*,#9799,.F.);\r\n#9814=ORIENTED_EDGE('',*,*,#6045,.T.);\r\n#9815=ORIENTED_EDGE('',*,*,#9718,.T.);\r\n#9817=ORIENTED_EDGE('',*,*,#9816,.T.);\r\n#9818=EDGE_LOOP('',(#9813,#9814,#9815,#9817));\r\n#9819=FACE_OUTER_BOUND('',#9818,.F.);\r\n#9820=ADVANCED_FACE('',(#9819),#9812,.F.);\r\n#9821=CARTESIAN_POINT('',(0.E0,0.E0,8.5E0));\r\n#9822=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9823=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9824=AXIS2_PLACEMENT_3D('',#9821,#9822,#9823);\r\n#9825=PLANE('',#9824);\r\n#9826=ORIENTED_EDGE('',*,*,#9733,.F.);\r\n#9827=ORIENTED_EDGE('',*,*,#9747,.F.);\r\n#9828=ORIENTED_EDGE('',*,*,#9761,.F.);\r\n#9829=ORIENTED_EDGE('',*,*,#9773,.F.);\r\n#9830=ORIENTED_EDGE('',*,*,#9789,.F.);\r\n#9831=ORIENTED_EDGE('',*,*,#9801,.F.);\r\n#9832=ORIENTED_EDGE('',*,*,#9816,.F.);\r\n#9833=ORIENTED_EDGE('',*,*,#9716,.F.);\r\n#9834=EDGE_LOOP('',(#9826,#9827,#9828,#9829,#9830,#9831,#9832,#9833));\r\n#9835=FACE_OUTER_BOUND('',#9834,.F.);\r\n#9836=ADVANCED_FACE('',(#9835),#9825,.T.);\r\n#9837=CARTESIAN_POINT('',(2.541980859936E1,2.E0,8.E0));\r\n#9838=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0));\r\n#9839=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0));\r\n#9840=AXIS2_PLACEMENT_3D('',#9837,#9838,#9839);\r\n#9841=PLANE('',#9840);\r\n#9843=ORIENTED_EDGE('',*,*,#9842,.T.);\r\n#9844=ORIENTED_EDGE('',*,*,#6061,.T.);\r\n#9846=ORIENTED_EDGE('',*,*,#9845,.F.);\r\n#9848=ORIENTED_EDGE('',*,*,#9847,.F.);\r\n#9849=EDGE_LOOP('',(#9843,#9844,#9846,#9848));\r\n#9850=FACE_OUTER_BOUND('',#9849,.F.);\r\n#9851=ADVANCED_FACE('',(#9850),#9841,.T.);\r\n#9852=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.558891941783E0));\r\n#9853=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9854=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0));\r\n#9855=AXIS2_PLACEMENT_3D('',#9852,#9853,#9854);\r\n#9856=CYLINDRICAL_SURFACE('',#9855,7.5E-1);\r\n#9857=ORIENTED_EDGE('',*,*,#9842,.F.);\r\n#9859=ORIENTED_EDGE('',*,*,#9858,.T.);\r\n#9861=ORIENTED_EDGE('',*,*,#9860,.T.);\r\n#9862=ORIENTED_EDGE('',*,*,#6063,.T.);\r\n#9863=EDGE_LOOP('',(#9857,#9859,#9861,#9862));\r\n#9864=FACE_OUTER_BOUND('',#9863,.F.);\r\n#9865=ADVANCED_FACE('',(#9864),#9856,.F.);\r\n#9866=CARTESIAN_POINT('',(2.4E1,0.E0,8.5E0));\r\n#9867=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9868=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9869=AXIS2_PLACEMENT_3D('',#9866,#9867,#9868);\r\n#9870=PLANE('',#9869);\r\n#9872=ORIENTED_EDGE('',*,*,#9871,.F.);\r\n#9874=ORIENTED_EDGE('',*,*,#9873,.T.);\r\n#9875=ORIENTED_EDGE('',*,*,#9858,.F.);\r\n#9876=ORIENTED_EDGE('',*,*,#9847,.T.);\r\n#9878=ORIENTED_EDGE('',*,*,#9877,.F.);\r\n#9880=ORIENTED_EDGE('',*,*,#9879,.T.);\r\n#9882=ORIENTED_EDGE('',*,*,#9881,.F.);\r\n#9884=ORIENTED_EDGE('',*,*,#9883,.T.);\r\n#9885=EDGE_LOOP('',(#9872,#9874,#9875,#9876,#9878,#9880,#9882,#9884));\r\n#9886=FACE_OUTER_BOUND('',#9885,.F.);\r\n#9887=ADVANCED_FACE('',(#9886),#9870,.F.);\r\n#9888=CARTESIAN_POINT('',(2.025E1,2.75E0,8.558891941783E0));\r\n#9889=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9890=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9891=AXIS2_PLACEMENT_3D('',#9888,#9889,#9890);\r\n#9892=CYLINDRICAL_SURFACE('',#9891,7.5E-1);\r\n#9894=ORIENTED_EDGE('',*,*,#9893,.F.);\r\n#9895=ORIENTED_EDGE('',*,*,#9871,.T.);\r\n#9897=ORIENTED_EDGE('',*,*,#9896,.T.);\r\n#9898=ORIENTED_EDGE('',*,*,#6067,.T.);\r\n#9899=EDGE_LOOP('',(#9894,#9895,#9897,#9898));\r\n#9900=FACE_OUTER_BOUND('',#9899,.F.);\r\n#9901=ADVANCED_FACE('',(#9900),#9892,.F.);\r\n#9902=CARTESIAN_POINT('',(1.95E1,2.E0,8.E0));\r\n#9903=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9904=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9905=AXIS2_PLACEMENT_3D('',#9902,#9903,#9904);\r\n#9906=PLANE('',#9905);\r\n#9907=ORIENTED_EDGE('',*,*,#9893,.T.);\r\n#9908=ORIENTED_EDGE('',*,*,#6065,.T.);\r\n#9909=ORIENTED_EDGE('',*,*,#9860,.F.);\r\n#9910=ORIENTED_EDGE('',*,*,#9873,.F.);\r\n#9911=EDGE_LOOP('',(#9907,#9908,#9909,#9910));\r\n#9912=FACE_OUTER_BOUND('',#9911,.F.);\r\n#9913=ADVANCED_FACE('',(#9912),#9906,.T.);\r\n#9914=CARTESIAN_POINT('',(1.95E1,9.5E0,8.E0));\r\n#9915=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9916=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9917=AXIS2_PLACEMENT_3D('',#9914,#9915,#9916);\r\n#9918=PLANE('',#9917);\r\n#9919=ORIENTED_EDGE('',*,*,#9896,.F.);\r\n#9920=ORIENTED_EDGE('',*,*,#9883,.F.);\r\n#9922=ORIENTED_EDGE('',*,*,#9921,.T.);\r\n#9923=ORIENTED_EDGE('',*,*,#6069,.T.);\r\n#9924=EDGE_LOOP('',(#9919,#9920,#9922,#9923));\r\n#9925=FACE_OUTER_BOUND('',#9924,.F.);\r\n#9926=ADVANCED_FACE('',(#9925),#9918,.T.);\r\n#9927=CARTESIAN_POINT('',(2.025E1,8.75E0,8.558891941783E0));\r\n#9928=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9929=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9930=AXIS2_PLACEMENT_3D('',#9927,#9928,#9929);\r\n#9931=CYLINDRICAL_SURFACE('',#9930,7.5E-1);\r\n#9932=ORIENTED_EDGE('',*,*,#9921,.F.);\r\n#9933=ORIENTED_EDGE('',*,*,#9881,.T.);\r\n#9935=ORIENTED_EDGE('',*,*,#9934,.T.);\r\n#9936=ORIENTED_EDGE('',*,*,#6071,.T.);\r\n#9937=EDGE_LOOP('',(#9932,#9933,#9935,#9936));\r\n#9938=FACE_OUTER_BOUND('',#9937,.F.);\r\n#9939=ADVANCED_FACE('',(#9938),#9931,.F.);\r\n#9940=CARTESIAN_POINT('',(2.125314193270E1,9.5E0,8.E0));\r\n#9941=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9942=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9943=AXIS2_PLACEMENT_3D('',#9940,#9941,#9942);\r\n#9944=PLANE('',#9943);\r\n#9946=ORIENTED_EDGE('',*,*,#9945,.T.);\r\n#9947=ORIENTED_EDGE('',*,*,#6073,.T.);\r\n#9948=ORIENTED_EDGE('',*,*,#9934,.F.);\r\n#9949=ORIENTED_EDGE('',*,*,#9879,.F.);\r\n#9950=EDGE_LOOP('',(#9946,#9947,#9948,#9949));\r\n#9951=FACE_OUTER_BOUND('',#9950,.F.);\r\n#9952=ADVANCED_FACE('',(#9951),#9944,.T.);\r\n#9953=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.558891941783E0));\r\n#9954=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9955=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#9956=AXIS2_PLACEMENT_3D('',#9953,#9954,#9955);\r\n#9957=CYLINDRICAL_SURFACE('',#9956,7.5E-1);\r\n#9958=ORIENTED_EDGE('',*,*,#9945,.F.);\r\n#9959=ORIENTED_EDGE('',*,*,#9877,.T.);\r\n#9960=ORIENTED_EDGE('',*,*,#9845,.T.);\r\n#9961=ORIENTED_EDGE('',*,*,#6075,.T.);\r\n#9962=EDGE_LOOP('',(#9958,#9959,#9960,#9961));\r\n#9963=FACE_OUTER_BOUND('',#9962,.F.);\r\n#9964=ADVANCED_FACE('',(#9963),#9957,.F.);\r\n#9965=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1));\r\n#9966=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#9967=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9968=AXIS2_PLACEMENT_3D('',#9965,#9966,#9967);\r\n#9969=PLANE('',#9968);\r\n#9970=ORIENTED_EDGE('',*,*,#5726,.F.);\r\n#9972=ORIENTED_EDGE('',*,*,#9971,.T.);\r\n#9974=ORIENTED_EDGE('',*,*,#9973,.T.);\r\n#9976=ORIENTED_EDGE('',*,*,#9975,.F.);\r\n#9977=EDGE_LOOP('',(#9970,#9972,#9974,#9976));\r\n#9978=FACE_OUTER_BOUND('',#9977,.F.);\r\n#9979=ADVANCED_FACE('',(#9978),#9969,.F.);\r\n#9980=CARTESIAN_POINT('',(7.5E0,0.E0,1.25E0));\r\n#9981=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#9982=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#9983=AXIS2_PLACEMENT_3D('',#9980,#9981,#9982);\r\n#9984=CYLINDRICAL_SURFACE('',#9983,5.625E-1);\r\n#9985=ORIENTED_EDGE('',*,*,#5732,.F.);\r\n#9987=ORIENTED_EDGE('',*,*,#9986,.T.);\r\n#9989=ORIENTED_EDGE('',*,*,#9988,.T.);\r\n#9990=ORIENTED_EDGE('',*,*,#9971,.F.);\r\n#9991=EDGE_LOOP('',(#9985,#9987,#9989,#9990));\r\n#9992=FACE_OUTER_BOUND('',#9991,.F.);\r\n#9993=ADVANCED_FACE('',(#9992),#9984,.F.);\r\n#9994=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0));\r\n#9995=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#9996=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#9997=AXIS2_PLACEMENT_3D('',#9994,#9995,#9996);\r\n#9998=PLANE('',#9997);\r\n#9999=ORIENTED_EDGE('',*,*,#5730,.F.);\r\n#10001=ORIENTED_EDGE('',*,*,#10000,.T.);\r\n#10003=ORIENTED_EDGE('',*,*,#10002,.T.);\r\n#10004=ORIENTED_EDGE('',*,*,#9986,.F.);\r\n#10005=EDGE_LOOP('',(#9999,#10001,#10003,#10004));\r\n#10006=FACE_OUTER_BOUND('',#10005,.F.);\r\n#10007=ADVANCED_FACE('',(#10006),#9998,.F.);\r\n#10008=CARTESIAN_POINT('',(1.05E1,0.E0,1.25E0));\r\n#10009=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10010=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10011=AXIS2_PLACEMENT_3D('',#10008,#10009,#10010);\r\n#10012=CYLINDRICAL_SURFACE('',#10011,5.625E-1);\r\n#10013=ORIENTED_EDGE('',*,*,#5728,.F.);\r\n#10014=ORIENTED_EDGE('',*,*,#9975,.T.);\r\n#10016=ORIENTED_EDGE('',*,*,#10015,.T.);\r\n#10017=ORIENTED_EDGE('',*,*,#10000,.F.);\r\n#10018=EDGE_LOOP('',(#10013,#10014,#10016,#10017));\r\n#10019=FACE_OUTER_BOUND('',#10018,.F.);\r\n#10020=ADVANCED_FACE('',(#10019),#10012,.F.);\r\n#10021=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10022=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10023=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10024=AXIS2_PLACEMENT_3D('',#10021,#10022,#10023);\r\n#10025=PLANE('',#10024);\r\n#10026=ORIENTED_EDGE('',*,*,#9973,.F.);\r\n#10027=ORIENTED_EDGE('',*,*,#9988,.F.);\r\n#10028=ORIENTED_EDGE('',*,*,#10002,.F.);\r\n#10029=ORIENTED_EDGE('',*,*,#10015,.F.);\r\n#10030=EDGE_LOOP('',(#10026,#10027,#10028,#10029));\r\n#10031=FACE_OUTER_BOUND('',#10030,.F.);\r\n#10032=ADVANCED_FACE('',(#10031),#10025,.T.);\r\n#10033=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10034=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10035=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10036=AXIS2_PLACEMENT_3D('',#10033,#10034,#10035);\r\n#10037=PLANE('',#10036);\r\n#10039=ORIENTED_EDGE('',*,*,#10038,.F.);\r\n#10041=ORIENTED_EDGE('',*,*,#10040,.F.);\r\n#10043=ORIENTED_EDGE('',*,*,#10042,.F.);\r\n#10045=ORIENTED_EDGE('',*,*,#10044,.F.);\r\n#10047=ORIENTED_EDGE('',*,*,#10046,.F.);\r\n#10048=EDGE_LOOP('',(#10039,#10041,#10043,#10045,#10047));\r\n#10049=FACE_OUTER_BOUND('',#10048,.F.);\r\n#10050=ADVANCED_FACE('',(#10049),#10037,.T.);\r\n#10051=CARTESIAN_POINT('',(1.455736763592E0,-6.892397422826E-2,\r\n4.577195232320E0));\r\n#10052=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10053=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#10054=AXIS2_PLACEMENT_3D('',#10051,#10052,#10053);\r\n#10055=CYLINDRICAL_SURFACE('',#10054,7.5E-1);\r\n#10057=ORIENTED_EDGE('',*,*,#10056,.F.);\r\n#10058=ORIENTED_EDGE('',*,*,#5738,.T.);\r\n#10060=ORIENTED_EDGE('',*,*,#10059,.T.);\r\n#10061=ORIENTED_EDGE('',*,*,#10038,.T.);\r\n#10062=EDGE_LOOP('',(#10057,#10058,#10060,#10061));\r\n#10063=FACE_OUTER_BOUND('',#10062,.F.);\r\n#10064=ADVANCED_FACE('',(#10063),#10055,.F.);\r\n#10065=CARTESIAN_POINT('',(6.875E-1,0.E0,4.284771824132E0));\r\n#10066=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#10067=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#10068=AXIS2_PLACEMENT_3D('',#10065,#10066,#10067);\r\n#10069=PLANE('',#10068);\r\n#10070=ORIENTED_EDGE('',*,*,#10056,.T.);\r\n#10071=ORIENTED_EDGE('',*,*,#10046,.T.);\r\n#10073=ORIENTED_EDGE('',*,*,#10072,.F.);\r\n#10074=ORIENTED_EDGE('',*,*,#5740,.F.);\r\n#10075=EDGE_LOOP('',(#10070,#10071,#10073,#10074));\r\n#10076=FACE_OUTER_BOUND('',#10075,.F.);\r\n#10077=ADVANCED_FACE('',(#10076),#10069,.F.);\r\n#10078=CARTESIAN_POINT('',(4.553039342392E0,0.E0,1.645354088550E0));\r\n#10079=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10080=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10081=AXIS2_PLACEMENT_3D('',#10078,#10079,#10080);\r\n#10082=CYLINDRICAL_SURFACE('',#10081,8.669989027347E-1);\r\n#10083=ORIENTED_EDGE('',*,*,#5742,.F.);\r\n#10084=ORIENTED_EDGE('',*,*,#10072,.T.);\r\n#10085=ORIENTED_EDGE('',*,*,#10044,.T.);\r\n#10087=ORIENTED_EDGE('',*,*,#10086,.F.);\r\n#10088=EDGE_LOOP('',(#10083,#10084,#10085,#10087));\r\n#10089=FACE_OUTER_BOUND('',#10088,.F.);\r\n#10090=ADVANCED_FACE('',(#10089),#10082,.F.);\r\n#10091=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0));\r\n#10092=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10093=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10094=AXIS2_PLACEMENT_3D('',#10091,#10092,#10093);\r\n#10095=CYLINDRICAL_SURFACE('',#10094,5.6875E0);\r\n#10096=ORIENTED_EDGE('',*,*,#5744,.T.);\r\n#10097=ORIENTED_EDGE('',*,*,#10086,.T.);\r\n#10098=ORIENTED_EDGE('',*,*,#10042,.T.);\r\n#10100=ORIENTED_EDGE('',*,*,#10099,.F.);\r\n#10101=EDGE_LOOP('',(#10096,#10097,#10098,#10100));\r\n#10102=FACE_OUTER_BOUND('',#10101,.F.);\r\n#10103=ADVANCED_FACE('',(#10102),#10095,.T.);\r\n#10104=CARTESIAN_POINT('',(1.61E0,0.E0,4.5E0));\r\n#10105=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10106=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10107=AXIS2_PLACEMENT_3D('',#10104,#10105,#10106);\r\n#10108=CYLINDRICAL_SURFACE('',#10107,9.225E-1);\r\n#10109=ORIENTED_EDGE('',*,*,#10059,.F.);\r\n#10110=ORIENTED_EDGE('',*,*,#5736,.F.);\r\n#10111=ORIENTED_EDGE('',*,*,#10099,.T.);\r\n#10112=ORIENTED_EDGE('',*,*,#10040,.T.);\r\n#10113=EDGE_LOOP('',(#10109,#10110,#10111,#10112));\r\n#10114=FACE_OUTER_BOUND('',#10113,.F.);\r\n#10115=ADVANCED_FACE('',(#10114),#10108,.F.);\r\n#10116=CARTESIAN_POINT('',(-1.85E-1,7.463919417831E-1,7.815E0));\r\n#10117=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10118=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10119=AXIS2_PLACEMENT_3D('',#10116,#10117,#10118);\r\n#10120=CYLINDRICAL_SURFACE('',#10119,8.75E-1);\r\n#10122=ORIENTED_EDGE('',*,*,#10121,.T.);\r\n#10123=ORIENTED_EDGE('',*,*,#5748,.T.);\r\n#10125=ORIENTED_EDGE('',*,*,#10124,.F.);\r\n#10127=ORIENTED_EDGE('',*,*,#10126,.T.);\r\n#10128=EDGE_LOOP('',(#10122,#10123,#10125,#10127));\r\n#10129=FACE_OUTER_BOUND('',#10128,.F.);\r\n#10130=ADVANCED_FACE('',(#10129),#10120,.T.);\r\n#10131=CARTESIAN_POINT('',(6.9E-1,0.E0,8.69E0));\r\n#10132=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10133=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10134=AXIS2_PLACEMENT_3D('',#10131,#10132,#10133);\r\n#10135=PLANE('',#10134);\r\n#10136=ORIENTED_EDGE('',*,*,#10121,.F.);\r\n#10138=ORIENTED_EDGE('',*,*,#10137,.T.);\r\n#10140=ORIENTED_EDGE('',*,*,#10139,.F.);\r\n#10141=ORIENTED_EDGE('',*,*,#5750,.F.);\r\n#10142=EDGE_LOOP('',(#10136,#10138,#10140,#10141));\r\n#10143=FACE_OUTER_BOUND('',#10142,.F.);\r\n#10144=ADVANCED_FACE('',(#10143),#10135,.F.);\r\n#10145=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10146=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10147=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10148=AXIS2_PLACEMENT_3D('',#10145,#10146,#10147);\r\n#10149=PLANE('',#10148);\r\n#10151=ORIENTED_EDGE('',*,*,#10150,.F.);\r\n#10153=ORIENTED_EDGE('',*,*,#10152,.F.);\r\n#10155=ORIENTED_EDGE('',*,*,#10154,.F.);\r\n#10157=ORIENTED_EDGE('',*,*,#10156,.F.);\r\n#10158=ORIENTED_EDGE('',*,*,#10137,.F.);\r\n#10159=ORIENTED_EDGE('',*,*,#10126,.F.);\r\n#10161=ORIENTED_EDGE('',*,*,#10160,.F.);\r\n#10163=ORIENTED_EDGE('',*,*,#10162,.F.);\r\n#10165=ORIENTED_EDGE('',*,*,#10164,.F.);\r\n#10167=ORIENTED_EDGE('',*,*,#10166,.F.);\r\n#10169=ORIENTED_EDGE('',*,*,#10168,.F.);\r\n#10171=ORIENTED_EDGE('',*,*,#10170,.F.);\r\n#10173=ORIENTED_EDGE('',*,*,#10172,.F.);\r\n#10175=ORIENTED_EDGE('',*,*,#10174,.F.);\r\n#10176=EDGE_LOOP('',(#10151,#10153,#10155,#10157,#10158,#10159,#10161,#10163,\r\n#10165,#10167,#10169,#10171,#10173,#10175));\r\n#10177=FACE_OUTER_BOUND('',#10176,.F.);\r\n#10178=ADVANCED_FACE('',(#10177),#10149,.T.);\r\n#10179=CARTESIAN_POINT('',(1.8125E0,0.E0,8.69E0));\r\n#10180=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10181=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10182=AXIS2_PLACEMENT_3D('',#10179,#10180,#10181);\r\n#10183=PLANE('',#10182);\r\n#10185=ORIENTED_EDGE('',*,*,#10184,.F.);\r\n#10186=ORIENTED_EDGE('',*,*,#10150,.T.);\r\n#10188=ORIENTED_EDGE('',*,*,#10187,.F.);\r\n#10189=ORIENTED_EDGE('',*,*,#5758,.F.);\r\n#10190=EDGE_LOOP('',(#10185,#10186,#10188,#10189));\r\n#10191=FACE_OUTER_BOUND('',#10190,.F.);\r\n#10192=ADVANCED_FACE('',(#10191),#10183,.F.);\r\n#10193=CARTESIAN_POINT('',(2.6875E0,7.463919417831E-1,7.815E0));\r\n#10194=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10195=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10196=AXIS2_PLACEMENT_3D('',#10193,#10194,#10195);\r\n#10197=CYLINDRICAL_SURFACE('',#10196,8.75E-1);\r\n#10198=ORIENTED_EDGE('',*,*,#10184,.T.);\r\n#10199=ORIENTED_EDGE('',*,*,#5756,.T.);\r\n#10201=ORIENTED_EDGE('',*,*,#10200,.F.);\r\n#10202=ORIENTED_EDGE('',*,*,#10152,.T.);\r\n#10203=EDGE_LOOP('',(#10198,#10199,#10201,#10202));\r\n#10204=FACE_OUTER_BOUND('',#10203,.F.);\r\n#10205=ADVANCED_FACE('',(#10204),#10197,.T.);\r\n#10206=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0));\r\n#10207=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10208=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10209=AXIS2_PLACEMENT_3D('',#10206,#10207,#10208);\r\n#10210=PLANE('',#10209);\r\n#10211=ORIENTED_EDGE('',*,*,#10200,.T.);\r\n#10212=ORIENTED_EDGE('',*,*,#5754,.F.);\r\n#10214=ORIENTED_EDGE('',*,*,#10213,.T.);\r\n#10215=ORIENTED_EDGE('',*,*,#10154,.T.);\r\n#10216=EDGE_LOOP('',(#10211,#10212,#10214,#10215));\r\n#10217=FACE_OUTER_BOUND('',#10216,.F.);\r\n#10218=ADVANCED_FACE('',(#10217),#10210,.F.);\r\n#10219=CARTESIAN_POINT('',(1.25125E0,0.E0,7.5E0));\r\n#10220=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10221=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10222=AXIS2_PLACEMENT_3D('',#10219,#10220,#10221);\r\n#10223=CYLINDRICAL_SURFACE('',#10222,5.6125E-1);\r\n#10224=ORIENTED_EDGE('',*,*,#5752,.F.);\r\n#10225=ORIENTED_EDGE('',*,*,#10139,.T.);\r\n#10226=ORIENTED_EDGE('',*,*,#10156,.T.);\r\n#10227=ORIENTED_EDGE('',*,*,#10213,.F.);\r\n#10228=EDGE_LOOP('',(#10224,#10225,#10226,#10227));\r\n#10229=FACE_OUTER_BOUND('',#10228,.F.);\r\n#10230=ADVANCED_FACE('',(#10229),#10223,.F.);\r\n#10231=CARTESIAN_POINT('',(3.4375E0,-6.892397422826E-2,9.565E0));\r\n#10232=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10233=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10234=AXIS2_PLACEMENT_3D('',#10231,#10232,#10233);\r\n#10235=CYLINDRICAL_SURFACE('',#10234,8.75E-1);\r\n#10237=ORIENTED_EDGE('',*,*,#10236,.F.);\r\n#10238=ORIENTED_EDGE('',*,*,#5760,.T.);\r\n#10239=ORIENTED_EDGE('',*,*,#10187,.T.);\r\n#10240=ORIENTED_EDGE('',*,*,#10174,.T.);\r\n#10241=EDGE_LOOP('',(#10237,#10238,#10239,#10240));\r\n#10242=FACE_OUTER_BOUND('',#10241,.F.);\r\n#10243=ADVANCED_FACE('',(#10242),#10235,.F.);\r\n#10244=CARTESIAN_POINT('',(4.3125E0,0.E0,8.69E0));\r\n#10245=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10246=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10247=AXIS2_PLACEMENT_3D('',#10244,#10245,#10246);\r\n#10248=PLANE('',#10247);\r\n#10249=ORIENTED_EDGE('',*,*,#10236,.T.);\r\n#10250=ORIENTED_EDGE('',*,*,#10172,.T.);\r\n#10252=ORIENTED_EDGE('',*,*,#10251,.F.);\r\n#10253=ORIENTED_EDGE('',*,*,#5762,.F.);\r\n#10254=EDGE_LOOP('',(#10249,#10250,#10252,#10253));\r\n#10255=FACE_OUTER_BOUND('',#10254,.F.);\r\n#10256=ADVANCED_FACE('',(#10255),#10248,.F.);\r\n#10257=CARTESIAN_POINT('',(3.4375E0,-6.892397422826E-2,1.0375E1));\r\n#10258=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10259=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10260=AXIS2_PLACEMENT_3D('',#10257,#10258,#10259);\r\n#10261=CYLINDRICAL_SURFACE('',#10260,8.75E-1);\r\n#10263=ORIENTED_EDGE('',*,*,#10262,.F.);\r\n#10264=ORIENTED_EDGE('',*,*,#5764,.T.);\r\n#10265=ORIENTED_EDGE('',*,*,#10251,.T.);\r\n#10266=ORIENTED_EDGE('',*,*,#10170,.T.);\r\n#10267=EDGE_LOOP('',(#10263,#10264,#10265,#10266));\r\n#10268=FACE_OUTER_BOUND('',#10267,.F.);\r\n#10269=ADVANCED_FACE('',(#10268),#10261,.F.);\r\n#10270=CARTESIAN_POINT('',(4.3125E0,0.E0,1.125E1));\r\n#10271=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10272=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10273=AXIS2_PLACEMENT_3D('',#10270,#10271,#10272);\r\n#10274=PLANE('',#10273);\r\n#10276=ORIENTED_EDGE('',*,*,#10275,.F.);\r\n#10277=ORIENTED_EDGE('',*,*,#5766,.F.);\r\n#10278=ORIENTED_EDGE('',*,*,#10262,.T.);\r\n#10279=ORIENTED_EDGE('',*,*,#10168,.T.);\r\n#10280=EDGE_LOOP('',(#10276,#10277,#10278,#10279));\r\n#10281=FACE_OUTER_BOUND('',#10280,.F.);\r\n#10282=ADVANCED_FACE('',(#10281),#10274,.F.);\r\n#10283=CARTESIAN_POINT('',(-4.375E-1,-6.892397422826E-2,1.0375E1));\r\n#10284=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10285=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10286=AXIS2_PLACEMENT_3D('',#10283,#10284,#10285);\r\n#10287=CYLINDRICAL_SURFACE('',#10286,8.75E-1);\r\n#10289=ORIENTED_EDGE('',*,*,#10288,.F.);\r\n#10290=ORIENTED_EDGE('',*,*,#5768,.T.);\r\n#10291=ORIENTED_EDGE('',*,*,#10275,.T.);\r\n#10292=ORIENTED_EDGE('',*,*,#10166,.T.);\r\n#10293=EDGE_LOOP('',(#10289,#10290,#10291,#10292));\r\n#10294=FACE_OUTER_BOUND('',#10293,.F.);\r\n#10295=ADVANCED_FACE('',(#10294),#10287,.F.);\r\n#10296=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.125E1));\r\n#10297=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10298=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10299=AXIS2_PLACEMENT_3D('',#10296,#10297,#10298);\r\n#10300=PLANE('',#10299);\r\n#10301=ORIENTED_EDGE('',*,*,#10288,.T.);\r\n#10302=ORIENTED_EDGE('',*,*,#10164,.T.);\r\n#10304=ORIENTED_EDGE('',*,*,#10303,.F.);\r\n#10305=ORIENTED_EDGE('',*,*,#5770,.F.);\r\n#10306=EDGE_LOOP('',(#10301,#10302,#10304,#10305));\r\n#10307=FACE_OUTER_BOUND('',#10306,.F.);\r\n#10308=ADVANCED_FACE('',(#10307),#10300,.F.);\r\n#10309=CARTESIAN_POINT('',(-4.375E-1,-6.892397422826E-2,9.565E0));\r\n#10310=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10311=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10312=AXIS2_PLACEMENT_3D('',#10309,#10310,#10311);\r\n#10313=CYLINDRICAL_SURFACE('',#10312,8.75E-1);\r\n#10315=ORIENTED_EDGE('',*,*,#10314,.F.);\r\n#10316=ORIENTED_EDGE('',*,*,#5772,.T.);\r\n#10317=ORIENTED_EDGE('',*,*,#10303,.T.);\r\n#10318=ORIENTED_EDGE('',*,*,#10162,.T.);\r\n#10319=EDGE_LOOP('',(#10315,#10316,#10317,#10318));\r\n#10320=FACE_OUTER_BOUND('',#10319,.F.);\r\n#10321=ADVANCED_FACE('',(#10320),#10313,.F.);\r\n#10322=CARTESIAN_POINT('',(-1.3125E0,0.E0,8.69E0));\r\n#10323=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10324=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10325=AXIS2_PLACEMENT_3D('',#10322,#10323,#10324);\r\n#10326=PLANE('',#10325);\r\n#10327=ORIENTED_EDGE('',*,*,#10124,.T.);\r\n#10328=ORIENTED_EDGE('',*,*,#5774,.F.);\r\n#10329=ORIENTED_EDGE('',*,*,#10314,.T.);\r\n#10330=ORIENTED_EDGE('',*,*,#10160,.T.);\r\n#10331=EDGE_LOOP('',(#10327,#10328,#10329,#10330));\r\n#10332=FACE_OUTER_BOUND('',#10331,.F.);\r\n#10333=ADVANCED_FACE('',(#10332),#10326,.F.);\r\n#10334=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1));\r\n#10335=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10336=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10337=AXIS2_PLACEMENT_3D('',#10334,#10335,#10336);\r\n#10338=PLANE('',#10337);\r\n#10339=ORIENTED_EDGE('',*,*,#5778,.F.);\r\n#10341=ORIENTED_EDGE('',*,*,#10340,.T.);\r\n#10343=ORIENTED_EDGE('',*,*,#10342,.T.);\r\n#10345=ORIENTED_EDGE('',*,*,#10344,.F.);\r\n#10346=EDGE_LOOP('',(#10339,#10341,#10343,#10345));\r\n#10347=FACE_OUTER_BOUND('',#10346,.F.);\r\n#10348=ADVANCED_FACE('',(#10347),#10338,.F.);\r\n#10349=CARTESIAN_POINT('',(1.25E0,0.E0,1.65E1));\r\n#10350=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10351=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10352=AXIS2_PLACEMENT_3D('',#10349,#10350,#10351);\r\n#10353=CYLINDRICAL_SURFACE('',#10352,5.625E-1);\r\n#10354=ORIENTED_EDGE('',*,*,#5784,.F.);\r\n#10356=ORIENTED_EDGE('',*,*,#10355,.T.);\r\n#10358=ORIENTED_EDGE('',*,*,#10357,.T.);\r\n#10359=ORIENTED_EDGE('',*,*,#10340,.F.);\r\n#10360=EDGE_LOOP('',(#10354,#10356,#10358,#10359));\r\n#10361=FACE_OUTER_BOUND('',#10360,.F.);\r\n#10362=ADVANCED_FACE('',(#10361),#10353,.F.);\r\n#10363=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1));\r\n#10364=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10365=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10366=AXIS2_PLACEMENT_3D('',#10363,#10364,#10365);\r\n#10367=PLANE('',#10366);\r\n#10368=ORIENTED_EDGE('',*,*,#5782,.F.);\r\n#10370=ORIENTED_EDGE('',*,*,#10369,.T.);\r\n#10372=ORIENTED_EDGE('',*,*,#10371,.T.);\r\n#10373=ORIENTED_EDGE('',*,*,#10355,.F.);\r\n#10374=EDGE_LOOP('',(#10368,#10370,#10372,#10373));\r\n#10375=FACE_OUTER_BOUND('',#10374,.F.);\r\n#10376=ADVANCED_FACE('',(#10375),#10367,.F.);\r\n#10377=CARTESIAN_POINT('',(1.25E0,0.E0,1.35E1));\r\n#10378=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10379=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10380=AXIS2_PLACEMENT_3D('',#10377,#10378,#10379);\r\n#10381=CYLINDRICAL_SURFACE('',#10380,5.625E-1);\r\n#10382=ORIENTED_EDGE('',*,*,#5780,.F.);\r\n#10383=ORIENTED_EDGE('',*,*,#10344,.T.);\r\n#10385=ORIENTED_EDGE('',*,*,#10384,.T.);\r\n#10386=ORIENTED_EDGE('',*,*,#10369,.F.);\r\n#10387=EDGE_LOOP('',(#10382,#10383,#10385,#10386));\r\n#10388=FACE_OUTER_BOUND('',#10387,.F.);\r\n#10389=ADVANCED_FACE('',(#10388),#10381,.F.);\r\n#10390=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10391=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10392=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10393=AXIS2_PLACEMENT_3D('',#10390,#10391,#10392);\r\n#10394=PLANE('',#10393);\r\n#10395=ORIENTED_EDGE('',*,*,#10342,.F.);\r\n#10396=ORIENTED_EDGE('',*,*,#10357,.F.);\r\n#10397=ORIENTED_EDGE('',*,*,#10371,.F.);\r\n#10398=ORIENTED_EDGE('',*,*,#10384,.F.);\r\n#10399=EDGE_LOOP('',(#10395,#10396,#10397,#10398));\r\n#10400=FACE_OUTER_BOUND('',#10399,.F.);\r\n#10401=ADVANCED_FACE('',(#10400),#10394,.T.);\r\n#10402=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1));\r\n#10403=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10404=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10405=AXIS2_PLACEMENT_3D('',#10402,#10403,#10404);\r\n#10406=PLANE('',#10405);\r\n#10407=ORIENTED_EDGE('',*,*,#5788,.F.);\r\n#10409=ORIENTED_EDGE('',*,*,#10408,.T.);\r\n#10411=ORIENTED_EDGE('',*,*,#10410,.T.);\r\n#10413=ORIENTED_EDGE('',*,*,#10412,.F.);\r\n#10414=EDGE_LOOP('',(#10407,#10409,#10411,#10413));\r\n#10415=FACE_OUTER_BOUND('',#10414,.F.);\r\n#10416=ADVANCED_FACE('',(#10415),#10406,.F.);\r\n#10417=CARTESIAN_POINT('',(1.25E0,0.E0,2.25E1));\r\n#10418=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10419=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10420=AXIS2_PLACEMENT_3D('',#10417,#10418,#10419);\r\n#10421=CYLINDRICAL_SURFACE('',#10420,5.625E-1);\r\n#10422=ORIENTED_EDGE('',*,*,#5794,.F.);\r\n#10424=ORIENTED_EDGE('',*,*,#10423,.T.);\r\n#10426=ORIENTED_EDGE('',*,*,#10425,.T.);\r\n#10427=ORIENTED_EDGE('',*,*,#10408,.F.);\r\n#10428=EDGE_LOOP('',(#10422,#10424,#10426,#10427));\r\n#10429=FACE_OUTER_BOUND('',#10428,.F.);\r\n#10430=ADVANCED_FACE('',(#10429),#10421,.F.);\r\n#10431=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1));\r\n#10432=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10433=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10434=AXIS2_PLACEMENT_3D('',#10431,#10432,#10433);\r\n#10435=PLANE('',#10434);\r\n#10436=ORIENTED_EDGE('',*,*,#5792,.F.);\r\n#10438=ORIENTED_EDGE('',*,*,#10437,.T.);\r\n#10440=ORIENTED_EDGE('',*,*,#10439,.T.);\r\n#10441=ORIENTED_EDGE('',*,*,#10423,.F.);\r\n#10442=EDGE_LOOP('',(#10436,#10438,#10440,#10441));\r\n#10443=FACE_OUTER_BOUND('',#10442,.F.);\r\n#10444=ADVANCED_FACE('',(#10443),#10435,.F.);\r\n#10445=CARTESIAN_POINT('',(1.25E0,0.E0,1.95E1));\r\n#10446=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10447=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10448=AXIS2_PLACEMENT_3D('',#10445,#10446,#10447);\r\n#10449=CYLINDRICAL_SURFACE('',#10448,5.625E-1);\r\n#10450=ORIENTED_EDGE('',*,*,#5790,.F.);\r\n#10451=ORIENTED_EDGE('',*,*,#10412,.T.);\r\n#10453=ORIENTED_EDGE('',*,*,#10452,.T.);\r\n#10454=ORIENTED_EDGE('',*,*,#10437,.F.);\r\n#10455=EDGE_LOOP('',(#10450,#10451,#10453,#10454));\r\n#10456=FACE_OUTER_BOUND('',#10455,.F.);\r\n#10457=ADVANCED_FACE('',(#10456),#10449,.F.);\r\n#10458=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10459=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10460=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10461=AXIS2_PLACEMENT_3D('',#10458,#10459,#10460);\r\n#10462=PLANE('',#10461);\r\n#10463=ORIENTED_EDGE('',*,*,#10410,.F.);\r\n#10464=ORIENTED_EDGE('',*,*,#10425,.F.);\r\n#10465=ORIENTED_EDGE('',*,*,#10439,.F.);\r\n#10466=ORIENTED_EDGE('',*,*,#10452,.F.);\r\n#10467=EDGE_LOOP('',(#10463,#10464,#10465,#10466));\r\n#10468=FACE_OUTER_BOUND('',#10467,.F.);\r\n#10469=ADVANCED_FACE('',(#10468),#10462,.T.);\r\n#10470=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0));\r\n#10471=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10472=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10473=AXIS2_PLACEMENT_3D('',#10470,#10471,#10472);\r\n#10474=PLANE('',#10473);\r\n#10475=ORIENTED_EDGE('',*,*,#5798,.F.);\r\n#10477=ORIENTED_EDGE('',*,*,#10476,.T.);\r\n#10479=ORIENTED_EDGE('',*,*,#10478,.T.);\r\n#10481=ORIENTED_EDGE('',*,*,#10480,.F.);\r\n#10482=EDGE_LOOP('',(#10475,#10477,#10479,#10481));\r\n#10483=FACE_OUTER_BOUND('',#10482,.F.);\r\n#10484=ADVANCED_FACE('',(#10483),#10474,.F.);\r\n#10485=CARTESIAN_POINT('',(7.5E0,0.E0,9.E0));\r\n#10486=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10487=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10488=AXIS2_PLACEMENT_3D('',#10485,#10486,#10487);\r\n#10489=CYLINDRICAL_SURFACE('',#10488,5.E-1);\r\n#10490=ORIENTED_EDGE('',*,*,#5804,.F.);\r\n#10492=ORIENTED_EDGE('',*,*,#10491,.T.);\r\n#10494=ORIENTED_EDGE('',*,*,#10493,.T.);\r\n#10495=ORIENTED_EDGE('',*,*,#10476,.F.);\r\n#10496=EDGE_LOOP('',(#10490,#10492,#10494,#10495));\r\n#10497=FACE_OUTER_BOUND('',#10496,.F.);\r\n#10498=ADVANCED_FACE('',(#10497),#10489,.F.);\r\n#10499=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0));\r\n#10500=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10501=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10502=AXIS2_PLACEMENT_3D('',#10499,#10500,#10501);\r\n#10503=PLANE('',#10502);\r\n#10504=ORIENTED_EDGE('',*,*,#5802,.F.);\r\n#10506=ORIENTED_EDGE('',*,*,#10505,.T.);\r\n#10508=ORIENTED_EDGE('',*,*,#10507,.T.);\r\n#10509=ORIENTED_EDGE('',*,*,#10491,.F.);\r\n#10510=EDGE_LOOP('',(#10504,#10506,#10508,#10509));\r\n#10511=FACE_OUTER_BOUND('',#10510,.F.);\r\n#10512=ADVANCED_FACE('',(#10511),#10503,.F.);\r\n#10513=CARTESIAN_POINT('',(1.05E1,0.E0,9.E0));\r\n#10514=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10515=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10516=AXIS2_PLACEMENT_3D('',#10513,#10514,#10515);\r\n#10517=CYLINDRICAL_SURFACE('',#10516,5.E-1);\r\n#10518=ORIENTED_EDGE('',*,*,#5800,.F.);\r\n#10519=ORIENTED_EDGE('',*,*,#10480,.T.);\r\n#10521=ORIENTED_EDGE('',*,*,#10520,.T.);\r\n#10522=ORIENTED_EDGE('',*,*,#10505,.F.);\r\n#10523=EDGE_LOOP('',(#10518,#10519,#10521,#10522));\r\n#10524=FACE_OUTER_BOUND('',#10523,.F.);\r\n#10525=ADVANCED_FACE('',(#10524),#10517,.F.);\r\n#10526=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10527=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10528=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10529=AXIS2_PLACEMENT_3D('',#10526,#10527,#10528);\r\n#10530=PLANE('',#10529);\r\n#10531=ORIENTED_EDGE('',*,*,#10478,.F.);\r\n#10532=ORIENTED_EDGE('',*,*,#10493,.F.);\r\n#10533=ORIENTED_EDGE('',*,*,#10507,.F.);\r\n#10534=ORIENTED_EDGE('',*,*,#10520,.F.);\r\n#10535=EDGE_LOOP('',(#10531,#10532,#10533,#10534));\r\n#10536=FACE_OUTER_BOUND('',#10535,.F.);\r\n#10537=ADVANCED_FACE('',(#10536),#10530,.T.);\r\n#10538=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1));\r\n#10539=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10540=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10541=AXIS2_PLACEMENT_3D('',#10538,#10539,#10540);\r\n#10542=PLANE('',#10541);\r\n#10543=ORIENTED_EDGE('',*,*,#5808,.F.);\r\n#10545=ORIENTED_EDGE('',*,*,#10544,.T.);\r\n#10547=ORIENTED_EDGE('',*,*,#10546,.T.);\r\n#10549=ORIENTED_EDGE('',*,*,#10548,.F.);\r\n#10550=EDGE_LOOP('',(#10543,#10545,#10547,#10549));\r\n#10551=FACE_OUTER_BOUND('',#10550,.F.);\r\n#10552=ADVANCED_FACE('',(#10551),#10542,.F.);\r\n#10553=CARTESIAN_POINT('',(7.5E0,0.E0,1.8E1));\r\n#10554=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10555=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10556=AXIS2_PLACEMENT_3D('',#10553,#10554,#10555);\r\n#10557=CYLINDRICAL_SURFACE('',#10556,4.375E-1);\r\n#10558=ORIENTED_EDGE('',*,*,#5814,.F.);\r\n#10560=ORIENTED_EDGE('',*,*,#10559,.T.);\r\n#10562=ORIENTED_EDGE('',*,*,#10561,.T.);\r\n#10563=ORIENTED_EDGE('',*,*,#10544,.F.);\r\n#10564=EDGE_LOOP('',(#10558,#10560,#10562,#10563));\r\n#10565=FACE_OUTER_BOUND('',#10564,.F.);\r\n#10566=ADVANCED_FACE('',(#10565),#10557,.F.);\r\n#10567=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1));\r\n#10568=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10569=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10570=AXIS2_PLACEMENT_3D('',#10567,#10568,#10569);\r\n#10571=PLANE('',#10570);\r\n#10572=ORIENTED_EDGE('',*,*,#5812,.F.);\r\n#10574=ORIENTED_EDGE('',*,*,#10573,.T.);\r\n#10576=ORIENTED_EDGE('',*,*,#10575,.T.);\r\n#10577=ORIENTED_EDGE('',*,*,#10559,.F.);\r\n#10578=EDGE_LOOP('',(#10572,#10574,#10576,#10577));\r\n#10579=FACE_OUTER_BOUND('',#10578,.F.);\r\n#10580=ADVANCED_FACE('',(#10579),#10571,.F.);\r\n#10581=CARTESIAN_POINT('',(1.05E1,0.E0,1.8E1));\r\n#10582=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10583=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10584=AXIS2_PLACEMENT_3D('',#10581,#10582,#10583);\r\n#10585=CYLINDRICAL_SURFACE('',#10584,4.375E-1);\r\n#10586=ORIENTED_EDGE('',*,*,#5810,.F.);\r\n#10587=ORIENTED_EDGE('',*,*,#10548,.T.);\r\n#10589=ORIENTED_EDGE('',*,*,#10588,.T.);\r\n#10590=ORIENTED_EDGE('',*,*,#10573,.F.);\r\n#10591=EDGE_LOOP('',(#10586,#10587,#10589,#10590));\r\n#10592=FACE_OUTER_BOUND('',#10591,.F.);\r\n#10593=ADVANCED_FACE('',(#10592),#10585,.F.);\r\n#10594=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0));\r\n#10595=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#10596=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10597=AXIS2_PLACEMENT_3D('',#10594,#10595,#10596);\r\n#10598=PLANE('',#10597);\r\n#10599=ORIENTED_EDGE('',*,*,#10546,.F.);\r\n#10600=ORIENTED_EDGE('',*,*,#10561,.F.);\r\n#10601=ORIENTED_EDGE('',*,*,#10575,.F.);\r\n#10602=ORIENTED_EDGE('',*,*,#10588,.F.);\r\n#10603=EDGE_LOOP('',(#10599,#10600,#10601,#10602));\r\n#10604=FACE_OUTER_BOUND('',#10603,.F.);\r\n#10605=ADVANCED_FACE('',(#10604),#10598,.T.);\r\n#10606=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1));\r\n#10607=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10608=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10609=AXIS2_PLACEMENT_3D('',#10606,#10607,#10608);\r\n#10610=PLANE('',#10609);\r\n#10611=ORIENTED_EDGE('',*,*,#5818,.T.);\r\n#10613=ORIENTED_EDGE('',*,*,#10612,.T.);\r\n#10615=ORIENTED_EDGE('',*,*,#10614,.F.);\r\n#10617=ORIENTED_EDGE('',*,*,#10616,.F.);\r\n#10618=EDGE_LOOP('',(#10611,#10613,#10615,#10617));\r\n#10619=FACE_OUTER_BOUND('',#10618,.F.);\r\n#10620=ADVANCED_FACE('',(#10619),#10610,.T.);\r\n#10621=CARTESIAN_POINT('',(1.05E1,0.E0,3.075E1));\r\n#10622=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10623=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10624=AXIS2_PLACEMENT_3D('',#10621,#10622,#10623);\r\n#10625=CYLINDRICAL_SURFACE('',#10624,5.625E-1);\r\n#10626=ORIENTED_EDGE('',*,*,#5824,.T.);\r\n#10628=ORIENTED_EDGE('',*,*,#10627,.T.);\r\n#10630=ORIENTED_EDGE('',*,*,#10629,.F.);\r\n#10631=ORIENTED_EDGE('',*,*,#10612,.F.);\r\n#10632=EDGE_LOOP('',(#10626,#10628,#10630,#10631));\r\n#10633=FACE_OUTER_BOUND('',#10632,.F.);\r\n#10634=ADVANCED_FACE('',(#10633),#10625,.F.);\r\n#10635=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1));\r\n#10636=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10637=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10638=AXIS2_PLACEMENT_3D('',#10635,#10636,#10637);\r\n#10639=PLANE('',#10638);\r\n#10640=ORIENTED_EDGE('',*,*,#5822,.T.);\r\n#10642=ORIENTED_EDGE('',*,*,#10641,.T.);\r\n#10644=ORIENTED_EDGE('',*,*,#10643,.F.);\r\n#10645=ORIENTED_EDGE('',*,*,#10627,.F.);\r\n#10646=EDGE_LOOP('',(#10640,#10642,#10644,#10645));\r\n#10647=FACE_OUTER_BOUND('',#10646,.F.);\r\n#10648=ADVANCED_FACE('',(#10647),#10639,.T.);\r\n#10649=CARTESIAN_POINT('',(7.5E0,0.E0,3.075E1));\r\n#10650=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10651=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10652=AXIS2_PLACEMENT_3D('',#10649,#10650,#10651);\r\n#10653=CYLINDRICAL_SURFACE('',#10652,5.625E-1);\r\n#10654=ORIENTED_EDGE('',*,*,#5820,.T.);\r\n#10655=ORIENTED_EDGE('',*,*,#10616,.T.);\r\n#10657=ORIENTED_EDGE('',*,*,#10656,.F.);\r\n#10658=ORIENTED_EDGE('',*,*,#10641,.F.);\r\n#10659=EDGE_LOOP('',(#10654,#10655,#10657,#10658));\r\n#10660=FACE_OUTER_BOUND('',#10659,.F.);\r\n#10661=ADVANCED_FACE('',(#10660),#10653,.F.);\r\n#10662=CARTESIAN_POINT('',(0.E0,6.875E-1,3.2E1));\r\n#10663=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10664=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10665=AXIS2_PLACEMENT_3D('',#10662,#10663,#10664);\r\n#10666=PLANE('',#10665);\r\n#10667=ORIENTED_EDGE('',*,*,#10614,.T.);\r\n#10668=ORIENTED_EDGE('',*,*,#10629,.T.);\r\n#10669=ORIENTED_EDGE('',*,*,#10643,.T.);\r\n#10670=ORIENTED_EDGE('',*,*,#10656,.T.);\r\n#10671=EDGE_LOOP('',(#10667,#10668,#10669,#10670));\r\n#10672=FACE_OUTER_BOUND('',#10671,.F.);\r\n#10673=ADVANCED_FACE('',(#10672),#10666,.F.);\r\n#10674=CARTESIAN_POINT('',(0.E0,6.875E-1,3.2E1));\r\n#10675=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10676=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10677=AXIS2_PLACEMENT_3D('',#10674,#10675,#10676);\r\n#10678=PLANE('',#10677);\r\n#10680=ORIENTED_EDGE('',*,*,#10679,.F.);\r\n#10682=ORIENTED_EDGE('',*,*,#10681,.T.);\r\n#10684=ORIENTED_EDGE('',*,*,#10683,.T.);\r\n#10686=ORIENTED_EDGE('',*,*,#10685,.T.);\r\n#10688=ORIENTED_EDGE('',*,*,#10687,.T.);\r\n#10689=EDGE_LOOP('',(#10680,#10682,#10684,#10686,#10688));\r\n#10690=FACE_OUTER_BOUND('',#10689,.F.);\r\n#10691=ADVANCED_FACE('',(#10690),#10678,.F.);\r\n#10692=CARTESIAN_POINT('',(1.455736763592E0,-6.642389448824E-2,\r\n2.742280476768E1));\r\n#10693=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10694=DIRECTION('',(-8.942796313519E-1,0.E0,-4.475085931567E-1));\r\n#10695=AXIS2_PLACEMENT_3D('',#10692,#10693,#10694);\r\n#10696=CYLINDRICAL_SURFACE('',#10695,7.5E-1);\r\n#10698=ORIENTED_EDGE('',*,*,#10697,.F.);\r\n#10699=ORIENTED_EDGE('',*,*,#5932,.T.);\r\n#10701=ORIENTED_EDGE('',*,*,#10700,.T.);\r\n#10702=ORIENTED_EDGE('',*,*,#10679,.T.);\r\n#10703=EDGE_LOOP('',(#10698,#10699,#10701,#10702));\r\n#10704=FACE_OUTER_BOUND('',#10703,.F.);\r\n#10705=ADVANCED_FACE('',(#10704),#10696,.F.);\r\n#10706=CARTESIAN_POINT('',(1.61E0,0.E0,2.75E1));\r\n#10707=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10708=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10709=AXIS2_PLACEMENT_3D('',#10706,#10707,#10708);\r\n#10710=CYLINDRICAL_SURFACE('',#10709,9.225E-1);\r\n#10711=ORIENTED_EDGE('',*,*,#10697,.T.);\r\n#10712=ORIENTED_EDGE('',*,*,#10687,.F.);\r\n#10714=ORIENTED_EDGE('',*,*,#10713,.F.);\r\n#10715=ORIENTED_EDGE('',*,*,#5934,.T.);\r\n#10716=EDGE_LOOP('',(#10711,#10712,#10714,#10715));\r\n#10717=FACE_OUTER_BOUND('',#10716,.F.);\r\n#10718=ADVANCED_FACE('',(#10717),#10710,.F.);\r\n#10719=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1));\r\n#10720=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10721=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10722=AXIS2_PLACEMENT_3D('',#10719,#10720,#10721);\r\n#10723=CYLINDRICAL_SURFACE('',#10722,5.6875E0);\r\n#10724=ORIENTED_EDGE('',*,*,#5936,.F.);\r\n#10725=ORIENTED_EDGE('',*,*,#10713,.T.);\r\n#10726=ORIENTED_EDGE('',*,*,#10685,.F.);\r\n#10728=ORIENTED_EDGE('',*,*,#10727,.F.);\r\n#10729=EDGE_LOOP('',(#10724,#10725,#10726,#10728));\r\n#10730=FACE_OUTER_BOUND('',#10729,.F.);\r\n#10731=ADVANCED_FACE('',(#10730),#10723,.T.);\r\n#10732=CARTESIAN_POINT('',(4.553039342392E0,0.E0,3.035464591145E1));\r\n#10733=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10734=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10735=AXIS2_PLACEMENT_3D('',#10732,#10733,#10734);\r\n#10736=CYLINDRICAL_SURFACE('',#10735,8.669989027347E-1);\r\n#10737=ORIENTED_EDGE('',*,*,#5938,.T.);\r\n#10738=ORIENTED_EDGE('',*,*,#10727,.T.);\r\n#10739=ORIENTED_EDGE('',*,*,#10683,.F.);\r\n#10741=ORIENTED_EDGE('',*,*,#10740,.F.);\r\n#10742=EDGE_LOOP('',(#10737,#10738,#10739,#10741));\r\n#10743=FACE_OUTER_BOUND('',#10742,.F.);\r\n#10744=ADVANCED_FACE('',(#10743),#10736,.F.);\r\n#10745=CARTESIAN_POINT('',(6.875E-1,0.E0,2.771522817587E1));\r\n#10746=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#10747=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#10748=AXIS2_PLACEMENT_3D('',#10745,#10746,#10747);\r\n#10749=PLANE('',#10748);\r\n#10750=ORIENTED_EDGE('',*,*,#10700,.F.);\r\n#10751=ORIENTED_EDGE('',*,*,#5930,.T.);\r\n#10752=ORIENTED_EDGE('',*,*,#10740,.T.);\r\n#10753=ORIENTED_EDGE('',*,*,#10681,.F.);\r\n#10754=EDGE_LOOP('',(#10750,#10751,#10752,#10753));\r\n#10755=FACE_OUTER_BOUND('',#10754,.F.);\r\n#10756=ADVANCED_FACE('',(#10755),#10749,.T.);\r\n#10757=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1));\r\n#10758=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10759=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10760=AXIS2_PLACEMENT_3D('',#10757,#10758,#10759);\r\n#10761=PLANE('',#10760);\r\n#10762=ORIENTED_EDGE('',*,*,#5828,.T.);\r\n#10764=ORIENTED_EDGE('',*,*,#10763,.T.);\r\n#10766=ORIENTED_EDGE('',*,*,#10765,.F.);\r\n#10768=ORIENTED_EDGE('',*,*,#10767,.F.);\r\n#10769=EDGE_LOOP('',(#10762,#10764,#10766,#10768));\r\n#10770=FACE_OUTER_BOUND('',#10769,.F.);\r\n#10771=ADVANCED_FACE('',(#10770),#10761,.T.);\r\n#10772=CARTESIAN_POINT('',(1.35E1,0.E0,1.25E0));\r\n#10773=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10774=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10775=AXIS2_PLACEMENT_3D('',#10772,#10773,#10774);\r\n#10776=CYLINDRICAL_SURFACE('',#10775,5.625E-1);\r\n#10777=ORIENTED_EDGE('',*,*,#5834,.T.);\r\n#10779=ORIENTED_EDGE('',*,*,#10778,.T.);\r\n#10781=ORIENTED_EDGE('',*,*,#10780,.F.);\r\n#10782=ORIENTED_EDGE('',*,*,#10763,.F.);\r\n#10783=EDGE_LOOP('',(#10777,#10779,#10781,#10782));\r\n#10784=FACE_OUTER_BOUND('',#10783,.F.);\r\n#10785=ADVANCED_FACE('',(#10784),#10776,.F.);\r\n#10786=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0));\r\n#10787=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10788=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10789=AXIS2_PLACEMENT_3D('',#10786,#10787,#10788);\r\n#10790=PLANE('',#10789);\r\n#10791=ORIENTED_EDGE('',*,*,#5832,.T.);\r\n#10793=ORIENTED_EDGE('',*,*,#10792,.T.);\r\n#10795=ORIENTED_EDGE('',*,*,#10794,.F.);\r\n#10796=ORIENTED_EDGE('',*,*,#10778,.F.);\r\n#10797=EDGE_LOOP('',(#10791,#10793,#10795,#10796));\r\n#10798=FACE_OUTER_BOUND('',#10797,.F.);\r\n#10799=ADVANCED_FACE('',(#10798),#10790,.T.);\r\n#10800=CARTESIAN_POINT('',(1.65E1,0.E0,1.25E0));\r\n#10801=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10802=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10803=AXIS2_PLACEMENT_3D('',#10800,#10801,#10802);\r\n#10804=CYLINDRICAL_SURFACE('',#10803,5.625E-1);\r\n#10805=ORIENTED_EDGE('',*,*,#5830,.T.);\r\n#10806=ORIENTED_EDGE('',*,*,#10767,.T.);\r\n#10808=ORIENTED_EDGE('',*,*,#10807,.F.);\r\n#10809=ORIENTED_EDGE('',*,*,#10792,.F.);\r\n#10810=EDGE_LOOP('',(#10805,#10806,#10808,#10809));\r\n#10811=FACE_OUTER_BOUND('',#10810,.F.);\r\n#10812=ADVANCED_FACE('',(#10811),#10804,.F.);\r\n#10813=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#10814=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10815=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10816=AXIS2_PLACEMENT_3D('',#10813,#10814,#10815);\r\n#10817=PLANE('',#10816);\r\n#10818=ORIENTED_EDGE('',*,*,#10765,.T.);\r\n#10819=ORIENTED_EDGE('',*,*,#10780,.T.);\r\n#10820=ORIENTED_EDGE('',*,*,#10794,.T.);\r\n#10821=ORIENTED_EDGE('',*,*,#10807,.T.);\r\n#10822=EDGE_LOOP('',(#10818,#10819,#10820,#10821));\r\n#10823=FACE_OUTER_BOUND('',#10822,.F.);\r\n#10824=ADVANCED_FACE('',(#10823),#10817,.F.);\r\n#10825=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#10826=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10827=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10828=AXIS2_PLACEMENT_3D('',#10825,#10826,#10827);\r\n#10829=PLANE('',#10828);\r\n#10831=ORIENTED_EDGE('',*,*,#10830,.F.);\r\n#10833=ORIENTED_EDGE('',*,*,#10832,.T.);\r\n#10835=ORIENTED_EDGE('',*,*,#10834,.T.);\r\n#10837=ORIENTED_EDGE('',*,*,#10836,.T.);\r\n#10839=ORIENTED_EDGE('',*,*,#10838,.T.);\r\n#10840=EDGE_LOOP('',(#10831,#10833,#10835,#10837,#10839));\r\n#10841=FACE_OUTER_BOUND('',#10840,.F.);\r\n#10842=ADVANCED_FACE('',(#10841),#10829,.F.);\r\n#10843=CARTESIAN_POINT('',(2.254426323641E1,-6.642389448824E-2,\r\n4.577195232320E0));\r\n#10844=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10845=DIRECTION('',(8.942796313519E-1,0.E0,4.475085931567E-1));\r\n#10846=AXIS2_PLACEMENT_3D('',#10843,#10844,#10845);\r\n#10847=CYLINDRICAL_SURFACE('',#10846,7.5E-1);\r\n#10849=ORIENTED_EDGE('',*,*,#10848,.F.);\r\n#10850=ORIENTED_EDGE('',*,*,#5920,.T.);\r\n#10852=ORIENTED_EDGE('',*,*,#10851,.T.);\r\n#10853=ORIENTED_EDGE('',*,*,#10830,.T.);\r\n#10854=EDGE_LOOP('',(#10849,#10850,#10852,#10853));\r\n#10855=FACE_OUTER_BOUND('',#10854,.F.);\r\n#10856=ADVANCED_FACE('',(#10855),#10847,.F.);\r\n#10857=CARTESIAN_POINT('',(2.239E1,0.E0,4.5E0));\r\n#10858=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10859=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10860=AXIS2_PLACEMENT_3D('',#10857,#10858,#10859);\r\n#10861=CYLINDRICAL_SURFACE('',#10860,9.225E-1);\r\n#10862=ORIENTED_EDGE('',*,*,#10848,.T.);\r\n#10863=ORIENTED_EDGE('',*,*,#10838,.F.);\r\n#10865=ORIENTED_EDGE('',*,*,#10864,.F.);\r\n#10866=ORIENTED_EDGE('',*,*,#5922,.T.);\r\n#10867=EDGE_LOOP('',(#10862,#10863,#10865,#10866));\r\n#10868=FACE_OUTER_BOUND('',#10867,.F.);\r\n#10869=ADVANCED_FACE('',(#10868),#10861,.F.);\r\n#10870=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0));\r\n#10871=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10872=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10873=AXIS2_PLACEMENT_3D('',#10870,#10871,#10872);\r\n#10874=CYLINDRICAL_SURFACE('',#10873,5.6875E0);\r\n#10875=ORIENTED_EDGE('',*,*,#5924,.F.);\r\n#10876=ORIENTED_EDGE('',*,*,#10864,.T.);\r\n#10877=ORIENTED_EDGE('',*,*,#10836,.F.);\r\n#10879=ORIENTED_EDGE('',*,*,#10878,.F.);\r\n#10880=EDGE_LOOP('',(#10875,#10876,#10877,#10879));\r\n#10881=FACE_OUTER_BOUND('',#10880,.F.);\r\n#10882=ADVANCED_FACE('',(#10881),#10874,.T.);\r\n#10883=CARTESIAN_POINT('',(1.944696065761E1,0.E0,1.645354088550E0));\r\n#10884=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10885=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10886=AXIS2_PLACEMENT_3D('',#10883,#10884,#10885);\r\n#10887=CYLINDRICAL_SURFACE('',#10886,8.669989027347E-1);\r\n#10888=ORIENTED_EDGE('',*,*,#5926,.T.);\r\n#10889=ORIENTED_EDGE('',*,*,#10878,.T.);\r\n#10890=ORIENTED_EDGE('',*,*,#10834,.F.);\r\n#10892=ORIENTED_EDGE('',*,*,#10891,.F.);\r\n#10893=EDGE_LOOP('',(#10888,#10889,#10890,#10892));\r\n#10894=FACE_OUTER_BOUND('',#10893,.F.);\r\n#10895=ADVANCED_FACE('',(#10894),#10887,.F.);\r\n#10896=CARTESIAN_POINT('',(2.33125E1,0.E0,4.284771824132E0));\r\n#10897=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#10898=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1));\r\n#10899=AXIS2_PLACEMENT_3D('',#10896,#10897,#10898);\r\n#10900=PLANE('',#10899);\r\n#10901=ORIENTED_EDGE('',*,*,#10851,.F.);\r\n#10902=ORIENTED_EDGE('',*,*,#5918,.T.);\r\n#10903=ORIENTED_EDGE('',*,*,#10891,.T.);\r\n#10904=ORIENTED_EDGE('',*,*,#10832,.F.);\r\n#10905=EDGE_LOOP('',(#10901,#10902,#10903,#10904));\r\n#10906=FACE_OUTER_BOUND('',#10905,.F.);\r\n#10907=ADVANCED_FACE('',(#10906),#10900,.T.);\r\n#10908=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1));\r\n#10909=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10910=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10911=AXIS2_PLACEMENT_3D('',#10908,#10909,#10910);\r\n#10912=PLANE('',#10911);\r\n#10913=ORIENTED_EDGE('',*,*,#5838,.T.);\r\n#10915=ORIENTED_EDGE('',*,*,#10914,.T.);\r\n#10917=ORIENTED_EDGE('',*,*,#10916,.F.);\r\n#10919=ORIENTED_EDGE('',*,*,#10918,.F.);\r\n#10920=EDGE_LOOP('',(#10913,#10915,#10917,#10919));\r\n#10921=FACE_OUTER_BOUND('',#10920,.F.);\r\n#10922=ADVANCED_FACE('',(#10921),#10912,.T.);\r\n#10923=CARTESIAN_POINT('',(2.275E1,0.E0,1.35E1));\r\n#10924=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10925=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10926=AXIS2_PLACEMENT_3D('',#10923,#10924,#10925);\r\n#10927=CYLINDRICAL_SURFACE('',#10926,5.625E-1);\r\n#10928=ORIENTED_EDGE('',*,*,#5844,.T.);\r\n#10930=ORIENTED_EDGE('',*,*,#10929,.T.);\r\n#10932=ORIENTED_EDGE('',*,*,#10931,.F.);\r\n#10933=ORIENTED_EDGE('',*,*,#10914,.F.);\r\n#10934=EDGE_LOOP('',(#10928,#10930,#10932,#10933));\r\n#10935=FACE_OUTER_BOUND('',#10934,.F.);\r\n#10936=ADVANCED_FACE('',(#10935),#10927,.F.);\r\n#10937=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1));\r\n#10938=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#10939=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#10940=AXIS2_PLACEMENT_3D('',#10937,#10938,#10939);\r\n#10941=PLANE('',#10940);\r\n#10942=ORIENTED_EDGE('',*,*,#5842,.T.);\r\n#10944=ORIENTED_EDGE('',*,*,#10943,.T.);\r\n#10946=ORIENTED_EDGE('',*,*,#10945,.F.);\r\n#10947=ORIENTED_EDGE('',*,*,#10929,.F.);\r\n#10948=EDGE_LOOP('',(#10942,#10944,#10946,#10947));\r\n#10949=FACE_OUTER_BOUND('',#10948,.F.);\r\n#10950=ADVANCED_FACE('',(#10949),#10941,.T.);\r\n#10951=CARTESIAN_POINT('',(2.275E1,0.E0,1.65E1));\r\n#10952=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10953=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10954=AXIS2_PLACEMENT_3D('',#10951,#10952,#10953);\r\n#10955=CYLINDRICAL_SURFACE('',#10954,5.625E-1);\r\n#10956=ORIENTED_EDGE('',*,*,#5840,.T.);\r\n#10957=ORIENTED_EDGE('',*,*,#10918,.T.);\r\n#10959=ORIENTED_EDGE('',*,*,#10958,.F.);\r\n#10960=ORIENTED_EDGE('',*,*,#10943,.F.);\r\n#10961=EDGE_LOOP('',(#10956,#10957,#10959,#10960));\r\n#10962=FACE_OUTER_BOUND('',#10961,.F.);\r\n#10963=ADVANCED_FACE('',(#10962),#10955,.F.);\r\n#10964=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#10965=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10966=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10967=AXIS2_PLACEMENT_3D('',#10964,#10965,#10966);\r\n#10968=PLANE('',#10967);\r\n#10969=ORIENTED_EDGE('',*,*,#10916,.T.);\r\n#10970=ORIENTED_EDGE('',*,*,#10931,.T.);\r\n#10971=ORIENTED_EDGE('',*,*,#10945,.T.);\r\n#10972=ORIENTED_EDGE('',*,*,#10958,.T.);\r\n#10973=EDGE_LOOP('',(#10969,#10970,#10971,#10972));\r\n#10974=FACE_OUTER_BOUND('',#10973,.F.);\r\n#10975=ADVANCED_FACE('',(#10974),#10968,.F.);\r\n#10976=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1));\r\n#10977=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10978=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#10979=AXIS2_PLACEMENT_3D('',#10976,#10977,#10978);\r\n#10980=PLANE('',#10979);\r\n#10981=ORIENTED_EDGE('',*,*,#5848,.T.);\r\n#10983=ORIENTED_EDGE('',*,*,#10982,.T.);\r\n#10985=ORIENTED_EDGE('',*,*,#10984,.F.);\r\n#10987=ORIENTED_EDGE('',*,*,#10986,.F.);\r\n#10988=EDGE_LOOP('',(#10981,#10983,#10985,#10987));\r\n#10989=FACE_OUTER_BOUND('',#10988,.F.);\r\n#10990=ADVANCED_FACE('',(#10989),#10980,.T.);\r\n#10991=CARTESIAN_POINT('',(2.275E1,0.E0,1.95E1));\r\n#10992=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#10993=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#10994=AXIS2_PLACEMENT_3D('',#10991,#10992,#10993);\r\n#10995=CYLINDRICAL_SURFACE('',#10994,5.625E-1);\r\n#10996=ORIENTED_EDGE('',*,*,#5854,.T.);\r\n#10998=ORIENTED_EDGE('',*,*,#10997,.T.);\r\n#11000=ORIENTED_EDGE('',*,*,#10999,.F.);\r\n#11001=ORIENTED_EDGE('',*,*,#10982,.F.);\r\n#11002=EDGE_LOOP('',(#10996,#10998,#11000,#11001));\r\n#11003=FACE_OUTER_BOUND('',#11002,.F.);\r\n#11004=ADVANCED_FACE('',(#11003),#10995,.F.);\r\n#11005=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1));\r\n#11006=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11007=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11008=AXIS2_PLACEMENT_3D('',#11005,#11006,#11007);\r\n#11009=PLANE('',#11008);\r\n#11010=ORIENTED_EDGE('',*,*,#5852,.T.);\r\n#11012=ORIENTED_EDGE('',*,*,#11011,.T.);\r\n#11014=ORIENTED_EDGE('',*,*,#11013,.F.);\r\n#11015=ORIENTED_EDGE('',*,*,#10997,.F.);\r\n#11016=EDGE_LOOP('',(#11010,#11012,#11014,#11015));\r\n#11017=FACE_OUTER_BOUND('',#11016,.F.);\r\n#11018=ADVANCED_FACE('',(#11017),#11009,.T.);\r\n#11019=CARTESIAN_POINT('',(2.275E1,0.E0,2.25E1));\r\n#11020=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11021=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11022=AXIS2_PLACEMENT_3D('',#11019,#11020,#11021);\r\n#11023=CYLINDRICAL_SURFACE('',#11022,5.625E-1);\r\n#11024=ORIENTED_EDGE('',*,*,#5850,.T.);\r\n#11025=ORIENTED_EDGE('',*,*,#10986,.T.);\r\n#11027=ORIENTED_EDGE('',*,*,#11026,.F.);\r\n#11028=ORIENTED_EDGE('',*,*,#11011,.F.);\r\n#11029=EDGE_LOOP('',(#11024,#11025,#11027,#11028));\r\n#11030=FACE_OUTER_BOUND('',#11029,.F.);\r\n#11031=ADVANCED_FACE('',(#11030),#11023,.F.);\r\n#11032=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#11033=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11034=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11035=AXIS2_PLACEMENT_3D('',#11032,#11033,#11034);\r\n#11036=PLANE('',#11035);\r\n#11037=ORIENTED_EDGE('',*,*,#10984,.T.);\r\n#11038=ORIENTED_EDGE('',*,*,#10999,.T.);\r\n#11039=ORIENTED_EDGE('',*,*,#11013,.T.);\r\n#11040=ORIENTED_EDGE('',*,*,#11026,.T.);\r\n#11041=EDGE_LOOP('',(#11037,#11038,#11039,#11040));\r\n#11042=FACE_OUTER_BOUND('',#11041,.F.);\r\n#11043=ADVANCED_FACE('',(#11042),#11036,.F.);\r\n#11044=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0));\r\n#11045=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11046=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11047=AXIS2_PLACEMENT_3D('',#11044,#11045,#11046);\r\n#11048=PLANE('',#11047);\r\n#11049=ORIENTED_EDGE('',*,*,#5858,.T.);\r\n#11051=ORIENTED_EDGE('',*,*,#11050,.T.);\r\n#11053=ORIENTED_EDGE('',*,*,#11052,.F.);\r\n#11055=ORIENTED_EDGE('',*,*,#11054,.F.);\r\n#11056=EDGE_LOOP('',(#11049,#11051,#11053,#11055));\r\n#11057=FACE_OUTER_BOUND('',#11056,.F.);\r\n#11058=ADVANCED_FACE('',(#11057),#11048,.T.);\r\n#11059=CARTESIAN_POINT('',(1.35E1,0.E0,9.E0));\r\n#11060=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11061=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11062=AXIS2_PLACEMENT_3D('',#11059,#11060,#11061);\r\n#11063=CYLINDRICAL_SURFACE('',#11062,5.E-1);\r\n#11064=ORIENTED_EDGE('',*,*,#5864,.T.);\r\n#11066=ORIENTED_EDGE('',*,*,#11065,.T.);\r\n#11068=ORIENTED_EDGE('',*,*,#11067,.F.);\r\n#11069=ORIENTED_EDGE('',*,*,#11050,.F.);\r\n#11070=EDGE_LOOP('',(#11064,#11066,#11068,#11069));\r\n#11071=FACE_OUTER_BOUND('',#11070,.F.);\r\n#11072=ADVANCED_FACE('',(#11071),#11063,.F.);\r\n#11073=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0));\r\n#11074=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11075=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11076=AXIS2_PLACEMENT_3D('',#11073,#11074,#11075);\r\n#11077=PLANE('',#11076);\r\n#11078=ORIENTED_EDGE('',*,*,#5862,.T.);\r\n#11080=ORIENTED_EDGE('',*,*,#11079,.T.);\r\n#11082=ORIENTED_EDGE('',*,*,#11081,.F.);\r\n#11083=ORIENTED_EDGE('',*,*,#11065,.F.);\r\n#11084=EDGE_LOOP('',(#11078,#11080,#11082,#11083));\r\n#11085=FACE_OUTER_BOUND('',#11084,.F.);\r\n#11086=ADVANCED_FACE('',(#11085),#11077,.T.);\r\n#11087=CARTESIAN_POINT('',(1.65E1,0.E0,9.E0));\r\n#11088=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11089=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11090=AXIS2_PLACEMENT_3D('',#11087,#11088,#11089);\r\n#11091=CYLINDRICAL_SURFACE('',#11090,5.E-1);\r\n#11092=ORIENTED_EDGE('',*,*,#5860,.T.);\r\n#11093=ORIENTED_EDGE('',*,*,#11054,.T.);\r\n#11095=ORIENTED_EDGE('',*,*,#11094,.F.);\r\n#11096=ORIENTED_EDGE('',*,*,#11079,.F.);\r\n#11097=EDGE_LOOP('',(#11092,#11093,#11095,#11096));\r\n#11098=FACE_OUTER_BOUND('',#11097,.F.);\r\n#11099=ADVANCED_FACE('',(#11098),#11091,.F.);\r\n#11100=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#11101=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11102=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11103=AXIS2_PLACEMENT_3D('',#11100,#11101,#11102);\r\n#11104=PLANE('',#11103);\r\n#11105=ORIENTED_EDGE('',*,*,#11052,.T.);\r\n#11106=ORIENTED_EDGE('',*,*,#11067,.T.);\r\n#11107=ORIENTED_EDGE('',*,*,#11081,.T.);\r\n#11108=ORIENTED_EDGE('',*,*,#11094,.T.);\r\n#11109=EDGE_LOOP('',(#11105,#11106,#11107,#11108));\r\n#11110=FACE_OUTER_BOUND('',#11109,.F.);\r\n#11111=ADVANCED_FACE('',(#11110),#11104,.F.);\r\n#11112=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1));\r\n#11113=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11114=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11115=AXIS2_PLACEMENT_3D('',#11112,#11113,#11114);\r\n#11116=PLANE('',#11115);\r\n#11117=ORIENTED_EDGE('',*,*,#5868,.T.);\r\n#11119=ORIENTED_EDGE('',*,*,#11118,.T.);\r\n#11121=ORIENTED_EDGE('',*,*,#11120,.F.);\r\n#11123=ORIENTED_EDGE('',*,*,#11122,.F.);\r\n#11124=EDGE_LOOP('',(#11117,#11119,#11121,#11123));\r\n#11125=FACE_OUTER_BOUND('',#11124,.F.);\r\n#11126=ADVANCED_FACE('',(#11125),#11116,.T.);\r\n#11127=CARTESIAN_POINT('',(1.35E1,0.E0,1.8E1));\r\n#11128=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11129=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11130=AXIS2_PLACEMENT_3D('',#11127,#11128,#11129);\r\n#11131=CYLINDRICAL_SURFACE('',#11130,4.375E-1);\r\n#11132=ORIENTED_EDGE('',*,*,#5874,.T.);\r\n#11134=ORIENTED_EDGE('',*,*,#11133,.T.);\r\n#11136=ORIENTED_EDGE('',*,*,#11135,.F.);\r\n#11137=ORIENTED_EDGE('',*,*,#11118,.F.);\r\n#11138=EDGE_LOOP('',(#11132,#11134,#11136,#11137));\r\n#11139=FACE_OUTER_BOUND('',#11138,.F.);\r\n#11140=ADVANCED_FACE('',(#11139),#11131,.F.);\r\n#11141=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1));\r\n#11142=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11143=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11144=AXIS2_PLACEMENT_3D('',#11141,#11142,#11143);\r\n#11145=PLANE('',#11144);\r\n#11146=ORIENTED_EDGE('',*,*,#5872,.T.);\r\n#11148=ORIENTED_EDGE('',*,*,#11147,.T.);\r\n#11150=ORIENTED_EDGE('',*,*,#11149,.F.);\r\n#11151=ORIENTED_EDGE('',*,*,#11133,.F.);\r\n#11152=EDGE_LOOP('',(#11146,#11148,#11150,#11151));\r\n#11153=FACE_OUTER_BOUND('',#11152,.F.);\r\n#11154=ADVANCED_FACE('',(#11153),#11145,.T.);\r\n#11155=CARTESIAN_POINT('',(1.65E1,0.E0,1.8E1));\r\n#11156=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11157=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11158=AXIS2_PLACEMENT_3D('',#11155,#11156,#11157);\r\n#11159=CYLINDRICAL_SURFACE('',#11158,4.375E-1);\r\n#11160=ORIENTED_EDGE('',*,*,#5870,.T.);\r\n#11161=ORIENTED_EDGE('',*,*,#11122,.T.);\r\n#11163=ORIENTED_EDGE('',*,*,#11162,.F.);\r\n#11164=ORIENTED_EDGE('',*,*,#11147,.F.);\r\n#11165=EDGE_LOOP('',(#11160,#11161,#11163,#11164));\r\n#11166=FACE_OUTER_BOUND('',#11165,.F.);\r\n#11167=ADVANCED_FACE('',(#11166),#11159,.F.);\r\n#11168=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#11169=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11170=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11171=AXIS2_PLACEMENT_3D('',#11168,#11169,#11170);\r\n#11172=PLANE('',#11171);\r\n#11173=ORIENTED_EDGE('',*,*,#11120,.T.);\r\n#11174=ORIENTED_EDGE('',*,*,#11135,.T.);\r\n#11175=ORIENTED_EDGE('',*,*,#11149,.T.);\r\n#11176=ORIENTED_EDGE('',*,*,#11162,.T.);\r\n#11177=EDGE_LOOP('',(#11173,#11174,#11175,#11176));\r\n#11178=FACE_OUTER_BOUND('',#11177,.F.);\r\n#11179=ADVANCED_FACE('',(#11178),#11172,.F.);\r\n#11180=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1));\r\n#11181=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11182=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11183=AXIS2_PLACEMENT_3D('',#11180,#11181,#11182);\r\n#11184=PLANE('',#11183);\r\n#11185=ORIENTED_EDGE('',*,*,#5878,.F.);\r\n#11187=ORIENTED_EDGE('',*,*,#11186,.T.);\r\n#11189=ORIENTED_EDGE('',*,*,#11188,.T.);\r\n#11191=ORIENTED_EDGE('',*,*,#11190,.F.);\r\n#11192=EDGE_LOOP('',(#11185,#11187,#11189,#11191));\r\n#11193=FACE_OUTER_BOUND('',#11192,.F.);\r\n#11194=ADVANCED_FACE('',(#11193),#11184,.F.);\r\n#11195=CARTESIAN_POINT('',(1.65E1,0.E0,3.075E1));\r\n#11196=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11197=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11198=AXIS2_PLACEMENT_3D('',#11195,#11196,#11197);\r\n#11199=CYLINDRICAL_SURFACE('',#11198,5.625E-1);\r\n#11200=ORIENTED_EDGE('',*,*,#5884,.F.);\r\n#11202=ORIENTED_EDGE('',*,*,#11201,.T.);\r\n#11204=ORIENTED_EDGE('',*,*,#11203,.T.);\r\n#11205=ORIENTED_EDGE('',*,*,#11186,.F.);\r\n#11206=EDGE_LOOP('',(#11200,#11202,#11204,#11205));\r\n#11207=FACE_OUTER_BOUND('',#11206,.F.);\r\n#11208=ADVANCED_FACE('',(#11207),#11199,.F.);\r\n#11209=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1));\r\n#11210=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11211=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11212=AXIS2_PLACEMENT_3D('',#11209,#11210,#11211);\r\n#11213=PLANE('',#11212);\r\n#11214=ORIENTED_EDGE('',*,*,#5882,.F.);\r\n#11216=ORIENTED_EDGE('',*,*,#11215,.T.);\r\n#11218=ORIENTED_EDGE('',*,*,#11217,.T.);\r\n#11219=ORIENTED_EDGE('',*,*,#11201,.F.);\r\n#11220=EDGE_LOOP('',(#11214,#11216,#11218,#11219));\r\n#11221=FACE_OUTER_BOUND('',#11220,.F.);\r\n#11222=ADVANCED_FACE('',(#11221),#11213,.F.);\r\n#11223=CARTESIAN_POINT('',(1.35E1,0.E0,3.075E1));\r\n#11224=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11225=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11226=AXIS2_PLACEMENT_3D('',#11223,#11224,#11225);\r\n#11227=CYLINDRICAL_SURFACE('',#11226,5.625E-1);\r\n#11228=ORIENTED_EDGE('',*,*,#5880,.F.);\r\n#11229=ORIENTED_EDGE('',*,*,#11190,.T.);\r\n#11231=ORIENTED_EDGE('',*,*,#11230,.T.);\r\n#11232=ORIENTED_EDGE('',*,*,#11215,.F.);\r\n#11233=EDGE_LOOP('',(#11228,#11229,#11231,#11232));\r\n#11234=FACE_OUTER_BOUND('',#11233,.F.);\r\n#11235=ADVANCED_FACE('',(#11234),#11227,.F.);\r\n#11236=CARTESIAN_POINT('',(2.4E1,6.875E-1,3.2E1));\r\n#11237=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11238=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11239=AXIS2_PLACEMENT_3D('',#11236,#11237,#11238);\r\n#11240=PLANE('',#11239);\r\n#11241=ORIENTED_EDGE('',*,*,#11188,.F.);\r\n#11242=ORIENTED_EDGE('',*,*,#11203,.F.);\r\n#11243=ORIENTED_EDGE('',*,*,#11217,.F.);\r\n#11244=ORIENTED_EDGE('',*,*,#11230,.F.);\r\n#11245=EDGE_LOOP('',(#11241,#11242,#11243,#11244));\r\n#11246=FACE_OUTER_BOUND('',#11245,.F.);\r\n#11247=ADVANCED_FACE('',(#11246),#11240,.T.);\r\n#11248=CARTESIAN_POINT('',(2.4E1,6.875E-1,3.2E1));\r\n#11249=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11250=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11251=AXIS2_PLACEMENT_3D('',#11248,#11249,#11250);\r\n#11252=PLANE('',#11251);\r\n#11254=ORIENTED_EDGE('',*,*,#11253,.F.);\r\n#11256=ORIENTED_EDGE('',*,*,#11255,.F.);\r\n#11258=ORIENTED_EDGE('',*,*,#11257,.F.);\r\n#11260=ORIENTED_EDGE('',*,*,#11259,.F.);\r\n#11262=ORIENTED_EDGE('',*,*,#11261,.F.);\r\n#11263=EDGE_LOOP('',(#11254,#11256,#11258,#11260,#11262));\r\n#11264=FACE_OUTER_BOUND('',#11263,.F.);\r\n#11265=ADVANCED_FACE('',(#11264),#11252,.T.);\r\n#11266=CARTESIAN_POINT('',(2.254426323641E1,-6.892397422826E-2,\r\n2.742280476768E1));\r\n#11267=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11268=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#11269=AXIS2_PLACEMENT_3D('',#11266,#11267,#11268);\r\n#11270=CYLINDRICAL_SURFACE('',#11269,7.5E-1);\r\n#11272=ORIENTED_EDGE('',*,*,#11271,.F.);\r\n#11273=ORIENTED_EDGE('',*,*,#5944,.T.);\r\n#11275=ORIENTED_EDGE('',*,*,#11274,.T.);\r\n#11276=ORIENTED_EDGE('',*,*,#11253,.T.);\r\n#11277=EDGE_LOOP('',(#11272,#11273,#11275,#11276));\r\n#11278=FACE_OUTER_BOUND('',#11277,.F.);\r\n#11279=ADVANCED_FACE('',(#11278),#11270,.F.);\r\n#11280=CARTESIAN_POINT('',(2.33125E1,0.E0,2.771522817587E1));\r\n#11281=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#11282=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1));\r\n#11283=AXIS2_PLACEMENT_3D('',#11280,#11281,#11282);\r\n#11284=PLANE('',#11283);\r\n#11285=ORIENTED_EDGE('',*,*,#11271,.T.);\r\n#11286=ORIENTED_EDGE('',*,*,#11261,.T.);\r\n#11288=ORIENTED_EDGE('',*,*,#11287,.F.);\r\n#11289=ORIENTED_EDGE('',*,*,#5946,.F.);\r\n#11290=EDGE_LOOP('',(#11285,#11286,#11288,#11289));\r\n#11291=FACE_OUTER_BOUND('',#11290,.F.);\r\n#11292=ADVANCED_FACE('',(#11291),#11284,.F.);\r\n#11293=CARTESIAN_POINT('',(1.944696065761E1,0.E0,3.035464591145E1));\r\n#11294=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11295=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11296=AXIS2_PLACEMENT_3D('',#11293,#11294,#11295);\r\n#11297=CYLINDRICAL_SURFACE('',#11296,8.669989027347E-1);\r\n#11298=ORIENTED_EDGE('',*,*,#5948,.F.);\r\n#11299=ORIENTED_EDGE('',*,*,#11287,.T.);\r\n#11300=ORIENTED_EDGE('',*,*,#11259,.T.);\r\n#11302=ORIENTED_EDGE('',*,*,#11301,.F.);\r\n#11303=EDGE_LOOP('',(#11298,#11299,#11300,#11302));\r\n#11304=FACE_OUTER_BOUND('',#11303,.F.);\r\n#11305=ADVANCED_FACE('',(#11304),#11297,.F.);\r\n#11306=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1));\r\n#11307=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11308=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11309=AXIS2_PLACEMENT_3D('',#11306,#11307,#11308);\r\n#11310=CYLINDRICAL_SURFACE('',#11309,5.6875E0);\r\n#11311=ORIENTED_EDGE('',*,*,#5950,.T.);\r\n#11312=ORIENTED_EDGE('',*,*,#11301,.T.);\r\n#11313=ORIENTED_EDGE('',*,*,#11257,.T.);\r\n#11315=ORIENTED_EDGE('',*,*,#11314,.F.);\r\n#11316=EDGE_LOOP('',(#11311,#11312,#11313,#11315));\r\n#11317=FACE_OUTER_BOUND('',#11316,.F.);\r\n#11318=ADVANCED_FACE('',(#11317),#11310,.T.);\r\n#11319=CARTESIAN_POINT('',(2.239E1,0.E0,2.75E1));\r\n#11320=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11321=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11322=AXIS2_PLACEMENT_3D('',#11319,#11320,#11321);\r\n#11323=CYLINDRICAL_SURFACE('',#11322,9.225E-1);\r\n#11324=ORIENTED_EDGE('',*,*,#11274,.F.);\r\n#11325=ORIENTED_EDGE('',*,*,#5942,.F.);\r\n#11326=ORIENTED_EDGE('',*,*,#11314,.T.);\r\n#11327=ORIENTED_EDGE('',*,*,#11255,.T.);\r\n#11328=EDGE_LOOP('',(#11324,#11325,#11326,#11327));\r\n#11329=FACE_OUTER_BOUND('',#11328,.F.);\r\n#11330=ADVANCED_FACE('',(#11329),#11323,.F.);\r\n#11331=CARTESIAN_POINT('',(2.13075E1,-6.892397422826E-2,7.81E0));\r\n#11332=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11333=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11334=AXIS2_PLACEMENT_3D('',#11331,#11332,#11333);\r\n#11335=CYLINDRICAL_SURFACE('',#11334,8.8E-1);\r\n#11337=ORIENTED_EDGE('',*,*,#11336,.T.);\r\n#11339=ORIENTED_EDGE('',*,*,#11338,.T.);\r\n#11341=ORIENTED_EDGE('',*,*,#11340,.F.);\r\n#11342=ORIENTED_EDGE('',*,*,#5888,.T.);\r\n#11343=EDGE_LOOP('',(#11337,#11339,#11341,#11342));\r\n#11344=FACE_OUTER_BOUND('',#11343,.F.);\r\n#11345=ADVANCED_FACE('',(#11344),#11335,.T.);\r\n#11346=CARTESIAN_POINT('',(2.21875E1,0.E0,8.69E0));\r\n#11347=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11348=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11349=AXIS2_PLACEMENT_3D('',#11346,#11347,#11348);\r\n#11350=PLANE('',#11349);\r\n#11351=ORIENTED_EDGE('',*,*,#11336,.F.);\r\n#11352=ORIENTED_EDGE('',*,*,#5914,.T.);\r\n#11354=ORIENTED_EDGE('',*,*,#11353,.F.);\r\n#11356=ORIENTED_EDGE('',*,*,#11355,.F.);\r\n#11357=EDGE_LOOP('',(#11351,#11352,#11354,#11356));\r\n#11358=FACE_OUTER_BOUND('',#11357,.F.);\r\n#11359=ADVANCED_FACE('',(#11358),#11350,.T.);\r\n#11360=CARTESIAN_POINT('',(2.05675E1,7.463919417831E-1,9.57E0));\r\n#11361=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11362=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11363=AXIS2_PLACEMENT_3D('',#11360,#11361,#11362);\r\n#11364=CYLINDRICAL_SURFACE('',#11363,8.8E-1);\r\n#11366=ORIENTED_EDGE('',*,*,#11365,.F.);\r\n#11368=ORIENTED_EDGE('',*,*,#11367,.T.);\r\n#11369=ORIENTED_EDGE('',*,*,#11353,.T.);\r\n#11370=ORIENTED_EDGE('',*,*,#5912,.T.);\r\n#11371=EDGE_LOOP('',(#11366,#11368,#11369,#11370));\r\n#11372=FACE_OUTER_BOUND('',#11371,.F.);\r\n#11373=ADVANCED_FACE('',(#11372),#11364,.F.);\r\n#11374=CARTESIAN_POINT('',(1.96875E1,0.E0,8.69E0));\r\n#11375=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11376=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11377=AXIS2_PLACEMENT_3D('',#11374,#11375,#11376);\r\n#11378=PLANE('',#11377);\r\n#11379=ORIENTED_EDGE('',*,*,#11365,.T.);\r\n#11380=ORIENTED_EDGE('',*,*,#5910,.T.);\r\n#11382=ORIENTED_EDGE('',*,*,#11381,.F.);\r\n#11384=ORIENTED_EDGE('',*,*,#11383,.F.);\r\n#11385=EDGE_LOOP('',(#11379,#11380,#11382,#11384));\r\n#11386=FACE_OUTER_BOUND('',#11385,.F.);\r\n#11387=ADVANCED_FACE('',(#11386),#11378,.T.);\r\n#11388=CARTESIAN_POINT('',(2.05675E1,7.463919417831E-1,1.037E1));\r\n#11389=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11390=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11391=AXIS2_PLACEMENT_3D('',#11388,#11389,#11390);\r\n#11392=CYLINDRICAL_SURFACE('',#11391,8.8E-1);\r\n#11394=ORIENTED_EDGE('',*,*,#11393,.F.);\r\n#11396=ORIENTED_EDGE('',*,*,#11395,.T.);\r\n#11397=ORIENTED_EDGE('',*,*,#11381,.T.);\r\n#11398=ORIENTED_EDGE('',*,*,#5908,.T.);\r\n#11399=EDGE_LOOP('',(#11394,#11396,#11397,#11398));\r\n#11400=FACE_OUTER_BOUND('',#11399,.F.);\r\n#11401=ADVANCED_FACE('',(#11400),#11392,.F.);\r\n#11402=CARTESIAN_POINT('',(1.96875E1,0.E0,1.125E1));\r\n#11403=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11404=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11405=AXIS2_PLACEMENT_3D('',#11402,#11403,#11404);\r\n#11406=PLANE('',#11405);\r\n#11407=ORIENTED_EDGE('',*,*,#11393,.T.);\r\n#11408=ORIENTED_EDGE('',*,*,#5906,.T.);\r\n#11410=ORIENTED_EDGE('',*,*,#11409,.F.);\r\n#11412=ORIENTED_EDGE('',*,*,#11411,.F.);\r\n#11413=EDGE_LOOP('',(#11407,#11408,#11410,#11412));\r\n#11414=FACE_OUTER_BOUND('',#11413,.F.);\r\n#11415=ADVANCED_FACE('',(#11414),#11406,.T.);\r\n#11416=CARTESIAN_POINT('',(2.44325E1,7.463919417831E-1,1.037E1));\r\n#11417=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11418=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11419=AXIS2_PLACEMENT_3D('',#11416,#11417,#11418);\r\n#11420=CYLINDRICAL_SURFACE('',#11419,8.8E-1);\r\n#11422=ORIENTED_EDGE('',*,*,#11421,.F.);\r\n#11424=ORIENTED_EDGE('',*,*,#11423,.T.);\r\n#11425=ORIENTED_EDGE('',*,*,#11409,.T.);\r\n#11426=ORIENTED_EDGE('',*,*,#5904,.T.);\r\n#11427=EDGE_LOOP('',(#11422,#11424,#11425,#11426));\r\n#11428=FACE_OUTER_BOUND('',#11427,.F.);\r\n#11429=ADVANCED_FACE('',(#11428),#11420,.F.);\r\n#11430=CARTESIAN_POINT('',(2.53125E1,0.E0,1.125E1));\r\n#11431=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11432=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11433=AXIS2_PLACEMENT_3D('',#11430,#11431,#11432);\r\n#11434=PLANE('',#11433);\r\n#11436=ORIENTED_EDGE('',*,*,#11435,.F.);\r\n#11438=ORIENTED_EDGE('',*,*,#11437,.F.);\r\n#11439=ORIENTED_EDGE('',*,*,#11421,.T.);\r\n#11440=ORIENTED_EDGE('',*,*,#5902,.T.);\r\n#11441=EDGE_LOOP('',(#11436,#11438,#11439,#11440));\r\n#11442=FACE_OUTER_BOUND('',#11441,.F.);\r\n#11443=ADVANCED_FACE('',(#11442),#11434,.T.);\r\n#11444=CARTESIAN_POINT('',(2.44325E1,7.463919417831E-1,9.57E0));\r\n#11445=DIRECTION('',(0.E0,-1.E0,0.E0));\r\n#11446=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11447=AXIS2_PLACEMENT_3D('',#11444,#11445,#11446);\r\n#11448=CYLINDRICAL_SURFACE('',#11447,8.8E-1);\r\n#11450=ORIENTED_EDGE('',*,*,#11449,.F.);\r\n#11452=ORIENTED_EDGE('',*,*,#11451,.T.);\r\n#11453=ORIENTED_EDGE('',*,*,#11435,.T.);\r\n#11454=ORIENTED_EDGE('',*,*,#5900,.T.);\r\n#11455=EDGE_LOOP('',(#11450,#11452,#11453,#11454));\r\n#11456=FACE_OUTER_BOUND('',#11455,.F.);\r\n#11457=ADVANCED_FACE('',(#11456),#11448,.F.);\r\n#11458=CARTESIAN_POINT('',(2.53125E1,0.E0,8.69E0));\r\n#11459=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11460=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11461=AXIS2_PLACEMENT_3D('',#11458,#11459,#11460);\r\n#11462=PLANE('',#11461);\r\n#11464=ORIENTED_EDGE('',*,*,#11463,.T.);\r\n#11466=ORIENTED_EDGE('',*,*,#11465,.F.);\r\n#11467=ORIENTED_EDGE('',*,*,#11449,.T.);\r\n#11468=ORIENTED_EDGE('',*,*,#5898,.T.);\r\n#11469=EDGE_LOOP('',(#11464,#11466,#11467,#11468));\r\n#11470=FACE_OUTER_BOUND('',#11469,.F.);\r\n#11471=ADVANCED_FACE('',(#11470),#11462,.T.);\r\n#11472=CARTESIAN_POINT('',(2.419E1,-6.892397422826E-2,7.81E0));\r\n#11473=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11474=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11475=AXIS2_PLACEMENT_3D('',#11472,#11473,#11474);\r\n#11476=CYLINDRICAL_SURFACE('',#11475,8.8E-1);\r\n#11478=ORIENTED_EDGE('',*,*,#11477,.T.);\r\n#11480=ORIENTED_EDGE('',*,*,#11479,.T.);\r\n#11481=ORIENTED_EDGE('',*,*,#11463,.F.);\r\n#11482=ORIENTED_EDGE('',*,*,#5896,.T.);\r\n#11483=EDGE_LOOP('',(#11478,#11480,#11481,#11482));\r\n#11484=FACE_OUTER_BOUND('',#11483,.F.);\r\n#11485=ADVANCED_FACE('',(#11484),#11476,.T.);\r\n#11486=CARTESIAN_POINT('',(2.331E1,0.E0,8.69E0));\r\n#11487=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11488=DIRECTION('',(0.E0,0.E0,-1.E0));\r\n#11489=AXIS2_PLACEMENT_3D('',#11486,#11487,#11488);\r\n#11490=PLANE('',#11489);\r\n#11491=ORIENTED_EDGE('',*,*,#11477,.F.);\r\n#11492=ORIENTED_EDGE('',*,*,#5894,.T.);\r\n#11494=ORIENTED_EDGE('',*,*,#11493,.T.);\r\n#11496=ORIENTED_EDGE('',*,*,#11495,.F.);\r\n#11497=EDGE_LOOP('',(#11491,#11492,#11494,#11496));\r\n#11498=FACE_OUTER_BOUND('',#11497,.F.);\r\n#11499=ADVANCED_FACE('',(#11498),#11490,.T.);\r\n#11500=CARTESIAN_POINT('',(2.274875E1,0.E0,7.5E0));\r\n#11501=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11502=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11503=AXIS2_PLACEMENT_3D('',#11500,#11501,#11502);\r\n#11504=CYLINDRICAL_SURFACE('',#11503,5.6125E-1);\r\n#11505=ORIENTED_EDGE('',*,*,#5892,.T.);\r\n#11507=ORIENTED_EDGE('',*,*,#11506,.T.);\r\n#11509=ORIENTED_EDGE('',*,*,#11508,.F.);\r\n#11510=ORIENTED_EDGE('',*,*,#11493,.F.);\r\n#11511=EDGE_LOOP('',(#11505,#11507,#11509,#11510));\r\n#11512=FACE_OUTER_BOUND('',#11511,.F.);\r\n#11513=ADVANCED_FACE('',(#11512),#11504,.F.);\r\n#11514=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0));\r\n#11515=DIRECTION('',(1.E0,0.E0,0.E0));\r\n#11516=DIRECTION('',(0.E0,0.E0,1.E0));\r\n#11517=AXIS2_PLACEMENT_3D('',#11514,#11515,#11516);\r\n#11518=PLANE('',#11517);\r\n#11519=ORIENTED_EDGE('',*,*,#11340,.T.);\r\n#11521=ORIENTED_EDGE('',*,*,#11520,.F.);\r\n#11522=ORIENTED_EDGE('',*,*,#11506,.F.);\r\n#11523=ORIENTED_EDGE('',*,*,#5890,.T.);\r\n#11524=EDGE_LOOP('',(#11519,#11521,#11522,#11523));\r\n#11525=FACE_OUTER_BOUND('',#11524,.F.);\r\n#11526=ADVANCED_FACE('',(#11525),#11518,.T.);\r\n#11527=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0));\r\n#11528=DIRECTION('',(0.E0,1.E0,0.E0));\r\n#11529=DIRECTION('',(-1.E0,0.E0,0.E0));\r\n#11530=AXIS2_PLACEMENT_3D('',#11527,#11528,#11529);\r\n#11531=PLANE('',#11530);\r\n#11532=ORIENTED_EDGE('',*,*,#11465,.T.);\r\n#11533=ORIENTED_EDGE('',*,*,#11479,.F.);\r\n#11534=ORIENTED_EDGE('',*,*,#11495,.T.);\r\n#11535=ORIENTED_EDGE('',*,*,#11508,.T.);\r\n#11536=ORIENTED_EDGE('',*,*,#11520,.T.);\r\n#11537=ORIENTED_EDGE('',*,*,#11338,.F.);\r\n#11538=ORIENTED_EDGE('',*,*,#11355,.T.);\r\n#11539=ORIENTED_EDGE('',*,*,#11367,.F.);\r\n#11540=ORIENTED_EDGE('',*,*,#11383,.T.);\r\n#11541=ORIENTED_EDGE('',*,*,#11395,.F.);\r\n#11542=ORIENTED_EDGE('',*,*,#11411,.T.);\r\n#11543=ORIENTED_EDGE('',*,*,#11423,.F.);\r\n#11544=ORIENTED_EDGE('',*,*,#11437,.T.);\r\n#11545=ORIENTED_EDGE('',*,*,#11451,.F.);\r\n#11546=EDGE_LOOP('',(#11532,#11533,#11534,#11535,#11536,#11537,#11538,#11539,\r\n#11540,#11541,#11542,#11543,#11544,#11545));\r\n#11547=FACE_OUTER_BOUND('',#11546,.F.);\r\n#11548=ADVANCED_FACE('',(#11547),#11531,.F.);\r\n#11549=CLOSED_SHELL('',(#5954,#6079,#6094,#6107,#6117,#6132,#6145,#6201,#6214,\r\n#6278,#6488,#6503,#6516,#6529,#6540,#6555,#6568,#6581,#6592,#6605,#6618,#6631,\r\n#6644,#6656,#6669,#6683,#6696,#6709,#6723,#6736,#6749,#6763,#6776,#6789,#6802,\r\n#6815,#6828,#6842,#6855,#6868,#6880,#6893,#6906,#6918,#6931,#6945,#6958,#6971,\r\n#6984,#6998,#7011,#7024,#7036,#7048,#7061,#7074,#7086,#7099,#7114,#7127,#7152,\r\n#7166,#7178,#7191,#7204,#7217,#7230,#7244,#7256,#7311,#7325,#7337,#7349,#7368,\r\n#7379,#7394,#7407,#7423,#7437,#7449,#7465,#7477,#7490,#7514,#7529,#7542,#7552,\r\n#7567,#7580,#7590,#7605,#7619,#7649,#7662,#7675,#7688,#7701,#7714,#7727,#7740,\r\n#7753,#7766,#7778,#7790,#7805,#7818,#7828,#7843,#7856,#7866,#7881,#7894,#7907,\r\n#7918,#7933,#7946,#7959,#7970,#7985,#7998,#8014,#8028,#8040,#8055,#8068,#8084,\r\n#8098,#8110,#8125,#8138,#8154,#8168,#8180,#8195,#8208,#8224,#8238,#8250,#8265,\r\n#8278,#8294,#8308,#8320,#8335,#8348,#8364,#8378,#8390,#8405,#8418,#8434,#8448,\r\n#8460,#8475,#8488,#8504,#8518,#8530,#8545,#8558,#8574,#8588,#8600,#8615,#8628,\r\n#8644,#8658,#8670,#8685,#8698,#8714,#8728,#8740,#8755,#8768,#8784,#8798,#8810,\r\n#8825,#8838,#8854,#8868,#8880,#8895,#8908,#8924,#8938,#8950,#8965,#8978,#8994,\r\n#9008,#9020,#9035,#9048,#9064,#9078,#9090,#9105,#9118,#9134,#9148,#9160,#9175,\r\n#9188,#9204,#9218,#9230,#9242,#9260,#9275,#9288,#9304,#9318,#9330,#9345,#9359,\r\n#9373,#9387,#9401,#9415,#9429,#9443,#9457,#9471,#9485,#9498,#9518,#9533,#9546,\r\n#9556,#9571,#9584,#9594,#9609,#9622,#9632,#9647,#9660,#9670,#9685,#9698,#9708,\r\n#9723,#9737,#9751,#9765,#9779,#9793,#9807,#9820,#9836,#9851,#9865,#9887,#9901,\r\n#9913,#9926,#9939,#9952,#9964,#9979,#9993,#10007,#10020,#10032,#10050,#10064,\r\n#10077,#10090,#10103,#10115,#10130,#10144,#10178,#10192,#10205,#10218,#10230,\r\n#10243,#10256,#10269,#10282,#10295,#10308,#10321,#10333,#10348,#10362,#10376,\r\n#10389,#10401,#10416,#10430,#10444,#10457,#10469,#10484,#10498,#10512,#10525,\r\n#10537,#10552,#10566,#10580,#10593,#10605,#10620,#10634,#10648,#10661,#10673,\r\n#10691,#10705,#10718,#10731,#10744,#10756,#10771,#10785,#10799,#10812,#10824,\r\n#10842,#10856,#10869,#10882,#10895,#10907,#10922,#10936,#10950,#10963,#10975,\r\n#10990,#11004,#11018,#11031,#11043,#11058,#11072,#11086,#11099,#11111,#11126,\r\n#11140,#11154,#11167,#11179,#11194,#11208,#11222,#11235,#11247,#11265,#11279,\r\n#11292,#11305,#11318,#11330,#11345,#11359,#11373,#11387,#11401,#11415,#11429,\r\n#11443,#11457,#11471,#11485,#11499,#11513,#11526,#11548));\r\n#11550=MANIFOLD_SOLID_BREP('',#11549);\r\n#11551=DIMENSIONAL_EXPONENTS(1.E0,0.E0,0.E0,0.E0,0.E0,0.E0,0.E0);\r\n#11552=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));\r\n#11553=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(2.54E1),#11552);\r\n#11554=(CONVERSION_BASED_UNIT('INCH',#11553)LENGTH_UNIT()NAMED_UNIT(#11551));\r\n#11555=DIMENSIONAL_EXPONENTS(0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,0.E0);\r\n#11556=(NAMED_UNIT(*)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.));\r\n#11557=PLANE_ANGLE_MEASURE_WITH_UNIT(PLANE_ANGLE_MEASURE(1.745329251994E-2),\r\n#11556);\r\n#11558=(CONVERSION_BASED_UNIT('DEGREE',#11557)NAMED_UNIT(#11555)PLANE_ANGLE_UNIT());\r\n#11559=(NAMED_UNIT(*)SI_UNIT($,.STERADIAN.)SOLID_ANGLE_UNIT());\r\n#11560=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(4.404650704771E-3),#11554,\r\n'closure',\r\n'Maximum model space distance between geometric entities at asserted connectivities');\r\n#11561=(GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((\r\n#11560))GLOBAL_UNIT_ASSIGNED_CONTEXT((#11554,#11558,#11559))REPRESENTATION_CONTEXT('ID1','3'));\r\n#11563=APPLICATION_CONTEXT(\r\n'CONFIGURATION CONTROLLED 3D DESIGNS OF MECHANICAL PARTS AND ASSEMBLIES');\r\n#11564=APPLICATION_PROTOCOL_DEFINITION('international standard',\r\n'config_control_design',1994,#11563);\r\n#11565=DESIGN_CONTEXT('',#11563,'design');\r\n#11566=MECHANICAL_CONTEXT('',#11563,'mechanical');\r\n#11567=PRODUCT('PROESOURCE','PROESOURCE','NOT SPECIFIED',(#11566));\r\n#11568=PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE('1','LAST_VERSION',\r\n#11567,.MADE.);\r\n#11572=PRODUCT_CATEGORY('part','');\r\n#11573=PRODUCT_RELATED_PRODUCT_CATEGORY('detail','',(#11567));\r\n#11574=PRODUCT_CATEGORY_RELATIONSHIP('','',#11572,#11573);\r\n#11575=SECURITY_CLASSIFICATION_LEVEL('unclassified');\r\n#11576=SECURITY_CLASSIFICATION('','',#11575);\r\n#11577=CC_DESIGN_SECURITY_CLASSIFICATION(#11576,(#11568));\r\n#11578=APPROVAL_STATUS('approved');\r\n#11579=APPROVAL(#11578,'');\r\n#11580=CC_DESIGN_APPROVAL(#11579,(#11576,#11568,#11569));\r\n#11581=CALENDAR_DATE(102,4,11);\r\n#11582=COORDINATED_UNIVERSAL_TIME_OFFSET(5,0,.BEHIND.);\r\n#11583=LOCAL_TIME(14,0,4.8E1,#11582);\r\n#11584=DATE_AND_TIME(#11581,#11583);\r\n#11585=APPROVAL_DATE_TIME(#11584,#11579);\r\n#11586=DATE_TIME_ROLE('creation_date');\r\n#11587=CC_DESIGN_DATE_AND_TIME_ASSIGNMENT(#11584,#11586,(#11569));\r\n#11588=DATE_TIME_ROLE('classification_date');\r\n#11589=CC_DESIGN_DATE_AND_TIME_ASSIGNMENT(#11584,#11588,(#11576));\r\n#11590=PERSON('UNSPECIFIED','UNSPECIFIED',$,$,$,$);\r\n#11591=ORGANIZATION('UNSPECIFIED','UNSPECIFIED','UNSPECIFIED');\r\n#11592=PERSON_AND_ORGANIZATION(#11590,#11591);\r\n#11593=APPROVAL_ROLE('approver');\r\n#11594=APPROVAL_PERSON_ORGANIZATION(#11592,#11579,#11593);\r\n#11595=PERSON_AND_ORGANIZATION_ROLE('creator');\r\n#11596=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11595,(#11568,\r\n#11569));\r\n#11597=PERSON_AND_ORGANIZATION_ROLE('design_supplier');\r\n#11598=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11597,(#11568));\r\n#11599=PERSON_AND_ORGANIZATION_ROLE('classification_officer');\r\n#11600=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11599,(#11576));\r\n#11601=PERSON_AND_ORGANIZATION_ROLE('design_owner');\r\n#11602=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11601,(#11567));\r\n#13=CIRCLE('',#12,1.925E-1);\r\n#18=CIRCLE('',#17,1.925E-1);\r\n#23=CIRCLE('',#22,1.925E-1);\r\n#28=CIRCLE('',#27,1.925E-1);\r\n#33=CIRCLE('',#32,1.925E-1);\r\n#38=CIRCLE('',#37,1.925E-1);\r\n#43=CIRCLE('',#42,1.925E-1);\r\n#48=CIRCLE('',#47,1.925E-1);\r\n#53=CIRCLE('',#52,1.925E-1);\r\n#58=CIRCLE('',#57,1.925E-1);\r\n#63=CIRCLE('',#62,1.925E-1);\r\n#68=CIRCLE('',#67,1.925E-1);\r\n#73=CIRCLE('',#72,1.925E-1);\r\n#78=CIRCLE('',#77,1.925E-1);\r\n#83=CIRCLE('',#82,1.925E-1);\r\n#88=CIRCLE('',#87,1.925E-1);\r\n#93=CIRCLE('',#92,1.925E-1);\r\n#98=CIRCLE('',#97,1.925E-1);\r\n#103=CIRCLE('',#102,1.925E-1);\r\n#108=CIRCLE('',#107,1.925E-1);\r\n#113=CIRCLE('',#112,1.925E-1);\r\n#118=CIRCLE('',#117,1.925E-1);\r\n#123=CIRCLE('',#122,1.925E-1);\r\n#128=CIRCLE('',#127,1.925E-1);\r\n#181=CIRCLE('',#180,1.925E-1);\r\n#186=CIRCLE('',#185,1.925E-1);\r\n#191=CIRCLE('',#190,1.925E-1);\r\n#196=CIRCLE('',#195,1.925E-1);\r\n#249=CIRCLE('',#248,1.925E-1);\r\n#254=CIRCLE('',#253,1.925E-1);\r\n#259=CIRCLE('',#258,1.925E-1);\r\n#264=CIRCLE('',#263,1.925E-1);\r\n#269=CIRCLE('',#268,1.925E-1);\r\n#274=CIRCLE('',#273,1.925E-1);\r\n#279=CIRCLE('',#278,1.925E-1);\r\n#284=CIRCLE('',#283,1.925E-1);\r\n#289=CIRCLE('',#288,1.925E-1);\r\n#294=CIRCLE('',#293,1.925E-1);\r\n#299=CIRCLE('',#298,1.925E-1);\r\n#304=CIRCLE('',#303,1.925E-1);\r\n#313=CIRCLE('',#312,5.625E-1);\r\n#322=CIRCLE('',#321,5.625E-1);\r\n#327=CIRCLE('',#326,9.225E-1);\r\n#336=CIRCLE('',#335,8.669989027347E-1);\r\n#341=CIRCLE('',#340,5.6875E0);\r\n#350=CIRCLE('',#349,5.6125E-1);\r\n#383=CIRCLE('',#382,5.625E-1);\r\n#392=CIRCLE('',#391,5.625E-1);\r\n#401=CIRCLE('',#400,5.625E-1);\r\n#410=CIRCLE('',#409,5.625E-1);\r\n#419=CIRCLE('',#418,5.E-1);\r\n#428=CIRCLE('',#427,5.E-1);\r\n#437=CIRCLE('',#436,4.375E-1);\r\n#446=CIRCLE('',#445,4.375E-1);\r\n#455=CIRCLE('',#454,5.625E-1);\r\n#464=CIRCLE('',#463,5.625E-1);\r\n#473=CIRCLE('',#472,5.625E-1);\r\n#482=CIRCLE('',#481,5.625E-1);\r\n#491=CIRCLE('',#490,5.625E-1);\r\n#500=CIRCLE('',#499,5.625E-1);\r\n#509=CIRCLE('',#508,5.625E-1);\r\n#518=CIRCLE('',#517,5.625E-1);\r\n#527=CIRCLE('',#526,5.E-1);\r\n#536=CIRCLE('',#535,5.E-1);\r\n#545=CIRCLE('',#544,4.375E-1);\r\n#554=CIRCLE('',#553,4.375E-1);\r\n#563=CIRCLE('',#562,5.625E-1);\r\n#572=CIRCLE('',#571,5.625E-1);\r\n#581=CIRCLE('',#580,5.6125E-1);\r\n#614=CIRCLE('',#613,9.225E-1);\r\n#619=CIRCLE('',#618,5.6875E0);\r\n#624=CIRCLE('',#623,8.669989027347E-1);\r\n#633=CIRCLE('',#632,9.225E-1);\r\n#638=CIRCLE('',#637,5.6875E0);\r\n#643=CIRCLE('',#642,8.669989027347E-1);\r\n#648=CIRCLE('',#647,9.225E-1);\r\n#657=CIRCLE('',#656,8.669989027347E-1);\r\n#662=CIRCLE('',#661,5.6875E0);\r\n#667=CIRCLE('',#666,9.5E-2);\r\n#672=CIRCLE('',#671,9.5E-2);\r\n#677=CIRCLE('',#676,1.625E-1);\r\n#682=CIRCLE('',#681,1.625E-1);\r\n#687=CIRCLE('',#686,9.5E-2);\r\n#692=CIRCLE('',#691,9.5E-2);\r\n#697=CIRCLE('',#696,9.5E-2);\r\n#702=CIRCLE('',#701,9.5E-2);\r\n#707=CIRCLE('',#706,9.5E-2);\r\n#712=CIRCLE('',#711,9.5E-2);\r\n#717=CIRCLE('',#716,9.5E-2);\r\n#722=CIRCLE('',#721,9.5E-2);\r\n#727=CIRCLE('',#726,1.625E-1);\r\n#732=CIRCLE('',#731,1.625E-1);\r\n#737=CIRCLE('',#736,9.5E-2);\r\n#742=CIRCLE('',#741,9.5E-2);\r\n#803=CIRCLE('',#802,9.5E-2);\r\n#808=CIRCLE('',#807,9.5E-2);\r\n#821=CIRCLE('',#820,1.625E-1);\r\n#826=CIRCLE('',#825,1.625E-1);\r\n#887=CIRCLE('',#886,1.E-1);\r\n#892=CIRCLE('',#891,1.E-1);\r\n#897=CIRCLE('',#896,1.E-1);\r\n#902=CIRCLE('',#901,1.E-1);\r\n#931=CIRCLE('',#930,1.E-1);\r\n#936=CIRCLE('',#935,1.E-1);\r\n#941=CIRCLE('',#940,1.E-1);\r\n#946=CIRCLE('',#945,1.E-1);\r\n#951=CIRCLE('',#950,2.575E-1);\r\n#956=CIRCLE('',#955,2.575E-1);\r\n#961=CIRCLE('',#960,2.575E-1);\r\n#966=CIRCLE('',#965,2.575E-1);\r\n#971=CIRCLE('',#970,2.575E-1);\r\n#976=CIRCLE('',#975,2.575E-1);\r\n#981=CIRCLE('',#980,2.575E-1);\r\n#986=CIRCLE('',#985,2.575E-1);\r\n#991=CIRCLE('',#990,2.575E-1);\r\n#996=CIRCLE('',#995,2.575E-1);\r\n#1001=CIRCLE('',#1000,2.575E-1);\r\n#1006=CIRCLE('',#1005,2.575E-1);\r\n#1011=CIRCLE('',#1010,2.56E-1);\r\n#1016=CIRCLE('',#1015,2.56E-1);\r\n#1021=CIRCLE('',#1020,2.56E-1);\r\n#1026=CIRCLE('',#1025,2.56E-1);\r\n#1031=CIRCLE('',#1030,2.56E-1);\r\n#1036=CIRCLE('',#1035,2.56E-1);\r\n#1041=CIRCLE('',#1040,2.56E-1);\r\n#1046=CIRCLE('',#1045,2.56E-1);\r\n#1051=CIRCLE('',#1050,2.56E-1);\r\n#1056=CIRCLE('',#1055,2.56E-1);\r\n#1061=CIRCLE('',#1060,2.56E-1);\r\n#1066=CIRCLE('',#1065,2.56E-1);\r\n#1115=CIRCLE('',#1114,2.575E-1);\r\n#1120=CIRCLE('',#1119,2.575E-1);\r\n#1125=CIRCLE('',#1124,2.575E-1);\r\n#1130=CIRCLE('',#1129,2.575E-1);\r\n#1135=CIRCLE('',#1134,2.575E-1);\r\n#1140=CIRCLE('',#1139,2.575E-1);\r\n#1145=CIRCLE('',#1144,2.575E-1);\r\n#1150=CIRCLE('',#1149,2.575E-1);\r\n#1155=CIRCLE('',#1154,2.575E-1);\r\n#1160=CIRCLE('',#1159,2.575E-1);\r\n#1165=CIRCLE('',#1164,2.575E-1);\r\n#1170=CIRCLE('',#1169,2.575E-1);\r\n#1259=CIRCLE('',#1258,1.E-1);\r\n#1268=CIRCLE('',#1267,1.E-1);\r\n#1285=CIRCLE('',#1284,1.E-1);\r\n#1294=CIRCLE('',#1293,1.E-1);\r\n#1303=CIRCLE('',#1302,1.E0);\r\n#1312=CIRCLE('',#1311,1.E0);\r\n#1317=CIRCLE('',#1316,5.E0);\r\n#1326=CIRCLE('',#1325,5.E0);\r\n#1331=CIRCLE('',#1330,5.E0);\r\n#1340=CIRCLE('',#1339,5.E0);\r\n#1349=CIRCLE('',#1348,1.E0);\r\n#1358=CIRCLE('',#1357,1.E0);\r\n#1367=CIRCLE('',#1366,1.E0);\r\n#1376=CIRCLE('',#1375,1.E0);\r\n#1385=CIRCLE('',#1384,1.E0);\r\n#1394=CIRCLE('',#1393,1.E0);\r\n#1403=CIRCLE('',#1402,1.E0);\r\n#1412=CIRCLE('',#1411,1.E0);\r\n#1421=CIRCLE('',#1420,3.E0);\r\n#1430=CIRCLE('',#1429,3.E0);\r\n#1439=CIRCLE('',#1438,3.E0);\r\n#1448=CIRCLE('',#1447,3.E0);\r\n#1457=CIRCLE('',#1456,5.E0);\r\n#1466=CIRCLE('',#1465,5.E0);\r\n#1475=CIRCLE('',#1474,5.E0);\r\n#1484=CIRCLE('',#1483,5.E0);\r\n#1493=CIRCLE('',#1492,3.E0);\r\n#1502=CIRCLE('',#1501,3.E0);\r\n#1511=CIRCLE('',#1510,3.E0);\r\n#1520=CIRCLE('',#1519,3.E0);\r\n#1529=CIRCLE('',#1528,1.E0);\r\n#1538=CIRCLE('',#1537,1.E0);\r\n#1547=CIRCLE('',#1546,1.E0);\r\n#1556=CIRCLE('',#1555,1.E0);\r\n#1597=CIRCLE('',#1596,1.E0);\r\n#1606=CIRCLE('',#1605,1.E0);\r\n#1675=CIRCLE('',#1674,9.5E-2);\r\n#1680=CIRCLE('',#1679,9.5E-2);\r\n#1685=CIRCLE('',#1684,6.25E-2);\r\n#1690=CIRCLE('',#1689,6.25E-2);\r\n#1707=CIRCLE('',#1706,1.E0);\r\n#1716=CIRCLE('',#1715,1.E0);\r\n#1729=CIRCLE('',#1728,1.E0);\r\n#1738=CIRCLE('',#1737,1.E0);\r\n#1767=CIRCLE('',#1766,1.625E-1);\r\n#1772=CIRCLE('',#1771,1.625E-1);\r\n#1846=B_SPLINE_CURVE_WITH_KNOTS('',3,(#1837,#1838,#1839,#1840,#1841,#1842,#1843,\r\n#1844,#1845),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1,\r\n6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.);\r\n#1856=B_SPLINE_CURVE_WITH_KNOTS('',3,(#1847,#1848,#1849,#1850,#1851,#1852,#1853,\r\n#1854,#1855),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1,\r\n6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.);\r\n#1873=CIRCLE('',#1872,2.575E-1);\r\n#1878=CIRCLE('',#1877,2.575E-1);\r\n#1883=CIRCLE('',#1882,1.925E-1);\r\n#1888=CIRCLE('',#1887,1.925E-1);\r\n#1933=CIRCLE('',#1932,9.5E-2);\r\n#1938=CIRCLE('',#1937,9.5E-2);\r\n#1943=CIRCLE('',#1942,6.25E-2);\r\n#1948=CIRCLE('',#1947,6.25E-2);\r\n#1961=CIRCLE('',#1960,9.5E-2);\r\n#1966=CIRCLE('',#1965,9.5E-2);\r\n#1979=CIRCLE('',#1978,6.25E-2);\r\n#1984=CIRCLE('',#1983,6.25E-2);\r\n#1993=CIRCLE('',#1992,3.5E-1);\r\n#2002=CIRCLE('',#2001,3.5E-1);\r\n#2035=CIRCLE('',#2034,3.5E-1);\r\n#2044=CIRCLE('',#2043,3.5E-1);\r\n#2053=CIRCLE('',#2052,3.5E-1);\r\n#2062=CIRCLE('',#2061,3.5E-1);\r\n#2071=CIRCLE('',#2070,3.5E-1);\r\n#2080=CIRCLE('',#2079,3.5E-1);\r\n#2089=CIRCLE('',#2088,3.5E-1);\r\n#2098=CIRCLE('',#2097,3.5E-1);\r\n#2107=CIRCLE('',#2106,3.5E-1);\r\n#2116=CIRCLE('',#2115,3.5E-1);\r\n#2145=CIRCLE('',#2144,9.5E-2);\r\n#2150=CIRCLE('',#2149,9.5E-2);\r\n#2163=CIRCLE('',#2162,6.25E-2);\r\n#2168=CIRCLE('',#2167,6.25E-2);\r\n#2189=CIRCLE('',#2188,1.E-1);\r\n#2194=CIRCLE('',#2193,1.E-1);\r\n#2215=CIRCLE('',#2214,1.E-1);\r\n#2220=CIRCLE('',#2219,1.E-1);\r\n#2233=CIRCLE('',#2232,2.575E-1);\r\n#2238=CIRCLE('',#2237,2.575E-1);\r\n#2243=CIRCLE('',#2242,1.925E-1);\r\n#2248=CIRCLE('',#2247,1.925E-1);\r\n#2269=CIRCLE('',#2268,2.575E-1);\r\n#2274=CIRCLE('',#2273,2.575E-1);\r\n#2279=CIRCLE('',#2278,1.925E-1);\r\n#2284=CIRCLE('',#2283,1.925E-1);\r\n#2305=CIRCLE('',#2304,2.575E-1);\r\n#2310=CIRCLE('',#2309,2.575E-1);\r\n#2315=CIRCLE('',#2314,1.925E-1);\r\n#2320=CIRCLE('',#2319,1.925E-1);\r\n#2341=CIRCLE('',#2340,2.575E-1);\r\n#2346=CIRCLE('',#2345,2.575E-1);\r\n#2351=CIRCLE('',#2350,1.925E-1);\r\n#2356=CIRCLE('',#2355,1.925E-1);\r\n#2377=CIRCLE('',#2376,2.575E-1);\r\n#2382=CIRCLE('',#2381,2.575E-1);\r\n#2387=CIRCLE('',#2386,1.925E-1);\r\n#2392=CIRCLE('',#2391,1.925E-1);\r\n#2413=CIRCLE('',#2412,2.575E-1);\r\n#2418=CIRCLE('',#2417,2.575E-1);\r\n#2423=CIRCLE('',#2422,1.925E-1);\r\n#2428=CIRCLE('',#2427,1.925E-1);\r\n#2449=CIRCLE('',#2448,2.56E-1);\r\n#2454=CIRCLE('',#2453,2.56E-1);\r\n#2459=CIRCLE('',#2458,1.925E-1);\r\n#2464=CIRCLE('',#2463,1.925E-1);\r\n#2485=CIRCLE('',#2484,2.56E-1);\r\n#2490=CIRCLE('',#2489,2.56E-1);\r\n#2495=CIRCLE('',#2494,1.925E-1);\r\n#2500=CIRCLE('',#2499,1.925E-1);\r\n#2521=CIRCLE('',#2520,2.56E-1);\r\n#2526=CIRCLE('',#2525,2.56E-1);\r\n#2531=CIRCLE('',#2530,1.925E-1);\r\n#2536=CIRCLE('',#2535,1.925E-1);\r\n#2557=CIRCLE('',#2556,2.56E-1);\r\n#2562=CIRCLE('',#2561,2.56E-1);\r\n#2567=CIRCLE('',#2566,1.925E-1);\r\n#2572=CIRCLE('',#2571,1.925E-1);\r\n#2593=CIRCLE('',#2592,2.56E-1);\r\n#2598=CIRCLE('',#2597,2.56E-1);\r\n#2603=CIRCLE('',#2602,1.925E-1);\r\n#2608=CIRCLE('',#2607,1.925E-1);\r\n#2629=CIRCLE('',#2628,2.56E-1);\r\n#2634=CIRCLE('',#2633,2.56E-1);\r\n#2639=CIRCLE('',#2638,1.925E-1);\r\n#2644=CIRCLE('',#2643,1.925E-1);\r\n#2665=CIRCLE('',#2664,2.575E-1);\r\n#2670=CIRCLE('',#2669,2.575E-1);\r\n#2675=CIRCLE('',#2674,1.925E-1);\r\n#2680=CIRCLE('',#2679,1.925E-1);\r\n#2701=CIRCLE('',#2700,2.575E-1);\r\n#2706=CIRCLE('',#2705,2.575E-1);\r\n#2711=CIRCLE('',#2710,1.925E-1);\r\n#2716=CIRCLE('',#2715,1.925E-1);\r\n#2737=CIRCLE('',#2736,2.575E-1);\r\n#2742=CIRCLE('',#2741,2.575E-1);\r\n#2747=CIRCLE('',#2746,1.925E-1);\r\n#2752=CIRCLE('',#2751,1.925E-1);\r\n#2773=CIRCLE('',#2772,2.575E-1);\r\n#2778=CIRCLE('',#2777,2.575E-1);\r\n#2783=CIRCLE('',#2782,1.925E-1);\r\n#2788=CIRCLE('',#2787,1.925E-1);\r\n#2809=CIRCLE('',#2808,2.575E-1);\r\n#2814=CIRCLE('',#2813,2.575E-1);\r\n#2819=CIRCLE('',#2818,1.925E-1);\r\n#2824=CIRCLE('',#2823,1.925E-1);\r\n#2845=CIRCLE('',#2844,2.575E-1);\r\n#2850=CIRCLE('',#2849,2.575E-1);\r\n#2855=CIRCLE('',#2854,1.925E-1);\r\n#2860=CIRCLE('',#2859,1.925E-1);\r\n#2882=B_SPLINE_CURVE_WITH_KNOTS('',3,(#2873,#2874,#2875,#2876,#2877,#2878,#2879,\r\n#2880,#2881),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1,\r\n6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.);\r\n#2892=B_SPLINE_CURVE_WITH_KNOTS('',3,(#2883,#2884,#2885,#2886,#2887,#2888,#2889,\r\n#2890,#2891),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1,\r\n6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.);\r\n#2905=CIRCLE('',#2904,2.575E-1);\r\n#2910=CIRCLE('',#2909,2.575E-1);\r\n#2915=CIRCLE('',#2914,1.925E-1);\r\n#2920=CIRCLE('',#2919,1.925E-1);\r\n#2937=CIRCLE('',#2936,3.5E-1);\r\n#2946=CIRCLE('',#2945,3.5E-1);\r\n#2955=CIRCLE('',#2954,3.5E-1);\r\n#2964=CIRCLE('',#2963,3.5E-1);\r\n#2973=CIRCLE('',#2972,3.5E-1);\r\n#2982=CIRCLE('',#2981,3.5E-1);\r\n#2991=CIRCLE('',#2990,3.5E-1);\r\n#3000=CIRCLE('',#2999,3.5E-1);\r\n#3009=CIRCLE('',#3008,3.5E-1);\r\n#3018=CIRCLE('',#3017,3.5E-1);\r\n#3027=CIRCLE('',#3026,3.5E-1);\r\n#3036=CIRCLE('',#3035,3.5E-1);\r\n#3073=CIRCLE('',#3072,9.5E-2);\r\n#3078=CIRCLE('',#3077,9.5E-2);\r\n#3091=CIRCLE('',#3090,9.5E-2);\r\n#3096=CIRCLE('',#3095,9.5E-2);\r\n#3109=CIRCLE('',#3108,9.5E-2);\r\n#3114=CIRCLE('',#3113,9.5E-2);\r\n#3127=CIRCLE('',#3126,9.5E-2);\r\n#3132=CIRCLE('',#3131,9.5E-2);\r\n#3145=CIRCLE('',#3144,9.5E-2);\r\n#3150=CIRCLE('',#3149,9.5E-2);\r\n#3159=CIRCLE('',#3158,7.5E-1);\r\n#3168=CIRCLE('',#3167,7.5E-1);\r\n#3177=CIRCLE('',#3176,7.5E-1);\r\n#3186=CIRCLE('',#3185,7.5E-1);\r\n#3195=CIRCLE('',#3194,7.5E-1);\r\n#3204=CIRCLE('',#3203,7.5E-1);\r\n#3213=CIRCLE('',#3212,7.5E-1);\r\n#3222=CIRCLE('',#3221,7.5E-1);\r\n#3247=CIRCLE('',#3246,7.5E-1);\r\n#3256=CIRCLE('',#3255,7.5E-1);\r\n#3281=CIRCLE('',#3280,7.5E-1);\r\n#3290=CIRCLE('',#3289,7.5E-1);\r\n#3299=CIRCLE('',#3298,7.5E-1);\r\n#3308=CIRCLE('',#3307,7.5E-1);\r\n#3317=CIRCLE('',#3316,7.5E-1);\r\n#3326=CIRCLE('',#3325,7.5E-1);\r\n#3351=CIRCLE('',#3350,5.625E-1);\r\n#3360=CIRCLE('',#3359,5.625E-1);\r\n#3365=CIRCLE('',#3364,9.225E-1);\r\n#3370=CIRCLE('',#3369,5.6875E0);\r\n#3375=CIRCLE('',#3374,8.669989027347E-1);\r\n#3388=CIRCLE('',#3387,7.5E-1);\r\n#3397=CIRCLE('',#3396,7.5E-1);\r\n#3418=CIRCLE('',#3417,8.75E-1);\r\n#3427=CIRCLE('',#3426,8.75E-1);\r\n#3440=CIRCLE('',#3439,5.6125E-1);\r\n#3469=CIRCLE('',#3468,8.75E-1);\r\n#3478=CIRCLE('',#3477,8.75E-1);\r\n#3495=CIRCLE('',#3494,8.75E-1);\r\n#3504=CIRCLE('',#3503,8.75E-1);\r\n#3513=CIRCLE('',#3512,8.75E-1);\r\n#3522=CIRCLE('',#3521,8.75E-1);\r\n#3531=CIRCLE('',#3530,8.75E-1);\r\n#3540=CIRCLE('',#3539,8.75E-1);\r\n#3549=CIRCLE('',#3548,8.75E-1);\r\n#3558=CIRCLE('',#3557,8.75E-1);\r\n#3583=CIRCLE('',#3582,5.625E-1);\r\n#3592=CIRCLE('',#3591,5.625E-1);\r\n#3617=CIRCLE('',#3616,5.625E-1);\r\n#3626=CIRCLE('',#3625,5.625E-1);\r\n#3651=CIRCLE('',#3650,5.E-1);\r\n#3660=CIRCLE('',#3659,5.E-1);\r\n#3685=CIRCLE('',#3684,4.375E-1);\r\n#3694=CIRCLE('',#3693,4.375E-1);\r\n#3719=CIRCLE('',#3718,5.625E-1);\r\n#3728=CIRCLE('',#3727,5.625E-1);\r\n#3737=CIRCLE('',#3736,8.669989027347E-1);\r\n#3742=CIRCLE('',#3741,5.6875E0);\r\n#3747=CIRCLE('',#3746,9.225E-1);\r\n#3756=CIRCLE('',#3755,7.5E-1);\r\n#3765=CIRCLE('',#3764,7.5E-1);\r\n#3802=CIRCLE('',#3801,5.625E-1);\r\n#3811=CIRCLE('',#3810,5.625E-1);\r\n#3820=CIRCLE('',#3819,8.669989027347E-1);\r\n#3825=CIRCLE('',#3824,5.6875E0);\r\n#3830=CIRCLE('',#3829,9.225E-1);\r\n#3839=CIRCLE('',#3838,7.5E-1);\r\n#3848=CIRCLE('',#3847,7.5E-1);\r\n#3885=CIRCLE('',#3884,5.625E-1);\r\n#3894=CIRCLE('',#3893,5.625E-1);\r\n#3919=CIRCLE('',#3918,5.625E-1);\r\n#3928=CIRCLE('',#3927,5.625E-1);\r\n#3953=CIRCLE('',#3952,5.E-1);\r\n#3962=CIRCLE('',#3961,5.E-1);\r\n#3987=CIRCLE('',#3986,4.375E-1);\r\n#3996=CIRCLE('',#3995,4.375E-1);\r\n#4021=CIRCLE('',#4020,5.625E-1);\r\n#4030=CIRCLE('',#4029,5.625E-1);\r\n#4035=CIRCLE('',#4034,9.225E-1);\r\n#4040=CIRCLE('',#4039,5.6875E0);\r\n#4045=CIRCLE('',#4044,8.669989027347E-1);\r\n#4058=CIRCLE('',#4057,7.5E-1);\r\n#4067=CIRCLE('',#4066,7.5E-1);\r\n#4088=CIRCLE('',#4087,8.8E-1);\r\n#4097=CIRCLE('',#4096,8.8E-1);\r\n#4106=CIRCLE('',#4105,8.8E-1);\r\n#4115=CIRCLE('',#4114,8.8E-1);\r\n#4124=CIRCLE('',#4123,8.8E-1);\r\n#4133=CIRCLE('',#4132,8.8E-1);\r\n#4142=CIRCLE('',#4141,8.8E-1);\r\n#4151=CIRCLE('',#4150,8.8E-1);\r\n#4160=CIRCLE('',#4159,8.8E-1);\r\n#4169=CIRCLE('',#4168,8.8E-1);\r\n#4178=CIRCLE('',#4177,8.8E-1);\r\n#4187=CIRCLE('',#4186,8.8E-1);\r\n#4208=CIRCLE('',#4207,5.6125E-1);\r\n#5494=EDGE_CURVE('',#4423,#4400,#132,.T.);\r\n#5496=EDGE_CURVE('',#4419,#4423,#1597,.T.);\r\n#5498=EDGE_CURVE('',#4419,#4243,#136,.T.);\r\n#5500=EDGE_CURVE('',#4239,#4243,#1614,.T.);\r\n#5502=EDGE_CURVE('',#4239,#4259,#140,.T.);\r\n#5504=EDGE_CURVE('',#4255,#4259,#1630,.T.);\r\n#5506=EDGE_CURVE('',#4255,#4320,#144,.T.);\r\n#5508=EDGE_CURVE('',#4324,#4320,#1376,.T.);\r\n#5510=EDGE_CURVE('',#4324,#4300,#148,.T.);\r\n#5512=EDGE_CURVE('',#4300,#4347,#152,.T.);\r\n#5514=EDGE_CURVE('',#4343,#4347,#1912,.T.);\r\n#5516=EDGE_CURVE('',#4343,#4315,#156,.T.);\r\n#5518=EDGE_CURVE('',#4311,#4315,#1385,.T.);\r\n#5520=EDGE_CURVE('',#4311,#4251,#160,.T.);\r\n#5522=EDGE_CURVE('',#4247,#4251,#1580,.T.);\r\n#5524=EDGE_CURVE('',#4247,#4235,#164,.T.);\r\n#5526=EDGE_CURVE('',#4231,#4235,#1564,.T.);\r\n#5528=EDGE_CURVE('',#4231,#4404,#168,.T.);\r\n#5530=EDGE_CURVE('',#4408,#4404,#1556,.T.);\r\n#5532=EDGE_CURVE('',#4444,#4408,#172,.T.);\r\n#5534=EDGE_CURVE('',#4444,#4448,#1654,.T.);\r\n#5536=EDGE_CURVE('',#4400,#4448,#176,.T.);\r\n#5540=EDGE_CURVE('',#4427,#4328,#4,.T.);\r\n#5542=EDGE_CURVE('',#4332,#4328,#1358,.T.);\r\n#5544=EDGE_CURVE('',#4264,#4332,#1340,.T.);\r\n#5546=EDGE_CURVE('',#4268,#4264,#8,.T.);\r\n#5548=EDGE_CURVE('',#4431,#4268,#1317,.T.);\r\n#5550=EDGE_CURVE('',#4427,#4431,#1303,.T.);\r\n#5554=EDGE_CURVE('',#4639,#4640,#13,.T.);\r\n#5556=EDGE_CURVE('',#4640,#4639,#18,.T.);\r\n#5560=EDGE_CURVE('',#4635,#4636,#23,.T.);\r\n#5562=EDGE_CURVE('',#4636,#4635,#28,.T.);\r\n#5566=EDGE_CURVE('',#4631,#4632,#33,.T.);\r\n#5568=EDGE_CURVE('',#4632,#4631,#38,.T.);\r\n#5572=EDGE_CURVE('',#4627,#4628,#43,.T.);\r\n#5574=EDGE_CURVE('',#4628,#4627,#48,.T.);\r\n#5578=EDGE_CURVE('',#4623,#4624,#53,.T.);\r\n#5580=EDGE_CURVE('',#4624,#4623,#58,.T.);\r\n#5584=EDGE_CURVE('',#4527,#4528,#63,.T.);\r\n#5586=EDGE_CURVE('',#4528,#4527,#68,.T.);\r\n#5590=EDGE_CURVE('',#4523,#4524,#73,.T.);\r\n#5592=EDGE_CURVE('',#4524,#4523,#78,.T.);\r\n#5596=EDGE_CURVE('',#4519,#4520,#83,.T.);\r\n#5598=EDGE_CURVE('',#4520,#4519,#88,.T.);\r\n#5602=EDGE_CURVE('',#4515,#4516,#93,.T.);\r\n#5604=EDGE_CURVE('',#4516,#4515,#98,.T.);\r\n#5608=EDGE_CURVE('',#4511,#4512,#103,.T.);\r\n#5610=EDGE_CURVE('',#4512,#4511,#108,.T.);\r\n#5614=EDGE_CURVE('',#4507,#4508,#113,.T.);\r\n#5616=EDGE_CURVE('',#4508,#4507,#118,.T.);\r\n#5620=EDGE_CURVE('',#4503,#4504,#123,.T.);\r\n#5622=EDGE_CURVE('',#4504,#4503,#128,.T.);\r\n#5626=EDGE_CURVE('',#4487,#4488,#181,.T.);\r\n#5628=EDGE_CURVE('',#4488,#4487,#186,.T.);\r\n#5632=EDGE_CURVE('',#4607,#4608,#191,.T.);\r\n#5634=EDGE_CURVE('',#4608,#4607,#196,.T.);\r\n#5638=EDGE_CURVE('',#4796,#4803,#200,.T.);\r\n#5640=EDGE_CURVE('',#4799,#4803,#1439,.T.);\r\n#5642=EDGE_CURVE('',#4280,#4799,#204,.T.);\r\n#5644=EDGE_CURVE('',#4284,#4280,#1466,.T.);\r\n#5646=EDGE_CURVE('',#4272,#4284,#208,.T.);\r\n#5648=EDGE_CURVE('',#4276,#4272,#1484,.T.);\r\n#5650=EDGE_CURVE('',#4792,#4276,#212,.T.);\r\n#5652=EDGE_CURVE('',#4796,#4792,#1430,.T.);\r\n#5656=EDGE_CURVE('',#4808,#4411,#216,.T.);\r\n#5658=EDGE_CURVE('',#4812,#4808,#1502,.T.);\r\n#5660=EDGE_CURVE('',#4812,#4819,#220,.T.);\r\n#5662=EDGE_CURVE('',#4815,#4819,#1511,.T.);\r\n#5664=EDGE_CURVE('',#4304,#4815,#224,.T.);\r\n#5666=EDGE_CURVE('',#4308,#4304,#1412,.T.);\r\n#5668=EDGE_CURVE('',#4308,#4339,#228,.T.);\r\n#5670=EDGE_CURVE('',#4335,#4339,#1754,.T.);\r\n#5672=EDGE_CURVE('',#4335,#4772,#232,.T.);\r\n#5674=EDGE_CURVE('',#4776,#4772,#1738,.T.);\r\n#5676=EDGE_CURVE('',#4776,#4783,#236,.T.);\r\n#5678=EDGE_CURVE('',#4779,#4783,#1707,.T.);\r\n#5680=EDGE_CURVE('',#4436,#4779,#240,.T.);\r\n#5682=EDGE_CURVE('',#4436,#4440,#2132,.T.);\r\n#5684=EDGE_CURVE('',#4415,#4440,#244,.T.);\r\n#5686=EDGE_CURVE('',#4411,#4415,#1529,.T.);\r\n#5690=EDGE_CURVE('',#4823,#4824,#249,.T.);\r\n#5692=EDGE_CURVE('',#4824,#4823,#254,.T.);\r\n#5696=EDGE_CURVE('',#4839,#4840,#259,.T.);\r\n#5698=EDGE_CURVE('',#4840,#4839,#264,.T.);\r\n#5702=EDGE_CURVE('',#4843,#4844,#269,.T.);\r\n#5704=EDGE_CURVE('',#4844,#4843,#274,.T.);\r\n#5708=EDGE_CURVE('',#4847,#4848,#279,.T.);\r\n#5710=EDGE_CURVE('',#4848,#4847,#284,.T.);\r\n#5714=EDGE_CURVE('',#4851,#4852,#289,.T.);\r\n#5716=EDGE_CURVE('',#4852,#4851,#294,.T.);\r\n#5720=EDGE_CURVE('',#4855,#4856,#299,.T.);\r\n#5722=EDGE_CURVE('',#4856,#4855,#304,.T.);\r\n#5726=EDGE_CURVE('',#5121,#5122,#308,.T.);\r\n#5728=EDGE_CURVE('',#5122,#5124,#313,.T.);\r\n#5730=EDGE_CURVE('',#5124,#5126,#317,.T.);\r\n#5732=EDGE_CURVE('',#5126,#5121,#322,.T.);\r\n#5736=EDGE_CURVE('',#5132,#5139,#327,.T.);\r\n#5738=EDGE_CURVE('',#5135,#5139,#3388,.T.);\r\n#5740=EDGE_CURVE('',#5135,#5129,#331,.T.);\r\n#5742=EDGE_CURVE('',#5129,#5130,#336,.T.);\r\n#5744=EDGE_CURVE('',#5132,#5130,#341,.T.);\r\n#5748=EDGE_CURVE('',#5184,#5186,#3418,.T.);\r\n#5750=EDGE_CURVE('',#5184,#5147,#345,.T.);\r\n#5752=EDGE_CURVE('',#5147,#5148,#350,.T.);\r\n#5754=EDGE_CURVE('',#5148,#5194,#354,.T.);\r\n#5756=EDGE_CURVE('',#5192,#5194,#3469,.T.);\r\n#5758=EDGE_CURVE('',#5192,#5171,#358,.T.);\r\n#5760=EDGE_CURVE('',#5167,#5171,#3495,.T.);\r\n#5762=EDGE_CURVE('',#5167,#5179,#362,.T.);\r\n#5764=EDGE_CURVE('',#5175,#5179,#3513,.T.);\r\n#5766=EDGE_CURVE('',#5175,#5155,#366,.T.);\r\n#5768=EDGE_CURVE('',#5151,#5155,#3531,.T.);\r\n#5770=EDGE_CURVE('',#5151,#5163,#370,.T.);\r\n#5772=EDGE_CURVE('',#5159,#5163,#3549,.T.);\r\n#5774=EDGE_CURVE('',#5159,#5186,#374,.T.);\r\n#5778=EDGE_CURVE('',#5207,#5208,#378,.T.);\r\n#5780=EDGE_CURVE('',#5208,#5210,#383,.T.);\r\n#5782=EDGE_CURVE('',#5210,#5212,#387,.T.);\r\n#5784=EDGE_CURVE('',#5212,#5207,#392,.T.);\r\n#5788=EDGE_CURVE('',#5223,#5224,#396,.T.);\r\n#5790=EDGE_CURVE('',#5224,#5226,#401,.T.);\r\n#5792=EDGE_CURVE('',#5226,#5228,#405,.T.);\r\n#5794=EDGE_CURVE('',#5228,#5223,#410,.T.);\r\n#5798=EDGE_CURVE('',#5239,#5240,#414,.T.);\r\n#5800=EDGE_CURVE('',#5240,#5242,#419,.T.);\r\n#5802=EDGE_CURVE('',#5242,#5244,#423,.T.);\r\n#5804=EDGE_CURVE('',#5244,#5239,#428,.T.);\r\n#5808=EDGE_CURVE('',#5255,#5256,#432,.T.);\r\n#5810=EDGE_CURVE('',#5256,#5258,#437,.T.);\r\n#5812=EDGE_CURVE('',#5258,#5260,#441,.T.);\r\n#5814=EDGE_CURVE('',#5260,#5255,#446,.T.);\r\n#5818=EDGE_CURVE('',#5277,#5278,#450,.T.);\r\n#5820=EDGE_CURVE('',#5282,#5277,#455,.T.);\r\n#5822=EDGE_CURVE('',#5280,#5282,#459,.T.);\r\n#5824=EDGE_CURVE('',#5278,#5280,#464,.T.);\r\n#5828=EDGE_CURVE('',#5305,#5306,#468,.T.);\r\n#5830=EDGE_CURVE('',#5310,#5305,#473,.T.);\r\n#5832=EDGE_CURVE('',#5308,#5310,#477,.T.);\r\n#5834=EDGE_CURVE('',#5306,#5308,#482,.T.);\r\n#5838=EDGE_CURVE('',#5335,#5336,#486,.T.);\r\n#5840=EDGE_CURVE('',#5340,#5335,#491,.T.);\r\n#5842=EDGE_CURVE('',#5338,#5340,#495,.T.);\r\n#5844=EDGE_CURVE('',#5336,#5338,#500,.T.);\r\n#5848=EDGE_CURVE('',#5351,#5352,#504,.T.);\r\n#5850=EDGE_CURVE('',#5356,#5351,#509,.T.);\r\n#5852=EDGE_CURVE('',#5354,#5356,#513,.T.);\r\n#5854=EDGE_CURVE('',#5352,#5354,#518,.T.);\r\n#5858=EDGE_CURVE('',#5367,#5368,#522,.T.);\r\n#5860=EDGE_CURVE('',#5372,#5367,#527,.T.);\r\n#5862=EDGE_CURVE('',#5370,#5372,#531,.T.);\r\n#5864=EDGE_CURVE('',#5368,#5370,#536,.T.);\r\n#5868=EDGE_CURVE('',#5383,#5384,#540,.T.);\r\n#5870=EDGE_CURVE('',#5388,#5383,#545,.T.);\r\n#5872=EDGE_CURVE('',#5386,#5388,#549,.T.);\r\n#5874=EDGE_CURVE('',#5384,#5386,#554,.T.);\r\n#5878=EDGE_CURVE('',#5405,#5406,#558,.T.);\r\n#5880=EDGE_CURVE('',#5406,#5408,#563,.T.);\r\n#5882=EDGE_CURVE('',#5408,#5410,#567,.T.);\r\n#5884=EDGE_CURVE('',#5410,#5405,#572,.T.);\r\n#5888=EDGE_CURVE('',#5455,#5451,#4097,.T.);\r\n#5890=EDGE_CURVE('',#5324,#5455,#576,.T.);\r\n#5892=EDGE_CURVE('',#5323,#5324,#581,.T.);\r\n#5894=EDGE_CURVE('',#5459,#5323,#585,.T.);\r\n#5896=EDGE_CURVE('',#5463,#5459,#4187,.T.);\r\n#5898=EDGE_CURVE('',#5436,#5463,#589,.T.);\r\n#5900=EDGE_CURVE('',#5440,#5436,#4169,.T.);\r\n#5902=EDGE_CURVE('',#5444,#5440,#593,.T.);\r\n#5904=EDGE_CURVE('',#5448,#5444,#4151,.T.);\r\n#5906=EDGE_CURVE('',#5428,#5448,#597,.T.);\r\n#5908=EDGE_CURVE('',#5432,#5428,#4133,.T.);\r\n#5910=EDGE_CURVE('',#5420,#5432,#601,.T.);\r\n#5912=EDGE_CURVE('',#5424,#5420,#4115,.T.);\r\n#5914=EDGE_CURVE('',#5451,#5424,#605,.T.);\r\n#5918=EDGE_CURVE('',#5471,#5313,#609,.T.);\r\n#5920=EDGE_CURVE('',#5467,#5471,#3839,.T.);\r\n#5922=EDGE_CURVE('',#5316,#5467,#614,.T.);\r\n#5924=EDGE_CURVE('',#5316,#5314,#619,.T.);\r\n#5926=EDGE_CURVE('',#5313,#5314,#624,.T.);\r\n#5930=EDGE_CURVE('',#5479,#5285,#628,.T.);\r\n#5932=EDGE_CURVE('',#5475,#5479,#3756,.T.);\r\n#5934=EDGE_CURVE('',#5288,#5475,#633,.T.);\r\n#5936=EDGE_CURVE('',#5288,#5286,#638,.T.);\r\n#5938=EDGE_CURVE('',#5285,#5286,#643,.T.);\r\n#5942=EDGE_CURVE('',#5416,#5487,#648,.T.);\r\n#5944=EDGE_CURVE('',#5483,#5487,#4058,.T.);\r\n#5946=EDGE_CURVE('',#5483,#5413,#652,.T.);\r\n#5948=EDGE_CURVE('',#5413,#5414,#657,.T.);\r\n#5950=EDGE_CURVE('',#5416,#5414,#662,.T.);\r\n#5961=EDGE_CURVE('',#4427,#4428,#1298,.T.);\r\n#5963=EDGE_CURVE('',#4424,#4428,#906,.T.);\r\n#5965=EDGE_CURVE('',#4423,#4424,#1601,.T.);\r\n#5968=EDGE_CURVE('',#4390,#4400,#1658,.T.);\r\n#5970=EDGE_CURVE('',#4387,#4390,#746,.T.);\r\n#5972=EDGE_CURVE('',#4387,#4388,#750,.T.);\r\n#5974=EDGE_CURVE('',#4768,#4388,#1698,.T.);\r\n#5976=EDGE_CURVE('',#4767,#4768,#1230,.T.);\r\n#5978=EDGE_CURVE('',#4287,#4767,#1746,.T.);\r\n#5980=EDGE_CURVE('',#4287,#4288,#754,.T.);\r\n#5982=EDGE_CURVE('',#4288,#4290,#758,.T.);\r\n#5984=EDGE_CURVE('',#4300,#4290,#1900,.T.);\r\n#5987=EDGE_CURVE('',#4323,#4324,#1371,.T.);\r\n#5989=EDGE_CURVE('',#4327,#4323,#914,.T.);\r\n#5991=EDGE_CURVE('',#4327,#4328,#1344,.T.);\r\n#5995=EDGE_CURVE('',#4747,#4748,#667,.T.);\r\n#5997=EDGE_CURVE('',#4748,#4747,#672,.T.);\r\n#6001=EDGE_CURVE('',#4735,#4736,#677,.T.);\r\n#6003=EDGE_CURVE('',#4736,#4735,#682,.T.);\r\n#6007=EDGE_CURVE('',#4755,#4756,#687,.T.);\r\n#6009=EDGE_CURVE('',#4756,#4755,#692,.T.);\r\n#6013=EDGE_CURVE('',#4763,#4764,#697,.T.);\r\n#6015=EDGE_CURVE('',#4764,#4763,#702,.T.);\r\n#6019=EDGE_CURVE('',#4731,#4732,#707,.T.);\r\n#6021=EDGE_CURVE('',#4732,#4731,#712,.T.);\r\n#6025=EDGE_CURVE('',#4723,#4724,#717,.T.);\r\n#6027=EDGE_CURVE('',#4724,#4723,#722,.T.);\r\n#6031=EDGE_CURVE('',#4703,#4704,#727,.T.);\r\n#6033=EDGE_CURVE('',#4704,#4703,#732,.T.);\r\n#6037=EDGE_CURVE('',#4715,#4716,#737,.T.);\r\n#6039=EDGE_CURVE('',#4716,#4715,#742,.T.);\r\n#6043=EDGE_CURVE('',#4947,#4959,#762,.T.);\r\n#6045=EDGE_CURVE('',#4955,#4959,#3213,.T.);\r\n#6047=EDGE_CURVE('',#4955,#4967,#766,.T.);\r\n#6049=EDGE_CURVE('',#4963,#4967,#3195,.T.);\r\n#6051=EDGE_CURVE('',#4963,#4975,#770,.T.);\r\n#6053=EDGE_CURVE('',#4971,#4975,#3177,.T.);\r\n#6055=EDGE_CURVE('',#4971,#4951,#774,.T.);\r\n#6057=EDGE_CURVE('',#4947,#4951,#3159,.T.);\r\n#6061=EDGE_CURVE('',#5036,#5048,#778,.T.);\r\n#6063=EDGE_CURVE('',#5040,#5036,#3256,.T.);\r\n#6065=EDGE_CURVE('',#5028,#5040,#782,.T.);\r\n#6067=EDGE_CURVE('',#5032,#5028,#3290,.T.);\r\n#6069=EDGE_CURVE('',#5052,#5032,#786,.T.);\r\n#6071=EDGE_CURVE('',#5056,#5052,#3308,.T.);\r\n#6073=EDGE_CURVE('',#5044,#5056,#790,.T.);\r\n#6075=EDGE_CURVE('',#5048,#5044,#3326,.T.);\r\n#6086=EDGE_CURVE('',#4747,#4743,#794,.T.);\r\n#6088=EDGE_CURVE('',#4743,#4744,#803,.T.);\r\n#6090=EDGE_CURVE('',#4748,#4744,#798,.T.);\r\n#6102=EDGE_CURVE('',#4744,#4743,#808,.T.);\r\n#6124=EDGE_CURVE('',#4735,#4739,#812,.T.);\r\n#6126=EDGE_CURVE('',#4739,#4740,#821,.T.);\r\n#6128=EDGE_CURVE('',#4736,#4740,#816,.T.);\r\n#6140=EDGE_CURVE('',#4740,#4739,#826,.T.);\r\n#6151=EDGE_CURVE('',#4934,#4940,#830,.T.);\r\n#6153=EDGE_CURVE('',#4940,#4942,#834,.T.);\r\n#6155=EDGE_CURVE('',#4938,#4942,#838,.T.);\r\n#6157=EDGE_CURVE('',#4788,#4938,#1234,.T.);\r\n#6159=EDGE_CURVE('',#4788,#4393,#842,.T.);\r\n#6161=EDGE_CURVE('',#4393,#4394,#846,.T.);\r\n#6163=EDGE_CURVE('',#4394,#4396,#850,.T.);\r\n#6165=EDGE_CURVE('',#4396,#4398,#854,.T.);\r\n#6167=EDGE_CURVE('',#4934,#4398,#1178,.T.);\r\n#6175=EDGE_CURVE('',#5103,#5099,#2946,.T.);\r\n#6177=EDGE_CURVE('',#5076,#5103,#858,.T.);\r\n#6179=EDGE_CURVE('',#5080,#5076,#3036,.T.);\r\n#6181=EDGE_CURVE('',#5084,#5080,#862,.T.);\r\n#6183=EDGE_CURVE('',#5088,#5084,#3018,.T.);\r\n#6185=EDGE_CURVE('',#5092,#5088,#866,.T.);\r\n#6187=EDGE_CURVE('',#5096,#5092,#3000,.T.);\r\n#6189=EDGE_CURVE('',#5068,#5096,#870,.T.);\r\n#6191=EDGE_CURVE('',#5072,#5068,#2982,.T.);\r\n#6193=EDGE_CURVE('',#5060,#5072,#874,.T.);\r\n#6195=EDGE_CURVE('',#5064,#5060,#2964,.T.);\r\n#6197=EDGE_CURVE('',#5099,#5064,#878,.T.);\r\n#6207=EDGE_CURVE('',#4933,#4934,#1174,.T.);\r\n#6209=EDGE_CURVE('',#4940,#4933,#882,.T.);\r\n#6221=EDGE_CURVE('',#4432,#4428,#1312,.T.);\r\n#6223=EDGE_CURVE('',#4267,#4432,#1326,.T.);\r\n#6225=EDGE_CURVE('',#4267,#4263,#910,.T.);\r\n#6227=EDGE_CURVE('',#4331,#4263,#1331,.T.);\r\n#6229=EDGE_CURVE('',#4327,#4331,#1349,.T.);\r\n#6232=EDGE_CURVE('',#4319,#4323,#1367,.T.);\r\n#6234=EDGE_CURVE('',#4256,#4319,#918,.T.);\r\n#6236=EDGE_CURVE('',#4256,#4260,#1638,.T.);\r\n#6238=EDGE_CURVE('',#4240,#4260,#922,.T.);\r\n#6240=EDGE_CURVE('',#4240,#4244,#1622,.T.);\r\n#6242=EDGE_CURVE('',#4420,#4244,#926,.T.);\r\n#6244=EDGE_CURVE('',#4424,#4420,#1606,.T.);\r\n#6248=EDGE_CURVE('',#4495,#4496,#951,.T.);\r\n#6250=EDGE_CURVE('',#4496,#4495,#956,.T.);\r\n#6254=EDGE_CURVE('',#4567,#4568,#981,.T.);\r\n#6256=EDGE_CURVE('',#4568,#4567,#986,.T.);\r\n#6260=EDGE_CURVE('',#4615,#4616,#1011,.T.);\r\n#6262=EDGE_CURVE('',#4616,#4615,#1016,.T.);\r\n#6266=EDGE_CURVE('',#4647,#4648,#1021,.T.);\r\n#6268=EDGE_CURVE('',#4648,#4647,#1026,.T.);\r\n#6272=EDGE_CURVE('',#4659,#4660,#1031,.T.);\r\n#6274=EDGE_CURVE('',#4660,#4659,#1036,.T.);\r\n#6286=EDGE_CURVE('',#4398,#4447,#1182,.T.);\r\n#6288=EDGE_CURVE('',#4443,#4447,#1646,.T.);\r\n#6290=EDGE_CURVE('',#4443,#4407,#1186,.T.);\r\n#6292=EDGE_CURVE('',#4403,#4407,#1547,.T.);\r\n#6294=EDGE_CURVE('',#4232,#4403,#1190,.T.);\r\n#6296=EDGE_CURVE('',#4232,#4236,#1572,.T.);\r\n#6298=EDGE_CURVE('',#4248,#4236,#1194,.T.);\r\n#6300=EDGE_CURVE('',#4248,#4252,#1588,.T.);\r\n#6302=EDGE_CURVE('',#4312,#4252,#1198,.T.);\r\n#6304=EDGE_CURVE('',#4316,#4312,#1394,.T.);\r\n#6306=EDGE_CURVE('',#4344,#4316,#1202,.T.);\r\n#6308=EDGE_CURVE('',#4344,#4348,#1920,.T.);\r\n#6310=EDGE_CURVE('',#4298,#4348,#1206,.T.);\r\n#6312=EDGE_CURVE('',#4298,#4920,#1210,.T.);\r\n#6314=EDGE_CURVE('',#4919,#4920,#1214,.T.);\r\n#6316=EDGE_CURVE('',#4919,#4923,#1218,.T.);\r\n#6318=EDGE_CURVE('',#4923,#4924,#1222,.T.);\r\n#6320=EDGE_CURVE('',#4924,#4786,#1226,.T.);\r\n#6322=EDGE_CURVE('',#4767,#4786,#1742,.T.);\r\n#6325=EDGE_CURVE('',#4768,#4788,#1694,.T.);\r\n#6328=EDGE_CURVE('',#4937,#4938,#1238,.T.);\r\n#6330=EDGE_CURVE('',#4933,#4937,#1242,.T.);\r\n#6334=EDGE_CURVE('',#4373,#4374,#887,.T.);\r\n#6336=EDGE_CURVE('',#4374,#4373,#892,.T.);\r\n#6340=EDGE_CURVE('',#4383,#4384,#897,.T.);\r\n#6342=EDGE_CURVE('',#4384,#4383,#902,.T.);\r\n#6346=EDGE_CURVE('',#4473,#4474,#931,.T.);\r\n#6348=EDGE_CURVE('',#4474,#4473,#936,.T.);\r\n#6352=EDGE_CURVE('',#4483,#4484,#941,.T.);\r\n#6354=EDGE_CURVE('',#4484,#4483,#946,.T.);\r\n#6358=EDGE_CURVE('',#4543,#4544,#961,.T.);\r\n#6360=EDGE_CURVE('',#4544,#4543,#966,.T.);\r\n#6364=EDGE_CURVE('',#4555,#4556,#971,.T.);\r\n#6366=EDGE_CURVE('',#4556,#4555,#976,.T.);\r\n#6370=EDGE_CURVE('',#4587,#4588,#991,.T.);\r\n#6372=EDGE_CURVE('',#4588,#4587,#996,.T.);\r\n#6376=EDGE_CURVE('',#4599,#4600,#1001,.T.);\r\n#6378=EDGE_CURVE('',#4600,#4599,#1006,.T.);\r\n#6382=EDGE_CURVE('',#4671,#4672,#1041,.T.);\r\n#6384=EDGE_CURVE('',#4672,#4671,#1046,.T.);\r\n#6388=EDGE_CURVE('',#4683,#4684,#1051,.T.);\r\n#6390=EDGE_CURVE('',#4684,#4683,#1056,.T.);\r\n#6394=EDGE_CURVE('',#4695,#4696,#1061,.T.);\r\n#6396=EDGE_CURVE('',#4696,#4695,#1066,.T.);\r\n#6400=EDGE_CURVE('',#4279,#4800,#1070,.T.);\r\n#6402=EDGE_CURVE('',#4804,#4800,#1448,.T.);\r\n#6404=EDGE_CURVE('',#4795,#4804,#1074,.T.);\r\n#6406=EDGE_CURVE('',#4791,#4795,#1421,.T.);\r\n#6408=EDGE_CURVE('',#4791,#4275,#1078,.T.);\r\n#6410=EDGE_CURVE('',#4271,#4275,#1475,.T.);\r\n#6412=EDGE_CURVE('',#4271,#4283,#1082,.T.);\r\n#6414=EDGE_CURVE('',#4279,#4283,#1457,.T.);\r\n#6418=EDGE_CURVE('',#4811,#4820,#1086,.T.);\r\n#6420=EDGE_CURVE('',#4807,#4811,#1493,.T.);\r\n#6422=EDGE_CURVE('',#4807,#4412,#1090,.T.);\r\n#6424=EDGE_CURVE('',#4416,#4412,#1538,.T.);\r\n#6426=EDGE_CURVE('',#4416,#4439,#1094,.T.);\r\n#6428=EDGE_CURVE('',#4435,#4439,#2124,.T.);\r\n#6430=EDGE_CURVE('',#4435,#4780,#1098,.T.);\r\n#6432=EDGE_CURVE('',#4784,#4780,#1716,.T.);\r\n#6434=EDGE_CURVE('',#4775,#4784,#1720,.T.);\r\n#6436=EDGE_CURVE('',#4771,#4775,#1729,.T.);\r\n#6438=EDGE_CURVE('',#4336,#4771,#1102,.T.);\r\n#6440=EDGE_CURVE('',#4336,#4340,#1762,.T.);\r\n#6442=EDGE_CURVE('',#4307,#4340,#1106,.T.);\r\n#6444=EDGE_CURVE('',#4303,#4307,#1403,.T.);\r\n#6446=EDGE_CURVE('',#4303,#4816,#1110,.T.);\r\n#6448=EDGE_CURVE('',#4820,#4816,#1520,.T.);\r\n#6452=EDGE_CURVE('',#4831,#4832,#1115,.T.);\r\n#6454=EDGE_CURVE('',#4832,#4831,#1120,.T.);\r\n#6458=EDGE_CURVE('',#4863,#4864,#1125,.T.);\r\n#6460=EDGE_CURVE('',#4864,#4863,#1130,.T.);\r\n#6464=EDGE_CURVE('',#4875,#4876,#1135,.T.);\r\n#6466=EDGE_CURVE('',#4876,#4875,#1140,.T.);\r\n#6470=EDGE_CURVE('',#4887,#4888,#1145,.T.);\r\n#6472=EDGE_CURVE('',#4888,#4887,#1150,.T.);\r\n#6476=EDGE_CURVE('',#4899,#4900,#1155,.T.);\r\n#6478=EDGE_CURVE('',#4900,#4899,#1160,.T.);\r\n#6482=EDGE_CURVE('',#4911,#4912,#1165,.T.);\r\n#6484=EDGE_CURVE('',#4912,#4911,#1170,.T.);\r\n#6495=EDGE_CURVE('',#4368,#4374,#1250,.T.);\r\n#6497=EDGE_CURVE('',#4370,#4368,#1268,.T.);\r\n#6499=EDGE_CURVE('',#4370,#4373,#1246,.T.);\r\n#6511=EDGE_CURVE('',#4370,#4368,#1259,.T.);\r\n#6522=EDGE_CURVE('',#4367,#4368,#1254,.T.);\r\n#6525=EDGE_CURVE('',#4367,#4370,#1263,.T.);\r\n#6547=EDGE_CURVE('',#4378,#4384,#1276,.T.);\r\n#6549=EDGE_CURVE('',#4380,#4378,#1294,.T.);\r\n#6551=EDGE_CURVE('',#4380,#4383,#1272,.T.);\r\n#6563=EDGE_CURVE('',#4380,#4378,#1285,.T.);\r\n#6574=EDGE_CURVE('',#4377,#4378,#1280,.T.);\r\n#6577=EDGE_CURVE('',#4377,#4380,#1289,.T.);\r\n#6600=EDGE_CURVE('',#4431,#4432,#1307,.T.);\r\n#6613=EDGE_CURVE('',#4267,#4268,#1321,.T.);\r\n#6624=EDGE_CURVE('',#4263,#4264,#1335,.T.);\r\n#6637=EDGE_CURVE('',#4331,#4332,#1353,.T.);\r\n#6662=EDGE_CURVE('',#4319,#4320,#1362,.T.);\r\n#6675=EDGE_CURVE('',#4311,#4312,#1380,.T.);\r\n#6678=EDGE_CURVE('',#4251,#4252,#1584,.T.);\r\n#6691=EDGE_CURVE('',#4255,#4256,#1626,.T.);\r\n#6704=EDGE_CURVE('',#4315,#4316,#1389,.T.);\r\n#6715=EDGE_CURVE('',#4307,#4308,#1407,.T.);\r\n#6718=EDGE_CURVE('',#4339,#4340,#1758,.T.);\r\n#6731=EDGE_CURVE('',#4343,#4344,#1908,.T.);\r\n#6742=EDGE_CURVE('',#4303,#4304,#1398,.T.);\r\n#6755=EDGE_CURVE('',#4791,#4792,#1416,.T.);\r\n#6758=EDGE_CURVE('',#4275,#4276,#1479,.T.);\r\n#6769=EDGE_CURVE('',#4815,#4816,#1506,.T.);\r\n#6784=EDGE_CURVE('',#4795,#4796,#1425,.T.);\r\n#6797=EDGE_CURVE('',#4803,#4804,#1443,.T.);\r\n#6808=EDGE_CURVE('',#4799,#4800,#1434,.T.);\r\n#6823=EDGE_CURVE('',#4279,#4280,#1452,.T.);\r\n#6834=EDGE_CURVE('',#4807,#4808,#1488,.T.);\r\n#6837=EDGE_CURVE('',#4411,#4412,#1524,.T.);\r\n#6850=EDGE_CURVE('',#4283,#4284,#1461,.T.);\r\n#6861=EDGE_CURVE('',#4271,#4272,#1470,.T.);\r\n#6888=EDGE_CURVE('',#4811,#4812,#1497,.T.);\r\n#6901=EDGE_CURVE('',#4819,#4820,#1515,.T.);\r\n#6926=EDGE_CURVE('',#4415,#4416,#1533,.T.);\r\n#6937=EDGE_CURVE('',#4407,#4408,#1551,.T.);\r\n#6940=EDGE_CURVE('',#4443,#4444,#1642,.T.);\r\n#6953=EDGE_CURVE('',#4439,#4440,#2128,.T.);\r\n#6964=EDGE_CURVE('',#4403,#4404,#1542,.T.);\r\n#6979=EDGE_CURVE('',#4231,#4232,#1560,.T.);\r\n#6990=EDGE_CURVE('',#4419,#4420,#1592,.T.);\r\n#6993=EDGE_CURVE('',#4243,#4244,#1618,.T.);\r\n#7006=EDGE_CURVE('',#4235,#4236,#1568,.T.);\r\n#7018=EDGE_CURVE('',#4247,#4248,#1576,.T.);\r\n#7054=EDGE_CURVE('',#4239,#4240,#1610,.T.);\r\n#7070=EDGE_CURVE('',#4259,#4260,#1634,.T.);\r\n#7094=EDGE_CURVE('',#4447,#4448,#1650,.T.);\r\n#7110=EDGE_CURVE('',#4390,#4396,#1662,.T.);\r\n#7123=EDGE_CURVE('',#4387,#4394,#1666,.T.);\r\n#7136=EDGE_CURVE('',#4388,#4393,#1670,.T.);\r\n#7140=EDGE_CURVE('',#4455,#4456,#1675,.T.);\r\n#7142=EDGE_CURVE('',#4456,#4455,#1680,.T.);\r\n#7146=EDGE_CURVE('',#4463,#4464,#1685,.T.);\r\n#7148=EDGE_CURVE('',#4464,#4463,#1690,.T.);\r\n#7158=EDGE_CURVE('',#4779,#4780,#1702,.T.);\r\n#7161=EDGE_CURVE('',#4435,#4436,#2120,.T.);\r\n#7186=EDGE_CURVE('',#4783,#4784,#1711,.T.);\r\n#7197=EDGE_CURVE('',#4775,#4776,#1733,.T.);\r\n#7210=EDGE_CURVE('',#4771,#4772,#1724,.T.);\r\n#7225=EDGE_CURVE('',#4335,#4336,#1750,.T.);\r\n#7237=EDGE_CURVE('',#4786,#4293,#1792,.T.);\r\n#7239=EDGE_CURVE('',#4287,#4293,#1928,.T.);\r\n#7262=EDGE_CURVE('',#4920,#4926,#1776,.T.);\r\n#7265=EDGE_CURVE('',#4296,#4298,#1780,.T.);\r\n#7267=EDGE_CURVE('',#4294,#4296,#1784,.T.);\r\n#7269=EDGE_CURVE('',#4293,#4294,#1788,.T.);\r\n#7273=EDGE_CURVE('',#4924,#4928,#1796,.T.);\r\n#7275=EDGE_CURVE('',#4926,#4928,#1800,.T.);\r\n#7279=EDGE_CURVE('',#4707,#4708,#1767,.T.);\r\n#7281=EDGE_CURVE('',#4708,#4707,#1772,.T.);\r\n#7285=EDGE_CURVE('',#5020,#5022,#1993,.T.);\r\n#7287=EDGE_CURVE('',#5020,#4983,#1804,.T.);\r\n#7289=EDGE_CURVE('',#4979,#4983,#2107,.T.);\r\n#7291=EDGE_CURVE('',#4979,#4991,#1808,.T.);\r\n#7293=EDGE_CURVE('',#4987,#4991,#2089,.T.);\r\n#7295=EDGE_CURVE('',#4987,#5015,#1812,.T.);\r\n#7297=EDGE_CURVE('',#5011,#5015,#2071,.T.);\r\n#7299=EDGE_CURVE('',#5011,#5007,#1816,.T.);\r\n#7301=EDGE_CURVE('',#5003,#5007,#2053,.T.);\r\n#7303=EDGE_CURVE('',#5003,#4999,#1820,.T.);\r\n#7305=EDGE_CURVE('',#4995,#4999,#2035,.T.);\r\n#7307=EDGE_CURVE('',#4995,#5022,#1824,.T.);\r\n#7318=EDGE_CURVE('',#4704,#4708,#1832,.T.);\r\n#7321=EDGE_CURVE('',#4703,#4707,#1828,.T.);\r\n#7345=EDGE_CURVE('',#4926,#4919,#1836,.T.);\r\n#7358=EDGE_CURVE('',#4928,#4923,#1860,.T.);\r\n#7362=EDGE_CURVE('',#4929,#4930,#1846,.T.);\r\n#7364=EDGE_CURVE('',#4930,#4929,#1856,.T.);\r\n#7385=EDGE_CURVE('',#4930,#4531,#1868,.T.);\r\n#7388=EDGE_CURVE('',#4532,#4929,#1864,.T.);\r\n#7390=EDGE_CURVE('',#4531,#4532,#1873,.T.);\r\n#7403=EDGE_CURVE('',#4532,#4531,#1878,.T.);\r\n#7417=EDGE_CURVE('',#4535,#4536,#1883,.T.);\r\n#7419=EDGE_CURVE('',#4536,#4535,#1888,.T.);\r\n#7430=EDGE_CURVE('',#4536,#4504,#1896,.T.);\r\n#7433=EDGE_CURVE('',#4535,#4503,#1892,.T.);\r\n#7457=EDGE_CURVE('',#4347,#4348,#1916,.T.);\r\n#7461=EDGE_CURVE('',#4290,#4296,#1904,.T.);\r\n#7484=EDGE_CURVE('',#4288,#4294,#1924,.T.);\r\n#7502=EDGE_CURVE('',#4355,#4356,#1933,.T.);\r\n#7504=EDGE_CURVE('',#4356,#4355,#1938,.T.);\r\n#7508=EDGE_CURVE('',#4363,#4364,#1943,.T.);\r\n#7510=EDGE_CURVE('',#4364,#4363,#1948,.T.);\r\n#7521=EDGE_CURVE('',#4356,#4352,#1956,.T.);\r\n#7523=EDGE_CURVE('',#4351,#4352,#1961,.T.);\r\n#7525=EDGE_CURVE('',#4355,#4351,#1952,.T.);\r\n#7537=EDGE_CURVE('',#4352,#4351,#1966,.T.);\r\n#7559=EDGE_CURVE('',#4364,#4360,#1974,.T.);\r\n#7561=EDGE_CURVE('',#4359,#4360,#1979,.T.);\r\n#7563=EDGE_CURVE('',#4363,#4359,#1970,.T.);\r\n#7575=EDGE_CURVE('',#4360,#4359,#1984,.T.);\r\n#7596=EDGE_CURVE('',#5019,#5020,#1988,.T.);\r\n#7599=EDGE_CURVE('',#5024,#5022,#1997,.T.);\r\n#7601=EDGE_CURVE('',#5024,#5019,#2002,.T.);\r\n#7612=EDGE_CURVE('',#5019,#4984,#2006,.T.);\r\n#7614=EDGE_CURVE('',#4983,#4984,#2111,.T.);\r\n#7627=EDGE_CURVE('',#4996,#5024,#2010,.T.);\r\n#7629=EDGE_CURVE('',#5000,#4996,#2044,.T.);\r\n#7631=EDGE_CURVE('',#5004,#5000,#2014,.T.);\r\n#7633=EDGE_CURVE('',#5008,#5004,#2062,.T.);\r\n#7635=EDGE_CURVE('',#5012,#5008,#2018,.T.);\r\n#7637=EDGE_CURVE('',#5016,#5012,#2080,.T.);\r\n#7639=EDGE_CURVE('',#4988,#5016,#2022,.T.);\r\n#7641=EDGE_CURVE('',#4992,#4988,#2098,.T.);\r\n#7643=EDGE_CURVE('',#4980,#4992,#2026,.T.);\r\n#7645=EDGE_CURVE('',#4984,#4980,#2116,.T.);\r\n#7657=EDGE_CURVE('',#4995,#4996,#2030,.T.);\r\n#7670=EDGE_CURVE('',#4999,#5000,#2039,.T.);\r\n#7683=EDGE_CURVE('',#5003,#5004,#2048,.T.);\r\n#7696=EDGE_CURVE('',#5007,#5008,#2057,.T.);\r\n#7709=EDGE_CURVE('',#5011,#5012,#2066,.T.);\r\n#7722=EDGE_CURVE('',#5015,#5016,#2075,.T.);\r\n#7733=EDGE_CURVE('',#4987,#4988,#2084,.T.);\r\n#7748=EDGE_CURVE('',#4991,#4992,#2093,.T.);\r\n#7759=EDGE_CURVE('',#4979,#4980,#2102,.T.);\r\n#7797=EDGE_CURVE('',#4455,#4451,#2136,.T.);\r\n#7799=EDGE_CURVE('',#4451,#4452,#2145,.T.);\r\n#7801=EDGE_CURVE('',#4456,#4452,#2140,.T.);\r\n#7813=EDGE_CURVE('',#4452,#4451,#2150,.T.);\r\n#7835=EDGE_CURVE('',#4463,#4459,#2154,.T.);\r\n#7837=EDGE_CURVE('',#4459,#4460,#2163,.T.);\r\n#7839=EDGE_CURVE('',#4464,#4460,#2158,.T.);\r\n#7851=EDGE_CURVE('',#4460,#4459,#2168,.T.);\r\n#7873=EDGE_CURVE('',#4470,#4473,#2176,.T.);\r\n#7875=EDGE_CURVE('',#4470,#4468,#2194,.T.);\r\n#7877=EDGE_CURVE('',#4468,#4474,#2172,.T.);\r\n#7889=EDGE_CURVE('',#4470,#4468,#2189,.T.);\r\n#7900=EDGE_CURVE('',#4467,#4468,#2180,.T.);\r\n#7902=EDGE_CURVE('',#4467,#4470,#2184,.T.);\r\n#7925=EDGE_CURVE('',#4480,#4483,#2202,.T.);\r\n#7927=EDGE_CURVE('',#4480,#4478,#2220,.T.);\r\n#7929=EDGE_CURVE('',#4478,#4484,#2198,.T.);\r\n#7941=EDGE_CURVE('',#4480,#4478,#2215,.T.);\r\n#7952=EDGE_CURVE('',#4477,#4478,#2206,.T.);\r\n#7954=EDGE_CURVE('',#4477,#4480,#2210,.T.);\r\n#7977=EDGE_CURVE('',#4496,#4492,#2228,.T.);\r\n#7979=EDGE_CURVE('',#4491,#4492,#2233,.T.);\r\n#7981=EDGE_CURVE('',#4495,#4491,#2224,.T.);\r\n#7993=EDGE_CURVE('',#4492,#4491,#2238,.T.);\r\n#8008=EDGE_CURVE('',#4499,#4500,#2243,.T.);\r\n#8010=EDGE_CURVE('',#4500,#4499,#2248,.T.);\r\n#8021=EDGE_CURVE('',#4500,#4488,#2256,.T.);\r\n#8024=EDGE_CURVE('',#4499,#4487,#2252,.T.);\r\n#8047=EDGE_CURVE('',#4544,#4540,#2264,.T.);\r\n#8049=EDGE_CURVE('',#4539,#4540,#2269,.T.);\r\n#8051=EDGE_CURVE('',#4543,#4539,#2260,.T.);\r\n#8063=EDGE_CURVE('',#4540,#4539,#2274,.T.);\r\n#8078=EDGE_CURVE('',#4547,#4548,#2279,.T.);\r\n#8080=EDGE_CURVE('',#4548,#4547,#2284,.T.);\r\n#8091=EDGE_CURVE('',#4548,#4508,#2292,.T.);\r\n#8094=EDGE_CURVE('',#4547,#4507,#2288,.T.);\r\n#8117=EDGE_CURVE('',#4556,#4552,#2300,.T.);\r\n#8119=EDGE_CURVE('',#4551,#4552,#2305,.T.);\r\n#8121=EDGE_CURVE('',#4555,#4551,#2296,.T.);\r\n#8133=EDGE_CURVE('',#4552,#4551,#2310,.T.);\r\n#8148=EDGE_CURVE('',#4559,#4560,#2315,.T.);\r\n#8150=EDGE_CURVE('',#4560,#4559,#2320,.T.);\r\n#8161=EDGE_CURVE('',#4560,#4512,#2328,.T.);\r\n#8164=EDGE_CURVE('',#4559,#4511,#2324,.T.);\r\n#8187=EDGE_CURVE('',#4568,#4564,#2336,.T.);\r\n#8189=EDGE_CURVE('',#4563,#4564,#2341,.T.);\r\n#8191=EDGE_CURVE('',#4567,#4563,#2332,.T.);\r\n#8203=EDGE_CURVE('',#4564,#4563,#2346,.T.);\r\n#8218=EDGE_CURVE('',#4571,#4572,#2351,.T.);\r\n#8220=EDGE_CURVE('',#4572,#4571,#2356,.T.);\r\n#8231=EDGE_CURVE('',#4572,#4516,#2364,.T.);\r\n#8234=EDGE_CURVE('',#4571,#4515,#2360,.T.);\r\n#8257=EDGE_CURVE('',#4588,#4584,#2372,.T.);\r\n#8259=EDGE_CURVE('',#4583,#4584,#2377,.T.);\r\n#8261=EDGE_CURVE('',#4587,#4583,#2368,.T.);\r\n#8273=EDGE_CURVE('',#4584,#4583,#2382,.T.);\r\n#8288=EDGE_CURVE('',#4591,#4592,#2387,.T.);\r\n#8290=EDGE_CURVE('',#4592,#4591,#2392,.T.);\r\n#8301=EDGE_CURVE('',#4592,#4524,#2400,.T.);\r\n#8304=EDGE_CURVE('',#4591,#4523,#2396,.T.);\r\n#8327=EDGE_CURVE('',#4600,#4596,#2408,.T.);\r\n#8329=EDGE_CURVE('',#4595,#4596,#2413,.T.);\r\n#8331=EDGE_CURVE('',#4599,#4595,#2404,.T.);\r\n#8343=EDGE_CURVE('',#4596,#4595,#2418,.T.);\r\n#8358=EDGE_CURVE('',#4603,#4604,#2423,.T.);\r\n#8360=EDGE_CURVE('',#4604,#4603,#2428,.T.);\r\n#8371=EDGE_CURVE('',#4604,#4528,#2436,.T.);\r\n#8374=EDGE_CURVE('',#4603,#4527,#2432,.T.);\r\n#8397=EDGE_CURVE('',#4616,#4612,#2444,.T.);\r\n#8399=EDGE_CURVE('',#4611,#4612,#2449,.T.);\r\n#8401=EDGE_CURVE('',#4615,#4611,#2440,.T.);\r\n#8413=EDGE_CURVE('',#4612,#4611,#2454,.T.);\r\n#8428=EDGE_CURVE('',#4619,#4620,#2459,.T.);\r\n#8430=EDGE_CURVE('',#4620,#4619,#2464,.T.);\r\n#8441=EDGE_CURVE('',#4620,#4608,#2472,.T.);\r\n#8444=EDGE_CURVE('',#4619,#4607,#2468,.T.);\r\n#8467=EDGE_CURVE('',#4648,#4644,#2480,.T.);\r\n#8469=EDGE_CURVE('',#4643,#4644,#2485,.T.);\r\n#8471=EDGE_CURVE('',#4647,#4643,#2476,.T.);\r\n#8483=EDGE_CURVE('',#4644,#4643,#2490,.T.);\r\n#8498=EDGE_CURVE('',#4651,#4652,#2495,.T.);\r\n#8500=EDGE_CURVE('',#4652,#4651,#2500,.T.);\r\n#8511=EDGE_CURVE('',#4652,#4624,#2508,.T.);\r\n#8514=EDGE_CURVE('',#4651,#4623,#2504,.T.);\r\n#8537=EDGE_CURVE('',#4660,#4656,#2516,.T.);\r\n#8539=EDGE_CURVE('',#4655,#4656,#2521,.T.);\r\n#8541=EDGE_CURVE('',#4659,#4655,#2512,.T.);\r\n#8553=EDGE_CURVE('',#4656,#4655,#2526,.T.);\r\n#8568=EDGE_CURVE('',#4663,#4664,#2531,.T.);\r\n#8570=EDGE_CURVE('',#4664,#4663,#2536,.T.);\r\n#8581=EDGE_CURVE('',#4664,#4636,#2544,.T.);\r\n#8584=EDGE_CURVE('',#4663,#4635,#2540,.T.);\r\n#8607=EDGE_CURVE('',#4672,#4668,#2552,.T.);\r\n#8609=EDGE_CURVE('',#4667,#4668,#2557,.T.);\r\n#8611=EDGE_CURVE('',#4671,#4667,#2548,.T.);\r\n#8623=EDGE_CURVE('',#4668,#4667,#2562,.T.);\r\n#8638=EDGE_CURVE('',#4675,#4676,#2567,.T.);\r\n#8640=EDGE_CURVE('',#4676,#4675,#2572,.T.);\r\n#8651=EDGE_CURVE('',#4676,#4628,#2580,.T.);\r\n#8654=EDGE_CURVE('',#4675,#4627,#2576,.T.);\r\n#8677=EDGE_CURVE('',#4684,#4680,#2588,.T.);\r\n#8679=EDGE_CURVE('',#4679,#4680,#2593,.T.);\r\n#8681=EDGE_CURVE('',#4683,#4679,#2584,.T.);\r\n#8693=EDGE_CURVE('',#4680,#4679,#2598,.T.);\r\n#8708=EDGE_CURVE('',#4687,#4688,#2603,.T.);\r\n#8710=EDGE_CURVE('',#4688,#4687,#2608,.T.);\r\n#8721=EDGE_CURVE('',#4688,#4632,#2616,.T.);\r\n#8724=EDGE_CURVE('',#4687,#4631,#2612,.T.);\r\n#8747=EDGE_CURVE('',#4696,#4692,#2624,.T.);\r\n#8749=EDGE_CURVE('',#4691,#4692,#2629,.T.);\r\n#8751=EDGE_CURVE('',#4695,#4691,#2620,.T.);\r\n#8763=EDGE_CURVE('',#4692,#4691,#2634,.T.);\r\n#8778=EDGE_CURVE('',#4699,#4700,#2639,.T.);\r\n#8780=EDGE_CURVE('',#4700,#4699,#2644,.T.);\r\n#8791=EDGE_CURVE('',#4700,#4640,#2652,.T.);\r\n#8794=EDGE_CURVE('',#4699,#4639,#2648,.T.);\r\n#8817=EDGE_CURVE('',#4832,#4828,#2660,.T.);\r\n#8819=EDGE_CURVE('',#4827,#4828,#2665,.T.);\r\n#8821=EDGE_CURVE('',#4831,#4827,#2656,.T.);\r\n#8833=EDGE_CURVE('',#4828,#4827,#2670,.T.);\r\n#8848=EDGE_CURVE('',#4835,#4836,#2675,.T.);\r\n#8850=EDGE_CURVE('',#4836,#4835,#2680,.T.);\r\n#8861=EDGE_CURVE('',#4836,#4824,#2688,.T.);\r\n#8864=EDGE_CURVE('',#4835,#4823,#2684,.T.);\r\n#8887=EDGE_CURVE('',#4864,#4860,#2696,.T.);\r\n#8889=EDGE_CURVE('',#4859,#4860,#2701,.T.);\r\n#8891=EDGE_CURVE('',#4863,#4859,#2692,.T.);\r\n#8903=EDGE_CURVE('',#4860,#4859,#2706,.T.);\r\n#8918=EDGE_CURVE('',#4867,#4868,#2711,.T.);\r\n#8920=EDGE_CURVE('',#4868,#4867,#2716,.T.);\r\n#8931=EDGE_CURVE('',#4868,#4840,#2724,.T.);\r\n#8934=EDGE_CURVE('',#4867,#4839,#2720,.T.);\r\n#8957=EDGE_CURVE('',#4876,#4872,#2732,.T.);\r\n#8959=EDGE_CURVE('',#4871,#4872,#2737,.T.);\r\n#8961=EDGE_CURVE('',#4875,#4871,#2728,.T.);\r\n#8973=EDGE_CURVE('',#4872,#4871,#2742,.T.);\r\n#8988=EDGE_CURVE('',#4879,#4880,#2747,.T.);\r\n#8990=EDGE_CURVE('',#4880,#4879,#2752,.T.);\r\n#9001=EDGE_CURVE('',#4880,#4844,#2760,.T.);\r\n#9004=EDGE_CURVE('',#4879,#4843,#2756,.T.);\r\n#9027=EDGE_CURVE('',#4888,#4884,#2768,.T.);\r\n#9029=EDGE_CURVE('',#4883,#4884,#2773,.T.);\r\n#9031=EDGE_CURVE('',#4887,#4883,#2764,.T.);\r\n#9043=EDGE_CURVE('',#4884,#4883,#2778,.T.);\r\n#9058=EDGE_CURVE('',#4891,#4892,#2783,.T.);\r\n#9060=EDGE_CURVE('',#4892,#4891,#2788,.T.);\r\n#9071=EDGE_CURVE('',#4892,#4848,#2796,.T.);\r\n#9074=EDGE_CURVE('',#4891,#4847,#2792,.T.);\r\n#9097=EDGE_CURVE('',#4900,#4896,#2804,.T.);\r\n#9099=EDGE_CURVE('',#4895,#4896,#2809,.T.);\r\n#9101=EDGE_CURVE('',#4899,#4895,#2800,.T.);\r\n#9113=EDGE_CURVE('',#4896,#4895,#2814,.T.);\r\n#9128=EDGE_CURVE('',#4903,#4904,#2819,.T.);\r\n#9130=EDGE_CURVE('',#4904,#4903,#2824,.T.);\r\n#9141=EDGE_CURVE('',#4904,#4852,#2832,.T.);\r\n#9144=EDGE_CURVE('',#4903,#4851,#2828,.T.);\r\n#9167=EDGE_CURVE('',#4912,#4908,#2840,.T.);\r\n#9169=EDGE_CURVE('',#4907,#4908,#2845,.T.);\r\n#9171=EDGE_CURVE('',#4911,#4907,#2836,.T.);\r\n#9183=EDGE_CURVE('',#4908,#4907,#2850,.T.);\r\n#9198=EDGE_CURVE('',#4915,#4916,#2855,.T.);\r\n#9200=EDGE_CURVE('',#4916,#4915,#2860,.T.);\r\n#9211=EDGE_CURVE('',#4916,#4856,#2868,.T.);\r\n#9214=EDGE_CURVE('',#4915,#4855,#2864,.T.);\r\n#9238=EDGE_CURVE('',#4942,#4937,#2872,.T.);\r\n#9254=EDGE_CURVE('',#4943,#4944,#2882,.T.);\r\n#9256=EDGE_CURVE('',#4944,#4943,#2892,.T.);\r\n#9266=EDGE_CURVE('',#4943,#4575,#2900,.T.);\r\n#9269=EDGE_CURVE('',#4576,#4944,#2896,.T.);\r\n#9271=EDGE_CURVE('',#4575,#4576,#2905,.T.);\r\n#9284=EDGE_CURVE('',#4576,#4575,#2910,.T.);\r\n#9298=EDGE_CURVE('',#4579,#4580,#2915,.T.);\r\n#9300=EDGE_CURVE('',#4580,#4579,#2920,.T.);\r\n#9311=EDGE_CURVE('',#4580,#4520,#2928,.T.);\r\n#9314=EDGE_CURVE('',#4579,#4519,#2924,.T.);\r\n#9336=EDGE_CURVE('',#5099,#5100,#2932,.T.);\r\n#9338=EDGE_CURVE('',#5100,#5104,#2937,.T.);\r\n#9340=EDGE_CURVE('',#5103,#5104,#2941,.T.);\r\n#9353=EDGE_CURVE('',#5062,#5064,#2959,.T.);\r\n#9355=EDGE_CURVE('',#5100,#5062,#3044,.T.);\r\n#9365=EDGE_CURVE('',#5059,#5060,#2950,.T.);\r\n#9367=EDGE_CURVE('',#5059,#5062,#2955,.T.);\r\n#9381=EDGE_CURVE('',#5070,#5072,#2977,.T.);\r\n#9383=EDGE_CURVE('',#5059,#5070,#3048,.T.);\r\n#9393=EDGE_CURVE('',#5067,#5068,#2968,.T.);\r\n#9395=EDGE_CURVE('',#5067,#5070,#2973,.T.);\r\n#9409=EDGE_CURVE('',#5094,#5096,#2995,.T.);\r\n#9411=EDGE_CURVE('',#5067,#5094,#3052,.T.);\r\n#9421=EDGE_CURVE('',#5091,#5092,#2986,.T.);\r\n#9423=EDGE_CURVE('',#5091,#5094,#2991,.T.);\r\n#9435=EDGE_CURVE('',#5086,#5088,#3013,.T.);\r\n#9437=EDGE_CURVE('',#5091,#5086,#3056,.T.);\r\n#9449=EDGE_CURVE('',#5083,#5084,#3004,.T.);\r\n#9451=EDGE_CURVE('',#5083,#5086,#3009,.T.);\r\n#9463=EDGE_CURVE('',#5078,#5080,#3031,.T.);\r\n#9465=EDGE_CURVE('',#5083,#5078,#3060,.T.);\r\n#9477=EDGE_CURVE('',#5075,#5076,#3022,.T.);\r\n#9479=EDGE_CURVE('',#5075,#5078,#3027,.T.);\r\n#9492=EDGE_CURVE('',#5075,#5104,#3040,.T.);\r\n#9525=EDGE_CURVE('',#4755,#4751,#3064,.T.);\r\n#9527=EDGE_CURVE('',#4751,#4752,#3073,.T.);\r\n#9529=EDGE_CURVE('',#4756,#4752,#3068,.T.);\r\n#9541=EDGE_CURVE('',#4752,#4751,#3078,.T.);\r\n#9563=EDGE_CURVE('',#4763,#4759,#3082,.T.);\r\n#9565=EDGE_CURVE('',#4759,#4760,#3091,.T.);\r\n#9567=EDGE_CURVE('',#4764,#4760,#3086,.T.);\r\n#9579=EDGE_CURVE('',#4760,#4759,#3096,.T.);\r\n#9601=EDGE_CURVE('',#4732,#4728,#3104,.T.);\r\n#9603=EDGE_CURVE('',#4727,#4728,#3109,.T.);\r\n#9605=EDGE_CURVE('',#4731,#4727,#3100,.T.);\r\n#9617=EDGE_CURVE('',#4728,#4727,#3114,.T.);\r\n#9639=EDGE_CURVE('',#4724,#4720,#3122,.T.);\r\n#9641=EDGE_CURVE('',#4719,#4720,#3127,.T.);\r\n#9643=EDGE_CURVE('',#4723,#4719,#3118,.T.);\r\n#9655=EDGE_CURVE('',#4720,#4719,#3132,.T.);\r\n#9677=EDGE_CURVE('',#4716,#4712,#3140,.T.);\r\n#9679=EDGE_CURVE('',#4711,#4712,#3145,.T.);\r\n#9681=EDGE_CURVE('',#4715,#4711,#3136,.T.);\r\n#9693=EDGE_CURVE('',#4712,#4711,#3150,.T.);\r\n#9714=EDGE_CURVE('',#4947,#4948,#3154,.T.);\r\n#9716=EDGE_CURVE('',#4948,#4960,#3238,.T.);\r\n#9718=EDGE_CURVE('',#4959,#4960,#3217,.T.);\r\n#9731=EDGE_CURVE('',#4951,#4952,#3163,.T.);\r\n#9733=EDGE_CURVE('',#4952,#4948,#3168,.T.);\r\n#9745=EDGE_CURVE('',#4971,#4972,#3172,.T.);\r\n#9747=EDGE_CURVE('',#4972,#4952,#3226,.T.);\r\n#9759=EDGE_CURVE('',#4975,#4976,#3181,.T.);\r\n#9761=EDGE_CURVE('',#4976,#4972,#3186,.T.);\r\n#9771=EDGE_CURVE('',#4963,#4964,#3190,.T.);\r\n#9773=EDGE_CURVE('',#4964,#4976,#3230,.T.);\r\n#9787=EDGE_CURVE('',#4967,#4968,#3199,.T.);\r\n#9789=EDGE_CURVE('',#4968,#4964,#3204,.T.);\r\n#9799=EDGE_CURVE('',#4955,#4956,#3208,.T.);\r\n#9801=EDGE_CURVE('',#4956,#4968,#3234,.T.);\r\n#9816=EDGE_CURVE('',#4960,#4956,#3222,.T.);\r\n#9842=EDGE_CURVE('',#5035,#5036,#3242,.T.);\r\n#9845=EDGE_CURVE('',#5046,#5048,#3321,.T.);\r\n#9847=EDGE_CURVE('',#5035,#5046,#3264,.T.);\r\n#9858=EDGE_CURVE('',#5035,#5038,#3247,.T.);\r\n#9860=EDGE_CURVE('',#5038,#5040,#3251,.T.);\r\n#9871=EDGE_CURVE('',#5027,#5030,#3281,.T.);\r\n#9873=EDGE_CURVE('',#5027,#5038,#3260,.T.);\r\n#9877=EDGE_CURVE('',#5043,#5046,#3317,.T.);\r\n#9879=EDGE_CURVE('',#5043,#5054,#3268,.T.);\r\n#9881=EDGE_CURVE('',#5051,#5054,#3299,.T.);\r\n#9883=EDGE_CURVE('',#5051,#5030,#3272,.T.);\r\n#9893=EDGE_CURVE('',#5027,#5028,#3276,.T.);\r\n#9896=EDGE_CURVE('',#5030,#5032,#3285,.T.);\r\n#9921=EDGE_CURVE('',#5051,#5052,#3294,.T.);\r\n#9934=EDGE_CURVE('',#5054,#5056,#3303,.T.);\r\n#9945=EDGE_CURVE('',#5043,#5044,#3312,.T.);\r\n#9971=EDGE_CURVE('',#5121,#5107,#3330,.T.);\r\n#9973=EDGE_CURVE('',#5107,#5108,#3346,.T.);\r\n#9975=EDGE_CURVE('',#5122,#5108,#3342,.T.);\r\n#9986=EDGE_CURVE('',#5126,#5112,#3334,.T.);\r\n#9988=EDGE_CURVE('',#5112,#5107,#3351,.T.);\r\n#10000=EDGE_CURVE('',#5124,#5110,#3338,.T.);\r\n#10002=EDGE_CURVE('',#5110,#5112,#3355,.T.);\r\n#10015=EDGE_CURVE('',#5108,#5110,#3360,.T.);\r\n#10038=EDGE_CURVE('',#5140,#5136,#3397,.T.);\r\n#10040=EDGE_CURVE('',#5118,#5140,#3365,.T.);\r\n#10042=EDGE_CURVE('',#5116,#5118,#3370,.T.);\r\n#10044=EDGE_CURVE('',#5115,#5116,#3375,.T.);\r\n#10046=EDGE_CURVE('',#5136,#5115,#3379,.T.);\r\n#10056=EDGE_CURVE('',#5135,#5136,#3383,.T.);\r\n#10059=EDGE_CURVE('',#5139,#5140,#3392,.T.);\r\n#10072=EDGE_CURVE('',#5129,#5115,#3401,.T.);\r\n#10086=EDGE_CURVE('',#5130,#5116,#3405,.T.);\r\n#10099=EDGE_CURVE('',#5132,#5118,#3409,.T.);\r\n#10121=EDGE_CURVE('',#5183,#5184,#3413,.T.);\r\n#10124=EDGE_CURVE('',#5188,#5186,#3422,.T.);\r\n#10126=EDGE_CURVE('',#5188,#5183,#3427,.T.);\r\n#10137=EDGE_CURVE('',#5183,#5143,#3444,.T.);\r\n#10139=EDGE_CURVE('',#5147,#5143,#3486,.T.);\r\n#10150=EDGE_CURVE('',#5191,#5172,#3431,.T.);\r\n#10152=EDGE_CURVE('',#5196,#5191,#3478,.T.);\r\n#10154=EDGE_CURVE('',#5144,#5196,#3435,.T.);\r\n#10156=EDGE_CURVE('',#5143,#5144,#3440,.T.);\r\n#10160=EDGE_CURVE('',#5160,#5188,#3448,.T.);\r\n#10162=EDGE_CURVE('',#5164,#5160,#3558,.T.);\r\n#10164=EDGE_CURVE('',#5152,#5164,#3452,.T.);\r\n#10166=EDGE_CURVE('',#5156,#5152,#3540,.T.);\r\n#10168=EDGE_CURVE('',#5176,#5156,#3456,.T.);\r\n#10170=EDGE_CURVE('',#5180,#5176,#3522,.T.);\r\n#10172=EDGE_CURVE('',#5168,#5180,#3460,.T.);\r\n#10174=EDGE_CURVE('',#5172,#5168,#3504,.T.);\r\n#10184=EDGE_CURVE('',#5191,#5192,#3464,.T.);\r\n#10187=EDGE_CURVE('',#5171,#5172,#3499,.T.);\r\n#10200=EDGE_CURVE('',#5196,#5194,#3473,.T.);\r\n#10213=EDGE_CURVE('',#5148,#5144,#3482,.T.);\r\n#10236=EDGE_CURVE('',#5167,#5168,#3490,.T.);\r\n#10251=EDGE_CURVE('',#5179,#5180,#3517,.T.);\r\n#10262=EDGE_CURVE('',#5175,#5176,#3508,.T.);\r\n#10275=EDGE_CURVE('',#5155,#5156,#3535,.T.);\r\n#10288=EDGE_CURVE('',#5151,#5152,#3526,.T.);\r\n#10303=EDGE_CURVE('',#5163,#5164,#3553,.T.);\r\n#10314=EDGE_CURVE('',#5159,#5160,#3544,.T.);\r\n#10340=EDGE_CURVE('',#5207,#5199,#3562,.T.);\r\n#10342=EDGE_CURVE('',#5199,#5200,#3578,.T.);\r\n#10344=EDGE_CURVE('',#5208,#5200,#3574,.T.);\r\n#10355=EDGE_CURVE('',#5212,#5204,#3566,.T.);\r\n#10357=EDGE_CURVE('',#5204,#5199,#3583,.T.);\r\n#10369=EDGE_CURVE('',#5210,#5202,#3570,.T.);\r\n#10371=EDGE_CURVE('',#5202,#5204,#3587,.T.);\r\n#10384=EDGE_CURVE('',#5200,#5202,#3592,.T.);\r\n#10408=EDGE_CURVE('',#5223,#5215,#3596,.T.);\r\n#10410=EDGE_CURVE('',#5215,#5216,#3612,.T.);\r\n#10412=EDGE_CURVE('',#5224,#5216,#3608,.T.);\r\n#10423=EDGE_CURVE('',#5228,#5220,#3600,.T.);\r\n#10425=EDGE_CURVE('',#5220,#5215,#3617,.T.);\r\n#10437=EDGE_CURVE('',#5226,#5218,#3604,.T.);\r\n#10439=EDGE_CURVE('',#5218,#5220,#3621,.T.);\r\n#10452=EDGE_CURVE('',#5216,#5218,#3626,.T.);\r\n#10476=EDGE_CURVE('',#5239,#5231,#3630,.T.);\r\n#10478=EDGE_CURVE('',#5231,#5232,#3646,.T.);\r\n#10480=EDGE_CURVE('',#5240,#5232,#3642,.T.);\r\n#10491=EDGE_CURVE('',#5244,#5236,#3634,.T.);\r\n#10493=EDGE_CURVE('',#5236,#5231,#3651,.T.);\r\n#10505=EDGE_CURVE('',#5242,#5234,#3638,.T.);\r\n#10507=EDGE_CURVE('',#5234,#5236,#3655,.T.);\r\n#10520=EDGE_CURVE('',#5232,#5234,#3660,.T.);\r\n#10544=EDGE_CURVE('',#5255,#5247,#3664,.T.);\r\n#10546=EDGE_CURVE('',#5247,#5248,#3680,.T.);\r\n#10548=EDGE_CURVE('',#5256,#5248,#3676,.T.);\r\n#10559=EDGE_CURVE('',#5260,#5252,#3668,.T.);\r\n#10561=EDGE_CURVE('',#5252,#5247,#3685,.T.);\r\n#10573=EDGE_CURVE('',#5258,#5250,#3672,.T.);\r\n#10575=EDGE_CURVE('',#5250,#5252,#3689,.T.);\r\n#10588=EDGE_CURVE('',#5248,#5250,#3694,.T.);\r\n#10612=EDGE_CURVE('',#5278,#5264,#3702,.T.);\r\n#10614=EDGE_CURVE('',#5263,#5264,#3714,.T.);\r\n#10616=EDGE_CURVE('',#5277,#5263,#3698,.T.);\r\n#10627=EDGE_CURVE('',#5280,#5266,#3706,.T.);\r\n#10629=EDGE_CURVE('',#5264,#5266,#3719,.T.);\r\n#10641=EDGE_CURVE('',#5282,#5268,#3710,.T.);\r\n#10643=EDGE_CURVE('',#5266,#5268,#3723,.T.);\r\n#10656=EDGE_CURVE('',#5268,#5263,#3728,.T.);\r\n#10679=EDGE_CURVE('',#5480,#5476,#3765,.T.);\r\n#10681=EDGE_CURVE('',#5480,#5271,#3732,.T.);\r\n#10683=EDGE_CURVE('',#5271,#5272,#3737,.T.);\r\n#10685=EDGE_CURVE('',#5272,#5274,#3742,.T.);\r\n#10687=EDGE_CURVE('',#5274,#5476,#3747,.T.);\r\n#10697=EDGE_CURVE('',#5475,#5476,#3751,.T.);\r\n#10700=EDGE_CURVE('',#5479,#5480,#3760,.T.);\r\n#10713=EDGE_CURVE('',#5288,#5274,#3769,.T.);\r\n#10727=EDGE_CURVE('',#5286,#5272,#3773,.T.);\r\n#10740=EDGE_CURVE('',#5285,#5271,#3777,.T.);\r\n#10763=EDGE_CURVE('',#5306,#5292,#3785,.T.);\r\n#10765=EDGE_CURVE('',#5291,#5292,#3797,.T.);\r\n#10767=EDGE_CURVE('',#5305,#5291,#3781,.T.);\r\n#10778=EDGE_CURVE('',#5308,#5294,#3789,.T.);\r\n#10780=EDGE_CURVE('',#5292,#5294,#3802,.T.);\r\n#10792=EDGE_CURVE('',#5310,#5296,#3793,.T.);\r\n#10794=EDGE_CURVE('',#5294,#5296,#3806,.T.);\r\n#10807=EDGE_CURVE('',#5296,#5291,#3811,.T.);\r\n#10830=EDGE_CURVE('',#5472,#5468,#3848,.T.);\r\n#10832=EDGE_CURVE('',#5472,#5299,#3815,.T.);\r\n#10834=EDGE_CURVE('',#5299,#5300,#3820,.T.);\r\n#10836=EDGE_CURVE('',#5300,#5302,#3825,.T.);\r\n#10838=EDGE_CURVE('',#5302,#5468,#3830,.T.);\r\n#10848=EDGE_CURVE('',#5467,#5468,#3834,.T.);\r\n#10851=EDGE_CURVE('',#5471,#5472,#3843,.T.);\r\n#10864=EDGE_CURVE('',#5316,#5302,#3852,.T.);\r\n#10878=EDGE_CURVE('',#5314,#5300,#3856,.T.);\r\n#10891=EDGE_CURVE('',#5313,#5299,#3860,.T.);\r\n#10914=EDGE_CURVE('',#5336,#5328,#3868,.T.);\r\n#10916=EDGE_CURVE('',#5327,#5328,#3880,.T.);\r\n#10918=EDGE_CURVE('',#5335,#5327,#3864,.T.);\r\n#10929=EDGE_CURVE('',#5338,#5330,#3872,.T.);\r\n#10931=EDGE_CURVE('',#5328,#5330,#3885,.T.);\r\n#10943=EDGE_CURVE('',#5340,#5332,#3876,.T.);\r\n#10945=EDGE_CURVE('',#5330,#5332,#3889,.T.);\r\n#10958=EDGE_CURVE('',#5332,#5327,#3894,.T.);\r\n#10982=EDGE_CURVE('',#5352,#5344,#3902,.T.);\r\n#10984=EDGE_CURVE('',#5343,#5344,#3914,.T.);\r\n#10986=EDGE_CURVE('',#5351,#5343,#3898,.T.);\r\n#10997=EDGE_CURVE('',#5354,#5346,#3906,.T.);\r\n#10999=EDGE_CURVE('',#5344,#5346,#3919,.T.);\r\n#11011=EDGE_CURVE('',#5356,#5348,#3910,.T.);\r\n#11013=EDGE_CURVE('',#5346,#5348,#3923,.T.);\r\n#11026=EDGE_CURVE('',#5348,#5343,#3928,.T.);\r\n#11050=EDGE_CURVE('',#5368,#5360,#3936,.T.);\r\n#11052=EDGE_CURVE('',#5359,#5360,#3948,.T.);\r\n#11054=EDGE_CURVE('',#5367,#5359,#3932,.T.);\r\n#11065=EDGE_CURVE('',#5370,#5362,#3940,.T.);\r\n#11067=EDGE_CURVE('',#5360,#5362,#3953,.T.);\r\n#11079=EDGE_CURVE('',#5372,#5364,#3944,.T.);\r\n#11081=EDGE_CURVE('',#5362,#5364,#3957,.T.);\r\n#11094=EDGE_CURVE('',#5364,#5359,#3962,.T.);\r\n#11118=EDGE_CURVE('',#5384,#5376,#3970,.T.);\r\n#11120=EDGE_CURVE('',#5375,#5376,#3982,.T.);\r\n#11122=EDGE_CURVE('',#5383,#5375,#3966,.T.);\r\n#11133=EDGE_CURVE('',#5386,#5378,#3974,.T.);\r\n#11135=EDGE_CURVE('',#5376,#5378,#3987,.T.);\r\n#11147=EDGE_CURVE('',#5388,#5380,#3978,.T.);\r\n#11149=EDGE_CURVE('',#5378,#5380,#3991,.T.);\r\n#11162=EDGE_CURVE('',#5380,#5375,#3996,.T.);\r\n#11186=EDGE_CURVE('',#5405,#5391,#4000,.T.);\r\n#11188=EDGE_CURVE('',#5391,#5392,#4016,.T.);\r\n#11190=EDGE_CURVE('',#5406,#5392,#4012,.T.);\r\n#11201=EDGE_CURVE('',#5410,#5396,#4004,.T.);\r\n#11203=EDGE_CURVE('',#5396,#5391,#4021,.T.);\r\n#11215=EDGE_CURVE('',#5408,#5394,#4008,.T.);\r\n#11217=EDGE_CURVE('',#5394,#5396,#4025,.T.);\r\n#11230=EDGE_CURVE('',#5392,#5394,#4030,.T.);\r\n#11253=EDGE_CURVE('',#5488,#5484,#4067,.T.);\r\n#11255=EDGE_CURVE('',#5402,#5488,#4035,.T.);\r\n#11257=EDGE_CURVE('',#5400,#5402,#4040,.T.);\r\n#11259=EDGE_CURVE('',#5399,#5400,#4045,.T.);\r\n#11261=EDGE_CURVE('',#5484,#5399,#4049,.T.);\r\n#11271=EDGE_CURVE('',#5483,#5484,#4053,.T.);\r\n#11274=EDGE_CURVE('',#5487,#5488,#4062,.T.);\r\n#11287=EDGE_CURVE('',#5413,#5399,#4071,.T.);\r\n#11301=EDGE_CURVE('',#5414,#5400,#4075,.T.);\r\n#11314=EDGE_CURVE('',#5416,#5402,#4079,.T.);\r\n#11336=EDGE_CURVE('',#5451,#5452,#4083,.T.);\r\n#11338=EDGE_CURVE('',#5452,#5456,#4088,.T.);\r\n#11340=EDGE_CURVE('',#5455,#5456,#4092,.T.);\r\n#11353=EDGE_CURVE('',#5422,#5424,#4110,.T.);\r\n#11355=EDGE_CURVE('',#5452,#5422,#4216,.T.);\r\n#11365=EDGE_CURVE('',#5419,#5420,#4101,.T.);\r\n#11367=EDGE_CURVE('',#5419,#5422,#4106,.T.);\r\n#11381=EDGE_CURVE('',#5430,#5432,#4128,.T.);\r\n#11383=EDGE_CURVE('',#5419,#5430,#4220,.T.);\r\n#11393=EDGE_CURVE('',#5427,#5428,#4119,.T.);\r\n#11395=EDGE_CURVE('',#5427,#5430,#4124,.T.);\r\n#11409=EDGE_CURVE('',#5446,#5448,#4146,.T.);\r\n#11411=EDGE_CURVE('',#5427,#5446,#4224,.T.);\r\n#11421=EDGE_CURVE('',#5443,#5444,#4137,.T.);\r\n#11423=EDGE_CURVE('',#5443,#5446,#4142,.T.);\r\n#11435=EDGE_CURVE('',#5438,#5440,#4164,.T.);\r\n#11437=EDGE_CURVE('',#5443,#5438,#4228,.T.);\r\n#11449=EDGE_CURVE('',#5435,#5436,#4155,.T.);\r\n#11451=EDGE_CURVE('',#5435,#5438,#4160,.T.);\r\n#11463=EDGE_CURVE('',#5463,#5464,#4182,.T.);\r\n#11465=EDGE_CURVE('',#5435,#5464,#4199,.T.);\r\n#11477=EDGE_CURVE('',#5459,#5460,#4173,.T.);\r\n#11479=EDGE_CURVE('',#5460,#5464,#4178,.T.);\r\n#11493=EDGE_CURVE('',#5323,#5319,#4191,.T.);\r\n#11495=EDGE_CURVE('',#5460,#5319,#4203,.T.);\r\n#11506=EDGE_CURVE('',#5324,#5320,#4195,.T.);\r\n#11508=EDGE_CURVE('',#5319,#5320,#4208,.T.);\r\n#11520=EDGE_CURVE('',#5320,#5456,#4212,.T.);\r\n#11562=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#11550),#11561);\r\n#11569=PRODUCT_DEFINITION('design','',#11568,#11565);\r\n#11570=PRODUCT_DEFINITION_SHAPE('','SHAPE FOR PROESOURCE.',#11569);\r\n#11571=SHAPE_DEFINITION_REPRESENTATION(#11570,#11562);\r\nENDSEC;\r\nEND-ISO-10303-21;\r\n"
  },
  {
    "path": "tutorials/hinge.stl",
    "content": "solid\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 5.300545e-016\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015\n    outer loop\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.428222e+001 1.749552e+001 4.399139e+000\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 1.440206e-016\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015\n    outer loop\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015\n    outer loop\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016\n    outer loop\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015\n    outer loop\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.038636e-017\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316081e-016\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.855272e-016\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 3.307707e-016\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -6.826070e-016\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -4.180408e-016\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.800343e-017\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -3.659639e-016\n    outer loop\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 5.956618e-016\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n      vertex 4.428222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.373531e+001 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 8.614567e-016\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -3.257609e-016\n    outer loop\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 3.166431e-016\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.267525e+001 1.471217e+001 4.399139e+000\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.182020e+001 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -1.411631e-016\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.138608e+001 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -4.198697e-016\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.096515e+001 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 3.691957e-016\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 3.330001e-016\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 4.021323e+001 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.855272e-016\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 4.399139e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.947097e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 2.090204e-016\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 4.399139e+000\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 9.048915e-016\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.935818e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 1.030095e-015\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 4.399139e+000\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 1.954566e-016\n    outer loop\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 2.606088e-016\n    outer loop\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 5.710544e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.021323e+001 1.897651e+001 4.399139e+000\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 3.981523e-016\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 1.216174e-015\n    outer loop\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 5.284567e-016\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.138608e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 1.013479e-016\n    outer loop\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 2.497501e-016\n    outer loop\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.267525e+001 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 2.461305e-016\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 2.678479e-016\n    outer loop\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 0.000000e+000\n    outer loop\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.373531e+001 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 1.520218e-015\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 4.850219e-016\n    outer loop\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 -3.438588e-017\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 1.414640e-015\n    outer loop\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016\n    outer loop\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 4.399139e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016\n    outer loop\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016\n    outer loop\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 3.519318e-017\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -5.710544e-016\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 1.706518e-016\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316081e-016\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -2.855272e-016\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -3.413035e-016\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -2.090204e-016\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -7.038636e-017\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 -3.318735e-016\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.090204e-016\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 1.324456e-016\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 5.710544e-016\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 -3.413035e-016\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -1.045102e-016\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n      vertex 2.728222e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -2.063153e-016\n    outer loop\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 6.587610e-016\n    outer loop\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.673531e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 2.895653e-016\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 3.402392e-016\n    outer loop\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.567525e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -1.845979e-016\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 7.058154e-017\n    outer loop\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -7.058154e-017\n    outer loop\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -2.099348e-016\n    outer loop\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.396515e+001 1.071217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 -1.303044e-016\n    outer loop\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 2.895653e-016\n    outer loop\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.290509e+001 1.145443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 2.316522e-016\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -3.909131e-016\n    outer loop\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.247097e+001 1.220635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 1.049674e-016\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 9.048915e-016\n    outer loop\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 1.134605e-015\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 4.399139e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 5.863697e-016\n    outer loop\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 9.266089e-016\n    outer loop\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 8.542176e-016\n    outer loop\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 8.612394e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 4.399139e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 8.542176e-016\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 9.193698e-016\n    outer loop\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 9.051759e-016\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 4.399139e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 1.031576e-015\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 5.863697e-016\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 9.266089e-016\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 1.143783e-015\n    outer loop\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 6.298045e-016\n    outer loop\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 1.049674e-015\n    outer loop\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 -1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.230768e-001 2.962415e-001 8.562984e-001\n    outer loop\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.145160e-001 -4.501432e-002 8.562984e-001\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.680911e-001 -2.182745e-001 8.562984e-001\n    outer loop\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 -4.230768e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 -4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 -4.988827e-001 8.562984e-001\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 -5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 -3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.230768e-001 -2.962415e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.182745e-001 4.680911e-001 8.562984e-001\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.336752e-001 4.988827e-001 8.562984e-001\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.501432e-002 5.145160e-001 8.562984e-001\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.962415e-001 4.230768e-001 8.562984e-001\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.652075e-001 3.652075e-001 8.562984e-001\n    outer loop\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.988827e-001 1.336752e-001 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.145160e-001 4.501432e-002 8.562984e-001\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 0.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 5.300545e-016\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016\n    outer loop\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 1.028222e+001 1.749552e+001 4.399139e+000\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016\n    outer loop\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015\n    outer loop\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016\n    outer loop\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016\n    outer loop\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.038636e-017\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -3.900374e-016\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -1.829819e-016\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 6.622278e-017\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -6.583952e-030\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 2.149666e-016\n    outer loop\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -2.559776e-016\n    outer loop\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -1.567653e-016\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -1.759659e-017\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 7.038636e-017\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -2.855272e-016\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -1.953121e-016\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -9.916256e-017\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 3.659639e-016\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n      vertex 1.028222e+001 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 3.909131e-016\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.985264e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.427169e+000 1.514629e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -9.410872e-017\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -1.954566e-016\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.675250e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 2.099348e-016\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 1.809783e-017\n    outer loop\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -5.429349e-017\n    outer loop\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 7.386080e+000 1.459938e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -1.592609e-016\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 2.750870e-016\n    outer loop\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 9.916256e-017\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 6.213231e+000 1.514629e+001 4.399139e+000\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 1.447826e-016\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 -1.592609e-016\n    outer loop\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -3.691957e-016\n    outer loop\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.470968e+000 1.620635e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 2.099348e-016\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 7.040056e-016\n    outer loop\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 7.040056e-016\n    outer loop\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.358181e+000 1.749552e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 6.400577e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 4.399139e+000\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 9.338481e-016\n    outer loop\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 5.942889e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 5.905089e+000 1.866837e+001 4.399139e+000\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 4.271088e-016\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 6.298045e-016\n    outer loop\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 1.049674e-015\n    outer loop\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 6.965150e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 5.300545e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 4.399139e+000\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 7.040056e-016\n    outer loop\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 1.013479e-016\n    outer loop\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.254320e+000 1.952342e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 3.547175e-016\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 7.601089e-016\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 2.678479e-016\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 8.542176e-016\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.735311e+000 1.866837e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 8.614567e-016\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 9.985264e+000 1.831140e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 8.542176e-016\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 4.399139e+000\n    endloop\n  endfacet\n  facet normal 4.639778e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -2.425509e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 2.425509e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.635355e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.101317e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -5.024296e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.870609e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -4.973720e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.930284e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.872123e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -5.049222e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.815345e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -4.851017e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -5.189602e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.739404e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -5.015272e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -4.479280e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -5.101317e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.688432e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.971507e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.936122e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.670740e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.776893e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 4.891892e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.741508e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.759201e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 4.546894e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.639778e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -2.425509e-016 9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 2.425509e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.635355e-016 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.101317e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -5.024296e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.870609e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -4.973720e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.930284e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -4.872123e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal -4.809511e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -5.049222e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -4.815345e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -4.851017e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -5.189602e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -4.739404e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -5.015272e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -4.479280e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -4.605605e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -4.955515e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -4.562199e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -5.101317e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.688432e-016 9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.971507e-016 4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 4.635355e-016 2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 4.936122e-016 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 5.236890e-016 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 4.670740e-016 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 5.130737e-016 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.776893e-016 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.953815e-016 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.799008e-016 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 4.891892e-016 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 4.741508e-016 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 4.759201e-016 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 4.706124e-016 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 4.599971e-016 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 4.812277e-016 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 4.546894e-016 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.823445e-001 2.045577e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 1.087460e+000 2.180922e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 2.701867e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 2.359533e+000 3.071637e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.015823e+000 5.520945e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 2.880478e+000 6.026060e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.989763e+000 7.298133e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.561400e+000 7.598076e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -1.866963e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.236733e+000 6.928363e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 3.015823e+000 4.479055e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 6.140000e-002 8.000000e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 5.823445e-001 7.954423e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.087460e+000 7.819078e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 2.359533e+000 6.928363e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 2.659476e+000 6.500000e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.966323e-001 8.200039e-002\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal -4.306895e-017 -9.698266e-001 2.437957e-001\n    outer loop\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal -4.425936e-017 -9.966323e-001 8.200039e-002\n    outer loop\n      vertex 3.482020e+001 5.980711e+000 4.019309e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal 1.692405e-017 -9.698266e-001 2.437957e-001\n    outer loop\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal -3.581497e-018 -9.169362e-001 3.990338e-001\n    outer loop\n      vertex 3.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.169362e-001 3.990338e-001\n    outer loop\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.313813e-017 -8.393837e-001 5.435393e-001\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.392549e-001 6.734257e-001\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -6.192429e-001 7.851995e-001\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -6.192429e-001 7.851995e-001\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n    endloop\n  endfacet\n  facet normal 2.820675e-018 -7.392549e-001 6.734257e-001\n    outer loop\n      vertex 3.482020e+001 4.150665e+000 6.093379e-001\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.393837e-001 5.435393e-001\n    outer loop\n      vertex 3.482020e+001 4.813319e+000 1.336768e+000\n      vertex 3.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.893023e+000 5.520945e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 6.026060e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.866963e+000 7.298133e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -1.438600e+000 7.598076e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.659476e+000 6.500000e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 2.880478e+000 6.026060e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.015823e+000 4.479055e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 2.880478e+000 3.973940e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.087460e+000 2.180922e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 5.823445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.595445e-001 2.045577e+000\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -9.646604e-001 2.180922e+000\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.236733e+000 3.071637e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -2.536676e+000 3.500000e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.980711e+000 4.019309e+000\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 5.740815e+000 3.064995e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.989763e+000 7.298133e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 5.823445e-001 7.954423e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 8.000000e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.866963e+000 2.701867e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 1.989763e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.150665e+000 6.093379e-001\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 2.359533e+000 3.071637e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.482020e+001 4.813319e+000 1.336768e+000\n      vertex 1.482020e+001 5.348164e+000 2.162726e+000\n      vertex 1.482020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 3.832020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.706996e+001 1.574256e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.837337e+001 1.645363e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 2.750136e+001 1.531116e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 2.810912e+001 1.186433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.785129e+001 1.131140e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.242797e+001 1.361457e+001 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.657020e+001 1.609249e+001 5.000000e+000\n      vertex 3.837337e+001 1.766917e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n      vertex 3.853128e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 2.601727e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.881140e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 3.913904e+001 1.931116e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.570200e+000 2.009249e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 1.006996e+001 1.974256e+001 5.000000e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n      vertex 1.050136e+001 1.931116e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 2.421243e+001 1.650823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.085129e+001 1.881140e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 1.110912e+001 1.825847e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.153128e+001 1.186433e+001 5.000000e+000\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.007020e+001 2.009249e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 2.050823e+001 5.000000e+000\n      vertex 9.017271e+000 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 2.050823e+001 5.000000e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.182020e+001 2.056140e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.242797e+001 2.050823e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.301727e+001 2.035032e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.357020e+001 2.009249e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.406996e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.450136e+001 1.931116e+001 5.000000e+000\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.485129e+001 1.881140e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.510912e+001 1.825847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.526703e+001 1.766917e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.532020e+001 1.706140e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.510912e+001 1.586433e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.485129e+001 1.531140e+001 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.450136e+001 1.481164e+001 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.406996e+001 1.438024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.357020e+001 1.403031e+001 5.000000e+000\n      vertex 4.301727e+001 1.377248e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.121243e+001 1.361457e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 4.182020e+001 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.062313e+001 1.377248e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n      vertex 2.826703e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 2.832020e+001 1.306140e+001 5.000000e+000\n      vertex 4.007020e+001 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.957044e+001 1.438024e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n      vertex 2.826703e+001 1.366917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 2.810912e+001 1.425847e+001 5.000000e+000\n      vertex 3.913904e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.878911e+001 1.531140e+001 5.000000e+000\n      vertex 3.853128e+001 1.586433e+001 5.000000e+000\n      vertex 2.785129e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 1.006996e+001 1.438024e+001 5.000000e+000\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.137337e+001 1.366917e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n      vertex 1.050136e+001 1.481164e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n      vertex 1.085129e+001 1.531140e+001 5.000000e+000\n      vertex 2.153128e+001 1.425847e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 1.110912e+001 1.586433e+001 5.000000e+000\n      vertex 2.178911e+001 1.481140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.531116e+001 5.000000e+000\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 1.126703e+001 1.645363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.257044e+001 1.574256e+001 5.000000e+000\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 1.132020e+001 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.307020e+001 1.609249e+001 5.000000e+000\n      vertex 2.362313e+001 1.635032e+001 5.000000e+000\n      vertex 1.126703e+001 1.766917e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.482020e+001 1.656140e+001 5.000000e+000\n      vertex 2.542797e+001 1.650823e+001 5.000000e+000\n      vertex 3.957044e+001 1.974256e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.750136e+001 1.081164e+001 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.706996e+001 1.038024e+001 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.657020e+001 1.003031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.601727e+001 9.772476e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.542797e+001 9.614573e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.421243e+001 9.614573e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.362313e+001 9.772476e+000 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.307020e+001 1.003031e+001 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.257044e+001 1.038024e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.213904e+001 1.081164e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 2.178911e+001 1.131140e+001 5.000000e+000\n      vertex 9.017271e+000 1.377248e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 2.132020e+001 1.306140e+001 5.000000e+000\n      vertex 9.570200e+000 1.403031e+001 5.000000e+000\n      vertex 2.137337e+001 1.245363e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.373373e+000 1.766917e+001 5.000000e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.531276e+000 1.825847e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.789111e+000 1.881140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.139044e+000 1.931116e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 5.570443e+000 1.974256e+001 5.000000e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 6.070200e+000 2.009249e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.623129e+000 2.035032e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 7.212431e+000 2.050823e+001 5.000000e+000\n      vertex 7.820200e+000 2.056140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.427969e+000 1.361457e+001 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 7.820200e+000 1.356140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 7.212431e+000 1.361457e+001 5.000000e+000\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 6.623129e+000 1.377248e+001 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 6.070200e+000 1.403031e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.570443e+000 1.438024e+001 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 5.139044e+000 1.481164e+001 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 4.789111e+000 1.531140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.531276e+000 1.586433e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.373373e+000 1.645363e+001 5.000000e+000\n      vertex 4.320200e+000 1.706140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 2.482020e+001 9.561400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.061400e+000 5.000000e+000\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.526703e+001 1.645363e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.062313e+001 2.035032e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 3.482020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 3.482020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 3.482020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 3.482020e+001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 3.482020e+001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 3.482020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 3.482020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 3.482020e+001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 3.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 3.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 3.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 3.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 3.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 3.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 3.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 3.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 3.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 3.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 3.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 0.000000e+000 2.588190e-001 9.659258e-001\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 3.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 3.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 3.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 3.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 3.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.063078e-001 4.226183e-001\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 3.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 3.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.432567e-016 1.253334e-017 -1.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.174024e-016 3.145787e-017 -1.000000e+000\n    outer loop\n      vertex 4.428222e+001 1.749552e+001 -8.881784e-016\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 9.887861e-017 4.610785e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.416943e+001 1.791645e+001 -8.881784e-016\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.409715e-017 5.888546e-017 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.398526e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.118001e-017 7.118001e-017 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.866837e+001 -8.881784e-016\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.888546e-017 8.409715e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.342717e+001 1.897651e+001 -8.881784e-016\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 4.610785e-017 9.887861e-017 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.307020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.145787e-017 1.174024e-016 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.941063e+001 -8.881784e-016\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.253334e-017 1.432567e-016 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.225432e+001 1.952342e+001 -8.881784e-016\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.618835e-017 1.850337e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.182020e+001 1.956140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.259975e-017 2.709460e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.952342e+001 -8.881784e-016\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.571783e-016 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.383491e-031 1.571783e-016 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.259975e-017 2.709460e-016 -1.000000e+000\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.618835e-017 1.850337e-016 -1.000000e+000\n    outer loop\n      vertex 8.254320e+000 1.952342e+001 -8.881784e-016\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.253334e-017 1.432567e-016 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 7.820200e+000 1.956140e+001 -8.881784e-016\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.145787e-017 1.174024e-016 -1.000000e+000\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 7.386080e+000 1.952342e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -4.610785e-017 9.887861e-017 -1.000000e+000\n    outer loop\n      vertex 6.965150e+000 1.941063e+001 -8.881784e-016\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.888546e-017 8.409715e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 6.570200e+000 1.922646e+001 -8.881784e-016\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.118001e-017 7.118001e-017 -1.000000e+000\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 6.213231e+000 1.897651e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -8.409715e-017 5.888546e-017 -1.000000e+000\n    outer loop\n      vertex 5.905089e+000 1.866837e+001 -8.881784e-016\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -9.887861e-017 4.610785e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.655136e+000 1.831140e+001 -8.881784e-016\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.174024e-016 3.145787e-017 -1.000000e+000\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.470968e+000 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.432567e-016 1.253334e-017 -1.000000e+000\n    outer loop\n      vertex 5.358181e+000 1.749552e+001 -8.881784e-016\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.320200e+000 1.706140e+001 -8.881784e-016\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex 5.358181e+000 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.015055e-016 3.552714e-017 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.470968e+000 1.620635e+001 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 5.655136e+000 1.581140e+001 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 5.905089e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.213231e+000 1.514629e+001 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 6.570200e+000 1.489634e+001 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 6.965150e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000\n    outer loop\n      vertex 7.386080e+000 1.459938e+001 -8.881784e-016\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 7.820200e+000 1.456140e+001 -8.881784e-016\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.290509e+001 1.145443e+001 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.321323e+001 1.114629e+001 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.357020e+001 1.089634e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.396515e+001 1.071217e+001 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.438608e+001 1.059938e+001 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.525432e+001 1.059938e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.071217e+001 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.607020e+001 1.089634e+001 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.642717e+001 1.114629e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.673531e+001 1.145443e+001 0.000000e+000\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 2.698526e+001 1.181140e+001 0.000000e+000\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n      vertex 2.728222e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 2.732020e+001 1.306140e+001 0.000000e+000\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.514629e+001 -8.881784e-016\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 2.728222e+001 1.349552e+001 0.000000e+000\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 3.935818e+001 1.749552e+001 -8.881784e-016\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.941063e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.675250e+000 1.941063e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000\n    outer loop\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.719385e-017 7.719385e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.866837e+001 -8.881784e-016\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -8.446175e-017 1.206239e-016 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n      vertex 4.057020e+001 1.922646e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.719385e-017 7.719385e-017 -1.000000e+000\n    outer loop\n      vertex 4.021323e+001 1.897651e+001 -8.881784e-016\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -7.134736e-017 4.995796e-017 -1.000000e+000\n    outer loop\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 3.990509e+001 1.866837e+001 -8.881784e-016\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 2.607020e+001 1.522646e+001 0.000000e+000\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 3.947097e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 3.932020e+001 1.706140e+001 -8.881784e-016\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n      vertex 2.642717e+001 1.497651e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 2.673531e+001 1.466837e+001 0.000000e+000\n      vertex 3.935818e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 3.947097e+001 1.620635e+001 -8.881784e-016\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 2.698526e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 3.965514e+001 1.581140e+001 -8.881784e-016\n      vertex 3.990509e+001 1.545443e+001 -8.881784e-016\n      vertex 2.716943e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 4.096515e+001 1.471217e+001 -8.881784e-016\n      vertex 2.716943e+001 1.220635e+001 0.000000e+000\n      vertex 4.057020e+001 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.138608e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000\n    outer loop\n      vertex 4.182020e+001 1.456140e+001 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n    endloop\n  endfacet\n  facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -5.921189e-017 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 6.140000e-002 0.000000e+000\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.225432e+001 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.267525e+001 1.471217e+001 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.307020e+001 1.489634e+001 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.342717e+001 1.514629e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.373531e+001 1.545443e+001 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.398526e+001 1.581140e+001 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000\n    outer loop\n      vertex 4.432020e+001 1.706140e+001 -8.881784e-016\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.428222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 2.567525e+001 1.541063e+001 0.000000e+000\n      vertex 2.525432e+001 1.552342e+001 0.000000e+000\n      vertex 3.965514e+001 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 2.438608e+001 1.552342e+001 0.000000e+000\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.831140e+001 -8.881784e-016\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 2.396515e+001 1.541063e+001 0.000000e+000\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.749552e+001 -8.881784e-016\n      vertex 1.016943e+001 1.791645e+001 -8.881784e-016\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 2.357020e+001 1.522646e+001 0.000000e+000\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 1.032020e+001 1.706140e+001 -8.881784e-016\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 2.321323e+001 1.497651e+001 0.000000e+000\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.785445e-017 5.936495e-018 -1.000000e+000\n    outer loop\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 7.004568e-017 1.876868e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n      vertex 2.235818e+001 1.262728e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 7.033831e-017 3.279929e-017 -1.000000e+000\n    outer loop\n      vertex 2.247097e+001 1.220635e+001 0.000000e+000\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000\n    outer loop\n      vertex 8.675250e+000 1.471217e+001 -8.881784e-016\n      vertex 2.265514e+001 1.181140e+001 0.000000e+000\n      vertex 8.254320e+000 1.459938e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 8.446175e-017 1.206239e-016 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.897651e+001 -8.881784e-016\n      vertex 9.070200e+000 1.922646e+001 -8.881784e-016\n      vertex 2.482020e+001 1.556140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 2.232020e+001 1.306140e+001 0.000000e+000\n      vertex 9.070200e+000 1.489634e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000\n    outer loop\n      vertex 9.427169e+000 1.514629e+001 -8.881784e-016\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n      vertex 2.235818e+001 1.349552e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 2.247097e+001 1.391645e+001 0.000000e+000\n      vertex 9.735311e+000 1.545443e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000\n    outer loop\n      vertex 9.985264e+000 1.581140e+001 -8.881784e-016\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n      vertex 2.265514e+001 1.431140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000\n    outer loop\n      vertex 1.028222e+001 1.662728e+001 -8.881784e-016\n      vertex 2.290509e+001 1.466837e+001 0.000000e+000\n      vertex 1.016943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 5.921189e-017 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.015055e-016 3.552714e-017 -1.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.416943e+001 1.620635e+001 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.482020e+001 3.378025e+000 0.000000e+000\n      vertex 1.482020e+001 3.378025e+000 0.000000e+000\n      vertex 2.482020e+001 1.056140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 5.520945e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.866963e+000 7.298133e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -2.893023e+000 4.479055e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 3.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -2.236733e+000 3.071637e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.438600e+000 2.401924e+000\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -9.646604e-001 2.180922e+000\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 6.140000e-002 2.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 5.823445e-001 2.045577e+000\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 1.087460e+000 2.180922e+000\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 1.561400e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 2.701867e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 1.776357e-016 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.506140e+001 5.000000e+000\n      vertex -1.798000e-001 2.506140e+001 0.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.628500e-015 1.840496e-015\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 3.071637e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -2.086809e-015 9.730950e-016\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 2.659476e+000 3.500000e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.863973e-015 4.994500e-016\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 2.880478e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.776357e-015 1.554111e-016\n    outer loop\n      vertex -1.798000e-001 3.015823e+000 4.479055e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016\n    outer loop\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.989763e+000 7.298133e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 1.561400e+000 7.598076e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -1.438600e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -2.536676e+000 6.500000e+000\n      vertex -1.798000e-001 -2.757678e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -4.595445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex -1.798000e-001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 6.140000e-002 8.000000e+000\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 2.359533e+000 6.928363e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 2.659476e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 -7.105427e-016 4.029688e-015\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 -8.881784e-016\n      vertex 1.482020e+001 6.140000e-002 0.000000e+000\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 7.596123e-002\n      vertex 1.482020e+001 -8.068409e-001 7.596123e-002\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\n  facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 3.015369e-001\n      vertex 1.482020e+001 -1.648701e+000 3.015369e-001\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n    endloop\n  endfacet\n  facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 6.698730e-001\n      vertex 1.482020e+001 -2.438600e+000 6.698730e-001\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 1.169778e+000\n      vertex 1.482020e+001 -3.152538e+000 1.169778e+000\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 1.786062e+000\n      vertex 1.482020e+001 -3.768822e+000 1.786062e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex 1.482020e+001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 2.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.637063e+000 3.289899e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 3.318329e-017 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 7.232290e-018 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -2.172279e-030 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 3.884310e-017 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 8.428841e-017 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal -2.322295e-017 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 4.159406e-017 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 5.816399e-017 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 3.884310e-017 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 7.145594e-017 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex 1.482020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 9.961947e-001 8.715574e-002\n    outer loop\n      vertex 1.482020e+001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 5.061400e+000 5.000000e+000\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.910757e-017 9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 4.985439e+000 5.868241e+000\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex 1.482020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -8.492254e-018 9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 4.759863e+000 6.710101e+000\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex 1.482020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 4.391527e+000 7.500000e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n      vertex 1.482020e+001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -4.344559e-030 7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex 1.482020e+001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 3.891622e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 3.275338e+000 8.830222e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n      vertex 1.482020e+001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -1.153573e-017 4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex 1.482020e+001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 2.561400e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -6.793803e-017 2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 1.771501e+000 9.698463e+000\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex 1.482020e+001 9.296409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 9.296409e-001 9.924039e+000\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex 1.482020e+001 6.140000e-002 1.000000e+001\n    endloop\n  endfacet\n  facet normal 2.866136e-017 -8.715574e-002 9.961947e-001\n    outer loop\n      vertex -1.798000e-001 6.140000e-002 1.000000e+001\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex 1.482020e+001 -8.068409e-001 9.924039e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -2.588190e-001 9.659258e-001\n    outer loop\n      vertex -1.798000e-001 -8.068409e-001 9.924039e+000\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex 1.482020e+001 -1.648701e+000 9.698463e+000\n    endloop\n  endfacet\n  facet normal -8.492254e-018 -4.226183e-001 9.063078e-001\n    outer loop\n      vertex -1.798000e-001 -1.648701e+000 9.698463e+000\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex 1.482020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal -5.944578e-017 -5.735764e-001 8.191520e-001\n    outer loop\n      vertex -1.798000e-001 -2.438600e+000 9.330127e+000\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex 1.482020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -7.071068e-001 7.071068e-001\n    outer loop\n      vertex -1.798000e-001 -3.152538e+000 8.830222e+000\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex 1.482020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal -3.821514e-017 -8.191520e-001 5.735764e-001\n    outer loop\n      vertex -1.798000e-001 -3.768822e+000 8.213938e+000\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex 1.482020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -9.063078e-001 4.226183e-001\n    outer loop\n      vertex -1.798000e-001 -4.268727e+000 7.500000e+000\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex 1.482020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal -1.910757e-017 -9.659258e-001 2.588190e-001\n    outer loop\n      vertex -1.798000e-001 -4.637063e+000 6.710101e+000\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex 1.482020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal -9.023020e-017 -9.961947e-001 8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.862639e+000 5.868241e+000\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex 1.482020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002\n    outer loop\n      vertex -1.798000e-001 -4.938600e+000 5.000000e+000\n      vertex -1.798000e-001 -4.862639e+000 4.131759e+000\n      vertex 1.482020e+001 -4.862639e+000 4.131759e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.893023e+000 5.520945e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 6.710101e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 6.026060e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -2.236733e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 7.298133e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 8.830222e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -1.438600e+000 7.598076e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.891622e+000 8.213938e+000\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 6.928363e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.391527e+000 7.500000e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 2.659476e+000 6.500000e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 3.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.015823e+000 4.479055e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.880478e+000 3.973940e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.659476e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.359533e+000 3.071637e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 5.000000e+000\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.506140e+001 0.000000e+000\n      vertex 4.982020e+001 1.989763e+000 2.701867e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.561400e+000 2.401924e+000\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 1.087460e+000 2.180922e+000\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 5.823445e-001 2.045577e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 2.000000e+000\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 -8.881784e-016\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -4.595445e-001 2.045577e+000\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.152538e+000 1.169778e+000\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.866963e+000 2.701867e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 1.786062e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -2.236733e+000 3.071637e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 5.868241e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n      vertex 4.982020e+001 -2.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 5.061400e+000 5.000000e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n      vertex 4.982020e+001 3.015823e+000 5.520945e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 4.759863e+000 6.710101e+000\n      vertex 4.982020e+001 2.880478e+000 6.026060e+000\n      vertex 4.982020e+001 4.985439e+000 5.868241e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 3.275338e+000 8.830222e+000\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.989763e+000 7.298133e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 2.561400e+000 9.330127e+000\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 1.561400e+000 7.598076e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 1.771501e+000 9.698463e+000\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 1.087460e+000 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 9.296409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 5.823445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 6.140000e-002 1.000000e+001\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 6.140000e-002 8.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 9.924039e+000\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -4.595445e-001 7.954423e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -1.648701e+000 9.698463e+000\n      vertex 4.982020e+001 -2.438600e+000 9.330127e+000\n      vertex 4.982020e+001 -9.646604e-001 7.819078e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -3.768822e+000 8.213938e+000\n      vertex 4.982020e+001 -4.268727e+000 7.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 6.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -2.893023e+000 4.479055e+000\n      vertex 4.982020e+001 -4.938600e+000 5.000000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.862639e+000 4.131759e+000\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -2.757678e+000 3.973940e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -4.637063e+000 3.289899e+000\n      vertex 4.982020e+001 -4.268727e+000 2.500000e+000\n      vertex 4.982020e+001 -2.536676e+000 3.500000e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -2.438600e+000 6.698730e-001\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n      vertex 4.982020e+001 -1.438600e+000 2.401924e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 4.982020e+001 -8.068409e-001 7.596123e-002\n      vertex 4.982020e+001 -9.646604e-001 2.180922e+000\n      vertex 4.982020e+001 -1.648701e+000 3.015369e-001\n    endloop\n  endfacet\nendsolid\n"
  },
  {
    "path": "tutorials/lense.in2d",
    "content": "splinecurves2dv2\n5\n\n\npoints\n\n1\t-1.0\t-1.0\t\n2\t-1.0\t 1.0\t\n3\t 0.0\t 1.0\n4\t 1.0\t 1.0\t\n5\t 1.0\t-1.0\n6\t 0.0\t-1.0\n\n\nsegments\n0\t1\t2\t6\t1\t-bc=1\n0\t1\t2\t1\t2\t-bc=1\n0\t1\t2\t2\t3\t-bc=1\n\n\n0\t2\t2\t3\t4\t-bc=1\n0\t2\t2\t4\t5\t-bc=1\n0\t2\t2\t5\t6\t-bc=1\n\n\n\n\n1\t3\tbsplinepoints \t21\t4\n         0   -1.0000\n   -0.0380   -0.9000\n   -0.0720   -0.8000\n   -0.1020   -0.7000\n   -0.1280   -0.6000\n   -0.1500   -0.5000\n   -0.1680   -0.4000\n   -0.1820   -0.3000\n   -0.1920   -0.2000\n   -0.1980   -0.1000\n   -0.2000         0\n   -0.1980    0.1000\n   -0.1920    0.2000\n   -0.1820    0.3000\n   -0.1680    0.4000\n   -0.1500    0.5000\n   -0.1280    0.6000\n   -0.1020    0.7000\n   -0.0720    0.8000\n   -0.0380    0.9000\n         0    1.0000\n    -bc=2  -maxh=0.1\n\n3\t2\tbsplinepoints \t21\t3\n         0   -1.0000\n    0.0380   -0.9000\n    0.0720   -0.8000\n    0.1020   -0.7000\n    0.1280   -0.6000\n    0.1500   -0.5000\n    0.1680   -0.4000\n    0.1820   -0.3000\n    0.1920   -0.2000\n    0.1980   -0.1000\n    0.2000         0\n    0.1980    0.1000\n    0.1920    0.2000\n    0.1820    0.3000\n    0.1680    0.4000\n    0.1500    0.5000\n    0.1280    0.6000\n    0.1020    0.7000\n    0.0720    0.8000\n    0.0380    0.9000\n         0    1.0000\n    -bc=2  -maxh=0.1\n\n\nmaterials\n1       domain1   -maxh=0.2\n2       domain2   -maxh=0.2\n3       domain3   -maxh=0.2\n"
  },
  {
    "path": "tutorials/lshape3d.geo",
    "content": "algebraic3d\n\n#\n## 3D Lshape - domain\n#\n\nsolid c1 = plane (-1, -1, 0; 0, 0, -1)\n         and plane (-1, -1, 0; 0, -1, 0)\n         and plane (-1, -1, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\nsolid f1 = plane (0, 0, 0; -1, 0, 0);\nsolid f2 = plane (0, 0, 0; 0, 1, 0);\n\nsolid main = c1 and not (f1 and f2);\n\ntlo main;\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tutorials/manyholes.geo",
    "content": "algebraic3d\n#\n## CSG feature copy\n#\n\n\n# define a axis parallel brick:\n\nsolid br = orthobrick (0, 0, 0; 10, 10, 1);\n\n# define reference cylinder:\n\nsolid cyl1 = cylinder (0.5, 0.5, -1; 0.5, 0.5, 3; 0.2);\n\n\n# make copies:\nsolid cylx = multitranslate (1, 0, 0; 9; cyl1);\nsolid cyls = multitranslate (0, 1, 0; 9; cylx);\n\nsolid main = br and not cyls;\n\ntlo main;\n\n# provide bounding-box for fastening bisection alg:\n\nboundingbox (-1, -1, -1; 11, 11, 2);\n"
  },
  {
    "path": "tutorials/manyholes2.geo",
    "content": "algebraic3d\n#\n## CSG feature copy\n#\n\n\n# define a axis parallel brick:\n\nsolid br = orthobrick (0, 0, 0; 20, 20, 1);\n\n# define reference cylinder:\n\nsolid cyl1 = cylinder (0.5, 0.5, -1; 0.5, 0.5, 3; 0.2);\n\n\n# make copies:\nsolid cylx = multitranslate (1, 0, 0; 19; cyl1);\nsolid cyls = multitranslate (0, 1, 0; 19; cylx);\n\nsolid main = br and not cyls;\n\ntlo main;\n\n# provide bounding-box for fastening bisection alg:\n\nboundingbox (-1, -1, -1; 21, 21, 2);\n"
  },
  {
    "path": "tutorials/matrix.geo",
    "content": "#\n# a matrix with holes\n#\nalgebraic3d\n\nsolid holes = sphere (0.3, 0.4, 0.4; 0.1)\n           or sphere (0.7, 0.2, 0.8; 0.15)\n           or sphere (0.8, 0.5, 0.4; 0.11)\n           or sphere (0.6, 0.2, 0.8; 0.13)\n           or sphere (0.4, 0.3, 0.6; 0.14)\n           or sphere (0.6, 0.3, 0.4; 0.16)\n           or sphere (0.2, 0.8, 0.6; 0.17)\n           or sphere (0.4, 0.6, 0.5; 0.2);\n\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\n\nsolid rest = cube and not holes;\n\n# two sub-domains\n\ntlo holes -col=[1,0,0];\ntlo rest -col=[0,0,1] -transparent;\n"
  },
  {
    "path": "tutorials/ortho.geo",
    "content": "#\n## A cube\n#\nalgebraic3d\n\n# cube consisting of 6 planes:\n\nsolid cube = orthobrick (0, 0, 0; 1, 1, 1);\n\ntlo cube;\n\n"
  },
  {
    "path": "tutorials/part1.stl",
    "content": "solid\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -9.172298e-016\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 6.332898e+000\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 9.289182e-016\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.555220e+000 5.027685e+000 6.332898e+000\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 -9.289182e-016\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.543826e+000 4.897449e+000 6.332898e+000\n      vertex 4.555220e+000 5.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 1.758162e-015\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 5.332898e+000\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.543826e+000 4.897449e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -1.855524e-015\n    outer loop\n      vertex 4.543826e+000 4.897449e+000 6.332898e+000\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.509990e+000 4.771170e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 2.035888e-015\n    outer loop\n      vertex 4.509990e+000 4.771170e+000 6.332898e+000\n      vertex 4.543826e+000 4.897449e+000 5.332898e+000\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 2.152348e-015\n    outer loop\n      vertex 4.454740e+000 4.652685e+000 6.332898e+000\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 1.743410e-015\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 6.332898e+000\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 1.256074e-015\n    outer loop\n      vertex 4.287311e+000 4.453152e+000 6.332898e+000\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 1.458126e-015\n    outer loop\n      vertex 4.180220e+000 4.378166e+000 6.332898e+000\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 1.442865e-015\n    outer loop\n      vertex 4.061736e+000 4.322916e+000 6.332898e+000\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 1.855524e-015\n    outer loop\n      vertex 3.935457e+000 4.289079e+000 6.332898e+000\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 1.819131e-015\n    outer loop\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 1.797473e-015\n    outer loop\n      vertex 3.674984e+000 4.289079e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 1.063035e-015\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 6.332898e+000\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 2.152348e-015\n    outer loop\n      vertex 3.430220e+000 4.378166e+000 6.332898e+000\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 1.998129e-015\n    outer loop\n      vertex 3.323130e+000 4.453152e+000 6.332898e+000\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 1.884111e-015\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 6.332898e+000\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 1.458126e-015\n    outer loop\n      vertex 3.155701e+000 4.652685e+000 6.332898e+000\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 1.442865e-015\n    outer loop\n      vertex 3.100451e+000 4.771170e+000 6.332898e+000\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 1.855524e-015\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 6.332898e+000\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 9.289182e-016\n    outer loop\n      vertex 3.055220e+000 5.027685e+000 6.332898e+000\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 1.283078e-015\n    outer loop\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 9.030055e-016\n    outer loop\n      vertex 3.100451e+000 5.284200e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 1.076174e-015\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 6.332898e+000\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 8.717048e-016\n    outer loop\n      vertex 3.230687e+000 5.509776e+000 6.332898e+000\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 1.256074e-015\n    outer loop\n      vertex 3.323130e+000 5.602218e+000 6.332898e+000\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 7.290631e-016\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 6.332898e+000\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 9.091125e-016\n    outer loop\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 1.847865e-016\n    outer loop\n      vertex 3.674984e+000 5.766291e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 8.902133e-016\n    outer loop\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 8.406791e-016\n    outer loop\n      vertex 3.935457e+000 5.766291e+000 6.332898e+000\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 1.760920e-015\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 1.076174e-015\n    outer loop\n      vertex 4.180220e+000 5.677204e+000 6.332898e+000\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 5.079283e-016\n    outer loop\n      vertex 4.287311e+000 5.602218e+000 6.332898e+000\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 6.280370e-016\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 6.332898e+000\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 7.290631e-016\n    outer loop\n      vertex 4.454740e+000 5.402685e+000 6.332898e+000\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 9.091125e-016\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 6.332898e+000\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 8.128234e-016\n    outer loop\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n      vertex 4.543826e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -9.023020e-016\n    outer loop\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n      vertex 4.509990e+000 5.284200e+000 6.332898e+000\n      vertex 4.509990e+000 5.284200e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -1.081435e-015\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 6.332898e+000\n      vertex 4.454740e+000 5.402685e+000 6.332898e+000\n      vertex 4.454740e+000 5.402685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -1.235481e-015\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 6.332898e+000\n      vertex 4.379754e+000 5.509776e+000 5.332898e+000\n      vertex 4.454740e+000 5.402685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -1.260569e-015\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 6.332898e+000\n      vertex 4.287311e+000 5.602218e+000 6.332898e+000\n      vertex 4.287311e+000 5.602218e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -7.165339e-016\n    outer loop\n      vertex 4.287311e+000 5.602218e+000 6.332898e+000\n      vertex 4.180220e+000 5.677204e+000 6.332898e+000\n      vertex 4.180220e+000 5.677204e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -9.951860e-017\n    outer loop\n      vertex 4.180220e+000 5.677204e+000 6.332898e+000\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 4.061736e+000 5.732455e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -1.041628e-015\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 3.935457e+000 5.766291e+000 6.332898e+000\n      vertex 3.935457e+000 5.766291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -8.902133e-016\n    outer loop\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n      vertex 3.805220e+000 5.777685e+000 5.332898e+000\n      vertex 3.935457e+000 5.766291e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -1.726648e-015\n    outer loop\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n      vertex 3.674984e+000 5.766291e+000 6.332898e+000\n      vertex 3.674984e+000 5.766291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -9.089365e-016\n    outer loop\n      vertex 3.674984e+000 5.766291e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -1.081435e-015\n    outer loop\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 3.430220e+000 5.677204e+000 6.332898e+000\n      vertex 3.430220e+000 5.677204e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -5.042276e-016\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 6.332898e+000\n      vertex 3.323130e+000 5.602218e+000 6.332898e+000\n      vertex 3.323130e+000 5.602218e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -9.421094e-016\n    outer loop\n      vertex 3.323130e+000 5.602218e+000 6.332898e+000\n      vertex 3.230687e+000 5.509776e+000 6.332898e+000\n      vertex 3.230687e+000 5.509776e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -7.298031e-016\n    outer loop\n      vertex 3.230687e+000 5.509776e+000 6.332898e+000\n      vertex 3.155701e+000 5.402685e+000 6.332898e+000\n      vertex 3.155701e+000 5.402685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -9.089365e-016\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 6.332898e+000\n      vertex 3.100451e+000 5.284200e+000 6.332898e+000\n      vertex 3.100451e+000 5.284200e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -6.103807e-016\n    outer loop\n      vertex 3.100451e+000 5.284200e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -9.289182e-016\n    outer loop\n      vertex 3.055220e+000 5.027685e+000 6.332898e+000\n      vertex 3.055220e+000 5.027685e+000 5.332898e+000\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 -1.759821e-015\n    outer loop\n      vertex 3.055220e+000 5.027685e+000 6.332898e+000\n      vertex 3.066615e+000 4.897449e+000 6.332898e+000\n      vertex 3.066615e+000 4.897449e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -2.036814e-015\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 6.332898e+000\n      vertex 3.100451e+000 4.771170e+000 6.332898e+000\n      vertex 3.100451e+000 4.771170e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -2.149602e-015\n    outer loop\n      vertex 3.100451e+000 4.771170e+000 6.332898e+000\n      vertex 3.155701e+000 4.652685e+000 6.332898e+000\n      vertex 3.155701e+000 4.652685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 -1.738258e-015\n    outer loop\n      vertex 3.155701e+000 4.652685e+000 6.332898e+000\n      vertex 3.230687e+000 4.545594e+000 6.332898e+000\n      vertex 3.230687e+000 4.545594e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -1.579028e-015\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 6.332898e+000\n      vertex 3.323130e+000 4.453152e+000 6.332898e+000\n      vertex 3.323130e+000 4.453152e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 -1.459606e-015\n    outer loop\n      vertex 3.323130e+000 4.453152e+000 6.332898e+000\n      vertex 3.430220e+000 4.378166e+000 6.332898e+000\n      vertex 3.430220e+000 4.378166e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -2.434888e-015\n    outer loop\n      vertex 3.430220e+000 4.378166e+000 6.332898e+000\n      vertex 3.548705e+000 4.322916e+000 6.332898e+000\n      vertex 3.548705e+000 4.322916e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -1.738258e-015\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 6.332898e+000\n      vertex 3.674984e+000 4.289079e+000 6.332898e+000\n      vertex 3.674984e+000 4.289079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -1.819532e-015\n    outer loop\n      vertex 3.674984e+000 4.289079e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 -1.758162e-015\n    outer loop\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n      vertex 3.935457e+000 4.289079e+000 6.332898e+000\n      vertex 3.935457e+000 4.289079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -2.036814e-015\n    outer loop\n      vertex 3.935457e+000 4.289079e+000 6.332898e+000\n      vertex 4.061736e+000 4.322916e+000 6.332898e+000\n      vertex 4.061736e+000 4.322916e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -2.149602e-015\n    outer loop\n      vertex 4.061736e+000 4.322916e+000 6.332898e+000\n      vertex 4.180220e+000 4.378166e+000 6.332898e+000\n      vertex 4.180220e+000 4.378166e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -2.242486e-015\n    outer loop\n      vertex 4.180220e+000 4.378166e+000 6.332898e+000\n      vertex 4.287311e+000 4.453152e+000 6.332898e+000\n      vertex 4.287311e+000 4.453152e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 -1.884219e-015\n    outer loop\n      vertex 4.287311e+000 4.453152e+000 6.332898e+000\n      vertex 4.379754e+000 4.545594e+000 6.332898e+000\n      vertex 4.379754e+000 4.545594e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 -1.459606e-015\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 6.332898e+000\n      vertex 4.454740e+000 4.652685e+000 6.332898e+000\n      vertex 4.454740e+000 4.652685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 -1.446337e-015\n    outer loop\n      vertex 4.454740e+000 4.652685e+000 6.332898e+000\n      vertex 4.509990e+000 4.771170e+000 6.332898e+000\n      vertex 4.509990e+000 4.771170e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 7.470115e-016\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 3.332898e+000\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 -3.096394e-016\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n      vertex 4.305220e+000 5.027685e+000 3.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 3.096394e-016\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 3.332898e+000\n      vertex 4.305220e+000 5.027685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 -8.715574e-002 -7.470115e-016\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n      vertex 4.297624e+000 5.114509e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 4.372095e-016\n    outer loop\n      vertex 4.297624e+000 5.114509e+000 3.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n      vertex 4.275067e+000 5.198695e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 -2.588190e-001 -4.207050e-016\n    outer loop\n      vertex 4.275067e+000 5.198695e+000 3.332898e+000\n      vertex 4.297624e+000 5.114509e+000 5.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 -5.923291e-016\n    outer loop\n      vertex 4.238233e+000 5.277685e+000 3.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 -3.264175e-016\n    outer loop\n      vertex 4.188243e+000 5.349079e+000 3.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 -6.280370e-016\n    outer loop\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 -4.011357e-016\n    outer loop\n      vertex 4.055220e+000 5.460698e+000 3.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 -4.003141e-016\n    outer loop\n      vertex 3.976231e+000 5.497531e+000 3.332898e+000\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 -9.236361e-016\n    outer loop\n      vertex 3.892045e+000 5.520089e+000 3.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 -5.999263e-016\n    outer loop\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 -7.272716e-016\n    outer loop\n      vertex 3.718396e+000 5.520089e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 -4.207050e-016\n    outer loop\n      vertex 3.634210e+000 5.497531e+000 3.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 -6.861692e-016\n    outer loop\n      vertex 3.555220e+000 5.460698e+000 3.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 -5.811366e-016\n    outer loop\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 -6.280370e-016\n    outer loop\n      vertex 3.422198e+000 5.349079e+000 3.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 -5.830240e-016\n    outer loop\n      vertex 3.372208e+000 5.277685e+000 3.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 -4.138746e-016\n    outer loop\n      vertex 3.335374e+000 5.198695e+000 3.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 -4.372095e-016\n    outer loop\n      vertex 3.312817e+000 5.114509e+000 3.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 -6.192788e-016\n    outer loop\n      vertex 3.305220e+000 5.027685e+000 3.332898e+000\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 -7.466241e-016\n    outer loop\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 -7.501224e-016\n    outer loop\n      vertex 3.335374e+000 4.856675e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 -5.787686e-016\n    outer loop\n      vertex 3.372208e+000 4.777685e+000 3.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 -5.811366e-016\n    outer loop\n      vertex 3.422198e+000 4.706291e+000 3.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 -6.280370e-016\n    outer loop\n      vertex 3.483827e+000 4.644663e+000 3.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 -5.284953e-016\n    outer loop\n      vertex 3.555220e+000 4.594672e+000 3.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 -8.027956e-016\n    outer loop\n      vertex 3.634210e+000 4.557839e+000 3.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 -4.946788e-016\n    outer loop\n      vertex 3.718396e+000 4.535281e+000 3.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 -5.999263e-016\n    outer loop\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 -2.848723e-016\n    outer loop\n      vertex 3.892045e+000 4.535281e+000 3.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 -8.496622e-016\n    outer loop\n      vertex 3.976231e+000 4.557839e+000 3.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -7.800093e-016\n    outer loop\n      vertex 4.055220e+000 4.594672e+000 3.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -5.811366e-016\n    outer loop\n      vertex 4.126614e+000 4.644663e+000 3.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 -9.420555e-016\n    outer loop\n      vertex 4.188243e+000 4.706291e+000 3.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 -6.558548e-016\n    outer loop\n      vertex 4.238233e+000 4.777685e+000 3.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 -8.027956e-016\n    outer loop\n      vertex 4.275067e+000 4.856675e+000 3.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 -4.372095e-016\n    outer loop\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n      vertex 4.297624e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 4.204661e-016\n    outer loop\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n      vertex 4.275067e+000 4.856675e+000 3.332898e+000\n      vertex 4.275067e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 5.946236e-016\n    outer loop\n      vertex 4.275067e+000 4.856675e+000 3.332898e+000\n      vertex 4.238233e+000 4.777685e+000 3.332898e+000\n      vertex 4.238233e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 3.259234e-016\n    outer loop\n      vertex 4.238233e+000 4.777685e+000 3.332898e+000\n      vertex 4.188243e+000 4.706291e+000 3.332898e+000\n      vertex 4.188243e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 6.269672e-016\n    outer loop\n      vertex 4.188243e+000 4.706291e+000 3.332898e+000\n      vertex 4.126614e+000 4.644663e+000 3.332898e+000\n      vertex 4.126614e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 4.005624e-016\n    outer loop\n      vertex 4.126614e+000 4.644663e+000 3.332898e+000\n      vertex 4.055220e+000 4.594672e+000 3.332898e+000\n      vertex 4.055220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 4.005624e-016\n    outer loop\n      vertex 4.055220e+000 4.594672e+000 3.332898e+000\n      vertex 3.976231e+000 4.557839e+000 3.332898e+000\n      vertex 3.976231e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 9.230350e-016\n    outer loop\n      vertex 3.976231e+000 4.557839e+000 3.332898e+000\n      vertex 3.892045e+000 4.535281e+000 3.332898e+000\n      vertex 3.892045e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 6.002215e-016\n    outer loop\n      vertex 3.892045e+000 4.535281e+000 3.332898e+000\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 3.805220e+000 4.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 7.277298e-016\n    outer loop\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 3.718396e+000 4.535281e+000 3.332898e+000\n      vertex 3.718396e+000 4.535281e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 4.204661e-016\n    outer loop\n      vertex 3.718396e+000 4.535281e+000 3.332898e+000\n      vertex 3.634210e+000 4.557839e+000 3.332898e+000\n      vertex 3.634210e+000 4.557839e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 6.841904e-016\n    outer loop\n      vertex 3.634210e+000 4.557839e+000 3.332898e+000\n      vertex 3.555220e+000 4.594672e+000 3.332898e+000\n      vertex 3.555220e+000 4.594672e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 5.796958e-016\n    outer loop\n      vertex 3.555220e+000 4.594672e+000 3.332898e+000\n      vertex 3.483827e+000 4.644663e+000 3.332898e+000\n      vertex 3.483827e+000 4.644663e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 6.269672e-016\n    outer loop\n      vertex 3.483827e+000 4.644663e+000 3.332898e+000\n      vertex 3.422198e+000 4.706291e+000 3.332898e+000\n      vertex 3.422198e+000 4.706291e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 5.821838e-016\n    outer loop\n      vertex 3.422198e+000 4.706291e+000 3.332898e+000\n      vertex 3.372208e+000 4.777685e+000 3.332898e+000\n      vertex 3.372208e+000 4.777685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 4.154901e-016\n    outer loop\n      vertex 3.372208e+000 4.777685e+000 3.332898e+000\n      vertex 3.335374e+000 4.856675e+000 3.332898e+000\n      vertex 3.335374e+000 4.856675e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 4.366379e-016\n    outer loop\n      vertex 3.335374e+000 4.856675e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 6.195033e-016\n    outer loop\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 3.305220e+000 5.027685e+000 3.332898e+000\n      vertex 3.305220e+000 5.027685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 -8.715574e-002 7.470115e-016\n    outer loop\n      vertex 3.305220e+000 5.027685e+000 3.332898e+000\n      vertex 3.312817e+000 5.114509e+000 3.332898e+000\n      vertex 3.312817e+000 5.114509e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 -2.588190e-001 7.501214e-016\n    outer loop\n      vertex 3.312817e+000 5.114509e+000 3.332898e+000\n      vertex 3.335374e+000 5.198695e+000 3.332898e+000\n      vertex 3.335374e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 -4.226183e-001 5.796958e-016\n    outer loop\n      vertex 3.335374e+000 5.198695e+000 3.332898e+000\n      vertex 3.372208e+000 5.277685e+000 3.332898e+000\n      vertex 3.372208e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 -5.735764e-001 5.796958e-016\n    outer loop\n      vertex 3.372208e+000 5.277685e+000 3.332898e+000\n      vertex 3.422198e+000 5.349079e+000 3.332898e+000\n      vertex 3.422198e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 -7.071068e-001 6.269672e-016\n    outer loop\n      vertex 3.422198e+000 5.349079e+000 3.332898e+000\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n      vertex 3.483827e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 -8.191520e-001 5.274486e-016\n    outer loop\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n      vertex 3.555220e+000 5.460698e+000 3.332898e+000\n      vertex 3.555220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 -9.063078e-001 8.036127e-016\n    outer loop\n      vertex 3.555220e+000 5.460698e+000 3.332898e+000\n      vertex 3.634210e+000 5.497531e+000 3.332898e+000\n      vertex 3.634210e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 -9.659258e-001 4.951050e-016\n    outer loop\n      vertex 3.634210e+000 5.497531e+000 3.332898e+000\n      vertex 3.718396e+000 5.520089e+000 3.332898e+000\n      vertex 3.718396e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 -9.961947e-001 5.995996e-016\n    outer loop\n      vertex 3.718396e+000 5.520089e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 -9.961947e-001 2.848720e-016\n    outer loop\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 3.892045e+000 5.520089e+000 3.332898e+000\n      vertex 3.892045e+000 5.520089e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 -9.659258e-001 8.496400e-016\n    outer loop\n      vertex 3.892045e+000 5.520089e+000 3.332898e+000\n      vertex 3.976231e+000 5.497531e+000 3.332898e+000\n      vertex 3.976231e+000 5.497531e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 -9.063078e-001 7.787330e-016\n    outer loop\n      vertex 3.976231e+000 5.497531e+000 3.332898e+000\n      vertex 4.055220e+000 5.460698e+000 3.332898e+000\n      vertex 4.055220e+000 5.460698e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 -8.191520e-001 5.796958e-016\n    outer loop\n      vertex 4.055220e+000 5.460698e+000 3.332898e+000\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 4.126614e+000 5.410707e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 -7.071068e-001 9.404508e-016\n    outer loop\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 4.188243e+000 5.349079e+000 3.332898e+000\n      vertex 4.188243e+000 5.349079e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 -5.735764e-001 6.543348e-016\n    outer loop\n      vertex 4.188243e+000 5.349079e+000 3.332898e+000\n      vertex 4.238233e+000 5.277685e+000 3.332898e+000\n      vertex 4.238233e+000 5.277685e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 -4.226183e-001 8.036127e-016\n    outer loop\n      vertex 4.238233e+000 5.277685e+000 3.332898e+000\n      vertex 4.275067e+000 5.198695e+000 3.332898e+000\n      vertex 4.275067e+000 5.198695e+000 5.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.000000e-001 6.000000e-001\n    outer loop\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -8.000000e-001 6.000000e-001\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 8.052205e-001 2.527685e+000 4.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -1.000000e+000 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 -1.000000e+000 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 8.052205e-001 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 4.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 5.978869e+000 7.512493e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 5.978869e+000 7.512493e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 5.978869e+000 7.512493e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 6.147241e+000 7.467378e+000 3.332898e+000\n      vertex 5.978869e+000 7.512493e+000 6.332898e+000\n      vertex 6.147241e+000 7.467378e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 6.305220e+000 7.393710e+000 3.332898e+000\n      vertex 6.147241e+000 7.467378e+000 6.332898e+000\n      vertex 6.305220e+000 7.393710e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 6.448008e+000 7.293729e+000 3.332898e+000\n      vertex 6.305220e+000 7.393710e+000 6.332898e+000\n      vertex 6.448008e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 6.571265e+000 7.170473e+000 3.332898e+000\n      vertex 6.448008e+000 7.293729e+000 6.332898e+000\n      vertex 6.571265e+000 7.170473e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 6.671246e+000 7.027685e+000 3.332898e+000\n      vertex 6.571265e+000 7.170473e+000 6.332898e+000\n      vertex 6.671246e+000 7.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 6.744913e+000 6.869705e+000 3.332898e+000\n      vertex 6.671246e+000 7.027685e+000 6.332898e+000\n      vertex 6.744913e+000 6.869705e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 6.790028e+000 6.701333e+000 3.332898e+000\n      vertex 6.744913e+000 6.869705e+000 6.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 6.790028e+000 6.701333e+000 3.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 6.790028e+000 6.701333e+000 3.332898e+000\n      vertex 6.744913e+000 6.869705e+000 3.332898e+000\n      vertex 6.744913e+000 6.869705e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 6.744913e+000 6.869705e+000 3.332898e+000\n      vertex 6.671246e+000 7.027685e+000 3.332898e+000\n      vertex 6.671246e+000 7.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 6.671246e+000 7.027685e+000 3.332898e+000\n      vertex 6.571265e+000 7.170473e+000 3.332898e+000\n      vertex 6.571265e+000 7.170473e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 6.571265e+000 7.170473e+000 3.332898e+000\n      vertex 6.448008e+000 7.293729e+000 3.332898e+000\n      vertex 6.448008e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 6.448008e+000 7.293729e+000 3.332898e+000\n      vertex 6.305220e+000 7.393710e+000 3.332898e+000\n      vertex 6.305220e+000 7.393710e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 6.305220e+000 7.393710e+000 3.332898e+000\n      vertex 6.147241e+000 7.467378e+000 3.332898e+000\n      vertex 6.147241e+000 7.467378e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 6.147241e+000 7.467378e+000 3.332898e+000\n      vertex 5.978869e+000 7.512493e+000 3.332898e+000\n      vertex 5.978869e+000 7.512493e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 8.204127e-001 6.701333e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -9.961947e-001 8.715574e-002 0.000000e+000\n    outer loop\n      vertex 8.204127e-001 6.701333e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n      vertex 8.655279e-001 6.869705e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 0.000000e+000\n    outer loop\n      vertex 9.391951e-001 7.027685e+000 6.332898e+000\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n      vertex 8.655279e-001 6.869705e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.063078e-001 4.226183e-001 -3.354013e-017\n    outer loop\n      vertex 9.391951e-001 7.027685e+000 6.332898e+000\n      vertex 9.391951e-001 7.027685e+000 3.332898e+000\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 -3.031472e-017\n    outer loop\n      vertex 9.391951e-001 7.027685e+000 6.332898e+000\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 9.391951e-001 7.027685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -8.191520e-001 5.735764e-001 0.000000e+000\n    outer loop\n      vertex 9.391951e-001 7.027685e+000 3.332898e+000\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 1.039176e+000 7.170473e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 1.039176e+000 7.170473e+000 3.332898e+000\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -7.071068e-001 7.071068e-001 0.000000e+000\n    outer loop\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 1.162433e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 0.000000e+000\n    outer loop\n      vertex 1.305220e+000 7.393710e+000 6.332898e+000\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n      vertex 1.162433e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -5.735764e-001 8.191520e-001 -4.245318e-017\n    outer loop\n      vertex 1.305220e+000 7.393710e+000 6.332898e+000\n      vertex 1.305220e+000 7.393710e+000 3.332898e+000\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 -3.128003e-017\n    outer loop\n      vertex 1.305220e+000 7.393710e+000 6.332898e+000\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.305220e+000 7.393710e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -4.226183e-001 9.063078e-001 0.000000e+000\n    outer loop\n      vertex 1.305220e+000 7.393710e+000 3.332898e+000\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.463200e+000 7.467378e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 1.463200e+000 7.467378e+000 3.332898e+000\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.631572e+000 7.512493e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal -2.588190e-001 9.659258e-001 0.000000e+000\n    outer loop\n      vertex 1.631572e+000 7.512493e+000 3.332898e+000\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.631572e+000 7.512493e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.631572e+000 7.512493e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -8.715574e-002 9.961947e-001 0.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.631572e+000 7.512493e+000 3.332898e+000\n      vertex 1.631572e+000 7.512493e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal -9.659258e-001 2.588190e-001 0.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n      vertex 8.204127e-001 6.701333e+000 3.332898e+000\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 1.000000e+000 0.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 3.332898e+000\n      vertex 4.297624e+000 5.114509e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.275067e+000 4.856675e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 4.238233e+000 4.777685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.275067e+000 4.856675e+000 3.332898e+000\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.275067e+000 5.198695e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 4.297624e+000 5.114509e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.275067e+000 5.198695e+000 3.332898e+000\n      vertex 4.238233e+000 5.277685e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 4.238233e+000 5.277685e+000 3.332898e+000\n      vertex 4.188243e+000 5.349079e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 4.188243e+000 5.349079e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.126614e+000 5.410707e+000 3.332898e+000\n      vertex 4.055220e+000 5.460698e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 4.055220e+000 5.460698e+000 3.332898e+000\n      vertex 3.976231e+000 5.497531e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.892045e+000 5.520089e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 3.976231e+000 5.497531e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.892045e+000 5.520089e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 3.805220e+000 5.527685e+000 3.332898e+000\n      vertex 3.718396e+000 5.520089e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.634210e+000 5.497531e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 3.718396e+000 5.520089e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.634210e+000 5.497531e+000 3.332898e+000\n      vertex 3.555220e+000 5.460698e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 3.555220e+000 5.460698e+000 3.332898e+000\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n      vertex 3.422198e+000 5.349079e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.372208e+000 5.277685e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 3.422198e+000 5.349079e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.372208e+000 5.277685e+000 3.332898e+000\n      vertex 3.335374e+000 5.198695e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 3.335374e+000 5.198695e+000 3.332898e+000\n      vertex 3.312817e+000 5.114509e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.305220e+000 5.027685e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 3.312817e+000 5.114509e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.305220e+000 5.027685e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.312817e+000 4.940861e+000 3.332898e+000\n      vertex 3.335374e+000 4.856675e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.372208e+000 4.777685e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.335374e+000 4.856675e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.372208e+000 4.777685e+000 3.332898e+000\n      vertex 3.422198e+000 4.706291e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.422198e+000 4.706291e+000 3.332898e+000\n      vertex 3.483827e+000 4.644663e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.555220e+000 4.594672e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.483827e+000 4.644663e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.555220e+000 4.594672e+000 3.332898e+000\n      vertex 3.634210e+000 4.557839e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.634210e+000 4.557839e+000 3.332898e+000\n      vertex 3.718396e+000 4.535281e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n      vertex 3.718396e+000 4.535281e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 8.052205e-001 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.805220e+000 4.527685e+000 3.332898e+000\n      vertex 3.892045e+000 4.535281e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 3.892045e+000 4.535281e+000 3.332898e+000\n      vertex 3.976231e+000 4.557839e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.055220e+000 4.594672e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 3.976231e+000 4.557839e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.055220e+000 4.594672e+000 3.332898e+000\n      vertex 4.126614e+000 4.644663e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 4.126614e+000 4.644663e+000 3.332898e+000\n      vertex 4.188243e+000 4.706291e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.238233e+000 4.777685e+000 3.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 4.188243e+000 4.706291e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 4.305220e+000 5.027685e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 4.297624e+000 4.940861e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.147241e+000 7.467378e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 5.978869e+000 7.512493e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.147241e+000 7.467378e+000 3.332898e+000\n      vertex 6.305220e+000 7.393710e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 6.305220e+000 7.393710e+000 3.332898e+000\n      vertex 6.448008e+000 7.293729e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.571265e+000 7.170473e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 6.448008e+000 7.293729e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.571265e+000 7.170473e+000 3.332898e+000\n      vertex 6.671246e+000 7.027685e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 6.671246e+000 7.027685e+000 3.332898e+000\n      vertex 6.744913e+000 6.869705e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.790028e+000 6.701333e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n      vertex 6.744913e+000 6.869705e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 6.790028e+000 6.701333e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n      vertex 5.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 8.204127e-001 6.701333e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 3.483827e+000 5.410707e+000 3.332898e+000\n      vertex 8.052205e-001 6.527685e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 8.204127e-001 6.701333e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 3.332898e+000\n      vertex 9.391951e-001 7.027685e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 9.391951e-001 7.027685e+000 3.332898e+000\n      vertex 1.039176e+000 7.170473e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.039176e+000 7.170473e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.162433e+000 7.293729e+000 3.332898e+000\n      vertex 1.305220e+000 7.393710e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.305220e+000 7.393710e+000 3.332898e+000\n      vertex 1.463200e+000 7.467378e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 -1.000000e+000\n    outer loop\n      vertex 1.631572e+000 7.512493e+000 3.332898e+000\n      vertex 1.805220e+000 7.527685e+000 3.332898e+000\n      vertex 1.463200e+000 7.467378e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 6.332898e+000\n      vertex 4.543826e+000 4.897449e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n      vertex 4.454740e+000 5.402685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.509990e+000 5.284200e+000 6.332898e+000\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.543826e+000 4.897449e+000 6.332898e+000\n      vertex 4.509990e+000 4.771170e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 4.509990e+000 4.771170e+000 6.332898e+000\n      vertex 4.454740e+000 4.652685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 4.454740e+000 4.652685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 4.545594e+000 6.332898e+000\n      vertex 4.287311e+000 4.453152e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 4.287311e+000 4.453152e+000 6.332898e+000\n      vertex 4.180220e+000 4.378166e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 4.322916e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 4.180220e+000 4.378166e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 4.322916e+000 6.332898e+000\n      vertex 3.935457e+000 4.289079e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 3.935457e+000 4.289079e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n      vertex 3.674984e+000 4.289079e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.674984e+000 4.289079e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 4.322916e+000 6.332898e+000\n      vertex 3.430220e+000 4.378166e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.430220e+000 4.378166e+000 6.332898e+000\n      vertex 3.323130e+000 4.453152e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.323130e+000 4.453152e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.230687e+000 4.545594e+000 6.332898e+000\n      vertex 3.155701e+000 4.652685e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.155701e+000 4.652685e+000 6.332898e+000\n      vertex 3.100451e+000 4.771170e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.100451e+000 4.771170e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.066615e+000 4.897449e+000 6.332898e+000\n      vertex 3.055220e+000 5.027685e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.055220e+000 5.027685e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n      vertex 3.100451e+000 5.284200e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 3.100451e+000 5.284200e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.155701e+000 5.402685e+000 6.332898e+000\n      vertex 3.230687e+000 5.509776e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 3.230687e+000 5.509776e+000 6.332898e+000\n      vertex 3.323130e+000 5.602218e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 3.323130e+000 5.602218e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.430220e+000 5.677204e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 9.391951e-001 7.027685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.655279e-001 6.869705e+000 6.332898e+000\n      vertex 8.204127e-001 6.701333e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 3.548705e+000 5.732455e+000 6.332898e+000\n      vertex 3.674984e+000 5.766291e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 3.674984e+000 5.766291e+000 6.332898e+000\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n      vertex 3.935457e+000 5.766291e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 3.935457e+000 5.766291e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.061736e+000 5.732455e+000 6.332898e+000\n      vertex 4.180220e+000 5.677204e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n      vertex 4.180220e+000 5.677204e+000 6.332898e+000\n      vertex 4.287311e+000 5.602218e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n      vertex 4.287311e+000 5.602218e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.379754e+000 5.509776e+000 6.332898e+000\n      vertex 4.454740e+000 5.402685e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 4.555220e+000 5.027685e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 4.543826e+000 5.157921e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 3.805220e+000 4.277685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.744913e+000 6.869705e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 6.790028e+000 6.701333e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.744913e+000 6.869705e+000 6.332898e+000\n      vertex 6.671246e+000 7.027685e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 6.671246e+000 7.027685e+000 6.332898e+000\n      vertex 6.571265e+000 7.170473e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.448008e+000 7.293729e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 6.571265e+000 7.170473e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 6.448008e+000 7.293729e+000 6.332898e+000\n      vertex 6.305220e+000 7.393710e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 6.305220e+000 7.393710e+000 6.332898e+000\n      vertex 6.147241e+000 7.467378e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 5.978869e+000 7.512493e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n      vertex 6.147241e+000 7.467378e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 3.805220e+000 5.777685e+000 6.332898e+000\n      vertex 5.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 1.631572e+000 7.512493e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.463200e+000 7.467378e+000 6.332898e+000\n      vertex 1.305220e+000 7.393710e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 1.305220e+000 7.393710e+000 6.332898e+000\n      vertex 1.162433e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n      vertex 1.162433e+000 7.293729e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 1.039176e+000 7.170473e+000 6.332898e+000\n      vertex 9.391951e-001 7.027685e+000 6.332898e+000\n      vertex 1.805220e+000 7.527685e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 0.000000e+000 0.000000e+000 1.000000e+000\n    outer loop\n      vertex 8.052205e-001 6.527685e+000 6.332898e+000\n      vertex 8.052205e-001 4.027685e+000 6.332898e+000\n      vertex 3.066615e+000 5.157921e+000 6.332898e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 6.527685e+000 6.332898e+000\n      vertex 6.805220e+000 4.027685e+000 6.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\n  facet normal 1.000000e+000 0.000000e+000 0.000000e+000\n    outer loop\n      vertex 6.805220e+000 2.527685e+000 4.332898e+000\n      vertex 6.805220e+000 2.527685e+000 3.332898e+000\n      vertex 6.805220e+000 6.527685e+000 3.332898e+000\n    endloop\n  endfacet\nendsolid\n"
  },
  {
    "path": "tutorials/period.geo",
    "content": "##\n## Example with periodic boundary conditions\n##    by Joachim Schoeberl\n##\n##\n\nalgebraic3d\n\nsolid p1 = plane (0, 0, 0; 0, 0, -1);\nsolid p2 = plane (1, 1, 1; 0, 0, 1);\n\nsolid p3 = plane (0, 0, 0; 0, -1, 0);\nsolid p4 = plane (1, 1, 1; 0, 1, 0);\n\nsolid p5 = plane (0, 0, 0; -1, 0, 0);\nsolid p6 = plane (1, 1, 1; 1, 0, 0);\n\n \nsolid cube = p1 and p2 and p3 and p4 and p5 and p6;\n\nsolid cyls = \n\tcylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.3)\n\tor cylinder (0, 0.5, 0.2; 1, 0.5, 0.2; 0.1);\nsolid matrix = cube and not cyls;\nsolid inner = cube and cyls;\n\ntlo matrix -transparent;\ntlo inner -col=[1,0,0];\n\nidentify periodic p1 p2;\nidentify periodic p3 p4;\nidentify periodic p5 p6;\n\n"
  },
  {
    "path": "tutorials/revolution.geo",
    "content": "algebraic3d\n\ncurve2d testcurve=(7;\n\t1,0;\n\t1,1;\n\t1.5,1.5;\n\t2,3;\n\t2.5,1.5;\n\t3,1;\n\t3,0;\n\t3;\n\t3,1,2,3;\n\t3,3,4,5;\n\t3,5,6,7);\n\nsolid something = revolution(0,0,0;1,0,0;testcurve);\n\ntlo something;"
  },
  {
    "path": "tutorials/screw.step",
    "content": "ISO-10303-21;\nHEADER;\n FILE_DESCRIPTION(('a Product shape'),'1');\n FILE_NAME('Euclid  Shape Model','1998-09-10T11:25:01',('Author Name'),(\n    'MATRA-DATAVISION'),'OL-2.0B','EUCLID','Authorisation status');\n FILE_SCHEMA(('AUTOMOTIVE_DESIGN_CC1 { 1 2 10303 214 -1 1 3  2}'));\nENDSEC;\nDATA;\n#1 = PRODUCT_RELATED_PRODUCT_CATEGORY('Undefined Category','Undefined De\nscription',(#2));\n#2 = PRODUCT('the product name','the product name','void',(#3));\n#3 = MECHANICAL_CONTEXT('Mechanical',#4,'Assembly');\n#4 = APPLICATION_CONTEXT('EUCLID');\n#5 = APPLICATION_PROTOCOL_DEFINITION('CommitteeDraft','automotive_design\n',1997,#4);\n#6 = SHAPE_DEFINITION_REPRESENTATION(#7,#11);\n#7 = PRODUCT_DEFINITION_SHAPE('void','void',#8);\n#8 = PRODUCT_DEFINITION('void','void',#9,#10);\n#9 = PRODUCT_DEFINITION_FORMATION('ID','void',#2);\n#10 = PRODUCT_DEFINITION_CONTEXT('as proposed',#4,'First_Design');\n#11 = ADVANCED_BREP_SHAPE_REPRESENTATION('',(#12),#1236);\n#12 = MANIFOLD_SOLID_BREP('',#13);\n#13 = CLOSED_SHELL('',(#14,#257,#558,#709,#803,#874,#944,#1052,#1151,\n    #1232));\n#14 = ADVANCED_FACE('',(#15),#49,.F.);\n#15 = FACE_BOUND('',#16,.F.);\n#16 = EDGE_LOOP('',(#17,#136,#186,#214));\n#17 = ORIENTED_EDGE('',*,*,#18,.T.);\n#18 = EDGE_CURVE('',#19,#21,#23,.T.);\n#19 = VERTEX_POINT('',#20);\n#20 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633));\n#21 = VERTEX_POINT('',#22);\n#22 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633));\n#23 = SURFACE_CURVE('',#24,(#48,#80),.PCURVE_S2.);\n#24 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#25,#26,#27,#28,#29,#30,#31,#32,\n    #33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#44,#45,#46,#47),\n  .UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(-9.753048731913,\n    -8.657376849694,-4.328688424847,-2.164344212423,-1.082172106212,\n    0.E+000,1.082172106212,2.164344212423,4.328688424847,8.657376849694,\n    9.753048731913),.UNSPECIFIED.);\n#25 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633));\n#26 = CARTESIAN_POINT('',(-27.44664177115,0.423702927757,5.566853116015)\n  );\n#27 = CARTESIAN_POINT('',(-27.07201055731,0.423702927757,5.693350129935)\n  );\n#28 = CARTESIAN_POINT('',(-25.21253263571,0.423702927757,6.298546031822)\n  );\n#29 = CARTESIAN_POINT('',(-23.71979442537,0.423702927757,6.713431512354)\n  );\n#30 = CARTESIAN_POINT('',(-21.51106042838,0.423702927757,7.221607932559)\n  );\n#31 = CARTESIAN_POINT('',(-20.78124758741,0.423702927757,7.372657524772)\n  );\n#32 = CARTESIAN_POINT('',(-19.696293462,0.423702927757,7.56017012803));\n#33 = CARTESIAN_POINT('',(-19.33642071715,0.423702927757,7.616304970701)\n  );\n#34 = CARTESIAN_POINT('',(-18.61775332841,0.423702927757,7.702450972357)\n  );\n#35 = CARTESIAN_POINT('',(-18.25883772732,0.423702927757,7.731450038723)\n  );\n#36 = CARTESIAN_POINT('',(-17.89811369191,0.423702927757,7.731450038723)\n  );\n#37 = CARTESIAN_POINT('',(-17.53738965651,0.423702927757,7.731450038723)\n  );\n#38 = CARTESIAN_POINT('',(-17.17847405541,0.423702927757,7.702450972357)\n  );\n#39 = CARTESIAN_POINT('',(-16.45980666667,0.423702927757,7.616304970701)\n  );\n#40 = CARTESIAN_POINT('',(-16.09993392183,0.423702927757,7.56017012803)\n  );\n#41 = CARTESIAN_POINT('',(-15.01497979641,0.423702927757,7.372657524772)\n  );\n#42 = CARTESIAN_POINT('',(-14.28516695545,0.423702927757,7.221607932559)\n  );\n#43 = CARTESIAN_POINT('',(-12.07643295845,0.423702927757,6.713431512354)\n  );\n#44 = CARTESIAN_POINT('',(-10.58369474811,0.423702927757,6.298546031822)\n  );\n#45 = CARTESIAN_POINT('',(-8.724216826515,0.423702927757,5.693350129935)\n  );\n#46 = CARTESIAN_POINT('',(-8.349585612678,0.423702927757,5.566853116015)\n  );\n#47 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633));\n#48 = PCURVE('',#49,#54);\n#49 = PLANE('',#50);\n#50 = AXIS2_PLACEMENT_3D('',#51,#52,#53);\n#51 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,7.93633));\n#52 = DIRECTION('',(0.E+000,1.,0.E+000));\n#53 = DIRECTION('',(0.E+000,0.E+000,1.));\n#54 = DEFINITIONAL_REPRESENTATION('',(#55),#79);\n#55 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#56,#57,#58,#59,#60,#61,#62,#63,\n    #64,#65,#66,#67,#68,#69,#70,#71,#72,#73,#74,#75,#76,#77,#78),\n  .UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(-9.753048731913,\n    -8.657376849694,-4.328688424847,-2.164344212423,-1.082172106212,\n    0.E+000,1.082172106212,2.164344212423,4.328688424847,8.657376849694,\n    9.753048731913),.UNSPECIFIED.);\n#56 = CARTESIAN_POINT('',(-2.5,-24.92156741649));\n#57 = CARTESIAN_POINT('',(-2.369476883985,-24.54852807923));\n#58 = CARTESIAN_POINT('',(-2.242979870065,-24.1738968654));\n#59 = CARTESIAN_POINT('',(-1.637783968178,-22.31441894379));\n#60 = CARTESIAN_POINT('',(-1.222898487646,-20.82168073346));\n#61 = CARTESIAN_POINT('',(-0.714722067441,-18.61294673646));\n#62 = CARTESIAN_POINT('',(-0.563672475228,-17.88313389549));\n#63 = CARTESIAN_POINT('',(-0.37615987197,-16.79817977008));\n#64 = CARTESIAN_POINT('',(-0.320025029299,-16.43830702524));\n#65 = CARTESIAN_POINT('',(-0.233879027643,-15.71963963649));\n#66 = CARTESIAN_POINT('',(-0.204879961277,-15.3607240354));\n#67 = CARTESIAN_POINT('',(-0.204879961277,-15.));\n#68 = CARTESIAN_POINT('',(-0.204879961277,-14.63927596459));\n#69 = CARTESIAN_POINT('',(-0.233879027643,-14.2803603635));\n#70 = CARTESIAN_POINT('',(-0.320025029299,-13.56169297476));\n#71 = CARTESIAN_POINT('',(-0.37615987197,-13.20182022991));\n#72 = CARTESIAN_POINT('',(-0.563672475228,-12.1168661045));\n#73 = CARTESIAN_POINT('',(-0.714722067441,-11.38705326353));\n#74 = CARTESIAN_POINT('',(-1.222898487646,-9.178319266539));\n#75 = CARTESIAN_POINT('',(-1.637783968178,-7.685581056201));\n#76 = CARTESIAN_POINT('',(-2.242979870065,-5.826103134599));\n#77 = CARTESIAN_POINT('',(-2.369476883985,-5.451471920761));\n#78 = CARTESIAN_POINT('',(-2.5,-5.078432583508));\n#79 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#80 = PCURVE('',#81,#86);\n#81 = TOROIDAL_SURFACE('',#82,8.25,54.873718663856);\n#82 = AXIS2_PLACEMENT_3D('',#83,#84,#85);\n#83 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367));\n#84 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#85 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016));\n#86 = DEFINITIONAL_REPRESENTATION('',(#87),#135);\n#87 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#88,#89,#90,#91,#92,#93,#94,#95,\n    #96,#97,#98,#99,#100,#101,#102,#103,#104,#105,#106,#107,#108,#109,\n    #110,#111,#112,#113,#114,#115,#116,#117,#118,#119,#120,#121,#122,\n    #123,#124,#125,#126,#127,#128,#129,#130,#131,#132,#133,#134),\n  .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\n    ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(-9.753048731913,\n    -9.309728335008,-8.866407938103,-8.423087541198,-7.979767144292,\n    -7.536446747387,-7.093126350482,-6.649805953577,-6.206485556672,\n    -5.763165159767,-5.319844762862,-4.876524365957,-4.433203969051,\n    -3.989883572146,-3.546563175241,-3.103242778336,-2.659922381431,\n    -2.216601984526,-1.773281587621,-1.329961190715,-0.88664079381,\n    -0.443320396905,-3.552713678801E-015,0.443320396905,0.88664079381,\n    1.329961190715,1.773281587621,2.216601984526,2.659922381431,\n    3.103242778336,3.546563175241,3.989883572146,4.433203969051,\n    4.876524365957,5.319844762862,5.763165159767,6.206485556672,\n    6.649805953577,7.093126350482,7.536446747387,7.979767144292,\n    8.423087541198,8.866407938103,9.309728335008,9.753048731913),\n  .UNSPECIFIED.);\n#88 = CARTESIAN_POINT('',(1.696124157963,-1.90983622455));\n#89 = CARTESIAN_POINT('',(1.698012122136,-1.906942595099));\n#90 = CARTESIAN_POINT('',(1.701959356034,-1.901155814072));\n#91 = CARTESIAN_POINT('',(1.7084874644,-1.89248391648));\n#92 = CARTESIAN_POINT('',(1.715711359905,-1.883824473771));\n#93 = CARTESIAN_POINT('',(1.723736411497,-1.875190974748));\n#94 = CARTESIAN_POINT('',(1.732699041614,-1.866586665031));\n#95 = CARTESIAN_POINT('',(1.742767310299,-1.858016637247));\n#96 = CARTESIAN_POINT('',(1.754151612829,-1.849486074495));\n#97 = CARTESIAN_POINT('',(1.767118375587,-1.841000912303));\n#98 = CARTESIAN_POINT('',(1.782009704244,-1.832567946628));\n#99 = CARTESIAN_POINT('',(1.799271790701,-1.824195173621));\n#100 = CARTESIAN_POINT('',(1.819496092675,-1.815892420892));\n#101 = CARTESIAN_POINT('',(1.843483731328,-1.80767162354));\n#102 = CARTESIAN_POINT('',(1.872335628537,-1.799549911231));\n#103 = CARTESIAN_POINT('',(1.907592262986,-1.791552841646));\n#104 = CARTESIAN_POINT('',(1.951530266856,-1.783707862826));\n#105 = CARTESIAN_POINT('',(2.007543357991,-1.776058774724));\n#106 = CARTESIAN_POINT('',(2.080862934592,-1.768674005145));\n#107 = CARTESIAN_POINT('',(2.179681847184,-1.761668166881));\n#108 = CARTESIAN_POINT('',(2.317050874271,-1.755240554276));\n#109 = CARTESIAN_POINT('',(2.512524285783,-1.74974343193));\n#110 = CARTESIAN_POINT('',(2.788441810662,-1.745797607263));\n#111 = CARTESIAN_POINT('',(3.14159265359,-1.744297890708));\n#112 = CARTESIAN_POINT('',(3.494743496518,-1.745797607263));\n#113 = CARTESIAN_POINT('',(3.770661021397,-1.74974343193));\n#114 = CARTESIAN_POINT('',(3.966134432908,-1.755240554276));\n#115 = CARTESIAN_POINT('',(4.103503459996,-1.761668166881));\n#116 = CARTESIAN_POINT('',(4.202322372587,-1.768674005145));\n#117 = CARTESIAN_POINT('',(4.275641949188,-1.776058774724));\n#118 = CARTESIAN_POINT('',(4.331655040323,-1.783707862826));\n#119 = CARTESIAN_POINT('',(4.375593044193,-1.791552841646));\n#120 = CARTESIAN_POINT('',(4.410849678643,-1.799549911231));\n#121 = CARTESIAN_POINT('',(4.439701575852,-1.80767162354));\n#122 = CARTESIAN_POINT('',(4.463689214504,-1.815892420892));\n#123 = CARTESIAN_POINT('',(4.483913516478,-1.824195173621));\n#124 = CARTESIAN_POINT('',(4.501175602935,-1.832567946628));\n#125 = CARTESIAN_POINT('',(4.516066931592,-1.841000912303));\n#126 = CARTESIAN_POINT('',(4.529033694351,-1.849486074495));\n#127 = CARTESIAN_POINT('',(4.54041799688,-1.858016637247));\n#128 = CARTESIAN_POINT('',(4.550486265566,-1.866586665031));\n#129 = CARTESIAN_POINT('',(4.559448895683,-1.875190974748));\n#130 = CARTESIAN_POINT('',(4.567473947275,-1.883824473771));\n#131 = CARTESIAN_POINT('',(4.57469784278,-1.89248391648));\n#132 = CARTESIAN_POINT('',(4.581225951145,-1.901155814072));\n#133 = CARTESIAN_POINT('',(4.585173185044,-1.906942595099));\n#134 = CARTESIAN_POINT('',(4.587061149217,-1.90983622455));\n#135 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#136 = ORIENTED_EDGE('',*,*,#137,.T.);\n#137 = EDGE_CURVE('',#21,#138,#140,.T.);\n#138 = VERTEX_POINT('',#139);\n#139 = CARTESIAN_POINT('',(-10.50301396304,0.423702927757,2.93633));\n#140 = SURFACE_CURVE('',#141,(#145,#152),.PCURVE_S2.);\n#141 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#142,#143,#144),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075049,1.)) REPRESENTATION_ITEM('') );\n#142 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633));\n#143 = CARTESIAN_POINT('',(-9.420242096928,0.423702927757,4.003957457804\n    ));\n#144 = CARTESIAN_POINT('',(-10.50301396304,0.423702927757,2.93633));\n#145 = PCURVE('',#49,#146);\n#146 = DEFINITIONAL_REPRESENTATION('',(#147),#151);\n#147 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#148,#149,#150),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075049,1.)) REPRESENTATION_ITEM('') );\n#148 = CARTESIAN_POINT('',(-2.5,-5.078432583508));\n#149 = CARTESIAN_POINT('',(-3.932372542196,-6.522128405011));\n#150 = CARTESIAN_POINT('',(-5.,-7.604900271125));\n#151 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#152 = PCURVE('',#153,#158);\n#153 = CONICAL_SURFACE('',#154,7.5,0.785398163397);\n#154 = AXIS2_PLACEMENT_3D('',#155,#156,#157);\n#155 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-12.06367));\n#156 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#157 = DIRECTION('',(-1.,-1.224606353822E-016,2.719172340232E-032));\n#158 = DEFINITIONAL_REPRESENTATION('',(#159),#185);\n#159 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#160,#161,#162,#163,#164,#165,\n    #166,#167,#168,#169,#170,#171,#172,#173,#174,#175,#176,#177,#178,\n    #179,#180,#181,#182,#183,#184),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775,\n    0.323118155001,0.484677232501,0.646236310001,0.807795387502,\n    0.969354465002,1.130913542503,1.292472620003,1.454031697503,\n    1.615590775004,1.777149852504,1.938708930004,2.100268007505,\n    2.261827085005,2.423386162505,2.584945240006,2.746504317506,\n    2.908063395007,3.069622472507,3.231181550007,3.392740627508,\n    3.554299705008),.QUASI_UNIFORM_KNOTS.);\n#160 = CARTESIAN_POINT('',(6.157857476012,-17.5));\n#161 = CARTESIAN_POINT('',(6.157304831179,-17.45613532843));\n#162 = CARTESIAN_POINT('',(6.156192803831,-17.369034253));\n#163 = CARTESIAN_POINT('',(6.154504167531,-17.24022922767));\n#164 = CARTESIAN_POINT('',(6.15279455739,-17.11323215337));\n#165 = CARTESIAN_POINT('',(6.15106358201,-16.98800586851));\n#166 = CARTESIAN_POINT('',(6.149310841213,-16.86451413191));\n#167 = CARTESIAN_POINT('',(6.147535924576,-16.74272172673));\n#168 = CARTESIAN_POINT('',(6.145738411434,-16.62259438981));\n#169 = CARTESIAN_POINT('',(6.143917870468,-16.5040987895));\n#170 = CARTESIAN_POINT('',(6.142073859396,-16.38720249214));\n#171 = CARTESIAN_POINT('',(6.140205924616,-16.27187393322));\n#172 = CARTESIAN_POINT('',(6.138313600849,-16.15808238872));\n#173 = CARTESIAN_POINT('',(6.136396410758,-16.04579794794));\n#174 = CARTESIAN_POINT('',(6.134453864564,-15.93499148723));\n#175 = CARTESIAN_POINT('',(6.132485459637,-15.82563464481));\n#176 = CARTESIAN_POINT('',(6.130490680076,-15.7176997966));\n#177 = CARTESIAN_POINT('',(6.128468996271,-15.61116003298));\n#178 = CARTESIAN_POINT('',(6.126419864458,-15.50598913612));\n#179 = CARTESIAN_POINT('',(6.124342726204,-15.40216155983));\n#180 = CARTESIAN_POINT('',(6.122237008073,-15.29965240364));\n#181 = CARTESIAN_POINT('',(6.120102120531,-15.19843741256));\n#182 = CARTESIAN_POINT('',(6.11793745959,-15.09849288457));\n#183 = CARTESIAN_POINT('',(6.116474085284,-15.03269491212));\n#184 = CARTESIAN_POINT('',(6.11573722796,-15.));\n#185 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#186 = ORIENTED_EDGE('',*,*,#187,.T.);\n#187 = EDGE_CURVE('',#138,#188,#190,.T.);\n#188 = VERTEX_POINT('',#189);\n#189 = CARTESIAN_POINT('',(-25.29321342079,0.423702927757,2.93633));\n#190 = SURFACE_CURVE('',#191,(#195,#202),.PCURVE_S2.);\n#191 = LINE('',#192,#193);\n#192 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,2.93633));\n#193 = VECTOR('',#194,1.);\n#194 = DIRECTION('',(-1.,0.E+000,0.E+000));\n#195 = PCURVE('',#49,#196);\n#196 = DEFINITIONAL_REPRESENTATION('',(#197),#201);\n#197 = LINE('',#198,#199);\n#198 = CARTESIAN_POINT('',(-5.,0.E+000));\n#199 = VECTOR('',#200,1.);\n#200 = DIRECTION('',(0.E+000,-1.));\n#201 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#202 = PCURVE('',#203,#208);\n#203 = PLANE('',#204);\n#204 = AXIS2_PLACEMENT_3D('',#205,#206,#207);\n#205 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,2.93633));\n#206 = DIRECTION('',(0.E+000,0.E+000,-1.));\n#207 = DIRECTION('',(1.,0.E+000,0.E+000));\n#208 = DEFINITIONAL_REPRESENTATION('',(#209),#213);\n#209 = LINE('',#210,#211);\n#210 = CARTESIAN_POINT('',(0.E+000,0.E+000));\n#211 = VECTOR('',#212,1.);\n#212 = DIRECTION('',(-1.,0.E+000));\n#213 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#214 = ORIENTED_EDGE('',*,*,#215,.T.);\n#215 = EDGE_CURVE('',#188,#19,#216,.T.);\n#216 = SURFACE_CURVE('',#217,(#221,#228),.PCURVE_S2.);\n#217 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#218,#219,#220),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075049,1.)) REPRESENTATION_ITEM('') );\n#218 = CARTESIAN_POINT('',(-25.29321342079,0.423702927757,2.93633));\n#219 = CARTESIAN_POINT('',(-26.3759852869,0.423702927757,4.003957457804)\n  );\n#220 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633));\n#221 = PCURVE('',#49,#222);\n#222 = DEFINITIONAL_REPRESENTATION('',(#223),#227);\n#223 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#224,#225,#226),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075049,1.)) REPRESENTATION_ITEM('') );\n#224 = CARTESIAN_POINT('',(-5.,-22.39509972887));\n#225 = CARTESIAN_POINT('',(-3.932372542196,-23.47787159498));\n#226 = CARTESIAN_POINT('',(-2.5,-24.92156741649));\n#227 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#228 = PCURVE('',#153,#229);\n#229 = DEFINITIONAL_REPRESENTATION('',(#230),#256);\n#230 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#231,#232,#233,#234,#235,#236,\n    #237,#238,#239,#240,#241,#242,#243,#244,#245,#246,#247,#248,#249,\n    #250,#251,#252,#253,#254,#255),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775,\n    0.323118155001,0.484677232501,0.646236310001,0.807795387502,\n    0.969354465002,1.130913542503,1.292472620003,1.454031697503,\n    1.615590775004,1.777149852504,1.938708930004,2.100268007505,\n    2.261827085005,2.423386162505,2.584945240006,2.746504317506,\n    2.908063395007,3.069622472507,3.231181550007,3.392740627508,\n    3.554299705008),.QUASI_UNIFORM_KNOTS.);\n#231 = CARTESIAN_POINT('',(3.309040732809,-15.));\n#232 = CARTESIAN_POINT('',(3.308303875485,-15.03269491212));\n#233 = CARTESIAN_POINT('',(3.306840501179,-15.09849288457));\n#234 = CARTESIAN_POINT('',(3.304675840238,-15.19843741256));\n#235 = CARTESIAN_POINT('',(3.302540952696,-15.29965240364));\n#236 = CARTESIAN_POINT('',(3.300435234565,-15.40216155983));\n#237 = CARTESIAN_POINT('',(3.298358096311,-15.50598913612));\n#238 = CARTESIAN_POINT('',(3.296308964498,-15.61116003298));\n#239 = CARTESIAN_POINT('',(3.294287280694,-15.7176997966));\n#240 = CARTESIAN_POINT('',(3.292292501133,-15.82563464481));\n#241 = CARTESIAN_POINT('',(3.290324096205,-15.93499148723));\n#242 = CARTESIAN_POINT('',(3.288381550011,-16.04579794794));\n#243 = CARTESIAN_POINT('',(3.286464359921,-16.15808238872));\n#244 = CARTESIAN_POINT('',(3.284572036153,-16.27187393322));\n#245 = CARTESIAN_POINT('',(3.282704101374,-16.38720249214));\n#246 = CARTESIAN_POINT('',(3.280860090302,-16.5040987895));\n#247 = CARTESIAN_POINT('',(3.279039549336,-16.62259438981));\n#248 = CARTESIAN_POINT('',(3.277242036193,-16.74272172673));\n#249 = CARTESIAN_POINT('',(3.275467119556,-16.86451413191));\n#250 = CARTESIAN_POINT('',(3.273714378759,-16.98800586851));\n#251 = CARTESIAN_POINT('',(3.271983403379,-17.11323215337));\n#252 = CARTESIAN_POINT('',(3.270273793238,-17.24022922767));\n#253 = CARTESIAN_POINT('',(3.268585156938,-17.369034253));\n#254 = CARTESIAN_POINT('',(3.26747312959,-17.45613532843));\n#255 = CARTESIAN_POINT('',(3.266920484758,-17.5));\n#256 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#257 = ADVANCED_FACE('',(#258),#272,.F.);\n#258 = FACE_BOUND('',#259,.F.);\n#259 = EDGE_LOOP('',(#260,#290,#335,#425,#515));\n#260 = ORIENTED_EDGE('',*,*,#261,.T.);\n#261 = EDGE_CURVE('',#262,#264,#266,.T.);\n#262 = VERTEX_POINT('',#263);\n#263 = CARTESIAN_POINT('',(-25.29321342079,-2.076297072243,2.93633));\n#264 = VERTEX_POINT('',#265);\n#265 = CARTESIAN_POINT('',(-10.50301396304,-2.076297072243,2.93633));\n#266 = SURFACE_CURVE('',#267,(#271,#283),.PCURVE_S2.);\n#267 = LINE('',#268,#269);\n#268 = CARTESIAN_POINT('',(-32.89811369191,-2.076297072243,2.93633));\n#269 = VECTOR('',#270,1.);\n#270 = DIRECTION('',(1.,0.E+000,0.E+000));\n#271 = PCURVE('',#272,#277);\n#272 = PLANE('',#273);\n#273 = AXIS2_PLACEMENT_3D('',#274,#275,#276);\n#274 = CARTESIAN_POINT('',(-32.89811369191,-2.076297072243,7.93633));\n#275 = DIRECTION('',(0.E+000,-1.,0.E+000));\n#276 = DIRECTION('',(0.E+000,0.E+000,-1.));\n#277 = DEFINITIONAL_REPRESENTATION('',(#278),#282);\n#278 = LINE('',#279,#280);\n#279 = CARTESIAN_POINT('',(5.,0.E+000));\n#280 = VECTOR('',#281,1.);\n#281 = DIRECTION('',(0.E+000,1.));\n#282 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#283 = PCURVE('',#203,#284);\n#284 = DEFINITIONAL_REPRESENTATION('',(#285),#289);\n#285 = LINE('',#286,#287);\n#286 = CARTESIAN_POINT('',(-30.,2.5));\n#287 = VECTOR('',#288,1.);\n#288 = DIRECTION('',(1.,0.E+000));\n#289 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#290 = ORIENTED_EDGE('',*,*,#291,.T.);\n#291 = EDGE_CURVE('',#264,#292,#294,.T.);\n#292 = VERTEX_POINT('',#293);\n#293 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633));\n#294 = SURFACE_CURVE('',#295,(#299,#306),.PCURVE_S2.);\n#295 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#296,#297,#298),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075051,1.)) REPRESENTATION_ITEM('') );\n#296 = CARTESIAN_POINT('',(-10.50301396304,-2.076297072243,2.93633));\n#297 = CARTESIAN_POINT('',(-9.420242096928,-2.076297072243,\n    4.003957457804));\n#298 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633));\n#299 = PCURVE('',#272,#300);\n#300 = DEFINITIONAL_REPRESENTATION('',(#301),#305);\n#301 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#302,#303,#304),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075051,1.)) REPRESENTATION_ITEM('') );\n#302 = CARTESIAN_POINT('',(5.,22.395099728875));\n#303 = CARTESIAN_POINT('',(3.932372542196,23.477871594989));\n#304 = CARTESIAN_POINT('',(2.5,24.921567416492));\n#305 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#306 = PCURVE('',#153,#307);\n#307 = DEFINITIONAL_REPRESENTATION('',(#308),#334);\n#308 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#309,#310,#311,#312,#313,#314,\n    #315,#316,#317,#318,#319,#320,#321,#322,#323,#324,#325,#326,#327,\n    #328,#329,#330,#331,#332,#333),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775,\n    0.323118155001,0.484677232501,0.646236310001,0.807795387502,\n    0.969354465002,1.130913542503,1.292472620003,1.454031697503,\n    1.615590775004,1.777149852504,1.938708930004,2.100268007505,\n    2.261827085005,2.423386162505,2.584945240006,2.746504317506,\n    2.908063395007,3.069622472507,3.231181550007,3.392740627508,\n    3.554299705008),.QUASI_UNIFORM_KNOTS.);\n#309 = CARTESIAN_POINT('',(0.16744807922,-15.));\n#310 = CARTESIAN_POINT('',(0.166711221896,-15.03269491212));\n#311 = CARTESIAN_POINT('',(0.16524784759,-15.09849288457));\n#312 = CARTESIAN_POINT('',(0.163083186648,-15.19843741256));\n#313 = CARTESIAN_POINT('',(0.160948299106,-15.29965240364));\n#314 = CARTESIAN_POINT('',(0.158842580975,-15.40216155983));\n#315 = CARTESIAN_POINT('',(0.156765442722,-15.50598913612));\n#316 = CARTESIAN_POINT('',(0.154716310909,-15.61116003298));\n#317 = CARTESIAN_POINT('',(0.152694627104,-15.7176997966));\n#318 = CARTESIAN_POINT('',(0.150699847543,-15.82563464481));\n#319 = CARTESIAN_POINT('',(0.148731442616,-15.93499148723));\n#320 = CARTESIAN_POINT('',(0.146788896422,-16.04579794794));\n#321 = CARTESIAN_POINT('',(0.144871706331,-16.15808238872));\n#322 = CARTESIAN_POINT('',(0.142979382563,-16.27187393322));\n#323 = CARTESIAN_POINT('',(0.141111447784,-16.38720249214));\n#324 = CARTESIAN_POINT('',(0.139267436712,-16.5040987895));\n#325 = CARTESIAN_POINT('',(0.137446895746,-16.62259438981));\n#326 = CARTESIAN_POINT('',(0.135649382603,-16.74272172673));\n#327 = CARTESIAN_POINT('',(0.133874465967,-16.86451413191));\n#328 = CARTESIAN_POINT('',(0.132121725169,-16.98800586851));\n#329 = CARTESIAN_POINT('',(0.130390749789,-17.11323215337));\n#330 = CARTESIAN_POINT('',(0.128681139649,-17.24022922767));\n#331 = CARTESIAN_POINT('',(0.126992503349,-17.369034253));\n#332 = CARTESIAN_POINT('',(0.125880476001,-17.45613532843));\n#333 = CARTESIAN_POINT('',(0.125327831168,-17.5));\n#334 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#335 = ORIENTED_EDGE('',*,*,#336,.T.);\n#336 = EDGE_CURVE('',#292,#337,#339,.T.);\n#337 = VERTEX_POINT('',#338);\n#338 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243,\n    7.731450038723));\n#339 = SURFACE_CURVE('',#340,(#364,#391),.PCURVE_S2.);\n#340 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#341,#342,#343,#344,#345,#346,\n    #347,#348,#349,#350,#351,#352,#353,#354,#355,#356,#357,#358,#359,\n    #360,#361,#362,#363),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(\n    -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423,\n    -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847\n    ,8.657376849694,9.753048731913),.UNSPECIFIED.);\n#341 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633));\n#342 = CARTESIAN_POINT('',(-8.349585612678,-2.076297072243,\n    5.566853116015));\n#343 = CARTESIAN_POINT('',(-8.724216826515,-2.076297072243,\n    5.693350129935));\n#344 = CARTESIAN_POINT('',(-10.58369474811,-2.076297072243,\n    6.298546031822));\n#345 = CARTESIAN_POINT('',(-12.07643295845,-2.076297072243,\n    6.713431512354));\n#346 = CARTESIAN_POINT('',(-14.28516695545,-2.076297072243,\n    7.221607932559));\n#347 = CARTESIAN_POINT('',(-15.01497979641,-2.076297072243,\n    7.372657524772));\n#348 = CARTESIAN_POINT('',(-16.09993392183,-2.076297072243,7.56017012803\n    ));\n#349 = CARTESIAN_POINT('',(-16.45980666667,-2.076297072243,\n    7.616304970701));\n#350 = CARTESIAN_POINT('',(-17.17847405541,-2.076297072243,\n    7.702450972357));\n#351 = CARTESIAN_POINT('',(-17.53738965651,-2.076297072243,\n    7.731450038723));\n#352 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243,\n    7.731450038723));\n#353 = CARTESIAN_POINT('',(-18.25883772732,-2.076297072243,\n    7.731450038723));\n#354 = CARTESIAN_POINT('',(-18.61775332841,-2.076297072243,\n    7.702450972357));\n#355 = CARTESIAN_POINT('',(-19.33642071715,-2.076297072243,\n    7.616304970701));\n#356 = CARTESIAN_POINT('',(-19.696293462,-2.076297072243,7.56017012803)\n  );\n#357 = CARTESIAN_POINT('',(-20.78124758741,-2.076297072243,\n    7.372657524772));\n#358 = CARTESIAN_POINT('',(-21.51106042838,-2.076297072243,\n    7.221607932559));\n#359 = CARTESIAN_POINT('',(-23.71979442537,-2.076297072243,\n    6.713431512354));\n#360 = CARTESIAN_POINT('',(-25.21253263571,-2.076297072243,\n    6.298546031822));\n#361 = CARTESIAN_POINT('',(-27.07201055731,-2.076297072243,\n    5.693350129935));\n#362 = CARTESIAN_POINT('',(-27.44664177115,-2.076297072243,\n    5.566853116015));\n#363 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633));\n#364 = PCURVE('',#272,#365);\n#365 = DEFINITIONAL_REPRESENTATION('',(#366),#390);\n#366 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#367,#368,#369,#370,#371,#372,\n    #373,#374,#375,#376,#377,#378,#379,#380,#381,#382,#383,#384,#385,\n    #386,#387,#388,#389),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(\n    -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423,\n    -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847\n    ,8.657376849694,9.753048731913),.UNSPECIFIED.);\n#367 = CARTESIAN_POINT('',(2.5,24.921567416492));\n#368 = CARTESIAN_POINT('',(2.369476883985,24.548528079239));\n#369 = CARTESIAN_POINT('',(2.242979870065,24.173896865401));\n#370 = CARTESIAN_POINT('',(1.637783968178,22.314418943799));\n#371 = CARTESIAN_POINT('',(1.222898487646,20.821680733461));\n#372 = CARTESIAN_POINT('',(0.714722067441,18.612946736467));\n#373 = CARTESIAN_POINT('',(0.563672475228,17.883133895499));\n#374 = CARTESIAN_POINT('',(0.37615987197,16.798179770085));\n#375 = CARTESIAN_POINT('',(0.320025029299,16.43830702524));\n#376 = CARTESIAN_POINT('',(0.233879027643,15.719639636498));\n#377 = CARTESIAN_POINT('',(0.204879961277,15.360724035404));\n#378 = CARTESIAN_POINT('',(0.204879961277,15.));\n#379 = CARTESIAN_POINT('',(0.204879961277,14.639275964596));\n#380 = CARTESIAN_POINT('',(0.233879027643,14.280360363502));\n#381 = CARTESIAN_POINT('',(0.320025029299,13.56169297476));\n#382 = CARTESIAN_POINT('',(0.37615987197,13.201820229915));\n#383 = CARTESIAN_POINT('',(0.563672475228,12.116866104502));\n#384 = CARTESIAN_POINT('',(0.714722067441,11.387053263533));\n#385 = CARTESIAN_POINT('',(1.222898487646,9.178319266539));\n#386 = CARTESIAN_POINT('',(1.637783968178,7.685581056201));\n#387 = CARTESIAN_POINT('',(2.242979870065,5.826103134599));\n#388 = CARTESIAN_POINT('',(2.369476883985,5.451471920761));\n#389 = CARTESIAN_POINT('',(2.5,5.078432583508));\n#390 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#391 = PCURVE('',#392,#397);\n#392 = TOROIDAL_SURFACE('',#393,8.25,54.873718663856);\n#393 = AXIS2_PLACEMENT_3D('',#394,#395,#396);\n#394 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367));\n#395 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#396 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016));\n#397 = DEFINITIONAL_REPRESENTATION('',(#398),#424);\n#398 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#399,#400,#401,#402,#403,#404,\n    #405,#406,#407,#408,#409,#410,#411,#412,#413,#414,#415,#416,#417,\n    #418,#419,#420,#421,#422,#423),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(-9.753048731913,-9.309728335008,\n    -8.866407938103,-8.423087541198,-7.979767144292,-7.536446747387,\n    -7.093126350482,-6.649805953577,-6.206485556672,-5.763165159767,\n    -5.319844762862,-4.876524365957,-4.433203969051,-3.989883572146,\n    -3.546563175241,-3.103242778336,-2.659922381431,-2.216601984526,\n    -1.773281587621,-1.329961190715,-0.88664079381,-0.443320396905,\n    0.E+000),.UNSPECIFIED.);\n#399 = CARTESIAN_POINT('',(4.837716811553,-1.90983622455));\n#400 = CARTESIAN_POINT('',(4.839604775725,-1.906942595099));\n#401 = CARTESIAN_POINT('',(4.843552009624,-1.901155814072));\n#402 = CARTESIAN_POINT('',(4.85008011799,-1.89248391648));\n#403 = CARTESIAN_POINT('',(4.857304013494,-1.883824473771));\n#404 = CARTESIAN_POINT('',(4.865329065086,-1.875190974748));\n#405 = CARTESIAN_POINT('',(4.874291695205,-1.866586665031));\n#406 = CARTESIAN_POINT('',(4.884359963883,-1.858016637247));\n#407 = CARTESIAN_POINT('',(4.895744266443,-1.849486074495));\n#408 = CARTESIAN_POINT('',(4.908711029087,-1.841000912302));\n#409 = CARTESIAN_POINT('',(4.923602358169,-1.832567946629));\n#410 = CARTESIAN_POINT('',(4.940864443041,-1.824195173617));\n#411 = CARTESIAN_POINT('',(4.961088750932,-1.815892420907));\n#412 = CARTESIAN_POINT('',(4.985076367501,-1.807671623483));\n#413 = CARTESIAN_POINT('',(5.013928347127,-1.799549911442));\n#414 = CARTESIAN_POINT('',(5.04918467399,-1.79155284086));\n#415 = CARTESIAN_POINT('',(5.09312382579,-1.783707865756));\n#416 = CARTESIAN_POINT('',(5.149132632791,-1.776058763789));\n#417 = CARTESIAN_POINT('',(5.222468198,-1.768674045956));\n#418 = CARTESIAN_POINT('',(5.321227440292,-1.761668014571));\n#419 = CARTESIAN_POINT('',(5.458819159968,-1.755241122705));\n#420 = CARTESIAN_POINT('',(5.653461471425,-1.749741310524));\n#421 = CARTESIAN_POINT('',(5.932480703933,-1.745805524459));\n#422 = CARTESIAN_POINT('',(6.160197445577,-1.744780737041));\n#423 = CARTESIAN_POINT('',(6.28318530718,-1.744797796227));\n#424 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#425 = ORIENTED_EDGE('',*,*,#426,.T.);\n#426 = EDGE_CURVE('',#337,#427,#429,.T.);\n#427 = VERTEX_POINT('',#428);\n#428 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633));\n#429 = SURFACE_CURVE('',#430,(#454,#481),.PCURVE_S2.);\n#430 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#431,#432,#433,#434,#435,#436,\n    #437,#438,#439,#440,#441,#442,#443,#444,#445,#446,#447,#448,#449,\n    #450,#451,#452,#453),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(\n    -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423,\n    -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847\n    ,8.657376849694,9.753048731913),.UNSPECIFIED.);\n#431 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633));\n#432 = CARTESIAN_POINT('',(-8.349585612678,-2.076297072243,\n    5.566853116015));\n#433 = CARTESIAN_POINT('',(-8.724216826515,-2.076297072243,\n    5.693350129935));\n#434 = CARTESIAN_POINT('',(-10.58369474811,-2.076297072243,\n    6.298546031822));\n#435 = CARTESIAN_POINT('',(-12.07643295845,-2.076297072243,\n    6.713431512354));\n#436 = CARTESIAN_POINT('',(-14.28516695545,-2.076297072243,\n    7.221607932559));\n#437 = CARTESIAN_POINT('',(-15.01497979641,-2.076297072243,\n    7.372657524772));\n#438 = CARTESIAN_POINT('',(-16.09993392183,-2.076297072243,7.56017012803\n    ));\n#439 = CARTESIAN_POINT('',(-16.45980666667,-2.076297072243,\n    7.616304970701));\n#440 = CARTESIAN_POINT('',(-17.17847405541,-2.076297072243,\n    7.702450972357));\n#441 = CARTESIAN_POINT('',(-17.53738965651,-2.076297072243,\n    7.731450038723));\n#442 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243,\n    7.731450038723));\n#443 = CARTESIAN_POINT('',(-18.25883772732,-2.076297072243,\n    7.731450038723));\n#444 = CARTESIAN_POINT('',(-18.61775332841,-2.076297072243,\n    7.702450972357));\n#445 = CARTESIAN_POINT('',(-19.33642071715,-2.076297072243,\n    7.616304970701));\n#446 = CARTESIAN_POINT('',(-19.696293462,-2.076297072243,7.56017012803)\n  );\n#447 = CARTESIAN_POINT('',(-20.78124758741,-2.076297072243,\n    7.372657524772));\n#448 = CARTESIAN_POINT('',(-21.51106042838,-2.076297072243,\n    7.221607932559));\n#449 = CARTESIAN_POINT('',(-23.71979442537,-2.076297072243,\n    6.713431512354));\n#450 = CARTESIAN_POINT('',(-25.21253263571,-2.076297072243,\n    6.298546031822));\n#451 = CARTESIAN_POINT('',(-27.07201055731,-2.076297072243,\n    5.693350129935));\n#452 = CARTESIAN_POINT('',(-27.44664177115,-2.076297072243,\n    5.566853116015));\n#453 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633));\n#454 = PCURVE('',#272,#455);\n#455 = DEFINITIONAL_REPRESENTATION('',(#456),#480);\n#456 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#457,#458,#459,#460,#461,#462,\n    #463,#464,#465,#466,#467,#468,#469,#470,#471,#472,#473,#474,#475,\n    #476,#477,#478,#479),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(\n    -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423,\n    -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847\n    ,8.657376849694,9.753048731913),.UNSPECIFIED.);\n#457 = CARTESIAN_POINT('',(2.5,24.921567416492));\n#458 = CARTESIAN_POINT('',(2.369476883985,24.548528079239));\n#459 = CARTESIAN_POINT('',(2.242979870065,24.173896865401));\n#460 = CARTESIAN_POINT('',(1.637783968178,22.314418943799));\n#461 = CARTESIAN_POINT('',(1.222898487646,20.821680733461));\n#462 = CARTESIAN_POINT('',(0.714722067441,18.612946736467));\n#463 = CARTESIAN_POINT('',(0.563672475228,17.883133895499));\n#464 = CARTESIAN_POINT('',(0.37615987197,16.798179770085));\n#465 = CARTESIAN_POINT('',(0.320025029299,16.43830702524));\n#466 = CARTESIAN_POINT('',(0.233879027643,15.719639636498));\n#467 = CARTESIAN_POINT('',(0.204879961277,15.360724035404));\n#468 = CARTESIAN_POINT('',(0.204879961277,15.));\n#469 = CARTESIAN_POINT('',(0.204879961277,14.639275964596));\n#470 = CARTESIAN_POINT('',(0.233879027643,14.280360363502));\n#471 = CARTESIAN_POINT('',(0.320025029299,13.56169297476));\n#472 = CARTESIAN_POINT('',(0.37615987197,13.201820229915));\n#473 = CARTESIAN_POINT('',(0.563672475228,12.116866104502));\n#474 = CARTESIAN_POINT('',(0.714722067441,11.387053263533));\n#475 = CARTESIAN_POINT('',(1.222898487646,9.178319266539));\n#476 = CARTESIAN_POINT('',(1.637783968178,7.685581056201));\n#477 = CARTESIAN_POINT('',(2.242979870065,5.826103134599));\n#478 = CARTESIAN_POINT('',(2.369476883985,5.451471920761));\n#479 = CARTESIAN_POINT('',(2.5,5.078432583508));\n#480 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#481 = PCURVE('',#482,#487);\n#482 = TOROIDAL_SURFACE('',#483,8.25,54.873718663856);\n#483 = AXIS2_PLACEMENT_3D('',#484,#485,#486);\n#484 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367));\n#485 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#486 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016));\n#487 = DEFINITIONAL_REPRESENTATION('',(#488),#514);\n#488 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#489,#490,#491,#492,#493,#494,\n    #495,#496,#497,#498,#499,#500,#501,#502,#503,#504,#505,#506,#507,\n    #508,#509,#510,#511,#512,#513),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.443320396905,\n    0.88664079381,1.329961190715,1.773281587621,2.216601984526,\n    2.659922381431,3.103242778336,3.546563175241,3.989883572146,\n    4.433203969051,4.876524365957,5.319844762862,5.763165159767,\n    6.206485556672,6.649805953577,7.093126350482,7.536446747387,\n    7.979767144292,8.423087541198,8.866407938103,9.309728335008,\n    9.753048731913),.QUASI_UNIFORM_KNOTS.);\n#489 = CARTESIAN_POINT('',(0.E+000,-1.744797796227));\n#490 = CARTESIAN_POINT('',(0.122987861602,-1.744780737041));\n#491 = CARTESIAN_POINT('',(0.350704603246,-1.745805524459));\n#492 = CARTESIAN_POINT('',(0.629723835754,-1.749741310524));\n#493 = CARTESIAN_POINT('',(0.824366147211,-1.755241122705));\n#494 = CARTESIAN_POINT('',(0.961957866888,-1.761668014571));\n#495 = CARTESIAN_POINT('',(1.06071710918,-1.768674045956));\n#496 = CARTESIAN_POINT('',(1.134052674389,-1.776058763789));\n#497 = CARTESIAN_POINT('',(1.190061481389,-1.783707865756));\n#498 = CARTESIAN_POINT('',(1.23400063319,-1.79155284086));\n#499 = CARTESIAN_POINT('',(1.269256960052,-1.799549911442));\n#500 = CARTESIAN_POINT('',(1.298108939679,-1.807671623483));\n#501 = CARTESIAN_POINT('',(1.322096556248,-1.815892420907));\n#502 = CARTESIAN_POINT('',(1.342320864139,-1.824195173617));\n#503 = CARTESIAN_POINT('',(1.359582949011,-1.832567946629));\n#504 = CARTESIAN_POINT('',(1.374474278092,-1.841000912302));\n#505 = CARTESIAN_POINT('',(1.387441040737,-1.849486074495));\n#506 = CARTESIAN_POINT('',(1.398825343297,-1.858016637247));\n#507 = CARTESIAN_POINT('',(1.408893611974,-1.866586665031));\n#508 = CARTESIAN_POINT('',(1.417856242094,-1.875190974748));\n#509 = CARTESIAN_POINT('',(1.425881293685,-1.883824473771));\n#510 = CARTESIAN_POINT('',(1.43310518919,-1.89248391648));\n#511 = CARTESIAN_POINT('',(1.439633297555,-1.901155814072));\n#512 = CARTESIAN_POINT('',(1.443580531454,-1.906942595099));\n#513 = CARTESIAN_POINT('',(1.445468495627,-1.90983622455));\n#514 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#515 = ORIENTED_EDGE('',*,*,#516,.T.);\n#516 = EDGE_CURVE('',#427,#262,#517,.T.);\n#517 = SURFACE_CURVE('',#518,(#522,#529),.PCURVE_S2.);\n#518 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#519,#520,#521),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075051,1.)) REPRESENTATION_ITEM('') );\n#519 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633));\n#520 = CARTESIAN_POINT('',(-26.3759852869,-2.076297072243,4.003957457804\n    ));\n#521 = CARTESIAN_POINT('',(-25.29321342079,-2.076297072243,2.93633));\n#522 = PCURVE('',#272,#523);\n#523 = DEFINITIONAL_REPRESENTATION('',(#524),#528);\n#524 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#525,#526,#527),\n.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000,\n3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,\n1.010587075051,1.)) REPRESENTATION_ITEM('') );\n#525 = CARTESIAN_POINT('',(2.5,5.078432583508));\n#526 = CARTESIAN_POINT('',(3.932372542196,6.522128405011));\n#527 = CARTESIAN_POINT('',(5.,7.604900271125));\n#528 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#529 = PCURVE('',#153,#530);\n#530 = DEFINITIONAL_REPRESENTATION('',(#531),#557);\n#531 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#532,#533,#534,#535,#536,#537,\n    #538,#539,#540,#541,#542,#543,#544,#545,#546,#547,#548,#549,#550,\n    #551,#552,#553,#554,#555,#556),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775,\n    0.323118155001,0.484677232501,0.646236310001,0.807795387502,\n    0.969354465002,1.130913542503,1.292472620003,1.454031697503,\n    1.615590775004,1.777149852504,1.938708930004,2.100268007505,\n    2.261827085005,2.423386162505,2.584945240006,2.746504317506,\n    2.908063395007,3.069622472507,3.231181550007,3.392740627508,\n    3.554299705008),.QUASI_UNIFORM_KNOTS.);\n#532 = CARTESIAN_POINT('',(3.016264822422,-17.5));\n#533 = CARTESIAN_POINT('',(3.015712177589,-17.45613532843));\n#534 = CARTESIAN_POINT('',(3.014600150241,-17.369034253));\n#535 = CARTESIAN_POINT('',(3.012911513941,-17.24022922767));\n#536 = CARTESIAN_POINT('',(3.011201903801,-17.11323215337));\n#537 = CARTESIAN_POINT('',(3.00947092842,-16.98800586851));\n#538 = CARTESIAN_POINT('',(3.007718187623,-16.86451413191));\n#539 = CARTESIAN_POINT('',(3.005943270986,-16.74272172673));\n#540 = CARTESIAN_POINT('',(3.004145757844,-16.62259438981));\n#541 = CARTESIAN_POINT('',(3.002325216878,-16.5040987895));\n#542 = CARTESIAN_POINT('',(3.000481205806,-16.38720249214));\n#543 = CARTESIAN_POINT('',(2.998613271026,-16.27187393322));\n#544 = CARTESIAN_POINT('',(2.996720947259,-16.15808238872));\n#545 = CARTESIAN_POINT('',(2.994803757168,-16.04579794794));\n#546 = CARTESIAN_POINT('',(2.992861210974,-15.93499148723));\n#547 = CARTESIAN_POINT('',(2.990892806047,-15.82563464481));\n#548 = CARTESIAN_POINT('',(2.988898026486,-15.7176997966));\n#549 = CARTESIAN_POINT('',(2.986876342681,-15.61116003298));\n#550 = CARTESIAN_POINT('',(2.984827210868,-15.50598913612));\n#551 = CARTESIAN_POINT('',(2.982750072614,-15.40216155983));\n#552 = CARTESIAN_POINT('',(2.980644354484,-15.29965240364));\n#553 = CARTESIAN_POINT('',(2.978509466942,-15.19843741256));\n#554 = CARTESIAN_POINT('',(2.976344806,-15.09849288457));\n#555 = CARTESIAN_POINT('',(2.974881431694,-15.03269491212));\n#556 = CARTESIAN_POINT('',(2.97414457437,-15.));\n#557 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#558 = ADVANCED_FACE('',(#559),#203,.F.);\n#559 = FACE_BOUND('',#560,.F.);\n#560 = EDGE_LOOP('',(#561,#562,#612,#660,#661));\n#561 = ORIENTED_EDGE('',*,*,#187,.F.);\n#562 = ORIENTED_EDGE('',*,*,#563,.T.);\n#563 = EDGE_CURVE('',#138,#564,#566,.T.);\n#564 = VERTEX_POINT('',#565);\n#565 = CARTESIAN_POINT('',(-10.39811369191,-0.826297072243,2.93633));\n#566 = SURFACE_CURVE('',#567,(#572,#583),.PCURVE_S2.);\n#567 = CIRCLE('',#568,7.5);\n#568 = AXIS2_PLACEMENT_3D('',#569,#570,#571);\n#569 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633));\n#570 = DIRECTION('',(0.E+000,0.E+000,-1.));\n#571 = DIRECTION('',(1.,0.E+000,0.E+000));\n#572 = PCURVE('',#203,#573);\n#573 = DEFINITIONAL_REPRESENTATION('',(#574),#582);\n#574 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#575,#576,#577,#578,#579,#580\n,#581),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),(\n    -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718,\n8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() \nRATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM('\n') );\n#575 = CARTESIAN_POINT('',(-7.5,1.25));\n#576 = CARTESIAN_POINT('',(-7.5,14.240381056767));\n#577 = CARTESIAN_POINT('',(-18.75,7.745190528383));\n#578 = CARTESIAN_POINT('',(-30.,1.25));\n#579 = CARTESIAN_POINT('',(-18.75,-5.245190528383));\n#580 = CARTESIAN_POINT('',(-7.5,-11.74038105676));\n#581 = CARTESIAN_POINT('',(-7.5,1.25));\n#582 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#583 = PCURVE('',#153,#584);\n#584 = DEFINITIONAL_REPRESENTATION('',(#585),#611);\n#585 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#586,#587,#588,#589,#590,#591,\n    #592,#593,#594,#595,#596,#597,#598,#599,#600,#601,#602,#603,#604,\n    #605,#606,#607,#608,#609,#610),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(6.11573722796,6.123348504288,\n    6.130959780616,6.138571056944,6.146182333273,6.153793609601,\n    6.161404885929,6.169016162257,6.176627438585,6.184238714913,\n    6.191849991242,6.19946126757,6.207072543898,6.214683820226,\n    6.222295096554,6.229906372882,6.237517649211,6.245128925539,\n    6.252740201867,6.260351478195,6.267962754523,6.275574030851,\n    6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#586 = CARTESIAN_POINT('',(6.11573722796,-15.));\n#587 = CARTESIAN_POINT('',(6.118274320069,-15.));\n#588 = CARTESIAN_POINT('',(6.123348504288,-15.));\n#589 = CARTESIAN_POINT('',(6.130959780616,-15.));\n#590 = CARTESIAN_POINT('',(6.138571056944,-15.));\n#591 = CARTESIAN_POINT('',(6.146182333273,-15.));\n#592 = CARTESIAN_POINT('',(6.153793609601,-15.));\n#593 = CARTESIAN_POINT('',(6.161404885929,-15.));\n#594 = CARTESIAN_POINT('',(6.169016162257,-15.));\n#595 = CARTESIAN_POINT('',(6.176627438585,-15.));\n#596 = CARTESIAN_POINT('',(6.184238714913,-15.));\n#597 = CARTESIAN_POINT('',(6.191849991242,-15.));\n#598 = CARTESIAN_POINT('',(6.19946126757,-15.));\n#599 = CARTESIAN_POINT('',(6.207072543898,-15.));\n#600 = CARTESIAN_POINT('',(6.214683820226,-15.));\n#601 = CARTESIAN_POINT('',(6.222295096554,-15.));\n#602 = CARTESIAN_POINT('',(6.229906372882,-15.));\n#603 = CARTESIAN_POINT('',(6.237517649211,-15.));\n#604 = CARTESIAN_POINT('',(6.245128925539,-15.));\n#605 = CARTESIAN_POINT('',(6.252740201867,-15.));\n#606 = CARTESIAN_POINT('',(6.260351478195,-15.));\n#607 = CARTESIAN_POINT('',(6.267962754523,-15.));\n#608 = CARTESIAN_POINT('',(6.275574030851,-15.));\n#609 = CARTESIAN_POINT('',(6.28064821507,-15.));\n#610 = CARTESIAN_POINT('',(6.28318530718,-15.));\n#611 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#612 = ORIENTED_EDGE('',*,*,#613,.T.);\n#613 = EDGE_CURVE('',#564,#264,#614,.T.);\n#614 = SURFACE_CURVE('',#615,(#620,#631),.PCURVE_S2.);\n#615 = CIRCLE('',#616,7.5);\n#616 = AXIS2_PLACEMENT_3D('',#617,#618,#619);\n#617 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633));\n#618 = DIRECTION('',(0.E+000,0.E+000,-1.));\n#619 = DIRECTION('',(1.,0.E+000,0.E+000));\n#620 = PCURVE('',#203,#621);\n#621 = DEFINITIONAL_REPRESENTATION('',(#622),#630);\n#622 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#623,#624,#625,#626,#627,#628\n,#629),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),(\n    -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718,\n8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() \nRATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM('\n') );\n#623 = CARTESIAN_POINT('',(-7.5,1.25));\n#624 = CARTESIAN_POINT('',(-7.5,14.240381056767));\n#625 = CARTESIAN_POINT('',(-18.75,7.745190528383));\n#626 = CARTESIAN_POINT('',(-30.,1.25));\n#627 = CARTESIAN_POINT('',(-18.75,-5.245190528383));\n#628 = CARTESIAN_POINT('',(-7.5,-11.74038105676));\n#629 = CARTESIAN_POINT('',(-7.5,1.25));\n#630 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#631 = PCURVE('',#153,#632);\n#632 = DEFINITIONAL_REPRESENTATION('',(#633),#659);\n#633 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#634,#635,#636,#637,#638,#639,\n    #640,#641,#642,#643,#644,#645,#646,#647,#648,#649,#650,#651,#652,\n    #653,#654,#655,#656,#657,#658),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(8.881784197001E-016,\n    7.611276328169E-003,1.522255265634E-002,2.28338289845E-002,\n    3.044510531267E-002,3.805638164084E-002,4.566765796901E-002,\n    5.327893429717E-002,6.089021062534E-002,6.850148695351E-002,\n    7.611276328168E-002,8.372403960985E-002,9.133531593801E-002,\n    9.894659226618E-002,0.106557868594,0.114169144923,0.121780421251,\n    0.129391697579,0.137002973907,0.144614250235,0.152225526563,\n    0.159836802892,0.16744807922),.QUASI_UNIFORM_KNOTS.);\n#634 = CARTESIAN_POINT('',(1.021405182655E-015,-15.));\n#635 = CARTESIAN_POINT('',(2.53709210939E-003,-15.));\n#636 = CARTESIAN_POINT('',(7.611276328169E-003,-15.));\n#637 = CARTESIAN_POINT('',(1.522255265634E-002,-15.));\n#638 = CARTESIAN_POINT('',(2.28338289845E-002,-15.));\n#639 = CARTESIAN_POINT('',(3.044510531267E-002,-15.));\n#640 = CARTESIAN_POINT('',(3.805638164084E-002,-15.));\n#641 = CARTESIAN_POINT('',(4.566765796901E-002,-15.));\n#642 = CARTESIAN_POINT('',(5.327893429717E-002,-15.));\n#643 = CARTESIAN_POINT('',(6.089021062534E-002,-15.));\n#644 = CARTESIAN_POINT('',(6.850148695351E-002,-15.));\n#645 = CARTESIAN_POINT('',(7.611276328168E-002,-15.));\n#646 = CARTESIAN_POINT('',(8.372403960985E-002,-15.));\n#647 = CARTESIAN_POINT('',(9.133531593801E-002,-15.));\n#648 = CARTESIAN_POINT('',(9.894659226618E-002,-15.));\n#649 = CARTESIAN_POINT('',(0.106557868594,-15.));\n#650 = CARTESIAN_POINT('',(0.114169144923,-15.));\n#651 = CARTESIAN_POINT('',(0.121780421251,-15.));\n#652 = CARTESIAN_POINT('',(0.129391697579,-15.));\n#653 = CARTESIAN_POINT('',(0.137002973907,-15.));\n#654 = CARTESIAN_POINT('',(0.144614250235,-15.));\n#655 = CARTESIAN_POINT('',(0.152225526563,-15.));\n#656 = CARTESIAN_POINT('',(0.159836802892,-15.));\n#657 = CARTESIAN_POINT('',(0.16491098711,-15.));\n#658 = CARTESIAN_POINT('',(0.16744807922,-15.));\n#659 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#660 = ORIENTED_EDGE('',*,*,#261,.F.);\n#661 = ORIENTED_EDGE('',*,*,#662,.T.);\n#662 = EDGE_CURVE('',#262,#188,#663,.T.);\n#663 = SURFACE_CURVE('',#664,(#669,#680),.PCURVE_S2.);\n#664 = CIRCLE('',#665,7.5);\n#665 = AXIS2_PLACEMENT_3D('',#666,#667,#668);\n#666 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633));\n#667 = DIRECTION('',(0.E+000,0.E+000,-1.));\n#668 = DIRECTION('',(1.,0.E+000,0.E+000));\n#669 = PCURVE('',#203,#670);\n#670 = DEFINITIONAL_REPRESENTATION('',(#671),#679);\n#671 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#672,#673,#674,#675,#676,#677\n,#678),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),(\n    -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718,\n8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() \nRATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM('\n') );\n#672 = CARTESIAN_POINT('',(-7.5,1.25));\n#673 = CARTESIAN_POINT('',(-7.5,14.240381056767));\n#674 = CARTESIAN_POINT('',(-18.75,7.745190528383));\n#675 = CARTESIAN_POINT('',(-30.,1.25));\n#676 = CARTESIAN_POINT('',(-18.75,-5.245190528383));\n#677 = CARTESIAN_POINT('',(-7.5,-11.74038105676));\n#678 = CARTESIAN_POINT('',(-7.5,1.25));\n#679 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#680 = PCURVE('',#153,#681);\n#681 = DEFINITIONAL_REPRESENTATION('',(#682),#708);\n#682 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#683,#684,#685,#686,#687,#688,\n    #689,#690,#691,#692,#693,#694,#695,#696,#697,#698,#699,#700,#701,\n    #702,#703,#704,#705,#706,#707),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(2.97414457437,2.989367127026,\n    3.004589679683,3.019812232339,3.035034784995,3.050257337652,\n    3.065479890308,3.080702442964,3.095924995621,3.111147548277,\n    3.126370100933,3.14159265359,3.156815206246,3.172037758902,\n    3.187260311559,3.202482864215,3.217705416871,3.232927969528,\n    3.248150522184,3.26337307484,3.278595627497,3.293818180153,\n    3.309040732809),.QUASI_UNIFORM_KNOTS.);\n#683 = CARTESIAN_POINT('',(2.97414457437,-15.));\n#684 = CARTESIAN_POINT('',(2.979218758589,-15.));\n#685 = CARTESIAN_POINT('',(2.989367127026,-15.));\n#686 = CARTESIAN_POINT('',(3.004589679683,-15.));\n#687 = CARTESIAN_POINT('',(3.019812232339,-15.));\n#688 = CARTESIAN_POINT('',(3.035034784995,-15.));\n#689 = CARTESIAN_POINT('',(3.050257337652,-15.));\n#690 = CARTESIAN_POINT('',(3.065479890308,-15.));\n#691 = CARTESIAN_POINT('',(3.080702442964,-15.));\n#692 = CARTESIAN_POINT('',(3.095924995621,-15.));\n#693 = CARTESIAN_POINT('',(3.111147548277,-15.));\n#694 = CARTESIAN_POINT('',(3.126370100933,-15.));\n#695 = CARTESIAN_POINT('',(3.14159265359,-15.));\n#696 = CARTESIAN_POINT('',(3.156815206246,-15.));\n#697 = CARTESIAN_POINT('',(3.172037758902,-15.));\n#698 = CARTESIAN_POINT('',(3.187260311559,-15.));\n#699 = CARTESIAN_POINT('',(3.202482864215,-15.));\n#700 = CARTESIAN_POINT('',(3.217705416871,-15.));\n#701 = CARTESIAN_POINT('',(3.232927969528,-15.));\n#702 = CARTESIAN_POINT('',(3.248150522184,-15.));\n#703 = CARTESIAN_POINT('',(3.26337307484,-15.));\n#704 = CARTESIAN_POINT('',(3.278595627497,-15.));\n#705 = CARTESIAN_POINT('',(3.293818180153,-15.));\n#706 = CARTESIAN_POINT('',(3.303966548591,-15.));\n#707 = CARTESIAN_POINT('',(3.309040732809,-15.));\n#708 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#709 = ADVANCED_FACE('',(#710),#482,.F.);\n#710 = FACE_BOUND('',#711,.T.);\n#711 = EDGE_LOOP('',(#712,#713,#781));\n#712 = ORIENTED_EDGE('',*,*,#426,.T.);\n#713 = ORIENTED_EDGE('',*,*,#714,.F.);\n#714 = EDGE_CURVE('',#715,#427,#717,.T.);\n#715 = VERTEX_POINT('',#716);\n#716 = CARTESIAN_POINT('',(-17.89811369191,-10.82629707224,5.43633));\n#717 = SURFACE_CURVE('',#718,(#723,#752),.PCURVE_S2.);\n#718 = CIRCLE('',#719,10.);\n#719 = AXIS2_PLACEMENT_3D('',#720,#721,#722);\n#720 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633));\n#721 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#722 = DIRECTION('',(1.,0.E+000,0.E+000));\n#723 = PCURVE('',#482,#724);\n#724 = DEFINITIONAL_REPRESENTATION('',(#725),#751);\n#725 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#726,#727,#728,#729,#730,#731,\n    #732,#733,#734,#735,#736,#737,#738,#739,#740,#741,#742,#743,#744,\n    #745,#746,#747,#748,#749,#750),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(1.570796326795,1.636499440232,\n    1.70220255367,1.767905667108,1.833608780545,1.899311893983,\n    1.96501500742,2.030718120858,2.096421234296,2.162124347733,\n    2.227827461171,2.293530574608,2.359233688046,2.424936801483,\n    2.490639914921,2.556343028359,2.622046141796,2.687749255234,\n    2.753452368671,2.819155482109,2.884858595547,2.950561708984,\n    3.016264822422),.QUASI_UNIFORM_KNOTS.);\n#726 = CARTESIAN_POINT('',(0.E+000,-1.90983622455));\n#727 = CARTESIAN_POINT('',(2.190103781253E-002,-1.90983622455));\n#728 = CARTESIAN_POINT('',(6.570311343758E-002,-1.90983622455));\n#729 = CARTESIAN_POINT('',(0.131406226875,-1.90983622455));\n#730 = CARTESIAN_POINT('',(0.197109340313,-1.90983622455));\n#731 = CARTESIAN_POINT('',(0.26281245375,-1.90983622455));\n#732 = CARTESIAN_POINT('',(0.328515567188,-1.90983622455));\n#733 = CARTESIAN_POINT('',(0.394218680625,-1.90983622455));\n#734 = CARTESIAN_POINT('',(0.459921794063,-1.90983622455));\n#735 = CARTESIAN_POINT('',(0.525624907501,-1.90983622455));\n#736 = CARTESIAN_POINT('',(0.591328020938,-1.90983622455));\n#737 = CARTESIAN_POINT('',(0.657031134376,-1.90983622455));\n#738 = CARTESIAN_POINT('',(0.722734247813,-1.90983622455));\n#739 = CARTESIAN_POINT('',(0.788437361251,-1.90983622455));\n#740 = CARTESIAN_POINT('',(0.854140474689,-1.90983622455));\n#741 = CARTESIAN_POINT('',(0.919843588126,-1.90983622455));\n#742 = CARTESIAN_POINT('',(0.985546701564,-1.90983622455));\n#743 = CARTESIAN_POINT('',(1.051249815001,-1.90983622455));\n#744 = CARTESIAN_POINT('',(1.116952928439,-1.90983622455));\n#745 = CARTESIAN_POINT('',(1.182656041876,-1.90983622455));\n#746 = CARTESIAN_POINT('',(1.248359155314,-1.90983622455));\n#747 = CARTESIAN_POINT('',(1.314062268752,-1.90983622455));\n#748 = CARTESIAN_POINT('',(1.379765382189,-1.90983622455));\n#749 = CARTESIAN_POINT('',(1.423567457814,-1.90983622455));\n#750 = CARTESIAN_POINT('',(1.445468495627,-1.90983622455));\n#751 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#752 = PCURVE('',#153,#753);\n#753 = DEFINITIONAL_REPRESENTATION('',(#754),#780);\n#754 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#755,#756,#757,#758,#759,#760,\n    #761,#762,#763,#764,#765,#766,#767,#768,#769,#770,#771,#772,#773,\n    #774,#775,#776,#777,#778,#779),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(1.570796326795,1.636499440232,\n    1.70220255367,1.767905667108,1.833608780545,1.899311893983,\n    1.96501500742,2.030718120858,2.096421234296,2.162124347733,\n    2.227827461171,2.293530574608,2.359233688046,2.424936801483,\n    2.490639914921,2.556343028359,2.622046141796,2.687749255234,\n    2.753452368671,2.819155482109,2.884858595547,2.950561708984,\n    3.016264822422),.QUASI_UNIFORM_KNOTS.);\n#755 = CARTESIAN_POINT('',(1.570796326795,-17.5));\n#756 = CARTESIAN_POINT('',(1.592697364607,-17.5));\n#757 = CARTESIAN_POINT('',(1.636499440232,-17.5));\n#758 = CARTESIAN_POINT('',(1.70220255367,-17.5));\n#759 = CARTESIAN_POINT('',(1.767905667108,-17.5));\n#760 = CARTESIAN_POINT('',(1.833608780545,-17.5));\n#761 = CARTESIAN_POINT('',(1.899311893983,-17.5));\n#762 = CARTESIAN_POINT('',(1.96501500742,-17.5));\n#763 = CARTESIAN_POINT('',(2.030718120858,-17.5));\n#764 = CARTESIAN_POINT('',(2.096421234296,-17.5));\n#765 = CARTESIAN_POINT('',(2.162124347733,-17.5));\n#766 = CARTESIAN_POINT('',(2.227827461171,-17.5));\n#767 = CARTESIAN_POINT('',(2.293530574608,-17.5));\n#768 = CARTESIAN_POINT('',(2.359233688046,-17.5));\n#769 = CARTESIAN_POINT('',(2.424936801483,-17.5));\n#770 = CARTESIAN_POINT('',(2.490639914921,-17.5));\n#771 = CARTESIAN_POINT('',(2.556343028359,-17.5));\n#772 = CARTESIAN_POINT('',(2.622046141796,-17.5));\n#773 = CARTESIAN_POINT('',(2.687749255234,-17.5));\n#774 = CARTESIAN_POINT('',(2.753452368671,-17.5));\n#775 = CARTESIAN_POINT('',(2.819155482109,-17.5));\n#776 = CARTESIAN_POINT('',(2.884858595547,-17.5));\n#777 = CARTESIAN_POINT('',(2.950561708984,-17.5));\n#778 = CARTESIAN_POINT('',(2.994363784609,-17.5));\n#779 = CARTESIAN_POINT('',(3.016264822422,-17.5));\n#780 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#781 = ORIENTED_EDGE('',*,*,#782,.F.);\n#782 = EDGE_CURVE('',#337,#715,#783,.T.);\n#783 = SURFACE_CURVE('',#784,(#789,#796),.PCURVE_S2.);\n#784 = CIRCLE('',#785,54.873718663856);\n#785 = AXIS2_PLACEMENT_3D('',#786,#787,#788);\n#786 = CARTESIAN_POINT('',(-17.89811369191,7.423702927757,-46.31367));\n#787 = DIRECTION('',(1.,0.E+000,0.E+000));\n#788 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016));\n#789 = PCURVE('',#482,#790);\n#790 = DEFINITIONAL_REPRESENTATION('',(#791),#795);\n#791 = LINE('',#792,#793);\n#792 = CARTESIAN_POINT('',(0.E+000,0.E+000));\n#793 = VECTOR('',#794,1.);\n#794 = DIRECTION('',(0.E+000,-1.));\n#795 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#796 = PCURVE('',#392,#797);\n#797 = DEFINITIONAL_REPRESENTATION('',(#798),#802);\n#798 = LINE('',#799,#800);\n#799 = CARTESIAN_POINT('',(6.28318530718,0.E+000));\n#800 = VECTOR('',#801,1.);\n#801 = DIRECTION('',(0.E+000,-1.));\n#802 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#803 = ADVANCED_FACE('',(#804),#392,.F.);\n#804 = FACE_BOUND('',#805,.T.);\n#805 = EDGE_LOOP('',(#806,#872,#873));\n#806 = ORIENTED_EDGE('',*,*,#807,.F.);\n#807 = EDGE_CURVE('',#292,#715,#808,.T.);\n#808 = SURFACE_CURVE('',#809,(#814,#843),.PCURVE_S2.);\n#809 = CIRCLE('',#810,10.);\n#810 = AXIS2_PLACEMENT_3D('',#811,#812,#813);\n#811 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633));\n#812 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#813 = DIRECTION('',(1.,0.E+000,0.E+000));\n#814 = PCURVE('',#392,#815);\n#815 = DEFINITIONAL_REPRESENTATION('',(#816),#842);\n#816 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#817,#818,#819,#820,#821,#822,\n    #823,#824,#825,#826,#827,#828,#829,#830,#831,#832,#833,#834,#835,\n    #836,#837,#838,#839,#840,#841),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.125327831168,0.191030944606,\n    0.256734058043,0.322437171481,0.388140284918,0.453843398356,\n    0.519546511794,0.585249625231,0.650952738669,0.716655852106,\n    0.782358965544,0.848062078981,0.913765192419,0.979468305857,\n    1.045171419294,1.110874532732,1.176577646169,1.242280759607,\n    1.307983873045,1.373686986482,1.43939009992,1.505093213357,\n    1.570796326795),.QUASI_UNIFORM_KNOTS.);\n#817 = CARTESIAN_POINT('',(4.837716811553,-1.90983622455));\n#818 = CARTESIAN_POINT('',(4.859617849365,-1.90983622455));\n#819 = CARTESIAN_POINT('',(4.90341992499,-1.90983622455));\n#820 = CARTESIAN_POINT('',(4.969123038428,-1.90983622455));\n#821 = CARTESIAN_POINT('',(5.034826151866,-1.90983622455));\n#822 = CARTESIAN_POINT('',(5.100529265303,-1.90983622455));\n#823 = CARTESIAN_POINT('',(5.166232378741,-1.90983622455));\n#824 = CARTESIAN_POINT('',(5.231935492178,-1.90983622455));\n#825 = CARTESIAN_POINT('',(5.297638605616,-1.90983622455));\n#826 = CARTESIAN_POINT('',(5.363341719053,-1.90983622455));\n#827 = CARTESIAN_POINT('',(5.429044832491,-1.90983622455));\n#828 = CARTESIAN_POINT('',(5.494747945929,-1.90983622455));\n#829 = CARTESIAN_POINT('',(5.560451059366,-1.90983622455));\n#830 = CARTESIAN_POINT('',(5.626154172804,-1.90983622455));\n#831 = CARTESIAN_POINT('',(5.691857286241,-1.90983622455));\n#832 = CARTESIAN_POINT('',(5.757560399679,-1.90983622455));\n#833 = CARTESIAN_POINT('',(5.823263513117,-1.90983622455));\n#834 = CARTESIAN_POINT('',(5.888966626554,-1.90983622455));\n#835 = CARTESIAN_POINT('',(5.954669739992,-1.90983622455));\n#836 = CARTESIAN_POINT('',(6.020372853429,-1.90983622455));\n#837 = CARTESIAN_POINT('',(6.086075966867,-1.90983622455));\n#838 = CARTESIAN_POINT('',(6.151779080304,-1.90983622455));\n#839 = CARTESIAN_POINT('',(6.217482193742,-1.90983622455));\n#840 = CARTESIAN_POINT('',(6.261284269367,-1.90983622455));\n#841 = CARTESIAN_POINT('',(6.28318530718,-1.90983622455));\n#842 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#843 = PCURVE('',#153,#844);\n#844 = DEFINITIONAL_REPRESENTATION('',(#845),#871);\n#845 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#846,#847,#848,#849,#850,#851,\n    #852,#853,#854,#855,#856,#857,#858,#859,#860,#861,#862,#863,#864,\n    #865,#866,#867,#868,#869,#870),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.125327831168,0.191030944606,\n    0.256734058043,0.322437171481,0.388140284918,0.453843398356,\n    0.519546511794,0.585249625231,0.650952738669,0.716655852106,\n    0.782358965544,0.848062078981,0.913765192419,0.979468305857,\n    1.045171419294,1.110874532732,1.176577646169,1.242280759607,\n    1.307983873045,1.373686986482,1.43939009992,1.505093213357,\n    1.570796326795),.QUASI_UNIFORM_KNOTS.);\n#846 = CARTESIAN_POINT('',(0.125327831168,-17.5));\n#847 = CARTESIAN_POINT('',(0.147228868981,-17.5));\n#848 = CARTESIAN_POINT('',(0.191030944606,-17.5));\n#849 = CARTESIAN_POINT('',(0.256734058043,-17.5));\n#850 = CARTESIAN_POINT('',(0.322437171481,-17.5));\n#851 = CARTESIAN_POINT('',(0.388140284918,-17.5));\n#852 = CARTESIAN_POINT('',(0.453843398356,-17.5));\n#853 = CARTESIAN_POINT('',(0.519546511794,-17.5));\n#854 = CARTESIAN_POINT('',(0.585249625231,-17.5));\n#855 = CARTESIAN_POINT('',(0.650952738669,-17.5));\n#856 = CARTESIAN_POINT('',(0.716655852106,-17.5));\n#857 = CARTESIAN_POINT('',(0.782358965544,-17.5));\n#858 = CARTESIAN_POINT('',(0.848062078981,-17.5));\n#859 = CARTESIAN_POINT('',(0.913765192419,-17.5));\n#860 = CARTESIAN_POINT('',(0.979468305857,-17.5));\n#861 = CARTESIAN_POINT('',(1.045171419294,-17.5));\n#862 = CARTESIAN_POINT('',(1.110874532732,-17.5));\n#863 = CARTESIAN_POINT('',(1.176577646169,-17.5));\n#864 = CARTESIAN_POINT('',(1.242280759607,-17.5));\n#865 = CARTESIAN_POINT('',(1.307983873045,-17.5));\n#866 = CARTESIAN_POINT('',(1.373686986482,-17.5));\n#867 = CARTESIAN_POINT('',(1.43939009992,-17.5));\n#868 = CARTESIAN_POINT('',(1.505093213357,-17.5));\n#869 = CARTESIAN_POINT('',(1.548895288982,-17.5));\n#870 = CARTESIAN_POINT('',(1.570796326795,-17.5));\n#871 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#872 = ORIENTED_EDGE('',*,*,#336,.T.);\n#873 = ORIENTED_EDGE('',*,*,#782,.T.);\n#874 = ADVANCED_FACE('',(#875),#81,.F.);\n#875 = FACE_BOUND('',#876,.T.);\n#876 = EDGE_LOOP('',(#877,#878));\n#877 = ORIENTED_EDGE('',*,*,#18,.T.);\n#878 = ORIENTED_EDGE('',*,*,#879,.F.);\n#879 = EDGE_CURVE('',#19,#21,#880,.T.);\n#880 = SURFACE_CURVE('',#881,(#886,#915),.PCURVE_S2.);\n#881 = CIRCLE('',#882,10.);\n#882 = AXIS2_PLACEMENT_3D('',#883,#884,#885);\n#883 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633));\n#884 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#885 = DIRECTION('',(1.,0.E+000,0.E+000));\n#886 = PCURVE('',#81,#887);\n#887 = DEFINITIONAL_REPRESENTATION('',(#888),#914);\n#888 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#889,#890,#891,#892,#893,#894,\n    #895,#896,#897,#898,#899,#900,#901,#902,#903,#904,#905,#906,#907,\n    #908,#909,#910,#911,#912,#913),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(3.266920484758,3.398326711633,\n    3.529732938508,3.661139165383,3.792545392259,3.923951619134,\n    4.055357846009,4.186764072884,4.318170299759,4.449576526634,\n    4.58098275351,4.712388980385,4.84379520726,4.975201434135,\n    5.10660766101,5.238013887885,5.369420114761,5.500826341636,\n    5.632232568511,5.763638795386,5.895045022261,6.026451249136,\n    6.157857476012),.QUASI_UNIFORM_KNOTS.);\n#889 = CARTESIAN_POINT('',(1.696124157963,-1.90983622455));\n#890 = CARTESIAN_POINT('',(1.739926233588,-1.90983622455));\n#891 = CARTESIAN_POINT('',(1.827530384838,-1.90983622455));\n#892 = CARTESIAN_POINT('',(1.958936611713,-1.90983622455));\n#893 = CARTESIAN_POINT('',(2.090342838588,-1.90983622455));\n#894 = CARTESIAN_POINT('',(2.221749065464,-1.90983622455));\n#895 = CARTESIAN_POINT('',(2.353155292339,-1.90983622455));\n#896 = CARTESIAN_POINT('',(2.484561519214,-1.90983622455));\n#897 = CARTESIAN_POINT('',(2.615967746089,-1.90983622455));\n#898 = CARTESIAN_POINT('',(2.747373972964,-1.90983622455));\n#899 = CARTESIAN_POINT('',(2.878780199839,-1.90983622455));\n#900 = CARTESIAN_POINT('',(3.010186426715,-1.90983622455));\n#901 = CARTESIAN_POINT('',(3.14159265359,-1.90983622455));\n#902 = CARTESIAN_POINT('',(3.272998880465,-1.90983622455));\n#903 = CARTESIAN_POINT('',(3.40440510734,-1.90983622455));\n#904 = CARTESIAN_POINT('',(3.535811334215,-1.90983622455));\n#905 = CARTESIAN_POINT('',(3.66721756109,-1.90983622455));\n#906 = CARTESIAN_POINT('',(3.798623787966,-1.90983622455));\n#907 = CARTESIAN_POINT('',(3.930030014841,-1.90983622455));\n#908 = CARTESIAN_POINT('',(4.061436241716,-1.90983622455));\n#909 = CARTESIAN_POINT('',(4.192842468591,-1.90983622455));\n#910 = CARTESIAN_POINT('',(4.324248695466,-1.90983622455));\n#911 = CARTESIAN_POINT('',(4.455654922341,-1.90983622455));\n#912 = CARTESIAN_POINT('',(4.543259073592,-1.90983622455));\n#913 = CARTESIAN_POINT('',(4.587061149217,-1.90983622455));\n#914 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#915 = PCURVE('',#153,#916);\n#916 = DEFINITIONAL_REPRESENTATION('',(#917),#943);\n#917 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#918,#919,#920,#921,#922,#923,\n    #924,#925,#926,#927,#928,#929,#930,#931,#932,#933,#934,#935,#936,\n    #937,#938,#939,#940,#941,#942),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,\n    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(3.266920484758,3.398326711633,\n    3.529732938508,3.661139165383,3.792545392259,3.923951619134,\n    4.055357846009,4.186764072884,4.318170299759,4.449576526634,\n    4.58098275351,4.712388980385,4.84379520726,4.975201434135,\n    5.10660766101,5.238013887885,5.369420114761,5.500826341636,\n    5.632232568511,5.763638795386,5.895045022261,6.026451249136,\n    6.157857476012),.QUASI_UNIFORM_KNOTS.);\n#918 = CARTESIAN_POINT('',(3.266920484758,-17.5));\n#919 = CARTESIAN_POINT('',(3.310722560383,-17.5));\n#920 = CARTESIAN_POINT('',(3.398326711633,-17.5));\n#921 = CARTESIAN_POINT('',(3.529732938508,-17.5));\n#922 = CARTESIAN_POINT('',(3.661139165383,-17.5));\n#923 = CARTESIAN_POINT('',(3.792545392259,-17.5));\n#924 = CARTESIAN_POINT('',(3.923951619134,-17.5));\n#925 = CARTESIAN_POINT('',(4.055357846009,-17.5));\n#926 = CARTESIAN_POINT('',(4.186764072884,-17.5));\n#927 = CARTESIAN_POINT('',(4.318170299759,-17.5));\n#928 = CARTESIAN_POINT('',(4.449576526634,-17.5));\n#929 = CARTESIAN_POINT('',(4.58098275351,-17.5));\n#930 = CARTESIAN_POINT('',(4.712388980385,-17.5));\n#931 = CARTESIAN_POINT('',(4.84379520726,-17.5));\n#932 = CARTESIAN_POINT('',(4.975201434135,-17.5));\n#933 = CARTESIAN_POINT('',(5.10660766101,-17.5));\n#934 = CARTESIAN_POINT('',(5.238013887885,-17.5));\n#935 = CARTESIAN_POINT('',(5.369420114761,-17.5));\n#936 = CARTESIAN_POINT('',(5.500826341636,-17.5));\n#937 = CARTESIAN_POINT('',(5.632232568511,-17.5));\n#938 = CARTESIAN_POINT('',(5.763638795386,-17.5));\n#939 = CARTESIAN_POINT('',(5.895045022261,-17.5));\n#940 = CARTESIAN_POINT('',(6.026451249136,-17.5));\n#941 = CARTESIAN_POINT('',(6.114055400386,-17.5));\n#942 = CARTESIAN_POINT('',(6.157857476012,-17.5));\n#943 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#944 = ADVANCED_FACE('',(#945),#153,.T.);\n#945 = FACE_BOUND('',#946,.T.);\n#946 = EDGE_LOOP('',(#947,#948,#949,#950,#951,#952,#953,#954,#955,#956,\n    #957,#980,#1051));\n#947 = ORIENTED_EDGE('',*,*,#613,.T.);\n#948 = ORIENTED_EDGE('',*,*,#291,.T.);\n#949 = ORIENTED_EDGE('',*,*,#807,.T.);\n#950 = ORIENTED_EDGE('',*,*,#714,.T.);\n#951 = ORIENTED_EDGE('',*,*,#516,.T.);\n#952 = ORIENTED_EDGE('',*,*,#662,.T.);\n#953 = ORIENTED_EDGE('',*,*,#215,.T.);\n#954 = ORIENTED_EDGE('',*,*,#879,.T.);\n#955 = ORIENTED_EDGE('',*,*,#137,.T.);\n#956 = ORIENTED_EDGE('',*,*,#563,.T.);\n#957 = ORIENTED_EDGE('',*,*,#958,.T.);\n#958 = EDGE_CURVE('',#564,#959,#961,.T.);\n#959 = VERTEX_POINT('',#960);\n#960 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,0.43633));\n#961 = SEAM_CURVE('',#962,(#966,#973),.PCURVE_S2.);\n#962 = LINE('',#963,#964);\n#963 = CARTESIAN_POINT('',(-25.39811369191,-0.826297072243,-12.06367));\n#964 = VECTOR('',#965,1.);\n#965 = DIRECTION('',(-0.707106781187,-2.436019915756E-016,\n    -0.707106781187));\n#966 = PCURVE('',#153,#967);\n#967 = DEFINITIONAL_REPRESENTATION('',(#968),#972);\n#968 = LINE('',#969,#970);\n#969 = CARTESIAN_POINT('',(6.28318530718,0.E+000));\n#970 = VECTOR('',#971,1.);\n#971 = DIRECTION('',(0.E+000,1.));\n#972 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#973 = PCURVE('',#153,#974);\n#974 = DEFINITIONAL_REPRESENTATION('',(#975),#979);\n#975 = LINE('',#976,#977);\n#976 = CARTESIAN_POINT('',(0.E+000,0.E+000));\n#977 = VECTOR('',#978,1.);\n#978 = DIRECTION('',(0.E+000,1.));\n#979 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#980 = ORIENTED_EDGE('',*,*,#981,.F.);\n#981 = EDGE_CURVE('',#959,#959,#982,.T.);\n#982 = SURFACE_CURVE('',#983,(#988,#1017),.PCURVE_S2.);\n#983 = CIRCLE('',#984,5.);\n#984 = AXIS2_PLACEMENT_3D('',#985,#986,#987);\n#985 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,0.43633));\n#986 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#987 = DIRECTION('',(1.,0.E+000,0.E+000));\n#988 = PCURVE('',#153,#989);\n#989 = DEFINITIONAL_REPRESENTATION('',(#990),#1016);\n#990 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#991,#992,#993,#994,#995,#996,\n    #997,#998,#999,#1000,#1001,#1002,#1003,#1004,#1005,#1006,#1007,#1008\n    ,#1009,#1010,#1011,#1012,#1013,#1014,#1015),.UNSPECIFIED.,.F.,.F.,(4\n    ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,\n    0.285599332145,0.571198664289,0.856797996434,1.142397328578,\n    1.427996660723,1.713595992867,1.999195325012,2.284794657156,\n    2.570393989301,2.855993321445,3.14159265359,3.427191985734,\n    3.712791317879,3.998390650023,4.283989982168,4.569589314312,\n    4.855188646457,5.140787978601,5.426387310746,5.711986642891,\n    5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#991 = CARTESIAN_POINT('',(1.33226762955E-016,-12.5));\n#992 = CARTESIAN_POINT('',(9.519977738151E-002,-12.5));\n#993 = CARTESIAN_POINT('',(0.285599332145,-12.5));\n#994 = CARTESIAN_POINT('',(0.571198664289,-12.5));\n#995 = CARTESIAN_POINT('',(0.856797996434,-12.5));\n#996 = CARTESIAN_POINT('',(1.142397328578,-12.5));\n#997 = CARTESIAN_POINT('',(1.427996660723,-12.5));\n#998 = CARTESIAN_POINT('',(1.713595992867,-12.5));\n#999 = CARTESIAN_POINT('',(1.999195325012,-12.5));\n#1000 = CARTESIAN_POINT('',(2.284794657156,-12.5));\n#1001 = CARTESIAN_POINT('',(2.570393989301,-12.5));\n#1002 = CARTESIAN_POINT('',(2.855993321445,-12.5));\n#1003 = CARTESIAN_POINT('',(3.14159265359,-12.5));\n#1004 = CARTESIAN_POINT('',(3.427191985734,-12.5));\n#1005 = CARTESIAN_POINT('',(3.712791317879,-12.5));\n#1006 = CARTESIAN_POINT('',(3.998390650023,-12.5));\n#1007 = CARTESIAN_POINT('',(4.283989982168,-12.5));\n#1008 = CARTESIAN_POINT('',(4.569589314312,-12.5));\n#1009 = CARTESIAN_POINT('',(4.855188646457,-12.5));\n#1010 = CARTESIAN_POINT('',(5.140787978601,-12.5));\n#1011 = CARTESIAN_POINT('',(5.426387310746,-12.5));\n#1012 = CARTESIAN_POINT('',(5.711986642891,-12.5));\n#1013 = CARTESIAN_POINT('',(5.997585975035,-12.5));\n#1014 = CARTESIAN_POINT('',(6.187985529798,-12.5));\n#1015 = CARTESIAN_POINT('',(6.28318530718,-12.5));\n#1016 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1017 = PCURVE('',#1018,#1023);\n#1018 = CYLINDRICAL_SURFACE('',#1019,5.);\n#1019 = AXIS2_PLACEMENT_3D('',#1020,#1021,#1022);\n#1020 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-16.60362));\n#1021 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1022 = DIRECTION('',(1.,0.E+000,0.E+000));\n#1023 = DEFINITIONAL_REPRESENTATION('',(#1024),#1050);\n#1024 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1025,#1026,#1027,#1028,#1029,\n    #1030,#1031,#1032,#1033,#1034,#1035,#1036,#1037,#1038,#1039,#1040,\n    #1041,#1042,#1043,#1044,#1045,#1046,#1047,#1048,#1049),\n  .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),\n  (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578,\n    1.427996660723,1.713595992867,1.999195325012,2.284794657156,\n    2.570393989301,2.855993321445,3.14159265359,3.427191985734,\n    3.712791317879,3.998390650023,4.283989982168,4.569589314312,\n    4.855188646457,5.140787978601,5.426387310746,5.711986642891,\n    5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#1025 = CARTESIAN_POINT('',(0.E+000,-17.03995));\n#1026 = CARTESIAN_POINT('',(9.519977738151E-002,-17.03995));\n#1027 = CARTESIAN_POINT('',(0.285599332145,-17.03995));\n#1028 = CARTESIAN_POINT('',(0.571198664289,-17.03995));\n#1029 = CARTESIAN_POINT('',(0.856797996434,-17.03995));\n#1030 = CARTESIAN_POINT('',(1.142397328578,-17.03995));\n#1031 = CARTESIAN_POINT('',(1.427996660723,-17.03995));\n#1032 = CARTESIAN_POINT('',(1.713595992867,-17.03995));\n#1033 = CARTESIAN_POINT('',(1.999195325012,-17.03995));\n#1034 = CARTESIAN_POINT('',(2.284794657156,-17.03995));\n#1035 = CARTESIAN_POINT('',(2.570393989301,-17.03995));\n#1036 = CARTESIAN_POINT('',(2.855993321445,-17.03995));\n#1037 = CARTESIAN_POINT('',(3.14159265359,-17.03995));\n#1038 = CARTESIAN_POINT('',(3.427191985734,-17.03995));\n#1039 = CARTESIAN_POINT('',(3.712791317879,-17.03995));\n#1040 = CARTESIAN_POINT('',(3.998390650023,-17.03995));\n#1041 = CARTESIAN_POINT('',(4.283989982168,-17.03995));\n#1042 = CARTESIAN_POINT('',(4.569589314312,-17.03995));\n#1043 = CARTESIAN_POINT('',(4.855188646457,-17.03995));\n#1044 = CARTESIAN_POINT('',(5.140787978601,-17.03995));\n#1045 = CARTESIAN_POINT('',(5.426387310746,-17.03995));\n#1046 = CARTESIAN_POINT('',(5.711986642891,-17.03995));\n#1047 = CARTESIAN_POINT('',(5.997585975035,-17.03995));\n#1048 = CARTESIAN_POINT('',(6.187985529798,-17.03995));\n#1049 = CARTESIAN_POINT('',(6.28318530718,-17.03995));\n#1050 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1051 = ORIENTED_EDGE('',*,*,#958,.F.);\n#1052 = ADVANCED_FACE('',(#1053),#1018,.T.);\n#1053 = FACE_BOUND('',#1054,.T.);\n#1054 = EDGE_LOOP('',(#1055,#1128,#1149,#1150));\n#1055 = ORIENTED_EDGE('',*,*,#1056,.F.);\n#1056 = EDGE_CURVE('',#1057,#1057,#1059,.T.);\n#1057 = VERTEX_POINT('',#1058);\n#1058 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,-33.64357));\n#1059 = SURFACE_CURVE('',#1060,(#1065,#1094),.PCURVE_S2.);\n#1060 = CIRCLE('',#1061,5.);\n#1061 = AXIS2_PLACEMENT_3D('',#1062,#1063,#1064);\n#1062 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-33.64357));\n#1063 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1064 = DIRECTION('',(1.,0.E+000,0.E+000));\n#1065 = PCURVE('',#1018,#1066);\n#1066 = DEFINITIONAL_REPRESENTATION('',(#1067),#1093);\n#1067 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1068,#1069,#1070,#1071,#1072,\n    #1073,#1074,#1075,#1076,#1077,#1078,#1079,#1080,#1081,#1082,#1083,\n    #1084,#1085,#1086,#1087,#1088,#1089,#1090,#1091,#1092),\n  .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),\n  (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578,\n    1.427996660723,1.713595992867,1.999195325012,2.284794657156,\n    2.570393989301,2.855993321445,3.14159265359,3.427191985734,\n    3.712791317879,3.998390650023,4.283989982168,4.569589314312,\n    4.855188646457,5.140787978601,5.426387310746,5.711986642891,\n    5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#1068 = CARTESIAN_POINT('',(0.E+000,17.03995));\n#1069 = CARTESIAN_POINT('',(9.519977738151E-002,17.03995));\n#1070 = CARTESIAN_POINT('',(0.285599332145,17.03995));\n#1071 = CARTESIAN_POINT('',(0.571198664289,17.03995));\n#1072 = CARTESIAN_POINT('',(0.856797996434,17.03995));\n#1073 = CARTESIAN_POINT('',(1.142397328578,17.03995));\n#1074 = CARTESIAN_POINT('',(1.427996660723,17.03995));\n#1075 = CARTESIAN_POINT('',(1.713595992867,17.03995));\n#1076 = CARTESIAN_POINT('',(1.999195325012,17.03995));\n#1077 = CARTESIAN_POINT('',(2.284794657156,17.03995));\n#1078 = CARTESIAN_POINT('',(2.570393989301,17.03995));\n#1079 = CARTESIAN_POINT('',(2.855993321445,17.03995));\n#1080 = CARTESIAN_POINT('',(3.14159265359,17.03995));\n#1081 = CARTESIAN_POINT('',(3.427191985734,17.03995));\n#1082 = CARTESIAN_POINT('',(3.712791317879,17.03995));\n#1083 = CARTESIAN_POINT('',(3.998390650023,17.03995));\n#1084 = CARTESIAN_POINT('',(4.283989982168,17.03995));\n#1085 = CARTESIAN_POINT('',(4.569589314312,17.03995));\n#1086 = CARTESIAN_POINT('',(4.855188646457,17.03995));\n#1087 = CARTESIAN_POINT('',(5.140787978601,17.03995));\n#1088 = CARTESIAN_POINT('',(5.426387310746,17.03995));\n#1089 = CARTESIAN_POINT('',(5.711986642891,17.03995));\n#1090 = CARTESIAN_POINT('',(5.997585975035,17.03995));\n#1091 = CARTESIAN_POINT('',(6.187985529798,17.03995));\n#1092 = CARTESIAN_POINT('',(6.28318530718,17.03995));\n#1093 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1094 = PCURVE('',#1095,#1100);\n#1095 = CONICAL_SURFACE('',#1096,4.53995,0.785398163397);\n#1096 = AXIS2_PLACEMENT_3D('',#1097,#1098,#1099);\n#1097 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-43.18352));\n#1098 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1099 = DIRECTION('',(-1.,-1.224606353822E-016,2.719172340232E-032));\n#1100 = DEFINITIONAL_REPRESENTATION('',(#1101),#1127);\n#1101 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1102,#1103,#1104,#1105,#1106,\n    #1107,#1108,#1109,#1110,#1111,#1112,#1113,#1114,#1115,#1116,#1117,\n    #1118,#1119,#1120,#1121,#1122,#1123,#1124,#1125,#1126),\n  .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),\n  (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578,\n    1.427996660723,1.713595992867,1.999195325012,2.284794657156,\n    2.570393989301,2.855993321445,3.14159265359,3.427191985734,\n    3.712791317879,3.998390650023,4.283989982168,4.569589314312,\n    4.855188646457,5.140787978601,5.426387310746,5.711986642891,\n    5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#1102 = CARTESIAN_POINT('',(1.554312234475E-016,-9.53995));\n#1103 = CARTESIAN_POINT('',(9.519977738151E-002,-9.53995));\n#1104 = CARTESIAN_POINT('',(0.285599332145,-9.53995));\n#1105 = CARTESIAN_POINT('',(0.571198664289,-9.53995));\n#1106 = CARTESIAN_POINT('',(0.856797996434,-9.53995));\n#1107 = CARTESIAN_POINT('',(1.142397328578,-9.53995));\n#1108 = CARTESIAN_POINT('',(1.427996660723,-9.53995));\n#1109 = CARTESIAN_POINT('',(1.713595992867,-9.53995));\n#1110 = CARTESIAN_POINT('',(1.999195325012,-9.53995));\n#1111 = CARTESIAN_POINT('',(2.284794657156,-9.53995));\n#1112 = CARTESIAN_POINT('',(2.570393989301,-9.53995));\n#1113 = CARTESIAN_POINT('',(2.855993321445,-9.53995));\n#1114 = CARTESIAN_POINT('',(3.14159265359,-9.53995));\n#1115 = CARTESIAN_POINT('',(3.427191985734,-9.53995));\n#1116 = CARTESIAN_POINT('',(3.712791317879,-9.53995));\n#1117 = CARTESIAN_POINT('',(3.998390650023,-9.53995));\n#1118 = CARTESIAN_POINT('',(4.283989982168,-9.53995));\n#1119 = CARTESIAN_POINT('',(4.569589314312,-9.53995));\n#1120 = CARTESIAN_POINT('',(4.855188646457,-9.53995));\n#1121 = CARTESIAN_POINT('',(5.140787978601,-9.53995));\n#1122 = CARTESIAN_POINT('',(5.426387310746,-9.53995));\n#1123 = CARTESIAN_POINT('',(5.711986642891,-9.53995));\n#1124 = CARTESIAN_POINT('',(5.997585975035,-9.53995));\n#1125 = CARTESIAN_POINT('',(6.187985529798,-9.53995));\n#1126 = CARTESIAN_POINT('',(6.28318530718,-9.53995));\n#1127 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1128 = ORIENTED_EDGE('',*,*,#1129,.F.);\n#1129 = EDGE_CURVE('',#959,#1057,#1130,.T.);\n#1130 = SEAM_CURVE('',#1131,(#1135,#1142),.PCURVE_S2.);\n#1131 = LINE('',#1132,#1133);\n#1132 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,-16.60362));\n#1133 = VECTOR('',#1134,1.);\n#1134 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1135 = PCURVE('',#1018,#1136);\n#1136 = DEFINITIONAL_REPRESENTATION('',(#1137),#1141);\n#1137 = LINE('',#1138,#1139);\n#1138 = CARTESIAN_POINT('',(0.E+000,0.E+000));\n#1139 = VECTOR('',#1140,1.);\n#1140 = DIRECTION('',(0.E+000,1.));\n#1141 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1142 = PCURVE('',#1018,#1143);\n#1143 = DEFINITIONAL_REPRESENTATION('',(#1144),#1148);\n#1144 = LINE('',#1145,#1146);\n#1145 = CARTESIAN_POINT('',(6.28318530718,0.E+000));\n#1146 = VECTOR('',#1147,1.);\n#1147 = DIRECTION('',(0.E+000,1.));\n#1148 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1149 = ORIENTED_EDGE('',*,*,#981,.T.);\n#1150 = ORIENTED_EDGE('',*,*,#1129,.T.);\n#1151 = ADVANCED_FACE('',(#1152),#1095,.T.);\n#1152 = FACE_BOUND('',#1153,.T.);\n#1153 = EDGE_LOOP('',(#1154,#1209,#1230,#1231));\n#1154 = ORIENTED_EDGE('',*,*,#1155,.F.);\n#1155 = EDGE_CURVE('',#1156,#1156,#1158,.T.);\n#1156 = VERTEX_POINT('',#1157);\n#1157 = CARTESIAN_POINT('',(-13.81821369191,-0.826297072243,-34.56367));\n#1158 = SURFACE_CURVE('',#1159,(#1164,#1193),.PCURVE_S2.);\n#1159 = CIRCLE('',#1160,4.0799);\n#1160 = AXIS2_PLACEMENT_3D('',#1161,#1162,#1163);\n#1161 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-34.56367));\n#1162 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1163 = DIRECTION('',(1.,0.E+000,0.E+000));\n#1164 = PCURVE('',#1095,#1165);\n#1165 = DEFINITIONAL_REPRESENTATION('',(#1166),#1192);\n#1166 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1167,#1168,#1169,#1170,#1171,\n    #1172,#1173,#1174,#1175,#1176,#1177,#1178,#1179,#1180,#1181,#1182,\n    #1183,#1184,#1185,#1186,#1187,#1188,#1189,#1190,#1191),\n  .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),\n  (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578,\n    1.427996660723,1.713595992867,1.999195325012,2.284794657156,\n    2.570393989301,2.855993321445,3.14159265359,3.427191985734,\n    3.712791317879,3.998390650023,4.283989982168,4.569589314312,\n    4.855188646457,5.140787978601,5.426387310746,5.711986642891,\n    5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.);\n#1167 = CARTESIAN_POINT('',(1.632720936236E-016,-8.61985));\n#1168 = CARTESIAN_POINT('',(9.519977738151E-002,-8.61985));\n#1169 = CARTESIAN_POINT('',(0.285599332145,-8.61985));\n#1170 = CARTESIAN_POINT('',(0.571198664289,-8.61985));\n#1171 = CARTESIAN_POINT('',(0.856797996434,-8.61985));\n#1172 = CARTESIAN_POINT('',(1.142397328578,-8.61985));\n#1173 = CARTESIAN_POINT('',(1.427996660723,-8.61985));\n#1174 = CARTESIAN_POINT('',(1.713595992867,-8.61985));\n#1175 = CARTESIAN_POINT('',(1.999195325012,-8.61985));\n#1176 = CARTESIAN_POINT('',(2.284794657156,-8.61985));\n#1177 = CARTESIAN_POINT('',(2.570393989301,-8.61985));\n#1178 = CARTESIAN_POINT('',(2.855993321445,-8.61985));\n#1179 = CARTESIAN_POINT('',(3.14159265359,-8.61985));\n#1180 = CARTESIAN_POINT('',(3.427191985734,-8.61985));\n#1181 = CARTESIAN_POINT('',(3.712791317879,-8.61985));\n#1182 = CARTESIAN_POINT('',(3.998390650023,-8.61985));\n#1183 = CARTESIAN_POINT('',(4.283989982168,-8.61985));\n#1184 = CARTESIAN_POINT('',(4.569589314312,-8.61985));\n#1185 = CARTESIAN_POINT('',(4.855188646457,-8.61985));\n#1186 = CARTESIAN_POINT('',(5.140787978601,-8.61985));\n#1187 = CARTESIAN_POINT('',(5.426387310746,-8.61985));\n#1188 = CARTESIAN_POINT('',(5.711986642891,-8.61985));\n#1189 = CARTESIAN_POINT('',(5.997585975035,-8.61985));\n#1190 = CARTESIAN_POINT('',(6.187985529798,-8.61985));\n#1191 = CARTESIAN_POINT('',(6.28318530718,-8.61985));\n#1192 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1193 = PCURVE('',#1194,#1199);\n#1194 = PLANE('',#1195);\n#1195 = AXIS2_PLACEMENT_3D('',#1196,#1197,#1198);\n#1196 = CARTESIAN_POINT('',(-15.85816369191,-0.826297072243,-34.56367));\n#1197 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.));\n#1198 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016));\n#1199 = DEFINITIONAL_REPRESENTATION('',(#1200),#1208);\n#1200 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#1201,#1202,#1203,#1204,\n#1205,#1206,#1207),.UNSPECIFIED.,.T.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2\n    ,2,2,2,1),(-2.094395102393,0.E+000,2.094395102393,4.188790204786,\n6.28318530718,8.377580409573),.UNSPECIFIED.) CURVE() \nGEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,\n1.,0.5,1.)) REPRESENTATION_ITEM('') );\n#1201 = CARTESIAN_POINT('',(0.E+000,2.03995));\n#1202 = CARTESIAN_POINT('',(-7.0665940898,2.03995));\n#1203 = CARTESIAN_POINT('',(-3.5332970449,-4.0799));\n#1204 = CARTESIAN_POINT('',(-9.99254292592E-016,-10.19975));\n#1205 = CARTESIAN_POINT('',(3.5332970449,-4.0799));\n#1206 = CARTESIAN_POINT('',(7.0665940898,2.03995));\n#1207 = CARTESIAN_POINT('',(0.E+000,2.03995));\n#1208 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1209 = ORIENTED_EDGE('',*,*,#1210,.F.);\n#1210 = EDGE_CURVE('',#1057,#1156,#1211,.T.);\n#1211 = SEAM_CURVE('',#1212,(#1216,#1223),.PCURVE_S2.);\n#1212 = LINE('',#1213,#1214);\n#1213 = CARTESIAN_POINT('',(-22.43806369191,-0.826297072243,-43.18352));\n#1214 = VECTOR('',#1215,1.);\n#1215 = DIRECTION('',(-0.707106781187,-2.436019915756E-016,\n    -0.707106781187));\n#1216 = PCURVE('',#1095,#1217);\n#1217 = DEFINITIONAL_REPRESENTATION('',(#1218),#1222);\n#1218 = LINE('',#1219,#1220);\n#1219 = CARTESIAN_POINT('',(0.E+000,0.E+000));\n#1220 = VECTOR('',#1221,1.);\n#1221 = DIRECTION('',(0.E+000,1.));\n#1222 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1223 = PCURVE('',#1095,#1224);\n#1224 = DEFINITIONAL_REPRESENTATION('',(#1225),#1229);\n#1225 = LINE('',#1226,#1227);\n#1226 = CARTESIAN_POINT('',(6.28318530718,0.E+000));\n#1227 = VECTOR('',#1228,1.);\n#1228 = DIRECTION('',(0.E+000,1.));\n#1229 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) \nPARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE',''\n  ) );\n#1230 = ORIENTED_EDGE('',*,*,#1056,.T.);\n#1231 = ORIENTED_EDGE('',*,*,#1210,.T.);\n#1232 = ADVANCED_FACE('',(#1233),#1194,.T.);\n#1233 = FACE_BOUND('',#1234,.T.);\n#1234 = EDGE_LOOP('',(#1235));\n#1235 = ORIENTED_EDGE('',*,*,#1155,.T.);\n#1236 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) \nGLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1239)) \nGLOBAL_UNIT_ASSIGNED_CONTEXT((#1237,#1238)) REPRESENTATION_CONTEXT('Cont\next #1','3D Context with UNIT and UNCERTAINTY') );\n#1237 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );\n#1238 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) );\n#1239 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-006),#1237,'dis\ntance_accuracy_value','Confusion accuracy');\nENDSEC;\nEND-ISO-10303-21;\n"
  },
  {
    "path": "tutorials/sculpture.geo",
    "content": "algebraic3d\n#\n# intersection of sphere and cylinders\n# motivated by a sculpture found in St. Gallen\n#\n\nsolid cyls = cylinder ( -100, 0, 0; 200, 0, 0; 40 )\n          or cylinder ( 100, -100, 100; 100, 200, 100; 40)\n          or cylinder ( 0, 100, -100; 0, 100, 200; 40);\nsolid sculpture = sphere (50, 50, 50; 80) and not cyls\n        and not sphere (50, 50, 50; 50);\n\ntlo sculpture -col=[0.5, 0.5, 0.5]; \n"
  },
  {
    "path": "tutorials/shaft.geo",
    "content": "#\n## Crankshaft\n#\nalgebraic3d\nsolid p1 = plane (0, 0, 0; -1, 0, 0)\n         and plane (10, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, -1, 3)\n           and plane (35, 0, -28; 0, -1, -3)\n           and plane (35, 0, 0; 0, 1, 0)\n           and plane (35, -30, 0; 0, -1, 0)\n           or cylinder (-10, 0, 0; 20, 0, 0; 30)\n           or cylinder (-10, -30, 0; 20, -30, 0; 20)\n         );\nsolid p2 = plane (35, 0, 0; -1, 0, 0)\n         and plane (45, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, -1, 3)\n           and plane (35, 0, -28; 0, -1, -3)\n           and plane (35, 0, 0; 0, 1, 0)\n           and plane (35, -30, 0; 0, -1, 0)\n           or cylinder (30, 0, 0; 50, 0, 0; 30)\n           or cylinder (30, -30, 0; 50, -30, 0; 20)\n         );\nsolid p3 = plane (80, 0, 0; -1, 0, 0)\n         and plane (90, 0, 0; 1, 0, 0)\n         and\n         (     plane (0, 0, 28; 0, 1, 3)\n           and plane (0, 0, -28; 0, 1, -3)\n           and plane (0, 0, 0; 0, -1, 0)\n           and plane (0, 30, 0; 0, 1, 0)\n           or cylinder (70, 0, 0; 100, 0, 0; 30)\n           or cylinder (70, 30, 0; 100, 30, 0; 20)\n         );\nsolid p4 = plane (115, 0, 0; -1, 0, 0)\n         and plane (125, 0, 0; 1, 0, 0)\n         and\n         (     plane (35, 0, 28; 0, 1, 3)\n           and plane (35, 0, -28; 0, 1, -3)\n           and plane (35, 0, 0; 0, -1, 0)\n           and plane (35, 30, 0; 0, 1, 0)\n           or cylinder (110, 0, 0; 130, 0, 0; 30)\n           or cylinder (110, 30, 0;130, 30, 0; 20)\n         );\nsolid sh1 =   cylinder (-50, 0, 0; 10, 0, 0; 15)\n            and plane (-40, 0, 0; -1, 0, 0)\n            and plane (5, 0, 0; 1, 0, 0);\nsolid sh2 =   cylinder (30, 0, 0; 90, 0, 0; 15)\n            and plane (40, 0, 0; -1, 0, 0)\n            and plane (85, 0, 0; 1, 0, 0);\nsolid sh3 =   cylinder (110, 0, 0; 170, 0, 0; 15)\n            and plane (120, 0, 0; -1, 0, 0)\n            and plane (165, 0, 0; 1, 0, 0);\n\nsolid pl1 = cylinder (0, -30, 0; 50, -30, 0; 10)\n            and plane (5, 0, 0; -1, 0, 0)\n            and plane (40, 0, 0; 1, 0, 0);\nsolid pl2 = cylinder (80, 30, 0; 130, 30, 0; 10)\n            and plane (85, 0, 0; -1, 0, 0)\n            and plane (120, 0, 0; 1, 0, 0);\n#\n#\nsolid main = p1 or p2 or p3 or p4 or sh1 or sh2 or sh3 or pl1 or pl2;\n\ntlo main;\n"
  },
  {
    "path": "tutorials/shell.geo",
    "content": "algebraic3d\n\nsolid main = sphere (0, 0, 0; 1)\n        and not sphere (0, 0, 0; 0.98);\n#        or orthobrick (-0.4, -0.4, -0.4; 0.4, 0.4, 0.4);\n\ntlo main -maxh=0.02;\n\n\n\n"
  },
  {
    "path": "tutorials/sphere.geo",
    "content": "algebraic3d\n\nsolid main = sphere (0, 0, 0; 1);\n\ntlo main;\npoint (0, 0, 0);\n\n\n"
  },
  {
    "path": "tutorials/sphereincube.geo",
    "content": "algebraic3d\n#\n# Example with two sub-domains: \n#\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\nsolid sph = sphere (0.5, 0.5, 0.5; 0.3);\n\nsolid rest = cube and not sph;\n\ntlo rest -transparent -col=[0,0,1];\ntlo sph -col=[1,0,0];\n\n"
  },
  {
    "path": "tutorials/square.in2d",
    "content": "# keyword for 2D geometry, version 2 \nsplinecurves2dv2\n\n\n# a global grading factor\n2\n\n\n# the points (point number, x and y coordinates)\npoints\n1       0       0     -maxh=0.01\n2       1       0\n3       1       1\n4       0       1\n\n\n# boundary curves consisting of\n# dl    dr      np      p1      p1      flaglist\n# with \n# dl ... sub-domain nr on left side \n# dr ... sub-domain nr on right side \n# np ... curve is given by 2 (or 3) points\n# p1, p2 ... points defining the curve\n# flagslist\nsegments\n1       0       2       1       2       -bc=1  -maxh=0.1\n1       0       2       2       3       -bc=1\n1       0       2       3       4       -bc=1\n1       0       2       4       1       -bc=2\n\n\nmaterials\n1       domain1   -maxh=0.3\n\n\n"
  },
  {
    "path": "tutorials/squarecircle.in2d",
    "content": "# keyword for 2D geometry, version 2 \nsplinecurves2dv2\n\n\n# a global grading factor\n2\n\n\n# the points (point number, x and y coordinates)\npoints\n1       0       0   \n2       1       0\n3       1       1\n4       0       1\n5       0.5     0.4\n6       0.6     0.4\n7       0.6     0.5\n8       0.6     0.6\n9       0.5     0.6\n10       0.4     0.6\n11       0.4     0.5\n12       0.4     0.4\n\n\n# boundary curves consisting of\n# dl    dr      np      p1      p1      flaglist\n# with \n# dl ... sub-domain nr on left side \n# dr ... sub-domain nr on right side \n# np ... curve is given by 2 (or 3) points\n# p1, p2 ... points defining the curve\n\n# flagslist\nsegments\n1       0       2       1       2       -bc=1\n1       0       2       2       3       -bc=1\n1       0       2       3       4       -bc=1\n1       0       2       4       1       -bc=1\n2       1       3       5       6       7       -bc=2\n2       1       3       7       8       9       -bc=2\n2       1       3       9       10      11      -bc=2\n2       1       3       11      12      5       -bc=2\n\nmaterials\n1       domain1   -maxh=0.2\n2       domain2   -maxh=0.05\n\n\n"
  },
  {
    "path": "tutorials/squarehole.in2d",
    "content": "# keyword for 2D geometry, version 2 \nsplinecurves2dv2\n\n\n# a global grading factor\n2\n\n\n# the points (point number, x and y coordinates)\npoints\n1       0       0   \n2       1       0\n3       1       1\n4       0       1\n5       0.5     0.4\n6       0.6     0.4\n7       0.6     0.5\n8       0.6     0.6\n9       0.5     0.6\n10       0.4     0.6\n11       0.4     0.5\n12       0.4     0.4\n\n\n# boundary curves consisting of\n# dl    dr      np      p1      p1      flaglist\n# with \n# dl ... sub-domain nr on left side \n# dr ... sub-domain nr on right side \n# np ... curve is given by 2 (or 3) points\n# p1, p2 ... points defining the curve\n\n# flagslist\nsegments\n1       0       2       1       2       -bc=1\n1       0       2       2       3       -bc=1\n1       0       2       3       4       -bc=1\n1       0       2       4       1       -bc=1\n0       1       3       5       6       7       -bc=2 -maxh=0.05\n0       1       3       7       8       9       -bc=2 -maxh=0.05\n0       1       3       9       10      11      -bc=2 -maxh=0.05\n0       1       3       11      12      5       -bc=2 -maxh=0.05\n\nmaterials\n1       domain1   -maxh=0.2\n\n\n"
  },
  {
    "path": "tutorials/test.dem",
    "content": "# Demo file\n\nt = 0;\n\ncamerapos (0 : -7,0,0;  1: -6,0,0; 10: -5,0,0);\ncamerapos (10: -5,0,0; 11: -5,-5,0; 12: 0,-5,0);\ncamerapos (12: 0,-5,0);\n\ncamerapos (14: 0,-5,0; 15: 0,-4,0);\ncamerapos (15: 0,-4,0; 16: 4,-4,0; 17: 4,0,0);\ncamerapos (17: 4,0,0; 18: 4,4,0; 19: 0,4,0);\ncamerapos (19: 0,4,0; 20: -4,4,0; 21: -4,0,0);\n\ncamerapos (21: -4,0,0);\ncamerapos (22: 0,-4,-4);\ncamerapos (23: -4,0,-4);\ncamerapos (24: -4,-4,-4);\n\ncamerapos (25: -4,-4,-4; 30: 4,-4,-4; 35: 4,4,4);\n\n"
  },
  {
    "path": "tutorials/torus.geo",
    "content": "#\n## a torus\n#\nalgebraic3d\n\nsolid tor = torus ( 0, 0, 0; 1, 0, 0; 2 ; 1 );\n\t\t\ntlo tor;\n"
  },
  {
    "path": "tutorials/trafo.geo",
    "content": "algebraic3d\n#\n# a transformer\n#\nsolid core = \n\t    plane (-8,  0,  0; -1,  0,  0)\n\tand plane ( 8,  0,  0;  1,  0,  0)\n\tand plane ( 0, -6,  0;  0, -1,  0)\n\tand plane ( 0,  6,  0;  0,  1,  0)\n\tand plane ( 0,  0, -1;  0,  0, -1)\n\tand plane ( 0,  0,  1;  0,  0,  1)\n\tand not \n\t(    plane (-6,  0,  0; -1,  0,  0)\n\t and plane (-1,  0,  0;  1,  0,  0)\n\t and plane ( 0, -4,  0;  0, -1,  0)\n\t and plane ( 0,  4,  0;  0,  1,  0) )\n\tand not \n\t(    plane ( 6,  0,  0;  1,  0,  0)\n\t and plane ( 1,  0,  0; -1,  0,  0)\n\t and plane ( 0, -4,  0;  0, -1,  0)\n\t and plane ( 0,  4,  0;  0,  1,  0) );\n\nsolid coil1 =\n\t        cylinder (-7, -3, 0;-7, 3, 0; 3)\n\tand not cylinder (-7, -3, 0;-7, 3, 0; 2)\n\tand plane (0, -3, 0; 0, -1, 0) \n\tand plane (0,  3, 0; 0,  1, 0);\nsolid coil2 =\n\t        cylinder ( 0, -3, 0; 0, 3, 0; 3)\n\tand not cylinder ( 0, -3, 0; 0, 3, 0; 2)\n\tand plane (0, -3, 0; 0, -1, 0) \n\tand plane (0,  3, 0; 0,  1, 0);\nsolid coil3 =\n\t        cylinder ( 7, -3, 0; 7, 3, 0; 3)\n\tand not cylinder ( 7, -3, 0; 7, 3, 0; 2)\n\tand plane (0, -3, 0; 0, -1, 0) \n\tand plane (0,  3, 0; 0,  1, 0);\n\t\nsolid box =\n\t    plane (-12, 0,  0; -1,  0,  0)\n\tand plane ( 12, 0,  0;  1,  0,  0)\n\tand plane (  0, 8,  0;  0,  1,  0)\n\tand plane (  0,-8,  0;  0, -1,  0)\n\tand plane (  0, 0,  5;  0,  0,  1)\n\tand plane (  0, 0, -5;  0,  0, -1);\n\nsolid air = box and not core and not coil1 and not coil2 and not coil3;\n\ntlo coil1 -col=[0,1,0];\ntlo coil2 -col=[0,1,0];\ntlo coil3 -col=[0,1,0];\ntlo air -col=[0,0,1] -transparent;\ntlo core -col=[1,1,0];\n\n\n\n\n"
  },
  {
    "path": "tutorials/twobricks.geo",
    "content": "algebraic3d\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\nsolid cutplane = plane (0.5, 0, 0; -1, 0, 0);\n\nsolid right = cube and cutplane;\nsolid left = cube and not cutplane;\n\ntlo right -col=[1,0,0] -material=copper;\ntlo left -col=[0,0,1];\n\n"
  },
  {
    "path": "tutorials/twocubes.geo",
    "content": "algebraic3d\n\n# example with two sub-domains\n\nsolid cube = plane (0, 0, 0; 0, 0, -1)\n         and plane (0, 0, 0; 0, -1, 0)\n         and plane (0, 0, 0; -1, 0, 0)\n         and plane (1, 1, 1; 0, 0, 1)\n         and plane (1, 1, 1; 0, 1, 0)\n         and plane (1, 1, 1; 1, 0, 0);\nsolid cutplane = plane (0.5, 0, 0; -1, 0, 0);\n\nsolid right = cube and cutplane;\nsolid left = cube and not cutplane;\n\ntlo right -col=[1,0,0];\ntlo left -col=[0,0,1];\n\n"
  },
  {
    "path": "tutorials/twocyl.geo",
    "content": "algebraic3d\n\n#\n# two intersecting cylinderes\n#\n\nsolid cyl1 = cylinder ( 1, 0, 0; -1, 0, 0; 0.5 )\n\tand plane (-1, 0, 0; -1, 0, 0)\n\tand plane (1, 0, 0; 1, 0, 0);\nsolid cyl2 = cylinder ( 0, 1, 0.3; 0, -1, 0.3; 0.5 )\n\tand plane (0, -1, 0; 0, -1, 0)\n\tand plane (0, 1, 0; 0, 1, 0);\nsolid main = cyl1 or cyl2;\n\n\ntlo main;\n"
  },
  {
    "path": "windows/.gitignore",
    "content": "netgen.rc\n"
  },
  {
    "path": "windows/CMakeLists.txt",
    "content": "configure_file(\n    \"${CMAKE_CURRENT_SOURCE_DIR}/netgen.rc.template\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/netgen.rc\"\n    IMMEDIATE @ONLY)\n"
  },
  {
    "path": "windows/netgen.rc.template",
    "content": "// Microsoft Visual C++ generated resource script.\r\n//\r\n#include \"resource.h\"\r\n\r\n#define APSTUDIO_READONLY_SYMBOLS\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 2 resource.\r\n//\r\n#include <windows.h>\r\n/////////////////////////////////////////////////////////////////////////////\r\n#undef APSTUDIO_READONLY_SYMBOLS\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// German (Germany) resources\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)\r\n#ifdef _WIN32\r\nLANGUAGE LANG_GERMAN, SUBLANG_GERMAN\r\n#pragma code_page(1252)\r\n#endif //_WIN32\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Icon\r\n//\r\n\r\n// Icon with lowest ID value placed first to ensure application icon\r\n// remains consistent on all systems.\r\n100                     ICON                    \"netgen.ico\"\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Version\r\n//\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\n FILEVERSION @NETGEN_VERSION_MAJOR@,@NETGEN_VERSION_MINOR@,@NETGEN_VERSION_PATCH@,@NETGEN_VERSION_TWEAK@\r\n PRODUCTVERSION @NETGEN_VERSION_MAJOR@,@NETGEN_VERSION_MINOR@,@NETGEN_VERSION_PATCH@,@NETGEN_VERSION_TWEAK@\r\n FILEFLAGSMASK 0x3fL\r\n#ifdef _DEBUG\r\n FILEFLAGS 0x3L\r\n#else\r\n FILEFLAGS 0x2L\r\n#endif\r\n FILEOS 0x4L\r\n FILETYPE 0x1L\r\n FILESUBTYPE 0x0L\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n        BLOCK \"040904b0\"\r\n        BEGIN\r\n            VALUE \"CompanyName\", \"TU Wien\"\r\n            VALUE \"FileDescription\", \"Netgen Meshing Software\"\r\n            VALUE \"FileVersion\", \"@NETGEN_VERSION@\"\r\n            VALUE \"InternalName\", \"Netgen\"\r\n            VALUE \"LegalCopyright\", \"GNU Lesser General Public License (LGPL)\"\r\n            VALUE \"OriginalFilename\", \"Netgen.exe\"\r\n            VALUE \"ProductName\", \"Netgen\"\r\n            VALUE \"ProductVersion\", \"@NETGEN_VERSION@\"\r\n        END\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n        VALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n\r\n#ifdef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// TEXTINCLUDE\r\n//\r\n\r\n1 TEXTINCLUDE \r\nBEGIN\r\n    \"resource.\\0\"\r\nEND\r\n\r\n3 TEXTINCLUDE \r\nBEGIN\r\n    \"\\r\\0\"\r\nEND\r\n\r\n2 TEXTINCLUDE \r\nBEGIN\r\n    \"#include \"\"afxres.h\"\"\\r\\0\"\r\nEND\r\n\r\n#endif    // APSTUDIO_INVOKED\r\n\r\n#endif    // German (Germany) resources\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\r\n#ifndef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 3 resource.\r\n//\r\n\r\r\n/////////////////////////////////////////////////////////////////////////////\r\n#endif    // not APSTUDIO_INVOKED\r\n\r\n"
  },
  {
    "path": "windows/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\r\n// Microsoft Visual C++ generated include file.\r\n// Used by netgen.rc and nglib.rc\r\n//\r\n#define _USE_DECLSPECS_FOR_SAL          0\r\n#define _USE_ATTRIBUTES_FOR_SAL         0\r\n#define VS_VERSION_INFO                 1\r\n#define VFFF_ISSHAREDFILE               0x0001\r\n#define VFF_CURNEDEST                   0x0001\r\n#define VIFF_FORCEINSTALL               0x0001\r\n#define VFF_FILEINUSE                   0x0002\r\n#define VIFF_DONTDELETEOLD              0x0002\r\n#define VFF_BUFFTOOSMALL                0x0004\r\n#define VS_USER_DEFINED                 100\r\n\r\n// Next default values for new objects\r\n// \r\n#ifdef APSTUDIO_INVOKED\r\n#ifndef APSTUDIO_READONLY_SYMBOLS\r\n#define _APS_NEXT_RESOURCE_VALUE        101\r\n#define _APS_NEXT_COMMAND_VALUE         40001\r\n#define _APS_NEXT_CONTROL_VALUE         1000\r\n#define _APS_NEXT_SYMED_VALUE           101\r\n#endif\r\n#endif\r\n"
  }
]